home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume18 / perl / part24 < prev    next >
Encoding:
Internet Message Format  |  1991-04-17  |  49.9 KB

  1. From: lwall@netlabs.com (Larry Wall)
  2. Newsgroups: comp.sources.misc
  3. Subject: v18i042:  perl - The perl programming language, Part24/36
  4. Message-ID: <1991Apr17.185629.2474@sparky.IMD.Sterling.COM>
  5. Date: 17 Apr 91 18:56:29 GMT
  6. Approved: kent@sparky.imd.sterling.com
  7. X-Checksum-Snefru: 28e21801 d82a21aa 374acb88 d6c54df7
  8.  
  9. Submitted-by: Larry Wall <lwall@netlabs.com>
  10. Posting-number: Volume 18, Issue 42
  11. Archive-name: perl/part24
  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 24 (of 36).  If kit 24 is complete, the line"
  21. echo '"'"End of kit 24 (of 36)"'" will echo at the end.'
  22. echo ""
  23. export PATH || (echo "You didn't use sh, you clunch." ; kill $$)
  24. mkdir msdos x2p 2>/dev/null
  25. echo Extracting x2p/a2py.c
  26. sed >x2p/a2py.c <<'!STUFFY!FUNK!' -e 's/X//'
  27. X/* $Header: a2py.c,v 4.0 91/03/20 01:57:26 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:    a2py.c,v $
  35. X * Revision 4.0  91/03/20  01:57:26  lwall
  36. X * 4.0 baseline.
  37. X * 
  38. X */
  39. X
  40. X#ifdef MSDOS
  41. X#include "../patchlev.h"
  42. X#endif
  43. X#include "util.h"
  44. Xchar *index();
  45. X
  46. Xchar *filename;
  47. Xchar *myname;
  48. X
  49. Xint checkers = 0;
  50. XSTR *walk();
  51. X
  52. X#ifdef MSDOS
  53. Xusage()
  54. X{
  55. X    printf("\nThis is the AWK to PERL translator, version 3.0, patchlevel %d\n", PATCHLEVEL);
  56. X    printf("\nUsage: %s [-D<number>] [-F<char>] [-n<fieldlist>] [-<number>] filename\n", myname);
  57. X    printf("\n  -D<number>      sets debugging flags."
  58. X           "\n  -F<character>   the awk script to translate is always invoked with"
  59. X           "\n                  this -F switch."
  60. X           "\n  -n<fieldlist>   specifies the names of the input fields if input does"
  61. X           "\n                  not have to be split into an array."
  62. X           "\n  -<number>       causes a2p to assume that input will always have that"
  63. X           "\n                  many fields.\n");
  64. X    exit(1);
  65. X}
  66. X#endif
  67. Xmain(argc,argv,env)
  68. Xregister int argc;
  69. Xregister char **argv;
  70. Xregister char **env;
  71. X{
  72. X    register STR *str;
  73. X    register char *s;
  74. X    int i;
  75. X    STR *tmpstr;
  76. X
  77. X    myname = argv[0];
  78. X    linestr = str_new(80);
  79. X    str = str_new(0);        /* first used for -I flags */
  80. X    for (argc--,argv++; argc; argc--,argv++) {
  81. X    if (argv[0][0] != '-' || !argv[0][1])
  82. X        break;
  83. X      reswitch:
  84. X    switch (argv[0][1]) {
  85. X#ifdef DEBUGGING
  86. X    case 'D':
  87. X        debug = atoi(argv[0]+2);
  88. X#ifdef YYDEBUG
  89. X        yydebug = (debug & 1);
  90. X#endif
  91. X        break;
  92. X#endif
  93. X    case '0': case '1': case '2': case '3': case '4':
  94. X    case '5': case '6': case '7': case '8': case '9':
  95. X        maxfld = atoi(argv[0]+1);
  96. X        absmaxfld = TRUE;
  97. X        break;
  98. X    case 'F':
  99. X        fswitch = argv[0][2];
  100. X        break;
  101. X    case 'n':
  102. X        namelist = savestr(argv[0]+2);
  103. X        break;
  104. X    case '-':
  105. X        argc--,argv++;
  106. X        goto switch_end;
  107. X    case 0:
  108. X        break;
  109. X    default:
  110. X        fatal("Unrecognized switch: %s\n",argv[0]);
  111. X#ifdef MSDOS
  112. X            usage();
  113. X#endif
  114. X    }
  115. X    }
  116. X  switch_end:
  117. X
  118. X    /* open script */
  119. X
  120. X    if (argv[0] == Nullch) {
  121. X#ifdef MSDOS
  122. X    if ( isatty(fileno(stdin)) )
  123. X        usage();
  124. X#endif
  125. X        argv[0] = "-";
  126. X    }
  127. X    filename = savestr(argv[0]);
  128. X
  129. X    filename = savestr(argv[0]);
  130. X    if (strEQ(filename,"-"))
  131. X    argv[0] = "";
  132. X    if (!*argv[0])
  133. X    rsfp = stdin;
  134. X    else
  135. X    rsfp = fopen(argv[0],"r");
  136. X    if (rsfp == Nullfp)
  137. X    fatal("Awk script \"%s\" doesn't seem to exist.\n",filename);
  138. X
  139. X    /* init tokener */
  140. X
  141. X    bufptr = str_get(linestr);
  142. X    symtab = hnew();
  143. X    curarghash = hnew();
  144. X
  145. X    /* now parse the report spec */
  146. X
  147. X    if (yyparse())
  148. X    fatal("Translation aborted due to syntax errors.\n");
  149. X
  150. X#ifdef DEBUGGING
  151. X    if (debug & 2) {
  152. X    int type, len;
  153. X
  154. X    for (i=1; i<mop;) {
  155. X        type = ops[i].ival;
  156. X        len = type >> 8;
  157. X        type &= 255;
  158. X        printf("%d\t%d\t%d\t%-10s",i++,type,len,opname[type]);
  159. X        if (type == OSTRING)
  160. X        printf("\t\"%s\"\n",ops[i].cval),i++;
  161. X        else {
  162. X        while (len--) {
  163. X            printf("\t%d",ops[i].ival),i++;
  164. X        }
  165. X        putchar('\n');
  166. X        }
  167. X    }
  168. X    }
  169. X    if (debug & 8)
  170. X    dump(root);
  171. X#endif
  172. X
  173. X    /* first pass to look for numeric variables */
  174. X
  175. X    prewalk(0,0,root,&i);
  176. X
  177. X    /* second pass to produce new program */
  178. X
  179. X    tmpstr = walk(0,0,root,&i,P_MIN);
  180. X    str = str_make("#!");
  181. X    str_cat(str, BIN);
  182. X    str_cat(str, "/perl\neval \"exec ");
  183. X    str_cat(str, BIN);
  184. X    str_cat(str, "/perl -S $0 $*\"\n\
  185. X    if $running_under_some_shell;\n\
  186. X            # this emulates #! processing on NIH machines.\n\
  187. X            # (remove #! line above if indigestible)\n\n");
  188. X    str_cat(str,
  189. X      "eval '$'.$1.'$2;' while $ARGV[0] =~ /^([A-Za-z_]+=)(.*)/ && shift;\n");
  190. X    str_cat(str,
  191. X      "            # process any FOO=bar switches\n\n");
  192. X    if (do_opens && opens) {
  193. X    str_scat(str,opens);
  194. X    str_free(opens);
  195. X    str_cat(str,"\n");
  196. X    }
  197. X    str_scat(str,tmpstr);
  198. X    str_free(tmpstr);
  199. X#ifdef DEBUGGING
  200. X    if (!(debug & 16))
  201. X#endif
  202. X    fixup(str);
  203. X    putlines(str);
  204. X    if (checkers) {
  205. X    fprintf(stderr,
  206. X      "Please check my work on the %d line%s I've marked with \"#???\".\n",
  207. X        checkers, checkers == 1 ? "" : "s" );
  208. X    fprintf(stderr,
  209. X      "The operation I've selected may be wrong for the operand types.\n");
  210. X    }
  211. X    exit(0);
  212. X}
  213. X
  214. X#define RETURN(retval) return (bufptr = s,retval)
  215. X#define XTERM(retval) return (expectterm = TRUE,bufptr = s,retval)
  216. X#define XOP(retval) return (expectterm = FALSE,bufptr = s,retval)
  217. X#define ID(x) return (yylval=string(x,0),expectterm = FALSE,bufptr = s,idtype)
  218. X
  219. Xint idtype;
  220. X
  221. Xyylex()
  222. X{
  223. X    register char *s = bufptr;
  224. X    register char *d;
  225. X    register int tmp;
  226. X
  227. X  retry:
  228. X#ifdef YYDEBUG
  229. X    if (yydebug)
  230. X    if (index(s,'\n'))
  231. X        fprintf(stderr,"Tokener at %s",s);
  232. X    else
  233. X        fprintf(stderr,"Tokener at %s\n",s);
  234. X#endif
  235. X    switch (*s) {
  236. X    default:
  237. X    fprintf(stderr,
  238. X        "Unrecognized character %c in file %s line %d--ignoring.\n",
  239. X         *s++,filename,line);
  240. X    goto retry;
  241. X    case '\\':
  242. X    case 0:
  243. X    s = str_get(linestr);
  244. X    *s = '\0';
  245. X    if (!rsfp)
  246. X        RETURN(0);
  247. X    line++;
  248. X    if ((s = str_gets(linestr, rsfp)) == Nullch) {
  249. X        if (rsfp != stdin)
  250. X        fclose(rsfp);
  251. X        rsfp = Nullfp;
  252. X        s = str_get(linestr);
  253. X        RETURN(0);
  254. X    }
  255. X    goto retry;
  256. X    case ' ': case '\t':
  257. X    s++;
  258. X    goto retry;
  259. X    case '\n':
  260. X    *s = '\0';
  261. X    XTERM(NEWLINE);
  262. X    case '#':
  263. X    yylval = string(s,0);
  264. X    *s = '\0';
  265. X    XTERM(COMMENT);
  266. X    case ';':
  267. X    tmp = *s++;
  268. X    if (*s == '\n') {
  269. X        s++;
  270. X        XTERM(SEMINEW);
  271. X    }
  272. X    XTERM(tmp);
  273. X    case '(':
  274. X    tmp = *s++;
  275. X    XTERM(tmp);
  276. X    case '{':
  277. X    case '[':
  278. X    case ')':
  279. X    case ']':
  280. X    case '?':
  281. X    case ':':
  282. X    tmp = *s++;
  283. X    XOP(tmp);
  284. X    case 127:
  285. X    s++;
  286. X    XTERM('}');
  287. X    case '}':
  288. X    for (d = s + 1; isspace(*d); d++) ;
  289. X    if (!*d)
  290. X        s = d - 1;
  291. X    *s = 127;
  292. X    XTERM(';');
  293. X    case ',':
  294. X    tmp = *s++;
  295. X    XTERM(tmp);
  296. X    case '~':
  297. X    s++;
  298. X    yylval = string("~",1);
  299. X    XTERM(MATCHOP);
  300. X    case '+':
  301. X    case '-':
  302. X    if (s[1] == *s) {
  303. X        s++;
  304. X        if (*s++ == '+')
  305. X        XTERM(INCR);
  306. X        else
  307. X        XTERM(DECR);
  308. X    }
  309. X    /* FALL THROUGH */
  310. X    case '*':
  311. X    case '%':
  312. X    case '^':
  313. X    tmp = *s++;
  314. X    if (*s == '=') {
  315. X        if (tmp == '^')
  316. X        yylval = string("**=",3);
  317. X        else
  318. X        yylval = string(s-1,2);
  319. X        s++;
  320. X        XTERM(ASGNOP);
  321. X    }
  322. X    XTERM(tmp);
  323. X    case '&':
  324. X    s++;
  325. X    tmp = *s++;
  326. X    if (tmp == '&')
  327. X        XTERM(ANDAND);
  328. X    s--;
  329. X    XTERM('&');
  330. X    case '|':
  331. X    s++;
  332. X    tmp = *s++;
  333. X    if (tmp == '|')
  334. X        XTERM(OROR);
  335. X    s--;
  336. X    while (*s == ' ' || *s == '\t')
  337. X        s++;
  338. X    if (strnEQ(s,"getline",7))
  339. X        XTERM('p');
  340. X    else
  341. X        XTERM('|');
  342. X    case '=':
  343. X    s++;
  344. X    tmp = *s++;
  345. X    if (tmp == '=') {
  346. X        yylval = string("==",2);
  347. X        XTERM(RELOP);
  348. X    }
  349. X    s--;
  350. X    yylval = string("=",1);
  351. X    XTERM(ASGNOP);
  352. X    case '!':
  353. X    s++;
  354. X    tmp = *s++;
  355. X    if (tmp == '=') {
  356. X        yylval = string("!=",2);
  357. X        XTERM(RELOP);
  358. X    }
  359. X    if (tmp == '~') {
  360. X        yylval = string("!~",2);
  361. X        XTERM(MATCHOP);
  362. X    }
  363. X    s--;
  364. X    XTERM(NOT);
  365. X    case '<':
  366. X    s++;
  367. X    tmp = *s++;
  368. X    if (tmp == '=') {
  369. X        yylval = string("<=",2);
  370. X        XTERM(RELOP);
  371. X    }
  372. X    s--;
  373. X    XTERM('<');
  374. X    case '>':
  375. X    s++;
  376. X    tmp = *s++;
  377. X    if (tmp == '>') {
  378. X        yylval = string(">>",2);
  379. X        XTERM(GRGR);
  380. X    }
  381. X    if (tmp == '=') {
  382. X        yylval = string(">=",2);
  383. X        XTERM(RELOP);
  384. X    }
  385. X    s--;
  386. X    XTERM('>');
  387. X
  388. X#define SNARFWORD \
  389. X    d = tokenbuf; \
  390. X    while (isalpha(*s) || isdigit(*s) || *s == '_') \
  391. X        *d++ = *s++; \
  392. X    *d = '\0'; \
  393. X    d = tokenbuf; \
  394. X    if (*s == '(') \
  395. X        idtype = USERFUN; \
  396. X    else \
  397. X        idtype = VAR;
  398. X
  399. X    case '$':
  400. X    s++;
  401. X    if (*s == '0') {
  402. X        s++;
  403. X        do_chop = TRUE;
  404. X        need_entire = TRUE;
  405. X        idtype = VAR;
  406. X        ID("0");
  407. X    }
  408. X    do_split = TRUE;
  409. X    if (isdigit(*s)) {
  410. X        for (d = s; isdigit(*s); s++) ;
  411. X        yylval = string(d,s-d);
  412. X        tmp = atoi(d);
  413. X        if (tmp > maxfld)
  414. X        maxfld = tmp;
  415. X        XOP(FIELD);
  416. X    }
  417. X    split_to_array = set_array_base = TRUE;
  418. X    XOP(VFIELD);
  419. X
  420. X    case '/':            /* may either be division or pattern */
  421. X    if (expectterm) {
  422. X        s = scanpat(s);
  423. X        XTERM(REGEX);
  424. X    }
  425. X    tmp = *s++;
  426. X    if (*s == '=') {
  427. X        yylval = string("/=",2);
  428. X        s++;
  429. X        XTERM(ASGNOP);
  430. X    }
  431. X    XTERM(tmp);
  432. X
  433. X    case '0': case '1': case '2': case '3': case '4':
  434. X    case '5': case '6': case '7': case '8': case '9': case '.':
  435. X    s = scannum(s);
  436. X    XOP(NUMBER);
  437. X    case '"':
  438. X    s++;
  439. X    s = cpy2(tokenbuf,s,s[-1]);
  440. X    if (!*s)
  441. X        fatal("String not terminated:\n%s",str_get(linestr));
  442. X    s++;
  443. X    yylval = string(tokenbuf,0);
  444. X    XOP(STRING);
  445. X
  446. X    case 'a': case 'A':
  447. X    SNARFWORD;
  448. X    if (strEQ(d,"ARGC"))
  449. X        set_array_base = TRUE;
  450. X    if (strEQ(d,"ARGV")) {
  451. X        yylval=numary(string("ARGV",0));
  452. X        XOP(VAR);
  453. X    }
  454. X    if (strEQ(d,"atan2")) {
  455. X        yylval = OATAN2;
  456. X        XTERM(FUNN);
  457. X    }
  458. X    ID(d);
  459. X    case 'b': case 'B':
  460. X    SNARFWORD;
  461. X    if (strEQ(d,"break"))
  462. X        XTERM(BREAK);
  463. X    if (strEQ(d,"BEGIN"))
  464. X        XTERM(BEGIN);
  465. X    ID(d);
  466. X    case 'c': case 'C':
  467. X    SNARFWORD;
  468. X    if (strEQ(d,"continue"))
  469. X        XTERM(CONTINUE);
  470. X    if (strEQ(d,"cos")) {
  471. X        yylval = OCOS;
  472. X        XTERM(FUN1);
  473. X    }
  474. X    if (strEQ(d,"close")) {
  475. X        do_fancy_opens = 1;
  476. X        yylval = OCLOSE;
  477. X        XTERM(FUN1);
  478. X    }
  479. X    if (strEQ(d,"chdir"))
  480. X        *d = toupper(*d);
  481. X    else if (strEQ(d,"crypt"))
  482. X        *d = toupper(*d);
  483. X    else if (strEQ(d,"chop"))
  484. X        *d = toupper(*d);
  485. X    else if (strEQ(d,"chmod"))
  486. X        *d = toupper(*d);
  487. X    else if (strEQ(d,"chown"))
  488. X        *d = toupper(*d);
  489. X    ID(d);
  490. X    case 'd': case 'D':
  491. X    SNARFWORD;
  492. X    if (strEQ(d,"do"))
  493. X        XTERM(DO);
  494. X    if (strEQ(d,"delete"))
  495. X        XTERM(DELETE);
  496. X    if (strEQ(d,"die"))
  497. X        *d = toupper(*d);
  498. X    ID(d);
  499. X    case 'e': case 'E':
  500. X    SNARFWORD;
  501. X    if (strEQ(d,"END"))
  502. X        XTERM(END);
  503. X    if (strEQ(d,"else"))
  504. X        XTERM(ELSE);
  505. X    if (strEQ(d,"exit")) {
  506. X        saw_line_op = TRUE;
  507. X        XTERM(EXIT);
  508. X    }
  509. X    if (strEQ(d,"exp")) {
  510. X        yylval = OEXP;
  511. X        XTERM(FUN1);
  512. X    }
  513. X    if (strEQ(d,"elsif"))
  514. X        *d = toupper(*d);
  515. X    else if (strEQ(d,"eq"))
  516. X        *d = toupper(*d);
  517. X    else if (strEQ(d,"eval"))
  518. X        *d = toupper(*d);
  519. X    else if (strEQ(d,"eof"))
  520. X        *d = toupper(*d);
  521. X    else if (strEQ(d,"each"))
  522. X        *d = toupper(*d);
  523. X    else if (strEQ(d,"exec"))
  524. X        *d = toupper(*d);
  525. X    ID(d);
  526. X    case 'f': case 'F':
  527. X    SNARFWORD;
  528. X    if (strEQ(d,"FS")) {
  529. X        saw_FS++;
  530. X        if (saw_FS == 1 && in_begin) {
  531. X        for (d = s; *d && isspace(*d); d++) ;
  532. X        if (*d == '=') {
  533. X            for (d++; *d && isspace(*d); d++) ;
  534. X            if (*d == '"' && d[2] == '"')
  535. X            const_FS = d[1];
  536. X        }
  537. X        }
  538. X        ID(tokenbuf);
  539. X    }
  540. X    if (strEQ(d,"for"))
  541. X        XTERM(FOR);
  542. X    else if (strEQ(d,"function"))
  543. X        XTERM(FUNCTION);
  544. X    if (strEQ(d,"FILENAME"))
  545. X        d = "ARGV";
  546. X    if (strEQ(d,"foreach"))
  547. X        *d = toupper(*d);
  548. X    else if (strEQ(d,"format"))
  549. X        *d = toupper(*d);
  550. X    else if (strEQ(d,"fork"))
  551. X        *d = toupper(*d);
  552. X    else if (strEQ(d,"fh"))
  553. X        *d = toupper(*d);
  554. X    ID(d);
  555. X    case 'g': case 'G':
  556. X    SNARFWORD;
  557. X    if (strEQ(d,"getline"))
  558. X        XTERM(GETLINE);
  559. X    if (strEQ(d,"gsub"))
  560. X        XTERM(GSUB);
  561. X    if (strEQ(d,"ge"))
  562. X        *d = toupper(*d);
  563. X    else if (strEQ(d,"gt"))
  564. X        *d = toupper(*d);
  565. X    else if (strEQ(d,"goto"))
  566. X        *d = toupper(*d);
  567. X    else if (strEQ(d,"gmtime"))
  568. X        *d = toupper(*d);
  569. X    ID(d);
  570. X    case 'h': case 'H':
  571. X    SNARFWORD;
  572. X    if (strEQ(d,"hex"))
  573. X        *d = toupper(*d);
  574. X    ID(d);
  575. X    case 'i': case 'I':
  576. X    SNARFWORD;
  577. X    if (strEQ(d,"if"))
  578. X        XTERM(IF);
  579. X    if (strEQ(d,"in"))
  580. X        XTERM(IN);
  581. X    if (strEQ(d,"index")) {
  582. X        set_array_base = TRUE;
  583. X        XTERM(INDEX);
  584. X    }
  585. X    if (strEQ(d,"int")) {
  586. X        yylval = OINT;
  587. X        XTERM(FUN1);
  588. X    }
  589. X    ID(d);
  590. X    case 'j': case 'J':
  591. X    SNARFWORD;
  592. X    if (strEQ(d,"join"))
  593. X        *d = toupper(*d);
  594. X    ID(d);
  595. X    case 'k': case 'K':
  596. X    SNARFWORD;
  597. X    if (strEQ(d,"keys"))
  598. X        *d = toupper(*d);
  599. X    else if (strEQ(d,"kill"))
  600. X        *d = toupper(*d);
  601. X    ID(d);
  602. X    case 'l': case 'L':
  603. X    SNARFWORD;
  604. X    if (strEQ(d,"length")) {
  605. X        yylval = OLENGTH;
  606. X        XTERM(FUN1);
  607. X    }
  608. X    if (strEQ(d,"log")) {
  609. X        yylval = OLOG;
  610. X        XTERM(FUN1);
  611. X    }
  612. X    if (strEQ(d,"last"))
  613. X        *d = toupper(*d);
  614. X    else if (strEQ(d,"local"))
  615. X        *d = toupper(*d);
  616. X    else if (strEQ(d,"lt"))
  617. X        *d = toupper(*d);
  618. X    else if (strEQ(d,"le"))
  619. X        *d = toupper(*d);
  620. X    else if (strEQ(d,"locatime"))
  621. X        *d = toupper(*d);
  622. X    else if (strEQ(d,"link"))
  623. X        *d = toupper(*d);
  624. X    ID(d);
  625. X    case 'm': case 'M':
  626. X    SNARFWORD;
  627. X    if (strEQ(d,"match")) {
  628. X        set_array_base = TRUE;
  629. X        XTERM(MATCH);
  630. X    }
  631. X    if (strEQ(d,"m"))
  632. X        *d = toupper(*d);
  633. X    ID(d);
  634. X    case 'n': case 'N':
  635. X    SNARFWORD;
  636. X    if (strEQ(d,"NF"))
  637. X        do_chop = do_split = split_to_array = set_array_base = TRUE;
  638. X    if (strEQ(d,"next")) {
  639. X        saw_line_op = TRUE;
  640. X        XTERM(NEXT);
  641. X    }
  642. X    if (strEQ(d,"ne"))
  643. X        *d = toupper(*d);
  644. X    ID(d);
  645. X    case 'o': case 'O':
  646. X    SNARFWORD;
  647. X    if (strEQ(d,"ORS")) {
  648. X        saw_ORS = TRUE;
  649. X        d = "\\";
  650. X    }
  651. X    if (strEQ(d,"OFS")) {
  652. X        saw_OFS = TRUE;
  653. X        d = ",";
  654. X    }
  655. X    if (strEQ(d,"OFMT")) {
  656. X        d = "#";
  657. X    }
  658. X    if (strEQ(d,"open"))
  659. X        *d = toupper(*d);
  660. X    else if (strEQ(d,"ord"))
  661. X        *d = toupper(*d);
  662. X    else if (strEQ(d,"oct"))
  663. X        *d = toupper(*d);
  664. X    ID(d);
  665. X    case 'p': case 'P':
  666. X    SNARFWORD;
  667. X    if (strEQ(d,"print")) {
  668. X        XTERM(PRINT);
  669. X    }
  670. X    if (strEQ(d,"printf")) {
  671. X        XTERM(PRINTF);
  672. X    }
  673. X    if (strEQ(d,"push"))
  674. X        *d = toupper(*d);
  675. X    else if (strEQ(d,"pop"))
  676. X        *d = toupper(*d);
  677. X    ID(d);
  678. X    case 'q': case 'Q':
  679. X    SNARFWORD;
  680. X    ID(d);
  681. X    case 'r': case 'R':
  682. X    SNARFWORD;
  683. X    if (strEQ(d,"RS")) {
  684. X        d = "/";
  685. X        saw_RS = TRUE;
  686. X    }
  687. X    if (strEQ(d,"rand")) {
  688. X        yylval = ORAND;
  689. X        XTERM(FUN1);
  690. X    }
  691. X    if (strEQ(d,"return"))
  692. X        XTERM(RET);
  693. X    if (strEQ(d,"reset"))
  694. X        *d = toupper(*d);
  695. X    else if (strEQ(d,"redo"))
  696. X        *d = toupper(*d);
  697. X    else if (strEQ(d,"rename"))
  698. X        *d = toupper(*d);
  699. X    ID(d);
  700. X    case 's': case 'S':
  701. X    SNARFWORD;
  702. X    if (strEQ(d,"split")) {
  703. X        set_array_base = TRUE;
  704. X        XOP(SPLIT);
  705. X    }
  706. X    if (strEQ(d,"substr")) {
  707. X        set_array_base = TRUE;
  708. X        XTERM(SUBSTR);
  709. X    }
  710. X    if (strEQ(d,"sub"))
  711. X        XTERM(SUB);
  712. X    if (strEQ(d,"sprintf"))
  713. X        XTERM(SPRINTF);
  714. X    if (strEQ(d,"sqrt")) {
  715. X        yylval = OSQRT;
  716. X        XTERM(FUN1);
  717. X    }
  718. X    if (strEQ(d,"SUBSEP")) {
  719. X        d = ";";
  720. X    }
  721. X    if (strEQ(d,"sin")) {
  722. X        yylval = OSIN;
  723. X        XTERM(FUN1);
  724. X    }
  725. X    if (strEQ(d,"srand")) {
  726. X        yylval = OSRAND;
  727. X        XTERM(FUN1);
  728. X    }
  729. X    if (strEQ(d,"system")) {
  730. X        yylval = OSYSTEM;
  731. X        XTERM(FUN1);
  732. X    }
  733. X    if (strEQ(d,"s"))
  734. X        *d = toupper(*d);
  735. X    else if (strEQ(d,"shift"))
  736. X        *d = toupper(*d);
  737. X    else if (strEQ(d,"select"))
  738. X        *d = toupper(*d);
  739. X    else if (strEQ(d,"seek"))
  740. X        *d = toupper(*d);
  741. X    else if (strEQ(d,"stat"))
  742. X        *d = toupper(*d);
  743. X    else if (strEQ(d,"study"))
  744. X        *d = toupper(*d);
  745. X    else if (strEQ(d,"sleep"))
  746. X        *d = toupper(*d);
  747. X    else if (strEQ(d,"symlink"))
  748. X        *d = toupper(*d);
  749. X    else if (strEQ(d,"sort"))
  750. X        *d = toupper(*d);
  751. X    ID(d);
  752. X    case 't': case 'T':
  753. X    SNARFWORD;
  754. X    if (strEQ(d,"tr"))
  755. X        *d = toupper(*d);
  756. X    else if (strEQ(d,"tell"))
  757. X        *d = toupper(*d);
  758. X    else if (strEQ(d,"time"))
  759. X        *d = toupper(*d);
  760. X    else if (strEQ(d,"times"))
  761. X        *d = toupper(*d);
  762. X    ID(d);
  763. X    case 'u': case 'U':
  764. X    SNARFWORD;
  765. X    if (strEQ(d,"until"))
  766. X        *d = toupper(*d);
  767. X    else if (strEQ(d,"unless"))
  768. X        *d = toupper(*d);
  769. X    else if (strEQ(d,"umask"))
  770. X        *d = toupper(*d);
  771. X    else if (strEQ(d,"unshift"))
  772. X        *d = toupper(*d);
  773. X    else if (strEQ(d,"unlink"))
  774. X        *d = toupper(*d);
  775. X    else if (strEQ(d,"utime"))
  776. X        *d = toupper(*d);
  777. X    ID(d);
  778. X    case 'v': case 'V':
  779. X    SNARFWORD;
  780. X    if (strEQ(d,"values"))
  781. X        *d = toupper(*d);
  782. X    ID(d);
  783. X    case 'w': case 'W':
  784. X    SNARFWORD;
  785. X    if (strEQ(d,"while"))
  786. X        XTERM(WHILE);
  787. X    if (strEQ(d,"write"))
  788. X        *d = toupper(*d);
  789. X    else if (strEQ(d,"wait"))
  790. X        *d = toupper(*d);
  791. X    ID(d);
  792. X    case 'x': case 'X':
  793. X    SNARFWORD;
  794. X    if (strEQ(d,"x"))
  795. X        *d = toupper(*d);
  796. X    ID(d);
  797. X    case 'y': case 'Y':
  798. X    SNARFWORD;
  799. X    if (strEQ(d,"y"))
  800. X        *d = toupper(*d);
  801. X    ID(d);
  802. X    case 'z': case 'Z':
  803. X    SNARFWORD;
  804. X    ID(d);
  805. X    }
  806. X}
  807. X
  808. Xchar *
  809. Xscanpat(s)
  810. Xregister char *s;
  811. X{
  812. X    register char *d;
  813. X
  814. X    switch (*s++) {
  815. X    case '/':
  816. X    break;
  817. X    default:
  818. X    fatal("Search pattern not found:\n%s",str_get(linestr));
  819. X    }
  820. X
  821. X    d = tokenbuf;
  822. X    for (; *s; s++,d++) {
  823. X    if (*s == '\\') {
  824. X        if (s[1] == '/')
  825. X        *d++ = *s++;
  826. X        else if (s[1] == '\\')
  827. X        *d++ = *s++;
  828. X    }
  829. X    else if (*s == '[') {
  830. X        *d++ = *s++;
  831. X        do {
  832. X        if (*s == '\\' && s[1])
  833. X            *d++ = *s++;
  834. X        if (*s == '/' || (*s == '-' && s[1] == ']'))
  835. X            *d++ = '\\';
  836. X        *d++ = *s++;
  837. X        } while (*s && *s != ']');
  838. X    }
  839. X    else if (*s == '/')
  840. X        break;
  841. X    *d = *s;
  842. X    }
  843. X    *d = '\0';
  844. X
  845. X    if (!*s)
  846. X    fatal("Search pattern not terminated:\n%s",str_get(linestr));
  847. X    s++;
  848. X    yylval = string(tokenbuf,0);
  849. X    return s;
  850. X}
  851. X
  852. Xyyerror(s)
  853. Xchar *s;
  854. X{
  855. X    fprintf(stderr,"%s in file %s at line %d\n",
  856. X      s,filename,line);
  857. X}
  858. X
  859. Xchar *
  860. Xscannum(s)
  861. Xregister char *s;
  862. X{
  863. X    register char *d;
  864. X
  865. X    switch (*s) {
  866. X    case '1': case '2': case '3': case '4': case '5':
  867. X    case '6': case '7': case '8': case '9': case '0' : case '.':
  868. X    d = tokenbuf;
  869. X    while (isdigit(*s)) {
  870. X        *d++ = *s++;
  871. X    }
  872. X    if (*s == '.' && index("0123456789eE",s[1])) {
  873. X        *d++ = *s++;
  874. X        while (isdigit(*s)) {
  875. X        *d++ = *s++;
  876. X        }
  877. X    }
  878. X    if (index("eE",*s) && index("+-0123456789",s[1])) {
  879. X        *d++ = *s++;
  880. X        if (*s == '+' || *s == '-')
  881. X        *d++ = *s++;
  882. X        while (isdigit(*s))
  883. X        *d++ = *s++;
  884. X    }
  885. X    *d = '\0';
  886. X    yylval = string(tokenbuf,0);
  887. X    break;
  888. X    }
  889. X    return s;
  890. X}
  891. X
  892. Xstring(ptr,len)
  893. Xchar *ptr;
  894. X{
  895. X    int retval = mop;
  896. X
  897. X    ops[mop++].ival = OSTRING + (1<<8);
  898. X    if (!len)
  899. X    len = strlen(ptr);
  900. X    ops[mop].cval = safemalloc(len+1);
  901. X    strncpy(ops[mop].cval,ptr,len);
  902. X    ops[mop++].cval[len] = '\0';
  903. X    if (mop >= OPSMAX)
  904. X    fatal("Recompile a2p with larger OPSMAX\n");
  905. X    return retval;
  906. X}
  907. X
  908. Xoper0(type)
  909. Xint type;
  910. X{
  911. X    int retval = mop;
  912. X
  913. X    if (type > 255)
  914. X    fatal("type > 255 (%d)\n",type);
  915. X    ops[mop++].ival = type;
  916. X    if (mop >= OPSMAX)
  917. X    fatal("Recompile a2p with larger OPSMAX\n");
  918. X    return retval;
  919. X}
  920. X
  921. Xoper1(type,arg1)
  922. Xint type;
  923. Xint arg1;
  924. X{
  925. X    int retval = mop;
  926. X
  927. X    if (type > 255)
  928. X    fatal("type > 255 (%d)\n",type);
  929. X    ops[mop++].ival = type + (1<<8);
  930. X    ops[mop++].ival = arg1;
  931. X    if (mop >= OPSMAX)
  932. X    fatal("Recompile a2p with larger OPSMAX\n");
  933. X    return retval;
  934. X}
  935. X
  936. Xoper2(type,arg1,arg2)
  937. Xint type;
  938. Xint arg1;
  939. Xint arg2;
  940. X{
  941. X    int retval = mop;
  942. X
  943. X    if (type > 255)
  944. X    fatal("type > 255 (%d)\n",type);
  945. X    ops[mop++].ival = type + (2<<8);
  946. X    ops[mop++].ival = arg1;
  947. X    ops[mop++].ival = arg2;
  948. X    if (mop >= OPSMAX)
  949. X    fatal("Recompile a2p with larger OPSMAX\n");
  950. X    return retval;
  951. X}
  952. X
  953. Xoper3(type,arg1,arg2,arg3)
  954. Xint type;
  955. Xint arg1;
  956. Xint arg2;
  957. Xint arg3;
  958. X{
  959. X    int retval = mop;
  960. X
  961. X    if (type > 255)
  962. X    fatal("type > 255 (%d)\n",type);
  963. X    ops[mop++].ival = type + (3<<8);
  964. X    ops[mop++].ival = arg1;
  965. X    ops[mop++].ival = arg2;
  966. X    ops[mop++].ival = arg3;
  967. X    if (mop >= OPSMAX)
  968. X    fatal("Recompile a2p with larger OPSMAX\n");
  969. X    return retval;
  970. X}
  971. X
  972. Xoper4(type,arg1,arg2,arg3,arg4)
  973. Xint type;
  974. Xint arg1;
  975. Xint arg2;
  976. Xint arg3;
  977. Xint arg4;
  978. X{
  979. X    int retval = mop;
  980. X
  981. X    if (type > 255)
  982. X    fatal("type > 255 (%d)\n",type);
  983. X    ops[mop++].ival = type + (4<<8);
  984. X    ops[mop++].ival = arg1;
  985. X    ops[mop++].ival = arg2;
  986. X    ops[mop++].ival = arg3;
  987. X    ops[mop++].ival = arg4;
  988. X    if (mop >= OPSMAX)
  989. X    fatal("Recompile a2p with larger OPSMAX\n");
  990. X    return retval;
  991. X}
  992. X
  993. Xoper5(type,arg1,arg2,arg3,arg4,arg5)
  994. Xint type;
  995. Xint arg1;
  996. Xint arg2;
  997. Xint arg3;
  998. Xint arg4;
  999. Xint arg5;
  1000. X{
  1001. X    int retval = mop;
  1002. X
  1003. X    if (type > 255)
  1004. X    fatal("type > 255 (%d)\n",type);
  1005. X    ops[mop++].ival = type + (5<<8);
  1006. X    ops[mop++].ival = arg1;
  1007. X    ops[mop++].ival = arg2;
  1008. X    ops[mop++].ival = arg3;
  1009. X    ops[mop++].ival = arg4;
  1010. X    ops[mop++].ival = arg5;
  1011. X    if (mop >= OPSMAX)
  1012. X    fatal("Recompile a2p with larger OPSMAX\n");
  1013. X    return retval;
  1014. X}
  1015. X
  1016. Xint depth = 0;
  1017. X
  1018. Xdump(branch)
  1019. Xint branch;
  1020. X{
  1021. X    register int type;
  1022. X    register int len;
  1023. X    register int i;
  1024. X
  1025. X    type = ops[branch].ival;
  1026. X    len = type >> 8;
  1027. X    type &= 255;
  1028. X    for (i=depth; i; i--)
  1029. X    printf(" ");
  1030. X    if (type == OSTRING) {
  1031. X    printf("%-5d\"%s\"\n",branch,ops[branch+1].cval);
  1032. X    }
  1033. X    else {
  1034. X    printf("(%-5d%s %d\n",branch,opname[type],len);
  1035. X    depth++;
  1036. X    for (i=1; i<=len; i++)
  1037. X        dump(ops[branch+i].ival);
  1038. X    depth--;
  1039. X    for (i=depth; i; i--)
  1040. X        printf(" ");
  1041. X    printf(")\n");
  1042. X    }
  1043. X}
  1044. X
  1045. Xbl(arg,maybe)
  1046. Xint arg;
  1047. Xint maybe;
  1048. X{
  1049. X    if (!arg)
  1050. X    return 0;
  1051. X    else if ((ops[arg].ival & 255) != OBLOCK)
  1052. X    return oper2(OBLOCK,arg,maybe);
  1053. X    else if ((ops[arg].ival >> 8) < 2)
  1054. X    return oper2(OBLOCK,ops[arg+1].ival,maybe);
  1055. X    else
  1056. X    return arg;
  1057. X}
  1058. X
  1059. Xfixup(str)
  1060. XSTR *str;
  1061. X{
  1062. X    register char *s;
  1063. X    register char *t;
  1064. X
  1065. X    for (s = str->str_ptr; *s; s++) {
  1066. X    if (*s == ';' && s[1] == ' ' && s[2] == '\n') {
  1067. X        strcpy(s+1,s+2);
  1068. X        s++;
  1069. X    }
  1070. X    else if (*s == '\n') {
  1071. X        for (t = s+1; isspace(*t & 127); t++) ;
  1072. X        t--;
  1073. X        while (isspace(*t & 127) && *t != '\n') t--;
  1074. X        if (*t == '\n' && t-s > 1) {
  1075. X        if (s[-1] == '{')
  1076. X            s--;
  1077. X        strcpy(s+1,t);
  1078. X        }
  1079. X        s++;
  1080. X    }
  1081. X    }
  1082. X}
  1083. X
  1084. Xputlines(str)
  1085. XSTR *str;
  1086. X{
  1087. X    register char *d, *s, *t, *e;
  1088. X    register int pos, newpos;
  1089. X
  1090. X    d = tokenbuf;
  1091. X    pos = 0;
  1092. X    for (s = str->str_ptr; *s; s++) {
  1093. X    *d++ = *s;
  1094. X    pos++;
  1095. X    if (*s == '\n') {
  1096. X        *d = '\0';
  1097. X        d = tokenbuf;
  1098. X        pos = 0;
  1099. X        putone();
  1100. X    }
  1101. X    else if (*s == '\t')
  1102. X        pos += 7;
  1103. X    if (pos > 78) {        /* split a long line? */
  1104. X        *d-- = '\0';
  1105. X        newpos = 0;
  1106. X        for (t = tokenbuf; isspace(*t & 127); t++) {
  1107. X        if (*t == '\t')
  1108. X            newpos += 8;
  1109. X        else
  1110. X            newpos += 1;
  1111. X        }
  1112. X        e = d;
  1113. X        while (d > tokenbuf && (*d != ' ' || d[-1] != ';'))
  1114. X        d--;
  1115. X        if (d < t+10) {
  1116. X        d = e;
  1117. X        while (d > tokenbuf &&
  1118. X          (*d != ' ' || d[-1] != '|' || d[-2] != '|') )
  1119. X            d--;
  1120. X        }
  1121. X        if (d < t+10) {
  1122. X        d = e;
  1123. X        while (d > tokenbuf &&
  1124. X          (*d != ' ' || d[-1] != '&' || d[-2] != '&') )
  1125. X            d--;
  1126. X        }
  1127. X        if (d < t+10) {
  1128. X        d = e;
  1129. X        while (d > tokenbuf && (*d != ' ' || d[-1] != ','))
  1130. X            d--;
  1131. X        }
  1132. X        if (d < t+10) {
  1133. X        d = e;
  1134. X        while (d > tokenbuf && *d != ' ')
  1135. X            d--;
  1136. X        }
  1137. X        if (d > t+3) {
  1138. X                char save[2048];
  1139. X                strcpy(save, d);
  1140. X        *d = '\n';
  1141. X                d[1] = '\0';
  1142. X        putone();
  1143. X        putchar('\n');
  1144. X        if (d[-1] != ';' && !(newpos % 4)) {
  1145. X            *t++ = ' ';
  1146. X            *t++ = ' ';
  1147. X            newpos += 2;
  1148. X        }
  1149. X        strcpy(t,save+1);
  1150. X        newpos += strlen(t);
  1151. X        d = t + strlen(t);
  1152. X        pos = newpos;
  1153. X        }
  1154. X        else
  1155. X        d = e + 1;
  1156. X    }
  1157. X    }
  1158. X}
  1159. X
  1160. Xputone()
  1161. X{
  1162. X    register char *t;
  1163. X
  1164. X    for (t = tokenbuf; *t; t++) {
  1165. X    *t &= 127;
  1166. X    if (*t == 127) {
  1167. X        *t = ' ';
  1168. X        strcpy(t+strlen(t)-1, "\t#???\n");
  1169. X        checkers++;
  1170. X    }
  1171. X    }
  1172. X    t = tokenbuf;
  1173. X    if (*t == '#') {
  1174. X    if (strnEQ(t,"#!/bin/awk",10) || strnEQ(t,"#! /bin/awk",11))
  1175. X        return;
  1176. X    if (strnEQ(t,"#!/usr/bin/awk",14) || strnEQ(t,"#! /usr/bin/awk",15))
  1177. X        return;
  1178. X    }
  1179. X    fputs(tokenbuf,stdout);
  1180. X}
  1181. X
  1182. Xnumary(arg)
  1183. Xint arg;
  1184. X{
  1185. X    STR *key;
  1186. X    int dummy;
  1187. X
  1188. X    key = walk(0,0,arg,&dummy,P_MIN);
  1189. X    str_cat(key,"[]");
  1190. X    hstore(symtab,key->str_ptr,str_make("1"));
  1191. X    str_free(key);
  1192. X    set_array_base = TRUE;
  1193. X    return arg;
  1194. X}
  1195. X
  1196. Xrememberargs(arg)
  1197. Xint arg;
  1198. X{
  1199. X    int type;
  1200. X    STR *str;
  1201. X
  1202. X    if (!arg)
  1203. X    return arg;
  1204. X    type = ops[arg].ival & 255;
  1205. X    if (type == OCOMMA) {
  1206. X    rememberargs(ops[arg+1].ival);
  1207. X    rememberargs(ops[arg+3].ival);
  1208. X    }
  1209. X    else if (type == OVAR) {
  1210. X    str = str_new(0);
  1211. X    hstore(curarghash,ops[ops[arg+1].ival+1].cval,str);
  1212. X    }
  1213. X    else
  1214. X    fatal("panic: unknown argument type %d, line %d\n",type,line);
  1215. X    return arg;
  1216. X}
  1217. X
  1218. Xaryrefarg(arg)
  1219. Xint arg;
  1220. X{
  1221. X    int type = ops[arg].ival & 255;
  1222. X    STR *str;
  1223. X
  1224. X    if (type != OSTRING)
  1225. X    fatal("panic: aryrefarg %d, line %d\n",type,line);
  1226. X    str = hfetch(curarghash,ops[arg+1].cval);
  1227. X    if (str)
  1228. X    str_set(str,"*");
  1229. X    return arg;
  1230. X}
  1231. X
  1232. Xfixfargs(name,arg,prevargs)
  1233. Xint name;
  1234. Xint arg;
  1235. Xint prevargs;
  1236. X{
  1237. X    int type;
  1238. X    STR *str;
  1239. X    int numargs;
  1240. X
  1241. X    if (!arg)
  1242. X    return prevargs;
  1243. X    type = ops[arg].ival & 255;
  1244. X    if (type == OCOMMA) {
  1245. X    numargs = fixfargs(name,ops[arg+1].ival,prevargs);
  1246. X    numargs = fixfargs(name,ops[arg+3].ival,numargs);
  1247. X    }
  1248. X    else if (type == OVAR) {
  1249. X    str = hfetch(curarghash,ops[ops[arg+1].ival+1].cval);
  1250. X    if (strEQ(str_get(str),"*")) {
  1251. X        char tmpbuf[128];
  1252. X
  1253. X        str_set(str,"");        /* in case another routine has this */
  1254. X        ops[arg].ival &= ~255;
  1255. X        ops[arg].ival |= OSTAR;
  1256. X        sprintf(tmpbuf,"%s:%d",ops[name+1].cval,prevargs);
  1257. X        fprintf(stderr,"Adding %s\n",tmpbuf);
  1258. X        str = str_new(0);
  1259. X        str_set(str,"*");
  1260. X        hstore(curarghash,tmpbuf,str);
  1261. X    }
  1262. X    numargs = prevargs + 1;
  1263. X    }
  1264. X    else
  1265. X    fatal("panic: unknown argument type %d, arg %d, line %d\n",
  1266. X      type,prevargs+1,line);
  1267. X    return numargs;
  1268. X}
  1269. X
  1270. Xfixrargs(name,arg,prevargs)
  1271. Xchar *name;
  1272. Xint arg;
  1273. Xint prevargs;
  1274. X{
  1275. X    int type;
  1276. X    STR *str;
  1277. X    int numargs;
  1278. X
  1279. X    if (!arg)
  1280. X    return prevargs;
  1281. X    type = ops[arg].ival & 255;
  1282. X    if (type == OCOMMA) {
  1283. X    numargs = fixrargs(name,ops[arg+1].ival,prevargs);
  1284. X    numargs = fixrargs(name,ops[arg+3].ival,numargs);
  1285. X    }
  1286. X    else {
  1287. X    char tmpbuf[128];
  1288. X
  1289. X    sprintf(tmpbuf,"%s:%d",name,prevargs);
  1290. X    str = hfetch(curarghash,tmpbuf);
  1291. X    fprintf(stderr,"Looking for %s\n",tmpbuf);
  1292. X    if (str && strEQ(str->str_ptr,"*")) {
  1293. X        if (type == OVAR || type == OSTAR) {
  1294. X        ops[arg].ival &= ~255;
  1295. X        ops[arg].ival |= OSTAR;
  1296. X        }
  1297. X        else
  1298. X        fatal("Can't pass expression by reference as arg %d of %s\n",
  1299. X            prevargs+1, name);
  1300. X    }
  1301. X    numargs = prevargs + 1;
  1302. X    }
  1303. X    return numargs;
  1304. X}
  1305. X
  1306. !STUFFY!FUNK!
  1307. echo Extracting stab.c
  1308. sed >stab.c <<'!STUFFY!FUNK!' -e 's/X//'
  1309. X/* $RCSfile: stab.c,v $$Revision: 4.0.1.1 $$Date: 91/04/12 09:10:24 $
  1310. X *
  1311. X *    Copyright (c) 1989, Larry Wall
  1312. X *
  1313. X *    You may distribute under the terms of the GNU General Public License
  1314. X *    as specified in the README file that comes with the perl 3.0 kit.
  1315. X *
  1316. X * $Log:    stab.c,v $
  1317. X * Revision 4.0.1.1  91/04/12  09:10:24  lwall
  1318. X * patch1: Configure now differentiates getgroups() type from getgid() type
  1319. X * patch1: you may now use "die" and "caller" in a signal handler
  1320. X * 
  1321. X * Revision 4.0  91/03/20  01:39:41  lwall
  1322. X * 4.0 baseline.
  1323. X * 
  1324. X */
  1325. X
  1326. X#include "EXTERN.h"
  1327. X#include "perl.h"
  1328. X
  1329. X#if !defined(NSIG) || defined(M_UNIX) || defined(M_XENIX)
  1330. X#include <signal.h>
  1331. X#endif
  1332. X
  1333. Xstatic char *sig_name[] = {
  1334. X    SIG_NAME,0
  1335. X};
  1336. X
  1337. X#ifdef VOIDSIG
  1338. X#define handlertype void
  1339. X#else
  1340. X#define handlertype int
  1341. X#endif
  1342. X
  1343. Xstatic handlertype sighandler();
  1344. X
  1345. Xstatic int origalen = 0;
  1346. X
  1347. XSTR *
  1348. Xstab_str(str)
  1349. XSTR *str;
  1350. X{
  1351. X    STAB *stab = str->str_u.str_stab;
  1352. X    register int paren;
  1353. X    register char *s;
  1354. X    register int i;
  1355. X
  1356. X    if (str->str_rare)
  1357. X    return stab_val(stab);
  1358. X
  1359. X    switch (*stab->str_magic->str_ptr) {
  1360. X    case '\004':        /* ^D */
  1361. X#ifdef DEBUGGING
  1362. X    str_numset(stab_val(stab),(double)(debug & 32767));
  1363. X#endif
  1364. X    break;
  1365. X    case '\t':            /* ^I */
  1366. X    if (inplace)
  1367. X        str_set(stab_val(stab), inplace);
  1368. X    else
  1369. X        str_sset(stab_val(stab),&str_undef);
  1370. X    break;
  1371. X    case '\024':        /* ^T */
  1372. X    str_numset(stab_val(stab),(double)basetime);
  1373. X    break;
  1374. X    case '\027':        /* ^W */
  1375. X    str_numset(stab_val(stab),(double)dowarn);
  1376. X    break;
  1377. X    case '1': case '2': case '3': case '4':
  1378. X    case '5': case '6': case '7': case '8': case '9': case '&':
  1379. X    if (curspat) {
  1380. X        paren = atoi(stab_name(stab));
  1381. X      getparen:
  1382. X        if (curspat->spat_regexp &&
  1383. X          paren <= curspat->spat_regexp->nparens &&
  1384. X          (s = curspat->spat_regexp->startp[paren]) ) {
  1385. X        i = curspat->spat_regexp->endp[paren] - s;
  1386. X        if (i >= 0)
  1387. X            str_nset(stab_val(stab),s,i);
  1388. X        else
  1389. X            str_sset(stab_val(stab),&str_undef);
  1390. X        }
  1391. X        else
  1392. X        str_sset(stab_val(stab),&str_undef);
  1393. X    }
  1394. X    break;
  1395. X    case '+':
  1396. X    if (curspat) {
  1397. X        paren = curspat->spat_regexp->lastparen;
  1398. X        goto getparen;
  1399. X    }
  1400. X    break;
  1401. X    case '`':
  1402. X    if (curspat) {
  1403. X        if (curspat->spat_regexp &&
  1404. X          (s = curspat->spat_regexp->subbase) ) {
  1405. X        i = curspat->spat_regexp->startp[0] - s;
  1406. X        if (i >= 0)
  1407. X            str_nset(stab_val(stab),s,i);
  1408. X        else
  1409. X            str_nset(stab_val(stab),"",0);
  1410. X        }
  1411. X        else
  1412. X        str_nset(stab_val(stab),"",0);
  1413. X    }
  1414. X    break;
  1415. X    case '\'':
  1416. X    if (curspat) {
  1417. X        if (curspat->spat_regexp &&
  1418. X          (s = curspat->spat_regexp->endp[0]) ) {
  1419. X        str_nset(stab_val(stab),s, curspat->spat_regexp->subend - s);
  1420. X        }
  1421. X        else
  1422. X        str_nset(stab_val(stab),"",0);
  1423. X    }
  1424. X    break;
  1425. X    case '.':
  1426. X#ifndef lint
  1427. X    if (last_in_stab) {
  1428. X        str_numset(stab_val(stab),(double)stab_io(last_in_stab)->lines);
  1429. X    }
  1430. X#endif
  1431. X    break;
  1432. X    case '?':
  1433. X    str_numset(stab_val(stab),(double)statusvalue);
  1434. X    break;
  1435. X    case '^':
  1436. X    s = stab_io(curoutstab)->top_name;
  1437. X    str_set(stab_val(stab),s);
  1438. X    break;
  1439. X    case '~':
  1440. X    s = stab_io(curoutstab)->fmt_name;
  1441. X    str_set(stab_val(stab),s);
  1442. X    break;
  1443. X#ifndef lint
  1444. X    case '=':
  1445. X    str_numset(stab_val(stab),(double)stab_io(curoutstab)->page_len);
  1446. X    break;
  1447. X    case '-':
  1448. X    str_numset(stab_val(stab),(double)stab_io(curoutstab)->lines_left);
  1449. X    break;
  1450. X    case '%':
  1451. X    str_numset(stab_val(stab),(double)stab_io(curoutstab)->page);
  1452. X    break;
  1453. X#endif
  1454. X    case '/':
  1455. X    break;
  1456. X    case '[':
  1457. X    str_numset(stab_val(stab),(double)arybase);
  1458. X    break;
  1459. X    case '|':
  1460. X    if (!stab_io(curoutstab))
  1461. X        stab_io(curoutstab) = stio_new();
  1462. X    str_numset(stab_val(stab),
  1463. X       (double)((stab_io(curoutstab)->flags & IOF_FLUSH) != 0) );
  1464. X    break;
  1465. X    case ',':
  1466. X    str_nset(stab_val(stab),ofs,ofslen);
  1467. X    break;
  1468. X    case '\\':
  1469. X    str_nset(stab_val(stab),ors,orslen);
  1470. X    break;
  1471. X    case '#':
  1472. X    str_set(stab_val(stab),ofmt);
  1473. X    break;
  1474. X    case '!':
  1475. X    str_numset(stab_val(stab), (double)errno);
  1476. X    str_set(stab_val(stab), errno ? strerror(errno) : "");
  1477. X    stab_val(stab)->str_nok = 1;    /* what a wonderful hack! */
  1478. X    break;
  1479. X    case '<':
  1480. X    str_numset(stab_val(stab),(double)uid);
  1481. X    break;
  1482. X    case '>':
  1483. X    str_numset(stab_val(stab),(double)euid);
  1484. X    break;
  1485. X    case '(':
  1486. X    s = buf;
  1487. X    (void)sprintf(s,"%d",(int)gid);
  1488. X    goto add_groups;
  1489. X    case ')':
  1490. X    s = buf;
  1491. X    (void)sprintf(s,"%d",(int)egid);
  1492. X      add_groups:
  1493. X    while (*s) s++;
  1494. X#ifdef HAS_GETGROUPS
  1495. X#ifndef NGROUPS
  1496. X#define NGROUPS 32
  1497. X#endif
  1498. X    {
  1499. X        GROUPSTYPE gary[NGROUPS];
  1500. X
  1501. X        i = getgroups(NGROUPS,gary);
  1502. X        while (--i >= 0) {
  1503. X        (void)sprintf(s," %ld", (long)gary[i]);
  1504. X        while (*s) s++;
  1505. X        }
  1506. X    }
  1507. X#endif
  1508. X    str_set(stab_val(stab),buf);
  1509. X    break;
  1510. X    case '*':
  1511. X    break;
  1512. X    case '0':
  1513. X    break;
  1514. X    default:
  1515. X    {
  1516. X        struct ufuncs *uf = (struct ufuncs *)str->str_ptr;
  1517. X
  1518. X        if (uf && uf->uf_val)
  1519. X        (*uf->uf_val)(uf->uf_index, stab_val(stab));
  1520. X    }
  1521. X    break;
  1522. X    }
  1523. X    return stab_val(stab);
  1524. X}
  1525. X
  1526. Xstabset(mstr,str)
  1527. Xregister STR *mstr;
  1528. XSTR *str;
  1529. X{
  1530. X    STAB *stab = mstr->str_u.str_stab;
  1531. X    register char *s;
  1532. X    int i;
  1533. X
  1534. X    switch (mstr->str_rare) {
  1535. X    case 'E':
  1536. X    setenv(mstr->str_ptr,str_get(str));
  1537. X                /* And you'll never guess what the dog had */
  1538. X                /*   in its mouth... */
  1539. X#ifdef TAINT
  1540. X    if (strEQ(mstr->str_ptr,"PATH")) {
  1541. X        char *strend = str->str_ptr + str->str_cur;
  1542. X
  1543. X        s = str->str_ptr;
  1544. X        while (s < strend) {
  1545. X        s = cpytill(tokenbuf,s,strend,':',&i);
  1546. X        s++;
  1547. X        if (*tokenbuf != '/'
  1548. X          || (stat(tokenbuf,&statbuf) && (statbuf.st_mode & 2)) )
  1549. X            str->str_tainted = 2;
  1550. X        }
  1551. X    }
  1552. X#endif
  1553. X    break;
  1554. X    case 'S':
  1555. X    s = str_get(str);
  1556. X    i = whichsig(mstr->str_ptr);    /* ...no, a brick */
  1557. X    if (strEQ(s,"IGNORE"))
  1558. X#ifndef lint
  1559. X        (void)signal(i,SIG_IGN);
  1560. X#else
  1561. X        ;
  1562. X#endif
  1563. X    else if (strEQ(s,"DEFAULT") || !*s)
  1564. X        (void)signal(i,SIG_DFL);
  1565. X    else {
  1566. X        (void)signal(i,sighandler);
  1567. X        if (!index(s,'\'')) {
  1568. X        sprintf(tokenbuf, "main'%s",s);
  1569. X        str_set(str,tokenbuf);
  1570. X        }
  1571. X    }
  1572. X    break;
  1573. X#ifdef SOME_DBM
  1574. X    case 'D':
  1575. X    hdbmstore(stab_hash(stab),mstr->str_ptr,mstr->str_cur,str);
  1576. X    break;
  1577. X#endif
  1578. X    case 'L':
  1579. X    {
  1580. X        CMD *cmd;
  1581. X
  1582. X        i = str_true(str);
  1583. X        str = afetch(stab_xarray(stab),atoi(mstr->str_ptr), FALSE);
  1584. X        cmd = str->str_magic->str_u.str_cmd;
  1585. X        cmd->c_flags &= ~CF_OPTIMIZE;
  1586. X        cmd->c_flags |= i? CFT_D1 : CFT_D0;
  1587. X    }
  1588. X    break;
  1589. X    case '#':
  1590. X    afill(stab_array(stab), (int)str_gnum(str) - arybase);
  1591. X    break;
  1592. X    case 'X':    /* merely a copy of a * string */
  1593. X    break;
  1594. X    case '*':
  1595. X    s = str_get(str);
  1596. X    if (strNE(s,"StB") || str->str_cur != sizeof(STBP)) {
  1597. X        if (!*s) {
  1598. X        STBP *stbp;
  1599. X
  1600. X        (void)savenostab(stab);    /* schedule a free of this stab */
  1601. X        if (stab->str_len)
  1602. X            Safefree(stab->str_ptr);
  1603. X        Newz(601,stbp, 1, STBP);
  1604. X        stab->str_ptr = stbp;
  1605. X        stab->str_len = stab->str_cur = sizeof(STBP);
  1606. X        stab->str_pok = 1;
  1607. X        strcpy(stab_magic(stab),"StB");
  1608. X        stab_val(stab) = Str_new(70,0);
  1609. X        stab_line(stab) = curcmd->c_line;
  1610. X        stab_stash(stab) = curcmd->c_stash;
  1611. X        }
  1612. X        else {
  1613. X        stab = stabent(s,TRUE);
  1614. X        if (!stab_xarray(stab))
  1615. X            aadd(stab);
  1616. X        if (!stab_xhash(stab))
  1617. X            hadd(stab);
  1618. X        if (!stab_io(stab))
  1619. X            stab_io(stab) = stio_new();
  1620. X        }
  1621. X        str_sset(str,stab);
  1622. X    }
  1623. X    break;
  1624. X    case 's': {
  1625. X        struct lstring *lstr = (struct lstring*)str;
  1626. X        char *tmps;
  1627. X
  1628. X        mstr->str_rare = 0;
  1629. X        str->str_magic = Nullstr;
  1630. X        tmps = str_get(str);
  1631. X        str_insert(mstr,lstr->lstr_offset,lstr->lstr_len,
  1632. X          tmps,str->str_cur);
  1633. X    }
  1634. X    break;
  1635. X
  1636. X    case 'v':
  1637. X    do_vecset(mstr,str);
  1638. X    break;
  1639. X
  1640. X    case 0:
  1641. X    switch (*stab->str_magic->str_ptr) {
  1642. X    case '\004':    /* ^D */
  1643. X#ifdef DEBUGGING
  1644. X        debug = (int)(str_gnum(str)) | 32768;
  1645. X#endif
  1646. X        break;
  1647. X    case '\t':    /* ^I */
  1648. X        if (inplace)
  1649. X        Safefree(inplace);
  1650. X        if (str->str_pok || str->str_nok)
  1651. X        inplace = savestr(str_get(str));
  1652. X        else
  1653. X        inplace = Nullch;
  1654. X        break;
  1655. X    case '\024':    /* ^T */
  1656. X        basetime = (long)str_gnum(str);
  1657. X        break;
  1658. X    case '\027':    /* ^W */
  1659. X        dowarn = (bool)str_gnum(str);
  1660. X        break;
  1661. X    case '.':
  1662. X        if (localizing)
  1663. X        savesptr((STR**)&last_in_stab);
  1664. X        break;
  1665. X    case '^':
  1666. X        Safefree(stab_io(curoutstab)->top_name);
  1667. X        stab_io(curoutstab)->top_name = s = savestr(str_get(str));
  1668. X        stab_io(curoutstab)->top_stab = stabent(s,TRUE);
  1669. X        break;
  1670. X    case '~':
  1671. X        Safefree(stab_io(curoutstab)->fmt_name);
  1672. X        stab_io(curoutstab)->fmt_name = s = savestr(str_get(str));
  1673. X        stab_io(curoutstab)->fmt_stab = stabent(s,TRUE);
  1674. X        break;
  1675. X    case '=':
  1676. X        stab_io(curoutstab)->page_len = (long)str_gnum(str);
  1677. X        break;
  1678. X    case '-':
  1679. X        stab_io(curoutstab)->lines_left = (long)str_gnum(str);
  1680. X        if (stab_io(curoutstab)->lines_left < 0L)
  1681. X        stab_io(curoutstab)->lines_left = 0L;
  1682. X        break;
  1683. X    case '%':
  1684. X        stab_io(curoutstab)->page = (long)str_gnum(str);
  1685. X        break;
  1686. X    case '|':
  1687. X        if (!stab_io(curoutstab))
  1688. X        stab_io(curoutstab) = stio_new();
  1689. X        stab_io(curoutstab)->flags &= ~IOF_FLUSH;
  1690. X        if (str_gnum(str) != 0.0) {
  1691. X        stab_io(curoutstab)->flags |= IOF_FLUSH;
  1692. X        }
  1693. X        break;
  1694. X    case '*':
  1695. X        i = (int)str_gnum(str);
  1696. X        multiline = (i != 0);
  1697. X        break;
  1698. X    case '/':
  1699. X        if (str->str_pok) {
  1700. X        rs = str_get(str);
  1701. X        rslen = str->str_cur;
  1702. X        if (!rslen) {
  1703. X            rs = "\n\n";
  1704. X            rslen = 2;
  1705. X        }
  1706. X        rschar = rs[rslen - 1];
  1707. X        }
  1708. X        else {
  1709. X        rschar = 0777;    /* fake a non-existent char */
  1710. X        rslen = 1;
  1711. X        }
  1712. X        break;
  1713. X    case '\\':
  1714. X        if (ors)
  1715. X        Safefree(ors);
  1716. X        ors = savestr(str_get(str));
  1717. X        orslen = str->str_cur;
  1718. X        break;
  1719. X    case ',':
  1720. X        if (ofs)
  1721. X        Safefree(ofs);
  1722. X        ofs = savestr(str_get(str));
  1723. X        ofslen = str->str_cur;
  1724. X        break;
  1725. X    case '#':
  1726. X        if (ofmt)
  1727. X        Safefree(ofmt);
  1728. X        ofmt = savestr(str_get(str));
  1729. X        break;
  1730. X    case '[':
  1731. X        arybase = (int)str_gnum(str);
  1732. X        break;
  1733. X    case '?':
  1734. X        statusvalue = U_S(str_gnum(str));
  1735. X        break;
  1736. X    case '!':
  1737. X        errno = (int)str_gnum(str);        /* will anyone ever use this? */
  1738. X        break;
  1739. X    case '<':
  1740. X        uid = (int)str_gnum(str);
  1741. X#ifdef HAS_SETREUID
  1742. X        if (delaymagic) {
  1743. X        delaymagic |= DM_REUID;
  1744. X        break;                /* don't do magic till later */
  1745. X        }
  1746. X#endif /* HAS_SETREUID */
  1747. X#ifdef HAS_SETRUID
  1748. X        if (setruid((UIDTYPE)uid) < 0)
  1749. X        uid = (int)getuid();
  1750. X#else
  1751. X#ifdef HAS_SETREUID
  1752. X        if (setreuid((UIDTYPE)uid, (UIDTYPE)-1) < 0)
  1753. X        uid = (int)getuid();
  1754. X#else
  1755. X        if (uid == euid)        /* special case $< = $> */
  1756. X        setuid(uid);
  1757. X        else
  1758. X        fatal("setruid() not implemented");
  1759. X#endif
  1760. X#endif
  1761. X        break;
  1762. X    case '>':
  1763. X        euid = (int)str_gnum(str);
  1764. X#ifdef HAS_SETREUID
  1765. X        if (delaymagic) {
  1766. X        delaymagic |= DM_REUID;
  1767. X        break;                /* don't do magic till later */
  1768. X        }
  1769. X#endif /* HAS_SETREUID */
  1770. X#ifdef HAS_SETEUID
  1771. X        if (seteuid((UIDTYPE)euid) < 0)
  1772. X        euid = (int)geteuid();
  1773. X#else
  1774. X#ifdef HAS_SETREUID
  1775. X        if (setreuid((UIDTYPE)-1, (UIDTYPE)euid) < 0)
  1776. X        euid = (int)geteuid();
  1777. X#else
  1778. X        if (euid == uid)        /* special case $> = $< */
  1779. X        setuid(euid);
  1780. X        else
  1781. X        fatal("seteuid() not implemented");
  1782. X#endif
  1783. X#endif
  1784. X        break;
  1785. X    case '(':
  1786. X        gid = (int)str_gnum(str);
  1787. X#ifdef HAS_SETREGID
  1788. X        if (delaymagic) {
  1789. X        delaymagic |= DM_REGID;
  1790. X        break;                /* don't do magic till later */
  1791. X        }
  1792. X#endif /* HAS_SETREGID */
  1793. X#ifdef HAS_SETRGID
  1794. X        (void)setrgid((GIDTYPE)gid);
  1795. X#else
  1796. X#ifdef HAS_SETREGID
  1797. X        (void)setregid((GIDTYPE)gid, (GIDTYPE)-1);
  1798. X#else
  1799. X        fatal("setrgid() not implemented");
  1800. X#endif
  1801. X#endif
  1802. X        break;
  1803. X    case ')':
  1804. X        egid = (int)str_gnum(str);
  1805. X#ifdef HAS_SETREGID
  1806. X        if (delaymagic) {
  1807. X        delaymagic |= DM_REGID;
  1808. X        break;                /* don't do magic till later */
  1809. X        }
  1810. X#endif /* HAS_SETREGID */
  1811. X#ifdef HAS_SETEGID
  1812. X        (void)setegid((GIDTYPE)egid);
  1813. X#else
  1814. X#ifdef HAS_SETREGID
  1815. X        (void)setregid((GIDTYPE)-1, (GIDTYPE)egid);
  1816. X#else
  1817. X        fatal("setegid() not implemented");
  1818. X#endif
  1819. X#endif
  1820. X        break;
  1821. X    case ':':
  1822. X        chopset = str_get(str);
  1823. X        break;
  1824. X    case '0':
  1825. X        if (!origalen) {
  1826. X        s = origargv[0];
  1827. X        s += strlen(s);
  1828. X        /* See if all the arguments are contiguous in memory */
  1829. X        for (i = 1; i < origargc; i++) {
  1830. X            if (origargv[i] == s + 1)
  1831. X            s += strlen(++s);    /* this one is ok too */
  1832. X        }
  1833. X        if (origenviron[0] == s + 1) {    /* can grab env area too? */
  1834. X            setenv("NoNeSuCh", Nullch);    /* force copy of environment */
  1835. X            for (i = 0; origenviron[i]; i++)
  1836. X            if (origenviron[i] == s + 1)
  1837. X                s += strlen(++s);
  1838. X        }
  1839. X        origalen = s - origargv[0];
  1840. X        }
  1841. X        s = str_get(str);
  1842. X        i = str->str_cur;
  1843. X        if (i >= origalen) {
  1844. X        i = origalen;
  1845. X        str->str_cur = i;
  1846. X        str->str_ptr[i] = '\0';
  1847. X        bcopy(s, origargv[0], i);
  1848. X        }
  1849. X        else {
  1850. X        bcopy(s, origargv[0], i);
  1851. X        s = origargv[0]+i;
  1852. X        *s++ = '\0';
  1853. X        while (++i < origalen)
  1854. X            *s++ = ' ';
  1855. X        }
  1856. X        break;
  1857. X    default:
  1858. X        {
  1859. X        struct ufuncs *uf = (struct ufuncs *)str->str_magic->str_ptr;
  1860. X
  1861. X        if (uf && uf->uf_set)
  1862. X            (*uf->uf_set)(uf->uf_index, str);
  1863. X        }
  1864. X        break;
  1865. X    }
  1866. X    break;
  1867. X    }
  1868. X}
  1869. X
  1870. Xwhichsig(sig)
  1871. Xchar *sig;
  1872. X{
  1873. X    register char **sigv;
  1874. X
  1875. X    for (sigv = sig_name+1; *sigv; sigv++)
  1876. X    if (strEQ(sig,*sigv))
  1877. X        return sigv - sig_name;
  1878. X#ifdef SIGCLD
  1879. X    if (strEQ(sig,"CHLD"))
  1880. X    return SIGCLD;
  1881. X#endif
  1882. X#ifdef SIGCHLD
  1883. X    if (strEQ(sig,"CLD"))
  1884. X    return SIGCHLD;
  1885. X#endif
  1886. X    return 0;
  1887. X}
  1888. X
  1889. Xstatic handlertype
  1890. Xsighandler(sig)
  1891. Xint sig;
  1892. X{
  1893. X    STAB *stab;
  1894. X    STR *str;
  1895. X    int oldsave = savestack->ary_fill;
  1896. X    int oldtmps_base = tmps_base;
  1897. X    register CSV *csv;
  1898. X    SUBR *sub;
  1899. X
  1900. X#ifdef OS2        /* or anybody else who requires SIG_ACK */
  1901. X    signal(sig, SIG_ACK);
  1902. X#endif
  1903. X    stab = stabent(
  1904. X    str_get(hfetch(stab_hash(sigstab),sig_name[sig],strlen(sig_name[sig]),
  1905. X      TRUE)), TRUE);
  1906. X    sub = stab_sub(stab);
  1907. X    if (!sub && *sig_name[sig] == 'C' && instr(sig_name[sig],"LD")) {
  1908. X    if (sig_name[sig][1] == 'H')
  1909. X        stab = stabent(str_get(hfetch(stab_hash(sigstab),"CLD",3,TRUE)),
  1910. X          TRUE);
  1911. X    else
  1912. X        stab = stabent(str_get(hfetch(stab_hash(sigstab),"CHLD",4,TRUE)),
  1913. X          TRUE);
  1914. X    sub = stab_sub(stab);    /* gag */
  1915. X    }
  1916. X    if (!sub) {
  1917. X    if (dowarn)
  1918. X        warn("SIG%s handler \"%s\" not defined.\n",
  1919. X        sig_name[sig], stab_name(stab) );
  1920. X    return;
  1921. X    }
  1922. X    saveaptr(&stack);
  1923. X    str = Str_new(15, sizeof(CSV));
  1924. X    str->str_state = SS_SCSV;
  1925. X    (void)apush(savestack,str);
  1926. X    csv = (CSV*)str->str_ptr;
  1927. X    csv->sub = sub;
  1928. X    csv->stab = stab;
  1929. X    csv->curcsv = curcsv;
  1930. X    csv->curcmd = curcmd;
  1931. X    csv->depth = sub->depth;
  1932. X    csv->wantarray = G_SCALAR;
  1933. X    csv->hasargs = TRUE;
  1934. X    csv->savearray = stab_xarray(defstab);
  1935. X    csv->argarray = stab_xarray(defstab) = stack = anew(defstab);
  1936. X    stack->ary_flags = 0;
  1937. X    curcsv = csv;
  1938. X    str = str_mortal(&str_undef);
  1939. X    str_set(str,sig_name[sig]);
  1940. X    (void)apush(stab_xarray(defstab),str);
  1941. X    sub->depth++;
  1942. X    if (sub->depth >= 2) {    /* save temporaries on recursion? */
  1943. X    if (sub->depth == 100 && dowarn)
  1944. X        warn("Deep recursion on subroutine \"%s\"",stab_name(stab));
  1945. X    savelist(sub->tosave->ary_array,sub->tosave->ary_fill);
  1946. X    }
  1947. X
  1948. X    tmps_base = tmps_max;        /* protect our mortal string */
  1949. X    (void)cmd_exec(sub->cmd,G_SCALAR,0);        /* so do it already */
  1950. X    tmps_base = oldtmps_base;
  1951. X
  1952. X    restorelist(oldsave);        /* put everything back */
  1953. X}
  1954. X
  1955. XSTAB *
  1956. Xaadd(stab)
  1957. Xregister STAB *stab;
  1958. X{
  1959. X    if (!stab_xarray(stab))
  1960. X    stab_xarray(stab) = anew(stab);
  1961. X    return stab;
  1962. X}
  1963. X
  1964. XSTAB *
  1965. Xhadd(stab)
  1966. Xregister STAB *stab;
  1967. X{
  1968. X    if (!stab_xhash(stab))
  1969. X    stab_xhash(stab) = hnew(COEFFSIZE);
  1970. X    return stab;
  1971. X}
  1972. X
  1973. XSTAB *
  1974. Xfstab(name)
  1975. Xchar *name;
  1976. X{
  1977. X    char tmpbuf[1200];
  1978. X    STAB *stab;
  1979. X
  1980. X    sprintf(tmpbuf,"'_<%s", name);
  1981. X    stab = stabent(tmpbuf, TRUE);
  1982. X    str_set(stab_val(stab), name);
  1983. X    if (perldb)
  1984. X    (void)hadd(aadd(stab));
  1985. X    return stab;
  1986. X}
  1987. X
  1988. XSTAB *
  1989. Xstabent(name,add)
  1990. Xregister char *name;
  1991. Xint add;
  1992. X{
  1993. X    register STAB *stab;
  1994. X    register STBP *stbp;
  1995. X    int len;
  1996. X    register char *namend;
  1997. X    HASH *stash;
  1998. X    char *sawquote = Nullch;
  1999. X    char *prevquote = Nullch;
  2000. X    bool global = FALSE;
  2001. X
  2002. X    if (isascii(*name) && isupper(*name)) {
  2003. X    if (*name > 'I') {
  2004. X        if (*name == 'S' && (
  2005. X          strEQ(name, "SIG") ||
  2006. X          strEQ(name, "STDIN") ||
  2007. X          strEQ(name, "STDOUT") ||
  2008. X          strEQ(name, "STDERR") ))
  2009. X        global = TRUE;
  2010. X    }
  2011. X    else if (*name > 'E') {
  2012. X        if (*name == 'I' && strEQ(name, "INC"))
  2013. X        global = TRUE;
  2014. X    }
  2015. X    else if (*name > 'A') {
  2016. X        if (*name == 'E' && strEQ(name, "ENV"))
  2017. X        global = TRUE;
  2018. X    }
  2019. X    else if (*name == 'A' && (
  2020. X      strEQ(name, "ARGV") ||
  2021. X      strEQ(name, "ARGVOUT") ))
  2022. X        global = TRUE;
  2023. X    }
  2024. X    for (namend = name; *namend; namend++) {
  2025. X    if (*namend == '\'' && namend[1])
  2026. X        prevquote = sawquote, sawquote = namend;
  2027. X    }
  2028. X    if (sawquote == name && name[1]) {
  2029. X    stash = defstash;
  2030. X    sawquote = Nullch;
  2031. X    name++;
  2032. X    }
  2033. X    else if (!isalpha(*name) || global)
  2034. X    stash = defstash;
  2035. X    else if (curcmd == &compiling)
  2036. X    stash = curstash;
  2037. X    else
  2038. X    stash = curcmd->c_stash;
  2039. X    if (sawquote) {
  2040. X    char tmpbuf[256];
  2041. X    char *s, *d;
  2042. X
  2043. X    *sawquote = '\0';
  2044. X    if (s = prevquote) {
  2045. X        strncpy(tmpbuf,name,s-name+1);
  2046. X        d = tmpbuf+(s-name+1);
  2047. X        *d++ = '_';
  2048. X        strcpy(d,s+1);
  2049. X    }
  2050. X    else {
  2051. X        *tmpbuf = '_';
  2052. X        strcpy(tmpbuf+1,name);
  2053. X    }
  2054. X    stab = stabent(tmpbuf,TRUE);
  2055. X    if (!(stash = stab_xhash(stab)))
  2056. X        stash = stab_xhash(stab) = hnew(0);
  2057. X    if (!stash->tbl_name)
  2058. X        stash->tbl_name = savestr(name);
  2059. X    name = sawquote+1;
  2060. X    *sawquote = '\'';
  2061. X    }
  2062. X    len = namend - name;
  2063. X    stab = (STAB*)hfetch(stash,name,len,add);
  2064. X    if (stab == (STAB*)&str_undef)
  2065. X    return Nullstab;
  2066. X    if (stab->str_pok) {
  2067. X    stab->str_pok |= SP_MULTI;
  2068. X    return stab;
  2069. X    }
  2070. X    else {
  2071. X    if (stab->str_len)
  2072. X        Safefree(stab->str_ptr);
  2073. X    Newz(602,stbp, 1, STBP);
  2074. X    stab->str_ptr = stbp;
  2075. X    stab->str_len = stab->str_cur = sizeof(STBP);
  2076. X    stab->str_pok = 1;
  2077. X    strcpy(stab_magic(stab),"StB");
  2078. X    stab_val(stab) = Str_new(72,0);
  2079. X    stab_line(stab) = curcmd->c_line;
  2080. X    str_magic(stab,stab,'*',name,len);
  2081. X    stab_stash(stab) = stash;
  2082. X    if (isdigit(*name) && *name != '0') {
  2083. X        stab_flags(stab) = SF_VMAGIC;
  2084. X        str_magic(stab_val(stab), stab, 0, Nullch, 0);
  2085. X    }
  2086. X    return stab;
  2087. X    }
  2088. X}
  2089. X
  2090. Xstab_fullname(str,stab)
  2091. XSTR *str;
  2092. XSTAB *stab;
  2093. X{
  2094. X    HASH *tb = stab_stash(stab);
  2095. X
  2096. X    if (!tb)
  2097. X    return;
  2098. X    str_set(str,tb->tbl_name);
  2099. X    str_ncat(str,"'", 1);
  2100. X    str_scat(str,stab->str_magic);
  2101. X}
  2102. X
  2103. XSTIO *
  2104. Xstio_new()
  2105. X{
  2106. X    STIO *stio;
  2107. X
  2108. X    Newz(603,stio,1,STIO);
  2109. X    stio->page_len = 60;
  2110. X    return stio;
  2111. X}
  2112. X
  2113. Xstab_check(min,max)
  2114. Xint min;
  2115. Xregister int max;
  2116. X{
  2117. X    register HENT *entry;
  2118. X    register int i;
  2119. X    register STAB *stab;
  2120. X
  2121. X    for (i = min; i <= max; i++) {
  2122. X    for (entry = defstash->tbl_array[i]; entry; entry = entry->hent_next) {
  2123. X        stab = (STAB*)entry->hent_val;
  2124. X        if (stab->str_pok & SP_MULTI)
  2125. X        continue;
  2126. X        curcmd->c_line = stab_line(stab);
  2127. X        warn("Possible typo: \"%s\"", stab_name(stab));
  2128. X    }
  2129. X    }
  2130. X}
  2131. X
  2132. Xstatic int gensym = 0;
  2133. X
  2134. XSTAB *
  2135. Xgenstab()
  2136. X{
  2137. X    (void)sprintf(tokenbuf,"_GEN_%d",gensym++);
  2138. X    return stabent(tokenbuf,TRUE);
  2139. X}
  2140. X
  2141. X/* hopefully this is only called on local symbol table entries */
  2142. X
  2143. Xvoid
  2144. Xstab_clear(stab)
  2145. Xregister STAB *stab;
  2146. X{
  2147. X    STIO *stio;
  2148. X    SUBR *sub;
  2149. X
  2150. X    afree(stab_xarray(stab));
  2151. X    stab_xarray(stab) = Null(ARRAY*);
  2152. X    (void)hfree(stab_xhash(stab), FALSE);
  2153. X    stab_xhash(stab) = Null(HASH*);
  2154. X    str_free(stab_val(stab));
  2155. X    stab_val(stab) = Nullstr;
  2156. X    if (stio = stab_io(stab)) {
  2157. X    do_close(stab,FALSE);
  2158. X    Safefree(stio->top_name);
  2159. X    Safefree(stio->fmt_name);
  2160. X    }
  2161. X    if (sub = stab_sub(stab)) {
  2162. X    afree(sub->tosave);
  2163. X    cmd_free(sub->cmd);
  2164. X    }
  2165. X    Safefree(stab->str_ptr);
  2166. X    stab->str_ptr = Null(STBP*);
  2167. X    stab->str_len = 0;
  2168. X    stab->str_cur = 0;
  2169. X}
  2170. X
  2171. X#if defined(CRIPPLED_CC) && (defined(iAPX286) || defined(M_I286) || defined(I80286))
  2172. X#define MICROPORT
  2173. X#endif
  2174. X
  2175. X#ifdef    MICROPORT    /* Microport 2.4 hack */
  2176. XARRAY *stab_array(stab)
  2177. Xregister STAB *stab;
  2178. X{
  2179. X    if (((STBP*)(stab->str_ptr))->stbp_array) 
  2180. X    return ((STBP*)(stab->str_ptr))->stbp_array;
  2181. X    else
  2182. X    return ((STBP*)(aadd(stab)->str_ptr))->stbp_array;
  2183. X}
  2184. X
  2185. XHASH *stab_hash(stab)
  2186. Xregister STAB *stab;
  2187. X{
  2188. X    if (((STBP*)(stab->str_ptr))->stbp_hash)
  2189. X    return ((STBP*)(stab->str_ptr))->stbp_hash;
  2190. X    else
  2191. X    return ((STBP*)(hadd(stab)->str_ptr))->stbp_hash;
  2192. X}
  2193. X#endif            /* Microport 2.4 hack */
  2194. !STUFFY!FUNK!
  2195. echo Extracting msdos/Makefile
  2196. sed >msdos/Makefile <<'!STUFFY!FUNK!' -e 's/X//'
  2197. X#
  2198. X# Makefile for compiling Perl under MS-DOS
  2199. X#
  2200. X# Needs a Unix compatible make.
  2201. X# This makefile works for an initial compilation.  It does not
  2202. X# include all dependencies and thus is unsuitable for serious
  2203. X# development work.  But who would do serious development under
  2204. X# MS-DOS?
  2205. X#
  2206. X# By Diomidis Spinellis, March 1990
  2207. X#
  2208. X
  2209. X# Source files
  2210. XSRC = array.c cmd.c cons.c consarg.c doarg.c doio.c dolist.c dump.c \
  2211. Xeval.c form.c hash.c perl.y perly.c regcomp.c regexec.c \
  2212. Xstab.c str.c toke.c util.c msdos.c popen.c directory.c
  2213. X
  2214. X# Object files
  2215. XOBJ = perl.obj array.obj cmd.obj cons.obj consarg.obj doarg.obj doio.obj \
  2216. Xdolist.obj dump.obj eval.obj form.obj hash.obj perly.obj regcomp.obj \
  2217. Xregexec.obj stab.obj str.obj toke.obj util.obj msdos.obj popen.obj \
  2218. Xdirectory.obj
  2219. X
  2220. X# Files in the MS-DOS distribution
  2221. XDOSFILES=config.h dir.h director.c glob.c makefile msdos.c popen.c readme.msd \
  2222. Xchanges.dds wishlist.dds patches manifest
  2223. X
  2224. X# Yacc flags
  2225. XYFLAGS=-d
  2226. X
  2227. X# Manual pages
  2228. XMAN=perlman.1 perlman.2 perlman.3 perlman.4
  2229. X
  2230. XCC=cc
  2231. X# Cflags for the files that break under the optimiser
  2232. XCPLAIN=-AL -DCRIPPLED_CC
  2233. X# Cflags for all the rest
  2234. XCFLAGS=$(CPLAIN) -Ox
  2235. X# Destination directory for executables
  2236. XDESTDIR=\usr\bin
  2237. X
  2238. X# Deliverables
  2239. Xall: perl.exe perl.1 glob.exe
  2240. X
  2241. Xperl.exe: $(OBJ)
  2242. X    echo array+cmd+cons+consarg+doarg+doio+dolist+dump+ >perl.arp
  2243. X    echo eval+form+hash+perl+perly+regcomp+regexec+ >>perl.arp
  2244. X    echo stab+str+toke+util+msdos+popen+directory+\lib\setargv >>perl.arp
  2245. X    echo perl.exe >>perl.arp
  2246. X    echo nul >>perl.arp
  2247. X    echo /stack:32767 /NOE >>perl.arp
  2248. X    link @perl.arp
  2249. X
  2250. Xglob.exe: glob.c
  2251. X    $(CC) glob.c \lib\setargv.obj -link /NOE
  2252. X
  2253. Xarray.obj: array.c
  2254. Xcmd.obj: cmd.c
  2255. Xcons.obj: cons.c perly.h
  2256. Xconsarg.obj: consarg.c
  2257. X    $(CC) $(CPLAIN) -c consarg.c
  2258. Xdoarg.obj: doarg.c
  2259. Xdoio.obj: doio.c
  2260. Xdolist.obj: dolist.c
  2261. Xdump.obj: dump.c
  2262. Xeval.obj: eval.c evalargs.xc
  2263. Xform.obj: form.c
  2264. Xhash.obj: hash.c
  2265. Xperl.obj: perl.y
  2266. Xperly.obj: perly.c
  2267. Xregcomp.obj: regcomp.c
  2268. Xregexec.obj: regexec.c
  2269. Xstab.obj: stab.c
  2270. Xstr.obj: str.c
  2271. Xtoke.obj: toke.c
  2272. Xutil.obj: util.c
  2273. X    $(CC) $(CPLAIN) -c util.c
  2274. Xperly.h: perl.obj
  2275. X    mv ytab.h perly.h
  2276. Xdirectory.obj: directory.c
  2277. Xpopen.obj: popen.c
  2278. Xmsdos.obj: msdos.c
  2279. X
  2280. Xperl.1: $(MAN)
  2281. X    nroff -man $(MAN) >perl.1
  2282. X
  2283. Xinstall: all
  2284. X    exepack perl.exe $(DESTDIR)\perl.exe
  2285. X    exepack glob.exe $(DESTDIR)\glob.exe
  2286. X
  2287. Xclean:
  2288. X    rm -f *.obj *.exe perl.1 perly.h perl.arp
  2289. X
  2290. Xtags:
  2291. X    ctags *.c *.h *.xc
  2292. X
  2293. Xdosperl:
  2294. X    mv $(DOSFILES) ../perl30.new
  2295. X
  2296. Xdoskit:
  2297. X    mv $(DOSFILES) ../msdos
  2298. !STUFFY!FUNK!
  2299. echo " "
  2300. echo "End of kit 24 (of 36)"
  2301. cat /dev/null >kit24isdone
  2302. run=''
  2303. config=''
  2304. 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
  2305.     if test -f kit${iskit}isdone; then
  2306.     run="$run $iskit"
  2307.     else
  2308.     todo="$todo $iskit"
  2309.     fi
  2310. done
  2311. case $todo in
  2312.     '')
  2313.     echo "You have run all your kits.  Please read README and then type Configure."
  2314.     for combo in *:AA; do
  2315.         if test -f "$combo"; then
  2316.         realfile=`basename $combo :AA`
  2317.         cat $realfile:[A-Z][A-Z] >$realfile
  2318.         rm -rf $realfile:[A-Z][A-Z]
  2319.         fi
  2320.     done
  2321.     rm -rf kit*isdone
  2322.     chmod 755 Configure
  2323.     ;;
  2324.     *)  echo "You have run$run."
  2325.     echo "You still need to run$todo."
  2326.     ;;
  2327. esac
  2328. : Someone might mail this, so...
  2329. exit
  2330.  
  2331. exit 0 # Just in case...
  2332. -- 
  2333. Kent Landfield                   INTERNET: kent@sparky.IMD.Sterling.COM
  2334. Sterling Software, IMD           UUCP:     uunet!sparky!kent
  2335. Phone:    (402) 291-8300         FAX:      (402) 291-4362
  2336. Please send comp.sources.misc-related mail to kent@uunet.uu.net.
  2337.