netnews@netcom.UUCP (USENET Administration) (12/12/90)
#!/bin/sh # This is part 06 of ksh-pd # ============= src/eval.c ============== if test ! -d 'src'; then echo 'x - creating directory src' mkdir 'src' fi if test -f 'src/eval.c' -a X"$1" != X"-c"; then echo 'x - skipping src/eval.c (File already exists)' else echo 'x - extracting src/eval.c (Text)' sed 's/^X//' << 'SHAR_EOF' > 'src/eval.c' && X/* X * Expansion - quoting, separation, substitution, globbing X */ X Xstatic char *RCSid = "$Header: /tmp/egisin/src/RCS/eval.c,v 3.3 88/12/17 20:59:47 egisin Exp $"; X X#include <stddef.h> X#include <stdio.h> X#include <string.h> X#include <errno.h> X#include <setjmp.h> X#include <unistd.h> X#include <sys/types.h> X#include <dirent.h> X#include <pwd.h> X#include "sh.h" X#include "lex.h" X#include "tree.h" X#include "table.h" X#include "expand.h" X X/* X * string expansion X * X * first pass: quoting, IFS separation, ${} and $() substitution. X * second pass: filename expansion (*?[]~). X */ X X/* expansion generator state */ Xtypedef struct Expand { X /* int type; */ /* see expand() */ X char *str; /* string */ X union { X char **strv; /* string[] */ X FILE *file; /* file */ X } u; /* source */ X short split; /* split "$@"*/ X} Expand; X X#define XBASE 0 /* scanning original */ X#define XSUB 1 /* expanding ${} string */ X#define XARGSEP 2 /* ifs0 between "$@" */ X#define XARG 3 /* expanding $*, $@ */ X#define XCOM 4 /* expanding $() */ X Xstatic void expand ARGS((char *, XPtrV *, int)); Xstatic int comsub ARGS((Expand *, char *comm)); Xstatic int varsub ARGS((Expand *, char *name, int stype)); Xstatic void glob ARGS((char *cp, XPtrV *wp)); Xstatic void globit ARGS((char *ds, char *dp, char *sp, XPtrV *wp, int check)); Xstatic char *tilde ARGS((char *wp)); Xstatic char *trimsub ARGS((char *str, char *pat, int how)); X Xint ifs0 = ' '; /* todo: first char of $IFS */ X X/* compile and expand word */ Xchar * Xsubstitute(cp, f) X char Const *cp; X int f; X{ X struct source *s, *sold; X X sold = source; X s = pushs(SWSTR); X s->str = (char *) cp; X source = s; X if (yylex(ONEWORD) != LWORD) X errorf("eval:substitute error\n"); X source = sold; X return evalstr(yylval.cp, f); X} X X/* X * expand arg-list X */ Xchar ** Xeval(ap, f) X register char **ap; X{ X XPtrV w; X X if (*ap == NULL) X return ap; X XPinit(w, 32); X XPput(w, NULL); /* space for shell name */ X while (*ap != NULL) X expand(*ap++, &w, f); X XPput(w, NULL); X return (char **) XPclose(w) + 1; X} X X/* X * expand string X */ Xchar * Xevalstr(cp, f) X register char *cp; X int f; X{ X XPtrV w; X X XPinit(w, 1); X expand(cp, &w, f); X cp = (XPsize(w) == 0) ? "" : (char*) *XPptrv(w); X XPfree(w); X return cp; X} X X/* for nested substitution: ${var:=$var2} */ Xtypedef struct SubType { X short type; /* [=+-?%#] action after expanded word */ X short base; /* begin position of expanded word */ X char *name; /* name for ${var=word} */ X} SubType; X Xstatic void Xexpand(cp, wp, f) X char *cp; /* input word */ X register XPtrV *wp; /* output words */ X int f; /* DO* flags */ X{ X register int c; X register int type = XBASE; /* expansion type */ X register int quote = 0; /* quoted */ X XString ds; /* destination string */ X register char *dp, *sp; /* dest., source */ X int fdo, word, combase; /* second pass flags; have word */ X Expand x; /* expansion variables */ X SubType subtype [10]; /* substitution type stack */ X register SubType *st = subtype + 10; X X if (cp == NULL) X errorf("eval:expand(NULL)\n"); X if (flag[FNOGLOB]) X f &= ~ DOGLOB; X X Xinit(ds, dp, 128); /* init dest. string */ X type = XBASE; X sp = cp; X fdo = 0; X word = !(f&DOBLANK); X X while (1) { X Xcheck(ds, dp); X X switch (type) { X case XBASE: /* original prefixed string */ X c = *sp++; X switch (c) { X case EOS: X c = 0; X break; X case CHAR: X c = *sp++; X break; X case QCHAR: X quote |= 2; /* temporary quote */ X c = *sp++; X break; X case OQUOTE: X word = quote = 1; X continue; X case CQUOTE: X quote = 0; X continue; X case COMSUB: X type = comsub(&x, sp); X sp = strchr(sp, 0) + 1; X combase = Xsavepos(ds, dp); X continue; X case OSUBST: /* ${var{:}[=+-?]word} */ X cp = sp; /* variable */ X sp = strchr(sp, 0) + 1; /* skip variable */ X c = (*sp == CSUBST) ? 0 : *sp++; X if ((c&0x7F) == '#' || (c&0x7F) == '%') X f |= DOPAT; X type = varsub(&x, cp, c); X if (type == XBASE) { /* expand? */ X if (st == subtype) X errorf("ridiculous ${} nesting\n"); X --st; X st->type = c; X st->base = Xsavepos(ds, dp); X st->name = cp; X } else X /* todo: nested OSUBST/CSUBST */ X sp = wdscan(sp, CSUBST); /* skip word */ X continue; X case CSUBST: /* only get here if expanding word */ X *dp = 0; X if (f&DOGLOB) X f &= ~DOPAT; X switch (st->type&0x7F) { X case '#': X case '%': X *dp = 0; X dp = Xrestpos(ds, dp, st->base); X x.str = trimsub(x.str, dp, st->type); X type = XSUB; X continue; X case '=': X#if 0 X if ((x.u.vp->flag&RDONLY)) X errorf("cannot set readonly %s\n", cp); X#endif X setstr(global(st->name), Xrestpos(ds, dp, st->base)); X break; X case '?': X if (dp == Xrestpos(ds, dp, st->base)) X errorf("missing value for %s\n", cp); X else X errorf("%s\n", Xrestpos(ds, dp, st->base)); X } X st++; X type = XBASE; X continue; X } X break; X X case XSUB: X if ((c = *x.str++) == 0) { X type = XBASE; X continue; X } X break; X X case XARGSEP: X type = XARG; X quote = 1; X case XARG: X if ((c = *x.str++) == 0) { X if ((x.str = *x.u.strv++) == NULL) { X type = XBASE; X continue; X } else if (quote && x.split) { X /* terminate word for "$@" */ X type = XARGSEP; X quote = 0; X } X c = ifs0; X } X break; X X case XCOM: X c = getc(x.u.file); X if (quote) { X if (c == EOF) { X cp = Xrestpos(ds, sp, combase); X for (dp--; dp >= cp && *dp == '\n'; dp--) X ; X dp++; X fclose(x.u.file); X if (x.split) X waitlast(); X type = XBASE; X continue; X } X } else { /* this part is probably redundant */ X if (c == EOF || c == '\n') { X while ((c = getc(x.u.file)) == '\n') X ; X if (c == EOF) { X fclose(x.u.file); X if (x.split) X waitlast(); X type = XBASE; X continue; X } X ungetc(c, x.u.file); X c = ifs0; X } X } X break; X } X X /* check for end of word or IFS separation */ X if (c == 0 || !quote && (f&DOBLANK) && ctype(c, C_IFS)) { X if (word) { X *dp++ = 0; X cp = Xclose(ds, dp); X if (fdo&DOTILDE) X cp = tilde(cp); X if (fdo&DOGLOB) X glob(cp, wp); X else X {XPput(*wp, cp);} X fdo = word = 0; X if (c != 0) X Xinit(ds, dp, 128); X } else X ; /* ignore IFS */ X if (c == 0) X return; X } else { X /* mark any special second pass chars */ X if (!quote) X switch (c) { X case '*': X case '?': X case '[': X if (f&(DOPAT|DOGLOB)) { X fdo |= (f&DOGLOB); X *dp++ = MAGIC; X } X break; X case '~': X if ((f&DOTILDE) && dp == Xstring(ds, dp) || X !(f&DOBLANK) && X (dp[-1] == '=' || dp[-1] == ':')) { X fdo |= DOTILDE; X *dp++ = MAGIC; X } X break; X } X else X quote &= ~2; /* undo temporary */ X X word = 1; X *dp++ = c; /* save output char */ X } X } X} X X/* X * Prepare to generate the string returned by ${} substitution. X */ Xstatic int Xvarsub(xp, sp, stype) X register Expand *xp; X register char *sp; X int stype; X{ X register int c; X int type; X X /* ${#var}, string length or argc */ X if (sp[0] == '#' && (c = sp[1]) != 0) { X c = (c == '*' || c == '@') ? e.loc->argc : X strlen(strval(global(sp+1))); X xp->str = strsave(ulton((unsigned long)c, 10), ATEMP); X return XSUB; X } X X c = sp[0]; X if (c == '*' || c == '@') { X if (e.loc->argc == 0) { X xp->str = null; X type = XSUB; X } else { X xp->u.strv = e.loc->argv + 1; X xp->str = *xp->u.strv++; X xp->split = c == '@'; /* $@ */ X type = XARG; X } X } else { X xp->str = strval(global(sp)); X type = XSUB; X } X X c = stype&0x7F; X /* test the compiler's code generator */ X if (c == '%' || c == '#' || X (((stype&0x80) ? *xp->str=='\0' : xp->str==null) ? /* undef? */ X c == '=' || c == '-' || c == '?' : c == '+')) X type = XBASE; /* expand word instead of variable value */ X if (type != XBASE && flag[FNOUNSET] && xp->str == null) X errorf("%s: unset variable\n", sp); X return type; X} X X/* X * Run the command in $(...) and read its output. X */ Xstatic int Xcomsub(xp, cp) X register Expand *xp; X char *cp; X{ X Source *s; X register struct op *t; X FILE *fi; X X s = pushs(SSTRING); X s->str = cp; X t = compile(s); X X if (t != NULL && t->type == TCOM && /* $(<file) */ X *t->args == NULL && *t->vars == NULL && t->ioact != NULL) { X register struct ioword *io = *t->ioact; X X if ((io->flag&IOTYPE) != IOREAD) X errorf("funny $() command\n"); X fi = fopen(evalstr(io->name, DOTILDE), "r"); X if (fi != NULL) X fileno(fi) = savefd(fileno(fi)); X xp->split = 0; /* no waitlast() */ X } else { X int ofd1, pv[2]; X openpipe(pv); X fi = fdopen(pv[0], "r"); X ofd1 = savefd(1); X dup2(pv[1], 1); X close(pv[1]); X#if 0 X exchild(t, XXCOM|XPIPEO); X#else X execute(t, XFORK|XXCOM|XPIPEO); X#endif X dup2(ofd1, 1); X xp->split = 1; /* waitlast() */ X } X X if (fi == NULL) X errorf("cannot open $() input\n"); X setvbuf(fi, (char *)NULL, _IOFBF, BUFSIZ); X xp->u.file = fi; X return XCOM; X} X X/* X * perform #pattern and %pattern substitution in ${} X */ X Xstatic char * Xtrimsub(str, pat, how) X register char *str; X char *pat; X int how; X{ X register char *end = strchr(str, 0); X register char *p, c; X X switch (how) { X case '#': /* shortest at begin */ X for (p = str; p <= end; p++) { X c = *p; *p = '\0'; X if (gmatch(str, pat)) { X *p = c; X return p; X } X *p = c; X } X break; X case '#'|0x80: /* longest match at begin */ X for (p = end; p >= str; p--) { X c = *p; *p = '\0'; X if (gmatch(str, pat)) { X *p = c; X return p; X } X *p = c; X } X break; X case '%': /* shortest match at end */ X for (p = end; p >= str; p--) { X if (gmatch(p, pat)) { X *p = '\0'; X return str; X } X } X break; X case '%'|0x80: /* longest match at end */ X for (p = str; p <= end; p++) { X if (gmatch(p, pat)) { X *p = '\0'; X return str; X } X } X break; X } X X return str; /* no match, return string */ X} X X/* X * glob X * Name derived from V6's /etc/glob, the program that expanded filenames. X */ X Xstatic char *debunk(); X Xstatic void Xglob(cp, wp) X char *cp; X register XPtrV *wp; X{ X char path [PATH]; X register char *sp = cp; X int oldsize; X X oldsize = XPsize(*wp); X globit(path, path, sp, wp, 0); X X if (XPsize(*wp) == oldsize) X {XPput(*wp, debunk(cp));} X else X qsortp(XPptrv(*wp) + oldsize, (size_t)(XPsize(*wp) - oldsize), xstrcmp); X} X Xstatic void Xglobit(ds, dp, sp, wp, check) X char *ds; /* dest path */ X char *dp; /* dest end */ X char *sp; /* source path */ X register XPtrV *wp; /* output list */ X int check; /* check dest existence */ X{ X register char *np; /* next source component */ X register char *tsp, *tdp; X X if (sp == NULL) { /* end of source path */ X if (check && eaccess(ds, 0) < 0) X return; X XPput(*wp, strsave(ds, ATEMP)); X return; X } X X if (dp > ds) X *dp++ = '/'; X while (*sp == '/') X *dp++ = *sp++; X np = strchr(sp, '/'); X if (np != NULL) X *np++ = 0; X X *dp = 0; X if (strchr(sp, MAGIC) == NULL) { /* contains no pattern? */ X tdp = dp; tsp = sp; X while ((*tdp++ = *tsp++) != 0) X ; X --tdp; X globit(ds, tdp, np, wp, check); X } else { X DIR *dirp; X struct dirent *d; X X /* ToDo: X * should not attemp to open() special files: /dev/ttyd0/* X * opendir should do this check, but Doug Gwyn's does not. X */ X dirp = opendir((*ds == 0) ? "." : ds); X if (dirp == NULL) X goto Nodir; X while ((d = readdir(dirp)) != NULL) { X tsp = d->d_name; X if (tsp[0] == '.' && X (tsp[1] == 0 || tsp[1] == '.' && tsp[2] == 0)) X continue; /* always ignore . and .. */ X if (*tsp == '.' && *sp != '.' || !gmatch(tsp, sp)) X continue; X X tdp = dp; X while ((*tdp++ = *tsp++) != 0) X ; X --tdp; X globit(ds, tdp, np, wp, np != NULL); X } X closedir(dirp); X Nodir:; X } X X if (np != NULL) X *--np = '/'; X} X X/* remove MAGIC from string */ Xstatic char * Xdebunk(cp) X char *cp; X{ X register char *dp, *sp; X X for (dp = sp = cp; *sp != 0; sp++) X if (*sp != MAGIC) X *dp++ = *sp; X *dp = 0; X return cp; X} X X/* X * tilde expansion X * X * based on a version by Arnold Robbins X */ X Xstatic char *homedir(); X Xstatic char * Xtilde(acp) X char *acp; X{ X register int c; X char path [PATH+1]; X register char *cp = acp, *wp = path, *dp; X char userid [16+1]; X X Again: X while (1) { X if ((c = *cp++) == 0) { X *wp = 0; X afree((Void*)acp, ATEMP); X return strsave(path, ATEMP); X } else if (c == MAGIC && *cp == '~') X break; X else X *wp++ = c; X } X X dp = NULL; /* no output substitution */ X if (cp[1] == 0 || cp[1] == '/' || cp[1] == ':') /* ~ or ~/ */ X dp = strval(global("HOME")), cp += 1; X else if (cp[1] == '+' && (cp[2] == '/' || cp[2] == ':' || cp[2] == 0)) X dp = strval(global("PWD")), cp += 2; X else if (cp[1] == '-' && (cp[2] == '/' || cp[2] == ':' || cp[2] == 0)) X dp = strval(global("OLDPWD")), cp += 2; X else if (letter(cp[1])) { X char *save = cp; X for (dp = userid, cp++; letnum(*cp) && dp < userid+16; ) X *dp++ = *cp++; X *dp = 0; X dp = homedir(userid); X if (dp == NULL) X cp = save; X } X /* substitute */ X if (dp != NULL) X while (*dp != 0) X *wp++ = *dp++; X goto Again; X} X X/* X * map userid to user's home directory. X * todo: implement a cache with the "homedirs" table. X * note that 4.3's getpw adds more than 6K to the shell, X * and the YP version probably adds much more. X * we might consider our own version of getpwnam() to keep the size down. X */ X Xstatic char * Xhomedir(name) X char *name; X{ X register struct tbl *ap; X register struct passwd *pw; X X ap = tsearch(&homedirs, name, hash(name)); X if ((ap != NULL && (ap->flag&ISSET))) X return ap->val.s; X pw = getpwnam(name); X if (pw == NULL) X return NULL; X return pw->pw_dir; X} X SHAR_EOF true || echo 'restore of src/eval.c failed' fi # ============= src/expr.c ============== if test -f 'src/expr.c' -a X"$1" != X"-c"; then echo 'x - skipping src/expr.c (File already exists)' else echo 'x - extracting src/expr.c (Text)' sed 's/^X//' << 'SHAR_EOF' > 'src/expr.c' && X/* X * Korn expression evaluation X */ X Xstatic char *RCSid = "$Header: /tmp/egisin/src/RCS/expr.c,v 3.1 88/11/03 09:15:55 egisin Exp $"; X X#include <stddef.h> X#include <errno.h> X#include <setjmp.h> X#include "sh.h" X#include "table.h" X X#define ef else if /* fashion statement */ X X#define VAR 0x01 X#define LIT 0x02 X#define LEQ 0x03 X#define LNE 0x04 X#define LLE 0x05 X#define LGE 0x06 X Xstatic void token(); /* read next token */ Xstatic Const char *expression; /* expression being evaluated */ Xstatic Const char *tokp; /* lexical position */ Xstatic int tok; /* token from token() */ Xstatic struct tbl *val; /* value from token() */ X Xstatic struct tbl *tempvar(), *intvar(); Xstatic struct tbl *asn(), *e6(), *e5(), *e3(), *e2(), *e0(); X X/* X * parse and evalute expression X */ Xvoid Xevalerr(err) X char *err; X{ X errorf("%s: %s\n", expression, err); X} X Xlong Xevaluate(expr) X Const char *expr; X{ X struct tbl *v; X X expression = tokp = expr; X token(); X v = intvar(asn()); X if (!(tok == 0)) X evalerr("bad expression"); X return v->val.i; X} X Xstatic struct tbl * Xasn() X{ X register struct tbl *vl, *vr; X X vr = vl = e6(); X if ((tok == '=')) { X Area * olastarea = lastarea; X token(); X if ((vl->flag&RDONLY)) /* assign to rvalue */ X evalerr("bad assignment"); X vr = intvar(asn()); X lastarea = olastarea; X setint(vl, vr->val.i); X if ((vl->flag&INTEGER) && vl->type == 0) /* default base? */ X vl->type = vr->type; X } X return vr; X} X Xstatic struct tbl * Xe6() X{ X register struct tbl *vl, *vr; X X vl = e5(); X while ((tok == LEQ) || (tok == LNE)) { X int op = tok; X token(); X vl = intvar(vl); X vr = intvar(e5()); X vl->val.i = vl->val.i == vr->val.i; X if (op == LNE) X vl->val.i = ! vl->val.i; X } X return vl; X} X Xstatic struct tbl * Xe5() X{ X register struct tbl *vl, *vr; X X vl = e3(); X while ((tok == LLE) || (tok == '<') || (tok == '>') || (tok == LGE)) { X int op = tok; X token(); X vl = intvar(vl); X vr = intvar(e3()); X if (op == LLE) X vl->val.i = vl->val.i <= vr->val.i; X ef (op == '<') X vl->val.i = vl->val.i < vr->val.i; X ef (op == LGE) X vl->val.i = vl->val.i >= vr->val.i; X ef (op == '>') X vl->val.i = vl->val.i > vr->val.i; X } X return vl; X} X Xstatic struct tbl * Xe3() X{ X register struct tbl *vl, *vr; X X vl = e2(); X while ((tok == '+') || (tok == '-')) { X int op = tok; X token(); X vl = intvar(vl); X vr = intvar(e2()); X if (op == '+') X vl->val.i += vr->val.i; X ef (op == '-') X vl->val.i -= vr->val.i; X } X return vl; X} X Xstatic struct tbl * Xe2() X{ X register struct tbl *vl, *vr; X X vl = e0(); X while ((tok == '*') || (tok == '/') || (tok == '%')) { X int op = tok; X token(); X vl = intvar(vl); X vr = intvar(e0()); X if (op != '*' && vr->val.i == 0) X evalerr("zero divisor"); X if (op == '*') X vl->val.i *= vr->val.i; X ef (op == '/') X vl->val.i /= vr->val.i; X ef (op == '%') X vl->val.i %= vr->val.i; X } X return vl; X} X Xstatic struct tbl * Xe0() X{ X register struct tbl *v; X X if ((tok == '!') || (tok == '-')) { X int op = tok; X token(); X v = intvar(e0()); X if (op == '!') X v->val.i = !v->val.i; X ef (op == '-') X v->val.i = -v->val.i; X } else X if ((tok == '(')) { X token(); X v = asn(); X if (!(tok == ')')) X evalerr("missing )"); X token(); X } else X if ((tok == VAR) || (tok == LIT)) { X v = val; X token(); X } else X evalerr("bad expression"); X return v; X} X Xstatic void Xtoken() X{ X register char *cp = (char *) tokp; X register int c, c2; X X /* skip white space */ X do c = *cp++; while (c != '\0' && (c == ' ' || c == '\t')); X tokp = cp-1; X X if (letter(c)) { X for (; letnum(c); c = *cp++) X ; X c = *--cp; X *cp = 0; X val = global(tokp); X *cp = c; X tok = VAR; X } else X if (digit(c)) { X for (; letnum(c) || c == '#'; c = *cp++) X ; X c = *--cp; X *cp = 0; X val = tempvar(); X setstr(val, tokp); X val->flag |= RDONLY; X *cp = c; X tok = LIT; X } else { X c2 = *cp++; X if (c == '=' && c2 == '=') X c = LEQ; X ef (c == '!' && c2 == '=') X c = LNE; X ef (c == '<' && c2 == '=') X c = LLE; X ef (c == '>' && c2 == '=') X c = LGE; X else X cp--; X tok = c; X } X tokp = cp; X} X Xstatic struct tbl * Xtempvar() X{ X register struct tbl *vp; X X vp = alloc(sizeof(struct tbl), ATEMP); X lastarea = ATEMP; X vp->flag = ISSET|INTEGER; X vp->type = 0; X vp->name[0] = '\0'; X return vp; X} X X/* cast (string) variable to temporary integer variable */ Xstatic struct tbl * Xintvar(vp) X register struct tbl *vp; X{ X register struct tbl *vq; X X vq = tempvar(); X vq->type = 10; X return strint(vq, vp); X} X SHAR_EOF true || echo 'restore of src/expr.c failed' fi # ============= ReadMe ============== if test -f 'ReadMe' -a X"$1" != X"-c"; then echo 'x - skipping ReadMe (File already exists)' else echo 'x - extracting ReadMe (Text)' sed 's/^X//' << 'SHAR_EOF' > 'ReadMe' && X Notes on the Standard C / POSIX P1003.1 package X XThis package contains header files and library routines Xto provide a standard C (ANSI) and POSIX enviroment for portable programs. XThis allows most OS dependcies to be removed from an application, Xmaking it much more readable, and isolating them in a small, Xstandardized library. It has the disadvantage that it only Xworks with fairly stock UNIX versions, but a different approach Xwill be used for other systems. X XThis package supplements the existing libraries and header files Xof a AT&T-derived Unix system (System V and BSD in particular). XIt also provides function prototypes when the compiler supports them, Ximproving compile-time error checking and improving portability on Xmachines where sizeof(int) == sizeof(size_t) == sizeof(void*) does not hold. X XA different approach will be used for the DOS, Atari St, Minix, Xand possibly V7: a complete replacement standard C library will Xbe provided as a separate package. This would not be practical Xwith BSD or NFS systems because of the conflicts with the host Xstdio and the replacement stdio in libc's getpwent(). X XContents: Xstdc/*: The standard C header files and library. Xposix/*: The POSIX header files and library. Xh/*, h/sys/*: Links to the header files in stdc/ and posix/. Xlibstdc.a: The standard C library. Xlibposix.a: The POSIX emulation library. X XTo create the header files and libraries, perform the following Xthree steps in the stdc and posix directories: X One of _BSD, _SYSV, or _V7 should be defined in the Makefile. X Do "rm stdc/stdio.h", it gets created by make. X Do "make link" first to set up the links from *.h to ../h. X Do "make" to create the library. XCompile applications with -I$STD/h, link them with -L$STD ... -lstdc -lposix. X X Notes on the standard C package XThe files <locale.h>, <assert.h>, and <math.h> don't exist yet. XMany standard C functions are not implemented yet. XThese include strtol, strtoul, atexit, tempfile(?), etc. XThe string routines are by Henry Spencer. X XKnown portability problems include: Xsize_t or ptrdiff_t in <stddef.h> may need to be long. XThe method of creating <stdio.h> from /usr/include/stdio.h and stdio.h_std Xmay not work on some versions of UNIX. XAlmost definitely not on Xenix, maybe not on merged BSD-SysV systems. XThis package contains a correct version of setvbuf() which Xdepends on the contents of FILE in the host stdio.h. XThis will not work if FILE is neither stock System V or BSD. XYou can safely "#if 0" out the body of setvbuf for PD ksh, Xsetvbuf is used to decrease the size of buffers to speed up forks. X X Notes on the POSIX package XOnly headers and function required by the PD KornShell are implemented. XI do not intend to develop this into a full POSIX emulation package. XYou should install Doug Gwyn's <dirent> package if you do not have X<dirent.h> nor <sys/dir>. If you do have <dirent.h>, unlink h/dirent.h X(this should be configured automatically by the makefile). X SHAR_EOF true || echo 'restore of ReadMe failed' fi # ============= posix/Makefile ============== if test ! -d 'posix'; then echo 'x - creating directory posix' mkdir 'posix' fi if test -f 'posix/Makefile' -a X"$1" != X"-c"; then echo 'x - skipping posix/Makefile (File already exists)' else echo 'x - extracting posix/Makefile (Text)' sed 's/^X//' << 'SHAR_EOF' > 'posix/Makefile' && X# POSIX P1003.1 compatability X# does not requires SVID/P1003.2-compatible "make" X X# $Header: Makefile,v 1.1 88/03/29 18:28:38 egisin Locked $ X XSYSTEM=BSD XCC = gcc -ansi -O -W XLN = ln XPRINT = lpr -p -Plp26_3018 X XCFLAGS = -I../h -D_$(SYSTEM) X XMISC = Makefile XHDRS = wait.h times.h unistd.h fcntl.h dirent.h XSRCS = unistd.c fcntl.c times.c XOBJS = unistd.o fcntl.o times.o X#OBJS = $(SRCS:.c=.o) XLIB = libposix.a XINCL = ../h X Xall: $(LIB) X Xlink: $(HDRS) X [ -d $(INCL) ] || mkdir $(INCL) X [ -d $(INCL)/sys ] || mkdir $(INCL)/sys X $(LN) wait.h time.h times.h $(INCL)/sys X $(LN) unistd.h $(INCL) X if [ ! -r /usr/include/unistd.h ]; then $(LN) dirent.h $(INCL); fi X X$(LIB)(%.o): %.o X X%: RCS/%,v X co %@ X X$(LIB): $(OBJS) X ar r $@ $? X -ranlib $@ X X#$(LIB): lib.a($OBJS) X# ar rv $@ $? X# -ranlib $@ X# rm -f $? X Xstd_p.tar: $(MISC) $(SRCS) X tar cf std_p.tar $(MISC) $(HDRS) $(SRCS) X Xprint: $(MISC) $(HDRS) $(SRCS) X $(PRINT) $(MISC) $(HDRS) $(SRCS) X XIndex: $(SRCS) X ctags -x $(HDRS) $(SRCS) >Index X Xci: X ci -l $(MISC) $(HDRS) $(SRCS) X Xfcntl.o: fcntl.h X Xtimes.o: times.h X SHAR_EOF true || echo 'restore of posix/Makefile failed' fi # ============= posix/dirent.C ============== if test -f 'posix/dirent.C' -a X"$1" != X"-c"; then echo 'x - skipping posix/dirent.C (File already exists)' else echo 'x - extracting posix/dirent.C (Text)' sed 's/^X//' << 'SHAR_EOF' > 'posix/dirent.C' && X/* X * simple implementation of directory(3) routines for V7 and Minix. X * completly untested. not designed to be efficient. X * missing telldir and seekdir. X */ X X#include <sys/types.h> X#include <dirent.h> X Xchar *malloc(); X X#define DIRSIZ 14 Xstruct direct_v7 X{ X unsigned short d_ino; X char d_name[DIRSIZ]; X}; X XDIR *opendir(filename) X char *filename; X{ X DIR *dirp; X X dirp = (DIR *) malloc(sizeof(DIR)); X if (dirp == NULL) X return NULL; X dirp->fd = open(filename, 0); X if (dirp->fd < 0) { X free((char *) dirp); X return NULL; X } X return dirp; X} X Xstruct dirent *readdir(dirp) X register DIR *dirp; X{ X static struct direct_v7 ent; X X while (read(dirp->fd, (char *)&ent, (int)sizeof(ent)) == sizeof(ent)) X if (ent.d_ino != 0) X goto found; X return (struct dirent *) NULL; X found: X dirp->ent.d_ino = ent.d_ino; X strncpy(dirp->ent.d_name, ent.d_name, DIRSIZ); X return &dirp->ent; X} X Xvoid rewinddir(dirp) X DIR *dirp; X{ X lseek(dirp->fd, 0L, 0); X} X Xclosedir(dirp) X DIR *dirp; X{ X close(dirp->fd); X dirp->fd = -1; X free((char *) dirp); X return 0; X} SHAR_EOF true || echo 'restore of posix/dirent.C failed' fi # ============= posix/dirent.H ============== if test -f 'posix/dirent.H' -a X"$1" != X"-c"; then echo 'x - skipping posix/dirent.H (File already exists)' else echo 'x - extracting posix/dirent.H (Text)' sed 's/^X//' << 'SHAR_EOF' > 'posix/dirent.H' && X/* X <sys/dirent.h> -- file system independent directory entry (SVR3) X X last edit: 25-Apr-1987 D A Gwyn X last hack: 14-Aug-1987 Eric Gisin X X prerequisite: <sys/types.h> X*/ X X#define MAXNAMLEN 16 /* maximum filename length */ X Xstruct dirent /* data from getdents()/readdir() */ X { X long d_ino; /* inode number of entry */ X off_t d_off; /* offset of disk directory entry */ X unsigned short d_reclen; /* length of this record */ X char d_name[MAXNAMLEN]; /* name of file */ X}; X X#ifndef NAME_MAX X#define NAME_MAX (MAXNAMLEN - 1) /* DAG -- added for POSIX */ X#endif X Xtypedef struct { /* returned by opendir() */ X int fd; X struct dirent ent; X} DIR; X Xextern DIR *opendir(); Xextern struct dirent *readdir(); Xextern off_t telldir(); Xextern void seekdir(); Xextern void rewinddir(); Xextern int closedir(); X X#ifndef NULL X#define NULL 0 /* DAG -- added for convenience */ X#endif SHAR_EOF true || echo 'restore of posix/dirent.H failed' fi # ============= posix/dirent.h ============== if test -f 'posix/dirent.h' -a X"$1" != X"-c"; then echo 'x - skipping posix/dirent.h (File already exists)' else echo 'x - extracting posix/dirent.h (Text)' sed 's/^X//' << 'SHAR_EOF' > 'posix/dirent.h' && X/* <dirent.h> based on BSD <sys/dir.h> */ X X#include <sys/dir.h> X#define dirent direct X SHAR_EOF true || echo 'restore of posix/dirent.h failed' fi # ============= posix/fcntl.c ============== if test -f 'posix/fcntl.c' -a X"$1" != X"-c"; then echo 'x - skipping posix/fcntl.c (File already exists)' else echo 'x - extracting posix/fcntl.c (Text)' sed 's/^X//' << 'SHAR_EOF' > 'posix/fcntl.c' && X/* fcntl emulation */ X X#include <errno.h> X#include <sys/types.h> X#include <unistd.h> X#include <fcntl.h> X X#if _V7 X X#include <sgtty.h> X Xint Xfcntl(fd, cmd, arg) X int fd, cmd, arg; X{ X switch (cmd) { X case F_SETFD: /* set fd flags */ X ioctl(fd, (arg&FD_CLEXEC) ? FIOCLEX : FIONCLEX, (char *)NULL); X break; X case F_DUPFD: /* dup fd */ X /* this one is fun. find an unused fd >= arg and dup2 */ X break; X } X return 0; X} X X#endif X SHAR_EOF true || echo 'restore of posix/fcntl.c failed' fi # ============= posix/fcntl.h ============== if test -f 'posix/fcntl.h' -a X"$1" != X"-c"; then echo 'x - skipping posix/fcntl.h (File already exists)' else echo 'x - extracting posix/fcntl.h (Text)' sed 's/^X//' << 'SHAR_EOF' > 'posix/fcntl.h' && X/* P1003.1 fcntl/open definitions */ X/* Based on a version by Terrence W. Holm */ X X/* for fcntl(2) */ X X#define F_DUPFD 0 X#define F_GETFD 1 X#define F_SETFD 2 X#define F_GETFL 3 X#define F_SETFL 4 X X#define FD_CLEXEC 1 /* fcntl F_SETFD close on exec mode */ X X/* for open(2) */ X X#define O_RDONLY 0 X#define O_WRONLY 1 X#define O_RDWR 2 X X#if _BSD X#undef O_RDONLY X#undef O_WRONLY X#undef O_RDWR X#include "/usr/include/fcntl.h" X#endif X SHAR_EOF true || echo 'restore of posix/fcntl.h failed' fi # ============= posix/io.h ============== if test -f 'posix/io.h' -a X"$1" != X"-c"; then echo 'x - skipping posix/io.h (File already exists)' else echo 'x - extracting posix/io.h (Text)' sed 's/^X//' << 'SHAR_EOF' > 'posix/io.h' && X/* POSIX IO functions */ X X/* include <unistd.h> to get this */ X X#if ! _IO_H X#define _IO_H 1 X X#include <unistd.h> X X#if _ST /* dLibs hack */ X#define unlink remove X#endif X Xstruct stat; /* create global incompletely-typed structure */ X Xint chdir ARGS ((const char *path)); Xint umask ARGS ((int mode)); X Xint open ARGS ((const char *path, int flags, ... /*mode*/)); Xint creat ARGS ((const char *path, int mode)); Xint pipe ARGS ((int pv[2])); Xint close ARGS ((int fd)); X Xint fcntl ARGS ((int fd, int cmd, int arg)); Xint dup ARGS ((int fd)); Xint dup2 ARGS ((int ofd, int nfd)); X Xint link ARGS ((const char *opath, const char *npath)); Xint unlink ARGS ((const char *path)); Xint rename ARGS ((const char *opath, const char *npath)); Xint mkdir ARGS ((const char *path, int mode)); X Xlong lseek ARGS ((int fd, long off, int how)); Xint read ARGS ((int fd, char *buf, unsigned len)); Xint write ARGS ((int fd, char *buf, unsigned len)); X Xint access ARGS ((const char *path, int mode)); Xint stat ARGS ((const char *path, struct stat *sp)); Xint fstat ARGS ((int fd, struct stat *sp)); X Xint chmod ARGS ((const char *path, int mode)); Xint chown ARGS ((const char *path, int uid)); Xint chgrp ARGS ((const char *path, int gid)); Xint utime ARGS ((const char *path, long tv[2])); X X#if _BSD || _V7 Xint ioctl ARGS ((int fd, int cmd, void *argp)); /* BSD is "uns long cmd" */ X#endif X X#endif SHAR_EOF true || echo 'restore of posix/io.h failed' fi # ============= posix/times.c ============== if test -f 'posix/times.c' -a X"$1" != X"-c"; then echo 'x - skipping posix/times.c (File already exists)' else echo 'x - extracting posix/times.c (Text)' sed 's/^X//' << 'SHAR_EOF' > 'posix/times.c' && X/* P1003.1 times emulation */ X X#include <sys/times.h> X X#if _BSD X X#include <sys/time.h> X#include <sys/resource.h> X Xstatic long base_tv_sec = 0; X Xclock_t Xtimes(tmsp) X register struct tms *tmsp; X{ X struct timeval tv; X struct rusage ru; X X getrusage(RUSAGE_SELF, &ru); X tmsp->tms_utime = ru.ru_utime.tv_sec*CLK_TCK X + (long)ru.ru_utime.tv_usec*CLK_TCK/1000000; X tmsp->tms_stime = ru.ru_stime.tv_sec*CLK_TCK X + (long)ru.ru_stime.tv_usec*CLK_TCK/1000000; X getrusage(RUSAGE_CHILDREN, &ru); X tmsp->tms_cutime = ru.ru_utime.tv_sec*CLK_TCK X + (long)ru.ru_utime.tv_usec*CLK_TCK/1000000; X tmsp->tms_cstime = ru.ru_stime.tv_sec*CLK_TCK X + (long)ru.ru_stime.tv_usec*CLK_TCK/1000000; X X gettimeofday(&tv, (struct timezone *)NULL); X if (base_tv_sec == 0) X base_tv_sec = tv.tv_sec; X tv.tv_sec -= base_tv_sec; /* prevent clock_t overflow */ X return tv.tv_sec*CLK_TCK + (long)tv.tv_usec*CLK_TCK/1000000; X} X X#endif X X#if _V7 X Xclock_t Xtimes(tmsp) X struct tms *tmsp; X{ X struct timeb tb; X X#undef times /* access real times() */ X times(tmsp); X#define times times_ X ftime(&tb); X return tb.time*CLK_TCK + (long)tb.millitm*CLK_TCK/1000; X} X X#endif X SHAR_EOF true || echo 'restore of posix/times.c failed' fi # ============= posix/unistd.c ============== if test -f 'posix/unistd.c' -a X"$1" != X"-c"; then echo 'x - skipping posix/unistd.c (File already exists)' else echo 'x - extracting posix/unistd.c (Text)' sed 's/^X//' << 'SHAR_EOF' > 'posix/unistd.c' && X/* misc. POSIX emulation */ X X/* $Header$ */ X X#include <string.h> X#include <errno.h> X#include <sys/types.h> X#include <unistd.h> X X#if _V7 || _BSD X Xchar * Xgetcwd(buf, len) X char *buf; X size_t len; X{ X char cwd [1024]; X extern char *getwd(); X if (getwd(cwd) == NULL) X return NULL; X if (strlen(cwd)+1 >= len) { X errno = ERANGE; X return NULL; X } X return strcpy(buf, cwd); X} X X#endif X X#if _V7 X Xlong Xulimit(cmd, limit) X int cmd; X long limit; X{ X return 0; X} X X#endif X SHAR_EOF true || echo 'restore of posix/unistd.c failed' fi # ============= posix/unistd.h ============== if test -f 'posix/unistd.h' -a X"$1" != X"-c"; then echo 'x - skipping posix/unistd.h (File already exists)' else echo 'x - extracting posix/unistd.h (Text)' sed 's/^X//' << 'SHAR_EOF' > 'posix/unistd.h' && X/* unistd.h: misc. P1003.1 definitions */ X/* Based on a version by Terrence W. Holm */ X X#if ! _UNISTD_H X#define _UNISTD_H 1 X X#include <stddef.h> X X/* doesn't really belong here, but the library function need it */ X/* todo: use _ARGS, _Void, _Const */ X#if __STDC__ X#define ARGS(args) args X#define Void void X#define Const const X#else X#define ARGS(args) () X#define Void char X#define Const X#endif X X#include <io.h> /* POSIX IO functions */ X X/* for access(2) */ X X#define R_OK 4 X#define W_OK 2 X#define X_OK 1 X#define F_OK 0 X X/* for lockf(2) */ X X#define F_ULOCK 0 X#define F_LOCK 1 X#define F_TLOCK 2 X#define F_TEST 3 X X/* for lseek(2) */ X X#define SEEK_SET 0 X#define SEEK_CUR 1 X#define SEEK_END 2 X X#define IN_PATH "/usr/include" X Xchar *getcwd ARGS ((char *buf, size_t len)); X X#endif X SHAR_EOF true || echo 'restore of posix/unistd.h failed' fi # ============= posix/time.h ============== if test -f 'posix/time.h' -a X"$1" != X"-c"; then echo 'x - skipping posix/time.h (File already exists)' else echo 'x - extracting posix/time.h (Text)' sed 's/^X//' << 'SHAR_EOF' > 'posix/time.h' && X/* X * Replacement for BSD <sys/time.h> X * because Ultrix screws it up. X */ X Xstruct timeval { X long tv_sec; /* time_t */ X long tv_usec; /* microsex */ X}; X Xstruct timezone { X int tz_minuteswest; /* of Greenwinch */ X int tz_dsttime; /* type of dst correction to apply */ X}; SHAR_EOF true || echo 'restore of posix/time.h failed' fi # ============= posix/times.h ============== if test -f 'posix/times.h' -a X"$1" != X"-c"; then echo 'x - skipping posix/times.h (File already exists)' else echo 'x - extracting posix/times.h (Text)' sed 's/^X//' << 'SHAR_EOF' > 'posix/times.h' && X/* X * sys/times.h: POSIX times() X */ X X#if ! _TIMES_H X#define _TIMES_H 1 X X#include <time.h> /* defines CLK_TCK */ X X#if __STDC__ X#define ARGS(args) args X#else X#define ARGS(args) () X#endif X Xstruct tms { X clock_t tms_utime, tms_stime; X clock_t tms_cutime, tms_cstime; X}; X X#if _V7 X#define times times_ X#endif X Xclock_t times ARGS((struct tms *tmsp)); X X#endif X SHAR_EOF true || echo 'restore of posix/times.h failed' fi # ============= posix/wait.h ============== if test -f 'posix/wait.h' -a X"$1" != X"-c"; then echo 'x - skipping posix/wait.h (File already exists)' else echo 'x - extracting posix/wait.h (Text)' sed 's/^X//' << 'SHAR_EOF' > 'posix/wait.h' && X/* X * POSIX <sys/wait.h> X */ X X#if __STDC__ X#define ARGS(args) args X#else X#define ARGS(args) () X#endif X X#if 1 Xtypedef int pid_t; /* belong in sys/types.h */ X#endif X X/* waitpid options */ X#define WNOHANG 1 /* don't hang in wait */ X#define WUNTRACED 2 /* tell about stopped, untraced children */ X X#define WSTOPPED 0x7F /* process is stopped */ X X#define WIFSTOPPED(x) (((x)&0xFF) == 0x7F) X#define WIFSIGNALED(x) (((x)&0xFF) != 0x7F && ((x)&0x7F) != 0) X#define WIFEXITED(x) (((x)&0xFF) != 0x7F && ((x)&0x7F) == 0) X#define WIFCORED(x) (!!((x)&0x80)) /* non-standard */ X#define WEXITSTATUS(x) ((x)>>8&0xFF) X#define WTERMSIG(x) ((x)&0x7F) X#define WSTOPSIG(x) ((x)>>8&0xFF) X Xpid_t wait ARGS((int *statp)); X#if _BSD Xpid_t wait3 ARGS((int *statp, int options, Void *)); X/* todo: does not emulate pid argument */ X#define waitpid(pid, sp, opts) wait3(sp, opts, (Void*)NULL) X#else Xpid_t waitpid ARGS((pid_t pid, int *statp, int options)); X#endif X SHAR_EOF true || echo 'restore of posix/wait.h failed' fi # ============= posix/fixincludes ============== if test -f 'posix/fixincludes' -a X"$1" != X"-c"; then echo 'x - skipping posix/fixincludes (File already exists)' else echo 'x - extracting posix/fixincludes (Text)' sed 's/^X//' << 'SHAR_EOF' > 'posix/fixincludes' && X# Install modified versions of certain ANSI-incompatible system header files X# which are fixed to work correctly with ANSI C X# and placed in a directory that GNU C will search. X# This works properly on a Sun in system version 3.4; X# for other versions, you had better check. X Xmkdir /usr/local/lib/gcc-include Xmkdir /usr/local/lib/gcc-include/sys Xcp /usr/include/sys/ioctl.h /usr/local/lib/gcc-include/sys/ioctl.h Xchmod +w /usr/local/lib/gcc-include/sys/ioctl.h Xex /usr/local/lib/gcc-include/sys/ioctl.h <<\EOF Xg/_IO/s/(\(.\),/('\1',/ Xg/#define._IO/s/'x'/x/g Xwq XEOF X Xcp /usr/include/sys/ttychars.h /usr/local/lib/gcc-include/sys/ttychars.h Xchmod +w /usr/local/lib/gcc-include/sys/ttychars.h Xex /usr/local/lib/gcc-include/sys/ttychars.h <<\EOF Xg/CTRL/s/(\(.\))/('\1')/ Xg/#define.CTRL/s/'c'/c/g Xwq XEOF SHAR_EOF true || echo 'restore of posix/fixincludes failed' fi # ============= stdc/Makefile ============== if test ! -d 'stdc'; then echo 'x - creating directory stdc' mkdir 'stdc' fi if test -f 'stdc/Makefile' -a X"$1" != X"-c"; then echo 'x - skipping stdc/Makefile (File already exists)' else echo 'x - extracting stdc/Makefile (Text)' sed 's/^X//' << 'SHAR_EOF' > 'stdc/Makefile' && X# Standard C (ANSI) compatabilaty X# does not requires SVID/P1003.2-compatible "make" X X# $Header: Makefile,v 1.1 88/03/29 18:28:38 egisin Locked $ X XSYSTEM=BSD XCC = gcc -ansi -O -W XLN = ln XPRINT = lpr -p -Plp26_3018 X XCFLAGS = -I../h -D_$(SYSTEM) X XMISC = Makefile stdio.h_std XHDRS = limits.h stddef.h stdlib.h string.h time.h stdarg.h XSRCS = clock.c stdio.c setvbuf.c vprintf.c fprintf.c sprintf.c \ X strstr.c \ X memmove.c memcpy.c memset.c memcmp.c memchr.c XOBJS = clock.o stdio.o setvbuf.o vprintf.o fprintf.o sprintf.o \ X strstr.o \ X memmove.o memcpy.o memset.o memcmp.o memchr.o X#OBJS = $(SRCS:.c=.o) XLIB = libstdc.a XINCL = ../h X Xall: $(LIB) X Xlink: $(HDRS) stdio.h X [ -d $(INCL) ] || mkdir $(INCL) X [ -d $(INCL)/sys ] || mkdir $(INCL)/sys X $(LN) types.h $(INCL)/sys X $(LN) limits.h stddef.h stdlib.h stdio.h string.h time.h stdarg.h $(INCL) X X$(LIB)(%.o): %.o X X%: RCS/%,v X co %@ X X$(LIB): $(OBJS) X ar r $@ $? X -ranlib $@ X X#$(LIB): lib.a($OBJS) X# ar rv $@ $? X# -ranlib $@ X# rm -f $? X Xstdio.h: stdio.h_std /usr/include/stdio.h X sed </usr/include/stdio.h >stdio.hacked \ X -e '/^# *include/ d' -e '/char..sprintf/ d' -e '/# *define.NULL./ d' X sed <stdio.h_std >stdio.h -e '/%%%/ r stdio.hacked' X rm stdio.hacked X Xstd_c.tar: $(MISC) $(HDRS) $(SRCS) X tar cf std_c.tar $(MISC) $(HDRS) $(SRCS) X Xprint: $(MISC) $(HDRS) $(SRCS) X $(PRINT) $(MISC) $(HDRS) $(SRCS) X Xstring.h: stddef.h X Xstdlib.h: stddef.h X Xstdio.h: stddef.h X Xtime.h: stddef.h X Xstdio.o: stdio.h X Xsetvbuf.o: stdlib.h stdio.h X Xfprintf.o: stdarg.h stdio.h X Xsprintf.o: stdarg.h stdio.h X Xvprintf.o: stdarg.h stdio.h X Xstrstr.o: string.h X SHAR_EOF true || echo 'restore of stdc/Makefile failed' fi # ============= stdc/vprintf.c ============== if test -f 'stdc/vprintf.c' -a X"$1" != X"-c"; then echo 'x - skipping stdc/vprintf.c (File already exists)' else echo 'x - extracting stdc/vprintf.c (Text)' sed 's/^X//' << 'SHAR_EOF' > 'stdc/vprintf.c' && X#if __STDC__ X#include <stdarg.h> X#else X#include <varargs.h> X#endif X#include <stdio.h> X X#define BUF 40 /* buffer for int -> string conversion */ X Xint X#if __STDC__ Xvprintf(Const char *fmt, va_list va) { X#else Xvprintf(fmt, va) char *fmt; va_list va; { X#endif X return vfprintf(stdout, fmt, va); X} X Xint X#if __STDC__ Xvfprintf(register FILE *f, register Const char *fmt, register va_list va) { X#else Xvfprintf(f, fmt, va) register FILE *f; register char *fmt; register va_list va; { X#endif X register int c; X int pos = 0; /* todo: implement */ X X while ((c = *fmt++)) X if (c == '%') { X long n; X register unsigned long u; X char buf [BUF+1]; X register char *p = buf + BUF; X register enum { X FF_ALT = 0x01, /* #, alternate format */ X FF_SHORT = 0x02, /* h, short arg */ X FF_LONG = 0x04, /* l, long arg */ X FF_ZERO = 0x08, /* 0, zero fill */ X FF_LEFT = 0x10, /* -, left adjust */ X FF_PREC = 0x20, /* .*, precision */ X FF_NEG = 0x40, /* signed arg */ X FF_PUTS = 0x80, /* fputs(p, f) */ X FF_DEFAULT = 0 X } flags = FF_DEFAULT; X int sign = '-'; /* sign: [ +-] */ X int width = 0, prec = 0; /* width, precision */ X X *p = 0; X X /* scan flag characters */ X for (c = *fmt++; ; c = *fmt++) switch (c) { X case '0': X flags |= FF_ZERO; X break; X X case '#': /* alternate format */ X flags |= FF_ALT; X break; X X case ' ': /* blank sign */ X sign = ' '; X break; X case '+': /* +/- sign */ X sign = '+'; X break; X X case '-': /* left just. */ X flags |= FF_LEFT; X break; X X default: X goto Frogs; X } X Frogs: X X /* scan width */ X if (c == '*') { /* width from arg list */ X width = va_arg(va, int); X c = *fmt++; X } else X while ('0' <= c && c <= '9') { X width = width*10 + (c-'0'); X c = *fmt++; X } X X if (c == '.') { /* scan precision */ X flags |= FF_PREC; X c = *fmt++; X if (c == '*') { /* precision from arg list */ X prec = va_arg(va, int); X c = *fmt++; X } else X while ('0' <= c && c <= '9') { X prec = prec*10 + (c-'0'); X c = *fmt++; X } X } X X /* length modifiers */ X if (c == 'h') { X flags |= FF_SHORT; X c = *fmt++; X } else if (c == 'l') { X flags |= FF_LONG; X c = *fmt++; X } X X /* do conversion */ X switch (c) { X case '%': /* %% -> % */ X putc(c, f); X pos ++; X break; X X case 'p': /* pointer */ X *--p = '}'; X u = (unsigned long) va_arg(va, Void*); X do { X *--p = "0123456789ABCDEF"[u%16]; X u /= 16; X } while (u != 0); X *--p = '{'; X flags |= FF_PUTS; X break; X X case 'n': /* save position */ X *va_arg(va, int*) = pos; X break; X X case 'c': /* character */ X u = (flags&FF_SHORT) ? va_arg(va, unsigned short) X : (flags&&FF_LONG) ? va_arg(va, unsigned long) X : va_arg(va, unsigned int); X *--p = u; X flags |= FF_PUTS; X break; X X case 's': /* string */ X p = va_arg(va, char *); X if ((flags&FF_PREC) && strlen(p) > prec) { X pos += prec; X while (--prec >= 0) X putc(*p++, f); X break; X } X flags |= FF_PUTS; X break; X X case 'i': case 'd': case 'u': /* decimal */ X if (c != 'u') { /* signed */ X n = (flags&FF_SHORT) ? va_arg(va, short) X : (flags&&FF_LONG) ? va_arg(va, long) X : va_arg(va, int); X if (n < 0) X flags |= FF_NEG; X u = (n < 0) ? -n : n; X } else X u = (flags&FF_SHORT) ? va_arg(va, unsigned short) X : (flags&&FF_LONG) ? va_arg(va, unsigned long) X : va_arg(va, unsigned int); X do { X *--p = '0' + u%10; X u /= 10; X } while (u != 0); X prec -= buf+BUF - p; X while (--prec >= 0) X *--p = '0'; X if (flags&FF_NEG) X *--p = '-'; X else X if (sign != '-') X *--p = (sign == '+') ? '+' : ' '; X flags |= FF_PUTS; X break; X X case 'x': case 'X': /* hex, Hex */ X u = (flags&FF_SHORT) ? va_arg(va, unsigned short) X : (flags&&FF_LONG) ? va_arg(va, unsigned long) X : va_arg(va, unsigned int); X do { X *--p = "0123456789ABCDEF"[u%16]; X u /= 16; X } while (u != 0); X prec -= buf+BUF - p; X while (--prec >= 0) X *--p = '0'; X if (flags&&FF_ALT) X *--p = 'x', *--p = '0'; X flags |= FF_PUTS; X break; X X case 'o': /* octal */ X u = (flags&FF_SHORT) ? va_arg(va, unsigned short) X : (flags&&FF_LONG) ? va_arg(va, unsigned long) X : va_arg(va, unsigned int); X do { X *--p = '0' + u%8; X u /= 8; X } while (u != 0); X prec -= buf+BUF - p; X while (--prec >= 0) X *--p = '0'; X if (flags&&FF_ALT && *p != '0') X *--p = '0'; X flags |= FF_PUTS; X break; X X default: /* todo: error */ X putc('%', f); X putc(c, f); X pos += 2; X break; X } X X /* copy adjusted string "p" to output */ X if (flags&FF_PUTS) { X int len = strlen(p); X int pad = width - len; X if (!(flags&FF_LEFT)) X while (--pad >= 0) X putc(' ', f); X while (*p) X putc(*p++, f); X if ((flags&FF_LEFT)) X while (--pad >= 0) X putc(' ', f); X pos += (len < width) ? width : len; X } X } else { /* ordinary character */ X putc(c, f); X pos ++; X } X return pos; X} X SHAR_EOF true || echo 'restore of stdc/vprintf.c failed' fi # ============= stdc/stddef.h ============== if test -f 'stdc/stddef.h' -a X"$1" != X"-c"; then echo 'x - skipping stdc/stddef.h (File already exists)' else echo 'x - extracting stdc/stddef.h (Text)' sed 's/^X//' << 'SHAR_EOF' > 'stdc/stddef.h' && X/* ANSI common definitions */ X X/* $Header$ */ X X#ifndef NULL X#if __STDC__ X#define NULL (void*)0 X#else X#define NULL 0 X#endif X#endif X X#if ! _STDDEF_H X#define _STDDEF_H 1 X X/* doesn't really belong here, but the library function need it */ X#if __STDC__ X#define ARGS(args) args X#define Void void X#define Const const X#else X#define ARGS(args) () X#define Void char X#define Const X#endif X Xtypedef unsigned size_t; /* may need long */ Xtypedef int ptrdiff_t; X X#define offsetof(type,id) ((size_t)&((type*)NULL)->id) X Xextern int errno; /* really belongs in <errno.h> */ X X#endif X SHAR_EOF true || echo 'restore of stdc/stddef.h failed' fi # ============= stdc/stdio.c ============== if test -f 'stdc/stdio.c' -a X"$1" != X"-c"; then echo 'x - skipping stdc/stdio.c (File already exists)' else echo 'x - extracting stdc/stdio.c (Text)' sed 's/^X//' << 'SHAR_EOF' > 'stdc/stdio.c' && X/* X * Emulation of misc. ANSI C stdio functions X */ X X/* $Header */ X X#include <stdio.h> X X#if 1 Xint Xremove(name) X Const char *name; X{ X return unlink(name); X} X#endif X X#if _V7 Xint Xrename(oname, name) X Const char *oname, *nname; X{ X return link(oname, nname) == 0 && unlink(oname) == 0 ? 0 : -1; X} X#endif X SHAR_EOF true || echo 'restore of stdc/stdio.c failed' fi true || echo 'restore of stdc/stdio.h failed' echo End of part 6, continue with part 7 exit 0