lex.cc 43 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259
  1. // -*- C++ -*-
  2. /* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
  3. Written by James Clark (jjc@jclark.com) */
  4. /* Comment by rsm: shortly after label got_dot, there is a line that looks
  5. bogus:
  6. if (!c == EOF || !csdigit(c)) break;
  7. */
  8. #include "pic.h"
  9. #include "object.h"
  10. #include "gram.h"
  11. // Character representing $1. Must be illegal input character.
  12. #define ARG1 14
  13. declare_ptable(char)
  14. implement_ptable(char)
  15. PTABLE(char) macro_table;
  16. //////////////////////////////////////////////////////////////////////
  17. // Forward declarations for lexer
  18. //////////////////////////////////////////////////////////////////////
  19. // forward references to internal lexer functions
  20. static char * process_body(const char *body);
  21. static char * get_thru_arg(void);
  22. static int docmp(const char *s1, int n1, const char *s2, int n2);
  23. static int get_delimited(void);
  24. static int get_token(int lookup_flag);
  25. static int get_token_after_dot(int c);
  26. static int lookup_keyword(const char *str, int len);
  27. static void do_define(void);
  28. static void do_undef(void);
  29. static void interpolate_macro_with_args(const char *body);
  30. // lexer global variables
  31. static double token_double;
  32. static int lookahead_token = -1;
  33. static int token_int;
  34. static string context_buffer;
  35. static string old_context_buffer;
  36. static string token_buffer;
  37. //////////////////////////////////////////////////////////////////////
  38. // default function members for input classes
  39. //////////////////////////////////////////////////////////////////////
  40. input::input() : next(0)
  41. {
  42. }
  43. input::~input()
  44. {
  45. }
  46. int
  47. input::get_location (const char **, int *)
  48. {
  49. return 0;
  50. }
  51. //////////////////////////////////////////////////////////////////////
  52. // MACRO_INPUT class
  53. //////////////////////////////////////////////////////////////////////
  54. class macro_input : public input
  55. {
  56. public:
  57. // ctor, dtor
  58. macro_input(const char *);
  59. ~macro_input();
  60. // public functions
  61. int get (void);
  62. int peek (void);
  63. private:
  64. char *s;
  65. char *p;
  66. };
  67. macro_input::macro_input(const char *str)
  68. {
  69. p = s = strsave(str);
  70. }
  71. macro_input::~macro_input()
  72. {
  73. a_delete s;
  74. }
  75. int
  76. macro_input::get(void)
  77. {
  78. if (p == 0 || *p == '\0')
  79. return EOF;
  80. else
  81. return (unsigned char)*p++;
  82. }
  83. int
  84. macro_input::peek(void)
  85. {
  86. if (p == 0 || *p == '\0')
  87. return EOF;
  88. else
  89. return (unsigned char)*p;
  90. }
  91. //////////////////////////////////////////////////////////////////////
  92. // FILE_INPUT class
  93. //////////////////////////////////////////////////////////////////////
  94. file_input::file_input(FILE *f, const char *fn)
  95. : filename(fn), lineno(0), ptr("")
  96. {
  97. fp = f;
  98. }
  99. file_input::~file_input()
  100. {
  101. fclose(fp);
  102. }
  103. int
  104. file_input::get(void)
  105. {
  106. if (*ptr != '\0' || read_line())
  107. return (unsigned char)*ptr++;
  108. else
  109. return EOF;
  110. }
  111. int
  112. file_input::peek(void)
  113. {
  114. if (*ptr != '\0' || read_line())
  115. return (unsigned char)*ptr;
  116. else
  117. return EOF;
  118. }
  119. int
  120. file_input::get_location (const char **fnp, int *lnp)
  121. {
  122. *fnp = filename;
  123. *lnp = lineno;
  124. return 1;
  125. }
  126. int
  127. file_input::read_line(void)
  128. {
  129. for (;;)
  130. {
  131. line.clear();
  132. lineno++;
  133. for (;;)
  134. {
  135. int c = getc(fp);
  136. if (c == EOF)
  137. break;
  138. else if (illegal_input_char(c))
  139. lex_error("illegal input character code %1", c);
  140. else
  141. {
  142. line += char(c);
  143. if (c == '\n')
  144. break;
  145. }
  146. }
  147. if (line.length() == 0)
  148. return 0;
  149. if (!(line.length() >= 3 && line[0] == '.' && line[1] == 'P'
  150. && (line[2] == 'S' || line[2] == 'E' || line[2] == 'F')
  151. && (line.length() == 3 || line[3] == ' ' || line[3] == '\n'
  152. || compatible_flag)))
  153. {
  154. line += '\0';
  155. ptr = line.contents();
  156. return 1;
  157. }
  158. }
  159. }
  160. //////////////////////////////////////////////////////////////////////
  161. // ARGUMENT_MACRO_INPUT class
  162. //////////////////////////////////////////////////////////////////////
  163. class argument_macro_input : public input
  164. {
  165. public:
  166. // ctor, dtor
  167. argument_macro_input(const char *, int, char **);
  168. ~argument_macro_input();
  169. // public functions
  170. int get (void);
  171. int peek (void);
  172. private:
  173. char *s;
  174. char *p;
  175. char *ap;
  176. int argc;
  177. char *argv[9];
  178. };
  179. argument_macro_input::argument_macro_input(const char *body, int ac, char **av)
  180. : ap(0), argc(ac)
  181. {
  182. for (int i = 0; i < argc; i++)
  183. argv[i] = av[i];
  184. p = s = process_body(body);
  185. }
  186. argument_macro_input::~argument_macro_input()
  187. {
  188. for (int i = 0; i < argc; i++)
  189. a_delete argv[i];
  190. a_delete s;
  191. }
  192. int
  193. argument_macro_input::get(void)
  194. {
  195. if (ap)
  196. {
  197. if (*ap != '\0')
  198. return (unsigned char)*ap++;
  199. ap = 0;
  200. }
  201. if (p == 0)
  202. return EOF;
  203. while (*p >= ARG1 && *p <= ARG1 + 8)
  204. {
  205. int i = *p++ - ARG1;
  206. if (i < argc && argv[i] != 0 && argv[i][0] != '\0')
  207. {
  208. ap = argv[i];
  209. return (unsigned char)*ap++;
  210. }
  211. }
  212. if (*p == '\0')
  213. return EOF;
  214. return (unsigned char)*p++;
  215. }
  216. int
  217. argument_macro_input::peek(void)
  218. {
  219. if (ap)
  220. {
  221. if (*ap != '\0')
  222. return (unsigned char)*ap;
  223. ap = 0;
  224. }
  225. if (p == 0)
  226. return EOF;
  227. while (*p >= ARG1 && *p <= ARG1 + 8)
  228. {
  229. int i = *p++ - ARG1;
  230. if (i < argc && argv[i] != 0 && argv[i][0] != '\0')
  231. {
  232. ap = argv[i];
  233. return (unsigned char)*ap;
  234. }
  235. }
  236. if (*p == '\0')
  237. return EOF;
  238. return (unsigned char)*p;
  239. }
  240. //////////////////////////////////////////////////////////////////////
  241. // CHAR_INPUT class
  242. //////////////////////////////////////////////////////////////////////
  243. class char_input : public input
  244. {
  245. public:
  246. // ctor
  247. char_input (int n);
  248. // public functions
  249. int get (void);
  250. int peek (void);
  251. private:
  252. int c;
  253. };
  254. char_input::char_input(int n) : c((unsigned char)n)
  255. {
  256. }
  257. int
  258. char_input::get (void)
  259. {
  260. int n = c;
  261. c = EOF;
  262. return n;
  263. }
  264. int
  265. char_input::peek (void)
  266. {
  267. return c;
  268. }
  269. //////////////////////////////////////////////////////////////////////
  270. // FOR_INPUT class
  271. //////////////////////////////////////////////////////////////////////
  272. class for_input : public input
  273. {
  274. public:
  275. //ctor, dtor
  276. for_input(char *, double, int, double, char *);
  277. ~for_input();
  278. // public functions
  279. int get (void);
  280. int peek (void);
  281. private:
  282. char *var;
  283. char *body;
  284. double to;
  285. int by_is_multiplicative;
  286. double by;
  287. const char *p;
  288. int done_newline;
  289. };
  290. for_input::for_input(char *vr, double t, int bim, double b, char *bd)
  291. : var(vr), body(bd), to(t), by_is_multiplicative(bim), by(b), p(body),
  292. done_newline(0)
  293. {
  294. }
  295. for_input::~for_input()
  296. {
  297. a_delete var;
  298. a_delete body;
  299. }
  300. int
  301. for_input::get(void)
  302. {
  303. if (p == 0)
  304. return EOF;
  305. for (;;)
  306. {
  307. if (*p != '\0')
  308. return (unsigned char)*p++;
  309. if (!done_newline)
  310. {
  311. done_newline = 1;
  312. return '\n';
  313. }
  314. double val;
  315. if (!lookup_variable(var, &val))
  316. {
  317. lex_error("body of `for' terminated enclosing block");
  318. return EOF;
  319. }
  320. if (by_is_multiplicative)
  321. val *= by;
  322. else
  323. val += by;
  324. define_variable(var, val);
  325. if (val > to)
  326. {
  327. p = 0;
  328. return EOF;
  329. }
  330. p = body;
  331. done_newline = 0;
  332. }
  333. }
  334. int
  335. for_input::peek(void)
  336. {
  337. if (p == 0)
  338. return EOF;
  339. if (*p != '\0')
  340. return (unsigned char)*p;
  341. if (!done_newline)
  342. return '\n';
  343. double val;
  344. if (!lookup_variable(var, &val))
  345. return EOF;
  346. if (by_is_multiplicative)
  347. {
  348. if (val * by > to)
  349. return EOF;
  350. }
  351. else
  352. {
  353. if (val + by > to)
  354. return EOF;
  355. }
  356. if (*body == '\0')
  357. return EOF;
  358. return (unsigned char)*body;
  359. }
  360. //////////////////////////////////////////////////////////////////////
  361. // COPY_THRU_INPUT class
  362. //////////////////////////////////////////////////////////////////////
  363. class copy_thru_input : public input
  364. {
  365. public:
  366. // ctor, dtor
  367. copy_thru_input(const char *b, const char *u);
  368. ~copy_thru_input();
  369. // public functions
  370. int get (void);
  371. int peek (void);
  372. private:
  373. int done;
  374. char *body;
  375. char *until;
  376. const char *p;
  377. const char *ap;
  378. int argv[9];
  379. int argc;
  380. string line;
  381. int get_line();
  382. virtual int inget() = 0;
  383. };
  384. copy_thru_input::copy_thru_input(const char *b, const char *u)
  385. : done(0)
  386. {
  387. ap = 0;
  388. body = process_body(b);
  389. p = 0;
  390. until = strsave(u);
  391. }
  392. copy_thru_input::~copy_thru_input()
  393. {
  394. a_delete body;
  395. a_delete until;
  396. }
  397. int
  398. copy_thru_input::get(void)
  399. {
  400. if (ap)
  401. {
  402. if (*ap != '\0')
  403. return (unsigned char)*ap++;
  404. ap = 0;
  405. }
  406. for (;;)
  407. {
  408. if (p == 0)
  409. {
  410. if (!get_line())
  411. break;
  412. p = body;
  413. }
  414. if (*p == '\0')
  415. {
  416. p = 0;
  417. return '\n';
  418. }
  419. while (*p >= ARG1 && *p <= ARG1 + 8)
  420. {
  421. int i = *p++ - ARG1;
  422. if (i < argc && line[argv[i]] != '\0')
  423. {
  424. ap = line.contents() + argv[i];
  425. return (unsigned char)*ap++;
  426. }
  427. }
  428. if (*p != '\0')
  429. return (unsigned char)*p++;
  430. }
  431. return EOF;
  432. }
  433. int
  434. copy_thru_input::peek(void)
  435. {
  436. if (ap)
  437. {
  438. if (*ap != '\0')
  439. return (unsigned char)*ap;
  440. ap = 0;
  441. }
  442. for (;;)
  443. {
  444. if (p == 0)
  445. {
  446. if (!get_line())
  447. break;
  448. p = body;
  449. }
  450. if (*p == '\0')
  451. return '\n';
  452. while (*p >= ARG1 && *p <= ARG1 + 8)
  453. {
  454. int i = *p++ - ARG1;
  455. if (i < argc && line[argv[i]] != '\0')
  456. {
  457. ap = line.contents() + argv[i];
  458. return (unsigned char)*ap;
  459. }
  460. }
  461. if (*p != '\0')
  462. return (unsigned char)*p;
  463. }
  464. return EOF;
  465. }
  466. int
  467. copy_thru_input::get_line(void)
  468. {
  469. if (done)
  470. return 0;
  471. line.clear();
  472. argc = 0;
  473. int c = inget();
  474. for (;;)
  475. {
  476. while (c == ' ')
  477. c = inget();
  478. if (c == EOF || c == '\n')
  479. break;
  480. if (argc == 9)
  481. {
  482. do
  483. {
  484. c = inget();
  485. } while (c != '\n' && c != EOF);
  486. break;
  487. }
  488. argv[argc++] = line.length();
  489. do
  490. {
  491. line += char(c);
  492. c = inget();
  493. } while (c != ' ' && c != '\n');
  494. line += '\0';
  495. }
  496. if (until != 0 && argc > 0 && strcmp(&line[argv[0]], until) == 0)
  497. {
  498. done = 1;
  499. return 0;
  500. }
  501. return argc > 0 || c == '\n';
  502. }
  503. //////////////////////////////////////////////////////////////////////
  504. // COPY_FILE_THRU_INPUT class (subclassed from COPY_THRU_INPUT)
  505. //////////////////////////////////////////////////////////////////////
  506. class copy_file_thru_input : public copy_thru_input
  507. {
  508. public:
  509. copy_file_thru_input(input *, const char *b, const char *u);
  510. ~copy_file_thru_input();
  511. int inget();
  512. private:
  513. input *in;
  514. };
  515. copy_file_thru_input::copy_file_thru_input(input *i, const char *b,
  516. const char *u)
  517. : copy_thru_input(b, u), in(i)
  518. {
  519. }
  520. copy_file_thru_input::~copy_file_thru_input()
  521. {
  522. delete in;
  523. }
  524. int
  525. copy_file_thru_input::inget(void)
  526. {
  527. if (!in)
  528. return EOF;
  529. else
  530. return in->get();
  531. }
  532. //////////////////////////////////////////////////////////////////////
  533. // COPY_REST_THRU_INPUT class (subclassed from COPY_THRU_INPUT)
  534. //////////////////////////////////////////////////////////////////////
  535. class copy_rest_thru_input : public copy_thru_input
  536. {
  537. public:
  538. // ctor
  539. copy_rest_thru_input (const char *, const char *u);
  540. // public functions
  541. int inget (void);
  542. };
  543. copy_rest_thru_input::copy_rest_thru_input(const char *b, const char *u)
  544. : copy_thru_input(b, u)
  545. {
  546. }
  547. int
  548. copy_rest_thru_input::inget(void)
  549. {
  550. while (next != 0)
  551. {
  552. int c = next->get();
  553. if (c != EOF)
  554. return c;
  555. if (next->next == 0)
  556. return EOF;
  557. input *tem = next;
  558. next = next->next;
  559. delete tem;
  560. }
  561. return EOF;
  562. }
  563. //////////////////////////////////////////////////////////////////////
  564. // SIMPLE_FILE_INPUT class
  565. //////////////////////////////////////////////////////////////////////
  566. class simple_file_input : public input
  567. {
  568. public:
  569. // ctor, dtor
  570. simple_file_input(FILE *, const char *);
  571. ~simple_file_input();
  572. // public functions
  573. int get (void);
  574. int peek (void);
  575. int get_location (const char **, int *);
  576. private:
  577. const char *filename;
  578. int lineno;
  579. FILE *fp;
  580. };
  581. simple_file_input::simple_file_input(FILE *p, const char *s)
  582. : filename(s), lineno(1), fp(p)
  583. {
  584. }
  585. simple_file_input::~simple_file_input(void)
  586. {
  587. // don't delete the filename
  588. fclose(fp);
  589. }
  590. int
  591. simple_file_input::get(void)
  592. {
  593. int c = getc(fp);
  594. while (illegal_input_char(c))
  595. {
  596. error("illegal input character code %1", c);
  597. c = getc(fp);
  598. }
  599. if (c == '\n')
  600. lineno++;
  601. return c;
  602. }
  603. int
  604. simple_file_input::peek(void)
  605. {
  606. int c = getc(fp);
  607. while (illegal_input_char(c))
  608. {
  609. error("illegal input character code %1", c);
  610. c = getc(fp);
  611. }
  612. if (c != EOF)
  613. ungetc(c, fp);
  614. return c;
  615. }
  616. int
  617. simple_file_input::get_location (const char **fnp, int *lnp)
  618. {
  619. *fnp = filename;
  620. *lnp = lineno;
  621. return 1;
  622. }
  623. //////////////////////////////////////////////////////////////////////
  624. // INPUT_STACK class (not subclassed from INPUT)
  625. //////////////////////////////////////////////////////////////////////
  626. class input_stack
  627. {
  628. public:
  629. static void push(input *);
  630. static void clear();
  631. static int get_char();
  632. static int peek_char();
  633. static int get_location (const char **fnp, int *lnp);
  634. static void push_back(unsigned char c, int was_bol = 0);
  635. static int bol();
  636. private:
  637. static input *current_input;
  638. static int bol_flag;
  639. };
  640. void
  641. input_stack::push(input *in)
  642. {
  643. in->next = current_input;
  644. current_input = in;
  645. }
  646. void
  647. input_stack::clear(void)
  648. {
  649. while (current_input != 0)
  650. {
  651. input *tem = current_input;
  652. current_input = current_input->next;
  653. delete tem;
  654. }
  655. bol_flag = 1;
  656. }
  657. int
  658. input_stack::get_char(void)
  659. {
  660. while (current_input != 0)
  661. {
  662. int c = current_input->get();
  663. if (c != EOF)
  664. {
  665. bol_flag = c == '\n';
  666. return c;
  667. }
  668. // don't pop the top-level input off the stack
  669. if (current_input->next == 0)
  670. return EOF;
  671. input *tem = current_input;
  672. current_input = current_input->next;
  673. delete tem;
  674. }
  675. return EOF;
  676. }
  677. int
  678. input_stack::peek_char(void)
  679. {
  680. while (current_input != 0)
  681. {
  682. int c = current_input->peek();
  683. if (c != EOF)
  684. return c;
  685. if (current_input->next == 0)
  686. return EOF;
  687. input *tem = current_input;
  688. current_input = current_input->next;
  689. delete tem;
  690. }
  691. return EOF;
  692. }
  693. int
  694. input_stack::get_location (const char **fnp, int *lnp)
  695. {
  696. for (input *p = current_input; p; p = p->next)
  697. if (p->get_location (fnp, lnp))
  698. return 1;
  699. return 0;
  700. }
  701. void
  702. input_stack::push_back(unsigned char c, int was_bol)
  703. {
  704. push(new char_input(c));
  705. bol_flag = was_bol;
  706. }
  707. inline int
  708. input_stack::bol(void)
  709. {
  710. return bol_flag;
  711. }
  712. input *input_stack::current_input = 0;
  713. int input_stack::bol_flag = 0;
  714. //////////////////////////////////////////////////////////////////////
  715. // PIC LEXER
  716. //
  717. // Public interface (declared in pic.h):
  718. //
  719. // lex_init(), lex_cleanup()
  720. // yylex(), yyerror()
  721. // lex_error(), lex_warning(),
  722. // do_copy(), do_for(), copy_file_thru(), copy_rest_thru(), push_body()
  723. // do_lookahead()
  724. //
  725. // The lexer accesses a read-only variable of the parser, `delim_flag',
  726. // and also calls the parser's define_variable() and lookup_variable()
  727. // functions [they're used in for loops].
  728. //////////////////////////////////////////////////////////////////////
  729. void
  730. lex_init(input *top)
  731. {
  732. input_stack::clear();
  733. input_stack::push(top);
  734. }
  735. void
  736. lex_cleanup(void)
  737. {
  738. while (input_stack::get_char() != EOF)
  739. ;
  740. }
  741. static void
  742. interpolate_macro_with_args(const char *body)
  743. {
  744. char *argv[9];
  745. int argc = 0;
  746. int i;
  747. for (i = 0; i < 9; i++)
  748. argv[i] = 0;
  749. int level = 0;
  750. int c;
  751. enum { NORMAL, IN_STRING, IN_STRING_QUOTED } state = NORMAL;
  752. do
  753. {
  754. token_buffer.clear();
  755. for (;;)
  756. {
  757. c = input_stack::get_char();
  758. if (c == EOF)
  759. {
  760. lex_error("end of input while scanning macro arguments");
  761. break;
  762. }
  763. if (state == NORMAL && level == 0 && (c == ',' || c == ')'))
  764. {
  765. if (token_buffer.length() > 0)
  766. {
  767. token_buffer += '\0';
  768. argv[argc] = strsave(token_buffer.contents());
  769. }
  770. // for `foo()', argc = 0
  771. if (argc > 0 || c != ')' || i > 0)
  772. argc++;
  773. break;
  774. }
  775. token_buffer += char(c);
  776. switch (state)
  777. {
  778. case NORMAL:
  779. if (c == '"')
  780. state = IN_STRING;
  781. else if (c == '(')
  782. level++;
  783. else if (c == ')')
  784. level--;
  785. break;
  786. case IN_STRING:
  787. if (c == '"')
  788. state = NORMAL;
  789. else if (c == '\\')
  790. state = IN_STRING_QUOTED;
  791. break;
  792. case IN_STRING_QUOTED:
  793. state = IN_STRING;
  794. break;
  795. }
  796. }
  797. } while (c != ')' && c != EOF);
  798. input_stack::push(new argument_macro_input(body, argc, argv));
  799. }
  800. static int
  801. docmp(const char *s1, int n1, const char *s2, int n2)
  802. {
  803. if (n1 < n2)
  804. {
  805. int r = memcmp(s1, s2, n1);
  806. return r ? r : -1;
  807. }
  808. else if (n1 > n2)
  809. {
  810. int r = memcmp(s1, s2, n2);
  811. return r ? r : 1;
  812. }
  813. else
  814. return memcmp(s1, s2, n1);
  815. }
  816. static int
  817. lookup_keyword(const char *str, int len)
  818. {
  819. static struct keyword
  820. {
  821. const char *name;
  822. int token;
  823. } table[] =
  824. {
  825. { "Here", HERE },
  826. { "above", ABOVE },
  827. { "aligned", ALIGNED },
  828. { "and", AND },
  829. { "arc", ARC },
  830. { "arrow", ARROW },
  831. { "at", AT },
  832. { "atan2", ATAN2 },
  833. { "below", BELOW },
  834. { "between", BETWEEN },
  835. { "bottom", BOTTOM },
  836. { "box", BOX },
  837. { "by", BY },
  838. { "ccw", CCW },
  839. { "center", CENTER },
  840. { "chop", CHOP },
  841. { "circle", CIRCLE },
  842. { "command", COMMAND },
  843. { "copy", COPY },
  844. { "cos", COS },
  845. { "cw", CW },
  846. { "dashed", DASHED },
  847. { "define", DEFINE },
  848. { "diam", DIAMETER },
  849. { "diameter", DIAMETER },
  850. { "do", DO },
  851. { "dotted", DOTTED },
  852. { "down", DOWN },
  853. { "ellipse", ELLIPSE },
  854. { "else", ELSE },
  855. { "end", END },
  856. { "exp", EXP },
  857. { "fill", FILL },
  858. { "filled", FILL },
  859. { "for", FOR },
  860. { "from", FROM },
  861. { "height", HEIGHT },
  862. { "ht", HEIGHT },
  863. { "if", IF },
  864. { "int", INT },
  865. { "invis", INVISIBLE },
  866. { "invisible", INVISIBLE },
  867. { "last", LAST },
  868. { "left", LEFT },
  869. { "line", LINE },
  870. { "ljust", LJUST },
  871. { "log", LOG },
  872. { "lower", LOWER },
  873. { "max", K_MAX },
  874. { "min", K_MIN },
  875. { "move", MOVE },
  876. { "of", OF },
  877. { "plot", PLOT },
  878. { "print", PRINT },
  879. { "rad", RADIUS },
  880. { "radius", RADIUS },
  881. { "rand", RAND },
  882. { "reset", RESET },
  883. { "right", RIGHT },
  884. { "rjust", RJUST },
  885. { "same", SAME },
  886. { "sh", SH },
  887. { "sin", SIN },
  888. { "spline", SPLINE },
  889. { "sprintf", SPRINTF },
  890. { "sqrt", SQRT },
  891. { "start", START },
  892. { "the", THE },
  893. { "then", THEN },
  894. { "thick", THICKNESS },
  895. { "thickness", THICKNESS },
  896. { "thru", THRU },
  897. { "to", TO },
  898. { "top", TOP },
  899. { "undef", UNDEF },
  900. { "until", UNTIL },
  901. { "up", UP },
  902. { "upper", UPPER },
  903. { "way", WAY },
  904. { "wid", WIDTH },
  905. { "width", WIDTH },
  906. { "with", WITH },
  907. };
  908. const keyword *start = table;
  909. const keyword *end = table + sizeof(table)/sizeof(table[0]);
  910. while (start < end)
  911. {
  912. // start <= target < end
  913. const keyword *mid = start + (end - start)/2;
  914. int cmp = docmp(str, len, mid->name, strlen(mid->name));
  915. if (cmp == 0)
  916. return mid->token;
  917. if (cmp < 0)
  918. end = mid;
  919. else
  920. start = mid + 1;
  921. }
  922. return 0;
  923. }
  924. static int
  925. get_token_after_dot(int c)
  926. {
  927. // get_token deals with the case where c is a digit
  928. switch (c)
  929. {
  930. case 'h':
  931. input_stack::get_char();
  932. c = input_stack::peek_char();
  933. if (c == 't')
  934. {
  935. input_stack::get_char();
  936. context_buffer = ".ht";
  937. return DOT_HT;
  938. }
  939. else if (c == 'e')
  940. {
  941. input_stack::get_char();
  942. c = input_stack::peek_char();
  943. if (c == 'i')
  944. {
  945. input_stack::get_char();
  946. c = input_stack::peek_char();
  947. if (c == 'g')
  948. {
  949. input_stack::get_char();
  950. c = input_stack::peek_char();
  951. if (c == 'h')
  952. {
  953. input_stack::get_char();
  954. c = input_stack::peek_char();
  955. if (c == 't')
  956. {
  957. input_stack::get_char();
  958. context_buffer = ".height";
  959. return DOT_HT;
  960. }
  961. input_stack::push_back('h');
  962. }
  963. input_stack::push_back('g');
  964. }
  965. input_stack::push_back('i');
  966. }
  967. input_stack::push_back('e');
  968. }
  969. input_stack::push_back('h');
  970. return '.';
  971. case 'x':
  972. input_stack::get_char();
  973. context_buffer = ".x";
  974. return DOT_X;
  975. case 'y':
  976. input_stack::get_char();
  977. context_buffer = ".y";
  978. return DOT_Y;
  979. case 'c':
  980. input_stack::get_char();
  981. c = input_stack::peek_char();
  982. if (c == 'e')
  983. {
  984. input_stack::get_char();
  985. c = input_stack::peek_char();
  986. if (c == 'n')
  987. {
  988. input_stack::get_char();
  989. c = input_stack::peek_char();
  990. if (c == 't')
  991. {
  992. input_stack::get_char();
  993. c = input_stack::peek_char();
  994. if (c == 'e')
  995. {
  996. input_stack::get_char();
  997. c = input_stack::peek_char();
  998. if (c == 'r')
  999. {
  1000. input_stack::get_char();
  1001. context_buffer = ".center";
  1002. return DOT_C;
  1003. }
  1004. input_stack::push_back('e');
  1005. }
  1006. input_stack::push_back('t');
  1007. }
  1008. input_stack::push_back('n');
  1009. }
  1010. input_stack::push_back('e');
  1011. }
  1012. context_buffer = ".c";
  1013. return DOT_C;
  1014. case 'n':
  1015. input_stack::get_char();
  1016. c = input_stack::peek_char();
  1017. if (c == 'e')
  1018. {
  1019. input_stack::get_char();
  1020. context_buffer = ".ne";
  1021. return DOT_NE;
  1022. }
  1023. else if (c == 'w')
  1024. {
  1025. input_stack::get_char();
  1026. context_buffer = ".nw";
  1027. return DOT_NW;
  1028. }
  1029. else
  1030. {
  1031. context_buffer = ".n";
  1032. return DOT_N;
  1033. }
  1034. break;
  1035. case 'e':
  1036. input_stack::get_char();
  1037. c = input_stack::peek_char();
  1038. if (c == 'n')
  1039. {
  1040. input_stack::get_char();
  1041. c = input_stack::peek_char();
  1042. if (c == 'd')
  1043. {
  1044. input_stack::get_char();
  1045. context_buffer = ".end";
  1046. return DOT_END;
  1047. }
  1048. input_stack::push_back('n');
  1049. context_buffer = ".e";
  1050. return DOT_E;
  1051. }
  1052. context_buffer = ".e";
  1053. return DOT_E;
  1054. case 'w':
  1055. input_stack::get_char();
  1056. c = input_stack::peek_char();
  1057. if (c == 'i')
  1058. {
  1059. input_stack::get_char();
  1060. c = input_stack::peek_char();
  1061. if (c == 'd')
  1062. {
  1063. input_stack::get_char();
  1064. c = input_stack::peek_char();
  1065. if (c == 't')
  1066. {
  1067. input_stack::get_char();
  1068. c = input_stack::peek_char();
  1069. if (c == 'h')
  1070. {
  1071. input_stack::get_char();
  1072. context_buffer = ".width";
  1073. return DOT_WID;
  1074. }
  1075. input_stack::push_back('t');
  1076. }
  1077. context_buffer = ".wid";
  1078. return DOT_WID;
  1079. }
  1080. input_stack::push_back('i');
  1081. }
  1082. context_buffer = ".w";
  1083. return DOT_W;
  1084. case 's':
  1085. input_stack::get_char();
  1086. c = input_stack::peek_char();
  1087. if (c == 'e')
  1088. {
  1089. input_stack::get_char();
  1090. context_buffer = ".se";
  1091. return DOT_SE;
  1092. }
  1093. else if (c == 'w')
  1094. {
  1095. input_stack::get_char();
  1096. context_buffer = ".sw";
  1097. return DOT_SW;
  1098. }
  1099. else
  1100. {
  1101. if (c == 't')
  1102. {
  1103. input_stack::get_char();
  1104. c = input_stack::peek_char();
  1105. if (c == 'a')
  1106. {
  1107. input_stack::get_char();
  1108. c = input_stack::peek_char();
  1109. if (c == 'r')
  1110. {
  1111. input_stack::get_char();
  1112. c = input_stack::peek_char();
  1113. if (c == 't')
  1114. {
  1115. input_stack::get_char();
  1116. context_buffer = ".start";
  1117. return DOT_START;
  1118. }
  1119. input_stack::push_back('r');
  1120. }
  1121. input_stack::push_back('a');
  1122. }
  1123. input_stack::push_back('t');
  1124. }
  1125. context_buffer = ".s";
  1126. return DOT_S;
  1127. }
  1128. break;
  1129. case 't':
  1130. input_stack::get_char();
  1131. c = input_stack::peek_char();
  1132. if (c == 'o')
  1133. {
  1134. input_stack::get_char();
  1135. c = input_stack::peek_char();
  1136. if (c == 'p')
  1137. {
  1138. input_stack::get_char();
  1139. context_buffer = ".top";
  1140. return DOT_N;
  1141. }
  1142. input_stack::push_back('o');
  1143. }
  1144. context_buffer = ".t";
  1145. return DOT_N;
  1146. case 'l':
  1147. input_stack::get_char();
  1148. c = input_stack::peek_char();
  1149. if (c == 'e')
  1150. {
  1151. input_stack::get_char();
  1152. c = input_stack::peek_char();
  1153. if (c == 'f')
  1154. {
  1155. input_stack::get_char();
  1156. c = input_stack::peek_char();
  1157. if (c == 't')
  1158. {
  1159. input_stack::get_char();
  1160. context_buffer = ".left";
  1161. return DOT_W;
  1162. }
  1163. input_stack::push_back('f');
  1164. }
  1165. input_stack::push_back('e');
  1166. }
  1167. context_buffer = ".l";
  1168. return DOT_W;
  1169. case 'r':
  1170. input_stack::get_char();
  1171. c = input_stack::peek_char();
  1172. if (c == 'a')
  1173. {
  1174. input_stack::get_char();
  1175. c = input_stack::peek_char();
  1176. if (c == 'd')
  1177. {
  1178. input_stack::get_char();
  1179. context_buffer = ".rad";
  1180. return DOT_RAD;
  1181. }
  1182. input_stack::push_back('a');
  1183. }
  1184. else if (c == 'i')
  1185. {
  1186. input_stack::get_char();
  1187. c = input_stack::peek_char();
  1188. if (c == 'g')
  1189. {
  1190. input_stack::get_char();
  1191. c = input_stack::peek_char();
  1192. if (c == 'h')
  1193. {
  1194. input_stack::get_char();
  1195. c = input_stack::peek_char();
  1196. if (c == 't')
  1197. {
  1198. input_stack::get_char();
  1199. context_buffer = ".right";
  1200. return DOT_E;
  1201. }
  1202. input_stack::push_back('h');
  1203. }
  1204. input_stack::push_back('g');
  1205. }
  1206. input_stack::push_back('i');
  1207. }
  1208. context_buffer = ".r";
  1209. return DOT_E;
  1210. case 'b':
  1211. input_stack::get_char();
  1212. c = input_stack::peek_char();
  1213. if (c == 'o')
  1214. {
  1215. input_stack::get_char();
  1216. c = input_stack::peek_char();
  1217. if (c == 't')
  1218. {
  1219. input_stack::get_char();
  1220. c = input_stack::peek_char();
  1221. if (c == 't')
  1222. {
  1223. input_stack::get_char();
  1224. c = input_stack::peek_char();
  1225. if (c == 'o')
  1226. {
  1227. input_stack::get_char();
  1228. c = input_stack::peek_char();
  1229. if (c == 'm')
  1230. {
  1231. input_stack::get_char();
  1232. context_buffer = ".bottom";
  1233. return DOT_S;
  1234. }
  1235. input_stack::push_back('o');
  1236. }
  1237. input_stack::push_back('t');
  1238. }
  1239. context_buffer = ".bot";
  1240. return DOT_S;
  1241. }
  1242. input_stack::push_back('o');
  1243. }
  1244. context_buffer = ".b";
  1245. return DOT_S;
  1246. default:
  1247. context_buffer = '.';
  1248. return '.';
  1249. }
  1250. }
  1251. static int
  1252. get_token(int lookup_flag)
  1253. {
  1254. context_buffer.clear();
  1255. for (;;)
  1256. {
  1257. int n = 0;
  1258. int bol = input_stack::bol();
  1259. int c = input_stack::get_char();
  1260. if (bol && c == command_char)
  1261. {
  1262. token_buffer.clear();
  1263. token_buffer += c;
  1264. // the newline is not part of the token
  1265. for (;;)
  1266. {
  1267. c = input_stack::peek_char();
  1268. if (c == EOF || c == '\n')
  1269. break;
  1270. input_stack::get_char();
  1271. token_buffer += char(c);
  1272. }
  1273. context_buffer = token_buffer;
  1274. return COMMAND_LINE;
  1275. }
  1276. switch (c)
  1277. {
  1278. case EOF:
  1279. return EOF;
  1280. case ' ':
  1281. case '\t':
  1282. break;
  1283. case '\\':
  1284. {
  1285. int d = input_stack::peek_char();
  1286. if (d != '\n')
  1287. {
  1288. context_buffer = '\\';
  1289. return '\\';
  1290. }
  1291. input_stack::get_char();
  1292. break;
  1293. }
  1294. case '#':
  1295. do
  1296. {
  1297. c = input_stack::get_char();
  1298. } while (c != '\n' && c != EOF);
  1299. if (c == '\n')
  1300. context_buffer = '\n';
  1301. return c;
  1302. case '"':
  1303. context_buffer = '"';
  1304. token_buffer.clear();
  1305. for (;;)
  1306. {
  1307. c = input_stack::get_char();
  1308. if (c == '\\')
  1309. {
  1310. context_buffer += '\\';
  1311. c = input_stack::peek_char();
  1312. if (c == '"')
  1313. {
  1314. input_stack::get_char();
  1315. token_buffer += '"';
  1316. context_buffer += '"';
  1317. }
  1318. else
  1319. token_buffer += '\\';
  1320. }
  1321. else if (c == '\n')
  1322. {
  1323. error("newline in string");
  1324. break;
  1325. }
  1326. else if (c == EOF)
  1327. {
  1328. error("missing `\"'");
  1329. break;
  1330. }
  1331. else if (c == '"')
  1332. {
  1333. context_buffer += '"';
  1334. break;
  1335. }
  1336. else
  1337. {
  1338. context_buffer += char(c);
  1339. token_buffer += char(c);
  1340. }
  1341. }
  1342. return TEXT;
  1343. case '0':
  1344. case '1':
  1345. case '2':
  1346. case '3':
  1347. case '4':
  1348. case '5':
  1349. case '6':
  1350. case '7':
  1351. case '8':
  1352. case '9':
  1353. {
  1354. int overflow = 0;
  1355. n = 0;
  1356. for (;;)
  1357. {
  1358. if (n > (INT_MAX - 9)/10)
  1359. {
  1360. overflow = 1;
  1361. break;
  1362. }
  1363. n *= 10;
  1364. n += c - '0';
  1365. context_buffer += char(c);
  1366. c = input_stack::peek_char();
  1367. if (c == EOF || !csdigit(c))
  1368. break;
  1369. c = input_stack::get_char();
  1370. }
  1371. token_double = n;
  1372. if (overflow)
  1373. {
  1374. for (;;)
  1375. {
  1376. token_double *= 10.0;
  1377. token_double += c - '0';
  1378. context_buffer += char(c);
  1379. c = input_stack::peek_char();
  1380. if (c == EOF || !csdigit(c))
  1381. break;
  1382. c = input_stack::get_char();
  1383. }
  1384. // if somebody asks for 1000000000000th, we will silently
  1385. // give them INT_MAXth
  1386. double temp = token_double; // work around gas 1.34/sparc bug
  1387. if (token_double > INT_MAX)
  1388. n = INT_MAX;
  1389. else
  1390. n = int(temp);
  1391. }
  1392. }
  1393. switch (c)
  1394. {
  1395. case 'i':
  1396. case 'I':
  1397. context_buffer += char(c);
  1398. input_stack::get_char();
  1399. return NUMBER;
  1400. case '.':
  1401. {
  1402. context_buffer += '.';
  1403. input_stack::get_char();
  1404. got_dot:
  1405. double factor = 1.0;
  1406. for (;;)
  1407. {
  1408. c = input_stack::peek_char();
  1409. if (!c == EOF || !csdigit(c))
  1410. break;
  1411. input_stack::get_char();
  1412. context_buffer += char(c);
  1413. factor /= 10.0;
  1414. if (c != '0')
  1415. token_double += factor*(c - '0');
  1416. }
  1417. if (c != 'e' && c != 'E')
  1418. {
  1419. if (c == 'i' || c == 'I')
  1420. {
  1421. context_buffer += char(c);
  1422. input_stack::get_char();
  1423. }
  1424. return NUMBER;
  1425. }
  1426. }
  1427. // fall through
  1428. case 'e':
  1429. case 'E':
  1430. {
  1431. int echar = c;
  1432. input_stack::get_char();
  1433. c = input_stack::peek_char();
  1434. int sign = '+';
  1435. if (c == '+' || c == '-')
  1436. {
  1437. sign = c;
  1438. input_stack::get_char();
  1439. c = input_stack::peek_char();
  1440. if (c == EOF || !csdigit(c))
  1441. {
  1442. input_stack::push_back(sign);
  1443. input_stack::push_back(echar);
  1444. return NUMBER;
  1445. }
  1446. context_buffer += char(echar);
  1447. context_buffer += char(sign);
  1448. }
  1449. else
  1450. {
  1451. if (c == EOF || !csdigit(c))
  1452. {
  1453. input_stack::push_back(echar);
  1454. return NUMBER;
  1455. }
  1456. context_buffer += char(echar);
  1457. }
  1458. input_stack::get_char();
  1459. context_buffer += char(c);
  1460. n = c - '0';
  1461. for (;;)
  1462. {
  1463. c = input_stack::peek_char();
  1464. if (c == EOF || !csdigit(c))
  1465. break;
  1466. input_stack::get_char();
  1467. context_buffer += char(c);
  1468. n = n*10 + (c - '0');
  1469. }
  1470. if (sign == '-')
  1471. n = -n;
  1472. if (c == 'i' || c == 'I')
  1473. {
  1474. context_buffer += char(c);
  1475. input_stack::get_char();
  1476. }
  1477. token_double *= pow(10.0, n);
  1478. return NUMBER;
  1479. }
  1480. case 'n':
  1481. input_stack::get_char();
  1482. c = input_stack::peek_char();
  1483. if (c == 'd')
  1484. {
  1485. input_stack::get_char();
  1486. token_int = n;
  1487. context_buffer += "nd";
  1488. return ORDINAL;
  1489. }
  1490. input_stack::push_back('n');
  1491. return NUMBER;
  1492. case 'r':
  1493. input_stack::get_char();
  1494. c = input_stack::peek_char();
  1495. if (c == 'd')
  1496. {
  1497. input_stack::get_char();
  1498. token_int = n;
  1499. context_buffer += "rd";
  1500. return ORDINAL;
  1501. }
  1502. input_stack::push_back('r');
  1503. return NUMBER;
  1504. case 't':
  1505. input_stack::get_char();
  1506. c = input_stack::peek_char();
  1507. if (c == 'h')
  1508. {
  1509. input_stack::get_char();
  1510. token_int = n;
  1511. context_buffer += "th";
  1512. return ORDINAL;
  1513. }
  1514. input_stack::push_back('t');
  1515. return NUMBER;
  1516. case 's':
  1517. input_stack::get_char();
  1518. c = input_stack::peek_char();
  1519. if (c == 't')
  1520. {
  1521. input_stack::get_char();
  1522. token_int = n;
  1523. context_buffer += "st";
  1524. return ORDINAL;
  1525. }
  1526. input_stack::push_back('s');
  1527. return NUMBER;
  1528. default:
  1529. return NUMBER;
  1530. }
  1531. break;
  1532. case '\'':
  1533. {
  1534. c = input_stack::peek_char();
  1535. if (c == 't')
  1536. {
  1537. input_stack::get_char();
  1538. c = input_stack::peek_char();
  1539. if (c == 'h')
  1540. {
  1541. input_stack::get_char();
  1542. context_buffer = "'th";
  1543. return TH;
  1544. }
  1545. else
  1546. input_stack::push_back('t');
  1547. }
  1548. context_buffer = "'";
  1549. return '\'';
  1550. }
  1551. case '.':
  1552. {
  1553. c = input_stack::peek_char();
  1554. if (c != EOF && csdigit(c))
  1555. {
  1556. n = 0;
  1557. token_double = 0.0;
  1558. context_buffer = '.';
  1559. goto got_dot;
  1560. }
  1561. return get_token_after_dot(c);
  1562. }
  1563. case '<':
  1564. c = input_stack::peek_char();
  1565. if (c == '-')
  1566. {
  1567. input_stack::get_char();
  1568. c = input_stack::peek_char();
  1569. if (c == '>')
  1570. {
  1571. input_stack::get_char();
  1572. context_buffer = "<->";
  1573. return DOUBLE_ARROW_HEAD;
  1574. }
  1575. context_buffer = "<-";
  1576. return LEFT_ARROW_HEAD;
  1577. }
  1578. else if (c == '=')
  1579. {
  1580. input_stack::get_char();
  1581. context_buffer = "<=";
  1582. return LESSEQUAL;
  1583. }
  1584. context_buffer = "<";
  1585. return '<';
  1586. case '-':
  1587. c = input_stack::peek_char();
  1588. if (c == '>')
  1589. {
  1590. input_stack::get_char();
  1591. context_buffer = "->";
  1592. return RIGHT_ARROW_HEAD;
  1593. }
  1594. context_buffer = "-";
  1595. return '-';
  1596. case '!':
  1597. c = input_stack::peek_char();
  1598. if (c == '=')
  1599. {
  1600. input_stack::get_char();
  1601. context_buffer = "!=";
  1602. return NOTEQUAL;
  1603. }
  1604. context_buffer = "!";
  1605. return '!';
  1606. case '>':
  1607. c = input_stack::peek_char();
  1608. if (c == '=')
  1609. {
  1610. input_stack::get_char();
  1611. context_buffer = ">=";
  1612. return GREATEREQUAL;
  1613. }
  1614. context_buffer = ">";
  1615. return '>';
  1616. case '=':
  1617. c = input_stack::peek_char();
  1618. if (c == '=')
  1619. {
  1620. input_stack::get_char();
  1621. context_buffer = "==";
  1622. return EQUALEQUAL;
  1623. }
  1624. context_buffer = "=";
  1625. return '=';
  1626. case '&':
  1627. c = input_stack::peek_char();
  1628. if (c == '&')
  1629. {
  1630. input_stack::get_char();
  1631. context_buffer = "&&";
  1632. return ANDAND;
  1633. }
  1634. context_buffer = "&";
  1635. return '&';
  1636. case '|':
  1637. c = input_stack::peek_char();
  1638. if (c == '|')
  1639. {
  1640. input_stack::get_char();
  1641. context_buffer = "||";
  1642. return OROR;
  1643. }
  1644. context_buffer = "|";
  1645. return '|';
  1646. default:
  1647. if (c != EOF && csalpha(c))
  1648. {
  1649. token_buffer.clear();
  1650. token_buffer = c;
  1651. for (;;)
  1652. {
  1653. c = input_stack::peek_char();
  1654. if (c == EOF || (!csalnum(c) && c != '_'))
  1655. break;
  1656. input_stack::get_char();
  1657. token_buffer += char(c);
  1658. }
  1659. int tok = lookup_keyword(token_buffer.contents(),
  1660. token_buffer.length());
  1661. if (tok != 0)
  1662. {
  1663. context_buffer = token_buffer;
  1664. return tok;
  1665. }
  1666. char *def = 0;
  1667. if (lookup_flag)
  1668. {
  1669. token_buffer += '\0';
  1670. def = macro_table.lookup(token_buffer.contents());
  1671. token_buffer.set_length(token_buffer.length() - 1);
  1672. if (def)
  1673. {
  1674. if (c == '(')
  1675. {
  1676. input_stack::get_char();
  1677. interpolate_macro_with_args(def);
  1678. }
  1679. else
  1680. input_stack::push(new macro_input(def));
  1681. }
  1682. }
  1683. if (!def)
  1684. {
  1685. context_buffer = token_buffer;
  1686. if (csupper(token_buffer[0]))
  1687. return LABEL;
  1688. else
  1689. return VARIABLE;
  1690. }
  1691. }
  1692. else
  1693. {
  1694. context_buffer = char(c);
  1695. return (unsigned char)c;
  1696. }
  1697. break;
  1698. }
  1699. }
  1700. }
  1701. static int
  1702. get_delimited(void)
  1703. {
  1704. token_buffer.clear();
  1705. int c = input_stack::get_char();
  1706. while (c == ' ' || c == '\t' || c == '\n')
  1707. c = input_stack::get_char();
  1708. if (c == EOF)
  1709. {
  1710. lex_error("missing delimiter");
  1711. return 0;
  1712. }
  1713. context_buffer = char(c);
  1714. int had_newline = 0;
  1715. int start = c;
  1716. int level = 0;
  1717. enum { NORMAL, IN_STRING, IN_STRING_QUOTED, DELIM_END } state = NORMAL;
  1718. for (;;)
  1719. {
  1720. c = input_stack::get_char();
  1721. if (c == EOF)
  1722. {
  1723. lex_error("missing closing delimiter");
  1724. return 0;
  1725. }
  1726. if (c == '\n')
  1727. had_newline = 1;
  1728. else if (!had_newline)
  1729. context_buffer += char(c);
  1730. switch (state)
  1731. {
  1732. case NORMAL:
  1733. if (start == '{')
  1734. {
  1735. if (c == '{')
  1736. {
  1737. level++;
  1738. break;
  1739. }
  1740. if (c == '}')
  1741. {
  1742. if (--level < 0)
  1743. state = DELIM_END;
  1744. break;
  1745. }
  1746. }
  1747. else
  1748. {
  1749. if (c == start)
  1750. {
  1751. state = DELIM_END;
  1752. break;
  1753. }
  1754. }
  1755. if (c == '"')
  1756. state = IN_STRING;
  1757. break;
  1758. case IN_STRING_QUOTED:
  1759. if (c == '\n')
  1760. state = NORMAL;
  1761. else
  1762. state = IN_STRING;
  1763. break;
  1764. case IN_STRING:
  1765. if (c == '"' || c == '\n')
  1766. state = NORMAL;
  1767. else if (c == '\\')
  1768. state = IN_STRING_QUOTED;
  1769. break;
  1770. case DELIM_END:
  1771. // This case is just to shut cfront 2.0 up.
  1772. default:
  1773. assert(0);
  1774. }
  1775. if (state == DELIM_END)
  1776. break;
  1777. token_buffer += c;
  1778. }
  1779. return 1;
  1780. }
  1781. static void
  1782. do_define(void)
  1783. {
  1784. int t = get_token(0); // do not expand what we are defining
  1785. if (t != VARIABLE && t != LABEL)
  1786. {
  1787. lex_error("can only define variable or placename");
  1788. return;
  1789. }
  1790. token_buffer += '\0';
  1791. string nm = token_buffer;
  1792. const char *name = nm.contents();
  1793. if (!get_delimited())
  1794. return;
  1795. token_buffer += '\0';
  1796. macro_table.define(name, strsave(token_buffer.contents()));
  1797. }
  1798. static void
  1799. do_undef(void)
  1800. {
  1801. int t = get_token(0); // do not expand what we are undefining
  1802. if (t != VARIABLE && t != LABEL)
  1803. {
  1804. lex_error("can only define variable or placename");
  1805. return;
  1806. }
  1807. token_buffer += '\0';
  1808. macro_table.define(token_buffer.contents(), 0);
  1809. }
  1810. void
  1811. do_for(char *var, double from, double to, int by_is_multiplicative,
  1812. double by, char *body)
  1813. {
  1814. define_variable(var, from);
  1815. if (from <= to)
  1816. input_stack::push(new for_input(var, to, by_is_multiplicative, by, body));
  1817. }
  1818. void
  1819. do_copy(const char *filename)
  1820. {
  1821. errno = 0;
  1822. FILE *fp = fopen(filename, "r");
  1823. if (fp == 0)
  1824. {
  1825. lex_error("can't open `%1': %2", filename, strerror(errno));
  1826. return;
  1827. }
  1828. input_stack::push(new file_input(fp, filename));
  1829. }
  1830. void
  1831. copy_file_thru(const char *filename, const char *body, const char *until)
  1832. {
  1833. errno = 0;
  1834. FILE *fp = fopen(filename, "r");
  1835. if (fp == 0)
  1836. {
  1837. lex_error("can't open `%1': %2", filename, strerror(errno));
  1838. return;
  1839. }
  1840. input *in = new copy_file_thru_input(new simple_file_input(fp, filename),
  1841. body, until);
  1842. input_stack::push(in);
  1843. }
  1844. void
  1845. copy_rest_thru(const char *body, const char *until)
  1846. {
  1847. input_stack::push(new copy_rest_thru_input(body, until));
  1848. }
  1849. void
  1850. push_body(const char *s)
  1851. {
  1852. input_stack::push(new char_input('\n'));
  1853. input_stack::push(new macro_input(s));
  1854. }
  1855. static char *
  1856. get_thru_arg(void)
  1857. {
  1858. int c = input_stack::peek_char();
  1859. while (c == ' ')
  1860. {
  1861. input_stack::get_char();
  1862. c = input_stack::peek_char();
  1863. }
  1864. if (c != EOF && csalpha(c))
  1865. {
  1866. // looks like a macro
  1867. input_stack::get_char();
  1868. token_buffer = c;
  1869. for (;;)
  1870. {
  1871. c = input_stack::peek_char();
  1872. if (c == EOF || (!csalnum(c) && c != '_'))
  1873. break;
  1874. input_stack::get_char();
  1875. token_buffer += char(c);
  1876. }
  1877. context_buffer = token_buffer;
  1878. token_buffer += '\0';
  1879. char *def = macro_table.lookup(token_buffer.contents());
  1880. if (def)
  1881. return strsave(def);
  1882. // I guess it wasn't a macro after all; so push the macro name back.
  1883. // -2 because we added a '\0'
  1884. for (int i = token_buffer.length() - 2; i >= 0; i--)
  1885. input_stack::push_back(token_buffer[i]);
  1886. }
  1887. if (get_delimited())
  1888. {
  1889. token_buffer += '\0';
  1890. return strsave(token_buffer.contents());
  1891. }
  1892. else
  1893. return 0;
  1894. }
  1895. static char *
  1896. process_body(const char *body)
  1897. {
  1898. char *s = strsave(body);
  1899. int j = 0;
  1900. for (int i = 0; s[i] != '\0'; i++)
  1901. if (s[i] == '$' && s[i+1] >= '0' && s[i+1] <= '9')
  1902. {
  1903. if (s[i+1] != '0')
  1904. s[j++] = ARG1 + s[++i] - '1';
  1905. }
  1906. else
  1907. s[j++] = s[i];
  1908. s[j] = '\0';
  1909. return s;
  1910. }
  1911. void
  1912. do_lookahead(void)
  1913. {
  1914. if (lookahead_token == -1)
  1915. {
  1916. old_context_buffer = context_buffer;
  1917. lookahead_token = get_token(1);
  1918. }
  1919. }
  1920. int
  1921. yylex(void)
  1922. {
  1923. if (delim_flag)
  1924. {
  1925. assert(lookahead_token == -1);
  1926. if (delim_flag == 2)
  1927. {
  1928. if ((yylval.str = get_thru_arg()) != 0)
  1929. return DELIMITED;
  1930. else
  1931. return 0;
  1932. }
  1933. else
  1934. {
  1935. if (get_delimited())
  1936. {
  1937. token_buffer += '\0';
  1938. yylval.str = strsave(token_buffer.contents());
  1939. return DELIMITED;
  1940. }
  1941. else
  1942. return 0;
  1943. }
  1944. }
  1945. for (;;)
  1946. {
  1947. int t;
  1948. if (lookahead_token >= 0)
  1949. {
  1950. t = lookahead_token;
  1951. lookahead_token = -1;
  1952. }
  1953. else
  1954. t = get_token(1);
  1955. switch (t)
  1956. {
  1957. case '\n':
  1958. return ';';
  1959. case EOF:
  1960. return 0;
  1961. case DEFINE:
  1962. do_define();
  1963. break;
  1964. case UNDEF:
  1965. do_undef();
  1966. break;
  1967. case ORDINAL:
  1968. yylval.n = token_int;
  1969. return t;
  1970. case NUMBER:
  1971. yylval.x = token_double;
  1972. return t;
  1973. case COMMAND_LINE:
  1974. case TEXT:
  1975. token_buffer += '\0';
  1976. if (!input_stack::get_location (&yylval.lstr.filename,
  1977. &yylval.lstr.lineno))
  1978. {
  1979. yylval.lstr.filename = 0;
  1980. yylval.lstr.lineno = -1;
  1981. }
  1982. yylval.lstr.str = strsave(token_buffer.contents());
  1983. return t;
  1984. case LABEL:
  1985. case VARIABLE:
  1986. token_buffer += '\0';
  1987. yylval.str = strsave(token_buffer.contents());
  1988. return t;
  1989. case LEFT:
  1990. // change LEFT to LEFT_CORNER when followed by OF
  1991. old_context_buffer = context_buffer;
  1992. lookahead_token = get_token(1);
  1993. if (lookahead_token == OF)
  1994. return LEFT_CORNER;
  1995. else
  1996. return t;
  1997. case RIGHT:
  1998. // change RIGHT to RIGHT_CORNER when followed by OF
  1999. old_context_buffer = context_buffer;
  2000. lookahead_token = get_token(1);
  2001. if (lookahead_token == OF)
  2002. return RIGHT_CORNER;
  2003. else
  2004. return t;
  2005. case UPPER:
  2006. // recognise UPPER only before LEFT or RIGHT
  2007. old_context_buffer = context_buffer;
  2008. lookahead_token = get_token(1);
  2009. if (lookahead_token != LEFT && lookahead_token != RIGHT)
  2010. {
  2011. yylval.str = strsave("upper");
  2012. return VARIABLE;
  2013. }
  2014. else
  2015. return t;
  2016. case LOWER:
  2017. // recognise LOWER only before LEFT or RIGHT
  2018. old_context_buffer = context_buffer;
  2019. lookahead_token = get_token(1);
  2020. if (lookahead_token != LEFT && lookahead_token != RIGHT)
  2021. {
  2022. yylval.str = strsave("lower");
  2023. return VARIABLE;
  2024. }
  2025. else
  2026. return t;
  2027. case TOP:
  2028. // recognise TOP only before OF
  2029. old_context_buffer = context_buffer;
  2030. lookahead_token = get_token(1);
  2031. if (lookahead_token != OF)
  2032. {
  2033. yylval.str = strsave("top");
  2034. return VARIABLE;
  2035. }
  2036. else
  2037. return t;
  2038. case BOTTOM:
  2039. // recognise BOTTOM only before OF
  2040. old_context_buffer = context_buffer;
  2041. lookahead_token = get_token(1);
  2042. if (lookahead_token != OF)
  2043. {
  2044. yylval.str = strsave("bottom");
  2045. return VARIABLE;
  2046. }
  2047. else
  2048. return t;
  2049. case CENTER:
  2050. // recognise CENTER only before OF
  2051. old_context_buffer = context_buffer;
  2052. lookahead_token = get_token(1);
  2053. if (lookahead_token != OF)
  2054. {
  2055. yylval.str = strsave("center");
  2056. return VARIABLE;
  2057. }
  2058. else
  2059. return t;
  2060. case START:
  2061. // recognise START only before OF
  2062. old_context_buffer = context_buffer;
  2063. lookahead_token = get_token(1);
  2064. if (lookahead_token != OF)
  2065. {
  2066. yylval.str = strsave("start");
  2067. return VARIABLE;
  2068. }
  2069. else
  2070. return t;
  2071. case END:
  2072. // recognise END only before OF
  2073. old_context_buffer = context_buffer;
  2074. lookahead_token = get_token(1);
  2075. if (lookahead_token != OF)
  2076. {
  2077. yylval.str = strsave("end");
  2078. return VARIABLE;
  2079. }
  2080. else
  2081. return t;
  2082. default:
  2083. return t;
  2084. }
  2085. }
  2086. }
  2087. void
  2088. lex_error(const char *message, const errarg &arg1,
  2089. const errarg &arg2, const errarg &arg3)
  2090. {
  2091. const char *filename;
  2092. int lineno;
  2093. if (!input_stack::get_location (&filename, &lineno))
  2094. error(message, arg1, arg2, arg3);
  2095. else
  2096. error_with_file_and_line(filename, lineno, message, arg1, arg2, arg3);
  2097. }
  2098. void
  2099. lex_warning(const char *message, const errarg &arg1,
  2100. const errarg &arg2, const errarg &arg3)
  2101. {
  2102. const char *filename;
  2103. int lineno;
  2104. if (!input_stack::get_location (&filename, &lineno))
  2105. warning(message, arg1, arg2, arg3);
  2106. else
  2107. warning_with_file_and_line(filename, lineno, message, arg1, arg2, arg3);
  2108. }
  2109. void
  2110. yyerror(const char *s)
  2111. {
  2112. const char *filename;
  2113. int lineno;
  2114. const char *context = 0;
  2115. if (lookahead_token == -1)
  2116. {
  2117. if (context_buffer.length() > 0)
  2118. {
  2119. context_buffer += '\0';
  2120. context = context_buffer.contents();
  2121. }
  2122. }
  2123. else
  2124. {
  2125. if (old_context_buffer.length() > 0)
  2126. {
  2127. old_context_buffer += '\0';
  2128. context = old_context_buffer.contents();
  2129. }
  2130. }
  2131. if (!input_stack::get_location (&filename, &lineno))
  2132. {
  2133. if (context)
  2134. {
  2135. if (context[0] == '\n' && context[1] == '\0')
  2136. error("%1 before newline", s);
  2137. else
  2138. error("%1 before `%2'", s, context);
  2139. }
  2140. else
  2141. error("%1 at end of picture", s);
  2142. }
  2143. else
  2144. {
  2145. if (context)
  2146. {
  2147. if (context[0] == '\n' && context[1] == '\0')
  2148. error_with_file_and_line(filename, lineno, "%1 before newline", s);
  2149. else
  2150. error_with_file_and_line(filename, lineno, "%1 before `%2'",
  2151. s, context);
  2152. }
  2153. else
  2154. error_with_file_and_line(filename, lineno, "%1 at end of picture", s);
  2155. }
  2156. }