|
|
1.1 ! root 1: static char sccsid[] = "@(#)tk.c 2.6"; ! 2: ! 3: #include <ctype.h> ! 4: #include "cdb.h" ! 5: ! 6: #define chTab '\t' ! 7: #define chSpace ' ' ! 8: #define chUnder '_' ! 9: #define chDollar '$' ! 10: #define chBackSlash '\\' ! 11: ! 12: export int vcbTok, vcbPeek; ! 13: export TKE vtk, vtkPeek; ! 14: export char vsbTok[100], vsbTokPeek[100]; ! 15: export LCE vlc; /* the current language which has precedence */ ! 16: ! 17: #define icmdMax 20 ! 18: int vicmdMac; ! 19: char *vrgCmd[icmdMax]; /* where we push command pointers */ ! 20: ! 21: typedef struct { /* keyword */ ! 22: char *sbKey; ! 23: short tk; ! 24: } ! 25: KWR, *pKWR; ! 26: #define cbKWR sizeof(KWR) ! 27: #define kwNil ((pKWR)0) ! 28: ! 29: KWR vrgKwCdb[] = { ! 30: "$in", tkInside, ! 31: }; ! 32: #define ikwCdbMax (sizeof(vrgKwCdb)/cbKWR) ! 33: ! 34: KWR vrgKwC[] = { ! 35: "sizeof", tkSizeof, ! 36: }; ! 37: #define ikwCMax (sizeof(vrgKwC)/cbKWR) ! 38: ! 39: KWR vrgKwFor[] = { ! 40: ".NE.", tkNotEqual, ! 41: ".EQ.", tkEqual, ! 42: ".LT.", tkLT, ! 43: ".LE.", tkLE, ! 44: ".GT.", tkGT, ! 45: ".GE.", tkGE, ! 46: }; ! 47: #define ikwForMax (sizeof(vrgKwFor)/cbKWR) ! 48: ! 49: KWR vrgKwPas[] = { ! 50: "and", tkLAND, ! 51: "or", tkLOR, ! 52: "not", tkBang, ! 53: "div", tkDiv, ! 54: "mod", tkModulo, ! 55: }; ! 56: #define ikwPasMax (sizeof(vrgKwPas)/cbKWR) ! 57: ! 58: #define isodigit(ch) (isdigit(ch) && (ch!='8') && (ch!='9')) ! 59: ! 60: ! 61: /* T K F K W */ ! 62: ! 63: export void TkFKw(ptk, sbKey, rgKw, ikwMax) ! 64: TKE *ptk; ! 65: char *sbKey; ! 66: pKWR rgKw; ! 67: int ikwMax; ! 68: { ! 69: int i; ! 70: for (i=0; i < ikwMax; i++) { ! 71: if (FSbCmp(sbKey, rgKw[i].sbKey)) { ! 72: *ptk = rgKw[i].tk; ! 73: return; ! 74: } ! 75: } ! 76: } /* TkFKw */ ! 77: ! 78: ! 79: /* C H F E S C A P E */ ! 80: ! 81: local char ChFEscape(psbIn) ! 82: char **psbIn; ! 83: { ! 84: int i, val; ! 85: char ch; ! 86: ! 87: ch = **psbIn; ! 88: (*psbIn)++; ! 89: if (ch != chBackSlash) ! 90: return(ch); /* vanilla flavored char */ ! 91: ch = **psbIn; ! 92: (*psbIn)++; ! 93: switch (ch) { ! 94: case 'b': ! 95: return('\b'); ! 96: case 'f': ! 97: return('\f'); ! 98: case 'n': ! 99: return('\n'); ! 100: case 'r': ! 101: return('\r'); ! 102: case 't': ! 103: return('\t'); ! 104: case '\\': ! 105: return('\\'); ! 106: case '\'': ! 107: return('\''); ! 108: case '0': ! 109: case '1': ! 110: case '2': ! 111: case '3': ! 112: case '4': ! 113: case '5': ! 114: case '6': ! 115: case '7': ! 116: /* it is an arbitrary 1-3 octal digit thingie */ ! 117: val = 0; ! 118: for (i=0; i<3; i++) { ! 119: val = (val * 8) + (ch - '0'); ! 120: ch = **psbIn; /* look at NEXT character */ ! 121: if (!isodigit(ch)) ! 122: break; ! 123: (*psbIn)++; /* is good digit, advance str pointer */ ! 124: } /* for */ ! 125: return(val); ! 126: } /* switch */ ! 127: return(ch); /* by default we just ignore the backslash */ ! 128: } /* ChFEscape */ ! 129: ! 130: ! 131: /* T K F S T R */ ! 132: ! 133: export TKE TkFStr(psbCmd, sbTok, pcb) ! 134: char **psbCmd, *sbTok; ! 135: int *pcb; ! 136: { ! 137: int i; ! 138: char ch, *sbCmd, *sbStart, sbT[10]; ! 139: TKE tk; ! 140: ! 141: /* given a string, copy first token to safe place and advance string */ ! 142: ! 143: sbCmd = *psbCmd; ! 144: if (sbCmd == sbNil) ! 145: return(tkNil); ! 146: ! 147: while (*sbCmd != chNull AND *sbCmd == chTab OR *sbCmd == chSpace) ! 148: sbCmd++; /* eat leading tabs and spaces */ ! 149: if (*sbCmd == chNull) { ! 150: *pcb = 0; ! 151: sbTok[0] = chNull; ! 152: return(tkNil); ! 153: } /* if */ ! 154: ! 155: sbStart = sbCmd; /* remember where we started */ ! 156: ! 157: tk = tkNil; ! 158: ch = *sbCmd++; ! 159: if (isalpha(ch) ! 160: OR (ch == chUnder) ! 161: OR (ch == chDollar)) { /* string (var|command) token */ ! 162: tk = tkStr; ! 163: while (isalnum(*sbCmd) ! 164: OR *sbCmd == chUnder) ! 165: sbCmd++; ! 166: } ! 167: else if (isdigit(ch)) { /* number */ ! 168: tk = tkNumber; ! 169: if ((ch == '0') AND (*sbCmd == 'x')) { ! 170: sbCmd++; /* it's a hex number */ ! 171: while (isxdigit(*sbCmd)) ! 172: sbCmd++; ! 173: } ! 174: else { ! 175: while (isdigit(*sbCmd)) ! 176: sbCmd++; ! 177: } /* if */ ! 178: } ! 179: else if (ispunct(ch)) { ! 180: /* hopefully an interesting operator or something */ ! 181: switch (ch) { ! 182: case '[': ! 183: tk = tkLSB; ! 184: break; ! 185: case ']': ! 186: tk = tkRSB; ! 187: break; ! 188: case '(': ! 189: tk = tkLP; ! 190: break; ! 191: case ')': ! 192: tk = tkRP; ! 193: break; ! 194: case '{': ! 195: tk = tkLCB; ! 196: break; ! 197: case '}': ! 198: tk = tkRCB; ! 199: break; ! 200: case '?': ! 201: tk = tkQuest; ! 202: break; ! 203: case '@': ! 204: tk = tkAt; ! 205: break; ! 206: case '$': ! 207: tk = tkDollar; ! 208: break; ! 209: case '#': ! 210: tk = tkHash; ! 211: break; ! 212: case ';': ! 213: tk = tkSemi; ! 214: break; ! 215: case ',': ! 216: tk = tkComma; ! 217: break; ! 218: case '_': ! 219: tk = tkUnderScore; ! 220: break; ! 221: case '\\': ! 222: tk = tkBackSlash; ! 223: break; ! 224: case '\'': ! 225: tk = tkCharConstant; ! 226: sbTok[0] = ChFEscape(&sbCmd); ! 227: if (*sbCmd != '\'') ! 228: UError("Character constant is missing ending '"); ! 229: sbCmd++; ! 230: *pcb = 1; ! 231: goto special; ! 232: case '"': ! 233: tk = tkStrConstant; ! 234: i = 0; ! 235: while ((*sbCmd != chNull) AND (*sbCmd != '"')) { ! 236: sbTok[i] = ChFEscape(&sbCmd); ! 237: i++; ! 238: } /* while */ ! 239: if (*sbCmd != '"') ! 240: UError("String constant is missing ending \""); ! 241: sbCmd++; ! 242: *pcb = i; ! 243: goto special; ! 244: case '.': ! 245: tk = tkDot; ! 246: if (vlc != lcFortran) ! 247: break; ! 248: if (sbCmd[2] == '.') { ! 249: /* we have '.XX.' - might be a relop */ ! 250: strncpy(sbT, sbCmd-1, 4); /* get the whole thing */ ! 251: TkFKw(&tk, sbT, vrgKwFor, ikwForMax); ! 252: if (tk != tkDot) { ! 253: /* we have a hit */ ! 254: sbCmd += 3; ! 255: } ! 256: } ! 257: break; ! 258: case ':': ! 259: tk = tkColon; ! 260: if (*sbCmd == '=') { ! 261: sbCmd++; ! 262: tk = tkAssign; ! 263: } /* if */ ! 264: break; ! 265: case '+': ! 266: tk = tkPlus; ! 267: if (*sbCmd == '=') { ! 268: sbCmd++; ! 269: tk = tkAssPlus; ! 270: } /* if */ ! 271: break; ! 272: case '-': ! 273: tk = tkMinus; ! 274: if (*sbCmd == '>') { ! 275: sbCmd++; ! 276: tk = tkPtr; ! 277: } ! 278: else if (*sbCmd == '=') { ! 279: sbCmd++; ! 280: tk = tkAssMinus; ! 281: } /* if */ ! 282: break; ! 283: case '*': ! 284: tk = tkStar; ! 285: if (*sbCmd == '=') { ! 286: sbCmd++; ! 287: tk = tkAssMult; ! 288: } /* if */ ! 289: break; ! 290: case '/': ! 291: tk = tkSlash; ! 292: if (*sbCmd == '/') { ! 293: sbCmd++; ! 294: tk = tkDiv; ! 295: if (*sbCmd == '=') { ! 296: sbCmd++; ! 297: tk = tkAssDiv; ! 298: } /* if */ ! 299: } /* if */ ! 300: break; ! 301: case '%': ! 302: tk = tkModulo; ! 303: if (*sbCmd == '=') { ! 304: sbCmd++; ! 305: tk = tkAssMod; ! 306: } /* if */ ! 307: break; ! 308: case '&': ! 309: tk = tkBitAnd; ! 310: if (*sbCmd == '&') { ! 311: sbCmd++; ! 312: tk = tkLAND; ! 313: } ! 314: else if (*sbCmd == '=') { ! 315: sbCmd++; ! 316: tk = tkAssBAND; ! 317: } /* if */ ! 318: break; ! 319: case '|': ! 320: tk = tkBitOr; ! 321: if (*sbCmd == '|') { ! 322: sbCmd++; ! 323: tk = tkLOR; ! 324: } ! 325: else if (*sbCmd == '=') { ! 326: sbCmd++; ! 327: tk = tkAssBOR; ! 328: } /* if */ ! 329: break; ! 330: case '^': ! 331: tk = tkXOR; ! 332: if (*sbCmd == '=') { ! 333: sbCmd++; ! 334: tk = tkAssXOR; ! 335: } ! 336: else if (*sbCmd == '.') { ! 337: if (vlc == lcPascal) { ! 338: sbCmd++; ! 339: tk = tkPtr; ! 340: } ! 341: } /* if */ ! 342: break; ! 343: case '~': ! 344: tk = tkTilda; ! 345: break; ! 346: case '!': ! 347: tk = tkBang; ! 348: if (*sbCmd == '=') { ! 349: sbCmd++; ! 350: tk = tkNotEqual; ! 351: } /* if */ ! 352: break; ! 353: case '=': ! 354: if (vlc == lcPascal) { ! 355: tk = tkEqual; ! 356: } ! 357: else { ! 358: tk = tkAssign; ! 359: if (*sbCmd == '=') { ! 360: sbCmd++; ! 361: tk = tkEqual; ! 362: } /* if */ ! 363: } ! 364: break; ! 365: case '<': ! 366: tk = tkLT; ! 367: if (*sbCmd == '=') { ! 368: sbCmd++; ! 369: tk = tkLE; ! 370: } ! 371: else if (*sbCmd =='<') { ! 372: sbCmd++; ! 373: tk = tkLShift; ! 374: if (*sbCmd == '=') { ! 375: sbCmd++; ! 376: tk = tkAssLeft; ! 377: } /* if */ ! 378: } ! 379: else if (*sbCmd == '>') { ! 380: sbCmd++; ! 381: tk = tkNotEqual; ! 382: } /* if */ ! 383: break; ! 384: case '>': ! 385: tk = tkGT; ! 386: if (*sbCmd == '=') { ! 387: sbCmd++; ! 388: tk = tkGE; ! 389: } ! 390: else if (*sbCmd =='>') { ! 391: sbCmd++; ! 392: tk = tkRShift; ! 393: if (*sbCmd == '=') { ! 394: sbCmd++; ! 395: tk = tkAssRight; ! 396: } /* if */ ! 397: } /* if */ ! 398: break; ! 399: } /* switch */ ! 400: } ! 401: else { /* it's <something else> !! */ ! 402: tk = tkOther; ! 403: } /* if */ ! 404: ! 405: *pcb = sbCmd - sbStart; ! 406: strncpy(sbTok, sbStart, *pcb); ! 407: ! 408: special: /* used by character and string constant routines */ ! 409: sbTok[*pcb] = chNull; ! 410: *psbCmd = sbCmd; ! 411: ! 412: if (tk == tkStr) { ! 413: TkFKw(&tk, sbTok, vrgKwCdb, ikwCdbMax); ! 414: switch (vlc) { ! 415: case lcC: ! 416: TkFKw(&tk, sbTok, vrgKwC, ikwCMax); ! 417: break; ! 418: case lcPascal: ! 419: TkFKw(&tk, sbTok, vrgKwPas, ikwPasMax); ! 420: break; ! 421: case lcFortran: ! 422: TkFKw(&tk, sbTok, vrgKwFor, ikwForMax); ! 423: break; ! 424: } /* switch */ ! 425: } ! 426: ! 427: return(tk); ! 428: } /* TkFStr */ ! 429: ! 430: ! 431: /* P O P C M D */ ! 432: ! 433: export char * PopCmd() ! 434: { ! 435: if (vicmdMac == 0) ! 436: return(sbNil); ! 437: return(vrgCmd[--vicmdMac]); ! 438: } /* PopCmd */ ! 439: ! 440: ! 441: /* P U S H C M D */ ! 442: ! 443: export void PushCmd(sbCmd) ! 444: char *sbCmd; ! 445: { ! 446: if (sbCmd == sbNil OR *sbCmd == chNull) ! 447: return; ! 448: if (vicmdMac >= icmdMax) { ! 449: vicmdMac = 0; ! 450: Panic("Too much command nesting - flushing everything"); ! 451: } /* if */ ! 452: vrgCmd[vicmdMac++] = sbCmd; ! 453: } /* PushCmd */ ! 454: ! 455: ! 456: /* T K P E E K */ ! 457: ! 458: export TKE TkPeek() ! 459: { ! 460: char *sbCmd; ! 461: /* used to peek at next token in global command line */ ! 462: sbCmd = vsbCmd; ! 463: vtkPeek = TkFStr(&sbCmd, vsbTokPeek, &vcbPeek); ! 464: return(vtkPeek); ! 465: } /* TkPeek */ ! 466: ! 467: ! 468: /* T K N E X T */ ! 469: ! 470: export TKE TkNext() ! 471: { ! 472: /* used by most routines to eat next token in the global command line */ ! 473: while ((vtk = TkFStr(&vsbCmd, vsbTok, &vcbTok)) == tkNil) { ! 474: if (vicmdMac == 0) ! 475: return(tkNil); ! 476: vsbCmd = PopCmd(); ! 477: } /* while */ ! 478: return(vtk); ! 479: } /* TkNext */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.