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