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