home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume18 / perl / part09 < prev    next >
Internet Message Format  |  1991-04-15  |  52KB

  1. From: lwall@netlabs.com (Larry Wall)
  2. Newsgroups: comp.sources.misc
  3. Subject: v18i027:  perl - The perl programming language, Part09/36
  4. Message-ID: <1991Apr15.235945.22666@sparky.IMD.Sterling.COM>
  5. Date: 15 Apr 91 23:59:45 GMT
  6. Approved: kent@sparky.imd.sterling.com
  7. X-Checksum-Snefru: b7845ef9 09a23c7b 1cb933c8 ff1ba6f3
  8.  
  9. Submitted-by: Larry Wall <lwall@netlabs.com>
  10. Posting-number: Volume 18, Issue 27
  11. Archive-name: perl/part09
  12.  
  13. [There are 36 kits for perl version 4.0.]
  14.  
  15. #! /bin/sh
  16.  
  17. # Make a new directory for the perl sources, cd to it, and run kits 1
  18. # thru 36 through sh.  When all 36 kits have been run, read README.
  19.  
  20. echo "This is perl 4.0 kit 9 (of 36).  If kit 9 is complete, the line"
  21. echo '"'"End of kit 9 (of 36)"'" will echo at the end.'
  22. echo ""
  23. export PATH || (echo "You didn't use sh, you clunch." ; kill $$)
  24. mkdir x2p 2>/dev/null
  25. echo Extracting x2p/walk.c
  26. sed >x2p/walk.c <<'!STUFFY!FUNK!' -e 's/X//'
  27. X/* $Header: walk.c,v 4.0 91/03/20 01:58:36 lwall Locked $
  28. X *
  29. X *    Copyright (c) 1989, Larry Wall
  30. X *
  31. X *    You may distribute under the terms of the GNU General Public License
  32. X *    as specified in the README file that comes with the perl 3.0 kit.
  33. X *
  34. X * $Log:    walk.c,v $
  35. X * Revision 4.0  91/03/20  01:58:36  lwall
  36. X * 4.0 baseline.
  37. X * 
  38. X */
  39. X
  40. X#include "handy.h"
  41. X#include "EXTERN.h"
  42. X#include "util.h"
  43. X#include "a2p.h"
  44. X
  45. Xbool exitval = FALSE;
  46. Xbool realexit = FALSE;
  47. Xbool saw_getline = FALSE;
  48. Xbool subretnum = FALSE;
  49. Xbool saw_FNR = FALSE;
  50. Xbool saw_argv0 = FALSE;
  51. Xint maxtmp = 0;
  52. Xchar *lparen;
  53. Xchar *rparen;
  54. XSTR *subs;
  55. XSTR *curargs = Nullstr;
  56. X
  57. XSTR *
  58. Xwalk(useval,level,node,numericptr,minprec)
  59. Xint useval;
  60. Xint level;
  61. Xregister int node;
  62. Xint *numericptr;
  63. Xint minprec;            /* minimum precedence without parens */
  64. X{
  65. X    register int len;
  66. X    register STR *str;
  67. X    register int type;
  68. X    register int i;
  69. X    register STR *tmpstr;
  70. X    STR *tmp2str;
  71. X    STR *tmp3str;
  72. X    char *t;
  73. X    char *d, *s;
  74. X    int numarg;
  75. X    int numeric = FALSE;
  76. X    STR *fstr;
  77. X    int prec = P_MAX;        /* assume no parens needed */
  78. X    char *index();
  79. X
  80. X    if (!node) {
  81. X    *numericptr = 0;
  82. X    return str_make("");
  83. X    }
  84. X    type = ops[node].ival;
  85. X    len = type >> 8;
  86. X    type &= 255;
  87. X    switch (type) {
  88. X    case OPROG:
  89. X    opens = str_new(0);
  90. X    subs = str_new(0);
  91. X    str = walk(0,level,ops[node+1].ival,&numarg,P_MIN);
  92. X    if (do_split && need_entire && !absmaxfld)
  93. X        split_to_array = TRUE;
  94. X    if (do_split && split_to_array)
  95. X        set_array_base = TRUE;
  96. X    if (set_array_base) {
  97. X        str_cat(str,"$[ = 1;\t\t\t# set array base to 1\n");
  98. X    }
  99. X    if (fswitch && !const_FS)
  100. X        const_FS = fswitch;
  101. X    if (saw_FS > 1 || saw_RS)
  102. X        const_FS = 0;
  103. X    if (saw_ORS && need_entire)
  104. X        do_chop = TRUE;
  105. X    if (fswitch) {
  106. X        str_cat(str,"$FS = '");
  107. X        if (index("*+?.[]()|^$\\",fswitch))
  108. X        str_cat(str,"\\");
  109. X        sprintf(tokenbuf,"%c",fswitch);
  110. X        str_cat(str,tokenbuf);
  111. X        str_cat(str,"';\t\t# field separator from -F switch\n");
  112. X    }
  113. X    else if (saw_FS && !const_FS) {
  114. X        str_cat(str,"$FS = ' ';\t\t# set field separator\n");
  115. X    }
  116. X    if (saw_OFS) {
  117. X        str_cat(str,"$, = ' ';\t\t# set output field separator\n");
  118. X    }
  119. X    if (saw_ORS) {
  120. X        str_cat(str,"$\\ = \"\\n\";\t\t# set output record separator\n");
  121. X    }
  122. X    if (saw_argv0) {
  123. X        str_cat(str,"$ARGV0 = $0;\t\t# remember what we ran as\n");
  124. X    }
  125. X    if (str->str_cur > 20)
  126. X        str_cat(str,"\n");
  127. X    if (ops[node+2].ival) {
  128. X        str_scat(str,fstr=walk(0,level,ops[node+2].ival,&numarg,P_MIN));
  129. X        str_free(fstr);
  130. X        str_cat(str,"\n\n");
  131. X    }
  132. X    fstr = walk(0,level+1,ops[node+3].ival,&numarg,P_MIN);
  133. X    if (*fstr->str_ptr) {
  134. X        if (saw_line_op)
  135. X        str_cat(str,"line: ");
  136. X        str_cat(str,"while (<>) {\n");
  137. X        tab(str,++level);
  138. X        if (saw_FS && !const_FS)
  139. X        do_chop = TRUE;
  140. X        if (do_chop) {
  141. X        str_cat(str,"chop;\t# strip record separator\n");
  142. X        tab(str,level);
  143. X        }
  144. X        arymax = 0;
  145. X        if (namelist) {
  146. X        while (isalpha(*namelist)) {
  147. X            for (d = tokenbuf,s=namelist;
  148. X              isalpha(*s) || isdigit(*s) || *s == '_';
  149. X              *d++ = *s++) ;
  150. X            *d = '\0';
  151. X            while (*s && !isalpha(*s)) s++;
  152. X            namelist = s;
  153. X            nameary[++arymax] = savestr(tokenbuf);
  154. X        }
  155. X        }
  156. X        if (maxfld < arymax)
  157. X        maxfld = arymax;
  158. X        if (do_split)
  159. X        emit_split(str,level);
  160. X        str_scat(str,fstr);
  161. X        str_free(fstr);
  162. X        fixtab(str,--level);
  163. X        str_cat(str,"}\n");
  164. X        if (saw_FNR)
  165. X        str_cat(str,"continue {\n    $FNRbase = $. if eof;\n}\n");
  166. X    }
  167. X    else
  168. X        str_cat(str,"while (<>) { }        # (no line actions)\n");
  169. X    if (ops[node+4].ival) {
  170. X        realexit = TRUE;
  171. X        str_cat(str,"\n");
  172. X        tab(str,level);
  173. X        str_scat(str,fstr=walk(0,level,ops[node+4].ival,&numarg,P_MIN));
  174. X        str_free(fstr);
  175. X        str_cat(str,"\n");
  176. X    }
  177. X    if (exitval)
  178. X        str_cat(str,"exit $ExitValue;\n");
  179. X    if (subs->str_ptr) {
  180. X        str_cat(str,"\n");
  181. X        str_scat(str,subs);
  182. X    }
  183. X    if (saw_getline) {
  184. X        for (len = 0; len < 4; len++) {
  185. X        if (saw_getline & (1 << len)) {
  186. X            sprintf(tokenbuf,"\nsub Getline%d {\n",len);
  187. X            str_cat(str, tokenbuf);
  188. X            if (len & 2) {
  189. X            if (do_fancy_opens)
  190. X                str_cat(str,"    &Pick('',@_);\n");
  191. X            else
  192. X                str_cat(str,"    ($fh) = @_;\n");
  193. X            }
  194. X            else {
  195. X            if (saw_FNR)
  196. X                str_cat(str,"    $FNRbase = $. if eof;\n");
  197. X            }
  198. X            if (len & 1)
  199. X            str_cat(str,"    local($_);\n");
  200. X            if (len & 2)
  201. X            str_cat(str,
  202. X              "    if ($getline_ok = (($_ = <$fh>) ne ''))");
  203. X            else
  204. X            str_cat(str,
  205. X              "    if ($getline_ok = (($_ = <>) ne ''))");
  206. X            str_cat(str, " {\n");
  207. X            level += 2;
  208. X            tab(str,level);
  209. X            i = 0;
  210. X            if (do_chop) {
  211. X            i++;
  212. X            str_cat(str,"chop;\t# strip record separator\n");
  213. X            tab(str,level);
  214. X            }
  215. X            if (do_split && !(len & 1)) {
  216. X            i++;
  217. X            emit_split(str,level);
  218. X            }
  219. X            if (!i)
  220. X            str_cat(str,";\n");
  221. X            fixtab(str,--level);
  222. X            str_cat(str,"}\n    $_;\n}\n");
  223. X            --level;
  224. X        }
  225. X        }
  226. X    }
  227. X    if (do_fancy_opens) {
  228. X        str_cat(str,"\n\
  229. Xsub Pick {\n\
  230. X    local($mode,$name,$pipe) = @_;\n\
  231. X    $fh = $opened{$name};\n\
  232. X    if (!$fh) {\n\
  233. X    $fh = $opened{$name} = 'fh_' . ($nextfh++ + 0);\n\
  234. X    open($fh,$mode.$name.$pipe);\n\
  235. X    }\n\
  236. X}\n\
  237. X");
  238. X    }
  239. X    break;
  240. X    case OHUNKS:
  241. X    str = walk(0,level,ops[node+1].ival,&numarg,P_MIN);
  242. X    str_scat(str,fstr=walk(0,level,ops[node+2].ival,&numarg,P_MIN));
  243. X    str_free(fstr);
  244. X    if (len == 3) {
  245. X        str_scat(str,fstr=walk(0,level,ops[node+3].ival,&numarg,P_MIN));
  246. X        str_free(fstr);
  247. X    }
  248. X    else {
  249. X    }
  250. X    break;
  251. X    case ORANGE:
  252. X    prec = P_DOTDOT;
  253. X    str = walk(1,level,ops[node+1].ival,&numarg,prec+1);
  254. X    str_cat(str," .. ");
  255. X    str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg,prec+1));
  256. X    str_free(fstr);
  257. X    break;
  258. X    case OPAT:
  259. X    goto def;
  260. X    case OREGEX:
  261. X    str = str_new(0);
  262. X    str_set(str,"/");
  263. X    tmpstr=walk(0,level,ops[node+1].ival,&numarg,P_MIN);
  264. X    /* translate \nnn to [\nnn] */
  265. X    for (s = tmpstr->str_ptr, d = tokenbuf; *s; s++, d++) {
  266. X        if (*s == '\\' && isdigit(s[1]) && isdigit(s[2]) && isdigit(s[3])){
  267. X        *d++ = '[';
  268. X        *d++ = *s++;
  269. X        *d++ = *s++;
  270. X        *d++ = *s++;
  271. X        *d++ = *s;
  272. X        *d = ']';
  273. X        }
  274. X        else
  275. X        *d = *s;
  276. X    }
  277. X    *d = '\0';
  278. X    for (d=tokenbuf; *d; d++)
  279. X        *d += 128;
  280. X    str_cat(str,tokenbuf);
  281. X    str_free(tmpstr);
  282. X    str_cat(str,"/");
  283. X    break;
  284. X    case OHUNK:
  285. X    if (len == 1) {
  286. X        str = str_new(0);
  287. X        str = walk(0,level,oper1(OPRINT,0),&numarg,P_MIN);
  288. X        str_cat(str," if ");
  289. X        str_scat(str,fstr=walk(0,level,ops[node+1].ival,&numarg,P_MIN));
  290. X        str_free(fstr);
  291. X        str_cat(str,";");
  292. X    }
  293. X    else {
  294. X        tmpstr = walk(0,level,ops[node+1].ival,&numarg,P_MIN);
  295. X        if (*tmpstr->str_ptr) {
  296. X        str = str_new(0);
  297. X        str_set(str,"if (");
  298. X        str_scat(str,tmpstr);
  299. X        str_cat(str,") {\n");
  300. X        tab(str,++level);
  301. X        str_scat(str,fstr=walk(0,level,ops[node+2].ival,&numarg,P_MIN));
  302. X        str_free(fstr);
  303. X        fixtab(str,--level);
  304. X        str_cat(str,"}\n");
  305. X        tab(str,level);
  306. X        }
  307. X        else {
  308. X        str = walk(0,level,ops[node+2].ival,&numarg,P_MIN);
  309. X        }
  310. X    }
  311. X    break;
  312. X    case OPPAREN:
  313. X    str = str_new(0);
  314. X    str_set(str,"(");
  315. X    str_scat(str,fstr=walk(useval != 0,level,ops[node+1].ival,&numarg,P_MIN));
  316. X    str_free(fstr);
  317. X    str_cat(str,")");
  318. X    break;
  319. X    case OPANDAND:
  320. X    prec = P_ANDAND;
  321. X    str = walk(1,level,ops[node+1].ival,&numarg,prec);
  322. X    str_cat(str," && ");
  323. X    str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg,prec+1));
  324. X    str_free(fstr);
  325. X    str_scat(str,fstr=walk(1,level,ops[node+3].ival,&numarg,prec+1));
  326. X    str_free(fstr);
  327. X    break;
  328. X    case OPOROR:
  329. X    prec = P_OROR;
  330. X    str = walk(1,level,ops[node+1].ival,&numarg,prec);
  331. X    str_cat(str," || ");
  332. X    str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg,prec+1));
  333. X    str_free(fstr);
  334. X    str_scat(str,fstr=walk(1,level,ops[node+3].ival,&numarg,prec+1));
  335. X    str_free(fstr);
  336. X    break;
  337. X    case OPNOT:
  338. X    prec = P_UNARY;
  339. X    str = str_new(0);
  340. X    str_set(str,"!");
  341. X    str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg,prec));
  342. X    str_free(fstr);
  343. X    break;
  344. X    case OCOND:
  345. X    prec = P_COND;
  346. X    str = walk(1,level,ops[node+1].ival,&numarg,prec);
  347. X    str_cat(str," ? ");
  348. X    str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg,prec+1));
  349. X    str_free(fstr);
  350. X    str_cat(str," : ");
  351. X    str_scat(str,fstr=walk(1,level,ops[node+3].ival,&numarg,prec+1));
  352. X    str_free(fstr);
  353. X    break;
  354. X    case OCPAREN:
  355. X    str = str_new(0);
  356. X    str_set(str,"(");
  357. X    str_scat(str,fstr=walk(useval != 0,level,ops[node+1].ival,&numarg,P_MIN));
  358. X    str_free(fstr);
  359. X    numeric |= numarg;
  360. X    str_cat(str,")");
  361. X    break;
  362. X    case OCANDAND:
  363. X    prec = P_ANDAND;
  364. X    str = walk(1,level,ops[node+1].ival,&numarg,prec);
  365. X    numeric = 1;
  366. X    str_cat(str," && ");
  367. X    str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg,prec+1));
  368. X    str_free(fstr);
  369. X    str_scat(str,fstr=walk(1,level,ops[node+3].ival,&numarg,prec+1));
  370. X    str_free(fstr);
  371. X    break;
  372. X    case OCOROR:
  373. X    prec = P_OROR;
  374. X    str = walk(1,level,ops[node+1].ival,&numarg,prec);
  375. X    numeric = 1;
  376. X    str_cat(str," || ");
  377. X    str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg,prec+1));
  378. X    str_free(fstr);
  379. X    str_scat(str,fstr=walk(1,level,ops[node+3].ival,&numarg,prec+1));
  380. X    str_free(fstr);
  381. X    break;
  382. X    case OCNOT:
  383. X    prec = P_UNARY;
  384. X    str = str_new(0);
  385. X    str_set(str,"!");
  386. X    str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg,prec));
  387. X    str_free(fstr);
  388. X    numeric = 1;
  389. X    break;
  390. X    case ORELOP:
  391. X    prec = P_REL;
  392. X    str = walk(1,level,ops[node+2].ival,&numarg,prec+1);
  393. X    numeric |= numarg;
  394. X    tmpstr = walk(0,level,ops[node+1].ival,&numarg,P_MIN);
  395. X    tmp2str = walk(1,level,ops[node+3].ival,&numarg,prec+1);
  396. X    numeric |= numarg;
  397. X    if (!numeric ||
  398. X     (!numarg && (*tmp2str->str_ptr == '"' || *tmp2str->str_ptr == '\''))) {
  399. X        t = tmpstr->str_ptr;
  400. X        if (strEQ(t,"=="))
  401. X        str_set(tmpstr,"eq");
  402. X        else if (strEQ(t,"!="))
  403. X        str_set(tmpstr,"ne");
  404. X        else if (strEQ(t,"<"))
  405. X        str_set(tmpstr,"lt");
  406. X        else if (strEQ(t,"<="))
  407. X        str_set(tmpstr,"le");
  408. X        else if (strEQ(t,">"))
  409. X        str_set(tmpstr,"gt");
  410. X        else if (strEQ(t,">="))
  411. X        str_set(tmpstr,"ge");
  412. X        if (!index(tmpstr->str_ptr,'\'') && !index(tmpstr->str_ptr,'"') &&
  413. X          !index(tmp2str->str_ptr,'\'') && !index(tmp2str->str_ptr,'"') )
  414. X        numeric |= 2;
  415. X    }
  416. X    if (numeric & 2) {
  417. X        if (numeric & 1)        /* numeric is very good guess */
  418. X        str_cat(str," ");
  419. X        else
  420. X        str_cat(str,"\377");
  421. X        numeric = 1;
  422. X    }
  423. X    else
  424. X        str_cat(str," ");
  425. X    str_scat(str,tmpstr);
  426. X    str_free(tmpstr);
  427. X    str_cat(str," ");
  428. X    str_scat(str,tmp2str);
  429. X    str_free(tmp2str);
  430. X    numeric = 1;
  431. X    break;
  432. X    case ORPAREN:
  433. X    str = str_new(0);
  434. X    str_set(str,"(");
  435. X    str_scat(str,fstr=walk(useval != 0,level,ops[node+1].ival,&numarg,P_MIN));
  436. X    str_free(fstr);
  437. X    numeric |= numarg;
  438. X    str_cat(str,")");
  439. X    break;
  440. X    case OMATCHOP:
  441. X    prec = P_MATCH;
  442. X    str = walk(1,level,ops[node+2].ival,&numarg,prec+1);
  443. X    str_cat(str," ");
  444. X    tmpstr = walk(0,level,ops[node+1].ival,&numarg,P_MIN);
  445. X    if (strEQ(tmpstr->str_ptr,"~"))
  446. X        str_cat(str,"=~");
  447. X    else {
  448. X        str_scat(str,tmpstr);
  449. X        str_free(tmpstr);
  450. X    }
  451. X    str_cat(str," ");
  452. X    str_scat(str,fstr=walk(1,level,ops[node+3].ival,&numarg,prec+1));
  453. X    str_free(fstr);
  454. X    numeric = 1;
  455. X    break;
  456. X    case OMPAREN:
  457. X    str = str_new(0);
  458. X    str_set(str,"(");
  459. X    str_scat(str,
  460. X      fstr=walk(useval != 0,level,ops[node+1].ival,&numarg,P_MIN));
  461. X    str_free(fstr);
  462. X    numeric |= numarg;
  463. X    str_cat(str,")");
  464. X    break;
  465. X    case OCONCAT:
  466. X    prec = P_ADD;
  467. X    type = ops[ops[node+1].ival].ival & 255;
  468. X    str = walk(1,level,ops[node+1].ival,&numarg,prec+(type != OCONCAT));
  469. X    str_cat(str," . ");
  470. X    type = ops[ops[node+2].ival].ival & 255;
  471. X    str_scat(str,
  472. X      fstr=walk(1,level,ops[node+2].ival,&numarg,prec+(type != OCONCAT)));
  473. X    str_free(fstr);
  474. X    break;
  475. X    case OASSIGN:
  476. X    prec = P_ASSIGN;
  477. X    str = walk(0,level,ops[node+2].ival,&numarg,prec+1);
  478. X    str_cat(str," ");
  479. X    tmpstr = walk(0,level,ops[node+1].ival,&numarg,P_MIN);
  480. X    str_scat(str,tmpstr);
  481. X    if (str_len(tmpstr) > 1)
  482. X        numeric = 1;
  483. X    str_free(tmpstr);
  484. X    str_cat(str," ");
  485. X    str_scat(str,fstr=walk(1,level,ops[node+3].ival,&numarg,prec));
  486. X    str_free(fstr);
  487. X    numeric |= numarg;
  488. X    break;
  489. X    case OADD:
  490. X    prec = P_ADD;
  491. X    str = walk(1,level,ops[node+1].ival,&numarg,prec);
  492. X    str_cat(str," + ");
  493. X    str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg,prec+1));
  494. X    str_free(fstr);
  495. X    numeric = 1;
  496. X    break;
  497. X    case OSUBTRACT:
  498. X    prec = P_ADD;
  499. X    str = walk(1,level,ops[node+1].ival,&numarg,prec);
  500. X    str_cat(str," - ");
  501. X    str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg,prec+1));
  502. X    str_free(fstr);
  503. X    numeric = 1;
  504. X    break;
  505. X    case OMULT:
  506. X    prec = P_MUL;
  507. X    str = walk(1,level,ops[node+1].ival,&numarg,prec);
  508. X    str_cat(str," * ");
  509. X    str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg,prec+1));
  510. X    str_free(fstr);
  511. X    numeric = 1;
  512. X    break;
  513. X    case ODIV:
  514. X    prec = P_MUL;
  515. X    str = walk(1,level,ops[node+1].ival,&numarg,prec);
  516. X    str_cat(str," / ");
  517. X    str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg,prec+1));
  518. X    str_free(fstr);
  519. X    numeric = 1;
  520. X    break;
  521. X    case OPOW:
  522. X    prec = P_POW;
  523. X    str = walk(1,level,ops[node+1].ival,&numarg,prec+1);
  524. X    str_cat(str," ** ");
  525. X    str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg,prec));
  526. X    str_free(fstr);
  527. X    numeric = 1;
  528. X    break;
  529. X    case OMOD:
  530. X    prec = P_MUL;
  531. X    str = walk(1,level,ops[node+1].ival,&numarg,prec);
  532. X    str_cat(str," % ");
  533. X    str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg,prec+1));
  534. X    str_free(fstr);
  535. X    numeric = 1;
  536. X    break;
  537. X    case OPOSTINCR:
  538. X    prec = P_AUTO;
  539. X    str = walk(1,level,ops[node+1].ival,&numarg,prec+1);
  540. X    str_cat(str,"++");
  541. X    numeric = 1;
  542. X    break;
  543. X    case OPOSTDECR:
  544. X    prec = P_AUTO;
  545. X    str = walk(1,level,ops[node+1].ival,&numarg,prec+1);
  546. X    str_cat(str,"--");
  547. X    numeric = 1;
  548. X    break;
  549. X    case OPREINCR:
  550. X    prec = P_AUTO;
  551. X    str = str_new(0);
  552. X    str_set(str,"++");
  553. X    str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg,prec+1));
  554. X    str_free(fstr);
  555. X    numeric = 1;
  556. X    break;
  557. X    case OPREDECR:
  558. X    prec = P_AUTO;
  559. X    str = str_new(0);
  560. X    str_set(str,"--");
  561. X    str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg,prec+1));
  562. X    str_free(fstr);
  563. X    numeric = 1;
  564. X    break;
  565. X    case OUMINUS:
  566. X    prec = P_UNARY;
  567. X    str = str_new(0);
  568. X    str_set(str,"-");
  569. X    str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg,prec));
  570. X    str_free(fstr);
  571. X    numeric = 1;
  572. X    break;
  573. X    case OUPLUS:
  574. X    numeric = 1;
  575. X    goto def;
  576. X    case OPAREN:
  577. X    str = str_new(0);
  578. X    str_set(str,"(");
  579. X    str_scat(str,
  580. X      fstr=walk(useval != 0,level,ops[node+1].ival,&numarg,P_MIN));
  581. X    str_free(fstr);
  582. X    str_cat(str,")");
  583. X    numeric |= numarg;
  584. X    break;
  585. X    case OGETLINE:
  586. X    str = str_new(0);
  587. X    if (useval)
  588. X        str_cat(str,"(");
  589. X    if (len > 0) {
  590. X        str_cat(str,"$");
  591. X        str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg,P_MIN));
  592. X        if (!*fstr->str_ptr) {
  593. X        str_cat(str,"_");
  594. X        len = 2;        /* a legal fiction */
  595. X        }
  596. X        str_free(fstr);
  597. X    }
  598. X    else
  599. X        str_cat(str,"$_");
  600. X    if (len > 1) {
  601. X        tmpstr=walk(1,level,ops[node+3].ival,&numarg,P_MIN);
  602. X        fstr=walk(1,level,ops[node+2].ival,&numarg,P_MIN);
  603. X        if (!do_fancy_opens) {
  604. X        t = tmpstr->str_ptr;
  605. X        if (*t == '"' || *t == '\'')
  606. X            t = cpytill(tokenbuf,t+1,*t);
  607. X        else
  608. X            fatal("Internal error: OGETLINE %s", t);
  609. X        d = savestr(t);
  610. X        s = savestr(tokenbuf);
  611. X        for (t = tokenbuf; *t; t++) {
  612. X            *t &= 127;
  613. X            if (!isalpha(*t) && !isdigit(*t))
  614. X            *t = '_';
  615. X        }
  616. X        if (!index(tokenbuf,'_'))
  617. X            strcpy(t,"_fh");
  618. X        tmp3str = hfetch(symtab,tokenbuf);
  619. X        if (!tmp3str) {
  620. X            do_opens = TRUE;
  621. X            str_cat(opens,"open(");
  622. X            str_cat(opens,tokenbuf);
  623. X            str_cat(opens,", ");
  624. X            d[1] = '\0';
  625. X            str_cat(opens,d);
  626. X            str_cat(opens,tmpstr->str_ptr+1);
  627. X            opens->str_cur--;
  628. X            if (*fstr->str_ptr == '|')
  629. X            str_cat(opens,"|");
  630. X            str_cat(opens,d);
  631. X            if (*fstr->str_ptr == '|')
  632. X            str_cat(opens,") || die 'Cannot pipe from \"");
  633. X            else
  634. X            str_cat(opens,") || die 'Cannot open file \"");
  635. X            if (*d == '"')
  636. X            str_cat(opens,"'.\"");
  637. X            str_cat(opens,s);
  638. X            if (*d == '"')
  639. X            str_cat(opens,"\".'");
  640. X            str_cat(opens,"\".';\n");
  641. X            hstore(symtab,tokenbuf,str_make("x"));
  642. X        }
  643. X        safefree(s);
  644. X        safefree(d);
  645. X        str_set(tmpstr,"'");
  646. X        str_cat(tmpstr,tokenbuf);
  647. X        str_cat(tmpstr,"'");
  648. X        }
  649. X        if (*fstr->str_ptr == '|')
  650. X        str_cat(tmpstr,", '|'");
  651. X        str_free(fstr);
  652. X    }
  653. X    else
  654. X        tmpstr = str_make("");
  655. X    sprintf(tokenbuf," = &Getline%d(%s)",len,tmpstr->str_ptr);
  656. X    str_cat(str,tokenbuf); 
  657. X    str_free(tmpstr);
  658. X    if (useval)
  659. X        str_cat(str,",$getline_ok)");
  660. X    saw_getline |= 1 << len;
  661. X    break;
  662. X    case OSPRINTF:
  663. X    str = str_new(0);
  664. X    str_set(str,"sprintf(");
  665. X    str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg,P_MIN));
  666. X    str_free(fstr);
  667. X    str_cat(str,")");
  668. X    break;
  669. X    case OSUBSTR:
  670. X    str = str_new(0);
  671. X    str_set(str,"substr(");
  672. X    str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg,P_COMMA+1));
  673. X    str_free(fstr);
  674. X    str_cat(str,", ");
  675. X    str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg,P_COMMA+1));
  676. X    str_free(fstr);
  677. X    str_cat(str,", ");
  678. X    if (len == 3) {
  679. X        str_scat(str,fstr=walk(1,level,ops[node+3].ival,&numarg,P_COMMA+1));
  680. X        str_free(fstr);
  681. X    }
  682. X    else
  683. X        str_cat(str,"999999");
  684. X    str_cat(str,")");
  685. X    break;
  686. X    case OSTRING:
  687. X    str = str_new(0);
  688. X    str_set(str,ops[node+1].cval);
  689. X    break;
  690. X    case OSPLIT:
  691. X    str = str_new(0);
  692. X    numeric = 1;
  693. X    tmpstr = walk(1,level,ops[node+2].ival,&numarg,P_MIN);
  694. X    if (useval)
  695. X        str_set(str,"(@");
  696. X    else
  697. X        str_set(str,"@");
  698. X    str_scat(str,tmpstr);
  699. X    str_cat(str," = split(");
  700. X    if (len == 3) {
  701. X        fstr = walk(1,level,ops[node+3].ival,&numarg,P_COMMA+1);
  702. X        if (str_len(fstr) == 3 && *fstr->str_ptr == '\'') {
  703. X        i = fstr->str_ptr[1] & 127;
  704. X        if (index("*+?.[]()|^$\\",i))
  705. X            sprintf(tokenbuf,"/\\%c/",i);
  706. X        else if (i == ' ')
  707. X            sprintf(tokenbuf,"' '");
  708. X        else
  709. X            sprintf(tokenbuf,"/%c/",i);
  710. X        str_cat(str,tokenbuf);
  711. X        }
  712. X        else
  713. X        str_scat(str,fstr);
  714. X        str_free(fstr);
  715. X    }
  716. X    else if (const_FS) {
  717. X        sprintf(tokenbuf,"/[%c\\n]/",const_FS);
  718. X        str_cat(str,tokenbuf);
  719. X    }
  720. X    else if (saw_FS)
  721. X        str_cat(str,"$FS");
  722. X    else
  723. X        str_cat(str,"' '");
  724. X    str_cat(str,", ");
  725. X    str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg,P_COMMA+1));
  726. X    str_free(fstr);
  727. X    str_cat(str,", 9999)");
  728. X    if (useval) {
  729. X        str_cat(str,")");
  730. X    }
  731. X    str_free(tmpstr);
  732. X    break;
  733. X    case OINDEX:
  734. X    str = str_new(0);
  735. X    str_set(str,"index(");
  736. X    str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg,P_COMMA+1));
  737. X    str_free(fstr);
  738. X    str_cat(str,", ");
  739. X    str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg,P_COMMA+1));
  740. X    str_free(fstr);
  741. X    str_cat(str,")");
  742. X    numeric = 1;
  743. X    break;
  744. X    case OMATCH:
  745. X    str = str_new(0);
  746. X    prec = P_ANDAND;
  747. X    str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg,P_MATCH+1));
  748. X    str_free(fstr);
  749. X    str_cat(str," =~ ");
  750. X    str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg,P_MATCH+1));
  751. X    str_free(fstr);
  752. X    str_cat(str," && ($RLENGTH = length($&), $RSTART = length($`)+1)");
  753. X    numeric = 1;
  754. X    break;
  755. X    case OUSERDEF:
  756. X    str = str_new(0);
  757. X    subretnum = FALSE;
  758. X    fstr=walk(1,level-1,ops[node+2].ival,&numarg,P_MIN);
  759. X    curargs = str_new(0);
  760. X    str_sset(curargs,fstr);
  761. X    str_cat(curargs,",");
  762. X    tmp2str=walk(1,level,ops[node+5].ival,&numarg,P_MIN);
  763. X    str_free(curargs);
  764. X    curargs = Nullstr;
  765. X    level--;
  766. X    subretnum |= numarg;
  767. X    s = Nullch;
  768. X    t = tmp2str->str_ptr;
  769. X    while (t = instr(t,"return "))
  770. X        s = t++;
  771. X    if (s) {
  772. X        i = 0;
  773. X        for (t = s+7; *t; t++) {
  774. X        if (*t == ';' || *t == '}')
  775. X            i++;
  776. X        }
  777. X        if (i == 1) {
  778. X        strcpy(s,s+7);
  779. X        tmp2str->str_cur -= 7;
  780. X        }
  781. X    }
  782. X    str_set(str,"\n");
  783. X    tab(str,level);
  784. X    str_cat(str,"sub ");
  785. X    str_scat(str,tmpstr=walk(1,level,ops[node+1].ival,&numarg,P_MIN));
  786. X    str_cat(str," {\n");
  787. X    tab(str,++level);
  788. X    if (fstr->str_cur) {
  789. X        str_cat(str,"local(");
  790. X        str_scat(str,fstr);
  791. X        str_cat(str,") = @_;");
  792. X    }
  793. X    str_free(fstr);
  794. X    str_scat(str,fstr=walk(1,level,ops[node+3].ival,&numarg,P_MIN));
  795. X    str_free(fstr);
  796. X    fixtab(str,level);
  797. X    str_scat(str,fstr=walk(1,level,ops[node+4].ival,&numarg,P_MIN));
  798. X    str_free(fstr);
  799. X    fixtab(str,level);
  800. X    str_scat(str,tmp2str);
  801. X    str_free(tmp2str);
  802. X    fixtab(str,--level);
  803. X    str_cat(str,"}\n");
  804. X    tab(str,level);
  805. X    str_scat(subs,str);
  806. X    str_set(str,"");
  807. X    str_cat(tmpstr,"(");
  808. X    tmp2str = str_new(0);
  809. X    if (subretnum)
  810. X        str_set(tmp2str,"1");
  811. X    hstore(symtab,tmpstr->str_ptr,tmp2str);
  812. X    str_free(tmpstr);
  813. X    level++;
  814. X    break;
  815. X    case ORETURN:
  816. X    str = str_new(0);
  817. X    if (len > 0) {
  818. X        str_cat(str,"return ");
  819. X        str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg,P_UNI+1));
  820. X        str_free(fstr);
  821. X        if (numarg)
  822. X        subretnum = TRUE;
  823. X    }
  824. X    else
  825. X        str_cat(str,"return");
  826. X    break;
  827. X    case OUSERFUN:
  828. X    str = str_new(0);
  829. X    str_set(str,"&");
  830. X    str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg,P_MIN));
  831. X    str_free(fstr);
  832. X    str_cat(str,"(");
  833. X    tmpstr = hfetch(symtab,str->str_ptr+3);
  834. X    if (tmpstr && tmpstr->str_ptr)
  835. X        numeric |= atoi(tmpstr->str_ptr);
  836. X    str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg,P_MIN));
  837. X    str_free(fstr);
  838. X    str_cat(str,")");
  839. X    break;
  840. X    case OGSUB:
  841. X    case OSUB:
  842. X    if (type == OGSUB)
  843. X        s = "g";
  844. X    else
  845. X        s = "";
  846. X    str = str_new(0);
  847. X    tmpstr = str_new(0);
  848. X    i = 0;
  849. X    if (len == 3) {
  850. X        tmpstr = walk(1,level,ops[node+3].ival,&numarg,P_MATCH+1);
  851. X        if (strNE(tmpstr->str_ptr,"$_")) {
  852. X        str_cat(tmpstr, " =~ s");
  853. X        i++;
  854. X        }
  855. X        else
  856. X        str_set(tmpstr, "s");
  857. X    }
  858. X    else
  859. X        str_set(tmpstr, "s");
  860. X    type = ops[ops[node+2].ival].ival;
  861. X    len = type >> 8;
  862. X    type &= 255;
  863. X    tmp3str = str_new(0);
  864. X    if (type == OSTR) {
  865. X        tmp2str=walk(1,level,ops[ops[node+2].ival+1].ival,&numarg,P_MIN);
  866. X        for (t = tmp2str->str_ptr, d=tokenbuf; *t; d++,t++) {
  867. X        if (*t == '&')
  868. X            *d++ = '$' + 128;
  869. X        else if (*t == '$')
  870. X            *d++ = '\\' + 128;
  871. X        *d = *t + 128;
  872. X        }
  873. X        *d = '\0';
  874. X        str_set(tmp2str,tokenbuf);
  875. X    }
  876. X    else {
  877. X        tmp2str=walk(1,level,ops[node+2].ival,&numarg,P_MIN);
  878. X        str_set(tmp3str,"($s_ = '\"'.(");
  879. X        str_scat(tmp3str,tmp2str);
  880. X        str_cat(tmp3str,").'\"') =~ s/&/\\$&/g, ");
  881. X        str_set(tmp2str,"eval $s_");
  882. X        s = (*s == 'g' ? "ge" : "e");
  883. X        i++;
  884. X    }
  885. X    type = ops[ops[node+1].ival].ival;
  886. X    len = type >> 8;
  887. X    type &= 255;
  888. X    fstr=walk(1,level,ops[node+1].ival,&numarg,P_MIN);
  889. X    if (type == OREGEX) {
  890. X        if (useval && i)
  891. X        str_cat(str,"(");
  892. X        str_scat(str,tmp3str);
  893. X        str_scat(str,tmpstr);
  894. X        str_scat(str,fstr);
  895. X        str_scat(str,tmp2str);
  896. X        str_cat(str,"/");
  897. X        str_cat(str,s);
  898. X    }
  899. X    else if ((type == OFLD && !split_to_array) || (type == OVAR && len == 1)) {
  900. X        if (useval && i)
  901. X        str_cat(str,"(");
  902. X        str_scat(str,tmp3str);
  903. X        str_scat(str,tmpstr);
  904. X        str_cat(str,"/");
  905. X        str_scat(str,fstr);
  906. X        str_cat(str,"/");
  907. X        str_scat(str,tmp2str);
  908. X        str_cat(str,"/");
  909. X        str_cat(str,s);
  910. X    }
  911. X    else {
  912. X        i++;
  913. X        if (useval)
  914. X        str_cat(str,"(");
  915. X        str_cat(str,"$s = ");
  916. X        str_scat(str,fstr);
  917. X        str_cat(str,", ");
  918. X        str_scat(str,tmp3str);
  919. X        str_scat(str,tmpstr);
  920. X        str_cat(str,"/$s/");
  921. X        str_scat(str,tmp2str);
  922. X        str_cat(str,"/");
  923. X        str_cat(str,s);
  924. X    }
  925. X    if (useval && i)
  926. X        str_cat(str,")");
  927. X    str_free(fstr);
  928. X    str_free(tmpstr);
  929. X    str_free(tmp2str);
  930. X    str_free(tmp3str);
  931. X    numeric = 1;
  932. X    break;
  933. X    case ONUM:
  934. X    str = walk(1,level,ops[node+1].ival,&numarg,P_MIN);
  935. X    numeric = 1;
  936. X    break;
  937. X    case OSTR:
  938. X    tmpstr = walk(1,level,ops[node+1].ival,&numarg,P_MIN);
  939. X    s = "'";
  940. X    for (t = tmpstr->str_ptr, d=tokenbuf; *t; d++,t++) {
  941. X        if (*t == '\'')
  942. X        s = "\"";
  943. X        else if (*t == '\\') {
  944. X        s = "\"";
  945. X        *d++ = *t++ + 128;
  946. X        switch (*t) {
  947. X        case '\\': case '"': case 'n': case 't': case '$':
  948. X            break;
  949. X        default:    /* hide this from perl */
  950. X            *d++ = '\\' + 128;
  951. X        }
  952. X        }
  953. X        *d = *t + 128;
  954. X    }
  955. X    *d = '\0';
  956. X    str = str_new(0);
  957. X    str_set(str,s);
  958. X    str_cat(str,tokenbuf);
  959. X    str_free(tmpstr);
  960. X    str_cat(str,s);
  961. X    break;
  962. X    case ODEFINED:
  963. X    prec = P_UNI;
  964. X    str = str_new(0);
  965. X    str_set(str,"defined $");
  966. X    goto addvar;
  967. X    case ODELETE:
  968. X    str = str_new(0);
  969. X    str_set(str,"delete $");
  970. X    goto addvar;
  971. X    case OSTAR:
  972. X    str = str_new(0);
  973. X    str_set(str,"*");
  974. X    goto addvar;
  975. X    case OVAR:
  976. X    str = str_new(0);
  977. X    str_set(str,"$");
  978. X      addvar:
  979. X    str_scat(str,tmpstr=walk(1,level,ops[node+1].ival,&numarg,P_MIN));
  980. X    if (len == 1) {
  981. X        tmp2str = hfetch(symtab,tmpstr->str_ptr);
  982. X        if (tmp2str && atoi(tmp2str->str_ptr))
  983. X        numeric = 2;
  984. X        if (strEQ(str->str_ptr,"$FNR")) {
  985. X        numeric = 1;
  986. X        saw_FNR++;
  987. X        str_set(str,"($.-$FNRbase)");
  988. X        }
  989. X        else if (strEQ(str->str_ptr,"$NR")) {
  990. X        numeric = 1;
  991. X        str_set(str,"$.");
  992. X        }
  993. X        else if (strEQ(str->str_ptr,"$NF")) {
  994. X        numeric = 1;
  995. X        str_set(str,"$#Fld");
  996. X        }
  997. X        else if (strEQ(str->str_ptr,"$0"))
  998. X        str_set(str,"$_");
  999. X        else if (strEQ(str->str_ptr,"$ARGC"))
  1000. X        str_set(str,"($#ARGV+1)");
  1001. X    }
  1002. X    else {
  1003. X#ifdef NOTDEF
  1004. X        if (curargs) {
  1005. X        sprintf(tokenbuf,"$%s,",tmpstr->str_ptr);
  1006. X    ???    if (instr(curargs->str_ptr,tokenbuf))
  1007. X            str_cat(str,"\377");    /* can't translate yet */
  1008. X        }
  1009. X#endif
  1010. X        str_cat(tmpstr,"[]");
  1011. X        tmp2str = hfetch(symtab,tmpstr->str_ptr);
  1012. X        if (tmp2str && atoi(tmp2str->str_ptr))
  1013. X        str_cat(str,"[");
  1014. X        else
  1015. X        str_cat(str,"{");
  1016. X        str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg,P_MIN));
  1017. X        str_free(fstr);
  1018. X        if (strEQ(str->str_ptr,"$ARGV[0")) {
  1019. X        str_set(str,"$ARGV0");
  1020. X        saw_argv0++;
  1021. X        }
  1022. X        else {
  1023. X        if (tmp2str && atoi(tmp2str->str_ptr))
  1024. X            strcpy(tokenbuf,"]");
  1025. X        else
  1026. X            strcpy(tokenbuf,"}");
  1027. X        *tokenbuf += 128;
  1028. X        str_cat(str,tokenbuf);
  1029. X        }
  1030. X    }
  1031. X    str_free(tmpstr);
  1032. X    break;
  1033. X    case OFLD:
  1034. X    str = str_new(0);
  1035. X    if (split_to_array) {
  1036. X        str_set(str,"$Fld");
  1037. X        str_cat(str,"[");
  1038. X        str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg,P_MIN));
  1039. X        str_free(fstr);
  1040. X        str_cat(str,"]");
  1041. X    }
  1042. X    else {
  1043. X        i = atoi(walk(1,level,ops[node+1].ival,&numarg,P_MIN)->str_ptr);
  1044. X        if (i <= arymax)
  1045. X        sprintf(tokenbuf,"$%s",nameary[i]);
  1046. X        else
  1047. X        sprintf(tokenbuf,"$Fld%d",i);
  1048. X        str_set(str,tokenbuf);
  1049. X    }
  1050. X    break;
  1051. X    case OVFLD:
  1052. X    str = str_new(0);
  1053. X    str_set(str,"$Fld[");
  1054. X    i = ops[node+1].ival;
  1055. X    if ((ops[i].ival & 255) == OPAREN)
  1056. X        i = ops[i+1].ival;
  1057. X    tmpstr=walk(1,level,i,&numarg,P_MIN);
  1058. X    str_scat(str,tmpstr);
  1059. X    str_free(tmpstr);
  1060. X    str_cat(str,"]");
  1061. X    break;
  1062. X    case OJUNK:
  1063. X    goto def;
  1064. X    case OSNEWLINE:
  1065. X    str = str_new(2);
  1066. X    str_set(str,";\n");
  1067. X    tab(str,level);
  1068. X    break;
  1069. X    case ONEWLINE:
  1070. X    str = str_new(1);
  1071. X    str_set(str,"\n");
  1072. X    tab(str,level);
  1073. X    break;
  1074. X    case OSCOMMENT:
  1075. X    str = str_new(0);
  1076. X    str_set(str,";");
  1077. X    tmpstr = walk(0,level,ops[node+1].ival,&numarg,P_MIN);
  1078. X    for (s = tmpstr->str_ptr; *s && *s != '\n'; s++)
  1079. X        *s += 128;
  1080. X    str_scat(str,tmpstr);
  1081. X    str_free(tmpstr);
  1082. X    tab(str,level);
  1083. X    break;
  1084. X    case OCOMMENT:
  1085. X    str = str_new(0);
  1086. X    tmpstr = walk(0,level,ops[node+1].ival,&numarg,P_MIN);
  1087. X    for (s = tmpstr->str_ptr; *s && *s != '\n'; s++)
  1088. X        *s += 128;
  1089. X    str_scat(str,tmpstr);
  1090. X    str_free(tmpstr);
  1091. X    tab(str,level);
  1092. X    break;
  1093. X    case OCOMMA:
  1094. X    prec = P_COMMA;
  1095. X    str = walk(1,level,ops[node+1].ival,&numarg,prec);
  1096. X    str_cat(str,", ");
  1097. X    str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg,P_MIN));
  1098. X    str_free(fstr);
  1099. X    str_scat(str,fstr=walk(1,level,ops[node+3].ival,&numarg,prec+1));
  1100. X    str_free(fstr);
  1101. X    break;
  1102. X    case OSEMICOLON:
  1103. X    str = str_new(1);
  1104. X    str_set(str,";\n");
  1105. X    tab(str,level);
  1106. X    break;
  1107. X    case OSTATES:
  1108. X    str = walk(0,level,ops[node+1].ival,&numarg,P_MIN);
  1109. X    str_scat(str,fstr=walk(0,level,ops[node+2].ival,&numarg,P_MIN));
  1110. X    str_free(fstr);
  1111. X    break;
  1112. X    case OSTATE:
  1113. X    str = str_new(0);
  1114. X    if (len >= 1) {
  1115. X        str_scat(str,fstr=walk(0,level,ops[node+1].ival,&numarg,P_MIN));
  1116. X        str_free(fstr);
  1117. X        if (len >= 2) {
  1118. X        tmpstr = walk(0,level,ops[node+2].ival,&numarg,P_MIN);
  1119. X        if (*tmpstr->str_ptr == ';') {
  1120. X            addsemi(str);
  1121. X            str_cat(str,tmpstr->str_ptr+1);
  1122. X        }
  1123. X        str_free(tmpstr);
  1124. X        }
  1125. X    }
  1126. X    break;
  1127. X    case OCLOSE:
  1128. X    str = str_make("close(");
  1129. X    tmpstr = walk(1,level,ops[node+1].ival,&numarg,P_MIN);
  1130. X    if (!do_fancy_opens) {
  1131. X        t = tmpstr->str_ptr;
  1132. X        if (*t == '"' || *t == '\'')
  1133. X        t = cpytill(tokenbuf,t+1,*t);
  1134. X        else
  1135. X        fatal("Internal error: OCLOSE %s",t);
  1136. X        s = savestr(tokenbuf);
  1137. X        for (t = tokenbuf; *t; t++) {
  1138. X        *t &= 127;
  1139. X        if (!isalpha(*t) && !isdigit(*t))
  1140. X            *t = '_';
  1141. X        }
  1142. X        if (!index(tokenbuf,'_'))
  1143. X        strcpy(t,"_fh");
  1144. X        str_free(tmpstr);
  1145. X        safefree(s);
  1146. X        str_set(str,"close ");
  1147. X        str_cat(str,tokenbuf);
  1148. X    }
  1149. X    else {
  1150. X        sprintf(tokenbuf,"$fh = delete $opened{%s} && close($fh)",
  1151. X           tmpstr->str_ptr);
  1152. X        str_free(tmpstr);
  1153. X        str_set(str,tokenbuf);
  1154. X    }
  1155. X    break;
  1156. X    case OPRINTF:
  1157. X    case OPRINT:
  1158. X    lparen = "";    /* set to parens if necessary */
  1159. X    rparen = "";
  1160. X    str = str_new(0);
  1161. X    if (len == 3) {        /* output redirection */
  1162. X        tmpstr = walk(1,level,ops[node+3].ival,&numarg,P_MIN);
  1163. X        tmp2str = walk(1,level,ops[node+2].ival,&numarg,P_MIN);
  1164. X        if (!do_fancy_opens) {
  1165. X        t = tmpstr->str_ptr;
  1166. X        if (*t == '"' || *t == '\'')
  1167. X            t = cpytill(tokenbuf,t+1,*t);
  1168. X        else
  1169. X            fatal("Internal error: OPRINT");
  1170. X        d = savestr(t);
  1171. X        s = savestr(tokenbuf);
  1172. X        for (t = tokenbuf; *t; t++) {
  1173. X            *t &= 127;
  1174. X            if (!isalpha(*t) && !isdigit(*t))
  1175. X            *t = '_';
  1176. X        }
  1177. X        if (!index(tokenbuf,'_'))
  1178. X            strcpy(t,"_fh");
  1179. X        tmp3str = hfetch(symtab,tokenbuf);
  1180. X        if (!tmp3str) {
  1181. X            str_cat(opens,"open(");
  1182. X            str_cat(opens,tokenbuf);
  1183. X            str_cat(opens,", ");
  1184. X            d[1] = '\0';
  1185. X            str_cat(opens,d);
  1186. X            str_scat(opens,tmp2str);
  1187. X            str_cat(opens,tmpstr->str_ptr+1);
  1188. X            if (*tmp2str->str_ptr == '|')
  1189. X            str_cat(opens,") || die 'Cannot pipe to \"");
  1190. X            else
  1191. X            str_cat(opens,") || die 'Cannot create file \"");
  1192. X            if (*d == '"')
  1193. X            str_cat(opens,"'.\"");
  1194. X            str_cat(opens,s);
  1195. X            if (*d == '"')
  1196. X            str_cat(opens,"\".'");
  1197. X            str_cat(opens,"\".';\n");
  1198. X            hstore(symtab,tokenbuf,str_make("x"));
  1199. X        }
  1200. X        str_free(tmpstr);
  1201. X        str_free(tmp2str);
  1202. X        safefree(s);
  1203. X        safefree(d);
  1204. X        }
  1205. X        else {
  1206. X        sprintf(tokenbuf,"&Pick('%s', %s) &&\n",
  1207. X           tmp2str->str_ptr, tmpstr->str_ptr);
  1208. X        str_cat(str,tokenbuf);
  1209. X        tab(str,level+1);
  1210. X        strcpy(tokenbuf,"$fh");
  1211. X        str_free(tmpstr);
  1212. X        str_free(tmp2str);
  1213. X        lparen = "(";
  1214. X        rparen = ")";
  1215. X        }
  1216. X    }
  1217. X    else
  1218. X        strcpy(tokenbuf,"");
  1219. X    str_cat(str,lparen);    /* may be null */
  1220. X    if (type == OPRINTF)
  1221. X        str_cat(str,"printf");
  1222. X    else
  1223. X        str_cat(str,"print");
  1224. X    if (len == 3 || do_fancy_opens) {
  1225. X        if (*tokenbuf)
  1226. X        str_cat(str," ");
  1227. X        str_cat(str,tokenbuf);
  1228. X    }
  1229. X    tmpstr = walk(1+(type==OPRINT),level,ops[node+1].ival,&numarg,P_MIN);
  1230. X    if (!*tmpstr->str_ptr && lval_field) {
  1231. X        t = saw_OFS ? "$," : "' '";
  1232. X        if (split_to_array) {
  1233. X        sprintf(tokenbuf,"join(%s,@Fld)",t);
  1234. X        str_cat(tmpstr,tokenbuf);
  1235. X        }
  1236. X        else {
  1237. X        for (i = 1; i < maxfld; i++) {
  1238. X            if (i <= arymax)
  1239. X            sprintf(tokenbuf,"$%s, ",nameary[i]);
  1240. X            else
  1241. X            sprintf(tokenbuf,"$Fld%d, ",i);
  1242. X            str_cat(tmpstr,tokenbuf);
  1243. X        }
  1244. X        if (maxfld <= arymax)
  1245. X            sprintf(tokenbuf,"$%s",nameary[maxfld]);
  1246. X        else
  1247. X            sprintf(tokenbuf,"$Fld%d",maxfld);
  1248. X        str_cat(tmpstr,tokenbuf);
  1249. X        }
  1250. X    }
  1251. X    if (*tmpstr->str_ptr) {
  1252. X        str_cat(str," ");
  1253. X        str_scat(str,tmpstr);
  1254. X    }
  1255. X    else {
  1256. X        str_cat(str," $_");
  1257. X    }
  1258. X    str_cat(str,rparen);    /* may be null */
  1259. X    str_free(tmpstr);
  1260. X    break;
  1261. X    case ORAND:
  1262. X    str = str_make("rand(1)");
  1263. X    break;
  1264. X    case OSRAND:
  1265. X    str = str_make("srand(");
  1266. X    goto maybe0;
  1267. X    case OATAN2:
  1268. X    str = str_make("atan2(");
  1269. X    goto maybe0;
  1270. X    case OSIN:
  1271. X    str = str_make("sin(");
  1272. X    goto maybe0;
  1273. X    case OCOS:
  1274. X    str = str_make("cos(");
  1275. X    goto maybe0;
  1276. X    case OSYSTEM:
  1277. X    str = str_make("system(");
  1278. X    goto maybe0;
  1279. X    case OLENGTH:
  1280. X    str = str_make("length(");
  1281. X    goto maybe0;
  1282. X    case OLOG:
  1283. X    str = str_make("log(");
  1284. X    goto maybe0;
  1285. X    case OEXP:
  1286. X    str = str_make("exp(");
  1287. X    goto maybe0;
  1288. X    case OSQRT:
  1289. X    str = str_make("sqrt(");
  1290. X    goto maybe0;
  1291. X    case OINT:
  1292. X    str = str_make("int(");
  1293. X      maybe0:
  1294. X    numeric = 1;
  1295. X    if (len > 0)
  1296. X        tmpstr = walk(1,level,ops[node+1].ival,&numarg,P_MIN);
  1297. X    else
  1298. X        tmpstr = str_new(0);;
  1299. X    if (!tmpstr->str_ptr || !*tmpstr->str_ptr) {
  1300. X        if (lval_field) {
  1301. X        t = saw_OFS ? "$," : "' '";
  1302. X        if (split_to_array) {
  1303. X            sprintf(tokenbuf,"join(%s,@Fld)",t);
  1304. X            str_cat(tmpstr,tokenbuf);
  1305. X        }
  1306. X        else {
  1307. X            sprintf(tokenbuf,"join(%s, ",t);
  1308. X            str_cat(tmpstr,tokenbuf);
  1309. X            for (i = 1; i < maxfld; i++) {
  1310. X            if (i <= arymax)
  1311. X                sprintf(tokenbuf,"$%s,",nameary[i]);
  1312. X            else
  1313. X                sprintf(tokenbuf,"$Fld%d,",i);
  1314. X            str_cat(tmpstr,tokenbuf);
  1315. X            }
  1316. X            if (maxfld <= arymax)
  1317. X            sprintf(tokenbuf,"$%s)",nameary[maxfld]);
  1318. X            else
  1319. X            sprintf(tokenbuf,"$Fld%d)",maxfld);
  1320. X            str_cat(tmpstr,tokenbuf);
  1321. X        }
  1322. X        }
  1323. X        else
  1324. X        str_cat(tmpstr,"$_");
  1325. X    }
  1326. X    if (strEQ(tmpstr->str_ptr,"$_")) {
  1327. X        if (type == OLENGTH && !do_chop) {
  1328. X        str = str_make("(length(");
  1329. X        str_cat(tmpstr,") - 1");
  1330. X        }
  1331. X    }
  1332. X    str_scat(str,tmpstr);
  1333. X    str_free(tmpstr);
  1334. X    str_cat(str,")");
  1335. X    break;
  1336. X    case OBREAK:
  1337. X    str = str_new(0);
  1338. X    str_set(str,"last");
  1339. X    break;
  1340. X    case ONEXT:
  1341. X    str = str_new(0);
  1342. X    str_set(str,"next line");
  1343. X    break;
  1344. X    case OEXIT:
  1345. X    str = str_new(0);
  1346. X    if (realexit) {
  1347. X        prec = P_UNI;
  1348. X        str_set(str,"exit");
  1349. X        if (len == 1) {
  1350. X        str_cat(str," ");
  1351. X        exitval = TRUE;
  1352. X        str_scat(str,
  1353. X          fstr=walk(1,level,ops[node+1].ival,&numarg,prec+1));
  1354. X        str_free(fstr);
  1355. X        }
  1356. X    }
  1357. X    else {
  1358. X        if (len == 1) {
  1359. X        str_set(str,"$ExitValue = ");
  1360. X        exitval = TRUE;
  1361. X        str_scat(str,
  1362. X          fstr=walk(1,level,ops[node+1].ival,&numarg,P_ASSIGN));
  1363. X        str_free(fstr);
  1364. X        str_cat(str,"; ");
  1365. X        }
  1366. X        str_cat(str,"last line");
  1367. X    }
  1368. X    break;
  1369. X    case OCONTINUE:
  1370. X    str = str_new(0);
  1371. X    str_set(str,"next");
  1372. X    break;
  1373. X    case OREDIR:
  1374. X    goto def;
  1375. X    case OIF:
  1376. X    str = str_new(0);
  1377. X    str_set(str,"if (");
  1378. X    str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg,P_MIN));
  1379. X    str_free(fstr);
  1380. X    str_cat(str,") ");
  1381. X    str_scat(str,fstr=walk(0,level,ops[node+2].ival,&numarg,P_MIN));
  1382. X    str_free(fstr);
  1383. X    if (len == 3) {
  1384. X        i = ops[node+3].ival;
  1385. X        if (i) {
  1386. X        if ((ops[i].ival & 255) == OBLOCK) {
  1387. X            i = ops[i+1].ival;
  1388. X            if (i) {
  1389. X            if ((ops[i].ival & 255) != OIF)
  1390. X                i = 0;
  1391. X            }
  1392. X        }
  1393. X        else
  1394. X            i = 0;
  1395. X        }
  1396. X        if (i) {
  1397. X        str_cat(str,"els");
  1398. X        str_scat(str,fstr=walk(0,level,i,&numarg,P_MIN));
  1399. X        str_free(fstr);
  1400. X        }
  1401. X        else {
  1402. X        str_cat(str,"else ");
  1403. X        str_scat(str,fstr=walk(0,level,ops[node+3].ival,&numarg,P_MIN));
  1404. X        str_free(fstr);
  1405. X        }
  1406. X    }
  1407. X    break;
  1408. X    case OWHILE:
  1409. X    str = str_new(0);
  1410. X    str_set(str,"while (");
  1411. X    str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg,P_MIN));
  1412. X    str_free(fstr);
  1413. X    str_cat(str,") ");
  1414. X    str_scat(str,fstr=walk(0,level,ops[node+2].ival,&numarg,P_MIN));
  1415. X    str_free(fstr);
  1416. X    break;
  1417. X    case OFOR:
  1418. X    str = str_new(0);
  1419. X    str_set(str,"for (");
  1420. X    str_scat(str,tmpstr=walk(1,level,ops[node+1].ival,&numarg,P_MIN));
  1421. X    i = numarg;
  1422. X    if (i) {
  1423. X        t = s = tmpstr->str_ptr;
  1424. X        while (isalpha(*t) || isdigit(*t) || *t == '$' || *t == '_')
  1425. X        t++;
  1426. X        i = t - s;
  1427. X        if (i < 2)
  1428. X        i = 0;
  1429. X    }
  1430. X    str_cat(str,"; ");
  1431. X    fstr=walk(1,level,ops[node+2].ival,&numarg,P_MIN);
  1432. X    if (i && (t = index(fstr->str_ptr,0377))) {
  1433. X        if (strnEQ(fstr->str_ptr,s,i))
  1434. X        *t = ' ';
  1435. X    }
  1436. X    str_scat(str,fstr);
  1437. X    str_free(fstr);
  1438. X    str_free(tmpstr);
  1439. X    str_cat(str,"; ");
  1440. X    str_scat(str,fstr=walk(1,level,ops[node+3].ival,&numarg,P_MIN));
  1441. X    str_free(fstr);
  1442. X    str_cat(str,") ");
  1443. X    str_scat(str,fstr=walk(0,level,ops[node+4].ival,&numarg,P_MIN));
  1444. X    str_free(fstr);
  1445. X    break;
  1446. X    case OFORIN:
  1447. X    tmpstr = walk(0,level,ops[node+1].ival,&numarg,P_MIN);
  1448. X    d = index(tmpstr->str_ptr,'$');
  1449. X    if (!d)
  1450. X        fatal("Illegal for loop: %s",tmpstr->str_ptr);
  1451. X    s = index(d,'{');
  1452. X    if (!s)
  1453. X        s = index(d,'[');
  1454. X    if (!s)
  1455. X        fatal("Illegal for loop: %s",d);
  1456. X    *s++ = '\0';
  1457. X    for (t = s; i = *t; t++) {
  1458. X        i &= 127;
  1459. X        if (i == '}' || i == ']')
  1460. X        break;
  1461. X    }
  1462. X    if (*t)
  1463. X        *t = '\0';
  1464. X    str = str_new(0);
  1465. X    str_set(str,d+1);
  1466. X    str_cat(str,"[]");
  1467. X    tmp2str = hfetch(symtab,str->str_ptr);
  1468. X    if (tmp2str && atoi(tmp2str->str_ptr)) {
  1469. X        sprintf(tokenbuf,
  1470. X          "foreach %s ($[ .. $#%s) ",
  1471. X          s,
  1472. X          d+1);
  1473. X    }
  1474. X    else {
  1475. X        sprintf(tokenbuf,
  1476. X          "foreach %s (keys %%%s) ",
  1477. X          s,
  1478. X          d+1);
  1479. X    }
  1480. X    str_set(str,tokenbuf);
  1481. X    str_scat(str,fstr=walk(0,level,ops[node+2].ival,&numarg,P_MIN));
  1482. X    str_free(fstr);
  1483. X    str_free(tmpstr);
  1484. X    break;
  1485. X    case OBLOCK:
  1486. X    str = str_new(0);
  1487. X    str_set(str,"{");
  1488. X    if (len >= 2 && ops[node+2].ival) {
  1489. X        str_scat(str,fstr=walk(0,level,ops[node+2].ival,&numarg,P_MIN));
  1490. X        str_free(fstr);
  1491. X    }
  1492. X    fixtab(str,++level);
  1493. X    str_scat(str,fstr=walk(0,level,ops[node+1].ival,&numarg,P_MIN));
  1494. X    str_free(fstr);
  1495. X    addsemi(str);
  1496. X    fixtab(str,--level);
  1497. X    str_cat(str,"}\n");
  1498. X    tab(str,level);
  1499. X    if (len >= 3) {
  1500. X        str_scat(str,fstr=walk(0,level,ops[node+3].ival,&numarg,P_MIN));
  1501. X        str_free(fstr);
  1502. X    }
  1503. X    break;
  1504. X    default:
  1505. X      def:
  1506. X    if (len) {
  1507. X        if (len > 5)
  1508. X        fatal("Garbage length in walk");
  1509. X        str = walk(0,level,ops[node+1].ival,&numarg,P_MIN);
  1510. X        for (i = 2; i<= len; i++) {
  1511. X        str_scat(str,fstr=walk(0,level,ops[node+i].ival,&numarg,P_MIN));
  1512. X        str_free(fstr);
  1513. X        }
  1514. X    }
  1515. X    else {
  1516. X        str = Nullstr;
  1517. X    }
  1518. X    break;
  1519. X    }
  1520. X    if (!str)
  1521. X    str = str_new(0);
  1522. X
  1523. X    if (useval && prec < minprec) {        /* need parens? */
  1524. X    fstr = str_new(str->str_cur+2);
  1525. X    str_nset(fstr,"(",1);
  1526. X    str_scat(fstr,str);
  1527. X    str_ncat(fstr,")",1);
  1528. X    str_free(str);
  1529. X    str = fstr;
  1530. X    }
  1531. X
  1532. X    *numericptr = numeric;
  1533. X#ifdef DEBUGGING
  1534. X    if (debug & 4) {
  1535. X    printf("%3d %5d %15s %d %4d ",level,node,opname[type],len,str->str_cur);
  1536. X    for (t = str->str_ptr; *t && t - str->str_ptr < 40; t++)
  1537. X        if (*t == '\n')
  1538. X        printf("\\n");
  1539. X        else if (*t == '\t')
  1540. X        printf("\\t");
  1541. X        else
  1542. X        putchar(*t);
  1543. X    putchar('\n');
  1544. X    }
  1545. X#endif
  1546. X    return str;
  1547. X}
  1548. X
  1549. Xtab(str,lvl)
  1550. Xregister STR *str;
  1551. Xregister int lvl;
  1552. X{
  1553. X    while (lvl > 1) {
  1554. X    str_cat(str,"\t");
  1555. X    lvl -= 2;
  1556. X    }
  1557. X    if (lvl)
  1558. X    str_cat(str,"    ");
  1559. X}
  1560. X
  1561. Xfixtab(str,lvl)
  1562. Xregister STR *str;
  1563. Xregister int lvl;
  1564. X{
  1565. X    register char *s;
  1566. X
  1567. X    /* strip trailing white space */
  1568. X
  1569. X    s = str->str_ptr+str->str_cur - 1;
  1570. X    while (s >= str->str_ptr && (*s == ' ' || *s == '\t' || *s == '\n'))
  1571. X    s--;
  1572. X    s[1] = '\0';
  1573. X    str->str_cur = s + 1 - str->str_ptr;
  1574. X    if (s >= str->str_ptr && *s != '\n')
  1575. X    str_cat(str,"\n");
  1576. X
  1577. X    tab(str,lvl);
  1578. X}
  1579. X
  1580. Xaddsemi(str)
  1581. Xregister STR *str;
  1582. X{
  1583. X    register char *s;
  1584. X
  1585. X    s = str->str_ptr+str->str_cur - 1;
  1586. X    while (s >= str->str_ptr && (*s == ' ' || *s == '\t' || *s == '\n'))
  1587. X    s--;
  1588. X    if (s >= str->str_ptr && *s != ';' && *s != '}')
  1589. X    str_cat(str,";");
  1590. X}
  1591. X
  1592. Xemit_split(str,level)
  1593. Xregister STR *str;
  1594. Xint level;
  1595. X{
  1596. X    register int i;
  1597. X
  1598. X    if (split_to_array)
  1599. X    str_cat(str,"@Fld");
  1600. X    else {
  1601. X    str_cat(str,"(");
  1602. X    for (i = 1; i < maxfld; i++) {
  1603. X        if (i <= arymax)
  1604. X        sprintf(tokenbuf,"$%s,",nameary[i]);
  1605. X        else
  1606. X        sprintf(tokenbuf,"$Fld%d,",i);
  1607. X        str_cat(str,tokenbuf);
  1608. X    }
  1609. X    if (maxfld <= arymax)
  1610. X        sprintf(tokenbuf,"$%s)",nameary[maxfld]);
  1611. X    else
  1612. X        sprintf(tokenbuf,"$Fld%d)",maxfld);
  1613. X    str_cat(str,tokenbuf);
  1614. X    }
  1615. X    if (const_FS) {
  1616. X    sprintf(tokenbuf," = split(/[%c\\n]/, $_, 9999);\n",const_FS);
  1617. X    str_cat(str,tokenbuf);
  1618. X    }
  1619. X    else if (saw_FS)
  1620. X    str_cat(str," = split($FS, $_, 9999);\n");
  1621. X    else
  1622. X    str_cat(str," = split(' ', $_, 9999);\n");
  1623. X    tab(str,level);
  1624. X}
  1625. X
  1626. Xprewalk(numit,level,node,numericptr)
  1627. Xint numit;
  1628. Xint level;
  1629. Xregister int node;
  1630. Xint *numericptr;
  1631. X{
  1632. X    register int len;
  1633. X    register int type;
  1634. X    register int i;
  1635. X    char *t;
  1636. X    char *d, *s;
  1637. X    int numarg;
  1638. X    int numeric = FALSE;
  1639. X    STR *tmpstr;
  1640. X    STR *tmp2str;
  1641. X
  1642. X    if (!node) {
  1643. X    *numericptr = 0;
  1644. X    return 0;
  1645. X    }
  1646. X    type = ops[node].ival;
  1647. X    len = type >> 8;
  1648. X    type &= 255;
  1649. X    switch (type) {
  1650. X    case OPROG:
  1651. X    prewalk(0,level,ops[node+1].ival,&numarg);
  1652. X    if (ops[node+2].ival) {
  1653. X        prewalk(0,level,ops[node+2].ival,&numarg);
  1654. X    }
  1655. X    ++level;
  1656. X    prewalk(0,level,ops[node+3].ival,&numarg);
  1657. X    --level;
  1658. X    if (ops[node+3].ival) {
  1659. X        prewalk(0,level,ops[node+4].ival,&numarg);
  1660. X    }
  1661. X    break;
  1662. X    case OHUNKS:
  1663. X    prewalk(0,level,ops[node+1].ival,&numarg);
  1664. X    prewalk(0,level,ops[node+2].ival,&numarg);
  1665. X    if (len == 3) {
  1666. X        prewalk(0,level,ops[node+3].ival,&numarg);
  1667. X    }
  1668. X    break;
  1669. X    case ORANGE:
  1670. X    prewalk(1,level,ops[node+1].ival,&numarg);
  1671. X    prewalk(1,level,ops[node+2].ival,&numarg);
  1672. X    break;
  1673. X    case OPAT:
  1674. X    goto def;
  1675. X    case OREGEX:
  1676. X    prewalk(0,level,ops[node+1].ival,&numarg);
  1677. X    break;
  1678. X    case OHUNK:
  1679. X    if (len == 1) {
  1680. X        prewalk(0,level,ops[node+1].ival,&numarg);
  1681. X    }
  1682. X    else {
  1683. X        i = prewalk(0,level,ops[node+1].ival,&numarg);
  1684. X        if (i) {
  1685. X        ++level;
  1686. X        prewalk(0,level,ops[node+2].ival,&numarg);
  1687. X        --level;
  1688. X        }
  1689. X        else {
  1690. X        prewalk(0,level,ops[node+2].ival,&numarg);
  1691. X        }
  1692. X    }
  1693. X    break;
  1694. X    case OPPAREN:
  1695. X    prewalk(0,level,ops[node+1].ival,&numarg);
  1696. X    break;
  1697. X    case OPANDAND:
  1698. X    prewalk(0,level,ops[node+1].ival,&numarg);
  1699. X    prewalk(0,level,ops[node+2].ival,&numarg);
  1700. X    break;
  1701. X    case OPOROR:
  1702. X    prewalk(0,level,ops[node+1].ival,&numarg);
  1703. X    prewalk(0,level,ops[node+2].ival,&numarg);
  1704. X    break;
  1705. X    case OPNOT:
  1706. X    prewalk(0,level,ops[node+1].ival,&numarg);
  1707. X    break;
  1708. X    case OCPAREN:
  1709. X    prewalk(0,level,ops[node+1].ival,&numarg);
  1710. X    numeric |= numarg;
  1711. X    break;
  1712. X    case OCANDAND:
  1713. X    prewalk(0,level,ops[node+1].ival,&numarg);
  1714. X    numeric = 1;
  1715. X    prewalk(0,level,ops[node+2].ival,&numarg);
  1716. X    break;
  1717. X    case OCOROR:
  1718. X    prewalk(0,level,ops[node+1].ival,&numarg);
  1719. X    numeric = 1;
  1720. X    prewalk(0,level,ops[node+2].ival,&numarg);
  1721. X    break;
  1722. X    case OCNOT:
  1723. X    prewalk(0,level,ops[node+1].ival,&numarg);
  1724. X    numeric = 1;
  1725. X    break;
  1726. X    case ORELOP:
  1727. X    prewalk(0,level,ops[node+2].ival,&numarg);
  1728. X    numeric |= numarg;
  1729. X    prewalk(0,level,ops[node+1].ival,&numarg);
  1730. X    prewalk(0,level,ops[node+3].ival,&numarg);
  1731. X    numeric |= numarg;
  1732. X    numeric = 1;
  1733. X    break;
  1734. X    case ORPAREN:
  1735. X    prewalk(0,level,ops[node+1].ival,&numarg);
  1736. X    numeric |= numarg;
  1737. X    break;
  1738. X    case OMATCHOP:
  1739. X    prewalk(0,level,ops[node+2].ival,&numarg);
  1740. X    prewalk(0,level,ops[node+1].ival,&numarg);
  1741. X    prewalk(0,level,ops[node+3].ival,&numarg);
  1742. X    numeric = 1;
  1743. X    break;
  1744. X    case OMPAREN:
  1745. X    prewalk(0,level,ops[node+1].ival,&numarg);
  1746. X    numeric |= numarg;
  1747. X    break;
  1748. X    case OCONCAT:
  1749. X    prewalk(0,level,ops[node+1].ival,&numarg);
  1750. X    prewalk(0,level,ops[node+2].ival,&numarg);
  1751. X    break;
  1752. X    case OASSIGN:
  1753. X    prewalk(0,level,ops[node+2].ival,&numarg);
  1754. X    prewalk(0,level,ops[node+1].ival,&numarg);
  1755. X    prewalk(0,level,ops[node+3].ival,&numarg);
  1756. X    if (numarg || strlen(ops[ops[node+1].ival+1].cval) > 1) {
  1757. X        numericize(ops[node+2].ival);
  1758. X        if (!numarg)
  1759. X        numericize(ops[node+3].ival);
  1760. X    }
  1761. X    numeric |= numarg;
  1762. X    break;
  1763. X    case OADD:
  1764. X    prewalk(1,level,ops[node+1].ival,&numarg);
  1765. X    prewalk(1,level,ops[node+2].ival,&numarg);
  1766. X    numeric = 1;
  1767. X    break;
  1768. X    case OSUBTRACT:
  1769. X    prewalk(1,level,ops[node+1].ival,&numarg);
  1770. X    prewalk(1,level,ops[node+2].ival,&numarg);
  1771. X    numeric = 1;
  1772. X    break;
  1773. X    case OMULT:
  1774. X    prewalk(1,level,ops[node+1].ival,&numarg);
  1775. X    prewalk(1,level,ops[node+2].ival,&numarg);
  1776. X    numeric = 1;
  1777. X    break;
  1778. X    case ODIV:
  1779. X    prewalk(1,level,ops[node+1].ival,&numarg);
  1780. X    prewalk(1,level,ops[node+2].ival,&numarg);
  1781. X    numeric = 1;
  1782. X    break;
  1783. X    case OPOW:
  1784. X    prewalk(1,level,ops[node+1].ival,&numarg);
  1785. X    prewalk(1,level,ops[node+2].ival,&numarg);
  1786. X    numeric = 1;
  1787. X    break;
  1788. X    case OMOD:
  1789. X    prewalk(1,level,ops[node+1].ival,&numarg);
  1790. X    prewalk(1,level,ops[node+2].ival,&numarg);
  1791. X    numeric = 1;
  1792. X    break;
  1793. X    case OPOSTINCR:
  1794. X    prewalk(1,level,ops[node+1].ival,&numarg);
  1795. X    numeric = 1;
  1796. X    break;
  1797. X    case OPOSTDECR:
  1798. X    prewalk(1,level,ops[node+1].ival,&numarg);
  1799. X    numeric = 1;
  1800. X    break;
  1801. X    case OPREINCR:
  1802. X    prewalk(1,level,ops[node+1].ival,&numarg);
  1803. X    numeric = 1;
  1804. X    break;
  1805. X    case OPREDECR:
  1806. X    prewalk(1,level,ops[node+1].ival,&numarg);
  1807. X    numeric = 1;
  1808. X    break;
  1809. X    case OUMINUS:
  1810. X    prewalk(1,level,ops[node+1].ival,&numarg);
  1811. X    numeric = 1;
  1812. X    break;
  1813. X    case OUPLUS:
  1814. X    prewalk(1,level,ops[node+1].ival,&numarg);
  1815. X    numeric = 1;
  1816. X    break;
  1817. X    case OPAREN:
  1818. X    prewalk(0,level,ops[node+1].ival,&numarg);
  1819. X    numeric |= numarg;
  1820. X    break;
  1821. X    case OGETLINE:
  1822. X    break;
  1823. X    case OSPRINTF:
  1824. X    prewalk(0,level,ops[node+1].ival,&numarg);
  1825. X    break;
  1826. X    case OSUBSTR:
  1827. X    prewalk(0,level,ops[node+1].ival,&numarg);
  1828. X    prewalk(1,level,ops[node+2].ival,&numarg);
  1829. X    if (len == 3) {
  1830. X        prewalk(1,level,ops[node+3].ival,&numarg);
  1831. X    }
  1832. X    break;
  1833. X    case OSTRING:
  1834. X    break;
  1835. X    case OSPLIT:
  1836. X    numeric = 1;
  1837. X    prewalk(0,level,ops[node+2].ival,&numarg);
  1838. X    if (len == 3)
  1839. X        prewalk(0,level,ops[node+3].ival,&numarg);
  1840. X    prewalk(0,level,ops[node+1].ival,&numarg);
  1841. X    break;
  1842. X    case OINDEX:
  1843. X    prewalk(0,level,ops[node+1].ival,&numarg);
  1844. X    prewalk(0,level,ops[node+2].ival,&numarg);
  1845. X    numeric = 1;
  1846. X    break;
  1847. X    case OMATCH:
  1848. X    prewalk(0,level,ops[node+1].ival,&numarg);
  1849. X    prewalk(0,level,ops[node+2].ival,&numarg);
  1850. X    numeric = 1;
  1851. X    break;
  1852. X    case OUSERDEF:
  1853. X    subretnum = FALSE;
  1854. X    --level;
  1855. X    tmpstr = walk(0,level,ops[node+1].ival,&numarg,P_MIN);
  1856. X    ++level;
  1857. X    prewalk(0,level,ops[node+2].ival,&numarg);
  1858. X    prewalk(0,level,ops[node+4].ival,&numarg);
  1859. X    prewalk(0,level,ops[node+5].ival,&numarg);
  1860. X    --level;
  1861. X    str_cat(tmpstr,"(");
  1862. X    tmp2str = str_new(0);
  1863. X    if (subretnum || numarg)
  1864. X        str_set(tmp2str,"1");
  1865. X    hstore(symtab,tmpstr->str_ptr,tmp2str);
  1866. X    str_free(tmpstr);
  1867. X    level++;
  1868. X    break;
  1869. X    case ORETURN:
  1870. X    if (len > 0) {
  1871. X        prewalk(0,level,ops[node+1].ival,&numarg);
  1872. X        if (numarg)
  1873. X        subretnum = TRUE;
  1874. X    }
  1875. X    break;
  1876. X    case OUSERFUN:
  1877. X    tmp2str = str_new(0);
  1878. X    str_scat(tmp2str,tmpstr=walk(1,level,ops[node+1].ival,&numarg,P_MIN));
  1879. X    fixrargs(tmpstr->str_ptr,ops[node+2].ival,0);
  1880. X    str_free(tmpstr);
  1881. X    str_cat(tmp2str,"(");
  1882. X    tmpstr = hfetch(symtab,tmp2str->str_ptr);
  1883. X    if (tmpstr && tmpstr->str_ptr)
  1884. X        numeric |= atoi(tmpstr->str_ptr);
  1885. X    prewalk(0,level,ops[node+2].ival,&numarg);
  1886. X    str_free(tmp2str);
  1887. X    break;
  1888. X    case OGSUB:
  1889. X    case OSUB:
  1890. X    if (len >= 3)
  1891. X        prewalk(0,level,ops[node+3].ival,&numarg);
  1892. X    prewalk(0,level,ops[ops[node+2].ival+1].ival,&numarg);
  1893. X    prewalk(0,level,ops[node+1].ival,&numarg);
  1894. X    numeric = 1;
  1895. X    break;
  1896. X    case ONUM:
  1897. X    prewalk(0,level,ops[node+1].ival,&numarg);
  1898. X    numeric = 1;
  1899. X    break;
  1900. X    case OSTR:
  1901. X    prewalk(0,level,ops[node+1].ival,&numarg);
  1902. X    break;
  1903. X    case ODEFINED:
  1904. X    case ODELETE:
  1905. X    case OSTAR:
  1906. X    case OVAR:
  1907. X    prewalk(0,level,ops[node+1].ival,&numarg);
  1908. X    if (len == 1) {
  1909. X        if (numit)
  1910. X        numericize(node);
  1911. X    }
  1912. X    else {
  1913. X        prewalk(0,level,ops[node+2].ival,&numarg);
  1914. X    }
  1915. X    break;
  1916. X    case OFLD:
  1917. X    prewalk(0,level,ops[node+1].ival,&numarg);
  1918. X    break;
  1919. X    case OVFLD:
  1920. X    i = ops[node+1].ival;
  1921. X    prewalk(0,level,i,&numarg);
  1922. X    break;
  1923. X    case OJUNK:
  1924. X    goto def;
  1925. X    case OSNEWLINE:
  1926. X    break;
  1927. X    case ONEWLINE:
  1928. X    break;
  1929. X    case OSCOMMENT:
  1930. X    break;
  1931. X    case OCOMMENT:
  1932. X    break;
  1933. X    case OCOMMA:
  1934. X    prewalk(0,level,ops[node+1].ival,&numarg);
  1935. X    prewalk(0,level,ops[node+2].ival,&numarg);
  1936. X    prewalk(0,level,ops[node+3].ival,&numarg);
  1937. X    break;
  1938. X    case OSEMICOLON:
  1939. X    break;
  1940. X    case OSTATES:
  1941. X    prewalk(0,level,ops[node+1].ival,&numarg);
  1942. X    prewalk(0,level,ops[node+2].ival,&numarg);
  1943. X    break;
  1944. X    case OSTATE:
  1945. X    if (len >= 1) {
  1946. X        prewalk(0,level,ops[node+1].ival,&numarg);
  1947. X        if (len >= 2) {
  1948. X        prewalk(0,level,ops[node+2].ival,&numarg);
  1949. X        }
  1950. X    }
  1951. X    break;
  1952. X    case OCLOSE:
  1953. X    prewalk(0,level,ops[node+1].ival,&numarg);
  1954. X    break;
  1955. X    case OPRINTF:
  1956. X    case OPRINT:
  1957. X    if (len == 3) {        /* output redirection */
  1958. X        prewalk(0,level,ops[node+3].ival,&numarg);
  1959. X        prewalk(0,level,ops[node+2].ival,&numarg);
  1960. X    }
  1961. X    prewalk(0+(type==OPRINT),level,ops[node+1].ival,&numarg);
  1962. X    break;
  1963. X    case ORAND:
  1964. X    break;
  1965. X    case OSRAND:
  1966. X    goto maybe0;
  1967. X    case OATAN2:
  1968. X    goto maybe0;
  1969. X    case OSIN:
  1970. X    goto maybe0;
  1971. X    case OCOS:
  1972. X    goto maybe0;
  1973. X    case OSYSTEM:
  1974. X    goto maybe0;
  1975. X    case OLENGTH:
  1976. X    goto maybe0;
  1977. X    case OLOG:
  1978. X    goto maybe0;
  1979. X    case OEXP:
  1980. X    goto maybe0;
  1981. X    case OSQRT:
  1982. X    goto maybe0;
  1983. X    case OINT:
  1984. X      maybe0:
  1985. X    numeric = 1;
  1986. X    if (len > 0)
  1987. X        prewalk(type != OLENGTH && type != OSYSTEM,
  1988. X          level,ops[node+1].ival,&numarg);
  1989. X    break;
  1990. X    case OBREAK:
  1991. X    break;
  1992. X    case ONEXT:
  1993. X    break;
  1994. X    case OEXIT:
  1995. X    if (len == 1) {
  1996. X        prewalk(1,level,ops[node+1].ival,&numarg);
  1997. X    }
  1998. X    break;
  1999. X    case OCONTINUE:
  2000. X    break;
  2001. X    case OREDIR:
  2002. X    goto def;
  2003. X    case OIF:
  2004. X    prewalk(0,level,ops[node+1].ival,&numarg);
  2005. X    prewalk(0,level,ops[node+2].ival,&numarg);
  2006. X    if (len == 3) {
  2007. X        prewalk(0,level,ops[node+3].ival,&numarg);
  2008. X    }
  2009. X    break;
  2010. X    case OWHILE:
  2011. X    prewalk(0,level,ops[node+1].ival,&numarg);
  2012. X    prewalk(0,level,ops[node+2].ival,&numarg);
  2013. X    break;
  2014. X    case OFOR:
  2015. X    prewalk(0,level,ops[node+1].ival,&numarg);
  2016. X    prewalk(0,level,ops[node+2].ival,&numarg);
  2017. X    prewalk(0,level,ops[node+3].ival,&numarg);
  2018. X    prewalk(0,level,ops[node+4].ival,&numarg);
  2019. X    break;
  2020. X    case OFORIN:
  2021. X    prewalk(0,level,ops[node+2].ival,&numarg);
  2022. X    prewalk(0,level,ops[node+1].ival,&numarg);
  2023. X    break;
  2024. X    case OBLOCK:
  2025. X    if (len == 2) {
  2026. X        prewalk(0,level,ops[node+2].ival,&numarg);
  2027. X    }
  2028. X    ++level;
  2029. X    prewalk(0,level,ops[node+1].ival,&numarg);
  2030. X    --level;
  2031. X    break;
  2032. X    default:
  2033. X      def:
  2034. X    if (len) {
  2035. X        if (len > 5)
  2036. X        fatal("Garbage length in prewalk");
  2037. X        prewalk(0,level,ops[node+1].ival,&numarg);
  2038. X        for (i = 2; i<= len; i++) {
  2039. X        prewalk(0,level,ops[node+i].ival,&numarg);
  2040. X        }
  2041. X    }
  2042. X    break;
  2043. X    }
  2044. X    *numericptr = numeric;
  2045. X    return 1;
  2046. X}
  2047. X
  2048. Xnumericize(node)
  2049. Xregister int node;
  2050. X{
  2051. X    register int len;
  2052. X    register int type;
  2053. X    register int i;
  2054. X    STR *tmpstr;
  2055. X    STR *tmp2str;
  2056. X    int numarg;
  2057. X
  2058. X    type = ops[node].ival;
  2059. X    len = type >> 8;
  2060. X    type &= 255;
  2061. X    if (type == OVAR && len == 1) {
  2062. X    tmpstr=walk(0,0,ops[node+1].ival,&numarg,P_MIN);
  2063. X    tmp2str = str_make("1");
  2064. X    hstore(symtab,tmpstr->str_ptr,tmp2str);
  2065. X    }
  2066. X}
  2067. !STUFFY!FUNK!
  2068. echo " "
  2069. echo "End of kit 9 (of 36)"
  2070. cat /dev/null >kit9isdone
  2071. run=''
  2072. config=''
  2073. for iskit in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36; do
  2074.     if test -f kit${iskit}isdone; then
  2075.     run="$run $iskit"
  2076.     else
  2077.     todo="$todo $iskit"
  2078.     fi
  2079. done
  2080. case $todo in
  2081.     '')
  2082.     echo "You have run all your kits.  Please read README and then type Configure."
  2083.     for combo in *:AA; do
  2084.         if test -f "$combo"; then
  2085.         realfile=`basename $combo :AA`
  2086.         cat $realfile:[A-Z][A-Z] >$realfile
  2087.         rm -rf $realfile:[A-Z][A-Z]
  2088.         fi
  2089.     done
  2090.     rm -rf kit*isdone
  2091.     chmod 755 Configure
  2092.     ;;
  2093.     *)  echo "You have run$run."
  2094.     echo "You still need to run$todo."
  2095.     ;;
  2096. esac
  2097. : Someone might mail this, so...
  2098. exit
  2099.  
  2100. exit 0 # Just in case...
  2101. -- 
  2102. Kent Landfield                   INTERNET: kent@sparky.IMD.Sterling.COM
  2103. Sterling Software, IMD           UUCP:     uunet!sparky!kent
  2104. Phone:    (402) 291-8300         FAX:      (402) 291-4362
  2105. Please send comp.sources.misc-related mail to kent@uunet.uu.net.
  2106.