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