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