home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume11 / inline / part03 < prev    next >
Encoding:
Internet Message Format  |  1987-09-14  |  55.9 KB

  1. Subject:  v11i041:  Inline code expander for C, Part03/04
  2. Newsgroups: comp.sources.unix
  3. Sender: sources
  4. Approved: rs@uunet.UU.NET
  5.  
  6. Submitted-by: omepd!mcg
  7. Posting-number: Volume 11, Issue 41
  8. Archive-name: inline/Part03
  9.  
  10. # This is a shell archive.  Remove anything before this line
  11. # then unpack it by saving it in a file and typing "sh file"
  12. # (Files unpacked will be owned by you and have original permissions).
  13. # This archive contains the following files:
  14. #    ./expand.c
  15. #    ./rewrite.c
  16. #    ./yylex.c
  17. #    ./tokens.c
  18. #    ./utils.c
  19. #    ./mem.c
  20. #
  21. if `test ! -s ./expand.c`
  22. then
  23. echo "writing ./expand.c"
  24. sed 's/^X//' > ./expand.c << '\Rogue\Monster\'
  25. X/*
  26. X * inline code expander
  27. X *
  28. X * (c) 1986 - copyright 1986, s. mcgeady, all rights reserved
  29. X */
  30. X
  31. X/* $Header: expand.c,v 1.13 87/06/24 13:11:24 mcg Rel $ */
  32. X
  33. X/*
  34. X * find an expansion opportunity, get its parameters, and expand the node
  35. X */
  36. X#include "inline.h"
  37. X#include "tokens.h"
  38. X
  39. Xextern struct expand_node *mkenode(); /* forward declaration */
  40. Xextern struct expand_node *doactuals();
  41. Xextern struct token *dostmt();
  42. Xextern struct token *doexpr();
  43. X
  44. Xdoinline(mem,prog)
  45. Xregister int mem;
  46. Xregister struct toklist *prog;
  47. X{
  48. X    register struct token *tt, *tl, *tx;
  49. X    register struct token *begin = NILTOK;
  50. X    register struct token *end;
  51. X    register struct expand_node *e;
  52. X    register struct inline_node *node;
  53. X    register int i;
  54. X    register int emem;
  55. X    int expanded = 0;
  56. X
  57. X    /*
  58. X     * look through list to find first expansion possibility,
  59. X     * keeping track of statement breaks.  a statement break occurs
  60. X     * at the last semicolon, closing brace, or opening brace.  expansions
  61. X     * inside control statements complicate matters
  62. X     */
  63. X
  64. X    emem = openpool();
  65. X    tt = NILTOK;
  66. X    for (tl = prog->tl_head; tl != NILTOK; tt = tl, tl = tl->t_next) {
  67. X        switch(tl->t_tok) {
  68. X        case T_IDENT:
  69. X            if (iscall(tl) && (node = isinline(tl->t_id))) {
  70. X                node->i_nseen++;
  71. X
  72. X                /* don't expand if this expression has ||, && */
  73. X                /* or  ?: --- should not expand if there's a */
  74. X                /* comma operator, but can't identify those */
  75. X                /* easily            */
  76. X
  77. X                for (tx = begin; tx && tx != tl; tx = tx->t_next) {
  78. X                    if (tx->t_tok == T_CAND ||
  79. X                        tx->t_tok == T_COR ||
  80. X                        tx->t_tok == T_QUEST) {
  81. X                        if (node->i_flags&I_EXPR) {
  82. X                            tl->t_flags |= TNEEDEXPR;
  83. X                        } else {
  84. X                            tl->t_flags |= TNOEXPAND;
  85. X                            warn(tl->t_line,"inline %s is not expandable in this context", tl->t_id);
  86. X                        }
  87. X                    }
  88. X                }
  89. X                if (tl->t_flags&TNOEXPAND) {
  90. X                    break;
  91. X                }
  92. X
  93. X                if ((e = doactuals(emem,tt,node)) == NILP(struct expand_node *)) {
  94. X                    /* don't expand again */
  95. X                    tl->t_flags |= TNOEXPAND;
  96. X                    warn(tl->t_line,"inline %s is not expandable in this context", tl->t_id);
  97. X                } else {
  98. X
  99. X                    end = dostmt(begin->t_next,0);
  100. X                    if (doexpand(mem,begin,end,tt->t_next,tl->t_flags&TNEEDEXPR,e)) {
  101. X                        node->i_nexpand++;
  102. X                        tl = begin;
  103. X                        expanded++;
  104. X                    }
  105. X                }
  106. X            }
  107. X            break;
  108. X
  109. X        case T_IF:
  110. X        case T_SWITCH:
  111. X            begin = tt;    /* point to node before */
  112. X            break;
  113. X
  114. X        case T_WHILE:
  115. X        case T_FOR:
  116. X            /* skip over control part */
  117. X            end = dostmt(tl,1);
  118. X            i = 0;
  119. X            for (tx = tl->t_next; tx != end; tx = tx->t_next) {
  120. X                if (iscall(tx) && (node = isinline(tx->t_id))) {
  121. X                    node->i_nseen++;
  122. X                    if (node->i_flags&I_EXPR) {
  123. X                        tx->t_flags |= TNEEDEXPR;
  124. X                        i = 1;
  125. X                    } else {
  126. X                        warn(tx->t_line,"inline %s is not expandable in this context", tx->t_id);
  127. X                        tx->t_flags |= TNOEXPAND;
  128. X                    }
  129. X                }
  130. X            }
  131. X            /* no expansion possibility inside for, while */
  132. X            if (i) {
  133. X                begin = tt;
  134. X            } else {
  135. X                begin = tl = end;
  136. X            }
  137. X            break;
  138. X
  139. X        case T_COLON:
  140. X            /* distinguish between label and ? : op */
  141. X            for (tx = begin; tx != tl; tx = tx->t_next) {
  142. X                if (tx->t_tok == T_QUEST) {
  143. X                    break;
  144. X                }
  145. X            }
  146. X            if (tx->t_tok == T_QUEST) {
  147. X                break;
  148. X            }
  149. X            /*FALLTHROUGH*/
  150. X    
  151. X        case T_SEMIC:
  152. X        case T_LBRACE:
  153. X        case T_RBRACE:
  154. X            begin = tl;
  155. X            break;
  156. X
  157. X        default:
  158. X            if (istype(tl) || isstoreclass(tl)) {
  159. X                end = dostmt(tl->t_next,0);
  160. X                for (tx = tl->t_next; tx != end; tx = tx->t_next) {
  161. X                    if (iscall(tx) && (node = isinline(tx->t_id))) {
  162. X                        node->i_nseen++;
  163. X                        tx->t_flags |= TNOEXPAND;
  164. X                        warn(tx->t_line,"inline %s is not expandable in this context", tx->t_id);
  165. X                    }
  166. X                }
  167. X                /* no expansion in initializations */
  168. X                begin = tl = end;
  169. X            }
  170. X            break;
  171. X        }
  172. X    }
  173. X    (void) closepool(emem);
  174. X    return(expanded);
  175. X}
  176. X
  177. Xstruct token *
  178. Xdostmt(begin,ctrl)
  179. Xregister struct token *begin;
  180. Xregister int ctrl;
  181. X{
  182. X    register struct token *tx;
  183. X    register int seenquest = 0;
  184. X
  185. X    begin = skipws(begin);
  186. X    while (begin) {
  187. X        switch(begin->t_tok) {
  188. X        case T_SWITCH:
  189. X        case T_WHILE:
  190. X        case T_FOR:
  191. X        case T_IF:
  192. X            /* find end of control part */
  193. X            tx = doexpr(begin->t_next,1);
  194. X            if (ctrl) {
  195. X                return(tx);
  196. X            }
  197. X            /* find end of body */
  198. X            tx = dostmt(tx->t_next,0);
  199. X
  200. X            if (begin->t_tok == T_IF) {
  201. X                /* look for 'else' */
  202. X                begin = skipws(tx->t_next);
  203. X                if (begin->t_tok == T_ELSE) {
  204. X                    return(dostmt(begin,0));
  205. X                }
  206. X            }
  207. X            return(tx);
  208. X
  209. X        case T_ELSE:
  210. X            return(dostmt(begin->t_next,0));
  211. X
  212. X        case T_LBRACE:
  213. X            for (tx = begin; tx != NILTOK; tx = tx->t_next) {
  214. X                if ((tx->t_tok == T_RBRACE) &&
  215. X                     (tx->t_level == begin->t_level)) {
  216. X                    return(tx);
  217. X                }
  218. X            }
  219. X            error(begin->t_line,"unmatched {");
  220. X            break;
  221. X
  222. X        case T_SEMIC:
  223. X            return(begin);
  224. X
  225. X        case T_COLON:
  226. X            if (seenquest--) {
  227. X                begin = begin->t_next;
  228. X                continue;
  229. X            }
  230. X            return(begin);
  231. X
  232. X        case T_QUEST:
  233. X            seenquest++;
  234. X        default:
  235. X            begin = begin->t_next;
  236. X            continue;
  237. X        }
  238. X        /* if we get here, it's an error */
  239. X        break;
  240. X    }
  241. X    error(begin->t_line, "statement termination error");
  242. X    return(NILTOK);
  243. X}
  244. X
  245. Xstruct token *
  246. Xdoexpr(begin,ctrl)
  247. Xregister struct token *begin;
  248. Xregister int ctrl;
  249. X{
  250. X    register int seenquest = 0;
  251. X    register struct token *tx;
  252. X
  253. X    begin = skipws(begin);
  254. X    while (begin) {
  255. X        switch(begin->t_tok) {
  256. X        case T_LPAREN:
  257. X            for(tx = begin; tx != NILTOK; tx = tx->t_next) {
  258. X                if ((tx->t_tok == T_RPAREN) &&
  259. X                    (tx->t_paren == begin->t_paren)) {
  260. X                    if (ctrl) {
  261. X                        return(tx);
  262. X                    } else {
  263. X                        begin = begin->t_next;
  264. X                        continue;
  265. X                    }
  266. X                }
  267. X            }
  268. X            error(begin->t_line, "unmatched parenthesis");
  269. X            break;
  270. X
  271. X        case T_WHILE:
  272. X        case T_FOR:
  273. X        case T_SWITCH:
  274. X        case T_IF:
  275. X            break;
  276. X
  277. X
  278. X        case T_RBRACE:
  279. X        case T_LBRACE:
  280. X        case T_SEMIC:
  281. X            return(begin);
  282. X
  283. X        case T_QUEST:
  284. X            seenquest++;
  285. X            begin = begin->t_next;
  286. X            continue;
  287. X
  288. X        case T_COLON:
  289. X            if (seenquest--) {
  290. X                return(begin);
  291. X            }
  292. X        default:
  293. X            begin = begin->t_next;
  294. X            continue;
  295. X        }
  296. X        /* if we get here, it's an error */
  297. X        break;
  298. X    }
  299. X    error(begin->t_line, "expression error");
  300. X    return(NILTOK);
  301. X}
  302. X
  303. Xdoexpand(mem,begin,end,here,expr,enode)
  304. Xregister int mem;
  305. Xregister int expr;
  306. Xregister struct token *begin, *end, *here;
  307. Xregister struct expand_node *enode;
  308. X{
  309. X    struct toklist insert;
  310. X    register struct token *tl, *tx, *th, *tp;
  311. X    register struct inline_node *node;
  312. X    register int formal;
  313. X    register int i;
  314. X    static int ident = 0;
  315. X
  316. X    if ((here->t_tok != T_ARGLIST) || !(node = isinline(here->t_id))) {
  317. X        error(here->t_line, "bad call to doexpand '%s' not inline",
  318. X            here->t_id);
  319. X        return(0);
  320. X    }
  321. X    if (expr && !node->i_flags&I_EXPR) {
  322. X        error(here->t_line, "bad call to doexpand '%s' not inline",
  323. X            here->t_id);
  324. X        return(0);
  325. X    }
  326. X
  327. X    insert.tl_head = insert.tl_tail = NILTOK;
  328. X
  329. X    addtok(&insert, newtok(mem,T_WS, "\n"));
  330. X    addtok(&insert, newtok(mem,T_LBRACE, NIL));
  331. X    addtok(&insert, newtok(mem,T_WS, "\n"));
  332. X
  333. X    /* output declaration sections for each inline */
  334. X    /* declare formal parameters */
  335. X
  336. X    cpytoklist(mem,&insert,&node->i_tl[SDECLBODY]);
  337. X    if (expr) {
  338. X        cpytoklist(mem,&insert,&node->i_tl[SEXPRDECL]);
  339. X    }
  340. X
  341. X    for(tx = insert.tl_head; tx != NILTOK; tx = tx->t_next) {
  342. X        if (tx->t_tok == T_FORMAL) {
  343. X            tx->t_flags |= TNOEXPAND;
  344. X        }
  345. X    }
  346. X
  347. X    /* declare return value holders */
  348. X
  349. X    if (node->i_flags&NEEDRETVAL) {
  350. X        addtok(&insert, newtok(mem,T_AUTO,NIL));
  351. X        addtok(&insert, newtok(mem,T_WS, " "));
  352. X
  353. X        /* cpytoklist(mem, &insert, &node->i_tl[SDECL]); */
  354. X
  355. X        /*
  356. X         * this is a hack to rewrite function pointers found in
  357. X         * declaration form, e.g:
  358. X         *    int (*(*fp())())() {}        [1]
  359. X         *    int (*fp())() {}        [2]
  360. X         * into pointer declaration form:
  361. X         *    int (*(*fp)())();        [1]
  362. X         *    int (*fp)();            [2]
  363. X         *
  364. X         * we do this by putting an RPAREN immediately after the
  365. X         * identifier, and then deleting the next RPAREN of the
  366. X         * appropriate nesting level.
  367. X         *
  368. X         * thanks to the bizarre syntax of C for this one
  369. X         */
  370. X
  371. X        {
  372. X        int plev = -1;
  373. X        for(tp = node->i_tl[SDECL].tl_head;tp != NILTOK; tp = tp->t_next) {
  374. X            if (tp->t_tok == T_RPAREN && tp->t_paren == plev) {
  375. X                plev = -1;
  376. X                continue;
  377. X            }
  378. X            if ((tp->t_tok == T_LPAREN) && (tp->t_paren > 0) &&
  379. X                (tp->t_next->t_tok == T_RPAREN)) {
  380. X                addtok(&insert,newtok(mem,T_RPAREN,NIL));
  381. X                plev = tp->t_paren - 1;
  382. X            }
  383. X            addtok(&insert,duptok(mem,tp));
  384. X        }
  385. X        }
  386. X
  387. X        /* end of hack */
  388. X
  389. X        addtok(&insert, newtok(mem,T_SEMIC,NIL));
  390. X        addtok(&insert, newtok(mem,T_WS, "\n"));
  391. X    }
  392. X
  393. X    /* determine which actuals can be substituted directly, and    */
  394. X    /* which need to be copied in  --  if the formal is never used    */
  395. X    /* as an lvalue in the expanded routine, and if the actual    */
  396. X    /* doesn't have any side-effects of referencing it, then it is    */
  397. X    /* ok to replace instances of the formal with the actual string    */
  398. X
  399. X    /* output initialization */
  400. X    /* ... but only for those not sub'd directly */
  401. X
  402. X    /* cpytoklist(mem,&insert,&node->i_tl[SINITBODY]); */
  403. X
  404. X    for (i = 0; i < node->i_nformals; i++) {
  405. X        node->i_formalinfo[i] &= ~I_SUB_OK;
  406. X        if ((node->i_formalinfo[i]&I_LVALUE) ||
  407. X            (sideeffect(&enode->e_actuals[i]))) {
  408. X            addtok(&insert,newtok(mem,T_FORMAL,node->i_formals[i]));
  409. X            /* addtok(&insert,newtok(mem,T_EQ,NIL)); */
  410. X            addtok(&insert,newtok(mem,T_ACTUAL,node->i_formals[i]));
  411. X            addtok(&insert,newtok(mem,T_SEMIC,NIL));
  412. X            addtok(&insert,newtok(mem,T_WS," "));
  413. X        } else {
  414. X            /* this actual can be sub'd directly */
  415. X            node->i_formalinfo[i] |= I_SUB_OK;
  416. X        }
  417. X    }
  418. X
  419. X    /* output body */
  420. X
  421. X
  422. X    here->t_tok = T_WS;
  423. X    here->t_id = "";
  424. X
  425. X    if (expr) {
  426. X        (void) instok(begin, insert.tl_head);
  427. X        insert.tl_head = insert.tl_tail = NILTOK;
  428. X        cpytoklist(mem,&insert,&node->i_tl[SEXPRBODY]);
  429. X        (void) instok(here, insert.tl_head);
  430. X    } else {
  431. X        cpytoklist(mem,&insert,&node->i_tl[SBODY]);
  432. X        if (node->i_flags&NEEDRETVAL) {
  433. X            here->t_tok = T_IDENT;
  434. X            here->t_id = mkstr(mem,"_",node->i_id,"_ret_",itoa(ident),"_",0);
  435. X        }
  436. X        (void) instok(begin, insert.tl_head);
  437. X    }
  438. X
  439. X    tl = instok(end, newtok(mem,T_RBRACE, NIL));
  440. X    end = instok(tl, newtok(mem,T_WS, "\n"));
  441. X
  442. X    /* go back and fix up all the special stuff */
  443. X
  444. X    for(tp = NILTOK,tx = begin; tx && tx != end; tp = tx,tx = tx->t_next) {
  445. X        switch(tx->t_tok) {
  446. X        case T_RETLAB:
  447. X            tx->t_tok = T_IDENT;
  448. X            tx->t_id = mkstr(mem,"_",node->i_id,"_end_",itoa(ident),"_",0);
  449. X            break;
  450. X
  451. X        case T_RETVAL:
  452. X            tx->t_tok = T_IDENT;
  453. X            tx->t_id = mkstr(mem,"_",node->i_id,"_ret_",itoa(ident),"_",0);
  454. X            break;
  455. X
  456. X        case T_FORMAL:
  457. X            if ((formal = isformal(node,tx)) < 0) {
  458. X                error(tx->t_line,"bogus formal");
  459. X                break;
  460. X            }
  461. X            if ((node->i_formalinfo[formal]&I_SUB_OK) && !(tx->t_flags&TNOEXPAND)) {
  462. X                insert.tl_head = insert.tl_tail = NILTOK;
  463. X                addtok(&insert,newtok(mem,T_LPAREN,NIL));
  464. X                cpytoklist(mem,&insert,&enode->e_actuals[formal]);
  465. X                addtok(&insert,newtok(mem,T_RPAREN,NIL));
  466. X                tp->t_next = tx->t_next;    /* drop formal node */
  467. X                (void) instok(tp, insert.tl_head);
  468. X
  469. X            } else {
  470. X                tx->t_tok = T_IDENT;
  471. X                tx->t_id = mkstr(mem,"_",node->i_id,"_",tx->t_id,"_",itoa(ident),0);
  472. X                tx->t_flags &= ~TNOEXPAND;
  473. X            }
  474. X            break;
  475. X
  476. X        case T_ACTUAL:
  477. X            if ((formal = isformal(node,tx)) < 0) {
  478. X                error(tx->t_line,"actual-formal mismatch");
  479. X                break;
  480. X            }
  481. X            insert.tl_head = insert.tl_tail = NILTOK;
  482. X            addtok(&insert, newtok(mem,T_WS, " "));
  483. X            addtok(&insert, newtok(mem,T_EQ, NIL));
  484. X            addtok(&insert, newtok(mem,T_WS, " "));
  485. X            cpytoklist(mem,&insert,&enode->e_actuals[formal]);
  486. X            tp->t_next = tx->t_next;    /* drop formal node */
  487. X            (void) instok(tp, insert.tl_head);
  488. X
  489. X            break;
  490. X
  491. X        case T_LABEL:
  492. X            tx->t_id = mkstr(mem,"_",node->i_id,"_",tx->t_id,"_",itoa(ident),0);
  493. X            break;
  494. X        }
  495. X    }
  496. X
  497. X    /* update expansion identifier digit */
  498. X    ident++;
  499. X
  500. X    return(1);
  501. X}
  502. X
  503. X/*
  504. X * begin an inline expansion by gathering actual arguments
  505. X */
  506. X
  507. Xstruct expand_node *
  508. Xdoactuals(mem,prog,node)
  509. Xregister int mem;
  510. Xstruct token *prog;
  511. Xstruct inline_node *node;
  512. X{
  513. X    register struct token *tl;
  514. X    int paramnest = 0;
  515. X    register struct toklist *subparam;
  516. X    struct expand_node *e;
  517. X    int sawtok = 0;
  518. X
  519. X    for (tl = prog->t_next; tl != NILTOK; tl = tl->t_next) {
  520. X        if (tl->t_tok == T_LPAREN)
  521. X            break;
  522. X    }
  523. X
  524. X    if (!tl) {    /* error */
  525. X        error(prog->t_line, "gack!! lost '(' in doactuals()");
  526. X        return(NILP(struct expand_node *));
  527. X    }
  528. X
  529. X    /* setup an expansion node for this expansion */
  530. X
  531. X    e = mkenode(mem);
  532. X    e->e_node = node;
  533. X    subparam = e->e_actuals;
  534. X
  535. X    /* store the actuals away in the expansion node */
  536. X
  537. X    for (  ; tl != NILTOK; tl = tl->t_next) {
  538. X        /* gather the actual parameter list */
  539. X        switch(tl->t_tok) {
  540. X        case T_LPAREN:
  541. X            if (paramnest++ == 0) {
  542. X                /* don't add the paren */
  543. X                continue;
  544. X            }
  545. X            break;
  546. X
  547. X        case T_RPAREN:
  548. X            if (paramnest == 0) {
  549. X                error(tl->t_line, "bad parameter list - too many ')'s");
  550. X                return(NILP(struct expand_node *));
  551. X            }
  552. X            if (--paramnest == 0) {    /* end of parameter list */
  553. X                if (sawtok) {
  554. X                    e->e_nactuals++;
  555. X                }
  556. X                if (e->e_nactuals != node->i_nformals) {
  557. X                    error(tl->t_line, "wrong number of actuals to inline func %s", node->i_id);
  558. X                    return(NILP(struct expand_node *));
  559. X                }
  560. X                /* replace to argument list with the ARGLIST token */
  561. X                prog->t_next = newtok(mem,T_ARGLIST,e->e_node->i_id);
  562. X                prog->t_next->t_next = tl->t_next;
  563. X
  564. X                return(e);
  565. X            }
  566. X            break;
  567. X
  568. X        case T_COMMA:
  569. X            if (paramnest == 1) {
  570. X                subparam++;
  571. X                e->e_nactuals++;
  572. X                sawtok = 0;
  573. X                /* don't include the comma */
  574. X                continue;
  575. X            }
  576. X            break;
  577. X        }
  578. X        if (paramnest) {
  579. X            sawtok = 1;
  580. X            addtok(subparam,duptok(mem,tl));
  581. X        }
  582. X    }
  583. X    /* hmm, got an EOF */
  584. X    error(prog->t_line, "improper call - EOF during arg gathering");
  585. X    return(NILP(struct expand_node *));
  586. X}
  587. X
  588. Xstruct expand_node *
  589. Xmkenode(mem) {
  590. X    register struct expand_node *e;
  591. X    register int i;
  592. X
  593. X    e = (struct expand_node *) getmem(mem,1,sizeof(struct expand_node));
  594. X    
  595. X    e->e_node = NILP(struct inline_node *);
  596. X    e->e_multiple = 0; /* more than one call to this inline */
  597. X    for (i = 0; i < NFORMALS; i++) {
  598. X        e->e_actuals[i].tl_head = NILTOK;
  599. X        e->e_actuals[i].tl_tail = NILTOK;
  600. X    }
  601. X    e->e_nactuals = 0;
  602. X    return(e);
  603. X}
  604. X
  605. Xsideeffect(tl)
  606. Xregister struct toklist *tl;
  607. X{
  608. X    register struct token *t,*tp;
  609. X
  610. X    tp = NILTOK;
  611. X    for (t = tl->tl_head; t != NILTOK; t = t->t_next) {
  612. X        switch(t->t_tok) {
  613. X        case T_EQ:    case T_RS_EQ:    case T_LS_EQ:
  614. X        case T_ADD_EQ:    case T_SUB_EQ:    case T_MUL_EQ:
  615. X        case T_DIV_EQ:    case T_MOD_EQ:    case T_AND_EQ:
  616. X        case T_XOR_EQ:    case T_OR_EQ:
  617. X        case T_INC:    case T_DEC:    
  618. X            return(1);
  619. X
  620. X        case T_LPAREN:
  621. X            /* function call */
  622. X            /* catches "fp(x)", "(*fp)(x)", "fp[foo](x)" */
  623. X            if (tp && (
  624. X                (tp->t_tok == T_IDENT) ||
  625. X                (tp->t_tok == T_RPAREN) ||
  626. X                (tp->t_tok == T_RSQ)
  627. X               )) {
  628. X                return(1);
  629. X            }
  630. X            break;
  631. X
  632. X        case T_LBRACE: case T_RBRACE:
  633. X            error(tp->t_line, "brace in actual argument", 0);
  634. X            return(1);
  635. X
  636. X        case T_WS: case T_COMMENT:
  637. X            break;
  638. X
  639. X        default:
  640. X            if (istype(t)) {    /* must be a cast */
  641. X                return(1);    /* ???? */
  642. X            }
  643. X            tp = t;        /* save previous non-ws token */
  644. X            break;
  645. X        }
  646. X        if (t == tl->tl_tail) {
  647. X            break;
  648. X        }
  649. X    }
  650. X    return(0);
  651. X}
  652. X
  653. \Rogue\Monster\
  654. else
  655.   echo "will not over write ./expand.c"
  656. fi
  657. chmod 444 ./expand.c
  658. if [ `wc -c ./expand.c | awk '{printf $1}'` -ne 14621 ]
  659. then
  660. echo `wc -c ./expand.c | awk '{print "Got " $1 ", Expected " 14621}'`
  661. fi
  662. if `test ! -s ./rewrite.c`
  663. then
  664. echo "writing ./rewrite.c"
  665. sed 's/^X//' > ./rewrite.c << '\Rogue\Monster\'
  666. X/*
  667. X * inline code expander - rewrite a procedure into an expression if possible
  668. X *
  669. X * (c) 1986 - copyright 1986, s. mcgeady, all rights reserved
  670. X */
  671. X
  672. X/* $Header: rewrite.c,v 1.3 87/05/12 10:53:05 mcg Rel $ */
  673. X
  674. X#include "inline.h"
  675. X#include "tokens.h"
  676. X
  677. Xextern struct token *dostmt();        /* see expand.c */
  678. Xextern struct token *doexpr();        /* see expand.c */
  679. X
  680. X
  681. X/*
  682. X * This module takes arbitrary sequences of C statements (assumed to be
  683. X * the output of the inline declaration process), and rewrites them, if
  684. X * possible, in an expression form, depositing the result in the
  685. X * appropriate place (i_tl[SEXPRBODY]) in the inline node structure.
  686. X *
  687. X * This is done, fundamentally, by replacing semicolons with commas,
  688. X * and deleting if's, following if conditional expressions with '?', and
  689. X * replacing else's with ':'.  Clearly, it is somewhat more complex than
  690. X * that, but most of the difficulty merely comes in keeping one's
  691. X * parentheses matched.
  692. X *
  693. X * One subtlety is that local declarations need to be factored out,
  694. X * except that if they contain initializations, the initializations need
  695. X * to be separated from the declarations and prepended to the expression
  696. X * list.  This is handled by the routine coalesce().  Coalesce() also
  697. X * needs to handle name conflicts caused by local variables declared in
  698. X * inner scopes when it is moving these to outer scopes.
  699. X *
  700. X * If rewrite() finds a statement that it can't rewrite into an expression
  701. X * (this class consists entirely of loops (while(), for()), goto's, and
  702. X * switch statements, and the break's and continue's that go along with
  703. X * these), then it returns -1, and the calling routine (declare.c:dodecl())
  704. X * frees the memory pool associated with it.
  705. X */
  706. X
  707. X
  708. Xstatic int saw_innerret = 0;
  709. X
  710. X
  711. X/* turn a basic block into an expression */
  712. X
  713. Xrewrite(node,tl,toplevel)
  714. Xregister struct inline_node *node;
  715. Xregister struct toklist *tl;
  716. Xregister int toplevel;
  717. X{
  718. X    register struct token *tx, *tt;
  719. X    register struct token *estart;    /* start of current expression */
  720. X    register struct token *bstart;    /* start of this block */
  721. X    register struct token *last = NILTOK;
  722. X    struct toklist *expr = &node->i_tl[SEXPRBODY];
  723. X    register int mem = node->i_exprmem;
  724. X    struct toklist block;
  725. X    register int inblock = 0;
  726. X    register int ntok = 0;
  727. X    int saw_topret = 0;
  728. X    int nonempty = 0;
  729. X
  730. X
  731. X    /* skip over leading whitespace */
  732. X
  733. X    tx = skipws(tl->tl_head);
  734. X    if (tx->t_tok == T_LBRACE) {
  735. X        inblock++;
  736. X    }
  737. X    if (toplevel) {
  738. X        addtok(expr,last = bstart = estart = newtok(mem,T_WS,""));
  739. X        saw_innerret = 0;
  740. X    } else {
  741. X        bstart = estart = expr->tl_tail;
  742. X    }
  743. X
  744. X    for(  ; tx && tx != tl->tl_tail; last = tx, tx = tx->t_next) {
  745. X        if (istype(tx) || isstoreclass(tx)) {
  746. X            /* local definition block */
  747. X            block.tl_head = tx;
  748. X            tx = block.tl_tail = dostmt(tx,0);
  749. X
  750. X            if (tx->t_tok != T_SEMIC) {
  751. X                /* weird */
  752. X                return(-1);
  753. X            }
  754. X
  755. X            if (ntok = coalesce(node,&block)) {
  756. X                nonempty++;
  757. X            }
  758. X        }
  759. X
  760. X
  761. X        switch(tx->t_tok) {
  762. X        case T_CONTINUE:
  763. X        case T_BREAK:
  764. X            /*FALLTHROUGH*/
  765. X        case T_WHILE:
  766. X        case T_FOR:
  767. X        case T_SWITCH:
  768. X            return(-1);
  769. X
  770. X        case T_RBRACE:
  771. X            if (inblock && tx->t_level == tl->tl_head->t_level) {
  772. X                goto end;
  773. X            }
  774. X            /*FALLTHROUGH*/
  775. X
  776. X        case T_LBRACE:
  777. X            break;
  778. X
  779. X        case T_GOTO:
  780. X            /* if it's not a rewritten return(), it's an error */
  781. X            if (tx->t_next->t_next->t_tok == T_RETLAB) {
  782. X                tx = dostmt(tx,0);
  783. X                break;
  784. X            }
  785. X            return(-1);
  786. X
  787. X        case T_IF:
  788. X            block.tl_head = skipws(tx->t_next);
  789. X            block.tl_tail = doexpr(block.tl_head,1);
  790. X
  791. X            /* copy control part */
  792. X            cpytoklist(mem,expr,&block);
  793. X
  794. X            addtok(expr,newtok(mem,T_QUEST,NIL));
  795. X            addtok(expr,newtok(mem,T_WS," "));
  796. X
  797. X            block.tl_head = skipws(block.tl_tail->t_next);
  798. X            block.tl_tail = dostmt(block.tl_head,0);
  799. X
  800. X            if ((ntok = rewrite(node,&block,0)) < 0) {
  801. X                return(-1);
  802. X            }
  803. X            /* if no tokens added - i.e. empty block */
  804. X            if (ntok == 0) {
  805. X                addtok(expr,newtok(mem,T_NUM,"0"));
  806. X            }
  807. X
  808. X            addtok(expr,newtok(mem,T_COLON,NIL));
  809. X            addtok(expr,newtok(mem,T_WS," "));
  810. X
  811. X            tx = skipws(block.tl_tail->t_next);
  812. X            if (tx && tx != tl->tl_tail) {
  813. X                if (tx->t_tok != T_ELSE) {
  814. X                    /* no else - treat rest of block like else */
  815. X                    block.tl_head = tx;
  816. X                    tx = block.tl_tail = tl->tl_tail;
  817. X                    if ((ntok = rewrite(node,&block,0)) < 0) {
  818. X                        return(-1);
  819. X                    }
  820. X                } else {
  821. X                    block.tl_head = skipws(tx->t_next);
  822. X                    tx = block.tl_tail = dostmt(block.tl_head,0);
  823. X                    if ((ntok = rewrite(node,&block,0)) < 0) {
  824. X                        return(-1);
  825. X                    }
  826. X                }
  827. X            } else {
  828. X                ntok = 0;
  829. X            }
  830. X            /* if no tokens added - i.e. empty block */
  831. X            if (ntok == 0) {
  832. X                addtok(expr,newtok(mem,T_NUM,"0"));
  833. X            }
  834. X            ntok = 1;
  835. X            nonempty++;
  836. X            /*FALLTHROUGH*/
  837. X
  838. X        case T_SEMIC:
  839. X            if (ntok == 0) {
  840. X                break;
  841. X            }
  842. X            /* if there was a preceding expression, insert a comma */
  843. X            if (estart && estart->t_tok == T_RPAREN) {
  844. X                instok(estart,tt = newtok(mem,T_COMMA,NIL));
  845. X                estart = tt;
  846. X            }
  847. X
  848. X            /* wrap some parens around the expression itself */
  849. X            instok(estart,newtok(mem,T_LPAREN,NIL));
  850. X            addtok(expr,newtok(mem,T_RPAREN,NIL));
  851. X
  852. X            /* ... and around the whole expression so far */
  853. X            if (bstart && bstart != expr->tl_head) {
  854. X                instok(bstart,newtok(mem,T_LPAREN,NIL));
  855. X                addtok(expr,newtok(mem,T_RPAREN,NIL));
  856. X            }
  857. X            estart = expr->tl_tail;
  858. X            bstart = bstart->t_next;
  859. X            ntok = 0;
  860. X            nonempty++;
  861. X            if (debug >= 9) {
  862. X                fprintf(stderr,"> ");
  863. X                prtoklist(expr,0,stderr);
  864. X                fprintf(stderr,"\n");
  865. X            }
  866. X            break;
  867. X
  868. X        case T_WS:
  869. X            if (last && last->t_tok != T_WS &&
  870. X                last->t_tok != T_RPAREN &&
  871. X                last->t_tok != T_LPAREN) {
  872. X                addtok(expr,newtok(mem,T_WS," "));
  873. X            }
  874. X            break;
  875. X
  876. X        case T_RETVAL:
  877. X            if (toplevel) {
  878. X                saw_topret++;
  879. X                for ( ; tx && tx != tl->tl_tail; tx = tx->t_next) {
  880. X                    if (tx->t_tok == T_EQ) {
  881. X                        break;
  882. X                    }
  883. X                }
  884. X                break;
  885. X            } else {
  886. X                saw_innerret++;
  887. X            }
  888. X            /*FALLTHROUGH*/
  889. X        default:
  890. X            addtok(expr,duptok(mem,tx));
  891. X            ntok++;
  892. X            nonempty++;
  893. X            break;
  894. X        }
  895. X    }
  896. X    end:
  897. X    if (toplevel) {
  898. X        if (saw_innerret == 0 && saw_topret == 0) {
  899. X            /* no returns, must be void */
  900. X            return(-1);
  901. X        }
  902. X        if (saw_innerret) {
  903. X            if (expr->tl_head != expr->tl_tail) {
  904. X                addtok(expr,newtok(mem,T_COMMA,NIL));
  905. X            }
  906. X            addtok(expr,newtok(mem,T_RETVAL,NIL));
  907. X        }
  908. X        instok(expr->tl_head,newtok(mem,T_LPAREN,NIL));
  909. X        addtok(expr,newtok(mem,T_RPAREN,NIL));
  910. X        fixparens(expr,0,0);
  911. X    }
  912. X    if (debug >= 9) {
  913. X        fprintf(stderr,"% ");
  914. X        prtoklist(expr,0,stderr);
  915. X        fprintf(stderr,"\n");
  916. X    }
  917. X    return(nonempty);
  918. X}
  919. X
  920. X
  921. Xcoalesce(node,tl)
  922. Xregister struct inline_node *node;
  923. Xregister struct toklist *tl;
  924. X{
  925. X    register struct token *tx, *ts, *estart, *bstart;
  926. X    struct toklist *expr = &node->i_tl[SEXPRBODY];
  927. X    struct toklist *exprdecl = &node->i_tl[SEXPRDECL];
  928. X    register int mem = node->i_exprmem;
  929. X    int initializer = 0;
  930. X    int ntok = 0;
  931. X
  932. X    bstart = expr->tl_tail;
  933. X
  934. X    /* copy up to an '=' or ';' */
  935. X    for(tx = tl->tl_head; tx && tx != tl->tl_tail->t_next; tx = tx->t_next) {
  936. X        if (!initializer) {
  937. X            if (tx->t_tok == T_IDENT) {
  938. X                ts = tx;    /* save for future reference */
  939. X            }
  940. X            if (tx->t_tok != T_EQ) {
  941. X                addtok(exprdecl,duptok(mem,tx));
  942. X                if (tx->t_tok == T_SEMIC) {
  943. X                    return(ntok);
  944. X                }
  945. X                continue;
  946. X            }
  947. X            estart = expr->tl_tail;
  948. X            /* an '=' */
  949. X            addtok(expr,duptok(mem,ts));
  950. X            addtok(expr,newtok(mem,T_WS," "));
  951. X            ntok++;
  952. X            initializer = 1;
  953. X        }
  954. X        /* in initializer */
  955. X
  956. X        /* look for ',' or ';' terminating initialization */
  957. X        if ((tx->t_tok == T_COMMA && tx->t_paren <= ts->t_paren)
  958. X             || tx->t_tok == T_SEMIC) {
  959. X
  960. X            addtok(exprdecl,duptok(mem,tx));
  961. X
  962. X            /* if there was a preceeding expr, prepend a comma */
  963. X            if (estart && estart->t_tok == T_RPAREN) {
  964. X                instok(estart,ts = newtok(mem,T_COMMA,NIL));
  965. X                 estart = ts;
  966. X            }
  967. X
  968. X            /* wrap some parens around this expr */
  969. X            instok(estart,newtok(mem,T_LPAREN,NIL));
  970. X            addtok(expr,newtok(mem,T_RPAREN,NIL));
  971. X
  972. X            /* ... and around the whole expression so far */
  973. X            if (bstart && bstart != estart) {
  974. X                instok(bstart,newtok(mem,T_LPAREN,NIL));
  975. X                addtok(expr,newtok(mem,T_RPAREN,NIL));
  976. X            }
  977. X            estart = expr->tl_tail;
  978. X            bstart = bstart->t_next;
  979. X            initializer = 0;
  980. X            if (debug >= 9) {
  981. X                fprintf(stderr,">> ");
  982. X                prtoklist(expr,0,stderr);
  983. X                fprintf(stderr,"\n");
  984. X            }
  985. X        } else {
  986. X            addtok(expr,duptok(mem,tx));
  987. X        }
  988. X    }
  989. X    if (debug >= 9) {
  990. X        fprintf(stderr,">> ");
  991. X        prtoklist(expr,0,stderr);
  992. X        fprintf(stderr,"\n");
  993. X    }
  994. X    return(ntok);
  995. X}
  996. \Rogue\Monster\
  997. else
  998.   echo "will not over write ./rewrite.c"
  999. fi
  1000. chmod 444 ./rewrite.c
  1001. if [ `wc -c ./rewrite.c | awk '{printf $1}'` -ne 8260 ]
  1002. then
  1003. echo `wc -c ./rewrite.c | awk '{print "Got " $1 ", Expected " 8260}'`
  1004. fi
  1005. if `test ! -s ./yylex.c`
  1006. then
  1007. echo "writing ./yylex.c"
  1008. sed 's/^X//' > ./yylex.c << '\Rogue\Monster\'
  1009. X/*
  1010. X * inline code expander
  1011. X *
  1012. X * (c) 1986,1987 - copyright 1986,1987, s. mcgeady, all rights reserved
  1013. X */
  1014. X
  1015. X/*
  1016. X * fast lexer for C
  1017. X */
  1018. X
  1019. X/* $Header: yylex.c,v 1.9 87/06/24 13:05:47 mcg Rel $ */
  1020. X
  1021. X#include "inline.h"
  1022. X#include <ctype.h>
  1023. X#include "tokens.h"
  1024. X
  1025. X#define    MAXLEXBUF    1024
  1026. X
  1027. X/* you can use these macros on any machine with stdio guts like a VAX */
  1028. X#if defined(vax) || defined(sun) || defined(gould) || defined(pyr)
  1029. X
  1030. X#ifndef lint
  1031. X#define    peekc(p)   ((p)->_cnt > 0 ? (int)(*(unsigned char *)(p)->_ptr) \
  1032. X            :((_filbuf(p) == EOF) ? EOF :            \
  1033. X                ((p)->_cnt++),(int)(*(unsigned char *)(--(p)->_ptr))))
  1034. X
  1035. X
  1036. X#define ungetc(c, p)    ((c) == EOF) ? EOF : ((p)->_cnt++ == 0 ?    \
  1037. X        (((p)->_ptr == (p)->_base) ?                 \
  1038. X        *(p)->_ptr = (c) : (*--((p)->_ptr) = (c)))        \
  1039. X        : (((p)->_ptr == (p)->_base) ? (p)->_cnt--,EOF :     \
  1040. X        (*--((p)->_ptr) = (c))))
  1041. X
  1042. X#endif
  1043. X#else
  1044. Xstatic int _pc;        /* 'peek'ed character holder */
  1045. X
  1046. X#define    peekc(p)    ((_pc = getc(p),ungetc(_pc,p)),_pc)
  1047. X#endif
  1048. X
  1049. Xextern char *gather();
  1050. X
  1051. X#ifndef NIL
  1052. X#define NIL (char *) 0
  1053. X#endif
  1054. X
  1055. X/* 33 keywords */
  1056. Xstruct keys {
  1057. X    char    *k_str;
  1058. X    int    k_val;
  1059. X} kw[8][10] = {
  1060. X{
  1061. X    { NIL,        0,        /* */ },
  1062. X},
  1063. X{
  1064. X    { "do",        T_DO,        /* do */ },
  1065. X    { "if",        T_IF,        /* if */ },
  1066. X    { NIL,        0,        /* */ },
  1067. X},
  1068. X{
  1069. X    { "for",    T_FOR,        /* for */ },
  1070. X    { "int",    T_INT,        /* int */ },
  1071. X    { NIL,        0,        /* */ },
  1072. X},
  1073. X{
  1074. X    { "auto",    T_AUTO,        /* auto */ },
  1075. X    { "case",    T_CASE,        /* case */ },
  1076. X    { "char",    T_CHAR,        /* char */ },
  1077. X    { "else",    T_ELSE,        /* else */ },
  1078. X    { "enum",    T_ENUM,        /* enum */ },
  1079. X    { "goto",    T_GOTO,        /* goto */ },
  1080. X    { "long",    T_LONG,        /* long */ },
  1081. X    { "void",    T_VOID,        /* void */ },
  1082. X    { NIL,        0,        /* */ },
  1083. X},
  1084. X{
  1085. X    { "break",    T_BREAK,    /* break */ },
  1086. X    { "const",    T_CONST,    /* const */ },
  1087. X    { "float",    T_FLOAT,    /* float */ },
  1088. X    { "short",    T_SHORT,    /* short */ },
  1089. X    { "union",    T_UNION,    /* union */ },
  1090. X    { "while",    T_WHILE,    /* while */ },
  1091. X    { NIL,        0,        /* */ },
  1092. X},
  1093. X{
  1094. X    { "double",    T_DOUBLE,    /* double */ },
  1095. X    { "extern",    T_EXTERN,    /* extern */ },
  1096. X    { "inline",    T_INLINE,    /* inline */ },
  1097. X    { "return",    T_RETURN,    /* return */ },
  1098. X    { "signed",    T_SIGNED,    /* signed */ },
  1099. X    { "sizeof",    T_SIZEOF,    /* sizeof */ },
  1100. X    { "static",    T_STATIC,    /* static */ },
  1101. X    { "struct",    T_STRUCT,    /* struct */ },
  1102. X    { "switch",    T_SWITCH,    /* switch */ },
  1103. X    { NIL,        0,        /* */ },
  1104. X},
  1105. X{
  1106. X    { "default",    T_DEFAULT,    /* default */ },
  1107. X    { "typedef",    T_TYPEDEF,    /* typedef */ },
  1108. X    { NIL,        0,         /* */ },
  1109. X},
  1110. X{
  1111. X    { "continue",    T_CONTINUE,    /* continue */ },
  1112. X    { "register",    T_REGISTER,    /* register */ },
  1113. X    { "unsigned",    T_UNSIGNED,    /* unsigned */ },
  1114. X    { "volatile",    T_VOLATILE,    /* volatile */ },
  1115. X    { NIL,        0,        /* */ },
  1116. X}
  1117. X};
  1118. X
  1119. Xiskeyword(s,n)
  1120. Xregister char *s;
  1121. Xregister int n;
  1122. X{
  1123. X    register struct keys *kwp;
  1124. X
  1125. X    kwp = &kw[n-1][0];
  1126. X
  1127. X    if (n < 2 || n > 8) return(0);
  1128. X    do {
  1129. X        if (s[0] != kwp->k_str[0] || s[1] != kwp->k_str[1])
  1130. X            continue;
  1131. X        if (strncmp(s,kwp->k_str,n) == 0)
  1132. X            return(kwp->k_val);
  1133. X    } while ((++kwp)->k_str);    /* fix thanks to ucbcad!thomas */
  1134. X    return(0);
  1135. X}
  1136. X
  1137. Xstatic char yytext[MAXLEXBUF];
  1138. Xstatic char *yylval;
  1139. Xint line = 1;
  1140. X
  1141. Xyylex(mem)
  1142. Xregister int mem;
  1143. X{
  1144. X    register int c, cc, pc;
  1145. X    register int len;
  1146. X    register char *p;
  1147. X    int base, i;
  1148. X
  1149. X    base = 10;
  1150. X    yylval = NIL;
  1151. X
  1152. X    if ((c = getc(stdin)) == EOF) {
  1153. X        return(0);
  1154. X    }
  1155. X    pc = peekc(stdin);
  1156. X    if (pc == '=') {
  1157. X        cc = getc(stdin);
  1158. X        switch(c) {
  1159. X            case '+': { return(T_ADD_EQ); }
  1160. X            case '-': { return(T_SUB_EQ); }
  1161. X            case '*': { return(T_MUL_EQ); }
  1162. X            case '/': { return(T_DIV_EQ); }
  1163. X            case '%': { return(T_MOD_EQ); }
  1164. X            case '&': { return(T_AND_EQ); }
  1165. X            case '^': { return(T_XOR_EQ); }
  1166. X            case '|': { return(T_OR_EQ); }
  1167. X            case '=': { return(T_CEQ); }
  1168. X            case '!': { return(T_NE); }
  1169. X            default:
  1170. X                ungetc(cc,stdin);
  1171. X                /* pc is correct */
  1172. X                break;
  1173. X        }
  1174. X    } else if (pc == c) {
  1175. X        cc = getc(stdin);
  1176. X        pc = peekc(stdin);
  1177. X        switch(c) {
  1178. X        case '+': { return(T_INC); }
  1179. X        case '-': { return(T_DEC); }
  1180. X        case '&': { return(T_CAND); }
  1181. X        case '|': { return(T_COR); }
  1182. X        case '>':        /* also >>, >>= */
  1183. X            if (pc == '=') {
  1184. X                getc(stdin);
  1185. X                return(T_RS_EQ);
  1186. X            }
  1187. X            return(T_RS);
  1188. X
  1189. X        case '<':        /* also <<, <<= */
  1190. X            if (pc == '=') {
  1191. X                getc(stdin);
  1192. X                return(T_LS_EQ);
  1193. X            }
  1194. X            return(T_LS);
  1195. X
  1196. X        default:
  1197. X            ungetc(cc,stdin);
  1198. X            pc = cc;
  1199. X            break;
  1200. X        }
  1201. X    }
  1202. X    switch(c) {
  1203. X    case '#':        /* CPP line */
  1204. X        yylval = gather(mem,T_CPP,"#");
  1205. X        return(T_CPP);
  1206. X
  1207. X
  1208. X    case '-':        /* also --, -=, -> */
  1209. X        if (pc == '>') { getc(stdin); return(T_PTR); }
  1210. X        return(T_MINUS);
  1211. X
  1212. X
  1213. X    case '/':        /* also /=, comment */
  1214. X        if (pc == '*') {    /* comment */
  1215. X            getc(stdin);
  1216. X            yylval = gather(mem,T_COMMENT,"/*");
  1217. X            return(T_COMMENT);
  1218. X        }
  1219. X        return(T_DIV);
  1220. X
  1221. X    case '<': return(T_LT);        /* also <<, <<= */
  1222. X    case '>': return(T_GT);        /* also >>, >>= */
  1223. X    case '+': return(T_PLUS);    /* also ++, += */
  1224. X    case '*': return(T_STAR);    /* also *= */
  1225. X    case '%': return(T_MOD);    /* also %= */
  1226. X    case '&': return(T_AMPER);    /* also &&, &= */
  1227. X    case '^': return(T_XOR);    /* also ^= */
  1228. X    case '|': return(T_OR);        /* also ||, |= */
  1229. X    case '=': return(T_EQ);        /* also == */
  1230. X    case '!': return(T_NOT);    /* also != */
  1231. X    case '.':            /* also ... */
  1232. X        if (pc == '.') {
  1233. X            cc = getc(stdin);
  1234. X            if (peekc(stdin) == '.') {
  1235. X                getc(stdin);
  1236. X                return(T_ELLIPSES);
  1237. X            }
  1238. X            ungetc(cc,stdin);
  1239. X        }
  1240. X        return(T_DOT);
  1241. X
  1242. X    case ';': return(T_SEMIC);
  1243. X    case '{': return(T_LBRACE);
  1244. X    case '}': return(T_RBRACE);
  1245. X    case ',': return(T_COMMA);
  1246. X    case ':': return(T_COLON);
  1247. X    case '(': return(T_LPAREN);
  1248. X    case ')': return(T_RPAREN);
  1249. X    case '[': return(T_LSQ);
  1250. X    case ']': return(T_RSQ);
  1251. X    case '~': return(T_TILDE);
  1252. X    case '?': return(T_QUEST);
  1253. X
  1254. X    case '\'':
  1255. X        yylval = gather(mem,T_CHARCONST,"'");
  1256. X        return(T_CHARCONST);
  1257. X
  1258. X    case '"':
  1259. X        yylval = gather(mem,T_STR,"\"");
  1260. X        return(T_STR);
  1261. X
  1262. X    case ' ': case '\t': case '\v': case '\n': case '\f':
  1263. X        p = yytext;
  1264. X        do {
  1265. X            *p++ = c;
  1266. X            if (c == '\n') line++;
  1267. X            c = peekc(stdin);
  1268. X        } while ((c == ' ' || c == '\t' || c == '\v' || c == '\n' ||
  1269. X              c == '\f') && (p < &yytext[MAXLEXBUF]) && 
  1270. X              ((c = getc(stdin)) != EOF));
  1271. X        *p = '\0';
  1272. X        yylval = yytext;
  1273. X        return(T_WS);
  1274. X
  1275. X    case '0':
  1276. X        p = yytext;
  1277. X        *p++ = c;
  1278. X        if (tolower(pc) == 'x') {
  1279. X            base = 16;
  1280. X            *p++ = getc(stdin);
  1281. X            c = getc(stdin);
  1282. X        } else if (tolower(pc) == 'f') {
  1283. X#ifdef notdef
  1284. X            /* 0finf or 0fnan(xxx) */
  1285. X            *p++ = getc(stdin);
  1286. X            base = -1;    /* FLOAT */
  1287. X            c = getc(stdin);
  1288. X#endif
  1289. X        } else if (isdigit(pc)) {
  1290. X            base = 8;
  1291. X            c = getc(stdin);
  1292. X        } else {
  1293. X            p = yytext;
  1294. X        }
  1295. X        /*FALLTHROUGH*/
  1296. X
  1297. X    case '1': case '2': case '3': case '4': case '5':
  1298. X    case '6': case '7': case '8': case '9':
  1299. X
  1300. X        if (base == 10) {
  1301. X            p = yytext;
  1302. X        }
  1303. X        do {
  1304. X            if (!isdigit(c) &&
  1305. X                !((c == '.') || (tolower(c) == 'e') ||
  1306. X                  (c == '+') || (c == '-'))) {
  1307. X                ungetc(c,stdin);
  1308. X                break;
  1309. X            }
  1310. X            *p++ = c;
  1311. X        } while((c = getc(stdin)) != EOF);
  1312. X        *p = '\0';
  1313. X        yylval = yytext;
  1314. X        return(T_NUM);
  1315. X
  1316. X    case EOF:
  1317. X        return(0);
  1318. X
  1319. X    default:    /* an identifier or keyword */
  1320. X        if ((c < ' ') || (c > '~') || !isalpha(c)) {
  1321. X            error(line,"illegal character");
  1322. X            yytext[0] = c; yytext[1] = '\0';
  1323. X            yylval = yytext;
  1324. X            return(T_WS);
  1325. X        }
  1326. X        /*FALLTHROUGH*/
  1327. X    case '_':
  1328. X        yytext[0] = c;
  1329. X        p = &yytext[1];
  1330. X        len = 1;
  1331. X        while((c = getc(stdin)) != EOF) {
  1332. X            if (!isalpha(c) && !isdigit(c) && c != '$' && c != '_') {
  1333. X                ungetc(c,stdin);
  1334. X                break;
  1335. X            }
  1336. X            *p++ = c;
  1337. X            len++;
  1338. X        }
  1339. X        *p = '\0';
  1340. X        if (i = iskeyword(yytext,len)) {
  1341. X            return(i);
  1342. X        } else {
  1343. X            yylval = yytext;
  1344. X            return(T_IDENT);
  1345. X        }
  1346. X    }
  1347. X    /*NOTREACHED*/
  1348. X}
  1349. X
  1350. X/*
  1351. X */
  1352. X
  1353. Xchar *
  1354. Xgather(mem,type,init)
  1355. Xregister int mem;
  1356. Xint type;
  1357. Xchar *init;
  1358. X{
  1359. X    char buf[MAXLEXBUF];
  1360. X    register int c;
  1361. X    register char *tbuf;
  1362. X    register int tbufsize = 0;
  1363. X    register char *bb = buf;
  1364. X    register char *p = bb;
  1365. X    register char *ebuf = &buf[MAXLEXBUF-1];
  1366. X    
  1367. X
  1368. X    strcpy(buf,init);
  1369. X    p = buf + strlen(init);
  1370. X    while ((c = getc(stdin)) != EOF) {
  1371. X        *p = c;
  1372. X        if (*p == 0)
  1373. X            break;
  1374. X
  1375. X        if (*p == '\n') line++;
  1376. X
  1377. X        switch (type) {
  1378. X        case T_COMMENT:
  1379. X            if (*p == '*' && peekc(stdin) == '/') {
  1380. X                *++p = getc(stdin);
  1381. X                goto end;
  1382. X            }
  1383. X            break;
  1384. X        case T_CPP:
  1385. X            if (*p == '\\') {
  1386. X                *++p = getc(stdin);
  1387. X            } else if (*p == '\n') {
  1388. X                /* ungetc(*p,stdin); */
  1389. X                goto end;
  1390. X            }
  1391. X            break;
  1392. X        case T_STR:
  1393. X            if (*p == '\\') {
  1394. X                *++p = getc(stdin);
  1395. X            } else if (*p == '\n') {
  1396. X                /* error */
  1397. X            } else if (*p == '"') {
  1398. X                goto end;
  1399. X            }
  1400. X            break;
  1401. X
  1402. X        case T_CHARCONST:
  1403. X            if (*p == '\\') {
  1404. X                *++p = getc(stdin);
  1405. X            } else if (*p == '\n') {
  1406. X                /* error */
  1407. X            } else if (*p == '\'') {
  1408. X                goto end;
  1409. X            }
  1410. X            break;
  1411. X        }
  1412. X        /* leave two slots open at end */
  1413. X        if (++p >= ebuf-1) {
  1414. X            *p = '\0';
  1415. X            if (tbufsize == 0) {
  1416. X                tbufsize = 1024;
  1417. X            }
  1418. X            if (mem < 0) {
  1419. X                tbuf = (char *) malloc((unsigned) (tbufsize *= 2));
  1420. X            } else {
  1421. X                tbuf = getmem(mem, 0, (unsigned) (tbufsize *= 2));
  1422. X            }
  1423. X            strcpy(tbuf, bb);
  1424. X            p = tbuf + (p - bb);
  1425. X            if (bb != buf) {
  1426. X                free(bb);
  1427. X            }
  1428. X            bb = tbuf;
  1429. X            ebuf = bb + tbufsize;
  1430. X        }
  1431. X    }
  1432. X    end:
  1433. X    *++p = '\0';
  1434. X    p++;
  1435. X    if (tbufsize == 0) {
  1436. X        if (mem < 0) {
  1437. X            tbuf = (char *) malloc((unsigned) (p-bb));
  1438. X        } else {
  1439. X            tbuf = getmem(mem, 0, (unsigned) (p-bb));
  1440. X        }
  1441. X        strcpy(tbuf, bb);
  1442. X        bb = tbuf;
  1443. X    }
  1444. X    return(bb);
  1445. X}
  1446. X
  1447. X
  1448. X#ifndef TEST
  1449. X
  1450. Xcheck_type(tok)
  1451. Xregister struct token *tok;
  1452. X{
  1453. X    register int i;
  1454. X    register char **p;
  1455. X
  1456. X    for (i = 0; (i < NSCOPE) && (typeid[i] != NILP(struct typelist *));i++) {
  1457. X        for (p = typeid[i]->type_id; *p != NIL; p++) {
  1458. X            if (strcmp(tok->t_id,*p) == 0) {
  1459. X                tok->t_tok = T_TYPE_ID;
  1460. X                return;
  1461. X            }
  1462. X        }
  1463. X    }
  1464. X}
  1465. X
  1466. Xstruct token *
  1467. Xgettok(mem)
  1468. Xregister int mem;
  1469. X{
  1470. X    register int t;
  1471. X    struct token *tok;
  1472. X    static int bracelev = 0;
  1473. X    static int parenlev = 0;
  1474. X
  1475. X    if ((t = yylex(mem)) == 0)
  1476. X        return((struct token *) 0);
  1477. X    tok = newtok(mem, t, yylval);
  1478. X    tok->t_line = line;
  1479. X    switch(t) {
  1480. X    case T_COMMENT:
  1481. X    case T_CPP:
  1482. X        tok->t_tok = T_WS;
  1483. X        /*FALLTHROUGH*/
  1484. X    case T_STR:
  1485. X        /* free(yylval); */
  1486. X        break;
  1487. X
  1488. X    case T_LBRACE:
  1489. X        tok->t_level = bracelev++;
  1490. X        tok->t_paren = parenlev;
  1491. X        pushscope(bracelev);
  1492. X        break;
  1493. X    case T_LPAREN:
  1494. X        tok->t_paren = parenlev++;
  1495. X        tok->t_level = bracelev;
  1496. X        break;
  1497. X    case T_RPAREN:
  1498. X        tok->t_level = bracelev;
  1499. X        tok->t_paren = --parenlev;
  1500. X        break;
  1501. X    case T_RBRACE:
  1502. X        popscope(bracelev);
  1503. X        tok->t_level = --bracelev;
  1504. X        tok->t_paren = parenlev;
  1505. X        break;
  1506. X
  1507. X    default:
  1508. X        tok->t_level = bracelev;
  1509. X        tok->t_paren = parenlev;
  1510. X        break;
  1511. X    }
  1512. X    if (t == T_IDENT) {
  1513. X        check_type(tok);
  1514. X    }
  1515. X    return(tok);
  1516. X}
  1517. X#endif
  1518. X
  1519. X#ifdef TEST
  1520. Xmain() {
  1521. X    int tok;
  1522. X    extern char *tokens[];
  1523. X
  1524. X    while(tok = yylex(-1)) {
  1525. X        switch (tok) {
  1526. X        case T_COMMENT:
  1527. X        case T_STR:
  1528. X        case T_CPP:
  1529. X            free(yylval);
  1530. X
  1531. X        case T_IDENT:
  1532. X        case T_WS:
  1533. X        case T_NUM:
  1534. X        case T_CHARCONST:
  1535. X        case T_TYPE_ID:
  1536. X            fputs(yylval,stdout);
  1537. X            break;
  1538. X        case T_ACTUAL:
  1539. X            fputs("<ACTUAL>",stdout);
  1540. X            break;
  1541. X        case T_RETVAL:
  1542. X            fputs("<RETVAL>",stdout);
  1543. X            break;
  1544. X        case T_ARGLIST:
  1545. X            fprintf(stdout,"%s(ARGLIST)", yylval);
  1546. X            break;
  1547. X        case T_RETLAB:
  1548. X            fputs("<RETLAB>",stdout);
  1549. X            break;
  1550. X        case T_FORMAL:
  1551. X            fprintf(stdout,"<FORMAL '%s'>",yylval);
  1552. X            break;
  1553. X        default:
  1554. X            if (tok <= T_INLINE)
  1555. X                fputs(tokens[tok],stdout);
  1556. X            else
  1557. X                fputs("???",stdout);
  1558. X
  1559. X            break;
  1560. X        }
  1561. X    }
  1562. X}
  1563. X#endif
  1564. \Rogue\Monster\
  1565. else
  1566.   echo "will not over write ./yylex.c"
  1567. fi
  1568. chmod 444 ./yylex.c
  1569. if [ `wc -c ./yylex.c | awk '{printf $1}'` -ne 10795 ]
  1570. then
  1571. echo `wc -c ./yylex.c | awk '{print "Got " $1 ", Expected " 10795}'`
  1572. fi
  1573. if `test ! -s ./tokens.c`
  1574. then
  1575. echo "writing ./tokens.c"
  1576. sed 's/^X//' > ./tokens.c << '\Rogue\Monster\'
  1577. X/*
  1578. X * inline code expander
  1579. X *
  1580. X * (c) 1986 - copyright 1986, s. mcgeady, all rights reserved
  1581. X */
  1582. X
  1583. X/* $Header: tokens.c,v 1.3 87/04/27 18:16:52 mcg Rel $ */
  1584. X
  1585. X
  1586. Xchar *tokens[] =  {
  1587. X    "",
  1588. X    "auto",
  1589. X    "break",
  1590. X    "case",
  1591. X    "char",
  1592. X    "const",
  1593. X    "continue",
  1594. X    "default",
  1595. X    "do",
  1596. X    "double",
  1597. X    "else",
  1598. X    "enum",
  1599. X    "extern",
  1600. X    "float",
  1601. X    "for",
  1602. X    "goto",
  1603. X    "if",
  1604. X    "int",
  1605. X    "long",
  1606. X    "register",
  1607. X    "return",
  1608. X    "short",
  1609. X    "signed",
  1610. X    "sizeof",
  1611. X    "static",
  1612. X    "struct",
  1613. X    "switch",
  1614. X    "typedef",
  1615. X    "union",
  1616. X    "unsigned",
  1617. X    "void",
  1618. X    "volatile",
  1619. X    "while",
  1620. X    "...",
  1621. X    "=",
  1622. X    ",",
  1623. X    "{",
  1624. X    "}",
  1625. X    ";",
  1626. X    ">>=",
  1627. X    "<<=",
  1628. X    "+=",
  1629. X    "-=",
  1630. X    "*=",
  1631. X    "/=",
  1632. X    "%=",
  1633. X    "&=",
  1634. X    "^=",
  1635. X    "|=",
  1636. X    ">>",
  1637. X    "<<",
  1638. X    "++",
  1639. X    "--",
  1640. X    "->",
  1641. X    "&&",
  1642. X    "||",
  1643. X    "<=",
  1644. X    ">=",
  1645. X    "==",
  1646. X    "!=",
  1647. X    ":",
  1648. X    "",
  1649. X    "(",
  1650. X    ")",
  1651. X    "[",
  1652. X    "]",
  1653. X    ".",
  1654. X    "&",
  1655. X    "!",
  1656. X    "~",
  1657. X    "-",
  1658. X    "+",
  1659. X    "*",
  1660. X    "/",
  1661. X    "%",
  1662. X    "<",
  1663. X    ">",
  1664. X    "^",
  1665. X    "|",
  1666. X    "?",
  1667. X    "inline",
  1668. X};
  1669. \Rogue\Monster\
  1670. else
  1671.   echo "will not over write ./tokens.c"
  1672. fi
  1673. chmod 444 ./tokens.c
  1674. if [ `wc -c ./tokens.c | awk '{printf $1}'` -ne 828 ]
  1675. then
  1676. echo `wc -c ./tokens.c | awk '{print "Got " $1 ", Expected " 828}'`
  1677. fi
  1678. if `test ! -s ./utils.c`
  1679. then
  1680. echo "writing ./utils.c"
  1681. sed 's/^X//' > ./utils.c << '\Rogue\Monster\'
  1682. X/*
  1683. X * C inline code substituter - 11/24/86 - mcg
  1684. X *
  1685. X * utility routines
  1686. X *
  1687. X * (c) 1986 - copyright 1986, s. mcgeady, all rights reserved
  1688. X */
  1689. X
  1690. X/* $Header: utils.c,v 1.13 87/06/24 13:11:40 mcg Rel $ */
  1691. X
  1692. X
  1693. X#include <stdio.h>
  1694. X#include "tokens.h"
  1695. X#include "inline.h"
  1696. X
  1697. Xstruct token *
  1698. Xskipws(t)
  1699. Xregister struct token *t;
  1700. X{
  1701. X    while (t && t->t_next && (t->t_tok == T_WS)) {
  1702. X        t = t->t_next;
  1703. X    }
  1704. X    return(t);
  1705. X}
  1706. X
  1707. X/*
  1708. X * add a token to a list
  1709. X */
  1710. X
  1711. Xaddtok(list, tok)
  1712. Xregister struct toklist *list;
  1713. Xregister struct token *tok;
  1714. X{
  1715. X    if (list->tl_head == NILTOK) {
  1716. X        list->tl_head = tok;
  1717. X    }
  1718. X    if (list->tl_tail != NILTOK) {
  1719. X        list->tl_tail->t_next = tok;
  1720. X    }
  1721. X    list->tl_tail = tok;
  1722. X}
  1723. X
  1724. Xstruct token *
  1725. Xinstok(tok,ntok)
  1726. Xregister struct token *tok;
  1727. Xregister struct token *ntok;
  1728. X{
  1729. X    register struct token *tl;
  1730. X
  1731. X    if (ntok == NILTOK) {
  1732. X        return(tok);
  1733. X    }
  1734. X    /* find end of new token list */
  1735. X    for(tl = ntok; tl->t_next != NILTOK; tl = tl->t_next)
  1736. X        ;
  1737. X
  1738. X    if (tok->t_next == NILTOK) {
  1739. X        tok->t_next = ntok;
  1740. X    } else {
  1741. X        tl->t_next = tok->t_next;
  1742. X        tok->t_next = ntok;
  1743. X    }
  1744. X    return(tl);    /* return end of new list */
  1745. X}
  1746. X
  1747. X/*
  1748. X * get a new token
  1749. X */
  1750. X
  1751. Xstruct token *
  1752. Xnewtok(mem,val, id)
  1753. Xint val;
  1754. Xchar *id;
  1755. X{
  1756. X    register struct token *t;
  1757. X    register unsigned int len,l;
  1758. X
  1759. X    len = sizeof(struct token);
  1760. X    if (id) {
  1761. X        len += (l = strlen(id) + 1);
  1762. X    }
  1763. X
  1764. X    t = (struct token *) getmem(mem,1,len);
  1765. X
  1766. X    if (id) {
  1767. X        t->t_id = ((char *) t) + sizeof(struct token);
  1768. X        (void) strncpy(t->t_id,id,l);
  1769. X    } else {
  1770. X        t->t_id = NIL;
  1771. X    }
  1772. X
  1773. X    t->t_tok = val;
  1774. X    t->t_flags = 0;
  1775. X    t->t_num = 0;
  1776. X    t->t_level = 0;
  1777. X    t->t_paren = 0;
  1778. X    t->t_line = 0;
  1779. X    t->t_next = NILTOK;
  1780. X    return(t);
  1781. X}
  1782. X
  1783. Xstruct token *
  1784. Xduptok(mem,tok)
  1785. Xregister struct token *tok;
  1786. X{
  1787. X    register struct token *t;
  1788. X
  1789. X    t = newtok(mem,tok->t_tok, tok->t_id);
  1790. X    t->t_flags = tok->t_flags;
  1791. X    t->t_num = tok->t_num;
  1792. X    t->t_level = tok->t_level;
  1793. X    t->t_paren = tok->t_paren;
  1794. X    t->t_line = 0;
  1795. X    t->t_next = NILTOK;    /* next token in this list */
  1796. X    return(t);
  1797. X}
  1798. X
  1799. Xcpytoklist(mem, olist, ilist)
  1800. Xint mem;
  1801. Xregister struct toklist *olist;
  1802. Xregister struct toklist *ilist;
  1803. X{
  1804. X    register struct token *tl;
  1805. X
  1806. X    for(tl = ilist->tl_head; tl != NILTOK; tl = tl->t_next) {
  1807. X        addtok(olist,duptok(mem,tl));
  1808. X        if (tl == ilist->tl_tail)
  1809. X            break;
  1810. X    }
  1811. X}
  1812. X
  1813. Xfixparens(tl,plev,blev)
  1814. Xregister struct toklist *tl;
  1815. Xregister int plev, blev;
  1816. X{
  1817. X    register struct token *tp;
  1818. X    register int paren = plev;
  1819. X    register int brace = blev;
  1820. X
  1821. X    for (tp = tl->tl_head; tp && tp != tl->tl_tail->t_next; tp = tp->t_next) {
  1822. X        tp->t_paren = paren;
  1823. X        tp->t_level = brace;
  1824. X        switch(tp->t_tok) {
  1825. X        case T_LPAREN:
  1826. X            paren++;
  1827. X            break;
  1828. X        case T_LBRACE:
  1829. X            brace++;
  1830. X            break;
  1831. X        case T_RBRACE:
  1832. X            tp->t_level = --brace;
  1833. X            break;
  1834. X        case T_RPAREN:
  1835. X            tp->t_paren = --paren;
  1836. X            break;
  1837. X        default:
  1838. X            break;
  1839. X        }
  1840. X    }
  1841. X}
  1842. X
  1843. X#include "varargs.h"
  1844. X
  1845. X/*VARARGS1*/
  1846. Xchar *
  1847. Xmkstr(mem,va_alist)
  1848. Xint mem;
  1849. Xva_dcl
  1850. X{
  1851. X    va_list s;
  1852. X    register int i;
  1853. X    register char *rs,*ts;
  1854. X
  1855. X    va_start(s);
  1856. X    i = 0;
  1857. X    while(1) {
  1858. X        rs = va_arg(s, char *);
  1859. X        if (rs == NIL) {
  1860. X            break;
  1861. X        }
  1862. X        i += strlen(rs);
  1863. X    }
  1864. X    va_end(s);
  1865. X    rs = (char *) getmem(mem,0,(unsigned) i+1);
  1866. X    *rs = '\0';
  1867. X    va_start(s);
  1868. X    while(1) {
  1869. X        ts = va_arg(s, char *);
  1870. X        if (ts == NIL) {
  1871. X            break;
  1872. X        }
  1873. X        (void) strcat(rs,ts);
  1874. X    }
  1875. X    va_end(s);
  1876. X    return(rs);
  1877. X}
  1878. X
  1879. X
  1880. X#ifdef vax
  1881. X/*VARARGS*/
  1882. Xerror(lin,fmt,args)
  1883. Xint lin;
  1884. Xchar *fmt;
  1885. Xchar *args;
  1886. X{
  1887. X    if (infile) {
  1888. X        fprintf(stderr,"\"%s\", line %d: ",infile,lin);
  1889. X    } else {
  1890. X        fprintf(stderr,"%s: line %d: ",myname,lin);
  1891. X    }
  1892. X    _doprnt(fmt,&args,stderr);
  1893. X    fputs("\n",stderr);
  1894. X    errs++;
  1895. X}
  1896. X
  1897. X
  1898. X/*VARARGS*/
  1899. Xwarn(lin,fmt,args)
  1900. Xint lin;
  1901. Xchar *fmt;
  1902. Xchar *args;
  1903. X{
  1904. X    if (nowarn) return;
  1905. X
  1906. X    if (infile) {
  1907. X        fprintf(stderr,"\"%s\", line %d: warning: ",infile,lin);
  1908. X    } else {
  1909. X        fprintf(stderr,"%s: line %d: warning: ",myname,lin);
  1910. X    }
  1911. X    _doprnt(fmt,&args,stderr);
  1912. X    fputs("\n",stderr);
  1913. X}
  1914. X#else
  1915. X/*VARARGS*/
  1916. Xerror(line,fmt,va_alist)
  1917. Xint line;
  1918. Xchar *fmt;
  1919. Xva_dcl
  1920. X{
  1921. X    va_list s;
  1922. X    va_list *p;
  1923. X    register int i;
  1924. X    register char *rs,*ts;
  1925. X
  1926. X    va_start(s);
  1927. X    p = &s;
  1928. X    if (infile) {
  1929. X        fprintf(stderr,"\"%s\", line %d: ",infile,line);
  1930. X    } else {
  1931. X        fprintf(stderr,"%s: line %d: ",myname,line);
  1932. X    }
  1933. X    _doprnt(fmt,p,stderr);
  1934. X    fputs("\n",stderr);
  1935. X    va_end(s);
  1936. X    errs++;
  1937. X}
  1938. X
  1939. X/*VARARGS*/
  1940. Xwarn(line,fmt,va_alist)
  1941. Xint line;
  1942. Xchar *fmt;
  1943. Xva_dcl
  1944. X{
  1945. X    va_list s;
  1946. X    va_list *p;
  1947. X    register int i;
  1948. X    register char *rs,*ts;
  1949. X
  1950. X    if (nowarn) return;
  1951. X
  1952. X    va_start(s);
  1953. X    p = &s;
  1954. X    if (infile) {
  1955. X        fprintf(stderr,"%s: \"%s\", line %d: ",infile,line);
  1956. X    } else {
  1957. X        fprintf(stderr,"%s: line %d: ",myname,line);
  1958. X    }
  1959. X    _doprnt(fmt,p,stderr);
  1960. X    fputs("\n",stderr);
  1961. X}
  1962. X
  1963. X#endif
  1964. X
  1965. X
  1966. X/* extremely limited - positive numbers only */
  1967. X/* useful only for appending positive digits to strings */
  1968. X
  1969. Xchar *
  1970. Xitoa(n)
  1971. X{
  1972. X    static char buf[20];
  1973. X    register char *p = &buf[18];
  1974. X
  1975. X    buf[19] = '\0';
  1976. X    do {
  1977. X        *p-- = '0' + (n%10);
  1978. X        n /= 10;
  1979. X    } while(n && (p >= buf));
  1980. X    return(++p);
  1981. X}
  1982. X
  1983. X/*
  1984. X * create a (non-filled-in) inline expansion node
  1985. X */
  1986. X
  1987. Xstruct inline_node *
  1988. Xmknode(mem)
  1989. Xint mem;
  1990. X{
  1991. X    register struct inline_node *node;
  1992. X    register int i;
  1993. X
  1994. X    node = (struct inline_node *) getmem(mem,1,sizeof (struct inline_node));
  1995. X    node->i_id = NIL;
  1996. X    for (i=0; i < NSTATES; i++) {
  1997. X        node->i_tl[i].tl_head = NILTOK;
  1998. X        node->i_tl[i].tl_tail = NILTOK;
  1999. X    }
  2000. X
  2001. X    node->i_text.tl_head = NILTOK;
  2002. X    node->i_text.tl_tail = NILTOK;
  2003. X
  2004. X    for(i=0; i < NFORMALS; i++) {
  2005. X        node->i_formals[i] = NIL;
  2006. X        node->i_formalinfo[i] = 0;
  2007. X    }
  2008. X    node->i_nformals = 0;
  2009. X
  2010. X    node->i_mem = mem;
  2011. X    node->i_line = 0;
  2012. X    node->i_flags = 0;
  2013. X    node->i_storclass = 0;
  2014. X    node->i_nseen = 0;
  2015. X    node->i_nexpand = 0;
  2016. X
  2017. X    node->i_exprmem = -1;
  2018. X
  2019. X    return(node);
  2020. X}
  2021. X
  2022. Xprtoklist(tl,doauto,s)
  2023. Xregister struct toklist *tl;
  2024. Xint doauto;
  2025. XFILE *s;
  2026. X{
  2027. X    register struct token *th = tl->tl_head;
  2028. X
  2029. X    while (th != NILTOK) {
  2030. X        prtok(th,doauto,s);
  2031. X        th = th->t_next;
  2032. X    }
  2033. X}
  2034. X
  2035. Xprtok(tok,doauto,s)
  2036. Xstruct token *tok;
  2037. Xint doauto;
  2038. XFILE *s;
  2039. X{
  2040. X    extern char *tokens[];
  2041. X
  2042. X    switch (tok->t_tok) {
  2043. X    case T_IDENT:
  2044. X        if (doauto && tok->t_flags&TAUTO) {
  2045. X            if (tok->t_flags&TINLINE) {
  2046. X                if (tok->t_num > 1) {
  2047. X                    fprintf(s,"_loc_%s_%d",tok->t_id,tok->t_num);
  2048. X                    break;
  2049. X                }
  2050. X            } else {
  2051. X                fprintf(s,"_auto_%s",tok->t_id);
  2052. X                break;
  2053. X            }
  2054. X        }
  2055. X        /*FALLTHROUGH*/
  2056. X    case T_LABEL:
  2057. X    case T_WS:
  2058. X    case T_NUM:
  2059. X    case T_CHARCONST:
  2060. X    case T_CPP:
  2061. X    case T_STR:
  2062. X    case T_TYPE_ID:
  2063. X    case T_STRTAG:
  2064. X        fputs(tok->t_id,s);
  2065. X        break;
  2066. X    case T_ACTUAL:
  2067. X        fputs("<ACTUAL>",s);
  2068. X        break;
  2069. X    case T_RETVAL:
  2070. X        fputs("<RETVAL>",s);
  2071. X        break;
  2072. X    case T_ARGLIST:
  2073. X        fprintf(s,"%s(ARGLIST)", tok->t_id);
  2074. X        break;
  2075. X    case T_RETLAB:
  2076. X        fputs("<RETLAB>",s);
  2077. X        break;
  2078. X    case T_FORMAL:
  2079. X        fprintf(s,"<FORMAL '%s'>",tok->t_id);
  2080. X        break;
  2081. X    default:
  2082. X        if (tok->t_tok <= T_INLINE)
  2083. X            fputs(tokens[tok->t_tok],s);
  2084. X        else
  2085. X            fputs("???",s);
  2086. X
  2087. X        break;
  2088. X    }
  2089. X}
  2090. X
  2091. X
  2092. Xdebugnode(node)
  2093. Xregister struct inline_node *node;
  2094. X{
  2095. X    register int i;
  2096. X
  2097. X    fprintf(stderr,"> inline '%s' @ line %d\n",node->i_id,node->i_line);
  2098. X    fprintf(stderr,"> formals (%d):\n", node->i_nformals);
  2099. X    for (i = 0; i < node->i_nformals; i++) {
  2100. X        fprintf(stderr,">    '%s'\n", node->i_formals[i]);
  2101. X    }
  2102. X    fprintf(stderr,"> function type:\n");
  2103. X    prtoklist(&node->i_tl[SDECL],0,stderr);
  2104. X    fprintf(stderr,"\n");
  2105. X    fprintf(stderr,"> declarations:\n");
  2106. X    prtoklist(&node->i_tl[SDECLBODY],0,stderr);
  2107. X    fprintf(stderr,"> body:\n");
  2108. X    prtoklist(&node->i_tl[SBODY],1,stderr);
  2109. X    fprintf(stderr,"\n");
  2110. X    if (node->i_flags&I_EXPR) {
  2111. X        fprintf(stderr,"> as expression:\n");
  2112. X        fprintf(stderr,">  declarations:\n");
  2113. X        prtoklist(&node->i_tl[SEXPRDECL],1,stderr);
  2114. X        fprintf(stderr,"\n>  body:\n");
  2115. X        prtoklist(&node->i_tl[SEXPRBODY],1,stderr);
  2116. X        fprintf(stderr,"\n");
  2117. X    } else {
  2118. X        fprintf(stderr, "(not an expression)\n");
  2119. X    }
  2120. X}
  2121. X
  2122. X
  2123. X
  2124. Xistype(tok)
  2125. Xstruct token *tok;
  2126. X{
  2127. X    switch(tok->t_tok) {
  2128. X    case T_CHAR:
  2129. X    case T_INT:
  2130. X    case T_SHORT:
  2131. X    case T_LONG:
  2132. X    case T_FLOAT:
  2133. X    case T_DOUBLE:
  2134. X    case T_UNSIGNED:
  2135. X    case T_SIGNED:
  2136. X    case T_VOID:
  2137. X    case T_ENUM:
  2138. X    case T_STRUCT:
  2139. X    case T_UNION:
  2140. X    case T_TYPE_ID:
  2141. X        return(1);
  2142. X
  2143. X    default:
  2144. X        return(0);
  2145. X    }
  2146. X}
  2147. X
  2148. Xisstoreclass(tok)
  2149. Xstruct token *tok;
  2150. X{
  2151. X    switch(tok->t_tok) {
  2152. X    case T_REGISTER:
  2153. X    case T_EXTERN:
  2154. X    case T_STATIC:
  2155. X    case T_AUTO:
  2156. X    case T_CONST:
  2157. X    case T_VOLATILE:
  2158. X        return(1);
  2159. X    default:
  2160. X        return(0);
  2161. X    }
  2162. X}
  2163. X
  2164. Xiscontrol(tok)
  2165. Xstruct token *tok;
  2166. X{
  2167. X    switch(tok->t_tok) {
  2168. X    case T_IF:
  2169. X    case T_WHILE:
  2170. X    case T_FOR:
  2171. X    case T_SWITCH:
  2172. X        return(1);
  2173. X    default:
  2174. X        return(0);
  2175. X    }
  2176. X}
  2177. X
  2178. X/*
  2179. X * returns true if the tokens following the argument conform to
  2180. X * the pattern of a simple call:
  2181. X *    identifier, optional whitespace, leftparen
  2182. X * e.g.:
  2183. X *    foo /* comment  ();
  2184. X *
  2185. X * thus
  2186. X *    (foo)();  (*foo)();  etc
  2187. X * are not calls
  2188. X */
  2189. X
  2190. Xiscall(tok)
  2191. Xregister struct token *tok;
  2192. X{
  2193. X    if (tok == NILTOK) {
  2194. X        return(0);
  2195. X    }
  2196. X    if ((tok->t_tok != T_IDENT) || (tok->t_flags&TNOEXPAND)) {
  2197. X        return(0);
  2198. X    }
  2199. X    /* skip over any leading whitespace */
  2200. X    for(tok = tok->t_next; tok != NILTOK; tok = tok->t_next) {
  2201. X        if (tok->t_tok != T_WS) {
  2202. X            break;
  2203. X        }
  2204. X    }
  2205. X    if (tok && (tok->t_tok == T_LPAREN)) {
  2206. X        return(1);
  2207. X    }
  2208. X    return(0);
  2209. X}
  2210. X
  2211. \Rogue\Monster\
  2212. else
  2213.   echo "will not over write ./utils.c"
  2214. fi
  2215. chmod 444 ./utils.c
  2216. if [ `wc -c ./utils.c | awk '{printf $1}'` -ne 8665 ]
  2217. then
  2218. echo `wc -c ./utils.c | awk '{print "Got " $1 ", Expected " 8665}'`
  2219. fi
  2220. if `test ! -s ./mem.c`
  2221. then
  2222. echo "writing ./mem.c"
  2223. sed 's/^X//' > ./mem.c << '\Rogue\Monster\'
  2224. X/*
  2225. X * pool-based memory allocation scheme
  2226. X *
  2227. X * (c) 1986 - copyright 1986, s. mcgeady, all rights reserved
  2228. X *
  2229. X * this is good for low-overhead memory allocation of many small units,
  2230. X * where all the memory is freed at once at the end
  2231. X */
  2232. X
  2233. X/* $Header: mem.c,v 1.6 87/04/27 18:16:43 mcg Rel $ */
  2234. X
  2235. X
  2236. X#define    STATS    1
  2237. X#define    FREELIST 1    /* maintain freelist of hunks and bufs, cutting down */
  2238. X            /* on calls to malloc() and free() */
  2239. X#define    NFREEBUFS 10    /* number of free buffers to maintain */
  2240. X
  2241. X/* #define    TEST    1 */
  2242. X/* #define    ZEROMEM(p,n,a)    bzero(p,n) /* define to zero memory on allocation */
  2243. X#define    ZEROMEM(p,n,a)    
  2244. X
  2245. Xextern char *malloc();
  2246. Xextern char *sbrk();
  2247. Xextern char *getmem();
  2248. X
  2249. X#define    NIL    0
  2250. X#define    POOLSIZE    4096
  2251. X
  2252. Xstruct memhunk {
  2253. X    char        *m_base;    /* pointer to memory buffer */
  2254. X    char        *m_free;    /* pointer to free mem */
  2255. X    unsigned    m_size;        /* size of this buffer */
  2256. X    unsigned    m_nleft;    /* number of bytes left */
  2257. X    struct memhunk    *m_next;    /* next pool in this cache */
  2258. X};
  2259. X
  2260. X/*
  2261. X * each pool consists of a series of 'hunks' of memory, organized
  2262. X * as a linked list.  the pool 'handle' is really a pointer to the
  2263. X * poolhead for the list
  2264. X */
  2265. Xstruct poolhead {
  2266. X    struct    memhunk    *pl_pool;
  2267. X    struct    poolhead *pl_next;
  2268. X};
  2269. X
  2270. Xstatic struct poolhead head = {0};
  2271. X
  2272. X#ifdef STATS
  2273. Xstatic int nrequest    = 0;
  2274. Xstatic int nloops    = 0;
  2275. Xstatic int maxloops    = 0;
  2276. Xstatic int minloops    = 0;
  2277. Xstatic int nfree    = 0;
  2278. Xstatic int nmalloc    = 0;
  2279. Xstatic int maxsize    = 0;
  2280. Xstatic int npools    = 0;
  2281. Xstatic int maxpools    = 0;
  2282. Xstatic int nhunks    = 0;
  2283. Xstatic int maxhunks    = 0;
  2284. Xstatic int firsttime    = 0;
  2285. Xstatic unsigned totsize = 0;
  2286. Xstatic char *lowwater    = 0;
  2287. Xstatic char *hiwater    = 0;
  2288. Xstatic int nphdr    = 0;
  2289. X
  2290. Xstatic
  2291. Xchar *
  2292. XMALLOC(n)
  2293. Xunsigned int n;
  2294. X{
  2295. X    register char *p;
  2296. X
  2297. X    nmalloc++;
  2298. X    p = malloc(n);
  2299. X    if (p > hiwater) {
  2300. X        hiwater = p;
  2301. X    }
  2302. X    return(p);
  2303. X}
  2304. X
  2305. X#define    FREE(x)        (nfree++,free((unsigned)x))
  2306. X
  2307. X#else
  2308. X
  2309. X#define    MALLOC    malloc
  2310. X#define    FREE    free
  2311. X
  2312. X#endif
  2313. X
  2314. X#ifndef FREELIST
  2315. X
  2316. X#define    getpool() ((struct poolhead *) MALLOC(sizeof(struct poolhead)))
  2317. X#define gethunk() ((struct memhunk *) MALLOC(sizeof(struct memhunk)))
  2318. X#define    getbuf(s)  ((char *) MALLOC(*(s)))
  2319. X#define freebuf(p,s) (FREE(p))
  2320. X#define    freehunk(p) (FREE(p))
  2321. X
  2322. X#else 
  2323. X#define    getpool() ((struct poolhead *) MALLOC(sizeof(struct poolhead)))
  2324. X
  2325. Xstruct freebufs {
  2326. X    int    fb_size;
  2327. X    char    *fb_buf;
  2328. X};
  2329. X
  2330. Xstatic struct memhunk *hunks = {0};
  2331. Xstatic struct freebufs bufs[NFREEBUFS] = {0};
  2332. X
  2333. X
  2334. Xstruct memhunk *
  2335. Xgethunk() {
  2336. X    register struct memhunk *p = hunks;
  2337. X
  2338. X    if (p != NIL) {
  2339. X        hunks = p->m_next;
  2340. X        return(p);
  2341. X    }
  2342. X    return((struct memhunk *) MALLOC(sizeof(struct memhunk)));
  2343. X}
  2344. X
  2345. X#define freehunk(p)    ((p)->m_next = hunks, hunks = (p))
  2346. X
  2347. Xchar *
  2348. Xgetbuf(size)
  2349. Xunsigned int *size;
  2350. X{
  2351. X    register int i;
  2352. X    register struct freebufs *p;
  2353. X
  2354. X    if (*size == 0) return(NIL);
  2355. X
  2356. X    for (i = 0, p = bufs; i < NFREEBUFS; i++, p++) {
  2357. X        if (p->fb_size >= *size) {
  2358. X            *size = p->fb_size;
  2359. X            p->fb_size = 0;
  2360. X            return(p->fb_buf);
  2361. X        }
  2362. X    }
  2363. X    return((char *) MALLOC(*size));
  2364. X}
  2365. X
  2366. Xvoid
  2367. Xfreebuf(p,size)
  2368. Xchar *p;
  2369. Xunsigned size;
  2370. X{
  2371. X    register int i;
  2372. X    register struct freebufs *q;
  2373. X
  2374. X    for (i = 0, q = bufs; i < NFREEBUFS; i++, q++) {
  2375. X        if (q->fb_size == 0) {
  2376. X            q->fb_size = size;
  2377. X            q->fb_buf = p;
  2378. X            return;
  2379. X        }
  2380. X    }
  2381. X    FREE(p);
  2382. X}
  2383. X
  2384. X#endif
  2385. X
  2386. X
  2387. X/*
  2388. X * open a new memory pool, returning a handle to it
  2389. X */
  2390. X
  2391. Xopenpool() {
  2392. X    register struct poolhead *pl, *lastpl;
  2393. X    register int pool = 0;
  2394. X
  2395. X#ifdef STATS
  2396. X    if (firsttime == 0) {
  2397. X        firsttime++;
  2398. X        lowwater = sbrk(0);
  2399. X    }
  2400. X    npools++;
  2401. X    if (npools > maxpools) {
  2402. X        maxpools = npools;
  2403. X    }
  2404. X#endif
  2405. X    /* this finds the last pool header */
  2406. X    for (pl = &head;
  2407. X        ((pl != NIL) && (pl->pl_pool != NIL));
  2408. X          lastpl = pl, pl = pl->pl_next)
  2409. X    {
  2410. X        pool++;
  2411. X    }
  2412. X    if (pl == NIL) {
  2413. X        /* add a new pool header on the end */
  2414. X        pl = lastpl->pl_next = getpool();
  2415. X        pl->pl_pool = gethunk();
  2416. X        pl->pl_next = NIL;
  2417. X        pl->pl_pool->m_base = NIL;
  2418. X        pl->pl_pool->m_free = NIL;
  2419. X        pl->pl_pool->m_size = 0;
  2420. X        pl->pl_pool->m_nleft = 0;
  2421. X        pl->pl_pool->m_next = NIL;
  2422. X#ifdef STATS
  2423. X        nhunks++;
  2424. X        nphdr++;
  2425. X#endif
  2426. X    }
  2427. X    return(pool);
  2428. X}
  2429. X
  2430. X
  2431. X
  2432. X/*
  2433. X * close a memory pool, freeing all memory associated with it
  2434. X */
  2435. X
  2436. Xclosepool(pool)
  2437. Xregister int pool;
  2438. X{
  2439. X    register struct poolhead *pl;
  2440. X    register struct memhunk *p, *q;
  2441. X
  2442. X    if (pool < 0) {
  2443. X        return(NIL);
  2444. X    }
  2445. X    for(pl = &head; pl != NIL; pl = pl->pl_next) {
  2446. X        if (pool == 0) {
  2447. X            break;
  2448. X        }
  2449. X        pool--;
  2450. X    }
  2451. X    if (pool != 0) {        /*  invalid pool */
  2452. X        return(0);
  2453. X    }
  2454. X
  2455. X    for(p = pl->pl_pool; p != NIL; p = q) {
  2456. X        q = p->m_next;
  2457. X        if (p->m_base) {
  2458. X            freebuf(p->m_base,p->m_size);
  2459. X        }
  2460. X        freehunk(p);
  2461. X#ifdef STATS
  2462. X        nhunks--;
  2463. X#endif
  2464. X    }
  2465. X    pl->pl_pool = NIL;
  2466. X#ifdef STATS
  2467. X    npools--;
  2468. X#endif
  2469. X    return(1);
  2470. X}
  2471. X
  2472. X
  2473. X/*
  2474. X * get 'size' bytes, from 'pool'
  2475. X * if 'align' is 1, align the result on a (sizeof long) boundary
  2476. X */
  2477. X
  2478. Xchar *
  2479. Xgetmem(pool,align,size)
  2480. Xint pool;
  2481. Xunsigned align;
  2482. Xunsigned size;
  2483. X{
  2484. X    register struct poolhead *pl;
  2485. X    register struct memhunk *p,*lastp;
  2486. X    register char *r;
  2487. X    register int psize;
  2488. X    register int lnloops;
  2489. X
  2490. X#ifdef STATS
  2491. X    nrequest++;
  2492. X    totsize += size;
  2493. X    if (size > maxsize) {
  2494. X        maxsize = size;
  2495. X    }
  2496. X    lnloops = 0;
  2497. X#endif
  2498. X
  2499. X    if (pool < 0) {
  2500. X        return(NIL);
  2501. X    }
  2502. X    for(pl = &head; pl != NIL; pl = pl->pl_next) {
  2503. X        if (pool == 0) {
  2504. X            break;
  2505. X        }
  2506. X        pool--;
  2507. X    }
  2508. X    if (pool != 0) {        /*  invalid pool */
  2509. X        return(NIL);
  2510. X    }
  2511. X
  2512. X    for(p = pl->pl_pool,lastp = NIL; p != NIL; lastp = p, p = p->m_next) {
  2513. X#ifdef STATS
  2514. X        nloops++;
  2515. X        lnloops++;
  2516. X#endif
  2517. X        if (!p->m_nleft)
  2518. X            continue;
  2519. X        if (align && (psize = (((int) p->m_free) % sizeof(long)))) {
  2520. X            psize = sizeof(long) - psize;
  2521. X            if (p->m_nleft >= size+psize) {
  2522. X                p->m_nleft -= psize;
  2523. X                p->m_free += psize;
  2524. X            } else {
  2525. X                continue;
  2526. X            }
  2527. X        }
  2528. X        if (p->m_nleft && (p->m_nleft >= size)) {
  2529. X            r = p->m_free;
  2530. X            p->m_nleft -= size;
  2531. X            p->m_free += size;
  2532. X            ZEROMEM(r,size,align);
  2533. X            return(r);
  2534. X        }
  2535. X    }
  2536. X    if (size < POOLSIZE) {
  2537. X        psize = POOLSIZE;
  2538. X    } else {
  2539. X        psize = size;
  2540. X    }
  2541. X
  2542. X#ifdef STATS
  2543. X    nhunks++;
  2544. X    if (nhunks > maxhunks) {
  2545. X        maxhunks = nhunks;
  2546. X    }
  2547. X    if (lnloops > maxloops) {
  2548. X        maxloops = lnloops;
  2549. X    }
  2550. X    if ((minloops == 0) || (lnloops < minloops)) {
  2551. X        minloops = lnloops;
  2552. X    }
  2553. X#endif
  2554. X
  2555. X    /* don't need to worry about alignment here, malloc always aligned */
  2556. X    p = gethunk();
  2557. X
  2558. X    /* if lastp == NIL, then this is first allocation for this pool */
  2559. X    if (lastp != NIL) {
  2560. X        lastp->m_next = p;
  2561. X    } else {
  2562. X        pl->pl_pool = p;
  2563. X    }
  2564. X    p->m_nleft = p->m_size = psize;
  2565. X    p->m_free = p->m_base = getbuf(&p->m_nleft);
  2566. X    p->m_next = NIL;
  2567. X
  2568. X    r = p->m_free;
  2569. X    p->m_nleft -= size;
  2570. X    p->m_free += size;
  2571. X    ZEROMEM(r,size,align);
  2572. X    return(r);
  2573. X}
  2574. X
  2575. X#ifdef notdef
  2576. X/* should improve this */
  2577. X
  2578. Xbzero(p,s,a)
  2579. Xregister char *p;
  2580. Xregister int s;
  2581. Xregister int a;
  2582. X{
  2583. X    while(s--) {
  2584. X        *p++ = 0;
  2585. X    }
  2586. X}
  2587. X#endif
  2588. X
  2589. X#ifdef STATS
  2590. X#include <stdio.h>
  2591. X
  2592. Xmemstats() {
  2593. X    fprintf(stderr,"%d hunks (max %d) in %d pools (max %d), (%d hdrs), largest is %d\n",
  2594. X        nhunks,maxhunks,npools,maxpools,nphdr,maxsize);
  2595. X    fprintf(stderr,"%d loops in getmem (avg), %d min, %d max\n",
  2596. X            nloops/nrequest, minloops, maxloops);
  2597. X    fprintf(stderr, "pools between 0x%x and 0x%x, heap max %d.%d Kb\n",
  2598. X        lowwater, hiwater, (hiwater-lowwater)/1024, (hiwater-lowwater)%1024);
  2599. X    fprintf(stderr, "%d requests, %d mallocs, %d frees\n", nrequest,nmalloc,nfree); 
  2600. X    fprintf(stderr, "%d total bytes, average request %d.%d\n", totsize,
  2601. X        totsize/nrequest, totsize%nrequest);
  2602. X}
  2603. X#endif
  2604. X
  2605. X#ifdef TEST
  2606. X/*
  2607. X * testing code
  2608. X */
  2609. X
  2610. X#include <stdio.h>
  2611. X
  2612. X#define skipws(p)    while((*p == ' ') || (*p == '\t')) p++
  2613. X#define skiptows(p)    while((*p != ' ') && (*p != '\t') && (*p != '\0')) p++
  2614. X
  2615. Xmain() {
  2616. X    register int i,n,x;
  2617. X    char buf[20];
  2618. X    char c;
  2619. X    register char *p,*q;
  2620. X
  2621. X    printf("memory allocator test routine\n");
  2622. X    while(printf("> "),gets(buf) != NIL) {
  2623. X        p = buf;
  2624. X        skipws(p);
  2625. X        c = *p++;
  2626. X        skipws(p);
  2627. X        switch(c) {
  2628. X        case 'd':
  2629. X            dump();
  2630. X            break;
  2631. X        case 's':
  2632. X#ifdef STATS
  2633. X            memstats();
  2634. X#else
  2635. X            printf("no statistics available\n");
  2636. X#endif
  2637. X            break;
  2638. X        case 'g':    /* get mem (nbytes) (align) (poolnum) */
  2639. X            n = atoi(p);
  2640. X            skiptows(p); skipws(p);
  2641. X            i = atoi(p);
  2642. X            skiptows(p); skipws(p);
  2643. X            x = atoi(p); 
  2644. X            q = getmem(x, i, n);
  2645. X            printf("got %d bytes @ 0x%x %sfrom pool %d\n", n, q,
  2646. X                 i ? "(aligned) ": "", x);
  2647. X            break;
  2648. X        case 'o':    /* open a new pool */
  2649. X            n = openpool();
  2650. X            printf("pool %d opened\n", n);
  2651. X            break;
  2652. X        case 'c':    /* close pool */
  2653. X            printf("closing pool %d\n", n = atoi(p));
  2654. X            x = closepool(n);
  2655. X            if (!x) {
  2656. X                printf("error closing pool %d\n", x);
  2657. X            }
  2658. X            break;
  2659. X        case 'q':
  2660. X            printf("exiting ...\n");
  2661. X            return;
  2662. X        default:
  2663. X            printf("unrecognized command '%c'\n", c);
  2664. X            break;
  2665. X
  2666. X        }
  2667. X    }
  2668. X}
  2669. X
  2670. Xdump() {
  2671. X    register struct poolhead *pl;
  2672. X    register struct memhunk *p;
  2673. X    register int i,j;
  2674. X
  2675. X    for (i=0, pl = &head; pl != NIL; i++,pl = pl->pl_next) {
  2676. X        printf("\tpool %d (@ 0x%x):\n", i, pl);
  2677. X        for(j=0, p = pl->pl_pool; p != NIL; j++,p = p->m_next) {
  2678. X            printf("\t\tmemhunk %d (@ 0x%x)", j, p);
  2679. X            printf("buf %d bytes @ 0x%x (%d left @ 0x%x)\n",
  2680. X                p->m_size, p->m_base, p->m_nleft, p->m_free);
  2681. X        }
  2682. X    }
  2683. X}
  2684. X
  2685. Xstatic
  2686. Xatoi(p)
  2687. Xregister char *p;
  2688. X{
  2689. X    register int n = 0;
  2690. X
  2691. X    while ((*p >= '0') && (*p <= '9')) {
  2692. X        n = (n*10) + (*p - '0');
  2693. X        p++;
  2694. X    }
  2695. X    return(n);
  2696. X}
  2697. X
  2698. X#endif /* TEST */
  2699. \Rogue\Monster\
  2700. else
  2701.   echo "will not over write ./mem.c"
  2702. fi
  2703. chmod 444 ./mem.c
  2704. if [ `wc -c ./mem.c | awk '{printf $1}'` -ne 8948 ]
  2705. then
  2706. echo `wc -c ./mem.c | awk '{print "Got " $1 ", Expected " 8948}'`
  2707. fi
  2708. echo "Finished archive 2 of 3"
  2709. # if you want to concatenate archives, remove anything after this line
  2710. exit
  2711.