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