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