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

  1. From: pfalstad@phoenix.Princeton.EDU (Paul John Falstad)
  2. Newsgroups: alt.sources
  3. Subject: zsh - ksh/tcsh-like shell (part 4 of 8)
  4. Message-ID: <4745@idunno.Princeton.EDU>
  5. Date: 14 Dec 90 23:31:22 GMT
  6.  
  7. ---cut here---cut here---cut here---
  8. -                case 'M':
  9. -                    stradd(&bp,hostM);
  10. -                    break;
  11. -                case 'm':
  12. -                    stradd(&bp,hostm);
  13. -                    break;
  14. -                case 'S':
  15. -                    if (tgetstr("so",&bp))
  16. -                        bp--;
  17. -                    break;
  18. -                case 's':
  19. -                    if (tgetstr("se",&bp))
  20. -                        bp--;
  21. -                    break;
  22. -                case 'B':
  23. -                    if (tgetstr("md",&bp))
  24. -                        bp--;
  25. -                    break;
  26. -                case 'b':
  27. -                    if (tgetstr("me",&bp))
  28. -                        bp--;
  29. -                    break;
  30. -                case 'U':
  31. -                    if (tgetstr("us",&bp))
  32. -                        bp--;
  33. -                    break;
  34. -                case 'u':
  35. -                    if (tgetstr("ue",&bp))
  36. -                        bp--;
  37. -                    break;
  38. -                case 't':
  39. -                case '@':
  40. -                    timet = time(NULL);
  41. -                    tm = localtime(&timet);
  42. -                    strftime(bp,16,"%l:%M%p",tm);
  43. -                    if (*bp == ' ')
  44. -                        chuck(bp);
  45. -                    bp += strlen(bp);
  46. -                    break;
  47. -                case 'T':
  48. -                    timet = time(NULL);
  49. -                    tm = localtime(&timet);
  50. -                    strftime(bp,16,"%k:%M",tm);
  51. -                    bp += strlen(bp);
  52. -                    break;
  53. -                case '*':
  54. -                    timet = time(NULL);
  55. -                    tm = localtime(&timet);
  56. -                    strftime(bp,16,"%k:%M:%S",tm);
  57. -                    bp += strlen(bp);
  58. -                    break;
  59. -                case 'n':
  60. -                    stradd(&bp,username);
  61. -                    break;
  62. -                case 'w':
  63. -                    timet = time(NULL);
  64. -                    tm = localtime(&timet);
  65. -                    strftime(bp,16,"%a %e",tm);
  66. -                    bp += strlen(bp);
  67. -                    break;
  68. -                case 'W':
  69. -                    timet = time(NULL);
  70. -                    tm = localtime(&timet);
  71. -                    strftime(bp,16,"%m/%d/%y",tm);
  72. -                    bp += strlen(bp);
  73. -                    break;
  74. -                case 'D':
  75. -                    timet = time(NULL);
  76. -                    tm = localtime(&timet);
  77. -                    strftime(bp,16,"%y-%m-%d",tm);
  78. -                    bp += strlen(bp);
  79. -                    break;
  80. -                case 'l':
  81. -                    if (ss = ttyname(SHTTY))
  82. -                        stradd(&bp,ss+8);
  83. -                    else
  84. -                        stradd(&bp,"(none)");
  85. -                    break;
  86. -                case '%':
  87. -                    *bp++ = '%';
  88. -                    break;
  89. -                case '#':
  90. -                    *bp++ = (geteuid()) ? '%' : '#';
  91. -                    break;
  92. -                default:
  93. -                    *bp++ = '%';
  94. -                    *bp++ = *fm;
  95. -                    break;
  96. -                }
  97. -        else    
  98. -            *bp++ = *fm;
  99. -        }
  100. -    *bp = '\0';
  101. -    return buf;
  102. -}
  103. -
  104. -void herrflush(void)
  105. -{
  106. -    if (strin)
  107. -        hflush();
  108. -    else while (lastc != '\n' && lastc != HERR)
  109. -        hgetch();
  110. -    if (magic)
  111. -        putc('\n',stderr);
  112. -}
  113. -
  114. -/* read an arbitrary amount of data into a buffer until stop is found */
  115. -
  116. -char *hdynread(char stop)
  117. -{
  118. -int bsiz = 256,ct = 0,c;
  119. -char *buf = zalloc(bsiz),*ptr;
  120. -    ptr = buf;
  121. -    while ((c = hgetch()) != stop && c != '\n')
  122. -        {
  123. -        if (c == '\\')
  124. -            c = hgetch();
  125. -        *ptr++ = c;
  126. -        if (++ct == bsiz)
  127. -            {
  128. -            buf = realloc(buf,bsiz *= 2);
  129. -            ptr = buf+ct;
  130. -            }
  131. -        }
  132. -    *ptr = 0;
  133. -    if (c == '\n')
  134. -        {
  135. -        hungetch('\n');
  136. -        zerr("delimiter expected");
  137. -        errflag = 1;
  138. -        free(buf);
  139. -        return NULL;
  140. -        }
  141. -    return buf;
  142. -}
  143. -char *hdynread2(char stop)
  144. -{
  145. -int bsiz = 256,ct = 0,c;
  146. -char *buf = zalloc(bsiz),*ptr;
  147. -    ptr = buf;
  148. -    while ((c = hgetch()) != stop && c != '\n')
  149. -        {
  150. -        if (c == '\n')
  151. -            {
  152. -            hungetch(c);
  153. -            break;
  154. -            }
  155. -        if (c == '\\')
  156. -            if ((c = hgetch()) == '&')
  157. -                c = '&';
  158. -        *ptr++ = c;
  159. -        if (++ct == bsiz)
  160. -            {
  161. -            buf = realloc(buf,bsiz *= 2);
  162. -            ptr = buf+ct;
  163. -            }
  164. -        }
  165. -    *ptr = 0;
  166. -    if (c == '\n')
  167. -        hungetch('\n');
  168. -    return buf;
  169. -}
  170. -
  171. -/* set cbreak mode, or the equivalent */
  172. -
  173. -void setcbreak(void)
  174. -{
  175. -struct ttyinfo ti;
  176. -
  177. -    ti = shttyinfo;
  178. -#ifdef TERMIOS
  179. -    ti.termios.c_lflag &= ~ICANON;
  180. -    ti.termios.c_cc[VMIN] = 1;
  181. -    ti.termios.c_cc[VTIME] = 0;
  182. -#else
  183. -    ti.sgttyb.sg_flags |= CBREAK;
  184. -#endif
  185. -    settyinfo(&ti);
  186. -}
  187. -
  188. -int getlineleng(void)
  189. -{
  190. -int z;
  191. -
  192. -    z = shttyinfo.winsize.ws_col;
  193. -    return (z) ? z : 80;
  194. -}
  195. -
  196. -void unsetcbreak(void)
  197. -{
  198. -    settyinfo(&shttyinfo);
  199. -}
  200. -
  201. -/* give the tty to some process */
  202. -
  203. -void attachtty(long pgrp)
  204. -{
  205. -static int ep = 0;
  206. -
  207. -    if (jobbing)
  208. -#ifdef BUGGY_GCC
  209. -        if (SHTTY != -1 && ioctl(SHTTY,(0x80000000|((sizeof(int)&0xff)<<16)|
  210. -            ('t'<<8)|118),&pgrp) == -1 && !ep)
  211. -#else
  212. -        if (SHTTY != -1 && ioctl(SHTTY,TIOCSPGRP,&pgrp) == -1 && !ep)
  213. -#endif
  214. -            {
  215. -            zerr("can't set tty pgrp: %e",errno);
  216. -            opts[MONITOR] = OPT_UNSET;
  217. -            ep =1;
  218. -            }
  219. -}
  220. -
  221. End of hist.c
  222. echo hist.pro 1>&2
  223. sed 's/^-//' >hist.pro <<'End of hist.pro'
  224. -void hwaddc(int c);
  225. -int hgetc(void);
  226. -void strinbeg(void);
  227. -void strinend(void);
  228. -int stuff(char *fn);
  229. -int hgetch(void);
  230. -void hungetch(int c);
  231. -void hungetc(int c);
  232. -void hflush(void);
  233. -void hungets(char *str);
  234. -void hbegin(void);
  235. -void inittty(void);
  236. -int hend(void);
  237. -void remhist(void);
  238. -void hwbegin(void);
  239. -char *hwadd(void);
  240. -int getargspec(int argc,int marg);
  241. -int hconsearch(char *str,int *marg);
  242. -int hcomsearch(char *str);
  243. -int apply1(int gflag,int (*func)(void **),table list);
  244. -int remtpath(void **junkptr);
  245. -int remtext(void **junkptr);
  246. -int rembutext(void **junkptr);
  247. -int remlpaths(void **junkptr);
  248. -int subst(int gbal,table slist,char *ptr1,char *ptr2);
  249. -int subststr(void **strptr,char *in,char *out,int gbal);
  250. -char *convamps(char *out,char *in);
  251. -char *makehlist(table tab,int freeit);
  252. -table quietgetevent(int ev);
  253. -table getevent(int ev);
  254. -int getargc(table tab);
  255. -table getargs(table elist,int arg1,int arg2);
  256. -int quote(void **tr);
  257. -int quotebreak(void **tr);
  258. -void stradd(char **p,char *d);
  259. -char *putprompt(char *fm);
  260. -void herrflush(void);
  261. -char *hdynread(char stop);
  262. -char *hdynread2(char stop);
  263. -void setcbreak(void);
  264. -int getlineleng(void);
  265. -void unsetcbreak(void);
  266. -void attachtty(long pgrp);
  267. End of hist.pro
  268. echo init.c 1>&2
  269. sed 's/^-//' >init.c <<'End of init.c'
  270. -/*
  271. -
  272. -    init.c - initialization, main loop
  273. -
  274. -    This file is part of zsh, the Z shell.
  275. -
  276. -   zsh is free software; no one can prevent you from reading the source
  277. -   code, or giving it to someone else.
  278. -   This file is copyrighted under the GNU General Public License, which
  279. -   can be found in the file called COPYING.
  280. -
  281. -   Copyright (C) 1990 Paul Falstad
  282. -
  283. -   zsh is distributed in the hope that it will be useful, but
  284. -   WITHOUT ANY WARRANTY.  No author or distributor accepts
  285. -   responsibility to anyone for the consequences of using it or for
  286. -   whether it serves any particular purpose or works at all, unless he
  287. -   says so in writing.  Refer to the GNU General Public License
  288. -   for full details.
  289. -
  290. -   Everyone is granted permission to copy, modify and redistribute
  291. -   zsh, but only under the conditions described in the GNU General Public
  292. -   License.   A copy of this license is supposed to have been given to you
  293. -   along with zsh so you can know your rights and responsibilities.
  294. -   It should be in a file named COPYING.
  295. -
  296. -   Among other things, the copyright notice and this notice must be
  297. -   preserved on all copies.
  298. -
  299. -*/
  300. -
  301. -#include "zsh.h"
  302. -#include "funcs.h"
  303. -#include <pwd.h>
  304. -
  305. -void main(int argc, char **argv)
  306. -{
  307. -int notect = 0;
  308. -
  309. -    setflags();
  310. -    parseargs(argv);
  311. -    setmoreflags();
  312. -    setupvals();
  313. -    initialize();
  314. -    runscripts();
  315. -    FOREVER
  316. -        {
  317. -        do
  318. -            loop();
  319. -        while (peek != EOF);
  320. -        if (!(isset(IGNOREEOF) && interact))
  321. -            {
  322. -            if (interact)
  323. -                fputs(islogin ? "logout\n" : "exit\n",stderr);
  324. -            zexit(NULL);
  325. -            continue;
  326. -            }
  327. -        zerrnam("\nzsh",(!islogin) ? "use 'exit' to exit."
  328. -            : "use 'logout' to logout.");
  329. -        notect++;
  330. -        if (notect == 10)
  331. -            zexit(NULL);
  332. -        }
  333. -}
  334. -
  335. -/* keep executing lists until EOF found */
  336. -
  337. -void loop(void)
  338. -{
  339. -list list;
  340. -
  341. -    FOREVER
  342. -        {
  343. -        peek = EMPTY;
  344. -        if (interact)
  345. -            preprompt();
  346. -        hbegin();        /* init history mech */
  347. -        intr();            /* interrupts on */
  348. -        ainit();            /* init alias mech */
  349. -        if (!(list = parlist1(0)))
  350. -            {                /* if we couldn't parse a list */
  351. -            hend();
  352. -            if (!errflag)
  353. -                if (peek == OUTPAR)
  354. -                    {
  355. -                    errflag = 1;
  356. -                    zerr("mismatched parenthesis");
  357. -                    }
  358. -                else if (peek == OUTBRACE)
  359. -                    {
  360. -                    errflag = 1;
  361. -                    zerr("mismatched brace");
  362. -                    }
  363. -                else if (peek != EOF && peek != EMPTY && peek != NEWLIN)
  364. -                    {
  365. -                    errflag = 1;
  366. -                    zerr("semicolon or newline expected");
  367. -                    }
  368. -            if (peek == EOF && !errflag)
  369. -                return;
  370. -            continue;
  371. -            }
  372. -        if (peek != EMPTY && peek != EOF)
  373. -            {
  374. -            if (peek == OUTPAR)
  375. -                zerr("mismatched parenthesis");
  376. -            else if (peek == OUTBRACE)
  377. -                zerr("mismatched brace");
  378. -            else
  379. -                zerr("semicolon or newline expected");
  380. -            hend();
  381. -            errflag = 1;
  382. -            }
  383. -        else if (hend())
  384. -            {
  385. -            if (stopmsg)        /* unset 'you have stopped jobs' flag */
  386. -                stopmsg--;
  387. -            execlist(list);
  388. -            }
  389. -        if (ferror(stderr))
  390. -            {
  391. -            zerr("write error");
  392. -            clearerr(stderr);
  393. -            }
  394. -        if (subsh)                /* how'd we get this far in a subshell? */
  395. -            exit(lastval);
  396. -        if ((!interact && errflag) || retflag)
  397. -            return;
  398. -        if ((opts['t'] == OPT_SET) || (lastval && opts[ERREXIT] == OPT_SET))
  399. -            {
  400. -            if (sigtrapped[SIGEXIT])
  401. -                dotrap(SIGEXIT);
  402. -            exit(lastval);
  403. -            }
  404. -        }
  405. -}
  406. -
  407. -void setflags(void)
  408. -{
  409. -int c;
  410. -
  411. -    for (c = 0; c != 128; c++)
  412. -        opts[c] = OPT_INVALID;
  413. -    opts['a'] = opts['e'] = opts['f'] = opts['h'] = opts['k'] = opts['n'] = 
  414. -        opts['s'] = opts['t'] = opts['u'] = opts['v'] = opts['x'] = 
  415. -        opts['c'] = OPT_UNSET;
  416. -    opts['i'] = (isatty(0)) ? OPT_SET : OPT_UNSET;
  417. -    for (c = '0'; c <= '9'; c++)
  418. -        opts[c] = OPT_UNSET;
  419. -    for (c = 'A'; c <= 'K'; c++)
  420. -        opts[c] = OPT_UNSET;
  421. -    opts[BGNICE] = opts[NOTIFY] = OPT_SET;
  422. -}
  423. -
  424. -static char *cmd;
  425. -
  426. -void parseargs(char **argv)
  427. -{
  428. -char *argv0 = *argv;
  429. -int bk = 0;
  430. -
  431. -    islogin = **(argv++) == '-';
  432. -    SHIN = 0;
  433. -    while (!bk && *argv && **argv == '-')
  434. -        {
  435. -        while (*++*argv)
  436. -            {
  437. -            if (opts[**argv] == OPT_INVALID)
  438. -                {
  439. -                zerr("bad option: -%c",**argv);
  440. -                exit(1);
  441. -                }
  442. -            opts[**argv] = OPT_SET;
  443. -            if (bk = **argv == 'b')
  444. -                break;
  445. -            if (**argv == 'c') /* -c command */
  446. -                {
  447. -                argv++;
  448. -                if (!*argv)
  449. -                    {
  450. -                    zerr("string expected after -c");
  451. -                    exit(1);
  452. -                    }
  453. -                cmd = strdup(*argv);
  454. -                opts[INTERACTIVE] = OPT_UNSET;
  455. -                break;
  456. -                }
  457. -            }
  458. -        argv++;
  459. -        }
  460. -    pparms = newtable();
  461. -    if (*argv)
  462. -        {
  463. -        if (opts[SHINSTDIN] == OPT_UNSET)
  464. -            {
  465. -            SHIN = movefd(open(argv0 = *argv,O_RDONLY));
  466. -            if (SHIN == -1)
  467. -                {
  468. -                zerr("can't open input file: %s",*argv);
  469. -                exit(1);
  470. -                }
  471. -            opts[INTERACTIVE] = OPT_UNSET;
  472. -            argv++;
  473. -            }
  474. -        addnode(pparms,argv0);  /* assign positional parameters */
  475. -        while (*argv)
  476. -            addnode(pparms,strdup(*argv++));
  477. -        }
  478. -    else
  479. -        {
  480. -        addnode(pparms,strdup(argv0));
  481. -        opts[SHINSTDIN] = OPT_SET;
  482. -        }
  483. -}
  484. -
  485. -void setmoreflags(void)
  486. -{
  487. -    setlinebuf(stderr);
  488. -    setlinebuf(stdout);
  489. -    subsh = 0;
  490. -    opts[MONITOR] = (interact) ? OPT_SET : OPT_UNSET;
  491. -    if (jobbing)
  492. -        {
  493. -        SHTTY = movefd((isatty(0)) ? dup(0) : open("/dev/tty",O_RDWR));
  494. -        if (SHTTY == -1)
  495. -            opts[MONITOR] = OPT_UNSET;
  496. -        else
  497. -            gettyinfo(&shttyinfo);    /* get tty state */
  498. -        if ((shpgrp = getpgrp(0)) <= 0)
  499. -            opts[MONITOR] = OPT_UNSET;
  500. -        }
  501. -    else
  502. -        SHTTY = -1;
  503. -}
  504. -
  505. -void setupvals(void)
  506. -{
  507. -struct passwd *pwd;
  508. -char *ptr;
  509. -
  510. -    shtimer = time(NULL);    /* init $SECONDS */
  511. -    /* build various hash tables; argument to newhtable is table size */
  512. -    alhtab = newhtable(37);
  513. -    parmhtab = newhtable(17);
  514. -    shfunchtab = newhtable(17);
  515. -    if (interact)
  516. -        {
  517. -        if (!getparm("PROMPT"))
  518. -            setparm(strdup("PROMPT"),strdup("%M%# "),0,0);
  519. -        if (!getparm("PROMPT2"))
  520. -            setparm(strdup("PROMPT2"),strdup("> "),0,0);
  521. -        if (!getparm("PROMPT3"))
  522. -            setparm(strdup("PROMPT3"),strdup("?# "),0,0);
  523. -        }
  524. -    if (!getparm("PATH"))
  525. -        setparm(strdup("PATH"),strdup("/bin:/usr/bin:/usr/ucb"),1,0);
  526. -    setparm(strdup("VERSION"),strdup(VERSIONSTR),1,0);
  527. -    home = xsymlink(getparm("HOME"));
  528. -    setparm(strdup("HOME"),strdup(home),0,0);
  529. -    setiparm(strdup("UID"),getuid(),1);
  530. -    setiparm(strdup("EUID"),geteuid(),1);
  531. -    setiparm(strdup("PPID"),getppid(),1);
  532. -    lineno = 0;
  533. -    pwd = getpwuid(getuid());
  534. -    setparm(strdup("USERNAME"),strdup(pwd->pw_name),0,0);
  535. -    username = strdup(pwd->pw_name);
  536. -    setparm(strdup("HOSTTYPE"),strdup(HOSTTYP),0,0);
  537. -    cwd = zgetwd();
  538. -    setparm(strdup("PWD"),strdup(cwd),0,0);
  539. -    if (!getparm("IFS"))
  540. -        {
  541. -        ifs = strdup(" \t\n");
  542. -        setparm(strdup("IFS"),strdup(ifs),0,0);
  543. -        }
  544. -    hostM = alloc(512);    /* get hostname, with and without .podunk.edu */
  545. -    hostm = hostM+256;
  546. -    gethostname(hostm,256);
  547. -    gethostname(hostM,256);
  548. -    procnum = getpid();
  549. -    for (ptr = hostM; *ptr && *ptr != '.'; ptr++);
  550. -    *ptr = '\0';
  551. -}
  552. -
  553. -void initialize(void)
  554. -{
  555. -int t0;
  556. -
  557. -    breaks = loops = incmd = 0;
  558. -    lastmailcheck = 0;
  559. -    lastmailval = -1;
  560. -    tfev = 1;
  561. -    tevs = DEFAULT_HISTSIZE;
  562. -    histlist = newtable();
  563. -    dirstack = newtable();
  564. -    ungots = ungotptr = NULL;
  565. -    signal(SIGQUIT,SIG_IGN);
  566. -    for (t0 = 0; t0 != RLIM_NLIMITS; t0++)
  567. -        getrlimit(t0,limits+t0);
  568. -    last = rast = NULL;
  569. -    proclast = 0;
  570. -    if (!interact || SHTTY == -1)
  571. -        bshin = fdopen(SHIN,"r");
  572. -    signal(SIGCHLD,handler);
  573. -    addreswords();
  574. -    addhnode(strdup("false"),mkanode(strdup("let 0"),1),alhtab,NULL);
  575. -    addhnode(strdup("history"),mkanode(strdup("fc -l"),1),alhtab,NULL);
  576. -    addhnode(strdup("nohup"),mkanode(strdup("nohup "),1),alhtab,NULL);
  577. -    addhnode(strdup("r"),mkanode(strdup("fc -e -"),1),alhtab,NULL);
  578. -    addhnode(strdup("true"),mkanode(strdup(":"),1),alhtab,NULL);
  579. -    addhnode(strdup("pwd"),mkanode(strdup("echo $PWD"),1),alhtab,NULL);
  580. -    parsepath();
  581. -    parsecdpath();
  582. -    if (jobbing)
  583. -        {
  584. -        signal(SIGTTOU,SIG_IGN);
  585. -        signal(SIGTSTP,SIG_IGN);
  586. -        signal(SIGTTIN,SIG_IGN);
  587. -        signal(SIGPIPE,SIG_IGN);
  588. -        attachtty(shpgrp);
  589. -        }
  590. -    if (interact)
  591. -        {
  592. -        signal(SIGTERM,SIG_IGN);
  593. -        intr();
  594. -        }
  595. -}
  596. -
  597. -void addreswords(void)
  598. -{
  599. -char *reswds[] = {
  600. -    "do", "done", "esac", "then", "elif", "else", "fi", "for", "case",
  601. -    "if", "while", "function", "repeat", "time", "until", "exec", "command",
  602. -    "select", "coproc", NULL
  603. -    };
  604. -int t0;
  605. -
  606. -    for (t0 = 0; reswds[t0]; t0++)
  607. -        addhnode(strdup(reswds[t0]),mkanode(NULL,-1-t0),alhtab,NULL);
  608. -}
  609. -
  610. -void runscripts(void)
  611. -{
  612. -    if (interact)
  613. -        checkfirstmail();
  614. -    if (opts[NORCS] == OPT_UNSET)
  615. -        {
  616. -#ifdef GLOBALZSHRC
  617. -        source(GLOBALZSHRC);
  618. -#endif
  619. -        sourcehome(".zshrc");
  620. -        if (islogin)
  621. -            {
  622. -#ifdef GLOBALZLOGIN
  623. -            source(GLOBALZLOGIN);
  624. -#endif
  625. -            sourcehome(".zlogin");
  626. -            }
  627. -        }
  628. -    if (opts['c'] == OPT_SET)
  629. -        {
  630. -        close(SHIN);
  631. -        SHIN = movefd(open("/dev/null",O_RDONLY));
  632. -        hungets(cmd);
  633. -        strinbeg();
  634. -        }
  635. -}
  636. -
  637. -void ainit(void)
  638. -{
  639. -    alix = 0;        /* reset alias stack */
  640. -    alstat = 0;
  641. -    firstln = 1;
  642. -}
  643. End of init.c
  644. echo init.pro 1>&2
  645. sed 's/^-//' >init.pro <<'End of init.pro'
  646. -void main(int argc, char **argv);
  647. -void loop(void);
  648. -void setflags(void);
  649. -void parseargs(char **argv);
  650. -void setmoreflags(void);
  651. -void setupvals(void);
  652. -void initialize(void);
  653. -void addreswords(void);
  654. -void runscripts(void);
  655. -void ainit(void);
  656. End of init.pro
  657. echo jobs.c 1>&2
  658. sed 's/^-//' >jobs.c <<'End of jobs.c'
  659. -/*
  660. -
  661. -    jobs.c - job control
  662. -
  663. -    This file is part of zsh, the Z shell.
  664. -
  665. -   zsh is free software; no one can prevent you from reading the source
  666. -   code, or giving it to someone else.
  667. -   This file is copyrighted under the GNU General Public License, which
  668. -   can be found in the file called COPYING.
  669. -
  670. -   Copyright (C) 1990 Paul Falstad
  671. -
  672. -   zsh is distributed in the hope that it will be useful, but
  673. -   WITHOUT ANY WARRANTY.  No author or distributor accepts
  674. -   responsibility to anyone for the consequences of using it or for
  675. -   whether it serves any particular purpose or works at all, unless he
  676. -   says so in writing.  Refer to the GNU General Public License
  677. -   for full details.
  678. -
  679. -   Everyone is granted permission to copy, modify and redistribute
  680. -   zsh, but only under the conditions described in the GNU General Public
  681. -   License.   A copy of this license is supposed to have been given to you
  682. -   along with zsh so you can know your rights and responsibilities.
  683. -   It should be in a file named COPYING.
  684. -
  685. -   Among other things, the copyright notice and this notice must be
  686. -   preserved on all copies.
  687. -
  688. -*/
  689. -
  690. -#include "zsh.h"
  691. -#include "funcs.h"
  692. -#include <sys/errno.h>
  693. -
  694. -#define WCOREDUMPED(x) ((x)&0x80)
  695. -
  696. -/* != 0 means the handler is active */
  697. -
  698. -static int handling = 0;
  699. -
  700. -/* != 0 means the shell is waiting for a job to complete */
  701. -
  702. -static int waiting = 0;
  703. -
  704. -/* != 0 means readline is active */
  705. -
  706. -extern int rl_active;
  707. -
  708. -/* != 0 means readline is waiting for a keypress */
  709. -
  710. -extern int rl_waiting;
  711. -
  712. -#ifdef INTHANDTYPE
  713. -#define RETURN return 0
  714. -#else
  715. -#define RETURN return
  716. -#endif
  717. -
  718. -/* the signal handler */
  719. -
  720. -HANDTYPE handler(int sig,int code)
  721. -{
  722. -long pid;
  723. -int statusp;
  724. -struct jobnode *jn;
  725. -struct procnode *pn;
  726. -struct rusage ru;
  727. -
  728. -    if (sig == SIGINT)
  729. -        {
  730. -        if (sigtrapped[SIGINT])
  731. -            dotrap(SIGINT);
  732. -        else
  733. -            errflag = 1;
  734. -        RETURN;
  735. -        }
  736. -    if (sig != SIGCHLD)
  737. -        {
  738. -        dotrap(sig);
  739. -        RETURN;
  740. -        }
  741. -    for (;;)
  742. -        {
  743. -        pid = wait3(&statusp,WNOHANG|WUNTRACED,&ru);
  744. -        if (pid == -1)
  745. -            {
  746. -            if (errno != ECHILD)
  747. -                zerr("%e",errno);
  748. -            RETURN;
  749. -            }
  750. -        if (!pid)
  751. -            RETURN;
  752. -        findproc(pid,&jn,&pn);    /* find the procnode of this pid */
  753. -        if (jn)
  754. -            {
  755. -            pn->statusp = statusp;
  756. -            handling = 1;
  757. -            pn->ru_utime = ru.ru_utime;
  758. -            pn->ru_stime = ru.ru_stime;
  759. -            pn->endtime = time(NULL);
  760. -            updatestatus(jn);
  761. -            handling = 0;
  762. -            }
  763. -        else if (WIFSTOPPED(SP(statusp)))
  764. -            kill(pid,SIGKILL);    /* kill stopped untraced children */
  765. -        }
  766. -    if (rl_active)
  767. -        rl_prep_terminal();
  768. -    RETURN;
  769. -}
  770. -
  771. -/* change job table entry from stopped to running */
  772. -
  773. -void makerunning(struct jobnode *jn)
  774. -{
  775. -struct procnode *pn;
  776. -
  777. -    jn->stat &= ~STAT_STOPPED;
  778. -    for (pn = jn->procs; pn; pn = pn->next)
  779. -        if (WIFSTOPPED(SP(pn->statusp)))
  780. -            pn->statusp = SP_RUNNING;
  781. -}
  782. -
  783. -/* update status of job, possibly printing it */
  784. -
  785. -void updatestatus(struct jobnode *jn)
  786. -{
  787. -struct procnode *pn;
  788. -int notrunning = 1,alldone = 1,val,job = jn-jobtab,somestopped = 0;
  789. -
  790. -    for (pn = jn->procs; pn; pn = pn->next)
  791. -        {
  792. -        if (pn->statusp == SP_RUNNING)
  793. -            notrunning = 0;
  794. -        if (pn->statusp == SP_RUNNING || WIFSTOPPED(SP(pn->statusp)))
  795. -            alldone = 0;
  796. -        if (WIFSTOPPED(SP(pn->statusp)))
  797. -            somestopped = 1;
  798. -        if (!pn->next && jn)
  799. -            val = (WIFSIGNALED(SP(pn->statusp))) ?
  800. -                0200 | WTERMSIG(SP(pn->statusp)) : WEXITSTATUS(SP(pn->statusp));
  801. -        }
  802. -    if (!notrunning)
  803. -        return;
  804. -    if (somestopped && (jn->stat & STAT_STOPPED))
  805. -        return;
  806. -    jn->stat |= (alldone) ? STAT_CHANGED|STAT_DONE :
  807. -        STAT_CHANGED|STAT_STOPPED;
  808. -    if (!alldone)
  809. -        gettyinfo(&jn->ttyinfo);
  810. -    if (job == curjob)
  811. -        {
  812. -        if (!val)
  813. -            gettyinfo(&shttyinfo);
  814. -        else
  815. -            settyinfo(&shttyinfo);
  816. -        lastval = val;
  817. -        }
  818. -    if (jn->stat & STAT_STOPPED)
  819. -        {
  820. -        prevjob = topjob;
  821. -        topjob = job;
  822. -        }
  823. -    if ((isset(NOTIFY) || job == curjob) && jn->stat & STAT_LOCKED)
  824. -        printjob(jn,0);
  825. -    if (sigtrapped[SIGCHLD] && job != curjob)
  826. -        dotrap(SIGCHLD);
  827. -}
  828. -
  829. -/* find procnode and jobnode associated with pid */
  830. -
  831. -void findproc(int pid,struct jobnode **jptr,struct procnode **pptr)
  832. -{
  833. -struct procnode *pn;
  834. -int jn;
  835. -
  836. -    for (jn = 1; jn != MAXJOB; jn++)
  837. -        for (pn = jobtab[jn].procs; pn; pn = pn->next)
  838. -            if (pn->pid == pid)
  839. -                {
  840. -                *pptr = pn;
  841. -                *jptr = jobtab+jn;
  842. -                return;
  843. -                }
  844. -    *pptr = NULL;
  845. -    *jptr = NULL;
  846. -}
  847. -
  848. -static char *sigmsg[32] = {
  849. -    "done","hangup","interrupt","quit",
  850. -    "illegal instruction","trace trap","IOT instruction","EMT instruction",
  851. -    "floating exception","killed","bus error","segmentation fault",
  852. -    "bad system call","broken pipe","SIGALRM","terminated",
  853. -#ifdef USE_SUSPENDED
  854. -    "SIGURG","suspended (signal)","suspended","continued",
  855. -    "SIGCHLD","suspended (tty input)","suspended (tty output)","SIGIO",
  856. -#else
  857. -    "SIGURG","stopped (signal)","stopped","continued",
  858. -    "SIGCHLD","stopped (tty input)","stopped (tty output)","SIGIO",
  859. -#endif
  860. -    "CPU time limit exceeded","file size limit exceeded","SIGVTALRM","SIGPROF",
  861. -    "window changed","resource lost","SIGUSR1","SIGUSR2"
  862. -    };
  863. -
  864. -/* lng = 0 means jobs 
  865. -    lng = 1 means jobs -l
  866. -    lng = 2 means jobs -p
  867. -*/
  868. -
  869. -void printjob(struct jobnode *jn,int lng)
  870. -{
  871. -int job = jn-jobtab,len = 9,sig = -1,sflag = 0,llen,printed = 0;
  872. -int conted = 0,lineleng = getlineleng(),doputnl = 0;
  873. -struct procnode *pn;
  874. -extern void rl_on_new_line(void);
  875. -
  876. -    if (lng < 0)
  877. -        {
  878. -        conted = 1;
  879. -        lng = 0;
  880. -        }
  881. -
  882. -    /* find length of longest signame, check to see if we
  883. -        really need to print this job */
  884. -
  885. -    for (pn = jn->procs; pn; pn = pn->next)
  886. -        {
  887. -        if (pn->statusp != SP_RUNNING)
  888. -            if (WIFSIGNALED(SP(pn->statusp)))
  889. -                {
  890. -                sig = WTERMSIG(SP(pn->statusp));
  891. -                llen = strlen(sigmsg[sig]);
  892. -                if (WCOREDUMPED(pn->statusp))
  893. -                    llen += 14;
  894. -                if (llen > len)
  895. -                    len = llen;
  896. -                if (sig != SIGINT && sig != SIGPIPE)
  897. -                    sflag = 1;
  898. -                if (sig == SIGINT && job == curjob && interact)
  899. -                    doputnl = 1;
  900. -                }
  901. -            else if (WIFSTOPPED(SP(pn->statusp)))
  902. -                {
  903. -                sig = WSTOPSIG(SP(pn->statusp));
  904. -                if (strlen(sigmsg[sig]) > len)
  905. -                    len = strlen(sigmsg[sig]);
  906. -                }
  907. -            else if (isset(PRINTEXITVALUE) && WEXITSTATUS(SP(pn->statusp)))
  908. -                sflag = 1;
  909. -        }
  910. -    if (doputnl)
  911. -        putc('\n',stderr);
  912. -
  913. -    /* print if necessary */
  914. -
  915. -    if (interact && jobbing && ((jn->stat & STAT_STOPPED) || sflag ||
  916. -            job != curjob))
  917. -        {
  918. -        int len2,fline = 1;
  919. -        struct procnode *qn;
  920. -
  921. -        if (handling && (!waiting || jn->stat & STAT_STOPPED))
  922. -            putc('\n',stderr);
  923. -        for (pn = jn->procs; pn;)
  924. -            {
  925. -            len2 = ((job == curjob) ? 5 : 10)+len; /* 2 spaces */
  926. -            if (lng)
  927. -                qn = pn->next;
  928. -            else for (qn = pn->next; qn; qn = qn->next)
  929. -                {
  930. -                if (qn->statusp != pn->statusp)
  931. -                    break;
  932. -                if (strlen(qn->text)+len2+((qn->next) ? 3 : 0) > lineleng)
  933. -                    break;
  934. -                len2 += strlen(qn->text)+2;
  935. -                }
  936. -            if (job != curjob)
  937. -                if (fline)
  938. -                    fprintf(stderr,"[%d]  %c ",jn-jobtab,(job == topjob) ? '+' :
  939. -                        (job == prevjob) ? '-' : ' ');
  940. -                else
  941. -                    fprintf(stderr,(job > 9) ? "        " : "       ");
  942. -            else
  943. -                fprintf(stderr,"zsh: ");
  944. -            if (lng)
  945. -                if (lng == 1)
  946. -                    fprintf(stderr,"%d ",pn->pid);
  947. -                else
  948. -                    {
  949. -                    fprintf(stderr,"%d ",jn->gleader);
  950. -                    lng = 0;
  951. -                    }
  952. -            if (pn->statusp == SP_RUNNING)
  953. -                if (!conted)
  954. -                    fprintf(stderr,"running%*s",len-7+2,"");
  955. -                else
  956. -                    fprintf(stderr,"continued%*s",len-9+2,"");
  957. -            else if (WIFEXITED(SP(pn->statusp)))
  958. -                if (WEXITSTATUS(SP(pn->statusp)))
  959. -                    fprintf(stderr,"exit %-4d%*s",WEXITSTATUS(SP(pn->statusp)),
  960. -                        len-9+2,"");
  961. -                else
  962. -                    fprintf(stderr,"done%*s",len-4+2,"");
  963. -            else if (WIFSTOPPED(SP(pn->statusp)))
  964. -                fprintf(stderr,"%-*s",len+2,sigmsg[WSTOPSIG(SP(pn->statusp))]);
  965. -            else if (WCOREDUMPED(pn->statusp))
  966. -                fprintf(stderr,"%s (core dumped)%*s",
  967. -                    sigmsg[WTERMSIG(SP(pn->statusp))],
  968. -                    len-14+2-strlen(sigmsg[WTERMSIG(SP(pn->statusp))]),"");
  969. -            else
  970. -                fprintf(stderr,"%-*s",len+2,sigmsg[WTERMSIG(SP(pn->statusp))]);
  971. -            for (; pn != qn; pn = pn->next)
  972. -                fprintf(stderr,(pn->next) ? "%s | " : "%s",pn->text);
  973. -            putc('\n',stderr);
  974. -            fline = 0;
  975. -            }
  976. -        printed = 1;
  977. -        }
  978. -
  979. -    /* print "(pwd now: foo)" messages */
  980. -
  981. -    if (interact && job==curjob && strcmp(jn->cwd,cwd))
  982. -        {
  983. -        printf("(pwd now: ");
  984. -        printdir(cwd);
  985. -        printf(")\n");
  986. -        fflush(stdout);
  987. -        }
  988. -
  989. -    /* delete job if done */
  990. -
  991. -    if (jn->stat & STAT_DONE)
  992. -        {
  993. -        static struct jobnode zero;
  994. -        struct procnode *nx;
  995. -        char *s;
  996. -
  997. -        if (jn->stat & STAT_TIMED)
  998. -            {
  999. -            dumptime(jn);
  1000. -            printed = 1;
  1001. -            }
  1002. -        for (pn = jn->procs; pn; pn = nx)
  1003. -            {
  1004. -            nx = pn->next;
  1005. -            if (pn->text)
  1006. -                free(pn->text);
  1007. -            free(pn);
  1008. -            }
  1009. -        free(jn->cwd);
  1010. -        if (jn->filelist)
  1011. -            {
  1012. -            while (s = getnode(jn->filelist))
  1013. -                {
  1014. -                unlink(s);
  1015. -                free(s);
  1016. -                }
  1017. -            free(jn->filelist);
  1018. -            }
  1019. -        *jn = zero;
  1020. -        if (job == topjob)
  1021. -            {
  1022. -            topjob = prevjob;
  1023. -            prevjob = job;
  1024. -            }
  1025. -        if (job == prevjob)
  1026. -            setprevjob();
  1027. -        }
  1028. -    else
  1029. -        jn->stat &= ~STAT_CHANGED;
  1030. -    if (printed && rl_active)
  1031. -        {
  1032. -        rl_on_new_line();
  1033. -        if (rl_waiting)
  1034. -            rl_redisplay();
  1035. -        }
  1036. -}
  1037. -
  1038. -/* set the previous job to something reasonable */
  1039. -
  1040. -void setprevjob(void)
  1041. -{
  1042. -int t0;
  1043. -
  1044. -    for (t0 = MAXJOB-1; t0; t0--)
  1045. -        if (jobtab[t0].stat && jobtab[t0].stat & STAT_STOPPED &&
  1046. -                t0 != topjob && t0 != curjob)
  1047. -            break;
  1048. -    if (!t0)
  1049. -        for (t0 = MAXJOB-1; t0; t0--)
  1050. -            if (jobtab[t0].stat && t0 != topjob && t0 != curjob)
  1051. -                break;
  1052. -    prevjob = (t0) ? t0 : -1;
  1053. -}
  1054. -
  1055. -/* initialize a job table entry */
  1056. -
  1057. -void initjob(int flags)
  1058. -{
  1059. -    jobtab[curjob].cwd = strdup(cwd);
  1060. -    jobtab[curjob].stat = (flags & PFLAG_TIMED) | STAT_INUSE;
  1061. -    jobtab[curjob].ttyinfo = shttyinfo;
  1062. -    jobtab[curjob].gleader = 0;
  1063. -}
  1064. -
  1065. -/* add a process to the current job */
  1066. -
  1067. -struct procnode *addproc(long pid,char *text)
  1068. -{
  1069. -struct procnode *procnode;
  1070. -
  1071. -    if (!jobtab[curjob].gleader)
  1072. -        jobtab[curjob].gleader = proclast = pid;
  1073. -    proclast = pid;
  1074. -    procnode = alloc(sizeof(struct procnode));
  1075. -    procnode->pid = pid;
  1076. -    procnode->text = text;
  1077. -    procnode->next = NULL;
  1078. -    procnode->statusp = SP_RUNNING;
  1079. -    procnode->bgtime = time(NULL);
  1080. -    if (jobtab[curjob].procs)
  1081. -        {
  1082. -        struct procnode *n;
  1083. -
  1084. -        for (n = jobtab[curjob].procs; n->next && !n->next->lastfg; n = n->next);
  1085. -        procnode->next = n->next;
  1086. -        n->next = procnode;
  1087. -        }
  1088. -    else
  1089. -        jobtab[curjob].procs = procnode;
  1090. -    return procnode;
  1091. -}
  1092. -
  1093. -/* determine if it's all right to exec a command without
  1094. -    forking in last component of subshells; it's not ok if we have files
  1095. -    to delete */
  1096. -
  1097. -int execok(void)
  1098. -{
  1099. -struct jobnode *jn;
  1100. -
  1101. -    if (!exiting)
  1102. -        return 0;
  1103. -    for (jn = jobtab+1; jn != jobtab+MAXJOB; jn++)
  1104. -        if (jn->stat && jn->filelist)
  1105. -            return 0;
  1106. -    return 1;
  1107. -}
  1108. -
  1109. -/* wait for a SIGCHLD, wait for the handler to execute, and return */
  1110. -
  1111. -void chldsuspend(void)
  1112. -{
  1113. -struct sigvec vec = { handler,sigmask(SIGCHLD),SV_INTERRUPT };
  1114. -
  1115. -    sigvec(SIGCHLD,&vec,NULL);
  1116. -    sigpause(0);
  1117. -    signal(SIGCHLD,handler);
  1118. -}
  1119. -
  1120. -/* wait for the current job to finish */
  1121. -
  1122. -void waitjobs(void)
  1123. -{
  1124. -static struct jobnode zero;
  1125. -struct jobnode *jn;
  1126. -
  1127. -    if (jobtab[curjob].procs)    /* if any forks were done */
  1128. -        {
  1129. -        jobtab[curjob].stat |= STAT_LOCKED;
  1130. -        waiting = 1;
  1131. -        if (jobtab[curjob].stat & STAT_CHANGED)
  1132. -            printjob(jobtab+curjob,0);
  1133. -        while (jobtab[curjob].stat &&
  1134. -                !(jobtab[curjob].stat & (STAT_DONE|STAT_STOPPED)))
  1135. -            chldsuspend();
  1136. -        waiting = 0;
  1137. -        }
  1138. -    else    /* else do what printjob() usually does */
  1139. -        {
  1140. -        char *s;
  1141. -
  1142. -        jn = jobtab+curjob;
  1143. -        free(jn->cwd);
  1144. -        if (jn->filelist)
  1145. -            {
  1146. -            while (s = getnode(jn->filelist))
  1147. -                {
  1148. -                unlink(s);
  1149. -                free(s);
  1150. -                }
  1151. -            free(jn->filelist);
  1152. -            }
  1153. -        *jn = zero;
  1154. -        }
  1155. -    curjob = -1;
  1156. -}
  1157. -
  1158. -/* clear jobtab when entering subshells */
  1159. -
  1160. -void clearjobtab(void)
  1161. -{
  1162. -static struct jobnode zero;
  1163. -int t0;
  1164. -
  1165. -    for (t0 = 1; t0 != MAXJOB; t0++)
  1166. -        jobtab[curjob] = zero;
  1167. -}
  1168. -
  1169. -/* get a free entry in the job table to use */
  1170. -
  1171. -int getfreejob(void)
  1172. -{
  1173. -int mask,t0;
  1174. -
  1175. -    FOREVER    
  1176. -        {
  1177. -        mask = sigblock(sigmask(SIGCHLD));
  1178. -        for (t0 = 1; t0 != MAXJOB; t0++)
  1179. -            if (!jobtab[t0].stat)
  1180. -                {
  1181. -                sigsetmask(mask);
  1182. -                jobtab[t0].stat |= STAT_INUSE;
  1183. -                return t0;
  1184. -                }
  1185. -        sigsetmask(mask);
  1186. -        sleep(1);
  1187. -        }
  1188. -}
  1189. -
  1190. -/* print pids for & */
  1191. -
  1192. -void spawnjob(void)
  1193. -{
  1194. -struct procnode *pn;
  1195. -
  1196. -    if (!subsh)
  1197. -        {
  1198. -        if (topjob == -1 || !(jobtab[topjob].stat & STAT_STOPPED))
  1199. -            {
  1200. -            topjob = curjob;
  1201. -            setprevjob();
  1202. -            }
  1203. -        else if (prevjob == -1 || !(jobtab[prevjob].stat & STAT_STOPPED))
  1204. -            prevjob = curjob;
  1205. -        if (interact && jobbing)
  1206. -            {
  1207. -            fprintf(stderr,"[%d]",curjob);
  1208. -            for (pn = jobtab[curjob].procs; pn; pn = pn->next)
  1209. -                fprintf(stderr," %d",pn->pid);
  1210. -            fprintf(stderr,"\n");
  1211. -            }
  1212. -        }
  1213. -    jobtab[curjob].stat |= STAT_LOCKED;
  1214. -    curjob = -1;
  1215. -}
  1216. -
  1217. -void fixsigs(void)
  1218. -{
  1219. -    sigsetmask(0);
  1220. -}
  1221. -
  1222. -/* timing */
  1223. -
  1224. -static void addtimeval(struct timeval *s,struct timeval *t)
  1225. -{
  1226. -    s->tv_sec += t->tv_sec+(s->tv_usec+t->tv_usec)/1000000;
  1227. -    s->tv_usec = (s->tv_usec+t->tv_usec)%1000000;
  1228. -}
  1229. -
  1230. -static void printtime(time_t real,struct timeval *u,struct timeval *s,char *desc)
  1231. -{
  1232. -    if (!desc)
  1233. -        desc = "";
  1234. -    fprintf(stderr,"real: %lds  user: %ld.%03lds  sys: %ld.%03lds\n",
  1235. -        real,u->tv_sec,u->tv_usec/1000,s->tv_sec,s->tv_usec/1000);
  1236. -}
  1237. -
  1238. -static void printheader(void)
  1239. -{
  1240. -    fprintf(stderr,"  real       user      system\n");
  1241. -}
  1242. -
  1243. -static void printtimes(time_t real,struct timeval *u,struct timeval *s,char *desc)
  1244. -{
  1245. -    if (!desc)
  1246. -        desc = "";
  1247. -    fprintf(stderr,"% 8lds  % 4d.%03lds  % 4d.%03lds  %s\n",
  1248. -        real,u->tv_sec,u->tv_usec/1000,s->tv_sec,s->tv_usec/1000,desc);
  1249. -}
  1250. -
  1251. -void dumptime(struct jobnode *jn)
  1252. -{
  1253. -struct procnode *pn = jn->procs;
  1254. -struct timeval utot = { 0,0 },stot = { 0,0 };
  1255. -time_t maxend,minbeg;
  1256. -
  1257. -    if (!jn->procs)
  1258. -        return;
  1259. -    if (!jn->procs->next)
  1260. -        printtime(pn->endtime-pn->bgtime,&pn->ru_utime,&pn->ru_stime,pn->text);
  1261. -    else
  1262. -        {
  1263. -        maxend = jn->procs->endtime;
  1264. -        minbeg = jn->procs->bgtime;
  1265. -        printheader();
  1266. -        for (pn = jn->procs; pn; pn = pn->next)
  1267. -            {
  1268. -            printtimes(pn->endtime-pn->bgtime,&pn->ru_utime,&pn->ru_stime,pn->text);
  1269. -            addtimeval(&utot,&pn->ru_utime);
  1270. -            addtimeval(&stot,&pn->ru_stime);
  1271. -            if (pn->endtime > maxend)
  1272. -                maxend = pn->endtime;
  1273. -            if (pn->bgtime < minbeg)
  1274. -                minbeg = pn->bgtime;
  1275. -            }
  1276. -        printtimes(maxend-minbeg,&utot,&stot,"total");
  1277. -        }
  1278. -}
  1279. -
  1280. -/* SIGHUP any jobs left running */
  1281. -
  1282. -void killrunjobs(void)
  1283. -{
  1284. -int t0,killed = 0;
  1285. -
  1286. -    for (t0 = 1; t0 != MAXJOB; t0++)
  1287. -        if (t0 != curjob && jobtab[t0].stat &&
  1288. -                !(jobtab[t0].stat & STAT_STOPPED))
  1289. -            {
  1290. -            killpg(jobtab[t0].gleader,SIGHUP);
  1291. -            killed++;
  1292. -            }
  1293. -    if (killed)
  1294. -        zerr("warning: %d jobs SIGHUPed",killed);
  1295. -}
  1296. -
  1297. -/* check to see if user has jobs running/stopped */
  1298. -
  1299. -void checkjobs(void)
  1300. -{
  1301. -int t0;
  1302. -
  1303. -    for (t0 = 1; t0 != MAXJOB; t0++)
  1304. -        if (t0 != curjob && jobtab[t0].stat)
  1305. -            break;
  1306. -    if (t0 != MAXJOB)
  1307. -        {
  1308. -        if (jobtab[t0].stat & STAT_STOPPED)
  1309. -            {
  1310. -#ifdef USE_SUSPENDED
  1311. -            zerr("you have suspended jobs.");
  1312. -#else
  1313. -            zerr("you have stopped jobs.");
  1314. -#endif
  1315. -            }
  1316. -        else
  1317. -            zerr("you have running jobs.");
  1318. -        stopmsg = 1;
  1319. -        }
  1320. -}
  1321. -
  1322. -/* send a signal to a job (simply involves killpg if monitoring is on) */
  1323. -
  1324. -int killjb(struct jobnode *jn,int sig)
  1325. -{
  1326. -struct procnode *pn;
  1327. -int err;
  1328. -
  1329. -    if (jobbing)
  1330. -        return(killpg(jn->gleader,sig));
  1331. -    for (pn = jn->procs; pn; pn = pn->next)
  1332. -        if ((err = kill(pn->pid,sig)) == -1 && errno != ESRCH)
  1333. -            return -1;
  1334. -    return err;
  1335. -}
  1336. -
  1337. End of jobs.c
  1338. echo jobs.pro 1>&2
  1339. sed 's/^-//' >jobs.pro <<'End of jobs.pro'
  1340. -HANDTYPE handler(int sig,int code);
  1341. -void makerunning(struct jobnode *jn);
  1342. -void updatestatus(struct jobnode *jn);
  1343. -void findproc(int pid,struct jobnode **jptr,struct procnode **pptr);
  1344. -void printjob(struct jobnode *jn,int lng);
  1345. -void setprevjob(void);
  1346. -void initjob(int flags);
  1347. -struct procnode *addproc(long pid,char *text);
  1348. -int execok(void);
  1349. -void chldsuspend(void);
  1350. -void waitjobs(void);
  1351. -void clearjobtab(void);
  1352. -int getfreejob(void);
  1353. -void spawnjob(void);
  1354. -void fixsigs(void);
  1355. -void dumptime(struct jobnode *jn);
  1356. -void killrunjobs(void);
  1357. -void checkjobs(void);
  1358. -int killjb(struct jobnode *jn,int sig);
  1359. End of jobs.pro
  1360. echo lex.c 1>&2
  1361. sed 's/^-//' >lex.c <<'End of lex.c'
  1362. -/*
  1363. -
  1364. -    lex.c - lexical analysis
  1365. -
  1366. -    This file is part of zsh, the Z shell.
  1367. -
  1368. -   zsh is free software; no one can prevent you from reading the source
  1369. -   code, or giving it to someone else.
  1370. -   This file is copyrighted under the GNU General Public License, which
  1371. -   can be found in the file called COPYING.
  1372. -
  1373. -   Copyright (C) 1990 Paul Falstad
  1374. -
  1375. -   zsh is distributed in the hope that it will be useful, but
  1376. -   WITHOUT ANY WARRANTY.  No author or distributor accepts
  1377. -   responsibility to anyone for the consequences of using it or for
  1378. -   whether it serves any particular purpose or works at all, unless he
  1379. -   says so in writing.  Refer to the GNU General Public License
  1380. -   for full details.
  1381. -
  1382. -   Everyone is granted permission to copy, modify and redistribute
  1383. -   zsh, but only under the conditions described in the GNU General Public
  1384. -   License.   A copy of this license is supposed to have been given to you
  1385. -   along with zsh so you can know your rights and responsibilities.
  1386. -   It should be in a file named COPYING.
  1387. -
  1388. -   Among other things, the copyright notice and this notice must be
  1389. -   preserved on all copies.
  1390. -
  1391. -*/
  1392. -
  1393. -#include "zsh.h"
  1394. -#include "funcs.h"
  1395. -
  1396. -/* match the current token and get another
  1397. -    (actually just get another) */
  1398. -
  1399. -void matchit(void)
  1400. -{
  1401. -    do
  1402. -        gettok();
  1403. -    while (exalias());
  1404. -}
  1405. -
  1406. -int len = 0,bsiz = 256;
  1407. -char *bptr;
  1408. -
  1409. -/* add a char to the string buffer */
  1410. -
  1411. -void add(int c)
  1412. -{
  1413. -    *bptr++ = c;
  1414. -    if (bsiz == ++len)
  1415. -        bptr = len+(tstr = realloc(tstr,bsiz *= 2));
  1416. -}
  1417. -
  1418. -/* get a token */
  1419. -
  1420. -void gettok(void)
  1421. -{
  1422. -int bct = 0,pct = 0;
  1423. -int c,d,intpos = 1;
  1424. -static int dbparens = 0;
  1425. -
  1426. -beginning:
  1427. -    hlastw = NULL;
  1428. -    tstr = NULL;
  1429. -    while (zspace(c = hgetc()) || c == '\t' || c == ' ');
  1430. -    firstln = 0;
  1431. -    hwbegin();
  1432. -    hwaddc(c);
  1433. -    if (dbparens)    /* handle ((...)) */
  1434. -        {
  1435. -        int pct = 2;
  1436. -
  1437. -        peek = STRING;
  1438. -        len = dbparens = 0;
  1439. -        bptr = tstr = zalloc(bsiz = 256);
  1440. -        for (;;)
  1441. -            {
  1442. -            if (c == '(')
  1443. -                pct++;
  1444. -            else if (c == ')')
  1445. -                pct--;
  1446. -            else if (c == '\n')
  1447. -                {
  1448. -                zerr("parse error: )) expected");
  1449. -                peek = HERR;
  1450. -                free(tstr);
  1451. -                return;
  1452. -                }
  1453. -            else if (c == '$')
  1454. -                c = Qstring;
  1455. -            if (pct >= 2)
  1456. -                add(c);
  1457. -            if (pct)
  1458. -                c = hgetc();
  1459. -            else
  1460. -                break;
  1461. -            }
  1462. -        *bptr = '\0';
  1463. -        return;
  1464. -        }
  1465. -    peekfd = -1;
  1466. -    if (isdigit(c))    /* handle 1< foo */
  1467. -        {
  1468. -        d = hgetc();
  1469. -        hungetc(d);
  1470. -        if (d == '>' || d == '<')
  1471. -            {
  1472. -            peekfd = c-'0';
  1473. -            c = hgetc();
  1474. -            }
  1475. -        }
  1476. -
  1477. -    /* chars in initial position in word */
  1478. -
  1479. -    switch (c)
  1480. -        {
  1481. -        case '\\':
  1482. -            d = hgetc();
  1483. -            if (d == '\n')
  1484. -                goto beginning;
  1485. -            hungetc(d);
  1486. -            break;
  1487. -        case EOF:
  1488. -            peek = EOF;
  1489. -            return;
  1490. -        case HERR:
  1491. -            peek = HERR;
  1492. -            return;
  1493. -        case '\n':
  1494. -            peek = NEWLIN;
  1495. -            return;
  1496. -        case ';':
  1497. -            d = hgetc();
  1498. -            if (d != ';')
  1499. -                {
  1500. -                hungetc(d);
  1501. -                peek = SEMI;
  1502. -                }
  1503. -            else
  1504. -                peek = DSEMI;
  1505. -            return;
  1506. -        case '!':
  1507. -            if (!incmd)
  1508. -                {
  1509. -                peek = BANG;
  1510. -                return;
  1511. -                }
  1512. -            break;
  1513. -        case '&':
  1514. -            d = hgetc();
  1515. -            if (d != '&')
  1516. -                {
  1517. -                hungetc(d);
  1518. -                peek = AMPER;
  1519. -                }
  1520. -            else
  1521. -                peek = DAMPER;
  1522. -            return;
  1523. -        case '|':
  1524. -            d = hgetc();
  1525. -            if (d == '|')
  1526. -                peek = DBAR;
  1527. -            else if (d == '&')
  1528. -                peek = BARAMP;
  1529. -            else
  1530. -                {
  1531. -                hungetc(d);
  1532. -                peek = BAR;
  1533. -                }
  1534. -            return;
  1535. -        case '(':
  1536. -            if (incmd)
  1537. -                break;
  1538. -            d = hgetc();
  1539. -            if (d == '(')
  1540. -                {
  1541. -                peek = STRING;
  1542. -                tstr = strdup("let");
  1543. -                dbparens = 1;
  1544. -                return;
  1545. -                }
  1546. -            hungetc(d);
  1547. -            peek = INPAR;
  1548. -            return;
  1549. -        case ')':
  1550. -            peek = OUTPAR;
  1551. -            return;
  1552. -        case '{':
  1553. -            if (incmd)
  1554. -                break;
  1555. -            peek = INBRACE;
  1556. -            return;
  1557. -        case '}':
  1558. -            peek = OUTBRACE;
  1559. -            return;
  1560. -        case '<':
  1561. -            d = hgetc();
  1562. -            if (incmd && d == '(')
  1563. -                {
  1564. -                hungetc(d);
  1565. -                break;
  1566. -                }
  1567. -            else if (d == '<')
  1568. -                {
  1569. -                int e = hgetc();
  1570. -
  1571. -                hungetc(e);
  1572. -                if (e == '(')
  1573. -                    {
  1574. -                    hungetc(d);
  1575. -                    peek = INANG;
  1576. -                    }
  1577. -                else
  1578. -                    peek = DINANG;
  1579. -                }
  1580. -            else if (d == '&')
  1581. -                peek = INANGAMP;
  1582. -            else
  1583. -                {
  1584. -                peek = INANG;
  1585. -                hungetc(d);
  1586. -                }
  1587. -            return;
  1588. -        case '>':
  1589. -            d = hgetc();
  1590. -            if (d == '(')
  1591. -                {
  1592. -                hungetc(d);
  1593. -                break;
  1594. -                }
  1595. -            else if (d == '&')
  1596. -                {
  1597. -                d = hgetc();
  1598. -                if (d == '!')
  1599. -                    peek = OUTANGAMPBANG;
  1600. -                else
  1601. -                    {
  1602. -                    hungetc(d);
  1603. -                    peek = OUTANGAMP;
  1604. -                    }
  1605. -                }
  1606. -            else if (d == '!')
  1607. -                peek = OUTANGBANG;
  1608. -            else if (d == '>')
  1609. -                {
  1610. -                d = hgetc();
  1611. -                if (d == '&')
  1612. -                    {
  1613. -                    d = hgetc();
  1614. -                    if (d == '!')
  1615. -                        peek = DOUTANGAMPBANG;
  1616. -                    else
  1617. -                        {
  1618. -                        hungetc(d);
  1619. -                        peek = DOUTANGAMP;
  1620. -                        }
  1621. -                    }
  1622. -                else if (d == '!')
  1623. -                    peek = DOUTANGBANG;
  1624. -                else if (d == '(')
  1625. -                    {
  1626. -                    hungetc(d);
  1627. -                    hungetc('>');
  1628. -                    peek = OUTANG;
  1629. -                    }
  1630. -                else
  1631. -                    {
  1632. -                    hungetc(d);
  1633. -                    peek = DOUTANG;
  1634. -                    }
  1635. -                }
  1636. -            else
  1637. -                {
  1638. -                hungetc(d);
  1639. -                peek = OUTANG;
  1640. -                }
  1641. -            return;
  1642. -        case '#':
  1643. -#ifndef INTERACTIVE_COMMENTS
  1644. -            if (interact)
  1645. -                break;
  1646. -#endif
  1647. -            while ((c = hgetch()) != '\n' && !istok(c) && c != EOF);
  1648. -            if (c == '\n')
  1649. -                peek = NEWLIN;
  1650. -            else
  1651. -                errflag = 1;
  1652. -            return;
  1653. -        }
  1654. -
  1655. -    /* we've started a string, now get the rest of it, performing
  1656. -        tokenization */
  1657. -
  1658. -    peek = STRING;
  1659. -    len = 0;
  1660. -    bptr = tstr = zalloc(bsiz = 256);
  1661. -    for(;;)
  1662. -        {
  1663. -        if (c == ';' || c == '&' || c == EOF ||
  1664. -                c == HERR || c == '\03' || c == '\n' || 
  1665. -                c == ' ' || c == '\t' || znspace(c))
  1666. -            break;
  1667. -        if (c == '#')
  1668. -            c = Pound;
  1669. -        else if (c == ')')
  1670. -            {
  1671. -            if (!pct)
  1672. -                break;
  1673. -            pct--;
  1674. -            c = Outpar;
  1675. -            }
  1676. -        else if (c == ',')
  1677. -            c = Comma;
  1678. -        else if (c == '|')
  1679. -            {
  1680. -            if (!pct)
  1681. -                break;
  1682. -            c = Bar;
  1683. -            }
  1684. -        else if (c == '$')
  1685. -            {
  1686. -            d = hgetc();
  1687. -
  1688. -            c = String;
  1689. -            if (d == '[')
  1690. -                {
  1691. -                add(String);
  1692. -                add(Inbrack);
  1693. -                while ((c = hgetc()) != ']' && !istok(c) && c != EOF)
  1694. -                    add(c);
  1695. -                c = Outbrack;
  1696. -                }
  1697. -            else if (d == '(')
  1698. -                {
  1699. -                add(String);
  1700. -                skipcomm();
  1701. -                c = Outpar;
  1702. -                }
  1703. -            else
  1704. -                hungetc(d);
  1705. -            }
  1706. -        else if (c == '^')
  1707. -            c = Hat;
  1708. -        else if (c == '[')
  1709. -            c = Inbrack;
  1710. -        else if (c == ']')
  1711. -            c = Outbrack;
  1712. -        else if (c == '*')
  1713. -            c = Star;
  1714. -        else if (intpos && c == '~')
  1715. -            c = Tilde;
  1716. -        else if (c == '?')
  1717. -            c = Quest;
  1718. -        else if (c == '(')
  1719. -            {
  1720. -            int d = hgetc();
  1721. -
  1722. -            hungetc(d);
  1723. -            if (!incmd)
  1724. -                break;
  1725. -#if 0
  1726. -            if (d != ')' && intpos)
  1727. -                {
  1728. -                add(Inang);
  1729. -                skipcomm();
  1730. -                c = Outpar;
  1731. -                }
  1732. -            else
  1733. -#endif
  1734. -                {
  1735. -                pct++;
  1736. -                c = Inpar;
  1737. -                }
  1738. -            }
  1739. -        else if (c == '{')
  1740. -            {
  1741. -            c = Inbrace;
  1742. -            bct++;
  1743. -            }
  1744. -        else if (c == '}')
  1745. -            {
  1746. -            if (!bct)
  1747. -                break;
  1748. -            c = Outbrace;
  1749. -            bct--;
  1750. -            }
  1751. -        else if (c == '>')
  1752. -            {
  1753. -            d = hgetc();
  1754. -            if (d != '(')
  1755. -                {
  1756. -                hungetc(d);
  1757. -                break;
  1758. -                }
  1759. -            add(Outang);
  1760. -            skipcomm();
  1761. -            c = Outpar;
  1762. -            }
  1763. -        else if (c == '<')
  1764. -            {
  1765. -            d = hgetc();
  1766. -            if (!(isdigit(d) || d == '-' || d == '>' || d == '(' || d == ')'))
  1767. -                {
  1768. -                hungetc(d);
  1769. -                break;
  1770. -                }
  1771. -            c = Inang;
  1772. -            if (d == '(')
  1773. -                {
  1774. -                add(c);
  1775. -                skipcomm();
  1776. -                c = Outpar;
  1777. -                }
  1778. -            else if (d == ')')
  1779. -                hungetc(d);
  1780. -            else
  1781. -                {
  1782. -                add(c);
  1783. -                c = d;
  1784. -                while (c != '>' && !istok(c) && c != EOF)
  1785. -                    add(c),c = hgetc();
  1786. -                if (c == EOF)
  1787. -                    {
  1788. -                    errflag = 1;
  1789. -                    peek = EOF;
  1790. -                    return;
  1791. -                    }
  1792. -                c = Outang;
  1793. -                }
  1794. -            }
  1795. -        else if (c == '=')
  1796. -            {
  1797. -            if (intpos)
  1798. -                {
  1799. -                d = hgetc();
  1800. -                if (d != '(')
  1801. -                    {
  1802. -                    hungetc(d);
  1803. -                    c = Equals;
  1804. -                    }
  1805. -                else
  1806. -                    {
  1807. -                    add(Equals);
  1808. -                    skipcomm();
  1809. -                    c = Outpar;
  1810. -                    }
  1811. -                }
  1812. -            else if (peek != ENVSTRING)
  1813. -                {
  1814. -                peek = ENVSTRING;
  1815. -                intpos = 2;
  1816. -                }
  1817. -            }
  1818. -        else if (c == '\\')
  1819. -            {
  1820. -            c = hgetc();
  1821. -
  1822. -            if (c == '\n')
  1823. -                {
  1824. -                c = hgetc();
  1825. -                continue;
  1826. -                }
  1827. -            add(c);
  1828. -            c = hgetc();
  1829. -            continue;
  1830. -            }
  1831. -        else if (c == '\'')
  1832. -            {
  1833. -            add(Nularg);
  1834. -
  1835. -            /* we add the Nularg to prevent this:
  1836. -
  1837. -            echo $PA'TH'
  1838. -
  1839. -            from printing the path. */
  1840. -
  1841. -            while ((c = hgetc()) != '\'' && !istok(c) && c != EOF)
  1842. -                add(c);
  1843. -            if (c == EOF)
  1844. -                {
  1845. -                errflag = 1;
  1846. -                peek = EOF;
  1847. -                return;
  1848. -                }
  1849. -            c = Nularg;
  1850. -            }
  1851. -        else if (c == HQUOT)
  1852. -            {
  1853. -            add(Nularg);
  1854. -            while ((c = hgetc()) != HQUOT && !istok(c) && c != EOF)
  1855. -                add(c);
  1856. -            if (c == EOF)
  1857. -                {
  1858. -                errflag = 1;
  1859. -                peek = EOF;
  1860. -                return;
  1861. -                }
  1862. -            c = Nularg;
  1863. -            }
  1864. -        else if (c == '\"')
  1865. -            {
  1866. -            add(Nularg);
  1867. -            while ((c = hgetc()) != '\"' && !istok(c) && c != EOF)
  1868. -                if (c == '\\')
  1869. -                    {
  1870. -                    c = hgetc();
  1871. -                    if (c != '\n')
  1872. -                        {
  1873. -                        if (c != '$' && c != '\\' && c != '\"' && c != '`')
  1874. -                            add('\\');
  1875. -                        add(c);
  1876. -                        }
  1877. -                    }
  1878. -                else
  1879. -                    {
  1880. -                    if (c == '$')
  1881. -                        {
  1882. -                        int d = hgetc();
  1883. -
  1884. -                        if (d == '(')
  1885. -                            {
  1886. -                            add(Qstring);
  1887. -                            skipcomm();
  1888. -                            c = Outpar;
  1889. -                            }
  1890. -                        else if (d == '[')
  1891. -                            {
  1892. -                            add(String);
  1893. -                            add(Inbrack);
  1894. -                            while ((c = hgetc()) != ']' && c != EOF)
  1895. -                                add(c);
  1896. -                            c = Outbrack;
  1897. -                            }
  1898. -                        else
  1899. -                            {
  1900. -                            c = Qstring;
  1901. -                            hungetc(d);
  1902. -                            }
  1903. -                        }
  1904. -                    else if (c == '`')
  1905. -                        c = Qtick;
  1906. -                    add(c);
  1907. -                    }
  1908. -            if (c == EOF)
  1909. -                {
  1910. -                errflag = 1;
  1911. -                peek = EOF;
  1912. -                return;
  1913. -                }
  1914. -            c = Nularg;
  1915. -            }
  1916. -        else if (c == '`')
  1917. -            {
  1918. -            add(Tick);
  1919. -            while ((c = hgetc()) != '`' && !istok(c) && c != EOF)
  1920. -                if (c == '\\')
  1921. -                    {
  1922. -                    c = hgetc();
  1923. -                    if (c != '\n')
  1924. -                        {
  1925. -                        if (c != '`' && c != '\\' && c != '$')
  1926. -                            add('\\');
  1927. -                        add(c);
  1928. -                        }
  1929. -                    }
  1930. -                else
  1931. -                    {
  1932. -                    if (c == '$')
  1933. -                        c = String;
  1934. -                    add(c);
  1935. -                    }
  1936. -            if (c == EOF)
  1937. -                {
  1938. -                errflag = 1;
  1939. -                peek = EOF;
  1940. -                return;
  1941. -                }
  1942. -            c = Tick;
  1943. -            }
  1944. -        add(c);
  1945. -        c = hgetc();
  1946. -        if (intpos)
  1947. -            intpos--;
  1948. -        }
  1949. -    if (c == HERR)
  1950. -        {
  1951. -        free(tstr);
  1952. -        peek = HERR;
  1953. -        return;
  1954. -        }
  1955. -    hungetc(c);
  1956. -    *bptr = '\0';
  1957. -}
  1958. -
  1959. -/* expand aliases, perhaps */
  1960. -
  1961. -int exalias(void)
  1962. -{
  1963. -struct anode *an;
  1964. -char *s;
  1965. -
  1966. -    s = hwadd();
  1967. -    if (alix != MAXAL && (an = gethnode(s,alhtab)) && !an->inuse &&
  1968. -            !(an->cmd && incmd && alstat != ALSTAT_MORE))
  1969. -        {
  1970. -        if (an->cmd < 0)
  1971. -            {
  1972. -            peek = DO-an->cmd-1;
  1973. -            return 0;
  1974. -            }
  1975. -        an->inuse = 1;
  1976. -        hungets(strdup(ALPOPS));
  1977. -        hungets(strdup((alstack[alix++] = an)->text));
  1978. -        alstat = 0;
  1979. -        if (tstr)
  1980. -            free(tstr);
  1981. -        return 1;
  1982. -        }
  1983. -    return 0;
  1984. -}
  1985. -
  1986. -/* != 0 if c is not a newline, but in IFS */
  1987. -
  1988. -int zspace(int c)
  1989. -{
  1990. -    if (c == '\n')
  1991. -        return 0;
  1992. -    return znspace(c);
  1993. -}
  1994. -
  1995. -/* != 0 if c is in IFS */
  1996. -
  1997. -int znspace(int c)
  1998. -{
  1999. -char *ptr = ifs;
  2000. -
  2001. -    while (*ptr)
  2002. -        if (*ptr++ == c)
  2003. -            return 1;
  2004. -    return 0;
  2005. -}
  2006. -
  2007. -/* skip (...) */
  2008. -
  2009. -void skipcomm(void)
  2010. -{
  2011. -int pct = 1,c;
  2012. -
  2013. -    c = Inpar;
  2014. -    do
  2015. -        {
  2016. -        add(c);
  2017. -reget:
  2018. -        c = hgetc();
  2019. -        if (istok(c) || c == EOF)
  2020. -            break;
  2021. -        else if (c == '(') pct++;
  2022. -        else if (c == ')') pct--;
  2023. -        else if (c == '\\')
  2024. -            {
  2025. -            add(c);
  2026. -            c = hgetc();
  2027. -            }
  2028. -        else if (c == '\'')
  2029. -            {
  2030. -            add(c);
  2031. -            while ((c = hgetc()) != '\'' && !istok(c) && c != EOF)
  2032. -                add(c);
  2033. -            }
  2034. -        else if (c == HQUOT)
  2035. -            {
  2036. -            while ((c = hgetc()) != HQUOT && !istok(c) && c != EOF)
  2037. -                add(c);
  2038. -            goto reget;
  2039. -            }
  2040. -        else if (c == '\"')
  2041. -            {
  2042. -            add(c);
  2043. -            while ((c = hgetc()) != '\"' && !istok(c) && c != EOF)
  2044. -                if (c == '\\')
  2045. -                    {
  2046. -                    add(c);
  2047. -                    add(hgetc());
  2048. -                    }
  2049. -                else add(c);
  2050. -            }
  2051. -        else if (c == '`')
  2052. -            {
  2053. -            add(c);
  2054. -            while ((c = hgetc()) != '`' && c != HERR && c != EOF)
  2055. -                if (c == '\\') add(c), add(hgetc());
  2056. -                else add(c);
  2057. -            }
  2058. -        }
  2059. -    while(pct);
  2060. -}
  2061. -
  2062. End of lex.c
  2063. echo lex.pro 1>&2
  2064. sed 's/^-//' >lex.pro <<'End of lex.pro'
  2065. -void matchit(void);
  2066. -void add(int c);
  2067. -void gettok(void);
  2068. -int exalias(void);
  2069. -int zspace(int c);
  2070. -int znspace(int c);
  2071. -void skipcomm(void);
  2072. End of lex.pro
  2073. echo loop.c 1>&2
  2074. sed 's/^-//' >loop.c <<'End of loop.c'
  2075. -/*
  2076. -
  2077. -    loop.c - parsing and executing loop constructs
  2078. -
  2079. -    This file is part of zsh, the Z shell.
  2080. -
  2081. -   zsh is free software; no one can prevent you from reading the source
  2082. -   code, or giving it to someone else.
  2083. -   This file is copyrighted under the GNU General Public License, which
  2084. -   can be found in the file called COPYING.
  2085. -
  2086. -   Copyright (C) 1990 Paul Falstad
  2087. -
  2088. -   zsh is distributed in the hope that it will be useful, but
  2089. -   WITHOUT ANY WARRANTY.  No author or distributor accepts
  2090. -   responsibility to anyone for the consequences of using it or for
  2091. -   whether it serves any particular purpose or works at all, unless he
  2092. -   says so in writing.  Refer to the GNU General Public License
  2093. -   for full details.
  2094. -
  2095. -   Everyone is granted permission to copy, modify and redistribute
  2096. -   zsh, but only under the conditions described in the GNU General Public
  2097. -   License.   A copy of this license is supposed to have been given to you
  2098. -   along with zsh so you can know your rights and responsibilities.
  2099. -   It should be in a file named COPYING.
  2100. -
  2101. -   Among other things, the copyright notice and this notice must be
  2102. -   preserved on all copies.
  2103. -
  2104. -*/
  2105. -
  2106. -#include "zsh.h"
  2107. -#include "funcs.h"
  2108. -
  2109. -/* parse a for/select loop */
  2110. -
  2111. -int parfor(comm comm,int isfor)
  2112. -{
  2113. -struct fornode *node = alloc(sizeof(struct fornode));
  2114. -char *comnam = (isfor) ? "for" : "select";
  2115. -
  2116. -    comm->type = (isfor) ? CFOR : CSELECT;
  2117. -    comm->info = node;
  2118. -    if (peek != STRING)
  2119. -        {
  2120. -        zerr("parse error in %s: identifier expected",comnam);
  2121. -        errflag = 1;
  2122. -        return 0;
  2123. -        }
  2124. -    node->name = tstr;
  2125. -    matchit();
  2126. -    node->list = NULL;
  2127. -    node->inflag = 0;
  2128. -    if (peek == STRING && !strcmp("in",tstr))
  2129. -       {
  2130. -        node->inflag = 1;
  2131. -        free(tstr);
  2132. -        matchit();
  2133. -        while (peek == STRING)
  2134. -            {
  2135. -            addnode(comm->args,tstr);
  2136. -            matchit();
  2137. -            }
  2138. -        }
  2139. -    if (peek != NEWLIN && peek != SEMI)
  2140. -        {
  2141. -        zerr("parse error: bad token in '%s' list",comnam);
  2142. -        freecmd(comm);
  2143. -        return 1;
  2144. -        }
  2145. -    incmd = 0;
  2146. -    matchit();
  2147. -    while (peek == NEWLIN)
  2148. -        matchit();
  2149. -    if (peek != DO)
  2150. -        {
  2151. -        zerr("parse error: 'do' expected");
  2152. -        freecmd(comm);
  2153. -        return 1;
  2154. -        }
  2155. -    matchit();
  2156. -    if (!(node->list = parlist(1)))
  2157. -        {
  2158. -        freecmd(comm);
  2159. -        return 1;
  2160. -        }
  2161. -    if (peek != DONE)
  2162. -        {
  2163. -        zerr("parse error: 'done' expected");
  2164. -        freecmd(comm);
  2165. -        return 1;
  2166. -        }
  2167. -    matchit();
  2168. -    return 0;
  2169. -}
  2170. -int parcase(comm comm)
  2171. -{
  2172. -struct casenode *node = alloc(sizeof(struct casenode)),*last = NULL;
  2173. -char *tok; /* add FREES to this function */
  2174. -
  2175. -    comm->type = CCASE;
  2176. -    comm->info = node;
  2177. -    if (peek != STRING)
  2178. -        {
  2179. -        zerr("parse error in case: identifier expected");
  2180. -        errflag = 1;
  2181. -        return 0;
  2182. -        }
  2183. -    addnode(comm->args,tstr);
  2184. -    matchit();
  2185. -    if (peek != STRING || strcmp(tstr,"in"))
  2186. -        {
  2187. -        zerr("parse error in case: `in' expected");
  2188. -        errflag = 1;
  2189. -        return 0;
  2190. -        }
  2191. -    while (tok = getcasepat())
  2192. -        {
  2193. -        node = alloc(sizeof(struct casenode));
  2194. -        node->pat = tok;
  2195. -        if (last)
  2196. -            last->next = node;
  2197. -        else
  2198. -            comm->info = node;
  2199. -        (last = node)->list = parlist(1);
  2200. -        if (peek != DSEMI)
  2201. -            {
  2202. -            zerr("parse error: ;; expected");
  2203. -            return 1;
  2204. -            }
  2205. -        }
  2206. -    if (!last)
  2207. -        {
  2208. -        zerr("null case construct");
  2209. -        return 1;
  2210. -        }
  2211. -    return 0;
  2212. -}
  2213. -
  2214. -/* get a case pattern: foo) */
  2215. -
  2216. -char *getcasepat(void)
  2217. -{
  2218. -int c,bsiz = 256,ct = 0,pct = 0,qt = 0;
  2219. -char *buf = zalloc(bsiz),*ptr,*s;
  2220. -    peek = EMPTY;
  2221. -    while (znspace(c = hgetc()))
  2222. -        {
  2223. -        if (c == '\n')
  2224. -            {
  2225. -            hwbegin();
  2226. -            hwaddc('\n');
  2227. -            hwadd();
  2228. -            }
  2229. -        }
  2230. -    ptr = buf;
  2231. -    hwbegin();
  2232. -    hwaddc(c);
  2233. -    while (c != ')' || pct)
  2234. -        {
  2235. -        for (s = tokens; *s; s++)
  2236. -            if (*s == c)
  2237. -                {
  2238. -                c = (s-tokens)+Pound;
  2239. -                break;
  2240. -                }
  2241. -        if (qt)
  2242. -            {
  2243. -            if (c == '\'')
  2244. -                {
  2245. -                qt = 0;
  2246. -                c = hgetc();
  2247. -                continue;
  2248. -                }
  2249. -            if (c == EOF)
  2250. -                {
  2251. -                qt = 0;
  2252. -                continue;
  2253. -                }
  2254. -            }
  2255. -        else
  2256. -            {
  2257. -            if (c == '\\')
  2258. -                c = hgetc();
  2259. -            if (c == '\'')
  2260. -                {
  2261. -                qt = 1;
  2262. -                c = hgetc();
  2263. -                continue;
  2264. -                }
  2265. -            if (c == Inpar)
  2266. -                pct++;
  2267. -            if (c == Outpar)
  2268. -                pct--;
  2269. -            if (ct == 4 && (znspace(c)||c ==';'||c=='&') && !strncmp(buf,"esac",4))
  2270. -                {
  2271. -                hungetc(c);
  2272. -                hwadd();
  2273. -                free(buf);
  2274. -                matchit();
  2275. -                return NULL;
  2276. -                }
  2277. -            if (c == '\n' || c == EOF)
  2278. -                {
  2279. -                free(buf);
  2280. -                zerr("parse error: 'esac' expected");
  2281. -                return NULL;
  2282. -                }
  2283. -            }
  2284. -        if (c == HERR)
  2285. -            {
  2286. -            free(buf);
  2287. -            return NULL;
  2288. -            }
  2289. -        *ptr++ = c;
  2290. -        if (++ct == bsiz)
  2291. -            {
  2292. -            ptr = zalloc(bsiz *= 2);
  2293. -            memcpy(ptr,buf,ct);
  2294. -            free(buf);
  2295. -            buf = ptr;
  2296. -            ptr = buf+ct;
  2297. -            }
  2298. -        c = hgetc();
  2299. -        }
  2300. -    *ptr = 0;
  2301. -    hwadd();
  2302. -    return buf;
  2303. -}
  2304. -int parif(comm comm)
  2305. -{
  2306. -struct ifnode *node = alloc(sizeof(struct ifnode));
  2307. -    comm->type = CIF;
  2308. -    comm->info = node;
  2309. -do_then:
  2310. -    node->next = NULL;
  2311. -    if (!(node->ifl = parlist(1)))
  2312. -        {
  2313. -        freecmd(comm);
  2314. -        return 1;
  2315. -        }
  2316. -    if (peek != THEN)
  2317. -        {
  2318. -        zerr("parse error: 'then' expected");
  2319. -        freecmd(comm);
  2320. -        return 1;
  2321. -        }
  2322. -    matchit();
  2323. -    if (!(node->thenl = parlist(1)))
  2324. -        {
  2325. -        freecmd(comm);
  2326. -        return 1;
  2327. -        }
  2328. -    if (peek == ELIF)
  2329. -        {
  2330. -        matchit();
  2331. -        node = node->next = alloc(sizeof(struct ifnode));
  2332. -        goto do_then;
  2333. -        }
  2334. -    else if (peek == ELSE)
  2335. -        {
  2336. -        matchit();
  2337. -        node = node->next = alloc(sizeof(struct ifnode));
  2338. -        node->next = NULL;
  2339. -        node->ifl = NULL;
  2340. -        if (!(node->thenl = parlist(1)))
  2341. -            {
  2342. -            freecmd(comm);
  2343. -            return 1;
  2344. -            }
  2345. -        }
  2346. -    if (peek != FI)
  2347. -        {
  2348. -        zerr("parse error: 'fi' expected");
  2349. -        freecmd(comm);
  2350. -        return 1;
  2351. -        }
  2352. -    matchit();
  2353. -    return 0;
  2354. -}
  2355. -
  2356. -/* parse while or until */
  2357. -
  2358. -int parwhile(comm comm,int cond)
  2359. -{
  2360. -struct whilenode *node = alloc(sizeof (struct whilenode));
  2361. -    comm->type = CWHILE;
  2362. -    comm->info = node;
  2363. -    node->cond = cond;
  2364. -    node->loop = node->cont = NULL;
  2365. -    if (!(node->cont = parlist(1)))
  2366. -        {
  2367. -        freecmd(comm);
  2368. -        return NULL;
  2369. -        }
  2370. -    if (peek != DO)
  2371. -        {
  2372. -        zerr("parse error: 'do' expected");
  2373. -        freecmd(comm);
  2374. -        return 1;
  2375. -        }
  2376. -    matchit();
  2377. -    node->loop = parlist(1);
  2378. -    if (peek != DONE)
  2379. -        {
  2380. -        zerr("parse error: 'done' expected");
  2381. -        freecmd(comm);
  2382. -        return 1;
  2383. -        }
  2384. -    matchit();
  2385. -    return 0;
  2386. -}
  2387. -int parrepeat(comm comm)
  2388. -{
  2389. -struct repeatnode *node = alloc(sizeof (struct repeatnode));
  2390. -
  2391. -    comm->type = CREPEAT;
  2392. -    comm->info = node;
  2393. -    node->list = NULL;
  2394. -    if (peek != STRING || !isdigit(*tstr))
  2395. -        {
  2396. -        zerr("parse error: number expected");
  2397. -        freecmd(comm);
  2398. -        return 1;
  2399. -        }
  2400. -    node->count = atoi(tstr);
  2401. -    free(tstr);
  2402. -    incmd = 0;
  2403. -    do
  2404. -        matchit();
  2405. -    while (peek == NEWLIN);
  2406. -    if (peek != DO)
  2407. -        {
  2408. -        zerr("parse error: 'do' expected");
  2409. -        freecmd(comm);
  2410. -        return 1;
  2411. -        }
  2412. -    matchit();
  2413. -    node->list = parlist(1);
  2414. -    if (peek != DONE)
  2415. -        {
  2416. -        zerr("parse error: 'done' expected");
  2417. -        freecmd(comm);
  2418. -        return 1;
  2419. -        }
  2420. -    matchit();
  2421. -    return 0;
  2422. -}
  2423. -
  2424. -void execfor(comm comm)
  2425. -{
  2426. -list list;
  2427. -struct fornode *node;
  2428. -char *str;
  2429. -table args;
  2430. -int cj = curjob;
  2431. -
  2432. -    loops++;
  2433. -    exiting = 0;
  2434. -    node = comm->info;
  2435. -    args = comm->args;
  2436. -    if (!node->inflag)
  2437. -        {
  2438. -        args = duptable(pparms,dupstr);
  2439. -        freestr(getnode(args));
  2440. -        }
  2441. -    while (str = getnode(args))
  2442. -        {
  2443. -        setparm(strdup(node->name),str,0,0);
  2444. -        list = duplist(node->list);
  2445. -        execlist(list);
  2446. -        if (breaks)
  2447. -            {
  2448. -            breaks--;
  2449. -            if (breaks || !contflag)
  2450. -                break;
  2451. -            contflag = 0;
  2452. -            }
  2453. -        }
  2454. -    curjob = cj;
  2455. -}
  2456. -
  2457. -void execselect(comm comm)
  2458. -{
  2459. -list list;
  2460. -struct fornode *node;
  2461. -char *str,*s;
  2462. -table args;
  2463. -Node n;
  2464. -int cj = curjob,t0;
  2465. -
  2466. -    loops++;
  2467. -    node = comm->info;
  2468. -    args = comm->args;
  2469. -    exiting = 0;
  2470. -    for (;;)
  2471. -        {
  2472. -        do
  2473. -            {
  2474. -            for (t0 = 1,n = args->first; n; n=n->next,t0++)
  2475. -                fprintf(stderr,"%d %s\n",t0,n->dat);
  2476. -            if (interact && SHTTY != -1)
  2477. -                {
  2478. -                inittty();
  2479. -                str = readline(putprompt("PROMPT3"));
  2480. -                }
  2481. -            else
  2482. -                str = fgets(zalloc(256),256,bshin);
  2483. -            if (!str || errflag)
  2484. -                {
  2485. -                fprintf(stderr,"\n");
  2486. -                goto done;
  2487. -                }
  2488. -            if (s = strchr(str,'\n'))
  2489. -                *s = '\0';
  2490. -            }
  2491. -        while (!*str);
  2492. -        setparm(strdup("REPLY"),str,0,0);
  2493. -        t0 = atoi(str);
  2494. -        if (!t0)
  2495. -            str = "";
  2496. -        else
  2497. -            {
  2498. -            for (t0--,n = args->first; n && t0; n=n->next,t0--);
  2499. -            if (n)
  2500. -                str = n->dat;
  2501. -            else
  2502. -                str = "";
  2503. -            }
  2504. -        setparm(strdup(node->name),strdup(str),0,0);
  2505. -        list = duplist(node->list);
  2506. -        execlist(list);
  2507. -        if (breaks)
  2508. -            {
  2509. -            breaks--;
  2510. -            if (breaks || !contflag)
  2511. -                break;
  2512. -            contflag = 0;
  2513. -            }
  2514. -        if (errflag)
  2515. -            break;
  2516. -        }
  2517. -done:
  2518. -    curjob = cj;
  2519. -}
  2520. -void execwhile(comm comm)
  2521. -{
  2522. -list list;
  2523. -struct whilenode *node;
  2524. -int cj = curjob; 
  2525. -
  2526. -    loops++;
  2527. -    node = comm->info;
  2528. -    exiting = 0;
  2529. -    FOREVER
  2530. -        {
  2531. -        list = duplist(node->cont);
  2532. -        execlist(list);
  2533. -        if (!((lastval == 0) ^ node->cond))
  2534. -            break;
  2535. -        if (breaks)
  2536. -            {
  2537. -            breaks--;
  2538. -            if (breaks || !contflag)
  2539. -                break;
  2540. -            contflag = 0;
  2541. -            }
  2542. -        list = duplist(node->loop);
  2543. -        execlist(list);
  2544. -        }
  2545. -    curjob = cj;
  2546. -}
  2547. -void execrepeat(comm comm)
  2548. -{
  2549. -list list;
  2550. -struct repeatnode *node;
  2551. -int cj = curjob;
  2552. -
  2553. -    loops++;
  2554. -    node = comm->info;
  2555. -    exiting = 0;
  2556. -    while (node->count--)
  2557. -        {
  2558. -        list = duplist(node->list);
  2559. -        execlist(list);
  2560. -        if (breaks)
  2561. -            {
  2562. -            breaks--;
  2563. -            if (breaks || !contflag)
  2564. -                break;
  2565. -            contflag = 0;
  2566. -            }
  2567. -        if (lastval)
  2568. -            break;
  2569. -        }
  2570. -    curjob = cj;
  2571. -}
  2572. -void execif(comm comm)
  2573. -{
  2574. -list list;
  2575. -struct ifnode *node;
  2576. -int cj = curjob;
  2577. -
  2578. -    node = comm->info;
  2579. -    exiting = 0;
  2580. -    while (node)
  2581. -        {
  2582. -        if (node->ifl)
  2583. -            {
  2584. -            list = duplist(node->ifl);
  2585. -            execlist(list);
  2586. -            if (lastval)
  2587. -                {
  2588. -                node = node->next;
  2589. -                continue;
  2590. -                }
  2591. -            }
  2592. -        list = duplist(node->thenl);
  2593. -        execlist(list);
  2594. -        break;
  2595. -        }
  2596. -    curjob = cj;
  2597. -}
  2598. -void execcase(comm comm)
  2599. -{
  2600. -list list;
  2601. -struct casenode *node;
  2602. -char *word;
  2603. -table args;
  2604. -int cj = curjob;
  2605. -
  2606. -    node = comm->info;
  2607. -    args = comm->args;
  2608. -    exiting = 0;
  2609. -    if (!args->first || args->first->next)
  2610. -        {
  2611. -        zerr("bad case statement");
  2612. -        errflag = 1;
  2613. -        return;
  2614. -        }
  2615. -    word = args->first->dat;
  2616. -    while (node)
  2617. -        if (matchpat(word,node->pat))
  2618. -            break;
  2619. -        else
  2620. -            node = node->next;
  2621. -    if (node)
  2622. -        {
  2623. -        list = duplist(node->list);
  2624. -        execlist(list);
  2625. -        }
  2626. -    curjob = cj;
  2627. -}
  2628. -list duplist(list xlist)
  2629. -{
  2630. -list nlist;
  2631. -    if (!xlist)
  2632. -        return NULL;
  2633. -    nlist = alloc(sizeof(struct lnode));
  2634. -    nlist->left = duplist2(xlist->left);
  2635. -    nlist->right = duplist(xlist->right);
  2636. -    nlist->type = xlist->type;
  2637. -    return nlist;
  2638. -}
  2639. -
  2640. -void freelist(list xlist)
  2641. -{
  2642. -    if (xlist)
  2643. -        {
  2644. -        freelist2(xlist->left);
  2645. -        freelist(xlist->right);
  2646. -        free(xlist);
  2647. -        }
  2648. -}
  2649. -
  2650. -list2 duplist2(list2 x)
  2651. -{
  2652. -list2 y;
  2653. -
  2654. -    if (!x)
  2655. -        return NULL;
  2656. -    y = alloc(sizeof(struct l2node));
  2657. -    *y = *x;
  2658. -    y->left = duppline(x->left);
  2659. -    y->right = duplist2(x->right);
  2660. -    return y;
  2661. -}
  2662. -
  2663. -void freelist2(list2 x)
  2664. -{
  2665. -    if (x)
  2666. -        {
  2667. -        freepline(x->left);
  2668. -        freelist2(x->right);
  2669. -        free(x);
  2670. -        }
  2671. -}
  2672. -
  2673. -pline duppline(pline xpline)
  2674. -{
  2675. -pline npline;
  2676. -    if (!xpline)
  2677. -        return NULL;
  2678. -    npline = alloc(sizeof(struct pnode));
  2679. -    npline->left = dupcomm(xpline->left);
  2680. -    npline->right = duppline(xpline->right);
  2681. -    npline->type = xpline->type;
  2682. -    return npline;
  2683. -}
  2684. -
  2685. -void freepline(pline x)
  2686. -{
  2687. -    if (x)
  2688. -        {
  2689. -        freecmd(x->left);
  2690. -        freepline(x->right);
  2691. -        free(x);
  2692. -        }
  2693. -}
  2694. -
  2695. -comm dupcomm(comm xcomm)
  2696. -{
  2697. -comm ncomm;
  2698. -void *(*duprs[])(void *) = {dupfor,dupwhile,duprepeat,dupif,dupcase};
  2699. -int type;
  2700. -    if (!xcomm)
  2701. -        return NULL;
  2702. -    ncomm = alloc(sizeof(struct cnode));
  2703. -    ncomm->left = duplist(xcomm->left);
  2704. -    ncomm->cmd = dupstr(xcomm->cmd);
  2705. -    ncomm->args = duptable(xcomm->args,dupstr);
  2706. -    ncomm->redir = duptable(xcomm->redir,dupfnode);
  2707. -    ncomm->vars = (xcomm->vars) ? duptable(xcomm->vars,dupstr) : NULL;
  2708. -    ncomm->type = type = xcomm->type;
  2709. -    if (type >= CFOR && type <= CCASE)
  2710. -        ncomm->info = (duprs[type-CFOR])(xcomm->info);
  2711. -    return ncomm;
  2712. -}
  2713. -
  2714. -void freecmd(comm x)
  2715. -{
  2716. -    if (x)
  2717. -        {
  2718. -        freelist(x->left);
  2719. -        if (x->cmd)
  2720. -            free(x->cmd);
  2721. -        if (x->args)
  2722. -            freetable(x->args,freestr);
  2723. -        if (x->redir)
  2724. -            freetable(x->redir,freeredir);
  2725. -        if (x->vars)
  2726. -            freetable(x->vars,freestr);
  2727. -/*        if (x->info)
  2728. -            freeinfo(x->info);*/
  2729. -        free(x);
  2730. -        }
  2731. -}
  2732. -
  2733. -void *dupstr(void *str)
  2734. -{
  2735. -    if (!str)
  2736. -        return NULL;
  2737. -    return strdup(str);
  2738. -}
  2739. -
  2740. -void *dupfnode(void *i)
  2741. -{
  2742. -struct fnode *fn = i,*nfn = alloc(sizeof(struct fnode));
  2743. -    if (!i)
  2744. -        return NULL;
  2745. -    *nfn = *fn;
  2746. -    if (nfn->type < HEREDOC)
  2747. -        nfn->u.name = strdup(fn->u.name);
  2748. -    return nfn;
  2749. -}
  2750. -
  2751. -void *dupfor(void *i)
  2752. -{
  2753. -struct fornode *nnode,*node = i;
  2754. -    nnode = alloc(sizeof(struct fornode));
  2755. -    *nnode = *(struct fornode *) i;
  2756. -    nnode->name = strdup(node->name);
  2757. -    nnode->list = duplist(node->list);
  2758. -    return nnode;
  2759. -}
  2760. -void *dupcase(void *i)
  2761. -{
  2762. -struct casenode *nnode,*node = i;
  2763. -    if (!i)
  2764. -        return NULL;
  2765. -    nnode = alloc(sizeof(struct casenode));
  2766. -    nnode->next = dupcase(node->next);
  2767. -    nnode->list = duplist(node->list);
  2768. -    nnode->pat = strdup(node->pat);
  2769. -    return nnode;
  2770. -}
  2771. -void *dupif(void *i)
  2772. -{
  2773. -struct ifnode *nnode,*node = i;
  2774. -    if (!i)
  2775. -        return NULL;
  2776. -    nnode = alloc(sizeof(struct ifnode));
  2777. -    nnode->next = dupif(node->next);
  2778. -    nnode->ifl = duplist(node->ifl);
  2779. -    nnode->thenl = duplist(node->thenl);
  2780. -    return nnode;
  2781. -}
  2782. -void *dupwhile(void *i)
  2783. -{
  2784. -struct whilenode *nnode,*node = i;
  2785. -    if (!i)
  2786. -        return NULL;
  2787. -    nnode = alloc(sizeof(struct whilenode));
  2788. -    nnode->cond = node->cond;
  2789. -    nnode->cont = duplist(node->cont);
  2790. -    nnode->loop = duplist(node->loop);
  2791. -    return nnode;
  2792. -}
  2793. -
  2794. -void *duprepeat(void *i)
  2795. -{
  2796. -struct repeatnode *nnode,*node = i;
  2797. -
  2798. -    if (!i)
  2799. -        return NULL;
  2800. -    nnode = alloc(sizeof(struct repeatnode));
  2801. -    nnode->count = node->count;
  2802. -    nnode->list = duplist(node->list);
  2803. -    return nnode;
  2804. -}    
  2805. -
  2806. -table duptable(table tab,void *(*func)(void *))
  2807. -{
  2808. -table ret;
  2809. -Node node;
  2810. -
  2811. -    ret = newtable();
  2812. -    for (node = tab->first; node; node = node->next)
  2813. -        addnode(ret,func(node->dat));
  2814. -    return ret;
  2815. -}
  2816. End of loop.c
  2817. echo loop.pro 1>&2
  2818. sed 's/^-//' >loop.pro <<'End of loop.pro'
  2819. -int parfor(comm comm,int isfor);
  2820. -int parcase(comm comm);
  2821. -char *getcasepat(void);
  2822. -int parif(comm comm);
  2823. -int parwhile(comm comm,int cond);
  2824. -int parrepeat(comm comm);
  2825. -void execfor(comm comm);
  2826. -void execselect(comm comm);
  2827. -void execwhile(comm comm);
  2828. -void execrepeat(comm comm);
  2829. -void execif(comm comm);
  2830. -void execcase(comm comm);
  2831. -list duplist(list xlist);
  2832. -void freelist(list xlist);
  2833. -list2 duplist2(list2 x);
  2834. -void freelist2(list2 x);
  2835. -pline duppline(pline xpline);
  2836. -void freepline(pline x);
  2837. -comm dupcomm(comm xcomm);
  2838. -void freecmd(comm x);
  2839. -void *dupstr(void *str);
  2840. -void *dupfnode(void *i);
  2841. -void *dupfor(void *i);
  2842. -void *dupcase(void *i);
  2843. -void *dupif(void *i);
  2844. -void *dupwhile(void *i);
  2845. -void *duprepeat(void *i);
  2846. -table duptable(table tab,void *(*func)(void *));
  2847. End of loop.pro
  2848. echo math.c 1>&2
  2849. sed 's/^-//' >math.c <<'End of math.c'
  2850. -/*
  2851. -
  2852. -    math.c - evaluating arithmetic expressions
  2853. -
  2854. -    This file is part of zsh, the Z shell.
  2855. -
  2856. -   zsh is free software; no one can prevent you from reading the source
  2857. -   code, or giving it to someone else.
  2858. -   This file is copyrighted under the GNU General Public License, which
  2859. -   can be found in the file called COPYING.
  2860. -
  2861. -   Copyright (C) 1990 Paul Falstad
  2862. -
  2863. -   zsh is distributed in the hope that it will be useful, but
  2864. -   WITHOUT ANY WARRANTY.  No author or distributor accepts
  2865. -   responsibility to anyone for the consequences of using it or for
  2866. -   whether it serves any particular purpose or works at all, unless he
  2867. -   says so in writing.  Refer to the GNU General Public License
  2868. -   for full details.
  2869. -
  2870. -   Everyone is granted permission to copy, modify and redistribute
  2871. -   zsh, but only under the conditions described in the GNU General Public
  2872. -   License.   A copy of this license is supposed to have been given to you
  2873. -   along with zsh so you can know your rights and responsibilities.
  2874. -   It should be in a file named COPYING.
  2875. -
  2876. -   Among other things, the copyright notice and this notice must be
  2877. -   preserved on all copies.
  2878. -
  2879. -*/
  2880. -
  2881. -#include <stdio.h>
  2882. -#include <ctype.h>
  2883. -#include <string.h>
  2884. -#include <math.h>
  2885. -#include <assert.h>
  2886. -
  2887. -extern int errflag;
  2888. -extern char *setiparm(char *,long,int);
  2889. -extern long getiparm(char *);
  2890. -extern void zerr(char *,...);
  2891. -extern char *strdup(char *);
  2892. -
  2893. -char *ptr;
  2894. -
  2895. -typedef int LV;
  2896. -
  2897. -long yyval;
  2898. -LV yylval;
  2899. -
  2900. -/* nonzero means we are not evaluating, just parsing */
  2901. -
  2902. -int noeval = 0;
  2903. -
  2904. -/* != 0 means recognize unary plus, minus, etc.
  2905. -    The parser was originally written in lex, hence the name. */
  2906. -
  2907. -int initial = 1;
  2908. -
  2909. -void mathparse(int);
  2910. -
  2911. -/* LR = left-to-right associativity
  2912. -    RL = right-to-left associativity
  2913. -    BOO = short-circuiting boolean */
  2914. -
  2915. -enum xtyp { LR,RL,BOO };
  2916. -
  2917. -enum xtok {
  2918. -INPAR, OUTPAR, NOT, COMP, POSTPLUS,
  2919. -POSTMINUS, UPLUS, UMINUS, AND, XOR,
  2920. -OR, MUL, DIV, MOD, PLUS,
  2921. -MINUS, SHLEFT, SHRIGHT, LES, LEQ,
  2922. -GRE, GEQ, DEQ, NEQ, DAND,
  2923. -DOR, DXOR, QUEST, COLON, EQ,
  2924. -PLUSEQ, MINUSEQ, MULEQ, DIVEQ, MODEQ,
  2925. -ANDEQ, XOREQ, OREQ, SHLEFTEQ, SHRIGHTEQ,
  2926. -DANDEQ, DOREQ, DXOREQ, COMMA, EOI,
  2927. -PREPLUS, PREMINUS, NUM, ID, TOKCOUNT
  2928. -};
  2929. -
  2930. -/* precedences */
  2931. -
  2932. -int prec[TOKCOUNT] = {
  2933. -1,200,2,2,2,
  2934. -2,2,2,3,4,
  2935. -5,6,6,6,7,
  2936. -7,8,8,9,9,
  2937. -9,9,10,10,11,
  2938. -12,12,13,13,14,
  2939. -14,14,14,14,14,
  2940. -14,14,14,14,14,
  2941. -14,14,14,15,200,
  2942. -2,2,0,0,
  2943. -};
  2944. -
  2945. -#define TOPPREC 15
  2946. -
  2947. -int type[TOKCOUNT] = {
  2948. -LR,LR,RL,RL,RL,
  2949. -RL,RL,RL,LR,LR,
  2950. -LR,LR,LR,LR,LR,
  2951. -LR,LR,LR,LR,LR,
  2952. -LR,LR,LR,LR,BOO,
  2953. -BOO,LR,RL,RL,RL,
  2954. -RL,RL,RL,RL,RL,
  2955. -RL,RL,RL,RL,RL,
  2956. -BOO,BOO,RL,RL,RL,
  2957. -RL,RL,LR,LR,
  2958. -};
  2959. -
  2960. -#define LVCOUNT 32
  2961. -
  2962. -/* table of lvalues (variables) */
  2963. -
  2964. -int lvc;
  2965. -char *lvals[LVCOUNT];
  2966. -
  2967. -int yylex(void)
  2968. -{
  2969. -    for(;;)
  2970. -        switch (*ptr++)
  2971. -            {
  2972. -            case '+':
  2973. -                if (*ptr == '+' && (initial || !isalnum(*ptr)))
  2974. -                    {
  2975. -                    ptr++;
  2976. -                    return (initial) ? PREPLUS : POSTPLUS;
  2977. -                    }
  2978. -                if (*ptr == '=') { initial = 1; ptr++; return PLUSEQ; }
  2979. -                return (initial) ? UPLUS : PLUS;
  2980. -            case '-':
  2981. -                if (*ptr == '-' && (initial || !isalnum(*ptr)))
  2982. -                    {
  2983. -                    ptr++;
  2984. -                    return (initial) ? PREMINUS : POSTMINUS;
  2985. -                    }
  2986. -                if (*ptr == '=') { initial = 1; ptr++; return MINUSEQ; }
  2987. -                return (initial) ? UMINUS : MINUS;
  2988. -            case '(': initial = 1; return INPAR;
  2989. -            case ')': return OUTPAR;
  2990. -            case '!': if (*ptr == '=')
  2991. -                        { initial = 1; ptr++; return NEQ; }
  2992. -                        return NOT;
  2993. -            case '~': return COMP;
  2994. -            case '&': initial = 1;
  2995. -                if (*ptr == '&') { if (*++ptr == '=')
  2996. -                { ptr++; return DANDEQ; } return DAND; }
  2997. -                else if (*ptr == '=') { ptr++; return ANDEQ; } return AND;
  2998. -            case '|': initial = 1;
  2999. -                if (*ptr == '|') { if (*++ptr == '=')
  3000. -                { ptr++; return DOREQ; } return DOR; }
  3001. -                else if (*ptr == '=') { ptr++; return OREQ; } return OR;
  3002. -            case '^': initial = 1;
  3003. -                if (*ptr == '^') { if (*++ptr == '=')
  3004. -                { ptr++; return DXOREQ; } return DXOR; }
  3005. -                else if (*ptr == '=') { ptr++; return XOREQ; } return XOR;
  3006. -            case '*': initial = 1;
  3007. -                if (*ptr == '=') { ptr++; return MULEQ; } return MUL;
  3008. -            case '/': initial = 1;
  3009. -                if (*ptr == '=') { ptr++; return DIVEQ; } return DIV;
  3010. -            case '%': initial = 1;
  3011. -                if (*ptr == '=') { ptr++; return MODEQ; } return MOD;
  3012. -            case '<': initial = 1; if (*ptr == '<')
  3013. -                { if (*++ptr == '=') { ptr++; return SHLEFTEQ; } return SHLEFT; }
  3014. -                else if (*ptr == '=') { ptr++; return LEQ; } return LES;
  3015. -            case '>': initial = 1; if (*ptr == '>')
  3016. -                { if (*++ptr == '=') { ptr++; return SHRIGHTEQ; } return SHRIGHT; }
  3017. -                else if (*ptr == '=') { ptr++; return GEQ; } return GRE;
  3018. -            case '=': initial = 1; if (*ptr == '=') { ptr++; return DEQ; }
  3019. -                return EQ;
  3020. -            case '?': initial = 1; return QUEST;
  3021. -            case ':': initial = 1; return COLON;
  3022. -            case ',': initial = 1; return COMMA;
  3023. -            case '\0': initial = 1; ptr--; return EOI;
  3024. -            case '[': initial = 0;
  3025. -                { int base = strtol(ptr,&ptr,10);
  3026. -                    yyval = strtol(ptr+1,&ptr,base); return NUM; }
  3027. -            case ' ': case '\t':
  3028. -                break;
  3029. -            default:
  3030. -                if (isdigit(*--ptr))
  3031. -                    { initial = 0; yyval = strtol(ptr,&ptr,10); return NUM; }
  3032. -                if (isalpha(*ptr) || *ptr == '$')
  3033. -                    {
  3034. -                    char *p,q;
  3035. -
  3036. -                    if (*ptr == '$')
  3037. -                        ptr++;
  3038. -                    p = ptr;
  3039. -                    if (lvc == LVCOUNT)
  3040. -                        {
  3041. -                        zerr("too many identifiers in expression");
  3042. -                        errflag = 1;
  3043. -                        return EOI;
  3044. -                        }
  3045. -                    initial = 0;
  3046. -                    while(isalpha(*++ptr));
  3047. -                    q = *ptr;
  3048. -                    *ptr = '\0';
  3049. -                    lvals[yylval = lvc++] = strdup(p);
  3050. -                    *ptr = q;
  3051. -                    return ID;
  3052. -                    }
  3053. -                zerr("illegal character: %c",*ptr);
  3054. -                errflag = 1;
  3055. -                return EOI;
  3056. -            }
  3057. -}
  3058. -
  3059. -/* the value stack */
  3060. -
  3061. -#define STACKSZ 1000
  3062. -int tok;            /* last token */
  3063. -int sp = -1;    /* stack pointer */
  3064. -struct value {
  3065. -    LV lval;
  3066. -    long val;
  3067. -    } stack[STACKSZ];
  3068. -
  3069. -void push(long val,LV lval)
  3070. -{
  3071. -    sp++;
  3072. -    stack[sp].val = val;
  3073. -    stack[sp].lval = lval;
  3074. -}
  3075. -
  3076. -long getvar(LV s)
  3077. -{
  3078. -long t;
  3079. -
  3080. -    if (!(t = getiparm(lvals[s])))
  3081. -        return 0;
  3082. -    return t;
  3083. -}
  3084. -
  3085. -long setvar(LV s,long v)
  3086. -{
  3087. -    if (s == -1)
  3088. -        {
  3089. -        zerr("lvalue required");
  3090. -        errflag = 1;
  3091. -        return 0;
  3092. -        }
  3093. -    if (noeval)
  3094. -        return v;
  3095. -    setiparm(strdup(lvals[s]),v,0);
  3096. -    return v;
  3097. -}
  3098. -
  3099. -int notzero(int a)
  3100. -{
  3101. -    if (a == 0)
  3102. -        {
  3103. -        errflag = 1;
  3104. -        zerr("division by zero");
  3105. -        return 0;
  3106. -        }
  3107. -    return 1;
  3108. -}
  3109. -
  3110. -#define pop2() { b = stack[sp--].val; a = stack[sp--].val; }
  3111. -#define pop3() {c=stack[sp--].val;b=stack[sp--].val;a=stack[sp--].val;}
  3112. -#define nolval() {stack[sp].lval=-1;}
  3113. -#define pushv(X) { push(X,-1); }
  3114. -#define pop2lv() { pop2() lv = stack[sp+1].lval; }
  3115. -#define set(X) { push(setvar(lv,X),lv); }
  3116. -
  3117. -void op(int what)
  3118. -{
  3119. -long a,b,c;
  3120. -LV lv;
  3121. -
  3122. -    switch(what) {
  3123. -        case NOT: stack[sp].val = !stack[sp].val; nolval(); break;
  3124. -        case COMP: stack[sp].val = ~stack[sp].val; nolval(); break;
  3125. -        case POSTPLUS: (void) setvar(stack[sp].lval,stack[sp].val+1); break;
  3126. -        case POSTMINUS: (void) setvar(stack[sp].lval,stack[sp].val-1); break;
  3127. -        case UPLUS: nolval(); break;
  3128. -        case UMINUS: stack[sp].val = -stack[sp].val; nolval(); break;
  3129. -        case AND: pop2(); pushv(a&b); break;
  3130. -        case XOR: pop2(); pushv(a^b); break;
  3131. -        case OR: pop2(); pushv(a|b); break;
  3132. -        case MUL: pop2(); pushv(a*b); break;
  3133. -        case DIV: pop2(); if (notzero(b)) pushv(a/b); break;
  3134. -        case MOD: pop2(); if (notzero(b)) pushv(a%b); break;
  3135. -        case PLUS: pop2(); pushv(a+b); break;
  3136. -        case MINUS: pop2(); pushv(a-b); break;
  3137. -        case SHLEFT: pop2(); pushv(a<<b); break;
  3138. -        case SHRIGHT: pop2(); pushv(a>>b); break;
  3139. -        case LES: pop2(); pushv(a<b); break;
  3140. -        case LEQ: pop2(); pushv(a<=b); break;
  3141. -        case GRE: pop2(); pushv(a>b); break;
  3142. -        case GEQ: pop2(); pushv(a>=b); break;
  3143. -        case DEQ: pop2(); pushv(a==b); break;
  3144. -        case NEQ: pop2(); pushv(a!=b); break;
  3145. -        case DAND: pop2(); pushv(a&&b); break;
  3146. -        case DOR: pop2(); pushv(a||b); break;
  3147. -        case DXOR: pop2(); pushv(a&&!b||!a&&b); break;
  3148. -        case QUEST: pop3(); pushv((a)?b:c); break;
  3149. -        case COLON: break;
  3150. -        case EQ: pop2lv(); set(b); break;
  3151. -        case PLUSEQ: pop2lv(); set(a+b); break;
  3152. -        case MINUSEQ: pop2lv(); set(a-b); break;
  3153. -        case MULEQ: pop2lv(); set(a*b); break;
  3154. -        case DIVEQ: pop2lv(); if (notzero(b)) set(a/b); break;
  3155. -        case MODEQ: pop2lv(); if (notzero(b)) set(a%b); break;
  3156. -        case ANDEQ: pop2lv(); set(a&b); break;
  3157. -        case XOREQ: pop2lv(); set(a^b); break;
  3158. -        case OREQ: pop2lv(); set(a|b); break;
  3159. -        case SHLEFTEQ: pop2lv(); set(a<<b); break;
  3160. -        case SHRIGHTEQ: pop2lv(); set(a>>b); break;
  3161. -        case DANDEQ: pop2lv(); set(a&&b); break;
  3162. -        case DOREQ: pop2lv(); set(a||b); break;
  3163. -        case DXOREQ: pop2lv(); set(a&&!b||!a&&b); break;
  3164. -        case COMMA: pop2(); pushv(b); break;
  3165. -        case PREPLUS: stack[sp].val = setvar(stack[sp].lval,
  3166. -            stack[sp].val+1); break;
  3167. -        case PREMINUS: stack[sp].val = setvar(stack[sp].lval,
  3168. -            stack[sp].val-1); break;
  3169. -        default: fprintf(stderr,"whoops.\n"); exit(1);
  3170. -    }
  3171. -}
  3172. -
  3173. -void bop(int tok)
  3174. -{
  3175. -    switch (tok) {
  3176. -        case DAND: case DANDEQ: if (!stack[sp].val) noeval++; break;
  3177. -        case DOR: case DOREQ: if (stack[sp].val) noeval++; break;
  3178. -        };
  3179. -}
  3180. -
  3181. -long matheval(char *s)
  3182. -{
  3183. -int t0;
  3184. -
  3185. -    for (t0 = 0; t0 != LVCOUNT; t0++)
  3186. -        lvals[t0] = NULL;
  3187. -    lvc = 0;
  3188. -    ptr = s;
  3189. -    sp = -1;
  3190. -    mathparse(TOPPREC);
  3191. -    if (!errflag && sp)
  3192. -        zerr("arithmetic error: unbalanced stack");
  3193. -    for (t0 = 0; t0 != lvc; t0++)
  3194. -        free(lvals[t0]);
  3195. -    return stack[0].val;
  3196. -}
  3197. -
  3198. -/* operator-precedence parse the string and execute */
  3199. -
  3200. -void mathparse(int pc)
  3201. -{
  3202. -    if (errflag)
  3203. -        return;
  3204. -    tok = yylex();
  3205. -    while (prec[tok] <= pc)
  3206. -        {
  3207. -        if (errflag)
  3208. -            return;
  3209. -        if (tok == NUM)
  3210. -            push(yyval,-1);
  3211. -        else if (tok == ID)
  3212. -            push(getvar(yylval),yylval);
  3213. -        else if (tok == INPAR)
  3214. -            {
  3215. -            mathparse(TOPPREC);
  3216. -            if (tok != OUTPAR)
  3217. -                exit(1);
  3218. -            }
  3219. -        else if (tok == QUEST)
  3220. -            {
  3221. -            int q = stack[sp].val;
  3222. -            if (!q) noeval++;
  3223. -            mathparse(prec[QUEST]-1);
  3224. -            if (!q) noeval--; else noeval++;
  3225. -            mathparse(prec[QUEST]);
  3226. -            if (q) noeval--;
  3227. -            op(QUEST);
  3228. -            continue;
  3229. -            }
  3230. -        else
  3231. -            {
  3232. -            int otok = tok,onoeval = noeval;
  3233. -
  3234. -            if (type[otok] == BOO)
  3235. -                bop(otok);
  3236. -            mathparse(prec[otok]-(type[otok] != RL));
  3237. -            noeval = onoeval;
  3238. -            op(otok);
  3239. -            continue;
  3240. -            }
  3241. -        tok = yylex();
  3242. -        }
  3243. -}
  3244. -
  3245. End of math.c
  3246. echo math.pro 1>&2
  3247. sed 's/^-//' >math.pro <<'End of math.pro'
  3248. -INPAR, OUTPAR, NOT, COMP, POSTPLUS,;
  3249. -POSTMINUS, UPLUS, UMINUS, AND, XOR,;
  3250. -OR, MUL, DIV, MOD, PLUS,;
  3251. -MINUS, SHLEFT, SHRIGHT, LES, LEQ,;
  3252. -GRE, GEQ, DEQ, NEQ, DAND,;
  3253. -DOR, DXOR, QUEST, COLON, EQ,;
  3254. -PLUSEQ, MINUSEQ, MULEQ, DIVEQ, MODEQ,;
  3255. -ANDEQ, XOREQ, OREQ, SHLEFTEQ, SHRIGHTEQ,;
  3256. -DANDEQ, DOREQ, DXOREQ, COMMA, EOI,;
  3257. -PREPLUS, PREMINUS, NUM, ID, TOKCOUNT;
  3258. -LR,LR,RL,RL,RL,;
  3259. -RL,RL,RL,LR,LR,;
  3260. -LR,LR,LR,LR,LR,;
  3261. -LR,LR,LR,LR,LR,;
  3262. -LR,LR,LR,LR,BOO,;
  3263. -BOO,LR,RL,RL,RL,;
  3264. -RL,RL,RL,RL,RL,;
  3265. -RL,RL,RL,RL,RL,;
  3266. -BOO,BOO,RL,RL,RL,;
  3267. -RL,RL,LR,LR,;
  3268. -int yylex(void);
  3269. -void push(long val,LV lval);
  3270. -long getvar(LV s);
  3271. -long setvar(LV s,long v);
  3272. -int notzero(int a);
  3273. -void op(int what);
  3274. -void bop(int tok);
  3275. -long matheval(char *s);
  3276. -void mathparse(int pc);
  3277. End of math.pro
  3278. echo parse.c 1>&2
  3279. sed 's/^-//' >parse.c <<'End of parse.c'
  3280. -/*
  3281. -
  3282. -    parse.c - parsing
  3283. -
  3284. -    This file is part of zsh, the Z shell.
  3285. -
  3286. -   zsh is free software; no one can prevent you from reading the source
  3287. -   code, or giving it to someone else.
  3288. -   This file is copyrighted under the GNU General Public License, which
  3289. -   can be found in the file called COPYING.
  3290. -
  3291. -   Copyright (C) 1990 Paul Falstad
  3292. -
  3293. -   zsh is distributed in the hope that it will be useful, but
  3294. -   WITHOUT ANY WARRANTY.  No author or distributor accepts
  3295. -   responsibility to anyone for the consequences of using it or for
  3296. -   whether it serves any particular purpose or works at all, unless he
  3297. -   says so in writing.  Refer to the GNU General Public License
  3298. -   for full details.
  3299. -
  3300. -   Everyone is granted permission to copy, modify and redistribute
  3301. -   zsh, but only under the conditions described in the GNU General Public
  3302. -   License.   A copy of this license is supposed to have been given to you
  3303. -   along with zsh so you can know your rights and responsibilities.
  3304. -   It should be in a file named COPYING.
  3305. -
  3306. -   Among other things, the copyright notice and this notice must be
  3307. -   preserved on all copies.
  3308. -
  3309. -*/
  3310. -
  3311. -#include "zsh.h"
  3312. -#include "funcs.h"
  3313. -
  3314. -/* parse a list, but return : instead of NULL */
  3315. -
  3316. -list parlist(int nest)
  3317. -{
  3318. -list l1;
  3319. -list2 l2;
  3320. -pline p;
  3321. -comm c;
  3322. -
  3323. -    if (l1 = parlist1(nest))
  3324. -        return l1;
  3325. -    if (errflag)
  3326. -        return NULL;
  3327. -    c = alloc(sizeof *c);
  3328. -    c->cmd = strdup("");
  3329. -    c->args = newtable();
  3330. -    c->redir = newtable();
  3331. -    c->type = SIMPLE;
  3332. -    p = alloc(sizeof *p);
  3333. -    p->left = c;
  3334. -    p->type = END;
  3335. -    l2 = alloc(sizeof *l2);
  3336. -    l2->left = p;
  3337. -    l2->type = END;
  3338. -    l1 = alloc(sizeof *l1);
  3339. -    l1->left = l2;
  3340. -    l1->type = SYNC;
  3341. -    return l1;
  3342. -}
  3343. -
  3344. -/* parse a list */
  3345. -
  3346. -list parlist1(int nest)
  3347. -{
  3348. -list l1 = (list) alloc(sizeof *l1);
  3349. -int isnl;
  3350. -
  3351. -    incmd = 0;
  3352. -    if (peek == EMPTY)
  3353. -        matchit();
  3354. -    if (nest)
  3355. -        while (peek == NEWLIN || peek == SEMI)
  3356. -            matchit();
  3357. -    if (!(l1->left = parlist2()))
  3358. -        {
  3359. -        free(l1);
  3360. -        return NULL;
  3361. -        }
  3362. -    l1->type = (peek == AMPER) ? ASYNC : SYNC;
  3363. -    if ((isnl = peek == NEWLIN) || peek == SEMI || peek == AMPER)
  3364. -        peek = EMPTY;
  3365. -    if ((nest || !isnl) && peek == EMPTY)
  3366. -        {
  3367. -        if (!(l1->right = parlist1(nest)))
  3368. -            {
  3369. -            if (!errflag)
  3370. -                {
  3371. -                if (peek == NEWLIN)
  3372. -                    peek = EMPTY;
  3373. -                return l1;
  3374. -                }
  3375. -            freelist2(l1->left);
  3376. -            free(l1);
  3377. -            return NULL;
  3378. -            }
  3379. -        }
  3380. -    else
  3381. -        l1->right = NULL;
  3382. -    return l1;
  3383. -}
  3384. -
  3385. -/* parse a sublist */
  3386. -
  3387. -list2 parlist2(void)
  3388. ---cut here---cut here---cut here---
  3389.