home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / misc / volume30 / rc / part04 < prev    next >
Encoding:
Text File  |  1992-05-29  |  60.5 KB  |  2,055 lines

  1. Newsgroups: comp.sources.misc
  2. From: byron@archone.tamu.edu (Byron Rakitzis)
  3. Subject:  v30i027:  rc - A Plan 9 shell reimplementation, v1.4, Part04/07
  4. Message-ID: <1992May30.031653.5456@sparky.imd.sterling.com>
  5. X-Md4-Signature: af485377e738596ad8a1fcfab92a3d86
  6. Date: Sat, 30 May 1992 03:16:53 GMT
  7. Approved: kent@sparky.imd.sterling.com
  8.  
  9. Submitted-by: byron@archone.tamu.edu (Byron Rakitzis)
  10. Posting-number: Volume 30, Issue 27
  11. Archive-name: rc/part04
  12. Environment: UNIX
  13. Supersedes: rc: Volume 23, Issue 61-66
  14.  
  15. #! /bin/sh
  16. # This is a shell archive.  Remove anything before this line, then feed it
  17. # into a shell via "sh file" or similar.  To overwrite existing files,
  18. # type "sh file -c".
  19. # The tool that generated this appeared in the comp.sources.unix newsgroup;
  20. # send mail to comp-sources-unix@uunet.uu.net if you want that tool.
  21. # Contents:  addon.c footobar.c glom.c print.c trip.rc.uu walk.c
  22. # Wrapped by kent@sparky on Fri May 29 20:55:24 1992
  23. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  24. echo If this archive is complete, you will see the following message:
  25. echo '          "shar: End of archive 4 (of 7)."'
  26. if test -f 'addon.c' -a "${1}" != "-c" ; then 
  27.   echo shar: Will not clobber existing file \"'addon.c'\"
  28. else
  29.   echo shar: Extracting \"'addon.c'\" \(350 characters\)
  30.   sed "s/^X//" >'addon.c' <<'END_OF_FILE'
  31. X/*
  32. X   This file contains the implementations of any locally defined
  33. X   builtins.
  34. X*/
  35. X
  36. X#ifdef    DWS
  37. X
  38. X/*
  39. X   This is what DaviD Sanderson (dws@cs.wisc.edu) uses.
  40. X*/
  41. X
  42. X#include <sys/types.h>
  43. X#include <sys/file.h>
  44. X#include <sys/stat.h>
  45. X
  46. X#include "rc.h"        /* for bool TRUE, FALSE */
  47. X#include "addon.h"
  48. X
  49. X#include "addon/access.c"
  50. X#include "addon/test.c"
  51. X
  52. X#endif
  53. END_OF_FILE
  54.   if test 350 -ne `wc -c <'addon.c'`; then
  55.     echo shar: \"'addon.c'\" unpacked with wrong size!
  56.   fi
  57.   # end of 'addon.c'
  58. fi
  59. if test -f 'footobar.c' -a "${1}" != "-c" ; then 
  60.   echo shar: Will not clobber existing file \"'footobar.c'\"
  61. else
  62.   echo shar: Extracting \"'footobar.c'\" \(9411 characters\)
  63.   sed "s/^X//" >'footobar.c' <<'END_OF_FILE'
  64. X/*
  65. X   footobar.c: a collection of functions to convert internal representations of
  66. X   variables and functions to external representations, and vice versa
  67. X*/
  68. X
  69. X#include "rc.h"
  70. X
  71. X#define FSCHAR '\1'
  72. X#define FSSTRING "\1"
  73. X
  74. Xstatic char *getenvw(char *, bool);
  75. X
  76. X#ifdef PROTECT_ENV
  77. Xstatic bool Fconv(Format *f, int ignore) {    /* protect an exported name from brain-dead shells */
  78. X    int c;
  79. X    unsigned const char *s = va_arg(f->args, unsigned const char *);
  80. X
  81. X    while ((c = *s++) != '\0')
  82. X        if (dnw[c] || c == '*' || (c == '_' && *s == '_'))
  83. X            fmtprint(f, "__%02x", c);
  84. X        else
  85. X            fmtputc(f, c);
  86. X    return FALSE;
  87. X}
  88. X#endif
  89. X
  90. X/* used to turn a function in Node * form into something we can export to the environment */
  91. X
  92. Xextern char *fun2str(char *name, Node *n) {
  93. X    return mprint("fn_%F={%T}", name, n);
  94. X}
  95. X
  96. X/* convert a redirection to a printable form */
  97. X
  98. Xstatic bool Dconv(Format *f, int ignore) {
  99. X    const char *name = "?";
  100. X    int n = va_arg(f->args, int);
  101. X    switch (n) {
  102. X    case rCreate:        name = ">";    break;
  103. X    case rAppend:        name = ">>";    break;
  104. X    case rFrom:        name = "<";    break;
  105. X    case rHeredoc:        name = "<<";    break;
  106. X    case rHerestring:    name = "<<<";    break;
  107. X    }
  108. X    fmtcat(f, name);
  109. X    return FALSE;
  110. X}
  111. X
  112. X/* defaultfd -- return the default fd for a given redirection operation */
  113. X
  114. Xextern int defaultfd(int op) {
  115. X    return (op == rCreate || op == rAppend) ? 1 : 0;
  116. X}
  117. X
  118. X/* convert a function in Node * form into something rc can parse (and humans can read?) */
  119. X
  120. Xstatic bool Tconv(Format *f, int ignore) {
  121. X    Node *n = va_arg(f->args, Node *);
  122. X    if (n == NULL) {
  123. X        fmtprint(f, "()");
  124. X        return FALSE;
  125. X    }
  126. X    switch (n->type) {
  127. X    case nWord:    fmtprint(f, "%S", n->u[0].s);                break;
  128. X    case nQword:    fmtprint(f, "%#S", n->u[0].s);                break;
  129. X    case nBang:    fmtprint(f, "! %T", n->u[0].p);                break;
  130. X    case nCase:    fmtprint(f, "case %T", n->u[0].p);            break;
  131. X    case nNowait:    fmtprint(f, "%T&", n->u[0].p);                break;
  132. X    case nCount:    fmtprint(f, "$#%T", n->u[0].p);                break;
  133. X    case nFlat:    fmtprint(f, "$^%T", n->u[0].p);                break;
  134. X    case nRmfn:    fmtprint(f, "fn %T", n->u[0].p);            break;
  135. X    case nSubshell:    fmtprint(f, "@ %T", n->u[0].p);                break;
  136. X    case nVar:    fmtprint(f, "$%T", n->u[0].p);                break;
  137. X    case nAndalso:    fmtprint(f, "%T&&%T", n->u[0].p, n->u[1].p);        break;
  138. X    case nAssign:    fmtprint(f, "%T=%T", n->u[0].p, n->u[1].p);        break;
  139. X    case nConcat:    fmtprint(f, "%T^%T", n->u[0].p, n->u[1].p);        break;
  140. X    case nElse:    fmtprint(f, "{%T}else %T", n->u[0].p, n->u[1].p);    break;
  141. X    case nNewfn:    fmtprint(f, "fn %T {%T}", n->u[0].p, n->u[1].p);    break;
  142. X    case nIf:    fmtprint(f, "if(%T)%T", n->u[0].p, n->u[1].p);        break;
  143. X    case nOrelse:    fmtprint(f, "%T||%T", n->u[0].p, n->u[1].p);        break;
  144. X    case nArgs:    fmtprint(f, "%T %T", n->u[0].p, n->u[1].p);        break;
  145. X    case nSwitch:    fmtprint(f, "switch(%T){%T}", n->u[0].p, n->u[1].p);    break;
  146. X    case nMatch:    fmtprint(f, "~ %T %T", n->u[0].p, n->u[1].p);        break;
  147. X    case nVarsub:    fmtprint(f, "$%T(%T)", n->u[0].p, n->u[1].p);        break;
  148. X    case nWhile:    fmtprint(f, "while(%T)%T", n->u[0].p, n->u[1].p);    break;
  149. X    case nLappend:    fmtprint(f, "(%T %T)", n->u[0].p, n->u[1].p);        break;
  150. X    case nForin:    fmtprint(f, "for(%T in %T)%T", n->u[0].p, n->u[1].p, n->u[2].p); break;
  151. X    case nDup:
  152. X        if (n->u[2].i != -1)
  153. X            fmtprint(f, "%D[%d=%d]", n->u[0].i, n->u[1].i, n->u[2].i);
  154. X        else
  155. X            fmtprint(f, "%D[%d=]", n->u[0].i, n->u[1].i);
  156. X        break;
  157. X    case nBackq: {
  158. X        Node *n0 = n->u[0].p, *n00;
  159. X        if (n0 != NULL && n0->type == nVar
  160. X            && (n00 = n0->u[0].p) != NULL && n00->type == nWord && streq(n00->u[0].s, "ifs"))
  161. X            fmtprint(f, "`");
  162. X        else
  163. X            fmtprint(f, "``%T", n0);
  164. X        fmtprint(f, "{%T}", n->u[1].p);
  165. X        break;
  166. X    }
  167. X    case nCbody:
  168. X    case nBody: {
  169. X        Node *n0 = n->u[0].p;
  170. X        if (n0 != NULL)
  171. X            fmtprint(f, "%T", n->u[0].p);
  172. X        if (n->u[1].p != NULL) {
  173. X            if (n0 != NULL && n0->type != nNowait)
  174. X                fmtprint(f, ";");
  175. X            fmtprint(f, "%T", n->u[1].p);
  176. X        }
  177. X        break;
  178. X    }
  179. X    case nBrace:
  180. X        fmtprint(f, "{%T}", n->u[0].p);
  181. X        if (n->u[1].p != NULL)
  182. X            fmtprint(f, "%T", n->u[1].p);
  183. X        break;
  184. X    case nEpilog:
  185. X    case nPre:
  186. X        fmtprint(f, "%T", n->u[0].p);
  187. X        if (n->u[1].p != NULL)
  188. X            fmtprint(f, " %T", n->u[1].p);
  189. X        break;
  190. X    case nPipe: {
  191. X        int ofd = n->u[0].i, ifd = n->u[1].i;
  192. X        fmtprint(f, "%T|", n->u[2].p);
  193. X        if (ifd != 0)
  194. X            fmtprint(f, "[%d=%d]", ofd, ifd);
  195. X        else if (ofd != 1)
  196. X            fmtprint(f, "[%d]", ofd);
  197. X        fmtprint(f, "%T", n->u[3].p);
  198. X        break;
  199. X    }
  200. X    case nRedir: {
  201. X        int op = n->u[0].i;
  202. X        fmtprint(f, "%D", op);
  203. X        if (n->u[1].i != defaultfd(op))
  204. X            fmtprint(f, "[%d]", n->u[1].i);
  205. X        fmtprint(f, "%T", n->u[2].p);
  206. X        break;
  207. X    }
  208. X    case nNmpipe: {
  209. X        int op = n->u[0].i;
  210. X        fmtprint(f, "%D", op);
  211. X        if (n->u[1].i != defaultfd(op))
  212. X            fmtprint(f, "[%d]", n->u[1].i);
  213. X        fmtprint(f, "{%T}", n->u[2].p);
  214. X        break;
  215. X    }
  216. X     }
  217. X    return FALSE;
  218. X}
  219. X
  220. X/* convert a List to a string, separating it with ^A characters. Used for exporting variables to the environment */
  221. X
  222. Xextern char *list2str(char *name, List *s) {
  223. X    SIZE_T size, step;
  224. X    List *t;
  225. X    char *w, *x;
  226. X    name = nprint("%F", name);
  227. X    size = strlen(name) + listlen(s);
  228. X    w = ealloc(size + 2);
  229. X    t = s;
  230. X    x = w;
  231. X    strcpy(x, name);
  232. X    strcpy(x += strlen(name), "=");
  233. X    strcpy(x += conststrlen("="), t->w);
  234. X    for (x += strlen(t->w), s = s->n; s != NULL; s = s->n) {
  235. X        memcpy(x, FSSTRING, step = conststrlen(FSSTRING));
  236. X        x += step;
  237. X        memcpy(x, s->w, step = strlen(s->w));
  238. X        x += step;
  239. X    }
  240. X    *x = '\0';
  241. X    return w;
  242. X}
  243. X
  244. X/* convert a List to an array, for execve() */
  245. X
  246. Xextern char **list2array(List *s, bool print) {
  247. X    char **av;
  248. X    int i;
  249. X
  250. X    /* 4 == 1 for the null terminator + 2 for the fake execve() + 1 for defaulting to sh */
  251. X    av = nalloc((listnel(s) + 4) * sizeof (char *));
  252. X    av += 3; /* hide the two free spots from rc (two for #! emulation, one for defaulting to sh) */
  253. X    if (print)
  254. X        fprint(2, "%L\n", s, " ");
  255. X    for (i = 0; s != NULL; i++) {
  256. X        av[i] = s->w;
  257. X        s = s->n;
  258. X    }
  259. X    av[i] = NULL;
  260. X    return av;
  261. X}
  262. X
  263. X/* figure out the name of a variable given an environment string. copy this into malloc space */
  264. X
  265. Xextern char *get_name(char *s) {
  266. X    int c;
  267. X    SIZE_T i;
  268. X    char *r, *namebuf;
  269. X    for (i = 0; s[i] != '\0' && s[i] != '='; i++)
  270. X        ;
  271. X    if (s[i] == '\0')
  272. X        return NULL;
  273. X    r = namebuf = ealloc(i + 1);
  274. X    while (1)
  275. X        switch (c = *s++) {
  276. X        case '=':
  277. X            *r++ = '\0';
  278. X            return namebuf;
  279. X#ifdef PROTECT_ENV
  280. X        case '_':
  281. X            if (*s == '_') {
  282. X                static const char hexchar[] = "0123456789abcdef";
  283. X                char *h1 = strchr(hexchar, s[1]);
  284. X                char *h2 = strchr(hexchar, s[2]);
  285. X                if (h1 != NULL && h2 != NULL) {
  286. X                    *r++ = ((h1 - hexchar) << 4) | (h2 - hexchar);
  287. X                    s += 3;
  288. X                    break;
  289. X                }
  290. X            }
  291. X            /* FALLTHROUGH */
  292. X#endif
  293. X        default:
  294. X            *r++ = c;
  295. X            break;
  296. X        }
  297. X}
  298. X
  299. X/* get the next word from a variable's value as represented in the environment. */
  300. X
  301. Xstatic char *getenvw(char *s, bool saw_alpha) {
  302. X    SIZE_T i;
  303. X    char *r;
  304. X    for (i = 0; s[i] != '\0' && s[i] != FSCHAR; i++)
  305. X        ;
  306. X    if (i == 0) {
  307. X        if (s[i] == '\0' && !saw_alpha)
  308. X            return NULL;
  309. X        else
  310. X            return clear(enew(char), (SIZE_T) 1);
  311. X    }
  312. X    r = strncpy(ealloc(i + 1), s, i);
  313. X    r[i] = '\0';
  314. X    return r;
  315. X}
  316. X
  317. X/* take an environment entry for a variable (elements ^A separated) and turn it into a List */
  318. X
  319. Xextern List *parse_var(char *name, char *extdef) {
  320. X    List *r, *top;
  321. X    char *f;
  322. X    bool saw_alpha;
  323. X    top = r = enew(List);
  324. X    extdef = strchr(extdef, '=') + 1;
  325. X    if ((f = getenvw(extdef, FALSE)) == NULL) {
  326. X        r->w = "";
  327. X        r->m = NULL;
  328. X        r->n = NULL;
  329. X    } else {
  330. X        while (1) {
  331. X            r->w = f;
  332. X            r->m = NULL;
  333. X            extdef += strlen(f);
  334. X            if (*extdef == FSCHAR) {
  335. X                extdef++;
  336. X                saw_alpha = TRUE;
  337. X            } else {
  338. X                saw_alpha = FALSE;
  339. X            }
  340. X            if ((f = getenvw(extdef, saw_alpha)) == NULL) {
  341. X                r->n = NULL;
  342. X                break;
  343. X            }
  344. X            r = r->n = enew(List);
  345. X        }
  346. X    }
  347. X    return top;
  348. X}
  349. X
  350. X/* get an environment entry for a function and have rc parse it. */
  351. X
  352. X#define PREFIX "fn x"
  353. X#define PRELEN conststrlen(PREFIX)
  354. Xextern Node *parse_fn(char *name, char *extdef) {
  355. X    Node *def;
  356. X    char *s, old[PRELEN];
  357. X    if ((s = strchr(extdef, '=')) == NULL)
  358. X        return NULL;
  359. X    memcpy(old, s -= (PRELEN-1), PRELEN);
  360. X    memcpy(s, PREFIX, PRELEN);
  361. X    def = parseline(s);
  362. X    memcpy(s, old, PRELEN);
  363. X    return (def == NULL || def->type != nNewfn) ? NULL : def->u[1].p;
  364. X}
  365. X
  366. Xstatic bool Aconv(Format *f, int c) {
  367. X    char **a = va_arg(f->args, char **);
  368. X    if (*a != NULL) {
  369. X        fmtcat(f, *a);
  370. X        while (*++a != NULL)
  371. X            fmtprint(f, " %s", *a);
  372. X    }
  373. X    return FALSE;
  374. X}
  375. X
  376. Xstatic bool Lconv(Format *f, int c) {
  377. X    List *l = va_arg(f->args, List *);
  378. X    char *sep = va_arg(f->args, char *);
  379. X    char *fmt = (f->flags & FMT_leftside) ? "%s%s" : "%-S%s";
  380. X    if (l == NULL && (f->flags & FMT_leftside) == 0)
  381. X        fmtprint(f, "()");
  382. X    else {
  383. X        List *s;
  384. X        for (s = l; s != NULL; s = s->n)
  385. X            fmtprint(f, fmt, s->w, s->n == NULL ? "" : sep);
  386. X    }
  387. X    return FALSE;
  388. X}
  389. X
  390. X#define    ISMETA(c)    (c == '*' || c == '?' || c == '[')
  391. X
  392. Xstatic bool Sconv(Format *f, int ignore) {
  393. X    int c;
  394. X    unsigned char *s = va_arg(f->args, unsigned char *), *t = s;
  395. X    bool quoted    = (f->flags & FMT_altform)  != 0;    /* '#' */
  396. X    bool metaquote = (f->flags & FMT_leftside) != 0;    /* '-' */
  397. X    if (*s == '\0') {
  398. X        fmtprint(f, "''");
  399. X        return FALSE;
  400. X    }
  401. X    if (!quoted) {
  402. X        while ((c = *t++) != '\0')
  403. X            if (nw[c] == 1 || (metaquote && ISMETA(c)))
  404. X                goto quoteit;
  405. X        fmtprint(f, "%s", s);
  406. X        return FALSE;
  407. X    }
  408. Xquoteit:
  409. X    fmtputc(f, '\'');
  410. X    while ((c = *s++) != '\0') {
  411. X        fmtputc(f, c);
  412. X        if (c == '\'')
  413. X            fmtputc(f, '\'');
  414. X
  415. X    }
  416. X    fmtputc(f, '\'');
  417. X    return FALSE;
  418. X}
  419. X
  420. Xvoid initprint(void) {
  421. X    fmtinstall('A', Aconv);
  422. X    fmtinstall('L', Lconv);
  423. X    fmtinstall('S', Sconv);
  424. X    fmtinstall('T', Tconv);
  425. X    fmtinstall('D', Dconv);
  426. X#ifdef PROTECT_ENV
  427. X    fmtinstall('F', Fconv);
  428. X#else
  429. X    fmtinstall('F', fmtinstall('s', NULL));
  430. X#endif
  431. X}
  432. END_OF_FILE
  433.   if test 9411 -ne `wc -c <'footobar.c'`; then
  434.     echo shar: \"'footobar.c'\" unpacked with wrong size!
  435.   fi
  436.   # end of 'footobar.c'
  437. fi
  438. if test -f 'glom.c' -a "${1}" != "-c" ; then 
  439.   echo shar: Will not clobber existing file \"'glom.c'\"
  440. else
  441.   echo shar: Extracting \"'glom.c'\" \(8963 characters\)
  442.   sed "s/^X//" >'glom.c' <<'END_OF_FILE'
  443. X/* glom.c: builds an argument list out of words, variables, etc. */
  444. X
  445. X#include <sys/types.h>
  446. X#include <sys/stat.h>
  447. X#include <signal.h>
  448. X#include "rc.h"
  449. X#if !defined(S_IFIFO) && !defined(DEVFD)
  450. X#define NOCMDARG
  451. X#endif
  452. X
  453. Xstatic List *backq(Node *, Node *);
  454. Xstatic List *bqinput(List *, int);
  455. Xstatic List *count(List *);
  456. Xstatic List *mkcmdarg(Node *);
  457. X
  458. XRq *redirq = NULL;
  459. X
  460. Xextern List *word(char *w, char *m) {
  461. X    List *s = NULL;
  462. X    if (w != NULL) {
  463. X        s = nnew(List);
  464. X        s->w = w;
  465. X        s->m = m;
  466. X        s->n = NULL;
  467. X    }
  468. X    return s;
  469. X}
  470. X
  471. X/*
  472. X   Append list s2 to list s1 by copying s1 and making the new copy
  473. X   point at s2.
  474. X*/
  475. X
  476. Xextern List *append(List *s1, List *s2) {
  477. X    List *r, *top;
  478. X    if (s1 == NULL)
  479. X        return s2;
  480. X    if (s2 == NULL)
  481. X        return s1;
  482. X    for (r = top = nnew(List); 1; r = r->n = nnew(List)) {
  483. X        r->w = s1->w;
  484. X        r->m = s1->m;
  485. X        if ((s1 = s1->n) == NULL)
  486. X            break;
  487. X    }
  488. X    r->n = s2;
  489. X    return top;
  490. X}
  491. X
  492. Xextern List *concat(List *s1, List *s2) {
  493. X    int n1, n2;
  494. X    List *r, *top;
  495. X    if (s1 == NULL)
  496. X        return s2;
  497. X    if (s2 == NULL)
  498. X        return s1;
  499. X    if ((n1 = listnel(s1)) != (n2 = listnel(s2)) && n1 != 1 && n2 != 1)
  500. X        rc_error("bad concatenation");
  501. X    for (r = top = nnew(List); 1; r = r->n = nnew(List)) {
  502. X        SIZE_T x = strlen(s1->w);
  503. X        SIZE_T y = strlen(s2->w);
  504. X        SIZE_T z = x + y + 1;
  505. X        r->w = nalloc(z);
  506. X        strcpy(r->w, s1->w);
  507. X        strcat(r->w, s2->w);
  508. X        if (s1->m == NULL && s2->m == NULL) {
  509. X            r->m = NULL;
  510. X        } else {
  511. X            r->m = nalloc(z);
  512. X            if (s1->m == NULL)
  513. X                clear(r->m, x);
  514. X            else
  515. X                memcpy(r->m, s1->m, x);
  516. X            if (s2->m == NULL)
  517. X                clear(&r->m[x], y);
  518. X            else
  519. X                memcpy(&r->m[x], s2->m, y);
  520. X            r->m[z] = 0;
  521. X        }
  522. X        if (n1 > 1)
  523. X            s1 = s1->n;
  524. X        if (n2 > 1)
  525. X            s2 = s2->n;
  526. X        if (s1 == NULL || s2 == NULL || (n1 == 1 && n2 == 1))
  527. X            break;
  528. X    }
  529. X    r->n = NULL;
  530. X    return top;
  531. X}
  532. X
  533. Xextern List *varsub(List *var, List *subs) {
  534. X    List *r, *top;
  535. X    int n = listnel(var);
  536. X    for (top = r = NULL; subs != NULL; subs = subs->n) {
  537. X        int i = a2u(subs->w);
  538. X        if (i < 1)
  539. X            rc_error("bad subscript");
  540. X        if (i <= n) {
  541. X            List *sub = var;
  542. X            while (--i)
  543. X                sub = sub->n; /* loop until sub == var(i) */
  544. X            if (top == NULL)
  545. X                top = r = nnew(List);
  546. X            else
  547. X                r = r->n = nnew(List);
  548. X            r->w = sub->w;
  549. X            r->m = sub->m;
  550. X        }
  551. X    }
  552. X    if (top != NULL)
  553. X        r->n = NULL;
  554. X    return top;
  555. X}
  556. X
  557. Xextern List *flatten(List *s) {
  558. X    List *r;
  559. X    SIZE_T step;
  560. X    char *f;
  561. X    if (s == NULL || s->n == NULL)
  562. X        return s;
  563. X    r = nnew(List);
  564. X    f = r->w = nalloc(listlen(s) + 1);
  565. X    r->m = NULL; /* flattened lists come from variables, so no meta */
  566. X    r->n = NULL;
  567. X    strcpy(f, s->w);
  568. X    f += strlen(s->w);
  569. X    do {
  570. X        *f++ = ' ';
  571. X        s = s->n;
  572. X        step = strlen(s->w);
  573. X        memcpy(f, s->w, step);
  574. X        f += step;
  575. X    } while (s->n != NULL);
  576. X    *f = '\0';
  577. X    return r;
  578. X}
  579. X
  580. Xstatic List *count(List *l) {
  581. X    List *s = nnew(List);
  582. X    s->w = nprint("%d", listnel(l));
  583. X    s->n = NULL;
  584. X    s->m = NULL;
  585. X    return s;
  586. X}
  587. X
  588. Xextern void assign(List *s1, List *s2, bool stack) {
  589. X    List *val = s2;
  590. X    if (s1 == NULL)
  591. X        rc_error("null variable name");
  592. X    if (s1->n != NULL)
  593. X        rc_error("multi-word variable name");
  594. X    if (*s1->w == '\0')
  595. X        rc_error("zero-length variable name");
  596. X    if (a2u(s1->w) != -1)
  597. X        rc_error("numeric variable name");
  598. X    if (strchr(s1->w, '=') != NULL)
  599. X        rc_error("'=' in variable name");
  600. X    if (*s1->w == '*' && s1->w[1] == '\0')
  601. X        val = append(varlookup("0"), s2); /* preserve $0 when * is assigned explicitly */
  602. X    if (s2 != NULL || stack) {
  603. X        if (dashex)
  604. X            prettyprint_var(2, s1->w, val);
  605. X        varassign(s1->w, val, stack);
  606. X        alias(s1->w, varlookup(s1->w), stack);
  607. X    } else {
  608. X        if (dashex)
  609. X            prettyprint_var(2, s1->w, NULL);
  610. X        varrm(s1->w, stack);
  611. X    }
  612. X}
  613. X
  614. X/*
  615. X   The following two functions are by the courtesy of Paul Haahr,
  616. X   who could not stand the incompetence of my own backquote implementation.
  617. X*/
  618. X
  619. X#define BUFSIZE    ((SIZE_T) 1000)
  620. X
  621. Xstatic List *bqinput(List *ifs, int fd) {
  622. X    char *end, *bufend, *s;
  623. X    List *r, *top, *prev;
  624. X    SIZE_T remain, bufsize;
  625. X    char isifs[256];
  626. X    int n, state; /* a simple FSA is used to read in data */
  627. X
  628. X    clear(isifs, sizeof isifs);
  629. X    for (isifs['\0'] = TRUE; ifs != NULL; ifs = ifs->n)
  630. X        for (s = ifs->w; *s != '\0'; s++)
  631. X            isifs[*(unsigned char *)s] = TRUE;
  632. X    remain = bufsize = BUFSIZE;
  633. X    top = r = nnew(List);
  634. X    r->w = end = nalloc(bufsize + 1);
  635. X    r->m = NULL;
  636. X    state = 0;
  637. X    prev = NULL;
  638. X
  639. X    while (1) {
  640. X        if (remain == 0) { /* is the string bigger than the buffer? */
  641. X            SIZE_T m = end - r->w;
  642. X            char *buf;
  643. X            while (bufsize < m + BUFSIZE)
  644. X                bufsize *= 2;
  645. X            buf = nalloc(bufsize + 1);
  646. X            memcpy(buf, r->w, m);
  647. X            r->w = buf;
  648. X            end = &buf[m];
  649. X            remain = bufsize - m;
  650. X        }
  651. X        if ((n = rc_read(fd, end, remain)) <= 0) {
  652. X            if (n == 0)
  653. X    /* break */        break;
  654. X            uerror("backquote read");
  655. X            rc_error(NULL);
  656. X        }
  657. X        remain -= n;
  658. X        for (bufend = &end[n]; end < bufend; end++)
  659. X            if (state == 0) {
  660. X                if (!isifs[*(unsigned char *)end]) {
  661. X                    state = 1;
  662. X                    r->w = end;
  663. X                }
  664. X            } else {
  665. X                if (isifs[*(unsigned char *)end]) {
  666. X                    state = 0;
  667. X                    *end = '\0';
  668. X                    prev = r;
  669. X                    r = r->n = nnew(List);
  670. X                    r->w = end+1;
  671. X                    r->m = NULL;
  672. X                }
  673. X            }
  674. X    }
  675. X    if (state == 1) { /* terminate last string */
  676. X        *end = '\0';
  677. X        r->n = NULL;
  678. X    } else {
  679. X        if (prev == NULL) /* no input at all? */
  680. X            top = NULL;
  681. X        else
  682. X            prev->n = NULL; /* else terminate list */
  683. X    }
  684. X    return top;
  685. X}
  686. X
  687. Xstatic List *backq(Node *ifs, Node *n) {
  688. X    int p[2], pid, sp;
  689. X    List *bq;
  690. X    if (n == NULL)
  691. X        return NULL;
  692. X    if (pipe(p) < 0) {
  693. X        uerror("pipe");
  694. X        rc_error(NULL);
  695. X    }
  696. X    if ((pid = rc_fork()) == 0) {
  697. X        setsigdefaults(FALSE);
  698. X        mvfd(p[1], 1);
  699. X        close(p[0]);
  700. X        redirq = NULL;
  701. X        walk(n, FALSE);
  702. X        exit(getstatus());
  703. X    }
  704. X    close(p[1]);
  705. X    bq = bqinput(glom(ifs), p[0]);
  706. X    close(p[0]);
  707. X    rc_wait4(pid, &sp, TRUE);
  708. X    statprint(-1, sp);
  709. X    SIGCHK;
  710. X    return bq;
  711. X}
  712. X
  713. Xextern void qredir(Node *n) {
  714. X    Rq *next;
  715. X    if (redirq == NULL) {
  716. X        next = redirq = nnew(Rq);
  717. X    } else {
  718. X        for (next = redirq; next->n != NULL; next = next->n)
  719. X            ;
  720. X        next->n = nnew(Rq);
  721. X        next = next->n;
  722. X    }
  723. X    next->r = n;
  724. X    next->n = NULL;
  725. X}
  726. X
  727. X#ifdef NOCMDARG
  728. Xstatic List *mkcmdarg(Node *n) {
  729. X    rc_error("named pipes are not supported");
  730. X    return NULL;
  731. X}
  732. X#else
  733. X#ifndef DEVFD
  734. Xstatic List *mkcmdarg(Node *n) {
  735. X    int fd;
  736. X    char *name;
  737. X    Edata efifo;
  738. X    Estack *e = enew(Estack);
  739. X    List *ret = nnew(List);
  740. X    static int fifonumber = 0;
  741. X    name = nprint("%s/rc%d.%d", TMPDIR, getpid(), fifonumber++);
  742. X    if (mknod(name, S_IFIFO | 0666, 0) < 0) {
  743. X        uerror("mknod");
  744. X        return NULL;
  745. X    }
  746. X    if (rc_fork() == 0) {
  747. X        setsigdefaults(FALSE);
  748. X        fd = rc_open(name, (n->u[0].i != rFrom) ? rFrom : rCreate); /* stupid hack */
  749. X        if (fd < 0) {
  750. X            uerror("open");
  751. X            exit(1);
  752. X        }
  753. X        if (mvfd(fd, (n->u[0].i == rFrom)) < 0) /* same stupid hack */
  754. X            exit(1);
  755. X        redirq = NULL;
  756. X        walk(n->u[2].p, FALSE);
  757. X        exit(getstatus());
  758. X    }
  759. X    efifo.name = name;
  760. X    except(eFifo, efifo, e);
  761. X    ret->w = name;
  762. X    ret->m = NULL;
  763. X    ret->n = NULL;
  764. X    return ret;
  765. X}
  766. X#else
  767. Xstatic List *mkcmdarg(Node *n) {
  768. X    char *name;
  769. X    List *ret = nnew(List);
  770. X    Estack *e = nnew(Estack);
  771. X    Edata efd;
  772. X    int p[2];
  773. X    if (pipe(p) < 0) {
  774. X        uerror("pipe");
  775. X        return NULL;
  776. X    }
  777. X    if (rc_fork() == 0) {
  778. X        setsigdefaults(FALSE);
  779. X        if (mvfd(p[n->u[0].i == rFrom], n->u[0].i == rFrom) < 0) /* stupid hack */
  780. X            exit(1);
  781. X        close(p[n->u[0].i != rFrom]);
  782. X        redirq = NULL;
  783. X        walk(n->u[2].p, FALSE);
  784. X        exit(getstatus());
  785. X    }
  786. X    name = nprint("/dev/fd/%d", p[n->u[0].i != rFrom]);
  787. X    efd.fd = p[n->u[0].i != rFrom];
  788. X    except(eFd, efd, e);
  789. X    close(p[n->u[0].i == rFrom]);
  790. X    ret->w = name;
  791. X    ret->m = NULL;
  792. X    ret->n = NULL;
  793. X    return ret;
  794. X}
  795. X#endif /* DEVFD */
  796. X#endif /* !NOCMDARG */
  797. X
  798. Xextern List *glom(Node *n) {
  799. X    List *v, *head, *tail;
  800. X    Node *words;
  801. X    if (n == NULL)
  802. X        return NULL;
  803. X    switch (n->type) {
  804. X    case nArgs:
  805. X    case nLappend:
  806. X        words = n->u[0].p;
  807. X        tail = NULL;
  808. X        while (words != NULL && (words->type == nArgs || words->type == nLappend)) {
  809. X            if (words->u[1].p != NULL && words->u[1].p->type != nWord && words->u[1].p->type != nQword)
  810. X                break;
  811. X            head = glom(words->u[1].p);
  812. X            if (head != NULL) {
  813. X                head->n = tail;
  814. X                tail = head;
  815. X            }
  816. X            words = words->u[0].p;
  817. X        }
  818. X        v = append(glom(words), tail); /* force left to right evaluation */
  819. X        return append(v, glom(n->u[1].p));
  820. X    case nBackq:
  821. X        return backq(n->u[0].p, n->u[1].p);
  822. X    case nConcat:
  823. X        head = glom(n->u[0].p); /* force left-to-right evaluation */
  824. X        return concat(head, glom(n->u[1].p));
  825. X    case nDup:
  826. X    case nRedir:
  827. X        qredir(n);
  828. X        return NULL;
  829. X    case nWord:
  830. X    case nQword:
  831. X        return word(n->u[0].s, n->u[1].s);
  832. X    case nNmpipe:
  833. X        return mkcmdarg(n);
  834. X    default:
  835. X        /*
  836. X           The next four operations depend on the left-child of glom
  837. X           to be a variable name. Therefore the variable is looked up
  838. X           here.
  839. X        */
  840. X        if ((v = glom(n->u[0].p)) == NULL)
  841. X            rc_error("null variable name");
  842. X        if (v->n != NULL)
  843. X            rc_error("multi-word variable name");
  844. X        if (*v->w == '\0')
  845. X            rc_error("zero-length variable name");
  846. X        v = (*v->w == '*' && v->w[1] == '\0') ? varlookup(v->w)->n : varlookup(v->w);
  847. X        switch (n->type) {
  848. X        default:
  849. X            panic("unexpected node in glom");
  850. X            exit(1);
  851. X            /* NOTREACHED */
  852. X        case nCount:
  853. X            return count(v);
  854. X        case nFlat:
  855. X            return flatten(v);
  856. X        case nVar:
  857. X            return v;
  858. X        case nVarsub:
  859. X            return varsub(v, glom(n->u[1].p));
  860. X        }
  861. X    }
  862. X}
  863. END_OF_FILE
  864.   if test 8963 -ne `wc -c <'glom.c'`; then
  865.     echo shar: \"'glom.c'\" unpacked with wrong size!
  866.   fi
  867.   # end of 'glom.c'
  868. fi
  869. if test -f 'print.c' -a "${1}" != "-c" ; then 
  870.   echo shar: Will not clobber existing file \"'print.c'\"
  871. else
  872.   echo shar: Extracting \"'print.c'\" \(9329 characters\)
  873.   sed "s/^X//" >'print.c' <<'END_OF_FILE'
  874. X/* print.c -- formatted printing routines (Paul Haahr, 12/91) */
  875. X
  876. X#include "rc.h"
  877. X#include <setjmp.h>
  878. X
  879. X#define    PRINT_ALLOCSIZE    ((SIZE_T)64)
  880. X#define    SPRINT_BUFSIZ    ((SIZE_T)1024)
  881. X
  882. X#define    MAXCONV 256
  883. X
  884. X/*
  885. X * conversion functions
  886. X *    true return -> flag changes only, not a conversion
  887. X */
  888. X
  889. X#define Flag(name, flag) \
  890. Xstatic bool name(Format *format, int c) { \
  891. X    format->flags |= flag; \
  892. X    return TRUE; \
  893. X}
  894. X
  895. XFlag(uconv,    FMT_unsigned)
  896. XFlag(hconv,    FMT_short)
  897. XFlag(lconv,    FMT_long)
  898. XFlag(altconv,    FMT_altform)
  899. XFlag(leftconv,    FMT_leftside)
  900. XFlag(dotconv,    FMT_f2set)
  901. X
  902. Xstatic bool digitconv(Format *format, int c) {
  903. X    if (format->flags & FMT_f2set)
  904. X        format->f2 = 10 * format->f2 + c - '0';
  905. X    else {
  906. X        format->flags |= FMT_f1set;
  907. X        format->f1 = 10 * format->f1 + c - '0';
  908. X    }
  909. X    return TRUE;
  910. X}
  911. X
  912. Xstatic bool zeroconv(Format *format, int c) {
  913. X    if (format->flags & (FMT_f1set | FMT_f2set))
  914. X        return digitconv(format, '0');
  915. X    format->flags |= FMT_zeropad;
  916. X    return TRUE;
  917. X}
  918. X
  919. Xstatic void pad(Format *format, SIZE_T len, int c) {
  920. X    while (len-- != 0)
  921. X        fmtputc(format, c);
  922. X}
  923. X
  924. Xstatic bool sconv(Format *format, int c) {
  925. X    char *s = va_arg(format->args, char *);
  926. X    if ((format->flags & FMT_f1set) == 0)
  927. X        fmtcat(format, s);
  928. X    else {
  929. X        SIZE_T len = strlen(s), width = format->f1 - len;
  930. X        if (format->flags & FMT_leftside) {
  931. X            fmtappend(format, s, len);
  932. X            pad(format, width, ' ');
  933. X        } else {
  934. X            pad(format, width, ' ');
  935. X            fmtappend(format, s, len);
  936. X        }
  937. X    }
  938. X    return FALSE;
  939. X}
  940. X
  941. Xstatic char *utoa(unsigned long u, char *t, unsigned int radix, const char *digit) {
  942. X    if (u >= radix) {
  943. X        t = utoa(u / radix, t, radix, digit);
  944. X        u %= radix;
  945. X    }
  946. X    *t++ = digit[u];
  947. X    return t;
  948. X}
  949. X
  950. Xstatic void intconv(Format *format, unsigned int radix, int upper, const char *altform) {
  951. X    static const char * const table[] = {
  952. X        "0123456789abcdefghijklmnopqrstuvwxyz",
  953. X        "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ",
  954. X    };
  955. X    char padchar;
  956. X    SIZE_T len, pre, zeroes, padding, width;
  957. X    long n, flags;
  958. X    unsigned long u;
  959. X    char number[64], prefix[20];
  960. X
  961. X    if (radix > 36)
  962. X        return;
  963. X
  964. X    flags = format->flags;
  965. X    if (flags & FMT_long)
  966. X        n = va_arg(format->args, long);
  967. X    else if (flags & FMT_short)
  968. X        n = va_arg(format->args, short);
  969. X    else
  970. X        n = va_arg(format->args, int);
  971. X
  972. X    pre = 0;
  973. X    if ((flags & FMT_unsigned) || n >= 0)
  974. X        u = n;
  975. X    else {
  976. X        prefix[pre++] = '-';
  977. X        u = -n;
  978. X    }
  979. X
  980. X    if (flags & FMT_altform)
  981. X        while (*altform != '\0')
  982. X            prefix[pre++] = *altform++;
  983. X
  984. X    len = utoa(u, number, radix, table[upper]) - number;
  985. X    if ((flags & FMT_f2set) && (SIZE_T) format->f2 > len)
  986. X        zeroes = format->f2 - len;
  987. X    else
  988. X        zeroes = 0;
  989. X
  990. X    width = pre + zeroes + len;
  991. X    if ((flags & FMT_f1set) && (SIZE_T) format->f1 > width) {
  992. X        padding = format->f1 - width;
  993. X    } else
  994. X        padding = 0;
  995. X
  996. X    padchar = ' ';
  997. X    if (padding > 0 && flags & FMT_zeropad) {
  998. X        padchar = '0';
  999. X        if ((flags & FMT_leftside) == 0) {
  1000. X            zeroes += padding;
  1001. X            padding = 0;
  1002. X        }
  1003. X    }
  1004. X
  1005. X
  1006. X    if ((flags & FMT_leftside) == 0)
  1007. X        pad(format, padding, padchar);
  1008. X    fmtappend(format, prefix, pre);
  1009. X    pad(format, zeroes, '0');
  1010. X    fmtappend(format, number, len);
  1011. X    if (flags & FMT_leftside)
  1012. X        pad(format, padding, padchar);
  1013. X}
  1014. X
  1015. Xstatic bool cconv(Format *format, int c) {
  1016. X    fmtputc(format, va_arg(format->args, int));
  1017. X    return FALSE;
  1018. X}
  1019. X
  1020. Xstatic bool dconv(Format *format, int c) {
  1021. X    intconv(format, 10, 0, "");
  1022. X    return FALSE;
  1023. X}
  1024. X
  1025. Xstatic bool oconv(Format *format, int c) {
  1026. X    intconv(format, 8, 0, "0");
  1027. X    return FALSE;
  1028. X}
  1029. X
  1030. Xstatic bool xconv(Format *format, int c) {
  1031. X    intconv(format, 16, 0, "0x");
  1032. X    return FALSE;
  1033. X}
  1034. X
  1035. Xstatic bool pctconv(Format *format, int c) {
  1036. X    fmtputc(format, '%');
  1037. X    return FALSE;
  1038. X}
  1039. X
  1040. Xstatic bool badconv(Format *format, int c) {
  1041. X    panic("bad conversion character in printfmt");
  1042. X    /* NOTREACHED */
  1043. X    return FALSE; /* hush up gcc -Wall */
  1044. X}
  1045. X
  1046. X
  1047. X/*
  1048. X * conversion table management
  1049. X */
  1050. X
  1051. Xstatic Conv fmttab[MAXCONV];
  1052. X
  1053. Xstatic void inittab(void) {
  1054. X    int i;
  1055. X    for (i = 0; i < MAXCONV; i++)
  1056. X        fmttab[i] = badconv;
  1057. X
  1058. X    fmttab['s'] = sconv;
  1059. X    fmttab['c'] = cconv;
  1060. X    fmttab['d'] = dconv;
  1061. X    fmttab['o'] = oconv;
  1062. X    fmttab['x'] = xconv;
  1063. X    fmttab['%'] = pctconv;
  1064. X
  1065. X    fmttab['u'] = uconv;
  1066. X    fmttab['h'] = hconv;
  1067. X    fmttab['l'] = lconv;
  1068. X    fmttab['#'] = altconv;
  1069. X    fmttab['-'] = leftconv;
  1070. X    fmttab['.'] = dotconv;
  1071. X
  1072. X    fmttab['0'] = zeroconv;
  1073. X    for (i = '1'; i <= '9'; i++)
  1074. X        fmttab[i] = digitconv;
  1075. X}
  1076. X
  1077. Xextern bool (*fmtinstall(int c, bool (*f)(Format *, int)))(Format *, int) {
  1078. X/*Conv fmtinstall(int c, Conv f) {*/
  1079. X    Conv oldf;
  1080. X    if (fmttab[0] == NULL)
  1081. X        inittab();
  1082. X    c &= MAXCONV - 1;
  1083. X    oldf = fmttab[c];
  1084. X    if (f != NULL)
  1085. X        fmttab[c] = f;
  1086. X    return oldf;
  1087. X}
  1088. X
  1089. X
  1090. X/*
  1091. X * functions for inserting strings in the format buffer
  1092. X */
  1093. X
  1094. Xextern void fmtappend(Format *format, const char *s, SIZE_T len) {
  1095. X    while (format->buf + len > format->bufend) {
  1096. X        SIZE_T split = format->bufend - format->buf;
  1097. X        memcpy(format->buf, s, split);
  1098. X        format->buf += split;
  1099. X        s += split;
  1100. X        len -= split;
  1101. X        (*format->grow)(format, len);
  1102. X    }
  1103. X    memcpy(format->buf, s, len);
  1104. X    format->buf += len;
  1105. X}
  1106. X
  1107. Xextern void fmtcat(Format *format, const char *s) {
  1108. X    fmtappend(format, s, strlen(s));
  1109. X}
  1110. X
  1111. X/*
  1112. X * printfmt -- the driver routine
  1113. X */
  1114. X
  1115. Xextern int printfmt(Format *format, const char *fmt) {
  1116. X    unsigned const char *s = (unsigned const char *) fmt;
  1117. X
  1118. X    if (fmttab[0] == NULL)
  1119. X        inittab();
  1120. X
  1121. X    for (;;) {
  1122. X        int c = *s++;
  1123. X        switch (c) {
  1124. X        case '%':
  1125. X            format->flags = format->f1 = format->f2 = 0;
  1126. X            do
  1127. X                c = *s++;
  1128. X            while ((*fmttab[c])(format, c));
  1129. X            break;
  1130. X        case '\0':
  1131. X            return format->buf - format->bufbegin + format->flushed;
  1132. X        default:
  1133. X            fmtputc(format, c);
  1134. X            break;
  1135. X        }
  1136. X    }
  1137. X}
  1138. X
  1139. X
  1140. X/*
  1141. X * the public entry points
  1142. X */
  1143. X
  1144. Xextern int fmtprint(Format *format, const char *fmt,...) {
  1145. X    int n = -format->flushed;
  1146. X    va_list saveargs = format->args;
  1147. X
  1148. X    va_start(format->args, fmt);
  1149. X    n += printfmt(format, fmt);
  1150. X    va_end(format->args);
  1151. X    format->args = saveargs;
  1152. X
  1153. X    return n + format->flushed;
  1154. X}
  1155. X
  1156. Xstatic void fprint_flush(Format *format, SIZE_T more) {
  1157. X    SIZE_T n = format->buf - format->bufbegin;
  1158. X    char *buf = format->bufbegin;
  1159. X
  1160. X    format->flushed += n;
  1161. X    format->buf = format->bufbegin;
  1162. X    writeall(format->u.n, buf, n);
  1163. X}
  1164. X
  1165. Xextern int fprint(int fd, const char *fmt,...) {
  1166. X    char buf[1024];
  1167. X    Format format;
  1168. X
  1169. X    format.buf    = buf;
  1170. X    format.bufbegin    = buf;
  1171. X    format.bufend    = buf + sizeof buf;
  1172. X    format.grow    = fprint_flush;
  1173. X    format.flushed    = 0;
  1174. X    format.u.n    = fd;
  1175. X
  1176. X    va_start(format.args, fmt);
  1177. X    printfmt(&format, fmt);
  1178. X    va_end(format.args);
  1179. X
  1180. X    fprint_flush(&format, (SIZE_T) 0);
  1181. X    return format.flushed;
  1182. X}
  1183. X
  1184. Xstatic void memprint_grow(Format *format, SIZE_T more) {
  1185. X    char *buf;
  1186. X    SIZE_T len = format->bufend - format->bufbegin + 1;
  1187. X    len = (len >= more)
  1188. X        ? len * 2
  1189. X        : ((len + more) + PRINT_ALLOCSIZE) &~ (PRINT_ALLOCSIZE - 1);
  1190. X    if (format->u.n)
  1191. X        buf = erealloc(format->bufbegin, len);
  1192. X    else {
  1193. X        SIZE_T used = format->buf - format->bufbegin;
  1194. X        buf = nalloc(len);
  1195. X        memcpy(buf, format->bufbegin, used);
  1196. X    }
  1197. X    format->buf     = buf + (format->buf - format->bufbegin);
  1198. X    format->bufbegin = buf;
  1199. X    format->bufend     = buf + len - 1;
  1200. X}
  1201. X
  1202. Xstatic char *memprint(Format *format, const char *fmt, char *buf, SIZE_T len) {
  1203. X    format->buf     = buf;
  1204. X    format->bufbegin = buf;
  1205. X    format->bufend     = buf + len - 1;
  1206. X    format->grow     = memprint_grow;
  1207. X    format->flushed     = 0;
  1208. X    printfmt(format, fmt);
  1209. X    *format->buf = '\0';
  1210. X    return format->bufbegin;
  1211. X}
  1212. X
  1213. Xextern char *mprint(const char *fmt,...) {
  1214. X    Format format;
  1215. X    char *result;
  1216. X    format.u.n = 1;
  1217. X    va_start(format.args, fmt);
  1218. X    result = memprint(&format, fmt, ealloc(PRINT_ALLOCSIZE), PRINT_ALLOCSIZE);
  1219. X    va_end(format.args);
  1220. X    return result;
  1221. X}
  1222. X
  1223. Xextern char *nprint(const char *fmt,...) {
  1224. X    Format format;
  1225. X    char *result;
  1226. X    format.u.n = 0;
  1227. X    va_start(format.args, fmt);
  1228. X    result = memprint(&format, fmt, nalloc(PRINT_ALLOCSIZE), PRINT_ALLOCSIZE);
  1229. X    va_end(format.args);
  1230. X    return result;
  1231. X}
  1232. X
  1233. X
  1234. X/* THESE ARE UNUSED IN rc */
  1235. X
  1236. X#if 0
  1237. X
  1238. Xextern int print(const char *fmt,...) {
  1239. X    char buf[1024];
  1240. X    Format format;
  1241. X
  1242. X    format.buf    = buf;
  1243. X    format.bufbegin    = buf;
  1244. X    format.bufend    = buf + sizeof buf;
  1245. X    format.grow    = fprint_flush;
  1246. X    format.flushed    = 0;
  1247. X    format.u.n    = 1;
  1248. X
  1249. X    va_start(format.args, fmt);
  1250. X    printfmt(&format, fmt);
  1251. X    va_end(format.args);
  1252. X
  1253. X    fprint_flush(&format, 0);
  1254. X    return format.flushed;
  1255. X}
  1256. X
  1257. Xextern int eprint(const char *fmt,...) {
  1258. X    char buf[1024];
  1259. X    Format format;
  1260. X
  1261. X    format.buf    = buf;
  1262. X    format.bufbegin    = buf;
  1263. X    format.bufend    = buf + sizeof buf;
  1264. X    format.grow    = fprint_flush;
  1265. X    format.flushed    = 0;
  1266. X    format.u.n    = 2;
  1267. X
  1268. X    va_start(format.args, fmt);
  1269. X    printfmt(&format, fmt);
  1270. X    va_end(format.args);
  1271. X
  1272. X    fprint_flush(&format, 0);
  1273. X    return format.flushed;
  1274. X}
  1275. X
  1276. Xstatic void snprint_grow(Format *format, SIZE_T more) {
  1277. X    longjmp(format->u.p, 1);
  1278. X}
  1279. X
  1280. Xextern int snprint(char *buf, int buflen, const char *fmt,...) {
  1281. X    int n;
  1282. X    jmp_buf jbuf;
  1283. X    Format format;
  1284. X
  1285. X    if (setjmp(jbuf)) {
  1286. X        *format.buf = '\0';
  1287. X        return format.buf - format.bufbegin;
  1288. X    }
  1289. X
  1290. X    format.buf    = buf;
  1291. X    format.bufbegin    = buf;
  1292. X    format.bufend    = buf + buflen - 1;
  1293. X    format.grow    = snprint_grow;
  1294. X    format.flushed    = 0;
  1295. X    format.u.p    = jbuf;
  1296. X
  1297. X    va_start(format.args, fmt);
  1298. X    n = printfmt(&format, fmt);
  1299. X    va_end(format.args);
  1300. X
  1301. X    *format.buf = '\0';
  1302. X    return n;
  1303. X}
  1304. X
  1305. Xextern int sprint(char *buf, const char *fmt,...) {
  1306. X    int n;
  1307. X    jmp_buf jbuf;
  1308. X    Format format;
  1309. X
  1310. X    if (setjmp(jbuf)) {
  1311. X        *format.buf = '\0';
  1312. X        return format.buf - format.bufbegin;
  1313. X    }
  1314. X
  1315. X    format.buf    = buf;
  1316. X    format.bufbegin    = buf;
  1317. X    format.bufend    = buf + SPRINT_BUFSIZ - 1;
  1318. X    format.grow    = snprint_grow;
  1319. X    format.flushed    = 0;
  1320. X    format.u.p    = jbuf;
  1321. X
  1322. X    va_start(format.args, fmt);
  1323. X    n = printfmt(&format, fmt);
  1324. X    va_end(format.args);
  1325. X
  1326. X    *format.buf = '\0';
  1327. X    return n;
  1328. X}
  1329. X#endif
  1330. END_OF_FILE
  1331.   if test 9329 -ne `wc -c <'print.c'`; then
  1332.     echo shar: \"'print.c'\" unpacked with wrong size!
  1333.   fi
  1334.   # end of 'print.c'
  1335. fi
  1336. if test -f 'trip.rc.uu' -a "${1}" != "-c" ; then 
  1337.   echo shar: Will not clobber existing file \"'trip.rc.uu'\"
  1338. else
  1339.   echo shar: Extracting \"'trip.rc.uu'\" \(20258 characters\)
  1340.   sed "s/^X//" >'trip.rc.uu' <<'END_OF_FILE'
  1341. Xbegin 644 trip.rc
  1342. XM(R!T<FEP+G)C("TM('1A:V4@82!T;W5R(&]F(')C"B,@26YV;VME(&%S(")P
  1343. XM871H+71O+6YE=RUR8R`\('1R:7`N<F,B"@IR8STD,`IE8VAO('1R:7!P:6YG
  1344. XM("1R8PH*9FX@9F%I;"!["@EE8VAO(#Y;,3TR72!T<FEP('1O;VL@82!W<F]N
  1345. XM9R!T=7)N.B`D*@H)<FT@+68@)'1M<`H)97AI="`Q"GT*9FX@97AP96-T('L*
  1346. XM"65C:&\@/ELQ/3)=("UN(&5X<&5C="`D7BI>)SH@)PI]"F9N('-U8FUA=&-H
  1347. XM('L*"6EF("@A?B`D(RH@,RD*"0EF86EL(&EN8V]R<F5C="!I;G9O8V%T:6]N
  1348. XM(&]F('-U8FUA=&-H"@EP<F]M<'0])&YL(&EF("@A?B!@8"`D;FP@>R1R8R`M
  1349. XM:6,@)#$^6S(],5U]("0R*0H)"69A:6P@)#,*?0IF;B!S:6=E>&ET('-I9VEN
  1350. XM="!S:6=Q=6ET('-I9W-E9W8*9FX@<VEG97AI="!["@EE8VAO('1R:7`@8V]M
  1351. XM<&QE=&4*?0IT;7`]+W1M<"]T<FEP+B1P:60*<FT@+68@)'1M<`IN;#TG"B<*
  1352. XM"B,*(R!R8R`M8PHC"@II9B`H)')C("UC(#Y;,ETO9&5V+VYU;&PI(&9A:6P@
  1353. XM)W)C("UC(&1I9&XG)W0@<F5P;W)T(&$@8F%D(&5X:70@<W1A='5S)PIX/6![
  1354. XM)')C("UC("=E8VAO("0P("0R("0C*B<@82!B(&,@9"!E(&9]"FEF("AF86QS
  1355. XM92D@>PD)"0D)(R!705).24Y'.B!T:&ES(&1I9F9E<G,@9G)O;2!S:`H):68@
  1356. XM*"%^("1X*#$I(&$I(&9A:6P@<F,@+6,@<F5P;W)T<R`G)#`G(&EN8V]R<F5C
  1357. XM=&QY(&%S("1X*#$I"@EI9B`H(7X@)'@H,BD@8RD@9F%I;"!R8R`M8R!R97!O
  1358. XM<G1S("<D,B<@:6YC;W)R96-T;'D@87,@)'@H,BD*"6EF("@A?B`D>"@S*2`U
  1359. XM*2!F86EL(')C("UC(')E<&]R=',@)R0C)R!I;F-O<G)E8W1L>2!A<R`D>"@S
  1360. XM*0I](&5L<V4@>PH):68@*"%^("1X*#$I("1R8RD@9F%I;"!R8R`M8R!R97!O
  1361. XM<G1S("<D,"<@:6YC;W)R96-T;'D@87,@)'@H,2D*"6EF("@A?B`D>"@R*2!B
  1362. XM*2!F86EL(')C("UC(')E<&]R=',@)R0R)R!I;F-O<G)E8W1L>2!A<R`D>"@R
  1363. XM*0H):68@*"%^("1X*#,I(#8I(&9A:6P@<F,@+6,@<F5P;W)T<R`G)",G(&EN
  1364. XM8V]R<F5C=&QY(&%S("1X*#,I"GT*"B,*(R!U;6%S:PHC"@IU;6%S:R`P"CX@
  1365. XM)'1M<`IX/6![;',@+6P@)'1M<'T*:68@*"%^("1X*#$I("<M<G<M<G<M<G<M
  1366. XM)RD@9F%I;"!U;6%S:R`P('!R;V1U8V5D(&EN8V]R<F5C="!R97-U;'0Z("1X
  1367. XM*#$I"G)M("UF("1T;7`*=6UA<VL@,#(W"CX@)'1M<`IY/6![;',@+6P@)'1M
  1368. XM<'T*:68@*"%^("1Y*#$I("<M<G<M<BTM+2TM)RD@9F%I;"!U;6%S:R`P,C<@
  1369. XM<')O9'5C960@:6YC;W)R96-T(&9I;&4Z("1Y*#$I"G)M("UF("1T;7`*:68@
  1370. XM*"%^(&!U;6%S:R`P,C<I(&9A:6P@=6UA<VL@<F5P;W)T960@8F%D('9A;'5E
  1371. XM.B!@=6UA<VL*"G-U8FUA=&-H("=U;6%S:R!B860G("=B860@=6UA<VLG("=B
  1372. XM860@=6UA<VLG"G-U8FUA=&-H("=U;6%S:R`M,#(W)R`G8F%D('5M87-K)R`G
  1373. XM8F%D('5M87-K)PIS=6)M871C:"`G=6UA<VL@.3DY.3DY)R`G8F%D('5M87-K
  1374. XM)R`G8F%D('5M87-K)PIS=6)M871C:"`G=6UA<VL@:&D@=&AE<F4G("=T;V\@
  1375. XM;6%N>2!A<F=U;65N=',@=&\@=6UA<VLG("=U;6%S:R!A<F<@8V]U;G0G"@II
  1376. XM9B`H(7X@8'5M87-K(#`R-RD@9F%I;"!B860@=6UA<VL@8VAA;F=E9"!U;6%S
  1377. XM:R!V86QU92!T;R!@=6UA<VL*"B,*(R!R961I<F5C=&EO;G,*(PH*9FX@8GET
  1378. XM97,@>R!F;W(@*&DI('@]8'MW8R`M8R`D:7T@96-H;R`D>"@Q*2!]"F5C:&\@
  1379. XM9F]O(#X@9F]O(#X@8F%R"FEF("@A?B!@>V)Y=&5S(&9O;WT@,"D@9F%I;"!D
  1380. XM;W5B;&4@<F5D:7)E8W1I;VX@8W)E871E9"!N;VXM96UP='D@96UP='D@9FEL
  1381. XM90II9B`H(7X@8'MB>71E<R!B87)](#0I(&9A:6P@9&]U8FQE(')E9&ER96-T
  1382. XM:6]N(&-R96%T960@=W)O;F<@<VEZ960@9FEL93H@8'MB>71E<R!B87)]"G)M
  1383. XM("UF(&9O;R!B87(*96-H;R`M;B`^,2`^6S)=,B`^6S$],ET@9F]O"G@@/2!@
  1384. XM8"`G)R![8V%T(#%]"FEF("@A?B`D(W@@,"D@9F%I;"!D=7`@8W)E871E9"!N
  1385. XM;VXM96UP='D@96UP='D@9FEL93H@8&`@)R<@>V-A="`Q?0II9B`H(7X@8&`@
  1386. XM)R<@>V-A="`R?2!F;V\I(&9A:6P@9'5P('!U="!W<F]N9R!C;VYT96YT<R!I
  1387. XM;B!F:6QE(#H@8&`@)R<@>V-A="`R?0IR;2`M9B`Q(#(*"F5X<&5C="!E<G)O
  1388. XM<B!F<F]M(&-A="P@8VQO<VEN9R!S=&1I;@IC870@/ELP/5T*"G-U8FUA=&-H
  1389. XM("=C870^*#$@,B`S*2<@)VUU;'1I+7=O<F0@9FEL96YA;64@:6X@<F5D:7)E
  1390. XM8W1I;VXG("=R961I<F5C=&EO;B!E<G)O<B<*<W5B;6%T8V@@)V-A=#XH*2<@
  1391. XM)VYU;&P@9FEL96YA;64@:6X@<F5D:7)E8W1I;VXG("=R961I<F5C=&EO;B!E
  1392. XM<G)O<B<*"B,*(R!B;&]W('1H92!I;G!U="!S=&%C:PHC"@II9B`H(7X@:&D@
  1393. XM8'L*979A;"!E=F%L(&5V86P@979A;"!E=F%L(&5V86P@979A;"!E=F%L(&5V
  1394. XM86P@979A;"!E=F%L(&5V86P@979A;"!<"F5V86P@979A;"!E=F%L(&5V86P@
  1395. XM979A;"!E=F%L(&5V86P@979A;"!E=F%L(&5V86P@979A;"!E=F%L(&5V86P@
  1396. XM7`IE=F%L(&5V86P@979A;"!E=F%L(&5V86P@979A;"!E=F%L(&5V86P@979A
  1397. XM;"!E=F%L(&5V86P@979A;"!E=F%L(%P*979A;"!E=F%L(&5V86P@979A;"!E
  1398. XM=F%L(&5V86P@979A;"!E=F%L(&5V86P@979A;"!E=F%L(&5V86P@979A;"!<
  1399. XM"F5V86P@979A;"!E=F%L(&5V86P@979A;"!E=F%L(&5V86P@979A;"!E=F%L
  1400. XM(&5V86P@979A;"!E=F%L(&5V86P@7`IE=F%L(&5V86P@979A;"!E=F%L(&5V
  1401. XM86P@979A;"!E=F%L(&5V86P@979A;"!E=F%L(&5V86P@979A;"!E=F%L(%P*
  1402. XM979A;"!E=F%L(&5V86P@979A;"!E=F%L(&5V86P@979A;"!E=F%L(&5V86P@
  1403. XM979A;"!E=F%L(&5V86P@979A;"!<"F5V86P@979A;"!E=F%L(&5V86P@979A
  1404. XM;"!E=F%L(&5V86P@979A;"!E=F%L(&5V86P@979A;"!E=F%L(&5V86P@7`IE
  1405. XM=F%L(&5V86P@979A;"!E=F%L(&5V86P@979A;"!E=F%L(&5V86P@979A;"!E
  1406. XM=F%L(&5V86P@979A;"!E=F%L(%P*979A;"!E=F%L(&5V86P@979A;"!E=F%L
  1407. XM(&5V86P@979A;"!E=F%L(&5V86P@979A;"!E=F%L(&5V86P@979A;"!<"F5V
  1408. XM86P@979A;"!E=F%L(&5V86P@979A;"!E=F%L(&5V86P@979A;"!E=F%L(&5V
  1409. XM86P@979A;"!E8VAO(&AI"GTI"@EF86EL(&AU9V4@979A;`H*(PHC(&AE<F5D
  1410. XM;V-S(&%N9"!H97)E<W1R:6YG<PHC"@IB:6=F:6QE/2]T;7`O8FEG+B1P:60*
  1411. XM;V0@)')C('P@<V5D(#4P,#!Q(#X@)&)I9V9I;&4*86)C/2AT:&ES(&ES(&$I
  1412. XM"G@]*"D*<F5S=6QT/2=T:&ES(&ES(&$@:&5R961O8PIT:&ES(&ES(&%N(&AE
  1413. XM<F5D;V,*)PII9B`H(7X@8&`@)R<@>SP\6S5=($5/1B!C870@/%LP/35=?2`D
  1414. XM<F5S=6QT*2!F86EL('5N<75O=&5D(&AE<F5D;V,*)&%B8R!H97)E9&]C)'@*
  1415. XM)&%B8UYN("1X7FAE<F4D>%YD;V,*14]&"GMI9B`H(7X@8&`@)&YL(&-A="`G
  1416. XM"2<I(&9A:6P@<75O=&5D(&AE<F5D;V-](#P\("<@)PH)"B`*"CP\/%LY72!@
  1417. XM8"<G>V-A="`D8FEG9FEL97T@7`I["B`):68H(7X@8&`G)WMC870@/%LP/3E=
  1418. XM?6!@)R<@8V%T*69A:6P@;&%R9V4@:&5R97-T<FEN9W,*?2`\(%P*)&)I9V9I
  1419. XM;&4*"G)M("UF("1B:6=F:6QE"@II9B`H(7X@8'MC870\/&5O9@HD)`IE;V8*
  1420. XM?2`G)"<I"@EF86EL('%U;W1I;F<@)R0G(&EN(&AE<F5D;V,*"G-U8FUA=&-H
  1421. XM("=C870\/&5O9B<@)VAE<F5D;V,@:6YC;VUP;&5T92<@)VEN8V]M<&QE=&4@
  1422. XM:&5R961O8R<*<W5B;6%T8V@@)V-A=#P\96]F"B<@)VAE<F5D;V,@:6YC;VUP
  1423. XM;&5T92<@)VEN8V]M<&QE=&4@:&5R961O8R<*"G-U8FUA=&-H("=C870\/"AE
  1424. XM;V8@96]F*2<@)V5O9BUM87)K97(@;F]T(&$@<VEN9VQE(&QI=&5R86P@=V]R
  1425. XM9"<@)V)A9"!H97)E9&]C(&UA<FME<B<*"B,*(R!L97AI8V%L(&%N86QY<VES
  1426. XM"B,*"F5X<&5C="!W87)N:6YG"@`*"F5C:&\@:&5R95]I<U]A7W)E86QL>5]L
  1427. XM;VYG7W=O<F0N271?:&%S7V=O=%]T;U]B95]L;VYG97)?=&AA;E\Q,#`P7V-H
  1428. XM87)A8W1E<G-?9F]R7W1H95]L97AI8V%L7V%N86QY>F5R<U]B=69F97)?=&]?
  1429. XM;W9E<F9L;W=?8G5T7W1H871?<VAO=6QD7VYO=%]B95]T;V]?9&EF9FEC=6QT
  1430. XM7W1O7V1O+DQE=%]M95]S=&%R=%]W<FET:6YG7W-O;65?3&5W:7-?0V%R<F]L
  1431. XM;"Y4=V%S7V)R:6QL:6=?86YD7W1H95]S;&ET:'E?=&]V97,L1&ED7V=Y<F5?
  1432. XM86YD7V=I;6)L95]I;E]T:&5?=V%B92Y!;&Q?;6EM<WE?=V5R95]T:&5?8F]R
  1433. XM;V=O=F5S+$%N9%]T:&5?;6]M92UR871H<U]O=71G<F%B92Y"97=A<F5?=&AE
  1434. XM7TIA8F)E<G=O8VM?;7E?<V]N+%1H95]J87=S7W1H871?8FET92QT:&5?8VQA
  1435. XM=W-?=&AA=%]C871C:"Y"97=A<F5?=&AE7TIU8BUJ=6)?8FER9"QA;F1?<VAU
  1436. XM;E]4:&5?9G)U;6EO=7-?0F%N9&5R<VYA=&-H+DAE7W1O;VM?:&ES7W9O<G!A
  1437. XM;%]S=V]R9%]I;E]H86YD+$QO;F=?=&EM95]T:&5?;6%N>&]M95]F;V5?:&5?
  1438. XM<V]U9VAT+%-O7W)E<W1E9%]H95]B>5]T:&5?5'5M='5M7W1R964L06YD7W-T
  1439. XM;V]D7V%W:&EL95]I;E]T:&]U9VAT+D%N9%]A<U]I;E]U9F9I<VA?=&AO=6=H
  1440. XM=%]H95]S=&]O9"Q4:&5?2F%B8F5R=V]C:RQW:71H7V5Y97-?;V9?9FQA;64L
  1441. XM0V%M95]W:&EF9FQI;F=?=&AR;W5G:%]T:&5?='5L9V5Y7W=O;V0L06YD7V)U
  1442. XM<F)L961?87-?:71?8V%M92Y/;F5?='=O+&]N95]T=V\N06YD7W1H<F]U9VA?
  1443. XM86YD7W1H<F]U9VA?5&AE7W9O<G!A;%]B;&%D95]W96YT7W-N:6-K97(M<VYA
  1444. XM8VLN2&5?;&5F=%]I=%]D96%D7V%N9%]W:71H7VET<U]H96%D+$AE7W=E;G1?
  1445. XM9V%L=6UP:&EN9U]B86-K+D%N9%]H87-T7W1H;W5?<VQA:6Y?=&AE7TIA8F)E
  1446. XM<G=O8VL_0V]M95]T;U]M>5]A<FUS+&UY7V)E86UI<VA?8F]Y+$]H7V9R86)J
  1447. XM;W5S7V1A>2Y#86QL;V]H7V-A;&QA>2Y(95]C:&]R=&QE9%]I;E]H:7-?:F]Y
  1448. XM+E1W87-?8G)I;&QI9RQA;F1?=&AE7W-L:71H>5]T;W9E<RQ$:61?9WER95]A
  1449. XM;F1?9VEM8FQE7VEN7W1H95]W86)E+$%L;%]M:6US>5]W97)E7W1H95]B;W)O
  1450. XM9V]V97,L06YD7W1H95]M;VUE+7)A=&AS7V]U=&=R86)E+B`^("]T;7`O)'!I
  1451. XM9"YL=PH*96-H;R`G:&5R95]I<U]A7W)E86QL>5]L;VYG7W=O<F0N271?:&%S
  1452. XM7V=O=%]T;U]B95]L;VYG97)?=&AA;E\Q,#`P7V-H87)A8W1E<G-?9F]R7W1H
  1453. XM95]L97AI8V%L7V%N86QY>F5R<U]B=69F97)?=&]?;W9E<F9L;W=?8G5T7W1H
  1454. XM871?<VAO=6QD7VYO=%]B95]T;V]?9&EF9FEC=6QT7W1O7V1O+DQE=%]M95]S
  1455. XM=&%R=%]W<FET:6YG7W-O;65?3&5W:7-?0V%R<F]L;"Y4=V%S7V)R:6QL:6=?
  1456. XM86YD7W1H95]S;&ET:'E?=&]V97,L1&ED7V=Y<F5?86YD7V=I;6)L95]I;E]T
  1457. XM:&5?=V%B92Y!;&Q?;6EM<WE?=V5R95]T:&5?8F]R;V=O=F5S+$%N9%]T:&5?
  1458. XM;6]M92UR871H<U]O=71G<F%B92Y"97=A<F5?=&AE7TIA8F)E<G=O8VM?;7E?
  1459. XM<V]N+%1H95]J87=S7W1H871?8FET92QT:&5?8VQA=W-?=&AA=%]C871C:"Y"
  1460. XM97=A<F5?=&AE7TIU8BUJ=6)?8FER9"QA;F1?<VAU;E]4:&5?9G)U;6EO=7-?
  1461. XM0F%N9&5R<VYA=&-H+DAE7W1O;VM?:&ES7W9O<G!A;%]S=V]R9%]I;E]H86YD
  1462. XM+$QO;F=?=&EM95]T:&5?;6%N>&]M95]F;V5?:&5?<V]U9VAT+%-O7W)E<W1E
  1463. XM9%]H95]B>5]T:&5?5'5M='5M7W1R964L06YD7W-T;V]D7V%W:&EL95]I;E]T
  1464. XM:&]U9VAT+D%N9%]A<U]I;E]U9F9I<VA?=&AO=6=H=%]H95]S=&]O9"Q4:&5?
  1465. XM2F%B8F5R=V]C:RQW:71H7V5Y97-?;V9?9FQA;64L0V%M95]W:&EF9FQI;F=?
  1466. XM=&AR;W5G:%]T:&5?='5L9V5Y7W=O;V0L06YD7V)U<F)L961?87-?:71?8V%M
  1467. XM92Y/;F5?='=O+&]N95]T=V\N06YD7W1H<F]U9VA?86YD7W1H<F]U9VA?5&AE
  1468. XM7W9O<G!A;%]B;&%D95]W96YT7W-N:6-K97(M<VYA8VLN2&5?;&5F=%]I=%]D
  1469. XM96%D7V%N9%]W:71H7VET<U]H96%D+$AE7W=E;G1?9V%L=6UP:&EN9U]B86-K
  1470. XM+D%N9%]H87-T7W1H;W5?<VQA:6Y?=&AE7TIA8F)E<G=O8VL_0V]M95]T;U]M
  1471. XM>5]A<FUS+&UY7V)E86UI<VA?8F]Y+$]H7V9R86)J;W5S7V1A>2Y#86QL;V]H
  1472. XM7V-A;&QA>2Y(95]C:&]R=&QE9%]I;E]H:7-?:F]Y+E1W87-?8G)I;&QI9RQA
  1473. XM;F1?=&AE7W-L:71H>5]T;W9E<RQ$:61?9WER95]A;F1?9VEM8FQE7VEN7W1H
  1474. XM95]W86)E+$%L;%]M:6US>5]W97)E7W1H95]B;W)O9V]V97,L06YD7W1H95]M
  1475. XM;VUE+7)A=&AS7V]U=&=R86)E+B<@/B`O=&UP+R1P:60N;'$*"FEF("@A?B!@
  1476. XM8"@I>V-A="`O=&UP+R1P:60N;'=](&!@*"E[8V%T("]T;7`O)'!I9"YL<7TI
  1477. XM"@EF86EL(&5X<&5C=&5D(&QO;F<@<W1R:6YG(&%N9"!L;VYG('=O<F0@=&\@
  1478. XM8F4@:61E;G1I8V%L"FEF("@A('@]8'MW8R`M8R`O=&UP+R1P:60N;'=]('X@
  1479. XM)'@H,2D@,3`X."D*"69A:6P@97AP96-T960@;&]N9R!W;W)D('1O(&)E(#$P
  1480. XM.#@@8GET97,*:68@*"$@>#U@>W=C("UC("]T;7`O)'!I9"YL<7T@?B`D>"@Q
  1481. XM*2`Q,#@X*0H)9F%I;"!E>'!E8W1E9"!L;VYG('%U;W1E('1O(&)E(#$P.#@@
  1482. XM8GET97,*"G)M("]T;7`O)'!I9"YL=PIR;2`O=&UP+R1P:60N;'$*"G-U8FUA
  1483. XM=&-H("=E8VAO(&AI('Q;,B<@)V5X<&5C=&5D("<G/2<G(&]R("<G72<G(&%F
  1484. XM=&5R(&1I9VET)R`G<V-A;B!E<G)O<B<*<W5B;6%T8V@@)V5C:&\@:&D@?%LY
  1485. XM,CU=)R`G97AP96-T960@9&EG:70@869T97(@)R<])R<G("=S8V%N(&5R<F]R
  1486. XM)PIS=6)M871C:"`G96-H;R!H:2!\6V%=)R`G97AP96-T960@9&EG:70@869T
  1487. XM97(@)R=;)R<G("=S8V%N(&5R<F]R)PIS=6)M871C:"`G96-H;R!H:2!\6S(M
  1488. XM)R`G97AP96-T960@)R<])R<@;W(@)R==)R<@869T97(@9&EG:70G("=S8V%N
  1489. XM(&5R<F]R)PIS=6)M871C:"`G96-H;R!H:2!\6S(].3EA72<@)V5X<&5C=&5D
  1490. XM("<G72<G(&%F=&5R(&1I9VET)R`G<V-A;B!E<G)O<B<*<W5B;6%T8V@@)V5C
  1491. XM:&\@:&D@?%LR/6$Y.5TG("=E>'!E8W1E9"!D:6=I="!O<B`G)UTG)R!A9G1E
  1492. XM<B`G)STG)R<@)W-C86X@97)R;W(G"G-U8FUA=&-H("=E8VAO("<G:&DG("=E
  1493. XM;V8@:6X@<75O=&5D('-T<FEN9R<@)W-C86X@97)R;W(G"@II9G,])R<@>PH)
  1494. XM:68@*"%^("=H(&DG(&![96-H;R`M;B!H7`II?2D*"0EF86EL(&)A8VMS;&%S
  1495. XM:"UN97=L:6YE('1O('-P86-E(&-O;G9E<G-I;VX*"6EF("@A?B`D<F->7')C
  1496. XM(&![96-H;R`M;B`D<F-<<F-]*0H)"69A:6P@8F%C:W-L87-H(&%F=&5R('9A
  1497. XM<FEA8FQE(&YA;64@9&ED(&YO="!T97)M:6YA=&4@=F%R:6%B;&4@;F%M92!S
  1498. XM8V%N"@EI9B`H(7X@)')C7B<@<F,G(&![96-H;R`M;B`D<F-<"G)C?2D*"0EF
  1499. XM86EL(&)A8VMS;&%S:"UN97=L:6YE(&%F=&5R('9A<FEA8FQE(&YA;64@<W!A
  1500. XM8V4@8V]N=F5R<VEO;@H):68@*"%^("=H7&DG(&![96-H;R`M;B!H7&E]*0H)
  1501. XM"69A:6P@8F%C:W-L87-H(&EN('1H92!M:61D;&4@;V8@=V]R9`H):68@*"%^
  1502. XM("=H(%P@:2<@8'ME8VAO("UN(&@@7"!I?2D*"0EF86EL(&9R964M<W1A;F1I
  1503. XM;F<@8F%C:W-L87-H"GT*"FEF("@A("1R8R`M8R`G(R!E;V8@:6X@8V]M;65N
  1504. XM="<I"@EF86EL(&5O9B!I;B!C;VUM96YT(&5X:71E9"!W:71H(&YO;GIE<F\@
  1505. XM<W1A='5S"@HC('1E<W0@=&AE('-Y;G1A>"!E<G)O<B!P<FEN=&5R"@IP<F]M
  1506. XM<'0])R<@:68@*"%^(&!@("1N;"![)')C("UC:68^6S(],5U]("=L:6YE(#$Z
  1507. XM("<J)R!E<G)O<B!N96%R(&EF)RD*"69A:6P@<')I;G0@<WEN=&%X(&5R<F]R
  1508. XM"@IP<F]M<'0])R<@:68@*"%^(&!@("1N;"![)')C("UI8VEF/ELR/3%=?2`J
  1509. XM)R!E<G)O<B<I"@EF86EL('!R:6YT('-Y;G1A>"!E<G)O<@H*(PHC(&)U:6QT
  1510. XM:6YS"B,*"F9N(&9O;R!["@ER971U<FX@<VEG9G!E"GT*"F9O;PII9B`H(7X@
  1511. XM)'-T871U<R!S:6=F<&4I"@EF86EL(')E='5R;B!B=6EL=&EN(&1I9"!N;W0@
  1512. XM<F5T=7)N('-I9V9P90H*9FX@9F]O(",@=&5S="!D96QE=&EN9R!O9B!F=6YC
  1513. XM=&EO;@IF;B!B87(@>PH)9F]R("AI(&EN(#$@,B`S(#0@-2D*"0EI9B`H?B`D
  1514. XM:2`S*0H)"0ER971U<FX*?0H*8F%R"FEF("@A?B`D:2`S*0H)9F%I;"!R971U
  1515. XM<FX@:6YS:61E(&QO;W`@:6YS:61E(&9U;F-T:6]N(&9A:6QE9`H*<W5B;6%T
  1516. XM8V@@<F5T=7)N("=R971U<FX@;W5T<VED92!O9B!F=6YC=&EO;B<@)W)E='5R
  1517. XM;B!O=71S:61E(&]F(&9U;F-T:6]N)PIS=6)M871C:"`G8G)E86L@,2<@)W1O
  1518. XM;R!M86YY(&%R9W5M96YT<R!T;R!B<F5A:R<@)V)R96%K(&%R9R!C;W5N="<*
  1519. XM<W5B;6%T8V@@8G)E86L@)V)R96%K(&]U='-I9&4@;V8@;&]O<"<@)V)R96%K
  1520. XM(&]U='-I9&4@;V8@;&]O<"<*"F9O<B`H:2!I;B`Q(#(@,R`T(#4I"@EI9B`H
  1521. XM?B`D:2`R*0H)"6)R96%K"FEF("@A?B`D:2`R*0H)9F%I;"!B<F5A:R!O=70@
  1522. XM;V8@;&]O<`H*<W5B;6%T8V@@)W=A:70@9F]O)R`G9F]O(&ES(&$@8F%D(&YU
  1523. XM;6)E<B<@)V)O9W5S(&%R9W5M96YT('1O('=A:70G"@II9B`H?B!@>V5C:&\@
  1524. XM+6Y](#\I"@EF86EL(&5C:&\@+6X*:68@*'XA(&!@("<G('ME8VAO("TM?2`D
  1525. XM;FPI"@EF86EL(&5C:&\@+2T*"G!W9#U@+V)I;B]P=V0@8V1P871H/2\@>R`C
  1526. XM('-O;64@;&]C86P@87-S:6=N;65N=',*"6AO;64]+W1M<"!C9`H):68@*"%^
  1527. XM(&`O8FEN+W!W9"!@>W-H("UC("=C9"`O=&UP.R`O8FEN+W!W9"=]*0H)"69A
  1528. XM:6P@8V]U;&0@;F]T(&-D('1O("<D:&]M92<*"@EC9'!A=&@]+R!C9"!T;7`*
  1529. XM"6EF("@A?B!@+V)I;B]P=V0@8'MS:"`M8R`G8V0@+W1M<#L@+V)I;B]P=V0G
  1530. XM?2D*"0EF86EL(&-O=6QD(&YO="!C9"!T;R`O=&UP"@H)8V0@)'!W9`H):68@
  1531. XM*"%^(&`O8FEN+W!W9"!@>W-H("UC("=C9"`D<'=D.R`O8FEN+W!W9"=]*0H)
  1532. XM"69A:6P@8V]U;&0@;F]T(&-D('1O(&-U<G)E;G0@9&ER96-T;W)Y(0I]"@HJ
  1533. XM/2@Q(#(@,R`T(#4I('L*"65X<&5C="!B860@;G5M8F5R"@ES:&EF="!F;V\*
  1534. XM"65X<&5C="!A<F<@8V]U;G0*"7-H:69T(#$@,B`S"@EE>'!E8W0@<VAI9G0@
  1535. XM;W9E<F9L;W<*"7-H:69T(#$R,PH)<VAI9G0@,PH):68@*"%^("0C*B`R*0H)
  1536. XM"69A:6P@<VAI9G0@,R!O9B`G*#$@,B`S(#0@-2DG(&9A:6QE9`H)<VAI9G0*
  1537. XM"6EF("@A?B`D*B`U*0H)"69A:6P@<VAI9G0@9F%I;&5D('1O('-H:69T(&QE
  1538. XM9G0M=&\M<FEG:'0*?0H*+V)I;B]F86QS90IE=F%L("8F(&9A:6P@;G5L;"!E
  1539. XM=F%L(')E<V5T("<D<W1A='5S)PH*:68@*"%^(&![<FT]*"D[(&9N(')M.R!P
  1540. XM871H/2@N("]B:6XI.R!W:&%T:7,@<FU]("]B:6XO<FTI"@EF86EL(')M(&ES
  1541. XM;B<G)R=T(&EN(&)I;B$_"@IE>'!E8W0@;&ES="!O9B!S:6=N86P@:&%N9&QE
  1542. XM<G,*=VAA=&ES("US"@IE>'!E8W0@;&ES="!O9B!V87)I86)L97,@86YD(&9U
  1543. XM;F-T:6]N<PIW:&%T:7,*"G-U8FUA=&-H("=W:&%T:7,@+68G("=W:&%T:7,Z
  1544. XM(&)A9"!O<'1I;VXZ("UF)R`G8F%D(&]P=&EO;B!T;R!W:&%T:7,G"@IS=6)M
  1545. XM871C:"`G=VAA=&ES("]F<F]B;F%T>B<@)R]F<F]B;F%T>B!N;W0@9F]U;F0G
  1546. XM("=S96%R8V@@9F]R("]F<F]B;F%T>B<*"FEF("A^(&![=VAA=&ES(&QI;6ET
  1547. XM(#Y;,ETO9&5V+VYU;&Q](&)U:6QT:6XI('L*"6QI;6ET(&-O<F5D=6UP<VEZ
  1548. XM92`P"@EI9B`H(7X@8'ML:6UI="!C;W)E9'5M<'-I>F5](#`J*0H)"69A:6P@
  1549. XM9F%I;&5D('1O('-E="!C;W)E9'5M<'-I>F4@=&\@>F5R;PH):68@*"%^(&!@
  1550. XM("@I('ML:6UI="!C;W)E9'5M<'-I>F5](&!@("@I('ML:6UI='QG<F5P(&-O
  1551. XM<F5D=6UP<VEZ97TI"@D)9F%I;"!L:6UI="!L:6UI=`H)<W5B;6%T8V@@)VQI
  1552. XM;6ET(&9O;R<@)VYO('-U8V@@;&EM:70G("=B860@;&EM:70G"GT*"F9N(&-D
  1553. XM"@IS=6)M871C:"`G8V0@82!B(&,G("=T;V\@;6%N>2!A<F=U;65N=',@=&\@
  1554. XM8V0G("=C9"!A<F<@8V]U;G0G"B1R8R`M8R`G8V1P871H/2@I(&-D("]F<F]B
  1555. XM;F%T>B<@/ELR72]D978O;G5L;"`F)B!F86EL("=C9"!T;R`O9G)O8FYA='H@
  1556. XM<W5C8V5E9&5D(3\G"G-U8FUA=&-H("=C9'!A=&@])R<G)R!C9"!F<F]B;F%T
  1557. XM>B<@)V-O=6QD;B<G="!C9"!T;R!F<F]B;F%T>B<@)V-D('1O(&9R;V)N871Z
  1558. XM('-U8V-E961E9"$_)PH*)VEF)SUK97EW;W)D('L*"7MW:&%T:7,@:68@?"!F
  1559. XM9W)E<"`G)R=I9B<G/6ME>7=O<F0G(#XO9&5V+VYU;&Q]('Q\(&9A:6P@=VAA
  1560. XM=&ES(&]F(&ME>7=O<F0@:7,@;F]T('%U;W1E9`I]"@HC"B,@=V%I=`HC"@IS
  1561. XM=6)M871C:"`G=V%I="`Q(#(@,R<@)W1O;R!M86YY(&%R9W5M96YT<R!T;R!W
  1562. XM86ET)R`G87)G(&-O=6YT)PHD<F,@+6,@)W=A:70@,2<@/ELR72]D978O;G5L
  1563. XM;"`F)B!F86EL('=A:70@,0H*<VQE97`@-28*97AP96-T("1A<&ED"F5C:&\@
  1564. XM)&%P:61S"G=A:70*"FEF("A^(&!@("<G('MW86ET?2`_*0H)9F%I;"!W86ET
  1565. XM:6YG(&9O<B!N;W1H:6YG"@HC"B,@;6%T8VAI;F<*(PH*=&]U8V@@+W1M<"]A
  1566. XM8F,N)'!I9"`O=&UP+V)B8RXD<&ED"FUK9&ER("]T;7`O9&ER+B1P:60@+W1M
  1567. XM<"]D:7`N)'!I9`IT;W5C:"`O=&UP+V1I<BXD<&ED+UXH82!B(&,I("]T;7`O
  1568. XM9&EP+B1P:60O7BAA(&(@8RD*"FEF("@A?B`Q,C,@6WYX73];,"TY72D*"69A
  1569. XM:6P@;6%T8V@*:68@*"%^("@I("HI"@EF86EL(&UA=&-H(&]F(&YU;&P@;&ES
  1570. XM="!W:71H("<J)PII9B`H?B`H*2`J=BHI"@EF86EL(&UA=&-H(&]F(&YU;&P@
  1571. XM;&ES="!W:71H("<J=BHG('-U8V-E961E9`II9B`H(7X@*&9O;R!B87(@>F%R
  1572. XM*2`J*BHJ*GHJ*BHJ*BD*"69A:6P@;6%T8V@@;V8@;&ES="!B>2!O;F4@<&%T
  1573. XM=&5R;B!F86EL960*:68@*'X@*&9O;R!B87(@>F%R*2`J8RHI"@EF86EL(&)A
  1574. XM9"!M871C:`II9B`H(7X@6V%A82!;86%A*0H)9F%I;"!B860@<F%N9V5M871C
  1575. XM:`II9B`H(7X@)UTG(%M=72D*"69A:6P@;6%T8V@@<FEG:'0@8G)A8VME=`II
  1576. XM9B`H?B!X(%MY72D*"69A:6P@<F%N9V5M871C:"!O=70@;V8@<F%N9V4*:68@
  1577. XM*'X@>"!X/RD*"69A:6P@=&]O(&UA;GD@8VAA<F%C=&5R<R!I;B!P871T97)N
  1578. XM"@IT97-T("UF("\O+R\O=&UP+R\O+R\O83]C+B1P:60@?'P@9F%I;"!G;&]B
  1579. XM('=I=&@@;6%N>2!S;&%S:&5S"FEF("@A?B`O+R\O+W1M<"\O+R\O+V$J+B1P
  1580. XM:60@+R\O+R]T;7`O+R\O+R]A/V,N)'!I9"D*"69A:6P@9VQO8B!W:71H(&UA
  1581. XM;GD@<VQA<VAE<PII9B`H(7X@+R\O+W1M<"\O+R]D:3\N)'!I9"\O+R\J("\O
  1582. XM+R]T;7`O+R\O9&ER+B1P:60O+R\O*F(J*0H)9F%I;"!G;&]B('=I=&@@;6]R
  1583. XM92!S;&%S:&5S"FEF("@A($![8V0@+SL@?B`J+V$J+B1P:60@=&UP+V$J?2D*
  1584. XM"69A:6P@9VQO8B!I;B!C=7)R96YT(&1I<F5C=&]R>0II9B`H(7X@+W1M<"\_
  1585. XM8F,N)'!I9"`O=&UP+V)B8RXD<&ED*0H)9F%I;"!M871C:"!O9B!B8F,N)'!I
  1586. XM9"!A9V%I;G-T("<H)V%B8RXD<&ED(&)B8RXD<&ED)RDG"@IR;2`O=&UP+V%B
  1587. XM8RXD<&ED("]T;7`O8F)C+B1P:60*<FT@+7)F("]T;7`O9&ER+B1P:60@+W1M
  1588. XM<"]D:7`N)'!I9`H*(PHC('-I9VYA;',*(PH*9FX@<VEG:6YT('ME=F%L?0IK
  1589. XM:6QL("TR("1P:60*9FX@<VEG:6YT"@HC"B,@<&%T:"!S96%R8VAI;F<*(PH*
  1590. XM)')C("UC("]F<F]B;F%T>B`^6S)=+V1E=B]N=6QL("8F(&9A:6P@)W-E87)C
  1591. XM:"!E<G)O<B<*"G1O=6-H("]T;7`O;F]E>&5C+B1P:60*8VAM;V0@82UX("]T
  1592. XM;7`O;F]E>&5C+B1P:60*)')C("UC("]T;7`O;F]E>&5C+B1P:60@/ELR72]D
  1593. XM978O;G5L;"`F)B!F86EL("]T;7`O;F]E>&5C+B1P:60@:7,@9F]U;F0A/PIR
  1594. XM;2`O=&UP+VYO97AE8RXD<&ED"@IS=6)M871C:"`G<&%T:#TG)R<G(&9R;V)N
  1595. XM871Z)R`G9G)O8FYA='H@;F]T(&9O=6YD)R`G<V5A<F-H(&5R<F]R)PH*>W!A
  1596. XM=&@]*"D@+V)I;B]S:"`M8R`G97AI="`P)WT@?'P@9F%I;"!A8G,@<&%T:&YA
  1597. XM;64@=VET:"!P871H('-E="!T;R!N=6QL"@HC"B,@;W!T:6]N<PHC"@HC('1H
  1598. XM:7,@=&5S="!I<R!M96%N:6YG;&5S<SL@;F]T(')E86QL>2!A('1R:7`*97AP
  1599. XM96-T('!R;VUP="P@96-H;R!H:0IH;VUE/2]F<F]B;F%T>B`D<F,@+6YO;'!E
  1600. XM:79D>&,@)V5C:&\@:&DG"FEF("@A?B!@8"`D;FP@>R1R8R`M8SY;,CTQ77T@
  1601. XM*B<Z(&]P=&EO;B!R97%U:7)E<R!A;B!A<F=U;65N="`M+2!C)RD*"69A:6P@
  1602. XM9V5T;W!T(&]N("UC"FEF("@A?B!@8"`D;FP@>R1R8R`M<3Y;,CTQ77T@*B<Z
  1603. XM(&)A9"!O<'1I;VXZ("UQ)RD*"69A:6P@9V5T;W!T(&]N("UQ("AB;V=U<R!O
  1604. XM<'1I;VXI"FEF("@A?B!@>V5C:&\@)R-E8VAO)R!\("1R8R`M=B!\6S)=('-E
  1605. XM9"`G<R\C+R\G?2!E8VAO*0H)9F%I;"!R8R`M=@H*(PHC(&1O=`HC"@II9B`H
  1606. XM?B!@8"`G)R`N(#\J*0H)9F%I;"!N=6QL(&1O=`II9B`H?B!@8"`G)R![+B`M
  1607. XM:7T@/RHI"@EF86EL(&YU;&P@9&]T("UI"@IC870@/B`O=&UP+V1O="XD<&ED
  1608. XM(#P\(&5O9@IE8VAO(&AI"F5O9@H*<')O;7!T/2<[)R!I9B`H?B$@8&`@)R<@
  1609. XM>RX@+6D@+W1M<"]D;W0N)'!I9#Y;,CTQ77T@)SMH:2=>)&YL)SLG*0H)9F%I
  1610. XM;"!D;W0@+6D*<W5B;6%T8V@@+B<@)R]T;7`O9&]T+B1P:60@:&D@9&]T"@IR
  1611. XM;2`O=&UP+V1O="XD<&ED"@HD<F,@+6,@)RX@+V9R;V)N871Z)R`^6S)=+V1E
  1612. XM=B]N=6QL("8F(&9A:6P@)V1O="!O9B!A(&YO;F5X:7-T96YT(&9I;&4G"@HC
  1613. XM"B,@<W1D:6X*(PH*:68@*"%^(&![96-H;R!E8VAO(&AI('P@)')C?2!H:2D*
  1614. XM"69A:6P@<&EP:6YG('-T9&EN('1O(')C"@HC"B,@9G5N8W1I;VYS+"!V87)I
  1615. XM86)L97,@)B!E;G9I<F]N;65N=`HC"@IF;B`M+2T@>V9O<BAI*6%\6S(],UUB
  1616. XM/CYC/#P\)V4G)F8^6S(],5U]"@II9B`H=VAA=&ES('!R:6YT96YV(#XO9&5V
  1617. XM+VYU;&P^6S(],5TI('L*"7!R:6YT96YV/7!R:6YT96YV"GT@96QS92!I9B`H
  1618. XM=VAA=&ES(&5N=B`^+V1E=B]N=6QL/ELR/3%=*2!["@EP<FEN=&5N=CUE;G8*
  1619. XM?2!E;'-E"@EP<FEN=&5N=CTH*0H*:68@*'X@)"-P<FEN=&5N=B`Q("8F("%^
  1620. XM(&!@("1N;"![)'!R:6YT96YV('P@9W)E<"!F;E]?7S)D7U\R9%]?,F1]("=F
  1621. XM;E]?7S)D7U\R9%]?,F0]>V9O<BAI(&EN("0J*6%\6S(],UUB(#X^8R`\/#PG
  1622. XM)V4G)R9F(#Y;,CTQ77TG*0H)9F%I;"!P<F]T96-T7V5N=@H*9FX@+2TM('MR
  1623. XM97!L86-E?0I^(&![=VAA=&ES("TM("TM+7T@*G)E<&QA8V4J('Q\(&9A:6P@
  1624. XM<F5P;&%C92!A(&9U;F-T:6]N(&1E9FEN:71I;VX*9FX@+2TM"G=H871I<R`M
  1625. XM+2`M+2T@/ELR72]D978O;G5L;"`F)B!F86EL(&9U;F-T:6]N(&1E;&5T:6]N
  1626. XM"F9O;SUB87(@*CUB87(*9F]O/6YE<W0@*CUN97-T('L*"7X@)&9O;R!N97-T
  1627. XM('Q\(&9A:6P@;&]C86P@87-S:6=N;65N=`H)?B`D*B!N97-T('Q\(&9A:6P@
  1628. XM;&]C86P@87-S:6=N;65N="!T;R`G)"HG"@EF;V\]*"D*"2H]*"D*"7X@)&9O
  1629. XM;R`H*2!\?"!F86EL(&QO8V%L(&1E;&5T:6]N"@E^("0J("@I('Q\(&9A:6P@
  1630. XM;&]C86P@9&5L971I;VX@=&\@)R0J)PI]"GX@)&9O;R!B87(@?'P@9F%I;"!R
  1631. XM97-T;W)E(&]F(&=L;V)A;"!A9G1E<B!L;V-A;"!G<F]U<`I^("0J(&)A<B!\
  1632. XM?"!F86EL(')E<W1O<F4@;V8@)R0J)R!A9G1E<B!L;V-A;"!G<F]U<`I^(&![
  1633. XM97AE8SY;,CTQ73LD<F,@+7AC("=F;V\]*"DG?2`G9F]O/2@I)R!\?"!F86EL
  1634. XM("UX(&5C:&\@;V8@=F%R:6%B;&4@9&5L971I;VX*"F9N7V9F/2=[)R!P<F]M
  1635. XM<'0])R<@:68@*'XA(&!@("1N;"![)')C("UC9F8^6S(],5U]("=L:6YE(#$Z
  1636. XM("<J)R!E<G)O<B!N96%R(&5O9B<I"@EF86EL("=B;V=U<R!F=6YC=&EO;B!I
  1637. XM;B!E;G9I<F]N;65N="<*"B,*(R!S=&%T=7-E<PHC"@I^(&![)')C("UE8R`G
  1638. XM<VQE97`@,3`F:VEL;"`M.2`D87!I9#MW86ET)SY;,CTQ77T@:VEL;&5D('Q\
  1639. XM"@EF86EL('-T871U<R!D:6%G;F]S=&EC"@HD<F,@+6,@)V5X:70@,"!S:6=F
  1640. XM<&4G("8F(&9A:6P@97AI="!O9B!B860@<&EP96QI;F4@:7,@=')U90H*<W5B
  1641. XM;6%T8V@@)V5X:70@9F]O)R`G8F%D('-T871U<R<@)V5X:70@9&EA9VYO<W1I
  1642. XM8R<*"B,*(R!C;VYT<F]L('-T<G5C='5R97,*(PH*:68@*"%^(&![9F%L<V4@
  1643. XM?'P@96-H;R!H:7T@:&DI"@EF86EL("=\?"<*:68@*"%^(&![=')U92`F)B!E
  1644. XM8VAO(&AI?2!H:2D*"69A:6P@)R8F)PII9B`H?B!@>W1R=64@?'P@96-H;R!H
  1645. XM:7T@:&DI"@EF86EL("=\?"<*:68@*'X@8'MF86QS92`F)B!E8VAO(&AI?2!H
  1646. XM:2D*"69A:6P@)R8F)PH*=VAI;&4@*&9A;'-E*0H)9F%I;"!F86QS92!W:&EL
  1647. XM90IW:&EL92`H=')U92D@>PH)8G)E86L*"69A:6P@8G)E86L@:6X@=VAI;&4*
  1648. XM?0H*<W=I=&-H("AF;V\I('L*"6-A<V4@8F%R"@D)9F%I;"!M871C:&5D(&)A
  1649. XM<B!I;B!S=VET8V@*"6-A<V4@9F]O"@D)979A;`H)8V%S92`J"@D)9F%I;"!M
  1650. XM871C:"!F;V\@:6X@<W=I=&-H"GT*"G-W:71C:"`H;F]T:&EN9RD@>PH)8V%S
  1651. XM92!B87(*"0EF86EL(&UA=&-H960@8F%R(&EN('-W:71C:`H)8V%S92`J"@D)
  1652. XM:3UF<F]B;F%T>@I]"@I^("1I(&9R;V)N871Z('Q\(&9A:6P@;6%T8V@@)RHG
  1653. XM(&EN('-W:71C:`H*<W5B;6%T8V@@)R@I/2@I)R`G;G5L;"!V87)I86)L92!N
  1654. XM86UE)R`G87-S:6=N;65N="!D:6%G;F]S=&EC)PIS=6)M871C:"`G9FX@*"D@
  1655. XM>V5V86Q])R`G;G5L;"!F=6YC=&EO;B!N86UE)R`G87-S:6=N:6YG(&YU;&P@
  1656. XM9G5N8W1I;VX@;F%M92<*"B,*(R!P<F]M<'0*(PH*9FX@<')O;7!T('ME8VAO
  1657. XM(&AI?0IP<F]M<'0]*"D@:68@*'XA(&![)')C("UI("]D978O;G5L;#Y;,ETO
  1658. XM9&5V+VYU;&Q](&AI*2!F86EL(&9N('!R;VUP=`IF;B!P<F]M<'0*"B,*(R!H
  1659. XM:7-T;W)Y"B,*"FAI<W1O<GD]+W1M<"]H:7-T+B1P:60@<')O;7!T/2<G(&5C
  1660. XM:&\@)VAI<W1O<GD]*"DG('P@)')C("UI"@II9B`H(7X@8'MC870@+W1M<"]H
  1661. XM:7-T+B1P:61]("=H:7-T;W)Y/2@I)RD*"69A:6P@;W5T<'5T('1O(&AI<W1O
  1662. XM<GD@9FEL90H*:&ES=&]R>3TO=&UP+VAI<W0N)'!I9"!P<F]M<'0])R<@96-H
  1663. XM;R`G:&ES=&]R>3TH*2<@?"`D<F,@+6D*"FEF("@A?B!@8"`H*2![8V%T("]T
  1664. XM;7`O:&ES="XD<&ED?2`G:&ES=&]R>3TH*0IH:7-T;W)Y/2@I"B<I"@EF86EL
  1665. XM(&%P<&5N9"!T;R!H:7-T;W)Y(&9I;&4*"G)M("]T;7`O:&ES="XD<&ED"@II
  1666. XM9B`H(7X@8'MH:7-T;W)Y/2]F<F]B;F%T>B]F;V\@<')O;7!T/2<G(&5C:&\@
  1667. XM979A;"!\("1R8R`M:2`^6S(],5U](#\J*0H)9F%I;"!A8V-E<W-I;F<@8F%D
  1668. X.(&AI<W1O<GD@9FEL90H^
  1669. X`
  1670. Xend
  1671. END_OF_FILE
  1672.   if test 20258 -ne `wc -c <'trip.rc.uu'`; then
  1673.     echo shar: \"'trip.rc.uu'\" unpacked with wrong size!
  1674.   else
  1675.     echo shar: Uudecoding \"'trip.rc.uu'\" \(14684 characters\)
  1676.     cat trip.rc.uu | uudecode
  1677.     if test -f trip.rc ; then
  1678.         rm trip.rc.uu
  1679.     fi
  1680.   fi
  1681.   # end of 'trip.rc.uu'
  1682. fi
  1683. if test -f 'walk.c' -a "${1}" != "-c" ; then 
  1684.   echo shar: Will not clobber existing file \"'walk.c'\"
  1685. else
  1686.   echo shar: Extracting \"'walk.c'\" \(7929 characters\)
  1687.   sed "s/^X//" >'walk.c' <<'END_OF_FILE'
  1688. X/* walk.c: walks the parse tree. */
  1689. X
  1690. X#include <signal.h>
  1691. X#include <setjmp.h>
  1692. X#include "rc.h"
  1693. X#include "jbwrap.h"
  1694. X
  1695. X/*
  1696. X   global which indicates whether rc is executing a test;
  1697. X   used by rc -e so that if (false) does not exit.
  1698. X*/
  1699. Xbool cond = FALSE;
  1700. X
  1701. Xstatic bool isallpre(Node *);
  1702. Xstatic bool dofork(bool);
  1703. Xstatic void dopipe(Node *);
  1704. X
  1705. X/* Tail-recursive version of walk() */
  1706. X
  1707. X#define WALK(x, y) { n = x; parent = y; goto top; }
  1708. X
  1709. X/* walk the parse-tree. "obvious". */
  1710. X
  1711. Xextern bool walk(Node *n, bool parent) {
  1712. Xtop:    SIGCHK;
  1713. X    if (n == NULL) {
  1714. X        if (!parent)
  1715. X            exit(0);
  1716. X        set(TRUE);
  1717. X        return TRUE;
  1718. X    }
  1719. X    switch (n->type) {
  1720. X    case nArgs: case nBackq: case nConcat: case nCount:
  1721. X    case nFlat: case nLappend: case nRedir: case nVar:
  1722. X    case nVarsub: case nWord: case nQword:
  1723. X        exec(glob(glom(n)), parent);    /* simple command */
  1724. X        break;
  1725. X    case nBody:
  1726. X        walk(n->u[0].p, TRUE);
  1727. X        WALK(n->u[1].p, parent);
  1728. X        /* WALK doesn't fall through */
  1729. X    case nNowait: {
  1730. X        int pid;
  1731. X        if ((pid = rc_fork()) == 0) {
  1732. X#if !defined(NOJOB) && defined(SIGTTOU) && defined(SIGTTIN) && defined(SIGTSTP)
  1733. X            setsigdefaults(FALSE);
  1734. X            rc_signal(SIGTTOU, SIG_IGN);    /* Berkeleyized version: put it in a new pgroup. */
  1735. X            rc_signal(SIGTTIN, SIG_IGN);
  1736. X            rc_signal(SIGTSTP, SIG_IGN);
  1737. X            setpgrp(0, getpid());
  1738. X#else
  1739. X            setsigdefaults(TRUE);        /* ignore SIGINT, SIGQUIT, SIGTERM */
  1740. X#endif
  1741. X            mvfd(rc_open("/dev/null", rFrom), 0);
  1742. X            walk(n->u[0].p, FALSE);
  1743. X            exit(getstatus());
  1744. X        }
  1745. X        if (interactive)
  1746. X            fprint(2, "%d\n", pid);
  1747. X        varassign("apid", word(nprint("%d", pid), NULL), FALSE);
  1748. X        redirq = NULL; /* kill pre-redir queue */
  1749. X        break;
  1750. X    }
  1751. X    case nAndalso: {
  1752. X        bool oldcond = cond;
  1753. X        cond = TRUE;
  1754. X        if (walk(n->u[0].p, TRUE)) {
  1755. X            cond = oldcond;
  1756. X            WALK(n->u[1].p, parent);
  1757. X        } else
  1758. X            cond = oldcond;
  1759. X        break;
  1760. X    }
  1761. X    case nOrelse: {
  1762. X        bool oldcond = cond;
  1763. X        cond = TRUE;
  1764. X        if (!walk(n->u[0].p, TRUE)) {
  1765. X            cond = oldcond;
  1766. X            WALK(n->u[1].p, parent);
  1767. X        } else
  1768. X            cond = oldcond;
  1769. X        break;
  1770. X    }
  1771. X    case nBang:
  1772. X        set(!walk(n->u[0].p, TRUE));
  1773. X        break;
  1774. X    case nIf: {
  1775. X        bool oldcond = cond;
  1776. X        Node *true_cmd = n->u[1].p, *false_cmd = NULL;
  1777. X        if (true_cmd != NULL && true_cmd->type == nElse) {
  1778. X            false_cmd = true_cmd->u[1].p;
  1779. X            true_cmd = true_cmd->u[0].p;
  1780. X        }
  1781. X        cond = TRUE;
  1782. X        if (!walk(n->u[0].p, TRUE))
  1783. X            true_cmd = false_cmd; /* run the else clause */
  1784. X        cond = oldcond;
  1785. X        WALK(true_cmd, parent);
  1786. X    }
  1787. X    case nWhile: {
  1788. X        Jbwrap j;
  1789. X        Edata jbreak;
  1790. X        Estack e1, e2;
  1791. X        bool testtrue, oldcond = cond;
  1792. X        cond = TRUE;
  1793. X        if (!walk(n->u[0].p, TRUE)) { /* prevent spurious breaks inside test */
  1794. X            cond = oldcond;
  1795. X            break;
  1796. X        }
  1797. X        if (setjmp(j.j))
  1798. X            break;
  1799. X        jbreak.jb = &j;
  1800. X        except(eBreak, jbreak, &e1);
  1801. X        do {
  1802. X            Edata block;
  1803. X            block.b = newblock();
  1804. X            cond = oldcond;
  1805. X            except(eArena, block, &e2);
  1806. X            walk(n->u[1].p, TRUE);
  1807. X            testtrue = walk(n->u[0].p, TRUE);
  1808. X            unexcept(); /* eArena */
  1809. X            cond = TRUE;
  1810. X        } while (testtrue);
  1811. X        cond = oldcond;
  1812. X        unexcept(); /* eBreak */
  1813. X        break;
  1814. X    }
  1815. X    case nForin: {
  1816. X        List *l, *var = glom(n->u[0].p);
  1817. X        Jbwrap j;
  1818. X        Estack e1, e2;
  1819. X        Edata jbreak;
  1820. X        if (setjmp(j.j))
  1821. X            break;
  1822. X        jbreak.jb = &j;
  1823. X        except(eBreak, jbreak, &e1);
  1824. X        for (l = listcpy(glob(glom(n->u[1].p)), nalloc); l != NULL; l = l->n) {
  1825. X            Edata block;
  1826. X            assign(var, word(l->w, NULL), FALSE);
  1827. X            block.b = newblock();
  1828. X            except(eArena, block, &e2);
  1829. X            walk(n->u[2].p, TRUE);
  1830. X            unexcept(); /* eArena */
  1831. X        }
  1832. X        unexcept(); /* eBreak */
  1833. X        break;
  1834. X    }
  1835. X    case nSubshell:
  1836. X        if (dofork(TRUE)) {
  1837. X            setsigdefaults(FALSE);
  1838. X            walk(n->u[0].p, FALSE);
  1839. X            rc_exit(getstatus());
  1840. X        }
  1841. X        break;
  1842. X    case nAssign:
  1843. X        if (n->u[0].p == NULL)
  1844. X            rc_error("null variable name");
  1845. X        assign(glom(n->u[0].p), glob(glom(n->u[1].p)), FALSE);
  1846. X        set(TRUE);
  1847. X        break;
  1848. X    case nPipe:
  1849. X        dopipe(n);
  1850. X        break;
  1851. X    case nNewfn: {
  1852. X        List *l = glom(n->u[0].p);
  1853. X        if (l == NULL)
  1854. X            rc_error("null function name");
  1855. X        while (l != NULL) {
  1856. X            if (dashex)
  1857. X                prettyprint_fn(2, l->w, n->u[1].p);
  1858. X            fnassign(l->w, n->u[1].p);
  1859. X            l = l->n;
  1860. X        }
  1861. X        set(TRUE);
  1862. X        break;
  1863. X    }
  1864. X    case nRmfn: {
  1865. X        List *l = glom(n->u[0].p);
  1866. X        while (l != NULL) {
  1867. X            if (dashex)
  1868. X                fprint(2, "fn %S\n", l->w);
  1869. X            fnrm(l->w);
  1870. X            l = l->n;
  1871. X        }
  1872. X        set(TRUE);
  1873. X        break;
  1874. X    }
  1875. X    case nDup:
  1876. X        redirq = NULL;
  1877. X        break; /* Null command */
  1878. X    case nMatch: {
  1879. X        List *a = glob(glom(n->u[0].p)), *b = glom(n->u[1].p);
  1880. X        if (dashex)
  1881. X            fprint(2, (a != NULL && a->n != NULL) ? "~ (%L) %L\n" : "~ %L %L\n", a, " ", b, " ");
  1882. X        set(lmatch(a, b));
  1883. X        break;
  1884. X    }
  1885. X    case nSwitch: {
  1886. X        List *v = glom(n->u[0].p);
  1887. X        while (1) {
  1888. X            do {
  1889. X                n = n->u[1].p;
  1890. X                if (n == NULL)
  1891. X                    return istrue();
  1892. X            } while (n->u[0].p == NULL || n->u[0].p->type != nCase);
  1893. X            if (lmatch(v, glom(n->u[0].p->u[0].p))) {
  1894. X                for (n = n->u[1].p; n != NULL && (n->u[0].p == NULL || n->u[0].p->type != nCase); n = n->u[1].p)
  1895. X                    walk(n->u[0].p, TRUE);
  1896. X                break;
  1897. X            }
  1898. X        }
  1899. X        break;
  1900. X    }
  1901. X    case nPre: {
  1902. X        List *v;
  1903. X        if (n->u[0].p->type == nRedir || n->u[0].p->type == nDup) {
  1904. X            qredir(n->u[0].p);
  1905. X            walk(n->u[1].p, parent);
  1906. X        } else if (n->u[0].p->type == nAssign) {
  1907. X            if (isallpre(n->u[1].p)) {
  1908. X                walk(n->u[0].p, TRUE);
  1909. X                WALK(n->u[1].p, parent);
  1910. X            } else {
  1911. X                Estack e;
  1912. X                Edata var;
  1913. X                v = glom(n->u[0].p->u[0].p);
  1914. X                assign(v, glob(glom(n->u[0].p->u[1].p)), TRUE);
  1915. X                var.name = v->w;
  1916. X                except(eVarstack, var, &e);
  1917. X                walk(n->u[1].p, parent);
  1918. X                varrm(v->w, TRUE);
  1919. X                unexcept(); /* eVarstack */
  1920. X            }
  1921. X        } else
  1922. X            panic("unexpected node in preredir section of walk");
  1923. X        break;
  1924. X    }
  1925. X    case nBrace:
  1926. X        if (n->u[1].p == NULL) {
  1927. X            WALK(n->u[0].p, parent);
  1928. X        } else if (dofork(parent)) {
  1929. X            setsigdefaults(FALSE);
  1930. X            walk(n->u[1].p, TRUE); /* Do redirections */
  1931. X            redirq = NULL;   /* Reset redirection queue */
  1932. X            walk(n->u[0].p, FALSE); /* Do commands */
  1933. X            rc_exit(getstatus());
  1934. X            /* NOTREACHED */
  1935. X        }
  1936. X        break;
  1937. X    case nEpilog:
  1938. X        qredir(n->u[0].p);
  1939. X        if (n->u[1].p != NULL) {
  1940. X            WALK(n->u[1].p, parent); /* Do more redirections. */
  1941. X        } else {
  1942. X            doredirs();    /* Okay, we hit the bottom. */
  1943. X        }
  1944. X        break;
  1945. X    case nNmpipe:
  1946. X        rc_error("named pipes cannot be executed as commands");
  1947. X        /* NOTREACHED */
  1948. X    default:
  1949. X        panic("unknown node in walk");
  1950. X        /* NOTREACHED */
  1951. X    }
  1952. X    return istrue();
  1953. X}
  1954. X
  1955. X/* checks to see whether a subtree is all pre-command directives, i.e., assignments and redirs only */
  1956. X
  1957. Xstatic bool isallpre(Node *n) {
  1958. X    while (n != NULL && n->type == nPre)
  1959. X        n = n->u[1].p;
  1960. X    return n == NULL || n->type == nRedir || n->type == nAssign || n->type == nDup;
  1961. X}
  1962. X
  1963. X/*
  1964. X   A code-saver. Forks, child returns (for further processing in walk()), and the parent
  1965. X   waits for the child to finish, setting $status appropriately.
  1966. X*/
  1967. X
  1968. Xstatic bool dofork(bool parent) {
  1969. X    int pid, sp;
  1970. X
  1971. X    if (!parent || (pid = rc_fork()) == 0)
  1972. X        return TRUE;
  1973. X    redirq = NULL; /* clear out the pre-redirection queue in the parent */
  1974. X    rc_wait4(pid, &sp, TRUE);
  1975. X    setstatus(-1, sp);
  1976. X    SIGCHK;
  1977. X    return FALSE;
  1978. X}
  1979. X
  1980. Xstatic void dopipe(Node *n) {
  1981. X    int i, j, sp, pid, fd_prev, fd_out, pids[512], stats[512], p[2];
  1982. X    bool intr;
  1983. X    Node *r;
  1984. X
  1985. X    fd_prev = fd_out = 1;
  1986. X    for (r = n, i = 0; r != NULL && r->type == nPipe; r = r->u[2].p, i++) {
  1987. X        if (i > 500) /* the only hard-wired limit in rc? */
  1988. X            rc_error("pipe too long");
  1989. X        if (pipe(p) < 0) {
  1990. X            uerror("pipe");
  1991. X            rc_error(NULL);
  1992. X        }
  1993. X        if ((pid = rc_fork()) == 0) {
  1994. X            setsigdefaults(FALSE);
  1995. X            redirq = NULL; /* clear preredir queue */
  1996. X            mvfd(p[0], r->u[1].i);
  1997. X            if (fd_prev != 1)
  1998. X                mvfd(fd_prev, fd_out);
  1999. X            close(p[1]);
  2000. X            walk(r->u[3].p, FALSE);
  2001. X            exit(getstatus());
  2002. X        }
  2003. X        if (fd_prev != 1)
  2004. X            close(fd_prev); /* parent must close all pipe fd's */
  2005. X        pids[i] = pid;
  2006. X        fd_prev = p[1];
  2007. X        fd_out = r->u[0].i;
  2008. X        close(p[0]);
  2009. X    }
  2010. X    if ((pid = rc_fork()) == 0) {
  2011. X        setsigdefaults(FALSE);
  2012. X        mvfd(fd_prev, fd_out);
  2013. X        walk(r, FALSE);
  2014. X        exit(getstatus());
  2015. X        /* NOTREACHED */
  2016. X    }
  2017. X    redirq = NULL; /* clear preredir queue */
  2018. X    close(fd_prev);
  2019. X    pids[i++] = pid;
  2020. X
  2021. X    /* collect statuses */
  2022. X
  2023. X    intr = FALSE;
  2024. X    for (j = 0; j < i; j++) {
  2025. X        rc_wait4(pids[j], &sp, TRUE);
  2026. X        stats[j] = sp;
  2027. X        intr |= (sp == SIGINT);
  2028. X    }
  2029. X    setpipestatus(stats, i);
  2030. X    SIGCHK;
  2031. X}
  2032. END_OF_FILE
  2033.   if test 7929 -ne `wc -c <'walk.c'`; then
  2034.     echo shar: \"'walk.c'\" unpacked with wrong size!
  2035.   fi
  2036.   # end of 'walk.c'
  2037. fi
  2038. echo shar: End of archive 4 \(of 7\).
  2039. cp /dev/null ark4isdone
  2040. MISSING=""
  2041. for I in 1 2 3 4 5 6 7 ; do
  2042.     if test ! -f ark${I}isdone ; then
  2043.     MISSING="${MISSING} ${I}"
  2044.     fi
  2045. done
  2046. if test "${MISSING}" = "" ; then
  2047.     echo You have unpacked all 7 archives.
  2048.     rm -f ark[1-9]isdone
  2049. else
  2050.     echo You still must unpack the following archives:
  2051.     echo "        " ${MISSING}
  2052. fi
  2053. exit 0
  2054. exit 0 # Just in case...
  2055.