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