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