1 | /* $Id: lex.c,v 1.12 2008/05/11 15:28:03 ragge Exp $ */
|
---|
2 | /*
|
---|
3 | * Copyright(C) Caldera International Inc. 2001-2002. All rights reserved.
|
---|
4 | *
|
---|
5 | * Redistribution and use in source and binary forms, with or without
|
---|
6 | * modification, are permitted provided that the following conditions
|
---|
7 | * are met:
|
---|
8 | *
|
---|
9 | * Redistributions of source code and documentation must retain the above
|
---|
10 | * copyright notice, this list of conditions and the following disclaimer.
|
---|
11 | * Redistributions in binary form must reproduce the above copyright
|
---|
12 | * notice, this list of conditionsand the following disclaimer in the
|
---|
13 | * documentation and/or other materials provided with the distribution.
|
---|
14 | * All advertising materials mentioning features or use of this software
|
---|
15 | * must display the following acknowledgement:
|
---|
16 | * This product includes software developed or owned by Caldera
|
---|
17 | * International, Inc.
|
---|
18 | * Neither the name of Caldera International, Inc. nor the names of other
|
---|
19 | * contributors may be used to endorse or promote products derived from
|
---|
20 | * this software without specific prior written permission.
|
---|
21 | *
|
---|
22 | * USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA
|
---|
23 | * INTERNATIONAL, INC. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR
|
---|
24 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
---|
25 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
---|
26 | * DISCLAIMED. IN NO EVENT SHALL CALDERA INTERNATIONAL, INC. BE LIABLE
|
---|
27 | * FOR ANY DIRECT, INDIRECT INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
---|
28 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
---|
29 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
---|
30 | * HOWEVER CAUSED AND ON ANY THEORY OFLIABILITY, WHETHER IN CONTRACT,
|
---|
31 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
---|
32 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
---|
33 | * POSSIBILITY OF SUCH DAMAGE.
|
---|
34 | */
|
---|
35 | #include "defines.h"
|
---|
36 | #include "defs.h"
|
---|
37 |
|
---|
38 | #include "gram.h"
|
---|
39 |
|
---|
40 | # define BLANK ' '
|
---|
41 | # define MYQUOTE (2)
|
---|
42 | # define SEOF 0
|
---|
43 |
|
---|
44 | /* card types */
|
---|
45 |
|
---|
46 | # define STEOF 1
|
---|
47 | # define STINITIAL 2
|
---|
48 | # define STCONTINUE 3
|
---|
49 |
|
---|
50 | /* lex states */
|
---|
51 |
|
---|
52 | #define NEWSTMT 1
|
---|
53 | #define FIRSTTOKEN 2
|
---|
54 | #define OTHERTOKEN 3
|
---|
55 | #define RETEOS 4
|
---|
56 |
|
---|
57 |
|
---|
58 | LOCAL int stkey;
|
---|
59 | LOCAL int stno;
|
---|
60 | LOCAL long int nxtstno;
|
---|
61 | LOCAL int parlev;
|
---|
62 | LOCAL int expcom;
|
---|
63 | LOCAL int expeql;
|
---|
64 | LOCAL char *nextch;
|
---|
65 | LOCAL char *lastch;
|
---|
66 | LOCAL char *nextcd = NULL;
|
---|
67 | LOCAL char *endcd;
|
---|
68 | LOCAL int prevlin;
|
---|
69 | LOCAL int thislin;
|
---|
70 | LOCAL int code;
|
---|
71 | LOCAL int lexstate = NEWSTMT;
|
---|
72 | LOCAL char s[1390];
|
---|
73 | LOCAL char *send = s+20*66;
|
---|
74 | LOCAL int nincl = 0;
|
---|
75 |
|
---|
76 | struct inclfile
|
---|
77 | {
|
---|
78 | struct inclfile *inclnext;
|
---|
79 | FILEP inclfp;
|
---|
80 | char *inclname;
|
---|
81 | int incllno;
|
---|
82 | char *incllinp;
|
---|
83 | int incllen;
|
---|
84 | int inclcode;
|
---|
85 | ftnint inclstno;
|
---|
86 | } ;
|
---|
87 |
|
---|
88 | LOCAL struct inclfile *inclp = NULL;
|
---|
89 | struct keylist { char *keyname; int keyval; } ;
|
---|
90 | struct punctlist { char punchar; int punval; };
|
---|
91 | struct fmtlist { char fmtchar; int fmtval; };
|
---|
92 | struct dotlist { char *dotname; int dotval; };
|
---|
93 | LOCAL struct dotlist dots[];
|
---|
94 | LOCAL struct keylist *keystart[26], *keyend[26];
|
---|
95 | LOCAL struct keylist keys[];
|
---|
96 |
|
---|
97 | LOCAL int getcds(void);
|
---|
98 | LOCAL void crunch(void);
|
---|
99 | LOCAL void analyz(void);
|
---|
100 | LOCAL int gettok(void);
|
---|
101 | LOCAL int getcd(char *b);
|
---|
102 | LOCAL int getkwd(void);
|
---|
103 | LOCAL int popinclude(void);
|
---|
104 |
|
---|
105 | /*
|
---|
106 | * called from main() to start parsing.
|
---|
107 | * name[0] may be \0 if stdin.
|
---|
108 | */
|
---|
109 | int
|
---|
110 | inilex(char *name)
|
---|
111 | {
|
---|
112 | nincl = 0;
|
---|
113 | inclp = NULL;
|
---|
114 | doinclude(name);
|
---|
115 | lexstate = NEWSTMT;
|
---|
116 | return(NO);
|
---|
117 | }
|
---|
118 |
|
---|
119 |
|
---|
120 |
|
---|
121 | /* throw away the rest of the current line */
|
---|
122 | void
|
---|
123 | flline()
|
---|
124 | {
|
---|
125 | lexstate = RETEOS;
|
---|
126 | }
|
---|
127 |
|
---|
128 |
|
---|
129 |
|
---|
130 | char *lexline(n)
|
---|
131 | ftnint *n;
|
---|
132 | {
|
---|
133 | *n = (lastch - nextch) + 1;
|
---|
134 | return(nextch);
|
---|
135 | }
|
---|
136 |
|
---|
137 |
|
---|
138 |
|
---|
139 |
|
---|
140 | void
|
---|
141 | doinclude(char *name)
|
---|
142 | {
|
---|
143 | FILEP fp;
|
---|
144 | struct inclfile *t;
|
---|
145 |
|
---|
146 | if(inclp) {
|
---|
147 | inclp->incllno = thislin;
|
---|
148 | inclp->inclcode = code;
|
---|
149 | inclp->inclstno = nxtstno;
|
---|
150 | if(nextcd)
|
---|
151 | inclp->incllinp =
|
---|
152 | copyn(inclp->incllen = endcd-nextcd , nextcd);
|
---|
153 | else
|
---|
154 | inclp->incllinp = 0;
|
---|
155 | }
|
---|
156 | nextcd = NULL;
|
---|
157 |
|
---|
158 | if(++nincl >= MAXINCLUDES)
|
---|
159 | fatal("includes nested too deep");
|
---|
160 | if(name[0] == '\0')
|
---|
161 | fp = stdin;
|
---|
162 | else
|
---|
163 | fp = fopen(name, "r");
|
---|
164 | if( fp ) {
|
---|
165 | t = inclp;
|
---|
166 | inclp = ALLOC(inclfile);
|
---|
167 | inclp->inclnext = t;
|
---|
168 | prevlin = thislin = 0;
|
---|
169 | infname = inclp->inclname = name;
|
---|
170 | infile = inclp->inclfp = fp;
|
---|
171 | } else {
|
---|
172 | fprintf(diagfile, "Cannot open file %s", name);
|
---|
173 | done(1);
|
---|
174 | }
|
---|
175 | }
|
---|
176 |
|
---|
177 |
|
---|
178 |
|
---|
179 |
|
---|
180 | LOCAL int
|
---|
181 | popinclude()
|
---|
182 | {
|
---|
183 | struct inclfile *t;
|
---|
184 | register char *p;
|
---|
185 | register int k;
|
---|
186 |
|
---|
187 | if(infile != stdin)
|
---|
188 | fclose(infile);
|
---|
189 | ckfree(infname);
|
---|
190 |
|
---|
191 | --nincl;
|
---|
192 | t = inclp->inclnext;
|
---|
193 | ckfree(inclp);
|
---|
194 | inclp = t;
|
---|
195 | if(inclp == NULL)
|
---|
196 | return(NO);
|
---|
197 |
|
---|
198 | infile = inclp->inclfp;
|
---|
199 | infname = inclp->inclname;
|
---|
200 | prevlin = thislin = inclp->incllno;
|
---|
201 | code = inclp->inclcode;
|
---|
202 | stno = nxtstno = inclp->inclstno;
|
---|
203 | if(inclp->incllinp) {
|
---|
204 | endcd = nextcd = s;
|
---|
205 | k = inclp->incllen;
|
---|
206 | p = inclp->incllinp;
|
---|
207 | while(--k >= 0)
|
---|
208 | *endcd++ = *p++;
|
---|
209 | ckfree(inclp->incllinp);
|
---|
210 | } else
|
---|
211 | nextcd = NULL;
|
---|
212 | return(YES);
|
---|
213 | }
|
---|
214 |
|
---|
215 |
|
---|
216 |
|
---|
217 | int
|
---|
218 | yylex()
|
---|
219 | {
|
---|
220 | static int tokno;
|
---|
221 |
|
---|
222 | switch(lexstate)
|
---|
223 | {
|
---|
224 | case NEWSTMT : /* need a new statement */
|
---|
225 | if(getcds() == STEOF)
|
---|
226 | return(SEOF);
|
---|
227 | crunch();
|
---|
228 | tokno = 0;
|
---|
229 | lexstate = FIRSTTOKEN;
|
---|
230 | yylval.num = stno;
|
---|
231 | stno = nxtstno;
|
---|
232 | toklen = 0;
|
---|
233 | return(SLABEL);
|
---|
234 |
|
---|
235 | first:
|
---|
236 | case FIRSTTOKEN : /* first step on a statement */
|
---|
237 | analyz();
|
---|
238 | lexstate = OTHERTOKEN;
|
---|
239 | tokno = 1;
|
---|
240 | return(stkey);
|
---|
241 |
|
---|
242 | case OTHERTOKEN : /* return next token */
|
---|
243 | if(nextch > lastch)
|
---|
244 | goto reteos;
|
---|
245 | ++tokno;
|
---|
246 | if((stkey==SLOGIF || stkey==SELSEIF) && parlev==0 && tokno>3) goto first;
|
---|
247 | if(stkey==SASSIGN && tokno==3 && nextch<lastch &&
|
---|
248 | nextch[0]=='t' && nextch[1]=='o')
|
---|
249 | {
|
---|
250 | nextch+=2;
|
---|
251 | return(STO);
|
---|
252 | }
|
---|
253 | return(gettok());
|
---|
254 |
|
---|
255 | reteos:
|
---|
256 | case RETEOS:
|
---|
257 | lexstate = NEWSTMT;
|
---|
258 | return(SEOS);
|
---|
259 | }
|
---|
260 | fatal1("impossible lexstate %d", lexstate);
|
---|
261 | /* NOTREACHED */
|
---|
262 | return 0; /* XXX gcc */
|
---|
263 | }
|
---|
264 |
|
---|
265 | LOCAL int
|
---|
266 | getcds()
|
---|
267 | {
|
---|
268 | register char *p, *q;
|
---|
269 |
|
---|
270 | top:
|
---|
271 | if(nextcd == NULL)
|
---|
272 | {
|
---|
273 | code = getcd( nextcd = s );
|
---|
274 | stno = nxtstno;
|
---|
275 | prevlin = thislin;
|
---|
276 | }
|
---|
277 | if(code == STEOF) {
|
---|
278 | if( popinclude() )
|
---|
279 | goto top;
|
---|
280 | else
|
---|
281 | return(STEOF);
|
---|
282 | }
|
---|
283 | if(code == STCONTINUE)
|
---|
284 | {
|
---|
285 | lineno = thislin;
|
---|
286 | err("illegal continuation card ignored");
|
---|
287 | nextcd = NULL;
|
---|
288 | goto top;
|
---|
289 | }
|
---|
290 |
|
---|
291 | if(nextcd > s)
|
---|
292 | {
|
---|
293 | q = nextcd;
|
---|
294 | p = s;
|
---|
295 | while(q < endcd)
|
---|
296 | *p++ = *q++;
|
---|
297 | endcd = p;
|
---|
298 | }
|
---|
299 | for(nextcd = endcd ;
|
---|
300 | nextcd+66<=send && (code = getcd(nextcd))==STCONTINUE ;
|
---|
301 | nextcd = endcd )
|
---|
302 | ;
|
---|
303 | nextch = s;
|
---|
304 | lastch = nextcd - 1;
|
---|
305 | if(nextcd >= send)
|
---|
306 | nextcd = NULL;
|
---|
307 | lineno = prevlin;
|
---|
308 | prevlin = thislin;
|
---|
309 | return(STINITIAL);
|
---|
310 | }
|
---|
311 |
|
---|
312 | LOCAL int
|
---|
313 | getcd(b)
|
---|
314 | register char *b;
|
---|
315 | {
|
---|
316 | register int c;
|
---|
317 | register char *p, *bend;
|
---|
318 | int speclin;
|
---|
319 | static char a[6];
|
---|
320 | static char *aend = a+6;
|
---|
321 |
|
---|
322 | top:
|
---|
323 | endcd = b;
|
---|
324 | bend = b+66;
|
---|
325 | speclin = NO;
|
---|
326 |
|
---|
327 | if( (c = getc(infile)) == '&')
|
---|
328 | {
|
---|
329 | a[0] = BLANK;
|
---|
330 | a[5] = 'x';
|
---|
331 | speclin = YES;
|
---|
332 | bend = send;
|
---|
333 | }
|
---|
334 | else if(c=='c' || c=='C' || c=='*')
|
---|
335 | {
|
---|
336 | while( (c = getc(infile)) != '\n')
|
---|
337 | if(c == EOF)
|
---|
338 | return(STEOF);
|
---|
339 | ++thislin;
|
---|
340 | goto top;
|
---|
341 | }
|
---|
342 |
|
---|
343 | else if(c != EOF)
|
---|
344 | {
|
---|
345 | /* a tab in columns 1-6 skips to column 7 */
|
---|
346 | ungetc(c, infile);
|
---|
347 | for(p=a; p<aend && (c=getc(infile)) != '\n' && c!=EOF; )
|
---|
348 | if(c == '\t')
|
---|
349 | {
|
---|
350 | while(p < aend)
|
---|
351 | *p++ = BLANK;
|
---|
352 | speclin = YES;
|
---|
353 | bend = send;
|
---|
354 | }
|
---|
355 | else
|
---|
356 | *p++ = c;
|
---|
357 | }
|
---|
358 | if(c == EOF)
|
---|
359 | return(STEOF);
|
---|
360 | if(c == '\n')
|
---|
361 | {
|
---|
362 | p = a; /* XXX ??? */
|
---|
363 | while(p < aend)
|
---|
364 | *p++ = BLANK;
|
---|
365 | if( ! speclin )
|
---|
366 | while(endcd < bend)
|
---|
367 | *endcd++ = BLANK;
|
---|
368 | }
|
---|
369 | else { /* read body of line */
|
---|
370 | while( endcd<bend && (c=getc(infile)) != '\n' && c!=EOF )
|
---|
371 | *endcd++ = (c == '\t' ? BLANK : c);
|
---|
372 | if(c == EOF)
|
---|
373 | return(STEOF);
|
---|
374 | if(c != '\n')
|
---|
375 | {
|
---|
376 | while( (c=getc(infile)) != '\n')
|
---|
377 | if(c == EOF)
|
---|
378 | return(STEOF);
|
---|
379 | }
|
---|
380 |
|
---|
381 | if( ! speclin )
|
---|
382 | while(endcd < bend)
|
---|
383 | *endcd++ = BLANK;
|
---|
384 | }
|
---|
385 | ++thislin;
|
---|
386 | if(a[5]!=BLANK && a[5]!='0')
|
---|
387 | return(STCONTINUE);
|
---|
388 | for(p=a; p<aend; ++p)
|
---|
389 | if(*p != BLANK) goto initline;
|
---|
390 | for(p = b ; p<endcd ; ++p)
|
---|
391 | if(*p != BLANK) goto initline;
|
---|
392 | goto top;
|
---|
393 |
|
---|
394 | initline:
|
---|
395 | nxtstno = 0;
|
---|
396 | for(p = a ; p<a+5 ; ++p)
|
---|
397 | if(*p != BLANK) {
|
---|
398 | if(isdigit((int)*p))
|
---|
399 | nxtstno = 10*nxtstno + (*p - '0');
|
---|
400 | else {
|
---|
401 | lineno = thislin;
|
---|
402 | err("nondigit in statement number field");
|
---|
403 | nxtstno = 0;
|
---|
404 | break;
|
---|
405 | }
|
---|
406 | }
|
---|
407 | return(STINITIAL);
|
---|
408 | }
|
---|
409 |
|
---|
410 | LOCAL void
|
---|
411 | crunch()
|
---|
412 | {
|
---|
413 | register char *i, *j, *j0, *j1, *prvstr;
|
---|
414 | int ten, nh, quote;
|
---|
415 |
|
---|
416 | /* i is the next input character to be looked at
|
---|
417 | j is the next output character */
|
---|
418 | parlev = 0;
|
---|
419 | expcom = 0; /* exposed ','s */
|
---|
420 | expeql = 0; /* exposed equal signs */
|
---|
421 | j = s;
|
---|
422 | prvstr = s;
|
---|
423 | for(i=s ; i<=lastch ; ++i)
|
---|
424 | {
|
---|
425 | if(*i == BLANK) continue;
|
---|
426 | if(*i=='\'' || *i=='"')
|
---|
427 | {
|
---|
428 | quote = *i;
|
---|
429 | *j = MYQUOTE; /* special marker */
|
---|
430 | for(;;)
|
---|
431 | {
|
---|
432 | if(++i > lastch)
|
---|
433 | {
|
---|
434 | err("unbalanced quotes; closing quote supplied");
|
---|
435 | break;
|
---|
436 | }
|
---|
437 | if(*i == quote)
|
---|
438 | if(i<lastch && i[1]==quote) ++i;
|
---|
439 | else break;
|
---|
440 | else if(*i=='\\' && i<lastch)
|
---|
441 | switch(*++i)
|
---|
442 | {
|
---|
443 | case 't':
|
---|
444 | *i = '\t'; break;
|
---|
445 | case 'b':
|
---|
446 | *i = '\b'; break;
|
---|
447 | case 'n':
|
---|
448 | *i = '\n'; break;
|
---|
449 | case 'f':
|
---|
450 | *i = '\f'; break;
|
---|
451 | case '0':
|
---|
452 | *i = '\0'; break;
|
---|
453 | default:
|
---|
454 | break;
|
---|
455 | }
|
---|
456 | *++j = *i;
|
---|
457 | }
|
---|
458 | j[1] = MYQUOTE;
|
---|
459 | j += 2;
|
---|
460 | prvstr = j;
|
---|
461 | }
|
---|
462 | else if( (*i=='h' || *i=='H') && j>prvstr) /* test for Hollerith strings */
|
---|
463 | {
|
---|
464 | if( ! isdigit((int)j[-1])) goto copychar;
|
---|
465 | nh = j[-1] - '0';
|
---|
466 | ten = 10;
|
---|
467 | j1 = prvstr - 1;
|
---|
468 | if (j1<j-5) j1=j-5;
|
---|
469 | for(j0=j-2 ; j0>j1; -- j0)
|
---|
470 | {
|
---|
471 | if( ! isdigit((int)*j0 ) ) break;
|
---|
472 | nh += ten * (*j0-'0');
|
---|
473 | ten*=10;
|
---|
474 | }
|
---|
475 | if(j0 <= j1) goto copychar;
|
---|
476 | /* a hollerith must be preceded by a punctuation mark.
|
---|
477 | '*' is possible only as repetition factor in a data statement
|
---|
478 | not, in particular, in character*2h
|
---|
479 | */
|
---|
480 |
|
---|
481 | if( !(*j0=='*'&&s[0]=='d') && *j0!='/' && *j0!='(' &&
|
---|
482 | *j0!=',' && *j0!='=' && *j0!='.')
|
---|
483 | goto copychar;
|
---|
484 | if(i+nh > lastch)
|
---|
485 | {
|
---|
486 | err1("%dH too big", nh);
|
---|
487 | nh = lastch - i;
|
---|
488 | }
|
---|
489 | j0[1] = MYQUOTE; /* special marker */
|
---|
490 | j = j0 + 1;
|
---|
491 | while(nh-- > 0)
|
---|
492 | {
|
---|
493 | if(*++i == '\\')
|
---|
494 | switch(*++i)
|
---|
495 | {
|
---|
496 | case 't':
|
---|
497 | *i = '\t'; break;
|
---|
498 | case 'b':
|
---|
499 | *i = '\b'; break;
|
---|
500 | case 'n':
|
---|
501 | *i = '\n'; break;
|
---|
502 | case 'f':
|
---|
503 | *i = '\f'; break;
|
---|
504 | case '0':
|
---|
505 | *i = '\0'; break;
|
---|
506 | default:
|
---|
507 | break;
|
---|
508 | }
|
---|
509 | *++j = *i;
|
---|
510 | }
|
---|
511 | j[1] = MYQUOTE;
|
---|
512 | j+=2;
|
---|
513 | prvstr = j;
|
---|
514 | }
|
---|
515 | else {
|
---|
516 | if(*i == '(') ++parlev;
|
---|
517 | else if(*i == ')') --parlev;
|
---|
518 | else if(parlev == 0) {
|
---|
519 | if(*i == '=') expeql = 1;
|
---|
520 | else if(*i == ',') expcom = 1;
|
---|
521 | copychar: ; /*not a string of BLANK -- copy, shifting case if necessary */
|
---|
522 | }
|
---|
523 | if(shiftcase && isupper((int)*i))
|
---|
524 | *j++ = tolower((int)*i);
|
---|
525 | else *j++ = *i;
|
---|
526 | }
|
---|
527 | }
|
---|
528 | lastch = j - 1;
|
---|
529 | nextch = s;
|
---|
530 | }
|
---|
531 |
|
---|
532 | LOCAL void
|
---|
533 | analyz()
|
---|
534 | {
|
---|
535 | register char *i;
|
---|
536 |
|
---|
537 | if(parlev != 0)
|
---|
538 | {
|
---|
539 | err("unbalanced parentheses, statement skipped");
|
---|
540 | stkey = SUNKNOWN;
|
---|
541 | return;
|
---|
542 | }
|
---|
543 | if(nextch+2<=lastch && nextch[0]=='i' && nextch[1]=='f' && nextch[2]=='(')
|
---|
544 | {
|
---|
545 | /* assignment or if statement -- look at character after balancing paren */
|
---|
546 | parlev = 1;
|
---|
547 | for(i=nextch+3 ; i<=lastch; ++i)
|
---|
548 | if(*i == (MYQUOTE))
|
---|
549 | {
|
---|
550 | while(*++i != MYQUOTE)
|
---|
551 | ;
|
---|
552 | }
|
---|
553 | else if(*i == '(')
|
---|
554 | ++parlev;
|
---|
555 | else if(*i == ')')
|
---|
556 | {
|
---|
557 | if(--parlev == 0)
|
---|
558 | break;
|
---|
559 | }
|
---|
560 | if(i >= lastch)
|
---|
561 | stkey = SLOGIF;
|
---|
562 | else if(i[1] == '=')
|
---|
563 | stkey = SLET;
|
---|
564 | else if( isdigit((int)i[1]) )
|
---|
565 | stkey = SARITHIF;
|
---|
566 | else stkey = SLOGIF;
|
---|
567 | if(stkey != SLET)
|
---|
568 | nextch += 2;
|
---|
569 | }
|
---|
570 | else if(expeql) /* may be an assignment */
|
---|
571 | {
|
---|
572 | if(expcom && nextch<lastch &&
|
---|
573 | nextch[0]=='d' && nextch[1]=='o')
|
---|
574 | {
|
---|
575 | stkey = SDO;
|
---|
576 | nextch += 2;
|
---|
577 | }
|
---|
578 | else stkey = SLET;
|
---|
579 | }
|
---|
580 | /* otherwise search for keyword */
|
---|
581 | else {
|
---|
582 | stkey = getkwd();
|
---|
583 | if(stkey==SGOTO && lastch>=nextch) {
|
---|
584 | if(nextch[0]=='(')
|
---|
585 | stkey = SCOMPGOTO;
|
---|
586 | else if(isalpha((int)nextch[0]))
|
---|
587 | stkey = SASGOTO;
|
---|
588 | }
|
---|
589 | }
|
---|
590 | parlev = 0;
|
---|
591 | }
|
---|
592 |
|
---|
593 |
|
---|
594 |
|
---|
595 | LOCAL int
|
---|
596 | getkwd()
|
---|
597 | {
|
---|
598 | register char *i, *j;
|
---|
599 | register struct keylist *pk, *pend;
|
---|
600 | int k;
|
---|
601 |
|
---|
602 | if(! isalpha((int)nextch[0]) )
|
---|
603 | return(SUNKNOWN);
|
---|
604 | k = nextch[0] - 'a';
|
---|
605 | if((pk = keystart[k]))
|
---|
606 | for(pend = keyend[k] ; pk<=pend ; ++pk )
|
---|
607 | {
|
---|
608 | i = pk->keyname;
|
---|
609 | j = nextch;
|
---|
610 | while(*++i==*++j && *i!='\0')
|
---|
611 | ;
|
---|
612 | if(*i == '\0')
|
---|
613 | {
|
---|
614 | nextch = j;
|
---|
615 | return(pk->keyval);
|
---|
616 | }
|
---|
617 | }
|
---|
618 | return(SUNKNOWN);
|
---|
619 | }
|
---|
620 |
|
---|
621 |
|
---|
622 | void
|
---|
623 | initkey()
|
---|
624 | {
|
---|
625 | register struct keylist *p;
|
---|
626 | register int i,j;
|
---|
627 |
|
---|
628 | for(i = 0 ; i<26 ; ++i)
|
---|
629 | keystart[i] = NULL;
|
---|
630 |
|
---|
631 | for(p = keys ; p->keyname ; ++p)
|
---|
632 | {
|
---|
633 | j = p->keyname[0] - 'a';
|
---|
634 | if(keystart[j] == NULL)
|
---|
635 | keystart[j] = p;
|
---|
636 | keyend[j] = p;
|
---|
637 | }
|
---|
638 | }
|
---|
639 | |
---|
640 |
|
---|
641 | LOCAL int
|
---|
642 | gettok()
|
---|
643 | {
|
---|
644 | int havdot, havexp, havdbl;
|
---|
645 | int radix;
|
---|
646 | extern struct punctlist puncts[];
|
---|
647 | struct punctlist *pp;
|
---|
648 | #if 0
|
---|
649 | extern struct fmtlist fmts[];
|
---|
650 | #endif
|
---|
651 | struct dotlist *pd;
|
---|
652 |
|
---|
653 | char *i, *j, *n1, *p;
|
---|
654 |
|
---|
655 | if(*nextch == (MYQUOTE))
|
---|
656 | {
|
---|
657 | ++nextch;
|
---|
658 | p = token;
|
---|
659 | while(*nextch != MYQUOTE)
|
---|
660 | *p++ = *nextch++;
|
---|
661 | ++nextch;
|
---|
662 | toklen = p - token;
|
---|
663 | *p = '\0';
|
---|
664 | return (SHOLLERITH);
|
---|
665 | }
|
---|
666 | /*
|
---|
667 | if(stkey == SFORMAT)
|
---|
668 | {
|
---|
669 | for(pf = fmts; pf->fmtchar; ++pf)
|
---|
670 | {
|
---|
671 | if(*nextch == pf->fmtchar)
|
---|
672 | {
|
---|
673 | ++nextch;
|
---|
674 | if(pf->fmtval == SLPAR)
|
---|
675 | ++parlev;
|
---|
676 | else if(pf->fmtval == SRPAR)
|
---|
677 | --parlev;
|
---|
678 | return(pf->fmtval);
|
---|
679 | }
|
---|
680 | }
|
---|
681 | if( isdigit(*nextch) )
|
---|
682 | {
|
---|
683 | p = token;
|
---|
684 | *p++ = *nextch++;
|
---|
685 | while(nextch<=lastch && isdigit(*nextch) )
|
---|
686 | *p++ = *nextch++;
|
---|
687 | toklen = p - token;
|
---|
688 | *p = '\0';
|
---|
689 | if(nextch<=lastch && *nextch=='p')
|
---|
690 | {
|
---|
691 | ++nextch;
|
---|
692 | return(SSCALE);
|
---|
693 | }
|
---|
694 | else return(SICON);
|
---|
695 | }
|
---|
696 | if( isalpha(*nextch) )
|
---|
697 | {
|
---|
698 | p = token;
|
---|
699 | *p++ = *nextch++;
|
---|
700 | while(nextch<=lastch &&
|
---|
701 | (*nextch=='.' || isdigit(*nextch) || isalpha(*nextch) ))
|
---|
702 | *p++ = *nextch++;
|
---|
703 | toklen = p - token;
|
---|
704 | *p = '\0';
|
---|
705 | return(SFIELD);
|
---|
706 | }
|
---|
707 | goto badchar;
|
---|
708 | }
|
---|
709 | XXX ??? */
|
---|
710 | /* Not a format statement */
|
---|
711 |
|
---|
712 | if(needkwd)
|
---|
713 | {
|
---|
714 | needkwd = 0;
|
---|
715 | return( getkwd() );
|
---|
716 | }
|
---|
717 |
|
---|
718 | for(pp=puncts; pp->punchar; ++pp)
|
---|
719 | if(*nextch == pp->punchar)
|
---|
720 | {
|
---|
721 | if( (*nextch=='*' || *nextch=='/') &&
|
---|
722 | nextch<lastch && nextch[1]==nextch[0])
|
---|
723 | {
|
---|
724 | if(*nextch == '*')
|
---|
725 | yylval.num = SPOWER;
|
---|
726 | else yylval.num = SCONCAT;
|
---|
727 | nextch+=2;
|
---|
728 | }
|
---|
729 | else {yylval.num=pp->punval;
|
---|
730 | if(yylval.num==SLPAR)
|
---|
731 | ++parlev;
|
---|
732 | else if(yylval.num==SRPAR)
|
---|
733 | --parlev;
|
---|
734 | ++nextch;
|
---|
735 | }
|
---|
736 | return(yylval.num);
|
---|
737 | }
|
---|
738 | if(*nextch == '.') {
|
---|
739 | if(nextch >= lastch) goto badchar;
|
---|
740 | else if(isdigit((int)nextch[1])) goto numconst;
|
---|
741 | else {
|
---|
742 | for(pd=dots ; (j=pd->dotname) ; ++pd)
|
---|
743 | {
|
---|
744 | for(i=nextch+1 ; i<=lastch ; ++i)
|
---|
745 | if(*i != *j) break;
|
---|
746 | else if(*i != '.') ++j;
|
---|
747 | else {
|
---|
748 | nextch = i+1;
|
---|
749 | return(pd->dotval);
|
---|
750 | }
|
---|
751 | }
|
---|
752 | goto badchar;
|
---|
753 | }
|
---|
754 | }
|
---|
755 | if( isalpha((int)*nextch) )
|
---|
756 | {
|
---|
757 | p = token;
|
---|
758 | *p++ = *nextch++;
|
---|
759 | while(nextch<=lastch)
|
---|
760 | if( isalpha((int)*nextch) || isdigit((int)*nextch) )
|
---|
761 | *p++ = *nextch++;
|
---|
762 | else break;
|
---|
763 | toklen = p - token;
|
---|
764 | *p = '\0';
|
---|
765 | if(inioctl && nextch<=lastch && *nextch=='=')
|
---|
766 | {
|
---|
767 | ++nextch;
|
---|
768 | return(SNAMEEQ);
|
---|
769 | }
|
---|
770 | if(toklen>=8 && eqn(8, token, "function") &&
|
---|
771 | nextch<lastch && *nextch=='(')
|
---|
772 | {
|
---|
773 | nextch -= (toklen - 8);
|
---|
774 | return(SFUNCTION);
|
---|
775 | }
|
---|
776 | if(toklen > VL)
|
---|
777 | {
|
---|
778 | err2("name %s too long, truncated to %d", token, VL);
|
---|
779 | toklen = VL;
|
---|
780 | token[6] = '\0';
|
---|
781 | }
|
---|
782 | if(toklen==1 && *nextch==MYQUOTE)
|
---|
783 | {
|
---|
784 | switch(token[0])
|
---|
785 | {
|
---|
786 | case 'z': case 'Z':
|
---|
787 | case 'x': case 'X':
|
---|
788 | radix = 16; break;
|
---|
789 | case 'o': case 'O':
|
---|
790 | radix = 8; break;
|
---|
791 | case 'b': case 'B':
|
---|
792 | radix = 2; break;
|
---|
793 | default:
|
---|
794 | err("bad bit identifier");
|
---|
795 | return(SFNAME);
|
---|
796 | }
|
---|
797 | ++nextch;
|
---|
798 | for(p = token ; *nextch!=MYQUOTE ; )
|
---|
799 | if( hextoi(*p++ = *nextch++) >= radix)
|
---|
800 | {
|
---|
801 | err("invalid binary character");
|
---|
802 | break;
|
---|
803 | }
|
---|
804 | ++nextch;
|
---|
805 | toklen = p - token;
|
---|
806 | return( radix==16 ? SHEXCON : (radix==8 ? SOCTCON : SBITCON) );
|
---|
807 | }
|
---|
808 | return(SFNAME);
|
---|
809 | }
|
---|
810 | if( ! isdigit((int)*nextch) ) goto badchar;
|
---|
811 | numconst:
|
---|
812 | havdot = NO;
|
---|
813 | havexp = NO;
|
---|
814 | havdbl = NO;
|
---|
815 | for(n1 = nextch ; nextch<=lastch ; ++nextch)
|
---|
816 | {
|
---|
817 | if(*nextch == '.')
|
---|
818 | if(havdot) break;
|
---|
819 | else if(nextch+2<=lastch && isalpha((int)nextch[1])
|
---|
820 | && isalpha((int)nextch[2]))
|
---|
821 | break;
|
---|
822 | else havdot = YES;
|
---|
823 | else if(*nextch=='d' || *nextch=='e')
|
---|
824 | {
|
---|
825 | p = nextch;
|
---|
826 | havexp = YES;
|
---|
827 | if(*nextch == 'd')
|
---|
828 | havdbl = YES;
|
---|
829 | if(nextch<lastch)
|
---|
830 | if(nextch[1]=='+' || nextch[1]=='-')
|
---|
831 | ++nextch;
|
---|
832 | if( ! isdigit((int)*++nextch) )
|
---|
833 | {
|
---|
834 | nextch = p;
|
---|
835 | havdbl = havexp = NO;
|
---|
836 | break;
|
---|
837 | }
|
---|
838 | for(++nextch ;
|
---|
839 | nextch<=lastch && isdigit((int)*nextch);
|
---|
840 | ++nextch);
|
---|
841 | break;
|
---|
842 | }
|
---|
843 | else if( ! isdigit((int)*nextch) )
|
---|
844 | break;
|
---|
845 | }
|
---|
846 | p = token;
|
---|
847 | i = n1;
|
---|
848 | while(i < nextch)
|
---|
849 | *p++ = *i++;
|
---|
850 | toklen = p - token;
|
---|
851 | *p = '\0';
|
---|
852 | if(havdbl) return(SDCON);
|
---|
853 | if(havdot || havexp) return(SRCON);
|
---|
854 | return(SICON);
|
---|
855 | badchar:
|
---|
856 | s[0] = *nextch++;
|
---|
857 | return(SUNKNOWN);
|
---|
858 | }
|
---|
859 | |
---|
860 |
|
---|
861 | /* KEYWORD AND SPECIAL CHARACTER TABLES
|
---|
862 | */
|
---|
863 |
|
---|
864 | struct punctlist puncts[ ] =
|
---|
865 | {
|
---|
866 | { '(', SLPAR, },
|
---|
867 | { ')', SRPAR, },
|
---|
868 | { '=', SEQUALS, },
|
---|
869 | { ',', SCOMMA, },
|
---|
870 | { '+', SPLUS, },
|
---|
871 | { '-', SMINUS, },
|
---|
872 | { '*', SSTAR, },
|
---|
873 | { '/', SSLASH, },
|
---|
874 | { '$', SCURRENCY, },
|
---|
875 | { ':', SCOLON, },
|
---|
876 | { 0, 0 }, } ;
|
---|
877 |
|
---|
878 | /*
|
---|
879 | LOCAL struct fmtlist fmts[ ] =
|
---|
880 | {
|
---|
881 | '(', SLPAR,
|
---|
882 | ')', SRPAR,
|
---|
883 | '/', SSLASH,
|
---|
884 | ',', SCOMMA,
|
---|
885 | '-', SMINUS,
|
---|
886 | ':', SCOLON,
|
---|
887 | 0, 0 } ;
|
---|
888 | */
|
---|
889 |
|
---|
890 | LOCAL struct dotlist dots[ ] =
|
---|
891 | {
|
---|
892 | { "and.", SAND, },
|
---|
893 | { "or.", SOR, },
|
---|
894 | { "not.", SNOT, },
|
---|
895 | { "true.", STRUE, },
|
---|
896 | { "false.", SFALSE, },
|
---|
897 | { "eq.", SEQ, },
|
---|
898 | { "ne.", SNE, },
|
---|
899 | { "lt.", SLT, },
|
---|
900 | { "le.", SLE, },
|
---|
901 | { "gt.", SGT, },
|
---|
902 | { "ge.", SGE, },
|
---|
903 | { "neqv.", SNEQV, },
|
---|
904 | { "eqv.", SEQV, },
|
---|
905 | { 0, 0 }, } ;
|
---|
906 |
|
---|
907 | LOCAL struct keylist keys[ ] =
|
---|
908 | {
|
---|
909 | { "assign", SASSIGN, },
|
---|
910 | { "automatic", SAUTOMATIC, },
|
---|
911 | { "backspace", SBACKSPACE, },
|
---|
912 | { "blockdata", SBLOCK, },
|
---|
913 | { "call", SCALL, },
|
---|
914 | { "character", SCHARACTER, },
|
---|
915 | { "close", SCLOSE, },
|
---|
916 | { "common", SCOMMON, },
|
---|
917 | { "complex", SCOMPLEX, },
|
---|
918 | { "continue", SCONTINUE, },
|
---|
919 | { "data", SDATA, },
|
---|
920 | { "dimension", SDIMENSION, },
|
---|
921 | { "doubleprecision", SDOUBLE, },
|
---|
922 | { "doublecomplex", SDCOMPLEX, },
|
---|
923 | { "elseif", SELSEIF, },
|
---|
924 | { "else", SELSE, },
|
---|
925 | { "endfile", SENDFILE, },
|
---|
926 | { "endif", SENDIF, },
|
---|
927 | { "end", SEND, },
|
---|
928 | { "entry", SENTRY, },
|
---|
929 | { "equivalence", SEQUIV, },
|
---|
930 | { "external", SEXTERNAL, },
|
---|
931 | { "format", SFORMAT, },
|
---|
932 | { "function", SFUNCTION, },
|
---|
933 | { "goto", SGOTO, },
|
---|
934 | { "implicit", SIMPLICIT, },
|
---|
935 | { "include", SINCLUDE, },
|
---|
936 | { "inquire", SINQUIRE, },
|
---|
937 | { "intrinsic", SINTRINSIC, },
|
---|
938 | { "integer", SINTEGER, },
|
---|
939 | { "logical", SLOGICAL, },
|
---|
940 | { "open", SOPEN, },
|
---|
941 | { "parameter", SPARAM, },
|
---|
942 | { "pause", SPAUSE, },
|
---|
943 | { "print", SPRINT, },
|
---|
944 | { "program", SPROGRAM, },
|
---|
945 | { "punch", SPUNCH, },
|
---|
946 | { "read", SREAD, },
|
---|
947 | { "real", SREAL, },
|
---|
948 | { "return", SRETURN, },
|
---|
949 | { "rewind", SREWIND, },
|
---|
950 | { "save", SSAVE, },
|
---|
951 | { "static", SSTATIC, },
|
---|
952 | { "stop", SSTOP, },
|
---|
953 | { "subroutine", SSUBROUTINE, },
|
---|
954 | { "then", STHEN, },
|
---|
955 | { "undefined", SUNDEFINED, },
|
---|
956 | { "write", SWRITE, },
|
---|
957 | { 0, 0 }, };
|
---|