1 #include <stdlib.h>
2 #include <stdio.h>
3 #include <assert.h>
4 #include <string.h>
5 #include <ctype.h>
6
7 #include "support.h"
8 #include "ossupport.h"
9
10 /* Zero terminate the current word. Returns -1 is *s == 0 or the next word
11 does not exist. Otherwise returns offset to the beginning of next word. */
skip_and_terminate_word(char * s,int i)12 int skip_and_terminate_word(char *s, int i)
13 {
14 i = skipnws(s, i);
15 if (i < 0)
16 return -1;
17
18 /* Zero terminate word */
19 s[i] = 0;
20
21 i = skipws(s, i + 1);
22 if (i < 0)
23 return -1;
24
25 return i;
26 }
27
xbasename(const char * s)28 char *xbasename(const char *s)
29 {
30 char *t = strrchr(s, (int) '/');
31 if (t == NULL) {
32 t = (char *) s;
33 } else {
34 t++;
35 }
36 return t;
37 }
38
39 /*
40 * Split a string into 2 whitespace separated fields returned in "key" and
41 * "value". If more than 2 fields are found, they are cut off by zero
42 * terminating "key" and "value" inside the string. If "value" is not found,
43 * *value is set to NULL. If "key" is not found, *key is set to NULL.
44 * If something is found, both *key and *value become pointers inside the
45 * string s.
46 *
47 * Return values:
48 * - 0 if neither "key" nor "value" is found
49 * - 1 if only "key" is found
50 * - 2 if both "key" and "value" are found
51 */
get_two_ws_separated_fields(char ** key,char ** value,char * s)52 int get_two_ws_separated_fields(char **key, char **value, char *s)
53 {
54 int i;
55
56 *key = NULL;
57 *value = NULL;
58
59 i = skipws(s, 0); /* Skip initial whitespace */
60
61 if (i < 0)
62 return 0; /* We got nothing */
63
64 *key = s + i;
65
66 i = skip_and_terminate_word(s, i);
67
68 if (i < 0)
69 return 1; /* We got a "key", but not a "value" */
70
71 *value = s + i;
72
73 skip_and_terminate_word(s, i);
74
75 return 2; /* We got both a "key" and a "value" */
76 }
77
78 /*
79 * Skip whitespace characters in string starting from offset i. Returns offset
80 * j >= i as the next non-whitespace character offset, or -1 if non-whitespace
81 * are not found.
82 */
skipws(const char * s,int i)83 int skipws(const char *s, int i)
84 {
85 while (isspace(s[i]))
86 i++;
87
88 if (s[i] == 0)
89 return -1;
90
91 return i;
92 }
93
94 /*
95 * Skip non-whitespace characters in string starting from offset i. Returns
96 * offset j >= i as the next whitespace character offset, or -1 if no
97 * whitespace if found.
98 */
skipnws(const char * s,int i)99 int skipnws(const char *s, int i)
100 {
101 while (!isspace(s[i]) && s[i] != 0)
102 i++;
103
104 if (s[i] == 0)
105 return -1;
106
107 return i;
108 }
109
110
111 /* Split line with respect to white space. */
read_and_split_lines(size_t * nitems,size_t * lineno,FILE * f,const char * delim)112 char **read_and_split_lines(size_t *nitems, size_t *lineno, FILE *f,
113 const char *delim)
114 {
115 char line[UADE_LINESIZE], templine[UADE_LINESIZE];
116 char **items = NULL;
117 size_t pos;
118 char *sp, *s;
119
120 *nitems = 0;
121
122 while (xfgets(line, sizeof line, f) != NULL) {
123
124 if (lineno != NULL)
125 (*lineno)++;
126
127 /* Skip, if a comment line */
128 if (line[0] == '#')
129 continue;
130
131 /* strsep() modifies line that it touches, so we make a copy
132 of it, and then count the number of items on the line */
133 strlcpy(templine, line, sizeof(templine));
134 sp = templine;
135 while ((s = strsep(&sp, delim)) != NULL) {
136 if (*s == 0)
137 continue;
138 (*nitems)++;
139 }
140
141 if (*nitems > 0)
142 break;
143 }
144
145 if (*nitems == 0)
146 return NULL;
147
148 if ((items = malloc(sizeof(items[0]) * (*nitems + 1))) == NULL)
149 uadeerror("No memory for nws items.\n");
150
151 sp = line;
152 pos = 0;
153 while ((s = strsep(&sp, delim)) != NULL) {
154 if (*s == 0)
155 continue;
156
157 if ((items[pos] = strdup(s)) == NULL)
158 uadeerror("No memory for an nws item.\n");
159
160 pos++;
161 }
162 items[pos] = NULL;
163 assert(pos == *nitems);
164
165 return items;
166 }
167
168
xfgets(char * s,int size,FILE * stream)169 char *xfgets(char *s, int size, FILE *stream)
170 {
171 char *ret;
172
173 while (1) {
174 ret = fgets(s, size, stream);
175 if (ret != NULL)
176 break;
177
178 if (feof(stream))
179 break;
180 }
181
182 return ret;
183 }
184