cccp.c 63 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469
  1. /* C Compatible Compiler Preprocessor (CCCP)
  2. Copyright (C) 1986, Free Software Foundation, Inc.
  3. Written by Paul Rubin, June 1986
  4. NO WARRANTY
  5. BECAUSE THIS PROGRAM IS LICENSED FREE OF CHARGE, WE PROVIDE ABSOLUTELY
  6. NO WARRANTY, TO THE EXTENT PERMITTED BY APPLICABLE STATE LAW. EXCEPT
  7. WHEN OTHERWISE STATED IN WRITING, FREE SOFTWARE FOUNDATION, INC,
  8. RICHARD M. STALLMAN AND/OR OTHER PARTIES PROVIDE THIS PROGRAM "AS IS"
  9. WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
  10. BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
  11. FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY
  12. AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE
  13. DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR
  14. CORRECTION.
  15. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW WILL RICHARD M.
  16. STALLMAN, THE FREE SOFTWARE FOUNDATION, INC., AND/OR ANY OTHER PARTY
  17. WHO MAY MODIFY AND REDISTRIBUTE THIS PROGRAM AS PERMITTED BELOW, BE
  18. LIABLE TO YOU FOR DAMAGES, INCLUDING ANY LOST PROFITS, LOST MONIES, OR
  19. OTHER SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
  20. USE OR INABILITY TO USE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR
  21. DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY THIRD PARTIES OR
  22. A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS) THIS
  23. PROGRAM, EVEN IF YOU HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH
  24. DAMAGES, OR FOR ANY CLAIM BY ANY OTHER PARTY.
  25. GENERAL PUBLIC LICENSE TO COPY
  26. 1. You may copy and distribute verbatim copies of this source file
  27. as you receive it, in any medium, provided that you conspicuously
  28. and appropriately publish on each copy a valid copyright notice
  29. "Copyright (C) 1986 Free Software Foundation"; and include
  30. following the copyright notice a verbatim copy of the above disclaimer
  31. of warranty and of this License.
  32. 2. You may modify your copy or copies of this source file or
  33. any portion of it, and copy and distribute such modifications under
  34. the terms of Paragraph 1 above, provided that you also do the following:
  35. a) cause the modified files to carry prominent notices stating
  36. that you changed the files and the date of any change; and
  37. b) cause the whole of any work that you distribute or publish,
  38. that in whole or in part contains or is a derivative of this
  39. program or any part thereof, to be freely distributed
  40. and licensed to all third parties on terms identical to those
  41. contained in this License Agreement (except that you may choose
  42. to grant more extensive warranty protection to third parties,
  43. at your option).
  44. 3. You may copy and distribute this program or any portion of it in
  45. compiled, executable or object code form under the terms of Paragraphs
  46. 1 and 2 above provided that you do the following:
  47. a) cause each such copy to be accompanied by the
  48. corresponding machine-readable source code, which must
  49. be distributed under the terms of Paragraphs 1 and 2 above; or,
  50. b) cause each such copy to be accompanied by a
  51. written offer, with no time limit, to give any third party
  52. free (except for a nominal shipping charge) a machine readable
  53. copy of the corresponding source code, to be distributed
  54. under the terms of Paragraphs 1 and 2 above; or,
  55. c) in the case of a recipient of this program in compiled, executable
  56. or object code form (without the corresponding source code) you
  57. shall cause copies you distribute to be accompanied by a copy
  58. of the written offer of source code which you received along
  59. with the copy you received.
  60. 4. You may not copy, sublicense, distribute or transfer this program
  61. except as expressly provided under this License Agreement. Any attempt
  62. otherwise to copy, sublicense, distribute or transfer this program is void and
  63. your rights to use the program under this License agreement shall be
  64. automatically terminated. However, parties who have received computer
  65. software programs from you with this License Agreement will not have
  66. their licenses terminated so long as such parties remain in full compliance.
  67. In other words, you are welcome to use, share and improve this program.
  68. You are forbidden to forbid anyone else to use, share and improve
  69. what you give them. Help stamp out software-hoarding! */
  70. typedef unsigned char U_CHAR;
  71. #ifdef EMACS
  72. #define NO_SHORTNAMES
  73. #include "../src/config.h"
  74. #ifdef open
  75. #undef open
  76. #undef read
  77. #undef write
  78. #endif /* open */
  79. #endif /* EMACS */
  80. #include <sys/types.h>
  81. #include <sys/stat.h>
  82. #include <sys/file.h>
  83. #include <ctype.h>
  84. #include <stdio.h>
  85. #ifndef USG
  86. #include <sys/time.h> /* for __DATE__ and __TIME__ */
  87. #else
  88. #define index strchr
  89. #define rindex strrchr
  90. #include <time.h>
  91. #include <fcntl.h>
  92. #endif /* USG */
  93. void bcopy (), bzero ();
  94. int bcmp ();
  95. char *xmalloc (), *xrealloc (), *xcalloc ();
  96. void fatal (), pfatal_with_name (), perror_with_name ();
  97. char *progname;
  98. #define FATAL_EXIT_CODE 33 /* gnu cc command understands this */
  99. struct directory_stack
  100. {
  101. struct directory_stack *next;
  102. char *fname;
  103. };
  104. /* #include "file" starts with the first entry in the stack */
  105. /* #include <file> starts with the second. */
  106. /* -I directories are added after the first */
  107. struct directory_stack default_includes[2] =
  108. {
  109. { &default_includes[1], "." },
  110. { 0, "/usr/include" }
  111. };
  112. struct directory_stack *include = &default_includes[0];
  113. int max_include_len = 14; /* strlen (default_include) + 2
  114. (for / and null) */
  115. char STDIN_FILE[] = ""; /* Empty, like real cpp */
  116. int put_out_comments = 0; /* JF non-zero means leave comments in the
  117. output file. Used by lint */
  118. /* table to tell if char can be part of a C identifier. */
  119. U_CHAR is_idchar[256];
  120. /* table to tell if char can be first char of a c identifier. */
  121. U_CHAR is_idstart[256];
  122. /* table to tell if c is horizontal space. isspace() thinks that
  123. newline is space; this is not a good idea for this program. */
  124. U_CHAR is_hor_space[256];
  125. /* I/O buffer structure. Ought to be used for the output file too.
  126. These are also used when there is no file present, for example,
  127. when rescanning a definition. Then, the fname field is null. */
  128. #define INPUT_STACK_MAX 100
  129. struct file_buf {
  130. struct infile *next; /* for making stacks of file ptrs */
  131. char *fname;
  132. int lineno;
  133. int length;
  134. U_CHAR *buf;
  135. U_CHAR *bufp;
  136. } instack[INPUT_STACK_MAX];
  137. int indepth = 0;
  138. typedef struct file_buf FILE_BUF;
  139. /* The output buffer. Its LENGTH field is the amount of room allocated
  140. for the buffer, not the number of chars actually present. To get
  141. that, subtract outbuf.buf from outbuf.bufp. */
  142. #define OUTBUF_SIZE 10 /* initial size of output buffer */
  143. FILE_BUF outbuf;
  144. /* Structure allocated for every #define. For a simple replacement
  145. such as
  146. #define foo bar ,
  147. nargs = -1, the `pattern' list is null, and the expansion is just
  148. the replacement text. Nargs = 0 means a real macro with no args,
  149. e.g.,
  150. #define getchar() getc(stdin) .
  151. When there are args, the expansion is the replacement text with the
  152. args squashed out, and the reflist is a list describing how to
  153. build the output from the input: e.g., "3 chars, then the 1st arg,
  154. then 9 chars, then the 3rd arg, then 0 chars, then the 2nd arg".
  155. The chars here come from the expansion. Thus, for any definition
  156. d , strlen(d->expansion) should equal the sum of all the
  157. d->pattern->nchars. Note that the list can be arbitrarily long---
  158. its length depends on the number of times the arguements appear in
  159. the replacement text, not how many args there are. Example:
  160. #define f(x) x+x+x+x+x+x+x would have replacement text "++++++" and
  161. pattern list
  162. { (0, 1), (1, 1), (1, 1), ..., (1, 1), NULL }
  163. where (x, y) means (nchars, argno). */
  164. typedef struct definition DEFINITION;
  165. struct definition {
  166. int nargs;
  167. int length; /* length of expansion string */
  168. U_CHAR *expansion;
  169. struct reflist {
  170. struct reflist *next;
  171. int nchars;
  172. int argno;
  173. } *pattern;
  174. };
  175. /* different kinds of things that can appear in the value field
  176. of a hash node. Actually, this may be useless now. */
  177. union hashval {
  178. int ival;
  179. char *cpval;
  180. DEFINITION *defn;
  181. };
  182. /* The structure of a node in the hash table. The hash table
  183. has entries for all tokens defined by #define commands (type T_MACRO),
  184. plus some special tokens like __LINE__ (these each have their own
  185. type, and the appropriate code is run when that type of node is seen.
  186. It does not contain control words like "#define", which are recognized
  187. by a separate piece of code. */
  188. typedef struct hashnode HASHNODE;
  189. struct hashnode {
  190. HASHNODE *next; /* double links for easy deletion */
  191. HASHNODE *prev;
  192. HASHNODE **bucket_hdr; /* also, a back pointer to this node's hash
  193. chain is kept, in case the node is the head
  194. of the chain and gets deleted. */
  195. int type; /* type of special token */
  196. int length; /* length of token, for quick comparison */
  197. U_CHAR *name; /* the actual name */
  198. union hashval value; /* pointer to expansion, or whatever */
  199. };
  200. HASHNODE *install();
  201. /* different flavors of hash nodes --- also used in keyword table */
  202. #define T_DEFINE 1 /* the "#define" keyword */
  203. #define T_INCLUDE 2 /* the "#include" keyword */
  204. #define T_IFDEF 3 /* the "#ifdef" keyword */
  205. #define T_IF 4 /* the "#if" keyword */
  206. #define T_EXPAND 5 /* argument to be expanded (now unused) */
  207. #define T_MACRO 6 /* macro defined by "#define" */
  208. #define T_ELSE 7 /* "#else" */
  209. #define T_PRAGMA 8 /* "#pragma" */
  210. #define T_ELIF 9 /* "#else" */
  211. #define T_UNDEF 10 /* "#undef" */
  212. #define T_LINE 11 /* "#line" */
  213. #define T_ERROR 12 /* "#error" */
  214. #define T_IFNDEF 13 /* "#ifndef"; forgot this earlier */
  215. #define T_ENDIF 14 /* "#endif" */
  216. #define T_SPECLINE 15 /* special symbol "__LINE__" */
  217. #define T_DATE 16 /* "__DATE__" */
  218. #define T_FILE 17 /* "__FILE__" */
  219. #define T_TIME 18 /* "__TIME__" */
  220. #define T_SPEC_DEFINED 19 /* special macro for use in #if statements */
  221. /* some more different types will be needed --- no longer bloody likely */
  222. int do_define(), do_line(), do_include(), do_undef(), do_error(),
  223. do_pragma(), do_if(), do_xifdef(), do_else(),
  224. do_elif(), do_endif();
  225. /* table of control words, along with code to execute when the keyword
  226. is seen. For now, it is searched linearly, so put the most frequently
  227. found keywords at the beginning of the list. */
  228. struct keyword_table {
  229. int length;
  230. int (*func)();
  231. char *name;
  232. int type;
  233. } keyword_table[] = {
  234. { 6, do_define, "define", T_DEFINE},
  235. { 4, do_line, "line", T_LINE},
  236. { 7, do_include, "include", T_INCLUDE},
  237. { 5, do_undef, "undef", T_UNDEF},
  238. { 5, do_error, "error", T_ERROR},
  239. { 2, do_if, "if", T_IF},
  240. { 5, do_xifdef, "ifdef", T_IFDEF},
  241. { 6, do_xifdef, "ifndef", T_IFNDEF},
  242. { 4, do_else, "else", T_ELSE},
  243. { 4, do_elif, "elif", T_ELIF},
  244. { 5, do_endif, "endif", T_ENDIF},
  245. { 6, do_pragma, "pragma", T_PRAGMA},
  246. { -1, 0, "", -1},
  247. };
  248. /* Some definitions for the hash table. The hash function MUST be
  249. computed as shown in hashf() below. That is because the rescan
  250. loop computes the hash value `on the fly' for most tokens,
  251. in order to avoid the overhead of a lot of procedure calls to
  252. the hashf() function. Hashf() only exists for the sake of
  253. politeness, for use when speed isn't so important. */
  254. #define HASHSIZE 1009
  255. HASHNODE *hashtab[HASHSIZE];
  256. #define HASHSTEP(old, c) ((old << 1) + c)
  257. #define MAKE_POS(v) (v & ~0x80000000) /* make number positive */
  258. #define SKIP_WHITE_SPACE(p) { while (is_hor_space[*p]) p++; }
  259. main (argc, argv)
  260. int argc;
  261. char **argv;
  262. {
  263. struct stat sbuf;
  264. char *in_fname, *out_fname;
  265. int out_fd = 1; /* default to stdout */
  266. int f, i;
  267. FILE_BUF *fp;
  268. progname = argv[0];
  269. in_fname = NULL;
  270. out_fname = NULL;
  271. initialize_random_junk ();
  272. fp = &instack[indepth++];
  273. /* if (argc < 2) JF no args means work as filter
  274. return FATAL_EXIT_CODE; */
  275. for (i = 1; i < argc; i++) {
  276. if (argv[i][0] != '-') {
  277. if (out_fname != NULL)
  278. fatal ("Usage: %s [switches] input output\n", argv[0]);
  279. else if (in_fname != NULL) {
  280. out_fname = argv[i];
  281. if ((out_fd = creat (out_fname, 0666)) < 0)
  282. pfatal_with_name (out_fname);
  283. } else
  284. in_fname = argv[i];
  285. } else {
  286. switch (argv[i][1]) {
  287. U_CHAR *p;
  288. struct directory_stack *dirtmp;
  289. case 'D':
  290. if ((p = (U_CHAR *) index(argv[i]+2, '=')) != NULL)
  291. *p = ' ';
  292. make_definition (argv[i] + 2);
  293. break;
  294. case 'U': /* JF #undef something */
  295. make_undef(argv[i] + 2);
  296. break;
  297. case 'C': /* JF do later -C means leave comments alone! */
  298. put_out_comments++;
  299. break;
  300. case 'E': /* -E comes from cc -E; ignore it. */
  301. break;
  302. case 'M': /* Makefile dependencies or something like
  303. that. Not implimented yet */
  304. break;
  305. case 'I': /* JF handle directory path right */
  306. dirtmp = (struct directory_stack *)
  307. xmalloc (sizeof (struct directory_stack));
  308. dirtmp->next = include->next;
  309. include->next = dirtmp;
  310. dirtmp->fname = argv[i]+2;
  311. include = dirtmp;
  312. if (strlen (argv[i]) > max_include_len)
  313. max_include_len = strlen (argv[i]);
  314. break;
  315. case '\0': /* JF handle '-' as file name meaning stdin or stdout */
  316. if (in_fname == NULL) {
  317. in_fname = STDIN_FILE;
  318. break;
  319. } else if (out_fname == NULL) {
  320. out_fname = "stdout";
  321. break;
  322. } /* else fall through into error */
  323. default:
  324. fatal ("Illegal option %s\n", argv[i]);
  325. }
  326. }
  327. }
  328. /* JF check for stdin */
  329. if (in_fname == STDIN_FILE || in_fname == NULL)
  330. f = 0;
  331. else if ((f = open (in_fname, O_RDONLY)) < 0)
  332. goto perror;
  333. fstat (f, &sbuf);
  334. fp->fname = in_fname;
  335. fp->lineno = 1;
  336. /* JF all this is mine about reading pipes and ttys */
  337. if ((sbuf.st_mode & S_IFMT) != S_IFREG) {
  338. int size;
  339. int bsize;
  340. int cnt;
  341. U_CHAR *bufp;
  342. bsize = 2000;
  343. size = 0;
  344. fp->buf = (U_CHAR *) xmalloc (bsize + 1);
  345. bufp = fp->buf;
  346. for (;;) {
  347. cnt = read (f, bufp, bsize - size);
  348. if (cnt < 0) goto perror; /* error! */
  349. if (cnt == 0) break; /* End of file */
  350. size += cnt;
  351. bufp += cnt;
  352. if (bsize-size == 0) { /* Buffer is full! */
  353. bsize *= 2;
  354. fp->buf = (U_CHAR *) xrealloc (fp->buf, bsize + 1);
  355. bufp = fp->buf + size; /* May have moved */
  356. }
  357. }
  358. fp->buf[size] = '\0';
  359. fp->length = size;
  360. } else {
  361. fp->length = sbuf.st_size;
  362. fp->buf = (U_CHAR *) alloca (sbuf.st_size + 1);
  363. if (read (f, fp->buf, sbuf.st_size) != sbuf.st_size)
  364. goto perror;
  365. fp->buf[sbuf.st_size] = '\0';
  366. }
  367. /* initialize output buffer */
  368. outbuf.buf = (U_CHAR *) xmalloc (OUTBUF_SIZE);
  369. outbuf.bufp = outbuf.buf;
  370. outbuf.length = OUTBUF_SIZE;
  371. output_line_command (fp, &outbuf);
  372. rescan (fp, &outbuf);
  373. /* do something different than this later */
  374. fflush (stdout);
  375. write (out_fd, outbuf.buf, outbuf.bufp - outbuf.buf);
  376. exit (0);
  377. perror:
  378. pfatal_with_name (argv[1]);
  379. }
  380. /*
  381. * The main loop of the program. Try to examine and move past most
  382. * ordinary input chars as fast as possible. Call appropriate routines
  383. * when something special (such as a macro expansion) has to happen.
  384. IP is the source of input to scan.
  385. OP is the place to put input. */
  386. rescan (ip, op)
  387. FILE_BUF *ip, *op;
  388. {
  389. register U_CHAR c;
  390. register int ident_length = 0, hash = 0;
  391. register U_CHAR *limit;
  392. U_CHAR *check_expand ();
  393. struct keyword_table *handle_directive ();
  394. int excess_newlines = 0;
  395. int escaped = 0;
  396. U_CHAR *bp;
  397. check_expand(op, ip->length);
  398. ip->bufp = ip->buf;
  399. limit = ip->buf + ip->length;
  400. while (1) {
  401. if (ip->bufp < limit) {
  402. c = *ip->bufp++;
  403. *op->bufp++ = c;
  404. } else {
  405. c = -1;
  406. }
  407. --escaped;
  408. /* Now ESCAPED is 0 if and only if this character is escaped. */
  409. switch (c) {
  410. case '\\':
  411. if (escaped == 0)
  412. goto randomchar;
  413. if (*ip->bufp != '\n')
  414. {
  415. escaped = 1;
  416. goto randomchar;
  417. }
  418. /* always merge lines ending with backslash-newline */
  419. ++ip->bufp;
  420. ++ip->lineno;
  421. ++excess_newlines;
  422. --op->bufp; /* remove backslash from obuf */
  423. continue; /* back to top of while loop */
  424. case '#':
  425. /* # keyword: a # must be first nonblank char on the line */
  426. for (bp = ip->bufp - 1; bp >= ip->buf; bp--)
  427. if (*bp == '\n')
  428. break;
  429. bp++; /* skip nl or move back into buffer */
  430. SKIP_WHITE_SPACE (bp);
  431. if (*bp != '#')
  432. goto randomchar;
  433. ident_length = hash = 0;
  434. --op->bufp; /* don't copy the '#' */
  435. if (handle_directive (ip, op, &excess_newlines) == NULL) {
  436. ++op->bufp; /* copy the '#' after all */
  437. goto randomchar;
  438. }
  439. break;
  440. case '\"': /* skip quoted string */
  441. case '\'':
  442. /* a single quoted string is treated like a double -- some
  443. programs (e.g., troff) are perverse this way */
  444. if (escaped == 0)
  445. goto randomchar; /* false alarm-- it's escaped. */
  446. /* skip ahead to a matching quote. */
  447. bp = ip->bufp;
  448. while (bp < limit) {
  449. *op->bufp++ = *bp;
  450. switch (*bp++) {
  451. case '\n':
  452. ++ip->lineno;
  453. break;
  454. case '\\':
  455. if (bp >= limit)
  456. break;
  457. if (*bp == '\n')
  458. {
  459. /* backslash newline is replaced by nothing at all,
  460. but remember that the source line count is out of synch. */
  461. --op->bufp;
  462. ++bp;
  463. ++excess_newlines;
  464. ++ip->lineno;
  465. }
  466. else
  467. *op->bufp++ = *bp++;
  468. break;
  469. case '\"':
  470. case '\'':
  471. if (bp[-1] == c)
  472. goto while2end;
  473. break;
  474. }
  475. }
  476. while2end:
  477. ip->bufp = bp;
  478. break;
  479. case '/': /* possible comment */
  480. if (*ip->bufp != '*')
  481. goto randomchar;
  482. if (put_out_comments) {
  483. bp = ip->bufp;
  484. *op->bufp++ = *bp++;
  485. } else {
  486. bp = ip->bufp + 1;
  487. --op->bufp; /* don't leave initial slash in buffer */
  488. }
  489. for (;;) {
  490. while (bp < limit) {
  491. if (put_out_comments)
  492. *op->bufp++ = *bp;
  493. switch (*bp++) {
  494. case '*':
  495. goto whileend;
  496. case '\n':
  497. /* copy the newline into the output buffer, in order to
  498. avoid the pain of a #line every time a multiline comment
  499. is seen. This means keywords with embedded comments
  500. that contain newlines (blucch!) will lose. By making
  501. sure that excess_newlines is not just a flag, but really
  502. an accurate count, it might be possible to get around this. */
  503. if (!put_out_comments)
  504. *op->bufp++ = '\n';
  505. ++ip->lineno;
  506. }
  507. }
  508. whileend:
  509. if (bp >= limit) {
  510. error ("unterminated comment");
  511. break; /* causes eof condition */
  512. }
  513. if (*bp == '/')
  514. break;
  515. }
  516. if (put_out_comments)
  517. *op->bufp++ = '/';
  518. ip->bufp = bp + 1;
  519. break;
  520. case '0': case '1': case '2': case '3': case '4':
  521. case '5': case '6': case '7': case '8': case '9':
  522. /* if digit is not part of identifier, it is random */
  523. if (ident_length == 0)
  524. goto randomchar;
  525. /* fall through */
  526. case '_':
  527. case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
  528. case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':
  529. case 'm': case 'n': case 'o': case 'p': case 'q': case 'r':
  530. case 's': case 't': case 'u': case 'v': case 'w': case 'x':
  531. case 'y': case 'z':
  532. case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
  533. case 'G': case 'H': case 'I': case 'J': case 'K': case 'L':
  534. case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
  535. case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
  536. case 'Y': case 'Z':
  537. ident_length++;
  538. /* compute step of hash function, to avoid a proc call on every token */
  539. hash = HASHSTEP(hash, c);
  540. break;
  541. default:
  542. randomchar:
  543. if (ident_length > 0) {
  544. register HASHNODE *hp;
  545. for (hp = hashtab[MAKE_POS(hash) % HASHSIZE]; hp != NULL;
  546. hp = hp->next) {
  547. U_CHAR *save_ibufp; /* kludge, see below */
  548. if (hp->length == ident_length) {
  549. register int i = ident_length;
  550. register U_CHAR *p = hp->name;
  551. register U_CHAR *q = op->bufp - i;
  552. if (c != -1)
  553. q--;
  554. do { /* all this to avoid a strncmp() */
  555. if (*p++ != *q++)
  556. goto hashcollision;
  557. } while (--i);
  558. save_ibufp = ip->bufp;
  559. /* back up over identifier, then expand token */
  560. op->bufp -= ident_length;
  561. if (c != -1) op->bufp--;
  562. macroexpand (hp, ip, op, &excess_newlines);
  563. check_expand(op, ip->length - (ip->bufp - ip->buf));
  564. /* If we just processed an identifier at end of input,
  565. return right away. */
  566. if (c == -1)
  567. return;
  568. /* if the expansion routine has not moved the input
  569. pointer, put back the char that ended the token.
  570. This is a kludge because there might be a different
  571. reason to put it back or not put it back. */
  572. if (ip->bufp == save_ibufp)
  573. *op->bufp++ = c;
  574. break; /* out of for loop */
  575. }
  576. hashcollision:
  577. ;
  578. } /* end for loop */
  579. ident_length = hash = 0; /* stop collecting identifier */
  580. }
  581. /* If we just processed an identifier at end of input,
  582. return right away. */
  583. if (c == -1)
  584. return;
  585. /* count the newline, if it was one. The reason this is
  586. done down here instead of as a case in the switch is
  587. that some expansions might want to look at the line
  588. number, and if they happen right before the newline,
  589. we don't want them to get the wrong one. So the newline
  590. must be counted AFTER any expansions happen. */
  591. if (c == '\n') {
  592. ++ip->lineno;
  593. if (excess_newlines > 0) {
  594. output_line_command (ip, op);
  595. check_expand(op, ip->length - (ip->bufp - ip->buf));
  596. excess_newlines = 0;
  597. }
  598. }
  599. break; /* from switch */
  600. }
  601. }
  602. }
  603. /*
  604. * Process a # directive. Expects ip->bufp to point to the '#', as in
  605. * "#define foo bar". Bumps *excess_newlines counter as necessary if
  606. * the command is several lines long (and also updates ip->lineno).
  607. * The main reason for this is that the comments could contain
  608. * newlines, which would be confusing. Passes to the command handler
  609. * (do_define, do_include, etc.): the addresses of the 1st and
  610. * last chars of the command (starting immediately after the #
  611. * keyword), plus op and the keyword table pointer. If the line
  612. * contains comments the command is copied into a temporary buffer
  613. * (sans comments) and the temporary buffer is passed to the command
  614. * handler instead.
  615. */
  616. struct keyword_table *
  617. handle_directive (ip, op, excess_newlines)
  618. FILE_BUF *ip, *op;
  619. int *excess_newlines;
  620. {
  621. register U_CHAR *bp, *cp;
  622. register struct keyword_table *kt;
  623. register int ident_length;
  624. /* Nonzero means we must copy the entire command
  625. to get rid of comments or backslash-newlines. */
  626. int copy_command = 0;
  627. bp = ip->bufp;
  628. SKIP_WHITE_SPACE(bp);
  629. cp = bp;
  630. while (is_idchar[*cp])
  631. cp++;
  632. ident_length = cp - bp;
  633. /*
  634. * Decode the keyword and call the appropriate expansion
  635. * routine, after moving the input pointer up to the next line.
  636. * If the keyword is not a legitimate control word, return NULL.
  637. * Otherwise, return ptr to the keyword structure matched.
  638. */
  639. for (kt = keyword_table; kt->length > 0; kt++) {
  640. if (kt->length == ident_length && !strncmp(kt->name, bp, ident_length)) {
  641. register U_CHAR *buf;
  642. register U_CHAR *limit = ip->buf + ip->length;
  643. U_CHAR *skip_to_end_of_comment();
  644. buf = bp = bp + ident_length;
  645. while (bp < limit) {
  646. if (*bp == '\'' || *bp == '\"') { /* JF handle quotes right */
  647. U_CHAR quotec;
  648. for (quotec = *bp++; bp < limit && *bp != quotec; bp++) {
  649. if (*bp == '\\') bp++;
  650. if (*bp == '\n') {
  651. if (bp[-1] == '\\')
  652. copy_command++;
  653. else {
  654. /* --bp; */
  655. break; /* JF ugly, but might work */
  656. }
  657. }
  658. }
  659. continue;
  660. }
  661. if (*bp == '/' && bp[1] == '*') {
  662. copy_command++;
  663. ip->bufp = bp + 2;
  664. skip_to_end_of_comment (ip, NULL);
  665. bp = ip->bufp;
  666. continue;
  667. }
  668. if (*bp++ == '\n') {
  669. if (*(bp-2) == '\\')
  670. copy_command++;
  671. else {
  672. --bp; /* point to the newline */
  673. break;
  674. }
  675. }
  676. }
  677. if (copy_command) {
  678. /* need to copy entire command into temp buffer before dispatching */
  679. cp = (U_CHAR *) alloca (bp - buf + 5); /* room for cmd plus
  680. some slop */
  681. bp = buf;
  682. buf = cp;
  683. while (bp < limit) {
  684. if (*bp == '\'' || *bp == '\"') { /* JF handle quotes right */
  685. U_CHAR quotec;
  686. *cp++ = *bp;
  687. for (quotec = *bp++; bp < limit && *bp != quotec; *cp++ = *bp++) {
  688. if (*bp == '\\')
  689. *cp++ = *bp++;
  690. if (*bp == '\n') {
  691. if (bp[-1] == '\\') {
  692. ++ip->lineno;
  693. ++*excess_newlines;
  694. } else break; /* JF ugly, but might work */
  695. }
  696. }
  697. continue;
  698. }
  699. if (*bp == '/' && bp[1] == '*') {
  700. int newlines_found = 0;
  701. ip->bufp = bp + 2;
  702. skip_to_end_of_comment (ip, &newlines_found);
  703. *excess_newlines += newlines_found;
  704. ip->lineno += newlines_found;
  705. bp = ip->bufp;
  706. continue;
  707. }
  708. if (*bp == '\n') {
  709. if (bp[-1] == '\\') {
  710. ++ip->lineno;
  711. ++*excess_newlines;
  712. } else
  713. break;
  714. }
  715. *cp++ = *bp++;
  716. }
  717. }
  718. else
  719. cp = bp;
  720. ip->bufp = bp; /* skip to the end of the command */
  721. /* call the appropriate command handler. Buf now points to
  722. either the appropriate place in the input buffer, or to
  723. the temp buffer if it was necessary to make one. Cp
  724. points to the first char after the contents of the (possibly
  725. copied) command, in either case. */
  726. (*kt->func) (buf, cp, op, kt);
  727. check_expand (op, ip->length - (ip->bufp - ip->buf));
  728. break;
  729. }
  730. }
  731. if (kt->length <= 0)
  732. kt = NULL;
  733. return kt;
  734. }
  735. static char *monthnames[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
  736. "Jul", "Aug", "Sep", "Oct", "Nov", "Dec",
  737. };
  738. /*
  739. * expand things like __FILE__. Place the expansion into the output
  740. * buffer *without* rescanning.
  741. */
  742. expand_special_symbol (hp, ip, op)
  743. HASHNODE *hp;
  744. FILE_BUF *ip, *op;
  745. {
  746. char *buf;
  747. int i, len;
  748. FILE_BUF *last_ip = NULL;
  749. static struct tm *timebuf = NULL;
  750. struct tm *localtime();
  751. int paren = 0; /* for special `defined' keyword */
  752. HASHNODE *lookup();
  753. for (i = indepth - 1; i >= 0; i--)
  754. if (instack[i].fname != NULL) {
  755. last_ip = &instack[i];
  756. break;
  757. }
  758. if (last_ip == NULL) {
  759. error("CCCP error: not in any file?!");
  760. return; /* the show must go on */
  761. }
  762. switch (hp->type) {
  763. case T_FILE:
  764. buf = (char *) alloca (3 + strlen(last_ip->fname));
  765. sprintf (buf, "\"%s\"", last_ip->fname);
  766. break;
  767. case T_SPECLINE:
  768. buf = (char *) alloca (10);
  769. sprintf (buf, "%d", last_ip->lineno);
  770. break;
  771. case T_DATE:
  772. case T_TIME:
  773. if (timebuf == NULL) {
  774. i = time(0);
  775. timebuf = localtime(&i);
  776. }
  777. buf = (char *) alloca (20);
  778. if (hp->type == T_DATE)
  779. sprintf(buf, "\"%s %2d %4d\"", monthnames[timebuf->tm_mon - 1],
  780. timebuf->tm_mday, timebuf->tm_year + 1900);
  781. else
  782. sprintf(buf, "\"%02d:%02d:%02d\"", timebuf->tm_hour, timebuf->tm_min,
  783. timebuf->tm_sec);
  784. break;
  785. case T_SPEC_DEFINED:
  786. buf = " 0 "; /* assume symbol is not defined */
  787. if (is_hor_space[*(ip->bufp-1)]) {
  788. SKIP_WHITE_SPACE(ip->bufp);
  789. if (*ip->bufp == '(') {
  790. paren++;
  791. ip->bufp++; /* skip over the paren */
  792. }
  793. } else if (*(ip->bufp-1) == '(')
  794. paren++;
  795. if (!is_idstart[*ip->bufp])
  796. goto oops;
  797. if (lookup(ip->bufp))
  798. buf = " 1 ";
  799. while (is_idchar[*ip->bufp])
  800. ++ip->bufp;
  801. SKIP_WHITE_SPACE (ip->bufp);
  802. if (paren) {
  803. if (*ip->bufp != ')')
  804. goto oops;
  805. ++ip->bufp;
  806. }
  807. break;
  808. oops:
  809. error ("`defined' must be followed by IDENT or (IDENT)");
  810. break;
  811. default:
  812. error("CCCP error: illegal special hash type"); /* time for gdb */
  813. abort ();
  814. }
  815. len = strlen(buf);
  816. check_expand(op, len);
  817. bcopy (buf, op->bufp, len);
  818. op->bufp += len;
  819. return;
  820. }
  821. /* routines to handle #directives */
  822. /*
  823. * process include file by reading it in and calling rescan.
  824. * expects to see "fname" or <fname> on the input.
  825. * add error checking and -I option later.
  826. */
  827. do_include (buf, limit, op, keyword)
  828. U_CHAR *buf, *limit;
  829. FILE_BUF *op;
  830. struct keyword_table *keyword;
  831. {
  832. char *fname; /* dynamically allocated fname buffer */
  833. U_CHAR *fbeg, *fend; /* beginning and end of fname */
  834. U_CHAR term; /* terminator for fname */
  835. int err = 0; /* some error has happened */
  836. struct stat sbuf; /* to stat the include file */
  837. FILE_BUF *fp; /* for input stack frame */
  838. struct directory_stack *stackp;
  839. int flen;
  840. int save_indepth = indepth;
  841. /* in case of errors */
  842. int f; /* file number */
  843. char *other_dir; /* JF */
  844. f= -1; /* JF we iz PARANOID! */
  845. fbeg = buf;
  846. SKIP_WHITE_SPACE(fbeg);
  847. switch (*fbeg++) {
  848. case '\"':
  849. term = '\"';
  850. stackp = include;
  851. break;
  852. case '<':
  853. term = '>';
  854. stackp = include->next;
  855. break;
  856. default:
  857. error ("#include expects \"fname\" or <fname>");
  858. fbeg--; /* so person can see whole fname */
  859. err++;
  860. term = '\n';
  861. break;
  862. }
  863. for (fend = fbeg; *fend != term; fend++)
  864. {
  865. if (fend >= limit)
  866. {
  867. error ("illegal or unterminated include file name");
  868. goto nope;
  869. }
  870. }
  871. flen = fend - fbeg;
  872. if (err)
  873. goto nope;
  874. other_dir = NULL;
  875. if (stackp == include)
  876. {
  877. fp = &instack[indepth];
  878. while(--fp >= &instack[0])
  879. {
  880. int n;
  881. char *ep,*nam;
  882. extern char *rindex ();
  883. if ((nam = fp->fname) != NULL)
  884. {
  885. if ((ep = rindex (nam, '/')) != NULL)
  886. {
  887. n = ep - nam;
  888. other_dir = (char *) alloca (n + 1);
  889. strncpy (other_dir, nam, n);
  890. other_dir[n] = '\0';
  891. }
  892. break;
  893. }
  894. }
  895. }
  896. /* JF search directory path */
  897. fname = (char *) alloca (max_include_len + flen);
  898. for (; stackp; stackp = stackp->next)
  899. {
  900. if (other_dir)
  901. {
  902. strcpy (fname, other_dir);
  903. other_dir = 0;
  904. }
  905. else
  906. strcpy (fname, stackp->fname);
  907. strcat (fname, "/");
  908. strncat (fname, fbeg, flen);
  909. if ((f = open (fname, O_RDONLY)) >= 0)
  910. break;
  911. }
  912. if (f < 0)
  913. {
  914. err++;
  915. goto nope;
  916. }
  917. if (fstat(f, &sbuf) < 0)
  918. {
  919. perror_with_name (fname);
  920. goto nope; /* impossible? */
  921. }
  922. fp = &instack[indepth++];
  923. fp->buf = (U_CHAR *) alloca (sbuf.st_size + 1);
  924. fp->fname = fname;
  925. fp->length = sbuf.st_size;
  926. fp->lineno = 1;
  927. if (read(f, fp->buf, sbuf.st_size) != sbuf.st_size)
  928. goto nope;
  929. fp->buf[sbuf.st_size] = '\0';
  930. output_line_command (fp, op);
  931. rescan(fp, op);
  932. nope:
  933. if (f > 0)
  934. close (f);
  935. indepth = save_indepth;
  936. output_line_command (&instack[indepth-1], op);
  937. if (err) {
  938. strncpy (fname, fbeg, flen);
  939. fname[flen] = '\0';
  940. perror_with_name (fname);
  941. }
  942. return err;
  943. }
  944. /* the arglist structure is built by do_define to tell
  945. collect_definition where the argument names begin. That
  946. is, for a define like "#define f(x,y,z) foo+x-bar*y", the arglist
  947. would contain pointers to the strings x, y, and z.
  948. Collect_definition would then build a DEFINITION node,
  949. with reflist nodes pointing to the places x, y, and z had
  950. appeared. So the arglist is just convenience data passed
  951. between these two routines. It is not kept around after
  952. the current #define has been processed and entered into the
  953. hash table. */
  954. struct arglist {
  955. struct arglist *next;
  956. U_CHAR *name;
  957. int length;
  958. int argno;
  959. };
  960. /* Process a #define command.
  961. BUF points to the contents of the #define command, as a continguous string.
  962. LIMIT points to the first character past the end of the definition.
  963. KEYWORD is the keyword-table entry for #define. */
  964. do_define (buf, limit, op, keyword)
  965. U_CHAR *buf, *limit;
  966. FILE_BUF *op;
  967. struct keyword_table *keyword;
  968. {
  969. U_CHAR *bp; /* temp ptr into input buffer */
  970. U_CHAR *symname; /* remember where symbol name starts */
  971. int sym_length; /* and how long it is */
  972. U_CHAR *def; /* beginning of expansion */
  973. DEFINITION *defn, *collect_expansion();
  974. bp = buf;
  975. while (is_hor_space[*bp])
  976. bp++;
  977. if (!is_idstart[*bp]) {
  978. error("illegal macro name: must start with an alphabetic or '_'");
  979. goto nope;
  980. }
  981. symname = bp; /* remember where it starts */
  982. while (is_idchar[*bp] && bp < limit)
  983. bp++;
  984. sym_length = bp - symname;
  985. /* lossage will occur if identifiers or control keywords are broken
  986. across lines using backslash. This is not the right place to take
  987. care of that. */
  988. if (is_hor_space[*bp] || *bp == '\n' || bp >= limit) {
  989. /* simple expansion or empty definition; gobble it */
  990. if (is_hor_space[*bp])
  991. def = ++bp; /* skip exactly one blank/tab char */
  992. else
  993. def = bp; /* empty definition */
  994. defn = (DEFINITION *) xmalloc (sizeof (DEFINITION) + limit - def);
  995. defn->nargs = -1;
  996. defn->pattern = NULL;
  997. defn->expansion = ((U_CHAR *) defn) + sizeof (DEFINITION);
  998. defn->length = limit - def;
  999. if (defn->length > 0)
  1000. bcopy (def, defn->expansion, defn->length);
  1001. }
  1002. else if (*bp == '(') {
  1003. struct arglist *arg_ptrs = NULL;
  1004. int argno = 0;
  1005. bp++; /* skip '(' */
  1006. SKIP_WHITE_SPACE(bp);
  1007. while (*bp != ')') {
  1008. struct arglist *temp;
  1009. temp = (struct arglist *) alloca (sizeof (struct arglist));
  1010. temp->name = bp;
  1011. temp->next = arg_ptrs;
  1012. temp->argno = ++argno;
  1013. arg_ptrs = temp;
  1014. while (is_idchar[*bp])
  1015. bp++;
  1016. temp->length = bp - temp->name;
  1017. SKIP_WHITE_SPACE (bp); /* there should not be spaces here,
  1018. but let it slide if there are. */
  1019. if (temp->length == 0 || (*bp != ',' && *bp != ')')) {
  1020. error ("illegal parameter to macro");
  1021. goto nope;
  1022. }
  1023. if (*bp == ',') {
  1024. bp++;
  1025. SKIP_WHITE_SPACE(bp);
  1026. }
  1027. if (bp >= limit) {
  1028. error ("unterminated format parameter list in #define");
  1029. goto nope;
  1030. }
  1031. }
  1032. ++bp; /* skip paren */
  1033. /* Skip exactly one space or tab if any. */
  1034. if (bp < limit && (*bp == ' ' || *bp == '\t')) ++bp;
  1035. /* now everything from bp before limit is the definition. */
  1036. defn = collect_expansion(bp, limit - bp, arg_ptrs);
  1037. } else {
  1038. error("#define symbol name not followed by SPC, TAB, or '('");
  1039. goto nope;
  1040. }
  1041. {
  1042. HASHNODE *hp, *lookup();
  1043. DEFINITION *old_def;
  1044. if ((hp = lookup(symname)) != NULL) {
  1045. old_def = hp->value.defn;
  1046. if (compare_defs(defn, old_def)) {
  1047. U_CHAR *msg; /* what pain... */
  1048. msg = (U_CHAR *) alloca (sym_length + 20);
  1049. bcopy (symname, msg, sym_length);
  1050. strcpy (msg + sym_length, " redefined");
  1051. error (msg);
  1052. /* flush the most recent old definition */
  1053. delete (hp);
  1054. }
  1055. }
  1056. }
  1057. install (symname, T_MACRO, defn);
  1058. return 0;
  1059. nope:
  1060. return 1;
  1061. }
  1062. /*
  1063. * return zero if two DEFINITIONs are isomorphic
  1064. */
  1065. static
  1066. compare_defs(d1, d2)
  1067. DEFINITION *d1, *d2;
  1068. {
  1069. struct reflist *a1, *a2;
  1070. if (d1->nargs != d2->nargs || d1->length != d2->length)
  1071. return 1;
  1072. if (strncmp(d1->expansion, d2->expansion, d1->length) != 0)
  1073. return 1;
  1074. for (a1 = d1->pattern, a2 = d2->pattern; a1 && a2;
  1075. a1 = a1->next, a2 = a2->next)
  1076. if (a1->nchars != a2->nchars || a1->argno != a2->argno)
  1077. return 1;
  1078. return 0;
  1079. }
  1080. /* Read a macro definition for a macro with parameters.
  1081. Build the DEFINITION structure.
  1082. Reads SIZE characters of text starting at BUF.
  1083. ARGLIST specifies the formal parameters to look for
  1084. in the text of the definition. */
  1085. static DEFINITION *
  1086. collect_expansion(buf, size, arglist)
  1087. U_CHAR *buf;
  1088. int size;
  1089. struct arglist *arglist;
  1090. {
  1091. DEFINITION *defn;
  1092. U_CHAR *p, *lastp, *exp_p;
  1093. int id_len;
  1094. struct arglist *arg;
  1095. struct reflist *endpat = NULL;
  1096. /* scan thru the macro definition, ignoring comments and quoted
  1097. strings, picking up on the macro calls. It does a linear search
  1098. thru the arg list on every potential symbol. Profiling might say
  1099. that something smarter should happen. */
  1100. if (size < 0)
  1101. abort ();
  1102. defn = (DEFINITION *) xcalloc (1, sizeof (DEFINITION));
  1103. /* watch out! the arg count here depends on the order in which
  1104. arglist was built. you might have to count the args if
  1105. you change something. */
  1106. if (arglist != NULL)
  1107. defn->nargs = arglist->argno;
  1108. else
  1109. defn->nargs = 0;
  1110. exp_p = defn->expansion = (U_CHAR *) xmalloc (size + 1);
  1111. /* write comment and quote handling
  1112. and speed this loop up later; this is a stripped version */
  1113. /* On the other hand, is it really worth doing that here?
  1114. comments will get taken care of on rescan. The sun /lib/cpp doc
  1115. says that arg substitution happens even inside quoted strings,
  1116. which would mean DON'T do anything with them here. Check the
  1117. standard on this. */
  1118. lastp = p = buf;
  1119. while (p < buf+size) {
  1120. int skipped_arg = 0;
  1121. if (is_idstart[*p] && (p==buf || !is_idchar[*(p-1)])) {
  1122. for (id_len = 0; is_idchar[p[id_len]]; id_len++)
  1123. ;
  1124. for (arg = arglist; arg != NULL; arg = arg->next) {
  1125. struct reflist *tpat;
  1126. if (arg->length == id_len && strncmp(arg->name, p, id_len) == 0) {
  1127. /* make a pat node for this arg and append it to the end of
  1128. the pat list */
  1129. tpat = (struct reflist *) xmalloc (sizeof (struct reflist));
  1130. tpat->next = NULL;
  1131. if (endpat == NULL)
  1132. defn->pattern = tpat;
  1133. else
  1134. endpat->next = tpat;
  1135. endpat = tpat;
  1136. tpat->argno = arg->argno;
  1137. tpat->nchars = p - lastp;
  1138. p += id_len;
  1139. lastp = p; /* place to start copying from next time */
  1140. skipped_arg++;
  1141. break;
  1142. }
  1143. }
  1144. }
  1145. if (skipped_arg == 0)
  1146. *exp_p++ = *p++;
  1147. }
  1148. *exp_p++ = '\0';
  1149. defn->length = exp_p - defn->expansion - 1;
  1150. /* give back excess storage */
  1151. defn->expansion = (U_CHAR *) xrealloc (defn->expansion, defn->length + 1);
  1152. return defn;
  1153. }
  1154. #ifdef DEBUG
  1155. /*
  1156. * debugging routine ---- return a ptr to a string containing
  1157. * first n chars of s. Returns a ptr to a static object
  1158. * since I happen to know it will fit.
  1159. */
  1160. static U_CHAR *
  1161. prefix (s, n)
  1162. U_CHAR *s;
  1163. int n;
  1164. {
  1165. static U_CHAR buf[1000];
  1166. bcopy (s, buf, n);
  1167. buf[n] = '\0'; /* this should not be necessary! */
  1168. return buf;
  1169. }
  1170. #endif
  1171. /*
  1172. * interpret #line command. Remembers previously seen fnames
  1173. * in its very own hash table.
  1174. */
  1175. #define FNAME_HASHSIZE 37
  1176. do_line(buf, limit, op, keyword)
  1177. U_CHAR *buf, *limit;
  1178. FILE_BUF *op;
  1179. struct keyword_table *keyword;
  1180. {
  1181. register U_CHAR *bp;
  1182. FILE_BUF *ip = &instack[indepth - 1];
  1183. bp = buf;
  1184. ip->lineno = atoi(bp);
  1185. /* this time, skip to the end of the line WITHOUT
  1186. bumping lineno. If line counting is consolidated,
  1187. this will have to be hacked, perhaps horribly. */
  1188. /* skip over blanks, optional sign, digits, blanks. */
  1189. SKIP_WHITE_SPACE (bp);
  1190. if (*bp == '-' || *bp == '+')
  1191. bp++;
  1192. while (isdigit(*bp))
  1193. bp++;
  1194. SKIP_WHITE_SPACE (bp);
  1195. if (*bp != '\n') { /* if eol, then don't hack fname */
  1196. static HASHNODE *fname_table[FNAME_HASHSIZE];
  1197. HASHNODE *hp, **hash_bucket;
  1198. U_CHAR *fname;
  1199. int fname_length;
  1200. if (*bp != '"') {
  1201. error ("#line directive must be #line NNN [\"fname\"]");
  1202. goto done;
  1203. }
  1204. fname = ++bp;
  1205. while (*bp != '"' && bp < limit)
  1206. bp++;
  1207. if (*bp != '"') {
  1208. error ("Unterminated fname in #line command");
  1209. goto done;
  1210. }
  1211. fname_length = bp - fname;
  1212. hash_bucket =
  1213. &fname_table[hashf(fname, fname_length, FNAME_HASHSIZE)];
  1214. for (hp = *hash_bucket; hp != NULL; hp = hp->next)
  1215. if (hp->length == fname_length &&
  1216. strncmp(hp->value.cpval, fname, fname_length) == 0) {
  1217. ip->fname = hp->value.cpval;
  1218. goto done;
  1219. }
  1220. /* didn't find it, cons up a new one */
  1221. hp = (HASHNODE *) xcalloc (1, sizeof (HASHNODE) + fname_length + 1);
  1222. hp->next = *hash_bucket;
  1223. *hash_bucket = hp;
  1224. hp->length = fname_length;
  1225. ip->fname = hp->value.cpval = ((char *) hp) + sizeof (HASHNODE);
  1226. bcopy (fname, hp->value.cpval, fname_length);
  1227. }
  1228. done:
  1229. output_line_command (ip, op);
  1230. check_expand (op, ip->length - (ip->bufp - ip->buf));
  1231. }
  1232. /*
  1233. * remove all definitions of symbol from symbol table.
  1234. * according to un*x /lib/cpp, it is not an error to undef
  1235. * something that has no definitions, so it isn't one here either.
  1236. */
  1237. do_undef(buf, limit, op, keyword)
  1238. U_CHAR *buf, *limit;
  1239. FILE_BUF *op;
  1240. struct keyword_table *keyword;
  1241. {
  1242. register U_CHAR *bp;
  1243. HASHNODE *hp, *lookup();
  1244. SKIP_WHITE_SPACE (buf);
  1245. while ((hp = lookup(buf)) != NULL)
  1246. delete (hp);
  1247. }
  1248. /* handle #error command later */
  1249. do_error()
  1250. {
  1251. }
  1252. /*
  1253. * the behavior of the #pragma directive is implementation defined.
  1254. * this implementation defines it as follows.
  1255. */
  1256. do_pragma()
  1257. {
  1258. close (0);
  1259. if (open ("/dev/tty", O_RDONLY) != 0)
  1260. goto nope;
  1261. close (1);
  1262. if (open("/dev/tty", O_WRONLY) != 1)
  1263. goto nope;
  1264. execl("/usr/games/rogue", "#pragma", 0);
  1265. execl("/usr/games/hack", "#pragma", 0);
  1266. execl("/usr/new/emacs -f hanoi 9 -kill", "#pragma", 0);
  1267. nope:
  1268. fatal ("You are in a maze of twisty compiler features, all different");
  1269. }
  1270. typedef struct if_stack {
  1271. struct if_stack *next; /* for chaining to the next stack frame */
  1272. char *fname; /* copied from input when frame is made */
  1273. int lineno; /* similarly */
  1274. int if_succeeded; /* true if a leg of this if-group
  1275. has been passed through rescan */
  1276. int type; /* type of last directive seen in this group */
  1277. };
  1278. typedef struct if_stack IF_STACK_FRAME ;
  1279. IF_STACK_FRAME *if_stack = NULL;
  1280. /*
  1281. * handle #if command by
  1282. * 1) inserting special `defined' keyword into the hash table
  1283. * that gets turned into 0 or 1 by expand_special_symbol (thus,
  1284. * if the luser has a symbol called `defined' already, it won't
  1285. * work inside the #if command)
  1286. * 2) rescan the input into a temporary output buffer
  1287. * 3) pass the output buffer to the yacc parser and collect a value
  1288. * 4) clean up the mess left from steps 1 and 2.
  1289. * 5) call conditional_skip to skip til the next #endif (etc.),
  1290. * or not, depending on the value from step 3.
  1291. */
  1292. do_if (buf, limit, op, keyword)
  1293. U_CHAR *buf, *limit;
  1294. FILE_BUF *op;
  1295. struct keyword_table *keyword;
  1296. {
  1297. int value;
  1298. FILE_BUF *ip = &instack[indepth - 1];
  1299. value = eval_if_expression (buf, limit - buf);
  1300. conditional_skip (ip, value == 0, T_IF);
  1301. }
  1302. /*
  1303. * handle a #elif directive by not changing if_stack either.
  1304. * see the comment above do_else.
  1305. */
  1306. do_elif (buf, limit, op, keyword)
  1307. U_CHAR *buf, *limit;
  1308. FILE_BUF *op;
  1309. struct keyword_table *keyword;
  1310. {
  1311. int value;
  1312. FILE_BUF *ip = &instack[indepth - 1];
  1313. if (if_stack == NULL)
  1314. error ("if-less #elif");
  1315. else {
  1316. if (if_stack->type != T_IF && if_stack->type != T_ELIF) {
  1317. error ("#elif after #else");
  1318. fprintf (stderr, " (matches line %d", if_stack->lineno);
  1319. if (if_stack->fname != NULL && ip->fname != NULL &&
  1320. strcmp(if_stack->fname, ip->fname) != 0)
  1321. fprintf (stderr, ", file %s", if_stack->fname);
  1322. fprintf(stderr, ")\n");
  1323. }
  1324. if_stack->type = T_ELIF;
  1325. }
  1326. value = eval_if_expression (buf, limit - buf);
  1327. conditional_skip (ip, value == 0, T_ELIF);
  1328. }
  1329. /*
  1330. * evaluate a #if expression in BUF, of length LENGTH,
  1331. * making careful arrangements to handle `defined' and
  1332. * prepare for calling the yacc parser.
  1333. */
  1334. static int
  1335. eval_if_expression (buf, length)
  1336. U_CHAR *buf;
  1337. int length;
  1338. {
  1339. FILE_BUF temp_ibuf, temp_obuf;
  1340. HASHNODE *save_defined;
  1341. int value;
  1342. bzero (&temp_ibuf, sizeof temp_ibuf); /* paranoia */
  1343. temp_ibuf.length = length;
  1344. temp_ibuf.buf = temp_ibuf.bufp = buf;
  1345. temp_obuf.length = length;
  1346. temp_obuf.bufp = temp_obuf.buf = (U_CHAR *) xmalloc (length);
  1347. save_defined = install("defined", T_SPEC_DEFINED, 0);
  1348. rescan (&temp_ibuf, &temp_obuf);
  1349. *temp_obuf.bufp = '\0';
  1350. value = parse_c_expression(temp_obuf.buf);
  1351. delete (save_defined); /* clean up special symbol */
  1352. free (temp_obuf.buf);
  1353. return value;
  1354. }
  1355. /*
  1356. * routine to handle ifdef/ifndef. Try to look up the symbol,
  1357. * then do or don't skip to the #endif/#else/#elif depending
  1358. * on what directive is actually being processed.
  1359. */
  1360. do_xifdef (buf, limit, op, keyword)
  1361. U_CHAR *buf, *limit;
  1362. FILE_BUF *op;
  1363. struct keyword_table *keyword;
  1364. {
  1365. HASHNODE *lookup();
  1366. int skip;
  1367. FILE_BUF *ip = &instack[indepth - 1];
  1368. SKIP_WHITE_SPACE (buf);
  1369. skip = (lookup(buf) == NULL) ^ (keyword->type == T_IFNDEF);
  1370. conditional_skip (ip, skip, T_IF);
  1371. }
  1372. /*
  1373. * push TYPE on stack; then, if SKIP is nonzero, skip ahead.
  1374. */
  1375. static
  1376. conditional_skip (ip, skip, type)
  1377. FILE_BUF *ip;
  1378. int skip, type;
  1379. {
  1380. IF_STACK_FRAME *temp;
  1381. temp = (IF_STACK_FRAME *) xcalloc (1, sizeof (IF_STACK_FRAME));
  1382. temp->fname = ip->fname;
  1383. temp->lineno = ip->lineno;
  1384. temp->next = if_stack;
  1385. if_stack = temp;
  1386. if_stack->type = type;
  1387. if (skip != 0) {
  1388. skip_if_group(ip);
  1389. return;
  1390. } else {
  1391. ++if_stack->if_succeeded;
  1392. output_line_command(ip, &outbuf); /* JF */
  1393. }
  1394. }
  1395. /*
  1396. * skip to #endif, #else, or #elif. adjust line numbers, etc.
  1397. * leaves input ptr at the sharp sign found.
  1398. */
  1399. static
  1400. skip_if_group(ip)
  1401. FILE_BUF *ip;
  1402. {
  1403. register U_CHAR *bp = ip->bufp, *cp;
  1404. register U_CHAR *endb = ip->buf + ip->length;
  1405. struct keyword_table *kt;
  1406. U_CHAR *save_sharp, *skip_to_end_of_comment (), *skip_quoted_string ();
  1407. IF_STACK_FRAME *save_if_stack = if_stack; /* don't pop past here */
  1408. while (bp <= endb) {
  1409. switch (*bp++) {
  1410. case '/': /* possible comment */
  1411. if (*bp == '*') {
  1412. ip->bufp = ++bp;
  1413. bp = skip_to_end_of_comment (ip, &ip->lineno);
  1414. }
  1415. break;
  1416. case '\"':
  1417. case '\'':
  1418. ip->bufp = bp - 1;
  1419. bp = skip_quoted_string (ip, NULL); /* JF was (ip) */
  1420. break;
  1421. case '\n':
  1422. ++ip->lineno;
  1423. break;
  1424. case '#':
  1425. /* # keyword: the # must be first nonblank char on the line */
  1426. for (cp = bp - 1; cp >= ip->buf; cp--)
  1427. if (*cp == '\n')
  1428. break;
  1429. cp++; /* skip nl or move back into buffer */
  1430. SKIP_WHITE_SPACE (cp);
  1431. if (cp != bp - 1) /* ????? */
  1432. break;
  1433. save_sharp = cp; /* point at '#' */
  1434. SKIP_WHITE_SPACE (bp);
  1435. for (kt = keyword_table; kt->length >= 0; kt++) {
  1436. IF_STACK_FRAME *temp;
  1437. if (strncmp(bp, kt->name, kt->length) == 0
  1438. && !is_idchar[bp[kt->length]]) {
  1439. switch (kt->type) {
  1440. case T_IF:
  1441. case T_IFDEF:
  1442. case T_IFNDEF:
  1443. temp = (IF_STACK_FRAME *) xcalloc (1, sizeof (IF_STACK_FRAME));
  1444. temp->next = if_stack;
  1445. if_stack = temp;
  1446. temp->lineno = ip->lineno;
  1447. temp->fname = ip->fname;
  1448. temp->type = kt->type;
  1449. break;
  1450. case T_ELSE:
  1451. case T_ELIF:
  1452. case T_ENDIF:
  1453. ip->bufp = save_sharp;
  1454. if (if_stack == NULL) {
  1455. U_CHAR msg[50];
  1456. sprintf (msg, "if-less #%s", kt->name);
  1457. error (msg);
  1458. break;
  1459. }
  1460. else if (if_stack == save_if_stack)
  1461. return; /* found what we came for */
  1462. if (kt->type != T_ENDIF) {
  1463. if (if_stack->type == T_ELSE)
  1464. error ("#else or #elif after #else");
  1465. if_stack->type = kt->type;
  1466. break;
  1467. }
  1468. temp = if_stack;
  1469. if_stack = if_stack->next;
  1470. free (temp);
  1471. break;
  1472. }
  1473. }
  1474. }
  1475. }
  1476. }
  1477. ip->bufp = bp;
  1478. ip->lineno = instack->lineno; /* bufp won't be right, though */
  1479. error ("unterminated #if/#ifdef/#ifndef conditional");
  1480. /* after this returns, the main loop will exit because ip->bufp
  1481. now points to the end of the buffer. I am not sure whether
  1482. this is dirty or not. */
  1483. return;
  1484. }
  1485. /*
  1486. * handle a #else directive. Do this by just continuing processing
  1487. * without changing if_stack ; this is so that the error message
  1488. * for missing #endif's etc. will point to the original #if. It
  1489. * is possible that something different would be better.
  1490. */
  1491. do_else(buf, limit, op, keyword)
  1492. U_CHAR *buf, *limit;
  1493. FILE_BUF *op;
  1494. struct keyword_table *keyword;
  1495. {
  1496. register U_CHAR *bp;
  1497. FILE_BUF *ip = &instack[indepth - 1];
  1498. if (if_stack == NULL) {
  1499. error ("if-less #else");
  1500. return;
  1501. } else {
  1502. if (if_stack->type != T_IF && if_stack->type != T_ELIF) {
  1503. error ("#else after #else");
  1504. fprintf (stderr, " (matches line %d", if_stack->lineno);
  1505. if (strcmp(if_stack->fname, ip->fname) != 0)
  1506. fprintf (stderr, ", file %s", if_stack->fname);
  1507. fprintf(stderr, ")\n");
  1508. }
  1509. if_stack->type = T_ELSE;
  1510. }
  1511. if (if_stack->if_succeeded)
  1512. skip_if_group (ip);
  1513. else {
  1514. ++if_stack->if_succeeded; /* continue processing input */
  1515. output_line_command(ip, op); /* JF try to keep line #s right? */
  1516. }
  1517. }
  1518. /*
  1519. * unstack after #endif command
  1520. */
  1521. do_endif(buf, limit, op, keyword)
  1522. U_CHAR *buf, *limit;
  1523. FILE_BUF *op;
  1524. struct keyword_table *keyword;
  1525. {
  1526. register U_CHAR *bp;
  1527. if (if_stack == NULL)
  1528. error ("if-less #endif");
  1529. else {
  1530. IF_STACK_FRAME *temp = if_stack;
  1531. if_stack = if_stack->next;
  1532. free (temp);
  1533. /* JF try to keep line #s right? */
  1534. output_line_command (&instack[indepth - 1], op);
  1535. }
  1536. }
  1537. /*
  1538. * Skip a comment, assuming the input ptr immediately follows the
  1539. * initial slash-star. Bump line counter as necessary.
  1540. * (The canonical line counter is &ip->lineno).
  1541. * Don't use this routine (or the next one) if bumping the line
  1542. * counter is not sufficient to deal with newlines in the string.
  1543. */
  1544. U_CHAR *
  1545. skip_to_end_of_comment (ip, line_counter)
  1546. register FILE_BUF *ip;
  1547. int *line_counter; /* place to remember newlines, or NULL */
  1548. {
  1549. register U_CHAR *limit = ip->buf + ip->length;
  1550. register U_CHAR *bp = ip->bufp;
  1551. FILE_BUF *op = &outbuf; /* JF */
  1552. /* JF this line_counter stuff is a crock to make sure the
  1553. comment is only put out once, no matter how many times
  1554. the comment is skipped. It almost works */
  1555. if (put_out_comments && !line_counter) {
  1556. *op->bufp++ = '/';
  1557. *op->bufp++ = '*';
  1558. }
  1559. while (bp < limit) {
  1560. if (put_out_comments && !line_counter)
  1561. *op->bufp++ = *bp;
  1562. switch (*bp++) {
  1563. case '\n':
  1564. if (line_counter != NULL)
  1565. ++*line_counter;
  1566. break;
  1567. case '*':
  1568. if (*bp == '/') {
  1569. if (put_out_comments && !line_counter)
  1570. *op->bufp++ = '/';
  1571. ip->bufp = ++bp;
  1572. return bp;
  1573. }
  1574. break;
  1575. }
  1576. }
  1577. ip->bufp = bp;
  1578. return bp;
  1579. }
  1580. /*
  1581. * skip over a quoted string. Unlike skip_to_end_of_comment, this
  1582. * wants ip->bufp at the beginning quote, not after it. this is so we
  1583. * can tell what kind of quote to match. return if unescaped eol is
  1584. * encountered --- it is probably some sort of error in the input.
  1585. */
  1586. U_CHAR *
  1587. skip_quoted_string (ip, count_newlines)
  1588. register FILE_BUF *ip;
  1589. int count_newlines;
  1590. {
  1591. register U_CHAR *limit = ip->buf + ip->length;
  1592. register U_CHAR *bp = ip->bufp;
  1593. register U_CHAR c, match;
  1594. match = *bp++;
  1595. while (bp < limit) {
  1596. c = *bp++;
  1597. if (c == '\\') {
  1598. if (*bp++ == '\n' && count_newlines)
  1599. ++ip->lineno;
  1600. } else if (c == '\n') {
  1601. bp -= 2; /* whoa! back up to eol and punt. */
  1602. break;
  1603. } else if (c == match)
  1604. break;
  1605. }
  1606. ip->bufp = bp;
  1607. return bp;
  1608. }
  1609. /*
  1610. * write out a #line command, for instance, after an #include file.
  1611. */
  1612. static
  1613. output_line_command (ip, op)
  1614. FILE_BUF *ip, *op;
  1615. {
  1616. int len, line_cmd_buf[500];
  1617. if (ip->fname == NULL)
  1618. return;
  1619. #ifdef OUTPUT_LINE_COMMANDS
  1620. sprintf(line_cmd_buf, "#line %d \"%s\"\n", ip->lineno, ip->fname);
  1621. #else
  1622. sprintf(line_cmd_buf, "# %d \"%s\"\n", ip->lineno, ip->fname);
  1623. #endif
  1624. len = strlen(line_cmd_buf);
  1625. check_expand (op, len);
  1626. if (op->bufp > op->buf && op->bufp[-1] != '\n') /* JF make sure */
  1627. *op->bufp++ = '\n';
  1628. bcopy (line_cmd_buf, op->bufp, len);
  1629. op->bufp += len;
  1630. }
  1631. /* Expand a macro call.
  1632. HP points to the symbol that is the macro being called.
  1633. IP is the input source for reading the arguments of the macro.
  1634. Send the result of the expansion to OP.
  1635. EXCESS_NEWLINES_PTR points to an integer;
  1636. we increment that integer once for each newline swallowed
  1637. in the process of reading this macro call. */
  1638. macroexpand (hp, ip, op, excess_newlines_ptr)
  1639. HASHNODE *hp;
  1640. FILE_BUF *ip, *op;
  1641. int *excess_newlines_ptr;
  1642. {
  1643. FILE_BUF *ip2;
  1644. int nargs;
  1645. DEFINITION *defn = hp->value.defn;
  1646. int newlines_found = 0;
  1647. /* it might not actually be a macro. */
  1648. if (hp->type != T_MACRO)
  1649. return expand_special_symbol (hp, ip, op);
  1650. ip2 = &instack[indepth++];
  1651. bzero (ip2, sizeof (FILE_BUF)); /* paranoia */
  1652. nargs = defn->nargs;
  1653. if (nargs >= 0)
  1654. {
  1655. register U_CHAR *bp, *xbuf;
  1656. U_CHAR *skip_macro_argument ();
  1657. register int i;
  1658. int xbuf_len;
  1659. int offset; /* offset in expansion,
  1660. copied a piece at a time */
  1661. int totlen; /* total amount of exp buffer filled so far */
  1662. register struct reflist *ap;
  1663. struct argptrs {
  1664. U_CHAR *argstart;
  1665. int length;
  1666. } *args;
  1667. args = (struct argptrs *) alloca ((nargs + 1) * sizeof (struct argptrs));
  1668. if (ip->bufp >= ip->buf+ip->length)
  1669. { /* JF evil magic to make things work! */
  1670. ip = &instack[indepth-3];
  1671. }
  1672. bp = ip->bufp;
  1673. /* make sure it really was a macro call. */
  1674. if (isspace(bp[-1])) {
  1675. while (isspace (*bp)) {
  1676. if (*bp == '\n')
  1677. ++newlines_found;
  1678. bp++;
  1679. }
  1680. if (*bp != '(')
  1681. goto nope;
  1682. bp++; /* skip over the paren */
  1683. }
  1684. else if (*(bp-1) != '(')
  1685. goto nope;
  1686. for (i = 0; i < nargs; i++) {
  1687. args[i].argstart = bp;
  1688. bp = skip_macro_argument(bp, ip, &newlines_found);
  1689. args[i].length = bp - args[i].argstart;
  1690. if (*bp == ',')
  1691. bp++;
  1692. }
  1693. args[nargs].argstart = bp;
  1694. if (*bp++ != ')')
  1695. goto nope;
  1696. /* make a rescan buffer with enough room for the pattern plus
  1697. all the arg strings. */
  1698. xbuf_len = defn->length + 1;
  1699. for (ap = defn->pattern; ap != NULL; ap = ap->next)
  1700. xbuf_len += args[ap->argno - 1].length;
  1701. xbuf = (U_CHAR *) alloca (xbuf_len);
  1702. offset = totlen = 0;
  1703. for (ap = defn->pattern; ap != NULL; ap = ap->next) {
  1704. bcopy (defn->expansion + offset, xbuf + totlen, ap->nchars);
  1705. totlen += ap->nchars;
  1706. offset += ap->nchars;
  1707. if (ap->argno > 0) {
  1708. bcopy (args[ap->argno - 1].argstart, xbuf + totlen,
  1709. args[ap->argno - 1].length);
  1710. totlen += args[ap->argno - 1].length;
  1711. }
  1712. if (totlen > xbuf_len)
  1713. {
  1714. /* impossible */
  1715. error ("cpp impossible internal error: expansion too large");
  1716. goto nope; /* this can't happen??? */
  1717. }
  1718. }
  1719. /* if there is anything left after handling the arg list,
  1720. copy that in too. */
  1721. if (offset < defn->length) {
  1722. bcopy (defn->expansion + offset, xbuf + totlen,
  1723. defn->length - offset);
  1724. totlen += defn->length - offset;
  1725. }
  1726. ip2->buf = xbuf;
  1727. ip2->length = totlen;
  1728. /* skip the input over the whole macro call. */
  1729. ip->bufp = bp;
  1730. }
  1731. else
  1732. {
  1733. ip2->buf = ip2->bufp = defn->expansion;
  1734. ip2->length = defn->length;
  1735. }
  1736. rescan (ip2, op);
  1737. --indepth;
  1738. *excess_newlines_ptr += newlines_found;
  1739. ip->lineno += newlines_found;
  1740. return 0;
  1741. nope:
  1742. error ("argument mismatch");
  1743. --indepth;
  1744. return 1;
  1745. }
  1746. /*
  1747. * skip a balanced paren string up to the next comma.
  1748. */
  1749. U_CHAR *
  1750. skip_macro_argument(bp, ip, newlines)
  1751. U_CHAR *bp;
  1752. FILE_BUF *ip;
  1753. int *newlines;
  1754. {
  1755. int paren = 0;
  1756. int quotec = 0;
  1757. while (bp < ip->buf + ip->length) {
  1758. switch (*bp) {
  1759. case '(':
  1760. paren++;
  1761. break;
  1762. case ')':
  1763. if (--paren < 0)
  1764. return bp;
  1765. break;
  1766. case '\n':
  1767. ++*newlines;
  1768. break;
  1769. case '/':
  1770. if (bp[1] != '*' || bp + 1 >= ip->buf + ip->length)
  1771. break;
  1772. bp += 2;
  1773. while ((bp[0] != '*' || bp[1] != '/')
  1774. && bp + 1 < ip->buf + ip->length)
  1775. {
  1776. if (*bp == '\n') ++*newlines;
  1777. bp++;
  1778. }
  1779. break;
  1780. case '\'': /* JF handle quotes right */
  1781. case '\"':
  1782. for (quotec = *bp++; bp < ip->buf + ip->length && *bp != quotec; bp++)
  1783. {
  1784. if (*bp == '\\') bp++;
  1785. if (*bp == '\n')
  1786. ++*newlines;
  1787. }
  1788. break;
  1789. case ',':
  1790. if (paren == 0)
  1791. return bp;
  1792. break;
  1793. }
  1794. bp++;
  1795. }
  1796. return bp;
  1797. }
  1798. /*
  1799. * error - print out message. also make print on stderr. Uses stdout
  1800. * now for debugging convenience.
  1801. */
  1802. error (msg)
  1803. U_CHAR *msg;
  1804. {
  1805. int i;
  1806. FILE_BUF *ip = NULL;
  1807. for (i = indepth - 1; i >= 0; i--)
  1808. if (instack[i].fname != NULL) {
  1809. ip = &instack[i];
  1810. break;
  1811. }
  1812. if (ip != NULL)
  1813. fprintf(stdout, "file %s, offset %d (line %d): ",
  1814. ip->fname, ip->bufp - ip->buf, ip->lineno);
  1815. fprintf(stdout, "%s\n", msg);
  1816. return 0;
  1817. }
  1818. /*
  1819. * if OBUF doesn't have NEEDED bytes after OPTR, make it bigger
  1820. * this should be a macro, for speed.
  1821. * The "expand" in the name of this routine means buffer expansion,
  1822. * not macro expansion. It may become necessary to have some hacky
  1823. * mechanism for flushing out the output buffer if it gets too big.
  1824. *
  1825. * As things stand, nothing is ever placed in the output buffer to be
  1826. * removed again except when it's KNOWN to be part of an identifier,
  1827. * so flushing and moving down everything left, instead of expanding,
  1828. * should work ok.
  1829. */
  1830. U_CHAR *
  1831. check_expand(obuf, needed)
  1832. register FILE_BUF *obuf;
  1833. register int needed;
  1834. {
  1835. register int i;
  1836. register U_CHAR *p;
  1837. if (obuf->length - (obuf->bufp - obuf->buf) > needed)
  1838. return obuf->buf;
  1839. i = 2 * obuf->length;
  1840. if (needed >= i)
  1841. i += (3 * needed) / 2;
  1842. if ((p = (U_CHAR *) xrealloc (obuf->buf, i)) == NULL)
  1843. return NULL;
  1844. obuf->bufp = p + (obuf->bufp - obuf->buf);
  1845. obuf->buf = p;
  1846. obuf->length = i;
  1847. return p;
  1848. }
  1849. /*
  1850. * install a name in the main hash table, even if it is already there.
  1851. * name stops with first non alphanumeric, except leading '#'.
  1852. * caller must check against redefinition if that is desired.
  1853. * delete() removes things installed by install() in fifo order.
  1854. * this is important because of the `defined' special symbol used
  1855. * in #if, and also if pushdef/popdef directives are ever implemented.
  1856. */
  1857. HASHNODE *
  1858. install (name, type, value)
  1859. U_CHAR *name;
  1860. int type;
  1861. int value;
  1862. /* watch out here if sizeof(U_CHAR *) != sizeof (int) */
  1863. {
  1864. HASHNODE *hp;
  1865. int i, len = 0, bucket;
  1866. register U_CHAR *p;
  1867. p = name;
  1868. while (is_idchar[*p])
  1869. p++;
  1870. len = p - name;
  1871. i = sizeof (HASHNODE) + len + 1;
  1872. hp = (HASHNODE *) xmalloc (i);
  1873. bucket = hashf(name, len, HASHSIZE);
  1874. hp->bucket_hdr = &hashtab[bucket];
  1875. hp->next = hashtab[bucket];
  1876. hashtab[bucket] = hp;
  1877. hp->prev = NULL;
  1878. if (hp->next != NULL)
  1879. hp->next->prev = hp;
  1880. hp->type = type;
  1881. hp->length = len;
  1882. hp->value.ival = value;
  1883. hp->name = ((U_CHAR *) hp) + sizeof (HASHNODE);
  1884. bcopy (name, hp->name, len);
  1885. return hp;
  1886. }
  1887. /*
  1888. * find the most recent hash node for name name (ending with first
  1889. * non-identifier char) installed by install
  1890. */
  1891. HASHNODE *
  1892. lookup (name)
  1893. U_CHAR *name;
  1894. {
  1895. register U_CHAR *bp;
  1896. register HASHNODE *bucket;
  1897. int len;
  1898. for (bp = name; is_idchar[*bp]; bp++)
  1899. ;
  1900. len = bp - name;
  1901. bucket = hashtab[hashf(name, len, HASHSIZE)];
  1902. while (bucket) {
  1903. if (bucket->length == len && strncmp(bucket->name, name, len) == 0)
  1904. return bucket;
  1905. bucket = bucket->next;
  1906. }
  1907. return NULL;
  1908. }
  1909. /*
  1910. * Delete a hash node. Some weirdness to free junk from macros.
  1911. * More such weirdness will have to be added if you define more hash
  1912. * types that need it.
  1913. */
  1914. delete(hp)
  1915. HASHNODE *hp;
  1916. {
  1917. if (hp->prev != NULL)
  1918. hp->prev->next = hp->next;
  1919. if (hp->next != NULL)
  1920. hp->next->prev = hp->prev;
  1921. /* make sure that the bucket chain header that
  1922. the deleted guy was on points to the right thing afterwards. */
  1923. if (hp == *hp->bucket_hdr)
  1924. *hp->bucket_hdr = hp->next;
  1925. if (hp->type == T_MACRO) {
  1926. DEFINITION *d = hp->value.defn;
  1927. struct reflist *ap, *nextap;
  1928. for (ap = d->pattern; ap != NULL; ap = nextap) {
  1929. nextap = ap->next;
  1930. free (ap);
  1931. }
  1932. free (d);
  1933. }
  1934. }
  1935. /*
  1936. * return hash function on name. must be compatible with the one
  1937. * computed a step at a time, elsewhere
  1938. */
  1939. int
  1940. hashf(name, len, hashsize)
  1941. register U_CHAR *name;
  1942. register int len;
  1943. int hashsize;
  1944. {
  1945. register int r = 0;
  1946. while (len--)
  1947. r = HASHSTEP(r, *name++);
  1948. return MAKE_POS(r) % hashsize;
  1949. }
  1950. /*
  1951. * initialize random junk in the hash table and maybe other places
  1952. */
  1953. initialize_random_junk()
  1954. {
  1955. register int i;
  1956. /*
  1957. * Set up is_idchar and is_idstart tables. These should be
  1958. * faster than saying (is_alpha(c) || c == '_'), etc.
  1959. * Must do set up these things before calling any routines tthat
  1960. * refer to them.
  1961. */
  1962. for (i = 'a'; i <= 'z'; i++) {
  1963. ++is_idchar[i - 'a' + 'A'];
  1964. ++is_idchar[i];
  1965. ++is_idstart[i - 'a' + 'A'];
  1966. ++is_idstart[i];
  1967. }
  1968. for (i = '0'; i <= '9'; i++)
  1969. ++is_idchar[i];
  1970. ++is_idchar['_'];
  1971. ++is_idstart['_'];
  1972. /* horizontal space table */
  1973. ++is_hor_space[' '];
  1974. ++is_hor_space['\t'];
  1975. install("__LINE__", T_SPECLINE, 0);
  1976. install("__DATE__", T_DATE, 0);
  1977. install("__FILE__", T_FILE, 0);
  1978. install("__TIME__", T_TIME, 0);
  1979. #ifdef vax
  1980. make_definition("vax 1");
  1981. #endif
  1982. #ifdef unix
  1983. make_definition("unix 1");
  1984. #endif
  1985. /* is there more? */
  1986. }
  1987. /*
  1988. * process a given definition string, for initialization
  1989. */
  1990. make_definition(str)
  1991. U_CHAR *str;
  1992. {
  1993. FILE_BUF *ip;
  1994. struct keyword_table *kt;
  1995. ip = &instack[indepth++];
  1996. ip->fname = "*Initialization*";
  1997. ip->buf = ip->bufp = str;
  1998. ip->length = strlen(str);
  1999. ip->lineno = 1;
  2000. for (kt = keyword_table; kt->type != T_DEFINE; kt++)
  2001. ;
  2002. /* pass NULL as output ptr to do_define since we KNOW it never
  2003. does any output.... */
  2004. do_define (str, str + strlen(str) /* - 1 JF */ , NULL, kt);
  2005. --indepth;
  2006. }
  2007. /* JF, this does the work for the -U option */
  2008. make_undef(str)
  2009. U_CHAR *str;
  2010. {
  2011. FILE_BUF *ip;
  2012. struct keyword_table *kt;
  2013. ip = &instack[indepth++];
  2014. ip->fname = "*undef*";
  2015. ip->buf = ip->bufp = str;
  2016. ip->length = strlen(str);
  2017. ip->lineno = 1;
  2018. for(kt = keyword_table; kt->type != T_UNDEF; kt++)
  2019. ;
  2020. do_undef(str,str + strlen(str) - 1, NULL, kt);
  2021. --indepth;
  2022. }
  2023. #ifndef BSD
  2024. #ifndef BSTRING
  2025. void
  2026. bzero (b, length)
  2027. register char *b;
  2028. register int length;
  2029. {
  2030. #ifdef VMS
  2031. short zero = 0;
  2032. long max_str = 65535;
  2033. while (length > max_str)
  2034. {
  2035. (void) LIB$MOVC5 (&zero, &zero, &zero, &max_str, b);
  2036. length -= max_str;
  2037. b += max_str;
  2038. }
  2039. (void) LIB$MOVC5 (&zero, &zero, &zero, &length, b);
  2040. #else
  2041. while (length-- > 0)
  2042. *b++ = 0;
  2043. #endif /* not VMS */
  2044. }
  2045. void
  2046. bcopy (b1, b2, length)
  2047. register char *b1;
  2048. register char *b2;
  2049. register int length;
  2050. {
  2051. #ifdef VMS
  2052. long max_str = 65535;
  2053. while (length > max_str)
  2054. {
  2055. (void) LIB$MOVC3 (&max_str, b1, b2);
  2056. length -= max_str;
  2057. b1 += max_str;
  2058. b2 += max_str;
  2059. }
  2060. (void) LIB$MOVC3 (&length, b1, b2);
  2061. #else
  2062. while (length-- > 0)
  2063. *b2++ = *b1++;
  2064. #endif /* not VMS */
  2065. }
  2066. int
  2067. bcmp (b1, b2, length) /* This could be a macro! */
  2068. register char *b1;
  2069. register char *b2;
  2070. register int length;
  2071. {
  2072. #ifdef VMS
  2073. struct dsc$descriptor_s src1 = {length, DSC$K_DTYPE_T, DSC$K_CLASS_S, b1};
  2074. struct dsc$descriptor_s src2 = {length, DSC$K_DTYPE_T, DSC$K_CLASS_S, b2};
  2075. return STR$COMPARE (&src1, &src2);
  2076. #else
  2077. while (length-- > 0)
  2078. if (*b1++ != *b2++)
  2079. return 1;
  2080. return 0;
  2081. #endif /* not VMS */
  2082. }
  2083. #endif /* not BSTRING */
  2084. #endif /* not BSD */
  2085. void
  2086. fatal (str, arg)
  2087. char *str, *arg;
  2088. {
  2089. fprintf (stderr, "%s: ", progname);
  2090. fprintf (stderr, str, arg);
  2091. fprintf (stderr, "\n");
  2092. exit (FATAL_EXIT_CODE);
  2093. }
  2094. void
  2095. perror_with_name (name)
  2096. char *name;
  2097. {
  2098. extern int errno, sys_nerr;
  2099. extern char *sys_errlist[];
  2100. fprintf (stderr, "%s: ", progname);
  2101. if (errno < sys_nerr)
  2102. fprintf (stderr, "%s for %s\n", sys_errlist[errno], name);
  2103. else
  2104. fprintf (stderr, "cannot open %s\n", sys_errlist[errno], name);
  2105. }
  2106. void
  2107. pfatal_with_name (name)
  2108. char *name;
  2109. {
  2110. perror_with_name (name);
  2111. exit (FATAL_EXIT_CODE);
  2112. }
  2113. static void
  2114. memory_full ()
  2115. {
  2116. fatal ("Memory exhausted.");
  2117. }
  2118. char *
  2119. xmalloc (size)
  2120. int size;
  2121. {
  2122. extern char *malloc ();
  2123. register char *ptr = malloc (size);
  2124. if (ptr != 0) return (ptr);
  2125. memory_full ();
  2126. /*NOTREACHED*/
  2127. }
  2128. char *
  2129. xrealloc (old, size)
  2130. char *old;
  2131. int size;
  2132. {
  2133. extern char *realloc ();
  2134. register char *ptr = realloc (old, size);
  2135. if (ptr != 0) return (ptr);
  2136. memory_full ();
  2137. /*NOTREACHED*/
  2138. }
  2139. char *
  2140. xcalloc (number, size)
  2141. int number, size;
  2142. {
  2143. extern char *malloc ();
  2144. register int total = number * size;
  2145. register char *ptr = malloc (total);
  2146. if (ptr != 0)
  2147. {
  2148. bzero (ptr, total);
  2149. return (ptr);
  2150. }
  2151. memory_full ();
  2152. /*NOTREACHED*/
  2153. }