macbody 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804
  1. long
  2. getnsn(void)
  3. {
  4. long n;
  5. int c;
  6. c = getnsc();
  7. if(c < '0' || c > '9')
  8. return -1;
  9. n = 0;
  10. while(c >= '0' && c <= '9') {
  11. n = n*10 + c-'0';
  12. c = getc();
  13. }
  14. unget(c);
  15. return n;
  16. }
  17. Sym*
  18. getsym(void)
  19. {
  20. int c;
  21. char *cp;
  22. c = getnsc();
  23. if(!isalpha(c) && c != '_') {
  24. unget(c);
  25. return S;
  26. }
  27. for(cp = symb;;) {
  28. if(cp <= symb+NSYMB-4)
  29. *cp++ = c;
  30. c = getc();
  31. if(isalnum(c) || c == '_')
  32. continue;
  33. unget(c);
  34. break;
  35. }
  36. *cp = 0;
  37. if(cp > symb+NSYMB-4)
  38. yyerror("symbol too large: %s", symb);
  39. return lookup();
  40. }
  41. int
  42. getcom(void)
  43. {
  44. int c;
  45. for(;;) {
  46. c = getnsc();
  47. if(c != '/')
  48. break;
  49. c = getc();
  50. if(c == '/') {
  51. while(c != '\n')
  52. c = getc();
  53. break;
  54. }
  55. if(c != '*')
  56. break;
  57. c = getc();
  58. for(;;) {
  59. if(c == '*') {
  60. c = getc();
  61. if(c != '/')
  62. continue;
  63. c = getc();
  64. break;
  65. }
  66. if(c == '\n') {
  67. yyerror("comment across newline");
  68. break;
  69. }
  70. c = getc();
  71. }
  72. if(c == '\n')
  73. break;
  74. }
  75. return c;
  76. }
  77. void
  78. dodefine(char *cp)
  79. {
  80. Sym *s;
  81. char *p;
  82. long l;
  83. strcpy(symb, cp);
  84. p = strchr(symb, '=');
  85. if(p) {
  86. *p++ = 0;
  87. s = lookup();
  88. l = strlen(p) + 2; /* +1 null, +1 nargs */
  89. while(l & 3)
  90. l++;
  91. while(nhunk < l)
  92. gethunk();
  93. *hunk = 0;
  94. strcpy(hunk+1, p);
  95. s->macro = hunk;
  96. hunk += l;
  97. nhunk -= l;
  98. } else {
  99. s = lookup();
  100. s->macro = "\0001"; /* \000 is nargs */
  101. }
  102. if(debug['m'])
  103. print("#define (-D) %s %s\n", s->name, s->macro+1);
  104. }
  105. struct
  106. {
  107. char *macname;
  108. void (*macf)(void);
  109. } mactab[] =
  110. {
  111. "ifdef", 0, /* macif(0) */
  112. "ifndef", 0, /* macif(1) */
  113. "else", 0, /* macif(2) */
  114. "line", maclin,
  115. "define", macdef,
  116. "include", macinc,
  117. "undef", macund,
  118. "pragma", macprag,
  119. "endif", macend,
  120. 0
  121. };
  122. void
  123. domacro(void)
  124. {
  125. int i;
  126. Sym *s;
  127. s = getsym();
  128. if(s == S)
  129. s = slookup("endif");
  130. for(i=0; mactab[i].macname; i++)
  131. if(strcmp(s->name, mactab[i].macname) == 0) {
  132. if(mactab[i].macf)
  133. (*mactab[i].macf)();
  134. else
  135. macif(i);
  136. return;
  137. }
  138. yyerror("unknown #: %s", s->name);
  139. macend();
  140. }
  141. void
  142. macund(void)
  143. {
  144. Sym *s;
  145. s = getsym();
  146. macend();
  147. if(s == S) {
  148. yyerror("syntax in #undef");
  149. return;
  150. }
  151. s->macro = 0;
  152. }
  153. #define NARG 25
  154. void
  155. macdef(void)
  156. {
  157. Sym *s, *a;
  158. char *args[NARG], *np, *base;
  159. int n, i, c, len;
  160. s = getsym();
  161. if(s == S)
  162. goto bad;
  163. if(s->macro)
  164. yyerror("macro redefined: %s", s->name);
  165. c = getc();
  166. n = -1;
  167. if(c == '(') {
  168. n++;
  169. c = getnsc();
  170. if(c != ')') {
  171. unget(c);
  172. for(;;) {
  173. a = getsym();
  174. if(a == S)
  175. goto bad;
  176. if(n >= NARG) {
  177. yyerror("too many arguments in #define: %s", s->name);
  178. goto bad;
  179. }
  180. args[n++] = a->name;
  181. c = getnsc();
  182. if(c == ')')
  183. break;
  184. if(c != ',')
  185. goto bad;
  186. }
  187. }
  188. c = getc();
  189. }
  190. if(isspace(c))
  191. if(c != '\n')
  192. c = getnsc();
  193. base = hunk;
  194. len = 1;
  195. for(;;) {
  196. if(isalpha(c) || c == '_') {
  197. np = symb;
  198. *np++ = c;
  199. c = getc();
  200. while(isalnum(c) || c == '_') {
  201. *np++ = c;
  202. c = getc();
  203. }
  204. *np = 0;
  205. for(i=0; i<n; i++)
  206. if(strcmp(symb, args[i]) == 0)
  207. break;
  208. if(i >= n) {
  209. i = strlen(symb);
  210. base = allocn(base, len, i);
  211. memcpy(base+len, symb, i);
  212. len += i;
  213. continue;
  214. }
  215. base = allocn(base, len, 2);
  216. base[len++] = '#';
  217. base[len++] = 'a' + i;
  218. continue;
  219. }
  220. if(c == '/') {
  221. c = getc();
  222. if(c == '/'){
  223. c = getc();
  224. for(;;) {
  225. if(c == '\n')
  226. break;
  227. c = getc();
  228. }
  229. continue;
  230. }
  231. if(c == '*'){
  232. c = getc();
  233. for(;;) {
  234. if(c == '*') {
  235. c = getc();
  236. if(c != '/')
  237. continue;
  238. c = getc();
  239. break;
  240. }
  241. if(c == '\n') {
  242. yyerror("comment and newline in define: %s", s->name);
  243. break;
  244. }
  245. c = getc();
  246. }
  247. continue;
  248. }
  249. base = allocn(base, len, 1);
  250. base[len++] = '/';
  251. continue;
  252. }
  253. if(c == '\\') {
  254. c = getc();
  255. if(c == '\n') {
  256. c = getc();
  257. continue;
  258. }
  259. else if(c == '\r') {
  260. c = getc();
  261. if(c == '\n') {
  262. c = getc();
  263. continue;
  264. }
  265. }
  266. base = allocn(base, len, 1);
  267. base[len++] = '\\';
  268. continue;
  269. }
  270. if(c == '\n')
  271. break;
  272. if(c == '#')
  273. if(n > 0) {
  274. base = allocn(base, len, 1);
  275. base[len++] = c;
  276. }
  277. base = allocn(base, len, 1);
  278. base[len++] = c;
  279. c = ((--fi.c < 0)? filbuf(): (*fi.p++ & 0xff));
  280. if(c == '\n')
  281. lineno++;
  282. if(c == -1) {
  283. yyerror("eof in a macro: %s", s->name);
  284. break;
  285. }
  286. }
  287. do {
  288. base = allocn(base, len, 1);
  289. base[len++] = 0;
  290. } while(len & 3);
  291. *base = n+1;
  292. s->macro = base;
  293. if(debug['m'])
  294. print("#define %s %s\n", s->name, s->macro+1);
  295. return;
  296. bad:
  297. if(s == S)
  298. yyerror("syntax in #define");
  299. else
  300. yyerror("syntax in #define: %s", s->name);
  301. macend();
  302. }
  303. void
  304. macexpand(Sym *s, char *b)
  305. {
  306. char buf[2000];
  307. int n, l, c, nargs;
  308. char *arg[NARG], *cp, *ob, *ecp;
  309. ob = b;
  310. nargs = *s->macro - 1;
  311. if(nargs < 0) {
  312. strcpy(b, s->macro+1);
  313. if(debug['m'])
  314. print("#expand %s %s\n", s->name, ob);
  315. return;
  316. }
  317. c = getnsc();
  318. if(c != '(')
  319. goto bad;
  320. n = 0;
  321. c = getc();
  322. if(c != ')') {
  323. unget(c);
  324. l = 0;
  325. cp = buf;
  326. ecp = cp + sizeof(buf)-4;
  327. arg[n++] = cp;
  328. for(;;) {
  329. if(cp >= ecp)
  330. goto toobig;
  331. c = getc();
  332. if(c == '"')
  333. for(;;) {
  334. if(cp >= ecp)
  335. goto toobig;
  336. *cp++ = c;
  337. c = getc();
  338. if(c == '\\') {
  339. *cp++ = c;
  340. c = getc();
  341. continue;
  342. }
  343. if(c == '\n')
  344. goto bad;
  345. if(c == '"')
  346. break;
  347. }
  348. if(c == '\'')
  349. for(;;) {
  350. if(cp >= ecp)
  351. goto toobig;
  352. *cp++ = c;
  353. c = getc();
  354. if(c == '\\') {
  355. *cp++ = c;
  356. c = getc();
  357. continue;
  358. }
  359. if(c == '\n')
  360. goto bad;
  361. if(c == '\'')
  362. break;
  363. }
  364. if(c == '/') {
  365. c = getc();
  366. switch(c) {
  367. case '*':
  368. for(;;) {
  369. c = getc();
  370. if(c == '*') {
  371. c = getc();
  372. if(c == '/')
  373. break;
  374. }
  375. }
  376. *cp++ = ' ';
  377. continue;
  378. case '/':
  379. while((c = getc()) != '\n')
  380. ;
  381. break;
  382. default:
  383. unget(c);
  384. c = '/';
  385. }
  386. }
  387. if(l == 0) {
  388. if(c == ',') {
  389. *cp++ = 0;
  390. arg[n++] = cp;
  391. if(n > nargs)
  392. break;
  393. continue;
  394. }
  395. if(c == ')')
  396. break;
  397. }
  398. if(c == '\n')
  399. c = ' ';
  400. *cp++ = c;
  401. if(c == '(')
  402. l++;
  403. if(c == ')')
  404. l--;
  405. }
  406. *cp = 0;
  407. }
  408. if(n != nargs) {
  409. yyerror("argument mismatch expanding: %s", s->name);
  410. *b = 0;
  411. return;
  412. }
  413. cp = s->macro+1;
  414. for(;;) {
  415. c = *cp++;
  416. if(c != '#') {
  417. *b++ = c;
  418. if(c == 0)
  419. break;
  420. continue;
  421. }
  422. c = *cp++;
  423. if(c == 0)
  424. goto bad;
  425. if(c == '#') {
  426. *b++ = c;
  427. continue;
  428. }
  429. c -= 'a';
  430. if(c < 0 || c >= n)
  431. continue;
  432. strcpy(b, arg[c]);
  433. b += strlen(arg[c]);
  434. }
  435. *b = 0;
  436. if(debug['m'])
  437. print("#expand %s %s\n", s->name, ob);
  438. return;
  439. bad:
  440. yyerror("syntax in macro expansion: %s", s->name);
  441. *b = 0;
  442. return;
  443. toobig:
  444. yyerror("too much text in macro expansion: %s", s->name);
  445. *b = 0;
  446. }
  447. void
  448. macinc(void)
  449. {
  450. int c0, c, i, f;
  451. char str[STRINGSZ], *hp;
  452. c0 = getnsc();
  453. if(c0 != '"') {
  454. c = c0;
  455. if(c0 != '<')
  456. goto bad;
  457. c0 = '>';
  458. }
  459. for(hp = str;;) {
  460. c = getc();
  461. if(c == c0)
  462. break;
  463. if(c == '\n')
  464. goto bad;
  465. *hp++ = c;
  466. }
  467. *hp = 0;
  468. c = getcom();
  469. if(c != '\n')
  470. goto bad;
  471. f = -1;
  472. for(i=0; i<ninclude; i++) {
  473. if(i == 0 && c0 == '>')
  474. continue;
  475. strcpy(symb, include[i]);
  476. strcat(symb, "/");
  477. if(strcmp(symb, "./") == 0)
  478. symb[0] = 0;
  479. strcat(symb, str);
  480. f = open(symb, 0);
  481. if(f >= 0)
  482. break;
  483. }
  484. if(f < 0)
  485. strcpy(symb, str);
  486. c = strlen(symb) + 1;
  487. while(c & 3)
  488. c++;
  489. while(nhunk < c)
  490. gethunk();
  491. hp = hunk;
  492. memcpy(hunk, symb, c);
  493. nhunk -= c;
  494. hunk += c;
  495. newio();
  496. pushio();
  497. newfile(hp, f);
  498. return;
  499. bad:
  500. unget(c);
  501. yyerror("syntax in #include");
  502. macend();
  503. }
  504. void
  505. maclin(void)
  506. {
  507. char *cp;
  508. int c;
  509. long n;
  510. n = getnsn();
  511. c = getc();
  512. if(n < 0)
  513. goto bad;
  514. for(;;) {
  515. if(c == ' ' || c == '\t') {
  516. c = getc();
  517. continue;
  518. }
  519. if(c == '"')
  520. break;
  521. if(c == '\n') {
  522. strcpy(symb, "<noname>");
  523. goto nn;
  524. }
  525. goto bad;
  526. }
  527. cp = symb;
  528. for(;;) {
  529. c = getc();
  530. if(c == '"')
  531. break;
  532. *cp++ = c;
  533. }
  534. *cp = 0;
  535. c = getcom();
  536. if(c != '\n')
  537. goto bad;
  538. nn:
  539. c = strlen(symb) + 1;
  540. while(c & 3)
  541. c++;
  542. while(nhunk < c)
  543. gethunk();
  544. cp = hunk;
  545. memcpy(hunk, symb, c);
  546. nhunk -= c;
  547. hunk += c;
  548. linehist(cp, n);
  549. return;
  550. bad:
  551. unget(c);
  552. yyerror("syntax in #line");
  553. macend();
  554. }
  555. void
  556. macif(int f)
  557. {
  558. int c, l, bol;
  559. Sym *s;
  560. if(f == 2)
  561. goto skip;
  562. s = getsym();
  563. if(s == S)
  564. goto bad;
  565. if(getcom() != '\n')
  566. goto bad;
  567. if((s->macro != 0) ^ f)
  568. return;
  569. skip:
  570. bol = 1;
  571. l = 0;
  572. for(;;) {
  573. c = getc();
  574. if(c != '#') {
  575. if(!isspace(c))
  576. bol = 0;
  577. if(c == '\n')
  578. bol = 1;
  579. continue;
  580. }
  581. if(!bol)
  582. continue;
  583. s = getsym();
  584. if(s == S)
  585. continue;
  586. if(strcmp(s->name, "endif") == 0) {
  587. if(l) {
  588. l--;
  589. continue;
  590. }
  591. macend();
  592. return;
  593. }
  594. if(strcmp(s->name, "ifdef") == 0 || strcmp(s->name, "ifndef") == 0) {
  595. l++;
  596. continue;
  597. }
  598. if(l == 0 && f != 2 && strcmp(s->name, "else") == 0) {
  599. macend();
  600. return;
  601. }
  602. }
  603. bad:
  604. yyerror("syntax in #if(n)def");
  605. macend();
  606. }
  607. void
  608. macprag(void)
  609. {
  610. Sym *s;
  611. int c0, c;
  612. char *hp;
  613. Hist *h;
  614. s = getsym();
  615. if(s && strcmp(s->name, "lib") == 0)
  616. goto praglib;
  617. if(s && strcmp(s->name, "pack") == 0) {
  618. pragpack();
  619. return;
  620. }
  621. if(s && strcmp(s->name, "fpround") == 0) {
  622. pragfpround();
  623. return;
  624. }
  625. if(s && strcmp(s->name, "profile") == 0) {
  626. pragprofile();
  627. return;
  628. }
  629. if(s && strcmp(s->name, "varargck") == 0) {
  630. pragvararg();
  631. return;
  632. }
  633. if(s && strcmp(s->name, "incomplete") == 0) {
  634. pragincomplete();
  635. return;
  636. }
  637. while(getnsc() != '\n')
  638. ;
  639. return;
  640. praglib:
  641. c0 = getnsc();
  642. if(c0 != '"') {
  643. c = c0;
  644. if(c0 != '<')
  645. goto bad;
  646. c0 = '>';
  647. }
  648. for(hp = symb;;) {
  649. c = getc();
  650. if(c == c0)
  651. break;
  652. if(c == '\n')
  653. goto bad;
  654. *hp++ = c;
  655. }
  656. *hp = 0;
  657. c = getcom();
  658. if(c != '\n')
  659. goto bad;
  660. /*
  661. * put pragma-line in as a funny history
  662. */
  663. c = strlen(symb) + 1;
  664. while(c & 3)
  665. c++;
  666. while(nhunk < c)
  667. gethunk();
  668. hp = hunk;
  669. memcpy(hunk, symb, c);
  670. nhunk -= c;
  671. hunk += c;
  672. h = alloc(sizeof(Hist));
  673. h->name = hp;
  674. h->line = lineno;
  675. h->offset = -1;
  676. h->link = H;
  677. if(ehist == H) {
  678. hist = h;
  679. ehist = h;
  680. return;
  681. }
  682. ehist->link = h;
  683. ehist = h;
  684. return;
  685. bad:
  686. unget(c);
  687. yyerror("syntax in #pragma lib");
  688. macend();
  689. }
  690. void
  691. macend(void)
  692. {
  693. int c;
  694. for(;;) {
  695. c = getnsc();
  696. if(c < 0 || c == '\n')
  697. return;
  698. }
  699. }
  700. void
  701. linehist(char *f, int offset)
  702. {
  703. Hist *h;
  704. /*
  705. * overwrite the last #line directive if
  706. * no alloc has happened since the last one
  707. */
  708. if(newflag == 0 && ehist != H && offset != 0 && ehist->offset != 0)
  709. if(f && ehist->name && strcmp(f, ehist->name) == 0) {
  710. ehist->line = lineno;
  711. ehist->offset = offset;
  712. return;
  713. }
  714. if(debug['f'])
  715. if(f) {
  716. if(offset)
  717. print("%4ld: %s (#line %d)\n", lineno, f, offset);
  718. else
  719. print("%4ld: %s\n", lineno, f);
  720. } else
  721. print("%4ld: <pop>\n", lineno);
  722. newflag = 0;
  723. h = alloc(sizeof(Hist));
  724. h->name = f;
  725. h->line = lineno;
  726. h->offset = offset;
  727. h->link = H;
  728. if(ehist == H) {
  729. hist = h;
  730. ehist = h;
  731. return;
  732. }
  733. ehist->link = h;
  734. ehist = h;
  735. }
  736. void
  737. gethunk(void)
  738. {
  739. char *h;
  740. long nh;
  741. nh = NHUNK;
  742. if(thunk >= 10L*NHUNK)
  743. nh = 10L*NHUNK;
  744. h = (char*)mysbrk(nh);
  745. if(h == (char*)-1) {
  746. yyerror("out of memory");
  747. errorexit();
  748. }
  749. hunk = h;
  750. nhunk = nh;
  751. thunk += nh;
  752. }