macbody 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790
  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. base = allocn(base, len, 1);
  260. base[len++] = '\\';
  261. continue;
  262. }
  263. if(c == '\n')
  264. break;
  265. if(c == '#')
  266. if(n > 0) {
  267. base = allocn(base, len, 1);
  268. base[len++] = c;
  269. }
  270. base = allocn(base, len, 1);
  271. base[len++] = c;
  272. c = ((--fi.c < 0)? filbuf(): (*fi.p++ & 0xff));
  273. if(c == '\n')
  274. lineno++;
  275. if(c == -1) {
  276. yyerror("eof in a macro: %s", s->name);
  277. break;
  278. }
  279. }
  280. do {
  281. base = allocn(base, len, 1);
  282. base[len++] = 0;
  283. } while(len & 3);
  284. *base = n+1;
  285. s->macro = base;
  286. if(debug['m'])
  287. print("#define %s %s\n", s->name, s->macro+1);
  288. return;
  289. bad:
  290. if(s == S)
  291. yyerror("syntax in #define");
  292. else
  293. yyerror("syntax in #define: %s", s->name);
  294. macend();
  295. }
  296. void
  297. macexpand(Sym *s, char *b)
  298. {
  299. char buf[2000];
  300. int n, l, c, nargs;
  301. char *arg[NARG], *cp, *ob, *ecp;
  302. ob = b;
  303. nargs = *s->macro - 1;
  304. if(nargs < 0) {
  305. strcpy(b, s->macro+1);
  306. if(debug['m'])
  307. print("#expand %s %s\n", s->name, ob);
  308. return;
  309. }
  310. c = getnsc();
  311. if(c != '(')
  312. goto bad;
  313. n = 0;
  314. c = getc();
  315. if(c != ')') {
  316. unget(c);
  317. l = 0;
  318. cp = buf;
  319. ecp = cp + sizeof(buf)-4;
  320. arg[n++] = cp;
  321. for(;;) {
  322. if(cp >= ecp)
  323. goto toobig;
  324. c = getc();
  325. if(c == '"')
  326. for(;;) {
  327. if(cp >= ecp)
  328. goto toobig;
  329. *cp++ = c;
  330. c = getc();
  331. if(c == '\\') {
  332. *cp++ = c;
  333. c = getc();
  334. continue;
  335. }
  336. if(c == '\n')
  337. goto bad;
  338. if(c == '"')
  339. break;
  340. }
  341. if(c == '\'')
  342. for(;;) {
  343. if(cp >= ecp)
  344. goto toobig;
  345. *cp++ = c;
  346. c = getc();
  347. if(c == '\\') {
  348. *cp++ = c;
  349. c = getc();
  350. continue;
  351. }
  352. if(c == '\n')
  353. goto bad;
  354. if(c == '\'')
  355. break;
  356. }
  357. if(c == '/') {
  358. c = getc();
  359. switch(c) {
  360. case '*':
  361. for(;;) {
  362. c = getc();
  363. if(c == '*') {
  364. c = getc();
  365. if(c == '/')
  366. break;
  367. }
  368. }
  369. *cp++ = ' ';
  370. continue;
  371. case '/':
  372. while((c = getc()) != '\n')
  373. ;
  374. break;
  375. default:
  376. unget(c);
  377. c = '/';
  378. }
  379. }
  380. if(l == 0) {
  381. if(c == ',') {
  382. *cp++ = 0;
  383. arg[n++] = cp;
  384. if(n > nargs)
  385. break;
  386. continue;
  387. }
  388. if(c == ')')
  389. break;
  390. }
  391. if(c == '\n')
  392. c = ' ';
  393. *cp++ = c;
  394. if(c == '(')
  395. l++;
  396. if(c == ')')
  397. l--;
  398. }
  399. *cp = 0;
  400. }
  401. if(n != nargs) {
  402. yyerror("argument mismatch expanding: %s", s->name);
  403. *b = 0;
  404. return;
  405. }
  406. cp = s->macro+1;
  407. for(;;) {
  408. c = *cp++;
  409. if(c != '#') {
  410. *b++ = c;
  411. if(c == 0)
  412. break;
  413. continue;
  414. }
  415. c = *cp++;
  416. if(c == 0)
  417. goto bad;
  418. if(c == '#') {
  419. *b++ = c;
  420. continue;
  421. }
  422. c -= 'a';
  423. if(c < 0 || c >= n)
  424. continue;
  425. strcpy(b, arg[c]);
  426. b += strlen(arg[c]);
  427. }
  428. *b = 0;
  429. if(debug['m'])
  430. print("#expand %s %s\n", s->name, ob);
  431. return;
  432. bad:
  433. yyerror("syntax in macro expansion: %s", s->name);
  434. *b = 0;
  435. return;
  436. toobig:
  437. yyerror("too much text in macro expansion: %s", s->name);
  438. *b = 0;
  439. }
  440. void
  441. macinc(void)
  442. {
  443. int c0, c, i, f;
  444. char str[STRINGSZ], *hp;
  445. c0 = getnsc();
  446. if(c0 != '"') {
  447. c = c0;
  448. if(c0 != '<')
  449. goto bad;
  450. c0 = '>';
  451. }
  452. for(hp = str;;) {
  453. c = getc();
  454. if(c == c0)
  455. break;
  456. if(c == '\n')
  457. goto bad;
  458. *hp++ = c;
  459. }
  460. *hp = 0;
  461. c = getcom();
  462. if(c != '\n')
  463. goto bad;
  464. f = -1;
  465. for(i=0; i<ninclude; i++) {
  466. if(i == 0 && c0 == '>')
  467. continue;
  468. strcpy(symb, include[i]);
  469. strcat(symb, "/");
  470. if(strcmp(symb, "./") == 0)
  471. symb[0] = 0;
  472. strcat(symb, str);
  473. f = open(symb, 0);
  474. if(f >= 0)
  475. break;
  476. }
  477. if(f < 0)
  478. strcpy(symb, str);
  479. c = strlen(symb) + 1;
  480. while(c & 3)
  481. c++;
  482. while(nhunk < c)
  483. gethunk();
  484. hp = hunk;
  485. memcpy(hunk, symb, c);
  486. nhunk -= c;
  487. hunk += c;
  488. newio();
  489. pushio();
  490. newfile(hp, f);
  491. return;
  492. bad:
  493. unget(c);
  494. yyerror("syntax in #include");
  495. macend();
  496. }
  497. void
  498. maclin(void)
  499. {
  500. char *cp;
  501. int c;
  502. long n;
  503. n = getnsn();
  504. c = getc();
  505. if(n < 0)
  506. goto bad;
  507. for(;;) {
  508. if(c == ' ' || c == '\t') {
  509. c = getc();
  510. continue;
  511. }
  512. if(c == '"')
  513. break;
  514. if(c == '\n') {
  515. strcpy(symb, "<noname>");
  516. goto nn;
  517. }
  518. goto bad;
  519. }
  520. cp = symb;
  521. for(;;) {
  522. c = getc();
  523. if(c == '"')
  524. break;
  525. *cp++ = c;
  526. }
  527. *cp = 0;
  528. c = getcom();
  529. if(c != '\n')
  530. goto bad;
  531. nn:
  532. c = strlen(symb) + 1;
  533. while(c & 3)
  534. c++;
  535. while(nhunk < c)
  536. gethunk();
  537. cp = hunk;
  538. memcpy(hunk, symb, c);
  539. nhunk -= c;
  540. hunk += c;
  541. linehist(cp, n);
  542. return;
  543. bad:
  544. unget(c);
  545. yyerror("syntax in #line");
  546. macend();
  547. }
  548. void
  549. macif(int f)
  550. {
  551. int c, l, bol;
  552. Sym *s;
  553. if(f == 2)
  554. goto skip;
  555. s = getsym();
  556. if(s == S)
  557. goto bad;
  558. if(getcom() != '\n')
  559. goto bad;
  560. if((s->macro != 0) ^ f)
  561. return;
  562. skip:
  563. bol = 1;
  564. l = 0;
  565. for(;;) {
  566. c = getc();
  567. if(c != '#') {
  568. if(!isspace(c))
  569. bol = 0;
  570. if(c == '\n')
  571. bol = 1;
  572. continue;
  573. }
  574. if(!bol)
  575. continue;
  576. s = getsym();
  577. if(s == S)
  578. continue;
  579. if(strcmp(s->name, "endif") == 0) {
  580. if(l) {
  581. l--;
  582. continue;
  583. }
  584. macend();
  585. return;
  586. }
  587. if(strcmp(s->name, "ifdef") == 0 || strcmp(s->name, "ifndef") == 0) {
  588. l++;
  589. continue;
  590. }
  591. if(l == 0 && f != 2 && strcmp(s->name, "else") == 0) {
  592. macend();
  593. return;
  594. }
  595. }
  596. bad:
  597. yyerror("syntax in #if(n)def");
  598. macend();
  599. }
  600. void
  601. macprag(void)
  602. {
  603. Sym *s;
  604. int c0, c;
  605. char *hp;
  606. Hist *h;
  607. s = getsym();
  608. if(s && strcmp(s->name, "lib") == 0)
  609. goto praglib;
  610. if(s && strcmp(s->name, "hjdicks") == 0) {
  611. praghjdicks();
  612. return;
  613. }
  614. if(s && strcmp(s->name, "fpround") == 0) {
  615. pragfpround();
  616. return;
  617. }
  618. if(s && strcmp(s->name, "varargck") == 0) {
  619. pragvararg();
  620. return;
  621. }
  622. while(getnsc() != '\n')
  623. ;
  624. return;
  625. praglib:
  626. c0 = getnsc();
  627. if(c0 != '"') {
  628. c = c0;
  629. if(c0 != '<')
  630. goto bad;
  631. c0 = '>';
  632. }
  633. for(hp = symb;;) {
  634. c = getc();
  635. if(c == c0)
  636. break;
  637. if(c == '\n')
  638. goto bad;
  639. *hp++ = c;
  640. }
  641. *hp = 0;
  642. c = getcom();
  643. if(c != '\n')
  644. goto bad;
  645. /*
  646. * put pragma-line in as a funny history
  647. */
  648. c = strlen(symb) + 1;
  649. while(c & 3)
  650. c++;
  651. while(nhunk < c)
  652. gethunk();
  653. hp = hunk;
  654. memcpy(hunk, symb, c);
  655. nhunk -= c;
  656. hunk += c;
  657. h = alloc(sizeof(Hist));
  658. h->name = hp;
  659. h->line = lineno;
  660. h->offset = -1;
  661. h->link = H;
  662. if(ehist == H) {
  663. hist = h;
  664. ehist = h;
  665. return;
  666. }
  667. ehist->link = h;
  668. ehist = h;
  669. return;
  670. bad:
  671. unget(c);
  672. yyerror("syntax in #pragma lib");
  673. macend();
  674. }
  675. void
  676. macend(void)
  677. {
  678. int c;
  679. for(;;) {
  680. c = getnsc();
  681. if(c < 0 || c == '\n')
  682. return;
  683. }
  684. }
  685. void
  686. linehist(char *f, int offset)
  687. {
  688. Hist *h;
  689. /*
  690. * overwrite the last #line directive if
  691. * no alloc has happened since the last one
  692. */
  693. if(newflag == 0 && ehist != H && offset != 0 && ehist->offset != 0)
  694. if(f && ehist->name && strcmp(f, ehist->name) == 0) {
  695. ehist->line = lineno;
  696. ehist->offset = offset;
  697. return;
  698. }
  699. if(debug['f'])
  700. if(f) {
  701. if(offset)
  702. print("%4ld: %s (#line %d)\n", lineno, f, offset);
  703. else
  704. print("%4ld: %s\n", lineno, f);
  705. } else
  706. print("%4ld: <pop>\n", lineno);
  707. newflag = 0;
  708. h = alloc(sizeof(Hist));
  709. h->name = f;
  710. h->line = lineno;
  711. h->offset = offset;
  712. h->link = H;
  713. if(ehist == H) {
  714. hist = h;
  715. ehist = h;
  716. return;
  717. }
  718. ehist->link = h;
  719. ehist = h;
  720. }
  721. void
  722. gethunk(void)
  723. {
  724. char *h;
  725. long nh;
  726. nh = NHUNK;
  727. if(thunk >= 10L*NHUNK)
  728. nh = 10L*NHUNK;
  729. h = (char*)mysbrk(nh);
  730. if(h == (char*)-1) {
  731. yyerror("out of memory");
  732. errorexit();
  733. }
  734. hunk = h;
  735. nhunk = nh;
  736. thunk += nh;
  737. }