home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume20 / perl3.0 / part04 < prev    next >
Encoding:
Internet Message Format  |  1989-10-29  |  49.6 KB

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