]> git.proxmox.com Git - mirror_edk2.git/blob - EdkCompatibilityPkg/Sample/Tools/Source/VfrCompile/VfrServices.cpp
Add in the 1st version of ECP.
[mirror_edk2.git] / EdkCompatibilityPkg / Sample / Tools / Source / VfrCompile / VfrServices.cpp
1 /*++
2
3 Copyright (c) 2004 - 2007, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this 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 VfrServices.cpp
15
16 Abstract:
17
18 Support routines for the VFR compiler
19
20 --*/
21
22 #include <stdio.h> // for FILE routines
23 #include <stdlib.h> // for malloc() and free()
24
25 #include "Tiano.h"
26 #include "EfiUtilityMsgs.h"
27 #include "EfiVfr.h"
28 #include "VfrServices.h"
29
30 #include EFI_PROTOCOL_DEFINITION (Hii)
31
32 static const char *mSourceFileHeader[] = {
33 "//",
34 "// DO NOT EDIT -- auto-generated file",
35 "//",
36 "// This file is generated by the VFR compiler.",
37 "//",
38 NULL
39 };
40
41 typedef struct {
42 INT8 *Name;
43 INT32 Size;
44 } IFR_OPCODE_SIZES;
45
46 //
47 // Create a table that can be used to do internal checking on the IFR
48 // bytes we emit.
49 //
50 static const IFR_OPCODE_SIZES mOpcodeSizes[] = {
51 { 0, 0 }, // invalid
52 { "EFI_IFR_FORM", sizeof (EFI_IFR_FORM) },
53 { "EFI_IFR_SUBTITLE", sizeof (EFI_IFR_SUBTITLE) },
54 { "EFI_IFR_TEXT", -6 }, //sizeof (EFI_IFR_TEXT) },
55 { "unused 0x04 opcode", 0 }, // EFI_IFR_GRAPHIC_OP
56 { "EFI_IFR_ONE_OF", sizeof (EFI_IFR_ONE_OF) },
57 { "EFI_IFR_CHECK_BOX", sizeof (EFI_IFR_CHECK_BOX) },
58 { "EFI_IFR_NUMERIC", sizeof (EFI_IFR_NUMERIC) },
59 { "EFI_IFR_PASSWORD", sizeof (EFI_IFR_PASSWORD) },
60 { "EFI_IFR_ONE_OF_OPTION", sizeof (EFI_IFR_ONE_OF_OPTION) },
61 { "EFI_IFR_SUPPRESS", sizeof (EFI_IFR_SUPPRESS) },
62 { "EFI_IFR_END_FORM", sizeof (EFI_IFR_END_FORM) },
63 { "EFI_IFR_HIDDEN", sizeof (EFI_IFR_HIDDEN) },
64 { "EFI_IFR_END_FORM_SET", sizeof (EFI_IFR_END_FORM_SET) },
65 { "EFI_IFR_FORM_SET", sizeof (EFI_IFR_FORM_SET) },
66 { "EFI_IFR_REF", sizeof (EFI_IFR_REF) },
67 { "EFI_IFR_END_ONE_OF", sizeof (EFI_IFR_END_ONE_OF) },
68 { "EFI_IFR_INCONSISTENT", sizeof (EFI_IFR_INCONSISTENT) },
69 { "EFI_IFR_EQ_ID_VAL", sizeof (EFI_IFR_EQ_ID_VAL) },
70 { "EFI_IFR_EQ_ID_ID", sizeof (EFI_IFR_EQ_ID_ID) },
71 { "EFI_IFR_EQ_ID_LIST", -sizeof (EFI_IFR_EQ_ID_LIST) },
72 { "EFI_IFR_AND", sizeof (EFI_IFR_AND) },
73 { "EFI_IFR_OR", sizeof (EFI_IFR_OR) },
74 { "EFI_IFR_NOT", sizeof (EFI_IFR_NOT) },
75 { "EFI_IFR_END_IF", sizeof (EFI_IFR_END_IF) },
76 { "EFI_IFR_GRAYOUT", sizeof (EFI_IFR_GRAYOUT) },
77 { "EFI_IFR_DATE", sizeof (EFI_IFR_DATE) / 3 },
78 { "EFI_IFR_TIME", sizeof (EFI_IFR_TIME) / 3 },
79 { "EFI_IFR_STRING", sizeof (EFI_IFR_STRING) },
80 { "EFI_IFR_LABEL", sizeof (EFI_IFR_LABEL) },
81 { "EFI_IFR_SAVE_DEFAULTS", sizeof (EFI_IFR_SAVE_DEFAULTS) },
82 { "EFI_IFR_RESTORE_DEFAULTS", sizeof (EFI_IFR_RESTORE_DEFAULTS) },
83 { "EFI_IFR_BANNER", sizeof (EFI_IFR_BANNER) },
84 { "EFI_IFR_INVENTORY", sizeof (EFI_IFR_INVENTORY) },
85 { "EFI_IFR_EQ_VAR_VAL_OP", sizeof (EFI_IFR_EQ_VAR_VAL) },
86 { "EFI_IFR_ORDERED_LIST_OP", sizeof (EFI_IFR_ORDERED_LIST) },
87 { "EFI_IFR_VARSTORE_OP", -sizeof (EFI_IFR_VARSTORE) },
88 { "EFI_IFR_VARSTORE_SELECT_OP", sizeof (EFI_IFR_VARSTORE_SELECT) },
89 { "EFI_IFR_VARSTORE_SELECT_PAIR_OP", sizeof (EFI_IFR_VARSTORE_SELECT_PAIR) },
90 { "EFI_IFR_TRUE", sizeof (EFI_IFR_TRUE)},
91 { "EFI_IFR_FALSE", sizeof (EFI_IFR_FALSE)},
92 { "EFI_IFR_GT", sizeof (EFI_IFR_GT)},
93 { "EFI_IFR_GE", sizeof (EFI_IFR_GE)},
94 { "EFI_IFR_OEM_DEFINED_OP", -2 },
95 };
96
97
98 VfrOpcodeHandler::VfrOpcodeHandler (
99 )
100 /*++
101
102 Routine Description:
103 Constructor for the VFR opcode handling class.
104
105 Arguments:
106 None
107
108 Returns:
109 None
110
111 --*/
112 {
113 mIfrBytes = NULL;
114 mLastIfrByte = NULL;
115 mBytesWritten = 0;
116 mQueuedByteCount = 0;
117 mQueuedOpcodeByteValid = 0;
118 mPrimaryVarStoreId = 0;
119 mSecondaryVarStoreId = 0;
120 mSecondaryVarStoreIdSet = 0;
121 mPrimaryVarStoreIdSet = 0;
122 mDefaultVarStoreId = 0;
123 }
124
125 VOID
126 VfrOpcodeHandler::SetVarStoreId (
127 UINT16 VarStoreId
128 )
129 /*++
130
131 Routine Description:
132 This function is invoked by the parser when a variable is referenced in the
133 VFR. Save the variable store (and set a flag) so that we can later determine
134 if we need to emit a varstore-select or varstore-select-pair opcode.
135
136 Arguments:
137 VarStoreId - ID of the variable store referenced in the VFR
138
139 Returns:
140 None
141
142 --*/
143 {
144 mPrimaryVarStoreId = VarStoreId;
145 mPrimaryVarStoreIdSet = 1;
146 }
147
148 VOID
149 VfrOpcodeHandler::SetSecondaryVarStoreId (
150 UINT16 VarStoreId
151 )
152 /*++
153
154 Routine Description:
155 This function is invoked by the parser when a secondary variable is
156 referenced in the VFR. Save the variable store (and set a flag) so
157 that we can later determine if we need to emit a varstore-select or
158 varstore-pair opcode.
159
160 Arguments:
161 VarStoreId - ID of the variable store referenced in the VFR
162
163 Returns:
164 None
165
166 --*/
167 {
168 mSecondaryVarStoreId = VarStoreId;
169 mSecondaryVarStoreIdSet = 1;
170 }
171
172 VOID
173 VfrOpcodeHandler::WriteIfrBytes (
174 )
175 /*++
176
177 Routine Description:
178 This function is invoked at the end of parsing. Its purpose
179 is to write out all the IFR bytes that were queued up while
180 parsing.
181
182 Arguments:
183 None
184
185 Returns:
186 None
187
188 --*/
189 {
190 IFR_BYTE *Curr;
191 IFR_BYTE *Next;
192 UINT32 Count;
193 UINT32 LineCount;
194 UINT32 PoundLines;
195 UINT32 ByteCount;
196 INT8 Line[MAX_LINE_LEN];
197 INT8 *Cptr;
198 FILE *InFptr;
199 FILE *OutFptr;
200 UINT32 ListFile;
201 EFI_HII_IFR_PACK_HEADER IfrHeader;
202 UINT8 *Ptr;
203 FILE *IfrBinFptr;
204 UINT32 BytesLeftThisOpcode;
205 //
206 // If someone added a new opcode and didn't update our opcode sizes structure, error out.
207 //
208 if (sizeof(mOpcodeSizes) / sizeof (mOpcodeSizes[0]) != EFI_IFR_LAST_OPCODE + 1) {
209 Error (__FILE__, __LINE__, 0, "application error", "internal IFR binary table size is incorrect");
210 return;
211 }
212 //
213 // Flush the queue
214 //
215 FlushQueue ();
216 //
217 // If there have been any errors to this point, then skip dumping the IFR
218 // binary data. This way doing an nmake again will try to build it again, and
219 // the build will fail if they did not fix the problem.
220 //
221 if (GetUtilityStatus () != STATUS_ERROR) {
222 if ((IfrBinFptr = fopen (gOptions.IfrOutputFileName, "w")) == NULL) {
223 Error (PROGRAM_NAME, 0, 0, gOptions.IfrOutputFileName, "could not open file for writing");
224 return;
225 }
226 //
227 // Write the standard file header to the output file
228 //
229 WriteStandardFileHeader (IfrBinFptr);
230 //
231 // Write the structure header
232 //
233 fprintf (IfrBinFptr, "\nunsigned char %sBin[] = {", gOptions.VfrBaseFileName);
234 //
235 // Write the header
236 //
237 memset ((char *)&IfrHeader, 0, sizeof (IfrHeader));
238 IfrHeader.Header.Type = EFI_HII_IFR;
239 IfrHeader.Header.Length = mBytesWritten + sizeof (IfrHeader);
240 Ptr = (UINT8 *)&IfrHeader;
241 for (Count = 0; Count < sizeof (IfrHeader); Count++, Ptr++) {
242 if ((Count & 0x03) == 0) {
243 fprintf (IfrBinFptr, "\n ");
244 }
245 fprintf (IfrBinFptr, "0x%02X, ", *Ptr);
246 }
247 //
248 //
249 // Write all the IFR bytes
250 //
251 fprintf (IfrBinFptr, "\n // start of IFR data");
252 Curr = mIfrBytes;
253 Count = 0;
254 while (Curr != NULL) {
255 if ((Count & 0x0F) == 0) {
256 fprintf (IfrBinFptr, "\n ");
257 }
258 if (Curr->KeyByte != 0) {
259 fprintf (IfrBinFptr, "/*%c*/ ", Curr->KeyByte);
260 }
261 fprintf (IfrBinFptr, "0x%02X, ", Curr->OpcodeByte);
262 Count++;
263 Curr = Curr->Next;
264 }
265 fprintf (IfrBinFptr, "\n};\n\n");
266 //
267 //
268 // Close the file
269 //
270 fclose (IfrBinFptr);
271 IfrBinFptr = NULL;
272 }
273 //
274 // Write the bytes as binary data if the user specified to do so
275 //
276 if ((GetUtilityStatus () != STATUS_ERROR) && (gOptions.CreateIfrBinFile != 0)) {
277 //
278 // Use the Ifr output file name with a ".hpk" extension.
279 //
280 for (Cptr = gOptions.IfrOutputFileName + strlen (gOptions.IfrOutputFileName) - 1;
281 (*Cptr != '.') && (Cptr > gOptions.IfrOutputFileName) && (*Cptr != '\\');
282 Cptr--) {
283 //
284 // do nothing
285 //
286 }
287 if (*Cptr == '.') {
288 strcpy (Cptr, ".hpk");
289 } else {
290 strcat (gOptions.IfrOutputFileName, ".hpk");
291 }
292 if ((IfrBinFptr = fopen (gOptions.IfrOutputFileName, "wb")) == NULL) {
293 Error (PROGRAM_NAME, 0, 0, gOptions.IfrOutputFileName, "could not open file for writing");
294 return;
295 }
296 //
297 // Write the structure header
298 //
299 memset ((char *)&IfrHeader, 0, sizeof (IfrHeader));
300 IfrHeader.Header.Type = EFI_HII_IFR;
301 IfrHeader.Header.Length = mBytesWritten + sizeof (IfrHeader);
302 Ptr = (UINT8 *)&IfrHeader;
303 for (Count = 0; Count < sizeof (IfrHeader); Count++, Ptr++) {
304 fwrite (Ptr, 1, 1, IfrBinFptr);
305 }
306 //
307 //
308 // Write all the IFR bytes
309 //
310 Curr = mIfrBytes;
311 Count = 0;
312 while (Curr != NULL) {
313 fwrite (&Curr->OpcodeByte, 1, 1, IfrBinFptr);
314 Curr = Curr->Next;
315 }
316 //
317 //
318 // Close the file
319 //
320 fclose (IfrBinFptr);
321 IfrBinFptr = NULL;
322 }
323 //
324 // If creating a listing file, then open the input and output files
325 //
326 ListFile = 0;
327 if (gOptions.CreateListFile) {
328 //
329 // Open the input VFR file and the output list file
330 //
331 if ((InFptr = fopen (gOptions.PreprocessorOutputFileName, "r")) == NULL) {
332 Warning (PROGRAM_NAME, 0, 0, gOptions.PreprocessorOutputFileName, "could not open file for creating a list file");
333 } else {
334 if ((OutFptr = fopen (gOptions.VfrListFileName, "w")) == NULL) {
335 Warning (PROGRAM_NAME, 0, 0, gOptions.VfrListFileName, "could not open output list file for writing");
336 fclose (InFptr);
337 InFptr = NULL;
338 } else {
339 LineCount = 0;
340 ListFile = 1;
341 PoundLines = 0;
342 ByteCount = 0;
343 }
344 }
345 }
346 //
347 // Write the list file
348 //
349 if (ListFile) {
350 //
351 // Write out the VFR compiler version
352 //
353 fprintf (OutFptr, "//\n// VFR compiler version " VFR_COMPILER_VERSION "\n//\n");
354 Curr = mIfrBytes;
355 while (Curr != NULL) {
356 //
357 // Print lines until we reach the line of the current opcode
358 //
359 while (LineCount < PoundLines + Curr->LineNum) {
360 if (fgets (Line, sizeof (Line), InFptr) != NULL) {
361 //
362 // We should check for line length exceeded on the fgets(). Otherwise it
363 // throws the listing file output off. Future enhancement perhaps.
364 //
365 fprintf (OutFptr, "%s", Line);
366 if (strncmp (Line, "#line", 5) == 0) {
367 PoundLines++;
368 }
369 }
370 LineCount++;
371 }
372 //
373 // Print all opcodes with line numbers less than where we are now
374 //
375 BytesLeftThisOpcode = 0;
376 while ((Curr != NULL) && ((Curr->LineNum == 0) || (LineCount >= PoundLines + Curr->LineNum))) {
377 if (BytesLeftThisOpcode == 0) {
378 fprintf (OutFptr, ">%08X: ", ByteCount);
379 if (Curr->Next != NULL) {
380 BytesLeftThisOpcode = (UINT32)Curr->Next->OpcodeByte;
381 }
382 }
383 fprintf (OutFptr, "%02X ", (UINT32)Curr->OpcodeByte);
384 ByteCount++;
385 BytesLeftThisOpcode--;
386 if (BytesLeftThisOpcode == 0) {
387 fprintf (OutFptr, "\n");
388 }
389 Curr = Curr->Next;
390 }
391 }
392 //
393 // Dump any remaining lines from the input file
394 //
395 while (fgets (Line, sizeof (Line), InFptr) != NULL) {
396 fprintf (OutFptr, "%s", Line);
397 }
398 fclose (InFptr);
399 fclose (OutFptr);
400 }
401 //
402 // Debug code to make sure that each opcode we write out has as many
403 // bytes as the IFR structure requires. If there were errors, then
404 // don't do this step.
405 //
406 if (GetUtilityStatus () != STATUS_ERROR) {
407 Curr = mIfrBytes;
408 ByteCount = 0;
409 while (Curr != NULL) {
410 //
411 // First byte is the opcode, second byte is the length
412 //
413 if (Curr->Next == NULL) {
414 Error (__FILE__, __LINE__, 0, "application error", "last opcode written does not contain a length byte");
415 break;
416 }
417 Count = (UINT32)Curr->Next->OpcodeByte;
418 if (Count == 0) {
419 Error (
420 __FILE__,
421 __LINE__,
422 0,
423 "application error",
424 "opcode with 0 length specified in output at offset 0x%X",
425 ByteCount
426 );
427 break;
428 }
429 //
430 // Check the length
431 //
432 if ((Curr->OpcodeByte > EFI_IFR_LAST_OPCODE) || (Curr->OpcodeByte == 0)) {
433 Error (
434 __FILE__,
435 __LINE__,
436 0,
437 "application error",
438 "invalid opcode 0x%X in output at offset 0x%X",
439 (UINT32) Curr->OpcodeByte, ByteCount
440 );
441 } else if (mOpcodeSizes[Curr->OpcodeByte].Size < 0) {
442 //
443 // For those cases where the length is variable, the size is negative, and indicates
444 // the miniumum size.
445 //
446 if ((mOpcodeSizes[Curr->OpcodeByte].Size * -1) > Count) {
447 Error (
448 __FILE__,
449 __LINE__,
450 0,
451 "application error",
452 "insufficient number of bytes written for %s at offset 0x%X",
453 mOpcodeSizes[Curr->OpcodeByte].Name,
454 ByteCount
455 );
456 }
457 } else {
458 //
459 // Check for gaps
460 //
461 if (mOpcodeSizes[Curr->OpcodeByte].Size == 0) {
462 Error (
463 __FILE__,
464 __LINE__,
465 0,
466 "application error",
467 "invalid opcode 0x%X in output at offset 0x%X",
468 (UINT32)Curr->OpcodeByte,
469 ByteCount
470 );
471 } else {
472 //
473 // Check size
474 //
475 if (mOpcodeSizes[Curr->OpcodeByte].Size != Count) {
476 Error (
477 __FILE__,
478 __LINE__,
479 0,
480 "application error",
481 "invalid number of bytes (%d written s/b %d) written for %s at offset 0x%X",
482 Count,
483 mOpcodeSizes[Curr->OpcodeByte].Size,
484 mOpcodeSizes[Curr->OpcodeByte].Name,
485 ByteCount
486 );
487 }
488 }
489 }
490 //
491 // Skip to next opcode
492 //
493 while (Count > 0) {
494 ByteCount++;
495 if (Curr == NULL) {
496 Error (__FILE__, __LINE__, 0, "application error", "last opcode written has invalid length");
497 break;
498 }
499 Curr = Curr->Next;
500 Count--;
501 }
502 }
503 }
504 }
505
506 VfrOpcodeHandler::~VfrOpcodeHandler(
507 )
508 /*++
509
510 Routine Description:
511 Destructor for the VFR opcode handler. Free up memory allocated
512 while parsing the VFR script.
513
514 Arguments:
515 None
516
517 Returns:
518 None
519
520 --*/
521 {
522 IFR_BYTE *Curr;
523 IFR_BYTE *Next;
524 //
525 // Free up the IFR bytes
526 //
527 Curr = mIfrBytes;
528 while (Curr != NULL) {
529 Next = Curr->Next;
530 free (Curr);
531 Curr = Next;
532 }
533 }
534
535 int
536 VfrOpcodeHandler::AddOpcodeByte (
537 UINT8 OpcodeByte,
538 UINT32 LineNum
539 )
540 /*++
541
542 Routine Description:
543 This function is invoked by the parser when a new IFR
544 opcode should be emitted.
545
546 Arguments:
547 OpcodeByte - the IFR opcode
548 LineNum - the line number from the source file that resulted
549 in the opcode being emitted.
550
551 Returns:
552 0 always
553
554 --*/
555 {
556 UINT32 Count;
557
558 FlushQueue();
559 //
560 // Now add this new byte
561 //
562 mQueuedOpcodeByte = OpcodeByte;
563 mQueuedLineNum = LineNum;
564 mQueuedOpcodeByteValid = 1;
565 return 0;
566 }
567
568 VOID
569 VfrOpcodeHandler::AddByte (
570 UINT8 ByteVal,
571 UINT8 KeyByte
572 )
573 /*++
574
575 Routine Description:
576 This function is invoked by the parser when it determines
577 that more raw IFR bytes should be emitted to the output stream.
578 Here we just queue them up into an output buffer.
579
580 Arguments:
581 ByteVal - the raw byte to emit to the output IFR stream
582 KeyByte - a value that can be used for debug.
583
584 Returns:
585 None
586
587 --*/
588 {
589 //
590 // Check for buffer overflow
591 //
592 if (mQueuedByteCount >= MAX_QUEUE_COUNT) {
593 Error (PROGRAM_NAME, 0, 0, NULL, "opcode queue overflow");
594 } else {
595 mQueuedBytes[mQueuedByteCount] = ByteVal;
596 mQueuedKeyBytes[mQueuedByteCount] = KeyByte;
597 mQueuedByteCount++;
598 }
599 }
600
601 int
602 VfrOpcodeHandler::FlushQueue (
603 )
604 /*++
605
606 Routine Description:
607 This function is invoked to flush the internal IFR buffer.
608
609 Arguments:
610 None
611
612 Returns:
613 0 always
614
615 --*/
616 {
617 UINT32 Count;
618 UINT32 EmitNoneOnePair;
619
620 EmitNoneOnePair = 0;
621 //
622 // If the secondary varstore was specified, then we have to emit
623 // a varstore-select-pair opcode, which only applies to the following
624 // statement.
625 //
626 if (mSecondaryVarStoreIdSet) {
627 mSecondaryVarStoreIdSet = 0;
628 //
629 // If primary and secondary are the same as the current default
630 // varstore, then we don't have to do anything.
631 // Note that the varstore-select-pair only applies to the following
632 // opcode.
633 //
634 if ((mPrimaryVarStoreId != mSecondaryVarStoreId) || (mPrimaryVarStoreId != mDefaultVarStoreId)) {
635 IAddByte (EFI_IFR_VARSTORE_SELECT_PAIR_OP, 'O', mQueuedLineNum);
636 IAddByte ((UINT8)sizeof (EFI_IFR_VARSTORE_SELECT_PAIR), 'L', 0);
637 IAddByte ((UINT8)mPrimaryVarStoreId, 0, 0);
638 IAddByte ((UINT8)(mPrimaryVarStoreId >> 8), 0, 0);
639 IAddByte ((UINT8)mSecondaryVarStoreId, 0, 0);
640 IAddByte ((UINT8)(mSecondaryVarStoreId >> 8), 0, 0);
641 }
642 } else if (mPrimaryVarStoreIdSet != 0) {
643 mPrimaryVarStoreIdSet = 0;
644 if (mDefaultVarStoreId != mPrimaryVarStoreId) {
645 //
646 // The VFR statement referenced a different variable store
647 // than the last one we reported. Insert a new varstore select
648 // statement.
649 //
650 IAddByte (EFI_IFR_VARSTORE_SELECT_OP, 'O', mQueuedLineNum);
651 IAddByte ((UINT8)sizeof (EFI_IFR_VARSTORE_SELECT), 'L', 0);
652 IAddByte ((UINT8)mPrimaryVarStoreId, 0, 0);
653 IAddByte ((UINT8)(mPrimaryVarStoreId >> 8), 0, 0);
654 mDefaultVarStoreId = mPrimaryVarStoreId;
655 }
656 }
657 //
658 // Likely a new opcode is being added. Since each opcode item in the IFR has
659 // a header that specifies the size of the opcode item (which we don't
660 // know until we find the next opcode in the VFR), we queue up bytes
661 // until we know the size. Then we write them out. So flush the queue
662 // now.
663 //
664 if (mQueuedOpcodeByteValid != 0) {
665 //
666 // Add the previous opcode byte, the length byte, and the binary
667 // data.
668 //
669 IAddByte (mQueuedOpcodeByte, 'O', mQueuedLineNum);
670 IAddByte ((UINT8)(mQueuedByteCount + 2), 'L', 0);
671 for (Count = 0; Count < mQueuedByteCount; Count++) {
672 IAddByte (mQueuedBytes[Count], mQueuedKeyBytes[Count], 0);
673 }
674 mQueuedByteCount = 0;
675 mQueuedOpcodeByteValid = 0;
676 }
677 return 0;
678 }
679
680 int
681 VfrOpcodeHandler::IAddByte (
682 UINT8 ByteVal,
683 UINT8 KeyByte,
684 UINT32 LineNum
685 )
686 /*++
687
688 Routine Description:
689 This internal function is used to add actual IFR bytes to
690 the output stream. Most other functions queue up the bytes
691 in an internal buffer. Once they come here, there's no
692 going back.
693
694
695 Arguments:
696 ByteVal - value to write to output
697 KeyByte - key value tied to the byte -- useful for debug
698 LineNum - line number from source file the byte resulted from
699
700 Returns:
701 0 - if successful
702 1 - failed due to memory allocation failure
703
704 --*/
705 {
706 IFR_BYTE *NewByte;
707 NewByte = (IFR_BYTE *)malloc (sizeof (IFR_BYTE));
708 if (NewByte == NULL) {
709 return 1;
710 }
711 memset ((char *)NewByte, 0, sizeof (IFR_BYTE));
712 NewByte->OpcodeByte = ByteVal;
713 NewByte->KeyByte = KeyByte;
714 NewByte->LineNum = LineNum;
715 //
716 // Add to the list
717 //
718 if (mIfrBytes == NULL) {
719 mIfrBytes = NewByte;
720 } else {
721 mLastIfrByte->Next = NewByte;
722 }
723 mLastIfrByte = NewByte;
724 mBytesWritten++;
725 return 0;
726 }
727
728 VOID
729 WriteStandardFileHeader (
730 FILE *OutFptr
731 )
732 /*++
733
734 Routine Description:
735 This function is invoked to emit a standard header to an
736 output text file.
737
738 Arguments:
739 OutFptr - file to write the header to
740
741 Returns:
742 None
743
744 --*/
745 {
746 UINT32 TempIndex;
747 for (TempIndex = 0; mSourceFileHeader[TempIndex] != NULL; TempIndex++) {
748 fprintf (OutFptr, "%s\n", mSourceFileHeader[TempIndex]);
749 }
750 //
751 // Write out the VFR compiler version
752 //
753 fprintf (OutFptr, "// VFR compiler version " VFR_COMPILER_VERSION "\n//\n");
754 }