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