| 1 | /* |
| 2 | * Copyright (c) 1982 Regents of the University of California |
| 3 | */ |
| 4 | #ifndef lint |
| 5 | static char sccsid[] = "@(#)asscan1.c 4.1 %G%"; |
| 6 | #endif not lint |
| 7 | |
| 8 | #include "asscanl.h" |
| 9 | |
| 10 | inittmpfile() |
| 11 | { |
| 12 | if (passno == 1){ |
| 13 | if (useVM){ |
| 14 | bufstart = &tokbuf[0]; |
| 15 | buftail = &tokbuf[1]; |
| 16 | bufstart->tok_next = buftail; |
| 17 | buftail->tok_next = 0; |
| 18 | } |
| 19 | tokbuf[0].tok_count = -1; |
| 20 | tokbuf[1].tok_count = -1; |
| 21 | } |
| 22 | tok_temp = 0; |
| 23 | tok_free = 0; |
| 24 | bufno = 0; |
| 25 | emptybuf = &tokbuf[bufno]; |
| 26 | tokptr = 0; |
| 27 | tokub = 0; |
| 28 | } |
| 29 | |
| 30 | closetmpfile() |
| 31 | { |
| 32 | if (passno == 1){ |
| 33 | if (useVM){ |
| 34 | emptybuf->toks[emptybuf->tok_count++] = PARSEEOF; |
| 35 | } else { |
| 36 | /* |
| 37 | * Clean up the buffers that haven't been |
| 38 | * written out yet |
| 39 | */ |
| 40 | if (tokbuf[bufno ^ 1].tok_count >= 0){ |
| 41 | if (writeTEST((char *)&tokbuf[bufno ^ 1], sizeof *emptybuf, 1, tmpfil)){ |
| 42 | badwrite: |
| 43 | yyerror("Unexpected end of file writing the interpass tmp file"); |
| 44 | exit(2); |
| 45 | } |
| 46 | } |
| 47 | /* |
| 48 | * Ensure that we will read an End of file, |
| 49 | * if there are more than one file names |
| 50 | * in the argument list |
| 51 | */ |
| 52 | tokbuf[bufno].toks[tokbuf[bufno].tok_count++] = PARSEEOF; |
| 53 | if (writeTEST((char *)&tokbuf[bufno], sizeof *emptybuf, 1, tmpfil)) |
| 54 | goto badwrite; |
| 55 | } |
| 56 | } /*end of being pass 1*/ |
| 57 | } |
| 58 | |
| 59 | inttoktype yylex() |
| 60 | { |
| 61 | register ptrall bufptr; |
| 62 | register inttoktype val; |
| 63 | register struct exp *locxp; |
| 64 | /* |
| 65 | * No local variables to be allocated; this saves |
| 66 | * one piddling instruction.. |
| 67 | */ |
| 68 | static int Lastjxxx; |
| 69 | |
| 70 | bufptr = tokptr; /*copy in the global value*/ |
| 71 | top: |
| 72 | if (bufptr < tokub){ |
| 73 | gtoken(val, bufptr); |
| 74 | switch(yylval = val){ |
| 75 | case PARSEEOF: |
| 76 | yylval = val = PARSEEOF; |
| 77 | break; |
| 78 | case BFINT: |
| 79 | case INT: |
| 80 | if (xp >= &explist[NEXP]) |
| 81 | yyerror("Too many expressions; try simplyfing"); |
| 82 | else |
| 83 | locxp = xp++; |
| 84 | locxp->e_number = Znumber; |
| 85 | locxp->e_number.num_tag = TYPL; |
| 86 | glong(locxp->e_xvalue, bufptr); |
| 87 | makevalue: |
| 88 | locxp->e_xtype = XABS; |
| 89 | locxp->e_xloc = 0; |
| 90 | locxp->e_xname = NULL; |
| 91 | yylval = (int)locxp; |
| 92 | break; |
| 93 | case BIGNUM: |
| 94 | if (xp >= &explist[NEXP]) |
| 95 | yyerror("Too many expressions; try simplyfing"); |
| 96 | else |
| 97 | locxp = xp++; |
| 98 | gnumber(locxp->e_number, bufptr); |
| 99 | goto makevalue; |
| 100 | case NAME: |
| 101 | gptr(yylval, bufptr); |
| 102 | lastnam = (struct symtab *)yylval; |
| 103 | break; |
| 104 | case SIZESPEC: |
| 105 | case REG: |
| 106 | gchar(yylval, bufptr); |
| 107 | break; |
| 108 | case INSTn: |
| 109 | case INST0: |
| 110 | gopcode(yyopcode, bufptr); |
| 111 | break; |
| 112 | case IJXXX: |
| 113 | gopcode(yyopcode, bufptr); |
| 114 | /* We can't cast Lastjxxx into (int *) here.. */ |
| 115 | gptr(Lastjxxx, bufptr); |
| 116 | lastjxxx = (struct symtab *)Lastjxxx; |
| 117 | break; |
| 118 | case ILINESKIP: |
| 119 | gint(yylval, bufptr); |
| 120 | lineno += yylval; |
| 121 | goto top; |
| 122 | case SKIP: |
| 123 | eatskiplg(bufptr); |
| 124 | goto top; |
| 125 | case VOID: |
| 126 | goto top; |
| 127 | case STRING: |
| 128 | strptr = &strbuf[strno ^= 1]; |
| 129 | strptr->str_lg = *((lgtype *)bufptr); |
| 130 | movestr(&strptr->str[0], |
| 131 | (char *)bufptr + sizeof(lgtype), |
| 132 | strptr->str_lg); |
| 133 | eatstrlg(bufptr); |
| 134 | yylval = (int)strptr; |
| 135 | break; |
| 136 | case ISTAB: |
| 137 | case ISTABSTR: |
| 138 | case ISTABNONE: |
| 139 | case ISTABDOT: |
| 140 | case IALIGN: |
| 141 | gptr(yylval, bufptr); |
| 142 | break; |
| 143 | } |
| 144 | #ifdef DEBUG |
| 145 | if (toktrace){ |
| 146 | char *tok_to_name(); |
| 147 | printf("P: %d T#: %4d, %s ", |
| 148 | passno, bufptr - firsttoken, tok_to_name(val)); |
| 149 | switch(val){ |
| 150 | case INT: printf("val %d", |
| 151 | ((struct exp *)yylval)->e_xvalue); |
| 152 | break; |
| 153 | case BFINT: printf("val %d", |
| 154 | ((struct exp *)yylval)->e_xvalue); |
| 155 | break; |
| 156 | case BIGNUM: bignumprint(((struct exp*)yylval)->e_number); |
| 157 | break; |
| 158 | case NAME: printf("\"%.8s\"", |
| 159 | ((struct symtab *)yylval)->s_name); |
| 160 | break; |
| 161 | case REG: printf(" r%d", |
| 162 | yylval); |
| 163 | break; |
| 164 | case IJXXX: |
| 165 | case INST0: |
| 166 | case INSTn: if (ITABCHECK(yyopcode)) |
| 167 | printf("%.8s", ITABFETCH(yyopcode)->s_name); |
| 168 | else |
| 169 | printf("IJXXX or INST0 or INSTn can't get into the itab\n"); |
| 170 | break; |
| 171 | case STRING: printf("length %d ", |
| 172 | ((struct strdesc *)yylval)->str_lg); |
| 173 | printf("value\"%s\"", |
| 174 | ((struct strdesc *)yylval)->str); |
| 175 | break; |
| 176 | } /*end of the debug switch*/ |
| 177 | printf("\n"); |
| 178 | } |
| 179 | #endif DEBUG |
| 180 | |
| 181 | } else { /* start a new buffer */ |
| 182 | if (useVM){ |
| 183 | if (passno == 2){ |
| 184 | tok_temp = emptybuf->tok_next; |
| 185 | emptybuf->tok_next = tok_free; |
| 186 | tok_free = emptybuf; |
| 187 | emptybuf = tok_temp; |
| 188 | } else { |
| 189 | emptybuf = emptybuf->tok_next; |
| 190 | } |
| 191 | bufno += 1; |
| 192 | if (emptybuf == 0){ |
| 193 | struct tokbufdesc *newdallop; |
| 194 | int i; |
| 195 | if (passno == 2) |
| 196 | goto badread; |
| 197 | emptybuf = newdallop = (struct tokbufdesc *) |
| 198 | Calloc(TOKDALLOP, sizeof (struct tokbufdesc)); |
| 199 | for (i=0; i < TOKDALLOP; i++){ |
| 200 | buftail->tok_next = newdallop; |
| 201 | buftail = newdallop; |
| 202 | newdallop += 1; |
| 203 | } |
| 204 | buftail->tok_next = 0; |
| 205 | } /*end of need to get more buffers*/ |
| 206 | (bytetoktype *)bufptr = &(emptybuf->toks[0]); |
| 207 | if (passno == 1) |
| 208 | scan_dot_s(emptybuf); |
| 209 | } else { /*don't use VM*/ |
| 210 | bufno ^= 1; |
| 211 | emptybuf = &tokbuf[bufno]; |
| 212 | ((bytetoktype *)bufptr) = &(emptybuf->toks[0]); |
| 213 | if (passno == 1){ |
| 214 | /* |
| 215 | * First check if there are things to write |
| 216 | * out at all |
| 217 | */ |
| 218 | if (emptybuf->tok_count >= 0){ |
| 219 | if (writeTEST((char *)emptybuf, sizeof *emptybuf, 1, tmpfil)){ |
| 220 | yyerror("Unexpected end of file writing the interpass tmp file"); |
| 221 | exit(2); |
| 222 | } |
| 223 | } |
| 224 | scan_dot_s(emptybuf); |
| 225 | } else { /*pass 2*/ |
| 226 | if (readTEST((char *)emptybuf, sizeof *emptybuf, 1, tmpfil)){ |
| 227 | badread: |
| 228 | yyerror("Unexpected end of file while reading the interpass tmp file"); |
| 229 | exit(1); |
| 230 | } |
| 231 | } |
| 232 | } /*end of using a real live file*/ |
| 233 | (char *)tokub = (char *)bufptr + emptybuf->tok_count; |
| 234 | #ifdef DEBUG |
| 235 | firsttoken = bufptr; |
| 236 | if (debug) |
| 237 | printf("created buffernumber %d with %d tokens\n", |
| 238 | bufno, emptybuf->tok_count); |
| 239 | #endif DEBUG |
| 240 | goto top; |
| 241 | } /*end of reading/creating a new buffer*/ |
| 242 | tokptr = bufptr; /*copy back the global value*/ |
| 243 | return(val); |
| 244 | } /*end of yylex*/ |
| 245 | |
| 246 | |
| 247 | buildskip(from, to) |
| 248 | register ptrall from, to; |
| 249 | { |
| 250 | int diff; |
| 251 | register struct tokbufdesc *middlebuf; |
| 252 | /* |
| 253 | * check if from and to are in the same buffer |
| 254 | * from and to DIFFER BY AT MOST 1 buffer and to is |
| 255 | * always ahead of from, with to being in the buffer emptybuf |
| 256 | * points to. |
| 257 | * The hard part here is accounting for the case where the |
| 258 | * skip is to cross a buffer boundary; we must construct |
| 259 | * two skips. |
| 260 | * |
| 261 | * Figure out where the buffer boundary between from and to is |
| 262 | * It's easy in VM, as buffers increase to high memory, but |
| 263 | * w/o VM, we alternate between two buffers, and want |
| 264 | * to look at the exact middle of the contiguous buffer region. |
| 265 | */ |
| 266 | middlebuf = useVM ? emptybuf : &tokbuf[1]; |
| 267 | if ( ( (bytetoktype *)from > (bytetoktype *)middlebuf) |
| 268 | ^ ( (bytetoktype *)to > (bytetoktype *)middlebuf) |
| 269 | ){ /*split across a buffer boundary*/ |
| 270 | ptoken(from, SKIP); |
| 271 | /* |
| 272 | * Set the skip so it lands someplace beyond |
| 273 | * the end of this buffer. |
| 274 | * When we pull this skip out in the second pass, |
| 275 | * we will temporarily move the current pointer |
| 276 | * out beyond the end of the buffer, but immediately |
| 277 | * do a compare and fail the compare, and then reset |
| 278 | * all the pointers correctly to point into the next buffer. |
| 279 | */ |
| 280 | bskiplg(from, TOKBUFLG + 1); |
| 281 | /* |
| 282 | * Now, force from to be in the same buffer as to |
| 283 | */ |
| 284 | (bytetoktype *)from = (bytetoktype *)&(emptybuf->toks[0]); |
| 285 | } |
| 286 | /* |
| 287 | * Now, to and from are in the same buffer |
| 288 | */ |
| 289 | if (from > to) |
| 290 | yyerror("Internal error: bad skip construction"); |
| 291 | else { |
| 292 | if ( (diff = (bytetoktype *)to - (bytetoktype *)from) >= |
| 293 | (sizeof(bytetoktype) + sizeof(lgtype) + 1)) { |
| 294 | ptoken(from, SKIP); |
| 295 | bskipfromto(from, to); |
| 296 | } else { |
| 297 | for ( ; diff > 0; --diff) |
| 298 | ptoken(from, VOID); |
| 299 | } |
| 300 | } |
| 301 | } |
| 302 | |
| 303 | movestr(to, from, lg) |
| 304 | register char *to, *from; |
| 305 | register int lg; |
| 306 | { |
| 307 | if (lg <= 0) return; |
| 308 | do |
| 309 | *to++ = *from++; |
| 310 | while (--lg); |
| 311 | } |
| 312 | |
| 313 | new_dot_s(namep) |
| 314 | char *namep; |
| 315 | { |
| 316 | newfflag = 1; |
| 317 | newfname = namep; |
| 318 | dotsname = namep; |
| 319 | lineno = 1; |
| 320 | scanlineno = 1; |
| 321 | } |