00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "defs.h"
00025 #include "tokdefs.h"
00026 #include "p1defs.h"
00027
00028 #ifdef _WIN32
00029 #undef MSDOS
00030 #define MSDOS
00031 #endif
00032
00033 #ifdef NO_EOF_CHAR_CHECK
00034 #undef EOF_CHAR
00035 #else
00036 #ifndef EOF_CHAR
00037 #define EOF_CHAR 26
00038 #endif
00039 #endif
00040
00041 #define BLANK ' '
00042 #define MYQUOTE (2)
00043 #define SEOF 0
00044
00045
00046
00047 #define STEOF 1
00048 #define STINITIAL 2
00049 #define STCONTINUE 3
00050
00051
00052
00053 #define NEWSTMT 1
00054 #define FIRSTTOKEN 2
00055 #define OTHERTOKEN 3
00056 #define RETEOS 4
00057
00058
00059 LOCAL int stkey;
00060 static int needwkey;
00061 ftnint yystno;
00062 flag intonly;
00063 extern int new_dcl;
00064 LOCAL long int stno;
00065 LOCAL long int nxtstno;
00066 LOCAL int parlev;
00067 LOCAL int parseen;
00068 LOCAL int expcom;
00069 LOCAL int expeql;
00070 LOCAL char *nextch;
00071 LOCAL char *lastch;
00072 LOCAL char *nextcd = NULL;
00073 LOCAL char *endcd;
00074 LOCAL long prevlin;
00075 LOCAL long thislin;
00076 LOCAL int code;
00077 LOCAL int lexstate = NEWSTMT;
00078 LOCAL char *sbuf;
00079 LOCAL char *send;
00080 LOCAL char *shend;
00081 LOCAL int maxcont;
00082 LOCAL int nincl = 0;
00083 LOCAL long firstline;
00084 LOCAL char *infname1, *infname2, *laststb, *stb0;
00085 extern int addftnsrc;
00086 static char **linestart;
00087 LOCAL int ncont;
00088 LOCAL char comstart[Table_size];
00089 #define USC (unsigned char *)
00090
00091 static char anum_buf[Table_size];
00092 #define isalnum_(x) anum_buf[x]
00093 #define isalpha_(x) (anum_buf[x] == 1)
00094
00095 #define COMMENT_BUF_STORE 4088
00096
00097 typedef struct comment_buf {
00098 struct comment_buf *next;
00099 char *last;
00100 char buf[COMMENT_BUF_STORE];
00101 } comment_buf;
00102 static comment_buf *cbfirst, *cbcur;
00103 static char *cbinit, *cbnext, *cblast;
00104 static void flush_comments Argdcl((void));
00105 extern flag use_bs;
00106 static char *lastfile = "??", *lastfile0 = "?";
00107 static char fbuf[P1_FILENAME_MAX];
00108 static long lastline;
00109 static void putlineno(Void);
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124 struct Inclfile
00125 {
00126 struct Inclfile *inclnext;
00127 FILEP inclfp;
00128 char *inclname;
00129 int incllno;
00130 char *incllinp;
00131 int incllen;
00132 int inclcode;
00133 ftnint inclstno;
00134 };
00135
00136 LOCAL struct Inclfile *inclp = NULL;
00137 struct Keylist {
00138 char *keyname;
00139 int keyval;
00140 char notinf66;
00141 };
00142 struct Punctlist {
00143 char punchar;
00144 int punval;
00145 };
00146 struct Fmtlist {
00147 char fmtchar;
00148 int fmtval;
00149 };
00150 struct Dotlist {
00151 char *dotname;
00152 int dotval;
00153 };
00154 LOCAL struct Keylist *keystart[26], *keyend[26];
00155
00156
00157
00158
00159 static struct Punctlist puncts[ ] =
00160 {
00161 '(', SLPAR,
00162 ')', SRPAR,
00163 '=', SEQUALS,
00164 ',', SCOMMA,
00165 '+', SPLUS,
00166 '-', SMINUS,
00167 '*', SSTAR,
00168 '/', SSLASH,
00169 '$', SCURRENCY,
00170 ':', SCOLON,
00171 '<', SLT,
00172 '>', SGT,
00173 0, 0 };
00174
00175 LOCAL struct Dotlist dots[ ] =
00176 {
00177 "and.", SAND,
00178 "or.", SOR,
00179 "not.", SNOT,
00180 "true.", STRUE,
00181 "false.", SFALSE,
00182 "eq.", SEQ,
00183 "ne.", SNE,
00184 "lt.", SLT,
00185 "le.", SLE,
00186 "gt.", SGT,
00187 "ge.", SGE,
00188 "neqv.", SNEQV,
00189 "eqv.", SEQV,
00190 0, 0 };
00191
00192 LOCAL struct Keylist keys[ ] =
00193 {
00194 { "assign", SASSIGN },
00195 { "automatic", SAUTOMATIC, YES },
00196 { "backspace", SBACKSPACE },
00197 { "blockdata", SBLOCK },
00198 { "byte", SBYTE },
00199 { "call", SCALL },
00200 { "character", SCHARACTER, YES },
00201 { "close", SCLOSE, YES },
00202 { "common", SCOMMON },
00203 { "complex", SCOMPLEX },
00204 { "continue", SCONTINUE },
00205 { "data", SDATA },
00206 { "dimension", SDIMENSION },
00207 { "doubleprecision", SDOUBLE },
00208 { "doublecomplex", SDCOMPLEX, YES },
00209 { "elseif", SELSEIF, YES },
00210 { "else", SELSE, YES },
00211 { "endfile", SENDFILE },
00212 { "endif", SENDIF, YES },
00213 { "enddo", SENDDO, YES },
00214 { "end", SEND },
00215 { "entry", SENTRY, YES },
00216 { "equivalence", SEQUIV },
00217 { "external", SEXTERNAL },
00218 { "format", SFORMAT },
00219 { "function", SFUNCTION },
00220 { "goto", SGOTO },
00221 { "implicit", SIMPLICIT, YES },
00222 { "include", SINCLUDE, YES },
00223 { "inquire", SINQUIRE, YES },
00224 { "intrinsic", SINTRINSIC, YES },
00225 { "integer", SINTEGER },
00226 { "logical", SLOGICAL },
00227 { "namelist", SNAMELIST, YES },
00228 { "none", SUNDEFINED, YES },
00229 { "open", SOPEN, YES },
00230 { "parameter", SPARAM, YES },
00231 { "pause", SPAUSE },
00232 { "print", SPRINT },
00233 { "program", SPROGRAM, YES },
00234 { "punch", SPUNCH, YES },
00235 { "read", SREAD },
00236 { "real", SREAL },
00237 { "return", SRETURN },
00238 { "rewind", SREWIND },
00239 { "save", SSAVE, YES },
00240 { "static", SSTATIC, YES },
00241 { "stop", SSTOP },
00242 { "subroutine", SSUBROUTINE },
00243 { "then", STHEN, YES },
00244 { "undefined", SUNDEFINED, YES },
00245 { "while", SWHILE, YES },
00246 { "write", SWRITE },
00247 { 0, 0 }
00248 };
00249
00250 static void analyz Argdcl((void));
00251 static void crunch Argdcl((void));
00252 static int getcd Argdcl((char*, int));
00253 static int getcds Argdcl((void));
00254 static int getkwd Argdcl((void));
00255 static int gettok Argdcl((void));
00256 static void store_comment Argdcl((char*));
00257 LOCAL char *stbuf[3];
00258
00259 int
00260 #ifdef KR_headers
00261 inilex(name)
00262 char *name;
00263 #else
00264 inilex(char *name)
00265 #endif
00266 {
00267 stbuf[0] = Alloc(3*P1_STMTBUFSIZE);
00268 stbuf[1] = stbuf[0] + P1_STMTBUFSIZE;
00269 stbuf[2] = stbuf[1] + P1_STMTBUFSIZE;
00270 nincl = 0;
00271 inclp = NULL;
00272 doinclude(name);
00273 lexstate = NEWSTMT;
00274 return(NO);
00275 }
00276
00277
00278
00279
00280 void
00281 flline(Void)
00282 {
00283 lexstate = RETEOS;
00284 }
00285
00286
00287
00288 char *
00289 #ifdef KR_headers
00290 lexline(n)
00291 int *n;
00292 #else
00293 lexline(int *n)
00294 #endif
00295 {
00296 *n = (lastch - nextch) + 1;
00297 return(nextch);
00298 }
00299
00300
00301
00302
00303 void
00304 #ifdef KR_headers
00305 doinclude(name)
00306 char *name;
00307 #else
00308 doinclude(char *name)
00309 #endif
00310 {
00311 FILEP fp;
00312 struct Inclfile *t;
00313 char *name0, *lastslash, *s, *s0, *temp;
00314 int j, k;
00315 chainp I;
00316 extern chainp Iargs;
00317
00318 err_lineno = -1;
00319 if(inclp)
00320 {
00321 inclp->incllno = thislin;
00322 inclp->inclcode = code;
00323 inclp->inclstno = nxtstno;
00324 if(nextcd && (j = endcd - nextcd) > 0)
00325 inclp->incllinp = copyn(inclp->incllen = j, nextcd);
00326 else
00327 inclp->incllinp = 0;
00328 }
00329 nextcd = NULL;
00330
00331 if(++nincl >= MAXINCLUDES)
00332 Fatal("includes nested too deep");
00333 if(name[0] == '\0')
00334 fp = stdin;
00335 else if(name[0] == '/' || inclp == NULL
00336 #ifdef MSDOS
00337 || name[0] == '\\'
00338 || name[1] == ':'
00339 #endif
00340 )
00341 fp = fopen(name, textread);
00342 else {
00343 lastslash = NULL;
00344 s = s0 = inclp->inclname;
00345 #ifdef MSDOS
00346 if (s[1] == ':')
00347 lastslash = s + 1;
00348 #endif
00349 for(; *s ; ++s)
00350 if(*s == '/'
00351 #ifdef MSDOS
00352 || *s == '\\'
00353 #endif
00354 )
00355 lastslash = s;
00356 name0 = name;
00357 if(lastslash) {
00358 k = lastslash - s0 + 1;
00359 temp = Alloc(k + strlen(name) + 1);
00360 strncpy(temp, s0, k);
00361 strcpy(temp+k, name);
00362 name = temp;
00363 }
00364 fp = fopen(name, textread);
00365 if (!fp && (I = Iargs)) {
00366 k = strlen(name0) + 2;
00367 for(; I; I = I->nextp) {
00368 j = strlen(s = I->datap);
00369 name = Alloc(j + k);
00370 strcpy(name, s);
00371 switch(s[j-1]) {
00372 case '/':
00373 #ifdef MSDOS
00374 case ':':
00375 case '\\':
00376 #endif
00377 break;
00378 default:
00379 name[j++] = '/';
00380 }
00381 strcpy(name+j, name0);
00382 if (fp = fopen(name, textread)) {
00383 free(name0);
00384 goto havefp;
00385 }
00386 free(name);
00387 name = name0;
00388 }
00389 }
00390 }
00391 if (fp)
00392 {
00393 havefp:
00394 t = inclp;
00395 inclp = ALLOC(Inclfile);
00396 inclp->inclnext = t;
00397 prevlin = thislin = lineno = 0;
00398 infname = inclp->inclname = name;
00399 infile = inclp->inclfp = fp;
00400 lastline = 0;
00401 putlineno();
00402 lastline = 0;
00403 }
00404 else
00405 {
00406 fprintf(diagfile, "Cannot open file %s\n", name);
00407 done(1);
00408 }
00409 }
00410
00411
00412
00413
00414 LOCAL int
00415 popinclude(Void)
00416 {
00417 struct Inclfile *t;
00418 register char *p;
00419 register int k;
00420
00421 if(infile != stdin)
00422 clf(&infile, infname, 1);
00423 free(infname);
00424
00425 --nincl;
00426 err_lineno = -1;
00427 t = inclp->inclnext;
00428 free( (charptr) inclp);
00429 inclp = t;
00430 if(inclp == NULL) {
00431 infname = 0;
00432 return(NO);
00433 }
00434
00435 infile = inclp->inclfp;
00436 infname = inclp->inclname;
00437 lineno = prevlin = thislin = inclp->incllno;
00438 code = inclp->inclcode;
00439 stno = nxtstno = inclp->inclstno;
00440 if(inclp->incllinp)
00441 {
00442 lastline = 0;
00443 putlineno();
00444 lastline = lineno;
00445 endcd = nextcd = sbuf;
00446 k = inclp->incllen;
00447 p = inclp->incllinp;
00448 while(--k >= 0)
00449 *endcd++ = *p++;
00450 free( (charptr) (inclp->incllinp) );
00451 }
00452 else
00453 nextcd = NULL;
00454 return(YES);
00455 }
00456
00457
00458 void
00459 #ifdef KR_headers
00460 p1_line_number(line_number)
00461 long line_number;
00462 #else
00463 p1_line_number(long line_number)
00464 #endif
00465 {
00466 if (lastfile != lastfile0) {
00467 p1puts(P1_FILENAME, fbuf);
00468 lastfile0 = lastfile;
00469 }
00470 fprintf(pass1_file, "%d: %ld\n", P1_SET_LINE, line_number);
00471 }
00472
00473 static void
00474 putlineno(Void)
00475 {
00476 extern int gflag;
00477 register char *s0, *s1;
00478
00479 if (gflag) {
00480 if (lastline)
00481 p1_line_number(lastline);
00482 lastline = firstline;
00483 if (lastfile != infname)
00484 if (lastfile = infname) {
00485 strncpy(fbuf, lastfile, sizeof(fbuf));
00486 fbuf[sizeof(fbuf)-1] = 0;
00487 }
00488 else
00489 fbuf[0] = 0;
00490 }
00491 if (addftnsrc) {
00492 if (laststb && *laststb) {
00493 for(s1 = laststb; *s1; s1++) {
00494 for(s0 = s1; *s1 != '\n'; s1++)
00495 if (*s1 == '*' && s1[1] == '/')
00496 *s1 = '+';
00497 *s1 = 0;
00498 p1puts(P1_FORTRAN, s0);
00499 }
00500 *laststb = 0;
00501 }
00502 laststb = stb0;
00503 }
00504 }
00505
00506 int
00507 yylex(Void)
00508 {
00509 static int tokno;
00510 int retval;
00511
00512 switch(lexstate)
00513 {
00514 case NEWSTMT :
00515 retval = getcds();
00516 putlineno();
00517 if(retval == STEOF) {
00518 retval = SEOF;
00519 break;
00520 }
00521 crunch();
00522 tokno = 0;
00523 lexstate = FIRSTTOKEN;
00524 yystno = stno;
00525 stno = nxtstno;
00526 toklen = 0;
00527 retval = SLABEL;
00528 break;
00529
00530 first:
00531 case FIRSTTOKEN :
00532 analyz();
00533 lexstate = OTHERTOKEN;
00534 tokno = 1;
00535 retval = stkey;
00536 break;
00537
00538 case OTHERTOKEN :
00539 if(nextch > lastch)
00540 goto reteos;
00541 ++tokno;
00542 if( (stkey==SLOGIF || stkey==SELSEIF) && parlev==0 && tokno>3)
00543 goto first;
00544
00545 if(stkey==SASSIGN && tokno==3 && nextch<lastch &&
00546 nextch[0]=='t' && nextch[1]=='o')
00547 {
00548 nextch+=2;
00549 retval = STO;
00550 break;
00551 }
00552 if (tokno == 2 && stkey == SDO) {
00553 intonly = 1;
00554 retval = gettok();
00555 intonly = 0;
00556 }
00557 else
00558 retval = gettok();
00559 break;
00560
00561 reteos:
00562 case RETEOS:
00563 lexstate = NEWSTMT;
00564 retval = SEOS;
00565 break;
00566 default:
00567 fatali("impossible lexstate %d", lexstate);
00568 break;
00569 }
00570
00571 if (retval == SEOF)
00572 flush_comments ();
00573
00574 return retval;
00575 }
00576
00577 LOCAL void
00578 contmax(Void)
00579 {
00580 lineno = thislin;
00581 many("continuation lines", 'C', maxcontin);
00582 }
00583
00584
00585
00586
00587
00588
00589 LOCAL int
00590 getcds(Void)
00591 {
00592 register char *p, *q;
00593
00594 flush_comments ();
00595 top:
00596 if(nextcd == NULL)
00597 {
00598 code = getcd( nextcd = sbuf, 1 );
00599 stno = nxtstno;
00600 prevlin = thislin;
00601 }
00602 if(code == STEOF)
00603 if( popinclude() )
00604 goto top;
00605 else
00606 return(STEOF);
00607
00608 if(code == STCONTINUE)
00609 {
00610 lineno = thislin;
00611 nextcd = NULL;
00612 goto top;
00613 }
00614
00615
00616
00617 if(nextcd > sbuf)
00618 {
00619 q = nextcd;
00620 p = sbuf;
00621 while(q < endcd)
00622 *p++ = *q++;
00623 endcd = p;
00624 }
00625
00626
00627
00628
00629
00630
00631
00632
00633 ncont = 0;
00634 for(;;) {
00635 nextcd = endcd;
00636 if (ncont >= maxcont || nextcd+66 > send)
00637 contmax();
00638 linestart[ncont++] = nextcd;
00639 if ((code = getcd(nextcd,0)) != STCONTINUE)
00640 break;
00641 if (ncont == 20 && noextflag) {
00642 lineno = thislin;
00643 errext("more than 19 continuation lines");
00644 }
00645 }
00646 nextch = sbuf;
00647 lastch = nextcd - 1;
00648
00649 lineno = prevlin;
00650 prevlin = thislin;
00651 if (infname2) {
00652 free(infname);
00653 infname = infname2;
00654 if (inclp)
00655 inclp->inclname = infname;
00656 }
00657 infname2 = infname1;
00658 infname1 = 0;
00659 return(STINITIAL);
00660 }
00661
00662 static void
00663 #ifdef KR_headers
00664 bang(a, b, c, d, e)
00665 char *a;
00666 char *b;
00667 char *c;
00668 register char *d;
00669 register char *e;
00670 #else
00671 bang(char *a, char *b, char *c, register char *d, register char *e)
00672 #endif
00673
00674 {
00675 char buf[COMMENT_BUFFER_SIZE + 1];
00676 register char *p, *pe;
00677
00678 p = buf;
00679 pe = buf + COMMENT_BUFFER_SIZE;
00680 *pe = 0;
00681 while(a < b)
00682 if (!(*p++ = *a++))
00683 p[-1] = 0;
00684 if (b < c)
00685 *p++ = '\t';
00686 while(d < e) {
00687 if (!(*p++ = *d++))
00688 p[-1] = ' ';
00689 if (p == pe) {
00690 store_comment(buf);
00691 p = buf;
00692 }
00693 }
00694 if (p > buf) {
00695 while(--p >= buf && *p == ' ');
00696 p[1] = 0;
00697 store_comment(buf);
00698 }
00699 }
00700
00701
00702
00703
00704
00705
00706
00707 LOCAL int
00708 #ifdef KR_headers
00709 getcd(b, nocont)
00710 register char *b;
00711 int nocont;
00712 #else
00713 getcd(register char *b, int nocont)
00714 #endif
00715 {
00716 register int c;
00717 register char *p, *bend;
00718 int speclin;
00719
00720
00721
00722 static char a[6];
00723 static char *aend = a+6;
00724 static char *stb, *stbend;
00725 static int nst;
00726 char *atend, *endcd0;
00727 extern int warn72;
00728 char buf72[24];
00729 int amp, i;
00730 char storage[COMMENT_BUFFER_SIZE + 1];
00731 char *pointer;
00732 long L;
00733
00734 top:
00735 endcd = b;
00736 bend = b+66;
00737 amp = speclin = NO;
00738 atend = aend;
00739
00740
00741
00742
00743 if( (c = getc(infile)) == '&')
00744 {
00745 a[0] = c;
00746 a[1] = 0;
00747 a[5] = 'x';
00748 amp = speclin = YES;
00749 bend = send;
00750 p = aend;
00751 }
00752
00753
00754
00755 else if(comstart[c & (Table_size-1)])
00756 {
00757 if (feof (infile)
00758 #ifdef EOF_CHAR
00759 || c == EOF_CHAR
00760 #endif
00761 )
00762 return STEOF;
00763
00764 if (c == '#') {
00765 *endcd++ = c;
00766 while((c = getc(infile)) != '\n')
00767 if (c == EOF)
00768 return STEOF;
00769 else if (endcd < shend)
00770 *endcd++ = c;
00771 ++thislin;
00772 *endcd = 0;
00773 if (b[1] == ' ')
00774 p = b + 2;
00775 else if (!strncmp(b,"#line ",6))
00776 p = b + 6;
00777 else {
00778 bad_cpp:
00779 lineno = thislin;
00780 errstr("Bad # line: \"%s\"", b);
00781 goto top;
00782 }
00783 if (*p < '1' || *p > '9')
00784 goto bad_cpp;
00785 L = *p - '0';
00786 while((c = *++p) >= '0' && c <= '9')
00787 L = 10*L + c - '0';
00788 while(c == ' ')
00789 c = *++p;
00790 if (!c) {
00791
00792 thislin = L - 1;
00793 goto top;
00794 }
00795 if (c != '"')
00796 goto bad_cpp;
00797 bend = p;
00798 while(*++p != '"')
00799 if (!*p)
00800 goto bad_cpp;
00801 *p = 0;
00802 i = p - bend++;
00803 thislin = L - 1;
00804 if (!infname1 || strcmp(infname1, bend)) {
00805 if (infname1)
00806 free(infname1);
00807 if (infname && !strcmp(infname, bend)) {
00808 infname1 = 0;
00809 goto top;
00810 }
00811 lastfile = 0;
00812 infname1 = Alloc(i);
00813 strcpy(infname1, bend);
00814 if (!infname) {
00815 infname = infname1;
00816 infname1 = 0;
00817 }
00818 }
00819 goto top;
00820 }
00821
00822 storage[COMMENT_BUFFER_SIZE] = c = '\0';
00823 pointer = storage;
00824 while( !feof (infile) && (*pointer++ = c = getc(infile)) != '\n') {
00825
00826
00827
00828 if (feof (infile) && (c == '\377' || c == EOF)) {
00829 pointer--;
00830 break;
00831 }
00832
00833 if (c == '\0')
00834 *(pointer - 1) = ' ';
00835
00836 if (pointer == &storage[COMMENT_BUFFER_SIZE]) {
00837 store_comment (storage);
00838 pointer = storage;
00839 }
00840 }
00841
00842 if (pointer > storage) {
00843 if (c == '\n')
00844
00845
00846
00847 pointer[-1] = 0;
00848 else
00849 *pointer = 0;
00850
00851 store_comment (storage);
00852 }
00853
00854 if (feof (infile))
00855 if (c != '\n')
00856
00857 return STEOF;
00858
00859 ++thislin;
00860 goto top;
00861 }
00862
00863 else if(c != EOF)
00864 {
00865
00866
00867
00868
00869 ungetc(c, infile);
00870 for(p=a; p<aend && (c=getc(infile)) != '\n' && c!=EOF; )
00871 if(c == '\t')
00872
00873
00874
00875 {
00876 atend = p;
00877 while(p < aend)
00878 *p++ = BLANK;
00879 speclin = YES;
00880 bend = send;
00881 }
00882 else
00883 *p++ = c;
00884 }
00885
00886
00887
00888
00889 if(c == EOF)
00890 return(STEOF);
00891
00892
00893
00894 if(c == '\n')
00895 {
00896 while(p < aend)
00897 *p++ = BLANK;
00898
00899
00900
00901 endcd0 = endcd;
00902 if( ! speclin )
00903 while(endcd < bend)
00904 *endcd++ = BLANK;
00905 }
00906 else {
00907 if (warn72 & 2) {
00908 speclin = YES;
00909 bend = send;
00910 }
00911 while( endcd<bend && (c=getc(infile)) != '\n' && c!=EOF )
00912 *endcd++ = c;
00913 if(c == EOF)
00914 return(STEOF);
00915
00916
00917
00918
00919 if(c != '\n')
00920 {
00921 i = 0;
00922 while( (c=getc(infile)) != '\n' && c != EOF)
00923 if (i < 23 && c != '\r')
00924 buf72[i++] = c;
00925 if (warn72 && i && !speclin) {
00926 buf72[i] = 0;
00927 if (i >= 23)
00928 strcpy(buf72+20, "...");
00929 lineno = thislin + 1;
00930 errstr("text after column 72: %s", buf72);
00931 }
00932 if(c == EOF)
00933 return(STEOF);
00934 }
00935
00936 endcd0 = endcd;
00937 if( ! speclin )
00938 while(endcd < bend)
00939 *endcd++ = BLANK;
00940 }
00941
00942
00943
00944
00945 ++thislin;
00946
00947
00948
00949
00950 if( !isspace(a[5]) && a[5]!='0') {
00951 if (!amp)
00952 for(p = a; p < aend;)
00953 if (*p++ == '!' && p != aend)
00954 goto initcheck;
00955 if (addftnsrc && stb) {
00956 if (stbend > stb + 7) {
00957
00958 *stb++ = '$';
00959 if (amp)
00960 *stb++ = '&';
00961 else
00962 for(p = a; p < atend;)
00963 *stb++ = *p++;
00964 }
00965 if (endcd0 - b > stbend - stb) {
00966 if (stb > stbend)
00967 stb = stbend;
00968 endcd0 = b + (stbend - stb);
00969 }
00970 for(p = b; p < endcd0;)
00971 *stb++ = *p++;
00972 *stb++ = '\n';
00973 *stb = 0;
00974 }
00975 if (nocont) {
00976 lineno = thislin;
00977 errstr("illegal continuation card (starts \"%.6s\")",a);
00978 }
00979 else if (!amp && strncmp(a," ",5)) {
00980 lineno = thislin;
00981 errstr("labeled continuation line (starts \"%.6s\")",a);
00982 }
00983 return(STCONTINUE);
00984 }
00985 initcheck:
00986 for(p=a; p<atend; ++p)
00987 if( !isspace(*p) ) {
00988 if (*p++ != '!')
00989 goto initline;
00990 bang(p, atend, aend, b, endcd);
00991 goto top;
00992 }
00993 for(p = b ; p<endcd ; ++p)
00994 if( !isspace(*p) ) {
00995 if (*p++ != '!')
00996 goto initline;
00997 bang(a, a, a, p, endcd);
00998 goto top;
00999 }
01000
01001
01002
01003 goto top;
01004
01005 initline:
01006 if (!lastline)
01007 lastline = thislin;
01008 if (addftnsrc) {
01009 nst = (nst+1)%3;
01010 if (!laststb && stb0)
01011 laststb = stb0;
01012 stb0 = stb = stbuf[nst];
01013 *stb++ = '$';
01014 stbend = stb + sizeof(stbuf[0])-2;
01015 for(p = a; p < atend;)
01016 *stb++ = *p++;
01017 if (atend < aend)
01018 *stb++ = '\t';
01019 for(p = b; p < endcd0;)
01020 *stb++ = *p++;
01021 *stb++ = '\n';
01022 *stb = 0;
01023 }
01024
01025
01026
01027 nxtstno = 0;
01028 bend = a + 5;
01029 for(p = a ; p < bend ; ++p)
01030 if( !isspace(*p) )
01031 if(isdigit(*p))
01032 nxtstno = 10*nxtstno + (*p - '0');
01033 else if (*p == '!') {
01034 if (!addftnsrc)
01035 bang(p+1,atend,aend,b,endcd);
01036 endcd = b;
01037 break;
01038 }
01039 else {
01040 lineno = thislin;
01041 errstr(
01042 "nondigit in statement label field \"%.5s\"", a);
01043 nxtstno = 0;
01044 break;
01045 }
01046 firstline = thislin;
01047 return(STINITIAL);
01048 }
01049
01050 LOCAL void
01051 #ifdef KR_headers
01052 adjtoklen(newlen)
01053 int newlen;
01054 #else
01055 adjtoklen(int newlen)
01056 #endif
01057 {
01058 while(maxtoklen < newlen)
01059 maxtoklen = 2*maxtoklen + 2;
01060 if (token = (char *)realloc(token, maxtoklen))
01061 return;
01062 fprintf(stderr, "adjtoklen: realloc(%d) failure!\n", maxtoklen);
01063 exit(2);
01064 }
01065
01066
01067
01068
01069 LOCAL void
01070 crunch(Void)
01071 {
01072 register char *i, *j, *j0, *j1, *prvstr;
01073 int k, ten, nh, nh0, quote;
01074
01075
01076
01077
01078 new_dcl = needwkey = parlev = parseen = 0;
01079 expcom = 0;
01080 expeql = 0;
01081 j = sbuf;
01082 prvstr = sbuf;
01083 k = 0;
01084 for(i=sbuf ; i<=lastch ; ++i)
01085 {
01086 if(isspace(*i) )
01087 continue;
01088 if (*i == '!') {
01089 while(i >= linestart[k])
01090 if (++k >= maxcont)
01091 contmax();
01092 j0 = linestart[k];
01093 if (!addftnsrc)
01094 bang(sbuf,sbuf,sbuf,i+1,j0);
01095 i = j0-1;
01096 continue;
01097 }
01098
01099
01100
01101 if(*i=='\'' || *i=='"')
01102 {
01103 int len = 0;
01104
01105 quote = *i;
01106 *j = MYQUOTE;
01107 for(;;)
01108 {
01109 if(++i > lastch)
01110 {
01111 err("unbalanced quotes; closing quote supplied");
01112 if (j >= lastch)
01113 j = lastch - 1;
01114 break;
01115 }
01116 if(*i == quote)
01117 if(i<lastch && i[1]==quote) ++i;
01118 else break;
01119 else if(*i=='\\' && i<lastch && use_bs) {
01120 ++i;
01121 *i = escapes[*(unsigned char *)i];
01122 }
01123 *++j = *i;
01124 len++;
01125 }
01126
01127 if ((len = j - sbuf) > maxtoklen)
01128 adjtoklen(len);
01129 j[1] = MYQUOTE;
01130 j += 2;
01131 prvstr = j;
01132 }
01133 else if( (*i=='h' || *i=='H') && j>prvstr)
01134 {
01135 j0 = j - 1;
01136 if( ! isdigit(*j0)) goto copychar;
01137 nh = *j0 - '0';
01138 ten = 10;
01139 j1 = prvstr;
01140 if (j1 > sbuf && j1[-1] == MYQUOTE)
01141 --j1;
01142 if (j1+4 < j)
01143 j1 = j-4;
01144 for(;;) {
01145 if (j0-- <= j1)
01146 goto copychar;
01147 if( ! isdigit(*j0 ) ) break;
01148 nh += ten * (*j0-'0');
01149 ten*=10;
01150 }
01151
01152
01153
01154
01155
01156
01157
01158 if( !(*j0=='*'&&sbuf[0]=='d') && *j0!='/'
01159 && *j0!='(' && *j0!=',' && *j0!='=' && *j0!='.'
01160 && *j0 != MYQUOTE)
01161 goto copychar;
01162 nh0 = nh;
01163 if(i+nh > lastch)
01164 {
01165 erri("%dH too big", nh);
01166 nh = lastch - i;
01167 nh0 = -1;
01168 }
01169 if (nh > maxtoklen)
01170 adjtoklen(nh);
01171 j0[1] = MYQUOTE;
01172 j = j0 + 1;
01173 while(nh-- > 0)
01174 {
01175 if (++i > lastch) {
01176 hol_overflow:
01177 if (nh0 >= 0)
01178 erri("escapes make %dH too big",
01179 nh0);
01180 break;
01181 }
01182 if(*i == '\\' && use_bs) {
01183 if (++i > lastch)
01184 goto hol_overflow;
01185 *i = escapes[*(unsigned char *)i];
01186 }
01187 *++j = *i;
01188 }
01189 j[1] = MYQUOTE;
01190 j+=2;
01191 prvstr = j;
01192 }
01193 else {
01194 if(*i == '(') parseen = ++parlev;
01195 else if(*i == ')') --parlev;
01196 else if(parlev == 0)
01197 if(*i == '=') expeql = 1;
01198 else if(*i == ',') expcom = 1;
01199 copychar:
01200 if(shiftcase && isupper(*i))
01201 *j++ = tolower(*i);
01202 else *j++ = *i;
01203 }
01204 }
01205 lastch = j - 1;
01206 nextch = sbuf;
01207 }
01208
01209 LOCAL void
01210 analyz(Void)
01211 {
01212 register char *i;
01213
01214 if(parlev != 0)
01215 {
01216 err("unbalanced parentheses, statement skipped");
01217 stkey = SUNKNOWN;
01218 lastch = sbuf - 1;
01219 return;
01220 }
01221 if(nextch+2<=lastch && nextch[0]=='i' && nextch[1]=='f' && nextch[2]=='(')
01222 {
01223
01224 parlev = 1;
01225 for(i=nextch+3 ; i<=lastch; ++i)
01226 if(*i == (MYQUOTE))
01227 {
01228 while(*++i != MYQUOTE)
01229 ;
01230 }
01231 else if(*i == '(')
01232 ++parlev;
01233 else if(*i == ')')
01234 {
01235 if(--parlev == 0)
01236 break;
01237 }
01238 if(i >= lastch)
01239 stkey = SLOGIF;
01240 else if(i[1] == '=')
01241 stkey = SLET;
01242 else if( isdigit(i[1]) )
01243 stkey = SARITHIF;
01244 else stkey = SLOGIF;
01245 if(stkey != SLET)
01246 nextch += 2;
01247 }
01248 else if(expeql)
01249 {
01250 if(expcom && nextch<lastch &&
01251 nextch[0]=='d' && nextch[1]=='o')
01252 {
01253 stkey = SDO;
01254 nextch += 2;
01255 }
01256 else stkey = SLET;
01257 }
01258 else if (parseen && nextch + 7 < lastch
01259 && nextch[2] != 'u'
01260 && nextch[0] == 'd' && nextch[1] == 'o'
01261 && ((nextch[2] >= '0' && nextch[2] <= '9')
01262 || nextch[2] == ','
01263 || nextch[2] == 'w'))
01264 {
01265 stkey = SDO;
01266 nextch += 2;
01267 needwkey = 1;
01268 }
01269
01270 else {
01271 stkey = getkwd();
01272 if(stkey==SGOTO && lastch>=nextch)
01273 if(nextch[0]=='(')
01274 stkey = SCOMPGOTO;
01275 else if(isalpha_(* USC nextch))
01276 stkey = SASGOTO;
01277 }
01278 parlev = 0;
01279 }
01280
01281
01282
01283 LOCAL int
01284 getkwd(Void)
01285 {
01286 register char *i, *j;
01287 register struct Keylist *pk, *pend;
01288 int k;
01289
01290 if(! isalpha_(* USC nextch) )
01291 return(SUNKNOWN);
01292 k = letter(nextch[0]);
01293 if(pk = keystart[k])
01294 for(pend = keyend[k] ; pk<=pend ; ++pk )
01295 {
01296 i = pk->keyname;
01297 j = nextch;
01298 while(*++i==*++j && *i!='\0')
01299 ;
01300 if(*i=='\0' && j<=lastch+1)
01301 {
01302 nextch = j;
01303 if(no66flag && pk->notinf66)
01304 errstr("Not a Fortran 66 keyword: %s",
01305 pk->keyname);
01306 return(pk->keyval);
01307 }
01308 }
01309 return(SUNKNOWN);
01310 }
01311
01312 void
01313 initkey(Void)
01314 {
01315 register struct Keylist *p;
01316 register int i,j;
01317 register char *s;
01318
01319 for(i = 0 ; i<26 ; ++i)
01320 keystart[i] = NULL;
01321
01322 for(p = keys ; p->keyname ; ++p) {
01323 j = letter(p->keyname[0]);
01324 if(keystart[j] == NULL)
01325 keystart[j] = p;
01326 keyend[j] = p;
01327 }
01328 i = (maxcontin + 2) * 66;
01329 sbuf = (char *)ckalloc(i + 70 + MAX_SHARPLINE_LEN);
01330 send = sbuf + i;
01331 shend = send + MAX_SHARPLINE_LEN;
01332 maxcont = maxcontin + 1;
01333 linestart = (char **)ckalloc(maxcont*sizeof(char*));
01334 comstart['c'] = comstart['C'] = comstart['*'] = comstart['!'] =
01335 comstart['#'] = 1;
01336 #ifdef EOF_CHAR
01337 comstart[EOF_CHAR] = 1;
01338 #endif
01339 s = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_";
01340 while(i = *s++)
01341 anum_buf[i] = 1;
01342 s = "0123456789";
01343 while(i = *s++)
01344 anum_buf[i] = 2;
01345 }
01346
01347 LOCAL int
01348 #ifdef KR_headers
01349 hexcheck(key)
01350 int key;
01351 #else
01352 hexcheck(int key)
01353 #endif
01354 {
01355 register int radix;
01356 register char *p;
01357 char *kind;
01358
01359 switch(key) {
01360 case 'z':
01361 case 'Z':
01362 case 'x':
01363 case 'X':
01364 radix = 16;
01365 key = SHEXCON;
01366 kind = "hexadecimal";
01367 break;
01368 case 'o':
01369 case 'O':
01370 radix = 8;
01371 key = SOCTCON;
01372 kind = "octal";
01373 break;
01374 case 'b':
01375 case 'B':
01376 radix = 2;
01377 key = SBITCON;
01378 kind = "binary";
01379 break;
01380 default:
01381 err("bad bit identifier");
01382 return(SNAME);
01383 }
01384 for(p = token; *p; p++)
01385 if (hextoi(*p) >= radix) {
01386 errstr("invalid %s character", kind);
01387 break;
01388 }
01389 return key;
01390 }
01391
01392
01393
01394
01395 LOCAL int
01396 gettok(Void)
01397 {
01398 int havdot, havexp, havdbl;
01399 int radix, val;
01400 struct Punctlist *pp;
01401 struct Dotlist *pd;
01402 register int ch;
01403 static char Exp_mi[] = "X**-Y treated as X**(-Y)",
01404 Exp_pl[] = "X**+Y treated as X**(+Y)";
01405
01406 char *i, *j, *n1, *p;
01407
01408 ch = * USC nextch;
01409 if(ch == (MYQUOTE))
01410 {
01411 ++nextch;
01412 p = token;
01413 while(*nextch != MYQUOTE)
01414 *p++ = *nextch++;
01415 toklen = p - token;
01416 *p = 0;
01417
01418 if (++nextch <= lastch && isalpha_(val = * USC nextch)) {
01419 ++nextch;
01420 return hexcheck(val);
01421 }
01422 return (SHOLLERITH);
01423 }
01424
01425 if(needkwd)
01426 {
01427 needkwd = 0;
01428 return( getkwd() );
01429 }
01430
01431 for(pp=puncts; pp->punchar; ++pp)
01432 if(ch == pp->punchar) {
01433 val = pp->punval;
01434 if (++nextch <= lastch)
01435 switch(ch) {
01436 case '/':
01437 switch(*nextch) {
01438 case '/':
01439 nextch++;
01440 val = SCONCAT;
01441 break;
01442 case '=':
01443 goto sne;
01444 default:
01445 if (new_dcl && parlev == 0)
01446 val = SSLASHD;
01447 }
01448 return val;
01449 case '*':
01450 if (*nextch == '*') {
01451 nextch++;
01452 if (noextflag
01453 && nextch <= lastch)
01454 switch(*nextch) {
01455 case '-':
01456 errext(Exp_mi);
01457 break;
01458 case '+':
01459 errext(Exp_pl);
01460 }
01461 return SPOWER;
01462 }
01463 break;
01464 case '<':
01465 switch(*nextch) {
01466 case '=':
01467 nextch++;
01468 val = SLE;
01469 break;
01470 case '>':
01471 sne:
01472 nextch++;
01473 val = SNE;
01474 }
01475 goto extchk;
01476 case '=':
01477 if (*nextch == '=') {
01478 nextch++;
01479 val = SEQ;
01480 goto extchk;
01481 }
01482 break;
01483 case '>':
01484 if (*nextch == '=') {
01485 nextch++;
01486 val = SGE;
01487 }
01488 extchk:
01489 NOEXT("Fortran 8x comparison operator");
01490 return val;
01491 }
01492 else if (ch == '/' && new_dcl && parlev == 0)
01493 return SSLASHD;
01494 switch(val) {
01495 case SLPAR:
01496 ++parlev;
01497 break;
01498 case SRPAR:
01499 --parlev;
01500 }
01501 return(val);
01502 }
01503 if(ch == '.')
01504 if(nextch >= lastch) goto badchar;
01505 else if(isdigit(nextch[1])) goto numconst;
01506 else {
01507 for(pd=dots ; (j=pd->dotname) ; ++pd)
01508 {
01509 for(i=nextch+1 ; i<=lastch ; ++i)
01510 if(*i != *j) break;
01511 else if(*i != '.') ++j;
01512 else {
01513 nextch = i+1;
01514 return(pd->dotval);
01515 }
01516 }
01517 goto badchar;
01518 }
01519 if( isalpha_(ch) )
01520 {
01521 p = token;
01522 *p++ = *nextch++;
01523 while(nextch<=lastch)
01524 if( isalnum_(* USC nextch) )
01525 *p++ = *nextch++;
01526 else break;
01527 toklen = p - token;
01528 *p = 0;
01529 if (needwkey) {
01530 needwkey = 0;
01531 if (toklen == 5
01532 && nextch <= lastch && *nextch == '('
01533 && !strcmp(token,"while"))
01534 return(SWHILE);
01535 }
01536 if(inioctl && nextch<=lastch && *nextch=='=')
01537 {
01538 ++nextch;
01539 return(SNAMEEQ);
01540 }
01541 if(toklen>8 && eqn(8,token,"function")
01542 && isalpha_(* USC (token+8)) &&
01543 nextch<lastch && nextch[0]=='(' &&
01544 (nextch[1]==')' || isalpha_(* USC (nextch+1))) )
01545 {
01546 nextch -= (toklen - 8);
01547 return(SFUNCTION);
01548 }
01549
01550 if(toklen > MAXNAMELEN)
01551 {
01552 char buff[2*MAXNAMELEN+50];
01553 if (toklen >= MAXNAMELEN+10)
01554 sprintf(buff,
01555 "name %.*s... too long, truncated to %.*s",
01556 MAXNAMELEN+6, token, MAXNAMELEN, token);
01557 else
01558 sprintf(buff,
01559 "name %s too long, truncated to %.*s",
01560 token, MAXNAMELEN, token);
01561 err(buff);
01562 toklen = MAXNAMELEN;
01563 token[MAXNAMELEN] = '\0';
01564 }
01565 if(toklen==1 && *nextch==MYQUOTE) {
01566 val = token[0];
01567 ++nextch;
01568 for(p = token ; *nextch!=MYQUOTE ; )
01569 *p++ = *nextch++;
01570 ++nextch;
01571 toklen = p - token;
01572 *p = 0;
01573 return hexcheck(val);
01574 }
01575 return(SNAME);
01576 }
01577
01578 if (isdigit(ch)) {
01579
01580
01581
01582 if (nextch[1] == '#' && nextch < lastch
01583 || nextch[2] == '#' && isdigit(nextch[1])
01584 && lastch - nextch >= 2) {
01585
01586 radix = atoi (nextch);
01587 if (*++nextch != '#')
01588 nextch++;
01589 if (radix != 2 && radix != 8 && radix != 16) {
01590 erri("invalid base %d for constant, defaulting to hex",
01591 radix);
01592 radix = 16;
01593 }
01594 if (++nextch > lastch)
01595 goto badchar;
01596 for (p = token; hextoi(*nextch) < radix;) {
01597 *p++ = *nextch++;
01598 if (nextch > lastch)
01599 break;
01600 }
01601 toklen = p - token;
01602 *p = 0;
01603 return (radix == 16) ? SHEXCON : ((radix == 8) ? SOCTCON :
01604 SBITCON);
01605 }
01606 }
01607 else
01608 goto badchar;
01609 numconst:
01610 havdot = NO;
01611 havexp = NO;
01612 havdbl = NO;
01613 for(n1 = nextch ; nextch<=lastch ; ++nextch)
01614 {
01615 if(*nextch == '.')
01616 if(havdot) break;
01617 else if(nextch+2<=lastch && isalpha_(* USC (nextch+1))
01618 && isalpha_(* USC (nextch+2)))
01619 break;
01620 else havdot = YES;
01621 else if( ! isdigit(* USC nextch) ) {
01622 if( !intonly && (*nextch=='d' || *nextch=='e') ) {
01623 p = nextch;
01624 havexp = YES;
01625 if(*nextch == 'd')
01626 havdbl = YES;
01627 if(nextch<lastch)
01628 if(nextch[1]=='+' || nextch[1]=='-')
01629 ++nextch;
01630 if( ! isdigit(*++nextch) ) {
01631 nextch = p;
01632 havdbl = havexp = NO;
01633 break;
01634 }
01635 for(++nextch ;
01636 nextch<=lastch && isdigit(* USC nextch);
01637 ++nextch);
01638 }
01639 break;
01640 }
01641 }
01642 p = token;
01643 i = n1;
01644 while(i < nextch)
01645 *p++ = *i++;
01646 toklen = p - token;
01647 *p = 0;
01648 if(havdbl) return(SDCON);
01649 if(havdot || havexp) return(SRCON);
01650 return(SICON);
01651 badchar:
01652 sbuf[0] = *nextch++;
01653 return(SUNKNOWN);
01654 }
01655
01656
01657
01658 static void
01659 #ifdef KR_headers
01660 store_comment(str)
01661 char *str;
01662 #else
01663 store_comment(char *str)
01664 #endif
01665 {
01666 int len;
01667 comment_buf *ncb;
01668
01669 if (nextcd == sbuf) {
01670 flush_comments();
01671 p1_comment(str);
01672 return;
01673 }
01674 len = strlen(str) + 1;
01675 if (cbnext + len > cblast) {
01676 ncb = 0;
01677 if (cbcur) {
01678 cbcur->last = cbnext;
01679 ncb = cbcur->next;
01680 }
01681 if (!ncb) {
01682 ncb = (comment_buf *) Alloc(sizeof(comment_buf));
01683 if (cbcur)
01684 cbcur->next = ncb;
01685 else {
01686 cbfirst = ncb;
01687 cbinit = ncb->buf;
01688 }
01689 ncb->next = 0;
01690 }
01691 cbcur = ncb;
01692 cbnext = ncb->buf;
01693 cblast = cbnext + COMMENT_BUF_STORE;
01694 }
01695 strcpy(cbnext, str);
01696 cbnext += len;
01697 }
01698
01699 static void
01700 flush_comments(Void)
01701 {
01702 register char *s, *s1;
01703 register comment_buf *cb;
01704 if (cbnext == cbinit)
01705 return;
01706 cbcur->last = cbnext;
01707 for(cb = cbfirst;; cb = cb->next) {
01708 for(s = cb->buf; s < cb->last; s = s1) {
01709
01710
01711 s1 = s + strlen(s) + 1;
01712 p1_comment(s);
01713 }
01714 if (cb == cbcur)
01715 break;
01716 }
01717 cbcur = cbfirst;
01718 cbnext = cbinit;
01719 cblast = cbnext + COMMENT_BUF_STORE;
01720 }
01721
01722 void
01723 unclassifiable(Void)
01724 {
01725 register char *s, *se;
01726
01727 s = sbuf;
01728 se = lastch;
01729 if (se < sbuf)
01730 return;
01731 lastch = s - 1;
01732 if (++se - s > 10)
01733 se = s + 10;
01734 for(; s < se; s++)
01735 if (*s == MYQUOTE) {
01736 se = s;
01737 break;
01738 }
01739 *se = 0;
01740 errstr("unclassifiable statement (starts \"%s\")", sbuf);
01741 }
01742
01743 void
01744 endcheck(Void)
01745 {
01746 if (nextch <= lastch)
01747 warn("ignoring text after \"end\".");
01748 lexstate = RETEOS;
01749 }