home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / altsrcs / 2 / 2266 < prev    next >
Encoding:
Internet Message Format  |  1990-12-28  |  45.0 KB

  1. From: netnews@netcom.UUCP (USENET Administration)
  2. Newsgroups: alt.sources
  3. Subject: Public Domain Korn Shell - Part.02 of 7
  4. Message-ID: <18607@netcom.UUCP>
  5. Date: 12 Dec 90 11:35:35 GMT
  6.  
  7. #!/bin/sh
  8. # This is part 02 of ksh-pd
  9. # ============= src/lex.h ==============
  10. if test ! -d 'src'; then
  11.     echo 'x - creating directory src'
  12.     mkdir 'src'
  13. fi
  14. if test -f 'src/lex.h' -a X"$1" != X"-c"; then
  15.     echo 'x - skipping src/lex.h (File already exists)'
  16. else
  17. echo 'x - extracting src/lex.h (Text)'
  18. sed 's/^X//' << 'SHAR_EOF' > 'src/lex.h' &&
  19. X/*
  20. X * Source input, lexer and parser
  21. X */
  22. X
  23. X/* $Header: /tmp/egisin/src/RCS/lex.h,v 3.2 88/12/17 21:40:07 egisin Exp $ */
  24. X
  25. X#define    IDENT    64
  26. X
  27. Xtypedef struct source Source;
  28. Xstruct source {
  29. X    char   *str;        /* input pointer */
  30. X    int    type;        /* input type */
  31. X    union {
  32. X        char  **strv;    /* string [] */
  33. X        FILE   *file;    /* file */
  34. X        struct tbl *tblp; /* alias */
  35. X    } u;
  36. X    int    line;        /* line number */
  37. X    char   *file;        /* input file name */
  38. X    int    echo;        /* echo input to shlout */
  39. X    Source *next;        /* stacked source */
  40. X};
  41. X
  42. X/* Source.type values */
  43. X#define    SEOF    0        /* input EOF */
  44. X#define    STTY    1        /* terminal input */
  45. X#define    SFILE    2        /* file input */
  46. X#define    SSTRING    4        /* string */
  47. X#define    SWSTR    3        /* string without \n */
  48. X#define    SWORDS    5        /* string[] */
  49. X#define    SWORDSEP 8        /* string[] seperator */
  50. X#define    SALIAS    6        /* alias expansion */
  51. X#define    SHIST    7        /* history expansion */
  52. X
  53. XSource *pushs ARGS((int stype));     /* push Source */
  54. Xstruct op *compile ARGS((Source *s));    /* compile tree */
  55. X
  56. X/*
  57. X * states while lexing word
  58. X */
  59. X#define    SBASE    0        /* outside any lexical constructs */
  60. X#define    SWORD    6        /* implicit quoting for substitute() */
  61. X#define    SSQUOTE    1        /* inside '' */
  62. X#define    SDQUOTE    2        /* inside "" */
  63. X#define    SBRACE    3        /* inside ${} */
  64. X#define    SPAREN    4        /* inside $() */
  65. X#define    SBQUOTE    5        /* inside `` */
  66. X
  67. XExtern    int    multiline;    /* \n changed to ; */
  68. X
  69. Xtypedef union {
  70. X    int    i;
  71. X    char   *cp;
  72. X    char  **wp;
  73. X    struct op *o;
  74. X    struct ioword *iop;
  75. X} YYSTYPE;
  76. X
  77. X#define    LWORD    256
  78. X#define    LOGAND    257
  79. X#define    LOGOR    258
  80. X#define    BREAK    259
  81. X#define    IF    260
  82. X#define    THEN    261
  83. X#define    ELSE    262
  84. X#define    ELIF    263
  85. X#define    FI    264
  86. X#define    CASE    265
  87. X#define    ESAC    266
  88. X#define    FOR    267
  89. X#define    WHILE    268
  90. X#define    UNTIL    269
  91. X#define    DO    270
  92. X#define    DONE    271
  93. X#define    IN    272
  94. X#define    FUNCTION 273
  95. X#define    TIME    274
  96. X#define    REDIR    275
  97. X#define    MPAREN    276        /* () */
  98. X#define    YYERRCODE 300
  99. X
  100. X/* flags to yylex */
  101. X#define    CONTIN    BIT(0)        /* skip new lines to complete command */
  102. X#define    ONEWORD    BIT(1)        /* single word for substitute() */
  103. X#define    ALIAS    BIT(2)        /* recognize alias */
  104. X#define    KEYWORD    BIT(3)        /* recognize keywords */
  105. X
  106. X#define    SYNTAXERR    zzerr()
  107. X#define    HERES    10        /* max << in line */
  108. X
  109. XExtern    char    line [LINE+1];    /* input line */
  110. XExtern    Source *source;        /* yyparse/yylex source */
  111. XExtern    YYSTYPE    yylval;        /* result from yylex */
  112. XExtern    int    yynerrs;
  113. XExtern    struct ioword *heres [HERES], **herep;
  114. XExtern    char    ident [IDENT+1];
  115. X
  116. Xextern    int    yylex ARGS((int flags));
  117. Xextern    void    yyerror ARGS((Const char *msg));
  118. X
  119. X#define    HISTORY    100        /* size of saved history */
  120. X
  121. Xextern    char   *history [HISTORY];    /* saved commands */
  122. Xextern    char  **histptr;    /* last history item */
  123. Xextern    int    histpush;    /* number of pushed fc commands */
  124. X
  125. SHAR_EOF
  126. true || echo 'restore of src/lex.h failed'
  127. fi
  128. # ============= src/tree.h ==============
  129. if test -f 'src/tree.h' -a X"$1" != X"-c"; then
  130.     echo 'x - skipping src/tree.h (File already exists)'
  131. else
  132. echo 'x - extracting src/tree.h (Text)'
  133. sed 's/^X//' << 'SHAR_EOF' > 'src/tree.h' &&
  134. X/*
  135. X * command trees for compile/execute
  136. X */
  137. X
  138. X/* $Header: /tmp/egisin/src/RCS/tree.h,v 3.2 88/12/17 21:40:31 egisin Exp $ */
  139. X
  140. X#define    NOBLOCK    ((struct op *)NULL)
  141. X#define    NOWORD    ((char *)NULL)
  142. X#define    NOWORDS    ((char **)NULL)
  143. X
  144. X/*
  145. X * Description of a command or an operation on commands.
  146. X */
  147. Xstruct op {
  148. X    int    type;            /* operation type, see below */
  149. X    char  **args;            /* arguments to a command */
  150. X    char  **vars;            /* variable assignments */
  151. X    struct ioword    **ioact;    /* IO actions (eg, < > >>) */
  152. X    struct op *left, *right;     /* descendents */
  153. X    char   *str;        /* identifier for case and for (use vars[0]) */
  154. X};
  155. X
  156. X/* Tree.type values */
  157. X#define    TEOF    0
  158. X#define    TCOM    1        /* command */
  159. X#define    TPAREN    2        /* (c-list) */
  160. X#define    TPIPE    3        /* a | b */
  161. X#define    TLIST    4        /* a [&;] b */
  162. X#define    TOR    5        /* || */
  163. X#define    TAND    6        /* && */
  164. X#define    TFOR    7
  165. X#define    TCASE    9
  166. X#define    TIF    10
  167. X#define    TWHILE    11
  168. X#define    TUNTIL    12
  169. X#define    TELIF    13
  170. X#define    TPAT    14        /* pattern in case */
  171. X#define    TBRACE    15        /* {c-list} */
  172. X#define    TASYNC    16        /* c & */
  173. X#define    TFUNCT    17        /* function name { command; } */
  174. X#define    TTIME    18        /* time pipeline */
  175. X#define    TEXEC    19        /* fork/exec eval'd TCOM */
  176. X
  177. X/*
  178. X * prefix codes for words in command tree
  179. X */
  180. X#define    EOS    0        /* end of string */
  181. X#define    CHAR    1        /* unquoted character */
  182. X#define    QCHAR    2        /* quoted character */
  183. X#define    COMSUB    3        /* $() substitution (0 terminated) */
  184. X#define    OQUOTE    4        /* opening " or ' */
  185. X#define    CQUOTE    5        /* closing " or ' */
  186. X#define    OSUBST    6        /* opening ${ substitution */
  187. X#define    CSUBST    7        /* closing } of above */
  188. X
  189. X/*
  190. X * IO redirection
  191. X */
  192. Xstruct ioword {
  193. X    short    unit;    /* unit affected */
  194. X    short    flag;    /* action (below) */
  195. X    char   *name;    /* file name */
  196. X};
  197. X
  198. X/* ioword.flag - type of redirection */
  199. X#define    IOTYPE    0xF        /* type: bits 0:3 */
  200. X#define    IOREAD    0x1        /* < */
  201. X#define    IOWRITE    0x2        /* > */
  202. X#define    IORDWR    0x3        /* <>: todo */
  203. X#define    IOHERE    0x4        /* << (here file) */
  204. X#define    IOCAT    0x5        /* >> */
  205. X#define    IODUP    0x6        /* <&/>& */
  206. X#define    IOEVAL    BIT(4)        /* expand in << */
  207. X#define    IOSKIP    BIT(5)        /* <<-, skip ^\t* */
  208. X#define    IOCLOB    BIT(6)        /* >!, override -o noclob */
  209. X
  210. X/* values for E_LOOP longjmp */
  211. X#define    LBREAK    1
  212. X#define    LCONTIN    2
  213. X
  214. X/* execute/exchild flags */
  215. X#define    XEXEC    BIT(0)        /* execute without forking */
  216. X#define    XFORK    BIT(5)        /* fork before executing */
  217. X#define    XBGND    BIT(1)        /* command & */
  218. X#define    XPIPEI    BIT(2)        /* input is pipe */
  219. X#define    XPIPEO    BIT(3)        /* output is pipe */
  220. X#define    XPIPE    (XPIPEI|XPIPEO)    /* member of pipe */
  221. X#define    XXCOM    BIT(4)        /* dup2 xcomfd to 1 */
  222. X
  223. X/*
  224. X * flags to control expansion of words
  225. X */
  226. X#define    DOBLANK    BIT(1)        /* perform blank interpretation */
  227. X#define    DOGLOB    BIT(2)        /* expand [?* */
  228. X#define    DOPAT    BIT(3)        /* quote *?[ */
  229. X#define    DOTILDE    BIT(5)        /* expand ~ */
  230. X
  231. X/* job.c: job control primatives */
  232. Xint    execute ARGS((struct op *, int flags));    /* execute tree */
  233. Xint    exchild ARGS((struct op *, int flags));    /* execute tree as child */
  234. Xint    waitfor ARGS((int job));         /* wait for job completion */
  235. Xint    waitlast ARGS((void));            /* wait for last job */
  236. X
  237. X/* eval.c: word expansion */
  238. Xchar  **eval ARGS((char **wv, int flag));     /* expand words */
  239. Xchar   *evalstr ARGS((char *wp, int flags));    /* expand word */
  240. Xchar   *substitute ARGS((Const char *s, int flags)); /* compile and expand string */
  241. X
  242. X/* tree.c: command trees */
  243. Xvoid    ptree ARGS((struct op *t, FILE *f));    /* print tree */
  244. Xchar   *wdscan ARGS((char *wp, int c));        /* scan word for prefix */
  245. Xchar   *wdcopy ARGS((char *wp, Area *));    /* copy word */
  246. Xstruct op *tcopy ARGS((struct op *t, Area *));    /* copy tree */
  247. Xvoid    tfree ARGS((struct op *t, Area *));    /* free tree */
  248. X
  249. SHAR_EOF
  250. true || echo 'restore of src/tree.h failed'
  251. fi
  252. # ============= src/tty.h ==============
  253. if test -f 'src/tty.h' -a X"$1" != X"-c"; then
  254.     echo 'x - skipping src/tty.h (File already exists)'
  255. else
  256. echo 'x - extracting src/tty.h (Text)'
  257. sed 's/^X//' << 'SHAR_EOF' > 'src/tty.h' &&
  258. X/*
  259. X    tty.h -- centralized definitions for a variety of terminal interfaces
  260. X
  261. X    created by DPK, Oct. 1986
  262. X
  263. X    last edit:    30-Jul-1987    D A Gwyn
  264. X*/
  265. X
  266. X#if _BSD_SYSV            /* BRL UNIX System V emulation */
  267. X#include <termio.h>    /* includes <sys/_ioctl.h> */
  268. X#ifndef NTTYDISC
  269. X#define    TIOCGETD    _IOR( 't', 0, int )
  270. X#define    TIOCSETD    _IOW( 't', 1, int )
  271. X#define    NTTYDISC    2
  272. X#endif
  273. X#ifndef TIOCSTI
  274. X#define    TIOCSTI        _IOW( 't', 114, char )
  275. X#endif
  276. X#ifndef TIOCSPGRP
  277. X#define    TIOCSPGRP    _IOW( 't', 118, int )
  278. X#endif
  279. X#else    /* !_BSD_SYSV */
  280. X#if _BSD
  281. X#include <sys/ioctl.h>
  282. X#else
  283. X#include <termio.h>
  284. X#endif
  285. X#endif    /* _BSD_SYSV */
  286. SHAR_EOF
  287. true || echo 'restore of src/tty.h failed'
  288. fi
  289. # ============= src/version.c ==============
  290. if test -f 'src/version.c' -a X"$1" != X"-c"; then
  291.     echo 'x - skipping src/version.c (File already exists)'
  292. else
  293. echo 'x - extracting src/version.c (Text)'
  294. sed 's/^X//' << 'SHAR_EOF' > 'src/version.c' &&
  295. X/*
  296. X * value of $KSH_VERSION
  297. X */
  298. X
  299. Xstatic char *RCSid = "$Header: /tmp/egisin/src/RCS/version.c,v 3.2 88/12/14 20:10:41 egisin Exp $";
  300. X
  301. X#include <stddef.h>
  302. X#include <setjmp.h>
  303. X#include "sh.h"
  304. X
  305. Xchar ksh_version [] =
  306. X    "KSH_VERSION=@(#) PD alpha $Revision: 3.2 $ $Date: 88/12/14 20:10:41 $";
  307. X
  308. X/***
  309. X$Log:    version.c,v $
  310. XRevision 3.2  88/12/14  20:10:41  egisin
  311. Xmany fixes
  312. X
  313. XRevision 3.1  88/11/03  09:18:36  egisin
  314. Xalpha distribution
  315. X
  316. XRevision 1.3  88/10/20  17:34:03  egisin
  317. Xadded @(#) to ksh_version
  318. X
  319. XRevision 1.2  88/09/27  19:01:58  egisin
  320. Xfix version.c
  321. X
  322. XRevision 1.1  88/09/27  18:59:06  egisin
  323. XInitial revision
  324. X***/
  325. X
  326. SHAR_EOF
  327. true || echo 'restore of src/version.c failed'
  328. fi
  329. # ============= src/main.c ==============
  330. if test -f 'src/main.c' -a X"$1" != X"-c"; then
  331.     echo 'x - skipping src/main.c (File already exists)'
  332. else
  333. echo 'x - extracting src/main.c (Text)'
  334. sed 's/^X//' << 'SHAR_EOF' > 'src/main.c' &&
  335. X/*
  336. X * startup, main loop, enviroments and error handling
  337. X */
  338. X
  339. Xstatic char *RCSid = "$Header: /tmp/egisin/src/RCS/main.c,v 3.2 88/12/17 19:56:54 egisin Exp $";
  340. X
  341. X#define    Extern                /* define Externs in sh.h */
  342. X
  343. X#include <stddef.h>
  344. X#include <stdlib.h>
  345. X#include <stdio.h>
  346. X#include <string.h>
  347. X#include <unistd.h>
  348. X#include <fcntl.h>
  349. X#include <signal.h>
  350. X#include <errno.h>
  351. X#include <setjmp.h>
  352. X#include "sh.h"
  353. X#include "lex.h"
  354. X#include "tree.h"
  355. X#include "table.h"
  356. X
  357. X/*
  358. X * global data
  359. X */
  360. X
  361. XArea    aperm;
  362. X
  363. Xstatic    void    reclaim ARGS((void));
  364. X
  365. X/*
  366. X * shell initialization
  367. X */
  368. X
  369. Xstatic    char    initifs [] = "IFS= \t\n"; /* must be R/W */
  370. X
  371. Xstatic    Const    char   initsubs [] = 
  372. X  "${SHELL:=/bin/sh} ${PATH:=/bin:/usr/bin:.} ${HOME:=/} ${PS1:=$ } ${PS2:=> }";
  373. X
  374. Xstatic    Const    char *initcoms [] = {
  375. X    "cd", ".", NULL,        /* set up $PWD */
  376. X    "typeset", "-x", "SHELL", "PATH", "HOME", NULL,
  377. X    "typeset", "-r", "PWD", "OLDPWD", NULL,
  378. X    "typeset", "-i", "SECONDS=0", "OPTIND", NULL,
  379. X    "alias",
  380. X      "integer=typeset -i", "pwd=print -r \"$PWD\"",
  381. X      "history=fc -l", "r=fc -s", "nohup=nohup ",
  382. X      "login=exec login", "newgrp=exec newgrp",
  383. X      "type=whence -v", "functions=typeset -f",
  384. X      "echo=print", "true=:", "false=let", "[=\\[", NULL,
  385. X    NULL
  386. X};
  387. X
  388. Xmain(argc, argv, envp)
  389. X    int argc;
  390. X    register char **argv;
  391. X    char **envp;
  392. X{
  393. X    register int i;
  394. X    register char *arg;
  395. X    int cflag = 0, qflag = 0;
  396. X    char *name;
  397. X    register Source *s;
  398. X    register struct block *l = &globals;
  399. X    register char **wp0, **wp;
  400. X    extern char ksh_version [];
  401. X
  402. X    ainit(&aperm);        /* initialize permanent Area */
  403. X
  404. X    /* set up base enviroment */
  405. X    e.type = E_NONE;
  406. X    ainit(&e.area);
  407. X    e.loc = l;
  408. X    e.savefd = NULL;
  409. X    e.oenv = NULL;
  410. X
  411. X    initctypes();
  412. X
  413. X    /* open file streams for fd's 0,1,2 */
  414. X    fopenshf(0);    fopenshf(1);    fopenshf(2);
  415. X
  416. X    /* set up variable and command dictionaries */
  417. X    newblock();        /* set up global l->vars and l->funs */
  418. X    tinit(&commands, APERM);
  419. X    tinit(&builtins, APERM);
  420. X    tinit(&lexicals, APERM);
  421. X    tinit(&homedirs, APERM);
  422. X
  423. X    /* import enviroment */
  424. X    if (envp != NULL)
  425. X        for (wp = envp; *wp != NULL; wp++)
  426. X            import(*wp);
  427. X
  428. X    typeset(initifs, 0, 0);    /* for security */
  429. X    typeset(ksh_version, 0, 0); /* RDONLY */
  430. X
  431. X    /* define shell keywords */
  432. X    keywords();
  433. X
  434. X    /* define built-in commands */
  435. X    for (i = 0; shbuiltins[i].name != NULL; i++)
  436. X        builtin(shbuiltins[i].name, shbuiltins[i].func);
  437. X    for (i = 0; kshbuiltins[i].name != NULL; i++)
  438. X        builtin(kshbuiltins[i].name, kshbuiltins[i].func);
  439. X
  440. X    /* assign default shell variable values */
  441. X    substitute(initsubs, 0);
  442. X    /* execute initialization statements */
  443. X    for (wp0 = (char**) initcoms; *wp0 != NULL; wp0 = wp+1) {
  444. X        /* copy because the alias initializers are readonly */
  445. X        for (wp = wp0; *wp != NULL; wp++)
  446. X            *wp = strsave(*wp, ATEMP);
  447. X        shcomexec(wp0);
  448. X    }
  449. X    afreeall(ATEMP);
  450. X
  451. X    if (geteuid() == 0)
  452. X        setstr(global("PS1"), "# ");
  453. X
  454. X    s = pushs(SFILE);
  455. X    s->u.file = stdin;
  456. X    cflag = 0;
  457. X    name = *argv++;
  458. X
  459. X    /* what a bloody mess */
  460. X    if (--argc >= 1) {
  461. X        if (argv[0][0] == '-' && argv[0][1] != '\0') {
  462. X            for (arg = argv[0]+1; *arg; arg++)
  463. X                switch (*arg) {
  464. X                  case 'c':
  465. X                    cflag = 1;
  466. X                    if (--argc > 0) {
  467. X                        s->type = SSTRING;
  468. X                        s->str = *++argv;
  469. X                    }
  470. X                    break;
  471. X    
  472. X                  case 'q':
  473. X                    qflag = 1;
  474. X                    break;
  475. X
  476. X                  default:
  477. X                    if (*arg>='a' && *arg<='z')
  478. X                        flag[FLAG(*arg)]++;
  479. X                }
  480. X        } else {
  481. X            argv--;
  482. X            argc++;
  483. X        }
  484. X        if (s->type == SFILE && --argc > 0) {
  485. X            if ((s->u.file = fopen(*++argv, "r")) == NULL)
  486. X                errorf("%s: cannot open\n", *argv);
  487. X            s->file = *argv;
  488. X            fileno(s->u.file) = savefd(fileno(s->u.file));
  489. X            setvbuf(s->u.file, (char *)NULL, _IOFBF, BUFSIZ);
  490. X        }
  491. X    }
  492. X
  493. X    if (s->type == SFILE) {
  494. X        if (fileno(s->u.file) == 0)
  495. X            flag[FSTDIN] = 1;
  496. X        if (isatty(0) && isatty(1) && !cflag)
  497. X            flag[FTALKING] = 1;
  498. X        if (flag[FTALKING] && flag[FSTDIN])
  499. X            s->type = STTY;
  500. X    }
  501. X    if (s->type == STTY) {
  502. X        ttyfd = fcntl(0, F_DUPFD, FDBASE);
  503. X        (void) fcntl(ttyfd, F_SETFD, FD_CLEXEC);
  504. X#if EDIT
  505. X        x_init();
  506. X#endif
  507. X    }
  508. X
  509. X    /* initialize job control */
  510. X    j_init();
  511. X
  512. X    if (!qflag)
  513. X        ignoresig(SIGQUIT);
  514. X
  515. X    l->argv = argv;
  516. X    l->argc = argc;
  517. X    l->argv[0] = name;
  518. X    resetopts();
  519. X
  520. X    if (name[0] == '-') {
  521. X        flag[FTALKING] = 1;
  522. X        (void) include("/etc/profile");
  523. X        (void) include(".profile");
  524. X    }
  525. X
  526. X    /* include $ENV */
  527. X    arg = substitute(strval(global("ENV")), DOTILDE);
  528. X    if (*arg != '\0')
  529. X        (void) include(arg);
  530. X
  531. X    if (flag[FTALKING]) {
  532. X        signal(SIGTERM, trapsig);
  533. X        ignoresig(SIGINT);
  534. X    } else
  535. X        flag[FHASHALL] = 1;
  536. X
  537. X#if JOBS            /* todo: could go before includes? */
  538. X    if (s->type == STTY) {
  539. X        flag[FMONITOR] = 1;
  540. X        j_change();
  541. X    }
  542. X#endif
  543. X
  544. X    argc = shell(s);
  545. X    leave(argc);
  546. X}
  547. X
  548. Xint
  549. Xinclude(name)
  550. X    register char *name;
  551. X{
  552. X    register FILE *f;
  553. X    register Source *s;
  554. X
  555. X    if (strcmp(name, "-") != 0) {
  556. X        f = fopen(name, "r");
  557. X        if (f == NULL)
  558. X            return 0;
  559. X        /* todo: the savefd doesn't get popped */
  560. X        fileno(f) = savefd(fileno(f)); /* questionable */
  561. X        setvbuf(f, (char *)NULL, _IOFBF, BUFSIZ);
  562. X    } else
  563. X        f = stdin;
  564. X    s = pushs(SFILE);
  565. X    s->u.file = f;
  566. X    s->file = name;
  567. X    /*return*/ shell(s);
  568. X    if (f != stdin)
  569. X        fclose(f);
  570. X    return 1;
  571. X}
  572. X
  573. Xint
  574. Xcommand(comm)
  575. X    register char *comm;
  576. X{
  577. X    register Source *s;
  578. X
  579. X    s = pushs(SSTRING);
  580. X    s->str = comm;
  581. X    return shell(s);
  582. X}
  583. X
  584. X/*
  585. X * run the commands from the input source, returning status.
  586. X */
  587. Xint
  588. Xshell(s)
  589. X    Source *s;        /* input source */
  590. X{
  591. X    struct op *t;
  592. X    Volatile int attempts = 13;
  593. X
  594. X    newenv(E_PARSE);
  595. X    e.interactive = 1;
  596. X    exstat = 0;
  597. X    if (setjmp(e.jbuf)) {
  598. X        /*shellf("<unwind>");*/
  599. X        if (trap)    /* pending SIGINT */
  600. X            shellf("\n");
  601. X        sigtraps[SIGINT].set = 0;
  602. X    }
  603. X
  604. X    while (1) {
  605. X        if (trap)
  606. X            runtraps();
  607. X        if (flag[FTALKING])
  608. X            signal(SIGINT, trapsig);
  609. X
  610. X        if (s->next == NULL)
  611. X            s->echo = flag[FVERBOSE];
  612. X
  613. X        j_notify();
  614. X
  615. X        if (s->type == STTY)
  616. X            prompt = substitute(strval(global("PS1")), 0);
  617. X
  618. X        t = compile(s);
  619. X        if (t != NULL && t->type == TEOF)
  620. X            if (s->type == STTY && flag[FIGNEOF] && --attempts > 0)
  621. X                shellf("Use `exit'\n");
  622. X            else
  623. X                break;
  624. X        flushshf(2);    /* flush -v output */
  625. X
  626. X        if (!flag[FNOEXEC] || s->type == STTY)
  627. X            execute(t, 0);
  628. X
  629. X        reclaim();
  630. X    }
  631. X  Error:
  632. X    quitenv();
  633. X    return exstat;
  634. X}
  635. X
  636. Xvoid
  637. Xleave(rv)
  638. X    int rv;
  639. X{
  640. X    if (e.type == E_TCOM && e.oenv != NULL)    /* exec'd command */
  641. X        unwind();
  642. X    runtrap(&sigtraps[0]);
  643. X    j_exit();
  644. X    exit(rv);
  645. X    /* NOTREACHED */
  646. X}
  647. X
  648. Xerror()
  649. X{
  650. X    if (flag[FERREXIT] || !flag[FTALKING])
  651. X        leave(1);
  652. X    unwind();
  653. X}
  654. X
  655. X/* return to closest error handler or shell(), exit if none found */
  656. Xunwind()
  657. X{
  658. X    while (1)
  659. X        switch (e.type) {
  660. X          case E_NONE:
  661. X            leave(1);
  662. X            /* NOTREACHED */
  663. X          case E_PARSE:
  664. X            longjmp(e.jbuf, 1);
  665. X            /* NOTREACHED */
  666. X          case E_ERRH:
  667. X            longjmp(e.jbuf, 1);
  668. X            /* NOTREACHED */
  669. X          default:
  670. X            quitenv();
  671. X            break;
  672. X        }
  673. X}
  674. X
  675. Xnewenv(type)
  676. X{
  677. X    register struct env *ep;
  678. X
  679. X    ep = (struct env *) alloc(sizeof(*ep), ATEMP);
  680. X    *ep = e;
  681. X    ainit(&e.area);
  682. X    e.type = type;
  683. X    e.oenv = ep;
  684. X    e.savefd = NULL;
  685. X    e.temps = NULL;
  686. X}
  687. X
  688. Xquitenv()
  689. X{
  690. X    register struct env *ep;
  691. X    register int fd;
  692. X
  693. X    if ((ep = e.oenv) == NULL)
  694. X        exit(exstat);    /* exit child */
  695. X    if (e.loc != ep->loc)
  696. X        popblock();
  697. X    if (e.savefd != NULL)
  698. X        for (fd = 0; fd < NUFILE; fd++)
  699. X            restfd(fd, e.savefd[fd]);
  700. X    reclaim();
  701. X    e = *ep;
  702. X}
  703. X
  704. X/* remove temp files and free ATEMP Area */
  705. Xstatic void
  706. Xreclaim()
  707. X{
  708. X    register struct temp *tp;
  709. X
  710. X    for (tp = e.temps; tp != NULL; tp = tp->next)
  711. X        remove(tp->name);
  712. X    e.temps = NULL;
  713. X    afreeall(&e.area);
  714. X}
  715. X
  716. Xvoid
  717. Xaerror(ap, msg)
  718. X    Area *ap;
  719. X    Const char *msg;
  720. X{
  721. X    errorf("alloc internal error: %s\n", msg);
  722. X}
  723. X
  724. SHAR_EOF
  725. true || echo 'restore of src/main.c failed'
  726. fi
  727. # ============= src/misc.c ==============
  728. if test -f 'src/misc.c' -a X"$1" != X"-c"; then
  729.     echo 'x - skipping src/misc.c (File already exists)'
  730. else
  731. echo 'x - extracting src/misc.c (Text)'
  732. sed 's/^X//' << 'SHAR_EOF' > 'src/misc.c' &&
  733. X/*
  734. X * Miscellaneous functions
  735. X */
  736. X
  737. Xstatic char *RCSid = "$Header: /tmp/egisin/src/RCS/misc.c,v 3.1 88/11/03 09:17:14 egisin Exp $";
  738. X
  739. X#include <stddef.h>
  740. X#include <limits.h>
  741. X#include <string.h>
  742. X#include <signal.h>
  743. X#include <errno.h>
  744. X#include <setjmp.h>
  745. X#include "sh.h"
  746. X#include "expand.h"
  747. X
  748. Xchar ctypes [UCHAR_MAX];    /* type bits for unsigned char */
  749. X
  750. X/*
  751. X * Fast character classes
  752. X */
  753. Xvoid
  754. Xsetctypes(s, t)
  755. X    register Const char *s;
  756. X    register int t;
  757. X{
  758. X    register int i;
  759. X
  760. X    if ((t&C_IFS)) {
  761. X        for (i = 0; i < UCHAR_MAX; i++)
  762. X            ctypes[i] &=~ C_IFS;
  763. X        ctypes[0] |= C_IFS; /* include \0 in C_IFS */
  764. X    }
  765. X    ctypes[(unsigned char) *s++] |= t;    /* allow leading \0 in string */
  766. X    while (*s != 0)
  767. X        ctypes[(unsigned char) *s++] |= t;
  768. X}
  769. X
  770. Xvoid
  771. Xinitctypes()
  772. X{
  773. X    register int c;
  774. X
  775. X    for (c = 'a'; c <= 'z'; c++)
  776. X        ctypes[c] |= C_ALPHA;
  777. X    for (c = 'A'; c <= 'Z'; c++)
  778. X        ctypes[c] |= C_ALPHA;
  779. X    ctypes['_'] |= C_ALPHA;
  780. X    setctypes("0123456789", C_DIGIT);
  781. X    setctypes("\0 \t\n|&;<>()", C_LEX1);
  782. X    setctypes("*@#!$-?", C_VAR1);
  783. X    setctypes("=-+?#%", C_SUBOP);
  784. X}
  785. X
  786. X/* convert unsigned long to base N string */
  787. X
  788. Xchar *
  789. Xulton(n, base)
  790. X    register unsigned long n;
  791. X    int base;
  792. X{
  793. X    register char *p;
  794. X    static char buf [20];
  795. X
  796. X    p = &buf[sizeof(buf)];
  797. X    *--p = '\0';
  798. X    do {
  799. X        *--p = "0123456789ABCDEF"[n%base];
  800. X        n /= base;
  801. X    } while (n != 0);
  802. X    return p;
  803. X}
  804. X
  805. Xchar *
  806. Xstrsave(s, ap)
  807. X    register char *s;
  808. X    Area *ap;
  809. X{
  810. X    return strcpy((char*) alloc((size_t)strlen(s)+1, ap), s);
  811. X}
  812. X
  813. Xstatic struct option {
  814. X    char *name;
  815. X    int flag;
  816. X} options[] = {
  817. X    {"allexport",    FEXPORT},
  818. X    {"bgnice",    FBGNICE},
  819. X#if EDIT
  820. X    {"emacs",    FEMACS},
  821. X#endif
  822. X    {"errexit",    FERREXIT},
  823. X    {"hashall",    FHASHALL},
  824. X    {"ignoreeof",    FIGNEOF},
  825. X    {"interactive",    FTALKING},
  826. X    {"keyword",    FKEYWORD},
  827. X    {"markdirs",    FMARKDIRS},
  828. X    {"monitor",    FMONITOR},
  829. X    {"noexec",    FNOEXEC},
  830. X    {"noglob",    FNOGLOB},
  831. X    {"nounset",    FNOUNSET},
  832. X    {"privileged",    FPRIVILEGED},
  833. X    {"stdin",    FSTDIN},
  834. X    {"trackall",    FHASHALL},
  835. X    {"verbose",    FVERBOSE},
  836. X    {"xtrace",    FXTRACE},
  837. X    {NULL,        0}
  838. X};    
  839. X
  840. X/*
  841. X * translate -o option into F* constant
  842. X */
  843. Xint
  844. Xoption(n)
  845. X    Const char *n;
  846. X{
  847. X    register struct option *op;
  848. X
  849. X    for (op = options; op->name != NULL; op++)
  850. X        if (strcmp(op->name, n) == 0)
  851. X            return op->flag;
  852. X    return 0;
  853. X}
  854. X
  855. Xchar *
  856. Xgetoptions()
  857. X{
  858. X    register int c;
  859. X    char m [26+1];
  860. X    register char *cp = m;
  861. X
  862. X    for (c = 'a'; c <= 'z'; c++)
  863. X        if (flag[FLAG(c)])
  864. X            *cp++ = (char) c;
  865. X    *cp = 0;
  866. X    return strsave(m, ATEMP);
  867. X}
  868. X
  869. Xvoid
  870. Xprintoptions()
  871. X{
  872. X    register struct option *op;
  873. X
  874. X    for (op = options; op->name != NULL; op++)
  875. X        if (flag[op->flag])
  876. X            shellf("%s ", op->name);
  877. X    shellf("\n");
  878. X}
  879. X    
  880. X/* atoi with error detection */
  881. X
  882. Xgetn(as)
  883. X    char *as;
  884. X{
  885. X    register char *s;
  886. X    register int n;
  887. X
  888. X    s = as;
  889. X    if (*s == '-')
  890. X        s++;
  891. X    for (n = 0; digit(*s); s++)
  892. X        n = (n*10) + (*s-'0');
  893. X    if (*s)
  894. X        errorf("%s: bad number\n", as);
  895. X    return (*as == '-') ? -n : n;
  896. X}
  897. X
  898. X/*
  899. X * stripped down strerror for kill and exec
  900. X */
  901. Xchar *
  902. Xstrerror(i)
  903. X    int i;
  904. X{
  905. X    switch (i) {
  906. X      case EINVAL:
  907. X        return "Invalid argument";
  908. X      case EACCES:
  909. X        return "Permission denied";
  910. X      case ESRCH:
  911. X        return "No such process";
  912. X      case EPERM:
  913. X        return "Not owner";
  914. X      case ENOENT:
  915. X        return "No such file or directory";
  916. X      case ENOTDIR:
  917. X        return "Not a directory";
  918. X      case ENOEXEC:
  919. X        return "Exec format error";
  920. X      case ENOMEM:
  921. X        return "Not enough memory";
  922. X      case E2BIG:
  923. X        return "Argument list too long";
  924. X      default:
  925. X        return "Unknown system error";
  926. X    }
  927. X}
  928. X
  929. Xxpexpand(xp)
  930. X    register XPtrV *xp;
  931. X{
  932. X    int n = XPsize(*xp);
  933. X    Void **vp;
  934. X    register Void **dvp, **svp;
  935. X
  936. X    vp = alloc(sizeofN(Void*, n*2), ATEMP);
  937. X    for (svp = xp->beg, dvp = vp; svp < xp->cur; )
  938. X        *dvp++ = *svp++;
  939. X    afree((Void*) xp->beg, ATEMP);
  940. X    xp->beg = vp;
  941. X    xp->cur = vp + n;
  942. X    xp->end = vp + n*2;
  943. X}
  944. X
  945. X/* -------- gmatch.c -------- */
  946. X
  947. X/*
  948. X * int gmatch(string, pattern)
  949. X * char *string, *pattern;
  950. X *
  951. X * Match a pattern as in sh(1).
  952. X * pattern character are prefixed with MAGIC by expand.
  953. X */
  954. X
  955. X#define    NOT    '!'    /* might use ^ */
  956. X
  957. Xstatic    char    *cclass ARGS((char *, int c));
  958. X
  959. Xint
  960. Xgmatch(s, p)
  961. X    register char *s, *p;
  962. X{
  963. X    register int sc, pc;
  964. X
  965. X    if (s == NULL || p == NULL)
  966. X        return 0;
  967. X    while ((pc = *p++) != 0) {
  968. X        sc = *s++;
  969. X        if (pc ==  MAGIC)
  970. X            switch (*p++) {
  971. X              case '[':
  972. X                if ((p = cclass(p, sc)) == NULL)
  973. X                    return (0);
  974. X                break;
  975. X
  976. X              case '?':
  977. X                if (sc == 0)
  978. X                    return (0);
  979. X                break;
  980. X
  981. X              case '*':
  982. X                s--;
  983. X                do {
  984. X                    if (*p == '\0' || gmatch(s, p))
  985. X                        return (1);
  986. X                } while (*s++ != '\0');
  987. X                return (0);
  988. X
  989. X            }
  990. X        else
  991. X            if (sc != pc)
  992. X                return 0;
  993. X    }
  994. X    return (*s == 0);
  995. X}
  996. X
  997. Xstatic char *
  998. Xcclass(p, sub)
  999. X    register char *p;
  1000. X    register int sub;
  1001. X{
  1002. X    register int c, d, not, found = 0;
  1003. X
  1004. X    if ((not = *p == NOT))
  1005. X        p++;
  1006. X    do {
  1007. X        if (*p == '\0')
  1008. X            return NULL;
  1009. X        c = *p;
  1010. X        if (p[1] == '-' && p[2] != ']') {
  1011. X            d = p[2];
  1012. X            p++;
  1013. X        } else
  1014. X            d = c;
  1015. X        if (c == sub || c <= sub && sub <= d)
  1016. X            found = 1;
  1017. X    } while (*++p != ']');
  1018. X
  1019. X    return (found != not) ? p+1 : NULL;
  1020. X}
  1021. X
  1022. X/* -------- qsort.c -------- */
  1023. X
  1024. X/*
  1025. X * quick sort of array of generic pointers to objects.
  1026. X */
  1027. X
  1028. Xvoid
  1029. Xqsortp(base, n, f)
  1030. X    Void **base;        /* base address */
  1031. X    size_t n;        /* elements */
  1032. X    int (*f)();        /* compare function */
  1033. X{
  1034. X    qsort1(base, base + n, f);
  1035. X}
  1036. X
  1037. X#define    swap2(a, b)    {\
  1038. X    register Void *t; t = *(a); *(a) = *(b); *(b) = t;\
  1039. X}
  1040. X#define    swap3(a, b, c)    {\
  1041. X    register Void *t; t = *(a); *(a) = *(c); *(c) = *(b); *(b) = t;\
  1042. X}
  1043. X
  1044. Xqsort1(base, lim, f)
  1045. X    Void **base, **lim;
  1046. X    int (*f)();
  1047. X{
  1048. X    register Void **i, **j;
  1049. X    register Void **lptr, **hptr;
  1050. X    size_t n;
  1051. X    int c;
  1052. X
  1053. X  top:
  1054. X    n = (lim - base) / 2;
  1055. X    if (n == 0)
  1056. X        return;
  1057. X    hptr = lptr = base+n;
  1058. X    i = base;
  1059. X    j = lim - 1;
  1060. X
  1061. X    for (;;) {
  1062. X        if (i < lptr) {
  1063. X            if ((c = (*f)(*i, *lptr)) == 0) {
  1064. X                lptr --;
  1065. X                swap2(i, lptr);
  1066. X                continue;
  1067. X            }
  1068. X            if (c < 0) {
  1069. X                i += 1;
  1070. X                continue;
  1071. X            }
  1072. X        }
  1073. X
  1074. X      begin:
  1075. X        if (j > hptr) {
  1076. X            if ((c = (*f)(*hptr, *j)) == 0) {
  1077. X                hptr ++;
  1078. X                swap2(hptr, j);
  1079. X                goto begin;
  1080. X            }
  1081. X            if (c > 0) {
  1082. X                if (i == lptr) {
  1083. X                    hptr ++;
  1084. X                    swap3(i, hptr, j);
  1085. X                    i = lptr += 1;
  1086. X                    goto begin;
  1087. X                }
  1088. X                swap2(i, j);
  1089. X                j -= 1;
  1090. X                i += 1;
  1091. X                continue;
  1092. X            }
  1093. X            j -= 1;
  1094. X            goto begin;
  1095. X        }
  1096. X
  1097. X        if (i == lptr) {
  1098. X            if (lptr-base >= lim-hptr) {
  1099. X                qsort1(hptr+1, lim, f);
  1100. X                lim = lptr;
  1101. X            } else {
  1102. X                qsort1(base, lptr, f);
  1103. X                base = hptr+1;
  1104. X            }
  1105. X            goto top;
  1106. X        }
  1107. X
  1108. X        lptr -= 1;
  1109. X        swap3(j, lptr, i);
  1110. X        j = hptr -= 1;
  1111. X    }
  1112. X}
  1113. X
  1114. Xint
  1115. Xxstrcmp(p1, p2)
  1116. X    Void *p1, *p2;
  1117. X{
  1118. X    return (strcmp((char *)p1, (char *)p2));
  1119. X}
  1120. X
  1121. SHAR_EOF
  1122. true || echo 'restore of src/misc.c failed'
  1123. fi
  1124. # ============= src/trap.c ==============
  1125. if test -f 'src/trap.c' -a X"$1" != X"-c"; then
  1126.     echo 'x - skipping src/trap.c (File already exists)'
  1127. else
  1128. echo 'x - extracting src/trap.c (Text)'
  1129. sed 's/^X//' << 'SHAR_EOF' > 'src/trap.c' &&
  1130. X/*
  1131. X * signal handling
  1132. X */
  1133. X
  1134. Xstatic char *RCSid = "$Header: /tmp/egisin/src/RCS/trap.c,v 3.1 88/11/03 09:18:00 egisin Exp $";
  1135. X
  1136. X#include <stddef.h>
  1137. X#include <string.h>
  1138. X#include <errno.h>
  1139. X#include <signal.h>
  1140. X#include <setjmp.h>
  1141. X#include "sh.h"
  1142. X
  1143. XTrap sigtraps [SIGNALS] = {
  1144. X    {0,    "EXIT", "Signal 0"}, /* todo: belongs in e.loc->exit */
  1145. X    {SIGHUP, "HUP", "Hangup"},
  1146. X    {SIGINT, "INT", "Interrupt"},
  1147. X    {SIGQUIT, "QUIT", "Quit"},
  1148. X    {SIGILL, "ILL", "Illegal instruction"},
  1149. X    {SIGTRAP, "TRAP", "Trace trap"},
  1150. X    {SIGIOT, "IOT", "Abort"},
  1151. X    {SIGEMT, "EMT", "EMT trap"},
  1152. X    {SIGFPE, "FPE", "Floating exception"},
  1153. X    {SIGKILL, "KILL", "Killed"},
  1154. X    {SIGBUS, "BUS", "Bus error"},
  1155. X    {SIGSEGV, "SEGV", "Memory fault"},
  1156. X    {SIGSYS, "SYS", "Bad system call"},
  1157. X    {SIGPIPE, "PIPE", "Broken pipe"},
  1158. X    {SIGALRM, "ALRM", "Alarm clock"},
  1159. X    {SIGTERM, "TERM", "Terminated"},
  1160. X#if JOBS            /* todo: need to be more portable */
  1161. X    {SIGURG, "URG", "Urgent condition"}, /* BSDism */
  1162. X    {SIGSTOP, "STOP", "Stop (signal)"},
  1163. X    {SIGTSTP, "TSTP", "Stop"},
  1164. X    {SIGCONT, "CONT", "Continue"},
  1165. X    {SIGCHLD, "CHLD", "Waiting children"},
  1166. X    {SIGTTIN, "TTIN", "Stop (tty input)"},
  1167. X    {SIGTTOU, "TTOU", "Stop (tty output)"},
  1168. X#endif
  1169. X};
  1170. X
  1171. XTrap *
  1172. Xgettrap(name)
  1173. X    char *name;
  1174. X{
  1175. X    int i;
  1176. X    register Trap *p;
  1177. X
  1178. X    if (digit(*name)) {
  1179. X        i = getn(name);
  1180. X        return (0 <= i && i < SIGNALS) ? &sigtraps[getn(name)] : NULL;
  1181. X    }
  1182. X#if 0
  1183. X    if (strcmp("ERR", name) == 0)
  1184. X        return &e.loc->err;
  1185. X    if (strcmp("EXIT", name) == 0)
  1186. X        return &e.loc->exit;
  1187. X#endif
  1188. X    for (p = sigtraps, i = SIGNALS; --i >= 0; p++)
  1189. X        if (strcmp(p->name, name) == 0)
  1190. X            return p;
  1191. X    return NULL;
  1192. X}
  1193. X
  1194. X/*
  1195. X * trap signal handler
  1196. X */
  1197. Xvoid
  1198. Xtrapsig(i)
  1199. X    int i;
  1200. X{
  1201. X    trap = sigtraps[i].set = 1;
  1202. X    if (i == SIGINT && e.type == E_PARSE)
  1203. X        /* dangerous but necessary to deal with BSD silly signals */
  1204. X        longjmp(e.jbuf, 1);
  1205. X    (void) signal(i, trapsig); /* todo: use sigact */
  1206. X}
  1207. X
  1208. X/*
  1209. X * run any pending traps
  1210. X */
  1211. Xruntraps()
  1212. X{
  1213. X    int i;
  1214. X    register Trap *p;
  1215. X
  1216. X    for (p = sigtraps, i = SIGNALS; --i >= 0; p++)
  1217. X        if (p->set)
  1218. X            runtrap(p);
  1219. X    trap = 0;
  1220. X}
  1221. X
  1222. Xruntrap(p)
  1223. X    Trap *p;
  1224. X{
  1225. X    char *trapstr;
  1226. X
  1227. X    p->set = 0;
  1228. X    if ((trapstr = p->trap) == NULL)
  1229. X        if (p->signal == SIGINT)
  1230. X            unwind();    /* return to shell() */
  1231. X        else
  1232. X            return;
  1233. X    if (p->signal == 0)    /* ??? */
  1234. X        p->trap = 0;
  1235. X    command(trapstr);
  1236. X}
  1237. X/* restore signals for children */
  1238. Xcleartraps()
  1239. X{
  1240. X    int i;
  1241. X    register Trap *p;
  1242. X
  1243. X    for (i = SIGNALS, p = sigtraps; --i >= 0; p++) {
  1244. X        p->set = 0;
  1245. X        if (p->ourtrap && signal(p->signal, SIG_IGN) != SIG_IGN)
  1246. X            (void) signal(p->signal, SIG_DFL);
  1247. X    }
  1248. X}
  1249. X
  1250. Xignoresig(i)
  1251. X    int i;
  1252. X{
  1253. X    if (signal(i, SIG_IGN) != SIG_IGN)
  1254. X        sigtraps[i].sig_dfl = 1;
  1255. X}
  1256. X
  1257. Xrestoresigs()
  1258. X{
  1259. X    int i;
  1260. X    register Trap *p;
  1261. X
  1262. X    for (p = sigtraps, i = SIGNALS; --i >= 0; p++)
  1263. X        if (p->sig_dfl) {
  1264. X            p->sig_dfl = 0;
  1265. X            (void) signal(p->signal, SIG_DFL);
  1266. X        }
  1267. X}
  1268. X
  1269. SHAR_EOF
  1270. true || echo 'restore of src/trap.c failed'
  1271. fi
  1272. # ============= src/alloc.c ==============
  1273. if test -f 'src/alloc.c' -a X"$1" != X"-c"; then
  1274.     echo 'x - skipping src/alloc.c (File already exists)'
  1275. else
  1276. echo 'x - extracting src/alloc.c (Text)'
  1277. sed 's/^X//' << 'SHAR_EOF' > 'src/alloc.c' &&
  1278. X/*
  1279. X * area-based allocation built on malloc/free
  1280. X */
  1281. X
  1282. Xstatic char *RCSid = "$Header";
  1283. X
  1284. X#include <stddef.h>
  1285. X#include <stdlib.h>
  1286. X#include <setjmp.h>
  1287. X#include "sh.h"
  1288. X
  1289. X#define    ICELLS    100        /* number of Cells in small Block */
  1290. X
  1291. Xtypedef union Cell Cell;
  1292. Xtypedef struct Block Block;
  1293. X
  1294. X/*
  1295. X * The Cells in a Block are organized as a set of objects.
  1296. X * Each object (pointed to by dp) begins with a size in (dp-1)->size,
  1297. X * followed with "size" data Cells.  Free objects are
  1298. X * linked together via dp->next.
  1299. X */
  1300. X
  1301. Xunion Cell {
  1302. X    size_t    size;
  1303. X    Cell   *next;
  1304. X    struct {int _;} junk;    /* alignment */
  1305. X};
  1306. X
  1307. Xstruct Block {
  1308. X    Block  *next;        /* list of Blocks in Area */
  1309. X    Cell   *free;        /* object free list */
  1310. X    Cell   *last;        /* &b.cell[size] */
  1311. X    Cell    cell [1];    /* [size] Cells for allocation */
  1312. X};
  1313. X
  1314. XBlock aempty = {&aempty, aempty.cell, aempty.cell};
  1315. X
  1316. X/* create empty Area */
  1317. XArea *
  1318. Xainit(ap)
  1319. X    register Area *ap;
  1320. X{
  1321. X    ap->free = &aempty;
  1322. X    return ap;
  1323. X}
  1324. X
  1325. X/* free all object in Area */
  1326. Xvoid
  1327. Xafreeall(ap)
  1328. X    register Area *ap;
  1329. X{
  1330. X    register Block *bp;
  1331. X
  1332. X    if (ap->free == NULL || ap->free == &aempty)
  1333. X        return;
  1334. X    for (bp = ap->free; ; bp = bp->next) {
  1335. X        free((Void*)bp);
  1336. X        if (bp->next == ap->free)
  1337. X            break;
  1338. X    }
  1339. X    ap->free = &aempty;
  1340. X}
  1341. X
  1342. X/* allocate object from Area */
  1343. XVoid *
  1344. Xalloc(size, ap)
  1345. X    size_t size;
  1346. X    register Area *ap;
  1347. X{
  1348. X    int cells, split;
  1349. X    register Block *bp;
  1350. X    register Cell *dp, *fp, *fpp;
  1351. X
  1352. X    if (size <= 0) {
  1353. X        aerror(ap, "allocate bad size");
  1354. X        return NULL;
  1355. X    }
  1356. X    cells = (unsigned)(size - 1) / sizeof(Cell) + 1;
  1357. X
  1358. X    /* find Cell large enough */
  1359. X    for (bp = ap->free; ; bp = bp->next) {
  1360. X        for (fpp = NULL, fp = bp->free;
  1361. X             fp != bp->last; fpp = fp, fp = fpp->next)
  1362. X            if ((fp-1)->size >= cells)
  1363. X                goto Found;
  1364. X
  1365. X        /* wrapped around Block list, create new Block */
  1366. X        if (bp == ap->free) {
  1367. X            bp = malloc(offsetof(Block, cell[ICELLS + cells]));
  1368. X            if (bp == NULL) {
  1369. X                aerror(ap, "cannot allocate");
  1370. X                return NULL;
  1371. X            }
  1372. X            if (ap->free == &aempty)
  1373. X                bp->next = bp;
  1374. X            else {
  1375. X                bp->next = ap->free->next;
  1376. X                ap->free->next = bp;
  1377. X            }
  1378. X            bp->last = bp->cell + ICELLS + cells;
  1379. X            fp = bp->free = bp->cell + 1; /* initial free list */
  1380. X            (fp-1)->size = ICELLS + cells - 1;
  1381. X            fp->next = bp->last;
  1382. X            fpp = NULL;
  1383. X            break;
  1384. X        }
  1385. X    }
  1386. X  Found:
  1387. X    ap->free = bp;
  1388. X    dp = fp;        /* allocated object */
  1389. X    split = (dp-1)->size - cells;
  1390. X    if (split < 0)
  1391. X        aerror(ap, "allocated object too small");
  1392. X    if (--split <= 0) {    /* allocate all */
  1393. X        fp = fp->next;
  1394. X    } else {        /* allocate head, free tail */
  1395. X        (fp-1)->size = cells;
  1396. X        fp += cells + 1;
  1397. X        (fp-1)->size = split;
  1398. X        fp->next = dp->next;
  1399. X    }
  1400. X    if (fpp == NULL)
  1401. X        bp->free = fp;
  1402. X    else
  1403. X        fpp->next = fp;
  1404. X    return (Void*) dp;
  1405. X}
  1406. X
  1407. X/* change size of object */
  1408. X/* todo: allow expansion */
  1409. XVoid *
  1410. Xaresize(ptr, size, ap)
  1411. X    register Void *ptr;
  1412. X    size_t size;
  1413. X    register Area *ap;
  1414. X{
  1415. X    int cells, split;
  1416. X    register Cell *dp = (Cell*)ptr;
  1417. X
  1418. X    if (size <= 0) {
  1419. X        aerror(ap, "allocate bad size");
  1420. X        return NULL;
  1421. X    }
  1422. X    cells = (unsigned)(size - 1) / sizeof(Cell) + 1;
  1423. X
  1424. X    split = (dp-1)->size - cells;
  1425. X    if (split < 0)
  1426. X        aerror(ap, "cannot resize larger");
  1427. X    if (--split <= 0)    /* cannot split */
  1428. X        ;
  1429. X    else {            /* shrink head, free tail */
  1430. X        (dp-1)->size = cells;
  1431. X        dp += cells + 1;
  1432. X        (dp-1)->size = split;
  1433. X        afree((Void*)dp, ap);
  1434. X    }
  1435. X
  1436. X    return (Void*) ptr;
  1437. X}
  1438. X
  1439. Xvoid
  1440. Xafree(ptr, ap)
  1441. X    Void *ptr;
  1442. X    register Area *ap;
  1443. X{
  1444. X    register Block *bp;
  1445. X    register Cell *fp, *fpp;
  1446. X    register Cell *dp = (Cell*)ptr;
  1447. X
  1448. X    /* find Block containing Cell */
  1449. X    for (bp = ap->free; ; bp = bp->next) {
  1450. X        if (bp->cell <= dp && dp < bp->last)
  1451. X            break;
  1452. X        if (bp->next == ap->free) {
  1453. X            aerror(ap, "freeing with invalid area");
  1454. X            return;
  1455. X        }
  1456. X    }
  1457. X
  1458. X    /* find position in free list */
  1459. X    for (fpp = NULL, fp = bp->free; fp < dp; fpp = fp, fp = fpp->next)
  1460. X        ;
  1461. X
  1462. X    if (fp == dp) {
  1463. X        aerror(ap, "freeing free object");
  1464. X        return;
  1465. X    }
  1466. X
  1467. X    /* join object with next */
  1468. X    if (dp + (dp-1)->size == fp-1) { /* adjacent */
  1469. X        (dp-1)->size += (fp-1)->size + 1;
  1470. X        dp->next = fp->next;
  1471. X    } else            /* non-adjacent */
  1472. X        dp->next = fp;
  1473. X
  1474. X    /* join previous with object */
  1475. X    if (fpp == NULL)
  1476. X        bp->free = dp;
  1477. X    else if (fpp + (fpp-1)->size == dp-1) { /* adjacent */
  1478. X        (fpp-1)->size += (dp-1)->size + 1;
  1479. X        fpp->next = dp->next;
  1480. X    } else            /* non-adjacent */
  1481. X        fpp->next = dp;
  1482. X}
  1483. X
  1484. X
  1485. X#if TEST_ALLOC
  1486. X
  1487. XArea a;
  1488. X
  1489. Xmain(int argc, char **argv) {
  1490. X    int i;
  1491. X    char *p [9];
  1492. X
  1493. X    ainit(&a);
  1494. X    for (i = 0; i < 9; i++) {
  1495. X        p[i] = alloc(124, &a);
  1496. X        printf("alloc: %x\n", p[i]);
  1497. X    }
  1498. X    for (i = 1; i < argc; i++)
  1499. X        afree(p[atoi(argv[i])], &a);
  1500. X    afreeall(&a);
  1501. X    return 0;
  1502. X}
  1503. X
  1504. Xvoid aerror(Area *ap, const char *msg) {
  1505. X    abort();
  1506. X}
  1507. X
  1508. X#endif
  1509. X
  1510. SHAR_EOF
  1511. true || echo 'restore of src/alloc.c failed'
  1512. fi
  1513. # ============= src/io.c ==============
  1514. if test -f 'src/io.c' -a X"$1" != X"-c"; then
  1515.     echo 'x - skipping src/io.c (File already exists)'
  1516. else
  1517. echo 'x - extracting src/io.c (Text)'
  1518. sed 's/^X//' << 'SHAR_EOF' > 'src/io.c' &&
  1519. X/*
  1520. X * shell buffered IO and formatted output
  1521. X */
  1522. X
  1523. Xstatic char *RCSid = "$Header: /tmp/egisin/src/RCS/io.c,v 3.3 88/11/25 10:55:52 egisin Exp $";
  1524. X
  1525. X#include <stddef.h>
  1526. X#include <stdlib.h>
  1527. X#include <stdio.h>
  1528. X#include <errno.h>
  1529. X#include <unistd.h>
  1530. X#include <fcntl.h>
  1531. X#include <signal.h>
  1532. X#include <setjmp.h>
  1533. X#if __STDC__
  1534. X#include <stdarg.h>
  1535. X#else
  1536. X#include <varargs.h>
  1537. X#endif
  1538. X#include "sh.h"
  1539. X
  1540. X#if 0
  1541. X/* fputc with ^ escaping */
  1542. Xstatic void
  1543. Xfzotc(c, f)
  1544. X    register int c;
  1545. X    register FILE *f;
  1546. X{
  1547. X    if ((c&0x60) == 0) {        /* C0|C1 */
  1548. X        putc((c&0x80) ? '$' : '^', f);
  1549. X        putc((c&0x7F|0x40), f);
  1550. X    } else if ((c&0x7F) == 0x7F) {    /* DEL */
  1551. X        putc((c&0x80) ? '$' : '^', f);
  1552. X        putc('?', f);
  1553. X    } else
  1554. X        putc(c, f);
  1555. X}
  1556. X#endif
  1557. X
  1558. X/*
  1559. X * formatted output functions
  1560. X */
  1561. X
  1562. X/* shellf(...); error() */
  1563. Xint
  1564. X#if __STDC__
  1565. Xerrorf(Const char *fmt, ...) {
  1566. X#else
  1567. Xerrorf(va_alist) va_dcl
  1568. X{
  1569. X    char *fmt;
  1570. X#endif
  1571. X    va_list va;
  1572. X
  1573. X#if __STDC__
  1574. X    va_start(va, fmt);
  1575. X#else
  1576. X    va_start(va);
  1577. X    fmt = va_arg(va, char *);
  1578. X#endif
  1579. X    vfprintf(shlout, fmt, va);
  1580. X    va_end(va);
  1581. X    /*fflush(shlout);*/
  1582. X    error();
  1583. X}
  1584. X
  1585. X/* printf to shlout (stderr) */
  1586. Xint
  1587. X#if __STDC__
  1588. Xshellf(Const char *fmt, ...) {
  1589. X#else
  1590. Xshellf(va_alist) va_dcl
  1591. X{
  1592. X    char *fmt;
  1593. X#endif
  1594. X    va_list va;
  1595. X
  1596. X#if __STDC__
  1597. X    va_start(va, fmt);
  1598. X#else
  1599. X    va_start(va);
  1600. X    fmt = va_arg(va, char *);
  1601. X#endif
  1602. X    vfprintf(shlout, fmt, va);
  1603. X    va_end(va);
  1604. X    return 0;
  1605. X}
  1606. X
  1607. X/*
  1608. X * We have a stdio stream for any open shell file descriptors (0-9)
  1609. X */
  1610. XFILE *    shf [NUFILE];        /* map shell fd to FILE * */
  1611. X
  1612. X/* open stream for shell fd */
  1613. Xvoid
  1614. Xfopenshf(fd)
  1615. X    int fd;
  1616. X{
  1617. X    if (shf[fd] != NULL)
  1618. X        return;
  1619. X    if (fd <= 2)
  1620. X        _iob[fd]._flag = 0; /* re-use stdin, stdout, stderr */
  1621. X    shf[fd] = fdopen(fd, "r+");
  1622. X    if (shf[fd] == NULL)
  1623. X        return;
  1624. X    setvbuf(shf[fd], (char*)NULL, _IOFBF, (size_t)BUFSIZ);
  1625. X}
  1626. X
  1627. X/* flush stream assoc with fd */
  1628. X/* this must invalidate input and output buffers */
  1629. Xvoid
  1630. Xflushshf(fd)
  1631. X    int fd;
  1632. X{
  1633. X    if (shf[fd] != NULL) {
  1634. X        fseek(shf[fd], 0L, 1); /* V7 derived */
  1635. X        fflush(shf[fd]);    /* standard C */
  1636. X    }
  1637. X}
  1638. X
  1639. X/*
  1640. X * move fd from user space (0<=fd<10) to shell space (fd>=10)
  1641. X */
  1642. Xint
  1643. Xsavefd(fd)
  1644. X    int fd;
  1645. X{
  1646. X    int nfd;
  1647. X
  1648. X    if (fd < FDBASE) {
  1649. X        flushshf(fd);
  1650. X        nfd = fcntl(fd, F_DUPFD, FDBASE);
  1651. X        if (nfd < 0)
  1652. X            if (errno == EBADF)
  1653. X                return -1;
  1654. X            else
  1655. X                errorf("too many files open in shell\n");
  1656. X        (void) fcntl(nfd, F_SETFD, FD_CLEXEC);
  1657. X        close(fd);
  1658. X    } else
  1659. X        nfd = fd;
  1660. X    return nfd;
  1661. X}
  1662. X
  1663. Xvoid
  1664. Xrestfd(fd, ofd)
  1665. X    int fd, ofd;
  1666. X{
  1667. X    if (ofd == 0)        /* not saved (e.savefd) */
  1668. X        return;
  1669. X    flushshf(fd);
  1670. X    close(fd);
  1671. X    if (ofd < 0)        /* original fd closed */
  1672. X        return;
  1673. X    (void) fcntl(ofd, F_DUPFD, fd);
  1674. X    close(ofd);
  1675. X}
  1676. X
  1677. Xvoid
  1678. Xopenpipe(pv)
  1679. X    register int *pv;
  1680. X{
  1681. X    if (pipe(pv) < 0)
  1682. X        errorf("can't create pipe - try again\n");
  1683. X    pv[0] = savefd(pv[0]);
  1684. X    pv[1] = savefd(pv[1]);
  1685. X}
  1686. X
  1687. Xvoid
  1688. Xclosepipe(pv)
  1689. X    register int *pv;
  1690. X{
  1691. X    close(pv[0]);
  1692. X    close(pv[1]);
  1693. X}
  1694. X
  1695. X/*
  1696. X * temporary files
  1697. X */
  1698. X
  1699. Xstruct temp *
  1700. Xmaketemp(ap)
  1701. X    Area *ap;
  1702. X{
  1703. X    register struct temp *tp;
  1704. X    static unsigned int inc = 0;
  1705. X    char path [PATH];
  1706. X
  1707. X    sprintf(path, "/tmp/sh%05u%02u", (unsigned)getpid(), inc++);
  1708. X    /* we could create the thing now with 600 mode */
  1709. X    tp = (struct temp *) alloc(sizeof(struct temp), ap);
  1710. X    tp->next = NULL;
  1711. X    tp->name = strsave(path, ap);
  1712. X    return tp;
  1713. X}
  1714. SHAR_EOF
  1715. true || echo 'restore of src/io.c failed'
  1716. fi
  1717. # ============= src/syn.c ==============
  1718. if test -f 'src/syn.c' -a X"$1" != X"-c"; then
  1719.     echo 'x - skipping src/syn.c (File already exists)'
  1720. else
  1721. echo 'x - extracting src/syn.c (Text)'
  1722. sed 's/^X//' << 'SHAR_EOF' > 'src/syn.c' &&
  1723. X/*
  1724. X * shell parser (C version)
  1725. X */
  1726. X
  1727. Xstatic char *RCSid = "$Header: /tmp/egisin/src/RCS/syn.c,v 3.2 88/12/17 21:18:59 egisin Exp $";
  1728. X
  1729. X#include <stddef.h>
  1730. X#include <stdio.h>
  1731. X#include <string.h>
  1732. X#include <errno.h>
  1733. X#include <setjmp.h>
  1734. X#include "sh.h"
  1735. X#include "lex.h"
  1736. X#include "tree.h"
  1737. X#include "table.h"
  1738. X#include "expand.h"
  1739. X
  1740. Xstatic    void    zzerr();
  1741. Xstatic    struct    op *block(), *newtp();
  1742. Xstatic    struct    op *pipeline(), *andor(), *command();
  1743. Xstatic    struct    op *nested(), *c_list();
  1744. Xstatic    struct    op *dogroup(), *thenpart(), *casepart(), *caselist();
  1745. Xstatic    struct    op *elsepart();
  1746. Xstatic    char  **wordlist();
  1747. Xstatic    void    musthave();
  1748. Xstatic    struct ioword *synio(), *io();
  1749. X
  1750. Xstatic    struct    op    *outtree; /* yyparse output */
  1751. X
  1752. Xstatic    int    reject;        /* token(cf) gets symbol again */
  1753. Xstatic    int    symbol;        /* yylex value */
  1754. X
  1755. X#define    REJECT    (reject = 1)
  1756. X#define    ACCEPT    (reject = 0)
  1757. X#define    token(cf) \
  1758. X    ((reject) ? (ACCEPT, symbol) : (symbol = yylex(cf)))
  1759. X#define    tpeek(cf) \
  1760. X    ((reject) ? (symbol) : (REJECT, symbol = yylex(cf)))
  1761. X
  1762. Xint
  1763. Xyyparse()
  1764. X{
  1765. X    ACCEPT;
  1766. X    yynerrs = 0;
  1767. X    if ((tpeek(KEYWORD|ALIAS)) == 0) { /* EOF */
  1768. X        outtree = newtp(TEOF);
  1769. X        return 0;
  1770. X    }
  1771. X    outtree = c_list();
  1772. X    musthave('\n', 0);
  1773. X    return (yynerrs != 0);
  1774. X}
  1775. X
  1776. Xstatic struct op *
  1777. Xpipeline(cf)
  1778. X    int cf;
  1779. X{
  1780. X    register struct op *t, *p, *tl = NULL;
  1781. X    register int c;
  1782. X
  1783. X    t = command(cf);
  1784. X    if (t != NULL) {
  1785. X        while ((c = token(0)) == '|') {
  1786. X            if ((p = command(CONTIN)) == NULL)
  1787. X                SYNTAXERR;
  1788. X            if (tl == NULL)
  1789. X                t = tl = block(TPIPE, t, p, NOWORDS);
  1790. X            else
  1791. X                tl = tl->right = block(TPIPE, tl->right, p, NOWORDS);
  1792. X            /*t = block(TPIPE, t, p, NOWORDS);*/
  1793. X        }
  1794. X        REJECT;
  1795. X    }
  1796. X    return (t);
  1797. X}
  1798. X
  1799. Xstatic struct op *
  1800. Xandor()
  1801. X{
  1802. X    register struct op *t, *p;
  1803. X    register int c;
  1804. X
  1805. X    t = pipeline(0);
  1806. X    if (t != NULL) {
  1807. X        while ((c = token(0)) == LOGAND || c == LOGOR) {
  1808. X            if ((p = pipeline(CONTIN)) == NULL)
  1809. X                SYNTAXERR;
  1810. X            t = block(c == LOGAND? TAND: TOR, t, p, NOWORDS);
  1811. X        }
  1812. X        REJECT;
  1813. X    }
  1814. X    return (t);
  1815. X}
  1816. X
  1817. Xstatic struct op *
  1818. Xc_list()
  1819. X{
  1820. X    register struct op *t, *p, *tl = NULL;
  1821. X    register int c;
  1822. X
  1823. X    t = andor();
  1824. X    if (t != NULL) {
  1825. X        while ((c = token(0)) == ';' || c == '&' ||
  1826. X               multiline && c == '\n') {
  1827. X            if (c == '&')
  1828. X                t = block(TASYNC, t, NOBLOCK, NOWORDS);
  1829. X            if ((p = andor()) == NULL)
  1830. X                return (t);
  1831. X            if (tl == NULL)
  1832. X                t = tl = block(TLIST, t, p, NOWORDS);
  1833. X            else
  1834. X                tl = tl->right = block(TLIST, tl->right, p, NOWORDS);
  1835. X        }
  1836. X        REJECT;
  1837. X    }
  1838. X    return (t);
  1839. X}
  1840. X
  1841. Xstatic struct ioword *
  1842. Xsynio(cf)
  1843. X    int cf;
  1844. X{
  1845. X    register struct ioword *iop;
  1846. X
  1847. X    if (tpeek(cf) != REDIR)
  1848. X        return NULL;
  1849. X    ACCEPT;
  1850. X    iop = yylval.iop;
  1851. X    musthave(LWORD, 0);
  1852. X    iop->name = yylval.cp;
  1853. X    if ((iop->flag&IOTYPE) == IOHERE) {
  1854. X        if (*ident != 0) /* unquoted */
  1855. X            iop->flag |= IOEVAL;
  1856. X        if (herep >= &heres[HERES])
  1857. X            errorf("too many <<'s\n");
  1858. X        *herep++ = iop;
  1859. X    }
  1860. X    return iop;
  1861. X}
  1862. X
  1863. Xstatic void
  1864. Xmusthave(c, cf)
  1865. X    int c, cf;
  1866. X{
  1867. X    if ((token(cf)) != c)
  1868. X        SYNTAXERR;
  1869. X}
  1870. X
  1871. Xstatic struct op *
  1872. Xnested(type, mark)
  1873. X    int type, mark;
  1874. X{
  1875. X    register struct op *t;
  1876. X
  1877. X    multiline++;
  1878. X    t = c_list();
  1879. X    musthave(mark, KEYWORD);
  1880. X    multiline--;
  1881. X    return (block(type, t, NOBLOCK, NOWORDS));
  1882. X}
  1883. X
  1884. Xstatic struct op *
  1885. Xcommand(cf)
  1886. X    int cf;
  1887. X{
  1888. X    register struct op *t;
  1889. X    register int c, iopn = 0;
  1890. X    struct ioword *iop, **iops;
  1891. X    XPtrV args, vars;
  1892. X
  1893. X    iops = (struct ioword **) alloc(sizeofN(struct ioword *, NUFILE+1), ATEMP);
  1894. X    XPinit(args, 16);
  1895. X    XPinit(vars, 16);
  1896. X
  1897. X    if (multiline)
  1898. X        cf = CONTIN;
  1899. X    cf |= KEYWORD|ALIAS;
  1900. X
  1901. X    while ((iop = synio(cf)) != NULL) {
  1902. X        if (iopn >= NUFILE)
  1903. X            yyerror("too many redirections");
  1904. X        iops[iopn++] = iop;
  1905. X        cf &=~ CONTIN;
  1906. X    }
  1907. X
  1908. X    switch (c = token(cf)) {
  1909. X      case 0:
  1910. X        yyerror("unexpected EOF");
  1911. X        return NULL;
  1912. X
  1913. X      default:
  1914. X        REJECT;
  1915. X        if (iopn == 0)
  1916. X            return NULL; /* empty line */
  1917. X        t = newtp(TCOM);
  1918. X        break;
  1919. X
  1920. X      case LWORD:
  1921. X        REJECT;
  1922. X        t = newtp(TCOM);
  1923. X        while (1)
  1924. X            switch (tpeek(0)) {
  1925. X              case REDIR:
  1926. X                if (iopn >= NUFILE)
  1927. X                    yyerror("too many redirections");
  1928. X                iops[iopn++] = synio(0);
  1929. X                break;
  1930. X
  1931. X              case LWORD:
  1932. X                ACCEPT;
  1933. X                if ((XPsize(args) == 0 || flag[FKEYWORD])
  1934. X                    && strchr(ident+1, '='))
  1935. X                    {XPput(vars, yylval.cp);}
  1936. X                else
  1937. X                    {XPput(args, yylval.cp);}
  1938. X                break;
  1939. X
  1940. X              case MPAREN:
  1941. X                ACCEPT;
  1942. X                if (XPsize(args) != 1)
  1943. X                    SYNTAXERR;
  1944. X                if (*ident == 0)
  1945. X                    yyerror("invalid function name\n");
  1946. X                t = newtp(TFUNCT);
  1947. X                t->str = strsave(ident, ATEMP);
  1948. X                musthave('{', CONTIN|KEYWORD);
  1949. X                t->left = nested(TBRACE, '}');
  1950. X                return t;
  1951. X
  1952. X              default:
  1953. X                goto Leave;
  1954. X            }
  1955. X      Leave:
  1956. X        break;
  1957. X
  1958. X      case '(':
  1959. X        t = nested(TPAREN, ')');
  1960. X        break;
  1961. X
  1962. X      case '{':
  1963. X        t = nested(TBRACE, '}');
  1964. X        break;
  1965. X
  1966. X      case FOR:
  1967. X        t = newtp(TFOR);
  1968. X        musthave(LWORD, 0);
  1969. X        t->str = strsave(ident, ATEMP);
  1970. X        multiline++;
  1971. X        t->vars = wordlist();
  1972. X        t->left = dogroup(0);
  1973. X        multiline--;
  1974. X        break;
  1975. X
  1976. X      case WHILE:
  1977. X      case UNTIL:
  1978. X        multiline++;
  1979. X        t = newtp((c == WHILE) ? TWHILE: TUNTIL);
  1980. X        t->left = c_list();
  1981. X        t->right = dogroup(1);
  1982. X        multiline--;
  1983. X        break;
  1984. X
  1985. X      case CASE:
  1986. X        t = newtp(TCASE);
  1987. X        musthave(LWORD, 0);
  1988. X        t->str = yylval.cp;
  1989. X        multiline++;
  1990. X        musthave(IN, KEYWORD|CONTIN);
  1991. X        t->left = caselist();
  1992. X        musthave(ESAC, KEYWORD);
  1993. X        multiline--;
  1994. X        break;
  1995. X
  1996. X      case IF:
  1997. X        multiline++;
  1998. X        t = newtp(TIF);
  1999. X        t->left = c_list();
  2000. X        t->right = thenpart();
  2001. X        musthave(FI, KEYWORD);
  2002. X        multiline--;
  2003. X        break;
  2004. X
  2005. X      case TIME:
  2006. X        t = pipeline(CONTIN);
  2007. X        t = block(TTIME, t, NOBLOCK, NOWORDS);
  2008. X        break;
  2009. X
  2010. X      case FUNCTION:
  2011. X        t = newtp(TFUNCT);
  2012. X        musthave(LWORD, 0);
  2013. X        t->str = strsave(ident, ATEMP);
  2014. X        musthave('{', CONTIN|KEYWORD);
  2015. X        t->left = nested(TBRACE, '}');
  2016. X        break;
  2017. X    }
  2018. X
  2019. X    while ((iop = synio(0)) != NULL) {
  2020. X        if (iopn >= NUFILE)
  2021. X            yyerror("too many redirections");
  2022. X        iops[iopn++] = iop;
  2023. X    }
  2024. X
  2025. X    if (iopn == 0) {
  2026. X        afree((Void*) iops, ATEMP);
  2027. X        t->ioact = NULL;
  2028. X    } else {
  2029. X        iops[iopn++] = NULL;
  2030. X        aresize((Void*) iops, sizeofN(struct ioword *, iopn), ATEMP);
  2031. X        t->ioact = iops;
  2032. X    }
  2033. X
  2034. X    if (t->type == TCOM) {
  2035. X        XPput(args, NULL);
  2036. X        t->args = (char **) XPclose(args);
  2037. X        XPput(vars, NULL);
  2038. X        t->vars = (char **) XPclose(vars);
  2039. X    } else {
  2040. X        XPfree(args);
  2041. X        XPfree(vars);
  2042. X    }
  2043. X
  2044. X    return t;
  2045. X}
  2046. X
  2047. Xstatic struct op *
  2048. Xdogroup(onlydone)
  2049. X    int onlydone;
  2050. X{
  2051. X    register int c;
  2052. X    register struct op *list;
  2053. X
  2054. X    c = token(CONTIN|KEYWORD);
  2055. X    if (c == DONE && onlydone)
  2056. X        return NULL;
  2057. X    if (c != DO)
  2058. X        SYNTAXERR;
  2059. X    list = c_list();
  2060. X    musthave(DONE, KEYWORD);
  2061. X    return list;
  2062. X}
  2063. X
  2064. Xstatic struct op *
  2065. Xthenpart()
  2066. X{
  2067. X    register int c;
  2068. X    register struct op *t;
  2069. X
  2070. X    if ((c = token(0)) != THEN) {
  2071. X        REJECT;
  2072. X        return NULL;
  2073. X    }
  2074. X    t = newtp(0);
  2075. X    t->left = c_list();
  2076. X    if (t->left == NULL)
  2077. X        SYNTAXERR;
  2078. X    t->right = elsepart();
  2079. X    return (t);
  2080. X}
  2081. X
  2082. Xstatic struct op *
  2083. Xelsepart()
  2084. X{
  2085. X    register int c;
  2086. X    register struct op *t;
  2087. X
  2088. X    switch (c = token(0)) {
  2089. X      case ELSE:
  2090. X        if ((t = c_list()) == NULL)
  2091. X            SYNTAXERR;
  2092. X        return (t);
  2093. X
  2094. X      case ELIF:
  2095. X        t = newtp(TELIF);
  2096. X        t->left = c_list();
  2097. X        t->right = thenpart();
  2098. X        return (t);
  2099. X
  2100. X      default:
  2101. X        REJECT;
  2102. X        return NULL;
  2103. X    }
  2104. X}
  2105. X
  2106. Xstatic struct op *
  2107. Xcaselist()
  2108. X{
  2109. X    register struct op *t, *tl;
  2110. X
  2111. X    t = tl = NULL;
  2112. X    while ((tpeek(CONTIN|KEYWORD)) != ESAC) {
  2113. X        struct op *tc = casepart();
  2114. X        if (tl == NULL)
  2115. X            t = tl = tc, tl->right = NULL;
  2116. X        else
  2117. X            tl->right = tc, tl = tc;
  2118. X    }
  2119. X    return (t);
  2120. X}
  2121. X
  2122. Xstatic struct op *
  2123. Xcasepart()
  2124. X{
  2125. X    register struct op *t;
  2126. X    register int c, cf;
  2127. X    XPtrV ptns;
  2128. X
  2129. X    XPinit(ptns, 16);
  2130. X    t = newtp(TPAT);
  2131. X    cf = CONTIN|KEYWORD;
  2132. X    c = token(cf);
  2133. X    if (c != '(')
  2134. X        REJECT;
  2135. X    else
  2136. X        cf = 0;
  2137. X    do {
  2138. X        musthave(LWORD, cf);
  2139. X        XPput(ptns, yylval.cp);
  2140. X        cf = 0;
  2141. X    } while ((c = token(0)) == '|');
  2142. X    REJECT;
  2143. X    XPput(ptns, NULL);
  2144. X    t->vars = (char **) XPclose(ptns);
  2145. X    musthave(')', 0);
  2146. X
  2147. X    t->left = c_list();
  2148. X    if ((tpeek(CONTIN|KEYWORD)) != ESAC)
  2149. X        musthave(BREAK, CONTIN|KEYWORD);
  2150. X    return (t);
  2151. X}
  2152. X
  2153. Xstatic char **
  2154. Xwordlist()
  2155. X{
  2156. X    register int c;
  2157. X    XPtrV args;
  2158. X
  2159. X    XPinit(args, 16);
  2160. X    if ((c = token(CONTIN|KEYWORD)) != IN) {
  2161. X        REJECT;
  2162. X        return NULL;
  2163. X    }
  2164. X    while ((c = token(0)) == LWORD)
  2165. X        XPput(args, yylval.cp);
  2166. X    if (c != '\n' && c != ';')
  2167. X        SYNTAXERR;
  2168. X    if (XPsize(args) == 0) {
  2169. X        XPfree(args);
  2170. X        return NULL;
  2171. X    } else {
  2172. X        XPput(args, NULL);
  2173. X        return (char **) XPclose(args);
  2174. X    }
  2175. X}
  2176. X
  2177. X/*
  2178. X * supporting functions
  2179. X */
  2180. X
  2181. Xstatic struct op *
  2182. Xblock(type, t1, t2, wp)
  2183. X    struct op *t1, *t2;
  2184. X    char **wp;
  2185. X{
  2186. X    register struct op *t;
  2187. X
  2188. X    t = newtp(type);
  2189. X    t->left = t1;
  2190. X    t->right = t2;
  2191. X    t->vars = wp;
  2192. X    return (t);
  2193. X}
  2194. X
  2195. XConst    struct res {
  2196. X    char    *name;
  2197. X    int    val;
  2198. X} restab[] = {
  2199. X    "for",        FOR,
  2200. X    "case",        CASE,
  2201. X    "esac",        ESAC,
  2202. X    "while",    WHILE,
  2203. X    "do",        DO,
  2204. X    "done",        DONE,
  2205. X    "if",        IF,
  2206. X    "in",        IN,
  2207. X    "then",        THEN,
  2208. X    "else",        ELSE,
  2209. X    "elif",        ELIF,
  2210. X    "until",    UNTIL,
  2211. X    "fi",        FI,
  2212. X    "function",    FUNCTION,
  2213. X    "time",        TIME,
  2214. X    "{",        '{',
  2215. X    "}",        '}',
  2216. X    0
  2217. X};
  2218. X
  2219. Xkeywords()
  2220. X{
  2221. X    register struct res Const *rp;
  2222. X    register struct tbl *p;
  2223. X
  2224. X    for (rp = restab; rp->name; rp++) {
  2225. X        p = tenter(&lexicals, rp->name, hash(rp->name));
  2226. X        p->flag |= DEFINED|ISSET;
  2227. X        p->type = CKEYWD;
  2228. X        p->val.i = rp->val;
  2229. X    }
  2230. X}
  2231. X
  2232. Xstatic struct op *
  2233. Xnewtp(type)
  2234. X    int type;
  2235. X{
  2236. X    register struct op *t;
  2237. X
  2238. X    t = (struct op *) alloc(sizeof(*t), ATEMP);
  2239. X    t->type = type;
  2240. X    t->args = t->vars = NULL;
  2241. X    t->ioact = NULL;
  2242. X    t->left = t->right = NULL;
  2243. X    t->str = NULL;
  2244. X    return (t);
  2245. X}
  2246. X
  2247. Xstatic void
  2248. Xzzerr()
  2249. X{
  2250. X    yyerror("syntax error");
  2251. X}
  2252. X
  2253. Xstruct op *
  2254. Xcompile(s)
  2255. X    Source *s;
  2256. X{
  2257. X    yynerrs = 0;
  2258. X    multiline = 0;
  2259. X    herep = heres;
  2260. X    source = s;
  2261. X    if (yyparse())
  2262. X        unwind();
  2263. X    if (s->type == STTY || s->type == SFILE)
  2264. X        s->str = null;    /* line is not preserved */
  2265. X    return outtree;
  2266. X}
  2267. X
  2268. SHAR_EOF
  2269. true || echo 'restore of src/syn.c failed'
  2270. fi
  2271. true || echo 'restore of src/lex.c failed'
  2272. echo End of part 2, continue with part 3
  2273. exit 0
  2274.