paraslash 0.5.1
[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 }