home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume11 / inline / part02 < prev    next >
Text File  |  1987-09-14  |  46KB  |  1,955 lines

  1. Subject:  v11i040:  Inline code expander for C, Part02/04
  2. Newsgroups: comp.sources.unix
  3. Sender: sources
  4. Approved: rs@uunet.UU.NET
  5.  
  6. Submitted-by: seismo!omepd!mcg@uunet.UU.NET
  7. Posting-number: Volume 11, Issue 40
  8. Archive-name: inline/Part02
  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. #    ./inline.1
  15. #    ./inline.h
  16. #    ./tokens.h
  17. #    ./inline.c
  18. #    ./declare.c
  19. #
  20. if `test ! -s ./inline.1`
  21. then
  22. echo "writing ./inline.1"
  23. sed 's/^X//' > ./inline.1 << '\Rogue\Monster\'
  24. X.TH INLINE 1 
  25. X.\" $Header: inline.1,v 1.8 87/06/24 13:21:28 mcg Rel $
  26. X.SH NAME
  27. Xinline \- C preprocessor for inline functions
  28. X.SH SYNOPSIS
  29. X.B inline
  30. X[
  31. X.B \-w
  32. X] [
  33. X.B \-e
  34. X] [
  35. X.B \-s
  36. X] [
  37. X.B \-n
  38. X] [
  39. X.B \-d
  40. X] [
  41. X.B \-2
  42. X] [
  43. X.B \-S [ em
  44. X]
  45. X]
  46. X[ infile ] [ outfile ]
  47. X.SH DESCRIPTION
  48. X.I Inline
  49. Xis a
  50. Xpreprocessor that accepts C language programs
  51. Xcontaining the additional storage-class keyword
  52. X\fBinline\fR applied to function declarations, and
  53. Xgenerates identical C programs that (usually) have the
  54. Xfunctions so marked expanded where they are called.
  55. XInput code lacking the
  56. X.B inline
  57. Xkeyword is output unchanged.
  58. XThus
  59. X.I inline
  60. Xallows C programmers a feature similar to that provided
  61. Xby the C++ language.
  62. XHowever, while the specifications are the same, the
  63. X.I inline
  64. Xprogram works substantially differently from currently
  65. Ximplemented C++ compilers.
  66. XCurrent C++ compilers rewrite
  67. Xinline functions into expressions, thus prohibiting loops in them, but
  68. Xallowing their use in contexts such as control statements of looping
  69. Xconstructs.
  70. X.I Inline
  71. Xnormally
  72. Xreformats
  73. Xinline functions into code concealed in local blocks, adds
  74. Xvariables for parameter and return values, and changes
  75. X.B return
  76. Xstatements into
  77. X.BR goto s.
  78. XThis allows use of all normal C constructs within inlines.
  79. XThis rewriting is appropriate in all contexts except when
  80. Xinline functions are called in the control parts of
  81. X.B for
  82. Xand
  83. X.B while
  84. Xloops, and in a few other cases.
  85. XIn these cases, the C++ style expansion is used, and the procedures are
  86. Xrewritten as expressions when
  87. Xpossible (that is, when they lack loops, switches, and goto's).
  88. X.PP
  89. X.I Inline
  90. Xemits
  91. X.B extern
  92. X(or, optionally,
  93. X.BR static )
  94. Xpredeclarations for
  95. Xinline functions, so that unexpanded instances are compiled correctly,
  96. Xand can be supplied externally.
  97. XAdditionally, options are provided to emit the bodies of any unexpanded
  98. Xfunctions as static procedures at the end of a module, or to emit
  99. Xthe bodies of all inline functions alone, allowing inline functions to
  100. Xbe collected into a library.
  101. X.PP
  102. XIn normal operation,
  103. X.I inline
  104. Xfunctions must be declared before they are used (like C++).
  105. XThe \-2 (two-pass) option relaxes this requirement, at a 30% penalty in
  106. Xprocessing time.
  107. X.PP
  108. XThe following options are provided:
  109. X.IP \-w
  110. Xsupress warning messages about unexpandable instances of inline functions.
  111. X.IP \-e
  112. Xemit predeclarations as
  113. X.BR extern s,
  114. Xand do not dump bodies of unexpanded functions (default).
  115. X.IP \-s
  116. Xemit predeclarations as
  117. X.BR static s,
  118. Xand dump bodies of unexpanded functions.
  119. X.IP \-n
  120. Xemit no predeclarations at all, and do not
  121. Xdump bodies of unexpanded functions.
  122. XThis allows the gathering of
  123. X.B inline
  124. Xfunctions into a library, to resolve unexpanded
  125. Xreferences and any instances where the address
  126. Xof an
  127. X.B inline
  128. Xwas taken.
  129. X.IP \-d
  130. Xdo not emit the main program, only dump the
  131. Xbodies of all inlines (incompatible with \-e, \-s, and \-n).
  132. X.IP \-2
  133. Xprocess the file in two passes.  This allows inline functions to be
  134. Xdeclared after their use.  For this option, standard input is not
  135. Xaccepted.
  136. X.IP \-S
  137. Xemit (on the standard error output) statistics
  138. Xabout the expansion process.
  139. X.IP \-Se
  140. Xemit extended statistics, giving expansion statistics
  141. Xfor each
  142. X.BR inline .
  143. X.IP \-Sm
  144. Xemit statistics about the memory usage of the program (if the program is
  145. Xcompiled to collect these statistics).
  146. X.PP
  147. XIf no input file is specified, the standard input is assumed,
  148. Xand likewise for the standard output.
  149. X.SH BUGS/CAVEATS
  150. X.I Inline
  151. Xdoes not perform predictably when given incorrect C programs.
  152. XIt is easy to test a program that contains inlines with the
  153. Xcommand:
  154. X.sp
  155. X.nf
  156. X.na
  157. X    cc -c -Dinline=static file.c
  158. X.fi
  159. X.ad
  160. X.PP
  161. XWhen multiple inline functions are present in a single expression,
  162. Xthe order in which the functions are executed in the inline code
  163. Xis sometimes different from the order in which they would have been
  164. Xcalled had they not been expanded.
  165. XIn particular, all functions in the expression will be evaluated,
  166. Xleft-to-right, before the operations in the expression are performed.
  167. XThis is correct for most C operators,
  168. X.I except
  169. Xthe comma, boolean-or (||), and boolean-and (&&) operators.
  170. XInline handles all but the comma operator correctly, expressionizing
  171. Xcalls on the right side of the conditional operators.
  172. X.PP
  173. XWhile
  174. X.I inline
  175. Xattempts to pass preprocessor defines through without change,
  176. Xit is strongly suggested that
  177. X.I inline
  178. Xbe executed
  179. Xon code that has already been processed by
  180. Xthe C preprocessor /lib/cpp.
  181. X.PP
  182. X.I Inline
  183. Xdoes not recognize certain degenerate cases of function declarations
  184. Xand calls, in particular:
  185. X.sp
  186. X.nf
  187. X.na
  188. X    (foo)(arg);
  189. X.fi
  190. X.ad
  191. X.I Inline
  192. Xalso does not correctly handle inline functions which take the address of
  193. Xlabels, or which use labels other than in \fBgoto\fR statements, both
  194. Xextremely distasteful (and probably illegal) practices.
  195. X.SH "SEE ALSO"
  196. Xcc(1), cpp(1)
  197. X.SH NOTE
  198. X.I Inline
  199. Xsource code
  200. Xis Copyright, 1986, 1987 by S. McGeady, all rights reserved.
  201. X.br
  202. XThe binaries for the VAX version of this program and this manual page are
  203. Xin the public domain.
  204. X.SH AUTHOR
  205. XS. McGeady
  206. X.br
  207. X3714 SE 26th Ave.
  208. X.br
  209. XPortland, OR 97202
  210. X.br
  211. X(503) 235-2462
  212. \Rogue\Monster\
  213. else
  214.   echo "will not over write ./inline.1"
  215. fi
  216. chmod 444 ./inline.1
  217. if [ `wc -c ./inline.1 | awk '{printf $1}'` -ne 5093 ]
  218. then
  219. echo `wc -c ./inline.1 | awk '{print "Got " $1 ", Expected " 5093}'`
  220. fi
  221. if `test ! -s ./inline.h`
  222. then
  223. echo "writing ./inline.h"
  224. sed 's/^X//' > ./inline.h << '\Rogue\Monster\'
  225. X/*
  226. X * inline code expander
  227. X *
  228. X * (c) 1986 - copyright 1986, s. mcgeady, all rights reserved
  229. X */
  230. X
  231. X/* $Header: inline.h,v 1.13 87/06/18 15:27:08 mcg Rel $ */
  232. X
  233. X
  234. X#include <stdio.h>
  235. X
  236. X#define    NFORMALS    30    /* max number of formal params */
  237. X#define    NINLINE        400    /* max number of inline decl's */
  238. X#define    NEXPAND        20    /* max number of expansions per stmt */
  239. X#define    NTYPEDEF    50    /* max number of typedefs per scope */
  240. X#define    NSCOPE        20    /* max scoping depth */
  241. X#define    NLOCALS        200    /* max # of local vars */
  242. X
  243. X#define    NIL        ((char *) 0)
  244. X#define    NILP(t)        ((t) 0)
  245. X#define    NILTOK        NILP(struct token *)
  246. X
  247. X/* token flags */
  248. X
  249. X#define    TNOEXPAND    0x01
  250. X#define    TNEEDEXPR    0x02
  251. X#define    TAUTO        0x04    /* an auto identifier */
  252. X#define    TINLINE        0x10
  253. X
  254. Xstruct token {
  255. X    int    t_tok;        /* token type */
  256. X    short    t_flags;    /* flag word */
  257. X    short    t_num;        /* number for id expansion */
  258. X    short    t_level;    /* brace level */
  259. X    short    t_paren;    /* paren level */
  260. X    int    t_line;        /* line this token occured on */
  261. X    char    *t_id;        /* identifier of this token, if any */
  262. X    struct token *t_next;    /* next token in this list */
  263. X};
  264. X
  265. Xstruct toklist {
  266. X    struct token *tl_head;    /* pointer to head token */
  267. X    struct token *tl_tail;    /* pointer to last token in the list */
  268. X};
  269. X
  270. X#define    SDECL        0    /* declaration */
  271. X#define    SFORMAL        1    /* formal list */
  272. X#define    SOPARAMDECL    2    /* old-style param declaration */
  273. X#define    SBODY        3    /* body */
  274. X#define    SDECLBODY    4    /* declaration of formals & return */
  275. X#define    SEXPRDECL    5    /* expression form declarations */
  276. X#define    SEXPRBODY    6    /* expression form body */
  277. X#define    NSTATES        7
  278. X
  279. X/*
  280. X * flags
  281. X */
  282. X
  283. X#define    NEEDRETVAL    1
  284. X
  285. X/*
  286. X * formal info
  287. X */
  288. X
  289. X#define    I_LVALUE    1    /* formal is used as an lvalue */
  290. X#define    I_SUB_OK    2    /* ok to substitute an actual here */
  291. X#define    I_EXPR        4    /* successfully rewrote as an expression */
  292. X
  293. Xstruct inline_node {
  294. X    char         *i_id;            /* ptr to identifier token */
  295. X    struct toklist    i_text;            /* saved text of original */
  296. X    struct toklist    i_tl[NSTATES];        /* token lists for sections */
  297. X    char        *i_formals[NFORMALS];    /* list of formals */
  298. X    int        i_formalinfo[NFORMALS];    /* info about formals */
  299. X    int        i_flags;        /* misc flags */
  300. X    int        i_nformals;        /* number of formals */
  301. X    int        i_storclass;        /* storage class of inline */
  302. X    int        i_line;            /* line number */
  303. X    int        i_mem;            /* memory pool for storage */
  304. X    int        i_exprmem;        /* pool for expression store */
  305. X    int        i_nseen;        /* # of calls seen */
  306. X    int        i_nexpand;        /* # of calls expanded */
  307. X};
  308. X
  309. X
  310. Xstruct expand_node {
  311. X    struct inline_node *e_node; /* ptr to inline node for this expansion */
  312. X    int        e_multiple; /* more than one call to this inline */
  313. X    struct toklist    e_actuals[NFORMALS]; /* actuals for this call */
  314. X    int        e_nactuals; /* number of actuals */
  315. X};
  316. X
  317. Xstruct typelist {
  318. X    char type_mem;
  319. X    char *type_id[NTYPEDEF];
  320. X};
  321. X
  322. Xstruct locallist {
  323. X    char    *l_id;
  324. X    long    l_scopes;
  325. X};
  326. X
  327. Xextern int line;
  328. Xextern int debug;
  329. Xextern int errs;
  330. Xextern int nowarn;
  331. Xextern int forward_decl;
  332. Xextern char *myname;
  333. Xextern char *infile;
  334. Xextern char *outfile;
  335. Xextern struct typelist *typeid[];
  336. X
  337. Xextern struct token *gettok();
  338. Xextern struct inline_node *isinline();
  339. Xextern struct inline_node *mknode();
  340. X
  341. X/* token manipulation routines */
  342. Xextern struct token *skipws();
  343. Xextern struct token *newtok();
  344. Xextern struct token *duptok();
  345. Xextern struct token *instok();
  346. X
  347. X/* miscellany */
  348. Xextern char *itoa();
  349. Xextern char *mkstr();
  350. Xextern char *MALLOC();
  351. Xextern char *getmem();
  352. X
  353. Xextern struct inline_node *nodelist[];
  354. \Rogue\Monster\
  355. else
  356.   echo "will not over write ./inline.h"
  357. fi
  358. chmod 444 ./inline.h
  359. if [ `wc -c ./inline.h | awk '{printf $1}'` -ne 3395 ]
  360. then
  361. echo `wc -c ./inline.h | awk '{print "Got " $1 ", Expected " 3395}'`
  362. fi
  363. if `test ! -s ./tokens.h`
  364. then
  365. echo "writing ./tokens.h"
  366. sed 's/^X//' > ./tokens.h << '\Rogue\Monster\'
  367. X
  368. X/* $Header: tokens.h,v 1.5 87/06/24 13:11:37 mcg Rel $ */
  369. X
  370. X
  371. X#define    T_EOT        0
  372. X
  373. X/*
  374. X * reserved words
  375. X */
  376. X
  377. X#define T_AUTO        1    /* auto */
  378. X#define T_BREAK        2    /* break */
  379. X#define T_CASE        3    /* case */
  380. X#define T_CHAR        4    /* char */
  381. X#define T_CONST        5    /* const */
  382. X#define T_CONTINUE    6    /* continue */
  383. X#define T_DEFAULT    7    /* default */
  384. X#define T_DO        8    /* do */
  385. X#define T_DOUBLE    9    /* double */
  386. X#define T_ELSE        10
  387. X#define T_ENUM        11
  388. X#define T_EXTERN    12
  389. X#define T_FLOAT        13
  390. X#define T_FOR        14
  391. X#define T_GOTO        15
  392. X#define T_IF        16
  393. X#define T_INT        17
  394. X#define T_LONG        18
  395. X#define T_REGISTER    19
  396. X#define T_RETURN    20
  397. X#define T_SHORT        21
  398. X#define T_SIGNED    22
  399. X#define T_SIZEOF    23
  400. X#define T_STATIC    24
  401. X#define T_STRUCT    25
  402. X#define T_SWITCH    26
  403. X#define T_TYPEDEF    27
  404. X#define T_UNION        28
  405. X#define T_UNSIGNED    29
  406. X#define T_VOID        30
  407. X#define T_VOLATILE    31
  408. X#define T_WHILE        32
  409. X
  410. X
  411. X#define T_ELLIPSES    33    /* ... */
  412. X#define T_EQ        34    /* = */
  413. X#define T_COMMA        35    /* , */
  414. X#define T_LBRACE    36    /* { */
  415. X#define T_RBRACE    37    /* } */
  416. X#define T_SEMIC        38    /* ; */
  417. X#define T_RS_EQ        39    /* <<= */
  418. X#define T_LS_EQ        40    /* >>= */
  419. X#define T_ADD_EQ    41    /* += */    
  420. X#define T_SUB_EQ    42    /* -= */
  421. X#define T_MUL_EQ    43    /* *= */
  422. X#define T_DIV_EQ    44    /* /= */
  423. X#define T_MOD_EQ    45    /* %= */
  424. X#define T_AND_EQ    46    /* &= */
  425. X#define T_XOR_EQ    47    /* ^= */
  426. X#define T_OR_EQ        48    /* |= */
  427. X#define T_RS         49    /* >> */
  428. X#define T_LS        50    /* << */
  429. X#define T_INC        51    /* ++ */
  430. X#define T_DEC        52    /* -- */
  431. X#define T_PTR         53    /* -> */
  432. X#define T_CAND         54    /* && */
  433. X#define T_COR        55    /* || */
  434. X#define T_LE         56    /* <= */
  435. X#define T_GE         57    /* >= */
  436. X#define T_CEQ        58    /* == */
  437. X#define T_NE         59    /* != */
  438. X#define    T_COLON        60    /* : */
  439. X                /* 61 missing */
  440. X#define    T_LPAREN    62    /* ( */
  441. X#define    T_RPAREN    63    /* ) */
  442. X#define    T_LSQ        64    /* [ */
  443. X#define    T_RSQ        65    /* ] */
  444. X#define    T_DOT        66    /* . */
  445. X#define    T_AMPER        67    /* & */
  446. X#define    T_NOT        68    /* ! */
  447. X#define    T_TILDE        69    /* ~ */
  448. X#define    T_MINUS        70    /* - */
  449. X#define    T_PLUS        71    /* + */
  450. X#define    T_STAR        72    /* * */
  451. X#define    T_DIV        73    /* / */
  452. X#define    T_MOD        74    /* % */
  453. X#define    T_LT        75    /* < */
  454. X#define    T_GT        76    /* > */
  455. X#define T_XOR        77    /* ^ */
  456. X#define    T_OR        78    /* | */
  457. X#define    T_QUEST        79    /* ? */
  458. X
  459. X#define T_INLINE    80    /* the 'inline' keyword */
  460. X#define T_IDENT        81    /* an identifier */
  461. X#define    T_TYPE_ID    82    /* a type identifier */
  462. X#define T_WS        83    /* whitespace and comments */
  463. X#define    T_NUM        84    /* a constant */
  464. X#define    T_STR        85    /* string */
  465. X#define    T_CPP        86    /* a preprocessor-style '#' line */
  466. X#define    T_CHARCONST    87    /* a character constant */
  467. X#define    T_COMMENT    88    /* a comment */
  468. X#define    T_STRTAG    89    /* a structure or union tag */
  469. X#define    T_LABEL        90    /* a label */
  470. X
  471. X#define T_ACTUAL    91    /* an actual parameter */
  472. X#define T_RETVAL    92
  473. X#define    T_ARGLIST    93    /* a substitutable argument list */
  474. X#define    T_RETLAB    94
  475. X#define    T_FORMAL    95
  476. \Rogue\Monster\
  477. else
  478.   echo "will not over write ./tokens.h"
  479. fi
  480. chmod 444 ./tokens.h
  481. if [ `wc -c ./tokens.h | awk '{printf $1}'` -ne 2763 ]
  482. then
  483. echo `wc -c ./tokens.h | awk '{print "Got " $1 ", Expected " 2763}'`
  484. fi
  485. if `test ! -s ./inline.c`
  486. then
  487. echo "writing ./inline.c"
  488. sed 's/^X//' > ./inline.c << '\Rogue\Monster\'
  489. X/*
  490. X * inline substituter for C
  491. X *
  492. X * s. mcgeady - 10/25/86
  493. X */
  494. X
  495. X/*
  496. X * (c) 1986 - copyright 1986, s. mcgeady, all rights reserved
  497. X */
  498. X
  499. X/* $Header: inline.c,v 1.20 87/06/24 13:11:30 mcg Rel $ */
  500. X
  501. X#include <stdio.h>
  502. X#include "tokens.h"
  503. X#include "inline.h"
  504. X
  505. X#define    strrchr rindex
  506. Xextern char *strrchr();
  507. X
  508. X#define    LOGFILE    "/c/mcg/.inline_use"
  509. X
  510. X/*
  511. X * global data declarations
  512. X */
  513. X
  514. Xstruct typelist *typeid[NSCOPE];
  515. X
  516. Xstatic struct locallist locals[NLOCALS];
  517. Xstatic int expanded = 0;
  518. X
  519. Xstruct inline_node *nodelist[NINLINE] = {0};
  520. X
  521. Xint forward_decl = T_EXTERN;
  522. Xchar *myname;
  523. Xchar *infile = NIL;
  524. Xchar *outfile = NIL;
  525. Xint debug = 0;
  526. Xint stats = 0;
  527. Xint mstats = 0;
  528. Xint dumpinline = 0;
  529. Xint noexpand = 0;
  530. Xint errs = 0;
  531. Xint nowarn = 0;
  532. Xint twopass = 0;
  533. Xint pass = 0;
  534. X
  535. Xmain(argc,argv)
  536. Xint argc;
  537. Xchar **argv;
  538. X{
  539. X    register int mem;
  540. X    struct toklist prog;
  541. X    register int r;
  542. X
  543. X#ifdef LOGFILE
  544. X    logusage(argc,argv);
  545. X#endif
  546. X    if (!(myname = strrchr(argv[0],'/'))) {
  547. X        myname = argv[0];
  548. X    } else {
  549. X        myname++;
  550. X    }
  551. X
  552. X    while (--argc) {
  553. X        ++argv;
  554. X        if ((*argv)[0] == '-') {
  555. X            switch((*argv)[1]) {
  556. X            case 'w':    /* supress warnings */
  557. X                nowarn++;
  558. X                break;
  559. X            case 'x':    /* debug */
  560. X                debug++;
  561. X                if ((*argv)[2] != '\0') {
  562. X                    debug = (*argv)[2] - '0';
  563. X                }
  564. X                break;
  565. X            case 'S':    /* stats */
  566. X                stats = 1;
  567. X                for (r = 2; (*argv)[r] != '\0'; r++) {
  568. X                    switch((*argv)[r]) {
  569. X                    case 'e':    /* expansion stats */
  570. X                        stats++;
  571. X                        break;
  572. X                    case 'm':    /* memory stats */
  573. X                        mstats++;
  574. X                        break;
  575. X                    }
  576. X                }
  577. X                break;
  578. X            case 'e':    /* externals */
  579. X                dumpinline = 0;
  580. X                break;
  581. X            case 's':    /* static */
  582. X                forward_decl = T_STATIC;
  583. X                dumpinline = 1;
  584. X                break;
  585. X            case 'n':    /* none */
  586. X                dumpinline = 0;
  587. X                forward_decl = 0;
  588. X                break;
  589. X            case 'd':    /* dump inlines */
  590. X                noexpand++;
  591. X                forward_decl = 0;
  592. X                dumpinline = 2;
  593. X                break;
  594. X
  595. X            case '2':
  596. X                twopass++;
  597. X                break;
  598. X
  599. X            default:
  600. X                error(0,"bad switch %s", *argv);
  601. X                break;
  602. X            }
  603. X        } else {    /* a filename */
  604. X            if (!infile) {
  605. X                infile = *argv;
  606. X                if (!freopen(infile,"r",stdin)) {
  607. X                    error(0,"cannot open %s", *argv);
  608. X                    exit(1);
  609. X                }
  610. X            } else if (!outfile) {
  611. X                outfile = *argv;
  612. X                if (!freopen(outfile,"w",stdout)) {
  613. X                    error(0,"cannot create %s", *argv);
  614. X                    exit(1);
  615. X                }
  616. X            } else {
  617. X                error(0,"usage: %s [flags] [infile] [outfile]", myname);
  618. X                exit(1);
  619. X            }
  620. X        }
  621. X    }
  622. X
  623. X    if (twopass) {
  624. X        if (dumpinline == 2) {
  625. X            warn(0, "two pass operations nonsensical with -d - twopass disabled");
  626. X            twopass = 0;
  627. X        }
  628. X        if (infile == NIL) {
  629. X            error(0, "two pass operation requires a named input file");
  630. X            exit(1);
  631. X        }
  632. X    }
  633. X    pushscope(0);
  634. X    while(1) {
  635. X        mem = openpool();
  636. X        expanded = 0;
  637. X        prog.tl_head = prog.tl_tail = NILTOK;
  638. X        r = doproc(mem,&prog);
  639. X        if (!noexpand || r >= 0)
  640. X            prtoklist(&prog,expanded,stdout);
  641. X        (void) closepool(mem);
  642. X        if (r == 0) {    /* end of file */
  643. X            if (twopass && (pass == 0)) {
  644. X                fclose(stdin);
  645. X                popscope(0);
  646. X                pushscope(0);
  647. X                if (!freopen(infile,"r",stdin)) {
  648. X                    error(0,"cannot reopen %s", infile);
  649. X                    exit(1);
  650. X                }
  651. X                pass = 1;
  652. X                continue;
  653. X            }
  654. X            break;
  655. X        }
  656. X    }
  657. X    if (dumpinline) {
  658. X        dump(dumpinline);
  659. X    }
  660. X    /* print memory allocator stats */
  661. X    if (mstats) {
  662. X        memstats();
  663. X    }
  664. X    if (stats) {
  665. X        prstats(stats);
  666. X    }
  667. X    return(errs);
  668. X}
  669. X
  670. X/*
  671. X * handle a procedure - return 0 on EOF
  672. X */
  673. X
  674. Xdoproc(mem,prog)
  675. Xregister int mem;
  676. Xstruct toklist *prog;
  677. X{
  678. X    register struct token *tok = NILTOK;
  679. X    register struct token *last = NILTOK;/* last **non-whitespace** token */
  680. X    register struct token *savtok = NILTOK;
  681. X    register struct token *decltok = NILTOK;
  682. X    register int state = 0;
  683. X    register int inlined = 0;
  684. X    int seenquest = 0;
  685. X    int seengoto = 0;
  686. X    int scope = 0;
  687. X    int i;
  688. X
  689. X#define    STYPEDEF    1        /* a typedef declaration */
  690. X#define    SSTRUCTDECL    2        /* a structure declaration */
  691. X#define    SSTRUCTTAG    3        /* as above, but have seen struct tag */
  692. X#define    SSTRUCTBODY    4        /* in the structure body */
  693. X#define    SSTRUCTREF    5        /* saw a "." or "->" */
  694. X
  695. X    clearlocals();
  696. X
  697. X    while((tok && tok->t_tok != T_WS ? last = tok: 0), tok = gettok(mem)) {
  698. X
  699. X        addtok(prog,tok);
  700. X
  701. X        switch(tok->t_tok) {
  702. X        case T_WS:
  703. X            continue;
  704. X
  705. X        case T_QUEST:
  706. X            seenquest++;
  707. X            continue;
  708. X
  709. X        case T_COLON:
  710. X            if (!seenquest && (last->t_tok == T_IDENT)) {
  711. X                /* a label */
  712. X                last->t_tok = T_LABEL;
  713. X            }
  714. X            if (seenquest) seenquest--;
  715. X            continue;
  716. X
  717. X        case T_GOTO:
  718. X            seengoto++;
  719. X            continue;
  720. X
  721. X        case T_SEMIC:
  722. X            seengoto = 0;
  723. X            if (state == STYPEDEF) {
  724. X                if (tok->t_level <= savtok->t_level) {
  725. X                    dotypedef(savtok);
  726. X                    state = 0;
  727. X                    decltok = savtok = NILTOK;
  728. X                }
  729. X                continue;
  730. X            }
  731. X            if (state == SSTRUCTBODY && (tok->t_level > savtok->t_level)) {
  732. X                continue;
  733. X            }
  734. X            if (state) {
  735. X                state = 0;
  736. X            }
  737. X            if (tok->t_level > 0 && decltok &&
  738. X                decltok->t_tok != T_EXTERN) {
  739. X                /* a declaration line */
  740. X                if (!twopass || ((pass == 0) && inlined) || ((pass == 1) && !inlined)) {
  741. X                    dolocals(mem,decltok,tok,inlined);
  742. X                }
  743. X            }
  744. X            decltok = NILTOK;
  745. X
  746. X            continue;
  747. X
  748. X        case T_LBRACE:
  749. X            scope++;
  750. X            if (state == SSTRUCTDECL || state == SSTRUCTTAG) {
  751. X                state = SSTRUCTBODY;
  752. X                continue;
  753. X            }
  754. X            if (state) {    /* typedef or struct body */
  755. X                continue;
  756. X            }
  757. X            if (scope-1 == 0) {
  758. X                if (!inlined && !(twopass && (pass == 0)))
  759. X                    doargs(mem,prog->tl_head,tok);
  760. X                decltok = NILTOK;
  761. X            }
  762. X            continue;
  763. X
  764. X        case T_RBRACE:
  765. X            scope--;
  766. X            if (state == SSTRUCTBODY) {
  767. X                if (tok->t_level <= savtok->t_level) {
  768. X                    state = 0;
  769. X                    decltok = savtok;
  770. X                    savtok = NILTOK;
  771. X                }
  772. X                continue;
  773. X            }
  774. X            if (scope != 0) {
  775. X                clearscope(scope);
  776. X                continue;
  777. X            }
  778. X            if (!state) {
  779. X                if (isdecl(prog)) {
  780. X                    if (twopass && pass == 1) {
  781. X                        /* NIL it out */
  782. X                        prog->tl_head = prog->tl_tail = NILTOK;
  783. X                    } else {
  784. X                        dodecl(prog,dumpinline);
  785. X                    }
  786. X                } else if (!noexpand) {
  787. X                    if (twopass && (pass == 0)) {
  788. X                        prog->tl_head = prog->tl_tail = NILTOK;
  789. X                    } else {
  790. X                        expanded += doinline(mem,prog);
  791. X                    }
  792. X                }
  793. X            }
  794. X            clearlocals();
  795. X            /* this is the only way out of doproc() except EOF */
  796. X            break;
  797. X
  798. X        case T_INLINE:
  799. X            inlined++;
  800. X            continue;
  801. X
  802. X        case T_TYPEDEF:
  803. X            savtok = tok;
  804. X            state = STYPEDEF;
  805. X            continue;
  806. X
  807. X        case T_STRUCT:
  808. X        case T_UNION:
  809. X            savtok = tok;
  810. X            if (tok->t_level > 0) {
  811. X                decltok = savtok;
  812. X            }
  813. X            state = SSTRUCTDECL;
  814. X            continue;
  815. X
  816. X        case T_DOT:
  817. X        case T_PTR:
  818. X            state = SSTRUCTREF;
  819. X            continue;
  820. X
  821. X        case T_IDENT:
  822. X            switch(state) {
  823. X            case SSTRUCTBODY:
  824. X            case STYPEDEF:
  825. X            case SSTRUCTTAG:
  826. X                continue;
  827. X
  828. X            case SSTRUCTREF:
  829. X                state = 0;
  830. X                continue;
  831. X
  832. X            case SSTRUCTDECL:
  833. X                tok->t_tok = T_STRTAG;
  834. X                state = SSTRUCTTAG;
  835. X                continue;
  836. X            }
  837. X            if (seengoto) {
  838. X                tok->t_tok = T_LABEL;
  839. X                continue;
  840. X            }
  841. X            if (scope > 0 && !decltok && islocal(tok->t_id,scope)) {
  842. X                tok->t_flags |= TAUTO;
  843. X                if (inlined) {
  844. X                    tok->t_flags |= TINLINE;
  845. X                    tok->t_num = deflevel(tok->t_id,scope);
  846. X                }
  847. X            }
  848. X            continue;
  849. X
  850. X        default:
  851. X            if (state == SSTRUCTBODY || state == STYPEDEF) {
  852. X                continue;
  853. X            }
  854. X            if (tok->t_level > 0 && !decltok &&
  855. X                (istype(tok) || isstoreclass(tok)) && 
  856. X                (last->t_tok == T_SEMIC || last->t_tok == T_LBRACE)) {
  857. X        
  858. X                decltok = tok;
  859. X            }
  860. X            continue;
  861. X        }
  862. X
  863. X        break;
  864. X    }
  865. X    if (!tok) return(0);
  866. X    return(1);
  867. X}
  868. X
  869. Xdoargs(mem,begin,end)
  870. Xint mem;
  871. Xregister struct token *begin, *end;
  872. X{
  873. X    register struct token *tp = begin;
  874. X
  875. X    /* first find an identifier */
  876. X    while(tp && tp->t_tok != T_IDENT) {
  877. X        tp = tp->t_next;
  878. X    }
  879. X    if (!tp) return;
  880. X
  881. X    /* then find level 0 left paren */
  882. X    while(tp && (tp->t_tok != T_LPAREN || tp->t_paren > 0)) {
  883. X        tp = tp->t_next;
  884. X    }
  885. X    if (!tp) return;
  886. X
  887. X    for ( ; tp && tp != end; tp = tp->t_next) {
  888. X        if ((tp->t_tok == T_IDENT) && (tp->t_level >= begin->t_level)) {
  889. X            if (addlocal(tp->t_id,1) < 0) {
  890. X                error(tp->t_line, "too many local variables");
  891. X            } else {
  892. X                tp->t_flags |= TAUTO;
  893. X            }
  894. X        }
  895. X    }
  896. X}
  897. X
  898. Xdolocals(mem,begin,end,inlined)
  899. Xint mem;
  900. Xregister struct token *begin, *end;
  901. Xint inlined;
  902. X{
  903. X    register int skip = 0;
  904. X    register struct token *tp;
  905. X    register int i;
  906. X
  907. X    for (tp = begin->t_next; tp && tp != end; tp = tp->t_next) {
  908. X        if (skip) {
  909. X            if (tp->t_tok == T_SEMIC ||
  910. X                (tp->t_tok == T_COMMA &&
  911. X                (tp->t_paren <= skip-1))) {
  912. X                skip = 0;
  913. X            } else if ((tp->t_tok == T_IDENT) &&
  914. X                   islocal(tp->t_id,tp->t_level)) {
  915. X                tp->t_flags |= TAUTO;
  916. X                if (inlined) {
  917. X                    tp->t_num = deflevel(tp->t_id,tp->t_level);
  918. X                    tp->t_flags |= TINLINE;
  919. X                }
  920. X            }
  921. X            continue;
  922. X        }
  923. X        if (tp->t_tok == T_EQ) {
  924. X            skip = tp->t_paren+1;
  925. X            continue;
  926. X        } else if ((tp->t_tok == T_IDENT) &&
  927. X               (tp->t_level >= begin->t_level)) {
  928. X
  929. X            if (addlocal(tp->t_id,tp->t_level) < 0) {
  930. X                error(tp->t_line, "too many local variables");
  931. X                continue;
  932. X            }
  933. X            tp->t_flags |= TAUTO;
  934. X            if (inlined) {
  935. X                tp->t_flags |= TINLINE;
  936. X                tp->t_num = tp->t_level;
  937. X            }
  938. X        }
  939. X    }
  940. X}
  941. X
  942. Xstatic int scopemask[] = {
  943. X        0x0001,        /* scope 1 */
  944. X        0x0003,        /* scope 2 */
  945. X        0x0007,        /* scope 3 */
  946. X        0x000f,        /* scope 4 */
  947. X        0x001f,        /* scope 5 */
  948. X        0x003f,        /* scope 6 */
  949. X        0x007f,        /* scope 7 */
  950. X        0x00ff,        /* scope 8 */
  951. X        0x01ff,        /* scope 9 */
  952. X        0x03ff,        /* scope 10 */
  953. X        0x07ff,        /* scope 11 */
  954. X        0x0fff,        /* scope 12 */
  955. X        0x1fff,        /* scope 13 */
  956. X        0x3fff,        /* scope 14 */
  957. X        0x7fff,        /* scope 15 */
  958. X        0xffff,        /* scope 16 */
  959. X        0x1ffff,    /* scope 17 */
  960. X        0x3ffff,    /* scope 18 */
  961. X        0x7ffff,    /* scope 19 */
  962. X        0xfffff        /* scope 20 */
  963. X};
  964. X
  965. X
  966. X
  967. Xaddlocal(s,scope)
  968. Xregister char *s;
  969. Xregister int scope;
  970. X{
  971. X    register struct locallist *p;
  972. X    register char *rs;
  973. X    register int i = 0;
  974. X
  975. X    if (scope > NSCOPE) return(-1);
  976. X
  977. X    for (rs = s; *rs != '\0'; i += *rs++)
  978. X        ;
  979. X
  980. X    i %= NLOCALS;
  981. X
  982. X    for (p = &locals[i]; p >= locals; p--) {
  983. X        if (p->l_id == NIL) {
  984. X            p->l_id = s;
  985. X            p->l_scopes |= (1<<(scope-1));
  986. X            return(0);
  987. X        } else if (strcmp(s,p->l_id) == 0) {
  988. X            p->l_scopes |= (1<<(scope-1));
  989. X            return(1);
  990. X        }
  991. X    }
  992. X    for (p = &locals[i+1]; p < &locals[NLOCALS]; p++) {
  993. X        if (p->l_id == NIL) {
  994. X            p->l_id = s;
  995. X            p->l_scopes |= (1<<(scope-1));
  996. X            return(0);
  997. X        } else if (strcmp(s,p->l_id) == 0) {
  998. X            p->l_scopes |= (1<<(scope-1));
  999. X            return(1);
  1000. X        }
  1001. X    }
  1002. X    return(-1);
  1003. X}
  1004. X
  1005. Xislocal(s,scope)
  1006. Xregister char *s;
  1007. Xregister int scope;
  1008. X{
  1009. X    register struct locallist *p;
  1010. X    register char *rs;
  1011. X    register int i = 0;
  1012. X
  1013. X    for (rs = s; *rs != '\0'; i += *rs++)
  1014. X        ;
  1015. X
  1016. X    i %= NLOCALS;
  1017. X
  1018. X    for (p = &locals[i]; p >= locals; p--) {
  1019. X        if (p->l_id == NIL) {
  1020. X            return(0);
  1021. X        } else if ((strcmp(s,p->l_id) == 0) &&
  1022. X                p->l_scopes&scopemask[scope-1]) {
  1023. X            return(1);
  1024. X        }
  1025. X    }
  1026. X    for (p = &locals[i+1]; p < &locals[NLOCALS]; p++) {
  1027. X        if (p->l_id == NIL) {
  1028. X            return(0);
  1029. X        } else if ((strcmp(s,p->l_id) == 0) &&
  1030. X               p->l_scopes&scopemask[scope-1]) {
  1031. X            return(1);
  1032. X        }
  1033. X    }
  1034. X    return(0);
  1035. X}
  1036. X
  1037. X
  1038. Xdeflevel(s,scope)
  1039. Xregister char *s;
  1040. Xregister int scope;
  1041. X{
  1042. X    register struct locallist *p;
  1043. X    register char *rs;
  1044. X    register int i = 0;
  1045. X
  1046. X    for (rs = s; *rs != '\0'; i += *rs++)
  1047. X        ;
  1048. X
  1049. X    i %= NLOCALS;
  1050. X
  1051. X    for (p = &locals[i]; p >= locals; p--) {
  1052. X        if (p->l_id == NIL) {
  1053. X            return(0);
  1054. X        } else if ((strcmp(s,p->l_id) == 0) &&
  1055. X                p->l_scopes&scopemask[scope-1]) {
  1056. X            goto end;
  1057. X        }
  1058. X    }
  1059. X    for (p = &locals[i+1]; p < &locals[NLOCALS]; p++) {
  1060. X        if (p->l_id == NIL) {
  1061. X            return(0);
  1062. X        } else if ((strcmp(s,p->l_id) == 0) &&
  1063. X               p->l_scopes&scopemask[scope-1]) {
  1064. X            goto end;
  1065. X        }
  1066. X    }
  1067. X    return(0);
  1068. X
  1069. X    end:
  1070. X    if (scope < 1 || scope > NSCOPE) {
  1071. X        return(0);
  1072. X    }
  1073. X    for (i = scope-1; i >= 0; i--) {
  1074. X        if (p->l_scopes&(1<<i)) {
  1075. X            return(i+1);
  1076. X        }
  1077. X    }
  1078. X    return(0);
  1079. X}
  1080. X
  1081. Xclearlocals() {
  1082. X    register int i;
  1083. X
  1084. X    for (i = 0; i < NLOCALS; i++) {
  1085. X        locals[i].l_id = NIL;
  1086. X        locals[i].l_scopes = 0;
  1087. X    }
  1088. X}
  1089. X
  1090. Xclearscope(scope)
  1091. Xregister int scope;
  1092. X{
  1093. X    register int i;
  1094. X
  1095. X    for (i = 0; i < NLOCALS; i++) {
  1096. X        if (locals[i].l_id != NIL) {
  1097. X            locals[i].l_scopes &= scopemask[scope-1];
  1098. X        }
  1099. X    }
  1100. X}
  1101. X
  1102. Xstruct inline_node *
  1103. Xisinline(id)
  1104. Xregister char *id;
  1105. X{
  1106. X    register int i;
  1107. X
  1108. X    for(i=0; (i < NINLINE) && (nodelist[i] != NILP(struct inline_node *)); i++) {
  1109. X        if (nodelist[i]->i_id && strcmp(nodelist[i]->i_id, id) == 0) {
  1110. X            return(nodelist[i]);
  1111. X        }
  1112. X    }
  1113. X    return((struct inline_node *) 0);
  1114. X}
  1115. X
  1116. X
  1117. Xpushscope(level)
  1118. X{
  1119. X    register int mem;
  1120. X    register int i;
  1121. X
  1122. X    if (level >= NSCOPE) {
  1123. X        error(line, "internal - push of invalid scope level");
  1124. X        return;
  1125. X    }
  1126. X    mem = openpool();
  1127. X    typeid[level] = (struct typelist *) getmem(mem,1,sizeof(struct typelist));
  1128. X    if (typeid[level] == NILP(struct typelist *)) {
  1129. X        error(line, "internal - out of memory");
  1130. X        return;
  1131. X    }
  1132. X    typeid[level]->type_mem = mem;
  1133. X    for (i = 0; i < NTYPEDEF; i++) {
  1134. X        typeid[level]->type_id[i] = NIL;
  1135. X    }
  1136. X    return;
  1137. X}
  1138. X
  1139. Xpopscope(level)
  1140. X{
  1141. X#ifdef notdef
  1142. X    if (level == 0) {
  1143. X        error(line, "internal - pop of scope 0\n");
  1144. X        return;
  1145. X    }
  1146. X#endif
  1147. X    if (level >= NSCOPE) {
  1148. X        error(line, "internal - invalid scope depth");
  1149. X        return;
  1150. X    }
  1151. X
  1152. X    (void) closepool(typeid[level]->type_mem);
  1153. X    typeid[level] = NILP(struct typelist *);
  1154. X    return;
  1155. X}
  1156. X
  1157. Xdump(n)
  1158. Xint n;
  1159. X{
  1160. X    register int i;
  1161. X    struct token tok;
  1162. X
  1163. X    if (n < 1) return;
  1164. X
  1165. X    for (i = 0; (i < NINLINE) && (nodelist[i] != NILP(struct inline_node *)); i++) {
  1166. X        if (n > 1 || (nodelist[i]->i_nseen > nodelist[i]->i_nexpand)) {
  1167. X            if (nodelist[i]->i_text.tl_head->t_tok == T_INLINE) {
  1168. X                nodelist[i]->i_text.tl_head =
  1169. X                    nodelist[i]->i_text.tl_head->t_next;
  1170. X            }
  1171. X
  1172. X            if (forward_decl) {
  1173. X                tok.t_tok = forward_decl;
  1174. X                prtok(&tok,0,stdout);
  1175. X            }
  1176. X            prtoklist(&nodelist[i]->i_text,0,stdout);
  1177. X            printf("\n\n");
  1178. X        }
  1179. X    }
  1180. X}
  1181. X
  1182. X
  1183. Xprstats(n)
  1184. Xint n;
  1185. X{
  1186. X    register int i;
  1187. X    int nseen = 0;
  1188. X    int nnode = 0;
  1189. X    int nexpand = 0;
  1190. X
  1191. X    for(i=0; (i < NINLINE) && (nodelist[i] != NILP(struct inline_node *)); i++) {
  1192. X        nnode++;
  1193. X        nseen += nodelist[i]->i_nseen;
  1194. X        nexpand += nodelist[i]->i_nexpand;
  1195. X        if (n > 1) {
  1196. X            fprintf(stderr,
  1197. X                "inline %s(): %d expansions in %d occurences\n",
  1198. X                nodelist[i]->i_id,nodelist[i]->i_nexpand,
  1199. X                nodelist[i]->i_nseen);
  1200. X        }
  1201. X    }
  1202. X    fprintf(stderr, "%d nodes, %d expansions in %d occurences\n",
  1203. X            nnode, nexpand, nseen);
  1204. X}
  1205. X
  1206. X#ifdef LOGFILE
  1207. X
  1208. X#include <pwd.h>
  1209. Xextern char *ctime();
  1210. X
  1211. Xlogusage(argc,argv)
  1212. Xint argc;
  1213. Xchar **argv;
  1214. X{
  1215. X    FILE *f;
  1216. X    struct passwd *pw;
  1217. X    char *name, *t;
  1218. X    long now;
  1219. X
  1220. X    if (f = fopen(LOGFILE,"a")) {
  1221. X        setpwent();
  1222. X        pw = getpwuid(getuid());
  1223. X        endpwent();
  1224. X        if (pw) {
  1225. X            name = pw->pw_name;
  1226. X            /* don't log the author */
  1227. X            if (strcmp(name,"mcg") == 0) {
  1228. X                fclose(f);
  1229. X                return;
  1230. X            }
  1231. X        } else {
  1232. X            name = "???";
  1233. X        }
  1234. X        now = time(0);
  1235. X        t = ctime(&now);
  1236. X        t[strlen(t)-1] = '\0';
  1237. X        t += 4;
  1238. X        fprintf(f,"%s [%s]", pw->pw_name, t);
  1239. X        if (argc > 1) {
  1240. X            fprintf(f," (");
  1241. X            while(--argc) {
  1242. X                fprintf(f,"%s", *argv);
  1243. X                argv++;
  1244. X                if (argc) fprintf(f," ");
  1245. X            }
  1246. X            fprintf(f,")");
  1247. X        }
  1248. X        fprintf(f,"\n");
  1249. X        fclose(f);
  1250. X    }
  1251. X    return;
  1252. X}
  1253. X
  1254. X#endif
  1255. \Rogue\Monster\
  1256. else
  1257.   echo "will not over write ./inline.c"
  1258. fi
  1259. chmod 444 ./inline.c
  1260. if [ `wc -c ./inline.c | awk '{printf $1}'` -ne 14368 ]
  1261. then
  1262. echo `wc -c ./inline.c | awk '{print "Got " $1 ", Expected " 14368}'`
  1263. fi
  1264. if `test ! -s ./declare.c`
  1265. then
  1266. echo "writing ./declare.c"
  1267. sed 's/^X//' > ./declare.c << '\Rogue\Monster\'
  1268. X/*
  1269. X * inline code expander
  1270. X *
  1271. X * (c) 1986 - copyright 1986, s. mcgeady, all rights reserved
  1272. X */
  1273. X
  1274. X/* $Header: declare.c,v 1.10 87/06/24 13:11:05 mcg Rel $ */
  1275. X
  1276. X
  1277. X/*
  1278. X * process the declaration of an inline subroutine
  1279. X *
  1280. X * this involves storing away the declaration, formal parameter list,
  1281. X * formal parameter declarations, and body, and rewriting the body part
  1282. X * of the inline by adding formal parameter declarations at the top
  1283. X * with initialization templates, and replace return statements with
  1284. X * assignments to the return value template and jumps to the end
  1285. X * of the block
  1286. X */
  1287. X
  1288. X
  1289. X#include "inline.h"
  1290. X#include "tokens.h"
  1291. X
  1292. Xdodecl(list,save)
  1293. Xregister struct toklist *list;
  1294. Xregister int save;
  1295. X{
  1296. X    struct inline_node *node;
  1297. X    register int state = SDECL;
  1298. X    register int nextstate;
  1299. X    register struct token *t, *tok, *lasttok;
  1300. X    int retstmt = 0;
  1301. X    int sawretstmt = 0;
  1302. X    int structmember = 0;
  1303. X    int seenincdec = 0;
  1304. X    int i;
  1305. X    int mem;
  1306. X
  1307. X    /* note that this memory pool is permanent */
  1308. X    mem = openpool();    /* a memory pool for this guy */
  1309. X
  1310. X    node = mknode(mem);    /* no need to ever free this */
  1311. X
  1312. X    node->i_mem = mem;
  1313. X
  1314. X    /* add the node to the list */
  1315. X    for(i = 0; i < NINLINE; i++) {
  1316. X        if (nodelist[i] == NILP(struct inline_node *)) {
  1317. X            nodelist[i] = node;
  1318. X            break;
  1319. X        }
  1320. X    }
  1321. X    if (nodelist[i] != node){
  1322. X        error(list->tl_head->t_line,"too many inline's");
  1323. X        return;
  1324. X    }
  1325. X    state = SDECL;
  1326. X    nextstate = -1;
  1327. X    node->i_line = line;
  1328. X
  1329. X    lasttok = NILTOK;
  1330. X    for (tok = list->tl_head; tok != NILTOK; tok = tok->t_next) {
  1331. X        if (tok->t_tok == T_INLINE) {
  1332. X            break;
  1333. X        }
  1334. X        lasttok = tok;
  1335. X    }
  1336. X    if (tok == NILTOK) {
  1337. X        error(list->tl_head->t_line,"internal error in dodecl()");
  1338. X        return;
  1339. X    }
  1340. X    /* break the inline declaration off from the preceding stream */
  1341. X    if (lasttok) {
  1342. X        lasttok->t_next = NILTOK;
  1343. X    } else {
  1344. X        list->tl_head = NILTOK;
  1345. X        list->tl_tail = NILTOK;
  1346. X    }
  1347. X    for ( /* */ ; tok != NILTOK; tok = tok->t_next) {
  1348. X        /* put tokens on save list for possible dump later */
  1349. X        if (save) {
  1350. X            addtok(&node->i_text,duptok(mem,tok));
  1351. X        }
  1352. X
  1353. X        if (nextstate >= 0) {
  1354. X            state = nextstate;
  1355. X            nextstate = -1;
  1356. X        }
  1357. X        if ((retstmt == 1) && (tok->t_tok != T_WS) &&
  1358. X            (tok->t_tok != T_SEMIC)) {
  1359. X            addtok(&node->i_tl[state], newtok(mem,T_RETVAL,NIL));
  1360. X            addtok(&node->i_tl[state], newtok(mem,T_WS," "));
  1361. X            addtok(&node->i_tl[state], newtok(mem,T_EQ,NIL));
  1362. X            addtok(&node->i_tl[state], newtok(mem,T_WS," "));
  1363. X            node->i_flags |= NEEDRETVAL;
  1364. X            retstmt++;
  1365. X        }
  1366. X        switch(tok->t_tok) {
  1367. X
  1368. X        case T_INLINE:
  1369. X            continue;
  1370. X
  1371. X        case T_LABEL:
  1372. X            if (state != SBODY) {
  1373. X                error(tok->t_line,"invalid label '%s:'",tok->t_id);
  1374. X            }
  1375. X            break;
  1376. X
  1377. X        case T_IDENT:
  1378. X            /* an identifier, what state are we in? */
  1379. X            if (!structmember) {
  1380. X                doident(state, seenincdec, tok, node, mem);
  1381. X            }
  1382. X            structmember = 0;
  1383. X            seenincdec = 0;
  1384. X            break;
  1385. X
  1386. X        case T_INC:    case T_DEC:    
  1387. X            seenincdec = 1;
  1388. X            break;
  1389. X
  1390. X        case T_LPAREN:
  1391. X            if ((state == SDECL) && (tok->t_paren == 0) &&
  1392. X                (node->i_id != NIL)) {
  1393. X                state = SFORMAL;
  1394. X            }
  1395. X            break;
  1396. X
  1397. X        case T_RPAREN:
  1398. X            if ((state == SFORMAL) && (tok->t_paren == 0)) {
  1399. X                nextstate = SOPARAMDECL;
  1400. X            }
  1401. X            break;
  1402. X
  1403. X        case T_LBRACE:
  1404. X            if ((state == SFORMAL) || (state == SOPARAMDECL)) {
  1405. X                doformals(node);
  1406. X                state = SBODY;
  1407. X                nextstate = -1;
  1408. X            } else if (state != SBODY) {
  1409. X                error(tok->t_line,"no identifier found after 'inline'");
  1410. X
  1411. X                /* rewrite node eliminating 'inline' */
  1412. X            }
  1413. X            seenincdec = 0;
  1414. X            break;
  1415. X
  1416. X        case T_RBRACE:
  1417. X            if ((state == SBODY) && (tok->t_level == 0)) {
  1418. X                addtok(&node->i_tl[state], duptok(mem,tok));
  1419. X                if (sawretstmt) {
  1420. X                    doretlab(&node->i_tl[state], node->i_id,mem);
  1421. X                }
  1422. X                /* add the extern or static decl for this */
  1423. X                if (forward_decl) {
  1424. X                    struct toklist fdecl;
  1425. X
  1426. X                    putdecl(node,&fdecl);
  1427. X                    if (lasttok) {
  1428. X                        (void) instok(lasttok,fdecl.tl_head);
  1429. X                    } else {
  1430. X                        list->tl_head = fdecl.tl_head;
  1431. X                        list->tl_tail = fdecl.tl_tail;
  1432. X                    }
  1433. X                }
  1434. X                node->i_exprmem = openpool();
  1435. X                if (rewrite(node,&node->i_tl[SBODY],1) > 0) {
  1436. X                    node->i_flags |= I_EXPR;
  1437. X                } else {
  1438. X                    closepool(node->i_exprmem);
  1439. X                    node->i_exprmem = -1;
  1440. X                }
  1441. X                if (debug) {
  1442. X                    debugnode(node);    /*DEBUG*/
  1443. X                }
  1444. X                return;    /* this is the only way out */
  1445. X            }
  1446. X            seenincdec = 0;
  1447. X            break;
  1448. X
  1449. X        case T_EXTERN:
  1450. X        case T_STATIC:
  1451. X            if (state == SDECL) {
  1452. X                node->i_storclass = tok->t_tok;
  1453. X            } else if (state != SBODY) {
  1454. X                error(tok->t_line,"illegal parameter declaration");
  1455. X            }
  1456. X            break;
  1457. X
  1458. X        case T_ELLIPSES:
  1459. X            error(tok->t_line,"inline routines can't be varargs");
  1460. X            break;
  1461. X
  1462. X        case T_RETURN:
  1463. X            addtok(&node->i_tl[state], t = newtok(mem,T_LBRACE,NIL));
  1464. X            t->t_level = tok->t_level;
  1465. X            retstmt = 1;
  1466. X            sawretstmt = 1;
  1467. X            seenincdec = 0;
  1468. X            continue;
  1469. X
  1470. X        case T_SEMIC:
  1471. X            if ((state == SBODY) && retstmt) {
  1472. X                doreturn(&node->i_tl[state], node->i_id,mem);
  1473. X                retstmt = 0;
  1474. X                addtok(&node->i_tl[state], duptok(mem,tok));
  1475. X                addtok(&node->i_tl[state], t = newtok(mem,T_RBRACE,NIL));
  1476. X                t->t_level = tok->t_level;
  1477. X                continue;
  1478. X            }
  1479. X            seenincdec = 0;
  1480. X            break;
  1481. X
  1482. X        case T_DOT:
  1483. X        case T_PTR:
  1484. X            structmember++;
  1485. X            break;
  1486. X
  1487. X        default:
  1488. X            break;
  1489. X        }
  1490. X
  1491. X        /* add the current token to the appropriate list */
  1492. X        addtok(&node->i_tl[state], duptok(mem,tok));
  1493. X    }
  1494. X    /*NOTREACHED*/
  1495. X    /* error(tok->t_line, "internal error in inline declaration"); */
  1496. X}
  1497. X
  1498. Xdoident(state,seenincdec,tok,node, mem)
  1499. Xint state, seenincdec;
  1500. Xregister struct token *tok;
  1501. Xregister struct inline_node *node;
  1502. Xint mem;
  1503. X{
  1504. X    register int i;
  1505. X
  1506. X    switch(state) {
  1507. X    case SDECL:    /* declaration */
  1508. X        if (node->i_id != NIL) {
  1509. X            error(tok->t_line, "too many identifiers on declaration line");
  1510. X            break;
  1511. X        }
  1512. X        if (isinline(tok->t_id)) {
  1513. X            error(tok->t_line, "redeclaration of inline '%s'", tok->t_id);
  1514. X            /* break; */
  1515. X        }
  1516. X        node->i_id = mkstr(mem,tok->t_id,0);
  1517. X        tok->t_tok = T_RETVAL;
  1518. X        break;
  1519. X
  1520. X    case SFORMAL:    /* formal parameter */
  1521. X        i = node->i_nformals++;
  1522. X        tok->t_tok = T_FORMAL;
  1523. X        node->i_formals[i] = mkstr(mem,tok->t_id,0);
  1524. X        break;
  1525. X
  1526. X    case SOPARAMDECL: /* old-style param declaration */
  1527. X        if (isformal(node,tok) < 0) {
  1528. X            error(tok->t_line,"parameter '%s' not in formal list",tok->t_id);
  1529. X        } else {
  1530. X            tok->t_tok = T_FORMAL;
  1531. X        }
  1532. X        break;
  1533. X    case SBODY:    /* found a formal in the body */
  1534. X        /*
  1535. X         * if an identifier in the body matches
  1536. X         * a formal, change it to be new formal name
  1537. X         *
  1538. X         * check to see if the formal is used as
  1539. X         * an lvalue, which prevents various
  1540. X         * optimizations we could otherwise perform 
  1541. X         */
  1542. X
  1543. X        if ((i = isformal(node,tok)) >= 0) {
  1544. X            tok->t_tok = T_FORMAL;
  1545. X            if (seenincdec || isassigned(tok)) {
  1546. X                node->i_formalinfo[i] |= I_LVALUE;
  1547. X            }
  1548. X        } else if ((strcmp(node->i_id,tok->t_id) == 0) && iscall(tok)) {
  1549. X            error(tok->t_line, "recursive inline expansion");
  1550. X        }
  1551. X        break;
  1552. X    default:    /* somewhere else ?? */
  1553. X        break;
  1554. X    }
  1555. X}
  1556. X
  1557. X
  1558. Xdoreturn(list,id,mem)
  1559. Xstruct toklist *list;
  1560. Xchar *id;
  1561. X{
  1562. X    addtok(list, newtok(mem,T_SEMIC, NIL));
  1563. X    addtok(list, newtok(mem,T_WS, " "));
  1564. X    addtok(list, newtok(mem,T_GOTO, NIL));
  1565. X    addtok(list, newtok(mem,T_WS, " "));
  1566. X    addtok(list, newtok(mem,T_RETLAB, NIL));
  1567. X}
  1568. X
  1569. Xdoretlab(list,id,mem)
  1570. Xstruct toklist *list;
  1571. Xchar *id;
  1572. Xint mem;
  1573. X{
  1574. X    addtok(list, newtok(mem,T_WS,"\n"));
  1575. X    addtok(list, newtok(mem,T_RETLAB,NIL));
  1576. X    addtok(list, newtok(mem,T_COLON,NIL));
  1577. X    addtok(list, newtok(mem,T_SEMIC,NIL));
  1578. X    addtok(list, newtok(mem,T_WS,"\n"));
  1579. X}
  1580. X
  1581. Xputdecl(node,decl)
  1582. Xregister struct inline_node *node;
  1583. Xregister struct toklist *decl;
  1584. X{
  1585. X    register struct token *tl;
  1586. X
  1587. X    decl->tl_head = decl->tl_tail = NILTOK;
  1588. X
  1589. X    addtok(decl, newtok(node->i_mem,forward_decl,NIL));
  1590. X
  1591. X    for(tl = node->i_tl[SDECL].tl_head; tl != NILTOK; tl = tl->t_next) {
  1592. X        addtok(decl,duptok(node->i_mem,tl));
  1593. X        if (tl->t_tok == T_RETVAL) {
  1594. X            decl->tl_tail->t_tok = T_IDENT;
  1595. X        }
  1596. X    }
  1597. X    addtok(decl, newtok(node->i_mem,T_LPAREN,NIL));
  1598. X    addtok(decl, newtok(node->i_mem,T_RPAREN,NIL));
  1599. X    addtok(decl, newtok(node->i_mem,T_SEMIC,NIL));
  1600. X    addtok(decl, newtok(node->i_mem,T_WS, " /* forward decl */\n"));
  1601. X}
  1602. X
  1603. Xisassigned(tok)
  1604. Xregister struct token *tok;
  1605. X{
  1606. X    register struct token *t;
  1607. X
  1608. X    for (t = tok; t != NILTOK; t = t->t_next) {
  1609. X        switch(t->t_tok) {
  1610. X
  1611. X        case T_LPAREN:    case T_RPAREN:
  1612. X        case T_WS:    case T_COMMENT:
  1613. X        case T_FORMAL:
  1614. X            break;
  1615. X
  1616. X        case T_EQ:    case T_RS_EQ:    case T_LS_EQ:
  1617. X        case T_ADD_EQ:    case T_SUB_EQ:    case T_MUL_EQ:
  1618. X        case T_DIV_EQ:    case T_MOD_EQ:    case T_AND_EQ:
  1619. X        case T_XOR_EQ:    case T_OR_EQ:
  1620. X        case T_INC:    case T_DEC:    
  1621. X        case T_DOT:            /* structure, no chances */
  1622. X            return(1);
  1623. X
  1624. X        default:
  1625. X            return(0);
  1626. X        }
  1627. X    }
  1628. X    return(0);
  1629. X}
  1630. X
  1631. X/*
  1632. X * this is called when we see an opening brace indicating the beginning
  1633. X * of the body of a function.  we look through the stored function
  1634. X * declaration, build up the formal parameter list, and rewrite the
  1635. X * function declaration into a form that can be expanded inline:
  1636. X *
  1637. X * input:                becomes:
  1638. X *
  1639. X * old-style:
  1640. X *    inline foo() { ...            { ...
  1641. X *
  1642. X *    inline foo(a,b,c) { ...            { int a = T_ACTUAL,
  1643. X *                        b = T_ACTUAL, c = T_ACTUAL;
  1644. X *                        ...
  1645. X *
  1646. X *    inline foo(a,b,c,d)            { int a = T_ACTUAL;
  1647. X *    int a; float b; char c,d;        float b = T_ACTUAL
  1648. X *    { ...                    char c = T_ACTUAL, d = T_ACTUAL;
  1649. X *                        ...
  1650. X * new-style:
  1651. X *    inline foo(int a, float b, char c) {    {
  1652. X *     ...                    int a = T_ACTUAL;
  1653. X *                        float b = T_ACTUAL;
  1654. X *                        char c = T_ACTUAL;
  1655. X *                        ...
  1656. X *****
  1657. X *
  1658. X * NOTE:
  1659. X *
  1660. X * the above is how it would be done in the best of all possible worlds.
  1661. X * in practice, it turns out to be easier to issue separate initializations
  1662. X * for formals, like this:
  1663. X *
  1664. X * input:                Becomes:
  1665. X *
  1666. X *    inline foo(a,b) { ...            { int a; int b;
  1667. X *                         int foo_ret;
  1668. X *                        a = T_ACTUAL; b = T_ACTUAL;
  1669. X */
  1670. X
  1671. Xdoformals(node)
  1672. Xregister struct inline_node *node;
  1673. X{
  1674. X    register int new = 0;
  1675. X    register struct token *tl, *tok;
  1676. X    register struct toklist *paramdecl = &node->i_tl[SDECLBODY];
  1677. X    register int i;
  1678. X    int formal = -1;
  1679. X    int needsep = 0;
  1680. X    int gotformal[NFORMALS];
  1681. X    int parennest = 0;
  1682. X    int mem = node->i_mem;
  1683. X
  1684. X    /* determine what style of function declaration it is */
  1685. X    /* an old style parameter declaration */
  1686. X
  1687. X    tok = skipws(node->i_tl[SOPARAMDECL].tl_head);
  1688. X
  1689. X    if (tok == NILTOK) {
  1690. X        /* nothing other than whitespace in here */
  1691. X        paramdecl->tl_head = node->i_tl[SOPARAMDECL].tl_head;
  1692. X        paramdecl->tl_tail = node->i_tl[SOPARAMDECL].tl_tail;
  1693. X        node->i_tl[SOPARAMDECL].tl_head = NILTOK;
  1694. X        node->i_tl[SOPARAMDECL].tl_tail = NILTOK;
  1695. X    }
  1696. X
  1697. X    if (node->i_nformals == 0) {
  1698. X        /* no formal parameters */
  1699. X        return;
  1700. X    }
  1701. X    for (i = 0; i < NFORMALS; i++) {
  1702. X        gotformal[i] = 0;
  1703. X    }
  1704. X
  1705. X    if (node->i_tl[SOPARAMDECL].tl_head == NILTOK) {
  1706. X        /* either new style prototype declaration or args are all int */
  1707. X        for (tl = node->i_tl[SFORMAL].tl_head; tl != NILTOK; tl = tl->t_next) {
  1708. X            /* we see something other than id's, commas */
  1709. X            /* and parens, it's new-style declaration */
  1710. X            switch(tl->t_tok) {
  1711. X            case T_FORMAL:
  1712. X            case T_LPAREN:
  1713. X            case T_COMMA:
  1714. X            case T_RPAREN:
  1715. X                /* it's a new-style prototype */
  1716. X                new++;
  1717. X                tl = node->i_tl[SFORMAL].tl_head;
  1718. X                break;
  1719. X            default:
  1720. X                continue;
  1721. X            }
  1722. X            break;
  1723. X        }
  1724. X        if (!new) {    /* old style w/ args defaulted to int */
  1725. X            /* if it's old-style, then all args are 'int', so add that */
  1726. X            addtok(paramdecl,newtok(mem,T_INT,NIL));
  1727. X            addtok(paramdecl,newtok(mem,T_WS," "));
  1728. X            new = 1;
  1729. X            tl = node->i_tl[SFORMAL].tl_head;
  1730. X        }
  1731. X    } else {
  1732. X        /* loop through old-style param decl's, order them, and fill */
  1733. X        /* in those that have been defaulted */
  1734. X        for (tok = node->i_tl[SOPARAMDECL].tl_head; tok != NILTOK; tok = tok->t_next) {
  1735. X            if (tok->t_tok == T_FORMAL) {
  1736. X                if ((formal = isformal(node, tok)) >= 0) {
  1737. X                    gotformal[formal] = 1;
  1738. X                } else {
  1739. X                    error(tok->t_line, "parameter '%s' not in formal list",tok->t_id);
  1740. X                }
  1741. X            }
  1742. X        }
  1743. X        for (i = 0; i < node->i_nformals; i++) {
  1744. X            if (gotformal[i] == 0) {
  1745. X                addtok(&node->i_tl[SOPARAMDECL], newtok(mem,T_INT, NIL));
  1746. X                addtok(&node->i_tl[SOPARAMDECL], newtok(mem,T_WS, " "));
  1747. X                addtok(&node->i_tl[SOPARAMDECL], newtok(mem,T_FORMAL, node->i_formals[i]));
  1748. X                addtok(&node->i_tl[SOPARAMDECL], newtok(mem,T_SEMIC, NIL));
  1749. X                addtok(&node->i_tl[SOPARAMDECL], newtok(mem,T_WS, " "));
  1750. X                gotformal[i] = 1;
  1751. X            }
  1752. X        }
  1753. X        tl = node->i_tl[SOPARAMDECL].tl_head;
  1754. X    }
  1755. X
  1756. X
  1757. X    /*
  1758. X     * loop through the formal declaration token list (or old style
  1759. X     * parameter declaration list, if applicable)
  1760. X     */
  1761. X    for ( /* tl init above */ ; tl != NILTOK; tl = tl->t_next) {
  1762. X        switch(tl->t_tok) {
  1763. X        case T_LPAREN:
  1764. X            if ((++parennest == 1) && new) {
  1765. X                continue;
  1766. X            }
  1767. X            break;
  1768. X
  1769. X        case T_SEMIC:
  1770. X            needsep = 0;
  1771. X            if (new) {
  1772. X                error(tl->t_line, "unexpected semicolon in new-style parameter list");
  1773. X            }
  1774. X            /*FALLTHROUGH*/
  1775. X        case T_RPAREN:
  1776. X            if (tl->t_tok == T_RPAREN) {
  1777. X                if (parennest >= 1) {
  1778. X                    parennest--;
  1779. X                } else {
  1780. X                    error(tl->t_line, "rparen error");
  1781. X                    break;
  1782. X                }
  1783. X                if (new && (parennest > 0)) {
  1784. X                    break;
  1785. X                }
  1786. X            }    
  1787. X            /*FALLTHROUGH*/
  1788. X        case T_COMMA:
  1789. X            if (formal >= 0) { /* seen a comma or semi-colon */
  1790. X
  1791. X                formal = -1;
  1792. X                /* haven't added the comma or semicolon */
  1793. X                if (tl->t_tok == T_SEMIC) {
  1794. X                    addtok(paramdecl, newtok(mem,T_SEMIC, NIL));
  1795. X                } else {
  1796. X                    needsep = 1;
  1797. X                }
  1798. X                continue;
  1799. X            }
  1800. X            break;    /* go ahead and add the token */
  1801. X
  1802. X        case T_FORMAL:
  1803. X            if (needsep) {
  1804. X                addtok(paramdecl,newtok(mem,T_COMMA,NIL));
  1805. X                needsep = 0;
  1806. X            }
  1807. X            addtok(paramdecl, tok = duptok(mem,tl));
  1808. X            if ((formal = isformal(node,tl)) < 0) {
  1809. X                error(tl->t_line,"parameter '%s' not in formals list", tl->t_id);
  1810. X            }
  1811. X            continue;
  1812. X
  1813. X        default:
  1814. X            break;
  1815. X        }
  1816. X        if (needsep) {
  1817. X            if (istype(tl) || isstoreclass(tl)) {
  1818. X                addtok(paramdecl,newtok(mem,T_SEMIC,NIL));
  1819. X                needsep = 0;
  1820. X            } else if (tl->t_tok == T_STAR) {
  1821. X                addtok(paramdecl,newtok(mem,T_COMMA,NIL));
  1822. X                needsep = 0;
  1823. X            }
  1824. X        }
  1825. X        addtok(paramdecl, tok = duptok(mem,tl));
  1826. X        /* don't put other tokens in init list */
  1827. X    }
  1828. X    if (needsep) {
  1829. X        addtok(paramdecl,newtok(mem,T_SEMIC,NIL));
  1830. X    }
  1831. X    addtok(paramdecl,newtok(mem,T_WS,"\n"));
  1832. X    return;
  1833. X}
  1834. X/*
  1835. X * return true if the argument tok is in the formal parameter list
  1836. X */
  1837. X
  1838. Xisformal(node,tok)
  1839. Xregister struct inline_node *node;
  1840. Xregister struct token *tok;
  1841. X{
  1842. X    register int i;
  1843. X
  1844. X    for(i=0; i < node->i_nformals; i++) {
  1845. X        if (strcmp(tok->t_id, node->i_formals[i]) == 0) {
  1846. X            return(i);
  1847. X        }
  1848. X    }
  1849. X    return(-1);
  1850. X}
  1851. X
  1852. Xisdecl(tl)
  1853. Xregister struct toklist *tl;
  1854. X{
  1855. X    register struct token *tok;
  1856. X
  1857. X    for (tok = tl->tl_head; tok != NILTOK; tok = tok->t_next) {
  1858. X        if (tok->t_tok == T_INLINE) {
  1859. X            return(1);
  1860. X        }
  1861. X    }
  1862. X    return(0);
  1863. X}
  1864. X
  1865. X
  1866. X/*
  1867. X * process a typedef line
  1868. X *
  1869. X * typedefs take the general form:
  1870. X *
  1871. X *    typedef base_type new_type;
  1872. X *
  1873. X *    however, one must watch for situations like:
  1874. X *
  1875. X *    typedef int newtype[DEFINE];
  1876. X *    typedef struct { int a; int b } newtype;
  1877. X *
  1878. X *    so the trick needs to be that the new type is the last identifier
  1879. X *    not embedded in braces or brackets;
  1880. X */
  1881. X
  1882. Xdotypedef(begin)
  1883. Xregister struct token *begin;
  1884. X{
  1885. X    register struct token *lastid = NILTOK;
  1886. X    register struct token *tl;
  1887. X    register char **p;
  1888. X    int level = -1;
  1889. X    int needbrack = 0;
  1890. X
  1891. X    for (tl = begin; tl != NILTOK; tl = tl->t_next) {
  1892. X        if (tl->t_tok == T_TYPEDEF) {
  1893. X            if (level >= 0) {
  1894. X                error(tl->t_line, "typedef within typedef");
  1895. X                return;
  1896. X            }
  1897. X            level = tl->t_level;
  1898. X            if ((level > NSCOPE) || (typeid[level] == NILP(struct typelist *))) {
  1899. X                error(tl->t_line, "bad level in dotypedef");
  1900. X                return;
  1901. X            }
  1902. X            continue;
  1903. X        }
  1904. X        if ((tl->t_tok == T_SEMIC) && (tl->t_level == level)) {
  1905. X            break;
  1906. X        }
  1907. X        if (tl->t_tok == T_LSQ) {
  1908. X            needbrack++;
  1909. X            continue;
  1910. X        }
  1911. X        if (needbrack) {
  1912. X            if (tl->t_tok == T_RSQ) {
  1913. X                needbrack--;
  1914. X            }
  1915. X            continue;
  1916. X        }
  1917. X        if ((tl->t_tok == T_IDENT) && (tl->t_level == level)) {
  1918. X            lastid = tl;
  1919. X        }
  1920. X    }
  1921. X    if (tl->t_tok != T_SEMIC) {
  1922. X        error(tl->t_line, "dotypedef terminated abnormally");
  1923. X    }
  1924. X    if (level < 0) {
  1925. X        error(tl->t_line, "internal error in dotypedef");
  1926. X        return;
  1927. X    }
  1928. X    if (lastid) {
  1929. X        lastid->t_tok = T_TYPE_ID;
  1930. X        for (p = typeid[level]->type_id; *p != NIL; p++) {
  1931. X            if (strcmp(lastid->t_id,*p) == 0) {
  1932. X                error(tl->t_line, "redeclaration of %s",*p);
  1933. X            }
  1934. X        }
  1935. X        if ((p-typeid[level]->type_id) < NTYPEDEF) {
  1936. X            *p = mkstr(typeid[level]->type_mem,lastid->t_id,0);
  1937. X        } else {
  1938. X            error(tl->t_line, "too many typedefs at scope level %d", level);
  1939. X        }
  1940. X    }
  1941. X}
  1942. X
  1943. \Rogue\Monster\
  1944. else
  1945.   echo "will not over write ./declare.c"
  1946. fi
  1947. chmod 444 ./declare.c
  1948. if [ `wc -c ./declare.c | awk '{printf $1}'` -ne 15931 ]
  1949. then
  1950. echo `wc -c ./declare.c | awk '{print "Got " $1 ", Expected " 15931}'`
  1951. fi
  1952. echo "Finished archive 3 of 3"
  1953. # if you want to concatenate archives, remove anything after this line
  1954. exit
  1955.