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