macbody 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824
  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 == '\n')
  435. c = ' ';
  436. if(c != '#') {
  437. *b++ = c;
  438. if(c == 0)
  439. break;
  440. continue;
  441. }
  442. c = *cp++;
  443. if(c == 0)
  444. goto bad;
  445. if(c == '#') {
  446. *b++ = c;
  447. continue;
  448. }
  449. c -= 'a';
  450. if(c < 0 || c >= n)
  451. continue;
  452. strcpy(b, arg[c]);
  453. b += strlen(arg[c]);
  454. }
  455. *b = 0;
  456. if(debug['m'])
  457. print("#expand %s %s\n", s->name, ob);
  458. return;
  459. bad:
  460. yyerror("syntax in macro expansion: %s", s->name);
  461. *b = 0;
  462. return;
  463. toobig:
  464. yyerror("too much text in macro expansion: %s", s->name);
  465. *b = 0;
  466. }
  467. void
  468. macinc(void)
  469. {
  470. int c0, c, i, f;
  471. char str[STRINGSZ], *hp;
  472. c0 = getnsc();
  473. if(c0 != '"') {
  474. c = c0;
  475. if(c0 != '<')
  476. goto bad;
  477. c0 = '>';
  478. }
  479. for(hp = str;;) {
  480. c = getc();
  481. if(c == c0)
  482. break;
  483. if(c == '\n')
  484. goto bad;
  485. *hp++ = c;
  486. }
  487. *hp = 0;
  488. c = getcom();
  489. if(c != '\n')
  490. goto bad;
  491. f = -1;
  492. for(i=0; i<ninclude; i++) {
  493. if(i == 0 && c0 == '>')
  494. continue;
  495. strcpy(symb, include[i]);
  496. strcat(symb, "/");
  497. if(strcmp(symb, "./") == 0)
  498. symb[0] = 0;
  499. strcat(symb, str);
  500. f = open(symb, 0);
  501. if(f >= 0)
  502. break;
  503. }
  504. if(f < 0)
  505. strcpy(symb, str);
  506. c = strlen(symb) + 1;
  507. while(c & 3)
  508. c++;
  509. while(nhunk < c)
  510. gethunk();
  511. hp = hunk;
  512. memcpy(hunk, symb, c);
  513. nhunk -= c;
  514. hunk += c;
  515. newio();
  516. pushio();
  517. newfile(hp, f);
  518. return;
  519. bad:
  520. unget(c);
  521. yyerror("syntax in #include");
  522. macend();
  523. }
  524. void
  525. maclin(void)
  526. {
  527. char *cp;
  528. int c;
  529. long n;
  530. n = getnsn();
  531. c = getc();
  532. if(n < 0)
  533. goto bad;
  534. for(;;) {
  535. if(c == ' ' || c == '\t') {
  536. c = getc();
  537. continue;
  538. }
  539. if(c == '"')
  540. break;
  541. if(c == '\n') {
  542. strcpy(symb, "<noname>");
  543. goto nn;
  544. }
  545. goto bad;
  546. }
  547. cp = symb;
  548. for(;;) {
  549. c = getc();
  550. if(c == '"')
  551. break;
  552. *cp++ = c;
  553. }
  554. *cp = 0;
  555. c = getcom();
  556. if(c != '\n')
  557. goto bad;
  558. nn:
  559. c = strlen(symb) + 1;
  560. while(c & 3)
  561. c++;
  562. while(nhunk < c)
  563. gethunk();
  564. cp = hunk;
  565. memcpy(hunk, symb, c);
  566. nhunk -= c;
  567. hunk += c;
  568. linehist(cp, n);
  569. return;
  570. bad:
  571. unget(c);
  572. yyerror("syntax in #line");
  573. macend();
  574. }
  575. void
  576. macif(int f)
  577. {
  578. int c, l, bol;
  579. Sym *s;
  580. if(f == 2)
  581. goto skip;
  582. s = getsym();
  583. if(s == S)
  584. goto bad;
  585. if(getcom() != '\n')
  586. goto bad;
  587. if((s->macro != 0) ^ f)
  588. return;
  589. skip:
  590. bol = 1;
  591. l = 0;
  592. for(;;) {
  593. c = getc();
  594. if(c != '#') {
  595. if(!isspace(c))
  596. bol = 0;
  597. if(c == '\n')
  598. bol = 1;
  599. continue;
  600. }
  601. if(!bol)
  602. continue;
  603. s = getsym();
  604. if(s == S)
  605. continue;
  606. if(strcmp(s->name, "endif") == 0) {
  607. if(l) {
  608. l--;
  609. continue;
  610. }
  611. macend();
  612. return;
  613. }
  614. if(strcmp(s->name, "ifdef") == 0 || strcmp(s->name, "ifndef") == 0) {
  615. l++;
  616. continue;
  617. }
  618. if(l == 0 && f != 2 && strcmp(s->name, "else") == 0) {
  619. macend();
  620. return;
  621. }
  622. }
  623. bad:
  624. yyerror("syntax in #if(n)def");
  625. macend();
  626. }
  627. void
  628. macprag(void)
  629. {
  630. Sym *s;
  631. int c0, c;
  632. char *hp;
  633. Hist *h;
  634. s = getsym();
  635. if(s && strcmp(s->name, "lib") == 0)
  636. goto praglib;
  637. if(s && strcmp(s->name, "pack") == 0) {
  638. pragpack();
  639. return;
  640. }
  641. if(s && strcmp(s->name, "fpround") == 0) {
  642. pragfpround();
  643. return;
  644. }
  645. if(s && strcmp(s->name, "profile") == 0) {
  646. pragprofile();
  647. return;
  648. }
  649. if(s && strcmp(s->name, "varargck") == 0) {
  650. pragvararg();
  651. return;
  652. }
  653. if(s && strcmp(s->name, "incomplete") == 0) {
  654. pragincomplete();
  655. return;
  656. }
  657. while(getnsc() != '\n')
  658. ;
  659. return;
  660. praglib:
  661. c0 = getnsc();
  662. if(c0 != '"') {
  663. c = c0;
  664. if(c0 != '<')
  665. goto bad;
  666. c0 = '>';
  667. }
  668. for(hp = symb;;) {
  669. c = getc();
  670. if(c == c0)
  671. break;
  672. if(c == '\n')
  673. goto bad;
  674. *hp++ = c;
  675. }
  676. *hp = 0;
  677. c = getcom();
  678. if(c != '\n')
  679. goto bad;
  680. /*
  681. * put pragma-line in as a funny history
  682. */
  683. c = strlen(symb) + 1;
  684. while(c & 3)
  685. c++;
  686. while(nhunk < c)
  687. gethunk();
  688. hp = hunk;
  689. memcpy(hunk, symb, c);
  690. nhunk -= c;
  691. hunk += c;
  692. h = alloc(sizeof(Hist));
  693. h->name = hp;
  694. h->line = lineno;
  695. h->offset = -1;
  696. h->link = H;
  697. if(ehist == H) {
  698. hist = h;
  699. ehist = h;
  700. return;
  701. }
  702. ehist->link = h;
  703. ehist = h;
  704. return;
  705. bad:
  706. unget(c);
  707. yyerror("syntax in #pragma lib");
  708. macend();
  709. }
  710. void
  711. macend(void)
  712. {
  713. int c;
  714. for(;;) {
  715. c = getnsc();
  716. if(c < 0 || c == '\n')
  717. return;
  718. }
  719. }
  720. void
  721. linehist(char *f, int offset)
  722. {
  723. Hist *h;
  724. /*
  725. * overwrite the last #line directive if
  726. * no alloc has happened since the last one
  727. */
  728. if(newflag == 0 && ehist != H && offset != 0 && ehist->offset != 0)
  729. if(f && ehist->name && strcmp(f, ehist->name) == 0) {
  730. ehist->line = lineno;
  731. ehist->offset = offset;
  732. return;
  733. }
  734. if(debug['f'])
  735. if(f) {
  736. if(offset)
  737. print("%4ld: %s (#line %d)\n", lineno, f, offset);
  738. else
  739. print("%4ld: %s\n", lineno, f);
  740. } else
  741. print("%4ld: <pop>\n", lineno);
  742. newflag = 0;
  743. h = alloc(sizeof(Hist));
  744. h->name = f;
  745. h->line = lineno;
  746. h->offset = offset;
  747. h->link = H;
  748. if(ehist == H) {
  749. hist = h;
  750. ehist = h;
  751. return;
  752. }
  753. ehist->link = h;
  754. ehist = h;
  755. }
  756. void
  757. gethunk(void)
  758. {
  759. char *h;
  760. long nh;
  761. nh = NHUNK;
  762. if(thunk >= 10L*NHUNK)
  763. nh = 10L*NHUNK;
  764. h = (char*)mysbrk(nh);
  765. if(h == (char*)-1) {
  766. yyerror("out of memory");
  767. errorexit();
  768. }
  769. hunk = h;
  770. nhunk = nh;
  771. thunk += nh;
  772. }