blob: 84af5b1c6482e452ea0c43ceb24b822e799179ed [file] [log] [blame]
Dave Barach52642c32016-02-11 19:28:19 -05001/*
2 *------------------------------------------------------------------
3 * Copyright (c) 2006-2016 Cisco and/or its affiliates.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at:
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <stdio.h>
18#include <ctype.h>
19#include <malloc.h>
20#include <time.h>
21#include <string.h>
22#include <unistd.h>
23#include <stdlib.h>
24
25static char *sxerox (char *s);
26
27#define NBUCKETS 97
28
29typedef struct prop_ {
30 struct prop_ *next;
31 char *name;
32 char *value;
33} prop_t;
34
35static prop_t *buckets [NBUCKETS];
36static int hash_shifts[4] = {24, 16, 8, 0};
37
38/*
39 * getprop
40 */
41
42char *getprop (char *name)
43{
44 unsigned char *cp;
45 unsigned long hash=0;
46 prop_t *bp;
47 int i=0;
48
49 for (cp = (unsigned char *) name; *cp; cp++)
50 hash ^= (*cp)<<(hash_shifts[(i++)&0x3]);
51
52 bp = buckets [hash%NBUCKETS];
53
54 while (bp && strcmp(bp->name, name)) {
55 bp = bp->next;
56 }
57
58 if (bp == NULL)
59 return (0);
60 else
61 return (bp->value);
62}
63
64/*
65 * getprop_default
66 */
67
68char *getprop_default (char *name, char *def)
69{
70 char *rv;
71 rv = getprop (name);
72 if (rv)
73 return (rv);
74 else
75 return (def);
76}
77
78/*
79 * addprop
80 */
81
82void addprop (char *name, char *value)
83{
84 unsigned char *cp;
85 unsigned long hash=0;
86 prop_t **bpp;
87 prop_t *bp;
88 int i=0;
89
90 bp = (prop_t *)malloc (sizeof (prop_t));
91
92 bp->next = 0;
93 bp->name = sxerox (name);
94 bp->value = sxerox (value);
95
96 for (cp = (unsigned char *)name; *cp; cp++)
97 hash ^= (*cp)<<(hash_shifts[(i++)&0x3]);
98
99 bpp = &buckets [hash%NBUCKETS];
100
101 if (*bpp == NULL)
102 *bpp = bp;
103 else {
104 bp->next = *bpp;
105 *bpp = bp;
106 }
107}
108
109/*
110 * sxerox
111 */
112
113static char *sxerox (char *s)
114{
115 char *rv = (char *) malloc (strlen (s) + 1);
116 strcpy (rv, s);
117 return rv;
118}
119
120/*
121 * readprops
122 */
123
124#define START 0
125#define READNAME 1
126#define READVALUE 2
127#define C_COMMENT 3
128#define CPP_COMMENT 4
129
130int readprops (char *filename)
131{
132 FILE *ifp;
133 unsigned char c;
134 int state=START;
135 int linenum=1;
136 char namebuf [128];
137 char valbuf [512];
138 int i;
139
140 ifp = fopen (filename, "r");
141
142 if (ifp == NULL)
143 return (-1);
144
145 while (1) {
146
147 readchar:
148 c = getc (ifp);
149
150 again:
151 switch (state) {
152 case START:
153 if (feof (ifp)) {
154 fclose (ifp);
155 return (0);
156 }
157
158 if (c == ' ' || c == '\t')
159 goto readchar;
160
161 if (c == '\n') {
162 linenum++;
163 goto readchar;
164 }
165 if (isalpha (c) || (c == '_')) {
166 state = READNAME;
167 goto again;
168 }
169 if (c == '/') {
170 c = getc (ifp);
171 if (c == '/') {
172 state = CPP_COMMENT;
173 goto readchar;
174 } else if (c == '*') {
175 state = C_COMMENT;
176 goto readchar;
177 } else {
178 fprintf (stderr, "unknown token '/' line %d\n",
179 linenum);
180 exit(1);
181 }
182 }
183 fprintf (stderr, "unknown token '%c' line %d\n",
184 c, linenum);
185 exit (1);
186 break;
187
188 case CPP_COMMENT:
189 while (1) {
190 c = getc (ifp);
191 if (feof (ifp))
192 return (0);
193 if (c == '\n') {
194 linenum++;
195 state = START;
196 goto readchar;
197 }
198 }
199 break;
200
201 case C_COMMENT:
202 while (1) {
203 c = getc (ifp);
204 if (feof (ifp)) {
205 fprintf (stderr, "unterminated comment, line %d\n",
206 linenum);
207 exit (1);
208 }
209 if (c == '*') {
210 staragain:
211 c = getc (ifp);
212 if (c == '/') {
213 state = START;
214 goto readchar;
215 }
216 if (c == '*')
217 goto staragain;
218 }
219 }
220 break;
221
222 case READNAME:
223 i = 0;
224 namebuf[i++] = c;
225 while (1) {
226 c = getc (ifp);
227 if (feof (ifp)) {
228 fprintf (stderr, "EOF while reading a name, line %d\n",
229 linenum);
230 exit (1);
231 }
232 if ((!isalnum (c)) && (c != '_')) {
233 namebuf [i] = 0;
234 state = READVALUE;
235 goto again;
236 }
237 namebuf [i++] = c;
238 }
239 break;
240
241 case READVALUE:
242 i = 0;
243 while ((c == ' ') || (c == '\t') || (c == '=')) {
244 c = getc (ifp);
245 if (feof (ifp)) {
246 fprintf (stderr, "EOF while reading a value, line %d\n",
247 linenum);
248 exit (1);
249 }
250 }
251 goto firsttime;
252 while (1) {
253 c = getc (ifp);
254
255 firsttime:
256 if (c == '\\') {
257 c = getc (ifp);
258 if (feof (ifp)) {
259 fprintf (stderr, "EOF after '\\', line %d\n",
260 linenum);
261 exit (1);
262 }
263 valbuf[i++] = c;
264 continue;
265 }
266 if (c == '\n') {
267 linenum++;
268 while (valbuf [i-1] == ' ' || valbuf[i-1] == '\t')
269 i--;
270 valbuf[i] = 0;
271 addprop (namebuf, valbuf);
272 state = START;
273 goto readchar;
274 }
275 valbuf[i++] = c;
276 }
277
278 }
279 }
280}