home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume24 / zsh2.1 / part09 < prev    next >
Text File  |  1991-10-24  |  49KB  |  2,479 lines

  1. Newsgroups: comp.sources.misc
  2. From: pfalstad@phoenix.Princeton.EDU (Paul Falstad)
  3. Subject:  v24i009:  zsh2.1 - The Z shell, Part09/19
  4. Message-ID: <1991Oct24.190947.25915@sparky.imd.sterling.com>
  5. X-Md4-Signature: 06654ce88b5661b0e7f5ad07c8b24377
  6. Date: Thu, 24 Oct 1991 19:09:47 GMT
  7. Approved: kent@sparky.imd.sterling.com
  8.  
  9. Submitted-by: pfalstad@phoenix.Princeton.EDU (Paul Falstad)
  10. Posting-number: Volume 24, Issue 9
  11. Archive-name: zsh2.1/part09
  12. Environment: BSD
  13. Supersedes: zsh2.00: Volume 18, Issue 84-98
  14.  
  15. #!/bin/sh
  16. # this is zshar.09 (part 9 of zsh2.1.0)
  17. # do not concatenate these parts, unpack them in order with /bin/sh
  18. # file zsh2.1/src/math.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" != 9; 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/math.c'
  34. else
  35. echo 'x - continuing file zsh2.1/src/math.c'
  36. sed 's/^X//' << 'SHAR_EOF' >> 'zsh2.1/src/math.c' &&
  37. X        case PREMINUS: stack[sp].val = setvar(stack[sp].lval,
  38. X            stack[sp].val-1); break;
  39. X        default: zerr("out of integers",NULL,0); exit(1);
  40. X    }
  41. X}
  42. X
  43. Xvoid bop(tk) /**/
  44. Xint tk;
  45. X{
  46. X    switch (tk) {
  47. X        case DAND: case DANDEQ: if (!stack[sp].val) noeval++; break;
  48. X        case DOR: case DOREQ: if (stack[sp].val) noeval++; break;
  49. X        };
  50. X}
  51. X
  52. Xlong mathevall(s,prek,ep) /**/
  53. Xchar *s;int prek;char **ep;
  54. X{
  55. Xint t0;
  56. X
  57. X    lastbase = -1;
  58. X    for (t0 = 0; t0 != LVCOUNT; t0++)
  59. X        lvals[t0] = NULL;
  60. X    lvc = 0;
  61. X    ptr = s;
  62. X    sp = -1;
  63. X    unary = 1;
  64. X    mathparse(prek);
  65. X    *ep = ptr;
  66. X    if (sp)
  67. X        zerr("bad math expression: unbalanced stack",NULL,0);
  68. X    for (t0 = 0; t0 != lvc; t0++)
  69. X        free(lvals[t0]);
  70. X    return stack[0].val;
  71. X}
  72. X
  73. Xlong matheval(s) /**/
  74. Xchar *s;
  75. X{
  76. Xchar *junk;
  77. Xlong x;
  78. X
  79. X    if (!*s)
  80. X        return 0;
  81. X    x = mathevall(s,TOPPREC,&junk);
  82. X    if (*junk)
  83. X        zerr("bad math expression: illegal character: %c",NULL,*junk);
  84. X    return x;
  85. X}
  86. X
  87. Xlong mathevalarg(s,ss) /**/
  88. Xchar *s;char **ss;
  89. X{
  90. Xlong x;
  91. X
  92. X    x = mathevall(s,ARGPREC,ss);
  93. X    if (mtok == COMMA)
  94. X        (*ss)--;
  95. X    return x;
  96. X}
  97. X
  98. X/* operator-precedence parse the string and execute */
  99. X
  100. Xvoid mathparse(pc) /**/
  101. Xint pc;
  102. X{
  103. X    if (errflag)
  104. X        return;
  105. X    mtok = zzlex();
  106. X    while (prec[mtok] <= pc)
  107. X        {
  108. X        if (errflag)
  109. X            return;
  110. X        if (mtok == NUM)
  111. X            push(yyval,-1);
  112. X        else if (mtok == ID)
  113. X            push(getvar(yylval),yylval);
  114. X        else if (mtok == M_INPAR)
  115. X            {
  116. X            mathparse(TOPPREC);
  117. X            if (mtok != M_OUTPAR)
  118. X                exit(1);
  119. X            }
  120. X        else if (mtok == QUEST)
  121. X            {
  122. X            int q = stack[sp].val;
  123. X            if (!q) noeval++;
  124. X            mathparse(prec[QUEST]-1);
  125. X            if (!q) noeval--; else noeval++;
  126. X            mathparse(prec[QUEST]);
  127. X            if (q) noeval--;
  128. X            op(QUEST);
  129. X            continue;
  130. X            }
  131. X        else
  132. X            {
  133. X            int otok = mtok,onoeval = noeval;
  134. X
  135. X            if (type[otok] == BOOL)
  136. X                bop(otok);
  137. X            mathparse(prec[otok]-(type[otok] != RL));
  138. X            noeval = onoeval;
  139. X            op(otok);
  140. X            continue;
  141. X            }
  142. X        mtok = zzlex();
  143. X        }
  144. X}
  145. X
  146. SHAR_EOF
  147. echo 'File zsh2.1/src/math.c is complete' &&
  148. chmod 0644 zsh2.1/src/math.c ||
  149. echo 'restore of zsh2.1/src/math.c failed'
  150. Wc_c="`wc -c < 'zsh2.1/src/math.c'`"
  151. test 10626 -eq "$Wc_c" ||
  152.     echo 'zsh2.1/src/math.c: original size 10626, current size' "$Wc_c"
  153. rm -f _shar_wnt_.tmp
  154. fi
  155. # ============= zsh2.1/src/mem.c ==============
  156. if test -f 'zsh2.1/src/mem.c' -a X"$1" != X"-c"; then
  157.     echo 'x - skipping zsh2.1/src/mem.c (File already exists)'
  158.     rm -f _shar_wnt_.tmp
  159. else
  160. > _shar_wnt_.tmp
  161. echo 'x - extracting zsh2.1/src/mem.c (Text)'
  162. sed 's/^X//' << 'SHAR_EOF' > 'zsh2.1/src/mem.c' &&
  163. X/*
  164. X
  165. X    mem.c - memory management
  166. X
  167. X    This file is part of zsh, the Z shell.
  168. X
  169. X    zsh is free software; no one can prevent you from reading the source
  170. X   code, or giving it to someone else.
  171. X
  172. X   This file is copyrighted under the GNU General Public License, which
  173. X   can be found in the file called COPYING.
  174. X
  175. X   Copyright (C) 1990, 1991 Paul Falstad
  176. X
  177. X   zsh is distributed in the hope that it will be useful, but
  178. X   WITHOUT ANY WARRANTY.  No author or distributor accepts
  179. X   responsibility to anyone for the consequences of using it or for
  180. X   whether it serves any particular purpose or works at all, unless he
  181. X   says so in writing.  Refer to the GNU General Public License
  182. X   for full details.
  183. X
  184. X   Everyone is granted permission to copy, modify and redistribute
  185. X   zsh, but only under the conditions described in the GNU General Public
  186. X   License.   A copy of this license is supposed to have been given to you
  187. X   along with zsh so you can know your rights and responsibilities.
  188. X   It should be in a file named COPYING.
  189. X
  190. X   Among other things, the copyright notice and this notice must be
  191. X   preserved on all copies.
  192. X
  193. X*/
  194. X
  195. X#include "zsh.h"
  196. X#define HEAPSIZE 8192
  197. X
  198. X/*
  199. X
  200. X    There are two ways to allocate memory in zsh.  The first way is
  201. X    to call zalloc/zcalloc, which call malloc/calloc directly.  It
  202. X    is legal to call realloc() or free() on memory allocated this way.
  203. X    The second way is to call halloc/hcalloc, which allocates memory
  204. X    from one of the memory pools on the heap stack.  A pool can be
  205. X    created by calling pushheap(), and destroyed by calling popheap().
  206. X    To free the memory in the pool without destroying it, call
  207. X    freeheap(); this is equivalent to { popheap(); pushheap(); }
  208. X    Memory allocated in this way does not have to be freed explicitly;
  209. X    it will all be freed when the pool is destroyed.  In fact,
  210. X    attempting to free this memory may result in a core dump.
  211. X    The pair of pointers ncalloc and alloc may point to either
  212. X    zalloc & zcalloc or halloc & hcalloc; permalloc() sets them to the
  213. X    former, and heapalloc() sets them to the latter. This can be useful.
  214. X    For example, the dupstruct() routine duplicates a syntax tree,
  215. X    allocating the new memory for the tree using alloc().  If you want
  216. X    to duplicate a structure for a one-time use (i.e. to execute the list
  217. X    in a for loop), call heapalloc(), then dupstruct().  If you want
  218. X    to duplicate a structure in order to preserve it (i.e. a function
  219. X    definition), call permalloc(), then dupstruct().
  220. X
  221. X*/
  222. X
  223. X/* initialize heap stack */
  224. X
  225. Xvoid meminit() /**/
  226. X{
  227. X    permalloc();
  228. X    heaplist = newlist();
  229. X    pushheap();
  230. X}
  231. X
  232. X/* set default allocation to heap stack */
  233. X
  234. Xvoid heapalloc() /**/
  235. X{
  236. X    alloc = hcalloc;
  237. X    ncalloc = halloc;
  238. X    useheap = 1;
  239. X}
  240. X
  241. Xstatic vptr (*lastcalloc) DCLPROTO((int));
  242. Xstatic vptr (*lastncalloc) DCLPROTO((int));
  243. X
  244. X/* set default allocation to malloc() */
  245. X
  246. Xvoid permalloc() /**/
  247. X{
  248. X    lastcalloc = alloc;
  249. X    lastncalloc = ncalloc;
  250. X    alloc = zcalloc;
  251. X    ncalloc = zalloc;
  252. X    useheap = 0;
  253. X}
  254. X
  255. X/* reset previous default allocation */
  256. X
  257. Xvoid lastalloc() /**/
  258. X{
  259. X    alloc = lastcalloc;
  260. X    ncalloc = lastncalloc;
  261. X}
  262. X
  263. Xstruct heap {
  264. X    char *pool,*ptr;
  265. X    int free;
  266. X    struct heap *next;
  267. X    };
  268. X
  269. X/* create a memory pool */
  270. X
  271. Xvoid pushheap() /**/
  272. X{
  273. XHeap h;
  274. X
  275. X    h = (Heap) zalloc(sizeof *h);
  276. X    h->pool = h->ptr = zalloc(HEAPSIZE);
  277. X    h->free = HEAPSIZE;
  278. X    h->next = NULL;
  279. X    permalloc();
  280. X    pushnode(heaplist,h);
  281. X    lastalloc();
  282. X}
  283. X
  284. X/* reset a memory pool */
  285. X
  286. Xvoid freeheap() /**/
  287. X{
  288. XHeap h = (Heap) peekfirst(heaplist);
  289. X
  290. X    freeh(h->next);
  291. X    h->free += (h->ptr-h->pool);
  292. X    h->ptr = h->pool;
  293. X}
  294. X
  295. X/* destroy a memory pool */
  296. X
  297. Xvoid popheap() /**/
  298. X{
  299. XHeap h = (Heap) getnode(heaplist);
  300. X
  301. X    freeh(h);
  302. X}
  303. X
  304. Xvoid freeh(h) /**/
  305. XHeap h;
  306. X{
  307. X    if (h)
  308. X        {
  309. X        freeh(h->next);
  310. X        free(h->pool);
  311. X        free(h);
  312. X        }
  313. X}
  314. X
  315. X/* allocate memory from the current memory pool */
  316. X
  317. Xvptr halloc(size) /**/
  318. Xint size;
  319. X{
  320. XHeap h = (Heap) peekfirst(heaplist),h2;
  321. Xchar *ret;
  322. X
  323. X    size = (size|7)+1;
  324. X    while (h && h->free-size < 0)
  325. X        h = h->next;
  326. X    if (!h)
  327. X        {
  328. X        h2 = (Heap) zalloc(sizeof *h2);
  329. X        h2->pool = h2->ptr = zalloc(h2->free = 
  330. X            (size < HEAPSIZE) ? HEAPSIZE : (size|(HEAPSIZE-1))+1);
  331. X        h2->next = h;
  332. X        setdata(firstnode(heaplist),(Heap) h2);
  333. X        h = h2;
  334. X        }
  335. X    h->free -= size;
  336. X    ret = h->ptr;
  337. X    h->ptr += size;
  338. X    return ret;
  339. X}
  340. X
  341. X/* allocate memory from the current memory pool and clear it */
  342. X
  343. Xvptr hcalloc(size) /**/
  344. Xint size;
  345. X{
  346. Xvptr ptr;
  347. X
  348. X    ptr = halloc(size);
  349. X    memset(ptr,0,size);
  350. X    return ptr;
  351. X}
  352. X
  353. Xvptr hrealloc(p,old,new) /**/
  354. Xchar *p;int old;int new;
  355. X{
  356. Xchar *ptr;
  357. X
  358. X    ptr = halloc(new);
  359. X    memcpy(ptr,p,old);
  360. X    return ptr;
  361. X}
  362. X
  363. X/* allocate permanent memory */
  364. X
  365. Xvptr zalloc(l) /**/
  366. Xint l;
  367. X{
  368. Xvptr z;
  369. X    if (!l)
  370. X        l = 1;
  371. X    if (!(z = malloc(l)))
  372. X        {
  373. X        zerr("fatal error: out of memory",NULL,0);
  374. X        exit(1);
  375. X        }
  376. X    return z;
  377. X}
  378. X
  379. Xvptr zcalloc(size) /**/
  380. Xint size;
  381. X{
  382. Xvptr ptr;
  383. X
  384. X    ptr = zalloc(size);
  385. X    memset(ptr,0,size);
  386. X    return ptr;
  387. X}
  388. X
  389. Xchar *strdup(s) /**/
  390. Xchar *s;
  391. X{
  392. Xchar *t;
  393. X
  394. X    if (!s)
  395. X        return NULL;
  396. X    t = ncalloc(strlen(s)+1);
  397. X    strcpy(t,s);
  398. X    return t;
  399. X}
  400. X
  401. Xchar *ztrdup(s) /**/
  402. Xchar *s;
  403. X{
  404. Xchar *t;
  405. X
  406. X    if (!s)
  407. X        return NULL;
  408. X    t = zalloc(strlen(s)+1);
  409. X    strcpy(t,s);
  410. X    return t;
  411. X}
  412. X
  413. SHAR_EOF
  414. chmod 0644 zsh2.1/src/mem.c ||
  415. echo 'restore of zsh2.1/src/mem.c failed'
  416. Wc_c="`wc -c < 'zsh2.1/src/mem.c'`"
  417. test 5007 -eq "$Wc_c" ||
  418.     echo 'zsh2.1/src/mem.c: original size 5007, current size' "$Wc_c"
  419. rm -f _shar_wnt_.tmp
  420. fi
  421. # ============= zsh2.1/src/params.c ==============
  422. if test -f 'zsh2.1/src/params.c' -a X"$1" != X"-c"; then
  423.     echo 'x - skipping zsh2.1/src/params.c (File already exists)'
  424.     rm -f _shar_wnt_.tmp
  425. else
  426. > _shar_wnt_.tmp
  427. echo 'x - extracting zsh2.1/src/params.c (Text)'
  428. sed 's/^X//' << 'SHAR_EOF' > 'zsh2.1/src/params.c' &&
  429. X/*
  430. X
  431. X    params.c - parameters
  432. X
  433. X    This file is part of zsh, the Z shell.
  434. X
  435. X    zsh is free software; no one can prevent you from reading the source
  436. X   code, or giving it to someone else.
  437. X
  438. X   This file is copyrighted under the GNU General Public License, which
  439. X   can be found in the file called COPYING.
  440. X
  441. X   Copyright (C) 1990, 1991 Paul Falstad
  442. X
  443. X   zsh is distributed in the hope that it will be useful, but
  444. X   WITHOUT ANY WARRANTY.  No author or distributor accepts
  445. X   responsibility to anyone for the consequences of using it or for
  446. X   whether it serves any particular purpose or works at all, unless he
  447. X   says so in writing.  Refer to the GNU General Public License
  448. X   for full details.
  449. X
  450. X   Everyone is granted permission to copy, modify and redistribute
  451. X   zsh, but only under the conditions described in the GNU General Public
  452. X   License.   A copy of this license is supposed to have been given to you
  453. X   along with zsh so you can know your rights and responsibilities.
  454. X   It should be in a file named COPYING.
  455. X
  456. X   Among other things, the copyright notice and this notice must be
  457. X   preserved on all copies.
  458. X
  459. X*/
  460. X
  461. X#include "zsh.h"
  462. X#include <pwd.h>
  463. X
  464. X#define new(X) (X=(vptr)alloc(sizeof(*(X))))
  465. X
  466. Xstatic Param argvparam;
  467. X
  468. X/* put predefined params in hash table */
  469. X
  470. Xvoid setupparams() /**/
  471. X{
  472. X/* special integer params */
  473. Xstatic struct { char *name;
  474. X            long (*get) DCLPROTO((Param));
  475. X            void (*set) DCLPROTO((Param,long)); } x1[] = {
  476. X    "#",poundgetfn,NULL,
  477. X    "ARGC",poundgetfn,NULL,
  478. X    "ERRNO",errnogetfn,NULL,
  479. X    "GID",gidgetfn,NULL,
  480. X    "HISTSIZE",histsizegetfn,histsizesetfn,
  481. X    "LITHISTSIZE",lithistsizegetfn,lithistsizesetfn,
  482. X    "RANDOM",randomgetfn,randomsetfn,
  483. X    "SECONDS",secondsgetfn,secondssetfn,
  484. X    "UID",uidgetfn,NULL,
  485. X    NULL,NULL,NULL
  486. X    }, *p1 = x1;
  487. X/* special string params */
  488. Xstatic struct { char *name;
  489. X            char *(*get) DCLPROTO((Param));
  490. X            void (*set) DCLPROTO((Param,char *)); } x2[] = {
  491. X    "-",dashgetfn,NULL,
  492. X    "HISTCHARS",histcharsgetfn,histcharssetfn,
  493. X    "HOME",homegetfn,homesetfn,
  494. X    "TERM",termgetfn,termsetfn,
  495. X    "WORDCHARS",wordcharsgetfn,wordcharssetfn,
  496. X    "IFS",ifsgetfn,ifssetfn,
  497. X    "_",underscoregetfn,NULL,
  498. X    NULL,NULL,NULL
  499. X    }, *p2 = x2;
  500. X/* constant string params */
  501. Xstatic struct { char *name,*data; } x3[] = {
  502. X    "HOSTTYPE",HOSTTYPE,
  503. X    "VERSION",VERSIONSTR,
  504. X    NULL,NULL
  505. X    }, *p3 = x3;
  506. X/* variable integer params */
  507. Xstatic struct { char *name; long *data; } x4[] = {
  508. X    "!",&lastpid,                /* read only */
  509. X    "$",&mypid,
  510. X    "?",&lastval,
  511. X    "status",&lastval,
  512. X    "LINENO",&lineno,
  513. X    "PPID",&ppid,
  514. X    NULL,NULL,
  515. X
  516. X    "BAUD",&baud,                /* read/write */
  517. X    "COLUMNS",&columns,
  518. X    "DIRSTACKSIZE",&dirstacksize,
  519. X    "LINES",&lines,
  520. X    "LISTMAX",&listmax,
  521. X    "LOGCHECK",&logcheck,
  522. X    "MAILCHECK",&mailcheck,
  523. X    "OPTIND",&optind,
  524. X    "PERIOD",&period,
  525. X    "SAVEHIST",&savehist,
  526. X    "SHLVL",&shlvl,
  527. X    "TMOUT",&tmout,
  528. X    NULL,NULL
  529. X    }, *p4 = x4;
  530. X/* variable string params */
  531. Xstatic struct { char *name; char **data; } x5[] = {
  532. X    "LOGNAME",&username,        /* read only */
  533. X    "OLDPWD",&oldpwd,
  534. X    "PWD",&cwd,
  535. X    "TTY",&ttystrname,
  536. X    "USERNAME",&username,
  537. X    NULL,NULL,
  538. X
  539. X    "FCEDIT",&fceditparam,    /* read/write */
  540. X    "HOST",&hostnam,
  541. X    "OPTARG",&optarg,
  542. X    "MAIL",&mailfile,
  543. X    "NULLCMD",&nullcmd,
  544. X    "prompt",&prompt,
  545. X    "PROMPT",&prompt,
  546. X    "PROMPT2",&prompt2,
  547. X    "PROMPT3",&prompt3,
  548. X    "PROMPT4",&prompt4,
  549. X    "RPROMPT",&rprompt,
  550. X    "PS1",&prompt,
  551. X    "PS2",&prompt2,
  552. X    "PS3",&prompt3,
  553. X    "PS4",&prompt4,
  554. X    "RPS1",&rprompt,
  555. X    "SPROMPT",&sprompt,
  556. X    "TIMEFMT",&timefmt,
  557. X    "TMPPREFIX",&tmpprefix,
  558. X    "WATCHFMT",&watchfmt,
  559. X    "0",&argzero,
  560. X    NULL,NULL
  561. X    }, *p5 = x5;
  562. X/* colonsplit string params */
  563. Xstatic struct { char *name; } x6[] = {
  564. X    "CDPATH","FIGNORE","FPATH","MAILPATH","WATCH","HOSTS",
  565. X    "HOSTCMDS","OPTCMDS","BINDCMDS","VARCMDS",
  566. X    NULL
  567. X    }, *p6 = x6;
  568. X/* variable array params */
  569. Xstatic struct { char *name; char ***data; } x7[] = {
  570. X    "cdpath",&cdpath,
  571. X    "fignore",&fignore,
  572. X    "fpath",&fpath,
  573. X    "mailpath",&mailpath,
  574. X    "watch",&watch,
  575. X    "hosts",&hosts,
  576. X    "hostcmds",&hostcmds,
  577. X    "optcmds",&optcmds,
  578. X    "bindcmds",&bindcmds,
  579. X    "varcmds",&varcmds,
  580. X    "signals",(char ***) &sigptr,
  581. X    "argv",&pparams,
  582. X    "*",&pparams,
  583. X    "@",&pparams,
  584. X    NULL,NULL
  585. X    }, *p7 = x7;
  586. X/* special array params */
  587. Xstatic struct { char *name;
  588. X                    char **(*get) DCLPROTO((Param));
  589. X                    void (*set) DCLPROTO((Param,char **)); } x8[] = {
  590. X    "path",pathgetfn,pathsetfn,
  591. X    NULL,NULL,NULL
  592. X    }, *p8 = x8;
  593. XParam pm,pm2;
  594. X
  595. X    for (;p1->name;p1++)
  596. X        {
  597. X        new(pm);
  598. X        pm->gets.ifn = p1->get;
  599. X        pm->sets.ifn = p1->set;
  600. X        pm->flags = (p1->set) ? PMFLAG_i|PMFLAG_SPECIAL :
  601. X            PMFLAG_r|PMFLAG_i|PMFLAG_SPECIAL;
  602. X        pm->ct = 10;
  603. X        addhperm(p1->name,pm,paramtab,NULL);
  604. X        }
  605. X    for (;p2->name;p2++)
  606. X        {
  607. X        new(pm);
  608. X        pm->gets.cfn = p2->get;
  609. X        pm->sets.cfn = p2->set;
  610. X        pm->flags = (p2->set) ? PMFLAG_SPECIAL : PMFLAG_r|PMFLAG_SPECIAL;
  611. X        addhperm(p2->name,pm,paramtab,NULL);
  612. X        }
  613. X    for (;p3->name;p3++)
  614. X        {
  615. X        new(pm);
  616. X        pm->gets.cfn = strconstgetfn;
  617. X        pm->flags = PMFLAG_r|PMFLAG_SPECIAL;
  618. X        pm->data = p3->data;
  619. X        addhperm(p3->name,pm,paramtab,NULL);
  620. X        }
  621. X    for (;p4->name;p4++)
  622. X        {
  623. X        new(pm);
  624. X        pm->gets.ifn = intvargetfn;
  625. X        pm->sets.ifn = NULL;
  626. X        pm->data = p4->data;
  627. X        pm->flags = PMFLAG_r|PMFLAG_i|PMFLAG_SPECIAL;
  628. X        pm->ct = 10;
  629. X        addhperm(p4->name,pm,paramtab,NULL);
  630. X        }
  631. X    for (p4++;p4->name;p4++)
  632. X        {
  633. X        new(pm);
  634. X        pm->gets.ifn = intvargetfn;
  635. X        pm->sets.ifn = intvarsetfn;
  636. X        pm->data = p4->data;
  637. X        pm->flags = PMFLAG_i|PMFLAG_SPECIAL;
  638. X        pm->ct = 10;
  639. X        addhperm(p4->name,pm,paramtab,NULL);
  640. X        }
  641. X    for (;p5->name;p5++)
  642. X        {
  643. X        new(pm);
  644. X        pm->gets.cfn = strvargetfn;
  645. X        pm->sets.cfn = NULL;
  646. X        pm->data = p5->data;
  647. X        pm->flags = PMFLAG_r|PMFLAG_SPECIAL;
  648. X        addhperm(p5->name,pm,paramtab,NULL);
  649. X        }
  650. X    for (p5++;p5->name;p5++)
  651. X        {
  652. X        new(pm);
  653. X        pm->gets.cfn = strvargetfn;
  654. X        pm->sets.cfn = strvarsetfn;
  655. X        pm->data = p5->data;
  656. X        pm->flags = PMFLAG_SPECIAL;
  657. X        addhperm(p5->name,pm,paramtab,NULL);
  658. X        }
  659. X    for (;p6->name;p6++,p7++)
  660. X        {
  661. X        new(pm);
  662. X        new(pm2);
  663. X        pm->gets.cfn = colonarrgetfn;
  664. X        pm->sets.cfn = colonarrsetfn;
  665. X        pm2->gets.afn = arrvargetfn;
  666. X        pm2->sets.afn = arrvarsetfn;
  667. X        pm->data = p7->data;
  668. X        pm2->data = p7->data;
  669. X        pm->flags = PMFLAG_SPECIAL;
  670. X        pm2->flags = PMFLAG_A|PMFLAG_SPECIAL;
  671. X        pm2->ename = p6->name;
  672. X        addhperm(p6->name,pm,paramtab,NULL);
  673. X        addhperm(p7->name,pm2,paramtab,NULL);
  674. X        }
  675. X    new(pm);
  676. X    pm->gets.cfn = colonarrgetfn;
  677. X    pm->sets.cfn = colonarrsetfn;
  678. X    pm->data = NULL;
  679. X    pm->flags = PMFLAG_SPECIAL;
  680. X    addhperm("PATH",pm,paramtab,NULL);
  681. X    for (;p7->name;p7++)
  682. X        {
  683. X        new(pm);
  684. X        pm->gets.afn = arrvargetfn;
  685. X        pm->sets.afn = arrvarsetfn;
  686. X        pm->data = p7->data;
  687. X        pm->flags = PMFLAG_A|PMFLAG_SPECIAL;
  688. X        if (pm->data == &sigptr)
  689. X            pm->flags |= PMFLAG_r;
  690. X        addhperm(p7->name,pm,paramtab,NULL);
  691. X        }
  692. X    for (;p8->name;p8++)
  693. X        {
  694. X        new(pm);
  695. X        pm->gets.afn = p8->get;
  696. X        pm->sets.afn = p8->set;
  697. X        pm->flags = PMFLAG_A|PMFLAG_SPECIAL;
  698. X        addhperm(p8->name,pm,paramtab,NULL);
  699. X        }
  700. X    argvparam = gethnode("argv",paramtab);
  701. X}
  702. X
  703. Xstatic int unsetflag;
  704. X
  705. Xstruct param *createparam(name,value,flags) /**/
  706. Xchar *name;vptr value;int flags;
  707. X{
  708. Xstruct param *pm;
  709. Xchar buf[20];
  710. X
  711. X    pm = zcalloc(sizeof *pm);
  712. X    if (isset(ALLEXPORT))
  713. X        flags |= PMFLAG_x;
  714. X    pm->flags = flags;
  715. X    if ((flags & PMTYPE) == PMFLAG_s)
  716. X        {
  717. X        pm->u.str = ztrdup(value);
  718. X        pm->sets.cfn = strsetfn;
  719. X        pm->gets.cfn = strgetfn;
  720. X        }
  721. X    else if ((flags & PMTYPE) == PMFLAG_A)
  722. X        {
  723. X        pm->u.arr = value;
  724. X        pm->sets.afn = arrsetfn;
  725. X        pm->gets.afn = arrgetfn;
  726. X        }
  727. X    else
  728. X        {
  729. X        pm->u.val = (value) ? matheval(value) : 0;
  730. X        pm->sets.ifn = intsetfn;
  731. X        pm->gets.ifn = intgetfn;
  732. X        sprintf(buf,"%ld",pm->u.val);
  733. X        value = buf;
  734. X        }
  735. X    if (flags & PMFLAG_x)
  736. X        pm->env = addenv(name,value);
  737. X    addhnode(ztrdup(name),pm,paramtab,freepm);
  738. X    return pm;
  739. X}
  740. X
  741. Xint isident(s) /**/
  742. Xchar *s;
  743. X{
  744. Xchar *ss;
  745. X
  746. X    for (ss = s; *ss; ss++) if (!iident(*ss)) break;
  747. X    if (!*ss || *ss == '[') return 1;
  748. X    if (*s == Quest)
  749. X        *s = '?';
  750. X    else if (*s == Pound)
  751. X        *s = '#';
  752. X    else if (*s == String || *s == Qstring)
  753. X        *s = '$';
  754. X    else if (*s == Star)
  755. X        *s = '*';
  756. X    if (*s == '#' || *s == '-' || *s == '?' || *s == '$' || *s == '_' ||
  757. X         *s == '!' || *s == '@' || *s == '*')
  758. X        return 1;
  759. X    return 0;
  760. X}
  761. X
  762. XValue getvalue(pptr,bracks) /**/
  763. Xchar **pptr;int bracks;
  764. X{
  765. Xchar *s = *pptr,*t = *pptr;
  766. Xchar sav;
  767. XValue v;
  768. X
  769. X    if (idigit(*s)) while (idigit(*s)) s++;
  770. X    else if (iident(*s)) while (iident(*s)) s++;
  771. X    else if (*s == Quest) *s++ = '?';
  772. X    else if (*s == Pound) *s++ = '#';
  773. X    else if (*s == String) *s++ = '$';
  774. X    else if (*s == Qstring) *s++ = '$';
  775. X    else if (*s == Star) *s++ = '*';
  776. X    else if (*s == '#' || *s == '-' || *s == '?' || *s == '$' ||
  777. X                *s == '_' || *s == '!' || *s == '@' || *s == '*') s++;
  778. X    else return NULL;
  779. X    if (sav = *s) *s = '\0';
  780. X    if (idigit(*t) && *t != '0') {
  781. X        v = (Value) alloc(sizeof *v);
  782. X        v->pm = argvparam;
  783. X        v->a = v->b = atoi(t)-1;
  784. X        if (sav)
  785. X            *s = sav;
  786. X    } else {
  787. X        struct param *pm;
  788. X        int isvarat = !strcmp(t, "@");
  789. X
  790. X        pm = gethnode(t,paramtab);
  791. X        if (sav)
  792. X            *s = sav;
  793. X        *pptr = s;
  794. X        if (!pm)
  795. X            return NULL;
  796. X        v = alloc(sizeof *v);
  797. X        if (pmtype(pm) == PMFLAG_A)
  798. X            v->isarr = isvarat ? -1 : 1;
  799. X        v->pm = pm;
  800. X        v->a = 0; v->b = -1;
  801. X        if (bracks && (*s == '[' || *s == Inbrack)) {
  802. X            int a,b;
  803. X            char *olds = s,*t;
  804. X
  805. X            *s++ = '[';
  806. X            for (t = s; *t && *t != ']' && *t != Outbrack; t++)
  807. X                if (itok(*t))
  808. X                    *t = ztokens[*t-Pound];
  809. X            if (*t == Outbrack)
  810. X                *t = ']';
  811. X            if ((s[0] == '*' || s[0] == '@')  && s[1] == ']') {
  812. X                v->isarr = (s[0] == '*') ? 1 : -1;
  813. X                v->a = 0;
  814. X                v->b = -1;
  815. X                s += 2;
  816. X            } else {
  817. X                a = mathevalarg(s,&s);
  818. X                if (a > 0) a--;
  819. X                if (*s == ',' || *s == Comma) {
  820. X                    s++;
  821. X                    b = mathevalarg(s,&s);
  822. X                    if (b > 0) b--;
  823. X                } else
  824. X                    b = a;
  825. X                if (*s == ']') {
  826. X                    s++;
  827. X                    if (v->isarr && a == b)
  828. X                        v->isarr = 0;
  829. X                    v->a = a;
  830. X                    v->b = b;
  831. X                } else
  832. X                    s = olds;
  833. X            }
  834. X        }
  835. X    }
  836. X    if (!bracks && *s)
  837. X        return NULL;
  838. X    *pptr = s;
  839. X    return v;
  840. X}
  841. X
  842. Xchar *getstrvalue(v) /**/
  843. XValue v;
  844. X{
  845. Xchar *s,**ss;
  846. Xstatic char buf[20];
  847. X
  848. X    if (!v)
  849. X        return "";
  850. X    if (pmtype(v->pm) != PMFLAG_A) {
  851. X        if ((pmtype(v->pm) == PMFLAG_i))
  852. X            convbase(s = buf,v->pm->gets.ifn(v->pm),v->pm->ct);
  853. X        else
  854. X            s = v->pm->gets.cfn(v->pm);
  855. X        if (v->a == 0 && v->b == -1) return s;
  856. X        if (v->a < 0) v->a += strlen(s);
  857. X        if (v->b < 0) v->b += strlen(s);
  858. X        s = (v->a > strlen(s)) ? strdup("") : strdup(s+v->a);
  859. X        if (v->b < v->a) s[0] = '\0';
  860. X        else if (v->b-v->a < strlen(s)) s[v->b-v->a+1] = '\0';
  861. X        return s;
  862. X    }
  863. X    if (v->isarr) return spacejoin(v->pm->gets.afn(v->pm));
  864. X
  865. X    ss = v->pm->gets.afn(v->pm);
  866. X    if (v->a < 0) v->a += arrlen(ss);
  867. X    s = (v->a >= arrlen(ss) || v->a < 0) ? "" : ss[v->a];
  868. X    return s;
  869. X}
  870. X
  871. Xchar **getarrvalue(v) /**/
  872. XValue v;
  873. X{
  874. Xchar **s;
  875. Xstatic char *nular[] = { "", NULL };
  876. X
  877. X    if (!v)
  878. X        return arrdup(nular);
  879. X    s = v->pm->gets.afn(v->pm);
  880. X    if (v->a == 0 && v->b == -1) return s;
  881. X    if (v->a < 0) v->a += arrlen(s);
  882. X    if (v->b < 0) v->b += arrlen(s);
  883. X    if (v->a > arrlen(s) || v->a < 0)
  884. X        s = arrdup(nular);
  885. X    else
  886. X        s = arrdup(s)+v->a;
  887. X    if (v->b < v->a) s[0] = NULL;
  888. X    else if (v->b-v->a < arrlen(s)) s[v->b-v->a+1] = NULL;
  889. X    return s;
  890. X}
  891. X
  892. Xlong getintvalue(v) /**/
  893. XValue v;
  894. X{
  895. Xchar **ss;
  896. X
  897. X    if (!v || v->isarr)
  898. X        return 0;
  899. X    if (pmtype(v->pm) != PMFLAG_A) {
  900. X        if (pmtype(v->pm) == PMFLAG_i)
  901. X            return v->pm->gets.ifn(v->pm);
  902. X        return atol(v->pm->gets.cfn(v->pm));
  903. X    }
  904. X    ss = v->pm->gets.afn(v->pm);
  905. X    if (v->a < 0) v->a += arrlen(ss);
  906. X    if (v->a < 0 || v->a > arrlen(ss)) return 0;
  907. X    return atol(ss[v->a]);
  908. X}
  909. X
  910. Xvoid setstrvalue(v,val) /**/
  911. XValue v;char *val;
  912. X{
  913. Xchar *s;
  914. X
  915. X    if (v->pm->flags & PMFLAG_r)
  916. X        return;
  917. X    if ((s = v->pm->env) && val)
  918. X        v->pm->env = replenv(v->pm->env,val);
  919. X    switch (pmtype(v->pm)) {
  920. X        case PMFLAG_s:
  921. X            if (v->a == 0 && v->b == -1)
  922. X                (v->pm->sets.cfn)(v->pm,val);
  923. X            else {
  924. X                char *z,*y,*x;
  925. X
  926. X                z = strdup((v->pm->gets.cfn)(v->pm));
  927. X                if (v->a < 0) {
  928. X                    v->a += strlen(z);
  929. X                    if (v->a < 0) v->a = 0;
  930. X                }
  931. X                if (v->a > strlen(z)) v->a = strlen(z);
  932. X                if (v->b < 0) v->b += strlen(z);
  933. X                if (v->b <= v->a) v->b = v->a-1;
  934. X                z[v->a] = '\0';
  935. X                y = z+v->b+1;
  936. X                x = zalloc(strlen(z)+strlen(y)+strlen(val)+1);
  937. X                strcpy(x,z);
  938. X                strcat(x,val);
  939. X                strcat(x,y);
  940. X                (v->pm->sets.cfn)(v->pm,z);
  941. X            }
  942. X            if (v->pm->flags & (PMFLAG_L|PMFLAG_R|PMFLAG_Z) && !v->pm->ct)
  943. X                v->pm->ct = strlen(val);
  944. X            break;
  945. X        case PMFLAG_i:
  946. X            (v->pm->sets.ifn)(v->pm,matheval(val));
  947. X            if (!v->pm->ct && lastbase != 1)
  948. X                v->pm->ct = lastbase;
  949. X            free(val);
  950. X            break;
  951. X        case PMFLAG_A:
  952. X            if (v->a != v->b)
  953. X                zerr("illegal array assignment",NULL,0);
  954. X            else {
  955. X                char **ss = (v->pm->gets.afn)(v->pm);
  956. X                int ac,ad,t0;
  957. X
  958. X                ac = arrlen(ss);
  959. X                if (v->a < 0) {
  960. X                    v->a += ac;
  961. X                    if (v->a < 0) v->a = 0;
  962. X                }
  963. X                if (v->a >= ac) {
  964. X                    char **st = ss;
  965. X
  966. X                    ad = v->a+1;
  967. X                    ss = zalloc((ad+1)*sizeof *ss);
  968. X                    memcpy(ss,st,(ad+1)*sizeof *ss);
  969. X                    for (t0 = 0; t0 != ac; t0++)
  970. X                        ss[t0] = ztrdup(ss[t0]);
  971. X                    while (ac < ad)
  972. X                        ss[ac++] = ztrdup("");
  973. X                    ss[ac] = NULL;
  974. X                }
  975. X                if (ss[v->a]) free(ss[v->a]);
  976. X                ss[v->a] = val;
  977. X                (v->pm->sets.afn)(v->pm,ss);
  978. X            }
  979. X            break;
  980. X    }
  981. X}
  982. X
  983. Xvoid setintvalue(v,val) /**/
  984. XValue v;long val;
  985. X{
  986. Xchar buf[20];
  987. X
  988. X    if (v->pm->flags & PMFLAG_r)
  989. X        return;
  990. X    if (v->pm->env) {
  991. X        sprintf(buf,"%ld",val);
  992. X        v->pm->env = replenv(v->pm->env,buf);
  993. X    }
  994. X    switch (pmtype(v->pm))
  995. X        {
  996. X        case PMFLAG_s:
  997. X            sprintf(buf,"%ld",val);
  998. X            (v->pm->sets.cfn)(v->pm,ztrdup(buf));
  999. X            break;
  1000. X        case PMFLAG_i:
  1001. X            (v->pm->sets.ifn)(v->pm,val);
  1002. X            if (!v->pm->ct && lastbase != -1)
  1003. X                v->pm->ct = lastbase;
  1004. X            break;
  1005. X        case PMFLAG_A:
  1006. X            zerr("attempt to assign integer to array",NULL,0);
  1007. X            break;
  1008. X        }
  1009. X}
  1010. X
  1011. Xvoid setarrvalue(v,val) /**/
  1012. XValue v;char **val;
  1013. X{
  1014. X    if (v->pm->flags & PMFLAG_r)
  1015. X        return;
  1016. X    if (pmtype(v->pm) != PMFLAG_A)
  1017. X        {
  1018. X        zerr("attempt to assign non-array to array",NULL,0);
  1019. X        return;
  1020. X        }
  1021. X    (v->pm->sets.afn)(v->pm,val);
  1022. X}
  1023. X
  1024. Xchar *getsparamval(s,l) /**/
  1025. Xchar *s;int l;
  1026. X{
  1027. Xchar sav,*t = s;
  1028. XValue v;
  1029. X
  1030. X    if (sav = t[l])
  1031. X        t[l] = '\0';
  1032. X    if (!(v = getvalue(&s,0)))
  1033. X        return NULL;
  1034. X    t[l] = sav;
  1035. X    t = getstrvalue(v);
  1036. X    return t;
  1037. X}
  1038. X
  1039. Xlong getiparam(s) /**/
  1040. Xchar *s;
  1041. X{
  1042. XValue v;
  1043. X
  1044. X    if (!(v = getvalue(&s,0)))
  1045. X        return 0;
  1046. X    return getintvalue(v);
  1047. X}
  1048. X
  1049. Xchar *getsparam(s) /**/
  1050. Xchar *s;
  1051. X{
  1052. XValue v;
  1053. X
  1054. X    if (!(v = getvalue(&s,0)))
  1055. X        return NULL;
  1056. X    return getstrvalue(v);
  1057. X}
  1058. X
  1059. XParam setsparam(s,val) /**/
  1060. Xchar *s;char *val;
  1061. X{
  1062. XValue v;
  1063. Xchar *t = s;
  1064. X
  1065. X    if (!isident(s))
  1066. X        {
  1067. X        zerr("not an identifier: %s",s,0);
  1068. X        return NULL;
  1069. X        }
  1070. X    if (!(v = getvalue(&s,1)) || *s)
  1071. X        return createparam(t,val,PMFLAG_s);
  1072. X    if ((v->pm->flags & PMTYPE) != PMFLAG_s &&
  1073. X            !(v->pm->flags & PMFLAG_SPECIAL)) {
  1074. X        unsetparam(s);
  1075. X        return createparam(t,val,PMFLAG_s);
  1076. X    }
  1077. X    setstrvalue(v,val);
  1078. X    return v->pm;
  1079. X}
  1080. X
  1081. XParam setaparam(s,val) /**/
  1082. Xchar *s;char **val;
  1083. X{
  1084. XValue v;
  1085. Xchar *t = s;
  1086. X
  1087. X    if (!isident(s))
  1088. X        {
  1089. X        zerr("not an identifier: %s",s,0);
  1090. X        return NULL;
  1091. X        }
  1092. X    if (!(v = getvalue(&s,1)) || *s)
  1093. X        return createparam(t,val,PMFLAG_A);
  1094. X    if ((v->pm->flags & PMTYPE) != PMFLAG_A &&
  1095. X            !(v->pm->flags & PMFLAG_SPECIAL)) {
  1096. X        unsetparam(s);
  1097. X        return createparam(t,val,PMFLAG_A);
  1098. X    }
  1099. X    setarrvalue(v,val);
  1100. X    return v->pm;
  1101. X}
  1102. X
  1103. XParam setiparam(s,val) /**/
  1104. Xchar *s;long val;
  1105. X{
  1106. XValue v;
  1107. Xchar *t = s;
  1108. XParam pm;
  1109. X
  1110. X    if (!isident(s))
  1111. X        {
  1112. X        zerr("not an identifier: %s",s,0);
  1113. X        return NULL;
  1114. X        }
  1115. X    if (!(v = getvalue(&s,0)))
  1116. X        {
  1117. X        pm = createparam(t,NULL,PMFLAG_i);
  1118. X        pm->u.val = val;
  1119. X        return pm;
  1120. X        }
  1121. X    setintvalue(v,val);
  1122. X    return v->pm;
  1123. X}
  1124. X
  1125. Xvoid unsetparam(s) /**/
  1126. Xchar *s;
  1127. X{
  1128. XParam pm;
  1129. X
  1130. X    if (!(pm = gethnode(s,paramtab)))
  1131. X        return;
  1132. X    if (pm->flags & PMFLAG_r)
  1133. X        return;
  1134. X    unsetflag = 1;
  1135. X    switch (pmtype(pm))
  1136. X        {
  1137. X        case 0:
  1138. X            (pm->sets.cfn)(pm,ztrdup(""));
  1139. X            break;
  1140. X        case PMFLAG_i:
  1141. X            (pm->sets.ifn)(pm,0);
  1142. X            break;
  1143. X        case PMFLAG_A:
  1144. X            (pm->sets.afn)(pm,mkarray(NULL));
  1145. X            break;
  1146. X        }
  1147. X    if (pmtype(pm) == PMFLAG_s && (pm->flags & PMFLAG_x))
  1148. X        delenv(pm->env);
  1149. X    if (!(pm->flags & PMFLAG_SPECIAL))
  1150. X        freepm(remhnode(s,paramtab));
  1151. X    unsetflag = 0;
  1152. X}
  1153. X
  1154. Xvoid intsetfn(pm,x) /**/
  1155. XParam pm;long x;
  1156. X{
  1157. X    pm->u.val = x;
  1158. X}
  1159. X
  1160. Xlong intgetfn(pm) /**/
  1161. XParam pm;
  1162. X{
  1163. X    return pm->u.val;
  1164. X}
  1165. X
  1166. Xvoid strsetfn(pm,x) /**/
  1167. XParam pm;char *x;
  1168. X{
  1169. X    if (x) 
  1170. X        {
  1171. X        if (pm->u.str)
  1172. X            free(pm->u.str);
  1173. X        pm->u.str = x;
  1174. X        }
  1175. X}
  1176. X
  1177. Xchar *strgetfn(pm) /**/
  1178. XParam pm;
  1179. X{
  1180. X    return pm->u.str;
  1181. X}
  1182. X
  1183. Xvoid arrsetfn(pm,x) /**/
  1184. XParam pm;char **x;
  1185. X{
  1186. Xint ct;
  1187. X
  1188. X    if (x)
  1189. X        {
  1190. X        if (pm->u.arr && pm->u.arr != x)
  1191. X            freearray(pm->u.arr);
  1192. X        pm->u.arr = x;
  1193. X        for (ct = 0; *x; x++,ct++);
  1194. X        pm->ct = ct;
  1195. X        }
  1196. X}
  1197. X
  1198. Xchar **arrgetfn(pm) /**/
  1199. XParam pm;
  1200. X{
  1201. X    return pm->u.arr;
  1202. X}
  1203. X
  1204. Xvoid intvarsetfn(pm,x) /**/
  1205. XParam pm;long x;
  1206. X{
  1207. X    *((long *) pm->data) = x;
  1208. X}
  1209. X
  1210. Xlong intvargetfn(pm) /**/
  1211. XParam pm;
  1212. X{
  1213. X    return *((long *) pm->data);
  1214. X}
  1215. X
  1216. Xvoid strvarsetfn(pm,x) /**/
  1217. XParam pm;char *x;
  1218. X{
  1219. X    *((char **) pm->data) = x;
  1220. X}
  1221. X
  1222. Xvoid strvarnonullsetfn(pm,x) /**/
  1223. XParam pm;char *x;
  1224. X{
  1225. X    *((char **) pm->data) = (x) ? x : ztrdup("");
  1226. X}
  1227. X
  1228. Xchar *strvargetfn(pm) /**/
  1229. XParam pm;
  1230. X{
  1231. Xchar *s;
  1232. X
  1233. X    s = *((char **) pm->data);
  1234. X    if (!s)
  1235. X        return "";
  1236. X    return s;
  1237. X}
  1238. X
  1239. Xchar *strconstgetfn(pm) /**/
  1240. XParam pm;
  1241. X{
  1242. X    return (char *) pm->data;
  1243. X}
  1244. X
  1245. Xvoid colonarrsetfn(pm,x) /**/
  1246. XParam pm;char *x;
  1247. X{
  1248. Xchar **s,**t,*u;
  1249. X
  1250. X    s = colonsplit(x);
  1251. X    for (t = s; *t; t++)
  1252. X        {
  1253. X        u = *t;
  1254. X        if (*u == '~')
  1255. X            *u = Tilde;
  1256. X        if (*u == '=')
  1257. X            *u = Equals;
  1258. X        u = strdup(u);
  1259. X        filesub(&u);
  1260. X        if (!*u)
  1261. X            u = ".";
  1262. X        *t = ztrdup(u);
  1263. X        }
  1264. X    if (pm->data)
  1265. X        {
  1266. X        *((char ***) pm->data) = s;
  1267. X        if (pm->ename)
  1268. X            arrfixenv(pm->ename,s);
  1269. X        }
  1270. X    else
  1271. X        {
  1272. X        path = s;
  1273. X        newcmdnamtab();
  1274. X        arrfixenv("PATH",s);
  1275. X        }
  1276. X}
  1277. X
  1278. Xchar *colonarrgetfn(pm) /**/
  1279. XParam pm;
  1280. X{
  1281. X    if ((char **) pm->data)
  1282. X        return colonjoin(*(char ***) pm->data);
  1283. X    else
  1284. X        return colonjoin(path);
  1285. X}
  1286. X
  1287. Xchar **arrvargetfn(pm) /**/
  1288. XParam pm;
  1289. X{
  1290. X    return *((char ***) pm->data);
  1291. X}
  1292. X
  1293. Xvoid arrvarsetfn(pm,x) /**/
  1294. XParam pm;char **x;
  1295. X{
  1296. X    if ((*(char ***) pm->data) != x)
  1297. X        freearray(*(char ***) pm->data);
  1298. X    *((char ***) pm->data) = x;
  1299. X    if (pm->ename)
  1300. X        arrfixenv(pm->ename,x);
  1301. X}
  1302. X
  1303. Xchar **pathgetfn(pm) /**/
  1304. XParam pm;
  1305. X{
  1306. X    return path;
  1307. X}
  1308. X
  1309. Xvoid pathsetfn(pm,x) /**/
  1310. XParam pm;char **x;
  1311. X{
  1312. X    if (path != x)
  1313. X        freearray(path);
  1314. X    path = x;
  1315. X    newcmdnamtab();
  1316. X    arrfixenv("PATH",x);
  1317. X}
  1318. X
  1319. Xvoid unsettablesetfn(pm,x) /**/
  1320. XParam pm;char *x;
  1321. X{ ; }
  1322. X
  1323. Xlong poundgetfn(pm) /**/
  1324. XParam pm;
  1325. X{
  1326. X    return arrlen(pparams);
  1327. X}
  1328. X
  1329. Xlong randomgetfn(pm) /**/
  1330. XParam pm;
  1331. X{
  1332. X    return rand() & 0x7fff;
  1333. X}
  1334. X
  1335. Xvoid randomsetfn(pm,v) /**/
  1336. XParam pm;long v;
  1337. X{
  1338. X    srand((unsigned int) v);
  1339. X}
  1340. X
  1341. Xlong secondsgetfn(pm) /**/
  1342. XParam pm;
  1343. X{
  1344. X    return time(NULL)-shtimer;
  1345. X}
  1346. X
  1347. Xvoid secondssetfn(pm,x) /**/
  1348. XParam pm;long x;
  1349. X{
  1350. X    shtimer = x+time(NULL);
  1351. X}
  1352. X
  1353. Xlong uidgetfn(pm) /**/
  1354. XParam pm;
  1355. X{
  1356. X    return getuid();
  1357. X}
  1358. X
  1359. Xlong gidgetfn(pm) /**/
  1360. XParam pm;
  1361. X{
  1362. X    return getegid();
  1363. X}
  1364. X
  1365. Xchar *usernamegetfn(pm) /**/
  1366. XParam pm;
  1367. X{
  1368. Xstruct passwd *pwd;
  1369. X
  1370. X    pwd = getpwuid(getuid());
  1371. X    return pwd->pw_name;
  1372. X}
  1373. X
  1374. Xchar *hostgetfn(pm) /**/
  1375. XParam pm;
  1376. X{
  1377. Xstatic char hostnam[65];
  1378. Xstatic int got = 0;
  1379. X
  1380. X    if (!got)
  1381. X        {
  1382. X        gethostname(hostnam,64);
  1383. X        hostnam[64] = '\0';
  1384. X        got = 1;
  1385. X        }
  1386. X    return hostnam;
  1387. X}
  1388. X
  1389. Xchar *ifsgetfn(pm) /**/
  1390. XParam pm;
  1391. X{
  1392. X    return ifs;
  1393. X}
  1394. X
  1395. Xvoid ifssetfn(pm,x) /**/
  1396. XParam pm;char *x;
  1397. X{
  1398. X    if (x) ifs = x;
  1399. X    inittyptab();
  1400. X}
  1401. X
  1402. Xvoid histsizesetfn(pm,v) /**/
  1403. XParam pm;long v;
  1404. X{
  1405. X    if ((histsiz = v) <= 2)
  1406. X        histsiz = 2;
  1407. X}
  1408. X
  1409. Xlong histsizegetfn(pm) /**/
  1410. XParam pm;
  1411. X{
  1412. X    return histsiz;
  1413. X}
  1414. X
  1415. Xvoid lithistsizesetfn(pm,v) /**/
  1416. XParam pm;long v;
  1417. X{
  1418. X    if ((lithistsiz = v) <= 2)
  1419. X        lithistsiz = 2;
  1420. X}
  1421. X
  1422. Xlong lithistsizegetfn(pm) /**/
  1423. XParam pm;
  1424. X{
  1425. X    return lithistsiz;
  1426. X}
  1427. X
  1428. Xvoid mailchecksetfn(pm,x) /**/
  1429. XParam pm;long x;
  1430. X{
  1431. X    mailcheck = (unsetflag) ? 600 : x;
  1432. X}
  1433. X
  1434. Xvoid pathasetfn(pm,x) /**/
  1435. XParam pm;char **x;
  1436. X{
  1437. X    freearray(path);
  1438. X    path = x;
  1439. X    newcmdnamtab();
  1440. X}
  1441. X
  1442. Xchar **pathagetfn(pm) /**/
  1443. XParam pm;
  1444. X{
  1445. X    return path;
  1446. X}
  1447. X
  1448. Xlong errnogetfn(pm) /**/
  1449. XParam pm;
  1450. X{
  1451. X    return errno;
  1452. X}
  1453. X
  1454. Xchar *dashgetfn(pm) /**/
  1455. XParam pm;
  1456. X{
  1457. Xstatic char buf[100];
  1458. Xchar *val = buf;
  1459. Xint t0;
  1460. X
  1461. X    for (val = buf, t0 = ' ';t0 <= 'z'; t0++)
  1462. X        if (opts[t0] == OPT_SET)
  1463. X            *val++ = t0;
  1464. X    *val = '\0';
  1465. X    return buf;
  1466. X}
  1467. X
  1468. Xchar *ttygetfn(pm) /**/
  1469. XParam pm;
  1470. X{
  1471. X    return ttyname(SHTTY);
  1472. X}
  1473. X
  1474. Xvoid histcharssetfn(pm,x) /**/
  1475. XParam pm;char *x;
  1476. X{
  1477. X    if (x)
  1478. X        {
  1479. X        bangchar = x[0];
  1480. X        hatchar = (bangchar) ? x[1] : '\0';
  1481. X        hashchar = (hatchar) ? x[2] : '\0';
  1482. X        free(x);
  1483. X        }
  1484. X}
  1485. X
  1486. Xchar *histcharsgetfn(pm) /**/
  1487. XParam pm;
  1488. X{
  1489. Xstatic char buf[4];
  1490. X
  1491. X    buf[0] = bangchar;
  1492. X    buf[1] = hatchar;
  1493. X    buf[2] = hashchar;
  1494. X    buf[3] = '\0';
  1495. X    return buf;
  1496. X}
  1497. X
  1498. Xchar *homegetfn(pm) /**/
  1499. XParam pm;
  1500. X{
  1501. X    return home;
  1502. X}
  1503. X
  1504. Xvoid homesetfn(pm,x) /**/
  1505. XParam pm;char *x;
  1506. X{
  1507. X    if (isset(CHASELINKS) && (home = xsymlink(x)))
  1508. X        free(x);
  1509. X    else
  1510. X        home = x;
  1511. X}
  1512. X
  1513. Xchar *wordcharsgetfn(pm) /**/
  1514. XParam pm;
  1515. X{
  1516. X    return wordchars;
  1517. X}
  1518. X
  1519. Xvoid wordcharssetfn(pm,x) /**/
  1520. XParam pm;char *x;
  1521. X{
  1522. X    if (x)
  1523. X        wordchars = x;
  1524. X    else
  1525. X        wordchars = ztrdup(DEFWORDCHARS);
  1526. X    inittyptab();
  1527. X}
  1528. X
  1529. Xchar *underscoregetfn(pm) /**/
  1530. XParam pm;
  1531. X{
  1532. Xchar *s,*t;
  1533. X
  1534. X    if (!(s = qgetevent(curhist-1)))
  1535. X        return "";
  1536. X    for (t = s+strlen(s); t > s; t--)
  1537. X        if (*t == HISTSPACE)
  1538. X            break;
  1539. X    if (t != s)
  1540. X        t++;
  1541. X    return t;
  1542. X}
  1543. X
  1544. Xchar *termgetfn(pm) /**/
  1545. XParam pm;
  1546. X{
  1547. X    return term;
  1548. X}
  1549. X
  1550. Xvoid termsetfn(pm,x) /**/
  1551. XParam pm;char *x;
  1552. X{
  1553. X    if (term)
  1554. X        free(term);
  1555. X    term = x;
  1556. X    if (!interact || unset(USEZLE))
  1557. X        return;
  1558. X    if (tgetent(termbuf,term) != 1)
  1559. X        {
  1560. X        zerr("can't find termcap info for %s",term,0);
  1561. X        errflag = 0;
  1562. X        termok = 0;
  1563. X        }
  1564. X    else
  1565. X        {
  1566. X        char tbuf[1024],*pp;
  1567. X        int t0;
  1568. X
  1569. X        termok = 1;
  1570. X        for (t0 = 0; t0 != TC_COUNT; t0++)
  1571. X            {
  1572. X            pp = tbuf;
  1573. X            if (tcstr[t0])
  1574. X                free(tcstr[t0]);
  1575. X            if (!tgetstr(tccapnams[t0],&pp))
  1576. X                tcstr[t0] = NULL, tclen[t0] = 0;
  1577. X            else
  1578. X                {
  1579. X                tcstr[t0] = zalloc(tclen[t0] = pp-tbuf);
  1580. X                memcpy(tcstr[t0],tbuf,tclen[t0]);
  1581. X                }
  1582. X            }
  1583. X
  1584. X/* if there's no termcap entry for cursor left, use \b. */
  1585. X
  1586. X        if (!tccan(TCLEFT))
  1587. X            {
  1588. X            tcstr[TCLEFT] = ztrdup("\b");
  1589. X            tclen[TCLEFT] = 1;
  1590. X            }
  1591. X
  1592. X/* if there's no termcap entry for clear, use ^L. */
  1593. X
  1594. X        if (!tccan(TCCLEARSCREEN))
  1595. X            {
  1596. X            tcstr[TCCLEARSCREEN] = ztrdup("\14");
  1597. X            tclen[TCCLEARSCREEN] = 1;
  1598. X            }
  1599. X
  1600. X/* if the termcap entry for down is \n, don't use it. */
  1601. X
  1602. X        if (tccan(TCDOWN) && tcstr[TCDOWN][0] == '\n')
  1603. X            {
  1604. X            tclen[TCDOWN] = 0;
  1605. X            tcstr[TCDOWN] = NULL;
  1606. X            }
  1607. X
  1608. X/* if there's no termcap entry for cursor up, forget it.
  1609. X    Use single line mode. */
  1610. X
  1611. X        if (!tccan(TCUP))
  1612. X            termok = 0;
  1613. X        }
  1614. X}
  1615. X
  1616. Xvoid setparams() /**/
  1617. X{
  1618. Xchar **envp,**envp2,**envp3,*str;
  1619. Xchar buf[50];
  1620. Xstruct param *pm;
  1621. Xint ct;
  1622. X
  1623. X    noerrs = 1;
  1624. X    for (envp = environ, ct = 2; *envp; envp++,ct++);
  1625. X    envp = environ;
  1626. X    envp2 = envp3 = (char **) zalloc(sizeof(char *)*ct);
  1627. X    for (; *envp; envp++)
  1628. X        *envp2++ = ztrdup(*envp);
  1629. X    *envp2 = NULL;
  1630. X    envp = environ;
  1631. X    environ = envp2 = envp3;
  1632. X    for (; *envp; envp++,envp2++) {
  1633. X        for (str = *envp; *str && *str != '='; str++);
  1634. X        if (*str == '=') {
  1635. X            char *iname;
  1636. X
  1637. X            *str = '\0';
  1638. X            if (isident(*envp))
  1639. X                pm = setsparam(iname = ztrdup(*envp),ztrdup(str+1));
  1640. X            *str = '=';
  1641. X            if (pm) {
  1642. X                pm->flags |= PMFLAG_x;
  1643. X                pm->env = *envp2;
  1644. X                if (pm->flags & PMFLAG_SPECIAL)
  1645. X                    pm->env = replenv(pm->env,getsparam(iname));
  1646. X            }
  1647. X        }
  1648. X    }
  1649. X    pm = gethnode("HOME",paramtab);
  1650. X    if (!(pm->flags & PMFLAG_x))
  1651. X        {
  1652. X        pm->flags |= PMFLAG_x;
  1653. X        pm->env = addenv("HOME",home);
  1654. X        }
  1655. X    pm = gethnode("PWD",paramtab);
  1656. X    if (!(pm->flags & PMFLAG_x))
  1657. X        {
  1658. X        pm->flags |= PMFLAG_x;
  1659. X        pm->env = addenv("PWD",cwd);
  1660. X        }
  1661. X    pm = gethnode("SHLVL",paramtab);
  1662. X    if (!(pm->flags & PMFLAG_x))
  1663. X        pm->flags |= PMFLAG_x;
  1664. X    sprintf(buf,"%d",++shlvl);
  1665. X    pm->env = addenv("SHLVL",buf);
  1666. X    noerrs = 0;
  1667. X}
  1668. X
  1669. Xchar *mkenvstr(x,y) /**/
  1670. Xchar *x;char *y;
  1671. X{
  1672. Xchar *z;
  1673. Xint xl = strlen(x),yl = strlen(y);
  1674. X
  1675. X    z = zalloc(xl+yl+2);
  1676. X    strcpy(z,x);
  1677. X    z[xl] = '=';
  1678. X    strcpy(z+xl+1,y);
  1679. X    z[xl+yl+1] = '\0';
  1680. X    return z;
  1681. X}
  1682. X
  1683. Xvoid arrfixenv(s,t) /**/
  1684. Xchar *s;char **t;
  1685. X{
  1686. Xchar **ep;
  1687. Xint sl = strlen(s);
  1688. X
  1689. X    for (ep = environ; *ep; ep++)
  1690. X        if (!strncmp(*ep,s,sl) && (*ep)[sl] == '=')
  1691. X            {
  1692. X            char *u = colonjoin(t);
  1693. X
  1694. X            replenv(*ep,u);
  1695. X            free(u);
  1696. X            break;
  1697. X            }
  1698. X}
  1699. X
  1700. Xchar *replenv(e,value) /**/
  1701. Xchar *e;char *value;
  1702. X{
  1703. Xchar **ep;
  1704. X
  1705. X    for (ep = environ; *ep; ep++)
  1706. X        if (*ep == e)
  1707. X            {
  1708. X            char *s = e;
  1709. X
  1710. X            while (*s++ != '=');
  1711. X            *s = '\0';
  1712. X            *ep = zalloc(strlen(e)+strlen(value)+2);
  1713. X            strcpy(*ep,e);
  1714. X            strcat(*ep,value);
  1715. X            free(e);
  1716. X            return *ep;
  1717. X            }
  1718. X    return NULL;
  1719. X}
  1720. X
  1721. Xchar *addenv(name,value) /**/
  1722. Xchar *name;char *value;
  1723. X{
  1724. Xchar **ep,**ep2,**ep3;
  1725. Xint envct;
  1726. X
  1727. X    for (ep = environ; *ep; ep++)
  1728. X        {
  1729. X        char *s = *ep,*t = name;
  1730. X
  1731. X        while (*s && *s == *t) s++,t++;
  1732. X        if (*s == '=' && !*t)
  1733. X            {
  1734. X            free(*ep);
  1735. X            return *ep = mkenvstr(name,value);
  1736. X            }
  1737. X        }
  1738. X    envct = arrlen(environ);
  1739. X    ep = ep2 = (char **) zalloc((sizeof (char *))*(envct+3));
  1740. X    for (ep3 = environ; *ep2 = *ep3; ep3++,ep2++);
  1741. X    *ep2 = mkenvstr(name,value);
  1742. X    ep2[1] = NULL;
  1743. X    free(environ);
  1744. X    environ = ep;
  1745. X    return *ep2;
  1746. X}
  1747. X
  1748. Xvoid delenv(x) /**/
  1749. Xchar *x;
  1750. X{
  1751. Xchar **ep;
  1752. X
  1753. X    ep = environ;
  1754. X    for (; *ep; ep++)
  1755. X        if (*ep == x)
  1756. X            break;
  1757. X    if (*ep)
  1758. X        for (; ep[0] = ep[1]; ep++);
  1759. X}
  1760. X
  1761. Xvoid convbase(s,v,base) /**/
  1762. Xchar *s;long v;int base;
  1763. X{
  1764. Xint digs = 0;
  1765. Xlong x;
  1766. X
  1767. X    if (base <= 1)
  1768. X        base = 10;
  1769. X    x = v;
  1770. X    if (x < 0)
  1771. X        {
  1772. X        x = -x;
  1773. X        digs++;
  1774. X        }
  1775. X    for (; x; digs++)
  1776. X        x /= base;
  1777. X    if (!digs)
  1778. X        digs = 1;
  1779. X    s[digs--] = '\0';
  1780. X    x = (v < 0) ? -v : v;
  1781. X    while (digs >= 0)
  1782. X        {
  1783. X        int dig = x%base;
  1784. X        s[digs--] = (dig < 10) ? '0'+dig : dig-10+'A';
  1785. X        x /= base;
  1786. X        }
  1787. X    if (v < 0)
  1788. X        s[0] = '-';
  1789. X}
  1790. X
  1791. X
  1792. SHAR_EOF
  1793. chmod 0644 zsh2.1/src/params.c ||
  1794. echo 'restore of zsh2.1/src/params.c failed'
  1795. Wc_c="`wc -c < 'zsh2.1/src/params.c'`"
  1796. test 24528 -eq "$Wc_c" ||
  1797.     echo 'zsh2.1/src/params.c: original size 24528, current size' "$Wc_c"
  1798. rm -f _shar_wnt_.tmp
  1799. fi
  1800. # ============= zsh2.1/src/subst.c ==============
  1801. if test -f 'zsh2.1/src/subst.c' -a X"$1" != X"-c"; then
  1802.     echo 'x - skipping zsh2.1/src/subst.c (File already exists)'
  1803.     rm -f _shar_wnt_.tmp
  1804. else
  1805. > _shar_wnt_.tmp
  1806. echo 'x - extracting zsh2.1/src/subst.c (Text)'
  1807. sed 's/^X//' << 'SHAR_EOF' > 'zsh2.1/src/subst.c' &&
  1808. X/*
  1809. X
  1810. X    subst.c - various substitutions
  1811. X
  1812. X    This file is part of zsh, the Z shell.
  1813. X
  1814. X    zsh is free software; no one can prevent you from reading the source
  1815. X   code, or giving it to someone else.
  1816. X
  1817. X   This file is copyrighted under the GNU General Public License, which
  1818. X   can be found in the file called COPYING.
  1819. X
  1820. X   Copyright (C) 1990, 1991 Paul Falstad
  1821. X
  1822. X   zsh is distributed in the hope that it will be useful, but
  1823. X   WITHOUT ANY WARRANTY.  No author or distributor accepts
  1824. X   responsibility to anyone for the consequences of using it or for
  1825. X   whether it serves any particular purpose or works at all, unless he
  1826. X   says so in writing.  Refer to the GNU General Public License
  1827. X   for full details.
  1828. X
  1829. X   Everyone is granted permission to copy, modify and redistribute
  1830. X   zsh, but only under the conditions described in the GNU General Public
  1831. X   License.   A copy of this license is supposed to have been given to you
  1832. X   along with zsh so you can know your rights and responsibilities.
  1833. X   It should be in a file named COPYING.
  1834. X
  1835. X   Among other things, the copyright notice and this notice must be
  1836. X   preserved on all copies.
  1837. X
  1838. X*/
  1839. X
  1840. X#include "zsh.h"
  1841. X#include <pwd.h>
  1842. X
  1843. X/* do substitutions before fork */
  1844. X
  1845. Xvoid prefork(list) /**/
  1846. XLklist list;
  1847. X{
  1848. XLknode node = firstnode(list);
  1849. Xint qt;
  1850. X
  1851. X    while (node)
  1852. X        {
  1853. X        char *str,*str3;
  1854. X        
  1855. X        str = str3 = getdata(node);
  1856. X        if (str[1] == Inpar && (*str == Inang ||
  1857. X                *str == Outang || *str == Equals))
  1858. X            {
  1859. X            if (*str == Inang)
  1860. X                setdata(node,getoutproc(str+2));        /* <(...) */
  1861. X            else if (*str == Equals)
  1862. X                setdata(node,getoutputfile(str+2));    /* =(...) */
  1863. X            else
  1864. X                setdata(node,getinproc(str+2));        /* >(...) */
  1865. X            if (!getdata(node))
  1866. X                {
  1867. X                zerr("parse error in process substitution",NULL,0);
  1868. X                return;
  1869. X                }
  1870. X            }
  1871. X        else while (*str)
  1872. X            {
  1873. X            if ((qt = *str == Qstring) || *str == String)
  1874. X                if (str[1] != Inpar)
  1875. X                    if (str[1] == Inbrack)
  1876. X                        {
  1877. X                        arithsubst((vptr*) &str,&str3);    /* $[...] */
  1878. X                        setdata(node,str3);
  1879. X                        }
  1880. X                    else
  1881. X                        {
  1882. X                        paramsubst(list,node,str,str3,qt);
  1883. X                        if (errflag)
  1884. X                            return;
  1885. X                        str3 = str = getdata(node);
  1886. X                        continue;
  1887. X                        }
  1888. X            str++;
  1889. X            if (errflag)
  1890. X                return;
  1891. X            }
  1892. X        if (*(char *) getdata(node))
  1893. X            remnulargs(getdata(node));
  1894. X        if (unset(IGNOREBRACES))
  1895. X            while (hasbraces(getdata(node)))
  1896. X                xpandbraces(list,&node);
  1897. X        filesub((char **) getaddrdata(node));
  1898. X        if (errflag)
  1899. X            return;
  1900. X        incnode(node);
  1901. X        }
  1902. X}
  1903. X
  1904. Xvoid postfork(list,doglob) /**/
  1905. XLklist list;int doglob;
  1906. X{
  1907. XLknode node = firstnode(list);
  1908. Xint glb = 1;
  1909. X
  1910. X    badcshglob = 0;
  1911. X    if (isset(NOGLOBOPT) || !doglob)
  1912. X        glb = 0;
  1913. X    while (node)
  1914. X        {
  1915. X        char *str3,*str;
  1916. X        
  1917. X        str = str3 = getdata(node);
  1918. X        while (*str)
  1919. X            {
  1920. X            if (((*str == String || *str == Qstring) && str[1] == Inpar) ||
  1921. X                    *str == Tick || *str == Qtick)
  1922. X                {
  1923. X                Lknode n = prevnode(node);
  1924. X
  1925. X                commsubst(list,node,str,str3,
  1926. X                    (*str == Qstring || *str == Qtick));    /* `...`,$(...) */
  1927. X                if (errflag)
  1928. X                    return;
  1929. X                str = str3 = getdata(node = nextnode(n));
  1930. X                }
  1931. X            str++;
  1932. X            }
  1933. X        if (glb)
  1934. X            {
  1935. X            if (haswilds(getdata(node)))
  1936. X                glob(list,&node);
  1937. X            if (errflag)
  1938. X                return;
  1939. X            }
  1940. X        incnode(node);
  1941. X        }
  1942. X    if (badcshglob == 1) zerr("no match",NULL,0);
  1943. X}
  1944. X
  1945. X/* perform substitution on a single word */
  1946. X
  1947. Xvoid singsub(s) /**/
  1948. Xchar **s;
  1949. X{
  1950. XLklist foo;
  1951. Xchar *t;
  1952. X
  1953. X    for (t = *s; *t; t++)
  1954. X        if (*t == String)
  1955. X            *t = Qstring;
  1956. X        else if (*t == Tick)
  1957. X            *t = Qtick;
  1958. X    foo = newlist();
  1959. X    addnode(foo,*s);
  1960. X    prefork(foo);
  1961. X    if (errflag)
  1962. X        return;
  1963. X    postfork(foo,0);
  1964. X    if (errflag)
  1965. X        return;
  1966. X    *s = ugetnode(foo);
  1967. X    if (firstnode(foo))
  1968. X        zerr("ambiguous: %s",*s,0);
  1969. X}
  1970. X
  1971. X/* strdup, but returns "Nularg" if this is a null string */
  1972. X
  1973. Xvptr nstrdup(s) /**/
  1974. Xvptr s;
  1975. X{
  1976. Xchar *t = s;
  1977. Xchar u[2];
  1978. X
  1979. X    u[0] = Nularg; u[1] = '\0';
  1980. X    if (!*t)
  1981. X        return strdup(u);
  1982. X    return strdup(t);
  1983. X}
  1984. X
  1985. Xchar *dynread(stop) /**/
  1986. Xint stop;
  1987. X{
  1988. Xint bsiz = 256,ct = 0,c;
  1989. Xchar *buf = zalloc(bsiz),*ptr;
  1990. X    ptr = buf;
  1991. X    while ((c = hgetc()) != stop)
  1992. X        {
  1993. X        *ptr++ = c;
  1994. X        if (++ct == bsiz)
  1995. X            {
  1996. X            buf = realloc(buf,bsiz *= 2);
  1997. X            ptr = buf+ct;
  1998. X            }
  1999. X        }
  2000. X    *ptr = 0;
  2001. X    return buf;
  2002. X}
  2003. X
  2004. Xint filesub(namptr) /**/
  2005. Xchar **namptr;
  2006. X{
  2007. Xchar *str = *namptr,*cnam;
  2008. X
  2009. X    if (*str == Tilde && str[1] != '=')
  2010. X        {
  2011. X        if (str[1] == '+' && (str[2] == '/' || str[2] == '\0'))
  2012. X            {
  2013. X            char *foo = strdup(cwd);    /* ~+ */
  2014. X
  2015. X            str+=2;
  2016. X            modify(&foo,&str);
  2017. X            *namptr = dyncat(cwd,str);
  2018. X            return 1;
  2019. X            }
  2020. X        else if (str[1] == '-' && (str[2] == '/' || str[2] == '\0'))
  2021. X            {
  2022. X            char *foo;                /* ~- */
  2023. X
  2024. X            if (cnam = oldpwd)
  2025. X                foo = cnam;
  2026. X            else
  2027. X                foo = cwd;
  2028. X            str += 2;
  2029. X            foo = strdup(foo);
  2030. X            modify(&foo,&str);
  2031. X            *namptr = dyncat(foo,str);
  2032. X            return 1;
  2033. X            }
  2034. X        if (ialpha(str[1]))        /* ~foo */
  2035. X            {
  2036. X            char *ptr,*hom;
  2037. X            for (ptr = ++str; *ptr && iuser(*ptr); ptr++)
  2038. X                if (*ptr == '-')
  2039. X                    *ptr = '-';
  2040. X            if (*ptr && *ptr != '/') return 0;
  2041. X            if (!(hom = gethome(str,ptr-str)))
  2042. X                {
  2043. X                zerr("user not found: %l",str,ptr-str);
  2044. X                errflag = 1;
  2045. X                return 0;
  2046. X                }
  2047. X            modify(&hom,&ptr);
  2048. X            *namptr = dyncat(hom,ptr);
  2049. X            return 1;
  2050. X            }
  2051. X        else if (str[1] == '/')    /* ~/foo */
  2052. X            {
  2053. X            *namptr = dyncat(home,str+1);
  2054. X            return 1;
  2055. X            }
  2056. X        else if (!str[1])        /* ~ by itself */
  2057. X            {
  2058. X            *namptr = strdup(home);
  2059. X            return 1;
  2060. X            }
  2061. X        }
  2062. X    if (*str == Equals && iuser(str[1]) && unset(NOEQUALS))
  2063. X        {
  2064. X        char *ptr,*s,*ds;
  2065. X        int val;
  2066. X        
  2067. X        if (ialpha(str[1]))        /* =foo */
  2068. X            {
  2069. X            char sav,*pp;
  2070. X            for (pp = str+1; *pp && *pp != ':'; pp++);
  2071. X            sav = *pp;
  2072. X            *pp = '\0';
  2073. X            if (!(cnam = findcmd(str+1)))
  2074. X                {
  2075. X                zerr("%s not found",str+1,0);
  2076. X                errflag = 1;
  2077. X                return 0;
  2078. X                }
  2079. X            *namptr = cnam;
  2080. X            if ((*pp = sav) == ':')
  2081. X                {
  2082. X                modify(namptr,&pp);
  2083. X                s = *namptr;
  2084. X                *namptr = dyncat(*namptr,pp);
  2085. X                }
  2086. X            return 1;
  2087. X            }
  2088. X        if (str[1] == '-')     /* =- */
  2089. X            {
  2090. X            val = -1;
  2091. X            ptr = str+2;
  2092. X            }
  2093. X        else
  2094. X            val = zstrtol(str+1,&ptr,10);    /* =# */
  2095. X        ds = dstackent(val);
  2096. X        if (!ds)
  2097. X            return 1;
  2098. X        s = strdup(ds);
  2099. X        modify(&s,&ptr);
  2100. X        *namptr = dyncat(s,ptr);
  2101. X        return 1;
  2102. X        }
  2103. X    return 0;
  2104. X}
  2105. X
  2106. X/* get a named directory */
  2107. X
  2108. Xchar *gethome(user,len) /**/
  2109. Xchar *user;int len;
  2110. X{
  2111. Xchar sav,*str;
  2112. Xstruct passwd *pw;
  2113. X    if (len == 0)
  2114. X        return strdup(home);
  2115. X    sav = user[len];
  2116. X    user[len] = '\0';
  2117. X    if ((str = getsparamval(user,len)) && *str == '/')
  2118. X        {
  2119. X        str = strdup(str);
  2120. X        adduserdir(user,str);
  2121. X        user[len] = sav;
  2122. X        return str;
  2123. X        }
  2124. X    if (!(pw = getpwnam(user))) {
  2125. X        user[len] = sav;
  2126. X        return NULL;
  2127. X    }
  2128. X    str = xsymlink(pw->pw_dir);
  2129. X    adduserdir(user,str);
  2130. X    user[len] = sav;
  2131. X    return str;
  2132. X}
  2133. X
  2134. X/* `...`, $(...) */
  2135. X
  2136. Xvoid commsubst(l,n,str3,str,qt) /**/
  2137. XLklist l;Lknode n;char *str3;char *str;int qt;
  2138. X{
  2139. Xchar *str2;
  2140. XLknode where = prevnode(n);
  2141. XLklist pl;
  2142. X
  2143. X    if (*str3 == Tick || *str3 == Qtick)
  2144. X        {
  2145. X        *str3 = '\0';
  2146. X        for (str2 = ++str3; *str3 != Tick && *str3 != Qtick; str3++);
  2147. X        *str3++ = '\0';
  2148. X        }
  2149. X    else
  2150. X        {
  2151. X        *str3++ = '\0';
  2152. X        for (str2 = ++str3; *str3 != Outpar; str3++);
  2153. X        *str3++ = '\0';
  2154. X        }
  2155. X    uremnode(l,n);
  2156. X    if (!(pl = getoutput(str2,qt)))
  2157. X        {
  2158. X        zerr("parse error in command substitution",NULL,0);
  2159. X        errflag = 1;
  2160. X        return;
  2161. X        }
  2162. X    if (full(pl))
  2163. X        {
  2164. X        setdata(firstnode(pl),dyncat(str,peekfirst(pl)));
  2165. X        setdata(lastnode(pl),dyncat(getdata(lastnode(pl)),str3));
  2166. X        inslist(pl,where,l);
  2167. X        }
  2168. X    else
  2169. X        insnode(l,where,dyncat(str,str3));
  2170. X}
  2171. X
  2172. X/* parameter substitution */
  2173. X
  2174. Xvoid paramsubst(l,n,aptr,bptr,qt) /**/
  2175. XLklist l;Lknode n;char *aptr;char *bptr;int qt;
  2176. X{
  2177. Xchar *s = aptr,*u,*idbeg,*idend,*ostr = bptr;
  2178. Xint brs;            /* != 0 means ${...}, otherwise $... */
  2179. Xint colf;        /* != 0 means we found a colon after the name */
  2180. Xint doub = 0;    /* != 0 means we have %%, not %, or ##, not # */
  2181. Xint isarr = 0;
  2182. Xint wasnularr = 0;
  2183. Xint plan9 = isset(RCEXPANDPARAM);
  2184. Xint getlen = 0;
  2185. Xint vunset = 0;
  2186. Xint spbreak = isset(SHWORDSPLIT) && !qt;
  2187. Xchar *val = NULL,**aval = NULL;
  2188. Xint fwidth = 0;
  2189. XValue v;
  2190. X
  2191. X    *s++ = '\0';
  2192. X    if (!ialnum(*s) && *s != '#' && *s != Pound && *s != '-' &&
  2193. X            *s != '!' && *s != '$' && *s != String && *s != Qstring &&
  2194. X            *s != '?' && *s != Quest && *s != '_' &&
  2195. X            *s != '*' && *s != Star && *s != '@' && *s != '{' &&
  2196. X            *s != Inbrace && *s != '=' && *s != Hat && *s != '^')
  2197. X        {
  2198. X        s[-1] = '$';
  2199. X        return;
  2200. X        }
  2201. X    if (brs = (*s == '{' || *s == Inbrace))
  2202. X        s++;
  2203. X    for (;;)
  2204. X        if (*s == '^' || *s == Hat)
  2205. X            plan9 ^= 1,s++;
  2206. X        else if (*s == '=')
  2207. X            spbreak ^= 1,s++;
  2208. X        else if ((*s == '#' || *s == Pound) && iident(s[1]))
  2209. X            getlen = 1,s++;
  2210. X        else
  2211. X            break;
  2212. X
  2213. X    idbeg = s;
  2214. X    if (!(v = getvalue(&s,1)))
  2215. X        {
  2216. X        vunset = 1;
  2217. X        idend = s;
  2218. X        }
  2219. X    else
  2220. X        if (isarr = v->isarr)
  2221. X            aval = getarrvalue(v);
  2222. X        else
  2223. X            {
  2224. X            val = getstrvalue(v);
  2225. X            fwidth = v->pm->ct;
  2226. X            switch (v->pm->flags & (PMFLAG_L | PMFLAG_R | PMFLAG_Z))
  2227. X                {
  2228. X                char *t;
  2229. X                int t0;
  2230. X
  2231. X                case PMFLAG_L:
  2232. X                case PMFLAG_L|PMFLAG_Z:
  2233. X                    t = val;
  2234. X                    if (v->pm->flags & PMFLAG_Z)
  2235. X                        while (*t == '0') t++;
  2236. X                    else
  2237. X                        while (isep(*t)) t++;
  2238. X                    val = ncalloc(fwidth+1);
  2239. X                    val[fwidth] = '\0';
  2240. X                    if ((t0 = strlen(t)) > fwidth)
  2241. X                        t0 = fwidth;
  2242. X                    memset(val,' ',fwidth);
  2243. X                    strncpy(val,t,t0);
  2244. X                    break;
  2245. X                case PMFLAG_R:
  2246. X                case PMFLAG_Z:
  2247. X                case PMFLAG_Z|PMFLAG_R:
  2248. X                    if (strlen(val) < fwidth) {
  2249. X                        t = ncalloc(fwidth+1);
  2250. X                        memset(t,(v->pm->flags & PMFLAG_R) ? ' ' : '0',fwidth);
  2251. X                        if ((t0 = strlen(val)) > fwidth)
  2252. X                            t0 = fwidth;
  2253. X                        strcpy(t+(fwidth-t0),val);
  2254. X                        val = t;
  2255. X                    } else {
  2256. X                        t = ncalloc(fwidth+1);
  2257. X                        t[fwidth] = '\0';
  2258. X                        strncpy(t,val+strlen(val)-fwidth,fwidth);
  2259. X                        val = t;
  2260. X                    }
  2261. X                    break;
  2262. X                }
  2263. X            switch (v->pm->flags & (PMFLAG_l | PMFLAG_u))
  2264. X                {
  2265. X                char *t;
  2266. X
  2267. X                case PMFLAG_l:
  2268. X                    t = val;
  2269. X                    for (;*t;t++)
  2270. X                        *t = tulower(*t);
  2271. X                    break;
  2272. X                case PMFLAG_u:
  2273. X                    t = val;
  2274. X                    for (;*t;t++)
  2275. X                        *t = tuupper(*t);
  2276. X                    break;
  2277. X                }
  2278. X            }
  2279. X    if (colf = *s == ':')
  2280. X        s++;
  2281. X    
  2282. X    /* check for ${..?...} or ${..=..} or one of those.  Only works
  2283. X        if the name is in braces. */
  2284. X
  2285. X    if (brs && (*s == '-' || *s == '=' || *s == '?' || *s == '+' || *s == '#' ||
  2286. X            *s == '%' || *s == Quest || *s == Pound))
  2287. X        {
  2288. X        if (v && v->isarr && (*s == '%' || *s == '#' || *s == Pound))
  2289. X            {
  2290. X            zerr("operator requires a scalar",NULL,0);
  2291. X            return;
  2292. X            }
  2293. X        if (*s == s[1])
  2294. X            {
  2295. X            s++;
  2296. X            doub = 1;
  2297. X            }
  2298. X        u = ++s;
  2299. X        if (brs)
  2300. X            {
  2301. X            int bct = 1;
  2302. X
  2303. X            for (;;)
  2304. X                {
  2305. X                if (*s == '{' || *s == Inbrace)
  2306. X                    bct++;
  2307. X                else if (*s == '}' || *s == Outbrace)
  2308. X                    bct--;
  2309. X                if (!bct || !*s)
  2310. X                    break;
  2311. X                s++;
  2312. X                }
  2313. X            }
  2314. X        else
  2315. X            {
  2316. X            while (*s++);
  2317. X            s--;
  2318. X            }
  2319. X        *s++ = '\0';
  2320. X        if (colf && !vunset)
  2321. X            vunset = (isarr) ? !*aval : !*val;
  2322. X        switch (u[-1])
  2323. X            {
  2324. X            case '-':
  2325. X                if (vunset)
  2326. X                    val = strdup(u), isarr = 0;
  2327. X                break;
  2328. X            case '=':
  2329. X                if (vunset)
  2330. X                    {
  2331. X                    char sav = *idend;
  2332. X
  2333. X                    *idend = '\0';
  2334. X                    setsparam(idbeg,ztrdup(val = strdup(u)));
  2335. X                    *idend = sav;
  2336. X                    isarr = 0;
  2337. X                    }
  2338. X                break;
  2339. X            case '?':
  2340. X            case Quest:
  2341. X                if (vunset)
  2342. X                    {
  2343. X                    zerr("%s",(*u) ? u : "parameter not set",0);
  2344. X                    if (!interact)
  2345. X                        exit(1);
  2346. X                    return;
  2347. X                    }
  2348. X                break;
  2349. X            case '+':
  2350. X                if (vunset)
  2351. X                    val = strdup("");
  2352. X                else
  2353. X                    val = strdup(u);
  2354. X                isarr = 0;
  2355. X                break;
  2356. X            case '#':
  2357. X            case Pound:
  2358. X                if (vunset)
  2359. X                    val = strdup("");
  2360. X                singsub(&u);
  2361. X                getmatch(&val,u,doub);
  2362. X                break;
  2363. X            case '%':
  2364. X                if (vunset)
  2365. X                    val = strdup("");
  2366. X                singsub(&u);
  2367. X                getmatch(&val,u,doub+2);
  2368. X                break;
  2369. X            }
  2370. X        }
  2371. X    else        /* no ${...=...} or anything, but possible modifiers. */
  2372. X        {
  2373. X        if (vunset)
  2374. X            {
  2375. X            if (isset(NOUNSET))
  2376. X                {
  2377. X                zerr("parameter not set",NULL,0);
  2378. X                return;
  2379. X                }
  2380. X            val = strdup("");
  2381. X            }
  2382. X        if (colf)
  2383. X            {
  2384. X            s--;
  2385. X            if (!isarr)
  2386. X                modify(&val,&s);
  2387. X            /*else
  2388. X                modifyarr(&aval,&s);*/
  2389. X            }
  2390. X        if (brs)
  2391. X            {
  2392. X            if (*s != '}' && *s != Outbrace)
  2393. X                {
  2394. X                zerr("closing brace expected",NULL,0);
  2395. X                errflag = 1;
  2396. X                return;
  2397. X                }
  2398. X            s++;
  2399. X            }
  2400. X        }
  2401. X    if (errflag)
  2402. X        return;
  2403. X    if (getlen)
  2404. X        {
  2405. X        long len = 0;
  2406. X        char buf[14];
  2407. X
  2408. X        if (isarr)
  2409. X            {
  2410. X            char **ctr;
  2411. X            for (ctr = aval; *ctr; ctr++,len++);
  2412. X            }
  2413. X        else
  2414. X            len = strlen(val);
  2415. X        sprintf(buf,"%ld",len);
  2416. X        val = strdup(buf);
  2417. X        isarr = 0;
  2418. X        }
  2419. X    if (isarr)
  2420. X        if (!aval || !aval[0])
  2421. X            {
  2422. X            if (isarr < 0)
  2423. X                wasnularr = 1;
  2424. X            val = strdup("");
  2425. X            isarr = 0;
  2426. X            }
  2427. X        else if (!aval[1])
  2428. X            {
  2429. X            val = aval[0];
  2430. X            isarr = 0;
  2431. X            }
  2432. X    if (qt)
  2433. X        {
  2434. X        if (isarr > 0)
  2435. X            {
  2436. X            val = spacejoin(aval);
  2437. X            isarr = 0;
  2438. X            }
  2439. X        }
  2440. X    else if (spbreak)
  2441. X        {
  2442. X        if (isarr)
  2443. X            val = spacejoin(aval);
  2444. X        isarr = 1;
  2445. X        aval = spacesplit(val);
  2446. X        if (!aval || !aval[0])
  2447. X            {
  2448. X            val = strdup("");
  2449. X            isarr = 0;
  2450. X            }
  2451. X        else if (!aval[1])
  2452. X            {
  2453. X            val = aval[0];
  2454. X            isarr = 0;
  2455. X            }
  2456. X        /* if only one member, not really an array */
  2457. X        if (!aval[1])
  2458. X            isarr = 0;
  2459. X        }
  2460. SHAR_EOF
  2461. true || echo 'restore of zsh2.1/src/subst.c failed'
  2462. fi
  2463. echo 'End of zsh2.1.0 part 9'
  2464. echo 'File zsh2.1/src/subst.c is continued in part 10'
  2465. echo 10 > _shar_seq_.tmp
  2466. exit 0
  2467.  
  2468. exit 0 # Just in case...
  2469. -- 
  2470. Kent Landfield                   INTERNET: kent@sparky.IMD.Sterling.COM
  2471. Sterling Software, IMD           UUCP:     uunet!sparky!kent
  2472. Phone:    (402) 291-8300         FAX:      (402) 291-4362
  2473. Please send comp.sources.misc-related mail to kent@uunet.uu.net.
  2474.