1 /*++ 2 3 Copyright (c) 2004 - 2010, Intel Corporation. All rights reserved.<BR> 4 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 (UTILITY_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 (UTILITY_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 (UTILITY_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 (UTILITY_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 " UTILITY_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 (UTILITY_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 " UTILITY_VERSION "\n//\n"); 754 } 755