1 mike 1.1 /*
2 **==============================================================================
3 **
4 ** Open Management Infrastructure (OMI)
5 **
6 ** Copyright (c) Microsoft Corporation
7 **
8 ** Licensed under the Apache License, Version 2.0 (the "License"); you may not
9 ** use this file except in compliance with the License. You may obtain a copy
10 ** of the License at
11 **
12 ** http://www.apache.org/licenses/LICENSE-2.0
13 **
14 ** THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 ** KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
16 ** WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
17 ** MERCHANTABLITY OR NON-INFRINGEMENT.
18 **
19 ** See the Apache 2 License for the specific language governing permissions
20 ** and limitations under the License.
21 **
22 mike 1.1 **==============================================================================
23 */
24
25 #include <stdio.h>
26 #include <ctype.h>
27 #include <base/strings.h>
28 #include <base/list.h>
29 #include <base/io.h>
30 #include "regfile.h"
31
32 // Parse an identifies of the form "[A-Za-z_][A-Za-z_0-9]*"
33 static int _ParseIdentifier(char** pOut, char** start, char** end)
34 {
35 char* p = *pOut;
36
37 /* Skip leading whitespace */
38 while (isspace((unsigned char)(*p)))
39 p++;
40
41 /* Set start of identifier */
42 *start = p;
43 mike 1.1
44 /* Expect [A-Za-z_] characters */
45 if (!isalpha((unsigned char)(*p)) && *p != '_')
46 return -1;
47
48 /* Skip [A-Za-z_0-9] characters */
49 while (isalnum((unsigned char)(*p)) || *p == '_')
50 p++;
51
52 /* Set end of identifier */
53 *end = p;
54
55 *pOut = p;
56 return 0;
57 }
58
59 // Parase class path of the form "CLASS1:CLASS2:CLASS3"
60 static int _ParseClassPath(char** pOut, char** start, char** end)
61 {
62 char* p = *pOut;
63
64 mike 1.1 /* Skip leading whitespace */
65 while (isspace((unsigned char)(*p)))
66 p++;
67
68 /* Set start of identifier */
69 *start = p;
70
71 /* Expect [A-Za-z_] characters */
72 if (!isalpha((unsigned char)(*p)) && *p != '_')
73 return -1;
74
75 /* Skip [A-Za-z_0-9] characters */
76 while (isalnum((unsigned char)(*p)) || *p == '_' || *p == ':')
77 p++;
78
79 /* Set end of identifier */
80 *end = p;
81
82 *pOut = p;
83 return 0;
84 }
85 mike 1.1
86 static int _ExpectChar(char** pOut, char ch)
87 {
88 char* p = *pOut;
89
90 /* Skip whitespace */
91 while (isspace((unsigned char)(*p)))
92 p++;
93
94 /* Expect character */
95 if (*p != ch)
96 return -1;
97 p++;
98
99 *pOut = p;
100 return 0;
101 }
102
103 // Parse a line of the form 'KEY=VALUE'
104 static int _ParseKeyValueLine(char** pOut, char** keyOut, char** valueOut)
105 {
106 mike 1.1 char* p = *pOut;
107 char* keyEnd;
108
109 /* Parse key */
110 if (_ParseIdentifier(&p, keyOut, &keyEnd) != 0)
111 return-1;
112
113 /* If out of input, error out */
114 if (!*p)
115 return -1;
116
117 /* Skip whitespace */
118 if (_ExpectChar(&p, '=') != 0)
119 return -1;
120
121 /* Null-terminate the key */
122 *keyEnd = '\0';
123
124 /* Skip whitespace */
125 while (isspace((unsigned char)(*p)))
126 p++;
127 mike 1.1
128 /* Set value */
129 *valueOut = p;
130
131 *pOut = p;
132 return 0;
133 }
134
135 static int _ParseClassValue(
136 char** pOut,
137 char** nameOut,
138 char** refName1Out,
139 char** refName2Out)
140 {
141 char* p = *pOut;
142 char* start;
143 char* end;
144
145 /* Expect class name */
146 if (_ParseClassPath(&p, &start, &end) != 0)
147 return -1;
148 mike 1.1
149 /* Skip whitespace */
150 while (isspace((unsigned char)(*p)))
151 p++;
152
153 /* If end of line */
154 if (!*p)
155 {
156 *nameOut = start;
157 *end = '\0';
158 *refName1Out = NULL;
159 *refName2Out = NULL;
160 *pOut = p;
161 return 0;
162 }
163
164 /* Expect '{' character */
165 if (_ExpectChar(&p, '{') != 0)
166 return -1;
167
168 /* Get 'name' */
169 mike 1.1 *nameOut = start;
170 *end = '\0';
171
172 /* Expect reference name */
173 if (_ParseClassPath(&p, &start, &end) != 0)
174 return -1;
175
176 /* Expect ',' character */
177 if (_ExpectChar(&p, ',') != 0)
178 return -1;
179
180 /* Get 'refName1' */
181 *refName1Out = start;
182 *end = '\0';
183
184 /* Expect reference name */
185 if (_ParseClassPath(&p, &start, &end) != 0)
186 return -1;
187
188 /* Expect '}' character */
189 if (_ExpectChar(&p, '}') != 0)
190 mike 1.1 return -1;
191
192 /* Get 'refName1' */
193 *refName2Out = start;
194 *end = '\0';
195
196 *pOut = p;
197 return 0;
198 }
199
200 RegFile* RegFile_New(const char* path)
201 {
202 FILE* is;
203 char buf[1024];
204 int foundLibrary = 0;
205 char* hosting = NULL;
206
207 RegFile* self = 0;
208
209 /* Open the file */
210 is = Fopen(path, "rb");
211 mike 1.1 if (!is)
212 return NULL;
213
214 /* Allocate self structure */
215 self = (RegFile*)calloc(1, sizeof(RegFile));
216 if (!self)
217 {
218 fclose(is);
219 return NULL;
220 }
221
222 /* Read line by line */
223 while (fgets(buf, sizeof(buf), is) != NULL)
224 {
225 char* start = buf;
226 char* p = start;
227 char* key;
228 char* value;
229
230 /* Skip comment lines */
231 if (*p == '#')
232 mike 1.1 continue;
233
234 /* Remove trailing whitespace */
235 {
236 char* end = buf + strlen(buf);
237
238 while (end != start && isspace((unsigned char)end[-1]))
239 *--end = '\0';
240 }
241
242 /* Skip leading whitespace */
243 while (isspace((unsigned char)(*p)))
244 p++;
245
246 /* Skip blank lines */
247 if (*p == '\0')
248 continue;
249
250 /* Look for LIBRARY= */
251 if (_ParseKeyValueLine(&p, &key, &value) != 0)
252 goto failed;
253 mike 1.1
254 if (strcmp(key, "LIBRARY") == 0)
255 {
256 if (foundLibrary)
257 goto failed;
258
259 self->library = Strdup(value);
260
261 if (!self->library)
262 goto failed;
263
264 foundLibrary = 1;
265 }
266 else if (strcmp(key, "HOSTING") == 0)
267 {
268 if (hosting)
269 free(hosting);
270
271 hosting = Strdup(value);
272 }
273 else if (strcmp(key, "CLASS") == 0)
274 mike 1.1 {
275 char* name;
276 char* refName1;
277 char* refName2;
278 RegClass* rc;
279
280 if (_ParseClassValue(&p, &name, &refName1, &refName2) != 0)
281 goto failed;
282
283 rc = (RegClass*)calloc(1, sizeof(RegClass));
284 if (!rc)
285 goto failed;
286
287 List_Append(
288 (ListElem**)&self->classesHead,
289 (ListElem**)&self->classesTail,
290 (ListElem*)rc);
291
292 rc->name = Strdup(name);
293 if (!rc->name)
294 goto failed;
295 mike 1.1
296 if (refName1)
297 {
298 rc->refName1 = Strdup(refName1);
299 if (!rc->refName1)
300 goto failed;
301 }
302
303 if (refName2)
304 {
305 rc->refName2 = Strdup(refName2);
306 if (!rc->refName2)
307 goto failed;
308 }
309
310 if (hosting)
311 rc->hosting = Strdup(hosting);
312 }
313 }
314
315 if (hosting)
316 mike 1.1 free(hosting);
317
318 fclose(is);
319
320 return self;
321
322 failed:
323 if (self)
324 RegFile_Delete(self);
325
326 if (is)
327 fclose(is);
328
329 return NULL;
330 }
331
332 void RegFile_Delete(RegFile* self)
333 {
334 RegClass* rc;
335 RegClass* next;
336
337 mike 1.1 if (!self)
338 return;
339
340 if (self->library)
341 free(self->library);
342
343 for (rc = self->classesHead; rc; rc = next)
344 {
345 if (rc->name)
346 free(rc->name);
347
348 if (rc->refName1)
349 free(rc->refName1);
350
351 if (rc->refName2)
352 free(rc->refName2);
353
354 if (rc->hosting)
355 free(rc->hosting);
356
357 next = rc->next;
358 mike 1.1 free(rc);
359 }
360
361 free(self);
362 }
363
364 void RegFile_Print(RegFile* self, FILE* os)
365 {
366 RegClass* rc;
367
368 fprintf(os, "LIBRARY=%s\n", self->library);
369
370 for (rc = self->classesHead; rc; rc = rc->next)
371 {
372 fprintf(os, "CLASS=%s", rc->name);
373
374 if (rc->refName1 && rc->refName2)
375 {
376 fprintf(os, "{");
377 fprintf(os, "%s", rc->refName1);
378 fprintf(os, ",");
379 mike 1.1 fprintf(os, "%s", rc->refName2);
380 fprintf(os, "}");
381 }
382
383 fprintf(os, "\n");
384 }
385 }
|