filter.c: Add documentation of stat_item_values[].
[paraslash.git] / error2.c
1 /*
2  * Copyright (C) 2013-2014 Andre Noll <maan@tuebingen.mpg.de>
3  *
4  * Licensed under the GPL v2. For licencing details see COPYING.
5  */
6
7 /** \file error2.c Simple program to create error2.h. */
8
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <assert.h>
12 #include <inttypes.h>
13 #include <string.h>
14 #include <stdbool.h>
15 #include <errno.h>
16 #include <ctype.h>
17
18 // #define DEBUG
19 #ifdef DEBUG
20         #define log(fmt, ...) fprintf(stderr, "%s: " fmt, __FUNCTION__, ## __VA_ARGS__)
21 #else
22         #define log(...) do {;} while (0)
23 #endif /* DEBUG*/
24
25 #define HASH_TABLE_BITS 8
26 #define HASH_TABLE_SIZE (1 << HASH_TABLE_BITS)
27
28 /* number of executables seen so far */
29 static int num_exe;
30
31 struct hash_table_entry {
32         char *key;
33         /* only used for objecs, not for executables */
34         unsigned exe_bitmask;
35 };
36
37 static struct hash_table_entry exe_table[HASH_TABLE_SIZE];
38 static struct hash_table_entry obj_table[HASH_TABLE_SIZE];
39
40 /* no need for anything sophisticated here */
41 static int hash_token(const char *tok)
42 {
43         uint32_t tmp = 31415927;
44         const uint8_t *src = (typeof(src))tok;
45
46         for (; *src; src++) {
47                 tmp *= 27182817;
48                 tmp += *tok;
49         }
50         return tmp % HASH_TABLE_SIZE;
51 }
52
53 static inline bool slot_empty(int idx, struct hash_table_entry *table)
54 {
55         return table[idx].key == NULL;
56 }
57
58 static char *safe_strdup(const char *str)
59 {
60         char *result = strdup(str);
61         if (result)
62                 return result;
63         errno = ENOMEM;
64         perror("strdup");
65         exit(EXIT_FAILURE);
66 }
67
68 static bool lookup(const char *tok, struct hash_table_entry *table, int *idx)
69 {
70         int i, h = hash_token(tok);
71
72         for (i = 0; i < HASH_TABLE_SIZE; i++) {
73                 *idx = (h + i) % HASH_TABLE_SIZE;
74                 if (slot_empty(*idx, table))
75                         return false;
76                 if (!strcmp(table[*idx].key, tok))
77                         return true;
78         }
79         log ("hash table full !?\n");
80         exit(EXIT_FAILURE);
81 }
82
83 static bool insert(const char *tok, struct hash_table_entry *table, int *idx)
84 {
85         if (lookup(tok, table, idx))
86                 return false; /* not inserted */
87         table[*idx].key = safe_strdup(tok);
88         return true;
89 }
90
91 static void process_token(char *tok)
92 {
93         int idx;
94         size_t len = strlen(tok);
95
96         assert(len > 0);
97         if (tok[len - 1] == ':') {
98                 tok[len - 1] = '\0';
99                 if (insert(tok, exe_table, &idx)) { /* new exe */
100                         log("exe #%d: '%s', idx: %d\n", num_exe, tok, idx);
101                         num_exe++;
102                 }
103         } else {
104                 if (num_exe == 0) {
105                         log("invalid input\n");
106                         exit(EXIT_FAILURE);
107                 }
108                 insert(tok, obj_table, &idx);
109                 obj_table[idx].exe_bitmask |= (1 << (num_exe - 1));
110         }
111 }
112
113 static void print_ss_enum(int idx)
114 {
115         char *s = obj_table[idx].key;
116
117         printf("SS_ENUM(");
118         for (; *s; s++)
119                 printf("%c", toupper(*s));
120         printf(");\n");
121 }
122
123 static void dump_bipolar(void)
124 {
125         int i, j;
126
127         for (i = 0; i < HASH_TABLE_SIZE; i++) {
128                 if (slot_empty(i, obj_table))
129                         continue;
130                 printf("#ifdef MAIN_INPUT_FILE_IS_%s\n", obj_table[i].key);
131                 for (j = 0; j < HASH_TABLE_SIZE; j++) {
132                         unsigned mi, mj;
133                         if (slot_empty(j, obj_table))
134                                 continue;
135                         mi = obj_table[i].exe_bitmask;
136                         mj = obj_table[j].exe_bitmask;
137                         if ((mi & mj) == mi)
138                                 print_ss_enum(j);
139                 }
140                 printf("#endif\n");
141         }
142 }
143
144 /**
145  * The main function of error2.c.
146  *
147  * The purpose of this program is to create the error2.h file which defines the
148  * enumerations of all error codes which may be used by any given .c file. This
149  * header is included by most .c files of the paraslash suite.
150  *
151  * Since this program is executed on the build system, it must be compiled with
152  * the host compiler.
153  *
154  * \return \p EXIT_SUCCESS or \p EXIT_FAILURE.
155  */
156 int main(void)
157 {
158         int ret;
159
160         for (;;) {
161                 char tok[100];
162                 ret = scanf("%96s", tok);
163                 if (ret != 1)
164                         break;
165                 process_token(tok);
166         }
167         dump_bipolar();
168         return 0;
169 }