13ae02089SMasatake YAMATO /*
23ae02089SMasatake YAMATO * windres.c
33ae02089SMasatake YAMATO *
43ae02089SMasatake YAMATO * Copyright (c) 2013, Frank Fesevur <ffes(at)users.sourceforge.net>
53ae02089SMasatake YAMATO *
63ae02089SMasatake YAMATO * This source code is released for free distribution under the terms of the
70ce38835Sviccuad * GNU General Public License version 2 or (at your option) any later version.
83ae02089SMasatake YAMATO *
93ae02089SMasatake YAMATO * This module contains functions for generating tags for Windows Resource files.
103ae02089SMasatake YAMATO */
113ae02089SMasatake YAMATO
123ae02089SMasatake YAMATO #include "general.h"
133ae02089SMasatake YAMATO
143ae02089SMasatake YAMATO #include <string.h>
153ae02089SMasatake YAMATO #include <ctype.h>
163ae02089SMasatake YAMATO
173ae02089SMasatake YAMATO #include "parse.h"
183ae02089SMasatake YAMATO #include "read.h"
193db72c21SMasatake YAMATO #include "routines.h"
203ae02089SMasatake YAMATO
213ae02089SMasatake YAMATO static int _blockDepth = 0;
223ae02089SMasatake YAMATO
233ae02089SMasatake YAMATO typedef enum _WindResKinds
243ae02089SMasatake YAMATO {
253ae02089SMasatake YAMATO K_NONE = -1,
263ae02089SMasatake YAMATO K_DIALOG,
273ae02089SMasatake YAMATO K_MENU,
283ae02089SMasatake YAMATO K_ICON,
293ae02089SMasatake YAMATO K_BITMAP,
303ae02089SMasatake YAMATO K_CURSOR,
313ae02089SMasatake YAMATO K_FONT,
323ae02089SMasatake YAMATO K_VERSION,
333ae02089SMasatake YAMATO K_ACCELERATORS
343ae02089SMasatake YAMATO } ResKind;
353ae02089SMasatake YAMATO
36e112e8abSMasatake YAMATO static kindDefinition ResKinds [] = {
37ce990805SThomas Braun { true, 'd', "dialog", "dialogs" },
38ce990805SThomas Braun { true, 'm', "menu", "menus" },
39ce990805SThomas Braun { true, 'i', "icon", "icons" },
40ce990805SThomas Braun { true, 'b', "bitmap", "bitmaps" },
41ce990805SThomas Braun { true, 'c', "cursor", "cursors" },
42ce990805SThomas Braun { true, 'f', "font", "fonts" },
43ce990805SThomas Braun { true, 'v', "version", "versions" },
44ce990805SThomas Braun { true, 'a', "accelerators", "accelerators" }
453ae02089SMasatake YAMATO };
463ae02089SMasatake YAMATO
473ae02089SMasatake YAMATO typedef enum _WindResParserState
483ae02089SMasatake YAMATO {
493ae02089SMasatake YAMATO P_STATE_NONE,
503ae02089SMasatake YAMATO P_STATE_IN_COMMENT,
513ae02089SMasatake YAMATO P_STATE_IN_STATEMENTS, /* Between first line of item and BEGIN/{ */
523ae02089SMasatake YAMATO P_STATE_IN_BLOCK, /* In a BEGIN/END or {/} block */
533ae02089SMasatake YAMATO P_STATE_AT_END
543ae02089SMasatake YAMATO } ResParserState;
553ae02089SMasatake YAMATO
makeResTag(vString * name,ResKind kind)563ae02089SMasatake YAMATO static void makeResTag(vString *name, ResKind kind)
573ae02089SMasatake YAMATO {
583ae02089SMasatake YAMATO vStringStripTrailing(name);
59*16a2541cSMasatake YAMATO makeSimpleTag(name, kind);
603ae02089SMasatake YAMATO vStringClear(name);
613ae02089SMasatake YAMATO }
623ae02089SMasatake YAMATO
parseResDefinition(const unsigned char * line)633ae02089SMasatake YAMATO static ResParserState parseResDefinition(const unsigned char *line)
643ae02089SMasatake YAMATO {
653ae02089SMasatake YAMATO ResParserState state = P_STATE_NONE;
663ae02089SMasatake YAMATO vString *name, *type;
673ae02089SMasatake YAMATO
683ae02089SMasatake YAMATO name = vStringNew();
693ae02089SMasatake YAMATO while (*line && !isspace((int) *line))
703ae02089SMasatake YAMATO {
713ae02089SMasatake YAMATO vStringPut(name, (int) *line);
723ae02089SMasatake YAMATO line++;
733ae02089SMasatake YAMATO }
743ae02089SMasatake YAMATO
753ae02089SMasatake YAMATO while (*line && isspace((int) *line))
763ae02089SMasatake YAMATO line++;
773ae02089SMasatake YAMATO
783ae02089SMasatake YAMATO type = vStringNew();
793ae02089SMasatake YAMATO while (*line && !isspace((int) *line))
803ae02089SMasatake YAMATO {
813ae02089SMasatake YAMATO vStringPut(type, (int) *line);
823ae02089SMasatake YAMATO line++;
833ae02089SMasatake YAMATO }
843ae02089SMasatake YAMATO
853ae02089SMasatake YAMATO if (strcmp(vStringValue(type), "DIALOG") == 0 || strcmp(vStringValue(type), "DIALOGEX") == 0)
863ae02089SMasatake YAMATO {
873ae02089SMasatake YAMATO makeResTag(name, K_DIALOG);
883ae02089SMasatake YAMATO state = P_STATE_IN_STATEMENTS;
893ae02089SMasatake YAMATO }
903ae02089SMasatake YAMATO else if (strcmp(vStringValue(type), "MENU") == 0 || strcmp(vStringValue(type), "MENUEX") == 0)
913ae02089SMasatake YAMATO {
923ae02089SMasatake YAMATO makeResTag(name, K_MENU);
933ae02089SMasatake YAMATO state = P_STATE_IN_STATEMENTS;
943ae02089SMasatake YAMATO }
953ae02089SMasatake YAMATO else if (strcmp(vStringValue(type), "VERSIONINFO") == 0)
963ae02089SMasatake YAMATO {
973ae02089SMasatake YAMATO makeResTag(name, K_VERSION);
983ae02089SMasatake YAMATO state = P_STATE_IN_STATEMENTS;
993ae02089SMasatake YAMATO }
1003ae02089SMasatake YAMATO else if (strcmp(vStringValue(type), "ACCELERATORS") == 0)
1013ae02089SMasatake YAMATO {
1023ae02089SMasatake YAMATO makeResTag(name, K_ACCELERATORS);
1033ae02089SMasatake YAMATO state = P_STATE_IN_STATEMENTS;
1043ae02089SMasatake YAMATO }
1053ae02089SMasatake YAMATO else if (strcmp(vStringValue(type), "ICON") == 0)
1063ae02089SMasatake YAMATO {
1073ae02089SMasatake YAMATO makeResTag(name, K_ICON);
1083ae02089SMasatake YAMATO state = P_STATE_NONE;
1093ae02089SMasatake YAMATO }
1103ae02089SMasatake YAMATO else if (strcmp(vStringValue(type), "CURSOR") == 0)
1113ae02089SMasatake YAMATO {
1123ae02089SMasatake YAMATO makeResTag(name, K_CURSOR);
1133ae02089SMasatake YAMATO state = P_STATE_NONE;
1143ae02089SMasatake YAMATO }
1153ae02089SMasatake YAMATO else if (strcmp(vStringValue(type), "BITMAP") == 0)
1163ae02089SMasatake YAMATO {
1173ae02089SMasatake YAMATO makeResTag(name, K_BITMAP);
1183ae02089SMasatake YAMATO state = P_STATE_NONE;
1193ae02089SMasatake YAMATO }
1203ae02089SMasatake YAMATO else if (strcmp(vStringValue(type), "FONT") == 0)
1213ae02089SMasatake YAMATO {
1223ae02089SMasatake YAMATO makeResTag(name, K_FONT);
1233ae02089SMasatake YAMATO state = P_STATE_NONE;
1243ae02089SMasatake YAMATO }
1253ae02089SMasatake YAMATO
1263ae02089SMasatake YAMATO vStringDelete(name);
1273ae02089SMasatake YAMATO vStringDelete(type);
1283ae02089SMasatake YAMATO
1293ae02089SMasatake YAMATO return state;
1303ae02089SMasatake YAMATO }
1313ae02089SMasatake YAMATO
parseResLine(const unsigned char * line,ResParserState state)1323ae02089SMasatake YAMATO static ResParserState parseResLine(const unsigned char *line, ResParserState state)
1333ae02089SMasatake YAMATO {
1341b312fe7SMasatake YAMATO while (*line != '\0') /* readLineFromInputFile returns NULL terminated strings */
1353ae02089SMasatake YAMATO {
1363ae02089SMasatake YAMATO while (isspace((int) *line))
1373ae02089SMasatake YAMATO line++;
1383ae02089SMasatake YAMATO
1393ae02089SMasatake YAMATO switch (state)
1403ae02089SMasatake YAMATO {
1413ae02089SMasatake YAMATO case P_STATE_NONE:
1423ae02089SMasatake YAMATO {
1433ae02089SMasatake YAMATO /* C-styled # line (#include, #define, etc), ignore rest of line */
1443ae02089SMasatake YAMATO if (*line == '#')
1453ae02089SMasatake YAMATO {
1463ae02089SMasatake YAMATO return P_STATE_NONE;
1473ae02089SMasatake YAMATO }
1483ae02089SMasatake YAMATO /* single line comment, ignore rest of line */
1493ae02089SMasatake YAMATO else if (*line == '/' && line[1] == '/')
1503ae02089SMasatake YAMATO {
1513ae02089SMasatake YAMATO return P_STATE_NONE;
1523ae02089SMasatake YAMATO }
1533ae02089SMasatake YAMATO /* multi-line comment */
1543ae02089SMasatake YAMATO else if( *line == '/' && line[1] == '*' )
1553ae02089SMasatake YAMATO {
1563ae02089SMasatake YAMATO state = P_STATE_IN_COMMENT;
1573ae02089SMasatake YAMATO }
1583ae02089SMasatake YAMATO else if (isalnum((int) *line))
1593ae02089SMasatake YAMATO {
1603ae02089SMasatake YAMATO return parseResDefinition(line);
1613ae02089SMasatake YAMATO }
1623ae02089SMasatake YAMATO break;
1633ae02089SMasatake YAMATO }
1643ae02089SMasatake YAMATO case P_STATE_IN_COMMENT:
1653ae02089SMasatake YAMATO {
1663ae02089SMasatake YAMATO if (*line == '*' && line[1] == '/')
1673ae02089SMasatake YAMATO state = P_STATE_NONE;
1683ae02089SMasatake YAMATO break;
1693ae02089SMasatake YAMATO }
1703ae02089SMasatake YAMATO case P_STATE_IN_STATEMENTS:
1713ae02089SMasatake YAMATO {
1723ae02089SMasatake YAMATO /* First BEGIN block */
1733ae02089SMasatake YAMATO if (*line == '{' || strcmp((const char *) line, "BEGIN") == 0)
1743ae02089SMasatake YAMATO {
1753ae02089SMasatake YAMATO _blockDepth = 1;
1763ae02089SMasatake YAMATO return P_STATE_IN_BLOCK;
1773ae02089SMasatake YAMATO }
1783ae02089SMasatake YAMATO break;
1793ae02089SMasatake YAMATO }
1803ae02089SMasatake YAMATO case P_STATE_IN_BLOCK:
1813ae02089SMasatake YAMATO {
1823ae02089SMasatake YAMATO /* Nested BEGIN blocks? */
1833ae02089SMasatake YAMATO if (*line == '{' || strcmp((const char *) line, "BEGIN") == 0)
1843ae02089SMasatake YAMATO {
1853ae02089SMasatake YAMATO _blockDepth++;
1863ae02089SMasatake YAMATO }
1873ae02089SMasatake YAMATO else if (*line == '}' || strcmp((const char *) line, "END") == 0)
1883ae02089SMasatake YAMATO {
1893ae02089SMasatake YAMATO if (_blockDepth == 1)
1903ae02089SMasatake YAMATO return P_STATE_NONE;
1913ae02089SMasatake YAMATO else
1923ae02089SMasatake YAMATO _blockDepth--;
1933ae02089SMasatake YAMATO }
1943ae02089SMasatake YAMATO break;
1953ae02089SMasatake YAMATO }
1963ae02089SMasatake YAMATO case P_STATE_AT_END:
1973ae02089SMasatake YAMATO {
1983ae02089SMasatake YAMATO return state;
1993ae02089SMasatake YAMATO }
2003ae02089SMasatake YAMATO }
2013ae02089SMasatake YAMATO if (line == NULL)
2023ae02089SMasatake YAMATO return P_STATE_AT_END;
2033ae02089SMasatake YAMATO line++;
2043ae02089SMasatake YAMATO }
2053ae02089SMasatake YAMATO
2063ae02089SMasatake YAMATO return state;
2073ae02089SMasatake YAMATO }
2083ae02089SMasatake YAMATO
findResTags(void)2093ae02089SMasatake YAMATO static void findResTags(void)
2103ae02089SMasatake YAMATO {
2113ae02089SMasatake YAMATO const unsigned char *line;
2123ae02089SMasatake YAMATO ResParserState state = P_STATE_NONE;
2133ae02089SMasatake YAMATO _blockDepth = 0;
2143ae02089SMasatake YAMATO
2151b312fe7SMasatake YAMATO while ((line = readLineFromInputFile()) != NULL)
2163ae02089SMasatake YAMATO {
2173ae02089SMasatake YAMATO state = parseResLine(line, state);
2183ae02089SMasatake YAMATO if (state == P_STATE_AT_END)
2193ae02089SMasatake YAMATO return;
2203ae02089SMasatake YAMATO }
2213ae02089SMasatake YAMATO }
2223ae02089SMasatake YAMATO
2233ae02089SMasatake YAMATO /* parser definition */
WindResParser(void)2243ae02089SMasatake YAMATO extern parserDefinition* WindResParser(void)
2253ae02089SMasatake YAMATO {
2263ae02089SMasatake YAMATO static const char *const extensions [] = { "rc", NULL };
2273ae02089SMasatake YAMATO parserDefinition* def = parserNew("WindRes");
22809ae690fSMasatake YAMATO def->kindTable = ResKinds;
2293db72c21SMasatake YAMATO def->kindCount = ARRAY_SIZE(ResKinds);
2303ae02089SMasatake YAMATO def->extensions = extensions;
2313ae02089SMasatake YAMATO def->parser = findResTags;
2323ae02089SMasatake YAMATO return def;
2333ae02089SMasatake YAMATO }
234