cb.c 18 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040
  1. #include <u.h>
  2. #include <libc.h>
  3. #include <bio.h>
  4. #include "cb.h"
  5. #include "cbtype.h"
  6. static void
  7. usage(void)
  8. {
  9. fprint(2, "usage: cb [-sj] [-l width]\n");
  10. exits("usage");
  11. }
  12. void
  13. main(int argc, char *argv[])
  14. {
  15. Biobuf stdin, stdout;
  16. ARGBEGIN{
  17. case 'j':
  18. join = 1;
  19. break;
  20. case 'l':
  21. maxleng = atoi(EARGF(usage()));
  22. maxtabs = maxleng/TABLENG - 2;
  23. maxleng -= (maxleng + 5)/10;
  24. break;
  25. case 's':
  26. strict = 1;
  27. break;
  28. default:
  29. usage();
  30. }ARGEND
  31. Binit(&stdout, 1, OWRITE);
  32. output = &stdout;
  33. if (argc <= 0){
  34. Binit(&stdin, 0, OREAD);
  35. input = &stdin;
  36. work();
  37. Bterm(input);
  38. } else {
  39. while (argc-- > 0){
  40. if ((input = Bopen(*argv, OREAD)) == 0)
  41. sysfatal("can't open input file %s: %r", *argv);
  42. work();
  43. Bterm(input);
  44. argv++;
  45. }
  46. }
  47. exits(0);
  48. }
  49. void
  50. work(void)
  51. {
  52. int c, cc;
  53. struct keyw *lptr;
  54. char *pt;
  55. int ct;
  56. while ((c = getch()) != Beof){
  57. switch (c){
  58. case '{':
  59. if ((lptr = lookup(lastlook,p)) != 0){
  60. if (lptr->type == ELSE)gotelse();
  61. else if(lptr->type == DO)gotdo();
  62. else if(lptr->type == STRUCT)structlev++;
  63. }
  64. if(++clev >= &ind[CLEVEL-1]){
  65. fprint(2,"too many levels of curly brackets\n");
  66. clev = &ind[CLEVEL-1];
  67. }
  68. clev->pdepth = 0;
  69. clev->tabs = (clev-1)->tabs;
  70. clearif(clev);
  71. if(strict && clev->tabs > 0)
  72. putspace(' ',NO);
  73. putch(c,NO);
  74. getnl();
  75. if(keyflag == DATADEF){
  76. OUT;
  77. }
  78. else {
  79. OUTK;
  80. }
  81. clev->tabs++;
  82. pt = getnext(0); /* to handle initialized structures */
  83. if(*pt == '{'){ /* hide one level of {} */
  84. while((c=getch()) != '{')
  85. if(c == Beof)error("{");
  86. putch(c,NO);
  87. if(strict){
  88. putch(' ',NO);
  89. eatspace();
  90. }
  91. keyflag = SINIT;
  92. }
  93. continue;
  94. case '}':
  95. pt = getnext(0); /* to handle initialized structures */
  96. if(*pt == ','){
  97. if(strict){
  98. putspace(' ',NO);
  99. eatspace();
  100. }
  101. putch(c,NO);
  102. putch(*pt,NO);
  103. *pt = '\0';
  104. ct = getnl();
  105. pt = getnext(0);
  106. if(*pt == '{'){
  107. OUT;
  108. while((cc = getch()) != '{')
  109. if(cc == Beof)error("}");
  110. putch(cc,NO);
  111. if(strict){
  112. putch(' ',NO);
  113. eatspace();
  114. }
  115. getnext(0);
  116. continue;
  117. }
  118. else if(strict || ct){
  119. OUT;
  120. }
  121. continue;
  122. }
  123. else if(keyflag == SINIT && *pt == '}'){
  124. if(strict)
  125. putspace(' ',NO);
  126. putch(c,NO);
  127. getnl();
  128. OUT;
  129. keyflag = DATADEF;
  130. *pt = '\0';
  131. pt = getnext(0);
  132. }
  133. outs(clev->tabs);
  134. if(--clev < ind)clev = ind;
  135. ptabs(clev->tabs);
  136. putch(c,NO);
  137. lbegin = 0;
  138. lptr=lookup(pt,lastplace+1);
  139. c = *pt;
  140. if(*pt == ';' || *pt == ','){
  141. putch(*pt,NO);
  142. *pt = '\0';
  143. lastplace=pt;
  144. }
  145. ct = getnl();
  146. if((dolevel && clev->tabs <= dotabs[dolevel]) || (structlev )
  147. || (lptr != 0 &&lptr->type == ELSE&& clev->pdepth == 0)){
  148. if(c == ';'){
  149. OUTK;
  150. }
  151. else if(strict || (lptr != 0 && lptr->type == ELSE && ct == 0)){
  152. putspace(' ',NO);
  153. eatspace();
  154. }
  155. else if(lptr != 0 && lptr->type == ELSE){
  156. OUTK;
  157. }
  158. if(structlev){
  159. structlev--;
  160. keyflag = DATADEF;
  161. }
  162. }
  163. else {
  164. OUTK;
  165. if(strict && clev->tabs == 0){
  166. if((c=getch()) != '\n'){
  167. Bputc(output, '\n');
  168. Bputc(output, '\n');
  169. unget(c);
  170. }
  171. else {
  172. lineno++;
  173. Bputc(output, '\n');
  174. if((c=getch()) != '\n')unget(c);
  175. else lineno++;
  176. Bputc(output, '\n');
  177. }
  178. }
  179. }
  180. if(lptr != 0 && lptr->type == ELSE && clev->pdepth != 0){
  181. UNBUMP;
  182. }
  183. if(lptr == 0 || lptr->type != ELSE){
  184. clev->iflev = 0;
  185. if(dolevel && docurly[dolevel] == NO && clev->tabs == dotabs[dolevel]+1)
  186. clev->tabs--;
  187. else if(clev->pdepth != 0){
  188. UNBUMP;
  189. }
  190. }
  191. continue;
  192. case '(':
  193. paren++;
  194. if ((lptr = lookup(lastlook,p)) != 0){
  195. if(!(lptr->type == TYPE || lptr->type == STRUCT))keyflag=KEYWORD;
  196. if (strict){
  197. putspace(lptr->punc,NO);
  198. opflag = 1;
  199. }
  200. putch(c,NO);
  201. if (lptr->type == IF)gotif();
  202. }
  203. else {
  204. putch(c,NO);
  205. lastlook = p;
  206. opflag = 1;
  207. }
  208. continue;
  209. case ')':
  210. if(--paren < 0)paren = 0;
  211. putch(c,NO);
  212. if((lptr = lookup(lastlook,p)) != 0){
  213. if(lptr->type == TYPE || lptr->type == STRUCT)
  214. opflag = 1;
  215. }
  216. else if(keyflag == DATADEF)opflag = 1;
  217. else opflag = 0;
  218. outs(clev->tabs);
  219. pt = getnext(1);
  220. if ((ct = getnl()) == 1 && !strict){
  221. if(dolevel && clev->tabs <= dotabs[dolevel])
  222. resetdo();
  223. if(clev->tabs > 0 && (paren != 0 || keyflag == 0)){
  224. if(join){
  225. eatspace();
  226. putch(' ',YES);
  227. continue;
  228. } else {
  229. OUT;
  230. split = 1;
  231. continue;
  232. }
  233. }
  234. else if(clev->tabs > 0 && *pt != '{'){
  235. BUMP;
  236. }
  237. OUTK;
  238. }
  239. else if(strict){
  240. if(clev->tabs == 0){
  241. if(*pt != ';' && *pt != ',' && *pt != '(' && *pt != '['){
  242. OUTK;
  243. }
  244. }
  245. else {
  246. if(keyflag == KEYWORD && paren == 0){
  247. if(dolevel && clev->tabs <= dotabs[dolevel]){
  248. resetdo();
  249. eatspace();
  250. continue;
  251. }
  252. if(*pt != '{'){
  253. BUMP;
  254. OUTK;
  255. }
  256. else {
  257. *pt='\0';
  258. eatspace();
  259. unget('{');
  260. }
  261. }
  262. else if(ct){
  263. if(paren){
  264. if(join){
  265. eatspace();
  266. } else {
  267. split = 1;
  268. OUT;
  269. }
  270. }
  271. else {
  272. OUTK;
  273. }
  274. }
  275. }
  276. }
  277. else if(dolevel && clev->tabs <= dotabs[dolevel])
  278. resetdo();
  279. continue;
  280. case ' ':
  281. case '\t':
  282. if ((lptr = lookup(lastlook,p)) != 0){
  283. if(!(lptr->type==TYPE||lptr->type==STRUCT))
  284. keyflag = KEYWORD;
  285. else if(paren == 0)keyflag = DATADEF;
  286. if(strict){
  287. if(lptr->type != ELSE){
  288. if(lptr->type == TYPE){
  289. if(paren != 0)putch(' ',YES);
  290. }
  291. else
  292. putch(lptr->punc,NO);
  293. eatspace();
  294. }
  295. }
  296. else putch(c,YES);
  297. switch(lptr->type){
  298. case CASE:
  299. outs(clev->tabs-1);
  300. continue;
  301. case ELSE:
  302. pt = getnext(1);
  303. eatspace();
  304. if((cc = getch()) == '\n' && !strict){
  305. unget(cc);
  306. }
  307. else {
  308. unget(cc);
  309. if(checkif(pt))continue;
  310. }
  311. gotelse();
  312. if(strict) unget(c);
  313. if(getnl() == 1 && !strict){
  314. OUTK;
  315. if(*pt != '{'){
  316. BUMP;
  317. }
  318. }
  319. else if(strict){
  320. if(*pt != '{'){
  321. OUTK;
  322. BUMP;
  323. }
  324. }
  325. continue;
  326. case IF:
  327. gotif();
  328. continue;
  329. case DO:
  330. gotdo();
  331. pt = getnext(1);
  332. if(*pt != '{'){
  333. eatallsp();
  334. OUTK;
  335. docurly[dolevel] = NO;
  336. dopdepth[dolevel] = clev->pdepth;
  337. clev->pdepth = 0;
  338. clev->tabs++;
  339. }
  340. continue;
  341. case TYPE:
  342. if(paren)continue;
  343. if(!strict)continue;
  344. gottype(lptr);
  345. continue;
  346. case STRUCT:
  347. gotstruct();
  348. continue;
  349. }
  350. }
  351. else if (lbegin == 0 || p > string)
  352. if(strict)
  353. putch(c,NO);
  354. else putch(c,YES);
  355. continue;
  356. case ';':
  357. putch(c,NO);
  358. if(paren != 0){
  359. if(strict){
  360. putch(' ',YES);
  361. eatspace();
  362. }
  363. opflag = 1;
  364. continue;
  365. }
  366. outs(clev->tabs);
  367. pt = getnext(0);
  368. lptr=lookup(pt,lastplace+1);
  369. if(lptr == 0 || lptr->type != ELSE){
  370. clev->iflev = 0;
  371. if(clev->pdepth != 0){
  372. UNBUMP;
  373. }
  374. if(dolevel && docurly[dolevel] == NO && clev->tabs <= dotabs[dolevel]+1)
  375. clev->tabs--;
  376. /*
  377. else if(clev->pdepth != 0){
  378. UNBUMP;
  379. }
  380. */
  381. }
  382. getnl();
  383. OUTK;
  384. continue;
  385. case '\n':
  386. if ((lptr = lookup(lastlook,p)) != 0){
  387. pt = getnext(1);
  388. if (lptr->type == ELSE){
  389. if(strict)
  390. if(checkif(pt))continue;
  391. gotelse();
  392. OUTK;
  393. if(*pt != '{'){
  394. BUMP;
  395. }
  396. }
  397. else if(lptr->type == DO){
  398. OUTK;
  399. gotdo();
  400. if(*pt != '{'){
  401. docurly[dolevel] = NO;
  402. dopdepth[dolevel] = clev->pdepth;
  403. clev->pdepth = 0;
  404. clev->tabs++;
  405. }
  406. }
  407. else {
  408. OUTK;
  409. if(lptr->type == STRUCT)gotstruct();
  410. }
  411. }
  412. else if(p == string)Bputc(output, '\n');
  413. else {
  414. if(clev->tabs > 0 &&(paren != 0 || keyflag == 0)){
  415. if(join){
  416. putch(' ',YES);
  417. eatspace();
  418. continue;
  419. } else {
  420. OUT;
  421. split = 1;
  422. continue;
  423. }
  424. }
  425. else if(keyflag == KEYWORD){
  426. OUTK;
  427. continue;
  428. }
  429. OUT;
  430. }
  431. continue;
  432. case '"':
  433. case '\'':
  434. putch(c,NO);
  435. while ((cc = getch()) != c){
  436. if(cc == Beof)
  437. error("\" or '");
  438. putch(cc,NO);
  439. if (cc == '\\'){
  440. putch(getch(),NO);
  441. }
  442. if (cc == '\n'){
  443. outs(clev->tabs);
  444. lbegin = 1;
  445. count = 0;
  446. }
  447. }
  448. putch(cc,NO);
  449. opflag=0;
  450. if (getnl() == 1){
  451. unget('\n');
  452. }
  453. continue;
  454. case '\\':
  455. putch(c,NO);
  456. putch(getch(),NO);
  457. continue;
  458. case '?':
  459. question = 1;
  460. gotop(c);
  461. continue;
  462. case ':':
  463. if ((cc = getch()) == ':') {
  464. putch(c,NO);
  465. putch(cc,NO);
  466. continue;
  467. }
  468. unget(cc);
  469. if (question == 1){
  470. question = 0;
  471. gotop(c);
  472. continue;
  473. }
  474. putch(c,NO);
  475. if(structlev)continue;
  476. if ((lptr = lookup(lastlook,p)) != 0){
  477. if (lptr->type == CASE)outs(clev->tabs - 1);
  478. }
  479. else {
  480. lbegin = 0;
  481. outs(clev->tabs);
  482. }
  483. getnl();
  484. OUTK;
  485. continue;
  486. case '/':
  487. if ((cc = getch()) == '/') {
  488. putch(c,NO);
  489. putch(cc,NO);
  490. cpp_comment(YES);
  491. OUT;
  492. lastlook = 0;
  493. continue;
  494. }
  495. else if (cc != '*') {
  496. unget(cc);
  497. gotop(c);
  498. continue;
  499. }
  500. putch(c,NO);
  501. putch(cc,NO);
  502. cc = comment(YES);
  503. if(getnl() == 1){
  504. if(cc == 0){
  505. OUT;
  506. }
  507. else {
  508. outs(0);
  509. Bputc(output, '\n');
  510. lbegin = 1;
  511. count = 0;
  512. }
  513. lastlook = 0;
  514. }
  515. continue;
  516. case '[':
  517. putch(c,NO);
  518. ct = 0;
  519. while((c = getch()) != ']' || ct > 0){
  520. if(c == Beof)error("]");
  521. putch(c,NO);
  522. if(c == '[')ct++;
  523. if(c == ']')ct--;
  524. }
  525. putch(c,NO);
  526. continue;
  527. case '#':
  528. putch(c,NO);
  529. while ((cc = getch()) != '\n'){
  530. if(cc == Beof)error("newline");
  531. if (cc == '\\'){
  532. putch(cc,NO);
  533. cc = getch();
  534. }
  535. putch(cc,NO);
  536. }
  537. putch(cc,NO);
  538. lbegin = 0;
  539. outs(clev->tabs);
  540. lbegin = 1;
  541. count = 0;
  542. continue;
  543. default:
  544. if (c == ','){
  545. opflag = 1;
  546. putch(c,YES);
  547. if (strict){
  548. if ((cc = getch()) != ' ')unget(cc);
  549. if(cc != '\n')putch(' ',YES);
  550. }
  551. }
  552. else if(isop(c))gotop(c);
  553. else {
  554. if(isalnum(c) && lastlook == 0)lastlook = p;
  555. if(isdigit(c)){
  556. putch(c,NO);
  557. while(isdigit(c=Bgetc(input))||c == '.')putch(c,NO);
  558. if(c == 'e'){
  559. putch(c,NO);
  560. c = Bgetc(input);
  561. putch(c, NO);
  562. while(isdigit(c=Bgetc(input)))putch(c,NO);
  563. }
  564. Bungetc(input);
  565. }
  566. else putch(c,NO);
  567. if(keyflag != DATADEF)opflag = 0;
  568. }
  569. }
  570. }
  571. }
  572. void
  573. gotif(void){
  574. outs(clev->tabs);
  575. if(++clev->iflev >= IFLEVEL-1){
  576. fprint(2,"too many levels of if %d\n",clev->iflev );
  577. clev->iflev = IFLEVEL-1;
  578. }
  579. clev->ifc[clev->iflev] = clev->tabs;
  580. clev->spdepth[clev->iflev] = clev->pdepth;
  581. }
  582. void
  583. gotelse(void){
  584. clev->tabs = clev->ifc[clev->iflev];
  585. clev->pdepth = clev->spdepth[clev->iflev];
  586. if(--(clev->iflev) < 0)clev->iflev = 0;
  587. }
  588. int
  589. checkif(char *pt)
  590. {
  591. struct keyw *lptr;
  592. int cc;
  593. if((lptr=lookup(pt,lastplace+1))!= 0){
  594. if(lptr->type == IF){
  595. if(strict)putch(' ',YES);
  596. copy(lptr->name);
  597. *pt='\0';
  598. lastplace = pt;
  599. if(strict){
  600. putch(lptr->punc,NO);
  601. eatallsp();
  602. }
  603. clev->tabs = clev->ifc[clev->iflev];
  604. clev->pdepth = clev->spdepth[clev->iflev];
  605. keyflag = KEYWORD;
  606. return(1);
  607. }
  608. }
  609. return(0);
  610. }
  611. void
  612. gotdo(void){
  613. if(++dolevel >= DOLEVEL-1){
  614. fprint(2,"too many levels of do %d\n",dolevel);
  615. dolevel = DOLEVEL-1;
  616. }
  617. dotabs[dolevel] = clev->tabs;
  618. docurly[dolevel] = YES;
  619. }
  620. void
  621. resetdo(void){
  622. if(docurly[dolevel] == NO)
  623. clev->pdepth = dopdepth[dolevel];
  624. if(--dolevel < 0)dolevel = 0;
  625. }
  626. void
  627. gottype(struct keyw *lptr)
  628. {
  629. char *pt;
  630. struct keyw *tlptr;
  631. int c;
  632. while(1){
  633. pt = getnext(1);
  634. if((tlptr=lookup(pt,lastplace+1))!=0){
  635. putch(' ',YES);
  636. copy(tlptr->name);
  637. *pt='\0';
  638. lastplace = pt;
  639. if(tlptr->type == STRUCT){
  640. putch(tlptr->punc,YES);
  641. gotstruct();
  642. break;
  643. }
  644. lptr=tlptr;
  645. continue;
  646. }
  647. else{
  648. putch(lptr->punc,NO);
  649. while((c=getch())== ' ' || c == '\t');
  650. unget(c);
  651. break;
  652. }
  653. }
  654. }
  655. void
  656. gotstruct(void){
  657. int c;
  658. int cc;
  659. char *pt;
  660. while((c=getch()) == ' ' || c == '\t')
  661. if(!strict)putch(c,NO);
  662. if(c == '{'){
  663. structlev++;
  664. unget(c);
  665. return;
  666. }
  667. if(isalpha(c)){
  668. putch(c,NO);
  669. while(isalnum(c=getch()))putch(c,NO);
  670. }
  671. unget(c);
  672. pt = getnext(1);
  673. if(*pt == '{')structlev++;
  674. if(strict){
  675. eatallsp();
  676. putch(' ',NO);
  677. }
  678. }
  679. void
  680. gotop(int c)
  681. {
  682. char optmp[OPLENGTH];
  683. char *op_ptr;
  684. struct op *s_op;
  685. char *a, *b;
  686. op_ptr = optmp;
  687. *op_ptr++ = c;
  688. while (isop(( *op_ptr = getch())))op_ptr++;
  689. if(!strict)unget(*op_ptr);
  690. else if (*op_ptr != ' ')unget( *op_ptr);
  691. *op_ptr = '\0';
  692. s_op = op;
  693. b = optmp;
  694. while ((a = s_op->name) != 0){
  695. op_ptr = b;
  696. while ((*op_ptr == *a) && (*op_ptr != '\0')){
  697. a++;
  698. op_ptr++;
  699. }
  700. if (*a == '\0'){
  701. keep(s_op);
  702. opflag = s_op->setop;
  703. if (*op_ptr != '\0'){
  704. b = op_ptr;
  705. s_op = op;
  706. continue;
  707. }
  708. else break;
  709. }
  710. else s_op++;
  711. }
  712. }
  713. void
  714. keep(struct op *o)
  715. {
  716. char *s;
  717. int ok;
  718. if(o->blanks == NEVER)ok = NO;
  719. else ok = YES;
  720. if (strict && ((o->blanks & ALWAYS)
  721. || ((opflag == 0 && o->blanks & SOMETIMES) && clev->tabs != 0)))
  722. putspace(' ',YES);
  723. for(s=o->name; *s != '\0'; s++){
  724. if(*(s+1) == '\0')putch(*s,ok);
  725. else
  726. putch(*s,NO);
  727. }
  728. if (strict && ((o->blanks & ALWAYS)
  729. || ((opflag == 0 && o->blanks & SOMETIMES) && clev->tabs != 0))) putch(' ',YES);
  730. }
  731. int
  732. getnl(void){
  733. int ch;
  734. char *savp;
  735. int gotcmt;
  736. gotcmt = 0;
  737. savp = p;
  738. while ((ch = getch()) == '\t' || ch == ' ')putch(ch,NO);
  739. if (ch == '/'){
  740. if ((ch = getch()) == '*'){
  741. putch('/',NO);
  742. putch('*',NO);
  743. comment(NO);
  744. ch = getch();
  745. gotcmt=1;
  746. }
  747. else if (ch == '/') {
  748. putch('/',NO);
  749. putch('/',NO);
  750. cpp_comment(NO);
  751. ch = getch();
  752. gotcmt = 1;
  753. }
  754. else {
  755. if(inswitch)*(++lastplace) = ch;
  756. else {
  757. inswitch = 1;
  758. *lastplace = ch;
  759. }
  760. unget('/');
  761. return(0);
  762. }
  763. }
  764. if(ch == '\n'){
  765. if(gotcmt == 0)p=savp;
  766. return(1);
  767. }
  768. unget(ch);
  769. return(0);
  770. }
  771. void
  772. ptabs(int n){
  773. int i;
  774. int num;
  775. if(n > maxtabs){
  776. if(!folded){
  777. Bprint(output, "/* code folded from here */\n");
  778. folded = 1;
  779. }
  780. num = n-maxtabs;
  781. }
  782. else {
  783. num = n;
  784. if(folded){
  785. folded = 0;
  786. Bprint(output, "/* unfolding */\n");
  787. }
  788. }
  789. for (i = 0; i < num; i++)Bputc(output, '\t');
  790. }
  791. void
  792. outs(int n){
  793. if (p > string){
  794. if (lbegin){
  795. ptabs(n);
  796. lbegin = 0;
  797. if (split == 1){
  798. split = 0;
  799. if (clev->tabs > 0)Bprint(output, "\t");
  800. }
  801. }
  802. *p = '\0';
  803. Bprint(output, "%s", string);
  804. lastlook = p = string;
  805. }
  806. else {
  807. if (lbegin != 0){
  808. lbegin = 0;
  809. split = 0;
  810. }
  811. }
  812. }
  813. void
  814. putch(char c,int ok)
  815. {
  816. int cc;
  817. if(p < &string[LINE-1]){
  818. if(count+TABLENG*clev->tabs >= maxleng && ok && !folded){
  819. if(c != ' ')*p++ = c;
  820. OUT;
  821. split = 1;
  822. if((cc=getch()) != '\n')unget(cc);
  823. }
  824. else {
  825. *p++ = c;
  826. count++;
  827. }
  828. }
  829. else {
  830. outs(clev->tabs);
  831. *p++ = c;
  832. count = 0;
  833. }
  834. }
  835. struct keyw *
  836. lookup(char *first, char *last)
  837. {
  838. struct keyw *ptr;
  839. char *cptr, *ckey, *k;
  840. if(first == last || first == 0)return(0);
  841. cptr = first;
  842. while (*cptr == ' ' || *cptr == '\t')cptr++;
  843. if(cptr >= last)return(0);
  844. ptr = key;
  845. while ((ckey = ptr->name) != 0){
  846. for (k = cptr; (*ckey == *k && *ckey != '\0'); k++, ckey++);
  847. if(*ckey=='\0' && (k==last|| (k<last && !isalnum(*k)))){
  848. opflag = 1;
  849. lastlook = 0;
  850. return(ptr);
  851. }
  852. ptr++;
  853. }
  854. return(0);
  855. }
  856. int
  857. comment(int ok)
  858. {
  859. int ch;
  860. int hitnl;
  861. hitnl = 0;
  862. while ((ch = getch()) != Beof){
  863. putch(ch, NO);
  864. if (ch == '*'){
  865. gotstar:
  866. if ((ch = getch()) == '/'){
  867. putch(ch,NO);
  868. return(hitnl);
  869. }
  870. putch(ch,NO);
  871. if (ch == '*')goto gotstar;
  872. }
  873. if (ch == '\n'){
  874. if(ok && !hitnl){
  875. outs(clev->tabs);
  876. }
  877. else {
  878. outs(0);
  879. }
  880. lbegin = 1;
  881. count = 0;
  882. hitnl = 1;
  883. }
  884. }
  885. return(hitnl);
  886. }
  887. int
  888. cpp_comment(int ok)
  889. {
  890. int ch;
  891. int hitnl;
  892. hitnl = 0;
  893. while ((ch = getch()) != -1) {
  894. if (ch == '\n') {
  895. if (ok && !hitnl)
  896. outs(clev->tabs);
  897. else
  898. outs(0);
  899. lbegin = 1;
  900. count = 0;
  901. hitnl = 1;
  902. break;
  903. }
  904. putch(ch, NO);
  905. }
  906. return hitnl;
  907. }
  908. void
  909. putspace(char ch, int ok)
  910. {
  911. if(p == string)putch(ch,ok);
  912. else if (*(p - 1) != ch) putch(ch,ok);
  913. }
  914. int
  915. getch(void){
  916. char c;
  917. if(inswitch){
  918. if(next != '\0'){
  919. c=next;
  920. next = '\0';
  921. return(c);
  922. }
  923. if(tptr <= lastplace){
  924. if(*tptr != '\0')return(*tptr++);
  925. else if(++tptr <= lastplace)return(*tptr++);
  926. }
  927. inswitch=0;
  928. lastplace = tptr = temp;
  929. }
  930. return(Bgetc(input));
  931. }
  932. void
  933. unget(char c)
  934. {
  935. if(inswitch){
  936. if(tptr != temp)
  937. *(--tptr) = c;
  938. else next = c;
  939. }
  940. else Bungetc(input);
  941. }
  942. char *
  943. getnext(int must){
  944. int c;
  945. char *beg;
  946. int prect,nlct;
  947. prect = nlct = 0;
  948. if(tptr > lastplace){
  949. tptr = lastplace = temp;
  950. err = 0;
  951. inswitch = 0;
  952. }
  953. tp = lastplace;
  954. if(inswitch && tptr <= lastplace)
  955. if (isalnum(*lastplace)||ispunct(*lastplace)||isop(*lastplace))return(lastplace);
  956. space:
  957. while(isspace(c=Bgetc(input)))puttmp(c,1);
  958. beg = tp;
  959. puttmp(c,1);
  960. if(c == '/'){
  961. if(puttmp(Bgetc(input),1) == '*'){
  962. cont:
  963. while((c=Bgetc(input)) != '*'){
  964. puttmp(c,0);
  965. if(must == 0 && c == '\n')
  966. if(nlct++ > 2)goto done;
  967. }
  968. puttmp(c,1);
  969. star:
  970. if(puttmp((c=Bgetc(input)),1) == '/'){
  971. beg = tp;
  972. puttmp((c=Bgetc(input)),1);
  973. }
  974. else if(c == '*')goto star;
  975. else goto cont;
  976. }
  977. else goto done;
  978. }
  979. if(isspace(c))goto space;
  980. if(c == '#' && tp > temp+1 && *(tp-2) == '\n'){
  981. if(prect++ > 2)goto done;
  982. while(puttmp((c=Bgetc(input)),1) != '\n')
  983. if(c == '\\')puttmp(Bgetc(input),1);
  984. goto space;
  985. }
  986. if(isalnum(c)){
  987. while(isalnum(c = Bgetc(input)))puttmp(c,1);
  988. Bungetc(input);
  989. }
  990. done:
  991. puttmp('\0',1);
  992. lastplace = tp-1;
  993. inswitch = 1;
  994. return(beg);
  995. }
  996. void
  997. copy(char *s)
  998. {
  999. while(*s != '\0')putch(*s++,NO);
  1000. }
  1001. void
  1002. clearif(struct indent *cl)
  1003. {
  1004. int i;
  1005. for(i=0;i<IFLEVEL-1;i++)cl->ifc[i] = 0;
  1006. }
  1007. char
  1008. puttmp(char c, int keep)
  1009. {
  1010. if(tp < &temp[TEMP-120])
  1011. *tp++ = c;
  1012. else {
  1013. if(keep){
  1014. if(tp >= &temp[TEMP-1]){
  1015. fprint(2,"can't look past huge comment - quiting\n");
  1016. exits("boom");
  1017. }
  1018. *tp++ = c;
  1019. }
  1020. else if(err == 0){
  1021. err++;
  1022. fprint(2,"truncating long comment\n");
  1023. }
  1024. }
  1025. return(c);
  1026. }
  1027. void
  1028. error(char *s)
  1029. {
  1030. fprint(2,"saw EOF while looking for %s\n",s);
  1031. exits("boom");
  1032. }