gram.y 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443
  1. %{#include "defs.h"
  2. %}
  3. %term NAME SHELLINE START MACRODEF COLON DOUBLECOLON GREATER AMPER AMPERAMPER
  4. %union
  5. {
  6. struct shblock *yshblock;
  7. depblkp ydepblock;
  8. nameblkp ynameblock;
  9. }
  10. %type <yshblock> SHELLINE, shlist, shellist
  11. %type <ynameblock> NAME, namelist
  12. %type <ydepblock> deplist, dlist
  13. %%
  14. %{
  15. struct depblock *pp;
  16. static struct shblock *prevshp;
  17. static struct nameblock *lefts[NLEFTS];
  18. struct nameblock *leftp;
  19. static int nlefts;
  20. struct lineblock *lp, *lpp;
  21. static struct depblock *prevdep;
  22. static int sepc;
  23. static int allnowait;
  24. static struct fstack
  25. {
  26. FILE *fin;
  27. char *fname;
  28. int lineno;
  29. } filestack[MAXINCLUDE];
  30. static int ninclude = 0;
  31. %}
  32. file:
  33. | file comline
  34. ;
  35. comline: START
  36. | MACRODEF
  37. | START namelist deplist shellist = {
  38. while( --nlefts >= 0)
  39. {
  40. wildp wp;
  41. leftp = lefts[nlefts];
  42. if(wp = iswild(leftp->namep))
  43. {
  44. leftp->septype = SOMEDEPS;
  45. if(lastwild)
  46. lastwild->next = wp;
  47. else
  48. firstwild = wp;
  49. lastwild = wp;
  50. }
  51. if(leftp->septype == 0)
  52. leftp->septype = sepc;
  53. else if(leftp->septype != sepc)
  54. {
  55. if(! wp)
  56. fprintf(stderr,
  57. "Inconsistent rules lines for `%s'\n",
  58. leftp->namep);
  59. }
  60. else if(sepc==ALLDEPS && leftp->namep[0]!='.' && $4!=0)
  61. {
  62. for(lp=leftp->linep; lp->nxtlineblock; lp=lp->nxtlineblock)
  63. if(lp->shp)
  64. fprintf(stderr,
  65. "Multiple rules lines for `%s'\n",
  66. leftp->namep);
  67. }
  68. lp = ALLOC(lineblock);
  69. lp->nxtlineblock = NULL;
  70. lp->depp = $3;
  71. lp->shp = $4;
  72. if(wp)
  73. wp->linep = lp;
  74. if(equal(leftp->namep, ".SUFFIXES") && $3==0)
  75. leftp->linep = 0;
  76. else if(leftp->linep == 0)
  77. leftp->linep = lp;
  78. else {
  79. for(lpp = leftp->linep; lpp->nxtlineblock;
  80. lpp = lpp->nxtlineblock) ;
  81. if(sepc==ALLDEPS && leftp->namep[0]=='.')
  82. lpp->shp = 0;
  83. lpp->nxtlineblock = lp;
  84. }
  85. }
  86. }
  87. | error
  88. ;
  89. namelist: NAME = { lefts[0] = $1; nlefts = 1; }
  90. | namelist NAME = { lefts[nlefts++] = $2;
  91. if(nlefts>=NLEFTS) fatal("Too many lefts"); }
  92. ;
  93. deplist:
  94. {
  95. char junk[100];
  96. sprintf(junk, "%s:%d", filestack[ninclude-1].fname, yylineno);
  97. fatal1("Must be a separator on rules line %s", junk);
  98. }
  99. | dlist
  100. ;
  101. dlist: sepchar = { prevdep = 0; $$ = 0; allnowait = NO; }
  102. | sepchar AMPER = { prevdep = 0; $$ = 0; allnowait = YES; }
  103. | dlist NAME = {
  104. pp = ALLOC(depblock);
  105. pp->nxtdepblock = NULL;
  106. pp->depname = $2;
  107. pp->nowait = allnowait;
  108. if(prevdep == 0) $$ = pp;
  109. else prevdep->nxtdepblock = pp;
  110. prevdep = pp;
  111. }
  112. | dlist AMPER = { if(prevdep) prevdep->nowait = YES; }
  113. | dlist AMPERAMPER
  114. ;
  115. sepchar: COLON = { sepc = ALLDEPS; }
  116. | DOUBLECOLON = { sepc = SOMEDEPS; }
  117. ;
  118. shellist: = {$$ = 0; }
  119. | shlist = { $$ = $1; }
  120. ;
  121. shlist: SHELLINE = { $$ = $1; prevshp = $1; }
  122. | shlist SHELLINE = { $$ = $1;
  123. prevshp->nxtshblock = $2;
  124. prevshp = $2;
  125. }
  126. ;
  127. %%
  128. static char *zznextc; /* null if need another line;
  129. otherwise points to next char */
  130. static int yylineno;
  131. static FILE * fin;
  132. static int retsh(char *);
  133. static int nextlin(void);
  134. static int isinclude(char *);
  135. int yyparse(void);
  136. int
  137. parse(char *name)
  138. {
  139. FILE *stream;
  140. if(name == CHNULL)
  141. {
  142. stream = NULL;
  143. name = "(builtin-rules)";
  144. }
  145. else if(equal(name, "-"))
  146. {
  147. stream = stdin;
  148. name = "(stdin)";
  149. }
  150. else if( (stream = fopen(name, "r")) == NULL)
  151. return NO;
  152. filestack[0].fname = copys(name);
  153. ninclude = 1;
  154. fin = stream;
  155. yylineno = 0;
  156. zznextc = 0;
  157. if( yyparse() )
  158. fatal("Description file error");
  159. if(fin)
  160. fclose(fin);
  161. return YES;
  162. }
  163. int
  164. yylex(void)
  165. {
  166. char *p;
  167. char *q;
  168. char word[INMAX];
  169. if(! zznextc )
  170. return nextlin() ;
  171. while( isspace(*zznextc) )
  172. ++zznextc;
  173. switch(*zznextc)
  174. {
  175. case '\0':
  176. return nextlin() ;
  177. case '|':
  178. if(zznextc[1]==':')
  179. {
  180. zznextc += 2;
  181. return DOUBLECOLON;
  182. }
  183. break;
  184. case ':':
  185. if(*++zznextc == ':')
  186. {
  187. ++zznextc;
  188. return DOUBLECOLON;
  189. }
  190. return COLON;
  191. case '>':
  192. ++zznextc;
  193. return GREATER;
  194. case '&':
  195. if(*++zznextc == '&')
  196. {
  197. ++zznextc;
  198. return AMPERAMPER;
  199. }
  200. return AMPER;
  201. case ';':
  202. return retsh(zznextc) ;
  203. }
  204. p = zznextc;
  205. q = word;
  206. while( ! ( funny[*p] & TERMINAL) )
  207. *q++ = *p++;
  208. if(p != zznextc)
  209. {
  210. *q = '\0';
  211. if((yylval.ynameblock=srchname(word))==0)
  212. yylval.ynameblock = makename(word);
  213. zznextc = p;
  214. return NAME;
  215. }
  216. else {
  217. char junk[100];
  218. sprintf(junk, "Bad character %c (octal %o), line %d of file %s",
  219. *zznextc, *zznextc, yylineno, filestack[ninclude-1].fname);
  220. fatal(junk);
  221. }
  222. return 0; /* never executed */
  223. }
  224. static int
  225. retsh(char *q)
  226. {
  227. register char *p;
  228. struct shblock *sp;
  229. for(p=q+1 ; *p==' '||*p=='\t' ; ++p) ;
  230. sp = ALLOC(shblock);
  231. sp->nxtshblock = NULL;
  232. sp->shbp = (fin ? copys(p) : p );
  233. yylval.yshblock = sp;
  234. zznextc = 0;
  235. return SHELLINE;
  236. }
  237. static int
  238. nextlin(void)
  239. {
  240. static char yytext[INMAX];
  241. static char *yytextl = yytext+INMAX;
  242. char *text, templin[INMAX];
  243. char c;
  244. char *p, *t;
  245. char lastch, *lastchp;
  246. extern char **linesptr;
  247. int incom;
  248. int kc;
  249. again:
  250. incom = NO;
  251. zznextc = 0;
  252. if(fin == NULL)
  253. {
  254. if( (text = *linesptr++) == 0)
  255. return 0;
  256. ++yylineno;
  257. }
  258. else {
  259. for(p = text = yytext ; p<yytextl ; *p++ = kc)
  260. switch(kc = getc(fin))
  261. {
  262. case '\t':
  263. if(p == yytext)
  264. incom = YES;
  265. break;
  266. case ';':
  267. incom = YES;
  268. break;
  269. case '#':
  270. if(! incom)
  271. kc = '\0';
  272. break;
  273. case '\n':
  274. ++yylineno;
  275. if(p==yytext || p[-1]!='\\')
  276. {
  277. *p = '\0';
  278. goto endloop;
  279. }
  280. p[-1] = ' ';
  281. while( (kc=getc(fin))=='\t' || kc==' ' || kc=='\n')
  282. if(kc == '\n')
  283. ++yylineno;
  284. if(kc != EOF)
  285. break;
  286. case EOF:
  287. *p = '\0';
  288. if(ninclude > 1)
  289. {
  290. register struct fstack *stp;
  291. fclose(fin);
  292. --ninclude;
  293. stp = filestack + ninclude;
  294. fin = stp->fin;
  295. yylineno = stp->lineno;
  296. free(stp->fname);
  297. goto again;
  298. }
  299. return 0;
  300. }
  301. fatal("line too long");
  302. }
  303. endloop:
  304. if((c = text[0]) == '\t')
  305. return retsh(text) ;
  306. if(isalpha(c) || isdigit(c) || c==' ' || c=='.'|| c=='_')
  307. for(p=text+1; *p!='\0'; )
  308. if(*p == ':')
  309. break;
  310. else if(*p++ == '=')
  311. {
  312. eqsign(text);
  313. return MACRODEF;
  314. }
  315. /* substitute for macros on dependency line up to the semicolon if any */
  316. for(t = yytext ; *t!='\0' && *t!=';' ; ++t)
  317. ;
  318. lastchp = t;
  319. lastch = *t;
  320. *t = '\0'; /* replace the semi with a null so subst will stop */
  321. /* Substitute for macros on dependency lines */
  322. subst(yytext, templin, &templin[sizeof templin - 1]);
  323. if(lastch) /* copy the stuff after the semicolon */
  324. {
  325. *lastchp = lastch;
  326. strcat(templin, lastchp);
  327. }
  328. strcpy(yytext, templin);
  329. /* process include files after macro substitution */
  330. if(strncmp(text, "include", 7) == 0) {
  331. if (isinclude(text+7))
  332. goto again;
  333. }
  334. for(p = zznextc = text ; *p ; ++p )
  335. if(*p!=' ' && *p!='\t')
  336. return START;
  337. goto again;
  338. }
  339. static int
  340. isinclude(char *s)
  341. {
  342. char *t;
  343. struct fstack *p;
  344. for(t=s; *t==' ' || *t=='\t' ; ++t)
  345. ;
  346. if(t == s)
  347. return NO;
  348. for(s = t; *s!='\n' && *s!='#' && *s!='\0' ; ++s)
  349. if(*s == ':')
  350. return NO;
  351. *s = '\0';
  352. if(ninclude >= MAXINCLUDE)
  353. fatal("include depth exceeded");
  354. p = filestack + ninclude;
  355. p->fin = fin;
  356. p->lineno = yylineno;
  357. p->fname = copys(t);
  358. if( (fin = fopen(t, "r")) == NULL)
  359. fatal1("Cannot open include file %s", t);
  360. yylineno = 0;
  361. ++ninclude;
  362. return YES;
  363. }
  364. int
  365. yyerror(char *s, ...)
  366. {
  367. char buf[100];
  368. sprintf(buf, "line %d of file %s: %s",
  369. yylineno, filestack[ninclude-1].fname, s);
  370. fatal(buf);
  371. return 0;
  372. }