home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume24 / zsh2.1 / part08 < prev    next >
Text File  |  1991-10-24  |  49KB  |  2,266 lines

  1. Newsgroups: comp.sources.misc
  2. From: pfalstad@phoenix.Princeton.EDU (Paul Falstad)
  3. Subject:  v24i008:  zsh2.1 - The Z shell, Part08/19
  4. Message-ID: <1991Oct24.190925.25848@sparky.imd.sterling.com>
  5. X-Md4-Signature: 45b7c4db263877d30de733d36d186705
  6. Date: Thu, 24 Oct 1991 19:09:25 GMT
  7. Approved: kent@sparky.imd.sterling.com
  8.  
  9. Submitted-by: pfalstad@phoenix.Princeton.EDU (Paul Falstad)
  10. Posting-number: Volume 24, Issue 8
  11. Archive-name: zsh2.1/part08
  12. Environment: BSD
  13. Supersedes: zsh2.00: Volume 18, Issue 84-98
  14.  
  15. #!/bin/sh
  16. # this is zshar.08 (part 8 of zsh2.1.0)
  17. # do not concatenate these parts, unpack them in order with /bin/sh
  18. # file zsh2.1/src/jobs.c continued
  19. #
  20. if test ! -r _shar_seq_.tmp; then
  21.     echo 'Please unpack part 1 first!'
  22.     exit 1
  23. fi
  24. (read Scheck
  25.  if test "$Scheck" != 8; then
  26.     echo Please unpack part "$Scheck" next!
  27.     exit 1
  28.  else
  29.     exit 0
  30.  fi
  31. ) < _shar_seq_.tmp || exit 1
  32. if test ! -f _shar_wnt_.tmp; then
  33.     echo 'x - still skipping zsh2.1/src/jobs.c'
  34. else
  35. echo 'x - continuing file zsh2.1/src/jobs.c'
  36. sed 's/^X//' << 'SHAR_EOF' >> 'zsh2.1/src/jobs.c' &&
  37. X
  38. X   zsh is distributed in the hope that it will be useful, but
  39. X   WITHOUT ANY WARRANTY.  No author or distributor accepts
  40. X   responsibility to anyone for the consequences of using it or for
  41. X   whether it serves any particular purpose or works at all, unless he
  42. X   says so in writing.  Refer to the GNU General Public License
  43. X   for full details.
  44. X
  45. X   Everyone is granted permission to copy, modify and redistribute
  46. X   zsh, but only under the conditions described in the GNU General Public
  47. X   License.   A copy of this license is supposed to have been given to you
  48. X   along with zsh so you can know your rights and responsibilities.
  49. X   It should be in a file named COPYING.
  50. X
  51. X   Among other things, the copyright notice and this notice must be
  52. X   preserved on all copies.
  53. X
  54. X*/
  55. X
  56. X#include "zsh.h"
  57. X#include <sys/errno.h>
  58. X
  59. X/* != 0 means the handler is active */
  60. X
  61. Xstatic int handling = 0;
  62. X
  63. X/* != 0 means the shell is waiting for a job to complete */
  64. X
  65. Xstatic int waiting = 0;
  66. X
  67. X#ifdef INTHANDTYPE
  68. X#define RETURN return 0
  69. X#else
  70. X#define RETURN return
  71. X#endif
  72. X
  73. X/* the signal handler */
  74. X
  75. XHANDTYPE handler(sig,code) /**/
  76. Xint sig;int code;
  77. X{
  78. Xlong pid;
  79. Xint statusp;
  80. XJob jn;
  81. Xstruct process *pn;
  82. Xstruct rusage ru;
  83. X
  84. X#ifdef RESETHANDNEEDED
  85. X    signal(sig,handler);
  86. X#endif
  87. X    if (sig == SIGINT)
  88. X        {
  89. X        if (sigtrapped[SIGINT])
  90. X            dotrap(SIGINT);
  91. X        else
  92. X            errflag = 1;
  93. X        RETURN;
  94. X        }
  95. X#ifdef SIGWINCH
  96. X    if (sig == SIGWINCH)
  97. X        adjustwinsize();
  98. X#endif
  99. X    if (sig != SIGCHLD)
  100. X        {
  101. X        dotrap(sig);
  102. X        if (sig == SIGALRM && !sigtrapped[SIGALRM])
  103. X            {
  104. X            zerr("timeout",NULL,0);
  105. X            exit(1);
  106. X            }
  107. X        RETURN;
  108. X        }
  109. X    for (;;)
  110. X        {
  111. X#ifdef SYSV
  112. X        pid = wait(&statusp);
  113. X#else
  114. X#if defined(RLIM_INFINITY)  & ! defined(__hpux)
  115. X        pid = wait3(&statusp,WNOHANG|WUNTRACED,&ru);
  116. X#else
  117. X        pid = wait3(&statusp,WNOHANG|WUNTRACED,NULL);
  118. X#endif
  119. X#endif
  120. X        if (pid == -1)
  121. X            {
  122. X            if (errno != ECHILD)
  123. X                zerr("wait failed: %e",NULL,errno);
  124. X            RETURN;
  125. X            }
  126. X        if (!pid)
  127. X            RETURN;
  128. X        findproc(pid,&jn,&pn);    /* find the process of this pid */
  129. X        if (jn)
  130. X            {
  131. X            pn->statusp = statusp;
  132. X            handling = 1;
  133. X            pn->ru = ru;
  134. X            pn->endtime = time(NULL);
  135. X            updatestatus(jn);
  136. X            handling = 0;
  137. X            if (zleactive)
  138. X                refresh();
  139. X            }
  140. X        else if (WIFSTOPPED(SP(statusp)))
  141. X            kill(pid,SIGKILL);    /* kill stopped untraced children */
  142. X        }
  143. X    RETURN;
  144. X}
  145. X
  146. X/* change job table entry from stopped to running */
  147. X
  148. Xvoid makerunning(jn) /**/
  149. XJob jn;
  150. X{
  151. Xstruct process *pn;
  152. X
  153. X    jn->stat &= ~STAT_STOPPED;
  154. X    for (pn = jn->procs; pn; pn = pn->next)
  155. X        if (WIFSTOPPED(SP(pn->statusp)))
  156. X            pn->statusp = SP_RUNNING;
  157. X}
  158. X
  159. X/* update status of job, possibly printing it */
  160. X
  161. Xvoid updatestatus(jn) /**/
  162. XJob jn;
  163. X{
  164. Xstruct process *pn;
  165. Xint notrunning = 1,alldone = 1,val,job = jn-jobtab,somestopped = 0;
  166. X
  167. X    for (pn = jn->procs; pn; pn = pn->next)
  168. X        {
  169. X        if (pn->statusp == SP_RUNNING)
  170. X            notrunning = 0;
  171. X        if (pn->statusp == SP_RUNNING || WIFSTOPPED(SP(pn->statusp)))
  172. X            alldone = 0;
  173. X        if (WIFSTOPPED(SP(pn->statusp)))
  174. X            somestopped = 1;
  175. X        if (!pn->next && jn)
  176. X            val = (WIFSIGNALED(SP(pn->statusp))) ?
  177. X                0200 | WTERMSIG(SP(pn->statusp)) : WEXITSTATUS(SP(pn->statusp));
  178. X        }
  179. X    if (!notrunning)
  180. X        return;
  181. X    if (somestopped && (jn->stat & STAT_STOPPED))
  182. X        return;
  183. X    jn->stat |= (alldone) ? STAT_CHANGED|STAT_DONE :
  184. X        STAT_CHANGED|STAT_STOPPED;
  185. X    if (alldone && job == thisjob)
  186. X        {
  187. X        if (!val) {
  188. X            gettyinfo(&shttyinfo);
  189. X            if (interact && isset(SHINSTDIN) && SHTTY != -1 && isset(USEZLE))
  190. X                sanetty(&shttyinfo);
  191. X#ifdef TIOCSWINSZ
  192. X            if (!(columns = shttyinfo.winsize.ws_col))
  193. X                columns = 80;
  194. X            lines = shttyinfo.winsize.ws_row;
  195. X#endif
  196. X        } else
  197. X            settyinfo(&shttyinfo);
  198. X        lastval = val;
  199. X        }
  200. X    if ((jn->stat & (STAT_DONE|STAT_STOPPED)) == STAT_STOPPED) {
  201. X        prevjob = curjob;
  202. X        curjob = job;
  203. X    }
  204. X    if ((isset(NOTIFY) || job == thisjob) && jn->stat & STAT_LOCKED)
  205. X        printjob(jn,!!isset(LONGLISTJOBS));
  206. X    if (sigtrapped[SIGCHLD] && job != thisjob)
  207. X        dotrap(SIGCHLD);
  208. X}
  209. X
  210. X/* find process and job associated with pid */
  211. X
  212. Xvoid findproc(pid,jptr,pptr) /**/
  213. Xint pid;Job *jptr;struct process **pptr;
  214. X{
  215. Xstruct process *pn;
  216. Xint jn;
  217. X
  218. X    for (jn = 1; jn != MAXJOB; jn++)
  219. X        for (pn = jobtab[jn].procs; pn; pn = pn->next)
  220. X            if (pn->pid == pid)
  221. X                {
  222. X                *pptr = pn;
  223. X                *jptr = jobtab+jn;
  224. X                return;
  225. X                }
  226. X    *pptr = NULL;
  227. X    *jptr = NULL;
  228. X}
  229. X
  230. X/*
  231. X    lng = 0 means jobs 
  232. X    lng = 1 means jobs -l
  233. X    lng = 2 means jobs -p
  234. X*/
  235. X
  236. Xvoid printjob(jn,lng) /**/
  237. XJob jn;int lng;
  238. X{
  239. Xint job = jn-jobtab,len = 9,sig = -1,sflag = 0,llen,printed = 0;
  240. Xint conted = 0,lineleng = getlineleng(),skip = 0,doputnl = 0;
  241. Xstruct process *pn;
  242. X
  243. X    if (lng < 0)
  244. X        {
  245. X        conted = 1;
  246. X        lng = 0;
  247. X        }
  248. X
  249. X    /* find length of longest signame, check to see if we
  250. X        really need to print this job */
  251. X
  252. X    for (pn = jn->procs; pn; pn = pn->next)
  253. X        {
  254. X        if (pn->statusp != SP_RUNNING)
  255. X            if (WIFSIGNALED(SP(pn->statusp)))
  256. X                {
  257. X                sig = WTERMSIG(SP(pn->statusp));
  258. X                llen = strlen(sigmsg[sig]);
  259. X                if (WCOREDUMPED(pn->statusp))
  260. X                    llen += 14;
  261. X                if (llen > len)
  262. X                    len = llen;
  263. X                if (sig != SIGINT && sig != SIGPIPE)
  264. X                    sflag = 1;
  265. X                else if (sig == SIGINT)
  266. X                    errflag = 1;
  267. X                if (job == thisjob && sig == SIGINT)
  268. X                    doputnl = 1;
  269. X                }
  270. X            else if (WIFSTOPPED(SP(pn->statusp)))
  271. X                {
  272. X                sig = WSTOPSIG(SP(pn->statusp));
  273. X                if (strlen(sigmsg[sig]) > len)
  274. X                    len = strlen(sigmsg[sig]);
  275. X                if (job == thisjob && sig == SIGTSTP)
  276. X                    doputnl = 1;
  277. X                }
  278. X            else if (isset(PRINTEXITVALUE) && WEXITSTATUS(SP(pn->statusp)))
  279. X                sflag = 1;
  280. X        }
  281. X
  282. X    /* print if necessary */
  283. X
  284. X    if (interact && jobbing && ((jn->stat & STAT_STOPPED) || sflag ||
  285. X            job != thisjob))
  286. X        {
  287. X        int len2,fline = 1;
  288. X        struct process *qn;
  289. X
  290. X        trashzle();
  291. X        if (doputnl)
  292. X            putc('\n',stderr);
  293. X        for (pn = jn->procs; pn;)
  294. X            {
  295. X            len2 = ((job == thisjob) ? 5 : 10)+len; /* 2 spaces */
  296. X            if (lng)
  297. X                qn = pn->next;
  298. X            else for (qn = pn->next; qn; qn = qn->next)
  299. X                {
  300. X                if (qn->statusp != pn->statusp)
  301. X                    break;
  302. X                if (strlen(qn->text)+len2+((qn->next) ? 3 : 0) > lineleng)
  303. X                    break;
  304. X                len2 += strlen(qn->text)+2;
  305. X                }
  306. X            if (job != thisjob)
  307. X                if (fline)
  308. X                    fprintf(stderr,"[%d]  %c ",jn-jobtab,(job == curjob) ? '+' :
  309. X                        (job == prevjob) ? '-' : ' ');
  310. X                else
  311. X                    fprintf(stderr,(job > 9) ? "        " : "       ");
  312. X            else
  313. X                fprintf(stderr,"zsh: ");
  314. X            if (lng)
  315. X                if (lng == 1)
  316. X                    fprintf(stderr,"%d ",pn->pid);
  317. X                else
  318. X                    {
  319. X                    int x = jn->gleader;
  320. X
  321. X                    fprintf(stderr,"%d ",x);
  322. X                    do skip++; while (x /= 10);
  323. X                    skip++;
  324. X                    lng = 0;
  325. X                    }
  326. X            else
  327. X                fprintf(stderr,"%*s",skip,"");
  328. X            if (pn->statusp == SP_RUNNING)
  329. X                if (!conted)
  330. X                    fprintf(stderr,"running%*s",len-7+2,"");
  331. X                else
  332. X                    fprintf(stderr,"continued%*s",len-9+2,"");
  333. X            else if (WIFEXITED(SP(pn->statusp)))
  334. X                if (WEXITSTATUS(SP(pn->statusp)))
  335. X                    fprintf(stderr,"exit %-4d%*s",WEXITSTATUS(SP(pn->statusp)),
  336. X                        len-9+2,"");
  337. X                else
  338. X                    fprintf(stderr,"done%*s",len-4+2,"");
  339. X            else if (WIFSTOPPED(SP(pn->statusp)))
  340. X                fprintf(stderr,"%-*s",len+2,sigmsg[WSTOPSIG(SP(pn->statusp))]);
  341. X            else if (WCOREDUMPED(pn->statusp))
  342. X                fprintf(stderr,"%s (core dumped)%*s",
  343. X                    sigmsg[WTERMSIG(SP(pn->statusp))],
  344. X                    len-14+2-strlen(sigmsg[WTERMSIG(SP(pn->statusp))]),"");
  345. X            else
  346. X                fprintf(stderr,"%-*s",len+2,sigmsg[WTERMSIG(SP(pn->statusp))]);
  347. X            for (; pn != qn; pn = pn->next)
  348. X                fprintf(stderr,(pn->next) ? "%s | " : "%s",pn->text);
  349. X            putc('\n',stderr);
  350. X            fline = 0;
  351. X            }
  352. X        printed = 1;
  353. X        }
  354. X    else if (doputnl && interact)
  355. X        putc('\n',stderr);
  356. X    fflush(stderr);
  357. X
  358. X    /* print "(pwd now: foo)" messages */
  359. X
  360. X    if (interact && job==thisjob && strcmp(jn->cwd,cwd))
  361. X        {
  362. X        printf("(pwd now: ");
  363. X        printdir(cwd);
  364. X        printf(")\n");
  365. X        fflush(stdout);
  366. X        }
  367. X
  368. X    /* delete job if done */
  369. X
  370. X    if (jn->stat & STAT_DONE)
  371. X        {
  372. X        static struct job zero;
  373. X        struct process *nx;
  374. X        char *s;
  375. X
  376. X        if (jn->stat & STAT_TIMED)
  377. X            {
  378. X            dumptime(jn);
  379. X            printed = 1;
  380. X            }
  381. X        for (pn = jn->procs; pn; pn = nx)
  382. X            {
  383. X            nx = pn->next;
  384. X            if (pn->text)
  385. X                free(pn->text);
  386. X            free(pn);
  387. X            }
  388. X        free(jn->cwd);
  389. X        if (jn->filelist)
  390. X            {
  391. X            while (s = getnode(jn->filelist))
  392. X                {
  393. X                unlink(s);
  394. X                free(s);
  395. X                }
  396. X            free(jn->filelist);
  397. X            }
  398. X        *jn = zero;
  399. X        if (job == curjob)
  400. X            {
  401. X            curjob = prevjob;
  402. X            prevjob = job;
  403. X            }
  404. X        if (job == prevjob)
  405. X            setprevjob();
  406. X        }
  407. X    else
  408. X        jn->stat &= ~STAT_CHANGED;
  409. X}
  410. X
  411. X/* set the previous job to something reasonable */
  412. X
  413. Xvoid setprevjob() /**/
  414. X{
  415. Xint t0;
  416. X
  417. X    for (t0 = MAXJOB-1; t0; t0--)
  418. X        if ((jobtab[t0].stat & STAT_INUSE) && (jobtab[t0].stat & STAT_STOPPED) &&
  419. X                t0 != curjob && t0 != thisjob)
  420. X            break;
  421. X    if (!t0)
  422. X        for (t0 = MAXJOB-1; t0; t0--)
  423. X            if ((jobtab[t0].stat & STAT_INUSE) && t0 != curjob && t0 != thisjob)
  424. X                break;
  425. X    prevjob = (t0) ? t0 : -1;
  426. X}
  427. X
  428. X/* initialize a job table entry */
  429. X
  430. Xvoid initjob() /**/
  431. X{
  432. X    jobtab[thisjob].cwd = ztrdup(cwd);
  433. X    jobtab[thisjob].stat = STAT_INUSE;
  434. X    jobtab[thisjob].gleader = 0;
  435. X}
  436. X
  437. X/* add a process to the current job */
  438. X
  439. Xstruct process *addproc(pid,text) /**/
  440. Xlong pid;char *text;
  441. X{
  442. Xstruct process *process;
  443. X
  444. X    if (!jobtab[thisjob].gleader)
  445. X        jobtab[thisjob].gleader = lastpid = pid;
  446. X    lastpid = pid;
  447. X    process = zcalloc(sizeof *process);
  448. X    process->pid = pid;
  449. X    process->text = text;
  450. X    process->next = NULL;
  451. X    process->statusp = SP_RUNNING;
  452. X    process->bgtime = time(NULL);
  453. X    if (jobtab[thisjob].procs)
  454. X        {
  455. X        struct process *n;
  456. X
  457. X        for (n = jobtab[thisjob].procs; n->next && !n->next->lastfg; n = n->next);
  458. X        process->next = n->next;
  459. X        n->next = process;
  460. X        }
  461. X    else
  462. X        jobtab[thisjob].procs = process;
  463. X    return process;
  464. X}
  465. X
  466. X/* determine if it's all right to exec a command without
  467. X    forking in last component of subshells; it's not ok if we have files
  468. X    to delete */
  469. X
  470. Xint execok() /**/
  471. X{
  472. XJob jn;
  473. X
  474. X    if (!exiting)
  475. X        return 0;
  476. X    for (jn = jobtab+1; jn != jobtab+MAXJOB; jn++)
  477. X        if (jn->stat && jn->filelist)
  478. X            return 0;
  479. X    return 1;
  480. X}
  481. X
  482. X/* wait for a job to finish */
  483. X
  484. Xvoid waitjob(job) /**/
  485. Xint job;
  486. X{
  487. Xstatic struct job zero;
  488. XJob jn;
  489. X
  490. X    if (jobtab[job].procs)    /* if any forks were done */
  491. X        {
  492. X        jobtab[job].stat |= STAT_LOCKED;
  493. X        waiting = 1;
  494. X        if (jobtab[job].stat & STAT_CHANGED)
  495. X            printjob(jobtab+job,!!isset(LONGLISTJOBS));
  496. X        while (jobtab[job].stat &&
  497. X                !(jobtab[job].stat & (STAT_DONE|STAT_STOPPED)))
  498. X            chldsuspend();
  499. X        waiting = 0;
  500. X        }
  501. X    else    /* else do what printjob() usually does */
  502. X        {
  503. X        char *s;
  504. X
  505. X        jn = jobtab+job;
  506. X        free(jn->cwd);
  507. X        if (jn->filelist)
  508. X            {
  509. X            while (s = getnode(jn->filelist))
  510. X                {
  511. X                unlink(s);
  512. X                free(s);
  513. X                }
  514. X            free(jn->filelist);
  515. X            }
  516. X        *jn = zero;
  517. X        }
  518. X}
  519. X
  520. X/* wait for running job to finish */
  521. X
  522. Xvoid waitjobs() /**/
  523. X{
  524. X    waitjob(thisjob);
  525. X    thisjob = -1;
  526. X}
  527. X
  528. X/* clear job table when entering subshells */
  529. X
  530. Xvoid clearjobtab() /**/
  531. X{
  532. Xstatic struct job zero;
  533. Xint t0;
  534. X
  535. X    for (t0 = 1; t0 != MAXJOB; t0++)
  536. X        jobtab[thisjob] = zero;
  537. X}
  538. X
  539. X/* get a free entry in the job table to use */
  540. X
  541. Xint getfreejob() /**/
  542. X{
  543. Xint t0;
  544. X
  545. X    for (t0 = 1; t0 != MAXJOB; t0++)
  546. X        if (!jobtab[t0].stat) {
  547. X            jobtab[t0].stat |= STAT_INUSE;
  548. X            return t0;
  549. X        }
  550. X    zerr("job table full or recursion limit exceeded",NULL,0);
  551. X    return -1;
  552. X}
  553. X
  554. X/* print pids for & */
  555. X
  556. Xvoid spawnjob() /**/
  557. X{
  558. Xstruct process *pn;
  559. X
  560. X    if (!subsh)
  561. X        {
  562. X        if (curjob == -1 || !(jobtab[curjob].stat & STAT_STOPPED))
  563. X            {
  564. X            curjob = thisjob;
  565. X            setprevjob();
  566. X            }
  567. X        else if (prevjob == -1 || !(jobtab[prevjob].stat & STAT_STOPPED))
  568. X            prevjob = thisjob;
  569. X        if (interact && jobbing && jobtab[thisjob].procs)
  570. X            {
  571. X            fprintf(stderr,"[%d]",thisjob);
  572. X            for (pn = jobtab[thisjob].procs; pn; pn = pn->next)
  573. X                fprintf(stderr," %d",pn->pid);
  574. X            fprintf(stderr,"\n");
  575. X            fflush(stderr);
  576. X            }
  577. X        }
  578. X    if (!jobtab[thisjob].procs)
  579. X        {
  580. X        char *s;
  581. X        static struct job zero;
  582. X        struct job *jn;
  583. X
  584. X        jn = jobtab+thisjob;
  585. X        free(jn->cwd);
  586. X        if (jn->filelist)
  587. X            {
  588. X            while (s = getnode(jn->filelist))
  589. X                {
  590. X                unlink(s);
  591. X                free(s);
  592. X                }
  593. X            free(jn->filelist);
  594. X            }
  595. X        *jn = zero;
  596. X        }
  597. X    else
  598. X        jobtab[thisjob].stat |= STAT_LOCKED;
  599. X    thisjob = -1;
  600. X}
  601. X
  602. Xvoid fixsigs() /**/
  603. X{
  604. X    unblockchld();
  605. X}
  606. X
  607. Xvoid printtime(real,ru,desc) /**/
  608. Xtime_t real;struct rusage *ru;char *desc;
  609. X{
  610. Xchar *s;
  611. X
  612. X    if (!desc)
  613. X        desc = "";
  614. X    for (s = (timefmt) ? timefmt : DEFTIMEFMT; *s; s++)
  615. X        if (*s == '%')
  616. X            switch(s++,*s)
  617. X                {
  618. X                case 'E': fprintf(stderr,"%lds",real); break;
  619. X                case 'U': fprintf(stderr,"%ld.%03lds",
  620. X                    ru->ru_utime.tv_sec,ru->ru_utime.tv_usec/1000); break;
  621. X                case 'S': fprintf(stderr,"%ld.%03lds",
  622. X                    ru->ru_stime.tv_sec,ru->ru_stime.tv_usec/1000); break;
  623. X                case 'P':
  624. X                    if (real)
  625. X                        fprintf(stderr,"%d%%",
  626. X                            (int) (100*ru->ru_utime.tv_sec+ru->ru_stime.tv_sec)
  627. X                                / real);
  628. X                    break;
  629. X                case 'W': fprintf(stderr,"%ld",ru->ru_nswap); break;
  630. X                case 'X': fprintf(stderr,"%ld",ru->ru_ixrss); break;
  631. X                case 'D': fprintf(stderr,"%ld",ru->ru_idrss); break;
  632. X                case 'K': fprintf(stderr,"%ld",ru->ru_ixrss+ru->ru_idrss); break;
  633. X                case 'M': fprintf(stderr,"%ld",ru->ru_maxrss); break;
  634. X                case 'F': fprintf(stderr,"%ld",ru->ru_majflt); break;
  635. X                case 'R': fprintf(stderr,"%ld",ru->ru_minflt); break;
  636. X                case 'I': fprintf(stderr,"%ld",ru->ru_inblock); break;
  637. X                case 'O': fprintf(stderr,"%ld",ru->ru_oublock); break;
  638. X                case 'r': fprintf(stderr,"%ld",ru->ru_msgrcv); break;
  639. X                case 's': fprintf(stderr,"%ld",ru->ru_msgsnd); break;
  640. X                case 'k': fprintf(stderr,"%ld",ru->ru_nsignals); break;
  641. X                case 'w': fprintf(stderr,"%ld",ru->ru_nvcsw); break;
  642. X                case 'c': fprintf(stderr,"%ld",ru->ru_nivcsw); break;
  643. X                default: fprintf(stderr,"%%%c",s[-1]); break;
  644. X                }
  645. X        else
  646. X            putc(*s,stderr);
  647. X    putc('\n',stderr);
  648. X    fflush(stderr);
  649. X}
  650. X
  651. Xvoid dumptime(jn) /**/
  652. XJob jn;
  653. X{
  654. Xstruct process *pn = jn->procs;
  655. X
  656. X    if (!jn->procs)
  657. X        return;
  658. X    for (pn = jn->procs; pn; pn = pn->next)
  659. X        printtime(pn->endtime-pn->bgtime,&pn->ru,pn->text);
  660. X}
  661. X
  662. X/* SIGHUP any jobs left running */
  663. X
  664. Xvoid killrunjobs() /**/
  665. X{
  666. Xint t0,killed = 0;
  667. X
  668. X    if (isset(NOHUP)) return;
  669. X    for (t0 = 1; t0 != MAXJOB; t0++)
  670. X        if (t0 != thisjob && jobtab[t0].stat &&
  671. X                !(jobtab[t0].stat & STAT_STOPPED))
  672. X            {
  673. X            kill(-jobtab[t0].gleader,SIGHUP);
  674. X            killed++;
  675. X            }
  676. X    if (killed)
  677. X        zerr("warning: %d jobs SIGHUPed",NULL,killed);
  678. X}
  679. X
  680. X/* check to see if user has jobs running/stopped */
  681. X
  682. Xvoid checkjobs() /**/
  683. X{
  684. Xint t0;
  685. X
  686. X    for (t0 = 1; t0 != MAXJOB; t0++)
  687. X        if (t0 != thisjob && jobtab[t0].stat)
  688. X            break;
  689. X    if (t0 != MAXJOB)
  690. X        {
  691. X        if (jobtab[t0].stat & STAT_STOPPED)
  692. X            {
  693. X#ifdef USE_SUSPENDED
  694. X            zerr("you have suspended jobs.",NULL,0);
  695. X#else
  696. X            zerr("you have stopped jobs.",NULL,0);
  697. X#endif
  698. X            }
  699. X        else
  700. X            zerr("you have running jobs.",NULL,0);
  701. X        stopmsg = 1;
  702. X        }
  703. X}
  704. X
  705. X/* send a signal to a job (simply involves kill if monitoring is on) */
  706. X
  707. Xint killjb(jn,sig) /**/
  708. XJob jn;int sig;
  709. X{
  710. Xstruct process *pn;
  711. Xint err;
  712. X
  713. X    if (jobbing)
  714. X        return(kill(-jn->gleader,sig));
  715. X    for (pn = jn->procs; pn; pn = pn->next)
  716. X        if ((err = kill(pn->pid,sig)) == -1 && errno != ESRCH)
  717. X            return -1;
  718. X    return err;
  719. X}
  720. X
  721. SHAR_EOF
  722. echo 'File zsh2.1/src/jobs.c is complete' &&
  723. chmod 0644 zsh2.1/src/jobs.c ||
  724. echo 'restore of zsh2.1/src/jobs.c failed'
  725. Wc_c="`wc -c < 'zsh2.1/src/jobs.c'`"
  726. test 14918 -eq "$Wc_c" ||
  727.     echo 'zsh2.1/src/jobs.c: original size 14918, current size' "$Wc_c"
  728. rm -f _shar_wnt_.tmp
  729. fi
  730. # ============= zsh2.1/src/lex.c ==============
  731. if test -f 'zsh2.1/src/lex.c' -a X"$1" != X"-c"; then
  732.     echo 'x - skipping zsh2.1/src/lex.c (File already exists)'
  733.     rm -f _shar_wnt_.tmp
  734. else
  735. > _shar_wnt_.tmp
  736. echo 'x - extracting zsh2.1/src/lex.c (Text)'
  737. sed 's/^X//' << 'SHAR_EOF' > 'zsh2.1/src/lex.c' &&
  738. X/*
  739. X
  740. X    lex.c - lexical analysis
  741. X
  742. X    This file is part of zsh, the Z shell.
  743. X
  744. X   zsh is free software; no one can prevent you from reading the source
  745. X   code, or giving it to someone else.
  746. X   This file is copyrighted under the GNU General Public License, which
  747. X   can be found in the file called COPYING.
  748. X
  749. X   Copyright (C) 1990, 1991 Paul Falstad
  750. X
  751. X   zsh is distributed in the hope that it will be useful, but
  752. X   WITHOUT ANY WARRANTY.  No author or distributor accepts
  753. X   responsibility to anyone for the consequences of using it or for
  754. X   whether it serves any particular purpose or works at all, unless he
  755. X   says so in writing.  Refer to the GNU General Public License
  756. X   for full details.
  757. X
  758. X   Everyone is granted permission to copy, modify and redistribute
  759. X   zsh, but only under the conditions described in the GNU General Public
  760. X   License.   A copy of this license is supposed to have been given to you
  761. X   along with zsh so you can know your rights and responsibilities.
  762. X   It should be in a file named COPYING.
  763. X
  764. X   Among other things, the copyright notice and this notice must be
  765. X   preserved on all copies.
  766. X
  767. X*/
  768. X
  769. X#include "zsh.h"
  770. X
  771. X/* lexical state */
  772. X
  773. Xstatic int xincmdpos,xincond,xincasepat,dbparens,xdbparens,xalstat;
  774. Xstatic char *xhlastw;
  775. X
  776. Xstatic int xisfirstln, xisfirstch, xhistremmed, xhistdone,
  777. X    xspaceflag, xstophist, xlithist, xalstackind,xhlinesz;
  778. Xstatic char *xhline, *xhptr;
  779. X
  780. X/* save the lexical state */
  781. X
  782. X/* is this a hack or what? */
  783. X
  784. Xvoid lexsave() /**/
  785. X{
  786. X    xincmdpos = incmdpos;
  787. X    xincond = incond;
  788. X    xincasepat = incasepat;
  789. X    xdbparens = dbparens;
  790. X    xalstat = alstat;
  791. X    xalstackind = alstackind;
  792. X    xisfirstln = isfirstln;
  793. X    xisfirstch = isfirstch;
  794. X    xhistremmed = histremmed;
  795. X    xhistdone = histdone;
  796. X    xspaceflag = spaceflag;
  797. X    xstophist = stophist;
  798. X    xlithist = lithist;
  799. X    xhline = hline;
  800. X    xhptr = hptr;
  801. X    xhlastw = hlastw;
  802. X    xhlinesz = hlinesz;
  803. X}
  804. X
  805. X/* restore lexical state */
  806. X
  807. Xvoid lexrestore() /**/
  808. X{
  809. X    incmdpos = xincmdpos;
  810. X    incond = xincond;
  811. X    incasepat = xincasepat;
  812. X    dbparens = xdbparens;
  813. X    alstat = xalstat;
  814. X    isfirstln = xisfirstln;
  815. X    isfirstch = xisfirstch;
  816. X    histremmed = xhistremmed;
  817. X    histdone = xhistdone;
  818. X    spaceflag = xspaceflag;
  819. X    stophist = xstophist;
  820. X    lithist = xlithist;
  821. X    hline = xhline;
  822. X    hptr = xhptr;
  823. X    hlastw = xhlastw;
  824. X    clearalstack();
  825. X    alstackind = xalstackind;
  826. X    hlinesz = xhlinesz;
  827. X    lexstop = errflag = 0;
  828. X}
  829. X
  830. Xvoid yylex() /**/
  831. X{
  832. X    if (tok == LEXERR) return;
  833. X    do
  834. X        tok = gettok();
  835. X    while (tok != ENDINPUT && exalias());
  836. X    isnewlin = (tok == NEWLIN && !inbufct);
  837. X    if (tok == SEMI || tok == NEWLIN)
  838. X        tok = SEPER;
  839. X}
  840. X
  841. Xvoid ctxtlex() /**/
  842. X{
  843. Xstatic int oldpos,inredir = 0;
  844. X
  845. X    yylex();
  846. X    switch (tok) {
  847. X    case SEPER: case NEWLIN: case SEMI: case DSEMI: case AMPER:
  848. X    case INPAR: case INBRACE: case DBAR: case DAMPER: case BAR:
  849. X    case BARAMP: case INOUTPAR: case DO: case THEN: case ELIF:
  850. X    case ELSE: incmdpos = 1; break;
  851. X    case STRING: case ENVSTRING: case ENVARRAY: case OUTPAR:
  852. X    case FOR: case SELECT: case FOREACH: case CASE: incmdpos = 0; break;
  853. X    }
  854. X    if (IS_REDIROP(tok)) {
  855. X        inredir = 2;
  856. X        oldpos = incmdpos;
  857. X        incmdpos = 0;
  858. X    } else if (inredir) {
  859. X        if (!--inredir) incmdpos = oldpos;
  860. X        else incmdpos = 0;
  861. X    }
  862. X}
  863. X
  864. X#define LX1_BKSLASH 0
  865. X#define LX1_COMMENT 1
  866. X#define LX1_NEWLIN 2
  867. X#define LX1_SEMI 3
  868. X#define LX1_BANG 4
  869. X#define LX1_AMPER 5
  870. X#define LX1_BAR 6
  871. X#define LX1_INPAR 7
  872. X#define LX1_OUTPAR 8
  873. X#define LX1_INBRACE 9
  874. X#define LX1_OUTBRACE 10
  875. X#define LX1_INBRACK 11
  876. X#define LX1_OUTBRACK 12
  877. X#define LX1_INANG 13
  878. X#define LX1_OUTANG 14
  879. X#define LX1_OTHER 15
  880. X
  881. X#define LX2_BREAK 0
  882. X#define LX2_OUTPAR 1
  883. X#define LX2_BAR 2
  884. X#define LX2_STRING 3
  885. X#define LX2_INBRACK 4
  886. X#define LX2_OUTBRACK 5
  887. X#define LX2_TILDE 6
  888. X#define LX2_INPAR 7
  889. X#define LX2_INBRACE 8
  890. X#define LX2_OUTBRACE 9
  891. X#define LX2_OUTANG 10
  892. X#define LX2_INANG 11
  893. X#define LX2_EQUALS 12
  894. X#define LX2_BKSLASH 13
  895. X#define LX2_QUOTE 14
  896. X#define LX2_DQUOTE 15
  897. X#define LX2_BQUOTE 16
  898. X#define LX2_OTHER 17
  899. X
  900. Xunsigned char lexact1[256],lexact2[256],lextok2[256];
  901. X
  902. Xvoid initlextabs() /**/
  903. X{
  904. Xint t0;
  905. Xstatic char *lx1 = "\\q\n;!&|(){}[]<>xx";
  906. Xstatic char *lx2 = "x)|$[]~({}><=\\\'\"`x";
  907. X
  908. X    for (t0 = 0; t0 != 256; t0++) {
  909. X        lexact1[t0] = LX1_OTHER;
  910. X        lexact2[t0] = LX2_OTHER;
  911. X        lextok2[t0] = t0;
  912. X    }
  913. X    for (t0 = 0; lx1[t0]; t0++)
  914. X        if (lx1[t0] != 'x')
  915. X            lexact1[lx1[t0]] = t0;
  916. X    for (t0 = 0; lx2[t0]; t0++)
  917. X        if (lx2[t0] != 'x')
  918. X            lexact2[lx2[t0]] = t0;
  919. X    lexact2[';'] = LX2_BREAK;
  920. X    lexact2['&'] = LX2_BREAK;
  921. X    lextok2[','] = Comma;
  922. X    lextok2['*'] = Star;
  923. X    lextok2['?'] = Quest;
  924. X    lextok2['{'] = Inbrace;
  925. X    lextok2['['] = Inbrack;
  926. X    lextok2['$'] = String;
  927. X}
  928. X
  929. X/* initialize lexical state */
  930. X
  931. Xvoid lexinit() /**/
  932. X{
  933. X    incond = incasepat = nocorrect =
  934. X        dbparens = alstat = lexstop = 0;
  935. X    incmdpos = 1;
  936. X    tok = ENDINPUT;
  937. X    if (isset(EXTENDEDGLOB))
  938. X        {
  939. X        lextok2['#'] = Pound;
  940. X        lextok2['^'] = Hat;
  941. X        }
  942. X    else
  943. X        {
  944. X        lextok2['#'] = '#'; 
  945. X        lextok2['^'] = '^';
  946. X        }
  947. X}
  948. X
  949. Xint len = 0,bsiz = 256;
  950. Xchar *bptr;
  951. X
  952. X/* add a char to the string buffer */
  953. X
  954. Xvoid add(c) /**/
  955. Xint c;
  956. X{
  957. X    *bptr++ = c;
  958. X    if (bsiz == ++len)
  959. X        {
  960. X        int newbsiz;
  961. X
  962. X        newbsiz = bsiz * 8;
  963. X        while (newbsiz < inbufct)
  964. X            newbsiz *= 2;
  965. X        bptr = len+(tokstr = hrealloc(tokstr,bsiz,newbsiz));
  966. X        bsiz = newbsiz;
  967. X        }
  968. X}
  969. X
  970. Xstatic void unadd()
  971. X{
  972. X    bptr--; bsiz--;
  973. X}
  974. X
  975. Xint gettok() /**/
  976. X{
  977. Xint bct = 0,pct = 0,brct = 0;
  978. Xint c,d,intpos = 1;
  979. Xint peekfd = -1,peek;
  980. X
  981. Xbeginning:
  982. X    hlastw = NULL;
  983. X    tokstr = NULL;
  984. X    parbegin = -1;
  985. X    while (iblank(c = hgetc()) && !lexstop);
  986. X    isfirstln = 0;
  987. X    wordbeg = inbufct;
  988. X    hwbegin();
  989. X    hwaddc(c);
  990. X    if (dbparens)    /* handle ((...)) */
  991. X        {
  992. X        pct = 2;
  993. X        peek = STRING;
  994. X        len = dbparens = 0;
  995. X        bptr = tokstr = ncalloc(bsiz = 256);
  996. X        for (;;)
  997. X            {
  998. X            if (c == '(')
  999. X                pct++;
  1000. X            else if (c == ')')
  1001. X                pct--;
  1002. X            else if (c == '\n')
  1003. X                {
  1004. X                zerr("parse error: )) expected",NULL,0);
  1005. X                peek = LEXERR;
  1006. X                return peek;
  1007. X                }
  1008. X            else if (c == '$')
  1009. X                c = Qstring;
  1010. X            if (pct >= 2)
  1011. X                add(c);
  1012. X            if (pct)
  1013. X                c = hgetc();
  1014. X            else
  1015. X                break;
  1016. X            }
  1017. X        *bptr = '\0';
  1018. X        return peek;
  1019. X        }
  1020. X    if (idigit(c))    /* handle 1< foo */
  1021. X        {
  1022. X        d = hgetc();
  1023. X        hungetc(d);
  1024. X        lexstop = 0;
  1025. X        if (d == '>' || d == '<')
  1026. X            {
  1027. X            peekfd = c-'0';
  1028. X            c = hgetc();
  1029. X            }
  1030. X        }
  1031. X
  1032. X    /* chars in initial position in word */
  1033. X
  1034. X    if (c == hashchar &&
  1035. X            (isset(INTERACTIVECOMMENTS) ||
  1036. X            (!zleparse && (!interact || unset(SHINSTDIN) || strin))))
  1037. X        {
  1038. X        /* changed hgetch to hgetc so comments appear in history */
  1039. X        stophist = 1;
  1040. X        while ((c = hgetc()) != '\n' && !lexstop);
  1041. X        if (c == '\n') {
  1042. X            hwaddc('\n');
  1043. X            peek = NEWLIN;
  1044. X        } else {
  1045. X            peek = (errflag) ? LEXERR : ENDINPUT;
  1046. X            errflag = 1;
  1047. X        }
  1048. X        return peek;
  1049. X        }
  1050. X    if (lexstop)
  1051. X        return (errflag) ? LEXERR : ENDINPUT;
  1052. X    switch (lexact1[(unsigned char) c])
  1053. X        {
  1054. X        case LX1_BKSLASH:
  1055. X            d = hgetc();
  1056. X            if (d == '\n')
  1057. X                goto beginning;
  1058. X            hungetc(d);
  1059. X            break;
  1060. X        case LX1_NEWLIN: return NEWLIN;
  1061. X        case LX1_SEMI:
  1062. X            d = hgetc();
  1063. X            if (d != ';')
  1064. X                {
  1065. X                hungetc(d);
  1066. X                return SEMI;
  1067. X                }
  1068. X            return DSEMI;
  1069. X        case LX1_BANG:
  1070. X            d = hgetc();
  1071. X            hungetc(d);
  1072. X            if (!inblank(d))
  1073. X                break;
  1074. X            if (incmdpos || incond)
  1075. X                return BANG;
  1076. X            break;
  1077. X        case LX1_AMPER:
  1078. X            d = hgetc();
  1079. X            if (d != '&')
  1080. X                {
  1081. X                hungetc(d);
  1082. X                return AMPER;
  1083. X                }
  1084. X            return DAMPER;
  1085. X        case LX1_BAR:
  1086. X            d = hgetc();
  1087. X            if (d == '|')
  1088. X                return DBAR;
  1089. X            else if (d == '&')
  1090. X                return BARAMP;
  1091. X            hungetc(d);
  1092. X            return BAR;
  1093. X        case LX1_INPAR:
  1094. X            d = hgetc();
  1095. X            if (d == '(' && incmdpos)
  1096. X                {
  1097. X                tokstr = strdup("let");
  1098. X                dbparens = 1;
  1099. X                return STRING;
  1100. X                }
  1101. X            else if (d == ')')
  1102. X                return INOUTPAR;
  1103. X            hungetc(d);
  1104. X            if (!(incond || incmdpos))
  1105. X                break;
  1106. X            return INPAR;
  1107. X        case LX1_OUTPAR: return OUTPAR;
  1108. X        case LX1_INBRACE: if (!incmdpos) break; return INBRACE;
  1109. X        case LX1_OUTBRACE: return OUTBRACE;
  1110. X        case LX1_INBRACK:
  1111. X            if (!incmdpos)
  1112. X                break;
  1113. X            d = hgetc();
  1114. X            if (d == '[')
  1115. X                return DINBRACK;
  1116. X            hungetc(d);
  1117. X            break;
  1118. X        case LX1_OUTBRACK:
  1119. X            if (!incond)
  1120. X                break;
  1121. X            d = hgetc();
  1122. X            if (d == ']')
  1123. X                return DOUTBRACK;
  1124. X            hungetc(d);
  1125. X            break;
  1126. X        case LX1_INANG:
  1127. X            d = hgetc();
  1128. X            if ((!incmdpos && d == '(') || incasepat) {
  1129. X                hungetc(d);
  1130. X                break;
  1131. X            } else if (d == '<') {
  1132. X                int e = hgetc();
  1133. X
  1134. X                if (e == '(') {
  1135. X                    hungetc(e);
  1136. X                    hungetc(d);
  1137. X                    peek = INANG;
  1138. X                } else if (e == '<')
  1139. X                    peek = TRINANG;
  1140. X                else if (e == '-')
  1141. X                    peek = DINANGDASH;
  1142. X                else {
  1143. X                    hungetc(e);
  1144. X                    peek = DINANG;
  1145. X                }
  1146. X            } else if (d == '&')
  1147. X                peek = INANGAMP;
  1148. X            else {
  1149. X                peek = INANG;
  1150. X                hungetc(d);
  1151. X            }
  1152. X            tokfd = peekfd;
  1153. X            return peek;
  1154. X        case LX1_OUTANG:
  1155. X            d = hgetc();
  1156. X            if (d == '(')
  1157. X                {
  1158. X                hungetc(d);
  1159. X                break;
  1160. X                }
  1161. X            else if (d == '&')
  1162. X                {
  1163. X                d = hgetc();
  1164. X                if (d == '!')
  1165. X                    peek = OUTANGAMPBANG;
  1166. X                else
  1167. X                    {
  1168. X                    hungetc(d);
  1169. X                    peek = OUTANGAMP;
  1170. X                    }
  1171. X                }
  1172. X            else if (d == '!')
  1173. X                peek = OUTANGBANG;
  1174. X            else if (d == '>')
  1175. X                {
  1176. X                d = hgetc();
  1177. X                if (d == '&')
  1178. X                    {
  1179. X                    d = hgetc();
  1180. X                    if (d == '!')
  1181. X                        peek = DOUTANGAMPBANG;
  1182. X                    else
  1183. X                        {
  1184. X                        hungetc(d);
  1185. X                        peek = DOUTANGAMP;
  1186. X                        }
  1187. X                    }
  1188. X                else if (d == '!')
  1189. X                    peek = DOUTANGBANG;
  1190. X                else if (d == '(')
  1191. X                    {
  1192. X                    hungetc(d);
  1193. X                    hungetc('>');
  1194. X                    peek = OUTANG;
  1195. X                    }
  1196. X                else
  1197. X                    {
  1198. X                    hungetc(d);
  1199. X                    peek = DOUTANG;
  1200. X                    if (isset(NOCLOBBER)) hwaddc('!');
  1201. X                    }
  1202. X                }
  1203. X            else
  1204. X                {
  1205. X                hungetc(d);
  1206. X                peek = OUTANG;
  1207. X                if (isset(NOCLOBBER)) hwaddc('!');
  1208. X                }
  1209. X            tokfd = peekfd;
  1210. X            return peek;
  1211. X        }
  1212. X
  1213. X    /* we've started a string, now get the rest of it, performing
  1214. X        tokenization */
  1215. X
  1216. X    peek = STRING;
  1217. X    len = 0;
  1218. X    bptr = tokstr = ncalloc(bsiz = 256);
  1219. X    for(;;)
  1220. X        {
  1221. X        int act;
  1222. X        int d;
  1223. X        
  1224. X        if (inblank(c))
  1225. X            act = LX2_BREAK;
  1226. X        else
  1227. X            {
  1228. X            act = lexact2[(unsigned char) c];
  1229. X            c = lextok2[(unsigned char) c];
  1230. X            }
  1231. X        switch (act)
  1232. X            {
  1233. X            case LX2_BREAK: goto brk;
  1234. X            case LX2_OUTPAR:
  1235. X                if (!pct)
  1236. X                    goto brk;
  1237. X                c = Outpar;
  1238. X                pct--;
  1239. X                break;
  1240. X            case LX2_BAR:
  1241. X                if (!pct && !incasepat)
  1242. X                    goto brk;
  1243. X                c = Bar;
  1244. X                break;
  1245. X            case LX2_STRING:
  1246. X                d = hgetc();
  1247. X                if (d == '[')
  1248. X                    {
  1249. X                    add(String);
  1250. X                    add(Inbrack);
  1251. X                    while ((c = hgetc()) != ']' && !lexstop)
  1252. X                        add(c);
  1253. X                    c = Outbrack;
  1254. X                    }
  1255. X                else if (d == '(')
  1256. X                    {
  1257. X                    add(String);
  1258. X                    if (skipcomm()) { peek = LEXERR; goto brk; }
  1259. X                    c = Outpar;
  1260. X                    }
  1261. X                else
  1262. X                    hungetc(d);
  1263. X                break;
  1264. X            case LX2_INBRACK: brct++; break;
  1265. X            case LX2_OUTBRACK:
  1266. X                if (incond && !brct)
  1267. X                    goto brk;
  1268. X                brct--;
  1269. X                c = Outbrack;
  1270. X                break;
  1271. X            case LX2_TILDE: /* if (intpos) */ c = Tilde; break;
  1272. X            case LX2_INPAR:
  1273. X                d = hgetc();
  1274. X                hungetc(d);
  1275. X                if (d == ')' || incmdpos)
  1276. X                    goto brk;
  1277. X                pct++;
  1278. X                c = Inpar;
  1279. X                break;
  1280. X            case LX2_INBRACE: bct++; break;
  1281. X            case LX2_OUTBRACE:
  1282. X                if (!bct)
  1283. X                    goto brk;
  1284. X                bct--;
  1285. X                c = Outbrace;
  1286. X                break;
  1287. X            case LX2_OUTANG:
  1288. X                d = hgetc();
  1289. X                if (d != '(')
  1290. X                    {
  1291. X                    hungetc(d);
  1292. X                    goto brk;
  1293. X                    }
  1294. X                add(Outang);
  1295. X                if (skipcomm()) { peek = LEXERR; goto brk; }
  1296. X                c = Outpar;
  1297. X                break;
  1298. X            case LX2_INANG:
  1299. X                d = hgetc();
  1300. X                if (!(idigit(d) || d == '-' || d == '>' || d == '(' || d == ')'))
  1301. X                    {
  1302. X                    hungetc(d);
  1303. X                    goto brk;
  1304. X                    }
  1305. X                c = Inang;
  1306. X                if (d == '(')
  1307. X                    {
  1308. X                    add(c);
  1309. X                    if (skipcomm()) { peek = LEXERR; goto brk; }
  1310. X                    c = Outpar;
  1311. X                    }
  1312. X                else if (d == ')')
  1313. X                    hungetc(d);
  1314. X                else
  1315. X                    {
  1316. X                    add(c);
  1317. X                    c = d;
  1318. X                    while (c != '>' && !lexstop)
  1319. X                        add(c),c = hgetc();
  1320. X                    c = Outang;
  1321. X                    }
  1322. X                break;
  1323. X            case LX2_EQUALS:
  1324. X                if (intpos)
  1325. X                    {
  1326. X                    d = hgetc();
  1327. X                    if (d != '(')
  1328. X                        {
  1329. X                        hungetc(d);
  1330. X                        c = Equals;
  1331. X                        }
  1332. X                    else
  1333. X                        {
  1334. X                        add(Equals);
  1335. X                        if (skipcomm()) { peek = LEXERR; goto brk; }
  1336. X                        c = Outpar;
  1337. X                        }
  1338. X                    }
  1339. X                else if (peek != ENVSTRING && incmdpos)
  1340. X                    {
  1341. X                    d = hgetc();
  1342. X                    if (d == '(' && incmdpos)
  1343. X                        {
  1344. X                        *bptr = '\0';
  1345. X                        return ENVARRAY;
  1346. X                        }
  1347. X                    hungetc(d);
  1348. X                    peek = ENVSTRING;
  1349. X                    intpos = 2;
  1350. X                    }
  1351. X                break;
  1352. X            case LX2_BKSLASH:
  1353. X                c = hgetc();
  1354. X                if (c == '\n')
  1355. X                    {
  1356. X                    c = hgetc();
  1357. X                    continue;
  1358. X                    }
  1359. X                add(c);
  1360. X                c = hgetc();
  1361. X                continue;
  1362. X            case LX2_QUOTE:
  1363. X                add(Nularg);
  1364. X
  1365. X                /* we add the Nularg to prevent this:
  1366. X
  1367. X                echo $PA'TH'
  1368. X
  1369. X                from printing the path. */
  1370. X
  1371. X                for (;;) {
  1372. X                    while ((c = hgetc()) != '\'' && !lexstop) {
  1373. X                        if (isset(CSHJUNKIEQUOTES) && c == '\n') {
  1374. X                            if (bptr[-1] == '\\') unadd(); else break;
  1375. X                        }
  1376. X                        add(c);
  1377. X                    }
  1378. X                    if (c != '\'') {
  1379. X                        zerr("unmatched \'",NULL,0);
  1380. X                        peek = LEXERR;
  1381. X                        goto brk;
  1382. X                    }
  1383. X                    d = hgetc();
  1384. X                    if (d != '\'' || unset(RCQUOTES)) break;
  1385. X                    add(c);
  1386. X                }
  1387. X                hungetc(d);
  1388. X                c = Nularg;
  1389. X                break;
  1390. X            case LX2_DQUOTE:
  1391. X                add(Nularg);
  1392. X                while ((c = hgetc()) != '\"' && !lexstop)
  1393. X                    if (c == '\\')
  1394. X                        {
  1395. X                        c = hgetc();
  1396. X                        if (c != '\n')
  1397. X                            {
  1398. X                            if (c != '$' && c != '\\' && c != '\"' && c != '`')
  1399. X                                add('\\');
  1400. X                            add(c);
  1401. X                            }
  1402. X                        }
  1403. X                    else {
  1404. X                        if (isset(CSHJUNKIEQUOTES) && c == '\n') {
  1405. X                            if (bptr[-1] == '\\') unadd(); else break;
  1406. X                        }
  1407. X                        if (c == '$') {
  1408. X                            d = hgetc();
  1409. X                            if (d == '(') {
  1410. X                                add(Qstring);
  1411. X                                if (skipcomm()) { peek = LEXERR; goto brk; }
  1412. X                                c = Outpar;
  1413. X                            } else if (d == '[') {
  1414. X                                add(String);
  1415. X                                add(Inbrack);
  1416. X                                while ((c = hgetc()) != ']' && !lexstop)
  1417. X                                    add(c);
  1418. X                                c = Outbrack;
  1419. X                            } else {
  1420. X                                c = Qstring;
  1421. X                                hungetc(d);
  1422. X                            }
  1423. X                        } else if (c == '`')
  1424. X                            c = Qtick;
  1425. X                        add(c);
  1426. X                    }
  1427. X                if (c != '\"') {
  1428. X                    zerr("unmatched \"",NULL,0);
  1429. X                    peek = LEXERR;
  1430. X                    goto brk;
  1431. X                }
  1432. X                c = Nularg;
  1433. X                break;
  1434. X            case LX2_BQUOTE:
  1435. X                add(Tick);
  1436. X                parbegin = inbufct;
  1437. X                while ((c = hgetc()) != '`' && !lexstop)
  1438. X                    if (c == '\\')
  1439. X                        {
  1440. X                        c = hgetc();
  1441. X                        if (c != '\n')
  1442. X                            {
  1443. X                            if (c != '`' && c != '\\' && c != '$')
  1444. X                                add('\\');
  1445. X                            add(c);
  1446. X                            }
  1447. X                        }
  1448. X                    else {
  1449. X                        if (isset(CSHJUNKIEQUOTES) && c == '\n') {
  1450. X                            if (bptr[-1] == '\\') unadd(); else break;
  1451. X                        }
  1452. X                        add(c);
  1453. X                    }
  1454. X                if (c != '`') {
  1455. X                    if (!zleparse) zerr("unmatched `",NULL,0);
  1456. X                    peek = LEXERR;
  1457. X                    goto brk;
  1458. X                }
  1459. X                c = Tick;
  1460. X                parbegin = -1;
  1461. X                break;
  1462. X            }
  1463. X        add(c);
  1464. X        c = hgetc();
  1465. X        if (intpos)
  1466. X            intpos--;
  1467. X        if (lexstop)
  1468. X            break;
  1469. X        }
  1470. Xbrk:
  1471. X    hungetc(c);
  1472. X    *bptr = '\0';
  1473. X    return peek;
  1474. X}
  1475. X
  1476. X/* expand aliases, perhaps */
  1477. X
  1478. Xint exalias() /**/
  1479. X{
  1480. Xstruct alias *an;
  1481. Xchar *s,*t;
  1482. X
  1483. X    s = yytext = hwadd();
  1484. X    for (t = s; *t && *t != HISTSPACE; t++);
  1485. X    if (!*t)
  1486. X        t = NULL;
  1487. X    else
  1488. X        *t = '\0';
  1489. X    if (interact && isset(SHINSTDIN) && !strin && !incasepat && tok == STRING &&
  1490. X        (isset(CORRECTALL) || (isset(CORRECT) && incmdpos)) && !nocorrect)
  1491. X            spckword(&tokstr,&s,&t,!incmdpos,1);
  1492. X    if (zleparse && !alstackind)
  1493. X        gotword(s);
  1494. X    an = gethnode(s,aliastab);
  1495. X    if (t)
  1496. X        *t = HISTSPACE;
  1497. X    if (alstackind != MAXAL && an && !an->inuse)
  1498. X        if (!(an->cmd && !incmdpos && alstat != ALSTAT_MORE))
  1499. X            {
  1500. X            if (an->cmd < 0)
  1501. X                {
  1502. X                tok = DO-an->cmd-1;
  1503. X                return 0;
  1504. X                }
  1505. X            else
  1506. X                {
  1507. X                an->inuse = 1;
  1508. X                hungets(ALPOPS);
  1509. X                hungets((alstack[alstackind++] = an)->text);
  1510. X                alstat = 0;
  1511. X                /* remove from history if it begins with space */
  1512. X                if (isset(HISTIGNORESPACE) && an->text[0] == ' ')
  1513. X                    remhist();
  1514. X                lexstop = 0;
  1515. X                return 1;
  1516. X                }
  1517. X            }
  1518. X    return 0;
  1519. X}
  1520. X
  1521. X/* skip (...) */
  1522. X
  1523. Xint skipcomm() /**/
  1524. X{
  1525. Xint pct = 1,c;
  1526. X
  1527. X    parbegin = inbufct;
  1528. X    c = Inpar;
  1529. X    do
  1530. X        {
  1531. X        add(c);
  1532. X        c = hgetc();
  1533. X        if (itok(c) || lexstop)
  1534. X            break;
  1535. X        else if (c == '(') pct++;
  1536. X        else if (c == ')') pct--;
  1537. X        else if (c == '\\')
  1538. X            {
  1539. X            add(c);
  1540. X            c = hgetc();
  1541. X            }
  1542. X        else if (c == '\'')
  1543. X            {
  1544. X            add(c);
  1545. X            while ((c = hgetc()) != '\'' && !lexstop)
  1546. X                add(c);
  1547. X            }
  1548. X        else if (c == '\"')
  1549. X            {
  1550. X            add(c);
  1551. X            while ((c = hgetc()) != '\"' && !lexstop)
  1552. X                if (c == '\\')
  1553. X                    {
  1554. X                    add(c);
  1555. X                    add(hgetc());
  1556. X                    }
  1557. X                else add(c);
  1558. X            }
  1559. X        else if (c == '`')
  1560. X            {
  1561. X            add(c);
  1562. X            while ((c = hgetc()) != '`' && !lexstop)
  1563. X                if (c == '\\') add(c), add(hgetc());
  1564. X                else add(c);
  1565. X            }
  1566. X        }
  1567. X    while(pct);
  1568. X    if (!lexstop) parbegin = -1;
  1569. X    return lexstop;
  1570. X}
  1571. X
  1572. SHAR_EOF
  1573. chmod 0644 zsh2.1/src/lex.c ||
  1574. echo 'restore of zsh2.1/src/lex.c failed'
  1575. Wc_c="`wc -c < 'zsh2.1/src/lex.c'`"
  1576. test 15750 -eq "$Wc_c" ||
  1577.     echo 'zsh2.1/src/lex.c: original size 15750, current size' "$Wc_c"
  1578. rm -f _shar_wnt_.tmp
  1579. fi
  1580. # ============= zsh2.1/src/loop.c ==============
  1581. if test -f 'zsh2.1/src/loop.c' -a X"$1" != X"-c"; then
  1582.     echo 'x - skipping zsh2.1/src/loop.c (File already exists)'
  1583.     rm -f _shar_wnt_.tmp
  1584. else
  1585. > _shar_wnt_.tmp
  1586. echo 'x - extracting zsh2.1/src/loop.c (Text)'
  1587. sed 's/^X//' << 'SHAR_EOF' > 'zsh2.1/src/loop.c' &&
  1588. X/*
  1589. X
  1590. X    loop.c - loop execution
  1591. X
  1592. X    This file is part of zsh, the Z shell.
  1593. X
  1594. X   zsh is free software; no one can prevent you from reading the source
  1595. X   code, or giving it to someone else.
  1596. X   This file is copyrighted under the GNU General Public License, which
  1597. X   can be found in the file called COPYING.
  1598. X
  1599. X   Copyright (C) 1990, 1991 Paul Falstad
  1600. X
  1601. X   zsh is distributed in the hope that it will be useful, but
  1602. X   WITHOUT ANY WARRANTY.  No author or distributor accepts
  1603. X   responsibility to anyone for the consequences of using it or for
  1604. X   whether it serves any particular purpose or works at all, unless he
  1605. X   says so in writing.  Refer to the GNU General Public License
  1606. X   for full details.
  1607. X
  1608. X   Everyone is granted permission to copy, modify and redistribute
  1609. X   zsh, but only under the conditions described in the GNU General Public
  1610. X   License.   A copy of this license is supposed to have been given to you
  1611. X   along with zsh so you can know your rights and responsibilities.
  1612. X   It should be in a file named COPYING.
  1613. X
  1614. X   Among other things, the copyright notice and this notice must be
  1615. X   preserved on all copies.
  1616. X
  1617. X*/
  1618. X
  1619. X#include "zsh.h"
  1620. X
  1621. Xint execfor(cmd) /**/
  1622. XCmd cmd;
  1623. X{
  1624. XList list;
  1625. Xstruct forcmd *node;
  1626. Xchar *str;
  1627. XLklist args;
  1628. Xint cj = thisjob;
  1629. X
  1630. X    loops++;
  1631. X    exiting = 0;
  1632. X    node = cmd->u.forcmd;
  1633. X    args = cmd->args;
  1634. X    if (!node->inflag)
  1635. X        {
  1636. X        char **x;
  1637. X
  1638. X        args = newlist();
  1639. X        for (x = pparams; *x; x++)
  1640. X            addnode(args,ztrdup(*x));
  1641. X        }
  1642. X    pushheap();
  1643. X    while (str = ugetnode(args))
  1644. X        {
  1645. X        setsparam(node->name,ztrdup(str));
  1646. X        list = dupstruct(node->list);
  1647. X        execlist(list);
  1648. X        if (breaks)
  1649. X            {
  1650. X            breaks--;
  1651. X            if (breaks || !contflag)
  1652. X                break;
  1653. X            contflag = 0;
  1654. X            }
  1655. X        if (errflag)
  1656. X            {
  1657. X            lastval = 1;
  1658. X            break;
  1659. X            }
  1660. X        freeheap();
  1661. X        }
  1662. X    popheap();
  1663. X    thisjob = cj;
  1664. X    return lastval;
  1665. X}
  1666. X
  1667. Xint execselect(cmd) /**/
  1668. XCmd cmd;
  1669. X{
  1670. XList list;
  1671. Xstruct forcmd *node;
  1672. Xchar *str,*s;
  1673. XLklist args;
  1674. XLknode n;
  1675. Xint cj = thisjob,t0;
  1676. X
  1677. X    loops++;
  1678. X    node = cmd->u.forcmd;
  1679. X    args = cmd->args;
  1680. X    if (!full(args))
  1681. X        return 1;
  1682. X    exiting = 0;
  1683. X    pushheap();
  1684. X    for (;;)
  1685. X        {
  1686. X        do
  1687. X            {
  1688. X            selectlist(args);
  1689. X            if (interact && SHTTY != -1 && isset(USEZLE))
  1690. X                {
  1691. X                int pl;
  1692. X
  1693. X                str = putprompt(prompt3,&pl);
  1694. X                str = zleread(str,NULL,pl);
  1695. X                }
  1696. X            else
  1697. X                str = fgets(zalloc(256),256,bshin);
  1698. X            if (!str || errflag)
  1699. X                {
  1700. X                fprintf(stderr,"\n");
  1701. X                fflush(stderr);
  1702. X                goto done;
  1703. X                }
  1704. X            if (s = strchr(str,'\n'))
  1705. X                *s = '\0';
  1706. X            }
  1707. X        while (!*str);
  1708. X        setsparam("REPLY",ztrdup(str));
  1709. X        t0 = atoi(str);
  1710. X        if (!t0)
  1711. X            str = "";
  1712. X        else
  1713. X            {
  1714. X            for (t0--,n = firstnode(args); n && t0; incnode(n),t0--);
  1715. X            if (n)
  1716. X                str = getdata(n);
  1717. X            else
  1718. X                str = "";
  1719. X            }
  1720. X        setsparam(node->name,ztrdup(str));
  1721. X        list = dupstruct(node->list);
  1722. X        execlist(list);
  1723. X        freeheap();
  1724. X        if (breaks)
  1725. X            {
  1726. X            breaks--;
  1727. X            if (breaks || !contflag)
  1728. X                break;
  1729. X            contflag = 0;
  1730. X            }
  1731. X        if (errflag)
  1732. X            break;
  1733. X        }
  1734. Xdone:
  1735. X    popheap();
  1736. X    thisjob = cj;
  1737. X    return lastval;
  1738. X}
  1739. Xint execwhile(cmd) /**/
  1740. XCmd cmd;
  1741. X{
  1742. XList list;
  1743. Xstruct whilecmd *node;
  1744. Xint cj = thisjob; 
  1745. X
  1746. X    loops++;
  1747. X    node = cmd->u.whilecmd;
  1748. X    exiting = 0;
  1749. X    pushheap();
  1750. X    for(;;)
  1751. X        {
  1752. X        list = dupstruct(node->cont);
  1753. X        execlist(list);
  1754. X        if (!((lastval == 0) ^ node->cond))
  1755. X            break;
  1756. X        list = dupstruct(node->loop);
  1757. X        execlist(list);
  1758. X        if (breaks)
  1759. X            {
  1760. X            breaks--;
  1761. X            if (breaks || !contflag)
  1762. X                break;
  1763. X            contflag = 0;
  1764. X            }
  1765. X        freeheap();
  1766. X        if (errflag)
  1767. X            {
  1768. X            lastval = 1;
  1769. X            break;
  1770. X            }
  1771. X        }
  1772. X    popheap();
  1773. X    thisjob = cj;
  1774. X    return lastval;
  1775. X}
  1776. Xint execrepeat(cmd) /**/
  1777. XCmd cmd;
  1778. X{
  1779. XList list;
  1780. Xint cj = thisjob,count;
  1781. X
  1782. X    loops++;
  1783. X    exiting = 0;
  1784. X    if (!full(cmd->args) || nextnode(firstnode(cmd->args)))
  1785. X        {
  1786. X        zerr("bad argument for repeat",NULL,0);
  1787. X        return 1;
  1788. X        }
  1789. X    count = atoi(peekfirst(cmd->args));
  1790. X    pushheap();
  1791. X    while (count--)
  1792. X        {
  1793. X        list = dupstruct(cmd->u.list);
  1794. X        execlist(list);
  1795. X        freeheap();
  1796. X        if (breaks)
  1797. X            {
  1798. X            breaks--;
  1799. X            if (breaks || !contflag)
  1800. X                break;
  1801. X            contflag = 0;
  1802. X            }
  1803. X        if (lastval)
  1804. X            break;
  1805. X        if (errflag)
  1806. X            {
  1807. X            lastval = 1;
  1808. X            break;
  1809. X            }
  1810. X        }
  1811. X    popheap();
  1812. X    thisjob = cj;
  1813. X    return lastval;
  1814. X}
  1815. Xint execif(cmd) /**/
  1816. XCmd cmd;
  1817. X{
  1818. Xstruct ifcmd *node;
  1819. Xint cj = thisjob;
  1820. X
  1821. X    node = cmd->u.ifcmd;
  1822. X    exiting = 0;
  1823. X    while (node)
  1824. X        {
  1825. X        if (node->ifl)
  1826. X            {
  1827. X            execlist(node->ifl);
  1828. X            if (lastval)
  1829. X                {
  1830. X                node = node->next;
  1831. X                continue;
  1832. X                }
  1833. X            }
  1834. X        execlist(node->thenl);
  1835. X        break;
  1836. X        }
  1837. X    thisjob = cj;
  1838. X    return lastval;
  1839. X}
  1840. Xint execcase(cmd) /**/
  1841. XCmd cmd;
  1842. X{
  1843. Xstruct casecmd *node;
  1844. Xchar *word;
  1845. XLklist args;
  1846. Xint cj = thisjob;
  1847. X
  1848. X    node = cmd->u.casecmd;
  1849. X    args = cmd->args;
  1850. X    exiting = 0;
  1851. X    if (firstnode(args) && nextnode(firstnode(args)))
  1852. X        {
  1853. X        zerr("too many arguments to case",NULL,0);
  1854. X        errflag = 1;
  1855. X        return 1;
  1856. X        }
  1857. X    if (!full(args))
  1858. X        word = strdup("");
  1859. X    else
  1860. X        word = peekfirst(args);
  1861. X    while (node)
  1862. X        {
  1863. X        singsub(&(node->pat));
  1864. X        if (matchpat(word,node->pat))
  1865. X            break;
  1866. X        else
  1867. X            node = node->next;
  1868. X        }
  1869. X    if (node && node->list)
  1870. X        execlist(node->list);
  1871. X    thisjob = cj;
  1872. X    return lastval;
  1873. X}
  1874. SHAR_EOF
  1875. chmod 0644 zsh2.1/src/loop.c ||
  1876. echo 'restore of zsh2.1/src/loop.c failed'
  1877. Wc_c="`wc -c < 'zsh2.1/src/loop.c'`"
  1878. test 4854 -eq "$Wc_c" ||
  1879.     echo 'zsh2.1/src/loop.c: original size 4854, current size' "$Wc_c"
  1880. rm -f _shar_wnt_.tmp
  1881. fi
  1882. # ============= zsh2.1/src/math.c ==============
  1883. if test -f 'zsh2.1/src/math.c' -a X"$1" != X"-c"; then
  1884.     echo 'x - skipping zsh2.1/src/math.c (File already exists)'
  1885.     rm -f _shar_wnt_.tmp
  1886. else
  1887. > _shar_wnt_.tmp
  1888. echo 'x - extracting zsh2.1/src/math.c (Text)'
  1889. sed 's/^X//' << 'SHAR_EOF' > 'zsh2.1/src/math.c' &&
  1890. X/*
  1891. X
  1892. X    math.c - mathematical expression evaluation
  1893. X
  1894. X    This file is part of zsh, the Z shell.
  1895. X
  1896. X    zsh is free software; no one can prevent you from reading the source
  1897. X   code, or giving it to someone else.
  1898. X
  1899. X   This file is copyrighted under the GNU General Public License, which
  1900. X   can be found in the file called COPYING.
  1901. X
  1902. X   Copyright (C) 1990, 1991 Paul Falstad
  1903. X
  1904. X   zsh is distributed in the hope that it will be useful, but
  1905. X   WITHOUT ANY WARRANTY.  No author or distributor accepts
  1906. X   responsibility to anyone for the consequences of using it or for
  1907. X   whether it serves any particular purpose or works at all, unless he
  1908. X   says so in writing.  Refer to the GNU General Public License
  1909. X   for full details.
  1910. X
  1911. X   Everyone is granted permission to copy, modify and redistribute
  1912. X   zsh, but only under the conditions described in the GNU General Public
  1913. X   License.   A copy of this license is supposed to have been given to you
  1914. X   along with zsh so you can know your rights and responsibilities.
  1915. X   It should be in a file named COPYING.
  1916. X
  1917. X   Among other things, the copyright notice and this notice must be
  1918. X   preserved on all copies.
  1919. X
  1920. X*/
  1921. X
  1922. X#include "zsh.h"
  1923. X
  1924. Xstatic char *ptr;
  1925. X
  1926. Xtypedef int LV;
  1927. X
  1928. Xstatic long yyval;
  1929. Xstatic LV yylval;
  1930. X
  1931. X/* nonzero means we are not evaluating, just parsing */
  1932. X
  1933. Xstatic int noeval = 0;
  1934. X
  1935. X/* != 0 means recognize unary plus, minus, etc. */
  1936. X
  1937. Xstatic int unary = 1;
  1938. X
  1939. Xvoid mathparse DCLPROTO((int));
  1940. X
  1941. X/* LR = left-to-right associativity
  1942. X    RL = right-to-left associativity
  1943. X    BOO = short-circuiting boolean */
  1944. X
  1945. X#define LR 0
  1946. X#define RL 1
  1947. X#define BOOL 2
  1948. X
  1949. X#define M_INPAR 0
  1950. X#define M_OUTPAR 1
  1951. X#define NOT 2
  1952. X#define COMP 3
  1953. X#define POSTPLUS 4
  1954. X#define POSTMINUS 5
  1955. X#define UPLUS 6
  1956. X#define UMINUS 7
  1957. X#define AND 8
  1958. X#define XOR 9
  1959. X#define OR 10
  1960. X#define MUL 11
  1961. X#define DIV 12
  1962. X#define MOD 13
  1963. X#define PLUS 14
  1964. X#define MINUS 15
  1965. X#define SHLEFT 16
  1966. X#define SHRIGHT 17
  1967. X#define LES 18
  1968. X#define LEQ 19
  1969. X#define GRE 20
  1970. X#define GEQ 21
  1971. X#define DEQ 22
  1972. X#define NEQ 23
  1973. X#define DAND 24
  1974. X#define DOR 25
  1975. X#define DXOR 26
  1976. X#define QUEST 27
  1977. X#define COLON 28
  1978. X#define EQ 29
  1979. X#define PLUSEQ 30
  1980. X#define MINUSEQ 31
  1981. X#define MULEQ 32
  1982. X#define DIVEQ 33
  1983. X#define MODEQ 34
  1984. X#define ANDEQ 35
  1985. X#define XOREQ 36
  1986. X#define OREQ 37
  1987. X#define SHLEFTEQ 38
  1988. X#define SHRIGHTEQ 39
  1989. X#define DANDEQ 40
  1990. X#define DOREQ 41
  1991. X#define DXOREQ 42
  1992. X#define COMMA 43
  1993. X#define EOI 44
  1994. X#define PREPLUS 45
  1995. X#define PREMINUS 46
  1996. X#define NUM 47
  1997. X#define ID 48
  1998. X#define TOKCOUNT 49
  1999. X
  2000. X/* precedences */
  2001. X
  2002. Xstatic int prec[TOKCOUNT] = {
  2003. X    1,137,2,2,2,
  2004. X    2,2,2,4,5,
  2005. X    6,7,7,7,8,
  2006. X    8,3,3,9,9,
  2007. X    9,9,10,10,11,
  2008. X    12,12,13,13,14,
  2009. X    14,14,14,14,14,
  2010. X    14,14,14,14,14,
  2011. X    14,14,14,15,200,
  2012. X    2,2,0,0,
  2013. X};
  2014. X
  2015. X#define TOPPREC 15
  2016. X#define ARGPREC (15-1)
  2017. X
  2018. Xstatic int type[TOKCOUNT] = {
  2019. X    LR,LR,RL,RL,RL,
  2020. X    RL,RL,RL,LR,LR,
  2021. X    LR,LR,LR,LR,LR,
  2022. X    LR,LR,LR,LR,LR,
  2023. X    LR,LR,LR,LR,BOOL,
  2024. X    BOOL,LR,RL,RL,RL,
  2025. X    RL,RL,RL,RL,RL,
  2026. X    RL,RL,RL,RL,RL,
  2027. X    BOOL,BOOL,RL,RL,RL,
  2028. X    RL,RL,LR,LR,
  2029. X};
  2030. X
  2031. X#define LVCOUNT 32
  2032. X
  2033. X/* list of lvalues (variables) */
  2034. X
  2035. Xstatic int lvc;
  2036. Xstatic char *lvals[LVCOUNT];
  2037. X
  2038. Xint zzlex() /**/
  2039. X{
  2040. X    for(;;)
  2041. X        switch (*ptr++)
  2042. X            {
  2043. X            case '+':
  2044. X                if (*ptr == '+' && (unary || !ialnum(*ptr)))
  2045. X                    {
  2046. X                    ptr++;
  2047. X                    return (unary) ? PREPLUS : POSTPLUS;
  2048. X                    }
  2049. X                if (*ptr == '=') { unary = 1; ptr++; return PLUSEQ; }
  2050. X                return (unary) ? UPLUS : PLUS;
  2051. X            case '-':
  2052. X                if (*ptr == '-' && (unary || !ialnum(*ptr)))
  2053. X                    {
  2054. X                    ptr++;
  2055. X                    return (unary) ? PREMINUS : POSTMINUS;
  2056. X                    }
  2057. X                if (*ptr == '=') { unary = 1; ptr++; return MINUSEQ; }
  2058. X                return (unary) ? UMINUS : MINUS;
  2059. X            case '(': unary = 1; return M_INPAR;
  2060. X            case ')': return M_OUTPAR;
  2061. X            case '!': if (*ptr == '=')
  2062. X                        { unary = 1; ptr++; return NEQ; }
  2063. X                        return NOT;
  2064. X            case '~': return COMP;
  2065. X            case '&': unary = 1;
  2066. X                if (*ptr == '&') { if (*++ptr == '=')
  2067. X                { ptr++; return DANDEQ; } return DAND; }
  2068. X                else if (*ptr == '=') { ptr++; return ANDEQ; } return AND;
  2069. X            case '|': unary = 1;
  2070. X                if (*ptr == '|') { if (*++ptr == '=')
  2071. X                { ptr++; return DOREQ; } return DOR; }
  2072. X                else if (*ptr == '=') { ptr++; return OREQ; } return OR;
  2073. X            case '^': unary = 1;
  2074. X                if (*ptr == '^') { if (*++ptr == '=')
  2075. X                { ptr++; return DXOREQ; } return DXOR; }
  2076. X                else if (*ptr == '=') { ptr++; return XOREQ; } return XOR;
  2077. X            case '*': unary = 1;
  2078. X                if (*ptr == '=') { ptr++; return MULEQ; } return MUL;
  2079. X            case '/': unary = 1;
  2080. X                if (*ptr == '=') { ptr++; return DIVEQ; } return DIV;
  2081. X            case '%': unary = 1;
  2082. X                if (*ptr == '=') { ptr++; return MODEQ; } return MOD;
  2083. X            case '<': unary = 1; if (*ptr == '<')
  2084. X                { if (*++ptr == '=') { ptr++; return SHLEFTEQ; } return SHLEFT; }
  2085. X                else if (*ptr == '=') { ptr++; return LEQ; } return LES;
  2086. X            case '>': unary = 1; if (*ptr == '>')
  2087. X                { if (*++ptr == '=') { ptr++; return SHRIGHTEQ; } return SHRIGHT; }
  2088. X                else if (*ptr == '=') { ptr++; return GEQ; } return GRE;
  2089. X            case '=': unary = 1; if (*ptr == '=') { ptr++; return DEQ; }
  2090. X                return EQ;
  2091. X            case '?': unary = 1; return QUEST;
  2092. X            case ':': unary = 1; return COLON;
  2093. X            case ',': unary = 1; return COMMA;
  2094. X            case '\0': unary = 1; ptr--; return EOI;
  2095. X            case '[': unary = 0;
  2096. X                { int base = zstrtol(ptr,&ptr,10);
  2097. X                    if (*ptr == ']') ptr++;
  2098. X                    yyval = zstrtol(ptr,&ptr,lastbase = base);
  2099. X                    return NUM; }
  2100. X            case ' ': case '\t':
  2101. X                break;
  2102. X            default:
  2103. X                if (idigit(*--ptr))
  2104. X                    { unary = 0; yyval = zstrtol(ptr,&ptr,10); return NUM; }
  2105. X                if (ialpha(*ptr) || *ptr == '$')
  2106. X                    {
  2107. X                    char *p,q;
  2108. X
  2109. X                    if (*ptr == '$')
  2110. X                        ptr++;
  2111. X                    p = ptr;
  2112. X                    if (lvc == LVCOUNT)
  2113. X                        {
  2114. X                        zerr("too many identifiers (complain to author)",NULL,0);
  2115. X                        return EOI;
  2116. X                        }
  2117. X                    unary = 0;
  2118. X                    while(ialpha(*++ptr));
  2119. X                    q = *ptr;
  2120. X                    *ptr = '\0';
  2121. X                    lvals[yylval = lvc++] = ztrdup(p);
  2122. X                    *ptr = q;
  2123. X                    return ID;
  2124. X                    }
  2125. X                return EOI;
  2126. X            }
  2127. X}
  2128. X
  2129. X/* the value stack */
  2130. X
  2131. X#define STACKSZ 100
  2132. Xint mtok;            /* last token */
  2133. Xint sp = -1;    /* stack pointer */
  2134. Xstruct mathvalue {
  2135. X    LV lval;
  2136. X    long val;
  2137. X    } stack[STACKSZ];
  2138. X
  2139. Xvoid push(val,lval)
  2140. Xlong val;LV lval;
  2141. X{
  2142. X    if (sp == STACKSZ-1)
  2143. X        zerr("stack overflow",NULL,0);
  2144. X    else
  2145. X        sp++;
  2146. X    stack[sp].val = val;
  2147. X    stack[sp].lval = lval;
  2148. X}
  2149. X
  2150. Xlong getvar(s)
  2151. XLV s;
  2152. X{
  2153. Xlong t;
  2154. X
  2155. X    if (!(t = getiparam(lvals[s])))
  2156. X        return 0;
  2157. X    return t;
  2158. X}
  2159. X
  2160. Xlong setvar(s,v)
  2161. XLV s;long v;
  2162. X{
  2163. X    if (s == -1 || s >= lvc)
  2164. X        {
  2165. X        zerr("lvalue required",NULL,0);
  2166. X        return 0;
  2167. X        }
  2168. X    if (noeval)
  2169. X        return v;
  2170. X    setiparam(lvals[s],v);
  2171. X    return v;
  2172. X}
  2173. X
  2174. Xint notzero(a) /**/
  2175. Xint a;
  2176. X{
  2177. X    if (a == 0)
  2178. X        {
  2179. X        zerr("division by zero",NULL,0);
  2180. X        return 0;
  2181. X        }
  2182. X    return 1;
  2183. X}
  2184. X
  2185. X#define pop2() { b = stack[sp--].val; a = stack[sp--].val; }
  2186. X#define pop3() {c=stack[sp--].val;b=stack[sp--].val;a=stack[sp--].val;}
  2187. X#define nolval() {stack[sp].lval= -1;}
  2188. X#define pushv(X) { push(X,-1); }
  2189. X#define pop2lv() { pop2() lv = stack[sp+1].lval; }
  2190. X#define set(X) { push(setvar(lv,X),lv); }
  2191. X
  2192. Xvoid op(what) /**/
  2193. Xint what;
  2194. X{
  2195. Xlong a,b,c;
  2196. XLV lv;
  2197. X
  2198. X    if (sp < 0)
  2199. X        {
  2200. X        zerr("bad math expression: stack empty",NULL,0);
  2201. X        return;
  2202. X        }
  2203. X    switch(what) {
  2204. X        case NOT: stack[sp].val = !stack[sp].val; nolval(); break;
  2205. X        case COMP: stack[sp].val = ~stack[sp].val; nolval(); break;
  2206. X        case POSTPLUS: ( void ) setvar(stack[sp].lval,stack[sp].val+1); break;
  2207. X        case POSTMINUS: ( void ) setvar(stack[sp].lval,stack[sp].val-1); break;
  2208. X        case UPLUS: nolval(); break;
  2209. X        case UMINUS: stack[sp].val = -stack[sp].val; nolval(); break;
  2210. X        case AND: pop2(); pushv(a&b); break;
  2211. X        case XOR: pop2(); pushv(a^b); break;
  2212. X        case OR: pop2(); pushv(a|b); break;
  2213. X        case MUL: pop2(); pushv(a*b); break;
  2214. X        case DIV: pop2(); if (notzero(b)) pushv(a/b); break;
  2215. X        case MOD: pop2(); if (notzero(b)) pushv(a%b); break;
  2216. X        case PLUS: pop2(); pushv(a+b); break;
  2217. X        case MINUS: pop2(); pushv(a-b); break;
  2218. X        case SHLEFT: pop2(); pushv(a<<b); break;
  2219. X        case SHRIGHT: pop2(); pushv(a>>b); break;
  2220. X        case LES: pop2(); pushv(a<b); break;
  2221. X        case LEQ: pop2(); pushv(a<=b); break;
  2222. X        case GRE: pop2(); pushv(a>b); break;
  2223. X        case GEQ: pop2(); pushv(a>=b); break;
  2224. X        case DEQ: pop2(); pushv(a==b); break;
  2225. X        case NEQ: pop2(); pushv(a!=b); break;
  2226. X        case DAND: pop2(); pushv(a&&b); break;
  2227. X        case DOR: pop2(); pushv(a||b); break;
  2228. X        case DXOR: pop2(); pushv(a&&!b||!a&&b); break;
  2229. X        case QUEST: pop3(); pushv((a)?b:c); break;
  2230. X        case COLON: break;
  2231. X        case EQ: pop2lv(); set(b); break;
  2232. X        case PLUSEQ: pop2lv(); set(a+b); break;
  2233. X        case MINUSEQ: pop2lv(); set(a-b); break;
  2234. X        case MULEQ: pop2lv(); set(a*b); break;
  2235. X        case DIVEQ: pop2lv(); if (notzero(b)) set(a/b); break;
  2236. X        case MODEQ: pop2lv(); if (notzero(b)) set(a%b); break;
  2237. X        case ANDEQ: pop2lv(); set(a&b); break;
  2238. X        case XOREQ: pop2lv(); set(a^b); break;
  2239. X        case OREQ: pop2lv(); set(a|b); break;
  2240. X        case SHLEFTEQ: pop2lv(); set(a<<b); break;
  2241. X        case SHRIGHTEQ: pop2lv(); set(a>>b); break;
  2242. X        case DANDEQ: pop2lv(); set(a&&b); break;
  2243. X        case DOREQ: pop2lv(); set(a||b); break;
  2244. X        case DXOREQ: pop2lv(); set(a&&!b||!a&&b); break;
  2245. X        case COMMA: pop2(); pushv(b); break;
  2246. X        case PREPLUS: stack[sp].val = setvar(stack[sp].lval,
  2247. X            stack[sp].val+1); break;
  2248. SHAR_EOF
  2249. true || echo 'restore of zsh2.1/src/math.c failed'
  2250. fi
  2251. echo 'End of zsh2.1.0 part 8'
  2252. echo 'File zsh2.1/src/math.c is continued in part 9'
  2253. echo 9 > _shar_seq_.tmp
  2254. exit 0
  2255.  
  2256. exit 0 # Just in case...
  2257. -- 
  2258. Kent Landfield                   INTERNET: kent@sparky.IMD.Sterling.COM
  2259. Sterling Software, IMD           UUCP:     uunet!sparky!kent
  2260. Phone:    (402) 291-8300         FAX:      (402) 291-4362
  2261. Please send comp.sources.misc-related mail to kent@uunet.uu.net.
  2262.