|
|
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.