|
|
1.1 ! root 1: /*++ ! 2: ! 3: Copyright (c) 1991 Microsoft Corporation ! 4: ! 5: Module Name: ! 6: ! 7: mclex.c ! 8: ! 9: Abstract: ! 10: ! 11: This file contains the input lexer for the Win32 Message Compiler (MC) ! 12: ! 13: --*/ ! 14: ! 15: ! 16: #include "mc.h" ! 17: ! 18: char LineBuffer[ 256 ]; ! 19: char *CurrentChar; ! 20: BOOLEAN ReturnCurrentToken; ! 21: ! 22: PNAME_INFO KeywordNames; ! 23: ! 24: typedef struct _COMMENT_INFO { ! 25: struct _COMMENT_INFO *Next; ! 26: char Text[ 1 ]; ! 27: } COMMENT_INFO, *PCOMMENT_INFO; ! 28: ! 29: PCOMMENT_INFO Comments, CurrentComment; ! 30: ! 31: /*++ ! 32: ! 33: Routine Description: ! 34: ! 35: This fills in the Key words associated with the Message file format ! 36: ! 37: Return Value: ! 38: ! 39: TRUE ! 40: ! 41: --*/ ! 42: ! 43: ! 44: ! 45: BOOLEAN ! 46: McInitLexer( void ) ! 47: { ! 48: ReturnCurrentToken = FALSE; ! 49: McAddName( &KeywordNames, "MessageIdTypedef", MCTOK_MSGIDTYPE_KEYWORD, NULL ); ! 50: McAddName( &KeywordNames, "SeverityNames", MCTOK_SEVNAMES_KEYWORD, NULL ); ! 51: McAddName( &KeywordNames, "FacilityNames", MCTOK_FACILITYNAMES_KEYWORD, NULL ); ! 52: McAddName( &KeywordNames, "LanguageNames", MCTOK_LANGNAMES_KEYWORD, NULL ); ! 53: McAddName( &KeywordNames, "MessageId", MCTOK_MESSAGEID_KEYWORD, NULL ); ! 54: McAddName( &KeywordNames, "Severity", MCTOK_SEVERITY_KEYWORD, NULL ); ! 55: McAddName( &KeywordNames, "Facility", MCTOK_FACILITY_KEYWORD, NULL ); ! 56: McAddName( &KeywordNames, "SymbolicName", MCTOK_SYMBOLNAME_KEYWORD, NULL ); ! 57: McAddName( &KeywordNames, "Language", MCTOK_LANGUAGE_KEYWORD, NULL ); ! 58: return( TRUE ); ! 59: } ! 60: ! 61: ! 62: ! 63: BOOLEAN ! 64: McOpenInputFile( void ) ! 65: { ! 66: char SavedChar, *s, *FileName; ! 67: BOOLEAN Result; ! 68: ! 69: s = MessageFileName; ! 70: FileName = s; ! 71: SavedChar = '\0'; ! 72: while (*s) { ! 73: if (*s == '.') { ! 74: SavedChar = '.'; ! 75: *s = '\0'; ! 76: break; ! 77: } ! 78: ! 79: if (*s == ':' || *s == '\\' || *s == '/') { ! 80: FileName = s+1; ! 81: } ! 82: ! 83: s++; ! 84: } ! 85: ! 86: strcat( HeaderFileName, FileName ); ! 87: strcat( HeaderFileName, ".h" ); ! 88: strcat( RcInclFileName, FileName ); ! 89: strcat( RcInclFileName, ".rc" ); ! 90: ! 91: if (SavedChar == '\0') { ! 92: strcpy( s, ".mc" ); ! 93: } ! 94: else { ! 95: *s = SavedChar; ! 96: } ! 97: ! 98: Result = FALSE; ! 99: MessageFileLineNumber = 0; ! 100: LineBuffer[ 0 ] = '\0'; ! 101: CurrentChar = NULL; ! 102: ! 103: MessageFile = fopen( MessageFileName, "rb" ); ! 104: if (MessageFile == NULL) { ! 105: McInputError( "unable to open input file", TRUE, NULL ); ! 106: } ! 107: else { ! 108: HeaderFile = fopen( HeaderFileName, "wb" ); ! 109: if (HeaderFile == NULL) { ! 110: McInputError( "unable to open output file - %s", TRUE, HeaderFileName ); ! 111: } ! 112: else { ! 113: RcInclFile = fopen( RcInclFileName, "wb" ); ! 114: if (RcInclFile == NULL) { ! 115: McInputError( "unable to open output file - %s", TRUE, RcInclFileName ); ! 116: } ! 117: else { ! 118: Result = TRUE; ! 119: } ! 120: } ! 121: } ! 122: ! 123: if (!Result) { ! 124: McCloseInputFile(); ! 125: McCloseOutputFiles(); ! 126: } ! 127: else { ! 128: return( TRUE ); ! 129: } ! 130: } ! 131: ! 132: ! 133: ! 134: void ! 135: McCloseInputFile( void ) ! 136: { ! 137: if (MessageFile != NULL) { ! 138: fclose( MessageFile ); ! 139: MessageFile = NULL; ! 140: CurrentChar = NULL; ! 141: LineBuffer[ 0 ] = '\0'; ! 142: } ! 143: } ! 144: ! 145: ! 146: ! 147: void ! 148: McCloseOutputFiles( void ) ! 149: { ! 150: if (HeaderFile != NULL) { ! 151: fclose( HeaderFile ); ! 152: } ! 153: ! 154: if (RcInclFile != NULL) { ! 155: fclose( RcInclFile ); ! 156: } ! 157: } ! 158: ! 159: ! 160: void ! 161: McInputError( ! 162: char *Message, ! 163: BOOLEAN Error, ! 164: PVOID Argument ! 165: ) ! 166: { ! 167: fprintf( stderr, ! 168: "%s (%d) : %s: ", ! 169: MessageFileName, ! 170: MessageFileLineNumber, ! 171: Error ? "Error" : "Warning" ! 172: ); ! 173: ! 174: fprintf( stderr, Message, Argument ); ! 175: fprintf( stderr, "\n" ); ! 176: } ! 177: ! 178: ! 179: /*++ ! 180: ! 181: Routine Description: ! 182: ! 183: This retrieves the current line then moves down to the ! 184: next line in the message file. ! 185: ! 186: Return Value: ! 187: ! 188: Returns the current line of in the file. ! 189: ! 190: --*/ ! 191: ! 192: ! 193: char * ! 194: McGetLine( void ) ! 195: { ! 196: char *s; ! 197: ! 198: if (MessageFile == NULL || feof( MessageFile )) { ! 199: return( NULL ); ! 200: } ! 201: ! 202: if (fgets( LineBuffer, sizeof( LineBuffer ), MessageFile ) == NULL) { ! 203: return( NULL ); ! 204: } ! 205: ! 206: s = LineBuffer + strlen( LineBuffer ); ! 207: if (s > LineBuffer && *--s == '\n') { ! 208: if (s > LineBuffer && *--s != '\r') { ! 209: *++s = '\r'; ! 210: *++s = '\n'; ! 211: *++s = '\0'; ! 212: } ! 213: } ! 214: ! 215: MessageFileLineNumber++; ! 216: return( CurrentChar = LineBuffer ); ! 217: } ! 218: ! 219: ! 220: void ! 221: McSkipLine( void ) ! 222: { ! 223: CurrentChar = NULL; ! 224: } ! 225: ! 226: ! 227: /*++ ! 228: ! 229: Routine Description: ! 230: ! 231: This retrieves the character at the current position of the line ! 232: buffer then advances to the next position. If the end of the line ! 233: is reached another line is retrieve. If the end of the file is reached ! 234: this returns with a NULL character. One is optionally able to flush ! 235: the white space from the line. ! 236: ! 237: Arguments: ! 238: ! 239: A boolean specifying whether whitespace should be consider significant. ! 240: ! 241: Return Value: ! 242: ! 243: Returns the character in the current line. ! 244: ! 245: --*/ ! 246: ! 247: ! 248: ! 249: ! 250: char ! 251: McGetChar( ! 252: BOOLEAN SkipWhiteSpace ! 253: ) ! 254: { ! 255: BOOLEAN SawWhiteSpace; ! 256: BOOLEAN SawNewLine; ! 257: PCOMMENT_INFO p; ! 258: ! 259: SawWhiteSpace = FALSE; ! 260: ! 261: tryagain: ! 262: SawNewLine = FALSE; ! 263: if (CurrentChar == NULL) { ! 264: McGetLine(); ! 265: if (CurrentChar == NULL) { ! 266: return( '\0' ); ! 267: } ! 268: ! 269: SawNewLine = TRUE; ! 270: } ! 271: ! 272: if (SkipWhiteSpace) { ! 273: while (*CurrentChar <= ' ') { ! 274: SawWhiteSpace = TRUE; ! 275: if (!*CurrentChar++) { ! 276: CurrentChar = NULL; ! 277: break; ! 278: } ! 279: } ! 280: } ! 281: ! 282: if (SawNewLine) { ! 283: if (CurrentChar != NULL && *CurrentChar == MCCHAR_END_OF_LINE_COMMENT) { ! 284: p = malloc( sizeof( *p ) + strlen( ++CurrentChar ) ); ! 285: p->Next = NULL; ! 286: strcpy( p->Text, CurrentChar ); ! 287: if (CurrentComment == NULL) { ! 288: Comments = p; ! 289: } ! 290: else { ! 291: CurrentComment->Next = p; ! 292: } ! 293: CurrentComment = p; ! 294: ! 295: CurrentChar = NULL; ! 296: } ! 297: } ! 298: ! 299: if (CurrentChar == NULL && SkipWhiteSpace) { ! 300: goto tryagain; ! 301: } ! 302: ! 303: if (SawWhiteSpace) { ! 304: return( ' ' ); ! 305: } ! 306: else { ! 307: return( *CurrentChar++ ); ! 308: } ! 309: } ! 310: ! 311: ! 312: void ! 313: McFlushComments( void ) ! 314: { ! 315: PCOMMENT_INFO p; ! 316: ! 317: while (p = Comments) { ! 318: fprintf( HeaderFile, "%s", p->Text ); ! 319: ! 320: Comments = Comments->Next; ! 321: free( p ); ! 322: } ! 323: Comments = NULL; ! 324: CurrentComment = NULL; ! 325: ! 326: fflush( HeaderFile ); ! 327: return; ! 328: } ! 329: ! 330: ! 331: void ! 332: McUnGetChar( ! 333: char c ! 334: ) ! 335: { ! 336: if (CurrentChar > LineBuffer) { ! 337: *--CurrentChar = c; ! 338: } ! 339: else { ! 340: LineBuffer[ 0 ] = c; ! 341: LineBuffer[ 1 ] = '\0'; ! 342: CurrentChar = LineBuffer; ! 343: } ! 344: } ! 345: ! 346: ! 347: /*++ ! 348: ! 349: Routine Description: ! 350: ! 351: Breaks input line into "tokens values" as defined in MC.H. ! 352: ! 353: Arguments: ! 354: ! 355: A boolean designating whether keywords are required. ! 356: ! 357: Return Value: ! 358: ! 359: Returns the the token corresponding to the "token value" For example ! 360: with a token of type MCTOK_NUMBER the value would be a string ! 361: representation of an integer. ! 362: ! 363: --*/ ! 364: ! 365: ! 366: unsigned int ! 367: McGetToken( ! 368: BOOLEAN KeywordExpected ! 369: ) ! 370: { ! 371: char c, *dst; ! 372: ! 373: if (ReturnCurrentToken) { ! 374: ReturnCurrentToken = FALSE; ! 375: if (Token == MCTOK_NAME && KeywordExpected) { ! 376: TokenKeyword = McFindName( KeywordNames, TokenCharValue ); ! 377: if (TokenKeyword == NULL) { ! 378: McInputError( "expected keyword - %s", TRUE, TokenCharValue ); ! 379: Token = MCTOK_END_OF_FILE; ! 380: } ! 381: else { ! 382: Token = (unsigned int)TokenKeyword->Id; ! 383: } ! 384: } ! 385: ! 386: return( Token ); ! 387: } ! 388: ! 389: Token = MCTOK_END_OF_FILE; ! 390: dst = TokenCharValue; ! 391: *dst = '\0'; ! 392: TokenNumericValue = 0L; ! 393: ! 394: while (TRUE) { ! 395: c = McGetChar( (BOOLEAN)(Token == MCTOK_END_OF_FILE) ); ! 396: if (Token == MCTOK_NUMBER) { ! 397: if (isdigit( c ) || ! 398: c == 'x' || ! 399: (c >= 'a' && c <= 'f') || ! 400: (c >= 'A' && c <= 'F') ! 401: ) { ! 402: *dst++ = c; ! 403: } ! 404: else { ! 405: McUnGetChar( c ); ! 406: *dst = '\0'; ! 407: ! 408: if (!McCharToInteger( TokenCharValue, 0, &TokenNumericValue )) { ! 409: McInputError( "invalid number - %s", TRUE, TokenCharValue ); ! 410: Token = MCTOK_END_OF_FILE; ! 411: } ! 412: else { ! 413: return( Token ); ! 414: } ! 415: } ! 416: } ! 417: else ! 418: if (Token == MCTOK_NAME) { ! 419: if (iscsym( c )) { ! 420: *dst++ = c; ! 421: } ! 422: else { ! 423: McUnGetChar( c ); ! 424: *dst = '\0'; ! 425: ! 426: if (KeywordExpected) { ! 427: TokenKeyword = McFindName( KeywordNames, TokenCharValue ); ! 428: if (TokenKeyword == NULL) { ! 429: McInputError( "expected keyword - %s", TRUE, TokenCharValue ); ! 430: Token = MCTOK_END_OF_FILE; ! 431: } ! 432: else { ! 433: Token = (unsigned int)TokenKeyword->Id; ! 434: } ! 435: } ! 436: return( Token ); ! 437: } ! 438: } ! 439: else ! 440: if (isdigit( c )) { ! 441: *dst++ = c; ! 442: Token = MCTOK_NUMBER; ! 443: } ! 444: else ! 445: if (iscsymf( c )) { ! 446: *dst++ = c; ! 447: Token = MCTOK_NAME; ! 448: } ! 449: else ! 450: if (c == '=') { ! 451: *dst++ = c; ! 452: *dst = '\0'; ! 453: Token = MCTOK_EQUAL; ! 454: return( Token ); ! 455: } ! 456: else ! 457: if (c == '(') { ! 458: *dst++ = c; ! 459: *dst = '\0'; ! 460: Token = MCTOK_LEFT_PAREN; ! 461: return( Token ); ! 462: } ! 463: else ! 464: if (c == ')') { ! 465: *dst++ = c; ! 466: *dst = '\0'; ! 467: Token = MCTOK_RIGHT_PAREN; ! 468: return( Token ); ! 469: } ! 470: else ! 471: if (c == ':') { ! 472: *dst++ = c; ! 473: *dst = '\0'; ! 474: Token = MCTOK_COLON; ! 475: return( Token ); ! 476: } ! 477: else ! 478: if (c == '+') { ! 479: *dst++ = c; ! 480: *dst = '\0'; ! 481: Token = MCTOK_PLUS; ! 482: return( Token ); ! 483: } ! 484: else ! 485: if (c == ' ') { ! 486: } ! 487: else ! 488: if (c == MCCHAR_END_OF_LINE_COMMENT) { ! 489: Token = MCTOK_END_OF_LINE_COMMENT; ! 490: strcpy( TokenCharValue, CurrentChar ); ! 491: CurrentChar = NULL; ! 492: return( Token ); ! 493: } ! 494: else ! 495: if (c == '\0') { ! 496: return( Token ); ! 497: } ! 498: else { ! 499: McInputError( "invalid character '%c'", TRUE, (PVOID)(ULONG)(UCHAR)c ); ! 500: } ! 501: } ! 502: } ! 503: ! 504: ! 505: void ! 506: McUnGetToken( void ) ! 507: { ! 508: ReturnCurrentToken = TRUE; ! 509: } ! 510: ! 511: char * ! 512: McSkipWhiteSpace( ! 513: char *s ! 514: ) ! 515: { ! 516: while (*s <= ' ') { ! 517: if (!*s++) { ! 518: s = NULL; ! 519: break; ! 520: } ! 521: } ! 522: ! 523: return( s ); ! 524: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.