macbody 11 KB

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