| 1 | %{#include "defs" |
| 2 | %} |
| 3 | |
| 4 | %term NAME SHELLINE START MACRODEF COLON DOUBLECOLON GREATER |
| 5 | %union |
| 6 | { |
| 7 | struct shblock *yshblock; |
| 8 | struct depblock *ydepblock; |
| 9 | struct nameblock *ynameblock; |
| 10 | } |
| 11 | |
| 12 | %type <yshblock> SHELLINE, shlist, shellist |
| 13 | %type <ynameblock> NAME, namelist |
| 14 | %type <ydepblock> deplist, dlist |
| 15 | |
| 16 | |
| 17 | %% |
| 18 | |
| 19 | %{ |
| 20 | struct depblock *pp; |
| 21 | FSTATIC struct shblock *prevshp; |
| 22 | |
| 23 | FSTATIC struct nameblock *lefts[NLEFTS]; |
| 24 | struct nameblock *leftp; |
| 25 | FSTATIC int nlefts; |
| 26 | |
| 27 | struct lineblock *lp, *lpp; |
| 28 | FSTATIC struct depblock *prevdep; |
| 29 | FSTATIC int sepc; |
| 30 | %} |
| 31 | |
| 32 | |
| 33 | file: |
| 34 | | file comline |
| 35 | ; |
| 36 | |
| 37 | comline: START |
| 38 | | MACRODEF |
| 39 | | START namelist deplist shellist = { |
| 40 | while( --nlefts >= 0) |
| 41 | { |
| 42 | leftp = lefts[nlefts]; |
| 43 | if(leftp->septype == 0) |
| 44 | leftp->septype = sepc; |
| 45 | else if(leftp->septype != sepc) |
| 46 | fprintf(stderr, "Inconsistent rules lines for `%s'\n", |
| 47 | leftp->namep); |
| 48 | else if(sepc==ALLDEPS && *(leftp->namep)!='.' && $4!=0) |
| 49 | { |
| 50 | for(lp=leftp->linep; lp->nxtlineblock!=0; lp=lp->nxtlineblock) |
| 51 | if(lp->shp) |
| 52 | fprintf(stderr, "Multiple rules lines for `%s'\n", |
| 53 | leftp->namep); |
| 54 | } |
| 55 | |
| 56 | lp = ALLOC(lineblock); |
| 57 | lp->nxtlineblock = NULL; |
| 58 | lp->depp = $3; |
| 59 | lp->shp = $4; |
| 60 | |
| 61 | if(! unequal(leftp->namep, ".SUFFIXES") && $3==0) |
| 62 | leftp->linep = 0; |
| 63 | else if(leftp->linep == 0) |
| 64 | leftp->linep = lp; |
| 65 | else { |
| 66 | for(lpp = leftp->linep; lpp->nxtlineblock; |
| 67 | lpp = lpp->nxtlineblock) ; |
| 68 | if(sepc==ALLDEPS && leftp->namep[0]=='.') |
| 69 | lpp->shp = 0; |
| 70 | lpp->nxtlineblock = lp; |
| 71 | } |
| 72 | } |
| 73 | } |
| 74 | | error |
| 75 | ; |
| 76 | |
| 77 | namelist: NAME = { lefts[0] = $1; nlefts = 1; } |
| 78 | | namelist NAME = { lefts[nlefts++] = $2; |
| 79 | if(nlefts>NLEFTS) fatal("Too many lefts"); } |
| 80 | ; |
| 81 | |
| 82 | deplist: |
| 83 | { |
| 84 | char junk[10]; |
| 85 | sprintf(junk, "%d", yylineno); |
| 86 | fatal1("Must be a separator on rules line %s", junk); |
| 87 | } |
| 88 | | dlist |
| 89 | ; |
| 90 | |
| 91 | dlist: sepchar = { prevdep = 0; $$ = 0; } |
| 92 | | dlist NAME = { |
| 93 | pp = ALLOC(depblock); |
| 94 | pp->nxtdepblock = NULL; |
| 95 | pp->depname = $2; |
| 96 | if(prevdep == 0) $$ = pp; |
| 97 | else prevdep->nxtdepblock = pp; |
| 98 | prevdep = pp; |
| 99 | } |
| 100 | ; |
| 101 | |
| 102 | sepchar: COLON = { sepc = ALLDEPS; } |
| 103 | | DOUBLECOLON = { sepc = SOMEDEPS; } |
| 104 | ; |
| 105 | |
| 106 | shellist: = {$$ = 0; } |
| 107 | | shlist = { $$ = $1; } |
| 108 | ; |
| 109 | |
| 110 | shlist: SHELLINE = { $$ = $1; prevshp = $1; } |
| 111 | | shlist SHELLINE = { $$ = $1; |
| 112 | prevshp->nxtshblock = $2; |
| 113 | prevshp = $2; |
| 114 | } |
| 115 | ; |
| 116 | |
| 117 | %% |
| 118 | \f |
| 119 | char *zznextc; /* zero if need another line; otherwise points to next char */ |
| 120 | int yylineno; |
| 121 | extern FILE * fin; |
| 122 | |
| 123 | yylex() |
| 124 | { |
| 125 | register char *p; |
| 126 | register char *q; |
| 127 | char word[INMAX]; |
| 128 | |
| 129 | if(zznextc == 0) |
| 130 | return( nextlin() ); |
| 131 | |
| 132 | while( isspace(*zznextc) ) |
| 133 | ++zznextc; |
| 134 | |
| 135 | if(*zznextc == '\0') |
| 136 | return( nextlin() ); |
| 137 | |
| 138 | if(*zznextc == ':') |
| 139 | { |
| 140 | if(*++zznextc == ':') |
| 141 | { |
| 142 | ++zznextc; |
| 143 | return(DOUBLECOLON); |
| 144 | } |
| 145 | else return(COLON); |
| 146 | } |
| 147 | |
| 148 | if(*zznextc == '>') |
| 149 | { |
| 150 | ++zznextc; |
| 151 | return(GREATER); |
| 152 | } |
| 153 | |
| 154 | if(*zznextc == ';') |
| 155 | return( retsh(zznextc) ); |
| 156 | |
| 157 | p = zznextc; |
| 158 | q = word; |
| 159 | |
| 160 | while( ! ( funny[*p] & TERMINAL) ) |
| 161 | *q++ = *p++; |
| 162 | |
| 163 | if(p != zznextc) |
| 164 | { |
| 165 | *q = '\0'; |
| 166 | if((yylval.ynameblock=srchname(word))==0) |
| 167 | yylval.ynameblock = makename(word); |
| 168 | zznextc = p; |
| 169 | return(NAME); |
| 170 | } |
| 171 | |
| 172 | else { |
| 173 | fprintf(stderr,"Bad character %c (octal %o), line %d", |
| 174 | *zznextc,*zznextc,yylineno); |
| 175 | fatal( (char *) NULL ); |
| 176 | } |
| 177 | return(0); /* never executed */ |
| 178 | } |
| 179 | |
| 180 | |
| 181 | |
| 182 | |
| 183 | |
| 184 | retsh(q) |
| 185 | char *q; |
| 186 | { |
| 187 | register char *p; |
| 188 | struct shblock *sp; |
| 189 | char *copys(); |
| 190 | |
| 191 | for(p=q+1 ; *p==' '||*p=='\t' ; ++p) ; |
| 192 | |
| 193 | sp = ALLOC(shblock); |
| 194 | sp->nxtshblock = NULL; |
| 195 | sp->shbp = (fin == NULL ? p : copys(p) ); |
| 196 | yylval.yshblock = sp; |
| 197 | zznextc = 0; |
| 198 | return(SHELLINE); |
| 199 | } |
| 200 | \f |
| 201 | nextlin() |
| 202 | { |
| 203 | static char yytext[INMAX]; |
| 204 | static char *yytextl = yytext+INMAX; |
| 205 | char *text, templin[INMAX]; |
| 206 | register char c; |
| 207 | register char *p, *t; |
| 208 | char lastch, *lastchp; |
| 209 | extern char **linesptr; |
| 210 | int incom; |
| 211 | int kc; |
| 212 | |
| 213 | again: |
| 214 | |
| 215 | incom = NO; |
| 216 | zznextc = 0; |
| 217 | |
| 218 | if(fin == NULL) |
| 219 | { |
| 220 | if( (text = *linesptr++) == 0) |
| 221 | return(0); |
| 222 | ++yylineno; |
| 223 | } |
| 224 | |
| 225 | else { |
| 226 | for(p = text = yytext ; p<yytextl ; *p++ = kc) |
| 227 | switch(kc = getc(fin)) |
| 228 | { |
| 229 | case '\t': |
| 230 | if(p != yytext) |
| 231 | break; |
| 232 | case ';': |
| 233 | incom = YES; |
| 234 | break; |
| 235 | |
| 236 | case '#': |
| 237 | if(! incom) |
| 238 | kc = '\0'; |
| 239 | break; |
| 240 | |
| 241 | case '\n': |
| 242 | ++yylineno; |
| 243 | if(p==yytext || p[-1]!='\\') |
| 244 | { |
| 245 | *p = '\0'; |
| 246 | goto endloop; |
| 247 | } |
| 248 | p[-1] = ' '; |
| 249 | while( (kc=getc(fin))=='\t' || kc==' ' || kc=='\n') |
| 250 | if(kc == '\n') |
| 251 | ++yylineno; |
| 252 | |
| 253 | if(kc != EOF) |
| 254 | break; |
| 255 | case EOF: |
| 256 | *p = '\0'; |
| 257 | return(0); |
| 258 | } |
| 259 | |
| 260 | fatal("line too long"); |
| 261 | } |
| 262 | |
| 263 | endloop: |
| 264 | |
| 265 | if((c = text[0]) == '\t') |
| 266 | return( retsh(text) ); |
| 267 | |
| 268 | if(isalpha(c) || isdigit(c) || c==' ' || c=='.') |
| 269 | for(p=text+1; *p!='\0'; ) |
| 270 | if(*p == ':') |
| 271 | break; |
| 272 | else if(*p++ == '=') |
| 273 | { |
| 274 | eqsign(text); |
| 275 | return(MACRODEF); |
| 276 | } |
| 277 | |
| 278 | /* substitute for macros on dependency line up to the semicolon if any */ |
| 279 | |
| 280 | for(t = yytext ; *t!='\0' && *t!=';' ; ++t) |
| 281 | ; |
| 282 | |
| 283 | lastchp = t; |
| 284 | lastch = *t; |
| 285 | *t = '\0'; |
| 286 | |
| 287 | subst(yytext, templin); /* Substitute for macros on dependency lines */ |
| 288 | |
| 289 | if(lastch) |
| 290 | { |
| 291 | for(t = templin ; *t ; ++t) |
| 292 | ; |
| 293 | *t = lastch; |
| 294 | while( *++t = *++lastchp ) ; |
| 295 | } |
| 296 | |
| 297 | p = templin; |
| 298 | t = yytext; |
| 299 | while( *t++ = *p++ ) |
| 300 | ; |
| 301 | |
| 302 | for(p = zznextc = text ; *p ; ++p ) |
| 303 | if(*p!=' ' && *p!='\t') |
| 304 | return(START); |
| 305 | goto again; |
| 306 | } |