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