update copyright dates
[deliverable/binutils-gdb.git] / binutils / rclex.c
CommitLineData
4a594fce
NC
1/* rclex.c -- lexer for Windows rc files parser */
2
aa820537 3/* Copyright 1997, 1998, 1999, 2001, 2002, 2003, 2005, 2006, 2007, 2008, 2009
4a594fce
NC
4 Free Software Foundation, Inc.
5
6 Written by Kai Tietz, Onevision.
7
8 This file is part of GNU Binutils.
9
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
32866df7 12 the Free Software Foundation; either version 3 of the License, or
4a594fce
NC
13 (at your option) any later version.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
23 02110-1301, USA. */
24
32866df7 25
4a594fce
NC
26/* This is a lexer used by the Windows rc file parser. It basically
27 just recognized a bunch of keywords. */
28
29#include "sysdep.h"
30#include "bfd.h"
31#include "bucomm.h"
32#include "libiberty.h"
33#include "safe-ctype.h"
34#include "windres.h"
35#include "rcparse.h"
36
37#include <assert.h>
38
39/* Whether we are in rcdata mode, in which we returns the lengths of
40 strings. */
41
42static int rcdata_mode;
43
44/* Whether we are supressing lines from cpp (including windows.h or
45 headers from your C sources may bring in externs and typedefs).
46 When active, we return IGNORED_TOKEN, which lets us ignore these
47 outside of resource constructs. Thus, it isn't required to protect
48 all the non-preprocessor lines in your header files with #ifdef
49 RC_INVOKED. It also means your RC file can't include other RC
50 files if they're named "*.h". Sorry. Name them *.rch or whatever. */
51
52static int suppress_cpp_data;
53
54#define IGNORE_CPP(x) (suppress_cpp_data ? IGNORED_TOKEN : (x))
55
56/* The first filename we detect in the cpp output. We use this to
57 tell included files from the original file. */
58
59static char *initial_fn;
60
61/* List of allocated strings. */
62
63struct alloc_string
64{
65 struct alloc_string *next;
66 char *s;
67};
68
69static struct alloc_string *strings;
70
71struct rclex_keywords
72{
73 const char *name;
74 int tok;
75};
76
77#define K(KEY) { #KEY, KEY }
78#define KRT(KEY) { #KEY, RT_##KEY }
79
80static const struct rclex_keywords keywds[] =
81{
82 K(ACCELERATORS), K(ALT), K(ANICURSOR), K(ANIICON), K(ASCII),
83 K(AUTO3STATE), K(AUTOCHECKBOX), K(AUTORADIOBUTTON),
84 K(BEDIT), { "BEGIN", BEG }, K(BITMAP), K(BLOCK), K(BUTTON),
85 K(CAPTION), K(CHARACTERISTICS), K(CHECKBOX), K(CHECKED),
86 K(CLASS), K(COMBOBOX), K(CONTROL), K(CTEXT), K(CURSOR),
87 K(DEFPUSHBUTTON), K(DIALOG), K(DIALOGEX), K(DISCARDABLE),
88 K(DLGINCLUDE), K(DLGINIT),
89 K(EDITTEXT), K(END), K(EXSTYLE),
90 K(FILEFLAGS), K(FILEFLAGSMASK), K(FILEOS), K(FILESUBTYPE),
91 K(FILETYPE), K(FILEVERSION), K(FIXED), K(FONT), K(FONTDIR),
92 K(GRAYED), KRT(GROUP_CURSOR), KRT(GROUP_ICON), K(GROUPBOX),
93 K(HEDIT), K(HELP), K(HTML),
94 K(ICON), K(IEDIT), K(IMPURE), K(INACTIVE),
95 K(LANGUAGE), K(LISTBOX), K(LOADONCALL), K(LTEXT),
96 K(MANIFEST), K(MENU), K(MENUBARBREAK), K(MENUBREAK),
97 K(MENUEX), K(MENUITEM), K(MESSAGETABLE), K(MOVEABLE),
98 K(NOINVERT), K(NOT),
99 K(PLUGPLAY), K(POPUP), K(PRELOAD), K(PRODUCTVERSION),
100 K(PURE), K(PUSHBOX), K(PUSHBUTTON),
101 K(RADIOBUTTON), K(RCDATA), K(RTEXT),
102 K(SCROLLBAR), K(SEPARATOR), K(SHIFT), K(STATE3),
103 K(STRINGTABLE), K(STYLE),
104 K(TOOLBAR),
105 K(USERBUTTON),
106 K(VALUE), { "VERSION", VERSIONK }, K(VERSIONINFO),
107 K(VIRTKEY), K(VXD),
108 { NULL, 0 },
109};
110
111/* External input stream from resrc */
112extern FILE *cpp_pipe;
113
114/* Lexical scanner helpers. */
115static int rclex_lastch = -1;
116static size_t rclex_tok_max = 0;
117static size_t rclex_tok_pos = 0;
118static char *rclex_tok = NULL;
119
120static int
121rclex_translatekeyword (const char *key)
122{
123 if (key && ISUPPER (key[0]))
124 {
125 const struct rclex_keywords *kw = &keywds[0];
126
127 do
128 {
129 if (! strcmp (kw->name, key))
130 return kw->tok;
131 ++kw;
132 }
133 while (kw->name != NULL);
134 }
135 return STRING;
136}
137
138/* Handle a C preprocessor line. */
139
140static void
141cpp_line (void)
142{
143 const char *s = rclex_tok;
144 int line;
145 char *send, *fn;
d856f2dd 146 size_t len, mlen;
4a594fce
NC
147
148 ++s;
149 while (ISSPACE (*s))
150 ++s;
151
d856f2dd
NC
152 /* Check for #pragma code_page ( DEFAULT | <nr>). */
153 len = strlen (s);
154 mlen = strlen ("pragma");
155 if (len > mlen && memcmp (s, "pragma", mlen) == 0 && ISSPACE (s[mlen]))
156 {
157 const char *end;
158
159 s += mlen + 1;
160 while (ISSPACE (*s))
161 ++s;
162 len = strlen (s);
163 mlen = strlen ("code_page");
164 if (len <= mlen || memcmp (s, "code_page", mlen) != 0)
165 /* FIXME: We ought to issue a warning message about an unrecognised pragma. */
166 return;
167 s += mlen;
168 while (ISSPACE (*s))
169 ++s;
170 if (*s != '(')
171 /* FIXME: We ought to issue an error message about a malformed pragma. */
172 return;
173 ++s;
174 while (ISSPACE (*s))
175 ++s;
176 if (*s == 0 || (end = strchr (s, ')')) == NULL)
177 /* FIXME: We ought to issue an error message about a malformed pragma. */
178 return;
179 len = (size_t) (end - s);
180 fn = xmalloc (len + 1);
181 if (len)
182 memcpy (fn, s, len);
183 fn[len] = 0;
184 while (len > 0 && (fn[len - 1] > 0 && fn[len - 1] <= 0x20))
185 fn[--len] = 0;
186 if (! len || (len == strlen ("DEFAULT") && strcasecmp (fn, "DEFAULT") == 0))
187 wind_current_codepage = wind_default_codepage;
188 else if (len > 0)
189 {
190 rc_uint_type ncp;
191
192 if (fn[0] == '0' && (fn[1] == 'x' || fn[1] == 'X'))
193 ncp = (rc_uint_type) strtol (fn + 2, NULL, 16);
194 else
195 ncp = (rc_uint_type) strtol (fn, NULL, 10);
196 if (ncp == CP_UTF16 || ! unicode_is_valid_codepage (ncp))
197 fatal (_("invalid value specified for pragma code_page.\n"));
198 wind_current_codepage = ncp;
199 }
200 free (fn);
201 return;
202 }
203
4a594fce
NC
204 line = strtol (s, &send, 0);
205 if (*send != '\0' && ! ISSPACE (*send))
206 return;
207
208 /* Subtract 1 because we are about to count the newline. */
209 rc_lineno = line - 1;
210
211 s = send;
212 while (ISSPACE (*s))
213 ++s;
214
215 if (*s != '"')
216 return;
217
218 ++s;
219 send = strchr (s, '"');
220 if (send == NULL)
221 return;
222
223 fn = xmalloc (send - s + 1);
224 strncpy (fn, s, send - s);
225 fn[send - s] = '\0';
226
227 free (rc_filename);
228 rc_filename = fn;
229
230 if (! initial_fn)
231 {
232 initial_fn = xmalloc (strlen (fn) + 1);
233 strcpy (initial_fn, fn);
234 }
235
236 /* Allow the initial file, regardless of name. Suppress all other
237 files if they end in ".h" (this allows included "*.rc"). */
238 if (strcmp (initial_fn, fn) == 0
239 || strcmp (fn + strlen (fn) - 2, ".h") != 0)
240 suppress_cpp_data = 0;
241 else
242 suppress_cpp_data = 1;
243}
244
245/* Allocate a string of a given length. */
246
247static char *
248get_string (int len)
249{
250 struct alloc_string *as;
251
252 as = xmalloc (sizeof *as);
253 as->s = xmalloc (len);
254
255 as->next = strings;
256 strings = as;
257
258 return as->s;
259}
260
261/* Handle a quoted string. The quotes are stripped. A pair of quotes
262 in a string are turned into a single quote. Adjacent strings are
263 merged separated by whitespace are merged, as in C. */
264
265static char *
266handle_quotes (rc_uint_type *len)
267{
268 const char *input = rclex_tok;
269 char *ret, *s;
270 const char *t;
271 int ch;
272 int num_xdigits;
273
274 ret = get_string (strlen (input) + 1);
275
276 s = ret;
277 t = input;
278 if (*t == '"')
279 ++t;
280 while (*t != '\0')
281 {
282 if (*t == '\\')
283 {
284 ++t;
285 switch (*t)
286 {
287 case '\0':
288 rcparse_warning ("backslash at end of string");
289 break;
290
291 case '\"':
292 rcparse_warning ("use \"\" to put \" in a string");
293 *s++ = '"';
294 ++t;
295 break;
296
297 case 'a':
298 *s++ = ESCAPE_B; /* Strange, but true... */
299 ++t;
300 break;
301
302 case 'b':
303 *s++ = ESCAPE_B;
304 ++t;
305 break;
306
307 case 'f':
308 *s++ = ESCAPE_F;
309 ++t;
310 break;
311
312 case 'n':
313 *s++ = ESCAPE_N;
314 ++t;
315 break;
316
317 case 'r':
318 *s++ = ESCAPE_R;
319 ++t;
320 break;
321
322 case 't':
323 *s++ = ESCAPE_T;
324 ++t;
325 break;
326
327 case 'v':
328 *s++ = ESCAPE_V;
329 ++t;
330 break;
331
332 case '\\':
333 *s++ = *t++;
334 break;
335
336 case '0': case '1': case '2': case '3':
337 case '4': case '5': case '6': case '7':
338 ch = *t - '0';
339 ++t;
340 if (*t >= '0' && *t <= '7')
341 {
342 ch = (ch << 3) | (*t - '0');
343 ++t;
344 if (*t >= '0' && *t <= '7')
345 {
346 ch = (ch << 3) | (*t - '0');
347 ++t;
348 }
349 }
350 *s++ = ch;
351 break;
352
353 case 'x': case 'X':
354 ++t;
355 ch = 0;
356 /* We only handle single byte chars here. Make sure
357 we finish an escape sequence like "/xB0ABC" after
358 the first two digits. */
359 num_xdigits = 2;
360 while (num_xdigits--)
361 {
362 if (*t >= '0' && *t <= '9')
363 ch = (ch << 4) | (*t - '0');
364 else if (*t >= 'a' && *t <= 'f')
365 ch = (ch << 4) | (*t - 'a' + 10);
366 else if (*t >= 'A' && *t <= 'F')
367 ch = (ch << 4) | (*t - 'A' + 10);
368 else
369 break;
370 ++t;
371 }
372 *s++ = ch;
373 break;
374
375 default:
376 rcparse_warning ("unrecognized escape sequence");
377 *s++ = '\\';
378 *s++ = *t++;
379 break;
380 }
381 }
382 else if (*t != '"')
383 *s++ = *t++;
384 else if (t[1] == '\0')
385 break;
386 else if (t[1] == '"')
387 {
388 *s++ = '"';
389 t += 2;
390 }
391 else
392 {
4a594fce 393 ++t;
a87a00ea
NC
394 if (! ISSPACE (*t))
395 rcparse_warning ("unexpected character after '\"'");
4a594fce
NC
396 while (ISSPACE (*t))
397 {
398 if ((*t) == '\n')
399 ++rc_lineno;
400 ++t;
401 }
402 if (*t == '\0')
403 break;
404 assert (*t == '"');
405 ++t;
406 }
407 }
408
409 *s = '\0';
410
411 *len = s - ret;
412
413 return ret;
414}
415
416/* Allocate a unicode string of a given length. */
417
418static unichar *
419get_unistring (int len)
420{
421 return (unichar *) get_string (len * sizeof (unichar));
422}
423
424/* Handle a quoted unicode string. The quotes are stripped. A pair of quotes
425 in a string are turned into a single quote. Adjacent strings are
426 merged separated by whitespace are merged, as in C. */
427
428static unichar *
429handle_uniquotes (rc_uint_type *len)
430{
431 const char *input = rclex_tok;
432 unichar *ret, *s;
433 const char *t;
434 int ch;
435 int num_xdigits;
436
437 ret = get_unistring (strlen (input) + 1);
438
439 s = ret;
440 t = input;
441 if ((*t == 'L' || *t == 'l') && t[1] == '"')
442 t += 2;
443 else if (*t == '"')
444 ++t;
445 while (*t != '\0')
446 {
447 if (*t == '\\')
448 {
449 ++t;
450 switch (*t)
451 {
452 case '\0':
453 rcparse_warning ("backslash at end of string");
454 break;
455
456 case '\"':
457 rcparse_warning ("use \"\" to put \" in a string");
458 break;
459
460 case 'a':
461 *s++ = ESCAPE_B; /* Strange, but true... */
462 ++t;
463 break;
464
465 case 'b':
466 *s++ = ESCAPE_B;
467 ++t;
468 break;
469
470 case 'f':
471 *s++ = ESCAPE_F;
472 ++t;
473 break;
474
475 case 'n':
476 *s++ = ESCAPE_N;
477 ++t;
478 break;
479
480 case 'r':
481 *s++ = ESCAPE_R;
482 ++t;
483 break;
484
485 case 't':
486 *s++ = ESCAPE_T;
487 ++t;
488 break;
489
490 case 'v':
491 *s++ = ESCAPE_V;
492 ++t;
493 break;
494
495 case '\\':
496 *s++ = (unichar) *t++;
497 break;
498
499 case '0': case '1': case '2': case '3':
500 case '4': case '5': case '6': case '7':
501 ch = *t - '0';
502 ++t;
503 if (*t >= '0' && *t <= '7')
504 {
505 ch = (ch << 3) | (*t - '0');
506 ++t;
507 if (*t >= '0' && *t <= '7')
508 {
509 ch = (ch << 3) | (*t - '0');
510 ++t;
511 }
512 }
513 *s++ = (unichar) ch;
514 break;
515
516 case 'x': case 'X':
517 ++t;
518 ch = 0;
519 /* We only handle two byte chars here. Make sure
520 we finish an escape sequence like "/xB0ABC" after
521 the first two digits. */
522 num_xdigits = 4;
523 while (num_xdigits--)
524 {
525 if (*t >= '0' && *t <= '9')
526 ch = (ch << 4) | (*t - '0');
527 else if (*t >= 'a' && *t <= 'f')
528 ch = (ch << 4) | (*t - 'a' + 10);
529 else if (*t >= 'A' && *t <= 'F')
530 ch = (ch << 4) | (*t - 'A' + 10);
531 else
532 break;
533 ++t;
534 }
535 *s++ = (unichar) ch;
536 break;
537
538 default:
539 rcparse_warning ("unrecognized escape sequence");
540 *s++ = '\\';
541 *s++ = (unichar) *t++;
542 break;
543 }
544 }
545 else if (*t != '"')
546 *s++ = (unichar) *t++;
547 else if (t[1] == '\0')
548 break;
549 else if (t[1] == '"')
550 {
551 *s++ = '"';
552 t += 2;
553 }
554 else
555 {
556 ++t;
557 assert (ISSPACE (*t));
558 while (ISSPACE (*t))
559 {
560 if ((*t) == '\n')
561 ++rc_lineno;
562 ++t;
563 }
564 if (*t == '\0')
565 break;
566 assert (*t == '"');
567 ++t;
568 }
569 }
570
571 *s = '\0';
572
573 *len = s - ret;
574
575 return ret;
576}
577
578/* Discard all the strings we have allocated. The parser calls this
579 when it no longer needs them. */
580
581void
582rcparse_discard_strings (void)
583{
584 struct alloc_string *as;
585
586 as = strings;
587 while (as != NULL)
588 {
589 struct alloc_string *n;
590
591 free (as->s);
592 n = as->next;
593 free (as);
594 as = n;
595 }
596
597 strings = NULL;
598}
599
600/* Enter rcdata mode. */
601void
602rcparse_rcdata (void)
603{
604 rcdata_mode = 1;
605}
606
607/* Go back to normal mode from rcdata mode. */
608void
609rcparse_normal (void)
610{
611 rcdata_mode = 0;
612}
613
614static void
615rclex_tok_add_char (int ch)
616{
617 if (! rclex_tok || rclex_tok_max <= rclex_tok_pos)
618 {
619 char *h = xmalloc (rclex_tok_max + 9);
620
621 if (! h)
622 abort ();
623 if (rclex_tok)
624 {
625 memcpy (h, rclex_tok, rclex_tok_pos + 1);
626 free (rclex_tok);
627 }
628 else
629 rclex_tok_pos = 0;
630 rclex_tok_max += 8;
631 rclex_tok = h;
632 }
633 if (ch != -1)
634 rclex_tok[rclex_tok_pos++] = (char) ch;
635 rclex_tok[rclex_tok_pos] = 0;
636}
637
638static int
639rclex_readch (void)
640{
641 int r = -1;
642
643 if ((r = rclex_lastch) != -1)
644 rclex_lastch = -1;
645 else
646 {
647 char ch;
648 do
649 {
650 if (! cpp_pipe || feof (cpp_pipe)
651 || fread (&ch, 1, 1,cpp_pipe) != 1)
652 break;
653 r = ((int) ch) & 0xff;
654 }
655 while (r == 0 || r == '\r');
656 }
657 rclex_tok_add_char (r);
658 return r;
659}
660
661static int
662rclex_peekch (void)
663{
664 int r;
665
666 if ((r = rclex_lastch) == -1)
667 {
668 if ((r = rclex_readch ()) != -1)
669 {
670 rclex_lastch = r;
671 if (rclex_tok_pos > 0)
672 rclex_tok[--rclex_tok_pos] = 0;
673 }
674 }
675 return r;
676}
677
678static void
679rclex_string (void)
680{
681 int c;
a87a00ea 682
4a594fce
NC
683 while ((c = rclex_peekch ()) != -1)
684 {
685 if (c == '\n')
686 break;
687 if (c == '\\')
688 {
689 rclex_readch ();
690 if ((c = rclex_peekch ()) == -1 || c == '\n')
691 break;
692 rclex_readch ();
693 }
694 else if (rclex_readch () == '"')
695 {
a87a00ea
NC
696 /* PR 6714
697 Skip any whitespace after the end of the double quotes. */
698 do
699 {
700 c = rclex_peekch ();
701 if (ISSPACE (c))
702 rclex_readch ();
703 else
704 c = -1;
705 }
706 while (c != -1);
707
4a594fce
NC
708 if (rclex_peekch () == '"')
709 rclex_readch ();
710 else
711 break;
712 }
713 }
714}
715
716static rc_uint_type
717read_digit (int ch)
718{
719 rc_uint_type base = 10;
720 rc_uint_type ret, val;
721 int warned = 0;
722
723 ret = 0;
724 if (ch == '0')
725 {
726 base = 8;
727 switch (rclex_peekch ())
728 {
729 case 'o': case 'O':
730 rclex_readch ();
731 base = 8;
732 break;
733
734 case 'x': case 'X':
735 rclex_readch ();
736 base = 16;
737 break;
738 }
739 }
740 else
741 ret = (rc_uint_type) (ch - '0');
742 while ((ch = rclex_peekch ()) != -1)
743 {
744 if (ISDIGIT (ch))
745 val = (rc_uint_type) (ch - '0');
746 else if (ch >= 'a' && ch <= 'f')
747 val = (rc_uint_type) ((ch - 'a') + 10);
748 else if (ch >= 'A' && ch <= 'F')
749 val = (rc_uint_type) ((ch - 'A') + 10);
750 else
751 break;
752 rclex_readch ();
753 if (! warned && val >= base)
754 {
755 warned = 1;
756 rcparse_warning ("digit exceeds base");
757 }
758 ret *= base;
759 ret += val;
760 }
761 return ret;
762}
763
764/* yyparser entry method. */
765
766int
767yylex (void)
768{
769 char *s;
770 unichar *us;
771 rc_uint_type length;
772 int ch;
773
774 /* Make sure that rclex_tok is initialized. */
775 if (! rclex_tok)
776 rclex_tok_add_char (-1);
777
778 do
779 {
780 do
781 {
782 /* Clear token. */
783 rclex_tok_pos = 0;
784 rclex_tok[0] = 0;
785
786 if ((ch = rclex_readch ()) == -1)
787 return -1;
788 if (ch == '\n')
789 ++rc_lineno;
790 }
791 while (ch <= 0x20);
792
793 switch (ch)
794 {
795 case '#':
796 while ((ch = rclex_peekch ()) != -1 && ch != '\n')
797 rclex_readch ();
798 cpp_line ();
799 ch = IGNORED_TOKEN;
800 break;
801
802 case '{':
803 ch = IGNORE_CPP (BEG);
804 break;
805
806 case '}':
807 ch = IGNORE_CPP (END);
808 break;
809
810 case '0': case '1': case '2': case '3': case '4':
811 case '5': case '6': case '7': case '8': case '9':
812 yylval.i.val = read_digit (ch);
813 yylval.i.dword = 0;
814 switch (rclex_peekch ())
815 {
816 case 'l': case 'L':
817 rclex_readch ();
818 yylval.i.dword = 1;
819 break;
820 }
821 ch = IGNORE_CPP (NUMBER);
822 break;
823 case '"':
824 rclex_string ();
825 ch = IGNORE_CPP ((! rcdata_mode ? QUOTEDSTRING : SIZEDSTRING));
826 if (ch == IGNORED_TOKEN)
827 break;
828 s = handle_quotes (&length);
829 if (! rcdata_mode)
830 yylval.s = s;
831 else
832 {
833 yylval.ss.length = length;
834 yylval.ss.s = s;
835 }
836 break;
837 case 'L': case 'l':
838 if (rclex_peekch () == '"')
839 {
840 rclex_readch ();
841 rclex_string ();
842 ch = IGNORE_CPP ((! rcdata_mode ? QUOTEDUNISTRING : SIZEDUNISTRING));
843 if (ch == IGNORED_TOKEN)
844 break;
845 us = handle_uniquotes (&length);
846 if (! rcdata_mode)
847 yylval.uni = us;
848 else
849 {
850 yylval.suni.length = length;
851 yylval.suni.s = us;
852 }
853 break;
854 }
855 /* Fall through. */
856 default:
857 if (ISIDST (ch) || ch=='$')
858 {
aeafac0c
KT
859 while ((ch = rclex_peekch ()) != -1
860 && (ISIDNUM (ch) || ch == '$' || ch == '.'
861 || ch == ':' || ch == '\\' || ch == '/'
e36ea2de 862 || ch == '_' || ch == '-')
aeafac0c 863 )
4a594fce
NC
864 rclex_readch ();
865 ch = IGNORE_CPP (rclex_translatekeyword (rclex_tok));
866 if (ch == STRING)
867 {
868 s = get_string (strlen (rclex_tok) + 1);
869 strcpy (s, rclex_tok);
870 yylval.s = s;
871 }
872 else if (ch == BLOCK)
873 {
874 const char *hs = NULL;
875
876 switch (yylex ())
877 {
878 case STRING:
879 case QUOTEDSTRING:
880 hs = yylval.s;
881 break;
882 case SIZEDSTRING:
883 hs = yylval.s = yylval.ss.s;
884 break;
885 }
886 if (! hs)
887 {
888 rcparse_warning ("BLOCK expects a string as argument.");
889 ch = IGNORED_TOKEN;
890 }
891 else if (! strcmp (hs, "StringFileInfo"))
892 ch = BLOCKSTRINGFILEINFO;
893 else if (! strcmp (hs, "VarFileInfo"))
894 ch = BLOCKVARFILEINFO;
895 }
896 break;
897 }
898 ch = IGNORE_CPP (ch);
899 break;
900 }
901 }
902 while (ch == IGNORED_TOKEN);
903
904 return ch;
905}
This page took 0.237102 seconds and 4 git commands to generate.