84af5b1c6482e452ea0c43ceb24b822e799179ed
[vpp.git] / perftool / props.c
1 /* 
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
25 static char *sxerox (char *s);
26
27 #define NBUCKETS 97
28
29 typedef struct prop_ {
30     struct prop_ *next;
31     char *name;
32     char *value;
33 } prop_t;
34
35 static prop_t *buckets [NBUCKETS];
36 static int hash_shifts[4] = {24, 16, 8, 0};
37
38 /*
39  * getprop 
40  */
41
42 char *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
68 char *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
82 void 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
113 static 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
130 int 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 }