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

Defined functions

analyz defined in line 626; used 1 times
crunch defined in line 503; used 1 times
doinclude defined in line 135; used 2 times
getcd defined in line 358; used 2 times
getcds defined in line 293; used 1 times
getkwd defined in line 687; used 2 times
gettok defined in line 737; used 1 times
inilex defined in line 104; used 1 times
initkey defined in line 719; used 1 times
lexline defined in line 124; used 2 times
popinclude defined in line 204; used 1 times
yylex defined in line 244; never used

Defined variables

code defined in line 75; used 6 times
dots defined in line 994; used 2 times
endcd defined in line 72; used 15 times
expcom defined in line 67; used 3 times
expeql defined in line 68; used 3 times
inclp defined in line 94; used 30 times
keyend defined in line 99; used 2 times
keys defined in line 1011; used 2 times
keystart defined in line 99; used 4 times
lastch defined in line 70; used 29 times
lastend defined in line 61; used 1 times
lexstate defined in line 76; used 7 times
newname defined in line 80; used 16 times
nextcd defined in line 71; used 18 times
nextch defined in line 69; used 97 times
nincl defined in line 79; used 3 times
nxtstno defined in line 65; used 8 times
parlev defined in line 66; used 12 times
prevlin defined in line 73; used 5 times
puncts defined in line 968; used 2 times
s defined in line 77; used 18 times
sccsid defined in line 8; never used
send defined in line 78; used 4 times
stkey defined in line 60; used 17 times
stno defined in line 64; used 4 times
thislin defined in line 74; used 10 times

Defined struct's

Dotlist defined in line 98; used 6 times
Fmtlist defined in line 97; used 2 times
  • in line 743(2)
Inclfile defined in line 82; used 8 times
Keylist defined in line 95; used 10 times
Punctlist defined in line 96; used 6 times

Defined macros

BLANK defined in line 42; used 8 times
FIRSTTOKEN defined in line 55; used 1 times
MYQUOTE defined in line 43; used 10 times
NEWSTMT defined in line 54; used 3 times
OTHERTOKEN defined in line 56; used 1 times
RETEOS defined in line 57; used 1 times
SEOF defined in line 44; used 1 times
STCONTINUE defined in line 50; used 3 times
STEOF defined in line 48; used 8 times
STINITIAL defined in line 49; used 2 times
Last modified: 1986-01-11
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 4789
Valid CSS Valid XHTML 1.0 Strict