Add -Wdeclaration-after-statement.
[paraslash.git] / error2.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <assert.h>
4 #include <assert.h>
5 #include <inttypes.h>
6 #include <string.h>
7 #include <stdbool.h>
8 #include <stdbool.h>
9 #include <errno.h>
10 #include <ctype.h>
11
12 // #define DEBUG
13 #ifdef DEBUG
14         #define log(fmt, ...) fprintf(stderr, "%s: " fmt, __FUNCTION__, ## __VA_ARGS__)
15 #else
16         #define log(...) do {;} while (0)
17 #endif /* DEBUG*/
18
19 #define HASH_TABLE_BITS 8
20 #define HASH_TABLE_SIZE (1 << HASH_TABLE_BITS)
21
22 /* number of executables seen so far */
23 static int num_exe;
24
25 struct hash_table_entry {
26         char *key;
27         /* only used for objecs, not for executables */
28         unsigned exe_bitmask;
29 };
30
31 static struct hash_table_entry exe_table[HASH_TABLE_SIZE];
32 static struct hash_table_entry obj_table[HASH_TABLE_SIZE];
33
34 /* no need for anything sophisticated here */
35 static int hash_token(const char *tok)
36 {
37         uint32_t tmp = 31415927;
38         const uint8_t *src = (typeof(src))tok;
39
40         for (; *src; src++) {
41                 tmp *= 27182817;
42                 tmp += *tok;
43         }
44         return tmp % HASH_TABLE_SIZE;
45 }
46
47 static inline bool slot_empty(int idx, struct hash_table_entry *table)
48 {
49         return table[idx].key == NULL;
50 }
51
52 static char *safe_strdup(const char *str)
53 {
54         char *result = strdup(str);
55         if (result)
56                 return result;
57         errno = ENOMEM;
58         perror("strdup");
59         exit(EXIT_FAILURE);
60 }
61
62 static bool lookup(const char *tok, struct hash_table_entry *table, int *idx)
63 {
64         int i, h = hash_token(tok);
65
66         for (i = 0; i < HASH_TABLE_SIZE; i++) {
67                 *idx = (h + i) % HASH_TABLE_SIZE;
68                 if (slot_empty(*idx, table))
69                         return false;
70                 if (!strcmp(table[*idx].key, tok))
71                         return true;
72         }
73         log ("hash table full !?\n");
74         exit(EXIT_FAILURE);
75 }
76
77 static bool insert(const char *tok, struct hash_table_entry *table, int *idx)
78 {
79         if (lookup(tok, table, idx))
80                 return false; /* not inserted */
81         table[*idx].key = safe_strdup(tok);
82         return true;
83 }
84
85 static void process_token(char *tok)
86 {
87         int idx;
88         size_t len = strlen(tok);
89
90         assert(len > 0);
91         if (tok[len - 1] == ':') {
92                 tok[len - 1] = '\0';
93                 if (insert(tok, exe_table, &idx)) { /* new exe */
94                         log("exe #%d: '%s', idx: %d\n", num_exe, tok, idx);
95                         num_exe++;
96                 }
97         } else {
98                 if (num_exe == 0) {
99                         log("invalid input\n");
100                         exit(EXIT_FAILURE);
101                 }
102                 insert(tok, obj_table, &idx);
103                 obj_table[idx].exe_bitmask |= (1 << (num_exe - 1));
104         }
105 }
106
107 static void print_ss_enum(int idx)
108 {
109         char *s = obj_table[idx].key;
110
111         printf("SS_ENUM(");
112         for (; *s; s++)
113                 printf("%c", toupper(*s));
114         printf(");\n");
115 }
116
117 static void dump_bipolar(void)
118 {
119         int i, j;
120
121         for (i = 0; i < HASH_TABLE_SIZE; i++) {
122                 if (slot_empty(i, obj_table))
123                         continue;
124                 printf("#ifdef MAIN_INPUT_FILE_IS_%s\n", obj_table[i].key);
125                 for (j = 0; j < HASH_TABLE_SIZE; j++) {
126                         unsigned mi, mj;
127                         if (slot_empty(j, obj_table))
128                                 continue;
129                         mi = obj_table[i].exe_bitmask;
130                         mj = obj_table[j].exe_bitmask;
131                         if ((mi & mj) == mi)
132                                 print_ss_enum(j);
133                 }
134                 printf("#endif\n");
135         }
136 }
137
138 int main(void)
139 {
140         int ret;
141
142         for (;;) {
143                 char tok[100];
144                 ret = scanf("%96s", tok);
145                 if (ret != 1)
146                         break;
147                 process_token(tok);
148         }
149         dump_bipolar();
150         return 0;
151 }