testsuite: rebuild all the 64-be|le data files
[mit.git] / util.c
blob4df11e09ba24f7892b7b917aba645bdce3816ab2
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <stdint.h>
4 #include <string.h>
5 #include <errno.h>
6 #include <elf.h>
7 #include "logging.h"
8 #include "util.h"
11 * Read one logical line from a configuration file.
13 * Line endings may be escaped with backslashes, to form one logical line from
14 * several physical lines. No end of line character(s) are included in the
15 * result.
17 * If linenum is not NULL, it is incremented by the number of physical lines
18 * which have been read.
20 char *getline_wrapped(FILE *file, unsigned int *linenum)
22 int size = 256;
23 int i = 0;
24 char *buf = NOFAIL(malloc(size));
25 for(;;) {
26 int ch = getc_unlocked(file);
28 switch(ch) {
29 case EOF:
30 if (i == 0) {
31 free(buf);
32 return NULL;
34 /* else fall through */
36 case '\n':
37 if (linenum)
38 (*linenum)++;
39 if (i == size)
40 buf = NOFAIL(realloc(buf, size + 1));
41 buf[i] = '\0';
42 return buf;
44 case '\\':
45 ch = getc_unlocked(file);
47 if (ch == '\n') {
48 if (linenum)
49 (*linenum)++;
50 continue;
52 /* else fall through */
54 default:
55 buf[i++] = ch;
57 if (i == size) {
58 size *= 2;
59 buf = NOFAIL(realloc(buf, size));
66 * Convert filename to the module name. Works if filename == modname, too.
68 void filename2modname(char *modname, const char *filename)
70 const char *afterslash;
71 unsigned int i;
73 afterslash = my_basename(filename);
75 /* Convert to underscores, stop at first . */
76 for (i = 0; afterslash[i] && afterslash[i] != '.'; i++) {
77 if (afterslash[i] == '-')
78 modname[i] = '_';
79 else
80 modname[i] = afterslash[i];
82 modname[i] = '\0';
86 * Replace dashes with underscores.
87 * Dashes inside character range patterns (e.g. [0-9]) are left unchanged.
89 char *underscores(char *string)
91 unsigned int i;
93 if (!string)
94 return NULL;
96 for (i = 0; string[i]; i++) {
97 switch (string[i]) {
98 case '-':
99 string[i] = '_';
100 break;
102 case ']':
103 warn("Unmatched bracket in %s\n", string);
104 break;
106 case '[':
107 i += strcspn(&string[i], "]");
108 if (!string[i])
109 warn("Unmatched bracket in %s\n", string);
110 break;
113 return string;
117 * strtbl_add - add a string to a string table.
119 * @str: string to add
120 * @tbl: current string table. NULL = allocate new table
122 * Allocates an array of pointers to strings.
123 * The strings themselves are not actually kept in the table.
125 * Returns reallocated and updated string table. NULL = out of memory.
127 * Implementation note: The string table is designed to be lighter-weight
128 * and faster than a more conventional linked list that stores the strings
129 * in the list elements, as it does far fewer malloc/realloc calls
130 * and avoids copying entirely.
132 struct string_table *strtbl_add(const char *str, struct string_table *tbl)
134 if (tbl == NULL) {
135 const char max = 100;
136 tbl = malloc(sizeof(*tbl) + sizeof(char *) * max);
137 if (!tbl)
138 return NULL;
139 tbl->max = max;
140 tbl->cnt = 0;
142 if (tbl->cnt >= tbl->max) {
143 tbl->max *= 2;
144 tbl = realloc(tbl, sizeof(*tbl) + sizeof(char *) * tbl->max);
145 if (!tbl)
146 return NULL;
148 tbl->str[tbl->cnt] = str;
149 tbl->cnt += 1;
151 return tbl;
155 * strtbl_free - string table destructor
157 void strtbl_free(struct string_table *tbl)
159 free(tbl);
163 * Get the basename in a pathname.
164 * Unlike the standard implementation, this does not copy the string.
166 char *my_basename(const char *path)
168 const char *base = strrchr(path, '/');
169 if (base)
170 return (char *) base + 1;
171 return (char *) path;
175 * Find the next string in an ELF section.
177 const char *next_string(const char *string, unsigned long *secsize)
179 /* Skip non-zero chars */
180 while (string[0]) {
181 string++;
182 if ((*secsize)-- <= 1)
183 return NULL;
186 /* Skip any zero padding. */
187 while (!string[0]) {
188 string++;
189 if ((*secsize)-- <= 1)
190 return NULL;
192 return string;
196 * Get CPU endianness. 0 = unknown, 1 = ELFDATA2LSB = little, 2 = ELFDATA2MSB = big
198 int __attribute__ ((pure)) native_endianness()
200 /* Encoding the endianness enums in a string and then reading that
201 * string as a 32-bit int, returns the correct endianness automagically.
203 return (char) *((uint32_t*)("\1\0\0\2"));