]> git.proxmox.com Git - mirror_edk2.git/blame - Tools/Source/TianoTools/FlashMap/Symbols.c
Applied BSD license to the source files
[mirror_edk2.git] / Tools / Source / TianoTools / FlashMap / Symbols.c
CommitLineData
d25c4bf0 1/*++\r
2\r
b84b42fc 3Copyright (c) 2004-2006 Intel Corporation. All rights reserved\r
4This program and the accompanying materials are licensed and made available \r
5under the terms and conditions of the BSD License which accompanies this \r
6distribution. The full text of the license may be found at\r
7http://opensource.org/licenses/bsd-license.php\r
8\r
9THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
10WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
d25c4bf0 11\r
12Module Name:\r
13\r
14 Symbol.c\r
15\r
16Abstract:\r
17\r
18 Class-like implementation for a symbol table.\r
19\r
20--*/\r
21\r
22// GC_TODO: fix comment to set correct module name: Symbols.c\r
23#include <stdio.h>\r
24#include <string.h>\r
25#include <stdlib.h>\r
26//\r
27// for isspace()\r
28//\r
29#include <ctype.h>\r
30\r
ce53a8c3 31#include <Common/UefiBaseTypes.h>\r
51d48c26 32\r
ce53a8c3 33#include "CommonLib.h"\r
d25c4bf0 34#include "EfiUtilityMsgs.h"\r
35#include "Symbols.h"\r
36\r
37#define MAX_LINE_LEN 512\r
38\r
39//\r
40// Linked list to keep track of all symbols\r
41//\r
42typedef struct _SYMBOL {\r
43 struct _SYMBOL *Next;\r
44 int Type;\r
45 char *Name;\r
46 char *Value;\r
47} SYMBOL;\r
48\r
49static\r
50SYMBOL *\r
51FreeSymbols (\r
52 SYMBOL *Syms\r
53 );\r
54\r
55static\r
56int\r
57ExpandMacros (\r
58 char *SourceLine,\r
59 char *DestLine,\r
60 int LineLen\r
61 );\r
62\r
63static SYMBOL *mSymbolTable = NULL;\r
64\r
65void\r
66SymbolsConstructor (\r
67 VOID\r
68 )\r
69/*++\r
70\r
71Routine Description:\r
72\r
73 GC_TODO: Add function description\r
74\r
75Arguments:\r
76\r
77 None\r
78\r
79Returns:\r
80\r
81 GC_TODO: add return values\r
82\r
83--*/\r
84{\r
85 SymbolsDestructor ();\r
86}\r
87\r
88void\r
89SymbolsDestructor (\r
90 VOID\r
91 )\r
92/*++\r
93\r
94Routine Description:\r
95\r
96 GC_TODO: Add function description\r
97\r
98Arguments:\r
99\r
100 None\r
101\r
102Returns:\r
103\r
104 GC_TODO: add return values\r
105\r
106--*/\r
107{\r
108 mSymbolTable = FreeSymbols (mSymbolTable);\r
109}\r
110\r
111char *\r
112GetSymbolValue (\r
113 char *SymbolName\r
114 )\r
115/*++\r
116\r
117Routine Description:\r
118 \r
119 Look up a symbol in our symbol table.\r
120\r
121Arguments:\r
122\r
123 SymbolName\r
124\r
125Returns:\r
126\r
127 Pointer to the value of the symbol if found\r
128 NULL if the symbol is not found\r
129\r
130--*/\r
131// GC_TODO: SymbolName - add argument and description to function comment\r
132{\r
133 SYMBOL *Symbol;\r
134 //\r
135 // Walk the symbol table\r
136 //\r
137 Symbol = mSymbolTable;\r
138 while (Symbol) {\r
139 if (stricmp (SymbolName, Symbol->Name) == 0) {\r
140 return Symbol->Value;\r
141 }\r
142\r
143 Symbol = Symbol->Next;\r
144 }\r
145\r
146 return NULL;\r
147}\r
148\r
149int\r
150SymbolAdd (\r
151 char *Name,\r
152 char *Value,\r
153 int Mode\r
154 )\r
155/*++\r
156\r
157Routine Description:\r
158 \r
159 Add a symbol name/value to the symbol table\r
160\r
161Arguments:\r
162\r
163 Name - name of symbol to add\r
164 Value - value of symbol to add\r
165 Mode - currrently unused\r
166\r
167Returns:\r
168\r
169 Length of symbol added.\r
170\r
171Notes:\r
172 If Value == NULL, then this routine will assume that the Name field\r
173 looks something like "MySymName = MySymValue", and will try to parse\r
174 it that way and add the symbol name/pair from the string.\r
175\r
176--*/\r
177{\r
178 SYMBOL *Symbol;\r
179\r
180 SYMBOL *NewSymbol;\r
181 int Len;\r
182 char *Start;\r
183 char *Cptr;\r
184 char CSave;\r
185 char *SaveCptr;\r
186\r
187 Len = 0;\r
188 SaveCptr = NULL;\r
189 CSave = 0;\r
190 //\r
191 // If value pointer is null, then they passed us a line something like:\r
192 // varname = value, or simply var =\r
193 //\r
194 if (Value == NULL) {\r
195 Start = Name;\r
196 while (*Name && isspace (*Name)) {\r
197 Name++;\r
198 }\r
199\r
200 if (Name == NULL) {\r
201 return -1;\r
202 }\r
203 //\r
204 // Find the end of the name. Either space or a '='.\r
205 //\r
206 for (Value = Name; *Value && !isspace (*Value) && (*Value != '='); Value++)\r
207 ;\r
208 if (Value == NULL) {\r
209 return -1;\r
210 }\r
211 //\r
212 // Look for the '='\r
213 //\r
214 Cptr = Value;\r
215 while (*Value && (*Value != '=')) {\r
216 Value++;\r
217 }\r
218\r
219 if (Value == NULL) {\r
220 return -1;\r
221 }\r
222 //\r
223 // Now truncate the name\r
224 //\r
225 *Cptr = 0;\r
226 //\r
227 // Skip over the = and then any spaces\r
228 //\r
229 Value++;\r
230 while (*Value && isspace (*Value)) {\r
231 Value++;\r
232\r
233 }\r
234 //\r
235 // Find end of string, checking for quoted string\r
236 //\r
237 if (*Value == '\"') {\r
238 Value++;\r
239 for (Cptr = Value; *Cptr && *Cptr != '\"'; Cptr++)\r
240 ;\r
241 } else {\r
242 for (Cptr = Value; *Cptr && !isspace (*Cptr); Cptr++)\r
243 ;\r
244 }\r
245 //\r
246 // Null terminate the value string\r
247 //\r
248 CSave = *Cptr;\r
249 SaveCptr = Cptr;\r
250 *Cptr = 0;\r
251 Len = (int) (Cptr - Start);\r
252 }\r
253 //\r
254 // We now have a symbol name and a value. Look for an existing variable\r
255 // and overwrite it.\r
256 //\r
257 Symbol = mSymbolTable;\r
258 while (Symbol) {\r
259 //\r
260 // Check for symbol name match\r
261 //\r
262 if (stricmp (Name, Symbol->Name) == 0) {\r
263 _free (Symbol->Value);\r
264 Symbol->Value = (char *) _malloc (strlen (Value) + 1);\r
265 if (Symbol->Value == NULL) {\r
266 Error (NULL, 0, 0, NULL, "failed to allocate memory");\r
267 return -1;\r
268 }\r
269\r
270 strcpy (Symbol->Value, Value);\r
271 //\r
272 // If value == "NULL", then make it a 0-length string\r
273 //\r
274 if (stricmp (Symbol->Value, "NULL") == 0) {\r
275 Symbol->Value[0] = 0;\r
276 }\r
277\r
278 return Len;\r
279 }\r
280\r
281 Symbol = Symbol->Next;\r
282 }\r
283 //\r
284 // Does not exist, create a new one\r
285 //\r
286 NewSymbol = (SYMBOL *) _malloc (sizeof (SYMBOL));\r
287 if (NewSymbol == NULL) {\r
288 Error (NULL, 0, 0, NULL, "memory allocation failure");\r
289 return -1;\r
290 }\r
291\r
292 memset ((char *) NewSymbol, 0, sizeof (SYMBOL));\r
293 NewSymbol->Name = (char *) _malloc (strlen (Name) + 1);\r
294 if (NewSymbol->Name == NULL) {\r
295 Error (NULL, 0, 0, NULL, "memory allocation failure");\r
296 _free (NewSymbol);\r
297 return -1;\r
298 }\r
299\r
300 NewSymbol->Value = (char *) _malloc (strlen (Value) + 1);\r
301 if (NewSymbol->Value == NULL) {\r
302 Error (NULL, 0, 0, NULL, "memory allocation failure");\r
303 _free (NewSymbol->Name);\r
304 _free (NewSymbol);\r
305 return -1;\r
306 }\r
307\r
308 strcpy (NewSymbol->Name, Name);\r
309 strcpy (NewSymbol->Value, Value);\r
310 //\r
311 // Remove trailing spaces\r
312 //\r
313 Cptr = NewSymbol->Value + strlen (NewSymbol->Value) - 1;\r
314 while (Cptr > NewSymbol->Value) {\r
315 if (isspace (*Cptr)) {\r
316 *Cptr = 0;\r
317 Cptr--;\r
318 } else {\r
319 break;\r
320 }\r
321 }\r
322 //\r
323 // Add it to the head of the list.\r
324 //\r
325 NewSymbol->Next = mSymbolTable;\r
326 mSymbolTable = NewSymbol;\r
327 //\r
328 // If value == "NULL", then make it a 0-length string\r
329 //\r
330 if (stricmp (NewSymbol->Value, "NULL") == 0) {\r
331 NewSymbol->Value[0] = 0;\r
332 }\r
333 //\r
334 // Restore the terminator we inserted if they passed in var=value\r
335 //\r
336 if (SaveCptr != NULL) {\r
337 *SaveCptr = CSave;\r
338 }\r
339 _free (NewSymbol->Value);\r
340 _free (NewSymbol->Name);\r
341 _free (NewSymbol);\r
342 return Len;\r
343}\r
344\r
345static\r
346STATUS\r
347RemoveSymbol (\r
348 char *Name,\r
349 char SymbolType\r
350 )\r
351/*++\r
352\r
353Routine Description:\r
354 \r
355 Remove a symbol name/value from the symbol table\r
356\r
357Arguments:\r
358\r
359 Name - name of symbol to remove\r
360 SymbolType - type of symbol to remove\r
361\r
362Returns:\r
363\r
364 STATUS_SUCCESS - matching symbol found and removed\r
365 STATUS_ERROR - matching symbol not found in symbol table\r
366\r
367--*/\r
368{\r
369 SYMBOL *Symbol;\r
370\r
371 SYMBOL *PrevSymbol;\r
372\r
373 PrevSymbol = NULL;\r
374 Symbol = mSymbolTable;\r
375 //\r
376 // Walk the linked list of symbols in the symbol table looking\r
377 // for a match of both symbol name and type.\r
378 //\r
379 while (Symbol) {\r
380 if ((stricmp (Name, Symbol->Name) == 0) && (Symbol->Type & SymbolType)) {\r
381 //\r
382 // If the symbol has a value associated with it, free the memory\r
383 // allocated for the value.\r
384 // Then free the memory allocated for the symbols string name.\r
385 //\r
386 if (Symbol->Value) {\r
387 _free (Symbol->Value);\r
388 }\r
389\r
390 _free (Symbol->Name);\r
391 //\r
392 // Link the previous symbol to the next symbol to effectively\r
393 // remove this symbol from the linked list.\r
394 //\r
395 if (PrevSymbol) {\r
396 PrevSymbol->Next = Symbol->Next;\r
397 } else {\r
398 mSymbolTable = Symbol->Next;\r
399 }\r
400\r
401 _free (Symbol);\r
402 return STATUS_SUCCESS;\r
403 }\r
404\r
405 PrevSymbol = Symbol;\r
406 Symbol = Symbol->Next;\r
407 }\r
408\r
409 return STATUS_WARNING;\r
410}\r
411\r
412static\r
413SYMBOL *\r
414FreeSymbols (\r
415 SYMBOL *Syms\r
416 )\r
417/*++\r
418\r
419Routine Description:\r
420\r
421 GC_TODO: Add function description\r
422\r
423Arguments:\r
424\r
425 Syms - GC_TODO: add argument description\r
426\r
427Returns:\r
428\r
429 GC_TODO: add return values\r
430\r
431--*/\r
432{\r
433 SYMBOL *Next;\r
434 while (Syms) {\r
435 if (Syms->Name != NULL) {\r
436 _free (Syms->Name);\r
437 }\r
438\r
439 if (Syms->Value != NULL) {\r
440 _free (Syms->Value);\r
441 }\r
442\r
443 Next = Syms->Next;\r
444 _free (Syms);\r
445 Syms = Next;\r
446 }\r
447\r
448 return Syms;\r
449}\r
450\r
451static\r
452int\r
453ExpandMacros (\r
454 char *SourceLine,\r
455 char *DestLine,\r
456 int LineLen\r
457 )\r
458/*++\r
459\r
460Routine Description:\r
461 \r
462 Given a line of text, replace all variables of format $(NAME) with values\r
463 from our symbol table.\r
464\r
465Arguments:\r
466\r
467 SourceLine - input line of text to do symbol replacements on\r
468 DestLine - on output, SourceLine with symbols replaced\r
469 LineLen - length of DestLine, so we don't exceed its allocated length\r
470\r
471Returns:\r
472\r
473 STATUS_SUCCESS - no problems encountered\r
474 STATUS_WARNING - missing closing parenthesis on a symbol reference in SourceLine\r
475 STATUS_ERROR - memory allocation failure\r
476\r
477--*/\r
478{\r
479 static int NestDepth = 0;\r
480 char *FromPtr;\r
481 char *ToPtr;\r
482 char *SaveStart;\r
483 char *Cptr;\r
484 char *value;\r
485 int Expanded;\r
486 int ExpandedCount;\r
487 INT8 *LocalDestLine;\r
488 STATUS Status;\r
489 int LocalLineLen;\r
490\r
491 NestDepth++;\r
492 Status = STATUS_SUCCESS;\r
493 LocalDestLine = (char *) _malloc (LineLen);\r
494 if (LocalDestLine == NULL) {\r
495 Error (__FILE__, __LINE__, 0, "memory allocation failed", NULL);\r
496 return STATUS_ERROR;\r
497 }\r
498\r
499 FromPtr = SourceLine;\r
500 ToPtr = LocalDestLine;\r
501 //\r
502 // Walk the entire line, replacing $(MACRO_NAME).\r
503 //\r
504 LocalLineLen = LineLen;\r
505 ExpandedCount = 0;\r
506 while (*FromPtr && (LocalLineLen > 0)) {\r
507 if ((*FromPtr == '$') && (*(FromPtr + 1) == '(')) {\r
508 //\r
509 // Save the start in case it's undefined, in which case we copy it as-is.\r
510 //\r
511 SaveStart = FromPtr;\r
512 Expanded = 0;\r
513 //\r
514 // Macro expansion time. Find the end (no spaces allowed)\r
515 //\r
516 FromPtr += 2;\r
517 for (Cptr = FromPtr; *Cptr && (*Cptr != ')'); Cptr++)\r
518 ;\r
519 if (*Cptr) {\r
520 //\r
521 // Truncate the string at the closing parenthesis for ease-of-use.\r
522 // Then copy the string directly to the destination line in case we don't find\r
523 // a definition for it.\r
524 //\r
525 *Cptr = 0;\r
526 strcpy (ToPtr, SaveStart);\r
527 if ((value = GetSymbolValue (FromPtr)) != NULL) {\r
528 strcpy (ToPtr, value);\r
529 LocalLineLen -= strlen (value);\r
530 ToPtr += strlen (value);\r
531 Expanded = 1;\r
532 ExpandedCount++;\r
533 }\r
534\r
535 if (!Expanded) {\r
536 //\r
537 // Restore closing parenthesis, and advance to next character\r
538 //\r
539 *Cptr = ')';\r
540 FromPtr = SaveStart + 1;\r
541 ToPtr++;\r
542 } else {\r
543 FromPtr = Cptr + 1;\r
544 }\r
545 } else {\r
546 Error (NULL, 0, 0, SourceLine, "missing closing parenthesis on macro");\r
547 strcpy (ToPtr, FromPtr);\r
548 Status = STATUS_WARNING;\r
549 goto Done;\r
550 }\r
551 } else {\r
552 *ToPtr = *FromPtr;\r
553 FromPtr++;\r
554 ToPtr++;\r
555 LocalLineLen--;\r
556 }\r
557 }\r
558\r
559 if (*FromPtr == 0) {\r
560 *ToPtr = 0;\r
561 }\r
562\r
563 //\r
564 // If we expanded at least one string successfully, then make a recursive call to try again.\r
565 //\r
566 if ((ExpandedCount != 0) && (Status == STATUS_SUCCESS) && (NestDepth < 10)) {\r
567 Status = ExpandMacros (LocalDestLine, DestLine, LineLen);\r
568 _free (LocalDestLine);\r
569 NestDepth = 0;\r
570 return Status;\r
571 }\r
572\r
573Done:\r
574 if (Status != STATUS_ERROR) {\r
575 strcpy (DestLine, LocalDestLine);\r
576 }\r
577\r
578 NestDepth = 0;\r
579 _free (LocalDestLine);\r
580 return Status;\r
581}\r
582\r
583STATUS\r
584SymbolsFileStringsReplace (\r
585 char *InFileName,\r
586 char *OutFileName\r
587 )\r
588/*++\r
589\r
590Routine Description:\r
591 \r
592 Given input and output file names, read in the input file, replace variable\r
593 references of format $(NAME) with appropriate values from our symbol table,\r
594 and write the result out to the output file.\r
595\r
596Arguments:\r
597\r
598 InFileName - name of input text file to replace variable references\r
599 OutFileName - name of output text file to write results to\r
600\r
601Returns:\r
602\r
603 STATUS_SUCCESS - no problems encountered\r
604 STATUS_ERROR - failed to open input or output file\r
605\r
606--*/\r
607{\r
608 STATUS Status;\r
609 FILE *InFptr;\r
610 FILE *OutFptr;\r
611 char Line[MAX_LINE_LEN];\r
612 char OutLine[MAX_LINE_LEN];\r
613\r
614 Status = STATUS_ERROR;\r
615 //\r
616 // Open input and output files\r
617 //\r
618 InFptr = NULL;\r
619 OutFptr = NULL;\r
620 if ((InFptr = fopen (InFileName, "r")) == NULL) {\r
621 Error (NULL, 0, 0, InFileName, "failed to open input file for reading");\r
622 goto Done;\r
623 }\r
624\r
625 if ((OutFptr = fopen (OutFileName, "w")) == NULL) {\r
626 Error (NULL, 0, 0, OutFileName, "failed to open output file for writing");\r
627 goto Done;\r
628 }\r
629 //\r
630 // Read lines from input file until done\r
631 //\r
632 while (fgets (Line, sizeof (Line), InFptr) != NULL) {\r
633 ExpandMacros (Line, OutLine, sizeof (OutLine));\r
634 fprintf (OutFptr, OutLine);\r
635 }\r
636\r
637 Status = STATUS_SUCCESS;\r
638Done:\r
639 if (InFptr != NULL) {\r
640 fclose (InFptr);\r
641 }\r
642\r
643 if (OutFptr != NULL) {\r
644 fclose (OutFptr);\r
645 }\r
646\r
647 return Status;\r
648}\r