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: };