/***********************************************************************
* *
* This software is part of the ast package *
* Copyright (c) 1982-2012 AT&T Intellectual Property *
* and is licensed under the *
* Eclipse Public License, Version 1.0 *
* by AT&T Intellectual Property *
* *
* A copy of the License is available at *
* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
* *
* Information and Software Systems Research *
* AT&T Research *
* Florham Park NJ *
* *
* David Korn <dgk@research.att.com> *
* *
***********************************************************************/
#pragma prototyped
/*
* echo [arg...]
* print [-nrps] [-f format] [-u filenum] [arg...]
* printf format [arg...]
*
* David Korn
* AT&T Labs
*/
#include "defs.h"
#include <error.h>
#include <stak.h>
#include "io.h"
#include "name.h"
#include "history.h"
#include "builtins.h"
#include "streval.h"
#include <tmx.h>
#include <ccode.h>
union types_t
{
unsigned char c;
short h;
int i;
long l;
double d;
float f;
char *s;
int *ip;
char **p;
};
struct printf
{
int argsize;
int intvar;
char **nextarg;
char *lastarg;
char cescape;
char err;
};
struct printmap
{
char *name;
const char *description;
};
{
3, "csv", "q+", "Equivalent to %#q",
4, "html", "H", "Equivalent to %H",
3, "ere", "R", "Equivalent to %R",
7, "pattern","P", "Equivalent to %#P",
3, "url", "H+", "Equivalent to %#H",
0, 0, 0,
};
static char *genformat(char*);
struct print
{
const char *options;
char raw;
char echon;
};
static char* nullarg[] = { 0, 0 };
#if !SHOPT_ECHOPRINT
{
static char bsd_univ;
{
register char *universe;
}
if(!bsd_univ)
{
#if !SHOPT_ECHOE
{
}
#endif /* SHOPT_ECHOE */
else
break;
argv++;
}
}
#endif /* SHOPT_ECHOPRINT */
{
}
{
char c='%';
{
}
return(1);
}
/*
* argc==0 when called from echo
* argc==-1 when called from printf
*/
{
char *format = 0;
if(argc>0)
{
format = 0;
}
else
{
if(argc==0)
{
argv++;
goto skip;
}
}
{
case 'n':
nflag++;
break;
case 'p':
break;
case 'f':
break;
case 's':
/* print to history file */
if(!sh_histinit((void*)shp))
sflag++;
break;
case 'e':
rflag = 0;
break;
case 'r':
rflag = 1;
break;
case 'u':
fd = -1;
fd = -1;
else if(!(shp->inuse_bits&(1<<fd)) && (sh_inuse(shp,fd) || (shp->gd->hist_ptr && fd==sffileno(shp->gd->hist_ptr->histfp))))
fd = -1;
break;
case 'v':
vflag='v';
break;
case 'C':
vflag='C';
break;
case ':':
/* The following is for backward compatibility */
#if OPT_VERSION >= 19990123
#else
#endif
{
rflag = 1;
if(error_info.errors==0)
{
/* special case test for -Rn */
nflag++;
{
nflag++;
argv++;
}
goto skip2;
}
}
else
break;
case '?':
break;
}
skip:
if(format)
/* handle special case of '-' operand for print */
argv++;
if(fd < 0)
{
n = 0;
}
if(!(n&IOWRITE))
{
/* don't print error message for stdout for compatibility */
if(fd==1)
return(1);
}
{
}
/* turn off share to guarantee atomic writes for printf */
if(format)
{
/* printf style print */
do
{
break;
}
else if(vflag)
{
while(*argv)
{
if(!nflag)
}
}
else
{
/* echo style print */
}
if(sflag)
{
}
else if(n&SF_SHARE)
{
}
return(exitval);
}
/*
* echo the argument list onto <outfile>
* if <raw> is non-zero then \ is not a special character.
* returns 0 for \c otherwise 1.
*/
{
register char *cp;
register int n;
{
{
if(n)
}
else
if(*argv)
}
}
/*
* modified version of stresc for generating formats
*/
static char strformat(char *s)
{
register char* t;
register int c;
char* b;
char* p;
#if SHOPT_MULTIBYTE && defined(FMT_EXP_WIDE)
int w;
#endif
b = t = s;
for (;;)
{
switch (c = *s++)
{
case '\\':
if(*s==0)
break;
#if SHOPT_MULTIBYTE && defined(FMT_EXP_WIDE)
#else
c = chresc(s - 1, &p);
#endif
s = p;
#if SHOPT_MULTIBYTE
#if defined(FMT_EXP_WIDE)
if(w)
{
continue;
}
#else
{
t += mbconv(t, c);
continue;
}
#endif /* FMT_EXP_WIDE */
#endif /* SHOPT_MULTIBYTE */
if(c=='%')
*t++ = '%';
else if(c==0)
{
*t++ = '%';
c = 'Z';
}
break;
case 0:
*t = 0;
return(t - b);
}
*t++ = c;
}
}
{
register char *fp;
stakseek(0);
return(fp);
}
{
if(!(flags&SFFMT_ALTER))
{
while(c= *(unsigned char*)cp++)
{
#if SHOPT_MULTIBYTE
register int s;
{
cp += (s-1);
continue;
}
#endif /* SHOPT_MULTIBYTE */
if(c=='<')
stakputs("<");
else if(c=='>')
stakputs(">");
else if(c=='&')
stakputs("&");
else if(c=='"')
stakputs(""");
else if(c=='\'')
stakputs("'");
else if(c==' ')
stakputs(" ");
else
stakputc(c);
}
}
else
{
while(c= *(unsigned char*)cp++)
{
else
stakputc(c);
}
}
stakputc(0);
}
#if 1
#else
#endif
{
char *cp;
Sfdouble_t d;
{
if(sh_isoption(SH_NOUNSET))
return(0);
}
{
{
{
size = sizeof(Sfdouble_t);
}
{
size = sizeof(float);
number.f = (float)d;
}
else
{
size = sizeof(double);
number.d = (double)d;
}
}
else
{
{
}
{
size = sizeof(short);
number.h = (short)d;
}
else
{
size = sizeof(short);
number.i = (int)d;
}
}
#if 1
#else
if(sz)
return((void*)&number);
#endif
}
#if 1
{
{
break;
}
if(fp)
else
{
if(nv_isarray(np))
{
}
else
if((size = n)==0)
return(n?n:size);
}
}
else if(nv_isarray(np) && (ap=nv_arrayptr(np)) && array_elem(ap) && (ap->nelem&(ARRAY_UNDEF|ARRAY_SCAN)))
{
}
else
{
else
alt = 0;
if(alt)
if(!cp)
return(0);
}
#else
if(sz)
return((void*)cp);
#endif
}
{
if(n < 0)
{
if(*str=='.')
str++;
}
for(;n > 0; n-=len)
{
#ifdef SHOPT_MULTIBYTE
#else
c = *(unsigned char*)str++;
#endif
break;
break;
dot = (c=='.');
}
return(n==0);
}
{
{
pm++;
}
return(0);
}
{
register int neg = 0;
Sfdouble_t d;
int n;
char *w,*s;
if(fe->n_str>0 && (format=='T'||format=='Q') && varname(fe->t_str,fe->n_str) && (!argp || varname(argp,-1)))
{
if(argp)
else
if(argp)
{
}
}
else
{
switch(format)
{
case 'c':
value->c = 0;
break;
case 'q':
format = 's';
/* FALL THROUGH */
case 's':
case 'H':
case 'B':
case 'P':
case 'R':
case 'Z':
case 'b':
value->s = "";
break;
case 'a':
case 'e':
case 'f':
case 'g':
case 'A':
case 'E':
case 'F':
case 'G':
if(SFFMT_LDOUBLE)
else
value->d = 0.;
break;
case 'n':
break;
case 'Q':
break;
case 'T':
break;
default:
break;
}
}
else
{
switch(format)
{
case 'p':
break;
case 'n':
{
if(sizeof(int)==sizeof(int32_t))
else
{
}
break;
}
case 'q':
{
if(fp)
{
if(fp[1])
}
}
case 'b':
case 's':
case 'B':
case 'H':
case 'P':
case 'R':
{
}
else
{
}
break;
case 'c':
{
}
else
break;
case 'o':
case 'x':
case 'X':
case 'u':
case 'U':
case '.':
{
break;
}
case 'd':
case 'D':
case 'i':
switch(*argp)
{
case '\'':
case '"':
w = argp + 1;
else
if(w[0] && (w[0] != argp[0] || w[1]))
{
}
break;
default:
if(d<longmin)
{
d = longmin;
}
else if(d>longmax)
{
d = longmax;
}
{
lastchar = "";
}
break;
}
if(neg)
break;
case 'a':
case 'e':
case 'f':
case 'g':
case 'A':
case 'E':
case 'F':
case 'G':
switch(*argp)
{
case '\'':
case '"':
d = ((unsigned char*)argp)[1];
{
}
break;
default:
break;
}
if(SFFMT_LDOUBLE)
{
}
else
{
value->d = d;
}
break;
case 'Q':
break;
case 'T':
break;
default:
break;
}
if (format == '.')
if(*lastchar)
{
}
}
switch(format)
{
case 'Z':
value->c = 0;
break;
case 'b':
{
{
return -1;
}
}
break;
case 'B':
break;
case 'H':
break;
case 'q':
break;
case 'P':
if(!s || *s==0)
value->s = s;
break;
case 'R':
if(!s || *s==0)
value->s = s;
break;
case 'Q':
{
}
else
{
}
break;
case 'T':
{
}
break;
}
return 0;
}
/*
* construct System V echo string out of <cp>
* If there are not escape sequences, returns -1
* Otherwise, puts null terminated result on stack, but doesn't freeze it
* returns length of output.
*/
{
register int c;
#if SHOPT_MULTIBYTE
int chlen;
if(mbwide())
{
while(1)
{
/* Skip over multibyte characters */
else if((c= *cp++)==0 || c == '\\')
break;
}
}
else
#endif /* SHOPT_MULTIBYTE */
while((c= *cp++) && (c!='\\'));
if(c==0)
return(-1);
if(c>0)
{
#if SHOPT_MULTIBYTE
{
continue;
}
#endif /* SHOPT_MULTIBYTE */
if( c=='\\') switch(*++cp)
{
case 'E':
break;
case 'a':
c = '\a';
break;
case 'b':
c = '\b';
break;
case 'c':
goto done;
case 'f':
c = '\f';
break;
case 'n':
c = '\n';
break;
case 'r':
c = '\r';
break;
case 'v':
c = '\v';
break;
case 't':
c = '\t';
break;
case '\\':
c = '\\';
break;
case '0':
c = 0;
{
c <<= 3;
c |= (*cp-'0');
}
default:
cp--;
}
stakputc(c);
}
done:
stakputc(0);
return(c);
}