summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbbahnsen <bbahnsen@6f19259b-4bc3-4df7-8a09-765794883524>2006-10-26 18:00:27 +0000
committerbbahnsen <bbahnsen@6f19259b-4bc3-4df7-8a09-765794883524>2006-10-26 18:00:27 +0000
commit67ec665a638098a9d5e05238fed4c67d4b0528ad (patch)
treec0089f6541d26e72c81698327ee78218d2f10b36
parent0cd8588f84fb4f86f0ff34df0b41cf631f93dc6c (diff)
downloadedk2-svn/branches/IPF-Tools.zip
edk2-svn/branches/IPF-Tools.tar.gz
edk2-svn/branches/IPF-Tools.tar.bz2
IPF Tools sourcesvn/branches/IPF-Tools
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/branches/IPF-Tools@1846 6f19259b-4bc3-4df7-8a09-765794883524
-rw-r--r--Source/Common/CommonLib.c516
-rw-r--r--Source/Common/CommonLib.h139
-rw-r--r--Source/Common/Crc32.c326
-rw-r--r--Source/Common/Crc32.h54
-rw-r--r--Source/Common/EfiCompress.c1742
-rw-r--r--Source/Common/EfiCompress.h69
-rw-r--r--Source/Common/EfiCustomizedCompress.h141
-rw-r--r--Source/Common/EfiDecompress.c790
-rw-r--r--Source/Common/EfiDecompress.h106
-rw-r--r--Source/Common/EfiUtilityMsgs.c755
-rw-r--r--Source/Common/EfiUtilityMsgs.h137
-rw-r--r--Source/Common/FvLib.c780
-rw-r--r--Source/Common/FvLib.h181
-rw-r--r--Source/Common/MyAlloc.c516
-rw-r--r--Source/Common/MyAlloc.h222
-rw-r--r--Source/Common/ParseInf.c630
-rw-r--r--Source/Common/ParseInf.h234
-rw-r--r--Source/Common/SimpleFileParsing.c1457
-rw-r--r--Source/Common/SimpleFileParsing.h120
-rw-r--r--Source/Common/WinNtInclude.h73
-rw-r--r--Source/Common/build.xml65
-rw-r--r--Source/CompressDll/CompressDll.c105
-rw-r--r--Source/CompressDll/CompressDll.h22
-rw-r--r--Source/CompressDll/build.xml78
-rw-r--r--Source/CreateMtFile/CreateMtFile.c247
-rw-r--r--Source/CreateMtFile/build.xml69
-rw-r--r--Source/CustomizedCompress/CustomizedCompress.c146
-rw-r--r--Source/CustomizedCompress/build.xml73
-rw-r--r--Source/EfiCompress/EfiCompressMain.c165
-rw-r--r--Source/EfiCompress/build.xml69
-rw-r--r--Source/EfiRom/EfiRom.c1536
-rw-r--r--Source/EfiRom/build.xml69
-rw-r--r--Source/FlashMap/FlashDefFile.c2788
-rw-r--r--Source/FlashMap/FlashDefFile.h281
-rw-r--r--Source/FlashMap/FlashMap.c769
-rw-r--r--Source/FlashMap/Microcode.c304
-rw-r--r--Source/FlashMap/Microcode.h87
-rw-r--r--Source/FlashMap/Symbols.c648
-rw-r--r--Source/FlashMap/Symbols.h124
-rw-r--r--Source/FlashMap/build.xml75
-rw-r--r--Source/FwImage/build.xml70
-rw-r--r--Source/FwImage/fwimage.c510
-rw-r--r--Source/GenAcpiTable/GenAcpiTable.c544
-rw-r--r--Source/GenAcpiTable/build.xml70
-rw-r--r--Source/GenBsfFixup/GenBsfFixup.c490
-rw-r--r--Source/GenBsfFixup/build.xml127
-rw-r--r--Source/GenBsfImage/GenBsfImage.c3519
-rw-r--r--Source/GenBsfImage/GenBsfImage.h633
-rw-r--r--Source/GenBsfImage/build.xml126
-rw-r--r--Source/GenCRC32Section/GenCRC32Section.c286
-rw-r--r--Source/GenCRC32Section/GenCRC32Section.h63
-rw-r--r--Source/GenCRC32Section/build.xml68
-rw-r--r--Source/GenCapsuleHdr/CreateGuid.c50
-rw-r--r--Source/GenCapsuleHdr/GenCapsuleHdr.c2674
-rw-r--r--Source/GenCapsuleHdr/build.xml71
-rw-r--r--Source/GenDepex/DepexParser.c903
-rw-r--r--Source/GenDepex/DepexParser.h26
-rw-r--r--Source/GenDepex/GenDepex.c919
-rw-r--r--Source/GenDepex/GenDepex.h71
-rw-r--r--Source/GenDepex/build.xml67
-rw-r--r--Source/GenFfsFile/GenFfsFile.c2646
-rw-r--r--Source/GenFfsFile/GenFfsFile.h36
-rw-r--r--Source/GenFfsFile/SimpleFileParsing.c969
-rw-r--r--Source/GenFfsFile/build.xml70
-rw-r--r--Source/GenFvImage/Ebc/PeCoffLoaderEx.c57
-rw-r--r--Source/GenFvImage/GenFvImageExe.c299
-rw-r--r--Source/GenFvImage/GenFvImageExe.h98
-rw-r--r--Source/GenFvImage/GenFvImageLib.c2719
-rw-r--r--Source/GenFvImage/GenFvImageLib.h142
-rw-r--r--Source/GenFvImage/GenFvImageLibInternal.h172
-rw-r--r--Source/GenFvImage/build.xml126
-rw-r--r--Source/GenSection/GenSection.c938
-rw-r--r--Source/GenSection/GenSection.h42
-rw-r--r--Source/GenSection/build.xml70
-rw-r--r--Source/GenTEImage/GenTEImage.c916
-rw-r--r--Source/GenTEImage/build.xml71
-rw-r--r--Source/GuidChk/CommonUtils.h57
-rw-r--r--Source/GuidChk/FileSearch.c285
-rw-r--r--Source/GuidChk/FileSearch.h108
-rw-r--r--Source/GuidChk/GuidChk.c2348
-rw-r--r--Source/GuidChk/GuidList.c186
-rw-r--r--Source/GuidChk/UtilsMsgs.c490
-rw-r--r--Source/GuidChk/UtilsMsgs.h106
-rw-r--r--Source/GuidChk/build.xml83
-rw-r--r--Source/Include/Common/BaseTypes.h212
-rw-r--r--Source/Include/Common/Capsule.h67
-rw-r--r--Source/Include/Common/Dependency.h50
-rw-r--r--Source/Include/Common/EfiImage.h716
-rw-r--r--Source/Include/Common/FirmwareFileSystem.h98
-rw-r--r--Source/Include/Common/FirmwareVolumeHeader.h109
-rw-r--r--Source/Include/Common/FirmwareVolumeImageFormat.h277
-rw-r--r--Source/Include/Common/InternalFormRepresentation.h422
-rw-r--r--Source/Include/Common/MultiPhase.h84
-rw-r--r--Source/Include/Common/UefiBaseTypes.h85
-rw-r--r--Source/Include/Common/Variable.h78
-rw-r--r--Source/Include/Common/WorkingBlockHeader.h47
-rw-r--r--Source/Include/Guid/AcpiTableStorage.h30
-rw-r--r--Source/Include/Guid/Apriori.h32
-rw-r--r--Source/Include/Guid/Capsule.h43
-rw-r--r--Source/Include/Guid/FirmwareFileSystem.h40
-rw-r--r--Source/Include/Ia32/ProcessorBind.h167
-rw-r--r--Source/Include/IndustryStandard/pci22.h481
-rw-r--r--Source/Include/Library/PeCoffLib.h131
-rw-r--r--Source/Include/Library/PrintLib.h406
-rw-r--r--Source/Include/Protocol/DevicePath.h94
-rw-r--r--Source/Include/Protocol/GuidedSectionExtraction.h102
-rw-r--r--Source/Include/Protocol/Hii.h1024
-rw-r--r--Source/Include/Protocol/UgaDraw.h168
-rw-r--r--Source/Include/X64/ProcessorBind.h193
-rwxr-xr-xSource/MakeDeps/MakeDeps.c1284
-rwxr-xr-xSource/MakeDeps/build.xml70
-rwxr-xr-xSource/ModifyInf/ModifyInf.c321
-rw-r--r--Source/ModifyInf/build.xml69
-rw-r--r--Source/Pccts/CHANGES_FROM_131.txt522
-rw-r--r--Source/Pccts/CHANGES_FROM_133.txt2448
-rw-r--r--Source/Pccts/CHANGES_FROM_133_BEFORE_MR13.txt3666
-rw-r--r--Source/Pccts/CHANGES_SUMMARY.txt2049
-rw-r--r--Source/Pccts/KNOWN_PROBLEMS.txt241
-rw-r--r--Source/Pccts/MPW_Read_Me21
-rw-r--r--Source/Pccts/NOTES.bcc184
-rw-r--r--Source/Pccts/NOTES.msvc189
-rw-r--r--Source/Pccts/README159
-rw-r--r--Source/Pccts/RIGHTS26
-rw-r--r--Source/Pccts/antlr/AntlrMS.mak233
-rw-r--r--Source/Pccts/antlr/AntlrPPC.mak101
-rw-r--r--Source/Pccts/antlr/README19
-rw-r--r--Source/Pccts/antlr/antlr.1209
-rw-r--r--Source/Pccts/antlr/antlr.c3564
-rw-r--r--Source/Pccts/antlr/antlr.g2586
-rw-r--r--Source/Pccts/antlr/antlr.r787
-rw-r--r--Source/Pccts/antlr/antlr1.txt264
-rw-r--r--Source/Pccts/antlr/bits.c1025
-rw-r--r--Source/Pccts/antlr/build.c813
-rw-r--r--Source/Pccts/antlr/build.xml136
-rw-r--r--Source/Pccts/antlr/dumpcycles.c67
-rw-r--r--Source/Pccts/antlr/dumpnode.c423
-rw-r--r--Source/Pccts/antlr/egman.c328
-rw-r--r--Source/Pccts/antlr/err.c538
-rw-r--r--Source/Pccts/antlr/fcache.c123
-rw-r--r--Source/Pccts/antlr/fset.c1555
-rw-r--r--Source/Pccts/antlr/fset2.c2250
-rw-r--r--Source/Pccts/antlr/gen.c4797
-rw-r--r--Source/Pccts/antlr/generic.h286
-rw-r--r--Source/Pccts/antlr/globals.c484
-rw-r--r--Source/Pccts/antlr/hash.c221
-rw-r--r--Source/Pccts/antlr/hash.h73
-rw-r--r--Source/Pccts/antlr/lex.c878
-rw-r--r--Source/Pccts/antlr/main.c1747
-rw-r--r--Source/Pccts/antlr/makefile218
-rw-r--r--Source/Pccts/antlr/makefile.cygwin219
-rw-r--r--Source/Pccts/antlr/makefile196
-rw-r--r--Source/Pccts/antlr/misc.c1864
-rw-r--r--Source/Pccts/antlr/mode.h12
-rw-r--r--Source/Pccts/antlr/mrhoist.c3030
-rw-r--r--Source/Pccts/antlr/parser.dlg1387
-rw-r--r--Source/Pccts/antlr/pred.c821
-rw-r--r--Source/Pccts/antlr/proto.h852
-rw-r--r--Source/Pccts/antlr/scan.c5735
-rw-r--r--Source/Pccts/antlr/stdpccts.h31
-rw-r--r--Source/Pccts/antlr/syn.h390
-rw-r--r--Source/Pccts/antlr/tokens.h246
-rw-r--r--Source/Pccts/build.xml49
-rw-r--r--Source/Pccts/dlg/DlgMS.mak121
-rw-r--r--Source/Pccts/dlg/DlgPPC.mak84
-rw-r--r--Source/Pccts/dlg/automata.c353
-rw-r--r--Source/Pccts/dlg/build.xml127
-rw-r--r--Source/Pccts/dlg/dlg.179
-rw-r--r--Source/Pccts/dlg/dlg.h250
-rw-r--r--Source/Pccts/dlg/dlg.r275
-rw-r--r--Source/Pccts/dlg/dlg1.txt132
-rw-r--r--Source/Pccts/dlg/dlg_a.c1414
-rw-r--r--Source/Pccts/dlg/dlg_p.c959
-rw-r--r--Source/Pccts/dlg/dlg_p.g614
-rw-r--r--Source/Pccts/dlg/err.c99
-rw-r--r--Source/Pccts/dlg/main.c281
-rw-r--r--Source/Pccts/dlg/makefile156
-rw-r--r--Source/Pccts/dlg/makefile.cygwin157
-rw-r--r--Source/Pccts/dlg/makefile163
-rw-r--r--Source/Pccts/dlg/mode.h4
-rw-r--r--Source/Pccts/dlg/output.c850
-rw-r--r--Source/Pccts/dlg/parser.dlg398
-rw-r--r--Source/Pccts/dlg/relabel.c217
-rw-r--r--Source/Pccts/dlg/stdpccts.h26
-rw-r--r--Source/Pccts/dlg/support.c240
-rw-r--r--Source/Pccts/dlg/tokens.h133
-rw-r--r--Source/Pccts/h/AParser.cpp871
-rw-r--r--Source/Pccts/h/AParser.h376
-rw-r--r--Source/Pccts/h/ASTBase.cpp256
-rw-r--r--Source/Pccts/h/ASTBase.h122
-rw-r--r--Source/Pccts/h/ATokPtr.h88
-rw-r--r--Source/Pccts/h/ATokPtrImpl.h88
-rw-r--r--Source/Pccts/h/AToken.h325
-rw-r--r--Source/Pccts/h/ATokenBuffer.cpp374
-rw-r--r--Source/Pccts/h/ATokenBuffer.h109
-rw-r--r--Source/Pccts/h/ATokenStream.h51
-rw-r--r--Source/Pccts/h/BufFileInput.cpp100
-rw-r--r--Source/Pccts/h/BufFileInput.h53
-rw-r--r--Source/Pccts/h/DLG_stream_input.h98
-rw-r--r--Source/Pccts/h/DLexer.h191
-rw-r--r--Source/Pccts/h/DLexerBase.cpp302
-rw-r--r--Source/Pccts/h/DLexerBase.h198
-rw-r--r--Source/Pccts/h/PBlackBox.h134
-rw-r--r--Source/Pccts/h/PCCTSAST.cpp684
-rw-r--r--Source/Pccts/h/PCCTSAST.h143
-rw-r--r--Source/Pccts/h/SList.h72
-rw-r--r--Source/Pccts/h/antlr.h807
-rw-r--r--Source/Pccts/h/ast.c345
-rw-r--r--Source/Pccts/h/ast.h121
-rw-r--r--Source/Pccts/h/charbuf.h46
-rw-r--r--Source/Pccts/h/charptr.c58
-rw-r--r--Source/Pccts/h/charptr.h48
-rw-r--r--Source/Pccts/h/config.h1
-rw-r--r--Source/Pccts/h/dlgauto.h504
-rw-r--r--Source/Pccts/h/dlgdef.h128
-rw-r--r--Source/Pccts/h/err.h1170
-rw-r--r--Source/Pccts/h/int.h37
-rw-r--r--Source/Pccts/h/pccts_assert.h10
-rw-r--r--Source/Pccts/h/pccts_iostream.h10
-rw-r--r--Source/Pccts/h/pccts_istream.h10
-rw-r--r--Source/Pccts/h/pccts_setjmp.h10
-rw-r--r--Source/Pccts/h/pccts_stdarg.h10
-rw-r--r--Source/Pccts/h/pccts_stdio.h10
-rw-r--r--Source/Pccts/h/pccts_stdlib.h10
-rw-r--r--Source/Pccts/h/pccts_string.h10
-rw-r--r--Source/Pccts/h/pcctscfg.h359
-rw-r--r--Source/Pccts/h/pcnames.bat11
-rw-r--r--Source/Pccts/h/slist.cpp116
-rw-r--r--Source/Pccts/history.ps473
-rw-r--r--Source/Pccts/history.txt186
-rw-r--r--Source/Pccts/makefile66
-rw-r--r--Source/Pccts/support/genmk/genmk.c1063
-rw-r--r--Source/Pccts/support/genmk/genmk_old.c762
-rw-r--r--Source/Pccts/support/genmk/makefile29
-rw-r--r--Source/Pccts/support/rexpr/makefile19
-rw-r--r--Source/Pccts/support/rexpr/rexpr.c586
-rw-r--r--Source/Pccts/support/rexpr/rexpr.h30
-rw-r--r--Source/Pccts/support/rexpr/test.c19
-rw-r--r--Source/Pccts/support/set/set.c816
-rw-r--r--Source/Pccts/support/set/set.h121
-rw-r--r--Source/Pccts/support/sym/sym.c402
-rw-r--r--Source/Pccts/support/sym/template.h41
-rw-r--r--Source/PeCoffLoader/BasePeCoff.c1060
-rw-r--r--Source/PeCoffLoader/Common/EfiImage.h701
-rw-r--r--Source/PeCoffLoader/Ia32/PeCoffLoaderEx.c56
-rw-r--r--Source/PeCoffLoader/Ipf/PeCoffLoaderEx.c249
-rw-r--r--Source/PeCoffLoader/X64/PeCoffLoaderEx.c74
-rw-r--r--Source/PeCoffLoader/build.xml153
-rw-r--r--Source/PeiRebase/PeiRebaseExe.c1059
-rw-r--r--Source/PeiRebase/PeiRebaseExe.h155
-rw-r--r--Source/PeiRebase/build.xml108
-rw-r--r--Source/SecApResetVectorFixup/SecApResetVectorFixup.c363
-rw-r--r--Source/SecApResetVectorFixup/SecApResetVectorFixup.h104
-rw-r--r--Source/SecApResetVectorFixup/build.xml69
-rw-r--r--Source/SecFixup/SecFixup.c362
-rw-r--r--Source/SecFixup/SecFixup.h146
-rw-r--r--Source/SecFixup/build.xml69
-rw-r--r--Source/SetStamp/SetStamp.c475
-rw-r--r--Source/SetStamp/build.xml69
-rw-r--r--Source/SplitFile/SplitFile.c131
-rw-r--r--Source/SplitFile/build.xml68
-rw-r--r--Source/StrGather/StrGather.c2531
-rw-r--r--Source/StrGather/StrGather.h84
-rw-r--r--Source/StrGather/StringDB.c2759
-rw-r--r--Source/StrGather/StringDB.h136
-rw-r--r--Source/StrGather/build.xml71
-rw-r--r--Source/String/PrintLib.c674
-rw-r--r--Source/String/PrintLibInternal.c142
-rw-r--r--Source/String/PrintLibInternal.h101
-rw-r--r--Source/String/String.c732
-rw-r--r--Source/String/build.xml94
-rw-r--r--Source/Strip/Strip.c105
-rw-r--r--Source/Strip/build.xml68
-rw-r--r--Source/TianoTools.msa316
-rw-r--r--Source/VfrCompile/EfiVfr.h181
-rw-r--r--Source/VfrCompile/VfrCompile.g3529
-rw-r--r--Source/VfrCompile/VfrServices.cpp758
-rw-r--r--Source/VfrCompile/VfrServices.h227
-rw-r--r--Source/VfrCompile/build.xml122
-rw-r--r--Source/ZeroDebugData/ZeroDebugData.c391
-rw-r--r--Source/ZeroDebugData/build.xml68
-rw-r--r--Source/build.xml272
281 files changed, 134834 insertions, 0 deletions
diff --git a/Source/Common/CommonLib.c b/Source/Common/CommonLib.c
new file mode 100644
index 0000000..618abd8
--- /dev/null
+++ b/Source/Common/CommonLib.c
@@ -0,0 +1,516 @@
+/*++
+
+Copyright (c) 2004, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ CommonLib.c
+
+Abstract:
+
+ Common Library Functions
+
+--*/
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include "CommonLib.h"
+
+VOID
+PeiZeroMem (
+ IN VOID *Buffer,
+ IN UINTN Size
+ )
+/*++
+
+Routine Description:
+
+ Set Buffer to zero for Size bytes.
+
+Arguments:
+
+ Buffer - Memory to set.
+
+ Size - Number of bytes to set
+
+Returns:
+
+ None
+
+--*/
+{
+ INT8 *Ptr;
+
+ Ptr = Buffer;
+ while (Size--) {
+ *(Ptr++) = 0;
+ }
+}
+
+VOID
+PeiCopyMem (
+ IN VOID *Destination,
+ IN VOID *Source,
+ IN UINTN Length
+ )
+/*++
+
+Routine Description:
+
+ Copy Length bytes from Source to Destination.
+
+Arguments:
+
+ Destination - Target of copy
+
+ Source - Place to copy from
+
+ Length - Number of bytes to copy
+
+Returns:
+
+ None
+
+--*/
+{
+ CHAR8 *Destination8;
+ CHAR8 *Source8;
+
+ Destination8 = Destination;
+ Source8 = Source;
+ while (Length--) {
+ *(Destination8++) = *(Source8++);
+ }
+}
+
+VOID
+ZeroMem (
+ IN VOID *Buffer,
+ IN UINTN Size
+ )
+{
+ PeiZeroMem (Buffer, Size);
+}
+
+VOID
+CopyMem (
+ IN VOID *Destination,
+ IN VOID *Source,
+ IN UINTN Length
+ )
+{
+ PeiCopyMem (Destination, Source, Length);
+}
+
+INTN
+CompareGuid (
+ IN EFI_GUID *Guid1,
+ IN EFI_GUID *Guid2
+ )
+/*++
+
+Routine Description:
+
+ Compares to GUIDs
+
+Arguments:
+
+ Guid1 - guid to compare
+ Guid2 - guid to compare
+
+Returns:
+ = 0 if Guid1 == Guid2
+ != 0 if Guid1 != Guid2
+
+--*/
+{
+ INT32 *g1;
+ INT32 *g2;
+ INT32 r;
+
+ //
+ // Compare 32 bits at a time
+ //
+ g1 = (INT32 *) Guid1;
+ g2 = (INT32 *) Guid2;
+
+ r = g1[0] - g2[0];
+ r |= g1[1] - g2[1];
+ r |= g1[2] - g2[2];
+ r |= g1[3] - g2[3];
+
+ return r;
+}
+
+EFI_STATUS
+GetFileImage (
+ IN CHAR8 *InputFileName,
+ OUT CHAR8 **InputFileImage,
+ OUT UINT32 *BytesRead
+ )
+/*++
+
+Routine Description:
+
+ This function opens a file and reads it into a memory buffer. The function
+ will allocate the memory buffer and returns the size of the buffer.
+
+Arguments:
+
+ InputFileName The name of the file to read.
+ InputFileImage A pointer to the memory buffer.
+ BytesRead The size of the memory buffer.
+
+Returns:
+
+ EFI_SUCCESS The function completed successfully.
+ EFI_INVALID_PARAMETER One of the input parameters was invalid.
+ EFI_ABORTED An error occurred.
+ EFI_OUT_OF_RESOURCES No resource to complete operations.
+
+--*/
+{
+ FILE *InputFile;
+ UINT32 FileSize;
+
+ //
+ // Verify input parameters.
+ //
+ if (InputFileName == NULL || strlen (InputFileName) == 0 || InputFileImage == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // Open the file and copy contents into a memory buffer.
+ //
+ //
+ // Open the file
+ //
+ InputFile = fopen (InputFileName, "rb");
+ if (InputFile == NULL) {
+ printf ("ERROR: Could not open input file \"%s\".\n", InputFileName);
+ return EFI_ABORTED;
+ }
+ //
+ // Go to the end so that we can determine the file size
+ //
+ if (fseek (InputFile, 0, SEEK_END)) {
+ printf ("ERROR: System error reading input file \"%s\".\n", InputFileName);
+ fclose (InputFile);
+ return EFI_ABORTED;
+ }
+ //
+ // Get the file size
+ //
+ FileSize = ftell (InputFile);
+ if (FileSize == -1) {
+ printf ("ERROR: System error parsing input file \"%s\".\n", InputFileName);
+ fclose (InputFile);
+ return EFI_ABORTED;
+ }
+ //
+ // Allocate a buffer
+ //
+ *InputFileImage = malloc (FileSize);
+ if (*InputFileImage == NULL) {
+ fclose (InputFile);
+ return EFI_OUT_OF_RESOURCES;
+ }
+ //
+ // Reset to the beginning of the file
+ //
+ if (fseek (InputFile, 0, SEEK_SET)) {
+ printf ("ERROR: System error reading input file \"%s\".\n", InputFileName);
+ fclose (InputFile);
+ free (*InputFileImage);
+ *InputFileImage = NULL;
+ return EFI_ABORTED;
+ }
+ //
+ // Read all of the file contents.
+ //
+ *BytesRead = fread (*InputFileImage, sizeof (UINT8), FileSize, InputFile);
+ if (*BytesRead != sizeof (UINT8) * FileSize) {
+ printf ("ERROR: Reading file \"%s\"%i.\n", InputFileName);
+ fclose (InputFile);
+ free (*InputFileImage);
+ *InputFileImage = NULL;
+ return EFI_ABORTED;
+ }
+ //
+ // Close the file
+ //
+ fclose (InputFile);
+
+ return EFI_SUCCESS;
+}
+
+UINT8
+CalculateChecksum8 (
+ IN UINT8 *Buffer,
+ IN UINTN Size
+ )
+/*++
+
+Routine Description:
+
+ This function calculates the value needed for a valid UINT8 checksum
+
+Arguments:
+
+ Buffer Pointer to buffer containing byte data of component.
+ Size Size of the buffer
+
+Returns:
+
+ The 8 bit checksum value needed.
+
+--*/
+{
+ return (UINT8) (0x100 - CalculateSum8 (Buffer, Size));
+}
+
+UINT8
+CalculateSum8 (
+ IN UINT8 *Buffer,
+ IN UINTN Size
+ )
+/*++
+
+Routine Description::
+
+ This function calculates the UINT8 sum for the requested region.
+
+Arguments:
+
+ Buffer Pointer to buffer containing byte data of component.
+ Size Size of the buffer
+
+Returns:
+
+ The 8 bit checksum value needed.
+
+--*/
+{
+ UINTN Index;
+ UINT8 Sum;
+
+ Sum = 0;
+
+ //
+ // Perform the byte sum for buffer
+ //
+ for (Index = 0; Index < Size; Index++) {
+ Sum = (UINT8) (Sum + Buffer[Index]);
+ }
+
+ return Sum;
+}
+
+UINT16
+CalculateChecksum16 (
+ IN UINT16 *Buffer,
+ IN UINTN Size
+ )
+/*++
+
+Routine Description::
+
+ This function calculates the value needed for a valid UINT16 checksum
+
+Arguments:
+
+ Buffer Pointer to buffer containing byte data of component.
+ Size Size of the buffer
+
+Returns:
+
+ The 16 bit checksum value needed.
+
+--*/
+{
+ return (UINT16) (0x10000 - CalculateSum16 (Buffer, Size));
+}
+
+UINT16
+CalculateSum16 (
+ IN UINT16 *Buffer,
+ IN UINTN Size
+ )
+/*++
+
+Routine Description:
+
+ This function calculates the UINT16 sum for the requested region.
+
+Arguments:
+
+ Buffer Pointer to buffer containing byte data of component.
+ Size Size of the buffer
+
+Returns:
+
+ The 16 bit checksum
+
+--*/
+{
+ UINTN Index;
+ UINT16 Sum;
+
+ Sum = 0;
+
+ //
+ // Perform the word sum for buffer
+ //
+ for (Index = 0; Index < Size; Index++) {
+ Sum = (UINT16) (Sum + Buffer[Index]);
+ }
+
+ return (UINT16) Sum;
+}
+
+EFI_STATUS
+PrintGuid (
+ IN EFI_GUID *Guid
+ )
+/*++
+
+Routine Description:
+
+ This function prints a GUID to STDOUT.
+
+Arguments:
+
+ Guid Pointer to a GUID to print.
+
+Returns:
+
+ EFI_SUCCESS The GUID was printed.
+ EFI_INVALID_PARAMETER The input was NULL.
+
+--*/
+{
+ if (Guid == NULL) {
+ printf ("ERROR: PrintGuid called with a NULL value.\n");
+ return EFI_INVALID_PARAMETER;
+ }
+
+ printf (
+ "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x\n",
+ Guid->Data1,
+ Guid->Data2,
+ Guid->Data3,
+ Guid->Data4[0],
+ Guid->Data4[1],
+ Guid->Data4[2],
+ Guid->Data4[3],
+ Guid->Data4[4],
+ Guid->Data4[5],
+ Guid->Data4[6],
+ Guid->Data4[7]
+ );
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+PrintGuidToBuffer (
+ IN EFI_GUID *Guid,
+ IN OUT UINT8 *Buffer,
+ IN UINT32 BufferLen,
+ IN BOOLEAN Uppercase
+ )
+/*++
+
+Routine Description:
+
+ This function prints a GUID to a buffer
+
+Arguments:
+
+ Guid - Pointer to a GUID to print.
+ Buffer - Pointer to a user-provided buffer to print to
+ BufferLen - Size of the Buffer
+ Uppercase - If use upper case.
+
+Returns:
+
+ EFI_SUCCESS The GUID was printed.
+ EFI_INVALID_PARAMETER The input was NULL.
+ EFI_BUFFER_TOO_SMALL The input buffer was not big enough
+
+--*/
+{
+ if (Guid == NULL) {
+ printf ("ERROR: PrintGuidToBuffer() called with a NULL value\n");
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (BufferLen < PRINTED_GUID_BUFFER_SIZE) {
+ printf ("ERORR: PrintGuidToBuffer() called with invalid buffer size\n");
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ if (Uppercase) {
+ sprintf (
+ Buffer,
+ "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X",
+ Guid->Data1,
+ Guid->Data2,
+ Guid->Data3,
+ Guid->Data4[0],
+ Guid->Data4[1],
+ Guid->Data4[2],
+ Guid->Data4[3],
+ Guid->Data4[4],
+ Guid->Data4[5],
+ Guid->Data4[6],
+ Guid->Data4[7]
+ );
+ } else {
+ sprintf (
+ Buffer,
+ "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
+ Guid->Data1,
+ Guid->Data2,
+ Guid->Data3,
+ Guid->Data4[0],
+ Guid->Data4[1],
+ Guid->Data4[2],
+ Guid->Data4[3],
+ Guid->Data4[4],
+ Guid->Data4[5],
+ Guid->Data4[6],
+ Guid->Data4[7]
+ );
+ }
+
+ return EFI_SUCCESS;
+}
+
+#ifdef __GNUC__
+
+size_t _filelength(FILE *file)
+{
+ struct stat stat_buf;
+ fstat(fileno(file), &stat_buf);
+ return stat_buf.st_size;
+}
+
+#ifndef __CYGWIN__
+char *strlwr(char *s)
+{
+ char *p = s;
+ for(;*s;s++) {
+ *s = tolower(*s);
+ }
+ return p;
+}
+#endif
+#endif
diff --git a/Source/Common/CommonLib.h b/Source/Common/CommonLib.h
new file mode 100644
index 0000000..f6c29ef
--- /dev/null
+++ b/Source/Common/CommonLib.h
@@ -0,0 +1,139 @@
+/*++
+
+Copyright (c) 2004, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ CommonLib.h
+
+Abstract:
+
+ Common library assistance routines.
+
+--*/
+
+#ifndef _EFI_COMMON_LIB_H
+#define _EFI_COMMON_LIB_H
+
+#include <Common/UefiBaseTypes.h>
+
+#ifndef _MAX_PATH
+#define _MAX_PATH 500
+#endif
+
+#define PRINTED_GUID_BUFFER_SIZE 37 // including null-termination
+//
+// Function declarations
+//
+VOID
+PeiZeroMem (
+ IN VOID *Buffer,
+ IN UINTN Size
+ )
+;
+
+VOID
+PeiCopyMem (
+ IN VOID *Destination,
+ IN VOID *Source,
+ IN UINTN Length
+ )
+;
+
+VOID
+ZeroMem (
+ IN VOID *Buffer,
+ IN UINTN Size
+ )
+;
+
+VOID
+CopyMem (
+ IN VOID *Destination,
+ IN VOID *Source,
+ IN UINTN Length
+ )
+;
+
+INTN
+CompareGuid (
+ IN EFI_GUID *Guid1,
+ IN EFI_GUID *Guid2
+ )
+;
+
+EFI_STATUS
+GetFileImage (
+ IN CHAR8 *InputFileName,
+ OUT CHAR8 **InputFileImage,
+ OUT UINT32 *BytesRead
+ )
+;
+
+UINT8
+CalculateChecksum8 (
+ IN UINT8 *Buffer,
+ IN UINTN Size
+ )
+;
+
+UINT8
+CalculateSum8 (
+ IN UINT8 *Buffer,
+ IN UINTN Size
+ )
+;
+
+UINT16
+CalculateChecksum16 (
+ IN UINT16 *Buffer,
+ IN UINTN Size
+ )
+;
+
+UINT16
+CalculateSum16 (
+ IN UINT16 *Buffer,
+ IN UINTN Size
+ )
+;
+
+EFI_STATUS
+PrintGuid (
+ IN EFI_GUID *Guid
+ )
+;
+
+#define PRINTED_GUID_BUFFER_SIZE 37 // including null-termination
+EFI_STATUS
+PrintGuidToBuffer (
+ IN EFI_GUID *Guid,
+ IN OUT UINT8 *Buffer,
+ IN UINT32 BufferLen,
+ IN BOOLEAN Uppercase
+ )
+;
+
+#define ASSERT(x) assert(x)
+
+#ifdef __GNUC__
+#include <stdio.h>
+#include <sys/stat.h>
+#define stricmp strcasecmp
+#define _stricmp strcasecmp
+#define strnicmp strncasecmp
+#define strcmpi strcasecmp
+size_t _filelength(FILE *file);
+#ifndef __CYGWIN__
+char *strlwr(char *s);
+#endif
+#endif
+
+#endif
diff --git a/Source/Common/Crc32.c b/Source/Common/Crc32.c
new file mode 100644
index 0000000..4ae5eb4
--- /dev/null
+++ b/Source/Common/Crc32.c
@@ -0,0 +1,326 @@
+/*++
+
+Copyright (c) 2004, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ crc32.c
+
+Abstract:
+
+ CalcuateCrc32 routine.
+
+--*/
+
+#include <stdlib.h>
+#include "Crc32.h"
+
+UINT32 mCrcTable[256] = {
+ 0x00000000,
+ 0x77073096,
+ 0xEE0E612C,
+ 0x990951BA,
+ 0x076DC419,
+ 0x706AF48F,
+ 0xE963A535,
+ 0x9E6495A3,
+ 0x0EDB8832,
+ 0x79DCB8A4,
+ 0xE0D5E91E,
+ 0x97D2D988,
+ 0x09B64C2B,
+ 0x7EB17CBD,
+ 0xE7B82D07,
+ 0x90BF1D91,
+ 0x1DB71064,
+ 0x6AB020F2,
+ 0xF3B97148,
+ 0x84BE41DE,
+ 0x1ADAD47D,
+ 0x6DDDE4EB,
+ 0xF4D4B551,
+ 0x83D385C7,
+ 0x136C9856,
+ 0x646BA8C0,
+ 0xFD62F97A,
+ 0x8A65C9EC,
+ 0x14015C4F,
+ 0x63066CD9,
+ 0xFA0F3D63,
+ 0x8D080DF5,
+ 0x3B6E20C8,
+ 0x4C69105E,
+ 0xD56041E4,
+ 0xA2677172,
+ 0x3C03E4D1,
+ 0x4B04D447,
+ 0xD20D85FD,
+ 0xA50AB56B,
+ 0x35B5A8FA,
+ 0x42B2986C,
+ 0xDBBBC9D6,
+ 0xACBCF940,
+ 0x32D86CE3,
+ 0x45DF5C75,
+ 0xDCD60DCF,
+ 0xABD13D59,
+ 0x26D930AC,
+ 0x51DE003A,
+ 0xC8D75180,
+ 0xBFD06116,
+ 0x21B4F4B5,
+ 0x56B3C423,
+ 0xCFBA9599,
+ 0xB8BDA50F,
+ 0x2802B89E,
+ 0x5F058808,
+ 0xC60CD9B2,
+ 0xB10BE924,
+ 0x2F6F7C87,
+ 0x58684C11,
+ 0xC1611DAB,
+ 0xB6662D3D,
+ 0x76DC4190,
+ 0x01DB7106,
+ 0x98D220BC,
+ 0xEFD5102A,
+ 0x71B18589,
+ 0x06B6B51F,
+ 0x9FBFE4A5,
+ 0xE8B8D433,
+ 0x7807C9A2,
+ 0x0F00F934,
+ 0x9609A88E,
+ 0xE10E9818,
+ 0x7F6A0DBB,
+ 0x086D3D2D,
+ 0x91646C97,
+ 0xE6635C01,
+ 0x6B6B51F4,
+ 0x1C6C6162,
+ 0x856530D8,
+ 0xF262004E,
+ 0x6C0695ED,
+ 0x1B01A57B,
+ 0x8208F4C1,
+ 0xF50FC457,
+ 0x65B0D9C6,
+ 0x12B7E950,
+ 0x8BBEB8EA,
+ 0xFCB9887C,
+ 0x62DD1DDF,
+ 0x15DA2D49,
+ 0x8CD37CF3,
+ 0xFBD44C65,
+ 0x4DB26158,
+ 0x3AB551CE,
+ 0xA3BC0074,
+ 0xD4BB30E2,
+ 0x4ADFA541,
+ 0x3DD895D7,
+ 0xA4D1C46D,
+ 0xD3D6F4FB,
+ 0x4369E96A,
+ 0x346ED9FC,
+ 0xAD678846,
+ 0xDA60B8D0,
+ 0x44042D73,
+ 0x33031DE5,
+ 0xAA0A4C5F,
+ 0xDD0D7CC9,
+ 0x5005713C,
+ 0x270241AA,
+ 0xBE0B1010,
+ 0xC90C2086,
+ 0x5768B525,
+ 0x206F85B3,
+ 0xB966D409,
+ 0xCE61E49F,
+ 0x5EDEF90E,
+ 0x29D9C998,
+ 0xB0D09822,
+ 0xC7D7A8B4,
+ 0x59B33D17,
+ 0x2EB40D81,
+ 0xB7BD5C3B,
+ 0xC0BA6CAD,
+ 0xEDB88320,
+ 0x9ABFB3B6,
+ 0x03B6E20C,
+ 0x74B1D29A,
+ 0xEAD54739,
+ 0x9DD277AF,
+ 0x04DB2615,
+ 0x73DC1683,
+ 0xE3630B12,
+ 0x94643B84,
+ 0x0D6D6A3E,
+ 0x7A6A5AA8,
+ 0xE40ECF0B,
+ 0x9309FF9D,
+ 0x0A00AE27,
+ 0x7D079EB1,
+ 0xF00F9344,
+ 0x8708A3D2,
+ 0x1E01F268,
+ 0x6906C2FE,
+ 0xF762575D,
+ 0x806567CB,
+ 0x196C3671,
+ 0x6E6B06E7,
+ 0xFED41B76,
+ 0x89D32BE0,
+ 0x10DA7A5A,
+ 0x67DD4ACC,
+ 0xF9B9DF6F,
+ 0x8EBEEFF9,
+ 0x17B7BE43,
+ 0x60B08ED5,
+ 0xD6D6A3E8,
+ 0xA1D1937E,
+ 0x38D8C2C4,
+ 0x4FDFF252,
+ 0xD1BB67F1,
+ 0xA6BC5767,
+ 0x3FB506DD,
+ 0x48B2364B,
+ 0xD80D2BDA,
+ 0xAF0A1B4C,
+ 0x36034AF6,
+ 0x41047A60,
+ 0xDF60EFC3,
+ 0xA867DF55,
+ 0x316E8EEF,
+ 0x4669BE79,
+ 0xCB61B38C,
+ 0xBC66831A,
+ 0x256FD2A0,
+ 0x5268E236,
+ 0xCC0C7795,
+ 0xBB0B4703,
+ 0x220216B9,
+ 0x5505262F,
+ 0xC5BA3BBE,
+ 0xB2BD0B28,
+ 0x2BB45A92,
+ 0x5CB36A04,
+ 0xC2D7FFA7,
+ 0xB5D0CF31,
+ 0x2CD99E8B,
+ 0x5BDEAE1D,
+ 0x9B64C2B0,
+ 0xEC63F226,
+ 0x756AA39C,
+ 0x026D930A,
+ 0x9C0906A9,
+ 0xEB0E363F,
+ 0x72076785,
+ 0x05005713,
+ 0x95BF4A82,
+ 0xE2B87A14,
+ 0x7BB12BAE,
+ 0x0CB61B38,
+ 0x92D28E9B,
+ 0xE5D5BE0D,
+ 0x7CDCEFB7,
+ 0x0BDBDF21,
+ 0x86D3D2D4,
+ 0xF1D4E242,
+ 0x68DDB3F8,
+ 0x1FDA836E,
+ 0x81BE16CD,
+ 0xF6B9265B,
+ 0x6FB077E1,
+ 0x18B74777,
+ 0x88085AE6,
+ 0xFF0F6A70,
+ 0x66063BCA,
+ 0x11010B5C,
+ 0x8F659EFF,
+ 0xF862AE69,
+ 0x616BFFD3,
+ 0x166CCF45,
+ 0xA00AE278,
+ 0xD70DD2EE,
+ 0x4E048354,
+ 0x3903B3C2,
+ 0xA7672661,
+ 0xD06016F7,
+ 0x4969474D,
+ 0x3E6E77DB,
+ 0xAED16A4A,
+ 0xD9D65ADC,
+ 0x40DF0B66,
+ 0x37D83BF0,
+ 0xA9BCAE53,
+ 0xDEBB9EC5,
+ 0x47B2CF7F,
+ 0x30B5FFE9,
+ 0xBDBDF21C,
+ 0xCABAC28A,
+ 0x53B39330,
+ 0x24B4A3A6,
+ 0xBAD03605,
+ 0xCDD70693,
+ 0x54DE5729,
+ 0x23D967BF,
+ 0xB3667A2E,
+ 0xC4614AB8,
+ 0x5D681B02,
+ 0x2A6F2B94,
+ 0xB40BBE37,
+ 0xC30C8EA1,
+ 0x5A05DF1B,
+ 0x2D02EF8D
+};
+
+EFI_STATUS
+CalculateCrc32 (
+ IN UINT8 *Data,
+ IN UINTN DataSize,
+ IN OUT UINT32 *CrcOut
+ )
+/*++
+
+Routine Description:
+
+ The CalculateCrc32 routine.
+
+Arguments:
+
+ Data - The buffer contaning the data to be processed
+ DataSize - The size of data to be processed
+ CrcOut - A pointer to the caller allocated UINT32 that on
+ contains the CRC32 checksum of Data
+
+Returns:
+
+ EFI_SUCCESS - Calculation is successful.
+ EFI_INVALID_PARAMETER - Data / CrcOut = NULL, or DataSize = 0
+
+--*/
+{
+ UINT32 Crc;
+ UINTN Index;
+ UINT8 *Ptr;
+
+ if ((DataSize == 0) || (Data == NULL) || (CrcOut == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Crc = 0xffffffff;
+ for (Index = 0, Ptr = Data; Index < DataSize; Index++, Ptr++) {
+ Crc = (Crc >> 8) ^ mCrcTable[(UINT8) Crc ^ *Ptr];
+ }
+
+ *CrcOut = Crc ^ 0xffffffff;
+
+ return EFI_SUCCESS;
+}
diff --git a/Source/Common/Crc32.h b/Source/Common/Crc32.h
new file mode 100644
index 0000000..ec48cdd
--- /dev/null
+++ b/Source/Common/Crc32.h
@@ -0,0 +1,54 @@
+/*++
+
+Copyright (c) 2004, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ Crc32.h
+
+Abstract:
+
+ Header file for CalcuateCrc32 routine
+
+--*/
+
+#ifndef _CRC32_H
+#define _CRC32_H
+
+#include <Common/UefiBaseTypes.h>
+
+EFI_STATUS
+CalculateCrc32 (
+ IN UINT8 *Data,
+ IN UINTN DataSize,
+ IN OUT UINT32 *CrcOut
+ )
+/*++
+
+Routine Description:
+
+ The CalculateCrc32 routine.
+
+Arguments:
+
+ Data - The buffer contaning the data to be processed
+ DataSize - The size of data to be processed
+ CrcOut - A pointer to the caller allocated UINT32 that on
+ contains the CRC32 checksum of Data
+
+Returns:
+
+ EFI_SUCCESS - Calculation is successful.
+ EFI_INVALID_PARAMETER - Data / CrcOut = NULL, or DataSize = 0
+
+--*/
+;
+
+#endif
diff --git a/Source/Common/EfiCompress.c b/Source/Common/EfiCompress.c
new file mode 100644
index 0000000..5b91b1d
--- /dev/null
+++ b/Source/Common/EfiCompress.c
@@ -0,0 +1,1742 @@
+/*++
+
+Copyright (c) 2004, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ EfiCompress.c
+
+Abstract:
+
+ Compression routine. The compression algorithm is a mixture of
+ LZ77 and Huffman coding. LZ77 transforms the source data into a
+ sequence of Original Characters and Pointers to repeated strings.
+ This sequence is further divided into Blocks and Huffman codings
+ are applied to each Block.
+
+--*/
+
+#include "EfiCompress.h"
+
+//
+// Macro Definitions
+//
+typedef INT32 NODE;
+#define UINT8_BIT 8
+#define THRESHOLD 3
+#define INIT_CRC 0
+#define WNDBIT 19
+#define WNDSIZ (1U << WNDBIT)
+#define MAXMATCH 256
+#define BLKSIZ (1U << 14) // 16 * 1024U
+#define PERC_FLAG 0x80000000U
+#define CODE_BIT 16
+#define NIL 0
+#define MAX_HASH_VAL (3 * WNDSIZ + (WNDSIZ / 512 + 1) * UINT8_MAX)
+#define HASH(p, c) ((p) + ((c) << (WNDBIT - 9)) + WNDSIZ * 2)
+#define CRCPOLY 0xA001
+#define UPDATE_CRC(c) mCrc = mCrcTable[(mCrc ^ (c)) & 0xFF] ^ (mCrc >> UINT8_BIT)
+
+//
+// C: the Char&Len Set; P: the Position Set; T: the exTra Set
+//
+#define NC (UINT8_MAX + MAXMATCH + 2 - THRESHOLD)
+#define CBIT 9
+#define NP (WNDBIT + 1)
+#define PBIT 5
+#define NT (CODE_BIT + 3)
+#define TBIT 5
+#if NT > NP
+#define NPT NT
+#else
+#define NPT NP
+#endif
+//
+// Function Prototypes
+//
+STATIC VOID PutDword(IN UINT32 Data);
+
+STATIC
+EFI_STATUS
+AllocateMemory (
+ VOID
+ );
+
+STATIC
+VOID
+FreeMemory (
+ VOID
+ );
+
+STATIC
+VOID
+InitSlide (
+ VOID
+ );
+
+STATIC
+NODE
+Child (
+ IN NODE NodeQ,
+ IN UINT8 CharC
+ );
+
+STATIC
+VOID
+MakeChild (
+ IN NODE NodeQ,
+ IN UINT8 CharC,
+ IN NODE NodeR
+ );
+
+STATIC
+VOID
+Split (
+ IN NODE Old
+ );
+
+STATIC
+VOID
+InsertNode (
+ VOID
+ );
+
+STATIC
+VOID
+DeleteNode (
+ VOID
+ );
+
+STATIC
+VOID
+GetNextMatch (
+ VOID
+ );
+
+STATIC
+EFI_STATUS
+Encode (
+ VOID
+ );
+
+STATIC
+VOID
+CountTFreq (
+ VOID
+ );
+
+STATIC
+VOID
+WritePTLen (
+ IN INT32 Number,
+ IN INT32 nbit,
+ IN INT32 Special
+ );
+
+STATIC
+VOID
+WriteCLen (
+ VOID
+ );
+
+STATIC
+VOID
+EncodeC (
+ IN INT32 Value
+ );
+
+STATIC
+VOID
+EncodeP (
+ IN UINT32 Value
+ );
+
+STATIC
+VOID
+SendBlock (
+ VOID
+ );
+
+STATIC
+VOID
+Output (
+ IN UINT32 c,
+ IN UINT32 p
+ );
+
+STATIC
+VOID
+HufEncodeStart (
+ VOID
+ );
+
+STATIC
+VOID
+HufEncodeEnd (
+ VOID
+ );
+
+STATIC
+VOID
+MakeCrcTable (
+ VOID
+ );
+
+STATIC
+VOID
+PutBits (
+ IN INT32 Number,
+ IN UINT32 Value
+ );
+
+STATIC
+INT32
+FreadCrc (
+ OUT UINT8 *Pointer,
+ IN INT32 Number
+ );
+
+STATIC
+VOID
+InitPutBits (
+ VOID
+ );
+
+STATIC
+VOID
+CountLen (
+ IN INT32 Index
+ );
+
+STATIC
+VOID
+MakeLen (
+ IN INT32 Root
+ );
+
+STATIC
+VOID
+DownHeap (
+ IN INT32 Index
+ );
+
+STATIC
+VOID
+MakeCode (
+ IN INT32 Number,
+ IN UINT8 Len[ ],
+ OUT UINT16 Code[]
+ );
+
+STATIC
+INT32
+MakeTree (
+ IN INT32 NParm,
+ IN UINT16 FreqParm[],
+ OUT UINT8 LenParm[ ],
+ OUT UINT16 CodeParm[]
+ );
+
+//
+// Global Variables
+//
+static UINT8 *mSrc, *mDst, *mSrcUpperLimit, *mDstUpperLimit;
+
+static UINT8 *mLevel, *mText, *mChildCount, *mBuf, mCLen[NC], mPTLen[NPT], *mLen;
+static INT16 mHeap[NC + 1];
+static INT32 mRemainder, mMatchLen, mBitCount, mHeapSize, mN;
+static UINT32 mBufSiz = 0, mOutputPos, mOutputMask, mSubBitBuf, mCrc;
+static UINT32 mCompSize, mOrigSize;
+
+static UINT16 *mFreq, *mSortPtr, mLenCnt[17], mLeft[2 * NC - 1], mRight[2 * NC - 1], mCrcTable[UINT8_MAX + 1],
+ mCFreq[2 * NC - 1], mCTable[4096], mCCode[NC], mPFreq[2 * NP - 1], mPTCode[NPT], mTFreq[2 * NT - 1];
+
+static NODE mPos, mMatchPos, mAvail, *mPosition, *mParent, *mPrev, *mNext = NULL;
+
+//
+// functions
+//
+EFI_STATUS
+Compress (
+ IN UINT8 *SrcBuffer,
+ IN UINT32 SrcSize,
+ IN UINT8 *DstBuffer,
+ IN OUT UINT32 *DstSize
+ )
+/*++
+
+Routine Description:
+
+ The main compression routine.
+
+Arguments:
+
+ SrcBuffer - The buffer storing the source data
+ SrcSize - The size of source data
+ DstBuffer - The buffer to store the compressed data
+ DstSize - On input, the size of DstBuffer; On output,
+ the size of the actual compressed data.
+
+Returns:
+
+ EFI_BUFFER_TOO_SMALL - The DstBuffer is too small. In this case,
+ DstSize contains the size needed.
+ EFI_SUCCESS - Compression is successful.
+ EFI_OUT_OF_RESOURCES - No resource to complete function.
+
+--*/
+{
+ EFI_STATUS Status;
+
+ //
+ // Initializations
+ //
+ mBufSiz = 0;
+ mBuf = NULL;
+ mText = NULL;
+ mLevel = NULL;
+ mChildCount = NULL;
+ mPosition = NULL;
+ mParent = NULL;
+ mPrev = NULL;
+ mNext = NULL;
+
+ mSrc = SrcBuffer;
+ mSrcUpperLimit = mSrc + SrcSize;
+ mDst = DstBuffer;
+ mDstUpperLimit = mDst +*DstSize;
+
+ PutDword (0L);
+ PutDword (0L);
+
+ MakeCrcTable ();
+
+ mOrigSize = mCompSize = 0;
+ mCrc = INIT_CRC;
+
+ //
+ // Compress it
+ //
+ Status = Encode ();
+ if (EFI_ERROR (Status)) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ //
+ // Null terminate the compressed data
+ //
+ if (mDst < mDstUpperLimit) {
+ *mDst++ = 0;
+ }
+ //
+ // Fill in compressed size and original size
+ //
+ mDst = DstBuffer;
+ PutDword (mCompSize + 1);
+ PutDword (mOrigSize);
+
+ //
+ // Return
+ //
+ if (mCompSize + 1 + 8 > *DstSize) {
+ *DstSize = mCompSize + 1 + 8;
+ return EFI_BUFFER_TOO_SMALL;
+ } else {
+ *DstSize = mCompSize + 1 + 8;
+ return EFI_SUCCESS;
+ }
+
+}
+
+STATIC
+VOID
+PutDword (
+ IN UINT32 Data
+ )
+/*++
+
+Routine Description:
+
+ Put a dword to output stream
+
+Arguments:
+
+ Data - the dword to put
+
+Returns: (VOID)
+
+--*/
+{
+ if (mDst < mDstUpperLimit) {
+ *mDst++ = (UINT8) (((UINT8) (Data)) & 0xff);
+ }
+
+ if (mDst < mDstUpperLimit) {
+ *mDst++ = (UINT8) (((UINT8) (Data >> 0x08)) & 0xff);
+ }
+
+ if (mDst < mDstUpperLimit) {
+ *mDst++ = (UINT8) (((UINT8) (Data >> 0x10)) & 0xff);
+ }
+
+ if (mDst < mDstUpperLimit) {
+ *mDst++ = (UINT8) (((UINT8) (Data >> 0x18)) & 0xff);
+ }
+}
+
+STATIC
+EFI_STATUS
+AllocateMemory (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Allocate memory spaces for data structures used in compression process
+
+Argements:
+ VOID
+
+Returns:
+
+ EFI_SUCCESS - Memory is allocated successfully
+ EFI_OUT_OF_RESOURCES - Allocation fails
+
+--*/
+{
+ UINT32 Index;
+
+ mText = malloc (WNDSIZ * 2 + MAXMATCH);
+ for (Index = 0; Index < WNDSIZ * 2 + MAXMATCH; Index++) {
+ mText[Index] = 0;
+ }
+
+ mLevel = malloc ((WNDSIZ + UINT8_MAX + 1) * sizeof (*mLevel));
+ mChildCount = malloc ((WNDSIZ + UINT8_MAX + 1) * sizeof (*mChildCount));
+ mPosition = malloc ((WNDSIZ + UINT8_MAX + 1) * sizeof (*mPosition));
+ mParent = malloc (WNDSIZ * 2 * sizeof (*mParent));
+ mPrev = malloc (WNDSIZ * 2 * sizeof (*mPrev));
+ mNext = malloc ((MAX_HASH_VAL + 1) * sizeof (*mNext));
+
+ mBufSiz = BLKSIZ;
+ mBuf = malloc (mBufSiz);
+ while (mBuf == NULL) {
+ mBufSiz = (mBufSiz / 10U) * 9U;
+ if (mBufSiz < 4 * 1024U) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ mBuf = malloc (mBufSiz);
+ }
+
+ mBuf[0] = 0;
+
+ return EFI_SUCCESS;
+}
+
+VOID
+FreeMemory (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Called when compression is completed to free memory previously allocated.
+
+Arguments: (VOID)
+
+Returns: (VOID)
+
+--*/
+{
+ if (mText != NULL) {
+ free (mText);
+ }
+
+ if (mLevel != NULL) {
+ free (mLevel);
+ }
+
+ if (mChildCount != NULL) {
+ free (mChildCount);
+ }
+
+ if (mPosition != NULL) {
+ free (mPosition);
+ }
+
+ if (mParent != NULL) {
+ free (mParent);
+ }
+
+ if (mPrev != NULL) {
+ free (mPrev);
+ }
+
+ if (mNext != NULL) {
+ free (mNext);
+ }
+
+ if (mBuf != NULL) {
+ free (mBuf);
+ }
+
+ return ;
+}
+
+STATIC
+VOID
+InitSlide (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Initialize String Info Log data structures
+
+Arguments: (VOID)
+
+Returns: (VOID)
+
+--*/
+{
+ NODE Index;
+
+ for (Index = WNDSIZ; Index <= WNDSIZ + UINT8_MAX; Index++) {
+ mLevel[Index] = 1;
+ mPosition[Index] = NIL; /* sentinel */
+ }
+
+ for (Index = WNDSIZ; Index < WNDSIZ * 2; Index++) {
+ mParent[Index] = NIL;
+ }
+
+ mAvail = 1;
+ for (Index = 1; Index < WNDSIZ - 1; Index++) {
+ mNext[Index] = (NODE) (Index + 1);
+ }
+
+ mNext[WNDSIZ - 1] = NIL;
+ for (Index = WNDSIZ * 2; Index <= MAX_HASH_VAL; Index++) {
+ mNext[Index] = NIL;
+ }
+}
+
+STATIC
+NODE
+Child (
+ IN NODE NodeQ,
+ IN UINT8 CharC
+ )
+/*++
+
+Routine Description:
+
+ Find child node given the parent node and the edge character
+
+Arguments:
+
+ NodeQ - the parent node
+ CharC - the edge character
+
+Returns:
+
+ The child node (NIL if not found)
+
+--*/
+{
+ NODE NodeR;
+
+ NodeR = mNext[HASH (NodeQ, CharC)];
+ //
+ // sentinel
+ //
+ mParent[NIL] = NodeQ;
+ while (mParent[NodeR] != NodeQ) {
+ NodeR = mNext[NodeR];
+ }
+
+ return NodeR;
+}
+
+STATIC
+VOID
+MakeChild (
+ IN NODE Parent,
+ IN UINT8 CharC,
+ IN NODE Child
+ )
+/*++
+
+Routine Description:
+
+ Create a new child for a given parent node.
+
+Arguments:
+
+ Parent - the parent node
+ CharC - the edge character
+ Child - the child node
+
+Returns: (VOID)
+
+--*/
+{
+ NODE Node1;
+ NODE Node2;
+
+ Node1 = (NODE) HASH (Parent, CharC);
+ Node2 = mNext[Node1];
+ mNext[Node1] = Child;
+ mNext[Child] = Node2;
+ mPrev[Node2] = Child;
+ mPrev[Child] = Node1;
+ mParent[Child] = Parent;
+ mChildCount[Parent]++;
+}
+
+STATIC
+VOID
+Split (
+ NODE Old
+ )
+/*++
+
+Routine Description:
+
+ Split a node.
+
+Arguments:
+
+ Old - the node to split
+
+Returns: (VOID)
+
+--*/
+{
+ NODE New;
+ NODE TempNode;
+
+ New = mAvail;
+ mAvail = mNext[New];
+ mChildCount[New] = 0;
+ TempNode = mPrev[Old];
+ mPrev[New] = TempNode;
+ mNext[TempNode] = New;
+ TempNode = mNext[Old];
+ mNext[New] = TempNode;
+ mPrev[TempNode] = New;
+ mParent[New] = mParent[Old];
+ mLevel[New] = (UINT8) mMatchLen;
+ mPosition[New] = mPos;
+ MakeChild (New, mText[mMatchPos + mMatchLen], Old);
+ MakeChild (New, mText[mPos + mMatchLen], mPos);
+}
+
+STATIC
+VOID
+InsertNode (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Insert string info for current position into the String Info Log
+
+Arguments: (VOID)
+
+Returns: (VOID)
+
+--*/
+{
+ NODE NodeQ;
+ NODE NodeR;
+ NODE Index2;
+ NODE NodeT;
+ UINT8 CharC;
+ UINT8 *t1;
+ UINT8 *t2;
+
+ if (mMatchLen >= 4) {
+ //
+ // We have just got a long match, the target tree
+ // can be located by MatchPos + 1. Travese the tree
+ // from bottom up to get to a proper starting point.
+ // The usage of PERC_FLAG ensures proper node deletion
+ // in DeleteNode() later.
+ //
+ mMatchLen--;
+ NodeR = (NODE) ((mMatchPos + 1) | WNDSIZ);
+ NodeQ = mParent[NodeR];
+ while (NodeQ == NIL) {
+ NodeR = mNext[NodeR];
+ NodeQ = mParent[NodeR];
+ }
+
+ while (mLevel[NodeQ] >= mMatchLen) {
+ NodeR = NodeQ;
+ NodeQ = mParent[NodeQ];
+ }
+
+ NodeT = NodeQ;
+ while (mPosition[NodeT] < 0) {
+ mPosition[NodeT] = mPos;
+ NodeT = mParent[NodeT];
+ }
+
+ if (NodeT < WNDSIZ) {
+ mPosition[NodeT] = (NODE) (mPos | (UINT32) PERC_FLAG);
+ }
+ } else {
+ //
+ // Locate the target tree
+ //
+ NodeQ = (NODE) (mText[mPos] + WNDSIZ);
+ CharC = mText[mPos + 1];
+ NodeR = Child (NodeQ, CharC);
+ if (NodeR == NIL) {
+ MakeChild (NodeQ, CharC, mPos);
+ mMatchLen = 1;
+ return ;
+ }
+
+ mMatchLen = 2;
+ }
+ //
+ // Traverse down the tree to find a match.
+ // Update Position value along the route.
+ // Node split or creation is involved.
+ //
+ for (;;) {
+ if (NodeR >= WNDSIZ) {
+ Index2 = MAXMATCH;
+ mMatchPos = NodeR;
+ } else {
+ Index2 = mLevel[NodeR];
+ mMatchPos = (NODE) (mPosition[NodeR] & (UINT32)~PERC_FLAG);
+ }
+
+ if (mMatchPos >= mPos) {
+ mMatchPos -= WNDSIZ;
+ }
+
+ t1 = &mText[mPos + mMatchLen];
+ t2 = &mText[mMatchPos + mMatchLen];
+ while (mMatchLen < Index2) {
+ if (*t1 != *t2) {
+ Split (NodeR);
+ return ;
+ }
+
+ mMatchLen++;
+ t1++;
+ t2++;
+ }
+
+ if (mMatchLen >= MAXMATCH) {
+ break;
+ }
+
+ mPosition[NodeR] = mPos;
+ NodeQ = NodeR;
+ NodeR = Child (NodeQ, *t1);
+ if (NodeR == NIL) {
+ MakeChild (NodeQ, *t1, mPos);
+ return ;
+ }
+
+ mMatchLen++;
+ }
+
+ NodeT = mPrev[NodeR];
+ mPrev[mPos] = NodeT;
+ mNext[NodeT] = mPos;
+ NodeT = mNext[NodeR];
+ mNext[mPos] = NodeT;
+ mPrev[NodeT] = mPos;
+ mParent[mPos] = NodeQ;
+ mParent[NodeR] = NIL;
+
+ //
+ // Special usage of 'next'
+ //
+ mNext[NodeR] = mPos;
+
+}
+
+STATIC
+VOID
+DeleteNode (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Delete outdated string info. (The Usage of PERC_FLAG
+ ensures a clean deletion)
+
+Arguments: (VOID)
+
+Returns: (VOID)
+
+--*/
+{
+ NODE NodeQ;
+ NODE NodeR;
+ NODE NodeS;
+ NODE NodeT;
+ NODE NodeU;
+
+ if (mParent[mPos] == NIL) {
+ return ;
+ }
+
+ NodeR = mPrev[mPos];
+ NodeS = mNext[mPos];
+ mNext[NodeR] = NodeS;
+ mPrev[NodeS] = NodeR;
+ NodeR = mParent[mPos];
+ mParent[mPos] = NIL;
+ if (NodeR >= WNDSIZ) {
+ return ;
+ }
+
+ mChildCount[NodeR]--;
+ if (mChildCount[NodeR] > 1) {
+ return ;
+ }
+
+ NodeT = (NODE) (mPosition[NodeR] & (UINT32)~PERC_FLAG);
+ if (NodeT >= mPos) {
+ NodeT -= WNDSIZ;
+ }
+
+ NodeS = NodeT;
+ NodeQ = mParent[NodeR];
+ NodeU = mPosition[NodeQ];
+ while (NodeU & (UINT32) PERC_FLAG) {
+ NodeU &= (UINT32)~PERC_FLAG;
+ if (NodeU >= mPos) {
+ NodeU -= WNDSIZ;
+ }
+
+ if (NodeU > NodeS) {
+ NodeS = NodeU;
+ }
+
+ mPosition[NodeQ] = (NODE) (NodeS | WNDSIZ);
+ NodeQ = mParent[NodeQ];
+ NodeU = mPosition[NodeQ];
+ }
+
+ if (NodeQ < WNDSIZ) {
+ if (NodeU >= mPos) {
+ NodeU -= WNDSIZ;
+ }
+
+ if (NodeU > NodeS) {
+ NodeS = NodeU;
+ }
+
+ mPosition[NodeQ] = (NODE) (NodeS | WNDSIZ | (UINT32) PERC_FLAG);
+ }
+
+ NodeS = Child (NodeR, mText[NodeT + mLevel[NodeR]]);
+ NodeT = mPrev[NodeS];
+ NodeU = mNext[NodeS];
+ mNext[NodeT] = NodeU;
+ mPrev[NodeU] = NodeT;
+ NodeT = mPrev[NodeR];
+ mNext[NodeT] = NodeS;
+ mPrev[NodeS] = NodeT;
+ NodeT = mNext[NodeR];
+ mPrev[NodeT] = NodeS;
+ mNext[NodeS] = NodeT;
+ mParent[NodeS] = mParent[NodeR];
+ mParent[NodeR] = NIL;
+ mNext[NodeR] = mAvail;
+ mAvail = NodeR;
+}
+
+STATIC
+VOID
+GetNextMatch (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Advance the current position (read in new data if needed).
+ Delete outdated string info. Find a match string for current position.
+
+Arguments: (VOID)
+
+Returns: (VOID)
+
+--*/
+{
+ INT32 Number;
+
+ mRemainder--;
+ mPos++;
+ if (mPos == WNDSIZ * 2) {
+ memmove (&mText[0], &mText[WNDSIZ], WNDSIZ + MAXMATCH);
+ Number = FreadCrc (&mText[WNDSIZ + MAXMATCH], WNDSIZ);
+ mRemainder += Number;
+ mPos = WNDSIZ;
+ }
+
+ DeleteNode ();
+ InsertNode ();
+}
+
+STATIC
+EFI_STATUS
+Encode (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ The main controlling routine for compression process.
+
+Arguments: (VOID)
+
+Returns:
+
+ EFI_SUCCESS - The compression is successful
+ EFI_OUT_0F_RESOURCES - Not enough memory for compression process
+
+--*/
+{
+ EFI_STATUS Status;
+ INT32 LastMatchLen;
+ NODE LastMatchPos;
+
+ Status = AllocateMemory ();
+ if (EFI_ERROR (Status)) {
+ FreeMemory ();
+ return Status;
+ }
+
+ InitSlide ();
+
+ HufEncodeStart ();
+
+ mRemainder = FreadCrc (&mText[WNDSIZ], WNDSIZ + MAXMATCH);
+
+ mMatchLen = 0;
+ mPos = WNDSIZ;
+ InsertNode ();
+ if (mMatchLen > mRemainder) {
+ mMatchLen = mRemainder;
+ }
+
+ while (mRemainder > 0) {
+ LastMatchLen = mMatchLen;
+ LastMatchPos = mMatchPos;
+ GetNextMatch ();
+ if (mMatchLen > mRemainder) {
+ mMatchLen = mRemainder;
+ }
+
+ if (mMatchLen > LastMatchLen || LastMatchLen < THRESHOLD) {
+ //
+ // Not enough benefits are gained by outputting a pointer,
+ // so just output the original character
+ //
+ Output (mText[mPos - 1], 0);
+
+ } else {
+
+ if (LastMatchLen == THRESHOLD) {
+ if (((mPos - LastMatchPos - 2) & (WNDSIZ - 1)) > (1U << 11)) {
+ Output (mText[mPos - 1], 0);
+ continue;
+ }
+ }
+ //
+ // Outputting a pointer is beneficial enough, do it.
+ //
+ Output (
+ LastMatchLen + (UINT8_MAX + 1 - THRESHOLD),
+ (mPos - LastMatchPos - 2) & (WNDSIZ - 1)
+ );
+ LastMatchLen--;
+ while (LastMatchLen > 0) {
+ GetNextMatch ();
+ LastMatchLen--;
+ }
+
+ if (mMatchLen > mRemainder) {
+ mMatchLen = mRemainder;
+ }
+ }
+ }
+
+ HufEncodeEnd ();
+ FreeMemory ();
+ return EFI_SUCCESS;
+}
+
+STATIC
+VOID
+CountTFreq (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Count the frequencies for the Extra Set
+
+Arguments: (VOID)
+
+Returns: (VOID)
+
+--*/
+{
+ INT32 Index;
+ INT32 Index3;
+ INT32 Number;
+ INT32 Count;
+
+ for (Index = 0; Index < NT; Index++) {
+ mTFreq[Index] = 0;
+ }
+
+ Number = NC;
+ while (Number > 0 && mCLen[Number - 1] == 0) {
+ Number--;
+ }
+
+ Index = 0;
+ while (Index < Number) {
+ Index3 = mCLen[Index++];
+ if (Index3 == 0) {
+ Count = 1;
+ while (Index < Number && mCLen[Index] == 0) {
+ Index++;
+ Count++;
+ }
+
+ if (Count <= 2) {
+ mTFreq[0] = (UINT16) (mTFreq[0] + Count);
+ } else if (Count <= 18) {
+ mTFreq[1]++;
+ } else if (Count == 19) {
+ mTFreq[0]++;
+ mTFreq[1]++;
+ } else {
+ mTFreq[2]++;
+ }
+ } else {
+ mTFreq[Index3 + 2]++;
+ }
+ }
+}
+
+STATIC
+VOID
+WritePTLen (
+ IN INT32 Number,
+ IN INT32 nbit,
+ IN INT32 Special
+ )
+/*++
+
+Routine Description:
+
+ Outputs the code length array for the Extra Set or the Position Set.
+
+Arguments:
+
+ Number - the number of symbols
+ nbit - the number of bits needed to represent 'n'
+ Special - the special symbol that needs to be take care of
+
+Returns: (VOID)
+
+--*/
+{
+ INT32 Index;
+ INT32 Index3;
+
+ while (Number > 0 && mPTLen[Number - 1] == 0) {
+ Number--;
+ }
+
+ PutBits (nbit, Number);
+ Index = 0;
+ while (Index < Number) {
+ Index3 = mPTLen[Index++];
+ if (Index3 <= 6) {
+ PutBits (3, Index3);
+ } else {
+ PutBits (Index3 - 3, (1U << (Index3 - 3)) - 2);
+ }
+
+ if (Index == Special) {
+ while (Index < 6 && mPTLen[Index] == 0) {
+ Index++;
+ }
+
+ PutBits (2, (Index - 3) & 3);
+ }
+ }
+}
+
+STATIC
+VOID
+WriteCLen (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Outputs the code length array for Char&Length Set
+
+Arguments: (VOID)
+
+Returns: (VOID)
+
+--*/
+{
+ INT32 Index;
+ INT32 Index3;
+ INT32 Number;
+ INT32 Count;
+
+ Number = NC;
+ while (Number > 0 && mCLen[Number - 1] == 0) {
+ Number--;
+ }
+
+ PutBits (CBIT, Number);
+ Index = 0;
+ while (Index < Number) {
+ Index3 = mCLen[Index++];
+ if (Index3 == 0) {
+ Count = 1;
+ while (Index < Number && mCLen[Index] == 0) {
+ Index++;
+ Count++;
+ }
+
+ if (Count <= 2) {
+ for (Index3 = 0; Index3 < Count; Index3++) {
+ PutBits (mPTLen[0], mPTCode[0]);
+ }
+ } else if (Count <= 18) {
+ PutBits (mPTLen[1], mPTCode[1]);
+ PutBits (4, Count - 3);
+ } else if (Count == 19) {
+ PutBits (mPTLen[0], mPTCode[0]);
+ PutBits (mPTLen[1], mPTCode[1]);
+ PutBits (4, 15);
+ } else {
+ PutBits (mPTLen[2], mPTCode[2]);
+ PutBits (CBIT, Count - 20);
+ }
+ } else {
+ PutBits (mPTLen[Index3 + 2], mPTCode[Index3 + 2]);
+ }
+ }
+}
+
+STATIC
+VOID
+EncodeC (
+ IN INT32 Value
+ )
+{
+ PutBits (mCLen[Value], mCCode[Value]);
+}
+
+STATIC
+VOID
+EncodeP (
+ IN UINT32 Value
+ )
+{
+ UINT32 Index;
+ UINT32 NodeQ;
+
+ Index = 0;
+ NodeQ = Value;
+ while (NodeQ) {
+ NodeQ >>= 1;
+ Index++;
+ }
+
+ PutBits (mPTLen[Index], mPTCode[Index]);
+ if (Index > 1) {
+ PutBits (Index - 1, Value & (0xFFFFFFFFU >> (32 - Index + 1)));
+ }
+}
+
+STATIC
+VOID
+SendBlock (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Huffman code the block and output it.
+
+Arguments:
+ (VOID)
+
+Returns:
+ (VOID)
+
+--*/
+{
+ UINT32 Index;
+ UINT32 Index2;
+ UINT32 Index3;
+ UINT32 Flags;
+ UINT32 Root;
+ UINT32 Pos;
+ UINT32 Size;
+ Flags = 0;
+
+ Root = MakeTree (NC, mCFreq, mCLen, mCCode);
+ Size = mCFreq[Root];
+ PutBits (16, Size);
+ if (Root >= NC) {
+ CountTFreq ();
+ Root = MakeTree (NT, mTFreq, mPTLen, mPTCode);
+ if (Root >= NT) {
+ WritePTLen (NT, TBIT, 3);
+ } else {
+ PutBits (TBIT, 0);
+ PutBits (TBIT, Root);
+ }
+
+ WriteCLen ();
+ } else {
+ PutBits (TBIT, 0);
+ PutBits (TBIT, 0);
+ PutBits (CBIT, 0);
+ PutBits (CBIT, Root);
+ }
+
+ Root = MakeTree (NP, mPFreq, mPTLen, mPTCode);
+ if (Root >= NP) {
+ WritePTLen (NP, PBIT, -1);
+ } else {
+ PutBits (PBIT, 0);
+ PutBits (PBIT, Root);
+ }
+
+ Pos = 0;
+ for (Index = 0; Index < Size; Index++) {
+ if (Index % UINT8_BIT == 0) {
+ Flags = mBuf[Pos++];
+ } else {
+ Flags <<= 1;
+ }
+
+ if (Flags & (1U << (UINT8_BIT - 1))) {
+ EncodeC (mBuf[Pos++] + (1U << UINT8_BIT));
+ Index3 = mBuf[Pos++];
+ for (Index2 = 0; Index2 < 3; Index2++) {
+ Index3 <<= UINT8_BIT;
+ Index3 += mBuf[Pos++];
+ }
+
+ EncodeP (Index3);
+ } else {
+ EncodeC (mBuf[Pos++]);
+ }
+ }
+
+ for (Index = 0; Index < NC; Index++) {
+ mCFreq[Index] = 0;
+ }
+
+ for (Index = 0; Index < NP; Index++) {
+ mPFreq[Index] = 0;
+ }
+}
+
+STATIC
+VOID
+Output (
+ IN UINT32 CharC,
+ IN UINT32 Pos
+ )
+/*++
+
+Routine Description:
+
+ Outputs an Original Character or a Pointer
+
+Arguments:
+
+ CharC - The original character or the 'String Length' element of a Pointer
+ Pos - The 'Position' field of a Pointer
+
+Returns: (VOID)
+
+--*/
+{
+ static UINT32 CPos;
+
+ if ((mOutputMask >>= 1) == 0) {
+ mOutputMask = 1U << (UINT8_BIT - 1);
+ //
+ // Check the buffer overflow per outputing UINT8_BIT symbols
+ // which is an Original Character or a Pointer. The biggest
+ // symbol is a Pointer which occupies 5 bytes.
+ //
+ if (mOutputPos >= mBufSiz - 5 * UINT8_BIT) {
+ SendBlock ();
+ mOutputPos = 0;
+ }
+
+ CPos = mOutputPos++;
+ mBuf[CPos] = 0;
+ }
+
+ mBuf[mOutputPos++] = (UINT8) CharC;
+ mCFreq[CharC]++;
+ if (CharC >= (1U << UINT8_BIT)) {
+ mBuf[CPos] |= mOutputMask;
+ mBuf[mOutputPos++] = (UINT8) (Pos >> 24);
+ mBuf[mOutputPos++] = (UINT8) (Pos >> 16);
+ mBuf[mOutputPos++] = (UINT8) (Pos >> (UINT8_BIT));
+ mBuf[mOutputPos++] = (UINT8) Pos;
+ CharC = 0;
+ while (Pos) {
+ Pos >>= 1;
+ CharC++;
+ }
+
+ mPFreq[CharC]++;
+ }
+}
+
+STATIC
+VOID
+HufEncodeStart (
+ VOID
+ )
+{
+ INT32 Index;
+
+ for (Index = 0; Index < NC; Index++) {
+ mCFreq[Index] = 0;
+ }
+
+ for (Index = 0; Index < NP; Index++) {
+ mPFreq[Index] = 0;
+ }
+
+ mOutputPos = mOutputMask = 0;
+ InitPutBits ();
+ return ;
+}
+
+STATIC
+VOID
+HufEncodeEnd (
+ VOID
+ )
+{
+ SendBlock ();
+
+ //
+ // Flush remaining bits
+ //
+ PutBits (UINT8_BIT - 1, 0);
+
+ return ;
+}
+
+STATIC
+VOID
+MakeCrcTable (
+ VOID
+ )
+{
+ UINT32 Index;
+ UINT32 Index2;
+ UINT32 Temp;
+
+ for (Index = 0; Index <= UINT8_MAX; Index++) {
+ Temp = Index;
+ for (Index2 = 0; Index2 < UINT8_BIT; Index2++) {
+ if (Temp & 1) {
+ Temp = (Temp >> 1) ^ CRCPOLY;
+ } else {
+ Temp >>= 1;
+ }
+ }
+
+ mCrcTable[Index] = (UINT16) Temp;
+ }
+}
+
+STATIC
+VOID
+PutBits (
+ IN INT32 Number,
+ IN UINT32 Value
+ )
+/*++
+
+Routine Description:
+
+ Outputs rightmost n bits of x
+
+Arguments:
+
+ Number - the rightmost n bits of the data is used
+ x - the data
+
+Returns: (VOID)
+
+--*/
+{
+ UINT8 Temp;
+
+ while (Number >= mBitCount) {
+ //
+ // Number -= mBitCount should never equal to 32
+ //
+ Temp = (UINT8) (mSubBitBuf | (Value >> (Number -= mBitCount)));
+ if (mDst < mDstUpperLimit) {
+ *mDst++ = Temp;
+ }
+
+ mCompSize++;
+ mSubBitBuf = 0;
+ mBitCount = UINT8_BIT;
+ }
+
+ mSubBitBuf |= Value << (mBitCount -= Number);
+}
+
+STATIC
+INT32
+FreadCrc (
+ OUT UINT8 *Pointer,
+ IN INT32 Number
+ )
+/*++
+
+Routine Description:
+
+ Read in source data
+
+Arguments:
+
+ Pointer - the buffer to hold the data
+ Number - number of bytes to read
+
+Returns:
+
+ number of bytes actually read
+
+--*/
+{
+ INT32 Index;
+
+ for (Index = 0; mSrc < mSrcUpperLimit && Index < Number; Index++) {
+ *Pointer++ = *mSrc++;
+ }
+
+ Number = Index;
+
+ Pointer -= Number;
+ mOrigSize += Number;
+ Index--;
+ while (Index >= 0) {
+ UPDATE_CRC (*Pointer++);
+ Index--;
+ }
+
+ return Number;
+}
+
+STATIC
+VOID
+InitPutBits (
+ VOID
+ )
+{
+ mBitCount = UINT8_BIT;
+ mSubBitBuf = 0;
+}
+
+STATIC
+VOID
+CountLen (
+ IN INT32 Index
+ )
+/*++
+
+Routine Description:
+
+ Count the number of each code length for a Huffman tree.
+
+Arguments:
+
+ Index - the top node
+
+Returns: (VOID)
+
+--*/
+{
+ static INT32 Depth = 0;
+
+ if (Index < mN) {
+ mLenCnt[(Depth < 16) ? Depth : 16]++;
+ } else {
+ Depth++;
+ CountLen (mLeft[Index]);
+ CountLen (mRight[Index]);
+ Depth--;
+ }
+}
+
+STATIC
+VOID
+MakeLen (
+ IN INT32 Root
+ )
+/*++
+
+Routine Description:
+
+ Create code length array for a Huffman tree
+
+Arguments:
+
+ Root - the root of the tree
+
+Returns:
+
+ VOID
+
+--*/
+{
+ INT32 Index;
+ INT32 Index3;
+ UINT32 Cum;
+
+ for (Index = 0; Index <= 16; Index++) {
+ mLenCnt[Index] = 0;
+ }
+
+ CountLen (Root);
+
+ //
+ // Adjust the length count array so that
+ // no code will be generated longer than its designated length
+ //
+ Cum = 0;
+ for (Index = 16; Index > 0; Index--) {
+ Cum += mLenCnt[Index] << (16 - Index);
+ }
+
+ while (Cum != (1U << 16)) {
+ mLenCnt[16]--;
+ for (Index = 15; Index > 0; Index--) {
+ if (mLenCnt[Index] != 0) {
+ mLenCnt[Index]--;
+ mLenCnt[Index + 1] += 2;
+ break;
+ }
+ }
+
+ Cum--;
+ }
+
+ for (Index = 16; Index > 0; Index--) {
+ Index3 = mLenCnt[Index];
+ Index3--;
+ while (Index3 >= 0) {
+ mLen[*mSortPtr++] = (UINT8) Index;
+ Index3--;
+ }
+ }
+}
+
+STATIC
+VOID
+DownHeap (
+ IN INT32 Index
+ )
+{
+ INT32 Index2;
+ INT32 Index3;
+
+ //
+ // priority queue: send Index-th entry down heap
+ //
+ Index3 = mHeap[Index];
+ Index2 = 2 * Index;
+ while (Index2 <= mHeapSize) {
+ if (Index2 < mHeapSize && mFreq[mHeap[Index2]] > mFreq[mHeap[Index2 + 1]]) {
+ Index2++;
+ }
+
+ if (mFreq[Index3] <= mFreq[mHeap[Index2]]) {
+ break;
+ }
+
+ mHeap[Index] = mHeap[Index2];
+ Index = Index2;
+ Index2 = 2 * Index;
+ }
+
+ mHeap[Index] = (INT16) Index3;
+}
+
+STATIC
+VOID
+MakeCode (
+ IN INT32 Number,
+ IN UINT8 Len[ ],
+ OUT UINT16 Code[]
+ )
+/*++
+
+Routine Description:
+
+ Assign code to each symbol based on the code length array
+
+Arguments:
+
+ Number - number of symbols
+ Len - the code length array
+ Code - stores codes for each symbol
+
+Returns: (VOID)
+
+--*/
+{
+ INT32 Index;
+ UINT16 Start[18];
+
+ Start[1] = 0;
+ for (Index = 1; Index <= 16; Index++) {
+ Start[Index + 1] = (UINT16) ((Start[Index] + mLenCnt[Index]) << 1);
+ }
+
+ for (Index = 0; Index < Number; Index++) {
+ Code[Index] = Start[Len[Index]]++;
+ }
+}
+
+STATIC
+INT32
+MakeTree (
+ IN INT32 NParm,
+ IN UINT16 FreqParm[],
+ OUT UINT8 LenParm[ ],
+ OUT UINT16 CodeParm[]
+ )
+/*++
+
+Routine Description:
+
+ Generates Huffman codes given a frequency distribution of symbols
+
+Arguments:
+
+ NParm - number of symbols
+ FreqParm - frequency of each symbol
+ LenParm - code length for each symbol
+ CodeParm - code for each symbol
+
+Returns:
+
+ Root of the Huffman tree.
+
+--*/
+{
+ INT32 Index;
+ INT32 Index2;
+ INT32 Index3;
+ INT32 Avail;
+
+ //
+ // make tree, calculate len[], return root
+ //
+ mN = NParm;
+ mFreq = FreqParm;
+ mLen = LenParm;
+ Avail = mN;
+ mHeapSize = 0;
+ mHeap[1] = 0;
+ for (Index = 0; Index < mN; Index++) {
+ mLen[Index] = 0;
+ if (mFreq[Index]) {
+ mHeapSize++;
+ mHeap[mHeapSize] = (INT16) Index;
+ }
+ }
+
+ if (mHeapSize < 2) {
+ CodeParm[mHeap[1]] = 0;
+ return mHeap[1];
+ }
+
+ for (Index = mHeapSize / 2; Index >= 1; Index--) {
+ //
+ // make priority queue
+ //
+ DownHeap (Index);
+ }
+
+ mSortPtr = CodeParm;
+ do {
+ Index = mHeap[1];
+ if (Index < mN) {
+ *mSortPtr++ = (UINT16) Index;
+ }
+
+ mHeap[1] = mHeap[mHeapSize--];
+ DownHeap (1);
+ Index2 = mHeap[1];
+ if (Index2 < mN) {
+ *mSortPtr++ = (UINT16) Index2;
+ }
+
+ Index3 = Avail++;
+ mFreq[Index3] = (UINT16) (mFreq[Index] + mFreq[Index2]);
+ mHeap[1] = (INT16) Index3;
+ DownHeap (1);
+ mLeft[Index3] = (UINT16) Index;
+ mRight[Index3] = (UINT16) Index2;
+ } while (mHeapSize > 1);
+
+ mSortPtr = CodeParm;
+ MakeLen (Index3);
+ MakeCode (NParm, LenParm, CodeParm);
+
+ //
+ // return root
+ //
+ return Index3;
+}
diff --git a/Source/Common/EfiCompress.h b/Source/Common/EfiCompress.h
new file mode 100644
index 0000000..6ad80e4
--- /dev/null
+++ b/Source/Common/EfiCompress.h
@@ -0,0 +1,69 @@
+/*++
+
+Copyright (c) 2004, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ EfiCompress.h
+
+Abstract:
+
+ Header file for compression routine
+
+--*/
+
+#ifndef _EFICOMPRESS_H
+#define _EFICOMPRESS_H
+
+#include <string.h>
+#include <stdlib.h>
+
+#include <Common/UefiBaseTypes.h>
+
+EFI_STATUS
+Compress (
+ IN UINT8 *SrcBuffer,
+ IN UINT32 SrcSize,
+ IN UINT8 *DstBuffer,
+ IN OUT UINT32 *DstSize
+ )
+;
+
+/*++
+
+Routine Description:
+
+ The compression routine.
+
+Arguments:
+
+ SrcBuffer - The buffer storing the source data
+ SrcSize - The size of source data
+ DstBuffer - The buffer to store the compressed data
+ DstSize - On input, the size of DstBuffer; On output,
+ the size of the actual compressed data.
+
+Returns:
+
+ EFI_BUFFER_TOO_SMALL - The DstBuffer is too small. In this case,
+ DstSize contains the size needed.
+ EFI_SUCCESS - Compression is successful.
+
+--*/
+typedef
+EFI_STATUS
+(*COMPRESS_FUNCTION) (
+ IN UINT8 *SrcBuffer,
+ IN UINT32 SrcSize,
+ IN UINT8 *DstBuffer,
+ IN OUT UINT32 *DstSize
+ );
+
+#endif
diff --git a/Source/Common/EfiCustomizedCompress.h b/Source/Common/EfiCustomizedCompress.h
new file mode 100644
index 0000000..af26b6f
--- /dev/null
+++ b/Source/Common/EfiCustomizedCompress.h
@@ -0,0 +1,141 @@
+/*++
+
+Copyright (c) 2004, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ EfiCustomizedCompress.h
+
+Abstract:
+
+ Header file for Customized compression routine
+
+--*/
+
+#ifndef _EFICUSTOMIZEDCOMPRESS_H
+#define _EFICUSTOMIZEDCOMPRESS_H
+
+#include <Common/UefiBaseTypes.h>
+
+EFI_STATUS
+SetCustomizedCompressionType (
+ IN CHAR8 *Type
+ )
+;
+
+/*++
+
+Routine Description:
+
+The implementation of Customized SetCompressionType().
+
+Arguments:
+ Type - The type if compression.
+
+Returns:
+
+ EFI_SUCCESS - The type has been set.
+ EFI_UNSUPPORTED - This type is unsupported.
+
+
+--*/
+EFI_STATUS
+CustomizedGetInfo (
+ IN VOID *Source,
+ IN UINT32 SrcSize,
+ OUT UINT32 *DstSize,
+ OUT UINT32 *ScratchSize
+ )
+;
+
+/*++
+
+Routine Description:
+
+ The implementation of Customized GetInfo().
+
+Arguments:
+
+ Source - The source buffer containing the compressed data.
+ SrcSize - The size of source buffer
+ DstSize - The size of destination buffer.
+ ScratchSize - The size of scratch buffer.
+
+Returns:
+
+ EFI_SUCCESS - The size of destination buffer and the size of scratch buffer are successull retrieved.
+ EFI_INVALID_PARAMETER - The source data is corrupted
+
+--*/
+EFI_STATUS
+CustomizedDecompress (
+ IN VOID *Source,
+ IN UINT32 SrcSize,
+ IN OUT VOID *Destination,
+ IN UINT32 DstSize,
+ IN OUT VOID *Scratch,
+ IN UINT32 ScratchSize
+ )
+;
+
+/*++
+
+Routine Description:
+
+ The implementation of Customized Decompress().
+
+Arguments:
+
+ This - The protocol instance pointer
+ Source - The source buffer containing the compressed data.
+ SrcSize - The size of source buffer
+ Destination - The destination buffer to store the decompressed data
+ DstSize - The size of destination buffer.
+ Scratch - The buffer used internally by the decompress routine. This buffer is needed to store intermediate data.
+ ScratchSize - The size of scratch buffer.
+
+Returns:
+
+ EFI_SUCCESS - Decompression is successfull
+ EFI_INVALID_PARAMETER - The source data is corrupted
+
+--*/
+EFI_STATUS
+CustomizedCompress (
+ IN UINT8 *SrcBuffer,
+ IN UINT32 SrcSize,
+ IN UINT8 *DstBuffer,
+ IN OUT UINT32 *DstSize
+ )
+;
+
+/*++
+
+Routine Description:
+
+ The Customized compression routine.
+
+Arguments:
+
+ SrcBuffer - The buffer storing the source data
+ SrcSize - The size of source data
+ DstBuffer - The buffer to store the compressed data
+ DstSize - On input, the size of DstBuffer; On output,
+ the size of the actual compressed data.
+
+Returns:
+
+ EFI_BUFFER_TOO_SMALL - The DstBuffer is too small. In this case,
+ DstSize contains the size needed.
+ EFI_SUCCESS - Compression is successful.
+
+--*/
+
+#endif
diff --git a/Source/Common/EfiDecompress.c b/Source/Common/EfiDecompress.c
new file mode 100644
index 0000000..288c425
--- /dev/null
+++ b/Source/Common/EfiDecompress.c
@@ -0,0 +1,790 @@
+/*++
+
+Copyright (c) 2004, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ EfiDecompress.c
+
+Abstract:
+
+ Decompressor. Algorithm Ported from OPSD code (Decomp.asm)
+
+--*/
+
+#include "EfiDecompress.h"
+
+//
+// Decompression algorithm begins here
+//
+#define BITBUFSIZ 32
+#define MAXMATCH 256
+#define THRESHOLD 3
+#define CODE_BIT 16
+#define BAD_TABLE - 1
+
+//
+// C: Char&Len Set; P: Position Set; T: exTra Set
+//
+#define NC (0xff + MAXMATCH + 2 - THRESHOLD)
+#define CBIT 9
+#define PBIT 5
+#define TBIT 5
+#define MAXNP ((1U << PBIT) - 1)
+#define NT (CODE_BIT + 3)
+#if NT > MAXNP
+#define NPT NT
+#else
+#define NPT MAXNP
+#endif
+
+typedef struct {
+ UINT8 *mSrcBase; // Starting address of compressed data
+ UINT8 *mDstBase; // Starting address of decompressed data
+ UINT32 mOutBuf;
+ UINT32 mInBuf;
+
+ UINT16 mBitCount;
+ UINT32 mBitBuf;
+ UINT32 mSubBitBuf;
+ UINT16 mBlockSize;
+ UINT32 mCompSize;
+ UINT32 mOrigSize;
+
+ UINT16 mBadTableFlag;
+
+ UINT16 mLeft[2 * NC - 1];
+ UINT16 mRight[2 * NC - 1];
+ UINT8 mCLen[NC];
+ UINT8 mPTLen[NPT];
+ UINT16 mCTable[4096];
+ UINT16 mPTTable[256];
+} SCRATCH_DATA;
+
+STATIC
+VOID
+FillBuf (
+ IN SCRATCH_DATA *Sd,
+ IN UINT16 NumOfBits
+ )
+/*++
+
+Routine Description:
+
+ Shift mBitBuf NumOfBits left. Read in NumOfBits of bits from source.
+
+Arguments:
+
+ Sd - The global scratch data
+ NumOfBit - The number of bits to shift and read.
+
+Returns: (VOID)
+
+--*/
+{
+ Sd->mBitBuf = (UINT32) (Sd->mBitBuf << NumOfBits);
+
+ while (NumOfBits > Sd->mBitCount) {
+
+ Sd->mBitBuf |= (UINT32) (Sd->mSubBitBuf << (NumOfBits = (UINT16) (NumOfBits - Sd->mBitCount)));
+
+ if (Sd->mCompSize > 0) {
+ //
+ // Get 1 byte into SubBitBuf
+ //
+ Sd->mCompSize--;
+ Sd->mSubBitBuf = 0;
+ Sd->mSubBitBuf = Sd->mSrcBase[Sd->mInBuf++];
+ Sd->mBitCount = 8;
+
+ } else {
+ //
+ // No more bits from the source, just pad zero bit.
+ //
+ Sd->mSubBitBuf = 0;
+ Sd->mBitCount = 8;
+
+ }
+ }
+
+ Sd->mBitCount = (UINT16) (Sd->mBitCount - NumOfBits);
+ Sd->mBitBuf |= Sd->mSubBitBuf >> Sd->mBitCount;
+}
+
+STATIC
+UINT32
+GetBits (
+ IN SCRATCH_DATA *Sd,
+ IN UINT16 NumOfBits
+ )
+/*++
+
+Routine Description:
+
+ Get NumOfBits of bits out from mBitBuf. Fill mBitBuf with subsequent
+ NumOfBits of bits from source. Returns NumOfBits of bits that are
+ popped out.
+
+Arguments:
+
+ Sd - The global scratch data.
+ NumOfBits - The number of bits to pop and read.
+
+Returns:
+
+ The bits that are popped out.
+
+--*/
+{
+ UINT32 OutBits;
+
+ OutBits = (UINT32) (Sd->mBitBuf >> (BITBUFSIZ - NumOfBits));
+
+ FillBuf (Sd, NumOfBits);
+
+ return OutBits;
+}
+
+STATIC
+UINT16
+MakeTable (
+ IN SCRATCH_DATA *Sd,
+ IN UINT16 NumOfChar,
+ IN UINT8 *BitLen,
+ IN UINT16 TableBits,
+ OUT UINT16 *Table
+ )
+/*++
+
+Routine Description:
+
+ Creates Huffman Code mapping table according to code length array.
+
+Arguments:
+
+ Sd - The global scratch data
+ NumOfChar - Number of symbols in the symbol set
+ BitLen - Code length array
+ TableBits - The width of the mapping table
+ Table - The table
+
+Returns:
+
+ 0 - OK.
+ BAD_TABLE - The table is corrupted.
+
+--*/
+{
+ UINT16 Count[17];
+ UINT16 Weight[17];
+ UINT16 Start[18];
+ UINT16 *Pointer;
+ UINT16 Index3;
+ UINT16 Index;
+ UINT16 Len;
+ UINT16 Char;
+ UINT16 JuBits;
+ UINT16 Avail;
+ UINT16 NextCode;
+ UINT16 Mask;
+
+ for (Index = 1; Index <= 16; Index++) {
+ Count[Index] = 0;
+ }
+
+ for (Index = 0; Index < NumOfChar; Index++) {
+ Count[BitLen[Index]]++;
+ }
+
+ Start[1] = 0;
+
+ for (Index = 1; Index <= 16; Index++) {
+ Start[Index + 1] = (UINT16) (Start[Index] + (Count[Index] << (16 - Index)));
+ }
+
+ if (Start[17] != 0) {
+ /*(1U << 16)*/
+ return (UINT16) BAD_TABLE;
+ }
+
+ JuBits = (UINT16) (16 - TableBits);
+
+ for (Index = 1; Index <= TableBits; Index++) {
+ Start[Index] >>= JuBits;
+ Weight[Index] = (UINT16) (1U << (TableBits - Index));
+ }
+
+ while (Index <= 16) {
+ Weight[Index++] = (UINT16) (1U << (16 - Index));
+ }
+
+ Index = (UINT16) (Start[TableBits + 1] >> JuBits);
+
+ if (Index != 0) {
+ Index3 = (UINT16) (1U << TableBits);
+ while (Index != Index3) {
+ Table[Index++] = 0;
+ }
+ }
+
+ Avail = NumOfChar;
+ Mask = (UINT16) (1U << (15 - TableBits));
+
+ for (Char = 0; Char < NumOfChar; Char++) {
+
+ Len = BitLen[Char];
+ if (Len == 0) {
+ continue;
+ }
+
+ NextCode = (UINT16) (Start[Len] + Weight[Len]);
+
+ if (Len <= TableBits) {
+
+ for (Index = Start[Len]; Index < NextCode; Index++) {
+ Table[Index] = Char;
+ }
+
+ } else {
+
+ Index3 = Start[Len];
+ Pointer = &Table[Index3 >> JuBits];
+ Index = (UINT16) (Len - TableBits);
+
+ while (Index != 0) {
+ if (*Pointer == 0) {
+ Sd->mRight[Avail] = Sd->mLeft[Avail] = 0;
+ *Pointer = Avail++;
+ }
+
+ if (Index3 & Mask) {
+ Pointer = &Sd->mRight[*Pointer];
+ } else {
+ Pointer = &Sd->mLeft[*Pointer];
+ }
+
+ Index3 <<= 1;
+ Index--;
+ }
+
+ *Pointer = Char;
+
+ }
+
+ Start[Len] = NextCode;
+ }
+ //
+ // Succeeds
+ //
+ return 0;
+}
+
+STATIC
+UINT32
+DecodeP (
+ IN SCRATCH_DATA *Sd
+ )
+/*++
+
+Routine Description:
+
+ Decodes a position value.
+
+Arguments:
+
+ Sd - the global scratch data
+
+Returns:
+
+ The position value decoded.
+
+--*/
+{
+ UINT16 Val;
+ UINT32 Mask;
+ UINT32 Pos;
+
+ Val = Sd->mPTTable[Sd->mBitBuf >> (BITBUFSIZ - 8)];
+
+ if (Val >= MAXNP) {
+ Mask = 1U << (BITBUFSIZ - 1 - 8);
+
+ do {
+
+ if (Sd->mBitBuf & Mask) {
+ Val = Sd->mRight[Val];
+ } else {
+ Val = Sd->mLeft[Val];
+ }
+
+ Mask >>= 1;
+ } while (Val >= MAXNP);
+ }
+ //
+ // Advance what we have read
+ //
+ FillBuf (Sd, Sd->mPTLen[Val]);
+
+ Pos = Val;
+ if (Val > 1) {
+ Pos = (UINT32) ((1U << (Val - 1)) + GetBits (Sd, (UINT16) (Val - 1)));
+ }
+
+ return Pos;
+}
+
+STATIC
+UINT16
+ReadPTLen (
+ IN SCRATCH_DATA *Sd,
+ IN UINT16 nn,
+ IN UINT16 nbit,
+ IN UINT16 Special
+ )
+/*++
+
+Routine Description:
+
+ Reads code lengths for the Extra Set or the Position Set
+
+Arguments:
+
+ Sd - The global scratch data
+ nn - Number of symbols
+ nbit - Number of bits needed to represent nn
+ Special - The special symbol that needs to be taken care of
+
+Returns:
+
+ 0 - OK.
+ BAD_TABLE - Table is corrupted.
+
+--*/
+{
+ UINT16 Number;
+ UINT16 CharC;
+ UINT16 Index;
+ UINT32 Mask;
+
+ Number = (UINT16) GetBits (Sd, nbit);
+
+ if (Number == 0) {
+ CharC = (UINT16) GetBits (Sd, nbit);
+
+ for (Index = 0; Index < 256; Index++) {
+ Sd->mPTTable[Index] = CharC;
+ }
+
+ for (Index = 0; Index < nn; Index++) {
+ Sd->mPTLen[Index] = 0;
+ }
+
+ return 0;
+ }
+
+ Index = 0;
+
+ while (Index < Number) {
+
+ CharC = (UINT16) (Sd->mBitBuf >> (BITBUFSIZ - 3));
+
+ if (CharC == 7) {
+ Mask = 1U << (BITBUFSIZ - 1 - 3);
+ while (Mask & Sd->mBitBuf) {
+ Mask >>= 1;
+ CharC += 1;
+ }
+ }
+
+ FillBuf (Sd, (UINT16) ((CharC < 7) ? 3 : CharC - 3));
+
+ Sd->mPTLen[Index++] = (UINT8) CharC;
+
+ if (Index == Special) {
+ CharC = (UINT16) GetBits (Sd, 2);
+ CharC--;
+ while ((INT16) (CharC) >= 0) {
+ Sd->mPTLen[Index++] = 0;
+ CharC--;
+ }
+ }
+ }
+
+ while (Index < nn) {
+ Sd->mPTLen[Index++] = 0;
+ }
+
+ return MakeTable (Sd, nn, Sd->mPTLen, 8, Sd->mPTTable);
+}
+
+STATIC
+VOID
+ReadCLen (
+ SCRATCH_DATA *Sd
+ )
+/*++
+
+Routine Description:
+
+ Reads code lengths for Char&Len Set.
+
+Arguments:
+
+ Sd - the global scratch data
+
+Returns: (VOID)
+
+--*/
+{
+ UINT16 Number;
+ UINT16 CharC;
+ UINT16 Index;
+ UINT32 Mask;
+
+ Number = (UINT16) GetBits (Sd, CBIT);
+
+ if (Number == 0) {
+ CharC = (UINT16) GetBits (Sd, CBIT);
+
+ for (Index = 0; Index < NC; Index++) {
+ Sd->mCLen[Index] = 0;
+ }
+
+ for (Index = 0; Index < 4096; Index++) {
+ Sd->mCTable[Index] = CharC;
+ }
+
+ return ;
+ }
+
+ Index = 0;
+ while (Index < Number) {
+
+ CharC = Sd->mPTTable[Sd->mBitBuf >> (BITBUFSIZ - 8)];
+ if (CharC >= NT) {
+ Mask = 1U << (BITBUFSIZ - 1 - 8);
+
+ do {
+
+ if (Mask & Sd->mBitBuf) {
+ CharC = Sd->mRight[CharC];
+ } else {
+ CharC = Sd->mLeft[CharC];
+ }
+
+ Mask >>= 1;
+
+ } while (CharC >= NT);
+ }
+ //
+ // Advance what we have read
+ //
+ FillBuf (Sd, Sd->mPTLen[CharC]);
+
+ if (CharC <= 2) {
+
+ if (CharC == 0) {
+ CharC = 1;
+ } else if (CharC == 1) {
+ CharC = (UINT16) (GetBits (Sd, 4) + 3);
+ } else if (CharC == 2) {
+ CharC = (UINT16) (GetBits (Sd, CBIT) + 20);
+ }
+
+ CharC--;
+ while ((INT16) (CharC) >= 0) {
+ Sd->mCLen[Index++] = 0;
+ CharC--;
+ }
+
+ } else {
+
+ Sd->mCLen[Index++] = (UINT8) (CharC - 2);
+
+ }
+ }
+
+ while (Index < NC) {
+ Sd->mCLen[Index++] = 0;
+ }
+
+ MakeTable (Sd, NC, Sd->mCLen, 12, Sd->mCTable);
+
+ return ;
+}
+
+STATIC
+UINT16
+DecodeC (
+ SCRATCH_DATA *Sd
+ )
+/*++
+
+Routine Description:
+
+ Decode a character/length value.
+
+Arguments:
+
+ Sd - The global scratch data.
+
+Returns:
+
+ The value decoded.
+
+--*/
+{
+ UINT16 Index2;
+ UINT32 Mask;
+
+ if (Sd->mBlockSize == 0) {
+ //
+ // Starting a new block
+ //
+ Sd->mBlockSize = (UINT16) GetBits (Sd, 16);
+ Sd->mBadTableFlag = ReadPTLen (Sd, NT, TBIT, 3);
+ if (Sd->mBadTableFlag != 0) {
+ return 0;
+ }
+
+ ReadCLen (Sd);
+
+ Sd->mBadTableFlag = ReadPTLen (Sd, MAXNP, PBIT, (UINT16) (-1));
+ if (Sd->mBadTableFlag != 0) {
+ return 0;
+ }
+ }
+
+ Sd->mBlockSize--;
+ Index2 = Sd->mCTable[Sd->mBitBuf >> (BITBUFSIZ - 12)];
+
+ if (Index2 >= NC) {
+ Mask = 1U << (BITBUFSIZ - 1 - 12);
+
+ do {
+ if (Sd->mBitBuf & Mask) {
+ Index2 = Sd->mRight[Index2];
+ } else {
+ Index2 = Sd->mLeft[Index2];
+ }
+
+ Mask >>= 1;
+ } while (Index2 >= NC);
+ }
+ //
+ // Advance what we have read
+ //
+ FillBuf (Sd, Sd->mCLen[Index2]);
+
+ return Index2;
+}
+
+STATIC
+VOID
+Decode (
+ SCRATCH_DATA *Sd
+ )
+/*++
+
+Routine Description:
+
+ Decode the source data and put the resulting data into the destination buffer.
+
+Arguments:
+
+ Sd - The global scratch data
+
+Returns: (VOID)
+
+ --*/
+{
+ UINT16 BytesRemain;
+ UINT32 DataIdx;
+ UINT16 CharC;
+
+ BytesRemain = (UINT16) (-1);
+
+ DataIdx = 0;
+
+ for (;;) {
+ CharC = DecodeC (Sd);
+ if (Sd->mBadTableFlag != 0) {
+ return ;
+ }
+
+ if (CharC < 256) {
+ //
+ // Process an Original character
+ //
+ Sd->mDstBase[Sd->mOutBuf++] = (UINT8) CharC;
+ if (Sd->mOutBuf >= Sd->mOrigSize) {
+ return ;
+ }
+
+ } else {
+ //
+ // Process a Pointer
+ //
+ CharC = (UINT16) (CharC - (UINT8_MAX + 1 - THRESHOLD));
+
+ BytesRemain = CharC;
+
+ DataIdx = Sd->mOutBuf - DecodeP (Sd) - 1;
+
+ BytesRemain--;
+ while ((INT16) (BytesRemain) >= 0) {
+ Sd->mDstBase[Sd->mOutBuf++] = Sd->mDstBase[DataIdx++];
+ if (Sd->mOutBuf >= Sd->mOrigSize) {
+ return ;
+ }
+
+ BytesRemain--;
+ }
+ }
+ }
+
+ return ;
+}
+
+EFI_STATUS
+GetInfo (
+ IN VOID *Source,
+ IN UINT32 SrcSize,
+ OUT UINT32 *DstSize,
+ OUT UINT32 *ScratchSize
+ )
+/*++
+
+Routine Description:
+
+ The implementation of EFI_DECOMPRESS_PROTOCOL.GetInfo().
+
+Arguments:
+
+ Source - The source buffer containing the compressed data.
+ SrcSize - The size of source buffer
+ DstSize - The size of destination buffer.
+ ScratchSize - The size of scratch buffer.
+
+Returns:
+
+ EFI_SUCCESS - The size of destination buffer and the size of scratch buffer are successull retrieved.
+ EFI_INVALID_PARAMETER - The source data is corrupted
+
+--*/
+{
+ UINT8 *Src;
+
+ *ScratchSize = sizeof (SCRATCH_DATA);
+
+ Src = Source;
+ if (SrcSize < 8) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *DstSize = Src[4] + (Src[5] << 8) + (Src[6] << 16) + (Src[7] << 24);
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+Decompress (
+ IN VOID *Source,
+ IN UINT32 SrcSize,
+ IN OUT VOID *Destination,
+ IN UINT32 DstSize,
+ IN OUT VOID *Scratch,
+ IN UINT32 ScratchSize
+ )
+/*++
+
+Routine Description:
+
+ The implementation of EFI_DECOMPRESS_PROTOCOL.Decompress().
+
+Arguments:
+
+ This - The protocol instance pointer
+ Source - The source buffer containing the compressed data.
+ SrcSize - The size of source buffer
+ Destination - The destination buffer to store the decompressed data
+ DstSize - The size of destination buffer.
+ Scratch - The buffer used internally by the decompress routine. This buffer is needed to store intermediate data.
+ ScratchSize - The size of scratch buffer.
+
+Returns:
+
+ EFI_SUCCESS - Decompression is successfull
+ EFI_INVALID_PARAMETER - The source data is corrupted
+
+--*/
+{
+ UINT32 Index;
+ UINT32 CompSize;
+ UINT32 OrigSize;
+ EFI_STATUS Status;
+ SCRATCH_DATA *Sd;
+ UINT8 *Src;
+ UINT8 *Dst;
+
+ Status = EFI_SUCCESS;
+ Src = Source;
+ Dst = Destination;
+
+ if (ScratchSize < sizeof (SCRATCH_DATA)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Sd = (SCRATCH_DATA *) Scratch;
+
+ if (SrcSize < 8) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ CompSize = Src[0] + (Src[1] << 8) + (Src[2] << 16) + (Src[3] << 24);
+ OrigSize = Src[4] + (Src[5] << 8) + (Src[6] << 16) + (Src[7] << 24);
+
+ if (SrcSize < CompSize + 8) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (DstSize != OrigSize) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Src = Src + 8;
+
+ for (Index = 0; Index < sizeof (SCRATCH_DATA); Index++) {
+ ((UINT8 *) Sd)[Index] = 0;
+ }
+
+ Sd->mSrcBase = Src;
+ Sd->mDstBase = Dst;
+ Sd->mCompSize = CompSize;
+ Sd->mOrigSize = OrigSize;
+
+ //
+ // Fill the first BITBUFSIZ bits
+ //
+ FillBuf (Sd, BITBUFSIZ);
+
+ //
+ // Decompress it
+ //
+ Decode (Sd);
+
+ if (Sd->mBadTableFlag != 0) {
+ //
+ // Something wrong with the source
+ //
+ Status = EFI_INVALID_PARAMETER;
+ }
+
+ return Status;
+}
diff --git a/Source/Common/EfiDecompress.h b/Source/Common/EfiDecompress.h
new file mode 100644
index 0000000..3f82ac6
--- /dev/null
+++ b/Source/Common/EfiDecompress.h
@@ -0,0 +1,106 @@
+/*++
+
+Copyright (c) 2004, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ EfiDecompress.h
+
+Abstract:
+
+ Header file for compression routine
+
+--*/
+
+#ifndef _EFI_DECOMPRESS_H
+#define _EFI_DECOMPRESS_H
+
+#include <Common/UefiBaseTypes.h>
+
+EFI_STATUS
+GetInfo (
+ IN VOID *Source,
+ IN UINT32 SrcSize,
+ OUT UINT32 *DstSize,
+ OUT UINT32 *ScratchSize
+ );
+
+/*++
+
+Routine Description:
+
+ The implementation of EFI_DECOMPRESS_PROTOCOL.GetInfo().
+
+Arguments:
+
+ Source - The source buffer containing the compressed data.
+ SrcSize - The size of source buffer
+ DstSize - The size of destination buffer.
+ ScratchSize - The size of scratch buffer.
+
+Returns:
+
+ EFI_SUCCESS - The size of destination buffer and the size of scratch buffer are successull retrieved.
+ EFI_INVALID_PARAMETER - The source data is corrupted
+
+--*/
+EFI_STATUS
+Decompress (
+ IN VOID *Source,
+ IN UINT32 SrcSize,
+ IN OUT VOID *Destination,
+ IN UINT32 DstSize,
+ IN OUT VOID *Scratch,
+ IN UINT32 ScratchSize
+ )
+;
+
+/*++
+
+Routine Description:
+
+ The implementation of EFI_DECOMPRESS_PROTOCOL.Decompress().
+
+Arguments:
+
+ This - The protocol instance pointer
+ Source - The source buffer containing the compressed data.
+ SrcSize - The size of source buffer
+ Destination - The destination buffer to store the decompressed data
+ DstSize - The size of destination buffer.
+ Scratch - The buffer used internally by the decompress routine. This buffer is needed to store intermediate data.
+ ScratchSize - The size of scratch buffer.
+
+Returns:
+
+ EFI_SUCCESS - Decompression is successfull
+ EFI_INVALID_PARAMETER - The source data is corrupted
+
+--*/
+typedef
+EFI_STATUS
+(*GETINFO_FUNCTION) (
+ IN VOID *Source,
+ IN UINT32 SrcSize,
+ OUT UINT32 *DstSize,
+ OUT UINT32 *ScratchSize
+ );
+
+typedef
+EFI_STATUS
+(*DECOMPRESS_FUNCTION) (
+ IN VOID *Source,
+ IN UINT32 SrcSize,
+ IN OUT VOID *Destination,
+ IN UINT32 DstSize,
+ IN OUT VOID *Scratch,
+ IN UINT32 ScratchSize
+ );
+#endif
diff --git a/Source/Common/EfiUtilityMsgs.c b/Source/Common/EfiUtilityMsgs.c
new file mode 100644
index 0000000..566d214
--- /dev/null
+++ b/Source/Common/EfiUtilityMsgs.c
@@ -0,0 +1,755 @@
+/*++
+
+Copyright (c) 2004, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ EfiUtilityMsgs.c
+
+Abstract:
+
+ EFI tools utility functions to display warning, error, and informational
+ messages.
+
+--*/
+
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <stdarg.h>
+
+#include "EfiUtilityMsgs.h"
+
+#define MAX_LINE_LEN 200
+
+//
+// Declare module globals for keeping track of the the utility's
+// name and other settings.
+//
+static STATUS mStatus = STATUS_SUCCESS;
+static CHAR8 mUtilityName[50] = { 0 };
+static UINT32 mDebugMsgMask = 0;
+static CHAR8 *mSourceFileName = NULL;
+static UINT32 mSourceFileLineNum = 0;
+static UINT32 mErrorCount = 0;
+static UINT32 mWarningCount = 0;
+static UINT32 mMaxErrors = 0;
+static UINT32 mMaxWarnings = 0;
+static UINT32 mMaxWarningsPlusErrors = 0;
+static INT8 mPrintLimitsSet = 0;
+
+static
+void
+PrintMessage (
+ CHAR8 *Type,
+ CHAR8 *FileName,
+ UINT32 LineNumber,
+ UINT32 MessageCode,
+ CHAR8 *Text,
+ CHAR8 *MsgFmt,
+ va_list List
+ );
+
+static
+void
+PrintLimitExceeded (
+ VOID
+ );
+
+void
+Error (
+ CHAR8 *FileName,
+ UINT32 LineNumber,
+ UINT32 MessageCode,
+ CHAR8 *Text,
+ CHAR8 *MsgFmt,
+ ...
+ )
+/*++
+
+Routine Description:
+ Prints an error message.
+
+Arguments:
+ All arguments are optional, though the printed message may be useless if
+ at least something valid is not specified.
+
+ FileName - name of the file or application. If not specified, then the
+ utilty name (as set by the utility calling SetUtilityName()
+ earlier) is used. Otherwise "Unknown utility" is used.
+
+ LineNumber - the line number of error, typically used by parsers. If the
+ utility is not a parser, then 0 should be specified. Otherwise
+ the FileName and LineNumber info can be used to cause
+ MS Visual Studio to jump to the error.
+
+ MessageCode - an application-specific error code that can be referenced in
+ other documentation.
+
+ Text - the text in question, typically used by parsers.
+
+ MsgFmt - the format string for the error message. Can contain formatting
+ controls for use with the varargs.
+
+Returns:
+ None.
+
+Notes:
+ We print the following (similar to the Warn() and Debug()
+ W
+ Typical error/warning message format:
+
+ bin\VfrCompile.cpp(330) : error C2660: 'AddVfrDataStructField' : function does not take 2 parameters
+
+ BUGBUG -- these three utility functions are almost identical, and
+ should be modified to share code.
+
+ Visual Studio does not find error messages with:
+
+ " error :"
+ " error 1:"
+ " error c1:"
+ " error 1000:"
+ " error c100:"
+
+ It does find:
+ " error c1000:"
+--*/
+{
+ va_list List;
+ //
+ // If limits have been set, then check that we have not exceeded them
+ //
+ if (mPrintLimitsSet) {
+ //
+ // See if we've exceeded our total count
+ //
+ if (mMaxWarningsPlusErrors != 0) {
+ if (mErrorCount + mWarningCount > mMaxWarningsPlusErrors) {
+ PrintLimitExceeded ();
+ return ;
+ }
+ }
+ //
+ // See if we've exceeded our error count
+ //
+ if (mMaxErrors != 0) {
+ if (mErrorCount > mMaxErrors) {
+ PrintLimitExceeded ();
+ return ;
+ }
+ }
+ }
+
+ mErrorCount++;
+ va_start (List, MsgFmt);
+ PrintMessage ("error", FileName, LineNumber, MessageCode, Text, MsgFmt, List);
+ va_end (List);
+ //
+ // Set status accordingly
+ //
+ if (mStatus < STATUS_ERROR) {
+ mStatus = STATUS_ERROR;
+ }
+}
+
+void
+ParserError (
+ UINT32 MessageCode,
+ CHAR8 *Text,
+ CHAR8 *MsgFmt,
+ ...
+ )
+/*++
+
+Routine Description:
+ Print a parser error, using the source file name and line number
+ set by a previous call to SetParserPosition().
+
+Arguments:
+ MessageCode - application-specific error code
+ Text - text to print in the error message
+ MsgFmt - format string to print at the end of the error message
+
+Returns:
+ NA
+
+--*/
+{
+ va_list List;
+ //
+ // If limits have been set, then check them
+ //
+ if (mPrintLimitsSet) {
+ //
+ // See if we've exceeded our total count
+ //
+ if (mMaxWarningsPlusErrors != 0) {
+ if (mErrorCount + mWarningCount > mMaxWarningsPlusErrors) {
+ PrintLimitExceeded ();
+ return ;
+ }
+ }
+ //
+ // See if we've exceeded our error count
+ //
+ if (mMaxErrors != 0) {
+ if (mErrorCount > mMaxErrors) {
+ PrintLimitExceeded ();
+ return ;
+ }
+ }
+ }
+
+ mErrorCount++;
+ va_start (List, MsgFmt);
+ PrintMessage ("error", mSourceFileName, mSourceFileLineNum, MessageCode, Text, MsgFmt, List);
+ va_end (List);
+ //
+ // Set status accordingly
+ //
+ if (mStatus < STATUS_ERROR) {
+ mStatus = STATUS_ERROR;
+ }
+}
+
+void
+ParserWarning (
+ UINT32 ErrorCode,
+ CHAR8 *OffendingText,
+ CHAR8 *MsgFmt,
+ ...
+ )
+/*++
+
+Routine Description:
+ Print a parser warning, using the source file name and line number
+ set by a previous call to SetParserPosition().
+
+Arguments:
+ ErrorCode - application-specific error code
+ OffendingText - text to print in the warning message
+ MsgFmt - format string to print at the end of the warning message
+
+Returns:
+ NA
+
+--*/
+{
+ va_list List;
+ //
+ // If limits have been set, then check them
+ //
+ if (mPrintLimitsSet) {
+ //
+ // See if we've exceeded our total count
+ //
+ if (mMaxWarningsPlusErrors != 0) {
+ if (mErrorCount + mWarningCount > mMaxWarningsPlusErrors) {
+ PrintLimitExceeded ();
+ return ;
+ }
+ }
+ //
+ // See if we've exceeded our warning count
+ //
+ if (mMaxWarnings != 0) {
+ if (mWarningCount > mMaxWarnings) {
+ PrintLimitExceeded ();
+ return ;
+ }
+ }
+ }
+
+ mWarningCount++;
+ va_start (List, MsgFmt);
+ PrintMessage ("warning", mSourceFileName, mSourceFileLineNum, ErrorCode, OffendingText, MsgFmt, List);
+ va_end (List);
+ //
+ // Set status accordingly
+ //
+ if (mStatus < STATUS_WARNING) {
+ mStatus = STATUS_WARNING;
+ }
+}
+
+void
+Warning (
+ CHAR8 *FileName,
+ UINT32 LineNumber,
+ UINT32 MessageCode,
+ CHAR8 *Text,
+ CHAR8 *MsgFmt,
+ ...
+ )
+/*++
+
+Routine Description:
+ Print a warning message.
+
+Arguments:
+ FileName - name of the file where the warning was detected, or the name
+ of the application that detected the warning
+
+ LineNumber - the line number where the warning was detected (parsers).
+ 0 should be specified if the utility is not a parser.
+
+ MessageCode - an application-specific warning code that can be referenced in
+ other documentation.
+
+ Text - the text in question (parsers)
+
+ MsgFmt - the format string for the warning message. Can contain formatting
+ controls for use with varargs.
+
+Returns:
+ None.
+
+--*/
+{
+ va_list List;
+ //
+ // If limits have been set, then check them
+ //
+ if (mPrintLimitsSet) {
+ //
+ // See if we've exceeded our total count
+ //
+ if (mMaxWarningsPlusErrors != 0) {
+ if (mErrorCount + mWarningCount > mMaxWarningsPlusErrors) {
+ PrintLimitExceeded ();
+ return ;
+ }
+ }
+ //
+ // See if we've exceeded our warning count
+ //
+ if (mMaxWarnings != 0) {
+ if (mWarningCount > mMaxWarnings) {
+ PrintLimitExceeded ();
+ return ;
+ }
+ }
+ }
+
+ mWarningCount++;
+ va_start (List, MsgFmt);
+ PrintMessage ("warning", FileName, LineNumber, MessageCode, Text, MsgFmt, List);
+ va_end (List);
+ //
+ // Set status accordingly
+ //
+ if (mStatus < STATUS_WARNING) {
+ mStatus = STATUS_WARNING;
+ }
+}
+
+void
+DebugMsg (
+ CHAR8 *FileName,
+ UINT32 LineNumber,
+ UINT32 MsgMask,
+ CHAR8 *Text,
+ CHAR8 *MsgFmt,
+ ...
+ )
+/*++
+
+Routine Description:
+ Print a warning message.
+
+Arguments:
+ FileName - typically the name of the utility printing the debug message, but
+ can be the name of a file being parsed.
+
+ LineNumber - the line number in FileName (parsers)
+
+ MsgMask - an application-specific bitmask that, in combination with mDebugMsgMask,
+ determines if the debug message gets printed.
+
+ Text - the text in question (parsers)
+
+ MsgFmt - the format string for the debug message. Can contain formatting
+ controls for use with varargs.
+
+Returns:
+ None.
+
+--*/
+{
+ va_list List;
+ //
+ // If the debug mask is not applicable, then do nothing.
+ //
+ if ((MsgMask != 0) && ((mDebugMsgMask & MsgMask) == 0)) {
+ return ;
+ }
+
+ va_start (List, MsgFmt);
+ PrintMessage ("debug", FileName, LineNumber, 0, Text, MsgFmt, List);
+ va_end (List);
+}
+
+static
+void
+PrintMessage (
+ CHAR8 *Type,
+ CHAR8 *FileName,
+ UINT32 LineNumber,
+ UINT32 MessageCode,
+ CHAR8 *Text,
+ CHAR8 *MsgFmt,
+ va_list List
+ )
+/*++
+
+Routine Description:
+ Worker routine for all the utility printing services. Prints the message in
+ a format that Visual Studio will find when scanning build outputs for
+ errors or warnings.
+
+Arguments:
+ Type - "warning" or "error" string to insert into the message to be
+ printed. The first character of this string (converted to uppercase)
+ is used to preceed the MessageCode value in the output string.
+
+ FileName - name of the file where the warning was detected, or the name
+ of the application that detected the warning
+
+ LineNumber - the line number where the warning was detected (parsers).
+ 0 should be specified if the utility is not a parser.
+
+ MessageCode - an application-specific warning code that can be referenced in
+ other documentation.
+
+ Text - part of the message to print
+
+ MsgFmt - the format string for the message. Can contain formatting
+ controls for use with varargs.
+ List - the variable list.
+
+Returns:
+ None.
+
+Notes:
+ If FileName == NULL then this utility will use the string passed into SetUtilityName().
+
+ LineNumber is only used if the caller is a parser, in which case FileName refers to the
+ file being parsed.
+
+ Text and MsgFmt are both optional, though it would be of little use calling this function with
+ them both NULL.
+
+ Output will typically be of the form:
+ <FileName>(<LineNumber>) : <Type> <Type[0]><MessageCode>: <Text> : <MsgFmt>
+
+ Parser (LineNumber != 0)
+ VfrCompile.cpp(330) : error E2660: AddVfrDataStructField : function does not take 2 parameters
+ Generic utility (LineNumber == 0)
+ UtilityName : error E1234 : Text string : MsgFmt string and args
+
+--*/
+{
+ CHAR8 Line[MAX_LINE_LEN];
+ CHAR8 Line2[MAX_LINE_LEN];
+ CHAR8 *Cptr;
+ //
+ // If given a filename, then add it (and the line number) to the string.
+ // If there's no filename, then use the program name if provided.
+ //
+ if (FileName != NULL) {
+ Cptr = FileName;
+ } else if (mUtilityName[0] != 0) {
+ Cptr = mUtilityName;
+ } else {
+ Cptr = "Unknown utility";
+ }
+
+ strcpy (Line, Cptr);
+ if (LineNumber != 0) {
+ sprintf (Line2, "(%d)", LineNumber);
+ strcat (Line, Line2);
+ }
+ //
+ // Have to print an error code or Visual Studio won't find the
+ // message for you. It has to be decimal digits too.
+ //
+ sprintf (Line2, " : %s %c%04d", Type, toupper (Type[0]), MessageCode);
+ strcat (Line, Line2);
+ fprintf (stdout, "%s", Line);
+ //
+ // If offending text was provided, then print it
+ //
+ if (Text != NULL) {
+ fprintf (stdout, ": %s ", Text);
+ }
+ //
+ // Print formatted message if provided
+ //
+ if (MsgFmt != NULL) {
+ vsprintf (Line2, MsgFmt, List);
+ fprintf (stdout, ": %s", Line2);
+ }
+
+ fprintf (stdout, "\n");
+}
+
+void
+ParserSetPosition (
+ CHAR8 *SourceFileName,
+ UINT32 LineNum
+ )
+/*++
+
+Routine Description:
+ Set the position in a file being parsed. This can be used to
+ print error messages deeper down in a parser.
+
+Arguments:
+ SourceFileName - name of the source file being parsed
+ LineNum - line number of the source file being parsed
+
+Returns:
+ NA
+
+--*/
+{
+ mSourceFileName = SourceFileName;
+ mSourceFileLineNum = LineNum;
+}
+
+void
+SetUtilityName (
+ CHAR8 *UtilityName
+ )
+/*++
+
+Routine Description:
+ All printed error/warning/debug messages follow the same format, and
+ typically will print a filename or utility name followed by the error
+ text. However if a filename is not passed to the print routines, then
+ they'll print the utility name if you call this function early in your
+ app to set the utility name.
+
+Arguments:
+ UtilityName - name of the utility, which will be printed with all
+ error/warning/debug messags.
+
+Returns:
+ NA
+
+--*/
+{
+ //
+ // Save the name of the utility in our local variable. Make sure its
+ // length does not exceed our buffer.
+ //
+ if (UtilityName != NULL) {
+ if (strlen (UtilityName) >= sizeof (mUtilityName)) {
+ Error (UtilityName, 0, 0, "application error", "utility name length exceeds internal buffer size");
+ strncpy (mUtilityName, UtilityName, sizeof (mUtilityName) - 1);
+ mUtilityName[sizeof (mUtilityName) - 1] = 0;
+ return ;
+ } else {
+ strcpy (mUtilityName, UtilityName);
+ }
+ } else {
+ Error (NULL, 0, 0, "application error", "SetUtilityName() called with NULL utility name");
+ }
+}
+
+STATUS
+GetUtilityStatus (
+ VOID
+ )
+/*++
+
+Routine Description:
+ When you call Error() or Warning(), this module keeps track of it and
+ sets a local mStatus to STATUS_ERROR or STATUS_WARNING. When the utility
+ exits, it can call this function to get the status and use it as a return
+ value.
+
+Arguments:
+ None.
+
+Returns:
+ Worst-case status reported, as defined by which print function was called.
+
+--*/
+{
+ return mStatus;
+}
+
+void
+SetDebugMsgMask (
+ UINT32 DebugMask
+ )
+/*++
+
+Routine Description:
+ Set the debug printing mask. This is used by the DebugMsg() function
+ to determine when/if a debug message should be printed.
+
+Arguments:
+ DebugMask - bitmask, specific to the calling application
+
+Returns:
+ NA
+
+--*/
+{
+ mDebugMsgMask = DebugMask;
+}
+
+void
+SetPrintLimits (
+ UINT32 MaxErrors,
+ UINT32 MaxWarnings,
+ UINT32 MaxWarningsPlusErrors
+ )
+/*++
+
+Routine Description:
+ Set the limits of how many errors, warnings, and errors+warnings
+ we will print.
+
+Arguments:
+ MaxErrors - maximum number of error messages to print
+ MaxWarnings - maximum number of warning messages to print
+ MaxWarningsPlusErrors
+ - maximum number of errors+warnings to print
+
+Returns:
+ NA
+
+--*/
+{
+ mMaxErrors = MaxErrors;
+ mMaxWarnings = MaxWarnings;
+ mMaxWarningsPlusErrors = MaxWarningsPlusErrors;
+ mPrintLimitsSet = 1;
+}
+
+static
+void
+PrintLimitExceeded (
+ VOID
+ )
+{
+ static INT8 mPrintLimitExceeded = 0;
+ //
+ // If we've already printed the message, do nothing. Otherwise
+ // temporarily increase our print limits so we can pass one
+ // more message through.
+ //
+ if (mPrintLimitExceeded == 0) {
+ mPrintLimitExceeded++;
+ mMaxErrors++;
+ mMaxWarnings++;
+ mMaxWarningsPlusErrors++;
+ Error (NULL, 0, 0, "error/warning print limit exceeded", NULL);
+ mMaxErrors--;
+ mMaxWarnings--;
+ mMaxWarningsPlusErrors--;
+ }
+}
+
+#if 0
+void
+TestUtilityMessages (
+ VOID
+ )
+{
+ char *ArgStr = "ArgString";
+ int ArgInt;
+
+ ArgInt = 0x12345678;
+ //
+ // Test without setting utility name
+ //
+ fprintf (stdout, "* Testing without setting utility name\n");
+ fprintf (stdout, "** Test debug message not printed\n");
+ DebugMsg (NULL, 0, 0x00000001, NULL, NULL);
+ fprintf (stdout, "** Test warning with two strings and two args\n");
+ Warning (NULL, 0, 1234, "Text1", "Text2 %s 0x%X", ArgStr, ArgInt);
+ fprintf (stdout, "** Test error with two strings and two args\n");
+ Warning (NULL, 0, 1234, "Text1", "Text2 %s 0x%X", ArgStr, ArgInt);
+ fprintf (stdout, "** Test parser warning with nothing\n");
+ ParserWarning (0, NULL, NULL);
+ fprintf (stdout, "** Test parser error with nothing\n");
+ ParserError (0, NULL, NULL);
+ //
+ // Test with utility name set now
+ //
+ fprintf (stdout, "** Testingin with utility name set\n");
+ SetUtilityName ("MyUtilityName");
+ //
+ // Test debug prints
+ //
+ SetDebugMsgMask (2);
+ fprintf (stdout, "** Test debug message with one string\n");
+ DebugMsg (NULL, 0, 0x00000002, "Text1", NULL);
+ fprintf (stdout, "** Test debug message with one string\n");
+ DebugMsg (NULL, 0, 0x00000002, NULL, "Text2");
+ fprintf (stdout, "** Test debug message with two strings\n");
+ DebugMsg (NULL, 0, 0x00000002, "Text1", "Text2");
+ fprintf (stdout, "** Test debug message with two strings and two args\n");
+ DebugMsg (NULL, 0, 0x00000002, "Text1", "Text2 %s 0x%X", ArgStr, ArgInt);
+ //
+ // Test warning prints
+ //
+ fprintf (stdout, "** Test warning with no strings\n");
+ Warning (NULL, 0, 1234, NULL, NULL);
+ fprintf (stdout, "** Test warning with one string\n");
+ Warning (NULL, 0, 1234, "Text1", NULL);
+ fprintf (stdout, "** Test warning with one string\n");
+ Warning (NULL, 0, 1234, NULL, "Text2");
+ fprintf (stdout, "** Test warning with two strings and two args\n");
+ Warning (NULL, 0, 1234, "Text1", "Text2 %s 0x%X", ArgStr, ArgInt);
+ //
+ // Test error prints
+ //
+ fprintf (stdout, "** Test error with no strings\n");
+ Error (NULL, 0, 1234, NULL, NULL);
+ fprintf (stdout, "** Test error with one string\n");
+ Error (NULL, 0, 1234, "Text1", NULL);
+ fprintf (stdout, "** Test error with one string\n");
+ Error (NULL, 0, 1234, NULL, "Text2");
+ fprintf (stdout, "** Test error with two strings and two args\n");
+ Error (NULL, 0, 1234, "Text1", "Text2 %s 0x%X", ArgStr, ArgInt);
+ //
+ // Test parser prints
+ //
+ fprintf (stdout, "** Test parser errors\n");
+ ParserSetPosition (__FILE__, __LINE__ + 1);
+ ParserError (1234, NULL, NULL);
+ ParserSetPosition (__FILE__, __LINE__ + 1);
+ ParserError (1234, "Text1", NULL);
+ ParserSetPosition (__FILE__, __LINE__ + 1);
+ ParserError (1234, NULL, "Text2");
+ ParserSetPosition (__FILE__, __LINE__ + 1);
+ ParserError (1234, "Text1", "Text2");
+ ParserSetPosition (__FILE__, __LINE__ + 1);
+ ParserError (1234, "Text1", "Text2 %s 0x%X", ArgStr, ArgInt);
+
+ fprintf (stdout, "** Test parser warnings\n");
+ ParserSetPosition (__FILE__, __LINE__ + 1);
+ ParserWarning (4321, NULL, NULL);
+ ParserSetPosition (__FILE__, __LINE__ + 1);
+ ParserWarning (4321, "Text1", NULL);
+ ParserSetPosition (__FILE__, __LINE__ + 1);
+ ParserWarning (4321, NULL, "Text2");
+ ParserSetPosition (__FILE__, __LINE__ + 1);
+ ParserWarning (4321, "Text1", "Text2");
+ ParserSetPosition (__FILE__, __LINE__ + 1);
+ ParserWarning (4321, "Text1", "Text2 %s 0x%X", ArgStr, ArgInt);
+}
+#endif
diff --git a/Source/Common/EfiUtilityMsgs.h b/Source/Common/EfiUtilityMsgs.h
new file mode 100644
index 0000000..a76b822
--- /dev/null
+++ b/Source/Common/EfiUtilityMsgs.h
@@ -0,0 +1,137 @@
+/*++
+
+Copyright (c) 2004, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ EfiUtilityMsgs.h
+
+Abstract:
+
+ Defines and prototypes for common EFI utility error and debug messages.
+
+--*/
+
+#ifndef _EFI_UTILITY_MSGS_H_
+#define _EFI_UTILITY_MSGS_H_
+
+#include <Common/UefiBaseTypes.h>
+
+//
+// Status codes returned by EFI utility programs and functions
+//
+#define STATUS_SUCCESS 0
+#define STATUS_WARNING 1
+#define STATUS_ERROR 2
+#define VOID void
+
+typedef int STATUS;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+//
+// When we call Error() or Warning(), the module keeps track of the worst
+// case reported. GetUtilityStatus() will get the worst-case results, which
+// can be used as the return value from the app.
+//
+STATUS
+GetUtilityStatus (
+ void
+ );
+
+//
+// If someone prints an error message and didn't specify a source file name,
+// then we print the utility name instead. However they must tell us the
+// utility name early on via this function.
+//
+void
+SetUtilityName (
+ CHAR8 *ProgramName
+ )
+;
+
+void
+Error (
+ CHAR8 *FileName,
+ UINT32 LineNumber,
+ UINT32 ErrorCode,
+ CHAR8 *OffendingText,
+ CHAR8 *MsgFmt,
+ ...
+ )
+;
+
+void
+Warning (
+ CHAR8 *FileName,
+ UINT32 LineNumber,
+ UINT32 ErrorCode,
+ CHAR8 *OffendingText,
+ CHAR8 *MsgFmt,
+ ...
+ )
+;
+
+void
+DebugMsg (
+ CHAR8 *FileName,
+ UINT32 LineNumber,
+ UINT32 MsgLevel,
+ CHAR8 *OffendingText,
+ CHAR8 *MsgFmt,
+ ...
+ )
+;
+
+void
+SetDebugMsgMask (
+ UINT32 MsgMask
+ )
+;
+
+void
+ParserSetPosition (
+ CHAR8 *SourceFileName,
+ UINT32 LineNum
+ )
+;
+
+void
+ParserError (
+ UINT32 ErrorCode,
+ CHAR8 *OffendingText,
+ CHAR8 *MsgFmt,
+ ...
+ )
+;
+
+void
+ParserWarning (
+ UINT32 ErrorCode,
+ CHAR8 *OffendingText,
+ CHAR8 *MsgFmt,
+ ...
+ )
+;
+
+void
+SetPrintLimits (
+ UINT32 NumErrors,
+ UINT32 NumWarnings,
+ UINT32 NumWarningsPlusErrors
+ )
+;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // #ifndef _EFI_UTILITY_MSGS_H_
diff --git a/Source/Common/FvLib.c b/Source/Common/FvLib.c
new file mode 100644
index 0000000..e8d6279
--- /dev/null
+++ b/Source/Common/FvLib.c
@@ -0,0 +1,780 @@
+/*++
+
+Copyright (c) 2004, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ FvLib.c
+
+Abstract:
+
+ These functions assist in parsing and manipulating a Firmware Volume.
+
+--*/
+
+//
+// Include files
+//
+#include "FvLib.h"
+#include "CommonLib.h"
+#include "EfiUtilityMsgs.h"
+
+//
+// Module global variables
+//
+EFI_FIRMWARE_VOLUME_HEADER *mFvHeader = NULL;
+UINT32 mFvLength = 0;
+
+//
+// External function implementations
+//
+EFI_STATUS
+InitializeFvLib (
+ IN VOID *Fv,
+ IN UINT32 FvLength
+ )
+/*++
+
+Routine Description:
+
+ This initializes the FV lib with a pointer to the FV and length. It does not
+ verify the FV in any way.
+
+Arguments:
+
+ Fv Buffer containing the FV.
+ FvLength Length of the FV
+
+Returns:
+
+ EFI_SUCCESS Function Completed successfully.
+ EFI_INVALID_PARAMETER A required parameter was NULL.
+
+--*/
+{
+ //
+ // Verify input arguments
+ //
+ if (Fv == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ mFvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) Fv;
+ mFvLength = FvLength;
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+GetFvHeader (
+ OUT EFI_FIRMWARE_VOLUME_HEADER **FvHeader,
+ OUT UINT32 *FvLength
+ )
+/*++
+
+Routine Description:
+
+ This function returns a pointer to the current FV and the size.
+
+Arguments:
+
+ FvHeader Pointer to the FV buffer.
+ FvLength Length of the FV
+
+Returns:
+
+ EFI_SUCCESS Function Completed successfully.
+ EFI_INVALID_PARAMETER A required parameter was NULL.
+ EFI_ABORTED The library needs to be initialized.
+
+--*/
+{
+ //
+ // Verify library has been initialized.
+ //
+ if (mFvHeader == NULL || mFvLength == 0) {
+ return EFI_ABORTED;
+ }
+ //
+ // Verify input arguments
+ //
+ if (FvHeader == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *FvHeader = mFvHeader;
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+GetNextFile (
+ IN EFI_FFS_FILE_HEADER *CurrentFile,
+ OUT EFI_FFS_FILE_HEADER **NextFile
+ )
+/*++
+
+Routine Description:
+
+ This function returns the next file. If the current file is NULL, it returns
+ the first file in the FV. If the function returns EFI_SUCCESS and the file
+ pointer is NULL, then there are no more files in the FV.
+
+Arguments:
+
+ CurrentFile Pointer to the current file, must be within the current FV.
+ NextFile Pointer to the next file in the FV.
+
+Returns:
+
+ EFI_SUCCESS Function completed successfully.
+ EFI_INVALID_PARAMETER A required parameter was NULL or is out of range.
+ EFI_ABORTED The library needs to be initialized.
+
+--*/
+{
+ EFI_STATUS Status;
+
+ //
+ // Verify library has been initialized.
+ //
+ if (mFvHeader == NULL || mFvLength == 0) {
+ return EFI_ABORTED;
+ }
+ //
+ // Verify input arguments
+ //
+ if (NextFile == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // Verify FV header
+ //
+ Status = VerifyFv (mFvHeader);
+ if (EFI_ERROR (Status)) {
+ return EFI_ABORTED;
+ }
+ //
+ // Get first file
+ //
+ if (CurrentFile == NULL) {
+ CurrentFile = (EFI_FFS_FILE_HEADER *) ((UINTN) mFvHeader + mFvHeader->HeaderLength);
+
+ //
+ // Verify file is valid
+ //
+ Status = VerifyFfsFile (CurrentFile);
+ if (EFI_ERROR (Status)) {
+ //
+ // no files in this FV
+ //
+ *NextFile = NULL;
+ return EFI_SUCCESS;
+ } else {
+ //
+ // Verify file is in this FV.
+ //
+ if ((UINTN) CurrentFile >= (UINTN) mFvHeader + mFvLength - sizeof (EFI_FFS_FILE_HEADER)) {
+ *NextFile = NULL;
+ return EFI_SUCCESS;
+ }
+
+ *NextFile = CurrentFile;
+ return EFI_SUCCESS;
+ }
+ }
+ //
+ // Verify current file is in range
+ //
+ if (((UINTN) CurrentFile < (UINTN) mFvHeader + sizeof (EFI_FIRMWARE_VOLUME_HEADER)) ||
+ ((UINTN) CurrentFile >= (UINTN) mFvHeader + mFvLength - sizeof (EFI_FIRMWARE_VOLUME_HEADER))
+ ) {
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // Get next file, compensate for 8 byte alignment if necessary.
+ //
+ *NextFile = (EFI_FFS_FILE_HEADER *) (((UINTN) CurrentFile + GetLength (CurrentFile->Size) + 0x07) & (-1 << 3));
+
+ //
+ // Verify file is in this FV.
+ //
+ if ((UINTN) *NextFile >= (UINTN) mFvHeader + mFvLength - sizeof (EFI_FFS_FILE_HEADER)) {
+ *NextFile = NULL;
+ return EFI_SUCCESS;
+ }
+ //
+ // Verify file is valid
+ //
+ Status = VerifyFfsFile (*NextFile);
+ if (EFI_ERROR (Status)) {
+ //
+ // no more files in this FV
+ //
+ *NextFile = NULL;
+ return EFI_SUCCESS;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+GetFileByName (
+ IN EFI_GUID *FileName,
+ OUT EFI_FFS_FILE_HEADER **File
+ )
+/*++
+
+Routine Description:
+
+ Find a file by name. The function will return NULL if the file is not found.
+
+Arguments:
+
+ FileName The GUID file name of the file to search for.
+ File Return pointer. In the case of an error, contents are undefined.
+
+Returns:
+
+ EFI_SUCCESS The function completed successfully.
+ EFI_ABORTED An error was encountered.
+ EFI_INVALID_PARAMETER One of the parameters was NULL.
+
+--*/
+{
+ EFI_FFS_FILE_HEADER *CurrentFile;
+ EFI_STATUS Status;
+
+ //
+ // Verify library has been initialized.
+ //
+ if (mFvHeader == NULL || mFvLength == 0) {
+ return EFI_ABORTED;
+ }
+ //
+ // Verify input parameters
+ //
+ if (FileName == NULL || File == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // Verify FV header
+ //
+ Status = VerifyFv (mFvHeader);
+ if (EFI_ERROR (Status)) {
+ return EFI_ABORTED;
+ }
+ //
+ // Get the first file
+ //
+ Status = GetNextFile (NULL, &CurrentFile);
+ if (EFI_ERROR (Status)) {
+ Error (NULL, 0, 0, "error parsing the FV", NULL);
+ return EFI_ABORTED;
+ }
+ //
+ // Loop as long as we have a valid file
+ //
+ while (CurrentFile) {
+ if (!CompareGuid (&CurrentFile->Name, FileName)) {
+ *File = CurrentFile;
+ return EFI_SUCCESS;
+ }
+
+ Status = GetNextFile (CurrentFile, &CurrentFile);
+ if (EFI_ERROR (Status)) {
+ Error (NULL, 0, 0, "error parsing the FV", NULL);
+ return EFI_ABORTED;
+ }
+ }
+ //
+ // File not found in this FV.
+ //
+ *File = NULL;
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+GetFileByType (
+ IN EFI_FV_FILETYPE FileType,
+ IN UINTN Instance,
+ OUT EFI_FFS_FILE_HEADER **File
+ )
+/*++
+
+Routine Description:
+
+ Find a file by type and instance. An instance of 1 is the first instance.
+ The function will return NULL if a matching file cannot be found.
+ File type EFI_FV_FILETYPE_ALL means any file type is valid.
+
+Arguments:
+
+ FileType Type of file to search for.
+ Instance Instace of the file type to return.
+ File Return pointer. In the case of an error, contents are undefined.
+
+Returns:
+
+ EFI_SUCCESS The function completed successfully.
+ EFI_ABORTED An error was encountered.
+ EFI_INVALID_PARAMETER One of the parameters was NULL.
+
+--*/
+{
+ EFI_FFS_FILE_HEADER *CurrentFile;
+ EFI_STATUS Status;
+ UINTN FileCount;
+
+ //
+ // Verify library has been initialized.
+ //
+ if (mFvHeader == NULL || mFvLength == 0) {
+ return EFI_ABORTED;
+ }
+ //
+ // Verify input parameters
+ //
+ if (File == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // Verify FV header
+ //
+ Status = VerifyFv (mFvHeader);
+ if (EFI_ERROR (Status)) {
+ return EFI_ABORTED;
+ }
+ //
+ // Initialize the number of matching files found.
+ //
+ FileCount = 0;
+
+ //
+ // Get the first file
+ //
+ Status = GetNextFile (NULL, &CurrentFile);
+ if (EFI_ERROR (Status)) {
+ Error (NULL, 0, 0, "error parsing FV", NULL);
+ return EFI_ABORTED;
+ }
+ //
+ // Loop as long as we have a valid file
+ //
+ while (CurrentFile) {
+ if (FileType == EFI_FV_FILETYPE_ALL || CurrentFile->Type == FileType) {
+ FileCount++;
+ }
+
+ if (FileCount == Instance) {
+ *File = CurrentFile;
+ return EFI_SUCCESS;
+ }
+
+ Status = GetNextFile (CurrentFile, &CurrentFile);
+ if (EFI_ERROR (Status)) {
+ Error (NULL, 0, 0, "error parsing the FV", NULL);
+ return EFI_ABORTED;
+ }
+ }
+
+ *File = NULL;
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+GetSectionByType (
+ IN EFI_FFS_FILE_HEADER *File,
+ IN EFI_SECTION_TYPE SectionType,
+ IN UINTN Instance,
+ OUT EFI_FILE_SECTION_POINTER *Section
+ )
+/*++
+
+Routine Description:
+
+ Find a section in a file by type and instance. An instance of 1 is the first
+ instance. The function will return NULL if a matching section cannot be found.
+ The function will not handle encapsulating sections.
+
+Arguments:
+
+ File The file to search.
+ SectionType Type of file to search for.
+ Instance Instace of the section to return.
+ Section Return pointer. In the case of an error, contents are undefined.
+
+Returns:
+
+ EFI_SUCCESS The function completed successfully.
+ EFI_ABORTED An error was encountered.
+ EFI_INVALID_PARAMETER One of the parameters was NULL.
+ EFI_NOT_FOUND No found.
+--*/
+{
+ EFI_FILE_SECTION_POINTER CurrentSection;
+ EFI_STATUS Status;
+ UINTN SectionCount;
+
+ //
+ // Verify input parameters
+ //
+ if (File == NULL || Instance == 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // Verify FFS header
+ //
+ Status = VerifyFfsFile (File);
+ if (EFI_ERROR (Status)) {
+ Error (NULL, 0, 0, "invalid FFS file", NULL);
+ return EFI_ABORTED;
+ }
+ //
+ // Initialize the number of matching sections found.
+ //
+ SectionCount = 0;
+
+ //
+ // Get the first section
+ //
+ CurrentSection.CommonHeader = (EFI_COMMON_SECTION_HEADER *) ((UINTN) File + sizeof (EFI_FFS_FILE_HEADER));
+
+ //
+ // Loop as long as we have a valid file
+ //
+ while ((UINTN) CurrentSection.CommonHeader < (UINTN) File + GetLength (File->Size)) {
+ if (CurrentSection.CommonHeader->Type == SectionType) {
+ SectionCount++;
+ }
+
+ if (SectionCount == Instance) {
+ *Section = CurrentSection;
+ return EFI_SUCCESS;
+ }
+ //
+ // Find next section (including compensating for alignment issues.
+ //
+ CurrentSection.CommonHeader = (EFI_COMMON_SECTION_HEADER *) ((((UINTN) CurrentSection.CommonHeader) + GetLength (CurrentSection.CommonHeader->Size) + 0x03) & (-1 << 2));
+ }
+ //
+ // Section not found
+ //
+ (*Section).Code16Section = NULL;
+ return EFI_NOT_FOUND;
+}
+//
+// will not parse compressed sections
+//
+EFI_STATUS
+VerifyFv (
+ IN EFI_FIRMWARE_VOLUME_HEADER *FvHeader
+ )
+/*++
+
+Routine Description:
+
+ Verify the current pointer points to a valid FV header.
+
+Arguments:
+
+ FvHeader Pointer to an alleged FV file.
+
+Returns:
+
+ EFI_SUCCESS The FV header is valid.
+ EFI_VOLUME_CORRUPTED The FV header is not valid.
+ EFI_INVALID_PARAMETER A required parameter was NULL.
+ EFI_ABORTED Operation aborted.
+
+--*/
+{
+ UINT16 Checksum;
+
+ //
+ // Verify input parameters
+ //
+ if (FvHeader == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (FvHeader->Signature != EFI_FVH_SIGNATURE) {
+ Error (NULL, 0, 0, "invalid FV header signature", NULL);
+ return EFI_VOLUME_CORRUPTED;
+ }
+ //
+ // Verify header checksum
+ //
+ Checksum = CalculateSum16 ((UINT16 *) FvHeader, FvHeader->HeaderLength / sizeof (UINT16));
+
+ if (Checksum != 0) {
+ Error (NULL, 0, 0, "invalid FV header checksum", NULL);
+ return EFI_ABORTED;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+VerifyFfsFile (
+ IN EFI_FFS_FILE_HEADER *FfsHeader
+ )
+/*++
+
+Routine Description:
+
+ Verify the current pointer points to a FFS file header.
+
+Arguments:
+
+ FfsHeader Pointer to an alleged FFS file.
+
+Returns:
+
+ EFI_SUCCESS The Ffs header is valid.
+ EFI_NOT_FOUND This "file" is the beginning of free space.
+ EFI_VOLUME_CORRUPTED The Ffs header is not valid.
+ EFI_ABORTED The erase polarity is not known.
+
+--*/
+{
+ BOOLEAN ErasePolarity;
+ EFI_STATUS Status;
+ EFI_FFS_FILE_HEADER BlankHeader;
+ UINT8 Checksum;
+ UINT32 FileLength;
+ UINT32 OccupiedFileLength;
+ EFI_FFS_FILE_TAIL *Tail;
+ UINT8 SavedChecksum;
+ UINT8 SavedState;
+ UINT8 FileGuidString[80];
+ UINT32 TailSize;
+ //
+ // Verify library has been initialized.
+ //
+ if (mFvHeader == NULL || mFvLength == 0) {
+ return EFI_ABORTED;
+ }
+ //
+ // Verify FV header
+ //
+ Status = VerifyFv (mFvHeader);
+ if (EFI_ERROR (Status)) {
+ return EFI_ABORTED;
+ }
+ //
+ // Get the erase polarity.
+ //
+ Status = GetErasePolarity (&ErasePolarity);
+ if (EFI_ERROR (Status)) {
+ return EFI_ABORTED;
+ }
+ //
+ // Check if we have free space
+ //
+ if (ErasePolarity) {
+ memset (&BlankHeader, -1, sizeof (EFI_FFS_FILE_HEADER));
+ } else {
+ memset (&BlankHeader, 0, sizeof (EFI_FFS_FILE_HEADER));
+ }
+
+ if (memcmp (&BlankHeader, FfsHeader, sizeof (EFI_FFS_FILE_HEADER)) == 0) {
+ return EFI_NOT_FOUND;
+ }
+ //
+ // Convert the GUID to a string so we can at least report which file
+ // if we find an error.
+ //
+ PrintGuidToBuffer (&FfsHeader->Name, FileGuidString, sizeof (FileGuidString), TRUE);
+ if (FfsHeader->Attributes & FFS_ATTRIB_TAIL_PRESENT) {
+ TailSize = sizeof (EFI_FFS_FILE_TAIL);
+ } else {
+ TailSize = 0;
+ }
+ //
+ // Verify file header checksum
+ //
+ SavedState = FfsHeader->State;
+ FfsHeader->State = 0;
+ SavedChecksum = FfsHeader->IntegrityCheck.Checksum.File;
+ FfsHeader->IntegrityCheck.Checksum.File = 0;
+ Checksum = CalculateSum8 ((UINT8 *) FfsHeader, sizeof (EFI_FFS_FILE_HEADER));
+ FfsHeader->State = SavedState;
+ FfsHeader->IntegrityCheck.Checksum.File = SavedChecksum;
+ if (Checksum != 0) {
+ Error (NULL, 0, 0, FileGuidString, "invalid FFS file header checksum");
+ return EFI_ABORTED;
+ }
+ //
+ // Verify file checksum
+ //
+ if (FfsHeader->Attributes & FFS_ATTRIB_CHECKSUM) {
+ //
+ // Verify file data checksum
+ //
+ FileLength = GetLength (FfsHeader->Size);
+ OccupiedFileLength = (FileLength + 0x07) & (-1 << 3);
+ Checksum = CalculateSum8 ((UINT8 *) FfsHeader, FileLength - TailSize);
+ Checksum = (UINT8) (Checksum - FfsHeader->State);
+ if (Checksum != 0) {
+ Error (NULL, 0, 0, FileGuidString, "invalid FFS file checksum");
+ return EFI_ABORTED;
+ }
+ } else {
+ //
+ // File does not have a checksum
+ // Verify contents are 0x5A as spec'd
+ //
+ if (FfsHeader->IntegrityCheck.Checksum.File != FFS_FIXED_CHECKSUM) {
+ Error (NULL, 0, 0, FileGuidString, "invalid fixed FFS file header checksum");
+ return EFI_ABORTED;
+ }
+ }
+ //
+ // Check if the tail is present and verify it if it is.
+ //
+ if (FfsHeader->Attributes & FFS_ATTRIB_TAIL_PRESENT) {
+ //
+ // Verify tail is complement of integrity check field in the header.
+ //
+ Tail = (EFI_FFS_FILE_TAIL *) ((UINTN) FfsHeader + GetLength (FfsHeader->Size) - sizeof (EFI_FFS_FILE_TAIL));
+ if (FfsHeader->IntegrityCheck.TailReference != (EFI_FFS_FILE_TAIL)~(*Tail)) {
+ Error (NULL, 0, 0, FileGuidString, "invalid FFS file tail");
+ return EFI_ABORTED;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+UINT32
+GetLength (
+ UINT8 *ThreeByteLength
+ )
+/*++
+
+Routine Description:
+
+ Converts a three byte length value into a UINT32.
+
+Arguments:
+
+ ThreeByteLength Pointer to the first of the 3 byte length.
+
+Returns:
+
+ UINT32 Size of the section
+
+--*/
+{
+ UINT32 Length;
+
+ if (ThreeByteLength == NULL) {
+ return 0;
+ }
+
+ Length = *((UINT32 *) ThreeByteLength);
+ Length = Length & 0x00FFFFFF;
+
+ return Length;
+}
+
+EFI_STATUS
+GetErasePolarity (
+ OUT BOOLEAN *ErasePolarity
+ )
+/*++
+
+Routine Description:
+
+ This function returns with the FV erase polarity. If the erase polarity
+ for a bit is 1, the function return TRUE.
+
+Arguments:
+
+ ErasePolarity A pointer to the erase polarity.
+
+Returns:
+
+ EFI_SUCCESS The function completed successfully.
+ EFI_INVALID_PARAMETER One of the input parameters was invalid.
+ EFI_ABORTED Operation aborted.
+
+--*/
+{
+ EFI_STATUS Status;
+
+ //
+ // Verify library has been initialized.
+ //
+ if (mFvHeader == NULL || mFvLength == 0) {
+ return EFI_ABORTED;
+ }
+ //
+ // Verify FV header
+ //
+ Status = VerifyFv (mFvHeader);
+ if (EFI_ERROR (Status)) {
+ return EFI_ABORTED;
+ }
+ //
+ // Verify input parameters.
+ //
+ if (ErasePolarity == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (mFvHeader->Attributes & EFI_FVB_ERASE_POLARITY) {
+ *ErasePolarity = TRUE;
+ } else {
+ *ErasePolarity = FALSE;
+ }
+
+ return EFI_SUCCESS;
+}
+
+UINT8
+GetFileState (
+ IN BOOLEAN ErasePolarity,
+ IN EFI_FFS_FILE_HEADER *FfsHeader
+ )
+/*++
+
+Routine Description:
+
+ This function returns a the highest state bit in the FFS that is set.
+ It in no way validate the FFS file.
+
+Arguments:
+
+ ErasePolarity The erase polarity for the file state bits.
+ FfsHeader Pointer to a FFS file.
+
+Returns:
+
+ UINT8 The hightest set state of the file.
+
+--*/
+{
+ UINT8 FileState;
+ UINT8 HighestBit;
+
+ FileState = FfsHeader->State;
+
+ if (ErasePolarity) {
+ FileState = (UINT8)~FileState;
+ }
+
+ HighestBit = 0x80;
+ while (HighestBit != 0 && (HighestBit & FileState) == 0) {
+ HighestBit >>= 1;
+ }
+
+ return HighestBit;
+}
diff --git a/Source/Common/FvLib.h b/Source/Common/FvLib.h
new file mode 100644
index 0000000..1ad1e81
--- /dev/null
+++ b/Source/Common/FvLib.h
@@ -0,0 +1,181 @@
+/*++
+
+Copyright (c) 2004, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ FvLib.h
+
+Abstract:
+
+ These functions assist in parsing and manipulating a Firmware Volume.
+
+--*/
+
+#ifndef _EFI_FV_LIB_H
+#define _EFI_FV_LIB_H
+
+//
+// Include files
+//
+#include <string.h>
+
+#include <Common/UefiBaseTypes.h>
+#include <Common/EfiImage.h>
+#include <Common/FirmwareVolumeImageFormat.h>
+#include <Common/FirmwareFileSystem.h>
+#include <Common/FirmwareVolumeHeader.h>
+#include <Common/MultiPhase.h>
+
+EFI_STATUS
+InitializeFvLib (
+ IN VOID *Fv,
+ IN UINT32 FvLength
+ )
+;
+
+EFI_STATUS
+GetFvHeader (
+ OUT EFI_FIRMWARE_VOLUME_HEADER **FvHeader,
+ OUT UINT32 *FvLength
+ )
+;
+
+EFI_STATUS
+GetNextFile (
+ IN EFI_FFS_FILE_HEADER *CurrentFile,
+ OUT EFI_FFS_FILE_HEADER **NextFile
+ )
+;
+
+EFI_STATUS
+GetFileByName (
+ IN EFI_GUID *FileName,
+ OUT EFI_FFS_FILE_HEADER **File
+ )
+;
+
+EFI_STATUS
+GetFileByType (
+ IN EFI_FV_FILETYPE FileType,
+ IN UINTN Instance,
+ OUT EFI_FFS_FILE_HEADER **File
+ )
+;
+
+EFI_STATUS
+GetSectionByType (
+ IN EFI_FFS_FILE_HEADER *File,
+ IN EFI_SECTION_TYPE SectionType,
+ IN UINTN Instance,
+ OUT EFI_FILE_SECTION_POINTER *Section
+ )
+;
+//
+// will not parse compressed sections
+//
+EFI_STATUS
+VerifyFv (
+ IN EFI_FIRMWARE_VOLUME_HEADER *FvHeader
+ )
+;
+
+EFI_STATUS
+VerifyFfsFile (
+ IN EFI_FFS_FILE_HEADER *FfsHeader
+ )
+;
+
+/*++
+
+Routine Description:
+
+ Verify the current pointer points to a FFS file header.
+
+Arguments:
+
+ FfsHeader Pointer to an alleged FFS file.
+
+Returns:
+
+ EFI_SUCCESS The Ffs header is valid.
+ EFI_NOT_FOUND This "file" is the beginning of free space.
+ EFI_VOLUME_CORRUPTED The Ffs header is not valid.
+
+--*/
+UINT32
+GetLength (
+ UINT8 *ThreeByteLength
+ )
+;
+
+/*++
+
+Routine Description:
+
+ Converts a three byte length value into a UINT32.
+
+Arguments:
+
+ ThreeByteLength Pointer to the first of the 3 byte length.
+
+Returns:
+
+ UINT32 Size of the section
+
+--*/
+EFI_STATUS
+GetErasePolarity (
+ OUT BOOLEAN *ErasePolarity
+ )
+;
+
+/*++
+
+Routine Description:
+
+ This function returns with the FV erase polarity. If the erase polarity
+ for a bit is 1, the function return TRUE.
+
+Arguments:
+
+ ErasePolarity A pointer to the erase polarity.
+
+Returns:
+
+ EFI_SUCCESS The function completed successfully.
+ EFI_INVALID_PARAMETER One of the input parameters was invalid.
+
+--*/
+UINT8
+GetFileState (
+ IN BOOLEAN ErasePolarity,
+ IN EFI_FFS_FILE_HEADER *FfsHeader
+ )
+;
+
+/*++
+
+Routine Description:
+
+ This function returns a the highest state bit in the FFS that is set.
+ It in no way validate the FFS file.
+
+Arguments:
+
+ ErasePolarity The erase polarity for the file state bits.
+ FfsHeader Pointer to a FFS file.
+
+Returns:
+
+ UINT8 The hightest set state of the file.
+
+--*/
+#endif
diff --git a/Source/Common/MyAlloc.c b/Source/Common/MyAlloc.c
new file mode 100644
index 0000000..39fddf7
--- /dev/null
+++ b/Source/Common/MyAlloc.c
@@ -0,0 +1,516 @@
+/*++
+
+Copyright (c) 2004, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ MyAlloc.c
+
+Abstract:
+
+ File for memory allocation tracking functions.
+
+--*/
+
+#include "MyAlloc.h"
+
+#if USE_MYALLOC
+//
+// Get back to original alloc/free calls.
+//
+#undef malloc
+#undef calloc
+#undef realloc
+#undef free
+//
+// Start of allocation list.
+//
+static MY_ALLOC_STRUCT *MyAllocData = NULL;
+
+//
+//
+//
+static UINT32 MyAllocHeadMagik = MYALLOC_HEAD_MAGIK;
+static UINT32 MyAllocTailMagik = MYALLOC_TAIL_MAGIK;
+
+//
+// ////////////////////////////////////////////////////////////////////////////
+//
+//
+VOID
+MyCheck (
+ BOOLEAN Final,
+ UINT8 File[],
+ UINTN Line
+ )
+// *++
+// Description:
+//
+// Check for corruptions in the allocated memory chain. If a corruption
+// is detection program operation stops w/ an exit(1) call.
+//
+// Parameters:
+//
+// Final := When FALSE, MyCheck() returns if the allocated memory chain
+// has not been corrupted. When TRUE, MyCheck() returns if there
+// are no un-freed allocations. If there are un-freed allocations,
+// they are displayed and exit(1) is called.
+//
+//
+// File := Set to __FILE__ by macro expansion.
+//
+// Line := Set to __LINE__ by macro expansion.
+//
+// Returns:
+//
+// n/a
+//
+// --*/
+//
+{
+ MY_ALLOC_STRUCT *Tmp;
+
+ //
+ // Check parameters.
+ //
+ if (File == NULL || Line == 0) {
+ printf (
+ "\nMyCheck(Final=%u, File=%xh, Line=%u)"
+ "Invalid parameter(s).\n",
+ Final,
+ File,
+ Line
+ );
+
+ exit (1);
+ }
+
+ if (strlen (File) == 0) {
+ printf (
+ "\nMyCheck(Final=%u, File=%s, Line=%u)"
+ "Invalid parameter.\n",
+ Final,
+ File,
+ Line
+ );
+
+ exit (1);
+ }
+ //
+ // Check structure contents.
+ //
+ for (Tmp = MyAllocData; Tmp != NULL; Tmp = Tmp->Next) {
+ if (memcmp(Tmp->Buffer, &MyAllocHeadMagik, sizeof MyAllocHeadMagik) ||
+ memcmp(&Tmp->Buffer[Tmp->Size + sizeof(UINT32)], &MyAllocTailMagik, sizeof MyAllocTailMagik)) {
+ break;
+ }
+ }
+ //
+ // If Tmp is not NULL, the structure is corrupt.
+ //
+ if (Tmp != NULL) {
+ printf (
+ "\nMyCheck(Final=%u, File=%s, Line=%u)""\nStructure corrupted!"
+ "\nFile=%s, Line=%u, nSize=%u, Head=%xh, Tail=%xh\n",
+ Final,
+ File,
+ Line,
+ Tmp->File,
+ Tmp->Line,
+ Tmp->Size,
+ *(UINT32 *) (Tmp->Buffer),
+ *(UINT32 *) (&Tmp->Buffer[Tmp->Size + sizeof (UINT32)])
+ );
+
+ exit (1);
+ }
+ //
+ // If Final is TRUE, display the state of the structure chain.
+ //
+ if (Final) {
+ if (MyAllocData != NULL) {
+ printf (
+ "\nMyCheck(Final=%u, File=%s, Line=%u)"
+ "\nSome allocated items have not been freed.\n",
+ Final,
+ File,
+ Line
+ );
+
+ for (Tmp = MyAllocData; Tmp != NULL; Tmp = Tmp->Next) {
+ printf (
+ "File=%s, Line=%u, nSize=%u, Head=%xh, Tail=%xh\n",
+ Tmp->File,
+ Tmp->Line,
+ Tmp->Size,
+ *(UINT32 *) (Tmp->Buffer),
+ *(UINT32 *) (&Tmp->Buffer[Tmp->Size + sizeof (UINT32)])
+ );
+ }
+ }
+ }
+}
+//
+// ////////////////////////////////////////////////////////////////////////////
+//
+//
+VOID *
+MyAlloc (
+ UINTN Size,
+ UINT8 File[],
+ UINTN Line
+ )
+// *++
+// Description:
+//
+// Allocate a new link in the allocation chain along with enough storage
+// for the File[] string, requested Size and alignment overhead. If
+// memory cannot be allocated or the allocation chain has been corrupted,
+// exit(1) will be called.
+//
+// Parameters:
+//
+// Size := Number of bytes (UINT8) requested by the called.
+// Size cannot be zero.
+//
+// File := Set to __FILE__ by macro expansion.
+//
+// Line := Set to __LINE__ by macro expansion.
+//
+// Returns:
+//
+// Pointer to the caller's buffer.
+//
+// --*/
+//
+{
+ MY_ALLOC_STRUCT *Tmp;
+ UINTN Len;
+
+ //
+ // Check for invalid parameters.
+ //
+ if (Size == 0 || File == NULL || Line == 0) {
+ printf (
+ "\nMyAlloc(Size=%u, File=%xh, Line=%u)"
+ "\nInvalid parameter(s).\n",
+ Size,
+ File,
+ Line
+ );
+
+ exit (1);
+ }
+
+ Len = strlen (File);
+ if (Len == 0) {
+ printf (
+ "\nMyAlloc(Size=%u, File=%s, Line=%u)"
+ "\nInvalid parameter.\n",
+ Size,
+ File,
+ Line
+ );
+
+ exit (1);
+ }
+ //
+ // Check the allocation list for corruption.
+ //
+ MyCheck (0, __FILE__, __LINE__);
+
+ //
+ // Allocate a new entry.
+ //
+ Tmp = calloc (
+ 1,
+ sizeof (MY_ALLOC_STRUCT) + Len + 1 + sizeof (UINT64) + Size + (sizeof MyAllocHeadMagik) + (sizeof MyAllocTailMagik)
+ );
+
+ if (Tmp == NULL) {
+ printf (
+ "\nMyAlloc(Size=%u, File=%s, Line=%u)"
+ "\nOut of memory.\n",
+ Size,
+ File,
+ Line
+ );
+
+ exit (1);
+ }
+ //
+ // Fill in the new entry.
+ //
+ Tmp->File = ((UINT8 *) Tmp) + sizeof (MY_ALLOC_STRUCT);
+ strcpy (Tmp->File, File);
+ Tmp->Line = Line;
+ Tmp->Size = Size;
+ Tmp->Buffer = (UINT8 *) (((UINTN) Tmp + Len + 9) &~7);
+
+ memcpy (Tmp->Buffer, &MyAllocHeadMagik, sizeof MyAllocHeadMagik);
+
+ memcpy (
+ &Tmp->Buffer[Size + sizeof (UINT32)],
+ &MyAllocTailMagik,
+ sizeof MyAllocTailMagik
+ );
+
+ Tmp->Next = MyAllocData;
+ Tmp->Cksum = (UINTN) Tmp + (UINTN) (Tmp->Next) + Tmp->Line + Tmp->Size + (UINTN) (Tmp->File) + (UINTN) (Tmp->Buffer);
+
+ MyAllocData = Tmp;
+
+ return Tmp->Buffer + sizeof (UINT32);
+}
+//
+// ////////////////////////////////////////////////////////////////////////////
+//
+//
+VOID *
+MyRealloc (
+ VOID *Ptr,
+ UINTN Size,
+ UINT8 File[],
+ UINTN Line
+ )
+// *++
+// Description:
+//
+// This does a MyAlloc(), memcpy() and MyFree(). There is no optimization
+// for shrinking or expanding buffers. An invalid parameter will cause
+// MyRealloc() to fail with a call to exit(1).
+//
+// Parameters:
+//
+// Ptr := Pointer to the caller's buffer to be re-allocated.
+//
+// Size := Size of new buffer. Size cannot be zero.
+//
+// File := Set to __FILE__ by macro expansion.
+//
+// Line := Set to __LINE__ by macro expansion.
+//
+// Returns:
+//
+// Pointer to new caller's buffer.
+//
+// --*/
+//
+{
+ MY_ALLOC_STRUCT *Tmp;
+ VOID *Buffer;
+
+ //
+ // Check for invalid parameter(s).
+ //
+ if (Size == 0 || File == NULL || Line == 0) {
+ printf (
+ "\nMyRealloc(Ptr=%xh, Size=%u, File=%xh, Line=%u)"
+ "\nInvalid parameter(s).\n",
+ Ptr,
+ Size,
+ File,
+ Line
+ );
+
+ exit (1);
+ }
+
+ if (strlen (File) == 0) {
+ printf (
+ "\nMyRealloc(Ptr=%xh, Size=%u, File=%s, Line=%u)"
+ "\nInvalid parameter.\n",
+ Ptr,
+ Size,
+ File,
+ Line
+ );
+
+ exit (1);
+ }
+ //
+ // Find existing buffer in allocation list.
+ //
+ if (Ptr == NULL) {
+ Tmp = NULL;
+ } else if (&MyAllocData->Buffer[sizeof (UINT32)] == Ptr) {
+ Tmp = MyAllocData;
+ } else {
+ for (Tmp = MyAllocData;; Tmp = Tmp->Next) {
+ if (Tmp->Next == NULL) {
+ printf (
+ "\nMyRealloc(Ptr=%xh, Size=%u, File=%s, Line=%u)"
+ "\nCould not find buffer.\n",
+ Ptr,
+ Size,
+ File,
+ Line
+ );
+
+ exit (1);
+ }
+
+ Tmp = Tmp->Next;
+ }
+ }
+ //
+ // Allocate new buffer, copy old data, free old buffer.
+ //
+ Buffer = MyAlloc (Size, File, Line);
+
+ if (Buffer != NULL && Tmp != NULL) {
+ memcpy (
+ Buffer,
+ &Tmp->Buffer[sizeof (UINT32)],
+ ((Size <= Tmp->Size) ? Size : Tmp->Size)
+ );
+
+ MyFree (Ptr, __FILE__, __LINE__);
+ }
+
+ return Buffer;
+}
+//
+// ////////////////////////////////////////////////////////////////////////////
+//
+//
+VOID
+MyFree (
+ VOID *Ptr,
+ UINT8 File[],
+ UINTN Line
+ )
+// *++
+// Description:
+//
+// Release a previously allocated buffer. Invalid parameters will cause
+// MyFree() to fail with an exit(1) call.
+//
+// Parameters:
+//
+// Ptr := Pointer to the caller's buffer to be freed.
+// A NULL pointer will be ignored.
+//
+// File := Set to __FILE__ by macro expansion.
+//
+// Line := Set to __LINE__ by macro expansion.
+//
+// Returns:
+//
+// n/a
+//
+// --*/
+//
+{
+ MY_ALLOC_STRUCT *Tmp;
+ MY_ALLOC_STRUCT *Tmp2;
+
+ //
+ // Check for invalid parameter(s).
+ //
+ if (File == NULL || Line == 0) {
+ printf (
+ "\nMyFree(Ptr=%xh, File=%xh, Line=%u)"
+ "\nInvalid parameter(s).\n",
+ Ptr,
+ File,
+ Line
+ );
+
+ exit (1);
+ }
+
+ if (strlen (File) == 0) {
+ printf (
+ "\nMyFree(Ptr=%xh, File=%s, Line=%u)"
+ "\nInvalid parameter.\n",
+ Ptr,
+ File,
+ Line
+ );
+
+ exit (1);
+ }
+ //
+ // Freeing NULL is always valid.
+ //
+ if (Ptr == NULL) {
+ return ;
+ }
+ //
+ // Fail if nothing is allocated.
+ //
+ if (MyAllocData == NULL) {
+ printf (
+ "\nMyFree(Ptr=%xh, File=%s, Line=%u)"
+ "\nCalled before memory allocated.\n",
+ Ptr,
+ File,
+ Line
+ );
+
+ exit (1);
+ }
+ //
+ // Check for corrupted allocation list.
+ //
+ MyCheck (0, __FILE__, __LINE__);
+
+ //
+ // Need special check for first item in list.
+ //
+ if (&MyAllocData->Buffer[sizeof (UINT32)] == Ptr) {
+ //
+ // Unlink first item in list.
+ //
+ Tmp = MyAllocData;
+ MyAllocData = MyAllocData->Next;
+ } else {
+ //
+ // Walk list looking for matching item.
+ //
+ for (Tmp = MyAllocData;; Tmp = Tmp->Next) {
+ //
+ // Fail if end of list is reached.
+ //
+ if (Tmp->Next == NULL) {
+ printf (
+ "\nMyFree(Ptr=%xh, File=%s, Line=%u)\n"
+ "\nNot found.\n",
+ Ptr,
+ File,
+ Line
+ );
+
+ exit (1);
+ }
+ //
+ // Leave loop when match is found.
+ //
+ if (&Tmp->Next->Buffer[sizeof (UINT32)] == Ptr) {
+ break;
+ }
+ }
+ //
+ // Unlink item from list.
+ //
+ Tmp2 = Tmp->Next;
+ Tmp->Next = Tmp->Next->Next;
+ Tmp = Tmp2;
+ }
+ //
+ // Release item.
+ //
+ free (Tmp);
+}
+
+#endif /* USE_MYALLOC */
+
+/* eof - MyAlloc.c */
diff --git a/Source/Common/MyAlloc.h b/Source/Common/MyAlloc.h
new file mode 100644
index 0000000..9697012
--- /dev/null
+++ b/Source/Common/MyAlloc.h
@@ -0,0 +1,222 @@
+/*++
+
+Copyright (c) 2004, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ MyAlloc.h
+
+Abstract:
+
+ Header file for memory allocation tracking functions.
+
+--*/
+
+#ifndef _MYALLOC_H_
+#define _MYALLOC_H_
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <Common/BaseTypes.h>
+
+//
+// Default operation is to use the memory allocation tracking functions.
+// To over-ride add "#define USE_MYALLOC 0" to your program header and/or
+// source files as needed. Or, just do not include this header file in
+// your project.
+//
+#ifndef USE_MYALLOC
+#define USE_MYALLOC 1
+#endif
+
+#if USE_MYALLOC
+//
+// Replace C library allocation routines with MyAlloc routines.
+//
+#define malloc(size) MyAlloc ((size), __FILE__, __LINE__)
+#define calloc(count, size) MyAlloc ((count) * (size), __FILE__, __LINE__)
+#define realloc(ptr, size) MyRealloc ((ptr), (size), __FILE__, __LINE__)
+#define free(ptr) MyFree ((ptr), __FILE__, __LINE__)
+#define alloc_check(final) MyCheck ((final), __FILE__, __LINE__)
+
+//
+// Structure for checking/tracking memory allocations.
+//
+typedef struct MyAllocStruct {
+ UINTN Cksum;
+ struct MyAllocStruct *Next;
+ UINTN Line;
+ UINTN Size;
+ UINT8 *File;
+ UINT8 *Buffer;
+} MY_ALLOC_STRUCT;
+//
+// Cksum := (UINTN)This + (UINTN)Next + Line + Size + (UINTN)File +
+// (UINTN)Buffer;
+//
+// Next := Pointer to next allocation structure in the list.
+//
+// Line := __LINE__
+//
+// Size := Size of allocation request.
+//
+// File := Pointer to __FILE__ string stored immediately following
+// MY_ALLOC_STRUCT in memory.
+//
+// Buffer := Pointer to UINT32 aligned storage immediately following
+// the NULL terminated __FILE__ string. This is UINT32
+// aligned because the underflow signature is 32-bits and
+// this will place the first caller address on a 64-bit
+// boundary.
+//
+//
+// Signatures used to check for buffer overflow/underflow conditions.
+//
+#define MYALLOC_HEAD_MAGIK 0xBADFACED
+#define MYALLOC_TAIL_MAGIK 0xDEADBEEF
+
+VOID
+MyCheck (
+ BOOLEAN Final,
+ UINT8 File[],
+ UINTN Line
+ )
+;
+//
+// *++
+// Description:
+//
+// Check for corruptions in the allocated memory chain. If a corruption
+// is detection program operation stops w/ an exit(1) call.
+//
+// Parameters:
+//
+// Final := When FALSE, MyCheck() returns if the allocated memory chain
+// has not been corrupted. When TRUE, MyCheck() returns if there
+// are no un-freed allocations. If there are un-freed allocations,
+// they are displayed and exit(1) is called.
+//
+//
+// File := Set to __FILE__ by macro expansion.
+//
+// Line := Set to __LINE__ by macro expansion.
+//
+// Returns:
+//
+// n/a
+//
+// --*/
+//
+VOID *
+MyAlloc (
+ UINTN Size,
+ UINT8 File[],
+ UINTN Line
+ )
+;
+//
+// *++
+// Description:
+//
+// Allocate a new link in the allocation chain along with enough storage
+// for the File[] string, requested Size and alignment overhead. If
+// memory cannot be allocated or the allocation chain has been corrupted,
+// exit(1) will be called.
+//
+// Parameters:
+//
+// Size := Number of bytes (UINT8) requested by the called.
+// Size cannot be zero.
+//
+// File := Set to __FILE__ by macro expansion.
+//
+// Line := Set to __LINE__ by macro expansion.
+//
+// Returns:
+//
+// Pointer to the caller's buffer.
+//
+// --*/
+//
+VOID *
+MyRealloc (
+ VOID *Ptr,
+ UINTN Size,
+ UINT8 File[],
+ UINTN Line
+ )
+;
+//
+// *++
+// Description:
+//
+// This does a MyAlloc(), memcpy() and MyFree(). There is no optimization
+// for shrinking or expanding buffers. An invalid parameter will cause
+// MyRealloc() to fail with a call to exit(1).
+//
+// Parameters:
+//
+// Ptr := Pointer to the caller's buffer to be re-allocated.
+// Ptr cannot be NULL.
+//
+// Size := Size of new buffer. Size cannot be zero.
+//
+// File := Set to __FILE__ by macro expansion.
+//
+// Line := Set to __LINE__ by macro expansion.
+//
+// Returns:
+//
+// Pointer to new caller's buffer.
+//
+// --*/
+//
+VOID
+MyFree (
+ VOID *Ptr,
+ UINT8 File[],
+ UINTN Line
+ )
+;
+//
+// *++
+// Description:
+//
+// Release a previously allocated buffer. Invalid parameters will cause
+// MyFree() to fail with an exit(1) call.
+//
+// Parameters:
+//
+// Ptr := Pointer to the caller's buffer to be freed.
+// A NULL pointer will be ignored.
+//
+// File := Set to __FILE__ by macro expansion.
+//
+// Line := Set to __LINE__ by macro expansion.
+//
+// Returns:
+//
+// n/a
+//
+// --*/
+//
+#else /* USE_MYALLOC */
+
+//
+// Nothing to do when USE_MYALLOC is zero.
+//
+#define alloc_check(final)
+
+#endif /* USE_MYALLOC */
+#endif /* _MYALLOC_H_ */
+
+/* eof - MyAlloc.h */
diff --git a/Source/Common/ParseInf.c b/Source/Common/ParseInf.c
new file mode 100644
index 0000000..de0ffd8
--- /dev/null
+++ b/Source/Common/ParseInf.c
@@ -0,0 +1,630 @@
+/*++
+
+Copyright (c) 2004, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ ParseInf.c
+
+Abstract:
+
+ This contains some useful functions for parsing INF files.
+
+--*/
+
+#include <assert.h>
+#include <string.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include "ParseInf.h"
+
+#ifndef _MAX_PATH
+#define _MAX_PATH 500
+#endif
+
+CHAR8 *
+ReadLine (
+ IN MEMORY_FILE *InputFile,
+ IN OUT CHAR8 *InputBuffer,
+ IN UINTN MaxLength
+ )
+/*++
+
+Routine Description:
+
+ This function reads a line, stripping any comments.
+ The function reads a string from the input stream argument and stores it in
+ the input string. ReadLine reads characters from the current file position
+ to and including the first newline character, to the end of the stream, or
+ until the number of characters read is equal to MaxLength - 1, whichever
+ comes first. The newline character, if read, is replaced with a \0.
+
+Arguments:
+
+ InputFile Memory file image.
+ InputBuffer Buffer to read into, must be _MAX_PATH size.
+ MaxLength The maximum size of the input buffer.
+
+Returns:
+
+ NULL if error or EOF
+ InputBuffer otherwise
+
+--*/
+{
+ CHAR8 *CharPtr;
+ CHAR8 *EndOfLine;
+ UINTN CharsToCopy;
+
+ //
+ // Verify input parameters are not null
+ //
+ assert (InputBuffer);
+ assert (InputFile->FileImage);
+ assert (InputFile->Eof);
+ assert (InputFile->CurrentFilePointer);
+
+ //
+ // Check for end of file condition
+ //
+ if (InputFile->CurrentFilePointer >= InputFile->Eof) {
+ return NULL;
+ }
+ //
+ // Find the next newline char
+ //
+ EndOfLine = strchr (InputFile->CurrentFilePointer, '\n');
+
+ //
+ // Determine the number of characters to copy.
+ //
+ if (EndOfLine == 0) {
+ //
+ // If no newline found, copy to the end of the file.
+ //
+ CharsToCopy = InputFile->Eof - InputFile->CurrentFilePointer;
+ } else if (EndOfLine >= InputFile->Eof) {
+ //
+ // If the newline found was beyond the end of file, copy to the eof.
+ //
+ CharsToCopy = InputFile->Eof - InputFile->CurrentFilePointer;
+ } else {
+ //
+ // Newline found in the file.
+ //
+ CharsToCopy = EndOfLine - InputFile->CurrentFilePointer;
+ }
+ //
+ // If the end of line is too big for the current buffer, set it to the max
+ // size of the buffer (leaving room for the \0.
+ //
+ if (CharsToCopy > MaxLength - 1) {
+ CharsToCopy = MaxLength - 1;
+ }
+ //
+ // Copy the line.
+ //
+ memcpy (InputBuffer, InputFile->CurrentFilePointer, CharsToCopy);
+
+ //
+ // Add the null termination over the 0x0D
+ //
+ InputBuffer[CharsToCopy - 1] = '\0';
+
+ //
+ // Increment the current file pointer (include the 0x0A)
+ //
+ InputFile->CurrentFilePointer += CharsToCopy + 1;
+
+ //
+ // Strip any comments
+ //
+ CharPtr = strstr (InputBuffer, "//");
+ if (CharPtr != 0) {
+ CharPtr[0] = 0;
+ }
+ //
+ // Return the string
+ //
+ return InputBuffer;
+}
+
+BOOLEAN
+FindSection (
+ IN MEMORY_FILE *InputFile,
+ IN CHAR8 *Section
+ )
+/*++
+
+Routine Description:
+
+ This function parses a file from the beginning to find a section.
+ The section string may be anywhere within a line.
+
+Arguments:
+
+ InputFile Memory file image.
+ Section Section to search for
+
+Returns:
+
+ FALSE if error or EOF
+ TRUE if section found
+
+--*/
+{
+ CHAR8 InputBuffer[_MAX_PATH];
+ CHAR8 *CurrentToken;
+
+ //
+ // Verify input is not NULL
+ //
+ assert (InputFile->FileImage);
+ assert (InputFile->Eof);
+ assert (InputFile->CurrentFilePointer);
+ assert (Section);
+
+ //
+ // Rewind to beginning of file
+ //
+ InputFile->CurrentFilePointer = InputFile->FileImage;
+
+ //
+ // Read lines until the section is found
+ //
+ while (InputFile->CurrentFilePointer < InputFile->Eof) {
+ //
+ // Read a line
+ //
+ ReadLine (InputFile, InputBuffer, _MAX_PATH);
+
+ //
+ // Check if the section is found
+ //
+ CurrentToken = strstr (InputBuffer, Section);
+ if (CurrentToken != NULL) {
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+EFI_STATUS
+FindToken (
+ IN MEMORY_FILE *InputFile,
+ IN CHAR8 *Section,
+ IN CHAR8 *Token,
+ IN UINTN Instance,
+ OUT CHAR8 *Value
+ )
+/*++
+
+Routine Description:
+
+ Finds a token value given the section and token to search for.
+
+Arguments:
+
+ InputFile Memory file image.
+ Section The section to search for, a string within [].
+ Token The token to search for, e.g. EFI_PEIM_RECOVERY, followed by an = in the INF file.
+ Instance The instance of the token to search for. Zero is the first instance.
+ Value The string that holds the value following the =. Must be _MAX_PATH in size.
+
+Returns:
+
+ EFI_SUCCESS Value found.
+ EFI_ABORTED Format error detected in INF file.
+ EFI_INVALID_PARAMETER Input argument was null.
+ EFI_LOAD_ERROR Error reading from the file.
+ EFI_NOT_FOUND Section/Token/Value not found.
+
+--*/
+{
+ CHAR8 InputBuffer[_MAX_PATH];
+ CHAR8 *CurrentToken;
+ BOOLEAN ParseError;
+ BOOLEAN ReadError;
+ UINTN Occurrance;
+
+ //
+ // Check input parameters
+ //
+ if (InputFile->FileImage == NULL ||
+ InputFile->Eof == NULL ||
+ InputFile->CurrentFilePointer == NULL ||
+ Section == NULL ||
+ strlen (Section) == 0 ||
+ Token == NULL ||
+ strlen (Token) == 0 ||
+ Value == NULL
+ ) {
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // Initialize error codes
+ //
+ ParseError = FALSE;
+ ReadError = FALSE;
+
+ //
+ // Initialize our instance counter for the search token
+ //
+ Occurrance = 0;
+
+ if (FindSection (InputFile, Section)) {
+ //
+ // Found the desired section, find and read the desired token
+ //
+ do {
+ //
+ // Read a line from the file
+ //
+ if (ReadLine (InputFile, InputBuffer, _MAX_PATH) == NULL) {
+ //
+ // Error reading from input file
+ //
+ ReadError = TRUE;
+ break;
+ }
+ //
+ // Get the first non-whitespace string
+ //
+ CurrentToken = strtok (InputBuffer, " \t\n");
+ if (CurrentToken == NULL) {
+ //
+ // Whitespace line found (or comment) so continue
+ //
+ CurrentToken = InputBuffer;
+ continue;
+ }
+ //
+ // Make sure we have not reached the end of the current section
+ //
+ if (CurrentToken[0] == '[') {
+ break;
+ }
+ //
+ // Compare the current token with the desired token
+ //
+ if (strcmp (CurrentToken, Token) == 0) {
+ //
+ // Found it
+ //
+ //
+ // Check if it is the correct instance
+ //
+ if (Instance == Occurrance) {
+ //
+ // Copy the contents following the =
+ //
+ CurrentToken = strtok (NULL, "= \t\n");
+ if (CurrentToken == NULL) {
+ //
+ // Nothing found, parsing error
+ //
+ ParseError = TRUE;
+ } else {
+ //
+ // Copy the current token to the output value
+ //
+ strcpy (Value, CurrentToken);
+ return EFI_SUCCESS;
+ }
+ } else {
+ //
+ // Increment the occurrance found
+ //
+ Occurrance++;
+ }
+ }
+ } while (
+ !ParseError &&
+ !ReadError &&
+ InputFile->CurrentFilePointer < InputFile->Eof &&
+ CurrentToken[0] != '[' &&
+ Occurrance <= Instance
+ );
+ }
+ //
+ // Distinguish between read errors and INF file format errors.
+ //
+ if (ReadError) {
+ return EFI_LOAD_ERROR;
+ }
+
+ if (ParseError) {
+ return EFI_ABORTED;
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+EFI_STATUS
+StringToGuid (
+ IN CHAR8 *AsciiGuidBuffer,
+ OUT EFI_GUID *GuidBuffer
+ )
+/*++
+
+Routine Description:
+
+ Converts a string to an EFI_GUID. The string must be in the
+ xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx format.
+
+Arguments:
+
+ AsciiGuidBuffer - pointer to ascii string
+ GuidBuffer - pointer to destination Guid
+
+Returns:
+
+ EFI_ABORTED Could not convert the string
+ EFI_SUCCESS The string was successfully converted
+ EFI_INVALID_PARAMETER Input parameter is invalid.
+
+--*/
+{
+ INT32 Index;
+ UINTN Data1;
+ UINTN Data2;
+ UINTN Data3;
+ UINTN Data4[8];
+
+ if (AsciiGuidBuffer == NULL || GuidBuffer == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // Scan the guid string into the buffer
+ //
+ Index = sscanf (
+ AsciiGuidBuffer,
+ "%08x-%04x-%04x-%02x%02x-%02hx%02hx%02hx%02hx%02hx%02hx",
+ &Data1,
+ &Data2,
+ &Data3,
+ &Data4[0],
+ &Data4[1],
+ &Data4[2],
+ &Data4[3],
+ &Data4[4],
+ &Data4[5],
+ &Data4[6],
+ &Data4[7]
+ );
+
+ //
+ // Verify the correct number of items were scanned.
+ //
+ if (Index != 11) {
+ printf ("ERROR: Malformed GUID \"%s\".\n\n", AsciiGuidBuffer);
+ return EFI_ABORTED;
+ }
+ //
+ // Copy the data into our GUID.
+ //
+ GuidBuffer->Data1 = (UINT32) Data1;
+ GuidBuffer->Data2 = (UINT16) Data2;
+ GuidBuffer->Data3 = (UINT16) Data3;
+ GuidBuffer->Data4[0] = (UINT8) Data4[0];
+ GuidBuffer->Data4[1] = (UINT8) Data4[1];
+ GuidBuffer->Data4[2] = (UINT8) Data4[2];
+ GuidBuffer->Data4[3] = (UINT8) Data4[3];
+ GuidBuffer->Data4[4] = (UINT8) Data4[4];
+ GuidBuffer->Data4[5] = (UINT8) Data4[5];
+ GuidBuffer->Data4[6] = (UINT8) Data4[6];
+ GuidBuffer->Data4[7] = (UINT8) Data4[7];
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+AsciiStringToUint64 (
+ IN CONST CHAR8 *AsciiString,
+ IN BOOLEAN IsHex,
+ OUT UINT64 *ReturnValue
+ )
+/*++
+
+Routine Description:
+
+ Converts a null terminated ascii string that represents a number into a
+ UINT64 value. A hex number may be preceeded by a 0x, but may not be
+ succeeded by an h. A number without 0x or 0X is considered to be base 10
+ unless the IsHex input is true.
+
+Arguments:
+
+ AsciiString The string to convert.
+ IsHex Force the string to be treated as a hex number.
+ ReturnValue The return value.
+
+Returns:
+
+ EFI_SUCCESS Number successfully converted.
+ EFI_ABORTED Invalid character encountered.
+
+--*/
+{
+ UINT8 Index;
+ UINT64 HexNumber;
+ CHAR8 CurrentChar;
+
+ //
+ // Initialize the result
+ //
+ HexNumber = 0;
+
+ //
+ // Add each character to the result
+ //
+ if (IsHex || (AsciiString[0] == '0' && (AsciiString[1] == 'x' || AsciiString[1] == 'X'))) {
+ //
+ // Verify string is a hex number
+ //
+ for (Index = 2; Index < strlen (AsciiString); Index++) {
+ if (isxdigit (AsciiString[Index]) == 0) {
+ return EFI_ABORTED;
+ }
+ }
+ //
+ // Convert the hex string.
+ //
+ for (Index = 2; AsciiString[Index] != '\0'; Index++) {
+ CurrentChar = AsciiString[Index];
+ HexNumber *= 16;
+ if (CurrentChar >= '0' && CurrentChar <= '9') {
+ HexNumber += CurrentChar - '0';
+ } else if (CurrentChar >= 'a' && CurrentChar <= 'f') {
+ HexNumber += CurrentChar - 'a' + 10;
+ } else if (CurrentChar >= 'A' && CurrentChar <= 'F') {
+ HexNumber += CurrentChar - 'A' + 10;
+ } else {
+ //
+ // Unrecognized character
+ //
+ return EFI_ABORTED;
+ }
+ }
+
+ *ReturnValue = HexNumber;
+ } else {
+ //
+ // Verify string is a number
+ //
+ for (Index = 0; Index < strlen (AsciiString); Index++) {
+ if (isdigit (AsciiString[Index]) == 0) {
+ return EFI_ABORTED;
+ }
+ }
+
+ *ReturnValue = atol (AsciiString);
+ }
+
+ return EFI_SUCCESS;
+};
+
+CHAR8 *
+ReadLineInStream (
+ IN FILE *InputFile,
+ IN OUT CHAR8 *InputBuffer
+ )
+/*++
+
+Routine Description:
+
+ This function reads a line, stripping any comments.
+ // BUGBUG: This is obsolete once genmake goes away...
+
+Arguments:
+
+ InputFile Stream pointer.
+ InputBuffer Buffer to read into, must be _MAX_PATH size.
+
+Returns:
+
+ NULL if error or EOF
+ InputBuffer otherwise
+
+--*/
+{
+ CHAR8 *CharPtr;
+
+ //
+ // Verify input parameters are not null
+ //
+ assert (InputFile);
+ assert (InputBuffer);
+
+ //
+ // Read a line
+ //
+ if (fgets (InputBuffer, _MAX_PATH, InputFile) == NULL) {
+ return NULL;
+ }
+ //
+ // Strip any comments
+ //
+ CharPtr = strstr (InputBuffer, "//");
+ if (CharPtr != 0) {
+ CharPtr[0] = 0;
+ }
+
+ CharPtr = strstr (InputBuffer, "#");
+ if (CharPtr != 0) {
+ CharPtr[0] = 0;
+ }
+ //
+ // Return the string
+ //
+ return InputBuffer;
+}
+
+BOOLEAN
+FindSectionInStream (
+ IN FILE *InputFile,
+ IN CHAR8 *Section
+ )
+/*++
+
+Routine Description:
+
+ This function parses a stream file from the beginning to find a section.
+ The section string may be anywhere within a line.
+ // BUGBUG: This is obsolete once genmake goes away...
+
+Arguments:
+
+ InputFile Stream pointer.
+ Section Section to search for
+
+Returns:
+
+ FALSE if error or EOF
+ TRUE if section found
+
+--*/
+{
+ CHAR8 InputBuffer[_MAX_PATH];
+ CHAR8 *CurrentToken;
+
+ //
+ // Verify input is not NULL
+ //
+ assert (InputFile);
+ assert (Section);
+
+ //
+ // Rewind to beginning of file
+ //
+ if (fseek (InputFile, 0, SEEK_SET) != 0) {
+ return FALSE;
+ }
+ //
+ // Read lines until the section is found
+ //
+ while (feof (InputFile) == 0) {
+ //
+ // Read a line
+ //
+ ReadLineInStream (InputFile, InputBuffer);
+
+ //
+ // Check if the section is found
+ //
+ CurrentToken = strstr (InputBuffer, Section);
+ if (CurrentToken != NULL) {
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
diff --git a/Source/Common/ParseInf.h b/Source/Common/ParseInf.h
new file mode 100644
index 0000000..ff98635
--- /dev/null
+++ b/Source/Common/ParseInf.h
@@ -0,0 +1,234 @@
+/*++
+
+Copyright (c) 2004, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ ParseInf.h
+
+Abstract:
+
+ Header file for helper functions useful for parsing INF files.
+
+--*/
+
+#ifndef _EFI_PARSE_INF_H
+#define _EFI_PARSE_INF_H
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <Common/UefiBaseTypes.h>
+
+//
+// Common data structures
+//
+typedef struct {
+ CHAR8 *FileImage;
+ CHAR8 *Eof;
+ CHAR8 *CurrentFilePointer;
+} MEMORY_FILE;
+
+//
+// Functions declarations
+//
+CHAR8 *
+ReadLine (
+ IN MEMORY_FILE *InputFile,
+ IN OUT CHAR8 *InputBuffer,
+ IN UINTN MaxLength
+ )
+;
+
+/*++
+
+Routine Description:
+
+ This function reads a line, stripping any comments.
+ The function reads a string from the input stream argument and stores it in
+ the input string. ReadLine reads characters from the current file position
+ to and including the first newline character, to the end of the stream, or
+ until the number of characters read is equal to MaxLength - 1, whichever
+ comes first. The newline character, if read, is replaced with a \0.
+
+Arguments:
+
+ InputFile Memory file image.
+ InputBuffer Buffer to read into, must be _MAX_PATH size.
+ MaxLength The maximum size of the input buffer.
+
+Returns:
+
+ NULL if error or EOF
+ InputBuffer otherwise
+
+--*/
+BOOLEAN
+FindSection (
+ IN MEMORY_FILE *InputFile,
+ IN CHAR8 *Section
+ )
+;
+
+/*++
+
+Routine Description:
+
+ This function parses a file from the beginning to find a section.
+ The section string may be anywhere within a line.
+
+Arguments:
+
+ InputFile Memory file image.
+ Section Section to search for
+
+Returns:
+
+ FALSE if error or EOF
+ TRUE if section found
+
+--*/
+EFI_STATUS
+FindToken (
+ IN MEMORY_FILE *InputFile,
+ IN CHAR8 *Section,
+ IN CHAR8 *Token,
+ IN UINTN Instance,
+ OUT CHAR8 *Value
+ )
+;
+
+/*++
+
+Routine Description:
+
+ Finds a token value given the section and token to search for.
+
+Arguments:
+
+ InputFile Memory file image.
+ Section The section to search for, a string within [].
+ Token The token to search for, e.g. EFI_PEIM_RECOVERY, followed by an = in the INF file.
+ Instance The instance of the token to search for. Zero is the first instance.
+ Value The string that holds the value following the =. Must be _MAX_PATH in size.
+
+Returns:
+
+ EFI_SUCCESS Value found.
+ EFI_ABORTED Format error detected in INF file.
+ EFI_INVALID_PARAMETER Input argument was null.
+ EFI_LOAD_ERROR Error reading from the file.
+ EFI_NOT_FOUND Section/Token/Value not found.
+
+--*/
+EFI_STATUS
+StringToGuid (
+ IN CHAR8 *AsciiGuidBuffer,
+ OUT EFI_GUID *GuidBuffer
+ )
+;
+
+/*++
+
+Routine Description:
+
+ Converts a string to an EFI_GUID. The string must be in the
+ xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx format.
+
+Arguments:
+
+ GuidBuffer - pointer to destination Guid
+ AsciiGuidBuffer - pointer to ascii string
+
+Returns:
+
+ EFI_ABORTED Could not convert the string
+ EFI_SUCCESS The string was successfully converted
+
+--*/
+EFI_STATUS
+AsciiStringToUint64 (
+ IN CONST CHAR8 *AsciiString,
+ IN BOOLEAN IsHex,
+ OUT UINT64 *ReturnValue
+ )
+;
+
+/*++
+
+Routine Description:
+
+ Converts a null terminated ascii string that represents a number into a
+ UINT64 value. A hex number may be preceeded by a 0x, but may not be
+ succeeded by an h. A number without 0x or 0X is considered to be base 10
+ unless the IsHex input is true.
+
+Arguments:
+
+ AsciiString The string to convert.
+ IsHex Force the string to be treated as a hex number.
+ ReturnValue The return value.
+
+Returns:
+
+ EFI_SUCCESS Number successfully converted.
+ EFI_ABORTED Invalid character encountered.
+
+--*/
+CHAR8 *
+ReadLineInStream (
+ IN FILE *InputFile,
+ IN OUT CHAR8 *InputBuffer
+ )
+;
+
+/*++
+
+Routine Description:
+
+ This function reads a line, stripping any comments.
+
+Arguments:
+
+ InputFile Stream pointer.
+ InputBuffer Buffer to read into, must be _MAX_PATH size.
+
+Returns:
+
+ NULL if error or EOF
+ InputBuffer otherwise
+
+--*/
+BOOLEAN
+FindSectionInStream (
+ IN FILE *InputFile,
+ IN CHAR8 *Section
+ )
+;
+
+/*++
+
+Routine Description:
+
+ This function parses a stream file from the beginning to find a section.
+ The section string may be anywhere within a line.
+
+Arguments:
+
+ InputFile Stream pointer.
+ Section Section to search for
+
+Returns:
+
+ FALSE if error or EOF
+ TRUE if section found
+
+--*/
+#endif
diff --git a/Source/Common/SimpleFileParsing.c b/Source/Common/SimpleFileParsing.c
new file mode 100644
index 0000000..73b74cd
--- /dev/null
+++ b/Source/Common/SimpleFileParsing.c
@@ -0,0 +1,1457 @@
+/*++
+
+Copyright (c) 2004, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ SimpleFileParsing.c
+
+Abstract:
+
+ Generic but simple file parsing routines.
+
+--*/
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+
+#include "EfiUtilityMsgs.h"
+#include "SimpleFileParsing.h"
+
+#ifndef MAX_PATH
+#define MAX_PATH 255
+#endif
+//
+// just in case we get in an endless loop.
+//
+#define MAX_NEST_DEPTH 20
+//
+// number of wchars
+//
+#define MAX_STRING_IDENTIFIER_NAME 100
+
+#define MAX_LINE_LEN 400
+
+#define T_CHAR_SPACE ' '
+#define T_CHAR_NULL 0
+#define T_CHAR_CR '\r'
+#define T_CHAR_TAB '\t'
+#define T_CHAR_LF '\n'
+#define T_CHAR_SLASH '/'
+#define T_CHAR_BACKSLASH '\\'
+#define T_CHAR_DOUBLE_QUOTE '"'
+#define T_CHAR_LC_X 'x'
+#define T_CHAR_0 '0'
+#define T_CHAR_STAR '*'
+
+//
+// We keep a linked list of these for the source files we process
+//
+typedef struct _SOURCE_FILE {
+ FILE *Fptr;
+ T_CHAR *FileBuffer;
+ T_CHAR *FileBufferPtr;
+ unsigned int FileSize;
+ char FileName[MAX_PATH];
+ unsigned int LineNum;
+ BOOLEAN EndOfFile;
+ BOOLEAN SkipToHash;
+ struct _SOURCE_FILE *Previous;
+ struct _SOURCE_FILE *Next;
+ T_CHAR ControlCharacter;
+} SOURCE_FILE;
+
+typedef struct {
+ T_CHAR *FileBufferPtr;
+} FILE_POSITION;
+
+//
+// Keep all our module globals in this structure
+//
+static struct {
+ SOURCE_FILE SourceFile;
+ BOOLEAN VerboseFile;
+ BOOLEAN VerboseToken;
+} mGlobals;
+
+static
+unsigned int
+t_strcmp (
+ T_CHAR *Buffer,
+ T_CHAR *Str
+ );
+
+static
+unsigned int
+t_strncmp (
+ T_CHAR *Str1,
+ T_CHAR *Str2,
+ int Len
+ );
+
+static
+unsigned int
+t_strlen (
+ T_CHAR *Str
+ );
+
+static
+void
+RewindFile (
+ SOURCE_FILE *SourceFile
+ );
+
+static
+BOOLEAN
+IsWhiteSpace (
+ SOURCE_FILE *SourceFile
+ );
+
+static
+unsigned int
+SkipWhiteSpace (
+ SOURCE_FILE *SourceFile
+ );
+
+static
+BOOLEAN
+EndOfFile (
+ SOURCE_FILE *SourceFile
+ );
+
+static
+void
+PreprocessFile (
+ SOURCE_FILE *SourceFile
+ );
+
+static
+T_CHAR *
+t_strcpy (
+ T_CHAR *Dest,
+ T_CHAR *Src
+ );
+
+static
+STATUS
+ProcessIncludeFile (
+ SOURCE_FILE *SourceFile,
+ SOURCE_FILE *ParentSourceFile
+ );
+
+static
+STATUS
+ParseFile (
+ SOURCE_FILE *SourceFile
+ );
+
+static
+FILE *
+FindFile (
+ char *FileName,
+ char *FoundFileName,
+ unsigned int FoundFileNameLen
+ );
+
+static
+STATUS
+ProcessFile (
+ SOURCE_FILE *SourceFile
+ );
+
+static
+STATUS
+GetFilePosition (
+ FILE_POSITION *Fpos
+ );
+
+static
+STATUS
+SetFilePosition (
+ FILE_POSITION *Fpos
+ );
+
+STATUS
+SFPInit (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+ None.
+
+Returns:
+ STATUS_SUCCESS always
+
+--*/
+{
+ memset ((void *) &mGlobals, 0, sizeof (mGlobals));
+ return STATUS_SUCCESS;
+}
+
+unsigned
+int
+SFPGetLineNumber (
+ VOID
+ )
+/*++
+
+Routine Description:
+ Return the line number of the file we're parsing. Used
+ for error reporting purposes.
+
+Arguments:
+ None.
+
+Returns:
+ The line number, or 0 if no file is being processed
+
+--*/
+{
+ return mGlobals.SourceFile.LineNum;
+}
+
+T_CHAR *
+SFPGetFileName (
+ VOID
+ )
+/*++
+
+Routine Description:
+ Return the name of the file we're parsing. Used
+ for error reporting purposes.
+
+Arguments:
+ None.
+
+Returns:
+ A pointer to the file name. Null if no file is being
+ processed.
+
+--*/
+{
+ if (mGlobals.SourceFile.FileName[0]) {
+ return mGlobals.SourceFile.FileName;
+ }
+
+ return NULL;
+}
+
+STATUS
+SFPOpenFile (
+ char *FileName
+ )
+/*++
+
+Routine Description:
+ Open a file for parsing.
+
+Arguments:
+ FileName - name of the file to parse
+
+Returns:
+
+
+--*/
+{
+ STATUS Status;
+ t_strcpy (mGlobals.SourceFile.FileName, FileName);
+ Status = ProcessIncludeFile (&mGlobals.SourceFile, NULL);
+ return Status;
+}
+
+BOOLEAN
+SFPIsToken (
+ T_CHAR *Str
+ )
+/*++
+
+Routine Description:
+ Check to see if the specified token is found at
+ the current position in the input file.
+
+Arguments:
+ Str - the token to look for
+
+Returns:
+ TRUE - the token is next
+ FALSE - the token is not next
+
+Notes:
+ We do a simple string comparison on this function. It is
+ the responsibility of the caller to ensure that the token
+ is not a subset of some other token.
+
+ The file pointer is advanced past the token in the input file.
+
+--*/
+{
+ unsigned int Len;
+ SkipWhiteSpace (&mGlobals.SourceFile);
+ if (EndOfFile (&mGlobals.SourceFile)) {
+ return FALSE;
+ }
+
+ if ((Len = t_strcmp (mGlobals.SourceFile.FileBufferPtr, Str)) > 0) {
+ mGlobals.SourceFile.FileBufferPtr += Len;
+ if (mGlobals.VerboseToken) {
+ printf ("Token: '%s'\n", Str);
+ }
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+BOOLEAN
+SFPIsKeyword (
+ T_CHAR *Str
+ )
+/*++
+
+Routine Description:
+ Check to see if the specified keyword is found at
+ the current position in the input file.
+
+Arguments:
+ Str - keyword to look for
+
+Returns:
+ TRUE - the keyword is next
+ FALSE - the keyword is not next
+
+Notes:
+ A keyword is defined as a "special" string that has a non-alphanumeric
+ character following it.
+
+--*/
+{
+ unsigned int Len;
+ SkipWhiteSpace (&mGlobals.SourceFile);
+ if (EndOfFile (&mGlobals.SourceFile)) {
+ return FALSE;
+ }
+
+ if ((Len = t_strcmp (mGlobals.SourceFile.FileBufferPtr, Str)) > 0) {
+ if (isalnum (mGlobals.SourceFile.FileBufferPtr[Len])) {
+ return FALSE;
+ }
+
+ mGlobals.SourceFile.FileBufferPtr += Len;
+ if (mGlobals.VerboseToken) {
+ printf ("Token: '%s'\n", Str);
+ }
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+BOOLEAN
+SFPGetNextToken (
+ T_CHAR *Str,
+ unsigned int Len
+ )
+/*++
+
+Routine Description:
+ Get the next token from the input stream.
+
+Arguments:
+ Str - pointer to a copy of the next token
+ Len - size of buffer pointed to by Str
+
+Returns:
+ TRUE - next token successfully returned
+ FALSE - otherwise
+
+Notes:
+ Preceeding white space is ignored.
+ The parser's buffer pointer is advanced past the end of the
+ token.
+
+--*/
+{
+ unsigned int Index;
+ T_CHAR TempChar;
+
+ SkipWhiteSpace (&mGlobals.SourceFile);
+ if (EndOfFile (&mGlobals.SourceFile)) {
+ return FALSE;
+ }
+ //
+ // Have to have enough string for at least one char and a null-terminator
+ //
+ if (Len < 2) {
+ return FALSE;
+ }
+ //
+ // Look at the first character. If it's an identifier, then treat it
+ // as such
+ //
+ TempChar = mGlobals.SourceFile.FileBufferPtr[0];
+ if (((TempChar >= 'a') && (TempChar <= 'z')) || ((TempChar >= 'A') && (TempChar <= 'Z')) || (TempChar == '_')) {
+ Str[0] = TempChar;
+ mGlobals.SourceFile.FileBufferPtr++;
+ Index = 1;
+ while (!EndOfFile (&mGlobals.SourceFile) && (Index < Len)) {
+ TempChar = mGlobals.SourceFile.FileBufferPtr[0];
+ if (((TempChar >= 'a') && (TempChar <= 'z')) ||
+ ((TempChar >= 'A') && (TempChar <= 'Z')) ||
+ ((TempChar >= '0') && (TempChar <= '9')) ||
+ (TempChar == '_')
+ ) {
+ Str[Index] = mGlobals.SourceFile.FileBufferPtr[0];
+ mGlobals.SourceFile.FileBufferPtr++;
+ Index++;
+ } else {
+ //
+ // Invalid character for symbol name, so break out
+ //
+ break;
+ }
+ }
+ //
+ // Null terminate and return success
+ //
+ Str[Index] = 0;
+ return TRUE;
+ } else if ((TempChar == ')') || (TempChar == '(') || (TempChar == '*')) {
+ Str[0] = mGlobals.SourceFile.FileBufferPtr[0];
+ mGlobals.SourceFile.FileBufferPtr++;
+ Str[1] = 0;
+ return TRUE;
+ } else {
+ //
+ // Everything else is white-space (or EOF) separated
+ //
+ Index = 0;
+ while (!EndOfFile (&mGlobals.SourceFile) && (Index < Len)) {
+ if (IsWhiteSpace (&mGlobals.SourceFile)) {
+ if (Index > 0) {
+ Str[Index] = 0;
+ return TRUE;
+ }
+
+ return FALSE;
+ } else {
+ Str[Index] = mGlobals.SourceFile.FileBufferPtr[0];
+ mGlobals.SourceFile.FileBufferPtr++;
+ Index++;
+ }
+ }
+ //
+ // See if we just ran out of file contents, but did find a token
+ //
+ if ((Index > 0) && EndOfFile (&mGlobals.SourceFile)) {
+ Str[Index] = 0;
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+BOOLEAN
+SFPGetGuidToken (
+ T_CHAR *Str,
+ UINT32 Len
+ )
+/*++
+
+Routine Description:
+ Parse a GUID from the input stream. Stop when you discover white space.
+
+Arguments:
+ Str - pointer to a copy of the next token
+ Len - size of buffer pointed to by Str
+
+Returns:
+ TRUE - GUID string returned successfully
+ FALSE - otherwise
+
+--*/
+{
+ UINT32 Index;
+ SkipWhiteSpace (&mGlobals.SourceFile);
+ if (EndOfFile (&mGlobals.SourceFile)) {
+ return FALSE;
+ }
+
+ Index = 0;
+ while (!EndOfFile (&mGlobals.SourceFile) && (Index < Len)) {
+ if (IsWhiteSpace (&mGlobals.SourceFile)) {
+ if (Index > 0) {
+ Str[Index] = 0;
+ return TRUE;
+ }
+
+ return FALSE;
+ } else {
+ Str[Index] = mGlobals.SourceFile.FileBufferPtr[0];
+ mGlobals.SourceFile.FileBufferPtr++;
+ Index++;
+ }
+ }
+
+ return FALSE;
+}
+
+BOOLEAN
+SFPSkipToToken (
+ T_CHAR *Str
+ )
+{
+ unsigned int Len;
+ T_CHAR *SavePos;
+ Len = t_strlen (Str);
+ SavePos = mGlobals.SourceFile.FileBufferPtr;
+ SkipWhiteSpace (&mGlobals.SourceFile);
+ while (!EndOfFile (&mGlobals.SourceFile)) {
+ if (t_strncmp (Str, mGlobals.SourceFile.FileBufferPtr, Len) == 0) {
+ mGlobals.SourceFile.FileBufferPtr += Len;
+ return TRUE;
+ }
+
+ mGlobals.SourceFile.FileBufferPtr++;
+ SkipWhiteSpace (&mGlobals.SourceFile);
+ }
+
+ mGlobals.SourceFile.FileBufferPtr = SavePos;
+ return FALSE;
+}
+
+BOOLEAN
+SFPGetNumber (
+ unsigned int *Value
+ )
+/*++
+
+Routine Description:
+ Check the token at the current file position for a numeric value.
+ May be either decimal or hex.
+
+Arguments:
+ Value - pointer where to store the value
+
+Returns:
+ FALSE - current token is not a number
+ TRUE - current token is a number
+
+--*/
+{
+ SkipWhiteSpace (&mGlobals.SourceFile);
+ if (EndOfFile (&mGlobals.SourceFile)) {
+ return FALSE;
+ }
+
+ if (isdigit (mGlobals.SourceFile.FileBufferPtr[0])) {
+ //
+ // Check for hex value
+ //
+ if ((mGlobals.SourceFile.FileBufferPtr[0] == T_CHAR_0) && (mGlobals.SourceFile.FileBufferPtr[1] == T_CHAR_LC_X)) {
+ if (!isxdigit (mGlobals.SourceFile.FileBufferPtr[2])) {
+ return FALSE;
+ }
+
+ mGlobals.SourceFile.FileBufferPtr += 2;
+ sscanf (mGlobals.SourceFile.FileBufferPtr, "%x", Value);
+ while (isxdigit (mGlobals.SourceFile.FileBufferPtr[0])) {
+ mGlobals.SourceFile.FileBufferPtr++;
+ }
+
+ return TRUE;
+ } else {
+ *Value = atoi (mGlobals.SourceFile.FileBufferPtr);
+ while (isdigit (mGlobals.SourceFile.FileBufferPtr[0])) {
+ mGlobals.SourceFile.FileBufferPtr++;
+ }
+
+ return TRUE;
+ }
+ } else {
+ return FALSE;
+ }
+}
+
+STATUS
+SFPCloseFile (
+ VOID
+ )
+/*++
+
+Routine Description:
+ Close the file being parsed.
+
+Arguments:
+ None.
+
+Returns:
+ STATUS_SUCCESS - the file was closed
+ STATUS_ERROR - no file is currently open
+
+--*/
+{
+ if (mGlobals.SourceFile.FileBuffer != NULL) {
+ free (mGlobals.SourceFile.FileBuffer);
+ memset (&mGlobals.SourceFile, 0, sizeof (mGlobals.SourceFile));
+ return STATUS_SUCCESS;
+ }
+
+ return STATUS_ERROR;
+}
+
+static
+STATUS
+ProcessIncludeFile (
+ SOURCE_FILE *SourceFile,
+ SOURCE_FILE *ParentSourceFile
+ )
+/*++
+
+Routine Description:
+
+ Given a source file, open the file and parse it
+
+Arguments:
+
+ SourceFile - name of file to parse
+ ParentSourceFile - for error reporting purposes, the file that #included SourceFile.
+
+Returns:
+
+ Standard status.
+
+--*/
+{
+ static unsigned int NestDepth = 0;
+ char FoundFileName[MAX_PATH];
+ STATUS Status;
+
+ Status = STATUS_SUCCESS;
+ NestDepth++;
+ //
+ // Print the file being processed. Indent so you can tell the include nesting
+ // depth.
+ //
+ if (mGlobals.VerboseFile) {
+ fprintf (stdout, "%*cProcessing file '%s'\n", NestDepth * 2, ' ', SourceFile->FileName);
+ fprintf (stdout, "Parent source file = '%s'\n", ParentSourceFile);
+ }
+
+ //
+ // Make sure we didn't exceed our maximum nesting depth
+ //
+ if (NestDepth > MAX_NEST_DEPTH) {
+ Error (NULL, 0, 0, SourceFile->FileName, "max nesting depth (%d) exceeded", NestDepth);
+ Status = STATUS_ERROR;
+ goto Finish;
+ }
+ //
+ // Try to open the file locally, and if that fails try along our include paths.
+ //
+ strcpy (FoundFileName, SourceFile->FileName);
+ if ((SourceFile->Fptr = fopen (FoundFileName, "rb")) == NULL) {
+ return STATUS_ERROR;
+ }
+ //
+ // Process the file found
+ //
+ ProcessFile (SourceFile);
+Finish:
+ //
+ // Close open files and return status
+ //
+ if (SourceFile->Fptr != NULL) {
+ fclose (SourceFile->Fptr);
+ SourceFile->Fptr = NULL;
+ }
+
+ return Status;
+}
+
+static
+STATUS
+ProcessFile (
+ SOURCE_FILE *SourceFile
+ )
+/*++
+
+Routine Description:
+
+ Given a source file that's been opened, read the contents into an internal
+ buffer and pre-process it to remove comments.
+
+Arguments:
+
+ SourceFile - structure containing info on the file to process
+
+Returns:
+
+ Standard status.
+
+--*/
+{
+ //
+ // Get the file size, and then read the entire thing into memory.
+ // Allocate extra space for a terminator character.
+ //
+ fseek (SourceFile->Fptr, 0, SEEK_END);
+ SourceFile->FileSize = ftell (SourceFile->Fptr);
+ if (mGlobals.VerboseFile) {
+ printf ("FileSize = %d (0x%X)\n", SourceFile->FileSize, SourceFile->FileSize);
+ }
+
+ fseek (SourceFile->Fptr, 0, SEEK_SET);
+ SourceFile->FileBuffer = (T_CHAR *) malloc (SourceFile->FileSize + sizeof (T_CHAR));
+ if (SourceFile->FileBuffer == NULL) {
+ Error (NULL, 0, 0, "memory allocation failure", NULL);
+ return STATUS_ERROR;
+ }
+
+ fread ((void *) SourceFile->FileBuffer, SourceFile->FileSize, 1, SourceFile->Fptr);
+ SourceFile->FileBuffer[(SourceFile->FileSize / sizeof (T_CHAR))] = T_CHAR_NULL;
+ //
+ // Pre-process the file to replace comments with spaces
+ //
+ PreprocessFile (SourceFile);
+ SourceFile->LineNum = 1;
+ return STATUS_SUCCESS;
+}
+
+static
+void
+PreprocessFile (
+ SOURCE_FILE *SourceFile
+ )
+/*++
+
+Routine Description:
+ Preprocess a file to replace all carriage returns with NULLs so
+ we can print lines (as part of error messages) from the file to the screen.
+
+Arguments:
+ SourceFile - structure that we use to keep track of an input file.
+
+Returns:
+ Nothing.
+
+--*/
+{
+ BOOLEAN InComment;
+ BOOLEAN SlashSlashComment;
+ int LineNum;
+
+ RewindFile (SourceFile);
+ InComment = FALSE;
+ SlashSlashComment = FALSE;
+ while (!EndOfFile (SourceFile)) {
+ //
+ // If a line-feed, then no longer in a comment if we're in a // comment
+ //
+ if (SourceFile->FileBufferPtr[0] == T_CHAR_LF) {
+ SourceFile->FileBufferPtr++;
+ SourceFile->LineNum++;
+ if (InComment && SlashSlashComment) {
+ InComment = FALSE;
+ SlashSlashComment = FALSE;
+ }
+ } else if (SourceFile->FileBufferPtr[0] == T_CHAR_CR) {
+ //
+ // Replace all carriage returns with a NULL so we can print stuff
+ //
+ SourceFile->FileBufferPtr[0] = 0;
+ SourceFile->FileBufferPtr++;
+ //
+ // Check for */ comment end
+ //
+ } else if (InComment &&
+ !SlashSlashComment &&
+ (SourceFile->FileBufferPtr[0] == T_CHAR_STAR) &&
+ (SourceFile->FileBufferPtr[1] == T_CHAR_SLASH)
+ ) {
+ SourceFile->FileBufferPtr[0] = T_CHAR_SPACE;
+ SourceFile->FileBufferPtr++;
+ SourceFile->FileBufferPtr[0] = T_CHAR_SPACE;
+ SourceFile->FileBufferPtr++;
+ InComment = FALSE;
+ } else if (InComment) {
+ SourceFile->FileBufferPtr[0] = T_CHAR_SPACE;
+ SourceFile->FileBufferPtr++;
+ //
+ // Check for // comments
+ //
+ } else if ((SourceFile->FileBufferPtr[0] == T_CHAR_SLASH) && (SourceFile->FileBufferPtr[1] == T_CHAR_SLASH)) {
+ InComment = TRUE;
+ SlashSlashComment = TRUE;
+ //
+ // Check for /* comment start
+ //
+ } else if ((SourceFile->FileBufferPtr[0] == T_CHAR_SLASH) && (SourceFile->FileBufferPtr[1] == T_CHAR_STAR)) {
+ SourceFile->FileBufferPtr[0] = T_CHAR_SPACE;
+ SourceFile->FileBufferPtr++;
+ SourceFile->FileBufferPtr[0] = T_CHAR_SPACE;
+ SourceFile->FileBufferPtr++;
+ SlashSlashComment = FALSE;
+ InComment = TRUE;
+ } else {
+ SourceFile->FileBufferPtr++;
+ }
+ }
+ //
+ // Could check for end-of-file and still in a comment, but
+ // should not be necessary. So just restore the file pointers.
+ //
+ RewindFile (SourceFile);
+ //
+ // Dump the reformatted file if verbose mode
+ //
+ if (mGlobals.VerboseFile) {
+ LineNum = 1;
+ printf ("%04d: ", LineNum);
+ while (!EndOfFile (SourceFile)) {
+ if (SourceFile->FileBufferPtr[0] == T_CHAR_LF) {
+ printf ("'\n%04d: '", ++LineNum);
+ } else {
+ printf ("%c", SourceFile->FileBufferPtr[0]);
+ }
+
+ SourceFile->FileBufferPtr++;
+ }
+
+ printf ("'\n");
+ printf ("FileSize = %d (0x%X)\n", SourceFile->FileSize, SourceFile->FileSize);
+ RewindFile (SourceFile);
+ }
+}
+
+BOOLEAN
+SFPGetQuotedString (
+ T_CHAR *Str,
+ int Length
+ )
+/*++
+
+Routine Description:
+ Retrieve a quoted-string from the input file.
+
+Arguments:
+ Str - pointer to a copy of the quoted string parsed
+ Length - size of buffer pointed to by Str
+
+Returns:
+ TRUE - next token in input stream was a quoted string, and
+ the string value was returned in Str
+ FALSE - otherwise
+
+--*/
+{
+ SkipWhiteSpace (&mGlobals.SourceFile);
+ if (EndOfFile (&mGlobals.SourceFile)) {
+ return FALSE;
+ }
+
+ if (mGlobals.SourceFile.FileBufferPtr[0] == T_CHAR_DOUBLE_QUOTE) {
+ mGlobals.SourceFile.FileBufferPtr++;
+ while (Length > 0) {
+ if (EndOfFile (&mGlobals.SourceFile)) {
+ return FALSE;
+ }
+ //
+ // Check for closing quote
+ //
+ if (mGlobals.SourceFile.FileBufferPtr[0] == T_CHAR_DOUBLE_QUOTE) {
+ mGlobals.SourceFile.FileBufferPtr++;
+ *Str = 0;
+ return TRUE;
+ }
+
+ *Str = mGlobals.SourceFile.FileBufferPtr[0];
+ Str++;
+ Length--;
+ mGlobals.SourceFile.FileBufferPtr++;
+ }
+ }
+ //
+ // First character was not a quote, or the input string length was
+ // insufficient to contain the quoted string, so return failure code.
+ //
+ return FALSE;
+}
+
+BOOLEAN
+SFPIsEOF (
+ VOID
+ )
+/*++
+
+Routine Description:
+ Return TRUE of FALSE to indicate whether or not we've reached the end of the
+ file we're parsing.
+
+Arguments:
+ NA
+
+Returns:
+ TRUE - EOF reached
+ FALSE - otherwise
+
+--*/
+{
+ SkipWhiteSpace (&mGlobals.SourceFile);
+ return EndOfFile (&mGlobals.SourceFile);
+}
+
+#if 0
+static
+T_CHAR *
+GetQuotedString (
+ SOURCE_FILE *SourceFile,
+ BOOLEAN Optional
+ )
+{
+ T_CHAR *String;
+ T_CHAR *Start;
+ T_CHAR *Ptr;
+ unsigned int Len;
+ BOOLEAN PreviousBackslash;
+
+ if (SourceFile->FileBufferPtr[0] != T_CHAR_DOUBLE_QUOTE) {
+ if (Optional == FALSE) {
+ Error (SourceFile->FileName, SourceFile->LineNum, 0, "expected quoted string", "%S", SourceFile->FileBufferPtr);
+ }
+
+ return NULL;
+ }
+
+ Len = 0;
+ SourceFile->FileBufferPtr++;
+ Start = Ptr = SourceFile->FileBufferPtr;
+ PreviousBackslash = FALSE;
+ while (!EndOfFile (SourceFile)) {
+ if ((SourceFile->FileBufferPtr[0] == T_CHAR_DOUBLE_QUOTE) && (PreviousBackslash == FALSE)) {
+ break;
+ } else if (SourceFile->FileBufferPtr[0] == T_CHAR_CR) {
+ Warning (SourceFile->FileName, SourceFile->LineNum, 0, "carriage return found in quoted string", "%S", Start);
+ PreviousBackslash = FALSE;
+ } else if (SourceFile->FileBufferPtr[0] == T_CHAR_BACKSLASH) {
+ PreviousBackslash = TRUE;
+ } else {
+ PreviousBackslash = FALSE;
+ }
+
+ SourceFile->FileBufferPtr++;
+ Len++;
+ }
+
+ if (SourceFile->FileBufferPtr[0] != T_CHAR_DOUBLE_QUOTE) {
+ Warning (SourceFile->FileName, SourceFile->LineNum, 0, "missing closing quote on string", "%S", Start);
+ } else {
+ SourceFile->FileBufferPtr++;
+ }
+ //
+ // Now allocate memory for the string and save it off
+ //
+ String = (T_CHAR *) malloc ((Len + 1) * sizeof (T_CHAR));
+ if (String == NULL) {
+ Error (NULL, 0, 0, "memory allocation failed", NULL);
+ return NULL;
+ }
+ //
+ // Copy the string from the file buffer to the local copy.
+ // We do no reformatting of it whatsoever at this point.
+ //
+ Ptr = String;
+ while (Len > 0) {
+ *Ptr = *Start;
+ Start++;
+ Ptr++;
+ Len--;
+ }
+
+ *Ptr = 0;
+ return String;
+}
+#endif
+static
+BOOLEAN
+EndOfFile (
+ SOURCE_FILE *SourceFile
+ )
+{
+ //
+ // The file buffer pointer will typically get updated before the End-of-file flag in the
+ // source file structure, so check it first.
+ //
+ if (SourceFile->FileBufferPtr >= SourceFile->FileBuffer + SourceFile->FileSize / sizeof (T_CHAR)) {
+ SourceFile->EndOfFile = TRUE;
+ return TRUE;
+ }
+
+ if (SourceFile->EndOfFile) {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+#if 0
+static
+void
+ProcessTokenInclude (
+ SOURCE_FILE *SourceFile
+ )
+{
+ char IncludeFileName[MAX_PATH];
+ char *To;
+ unsigned int Len;
+ BOOLEAN ReportedError;
+ SOURCE_FILE IncludedSourceFile;
+
+ ReportedError = FALSE;
+ if (SkipWhiteSpace (SourceFile) == 0) {
+ Warning (SourceFile->FileName, SourceFile->LineNum, 0, "expected whitespace following #include keyword", NULL);
+ }
+ //
+ // Should be quoted file name
+ //
+ if (SourceFile->FileBufferPtr[0] != T_CHAR_DOUBLE_QUOTE) {
+ Error (SourceFile->FileName, SourceFile->LineNum, 0, "expected quoted include file name", NULL);
+ goto FailDone;
+ }
+
+ SourceFile->FileBufferPtr++;
+ //
+ // Copy the filename as ascii to our local string
+ //
+ To = IncludeFileName;
+ Len = 0;
+ while (!EndOfFile (SourceFile)) {
+ if ((SourceFile->FileBufferPtr[0] == T_CHAR_CR) || (SourceFile->FileBufferPtr[0] == T_CHAR_LF)) {
+ Error (SourceFile->FileName, SourceFile->LineNum, 0, "end-of-line found in quoted include file name", NULL);
+ goto FailDone;
+ }
+
+ if (SourceFile->FileBufferPtr[0] == T_CHAR_DOUBLE_QUOTE) {
+ SourceFile->FileBufferPtr++;
+ break;
+ }
+ //
+ // If too long, then report the error once and process until the closing quote
+ //
+ Len++;
+ if (!ReportedError && (Len >= sizeof (IncludeFileName))) {
+ Error (SourceFile->FileName, SourceFile->LineNum, 0, "length of include file name exceeds limit", NULL);
+ ReportedError = TRUE;
+ }
+
+ if (!ReportedError) {
+ *To = (T_CHAR) SourceFile->FileBufferPtr[0];
+ To++;
+ }
+
+ SourceFile->FileBufferPtr++;
+ }
+
+ if (!ReportedError) {
+ *To = 0;
+ memset ((char *) &IncludedSourceFile, 0, sizeof (SOURCE_FILE));
+ strcpy (IncludedSourceFile.FileName, IncludeFileName);
+ ProcessIncludeFile (&IncludedSourceFile, SourceFile);
+ }
+
+ return ;
+FailDone:
+ //
+ // Error recovery -- skip to next #
+ //
+ SourceFile->SkipToHash = TRUE;
+}
+#endif
+static
+BOOLEAN
+IsWhiteSpace (
+ SOURCE_FILE *SourceFile
+ )
+{
+ switch (*SourceFile->FileBufferPtr) {
+ case T_CHAR_NULL:
+ case T_CHAR_CR:
+ case T_CHAR_SPACE:
+ case T_CHAR_TAB:
+ case T_CHAR_LF:
+ return TRUE;
+
+ default:
+ return FALSE;
+ }
+}
+
+unsigned int
+SkipWhiteSpace (
+ SOURCE_FILE *SourceFile
+ )
+{
+ unsigned int Count;
+
+ Count = 0;
+ while (!EndOfFile (SourceFile)) {
+ Count++;
+ switch (*SourceFile->FileBufferPtr) {
+ case T_CHAR_NULL:
+ case T_CHAR_CR:
+ case T_CHAR_SPACE:
+ case T_CHAR_TAB:
+ SourceFile->FileBufferPtr++;
+ break;
+
+ case T_CHAR_LF:
+ SourceFile->FileBufferPtr++;
+ SourceFile->LineNum++;
+ break;
+
+ default:
+ return Count - 1;
+ }
+ }
+ //
+ // Some tokens require trailing whitespace. If we're at the end of the
+ // file, then we count that as well.
+ //
+ if ((Count == 0) && (EndOfFile (SourceFile))) {
+ Count++;
+ }
+
+ return Count;
+}
+
+static
+unsigned int
+t_strcmp (
+ T_CHAR *Buffer,
+ T_CHAR *Str
+ )
+/*++
+
+Routine Description:
+ Compare two strings for equality. The string pointed to by 'Buffer' may or may not be null-terminated,
+ so only compare up to the length of Str.
+
+Arguments:
+ Buffer - pointer to first (possibly not null-terminated) string
+ Str - pointer to null-terminated string to compare to Buffer
+
+Returns:
+ Number of bytes matched if exact match
+ 0 if Buffer does not start with Str
+
+--*/
+{
+ unsigned int Len;
+
+ Len = 0;
+ while (*Str && (*Str == *Buffer)) {
+ Buffer++;
+ Str++;
+ Len++;
+ }
+
+ if (*Str) {
+ return 0;
+ }
+
+ return Len;
+}
+
+static
+unsigned int
+t_strlen (
+ T_CHAR *Str
+ )
+{
+ unsigned int Len;
+ Len = 0;
+ while (*Str) {
+ Len++;
+ Str++;
+ }
+
+ return Len;
+}
+
+static
+unsigned int
+t_strncmp (
+ T_CHAR *Str1,
+ T_CHAR *Str2,
+ int Len
+ )
+{
+ while (Len > 0) {
+ if (*Str1 != *Str2) {
+ return Len;
+ }
+
+ Len--;
+ Str1++;
+ Str2++;
+ }
+
+ return 0;
+}
+
+static
+T_CHAR *
+t_strcpy (
+ T_CHAR *Dest,
+ T_CHAR *Src
+ )
+{
+ T_CHAR *SaveDest;
+ SaveDest = Dest;
+ while (*Src) {
+ *Dest = *Src;
+ Dest++;
+ Src++;
+ }
+
+ *Dest = 0;
+ return SaveDest;
+}
+
+static
+void
+RewindFile (
+ SOURCE_FILE *SourceFile
+ )
+{
+ SourceFile->LineNum = 1;
+ SourceFile->FileBufferPtr = SourceFile->FileBuffer;
+ SourceFile->EndOfFile = 0;
+}
+
+static
+UINT32
+GetHexChars (
+ T_CHAR *Buffer,
+ UINT32 BufferLen
+ )
+{
+ UINT32 Len;
+ Len = 0;
+ while (!EndOfFile (&mGlobals.SourceFile) && (BufferLen > 0)) {
+ if (isxdigit (mGlobals.SourceFile.FileBufferPtr[0])) {
+ *Buffer = mGlobals.SourceFile.FileBufferPtr[0];
+ Buffer++;
+ Len++;
+ BufferLen--;
+ mGlobals.SourceFile.FileBufferPtr++;
+ } else {
+ break;
+ }
+ }
+ //
+ // Null terminate if we can
+ //
+ if ((Len > 0) && (BufferLen > 0)) {
+ *Buffer = 0;
+ }
+
+ return Len;
+}
+
+BOOLEAN
+SFPGetGuid (
+ int GuidStyle,
+ EFI_GUID *Value
+ )
+/*++
+
+Routine Description:
+ Parse a GUID from the input stream. Stop when you discover white space.
+
+Arguments:
+ GuidStyle - Style of the following GUID token
+ Value - pointer to EFI_GUID struct for output
+
+Returns:
+ TRUE - GUID string parsed successfully
+ FALSE - otherwise
+
+ GUID styles
+ Style[0] 12345678-1234-5678-AAAA-BBBBCCCCDDDD
+
+--*/
+{
+ UINT32 Value32;
+ UINT32 Index;
+ FILE_POSITION FPos;
+ T_CHAR TempString[20];
+ T_CHAR TempString2[3];
+ T_CHAR *From;
+ T_CHAR *To;
+ UINT32 Len;
+ BOOLEAN Status;
+
+ Status = FALSE;
+ //
+ // Skip white space, then start parsing
+ //
+ SkipWhiteSpace (&mGlobals.SourceFile);
+ GetFilePosition (&FPos);
+ if (EndOfFile (&mGlobals.SourceFile)) {
+ return FALSE;
+ }
+
+ if (GuidStyle == PARSE_GUID_STYLE_5_FIELDS) {
+ //
+ // Style[0] 12345678-1234-5678-AAAA-BBBBCCCCDDDD
+ //
+ Len = GetHexChars (TempString, sizeof (TempString));
+ if ((Len == 0) || (Len > 8)) {
+ goto Done;
+ }
+
+ sscanf (TempString, "%x", &Value32);
+ Value->Data1 = Value32;
+ //
+ // Next two UINT16 fields
+ //
+ if (mGlobals.SourceFile.FileBufferPtr[0] != '-') {
+ goto Done;
+ }
+
+ mGlobals.SourceFile.FileBufferPtr++;
+ Len = GetHexChars (TempString, sizeof (TempString));
+ if ((Len == 0) || (Len > 4)) {
+ goto Done;
+ }
+
+ sscanf (TempString, "%x", &Value32);
+ Value->Data2 = (UINT16) Value32;
+
+ if (mGlobals.SourceFile.FileBufferPtr[0] != '-') {
+ goto Done;
+ }
+
+ mGlobals.SourceFile.FileBufferPtr++;
+ Len = GetHexChars (TempString, sizeof (TempString));
+ if ((Len == 0) || (Len > 4)) {
+ goto Done;
+ }
+
+ sscanf (TempString, "%x", &Value32);
+ Value->Data3 = (UINT16) Value32;
+ //
+ // Parse the "AAAA" as two bytes
+ //
+ if (mGlobals.SourceFile.FileBufferPtr[0] != '-') {
+ goto Done;
+ }
+
+ mGlobals.SourceFile.FileBufferPtr++;
+ Len = GetHexChars (TempString, sizeof (TempString));
+ if ((Len == 0) || (Len > 4)) {
+ goto Done;
+ }
+
+ sscanf (TempString, "%x", &Value32);
+ Value->Data4[0] = (UINT8) (Value32 >> 8);
+ Value->Data4[1] = (UINT8) Value32;
+ if (mGlobals.SourceFile.FileBufferPtr[0] != '-') {
+ goto Done;
+ }
+
+ mGlobals.SourceFile.FileBufferPtr++;
+ //
+ // Read the last 6 bytes of the GUID
+ //
+ //
+ Len = GetHexChars (TempString, sizeof (TempString));
+ if ((Len == 0) || (Len > 12)) {
+ goto Done;
+ }
+ //
+ // Insert leading 0's to make life easier
+ //
+ if (Len != 12) {
+ From = TempString + Len - 1;
+ To = TempString + 11;
+ TempString[12] = 0;
+ while (From >= TempString) {
+ *To = *From;
+ To--;
+ From--;
+ }
+
+ while (To >= TempString) {
+ *To = '0';
+ To--;
+ }
+ }
+ //
+ // Now parse each byte
+ //
+ TempString2[2] = 0;
+ for (Index = 0; Index < 6; Index++) {
+ //
+ // Copy the two characters from the input string to something
+ // we can parse.
+ //
+ TempString2[0] = TempString[Index * 2];
+ TempString2[1] = TempString[Index * 2 + 1];
+ sscanf (TempString2, "%x", &Value32);
+ Value->Data4[Index + 2] = (UINT8) Value32;
+ }
+
+ Status = TRUE;
+ } else {
+ //
+ // Unsupported GUID style
+ //
+ return FALSE;
+ }
+
+Done:
+ if (Status == FALSE) {
+ SetFilePosition (&FPos);
+ }
+
+ return Status;
+}
+
+static
+STATUS
+GetFilePosition (
+ FILE_POSITION *Fpos
+ )
+{
+ Fpos->FileBufferPtr = mGlobals.SourceFile.FileBufferPtr;
+ return STATUS_SUCCESS;
+}
+
+static
+STATUS
+SetFilePosition (
+ FILE_POSITION *Fpos
+ )
+{
+ //
+ // Should check range of pointer
+ //
+ mGlobals.SourceFile.FileBufferPtr = Fpos->FileBufferPtr;
+ return STATUS_SUCCESS;
+}
diff --git a/Source/Common/SimpleFileParsing.h b/Source/Common/SimpleFileParsing.h
new file mode 100644
index 0000000..7cf25a6
--- /dev/null
+++ b/Source/Common/SimpleFileParsing.h
@@ -0,0 +1,120 @@
+/*++
+
+Copyright (c) 2004, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ SimpleFileParsing.h
+
+Abstract:
+
+ Function prototypes and defines for the simple file parsing routines.
+
+--*/
+
+#ifndef _SIMPLE_FILE_PARSING_H_
+#define _SIMPLE_FILE_PARSING_H_
+
+#include <Common/UefiBaseTypes.h>
+
+#define T_CHAR char
+
+STATUS
+SFPInit (
+ VOID
+ )
+;
+
+STATUS
+SFPOpenFile (
+ char *FileName
+ )
+;
+
+BOOLEAN
+SFPIsKeyword (
+ T_CHAR *Str
+ )
+;
+
+BOOLEAN
+SFPIsToken (
+ T_CHAR *Str
+ )
+;
+
+BOOLEAN
+SFPGetNextToken (
+ T_CHAR *Str,
+ unsigned int Len
+ )
+;
+
+BOOLEAN
+SFPGetGuidToken (
+ T_CHAR *Str,
+ UINT32 Len
+ )
+;
+
+#define PARSE_GUID_STYLE_5_FIELDS 0
+
+BOOLEAN
+SFPGetGuid (
+ int GuidStyle,
+ EFI_GUID *Value
+ )
+;
+
+BOOLEAN
+SFPSkipToToken (
+ T_CHAR *Str
+ )
+;
+
+BOOLEAN
+SFPGetNumber (
+ unsigned int *Value
+ )
+;
+
+BOOLEAN
+SFPGetQuotedString (
+ T_CHAR *Str,
+ int Length
+ )
+;
+
+BOOLEAN
+SFPIsEOF (
+ VOID
+ )
+;
+
+STATUS
+SFPCloseFile (
+ VOID
+ )
+;
+
+unsigned
+int
+SFPGetLineNumber (
+ VOID
+ )
+;
+
+T_CHAR *
+SFPGetFileName (
+ VOID
+ )
+;
+
+#endif // #ifndef _SIMPLE_FILE_PARSING_H_
diff --git a/Source/Common/WinNtInclude.h b/Source/Common/WinNtInclude.h
new file mode 100644
index 0000000..80e45b4
--- /dev/null
+++ b/Source/Common/WinNtInclude.h
@@ -0,0 +1,73 @@
+/*--
+
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+ WinNtInclude.h
+
+Abstract:
+ Include file for the WinNt Library
+
+--*/
+
+#ifndef __WIN_NT_INCLUDE_H__
+#define __WIN_NT_INCLUDE_H__
+
+//
+// Win32 include files do not compile clean with /W4, so we use the warning
+// pragma to suppress the warnings for Win32 only. This way our code can stil
+// compile at /W4 (highest warning level) with /WX (warnings cause build
+// errors).
+//
+#pragma warning(disable : 4115)
+#pragma warning(disable : 4201)
+#pragma warning(disable : 4214)
+#pragma warning(disable : 4028)
+#pragma warning(disable : 4133)
+
+#define GUID _WINNT_DUP_GUID_____
+#define _LIST_ENTRY _WINNT_DUP_LIST_ENTRY_FORWARD
+#define LIST_ENTRY _WINNT_DUP_LIST_ENTRY
+#define InterlockedIncrement _WINNT_DUP_InterlockedIncrement
+#define InterlockedDecrement _WINNT_DUP_InterlockedDecrement
+#define InterlockedCompareExchange64 _WINNT_DUP_InterlockedCompareExchange64
+#undef UNALIGNED
+#undef CONST
+#undef VOID
+
+#ifndef __GNUC__
+#include "windows.h"
+#endif
+
+#undef GUID
+#undef _LIST_ENTRY
+#undef LIST_ENTRY
+#undef InterlockedIncrement
+#undef InterlockedDecrement
+#undef InterlockedCompareExchange64
+#undef InterlockedCompareExchangePointer
+
+#define VOID void
+
+//
+// Prevent collisions with Windows API name macros that deal with Unicode/Not issues
+//
+#undef LoadImage
+#undef CreateEvent
+
+//
+// Set the warnings back on as the EFI code must be /W4.
+//
+#pragma warning(default : 4115)
+#pragma warning(default : 4201)
+#pragma warning(default : 4214)
+
+
+#endif
diff --git a/Source/Common/build.xml b/Source/Common/build.xml
new file mode 100644
index 0000000..38ae477
--- /dev/null
+++ b/Source/Common/build.xml
@@ -0,0 +1,65 @@
+<?xml version="1.0" ?>
+<!--
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+-->
+<project default="CommonTools.lib" basedir=".">
+<!--
+ EDK Common Tools Library
+ Copyright (c) 2006, Intel Corporation
+-->
+
+ <taskdef resource="net/sf/antcontrib/antlib.xml"/>
+
+ <property name="tmp" value="tmp"/>
+ <property name="LibName" value="CommonTool"/>
+
+ <property name="LINK_OUTPUT_TYPE" value="static"/>
+ <property name="BUILD_DIR" value="${PACKAGE_DIR}/Common/tmp"/>
+
+ <target name="CommonTools.lib" depends="init, ToolsLibrary">
+ <echo message="The EDK Tool Library: ${LibName} build has completed."/>
+ </target>
+
+ <target name="init">
+ <echo message="Building the EDK Tool Library: ${LibName}"/>
+ <mkdir dir="${BUILD_DIR}"/>
+ </target>
+
+ <target name="ToolsLibrary" depends="init">
+ <cc name="${ToolChain}" objdir="${BUILD_DIR}"
+ outfile="${LIB_DIR}/CommonTools"
+ outtype="static"
+ debug="true"
+ optimize="speed">
+ <compilerarg value="${ExtraArgus}" if="ExtraArgus" />
+ <compilerarg value="-fPIC" if="x86_64_linux"/>
+
+ <includepath path="${PACKAGE_DIR}/Include"/>
+ <includepath path="${PACKAGE_DIR}/Include/${HostArch}"/>
+
+ <fileset dir="${basedir}/Common"
+ includes="*.c" />
+ </cc>
+ </target>
+
+ <target name="clean">
+ <echo message="Removing Intermediate Files Only from ${BUILD_DIR}"/>
+ <delete dir="${BUILD_DIR}"/>
+ </target>
+
+ <target name="cleanall">
+ <echo message="Removing Object Files and the Library: ${LibName}${ext_static}"/>
+ <delete failonerror="false" quiet="true" includeEmptyDirs="true">
+ <fileset dir="${BUILD_DIR}"/>
+ <fileset file="${LIB_DIR}/${LibName}${ext_static}"/>
+ </delete>
+ </target>
+
+</project>
diff --git a/Source/CompressDll/CompressDll.c b/Source/CompressDll/CompressDll.c
new file mode 100644
index 0000000..cc06f26
--- /dev/null
+++ b/Source/CompressDll/CompressDll.c
@@ -0,0 +1,105 @@
+/** @file
+ Compression DLL used by PCD Tools
+
+ Copyright (c) 2006, Intel Corporation All rights reserved.
+ This program and the accompanying materials are licensed and made available
+ under the terms and conditions of the BSD License which accompanies this
+ distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#if defined(__GNUC__)
+typedef long long __int64;/*For cygwin build*/
+#endif
+#include "CompressDll.h"
+#include "EfiCompress.h"
+
+extern
+EFI_STATUS
+Compress (
+ IN UINT8 *SrcBuffer,
+ IN UINT32 SrcSize,
+ IN UINT8 *DstBuffer,
+ IN OUT UINT32 *DstSize
+ );
+
+JNIEXPORT jbyteArray JNICALL Java_org_tianocore_framework_tasks_Compress_CallCompress
+(JNIEnv *env, jobject obj, jbyteArray SourceBuffer, jint SourceSize, jstring path)
+{
+ char* DestBuffer;
+ int DestSize;
+ int Result;
+ char *InputBuffer;
+ jbyteArray OutputBuffer;
+ jbyte *TempByte;
+
+ DestSize = 0;
+ DestBuffer = NULL;
+
+ TempByte = (*env)->GetByteArrayElements(env, SourceBuffer, 0);
+ InputBuffer = (char*) TempByte;
+
+
+ //
+ // First call compress function and get need buffer size
+ //
+
+ Result = Compress (
+ (char*) InputBuffer,
+ SourceSize,
+ DestBuffer,
+ &DestSize
+ );
+
+ if (Result = EFI_BUFFER_TOO_SMALL) {
+ DestBuffer = malloc (DestSize);
+ }
+
+ //
+ // Second call compress and get the DestBuffer value
+ //
+ Result = Compress(
+ (char*) InputBuffer,
+ SourceSize,
+ DestBuffer,
+ &DestSize
+ );
+
+ //
+ // new a MV array to store the return compressed buffer
+ //
+ OutputBuffer = (*env)->NewByteArray(env, DestSize);
+ (*env)->SetByteArrayRegion(env, OutputBuffer,0, DestSize, (jbyte*) DestBuffer);
+
+ //
+ // Free Ouputbuffer.
+ //
+ free (DestBuffer);
+
+
+ if (Result != 0) {
+ return NULL;
+ } else {
+ return OutputBuffer;
+ }
+}
+
+#ifdef _MSC_VER
+BOOLEAN
+__stdcall
+DllMainCRTStartup(
+ unsigned int hDllHandle,
+ unsigned int nReason,
+ void* Reserved
+)
+{
+ return TRUE;
+}
+#else
+#ifdef __GNUC__
+#endif
+#endif
+
diff --git a/Source/CompressDll/CompressDll.h b/Source/CompressDll/CompressDll.h
new file mode 100644
index 0000000..fa3b83c
--- /dev/null
+++ b/Source/CompressDll/CompressDll.h
@@ -0,0 +1,22 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+
+#include <jni.h>
+/* Header for class org_tianocore_frameworktasks_Compress */
+
+#ifndef _Included_org_tianocore_framework_tasks_Compress
+#define _Included_org_tianocore_framework_tasks_Compress
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * Class: org_tianocore_frameworktasks_Compress
+ * Method: CallCompress
+ * Signature: ([BILjava/lang/String;)[B
+ */
+JNIEXPORT jbyteArray JNICALL Java_org_tianocore_framework_tasks_Compress_CallCompress
+ (JNIEnv *, jobject, jbyteArray, jint, jstring);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/Source/CompressDll/build.xml b/Source/CompressDll/build.xml
new file mode 100644
index 0000000..6f591b3
--- /dev/null
+++ b/Source/CompressDll/build.xml
@@ -0,0 +1,78 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+-->
+<project default="GenTool" basedir=".">
+<!--
+ EDK CompressDll Tool Library
+ Copyright (c) 2006, Intel Corporation
+-->
+
+ <property name="WORKSPACE" value="${env.WORKSPACE}"/>
+ <property name="LibName" value="CompressDll"/>
+ <property name="FileSet" value="CompressDll.c CompressDll.h"/>
+ <property name="LibFileSet" value="CompressDll.c DepexParser.h"/>
+
+ <taskdef resource="net/sf/antcontrib/antlib.xml"/>
+
+ <property name="LINK_OUTPUT_TYPE" value="static"/>
+ <property name="BUILD_DIR" value="${WORKSPACE}/Tools/CCode/Source/${LibName}/tmp"/>
+
+ <target name="GenTool" depends="init,Lib" >
+ <echo message="The EDK Tool Library: ${LibName} build has completed!"/>
+ </target>
+
+ <target name="init">
+ <echo message="Building the EDK Tool Library: ${LibName}"/>
+ <mkdir dir="${BUILD_DIR}"/>
+ </target>
+
+ <target name="Lib" depends="init">
+ <cc name="${ToolChain}"
+ objdir="${BUILD_DIR}"
+ outtype="shared"
+ debug="true"
+ optimize="speed"
+ outfile="${BIN_DIR}/${LibName}"
+ outputfileproperty="result"
+ >
+ <compilerarg value="${ExtraArgus}" if="ExtraArgus" />
+ <fileset dir="${LibName}" includes="${LibFileSet}" defaultexcludes="TRUE" excludes="*.xml *.inf"/>
+ <includepath path="${PACKAGE_DIR}/Include"/>
+ <includepath path="${PACKAGE_DIR}/Include/${HostArch}"/>
+ <includepath path="${PACKAGE_DIR}/Common"/>
+ <includepath path="${env.JAVA_HOME}/include"/>
+ <includepath path="${env.JAVA_HOME}/include/linux" if="gcc"/>
+ <includepath path="${env.JAVA_HOME}/include/win32" if="cygwin"/>
+ <includepath path="${env.JAVA_HOME}/include/win32" if="msft"/>
+ <libset dir="${LIB_DIR}" libs="CommonTools"/>
+ <syslibset libs="kernel32" if="msft"/>
+ <linkerarg value="-mno-cygwin" if="cygwin"/>
+ <linkerarg value="--add-stdcall-alias" if="cygwin"/>
+ </cc>
+ <copy file="${result}" tofile="${BIN_DIR}/CompressDll.dll"/>
+ <chmod file="${BIN_DIR}/CompressDll.dll" perm="ugo+x"/>
+ </target>
+
+ <target name="clean">
+ <echo message="Removing Intermediate Files Only"/>
+ <delete>
+ <fileset dir="${BUILD_DIR}" includes="*.obj"/>
+ </delete>
+ </target>
+
+ <target name="cleanall">
+ <echo message="Removing Object Files and the Executable: ${LibName}${ext_dynamic}"/>
+ <delete failonerror="false" quiet="true" includeEmptyDirs="true">
+ <fileset dir="${BUILD_DIR}"/>
+ <fileset file="${BIN_DIR}/${LibName}.*"/>
+ </delete>
+ </target>
+</project>
diff --git a/Source/CreateMtFile/CreateMtFile.c b/Source/CreateMtFile/CreateMtFile.c
new file mode 100644
index 0000000..1c17b3d
--- /dev/null
+++ b/Source/CreateMtFile/CreateMtFile.c
@@ -0,0 +1,247 @@
+/*++
+
+Copyright (c) 1999-2006 Intel Corporation. All rights reserved
+This program and the accompanying materials are licensed and made available
+under the terms and conditions of the BSD License which accompanies this
+distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+
+Module Name:
+
+ CreateMtFile.c
+
+Abstract:
+
+ Simple utility to create a pad file containing fixed data.
+
+--*/
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <Common/UefiBaseTypes.h>
+
+#define PROGRAM_NAME "CreateMtFile"
+
+typedef struct {
+ INT8 *OutFileName;
+ INT8 ByteValue;
+ UINT32 FileSize;
+} OPTIONS;
+
+static
+EFI_STATUS
+ProcessArgs (
+ IN INT32 Argc,
+ IN INT8 *Argv[],
+ IN OUT OPTIONS *Options
+ );
+
+static
+void
+Usage (
+ VOID
+ );
+
+int
+main (
+ IN INT32 Argc,
+ IN INT8 *Argv[]
+ )
+/*++
+
+Routine Description:
+
+ Main entry point for this utility.
+
+Arguments:
+
+ Standard C entry point args Argc and Argv
+
+Returns:
+
+ EFI_SUCCESS if good to go
+
+--*/
+// GC_TODO: ] - add argument and description to function comment
+// GC_TODO: EFI_INVALID_PARAMETER - add return value to function comment
+// GC_TODO: EFI_DEVICE_ERROR - add return value to function comment
+// GC_TODO: EFI_DEVICE_ERROR - add return value to function comment
+{
+ FILE *OutFptr;
+ OPTIONS Options;
+
+ //
+ // Process the command-line arguments.
+ //
+ if (ProcessArgs (Argc, Argv, &Options) != EFI_SUCCESS) {
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // Open the output file
+ //
+ if ((OutFptr = fopen (Options.OutFileName, "wb")) == NULL) {
+ fprintf (
+ stdout,
+ PROGRAM_NAME " ERROR: Could not open output file '%s' for writing\n",
+ Options.OutFileName
+ );
+ return EFI_DEVICE_ERROR;
+ }
+ //
+ // Write the pad bytes. Do it the slow way (one at a time) for now.
+ //
+ while (Options.FileSize > 0) {
+ if (fwrite (&Options.ByteValue, 1, 1, OutFptr) != 1) {
+ fclose (OutFptr);
+ fprintf (stdout, PROGRAM_NAME " ERROR: Failed to write to output file\n");
+ return EFI_DEVICE_ERROR;
+ }
+
+ Options.FileSize--;
+ }
+ //
+ // Close the file
+ //
+ fclose (OutFptr);
+ return EFI_SUCCESS;
+}
+
+static
+EFI_STATUS
+ProcessArgs (
+ IN INT32 Argc,
+ IN INT8 *Argv[],
+ IN OUT OPTIONS *Options
+ )
+/*++
+
+Routine Description:
+
+ Process the command line arguments.
+
+Arguments:
+
+ Argc - argument count as passed in to the entry point function
+ Argv - array of arguments as passed in to the entry point function
+ Options - stucture of where to put the values of the parsed arguments
+
+Returns:
+
+ EFI_SUCCESS if everything looks good
+ EFI_INVALID_PARAMETER otherwise
+
+--*/
+// GC_TODO: ] - add argument and description to function comment
+{
+ UINT32 Multiplier;
+
+ //
+ // Clear the options
+ //
+ memset ((char *) Options, 0, sizeof (OPTIONS));
+
+ //
+ // Skip program name
+ //
+ Argv++;
+ Argc--;
+ if (Argc < 2) {
+ Usage ();
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // If first arg is dash-option, then print usage.
+ //
+ if (Argv[0][0] == '-') {
+ Usage ();
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // First arg is file name
+ //
+ Options->OutFileName = Argv[0];
+ Argc--;
+ Argv++;
+
+ //
+ // Second arg is file size. Allow 0x1000, 0x100K, 1024, 1K
+ //
+ Multiplier = 1;
+ if ((Argv[0][strlen (Argv[0]) - 1] == 'k') || (Argv[0][strlen (Argv[0]) - 1] == 'K')) {
+ Multiplier = 1024;
+ }
+ //
+ // Look for 0x prefix on file size
+ //
+ if ((Argv[0][0] == '0') && ((Argv[0][1] == 'x') || (Argv[0][1] == 'X'))) {
+ if (sscanf (Argv[0], "%x", &Options->FileSize) != 1) {
+ fprintf (stdout, PROGRAM_NAME " ERROR: Invalid file size '%s'\n", Argv[0]);
+ Usage ();
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // Otherwise must be a decimal number
+ //
+ } else {
+ if (sscanf (Argv[0], "%d", &Options->FileSize) != 1) {
+ fprintf (stdout, PROGRAM_NAME " ERROR: Invalid file size '%s'\n", Argv[0]);
+ Usage ();
+ return EFI_INVALID_PARAMETER;
+ }
+ }
+
+ Options->FileSize *= Multiplier;
+ //
+ // Assume byte value of 0xff
+ //
+ Options->ByteValue = (INT8) (UINT8) 0xFF;
+ return EFI_SUCCESS;
+}
+//
+// Print utility usage info
+//
+static
+void
+Usage (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ None
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+{
+ UINT32 Index;
+ static const INT8 *Text[] = {
+ " ",
+ "Usage: "PROGRAM_NAME " OutFileName FileSize",
+ " where:",
+ " OutFileName is the name of the output file to generate",
+ " FileSize is the size of the file to create",
+ " Examples:",
+ " "PROGRAM_NAME " OutFile.bin 32K",
+ " "PROGRAM_NAME " OutFile.bin 0x1000",
+ " ",
+ NULL
+ };
+
+ for (Index = 0; Text[Index] != NULL; Index++) {
+ fprintf (stdout, "%s\n", Text[Index]);
+ }
+}
diff --git a/Source/CreateMtFile/build.xml b/Source/CreateMtFile/build.xml
new file mode 100644
index 0000000..3be4c90
--- /dev/null
+++ b/Source/CreateMtFile/build.xml
@@ -0,0 +1,69 @@
+<?xml version="1.0" ?>
+<!--
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+-->
+<project default="GenTool" basedir=".">
+<!--
+ EDK CreateMtFile Tool
+ Copyright (c) 2006, Intel Corporation
+-->
+ <property name="ToolName" value="CreateMtFile"/>
+ <property name="FileSet" value="*.c"/>
+
+ <taskdef resource="net/sf/antcontrib/antlib.xml"/>
+
+ <property name="LINK_OUTPUT_TYPE" value="static"/>
+ <property name="BUILD_DIR" value="${PACKAGE_DIR}/${ToolName}/tmp"/>
+
+ <target name="GenTool" depends="init, Tool">
+ <echo message="The EDK Tool: ${ToolName} build has completed!"/>
+ </target>
+
+ <target name="init">
+ <echo message="Building the EDK Tool: ${ToolName}"/>
+ <mkdir dir="${BUILD_DIR}"/>
+ </target>
+
+ <target name="Tool" depends="init">
+ <cc name="${ToolChain}" objdir="${BUILD_DIR}"
+ outfile="${BIN_DIR}/${ToolName}"
+ outtype="executable"
+ optimize="speed"
+ debug="true">
+ <compilerarg value="${ExtraArgus}" if="ExtraArgus" />
+
+ <fileset dir="${basedir}/${ToolName}"
+ includes="${FileSet}"
+ defaultexcludes="TRUE"
+ excludes="*.xml *.inf"/>
+
+ <includepath path="${PACKAGE_DIR}/Include"/>
+ <includepath path="${PACKAGE_DIR}/Include/Ia32"/>
+ <includepath path="${PACKAGE_DIR}/Common"/>
+ </cc>
+ </target>
+
+ <target name="clean">
+ <echo message="Removing Intermediate Files Only"/>
+ <delete>
+ <fileset dir="${BUILD_DIR}" includes="*.obj"/>
+ </delete>
+ </target>
+
+ <target name="cleanall">
+ <echo message="Removing Object Files and the Executable: ${ToolName}${ext_exe}"/>
+ <delete failonerror="false" quiet="true" includeEmptyDirs="true">
+ <fileset dir="${BUILD_DIR}"/>
+ <fileset file="${BIN_DIR}/${ToolName}${ext_exe}"/>
+ <fileset file="${BIN_DIR}/${ToolName}.pdb"/>
+ </delete>
+ </target>
+
+</project>
diff --git a/Source/CustomizedCompress/CustomizedCompress.c b/Source/CustomizedCompress/CustomizedCompress.c
new file mode 100644
index 0000000..0dc6612
--- /dev/null
+++ b/Source/CustomizedCompress/CustomizedCompress.c
@@ -0,0 +1,146 @@
+/*++
+
+Copyright (c) 2004, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ CustomizedCompress.c
+
+Abstract:
+
+ Header file for Customized compression routine
+
+--*/
+
+#include <Common/UefiBaseTypes.h>
+
+EFI_STATUS
+SetCustomizedCompressionType (
+ IN CHAR8 *Type
+ )
+/*++
+
+Routine Description:
+
+The implementation of Customized SetCompressionType().
+
+Arguments:
+ Type - The type if compression.
+
+Returns:
+
+ EFI_SUCCESS - The type has been set.
+ EFI_UNSUPPORTED - This type is unsupported.
+
+
+--*/
+{
+ return EFI_UNSUPPORTED;
+}
+
+EFI_STATUS
+CustomizedGetInfo (
+ IN VOID *Source,
+ IN UINT32 SrcSize,
+ OUT UINT32 *DstSize,
+ OUT UINT32 *ScratchSize
+ )
+/*++
+
+Routine Description:
+
+The implementation of Customized GetInfo().
+
+Arguments:
+ Source - The source buffer containing the compressed data.
+ SrcSize - The size of source buffer
+ DstSize - The size of destination buffer.
+ ScratchSize - The size of scratch buffer.
+
+Returns:
+
+ EFI_SUCCESS - The size of destination buffer and the size of scratch buffer are successull retrieved.
+ EFI_INVALID_PARAMETER - The source data is corrupted
+ EFI_UNSUPPORTED - The operation is unsupported.
+
+
+--*/
+{
+ return EFI_UNSUPPORTED;
+}
+
+EFI_STATUS
+CustomizedDecompress (
+ IN VOID *Source,
+ IN UINT32 SrcSize,
+ IN OUT VOID *Destination,
+ IN UINT32 DstSize,
+ IN OUT VOID *Scratch,
+ IN UINT32 ScratchSize
+ )
+/*++
+
+Routine Description:
+
+ The implementation of Customized Decompress().
+
+Arguments:
+
+ This - The protocol instance pointer
+ Source - The source buffer containing the compressed data.
+ SrcSize - The size of source buffer
+ Destination - The destination buffer to store the decompressed data
+ DstSize - The size of destination buffer.
+ Scratch - The buffer used internally by the decompress routine. This buffer is needed to store intermediate data.
+ ScratchSize - The size of scratch buffer.
+
+Returns:
+
+ EFI_SUCCESS - Decompression is successfull
+ EFI_INVALID_PARAMETER - The source data is corrupted
+ EFI_UNSUPPORTED - The operation is unsupported.
+
+--*/
+{
+ return EFI_UNSUPPORTED;
+}
+
+EFI_STATUS
+CustomizedCompress (
+ IN UINT8 *SrcBuffer,
+ IN UINT32 SrcSize,
+ IN UINT8 *DstBuffer,
+ IN OUT UINT32 *DstSize
+ )
+/*++
+
+Routine Description:
+
+ The Customized compression routine.
+
+Arguments:
+
+ SrcBuffer - The buffer storing the source data
+ SrcSize - The size of source data
+ DstBuffer - The buffer to store the compressed data
+ DstSize - On input, the size of DstBuffer; On output,
+ the size of the actual compressed data.
+
+Returns:
+
+ EFI_BUFFER_TOO_SMALL - The DstBuffer is too small. In this case,
+ DstSize contains the size needed.
+ EFI_SUCCESS - Compression is successful.
+
+ EFI_UNSUPPORTED - The operation is unsupported.
+--*/
+{
+ return EFI_UNSUPPORTED;
+}
diff --git a/Source/CustomizedCompress/build.xml b/Source/CustomizedCompress/build.xml
new file mode 100644
index 0000000..35bffa4
--- /dev/null
+++ b/Source/CustomizedCompress/build.xml
@@ -0,0 +1,73 @@
+<?xml version="1.0" ?>
+<!--
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+-->
+<project default="GenLib" basedir="." name="CustomizedCompressLibrary">
+<!--
+ EDK Customized Compress Library
+ Copyright (c) 2006, Intel Corporation
+-->
+
+ <taskdef resource="net/sf/antcontrib/antlib.xml"/>
+
+ <property name="LibName" value="CustomizedCompress"/>
+ <property name="LINK_OUTPUT_TYPE" value="static"/>
+ <property name="BUILD_DIR" value="${PACKAGE_DIR}/CustomizedCompress/tmp"/>
+
+ <target name="GenLib" depends="init, CustomizedCompress">
+ <echo message="The EDK Tool Library ${LibName} build has completed!"/>
+ </target>
+
+ <target name="init">
+ <echo message="Building the EDK Tool Library: ${LibName}"/>
+ <mkdir dir="${BUILD_DIR}"/>
+ </target>
+
+ <target name="CustomizedCompress" depends="init">
+ <cc name="${ToolChain}" objdir="${BUILD_DIR}"
+ outfile="${LIB_DIR}/${LibName}"
+ outtype="static"
+ debug="true"
+ optimize="speed">
+
+ <fileset dir="${basedir}/CustomizedCompress"
+ includes="*.c"
+ defaultexcludes="TRUE"
+ excludes="*.xml *.inf"/>
+
+ <includepath path="${PACKAGE_DIR}/Include"/>
+ <includepath path="${PACKAGE_DIR}/Include/Ia32"/>
+ </cc>
+ <if>
+ <istrue value="msft"/>
+ <then>
+ <exec dir="${BUILD_DIR}" executable="lib" failonerror="false">
+ <arg line="/NOLOGO *.lib /OUT:${LIB_DIR}/CustomizedCompress${ext_static}"/>
+ </exec>
+ </then>
+ </if>
+ </target>
+
+ <target name="clean">
+ <echo message="Removing Intermediate Files Only"/>
+ <delete>
+ <fileset dir="${BUILD_DIR}" includes="*.obj"/>
+ </delete>
+ </target>
+
+ <target name="cleanall">
+ <echo message="Removing Object Files and the Library: ${LibName}${ext_static}"/>
+ <delete failonerror="false" quiet="true" includeEmptyDirs="true">
+ <fileset dir="${BUILD_DIR}"/>
+ <fileset file="${LIB_DIR}/${LibName}${ext_static}"/>
+ </delete>
+ </target>
+
+</project>
diff --git a/Source/EfiCompress/EfiCompressMain.c b/Source/EfiCompress/EfiCompressMain.c
new file mode 100644
index 0000000..492210f
--- /dev/null
+++ b/Source/EfiCompress/EfiCompressMain.c
@@ -0,0 +1,165 @@
+/*++
+
+Copyright (c) 1999-2006 Intel Corporation. All rights reserved
+This program and the accompanying materials are licensed and made available
+under the terms and conditions of the BSD License which accompanies this
+distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+
+Module Name:
+
+ EfiCompressMain.c
+
+Abstract:
+
+ The main function for the compression utility.
+
+--*/
+
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <stdarg.h>
+#include <stdio.h>
+
+#include <Common/UefiBaseTypes.h>
+
+#include "EfiCompress.h"
+
+int
+main (
+ INT32 argc,
+ CHAR8 *argv[]
+ )
+/*++
+
+Routine Description:
+
+ Compresses the input files
+
+Arguments:
+
+ argc - number of arguments passed into the command line.
+ argv[] - files to compress and files to output compressed data to.
+
+Returns:
+
+ int: 0 for successful execution of the function.
+
+--*/
+{
+ EFI_STATUS Status;
+ FILE *infile;
+ FILE *outfile;
+ UINT32 SrcSize;
+ UINT32 DstSize;
+ UINT8 *SrcBuffer;
+ UINT8 *DstBuffer;
+ UINT8 Buffer[8];
+
+ //
+ // Added for makefile debug - KCE
+ //
+ INT32 arg_counter;
+ printf ("\n\n");
+ for (arg_counter = 0; arg_counter < argc; arg_counter++) {
+ printf ("%s ", argv[arg_counter]);
+ }
+
+ printf ("\n\n");
+
+ SrcBuffer = DstBuffer = NULL;
+
+ infile = outfile = NULL;
+
+ if (argc != 3) {
+ printf ("Usage: EFICOMPRESS <infile> <outfile>\n");
+ goto Done;
+ }
+
+ if ((outfile = fopen (argv[2], "wb")) == NULL) {
+ printf ("Can't open output file\n");
+ goto Done;
+ }
+
+ if ((infile = fopen (argv[1], "rb")) == NULL) {
+ printf ("Can't open input file\n");
+ goto Done;
+ }
+ //
+ // Get the size of source file
+ //
+ SrcSize = 0;
+ while (fread (Buffer, 1, 1, infile)) {
+ SrcSize++;
+
+ }
+ //
+ // Read in the source data
+ //
+ if ((SrcBuffer = malloc (SrcSize)) == NULL) {
+ printf ("Can't allocate memory\n");
+ goto Done;
+ }
+
+ rewind (infile);
+ if (fread (SrcBuffer, 1, SrcSize, infile) != SrcSize) {
+ printf ("Can't read from source\n");
+ goto Done;
+ }
+ //
+ // Get destination data size and do the compression
+ //
+ DstSize = 0;
+ Status = Compress (SrcBuffer, SrcSize, DstBuffer, &DstSize);
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+ if ((DstBuffer = malloc (DstSize)) == NULL) {
+ printf ("Can't allocate memory\n");
+ goto Done;
+ }
+
+ Status = Compress (SrcBuffer, SrcSize, DstBuffer, &DstSize);
+ }
+
+ if (EFI_ERROR (Status)) {
+ printf ("Compress Error\n");
+ goto Done;
+ }
+
+ printf ("\nOrig Size = %ld\n", SrcSize);
+ printf ("Comp Size = %ld\n", DstSize);
+
+ if (DstBuffer == NULL) {
+ printf ("No destination to write to.\n");
+ goto Done;
+ }
+ //
+ // Write out the result
+ //
+ if (fwrite (DstBuffer, 1, DstSize, outfile) != DstSize) {
+ printf ("Can't write to destination file\n");
+ }
+
+Done:
+ if (SrcBuffer) {
+ free (SrcBuffer);
+ }
+
+ if (DstBuffer) {
+ free (DstBuffer);
+ }
+
+ if (infile) {
+ fclose (infile);
+ }
+
+ if (outfile) {
+ fclose (outfile);
+ }
+
+ return 0;
+}
diff --git a/Source/EfiCompress/build.xml b/Source/EfiCompress/build.xml
new file mode 100644
index 0000000..32826d2
--- /dev/null
+++ b/Source/EfiCompress/build.xml
@@ -0,0 +1,69 @@
+<?xml version="1.0" ?>
+<!--
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+-->
+<project default="GenTool" basedir=".">
+<!--
+ EDK EfiCompress Tool
+ Copyright (c) 2006, Intel Corporation
+-->
+ <property name="ToolName" value="EfiCompress"/>
+ <property name="FileSet" value="*.c"/>
+
+ <taskdef resource="net/sf/antcontrib/antlib.xml"/>
+
+ <property name="LINK_OUTPUT_TYPE" value="static"/>
+ <property name="BUILD_DIR" value="${PACKAGE_DIR}/${ToolName}/tmp"/>
+
+ <target name="GenTool" depends="init, Tool">
+ <echo message="The EDK Tool: ${ToolName} build has completed!"/>
+ </target>
+
+ <target name="init">
+ <echo message="Building the EDK Tool: ${ToolName}"/>
+ <mkdir dir="${BUILD_DIR}"/>
+ </target>
+
+ <target name="Tool" depends="init">
+ <cc name="${ToolChain}" objdir="${BUILD_DIR}"
+ outfile="${BIN_DIR}/${ToolName}"
+ outtype="executable"
+ optimize="speed"
+ debug="true">
+
+ <fileset dir="${basedir}/${ToolName}"
+ includes="${FileSet}"
+ defaultexcludes="TRUE"
+ excludes="*.xml *.inf"/>
+
+ <includepath path="${PACKAGE_DIR}/Include"/>
+ <includepath path="${PACKAGE_DIR}/Include/${HostArch}"/>
+ <includepath path="${PACKAGE_DIR}/Common"/>
+ <libset dir="${LIB_DIR}" libs="CommonTools"/>
+ </cc>
+ </target>
+
+ <target name="clean">
+ <echo message="Removing Intermediate Files Only"/>
+ <delete>
+ <fileset dir="${BUILD_DIR}" includes="*.obj"/>
+ </delete>
+ </target>
+
+ <target name="cleanall">
+ <echo message="Removing Object Files and the Executable: ${ToolName}${ext_exe}"/>
+ <delete failonerror="false" quiet="true" includeEmptyDirs="true">
+ <fileset dir="${BUILD_DIR}"/>
+ <fileset file="${BIN_DIR}/${ToolName}${ext_exe}"/>
+ <fileset file="${BIN_DIR}/${ToolName}.pdb"/>
+ </delete>
+ </target>
+
+</project>
diff --git a/Source/EfiRom/EfiRom.c b/Source/EfiRom/EfiRom.c
new file mode 100644
index 0000000..2cc478b
--- /dev/null
+++ b/Source/EfiRom/EfiRom.c
@@ -0,0 +1,1536 @@
+/*++
+
+Copyright (c) 1999-2006 Intel Corporation. All rights reserved
+This program and the accompanying materials are licensed and made available
+under the terms and conditions of the BSD License which accompanies this
+distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ EfiRom.c
+
+Abstract:
+
+ Utility program to create an EFI option ROM image from binary and
+ EFI PE32 files.
+
+
+--*/
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <Common/UefiBaseTypes.h>
+#include <Common/EfiImage.h> // for PE32 structure definitions
+#include <Common/MultiPhase.h>
+
+#include <IndustryStandard/pci22.h> // for option ROM header structures
+
+#include "EfiCompress.h"
+#include "CommonLib.h"
+
+//
+// Version of this utility
+//
+#define UTILITY_VERSION "v2.5"
+
+//
+// Define some status return values
+//
+#define STATUS_SUCCESS 0
+#define STATUS_WARNING 1
+#define STATUS_ERROR 2
+
+//
+// Define the max length of a filename
+//
+#define MAX_PATH 200
+
+#define DEFAULT_OUTPUT_EXTENSION ".rom"
+
+//
+// Max size for an option ROM image
+//
+#define MAX_OPTION_ROM_SIZE (1024 * 1024 * 16) // 16MB
+//
+// Values for the indicator field in the PCI data structure
+//
+#define INDICATOR_LAST 0x80 // last file in series of files
+//
+// Masks for the FILE_LIST.FileFlags field
+//
+#define FILE_FLAG_BINARY 0x01
+#define FILE_FLAG_EFI 0x02
+#define FILE_FLAG_COMPRESS 0x04
+
+//
+// Use this linked list structure to keep track of all the filenames
+// specified on the command line.
+//
+typedef struct _FILE_LIST {
+ struct _FILE_LIST *Next;
+ INT8 *FileName;
+ UINT32 FileFlags;
+ UINT32 ClassCode;
+ UINT16 CodeRevision;
+} FILE_LIST;
+
+//
+// Use this to track our command-line options
+//
+typedef struct {
+ INT8 OutFileName[MAX_PATH];
+ INT8 NoLast;
+ INT8 Verbose;
+ INT8 DumpOption;
+ UINT8 DevIdValid;
+ UINT8 VendIdValid;
+ UINT16 VendId;
+ UINT16 DevId;
+ FILE_LIST *FileList;
+} OPTIONS;
+
+//
+// Make a global structure to keep track of command-line options
+//
+static OPTIONS mOptions;
+
+//
+// Use these to convert from machine type value to a named type
+//
+typedef struct {
+ UINT16 Value;
+ char *Name;
+} STRING_LOOKUP;
+
+static STRING_LOOKUP mMachineTypes[] = {
+ EFI_IMAGE_MACHINE_IA32,
+ "IA32",
+ EFI_IMAGE_MACHINE_IA64,
+ "IA64",
+ EFI_IMAGE_MACHINE_EBC,
+ "EBC",
+ 0,
+ NULL
+};
+
+static STRING_LOOKUP mSubsystemTypes[] = {
+ EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION,
+ "EFI application",
+ EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER,
+ "EFI boot service driver",
+ EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER,
+ "EFI runtime driver",
+ 0,
+ NULL
+};
+//
+// Function prototypes
+//
+static
+void
+Usage (
+ VOID
+ );
+
+static
+int
+ParseCommandLine (
+ int Argc,
+ char *Argv[],
+ OPTIONS *Options
+ );
+
+static
+int
+CheckPE32File (
+ FILE *Fptr,
+ UINT16 *MachineType,
+ UINT16 *SubSystem
+ );
+
+static
+int
+ProcessEfiFile (
+ FILE *OutFptr,
+ FILE_LIST *InFile,
+ UINT16 VendId,
+ UINT16 DevId,
+ UINT32 *Size
+ );
+
+static
+int
+ProcessBinFile (
+ FILE *OutFptr,
+ FILE_LIST *InFile,
+ UINT32 *Size
+ );
+
+static
+void
+DumpImage (
+ FILE_LIST *InFile
+ );
+
+char *
+GetMachineTypeStr (
+ UINT16 MachineType
+ );
+
+static
+char *
+GetSubsystemTypeStr (
+ UINT16 SubsystemType
+ );
+
+main (
+ int Argc,
+ char *Argv[]
+ )
+/*++
+
+Routine Description:
+
+ Given an EFI image filename, create a ROM-able image by creating an option
+ ROM header and PCI data structure, filling them in, and then writing the
+ option ROM header + PCI data structure + EFI image out to the output file.
+
+Arguments:
+
+ Argc - standard C main() argument count
+
+ Argv - standard C main() argument list
+
+Returns:
+
+ 0 success
+ non-zero otherwise
+
+--*/
+// GC_TODO: ] - add argument and description to function comment
+{
+ INT8 *Ext;
+ FILE *FptrOut;
+ UINT32 Status;
+ FILE_LIST *FList;
+ UINT32 TotalSize;
+ UINT32 Size;
+
+ Status = STATUS_SUCCESS;
+ FptrOut = NULL;
+
+ //
+ // Parse the command line arguments
+ //
+ if (ParseCommandLine (Argc, Argv, &mOptions)) {
+ return STATUS_ERROR;
+ }
+ //
+ // If dumping an image, then do that and quit
+ //
+ if (mOptions.DumpOption) {
+ DumpImage (mOptions.FileList);
+ goto BailOut;
+ }
+ //
+ // Determine the output filename. Either what they specified on
+ // the command line, or the first input filename with a different extension.
+ //
+ if (!mOptions.OutFileName[0]) {
+ strcpy (mOptions.OutFileName, mOptions.FileList->FileName);
+ //
+ // Find the last . on the line and replace the filename extension with
+ // the default
+ //
+ for (Ext = mOptions.OutFileName + strlen (mOptions.OutFileName) - 1;
+ (Ext >= mOptions.OutFileName) && (*Ext != '.') && (*Ext != '\\');
+ Ext--
+ )
+ ;
+ //
+ // If dot here, then insert extension here, otherwise append
+ //
+ if (*Ext != '.') {
+ Ext = mOptions.OutFileName + strlen (mOptions.OutFileName);
+ }
+
+ strcpy (Ext, DEFAULT_OUTPUT_EXTENSION);
+ }
+ //
+ // Make sure we don't have the same filename for input and output files
+ //
+ for (FList = mOptions.FileList; FList != NULL; FList = FList->Next) {
+ if (stricmp (mOptions.OutFileName, FList->FileName) == 0) {
+ Status = STATUS_ERROR;
+ fprintf (
+ stdout,
+ "ERROR: Input and output file names must be different - %s = %s\n",
+ FList->FileName,
+ mOptions.OutFileName
+ );
+ goto BailOut;
+ }
+ }
+ //
+ // Now open our output file
+ //
+ if ((FptrOut = fopen (mOptions.OutFileName, "w+b")) == NULL) {
+ fprintf (stdout, "ERROR: Failed to open output file %s\n", mOptions.OutFileName);
+ goto BailOut;
+ }
+ //
+ // Process all our files
+ //
+ TotalSize = 0;
+ for (FList = mOptions.FileList; FList != NULL; FList = FList->Next) {
+ Size = 0;
+ if (FList->FileFlags & FILE_FLAG_EFI) {
+ if (mOptions.Verbose) {
+ fprintf (stdout, "Processing EFI file %s\n", FList->FileName);
+ }
+
+ Status = ProcessEfiFile (FptrOut, FList, mOptions.VendId, mOptions.DevId, &Size);
+ } else if (FList->FileFlags & FILE_FLAG_BINARY) {
+ if (mOptions.Verbose) {
+ fprintf (stdout, "Processing binary file %s\n", FList->FileName);
+ }
+
+ Status = ProcessBinFile (FptrOut, FList, &Size);
+ } else {
+ fprintf (stdout, "ERROR: File not specified as EFI or binary: %s\n", FList->FileName);
+ Status = STATUS_ERROR;
+ }
+
+ if (mOptions.Verbose) {
+ fprintf (stdout, " Output size = 0x%X\n", Size);
+ }
+
+ if (Status != STATUS_SUCCESS) {
+ break;
+ }
+
+ TotalSize += Size;
+ }
+ //
+ // Check total size
+ //
+ if (TotalSize > MAX_OPTION_ROM_SIZE) {
+ fprintf (
+ stdout,
+ "ERROR: Option ROM image size exceeds limit 0x%X bytes\n",
+ MAX_OPTION_ROM_SIZE
+ );
+ Status = STATUS_ERROR;
+ }
+
+BailOut:
+ if (FptrOut != NULL) {
+ fclose (FptrOut);
+ }
+ //
+ // Clean up our file list
+ //
+ while (mOptions.FileList != NULL) {
+ FList = mOptions.FileList->Next;
+ free (mOptions.FileList);
+ mOptions.FileList = FList;
+ }
+
+ return Status;
+}
+
+static
+int
+ProcessBinFile (
+ FILE *OutFptr,
+ FILE_LIST *InFile,
+ UINT32 *Size
+ )
+/*++
+
+Routine Description:
+
+ Process a binary input file.
+
+Arguments:
+
+ OutFptr - file pointer to output binary ROM image file we're creating
+ InFile - structure contains information on the binary file to process
+ Size - pointer to where to return the size added to the output file
+
+Returns:
+
+ 0 - successful
+
+--*/
+{
+ FILE *InFptr;
+ UINT32 TotalSize;
+ UINT32 FileSize;
+ UINT8 *Buffer;
+ UINT32 Status;
+ PCI_EXPANSION_ROM_HEADER *RomHdr;
+ PCI_DATA_STRUCTURE *PciDs;
+ UINT32 Index;
+ UINT8 ByteCheckSum;
+
+ Status = STATUS_SUCCESS;
+
+ //
+ // Try to open the input file
+ //
+ if ((InFptr = fopen (InFile->FileName, "rb")) == NULL) {
+ fprintf (stdout, "ERROR: Failed to open input file %s\n", InFile->FileName);
+ return STATUS_ERROR;
+ }
+ //
+ // Seek to the end of the input file and get the file size. Then allocate
+ // a buffer to read it in to.
+ //
+ fseek (InFptr, 0, SEEK_END);
+ FileSize = ftell (InFptr);
+ if (mOptions.Verbose) {
+ fprintf (stdout, " File size = 0x%X\n", FileSize);
+ }
+
+ fseek (InFptr, 0, SEEK_SET);
+ Buffer = (INT8 *) malloc (FileSize);
+ if (Buffer == NULL) {
+ fprintf (stdout, "ERROR: Memory allocation failed\n");
+ Status = STATUS_ERROR;
+ goto BailOut;
+ }
+
+ if (fread (Buffer, FileSize, 1, InFptr) != 1) {
+ fprintf (stdout, "ERROR: Failed to read all bytes from input file\n");
+ Status = STATUS_ERROR;
+ goto BailOut;
+ }
+ //
+ // Total size must be an even multiple of 512 bytes, and can't exceed
+ // the option ROM image size.
+ //
+ TotalSize = FileSize;
+ if (TotalSize & 0x1FF) {
+ TotalSize = (TotalSize + 0x200) &~0x1ff;
+ }
+
+ if (TotalSize > MAX_OPTION_ROM_SIZE) {
+ fprintf (
+ stdout,
+ "ERROR: Option ROM image %s size exceeds limit 0x%X bytes\n",
+ InFile->FileName,
+ MAX_OPTION_ROM_SIZE
+ );
+ Status = STATUS_ERROR;
+ goto BailOut;
+ }
+ //
+ // Return the size to the caller so they can keep track of the running total.
+ //
+ *Size = TotalSize;
+
+ //
+ // Crude check to make sure it's a legitimate ROM image
+ //
+ RomHdr = (PCI_EXPANSION_ROM_HEADER *) Buffer;
+ if (RomHdr->Signature != PCI_EXPANSION_ROM_HEADER_SIGNATURE) {
+ fprintf (stdout, "ERROR: ROM image file has invalid ROM signature\n");
+ Status = STATUS_ERROR;
+ goto BailOut;
+ }
+ //
+ // Make sure the pointer to the PCI data structure is within the size of the image.
+ // Then check it for valid signature.
+ //
+ if ((RomHdr->PcirOffset > FileSize) || (RomHdr->PcirOffset == 0)) {
+ fprintf (stdout, "ERROR: Invalid PCI data structure offset\n");
+ Status = STATUS_ERROR;
+ goto BailOut;
+ }
+
+ PciDs = (PCI_DATA_STRUCTURE *) (Buffer + RomHdr->PcirOffset);
+ if (PciDs->Signature != PCI_DATA_STRUCTURE_SIGNATURE) {
+ fprintf (stdout, "ERROR: PCI data structure has invalid signature\n");
+ Status = STATUS_ERROR;
+ goto BailOut;
+ }
+ //
+ // If this is the last image, then set the LAST bit unless requested not
+ // to via the command-line -l argument. Otherwise, make sure you clear it.
+ //
+ if ((InFile->Next == NULL) && (mOptions.NoLast == 0)) {
+ PciDs->Indicator = INDICATOR_LAST;
+ } else {
+ PciDs->Indicator = 0;
+ }
+
+ ByteCheckSum = 0;
+ for (Index = 0; Index < FileSize - 1; Index++) {
+ ByteCheckSum = (UINT8) (ByteCheckSum + Buffer[Index]);
+ }
+
+ Buffer[FileSize - 1] = (UINT8) ((~ByteCheckSum) + 1);
+ fprintf (stdout, "CheckSUm = %02x\n", (UINT32) Buffer[FileSize - 1]);
+
+ //
+ // Now copy the input file contents out to the output file
+ //
+ if (fwrite (Buffer, FileSize, 1, OutFptr) != 1) {
+ fprintf (stdout, "ERROR: Failed to write all file bytes to output file\n");
+ Status = STATUS_ERROR;
+ goto BailOut;
+ }
+
+ TotalSize -= FileSize;
+ //
+ // Pad the rest of the image to make it a multiple of 512 bytes
+ //
+ while (TotalSize > 0) {
+ putc (~0, OutFptr);
+ TotalSize--;
+ }
+
+BailOut:
+ if (InFptr != NULL) {
+ fclose (InFptr);
+ }
+
+ if (Buffer != NULL) {
+ free (Buffer);
+ }
+ //
+ // Print the file name if errors occurred
+ //
+ if (Status != STATUS_SUCCESS) {
+ fprintf (stdout, "Error processing binary file %s\n", InFile->FileName);
+ }
+
+ return Status;
+}
+
+static
+int
+ProcessEfiFile (
+ FILE *OutFptr,
+ FILE_LIST *InFile,
+ UINT16 VendId,
+ UINT16 DevId,
+ UINT32 *Size
+ )
+/*++
+
+Routine Description:
+
+ Process a PE32 EFI file.
+
+Arguments:
+
+ OutFptr - file pointer to output binary ROM image file we're creating
+ InFile - structure contains information on the PE32 file to process
+ VendId - vendor ID as required in the option ROM header
+ DevId - device ID as required in the option ROM header
+ Size - pointer to where to return the size added to the output file
+
+Returns:
+
+ 0 - successful
+
+--*/
+{
+ UINT32 Status;
+ FILE *InFptr;
+ EFI_PCI_EXPANSION_ROM_HEADER RomHdr;
+ PCI_DATA_STRUCTURE PciDs;
+ UINT32 FileSize;
+ UINT32 CompressedFileSize;
+ UINT8 *Buffer;
+ UINT8 *CompressedBuffer;
+ UINT8 *TempBufferPtr;
+ UINT32 TotalSize;
+ UINT32 HeaderSize;
+ UINT16 MachineType;
+ UINT16 SubSystem;
+ UINT32 HeaderPadBytes;
+
+ //
+ // Try to open the input file
+ //
+ if ((InFptr = fopen (InFile->FileName, "rb")) == NULL) {
+ fprintf (stdout, "ERROR: Failed to open input file %s\n", InFile->FileName);
+ return STATUS_ERROR;
+ }
+ //
+ // Initialize our buffer pointers to null.
+ //
+ Buffer = NULL;
+ CompressedBuffer = NULL;
+
+ //
+ // Double-check the file to make sure it's what we expect it to be
+ //
+ Status = CheckPE32File (InFptr, &MachineType, &SubSystem);
+ if (Status != STATUS_SUCCESS) {
+ goto BailOut;
+ }
+ //
+ // Seek to the end of the input file and get the file size
+ //
+ fseek (InFptr, 0, SEEK_END);
+ FileSize = ftell (InFptr);
+
+ //
+ // Get the size of the headers we're going to put in front of the image. The
+ // EFI header must be aligned on a 4-byte boundary, so pad accordingly.
+ //
+ if (sizeof (RomHdr) & 0x03) {
+ HeaderPadBytes = 4 - (sizeof (RomHdr) & 0x03);
+ } else {
+ HeaderPadBytes = 0;
+ }
+
+ HeaderSize = sizeof (PCI_DATA_STRUCTURE) + HeaderPadBytes + sizeof (EFI_PCI_EXPANSION_ROM_HEADER);
+ if (mOptions.Verbose) {
+ fprintf (stdout, " File size = 0x%X\n", FileSize);
+ }
+ //
+ // Allocate memory for the entire file (in case we have to compress), then
+ // seek back to the beginning of the file and read it into our buffer.
+ //
+ Buffer = (INT8 *) malloc (FileSize);
+ if (Buffer == NULL) {
+ fprintf (stdout, "ERROR: Memory allocation failed\n");
+ Status = STATUS_ERROR;
+ goto BailOut;
+ }
+
+ fseek (InFptr, 0, SEEK_SET);
+ if (fread (Buffer, FileSize, 1, InFptr) != 1) {
+ fprintf (stdout, "ERROR: Failed to read all bytes from input file\n");
+ Status = STATUS_ERROR;
+ goto BailOut;
+ }
+ //
+ // Now determine the size of the final output file. It's either the header size
+ // plus the file's size, or the header size plus the compressed file size.
+ //
+ if (InFile->FileFlags & FILE_FLAG_COMPRESS) {
+ //
+ // Allocate a buffer into which we can compress the image, compress it,
+ // and use that size as the new size.
+ //
+ CompressedBuffer = (INT8 *) malloc (FileSize);
+ if (CompressedBuffer == NULL) {
+ fprintf (stdout, "ERROR: Memory allocation failed\n");
+ Status = STATUS_ERROR;
+ goto BailOut;
+ }
+
+ CompressedFileSize = FileSize;
+ Status = Compress (Buffer, FileSize, CompressedBuffer, &CompressedFileSize);
+ if (Status != STATUS_SUCCESS) {
+ fprintf (stdout, "ERROR: Compression failed\n");
+ goto BailOut;
+ }
+ //
+ // Now compute the size, then swap buffer pointers.
+ //
+ if (mOptions.Verbose) {
+ fprintf (stdout, " Comp size = 0x%X\n", CompressedFileSize);
+ }
+
+ TotalSize = CompressedFileSize + HeaderSize;
+ FileSize = CompressedFileSize;
+ TempBufferPtr = Buffer;
+ Buffer = CompressedBuffer;
+ CompressedBuffer = TempBufferPtr;
+ } else {
+ TotalSize = FileSize + HeaderSize;
+ }
+ //
+ // Total size must be an even multiple of 512 bytes
+ //
+ if (TotalSize & 0x1FF) {
+ TotalSize = (TotalSize + 0x200) &~0x1ff;
+ }
+ //
+ // Check size
+ //
+ if (TotalSize > MAX_OPTION_ROM_SIZE) {
+ fprintf (
+ stdout,
+ "ERROR: Option ROM image %s size exceeds limit 0x%X bytes\n",
+ InFile->FileName,
+ MAX_OPTION_ROM_SIZE
+ );
+ Status = STATUS_ERROR;
+ goto BailOut;
+ }
+ //
+ // Return the size to the caller so they can keep track of the running total.
+ //
+ *Size = TotalSize;
+
+ //
+ // Now fill in the ROM header. These values come from chapter 18 of the
+ // EFI 1.02 specification.
+ //
+ memset (&RomHdr, 0, sizeof (RomHdr));
+ RomHdr.Signature = PCI_EXPANSION_ROM_HEADER_SIGNATURE;
+ RomHdr.InitializationSize = (UINT16) (TotalSize / 512);
+ RomHdr.EfiSignature = EFI_PCI_EXPANSION_ROM_HEADER_EFISIGNATURE;
+ RomHdr.EfiSubsystem = SubSystem;
+ RomHdr.EfiMachineType = MachineType;
+ RomHdr.EfiImageHeaderOffset = (UINT16) HeaderSize;
+ RomHdr.PcirOffset = (UINT16) (sizeof (RomHdr) + HeaderPadBytes);
+ //
+ // Set image as compressed or not
+ //
+ if (InFile->FileFlags & FILE_FLAG_COMPRESS) {
+ RomHdr.CompressionType = EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED;
+ }
+ //
+ // Fill in the PCI data structure
+ //
+ memset (&PciDs, 0, sizeof (PCI_DATA_STRUCTURE));
+
+ PciDs.Signature = PCI_DATA_STRUCTURE_SIGNATURE;
+ PciDs.VendorId = VendId;
+ PciDs.DeviceId = DevId;
+ PciDs.Length = (UINT16) sizeof (PCI_DATA_STRUCTURE);
+ PciDs.Revision = 0;
+ //
+ // Class code and code revision from the command line (optional)
+ //
+ PciDs.ClassCode[0] = (UINT8) InFile->ClassCode;
+ PciDs.ClassCode[1] = (UINT8) (InFile->ClassCode >> 8);
+ PciDs.ClassCode[2] = (UINT8) (InFile->ClassCode >> 16);
+ PciDs.ImageLength = RomHdr.InitializationSize;
+ PciDs.CodeRevision = InFile->CodeRevision;
+ PciDs.CodeType = PCI_CODE_TYPE_EFI_IMAGE;
+
+ //
+ // If this is the last image, then set the LAST bit unless requested not
+ // to via the command-line -l argument.
+ //
+ if ((InFile->Next == NULL) && (mOptions.NoLast == 0)) {
+ PciDs.Indicator = INDICATOR_LAST;
+ }
+ //
+ // Write the ROM header to the output file
+ //
+ if (fwrite (&RomHdr, sizeof (RomHdr), 1, OutFptr) != 1) {
+ fprintf (stdout, "ERROR: Failed to write ROM header to output file\n");
+ Status = STATUS_ERROR;
+ goto BailOut;
+ }
+
+ //
+ // Write pad bytes to align the PciDs
+ //
+ while (HeaderPadBytes > 0) {
+ if (putc (0, OutFptr) == EOF) {
+ fprintf (stdout, "ERROR: Failed to write ROM header pad bytes to output file\n");
+ Status = STATUS_ERROR;
+ goto BailOut;
+ }
+
+ HeaderPadBytes--;
+ }
+ //
+ // Write the PCI data structure header to the output file
+ //
+ if (fwrite (&PciDs, sizeof (PciDs), 1, OutFptr) != 1) {
+ fprintf (stdout, "ERROR: Failed to write PCI ROM header to output file\n");
+ Status = STATUS_ERROR;
+ goto BailOut;
+ }
+ //
+ // Keep track of how many bytes left to write
+ //
+ TotalSize -= HeaderSize;
+
+ //
+ // Now dump the input file's contents to the output file
+ //
+ if (fwrite (Buffer, FileSize, 1, OutFptr) != 1) {
+ fprintf (stdout, "ERROR: Failed to write all file bytes to output file\n");
+ Status = STATUS_ERROR;
+ goto BailOut;
+ }
+
+ TotalSize -= FileSize;
+ //
+ // Pad the rest of the image to make it a multiple of 512 bytes
+ //
+ while (TotalSize > 0) {
+ if (putc (~0, OutFptr) == EOF) {
+ fprintf (stdout, "ERROR: Failed to write trailing pad bytes output file\n");
+ Status = STATUS_ERROR;
+ goto BailOut;
+ }
+
+ TotalSize--;
+ }
+
+BailOut:
+ if (InFptr != NULL) {
+ fclose (InFptr);
+ }
+
+ //
+ // Free up our buffers
+ //
+ if (Buffer != NULL) {
+ free (Buffer);
+ }
+
+ if (CompressedBuffer != NULL) {
+ free (CompressedBuffer);
+ }
+ //
+ // Print the file name if errors occurred
+ //
+ if (Status != STATUS_SUCCESS) {
+ fprintf (stdout, "Error processing EFI file %s\n", InFile->FileName);
+ }
+
+ return Status;
+}
+
+static
+int
+CheckPE32File (
+ FILE *Fptr,
+ UINT16 *MachineType,
+ UINT16 *SubSystem
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ Fptr - GC_TODO: add argument description
+ MachineType - GC_TODO: add argument description
+ SubSystem - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+{
+ /*++
+
+Routine Description:
+
+ Given a file pointer to a supposed PE32 image file, verify that it is indeed a
+ PE32 image file, and then return the machine type in the supplied pointer.
+
+Arguments:
+
+ Fptr File pointer to the already-opened PE32 file
+ MachineType Location to stuff the machine type of the PE32 file. This is needed
+ because the image may be Itanium-based, IA32, or EBC.
+
+Returns:
+
+ 0 success
+ non-zero otherwise
+
+--*/
+ EFI_IMAGE_DOS_HEADER DosHeader;
+ EFI_IMAGE_FILE_HEADER FileHdr;
+ EFI_IMAGE_OPTIONAL_HEADER OptionalHdr;
+ UINT32 PESig;
+
+ //
+ // Position to the start of the file
+ //
+ fseek (Fptr, 0, SEEK_SET);
+
+ //
+ // Read the DOS header
+ //
+ if (fread (&DosHeader, sizeof (DosHeader), 1, Fptr) != 1) {
+ fprintf (stdout, "ERROR: Failed to read the DOS stub from the input file\n");
+ return STATUS_ERROR;
+ }
+ //
+ // Check the magic number (0x5A4D)
+ //
+ if (DosHeader.e_magic != EFI_IMAGE_DOS_SIGNATURE) {
+ fprintf (stdout, "ERROR: Input file does not appear to be a PE32 image (magic number)\n");
+ return STATUS_ERROR;
+ }
+ //
+ // Position into the file and check the PE signature
+ //
+ fseek (Fptr, (long) DosHeader.e_lfanew, SEEK_SET);
+ if (fread (&PESig, sizeof (PESig), 1, Fptr) != 1) {
+ fprintf (stdout, "ERROR: Failed to read PE signature bytes from input file\n");
+ return STATUS_ERROR;
+ }
+ //
+ // Check the PE signature in the header "PE\0\0"
+ //
+ if (PESig != EFI_IMAGE_NT_SIGNATURE) {
+ fprintf (stdout, "ERROR: Input file does not appear to be a PE32 image (signature)\n");
+ return STATUS_ERROR;
+ }
+ //
+ // Read the file header and stuff their MachineType
+ //
+ if (fread (&FileHdr, sizeof (FileHdr), 1, Fptr) != 1) {
+ fprintf (stdout, "ERROR: Failed to read PE file header from input file\n");
+ return STATUS_ERROR;
+ }
+
+ memcpy ((char *) MachineType, &FileHdr.Machine, 2);
+
+ //
+ // Read the optional header so we can get the subsystem
+ //
+ if (fread (&OptionalHdr, sizeof (OptionalHdr), 1, Fptr) != 1) {
+ fprintf (stdout, "ERROR: Failed to read COFF optional header from input file\n");
+ return STATUS_ERROR;
+ }
+
+ *SubSystem = OptionalHdr.Subsystem;
+ if (mOptions.Verbose) {
+ fprintf (stdout, " Got subsystem = 0x%X from image\n", (int) *SubSystem);
+ }
+ //
+ // Good to go
+ //
+ return STATUS_SUCCESS;
+}
+
+static
+int
+ParseCommandLine (
+ int Argc,
+ char *Argv[],
+ OPTIONS *Options
+ )
+/*++
+
+Routine Description:
+
+ Given the Argc/Argv program arguments, and a pointer to an options structure,
+ parse the command-line options and check their validity.
+
+
+Arguments:
+
+ Argc - standard C main() argument count
+ Argv[] - standard C main() argument list
+ Options - pointer to a structure to store the options in
+
+Returns:
+
+ STATUS_SUCCESS success
+ non-zero otherwise
+
+--*/
+//
+{
+ FILE_LIST *FileList;
+
+ FILE_LIST *PrevFileList;
+ UINT32 FileFlags;
+ UINT32 ClassCode;
+ UINT32 CodeRevision;
+
+ FileFlags = 0;
+
+ //
+ // Clear out the options
+ //
+ memset ((char *) Options, 0, sizeof (OPTIONS));
+
+ //
+ // To avoid compile warnings
+ //
+ FileList = PrevFileList = NULL;
+
+ ClassCode = 0;
+ CodeRevision = 0;
+ //
+ // Skip over the program name
+ //
+ Argc--;
+ Argv++;
+
+ //
+ // If no arguments, assume they want usage info
+ //
+ if (Argc == 0) {
+ Usage ();
+ return STATUS_ERROR;
+ }
+ //
+ // Process until no more arguments
+ //
+ while (Argc > 0) {
+ if ((Argv[0][0] == '-') || (Argv[0][0] == '/')) {
+ //
+ // To simplify string comparisons, replace slashes with dashes
+ //
+ Argv[0][0] = '-';
+
+ //
+ // Vendor ID specified with -v
+ //
+ if (stricmp (Argv[0], "-v") == 0) {
+ //
+ // Make sure there's another parameter
+ //
+ if (Argc > 1) {
+ Options->VendId = (UINT16) strtol (Argv[1], NULL, 16);
+ Options->VendIdValid = 1;
+ } else {
+ fprintf (
+ stdout,
+ "ERROR: Missing Vendor ID with %s\n\n",
+ Argv[0]
+ );
+ Usage ();
+ return STATUS_ERROR;
+ }
+
+ Argv++;
+ Argc--;
+ } else if (stricmp (Argv[0], "-d") == 0) {
+ //
+ // Device ID specified with -d
+ // Make sure there's another parameter
+ //
+ if (Argc > 1) {
+ Options->DevId = (UINT16) strtol (Argv[1], NULL, 16);
+ Options->DevIdValid = 1;
+ } else {
+ fprintf (
+ stdout,
+ "ERROR: Missing Device ID with %s\n\n",
+ Argv[0]
+ );
+ Usage ();
+ return STATUS_ERROR;
+ }
+
+ Argv++;
+ Argc--;
+ } else if (stricmp (Argv[0], "-o") == 0) {
+ //
+ // Output filename specified with -o
+ // Make sure there's another parameter
+ //
+ if (Argc > 1) {
+ strcpy (Options->OutFileName, Argv[1]);
+ } else {
+ fprintf (
+ stdout,
+ "ERROR: Missing output file name with %s\n\n",
+ Argv[0]
+ );
+ Usage ();
+ return STATUS_ERROR;
+ }
+
+ Argv++;
+ Argc--;
+ } else if ((stricmp (Argv[0], "-h") == 0) || (strcmp (Argv[0], "-?") == 0)) {
+ //
+ // Help option
+ //
+ Usage ();
+ return STATUS_ERROR;
+ } else if (stricmp (Argv[0], "-b") == 0) {
+ //
+ // Specify binary files with -b
+ //
+ FileFlags = (FileFlags &~FILE_FLAG_EFI) | FILE_FLAG_BINARY;
+ } else if ((stricmp (Argv[0], "-e") == 0) || (stricmp (Argv[0], "-ec") == 0)) {
+ //
+ // Specify EFI files with -e. Specify EFI-compressed with -ec.
+ //
+ FileFlags = (FileFlags &~FILE_FLAG_BINARY) | FILE_FLAG_EFI;
+ if ((Argv[0][2] == 'c') || (Argv[0][2] == 'C')) {
+ FileFlags |= FILE_FLAG_COMPRESS;
+ }
+ //
+ // Specify not to set the LAST bit in the last file with -l
+ //
+ } else if (stricmp (Argv[0], "-l") == 0) {
+ Options->NoLast = 1;
+ } else if (stricmp (Argv[0], "-p") == 0) {
+ //
+ // -v for verbose would have been nicer, but it's already used. Let's use
+ // -p for prolix (wordy) output
+ //
+ Options->Verbose = 1;
+ } else if (stricmp (Argv[0], "-dump") == 0) {
+ //
+ // -dump for dumping a ROM image. In this case, say that the device id
+ // and vendor id are valid so we don't have to specify bogus ones on the
+ // command line.
+ //
+ Options->DumpOption = 1;
+
+ Options->VendIdValid = 1;
+ Options->DevIdValid = 1;
+ FileFlags = FILE_FLAG_BINARY;
+ } else if (stricmp (Argv[0], "-cc") == 0) {
+ //
+ // Class code value for the next file in the list.
+ // Make sure there's another parameter
+ //
+ if (Argc > 1) {
+ //
+ // No error checking on the return value. Could check for LONG_MAX,
+ // LONG_MIN, or 0 class code value if desired. Check range (3 bytes)
+ // at least.
+ //
+ ClassCode = (UINT32) strtol (Argv[1], NULL, 16);
+ if (ClassCode & 0xFF000000) {
+ fprintf (stdout, "ERROR: Class code %s out of range\n", Argv[1]);
+ return STATUS_ERROR;
+ }
+ } else {
+ fprintf (
+ stdout,
+ "ERROR: Missing class code value with %s\n\n",
+ Argv[0]
+ );
+ Usage ();
+ return STATUS_ERROR;
+ }
+
+ Argv++;
+ Argc--;
+ } else if (stricmp (Argv[0], "-rev") == 0) {
+ //
+ // Code revision in the PCI data structure. The value is for the next
+ // file in the list.
+ // Make sure there's another parameter
+ //
+ if (Argc > 1) {
+ //
+ // No error checking on the return value. Could check for LONG_MAX,
+ // LONG_MIN, or 0 value if desired. Check range (2 bytes)
+ // at least.
+ //
+ CodeRevision = (UINT32) strtol (Argv[1], NULL, 16);
+ if (CodeRevision & 0xFFFF0000) {
+ fprintf (stdout, "ERROR: Code revision %s out of range\n", Argv[1]);
+ return STATUS_ERROR;
+ }
+ } else {
+ fprintf (
+ stdout,
+ "ERROR: Missing code revision value with %s\n\n",
+ Argv[0]
+ );
+ Usage ();
+ return STATUS_ERROR;
+ }
+
+ Argv++;
+ Argc--;
+ } else {
+ fprintf (stdout, "ERROR: Invalid option specified: %s\n\n", Argv[0]);
+ Usage ();
+ return STATUS_ERROR;
+ }
+ } else {
+ //
+ // Not a slash-option argument. Must be a file name. Make sure they've specified
+ // -e or -b already.
+ //
+ if ((FileFlags & (FILE_FLAG_BINARY | FILE_FLAG_EFI)) == 0) {
+ fprintf (stdout, "ERROR: Missing -e or -b with input file %s\n", Argv[0]);
+ return STATUS_ERROR;
+ }
+ //
+ // Create a new file structure
+ //
+ FileList = (FILE_LIST *) malloc (sizeof (FILE_LIST));
+ if (FileList == NULL) {
+ fprintf (stdout, "ERROR: Memory allocation failure\n");
+ return STATUS_ERROR;
+ }
+
+ memset ((char *) FileList, 0, sizeof (FILE_LIST));
+ FileList->FileName = Argv[0];
+ FileList->FileFlags = FileFlags;
+ if (Options->FileList == NULL) {
+ Options->FileList = FileList;
+ } else {
+ if (PrevFileList == NULL) {
+ PrevFileList = FileList;
+ } else {
+ PrevFileList->Next = FileList;
+ }
+ }
+
+ PrevFileList = FileList;
+ //
+ // Set the class code and code revision for this file, then reset the values.
+ //
+ FileList->ClassCode = ClassCode;
+ FileList->CodeRevision = (UINT16) CodeRevision;
+ ClassCode = 0;
+ CodeRevision = 0;
+ }
+ //
+ // Next argument
+ //
+ Argv++;
+ Argc--;
+ }
+ //
+ // Make sure they specified a device ID and vendor ID
+ //
+ if (!Options->VendIdValid) {
+ fprintf (stdout, "ERROR: Missing Vendor ID on command line\n\n");
+ Usage ();
+ return STATUS_ERROR;
+ }
+
+ if (!Options->DevIdValid) {
+ fprintf (stdout, "ERROR: Missing Device ID on command line\n\n");
+ Usage ();
+ return STATUS_ERROR;
+ }
+ //
+ // Must have specified some files
+ //
+ if (Options->FileList == NULL) {
+ fprintf (stdout, "ERROR: Missing input file name\n");
+ Usage ();
+ return STATUS_ERROR;
+ }
+
+ return 0;
+}
+
+static
+void
+Usage (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Print usage information for this utility.
+
+Arguments:
+
+ None.
+
+Returns:
+
+ Nothing.
+
+--*/
+{
+ int Index;
+ static const char *Msg[] = {
+ "EfiRom "UTILITY_VERSION " - Intel EFI Make Option ROM utility",
+ " Copyright (C), 1999-2002 Intel Coproration\n",
+ " Create an option ROM image from a list of input files",
+ " Usage: efirom {-p} [-v VendorId] [-d DeviceId] {-o OutFileName} ",
+ " [-e|-b] [FileName(s)]",
+ " where:",
+ " VendorId - required hex PCI Vendor ID for the device",
+ " DeviceId - required hex PCI Device ID for the device",
+ " OutFileName - optional output file name. Default is the first input",
+ " file name with a "DEFAULT_OUTPUT_EXTENSION " file extension",
+ " FileNames - input PE32 or binary file name(s)",
+ " BinFileName - input binary file name(s)",
+ " -p - for verbose output",
+ " -l - to not automatically set the LAST bit on the last file",
+ " -b - following FileNames are binary files",
+ " -e - following FileNames are EFI PE32 image files",
+ " -ec - following FileNames are EFI PE32 image files, and should",
+ " be compressed by this utility",
+ " -cc ClassCode - to use hex ClassCode in the PCI data structure header for",
+ " the following FileName",
+ " -rev Revision - to use hex Revision in the PCI data structure header for",
+ " the following FileName",
+ " -dump - to dump the headers of an existing option ROM image",
+ "",
+ "Example usage: EfiRom -v 0xABCD -d 0x1234 -b File1.bin File2.bin -e File1.efi File2.efi ",
+ "",
+ NULL
+ };
+
+ for (Index = 0; Msg[Index] != NULL; Index++) {
+ fprintf (stdout, "%s\n", Msg[Index]);
+ }
+}
+
+static
+void
+DumpImage (
+ FILE_LIST *InFile
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ InFile - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+{
+ PCI_EXPANSION_ROM_HEADER PciRomHdr;
+ FILE *InFptr;
+ UINT32 ImageStart;
+ UINT32 ImageCount;
+ EFI_PCI_EXPANSION_ROM_HEADER EfiRomHdr;
+ PCI_DATA_STRUCTURE PciDs;
+
+ //
+ // Open the input file
+ //
+ if ((InFptr = fopen (InFile->FileName, "rb")) == NULL) {
+ fprintf (
+ stdout,
+ "ERROR: Could not open input file %s\n",
+ InFile->FileName
+ );
+ return ;
+ }
+ //
+ // Go through the image and dump the header stuff for each
+ //
+ ImageCount = 0;
+ for (;;) {
+ //
+ // Save our postition in the file, since offsets in the headers
+ // are relative to the particular image.
+ //
+ ImageStart = ftell (InFptr);
+ ImageCount++;
+
+ //
+ // Read the option ROM header. Have to assume a raw binary image for now.
+ //
+ if (fread (&PciRomHdr, sizeof (PciRomHdr), 1, InFptr) != 1) {
+ fprintf (stdout, "ERROR: Failed to read PCI ROM header from file\n");
+ goto BailOut;
+ }
+
+ //
+ // Dump the contents of the header
+ //
+ fprintf (stdout, "Image %d -- Offset 0x%X\n", ImageCount, ImageStart);
+ fprintf (stdout, " ROM header contents\n");
+ fprintf (stdout, " Signature 0x%04X\n", (UINT32) PciRomHdr.Signature);
+ fprintf (stdout, " PCIR offset 0x%04X\n", (UINT32) PciRomHdr.PcirOffset);
+ //
+ // Find PCI data structure
+ //
+ if (fseek (InFptr, ImageStart + PciRomHdr.PcirOffset, SEEK_SET)) {
+ fprintf (stdout, "ERROR: Failed to seek to PCI data structure\n");
+ goto BailOut;
+ }
+ //
+ // Read and dump the PCI data structure
+ //
+ if (fread (&PciDs, sizeof (PciDs), 1, InFptr) != 1) {
+ fprintf (stdout, "ERROR: Failed to read PCI data structure from file\n");
+ goto BailOut;
+ }
+
+ fprintf (stdout, " PCI Data Structure\n");
+ fprintf (
+ stdout,
+ " Signature %c%c%c%c\n",
+ (char) PciDs.Signature,
+ (char) (PciDs.Signature >> 8),
+ (char) (PciDs.Signature >> 16),
+ (char) (PciDs.Signature >> 24)
+ );
+ fprintf (stdout, " Vendor ID 0x%04X\n", PciDs.VendorId);
+ fprintf (stdout, " Device ID 0x%04X\n", PciDs.DeviceId);
+ fprintf (
+ stdout,
+ " Class Code 0x%06X\n",
+ (UINT32) (PciDs.ClassCode[0] | (PciDs.ClassCode[1] << 8) | (PciDs.ClassCode[2] << 16))
+ );
+ fprintf (stdout, " Image size 0x%X\n", PciDs.ImageLength * 512);
+ fprintf (stdout, " Code revision: 0x%04X\n", PciDs.CodeRevision);
+ fprintf (stdout, " Indicator 0x%02X", (UINT32) PciDs.Indicator);
+ //
+ // Print the indicator, used to flag the last image
+ //
+ if (PciDs.Indicator == INDICATOR_LAST) {
+ fprintf (stdout, " (last image)\n");
+ } else {
+ fprintf (stdout, "\n");
+ }
+ //
+ // Print the code type. If EFI code, then we can provide more info.
+ //
+ fprintf (stdout, " Code type 0x%02X", (UINT32) PciDs.CodeType);
+ if (PciDs.CodeType == PCI_CODE_TYPE_EFI_IMAGE) {
+ fprintf (stdout, " (EFI image)\n");
+ //
+ // Re-read the header as an EFI ROM header, then dump more info
+ //
+ fprintf (stdout, " EFI ROM header contents\n");
+ if (fseek (InFptr, ImageStart, SEEK_SET)) {
+ fprintf (stdout, "ERROR: Failed to re-seek to ROM header structure\n");
+ goto BailOut;
+ }
+
+ if (fread (&EfiRomHdr, sizeof (EfiRomHdr), 1, InFptr) != 1) {
+ fprintf (stdout, "ERROR: Failed to read EFI PCI ROM header from file\n");
+ goto BailOut;
+ }
+ //
+ // Now dump more info
+ //
+ fprintf (stdout, " EFI Signature 0x%04X\n", EfiRomHdr.EfiSignature);
+ fprintf (
+ stdout,
+ " Compression Type 0x%04X ",
+ (UINT32) EfiRomHdr.CompressionType
+ );
+ if (EfiRomHdr.CompressionType == EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED) {
+ fprintf (stdout, "(compressed)\n");
+ } else {
+ fprintf (stdout, "(not compressed)\n");
+ }
+
+ fprintf (
+ stdout,
+ " Machine type 0x%04X (%s)\n",
+ EfiRomHdr.EfiMachineType,
+ GetMachineTypeStr (EfiRomHdr.EfiMachineType)
+ );
+ fprintf (
+ stdout,
+ " Subsystem 0x%04X (%s)\n",
+ EfiRomHdr.EfiSubsystem,
+ GetSubsystemTypeStr (EfiRomHdr.EfiSubsystem)
+ );
+ fprintf (
+ stdout,
+ " EFI image offset 0x%04X (@0x%X)\n",
+ (UINT32) EfiRomHdr.EfiImageHeaderOffset,
+ (UINT32) (EfiRomHdr.EfiImageHeaderOffset + ImageStart)
+ );
+
+ } else {
+ //
+ // Not an EFI image
+ //
+ fprintf (stdout, "\n");
+ }
+ //
+ // If code type is EFI image, then dump it as well?
+ //
+ // if (PciDs.CodeType == PCI_CODE_TYPE_EFI_IMAGE) {
+ // }
+ //
+ // If last image, then we're done
+ //
+ if (PciDs.Indicator == INDICATOR_LAST) {
+ goto BailOut;
+ }
+ //
+ // Seek to the start of the next image
+ //
+ if (fseek (InFptr, ImageStart + (PciDs.ImageLength * 512), SEEK_SET)) {
+ fprintf (stdout, "ERROR: Failed to seek to next image\n");
+ goto BailOut;
+ }
+ }
+
+BailOut:
+ fclose (InFptr);
+}
+
+char *
+GetMachineTypeStr (
+ UINT16 MachineType
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ MachineType - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+{
+ int Index;
+
+ for (Index = 0; mMachineTypes[Index].Name != NULL; Index++) {
+ if (mMachineTypes[Index].Value == MachineType) {
+ return mMachineTypes[Index].Name;
+ }
+ }
+
+ return "unknown";
+}
+
+static
+char *
+GetSubsystemTypeStr (
+ UINT16 SubsystemType
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ SubsystemType - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+{
+ int Index;
+
+ for (Index = 0; mSubsystemTypes[Index].Name != NULL; Index++) {
+ if (mSubsystemTypes[Index].Value == SubsystemType) {
+ return mSubsystemTypes[Index].Name;
+ }
+ }
+
+ return "unknown";
+}
diff --git a/Source/EfiRom/build.xml b/Source/EfiRom/build.xml
new file mode 100644
index 0000000..3369eca
--- /dev/null
+++ b/Source/EfiRom/build.xml
@@ -0,0 +1,69 @@
+<?xml version="1.0" ?>
+<!--
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+-->
+<project default="GenTool" basedir=".">
+<!--
+ EDK EfiRom Tool
+ Copyright (c) 2006, Intel Corporation
+-->
+ <property name="ToolName" value="EfiRom"/>
+ <property name="FileSet" value="*.c"/>
+
+ <taskdef resource="net/sf/antcontrib/antlib.xml"/>
+
+ <property name="LINK_OUTPUT_TYPE" value="static"/>
+ <property name="BUILD_DIR" value="${PACKAGE_DIR}/${ToolName}/tmp"/>
+
+ <target name="GenTool" depends="init, Tool">
+ <echo message="The EDK Tool: ${ToolName} build has completed!"/>
+ </target>
+
+ <target name="init">
+ <echo message="Building the EDK Tool: ${ToolName}"/>
+ <mkdir dir="${BUILD_DIR}"/>
+ </target>
+
+ <target name="Tool" depends="init">
+ <cc name="${ToolChain}" objdir="${BUILD_DIR}"
+ outfile="${BIN_DIR}/${ToolName}"
+ outtype="executable"
+ optimize="speed"
+ debug="true">
+ <compilerarg value="${ExtraArgus}" if="ExtraArgus" />
+ <fileset dir="${basedir}/${ToolName}"
+ includes="${FileSet}"
+ defaultexcludes="TRUE"
+ excludes="*.xml *.inf"/>
+
+ <includepath path="${PACKAGE_DIR}/Include"/>
+ <includepath path="${PACKAGE_DIR}/Include/${HostArch}"/>
+ <includepath path="${PACKAGE_DIR}/Common"/>
+ <libset dir="${LIB_DIR}" libs="CommonTools"/>
+ </cc>
+ </target>
+
+ <target name="clean">
+ <echo message="Removing Intermediate Files Only"/>
+ <delete>
+ <fileset dir="${BUILD_DIR}" includes="*.obj"/>
+ </delete>
+ </target>
+
+ <target name="cleanall">
+ <echo message="Removing Object Files and the Executable: ${ToolName}${ext_exe}"/>
+ <delete failonerror="false" quiet="true" includeEmptyDirs="true">
+ <fileset dir="${BUILD_DIR}"/>
+ <fileset file="${BIN_DIR}/${ToolName}${ext_exe}"/>
+ <fileset file="${BIN_DIR}/${ToolName}.pdb"/>
+ </delete>
+ </target>
+
+</project>
diff --git a/Source/FlashMap/FlashDefFile.c b/Source/FlashMap/FlashDefFile.c
new file mode 100644
index 0000000..0bfdad2
--- /dev/null
+++ b/Source/FlashMap/FlashDefFile.c
@@ -0,0 +1,2788 @@
+/*++
+
+Copyright (c) 2004-2006 Intel Corporation. All rights reserved
+This program and the accompanying materials are licensed and made available
+under the terms and conditions of the BSD License which accompanies this
+distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ FlashDefFile.c
+
+Abstract:
+
+ Utility for flash management in the Intel Platform Innovation Framework
+ for EFI build environment.
+
+--*/
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <Common/UefiBaseTypes.h>
+#include <Common/FirmwareVolumeHeader.h>
+#include <Common/MultiPhase.h>
+
+#include "EfiUtilityMsgs.h"
+#include "FlashDefFile.h"
+#include "SimpleFileParsing.h"
+#include "Symbols.h"
+
+//
+// #include "TrackMallocFree.h"
+//
+#define WCHAR_T char
+#define MAX_STRING_LEN 256
+#define MAX_NAME_LEN 128
+#define BUFFER_SIZE 1024
+#define MAX_ATTR_LEN 128
+#define MAX_AREATYPE_LEN 128
+#define COLUMN2_START 60
+#define COLUMN3_START 70
+//
+// Information for each subregions defined in the fdf file will be saved in these
+//
+typedef struct _FLASH_SUBREGION_DESCRIPTION {
+ struct _FLASH_SUBREGION_DESCRIPTION *Next;
+ int CreateHob; // to add to the auto-created HOB array
+ WCHAR_T Name[MAX_NAME_LEN]; // each subregion within a region must have a unique name
+ unsigned int Size; // size, in bytes, of this subregion
+ unsigned int SizeLeft; // used when creating the image
+ WCHAR_T Attributes[MAX_ATTR_LEN]; // subregion attributes used in the output HOB
+ WCHAR_T AreaType[MAX_AREATYPE_LEN]; // subregion area type used in the output HOB
+ EFI_GUID NameGuid; // used in the output HOB
+ WCHAR_T NameGuidString[MAX_NAME_LEN];
+ EFI_GUID AreaTypeGuid; // used in the output HOB
+ WCHAR_T AreaTypeGuidString[MAX_NAME_LEN];
+ EFI_GUID FileSystemGuid; // used in the output HOB
+ WCHAR_T FileSystemGuidString[MAX_NAME_LEN];
+} FLASH_SUBREGION_DESCRIPTION;
+
+//
+// Information for each block in a flash device will be saved in one of these.
+// We'll also use it for region definitions.
+//
+typedef struct _FLASH_BLOCK_DESCRIPTION {
+ struct _FLASH_BLOCK_DESCRIPTION *Next; // next block in the linked list
+ WCHAR_T Name[MAX_NAME_LEN]; // each block must have a unique name
+ unsigned int Size; // size, in bytes, of this block
+ unsigned int SizeLeft; // for use when creating image
+ unsigned int Flags; // user-defined flags for the block
+ unsigned int Alignment; // power of 2 alignment
+ WCHAR_T Attributes[MAX_ATTR_LEN]; // only used for Region definitions
+ WCHAR_T AreaType[MAX_AREATYPE_LEN]; // only used for Region definitions
+ FLASH_SUBREGION_DESCRIPTION *Subregions;
+ FLASH_SUBREGION_DESCRIPTION *LastSubregion;
+} FLASH_BLOCK_DESCRIPTION;
+
+//
+// Information for each flash device will be saved in one of these
+//
+typedef struct _FLASH_DEVICE_DESCRIPTION {
+ struct _FLASH_DEVICE_DESCRIPTION *Next; // next flash device in our linked list
+ int ErasePolarity; // erase polarity of the flash device
+ unsigned int BaseAddress; // base address of the flash device
+ unsigned int Size; // total size, in bytes, of the flash device
+ WCHAR_T Name[MAX_NAME_LEN]; // name of the flash device
+ FLASH_BLOCK_DESCRIPTION *PBlocks; // linked list of physical block descriptors
+ FLASH_BLOCK_DESCRIPTION *LastPBlock; // last block in the linked list
+ FLASH_BLOCK_DESCRIPTION *Regions; // linked list of flash region descriptors
+ FLASH_BLOCK_DESCRIPTION *LastRegion; // last region in the linked list
+} FLASH_DEVICE_DESCRIPTION;
+
+//
+// For image definitions, they can specify a file name or raw data bytes. Keep a linked list.
+//
+typedef struct _IMAGE_DEFINITION_ENTRY {
+ struct _IMAGE_DEFINITION_ENTRY *Next;
+ WCHAR_T RegionName[MAX_NAME_LEN];
+ WCHAR_T SubregionName[MAX_NAME_LEN];
+ WCHAR_T Name[MAX_NAME_LEN]; // file or data name
+ int IsRawData; // non-zero if raw data bytes
+ unsigned int RawDataSize;
+ char *RawData;
+ int Optional; // optional file (don't include if it doesn't exist)
+} IMAGE_DEFINITION_ENTRY;
+
+//
+// When we parse an image definition, save all the data for each in one of these
+//
+typedef struct _IMAGE_DEFINITION {
+ struct _IMAGE_DEFINITION *Next;
+ WCHAR_T Name[MAX_NAME_LEN];
+ IMAGE_DEFINITION_ENTRY *Entries;
+ IMAGE_DEFINITION_ENTRY *LastEntry;
+} IMAGE_DEFINITION;
+
+typedef struct {
+ char *BufferStart;
+ char *BufferEnd;
+ char *BufferPos;
+} BUFFER_DATA;
+
+static const char *CIncludeHeader = "/*++\n\n"
+" DO NOT EDIT -- file auto-generated by FlashMap utility\n\n""--*/\n""\n""#ifndef _FLASH_MAP_H_\n"
+"#define _FLASH_MAP_H_\n\n";
+//
+// "#include \"EfiFlashMap.h\"\n\n";
+//
+static const char *CIncludeFooter = "#endif // #ifndef _FLASH_MAP_H_\n\n";
+
+static const char *CFlashMapDataFileHeader = "/*++\n\n"
+" DO NOT EDIT -- file auto-generated by FlashMap utility\n\n""--*/\n""\n";
+
+static FLASH_DEVICE_DESCRIPTION *mFlashDevices = NULL;
+static IMAGE_DEFINITION *mImageDefinitions = NULL;
+
+//
+// Local function prototypes
+//
+static
+BUFFER_DATA *
+CreateBufferData (
+ VOID
+ );
+
+static
+BOOLEAN
+AddBufferDataByte (
+ BUFFER_DATA *Buffer,
+ char Data
+ );
+
+static
+void
+FreeBufferData (
+ BUFFER_DATA *Buffer,
+ BOOLEAN FreeData
+ );
+
+static
+char *
+GetBufferData (
+ BUFFER_DATA *Buffer,
+ int *BufferSize
+ );
+
+static
+FLASH_SUBREGION_DESCRIPTION *
+ParseSubregionDefinition (
+ unsigned int SizeLeft
+ );
+
+void
+FDFConstructor (
+ VOID
+ )
+/*++
+
+Routine Description:
+ Initialization routine for the services that operate on a flash
+ definition file.
+
+Arguments:
+ None.
+
+Returns:
+ NA
+
+--*/
+{
+ mFlashDevices = NULL;
+ mImageDefinitions = NULL;
+}
+
+void
+FDFDestructor (
+ VOID
+ )
+/*++
+
+Routine Description:
+ Finalization/cleanup routine for the services that operate on a flash
+ definition file.
+
+Arguments:
+ None.
+
+Returns:
+ NA
+
+--*/
+{
+ FLASH_BLOCK_DESCRIPTION *FBNext;
+ FLASH_DEVICE_DESCRIPTION *FDNext;
+ IMAGE_DEFINITION *IDNext;
+ IMAGE_DEFINITION_ENTRY *IDENext;
+ FLASH_SUBREGION_DESCRIPTION *SubNext;
+ //
+ // Go through all our flash devices and free the memory
+ //
+ while (mFlashDevices != NULL) {
+ //
+ // Free the physical block definitions
+ //
+ while (mFlashDevices->PBlocks != NULL) {
+ FBNext = mFlashDevices->PBlocks->Next;
+ _free (mFlashDevices->PBlocks);
+ mFlashDevices->PBlocks = FBNext;
+ }
+ //
+ // Free the region definitions
+ //
+ while (mFlashDevices->Regions != NULL) {
+ FBNext = mFlashDevices->Regions->Next;
+ //
+ // First free the subregion definitions
+ //
+ while (mFlashDevices->Regions->Subregions != NULL) {
+ SubNext = mFlashDevices->Regions->Subregions->Next;
+ _free (mFlashDevices->Regions->Subregions);
+ mFlashDevices->Regions->Subregions = SubNext;
+ }
+
+ _free (mFlashDevices->Regions);
+ mFlashDevices->Regions = FBNext;
+ }
+
+ FDNext = mFlashDevices->Next;
+ _free (mFlashDevices);
+ mFlashDevices = FDNext;
+ }
+ //
+ // Free up the image definitions, and the data
+ //
+ while (mImageDefinitions != NULL) {
+ //
+ // Free the entries
+ //
+ while (mImageDefinitions->Entries != NULL) {
+ IDENext = mImageDefinitions->Entries->Next;
+ if (mImageDefinitions->Entries->RawData != NULL) {
+ _free (mImageDefinitions->Entries->RawData);
+ }
+
+ _free (mImageDefinitions->Entries);
+ mImageDefinitions->Entries = IDENext;
+ }
+
+ IDNext = mImageDefinitions->Next;
+ _free (mImageDefinitions);
+ mImageDefinitions = IDNext;
+ }
+}
+
+STATUS
+FDFParseFile (
+ char *FileName
+ )
+/*++
+
+Routine Description:
+ Parse the specified flash definition file, saving the definitions in
+ file-static variables for use by other functions.
+
+Arguments:
+ FileName - name of the input flash definition text file.
+
+Returns:
+ STATUS_SUCCESS - file parsed with no errors or warnings
+ STATUS_WARNING - warnings, but no errors, were encountered while parsing
+ STATUS_ERROR - errors were encountered while parsing
+
+--*/
+{
+ FILE *Fptr;
+ STATUS Status;
+ unsigned int Num;
+ FLASH_DEVICE_DESCRIPTION *FDDesc;
+ FLASH_BLOCK_DESCRIPTION *FBlockDesc;
+ FLASH_BLOCK_DESCRIPTION *TempBlockDesc;
+ FLASH_SUBREGION_DESCRIPTION *Subregion;
+ FLASH_SUBREGION_DESCRIPTION *TempSubregion;
+ unsigned int BlockSizeLeft;
+ unsigned int RegionSizeLeft;
+ unsigned int SubregionSizeLeft;
+ int ErrorCount;
+ int WarningCount;
+ IMAGE_DEFINITION *ImageDef;
+ IMAGE_DEFINITION_ENTRY *ImageDefEntry;
+ IMAGE_DEFINITION_ENTRY *TempImageDefEntry;
+ BUFFER_DATA *BufferData;
+ char Str[100];
+ BOOLEAN PreviousComma;
+
+ if ((Fptr = fopen (FileName, "r")) == NULL) {
+ Error (NULL, 0, 0, FileName, "failed to open input flash definition file for reading");
+ return STATUS_ERROR;
+ }
+
+ fclose (Fptr);
+ Status = STATUS_SUCCESS;
+ ErrorCount = 0;
+ WarningCount = 0;
+ //
+ // Initialize the simple-file-parsing routines
+ //
+ SFPInit ();
+ //
+ // Open the file
+ //
+ if ((Status = SFPOpenFile (FileName)) != STATUS_SUCCESS) {
+ return Status;
+ }
+ //
+ // Parse the file. Should start with a series of these:
+ // FlashDevice {
+ // Name = "FLASH_1234", Size = 0x2004, BaseAddress = 0xFFF0000, ErasePolarity = 1,
+ // Block { Name = "BLOCK1", Size = 0x1000, Flags = 0x0001 }
+ // Block { Name = "BLOCK2", Size = 0x1004, Flags = 0x0002 }
+ // Region { Name = "REGION_NAME", Size = 0x2004, Align= 4 }
+ // }
+ //
+ while (SFPIsKeyword ("FlashDevice")) {
+ //
+ // Allocate memory for new flash device description block
+ //
+ FDDesc = (FLASH_DEVICE_DESCRIPTION *) _malloc (sizeof (FLASH_DEVICE_DESCRIPTION));
+ if (FDDesc == NULL) {
+ Error (__FILE__, __LINE__, 0, "memory allocation failure", NULL);
+ ErrorCount++;
+ goto Done;
+ }
+
+ memset (FDDesc, 0, sizeof (FLASH_DEVICE_DESCRIPTION));
+ //
+ // Open brace -- warning if not there
+ //
+ if (!SFPIsToken ("{")) {
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected {", NULL);
+ WarningCount++;
+ }
+ //
+ // Parse: Name = "DeviceName",
+ //
+ if (!SFPIsKeyword ("Name")) {
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'Name'", NULL);
+ ErrorCount++;
+ goto Done;
+ }
+
+ if (!SFPIsToken ("=")) {
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);
+ WarningCount++;
+ }
+
+ if (!SFPGetQuotedString (FDDesc->Name, sizeof (FDDesc->Name))) {
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected quoted name of flash device", NULL);
+ ErrorCount++;
+ goto Done;
+ }
+
+ if (!SFPIsToken (",")) {
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected comma following flash device name", NULL);
+ WarningCount++;
+ }
+ //
+ // Parse: Size = 0x20000,
+ //
+ if (!SFPIsKeyword ("Size")) {
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'Size'", NULL);
+ ErrorCount++;
+ goto Done;
+ }
+
+ if (!SFPIsToken ("=")) {
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);
+ WarningCount++;
+ }
+
+ if (!SFPGetNumber (&FDDesc->Size)) {
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected numeric Size value", NULL);
+ ErrorCount++;
+ goto Done;
+ }
+ //
+ // Check for 0 size
+ //
+ if (FDDesc->Size == 0) {
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, FDDesc->Name, "Size field cannot be 0", NULL);
+ ErrorCount++;
+ goto Done;
+ }
+
+ SFPIsToken (",");
+ //
+ // Parse: BaseAddress = 0xFFF0000,
+ //
+ if (!SFPIsKeyword ("BaseAddress")) {
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'BaseAddress'", NULL);
+ ErrorCount++;
+ goto Done;
+ }
+
+ if (!SFPIsToken ("=")) {
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);
+ WarningCount++;
+ }
+
+ if (!SFPGetNumber (&FDDesc->BaseAddress)) {
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected numeric value for BaseAddress", NULL);
+ ErrorCount++;
+ goto Done;
+ }
+
+ if (!SFPIsToken (",")) {
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected comma following BaseAddress value", NULL);
+ WarningCount++;
+ }
+ //
+ // Parse: ErasePolarity = 1,
+ //
+ if (!SFPIsKeyword ("ErasePolarity")) {
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'ErasePolarity'", NULL);
+ ErrorCount++;
+ goto Done;
+ }
+
+ if (!SFPIsToken ("=")) {
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);
+ WarningCount++;
+ }
+
+ if (!SFPGetNumber (&Num) || ((Num != 0) && (Num != 1))) {
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected numeric erase polarity value 1 or 0", NULL);
+ ErrorCount++;
+ goto Done;
+ }
+
+ FDDesc->ErasePolarity = Num;
+ if (!SFPIsToken (",")) {
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected comma following erase polarity value", NULL);
+ WarningCount++;
+ }
+ //
+ // Parse array of:
+ // Block { Name = "BLOCK1", Size = 0x1000, Flags = 0x0001 }
+ //
+ // Keep track of size to make sure the sum of the physical blocks and region sizes do not
+ // exceed the size of the flash device.
+ //
+ BlockSizeLeft = FDDesc->Size;
+ RegionSizeLeft = FDDesc->Size;
+ while (SFPIsKeyword ("Block")) {
+ //
+ // Allocate memory for a new physical block descriptor
+ //
+ FBlockDesc = (FLASH_BLOCK_DESCRIPTION *) _malloc (sizeof (FLASH_BLOCK_DESCRIPTION));
+ if (FBlockDesc == NULL) {
+ Error (__FILE__, __LINE__, 0, "memory allocation failure", NULL);
+ ErrorCount++;
+ goto Done;
+ }
+
+ memset (FBlockDesc, 0, sizeof (FLASH_BLOCK_DESCRIPTION));
+ //
+ // Open brace -- warning if not there
+ //
+ if (!SFPIsToken ("{")) {
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected {", NULL);
+ WarningCount++;
+ }
+ //
+ // Parse: Name = "BlockName",
+ //
+ if (!SFPIsKeyword ("Name")) {
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'Name'", NULL);
+ ErrorCount++;
+ goto Done;
+ }
+
+ if (!SFPIsToken ("=")) {
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);
+ WarningCount++;
+ }
+
+ if (!SFPGetQuotedString (FBlockDesc->Name, sizeof (FBlockDesc->Name))) {
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected quoted name of physical block", NULL);
+ ErrorCount++;
+ goto Done;
+ }
+ //
+ // Make sure there are no other physical block names with this same name
+ //
+ for (TempBlockDesc = FDDesc->PBlocks; TempBlockDesc != NULL; TempBlockDesc = TempBlockDesc->Next) {
+ if (strcmp (TempBlockDesc->Name, FBlockDesc->Name) == 0) {
+ Error (
+ SFPGetFileName (),
+ SFPGetLineNumber (),
+ 0,
+ TempBlockDesc->Name,
+ "physical block with this name already defined"
+ );
+ ErrorCount++;
+ }
+ }
+
+ if (!SFPIsToken (",")) {
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected comma following physical block name", NULL);
+ WarningCount++;
+ }
+ //
+ // Parse: Size = 0x2000,
+ //
+ if (!SFPIsKeyword ("Size")) {
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'Size'", NULL);
+ ErrorCount++;
+ goto Done;
+ }
+
+ if (!SFPIsToken ("=")) {
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);
+ WarningCount++;
+ }
+
+ if (!SFPGetNumber (&FBlockDesc->Size)) {
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected numeric Size value", NULL);
+ ErrorCount++;
+ goto Done;
+ }
+ //
+ // Make sure the sum of physical blocks so far does not exceed flash device size
+ //
+ if (BlockSizeLeft < FBlockDesc->Size) {
+ Error (
+ SFPGetFileName (),
+ SFPGetLineNumber (),
+ 0,
+ "sum of physical block sizes exceeds flash device size",
+ NULL
+ );
+ ErrorCount++;
+ }
+
+ BlockSizeLeft -= FBlockDesc->Size;
+ SFPIsToken (",");
+ //
+ // Optional parse: Flags = 0xFFF0000,
+ //
+ if (SFPIsKeyword ("Flags")) {
+ if (!SFPIsToken ("=")) {
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);
+ WarningCount++;
+ }
+
+ if (!SFPGetNumber (&FBlockDesc->Flags)) {
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected numeric value for Flags", NULL);
+ ErrorCount++;
+ goto Done;
+ }
+ }
+
+ if (!SFPIsToken ("}")) {
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected PhysicalBlock closing brace '}'", NULL);
+ WarningCount++;
+ }
+ //
+ // Add the physical block descriptor to the end of the linked list
+ //
+ if (FDDesc->LastPBlock != NULL) {
+ FDDesc->LastPBlock->Next = FBlockDesc;
+ } else {
+ FDDesc->PBlocks = FBlockDesc;
+ }
+
+ FDDesc->LastPBlock = FBlockDesc;
+ }
+ //
+ // Make sure sum of sizes of physical blocks added up to size of flash device
+ //
+ if (BlockSizeLeft != 0) {
+ Error (
+ SFPGetFileName (),
+ SFPGetLineNumber (),
+ 0,
+ NULL,
+ "sum of sizes of physical blocks (0x%08X) != flash device size (0x%08X) : delta = 0x%08X",
+ FDDesc->Size - BlockSizeLeft,
+ FDDesc->Size,
+ BlockSizeLeft
+ );
+ ErrorCount++;
+ }
+ //
+ // Parse array of:
+ // Region { Name = "REGION_1", Size = 0x2000, Flags = 0x1234, Alignment = 4, Attributes = "str", AreaType = "str" }
+ //
+ while (SFPIsKeyword ("Region")) {
+ //
+ // Allocate memory for a new physical block descriptor
+ //
+ FBlockDesc = (FLASH_BLOCK_DESCRIPTION *) _malloc (sizeof (FLASH_BLOCK_DESCRIPTION));
+ if (FBlockDesc == NULL) {
+ Error (__FILE__, __LINE__, 0, "memory allocation failure", NULL);
+ ErrorCount++;
+ goto Done;
+ }
+
+ memset (FBlockDesc, 0, sizeof (FLASH_BLOCK_DESCRIPTION));
+ //
+ // Open brace -- warning if not there
+ //
+ if (!SFPIsToken ("{")) {
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected {", NULL);
+ WarningCount++;
+ }
+ //
+ // Parse: Name = "BlockName",
+ //
+ if (!SFPIsKeyword ("Name")) {
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'Name'", NULL);
+ ErrorCount++;
+ goto Done;
+ }
+
+ if (!SFPIsToken ("=")) {
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);
+ WarningCount++;
+ }
+
+ if (!SFPGetQuotedString (FBlockDesc->Name, sizeof (FBlockDesc->Name))) {
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected quoted Region name", NULL);
+ ErrorCount++;
+ goto Done;
+ }
+ //
+ // Make sure there are no other region names with this same name
+ //
+ for (TempBlockDesc = FDDesc->Regions; TempBlockDesc != NULL; TempBlockDesc = TempBlockDesc->Next) {
+ if (strcmp (TempBlockDesc->Name, FBlockDesc->Name) == 0) {
+ Error (
+ SFPGetFileName (),
+ SFPGetLineNumber (),
+ 0,
+ TempBlockDesc->Name,
+ "Region with this name already defined"
+ );
+ ErrorCount++;
+ }
+ }
+
+ if (!SFPIsToken (",")) {
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected comma following Region name", NULL);
+ WarningCount++;
+ }
+ //
+ // Parse: Size = 0x2000,
+ //
+ if (!SFPIsKeyword ("Size")) {
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'Size'", NULL);
+ ErrorCount++;
+ goto Done;
+ }
+
+ if (!SFPIsToken ("=")) {
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);
+ WarningCount++;
+ }
+
+ if (!SFPGetNumber (&FBlockDesc->Size)) {
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected numeric Size value", NULL);
+ ErrorCount++;
+ goto Done;
+ }
+
+ if (!SFPIsToken (",")) {
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected ','", NULL);
+ }
+ //
+ // Make sure the sum of regions so far does not exceed flash device size
+ //
+ if (RegionSizeLeft < FBlockDesc->Size) {
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "sum of Region sizes exceeds flash device size", NULL);
+ ErrorCount++;
+ }
+
+ RegionSizeLeft -= FBlockDesc->Size;
+ //
+ // Optional parse: Flags = 0xFFF0000,
+ //
+ if (SFPIsKeyword ("Flags")) {
+ if (!SFPIsToken ("=")) {
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);
+ WarningCount++;
+ }
+
+ if (!SFPGetNumber (&FBlockDesc->Flags)) {
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected numeric value for Flags", NULL);
+ ErrorCount++;
+ goto Done;
+ }
+ //
+ // comma
+ //
+ if (!SFPIsToken (",")) {
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected ','", NULL);
+ }
+ }
+ //
+ // Optional parse: Alignment = 4
+ //
+ if (SFPIsKeyword ("Alignment")) {
+ if (!SFPIsToken ("=")) {
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);
+ WarningCount++;
+ }
+
+ if (!SFPGetNumber (&FBlockDesc->Alignment)) {
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected numeric Alignment value", NULL);
+ ErrorCount++;
+ goto Done;
+ }
+ //
+ // comma
+ //
+ if (!SFPIsToken (",")) {
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected ','", NULL);
+ }
+ }
+ //
+ // Parse: Attributes = "String",
+ //
+ if (!SFPIsKeyword ("Attributes")) {
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'Attributes'", NULL);
+ ErrorCount++;
+ goto Done;
+ }
+
+ if (!SFPIsToken ("=")) {
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);
+ WarningCount++;
+ }
+
+ if (!SFPGetQuotedString (FBlockDesc->Attributes, sizeof (FBlockDesc->Attributes))) {
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected quoted Attributes string", NULL);
+ ErrorCount++;
+ goto Done;
+ }
+
+ if (!SFPIsToken (",")) {
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected ','", NULL);
+ }
+ //
+ // Parse: AreaType = "String",
+ //
+ if (!SFPIsKeyword ("AreaType")) {
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'AreaType'", NULL);
+ ErrorCount++;
+ goto Done;
+ }
+
+ if (!SFPIsToken ("=")) {
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);
+ WarningCount++;
+ }
+
+ if (!SFPGetQuotedString (FBlockDesc->AreaType, sizeof (FBlockDesc->AreaType))) {
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected quoted AreaType string", NULL);
+ ErrorCount++;
+ goto Done;
+ }
+
+ PreviousComma = SFPIsToken (",");
+ //
+ // Parse optional Subregion definitions
+ //
+ SubregionSizeLeft = FBlockDesc->Size;
+ while (SFPIsToken ("Subregion")) {
+ if (!PreviousComma) {
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected ',' before 'Subregion'", NULL);
+ WarningCount++;
+ PreviousComma = TRUE;
+ }
+
+ Subregion = ParseSubregionDefinition (SubregionSizeLeft);
+ if (Subregion == NULL) {
+ ErrorCount++;
+ goto Done;
+ }
+
+ SubregionSizeLeft -= Subregion->Size;
+ //
+ // Add it to the end of our list
+ //
+ if (FBlockDesc->Subregions == NULL) {
+ FBlockDesc->Subregions = Subregion;
+ } else {
+ FBlockDesc->LastSubregion->Next = Subregion;
+ }
+
+ FBlockDesc->LastSubregion = Subregion;
+ //
+ // Make sure all subregion names are unique. We do this each time
+ // through so that we catch the error immediately after it happens, in
+ // which case the reported line number is at least close to where the
+ // problem lies. We don't exit on the error because we can continue parsing
+ // the script to perhaps catch other errors or warnings.
+ //
+ for (Subregion = FBlockDesc->Subregions; Subregion != NULL; Subregion = Subregion->Next) {
+ for (TempSubregion = Subregion->Next; TempSubregion != NULL; TempSubregion = TempSubregion->Next) {
+ if (strcmp (Subregion->Name, TempSubregion->Name) == 0) {
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, Subregion->Name, "duplicate Subregion name");
+ ErrorCount++;
+ }
+ }
+ }
+ }
+
+ if (!SFPIsToken ("}")) {
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected Region closing brace '}'", NULL);
+ WarningCount++;
+ }
+ //
+ // Add the region descriptor to the end of the linked list
+ //
+ if (FDDesc->LastRegion != NULL) {
+ FDDesc->LastRegion->Next = FBlockDesc;
+ } else {
+ FDDesc->Regions = FBlockDesc;
+ }
+
+ FDDesc->LastRegion = FBlockDesc;
+ }
+ //
+ // Make sure sum of sizes of regions adds up to size of flash device
+ //
+ if (RegionSizeLeft != 0) {
+ Error (
+ SFPGetFileName (),
+ SFPGetLineNumber (),
+ 0,
+ NULL,
+ "sum of sizes of Regions (0x%08X) != flash device size (0x%08X) : delta = 0x%08X",
+ FDDesc->Size - RegionSizeLeft,
+ FDDesc->Size,
+ RegionSizeLeft
+ );
+ ErrorCount++;
+ }
+ //
+ // Look for closing brace
+ //
+ if (!SFPIsToken ("}")) {
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected FlashDevice closing brace '}'", NULL);
+ WarningCount++;
+ }
+ //
+ // Add this flash description to the list
+ //
+ FDDesc->Next = mFlashDevices;
+ mFlashDevices = FDDesc;
+ }
+
+ while (SFPIsKeyword ("FlashDeviceImage")) {
+ //
+ // Allocate memory for a new FD image definition
+ //
+ ImageDef = (IMAGE_DEFINITION *) _malloc (sizeof (IMAGE_DEFINITION));
+ if (ImageDef == NULL) {
+ Error (__FILE__, __LINE__, 0, "memory allocation failure", NULL);
+ ErrorCount++;
+ goto Done;
+ }
+
+ memset (ImageDef, 0, sizeof (IMAGE_DEFINITION));
+ //
+ // Open brace -- warning if not there
+ //
+ if (!SFPIsToken ("{")) {
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected {", NULL);
+ WarningCount++;
+ }
+ //
+ // Parse: Name = "ImageName",
+ //
+ if (!SFPIsKeyword ("Name")) {
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'Name'", NULL);
+ ErrorCount++;
+ goto Done;
+ }
+
+ if (!SFPIsToken ("=")) {
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);
+ WarningCount++;
+ }
+
+ if (!SFPGetQuotedString (ImageDef->Name, sizeof (ImageDef->Name))) {
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected quoted name of image", NULL);
+ ErrorCount++;
+ goto Done;
+ }
+
+ if (!SFPIsToken (",")) {
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected comma following image name", NULL);
+ WarningCount++;
+ }
+
+ while (1) {
+ //
+ // Parse: File { Name = "FV\FvOem.fv", Region = "REGION_OEM", Optional = TRUE }
+ //
+ if (SFPIsKeyword ("File")) {
+ ImageDefEntry = (IMAGE_DEFINITION_ENTRY *) _malloc (sizeof (IMAGE_DEFINITION_ENTRY));
+ if (ImageDefEntry == NULL) {
+ Error (__FILE__, __LINE__, 0, "memory allocation failure", NULL);
+ ErrorCount++;
+ goto Done;
+ }
+
+ memset (ImageDefEntry, 0, sizeof (IMAGE_DEFINITION_ENTRY));
+ //
+ // Open brace -- warning if not there
+ //
+ if (!SFPIsToken ("{")) {
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected {", NULL);
+ WarningCount++;
+ }
+ //
+ // Parse: Name = "FileName.txt"
+ //
+ if (!SFPIsKeyword ("Name")) {
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'Name'", NULL);
+ ErrorCount++;
+ goto Done;
+ }
+
+ if (!SFPIsToken ("=")) {
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);
+ WarningCount++;
+ }
+
+ if (!SFPGetQuotedString (ImageDefEntry->Name, sizeof (ImageDefEntry->Name))) {
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected quoted name of file", NULL);
+ ErrorCount++;
+ goto Done;
+ }
+
+ if (!SFPIsToken (",")) {
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected comma following file name", NULL);
+ WarningCount++;
+ }
+ //
+ // Parse: Region = "REGION_NAME"
+ //
+ if (!SFPIsKeyword ("Region")) {
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'Region'", NULL);
+ ErrorCount++;
+ goto Done;
+ }
+
+ if (!SFPIsToken ("=")) {
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);
+ WarningCount++;
+ }
+
+ if (!SFPGetQuotedString (ImageDefEntry->RegionName, sizeof (ImageDefEntry->RegionName))) {
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected quoted Region name", NULL);
+ ErrorCount++;
+ goto Done;
+ }
+
+ if (!SFPIsToken (",")) {
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected comma following Region name", NULL);
+ WarningCount++;
+ }
+ //
+ // Parse optional: Subregion = "SUBREGION_NAME"
+ //
+ if (SFPIsKeyword ("Subregion")) {
+ if (!SFPIsToken ("=")) {
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);
+ WarningCount++;
+ }
+
+ if (!SFPGetQuotedString (ImageDefEntry->SubregionName, sizeof (ImageDefEntry->SubregionName))) {
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected quoted Subegion name", NULL);
+ ErrorCount++;
+ goto Done;
+ }
+
+ if (!SFPIsToken (",")) {
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected comma following Subregion name", NULL);
+ WarningCount++;
+ }
+ //
+ // For a given region, you can only place data using the region name, or the subregion names.
+ // In other words, you can't say File1->Region1 and File2->Region1.Subregion1. Enforce that
+ // here by checking that any previous entries with the same Region name had a Subregion specified
+ // as well.
+ //
+ for (TempImageDefEntry = ImageDef->Entries;
+ TempImageDefEntry != NULL;
+ TempImageDefEntry = TempImageDefEntry->Next
+ ) {
+ if (strcmp (TempImageDefEntry->Name, ImageDefEntry->Name) == 0) {
+ if (TempImageDefEntry->SubregionName[0] == 0) {
+ Error (
+ SFPGetFileName (),
+ SFPGetLineNumber (),
+ 0,
+ TempImageDefEntry->RegionName,
+ "data already placed on a region-basis in the region, can't place data using subregions"
+ );
+ ErrorCount++;
+ }
+ }
+ }
+ }
+ //
+ // Optional parse: Optional = TRUE | FALSE
+ //
+ if (SFPIsKeyword ("Optional")) {
+ if (!SFPIsToken ("=")) {
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);
+ WarningCount++;
+ }
+
+ if (!SFPIsKeyword ("TRUE")) {
+ ImageDefEntry->Optional = 1;
+ } else if (SFPIsKeyword ("FALSE")) {
+ //
+ // Already set to 0
+ //
+ } else {
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'TRUE' or 'FALSE'", NULL);
+ ErrorCount++;
+ goto Done;
+ }
+
+ SFPIsToken (",");
+ }
+ //
+ // Closing brace
+ //
+ if (!SFPIsToken ("}")) {
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '}' closing brace to File entry", NULL);
+ ErrorCount++;
+ goto Done;
+ }
+ //
+ // Add the entry to the end of the list
+ //
+ if (ImageDef->LastEntry != NULL) {
+ ImageDef->LastEntry->Next = ImageDefEntry;
+ } else {
+ ImageDef->Entries = ImageDefEntry;
+ }
+
+ ImageDef->LastEntry = ImageDefEntry;
+ } else if (SFPIsKeyword ("RawData")) {
+ //
+ // Parse: RawData { Name = "PadBytes", Region = "REGION_1", Data = { 0x78, 0x56, 0x34, 0x12 }}
+ //
+ ImageDefEntry = (IMAGE_DEFINITION_ENTRY *) _malloc (sizeof (IMAGE_DEFINITION_ENTRY));
+ if (ImageDefEntry == NULL) {
+ Error (__FILE__, __LINE__, 0, "memory allocation failure", NULL);
+ ErrorCount++;
+ goto Done;
+ }
+
+ memset (ImageDefEntry, 0, sizeof (IMAGE_DEFINITION_ENTRY));
+ ImageDefEntry->IsRawData = 1;
+ //
+ // Open brace -- warning if not there
+ //
+ if (!SFPIsToken ("{")) {
+ Warning (
+ SFPGetFileName (),
+ SFPGetLineNumber (),
+ 0,
+ "expected '{' opening brace for RawData definition",
+ NULL
+ );
+ WarningCount++;
+ }
+ //
+ // Parse: Name = "PadBytes"
+ //
+ if (!SFPIsKeyword ("Name")) {
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'Name'", NULL);
+ ErrorCount++;
+ goto Done;
+ }
+
+ if (!SFPIsToken ("=")) {
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);
+ WarningCount++;
+ }
+
+ if (!SFPGetQuotedString (ImageDefEntry->Name, sizeof (ImageDefEntry->Name))) {
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected quoted name of raw data", NULL);
+ ErrorCount++;
+ goto Done;
+ }
+
+ if (!SFPIsToken (",")) {
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected comma following raw data name", NULL);
+ WarningCount++;
+ }
+ //
+ // Parse: Region = "REGION_NAME"
+ //
+ if (!SFPIsKeyword ("Region")) {
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'Region'", NULL);
+ ErrorCount++;
+ goto Done;
+ }
+
+ if (!SFPIsToken ("=")) {
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);
+ WarningCount++;
+ }
+
+ if (!SFPGetQuotedString (ImageDefEntry->RegionName, sizeof (ImageDefEntry->RegionName))) {
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected quoted Region name", NULL);
+ ErrorCount++;
+ goto Done;
+ }
+
+ if (!SFPIsToken (",")) {
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected comma following Region name", NULL);
+ WarningCount++;
+ }
+ //
+ // Parse optional: Subregion = "SUBREGION_NAME"
+ //
+ if (SFPIsKeyword ("Subregion")) {
+ if (!SFPIsToken ("=")) {
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);
+ WarningCount++;
+ }
+
+ if (!SFPGetQuotedString (ImageDefEntry->SubregionName, sizeof (ImageDefEntry->SubregionName))) {
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected quoted Subegion name", NULL);
+ ErrorCount++;
+ goto Done;
+ }
+
+ if (!SFPIsToken (",")) {
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected comma following Subregion name", NULL);
+ WarningCount++;
+ }
+ //
+ // For a given region, you can only place data using the region name, or the subregion names.
+ // In other words, you can't say File1->Region1 and File2->Region1.Subregion1. Enforce that
+ // here by checking that any previous entries with the same Region name had a Subregion specified
+ // as well.
+ //
+ for (TempImageDefEntry = ImageDef->Entries;
+ TempImageDefEntry != NULL;
+ TempImageDefEntry = TempImageDefEntry->Next
+ ) {
+ if (strcmp (TempImageDefEntry->Name, ImageDefEntry->Name) == 0) {
+ if (TempImageDefEntry->SubregionName[0] == 0) {
+ Error (
+ SFPGetFileName (),
+ SFPGetLineNumber (),
+ 0,
+ TempImageDefEntry->RegionName,
+ "data already placed on a region-basis in the region, can't place data using subregions"
+ );
+ ErrorCount++;
+ }
+ }
+ }
+ }
+ //
+ // Parse: Data = { 0x78, 0x56, 0x34, 0x12 }
+ //
+ if (!SFPIsKeyword ("Data")) {
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'Data'", NULL);
+ ErrorCount++;
+ goto Done;
+ }
+
+ if (!SFPIsToken ("=")) {
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);
+ WarningCount++;
+ }
+
+ if (!SFPIsToken ("{")) {
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '{' preceeding data list", NULL);
+ WarningCount++;
+ }
+
+ if ((BufferData = CreateBufferData ()) == NULL) {
+ ErrorCount++;
+ goto Done;
+ }
+ //
+ // Read bytes from input file until closing brace
+ //
+ while (!SFPIsToken ("}")) {
+ if (!SFPGetNumber (&Num)) {
+ SFPGetNextToken (Str, sizeof (Str));
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, Str, "expected data value", Str);
+ ErrorCount++;
+ FreeBufferData (BufferData, TRUE);
+ goto Done;
+ } else {
+ //
+ // Only allow bytes
+ //
+ if (Num > 0xFF) {
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "only values 0-255 (0x00-0xFF) allowed", NULL);
+ ErrorCount++;
+ FreeBufferData (BufferData, TRUE);
+ goto Done;
+ }
+
+ AddBufferDataByte (BufferData, (char) Num);
+ SFPIsToken (",");
+ }
+ }
+ //
+ // Now get the data and save it in our image entry
+ //
+ ImageDefEntry->RawData = GetBufferData (BufferData, &ImageDefEntry->RawDataSize);
+ FreeBufferData (BufferData, 0);
+ //
+ // Closing brace for RawData {}
+ //
+ if (!SFPIsToken ("}")) {
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '}' closing brace for RawData", NULL);
+ ErrorCount++;
+ goto Done;
+ }
+ //
+ // Add the entry to the end of the list
+ //
+ if (ImageDef->LastEntry != NULL) {
+ ImageDef->LastEntry->Next = ImageDefEntry;
+ } else {
+ ImageDef->Entries = ImageDefEntry;
+ }
+
+ ImageDef->LastEntry = ImageDefEntry;
+ } else if (SFPIsToken ("}")) {
+ //
+ // Closing brace for FDImage {}
+ //
+ break;
+ } else {
+ SFPGetNextToken (Str, sizeof (Str));
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, Str, "unrecognized token", Str);
+ ErrorCount++;
+ goto Done;
+ }
+ }
+ //
+ // Add this image definition to our global list
+ //
+ ImageDef->Next = mImageDefinitions;
+ mImageDefinitions = ImageDef;
+ }
+ //
+ // Check for end-of-file
+ //
+ if (!SFPIsEOF ()) {
+ SFPGetNextToken (Str, sizeof (Str));
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, Str, "expected end-of-file", Str);
+ ErrorCount++;
+ }
+
+Done:
+ SFPCloseFile ();
+ if (ErrorCount != 0) {
+ return STATUS_ERROR;
+ } else if (WarningCount != 0) {
+ return STATUS_WARNING;
+ }
+
+ return STATUS_SUCCESS;
+}
+
+static
+FLASH_SUBREGION_DESCRIPTION *
+ParseSubregionDefinition (
+ unsigned int SizeLeft
+ )
+/*++
+
+Routine Description:
+
+ Parse Subregion definitions from the input flash definition file. Format:
+
+ Subregion {
+ CreateHob = TRUE,
+ Name = "FOO",
+ Size = 0xA000,
+ Attributes = "EFI_FLASH_AREA_SUBFV | EFI_FLASH_AREA_MEMMAPPED_FV",
+ AreaType = "EFI_FLASH_AREA_EFI_VARIABLES",
+ NameGuid = 12345678-1234-5678-AAAA-BBBBCCCCDDDD (or "EFI_SOME_GUID"),
+ AreaTypeGuid = 11111111-2222-3333-4444-1, (or "EFI_SOME_GUID") (optional)
+ FileSystemGuid = 11111111-2222-3333-4444-1, (or "EFI_SOME_GUID") (optional)
+ }
+
+ NOTE: The caller has already parsed the "Subregion" token, so start with the opening brace.
+
+Arguments:
+
+ SizeLeft - in the flash definition file, a Region can be broken up into
+ one or more subregions. As we parse the subregion definitions,
+ the caller keeps track of how much space is left in the region
+ that we're parsing subregions for. SizeLeft is that size, and
+ so the size of the subregion we're now parsing better not
+ exceed the size left.
+ Returns:
+
+ NULL - unrecoverable errors detected while parsing the subregion definition
+
+ pointer to a subregion definition created from the parsed subregion
+
+--*/
+{
+ FLASH_SUBREGION_DESCRIPTION *Subregion;
+ int ErrorCount;
+ int WarningCount;
+ unsigned int Number;
+ BOOLEAN PreviousComma;
+ //
+ // Allocate memory for the new subregion descriptor
+ //
+ ErrorCount = 0;
+ WarningCount = 0;
+ Subregion = (FLASH_SUBREGION_DESCRIPTION *) _malloc (sizeof (FLASH_SUBREGION_DESCRIPTION));
+ if (Subregion == NULL) {
+ Error (__FILE__, __LINE__, 0, "memory allocation failure", NULL);
+ ErrorCount++;
+ goto Done;
+ }
+
+ memset (Subregion, 0, sizeof (FLASH_SUBREGION_DESCRIPTION));
+ //
+ // Open brace -- warning if not there
+ //
+ if (!SFPIsToken ("{")) {
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected {", NULL);
+ WarningCount++;
+ }
+ //
+ // Parse: CreateHob = TRUE | FALSE,
+ //
+ if (!SFPIsKeyword ("CreateHob")) {
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'CreateHob'", NULL);
+ ErrorCount++;
+ goto Done;
+ }
+
+ if (!SFPIsToken ("=")) {
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);
+ WarningCount++;
+ }
+
+ if (SFPIsToken ("TRUE")) {
+ Subregion->CreateHob = 1;
+ } else if (SFPIsToken ("FALSE")) {
+ //
+ // Subregion->CreateHob = 0; -- not required since we did a memset earlier
+ //
+ } else {
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'TRUE' or 'FALSE'", NULL);
+ ErrorCount++;
+ goto Done;
+ }
+
+ if (!SFPIsToken (",")) {
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected ',' following CreateHob value", NULL);
+ WarningCount++;
+ }
+ //
+ // Parse: Name = "Name",
+ //
+ if (!SFPIsKeyword ("Name")) {
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'Name'", NULL);
+ ErrorCount++;
+ goto Done;
+ }
+
+ if (!SFPIsToken ("=")) {
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);
+ WarningCount++;
+ }
+
+ if (!SFPGetQuotedString (Subregion->Name, sizeof (Subregion->Name))) {
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected Subregion name", NULL);
+ ErrorCount++;
+ goto Done;
+ }
+
+ if (!SFPIsToken (",")) {
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected comma following Region name", NULL);
+ WarningCount++;
+ }
+ //
+ // Parse: Size = 0x2000,
+ //
+ if (!SFPIsKeyword ("Size")) {
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'Size'", NULL);
+ ErrorCount++;
+ goto Done;
+ }
+
+ if (!SFPIsToken ("=")) {
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);
+ WarningCount++;
+ }
+
+ if (!SFPGetNumber (&Subregion->Size)) {
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected numeric Size value", NULL);
+ ErrorCount++;
+ goto Done;
+ }
+
+ //
+ // Check that the size does not exceed the size left passed in
+ //
+ if (Subregion->Size > SizeLeft) {
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "sum of Subregion sizes exceeds Region size", NULL);
+ ErrorCount++;
+ goto Done;
+ }
+
+ if (!SFPIsToken (",")) {
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected ',' following Size value", NULL);
+ }
+ //
+ // Parse: Attributes = Number | "String",
+ //
+ if (!SFPIsKeyword ("Attributes")) {
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'Attributes'", NULL);
+ ErrorCount++;
+ goto Done;
+ }
+
+ if (!SFPIsToken ("=")) {
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);
+ WarningCount++;
+ }
+
+ if (SFPGetNumber (&Number)) {
+ sprintf (Subregion->Attributes, "0x%X", Number);
+ } else if (!SFPGetQuotedString (Subregion->Attributes, sizeof (Subregion->Attributes))) {
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected quoted Attributes string", NULL);
+ ErrorCount++;
+ goto Done;
+ }
+
+ if (!SFPIsToken (",")) {
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected ','", NULL);
+ }
+ //
+ // Parse: AreaType = Number | "String",
+ // AreaType is a UINT8, so error if it exceeds the size
+ //
+ if (!SFPIsKeyword ("AreaType")) {
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'AreaType'", NULL);
+ ErrorCount++;
+ goto Done;
+ }
+
+ if (!SFPIsToken ("=")) {
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);
+ WarningCount++;
+ }
+
+ if (SFPGetNumber (&Number)) {
+ if (Number > 0xFF) {
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "AreaType value exceeds 255", NULL);
+ ErrorCount++;
+ }
+
+ sprintf (Subregion->AreaType, "0x%X", Number & 0x00FF);
+ } else if (!SFPGetQuotedString (Subregion->AreaType, sizeof (Subregion->AreaType))) {
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected quoted AreaType string", NULL);
+ ErrorCount++;
+ goto Done;
+ }
+
+ if (!SFPIsToken (",")) {
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected ',' following AreaType value", NULL);
+ }
+ //
+ // Parse the three GUIDs (last two are optional)
+ //
+ // NameGuid = 12345678-1234-5678-AAAA-BBBBCCCCDDDD, (or "EFI_SOME_GUID")
+ // AreaTypeGuid = 11111111-2222-3333-4444-1, (or "EFI_SOME_GUID")
+ // FileSysteGuid = 11111111-2222-3333-4444-1, (or "EFI_SOME_GUID")
+ //
+ if (!SFPIsKeyword ("NameGuid")) {
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'NameGuid'", NULL);
+ ErrorCount++;
+ goto Done;
+ }
+
+ if (!SFPIsToken ("=")) {
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);
+ WarningCount++;
+ }
+ //
+ // Allow a GUID or a quoted string identifier, which we'll just copy as a string
+ //
+ if (SFPGetQuotedString (Subregion->NameGuidString, sizeof (Subregion->NameGuidString))) {
+ //
+ // Nothing else to do
+ //
+ } else if (!SFPGetGuid (PARSE_GUID_STYLE_5_FIELDS, &Subregion->NameGuid)) {
+ Error (
+ SFPGetFileName (),
+ SFPGetLineNumber (),
+ 0,
+ "expected NameGuid quoted string or GUID of form 12345678-1234-1234-1234-123456789ABC",
+ NULL
+ );
+ ErrorCount++;
+ goto Done;
+ }
+ //
+ // Comma following NameGuid is optional if they don't specify AreaTypeGuid or FileSystemGuid
+ //
+ PreviousComma = SFPIsToken (",");
+ if (SFPIsKeyword ("AreaTypeGuid")) {
+ //
+ // Check for preceeding comma now
+ //
+ if (!PreviousComma) {
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected ',' before 'AreaTypeGuid'", NULL);
+ WarningCount++;
+ }
+
+ if (!SFPIsToken ("=")) {
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);
+ WarningCount++;
+ }
+
+ if (SFPGetQuotedString (Subregion->AreaTypeGuidString, sizeof (Subregion->AreaTypeGuidString))) {
+ //
+ // Nothing else to do
+ //
+ } else if (!SFPGetGuid (PARSE_GUID_STYLE_5_FIELDS, &Subregion->AreaTypeGuid)) {
+ Error (
+ SFPGetFileName (),
+ SFPGetLineNumber (),
+ 0,
+ "expected AreaTypeGuid quoted string or GUID of form 12345678-1234-1234-1234-123456789ABC",
+ NULL
+ );
+ ErrorCount++;
+ goto Done;
+ }
+
+ PreviousComma = SFPIsToken (",");
+ }
+
+ if (SFPIsKeyword ("FileSystemGuid")) {
+ //
+ // Check for preceeding comma now
+ //
+ if (!PreviousComma) {
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected ',' before 'FileSystemGuid'", NULL);
+ WarningCount++;
+ }
+
+ if (!SFPIsToken ("=")) {
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);
+ WarningCount++;
+ }
+ //
+ // Allow a GUID or a quoted string identifier, which we'll just copy as a string
+ //
+ if (SFPGetQuotedString (Subregion->FileSystemGuidString, sizeof (Subregion->FileSystemGuidString))) {
+ //
+ // Nothing else to do
+ //
+ } else if (!SFPGetGuid (PARSE_GUID_STYLE_5_FIELDS, &Subregion->FileSystemGuid)) {
+ Error (
+ SFPGetFileName (),
+ SFPGetLineNumber (),
+ 0,
+ "expected FileSystemGuid quoted string or GUID of form 12345678-1234-1234-1234-123456789ABC",
+ NULL
+ );
+ ErrorCount++;
+ goto Done;
+ }
+
+ SFPIsToken (",");
+ }
+ //
+ // Look for subregion closing brace
+ //
+ if (!SFPIsToken ("}")) {
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected Subregion closing brace '}'", NULL);
+ WarningCount++;
+ }
+
+Done:
+ //
+ // If any errors were encountered, then delete the subregion definition
+ //
+ if (ErrorCount != 0) {
+ _free (Subregion);
+ Subregion = NULL;
+ }
+
+ return Subregion;
+}
+
+STATUS
+FDFCreateCIncludeFile (
+ char *FlashDeviceName,
+ char *FileName
+ )
+/*++
+
+Routine Description:
+ Create a header file with #define definitions per an already-parsed
+ flash definition file.
+
+Arguments:
+ FlashDeviceName - name of flash device (from the flash definition file)
+ to use
+ FileName - name of output file to create
+
+Returns:
+ STATUS_SUCCESS - no errors or warnings
+ STATUS_WARNING - warnings, but no errors, were encountered
+ STATUS_ERROR - errors were encountered
+
+--*/
+{
+ FILE *OutFptr;
+ FLASH_BLOCK_DESCRIPTION *FBlock;
+ FLASH_DEVICE_DESCRIPTION *FDev;
+ FLASH_SUBREGION_DESCRIPTION *Subregion;
+ unsigned int Offset;
+ unsigned int SubregionOffset;
+ int CreateHobs;
+ //
+ // Find the definition we're supposed to use
+ //
+ for (FDev = mFlashDevices; FDev != NULL; FDev = FDev->Next) {
+ if (strcmp (FDev->Name, FlashDeviceName) == 0) {
+ break;
+ }
+ }
+
+ if (FDev == NULL) {
+ Error (NULL, 0, 0, NULL, FlashDeviceName, "flash device not found in flash definitions");
+ return STATUS_ERROR;
+ }
+
+ if ((OutFptr = fopen (FileName, "w")) == NULL) {
+ Error (NULL, 0, 0, FileName, "failed to open output file for writing");
+ return STATUS_ERROR;
+ }
+ //
+ // Write a header
+ //
+ fprintf (OutFptr, CIncludeHeader);
+ //
+ // Write flash block base and size defines
+ //
+ fprintf (OutFptr, "#define FLASH_BASE 0x%08X\n", FDev->BaseAddress);
+ fprintf (OutFptr, "#define FLASH_SIZE 0x%08X\n\n", FDev->Size);
+ //
+ // Write flash regions base, size and offset defines
+ //
+ Offset = 0;
+ CreateHobs = 0;
+ for (FBlock = FDev->Regions; FBlock != NULL; FBlock = FBlock->Next) {
+ fprintf (
+ OutFptr,
+ "#define FLASH_REGION_%s_BASE %*c0x%08X\n",
+ FBlock->Name,
+ COLUMN2_START - 40 - strlen (FBlock->Name),
+ ' ',
+ Offset + FDev->BaseAddress
+ );
+ fprintf (
+ OutFptr,
+ "#define FLASH_REGION_%s_SIZE %*c0x%08X\n",
+ FBlock->Name,
+ COLUMN2_START - 40 - strlen (FBlock->Name),
+ ' ',
+ FBlock->Size
+ );
+ fprintf (
+ OutFptr,
+ "#define FLASH_REGION_%s_OFFSET %*c0x%08X\n",
+ FBlock->Name,
+ COLUMN2_START - 40 - strlen (FBlock->Name),
+ ' ',
+ Offset
+ );
+ //
+ // Create defines for any subregions
+ //
+ SubregionOffset = 0;
+ for (Subregion = FBlock->Subregions; Subregion != NULL; Subregion = Subregion->Next) {
+ fprintf (
+ OutFptr,
+ "#define FLASH_REGION_%s_SUBREGION_%s_BASE %*c0x%08X\n",
+ FBlock->Name,
+ Subregion->Name,
+ COLUMN3_START - 43 - strlen (FBlock->Name) - strlen (Subregion->Name),
+ ' ',
+ FDev->BaseAddress + Offset + SubregionOffset
+ );
+ fprintf (
+ OutFptr,
+ "#define FLASH_REGION_%s_SUBREGION_%s_SIZE %*c0x%08X\n",
+ FBlock->Name,
+ Subregion->Name,
+ COLUMN3_START - 43 - strlen (FBlock->Name) - strlen (Subregion->Name),
+ ' ',
+ Subregion->Size
+ );
+ fprintf (
+ OutFptr,
+ "#define FLASH_REGION_%s_SUBREGION_%s_OFFSET %*c0x%08X\n",
+ FBlock->Name,
+ Subregion->Name,
+ COLUMN3_START - 43 - strlen (FBlock->Name) - strlen (Subregion->Name),
+ ' ',
+ Offset + SubregionOffset
+ );
+ SubregionOffset += Subregion->Size;
+ if (Subregion->CreateHob != 0) {
+ CreateHobs = 1;
+ }
+ }
+
+ Offset += FBlock->Size;
+ }
+ //
+ // Now create a #define for the flash map data definition
+ //
+ fprintf (OutFptr, "\n\n#define EFI_FLASH_AREA_DATA_DEFINITION \\\n");
+ //
+ // Emit entry for each region
+ //
+ Offset = 0;
+ for (FBlock = FDev->Regions; FBlock != NULL; FBlock = FBlock->Next) {
+ fprintf (OutFptr, " /* %s region */\\\n", FBlock->Name);
+ fprintf (OutFptr, " {\\\n");
+ fprintf (OutFptr, " FLASH_REGION_%s_BASE,\\\n", FBlock->Name);
+ fprintf (OutFptr, " FLASH_REGION_%s_SIZE,\\\n", FBlock->Name);
+ fprintf (OutFptr, " %s,\\\n", FBlock->Attributes);
+ fprintf (OutFptr, " %s,\\\n },\\\n", FBlock->AreaType);
+ }
+
+ fprintf (OutFptr, "\n\n");
+ //
+ // Now walk the list again to create the EFI_HOB_FLASH_MAP_ENTRY_TYPE definition
+ //
+ if (CreateHobs != 0) {
+ fprintf (OutFptr, "//\n// EFI_HOB_FLASH_MAP_ENTRY_TYPE definition\n//\n");
+ fprintf (OutFptr, "#define EFI_HOB_FLASH_MAP_ENTRY_TYPE_DATA_DEFINITION");
+ for (FBlock = FDev->Regions; FBlock != NULL; FBlock = FBlock->Next) {
+ //
+ // See if the block has subregions, and that the CreateHobs flag is set
+ // for any of them.
+ //
+ CreateHobs = 0;
+ for (Subregion = FBlock->Subregions; Subregion != NULL; Subregion = Subregion->Next) {
+ if (Subregion->CreateHob != 0) {
+ CreateHobs = 1;
+ break;
+ }
+ }
+ //
+ // If any of the subregions had the CreateHobs flag set, then create the entries in the
+ // output file
+ //
+ if (CreateHobs != 0) {
+ for (Subregion = FBlock->Subregions; Subregion != NULL; Subregion = Subregion->Next) {
+ if (Subregion->CreateHob != 0) {
+ fprintf (OutFptr, " \\\n");
+ fprintf (OutFptr, " /* %s.%s Subregion */\\\n", FBlock->Name, Subregion->Name);
+ fprintf (OutFptr, " {\\\n");
+ fprintf (OutFptr, " {EFI_HOB_TYPE_GUID_EXTENSION,\\\n");
+ fprintf (OutFptr, " sizeof (EFI_HOB_FLASH_MAP_ENTRY_TYPE ),\\\n");
+ fprintf (OutFptr, " 0},\\\n");
+ //
+ // The NameGuid may have been specified in the input flash definition file as a GUID, or
+ // as a quoted string. Do the right one.
+ //
+ if (Subregion->NameGuidString[0] != 0) {
+ fprintf (OutFptr, " %s, \\\n", Subregion->NameGuidString);
+ } else {
+ fprintf (
+ OutFptr,
+ " { 0x%08X, 0x%04X, 0x%04X, {0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X}},\\\n",
+ Subregion->NameGuid.Data1,
+ (unsigned int) Subregion->NameGuid.Data2,
+ (unsigned int) Subregion->NameGuid.Data3,
+ (unsigned int) Subregion->NameGuid.Data4[0],
+ (unsigned int) Subregion->NameGuid.Data4[1],
+ (unsigned int) Subregion->NameGuid.Data4[2],
+ (unsigned int) Subregion->NameGuid.Data4[3],
+ (unsigned int) Subregion->NameGuid.Data4[4],
+ (unsigned int) Subregion->NameGuid.Data4[5],
+ (unsigned int) Subregion->NameGuid.Data4[6],
+ (unsigned int) Subregion->NameGuid.Data4[7]
+ );
+ }
+
+ fprintf (OutFptr, " {0, 0, 0},\\\n");
+ fprintf (OutFptr, " %s,\\\n", Subregion->AreaType);
+ //
+ // The AreaTypeGuid may have been specified in the input flash definition file as a GUID, or
+ // as a quoted string. Do the right one.
+ //
+ if (Subregion->AreaTypeGuidString[0] != 0) {
+ fprintf (OutFptr, " %s, \\\n", Subregion->AreaTypeGuidString);
+ } else {
+ fprintf (
+ OutFptr,
+ " { 0x%08X, 0x%04X, 0x%04X, {0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X}},\\\n",
+ Subregion->AreaTypeGuid.Data1,
+ (unsigned int) Subregion->AreaTypeGuid.Data2,
+ (unsigned int) Subregion->AreaTypeGuid.Data3,
+ (unsigned int) Subregion->AreaTypeGuid.Data4[0],
+ (unsigned int) Subregion->AreaTypeGuid.Data4[1],
+ (unsigned int) Subregion->AreaTypeGuid.Data4[2],
+ (unsigned int) Subregion->AreaTypeGuid.Data4[3],
+ (unsigned int) Subregion->AreaTypeGuid.Data4[4],
+ (unsigned int) Subregion->AreaTypeGuid.Data4[5],
+ (unsigned int) Subregion->AreaTypeGuid.Data4[6],
+ (unsigned int) Subregion->AreaTypeGuid.Data4[7]
+ );
+ }
+
+ fprintf (OutFptr, " 1,\\\n");
+ fprintf (OutFptr, " {{\\\n");
+ fprintf (OutFptr, " %s,\\\n", Subregion->Attributes);
+ fprintf (OutFptr, " 0,\\\n");
+ fprintf (OutFptr, " FLASH_REGION_%s_SUBREGION_%s_BASE,\\\n", FBlock->Name, Subregion->Name);
+ fprintf (OutFptr, " FLASH_REGION_%s_SUBREGION_%s_SIZE,\\\n", FBlock->Name, Subregion->Name);
+ //
+ // The FileSystemGuid may have been specified in the input flash definition file as a GUID, or
+ // as a quoted string. Do the right one.
+ //
+ if (Subregion->FileSystemGuidString[0] != 0) {
+ fprintf (OutFptr, " %s, \\\n", Subregion->FileSystemGuidString);
+ } else {
+ fprintf (
+ OutFptr,
+ " { 0x%08X, 0x%04X, 0x%04X, {0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X}},\\\n",
+ Subregion->FileSystemGuid.Data1,
+ (unsigned int) Subregion->FileSystemGuid.Data2,
+ (unsigned int) Subregion->FileSystemGuid.Data3,
+ (unsigned int) Subregion->FileSystemGuid.Data4[0],
+ (unsigned int) Subregion->FileSystemGuid.Data4[1],
+ (unsigned int) Subregion->FileSystemGuid.Data4[2],
+ (unsigned int) Subregion->FileSystemGuid.Data4[3],
+ (unsigned int) Subregion->FileSystemGuid.Data4[4],
+ (unsigned int) Subregion->FileSystemGuid.Data4[5],
+ (unsigned int) Subregion->FileSystemGuid.Data4[6],
+ (unsigned int) Subregion->FileSystemGuid.Data4[7]
+ );
+ }
+
+ fprintf (OutFptr, " }},\\\n");
+ fprintf (OutFptr, " },");
+ }
+ }
+ }
+ }
+
+ fprintf (OutFptr, "\n\n");
+ }
+
+ //
+ // Write the file's closing #endif
+ //
+ fprintf (OutFptr, CIncludeFooter);
+ fclose (OutFptr);
+ return STATUS_SUCCESS;
+}
+
+STATUS
+FDFCreateAsmIncludeFile (
+ char *FlashDeviceName,
+ char *FileName
+ )
+/*++
+
+Routine Description:
+ Create an assembly header file with equate definitions per an already-parsed
+ flash definition file.
+
+Arguments:
+ FlashDeviceName - name of flash device (from the flash definition file)
+ to use
+ FileName - name of output file to create
+
+Returns:
+ STATUS_SUCCESS - no errors or warnings
+ STATUS_WARNING - warnings, but no errors, were encountered
+ STATUS_ERROR - errors were encountered
+
+--*/
+{
+ FILE *OutFptr;
+ FLASH_BLOCK_DESCRIPTION *FBlock;
+ FLASH_DEVICE_DESCRIPTION *FDev;
+ unsigned int Offset;
+ FLASH_SUBREGION_DESCRIPTION *Subregion;
+ unsigned int SubregionOffset;
+ //
+ // Find the definition we're supposed to use
+ //
+ for (FDev = mFlashDevices; FDev != NULL; FDev = FDev->Next) {
+ if (strcmp (FDev->Name, FlashDeviceName) == 0) {
+ break;
+ }
+ }
+
+ if (FDev == NULL) {
+ Error (NULL, 0, 0, NULL, FlashDeviceName, "flash device not found in flash definitions");
+ return STATUS_ERROR;
+ }
+
+ if ((OutFptr = fopen (FileName, "w")) == NULL) {
+ Error (NULL, 0, 0, FileName, "failed to open output file for writing");
+ return STATUS_ERROR;
+ }
+ //
+ // Write a header
+ //
+ fprintf (OutFptr, "\n\n");
+ //
+ // Write flash block size and offset defines
+ //
+ fprintf (
+ OutFptr,
+ "FLASH_BASE %*cequ 0%08Xh\n",
+ COLUMN2_START - 40,
+ ' ',
+ FDev->BaseAddress
+ );
+ fprintf (OutFptr, "FLASH_SIZE %*cequ 0%08Xh\n", COLUMN2_START - 40, ' ', FDev->Size);
+ //
+ // Write flash region size and offset defines
+ //
+ fprintf (OutFptr, "\n");
+ Offset = 0;
+ for (FBlock = FDev->Regions; FBlock != NULL; FBlock = FBlock->Next) {
+ fprintf (
+ OutFptr,
+ "FLASH_REGION_%s_BASE %*cequ 0%08Xh\n",
+ FBlock->Name,
+ COLUMN2_START - 20 - strlen (FBlock->Name),
+ ' ',
+ FDev->BaseAddress + Offset
+ );
+ fprintf (
+ OutFptr,
+ "FLASH_REGION_%s_SIZE %*cequ 0%08Xh\n",
+ FBlock->Name,
+ COLUMN2_START - 20 - strlen (FBlock->Name),
+ ' ',
+ FBlock->Size
+ );
+ fprintf (
+ OutFptr,
+ "FLASH_REGION_%s_OFFSET %*cequ 0%08Xh\n",
+ FBlock->Name,
+ COLUMN2_START - 20 - strlen (FBlock->Name),
+ ' ',
+ Offset
+ );
+ //
+ // Create defines for any subregions
+ //
+ SubregionOffset = 0;
+ for (Subregion = FBlock->Subregions; Subregion != NULL; Subregion = Subregion->Next) {
+ fprintf (
+ OutFptr,
+ "FLASH_REGION_%s_SUBREGION_%s_BASE %*cequ 0%08Xh\n",
+ FBlock->Name,
+ Subregion->Name,
+ COLUMN3_START - 39 - strlen (FBlock->Name) - strlen (Subregion->Name),
+ ' ',
+ FDev->BaseAddress + Offset + SubregionOffset
+ );
+ fprintf (
+ OutFptr,
+ "FLASH_REGION_%s_SUBREGION_%s_SIZE %*cequ 0%08Xh\n",
+ FBlock->Name,
+ Subregion->Name,
+ COLUMN3_START - 39 - strlen (FBlock->Name) - strlen (Subregion->Name),
+ ' ',
+ Subregion->Size
+ );
+ fprintf (
+ OutFptr,
+ "FLASH_REGION_%s_SUBREGION_%s_OFFSET %*cequ 0%08Xh\n",
+ FBlock->Name,
+ Subregion->Name,
+ COLUMN3_START - 39 - strlen (FBlock->Name) - strlen (Subregion->Name),
+ ' ',
+ Offset + SubregionOffset
+ );
+ SubregionOffset += Subregion->Size;
+ }
+
+ Offset += FBlock->Size;
+ }
+
+ //
+ // Write closing \n
+ //
+ fprintf (OutFptr, "\n\n");
+ fclose (OutFptr);
+ return STATUS_SUCCESS;
+}
+
+STATUS
+FDFCreateSymbols (
+ char *FlashDeviceName
+ )
+/*++
+
+Routine Description:
+ Using the given flash device name, add symbols to the global symbol table. This
+ allows other functions to use the symbol definitions for other purposes.
+
+Arguments:
+ FlashDeviceName - name of flash device (from the flash definition file)
+ to use
+
+Returns:
+ STATUS_SUCCESS - no errors or warnings
+ STATUS_WARNING - warnings, but no errors, were encountered
+ STATUS_ERROR - errors were encountered
+
+--*/
+{
+ FLASH_BLOCK_DESCRIPTION *FBlock;
+ FLASH_DEVICE_DESCRIPTION *FDev;
+ unsigned int Offset;
+ char SymName[120];
+ char SymValue[120];
+ FLASH_SUBREGION_DESCRIPTION *Subregion;
+ unsigned int SubregionOffset;
+ //
+ // Find the definition we're supposed to use
+ //
+ for (FDev = mFlashDevices; FDev != NULL; FDev = FDev->Next) {
+ if (strcmp (FDev->Name, FlashDeviceName) == 0) {
+ break;
+ }
+ }
+
+ if (FDev == NULL) {
+ Error (NULL, 0, 0, NULL, FlashDeviceName, "flash device not found in flash definitions");
+ return STATUS_ERROR;
+ }
+
+ sprintf (SymValue, "0x%08X", FDev->BaseAddress);
+ SymbolAdd ("FLASH_BASE", SymValue, 0);
+ sprintf (SymValue, "0x%08X", FDev->Size);
+ SymbolAdd ("FLASH_SIZE", SymValue, 0);
+ //
+ // Add flash block size and offset defines
+ //
+ // Offset = 0;
+ // for (FBlock = FDev->PBlocks; FBlock != NULL; FBlock = FBlock->Next) {
+ // sprintf (SymName, "FLASH_BLOCK_%s_BASE", FBlock->Name);
+ // sprintf (SymValue, "0x%08X", FDev->BaseAddress + Offset);
+ // SymbolAdd (SymName, SymValue, 0);
+ // sprintf (SymName, "FLASH_BLOCK_%s_SIZE", FBlock->Name);
+ // sprintf (SymValue, "0x%08X", FBlock->Size);
+ // SymbolAdd (SymName, SymValue, 0);
+ // sprintf (SymName, "FLASH_BLOCK_%s_OFFSET", FBlock->Name);
+ // sprintf (SymValue, "0x%08X", Offset);
+ // SymbolAdd (SymName, SymValue, 0);
+ // Offset += FBlock->Size;
+ // }
+ //
+ // Add flash region block base, size, and offset defines
+ //
+ Offset = 0;
+ for (FBlock = FDev->Regions; FBlock != NULL; FBlock = FBlock->Next) {
+ sprintf (SymName, "FLASH_REGION_%s_BASE", FBlock->Name);
+ sprintf (SymValue, "0x%08X", FDev->BaseAddress + Offset);
+ SymbolAdd (SymName, SymValue, 0);
+ sprintf (SymName, "FLASH_REGION_%s_SIZE", FBlock->Name);
+ sprintf (SymValue, "0x%08X", FBlock->Size);
+ SymbolAdd (SymName, SymValue, 0);
+ sprintf (SymName, "FLASH_REGION_%s_OFFSET", FBlock->Name);
+ sprintf (SymValue, "0x%08X", Offset);
+ SymbolAdd (SymName, SymValue, 0);
+ //
+ // Add subregion symbols
+ //
+ if (FBlock->Subregions != NULL) {
+ SubregionOffset = 0;
+ for (Subregion = FBlock->Subregions; Subregion != NULL; Subregion = Subregion->Next) {
+ sprintf (SymName, "FLASH_REGION_%s_SUBREGION_%s_BASE", FBlock->Name, Subregion->Name);
+ sprintf (SymValue, "0x%08X", FDev->BaseAddress + Offset + SubregionOffset);
+ SymbolAdd (SymName, SymValue, 0);
+ sprintf (SymName, "FLASH_REGION_%s_SUBREGION_%s_SIZE", FBlock->Name, Subregion->Name);
+ sprintf (SymValue, "0x%08X", Subregion->Size);
+ SymbolAdd (SymName, SymValue, 0);
+ sprintf (SymName, "FLASH_REGION_%s_SUBREGION_%s_OFFSET", FBlock->Name, Subregion->Name);
+ sprintf (SymValue, "0x%08X", Offset + SubregionOffset);
+ SymbolAdd (SymName, SymValue, 0);
+ SubregionOffset += Subregion->Size;
+ }
+ }
+
+ Offset += FBlock->Size;
+ }
+
+ return STATUS_SUCCESS;
+}
+
+STATUS
+FDFCreateImage (
+ char *FlashDeviceName,
+ char *ImageName,
+ char *FileName
+ )
+/*++
+
+Routine Description:
+ Create a flash image using the given device and image names.
+
+Arguments:
+ FlashDeviceName - name of flash device (from the flash definition file)
+ to use
+ ImageName - name of image (from the flash definition file) to create
+ FileName - name of output file to create
+
+Returns:
+ STATUS_SUCCESS - no errors or warnings
+ STATUS_WARNING - warnings, but no errors, were encountered
+ STATUS_ERROR - errors were encountered
+
+--*/
+{
+ STATUS Status;
+ FILE *OutFptr;
+ FLASH_BLOCK_DESCRIPTION *RegionDef;
+ FLASH_DEVICE_DESCRIPTION *FDev;
+ IMAGE_DEFINITION *ImageDef;
+ unsigned int Offset;
+ char *Buffer;
+ FILE *InFptr;
+ long FileSize;
+ IMAGE_DEFINITION_ENTRY *IDefEntry;
+ FLASH_SUBREGION_DESCRIPTION *SubregionDef;
+ //
+ // Find the flash definition we're supposed to use
+ //
+ InFptr = NULL;
+ Status = STATUS_ERROR;
+ for (FDev = mFlashDevices; FDev != NULL; FDev = FDev->Next) {
+ if (strcmp (FDev->Name, FlashDeviceName) == 0) {
+ break;
+ }
+ }
+
+ if (FDev == NULL) {
+ Error (NULL, 0, 0, FlashDeviceName, "flash device not found in flash definitions");
+ return STATUS_ERROR;
+ }
+ //
+ // Find the image name we're supposed to create
+ //
+ for (ImageDef = mImageDefinitions; ImageDef != NULL; ImageDef = ImageDef->Next) {
+ if (strcmp (ImageDef->Name, ImageName) == 0) {
+ break;
+ }
+ }
+
+ if (ImageDef == NULL) {
+ Error (NULL, 0, 0, ImageName, "image definition not found in image definitions");
+ return STATUS_ERROR;
+ }
+ //
+ // Open the output file
+ //
+ if ((OutFptr = fopen (FileName, "wb")) == NULL) {
+ Error (NULL, 0, 0, FileName, "failed to open output file for writing");
+ return STATUS_ERROR;
+ }
+ //
+ // Allocate a buffer to copy the input data to
+ //
+ Buffer = (char *) _malloc (FDev->Size);
+ if (Buffer == NULL) {
+ Error (NULL, 0, 0, (INT8 *) "failed to allocate memory", NULL);
+ goto Done;
+ }
+ //
+ // Set contents of buffer to the erased value
+ //
+ if (FDev->ErasePolarity) {
+ memset (Buffer, 0xFF, FDev->Size);
+ } else {
+ memset (Buffer, 0, FDev->Size);
+ }
+ //
+ // Set all region and subregion size-left fields to the size of the region/subregion
+ //
+ for (RegionDef = FDev->Regions; RegionDef != NULL; RegionDef = RegionDef->Next) {
+ RegionDef->SizeLeft = RegionDef->Size;
+ for (SubregionDef = RegionDef->Subregions; SubregionDef != NULL; SubregionDef = SubregionDef->Next) {
+ SubregionDef->SizeLeft = SubregionDef->Size;
+ }
+ }
+ //
+ // Now go through the image list, read files into the buffer.
+ //
+ for (IDefEntry = ImageDef->Entries; IDefEntry != NULL; IDefEntry = IDefEntry->Next) {
+ //
+ // If it's a file name, open the file, get the size, find the corresponding
+ // flash region it's in, and copy the data.
+ //
+ if (IDefEntry->IsRawData == 0) {
+ if ((InFptr = fopen (IDefEntry->Name, "rb")) == NULL) {
+ Error (NULL, 0, 0, IDefEntry->Name, "failed to open input file for reading");
+ goto Done;
+ }
+
+ fseek (InFptr, 0, SEEK_END);
+ FileSize = ftell (InFptr);
+ fseek (InFptr, 0, SEEK_SET);
+ } else {
+ FileSize = IDefEntry->RawDataSize;
+ }
+ //
+ // Find the region/subregion it's in, see if we have space left
+ //
+ Offset = 0;
+ for (RegionDef = FDev->Regions; RegionDef != NULL; RegionDef = RegionDef->Next) {
+ if (strcmp (RegionDef->Name, IDefEntry->RegionName) == 0) {
+ break;
+ }
+
+ Offset += RegionDef->Size;
+ }
+
+ if (RegionDef == NULL) {
+ Error (NULL, 0, 0, IDefEntry->RegionName, "Region name not found in FlashDevice %s definition", FDev->Name);
+ goto Done;
+ }
+
+ //
+ // Check for subregion
+ //
+ if (IDefEntry->SubregionName[0] != 0) {
+ for (SubregionDef = RegionDef->Subregions; SubregionDef != NULL; SubregionDef = SubregionDef->Next) {
+ if (strcmp (SubregionDef->Name, IDefEntry->SubregionName) == 0) {
+ break;
+ }
+
+ Offset += SubregionDef->Size;
+ }
+
+ if (SubregionDef == NULL) {
+ Error (
+ NULL,
+ 0,
+ 0,
+ IDefEntry->SubregionName,
+ "Subregion name not found in FlashDevice %s.%s Region definition",
+ FDev->Name,
+ RegionDef->Name
+ );
+ goto Done;
+ }
+ //
+ // Enough space in the subregion?
+ //
+ if (SubregionDef->SizeLeft < (unsigned int) FileSize) {
+ Error (
+ NULL,
+ 0,
+ 0,
+ IDefEntry->Name,
+ "insufficient space in Subregion (at least 0x%X additional bytes required)",
+ FileSize - SubregionDef->SizeLeft
+ );
+ goto Done;
+ }
+
+ //
+ // Read the file into the buffer if it's a file. Otherwise copy the raw data
+ //
+ if (IDefEntry->IsRawData == 0) {
+ if (fread (Buffer + Offset + (SubregionDef->Size - SubregionDef->SizeLeft), FileSize, 1, InFptr) != 1) {
+ Error (NULL, 0, 0, IDefEntry->Name, "failed to read file contents");
+ goto Done;
+ }
+
+ fclose (InFptr);
+ InFptr = NULL;
+ } else {
+ memcpy (
+ Buffer + Offset + (SubregionDef->Size - SubregionDef->SizeLeft),
+ IDefEntry->RawData,
+ IDefEntry->RawDataSize
+ );
+ }
+
+ SubregionDef->SizeLeft -= FileSize;
+ //
+ // Align based on the Region alignment requirements.
+ //
+ if (RegionDef->Alignment != 0) {
+ while (((unsigned int) (SubregionDef->Size - SubregionDef->SizeLeft) &~RegionDef->Alignment) != 0) {
+ if (SubregionDef->SizeLeft == 0) {
+ break;
+ }
+
+ SubregionDef->SizeLeft--;
+ }
+ }
+ } else {
+ //
+ // Placing data in a region. Check for enough space in the region left.
+ //
+ if (RegionDef->SizeLeft < (unsigned int) FileSize) {
+ Error (
+ NULL,
+ 0,
+ 0,
+ IDefEntry->Name,
+ "insufficient space in Region (at least 0x%X additional bytes required)",
+ FileSize - RegionDef->SizeLeft
+ );
+ goto Done;
+ }
+
+ //
+ // Read the file into the buffer if it's a file. Otherwise copy the raw data
+ //
+ if (IDefEntry->IsRawData == 0) {
+ if (fread (Buffer + Offset + (RegionDef->Size - RegionDef->SizeLeft), FileSize, 1, InFptr) != 1) {
+ Error (NULL, 0, 0, IDefEntry->Name, "failed to read file contents");
+ goto Done;
+ }
+
+ fclose (InFptr);
+ InFptr = NULL;
+ } else {
+ memcpy (Buffer + Offset + (RegionDef->Size - RegionDef->SizeLeft), IDefEntry->RawData, IDefEntry->RawDataSize);
+ }
+
+ RegionDef->SizeLeft -= FileSize;
+ //
+ // Align
+ //
+ if (RegionDef->Alignment != 0) {
+ while (((unsigned int) (RegionDef->Size - RegionDef->SizeLeft) &~RegionDef->Alignment) != 0) {
+ if (RegionDef->SizeLeft == 0) {
+ break;
+ }
+
+ RegionDef->SizeLeft--;
+ }
+ }
+ }
+ }
+
+ if (fwrite (Buffer, FDev->Size, 1, OutFptr) != 1) {
+ Error (NULL, 0, 0, "failed to write buffer contents to output file", NULL);
+ goto Done;
+ }
+
+ Status = STATUS_SUCCESS;
+Done:
+ if (InFptr != NULL) {
+ fclose (InFptr);
+ }
+
+ if (Buffer != NULL) {
+ _free (Buffer);
+ }
+
+ if (OutFptr != NULL) {
+ fclose (OutFptr);
+ if (Status == STATUS_ERROR) {
+ remove (FileName);
+ }
+ }
+
+ return Status;
+}
+
+STATUS
+FDFCreateDscFile (
+ char *FlashDeviceName,
+ char *FileName
+ )
+/*++
+
+Routine Description:
+ Create a DSC-style output file with equates for flash management.
+
+Arguments:
+ FlashDeviceName - name of flash device (from the flash definition file)
+ to use
+ FileName - name of output file to create
+
+Returns:
+ STATUS_SUCCESS - no errors or warnings
+ STATUS_WARNING - warnings, but no errors, were encountered
+ STATUS_ERROR - errors were encountered
+
+--*/
+{
+ FILE *OutFptr;
+ FLASH_BLOCK_DESCRIPTION *FBlock;
+ FLASH_DEVICE_DESCRIPTION *FDev;
+ unsigned int Offset;
+ FLASH_SUBREGION_DESCRIPTION *Subregion;
+ unsigned int SubregionOffset;
+ //
+ // Find the definition we're supposed to use
+ //
+ for (FDev = mFlashDevices; FDev != NULL; FDev = FDev->Next) {
+ if (strcmp (FDev->Name, FlashDeviceName) == 0) {
+ break;
+ }
+ }
+
+ if (FDev == NULL) {
+ Error (NULL, 0, 0, FlashDeviceName, "flash device not found in flash definitions");
+ return STATUS_ERROR;
+ }
+
+ if ((OutFptr = fopen (FileName, "w")) == NULL) {
+ Error (NULL, 0, 0, FileName, "failed to open output file for writing");
+ return STATUS_ERROR;
+ }
+ //
+ // Write the flash base address and size
+ //
+ fprintf (OutFptr, "\n");
+ fprintf (OutFptr, "FLASH_BASE = 0x%08X\n", FDev->BaseAddress);
+ fprintf (OutFptr, "FLASH_SIZE = 0x%08X\n\n", FDev->Size);
+ //
+ // Write flash block size and offset defines
+ //
+ Offset = 0;
+ for (FBlock = FDev->Regions; FBlock != NULL; FBlock = FBlock->Next) {
+ fprintf (
+ OutFptr,
+ "FLASH_REGION_%s_BASE %*c= 0x%08X\n",
+ FBlock->Name,
+ COLUMN2_START - 40 - strlen (FBlock->Name),
+ ' ',
+ Offset + FDev->BaseAddress
+ );
+ fprintf (
+ OutFptr,
+ "FLASH_REGION_%s_SIZE %*c= 0x%08X\n",
+ FBlock->Name,
+ COLUMN2_START - 40 - strlen (FBlock->Name),
+ ' ',
+ FBlock->Size
+ );
+ fprintf (
+ OutFptr,
+ "FLASH_REGION_%s_SIZE_BLOCKS %*c= 0x%x\n",
+ FBlock->Name,
+ COLUMN2_START - 40 - strlen (FBlock->Name),
+ ' ',
+ (FBlock->Size)/(FDev->PBlocks->Size)
+ );
+ //
+ // Create defines for any subregions
+ //
+ SubregionOffset = 0;
+ for (Subregion = FBlock->Subregions; Subregion != NULL; Subregion = Subregion->Next) {
+ fprintf (
+ OutFptr,
+ "FLASH_REGION_%s_SUBREGION_%s_BASE %*c= 0x%08X\n",
+ FBlock->Name,
+ Subregion->Name,
+ COLUMN3_START - 48 - strlen (FBlock->Name) - strlen (Subregion->Name),
+ ' ',
+ FDev->BaseAddress + Offset + SubregionOffset
+ );
+ fprintf (
+ OutFptr,
+ "FLASH_REGION_%s_SUBREGION_%s_SIZE %*c= 0x%08X\n",
+ FBlock->Name,
+ Subregion->Name,
+ COLUMN3_START - 48 - strlen (FBlock->Name) - strlen (Subregion->Name),
+ ' ',
+ Subregion->Size
+ );
+ fprintf (
+ OutFptr,
+ "FLASH_REGION_%s_SUBREGION_%s_OFFSET %*c= 0x%08X\n",
+ FBlock->Name,
+ Subregion->Name,
+ COLUMN3_START - 48 - strlen (FBlock->Name) - strlen (Subregion->Name),
+ ' ',
+ Offset + SubregionOffset
+ );
+
+ SubregionOffset += Subregion->Size;
+ }
+
+ Offset += FBlock->Size;
+ }
+ //
+ // Close file
+ //
+ fprintf (OutFptr, "\n");
+ fclose (OutFptr);
+ return STATUS_SUCCESS;
+}
+
+
+/*++
+
+Routine Description:
+ The following buffer management routines are used to encapsulate functionality
+ for managing a growable data buffer.
+
+Arguments:
+ BUFFER_DATA - structure that is used to maintain a data buffer
+
+Returns:
+ NA
+
+--*/
+static
+BUFFER_DATA *
+CreateBufferData (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Create a growable data buffer with default buffer length.
+
+Arguments:
+
+ None
+
+Returns:
+
+ NULL - error occured during data buffer creation
+ Not NULL - the pointer to the newly created data buffer
+
+--*/
+{
+ BUFFER_DATA *BD;
+ BD = (BUFFER_DATA *) _malloc (sizeof (BUFFER_DATA));
+ if (BD == NULL) {
+ Error (__FILE__, __LINE__, 0, "memory allocation failure", NULL);
+ return NULL;
+ }
+
+ memset (BD, 0, sizeof (BUFFER_DATA));
+ BD->BufferStart = (char *) _malloc (BUFFER_SIZE);
+ if (BD->BufferStart == NULL) {
+ _free (BD);
+ Error (__FILE__, __LINE__, 0, "memory allocation failure", NULL);
+ return NULL;
+ }
+
+ BD->BufferEnd = BD->BufferStart + BUFFER_SIZE;
+ BD->BufferPos = BD->BufferStart;
+ return BD;
+}
+
+static
+BOOLEAN
+AddBufferDataByte (
+ BUFFER_DATA *Buffer,
+ char Data
+ )
+/*++
+
+Routine Description:
+
+ Add a single byte to a growable data buffer, growing the buffer if required.
+
+Arguments:
+
+ Buffer - pointer to the growable data buffer to add a single byte to
+ Data - value of the single byte data to be added
+
+Returns:
+
+ TRUE - the single byte data was successfully added
+ FALSE - error occurred, the single byte data was not added
+
+--*/
+{
+ int Size;
+ char *NewBuffer;
+ //
+ // See if we have to grow the buffer
+ //
+ if (Buffer->BufferPos >= Buffer->BufferEnd) {
+ Size = (int) Buffer->BufferEnd - (int) Buffer->BufferStart;
+ NewBuffer = (char *) _malloc (Size + BUFFER_SIZE);
+ if (NewBuffer == NULL) {
+ Error (__FILE__, __LINE__, 0, "memory allocation failure", NULL);
+ return FALSE;
+ }
+
+ memcpy (NewBuffer, Buffer->BufferStart, Size);
+ _free (Buffer->BufferStart);
+ Buffer->BufferStart = NewBuffer;
+ Buffer->BufferPos = Buffer->BufferStart + Size;
+ Buffer->BufferEnd = Buffer->BufferStart + Size + BUFFER_SIZE;
+ }
+
+ *Buffer->BufferPos = Data;
+ Buffer->BufferPos++;
+ return TRUE;
+}
+
+static
+void
+FreeBufferData (
+ BUFFER_DATA *Buffer,
+ BOOLEAN FreeData
+ )
+/*++
+
+Routine Description:
+
+ Free memory used to manage a growable data buffer.
+
+Arguments:
+
+ Buffer - pointer to the growable data buffer to be destructed
+ FreeData - TRUE, free memory containing the buffered data
+ FALSE, do not free the buffered data memory
+
+Returns:
+
+ None
+
+--*/
+{
+ if (Buffer != NULL) {
+ if (FreeData && (Buffer->BufferStart != NULL)) {
+ _free (Buffer->BufferStart);
+ }
+
+ _free (Buffer);
+ }
+}
+
+static
+char *
+GetBufferData (
+ BUFFER_DATA *Buffer,
+ int *BufferSize
+ )
+/*++
+
+Routine Description:
+
+ Return a pointer and size of the data in a growable data buffer.
+
+Arguments:
+
+ Buffer - pointer to the growable data buffer
+ BufferSize - size of the data in the growable data buffer
+
+Returns:
+
+ pointer of the data in the growable data buffer
+
+--*/
+{
+ *BufferSize = (int) Buffer->BufferPos - (int) Buffer->BufferStart;
+ return Buffer->BufferStart;
+}
+
+STATUS
+FDDiscover (
+ char *FDFileName,
+ unsigned int BaseAddr
+ )
+/*++
+
+Routine Description:
+ Walk a binary image and see if you find anything that looks like a
+ firmware volume.
+
+Arguments:
+ FDFileName - name of input FD image to parse
+ BaseAddr - base address of input FD image
+
+Returns:
+ STATUS_SUCCESS - no errors or warnings
+ STATUS_WARNING - warnings, but no errors, were encountered
+ STATUS_ERROR - errors were encountered
+
+NOTE:
+ This routine is used for debug purposes only.
+
+--*/
+{
+ FILE *InFptr;
+ long FileSize;
+ long Offset;
+ EFI_FIRMWARE_VOLUME_HEADER FVHeader;
+ EFI_GUID
+ FileSystemGuid = { 0x7A9354D9, 0x0468, 0x444a, 0x81, 0xCE, 0x0B, 0xF6, 0x17, 0xD8, 0x90, 0xDF };
+
+ if ((InFptr = fopen (FDFileName, "rb")) == NULL) {
+ Error (NULL, 0, 0, FDFileName, "failed to open file for reading");
+ return STATUS_ERROR;
+ }
+
+ fseek (InFptr, 0, SEEK_END);
+ FileSize = ftell (InFptr);
+ fseek (InFptr, 0, SEEK_SET);
+ Offset = 0;
+ while (Offset < FileSize) {
+ fseek (InFptr, Offset, SEEK_SET);
+ //
+ // Read the contents of the file, see if it's an FV header
+ //
+ if (fread (&FVHeader, sizeof (EFI_FIRMWARE_VOLUME_HEADER), 1, InFptr) == 1) {
+ //
+ // Check version and GUID
+ //
+ if ((FVHeader.Revision == EFI_FVH_REVISION) && (FVHeader.Signature == EFI_FVH_SIGNATURE)) {
+ fprintf (stdout, "FV header at 0x%08X FVSize=0x%08X ", Offset + BaseAddr, (UINT32) FVHeader.FvLength);
+ if (memcmp (&FVHeader.FileSystemGuid, &FileSystemGuid, sizeof (EFI_GUID)) == 0) {
+ fprintf (stdout, "standard FFS file system\n");
+ } else {
+ fprintf (stdout, "non-standard FFS file system\n");
+ }
+ }
+ }
+
+ Offset += 16 * 1024;
+ }
+
+ fclose (InFptr);
+ return STATUS_SUCCESS;
+}
diff --git a/Source/FlashMap/FlashDefFile.h b/Source/FlashMap/FlashDefFile.h
new file mode 100644
index 0000000..0e2ea2c
--- /dev/null
+++ b/Source/FlashMap/FlashDefFile.h
@@ -0,0 +1,281 @@
+/*++
+
+Copyright (c) 2004-2006 Intel Corporation. All rights reserved
+This program and the accompanying materials are licensed and made available
+under the terms and conditions of the BSD License which accompanies this
+distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+
+Module Name:
+
+ FlashDefFile.h
+
+Abstract:
+
+ Header file for flash management utility in the Intel Platform
+ Innovation Framework for EFI build environment.
+
+--*/
+
+#ifndef _FLASH_DEF_FILE_H_
+#define _FLASH_DEF_FILE_H_
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+void
+FDFConstructor (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ None
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+void
+FDFDestructor (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ None
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+STATUS
+FDFParseFile (
+ char *FileName
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ FileName - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+STATUS
+FDFCreateCIncludeFile (
+ char *FlashDeviceName,
+ char *FileName
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ FlashDeviceName - GC_TODO: add argument description
+ FileName - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+STATUS
+FDFCreateCFlashMapDataFile (
+ char *FlashDeviceName,
+ char *FileName
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ FlashDeviceName - GC_TODO: add argument description
+ FileName - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+STATUS
+FDFCreateAsmIncludeFile (
+ char *FlashDeviceName,
+ char *FileName
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ FlashDeviceName - GC_TODO: add argument description
+ FileName - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+STATUS
+FDFParseFile (
+ char *FileName
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ FileName - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+STATUS
+FDFCreateImage (
+ char *FlashDeviceName,
+ char *ImageName,
+ char *FileName
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ FlashDeviceName - GC_TODO: add argument description
+ ImageName - GC_TODO: add argument description
+ FileName - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+STATUS
+FDFCreateDscFile (
+ char *FlashDeviceName,
+ char *FileName
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ FlashDeviceName - GC_TODO: add argument description
+ FileName - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+STATUS
+FDFCreateSymbols (
+ char *FlashDeviceName
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ FlashDeviceName - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+STATUS
+FDDiscover (
+ char *FDFileName,
+ unsigned int BaseAddr
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ FDFileName - GC_TODO: add argument description
+ BaseAddr - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // #ifndef _FLASH_DEF_FILE_H_
diff --git a/Source/FlashMap/FlashMap.c b/Source/FlashMap/FlashMap.c
new file mode 100644
index 0000000..88f5003
--- /dev/null
+++ b/Source/FlashMap/FlashMap.c
@@ -0,0 +1,769 @@
+/*++
+
+Copyright (c) 2004-2006 Intel Corporation. All rights reserved
+This program and the accompanying materials are licensed and made available
+under the terms and conditions of the BSD License which accompanies this
+distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ FlashMap.c
+
+Abstract:
+
+ Utility for flash management in the Intel Platform Innovation Framework
+ for EFI build environment.
+
+--*/
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+
+#include <Common/UefiBaseTypes.h>
+
+#include "EfiUtilityMsgs.h"
+#include "Microcode.h"
+#include "FlashDefFile.h"
+#include "Symbols.h"
+
+#define UTILITY_NAME "FlashMap"
+
+typedef struct _STRING_LIST {
+ struct _STRING_LIST *Next;
+ char *Str;
+} STRING_LIST;
+
+//
+// Keep our globals in one of these structures
+//
+static struct {
+ char *CIncludeFileName;
+ char *FlashDevice;
+ char *FlashDeviceImage;
+ char *MCIFileName;
+ char *MCOFileName;
+ char *ImageOutFileName;
+ char *DscFileName;
+ char *AsmIncludeFileName;
+ char *FlashDefinitionFileName;
+ char *StringReplaceInFileName;
+ char *StringReplaceOutFileName;
+ char *DiscoverFDImageName;
+ char MicrocodePadByteValue;
+ unsigned int MicrocodeAlignment;
+ STRING_LIST *MCIFileNames;
+ STRING_LIST *LastMCIFileNames;
+ unsigned int BaseAddress;
+} mGlobals;
+
+#define DEFAULT_MC_PAD_BYTE_VALUE 0xFF
+#define DEFAULT_MC_ALIGNMENT 16
+
+static
+STATUS
+ProcessCommandLine (
+ int argc,
+ char *argv[]
+ );
+
+static
+STATUS
+MergeMicrocodeFiles (
+ char *OutFileName,
+ STRING_LIST *FileNames,
+ unsigned int Alignment,
+ char PadByteValue
+ );
+
+static
+void
+Usage (
+ VOID
+ );
+
+char*
+NormalizePath (
+ char* OldPathName
+ );
+
+int
+main (
+ int argc,
+ char *argv[]
+ )
+/*++
+
+Routine Description:
+ Parse the command line arguments and then call worker functions to do the work
+
+Arguments:
+ argc - number of elements in argv
+ argv - array of command-line arguments
+
+Returns:
+ STATUS_SUCCESS - no problems encountered while processing
+ STATUS_WARNING - warnings, but no errors, were encountered while processing
+ STATUS_ERROR - errors were encountered while processing
+
+--*/
+{
+ STATUS Status;
+
+ SetUtilityName (UTILITY_NAME);
+ Status = ProcessCommandLine (argc, argv);
+ if (Status != STATUS_SUCCESS) {
+ return Status;
+ }
+ //
+ // Check for discovery of an FD (command line option)
+ //
+ if (mGlobals.DiscoverFDImageName != NULL) {
+ Status = FDDiscover (mGlobals.DiscoverFDImageName, mGlobals.BaseAddress);
+ goto Done;
+ }
+ //
+ // If they're doing microcode file parsing, then do that
+ //
+ if (mGlobals.MCIFileName != NULL) {
+ MicrocodeConstructor ();
+ MicrocodeParseFile (mGlobals.MCIFileName, mGlobals.MCOFileName);
+ MicrocodeDestructor ();
+ }
+ //
+ // If they're doing microcode file merging, then do that now
+ //
+ if (mGlobals.MCIFileNames != NULL) {
+ MergeMicrocodeFiles (
+ mGlobals.MCOFileName,
+ mGlobals.MCIFileNames,
+ mGlobals.MicrocodeAlignment,
+ mGlobals.MicrocodePadByteValue
+ );
+ }
+ //
+ // If using a flash definition file, then process that and return
+ //
+ if (mGlobals.FlashDefinitionFileName != NULL) {
+ FDFConstructor ();
+ SymbolsConstructor ();
+ Status = FDFParseFile (mGlobals.FlashDefinitionFileName);
+ if (GetUtilityStatus () != STATUS_ERROR) {
+ //
+ // If they want us to do a string-replace on a file, then add the symbol definitions to
+ // the symbol table, and then do the string replace.
+ //
+ if (mGlobals.StringReplaceInFileName != NULL) {
+ Status = FDFCreateSymbols (mGlobals.FlashDevice);
+ Status = SymbolsFileStringsReplace (mGlobals.StringReplaceInFileName, mGlobals.StringReplaceOutFileName);
+ }
+ //
+ // If they want us to create a .h defines file or .c flashmap data file, then do so now
+ //
+ if (mGlobals.CIncludeFileName != NULL) {
+ Status = FDFCreateCIncludeFile (mGlobals.FlashDevice, mGlobals.CIncludeFileName);
+ }
+ if (mGlobals.AsmIncludeFileName != NULL) {
+ Status = FDFCreateAsmIncludeFile (mGlobals.FlashDevice, mGlobals.AsmIncludeFileName);
+ }
+ //
+ // If they want us to create an image, do that now
+ //
+ if (mGlobals.ImageOutFileName != NULL) {
+ Status = FDFCreateImage (mGlobals.FlashDevice, mGlobals.FlashDeviceImage, mGlobals.ImageOutFileName);
+ }
+ //
+ // If they want to create an output DSC file, do that now
+ //
+ if (mGlobals.DscFileName != NULL) {
+ Status = FDFCreateDscFile (mGlobals.FlashDevice, mGlobals.DscFileName);
+ }
+ }
+ SymbolsDestructor ();
+ FDFDestructor ();
+ }
+Done:
+ //
+ // Free up memory
+ //
+ while (mGlobals.MCIFileNames != NULL) {
+ mGlobals.LastMCIFileNames = mGlobals.MCIFileNames->Next;
+ _free (mGlobals.MCIFileNames);
+ mGlobals.MCIFileNames = mGlobals.LastMCIFileNames;
+ }
+ return GetUtilityStatus ();
+}
+
+static
+STATUS
+MergeMicrocodeFiles (
+ char *OutFileName,
+ STRING_LIST *FileNames,
+ unsigned int Alignment,
+ char PadByteValue
+ )
+/*++
+
+Routine Description:
+
+ Merge binary microcode files into a single file, taking into consideration
+ the alignment and pad value.
+
+Arguments:
+
+ OutFileName - name of the output file to create
+ FileNames - linked list of input microcode files to merge
+ Alignment - alignment for each microcode file in the output image
+ PadByteValue - value to use when padding to meet alignment requirements
+
+Returns:
+
+ STATUS_SUCCESS - merge completed successfully or with acceptable warnings
+ STATUS_ERROR - merge failed, output file not created
+
+--*/
+{
+ long FileSize;
+ long TotalFileSize;
+ FILE *InFptr;
+ FILE *OutFptr;
+ char *Buffer;
+ STATUS Status;
+
+ //
+ // Open the output file
+ //
+ if ((OutFptr = fopen (OutFileName, "wb")) == NULL) {
+ Error (NULL, 0, 0, OutFileName, "failed to open output file for writing");
+ return STATUS_ERROR;
+ }
+ //
+ // Walk the list of files
+ //
+ Status = STATUS_ERROR;
+ Buffer = NULL;
+ InFptr = NULL;
+ TotalFileSize = 0;
+ while (FileNames != NULL) {
+ //
+ // Open the file, determine the size, then read it in and write
+ // it back out.
+ //
+ if ((InFptr = fopen (NormalizePath(FileNames->Str), "rb")) == NULL) {
+ Error (NULL, 0, 0, NormalizePath(FileNames->Str), "failed to open input file for reading");
+ goto Done;
+ }
+ fseek (InFptr, 0, SEEK_END);
+ FileSize = ftell (InFptr);
+ fseek (InFptr, 0, SEEK_SET);
+ if (FileSize != 0) {
+ Buffer = (char *) _malloc (FileSize);
+ if (Buffer == NULL) {
+ Error (NULL, 0, 0, "memory allocation failure", NULL);
+ goto Done;
+ }
+ if (fread (Buffer, FileSize, 1, InFptr) != 1) {
+ Error (NULL, 0, 0, FileNames->Str, "failed to read file contents");
+ goto Done;
+ }
+ //
+ // Align
+ //
+ if (Alignment != 0) {
+ while ((TotalFileSize % Alignment) != 0) {
+ if (fwrite (&PadByteValue, 1, 1, OutFptr) != 1) {
+ Error (NULL, 0, 0, OutFileName, "failed to write pad bytes to output file");
+ goto Done;
+ }
+ TotalFileSize++;
+ }
+ }
+ TotalFileSize += FileSize;
+ if (fwrite (Buffer, FileSize, 1, OutFptr) != 1) {
+ Error (NULL, 0, 0, OutFileName, "failed to write to output file");
+ goto Done;
+ }
+ _free (Buffer);
+ Buffer = NULL;
+ } else {
+ Warning (NULL, 0, 0, FileNames->Str, "0-size file encountered");
+ }
+ fclose (InFptr);
+ InFptr = NULL;
+ FileNames = FileNames->Next;
+ }
+ Status = STATUS_SUCCESS;
+Done:
+ fclose (OutFptr);
+ if (InFptr != NULL) {
+ fclose (InFptr);
+ }
+ if (Buffer != NULL) {
+ _free (Buffer);
+ }
+ if (Status == STATUS_ERROR) {
+ remove (OutFileName);
+ }
+ return Status;
+}
+
+static
+STATUS
+ProcessCommandLine (
+ int argc,
+ char *argv[]
+ )
+/*++
+
+Routine Description:
+ Process the command line arguments
+
+Arguments:
+ argc - Standard C entry point arguments
+ argv[] - Standard C entry point arguments
+
+Returns:
+ STATUS_SUCCESS - no problems encountered while processing
+ STATUS_WARNING - warnings, but no errors, were encountered while processing
+ STATUS_ERROR - errors were encountered while processing
+
+--*/
+{
+ int ThingsToDo;
+ unsigned int Temp;
+ STRING_LIST *Str;
+ //
+ // Skip program name arg, process others
+ //
+ argc--;
+ argv++;
+ if (argc == 0) {
+ Usage ();
+ return STATUS_ERROR;
+ }
+ //
+ // Clear out our globals, then start walking the arguments
+ //
+ memset ((void *) &mGlobals, 0, sizeof (mGlobals));
+ mGlobals.MicrocodePadByteValue = DEFAULT_MC_PAD_BYTE_VALUE;
+ mGlobals.MicrocodeAlignment = DEFAULT_MC_ALIGNMENT;
+ ThingsToDo = 0;
+ while (argc > 0) {
+ if (strcmp (argv[0], "-?") == 0) {
+ Usage ();
+ return STATUS_ERROR;
+ } else if (strcmp (argv[0], "-hfile") == 0) {
+ //
+ // -hfile FileName
+ //
+ // Used to specify an output C #include file to create that contains
+ // #define statements for all the flashmap region offsets and sizes.
+ // Check for additional argument.
+ //
+ if (argc < 2) {
+ Error (NULL, 0, 0, argv[0], "option requires an output file name");
+ return STATUS_ERROR;
+ }
+ argc--;
+ argv++;
+ mGlobals.CIncludeFileName = argv[0];
+ ThingsToDo++;
+ } else if (strcmp (argv[0], "-flashdevice") == 0) {
+ //
+ // -flashdevice FLASH_DEVICE_NAME
+ //
+ // Used to select which flash device definition to operate on.
+ // Check for additional argument
+ //
+ if (argc < 2) {
+ Error (NULL, 0, 0, argv[0], "option requires a flash device name to use");
+ return STATUS_ERROR;
+ }
+ argc--;
+ argv++;
+ mGlobals.FlashDevice = argv[0];
+ } else if (strcmp (argv[0], "-mco") == 0) {
+ //
+ // -mco OutFileName
+ //
+ // Used to specify a microcode output binary file to create.
+ // Check for additional argument.
+ //
+ if (argc < 2) {
+ Error (NULL, 0, 0, (INT8 *) argv[0], (INT8 *) "option requires an output microcode file name to create");
+ return STATUS_ERROR;
+ }
+ argc--;
+ argv++;
+ mGlobals.MCOFileName = argv[0];
+ ThingsToDo++;
+ } else if (strcmp (argv[0], "-asmincfile") == 0) {
+ //
+ // -asmincfile FileName
+ //
+ // Used to specify the name of the output assembly include file that contains
+ // equates for the flash region addresses and sizes.
+ // Check for additional argument.
+ //
+ if (argc < 2) {
+ Error (NULL, 0, 0, argv[0], "option requires an output ASM include file name to create");
+ return STATUS_ERROR;
+ }
+ argc--;
+ argv++;
+ mGlobals.AsmIncludeFileName = argv[0];
+ ThingsToDo++;
+ } else if (strcmp (argv[0], "-mci") == 0) {
+ //
+ // -mci FileName
+ //
+ // Used to specify an input microcode text file to parse.
+ // Check for additional argument
+ //
+ if (argc < 2) {
+ Error (NULL, 0, 0, (INT8 *) argv[0], (INT8 *) "option requires an input microcode text file name to parse");
+ return STATUS_ERROR;
+ }
+ argc--;
+ argv++;
+ mGlobals.MCIFileName = argv[0];
+ } else if (strcmp (argv[0], "-flashdeviceimage") == 0) {
+ //
+ // -flashdeviceimage FlashDeviceImage
+ //
+ // Used to specify which flash device image definition from the input flash definition file
+ // to create.
+ // Check for additional argument.
+ //
+ if (argc < 2) {
+ Error (NULL, 0, 0, argv[0], "option requires the name of a flash definition image to use");
+ return STATUS_ERROR;
+ }
+ argc--;
+ argv++;
+ mGlobals.FlashDeviceImage = argv[0];
+ } else if (strcmp (argv[0], "-imageout") == 0) {
+ //
+ // -imageout FileName
+ //
+ // Used to specify the name of the output FD image file to create.
+ // Check for additional argument.
+ //
+ if (argc < 2) {
+ Error (NULL, 0, 0, argv[0], "option requires an output image filename to create");
+ return STATUS_ERROR;
+ }
+ argc--;
+ argv++;
+ mGlobals.ImageOutFileName = argv[0];
+ ThingsToDo++;
+ } else if (strcmp (argv[0], "-dsc") == 0) {
+ //
+ // -dsc FileName
+ //
+ // Used to specify the name of the output DSC file to create.
+ // Check for additional argument.
+ //
+ if (argc < 2) {
+ Error (NULL, 0, 0, argv[0], "option requires an output DSC filename to create");
+ return STATUS_ERROR;
+ }
+ argc--;
+ argv++;
+ mGlobals.DscFileName = argv[0];
+ ThingsToDo++;
+ } else if (strcmp (argv[0], "-fdf") == 0) {
+ //
+ // -fdf FileName
+ //
+ // Used to specify the name of the input flash definition file.
+ // Check for additional argument.
+ //
+ if (argc < 2) {
+ Error (NULL, 0, 0, argv[0], "option requires an input flash definition file name");
+ return STATUS_ERROR;
+ }
+ argc--;
+ argv++;
+ mGlobals.FlashDefinitionFileName = argv[0];
+ } else if (strcmp (argv[0], "-discover") == 0) {
+ //
+ // -discover FDFileName
+ //
+ // Debug functionality used to scan an existing FD image, trying to find
+ // firmware volumes at 64K boundaries.
+ // Check for additional argument.
+ //
+ if (argc < 2) {
+ Error (NULL, 0, 0, argv[0], "option requires an input FD image file name");
+ return STATUS_ERROR;
+ }
+ argc--;
+ argv++;
+ mGlobals.DiscoverFDImageName = argv[0];
+ ThingsToDo++;
+ } else if (strcmp (argv[0], "-baseaddr") == 0) {
+ //
+ // -baseaddr Addr
+ //
+ // Used to specify a base address when doing a discover of an FD image.
+ // Check for additional argument.
+ //
+ if (argc < 2) {
+ Error (NULL, 0, 0, argv[0], "option requires a base address");
+ return STATUS_ERROR;
+ }
+ argc--;
+ argv++;
+ if (tolower (argv[0][1]) == 'x') {
+ sscanf (argv[0] + 2, "%x", &mGlobals.BaseAddress);
+ } else {
+ sscanf (argv[0], "%d", &mGlobals.BaseAddress);
+ }
+ } else if (strcmp (argv[0], "-padvalue") == 0) {
+ //
+ // -padvalue Value
+ //
+ // Used to specify the value to pad with when aligning data while
+ // creating an FD image. Check for additional argument.
+ //
+ if (argc < 2) {
+ Error (NULL, 0, 0, argv[0], "option requires a byte value");
+ return STATUS_ERROR;
+ }
+ argc--;
+ argv++;
+ if (tolower (argv[0][1]) == 'x') {
+ sscanf (argv[0] + 2, "%x", &Temp);
+ mGlobals.MicrocodePadByteValue = (char) Temp;
+ } else {
+ sscanf (argv[0], "%d", &Temp);
+ mGlobals.MicrocodePadByteValue = (char) Temp;
+ }
+ } else if (strcmp (argv[0], "-align") == 0) {
+ //
+ // -align Alignment
+ //
+ // Used to specify how each data file is aligned in the region
+ // when creating an FD image. Check for additional argument.
+ //
+ if (argc < 2) {
+ Error (NULL, 0, 0, argv[0], "option requires an alignment");
+ return STATUS_ERROR;
+ }
+ argc--;
+ argv++;
+ if (tolower (argv[0][1]) == 'x') {
+ sscanf (argv[0] + 2, "%x", &mGlobals.MicrocodeAlignment);
+ } else {
+ sscanf (argv[0], "%d", &mGlobals.MicrocodeAlignment);
+ }
+ } else if (strcmp (argv[0], "-mcmerge") == 0) {
+ //
+ // -mcmerge FileName(s)
+ //
+ // Used to concatenate multiple microde binary files. Can specify
+ // multiple file names with the one -mcmerge flag. Check for additional argument.
+ //
+ if ((argc < 2) || (argv[1][0] == '-')) {
+ Error (NULL, 0, 0, argv[0], "option requires one or more input file names");
+ return STATUS_ERROR;
+ }
+ //
+ // Take input files until another option or end of list
+ //
+ ThingsToDo++;
+ while ((argc > 1) && (argv[1][0] != '-')) {
+ Str = (STRING_LIST *) _malloc (sizeof (STRING_LIST));
+ if (Str == NULL) {
+ Error (NULL, 0, 0, "memory allocation failure", NULL);
+ return STATUS_ERROR;
+ }
+ memset (Str, 0, sizeof (STRING_LIST));
+ Str->Str = argv[1];
+ if (mGlobals.MCIFileNames == NULL) {
+ mGlobals.MCIFileNames = Str;
+ } else {
+ mGlobals.LastMCIFileNames->Next = Str;
+ }
+ mGlobals.LastMCIFileNames = Str;
+ argc--;
+ argv++;
+ }
+ } else if (strcmp (argv[0], "-strsub") == 0) {
+ //
+ // -strsub SrcFile DestFile
+ //
+ // Used to perform string substitutions on a file, writing the result to a new
+ // file. Check for two additional arguments.
+ //
+ if (argc < 3) {
+ Error (NULL, 0, 0, argv[0], "option requires input and output file names for string substitution");
+ return STATUS_ERROR;
+ }
+ argc--;
+ argv++;
+ mGlobals.StringReplaceInFileName = argv[0];
+ argc--;
+ argv++;
+ mGlobals.StringReplaceOutFileName = argv[0];
+ ThingsToDo++;
+ } else {
+ Error (NULL, 0, 0, argv[0], "invalid option");
+ return STATUS_ERROR;
+ }
+ argc--;
+ argv++;
+ }
+ //
+ // If no outputs requested, then report an error
+ //
+ if (ThingsToDo == 0) {
+ Error (NULL, 0, 0, "nothing to do", NULL);
+ return STATUS_ERROR;
+ }
+ //
+ // If they want an asm file, #include file, or C file to be created, then they have to specify a
+ // flash device name and flash definition file name.
+ //
+ if ((mGlobals.CIncludeFileName != NULL) &&
+ ((mGlobals.FlashDevice == NULL) || (mGlobals.FlashDefinitionFileName == NULL))) {
+ Error (NULL, 0, 0, "must specify -flashdevice and -fdf with -hfile", NULL);
+ return STATUS_ERROR;
+ }
+ if ((mGlobals.AsmIncludeFileName != NULL) &&
+ ((mGlobals.FlashDevice == NULL) || (mGlobals.FlashDefinitionFileName == NULL))) {
+ Error (NULL, 0, 0, "must specify -flashdevice and -fdf with -asmincfile", NULL);
+ return STATUS_ERROR;
+ }
+ //
+ // If they want a dsc file to be created, then they have to specify a
+ // flash device name and a flash definition file name
+ //
+ if (mGlobals.DscFileName != NULL) {
+ if (mGlobals.FlashDevice == NULL) {
+ Error (NULL, 0, 0, "must specify -flashdevice with -dsc", NULL);
+ return STATUS_ERROR;
+ }
+ if (mGlobals.FlashDefinitionFileName == NULL) {
+ Error (NULL, 0, 0, "must specify -fdf with -dsc", NULL);
+ return STATUS_ERROR;
+ }
+ }
+ //
+ // If they specified an output microcode file name, then they have to specify an input
+ // file name, and vice versa.
+ //
+ if ((mGlobals.MCIFileName != NULL) && (mGlobals.MCOFileName == NULL)) {
+ Error (NULL, 0, 0, "must specify output microcode file name", NULL);
+ return STATUS_ERROR;
+ }
+ if ((mGlobals.MCOFileName != NULL) && (mGlobals.MCIFileName == NULL) && (mGlobals.MCIFileNames == NULL)) {
+ Error (NULL, 0, 0, "must specify input microcode file name", NULL);
+ return STATUS_ERROR;
+ }
+ //
+ // If doing merge, then have to specify output file name
+ //
+ if ((mGlobals.MCIFileNames != NULL) && (mGlobals.MCOFileName == NULL)) {
+ Error (NULL, 0, 0, "must specify output microcode file name", NULL);
+ return STATUS_ERROR;
+ }
+ //
+ // If they want an output image to be created, then they have to specify
+ // the flash device and the flash device image to use.
+ //
+ if (mGlobals.ImageOutFileName != NULL) {
+ if (mGlobals.FlashDevice == NULL) {
+ Error (NULL, 0, 0, "must specify -flashdevice with -imageout", NULL);
+ return STATUS_ERROR;
+ }
+ if (mGlobals.FlashDeviceImage == NULL) {
+ Error (NULL, 0, 0, "must specify -flashdeviceimage with -imageout", NULL);
+ return STATUS_ERROR;
+ }
+ if (mGlobals.FlashDefinitionFileName == NULL) {
+ Error (NULL, 0, 0, "must specify -c or -fdf with -imageout", NULL);
+ return STATUS_ERROR;
+ }
+ }
+ return STATUS_SUCCESS;
+}
+
+static
+void
+Usage (
+ VOID
+ )
+/*++
+
+Routine Description:
+ Print utility command line help
+
+Arguments:
+ None
+
+Returns:
+ NA
+
+--*/
+{
+ int i;
+ char *Msg[] = {
+ "Usage: FlashTool -fdf FlashDefFile -flashdevice FlashDevice",
+ " -flashdeviceimage FlashDeviceImage -mci MCIFile -mco MCOFile",
+ " -discover FDImage -dsc DscFile -asmincfile AsmIncFile",
+ " -imageOut ImageOutFile -hfile HFile -strsub InStrFile OutStrFile",
+ " -baseaddr BaseAddr -align Alignment -padvalue PadValue",
+ " -mcmerge MCIFile(s)",
+ " where",
+ " FlashDefFile - input Flash Definition File",
+ " FlashDevice - flash device to use (from flash definition file)",
+ " FlashDeviceImage - flash device image to use (from flash definition file)",
+ " MCIFile - input microcode file to parse",
+ " MCOFile - output binary microcode image to create from MCIFile",
+ " HFile - output #include file to create",
+ " FDImage - name of input FDImage file to scan",
+ " ImageOutFile - output image file to create",
+ " DscFile - output DSC file to create",
+ " AsmIncFile - output ASM include file to create",
+ " InStrFile - input file to replace symbol names, writing result to OutStrFile",
+ " BaseAddr - base address of FDImage (used with -discover)",
+ " Alignment - alignment to use when merging microcode binaries",
+ " PadValue - byte value to use as pad value when aligning microcode binaries",
+ " MCIFile(s) - one or more microcode binary files to merge/concatenate",
+ "",
+ NULL
+ };
+ for (i = 0; Msg[i] != NULL; i++) {
+ fprintf (stdout, "%s\n", Msg[i]);
+ }
+}
+
+char*
+NormalizePath (
+ char* OldPathName
+ )
+{
+ char* Visitor;
+
+ if (OldPathName == NULL) {
+ return NULL;
+ }
+
+ Visitor = OldPathName;
+ while (*Visitor != '\0') {
+ if (*Visitor == '\\') {
+ *Visitor = '/';
+ }
+ Visitor++;
+ }
+
+ return OldPathName;
+}
+
diff --git a/Source/FlashMap/Microcode.c b/Source/FlashMap/Microcode.c
new file mode 100644
index 0000000..2335325
--- /dev/null
+++ b/Source/FlashMap/Microcode.c
@@ -0,0 +1,304 @@
+/*++
+
+Copyright (c) 2004-2006 Intel Corporation. All rights reserved
+This program and the accompanying materials are licensed and made available
+under the terms and conditions of the BSD License which accompanies this
+distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ Microcode.c
+
+Abstract:
+
+ Utility for working with microcode patch files in the Intel
+ Platform Innovation Framework for EFI build environment.
+
+--*/
+
+#include <stdio.h>
+#include <string.h> // for memset()
+#include <ctype.h>
+#include <stdlib.h> // for malloc()
+
+#include "EfiUtilityMsgs.h"
+#include "Microcode.h"
+
+#define MAX_LINE_LEN 256
+
+//
+// Structure definition for a microcode header
+//
+typedef struct {
+ unsigned int HeaderVersion;
+ unsigned int PatchId;
+ unsigned int Date;
+ unsigned int CpuId;
+ unsigned int Checksum;
+ unsigned int LoaderVersion;
+ unsigned int PlatformId;
+ unsigned int DataSize; // if 0, then TotalSize = 2048, and TotalSize field is invalid
+ unsigned int TotalSize; // number of bytes
+ unsigned int Reserved[3];
+} MICROCODE_IMAGE_HEADER;
+
+static
+STATUS
+MicrocodeReadData (
+ FILE *InFptr,
+ unsigned int *Data
+ );
+
+void
+MicrocodeConstructor (
+ void
+ )
+/*++
+
+Routine Description:
+
+ Constructor of module Microcode
+
+Arguments:
+
+ None
+
+Returns:
+
+ None
+
+--*/
+{
+}
+
+void
+MicrocodeDestructor (
+ void
+ )
+/*++
+
+Routine Description:
+
+ Destructor of module Microcode
+
+Arguments:
+
+ None
+
+Returns:
+
+ None
+
+--*/
+{
+}
+
+static
+STATUS
+MicrocodeReadData (
+ FILE *InFptr,
+ unsigned int *Data
+ )
+/*++
+
+Routine Description:
+ Read a 32-bit microcode data value from a text file and convert to raw binary form.
+
+Arguments:
+ InFptr - file pointer to input text file
+ Data - pointer to where to return the data parsed
+
+Returns:
+ STATUS_SUCCESS - no errors or warnings, Data contains valid information
+ STATUS_ERROR - errors were encountered
+
+--*/
+{
+ char Line[MAX_LINE_LEN];
+ char *cptr;
+
+ Line[MAX_LINE_LEN - 1] = 0;
+ *Data = 0;
+ if (fgets (Line, MAX_LINE_LEN, InFptr) == NULL) {
+ return STATUS_ERROR;
+ }
+ //
+ // If it was a binary file, then it may have overwritten our null terminator
+ //
+ if (Line[MAX_LINE_LEN - 1] != 0) {
+ return STATUS_ERROR;
+ }
+ //
+ // Look for
+ // dd 000000001h ; comment
+ // dd XXXXXXXX
+ // DD XXXXXXXXX
+ // DD XXXXXXXXX
+ //
+ for (cptr = Line; *cptr && isspace(*cptr); cptr++) {
+ }
+ if ((tolower(cptr[0]) == 'd') && (tolower(cptr[1]) == 'd') && isspace (cptr[2])) {
+ //
+ // Skip blanks and look for a hex digit
+ //
+ cptr += 3;
+ for (; *cptr && isspace(*cptr); cptr++) {
+ }
+ if (isxdigit (*cptr)) {
+ if (sscanf (cptr, "%X", Data) != 1) {
+ return STATUS_ERROR;
+ }
+ }
+ return STATUS_SUCCESS;
+ }
+ return STATUS_ERROR;
+}
+
+STATUS
+MicrocodeParseFile (
+ char *InFileName,
+ char *OutFileName
+ )
+/*++
+
+Routine Description:
+ Parse a microcode text file, and write the binary results to an output file.
+
+Arguments:
+ InFileName - input text file to parse
+ OutFileName - output file to write raw binary data from parsed input file
+
+Returns:
+ STATUS_SUCCESS - no errors or warnings
+ STATUS_ERROR - errors were encountered
+
+--*/
+{
+ FILE *InFptr;
+ FILE *OutFptr;
+ STATUS Status;
+ MICROCODE_IMAGE_HEADER *Header;
+ unsigned int Size;
+ unsigned int Size2;
+ unsigned int Data;
+ unsigned int Checksum;
+ char *Buffer;
+ char *Ptr;
+ unsigned int TotalSize;
+
+ Status = STATUS_ERROR;
+ InFptr = NULL;
+ OutFptr = NULL;
+ Buffer = NULL;
+ //
+ // Open the input text file
+ //
+ if ((InFptr = fopen (InFileName, "r")) == NULL) {
+ Error (NULL, 0, 0, InFileName, "failed to open input microcode file for reading");
+ return STATUS_ERROR;
+ }
+ //
+ // Make two passes on the input file. The first pass is to determine how
+ // much data is in the file so we can allocate a working buffer. Then
+ // we'll allocate a buffer and re-read the file into the buffer for processing.
+ //
+ Size = 0;
+ do {
+ Status = MicrocodeReadData (InFptr, &Data);
+ if (Status == STATUS_SUCCESS) {
+ Size += sizeof (Data);
+ }
+ } while (Status == STATUS_SUCCESS);
+ //
+ // Error if no data.
+ //
+ if (Size == 0) {
+ Error (NULL, 0, 0, InFileName, "no parse-able data found in file");
+ goto Done;
+ }
+ if (Size < sizeof (MICROCODE_IMAGE_HEADER)) {
+ Error (NULL, 0, 0, InFileName, "amount of parse-able data is insufficient to contain a microcode header");
+ goto Done;
+ }
+ //
+ // Allocate a buffer for the data
+ //
+ Buffer = (char *) _malloc (Size);
+ if (Buffer == NULL) {
+ Error (NULL, 0, 0, "memory allocation failure", NULL);
+ goto Done;
+ }
+ //
+ // Re-read the file, storing the data into our buffer
+ //
+ fseek (InFptr, 0, SEEK_SET);
+ Ptr = Buffer;
+ do {
+ Status = MicrocodeReadData (InFptr, &Data);
+ if (Status == STATUS_SUCCESS) {
+ *(unsigned int *) Ptr = Data;
+ Ptr += sizeof (Data);
+ }
+ } while (Status == STATUS_SUCCESS);
+ //
+ // Can't do much checking on the header because, per the spec, the
+ // DataSize field may be 0, which means DataSize = 2000 and TotalSize = 2K,
+ // and the TotalSize field is invalid (actually missing). Thus we can't
+ // even verify the Reserved fields are 0.
+ //
+ Header = (MICROCODE_IMAGE_HEADER *) Buffer;
+ if (Header->DataSize == 0) {
+ TotalSize = 2048;
+ } else {
+ TotalSize = Header->TotalSize;
+ }
+ if (TotalSize != Size) {
+ Error (NULL, 0, 0, InFileName, "file contents do not contain expected TotalSize 0x%04X", TotalSize);
+ goto Done;
+ }
+ //
+ // Checksum the contents
+ //
+ Ptr = Buffer;
+ Checksum = 0;
+ Size2 = 0;
+ while (Size2 < Size) {
+ Checksum += *(unsigned int *) Ptr;
+ Ptr += 4;
+ Size2 += 4;
+ }
+ if (Checksum != 0) {
+ Error (NULL, 0, 0, InFileName, "checksum failed on file contents");
+ goto Done;
+ }
+ //
+ // Open the output file and write the buffer contents
+ //
+ if ((OutFptr = fopen (OutFileName, "wb")) == NULL) {
+ Error (NULL, 0, 0, OutFileName, "failed to open output microcode file for writing");
+ goto Done;
+ }
+ if (fwrite (Buffer, Size, 1, OutFptr) != 1) {
+ Error (NULL, 0, 0, OutFileName, "failed to write microcode data to output file");
+ goto Done;
+ }
+ Status = STATUS_SUCCESS;
+Done:
+ if (Buffer != NULL) {
+ free (Buffer);
+ }
+ if (InFptr != NULL) {
+ fclose (InFptr);
+ }
+ if (OutFptr != NULL) {
+ fclose (OutFptr);
+ if (Status == STATUS_ERROR) {
+ remove (OutFileName);
+ }
+ }
+ return Status;
+}
diff --git a/Source/FlashMap/Microcode.h b/Source/FlashMap/Microcode.h
new file mode 100644
index 0000000..f85313e
--- /dev/null
+++ b/Source/FlashMap/Microcode.h
@@ -0,0 +1,87 @@
+/*++
+
+Copyright (c) 2004-2006 Intel Corporation. All rights reserved
+This program and the accompanying materials are licensed and made available
+under the terms and conditions of the BSD License which accompanies this
+distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ Microcode.h
+
+Abstract:
+
+ Header file for flash management utility in the Intel Platform
+ Innovation Framework for EFI build environment.
+
+--*/
+
+#ifndef _MICROCODE_H_
+#define _MICROCODE_H_
+
+void
+MicrocodeConstructor (
+ void
+ );
+/*++
+
+Routine Description:
+
+ Constructor of module Microcode
+
+Arguments:
+
+ None
+
+Returns:
+
+ None
+
+--*/
+
+void
+MicrocodeDestructor (
+ void
+ );
+/*++
+
+Routine Description:
+
+ Destructor of module Microcode
+
+Arguments:
+
+ None
+
+Returns:
+
+ None
+
+--*/
+
+STATUS
+MicrocodeParseFile (
+ char *InFileName,
+ char *OutFileName
+ );
+/*++
+
+Routine Description:
+ Parse a microcode text file, and write the binary results to an output file.
+
+Arguments:
+ InFileName - input text file to parse
+ OutFileName - output file to write raw binary data from parsed input file
+
+Returns:
+ STATUS_SUCCESS - no errors or warnings
+ STATUS_ERROR - errors were encountered
+
+--*/
+
+
+#endif // #ifndef _MICROCODE_H_
diff --git a/Source/FlashMap/Symbols.c b/Source/FlashMap/Symbols.c
new file mode 100644
index 0000000..8e40814
--- /dev/null
+++ b/Source/FlashMap/Symbols.c
@@ -0,0 +1,648 @@
+/*++
+
+Copyright (c) 2004-2006 Intel Corporation. All rights reserved
+This program and the accompanying materials are licensed and made available
+under the terms and conditions of the BSD License which accompanies this
+distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ Symbol.c
+
+Abstract:
+
+ Class-like implementation for a symbol table.
+
+--*/
+
+// GC_TODO: fix comment to set correct module name: Symbols.c
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+//
+// for isspace()
+//
+#include <ctype.h>
+
+#include <Common/UefiBaseTypes.h>
+
+#include "CommonLib.h"
+#include "EfiUtilityMsgs.h"
+#include "Symbols.h"
+
+#define MAX_LINE_LEN 512
+
+//
+// Linked list to keep track of all symbols
+//
+typedef struct _SYMBOL {
+ struct _SYMBOL *Next;
+ int Type;
+ char *Name;
+ char *Value;
+} SYMBOL;
+
+static
+SYMBOL *
+FreeSymbols (
+ SYMBOL *Syms
+ );
+
+static
+int
+ExpandMacros (
+ char *SourceLine,
+ char *DestLine,
+ int LineLen
+ );
+
+static SYMBOL *mSymbolTable = NULL;
+
+void
+SymbolsConstructor (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ None
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+{
+ SymbolsDestructor ();
+}
+
+void
+SymbolsDestructor (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ None
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+{
+ mSymbolTable = FreeSymbols (mSymbolTable);
+}
+
+char *
+GetSymbolValue (
+ char *SymbolName
+ )
+/*++
+
+Routine Description:
+
+ Look up a symbol in our symbol table.
+
+Arguments:
+
+ SymbolName
+
+Returns:
+
+ Pointer to the value of the symbol if found
+ NULL if the symbol is not found
+
+--*/
+// GC_TODO: SymbolName - add argument and description to function comment
+{
+ SYMBOL *Symbol;
+ //
+ // Walk the symbol table
+ //
+ Symbol = mSymbolTable;
+ while (Symbol) {
+ if (stricmp (SymbolName, Symbol->Name) == 0) {
+ return Symbol->Value;
+ }
+
+ Symbol = Symbol->Next;
+ }
+
+ return NULL;
+}
+
+int
+SymbolAdd (
+ char *Name,
+ char *Value,
+ int Mode
+ )
+/*++
+
+Routine Description:
+
+ Add a symbol name/value to the symbol table
+
+Arguments:
+
+ Name - name of symbol to add
+ Value - value of symbol to add
+ Mode - currrently unused
+
+Returns:
+
+ Length of symbol added.
+
+Notes:
+ If Value == NULL, then this routine will assume that the Name field
+ looks something like "MySymName = MySymValue", and will try to parse
+ it that way and add the symbol name/pair from the string.
+
+--*/
+{
+ SYMBOL *Symbol;
+
+ SYMBOL *NewSymbol;
+ int Len;
+ char *Start;
+ char *Cptr;
+ char CSave;
+ char *SaveCptr;
+
+ Len = 0;
+ SaveCptr = NULL;
+ CSave = 0;
+ //
+ // If value pointer is null, then they passed us a line something like:
+ // varname = value, or simply var =
+ //
+ if (Value == NULL) {
+ Start = Name;
+ while (*Name && isspace (*Name)) {
+ Name++;
+ }
+
+ if (Name == NULL) {
+ return -1;
+ }
+ //
+ // Find the end of the name. Either space or a '='.
+ //
+ for (Value = Name; *Value && !isspace (*Value) && (*Value != '='); Value++)
+ ;
+ if (Value == NULL) {
+ return -1;
+ }
+ //
+ // Look for the '='
+ //
+ Cptr = Value;
+ while (*Value && (*Value != '=')) {
+ Value++;
+ }
+
+ if (Value == NULL) {
+ return -1;
+ }
+ //
+ // Now truncate the name
+ //
+ *Cptr = 0;
+ //
+ // Skip over the = and then any spaces
+ //
+ Value++;
+ while (*Value && isspace (*Value)) {
+ Value++;
+
+ }
+ //
+ // Find end of string, checking for quoted string
+ //
+ if (*Value == '\"') {
+ Value++;
+ for (Cptr = Value; *Cptr && *Cptr != '\"'; Cptr++)
+ ;
+ } else {
+ for (Cptr = Value; *Cptr && !isspace (*Cptr); Cptr++)
+ ;
+ }
+ //
+ // Null terminate the value string
+ //
+ CSave = *Cptr;
+ SaveCptr = Cptr;
+ *Cptr = 0;
+ Len = (int) (Cptr - Start);
+ }
+ //
+ // We now have a symbol name and a value. Look for an existing variable
+ // and overwrite it.
+ //
+ Symbol = mSymbolTable;
+ while (Symbol) {
+ //
+ // Check for symbol name match
+ //
+ if (stricmp (Name, Symbol->Name) == 0) {
+ _free (Symbol->Value);
+ Symbol->Value = (char *) _malloc (strlen (Value) + 1);
+ if (Symbol->Value == NULL) {
+ Error (NULL, 0, 0, NULL, "failed to allocate memory");
+ return -1;
+ }
+
+ strcpy (Symbol->Value, Value);
+ //
+ // If value == "NULL", then make it a 0-length string
+ //
+ if (stricmp (Symbol->Value, "NULL") == 0) {
+ Symbol->Value[0] = 0;
+ }
+
+ return Len;
+ }
+
+ Symbol = Symbol->Next;
+ }
+ //
+ // Does not exist, create a new one
+ //
+ NewSymbol = (SYMBOL *) _malloc (sizeof (SYMBOL));
+ if (NewSymbol == NULL) {
+ Error (NULL, 0, 0, NULL, "memory allocation failure");
+ return -1;
+ }
+
+ memset ((char *) NewSymbol, 0, sizeof (SYMBOL));
+ NewSymbol->Name = (char *) _malloc (strlen (Name) + 1);
+ if (NewSymbol->Name == NULL) {
+ Error (NULL, 0, 0, NULL, "memory allocation failure");
+ _free (NewSymbol);
+ return -1;
+ }
+
+ NewSymbol->Value = (char *) _malloc (strlen (Value) + 1);
+ if (NewSymbol->Value == NULL) {
+ Error (NULL, 0, 0, NULL, "memory allocation failure");
+ _free (NewSymbol->Name);
+ _free (NewSymbol);
+ return -1;
+ }
+
+ strcpy (NewSymbol->Name, Name);
+ strcpy (NewSymbol->Value, Value);
+ //
+ // Remove trailing spaces
+ //
+ Cptr = NewSymbol->Value + strlen (NewSymbol->Value) - 1;
+ while (Cptr > NewSymbol->Value) {
+ if (isspace (*Cptr)) {
+ *Cptr = 0;
+ Cptr--;
+ } else {
+ break;
+ }
+ }
+ //
+ // Add it to the head of the list.
+ //
+ NewSymbol->Next = mSymbolTable;
+ mSymbolTable = NewSymbol;
+ //
+ // If value == "NULL", then make it a 0-length string
+ //
+ if (stricmp (NewSymbol->Value, "NULL") == 0) {
+ NewSymbol->Value[0] = 0;
+ }
+ //
+ // Restore the terminator we inserted if they passed in var=value
+ //
+ if (SaveCptr != NULL) {
+ *SaveCptr = CSave;
+ }
+ _free (NewSymbol->Value);
+ _free (NewSymbol->Name);
+ _free (NewSymbol);
+ return Len;
+}
+
+static
+STATUS
+RemoveSymbol (
+ char *Name,
+ char SymbolType
+ )
+/*++
+
+Routine Description:
+
+ Remove a symbol name/value from the symbol table
+
+Arguments:
+
+ Name - name of symbol to remove
+ SymbolType - type of symbol to remove
+
+Returns:
+
+ STATUS_SUCCESS - matching symbol found and removed
+ STATUS_ERROR - matching symbol not found in symbol table
+
+--*/
+{
+ SYMBOL *Symbol;
+
+ SYMBOL *PrevSymbol;
+
+ PrevSymbol = NULL;
+ Symbol = mSymbolTable;
+ //
+ // Walk the linked list of symbols in the symbol table looking
+ // for a match of both symbol name and type.
+ //
+ while (Symbol) {
+ if ((stricmp (Name, Symbol->Name) == 0) && (Symbol->Type & SymbolType)) {
+ //
+ // If the symbol has a value associated with it, free the memory
+ // allocated for the value.
+ // Then free the memory allocated for the symbols string name.
+ //
+ if (Symbol->Value) {
+ _free (Symbol->Value);
+ }
+
+ _free (Symbol->Name);
+ //
+ // Link the previous symbol to the next symbol to effectively
+ // remove this symbol from the linked list.
+ //
+ if (PrevSymbol) {
+ PrevSymbol->Next = Symbol->Next;
+ } else {
+ mSymbolTable = Symbol->Next;
+ }
+
+ _free (Symbol);
+ return STATUS_SUCCESS;
+ }
+
+ PrevSymbol = Symbol;
+ Symbol = Symbol->Next;
+ }
+
+ return STATUS_WARNING;
+}
+
+static
+SYMBOL *
+FreeSymbols (
+ SYMBOL *Syms
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ Syms - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+{
+ SYMBOL *Next;
+ while (Syms) {
+ if (Syms->Name != NULL) {
+ _free (Syms->Name);
+ }
+
+ if (Syms->Value != NULL) {
+ _free (Syms->Value);
+ }
+
+ Next = Syms->Next;
+ _free (Syms);
+ Syms = Next;
+ }
+
+ return Syms;
+}
+
+static
+int
+ExpandMacros (
+ char *SourceLine,
+ char *DestLine,
+ int LineLen
+ )
+/*++
+
+Routine Description:
+
+ Given a line of text, replace all variables of format $(NAME) with values
+ from our symbol table.
+
+Arguments:
+
+ SourceLine - input line of text to do symbol replacements on
+ DestLine - on output, SourceLine with symbols replaced
+ LineLen - length of DestLine, so we don't exceed its allocated length
+
+Returns:
+
+ STATUS_SUCCESS - no problems encountered
+ STATUS_WARNING - missing closing parenthesis on a symbol reference in SourceLine
+ STATUS_ERROR - memory allocation failure
+
+--*/
+{
+ static int NestDepth = 0;
+ char *FromPtr;
+ char *ToPtr;
+ char *SaveStart;
+ char *Cptr;
+ char *value;
+ int Expanded;
+ int ExpandedCount;
+ INT8 *LocalDestLine;
+ STATUS Status;
+ int LocalLineLen;
+
+ NestDepth++;
+ Status = STATUS_SUCCESS;
+ LocalDestLine = (char *) _malloc (LineLen);
+ if (LocalDestLine == NULL) {
+ Error (__FILE__, __LINE__, 0, "memory allocation failed", NULL);
+ return STATUS_ERROR;
+ }
+
+ FromPtr = SourceLine;
+ ToPtr = LocalDestLine;
+ //
+ // Walk the entire line, replacing $(MACRO_NAME).
+ //
+ LocalLineLen = LineLen;
+ ExpandedCount = 0;
+ while (*FromPtr && (LocalLineLen > 0)) {
+ if ((*FromPtr == '$') && (*(FromPtr + 1) == '(')) {
+ //
+ // Save the start in case it's undefined, in which case we copy it as-is.
+ //
+ SaveStart = FromPtr;
+ Expanded = 0;
+ //
+ // Macro expansion time. Find the end (no spaces allowed)
+ //
+ FromPtr += 2;
+ for (Cptr = FromPtr; *Cptr && (*Cptr != ')'); Cptr++)
+ ;
+ if (*Cptr) {
+ //
+ // Truncate the string at the closing parenthesis for ease-of-use.
+ // Then copy the string directly to the destination line in case we don't find
+ // a definition for it.
+ //
+ *Cptr = 0;
+ strcpy (ToPtr, SaveStart);
+ if ((value = GetSymbolValue (FromPtr)) != NULL) {
+ strcpy (ToPtr, value);
+ LocalLineLen -= strlen (value);
+ ToPtr += strlen (value);
+ Expanded = 1;
+ ExpandedCount++;
+ }
+
+ if (!Expanded) {
+ //
+ // Restore closing parenthesis, and advance to next character
+ //
+ *Cptr = ')';
+ FromPtr = SaveStart + 1;
+ ToPtr++;
+ } else {
+ FromPtr = Cptr + 1;
+ }
+ } else {
+ Error (NULL, 0, 0, SourceLine, "missing closing parenthesis on macro");
+ strcpy (ToPtr, FromPtr);
+ Status = STATUS_WARNING;
+ goto Done;
+ }
+ } else {
+ *ToPtr = *FromPtr;
+ FromPtr++;
+ ToPtr++;
+ LocalLineLen--;
+ }
+ }
+
+ if (*FromPtr == 0) {
+ *ToPtr = 0;
+ }
+
+ //
+ // If we expanded at least one string successfully, then make a recursive call to try again.
+ //
+ if ((ExpandedCount != 0) && (Status == STATUS_SUCCESS) && (NestDepth < 10)) {
+ Status = ExpandMacros (LocalDestLine, DestLine, LineLen);
+ _free (LocalDestLine);
+ NestDepth = 0;
+ return Status;
+ }
+
+Done:
+ if (Status != STATUS_ERROR) {
+ strcpy (DestLine, LocalDestLine);
+ }
+
+ NestDepth = 0;
+ _free (LocalDestLine);
+ return Status;
+}
+
+STATUS
+SymbolsFileStringsReplace (
+ char *InFileName,
+ char *OutFileName
+ )
+/*++
+
+Routine Description:
+
+ Given input and output file names, read in the input file, replace variable
+ references of format $(NAME) with appropriate values from our symbol table,
+ and write the result out to the output file.
+
+Arguments:
+
+ InFileName - name of input text file to replace variable references
+ OutFileName - name of output text file to write results to
+
+Returns:
+
+ STATUS_SUCCESS - no problems encountered
+ STATUS_ERROR - failed to open input or output file
+
+--*/
+{
+ STATUS Status;
+ FILE *InFptr;
+ FILE *OutFptr;
+ char Line[MAX_LINE_LEN];
+ char OutLine[MAX_LINE_LEN];
+
+ Status = STATUS_ERROR;
+ //
+ // Open input and output files
+ //
+ InFptr = NULL;
+ OutFptr = NULL;
+ if ((InFptr = fopen (InFileName, "r")) == NULL) {
+ Error (NULL, 0, 0, InFileName, "failed to open input file for reading");
+ goto Done;
+ }
+
+ if ((OutFptr = fopen (OutFileName, "w")) == NULL) {
+ Error (NULL, 0, 0, OutFileName, "failed to open output file for writing");
+ goto Done;
+ }
+ //
+ // Read lines from input file until done
+ //
+ while (fgets (Line, sizeof (Line), InFptr) != NULL) {
+ ExpandMacros (Line, OutLine, sizeof (OutLine));
+ fprintf (OutFptr, OutLine);
+ }
+
+ Status = STATUS_SUCCESS;
+Done:
+ if (InFptr != NULL) {
+ fclose (InFptr);
+ }
+
+ if (OutFptr != NULL) {
+ fclose (OutFptr);
+ }
+
+ return Status;
+}
diff --git a/Source/FlashMap/Symbols.h b/Source/FlashMap/Symbols.h
new file mode 100644
index 0000000..a3cadff
--- /dev/null
+++ b/Source/FlashMap/Symbols.h
@@ -0,0 +1,124 @@
+/*++
+
+Copyright (c) 2004-2006 Intel Corporation. All rights reserved
+This program and the accompanying materials are licensed and made available
+under the terms and conditions of the BSD License which accompanies this
+distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ Symbols.h
+
+Abstract:
+
+ Defines and prototypes for a class-like symbol table service.
+
+--*/
+
+#ifndef _SYMBOLS_H_
+#define _SYMBOLS_H_
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+int
+SymbolAdd (
+ char *Name,
+ char *Value,
+ int Mode
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ Name - GC_TODO: add argument description
+ Value - GC_TODO: add argument description
+ Mode - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+STATUS
+SymbolsFileStringsReplace (
+ char *InFileName,
+ char *OutFileName
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ InFileName - GC_TODO: add argument description
+ OutFileName - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+void
+SymbolsConstructor (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ None
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+void
+SymbolsDestructor (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ None
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // #ifndef _SYMBOLS_H_
diff --git a/Source/FlashMap/build.xml b/Source/FlashMap/build.xml
new file mode 100644
index 0000000..0fc7168
--- /dev/null
+++ b/Source/FlashMap/build.xml
@@ -0,0 +1,75 @@
+<?xml version="1.0" ?>
+<!--
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+-->
+<project default="GenTool" basedir=".">
+<!--
+ EDK FlashMap Tool
+ Copyright (c) 2006, Intel Corporation
+-->
+ <property name="ToolName" value="FlashMap"/>
+ <property name="FileSet" value="*.c"/>
+
+ <taskdef resource="net/sf/antcontrib/antlib.xml"/>
+
+ <property name="LINK_OUTPUT_TYPE" value="static"/>
+ <property name="BUILD_DIR" value="${PACKAGE_DIR}/${ToolName}/tmp"/>
+
+ <target name="GenTool" depends="init, Tool">
+ <echo message="The EDK Tool: ${ToolName} build has completed!"/>
+ </target>
+
+ <target name="init">
+ <echo message="Building the EDK Tool: ${ToolName}"/>
+ <mkdir dir="${BUILD_DIR}"/>
+ </target>
+
+ <target name="Tool" depends="init">
+ <cc name="${ToolChain}" objdir="${BUILD_DIR}"
+ outfile="${BIN_DIR}/${ToolName}"
+ outtype="executable"
+ optimize="speed"
+ debug="true">
+ <compilerarg value="${ExtraArgus}" if="ExtraArgus" />
+
+ <defineset>
+ <define name="_malloc" value="malloc"/>
+ <define name="_free" value="free"/>
+ </defineset>
+
+ <fileset dir="${basedir}/${ToolName}"
+ includes="${FileSet}"
+ defaultexcludes="TRUE"
+ excludes="*.xml *.inf"/>
+
+ <includepath path="${PACKAGE_DIR}/Include"/>
+ <includepath path="${PACKAGE_DIR}/Include/${HostArch}"/>
+ <includepath path="${PACKAGE_DIR}/Common"/>
+ <libset dir="${LIB_DIR}" libs="CommonTools"/>
+ </cc>
+ </target>
+
+ <target name="clean">
+ <echo message="Removing Intermediate Files Only"/>
+ <delete>
+ <fileset dir="${BUILD_DIR}" includes="*.obj"/>
+ </delete>
+ </target>
+
+ <target name="cleanall">
+ <echo message="Removing Object Files and the Executable: ${ToolName}${ext_exe}"/>
+ <delete failonerror="false" quiet="true" includeEmptyDirs="true">
+ <fileset dir="${BUILD_DIR}"/>
+ <fileset file="${BIN_DIR}/${ToolName}${ext_exe}"/>
+ <fileset file="${BIN_DIR}/${ToolName}.pdb"/>
+ </delete>
+ </target>
+
+</project>
diff --git a/Source/FwImage/build.xml b/Source/FwImage/build.xml
new file mode 100644
index 0000000..d992db2
--- /dev/null
+++ b/Source/FwImage/build.xml
@@ -0,0 +1,70 @@
+<?xml version="1.0" ?>
+<!--
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+-->
+<project default="GenTool" basedir=".">
+<!--
+ EDK FwImage Tool
+ Copyright (c) 2006, Intel Corporation
+-->
+ <property name="ToolName" value="FwImage"/>
+ <property name="FileSet" value="fwimage.c"/>
+
+ <taskdef resource="net/sf/antcontrib/antlib.xml"/>
+
+ <property name="LINK_OUTPUT_TYPE" value="static"/>
+ <property name="BUILD_DIR" value="${PACKAGE_DIR}/${ToolName}/tmp"/>
+
+ <target name="GenTool" depends="init, Tool">
+ <echo message="The EDK Tool: ${ToolName} build has completed!"/>
+ </target>
+
+ <target name="init">
+ <echo message="Building the EDK Tool: ${ToolName}"/>
+ <mkdir dir="${BUILD_DIR}"/>
+ </target>
+
+ <target name="Tool" depends="init">
+ <cc name="${ToolChain}" objdir="${BUILD_DIR}"
+ outfile="${BIN_DIR}/${ToolName}"
+ outtype="executable"
+ debug="true"
+ optimize="speed">
+ <compilerarg value="${ExtraArgus}" if="ExtraArgus" />
+
+ <fileset dir="${basedir}/${ToolName}"
+ includes="${FileSet}"
+ defaultexcludes="TRUE"
+ excludes="*.xml *.inf"/>
+
+ <includepath path="${PACKAGE_DIR}/Include"/>
+ <includepath path="${PACKAGE_DIR}/Include/${HostArch}"/>
+ <includepath path="${PACKAGE_DIR}/Common"/>
+ <libset dir="${LIB_DIR}" libs="CommonTools"/>
+ </cc>
+ </target>
+
+ <target name="clean">
+ <echo message="Removing Intermediate Files Only"/>
+ <delete>
+ <fileset dir="${BUILD_DIR}" includes="*.obj"/>
+ </delete>
+ </target>
+
+ <target name="cleanall">
+ <echo message="Removing Object Files and the Executable: ${ToolName}${ext_exe}"/>
+ <delete failonerror="false" quiet="true" includeEmptyDirs="true">
+ <fileset dir="${BUILD_DIR}"/>
+ <fileset file="${BIN_DIR}/${ToolName}${ext_exe}"/>
+ <fileset file="${BIN_DIR}/${ToolName}.pdb"/>
+ </delete>
+ </target>
+
+</project>
diff --git a/Source/FwImage/fwimage.c b/Source/FwImage/fwimage.c
new file mode 100644
index 0000000..5dd1634
--- /dev/null
+++ b/Source/FwImage/fwimage.c
@@ -0,0 +1,510 @@
+/*++
+
+Copyright (c) 2004, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ fwimage.c
+
+Abstract:
+
+ Converts a pe32+ image to an FW image type
+
+--*/
+
+#include "WinNtInclude.h"
+
+#ifndef __GNUC__
+#include <windows.h>
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#include <Common/UefiBaseTypes.h>
+#include <Common/EfiImage.h>
+
+#include "CommonLib.h"
+#include "EfiUtilityMsgs.c"
+
+#define UTILITY_NAME "FwImage"
+
+#ifdef __GNUC__
+typedef unsigned long ULONG;
+typedef unsigned char UCHAR;
+typedef unsigned char *PUCHAR;
+typedef unsigned short USHORT;
+#endif
+
+VOID
+Usage (
+ VOID
+ )
+{
+ printf ("Usage: " UTILITY_NAME " {-t time-date} [BASE|SEC|PEI_CORE|PEIM|DXE_CORE|DXE_DRIVER|DXE_RUNTIME_DRIVER|DXE_SAL_DRIVER|DXE_SMM_DRIVER|TOOL|UEFI_DRIVER|UEFI_APPLICATION|USER_DEFINED] peimage [outimage]");
+}
+
+static
+STATUS
+FCopyFile (
+ FILE *in,
+ FILE *out
+ )
+{
+ ULONG filesize;
+ ULONG offset;
+ ULONG length;
+ UCHAR Buffer[8 * 1024];
+
+ fseek (in, 0, SEEK_END);
+ filesize = ftell (in);
+
+ fseek (in, 0, SEEK_SET);
+ fseek (out, 0, SEEK_SET);
+
+ offset = 0;
+ while (offset < filesize) {
+ length = sizeof (Buffer);
+ if (filesize - offset < length) {
+ length = filesize - offset;
+ }
+
+ fread (Buffer, length, 1, in);
+ fwrite (Buffer, length, 1, out);
+ offset += length;
+ }
+
+ if ((ULONG) ftell (out) != filesize) {
+ Error (NULL, 0, 0, "write error", NULL);
+ return STATUS_ERROR;
+ }
+
+ return STATUS_SUCCESS;
+}
+
+static
+STATUS
+FReadFile (
+ FILE *in,
+ VOID **Buffer,
+ UINTN *Length
+ )
+{
+ fseek (in, 0, SEEK_END);
+ *Length = ftell (in);
+ *Buffer = malloc (*Length);
+ fseek (in, 0, SEEK_SET);
+ fread (*Buffer, *Length, 1, in);
+ return STATUS_SUCCESS;
+}
+
+static
+STATUS
+FWriteFile (
+ FILE *out,
+ VOID *Buffer,
+ UINTN Length
+ )
+{
+ fseek (out, 0, SEEK_SET);
+ fwrite (Buffer, Length, 1, out);
+ if ((ULONG) ftell (out) != Length) {
+ Error (NULL, 0, 0, "write error", NULL);
+ return STATUS_ERROR;
+ }
+ free (Buffer);
+ return STATUS_SUCCESS;
+}
+
+int
+main (
+ int argc,
+ char *argv[]
+ )
+/*++
+
+Routine Description:
+
+ Main function.
+
+Arguments:
+
+ argc - Number of command line parameters.
+ argv - Array of pointers to command line parameter strings.
+
+Returns:
+ STATUS_SUCCESS - Utility exits successfully.
+ STATUS_ERROR - Some error occurred during execution.
+
+--*/
+{
+ ULONG Type;
+ PUCHAR Ext;
+ PUCHAR p;
+ PUCHAR pe;
+ PUCHAR OutImageName;
+ UCHAR outname[500];
+ FILE *fpIn;
+ FILE *fpOut;
+ VOID *ZeroBuffer;
+ EFI_IMAGE_DOS_HEADER *DosHdr;
+ EFI_IMAGE_NT_HEADERS *PeHdr;
+ EFI_IMAGE_OPTIONAL_HEADER32 *Optional32;
+ EFI_IMAGE_OPTIONAL_HEADER64 *Optional64;
+ time_t TimeStamp;
+ struct tm TimeStruct;
+ EFI_IMAGE_DOS_HEADER BackupDosHdr;
+ ULONG Index;
+ ULONG Index1;
+ ULONG Index2;
+ ULONG Index3;
+ BOOLEAN TimeStampPresent;
+ UINTN AllignedRelocSize;
+ UINTN Delta;
+ EFI_IMAGE_SECTION_HEADER *SectionHeader;
+ UINT8 *FileBuffer;
+ UINTN FileLength;
+ RUNTIME_FUNCTION *RuntimeFunction;
+ UNWIND_INFO *UnwindInfo;
+
+ SetUtilityName (UTILITY_NAME);
+ //
+ // Assign to fix compile warning
+ //
+ OutImageName = NULL;
+ Type = 0;
+ Ext = 0;
+ TimeStamp = 0;
+ TimeStampPresent = FALSE;
+
+ //
+ // Look for -t time-date option first. If the time is "0", then
+ // skip it.
+ //
+ if ((argc > 2) && !strcmp (argv[1], "-t")) {
+ TimeStampPresent = TRUE;
+ if (strcmp (argv[2], "0") != 0) {
+ //
+ // Convert the string to a value
+ //
+ memset ((char *) &TimeStruct, 0, sizeof (TimeStruct));
+ if (sscanf(
+ argv[2], "%d/%d/%d,%d:%d:%d",
+ &TimeStruct.tm_mon, /* months since January - [0,11] */
+ &TimeStruct.tm_mday, /* day of the month - [1,31] */
+ &TimeStruct.tm_year, /* years since 1900 */
+ &TimeStruct.tm_hour, /* hours since midnight - [0,23] */
+ &TimeStruct.tm_min, /* minutes after the hour - [0,59] */
+ &TimeStruct.tm_sec /* seconds after the minute - [0,59] */
+ ) != 6) {
+ Error (NULL, 0, 0, argv[2], "failed to convert to mm/dd/yyyy,hh:mm:ss format");
+ return STATUS_ERROR;
+ }
+ //
+ // Now fixup some of the fields
+ //
+ TimeStruct.tm_mon--;
+ TimeStruct.tm_year -= 1900;
+ //
+ // Sanity-check values?
+ // Convert
+ //
+ TimeStamp = mktime (&TimeStruct);
+ if (TimeStamp == (time_t) - 1) {
+ Error (NULL, 0, 0, argv[2], "failed to convert time");
+ return STATUS_ERROR;
+ }
+ }
+ //
+ // Skip over the args
+ //
+ argc -= 2;
+ argv += 2;
+ }
+ //
+ // Check for enough args
+ //
+ if (argc < 3) {
+ Usage ();
+ return STATUS_ERROR;
+ }
+
+ if (argc == 4) {
+ OutImageName = argv[3];
+ }
+ //
+ // Get new image type
+ //
+ p = argv[1];
+ if (*p == '/' || *p == '\\') {
+ p += 1;
+ }
+
+ if (stricmp (p, "app") == 0 || stricmp (p, "UEFI_APPLICATION") == 0) {
+ Type = EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION;
+ Ext = ".efi";
+
+ } else if (stricmp (p, "bsdrv") == 0 || stricmp (p, "DXE_DRIVER") == 0) {
+ Type = EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER;
+ Ext = ".efi";
+
+ } else if (stricmp (p, "rtdrv") == 0 || stricmp (p, "DXE_RUNTIME_DRIVER") == 0) {
+ Type = EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER;
+ Ext = ".efi";
+
+ } else if (stricmp (p, "rtdrv") == 0 || stricmp (p, "DXE_SAL_DRIVER") == 0) {
+ Type = EFI_IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER;
+ Ext = ".efi";
+ } else if (stricmp (p, "SEC") == 0) {
+ Type = EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER;
+ Ext = ".sec";
+ } else if (stricmp (p, "peim") == 0 ||
+ stricmp (p, "BASE") == 0 ||
+ stricmp (p, "PEI_CORE") == 0 ||
+ stricmp (p, "PEIM") == 0 ||
+ stricmp (p, "DXE_SMM_DRIVER") == 0 ||
+ stricmp (p, "TOOL") == 0 ||
+ stricmp (p, "UEFI_APPLICATION") == 0 ||
+ stricmp (p, "USER_DEFINED") == 0 ||
+ stricmp (p, "UEFI_DRIVER") == 0 ||
+ stricmp (p, "DXE_CORE") == 0
+ ) {
+ Type = EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER;
+ Ext = ".pei";
+ } else {
+ printf ("%s", p);
+ Usage ();
+ return STATUS_ERROR;
+ }
+ //
+ // open source file
+ //
+ fpIn = fopen (argv[2], "rb");
+ if (!fpIn) {
+ Error (NULL, 0, 0, argv[2], "failed to open input file for reading");
+ return STATUS_ERROR;
+ }
+
+ FReadFile (fpIn, (VOID **)&FileBuffer, &FileLength);
+
+ //
+ // Read the dos & pe hdrs of the image
+ //
+ DosHdr = (EFI_IMAGE_DOS_HEADER *)FileBuffer;
+ if (DosHdr->e_magic != EFI_IMAGE_DOS_SIGNATURE) {
+ Error (NULL, 0, 0, argv[2], "DOS header signature not found in source image");
+ fclose (fpIn);
+ return STATUS_ERROR;
+ }
+
+ PeHdr = (EFI_IMAGE_NT_HEADERS *)(FileBuffer + DosHdr->e_lfanew);
+ if (PeHdr->Signature != EFI_IMAGE_NT_SIGNATURE) {
+ Error (NULL, 0, 0, argv[2], "PE header signature not found in source image");
+ fclose (fpIn);
+ return STATUS_ERROR;
+ }
+
+ //
+ // open output file
+ //
+ strcpy (outname, argv[2]);
+ pe = NULL;
+ for (p = outname; *p; p++) {
+ if (*p == '.') {
+ pe = p;
+ }
+ }
+
+ if (!pe) {
+ pe = p;
+ }
+
+ strcpy (pe, Ext);
+
+ if (!OutImageName) {
+ OutImageName = outname;
+ }
+
+ fpOut = fopen (OutImageName, "w+b");
+ if (!fpOut) {
+ Error (NULL, 0, 0, OutImageName, "could not open output file for writing");
+ fclose (fpIn);
+ return STATUS_ERROR;
+ }
+
+ //
+ // Zero all unused fields of the DOS header
+ //
+ memcpy (&BackupDosHdr, DosHdr, sizeof (EFI_IMAGE_DOS_HEADER));
+ memset (DosHdr, 0, sizeof (EFI_IMAGE_DOS_HEADER));
+ DosHdr->e_magic = BackupDosHdr.e_magic;
+ DosHdr->e_lfanew = BackupDosHdr.e_lfanew;
+
+ for (Index = sizeof (EFI_IMAGE_DOS_HEADER); Index < (ULONG) DosHdr->e_lfanew; Index++) {
+ FileBuffer[Index] = DosHdr->e_cp;
+ }
+
+ //
+ // Path the PE header
+ //
+ PeHdr->OptionalHeader.Subsystem = (USHORT) Type;
+ if (TimeStampPresent) {
+ PeHdr->FileHeader.TimeDateStamp = (UINT32) TimeStamp;
+ }
+
+ if (PeHdr->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
+ Optional32 = (EFI_IMAGE_OPTIONAL_HEADER32 *)&PeHdr->OptionalHeader;
+ Optional32->MajorLinkerVersion = 0;
+ Optional32->MinorLinkerVersion = 0;
+ Optional32->MajorOperatingSystemVersion = 0;
+ Optional32->MinorOperatingSystemVersion = 0;
+ Optional32->MajorImageVersion = 0;
+ Optional32->MinorImageVersion = 0;
+ Optional32->MajorSubsystemVersion = 0;
+ Optional32->MinorSubsystemVersion = 0;
+ Optional32->Win32VersionValue = 0;
+ Optional32->CheckSum = 0;
+ Optional32->SizeOfStackReserve = 0;
+ Optional32->SizeOfStackCommit = 0;
+ Optional32->SizeOfHeapReserve = 0;
+ Optional32->SizeOfHeapCommit = 0;
+
+ //
+ // Strip zero padding at the end of the .reloc section
+ //
+ if (Optional32->NumberOfRvaAndSizes >= 6) {
+ if (Optional32->DataDirectory[5].Size != 0) {
+ SectionHeader = (EFI_IMAGE_SECTION_HEADER *)(FileBuffer + DosHdr->e_lfanew + sizeof(UINT32) + sizeof (EFI_IMAGE_FILE_HEADER) + PeHdr->FileHeader.SizeOfOptionalHeader);
+ for (Index = 0; Index < PeHdr->FileHeader.NumberOfSections; Index++, SectionHeader++) {
+ //
+ // Look for the Section Header that starts as the same virtual address as the Base Relocation Data Directory
+ //
+ if (SectionHeader->VirtualAddress == Optional32->DataDirectory[5].VirtualAddress) {
+ SectionHeader->Misc.VirtualSize = Optional32->DataDirectory[5].Size;
+ AllignedRelocSize = (Optional32->DataDirectory[5].Size + Optional32->FileAlignment - 1) & (~(Optional32->FileAlignment - 1));
+ //
+ // Check to see if there is zero padding at the end of the base relocations
+ //
+ if (AllignedRelocSize < SectionHeader->SizeOfRawData) {
+ //
+ // Check to see if the base relocations are at the end of the file
+ //
+ if (SectionHeader->PointerToRawData + SectionHeader->SizeOfRawData == Optional32->SizeOfImage) {
+ //
+ // All the required conditions are met to strip the zero padding of the end of the base relocations section
+ //
+ Optional32->SizeOfImage -= (SectionHeader->SizeOfRawData - AllignedRelocSize);
+ Optional32->SizeOfInitializedData -= (SectionHeader->SizeOfRawData - AllignedRelocSize);
+ SectionHeader->SizeOfRawData = AllignedRelocSize;
+ FileLength = Optional32->SizeOfImage;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ if (PeHdr->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
+ Optional64 = (EFI_IMAGE_OPTIONAL_HEADER64 *)&PeHdr->OptionalHeader;
+ Optional64->MajorLinkerVersion = 0;
+ Optional64->MinorLinkerVersion = 0;
+ Optional64->MajorOperatingSystemVersion = 0;
+ Optional64->MinorOperatingSystemVersion = 0;
+ Optional64->MajorImageVersion = 0;
+ Optional64->MinorImageVersion = 0;
+ Optional64->MajorSubsystemVersion = 0;
+ Optional64->MinorSubsystemVersion = 0;
+ Optional64->Win32VersionValue = 0;
+ Optional64->CheckSum = 0;
+ Optional64->SizeOfStackReserve = 0;
+ Optional64->SizeOfStackCommit = 0;
+ Optional64->SizeOfHeapReserve = 0;
+ Optional64->SizeOfHeapCommit = 0;
+
+ //
+ // Zero the .pdata section if the machine type is X64 and the Debug Directory is empty
+ //
+ if (PeHdr->FileHeader.Machine == 0x8664) { // X64
+ if (Optional64->NumberOfRvaAndSizes >= 4) {
+ if (Optional64->NumberOfRvaAndSizes < 7 || (Optional64->NumberOfRvaAndSizes >= 7 && Optional64->DataDirectory[6].Size == 0)) {
+ SectionHeader = (EFI_IMAGE_SECTION_HEADER *)(FileBuffer + DosHdr->e_lfanew + sizeof(UINT32) + sizeof (EFI_IMAGE_FILE_HEADER) + PeHdr->FileHeader.SizeOfOptionalHeader);
+ for (Index = 0; Index < PeHdr->FileHeader.NumberOfSections; Index++, SectionHeader++) {
+ if (SectionHeader->VirtualAddress == Optional64->DataDirectory[3].VirtualAddress) {
+ RuntimeFunction = (RUNTIME_FUNCTION *)(FileBuffer + SectionHeader->PointerToRawData);
+ for (Index1 = 0; Index1 < Optional64->DataDirectory[3].Size / sizeof (RUNTIME_FUNCTION); Index1++, RuntimeFunction++) {
+ SectionHeader = (EFI_IMAGE_SECTION_HEADER *)(FileBuffer + DosHdr->e_lfanew + sizeof(UINT32) + sizeof (EFI_IMAGE_FILE_HEADER) + PeHdr->FileHeader.SizeOfOptionalHeader);
+ for (Index2 = 0; Index2 < PeHdr->FileHeader.NumberOfSections; Index2++, SectionHeader++) {
+ if (RuntimeFunction->UnwindInfoAddress > SectionHeader->VirtualAddress && RuntimeFunction->UnwindInfoAddress < (SectionHeader->VirtualAddress + SectionHeader->SizeOfRawData)) {
+ UnwindInfo = (UNWIND_INFO *)(FileBuffer + SectionHeader->PointerToRawData + (RuntimeFunction->UnwindInfoAddress - SectionHeader->VirtualAddress));
+ if (UnwindInfo->Version == 1) {
+ memset (UnwindInfo + 1, 0, UnwindInfo->CountOfUnwindCodes * sizeof (UINT16));
+ memset (UnwindInfo, 0, sizeof (UNWIND_INFO));
+ }
+ }
+ }
+ memset (RuntimeFunction, 0, sizeof (RUNTIME_FUNCTION));
+ }
+ }
+ }
+ Optional64->DataDirectory[3].Size = 0;
+ Optional64->DataDirectory[3].VirtualAddress = 0;
+ }
+ }
+ }
+
+ //
+ // Strip zero padding at the end of the .reloc section
+ //
+ if (Optional64->NumberOfRvaAndSizes >= 6) {
+ if (Optional64->DataDirectory[5].Size != 0) {
+ SectionHeader = (EFI_IMAGE_SECTION_HEADER *)(FileBuffer + DosHdr->e_lfanew + sizeof(UINT32) + sizeof (EFI_IMAGE_FILE_HEADER) + PeHdr->FileHeader.SizeOfOptionalHeader);
+ for (Index = 0; Index < PeHdr->FileHeader.NumberOfSections; Index++, SectionHeader++) {
+ //
+ // Look for the Section Header that starts as the same virtual address as the Base Relocation Data Directory
+ //
+ if (SectionHeader->VirtualAddress == Optional64->DataDirectory[5].VirtualAddress) {
+ SectionHeader->Misc.VirtualSize = Optional64->DataDirectory[5].Size;
+ AllignedRelocSize = (Optional64->DataDirectory[5].Size + Optional64->FileAlignment - 1) & (~(Optional64->FileAlignment - 1));
+ //
+ // Check to see if there is zero padding at the end of the base relocations
+ //
+ if (AllignedRelocSize < SectionHeader->SizeOfRawData) {
+ //
+ // Check to see if the base relocations are at the end of the file
+ //
+ if (SectionHeader->PointerToRawData + SectionHeader->SizeOfRawData == Optional64->SizeOfImage) {
+ //
+ // All the required conditions are met to strip the zero padding of the end of the base relocations section
+ //
+ Optional64->SizeOfImage -= (SectionHeader->SizeOfRawData - AllignedRelocSize);
+ Optional64->SizeOfInitializedData -= (SectionHeader->SizeOfRawData - AllignedRelocSize);
+ SectionHeader->SizeOfRawData = AllignedRelocSize;
+ FileLength = Optional64->SizeOfImage;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ FWriteFile (fpOut, FileBuffer, FileLength);
+
+ //
+ // Done
+ //
+ fclose (fpIn);
+ fclose (fpOut);
+ //
+ // printf ("Created %s\n", OutImageName);
+ //
+ return STATUS_SUCCESS;
+}
diff --git a/Source/GenAcpiTable/GenAcpiTable.c b/Source/GenAcpiTable/GenAcpiTable.c
new file mode 100644
index 0000000..7a413ea
--- /dev/null
+++ b/Source/GenAcpiTable/GenAcpiTable.c
@@ -0,0 +1,544 @@
+/*++
+
+Copyright (c) 2004-2006 Intel Corporation. All rights reserved
+This program and the accompanying materials are licensed and made available
+under the terms and conditions of the BSD License which accompanies this
+distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ GenAcpiTable.c
+
+Abstract:
+
+ A utility that extracts the .DATA section from a PE/COFF image.
+
+--*/
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <Common/UefiBaseTypes.h>
+#include <Common/EfiImage.h> // for PE32 structure definitions
+
+#include "CommonLib.h"
+#include "EfiUtilityMsgs.h"
+
+//
+// Version of this utility
+//
+#define UTILITY_NAME "GenAcpiTable"
+#define UTILITY_VERSION "v0.11"
+
+//
+// Define the max length of a filename
+//
+#define MAX_PATH 256
+#define DEFAULT_OUTPUT_EXTENSION ".acpi"
+
+//
+// Use this to track our command-line options and globals
+//
+struct {
+ INT8 OutFileName[MAX_PATH];
+ INT8 InFileName[MAX_PATH];
+} mOptions;
+
+//
+// Use these to convert from machine type value to a named type
+//
+typedef struct {
+ UINT16 Value;
+ INT8 *Name;
+} STRING_LOOKUP;
+
+static STRING_LOOKUP mMachineTypes[] = {
+ EFI_IMAGE_MACHINE_IA32,
+ "IA32",
+ EFI_IMAGE_MACHINE_IA64,
+ "IA64",
+ EFI_IMAGE_MACHINE_EBC,
+ "EBC",
+ 0,
+ NULL
+};
+
+static STRING_LOOKUP mSubsystemTypes[] = {
+ EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION,
+ "EFI application",
+ EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER,
+ "EFI boot service driver",
+ EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER,
+ "EFI runtime driver",
+ 0,
+ NULL
+};
+//
+// Function prototypes
+//
+static
+void
+Usage (
+ VOID
+ );
+
+static
+STATUS
+ParseCommandLine (
+ int Argc,
+ char *Argv[]
+ );
+
+static
+STATUS
+CheckPE32File (
+ INT8 *FileName,
+ FILE *Fptr,
+ UINT16 *MachineType,
+ UINT16 *SubSystem
+ );
+
+static
+STATUS
+ProcessFile (
+ INT8 *InFileName,
+ INT8 *OutFileName
+ );
+
+static
+void
+DumpImage (
+ INT8 *FileName
+ );
+
+main (
+ int Argc,
+ char *Argv[]
+ )
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+ Argc - standard C main() argument count
+
+ Argv - standard C main() argument list
+
+Returns:
+
+ 0 success
+ non-zero otherwise
+
+--*/
+// GC_TODO: ] - add argument and description to function comment
+{
+ UINT32 Status;
+
+ SetUtilityName (UTILITY_NAME);
+ //
+ // Parse the command line arguments
+ //
+ if (ParseCommandLine (Argc, Argv)) {
+ return STATUS_ERROR;
+ }
+ //
+ // Make sure we don't have the same filename for input and output files
+ //
+ if (stricmp (mOptions.OutFileName, mOptions.InFileName) == 0) {
+ Error (NULL, 0, 0, mOptions.OutFileName, "input and output file names must be different");
+ goto Finish;
+ }
+ //
+ // Process the file
+ //
+ ProcessFile (mOptions.InFileName, mOptions.OutFileName);
+Finish:
+ Status = GetUtilityStatus ();
+ return Status;
+}
+
+static
+STATUS
+ProcessFile (
+ INT8 *InFileName,
+ INT8 *OutFileName
+ )
+/*++
+
+Routine Description:
+
+ Process a PE32 EFI file.
+
+Arguments:
+
+ InFileName - Name of the PE32 EFI file to process.
+ OutFileName - Name of the output file for the processed data.
+
+Returns:
+
+ 0 - successful
+
+--*/
+{
+ STATUS Status;
+ UINTN Index;
+ FILE *InFptr;
+ FILE *OutFptr;
+ UINT16 MachineType;
+ UINT16 SubSystem;
+ UINT32 PESigOffset;
+ EFI_IMAGE_FILE_HEADER FileHeader;
+ EFI_IMAGE_OPTIONAL_HEADER32 OptionalHeader32;
+ EFI_IMAGE_OPTIONAL_HEADER64 OptionalHeader64;
+ EFI_IMAGE_SECTION_HEADER SectionHeader;
+ UINT8 *Buffer;
+ long SaveFilePosition;
+
+ InFptr = NULL;
+ OutFptr = NULL;
+ Buffer = NULL;
+ Status = STATUS_ERROR;
+ //
+ // Try to open the input file
+ //
+ if ((InFptr = fopen (InFileName, "rb")) == NULL) {
+ Error (NULL, 0, 0, InFileName, "failed to open input file for reading");
+ return STATUS_ERROR;
+ }
+ //
+ // Double-check the file to make sure it's what we expect it to be
+ //
+ if (CheckPE32File (InFileName, InFptr, &MachineType, &SubSystem) != STATUS_SUCCESS) {
+ goto Finish;
+ }
+ //
+ // Per the PE/COFF specification, at offset 0x3C in the file is a 32-bit
+ // offset (from the start of the file) to the PE signature, which always
+ // follows the MSDOS stub. The PE signature is immediately followed by the
+ // COFF file header.
+ //
+ //
+ if (fseek (InFptr, 0x3C, SEEK_SET) != 0) {
+ Error (NULL, 0, 0, InFileName, "failed to seek to PE signature in file", NULL);
+ goto Finish;
+ }
+
+ if (fread (&PESigOffset, sizeof (PESigOffset), 1, InFptr) != 1) {
+ Error (NULL, 0, 0, InFileName, "failed to read PE signature offset from file");
+ goto Finish;
+ }
+
+ if (fseek (InFptr, PESigOffset + 4, SEEK_SET) != 0) {
+ Error (NULL, 0, 0, InFileName, "failed to seek to PE signature");
+ goto Finish;
+ }
+ //
+ // We should now be at the COFF file header. Read it in and verify it's
+ // of an image type we support.
+ //
+ if (fread (&FileHeader, sizeof (EFI_IMAGE_FILE_HEADER), 1, InFptr) != 1) {
+ Error (NULL, 0, 0, InFileName, "failed to read file header from image");
+ goto Finish;
+ }
+
+ if ((FileHeader.Machine != EFI_IMAGE_MACHINE_IA32) && (FileHeader.Machine != EFI_IMAGE_MACHINE_IA64) && (FileHeader.Machine != EFI_IMAGE_MACHINE_X64)) {
+ Error (NULL, 0, 0, InFileName, "image is of an unsupported machine type 0x%X", (UINT32) FileHeader.Machine);
+ goto Finish;
+ }
+ //
+ // Read in the optional header. Assume PE32, and if not, then re-read as PE32+
+ //
+ SaveFilePosition = ftell (InFptr);
+ if (fread (&OptionalHeader32, sizeof (EFI_IMAGE_OPTIONAL_HEADER32), 1, InFptr) != 1) {
+ Error (NULL, 0, 0, InFileName, "failed to read optional header from input file");
+ goto Finish;
+ }
+
+ if (OptionalHeader32.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
+ if (fseek (InFptr, SaveFilePosition, SEEK_SET) != 0) {
+ Error (NULL, 0, 0, InFileName, "failed to seek to .data section");
+ goto Finish;
+ }
+
+ if (fread (&OptionalHeader64, sizeof (EFI_IMAGE_OPTIONAL_HEADER64), 1, InFptr) != 1) {
+ Error (NULL, 0, 0, InFileName, "failed to read optional header from input file");
+ goto Finish;
+ }
+ }
+ //
+ // Search for the ".data" section
+ //
+ for (Index = 0; Index < FileHeader.NumberOfSections; Index++) {
+ if (fread (&SectionHeader, sizeof (EFI_IMAGE_SECTION_HEADER), 1, InFptr) != 1) {
+ Error (NULL, 0, 0, InFileName, "failed to read optional header from input file");
+ goto Finish;
+ }
+
+ if (strcmp (SectionHeader.Name, ".data") == 0) {
+ if (fseek (InFptr, SectionHeader.PointerToRawData, SEEK_SET) != 0) {
+ Error (NULL, 0, 0, InFileName, "failed to seek to .data section");
+ goto Finish;
+ }
+
+ Buffer = (UINT8 *) malloc (SectionHeader.Misc.VirtualSize);
+ if (Buffer == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Finish;
+ }
+ if (fread (Buffer, SectionHeader.Misc.VirtualSize, 1, InFptr) != 1) {
+ Error (NULL, 0, 0, InFileName, "failed to .data section");
+ goto Finish;
+ }
+ //
+ // Now open our output file
+ //
+ if ((OutFptr = fopen (OutFileName, "wb")) == NULL) {
+ Error (NULL, 0, 0, OutFileName, "failed to open output file for writing");
+ goto Finish;
+ }
+
+ if (fwrite (Buffer, SectionHeader.Misc.VirtualSize, 1, OutFptr) != 1) {
+ Error (NULL, 0, 0, OutFileName, "failed to write .data section");
+ goto Finish;
+ }
+
+ Status = STATUS_SUCCESS;
+ goto Finish;
+ }
+ }
+
+ Status = STATUS_ERROR;
+
+Finish:
+ if (InFptr != NULL) {
+ fclose (InFptr);
+ }
+ //
+ // Close the output file. If there was an error, delete the output file so
+ // that a subsequent build will rebuild it.
+ //
+ if (OutFptr != NULL) {
+ fclose (OutFptr);
+ if (GetUtilityStatus () == STATUS_ERROR) {
+ remove (OutFileName);
+ }
+ }
+
+ //
+ // Free up our buffer
+ //
+ if (Buffer != NULL) {
+ free (Buffer);
+ }
+
+ return Status;
+}
+
+static
+STATUS
+CheckPE32File (
+ INT8 *FileName,
+ FILE *Fptr,
+ UINT16 *MachineType,
+ UINT16 *SubSystem
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ FileName - GC_TODO: add argument description
+ Fptr - GC_TODO: add argument description
+ MachineType - GC_TODO: add argument description
+ SubSystem - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+{
+ /*++
+
+Routine Description:
+
+ Given a file pointer to a supposed PE32 image file, verify that it is indeed a
+ PE32 image file, and then return the machine type in the supplied pointer.
+
+Arguments:
+
+ Fptr File pointer to the already-opened PE32 file
+ MachineType Location to stuff the machine type of the PE32 file. This is needed
+ because the image may be Itanium-based, IA32, or EBC.
+
+Returns:
+
+ 0 success
+ non-zero otherwise
+
+--*/
+ EFI_IMAGE_DOS_HEADER DosHeader;
+ EFI_IMAGE_FILE_HEADER FileHdr;
+ EFI_IMAGE_OPTIONAL_HEADER OptionalHdr;
+ UINT32 PESig;
+ STATUS Status;
+
+ Status = STATUS_ERROR;
+ //
+ // Position to the start of the file
+ //
+ fseek (Fptr, 0, SEEK_SET);
+ //
+ // Read the DOS header
+ //
+ if (fread (&DosHeader, sizeof (DosHeader), 1, Fptr) != 1) {
+ Error (NULL, 0, 0, FileName, "failed to read the DOS stub from the input file");
+ goto Finish;
+ }
+ //
+ // Check the magic number (0x5A4D)
+ //
+ if (DosHeader.e_magic != EFI_IMAGE_DOS_SIGNATURE) {
+ Error (NULL, 0, 0, FileName, "input file does not appear to be a PE32 image (magic number)");
+ goto Finish;
+ }
+ //
+ // Position into the file and check the PE signature
+ //
+ fseek (Fptr, (long) DosHeader.e_lfanew, SEEK_SET);
+ if (fread (&PESig, sizeof (PESig), 1, Fptr) != 1) {
+ Error (NULL, 0, 0, FileName, "failed to read PE signature bytes");
+ goto Finish;
+ }
+ //
+ // Check the PE signature in the header "PE\0\0"
+ //
+ if (PESig != EFI_IMAGE_NT_SIGNATURE) {
+ Error (NULL, 0, 0, FileName, "file does not appear to be a PE32 image (signature)");
+ goto Finish;
+ }
+ //
+ // Read the file header
+ //
+ if (fread (&FileHdr, sizeof (FileHdr), 1, Fptr) != 1) {
+ Error (NULL, 0, 0, FileName, "failed to read PE file header from input file");
+ goto Finish;
+ }
+ //
+ // Read the optional header so we can get the subsystem
+ //
+ if (fread (&OptionalHdr, sizeof (OptionalHdr), 1, Fptr) != 1) {
+ Error (NULL, 0, 0, FileName, "failed to read COFF optional header from input file");
+ goto Finish;
+ }
+
+ *SubSystem = OptionalHdr.Subsystem;
+ //
+ // Good to go
+ //
+ Status = STATUS_SUCCESS;
+Finish:
+ fseek (Fptr, 0, SEEK_SET);
+ return Status;
+}
+
+static
+int
+ParseCommandLine (
+ int Argc,
+ char *Argv[]
+ )
+/*++
+
+Routine Description:
+
+ Given the Argc/Argv program arguments, and a pointer to an options structure,
+ parse the command-line options and check their validity.
+
+
+Arguments:
+
+ Argc - standard C main() argument count
+ Argv - standard C main() argument list
+
+Returns:
+
+ STATUS_SUCCESS success
+ non-zero otherwise
+
+--*/
+// GC_TODO: ] - add argument and description to function comment
+{
+ //
+ // Clear out the options
+ //
+ memset ((char *) &mOptions, 0, sizeof (mOptions));
+ //
+ // Skip over the program name
+ //
+ Argc--;
+ Argv++;
+
+ if (Argc != 2) {
+ Usage ();
+ return STATUS_ERROR;
+ }
+
+ strcpy (mOptions.InFileName, Argv[0]);
+ //
+ // Next argument
+ //
+ Argv++;
+ Argc--;
+
+ strcpy (mOptions.OutFileName, Argv[0]);
+
+ return STATUS_SUCCESS;
+}
+
+static
+void
+Usage (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Print usage information for this utility.
+
+Arguments:
+
+ None.
+
+Returns:
+
+ Nothing.
+
+--*/
+{
+ int Index;
+ static const char *Msg[] = {
+ UTILITY_NAME " version "UTILITY_VERSION " - Generate ACPI Table image utility",
+ " Generate an ACPI Table image from an EFI PE32 image",
+ " Usage: "UTILITY_NAME " InFileName OutFileName",
+ " where:",
+ " InFileName - name of the input PE32 file",
+ " OutFileName - to write output to OutFileName rather than InFileName"DEFAULT_OUTPUT_EXTENSION,
+ "",
+ NULL
+ };
+ for (Index = 0; Msg[Index] != NULL; Index++) {
+ fprintf (stdout, "%s\n", Msg[Index]);
+ }
+}
diff --git a/Source/GenAcpiTable/build.xml b/Source/GenAcpiTable/build.xml
new file mode 100644
index 0000000..a60871b
--- /dev/null
+++ b/Source/GenAcpiTable/build.xml
@@ -0,0 +1,70 @@
+<?xml version="1.0" ?>
+<!--
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+-->
+<project default="GenTool" basedir=".">
+<!--
+ EDK GenAcpiTable Tool
+ Copyright (c) 2006, Intel Corporation
+-->
+ <property name="ToolName" value="GenAcpiTable"/>
+ <property name="FileSet" value="*.c"/>
+
+ <taskdef resource="net/sf/antcontrib/antlib.xml"/>
+
+ <property name="LINK_OUTPUT_TYPE" value="static"/>
+ <property name="BUILD_DIR" value="${PACKAGE_DIR}/${ToolName}/tmp"/>
+
+ <target name="GenTool" depends="init, Tool">
+ <echo message="The EDK Tool: ${ToolName} build has completed!"/>
+ </target>
+
+ <target name="init">
+ <echo message="Building the EDK Tool: ${ToolName}"/>
+ <mkdir dir="${BUILD_DIR}"/>
+ </target>
+
+ <target name="Tool" depends="init">
+ <cc name="${ToolChain}" objdir="${BUILD_DIR}"
+ outfile="${BIN_DIR}/${ToolName}"
+ outtype="executable"
+ optimize="speed"
+ debug="true">
+ <compilerarg value="${ExtraArgus}" if="ExtraArgus" />
+
+ <fileset dir="${basedir}/${ToolName}"
+ includes="${FileSet}"
+ defaultexcludes="TRUE"
+ excludes="*.xml *.inf"/>
+
+ <includepath path="${PACKAGE_DIR}/Include"/>
+ <includepath path="${PACKAGE_DIR}/Include/Ia32"/>
+ <includepath path="${PACKAGE_DIR}/Common"/>
+ <libset dir="${LIB_DIR}" libs="CommonTools"/>
+ </cc>
+ </target>
+
+ <target name="clean">
+ <echo message="Removing Intermediate Files Only"/>
+ <delete>
+ <fileset dir="${BUILD_DIR}" includes="*.obj"/>
+ </delete>
+ </target>
+
+ <target name="cleanall">
+ <echo message="Removing Object Files and the Executable: ${ToolName}${ext_exe}"/>
+ <delete failonerror="false" quiet="true" includeEmptyDirs="true">
+ <fileset dir="${BUILD_DIR}"/>
+ <fileset file="${BIN_DIR}/${ToolName}${ext_exe}"/>
+ <fileset file="${BIN_DIR}/${ToolName}.pdb"/>
+ </delete>
+ </target>
+
+</project>
diff --git a/Source/GenBsfFixup/GenBsfFixup.c b/Source/GenBsfFixup/GenBsfFixup.c
new file mode 100644
index 0000000..462f97f
--- /dev/null
+++ b/Source/GenBsfFixup/GenBsfFixup.c
@@ -0,0 +1,490 @@
+/*++
+
+Copyright (c) 1999 - 2002 Intel Corporation. All rights reserved
+This software and associated documentation (if any) is furnished
+under a license and may only be used or copied in accordance
+with the terms of the license. Except as permitted by such
+license, no part of this software or documentation may be
+reproduced, stored in a retrieval system, or transmitted in any
+form or by any means without the express written consent of
+Intel Corporation.
+
+
+Module Name:
+
+ GenBsfFixup.c
+
+Abstract:
+
+ Utility to Fixup the SEC component for IA32. This is an
+ interim tool in place of the full GenBsfImage support for
+ IA32.
+ This tool supports the Synch3 update
+
+--*/
+
+#include "BaseTypes.h"
+#include "UefiBaseTypes.h"
+#include "EfiImage.h"
+#include "FirmwareVolumeHeader.h"
+#include "FirmwareVolumeImageFormat.h"
+#include "ParseInf.h"
+#include "CommonLib.h"
+#include "FirmwareFileSystem.h"
+#include "FvLib.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+//
+// BugBug -- this port to the new FFS is really weird.
+// A lot of the file-header stuff has been ported, but
+// not the section information.
+//
+#define TOOLVERSION "0.1"
+
+UINT32 gFixup;
+
+UINT32
+GetOccupiedSize (
+ IN UINT32 ActualSize,
+ IN UINT32 Alignment
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ ActualSize - GC_TODO: add argument description
+ Alignment - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+{
+ UINT32 OccupiedSize;
+
+ OccupiedSize = ActualSize;
+ while ((OccupiedSize & (Alignment - 1)) != 0) {
+ OccupiedSize++;
+ }
+
+ return OccupiedSize;
+}
+
+int
+ReadHeader (
+ FILE *In,
+ UINT32 *FvSize
+ )
+/*++
+
+Routine Description:
+
+ Reads in Firmware Volume information from the volume header file.
+
+Arguments:
+
+ In: Firmware Volume header file to read from
+ FvSize: Size of Firmware Volume
+
+Returns:
+
+ int: Number of bytes read
+
+--*/
+{
+ EFI_FIRMWARE_VOLUME_HEADER VolumeHeader;
+ EFI_FV_BLOCK_MAP_ENTRY BlockMap;
+ INT32 SigTemp[2];
+ INT32 Invert;
+ INT32 bytesread;
+ UINT32 size;
+
+ size = 0;
+ Invert = 0;
+ bytesread = 0;
+
+ if (In == NULL) {
+ printf ("Error: Input file is NULL.\n");
+ return -1;
+ }
+
+ fread (&VolumeHeader, sizeof (EFI_FIRMWARE_VOLUME_HEADER) - sizeof (EFI_FV_BLOCK_MAP_ENTRY), 1, In);
+ bytesread = sizeof (EFI_FIRMWARE_VOLUME_HEADER) - sizeof (EFI_FV_BLOCK_MAP_ENTRY);
+ SigTemp[0] = VolumeHeader.Signature;
+ SigTemp[1] = 0;
+
+ if (VolumeHeader.Attributes & EFI_FVB_ERASE_POLARITY) {
+ Invert = 1;
+ }
+
+ do {
+ fread (&BlockMap, sizeof (EFI_FV_BLOCK_MAP_ENTRY), 1, In);
+ bytesread += sizeof (EFI_FV_BLOCK_MAP_ENTRY);
+
+ if (BlockMap.NumBlocks != 0) {
+ size += BlockMap.NumBlocks * BlockMap.BlockLength;
+ }
+
+ } while (BlockMap.NumBlocks != 0);
+
+ *FvSize = size;
+ rewind (In);
+
+ if (Invert == 1) {
+ bytesread *= -1;
+ }
+
+ return bytesread;
+}
+
+UINT32
+GetSectionLength (
+ IN UINT32 *Length
+ )
+/*++
+
+Routine Description:
+
+ Converts a UINT8[3] array to a UINT32
+
+Arguments:
+
+ Length A pointer to a 3 byte array
+
+Returns:
+
+ UINT32: The length.
+
+--*/
+{
+ return *Length & 0x00FFFFFF;
+}
+
+int
+Readfile (
+ UINT8 *FvImage,
+ int bytes,
+ int Invert
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ FvImage - GC_TODO: add argument description
+ bytes - GC_TODO: add argument description
+ Invert - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+{
+ UINT32 FileLength;
+ UINT32 OccupiedFileLength;
+ EFI_FFS_FILE_HEADER *FileHeader;
+ UINT8 FileState;
+ UINT8 Checksum;
+ UINT8 *Ptr;
+ UINT32 SectionLength;
+ EFI_COMMON_SECTION_HEADER *SectionHeader;
+ EFI_IMAGE_NT_HEADERS *PeHeader;
+ UINT32 PeiCoreOffset;
+
+ Ptr = FvImage + bytes;
+
+ FileHeader = (EFI_FFS_FILE_HEADER *) Ptr;
+
+ FileState = GetFileState ((UINT8) Invert, FileHeader);
+
+ switch (FileState) {
+ case EFI_FILE_HEADER_CONSTRUCTION:
+ case EFI_FILE_HEADER_INVALID:
+ return sizeof (EFI_FFS_FILE_HEADER);
+
+ case EFI_FILE_HEADER_VALID:
+ Checksum = CalculateSum8 ((UINT8 *) FileHeader, sizeof (EFI_FFS_FILE_HEADER));
+ Checksum = (UINT8) (Checksum - FileHeader->IntegrityCheck.Checksum.File);
+ Checksum = (UINT8) (Checksum - FileHeader->State);
+ if (Checksum != 0) {
+ return -1;
+ }
+ //
+ // Now do the fixup stuff - begin
+ //
+ if (FileHeader->Type == EFI_FV_FILETYPE_PEI_CORE) {
+ SectionHeader = (EFI_COMMON_SECTION_HEADER *) FileHeader + sizeof (EFI_FFS_FILE_HEADER);
+ SectionLength = GetSectionLength ((UINT32 *) &SectionHeader->Size[0]);
+
+ printf ("Section length is 0x%X\n", SectionLength);
+
+ if (SectionHeader->Type == EFI_SECTION_PE32) {
+
+ gFixup = bytes + sizeof (EFI_FFS_FILE_HEADER) + sizeof (EFI_COMMON_SECTION_HEADER);
+
+ PeHeader = (EFI_IMAGE_NT_HEADERS *) Ptr + sizeof (EFI_FFS_FILE_HEADER) + sizeof (EFI_COMMON_SECTION_HEADER);
+
+ if (((EFI_IMAGE_DOS_HEADER *) PeHeader)->e_magic == EFI_IMAGE_DOS_SIGNATURE) {
+ //
+ // DOS image header is present, so read the PE header after the DOS image header
+ //
+ PeHeader = (EFI_IMAGE_NT_HEADERS *) ((UINTN) PeHeader + (UINTN) ((((EFI_IMAGE_DOS_HEADER *) PeHeader)->e_lfanew) & 0x0ffff));
+
+ }
+
+ PeiCoreOffset = (UINTN) ((UINTN) (PeHeader->OptionalHeader.AddressOfEntryPoint & 0x0ffffffff));
+
+ gFixup += PeiCoreOffset;
+ }
+ }
+
+ FileLength = GetLength (FileHeader->Size);
+ OccupiedFileLength = GetOccupiedSize (FileLength, 8);
+ return OccupiedFileLength;
+
+ case EFI_FILE_DATA_VALID:
+ //
+ // Calculate header checksum
+ //
+ Checksum = CalculateSum8 ((UINT8 *) FileHeader, sizeof (EFI_FFS_FILE_HEADER));
+ Checksum = (UINT8) (Checksum - FileHeader->IntegrityCheck.Checksum.File);
+ Checksum = (UINT8) (Checksum - FileHeader->State);
+ if (Checksum != 0) {
+ return -1;
+ }
+ //
+ // Determine file length
+ //
+ FileLength = GetLength (FileHeader->Size);
+ OccupiedFileLength = GetOccupiedSize (FileLength, 8);
+
+ //
+ // Determine if file checksum is valid or fixed
+ //
+ if (FileHeader->Attributes & FFS_ATTRIB_CHECKSUM) {
+ Checksum = CalculateSum8 (Ptr, FileLength);
+ Checksum = (UINT8) (Checksum - FileHeader->State);
+ if (Checksum != 0) {
+ return -1;
+ }
+ } else {
+ if (FileHeader->IntegrityCheck.Checksum.File != FFS_FIXED_CHECKSUM) {
+ return -1;
+ }
+ }
+ break;
+
+ case EFI_FILE_MARKED_FOR_UPDATE:
+ case EFI_FILE_DELETED:
+ //
+ // Calculate header checksum
+ //
+ Checksum = CalculateSum8 ((UINT8 *) FileHeader, sizeof (EFI_FFS_FILE_HEADER));
+ Checksum = (UINT8) (Checksum - FileHeader->IntegrityCheck.Checksum.File);
+ Checksum = (UINT8) (Checksum - FileHeader->State);
+ if (Checksum != 0) {
+ return -1;
+ }
+ //
+ // Determine file length
+ //
+ FileLength = GetLength (FileHeader->Size);
+ OccupiedFileLength = GetOccupiedSize (FileLength, 8);
+
+ //
+ // Determine if file checksum is valid or fixed
+ //
+ if (FileHeader->Attributes & FFS_ATTRIB_CHECKSUM) {
+ Checksum = CalculateSum8 (Ptr, FileLength);
+ Checksum = (UINT8) (Checksum - FileHeader->State);
+ if (Checksum != 0) {
+ return -1;
+ }
+ } else {
+ if (FileHeader->IntegrityCheck.Checksum.File != FFS_FIXED_CHECKSUM) {
+ return -1;
+ }
+ }
+
+ return OccupiedFileLength;
+
+ default:
+ return sizeof (EFI_FFS_FILE_HEADER);
+ }
+
+ return OccupiedFileLength;
+}
+
+int
+main (
+ int argc,
+ char*argv[]
+ )
+/*++
+
+Routine Description:
+
+ Runs GenBsfFixup
+
+Arguments:
+
+ argc: number of command line arguments
+
+ arg[0] = This file name
+ arg[1] = Firmware Volume Name
+ arg[2] = Base Address to relocate
+ arg[3] = Relative offset of the fixup to perform
+ arg[4] = Output File Name
+
+Returns:
+
+ int: 0 code success, -1 code failure
+
+--*/
+{
+ FILE *In;
+ FILE *Out;
+ int ByteStart;
+ int Invert;
+ int Index;
+ int cnt;
+ UINT8 *FvImage;
+ int ByteRead;
+ UINT32 FvSize;
+ UINT64 delta;
+ UINT32 Idx;
+ UINT64 FvOffset;
+ EFI_STATUS Status;
+
+ Index = 0;
+ Invert = 0;
+ printf (
+ "GenBsfFixup EFI 2.0. Version %s, %s\n""Copyright (c) 2000-2001, Intel Corporation\n\n",
+ TOOLVERSION,
+ __DATE__
+ );
+
+ if (argc != 5) {
+ printf ("Usage:\n"" GenBsfFixup FvVolumeImageFile AddressOfFvInMemory OffsetOfFixup OutputFileName\n");
+ return -1;
+ }
+
+ In = fopen (argv[1], "rb");
+
+ if (In == NULL) {
+ printf ("Unable to open FV image file \"%s\"\n", argv[1]);
+ return -1;
+ }
+
+ ByteStart = ReadHeader (In, &FvSize);
+
+ if (ByteStart < 0) {
+ Invert = 1;
+ ByteStart *= -1;
+ }
+
+ FvImage = malloc (FvSize);
+ if (FvImage == NULL) {
+ printf ("Cannot allocate memory\n");
+ fclose (In);
+ return -1;
+ }
+
+ ByteRead = fread (FvImage, 1, FvSize, In);
+
+ if ((unsigned int) ByteRead != FvSize) {
+ printf ("Read File error\n");
+ fclose (In);
+ return -1;
+ }
+
+ cnt = 0;
+ while ((unsigned int) ByteStart < FvSize && cnt != -1) {
+ cnt = Readfile (FvImage, ByteStart, Invert);
+
+ if (cnt != -1) {
+ ByteStart += cnt;
+ }
+
+ if (cnt != sizeof (EFI_FFS_FILE_HEADER)) {
+ Index++;
+ }
+ }
+
+ if (cnt == -1) {
+ printf ("Firmware Volume image corrupted\n");
+ return -1;
+ }
+
+ fclose (In);
+
+ Out = fopen (argv[4], "wb");
+
+ if (Out == NULL) {
+ printf ("Unable to open FV image file \"%s\"\n", argv[4]);
+ return -1;
+ }
+
+ In = fopen (argv[1], "rb");
+
+ if (In == NULL) {
+ printf ("Unable to open FV image file \"%s\"\n", argv[1]);
+ return -1;
+ }
+
+ if (gFixup != 0) {
+
+ printf ("Fixup of 0x%X\n", gFixup);
+
+ Status = AsciiStringToUint64 (argv[2], TRUE, &FvOffset);
+
+ gFixup += (UINT32) FvOffset;
+
+ ByteStart = ReadHeader (In, &FvSize);
+
+ Readfile (FvImage, ByteStart, Invert);
+
+ cnt = 0;
+ Status = AsciiStringToUint64 (argv[3], TRUE, &delta);
+
+ fclose (In);
+ In = fopen (argv[1], "rb");
+
+ if (In == NULL) {
+ printf ("Unable to open FV image file \"%s\"\n", argv[1]);
+ return -1;
+ }
+
+ for (Idx = 0; Idx < delta - FvOffset; Idx++) {
+ fputc (fgetc (In), Out);
+ }
+
+ fwrite (&gFixup, sizeof (UINT32), 1, Out);
+ fseek (In, sizeof (UINT32), SEEK_CUR);
+
+ for (Idx = 0; Idx < FvSize - (delta - FvOffset) - sizeof (UINT32); Idx++) {
+ fputc (fgetc (In), Out);
+ }
+
+ fclose (In);
+ fclose (Out);
+ } else {
+ printf ("There was no fixup to perform\n");
+ }
+
+ free (FvImage);
+
+ return 0;
+}
diff --git a/Source/GenBsfFixup/build.xml b/Source/GenBsfFixup/build.xml
new file mode 100644
index 0000000..1f35cf2
--- /dev/null
+++ b/Source/GenBsfFixup/build.xml
@@ -0,0 +1,127 @@
+<?xml version="1.0" ?>
+<!--
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+-->
+<project default="GenTool" basedir=".">
+<!--
+ EDK GenFvImage Tool
+ Copyright (c) 2006, Intel Corporation
+-->
+ <property name="ToolName" value="GenBsfFixup"/>
+ <property name="FileSet" value="GenBsfFixup.c"/>
+
+ <taskdef resource="net/sf/antcontrib/antlib.xml"/>
+
+ <property name="LINK_OUTPUT_TYPE" value="static"/>
+ <property name="BUILD_DIR" value="${PACKAGE_DIR}/${ToolName}/tmp"/>
+
+ <target name="GenTool" depends="init, Tool">
+ <echo message="The EDK Tool: ${ToolName} build has completed"/>
+ </target>
+
+ <target name="init">
+ <echo message="Building the EDK Tool: ${ToolName}"/>
+ <mkdir dir="${BUILD_DIR}"/>
+ <if>
+ <istrue value="${OSX}"/>
+ <then>
+ <property name="syslibdirs" value=""/>
+ <property name="syslibs" value=""/>
+ </then>
+ </if>
+
+ <if>
+ <istrue value="${cygwin}"/>
+ <then>
+ <property name="syslibdirs" value="${env.CYGWIN_HOME}/lib/e2fsprogs"/>
+ <property name="syslibs" value="uuid"/>
+ </then>
+ </if>
+
+ <if>
+ <istrue value="${msft}"/>
+ <then>
+ <property name="syslibdirs" value=""/>
+ <property name="syslibs" value="uuid"/>
+ </then>
+ </if>
+
+ <if>
+ <istrue value="${linux}"/>
+ <then>
+ <if>
+ <istrue value="${x86_64_linux}"/>
+ <then>
+ <property name="syslibdirs" value="/lib64"/>
+ </then>
+ <else>
+ <property name="syslibdirs" value="/usr/lib"/>
+ </else>
+ </if>
+ <property name="syslibs" value="uuid"/>
+ </then>
+ </if>
+ <echo message="syslibdirs set to: ${syslibdirs}"/>
+ </target>
+
+ <target name="Tool" depends="init, GenBsfFixup"/>
+
+ <target name="GenBsfFixup" >
+ <cc name="${ToolChain}" objdir="${BUILD_DIR}"
+ outfile="${BIN_DIR}/${ToolName}"
+ outtype="executable"
+ debug="true"
+ optimize="speed">
+ <compilerarg value="${ExtraArgus}" if="ExtraArgus" />
+
+ <defineset>
+ <define name="BUILDING_TOOLS"/>
+ <define name="TOOL_BUILD_IA32_TARGET"/>
+ </defineset>
+
+ <fileset dir="${basedir}/${ToolName}"
+ includes="${FileSet}"/>
+
+ <includepath path="${PACKAGE_DIR}/${ToolName}"/>
+ <includepath path="${PACKAGE_DIR}/Include"/>
+ <includepath path="${PACKAGE_DIR}/Include/Common"/>
+ <includepath path="${PACKAGE_DIR}/Include/${HostArch}"/>
+ <includepath path="${PACKAGE_DIR}/Common"/>
+ <libset dir="${LIB_DIR}" libs="CommonTools"/>
+
+ <linkerarg value="/nodefaultlib:libc.lib" if="msft"/>
+ <syslibset dir="${syslibdirs}" libs="${syslibs}" if="cyglinux"/>
+ <syslibset libs="RpcRT4" if="msft"/>
+ </cc>
+ </target>
+
+ <target name="clean">
+ <echo message="Removing Intermediate Files Only"/>
+ <delete>
+ <fileset dir="${BUILD_DIR}" includes="*.obj"/>
+ </delete>
+ </target>
+
+ <target name="cleanall">
+ <echo message="Removing Object Files and the Executable: ${ToolName}${ext_exe}"/>
+ <delete failonerror="false" quiet="true" includeEmptyDirs="true">
+ <fileset dir="${BUILD_DIR}"/>
+ <fileset file="${BIN_DIR}/${ToolName}_Ia32${ext_exe}"/>
+ <fileset file="${BIN_DIR}/${ToolName}_X64${ext_exe}"/>
+ <fileset file="${BIN_DIR}/${ToolName}${ext_exe}"/>
+ <fileset file="${BIN_DIR}/${ToolName}_Ipf${ext_exe}"/>
+ <fileset file="${BIN_DIR}/${ToolName}_Ia32.pdb"/>
+ <fileset file="${BIN_DIR}/${ToolName}_X64.pdb"/>
+ <fileset file="${BIN_DIR}/${ToolName}.pdb"/>
+ <fileset file="${BIN_DIR}/${ToolName}_Ipf.pdb"/>
+ </delete>
+ </target>
+
+</project>
diff --git a/Source/GenBsfImage/GenBsfImage.c b/Source/GenBsfImage/GenBsfImage.c
new file mode 100644
index 0000000..59d20d0
--- /dev/null
+++ b/Source/GenBsfImage/GenBsfImage.c
@@ -0,0 +1,3519 @@
+/*++
+
+Copyright (c) 1999 - 2006, Intel Corporation. All rights reserved
+This software and associated documentation (if any) is furnished
+under a license and may only be used or copied in accordance
+with the terms of the license. Except as permitted by such
+license, no part of this software or documentation may be
+reproduced, stored in a retrieval system, or transmitted in any
+form or by any means without the express written consent of
+Intel Corporation.
+
+
+Module Name:
+
+ GenBsfImage.c
+
+Abstract:
+
+ This file contains functions required to generate a boot strap file (BSF)
+ also known as the Volume Top File (VTF)
+
+--*/
+
+//
+// Module Coded to EFI 2.0 Coding Conventions
+//
+#include <FvLib.h>
+#include <Common/UefiBaseTypes.h>
+#include "GenBsfImage.h"
+#include <Guid/FirmwareFileSystem.h>
+#include "CommonLib.h"
+
+//
+// Global variables
+//
+EFI_GUID Bsf1NameGuid = EFI_IPF_VTF1_GUID
+EFI_GUID Bsf2NameGuid = EFI_IPF_VTF2_GUID
+
+CHAR8 **TokenStr;
+CHAR8 **OrgStrTokPtr;
+
+PARSED_BSF_INFO *FileListPtr;
+PARSED_BSF_INFO *FileListHeadPtr;
+
+VOID *Bsf1Buffer;
+VOID *Bsf1EndBuffer;
+VOID *Bsf2Buffer;
+VOID *Bsf2EndBuffer;
+
+UINTN ValidLineNum = 0;
+UINTN ValidFFDFileListNum = 0;
+
+//
+// Section Description and their number of occurences in *.INF file
+//
+UINTN NumFvFiles = 0;
+UINTN SectionOptionNum = 0;
+
+//
+// Global flag which will check for BSF Present, if yes then will be used
+// to decide about adding FFS header to pad data
+//
+BOOLEAN BSFPresent = FALSE;
+
+//
+// Address related information
+//
+UINT64 Fv1BaseAddress = 0;
+UINT64 Fv2BaseAddress = 0;
+UINT64 Fv1EndAddress = 0;
+UINT64 Fv2EndAddress = 0;
+UINT32 Bsf1TotalSize = SIZE_TO_OFFSET_PAL_A_END;
+UINT64 Bsf1LastStartAddress = 0;
+UINT32 Bsf2TotalSize = 0;
+UINT64 Bsf2LastStartAddress = 0;
+
+UINT32 BufferToTop = 0;
+
+//
+// IA32 Reset Vector Bin name
+//
+CHAR8 IA32BinFile[FILE_NAME_SIZE];
+
+//
+// Function Implementations
+//
+VOID
+BuildTokenList (
+ IN CHAR8 *Token
+ )
+/*++
+Routine Description:
+
+ This function builds the token list in an array which will be parsed later
+
+Arguments:
+
+ Token - The pointer of string
+
+Returns:
+
+ None
+
+--*/
+{
+ strcpy (*TokenStr, Token);
+ TokenStr++;
+}
+
+EFI_STATUS
+ConvertVersionInfo (
+ IN CHAR8 *Str,
+ IN OUT UINT8 *MajorVer,
+ IN OUT UINT8 *MinorVer
+ )
+/*++
+Routine Description:
+
+ This function converts GUID string to GUID
+
+Arguments:
+
+ Str - String representing in form XX.XX
+ MajorVer - The major vertion
+ MinorVer - The minor vertion
+
+Returns:
+
+ EFI_SUCCESS - The fuction completed successfully.
+
+--*/
+{
+ CHAR8 StrPtr[40];
+ CHAR8 *Token;
+ UINTN Length;
+ UINTN Major;
+ UINTN Minor;
+
+ Major = 0;
+ Minor = 0;
+ memset (StrPtr, 0, 40);
+ Token = strtok (Str, ".");
+
+ while (Token != NULL) {
+ strcat (StrPtr, Token);
+ Token = strtok (NULL, ".");
+ }
+
+ Length = strlen (StrPtr);
+ sscanf (
+ StrPtr,
+ "%01x%02x",
+ &Major,
+ &Minor
+ );
+
+ *MajorVer = (UINT8) Major;
+ *MinorVer = (UINT8) Minor;
+ return EFI_SUCCESS;
+}
+
+VOID
+TrimLine (
+ IN CHAR8 *Line
+ )
+/*++
+Routine Description:
+
+ This function cleans up the line by removing all whitespace and
+ comments
+
+Arguments:
+
+ Line - The pointer of the string
+
+Returns:
+
+ None
+
+--*/
+{
+ CHAR8 TmpLine[FILE_NAME_SIZE];
+ CHAR8 Char;
+ CHAR8 *Ptr0;
+ UINTN Index;
+ UINTN Index2;
+
+ //
+ // Change '#' to '//' for Comment style
+ //
+ if (((Ptr0 = strchr (Line, '#')) != NULL) || ((Ptr0 = strstr (Line, "//")) != NULL)) {
+ Line[Ptr0 - Line] = 0;
+ }
+
+ //
+ // Initialize counters
+ //
+ Index = 0;
+ Index2 = 0;
+
+ while ((Char = Line[Index]) != 0) {
+ if ((Char != ' ') && (Char != '\t') && (Char != '\n')) {
+ TmpLine[Index2++] = Char;
+ }
+ Index++;
+ }
+
+ TmpLine[Index2] = 0;
+ strcpy (Line, TmpLine);
+}
+
+VOID
+ValidLineCount (
+ IN FILE *Fp
+ )
+/*++
+
+Routine Description:
+
+ This function calculated number of valid lines in a input file.
+
+Arguments:
+
+ Fp - Pointer to a file handle which has been opened.
+
+Returns:
+
+ None
+
+--*/
+{
+ CHAR8 Buff[FILE_NAME_SIZE];
+
+ while (fgets (Buff, sizeof (Buff), Fp)) {
+ TrimLine (Buff);
+ if (Buff[0] == 0) {
+ continue;
+ }
+
+ ValidLineNum++;
+ }
+}
+
+VOID
+ParseInputFile (
+ IN FILE *Fp
+ )
+/*++
+
+Routine Description:
+
+ This function parses the input file and tokenize the string
+
+Arguments:
+
+ Fp - Pointer to a file handle which has been opened.
+
+Returns:
+
+ None
+
+--*/
+{
+ CHAR8 *Token;
+ CHAR8 Buff[FILE_NAME_SIZE];
+ CHAR8 OrgLine[FILE_NAME_SIZE];
+ CHAR8 Str[FILE_NAME_SIZE];
+ CHAR8 Delimit[] = "=";
+
+ while (fgets (Buff, sizeof (Buff), Fp) != NULL) {
+ strcpy (OrgLine, Buff);
+ TrimLine (Buff);
+ if (Buff[0] == 0) {
+ continue;
+ }
+
+ Token = strtok (Buff, Delimit);
+
+ while (Token != NULL) {
+ strcpy (Str, Token);
+ BuildTokenList (Str);
+ Token = strtok (NULL, Delimit);
+ }
+ }
+}
+
+EFI_STATUS
+InitializeComps (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function intializes the relevant global variable which is being
+ used to store the information retrieved from INF file. This also initializes
+ the BSF symbol file.
+
+Arguments:
+
+ None
+
+Returns:
+
+ EFI_SUCCESS - The function completed successfully
+ EFI_OUT_OF_RESOURCES - Malloc failed.
+
+--*/
+{
+
+ FileListPtr = malloc (sizeof (PARSED_BSF_INFO));
+
+ if (FileListPtr == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ FileListHeadPtr = FileListPtr;
+ memset (FileListPtr, 0, sizeof (PARSED_BSF_INFO));
+ FileListPtr->NextBsfInfo = NULL;
+
+ remove (BSF_SYM_FILE);
+ return EFI_SUCCESS;
+}
+
+VOID
+ParseAndUpdateComponents (
+ IN PARSED_BSF_INFO *BsfInfo
+ )
+/*++
+
+Routine Description:
+
+ This function intializes the relevant global variable which is being
+ used to store the information retrieved from INF file.
+
+Arguments:
+
+ BsfInfo - A pointer to the BSF Info Structure
+
+
+Returns:
+
+ None
+
+--*/
+{
+ UINT64 StringValue;
+
+ while (*TokenStr != NULL && (_stricmp (*TokenStr, "COMP_NAME") != 0)) {
+
+ if (_stricmp (*TokenStr, "COMP_LOC") == 0) {
+ TokenStr++;
+ if (_stricmp (*TokenStr, "F") == 0) {
+ BsfInfo->LocationType = FIRST_VTF;
+ } else if (_stricmp (*TokenStr, "S") == 0) {
+ BsfInfo->LocationType = SECOND_VTF;
+ } else {
+ BsfInfo->LocationType = NONE;
+ printf ("\nERROR: Unknown location for component %s", BsfInfo->CompName);
+ }
+ } else if (_stricmp (*TokenStr, "COMP_TYPE") == 0) {
+ TokenStr++;
+ if (AsciiStringToUint64 (*TokenStr, FALSE, &StringValue) != EFI_SUCCESS) {
+ printf ("\nERROR: Could not read a numeric value from \"%s\".", TokenStr);
+ return ;
+ }
+
+ BsfInfo->CompType = (UINT8) StringValue;
+ } else if (_stricmp (*TokenStr, "COMP_VER") == 0) {
+ TokenStr++;
+ if (_stricmp (*TokenStr, "-") == 0) {
+ BsfInfo->VersionPresent = FALSE;
+ BsfInfo->MajorVer = 0;
+ BsfInfo->MinorVer = 0;
+ } else {
+ BsfInfo->VersionPresent = TRUE;
+ ConvertVersionInfo (*TokenStr, &BsfInfo->MajorVer, &BsfInfo->MinorVer);
+ }
+ } else if (_stricmp (*TokenStr, "COMP_BIN") == 0) {
+ TokenStr++;
+ strcpy (BsfInfo->CompBinName, *TokenStr);
+ } else if (_stricmp (*TokenStr, "COMP_SYM") == 0) {
+ TokenStr++;
+ strcpy (BsfInfo->CompSymName, *TokenStr);
+ } else if (_stricmp (*TokenStr, "COMP_SIZE") == 0) {
+ TokenStr++;
+ if (_stricmp (*TokenStr, "-") == 0) {
+ BsfInfo->PreferredSize = FALSE;
+ BsfInfo->CompSize = 0;
+ } else {
+ BsfInfo->PreferredSize = TRUE;
+ if (AsciiStringToUint64 (*TokenStr, FALSE, &StringValue) != EFI_SUCCESS) {
+ printf ("\nERROR: Could not read a numeric value from \"%s\".", TokenStr);
+ return ;
+ }
+
+ BsfInfo->CompSize = (UINTN) StringValue;
+ }
+
+ } else if (_stricmp (*TokenStr, "COMP_CS") == 0) {
+ TokenStr++;
+ if (_stricmp (*TokenStr, "1") == 0) {
+ BsfInfo->CheckSumRequired = 1;
+ } else if (_stricmp (*TokenStr, "0") == 0) {
+ BsfInfo->CheckSumRequired = 0;
+ } else {
+ printf ("\nERROR: Bad information in INF file about Checksum required field");
+ }
+ }
+
+ TokenStr++;
+ if (*TokenStr == NULL) {
+ break;
+ }
+ }
+}
+
+VOID
+InitializeInFileInfo (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function intializes the relevant global variable which is being
+ used to store the information retrieved from INF file.
+
+Arguments:
+
+ NONE
+
+Returns:
+
+ NONE
+
+--*/
+{
+ UINTN SectionOptionFlag;
+ UINTN SectionCompFlag;
+
+ SectionOptionFlag = 0;
+ SectionCompFlag = 0;
+ TokenStr = OrgStrTokPtr;
+ while (*TokenStr != NULL) {
+ if (_stricmp (*TokenStr, "[OPTIONS]") == 0) {
+ SectionOptionFlag = 1;
+ SectionCompFlag = 0;
+ }
+
+ if (_stricmp (*TokenStr, "[COMPONENTS]") == 0) {
+ if (FileListPtr == NULL) {
+ FileListPtr = FileListHeadPtr;
+ }
+
+ SectionCompFlag = 1;
+ SectionOptionFlag = 0;
+ TokenStr++;
+ }
+
+ if (SectionOptionFlag) {
+ if (_stricmp (*TokenStr, "IA32_RST_BIN") == 0) {
+ *TokenStr++;
+ strcpy (IA32BinFile, *TokenStr);
+ }
+ }
+
+ if (SectionCompFlag) {
+ if (_stricmp (*TokenStr, "COMP_NAME") == 0) {
+ TokenStr++;
+ strcpy (FileListPtr->CompName, *TokenStr);
+ TokenStr++;
+ ParseAndUpdateComponents (FileListPtr);
+ }
+
+ if (*TokenStr != NULL) {
+ FileListPtr->NextBsfInfo = malloc (sizeof (PARSED_BSF_INFO));
+ if (FileListPtr->NextBsfInfo == NULL) {
+ printf ("Error: Out of memory resources.\n");
+ break;
+ }
+ FileListPtr = FileListPtr->NextBsfInfo;
+ memset (FileListPtr, 0, sizeof (PARSED_BSF_INFO));
+ FileListPtr->NextBsfInfo = NULL;
+ continue;
+ } else {
+ break;
+ }
+ }
+
+ TokenStr++;
+ }
+}
+
+EFI_STATUS
+GetBsfRelatedInfoFromInfFile (
+ IN CHAR8 *FileName
+ )
+/*++
+
+Routine Description:
+
+ This function reads the input file, parse it and create a list of tokens
+ which is parsed and used, to intialize the data related to BSF
+
+Arguments:
+
+ FileName - FileName which needed to be read to parse data
+
+Returns:
+
+ EFI_ABORTED - Error in opening file
+ EFI_INVALID_PARAMETER - File doesn't contain any valid informations
+ EFI_OUT_OF_RESOURCES - Malloc Failed
+ EFI_SUCCESS - The function completed successfully
+
+--*/
+{
+ FILE *Fp;
+ UINTN Index;
+ EFI_STATUS Status;
+
+ Fp = fopen (FileName, "r");
+ if (Fp == NULL) {
+ printf ("\nERROR: Error in opening %s file\n", FileName);
+ return EFI_ABORTED;
+ }
+
+ ValidLineCount (Fp);
+
+ if (ValidLineNum == 0) {
+ printf ("\nERROR: File doesn't contain any valid informations");
+ return EFI_INVALID_PARAMETER;
+ }
+
+ TokenStr = (CHAR8 **) malloc (sizeof (UINTN) * (2 * ValidLineNum + 1));
+
+ if (TokenStr == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ memset (TokenStr, 0, (sizeof (UINTN) * (2 * ValidLineNum + 1)));
+ OrgStrTokPtr = TokenStr;
+
+ for (Index = 0; Index < (2 * ValidLineNum); Index++) {
+ *TokenStr = (CHAR8*)malloc (sizeof (CHAR8) * FILE_NAME_SIZE);
+
+ if (*TokenStr == NULL) {
+ free (OrgStrTokPtr);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ memset (*TokenStr, 0, FILE_NAME_SIZE);
+// free (*TokenStr);
+ TokenStr++;
+ }
+
+ TokenStr = NULL;
+ TokenStr = OrgStrTokPtr;
+ fseek (Fp, 0L, SEEK_SET);
+
+ Status = InitializeComps ();
+
+ if (Status != EFI_SUCCESS) {
+ free (OrgStrTokPtr);
+ return Status;
+ }
+
+ ParseInputFile (Fp);
+ InitializeInFileInfo ();
+
+ if (Fp) {
+ fclose (Fp);
+ }
+ free (OrgStrTokPtr);
+ return EFI_SUCCESS;
+}
+
+VOID
+GetRelativeAddressInBsfBuffer (
+ IN UINT64 Address,
+ IN OUT UINTN *RelativeAddress,
+ IN LOC_TYPE LocType
+ )
+/*++
+
+Routine Description:
+
+ This function checks for the address alignmnet for specified data boundary. In
+ case the address is not aligned, it returns FALSE and the amount of data in
+ terms of byte needed to adjust to get the boundary alignmnet. If data is
+ aligned, TRUE will be returned.
+
+Arguments:
+
+ Address - The address of the flash map space
+ RelativeAddress - The relative address of the Buffer
+ LocType - The type of the BSF
+
+
+Returns:
+
+
+--*/
+{
+ UINT64 TempAddress;
+ UINT8 *LocalBuff;
+
+ if (LocType == FIRST_VTF) {
+ LocalBuff = (UINT8 *) Bsf1EndBuffer;
+ TempAddress = Fv1EndAddress - Address;
+ *RelativeAddress = (UINTN) LocalBuff - (UINTN) TempAddress;
+ } else {
+ LocalBuff = (UINT8 *) Bsf2EndBuffer;
+ TempAddress = Fv2EndAddress - Address;
+ *RelativeAddress = (UINTN) LocalBuff - (UINTN) TempAddress;
+ }
+}
+
+EFI_STATUS
+GetComponentVersionInfo (
+ IN OUT PARSED_BSF_INFO *BsfInfo,
+ IN UINT8 *Buffer
+ )
+/*++
+Routine Description:
+
+ This function will extract the version information from File
+
+Arguments:
+
+ BsfInfo - A Pointer to the BSF Info Structure
+ Buffer - A Pointer to type UINT8
+
+Returns:
+
+ EFI_SUCCESS - The function completed successfully
+ EFI_INVALID_PARAMETER - The parameter is invalid
+
+--*/
+{
+ UINT16 VersionInfo;
+ EFI_STATUS Status;
+
+ switch (BsfInfo->CompType) {
+
+ case COMP_TYPE_FIT_PAL_A:
+ case COMP_TYPE_FIT_PAL_B:
+ memcpy (&VersionInfo, (Buffer + 8), sizeof (UINT16));
+ BsfInfo->MajorVer = (UINT8) ((VersionInfo & 0xFF00) >> 8);
+ BsfInfo->MinorVer = (UINT8) (VersionInfo & 0x00FF);
+ Status = EFI_SUCCESS;
+ break;
+
+ default:
+ Status = EFI_INVALID_PARAMETER;
+ break;
+ }
+
+ return Status;
+}
+
+BOOLEAN
+CheckAddressAlignment (
+ IN UINT64 Address,
+ IN UINT64 AlignmentData,
+ IN OUT UINT64 *AlignAdjustByte
+ )
+/*++
+
+Routine Description:
+
+ This function checks for the address alignmnet for specified data boundary. In
+ case the address is not aligned, it returns FALSE and the amount of data in
+ terms of byte needed to adjust to get the boundary alignmnet. If data is
+ aligned, TRUE will be returned.
+
+Arguments:
+
+ Address - Pointer to buffer containing byte data of component.
+ AlignmentData - DataSize for which address needed to be aligned
+ AlignAdjustByte - Number of bytes needed to adjust alignment.
+
+Returns:
+
+ TRUE - Address is aligned to specific data size boundary
+ FALSE - Address in not aligned to specified data size boundary
+ - Add/Subtract AlignAdjustByte to aling the address.
+
+--*/
+{
+ //
+ // Check if the assigned address is on address boundary. If not, it will
+ // return the remaining byte required to adjust the address for specified
+ // address boundary
+ //
+ *AlignAdjustByte = (Address % AlignmentData);
+
+ if (*AlignAdjustByte == 0) {
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
+EFI_STATUS
+GetFitTableStartAddress (
+ IN OUT FIT_TABLE **FitTable
+ )
+/*++
+
+Routine Description:
+
+ Get the FIT table start address in BSF Buffer
+
+Arguments:
+
+ FitTable - Pointer to available fit table where new component can be added
+
+Returns:
+
+ EFI_SUCCESS - The function completed successfully
+
+--*/
+{
+ UINT64 FitTableAdd;
+ UINT64 FitTableAddOffset;
+ UINTN RelativeAddress;
+
+ //
+ // Read the Fit Table address from Itanium-based address map.
+ //
+ FitTableAddOffset = Fv1EndAddress - (SIZE_IA32_RESET_VECT + SIZE_SALE_ENTRY_POINT + SIZE_FIT_TABLE_ADD);
+
+ //
+ // Translate this Itanium-based address in terms of local buffer address which
+ // contains the image for Boot Strapped File. The relative address will be
+ // the address of fit table BSF buffer.
+ //
+ GetRelativeAddressInBsfBuffer (FitTableAddOffset, &RelativeAddress, FIRST_VTF);
+ FitTableAdd = *(UINTN *) RelativeAddress;
+
+ //
+ // The FitTableAdd is the extracted Itanium based address pointing to FIT
+ // table. The relative address will return its actual location in BSF
+ // Buffer.
+ //
+ GetRelativeAddressInBsfBuffer (FitTableAdd, &RelativeAddress, FIRST_VTF);
+
+ *FitTable = (FIT_TABLE *) RelativeAddress;
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+GetNextAvailableFitPtr (
+ IN FIT_TABLE **FitPtr
+ )
+/*++
+
+Routine Description:
+
+ Get the FIT table address and locate the free space in fit where we can add
+ new component. In this process, this function locates the fit table using
+ Fit pointer in Itanium-based address map (as per Intel?Itanium(TM) SAL spec)
+ and locate the available location in FIT table to be used by new components.
+ If there are any Fit table which areg not being used contains ComponentType
+ field as 0x7F. If needed we can change this and spec this out.
+
+Arguments:
+
+ FitPtr - Pointer to available fit table where new component can be added
+
+Returns:
+
+ EFI_SUCCESS - The function completed successfully
+
+--*/
+{
+ FIT_TABLE *TmpFitPtr;
+ UINT64 FitTableAdd;
+ UINT64 FitTableAddOffset;
+ UINTN Index;
+ UINTN NumFitComponents;
+ UINTN RelativeAddress;
+
+ //
+ // Read the Fit Table address from Itanium-based address map.
+ //
+ FitTableAddOffset = Fv1EndAddress - (SIZE_IA32_RESET_VECT + SIZE_SALE_ENTRY_POINT + SIZE_FIT_TABLE_ADD);
+
+ //
+ // Translate this Itanium-based address in terms of local buffer address which
+ // contains the image for Boot Strapped File. The relative address will be
+ // the address of fit table BSF buffer.
+ //
+ GetRelativeAddressInBsfBuffer (FitTableAddOffset, &RelativeAddress, FIRST_VTF);
+ FitTableAdd = *(UINTN *) RelativeAddress;
+
+ //
+ // The FitTableAdd is the extracted Itanium based address pointing to FIT
+ // table. The relative address will return its actual location in BSF
+ // Buffer.
+ //
+ GetRelativeAddressInBsfBuffer (FitTableAdd, &RelativeAddress, FIRST_VTF);
+
+ TmpFitPtr = (FIT_TABLE *) RelativeAddress;
+ NumFitComponents = TmpFitPtr->CompSize;
+
+ for (Index = 0; Index < NumFitComponents; Index++) {
+ if ((TmpFitPtr->CvAndType & FIT_TYPE_MASK) == COMP_TYPE_FIT_UNUSED) {
+ *FitPtr = TmpFitPtr;
+ break;
+ }
+
+ TmpFitPtr++;
+ }
+
+ return EFI_SUCCESS;
+}
+
+INTN
+CompareItems (
+ IN const VOID *Arg1,
+ IN const VOID *Arg2
+ )
+/*++
+
+Routine Description:
+
+ This function is used by qsort to sort the FIT table based upon Component
+ Type in their incresing order.
+
+Arguments:
+
+ Arg1 - Pointer to Arg1
+ Arg2 - Pointer to Arg2
+
+Returns:
+
+ None
+
+--*/
+{
+ if ((((FIT_TABLE *) Arg1)->CvAndType & FIT_TYPE_MASK) > (((FIT_TABLE *) Arg2)->CvAndType & FIT_TYPE_MASK)) {
+ return 1;
+ } else if ((((FIT_TABLE *) Arg1)->CvAndType & FIT_TYPE_MASK) < (((FIT_TABLE *) Arg2)->CvAndType & FIT_TYPE_MASK)) {
+ return -1;
+ } else {
+ return 0;
+ }
+}
+
+VOID
+SortFitTable (
+ IN VOID
+ )
+/*++
+
+Routine Description:
+
+ This function is used by qsort to sort the FIT table based upon Component
+ Type in their incresing order.
+
+Arguments:
+
+ VOID
+
+Returns:
+
+ None
+
+--*/
+{
+ FIT_TABLE *FitTable;
+ FIT_TABLE *TmpFitPtr;
+ UINTN NumFitComponents;
+ UINTN Index;
+
+ GetFitTableStartAddress (&FitTable);
+ TmpFitPtr = FitTable;
+ NumFitComponents = 0;
+ for (Index = 0; Index < FitTable->CompSize; Index++) {
+ if ((TmpFitPtr->CvAndType & FIT_TYPE_MASK) != COMP_TYPE_FIT_UNUSED) {
+ NumFitComponents += 1;
+ }
+
+ TmpFitPtr++;
+ }
+
+ qsort ((VOID *) FitTable, NumFitComponents, sizeof (FIT_TABLE), CompareItems);
+}
+
+VOID
+UpdateFitEntryForFwVolume (
+ IN UINT64 Size
+ )
+/*++
+
+Routine Description:
+
+ This function updates the information about Firmware Volume in FIT TABLE.
+ This FIT table has to be immediately below the PAL_A Start and it contains
+ component type and address information. Other informations can't be
+ created this time so we would need to fix it up..
+
+
+Arguments:
+
+ Size - Firmware Volume Size
+
+Returns:
+
+ VOID
+
+--*/
+{
+ FIT_TABLE *CompFitPtr;
+ UINTN RelativeAddress;
+
+ //
+ // FV Fit table will be located at PAL_A Startaddress - 16 byte location
+ //
+ Bsf1LastStartAddress -= 0x10;
+ Bsf1TotalSize += 0x10;
+
+ GetRelativeAddressInBsfBuffer (Bsf1LastStartAddress, &RelativeAddress, FIRST_VTF);
+
+ CompFitPtr = (FIT_TABLE *) RelativeAddress;
+ CompFitPtr->CompAddress = Fv1BaseAddress;
+
+ //
+ // Since we don't have any information about its location in Firmware Volume,
+ // initialize address to 0. This will be updated once Firmware Volume is
+ // being build and its current address will be fixed in FIT table. Currently
+ // we haven't implemented it so far and working on architectural clarafication
+ //
+ //
+ // Firmware Volume Size in 16 byte block
+ //
+ CompFitPtr->CompSize = ((UINT32) Size) / 16;
+
+ //
+ // Since Firmware Volume does not exist by the time we create this FIT info
+ // this should be fixedup from Firmware Volume creation tool. We haven't
+ // worked out a method so far.
+ //
+ CompFitPtr->CompVersion = MAKE_VERSION (0, 0);
+
+ //
+ // Since we don't have any info about this file, we are making sure that
+ // checksum is not needed.
+ //
+ CompFitPtr->CvAndType = CV_N_TYPE (0, COMP_TYPE_FIT_FV_BOOT);
+
+ //
+ // Since non BSF component will reside outside the BSF, we will not have its
+ // binary image while creating BSF, hence we will not perform checksum at
+ // this time. Once Firmware Volume is being created which will contain this
+ // BSF, it will fix the FIT table for all the non BSF component and hence
+ // checksum
+ //
+ CompFitPtr->CheckSum = 0;
+}
+
+EFI_STATUS
+UpdateFitEntryForNonBSFComp (
+ IN PARSED_BSF_INFO *BsfInfo
+ )
+/*++
+
+Routine Description:
+
+ This function updates the information about non BSF component in FIT TABLE.
+ Since non BSF componets binaries are not part of BSF binary, we would still
+ be required to update its location information in Firmware Volume, inside
+ FIT table.
+
+Arguments:
+
+ BsfInfo - Pointer to BSF Info Structure
+
+Returns:
+
+ EFI_ABORTED - The function fails to update the component in FIT
+ EFI_SUCCESS - The function completed successfully
+
+--*/
+{
+ FIT_TABLE *CompFitPtr;
+
+ //
+ // Scan the FIT table for available space
+ //
+ GetNextAvailableFitPtr (&CompFitPtr);
+ if (CompFitPtr == NULL) {
+ printf ("\nERROR: Can't update this component in FIT");
+ return EFI_ABORTED;
+ }
+
+ //
+ // Since we don't have any information about its location in Firmware Volume,
+ // initialize address to 0. This will be updated once Firmware Volume is
+ // being build and its current address will be fixed in FIT table
+ //
+ CompFitPtr->CompAddress = 0;
+ CompFitPtr->CompSize = BsfInfo->CompSize;
+ CompFitPtr->CompVersion = MAKE_VERSION (BsfInfo->MajorVer, BsfInfo->MinorVer);
+ CompFitPtr->CvAndType = CV_N_TYPE (BsfInfo->CheckSumRequired, BsfInfo->CompType);
+
+ //
+ // Since non BSF component will reside outside the BSF, we will not have its
+ // binary image while creating BSF, hence we will not perform checksum at
+ // this time. Once Firmware Volume is being created which will contain this
+ // BSF, it will fix the FIT table for all the non BSF component and hence
+ // checksum
+ //
+ CompFitPtr->CheckSum = 0;
+
+ //
+ // Fit Type is FV_BOOT which means Firmware Volume, we initialize this to base
+ // address of Firmware Volume in which this BSF will be attached.
+ //
+ if ((CompFitPtr->CvAndType & 0x7F) == COMP_TYPE_FIT_FV_BOOT) {
+ CompFitPtr->CompAddress = Fv1BaseAddress;
+ }
+
+ return EFI_SUCCESS;
+}
+
+//
+// !!!WARNING
+// This function is updating the SALE_ENTRY in Itanium address space as per SAL
+// spec. SALE_ENTRY is being read from SYM file of PEICORE. Once the PEI
+// CORE moves in Firmware Volume, we would need to modify this function to be
+// used with a API which will detect PEICORE component while building Firmware
+// Volume and update its entry in FIT table as well as in Itanium address space
+// as per Intel?Itanium(TM) SAL address space
+//
+EFI_STATUS
+UpdateEntryPoint (
+ IN PARSED_BSF_INFO *BsfInfo,
+ IN UINT64 *CompStartAddress
+ )
+/*++
+
+Routine Description:
+
+ This function updated the architectural entry point in IPF, SALE_ENTRY.
+
+Arguments:
+
+ BsfInfo - Pointer to BSF Info Structure
+ CompStartAddress - Pointer to Component Start Address
+
+Returns:
+
+ EFI_INVALID_PARAMETER - The parameter is invalid
+ EFI_SUCCESS - The function completed successfully
+
+--*/
+{
+ UINTN RelativeAddress;
+ UINT64 SalEntryAdd;
+ FILE *Fp;
+ UINTN Offset;
+
+ CHAR8 Buff[FILE_NAME_SIZE];
+ CHAR8 Buff1[10];
+ CHAR8 Buff2[10];
+ CHAR8 OffsetStr[30];
+ CHAR8 Buff3[10];
+ CHAR8 Buff4[10];
+ CHAR8 Buff5[10];
+ CHAR8 Token[50];
+
+ Fp = fopen (BsfInfo->CompSymName, "r+b");
+
+ if (Fp == NULL) {
+ printf ("\nERROR: Error in opening file");
+ return EFI_INVALID_PARAMETER;
+ }
+
+ while (fgets (Buff, sizeof (Buff), Fp) != NULL) {
+ fscanf (
+ Fp,
+ "%s %s %s %s %s %s %s",
+ &Buff1,
+ &Buff2,
+ &OffsetStr,
+ &Buff3,
+ &Buff4,
+ &Buff5,
+ &Token
+ );
+ if (_stricmp (Token, "SALE_ENTRY") == 0) {
+ break;
+ }
+ }
+
+ Offset = strtoul (OffsetStr, NULL, 16);
+
+ *CompStartAddress += Offset;
+ SalEntryAdd = Fv1EndAddress - (SIZE_IA32_RESET_VECT + SIZE_SALE_ENTRY_POINT);
+
+ GetRelativeAddressInBsfBuffer (SalEntryAdd, &RelativeAddress, FIRST_VTF);
+
+ memcpy ((VOID *) RelativeAddress, (VOID *) CompStartAddress, sizeof (UINT64));
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+CreateAndUpdateComponent (
+ IN PARSED_BSF_INFO *BsfInfo
+ )
+/*++
+
+Routine Description:
+
+ This function reads the binary file for each components and update them
+ in BSF Buffer as well as in FIT table. If the component is located in non
+ BSF area, only the FIT table address will be updated
+
+Arguments:
+
+ BsfInfo - Pointer to Parsed Info
+
+Returns:
+
+ EFI_SUCCESS - The function completed successful
+ EFI_ABORTED - Aborted due to one of the many reasons like:
+ (a) Component Size greater than the specified size.
+ (b) Error opening files.
+
+ EFI_INVALID_PARAMETER Value returned from call to UpdateEntryPoint()
+ EFI_OUT_OF_RESOURCES Memory allocation failure.
+
+--*/
+{
+ EFI_STATUS Status;
+ UINT64 CompStartAddress;
+ UINT64 FileSize;
+ UINT64 NumByteRead;
+ UINT64 NumAdjustByte;
+ UINT8 *Buffer;
+ FILE *Fp;
+ FIT_TABLE *CompFitPtr;
+ BOOLEAN Aligncheck;
+
+ if (BsfInfo->LocationType == NONE) {
+ UpdateFitEntryForNonBSFComp (BsfInfo);
+ return EFI_SUCCESS;
+ }
+
+ Fp = fopen (BsfInfo->CompBinName, "r+b");
+
+ if (Fp == NULL) {
+ printf ("\nERROR: Opening file %s", BsfInfo->CompBinName);
+ return EFI_ABORTED;
+ }
+
+ FileSize = _filelength (_fileno (Fp));
+
+ if ((BsfInfo->CompType == COMP_TYPE_FIT_PAL_B) || (BsfInfo->CompType == COMP_TYPE_FIT_PAL_A_SPECIFIC)) {
+
+ //
+ // BUGBUG: Satish to correct
+ //
+ FileSize -= SIZE_OF_PAL_HEADER;
+ }
+
+ if (BsfInfo->PreferredSize) {
+ if (FileSize > BsfInfo->CompSize) {
+ printf ("\nERROR: The component size is more than specified size");
+ return EFI_ABORTED;
+ }
+
+ FileSize = BsfInfo->CompSize;
+ }
+
+ Buffer = malloc ((UINTN) FileSize);
+ if (Buffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ memset (Buffer, 0, (UINTN) FileSize);
+
+ if ((BsfInfo->CompType == COMP_TYPE_FIT_PAL_B) || (BsfInfo->CompType == COMP_TYPE_FIT_PAL_A_SPECIFIC)) {
+
+ //
+ // Read first 64 bytes of PAL header and use it to find version info
+ //
+ NumByteRead = fread (Buffer, sizeof (UINT8), SIZE_OF_PAL_HEADER, Fp);
+
+ //
+ // PAL header contains the version info. Currently, we will use the header
+ // to read version info and then discard.
+ //
+ if (!BsfInfo->VersionPresent) {
+ GetComponentVersionInfo (BsfInfo, Buffer);
+ }
+ }
+
+ NumByteRead = fread (Buffer, sizeof (UINT8), (UINTN) FileSize, Fp);
+ fclose (Fp);
+
+ //
+ // If it is non PAL_B component, pass the entire buffer to get the version
+ // info and implement any specific case inside GetComponentVersionInfo.
+ //
+ if (BsfInfo->CompType != COMP_TYPE_FIT_PAL_B) {
+ if (!BsfInfo->VersionPresent) {
+ GetComponentVersionInfo (BsfInfo, Buffer);
+ }
+ }
+
+ if (BsfInfo->LocationType == SECOND_VTF) {
+
+ CompStartAddress = (Bsf2LastStartAddress - FileSize);
+ } else {
+ CompStartAddress = (Bsf1LastStartAddress - FileSize);
+ }
+
+ if (BsfInfo->CompType == COMP_TYPE_FIT_PAL_B) {
+ Aligncheck = CheckAddressAlignment (CompStartAddress, 32 * 1024, &NumAdjustByte);
+ } else {
+ Aligncheck = CheckAddressAlignment (CompStartAddress, 8, &NumAdjustByte);
+ }
+
+ if (!Aligncheck) {
+ CompStartAddress -= NumAdjustByte;
+ }
+
+ if (BsfInfo->LocationType == SECOND_VTF) {
+ Bsf2LastStartAddress = CompStartAddress;
+ Bsf2TotalSize += (UINT32) (FileSize + NumAdjustByte);
+ Status = UpdateBsfBuffer (CompStartAddress, Buffer, FileSize, SECOND_VTF);
+ } else {
+ Bsf1LastStartAddress = CompStartAddress;
+ Bsf1TotalSize += (UINT32) (FileSize + NumAdjustByte);
+ Status = UpdateBsfBuffer (CompStartAddress, Buffer, FileSize, FIRST_VTF);
+ }
+
+ if (EFI_ERROR (Status)) {
+ return EFI_ABORTED;
+ }
+
+ GetNextAvailableFitPtr (&CompFitPtr);
+
+ CompFitPtr->CompAddress = CompStartAddress | IPF_CACHE_BIT;
+ assert ((FileSize % 16) == 0);
+ CompFitPtr->CompSize = (UINT32) (FileSize / 16);
+ CompFitPtr->CompVersion = MAKE_VERSION (BsfInfo->MajorVer, BsfInfo->MinorVer);
+ CompFitPtr->CvAndType = CV_N_TYPE (BsfInfo->CheckSumRequired, BsfInfo->CompType);
+ if (BsfInfo->CheckSumRequired) {
+ CompFitPtr->CheckSum = 0;
+ CompFitPtr->CheckSum = CalculateChecksum8 (Buffer, (UINTN) FileSize);
+ }
+
+ //
+ // Free the buffer
+ //
+ if (Buffer) {
+ free (Buffer);
+ }
+
+ //
+ // Update the SYM file for this component based on it's start address.
+ //
+ Status = UpdateSymFile (CompStartAddress, BSF_SYM_FILE, BsfInfo->CompSymName);
+ if (EFI_ERROR (Status)) {
+
+ //
+ // At this time, SYM files are not required, so continue on error.
+ //
+ }
+
+ // !!!!!!!!!!!!!!!!!!!!!
+ // BUGBUG:
+ // This part of the code is a temporary line since PEICORE is going to be inside
+ // BSF till we work out how to determine the SALE_ENTRY through it. We will need
+ // to clarify so many related questions
+ // !!!!!!!!!!!!!!!!!!!!!!!
+ if (BsfInfo->CompType == COMP_TYPE_FIT_PEICORE) {
+ Status = UpdateEntryPoint (BsfInfo, &CompStartAddress);
+ }
+
+ return Status;
+}
+
+EFI_STATUS
+CreateAndUpdatePAL_A (
+ IN PARSED_BSF_INFO *BsfInfo
+ )
+/*++
+
+Routine Description:
+
+ This function reads the binary file for each components and update them
+ in BSF Buffer as well as FIT table
+
+Arguments:
+
+ BsfInfo - Pointer to Parsed Info
+
+Returns:
+
+ EFI_ABORTED - Due to one of the following reasons:
+ (a)Error Opening File
+ (b)The PAL_A Size is more than specified size status
+ One of the values mentioned below returned from
+ call to UpdateSymFile
+ EFI_SUCCESS - The function completed successfully.
+ EFI_INVALID_PARAMETER - One of the input parameters was invalid.
+ EFI_ABORTED - An error occurred.UpdateSymFile
+ EFI_OUT_OF_RESOURCES - Memory allocation failed.
+
+--*/
+{
+ EFI_STATUS Status;
+ UINT64 PalStartAddress;
+ UINT64 AbsAddress;
+ UINTN RelativeAddress;
+ UINT64 FileSize;
+ UINT64 NumByteRead;
+ UINT8 *Buffer;
+ FILE *Fp;
+ FIT_TABLE *PalFitPtr;
+
+ Fp = fopen (BsfInfo->CompBinName, "r+b");
+
+ if (Fp == NULL) {
+ printf ("\nERROR: Opening file %s", BsfInfo->CompBinName);
+ return EFI_ABORTED;
+ }
+
+ FileSize = _filelength (_fileno (Fp));
+ FileSize -= SIZE_OF_PAL_HEADER;
+
+ if (BsfInfo->PreferredSize) {
+ if (FileSize > BsfInfo->CompSize) {
+ printf ("\nERROR: The PAL_A Size is more than specified size");
+ return EFI_ABORTED;
+ }
+
+ FileSize = BsfInfo->CompSize;
+ }
+
+ Buffer = malloc ((UINTN) FileSize);
+ if (Buffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ memset (Buffer, 0, (UINTN) FileSize);
+
+ //
+ // Read, Get version Info and discard the PAL header.
+ //
+ NumByteRead = fread (Buffer, sizeof (UINT8), SIZE_OF_PAL_HEADER, Fp);
+
+ //
+ // Extract the version info from header of PAL_A. Once done, discrad this buffer
+ //
+ if (!BsfInfo->VersionPresent) {
+ GetComponentVersionInfo (BsfInfo, Buffer);
+ }
+
+ //
+ // Read PAL_A file in a buffer
+ //
+ NumByteRead = fread (Buffer, sizeof (UINT8), (UINTN) FileSize, Fp);
+ fclose (Fp);
+
+ PalStartAddress = Fv1EndAddress - (SIZE_TO_OFFSET_PAL_A_END + FileSize);
+ Bsf1LastStartAddress = PalStartAddress;
+ Bsf1TotalSize += (UINT32) FileSize;
+ Status = UpdateBsfBuffer (PalStartAddress, Buffer, FileSize, FIRST_VTF);
+
+ AbsAddress = Fv1EndAddress - SIZE_TO_PAL_A_FIT;
+ GetRelativeAddressInBsfBuffer (AbsAddress, &RelativeAddress, FIRST_VTF);
+ PalFitPtr = (FIT_TABLE *) RelativeAddress;
+ PalFitPtr->CompAddress = PalStartAddress | IPF_CACHE_BIT;
+ assert ((FileSize % 16) == 0);
+ PalFitPtr->CompSize = (UINT32) (FileSize / 16);
+ PalFitPtr->CompVersion = MAKE_VERSION (BsfInfo->MajorVer, BsfInfo->MinorVer);
+ PalFitPtr->CvAndType = CV_N_TYPE (BsfInfo->CheckSumRequired, BsfInfo->CompType);
+ if (BsfInfo->CheckSumRequired) {
+ PalFitPtr->CheckSum = 0;
+ PalFitPtr->CheckSum = CalculateChecksum8 (Buffer, (UINTN) FileSize);
+ }
+
+ if (Buffer) {
+ free (Buffer);
+ }
+
+ //
+ // Update the SYM file for this component based on it's start address.
+ //
+ Status = UpdateSymFile (PalStartAddress, BSF_SYM_FILE, BsfInfo->CompSymName);
+ if (EFI_ERROR (Status)) {
+
+ //
+ // At this time, SYM files are not required, so continue on error.
+ //
+ }
+
+ return Status;
+}
+
+EFI_STATUS
+CreateFitTableAndInitialize (
+ IN PARSED_BSF_INFO *BsfInfo
+ )
+/*++
+
+Routine Description:
+
+ This function creates and intializes FIT table which would be used to
+ add component info inside this
+
+Arguments:
+
+ BsfInfo - Pointer to Parsed Info
+
+Returns:
+
+ EFI_ABORTED - Aborted due to no size information
+ EFI_SUCCESS - The function completed successfully
+
+--*/
+{
+ UINT64 PalFitTableAdd;
+ UINT64 FitTableAdd;
+ UINT64 FitTableAddressOffset;
+ FIT_TABLE *PalFitPtr;
+ FIT_TABLE *FitStartPtr;
+ UINTN NumFitComp;
+ UINTN RelativeAddress;
+ UINTN Index;
+
+ if (!BsfInfo->PreferredSize) {
+ printf ("\nERROR: FIT could not be allocated becuase there are no size information");
+ return EFI_ABORTED;
+ }
+
+ if ((BsfInfo->CompSize % 16) != 0) {
+ printf ("\nERROR: Invalid Fit Table Size, not multiple of 16 bytes. Please correct the size");
+ }
+
+ PalFitTableAdd = Fv1EndAddress - SIZE_TO_PAL_A_FIT;
+ GetRelativeAddressInBsfBuffer (PalFitTableAdd, &RelativeAddress, FIRST_VTF);
+ PalFitPtr = (FIT_TABLE *) RelativeAddress;
+ PalFitTableAdd = (PalFitPtr->CompAddress - BsfInfo->CompSize);
+
+ FitTableAdd = (PalFitPtr->CompAddress - 0x10) - BsfInfo->CompSize;
+ FitTableAddressOffset = Fv1EndAddress - (SIZE_IA32_RESET_VECT + SIZE_SALE_ENTRY_POINT + SIZE_FIT_TABLE_ADD);
+ GetRelativeAddressInBsfBuffer (FitTableAddressOffset, &RelativeAddress, FIRST_VTF);
+ *(UINT64 *) RelativeAddress = FitTableAdd;
+
+ GetRelativeAddressInBsfBuffer (FitTableAdd, &RelativeAddress, FIRST_VTF);
+
+ //
+ // Update Fit Table with FIT Signature and FIT info in first 16 bytes.
+ //
+ FitStartPtr = (FIT_TABLE *) RelativeAddress;
+
+ strncpy ((CHAR8 *) &FitStartPtr->CompAddress, FIT_SIGNATURE, 8); // "_FIT_ "
+ assert (((BsfInfo->CompSize & 0x00FFFFFF) % 16) == 0);
+ FitStartPtr->CompSize = (BsfInfo->CompSize & 0x00FFFFFF) / 16;
+ FitStartPtr->CompVersion = MAKE_VERSION (BsfInfo->MajorVer, BsfInfo->MinorVer);
+
+ //
+ // BUGBUG: If a checksum is required, add code to checksum the FIT table. Also
+ // determine what to do for things like the FV component that aren't easily checksummed.
+ // The checksum will be done once we are done with all the componet update in the FIT
+ // table
+ //
+ FitStartPtr->CvAndType = CV_N_TYPE (BsfInfo->CheckSumRequired, BsfInfo->CompType);
+
+ NumFitComp = FitStartPtr->CompSize;
+
+ FitStartPtr++;
+
+ //
+ // Intialize remaining FIT table space to UNUSED fit component type
+ // so that when we need to create a FIT entry for a component, we can
+ // locate a free one and use it.
+ //
+ for (Index = 0; Index < (NumFitComp - 1); Index++) {
+ FitStartPtr->CvAndType = 0x7F; // Initialize all with UNUSED
+ FitStartPtr++;
+ }
+
+ Bsf1TotalSize += BsfInfo->CompSize;
+ Bsf1LastStartAddress -= BsfInfo->CompSize;
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+WriteBsfBinary (
+ IN CHAR8 *FileName,
+ IN UINT32 BsfSize,
+ IN LOC_TYPE LocType
+ )
+/*++
+
+Routine Description:
+
+ Write Firmware Volume from memory to a file.
+
+Arguments:
+
+ FileName - Output File Name which needed to be created/
+ BsfSize - FileSize
+ LocType - The type of the BSF
+
+Returns:
+
+ EFI_ABORTED - Returned due to one of the following resons:
+ (a) Error Opening File
+ (b) Failing to copy buffers
+ EFI_SUCCESS - The fuction completes successfully
+
+--*/
+{
+ FILE *Fp;
+ UINTN NumByte;
+ VOID *BsfBuffer;
+ UINTN RelativeAddress;
+
+ if (LocType == FIRST_VTF) {
+ GetRelativeAddressInBsfBuffer (Bsf1LastStartAddress, &RelativeAddress, FIRST_VTF);
+ BsfBuffer = (VOID *) RelativeAddress;
+ } else {
+ GetRelativeAddressInBsfBuffer (Bsf2LastStartAddress, &RelativeAddress, SECOND_VTF);
+ BsfBuffer = (VOID *) RelativeAddress;
+ }
+
+ Fp = fopen (FileName, "w+b");
+ if (Fp == NULL) {
+ printf ("Error in opening file %s\n", FileName);
+ return EFI_ABORTED;
+ }
+
+ NumByte = fwrite (BsfBuffer, sizeof (UINT8), (UINTN) BsfSize, Fp);
+
+ if (Fp) {
+ fclose (Fp);
+ }
+
+ if (NumByte != (sizeof (UINT8) * BsfSize)) {
+ printf ("\nERROR: Could not copy buffer into file %s ", FileName);
+ return EFI_ABORTED;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+UpdateBsfBuffer (
+ IN UINT64 StartAddress,
+ IN UINT8 *Buffer,
+ IN UINT64 DataSize,
+ IN LOC_TYPE LocType
+ )
+/*++
+
+Routine Description:
+
+ Update the Firmware Volume Buffer with requested buffer data
+
+Arguments:
+
+ StartAddress - StartAddress in buffer. This number will automatically
+ point to right address in buffer where data needed
+ to be updated.
+ Buffer - Buffer pointer from data will be copied to memory mapped buffer.
+ DataSize - Size of the data needed to be copied.
+ LocType - The type of the BSF
+
+Returns:
+
+ EFI_ABORTED - The input parameter is error
+ EFI_SUCCESS - The function completed successfully
+
+--*/
+{
+ UINT8 *LocalBufferPtrToWrite;
+
+ if (LocType == FIRST_VTF) {
+ if ((StartAddress | IPF_CACHE_BIT) < (Bsf1LastStartAddress | IPF_CACHE_BIT)) {
+ printf ("ERROR: Start Address is less then the BSF start address\n");
+ return EFI_ABORTED;
+ }
+
+ LocalBufferPtrToWrite = (UINT8 *) Bsf1EndBuffer;
+ LocalBufferPtrToWrite -= (Fv1EndAddress - StartAddress);
+ } else {
+ if ((StartAddress | IPF_CACHE_BIT) < (Bsf2LastStartAddress | IPF_CACHE_BIT)) {
+ printf ("ERROR: Start Address is less then the BSF start address\n");
+ return EFI_ABORTED;
+ }
+ LocalBufferPtrToWrite = (UINT8 *) Bsf2EndBuffer;
+ LocalBufferPtrToWrite -= (Fv2EndAddress - StartAddress);
+ }
+
+ memcpy (LocalBufferPtrToWrite, Buffer, (UINTN) DataSize);
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+UpdateFfsHeader (
+ IN UINT32 TotalBsfSize,
+ IN LOC_TYPE LocType
+ )
+/*++
+
+Routine Description:
+
+ Update the Firmware Volume Buffer with requested buffer data
+
+Arguments:
+
+ TotalBsfSize - Size of the BSF
+ Fileoffset - The start of the file relative to the start of the FV.
+ LocType - The type of the BSF
+
+Returns:
+
+ EFI_SUCCESS - The function completed successfully
+ EFI_INVALID_PARAMETER - The Ffs File Header Pointer is NULL
+
+--*/
+{
+ EFI_FFS_FILE_HEADER *FileHeader;
+ UINTN RelativeAddress;
+ EFI_GUID EfiFirmwareVolumeTopFileGuid = EFI_FFS_VOLUME_TOP_FILE_GUID;
+
+ //
+ // Find the BSF file header location
+ //
+ if (LocType == FIRST_VTF) {
+ GetRelativeAddressInBsfBuffer (Bsf1LastStartAddress, &RelativeAddress, FIRST_VTF);
+ FileHeader = (EFI_FFS_FILE_HEADER *) RelativeAddress;
+ } else {
+ GetRelativeAddressInBsfBuffer (Bsf2LastStartAddress, &RelativeAddress, SECOND_VTF);
+ FileHeader = (EFI_FFS_FILE_HEADER *) RelativeAddress;
+ }
+
+ if (FileHeader == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // write header
+ //
+ memset (FileHeader, 0, sizeof (EFI_FFS_FILE_HEADER));
+ memcpy (&FileHeader->Name, &EfiFirmwareVolumeTopFileGuid, sizeof (EFI_GUID));
+ FileHeader->Type = EFI_FV_FILETYPE_FREEFORM;
+ FileHeader->Attributes = FFS_ATTRIB_CHECKSUM;
+
+ //
+ // Now FileSize includes the EFI_FFS_FILE_HEADER
+ //
+ FileHeader->Size[0] = (UINT8) (TotalBsfSize & 0x000000FF);
+ FileHeader->Size[1] = (UINT8) ((TotalBsfSize & 0x0000FF00) >> 8);
+ FileHeader->Size[2] = (UINT8) ((TotalBsfSize & 0x00FF0000) >> 16);
+
+ //
+ // Fill in checksums and state, all three must be zero for the checksums.
+ //
+ FileHeader->IntegrityCheck.Checksum.Header = 0;
+ FileHeader->IntegrityCheck.Checksum.File = 0;
+ FileHeader->State = 0;
+ FileHeader->IntegrityCheck.Checksum.Header = CalculateChecksum8 ((UINT8 *) FileHeader, sizeof (EFI_FFS_FILE_HEADER));
+ FileHeader->IntegrityCheck.Checksum.File = CalculateChecksum8 ((UINT8 *) FileHeader, TotalBsfSize);
+ FileHeader->State = EFI_FILE_HEADER_CONSTRUCTION | EFI_FILE_HEADER_VALID | EFI_FILE_DATA_VALID;
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+ValidateAddressAndSize (
+ IN UINT64 BaseAddress,
+ IN UINT64 FwVolSize
+ )
+/*++
+
+Routine Description:
+
+ Update the Firmware Volume Buffer with requested buffer data
+
+Arguments:
+
+ BaseAddress - Base address for the Fw Volume.
+
+ FwVolSize - Total Size of the FwVolume to which BSF will be attached..
+
+Returns:
+
+ EFI_SUCCESS - The function completed successfully
+ EFI_UNSUPPORTED - The input parameter is error
+
+--*/
+{
+ if ((BaseAddress >= 0) && (FwVolSize > 0x40) && ((BaseAddress + FwVolSize) % 8 == 0)) {
+ return EFI_SUCCESS;
+ }
+
+ return EFI_UNSUPPORTED;
+}
+
+EFI_STATUS
+UpdateIA32ResetVector (
+ IN CHAR8 *FileName,
+ IN UINT64 FirstFwVSize
+ )
+/*++
+
+Routine Description:
+
+ Update the 16 byte IA32 Reset vector to maintain the compatibility
+
+Arguments:
+
+ FileName - Binary file name which contains the IA32 Reset vector info..
+ FirstFwVSize - Total Size of the FwVolume to which BSF will be attached..
+
+Returns:
+
+ EFI_SUCCESS - The function completed successfully
+ EFI_ABORTED - Invalid File Size
+ EFI_INVALID_PARAMETER - Bad File Name
+ EFI_OUT_OF_RESOURCES - Memory allocation failed.
+
+--*/
+{
+ UINT8 *Buffer;
+ UINT8 *LocalBsfBuffer;
+ UINTN FileSize;
+ UINTN NumByteRead;
+ FILE *Fp;
+
+ if (!strcmp (FileName, "")) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Fp = fopen (FileName, "r+b");
+
+ if (Fp == NULL) {
+ printf ("\nERROR: Unable to open the file %s", FileName);
+ }
+
+ FileSize = _filelength (_fileno (Fp));
+
+ if (FileSize > 16) {
+ return EFI_ABORTED;
+ }
+
+ Buffer = malloc (FileSize);
+ if (Buffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ NumByteRead = fread (Buffer, sizeof (UINT8), FileSize, Fp);
+
+ LocalBsfBuffer = (UINT8 *) Bsf1EndBuffer - SIZE_IA32_RESET_VECT;
+ memcpy (LocalBsfBuffer, Buffer, FileSize);
+
+ if (Buffer) {
+ free (Buffer);
+ }
+
+ return EFI_SUCCESS;
+}
+
+VOID
+CleanUpMemory (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function cleans up any allocated buffer
+
+Arguments:
+
+ NONE
+
+Returns:
+
+ NONE
+
+--*/
+{
+ PARSED_BSF_INFO *TempFileListPtr;
+
+ if (Bsf1Buffer) {
+ free (Bsf1Buffer);
+ }
+
+ if (Bsf2Buffer) {
+ free (Bsf2Buffer);
+ }
+
+ //
+ // Cleanup the buffer which was allocated to read the file names from FV.INF
+ //
+ FileListPtr = FileListHeadPtr;
+ while (FileListPtr != NULL) {
+ TempFileListPtr = FileListPtr->NextBsfInfo;
+ free (FileListPtr);
+ FileListPtr = TempFileListPtr;
+ }
+}
+
+EFI_STATUS
+ProcessAndCreateBsf (
+ IN UINT64 Size
+ )
+/*++
+
+Routine Description:
+
+ This function process the link list created during INF file parsing
+ and create component in BSF and updates its info in FIT table
+
+Arguments:
+
+ Size - Size of the Firmware Volume of which, this BSF belongs to.
+
+Returns:
+
+ EFI_UNSUPPORTED - Unknown FIT type
+ EFI_SUCCESS - The function completed successfully
+
+--*/
+{
+ EFI_STATUS Status;
+ PARSED_BSF_INFO *ParsedInfoPtr;
+
+ Status = EFI_SUCCESS;
+
+ ParsedInfoPtr = FileListHeadPtr;
+
+ while (ParsedInfoPtr != NULL) {
+
+ switch (ParsedInfoPtr->CompType) {
+ //
+ // COMP_TYPE_FIT_HEADER is a special case, hence handle it here
+ //
+ case COMP_TYPE_FIT_HEADER:
+ Status = CreateFitTableAndInitialize (ParsedInfoPtr);
+ break;
+
+ //
+ // COMP_TYPE_FIT_PAL_A is a special case, hence handle it here
+ //
+ case COMP_TYPE_FIT_PAL_A:
+ Status = CreateAndUpdatePAL_A (ParsedInfoPtr);
+
+ //
+ // Based on BSF specification, once the PAL_A component has been written,
+ // update the Firmware Volume info as FIT table. This will be utilized
+ // to extract the Firmware Volume Start address where this BSF will be
+ // of part.
+ //
+ if (Status == EFI_SUCCESS) {
+ UpdateFitEntryForFwVolume (Size);
+ }
+ break;
+
+ case COMP_TYPE_FIT_FV_BOOT:
+ //
+ // Since FIT entry for Firmware Volume has been created and it is
+ // located at (PAL_A start - 16 byte). So we will not process any
+ // Firmware Volume related entry from INF file
+ //
+ Status = EFI_SUCCESS;
+ break;
+
+ default:
+ //
+ // Any other component type should be handled here. This will create the
+ // image in specified BSF and create appropriate entry about this
+ // component in FIT Entry.
+ //
+ Status = CreateAndUpdateComponent (ParsedInfoPtr);
+ if (EFI_ERROR (Status)) {
+ printf ("ERROR: Updating %s component.\n", ParsedInfoPtr->CompName);
+ }
+ break;
+ }
+
+ ParsedInfoPtr = ParsedInfoPtr->NextBsfInfo;
+ }
+
+ return Status;
+}
+
+EFI_STATUS
+GenerateBsfImage (
+ IN UINT64 StartAddress1,
+ IN UINT64 Size1,
+ IN UINT64 StartAddress2,
+ IN UINT64 Size2
+ )
+/*++
+
+Routine Description:
+
+ This is the main function which will be called from application.
+
+Arguments:
+
+ StartAddress1 - The start address of the first BSF
+ Size1 - The size of the first BSF
+ StartAddress2 - The start address of the second BSF
+ Size2 - The size of the second BSF
+
+Returns:
+
+ EFI_OUT_OF_RESOURCES - Can not allocate memory
+ The return value can be any of the values
+ returned by the calls to following functions:
+ GetBsfRelatedInfoFromInfFile
+ ProcessAndCreateBsf
+ UpdateIA32ResetVector
+ UpdateFfsHeader
+ WriteBsfBinary
+
+--*/
+{
+ EFI_STATUS Status;
+ CHAR8 OutFileName1[FILE_NAME_SIZE];
+ CHAR8 OutFileName2[FILE_NAME_SIZE];
+ BOOLEAN SecondBSF;
+
+ Status = EFI_UNSUPPORTED;
+
+ if (StartAddress2 == 0) {
+ SecondBSF = FALSE;
+ } else {
+ SecondBSF = TRUE;
+ }
+ Fv1BaseAddress = StartAddress1;
+ Fv1EndAddress = Fv1BaseAddress + Size1;
+
+ memset (OutFileName1, 0, FILE_NAME_SIZE);
+ sprintf (
+ OutFileName1,
+ "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x-%s",
+ Bsf1NameGuid.Data1,
+ Bsf1NameGuid.Data2,
+ Bsf1NameGuid.Data3,
+ Bsf1NameGuid.Data4[0],
+ Bsf1NameGuid.Data4[1],
+ Bsf1NameGuid.Data4[2],
+ Bsf1NameGuid.Data4[3],
+ Bsf1NameGuid.Data4[4],
+ Bsf1NameGuid.Data4[5],
+ Bsf1NameGuid.Data4[6],
+ Bsf1NameGuid.Data4[7],
+ BSF_OUTPUT_FILE
+ );
+
+ //
+ // The image buffer for the First BSF
+ //
+ Bsf1Buffer = malloc ((UINTN) Size1);
+ if (Bsf1Buffer == NULL) {
+ printf ("\nERROR: Not enough resource to create memory mapped file for Boot Strap File");
+ return EFI_OUT_OF_RESOURCES;
+ }
+ memset (Bsf1Buffer, 0x00, (UINTN) Size1);
+ Bsf1EndBuffer = (UINT8 *) Bsf1Buffer + Size1;
+ Bsf1LastStartAddress = Fv1EndAddress | IPF_CACHE_BIT;
+
+ if (SecondBSF) {
+ Fv2BaseAddress = StartAddress2;
+ Fv2EndAddress = Fv2BaseAddress + Size2;
+
+ memset (OutFileName2, 0, FILE_NAME_SIZE);
+ sprintf (
+ OutFileName2,
+ "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x-%s",
+ Bsf2NameGuid.Data1,
+ Bsf2NameGuid.Data2,
+ Bsf2NameGuid.Data3,
+ Bsf2NameGuid.Data4[0],
+ Bsf2NameGuid.Data4[1],
+ Bsf2NameGuid.Data4[2],
+ Bsf2NameGuid.Data4[3],
+ Bsf2NameGuid.Data4[4],
+ Bsf2NameGuid.Data4[5],
+ Bsf2NameGuid.Data4[6],
+ Bsf2NameGuid.Data4[7],
+ BSF_OUTPUT_FILE
+ );
+
+ //
+ // The image buffer for the second BSF
+ //
+ Bsf2Buffer = malloc ((UINTN) Size2);
+ if (Bsf2Buffer == NULL) {
+ printf ("\nERROR: Not enough resource to create memory mapped file for Boot Strap File");
+ return EFI_OUT_OF_RESOURCES;
+ }
+ memset (Bsf2Buffer, 0x00, (UINTN) Size2);
+ Bsf2EndBuffer = (UINT8 *) Bsf2Buffer + Size2;
+ Bsf2LastStartAddress = Fv2EndAddress | IPF_CACHE_BIT;
+ }
+
+ Status = GetBsfRelatedInfoFromInfFile (BSF_INPUT_FILE);
+ if (Status != EFI_SUCCESS) {
+ printf ("\nERROR: Error in parsing input file");
+ CleanUpMemory ();
+ return Status;
+ }
+
+ Status = ProcessAndCreateBsf (Size1);
+ if (Status != EFI_SUCCESS) {
+ CleanUpMemory ();
+ return Status;
+ }
+
+ Status = UpdateIA32ResetVector (IA32BinFile, Bsf1TotalSize);
+ if (Status != EFI_SUCCESS) {
+ CleanUpMemory ();
+ return Status;
+ }
+
+ //
+ // Re arrange the FIT Table for Ascending order of their FIT Type..
+ //
+ SortFitTable ();
+
+ //
+ // All components have been updated in FIT table. Now perform the FIT table
+ // checksum. The following function will check if Checksum is required,
+ // if yes, then it will perform the checksum otherwise not.
+ //
+ CalculateFitTableChecksum ();
+
+ //
+ // Write the FFS header
+ //
+ Bsf1TotalSize += sizeof (EFI_FFS_FILE_HEADER);
+ Bsf1LastStartAddress -= sizeof (EFI_FFS_FILE_HEADER);
+ Status = UpdateFfsHeader (Bsf1TotalSize, FIRST_VTF);
+ if (Status != EFI_SUCCESS) {
+ CleanUpMemory ();
+ return Status;
+ }
+ //
+ // Update the BSF buffer into specified BSF binary file
+ //
+ Status = WriteBsfBinary (OutFileName1, Bsf1TotalSize, FIRST_VTF);
+
+ if (SecondBSF) {
+ Bsf2TotalSize += sizeof (EFI_FFS_FILE_HEADER);
+ Bsf2LastStartAddress -= sizeof (EFI_FFS_FILE_HEADER);
+ Status = UpdateFfsHeader (Bsf2TotalSize, SECOND_VTF);
+ if (Status != EFI_SUCCESS) {
+ CleanUpMemory ();
+ return Status;
+ }
+
+ //
+ // Update the BSF buffer into specified BSF binary file
+ //
+ Status = WriteBsfBinary (OutFileName2, Bsf2TotalSize, SECOND_VTF);
+ }
+
+ CleanUpMemory ();
+ printf ("\n");
+
+ return Status;
+}
+
+EFI_STATUS
+PeimFixupInFitTable (
+ IN UINT64 StartAddress
+ )
+/*++
+
+Routine Description:
+
+ This function is an entry point to fixup SAL-E entry point.
+
+Arguments:
+
+ StartAddress - StartAddress for PEIM.....
+
+Returns:
+
+ EFI_SUCCESS - The function completed successfully
+ EFI_ABORTED - Error Opening File
+ EFI_OUT_OF_RESOURCES - System out of resources for memory allocation.
+
+--*/
+{
+ EFI_STATUS Status;
+ FILE *Fp;
+ UINT64 *StartAddressPtr;
+ UINTN FirstFwVSize;
+ UINTN NumByte;
+ CHAR8 OutFileName1[FILE_NAME_SIZE];
+
+ StartAddressPtr = malloc (sizeof (UINT64));
+ if (StartAddressPtr == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ *StartAddressPtr = StartAddress;
+
+ memset (OutFileName1, 0, FILE_NAME_SIZE);
+
+ sprintf (
+ OutFileName1,
+ "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x-%s",
+ Bsf1NameGuid.Data1,
+ Bsf1NameGuid.Data2,
+ Bsf1NameGuid.Data3,
+ Bsf1NameGuid.Data4[0],
+ Bsf1NameGuid.Data4[1],
+ Bsf1NameGuid.Data4[2],
+ Bsf1NameGuid.Data4[3],
+ Bsf1NameGuid.Data4[4],
+ Bsf1NameGuid.Data4[5],
+ Bsf1NameGuid.Data4[6],
+ Bsf1NameGuid.Data4[7],
+ BSF_OUTPUT_FILE
+ );
+
+ Fp = fopen (OutFileName1, "r+b");
+
+ if (Fp == NULL) {
+ printf ("\nERROR: Error opening file ");
+ if (StartAddressPtr) {
+ free (StartAddressPtr);
+ }
+
+ return EFI_ABORTED;
+ }
+
+ FirstFwVSize = _filelength (_fileno (Fp));
+ fseek (Fp, (long) (FirstFwVSize - (UINTN) (SIZE_IA32_RESET_VECT + SIZE_SALE_ENTRY_POINT)), SEEK_SET);
+ NumByte = fwrite ((VOID *) StartAddressPtr, sizeof (UINT64), 1, Fp);
+
+ if (Fp) {
+ fclose (Fp);
+ }
+
+ if (StartAddressPtr) {
+ free (StartAddressPtr);
+ }
+
+ printf ("\n");
+ Status = EFI_SUCCESS;
+ return Status;
+}
+
+EFI_STATUS
+UpdateSymFile (
+ IN UINT64 BaseAddress,
+ IN CHAR8 *DestFileName,
+ IN CHAR8 *SourceFileName
+ )
+/*++
+
+Routine Description:
+
+ This function adds the SYM tokens in the source file to the destination file.
+ The SYM tokens are updated to reflect the base address.
+
+Arguments:
+
+ BaseAddress - The base address for the new SYM tokens.
+ DestFileName - The destination file.
+ SourceFileName - The source file.
+
+Returns:
+
+ EFI_SUCCESS - The function completed successfully.
+ EFI_INVALID_PARAMETER - One of the input parameters was invalid.
+ EFI_ABORTED - An error occurred.
+
+--*/
+{
+ FILE *SourceFile;
+ FILE *DestFile;
+ CHAR8 Buffer[_MAX_PATH];
+ CHAR8 Type[_MAX_PATH];
+ CHAR8 Address[_MAX_PATH];
+ CHAR8 Section[_MAX_PATH];
+ CHAR8 Token[_MAX_PATH];
+ CHAR8 BaseToken[_MAX_PATH];
+ UINT64 TokenAddress;
+ long StartLocation;
+
+ //
+ // Verify input parameters.
+ //
+ if (BaseAddress == 0 || DestFileName == NULL || SourceFileName == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Open the source file
+ //
+ SourceFile = fopen (SourceFileName, "r");
+ if (SourceFile == NULL) {
+
+ //
+ // SYM files are not required.
+ //
+ return EFI_SUCCESS;
+ }
+
+ //
+ // Use the file name minus extension as the base for tokens
+ //
+ strcpy (BaseToken, SourceFileName);
+ strtok (BaseToken, ". \t\n");
+ strcat (BaseToken, "__");
+
+ //
+ // Open the destination file
+ //
+ DestFile = fopen (DestFileName, "a+");
+ if (DestFile == NULL) {
+ fclose (SourceFile);
+ return EFI_ABORTED;
+ }
+
+ //
+ // If this is the beginning of the output file, write the symbol format info.
+ //
+ if (fseek (DestFile, 0, SEEK_END) != 0) {
+ fclose (SourceFile);
+ fclose (DestFile);
+ return EFI_ABORTED;
+ }
+
+ StartLocation = ftell (DestFile);
+
+ if (StartLocation == 0) {
+ fprintf (DestFile, "TEXTSYM format | V1.0\n");
+ } else if (StartLocation == -1) {
+ fclose (SourceFile);
+ fclose (DestFile);
+ return EFI_ABORTED;
+ }
+
+ //
+ // Read the first line
+ //
+ if (fgets (Buffer, _MAX_PATH, SourceFile) == NULL) {
+ Buffer[0] = 0;
+ }
+
+ //
+ // Make sure it matches the expected sym format
+ //
+ if (strcmp (Buffer, "TEXTSYM format | V1.0\n")) {
+ fclose (SourceFile);
+ fclose (DestFile);
+ return EFI_ABORTED;
+ }
+
+ //
+ // Read in the file
+ //
+ while (feof (SourceFile) == 0) {
+
+ //
+ // Read a line
+ //
+ if (fscanf (SourceFile, "%s | %s | %s | %s\n", Type, Address, Section, Token) == 4) {
+
+ //
+ // Get the token address
+ //
+ AsciiStringToUint64 (Address, TRUE, &TokenAddress);
+
+ //
+ // Add the base address, the size of the FFS file header and the size of the peim header.
+ //
+ TokenAddress += BaseAddress &~IPF_CACHE_BIT;
+
+ fprintf (DestFile, "%s | %016I64X | %s | %s%s\n", Type, TokenAddress, Section, BaseToken, Token);
+ }
+ }
+
+ fclose (SourceFile);
+ fclose (DestFile);
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+CalculateFitTableChecksum (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function will perform byte checksum on the FIT table, if the the checksum required
+ field is set to CheckSum required. If the checksum is not required then checksum byte
+ will have value as 0;.
+
+Arguments:
+
+ NONE
+
+Returns:
+
+ Status - Value returned by call to CalculateChecksum8 ()
+ EFI_SUCCESS - The function completed successfully
+
+--*/
+{
+ FIT_TABLE *TmpFitPtr;
+ UINT64 FitTableAdd;
+ UINT64 FitTableAddOffset;
+ UINTN RelativeAddress;
+ UINTN Size;
+
+ //
+ // Read the Fit Table address from Itanium-based address map.
+ //
+ FitTableAddOffset = Fv1EndAddress - (SIZE_IA32_RESET_VECT + SIZE_SALE_ENTRY_POINT + SIZE_FIT_TABLE_ADD);
+
+ //
+ // Translate this Itanium-based address in terms of local buffer address which
+ // contains the image for Boot Strapped File
+ //
+ GetRelativeAddressInBsfBuffer (FitTableAddOffset, &RelativeAddress, FIRST_VTF);
+ FitTableAdd = *(UINTN *) RelativeAddress;
+
+ GetRelativeAddressInBsfBuffer (FitTableAdd, &RelativeAddress, FIRST_VTF);
+
+ TmpFitPtr = (FIT_TABLE *) RelativeAddress;
+
+ Size = TmpFitPtr->CompSize * 16;
+
+ if ((TmpFitPtr->CvAndType & CHECKSUM_BIT_MASK) >> 7) {
+ TmpFitPtr->CheckSum = 0;
+ TmpFitPtr->CheckSum = CalculateChecksum8 ((UINT8 *) TmpFitPtr, Size);
+ } else {
+ TmpFitPtr->CheckSum = 0;
+ }
+
+ return EFI_SUCCESS;
+}
+
+VOID
+PrintUtilityInfo (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Displays the standard utility information to SDTOUT
+
+Arguments:
+
+ None
+
+Returns:
+
+ None
+
+--*/
+{
+ printf (
+ "%s, EFI 2.0 BootStrap File Generation Utility. Version %i.%i, %s.\n\n",
+ UTILITY_NAME,
+ UTILITY_MAJOR_VERSION,
+ UTILITY_MINOR_VERSION,
+ UTILITY_DATE
+ );
+}
+
+VOID
+PrintUsage (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Displays the utility usage syntax to STDOUT
+
+Arguments:
+
+ None
+
+Returns:
+
+ None
+
+--*/
+{
+ printf (
+ "Usage: %s -B BaseAddress -S FwVolumeSize\n",
+ UTILITY_NAME
+ );
+ printf (" Where:\n");
+ printf ("\tBaseAddress is the starting address of Firmware Volume where\n\tBoot Strapped Image will reside.\n\n");
+ printf ("\tFwVolumeSize is the size of Firmware Volume.\n\n");
+}
+
+EFI_STATUS
+main (
+ IN UINTN argc,
+ IN CHAR8 **argv
+ )
+/*++
+
+Routine Description:
+
+ This utility uses GenBsfImage.dll to build a Boot Strap File Image which will be
+ part of firmware volume image.
+
+Arguments:
+
+ argc - The count of the parameters
+ argv - The parameters
+
+
+Returns:
+
+ 0 - No error conditions detected.
+ 1 - One or more of the input parameters is invalid.
+ 2 - A resource required by the utility was unavailable.
+ - Most commonly this will be memory allocation or file creation.
+ 3 - GenFvImage.dll could not be loaded.
+ 4 - Error executing the GenFvImage dll.
+ 5 - Now this tool does not support the IA32 platform
+
+--*/
+{
+ UINT8 Index;
+ UINT64 StartAddress1;
+ UINT64 StartAddress2;
+ UINT64 FwVolSize1;
+ UINT64 FwVolSize2;
+ BOOLEAN FirstRoundB;
+ BOOLEAN FirstRoundS;
+ EFI_STATUS Status;
+ BOOLEAN IsIA32;
+
+ //
+ // Display utility information
+ //
+ PrintUtilityInfo ();
+
+ //
+ // Verify the correct number of IA32 arguments
+ //
+ IsIA32 = FALSE;
+ if (argc == IA32_ARGS) {
+ //
+ // Now this tool is not used for IA32 platform, if it will be used in future,
+ // the IA32-specific functions need to be updated and verified, the updating can
+ // refer to IPF relevant functions)
+ //
+ printf ("ERROR: Now this tool does not support the IA32 platform!\n");
+ printf ("ERROR: And the IA32-specific functions need to be updated and verified!\n");
+ return 5;
+
+ /*
+ StartAddress1 = 0;
+ IsIA32 = TRUE;
+
+ //
+ // Parse the command line arguments
+ //
+ for (Index = 1; Index < IA32_ARGS; Index += 2) {
+
+ //
+ // Make sure argument pair begin with - or /
+ //
+ if (argv[Index][0] != '-' && argv[Index][0] != '/') {
+ PrintUsage ();
+ printf ("ERROR: Argument pair must begin with \"-\" or \"/\"\n");
+ return 1;
+ }
+
+ //
+ // Make sure argument specifier is only one letter
+ //
+ if (argv[Index][2] != 0) {
+ PrintUsage ();
+ printf ("ERROR: Unrecognized argument \"%s\".\n", argv[Index]);
+ return 1;
+ }
+
+ //
+ // Determine argument to read
+ //
+ switch (argv[Index][1]) {
+
+ case 't':
+ case 'T':
+ Status = AsciiStringToUint64 (argv[Index + 1], FALSE, &StartAddress1);
+ if (Status != EFI_SUCCESS) {
+ printf ("\nERROR: Bad start of address \"%s\"\n", argv[Index + 1]);
+ return 1;
+ }
+ break;
+
+ default:
+ PrintUsage ();
+ printf ("Unrecognized IA32 argument \"%s\".\n", argv[Index]);
+ IsIA32 = FALSE;
+ break;
+ }
+ }
+
+ if (IsIA32) {
+ //
+ // Call the GenBsfImage
+ //
+ Status = Generate32BsfImage (StartAddress1);
+
+ if (EFI_ERROR(Status)) {
+ switch (Status) {
+
+ case EFI_INVALID_PARAMETER:
+ printf ("\nERROR: Invalid parameter passed to GenBsfImage function .\n");
+ break;
+
+ case EFI_ABORTED:
+ printf ("\nERROR: Error detected while creating the file image.\n");
+ break;
+
+ case EFI_OUT_OF_RESOURCES:
+ printf ("\nERROR: GenBsfImage function could not allocate required resources.\n");
+ break;
+
+ case EFI_VOLUME_CORRUPTED:
+ printf ("\nERROR: No base address was specified \n");
+ break;
+
+ default:
+ printf ("\nERROR: GenBsfImage function returned unknown status %X.\n", Status);
+ break;
+ }
+ return 2;
+ }
+
+ return 0;
+ }
+ */
+ }
+
+ //
+ // Verify the correct number of arguments
+ //
+ if (argc != ONE_BSF_ARGS && argc != TWO_BSF_ARGS) {
+ PrintUsage ();
+ return 1;
+ }
+
+ //
+ // Initialize variables
+ //
+ StartAddress1 = 0;
+ StartAddress2 = 0;
+ FwVolSize1 = 0;
+ FwVolSize2 = 0;
+ FirstRoundB = TRUE;
+ FirstRoundS = TRUE;
+
+ //
+ // Parse the command line arguments
+ //
+ for (Index = 1; Index < argc; Index += 2) {
+
+ //
+ // Make sure argument pair begin with - or /
+ //
+ if (argv[Index][0] != '-' && argv[Index][0] != '/') {
+ PrintUsage ();
+ printf ("ERROR: Argument pair must begin with \"-\" or \"/\"\n");
+ return 1;
+ }
+
+ //
+ // Make sure argument specifier is only one letter
+ //
+ if (argv[Index][2] != 0) {
+ PrintUsage ();
+ printf ("ERROR: Unrecognized argument \"%s\".\n", argv[Index]);
+ return 1;
+ }
+
+ //
+ // Determine argument to read
+ //
+ switch (argv[Index][1]) {
+
+ case 'B':
+ case 'b':
+ if (FirstRoundB) {
+ Status = AsciiStringToUint64 (argv[Index + 1], FALSE, &StartAddress1);
+ FirstRoundB = FALSE;
+ } else {
+ Status = AsciiStringToUint64 (argv[Index + 1], FALSE, &StartAddress2);
+ }
+
+ if (Status != EFI_SUCCESS) {
+ printf ("\nERROR: Bad start of address \"%s\"\n", argv[Index + 1]);
+ return 1;
+ }
+ break;
+
+ case 'S':
+ case 's':
+ if (FirstRoundS) {
+ Status = AsciiStringToUint64 (argv[Index + 1], FALSE, &FwVolSize1);
+ FirstRoundS = FALSE;
+ } else {
+ Status = AsciiStringToUint64 (argv[Index + 1], FALSE, &FwVolSize2);
+ }
+
+ if (Status != EFI_SUCCESS) {
+ printf ("\nERROR: Bad size \"%s\"\n", argv[Index + 1]);
+ return 1;
+ }
+ break;
+
+ default:
+ PrintUsage ();
+ printf ("ERROR: Unrecognized argument \"%s\".\n", argv[Index]);
+ return 1;
+ break;
+ }
+ }
+
+ //
+ // Call the GenBsfImage
+ //
+ Status = GenerateBsfImage (StartAddress1, FwVolSize1, StartAddress2, FwVolSize2);
+
+ if (EFI_ERROR (Status)) {
+ switch (Status) {
+
+ case EFI_INVALID_PARAMETER:
+ printf ("\nERROR: Invalid parameter passed to GenBsfImage function .\n");
+ break;
+
+ case EFI_ABORTED:
+ printf ("\nERROR: Error detected while creating the file image.\n");
+ break;
+
+ case EFI_OUT_OF_RESOURCES:
+ printf ("\nERROR: GenBsfImage function could not allocate required resources.\n");
+ break;
+
+ case EFI_VOLUME_CORRUPTED:
+ printf ("\nERROR: No base address was specified \n");
+ break;
+
+ default:
+ printf ("\nERROR: GenBsfImage function returned unknown status %X.\n", Status);
+ break;
+ }
+ return 2;
+ }
+ return 0;
+}
+
+EFI_STATUS
+Generate32BsfImage (
+IN UINT64 BootFileStartAddress
+ )
+/*++
+
+Routine Description:
+
+ This is the main IA32 function which will be called from application.
+ (Now this tool is not used for IA32 platform, if it will be used in future,
+ the relative functions need to be updated, the updating can refer to IPF
+ functions)
+
+Arguments:
+
+ BootFileStartAddress - Top Address of Boot File
+
+Returns:
+
+ The return value can be any of the values
+ returned by the calls to following functions:
+ Get32BsfRelatedInfoFromInfFile
+ CreateBsfBuffer
+ ProcessAndCreate32Bsf
+ Update32FfsHeader
+ WriteBsfBinary
+
+--*/
+{
+ EFI_STATUS Status;
+ UINT32 BsfSize;
+ CHAR8 OutFileName[FILE_NAME_SIZE];
+
+ EFI_GUID BsfNameGuid = EFI_IA32_BOOT_STRAP_GUID;
+
+ Status = EFI_UNSUPPORTED;
+
+ memset (OutFileName, 0, FILE_NAME_SIZE);
+
+ sprintf (
+ OutFileName, "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x-%s",
+ BsfNameGuid.Data1,
+ BsfNameGuid.Data2,
+ BsfNameGuid.Data3,
+ BsfNameGuid.Data4[0],
+ BsfNameGuid.Data4[1],
+ BsfNameGuid.Data4[2],
+ BsfNameGuid.Data4[3],
+ BsfNameGuid.Data4[4],
+ BsfNameGuid.Data4[5],
+ BsfNameGuid.Data4[6],
+ BsfNameGuid.Data4[7],
+ BSF_OUTPUT_FILE
+ );
+
+
+ Status = Get32BsfRelatedInfoFromInfFile (BSF_INPUT_FILE);
+
+ if (Status != EFI_SUCCESS) {
+ printf ("\nERROR: Error in parsing input file");
+ CleanUpMemory ();
+ return Status;
+ }
+
+ if (GetTotal32BsfSize (&BsfSize) == EFI_SUCCESS) {
+ Bsf1Buffer = malloc ((UINTN) BsfSize);
+ if (Bsf1Buffer == NULL) {
+ printf ("\nERROR: Not enough resource to create memory mapped file for Boot Strap File");
+ CleanUpMemory ();
+ return EFI_OUT_OF_RESOURCES;
+ }
+ memset (Bsf1Buffer, 0x00, (UINTN) BsfSize);
+ } else {
+ printf ("\nERROR: Could not get BSF size.");
+ CleanUpMemory ();
+ return EFI_ABORTED;
+ }
+
+ //
+ //VTF must align properly
+ //
+ Bsf1LastStartAddress = BootFileStartAddress - BsfSize;
+ Bsf1LastStartAddress = Bsf1LastStartAddress & -8;
+ BsfSize = (UINT32)BootFileStartAddress - (UINT32)Bsf1LastStartAddress;
+ Bsf1LastStartAddress = BsfSize;
+ BufferToTop = (UINT32)BootFileStartAddress - BsfSize;
+
+ Status = ProcessAndCreate32Bsf (BsfSize);
+
+ if (Status != EFI_SUCCESS) {
+ CleanUpMemory();
+ return Status;
+ }
+
+ //
+ // Write the FFS header
+ //
+ Status = Update32FfsHeader (BsfSize);
+
+ if (Status != EFI_SUCCESS) {
+ CleanUpMemory();
+ return Status;
+ }
+
+ //
+ // Calculate the Start address of this BSF
+ //
+ Bsf1Buffer = (UINT8 *)Bsf1Buffer + Bsf1LastStartAddress;
+
+ //
+ // Update the BSF buffer into specified BSF binary file
+ //
+ Status = WriteBsfBinary (OutFileName, BsfSize - (UINT32)Bsf1LastStartAddress, FIRST_VTF);
+
+ if (Status != EFI_SUCCESS) {
+ CleanUpMemory();
+ return Status;
+ }
+
+ Status = Write32SoftFit (IA32_SOFT_FIT, FileListHeadPtr);
+
+ if (Status != EFI_SUCCESS) {
+ CleanUpMemory();
+ return Status;
+ }
+
+ CleanUpMemory ();
+ printf ("\n");
+
+ return Status;
+}
+
+EFI_STATUS
+GetTotal32BsfSize(
+ IN UINT32 *BsfSize
+ )
+/*++
+
+Routine Description:
+
+ This function calculates total size for IA32 BSF which would be needed to create
+ the buffer. This will be done using Passed Info link list and looking for the
+ size of the components which belong to BSF. The addtional file header is accounted.
+
+Arguments:
+
+ BSFSize - Pointer to the size of IA32 BSF
+
+Returns:
+
+ EFI_ABORTED - Returned due to one of the following resons:
+ (a) Error Opening File
+ EFI_SUCCESS - The fuction completes successfully
+
+--*/
+{
+ PARSED_BSF_INFO *BsfInfo;
+ FILE *Fp;
+ UINT32 Alignment;
+
+ *BsfSize = 0;
+ Alignment = 0;
+
+ BsfInfo = FileListHeadPtr;
+
+ while (BsfInfo != NULL) {
+ if (BsfInfo->LocationType != SECOND_VTF) {
+
+ if ( BsfInfo->Align ) {
+ //
+ // Create additional align to compensate for component boundary requirements
+ //
+ Alignment = 1 << BsfInfo->Align;
+ *BsfSize += Alignment;
+ }
+
+ if (BsfInfo->PreferredSize) {
+ *BsfSize += BsfInfo->CompSize;
+ } else {
+ Fp = fopen (BsfInfo->CompBinName,"r+b");
+
+ if (Fp == NULL) {
+ printf ("\nERROR: Error in opening file %s", BsfInfo->CompBinName);
+ return EFI_ABORTED;
+ }
+
+ *BsfSize += _filelength (_fileno (Fp));
+
+ if (Fp) {
+ fclose (Fp);
+ }
+ }
+ }
+ BsfInfo = BsfInfo->NextBsfInfo;
+ }
+
+ //
+ // Add file header space
+ //
+ *BsfSize += sizeof (EFI_FFS_FILE_HEADER);
+
+ //
+ // Create additional to IA32 Seccore section header
+ //
+ *BsfSize += sizeof (EFI_COMMON_SECTION_HEADER);
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+ProcessAndCreate32Bsf (
+ IN UINT64 Size
+ )
+/*++
+
+Routine Description:
+
+ This function process the link list created during INF file parsing
+ and create component in IA32 BSF
+
+Arguments:
+
+ Size - Size of the Firmware Volume of which, this BSF belongs to.
+
+Returns:
+
+ EFI_UNSUPPORTED - Unknown component type
+ EFI_SUCCESS - The function completed successfully
+
+--*/
+{
+ EFI_STATUS Status;
+ PARSED_BSF_INFO *ParsedInfoPtr;
+
+ Status = EFI_SUCCESS;
+
+ ParsedInfoPtr = FileListHeadPtr;
+
+ while (ParsedInfoPtr != NULL) {
+
+ switch (ParsedInfoPtr->CompType) {
+
+ case COMP_TYPE_SECCORE:
+ Status = CreateAndUpdateSeccore (ParsedInfoPtr);
+ break;
+
+ default:
+ //
+ // Any other component type should be handled here. This will create the
+ // image in specified BSF
+ //
+ Status = CreateAndUpdate32Component (ParsedInfoPtr);
+ if (EFI_ERROR(Status)) {
+ printf ("ERROR: Updating %s component.\n", ParsedInfoPtr->CompName);
+ }
+ break;
+ }
+
+ ParsedInfoPtr = ParsedInfoPtr->NextBsfInfo;
+ }
+
+ return Status;
+}
+
+EFI_STATUS
+CreateAndUpdateSeccore (
+ IN PARSED_BSF_INFO *BsfInfo
+ )
+/*++
+
+Routine Description:
+
+ This function reads the binary file for seccore and update them
+ in IA32 BSF Buffer
+
+Arguments:
+
+ BsfInfo - Pointer to Parsed Info
+
+Returns:
+
+ EFI_ABORTED - Due to one of the following reasons:
+ (a)Error Opening File
+ (b)The PAL_A Size is more than specified size status
+ One of the values mentioned below returned from
+ call to UpdateSymFile
+ EFI_SUCCESS - The function completed successfully.
+ EFI_INVALID_PARAMETER - One of the input parameters was invalid.
+ EFI_ABORTED - An error occurred.UpdateSymFile
+ EFI_OUT_OF_RESOURCES - Memory allocation failed.
+
+--*/
+{
+ UINT8 *SecbinStartAddress;
+ UINT8 *SecfileStartAddress;
+ UINT32 FileSize;
+ UINT64 NumByteRead;
+ UINT8 *Buffer;
+ FILE *Fp;
+ UINT64 TotalLength;
+ EFI_COMMON_SECTION_HEADER *SecHeader;
+
+ Fp = fopen (BsfInfo->CompBinName, "r+b");
+
+ if (Fp == NULL) {
+ printf ("\nERROR: Opening file %s", BsfInfo->CompBinName);
+ return EFI_ABORTED;
+ }
+
+ FileSize = _filelength (_fileno (Fp));
+
+ if (BsfInfo->PreferredSize) {
+ if (FileSize > BsfInfo->CompSize) {
+ printf("\nERROR: The Seccore Size is more than specified size");
+ return EFI_ABORTED;
+ }
+
+ FileSize = BsfInfo->CompSize;
+ }
+
+ BsfInfo->CompSize = FileSize;
+
+ Buffer = malloc ((UINTN) FileSize);
+ if (Buffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ memset (Buffer, 0, (UINTN) FileSize);
+
+ //
+ // Read seccore in a buffer
+ //
+ NumByteRead = fread (Buffer, sizeof (UINT8), (UINTN) FileSize, Fp);
+ fclose (Fp);
+
+ SecfileStartAddress = (UINT8 *) Bsf1Buffer + Bsf1LastStartAddress - FileSize - sizeof (EFI_COMMON_SECTION_HEADER);
+ if (SecfileStartAddress == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ SecbinStartAddress = SecfileStartAddress + sizeof (EFI_COMMON_SECTION_HEADER);
+
+ BsfInfo->CompPreferredAddress = Bsf1LastStartAddress - FileSize + BufferToTop;
+
+ //
+ // write section header
+ //
+ memset (SecfileStartAddress, 0, sizeof (EFI_COMMON_SECTION_HEADER));
+ SecHeader = (EFI_COMMON_SECTION_HEADER *) SecfileStartAddress;
+ SecHeader->Type = EFI_SECTION_RAW;
+ TotalLength = sizeof (EFI_COMMON_SECTION_HEADER) + (UINT64) FileSize;
+ memcpy (SecHeader->Size, &TotalLength, 3);
+
+ //
+ // write seccore
+ //
+ memcpy (SecbinStartAddress, Buffer, (UINTN) FileSize);
+
+ if (Buffer) {
+ free (Buffer);
+ }
+
+ Bsf1LastStartAddress = SecfileStartAddress - (UINT8 *) Bsf1Buffer;
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+CreateAndUpdate32Component (
+ IN PARSED_BSF_INFO *BsfInfo
+ )
+/*++
+
+Routine Description:
+
+ This function reads the binary file for each components. Add it at aligned address.
+
+Arguments:
+
+ BsfInfo - Pointer to Parsed Info
+
+Returns:
+
+ EFI_SUCCESS - The function completed successful
+ EFI_ABORTED - Aborted due to one of the many reasons like:
+ (a) Component Size greater than the specified size.
+ (b) Error opening files.
+ EFI_INVALID_PARAMETER - Value returned from call to UpdateEntryPoint()
+ EFI_OUT_OF_RESOURCES - Memory allocation failed.
+
+--*/
+{
+ UINT64 CompStartAddress;
+ UINT32 FileSize;
+ UINT64 NumByteRead;
+ UINT8 *Buffer;
+ FILE *Fp;
+ UINT8 *LocalBufferPtrToWrite;
+ UINT64 Alignment;
+
+ Fp = fopen (BsfInfo->CompBinName, "r+b");
+
+ if (Fp == NULL) {
+ printf("\nERROR: Opening file %s", BsfInfo->CompBinName);
+ return EFI_ABORTED;
+ }
+
+ FileSize = _filelength (_fileno (Fp));
+
+ if (BsfInfo->PreferredSize) {
+ if (FileSize > BsfInfo->CompSize) {
+ printf("\nERROR: The component size is more than specified size");
+ return EFI_ABORTED;
+ }
+ FileSize = BsfInfo->CompSize;
+ }
+ BsfInfo->CompSize = FileSize;
+
+ Buffer = malloc ((UINTN) FileSize);
+ if (Buffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ memset (Buffer,0, (UINTN) FileSize);
+
+ NumByteRead = fread (Buffer, sizeof (UINT8), (UINTN) FileSize, Fp);
+ fclose (Fp);
+
+ CompStartAddress = Bsf1LastStartAddress - FileSize + BufferToTop;
+
+ if (BsfInfo->Align) {
+ //
+ // Create additional align to compensate for component boundary requirements
+ //
+ Alignment = 0 - (1 << BsfInfo->Align);
+ CompStartAddress = CompStartAddress & Alignment;
+ }
+
+ BsfInfo->CompPreferredAddress = CompStartAddress;
+
+ //
+ // write bin
+ //
+ LocalBufferPtrToWrite = (UINT8 *) Bsf1Buffer;
+ Bsf1LastStartAddress = CompStartAddress - BufferToTop;
+ LocalBufferPtrToWrite += Bsf1LastStartAddress;
+ memcpy (LocalBufferPtrToWrite, Buffer, (UINTN) FileSize);
+ Bsf1LastStartAddress = CompStartAddress - BufferToTop;
+
+ //
+ // Free the buffer
+ //
+ if (Buffer) {
+ free (Buffer);
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+Update32FfsHeader(
+ IN UINT32 BsfSize
+ )
+/*++
+
+Routine Description:
+
+ Update the Firmware Volume Buffer with requested buffer data
+
+Arguments:
+
+ BsfSize - Size of the IA32 BSF
+
+Returns:
+
+ EFI_SUCCESS - The function completed successfully
+ EFI_INVALID_PARAMETER - The Ffs File Header Pointer is NULL
+
+--*/
+{
+ EFI_FFS_FILE_HEADER *FileHeader;
+ UINT32 TotalBsfSize;
+ EFI_GUID EfiFirmwareVolumeTopFileGuid = EFI_FFS_VOLUME_TOP_FILE_GUID;
+
+
+ //
+ // Find the BSF file header location, the bsf file must be 8 bytes aligned
+ //
+ Bsf1LastStartAddress -= sizeof (EFI_FFS_FILE_HEADER);
+ Bsf1LastStartAddress += BufferToTop;
+ Bsf1LastStartAddress = Bsf1LastStartAddress & -8;
+ Bsf1LastStartAddress -= BufferToTop;
+ FileHeader = (EFI_FFS_FILE_HEADER*)((UINT8*)Bsf1Buffer + Bsf1LastStartAddress);
+
+ if (FileHeader == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // write header
+ //
+ memset (FileHeader, 0, sizeof(EFI_FFS_FILE_HEADER));
+ memcpy (&FileHeader->Name, &EfiFirmwareVolumeTopFileGuid, sizeof (EFI_GUID));
+
+ FileHeader->Type = EFI_FV_FILETYPE_FREEFORM;
+ FileHeader->Attributes = FFS_ATTRIB_CHECKSUM;
+
+ //
+ // Now FileSize includes the EFI_FFS_FILE_HEADER
+ //
+ TotalBsfSize = BsfSize - (UINT32)Bsf1LastStartAddress;
+ FileHeader->Size[0] = (UINT8) (TotalBsfSize & 0x000000FF);
+ FileHeader->Size[1] = (UINT8) ((TotalBsfSize & 0x0000FF00) >> 8);
+ FileHeader->Size[2] = (UINT8) ((TotalBsfSize & 0x00FF0000) >> 16);
+
+ //
+ // Fill in checksums and state, all three must be zero for the checksums.
+ //
+ FileHeader->IntegrityCheck.Checksum.Header = 0;
+ FileHeader->IntegrityCheck.Checksum.File = 0;
+ FileHeader->State = 0;
+ FileHeader->IntegrityCheck.Checksum.Header = CalculateChecksum8 ((UINT8*) FileHeader, sizeof (EFI_FFS_FILE_HEADER));
+ FileHeader->IntegrityCheck.Checksum.File = CalculateChecksum8 ((UINT8*) FileHeader, TotalBsfSize);
+ FileHeader->State = EFI_FILE_HEADER_CONSTRUCTION | EFI_FILE_HEADER_VALID | EFI_FILE_DATA_VALID;
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+Get32BsfRelatedInfoFromInfFile (
+ IN CHAR8 *FileName
+ )
+/*++
+
+Routine Description:
+
+ This function reads the input file, parse it and create a list of tokens
+ which is parsed and used, to intialize the data related to IA32 BSF
+
+Arguments:
+
+ FileName FileName which needed to be read to parse data
+
+Returns:
+
+ EFI_ABORTED Error in opening file
+ EFI_INVALID_PARAMETER File doesn't contain any valid informations
+ EFI_OUT_OF_RESOURCES Malloc Failed
+ EFI_SUCCESS The function completed successfully
+
+--*/
+{
+ FILE *Fp;
+ UINTN Index;
+ EFI_STATUS Status;
+
+ Fp = fopen (FileName, "r");
+ if (Fp == NULL) {
+ printf ("\nERROR: Error in opening %s file\n", FileName);
+ return EFI_ABORTED;
+ }
+
+ ValidLineCount (Fp);
+
+ if (ValidLineNum == 0) {
+ printf ("\nERROR: File doesn't contain any valid informations");
+ return EFI_INVALID_PARAMETER;
+ }
+
+ TokenStr = (CHAR8 **)malloc (sizeof (UINTN) * (2 * ValidLineNum + 1));
+
+ if (TokenStr == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ memset (TokenStr, 0, (sizeof (UINTN) * (2 * ValidLineNum + 1)));
+ OrgStrTokPtr = TokenStr;
+
+ for (Index = 0; Index < (2 * ValidLineNum); Index++) {
+ *TokenStr = (CHAR8 *)malloc (sizeof (CHAR8) * FILE_NAME_SIZE);
+
+ if (*TokenStr == NULL) {
+ free (OrgStrTokPtr);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ memset (*TokenStr, 0, FILE_NAME_SIZE);
+// free (*TokenStr);
+ TokenStr++;
+ }
+
+ TokenStr = NULL;
+ TokenStr = OrgStrTokPtr;
+ fseek (Fp, 0L, SEEK_SET);
+
+ Status = InitializeComps();
+
+ if (Status != EFI_SUCCESS) {
+ free (TokenStr);
+ return Status;
+ }
+ ParseInputFile (Fp);
+ Initialize32InFileInfo ();
+
+ if (Fp) {
+ fclose (Fp);
+ }
+ free (TokenStr);
+ return EFI_SUCCESS;
+}
+
+VOID
+Initialize32InFileInfo (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function intializes the relevant global variable which is being
+ used to store the information retrieved from IA32 INF file.
+
+Arguments:
+
+ NONE
+
+Returns:
+
+ NONE
+
+--*/
+{
+ UINTN SectionOptionFlag;
+ UINTN SectionCompFlag;
+
+ SectionOptionFlag =0 ;
+ SectionCompFlag = 0;
+ TokenStr = OrgStrTokPtr;
+ while (*TokenStr != NULL) {
+ if (_stricmp (*TokenStr, "[OPTIONS]") == 0) {
+ SectionOptionFlag = 1;
+ SectionCompFlag = 0;
+ }
+
+ if (_stricmp (*TokenStr, "[COMPONENTS]") == 0) {
+ if (FileListPtr == NULL) {
+ FileListPtr = FileListHeadPtr;
+ }
+
+ SectionCompFlag = 1;
+ SectionOptionFlag = 0;
+ TokenStr++;
+ }
+
+ if (SectionOptionFlag) {
+ if (_stricmp (*TokenStr, "IA32_RST_BIN") == 0) {
+ *TokenStr++;
+ strcpy (IA32BinFile, *TokenStr);
+ }
+ }
+
+ if (SectionCompFlag) {
+ if (_stricmp (*TokenStr, "COMP_NAME") == 0) {
+ TokenStr++;
+ strcpy (FileListPtr->CompName, *TokenStr);
+ TokenStr++;
+ ParseAndUpdate32Components (FileListPtr);
+ }
+
+ if (*TokenStr != NULL) {
+ FileListPtr->NextBsfInfo = malloc (sizeof (PARSED_BSF_INFO));
+ if (FileListPtr->NextBsfInfo == NULL) {
+ printf ("Error: Out of memory resources.\n");
+ break;
+ }
+ FileListPtr = FileListPtr->NextBsfInfo;
+ memset (FileListPtr, 0, sizeof(PARSED_BSF_INFO));
+ FileListPtr->NextBsfInfo = NULL;
+ continue;
+ } else {
+ break;
+ }
+ }
+
+ TokenStr++;
+ }
+}
+
+VOID
+ParseAndUpdate32Components (
+ IN PARSED_BSF_INFO *BsfInfo
+ )
+/*++
+
+Routine Description:
+
+ This function intializes the relevant global variable which is being
+ used to store the information retrieved from INF file.
+
+Arguments:
+
+ BsfInfo - A pointer to the BSF Info Structure
+
+
+Returns:
+
+ None
+
+--*/
+{
+ UINT64 StringValue;
+ UINT64 AlignStringValue;
+
+ while (*TokenStr != NULL && (_stricmp (*TokenStr, "COMP_NAME") != 0)) {
+
+ if (_stricmp (*TokenStr, "COMP_LOC") == 0) {
+ TokenStr++;
+ if (_stricmp (*TokenStr, "B") == 0) {
+ BsfInfo->LocationType = FIRST_VTF;
+ } else if (_stricmp (*TokenStr, "N") == 0) {
+ BsfInfo->LocationType = SECOND_VTF;
+ } else {
+ BsfInfo->LocationType = NONE;
+ printf ("\nERROR: Unknown location for component %s", BsfInfo->CompName);
+ }
+ } else if (_stricmp (*TokenStr, "COMP_TYPE") == 0) {
+ TokenStr++;
+ if (AsciiStringToUint64 (*TokenStr, FALSE, &StringValue) != EFI_SUCCESS) {
+ printf ("\nERROR: Could not read a numeric value from \"%s\".", TokenStr);
+ return;
+ }
+ BsfInfo->CompType = (UINT8) StringValue;
+ } else if (_stricmp (*TokenStr, "COMP_VER") == 0) {
+ TokenStr++;
+ if (_stricmp (*TokenStr, "-") == 0) {
+ BsfInfo->VersionPresent = FALSE;
+ BsfInfo->MajorVer = 0;
+ BsfInfo->MinorVer = 0;
+ } else {
+ BsfInfo->VersionPresent = TRUE;
+ ConvertVersionInfo (*TokenStr, &BsfInfo->MajorVer, &BsfInfo->MinorVer);
+ }
+ } else if (_stricmp (*TokenStr, "COMP_BIN") == 0) {
+ TokenStr++;
+ strcpy (BsfInfo->CompBinName, *TokenStr);
+ } else if (_stricmp (*TokenStr, "COMP_SYM") == 0) {
+ TokenStr++;
+ strcpy (BsfInfo->CompSymName, *TokenStr);
+ } else if (_stricmp (*TokenStr, "COMP_SIZE") == 0) {
+ TokenStr++;
+ if (_stricmp (*TokenStr, "-") == 0) {
+ BsfInfo->PreferredSize = FALSE;
+ BsfInfo->CompSize = 0;
+ } else {
+ BsfInfo->PreferredSize = TRUE;
+ if (AsciiStringToUint64 (*TokenStr, FALSE, &StringValue) != EFI_SUCCESS) {
+ printf ("\nERROR: Could not read a numeric value from \"%s\".", TokenStr);
+ return;
+ }
+ BsfInfo->CompSize = (UINTN) StringValue;
+ }
+
+ } else if (_stricmp (*TokenStr, "COMP_CS") == 0) {
+ TokenStr++;
+ if (_stricmp (*TokenStr, "1") == 0) {
+ BsfInfo->CheckSumRequired = 1;
+ } else if (_stricmp (*TokenStr, "0") == 0) {
+ BsfInfo->CheckSumRequired = 0;
+ } else {
+ printf ("\nERROR: Bad information in INF file about Checksum required field");
+ }
+ } else if (_stricmp (*TokenStr, "COMP_ALIGN") == 0) {
+ TokenStr++;
+ if (AsciiStringToUint64 (*TokenStr, FALSE, &AlignStringValue) != EFI_SUCCESS) {
+ printf ("\nERROR: Could not read a numeric value from \"%s\".", TokenStr);
+ return;
+ }
+ if (AlignStringValue >= 0) {
+ BsfInfo->Align = (UINT32) AlignStringValue;
+ } else {
+ printf ("\nERROR: invalid align \"%s\".", AlignStringValue);
+ return;
+ }
+ }
+ TokenStr++;
+ if (*TokenStr == NULL) {
+ break;
+ }
+ }
+}
+
+EFI_STATUS
+Write32SoftFit(
+ IN CHAR8 *FileName,
+ IN PARSED_BSF_INFO *BsfInfo
+ )
+/*++
+
+Routine Description:
+
+ Write IA32 Firmware Volume component address from memory to a file.
+
+Arguments:
+
+ FileName Output File Name which needed to be created/
+ BsfInfo Parsed info link
+
+Returns:
+
+ EFI_ABORTED - Returned due to one of the following resons:
+ (a) Error Opening File
+ (b) Failing to copy buffers
+ EFI_SUCCESS - The function completes successfully
+
+--*/
+{
+ FILE *Fp;
+
+ Fp = fopen (FileName, "w+t");
+ if (Fp == NULL) {
+ printf ("Error in opening file %s\n", FileName);
+ return EFI_ABORTED;
+ }
+
+ while (BsfInfo != NULL) {
+ if (strlen (BsfInfo->CompName) != 0) {
+ fprintf (Fp, "\n%s\n", BsfInfo->CompName);
+ } else {
+ fprintf (Fp, "\n%s\n", "Name not available");
+ }
+
+ fprintf (Fp, "%d\n", BsfInfo->CompPreferredAddress);
+ fprintf (Fp, "%d\n", BsfInfo->CompSize);
+ fprintf (Fp, "%d\n", BsfInfo->Align);
+
+ BsfInfo = BsfInfo->NextBsfInfo;
+ }
+
+ if (Fp) {
+ fclose (Fp);
+ }
+
+ return EFI_SUCCESS;
+}
diff --git a/Source/GenBsfImage/GenBsfImage.h b/Source/GenBsfImage/GenBsfImage.h
new file mode 100644
index 0000000..1efbebc
--- /dev/null
+++ b/Source/GenBsfImage/GenBsfImage.h
@@ -0,0 +1,633 @@
+/*++
+
+Copyright (c) 1999 - 2002 Intel Corporation. All rights reserved
+This software and associated documentation (if any) is furnished
+under a license and may only be used or copied in accordance
+with the terms of the license. Except as permitted by such
+license, no part of this software or documentation may be
+reproduced, stored in a retrieval system, or transmitted in any
+form or by any means without the express written consent of
+Intel Corporation.
+
+
+Module Name:
+
+ GenBsfImage.h
+
+Abstract:
+
+ This file contains the relevant declarations required
+ to generate Boot Strap File
+
+--*/
+
+//
+// Module Coded to EFI 2.0 Coding Conventions
+//
+#ifndef _EFI_GEN_BSF_IMAGE_H
+#define _EFI_GEN_BSF_IMAGE_H
+
+//
+// External Files Referenced
+//
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <io.h>
+#include "assert.h"
+// #include "TianoCommon.h"
+#include "Common/FirmwareFileSystem.h"
+#include "Common/FirmwareVolumeHeader.h"
+#include "ParseInf.h"
+
+//
+// Internal Constants
+//
+#define EFI_IPF_VTF1_GUID \
+ { \
+ 0xfa371c9b, 0x5a86, 0x4198, 0xab, 0xc2, 0xed, 0x3f, 0xaa, 0xce, 0xb0, 0x8b \
+ };
+
+#define EFI_IPF_VTF2_GUID \
+ { \
+ 0x624a0d5a, 0x315f, 0x40b6, 0xa6, 0x33, 0xe5, 0xf7, 0xde, 0x58, 0x20, 0xa0 \
+ };
+
+#define EFI_IA32_BOOT_STRAP_GUID \
+ { \
+ 0xd4260a8d, 0x356, 0x4f45, 0x85, 0xe9, 0xad, 0x1d, 0x79, 0x22, 0x79, 0xf0 \
+ };
+
+#define CV_N_TYPE(a,b) (UINT8)(((UINT8)a << 7) + (UINT8)b) // Keeps the CV and Type in same byte field
+#define MAKE_VERSION(a,b) (UINT16)(((UINT16)a << 8) + (UINT16)b)
+
+#define FILE_NAME_SIZE 256
+#define COMPONENT_NAME_SIZE 128
+#define BSF_INPUT_FILE "BSF.INF"
+#define BSF_OUTPUT_FILE "Bsf.RAW"
+#define BSF_SYM_FILE "Bsf.SYM"
+#define FIT_SIGNATURE "_FIT_ "
+
+//
+// This is IA32 seccore
+//
+#define COMP_TYPE_SECCORE 0x0F
+
+//
+//Fit Type Definition
+//
+#define COMP_TYPE_FIT_HEADER 0x00
+#define COMP_TYPE_FIT_PAL_B 0x01
+
+//
+// This is generic PAL_A
+//
+#define COMP_TYPE_FIT_PAL_A 0x0F
+#define COMP_TYPE_FIT_PEICORE 0x10
+#define COMP_TYPE_FIT_AUTOSCAN 0x30
+#define COMP_TYPE_FIT_FV_BOOT 0x7E
+
+//
+//This is processor Specific PAL_A
+//
+#define COMP_TYPE_FIT_PAL_A_SPECIFIC 0x0E
+#define COMP_TYPE_FIT_UNUSED 0x7F
+
+#define FIT_TYPE_MASK 0x7F
+#define CHECKSUM_BIT_MASK 0x80
+
+//
+// IPF processor address is cached bit
+//
+#define IPF_CACHE_BIT 0x8000000000000000
+
+//
+// Size definition to calculate the location from top of address for
+// each component
+//
+#define SIZE_IA32_RESET_VECT 0x10 // 16 Bytes
+#define SIZE_SALE_ENTRY_POINT 0x08 // 8 Byte
+#define SIZE_FIT_TABLE_ADD 0x08 // 8 Byte
+#define SIZE_FIT_TABLE_PAL_A 0x10
+#define SIZE_RESERVED 0x10
+
+
+#define SIZE_TO_OFFSET_PAL_A_END (SIZE_IA32_RESET_VECT + SIZE_SALE_ENTRY_POINT + \
+ SIZE_FIT_TABLE_ADD + SIZE_FIT_TABLE_PAL_A + \
+ SIZE_RESERVED)
+#define SIZE_TO_PAL_A_FIT (SIZE_IA32_RESET_VECT + SIZE_SALE_ENTRY_POINT + \
+ SIZE_FIT_TABLE_ADD + SIZE_FIT_TABLE_PAL_A)
+
+#define SIZE_OF_PAL_HEADER 0x40 //PAL has 64 byte header
+
+//
+// Utility Name
+//
+#define UTILITY_NAME "GenBsfImage"
+
+//
+// Utility version information
+//
+#define UTILITY_MAJOR_VERSION 0
+#define UTILITY_MINOR_VERSION 0
+#define UTILITY_DATE __DATE__
+
+//
+// The maximum number of arguments accepted from the command line.
+//
+#define ONE_BSF_ARGS 5
+#define TWO_BSF_ARGS 9
+
+//
+// The number of IA32 bsf arguments accepted from the command line.
+//
+#define IA32_ARGS 3
+
+#define IA32_SOFT_FIT "IA32BsfAddress.inf"
+
+//
+// Internal Data Structure
+//
+typedef enum _LOC_TYPE
+{
+ NONE, // In case there is - INF file
+ FIRST_VTF, // First VTF
+ SECOND_VTF, // Outside BSF
+} LOC_TYPE;
+
+typedef struct _PARSED_BSF_INFO {
+ CHAR8 CompName[COMPONENT_NAME_SIZE];
+ LOC_TYPE LocationType;
+ UINT8 CompType;
+ UINT8 MajorVer;
+ UINT8 MinorVer;
+ UINT8 CheckSumRequired;
+ BOOLEAN VersionPresent; // If it is TRUE, then, Version is in INF file
+ BOOLEAN PreferredSize;
+ BOOLEAN PreferredAddress;
+ CHAR8 CompBinName[FILE_NAME_SIZE];
+ CHAR8 CompSymName[FILE_NAME_SIZE];
+ UINTN CompSize;
+ UINT64 CompPreferredAddress;
+ UINT32 Align;
+
+ //
+ // Fixed - warning C4133: '=' : incompatible types - from 'struct _ParsedBsfInfo *' to 'struct _PARSED_BSF_INFO *'
+ // Fixed - warning C4133: '=' : incompatible types - from 'struct _ParsedBsfInfo *' to 'struct _PARSED_BSF_INFO *'
+ // Fixed - warning C4133: '=' : incompatible types - from 'struct _ParsedBsfInfo *' to 'struct _PARSED_BSF_INFO *'
+ // Fixed - warning C4133: '=' : incompatible types - from 'struct _ParsedBsfInfo *' to 'struct _PARSED_BSF_INFO *'
+ //
+ struct _PARSED_BSF_INFO *NextBsfInfo;
+} PARSED_BSF_INFO;
+
+#pragma pack (1)
+typedef struct {
+ UINT64 CompAddress;
+ UINT32 CompSize;
+ UINT16 CompVersion;
+ UINT8 CvAndType;
+ UINT8 CheckSum;
+} FIT_TABLE;
+#pragma pack ()
+
+//
+// The function that displays general utility information
+//
+VOID
+PrintUtilityInfo (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Displays the standard utility information to SDTOUT
+
+Arguments:
+
+ None
+
+Returns:
+
+ None
+
+--*/
+;
+
+//
+// The function that displays the utility usage message.
+//
+VOID
+PrintUsage (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Displays the utility usage syntax to STDOUT
+
+Arguments:
+
+ None
+
+Returns:
+
+ None
+
+--*/
+;
+
+//
+// Other Function Prototype Declarations
+//
+
+EFI_STATUS
+UpdateBsfBuffer(
+ IN UINT64 StartAddress,
+ IN UINT8 *Buffer,
+ IN UINT64 DataSize,
+ IN LOC_TYPE LocType
+ )
+/*++
+
+Routine Description:
+
+ Update the Firmware Volume Buffer with requested buffer data
+
+Arguments:
+
+ StartAddress - StartAddress in buffer. This number will automatically
+ point to right address in buffer where data needed
+ to be updated.
+ Buffer - Buffer pointer from data will be copied to memory mapped buffer.
+ DataSize - Size of the data needed to be copied.
+ LocType - The type of the BSF
+
+Returns:
+
+ EFI_ABORTED - The input parameter is error
+ EFI_SUCCESS - The function completed successfully
+
+--*/
+;
+
+EFI_STATUS
+UpdateSymFile (
+ IN UINT64 BaseAddress,
+ IN CHAR8 *DestFileName,
+ IN CHAR8 *SourceFileName
+ )
+/*++
+
+Routine Description:
+
+ This function adds the SYM tokens in the source file to the destination file.
+ The SYM tokens are updated to reflect the base address.
+
+Arguments:
+
+ BaseAddress - The base address for the new SYM tokens.
+ DestFileName - The destination file.
+ SourceFileName - The source file.
+
+Returns:
+
+ EFI_SUCCESS - The function completed successfully.
+ EFI_INVALID_PARAMETER - One of the input parameters was invalid.
+ EFI_ABORTED - An error occurred.
+
+--*/
+;
+
+EFI_STATUS
+CalculateFitTableChecksum (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function will perform byte checksum on the FIT table, if the the checksum required
+ field is set to CheckSum required. If the checksum is not required then checksum byte
+ will have value as 0;.
+
+Arguments:
+
+ NONE
+
+Returns:
+
+ Status - Value returned by call to CalculateChecksum8 ()
+ EFI_SUCCESS - The function completed successfully
+
+--*/
+;
+
+EFI_STATUS
+GenerateBsfImage (
+ IN UINT64 StartAddress1,
+ IN UINT64 Size1,
+ IN UINT64 StartAddress2,
+ IN UINT64 Size2
+ )
+/*++
+
+Routine Description:
+
+ This is the main function which will be called from application.
+
+Arguments:
+
+ StartAddress1 - The start address of the first BSF
+ Size1 - The size of the first BSF
+ StartAddress2 - The start address of the second BSF
+ Size2 - The size of the second BSF
+
+Returns:
+
+ EFI_OUT_OF_RESOURCES - Can not allocate memory
+ The return value can be any of the values
+ returned by the calls to following functions:
+ GetBsfRelatedInfoFromInfFile
+ ProcessAndCreateBsf
+ UpdateIA32ResetVector
+ UpdateFfsHeader
+ WriteBsfBinary
+
+--*/
+;
+
+EFI_STATUS
+PeimFixupInFitTable (
+ IN UINT64 StartAddress
+ )
+/*++
+
+Routine Description:
+
+ This function is an entry point to fixup SAL-E entry point.
+
+Arguments:
+
+ StartAddress - StartAddress for PEIM.....
+
+Returns:
+
+ EFI_SUCCESS - The function completed successfully
+ EFI_ABORTED - Error Opening File
+
+--*/
+;
+
+EFI_STATUS
+Generate32BsfImage (
+IN UINT64 BootFileStartAddress
+ )
+/*++
+
+Routine Description:
+
+ This is the main IA32 function which will be called from application.
+ (Now this tool is not used for IA32 platform, if it will be used in future,
+ the relative functions need to be updated, the updating can refer to IPF
+ functions)
+
+Arguments:
+
+ BootFileStartAddress - Top Address of Boot File
+
+Returns:
+
+ The return value can be any of the values
+ returned by the calls to following functions:
+ Get32BsfRelatedInfoFromInfFile
+ CreateBsfBuffer
+ ProcessAndCreate32Bsf
+ Update32FfsHeader
+ WriteBsfBinary
+
+--*/
+;
+
+EFI_STATUS
+GetTotal32BsfSize(
+ IN UINT32 *BsfSize
+ )
+/*++
+
+Routine Description:
+
+ This function calculates total size for IA32 BSF which would be needed to create
+ the buffer. This will be done using Passed Info link list and looking for the
+ size of the components which belong to BSF. The addtional file header is accounted.
+
+Arguments:
+
+ BSFSize - Pointer to the size of IA32 BSF
+
+Returns:
+
+ EFI_ABORTED - Returned due to one of the following resons:
+ (a) Error Opening File
+ EFI_SUCCESS - The fuction completes successfully
+
+--*/
+;
+
+EFI_STATUS
+ProcessAndCreate32Bsf (
+ IN UINT64 Size
+ )
+/*++
+
+Routine Description:
+
+ This function process the link list created during INF file parsing
+ and create component in IA32 BSF
+
+Arguments:
+
+ Size - Size of the Firmware Volume of which, this BSF belongs to.
+
+Returns:
+
+ EFI_UNSUPPORTED - Unknown component type
+ EFI_SUCCESS - The function completed successfully
+
+--*/
+;
+
+EFI_STATUS
+CreateAndUpdateSeccore (
+ IN PARSED_BSF_INFO *BsfInfo
+ )
+/*++
+
+Routine Description:
+
+ This function reads the binary file for seccore and update them
+ in IA32 BSF Buffer
+
+Arguments:
+
+ BsfInfo - Pointer to Parsed Info
+
+Returns:
+
+ EFI_ABORTED - Due to one of the following reasons:
+ (a)Error Opening File
+ (b)The PAL_A Size is more than specified size status
+ One of the values mentioned below returned from
+ call to UpdateSymFile
+ EFI_SUCCESS - The function completed successfully.
+ EFI_INVALID_PARAMETER - One of the input parameters was invalid.
+ EFI_ABORTED - An error occurred.UpdateSymFile
+
+--*/
+;
+
+EFI_STATUS
+CreateAndUpdate32Component (
+ IN PARSED_BSF_INFO *BsfInfo
+ )
+/*++
+
+Routine Description:
+
+ This function reads the binary file for each components. Add it at aligned address.
+
+Arguments:
+
+ BsfInfo - Pointer to Parsed Info
+
+Returns:
+
+ EFI_SUCCESS - The function completed successful
+ EFI_ABORTED - Aborted due to one of the many reasons like:
+ (a) Component Size greater than the specified size.
+ (b) Error opening files.
+ EFI_INVALID_PARAMETER - Value returned from call to UpdateEntryPoint()
+
+--*/
+;
+
+EFI_STATUS
+Update32FfsHeader(
+ IN UINT32 BsfSize
+ )
+/*++
+
+Routine Description:
+
+ Update the Firmware Volume Buffer with requested buffer data
+
+Arguments:
+
+ BsfSize - Size of the IA32 BSF
+
+Returns:
+
+ EFI_SUCCESS - The function completed successfully
+ EFI_INVALID_PARAMETER - The Ffs File Header Pointer is NULL
+
+--*/
+;
+
+EFI_STATUS
+Get32BsfRelatedInfoFromInfFile (
+ IN CHAR8 *FileName
+ )
+/*++
+
+Routine Description:
+
+ This function reads the input file, parse it and create a list of tokens
+ which is parsed and used, to intialize the data related to IA32 BSF
+
+Arguments:
+
+ FileName FileName which needed to be read to parse data
+
+Returns:
+
+ EFI_ABORTED Error in opening file
+ EFI_INVALID_PARAMETER File doesn't contain any valid informations
+ EFI_OUT_OF_RESOURCES Malloc Failed
+ EFI_SUCCESS The function completed successfully
+
+--*/
+;
+
+VOID
+Initialize32InFileInfo (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function intializes the relevant global variable which is being
+ used to store the information retrieved from IA32 INF file.
+
+Arguments:
+
+ NONE
+
+Returns:
+
+ NONE
+
+--*/
+;
+
+VOID
+ParseAndUpdate32Components (
+ IN PARSED_BSF_INFO *BsfInfo
+ )
+/*++
+
+Routine Description:
+
+ This function intializes the relevant global variable which is being
+ used to store the information retrieved from INF file.
+
+Arguments:
+
+ BsfInfo - A pointer to the BSF Info Structure
+
+
+Returns:
+
+ None
+
+--*/
+;
+
+EFI_STATUS
+Write32SoftFit(
+ IN CHAR8 *FileName,
+ IN PARSED_BSF_INFO *BsfInfo
+ )
+/*++
+
+Routine Description:
+
+ Write IA32 Firmware Volume component address from memory to a file.
+
+Arguments:
+
+ FileName Output File Name which needed to be created/
+ BsfInfo Parsed info link
+
+Returns:
+
+ EFI_ABORTED - Returned due to one of the following resons:
+ (a) Error Opening File
+ (b) Failing to copy buffers
+ EFI_SUCCESS - The fuction completes successfully
+
+--*/
+;
+
+#endif
diff --git a/Source/GenBsfImage/build.xml b/Source/GenBsfImage/build.xml
new file mode 100644
index 0000000..fe8f202
--- /dev/null
+++ b/Source/GenBsfImage/build.xml
@@ -0,0 +1,126 @@
+<?xml version="1.0" ?>
+<!--
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+-->
+<project default="GenTool" basedir=".">
+<!--
+ EDK GenFvImage Tool
+ Copyright (c) 2006, Intel Corporation
+-->
+ <property name="ToolName" value="GenBsfImage"/>
+ <property name="FileSet" value="GenBsfImage.c"/>
+
+ <taskdef resource="net/sf/antcontrib/antlib.xml"/>
+
+ <property name="LINK_OUTPUT_TYPE" value="static"/>
+ <property name="BUILD_DIR" value="${PACKAGE_DIR}/${ToolName}/tmp"/>
+
+ <target name="GenTool" depends="init, Tool">
+ <echo message="The EDK Tool: ${ToolName} build has completed"/>
+ </target>
+
+ <target name="init">
+ <echo message="Building the EDK Tool: ${ToolName}"/>
+ <mkdir dir="${BUILD_DIR}"/>
+ <if>
+ <istrue value="${OSX}"/>
+ <then>
+ <property name="syslibdirs" value=""/>
+ <property name="syslibs" value=""/>
+ </then>
+ </if>
+
+ <if>
+ <istrue value="${cygwin}"/>
+ <then>
+ <property name="syslibdirs" value="${env.CYGWIN_HOME}/lib/e2fsprogs"/>
+ <property name="syslibs" value="uuid"/>
+ </then>
+ </if>
+
+ <if>
+ <istrue value="${msft}"/>
+ <then>
+ <property name="syslibdirs" value=""/>
+ <property name="syslibs" value="uuid"/>
+ </then>
+ </if>
+
+ <if>
+ <istrue value="${linux}"/>
+ <then>
+ <if>
+ <istrue value="${x86_64_linux}"/>
+ <then>
+ <property name="syslibdirs" value="/lib64"/>
+ </then>
+ <else>
+ <property name="syslibdirs" value="/usr/lib"/>
+ </else>
+ </if>
+ <property name="syslibs" value="uuid"/>
+ </then>
+ </if>
+ <echo message="syslibdirs set to: ${syslibdirs}"/>
+ </target>
+
+ <target name="Tool" depends="init, GenBsfImage"/>
+
+ <target name="GenBsfImage" >
+ <cc name="${ToolChain}" objdir="${BUILD_DIR}"
+ outfile="${BIN_DIR}/${ToolName}"
+ outtype="executable"
+ debug="true"
+ optimize="speed">
+ <compilerarg value="${ExtraArgus}" if="ExtraArgus" />
+
+ <defineset>
+ <define name="BUILDING_TOOLS"/>
+ <define name="TOOL_BUILD_IA32_TARGET"/>
+ </defineset>
+
+ <fileset dir="${basedir}/${ToolName}"
+ includes="${FileSet}"/>
+
+ <includepath path="${PACKAGE_DIR}/${ToolName}"/>
+ <includepath path="${PACKAGE_DIR}/Include"/>
+ <includepath path="${PACKAGE_DIR}/Include/${HostArch}"/>
+ <includepath path="${PACKAGE_DIR}/Common"/>
+ <libset dir="${LIB_DIR}" libs="CommonTools"/>
+
+ <!-- <linkerarg value="/nodefaultlib:libc.lib" if="msft"/>
+ <syslibset dir="${syslibdirs}" libs="${syslibs}" if="cyglinux"/>
+ <syslibset libs="RpcRT4" if="msft"/> -->
+ </cc>
+ </target>
+
+ <target name="clean">
+ <echo message="Removing Intermediate Files Only"/>
+ <delete>
+ <fileset dir="${BUILD_DIR}" includes="*.obj"/>
+ </delete>
+ </target>
+
+ <target name="cleanall">
+ <echo message="Removing Object Files and the Executable: ${ToolName}${ext_exe}"/>
+ <delete failonerror="false" quiet="true" includeEmptyDirs="true">
+ <fileset dir="${BUILD_DIR}"/>
+ <fileset file="${BIN_DIR}/${ToolName}_Ia32${ext_exe}"/>
+ <fileset file="${BIN_DIR}/${ToolName}_X64${ext_exe}"/>
+ <fileset file="${BIN_DIR}/${ToolName}${ext_exe}"/>
+ <fileset file="${BIN_DIR}/${ToolName}_Ipf${ext_exe}"/>
+ <fileset file="${BIN_DIR}/${ToolName}_Ia32.pdb"/>
+ <fileset file="${BIN_DIR}/${ToolName}_X64.pdb"/>
+ <fileset file="${BIN_DIR}/${ToolName}.pdb"/>
+ <fileset file="${BIN_DIR}/${ToolName}_Ipf.pdb"/>
+ </delete>
+ </target>
+
+</project>
diff --git a/Source/GenCRC32Section/GenCRC32Section.c b/Source/GenCRC32Section/GenCRC32Section.c
new file mode 100644
index 0000000..b99cf2f
--- /dev/null
+++ b/Source/GenCRC32Section/GenCRC32Section.c
@@ -0,0 +1,286 @@
+/*++
+
+Copyright (c) 2004, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ GenCRC32Section.c
+
+Abstract:
+
+ This file contains functions required to generate a Firmware File System
+ file. The code is compliant with the Tiano C Coding standards.
+
+--*/
+
+#include "GenCRC32Section.h"
+
+#define TOOLVERSION "0.2"
+
+#define UTILITY_NAME "GenCrc32Section"
+
+EFI_GUID gEfiCrc32SectionGuid = EFI_CRC32_GUIDED_SECTION_EXTRACTION_PROTOCOL_GUID;
+
+EFI_STATUS
+SignSectionWithCrc32 (
+ IN OUT UINT8 *FileBuffer,
+ IN OUT UINT32 *BufferSize,
+ IN UINT32 DataSize
+ )
+/*++
+
+Routine Description:
+
+ Signs the section with CRC32 and add GUIDed section header for the
+ signed data. data stays in same location (overwrites source data).
+
+Arguments:
+
+ FileBuffer - Buffer containing data to sign
+
+ BufferSize - On input, the size of FileBuffer. On output, the size of
+ actual section data (including added section header).
+
+ DataSize - Length of data to Sign
+
+ Key - Key to use when signing. Currently only CRC32 is supported.
+
+Returns:
+
+ EFI_SUCCESS - Successful
+ EFI_OUT_OF_RESOURCES - Not enough resource to complete the operation.
+
+--*/
+{
+
+ UINT32 Crc32Checksum;
+ EFI_STATUS Status;
+ UINT32 TotalSize;
+ CRC32_SECTION_HEADER Crc32Header;
+ UINT8 *SwapBuffer;
+
+ Crc32Checksum = 0;
+ SwapBuffer = NULL;
+
+ if (DataSize == 0) {
+ *BufferSize = 0;
+
+ return EFI_SUCCESS;
+ }
+
+ Status = CalculateCrc32 (FileBuffer, DataSize, &Crc32Checksum);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ TotalSize = DataSize + CRC32_SECTION_HEADER_SIZE;
+ Crc32Header.GuidSectionHeader.CommonHeader.Type = EFI_SECTION_GUID_DEFINED;
+ Crc32Header.GuidSectionHeader.CommonHeader.Size[0] = (UINT8) (TotalSize & 0xff);
+ Crc32Header.GuidSectionHeader.CommonHeader.Size[1] = (UINT8) ((TotalSize & 0xff00) >> 8);
+ Crc32Header.GuidSectionHeader.CommonHeader.Size[2] = (UINT8) ((TotalSize & 0xff0000) >> 16);
+ memcpy (&(Crc32Header.GuidSectionHeader.SectionDefinitionGuid), &gEfiCrc32SectionGuid, sizeof (EFI_GUID));
+ Crc32Header.GuidSectionHeader.Attributes = EFI_GUIDED_SECTION_AUTH_STATUS_VALID;
+ Crc32Header.GuidSectionHeader.DataOffset = CRC32_SECTION_HEADER_SIZE;
+ Crc32Header.CRC32Checksum = Crc32Checksum;
+
+ SwapBuffer = (UINT8 *) malloc (DataSize);
+ if (SwapBuffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ memcpy (SwapBuffer, FileBuffer, DataSize);
+ memcpy (FileBuffer, &Crc32Header, CRC32_SECTION_HEADER_SIZE);
+ memcpy (FileBuffer + CRC32_SECTION_HEADER_SIZE, SwapBuffer, DataSize);
+
+ //
+ // Make sure section ends on a DWORD boundary
+ //
+ while ((TotalSize & 0x03) != 0) {
+ FileBuffer[TotalSize] = 0;
+ TotalSize++;
+ }
+
+ *BufferSize = TotalSize;
+
+ if (SwapBuffer != NULL) {
+ free (SwapBuffer);
+ }
+
+ return EFI_SUCCESS;
+}
+
+VOID
+PrintUsage (
+ VOID
+ )
+{
+ printf ("Usage:\n");
+ printf (UTILITY_NAME " -i \"inputfile1\" \"inputfile2\" -o \"outputfile\" \n");
+ printf (" -i \"inputfile\":\n ");
+ printf (" specifies the input files that would be signed to CRC32 Guided section.\n");
+ printf (" -o \"outputfile\":\n");
+ printf (" specifies the output file that is a CRC32 Guided section.\n");
+}
+
+INT32
+ReadFilesContentsIntoBuffer (
+ IN CHAR8 *argv[],
+ IN INT32 Start,
+ IN OUT UINT8 **FileBuffer,
+ IN OUT UINT32 *BufferSize,
+ OUT UINT32 *ContentSize,
+ IN INT32 MaximumArguments
+ )
+{
+ INT32 Index;
+ CHAR8 *FileName;
+ FILE *InputFile;
+ UINT8 Temp;
+ UINT32 Size;
+
+ FileName = NULL;
+ InputFile = NULL;
+ Size = 0;
+ Index = 0;
+
+ //
+ // read all input files into one file buffer
+ //
+ while (argv[Start + Index][0] != '-') {
+
+ FileName = argv[Start + Index];
+ InputFile = fopen (FileName, "rb");
+ if (InputFile == NULL) {
+ Error (NULL, 0, 0, FileName, "failed to open input binary file");
+ return -1;
+ }
+
+ fread (&Temp, sizeof (UINT8), 1, InputFile);
+ while (!feof (InputFile)) {
+ (*FileBuffer)[Size++] = Temp;
+ fread (&Temp, sizeof (UINT8), 1, InputFile);
+ }
+
+ fclose (InputFile);
+ InputFile = NULL;
+
+ //
+ // Make sure section ends on a DWORD boundary
+ //
+ while ((Size & 0x03) != 0) {
+ (*FileBuffer)[Size] = 0;
+ Size++;
+ }
+
+ Index++;
+ if (Index == MaximumArguments) {
+ break;
+ }
+ }
+
+ *ContentSize = Size;
+ return Index;
+}
+
+int
+main (
+ INT32 argc,
+ CHAR8 *argv[]
+ )
+{
+ FILE *OutputFile;
+ UINT8 *FileBuffer;
+ UINT32 BufferSize;
+ EFI_STATUS Status;
+ UINT32 ContentSize;
+ CHAR8 *OutputFileName;
+ INT32 ReturnValue;
+ INT32 Index;
+
+ OutputFile = NULL;
+ FileBuffer = NULL;
+ ContentSize = 0;
+ OutputFileName = NULL;
+
+ SetUtilityName (UTILITY_NAME);
+
+ if (argc == 1) {
+ PrintUsage ();
+ return -1;
+ }
+
+ BufferSize = 1024 * 1024 * 16;
+ FileBuffer = (UINT8 *) malloc (BufferSize * sizeof (UINT8));
+ if (FileBuffer == NULL) {
+ Error (NULL, 0, 0, "memory allocation failed", NULL);
+ return -1;
+ }
+
+ ZeroMem (FileBuffer, BufferSize);
+
+ for (Index = 0; Index < argc; Index++) {
+ if (strcmpi (argv[Index], "-i") == 0) {
+ ReturnValue = ReadFilesContentsIntoBuffer (
+ argv,
+ (Index + 1),
+ &FileBuffer,
+ &BufferSize,
+ &ContentSize,
+ (argc - (Index + 1))
+ );
+ if (ReturnValue == -1) {
+ Error (NULL, 0, 0, "failed to read file contents", NULL);
+ return -1;
+ }
+
+ Index += ReturnValue;
+ }
+
+ if (strcmpi (argv[Index], "-o") == 0) {
+ OutputFileName = argv[Index + 1];
+ }
+ }
+
+ OutputFile = fopen (OutputFileName, "wb");
+ if (OutputFile == NULL) {
+ Error (NULL, 0, 0, OutputFileName, "failed to open output binary file");
+ free (FileBuffer);
+ return -1;
+ }
+
+ /*
+ //
+ // make sure section ends on a DWORD boundary ??
+ //
+ while ( (Size & 0x03) != 0 ) {
+ FileBuffer[Size] = 0;
+ Size ++;
+ }
+*/
+ Status = SignSectionWithCrc32 (FileBuffer, &BufferSize, ContentSize);
+ if (EFI_ERROR (Status)) {
+ Error (NULL, 0, 0, "failed to sign section", NULL);
+ free (FileBuffer);
+ fclose (OutputFile);
+ return -1;
+ }
+
+ ContentSize = fwrite (FileBuffer, sizeof (UINT8), BufferSize, OutputFile);
+ if (ContentSize != BufferSize) {
+ Error (NULL, 0, 0, "failed to write output buffer", NULL);
+ ReturnValue = -1;
+ } else {
+ ReturnValue = 0;
+ }
+
+ free (FileBuffer);
+ fclose (OutputFile);
+ return ReturnValue;
+}
diff --git a/Source/GenCRC32Section/GenCRC32Section.h b/Source/GenCRC32Section/GenCRC32Section.h
new file mode 100644
index 0000000..1cf976b
--- /dev/null
+++ b/Source/GenCRC32Section/GenCRC32Section.h
@@ -0,0 +1,63 @@
+/*++
+
+Copyright (c) 2004, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ GenCRC32Section.h
+
+Abstract:
+
+ Header file for GenFfsFile. Mainly defines the header of section
+ header for CRC32 GUID defined sections. Share with GenSection.c
+
+--*/
+
+//
+// External Files Referenced
+//
+
+/* Standard Headers */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+/* MDE Headers */
+#include <Common/UefiBaseTypes.h>
+#include <Common/EfiImage.h>
+#include <Common/FirmwareVolumeImageFormat.h>
+#include <Common/FirmwareFileSystem.h>
+#include <Common/FirmwareVolumeHeader.h>
+#include <Protocol/GuidedSectionExtraction.h>
+
+/* Tool Headers */
+#include "CommonLib.h"
+#include "Crc32.h"
+#include "EfiCompress.h"
+#include "EfiUtilityMsgs.h"
+#include "ParseInf.h"
+
+//
+// Module Coded to Tiano Coding Conventions
+//
+#ifndef _EFI_GEN_CRC32_SECTION_H
+#define _EFI_GEN_CRC32_SECTION_H
+
+
+typedef struct {
+ EFI_GUID_DEFINED_SECTION GuidSectionHeader;
+ UINT32 CRC32Checksum;
+} CRC32_SECTION_HEADER;
+
+#define EFI_SECTION_CRC32_GUID_DEFINED 0
+#define CRC32_SECTION_HEADER_SIZE (sizeof (CRC32_SECTION_HEADER))
+
+#endif
diff --git a/Source/GenCRC32Section/build.xml b/Source/GenCRC32Section/build.xml
new file mode 100644
index 0000000..3ec9ce5
--- /dev/null
+++ b/Source/GenCRC32Section/build.xml
@@ -0,0 +1,68 @@
+<?xml version="1.0" ?>
+<!--
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+-->
+<project default="GenTool" basedir=".">
+<!--
+ EDK GenCRC32Section Tool
+ Copyright (c) 2006, Intel Corporation
+-->
+ <property name="ToolName" value="GenCRC32Section"/>
+ <property name="FileSet" value="GenCRC32Section.c GenCRC32Section.h"/>
+
+ <taskdef resource="net/sf/antcontrib/antlib.xml"/>
+
+ <property name="LINK_OUTPUT_TYPE" value="static"/>
+ <property name="BUILD_DIR" value="${PACKAGE_DIR}/${ToolName}/tmp"/>
+
+ <target name="GenTool" depends="init, Tool">
+ <echo message="The EDK Tool: ${ToolName} build has completed!"/>
+ </target>
+
+ <target name="init">
+ <echo message="Building the EDK Tool: ${ToolName}"/>
+ <mkdir dir="${BUILD_DIR}"/>
+ </target>
+
+ <target name="Tool" depends="init">
+ <cc name="${ToolChain}" objdir="${BUILD_DIR}"
+ outfile="${BIN_DIR}/${ToolName}"
+ outtype="executable"
+ debug="true"
+ optimize="speed">
+
+ <fileset dir="${basedir}/${ToolName}"
+ includes="${FileSet}"/>
+
+ <includepath path="${PACKAGE_DIR}/Include"/>
+ <includepath path="${PACKAGE_DIR}/Include/${HostArch}"/>
+ <includepath path="${PACKAGE_DIR}/Common"/>
+ <libset dir="${LIB_DIR}" libs="CommonTools"/>
+
+ </cc>
+ </target>
+
+ <target name="clean">
+ <echo message="Removing Intermediate Files Only"/>
+ <delete>
+ <fileset dir="${BUILD_DIR}" includes="*.obj"/>
+ </delete>
+ </target>
+
+ <target name="cleanall">
+ <echo message="Removing Object Files and the Executable: ${ToolName}${ext_exe}"/>
+ <delete failonerror="false" quiet="true" includeEmptyDirs="true">
+ <fileset dir="${BUILD_DIR}"/>
+ <fileset file="${BIN_DIR}/${ToolName}${ext_exe}"/>
+ <fileset file="${BIN_DIR}/${ToolName}.pdb"/>
+ </delete>
+ </target>
+
+</project>
diff --git a/Source/GenCapsuleHdr/CreateGuid.c b/Source/GenCapsuleHdr/CreateGuid.c
new file mode 100644
index 0000000..2a984fa
--- /dev/null
+++ b/Source/GenCapsuleHdr/CreateGuid.c
@@ -0,0 +1,50 @@
+/*++
+
+Copyright (c) 2004-2006 Intel Corporation. All rights reserved
+This program and the accompanying materials are licensed and made available
+under the terms and conditions of the BSD License which accompanies this
+distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+
+Module Name:
+
+ CreateGuid.c
+
+Abstract:
+
+ Library routine to create a GUID
+
+--*/
+
+#include <windows.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+
+void
+CreateGuid (
+ GUID *Guid
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ Guid - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+{
+ CoCreateGuid (Guid);
+}
diff --git a/Source/GenCapsuleHdr/GenCapsuleHdr.c b/Source/GenCapsuleHdr/GenCapsuleHdr.c
new file mode 100644
index 0000000..d1f55b9
--- /dev/null
+++ b/Source/GenCapsuleHdr/GenCapsuleHdr.c
@@ -0,0 +1,2674 @@
+/*++
+
+Copyright (c) 2002-2006 Intel Corporation. All rights reserved
+This program and the accompanying materials are licensed and made available
+under the terms and conditions of the BSD License which accompanies this
+distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+
+Module Name:
+
+ GenCapsuleHdr.c
+
+Abstract:
+
+ Generate a capsule header for a file, and optionally prepend the
+ header to a file or list of files.
+
+--*/
+
+#define _UNICODE
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+
+#include <Common/UefiBaseTypes.h>
+#include <Common/MultiPhase.h>
+#include <Common/Capsule.h>
+#include <Common/FirmwareVolumeImageFormat.h>
+#include <Common/FirmwareVolumeHeader.h>
+#include <Common/FirmwareFileSystem.h> // for FV header GUID
+#include <Guid/Capsule.h>
+#include <Guid/FirmwareFileSystem.h> // for FV header GUID
+
+#include "CommonLib.h"
+#include "EfiUtilityMsgs.h"
+
+#define MAX_PATH 256
+#define PROGRAM_NAME "GenCapsuleHdr"
+
+#define UNICODE_BACKSLASH L'\\'
+#define UNICODE_FILE_START 0xFEFF
+#define UNICODE_CR 0x000D
+#define UNICODE_LF 0x000A
+#define UNICODE_NULL 0x0000
+#define UNICODE_SPACE L' '
+#define UNICODE_SLASH L'/'
+#define UNICODE_DOUBLE_QUOTE L'"'
+#define UNICODE_A L'A'
+#define UNICODE_F L'F'
+#define UNICODE_Z L'Z'
+#define UNICODE_a L'a'
+#define UNICODE_f L'f'
+#define UNICODE_z L'z'
+#define UNICODE_0 L'0'
+#define UNICODE_9 L'9'
+#define UNICODE_TAB L'\t'
+
+#define OEM_HEADER_STRING L"OemHeader"
+#define AUTHOR_INFO_STRING L"AuthorInfo"
+#define REVISION_INFO_STRING L"RevisionInfo"
+#define SHORT_DESCRIPTION_STRING L"ShortDescription"
+#define LONG_DESCRIPTION_STRING L"LongDescription"
+#define EQUAL_STRING L"="
+#define OPEN_BRACE_STRING L"{"
+#define CLOSE_BRACE_STRING L"}"
+#define GUID_STRING L"GUID"
+#define DATA_STRING L"DATA"
+
+#if (EFI_SPECIFICATION_VERSION >= 0x00020000)
+#define UEFI_CAPSULE_HEADER_NO_FALAGS 0
+#define UEFI_CAPSULE_HEADER_RESET_FALAGS CAPSULE_FLAGS_PERSIST_ACROSS_RESET
+#define UEFI_CAPSULE_HEADER_ALL_FALAGS (CAPSULE_FLAGS_PERSIST_ACROSS_RESET | CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE)
+#endif
+
+typedef wchar_t WCHAR;
+
+typedef struct _FILE_LIST {
+ struct _FILE_LIST *Next;
+ INT8 FileName[MAX_PATH];
+} FILE_LIST;
+
+typedef struct _SIZE_LIST {
+ struct _SIZE_LIST *Next;
+ UINT32 Size;
+} SIZE_LIST;
+
+typedef struct {
+ INT8 FileName[MAX_PATH];
+ WCHAR *FileBuffer;
+ WCHAR *FileBufferPtr;
+ UINT32 FileSize;
+ FILE *FilePtr;
+ BOOLEAN EndOfFile;
+ UINT32 LineNum;
+} SOURCE_FILE;
+
+//
+// Here's all our globals.
+//
+static struct {
+ BOOLEAN Dump;
+ BOOLEAN Verbose;
+ BOOLEAN JoinMode;
+ INT8 ScriptFileName[MAX_PATH];
+ INT8 OutputFileName[MAX_PATH];
+ FILE_LIST *FileList;
+ FILE *OutFptr;
+ SIZE_LIST *SizeList;
+ SIZE_LIST *LastSize;
+ SIZE_LIST *CurrentSize;
+} mOptions;
+
+static EFI_GUID mEfiCapsuleHeaderGuid = EFI_CAPSULE_GUID;
+
+void
+CreateGuid (
+ EFI_GUID *Guid
+ );
+
+static
+STATUS
+ProcessArgs (
+ int Argc,
+ char *Argv[]
+ );
+
+static
+void
+SkipWhiteSpace (
+ SOURCE_FILE *SourceFile
+ );
+
+static
+STATUS
+GetHexValue (
+ SOURCE_FILE *SourceFile,
+ UINT32 *Value,
+ UINT32 NumDigits
+ );
+
+static
+BOOLEAN
+GetSplitFileName (
+ INT8 *BaseFileName,
+ INT8 *NewFileName,
+ UINT32 SequenceNumber
+ );
+
+static
+STATUS
+SplitCapsule (
+ INT8 *CapsuleFileName
+ );
+
+static
+void
+Usage (
+ VOID
+ );
+
+static
+void
+DumpCapsule (
+ VOID
+ );
+
+static
+STATUS
+JoinCapsule (
+ VOID
+ );
+
+static
+STATUS
+DumpCapsuleHeaderStrings (
+ UINT8 *SectionName,
+ WCHAR *Buffer
+ );
+
+static
+STATUS
+CheckFirmwareVolumeHeader (
+ INT8 *FileName,
+ INT8 *Buffer,
+ UINT32 BufferSize
+ );
+
+static
+BOOLEAN
+IsToken (
+ SOURCE_FILE *File,
+ WCHAR *Token
+ );
+
+static
+BOOLEAN
+GetNumber (
+ INT8 *Str,
+ UINT32 *Value
+ );
+
+static
+STATUS
+ProcessScriptFile (
+ INT8 *ScriptFileName,
+ FILE *OutFptr,
+ EFI_CAPSULE_HEADER *CapsuleHeader
+ );
+
+static
+STATUS
+ParseCapsuleInfo (
+ SOURCE_FILE *SourceFile,
+ FILE *OutFptr,
+ WCHAR *SectionName
+ );
+
+static
+STATUS
+CreateCapsule (
+ VOID
+ );
+
+static
+STATUS
+ParseOemInfo (
+ SOURCE_FILE *SourceFile,
+ FILE *OutFptr
+ );
+
+static
+BOOLEAN
+IsWhiteSpace (
+ WCHAR Char
+ );
+
+static
+BOOLEAN
+EndOfFile (
+ SOURCE_FILE *File
+ );
+
+int
+main (
+ int Argc,
+ char *Argv[]
+ )
+/*++
+
+Routine Description:
+ Call the routine to process the command-line arguments, then
+ dispatch to the appropriate function.
+
+Arguments:
+ Standard C main() argc and argv.
+
+Returns:
+ 0 if successful
+ nonzero otherwise
+
+--*/
+// GC_TODO: Argc - add argument and description to function comment
+// GC_TODO: ] - add argument and description to function comment
+{
+ STATUS Status;
+ FILE_LIST *NextFile;
+ //
+ // Specify our program name to the error printing routines.
+ //
+ SetUtilityName (PROGRAM_NAME);
+ //
+ // Process the command-line arguments
+ //
+ Status = ProcessArgs (Argc, Argv);
+ if (Status == STATUS_SUCCESS) {
+ if (mOptions.Dump) {
+ DumpCapsule ();
+ } else if (mOptions.JoinMode) {
+ JoinCapsule ();
+ } else {
+ CreateCapsule ();
+ }
+ }
+ //
+ // Cleanup
+ //
+ while (mOptions.FileList != NULL) {
+ NextFile = mOptions.FileList->Next;
+ free (mOptions.FileList);
+ mOptions.FileList = NextFile;
+ }
+
+ while (mOptions.SizeList != NULL) {
+ mOptions.CurrentSize = mOptions.SizeList->Next;
+ free (mOptions.SizeList);
+ mOptions.SizeList = mOptions.CurrentSize;
+ }
+
+ return GetUtilityStatus ();
+}
+
+static
+STATUS
+CreateCapsule (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ None
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+{
+ FILE *InFptr;
+ FILE_LIST *FileList;
+ INT8 *Buffer;
+ UINT32 Size;
+ EFI_CAPSULE_HEADER CapsuleHeader;
+ UINT8 Zero;
+ UINT8 FirstFile;
+ UINT32 CapsuleHeaderSize;
+ long InsertedBlockMapEntryOffset;
+ EFI_FV_BLOCK_MAP_ENTRY InsertedBlockMapEntry;
+ UINT64 FirmwareVolumeSize;
+ long FileSize;
+ EFI_FIRMWARE_VOLUME_HEADER FVHeader;
+
+ Buffer = NULL;
+ InFptr = NULL;
+ FirmwareVolumeSize = 0;
+ CapsuleHeaderSize = 0;
+ InsertedBlockMapEntryOffset = 0;
+ memset (&InsertedBlockMapEntry, 0, sizeof (EFI_FV_BLOCK_MAP_ENTRY));
+ memset (&FVHeader, 0, sizeof (EFI_FIRMWARE_VOLUME_HEADER));
+
+ if ((mOptions.OutFptr = fopen (mOptions.OutputFileName, "wb")) == NULL) {
+ Error (NULL, 0, 0, mOptions.OutputFileName, "failed to open output file for writing");
+ return STATUS_ERROR;
+ }
+
+ memset ((char *) &CapsuleHeader, 0, sizeof (CapsuleHeader));
+ memcpy ((void *) &CapsuleHeader.CapsuleGuid, (void *) &mEfiCapsuleHeaderGuid, sizeof (EFI_GUID));
+ CapsuleHeader.HeaderSize = sizeof (EFI_CAPSULE_HEADER);
+ CapsuleHeader.CapsuleImageSize = sizeof (EFI_CAPSULE_HEADER);
+ if (mOptions.ScriptFileName[0] != 0) {
+ if (ProcessScriptFile (mOptions.ScriptFileName, mOptions.OutFptr, &CapsuleHeader) != STATUS_SUCCESS) {
+ goto Done;
+ }
+ } else {
+ //
+ // Insert a default capsule header
+#if (EFI_SPECIFICATION_VERSION >= 0x00020000)
+ CapsuleHeader.HeaderSize = sizeof (EFI_CAPSULE_HEADER);
+ CapsuleHeader.Flags = UEFI_CAPSULE_HEADER_ALL_FALAGS;
+#endif
+ CapsuleHeader.OffsetToCapsuleBody = sizeof (EFI_CAPSULE_HEADER);
+
+ if (fwrite ((void *) &CapsuleHeader, sizeof (CapsuleHeader), 1, mOptions.OutFptr) != 1) {
+ Error (NULL, 0, 0, mOptions.OutputFileName, "failed to write to file");
+ goto Done;
+ }
+ }
+
+ CapsuleHeaderSize = CapsuleHeader.OffsetToCapsuleBody;
+ //
+ // Now copy the contents of any other files specified on the command
+ // line to the output file. Files must be FFS files, which are aligned
+ // on 8-byte boundaries. Don't align the first file, since it's the start
+ // of the image once the capsule header has been removed.
+ //
+ FileList = mOptions.FileList;
+ FirstFile = 1;
+ Zero = 0;
+ while (FileList != NULL) {
+ if ((InFptr = fopen (FileList->FileName, "rb")) == NULL) {
+ Error (NULL, 0, 0, FileList->FileName, "failed to open file for reading");
+ goto Done;
+ }
+ //
+ // Allocate a buffer into which we can read the file.
+ //
+ fseek (InFptr, 0, SEEK_END);
+ Size = ftell (InFptr);
+ rewind (InFptr);
+ Buffer = (char *) malloc (Size);
+ if (Buffer == NULL) {
+ Error (__FILE__, __LINE__, 0, FileList->FileName, "failed to allocate buffer to read file into");
+ goto Done;
+ }
+
+ if (fread ((void *) Buffer, Size, 1, InFptr) != 1) {
+ Error (NULL, 0, 0, FileList->FileName, "failed to read file contents");
+ goto Done;
+ }
+
+ if (Size > 0) {
+ //
+ // Align the write of the first bytes from the file if not the first file
+ //
+ if (FirstFile) {
+ //
+ // First file must be a firmware volume. Double-check, and then insert
+ // an additional block map entry so we can add more files from the command line
+ //
+ if (CheckFirmwareVolumeHeader (FileList->FileName, Buffer, Size) != STATUS_SUCCESS) {
+ goto Done;
+ }
+ //
+ // Save a copy of the firmware volume header for later
+ //
+ memcpy (&FVHeader, Buffer, sizeof (EFI_FIRMWARE_VOLUME_HEADER));
+ FirmwareVolumeSize = FVHeader.FvLength;
+ if (FileList->Next != NULL) {
+ //
+ // Copy the firmware volume header
+ //
+ InsertedBlockMapEntryOffset = CapsuleHeaderSize + FVHeader.HeaderLength;
+ if (fwrite (Buffer, FVHeader.HeaderLength, 1, mOptions.OutFptr) != 1) {
+ Error (NULL, 0, 0, mOptions.OutputFileName, "failed to write to file");
+ goto Done;
+ }
+
+ if (fwrite (&InsertedBlockMapEntry, sizeof (EFI_FV_BLOCK_MAP_ENTRY), 1, mOptions.OutFptr) != 1) {
+ Error (NULL, 0, 0, mOptions.OutputFileName, "failed to write to file");
+ goto Done;
+ }
+
+ if (fwrite (
+ Buffer + FVHeader.HeaderLength,
+ Size - FVHeader.HeaderLength,
+ 1,
+ mOptions.OutFptr
+ ) != 1) {
+ Error (NULL, 0, 0, mOptions.OutputFileName, "failed to write to file");
+ goto Done;
+ }
+ } else {
+ //
+ // Copy the file contents as-is
+ //
+ if (fwrite ((void *) Buffer, Size, 1, mOptions.OutFptr) != 1) {
+ Error (NULL, 0, 0, mOptions.OutputFileName, "failed to write to file");
+ goto Done;
+ }
+ }
+ } else {
+ while ((ftell (mOptions.OutFptr) - CapsuleHeaderSize) & 0x07) {
+ if (fwrite ((void *) &Zero, 1, 1, mOptions.OutFptr) != 1) {
+ Error (NULL, 0, 0, mOptions.OutputFileName, "failed to write to file");
+ goto Done;
+ }
+ }
+
+ if (fwrite ((void *) Buffer, Size, 1, mOptions.OutFptr) != 1) {
+ Error (NULL, 0, 0, mOptions.OutputFileName, "failed to write to file");
+ goto Done;
+ }
+ }
+
+ FirstFile = 0;
+ }
+
+ free (Buffer);
+ Buffer = NULL;
+ fclose (InFptr);
+ InFptr = NULL;
+ FileList = FileList->Next;
+ }
+
+Done:
+ if (Buffer != NULL) {
+ free (Buffer);
+ }
+
+ if (InFptr != NULL) {
+ fclose (InFptr);
+ }
+ //
+ // If we inserted an additional block map entry, then fix it up. Fix up the
+ // FV header as well to reflect our new size.
+ //
+ if (InsertedBlockMapEntryOffset != 0) {
+ FileSize = ftell (mOptions.OutFptr);
+ InsertedBlockMapEntry.NumBlocks = 1;
+ InsertedBlockMapEntry.BlockLength = (UINT32) ((UINT64) FileSize - (UINT64) CapsuleHeaderSize - FirmwareVolumeSize - sizeof (EFI_FV_BLOCK_MAP_ENTRY));
+ fseek (mOptions.OutFptr, InsertedBlockMapEntryOffset, SEEK_SET);
+ fwrite (&InsertedBlockMapEntry, sizeof (EFI_FV_BLOCK_MAP_ENTRY), 1, mOptions.OutFptr);
+ //
+ // Fix up the firmware volume header and write it out
+ //
+ fseek (mOptions.OutFptr, CapsuleHeaderSize, SEEK_SET);
+ FVHeader.FvLength = FileSize - CapsuleHeaderSize;
+ FVHeader.HeaderLength += sizeof (EFI_FV_BLOCK_MAP_ENTRY);
+ fwrite (&FVHeader, sizeof (EFI_FIRMWARE_VOLUME_HEADER) - sizeof (EFI_FV_BLOCK_MAP_ENTRY), 1, mOptions.OutFptr);
+ //
+ // Reposition to the end of the file
+ //
+ }
+ //
+ // Close files and free the global string lists we allocated memory for
+ //
+ if (mOptions.OutFptr != NULL) {
+ //
+ // We should now know the full capsule image size. Update the header and write it again.
+ //
+ fseek (mOptions.OutFptr, 0, SEEK_END);
+ Size = ftell (mOptions.OutFptr);
+ CapsuleHeader.CapsuleImageSize = Size;
+ fseek (mOptions.OutFptr, 0, SEEK_SET);
+ if (fwrite ((void *) &CapsuleHeader, sizeof (CapsuleHeader), 1, mOptions.OutFptr) != 1) {
+ Error (NULL, 0, 0, mOptions.OutputFileName, "failed to write to file");
+ }
+
+ fseek (mOptions.OutFptr, 0, SEEK_END);
+ fclose (mOptions.OutFptr);
+ mOptions.OutFptr = NULL;
+ }
+ //
+ // If they are doing split capsule output, then split it up now.
+ //
+ if ((mOptions.Dump == 0) && (GetUtilityStatus () == STATUS_SUCCESS) && (mOptions.SizeList != NULL)) {
+ SplitCapsule (mOptions.OutputFileName);
+ }
+
+ return STATUS_SUCCESS;
+}
+
+static
+STATUS
+ProcessScriptFile (
+ INT8 *ScriptFileName,
+ FILE *OutFptr,
+ EFI_CAPSULE_HEADER *CapsuleHeader
+ )
+/*++
+
+Routine Description:
+ Parse a capsule header script file.
+
+Arguments:
+ ScriptFileName - name of script file to parse
+ OutFptr - output to dump binary data
+ CapsuleHeader - capsule header to update with size info
+ of parsed fields in the script file
+
+Returns:
+ STATUS_SUCCESS - if all went well
+
+--*/
+{
+#if 0
+ STATUS Status;
+ SOURCE_FILE SourceFile;
+ WCHAR *WScriptFileName;
+ BOOLEAN InComment;
+
+ if (fwrite (CapsuleHeader, sizeof (EFI_CAPSULE_HEADER), 1, OutFptr) != 1) {
+ Error (NULL, 0, 0, "failed to write capsule header to output file", NULL);
+ return STATUS_ERROR;
+ }
+
+ memset (&SourceFile, 0, sizeof (SOURCE_FILE));
+ strcpy (SourceFile.FileName, ScriptFileName);
+
+ Status = STATUS_ERROR;
+ //
+ // Open the input unicode script file and read it into a buffer
+ //
+ WScriptFileName = (WCHAR *) malloc ((strlen (ScriptFileName) + 1) * sizeof (WCHAR));
+ if (WScriptFileName == NULL) {
+ Error (__FILE__, __LINE__, 0, "failed to allocate memory", NULL);
+ return STATUS_ERROR;
+ }
+
+ swprintf (WScriptFileName, L"%S", ScriptFileName);
+ if ((SourceFile.FilePtr = _wfopen (WScriptFileName, L"r")) == NULL) {
+ free (WScriptFileName);
+ Error (NULL, 0, 0, ScriptFileName, "failed to open script file for reading");
+ goto Done;
+ }
+
+ free (WScriptFileName);
+ fseek (SourceFile.FilePtr, 0, SEEK_END);
+ SourceFile.FileSize = ftell (SourceFile.FilePtr);
+ rewind (SourceFile.FilePtr);
+ SourceFile.FileBuffer = (WCHAR *) malloc (SourceFile.FileSize + sizeof (WCHAR));
+ if (SourceFile.FileBuffer == NULL) {
+ Error (__FILE__, __LINE__, 0, ScriptFileName, "failed to allocate memory to read in file contents");
+ goto Done;
+ }
+
+ if (fread (SourceFile.FileBuffer, SourceFile.FileSize, 1, SourceFile.FilePtr) != 1) {
+ Error (NULL, 0, 0, ScriptFileName, "failed to read file contents");
+ goto Done;
+ }
+
+ SourceFile.FileBufferPtr = SourceFile.FileBuffer;
+ SourceFile.LineNum = 1;
+ if (SourceFile.FileBuffer[0] != UNICODE_FILE_START) {
+ Error (ScriptFileName, 1, 0, "file does not appear to be a unicode file", NULL);
+ goto Done;
+ }
+
+ SourceFile.FileBufferPtr++;
+ SourceFile.FileBuffer[SourceFile.FileSize / sizeof (WCHAR)] = 0;
+ //
+ // Walk the source file buffer and replace all carriage returns with 0 so
+ // we can print from the file contents on parse errors.
+ //
+ InComment = 0;
+ while (!EndOfFile (&SourceFile)) {
+ if (SourceFile.FileBufferPtr[0] == UNICODE_CR) {
+ SourceFile.FileBufferPtr[0] = 0;
+ InComment = 0;
+ } else if (SourceFile.FileBufferPtr[0] == UNICODE_LF) {
+ InComment = 0;
+ } else if (InComment) {
+ SourceFile.FileBufferPtr[0] = UNICODE_SPACE;
+ } else if ((SourceFile.FileBufferPtr[0] == UNICODE_SLASH) && (SourceFile.FileBufferPtr[1] == UNICODE_SLASH)) {
+ InComment = 1;
+ SourceFile.FileBufferPtr[0] = UNICODE_SPACE;
+ }
+
+ SourceFile.FileBufferPtr++;
+ }
+ //
+ // Reposition to the start of the file, but skip over the unicode file start
+ //
+ SourceFile.FileBufferPtr = SourceFile.FileBuffer;
+ SourceFile.FileBufferPtr++;
+ SourceFile.EndOfFile = 0;
+ CapsuleHeader->OffsetToOemDefinedHeader = ftell (OutFptr);
+ //
+ // Parse the OEM bytes
+ //
+ if (ParseOemInfo (&SourceFile, OutFptr) != STATUS_SUCCESS) {
+ goto Done;
+ }
+ //
+ // Parse the author information
+ //
+ CapsuleHeader->OffsetToAuthorInformation = ftell (OutFptr);
+ if (ParseCapsuleInfo (&SourceFile, OutFptr, AUTHOR_INFO_STRING) != STATUS_SUCCESS) {
+ goto Done;
+ }
+ //
+ // Parse the revision information
+ //
+ CapsuleHeader->OffsetToRevisionInformation = ftell (OutFptr);
+ if (ParseCapsuleInfo (&SourceFile, OutFptr, REVISION_INFO_STRING) != STATUS_SUCCESS) {
+ goto Done;
+ }
+ //
+ // Parse the short description
+ //
+ CapsuleHeader->OffsetToShortDescription = ftell (OutFptr);
+ if (ParseCapsuleInfo (&SourceFile, OutFptr, SHORT_DESCRIPTION_STRING) != STATUS_SUCCESS) {
+ goto Done;
+ }
+ //
+ // Parse the long description
+ //
+ CapsuleHeader->OffsetToLongDescription = ftell (OutFptr);
+ if (ParseCapsuleInfo (&SourceFile, OutFptr, LONG_DESCRIPTION_STRING) != STATUS_SUCCESS) {
+ goto Done;
+ }
+ //
+ // Better be end of contents
+ //
+ SkipWhiteSpace (&SourceFile);
+ if (!EndOfFile (&SourceFile)) {
+ Error (ScriptFileName, SourceFile.LineNum, 0, NULL, "expected end-of-file, not %.20S", SourceFile.FileBufferPtr);
+ goto Done;
+ }
+
+ CapsuleHeader->OffsetToCapsuleBody = ftell (OutFptr);
+ rewind (OutFptr);
+ fwrite (CapsuleHeader, sizeof (EFI_CAPSULE_HEADER), 1, OutFptr);
+ fseek (OutFptr, 0, SEEK_END);
+ Status = STATUS_SUCCESS;
+Done:
+ if (SourceFile.FilePtr != NULL) {
+ fclose (SourceFile.FilePtr);
+ }
+
+ if (SourceFile.FileBuffer != NULL) {
+ free (SourceFile.FileBuffer);
+ }
+
+ return Status;
+
+#endif
+ return STATUS_SUCCESS;
+}
+//
+// Parse the OEM data of format:
+// OemInfo {
+// GUID = 12345676-1234-1234-123456789ABC
+// DATA = 0x01, 0x02, 0x03...
+// }
+//
+static
+STATUS
+ParseOemInfo (
+ SOURCE_FILE *SourceFile,
+ FILE *OutFptr
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ SourceFile - GC_TODO: add argument description
+ OutFptr - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+{
+ long OemHeaderOffset;
+ UINT32 Data;
+ EFI_CAPSULE_OEM_HEADER OemHeader;
+ STATUS Status;
+ UINT32 DigitCount;
+ WCHAR *SaveFilePos;
+ UINT8 ByteData;
+
+ Status = STATUS_ERROR;
+ memset (&OemHeader, 0, sizeof (EFI_CAPSULE_OEM_HEADER));
+ OemHeaderOffset = ftell (OutFptr);
+ OemHeader.HeaderSize = sizeof (EFI_CAPSULE_OEM_HEADER);
+ if (fwrite (&OemHeader, sizeof (EFI_CAPSULE_OEM_HEADER), 1, OutFptr) != 1) {
+ Error (NULL, 0, 0, "failed to write OEM header to output file", NULL);
+ goto Done;
+ }
+
+ if (!IsToken (SourceFile, OEM_HEADER_STRING)) {
+ Error (
+ SourceFile->FileName,
+ SourceFile->LineNum,
+ 0,
+ NULL,
+ "expected %S, not %.20S",
+ OEM_HEADER_STRING,
+ SourceFile->FileBufferPtr
+ );
+ goto Done;
+ }
+
+ if (!IsToken (SourceFile, EQUAL_STRING)) {
+ Error (
+ SourceFile->FileName,
+ SourceFile->LineNum,
+ 0,
+ NULL,
+ "expected %S, not %.20S",
+ EQUAL_STRING,
+ SourceFile->FileBufferPtr
+ );
+ goto Done;
+ }
+
+ if (!IsToken (SourceFile, OPEN_BRACE_STRING)) {
+ Error (
+ SourceFile->FileName,
+ SourceFile->LineNum,
+ 0,
+ NULL,
+ "expected %S, not %.20S",
+ OPEN_BRACE_STRING,
+ SourceFile->FileBufferPtr
+ );
+ goto Done;
+ }
+ //
+ // Look for: GUID = xxxxxxx-xxxx-xxxx-xxxxxxxxxxxxx
+ //
+ if (!IsToken (SourceFile, GUID_STRING)) {
+ Error (
+ SourceFile->FileName,
+ SourceFile->LineNum,
+ 0,
+ NULL,
+ "expected %S, not %.20S",
+ GUID_STRING,
+ SourceFile->FileBufferPtr
+ );
+ goto Done;
+ }
+
+ if (!IsToken (SourceFile, EQUAL_STRING)) {
+ Error (
+ SourceFile->FileName,
+ SourceFile->LineNum,
+ 0,
+ NULL,
+ "expected %S, not %.20S",
+ EQUAL_STRING,
+ SourceFile->FileBufferPtr
+ );
+ goto Done;
+ }
+ //
+ // Parse the xxxxxxxx-xxxx-xxxx-xxxx portion of the GUID
+ //
+ SkipWhiteSpace (SourceFile);
+ if (GetHexValue (SourceFile, &Data, 8) != STATUS_SUCCESS) {
+ Error (SourceFile->FileName, SourceFile->LineNum, 0, "invalid GUID", NULL);
+ goto Done;
+ }
+
+ OemHeader.OemGuid.Data1 = Data;
+ if (!IsToken (SourceFile, L"-")) {
+ Error (
+ SourceFile->FileName,
+ SourceFile->LineNum,
+ 0,
+ NULL,
+ "expected dash in GUID, not %S",
+ SourceFile->FileBufferPtr
+ );
+ goto Done;
+ }
+ //
+ // Get 3 word values
+ //
+ for (DigitCount = 0; DigitCount < 3; DigitCount++) {
+ if (GetHexValue (SourceFile, &Data, 4) != STATUS_SUCCESS) {
+ Error (SourceFile->FileName, SourceFile->LineNum, 0, "invalid GUID", NULL);
+ goto Done;
+ }
+
+ switch (DigitCount) {
+ case 0:
+ OemHeader.OemGuid.Data2 = (UINT16) Data;
+ break;
+
+ case 1:
+ OemHeader.OemGuid.Data3 = (UINT16) Data;
+ break;
+
+ case 2:
+ OemHeader.OemGuid.Data4[1] = (UINT8) Data;
+ OemHeader.OemGuid.Data4[0] = (UINT8) (Data >> 8);
+ break;
+ }
+
+ if (!IsToken (SourceFile, L"-")) {
+ Error (
+ SourceFile->FileName,
+ SourceFile->LineNum,
+ 0,
+ NULL,
+ "expected dash in GUID, not %S",
+ SourceFile->FileBufferPtr
+ );
+ goto Done;
+ }
+ }
+ //
+ // Pick up the last 6 bytes of the GUID
+ //
+ SaveFilePos = SourceFile->FileBufferPtr;
+ for (DigitCount = 0; DigitCount < 6; DigitCount++) {
+ if (GetHexValue (SourceFile, &Data, 2) != STATUS_SUCCESS) {
+ Error (SourceFile->FileName, SourceFile->LineNum, 0, "invalid GUID", NULL);
+ goto Done;
+ }
+
+ OemHeader.OemGuid.Data4[DigitCount + 2] = (UINT8) Data;
+ }
+ //
+ // Now read raw OEM data bytes. May or may not be present.
+ // DATA = 0x01, 0x02, 0x02...
+ //
+ if (IsToken (SourceFile, CLOSE_BRACE_STRING)) {
+ Status = STATUS_SUCCESS;
+ goto Done;
+ }
+
+ if (!IsToken (SourceFile, DATA_STRING)) {
+ Error (
+ SourceFile->FileName,
+ SourceFile->LineNum,
+ 0,
+ NULL,
+ "expected %S, not %.20S",
+ DATA_STRING,
+ SourceFile->FileBufferPtr
+ );
+ goto Done;
+ }
+
+ if (!IsToken (SourceFile, EQUAL_STRING)) {
+ Error (
+ SourceFile->FileName,
+ SourceFile->LineNum,
+ 0,
+ NULL,
+ "expected %S, not %.20S",
+ EQUAL_STRING,
+ SourceFile->FileBufferPtr
+ );
+ goto Done;
+ }
+
+ while (!EndOfFile (SourceFile)) {
+ if (IsToken (SourceFile, CLOSE_BRACE_STRING)) {
+ Status = STATUS_SUCCESS;
+ goto Done;
+ }
+
+ if (IsToken (SourceFile, L"0x")) {
+ if (swscanf (SourceFile->FileBufferPtr, L"%x", &Data) != 1) {
+ Error (
+ SourceFile->FileName,
+ SourceFile->LineNum,
+ 0,
+ NULL,
+ "expected hex byte value, not %.20S",
+ SourceFile->FileBufferPtr
+ );
+ goto Done;
+ }
+
+ if (Data &~0xFF) {
+ Error (
+ SourceFile->FileName,
+ SourceFile->LineNum,
+ 0,
+ NULL,
+ "expected byte hex byte value at %.20S",
+ SourceFile->FileBufferPtr
+ );
+ goto Done;
+ }
+ //
+ // Skip over the hex digits, then write the data
+ //
+ while (iswxdigit (SourceFile->FileBufferPtr[0])) {
+ SourceFile->FileBufferPtr++;
+ }
+
+ ByteData = (UINT8) Data;
+ if (fwrite (&ByteData, 1, 1, OutFptr) != 1) {
+ Error (NULL, 0, 0, "failed to write OEM data to output file", NULL);
+ goto Done;
+ }
+
+ OemHeader.HeaderSize++;
+ //
+ // Optional comma
+ //
+ IsToken (SourceFile, L",");
+ } else {
+ Error (
+ SourceFile->FileName,
+ SourceFile->LineNum,
+ 0,
+ NULL,
+ "expected hex OEM data, not %.20S",
+ SourceFile->FileBufferPtr
+ );
+ goto Done;
+ }
+ }
+
+ if (EndOfFile (SourceFile)) {
+ Error (
+ SourceFile->FileName,
+ SourceFile->LineNum,
+ 0,
+ NULL,
+ "expected %S close to OEM header data",
+ CLOSE_BRACE_STRING
+ );
+ goto Done;
+ }
+
+ Status = STATUS_SUCCESS;
+Done:
+ //
+ // re-write the oem header if no errors
+ //
+ if (Status == STATUS_SUCCESS) {
+ fseek (OutFptr, OemHeaderOffset, SEEK_SET);
+ if (fwrite (&OemHeader, sizeof (EFI_CAPSULE_OEM_HEADER), 1, OutFptr) != 1) {
+ Error (NULL, 0, 0, "failed to write OEM header to output file", NULL);
+ goto Done;
+ }
+
+ fseek (OutFptr, 0, SEEK_END);
+ }
+
+ return Status;
+}
+
+static
+STATUS
+ParseCapsuleInfo (
+ SOURCE_FILE *SourceFile,
+ FILE *OutFptr,
+ WCHAR *SectionName
+ )
+// GC_TODO: function comment should start with '/*++'
+//
+// GC_TODO: function comment is missing 'Routine Description:'
+// GC_TODO: function comment is missing 'Arguments:'
+// GC_TODO: function comment is missing 'Returns:'
+// GC_TODO: SourceFile - add argument and description to function comment
+// GC_TODO: OutFptr - add argument and description to function comment
+// GC_TODO: SectionName - add argument and description to function comment
+// Parse: eng "string " "parts"
+// spa "string " "parts"
+// Write out: "eng string parts\0spa string parts\0\0
+//
+{
+ STATUS Status;
+ int StringCount;
+ WCHAR Zero;
+ WCHAR Spacebar;
+
+ Status = STATUS_ERROR;
+ Zero = 0;
+ Spacebar = UNICODE_SPACE;
+
+ if (!IsToken (SourceFile, SectionName)) {
+ Error (
+ SourceFile->FileName,
+ SourceFile->LineNum,
+ 0,
+ NULL,
+ "expected %S, not %.20S",
+ SectionName,
+ SourceFile->FileBufferPtr
+ );
+ goto Done;
+ }
+
+ if (!IsToken (SourceFile, EQUAL_STRING)) {
+ Error (
+ SourceFile->FileName,
+ SourceFile->LineNum,
+ 0,
+ NULL,
+ "expected %S, not %.20S",
+ EQUAL_STRING,
+ SourceFile->FileBufferPtr
+ );
+ goto Done;
+ }
+
+ if (!IsToken (SourceFile, OPEN_BRACE_STRING)) {
+ Error (
+ SourceFile->FileName,
+ SourceFile->LineNum,
+ 0,
+ NULL,
+ "expected %S, not %.20S",
+ OPEN_BRACE_STRING,
+ SourceFile->FileBufferPtr
+ );
+ goto Done;
+ }
+
+ while (!EndOfFile (SourceFile)) {
+ if (IsToken (SourceFile, CLOSE_BRACE_STRING)) {
+ break;
+ }
+ //
+ // Look for language identifier (3 lowercase chars)
+ //
+ if ((SourceFile->FileBufferPtr[0] >= UNICODE_a) &&
+ (SourceFile->FileBufferPtr[0] <= UNICODE_z) &&
+ (SourceFile->FileBufferPtr[1] >= UNICODE_a) &&
+ (SourceFile->FileBufferPtr[1] <= UNICODE_z) &&
+ (SourceFile->FileBufferPtr[2] >= UNICODE_a) &&
+ (SourceFile->FileBufferPtr[2] <= UNICODE_z) &&
+ IsWhiteSpace (SourceFile->FileBufferPtr[3])
+ ) {
+ //
+ // Write the 3 chars followed by a spacebar, and then look for opening quote
+ //
+ fwrite (SourceFile->FileBufferPtr, sizeof (WCHAR), 1, OutFptr);
+ SourceFile->FileBufferPtr++;
+ fwrite (SourceFile->FileBufferPtr, sizeof (WCHAR), 1, OutFptr);
+ SourceFile->FileBufferPtr++;
+ fwrite (SourceFile->FileBufferPtr, sizeof (WCHAR), 1, OutFptr);
+ SourceFile->FileBufferPtr++;
+ fwrite (&Spacebar, sizeof (WCHAR), 1, OutFptr);
+ StringCount = 0;
+ while (IsToken (SourceFile, L"\"")) {
+ StringCount++;
+ while (!EndOfFile (SourceFile)) {
+ if (SourceFile->FileBufferPtr[0] == UNICODE_DOUBLE_QUOTE) {
+ SourceFile->FileBufferPtr++;
+ break;
+ } else if ((SourceFile->FileBufferPtr[0] == UNICODE_LF) || (SourceFile->FileBufferPtr[0] == 0)) {
+ Error (SourceFile->FileName, SourceFile->LineNum, 0, "missing closing quote on string", NULL);
+ goto Done;
+ } else {
+ fwrite (SourceFile->FileBufferPtr, sizeof (WCHAR), 1, OutFptr);
+ SourceFile->FileBufferPtr++;
+ }
+ }
+ }
+
+ if (StringCount == 0) {
+ Error (
+ SourceFile->FileName,
+ SourceFile->LineNum,
+ 0,
+ NULL,
+ "expected quoted string, not %.20S",
+ SourceFile->FileBufferPtr
+ );
+ goto Done;
+ }
+ //
+ // This string's null terminator
+ //
+ fwrite (&Zero, sizeof (WCHAR), 1, OutFptr);
+ } else {
+ Error (
+ SourceFile->FileName,
+ SourceFile->LineNum,
+ 0,
+ NULL,
+ "expected valid language identifer, not %.20S",
+ SourceFile->FileBufferPtr
+ );
+ goto Done;
+ }
+ }
+ //
+ // Double null terminator
+ //
+ fwrite (&Zero, sizeof (WCHAR), 1, OutFptr);
+ Status = STATUS_SUCCESS;
+Done:
+ return Status;
+}
+
+static
+STATUS
+SplitCapsule (
+ INT8 *CapsuleFileName
+ )
+/*++
+
+Routine Description:
+ We've created an entire capsule image. Now split it up into the
+ size pieces they requested.
+
+Arguments:
+ CapsuleFileName - name of an existing capsule file on disk
+
+Returns:
+ STATUS_SUCCESS - if no problems
+
+Notes:
+ This implementation reads in the entire capsule image from
+ disk, then overwrites the original file with the first
+ in the series.
+
+--*/
+{
+#if 0
+ EFI_CAPSULE_HEADER *CapHdr;
+
+ EFI_CAPSULE_HEADER Hdr;
+ FILE *CapFptr;
+ FILE *OutFptr;
+ UINT32 SizeLeft;
+ UINT32 CurrentSize;
+ UINT32 DataSize;
+ UINT32 SequenceNumber;
+ INT8 *Buffer;
+ INT8 FileName[MAX_PATH];
+ STATUS Status;
+ UINT32 FileSize;
+ //
+ // Figure out the total size, then rewind the input file and
+ // read the entire thing in
+ //
+ if ((CapFptr = fopen (CapsuleFileName, "rb")) == NULL) {
+ Error (NULL, 0, 0, CapsuleFileName, "failed to open capsule image for reading");
+ return STATUS_ERROR;
+ }
+
+ OutFptr = NULL;
+ Status = STATUS_SUCCESS;
+ fseek (CapFptr, 0, SEEK_END);
+ SizeLeft = ftell (CapFptr);
+ fseek (CapFptr, 0, SEEK_SET);
+ CapHdr = (EFI_CAPSULE_HEADER *) malloc (SizeLeft);
+ if (CapHdr == NULL) {
+ Error (NULL, 0, 0, "memory allocation failure", NULL);
+ goto FailDone;
+ }
+
+ if (fread (CapHdr, SizeLeft, 1, CapFptr) != 1) {
+ Error (NULL, 0, 0, "failed to read capsule contents", "split failed");
+ goto FailDone;
+ }
+
+ fclose (CapFptr);
+ CapFptr = NULL;
+ //
+ // Get a GUID to fill in the InstanceId GUID in the header
+ //
+ CreateGuid (&CapHdr->InstanceId);
+ SequenceNumber = 0;
+ //
+ // If the split size is larger than the original capsule image, then
+ // we're done.
+ //
+ if (mOptions.SizeList->Size >= SizeLeft) {
+ mOptions.SizeList->Size = SizeLeft;
+ goto Done;
+ }
+ //
+ // First size has to be big enough for the original header
+ //
+ if (mOptions.SizeList->Size < CapHdr->OffsetToCapsuleBody) {
+ Error (NULL, 0, 0, "first split size is insufficient for the original capsule header", NULL);
+ goto FailDone;
+ }
+ //
+ // Initialize the header we'll use on all but the first part
+ //
+ memset (&Hdr, 0, sizeof (Hdr));
+ Hdr.CapsuleGuid = CapHdr->CapsuleGuid;
+ Hdr.HeaderSize = sizeof (Hdr);
+ Hdr.Flags = CapHdr->Flags;
+ Hdr.InstanceId = CapHdr->InstanceId;
+ Hdr.CapsuleImageSize = CapHdr->CapsuleImageSize;
+ Hdr.OffsetToCapsuleBody = Hdr.HeaderSize;
+ Hdr.SequenceNumber = 1;
+ //
+ // printf ("Created %s - 0x%X bytes\n", CapsuleFileName, mOptions.SizeList->Size);
+ //
+ Buffer = (UINT8 *) CapHdr;
+ //
+ // Walk the list of sizes and write out a capsule header, and
+ // then the raw capsule data.
+ //
+ // SizeLeft -= mOptions.SizeList->Size;
+ //
+ mOptions.CurrentSize = mOptions.SizeList;
+ while (SizeLeft) {
+ CurrentSize = mOptions.CurrentSize->Size;
+ GetSplitFileName (mOptions.OutputFileName, FileName, SequenceNumber);
+ if ((OutFptr = fopen (FileName, "wb")) == NULL) {
+ Error (NULL, 0, 0, FileName, "failed to open split file for writing");
+ goto FailDone;
+ }
+
+ if (Buffer == (UINT8 *) CapHdr) {
+ //
+ // First part -- write out original header and data
+ //
+ if (fwrite (Buffer, CurrentSize, 1, OutFptr) != 1) {
+ Error (NULL, 0, 0, FileName, "failed to write to split image file");
+ goto FailDone;
+ }
+
+ SizeLeft -= CurrentSize;
+ Buffer += CurrentSize;
+ DataSize = CurrentSize;
+ FileSize = CurrentSize;
+ } else {
+ //
+ // Not the first part. Write the default header, and then the raw bytes from the
+ // original image.
+ //
+ if (CurrentSize <= sizeof (Hdr)) {
+ Error (NULL, 0, 0, "split size too small for capsule header + data", "0x%X", CurrentSize);
+ goto FailDone;
+ }
+
+ DataSize = CurrentSize - sizeof (Hdr);
+ if (DataSize > SizeLeft) {
+ DataSize = SizeLeft;
+ }
+
+ if (fwrite (&Hdr, sizeof (Hdr), 1, OutFptr) != 1) {
+ Error (NULL, 0, 0, FileName, "failed to write capsule header to output file");
+ fclose (OutFptr);
+ goto FailDone;
+ }
+
+ if (fwrite (Buffer, DataSize, 1, OutFptr) != 1) {
+ Error (NULL, 0, 0, FileName, "failed to write capsule data to output file");
+ fclose (OutFptr);
+ goto FailDone;
+ }
+
+ Hdr.SequenceNumber++;
+ Buffer += DataSize;
+ SizeLeft -= DataSize;
+ FileSize = DataSize + sizeof (Hdr);
+ }
+ //
+ // Next size in list if there is one
+ //
+ if (mOptions.CurrentSize->Next != NULL) {
+ mOptions.CurrentSize = mOptions.CurrentSize->Next;
+ }
+
+ SequenceNumber++;
+ fclose (OutFptr);
+ OutFptr = NULL;
+ printf ("Created %s - 0x%X bytes (0x%X bytes of data)\n", FileName, FileSize, DataSize);
+ }
+
+ goto Done;
+FailDone:
+ Status = STATUS_ERROR;
+Done:
+ if (CapHdr != NULL) {
+ free (CapHdr);
+ }
+
+ if (CapFptr != NULL) {
+ fclose (CapFptr);
+ }
+
+ if (OutFptr != NULL) {
+ fclose (OutFptr);
+ }
+
+ return Status;
+
+#endif
+ return STATUS_SUCCESS;
+}
+
+static
+BOOLEAN
+GetSplitFileName (
+ INT8 *BaseFileName,
+ INT8 *NewFileName,
+ UINT32 SequenceNumber
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ BaseFileName - GC_TODO: add argument description
+ NewFileName - GC_TODO: add argument description
+ SequenceNumber - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+{
+ /*++
+
+Routine Description:
+ Given an initial split capsule file name and a sequence number,
+ create an appropriate file name for this split of a capsule image.
+
+Arguments:
+ BaseFileName - name of of the first split file in the series
+ NewFileName - output name of the split file
+ SequenceNumber - 0-based sequence number of split images
+
+Returns:
+ TRUE - name created successfully
+ FALSE - otherwise
+
+--*/
+ INT8 *Ptr;
+ INT8 *Part2Start;
+ UINT32 Digits;
+ UINT32 Len;
+ UINT32 BaseOffset;
+ //
+ // Work back from the end of the file name and see if there is a number somewhere
+ //
+ for (Ptr = BaseFileName + strlen (BaseFileName) - 1; (Ptr > BaseFileName) && !isdigit (*Ptr); Ptr--)
+ ;
+ if ((Ptr == BaseFileName) && (!isdigit (*Ptr))) {
+ //
+ // Found no number, so just add it to the end
+ //
+ sprintf (NewFileName, "%s%d", BaseFileName, SequenceNumber);
+ return TRUE;
+ } else {
+ //
+ // Found a number. Look back to find the first digit.
+ //
+ Part2Start = Ptr + 1;
+ for (Digits = 1; isdigit (*Ptr) && (Ptr > BaseFileName); Ptr--, Digits++)
+ ;
+ if (!isdigit (*Ptr)) {
+ Ptr++;
+ Digits--;
+ }
+
+ BaseOffset = atoi (Ptr);
+ SequenceNumber = SequenceNumber + BaseOffset;
+ if (Digits > 1) {
+ //
+ // Copy the first part of the original file name to the new filename
+ // This is the path for filenames with format path\name001.cap
+ //
+ Len = (UINT32) Ptr - (UINT32) BaseFileName;
+ strncpy (NewFileName, BaseFileName, Len);
+ sprintf (NewFileName + Len, "%0*d", Digits, SequenceNumber);
+ strcat (NewFileName, Part2Start);
+ return TRUE;
+ } else {
+ //
+ // Only one digit found. This is the path for filenames with
+ // format path\name1.cap
+ //
+ Len = (UINT32) Ptr - (UINT32) BaseFileName + 1;
+ strncpy (NewFileName, BaseFileName, Len);
+ sprintf (NewFileName + Len - 1, "%d", SequenceNumber);
+ strcat (NewFileName, Part2Start);
+ return TRUE;
+ }
+ }
+}
+
+static
+BOOLEAN
+IsWhiteSpace (
+ WCHAR Char
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ Char - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+{
+ switch (Char) {
+ case UNICODE_SPACE:
+ case UNICODE_TAB:
+ case UNICODE_NULL:
+ case UNICODE_CR:
+ case UNICODE_LF:
+ return TRUE;
+
+ default:
+ return FALSE;
+ }
+}
+
+static
+BOOLEAN
+IsToken (
+ SOURCE_FILE *File,
+ WCHAR *Token
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ File - GC_TODO: add argument description
+ Token - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+{
+ SkipWhiteSpace (File);
+ if (EndOfFile (File)) {
+ return FALSE;
+ }
+
+ if (wcsncmp (Token, File->FileBufferPtr, wcslen (Token)) == 0) {
+ File->FileBufferPtr += wcslen (Token);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static
+STATUS
+CheckFirmwareVolumeHeader (
+ INT8 *FileName,
+ INT8 *Buffer,
+ UINT32 BufferSize
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ FileName - GC_TODO: add argument description
+ Buffer - GC_TODO: add argument description
+ BufferSize - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+{
+ EFI_FIRMWARE_VOLUME_HEADER *Hdr;
+ EFI_GUID FVHeaderGuid = EFI_FIRMWARE_FILE_SYSTEM_GUID;
+
+ Hdr = (EFI_FIRMWARE_VOLUME_HEADER *) Buffer;
+ if (Hdr->Signature != EFI_FVH_SIGNATURE) {
+ Error (NULL, 0, 0, FileName, "file does not appear to be a firmware volume (bad signature)");
+ return STATUS_ERROR;
+ }
+
+ if (Hdr->Revision != EFI_FVH_REVISION) {
+ Error (NULL, 0, 0, FileName, "unsupported firmware volume header version");
+ return STATUS_ERROR;
+ }
+
+ if (Hdr->FvLength > BufferSize) {
+ Error (NULL, 0, 0, FileName, "malformed firmware volume -- FvLength > file size");
+ return STATUS_ERROR;
+ }
+
+ if (memcmp (&Hdr->FileSystemGuid, &FVHeaderGuid, sizeof (EFI_GUID)) != 0) {
+ Error (NULL, 0, 0, FileName, "invalid FFS GUID in firmware volume header");
+ return STATUS_ERROR;
+ }
+
+ return STATUS_SUCCESS;
+}
+
+static
+void
+DumpCapsule (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ None
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+{
+#if 0
+ FILE *InFptr;
+ FILE_LIST *FileList;
+ EFI_CAPSULE_HEADER CapsuleHeader;
+ EFI_FIRMWARE_VOLUME_HEADER FVHeader;
+ EFI_CAPSULE_OEM_HEADER *OemHeader;
+ UINT8 *BPtr;
+ UINT32 FileSize;
+ UINT32 CapsuleHeaderDataSize;
+ UINT8 ByteCount;
+ UINT8 *CapsuleHeaderData;
+ BOOLEAN SplitImage;
+
+ InFptr = NULL;
+ CapsuleHeaderData = NULL;
+ FileList = mOptions.FileList;
+ while (FileList != NULL) {
+ if ((InFptr = fopen (FileList->FileName, "rb")) == NULL) {
+ Error (NULL, 0, 0, FileList->FileName, "failed to open file for reading");
+ goto Done;
+ }
+
+ if (fread (&CapsuleHeader, sizeof (EFI_CAPSULE_HEADER), 1, InFptr) != 1) {
+ Error (NULL, 0, 0, FileList->FileName, "failed to read capsule header");
+ goto Done;
+ }
+
+ fseek (InFptr, 0, SEEK_END);
+ FileSize = ftell (InFptr);
+ if (CapsuleHeader.CapsuleImageSize > FileSize) {
+ SplitImage = TRUE;
+ } else {
+ SplitImage = FALSE;
+ }
+
+ printf (
+ "Capsule %s Size=0x%X CargoSize=0x%X\n",
+ FileList->FileName,
+ FileSize,
+ FileSize - CapsuleHeader.OffsetToCapsuleBody
+ );
+ printf (
+ " GUID %08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X",
+ CapsuleHeader.CapsuleGuid.Data1,
+ (UINT32) CapsuleHeader.CapsuleGuid.Data2,
+ (UINT32) CapsuleHeader.CapsuleGuid.Data3,
+ (UINT32) CapsuleHeader.CapsuleGuid.Data4[0],
+ (UINT32) CapsuleHeader.CapsuleGuid.Data4[1],
+ (UINT32) CapsuleHeader.CapsuleGuid.Data4[2],
+ (UINT32) CapsuleHeader.CapsuleGuid.Data4[3],
+ (UINT32) CapsuleHeader.CapsuleGuid.Data4[4],
+ (UINT32) CapsuleHeader.CapsuleGuid.Data4[5],
+ (UINT32) CapsuleHeader.CapsuleGuid.Data4[6],
+ (UINT32) CapsuleHeader.CapsuleGuid.Data4[7]
+ );
+ if (memcmp (&CapsuleHeader.CapsuleGuid, &mEfiCapsuleHeaderGuid, sizeof (EFI_GUID)) != 0) {
+ printf (" INVALID GUID");
+ }
+
+ printf ("\n");
+ printf (" Header size 0x%08X\n", CapsuleHeader.HeaderSize);
+ printf (" Flags 0x%08X\n", CapsuleHeader.Flags);
+ if (!SplitImage) {
+ printf (" Capsule image size 0x%08X\n", CapsuleHeader.CapsuleImageSize);
+ } else {
+ printf (" Capsule image size 0x%08X (split)\n", CapsuleHeader.CapsuleImageSize);
+ }
+
+ printf (" Sequence number %d\n", CapsuleHeader.SequenceNumber);
+ printf (
+ " InstanceId %08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X\n",
+ CapsuleHeader.InstanceId.Data1,
+ (UINT32) CapsuleHeader.InstanceId.Data2,
+ (UINT32) CapsuleHeader.InstanceId.Data3,
+ (UINT32) CapsuleHeader.InstanceId.Data4[0],
+ (UINT32) CapsuleHeader.InstanceId.Data4[1],
+ (UINT32) CapsuleHeader.InstanceId.Data4[2],
+ (UINT32) CapsuleHeader.InstanceId.Data4[3],
+ (UINT32) CapsuleHeader.InstanceId.Data4[4],
+ (UINT32) CapsuleHeader.InstanceId.Data4[5],
+ (UINT32) CapsuleHeader.InstanceId.Data4[6],
+ (UINT32) CapsuleHeader.InstanceId.Data4[7]
+ );
+ printf (" Offset to capsule 0x%X\n", CapsuleHeader.OffsetToCapsuleBody);
+ //
+ // Dump header data if there
+ //
+ CapsuleHeaderDataSize = CapsuleHeader.OffsetToCapsuleBody - CapsuleHeader.HeaderSize;
+ if (CapsuleHeaderDataSize != 0) {
+ CapsuleHeaderData = (UINT8 *) malloc (CapsuleHeaderDataSize);
+ if (CapsuleHeaderData == NULL) {
+ Error (
+ NULL,
+ 0,
+ 0,
+ "failed to allocate memory to read in capsule header data",
+ "0x%X bytes",
+ CapsuleHeaderDataSize
+ );
+ goto Done;
+ }
+
+ fseek (InFptr, CapsuleHeader.HeaderSize, SEEK_SET);
+ if (fread (CapsuleHeaderData, CapsuleHeaderDataSize, 1, InFptr) != 1) {
+ Error (
+ NULL,
+ 0,
+ 0,
+ "failed to read capsule header data contents from file",
+ "0x%X bytes",
+ CapsuleHeaderDataSize
+ );
+ goto Done;
+ }
+ //
+ // ************************************************************************
+ //
+ // OEM HEADER
+ //
+ // ************************************************************************
+ //
+ if (CapsuleHeader.OffsetToOemDefinedHeader != 0) {
+ OemHeader = (EFI_CAPSULE_OEM_HEADER *) (CapsuleHeaderData + CapsuleHeader.OffsetToOemDefinedHeader - CapsuleHeader.HeaderSize);
+ printf (" OEM Header\n");
+ printf (
+ " GUID %08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X\n",
+ OemHeader->OemGuid.Data1,
+ (UINT32) OemHeader->OemGuid.Data2,
+ (UINT32) OemHeader->OemGuid.Data3,
+ (UINT32) OemHeader->OemGuid.Data4[0],
+ (UINT32) OemHeader->OemGuid.Data4[1],
+ (UINT32) OemHeader->OemGuid.Data4[2],
+ (UINT32) OemHeader->OemGuid.Data4[3],
+ (UINT32) OemHeader->OemGuid.Data4[4],
+ (UINT32) OemHeader->OemGuid.Data4[5],
+ (UINT32) OemHeader->OemGuid.Data4[6],
+ (UINT32) OemHeader->OemGuid.Data4[7]
+ );
+ printf (" Header size: 0x%X\n", OemHeader->HeaderSize);
+ printf (" OEM data");
+ BPtr = (UINT8 *) (OemHeader + 1);
+ for (ByteCount = 0; ByteCount < OemHeader->HeaderSize - sizeof (EFI_CAPSULE_OEM_HEADER); ByteCount++) {
+ if ((ByteCount & 0x7) == 0) {
+ printf ("\n ");
+ }
+
+ printf ("%02X ", (UINT32) *BPtr);
+ BPtr++;
+ }
+
+ printf ("\n");
+ }
+ //
+ // ************************************************************************
+ //
+ // Author, revision, short description, and long description information
+ //
+ // ************************************************************************
+ //
+ if (CapsuleHeader.OffsetToAuthorInformation != 0) {
+ if (DumpCapsuleHeaderStrings (
+ "Author information",
+ (WCHAR *) (CapsuleHeaderData + CapsuleHeader.OffsetToAuthorInformation - CapsuleHeader.HeaderSize)
+ ) != STATUS_SUCCESS) {
+ goto Done;
+ }
+ }
+
+ if (CapsuleHeader.OffsetToRevisionInformation != 0) {
+ if (DumpCapsuleHeaderStrings (
+ "Revision information",
+ (WCHAR *) (CapsuleHeaderData + CapsuleHeader.OffsetToRevisionInformation - CapsuleHeader.HeaderSize)
+ ) != STATUS_SUCCESS) {
+ goto Done;
+ }
+ }
+
+ if (CapsuleHeader.OffsetToShortDescription != 0) {
+ if (DumpCapsuleHeaderStrings (
+ "Short description",
+ (WCHAR *) (CapsuleHeaderData + CapsuleHeader.OffsetToShortDescription - CapsuleHeader.HeaderSize)
+ ) != STATUS_SUCCESS) {
+ goto Done;
+ }
+ }
+
+ if (CapsuleHeader.OffsetToLongDescription != 0) {
+ if (DumpCapsuleHeaderStrings (
+ "Long description",
+ (WCHAR *) (CapsuleHeaderData + CapsuleHeader.OffsetToLongDescription - CapsuleHeader.HeaderSize)
+ ) != STATUS_SUCCESS) {
+ goto Done;
+ }
+ }
+ }
+ //
+ // If it's not a split image, or it is a split image and this is the first in the series, then
+ // dump the cargo volume.
+ //
+ if ((!SplitImage) || (CapsuleHeader.SequenceNumber == 0)) {
+ printf (" Cargo FV dump\n");
+ fseek (InFptr, CapsuleHeader.OffsetToCapsuleBody, SEEK_SET);
+ if (fread (&FVHeader, sizeof (EFI_FIRMWARE_VOLUME_HEADER), 1, InFptr) != 1) {
+ Error (NULL, 0, 0, FileList->FileName, "failed to read cargo FV header");
+ goto Done;
+ }
+
+ printf (" FV length 0x%X", FVHeader.FvLength);
+ if (FileSize - CapsuleHeader.OffsetToCapsuleBody != FVHeader.FvLength) {
+ if (!SplitImage) {
+ printf (" ERROR: expected 0x%X to jive with file size on disk", FileSize - CapsuleHeader.OffsetToCapsuleBody);
+ }
+ }
+
+ printf ("\n");
+ printf (" Signature 0x%X ", FVHeader.Signature);
+ if (FVHeader.Signature == EFI_FVH_SIGNATURE) {
+ printf ("_FVH\n");
+ } else {
+ printf ("INVALID\n");
+ }
+
+ printf (" FV header length 0x%X\n", (UINT32) FVHeader.HeaderLength);
+ printf (" Revision 0x%X\n", (UINT32) FVHeader.Revision);
+ printf ("\n");
+ }
+
+ FileList = FileList->Next;
+ }
+
+Done:
+ if (InFptr != NULL) {
+ fclose (InFptr);
+ }
+
+ if (CapsuleHeaderData != NULL) {
+ free (CapsuleHeaderData);
+ }
+#endif
+}
+
+static
+STATUS
+JoinCapsule (
+ VOID
+ )
+/*++
+
+Routine Description:
+ Join split capsule images into a single image. This is the
+ support function for the -j command-line option.
+
+Arguments:
+ None.
+
+Returns:
+ STATUS_SUCCESS - no problems encountered
+
+--*/
+{
+#if 0
+ UINT32 Size;
+ FILE *InFptr;
+ FILE *OutFptr;
+ INT8 *Buffer;
+ FILE_LIST *FileList;
+ STATUS Status;
+ EFI_CAPSULE_HEADER CapHdr;
+ EFI_CAPSULE_HEADER *CapHdrPtr;
+ UINT32 SizeLeft;
+ UINT32 SequenceNumber;
+ //
+ // Must have at least two files for join mode
+ //
+ if ((mOptions.FileList == NULL) || (mOptions.FileList->Next == NULL)) {
+ Error (NULL, 0, 0, "must specify at least two file names to join", NULL);
+ return STATUS_ERROR;
+ }
+ //
+ // Open the output file
+ //
+ if ((OutFptr = fopen (mOptions.OutputFileName, "wb")) == NULL) {
+ Error (NULL, 0, 0, mOptions.OutputFileName, "failed to open output file for writing");
+ return STATUS_ERROR;
+ }
+
+ FileList = mOptions.FileList;
+ Buffer = NULL;
+ SequenceNumber = 0;
+ InFptr = NULL;
+ SizeLeft = 0;
+ while (FileList != NULL) {
+ if ((InFptr = fopen (FileList->FileName, "rb")) == NULL) {
+ Error (NULL, 0, 0, FileList->FileName, "failed to open file for reading");
+ goto FailDone;
+ }
+ //
+ // Allocate a buffer into which we can read the file.
+ //
+ fseek (InFptr, 0, SEEK_END);
+ Size = ftell (InFptr);
+ rewind (InFptr);
+ Buffer = (char *) malloc (Size);
+ if (Buffer == NULL) {
+ Error (__FILE__, __LINE__, 0, FileList->FileName, "failed to allocate buffer to read file into");
+ goto FailDone;
+ }
+
+ CapHdrPtr = (EFI_CAPSULE_HEADER *) Buffer;
+ if (fread ((void *) Buffer, Size, 1, InFptr) != 1) {
+ Error (NULL, 0, 0, FileList->FileName, "failed to read file contents");
+ goto FailDone;
+ }
+ //
+ // Check the header for validity. Check size first.
+ //
+ if (Size < sizeof (EFI_CAPSULE_HEADER)) {
+ Error (NULL, 0, 0, FileList->FileName, "file size is insufficient for a capsule header");
+ goto FailDone;
+ }
+ //
+ // Check GUID
+ //
+ if (memcmp (&CapHdrPtr->CapsuleGuid, &mEfiCapsuleHeaderGuid, sizeof (EFI_GUID)) != 0) {
+ Error (NULL, 0, 0, FileList->FileName, "invalid capsule GUID");
+ goto FailDone;
+ }
+ //
+ // Check sequence number
+ //
+ if (CapHdrPtr->SequenceNumber != SequenceNumber) {
+ Error (
+ NULL,
+ 0,
+ 0,
+ FileList->FileName,
+ "invalid sequence number %d (expected %d)",
+ CapHdrPtr->SequenceNumber,
+ SequenceNumber
+ );
+ goto FailDone;
+ }
+ //
+ // If the first file, read save the capsule header
+ //
+ if (SequenceNumber == 0) {
+ memcpy (&CapHdr, CapHdrPtr, sizeof (EFI_CAPSULE_HEADER));
+ //
+ // Erase the InstanceId GUID
+ //
+ memset (&CapHdrPtr->InstanceId, 0, sizeof (EFI_GUID));
+ if (fwrite (Buffer, Size, 1, OutFptr) != 1) {
+ Error (NULL, 0, 0, FileList->FileName, "failed to write contents to output file");
+ goto FailDone;
+ }
+
+ if (CapHdr.CapsuleImageSize < Size) {
+ Error (NULL, 0, 0, FileList->FileName, "capsule image size in capsule header < image size");
+ goto FailDone;
+ }
+
+ SizeLeft = CapHdr.CapsuleImageSize - Size;
+ } else {
+ //
+ // Check the GUID against the first file's GUID
+ //
+ if (memcmp (&CapHdr.CapsuleGuid, &CapHdrPtr->CapsuleGuid, sizeof (EFI_GUID)) != 0) {
+ Error (NULL, 0, 0, FileList->FileName, "GUID does not match first file's GUID");
+ goto FailDone;
+ }
+ //
+ // Make sure we're not throwing out any header info
+ //
+ if (CapHdrPtr->OffsetToCapsuleBody > sizeof (EFI_CAPSULE_HEADER)) {
+ //
+ // Could be the split information, so just emit a warning
+ //
+ Warning (
+ NULL,
+ 0,
+ 0,
+ FileList->FileName,
+ "image appears to have additional capsule header information -- ignoring"
+ );
+ } else if (CapHdrPtr->OffsetToCapsuleBody < sizeof (EFI_CAPSULE_HEADER)) {
+ Error (NULL, 0, 0, FileList->FileName, "offset to capsule body in capsule header is insufficient");
+ goto FailDone;
+ }
+
+ if (fwrite (Buffer + CapHdrPtr->OffsetToCapsuleBody, Size - CapHdrPtr->OffsetToCapsuleBody, 1, OutFptr) != 1) {
+ Error (NULL, 0, 0, mOptions.OutputFileName, "failed to write to file");
+ goto FailDone;
+ }
+
+ if (SizeLeft < (Size - CapHdrPtr->OffsetToCapsuleBody)) {
+ Error (NULL, 0, 0, "sum of image sizes exceeds size specified in initial capsule header", NULL);
+ goto FailDone;
+ }
+ //
+ // printf ("FILE: %s OffsetToCapsuleBody=0x%X\n", FileList->FileName, CapHdrPtr->OffsetToCapsuleBody);
+ //
+ SizeLeft = SizeLeft - (Size - CapHdrPtr->OffsetToCapsuleBody);
+ }
+ //
+ // printf ("FILE: %s sizeleft=0x%X\n", FileList->FileName, SizeLeft);
+ //
+ fclose (InFptr);
+ InFptr = NULL;
+ free (Buffer);
+ Buffer = NULL;
+ FileList = FileList->Next;
+ SequenceNumber++;
+ }
+
+ if (SizeLeft) {
+ Error (NULL, 0, 0, "sum of capsule images is insufficient", "0x%X bytes missing", SizeLeft);
+ goto FailDone;
+ }
+
+ Status = STATUS_SUCCESS;
+ goto Done;
+FailDone:
+ Status = STATUS_ERROR;
+Done:
+ if (InFptr != NULL) {
+ fclose (InFptr);
+ }
+
+ if (OutFptr != NULL) {
+ fclose (OutFptr);
+ }
+
+ if (Buffer != NULL) {
+ free (Buffer);
+ }
+
+ return Status;
+
+#endif
+return STATUS_SUCCESS;
+}
+
+static
+STATUS
+DumpCapsuleHeaderStrings (
+ UINT8 *SectionName,
+ WCHAR *Buffer
+ )
+/*++
+
+Routine Description:
+ Given a pointer to string data from a capsule header, dump
+ the strings.
+
+Arguments:
+ SectionName - name of the capsule header section to which
+ the string data pertains
+ Buffer - pointer to string data from a capsule header
+
+Returns:
+ STATUS_SUCCESS - all went well
+
+--*/
+{
+ printf (" %s\n", SectionName);
+ while (*Buffer) {
+ printf (" Language: %S\n", Buffer);
+ while (*Buffer) {
+ Buffer++;
+ }
+
+ Buffer++;
+ while (*Buffer) {
+ if (wcslen (Buffer) > 60) {
+ printf (" %.60S\n", Buffer);
+ Buffer += 60;
+ } else {
+ printf (" %S\n", Buffer);
+ Buffer += wcslen (Buffer);
+ }
+ }
+
+ Buffer++;
+ }
+
+ return STATUS_SUCCESS;
+}
+
+static
+STATUS
+GetHexValue (
+ SOURCE_FILE *SourceFile,
+ UINT32 *Value,
+ UINT32 NumDigits
+ )
+/*++
+
+Routine Description:
+ Scan a hex value from the input stream.
+
+Arguments:
+ SourceFile - input file contents
+ Value - returned value
+ NumDigits - number of digits to read
+
+Returns:
+ STATUS_SUCCESS - if NumDigits were read from the file
+ STATUS_ERROR - otherwise
+
+
+--*/
+{
+ WCHAR *SaveFilePos;
+ UINT32 Digits;
+ WCHAR Nibble;
+
+ SaveFilePos = SourceFile->FileBufferPtr;
+ *Value = 0;
+ Digits = NumDigits;
+ while (Digits > 0) {
+ Nibble = SourceFile->FileBufferPtr[0];
+ if ((Nibble >= UNICODE_0) && (Nibble <= UNICODE_9)) {
+ *Value = (*Value << 4) | (Nibble - UNICODE_0);
+ } else if ((Nibble >= UNICODE_A) && (Nibble <= UNICODE_F)) {
+ *Value = (*Value << 4) | (Nibble - UNICODE_A + 0x10);
+ } else if ((Nibble >= UNICODE_a) && (Nibble <= UNICODE_f)) {
+ *Value = (*Value << 4) | (Nibble - UNICODE_a + 0x10);
+ } else {
+ Error (
+ SourceFile->FileName,
+ SourceFile->LineNum,
+ 0,
+ NULL,
+ "expected %d valid hex nibbles at %.20S",
+ NumDigits,
+ SaveFilePos
+ );
+ return STATUS_ERROR;
+ }
+
+ SourceFile->FileBufferPtr++;
+ Digits--;
+ }
+
+ return STATUS_SUCCESS;
+}
+
+static
+BOOLEAN
+EndOfFile (
+ SOURCE_FILE *File
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ File - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+{
+ if ((UINT32) File->FileBufferPtr - (UINT32) File->FileBuffer >= File->FileSize) {
+ File->EndOfFile = TRUE;
+ }
+ //
+ // Reposition to the end of the file if we went beyond
+ //
+ if (File->EndOfFile) {
+ File->FileBufferPtr = File->FileBuffer + File->FileSize / sizeof (WCHAR);
+ }
+
+ return File->EndOfFile;
+}
+
+static
+void
+SkipWhiteSpace (
+ SOURCE_FILE *SourceFile
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ SourceFile - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+{
+ while (!EndOfFile (SourceFile)) {
+ switch (*SourceFile->FileBufferPtr) {
+ case UNICODE_NULL:
+ case UNICODE_CR:
+ case UNICODE_SPACE:
+ case UNICODE_TAB:
+ SourceFile->FileBufferPtr++;
+ break;
+
+ case UNICODE_LF:
+ SourceFile->FileBufferPtr++;
+ SourceFile->LineNum++;
+ break;
+
+ default:
+ return ;
+ }
+ }
+}
+//
+// Parse a number. Possible format:
+// 1234
+// 1234k
+// 1234K
+// 1M
+// 1m
+// 0x100
+//
+static
+BOOLEAN
+GetNumber (
+ INT8 *Str,
+ UINT32 *Value
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ Str - GC_TODO: add argument description
+ Value - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+{
+ UINT32 LValue;
+
+ *Value = 0;
+ LValue = 0;
+ if (!isdigit (Str[0])) {
+ return FALSE;
+ }
+ //
+ // Look for hex number
+ //
+ if ((Str[0] == '0') && (tolower (Str[1]) == 'x')) {
+ Str += 2;
+ if (Str[0] == 0) {
+ return FALSE;
+ }
+
+ while (Str[0]) {
+ if ((Str[0] >= '0') && (Str[0] <= '9')) {
+ LValue = (LValue << 4) | (Str[0] - '0');
+ } else if ((Str[0] >= 'A') && (Str[0] <= 'F')) {
+ LValue = (LValue << 4) | (Str[0] - 'A' + 0x10);
+ } else if ((Str[0] >= 'a') && (Str[0] <= 'f')) {
+ LValue = (LValue << 4) | (Str[0] - 'a' + 0x10);
+ } else {
+ break;
+ }
+
+ Str++;
+ }
+ } else {
+ LValue = atoi (Str);
+ while (isdigit (*Str)) {
+ Str++;
+ }
+ }
+ //
+ // If string left over, better be one character we recognize
+ //
+ if (Str[0]) {
+ if (Str[1]) {
+ return FALSE;
+ }
+
+ switch (Str[0]) {
+ case 'k':
+ case 'K':
+ LValue *= 1024;
+ break;
+
+ case 'm':
+ case 'M':
+ LValue *= 1024 * 1024;
+ break;
+
+ default:
+ return FALSE;
+ }
+ }
+
+ *Value = LValue;
+ return TRUE;
+}
+//
+// Process the command-line arguments
+//
+static
+STATUS
+ProcessArgs (
+ int Argc,
+ char *Argv[]
+ )
+/*++
+
+Routine Description:
+
+ Processes command line arguments.
+
+Arguments:
+
+ Argc - Number of command line arguments
+ Argv[] - Array of files input on command line
+
+Returns:
+
+ STATUS_ERROR - Function exited with an error
+ STATUS_SUCCESS - Function executed successfully
+
+--*/
+{
+ FILE_LIST *NewFile;
+
+ FILE_LIST *LastFile;
+ SIZE_LIST *NewSize;
+
+ NewFile = NULL;
+ NewSize = NULL;
+
+ //
+ // Clear our globals
+ //
+ memset ((char *) &mOptions, 0, sizeof (mOptions));
+
+ //
+ // Skip program name
+ //
+ Argc--;
+ Argv++;
+
+ if (Argc == 0) {
+ Usage ();
+ return STATUS_ERROR;
+ }
+ //
+ // Process until no more options
+ //
+ while ((Argc > 0) && (Argv[0][0] == '-')) {
+ if (stricmp (Argv[0], "-script") == 0) {
+ //
+ // Check for one more arg
+ //
+ if (Argc > 1) {
+ //
+ // Save the file name
+ //
+ if (strlen (Argv[1]) >= sizeof (mOptions.ScriptFileName)) {
+ Error (NULL, 0, 0, NULL, "input script file name length exceeds internal buffer size");
+
+ if (NewFile != NULL) {
+ free (NewFile);
+ }
+ if (NewSize != NULL) {
+ free (NewSize);
+ }
+
+ return STATUS_ERROR;
+ }
+
+ strcpy (mOptions.ScriptFileName, Argv[1]);
+ } else {
+ Error (NULL, 0, 0, Argv[0], "missing script file name with option");
+ Usage ();
+
+ if (NewFile != NULL) {
+ free (NewFile);
+ }
+ if (NewSize != NULL) {
+ free (NewSize);
+ }
+
+ return STATUS_ERROR;
+ }
+
+ Argc--;
+ Argv++;
+ //
+ // -o outfilename -- specify output file name (required)
+ //
+ } else if (stricmp (Argv[0], "-o") == 0) {
+ //
+ // check for one more arg
+ //
+ if (Argc > 1) {
+ //
+ // Try to open the file
+ //
+ // if ((mOptions.OutFptr = fopen (Argv[1], "wb")) == NULL) {
+ // Error (NULL, 0, 0, Argv[1], "failed to open output file for writing");
+ // return STATUS_ERROR;
+ // }
+ //
+ strcpy (mOptions.OutputFileName, Argv[1]);
+ } else {
+ Error (NULL, 0, 0, Argv[0], "missing output filename with option");
+ Usage ();
+
+ if (NewFile != NULL) {
+ free (NewFile);
+ }
+ if (NewSize != NULL) {
+ free (NewSize);
+ }
+
+ return STATUS_ERROR;
+ }
+
+ Argc--;
+ Argv++;
+ } else if (stricmp (Argv[0], "-j") == 0) {
+ mOptions.JoinMode = TRUE;
+ //
+ // -split <size> option (multiple allowed)
+ //
+ } else if (stricmp (Argv[0], "-split") == 0) {
+ if (Argc > 1) {
+ NewSize = (SIZE_LIST *) malloc (sizeof (SIZE_LIST));
+ if (NewSize == NULL) {
+ Error (NULL, 0, 0, "memory allocation failure", NULL);
+
+ if (NewFile != NULL) {
+ free (NewFile);
+ }
+ if (NewSize != NULL) {
+ free (NewSize);
+ }
+
+ return STATUS_ERROR;
+ }
+
+ memset (NewSize, 0, sizeof (SIZE_LIST));
+ //
+ // Get the size from the next arg, and then add this size
+ // to our size list
+ //
+ if (!GetNumber (Argv[1], &NewSize->Size)) {
+ Error (NULL, 0, 0, Argv[1], "invalid split size argument");
+
+ if (NewFile != NULL) {
+ free (NewFile);
+ }
+ if (NewSize != NULL) {
+ free (NewSize);
+ }
+
+ return STATUS_ERROR;
+ }
+
+ if (mOptions.SizeList == NULL) {
+ mOptions.SizeList = NewSize;
+ mOptions.CurrentSize = NewSize;
+ } else {
+ mOptions.LastSize->Next = NewSize;
+ }
+
+ mOptions.LastSize = NewSize;
+ free (NewSize);
+ } else {
+ Error (NULL, 0, 0, Argv[0], "missing size parameter with option");
+ Usage ();
+
+ if (NewFile != NULL) {
+ free (NewFile);
+ }
+ if (NewSize != NULL) {
+ free (NewSize);
+ }
+
+ return STATUS_ERROR;
+ }
+
+ Argc--;
+ Argv++;
+ } else if ((stricmp (Argv[0], "-h") == 0) || (strcmp (Argv[0], "-?") == 0)) {
+ Usage ();
+
+ if (NewFile != NULL) {
+ free (NewFile);
+ }
+ if (NewSize != NULL) {
+ free (NewSize);
+ }
+
+ return STATUS_ERROR;
+ //
+ // Default minimum header
+ //
+ } else if (stricmp (Argv[0], "-dump") == 0) {
+ mOptions.Dump = TRUE;
+ } else if (stricmp (Argv[0], "-v") == 0) {
+ mOptions.Verbose = TRUE;
+ } else {
+ Error (NULL, 0, 0, Argv[0], "unrecognized option");
+ Usage ();
+
+ if (NewFile != NULL) {
+ free (NewFile);
+ }
+ if (NewSize != NULL) {
+ free (NewSize);
+ }
+
+ return STATUS_ERROR;
+ }
+
+ Argc--;
+ Argv++;
+ }
+ //
+ // Can't -j join files and -s split output capsule
+ //
+ if ((mOptions.SizeList != NULL) && (mOptions.JoinMode)) {
+ Error (NULL, 0, 0, "cannot specify both -j and -size", NULL);
+
+ if (NewFile != NULL) {
+ free (NewFile);
+ }
+ if (NewSize != NULL) {
+ free (NewSize);
+ }
+
+ return STATUS_ERROR;
+ }
+ //
+ // Must have specified an output file name if not -dump
+ //
+ if ((mOptions.Dump == 0) && (mOptions.OutputFileName[0] == 0)) {
+ Error (NULL, 0, 0, NULL, "-o OutputFileName must be specified");
+ Usage ();
+
+ if (NewFile != NULL) {
+ free (NewFile);
+ }
+ if (NewSize != NULL) {
+ free (NewSize);
+ }
+
+ return STATUS_ERROR;
+ }
+ //
+ // Rest of arguments are input files. The first one is a firmware
+ // volume image, and the rest are FFS files that are to be inserted
+ // into the firmware volume.
+ //
+ LastFile = NULL;
+ while (Argc > 0) {
+ NewFile = (FILE_LIST *) malloc (sizeof (FILE_LIST));
+ if (NewFile == NULL) {
+ Error (NULL, 0, 0, "memory allocation failure", NULL);
+
+ if (NewFile != NULL) {
+ free (NewFile);
+ }
+ if (NewSize != NULL) {
+ free (NewSize);
+ }
+
+ return STATUS_ERROR;
+ }
+
+ memset ((char *) NewFile, 0, sizeof (FILE_LIST));
+ strcpy (NewFile->FileName, Argv[0]);
+ if (mOptions.FileList == NULL) {
+ mOptions.FileList = NewFile;
+ } else {
+ if (LastFile == NULL) {
+ LastFile = NewFile;
+ } else {
+ LastFile->Next = NewFile;
+ }
+ }
+
+ LastFile = NewFile;
+ Argc--;
+ Argv++;
+ }
+
+ //
+ // Must have provided at least one file name
+ //
+ if (mOptions.FileList == NULL) {
+ Error (NULL, 0, 0, "must specify at least one file name", NULL);
+ Usage ();
+
+ if (NewFile != NULL) {
+ free (NewFile);
+ }
+ if (NewSize != NULL) {
+ free (NewSize);
+ }
+
+ return STATUS_ERROR;
+ }
+
+ return STATUS_SUCCESS;
+}
+
+static
+void
+Usage (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Print usage information for this utility.
+
+Arguments:
+
+ None.
+
+Returns:
+
+ Nothing.
+
+--*/
+{
+ int Index;
+ static const char *Str[] = {
+ PROGRAM_NAME " -- create a capsule header",
+ " Usage: "PROGRAM_NAME " {options} [CapsuleFV]",
+ //
+ // {FfsFileNames}",
+ //
+ " Options include:",
+ " -h or -? for this help information",
+ " -script fname to take capsule header info from unicode script",
+ " file fname",
+ " -o fname write output to file fname (required)",
+ " -split size split capsule image into multiple output files",
+ " -dump to dump a capsule header",
+ " -v for verbose output\n",
+ " -j to join split capsule images into a single image",
+ "",
+ " CapsuleFV is the name of an existing well-formed Tiano firmware",
+ " volume file.",
+ //
+ // FfsFileNames are the names of one or more Tiano FFS files to",
+ // " insert into the output capsule image.",
+ //
+ NULL
+ };
+ for (Index = 0; Str[Index] != NULL; Index++) {
+ fprintf (stdout, "%s\n", Str[Index]);
+ }
+}
diff --git a/Source/GenCapsuleHdr/build.xml b/Source/GenCapsuleHdr/build.xml
new file mode 100644
index 0000000..db72d16
--- /dev/null
+++ b/Source/GenCapsuleHdr/build.xml
@@ -0,0 +1,71 @@
+<?xml version="1.0" ?>
+<!--
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+-->
+<project default="GenTool" basedir=".">
+<!--
+ EDK GenCapsuleHdr Tool
+ Copyright (c) 2006, Intel Corporation
+-->
+ <property name="ToolName" value="GenCapsuleHdr"/>
+ <property name="FileSet" value="GenCapsuleHdr.c"/>
+
+ <taskdef resource="net/sf/antcontrib/antlib.xml"/>
+
+ <property name="LINK_OUTPUT_TYPE" value="static"/>
+ <property name="BUILD_DIR" value="${PACKAGE_DIR}/${ToolName}/tmp"/>
+
+ <target name="GenTool" depends="init, Tool">
+ <echo message="The EDK Tool: ${ToolName} build has completed!"/>
+ </target>
+
+ <target name="init">
+ <echo message="Building the EDK Tool: ${ToolName}"/>
+ <mkdir dir="${BUILD_DIR}"/>
+ </target>
+
+ <target name="Tool" depends="init">
+ <cc name="${ToolChain}" objdir="${BUILD_DIR}"
+ outfile="${BIN_DIR}/${ToolName}"
+ outtype="executable"
+ optimize="speed"
+ debug="true">
+ <compilerarg value="${ExtraArgus}" if="ExtraArgus" />
+
+ <fileset dir="${basedir}/${ToolName}"
+ includes="${FileSet}"
+ defaultexcludes="TRUE"
+ excludes="*.xml *.inf"/>
+
+ <includepath path="${PACKAGE_DIR}/Include"/>
+ <includepath path="${PACKAGE_DIR}/Include/${HostArch}"/>
+ <includepath path="${PACKAGE_DIR}/Common"/>
+ <libset dir="${LIB_DIR}" libs="CommonTools"/>
+ <syslibset dir="${env.CYGWIN_HOME}/lib/mingw" libs="msvcr71" if="cygwin"/>
+ </cc>
+ </target>
+
+ <target name="clean">
+ <echo message="Removing Intermediate Files Only"/>
+ <delete>
+ <fileset dir="${BUILD_DIR}" includes="*.obj"/>
+ </delete>
+ </target>
+
+ <target name="cleanall">
+ <echo message="Removing Object Files and the Executable: ${ToolName}${ext_exe}"/>
+ <delete failonerror="false" quiet="true" includeEmptyDirs="true">
+ <fileset dir="${BUILD_DIR}"/>
+ <fileset file="${BIN_DIR}/${ToolName}${ext_exe}"/>
+ <fileset file="${BIN_DIR}/${ToolName}.pdb"/>
+ </delete>
+ </target>
+
+</project>
diff --git a/Source/GenDepex/DepexParser.c b/Source/GenDepex/DepexParser.c
new file mode 100644
index 0000000..9f0a0cb
--- /dev/null
+++ b/Source/GenDepex/DepexParser.c
@@ -0,0 +1,903 @@
+/*++
+
+Copyright (c) 2004, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ DepexParser.c
+
+Abstract:
+
+ Validate Dependency Expression syntax
+ recursive descent Algorithm
+
+ The original BNF grammar(taken from "Pre EFI Initialization Core Interface Specification
+ draft review 0.9") is thus:
+ <depex> ::= BEFORE <guid> END
+ | AFTER <guid> END
+ | SOR <bool> END
+ | <bool> END
+ <bool> ::= <bool> AND <term>
+ | <bool> OR <term>
+ | <term>
+ <term> ::= NOT <factor>
+ | <factor>
+ <factor> ::= <bool>
+ | TRUE
+ | FALSE
+ | GUID
+
+ <guid> ::= '{' <hex32> ',' <hex16> ',' <hex16> ','
+ <hex8> ',' <hex8> ',' <hex8> ',' <hex8> ','
+ <hex8> ',' <hex8> ',' <hex8> ',' <hex8> '}'
+ <hex32> ::= <hexprefix> <hexvalue>
+ <hex16> ::= <hexprefix> <hexvalue>
+ <hex8> ::= <hexprefix> <hexvalue>
+ <hexprefix>::= '0' 'x'
+ | '0' 'X'
+ <hexvalue> ::= <hexdigit> <hexvalue>
+ | <hexdigit>
+ <hexdigit> ::= [0-9]
+ | [a-f]
+ | [A-F]
+
+ After cleaning left recursive and parentheses supported, the BNF grammar used in this module is thus:
+ <depex> ::= BEFORE <guid>
+ | AFTER <guid>
+ | SOR <bool>
+ | <bool>
+ <bool> ::= <term><rightbool>
+ <rightbool>::= AND <term><rightbool>
+ | OR <term><rightbool>
+ | ''
+ <term> ::= NOT <factor>
+ | <factor>
+ <factor> ::= '('<bool>')'<rightfactor>
+ | NOT <factor> <rightbool> <rightfactor>
+ | TRUE <rightfactor>
+ | FALSE <rightfactor>
+ | END <rightfactor>
+ | <guid> <rightfactor>
+ <rightfactor> ::=AND <term><rightbool> <rightfactor>
+ | OR <term><rightbool> <rightfactor>
+ | ''
+ <guid> ::= '{' <hex32> ',' <hex16> ',' <hex16> ','
+ <hex8> ',' <hex8> ',' <hex8> ',' <hex8> ','
+ <hex8> ',' <hex8> ',' <hex8> ',' <hex8> '}'
+ <hex32> ::= <hexprefix> <hexvalue>
+ <hex16> ::= <hexprefix> <hexvalue>
+ <hex8> ::= <hexprefix> <hexvalue>
+ <hexprefix>::= '0' 'x'
+ | '0' 'X'
+ <hexvalue> ::= <hexdigit> <hexvalue>
+ | <hexdigit>
+ <hexdigit> ::= [0-9]
+ | [a-f]
+ | [A-F]
+
+ Note: 1. There's no precedence in operators except parentheses;
+ 2. For hex32, less and equal than 8 bits is valid, more than 8 bits is invalid.
+ Same constraint for hex16 is 4, hex8 is 2. All hex should contains at least 1 bit.
+ 3. "<factor> ::= '('<bool>')'<rightfactor>" is added to support parentheses;
+ 4. "<factor> ::= GUID" is changed to "<factor> ::= <guid>";
+ 5. "DEPENDENCY_END" is the terminal of the expression. But it has been filtered by caller.
+ During parsing, "DEPENDENCY_END" will be treated as illegal factor;
+
+ This code should build in any environment that supports a standard C-library w/ string
+ operations and File I/O services.
+
+ As an example of usage, consider the following:
+
+ The input string could be something like:
+
+ NOT ({ 0xce345171, 0xba0b, 0x11d2, 0x8e, 0x4f, 0x0, 0xa0, 0xc9, 0x69, 0x72,
+ 0x3b } AND { 0x964e5b22, 0x6459, 0x11d2, 0x8e, 0x39, 0x0, 0xa0, 0xc9, 0x69,
+ 0x72, 0x3b }) OR { 0x03c4e603, 0xac28, 0x11d3, 0x9a, 0x2d, 0x00, 0x90, 0x27,
+ 0x3f, 0xc1, 0x4d } AND
+
+ It's invalid for an extra "AND" in the end.
+
+ Complies with Tiano C Coding Standards Document, version 0.33, 16 Aug 2001.
+
+--*/
+
+#include "DepexParser.h"
+
+BOOLEAN
+ParseBool (
+ IN INT8 *Pbegin,
+ IN UINT32 length,
+ IN OUT INT8 **Pindex
+ );
+
+BOOLEAN
+ParseTerm (
+ IN INT8 *Pbegin,
+ IN UINT32 length,
+ IN OUT INT8 **Pindex
+ );
+
+BOOLEAN
+ParseRightBool (
+ IN INT8 *Pbegin,
+ IN UINT32 length,
+ IN OUT INT8 **Pindex
+ );
+
+BOOLEAN
+ParseFactor (
+ IN INT8 *Pbegin,
+ IN UINT32 length,
+ IN OUT INT8 **Pindex
+ );
+
+VOID
+LeftTrim (
+ IN INT8 *Pbegin,
+ IN UINT32 length,
+ IN OUT INT8 **Pindex
+ )
+/*++
+
+Routine Description:
+
+ Left trim the space, '\n' and '\r' character in string.
+ The space at the end does not need trim.
+
+
+Arguments:
+
+ Pbegin The pointer to the string
+ length length of the string
+ Pindex The pointer of pointer to the next parse character in the string
+
+Returns:
+
+ None
+
+
+--*/
+{
+ while
+ (
+ ((*Pindex) < (Pbegin + length)) &&
+ ((strncmp (*Pindex, " ", 1) == 0) || (strncmp (*Pindex, "\n", 1) == 0) || (strncmp (*Pindex, "\r", 1) == 0))
+ ) {
+ (*Pindex)++;
+ }
+}
+
+BOOLEAN
+ParseHexdigit (
+ IN INT8 *Pbegin,
+ IN UINT32 length,
+ IN OUT INT8 **Pindex
+ )
+/*++
+
+Routine Description:
+
+ Parse Hex bit in dependency expression.
+
+Arguments:
+
+ Pbegin The pointer to the string
+ length Length of the string
+ Pindex The pointer of pointer to the next parse character in the string
+
+Returns:
+
+ BOOLEAN If parses a valid hex bit, return TRUE, otherwise FALSE
+
+
+--*/
+{
+ //
+ // <hexdigit> ::= [0-9] | [a-f] | [A-F]
+ //
+ if (((**Pindex) >= '0' && (**Pindex) <= '9') ||
+ ((**Pindex) >= 'a' && (**Pindex) <= 'f') ||
+ ((**Pindex) >= 'A' && (**Pindex) <= 'F')
+ ) {
+ (*Pindex)++;
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
+BOOLEAN
+ParseHex32 (
+ IN INT8 *Pbegin,
+ IN UINT32 length,
+ IN OUT INT8 **Pindex
+ )
+/*++
+
+Routine Description:
+
+ Parse Hex32 in dependency expression.
+
+Arguments:
+
+ Pbegin The pointer to the string
+ length Length of the string
+ Pindex The pointer of point to the next parse character in the string
+
+Returns:
+
+ BOOLEAN If parses a valid hex32, return TRUE, otherwise FALSE
+
+
+--*/
+{
+ INT32 Index;
+ INT8 *Pin;
+
+ Index = 0;
+ Pin = *Pindex;
+ LeftTrim (Pbegin, length, Pindex);
+
+ if ((strncmp (*Pindex, "0x", 2) != 0) && (strncmp (*Pindex, "0X", 2) != 0)) {
+ return FALSE;
+ }
+ (*Pindex) += 2;
+
+ while (ParseHexdigit (Pbegin, length, Pindex)) {
+ Index++;
+ }
+
+ if (Index > 0 && Index <= 8) {
+ return TRUE;
+ } else {
+ *Pindex = Pin;
+ return FALSE;
+ }
+}
+
+BOOLEAN
+ParseHex16 (
+ IN INT8 *Pbegin,
+ IN UINT32 length,
+ IN OUT INT8 **Pindex
+ )
+/*++
+
+Routine Description:
+
+ Parse Hex16 in dependency expression.
+
+Arguments:
+
+ Pbegin The pointer to the string
+ length Length of the string
+ Pindex The pointer of pointer to the next parse character in the string
+
+Returns:
+
+ BOOLEAN If parses a valid hex16, return TRUE, otherwise FALSE
+
+
+--*/
+{
+ int Index;
+ INT8 *Pin;
+
+ Index = 0;
+ Pin = *Pindex;
+ LeftTrim (Pbegin, length, Pindex);
+
+ if ((strncmp (*Pindex, "0x", 2) != 0) && (strncmp (*Pindex, "0X", 2) != 0)) {
+ return FALSE;
+ }
+ (*Pindex) += 2;
+
+ while (ParseHexdigit (Pbegin, length, Pindex)) {
+ Index++;
+ }
+
+ if (Index > 0 && Index <= 4) {
+ return TRUE;
+ } else {
+ *Pindex = Pin;
+ return FALSE;
+ }
+}
+
+BOOLEAN
+ParseHex8 (
+ IN INT8 *Pbegin,
+ IN UINT32 length,
+ IN OUT INT8 **Pindex
+ )
+/*++
+
+Routine Description:
+
+ Parse Hex8 in dependency expression.
+
+Arguments:
+
+ Pbegin The pointer to the string
+ length Length of the string
+ Pindex The pointer of pointer to the next parse character in the string
+
+Returns:
+
+ BOOLEAN If parses a valid hex8, return TRUE, otherwise FALSE
+
+
+--*/
+{
+ int Index;
+ INT8 *Pin;
+
+ Index = 0;
+ Pin = *Pindex;
+ LeftTrim (Pbegin, length, Pindex);
+
+ if ((strncmp (*Pindex, "0x", 2) != 0) && (strncmp (*Pindex, "0X", 2) != 0)) {
+ return FALSE;
+ }
+ (*Pindex) += 2;
+
+ while (ParseHexdigit (Pbegin, length, Pindex)) {
+ Index++;
+ }
+
+ if (Index > 0 && Index <= 2) {
+ return TRUE;
+ } else {
+ *Pindex = Pin;
+ return FALSE;
+ }
+}
+
+BOOLEAN
+ParseGuid (
+ IN INT8 *Pbegin,
+ IN UINT32 length,
+ IN OUT INT8 **Pindex
+ )
+/*++
+
+Routine Description:
+
+ Parse guid in dependency expression.
+ There can be any number of spaces between '{' and hexword, ',' and hexword,
+ hexword and ',', hexword and '}'. The hexword include hex32, hex16 and hex8.
+
+Arguments:
+
+ Pbegin The pointer to the string
+ length length of the string
+ Pindex The pointer of pointer to the next parse character in the string
+
+Returns:
+
+ BOOLEAN If parses a valid guid, return TRUE, otherwise FALSE
+
+
+--*/
+{
+ INT32 Index;
+ INT8 *Pin;
+ Pin = *Pindex;
+ LeftTrim (Pbegin, length, Pindex);
+ if (strncmp (*Pindex, "{", 1) != 0) {
+ return FALSE;
+ }
+ (*Pindex)++;
+
+ LeftTrim (Pbegin, length, Pindex);
+ if (!ParseHex32 (Pbegin, length, Pindex)) {
+ *Pindex = Pin;
+ return FALSE;
+ }
+
+ LeftTrim (Pbegin, length, Pindex);
+ if (strncmp (*Pindex, ",", 1) != 0) {
+ return FALSE;
+ } else {
+ (*Pindex)++;
+ }
+
+ for (Index = 0; Index < 2; Index++) {
+ LeftTrim (Pbegin, length, Pindex);
+ if (!ParseHex16 (Pbegin, length, Pindex)) {
+ *Pindex = Pin;
+ return FALSE;
+ }
+
+ LeftTrim (Pbegin, length, Pindex);
+ if (strncmp (*Pindex, ",", 1) != 0) {
+ return FALSE;
+ } else {
+ (*Pindex)++;
+ }
+ }
+
+ LeftTrim (Pbegin, length, Pindex);
+ if (strncmp (*Pindex, "{", 1) != 0) {
+ return FALSE;
+ }
+ (*Pindex)++;
+
+ for (Index = 0; Index < 7; Index++) {
+ LeftTrim (Pbegin, length, Pindex);
+ if (!ParseHex8 (Pbegin, length, Pindex)) {
+ *Pindex = Pin;
+ return FALSE;
+ }
+
+ LeftTrim (Pbegin, length, Pindex);
+ if (strncmp (*Pindex, ",", 1) != 0) {
+ return FALSE;
+ } else {
+ (*Pindex)++;
+ }
+ }
+
+ LeftTrim (Pbegin, length, Pindex);
+ if (!ParseHex8 (Pbegin, length, Pindex)) {
+ *Pindex = Pin;
+ return FALSE;
+ }
+
+ LeftTrim (Pbegin, length, Pindex);
+ if (strncmp (*Pindex, "}", 1) != 0) {
+ return FALSE;
+ } else {
+ (*Pindex)++;
+ }
+
+ LeftTrim (Pbegin, length, Pindex);
+ if (strncmp (*Pindex, "}", 1) != 0) {
+ return FALSE;
+ } else {
+ (*Pindex)++;
+ }
+
+ return TRUE;
+}
+
+BOOLEAN
+ParseRightFactor (
+ IN INT8 *Pbegin,
+ IN UINT32 length,
+ IN OUT INT8 **Pindex
+ )
+/*++
+
+Routine Description:
+
+ Parse rightfactor in bool expression.
+
+Arguments:
+
+ Pbegin The pointer to the string
+ length length of the string
+ Pindex The pointer of pointer to the next parse character in the string
+
+Returns:
+
+ BOOLEAN If string is a valid rightfactor expression, return TRUE, otherwise FALSE
+
+
+--*/
+{
+ INT8 *Pin;
+
+ Pin = *Pindex;
+ LeftTrim (Pbegin, length, Pindex);
+
+ //
+ // <rightfactor> ::=AND <term> <rightbool> <rightfactor>
+ //
+ if (strncmp (*Pindex, OPERATOR_AND, strlen (OPERATOR_AND)) == 0) {
+ *Pindex += strlen (OPERATOR_AND);
+ LeftTrim (Pbegin, length, Pindex);
+
+ if (ParseTerm (Pbegin, length, Pindex)) {
+ LeftTrim (Pbegin, length, Pindex);
+
+ if (ParseRightBool (Pbegin, length, Pindex)) {
+ LeftTrim (Pbegin, length, Pindex);
+ if (ParseRightFactor (Pbegin, length, Pindex)) {
+ return TRUE;
+ } else {
+ *Pindex = Pin;
+ }
+ } else {
+ *Pindex = Pin;
+ }
+ } else {
+ *Pindex = Pin;
+ }
+ }
+ //
+ // <rightfactor> ::=OR <term> <rightbool> <rightfactor>
+ //
+ if (strncmp (*Pindex, OPERATOR_OR, strlen (OPERATOR_OR)) == 0) {
+ *Pindex += strlen (OPERATOR_OR);
+ LeftTrim (Pbegin, length, Pindex);
+
+ if (ParseTerm (Pbegin, length, Pindex)) {
+ LeftTrim (Pbegin, length, Pindex);
+
+ if (ParseRightBool (Pbegin, length, Pindex)) {
+ LeftTrim (Pbegin, length, Pindex);
+ if (ParseRightFactor (Pbegin, length, Pindex)) {
+ return TRUE;
+ } else {
+ *Pindex = Pin;
+ }
+ } else {
+ *Pindex = Pin;
+ }
+ } else {
+ *Pindex = Pin;
+ }
+ }
+ //
+ // <rightfactor> ::= ''
+ //
+ *Pindex = Pin;
+ return TRUE;
+}
+
+BOOLEAN
+ParseRightBool (
+ IN INT8 *Pbegin,
+ IN UINT32 length,
+ IN OUT INT8 **Pindex
+ )
+/*++
+
+Routine Description:
+
+ Parse rightbool in bool expression.
+
+Arguments:
+
+ Pbegin The pointer to the string
+ length length of the string
+ Pindex The pointer of pointer to the next parse character in the string
+
+Returns:
+
+ BOOLEAN If string is a valid rightbool expression, return TRUE, otherwise FALSE
+
+
+--*/
+{
+ INT8 *Pin;
+
+ Pin = *Pindex;
+ LeftTrim (Pbegin, length, Pindex);
+
+ //
+ // <rightbool>::= AND <term><rightbool>
+ //
+ if (strncmp (*Pindex, OPERATOR_AND, strlen (OPERATOR_AND)) == 0) {
+ *Pindex += strlen (OPERATOR_AND);
+ LeftTrim (Pbegin, length, Pindex);
+
+ if (ParseTerm (Pbegin, length, Pindex)) {
+ LeftTrim (Pbegin, length, Pindex);
+
+ if (ParseRightBool (Pbegin, length, Pindex)) {
+ return TRUE;
+ } else {
+ *Pindex = Pin;
+ }
+ } else {
+ *Pindex = Pin;
+ }
+ }
+ //
+ // <rightbool>::= OR <term><rightbool>
+ //
+ if (strncmp (*Pindex, OPERATOR_OR, strlen (OPERATOR_OR)) == 0) {
+ *Pindex += strlen (OPERATOR_OR);
+ LeftTrim (Pbegin, length, Pindex);
+
+ if (ParseTerm (Pbegin, length, Pindex)) {
+ LeftTrim (Pbegin, length, Pindex);
+
+ if (ParseRightBool (Pbegin, length, Pindex)) {
+ return TRUE;
+ } else {
+ *Pindex = Pin;
+ }
+ } else {
+ *Pindex = Pin;
+ }
+ }
+ //
+ // <rightbool>::= ''
+ //
+ *Pindex = Pin;
+ return TRUE;
+}
+
+BOOLEAN
+ParseFactor (
+ IN INT8 *Pbegin,
+ IN UINT32 length,
+ IN OUT INT8 **Pindex
+ )
+/*++
+
+Routine Description:
+
+ Parse factor in bool expression.
+
+Arguments:
+
+ Pbegin The pointer to the string
+ length length of the string
+ Pindex The pointer of pointer to the next parse character in the string
+
+Returns:
+
+ BOOLEAN If string is a valid factor, return TRUE, otherwise FALSE
+
+
+--*/
+{
+ INT8 *Pin;
+
+ Pin = *Pindex;
+ LeftTrim (Pbegin, length, Pindex);
+
+ //
+ // <factor> ::= '('<bool>')'<rightfactor>
+ //
+ if (strncmp (*Pindex, OPERATOR_LEFT_PARENTHESIS, strlen (OPERATOR_LEFT_PARENTHESIS)) == 0) {
+ *Pindex += strlen (OPERATOR_LEFT_PARENTHESIS);
+ LeftTrim (Pbegin, length, Pindex);
+
+ if (!ParseBool (Pbegin, length, Pindex)) {
+ *Pindex = Pin;
+ } else {
+ LeftTrim (Pbegin, length, Pindex);
+
+ if (strncmp (*Pindex, OPERATOR_RIGHT_PARENTHESIS, strlen (OPERATOR_RIGHT_PARENTHESIS)) == 0) {
+ *Pindex += strlen (OPERATOR_RIGHT_PARENTHESIS);
+ LeftTrim (Pbegin, length, Pindex);
+
+ if (ParseRightFactor (Pbegin, length, Pindex)) {
+ return TRUE;
+ } else {
+ *Pindex = Pin;
+ }
+ }
+ }
+ }
+ //
+ // <factor> ::= NOT <factor> <rightbool> <rightfactor>
+ //
+ if (strncmp (*Pindex, OPERATOR_NOT, strlen (OPERATOR_NOT)) == 0) {
+ *Pindex += strlen (OPERATOR_NOT);
+ LeftTrim (Pbegin, length, Pindex);
+
+ if (ParseFactor (Pbegin, length, Pindex)) {
+ LeftTrim (Pbegin, length, Pindex);
+
+ if (ParseRightBool (Pbegin, length, Pindex)) {
+ LeftTrim (Pbegin, length, Pindex);
+
+ if (ParseRightFactor (Pbegin, length, Pindex)) {
+ return TRUE;
+ } else {
+ *Pindex = Pin;
+ }
+ } else {
+ *Pindex = Pin;
+ }
+ } else {
+ *Pindex = Pin;
+ }
+ }
+ //
+ // <factor> ::= TRUE <rightfactor>
+ //
+ if (strncmp (*Pindex, OPERATOR_TRUE, strlen (OPERATOR_TRUE)) == 0) {
+ *Pindex += strlen (OPERATOR_TRUE);
+ LeftTrim (Pbegin, length, Pindex);
+
+ if (ParseRightFactor (Pbegin, length, Pindex)) {
+ return TRUE;
+ } else {
+ *Pindex = Pin;
+ }
+ }
+ //
+ // <factor> ::= FALSE <rightfactor>
+ //
+ if (strncmp (*Pindex, OPERATOR_FALSE, strlen (OPERATOR_FALSE)) == 0) {
+ *Pindex += strlen (OPERATOR_FALSE);
+ LeftTrim (Pbegin, length, Pindex);
+
+ if (ParseRightFactor (Pbegin, length, Pindex)) {
+ return TRUE;
+ } else {
+ *Pindex = Pin;
+ }
+ }
+ //
+ // <factor> ::= <guid> <rightfactor>
+ //
+ if (ParseGuid (Pbegin, length, Pindex)) {
+ LeftTrim (Pbegin, length, Pindex);
+
+ if (ParseRightFactor (Pbegin, length, Pindex)) {
+ return TRUE;
+ } else {
+ *Pindex = Pin;
+ return FALSE;
+ }
+ } else {
+ *Pindex = Pin;
+ return FALSE;
+ }
+}
+
+BOOLEAN
+ParseTerm (
+ IN INT8 *Pbegin,
+ IN UINT32 length,
+ IN OUT INT8 **Pindex
+ )
+/*++
+
+Routine Description:
+
+ Parse term in bool expression.
+
+Arguments:
+
+ Pbegin The pointer to the string
+ length length of the string
+ Pindex The pointer of pointer to the next parse character in the string
+
+Returns:
+
+ BOOLEAN If string is a valid term, return TRUE, otherwise FALSE
+
+
+--*/
+{
+ INT8 *Pin;
+
+ Pin = *Pindex;
+ LeftTrim (Pbegin, length, Pindex);
+
+ //
+ // <term> ::= NOT <factor>
+ //
+ if (strncmp (*Pindex, OPERATOR_NOT, strlen (OPERATOR_NOT)) == 0) {
+ *Pindex += strlen (OPERATOR_NOT);
+ LeftTrim (Pbegin, length, Pindex);
+
+ if (!ParseFactor (Pbegin, length, Pindex)) {
+ *Pindex = Pin;
+ } else {
+ return TRUE;
+ }
+ }
+ //
+ // <term> ::=<factor>
+ //
+ if (ParseFactor (Pbegin, length, Pindex)) {
+ return TRUE;
+ } else {
+ *Pindex = Pin;
+ return FALSE;
+ }
+}
+
+BOOLEAN
+ParseBool (
+ IN INT8 *Pbegin,
+ IN UINT32 length,
+ IN OUT INT8 **Pindex
+ )
+/*++
+
+Routine Description:
+
+ Parse bool expression.
+
+Arguments:
+
+ Pbegin The pointer to the string
+ length length of the string
+ Pindex The pointer of pointer to the next parse character in the string
+
+Returns:
+
+ BOOLEAN If string is a valid bool expression, return TRUE, otherwise FALSE
+
+
+--*/
+{
+ INT8 *Pin;
+ Pin = *Pindex;
+ LeftTrim (Pbegin, length, Pindex);
+
+ if (ParseTerm (Pbegin, length, Pindex)) {
+ LeftTrim (Pbegin, length, Pindex);
+
+ if (!ParseRightBool (Pbegin, length, Pindex)) {
+ *Pindex = Pin;
+ return FALSE;
+ } else {
+ return TRUE;
+ }
+ } else {
+ *Pindex = Pin;
+ return FALSE;
+ }
+}
+
+BOOLEAN
+ParseDepex (
+ IN INT8 *Pbegin,
+ IN UINT32 length
+ )
+/*++
+
+Routine Description:
+
+ Parse whole dependency expression.
+
+Arguments:
+
+ Pbegin The pointer to the string
+ length length of the string
+
+Returns:
+
+ BOOLEAN If string is a valid dependency expression, return TRUE, otherwise FALSE
+
+
+--*/
+{
+ BOOLEAN Result;
+ INT8 **Pindex;
+ INT8 *temp;
+
+ Result = FALSE;
+ temp = Pbegin;
+ Pindex = &temp;
+
+ LeftTrim (Pbegin, length, Pindex);
+ if (strncmp (*Pindex, OPERATOR_BEFORE, strlen (OPERATOR_BEFORE)) == 0) {
+ (*Pindex) += strlen (OPERATOR_BEFORE);
+ Result = ParseGuid (Pbegin, length, Pindex);
+
+ } else if (strncmp (*Pindex, OPERATOR_AFTER, strlen (OPERATOR_AFTER)) == 0) {
+ (*Pindex) += strlen (OPERATOR_AFTER);
+ Result = ParseGuid (Pbegin, length, Pindex);
+
+ } else if (strncmp (*Pindex, OPERATOR_SOR, strlen (OPERATOR_SOR)) == 0) {
+ (*Pindex) += strlen (OPERATOR_SOR);
+ Result = ParseBool (Pbegin, length, Pindex);
+
+ } else {
+ Result = ParseBool (Pbegin, length, Pindex);
+
+ }
+
+ LeftTrim (Pbegin, length, Pindex);
+ return (BOOLEAN) (Result && (*Pindex) >= (Pbegin + length));
+}
diff --git a/Source/GenDepex/DepexParser.h b/Source/GenDepex/DepexParser.h
new file mode 100644
index 0000000..29e0884
--- /dev/null
+++ b/Source/GenDepex/DepexParser.h
@@ -0,0 +1,26 @@
+/*++
+Copyright (c) 2004, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+ Module Name:
+ GenDepex.h
+
+ Abstract:
+ This file contains the relevant declarations required
+ to generate a binary Dependency File
+
+ Complies with Tiano C Coding Standards Document, version 0.31, 12 Dec 2000.
+
+--*/
+
+// TODO: fix comment to set correct module name: DepexParser.h
+#ifndef _EFI_DEPEX_PARSER_H_
+#define _EFI_DEPEX_PARSER_H_
+#include "GenDepex.h"
+#endif
diff --git a/Source/GenDepex/GenDepex.c b/Source/GenDepex/GenDepex.c
new file mode 100644
index 0000000..3818649
--- /dev/null
+++ b/Source/GenDepex/GenDepex.c
@@ -0,0 +1,919 @@
+/*++
+
+Copyright (c) 2004, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ GenDepex.c
+
+Abstract:
+
+ Generate Dependency Expression ("GenDepex")
+
+ Infix to Postfix Algorithm
+
+ This code has been scrubbed to be free of having any EFI core tree dependencies.
+ It should build in any environment that supports a standard C-library w/ string
+ operations and File I/O services.
+
+ As an example of usage, consider the following:
+
+ The input user file could be something like "Sample.DXS" whose contents are
+
+ #include "Tiano.h"
+
+ DEPENDENCY_START
+ NOT (DISK_IO_PROTOCOL AND SIMPLE_FILE_SYSTEM_PROTOCOL)
+ OR EFI_PXE_BASE_CODE_PROTOCOL
+ DEPENDENCY_END
+
+ This file is then washed through the C-preprocessor, viz.,
+
+ cl /EP Sample.DXS > Sample.TMP1
+
+ This yields the following file "Sample.TMP1" whose contents are
+
+ DEPENDENCY_START
+ NOT ({ 0xce345171, 0xba0b, 0x11d2, 0x8e, 0x4f, 0x0, 0xa0, 0xc9, 0x69, 0x72,
+ 0x3b } AND { 0x964e5b22, 0x6459, 0x11d2, 0x8e, 0x39, 0x0, 0xa0, 0xc9, 0x69,
+ 0x72, 0x3b }) OR { 0x03c4e603, 0xac28, 0x11d3, 0x9a, 0x2d, 0x00, 0x90, 0x27,
+ 0x3f, 0xc1, 0x4d }
+ DEPENDENCY_END
+
+ This file, in turn, will be fed into the utility, viz.,
+
+ GenDepex Sample.TMP1 Sample.TMP2
+
+ With a file that is 55 bytes long:
+
+ 55 bytes for the grammar binary
+ PUSH opcode - 1 byte
+ GUID Instance - 16 bytes
+ PUSH opcode - 1 byte
+ GUID Instance - 16 bytes
+ AND opcode - 1 byte
+ NOT opcode - 1 byte
+ PUSH opcode - 1 byte
+ GUID Instance - 16 bytes
+ OR opcode - 1 byte
+ END opcode - 1 byte
+
+ The file "Sample.TMP2" could be fed via a Section-builder utility
+ (GenSection) that would be used for the creation of a dependency
+ section file (.DPX) which in turn would be used by a generate FFS
+ utility (GenFfsFile) to produce a DXE driver/core (.DXE) or
+ a DXE application (.APP) file.
+
+ Complies with Tiano C Coding Standards Document, version 0.31, 12 Dec 2000.
+
+--*/
+
+#include "GenDepex.h"
+
+#define TOOL_NAME "GenDepex"
+
+extern
+ParseDepex (
+ IN INT8 *Pbegin,
+ IN UINT32 length
+ );
+
+VOID
+PrintGenDepexUtilityInfo (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Displays the standard utility information to SDTOUT.
+
+Arguments:
+
+ None
+
+Returns:
+
+ None
+
+--*/
+{
+ printf (
+ "%s, Tiano Dependency Expression Generation Utility. Version %d.%d.\n",
+ UTILITY_NAME,
+ UTILITY_MAJOR_VERSION,
+ UTILITY_MINOR_VERSION
+ );
+ printf ("Copyright (C) 1996-2002 Intel Corporation. All rights reserved.\n\n");
+}
+
+VOID
+PrintGenDepexUsageInfo (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Displays the utility usage syntax to STDOUT.
+
+Arguments:
+
+ None
+
+Returns:
+
+ None
+
+--*/
+{
+ printf (
+ "Usage: %s -I <INFILE> -O <OUTFILE> [-P <Optional Boundary for padding up>] \n",
+ UTILITY_NAME
+ );
+ printf (" Where:\n");
+ printf (" <INFILE> is the input pre-processed dependency text files name.\n");
+ printf (" <OUTFILE> is the output binary dependency files name.\n");
+ printf (" <Optional Boundary for padding up> is the padding integer value.\n");
+ printf (" This is the boundary to align the output file size to.\n");
+}
+
+DEPENDENCY_OPCODE
+PopOpCode (
+ IN OUT VOID **Stack
+ )
+/*++
+
+Routine Description:
+
+ Pop an element from the Opcode stack.
+
+Arguments:
+
+ Stack Current top of the OpCode stack location
+
+Returns:
+
+ DEPENDENCY_OPCODE OpCode at the top of the OpCode stack.
+ Stack New top of the OpCode stack location
+
+
+--*/
+{
+ DEPENDENCY_OPCODE *OpCodePtr;
+
+ OpCodePtr = *Stack;
+ OpCodePtr--;
+ *Stack = OpCodePtr;
+ return *OpCodePtr;
+}
+
+VOID
+PushOpCode (
+ IN OUT VOID **Stack,
+ IN DEPENDENCY_OPCODE OpCode
+ )
+/*++
+
+Routine Description:
+
+ Push an element onto the Opcode Stack
+
+Arguments:
+
+ Stack Current top of the OpCode stack location
+ OpCode OpCode to push onto the stack
+
+Returns:
+
+ Stack New top of the OpCode stack location
+
+--*/
+{
+ DEPENDENCY_OPCODE *OpCodePtr;
+
+ OpCodePtr = *Stack;
+ *OpCodePtr = OpCode;
+ OpCodePtr++;
+ *Stack = OpCodePtr;
+}
+
+EFI_STATUS
+GenerateDependencyExpression (
+ IN FILE *InFile,
+ IN OUT FILE *OutFile,
+ IN INT8 Padding OPTIONAL
+ )
+/*++
+
+Routine Description:
+
+ This takes the pre-compiled dependency text file and
+ converts it into a binary dependency file.
+
+ The BNF for the dependency expression is as follows
+ (from the DXE 1.0 Draft specification).
+
+ The inputted BNF grammar is thus:
+ <depex> ::= sor <dep> |
+ before GUID <dep> |
+ after GUID <dep> |
+ <bool>
+
+ <dep> ::= <bool> |
+
+ <bool> ::= <bool> and <term> |
+ <bool> or <term> |
+ <term>
+
+ <term> ::= not <factor> |
+ <factor>
+
+ <factor> ::= ( <bool> ) |
+ <term> <term> |
+ GUID |
+ <boolval>
+
+ <boolval> ::= true |
+ false
+
+ The outputed binary grammer is thus:
+ <depex> ::= sor <dep> |
+ before <depinst> <dep> |
+ after <depinst> <dep> |
+ <bool>
+
+ <dep> ::= <bool> |
+
+ <bool> ::= <bool> and <term> |
+ <bool> or <term> | <term>
+
+ <term> ::= not <factor> |
+ <factor>
+
+ <factor> ::= ( <bool> ) |
+ <term> <term> |
+ <boolval> |
+ <depinst> |
+ <termval>
+
+ <boolval> ::= true |
+ false
+
+ <depinst> ::= push GUID
+
+ <termval> ::= end
+
+ BugBug: A correct grammer is parsed correctly. A file that violates the
+ grammer may parse when it should generate an error. There is some
+ error checking and it covers most of the case when it's an include
+ of definition issue. An ill formed expresion may not be detected.
+
+Arguments:
+
+ InFile - Input pre-compiled text file of the dependency expression.
+ This needs to be in ASCII.
+ The file pointer can not be NULL.
+
+ OutFile - Binary dependency file.
+ The file pointer can not be NULL.
+
+ Padding - OPTIONAL integer value to pad the output file to.
+
+
+Returns:
+
+ EFI_SUCCESS The function completed successfully.
+ EFI_INVALID_PARAMETER One of the parameters in the text file was invalid.
+ EFI_OUT_OF_RESOURCES Unable to allocate memory.
+ EFI_ABORTED An misc error occurred.
+
+--*/
+{
+ INT8 *Ptrx;
+ INT8 *Pend;
+ INT8 *EvaluationStack;
+ INT8 *StackPtr;
+ INT8 *Buffer;
+ INT8 Line[LINESIZE];
+ UINTN Index;
+ UINTN OutFileSize;
+ UINTN FileSize;
+ UINTN Results;
+ BOOLEAN NotDone;
+ BOOLEAN Before_Flag;
+ BOOLEAN After_Flag;
+ BOOLEAN Dep_Flag;
+ BOOLEAN SOR_Flag;
+ EFI_GUID Guid;
+ UINTN ArgCountParsed;
+ DEPENDENCY_OPCODE Opcode;
+
+ Before_Flag = FALSE;
+ After_Flag = FALSE;
+ Dep_Flag = FALSE;
+ SOR_Flag = FALSE;
+
+ memset (Line, 0, LINESIZE);
+
+ OutFileSize = 0;
+
+ EvaluationStack = (INT8 *) malloc (EVAL_STACK_SIZE);
+
+ if (EvaluationStack != NULL) {
+ StackPtr = EvaluationStack;
+ } else {
+ printf ("Unable to allocate memory to EvaluationStack - Out of resources\n");
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Results = (UINTN) fseek (InFile, 0, SEEK_END);
+
+ if (Results != 0) {
+ printf ("FSEEK failed - Aborted\n");
+ return EFI_ABORTED;
+ }
+
+ FileSize = ftell (InFile);
+
+ if (FileSize == -1L) {
+ printf ("FTELL failed - Aborted\n");
+ return EFI_ABORTED;
+ }
+
+ Buffer = (INT8 *) malloc (FileSize + BUFFER_SIZE);
+
+ if (Buffer == NULL) {
+ printf ("Unable to allocate memory to Buffer - Out of resources\n");
+ free (EvaluationStack);
+
+ Results = (UINTN) fclose (InFile);
+ if (Results != 0) {
+ printf ("FCLOSE failed\n");
+ }
+
+ Results = (UINTN) fclose (OutFile);
+ if (Results != 0) {
+ printf ("FCLOSE failed\n");
+ }
+
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Results = (UINTN) fseek (InFile, 0, SEEK_SET);
+
+ if (Results != 0) {
+ printf ("FSEEK failed - Aborted\n");
+ return EFI_ABORTED;
+ }
+
+ memset (Buffer, 0, FileSize + BUFFER_SIZE);
+ fread (Buffer, FileSize, 1, InFile);
+
+ Ptrx = Buffer;
+ Pend = Ptrx + FileSize - strlen (DEPENDENCY_END);
+ Index = FileSize;
+
+ NotDone = TRUE;
+ while ((Index--) && NotDone) {
+
+ if (strncmp (Pend, DEPENDENCY_END, strlen (DEPENDENCY_END)) == 0) {
+ NotDone = FALSE;
+ } else {
+ Pend--;
+ }
+ }
+
+ if (NotDone) {
+ printf ("Couldn't find end string %s\n", DEPENDENCY_END);
+
+ Results = (UINTN) fclose (InFile);
+ if (Results != 0) {
+ printf ("FCLOSE failed\n");
+ }
+
+ Results = (UINTN) fclose (OutFile);
+ if (Results != 0) {
+ printf ("FCLOSE failed\n");
+ }
+
+ free (Buffer);
+ free (EvaluationStack);
+
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Index = FileSize;
+
+ NotDone = TRUE;
+ while ((Index--) && NotDone) {
+
+ if (strncmp (Ptrx, DEPENDENCY_START, strlen (DEPENDENCY_START)) == 0) {
+ Ptrx += sizeof (DEPENDENCY_START);
+ NotDone = FALSE;
+ //
+ // BUGBUG -- should Index be decremented by sizeof(DEPENDENCY_START)?
+ //
+ } else {
+ Ptrx++;
+ }
+ }
+
+ if (NotDone) {
+ printf ("Couldn't find start string %s\n", DEPENDENCY_START);
+
+ Results = (UINTN) fclose (InFile);
+ if (Results != 0) {
+ printf ("FCLOSE failed\n");
+ }
+
+ Results = (UINTN) fclose (OutFile);
+ if (Results != 0) {
+ printf ("FCLOSE failed\n");
+ }
+
+ free (Buffer);
+ free (EvaluationStack);
+
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // validate the syntax of expression
+ //
+ if (!ParseDepex (Ptrx, Pend - Ptrx - 1)) {
+ printf ("The syntax of expression is wrong\n");
+
+ Results = (UINTN) fclose (InFile);
+ if (Results != 0) {
+ printf ("FCLOSE failed\n");
+ }
+
+ Results = (UINTN) fclose (OutFile);
+ if (Results != 0) {
+ printf ("FCLOSE failed\n");
+ }
+
+ free (Buffer);
+ free (EvaluationStack);
+
+ return EFI_INVALID_PARAMETER;
+ }
+
+ NotDone = TRUE;
+
+ while ((Index--) && NotDone) {
+
+ if (*Ptrx == ' ') {
+ Ptrx++;
+ } else if (*Ptrx == '\n' || *Ptrx == '\r') {
+ Ptrx++;
+ } else if (strncmp (Ptrx, OPERATOR_SOR, strlen (OPERATOR_SOR)) == 0) {
+ //
+ // Checks for some invalid dependencies
+ //
+ if (Before_Flag) {
+
+ printf ("A BEFORE operator was detected.\n");
+ printf ("There can only be one SOR or one AFTER or one BEFORE operator\n");
+ return EFI_INVALID_PARAMETER;
+
+ } else if (After_Flag) {
+
+ printf ("An AFTER operator was detected.\n");
+ printf ("There can only be one SOR or one AFTER or one BEFORE operator\n");
+ return EFI_INVALID_PARAMETER;
+
+ } else if (SOR_Flag) {
+
+ printf ("Another SOR operator was detected.\n");
+ printf ("There can only be one SOR or one AFTER or one BEFORE operator\n");
+ return EFI_INVALID_PARAMETER;
+
+ } else if (Dep_Flag) {
+
+ printf ("The Schedule On Request - SOR operator must be the first operator following DEPENDENCY_START\n");
+ return EFI_INVALID_PARAMETER;
+
+ } else {
+ //
+ // BUGBUG - This was not in the spec but is in the CORE code
+ // An OPERATOR_SOR has to be first - following the DEPENDENCY_START
+ //
+ fputc (EFI_DEP_SOR, OutFile);
+ OutFileSize++;
+ Ptrx += sizeof (OPERATOR_SOR);
+ SOR_Flag = TRUE;
+
+ }
+ } else if (strncmp (Ptrx, OPERATOR_BEFORE, strlen (OPERATOR_BEFORE)) == 0) {
+ //
+ // Checks for some invalid dependencies
+ //
+ if (Before_Flag) {
+
+ printf ("Another BEFORE operator was detected.\n");
+ printf ("There can only be one SOR or one AFTER or one BEFORE operator\n");
+ return EFI_INVALID_PARAMETER;
+
+ } else if (After_Flag) {
+
+ printf ("An AFTER operator was detected.\n");
+ printf ("There can only be one SOR or one AFTER or one BEFORE operator\n");
+ return EFI_INVALID_PARAMETER;
+
+ } else if (SOR_Flag) {
+
+ printf ("A SOR operator was detected.\n");
+ printf ("There can only be one SOR or one AFTER or one BEFORE operator\n");
+ return EFI_INVALID_PARAMETER;
+
+ } else if (Dep_Flag) {
+
+ printf ("The BEFORE operator must be the first operator following DEPENDENCY_START\n");
+ return EFI_INVALID_PARAMETER;
+
+ } else {
+ fputc (EFI_DEP_BEFORE, OutFile);
+ OutFileSize++;
+ Ptrx += sizeof (OPERATOR_BEFORE);
+ Before_Flag = TRUE;
+ }
+ } else if (strncmp (Ptrx, OPERATOR_AFTER, strlen (OPERATOR_AFTER)) == 0) {
+ //
+ // Checks for some invalid dependencies
+ //
+ if (Before_Flag) {
+
+ printf ("A BEFORE operator was detected.\n");
+ printf ("There can only be one SOR or one AFTER or one BEFORE operator\n");
+ return EFI_INVALID_PARAMETER;
+
+ } else if (After_Flag) {
+
+ printf ("Another AFTER operator was detected.\n");
+ printf ("There can only be one SOR or one AFTER or one BEFORE operator\n");
+ return EFI_INVALID_PARAMETER;
+
+ } else if (SOR_Flag) {
+
+ printf ("A SOR operator was detected.\n");
+ printf ("There can only be one SOR or one AFTER or one BEFORE operator\n");
+ return EFI_INVALID_PARAMETER;
+
+ } else if (Dep_Flag) {
+
+ printf ("The AFTER operator must be the first operator following DEPENDENCY_START\n");
+ return EFI_INVALID_PARAMETER;
+
+ } else {
+ fputc (EFI_DEP_AFTER, OutFile);
+ OutFileSize++;
+ Ptrx += sizeof (OPERATOR_AFTER);
+ Dep_Flag = TRUE;
+ After_Flag = TRUE;
+ }
+ } else if (strncmp (Ptrx, OPERATOR_AND, strlen (OPERATOR_AND)) == 0) {
+ while (StackPtr != EvaluationStack) {
+ Opcode = PopOpCode ((VOID **) &StackPtr);
+ if (Opcode != DXE_DEP_LEFT_PARENTHESIS) {
+ fputc (Opcode, OutFile);
+ OutFileSize++;
+ } else {
+ PushOpCode ((VOID **) &StackPtr, DXE_DEP_LEFT_PARENTHESIS);
+ break;
+ }
+ }
+
+ PushOpCode ((VOID **) &StackPtr, EFI_DEP_AND);
+ Ptrx += sizeof (OPERATOR_AND);
+ Dep_Flag = TRUE;
+
+ } else if (strncmp (Ptrx, OPERATOR_OR, strlen (OPERATOR_OR)) == 0) {
+ while (StackPtr != EvaluationStack) {
+ Opcode = PopOpCode ((VOID **) &StackPtr);
+ if (Opcode != DXE_DEP_LEFT_PARENTHESIS) {
+ fputc (Opcode, OutFile);
+ OutFileSize++;
+ } else {
+ PushOpCode ((VOID **) &StackPtr, DXE_DEP_LEFT_PARENTHESIS);
+ break;
+ }
+ }
+
+ PushOpCode ((VOID **) &StackPtr, EFI_DEP_OR);
+ Ptrx += sizeof (OPERATOR_OR);
+ Dep_Flag = TRUE;
+
+ } else if (strncmp (Ptrx, OPERATOR_NOT, strlen (OPERATOR_NOT)) == 0) {
+ while (StackPtr != EvaluationStack) {
+ Opcode = PopOpCode ((VOID **) &StackPtr);
+ if (Opcode != DXE_DEP_LEFT_PARENTHESIS) {
+ fputc (Opcode, OutFile);
+ OutFileSize++;
+ } else {
+ PushOpCode ((VOID **) &StackPtr, DXE_DEP_LEFT_PARENTHESIS);
+ break;
+ }
+ }
+
+ PushOpCode ((VOID **) &StackPtr, EFI_DEP_NOT);
+ Ptrx += sizeof (OPERATOR_NOT);
+ Dep_Flag = TRUE;
+
+ } else if (*Ptrx == '\t') {
+
+ printf ("File contains tabs. This violates the coding standard\n");
+ return EFI_INVALID_PARAMETER;
+
+ } else if (*Ptrx == '\n') {
+ //
+ // Skip the newline character in the file
+ //
+ Ptrx++;
+
+ } else if (strncmp (Ptrx, OPERATOR_LEFT_PARENTHESIS, strlen (OPERATOR_LEFT_PARENTHESIS)) == 0) {
+ PushOpCode ((VOID **) &StackPtr, DXE_DEP_LEFT_PARENTHESIS);
+
+ Ptrx += strlen (OPERATOR_LEFT_PARENTHESIS);
+ Dep_Flag = TRUE;
+
+ } else if (strncmp (Ptrx, OPERATOR_RIGHT_PARENTHESIS, strlen (OPERATOR_RIGHT_PARENTHESIS)) == 0) {
+ while (StackPtr != EvaluationStack) {
+ Opcode = PopOpCode ((VOID **) &StackPtr);
+ if (Opcode != DXE_DEP_LEFT_PARENTHESIS) {
+ fputc (Opcode, OutFile);
+ OutFileSize++;
+ } else {
+ break;
+ }
+ }
+
+ Ptrx += strlen (OPERATOR_RIGHT_PARENTHESIS);
+ Dep_Flag = TRUE;
+
+ } else if (strncmp (Ptrx, OPERATOR_TRUE, strlen (OPERATOR_TRUE)) == 0) {
+
+ fputc (EFI_DEP_TRUE, OutFile);
+
+ OutFileSize++;
+
+ //
+ // OutFileSize += sizeof (EFI_DEP_TRUE);
+ //
+ Dep_Flag = TRUE;
+
+ Ptrx += strlen (OPERATOR_TRUE);
+
+ } else if (strncmp (Ptrx, OPERATOR_FALSE, strlen (OPERATOR_FALSE)) == 0) {
+
+ fputc (EFI_DEP_FALSE, OutFile);
+
+ OutFileSize++;
+
+ //
+ // OutFileSize += sizeof (EFI_DEP_FALSE);
+ //
+ Dep_Flag = TRUE;
+
+ Ptrx += strlen (OPERATOR_FALSE);
+
+ } else if (*Ptrx == '{') {
+ Ptrx++;
+
+ if (*Ptrx == ' ') {
+ Ptrx++;
+ }
+
+ {
+ int byte_index;
+ // This is an array of UINT32s. sscanf will trash memory
+ // if you try to read into a UINT8 with a %x formatter.
+ UINT32 Guid_Data4[8];
+
+ ArgCountParsed = sscanf (
+ Ptrx,
+ "%x, %x, %x, { %x, %x, %x, %x, %x, %x, %x, %x }",
+ &Guid.Data1,
+ &Guid.Data2,
+ &Guid.Data3,
+ &Guid_Data4[0],
+ &Guid_Data4[1],
+ &Guid_Data4[2],
+ &Guid_Data4[3],
+ &Guid_Data4[4],
+ &Guid_Data4[5],
+ &Guid_Data4[6],
+ &Guid_Data4[7]
+ );
+
+ // Now we can copy the 32 bit ints into the GUID.
+ for (byte_index=0; byte_index<8; byte_index++) {
+ Guid.Data4[byte_index] = (UINT8) Guid_Data4[byte_index];
+ }
+ }
+
+ if (ArgCountParsed != 11) {
+ printf ("We have found an illegal GUID\n");
+ printf ("Fix your depex\n");
+ exit (-1);
+ }
+
+ while (*Ptrx != '}') {
+ Ptrx++;
+ }
+
+ Ptrx++;
+ while (*Ptrx != '}') {
+ Ptrx++;
+ }
+ //
+ // Absorb the closing }
+ //
+ Ptrx++;
+
+ //
+ // Don't provide a PUSH Opcode for the Before and After case
+ //
+ if ((!Before_Flag) && (!After_Flag)) {
+ fputc (EFI_DEP_PUSH, OutFile);
+ OutFileSize++;
+ }
+
+ fwrite (&Guid, sizeof (EFI_GUID), 1, OutFile);
+
+ OutFileSize += sizeof (EFI_GUID);
+ Dep_Flag = TRUE;
+
+ } else if (strncmp (Ptrx, DEPENDENCY_END, strlen (DEPENDENCY_END)) == 0) {
+ NotDone = FALSE;
+ } else {
+ //
+ // Not a valid construct. Null terminate somewhere out there and
+ // print an error message.
+ //
+ *(Ptrx + 20) = 0;
+ printf (TOOL_NAME " ERROR: Unrecognized input at: \"%s\"...\n", Ptrx);
+ return EFI_INVALID_PARAMETER;
+ }
+ }
+ //
+ // DRAIN();
+ //
+ while (StackPtr != EvaluationStack) {
+ fputc (PopOpCode ((VOID **) &StackPtr), OutFile);
+ OutFileSize++;
+ }
+
+ if (OutFileSize == 0) {
+ printf ("Grammer contains no operators or constants\n");
+ return EFI_INVALID_PARAMETER;
+ }
+
+ fputc (EFI_DEP_END, OutFile);
+
+ OutFileSize++;
+
+ //
+ // Checks for invalid padding values
+ //
+ if (Padding < 0) {
+
+ printf ("The inputted padding value was %d\n", Padding);
+ printf ("The optional padding value can not be less than ZERO\n");
+ return EFI_INVALID_PARAMETER;
+
+ } else if (Padding > 0) {
+
+ while ((OutFileSize % Padding) != 0) {
+
+ fputc (' ', OutFile);
+ OutFileSize++;
+ }
+ }
+
+ Results = (UINTN) fclose (InFile);
+ if (Results != 0) {
+ printf ("FCLOSE failed\n");
+ }
+
+ Results = (UINTN) fclose (OutFile);
+ if (Results != 0) {
+ printf ("FCLOSE failed\n");
+ }
+
+ free (Buffer);
+ free (EvaluationStack);
+
+ return EFI_SUCCESS;
+} // End GenerateDependencyExpression function
+
+int
+main (
+ IN UINTN argc,
+ IN CHAR8 *argv[]
+ )
+/*++
+
+Routine Description:
+
+ Parse user entries. Print some rudimentary help
+
+Arguments:
+
+ argc The count of input arguments
+ argv The input arguments string array
+
+Returns:
+
+ EFI_SUCCESS The function completed successfully.
+ EFI_INVALID_PARAMETER One of the input parameters was invalid or one of the parameters in the text file was invalid.
+ EFI_OUT_OF_RESOURCES Unable to allocate memory.
+ EFI_ABORTED Unable to open/create a file or a misc error.
+
+--*/
+// TODO: ] - add argument and description to function comment
+{
+ FILE *OutFile;
+ FILE *InFile;
+ UINT8 Padding;
+ UINTN Index;
+ BOOLEAN Input_Flag;
+ BOOLEAN Output_Flag;
+ BOOLEAN Pad_Flag;
+
+ InFile = NULL;
+ OutFile = NULL;
+ Padding = 0;
+ Input_Flag = FALSE;
+ Output_Flag = FALSE;
+ Pad_Flag = FALSE;
+
+ if (argc < 5) {
+ printf ("Not enough arguments\n");
+ PrintGenDepexUsageInfo ();
+ return EFI_INVALID_PARAMETER;
+ }
+
+ for (Index = 1; Index < argc - 1; Index++) {
+
+ if ((strcmp (argv[Index], "-I") == 0) || (strcmp (argv[Index], "-i") == 0)) {
+
+ if (!Input_Flag) {
+
+ InFile = fopen (argv[Index + 1], "rb");
+ Input_Flag = TRUE;
+
+ } else {
+ printf ("GenDepex only allows one INPUT (-I) argument\n");
+ return EFI_INVALID_PARAMETER;
+ }
+
+ } else if ((strcmp (argv[Index], "-O") == 0) || (strcmp (argv[Index], "-o") == 0)) {
+
+ if (!Output_Flag) {
+
+ OutFile = fopen (argv[Index + 1], "wb");
+ Output_Flag = TRUE;
+
+ } else {
+ printf ("GenDepex only allows one OUTPUT (-O) argument\n");
+ return EFI_INVALID_PARAMETER;
+ }
+
+ } else if ((strcmp (argv[Index], "-P") == 0) || (strcmp (argv[Index], "-p") == 0)) {
+
+ if (!Pad_Flag) {
+
+ Padding = (UINT8) atoi (argv[Index + 1]);
+ Pad_Flag = TRUE;
+
+ } else {
+ printf ("GenDepex only allows one PADDING (-P) argument\n");
+ return EFI_INVALID_PARAMETER;
+ }
+ }
+ }
+
+ PrintGenDepexUtilityInfo ();
+
+ if (InFile == NULL) {
+ printf ("Can not open <INFILE> for reading.\n");
+ PrintGenDepexUsageInfo ();
+ return EFI_ABORTED;
+ }
+
+ if (OutFile == NULL) {
+ printf ("Can not open <OUTFILE> for writting.\n");
+ PrintGenDepexUsageInfo ();
+ return EFI_ABORTED;
+ }
+
+ return GenerateDependencyExpression (InFile, OutFile, Padding);
+}
diff --git a/Source/GenDepex/GenDepex.h b/Source/GenDepex/GenDepex.h
new file mode 100644
index 0000000..b198156
--- /dev/null
+++ b/Source/GenDepex/GenDepex.h
@@ -0,0 +1,71 @@
+/*++
+Copyright (c) 2004, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+ Module Name:
+ GenDepex.h
+
+ Abstract:
+ This file contains the relevant declarations required
+ to generate a binary Dependency File
+
+ Complies with Tiano C Coding Standards Document, version 0.31, 12 Dec 2000.
+
+--*/
+
+#ifndef _EFI_GEN_DEPEX_H
+#define _EFI_GEN_DEPEX_H
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <memory.h>
+#include <string.h>
+#ifndef __GNUC__
+#include <malloc.h>
+#endif
+
+#include <Common/UefiBaseTypes.h>
+#include <Common/Dependency.h>
+
+#define DEPENDENCY_START "DEPENDENCY_START"
+#define OPERATOR_BEFORE "BEFORE"
+#define OPERATOR_AFTER "AFTER"
+#define OPERATOR_AND "AND"
+#define OPERATOR_OR "OR"
+#define OPERATOR_NOT "NOT"
+#define OPERATOR_TRUE "TRUE"
+#define OPERATOR_FALSE "FALSE"
+#define OPERATOR_SOR "SOR"
+#define OPERATOR_END "END"
+#define OPERATOR_LEFT_PARENTHESIS "("
+#define OPERATOR_RIGHT_PARENTHESIS ")"
+#define DEPENDENCY_END "DEPENDENCY_END"
+
+#define DXE_DEP_LEFT_PARENTHESIS 0x0a
+#define DXE_DEP_RIGHT_PARENTHESIS 0x0b
+
+#define LINESIZE 320
+#define SIZE_A_SYMBOL 60
+#define DEPENDENCY_OPCODE UINT8
+#define EVAL_STACK_SIZE 0x1024
+#define BUFFER_SIZE 0x100
+
+//
+// Utility Name
+//
+#define UTILITY_NAME "GenDepex"
+
+//
+// Utility version information
+//
+#define UTILITY_MAJOR_VERSION 0
+#define UTILITY_MINOR_VERSION 5
+
+#endif
diff --git a/Source/GenDepex/build.xml b/Source/GenDepex/build.xml
new file mode 100644
index 0000000..e749431
--- /dev/null
+++ b/Source/GenDepex/build.xml
@@ -0,0 +1,67 @@
+<?xml version="1.0" ?>
+<!--
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+-->
+<project default="GenTool" basedir=".">
+<!--
+ EDK GenDepex Tool
+ Copyright (c) 2006, Intel Corporation
+-->
+ <property name="ToolName" value="GenDepex"/>
+ <property name="FileSet" value="DepexParser.c GenDepex.c GenDepex.h"/>
+
+ <taskdef resource="net/sf/antcontrib/antlib.xml"/>
+
+ <property name="LINK_OUTPUT_TYPE" value="static"/>
+ <property name="BUILD_DIR" value="${PACKAGE_DIR}/${ToolName}/tmp"/>
+
+ <target name="GenTool" depends="init, Tool">
+ <echo message="The EDK Tool: ${ToolName} build has completed!"/>
+ </target>
+
+ <target name="init">
+ <echo message="Building the EDK Tool: ${ToolName}"/>
+ <mkdir dir="${BUILD_DIR}"/>
+ </target>
+
+ <target name="Tool" depends="init">
+ <cc name="${ToolChain}" objdir="${BUILD_DIR}"
+ outfile="${BIN_DIR}/${ToolName}"
+ outtype="executable"
+ debug="true"
+ optimize="speed">
+ <compilerarg value="${ExtraArgus}" if="ExtraArgus" />
+
+ <fileset dir="${basedir}/${ToolName}"
+ includes="${FileSet}" />
+
+ <includepath path="${PACKAGE_DIR}/Include"/>
+ <includepath path="${PACKAGE_DIR}/Include/Ia32"/>
+ <includepath path="${PACKAGE_DIR}/Common"/>
+ </cc>
+ </target>
+
+ <target name="clean">
+ <echo message="Removing Intermediate Files Only"/>
+ <delete>
+ <fileset dir="${BUILD_DIR}" includes="*.obj"/>
+ </delete>
+ </target>
+
+ <target name="cleanall">
+ <echo message="Removing Object Files and the Executable: ${ToolName}${ext_exe}"/>
+ <delete failonerror="false" quiet="true" includeEmptyDirs="true">
+ <fileset dir="${BUILD_DIR}"/>
+ <fileset file="${BIN_DIR}/${ToolName}${ext_exe}"/>
+ <fileset file="${BIN_DIR}/${ToolName}.pdb"/>
+ </delete>
+ </target>
+
+</project>
diff --git a/Source/GenFfsFile/GenFfsFile.c b/Source/GenFfsFile/GenFfsFile.c
new file mode 100644
index 0000000..1eea09f
--- /dev/null
+++ b/Source/GenFfsFile/GenFfsFile.c
@@ -0,0 +1,2646 @@
+/*++
+
+Copyright (c) 2004, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ GenFfsFile.c
+
+Abstract:
+
+ This file contains functions required to generate a Firmware File System
+ file.
+
+--*/
+
+#include <stdio.h>
+#include <ctype.h> // for isalpha()
+//
+// include file for _spawnv
+//
+#ifndef __GNUC__
+#include <process.h>
+#endif
+#include <stdlib.h>
+#include <string.h>
+
+#include <Common/UefiBaseTypes.h>
+#include <Common/FirmwareVolumeImageFormat.h>
+#include <Common/FirmwareFileSystem.h>
+#include <Common/FirmwareVolumeHeader.h>
+#include <Common/FirmwareVolumeImageFormat.h>
+
+#include "ParseInf.h"
+#include "EfiCompress.h"
+#include "EfiCustomizedCompress.h"
+#include "Crc32.h"
+#include "GenFfsFile.h"
+#include "CommonLib.h"
+#include "EfiUtilityMsgs.h"
+#include "SimpleFileParsing.h"
+
+#define UTILITY_NAME "GenFfsFile"
+#define TOOLVERSION "0.32"
+#define MAX_ARRAY_SIZE 100
+
+static
+INT32
+GetNextLine (
+ OUT CHAR8 *Destination,
+ IN FILE *Package,
+ IN OUT UINT32 *LineNumber
+ );
+
+static
+void
+CheckSlash (
+ IN OUT CHAR8 *String,
+ IN FILE *In,
+ IN OUT UINT32 *LineNumber
+ );
+
+static
+INT32
+FindSectionInPackage (
+ IN CHAR8 *BuildDirectory,
+ IN FILE *OverridePackage,
+ IN OUT UINT32 *LineNumber
+ );
+
+static
+STATUS
+ProcessCommandLineArgs (
+ int Argc,
+ char *Argv[]
+ );
+
+static
+void
+PrintUsage (
+ void
+ );
+
+//
+// Keep globals in this structure
+//
+static struct {
+ UINT8 BuildDirectory[_MAX_PATH];
+ UINT8 PrimaryPackagePath[_MAX_PATH];
+ UINT8 OverridePackagePath[_MAX_PATH];
+ BOOLEAN Verbose;
+} mGlobals;
+
+static EFI_GUID mZeroGuid = { 0 };
+
+static
+void
+StripQuotes (
+ IN OUT CHAR8 *String
+ )
+/*++
+
+Routine Description:
+
+ Removes quotes and/or whitespace from around a string
+
+Arguments:
+
+ String - String to remove quotes from
+
+Returns:
+
+ None
+
+--*/
+{
+ UINTN Index;
+ UINTN Index2;
+ UINTN StrLen;
+
+ Index2 = strspn (String, "\" \t\n");
+ StrLen = strlen (String);
+
+ for (Index = Index2; String[Index] != '\"', Index < StrLen; Index++) {
+ String[Index - Index2] = String[Index];
+ }
+
+ String[Index - Index2] = 0;
+}
+
+static
+void
+PrintUsage (
+ void
+ )
+/*++
+
+Routine Description:
+
+ Print Error / Help message.
+
+Arguments:
+
+ void
+
+Returns:
+
+ None
+
+--*/
+{
+ printf ("Usage:\n");
+ printf (UTILITY_NAME " -b \"build directory\" -p1 \"package1.inf\" -p2 \"package2.inf\" -v\n");
+ printf (" -b \"build directory\":\n ");
+ printf (" specifies the full path to the component build directory.\n");
+ printf (" -p1 \"P1_path\":\n");
+ printf (" specifies fully qualified file name to the primary package file.\n");
+ printf (" This file will normally exist in the same directory as the makefile\n");
+ printf (" for the component. Required.\n");
+ printf (" -p2 \"P2_path\":\n");
+ printf (" specifies fully qualified file name to the override package file.\n");
+ printf (" This file will normally exist in the build tip. Optional.\n");
+}
+
+static
+INT32
+TestComment (
+ IN CHAR8 *String,
+ IN FILE *In
+ )
+/*++
+
+Routine Description:
+
+ Tests input string to see if it is a comment, and if so goes to the next line in the file that is not a comment
+
+Arguments:
+
+ String - String to test
+
+ In - Open file to move pointer within
+
+Returns:
+
+ -1 - End of file reached
+ 0 - Not a comment
+ 1 - Comment bypassed
+
+--*/
+{
+ CHAR8 CharBuffer;
+
+ CharBuffer = 0;
+ if ((String[0] == '/') && (String[1] == '/')) {
+ while (CharBuffer != '\n') {
+ fscanf (In, "%c", &CharBuffer);
+ if (feof (In)) {
+ return -1;
+ }
+ }
+ } else {
+ return 0;
+ }
+
+ return 1;
+}
+
+static
+void
+BreakString (
+ IN CONST CHAR8 *Source,
+ OUT CHAR8 *Destination,
+ IN INTN Direction
+ )
+/*++
+
+Routine Description:
+
+ Takes an input string and returns either the part before the =, or the part after the =, depending on direction
+
+Arguments:
+
+ Source - String to break
+
+ Destination - Buffer to place new string in
+
+ Direction - 0 to return all of source string before =
+ 1 to return all of source string after =
+
+Returns:
+
+ None
+
+--*/
+{
+ UINTN Index;
+ UINTN Index2;
+
+ Index = 0;
+ Index2 = 0;
+
+ if (strchr (Source, '=') == NULL) {
+ strcpy (Destination, Source);
+
+ return ;
+ }
+
+ if (Direction == 0) {
+ //
+ // return part of string before =
+ //
+ while (Source[Index] != '=') {
+ Destination[Index] = Source[Index++];
+ }
+
+ Destination[Index] = 0;
+ } else {
+ //
+ // return part of string after =
+ //
+ strcpy (Destination, strchr (Source, '=') + 1);
+ }
+}
+
+static
+INT32
+GetNextLine (
+ OUT CHAR8 *Destination,
+ IN FILE *Package,
+ IN OUT UINT32 *LineNumber
+ )
+/*++
+
+Routine Description:
+
+ Gets the next non-commented line from the file
+
+Arguments:
+
+ Destination - Where to put string
+
+ Package - Package to get string from
+
+ LineNumber - The actual line number.
+
+Returns:
+
+ -1 - End of file reached
+ 0 - Success
+
+--*/
+{
+ CHAR8 String[_MAX_PATH];
+ fscanf (Package, "%s", &String);
+ if (feof (Package)) {
+ return -1;
+ }
+
+ while (TestComment (String, Package) == 1) {
+ fscanf (Package, "%s", &String);
+ if (feof (Package)) {
+ return -1;
+ }
+ }
+
+ strcpy (Destination, String);
+ return 0;
+}
+
+static
+VOID
+CheckSlash (
+ IN OUT CHAR8 *String,
+ IN FILE *In,
+ IN OUT UINT32 *LineNumber
+ )
+/*++
+
+Routine Description:
+
+ Checks to see if string is line continuation character, if so goes to next valid line
+
+Arguments:
+
+ String - String to test
+
+ In - Open file to move pointer within
+
+ LineNumber - The line number.
+
+Returns:
+
+ None
+
+--*/
+{
+ CHAR8 ByteBuffer;
+ ByteBuffer = 0;
+
+ switch (String[0]) {
+
+ case '\\':
+ while (String[0] == '\\') {
+ while (ByteBuffer != '\n') {
+ fscanf (In, "%c", &ByteBuffer);
+ }
+ (*LineNumber)++;
+ if (GetNextLine (String, In, LineNumber) == -1) {
+ return ;
+ }
+ }
+ break;
+
+ case '\n':
+ (*LineNumber)++;
+ while (String[0] == '\n') {
+ if (GetNextLine (String, In, LineNumber) == -1) {
+ return ;
+ }
+ }
+ break;
+
+ default:
+ break;
+
+ }
+
+}
+
+static
+INT32
+FindSectionInPackage (
+ IN CHAR8 *BuildDirectory,
+ IN FILE *OverridePackage,
+ IN OUT UINT32 *LineNumber
+ )
+/*++
+
+Routine Description:
+
+ Finds the matching section within the package
+
+Arguments:
+
+ BuildDirectory - name of section to find
+
+ OverridePackage - Package file to search within
+
+ LineNumber - The line number.
+
+Returns:
+
+ -1 - End of file reached
+ 0 - Success
+
+--*/
+{
+ CHAR8 String[_MAX_PATH];
+ CHAR8 NewString[_MAX_PATH];
+ String[0] = 0;
+
+ while (strcmp (BuildDirectory, String) != 0) {
+ if (GetNextLine (NewString, OverridePackage, LineNumber) != 0) {
+ return -1;
+ }
+
+ if (NewString[0] == '[') {
+ if (NewString[strlen (NewString) - 1] != ']') {
+ //
+ // have to construct string.
+ //
+ strcpy (String, NewString + 1);
+
+ while (1) {
+ fscanf (OverridePackage, "%s", &NewString);
+ if (feof (OverridePackage)) {
+ return -1;
+ }
+
+ if (NewString[0] != ']') {
+ if (strlen (String) != 0) {
+ strcat (String, " ");
+ }
+
+ strcat (String, NewString);
+ if (String[strlen (String) - 1] == ']') {
+ String[strlen (String) - 1] = 0;
+ break;
+ }
+ } else {
+ break;
+ }
+ }
+ } else {
+ NewString[strlen (NewString) - 1] = 0;
+ strcpy (String, NewString + 1);
+ }
+ }
+ }
+
+ return 0;
+}
+
+static
+EFI_STATUS
+GenSimpleGuidSection (
+ IN OUT UINT8 *FileBuffer,
+ IN OUT UINT32 *BufferSize,
+ IN UINT32 DataSize,
+ IN EFI_GUID SignGuid,
+ IN UINT16 GuidedSectionAttributes
+ )
+/*++
+
+Routine Description:
+
+ add GUIDed section header for the data buffer.
+ data stays in same location (overwrites source data).
+
+Arguments:
+
+ FileBuffer - Buffer containing data to sign
+
+ BufferSize - On input, the size of FileBuffer. On output, the size of
+ actual section data (including added section header).
+
+ DataSize - Length of data to Sign
+
+ SignGuid - Guid to be add.
+
+ GuidedSectionAttributes - The section attribute.
+
+Returns:
+
+ EFI_SUCCESS - Successful
+ EFI_OUT_OF_RESOURCES - Not enough resource.
+
+--*/
+{
+ UINT32 TotalSize;
+
+ EFI_GUID_DEFINED_SECTION GuidSectionHeader;
+ UINT8 *SwapBuffer;
+
+ SwapBuffer = NULL;
+
+ if (DataSize == 0) {
+ *BufferSize = 0;
+
+ return EFI_SUCCESS;
+ }
+
+ TotalSize = DataSize + sizeof (EFI_GUID_DEFINED_SECTION);
+ GuidSectionHeader.CommonHeader.Type = EFI_SECTION_GUID_DEFINED;
+ GuidSectionHeader.CommonHeader.Size[0] = (UINT8) (TotalSize & 0xff);
+ GuidSectionHeader.CommonHeader.Size[1] = (UINT8) ((TotalSize & 0xff00) >> 8);
+ GuidSectionHeader.CommonHeader.Size[2] = (UINT8) ((TotalSize & 0xff0000) >> 16);
+ memcpy (&(GuidSectionHeader.SectionDefinitionGuid), &SignGuid, sizeof (EFI_GUID));
+ GuidSectionHeader.Attributes = GuidedSectionAttributes;
+ GuidSectionHeader.DataOffset = sizeof (EFI_GUID_DEFINED_SECTION);
+
+ SwapBuffer = (UINT8 *) malloc (DataSize);
+ if (SwapBuffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ memcpy (SwapBuffer, FileBuffer, DataSize);
+ memcpy (FileBuffer, &GuidSectionHeader, sizeof (EFI_GUID_DEFINED_SECTION));
+ memcpy (FileBuffer + sizeof (EFI_GUID_DEFINED_SECTION), SwapBuffer, DataSize);
+
+ //
+ // Make sure section ends on a DWORD boundary
+ //
+ while ((TotalSize & 0x03) != 0) {
+ FileBuffer[TotalSize] = 0;
+ TotalSize++;
+ }
+
+ *BufferSize = TotalSize;
+
+ if (SwapBuffer != NULL) {
+ free (SwapBuffer);
+ }
+
+ return EFI_SUCCESS;
+}
+
+static
+EFI_STATUS
+CompressSection (
+ UINT8 *FileBuffer,
+ UINT32 *BufferSize,
+ UINT32 DataSize,
+ CHAR8 *Type
+ )
+/*++
+
+Routine Description:
+
+ Compress the data and add section header for the compressed data.
+ Compressed data (with section header) stays in same location as the source
+ (overwrites source data).
+
+Arguments:
+
+ FileBuffer - Buffer containing data to Compress
+
+ BufferSize - On input, the size of FileBuffer. On output, the size of
+ actual compressed data (including added section header).
+ When buffer is too small, this value indicates the size needed.
+
+ DataSize - The size of data to compress
+
+ Type - The compression type (not used currently).
+ Assume EFI_HEAVY_COMPRESSION.
+
+Returns:
+
+ EFI_BUFFER_TOO_SMALL - Buffer size is too small.
+ EFI_UNSUPPORTED - Compress type can not be supported.
+ EFI_SUCCESS - Successful
+ EFI_OUT_OF_RESOURCES - Not enough resource.
+
+--*/
+{
+ EFI_STATUS Status;
+ UINT8 *CompData;
+ UINT32 CompSize;
+ UINT32 TotalSize;
+ EFI_COMPRESSION_SECTION CompressionSet;
+ UINT8 CompressionType;
+ COMPRESS_FUNCTION CompressFunction;
+
+ Status = EFI_SUCCESS;
+ CompData = NULL;
+ CompSize = 0;
+ TotalSize = 0;
+ CompressFunction = NULL;
+
+ //
+ // Get the compress type
+ //
+ if (strcmpi (Type, "Dummy") == 0) {
+ //
+ // Added "Dummy" to keep backward compatibility.
+ //
+ CompressionType = EFI_STANDARD_COMPRESSION;
+ CompressFunction = (COMPRESS_FUNCTION) Compress;
+
+ } else if (strcmpi (Type, "LZH") == 0) {
+ //
+ // EFI stardard compression (LZH)
+ //
+ CompressionType = EFI_STANDARD_COMPRESSION;
+ CompressFunction = (COMPRESS_FUNCTION) Compress;
+
+ } else {
+ //
+ // Customized compression
+ //
+ Status = SetCustomizedCompressionType (Type);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ CompressionType = EFI_CUSTOMIZED_COMPRESSION;
+ CompressFunction = (COMPRESS_FUNCTION) CustomizedCompress;
+ }
+ //
+ // Compress the raw data
+ //
+ Status = CompressFunction (FileBuffer, DataSize, CompData, &CompSize);
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+ CompData = malloc (CompSize);
+ if (!CompData) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Status = CompressFunction (FileBuffer, DataSize, CompData, &CompSize);
+ }
+
+ if (EFI_ERROR (Status)) {
+ if (CompData != NULL) {
+ free (CompData);
+ }
+
+ return Status;
+ }
+
+ TotalSize = CompSize + sizeof (EFI_COMPRESSION_SECTION);
+
+ //
+ // Buffer too small?
+ //
+ if (TotalSize > *BufferSize) {
+ *BufferSize = TotalSize;
+ if (CompData != NULL) {
+ free (CompData);
+ }
+
+ return EFI_BUFFER_TOO_SMALL;
+ }
+ //
+ // Add the section header for the compressed data
+ //
+ CompressionSet.CommonHeader.Type = EFI_SECTION_COMPRESSION;
+ CompressionSet.CommonHeader.Size[0] = (UINT8) (TotalSize & 0xff);
+ CompressionSet.CommonHeader.Size[1] = (UINT8) ((TotalSize & 0xff00) >> 8);
+ CompressionSet.CommonHeader.Size[2] = (UINT8) ((TotalSize & 0xff0000) >> 16);
+ CompressionSet.CompressionType = CompressionType;
+ CompressionSet.UncompressedLength = DataSize;
+
+ //
+ // Copy header and data to the buffer
+ //
+ memcpy (FileBuffer, &CompressionSet, sizeof (EFI_COMPRESSION_SECTION));
+ memcpy (FileBuffer + sizeof (CompressionSet), CompData, CompSize);
+
+ //
+ // Make sure section ends on a DWORD boundary
+ //
+ while ((TotalSize & 0x03) != 0) {
+ FileBuffer[TotalSize] = 0;
+ TotalSize++;
+ }
+
+ *BufferSize = TotalSize;
+
+ if (CompData != NULL) {
+ free (CompData);
+ }
+
+ return EFI_SUCCESS;
+}
+
+static
+void
+StripParens (
+ IN OUT CHAR8 *String
+ )
+/*++
+
+Routine Description:
+
+ Removes Parenthesis from around a string
+
+Arguments:
+
+ String - String to remove parens from
+
+Returns:
+
+ None
+
+--*/
+{
+ INT32 Index;
+
+ if (String[0] != '(') {
+ return ;
+ }
+
+ for (Index = 1; String[Index] != ')'; Index++) {
+ String[Index - 1] = String[Index];
+ if (String[Index] == 0) {
+ return ;
+ }
+ }
+
+ String[Index - 1] = 0;
+
+ return ;
+}
+
+static
+void
+StripEqualMark (
+ IN OUT CHAR8 *String
+ )
+/*++
+
+Routine Description:
+
+ Removes Equal Mark from around a string
+
+Arguments:
+
+ String - String to remove equal mark from
+
+Returns:
+
+ None
+
+--*/
+{
+ INT32 Index;
+
+ if (String[0] != '=' && String[strlen (String) - 1] != '=') {
+ return ;
+ }
+
+ if (String[0] == '=') {
+
+ for (Index = 1; String[Index] != 0; Index++) {
+ String[Index - 1] = String[Index];
+ }
+
+ String[Index - 1] = 0;
+ }
+
+ if (String[strlen (String) - 1] == '=') {
+ String[strlen (String) - 1] = 0;
+ }
+
+ return ;
+}
+
+static
+INT32
+ProcessEnvironmentVariable (
+ IN CHAR8 *Buffer,
+ OUT CHAR8 *NewBuffer
+ )
+/*++
+
+Routine Description:
+
+ Converts environment variables to values
+
+Arguments:
+
+ Buffer - Buffer containing Environment Variable String
+
+ NewBuffer - Buffer containing value of environment variable
+
+
+Returns:
+
+ Number of characters from Buffer used
+
+--*/
+{
+ INT32 Index;
+ INT32 Index2;
+ CHAR8 VariableBuffer[_MAX_PATH];
+
+ Index = 2;
+ Index2 = 0;
+
+ while (Buffer[Index] != ')') {
+ VariableBuffer[Index - 2] = Buffer[Index++];
+ }
+
+ VariableBuffer[Index - 2] = 0;
+ Index++;
+
+ if (getenv (VariableBuffer) != NULL) {
+ strcpy (NewBuffer, getenv (VariableBuffer));
+ } else {
+ printf ("Environment variable %s not found!\n", VariableBuffer);
+ }
+
+ return Index;
+}
+
+static
+void
+SplitAttributesField (
+ IN CHAR8 *Buffer,
+ IN CHAR8 *AttributesArray[],
+ IN OUT UINT32 *NumberOfAttributes
+ )
+/*
+ NumberOfAttributes: on input, it specifies the current number of attributes
+ stored in AttributeArray.
+ on output, it is updated to the latest number of attributes
+ stored in AttributesArray.
+*/
+{
+ UINT32 Index;
+ UINT32 Index2;
+ UINT32 z;
+ CHAR8 *CharBuffer;
+
+ CharBuffer = NULL;
+ CharBuffer = (CHAR8 *) malloc (_MAX_PATH);
+ ZeroMem (CharBuffer, _MAX_PATH);
+
+ for (Index = 0, z = 0, Index2 = 0; Index < strlen (Buffer); Index++) {
+
+ if (Buffer[Index] != '|') {
+ CharBuffer[z] = Buffer[Index];
+ z++;
+ } else {
+
+ CharBuffer[z] = 0;
+ AttributesArray[*NumberOfAttributes + Index2] = CharBuffer;
+ Index2++;
+
+ //
+ // allocate new char buffer for the next attributes string
+ //
+ CharBuffer = (CHAR8 *) malloc (_MAX_PATH);
+ ZeroMem (CharBuffer, _MAX_PATH);
+ z = 0;
+ }
+ }
+
+ CharBuffer[z] = 0;
+ //
+ // record the last attributes string in the Buffer
+ //
+ AttributesArray[*NumberOfAttributes + Index2] = CharBuffer;
+ Index2++;
+
+ *NumberOfAttributes += Index2;
+
+ return ;
+}
+
+static
+INT32
+GetToolArguments (
+ CHAR8 *ToolArgumentsArray[],
+ FILE *Package,
+ CHAR8 **PtrInputFileName,
+ CHAR8 **PtrOutputFileName,
+ EFI_GUID *Guid,
+ UINT16 *GuidedSectionAttributes
+ )
+{
+ CHAR8 Buffer[_MAX_PATH];
+ BOOLEAN ArgumentsFlag;
+ BOOLEAN InputFlag;
+ BOOLEAN OutputFlag;
+ BOOLEAN GuidFlag;
+ BOOLEAN AttributesFlag;
+ UINT32 argc;
+ UINT32 Index2;
+ UINT32 z;
+ CHAR8 *CharBuffer;
+ INT32 Index;
+ INT32 ReturnValue;
+ EFI_STATUS Status;
+
+ CHAR8 *AttributesArray[MAX_ARRAY_SIZE];
+ UINT32 NumberOfAttributes;
+ CHAR8 *InputFileName;
+ CHAR8 *OutputFileName;
+ UINT32 LineNumber;
+ Buffer[_MAX_PATH];
+
+ ArgumentsFlag = FALSE;
+ InputFlag = FALSE;
+ OutputFlag = FALSE;
+ GuidFlag = FALSE;
+ AttributesFlag = FALSE;
+ //
+ // Start at 1, since ToolArgumentsArray[0]
+ // is the program name.
+ //
+ argc = 1;
+ Index2 = 0;
+
+ z = 0;
+ ReturnValue = 0;
+ NumberOfAttributes = 0;
+ InputFileName = NULL;
+ OutputFileName = NULL;
+
+ ZeroMem (Buffer, _MAX_PATH);
+ ZeroMem (AttributesArray, sizeof (CHAR8 *) * MAX_ARRAY_SIZE);
+ LineNumber = 0;
+ while (Buffer[0] != ')') {
+
+ if (GetNextLine (Buffer, Package, &LineNumber) != -1) {
+ CheckSlash (Buffer, Package, &LineNumber);
+ StripEqualMark (Buffer);
+ } else {
+ Error (NULL, 0, 0, "failed to get next line from package file", NULL);
+ return -1;
+ }
+
+ if (Buffer[0] == ')') {
+ break;
+ } else if (strcmpi (Buffer, "ARGS") == 0) {
+
+ ArgumentsFlag = TRUE;
+ AttributesFlag = FALSE;
+ continue;
+
+ } else if (strcmpi (Buffer, "INPUT") == 0) {
+
+ InputFlag = TRUE;
+ ArgumentsFlag = FALSE;
+ AttributesFlag = FALSE;
+ continue;
+
+ } else if (strcmpi (Buffer, "OUTPUT") == 0) {
+
+ OutputFlag = TRUE;
+ ArgumentsFlag = FALSE;
+ AttributesFlag = FALSE;
+ continue;
+
+ } else if (strcmpi (Buffer, "GUID") == 0) {
+
+ GuidFlag = TRUE;
+ ArgumentsFlag = FALSE;
+ AttributesFlag = FALSE;
+ //
+ // fetch the GUID for the section
+ //
+ continue;
+
+ } else if (strcmpi (Buffer, "ATTRIBUTES") == 0) {
+
+ AttributesFlag = TRUE;
+ ArgumentsFlag = FALSE;
+ //
+ // fetch the GUIDed Section's Attributes
+ //
+ continue;
+
+ } else if (strcmpi (Buffer, "") == 0) {
+ continue;
+ }
+ //
+ // get all command arguments into ToolArgumentsArray
+ //
+ if (ArgumentsFlag) {
+
+ StripEqualMark (Buffer);
+
+ CharBuffer = (CHAR8 *) malloc (_MAX_PATH);
+ if (CharBuffer == NULL) {
+ goto ErrorExit;
+ }
+
+ ZeroMem (CharBuffer, sizeof (_MAX_PATH));
+
+ ToolArgumentsArray[argc] = CharBuffer;
+
+ if (Buffer[0] == '$') {
+ Index = ProcessEnvironmentVariable (&Buffer[0], ToolArgumentsArray[argc]);
+ //
+ // if there is string after the environment variable, cat it.
+ //
+ if ((UINT32) Index < strlen (Buffer)) {
+ strcat (ToolArgumentsArray[argc], &Buffer[Index]);
+ }
+ } else {
+ strcpy (ToolArgumentsArray[argc], Buffer);
+ }
+
+ argc += 1;
+ ToolArgumentsArray[argc] = NULL;
+ continue;
+ }
+
+ if (InputFlag) {
+
+ StripEqualMark (Buffer);
+
+ InputFileName = (CHAR8 *) malloc (_MAX_PATH);
+ if (InputFileName == NULL) {
+ goto ErrorExit;
+ }
+
+ ZeroMem (InputFileName, sizeof (_MAX_PATH));
+
+ if (Buffer[0] == '$') {
+ Index = ProcessEnvironmentVariable (&Buffer[0], InputFileName);
+ //
+ // if there is string after the environment variable, cat it.
+ //
+ if ((UINT32) Index < strlen (Buffer)) {
+ strcat (InputFileName, &Buffer[Index]);
+ }
+ } else {
+ strcpy (InputFileName, Buffer);
+ }
+
+ InputFlag = FALSE;
+ continue;
+ }
+
+ if (OutputFlag) {
+
+ StripEqualMark (Buffer);
+
+ OutputFileName = (CHAR8 *) malloc (_MAX_PATH);
+ if (OutputFileName == NULL) {
+ goto ErrorExit;
+ }
+
+ ZeroMem (OutputFileName, sizeof (_MAX_PATH));
+
+ if (Buffer[0] == '$') {
+ Index = ProcessEnvironmentVariable (&Buffer[0], OutputFileName);
+ //
+ // if there is string after the environment variable, cat it.
+ //
+ if ((UINT32) Index < strlen (Buffer)) {
+ strcat (OutputFileName, &Buffer[Index]);
+ }
+ } else {
+ strcpy (OutputFileName, Buffer);
+ }
+
+ OutputFlag = FALSE;
+ continue;
+ }
+
+ if (GuidFlag) {
+
+ StripEqualMark (Buffer);
+
+ Status = StringToGuid (Buffer, Guid);
+ if (EFI_ERROR (Status)) {
+ ReturnValue = -1;
+ goto ErrorExit;
+ }
+
+ GuidFlag = FALSE;
+ }
+
+ if (AttributesFlag) {
+
+ StripEqualMark (Buffer);
+
+ //
+ // there might be no space between each attribute in the statement,
+ // split them aside and return each attribute string
+ // in the AttributesArray
+ //
+ SplitAttributesField (Buffer, AttributesArray, &NumberOfAttributes);
+ }
+ }
+ //
+ // ReplaceVariableInBuffer (ToolArgumentsArray,&i,"INPUT",InputVariable,j);
+ // ReplaceVariableInBuffer (ToolArgumentsArray,&i,"OUTPUT",&TargetFileName,1);
+ //
+ for (z = 0; z < NumberOfAttributes; z++) {
+ if (strcmpi (AttributesArray[z], "PROCESSING_REQUIRED") == 0) {
+ *GuidedSectionAttributes |= EFI_GUIDED_SECTION_PROCESSING_REQUIRED;
+ } else if (strcmpi (AttributesArray[z], "AUTH_STATUS_VALID") == 0) {
+ *GuidedSectionAttributes |= EFI_GUIDED_SECTION_AUTH_STATUS_VALID;
+ }
+ }
+
+ErrorExit:
+
+ for (Index2 = 0; Index2 < MAX_ARRAY_SIZE; Index2++) {
+ if (AttributesArray[Index2] == NULL) {
+ break;
+ }
+
+ free (AttributesArray[Index2]);
+ }
+
+ *PtrInputFileName = InputFileName;
+ *PtrOutputFileName = OutputFileName;
+
+ return ReturnValue;
+}
+
+static
+INT32
+ProcessScript (
+ IN OUT UINT8 *FileBuffer,
+ IN FILE *Package,
+ IN CHAR8 *BuildDirectory,
+ IN BOOLEAN ForceUncompress
+ )
+/*++
+
+Routine Description:
+
+ Signs the section, data stays in same location
+
+Arguments:
+
+ FileBuffer - Data Buffer
+
+ Package - Points to curly brace in Image Script
+
+ BuildDirectory - Name of the source directory parameter
+
+ ForceUncompress - Whether to force uncompress.
+
+Returns:
+
+ Number of bytes added to file buffer
+ -1 on error
+
+--*/
+{
+ EFI_STATUS Status;
+ UINT32 Size;
+ CHAR8 Buffer[_MAX_PATH];
+ CHAR8 Type[_MAX_PATH];
+ CHAR8 FileName[_MAX_PATH];
+ CHAR8 NewBuffer[_MAX_PATH];
+ INT32 Index3;
+ INT32 Index2;
+ UINT32 ReturnValue;
+ UINT8 ByteBuffer;
+ FILE *InFile;
+ UINT32 SourceDataSize;
+ CHAR8 *ToolArgumentsArray[MAX_ARRAY_SIZE];
+ CHAR8 *OutputFileName;
+ CHAR8 *InputFileName;
+ CHAR8 ToolName[_MAX_PATH];
+ FILE *OutputFile;
+ FILE *InputFile;
+ UINT8 Temp;
+ int returnint;
+ INT32 Index;
+ UINT32 LineNumber;
+ BOOLEAN IsError;
+ EFI_GUID SignGuid;
+ UINT16 GuidedSectionAttributes;
+ UINT8 *TargetFileBuffer;
+
+ OutputFileName = NULL;
+ InputFileName = NULL;
+ OutputFile = NULL;
+ InputFile = NULL;
+ IsError = FALSE;
+ GuidedSectionAttributes = 0;
+ TargetFileBuffer = NULL;
+
+ Size = 0;
+ LineNumber = 0;
+ Buffer[0] = 0;
+ for (Index3 = 0; Index3 < MAX_ARRAY_SIZE; ++Index3) {
+ ToolArgumentsArray[Index3] = NULL;
+ }
+
+ while (Buffer[0] != '}') {
+ if (GetNextLine (Buffer, Package, &LineNumber) != -1) {
+ CheckSlash (Buffer, Package, &LineNumber);
+ } else {
+ printf ("ERROR in IMAGE SCRIPT!\n");
+ IsError = TRUE;
+ goto Done;
+ }
+
+ if (strcmpi (Buffer, "Compress") == 0) {
+ //
+ // Handle compress
+ //
+ //
+ // read compression type
+ //
+ if (GetNextLine (Buffer, Package, &LineNumber) != -1) {
+ CheckSlash (Buffer, Package, &LineNumber);
+ }
+
+ StripParens (Buffer);
+ if (Buffer[0] == '$') {
+ ProcessEnvironmentVariable (&Buffer[0], Type);
+ } else {
+ strcpy (Type, Buffer);
+ }
+ //
+ // build buffer
+ //
+ while (Buffer[0] != '{') {
+ if (GetNextLine (Buffer, Package, &LineNumber) != -1) {
+ CheckSlash (Buffer, Package, &LineNumber);
+ }
+ }
+
+ ReturnValue = ProcessScript (&FileBuffer[Size], Package, BuildDirectory, ForceUncompress);
+ if (ReturnValue == -1) {
+ IsError = TRUE;
+ goto Done;
+ }
+ //
+ // Call compress routine on buffer.
+ // Occasionally, compressed data + section header would
+ // be largere than the source and EFI_BUFFER_TOO_SMALL is
+ // returned from CompressSection()
+ //
+ SourceDataSize = ReturnValue;
+
+ if (!ForceUncompress) {
+
+ Status = CompressSection (
+ &FileBuffer[Size],
+ &ReturnValue,
+ SourceDataSize,
+ Type
+ );
+
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+ Status = CompressSection (
+ &FileBuffer[Size],
+ &ReturnValue,
+ SourceDataSize,
+ Type
+ );
+ }
+
+ if (EFI_ERROR (Status)) {
+ IsError = TRUE;
+ goto Done;
+ }
+ }
+
+ Size += ReturnValue;
+
+ } else if (strcmpi (Buffer, "Tool") == 0) {
+
+ ZeroMem (ToolName, _MAX_PATH);
+ ZeroMem (ToolArgumentsArray, sizeof (CHAR8 *) * MAX_ARRAY_SIZE);
+ ZeroMem (&SignGuid, sizeof (EFI_GUID));
+
+ //
+ // handle signing Tool
+ //
+ while (Buffer[0] != '(') {
+ if (GetNextLine (Buffer, Package, &LineNumber) != -1) {
+ CheckSlash (Buffer, Package, &LineNumber);
+ }
+ }
+
+ if (strcmpi (Buffer, "(") == 0) {
+ if (GetNextLine (Buffer, Package, &LineNumber) != -1) {
+ CheckSlash (Buffer, Package, &LineNumber);
+ }
+ }
+
+ StripParens (Buffer);
+
+ if (Buffer[0] == '$') {
+ Index = ProcessEnvironmentVariable (&Buffer[0], ToolName);
+ //
+ // if there is string after the environment variable, cat it.
+ //
+ if ((UINT32) Index < strlen (Buffer)) {
+ strcat (ToolName, &Buffer[Index]);
+ }
+ } else {
+ strcpy (ToolName, Buffer);
+ }
+
+ ToolArgumentsArray[0] = ToolName;
+
+ //
+ // read ARGS
+ //
+ if (GetToolArguments (
+ ToolArgumentsArray,
+ Package,
+ &InputFileName,
+ &OutputFileName,
+ &SignGuid,
+ &GuidedSectionAttributes
+ ) == -1) {
+ IsError = TRUE;
+ goto Done;
+ }
+ //
+ // if the tool need input file,
+ // dump the file buffer to the specified input file.
+ //
+ if (InputFileName != NULL) {
+ InputFile = fopen (InputFileName, "wb");
+ if (InputFile == NULL) {
+ Error (NULL, 0, 0, InputFileName, "failed to open output file for writing");
+ IsError = TRUE;
+ goto Done;
+ }
+
+ fwrite (FileBuffer, sizeof (UINT8), Size, InputFile);
+ fclose (InputFile);
+ InputFile = NULL;
+ free (InputFileName);
+ InputFileName = NULL;
+ }
+ //
+ // dispatch signing tool
+ //
+#ifdef __GNUC__
+ {
+ char CommandLine[1000];
+ sprintf(CommandLine, "%s %s", ToolName, ToolArgumentsArray);
+ returnint = system(CommandLine);
+ }
+#else
+ returnint = _spawnv (_P_WAIT, ToolName, ToolArgumentsArray);
+#endif
+ if (returnint != 0) {
+ Error (NULL, 0, 0, ToolName, "external tool failed");
+ IsError = TRUE;
+ goto Done;
+ }
+ //
+ // if the tool has output file,
+ // dump the output file to the file buffer
+ //
+ if (OutputFileName != NULL) {
+
+ OutputFile = fopen (OutputFileName, "rb");
+ if (OutputFile == NULL) {
+ Error (NULL, 0, 0, OutputFileName, "failed to open output file for writing");
+ IsError = TRUE;
+ goto Done;
+ }
+
+ TargetFileBuffer = &FileBuffer[Size];
+ SourceDataSize = Size;
+
+ fread (&Temp, sizeof (UINT8), 1, OutputFile);
+ while (!feof (OutputFile)) {
+ FileBuffer[Size++] = Temp;
+ fread (&Temp, sizeof (UINT8), 1, OutputFile);
+ }
+
+ while ((Size & 0x03) != 0) {
+ FileBuffer[Size] = 0;
+ Size++;
+ }
+
+ SourceDataSize = Size - SourceDataSize;
+
+ fclose (OutputFile);
+ OutputFile = NULL;
+ free (OutputFileName);
+ OutputFileName = NULL;
+
+ if (CompareGuid (&SignGuid, &mZeroGuid) != 0) {
+ ReturnValue = SourceDataSize;
+ Status = GenSimpleGuidSection (
+ TargetFileBuffer,
+ &ReturnValue,
+ SourceDataSize,
+ SignGuid,
+ GuidedSectionAttributes
+ );
+ if (EFI_ERROR (Status)) {
+ IsError = TRUE;
+ goto Done;
+ }
+
+ Size = ReturnValue;
+ }
+ }
+
+ } else if (Buffer[0] != '}') {
+ //
+ // if we are here, we should see either a file name,
+ // or a }.
+ //
+ Index3 = 0;
+ FileName[0] = 0;
+ //
+ // Prepend the build directory to the file name if the
+ // file name does not already contain a full path.
+ //
+ if (!isalpha (Buffer[0]) || (Buffer[1] != ':')) {
+ sprintf (FileName, "%s\\", BuildDirectory);
+ }
+
+ while (Buffer[Index3] != '\n') {
+ if (Buffer[Index3] == '$') {
+ Index3 += ProcessEnvironmentVariable (&Buffer[Index3], NewBuffer);
+ strcat (FileName, NewBuffer);
+ }
+
+ if (Buffer[Index3] == 0) {
+ break;
+ } else {
+ Index2 = strlen (FileName);
+ FileName[Index2++] = Buffer[Index3++];
+ FileName[Index2] = 0;
+ }
+ }
+
+ InFile = fopen (FileName, "rb");
+ if (InFile == NULL) {
+ Error (NULL, 0, 0, FileName, "failed to open file for reading");
+ IsError = TRUE;
+ goto Done;
+ }
+
+ fread (&ByteBuffer, sizeof (UINT8), 1, InFile);
+ while (!feof (InFile)) {
+ FileBuffer[Size++] = ByteBuffer;
+ fread (&ByteBuffer, sizeof (UINT8), 1, InFile);
+ }
+
+ fclose (InFile);
+ InFile = NULL;
+
+ //
+ // Make sure section ends on a DWORD boundary
+ //
+ while ((Size & 0x03) != 0) {
+ FileBuffer[Size] = 0;
+ Size++;
+ }
+
+ }
+ }
+
+Done:
+ for (Index3 = 1; Index3 < MAX_ARRAY_SIZE; Index3++) {
+ if (ToolArgumentsArray[Index3] == NULL) {
+ break;
+ }
+
+ free (ToolArgumentsArray[Index3]);
+ }
+
+ if (IsError) {
+ return -1;
+ }
+
+ return Size;
+
+}
+
+static
+UINT8
+StringToType (
+ IN CHAR8 *String
+ )
+/*++
+
+Routine Description:
+
+ Converts File Type String to value. EFI_FV_FILETYPE_ALL indicates that an
+ unrecognized file type was specified.
+
+Arguments:
+
+ String - File type string
+
+Returns:
+
+ File Type Value
+
+--*/
+{
+ if (strcmpi (String, "EFI_FV_FILETYPE_RAW") == 0) {
+ return EFI_FV_FILETYPE_RAW;
+ }
+
+ if (strcmpi (String, "EFI_FV_FILETYPE_FREEFORM") == 0) {
+ return EFI_FV_FILETYPE_FREEFORM;
+ }
+
+ if (strcmpi (String, "EFI_FV_FILETYPE_SECURITY_CORE") == 0) {
+ return EFI_FV_FILETYPE_SECURITY_CORE;
+ }
+
+ if (strcmpi (String, "EFI_FV_FILETYPE_PEI_CORE") == 0) {
+ return EFI_FV_FILETYPE_PEI_CORE;
+ }
+
+ if (strcmpi (String, "EFI_FV_FILETYPE_DXE_CORE") == 0) {
+ return EFI_FV_FILETYPE_DXE_CORE;
+ }
+
+ if (strcmpi (String, "EFI_FV_FILETYPE_PEIM") == 0) {
+ return EFI_FV_FILETYPE_PEIM;
+ }
+
+ if (strcmpi (String, "EFI_FV_FILETYPE_DRIVER") == 0) {
+ return EFI_FV_FILETYPE_DRIVER;
+ }
+
+ if (strcmpi (String, "EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER") == 0) {
+ return EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER;
+ }
+
+ if (strcmpi (String, "EFI_FV_FILETYPE_APPLICATION") == 0) {
+ return EFI_FV_FILETYPE_APPLICATION;
+ }
+
+ if (strcmpi (String, "EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE") == 0) {
+ return EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE;
+ }
+
+ return EFI_FV_FILETYPE_ALL;
+}
+
+static
+UINT32
+AdjustFileSize (
+ IN UINT8 *FileBuffer,
+ IN UINT32 FileSize
+ )
+/*++
+
+Routine Description:
+ Adjusts file size to insure sectioned file is exactly the right length such
+ that it ends on exactly the last byte of the last section. ProcessScript()
+ may have padded beyond the end of the last section out to a 4 byte boundary.
+ This padding is stripped.
+
+Arguments:
+ FileBuffer - Data Buffer - contains a section stream
+ FileSize - Size of FileBuffer as returned from ProcessScript()
+
+Returns:
+ Corrected size of file.
+
+--*/
+{
+ UINT32 TotalLength;
+ UINT32 CurrentLength;
+ UINT32 SectionLength;
+ UINT32 SectionStreamLength;
+ EFI_COMMON_SECTION_HEADER *SectionHeader;
+ EFI_COMMON_SECTION_HEADER *NextSectionHeader;
+
+ TotalLength = 0;
+ CurrentLength = 0;
+ SectionStreamLength = FileSize;
+
+ SectionHeader = (EFI_COMMON_SECTION_HEADER *) FileBuffer;
+
+ while (TotalLength < SectionStreamLength) {
+ SectionLength = *((UINT32 *) SectionHeader->Size) & 0x00ffffff;
+ TotalLength += SectionLength;
+
+ if (TotalLength == SectionStreamLength) {
+ return TotalLength;
+ }
+ //
+ // Move to the next byte following the section...
+ //
+ SectionHeader = (EFI_COMMON_SECTION_HEADER *) ((UINT8 *) SectionHeader + SectionLength);
+ CurrentLength = (UINTN) SectionHeader - (UINTN) FileBuffer;
+
+ //
+ // Figure out where the next section begins
+ //
+ NextSectionHeader = (EFI_COMMON_SECTION_HEADER *) ((UINT8 *) SectionHeader + 3);
+ NextSectionHeader = (EFI_COMMON_SECTION_HEADER *) ((UINTN) NextSectionHeader &~ (UINTN) 3);
+ TotalLength += (UINTN) NextSectionHeader - (UINTN) SectionHeader;
+ SectionHeader = NextSectionHeader;
+ }
+
+ return CurrentLength;
+}
+
+static
+INT32
+MainEntry (
+ INT32 argc,
+ CHAR8 *argv[],
+ BOOLEAN ForceUncompress
+ )
+/*++
+
+Routine Description:
+
+ MainEntry function.
+
+Arguments:
+
+ argc - Number of command line parameters.
+ argv - Array of pointers to command line parameter strings.
+ ForceUncompress - If TRUE, force to do not compress the sections even if compression
+ is specified in the script. Otherwise, FALSE.
+
+Returns:
+ STATUS_SUCCESS - Function exits successfully.
+ STATUS_ERROR - Some error occurred during execution.
+
+--*/
+{
+ FILE *PrimaryPackage;
+ FILE *OverridePackage;
+ FILE *Out;
+ CHAR8 BaseName[_MAX_PATH];
+ EFI_GUID FfsGuid;
+ CHAR8 GuidString[_MAX_PATH];
+ EFI_FFS_FILE_HEADER FileHeader;
+ CHAR8 FileType[_MAX_PATH];
+ EFI_FFS_FILE_ATTRIBUTES FfsAttrib;
+ EFI_FFS_FILE_ATTRIBUTES FfsAttribDefined;
+ UINT64 FfsAlignment;
+ UINT32 FfsAlignment32;
+ CHAR8 InputString[_MAX_PATH];
+ BOOLEAN ImageScriptInOveride;
+ UINT32 FileSize;
+ UINT8 *FileBuffer;
+ EFI_STATUS Status;
+ UINT32 LineNumber;
+ EFI_FFS_FILE_TAIL TailValue;
+
+ BaseName[0] = 0;
+ FileType[0] = 0;
+ FfsAttrib = 0;
+ FfsAttribDefined = 0;
+ FfsAlignment = 0;
+ FfsAlignment32 = 0;
+ PrimaryPackage = NULL;
+ Out = NULL;
+ OverridePackage = NULL;
+ FileBuffer = NULL;
+
+ strcpy (GuidString, "00000000-0000-0000-0000-000000000000");
+ Status = StringToGuid (GuidString, &FfsGuid);
+ if (Status != 0) {
+ Error (NULL, 0, 0, GuidString, "error parsing GUID string");
+ return STATUS_ERROR;
+ }
+
+ GuidString[0] = 0;
+ ImageScriptInOveride = FALSE;
+ //
+ // Initialize the simple file parsing routines. Then open
+ // the primary package file for parsing.
+ //
+ SFPInit ();
+ if (SFPOpenFile (mGlobals.PrimaryPackagePath) != STATUS_SUCCESS) {
+ Error (NULL, 0, 0, mGlobals.PrimaryPackagePath, "unable to open primary package file");
+ goto Done;
+ }
+ //
+ // First token in the file must be "PACKAGE.INF"
+ //
+ if (!SFPIsToken ("PACKAGE.INF")) {
+ Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "expected 'PACKAGE.INF'", NULL);
+ goto Done;
+ }
+ //
+ // Find the [.] section
+ //
+ if (!SFPSkipToToken ("[.]")) {
+ Error (mGlobals.PrimaryPackagePath, 1, 0, "could not locate [.] section in package file", NULL);
+ goto Done;
+ }
+ //
+ // Start parsing the data. The algorithm is essentially the same for each keyword:
+ // 1. Identify the keyword
+ // 2. Verify that the keyword/value pair has not already been defined
+ // 3. Set some flag indicating that the keyword/value pair has been defined
+ // 4. Skip over the "="
+ // 5. Get the value, which may be a number, TRUE, FALSE, or a string.
+ //
+ while (1) {
+ if (SFPIsToken ("BASE_NAME")) {
+ //
+ // Found BASE_NAME, format:
+ // BASE_NAME = MyBaseName
+ //
+ if (BaseName[0] != 0) {
+ Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "BASE_NAME already defined", NULL);
+ goto Done;
+ }
+
+ if (!SFPIsToken ("=")) {
+ Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "expected '='", NULL);
+ goto Done;
+ }
+
+ if (!SFPGetNextToken (BaseName, sizeof (BaseName))) {
+ Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "expected valid base name", NULL);
+ goto Done;
+ }
+ } else if (SFPIsToken ("IMAGE_SCRIPT")) {
+ //
+ // Found IMAGE_SCRIPT. Break out and process below.
+ //
+ break;
+ } else if (SFPIsToken ("FFS_FILEGUID")) {
+ //
+ // found FILEGUID, format:
+ // FFS_FILEGUID = F7845C4F-EDF5-42C5-BD8F-A02AF63DD93A
+ //
+ if (GuidString[0] != 0) {
+ Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "FFS_FILEGUID already defined", NULL);
+ goto Done;
+ }
+
+ if (!SFPIsToken ("=")) {
+ Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "expected '='", NULL);
+ goto Done;
+ }
+
+ if (SFPGetGuidToken (GuidString, sizeof (GuidString)) != TRUE) {
+ Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "expected file GUID", NULL);
+ goto Done;
+ }
+
+ Status = StringToGuid (GuidString, &FfsGuid);
+ if (Status != 0) {
+ Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "expected valid file GUID", NULL);
+ goto Done;
+ }
+ } else if (SFPIsToken ("FFS_FILETYPE")) {
+ //
+ // ***********************************************************************
+ //
+ // Found FFS_FILETYPE, format:
+ // FFS_FILETYPE = EFI_FV_FILETYPE_APPLICATION
+ //
+ if (FileType[0] != 0) {
+ Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "FFS_FILETYPE previously defined", NULL);
+ goto Done;
+ }
+
+ if (!SFPIsToken ("=")) {
+ Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "expected '='", NULL);
+ goto Done;
+ }
+
+ if (!SFPGetNextToken (FileType, sizeof (FileType))) {
+ Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "expected valid FFS_FILETYPE", NULL);
+ goto Done;
+ }
+ } else if (SFPIsToken ("FFS_ATTRIB_HEADER_EXTENSION")) {
+ //
+ // ***********************************************************************
+ //
+ // Found: FFS_ATTRIB_HEADER_EXTENSION = FALSE
+ // Spec says the bit is for future expansion, and must be false.
+ //
+ if (FfsAttribDefined & FFS_ATTRIB_HEADER_EXTENSION) {
+ Error (
+ mGlobals.PrimaryPackagePath,
+ SFPGetLineNumber (),
+ 0,
+ "FFS_ATTRIB_HEADER_EXTENSION previously defined",
+ NULL
+ );
+ goto Done;
+ }
+
+ FfsAttribDefined |= FFS_ATTRIB_HEADER_EXTENSION;
+ if (!SFPIsToken ("=")) {
+ Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "expected '='", NULL);
+ goto Done;
+ }
+
+ if (SFPIsToken ("TRUE")) {
+ Error (
+ mGlobals.PrimaryPackagePath,
+ SFPGetLineNumber (),
+ 0,
+ "only FFS_ATTRIB_HEADER_EXTENSION = FALSE is supported",
+ NULL
+ );
+ goto Done;
+ } else if (SFPIsToken ("FALSE")) {
+ //
+ // Default is FALSE
+ //
+ } else {
+ Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "expected 'FALSE'", NULL);
+ goto Done;
+ }
+ } else if (SFPIsToken ("FFS_ATTRIB_TAIL_PRESENT")) {
+ //
+ // ***********************************************************************
+ //
+ // Found: FFS_ATTRIB_TAIL_PRESENT = TRUE | FALSE
+ //
+ if (FfsAttribDefined & FFS_ATTRIB_TAIL_PRESENT) {
+ Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "FFS_ATTRIB_TAIL_PRESENT previously defined", NULL);
+ goto Done;
+ }
+
+ FfsAttribDefined |= FFS_ATTRIB_TAIL_PRESENT;
+ if (!SFPIsToken ("=")) {
+ Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "expected '='", NULL);
+ goto Done;
+ }
+
+ if (SFPIsToken ("TRUE")) {
+ FfsAttrib |= FFS_ATTRIB_TAIL_PRESENT;
+ } else if (SFPIsToken ("FALSE")) {
+ //
+ // Default is FALSE
+ //
+ } else {
+ Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "expected 'TRUE' or 'FALSE'", NULL);
+ goto Done;
+ }
+ } else if (SFPIsToken ("FFS_ATTRIB_RECOVERY")) {
+ //
+ // ***********************************************************************
+ //
+ // Found: FFS_ATTRIB_RECOVERY = TRUE | FALSE
+ //
+ if (FfsAttribDefined & FFS_ATTRIB_RECOVERY) {
+ Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "FFS_ATTRIB_RECOVERY previously defined", NULL);
+ goto Done;
+ }
+
+ FfsAttribDefined |= FFS_ATTRIB_RECOVERY;
+ if (!SFPIsToken ("=")) {
+ Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "expected '='", NULL);
+ goto Done;
+ }
+
+ if (SFPIsToken ("TRUE")) {
+ FfsAttrib |= FFS_ATTRIB_RECOVERY;
+ } else if (SFPIsToken ("FALSE")) {
+ //
+ // Default is FALSE
+ //
+ } else {
+ Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "expected 'TRUE' or 'FALSE'", NULL);
+ goto Done;
+ }
+ } else if (SFPIsToken ("FFS_ATTRIB_CHECKSUM")) {
+ //
+ // ***********************************************************************
+ //
+ // Found: FFS_ATTRIB_CHECKSUM = TRUE | FALSE
+ //
+ if (FfsAttribDefined & FFS_ATTRIB_CHECKSUM) {
+ Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "FFS_ATTRIB_CHECKSUM previously defined", NULL);
+ goto Done;
+ }
+
+ FfsAttribDefined |= FFS_ATTRIB_CHECKSUM;
+ if (!SFPIsToken ("=")) {
+ Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "expected '='", NULL);
+ goto Done;
+ }
+
+ if (SFPIsToken ("TRUE")) {
+ FfsAttrib |= FFS_ATTRIB_CHECKSUM;
+ } else if (SFPIsToken ("FALSE")) {
+ //
+ // Default is FALSE
+ //
+ } else {
+ Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "expected 'TRUE' or 'FALSE'", NULL);
+ goto Done;
+ }
+ } else if (SFPIsToken ("FFS_ALIGNMENT") || SFPIsToken ("FFS_ATTRIB_DATA_ALIGNMENT")) {
+ //
+ // ***********************************************************************
+ //
+ // Found FFS_ALIGNMENT, formats:
+ // FFS_ALIGNMENT = 0-7
+ // FFS_ATTRIB_DATA_ALIGNMENT = 0-7
+ //
+ if (FfsAttribDefined & FFS_ATTRIB_DATA_ALIGNMENT) {
+ Error (
+ mGlobals.PrimaryPackagePath,
+ SFPGetLineNumber (),
+ 0,
+ "FFS_ALIGNMENT/FFS_ATTRIB_DATA_ALIGNMENT previously defined",
+ NULL
+ );
+ goto Done;
+ }
+
+ FfsAttribDefined |= FFS_ATTRIB_DATA_ALIGNMENT;
+ if (!SFPIsToken ("=")) {
+ Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "expected '='", NULL);
+ goto Done;
+ }
+
+ if (!SFPGetNumber (&FfsAlignment32)) {
+ Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "expected numeric value for alignment", NULL);
+ goto Done;
+ }
+
+ if (FfsAlignment32 > 7) {
+ Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "expected 0 <= alignment <= 7", NULL);
+ goto Done;
+ }
+
+ FfsAttrib |= (((EFI_FFS_FILE_ATTRIBUTES) FfsAlignment32) << 3);
+ } else {
+ SFPGetNextToken (InputString, sizeof (InputString));
+ Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, InputString, "unrecognized/unexpected token");
+ goto Done;
+ }
+ }
+ //
+ // Close the primary package file
+ //
+ SFPCloseFile ();
+ //
+ // TODO: replace code below with basically a copy of the code above. Don't
+ // forget to reset the FfsAttribDefined variable first. Also, you'll need
+ // to somehow keep track of whether or not the basename is defined multiple
+ // times in the override package. Ditto on the file GUID.
+ //
+ if (mGlobals.OverridePackagePath[0] != 0) {
+ OverridePackage = fopen (mGlobals.OverridePackagePath, "r");
+ //
+ // NOTE: For package override to work correctly, the code below must be modified to
+ // SET or CLEAR bits properly. For example, if the primary package set
+ // FFS_ATTRIB_CHECKSUM = TRUE, and the override set FFS_ATTRIB_CHECKSUM = FALSE, then
+ // we'd need to clear the bit below. Since this is not happening, I'm guessing that
+ // the override functionality is not being used, so should be made obsolete. If I'm
+ // wrong, and it is being used, then it needs to be fixed. Thus emit an error if it is
+ // used, and we'll address it then. 4/10/2003
+ //
+ Error (__FILE__, __LINE__, 0, "package override functionality is not implemented correctly", NULL);
+ goto Done;
+ } else {
+ OverridePackage = NULL;
+ }
+
+#ifdef OVERRIDE_SUPPORTED
+ if (OverridePackage != NULL) {
+ //
+ // Parse override package file
+ //
+ fscanf (OverridePackage, "%s", &InputString);
+ if (strcmpi (InputString, "PACKAGE.INF") != 0) {
+ Error (mGlobals.OverridePackagePath, 1, 0, "invalid package file", "expected 'PACKAGE.INF'");
+ goto Done;
+ }
+ //
+ // Match [dir] to Build Directory
+ //
+ if (FindSectionInPackage (mGlobals.BuildDirectory, OverridePackage, &LineNumber) != 0) {
+ Error (mGlobals.OverridePackagePath, 1, 0, mGlobals.BuildDirectory, "section not found in package file");
+ goto Done;
+ }
+
+ InputString[0] = 0;
+ while ((InputString[0] != '[') && (!feof (OverridePackage))) {
+ if (GetNextLine (InputString, OverridePackage, &LineNumber) != -1) {
+ if (InputString[0] != '[') {
+here:
+ if (strcmpi (InputString, "BASE_NAME") == 0) {
+ //
+ // found BASE_NAME, next is = and string.
+ //
+ fscanf (OverridePackage, "%s", &InputString);
+ CheckSlash (InputString, OverridePackage, &LineNumber);
+ if (strlen (InputString) == 1) {
+ //
+ // string is just =
+ //
+ fscanf (OverridePackage, "%s", &InputString);
+ CheckSlash (InputString, OverridePackage, &LineNumber);
+ strcpy (BaseName, InputString);
+ } else {
+ BreakString (InputString, InputString, 1);
+ strcpy (BaseName, InputString);
+ }
+ } else if (strcmpi (InputString, "IMAGE_SCRIPT") == 0) {
+ //
+ // found IMAGE_SCRIPT, come back later to process it
+ //
+ ImageScriptInOveride = TRUE;
+ fscanf (OverridePackage, "%s", &InputString);
+ } else if (strcmpi (InputString, "FFS_FILEGUID") == 0) {
+ //
+ // found FILEGUID, next is = and string.
+ //
+ fscanf (OverridePackage, "%s", &InputString);
+ CheckSlash (InputString, OverridePackage, &LineNumber);
+ if (strlen (InputString) == 1) {
+ //
+ // string is just =
+ //
+ fscanf (OverridePackage, "%s", &InputString);
+ CheckSlash (InputString, OverridePackage, &LineNumber);
+ Status = StringToGuid (InputString, &FfsGuid);
+ if (Status != 0) {
+ Error (mGlobals.OverridePackagePath, 1, 0, InputString, "bad FFS_FILEGUID format");
+ goto Done;
+ }
+ } else {
+ BreakString (InputString, InputString, 1);
+ Status = StringToGuid (InputString, &FfsGuid);
+ if (Status != 0) {
+ Error (mGlobals.OverridePackagePath, 1, 0, InputString, "bad FFS_FILEGUID format");
+ goto Done;
+ }
+ }
+ } else if (strcmpi (InputString, "FFS_FILETYPE") == 0) {
+ //
+ // found FILETYPE, next is = and string.
+ //
+ fscanf (OverridePackage, "%s", &InputString);
+ CheckSlash (InputString, OverridePackage, &LineNumber);
+ if (strlen (InputString) == 1) {
+ //
+ // string is just =
+ //
+ fscanf (OverridePackage, "%s", &InputString);
+ CheckSlash (InputString, OverridePackage, &LineNumber);
+ strcpy (FileType, InputString);
+ } else {
+ BreakString (InputString, InputString, 1);
+ strcpy (FileType, InputString);
+ }
+
+ } else if (strcmpi (InputString, "FFS_ATTRIB_RECOVERY") == 0) {
+ //
+ // found FFS_ATTRIB_RECOVERY, next is = and string.
+ //
+ fscanf (OverridePackage, "%s", &InputString);
+ CheckSlash (InputString, OverridePackage, &LineNumber);
+ if (strlen (InputString) == 1) {
+ //
+ // string is just =
+ //
+ fscanf (OverridePackage, "%s", &InputString);
+ CheckSlash (InputString, OverridePackage, &LineNumber);
+ if (strcmpi (InputString, "TRUE") == 0) {
+ FfsAttrib |= FFS_ATTRIB_RECOVERY;
+ }
+ } else {
+ BreakString (InputString, InputString, 1);
+ if (strcmpi (InputString, "TRUE") == 0) {
+ FfsAttrib |= FFS_ATTRIB_RECOVERY;
+ }
+ }
+ } else if (strcmpi (InputString, "FFS_ATTRIB_CHECKSUM") == 0) {
+ //
+ // found FFS_ATTRIB_CHECKSUM, next is = and string.
+ //
+ fscanf (OverridePackage, "%s", &InputString);
+ CheckSlash (InputString, OverridePackage, &LineNumber);
+ if (strlen (InputString) == 1) {
+ //
+ // string is just =
+ //
+ fscanf (OverridePackage, "%s", &InputString);
+ CheckSlash (InputString, OverridePackage, &LineNumber);
+ if (strcmpi (InputString, "TRUE") == 0) {
+ FfsAttrib |= FFS_ATTRIB_CHECKSUM;
+ }
+ } else {
+ BreakString (InputString, InputString, 1);
+ if (strcmpi (InputString, "TRUE") == 0) {
+ FfsAttrib |= FFS_ATTRIB_CHECKSUM;
+ }
+ }
+ } else if (strcmpi (InputString, "FFS_ALIGNMENT") == 0) {
+ //
+ // found FFS_ALIGNMENT, next is = and string.
+ //
+ fscanf (OverridePackage, "%s", &InputString);
+ CheckSlash (InputString, OverridePackage, &LineNumber);
+ if (strlen (InputString) == 1) {
+ //
+ // string is just =
+ //
+ fscanf (OverridePackage, "%s", &InputString);
+ CheckSlash (InputString, OverridePackage, &LineNumber);
+ } else {
+ BreakString (InputString, InputString, 1);
+ }
+
+ AsciiStringToUint64 (InputString, FALSE, &FfsAlignment);
+ if (FfsAlignment > 7) {
+ Error (mGlobals.OverridePackagePath, 1, 0, InputString, "invalid FFS_ALIGNMENT value");
+ goto Done;
+ }
+
+ FfsAttrib |= (((EFI_FFS_FILE_ATTRIBUTES) FfsAlignment) << 3);
+ } else if (strchr (InputString, '=') != NULL) {
+ BreakString (InputString, String, 1);
+ fseek (OverridePackage, (-1 * (strlen (String) + 1)), SEEK_CUR);
+ BreakString (InputString, InputString, 0);
+ goto here;
+ }
+ }
+ }
+ }
+ }
+#endif // #ifdef OVERRIDE_SUPPORTED
+ //
+ // Require that they specified a file GUID at least, since that's how we're
+ // naming the file.
+ //
+ if (GuidString[0] == 0) {
+ Error (mGlobals.PrimaryPackagePath, 1, 0, "FFS_FILEGUID must be specified", NULL);
+ return STATUS_ERROR;
+ }
+ //
+ // Build Header and process image script
+ //
+ FileBuffer = (UINT8 *) malloc ((1024 * 1024 * 16) * sizeof (UINT8));
+ if (FileBuffer == NULL) {
+ Error (__FILE__, __LINE__, 0, "memory allocation failed", NULL);
+ goto Done;
+ }
+
+ FileSize = 0;
+ if (ImageScriptInOveride) {
+#ifdef OVERRIDE_SUPORTED
+ rewind (OverridePackage);
+ LineNumber = 0;
+ FindSectionInPackage (mGlobals.BuildDirectory, OverridePackage, &LineNumber);
+ while (strcmpi (InputString, "IMAGE_SCRIPT") != 0) {
+ GetNextLine (InputString, OverridePackage, &LineNumber);
+ CheckSlash (InputString, OverridePackage, &LineNumber);
+ if (strchr (InputString, '=') != NULL) {
+ BreakString (InputString, InputString, 0);
+ }
+ }
+
+ while (InputString[0] != '{') {
+ GetNextLine (InputString, OverridePackage, &LineNumber);
+ CheckSlash (InputString, OverridePackage, &LineNumber);
+ }
+ //
+ // Found start of image script, process it
+ //
+ FileSize += ProcessScript (FileBuffer, OverridePackage, mGlobals.BuildDirectory, ForceUncompress);
+ if (FileSize == -1) {
+ return -1;
+ }
+
+ if (StringToType (FileType) != EFI_FV_FILETYPE_RAW) {
+ FileSize = AdjustFileSize (FileBuffer, FileSize);
+ }
+
+ if (BaseName[0] == '\"') {
+ StripQuotes (BaseName);
+ }
+
+ if (BaseName[0] != 0) {
+ sprintf (InputString, "%s-%s", GuidString, BaseName);
+ } else {
+ strcpy (InputString, GuidString);
+ }
+
+ switch (StringToType (FileType)) {
+
+ case EFI_FV_FILETYPE_SECURITY_CORE:
+ strcat (InputString, ".SEC");
+ break;
+
+ case EFI_FV_FILETYPE_PEIM:
+ case EFI_FV_FILETYPE_PEI_CORE:
+ case EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER:
+ strcat (InputString, ".PEI");
+ break;
+
+ case EFI_FV_FILETYPE_DRIVER:
+ case EFI_FV_FILETYPE_DXE_CORE:
+ strcat (InputString, ".DXE");
+ break;
+
+ case EFI_FV_FILETYPE_APPLICATION:
+ strcat (InputString, ".APP");
+ break;
+
+ case EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE:
+ strcat (InputString, ".FVI");
+ break;
+
+ case EFI_FV_FILETYPE_ALL:
+ Error (mGlobals.OverridePackagePath, 1, 0, "invalid FFS file type for this utility", NULL);
+ goto Done;
+
+ default:
+ strcat (InputString, ".FFS");
+ break;
+ }
+
+ if (ForceUncompress) {
+ strcat (InputString, ".ORG");
+ }
+
+ Out = fopen (InputString, "wb");
+ if (Out == NULL) {
+ Error (NULL, 0, 0, InputString, "could not open output file for writing");
+ goto Done;
+ }
+ //
+ // create ffs header
+ //
+ memset (&FileHeader, 0, sizeof (EFI_FFS_FILE_HEADER));
+ memcpy (&FileHeader.Name, &FfsGuid, sizeof (EFI_GUID));
+ FileHeader.Type = StringToType (FileType);
+ FileHeader.Attributes = FfsAttrib;
+ //
+ // Now FileSize includes the EFI_FFS_FILE_HEADER
+ //
+ FileSize += sizeof (EFI_FFS_FILE_HEADER);
+ FileHeader.Size[0] = (UINT8) (FileSize & 0xFF);
+ FileHeader.Size[1] = (UINT8) ((FileSize & 0xFF00) >> 8);
+ FileHeader.Size[2] = (UINT8) ((FileSize & 0xFF0000) >> 16);
+ //
+ // Fill in checksums and state, these must be zero for checksumming
+ //
+ // FileHeader.IntegrityCheck.Checksum.Header = 0;
+ // FileHeader.IntegrityCheck.Checksum.File = 0;
+ // FileHeader.State = 0;
+ //
+ FileHeader.IntegrityCheck.Checksum.Header = CalculateChecksum8 (
+ (UINT8 *) &FileHeader,
+ sizeof (EFI_FFS_FILE_HEADER)
+ );
+ if (FileHeader.Attributes & FFS_ATTRIB_CHECKSUM) {
+ FileHeader.IntegrityCheck.Checksum.File = CalculateChecksum8 ((UINT8 *) &FileHeader, FileSize);
+ } else {
+ FileHeader.IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM;
+ }
+
+ FileHeader.State = EFI_FILE_HEADER_CONSTRUCTION | EFI_FILE_HEADER_VALID | EFI_FILE_DATA_VALID;
+ //
+ // write header
+ //
+ if (fwrite (&FileHeader, sizeof (FileHeader), 1, Out) != 1) {
+ Error (NULL, 0, 0, "failed to write file header to output file", NULL);
+ goto Done;
+ }
+ //
+ // write data
+ //
+ if (fwrite (FileBuffer, FileSize - sizeof (EFI_FFS_FILE_HEADER), 1, Out) != 1) {
+ Error (NULL, 0, 0, "failed to write all bytes to output file", NULL);
+ goto Done;
+ }
+
+ fclose (Out);
+ Out = NULL;
+#endif // #ifdef OVERRIDE_SUPPORTED
+ } else {
+ //
+ // Open primary package file and process the IMAGE_SCRIPT section
+ //
+ PrimaryPackage = fopen (mGlobals.PrimaryPackagePath, "r");
+ if (PrimaryPackage == NULL) {
+ Error (NULL, 0, 0, mGlobals.PrimaryPackagePath, "unable to open primary package file");
+ goto Done;
+ }
+
+ LineNumber = 1;
+ FindSectionInPackage (".", PrimaryPackage, &LineNumber);
+ while (strcmpi (InputString, "IMAGE_SCRIPT") != 0) {
+ GetNextLine (InputString, PrimaryPackage, &LineNumber);
+ CheckSlash (InputString, PrimaryPackage, &LineNumber);
+ if (strchr (InputString, '=') != NULL) {
+ BreakString (InputString, InputString, 0);
+ }
+ }
+
+ while (InputString[0] != '{') {
+ GetNextLine (InputString, PrimaryPackage, &LineNumber);
+ CheckSlash (InputString, PrimaryPackage, &LineNumber);
+ }
+ //
+ // Found start of image script, process it
+ //
+ FileSize += ProcessScript (FileBuffer, PrimaryPackage, mGlobals.BuildDirectory, ForceUncompress);
+ if (FileSize == -1) {
+ goto Done;
+ }
+
+ if (StringToType (FileType) != EFI_FV_FILETYPE_RAW) {
+ FileSize = AdjustFileSize (FileBuffer, FileSize);
+ }
+
+ if (BaseName[0] == '\"') {
+ StripQuotes (BaseName);
+ }
+
+ if (BaseName[0] != 0) {
+ sprintf (InputString, "%s-%s", GuidString, BaseName);
+ } else {
+ strcpy (InputString, GuidString);
+ }
+
+ switch (StringToType (FileType)) {
+
+ case EFI_FV_FILETYPE_SECURITY_CORE:
+ strcat (InputString, ".SEC");
+ break;
+
+ case EFI_FV_FILETYPE_PEIM:
+ case EFI_FV_FILETYPE_PEI_CORE:
+ case EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER:
+ strcat (InputString, ".PEI");
+ break;
+
+ case EFI_FV_FILETYPE_DRIVER:
+ case EFI_FV_FILETYPE_DXE_CORE:
+ strcat (InputString, ".DXE");
+ break;
+
+ case EFI_FV_FILETYPE_APPLICATION:
+ strcat (InputString, ".APP");
+ break;
+
+ case EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE:
+ strcat (InputString, ".FVI");
+ break;
+
+ case EFI_FV_FILETYPE_ALL:
+ Error (mGlobals.PrimaryPackagePath, 1, 0, "invalid FFS file type for this utility", NULL);
+ goto Done;
+
+ default:
+ strcat (InputString, ".FFS");
+ break;
+ }
+
+ if (ForceUncompress) {
+ strcat (InputString, ".ORG");
+ }
+
+ Out = fopen (InputString, "wb");
+ if (Out == NULL) {
+ Error (NULL, 0, 0, InputString, "failed to open output file for writing");
+ goto Done;
+ }
+ //
+ // Initialize the FFS file header
+ //
+ memset (&FileHeader, 0, sizeof (EFI_FFS_FILE_HEADER));
+ memcpy (&FileHeader.Name, &FfsGuid, sizeof (EFI_GUID));
+ FileHeader.Type = StringToType (FileType);
+ FileHeader.Attributes = FfsAttrib;
+ //
+ // From this point on FileSize includes the size of the EFI_FFS_FILE_HEADER
+ //
+ FileSize += sizeof (EFI_FFS_FILE_HEADER);
+ //
+ // If using a tail, then it adds two bytes
+ //
+ if (FileHeader.Attributes & FFS_ATTRIB_TAIL_PRESENT) {
+ //
+ // Tail is not allowed for pad and 0-length files
+ //
+ if ((FileHeader.Type == EFI_FV_FILETYPE_FFS_PAD) || (FileSize == sizeof (EFI_FFS_FILE_HEADER))) {
+ Error (
+ mGlobals.PrimaryPackagePath,
+ 1,
+ 0,
+ "FFS_ATTRIB_TAIL_PRESENT=TRUE is invalid for PAD or 0-length files",
+ NULL
+ );
+ goto Done;
+ }
+
+ FileSize += sizeof (EFI_FFS_FILE_TAIL);
+ }
+
+ FileHeader.Size[0] = (UINT8) (FileSize & 0xFF);
+ FileHeader.Size[1] = (UINT8) ((FileSize & 0xFF00) >> 8);
+ FileHeader.Size[2] = (UINT8) ((FileSize & 0xFF0000) >> 16);
+ //
+ // Fill in checksums and state, they must be 0 for checksumming.
+ //
+ // FileHeader.IntegrityCheck.Checksum.Header = 0;
+ // FileHeader.IntegrityCheck.Checksum.File = 0;
+ // FileHeader.State = 0;
+ //
+ FileHeader.IntegrityCheck.Checksum.Header = CalculateChecksum8 (
+ (UINT8 *) &FileHeader,
+ sizeof (EFI_FFS_FILE_HEADER)
+ );
+ if (FileHeader.Attributes & FFS_ATTRIB_CHECKSUM) {
+ //
+ // Cheating here. Since the header checksums, just calculate the checksum of the body.
+ // Checksum does not include the tail
+ //
+ if (FileHeader.Attributes & FFS_ATTRIB_TAIL_PRESENT) {
+ FileHeader.IntegrityCheck.Checksum.File = CalculateChecksum8 (
+ FileBuffer,
+ FileSize - sizeof (EFI_FFS_FILE_HEADER) - sizeof (EFI_FFS_FILE_TAIL)
+ );
+ } else {
+ FileHeader.IntegrityCheck.Checksum.File = CalculateChecksum8 (
+ FileBuffer,
+ FileSize - sizeof (EFI_FFS_FILE_HEADER)
+ );
+ }
+ } else {
+ FileHeader.IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM;
+ }
+ //
+ // Set the state now. Spec says the checksum assumes the state is 0
+ //
+ FileHeader.State = EFI_FILE_HEADER_CONSTRUCTION | EFI_FILE_HEADER_VALID | EFI_FILE_DATA_VALID;
+ //
+ // If there is a tail, then set it
+ //
+ if (FileHeader.Attributes & FFS_ATTRIB_TAIL_PRESENT) {
+ TailValue = FileHeader.IntegrityCheck.TailReference;
+ TailValue = (UINT16) (~TailValue);
+ memcpy (
+ (UINT8 *) FileBuffer + FileSize - sizeof (EFI_FFS_FILE_HEADER) - sizeof (EFI_FFS_FILE_TAIL),
+ &TailValue,
+ sizeof (TailValue)
+ );
+ }
+ //
+ // Write the FFS file header
+ //
+ if (fwrite (&FileHeader, sizeof (FileHeader), 1, Out) != 1) {
+ Error (NULL, 0, 0, "failed to write file header contents", NULL);
+ goto Done;
+ }
+ //
+ // Write data
+ //
+ if (fwrite (FileBuffer, FileSize - sizeof (EFI_FFS_FILE_HEADER), 1, Out) != 1) {
+ Error (NULL, 0, 0, "failed to write file contents", NULL);
+ goto Done;
+ }
+ }
+
+Done:
+ SFPCloseFile ();
+ if (Out != NULL) {
+ fclose (Out);
+ }
+
+ if (PrimaryPackage != NULL) {
+ fclose (PrimaryPackage);
+ }
+
+ if (FileBuffer != NULL) {
+ free (FileBuffer);
+ }
+
+ if (OverridePackage != NULL) {
+ fclose (OverridePackage);
+ }
+
+ return GetUtilityStatus ();
+}
+
+int
+main (
+ INT32 argc,
+ CHAR8 *argv[]
+ )
+/*++
+
+Routine Description:
+
+ Main function.
+
+Arguments:
+
+ argc - Number of command line parameters.
+ argv - Array of pointers to parameter strings.
+
+Returns:
+ STATUS_SUCCESS - Utility exits successfully.
+ STATUS_ERROR - Some error occurred during execution.
+
+--*/
+{
+ STATUS Status;
+ //
+ // Set the name of our utility for error reporting purposes.
+ //
+ SetUtilityName (UTILITY_NAME);
+ Status = ProcessCommandLineArgs (argc, argv);
+ if (Status != STATUS_SUCCESS) {
+ return Status;
+ }
+
+ Status = MainEntry (argc, argv, TRUE);
+ if (Status == STATUS_SUCCESS) {
+ MainEntry (argc, argv, FALSE);
+ }
+ //
+ // If any errors were reported via the standard error reporting
+ // routines, then the status has been saved. Get the value and
+ // return it to the caller.
+ //
+ return GetUtilityStatus ();
+}
+
+static
+STATUS
+ProcessCommandLineArgs (
+ int Argc,
+ char *Argv[]
+ )
+/*++
+
+Routine Description:
+ Process the command line arguments.
+
+Arguments:
+ Argc - as passed in to main()
+ Argv - as passed in to main()
+
+Returns:
+ STATUS_SUCCESS - arguments all ok
+ STATUS_ERROR - problem with args, so caller should exit
+
+--*/
+{
+ //
+ // If no args, then print usage instructions and return an error
+ //
+ if (Argc == 1) {
+ PrintUsage ();
+ return STATUS_ERROR;
+ }
+
+ memset (&mGlobals, 0, sizeof (mGlobals));
+ Argc--;
+ Argv++;
+ while (Argc > 0) {
+ if (strcmpi (Argv[0], "-b") == 0) {
+ //
+ // OPTION: -b BuildDirectory
+ // Make sure there is another argument, then save it to our globals.
+ //
+ if (Argc < 2) {
+ Error (NULL, 0, 0, "-b option requires the build directory name", NULL);
+ return STATUS_ERROR;
+ }
+
+ if (mGlobals.BuildDirectory[0]) {
+ Error (NULL, 0, 0, Argv[0], "option can only be specified once");
+ return STATUS_ERROR;
+ }
+
+ strcpy (mGlobals.BuildDirectory, Argv[1]);
+ Argc--;
+ Argv++;
+ } else if (strcmpi (Argv[0], "-p1") == 0) {
+ //
+ // OPTION: -p1 PrimaryPackageFile
+ // Make sure there is another argument, then save it to our globals.
+ //
+ if (Argc < 2) {
+ Error (NULL, 0, 0, Argv[0], "option requires the primary package file name");
+ return STATUS_ERROR;
+ }
+
+ if (mGlobals.PrimaryPackagePath[0]) {
+ Error (NULL, 0, 0, Argv[0], "option can only be specified once");
+ return STATUS_ERROR;
+ }
+
+ strcpy (mGlobals.PrimaryPackagePath, Argv[1]);
+ Argc--;
+ Argv++;
+ } else if (strcmpi (Argv[0], "-p2") == 0) {
+ //
+ // OPTION: -p2 OverridePackageFile
+ // Make sure there is another argument, then save it to our globals.
+ //
+ if (Argc < 2) {
+ Error (NULL, 0, 0, Argv[0], "option requires the override package file name");
+ return STATUS_ERROR;
+ }
+
+ if (mGlobals.OverridePackagePath[0]) {
+ Error (NULL, 0, 0, Argv[0], "option can only be specified once");
+ return STATUS_ERROR;
+ }
+
+ strcpy (mGlobals.OverridePackagePath, Argv[1]);
+ Argc--;
+ Argv++;
+ } else if (strcmpi (Argv[0], "-v") == 0) {
+ //
+ // OPTION: -v verbose
+ //
+ mGlobals.Verbose = TRUE;
+ } else if (strcmpi (Argv[0], "-h") == 0) {
+ //
+ // OPTION: -h help
+ //
+ PrintUsage ();
+ return STATUS_ERROR;
+ } else if (strcmpi (Argv[0], "-?") == 0) {
+ //
+ // OPTION: -? help
+ //
+ PrintUsage ();
+ return STATUS_ERROR;
+ } else {
+ Error (NULL, 0, 0, Argv[0], "unrecognized option");
+ PrintUsage ();
+ return STATUS_ERROR;
+ }
+
+ Argv++;
+ Argc--;
+ }
+ //
+ // Must have at least specified the package file name
+ //
+ if (mGlobals.PrimaryPackagePath[0] == 0) {
+ Error (NULL, 0, 0, "must specify primary package file", NULL);
+ return STATUS_ERROR;
+ }
+
+ return STATUS_SUCCESS;
+}
diff --git a/Source/GenFfsFile/GenFfsFile.h b/Source/GenFfsFile/GenFfsFile.h
new file mode 100644
index 0000000..f5bc718
--- /dev/null
+++ b/Source/GenFfsFile/GenFfsFile.h
@@ -0,0 +1,36 @@
+/*++
+
+Copyright (c) 2004, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ GenFfsFile.h
+
+Abstract:
+
+ Header file for GenFfsFile.
+
+--*/
+
+//
+// Module Coded to Tiano Coding Conventions
+//
+#ifndef _EFI_GEN_FFSFILE_H
+#define _EFI_GEN_FFSFILE_H
+
+//
+// External Files Referenced
+//
+#include <Common/UefiBaseTypes.h>
+#include <Common/FirmwareVolumeImageFormat.h>
+
+#include "MyAlloc.h"
+
+#endif
diff --git a/Source/GenFfsFile/SimpleFileParsing.c b/Source/GenFfsFile/SimpleFileParsing.c
new file mode 100644
index 0000000..5fa5a22
--- /dev/null
+++ b/Source/GenFfsFile/SimpleFileParsing.c
@@ -0,0 +1,969 @@
+/*++
+
+Copyright (c) 2004, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ SimpleFileParsing.c
+
+Abstract:
+
+ Generic but simple file parsing routines.
+
+--*/
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+
+#include <Common/UefiBaseTypes.h>
+
+#include "EfiUtilityMsgs.h"
+#include "SimpleFileParsing.h"
+
+#define MAX_PATH 255
+#define MAX_NEST_DEPTH 20 // just in case we get in an endless loop.
+#define MAX_STRING_IDENTIFIER_NAME 100 // number of wchars
+#define MAX_LINE_LEN 400
+
+#define T_CHAR_SPACE ' '
+#define T_CHAR_NULL 0
+#define T_CHAR_CR '\r'
+#define T_CHAR_TAB '\t'
+#define T_CHAR_LF '\n'
+#define T_CHAR_SLASH '/'
+#define T_CHAR_BACKSLASH '\\'
+#define T_CHAR_DOUBLE_QUOTE '"'
+#define T_CHAR_LC_X 'x'
+#define T_CHAR_0 '0'
+
+//
+// We keep a linked list of these for the source files we process
+//
+typedef struct _SOURCE_FILE {
+ FILE *Fptr;
+ T_CHAR *FileBuffer;
+ T_CHAR *FileBufferPtr;
+ UINT32 FileSize;
+ INT8 FileName[MAX_PATH];
+ UINT32 LineNum;
+ BOOLEAN EndOfFile;
+ BOOLEAN SkipToHash;
+ struct _SOURCE_FILE *Previous;
+ struct _SOURCE_FILE *Next;
+ T_CHAR ControlCharacter;
+} SOURCE_FILE;
+
+//
+// Here's all our module globals.
+//
+static struct {
+ SOURCE_FILE SourceFile;
+ BOOLEAN Verbose;
+} mGlobals;
+
+static
+UINT32
+t_strcmp (
+ T_CHAR *Buffer,
+ T_CHAR *Str
+ );
+
+static
+UINT32
+t_strncmp (
+ T_CHAR *Str1,
+ T_CHAR *Str2,
+ UINT32 Len
+ );
+
+static
+UINT32
+t_strlen (
+ T_CHAR *Str
+ );
+
+static
+void
+RewindFile (
+ SOURCE_FILE *SourceFile
+ );
+
+static
+BOOLEAN
+SkipTo (
+ SOURCE_FILE *SourceFile,
+ T_CHAR TChar,
+ BOOLEAN StopAfterNewline
+ );
+
+static
+BOOLEAN
+IsWhiteSpace (
+ SOURCE_FILE *SourceFile
+ );
+
+static
+UINT32
+SkipWhiteSpace (
+ SOURCE_FILE *SourceFile
+ );
+
+static
+BOOLEAN
+EndOfFile (
+ SOURCE_FILE *SourceFile
+ );
+
+static
+void
+PreprocessFile (
+ SOURCE_FILE *SourceFile
+ );
+
+//
+// static
+// T_CHAR *
+// GetQuotedString (
+// SOURCE_FILE *SourceFile,
+// BOOLEAN Optional
+// );
+//
+static
+T_CHAR *
+t_strcpy (
+ T_CHAR *Dest,
+ T_CHAR *Src
+ );
+
+static
+STATUS
+ProcessIncludeFile (
+ SOURCE_FILE *SourceFile,
+ SOURCE_FILE *ParentSourceFile
+ );
+
+static
+STATUS
+ParseFile (
+ SOURCE_FILE *SourceFile
+ );
+
+static
+FILE *
+FindFile (
+ IN INT8 *FileName,
+ OUT INT8 *FoundFileName,
+ IN UINT32 FoundFileNameLen
+ );
+
+static
+STATUS
+ProcessFile (
+ SOURCE_FILE *SourceFile
+ );
+
+STATUS
+SFPInit (
+ VOID
+ )
+{
+ memset ((void *) &mGlobals, 0, sizeof (mGlobals));
+ return STATUS_SUCCESS;
+}
+
+UINT32
+SFPGetLineNumber (
+ VOID
+ )
+{
+ return mGlobals.SourceFile.LineNum;
+}
+
+/*++
+
+Routine Description:
+ Return the line number of the file we're parsing. Used
+ for error reporting purposes.
+
+Arguments:
+ None.
+
+Returns:
+ The line number, or 0 if no file is being processed
+
+--*/
+T_CHAR *
+SFPGetFileName (
+ VOID
+ )
+/*++
+
+Routine Description:
+ Return the name of the file we're parsing. Used
+ for error reporting purposes.
+
+Arguments:
+ None.
+
+Returns:
+ A pointer to the file name. Null if no file is being
+ processed.
+
+--*/
+{
+ if (mGlobals.SourceFile.FileName[0]) {
+ return mGlobals.SourceFile.FileName;
+ }
+
+ return NULL;
+}
+
+STATUS
+SFPOpenFile (
+ IN INT8 *FileName
+ )
+/*++
+
+Routine Description:
+ Open a file for parsing.
+
+Arguments:
+ FileName - name of the file to parse
+
+Returns:
+
+
+--*/
+{
+ STATUS Status;
+ t_strcpy (mGlobals.SourceFile.FileName, FileName);
+ Status = ProcessIncludeFile (&mGlobals.SourceFile, NULL);
+ return Status;
+}
+
+BOOLEAN
+SFPIsToken (
+ T_CHAR *Str
+ )
+/*++
+
+Routine Description:
+ Check to see if the specified token is found at
+ the current position in the input file.
+
+Arguments:
+ Str - the token to look for
+
+Returns:
+ TRUE - the token is next
+ FALSE - the token is not next
+
+Notes:
+ We do a simple string comparison on this function. It is
+ the responsibility of the caller to ensure that the token
+ is not a subset of some other token.
+
+ The file pointer is advanced past the token in the input file.
+
+--*/
+{
+ UINT32 Len;
+ SkipWhiteSpace (&mGlobals.SourceFile);
+
+ if ((Len = t_strcmp (mGlobals.SourceFile.FileBufferPtr, Str)) > 0) {
+ mGlobals.SourceFile.FileBufferPtr += Len;
+ return TRUE;
+ }
+
+ return FALSE;
+
+}
+
+BOOLEAN
+SFPGetNextToken (
+ T_CHAR *Str,
+ UINT32 Len
+ )
+{
+ UINT32 Index;
+ SkipWhiteSpace (&mGlobals.SourceFile);
+ Index = 0;
+ while (!EndOfFile (&mGlobals.SourceFile) && (Index < Len)) {
+ if (IsWhiteSpace (&mGlobals.SourceFile)) {
+ if (Index > 0) {
+ Str[Index] = 0;
+ return TRUE;
+ }
+
+ return FALSE;
+ } else {
+ Str[Index] = mGlobals.SourceFile.FileBufferPtr[0];
+ mGlobals.SourceFile.FileBufferPtr++;
+ Index++;
+ }
+ }
+
+ return FALSE;
+}
+
+BOOLEAN
+SFPSkipToToken (
+ T_CHAR *Str
+ )
+{
+ UINT32 Len;
+ T_CHAR *SavePos;
+ Len = t_strlen (Str);
+ SavePos = mGlobals.SourceFile.FileBufferPtr;
+ SkipWhiteSpace (&mGlobals.SourceFile);
+ while (!EndOfFile (&mGlobals.SourceFile)) {
+ if (t_strncmp (Str, mGlobals.SourceFile.FileBufferPtr, Len) == 0) {
+ mGlobals.SourceFile.FileBufferPtr += Len;
+ return TRUE;
+ }
+
+ mGlobals.SourceFile.FileBufferPtr++;
+ SkipWhiteSpace (&mGlobals.SourceFile);
+ }
+
+ mGlobals.SourceFile.FileBufferPtr = SavePos;
+ return FALSE;
+}
+
+BOOLEAN
+SFPGetNumber (
+ UINT32 *Value
+ )
+/*++
+
+Routine Description:
+ Check the token at the current file position for a numeric value.
+ May be either decimal or hex.
+
+Arguments:
+ Value - pointer where to store the value
+
+Returns:
+ FALSE - current token is not a number
+ TRUE - current token is a number
+
+--*/
+{
+ //
+ // UINT32 Len;
+ //
+ SkipWhiteSpace (&mGlobals.SourceFile);
+ if (EndOfFile (&mGlobals.SourceFile)) {
+ return FALSE;
+ }
+
+ if (isdigit (mGlobals.SourceFile.FileBufferPtr[0])) {
+ //
+ // Check for hex value
+ //
+ if ((mGlobals.SourceFile.FileBufferPtr[0] == T_CHAR_0) && (mGlobals.SourceFile.FileBufferPtr[1] == T_CHAR_LC_X)) {
+ if (!isxdigit (mGlobals.SourceFile.FileBufferPtr[2])) {
+ return FALSE;
+ }
+
+ mGlobals.SourceFile.FileBufferPtr += 2;
+ sscanf (mGlobals.SourceFile.FileBufferPtr, "%x", Value);
+ while (isxdigit (mGlobals.SourceFile.FileBufferPtr[0])) {
+ mGlobals.SourceFile.FileBufferPtr++;
+ }
+
+ return TRUE;
+ } else {
+ *Value = atoi (mGlobals.SourceFile.FileBufferPtr);
+ while (isdigit (mGlobals.SourceFile.FileBufferPtr[0])) {
+ mGlobals.SourceFile.FileBufferPtr++;
+ }
+
+ return TRUE;
+ }
+ } else {
+ return FALSE;
+ }
+}
+
+STATUS
+SFPCloseFile (
+ VOID
+ )
+/*++
+
+Routine Description:
+ Close the file being parsed.
+
+Arguments:
+ None.
+
+Returns:
+ STATUS_SUCCESS - the file was closed
+ STATUS_ERROR - no file is currently open
+
+--*/
+{
+ if (mGlobals.SourceFile.FileBuffer != NULL) {
+ free (mGlobals.SourceFile.FileBuffer);
+ memset (&mGlobals.SourceFile, 0, sizeof (mGlobals.SourceFile));
+ return STATUS_SUCCESS;
+ }
+
+ return STATUS_ERROR;
+}
+
+static
+STATUS
+ProcessIncludeFile (
+ SOURCE_FILE *SourceFile,
+ SOURCE_FILE *ParentSourceFile
+ )
+/*++
+
+Routine Description:
+
+ Given a source file, open the file and parse it
+
+Arguments:
+
+ SourceFile - name of file to parse
+ ParentSourceFile - for error reporting purposes, the file that #included SourceFile.
+
+Returns:
+
+ Standard status.
+
+--*/
+{
+ static UINT32 NestDepth = 0;
+ INT8 FoundFileName[MAX_PATH];
+ STATUS Status;
+
+ Status = STATUS_SUCCESS;
+ NestDepth++;
+ //
+ // Print the file being processed. Indent so you can tell the include nesting
+ // depth.
+ //
+ if (mGlobals.Verbose) {
+ fprintf (stdout, "%*cProcessing file '%s'\n", NestDepth * 2, ' ', SourceFile->FileName);
+ }
+
+ //
+ // Make sure we didn't exceed our maximum nesting depth
+ //
+ if (NestDepth > MAX_NEST_DEPTH) {
+ Error (NULL, 0, 0, SourceFile->FileName, "max nesting depth (%d) exceeded", NestDepth);
+ Status = STATUS_ERROR;
+ goto Finish;
+ }
+ //
+ // Try to open the file locally, and if that fails try along our include paths.
+ //
+ strcpy (FoundFileName, SourceFile->FileName);
+ if ((SourceFile->Fptr = fopen (FoundFileName, "r")) == NULL) {
+ //
+ // Try to find it among the paths if it has a parent (that is, it is included
+ // by someone else).
+ //
+ Error (NULL, 0, 0, SourceFile->FileName, "file not found");
+ return STATUS_ERROR;
+ }
+ //
+ // Process the file found
+ //
+ ProcessFile (SourceFile);
+Finish:
+ //
+ // Close open files and return status
+ //
+ if (SourceFile->Fptr != NULL) {
+ fclose (SourceFile->Fptr);
+ SourceFile->Fptr = NULL;
+ }
+
+ return Status;
+}
+
+static
+STATUS
+ProcessFile (
+ SOURCE_FILE *SourceFile
+ )
+{
+ //
+ // Get the file size, and then read the entire thing into memory.
+ // Allocate space for a terminator character.
+ //
+ fseek (SourceFile->Fptr, 0, SEEK_END);
+ SourceFile->FileSize = ftell (SourceFile->Fptr);
+ fseek (SourceFile->Fptr, 0, SEEK_SET);
+ SourceFile->FileBuffer = (T_CHAR *) malloc (SourceFile->FileSize + sizeof (T_CHAR));
+ if (SourceFile->FileBuffer == NULL) {
+ Error (NULL, 0, 0, "memory allocation failure", NULL);
+ return STATUS_ERROR;
+ }
+
+ fread ((VOID *) SourceFile->FileBuffer, SourceFile->FileSize, 1, SourceFile->Fptr);
+ SourceFile->FileBuffer[(SourceFile->FileSize / sizeof (T_CHAR))] = T_CHAR_NULL;
+ //
+ // Pre-process the file to replace comments with spaces
+ //
+ PreprocessFile (SourceFile);
+ SourceFile->LineNum = 1;
+ return STATUS_SUCCESS;
+}
+
+static
+void
+PreprocessFile (
+ SOURCE_FILE *SourceFile
+ )
+/*++
+
+Routine Description:
+ Preprocess a file to replace all carriage returns with NULLs so
+ we can print lines from the file to the screen.
+
+Arguments:
+ SourceFile - structure that we use to keep track of an input file.
+
+Returns:
+ Nothing.
+
+--*/
+{
+ BOOLEAN InComment;
+
+ RewindFile (SourceFile);
+ InComment = FALSE;
+ while (!EndOfFile (SourceFile)) {
+ //
+ // If a line-feed, then no longer in a comment
+ //
+ if (SourceFile->FileBufferPtr[0] == T_CHAR_LF) {
+ SourceFile->FileBufferPtr++;
+ SourceFile->LineNum++;
+ InComment = 0;
+ } else if (SourceFile->FileBufferPtr[0] == T_CHAR_CR) {
+ //
+ // Replace all carriage returns with a NULL so we can print stuff
+ //
+ SourceFile->FileBufferPtr[0] = 0;
+ SourceFile->FileBufferPtr++;
+ } else if (InComment) {
+ SourceFile->FileBufferPtr[0] = T_CHAR_SPACE;
+ SourceFile->FileBufferPtr++;
+ } else if ((SourceFile->FileBufferPtr[0] == T_CHAR_SLASH) && (SourceFile->FileBufferPtr[1] == T_CHAR_SLASH)) {
+ SourceFile->FileBufferPtr += 2;
+ InComment = TRUE;
+ } else {
+ SourceFile->FileBufferPtr++;
+ }
+ }
+ //
+ // Could check for end-of-file and still in a comment, but
+ // should not be necessary. So just restore the file pointers.
+ //
+ RewindFile (SourceFile);
+}
+
+#if 0
+static
+T_CHAR *
+GetQuotedString (
+ SOURCE_FILE *SourceFile,
+ BOOLEAN Optional
+ )
+{
+ T_CHAR *String;
+ T_CHAR *Start;
+ T_CHAR *Ptr;
+ UINT32 Len;
+ BOOLEAN PreviousBackslash;
+
+ if (SourceFile->FileBufferPtr[0] != T_CHAR_DOUBLE_QUOTE) {
+ if (!Optional) {
+ Error (SourceFile->FileName, SourceFile->LineNum, 0, "expected quoted string", "%S", SourceFile->FileBufferPtr);
+ }
+
+ return NULL;
+ }
+
+ Len = 0;
+ SourceFile->FileBufferPtr++;
+ Start = Ptr = SourceFile->FileBufferPtr;
+ PreviousBackslash = FALSE;
+ while (!EndOfFile (SourceFile)) {
+ if ((SourceFile->FileBufferPtr[0] == T_CHAR_DOUBLE_QUOTE) && (!PreviousBackslash)) {
+ break;
+ } else if (SourceFile->FileBufferPtr[0] == T_CHAR_CR) {
+ Warning (SourceFile->FileName, SourceFile->LineNum, 0, "carriage return found in quoted string", "%S", Start);
+ PreviousBackslash = FALSE;
+ } else if (SourceFile->FileBufferPtr[0] == T_CHAR_BACKSLASH) {
+ PreviousBackslash = TRUE;
+ } else {
+ PreviousBackslash = FALSE;
+ }
+
+ SourceFile->FileBufferPtr++;
+ Len++;
+ }
+
+ if (SourceFile->FileBufferPtr[0] != T_CHAR_DOUBLE_QUOTE) {
+ Warning (SourceFile->FileName, SourceFile->LineNum, 0, "missing closing quote on string", "%S", Start);
+ } else {
+ SourceFile->FileBufferPtr++;
+ }
+ //
+ // Now allocate memory for the string and save it off
+ //
+ String = (T_CHAR *) malloc ((Len + 1) * sizeof (T_CHAR));
+ if (String == NULL) {
+ Error (NULL, 0, 0, "memory allocation failed", NULL);
+ return NULL;
+ }
+ //
+ // Copy the string from the file buffer to the local copy.
+ // We do no reformatting of it whatsoever at this point.
+ //
+ Ptr = String;
+ while (Len > 0) {
+ *Ptr = *Start;
+ Start++;
+ Ptr++;
+ Len--;
+ }
+
+ *Ptr = 0;
+ return String;
+}
+#endif
+static
+BOOLEAN
+EndOfFile (
+ SOURCE_FILE *SourceFile
+ )
+{
+ //
+ // The file buffer pointer will typically get updated before the End-of-file flag in the
+ // source file structure, so check it first.
+ //
+ if (SourceFile->FileBufferPtr >= SourceFile->FileBuffer + SourceFile->FileSize / sizeof (T_CHAR)) {
+ SourceFile->EndOfFile = TRUE;
+ return TRUE;
+ }
+
+ if (SourceFile->EndOfFile) {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+#if 0
+static
+void
+ProcessTokenInclude (
+ SOURCE_FILE *SourceFile
+ )
+{
+ INT8 IncludeFileName[MAX_PATH];
+ INT8 *To;
+ UINT32 Len;
+ BOOLEAN ReportedError;
+ SOURCE_FILE IncludedSourceFile;
+
+ ReportedError = FALSE;
+ if (SkipWhiteSpace (SourceFile) == 0) {
+ Warning (SourceFile->FileName, SourceFile->LineNum, 0, "expected whitespace following #include keyword", NULL);
+ }
+ //
+ // Should be quoted file name
+ //
+ if (SourceFile->FileBufferPtr[0] != T_CHAR_DOUBLE_QUOTE) {
+ Error (SourceFile->FileName, SourceFile->LineNum, 0, "expected quoted include file name", NULL);
+ goto FailDone;
+ }
+
+ SourceFile->FileBufferPtr++;
+ //
+ // Copy the filename as ascii to our local string
+ //
+ To = IncludeFileName;
+ Len = 0;
+ while (!EndOfFile (SourceFile)) {
+ if ((SourceFile->FileBufferPtr[0] == T_CHAR_CR) || (SourceFile->FileBufferPtr[0] == T_CHAR_LF)) {
+ Error (SourceFile->FileName, SourceFile->LineNum, 0, "end-of-line found in quoted include file name", NULL);
+ goto FailDone;
+ }
+
+ if (SourceFile->FileBufferPtr[0] == T_CHAR_DOUBLE_QUOTE) {
+ SourceFile->FileBufferPtr++;
+ break;
+ }
+ //
+ // If too long, then report the error once and process until the closing quote
+ //
+ Len++;
+ if (!ReportedError && (Len >= sizeof (IncludeFileName))) {
+ Error (SourceFile->FileName, SourceFile->LineNum, 0, "length of include file name exceeds limit", NULL);
+ ReportedError = TRUE;
+ }
+
+ if (!ReportedError) {
+ //
+ // *To = UNICODE_TO_ASCII(SourceFile->FileBufferPtr[0]);
+ //
+ *To = (T_CHAR) SourceFile->FileBufferPtr[0];
+ To++;
+ }
+
+ SourceFile->FileBufferPtr++;
+ }
+
+ if (!ReportedError) {
+ *To = 0;
+ memset ((char *) &IncludedSourceFile, 0, sizeof (SOURCE_FILE));
+ strcpy (IncludedSourceFile.FileName, IncludeFileName);
+ //
+ // IncludedSourceFile.ControlCharacter = DEFAULT_CONTROL_CHARACTER;
+ //
+ ProcessIncludeFile (&IncludedSourceFile, SourceFile);
+ //
+ // printf ("including file '%s'\n", IncludeFileName);
+ //
+ }
+
+ return ;
+FailDone:
+ //
+ // Error recovery -- skip to next #
+ //
+ SourceFile->SkipToHash = TRUE;
+}
+#endif
+static
+BOOLEAN
+IsWhiteSpace (
+ SOURCE_FILE *SourceFile
+ )
+{
+ switch (*SourceFile->FileBufferPtr) {
+ case T_CHAR_NULL:
+ case T_CHAR_CR:
+ case T_CHAR_SPACE:
+ case T_CHAR_TAB:
+ case T_CHAR_LF:
+ return TRUE;
+
+ default:
+ return FALSE;
+ }
+}
+
+UINT32
+SkipWhiteSpace (
+ SOURCE_FILE *SourceFile
+ )
+{
+ UINT32 Count;
+
+ Count = 0;
+ while (!EndOfFile (SourceFile)) {
+ Count++;
+ switch (*SourceFile->FileBufferPtr) {
+ case T_CHAR_NULL:
+ case T_CHAR_CR:
+ case T_CHAR_SPACE:
+ case T_CHAR_TAB:
+ SourceFile->FileBufferPtr++;
+ break;
+
+ case T_CHAR_LF:
+ SourceFile->FileBufferPtr++;
+ SourceFile->LineNum++;
+ if (mGlobals.Verbose) {
+ printf ("%d: %S\n", SourceFile->LineNum, SourceFile->FileBufferPtr);
+ }
+ break;
+
+ default:
+ return Count - 1;
+ }
+ }
+ //
+ // Some tokens require trailing whitespace. If we're at the end of the
+ // file, then we count that as well.
+ //
+ if ((Count == 0) && (EndOfFile (SourceFile))) {
+ Count++;
+ }
+
+ return Count;
+}
+
+static
+UINT32
+t_strcmp (
+ T_CHAR *Buffer,
+ T_CHAR *Str
+ )
+{
+ UINT32 Len;
+
+ Len = 0;
+ while (*Str == *Buffer) {
+ Buffer++;
+ Str++;
+ Len++;
+ }
+
+ if (*Str) {
+ return 0;
+ }
+
+ return Len;
+}
+
+static
+UINT32
+t_strlen (
+ T_CHAR *Str
+ )
+{
+ UINT32 Len;
+ Len = 0;
+ while (*Str) {
+ Len++;
+ Str++;
+ }
+
+ return Len;
+}
+
+static
+UINT32
+t_strncmp (
+ T_CHAR *Str1,
+ T_CHAR *Str2,
+ UINT32 Len
+ )
+{
+ while (Len > 0) {
+ if (*Str1 != *Str2) {
+ return Len;
+ }
+
+ Len--;
+ Str1++;
+ Str2++;
+ }
+
+ return 0;
+}
+
+static
+T_CHAR *
+t_strcpy (
+ T_CHAR *Dest,
+ T_CHAR *Src
+ )
+{
+ T_CHAR *SaveDest;
+ SaveDest = Dest;
+ while (*Src) {
+ *Dest = *Src;
+ Dest++;
+ Src++;
+ }
+
+ *Dest = 0;
+ return SaveDest;
+}
+
+#if 0
+static
+BOOLEAN
+IsValidIdentifierChar (
+ INT8 Char,
+ BOOLEAN FirstChar
+ )
+{
+ //
+ // If it's the first character of an identifier, then
+ // it must be one of [A-Za-z_].
+ //
+ if (FirstChar) {
+ if (isalpha (Char) || (Char == '_')) {
+ return TRUE;
+ }
+ } else {
+ //
+ // If it's not the first character, then it can
+ // be one of [A-Za-z_0-9]
+ //
+ if (isalnum (Char) || (Char == '_')) {
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+#endif
+static
+void
+RewindFile (
+ SOURCE_FILE *SourceFile
+ )
+{
+ SourceFile->LineNum = 1;
+ SourceFile->FileBufferPtr = SourceFile->FileBuffer;
+ SourceFile->EndOfFile = 0;
+}
+
+#if 0
+static
+BOOLEAN
+SkipTo (
+ SOURCE_FILE *SourceFile,
+ T_CHAR TChar,
+ BOOLEAN StopAfterNewline
+ )
+{
+ while (!EndOfFile (SourceFile)) {
+ //
+ // Check for the character of interest
+ //
+ if (SourceFile->FileBufferPtr[0] == TChar) {
+ return TRUE;
+ } else {
+ if (SourceFile->FileBufferPtr[0] == T_CHAR_LF) {
+ SourceFile->LineNum++;
+ if (StopAfterNewline) {
+ SourceFile->FileBufferPtr++;
+ if (SourceFile->FileBufferPtr[0] == 0) {
+ SourceFile->FileBufferPtr++;
+ }
+
+ return FALSE;
+ }
+ }
+
+ SourceFile->FileBufferPtr++;
+ }
+ }
+
+ return FALSE;
+}
+#endif
diff --git a/Source/GenFfsFile/build.xml b/Source/GenFfsFile/build.xml
new file mode 100644
index 0000000..71f8bc9
--- /dev/null
+++ b/Source/GenFfsFile/build.xml
@@ -0,0 +1,70 @@
+<?xml version="1.0" ?>
+<!--
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+-->
+<project default="GenTool" basedir=".">
+<!--
+ EDK GenFfsFile Tool
+ Copyright (c) 2006, Intel Corporation
+-->
+ <property name="ToolName" value="GenFfsFile"/>
+ <property name="FileSet" value="GenFfsFile.c"/>
+
+ <taskdef resource="net/sf/antcontrib/antlib.xml"/>
+
+ <property name="LINK_OUTPUT_TYPE" value="static"/>
+ <property name="BUILD_DIR" value="${PACKAGE_DIR}/${ToolName}/tmp"/>
+
+ <target name="GenTool" depends="init, Tool">
+ <echo message="The EDK Tool: ${ToolName} build has completed!"/>
+ </target>
+
+ <target name="init">
+ <echo message="Building the EDK Tool: ${ToolName}"/>
+ <mkdir dir="${BUILD_DIR}"/>
+ </target>
+
+ <target name="Tool" depends="init">
+ <cc name="${ToolChain}" objdir="${BUILD_DIR}"
+ outfile="${BIN_DIR}/${ToolName}"
+ outtype="executable"
+ debug="true"
+ optimize="speed">
+ <compilerarg value="${ExtraArgus}" if="ExtraArgus" />
+
+ <fileset dir="${basedir}/${ToolName}"
+ includes="${FileSet}"
+ defaultexcludes="TRUE"
+ excludes="*.xml *.inf"/>
+
+ <includepath path="${PACKAGE_DIR}/Include"/>
+ <includepath path="${PACKAGE_DIR}/Include/${HostArch}"/>
+ <includepath path="${PACKAGE_DIR}/Common"/>
+ <libset dir="${LIB_DIR}" libs="CommonTools CustomizedCompress"/>
+ </cc>
+ </target>
+
+ <target name="clean">
+ <echo message="Removing Intermediate Files Only"/>
+ <delete>
+ <fileset dir="${BUILD_DIR}" includes="*.obj"/>
+ </delete>
+ </target>
+
+ <target name="cleanall">
+ <echo message="Removing Object Files and the Executable: ${ToolName}${ext_exe}"/>
+ <delete failonerror="false" quiet="true" includeEmptyDirs="true">
+ <fileset dir="${BUILD_DIR}"/>
+ <fileset file="${BIN_DIR}/${ToolName}${ext_exe}"/>
+ <fileset file="${BIN_DIR}/${ToolName}.pdb"/>
+ </delete>
+ </target>
+
+</project>
diff --git a/Source/GenFvImage/Ebc/PeCoffLoaderEx.c b/Source/GenFvImage/Ebc/PeCoffLoaderEx.c
new file mode 100644
index 0000000..e8cf8b6
--- /dev/null
+++ b/Source/GenFvImage/Ebc/PeCoffLoaderEx.c
@@ -0,0 +1,57 @@
+/*++
+
+Copyright (c) 2004, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ PeCoffLoaderEx.c
+
+Abstract:
+
+ EBC Specific relocation fixups
+
+Revision History
+
+--*/
+
+
+
+
+RETURN_STATUS
+PeCoffLoaderRelocateImageEx (
+ IN UINT16 *Reloc,
+ IN OUT CHAR8 *Fixup,
+ IN OUT CHAR8 **FixupData,
+ IN UINT64 Adjust
+ )
+/*++
+
+Routine Description:
+
+ Performs an IA-32 specific relocation fixup
+
+Arguments:
+
+ Reloc - Pointer to the relocation record
+
+ Fixup - Pointer to the address to fix up
+
+ FixupData - Pointer to a buffer to log the fixups
+
+ Adjust - The offset to adjust the fixup
+
+Returns:
+
+ EFI_UNSUPPORTED - Unsupported now
+
+--*/
+{
+ return RETURN_UNSUPPORTED;
+}
diff --git a/Source/GenFvImage/GenFvImageExe.c b/Source/GenFvImage/GenFvImageExe.c
new file mode 100644
index 0000000..d0117b8
--- /dev/null
+++ b/Source/GenFvImage/GenFvImageExe.c
@@ -0,0 +1,299 @@
+/*++
+
+Copyright (c) 2004, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ GenFvImageExe.c
+
+Abstract:
+
+ This contains all code necessary to build the GenFvImage.exe utility.
+ This utility relies heavily on the GenFvImage Lib. Definitions for both
+ can be found in the Tiano Firmware Volume Generation Utility
+ Specification, review draft.
+
+--*/
+
+//
+// File included in build
+//
+#include "GenFvImageExe.h"
+#include "CommonLib.h"
+#include "EfiUtilityMsgs.h"
+
+VOID
+PrintUtilityInfo (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Displays the standard utility information to SDTOUT
+
+Arguments:
+
+ None
+
+Returns:
+
+ None
+
+--*/
+{
+ printf (
+ "%s - Tiano Firmware Volume Generation Utility."" Version %i.%i\n\n",
+ UTILITY_NAME,
+ UTILITY_MAJOR_VERSION,
+ UTILITY_MINOR_VERSION
+ );
+}
+
+VOID
+PrintUsage (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Displays the utility usage syntax to STDOUT
+
+Arguments:
+
+ None
+
+Returns:
+
+ None
+
+--*/
+{
+ printf ("Usage: %s -I FvInfFileName\n", UTILITY_NAME);
+ printf (" Where:\n");
+ printf ("\tFvInfFileName is the name of the image description file.\n\n");
+}
+
+int
+main (
+ IN INTN argc,
+ IN CHAR8 **argv
+ )
+/*++
+
+Routine Description:
+
+ This utility uses GenFvImage.Lib to build a firmware volume image.
+
+Arguments:
+
+ FvInfFileName The name of an FV image description file.
+
+ Arguments come in pair in any order.
+ -I FvInfFileName
+
+Returns:
+
+ EFI_SUCCESS No error conditions detected.
+ EFI_INVALID_PARAMETER One or more of the input parameters is invalid.
+ EFI_OUT_OF_RESOURCES A resource required by the utility was unavailable.
+ Most commonly this will be memory allocation
+ or file creation.
+ EFI_LOAD_ERROR GenFvImage.lib could not be loaded.
+ EFI_ABORTED Error executing the GenFvImage lib.
+
+--*/
+{
+ EFI_STATUS Status;
+ CHAR8 InfFileName[_MAX_PATH];
+ CHAR8 *InfFileImage;
+ UINTN InfFileSize;
+ UINT8 *FvImage;
+ UINTN FvImageSize;
+ UINT8 Index;
+ CHAR8 FvFileNameBuffer[_MAX_PATH];
+ CHAR8 *FvFileName;
+ FILE *FvFile;
+ FILE *SymFile;
+ CHAR8 SymFileNameBuffer[_MAX_PATH];
+ CHAR8 *SymFileName;
+ UINT8 *SymImage;
+ UINTN SymImageSize;
+ CHAR8 *CurrentSymString;
+
+ FvFileName = FvFileNameBuffer;
+ SymFileName = SymFileNameBuffer;
+
+ SetUtilityName (UTILITY_NAME);
+ //
+ // Display utility information
+ //
+ PrintUtilityInfo ();
+
+ //
+ // Verify the correct number of arguments
+ //
+ if (argc != MAX_ARGS) {
+ Error (NULL, 0, 0, "invalid number of input parameters specified", NULL);
+ PrintUsage ();
+ return GetUtilityStatus ();
+ }
+ //
+ // Initialize variables
+ //
+ strcpy (InfFileName, "");
+
+ //
+ // Parse the command line arguments
+ //
+ for (Index = 1; Index < MAX_ARGS; Index += 2) {
+ //
+ // Make sure argument pair begin with - or /
+ //
+ if (argv[Index][0] != '-' && argv[Index][0] != '/') {
+ Error (NULL, 0, 0, argv[Index], "argument pair must begin with \"-\" or \"/\"");
+ PrintUsage ();
+ return GetUtilityStatus ();
+ }
+ //
+ // Make sure argument specifier is only one letter
+ //
+ if (argv[Index][2] != 0) {
+ Error (NULL, 0, 0, argv[Index], "unrecognized argument");
+ PrintUsage ();
+ return GetUtilityStatus ();
+ }
+ //
+ // Determine argument to read
+ //
+ switch (argv[Index][1]) {
+
+ case 'I':
+ case 'i':
+ if (strlen (InfFileName) == 0) {
+ strcpy (InfFileName, argv[Index + 1]);
+ } else {
+ Error (NULL, 0, 0, argv[Index + 1], "FvInfFileName may only be specified once");
+ PrintUsage ();
+ return GetUtilityStatus ();
+ }
+ break;
+
+ default:
+ Error (NULL, 0, 0, argv[Index], "unrecognized argument");
+ PrintUsage ();
+ return GetUtilityStatus ();
+ break;
+ }
+ }
+ //
+ // Read the INF file image
+ //
+ Status = GetFileImage (InfFileName, &InfFileImage, &InfFileSize);
+ if (EFI_ERROR (Status)) {
+ return STATUS_ERROR;
+ }
+ //
+ // Call the GenFvImage lib
+ //
+ Status = GenerateFvImage (
+ InfFileImage,
+ InfFileSize,
+ &FvImage,
+ &FvImageSize,
+ &FvFileName,
+ &SymImage,
+ &SymImageSize,
+ &SymFileName
+ );
+
+ if (EFI_ERROR (Status)) {
+ switch (Status) {
+
+ case EFI_INVALID_PARAMETER:
+ Error (NULL, 0, 0, "invalid parameter passed to GenFvImage Lib", NULL);
+ return GetUtilityStatus ();
+ break;
+
+ case EFI_ABORTED:
+ Error (NULL, 0, 0, "error detected while creating the file image", NULL);
+ return GetUtilityStatus ();
+ break;
+
+ case EFI_OUT_OF_RESOURCES:
+ Error (NULL, 0, 0, "GenFvImage Lib could not allocate required resources", NULL);
+ return GetUtilityStatus ();
+ break;
+
+ case EFI_VOLUME_CORRUPTED:
+ Error (NULL, 0, 0, "no base address was specified, but the FV.INF included a PEI or BSF file", NULL);
+ return GetUtilityStatus ();
+ break;
+
+ case EFI_LOAD_ERROR:
+ Error (NULL, 0, 0, "could not load FV image generation library", NULL);
+ return GetUtilityStatus ();
+ break;
+
+ default:
+ Error (NULL, 0, 0, "GenFvImage Lib returned unknown status", "status returned = 0x%X", Status);
+ return GetUtilityStatus ();
+ break;
+ }
+ }
+ //
+ // Write file
+ //
+ FvFile = fopen (FvFileName, "wb");
+ if (FvFile == NULL) {
+ Error (NULL, 0, 0, FvFileName, "could not open output file");
+ free (FvImage);
+ free (SymImage);
+ return GetUtilityStatus ();
+ }
+
+ if (fwrite (FvImage, 1, FvImageSize, FvFile) != FvImageSize) {
+ Error (NULL, 0, 0, FvFileName, "failed to write to output file");
+ free (FvImage);
+ free (SymImage);
+ fclose (FvFile);
+ return GetUtilityStatus ();
+ }
+
+ fclose (FvFile);
+ free (FvImage);
+
+ //
+ // Write symbol file
+ //
+ if (strcmp (SymFileName, "")) {
+ SymFile = fopen (SymFileName, "wt");
+ if (SymFile == NULL) {
+ Error (NULL, 0, 0, SymFileName, "could not open output symbol file");
+ free (SymImage);
+ return GetUtilityStatus ();
+ }
+
+ fprintf (SymFile, "TEXTSYM format | V1.0\n");
+
+ CurrentSymString = SymImage;
+ while (((UINTN) CurrentSymString - (UINTN) SymImage) < SymImageSize) {
+ fprintf (SymFile, "%s", CurrentSymString);
+ CurrentSymString = (CHAR8 *) (((UINTN) CurrentSymString) + strlen (CurrentSymString) + 1);
+ }
+
+ fclose (SymFile);
+ }
+
+ free (SymImage);
+
+ return GetUtilityStatus ();
+}
diff --git a/Source/GenFvImage/GenFvImageExe.h b/Source/GenFvImage/GenFvImageExe.h
new file mode 100644
index 0000000..9b97935
--- /dev/null
+++ b/Source/GenFvImage/GenFvImageExe.h
@@ -0,0 +1,98 @@
+/*++
+
+Copyright (c) 2004, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ GenFvImageExe.h
+
+Abstract:
+
+ Definitions for the PeimFixup exe utility.
+
+--*/
+
+//
+// Coded to Tiano Coding Standards
+//
+#ifndef _EFI_GEN_FV_IMAGE_EXE_H
+#define _EFI_GEN_FV_IMAGE_EXE_H
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include "GenFvImageLib.h"
+
+//
+// Utility Name
+//
+#define UTILITY_NAME "GenFvImage"
+
+//
+// Utility version information
+//
+#define UTILITY_MAJOR_VERSION 0
+#define UTILITY_MINOR_VERSION 1
+#define UTILITY_DATE __DATE__
+
+//
+// The maximum number of arguments accepted from the command line.
+//
+#define MAX_ARGS 3
+
+//
+// The function that displays general utility information
+//
+VOID
+PrintUtilityInfo (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ None
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+//
+// The function that displays the utility usage message.
+//
+VOID
+PrintUsage (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ None
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+#endif
diff --git a/Source/GenFvImage/GenFvImageLib.c b/Source/GenFvImage/GenFvImageLib.c
new file mode 100644
index 0000000..eb36663
--- /dev/null
+++ b/Source/GenFvImage/GenFvImageLib.c
@@ -0,0 +1,2719 @@
+/*++
+i
+
+Copyright (c) 2004, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ GenFvImageLib.c
+
+Abstract:
+
+ This file contains functions required to generate a Firmware Volume.
+
+--*/
+
+//
+// Include files
+//
+#ifdef __GNUC__
+#include <uuid/uuid.h>
+#include <sys/stat.h>
+#endif
+#include <string.h>
+#ifndef __GNUC__
+#include <io.h>
+#endif
+#include <assert.h>
+
+#include <Common/UefiBaseTypes.h>
+#include <Common/FirmwareVolumeImageFormat.h>
+#include <Common/Variable.h>
+#include <Common/WorkingBlockHeader.h>
+#include <Guid/FirmwareFileSystem.h>
+
+#include "GenFvImageLib.h"
+#include "GenFvImageLibInternal.h"
+#include "CommonLib.h"
+#include "Crc32.h"
+#include "EfiUtilityMsgs.h"
+#include "FvLib.h"
+#include "EfiCompress.h"
+#include "WinNtInclude.h"
+
+
+//
+// Local function prototypes
+//
+EFI_STATUS
+GetPe32Info (
+ IN UINT8 *Pe32,
+ OUT UINT32 *EntryPoint,
+ OUT UINT32 *BaseOfCode,
+ OUT UINT16 *MachineType
+ );
+
+//
+// Local function implementations.
+//
+EFI_GUID FfsGuid = EFI_FIRMWARE_FILE_SYSTEM_GUID;
+EFI_GUID DefaultFvPadFileNameGuid = { 0x78f54d4, 0xcc22, 0x4048, 0x9e, 0x94, 0x87, 0x9c, 0x21, 0x4d, 0x56, 0x2f };
+
+//
+// This data array will be located at the base of the Firmware Volume Header (FVH)
+// in the boot block. It must not exceed 14 bytes of code. The last 2 bytes
+// will be used to keep the FVH checksum consistent.
+// This code will be run in response to a starutp IPI for HT-enabled systems.
+//
+#define SIZEOF_STARTUP_DATA_ARRAY 0x10
+
+UINT8 m128kRecoveryStartupApDataArray[SIZEOF_STARTUP_DATA_ARRAY] = {
+ //
+ // EA D0 FF 00 F0 ; far jmp F000:FFD0
+ // 0, 0, 0, 0, 0, 0, 0, 0, 0, ; Reserved bytes
+ // 0, 0 ; Checksum Padding
+ //
+ 0xEA,
+ 0xD0,
+ 0xFF,
+ 0x0,
+ 0xF0,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00
+};
+
+UINT8 m64kRecoveryStartupApDataArray[SIZEOF_STARTUP_DATA_ARRAY] = {
+ //
+ // EB CE ; jmp short ($-0x30)
+ // ; (from offset 0x0 to offset 0xFFD0)
+ // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ; Reserved bytes
+ // 0, 0 ; Checksum Padding
+ //
+ 0xEB,
+ 0xCE,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00
+};
+
+EFI_STATUS
+ParseFvInf (
+ IN MEMORY_FILE *InfFile,
+ IN FV_INFO *FvInfo
+ )
+/*++
+
+Routine Description:
+
+ This function parses a FV.INF file and copies info into a FV_INFO structure.
+
+Arguments:
+
+ InfFile Memory file image.
+ FvInfo Information read from INF file.
+
+Returns:
+
+ EFI_SUCCESS INF file information successfully retrieved.
+ EFI_ABORTED INF file has an invalid format.
+ EFI_NOT_FOUND A required string was not found in the INF file.
+--*/
+{
+ CHAR8 Value[_MAX_PATH];
+ UINT64 Value64;
+ UINTN Index;
+ EFI_STATUS Status;
+
+ //
+ // Initialize FV info
+ //
+ memset (FvInfo, 0, sizeof (FV_INFO));
+
+ //
+ // Read the FV base address
+ //
+ Status = FindToken (InfFile, OPTIONS_SECTION_STRING, EFI_FV_BASE_ADDRESS_STRING, 0, Value);
+
+ if (Status == EFI_SUCCESS) {
+ //
+ // Get the base address
+ //
+ Status = AsciiStringToUint64 (Value, FALSE, &Value64);
+ if (EFI_ERROR (Status)) {
+ Error (NULL, 0, 0, EFI_FV_BASE_ADDRESS_STRING, "invalid value");
+ return EFI_ABORTED;
+ }
+
+ FvInfo->BaseAddress = Value64;
+ } else {
+ Error (NULL, 0, 0, EFI_FV_BASE_ADDRESS_STRING, "could not find value");
+ return EFI_ABORTED;
+ }
+ //
+ // Read the FV Guid
+ //
+ Status = FindToken (InfFile, OPTIONS_SECTION_STRING, EFI_FV_GUID_STRING, 0, Value);
+
+ if (Status == EFI_SUCCESS) {
+ //
+ // Get the guid value
+ //
+ Status = StringToGuid (Value, &FvInfo->FvGuid);
+ if (EFI_ERROR (Status)) {
+ memcpy (&FvInfo->FvGuid, &FfsGuid, sizeof (EFI_GUID));
+ }
+ } else {
+ memcpy (&FvInfo->FvGuid, &FfsGuid, sizeof (EFI_GUID));
+ }
+ //
+ // Read the FV file name
+ //
+ Status = FindToken (InfFile, OPTIONS_SECTION_STRING, EFI_FV_FILE_NAME_STRING, 0, Value);
+
+ if (Status == EFI_SUCCESS) {
+ //
+ // copy the file name
+ //
+ strcpy (FvInfo->FvName, Value);
+ } else {
+ Error (NULL, 0, 0, EFI_FV_FILE_NAME_STRING, "value not specified");
+ return EFI_ABORTED;
+ }
+ //
+ // Read the Sym file name
+ //
+ Status = FindToken (InfFile, OPTIONS_SECTION_STRING, EFI_SYM_FILE_NAME_STRING, 0, Value);
+
+ if (Status == EFI_SUCCESS) {
+ //
+ // copy the file name
+ //
+ strcpy (FvInfo->SymName, Value);
+ } else {
+ //
+ // Symbols not required, so init to NULL.
+ //
+ strcpy (FvInfo->SymName, "");
+ }
+ //
+ // Read the read disabled capability attribute
+ //
+ Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_READ_DISABLED_CAP_STRING, 0, Value);
+
+ if (Status == EFI_SUCCESS) {
+ //
+ // Update the read disabled flag
+ //
+ if (strcmp (Value, TRUE_STRING) == 0) {
+ FvInfo->FvAttributes |= EFI_FVB_READ_DISABLED_CAP;
+ } else if (strcmp (Value, FALSE_STRING) != 0) {
+ Error (NULL, 0, 0, EFI_FVB_READ_DISABLED_CAP_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
+ return EFI_ABORTED;
+ }
+ } else {
+ Error (NULL, 0, 0, EFI_FVB_READ_DISABLED_CAP_STRING, "value not specified");
+ return Status;
+ }
+ //
+ // Read the read enabled capability attribute
+ //
+ Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_READ_ENABLED_CAP_STRING, 0, Value);
+
+ if (Status == EFI_SUCCESS) {
+ //
+ // Update the read disabled flag
+ //
+ if (strcmp (Value, TRUE_STRING) == 0) {
+ FvInfo->FvAttributes |= EFI_FVB_READ_ENABLED_CAP;
+ } else if (strcmp (Value, FALSE_STRING) != 0) {
+ Error (NULL, 0, 0, EFI_FVB_READ_ENABLED_CAP_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
+ return EFI_ABORTED;
+ }
+ } else {
+ Error (NULL, 0, 0, EFI_FVB_READ_ENABLED_CAP_STRING, "value not specified");
+ return Status;
+ }
+ //
+ // Read the read status attribute
+ //
+ Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_READ_STATUS_STRING, 0, Value);
+
+ if (Status == EFI_SUCCESS) {
+ //
+ // Update the read disabled flag
+ //
+ if (strcmp (Value, TRUE_STRING) == 0) {
+ FvInfo->FvAttributes |= EFI_FVB_READ_STATUS;
+ } else if (strcmp (Value, FALSE_STRING) != 0) {
+ Error (NULL, 0, 0, EFI_FVB_READ_STATUS_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
+ return EFI_ABORTED;
+ }
+ } else {
+ Error (NULL, 0, 0, EFI_FVB_READ_STATUS_STRING, "value not specified");
+ return Status;
+ }
+ //
+ // Read the write disabled capability attribute
+ //
+ Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_WRITE_DISABLED_CAP_STRING, 0, Value);
+
+ if (Status == EFI_SUCCESS) {
+ //
+ // Update the write disabled flag
+ //
+ if (strcmp (Value, TRUE_STRING) == 0) {
+ FvInfo->FvAttributes |= EFI_FVB_WRITE_DISABLED_CAP;
+ } else if (strcmp (Value, FALSE_STRING) != 0) {
+ Error (NULL, 0, 0, EFI_FVB_WRITE_DISABLED_CAP_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
+ return EFI_ABORTED;
+ }
+ } else {
+ Error (NULL, 0, 0, EFI_FVB_WRITE_DISABLED_CAP_STRING, "value not specified");
+ return Status;
+ }
+ //
+ // Read the write enabled capability attribute
+ //
+ Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_WRITE_ENABLED_CAP_STRING, 0, Value);
+
+ if (Status == EFI_SUCCESS) {
+ //
+ // Update the write disabled flag
+ //
+ if (strcmp (Value, TRUE_STRING) == 0) {
+ FvInfo->FvAttributes |= EFI_FVB_WRITE_ENABLED_CAP;
+ } else if (strcmp (Value, FALSE_STRING) != 0) {
+ Error (NULL, 0, 0, EFI_FVB_WRITE_ENABLED_CAP_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
+ return EFI_ABORTED;
+ }
+ } else {
+ Error (NULL, 0, 0, EFI_FVB_WRITE_ENABLED_CAP_STRING, "value not specified");
+ return Status;
+ }
+ //
+ // Read the write status attribute
+ //
+ Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_WRITE_STATUS_STRING, 0, Value);
+
+ if (Status == EFI_SUCCESS) {
+ //
+ // Update the write disabled flag
+ //
+ if (strcmp (Value, TRUE_STRING) == 0) {
+ FvInfo->FvAttributes |= EFI_FVB_WRITE_STATUS;
+ } else if (strcmp (Value, FALSE_STRING) != 0) {
+ Error (NULL, 0, 0, EFI_FVB_WRITE_STATUS_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
+ return EFI_ABORTED;
+ }
+ } else {
+ Error (NULL, 0, 0, EFI_FVB_WRITE_STATUS_STRING, "value not specified");
+ return Status;
+ }
+ //
+ // Read the lock capability attribute
+ //
+ Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_LOCK_CAP_STRING, 0, Value);
+
+ if (Status == EFI_SUCCESS) {
+ //
+ // Update the attribute flag
+ //
+ if (strcmp (Value, TRUE_STRING) == 0) {
+ FvInfo->FvAttributes |= EFI_FVB_LOCK_CAP;
+ } else if (strcmp (Value, FALSE_STRING) != 0) {
+ Error (NULL, 0, 0, EFI_FVB_LOCK_CAP_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
+ return EFI_ABORTED;
+ }
+ } else {
+ Error (NULL, 0, 0, EFI_FVB_LOCK_CAP_STRING, "value not specified");
+ return Status;
+ }
+ //
+ // Read the lock status attribute
+ //
+ Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_LOCK_STATUS_STRING, 0, Value);
+
+ if (Status == EFI_SUCCESS) {
+ //
+ // Update the attribute flag
+ //
+ if (strcmp (Value, TRUE_STRING) == 0) {
+ FvInfo->FvAttributes |= EFI_FVB_LOCK_STATUS;
+ } else if (strcmp (Value, FALSE_STRING) != 0) {
+ Error (NULL, 0, 0, EFI_FVB_LOCK_STATUS_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
+ return EFI_ABORTED;
+ }
+ } else {
+ Error (NULL, 0, 0, EFI_FVB_LOCK_STATUS_STRING, "value not specified");
+ return Status;
+ }
+ //
+ // Read the sticky write attribute
+ //
+ Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_STICKY_WRITE_STRING, 0, Value);
+
+ if (Status == EFI_SUCCESS) {
+ //
+ // Update the attribute flag
+ //
+ if (strcmp (Value, TRUE_STRING) == 0) {
+ FvInfo->FvAttributes |= EFI_FVB_STICKY_WRITE;
+ } else if (strcmp (Value, FALSE_STRING) != 0) {
+ Error (NULL, 0, 0, EFI_FVB_STICKY_WRITE_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
+ return EFI_ABORTED;
+ }
+ } else {
+ Error (NULL, 0, 0, EFI_FVB_STICKY_WRITE_STRING, "value not specified");
+ return Status;
+ }
+ //
+ // Read the memory mapped attribute
+ //
+ Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_MEMORY_MAPPED_STRING, 0, Value);
+
+ if (Status == EFI_SUCCESS) {
+ //
+ // Update the attribute flag
+ //
+ if (strcmp (Value, TRUE_STRING) == 0) {
+ FvInfo->FvAttributes |= EFI_FVB_MEMORY_MAPPED;
+ } else if (strcmp (Value, FALSE_STRING) != 0) {
+ Error (NULL, 0, 0, EFI_FVB_MEMORY_MAPPED_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
+ return EFI_ABORTED;
+ }
+ } else {
+ Error (NULL, 0, 0, EFI_FVB_MEMORY_MAPPED_STRING, "value not specified");
+ return Status;
+ }
+ //
+ // Read the erase polarity attribute
+ //
+ Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ERASE_POLARITY_STRING, 0, Value);
+
+ if (Status == EFI_SUCCESS) {
+ //
+ // Update the attribute flag
+ //
+ if (strcmp (Value, ONE_STRING) == 0) {
+ FvInfo->FvAttributes |= EFI_FVB_ERASE_POLARITY;
+ } else if (strcmp (Value, ZERO_STRING) != 0) {
+ Error (NULL, 0, 0, EFI_FVB_ERASE_POLARITY_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
+ return EFI_ABORTED;
+ }
+ } else {
+ Error (NULL, 0, 0, EFI_FVB_ERASE_POLARITY_STRING, "value not specified");
+ return Status;
+ }
+ //
+ // Read the alignment capabilities attribute
+ //
+ Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_CAP_STRING, 0, Value);
+
+ if (Status == EFI_SUCCESS) {
+ //
+ // Update attribute
+ //
+ if (strcmp (Value, TRUE_STRING) == 0) {
+ FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_CAP;
+ } else if (strcmp (Value, FALSE_STRING) != 0) {
+ Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_CAP_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
+ return EFI_ABORTED;
+ }
+ } else {
+ Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_CAP_STRING, "value not specified");
+ return Status;
+ }
+ //
+ // Read the word alignment capability attribute
+ //
+ Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_2_STRING, 0, Value);
+
+ if (Status == EFI_SUCCESS) {
+ //
+ // Update attribute
+ //
+ if (strcmp (Value, TRUE_STRING) == 0) {
+ FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_2;
+ } else if (strcmp (Value, FALSE_STRING) != 0) {
+ Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_2_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
+ return EFI_ABORTED;
+ }
+ } else {
+ Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_2_STRING, "value not specified");
+ return Status;
+ }
+ //
+ // Read the dword alignment capability attribute
+ //
+ Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_4_STRING, 0, Value);
+
+ if (Status == EFI_SUCCESS) {
+ //
+ // Update attribute
+ //
+ if (strcmp (Value, TRUE_STRING) == 0) {
+ FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_4;
+ } else if (strcmp (Value, FALSE_STRING) != 0) {
+ Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_4_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
+ return EFI_ABORTED;
+ }
+ } else {
+ Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_4_STRING, "value not specified");
+ return Status;
+ }
+ //
+ // Read the word alignment capability attribute
+ //
+ Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_8_STRING, 0, Value);
+
+ if (Status == EFI_SUCCESS) {
+ //
+ // Update attribute
+ //
+ if (strcmp (Value, TRUE_STRING) == 0) {
+ FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_8;
+ } else if (strcmp (Value, FALSE_STRING) != 0) {
+ Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_8_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
+ return EFI_ABORTED;
+ }
+ } else {
+ Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_8_STRING, "value not specified");
+ return Status;
+ }
+ //
+ // Read the qword alignment capability attribute
+ //
+ Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_16_STRING, 0, Value);
+
+ if (Status == EFI_SUCCESS) {
+ //
+ // Update attribute
+ //
+ if (strcmp (Value, TRUE_STRING) == 0) {
+ FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_16;
+ } else if (strcmp (Value, FALSE_STRING) != 0) {
+ Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_16_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
+ return EFI_ABORTED;
+ }
+ } else {
+ Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_16_STRING, "value not specified");
+ return Status;
+ }
+ //
+ // Read the 32 byte alignment capability attribute
+ //
+ Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_32_STRING, 0, Value);
+
+ if (Status == EFI_SUCCESS) {
+ //
+ // Update attribute
+ //
+ if (strcmp (Value, TRUE_STRING) == 0) {
+ FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_32;
+ } else if (strcmp (Value, FALSE_STRING) != 0) {
+ Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_32_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
+ return EFI_ABORTED;
+ }
+ } else {
+ Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_32_STRING, "value not specified");
+ return Status;
+ }
+ //
+ // Read the 64 byte alignment capability attribute
+ //
+ Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_64_STRING, 0, Value);
+
+ if (Status == EFI_SUCCESS) {
+ //
+ // Update attribute
+ //
+ if (strcmp (Value, TRUE_STRING) == 0) {
+ FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_64;
+ } else if (strcmp (Value, FALSE_STRING) != 0) {
+ Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_64_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
+ return EFI_ABORTED;
+ }
+ } else {
+ Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_64_STRING, "value not specified");
+ return Status;
+ }
+ //
+ // Read the 128 byte alignment capability attribute
+ //
+ Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_128_STRING, 0, Value);
+
+ if (Status == EFI_SUCCESS) {
+ //
+ // Update attribute
+ //
+ if (strcmp (Value, TRUE_STRING) == 0) {
+ FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_128;
+ } else if (strcmp (Value, FALSE_STRING) != 0) {
+ Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_128_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
+ return EFI_ABORTED;
+ }
+ } else {
+ Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_128_STRING, "value not specified");
+ return Status;
+ }
+ //
+ // Read the 256 byte alignment capability attribute
+ //
+ Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_256_STRING, 0, Value);
+
+ if (Status == EFI_SUCCESS) {
+ //
+ // Update attribute
+ //
+ if (strcmp (Value, TRUE_STRING) == 0) {
+ FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_256;
+ } else if (strcmp (Value, FALSE_STRING) != 0) {
+ Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_256_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
+ return EFI_ABORTED;
+ }
+ } else {
+ Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_256_STRING, "value not specified");
+ return Status;
+ }
+ //
+ // Read the 512 byte alignment capability attribute
+ //
+ Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_512_STRING, 0, Value);
+
+ if (Status == EFI_SUCCESS) {
+ //
+ // Update attribute
+ //
+ if (strcmp (Value, TRUE_STRING) == 0) {
+ FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_512;
+ } else if (strcmp (Value, FALSE_STRING) != 0) {
+ Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_512_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
+ return EFI_ABORTED;
+ }
+ } else {
+ Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_512_STRING, "value not specified");
+ return Status;
+ }
+ //
+ // Read the 1K byte alignment capability attribute
+ //
+ Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_1K_STRING, 0, Value);
+
+ if (Status == EFI_SUCCESS) {
+ //
+ // Update attribute
+ //
+ if (strcmp (Value, TRUE_STRING) == 0) {
+ FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_1K;
+ } else if (strcmp (Value, FALSE_STRING) != 0) {
+ Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_1K_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
+ return EFI_ABORTED;
+ }
+ } else {
+ Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_1K_STRING, "value not specified");
+ return Status;
+ }
+ //
+ // Read the 2K byte alignment capability attribute
+ //
+ Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_2K_STRING, 0, Value);
+
+ if (Status == EFI_SUCCESS) {
+ //
+ // Update attribute
+ //
+ if (strcmp (Value, TRUE_STRING) == 0) {
+ FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_2K;
+ } else if (strcmp (Value, FALSE_STRING) != 0) {
+ Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_2K_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
+ return EFI_ABORTED;
+ }
+ } else {
+ Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_2K_STRING, "value not specified");
+ return Status;
+ }
+ //
+ // Read the 4K byte alignment capability attribute
+ //
+ Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_4K_STRING, 0, Value);
+
+ if (Status == EFI_SUCCESS) {
+ //
+ // Update attribute
+ //
+ if (strcmp (Value, TRUE_STRING) == 0) {
+ FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_4K;
+ } else if (strcmp (Value, FALSE_STRING) != 0) {
+ Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_4K_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
+ return EFI_ABORTED;
+ }
+ } else {
+ Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_4K_STRING, "value not specified");
+ return Status;
+ }
+ //
+ // Read the 8K byte alignment capability attribute
+ //
+ Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_8K_STRING, 0, Value);
+
+ if (Status == EFI_SUCCESS) {
+ //
+ // Update attribute
+ //
+ if (strcmp (Value, TRUE_STRING) == 0) {
+ FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_8K;
+ } else if (strcmp (Value, FALSE_STRING) != 0) {
+ Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_8K_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
+ return EFI_ABORTED;
+ }
+ } else {
+ Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_8K_STRING, "value not specified");
+ return Status;
+ }
+ //
+ // Read the 16K byte alignment capability attribute
+ //
+ Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_16K_STRING, 0, Value);
+
+ if (Status == EFI_SUCCESS) {
+ //
+ // Update attribute
+ //
+ if (strcmp (Value, TRUE_STRING) == 0) {
+ FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_16K;
+ } else if (strcmp (Value, FALSE_STRING) != 0) {
+ Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_16K_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
+ return EFI_ABORTED;
+ }
+ } else {
+ Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_16K_STRING, "value not specified");
+ return Status;
+ }
+ //
+ // Read the 32K byte alignment capability attribute
+ //
+ Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_32K_STRING, 0, Value);
+
+ if (Status == EFI_SUCCESS) {
+ //
+ // Update attribute
+ //
+ if (strcmp (Value, TRUE_STRING) == 0) {
+ FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_32K;
+ } else if (strcmp (Value, FALSE_STRING) != 0) {
+ Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_32K_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
+ return EFI_ABORTED;
+ }
+ } else {
+ Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_32K_STRING, "value not specified");
+ return Status;
+ }
+ //
+ // Read the 64K byte alignment capability attribute
+ //
+ Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_64K_STRING, 0, Value);
+
+ if (Status == EFI_SUCCESS) {
+ //
+ // Update attribute
+ //
+ if (strcmp (Value, TRUE_STRING) == 0) {
+ FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_64K;
+ } else if (strcmp (Value, FALSE_STRING) != 0) {
+ Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_64K_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
+ return EFI_ABORTED;
+ }
+ } else {
+ Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_64K_STRING, "value not specified");
+ return Status;
+ }
+
+ if (!(FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_CAP) &&
+ (
+ (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_2) ||
+ (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_4) ||
+ (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_8) ||
+ (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_16) ||
+ (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_32) ||
+ (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_64) ||
+ (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_128) ||
+ (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_256) ||
+ (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_512) ||
+ (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_1K) ||
+ (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_2K) ||
+ (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_4K) ||
+ (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_8K) ||
+ (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_16K) ||
+ (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_32K) ||
+ (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_64K)
+ )
+ ) {
+ Error (
+ NULL,
+ 0,
+ 0,
+ "illegal combination of alignment attributes",
+ "if %s is not %s, no individual alignments can be %s",
+ EFI_FVB_ALIGNMENT_CAP_STRING,
+ TRUE_STRING,
+ TRUE_STRING
+ );
+ return EFI_ABORTED;
+ }
+ //
+ // Read block maps
+ //
+ for (Index = 0; Index < MAX_NUMBER_OF_FV_BLOCKS; Index++) {
+ //
+ // Read the number of blocks
+ //
+ Status = FindToken (InfFile, OPTIONS_SECTION_STRING, EFI_NUM_BLOCKS_STRING, Index, Value);
+
+ if (Status == EFI_SUCCESS) {
+ //
+ // Update the number of blocks
+ //
+ Status = AsciiStringToUint64 (Value, FALSE, &Value64);
+ if (EFI_ERROR (Status)) {
+ Error (NULL, 0, 0, Value, "invalid value for %s", EFI_NUM_BLOCKS_STRING);
+ return EFI_ABORTED;
+ }
+
+ FvInfo->FvBlocks[Index].NumBlocks = (UINT32) Value64;
+ } else {
+ //
+ // If there is no number of blocks, but there is a size, then we have a mismatched pair
+ // and should return an error.
+ //
+ Status = FindToken (InfFile, OPTIONS_SECTION_STRING, EFI_BLOCK_SIZE_STRING, Index, Value);
+ if (!EFI_ERROR (Status)) {
+ Error (NULL, 0, 0, "must specify both", "%s and %s", EFI_NUM_BLOCKS_STRING, EFI_BLOCK_SIZE_STRING);
+ return EFI_ABORTED;
+ } else {
+ //
+ // We are done
+ //
+ break;
+ }
+ }
+ //
+ // Read the size of blocks
+ //
+ Status = FindToken (InfFile, OPTIONS_SECTION_STRING, EFI_BLOCK_SIZE_STRING, Index, Value);
+
+ if (Status == EFI_SUCCESS) {
+ //
+ // Update the number of blocks
+ //
+ Status = AsciiStringToUint64 (Value, FALSE, &Value64);
+ if (EFI_ERROR (Status)) {
+ Error (NULL, 0, 0, Value, "invalid value specified for %s", EFI_BLOCK_SIZE_STRING);
+ return EFI_ABORTED;
+ }
+
+ FvInfo->FvBlocks[Index].BlockLength = (UINT32) Value64;
+ } else {
+ //
+ // There is a number of blocks, but there is no size, so we have a mismatched pair
+ // and should return an error.
+ //
+ Error (NULL, 0, 0, "must specify both", "%s and %s", EFI_NUM_BLOCKS_STRING, EFI_BLOCK_SIZE_STRING);
+ return EFI_ABORTED;
+ }
+ }
+ //
+ // Read files
+ //
+ for (Index = 0; Index < MAX_NUMBER_OF_FILES_IN_FV; Index++) {
+ //
+ // Read the number of blocks
+ //
+ Status = FindToken (InfFile, FILES_SECTION_STRING, EFI_FILE_NAME_STRING, Index, Value);
+
+ if (Status == EFI_SUCCESS) {
+ //
+ // Add the file
+ //
+ strcpy (FvInfo->FvFiles[Index], Value);
+ } else {
+ break;
+ }
+ }
+
+ if (FindSection (InfFile, COMPONENT_SECTION_STRING)) {
+ Index = 0;
+ //
+ // Read component FV_VARIABLE
+ //
+ Status = FindToken (InfFile, COMPONENT_SECTION_STRING, EFI_NV_VARIABLE_STRING, 0, Value);
+
+ if (Status == EFI_SUCCESS) {
+ //
+ // Add the component
+ //
+ strcpy (FvInfo->FvComponents[Index].ComponentName, EFI_NV_VARIABLE_STRING);
+ Status = AsciiStringToUint64 (Value, FALSE, &Value64);
+ if (EFI_ERROR (Status)) {
+ printf ("ERROR: %s is not a valid integer.\n", EFI_NV_VARIABLE_STRING);
+ return EFI_ABORTED;
+ }
+
+ FvInfo->FvComponents[Index].Size = (UINTN) Value64;
+ } else {
+ printf ("WARNING: Could not read %s.\n", EFI_NV_VARIABLE_STRING);
+ }
+
+ Index++;
+ //
+ // Read component FV_EVENT_LOG
+ //
+ Status = FindToken (InfFile, COMPONENT_SECTION_STRING, EFI_NV_EVENT_LOG_STRING, 0, Value);
+
+ if (Status == EFI_SUCCESS) {
+ //
+ // Add the component
+ //
+ strcpy (FvInfo->FvComponents[Index].ComponentName, EFI_NV_EVENT_LOG_STRING);
+ Status = AsciiStringToUint64 (Value, FALSE, &Value64);
+ if (EFI_ERROR (Status)) {
+ printf ("ERROR: %s is not a valid integer.\n", EFI_NV_EVENT_LOG_STRING);
+ return EFI_ABORTED;
+ }
+
+ FvInfo->FvComponents[Index].Size = (UINTN) Value64;
+ } else {
+ printf ("WARNING: Could not read %s.\n", EFI_NV_EVENT_LOG_STRING);
+ }
+
+ Index++;
+ //
+ // Read component FV_FTW_WORKING
+ //
+ Status = FindToken (InfFile, COMPONENT_SECTION_STRING, EFI_NV_FTW_WORKING_STRING, 0, Value);
+
+ if (Status == EFI_SUCCESS) {
+ //
+ // Add the component
+ //
+ strcpy (FvInfo->FvComponents[Index].ComponentName, EFI_NV_FTW_WORKING_STRING);
+ Status = AsciiStringToUint64 (Value, FALSE, &Value64);
+ if (EFI_ERROR (Status)) {
+ printf ("ERROR: %s is not a valid integer.\n", EFI_NV_FTW_WORKING_STRING);
+ return EFI_ABORTED;
+ }
+
+ FvInfo->FvComponents[Index].Size = (UINTN) Value64;
+ } else {
+ printf ("WARNING: Could not read %s.\n", EFI_NV_FTW_WORKING_STRING);
+ }
+
+ Index++;
+ //
+ // Read component FV_FTW_SPARE
+ //
+ Status = FindToken (InfFile, COMPONENT_SECTION_STRING, EFI_NV_FTW_SPARE_STRING, 0, Value);
+
+ if (Status == EFI_SUCCESS) {
+ //
+ // Add the component
+ //
+ strcpy (FvInfo->FvComponents[Index].ComponentName, EFI_NV_FTW_SPARE_STRING);
+ Status = AsciiStringToUint64 (Value, FALSE, &Value64);
+ if (EFI_ERROR (Status)) {
+ printf ("ERROR: %s is not a valid integer.\n", EFI_NV_FTW_SPARE_STRING);
+ return EFI_ABORTED;
+ }
+
+ FvInfo->FvComponents[Index].Size = (UINTN) Value64;
+ } else {
+ printf ("WARNING: Could not read %s.\n", EFI_NV_FTW_SPARE_STRING);
+ }
+ }
+ //
+ // Compute size for easy access later
+ //
+ FvInfo->Size = 0;
+ for (Index = 0; FvInfo->FvBlocks[Index].NumBlocks; Index++) {
+ FvInfo->Size += FvInfo->FvBlocks[Index].NumBlocks * FvInfo->FvBlocks[Index].BlockLength;
+ }
+
+ return EFI_SUCCESS;
+}
+
+VOID
+UpdateFfsFileState (
+ IN EFI_FFS_FILE_HEADER *FfsFile,
+ IN EFI_FIRMWARE_VOLUME_HEADER *FvHeader
+ )
+/*++
+
+Routine Description:
+
+ This function changes the FFS file attributes based on the erase polarity
+ of the FV.
+
+Arguments:
+
+ FfsFile File header.
+ FvHeader FV header.
+
+Returns:
+
+ None
+
+--*/
+{
+ if (FvHeader->Attributes & EFI_FVB_ERASE_POLARITY) {
+ FfsFile->State = (UINT8)~(FfsFile->State);
+ }
+}
+
+EFI_STATUS
+ReadFfsAlignment (
+ IN EFI_FFS_FILE_HEADER *FfsFile,
+ IN OUT UINT32 *Alignment
+ )
+/*++
+
+Routine Description:
+
+ This function determines the alignment of the FFS input file from the file
+ attributes.
+
+Arguments:
+
+ FfsFile FFS file to parse
+ Alignment The minimum required alignment of the FFS file, in bytes
+
+Returns:
+
+ EFI_SUCCESS The function completed successfully.
+ EFI_INVALID_PARAMETER One of the input parameters was invalid.
+ EFI_ABORTED An error occurred.
+
+--*/
+{
+ //
+ // Verify input parameters.
+ //
+ if (FfsFile == NULL || Alignment == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ switch ((FfsFile->Attributes >> 3) & 0x07) {
+
+ case 0:
+ //
+ // 1 byte alignment
+ //
+ *Alignment = (1 << 0);
+ break;
+
+ case 1:
+ //
+ // 16 byte alignment
+ //
+ *Alignment = (1 << 4);
+ break;
+
+ case 2:
+ //
+ // 128 byte alignment
+ //
+ *Alignment = (1 << 7);
+ break;
+
+ case 3:
+ //
+ // 512 byte alignment
+ //
+ *Alignment = (1 << 9);
+ break;
+
+ case 4:
+ //
+ // 1K byte alignment
+ //
+ *Alignment = (1 << 10);
+ break;
+
+ case 5:
+ //
+ // 4K byte alignment
+ //
+ *Alignment = (1 << 12);
+ break;
+
+ case 6:
+ //
+ // 32K byte alignment
+ //
+ *Alignment = (1 << 15);
+ break;
+
+ case 7:
+ //
+ // 64K byte alignment
+ //
+ *Alignment = (1 << 16);
+ break;
+
+ default:
+ Error (NULL, 0, 0, "nvalid file attribute calculated, this is most likely a utility error", NULL);
+ return EFI_ABORTED;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+AddPadFile (
+ IN OUT MEMORY_FILE *FvImage,
+ IN UINT32 DataAlignment
+ )
+/*++
+
+Routine Description:
+
+ This function adds a pad file to the FV image if it required to align the
+ data of the next file.
+
+Arguments:
+
+ FvImage The memory image of the FV to add it to. The current offset
+ must be valid.
+ DataAlignment The data alignment of the next FFS file.
+
+Returns:
+
+ EFI_SUCCESS The function completed successfully.
+ EFI_INVALID_PARAMETER One of the input parameters was invalid.
+ EFI_OUT_OF_RESOURCES Insufficient resources exist in the FV to complete
+ the pad file add.
+
+--*/
+{
+ EFI_FFS_FILE_HEADER *PadFile;
+ EFI_GUID PadFileGuid;
+ UINTN PadFileSize;
+
+ //
+ // Verify input parameters.
+ //
+ if (FvImage == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // Basic assumption is we start from an 8 byte aligned address
+ // and our file header is a multiple of 8 bytes
+ //
+ assert ((UINTN) FvImage->CurrentFilePointer % 8 == 0);
+ assert (sizeof (EFI_FFS_FILE_HEADER) % 8 == 0);
+
+ //
+ // Check if a pad file is necessary
+ //
+ if (((UINTN) FvImage->CurrentFilePointer - (UINTN) FvImage->FileImage + sizeof (EFI_FFS_FILE_HEADER)) % DataAlignment == 0) {
+ return EFI_SUCCESS;
+ }
+ //
+ // Write pad file header
+ //
+ PadFile = (EFI_FFS_FILE_HEADER *) FvImage->CurrentFilePointer;
+
+ //
+ // Verify that we have enough space for the file header
+ //
+ if ((UINTN) (PadFile + sizeof (EFI_FFS_FILE_HEADER)) >= (UINTN) FvImage->Eof) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+#ifdef __GNUC__
+ {
+ uuid_t tmp_id;
+ uuid_generate (tmp_id);
+ memcpy (&PadFileGuid, tmp_id, sizeof (EFI_GUID));
+ }
+#else
+ UuidCreate (&PadFileGuid);
+#endif
+ memset (PadFile, 0, sizeof (EFI_FFS_FILE_HEADER));
+ memcpy (&PadFile->Name, &PadFileGuid, sizeof (EFI_GUID));
+ PadFile->Type = EFI_FV_FILETYPE_FFS_PAD;
+ PadFile->Attributes = 0;
+
+ //
+ // Calculate the pad file size
+ //
+ //
+ // This is the earliest possible valid offset (current plus pad file header
+ // plus the next file header)
+ //
+ PadFileSize = (UINTN) FvImage->CurrentFilePointer - (UINTN) FvImage->FileImage + (sizeof (EFI_FFS_FILE_HEADER) * 2);
+
+ //
+ // Add whatever it takes to get to the next aligned address
+ //
+ while ((PadFileSize % DataAlignment) != 0) {
+ PadFileSize++;
+ }
+ //
+ // Subtract the next file header size
+ //
+ PadFileSize -= sizeof (EFI_FFS_FILE_HEADER);
+
+ //
+ // Subtract the starting offset to get size
+ //
+ PadFileSize -= (UINTN) FvImage->CurrentFilePointer - (UINTN) FvImage->FileImage;
+
+ //
+ // Write pad file size (calculated size minus next file header size)
+ //
+ PadFile->Size[0] = (UINT8) (PadFileSize & 0xFF);
+ PadFile->Size[1] = (UINT8) ((PadFileSize >> 8) & 0xFF);
+ PadFile->Size[2] = (UINT8) ((PadFileSize >> 16) & 0xFF);
+
+ //
+ // Fill in checksums and state, they must be 0 for checksumming.
+ //
+ PadFile->IntegrityCheck.Checksum.Header = 0;
+ PadFile->IntegrityCheck.Checksum.File = 0;
+ PadFile->State = 0;
+ PadFile->IntegrityCheck.Checksum.Header = CalculateChecksum8 ((UINT8 *) PadFile, sizeof (EFI_FFS_FILE_HEADER));
+ if (PadFile->Attributes & FFS_ATTRIB_CHECKSUM) {
+ PadFile->IntegrityCheck.Checksum.File = CalculateChecksum8 ((UINT8 *) PadFile, PadFileSize);
+ } else {
+ PadFile->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM;
+ }
+
+ PadFile->State = EFI_FILE_HEADER_CONSTRUCTION | EFI_FILE_HEADER_VALID | EFI_FILE_DATA_VALID;
+ UpdateFfsFileState (
+ (EFI_FFS_FILE_HEADER *) PadFile,
+ (EFI_FIRMWARE_VOLUME_HEADER *) FvImage->FileImage
+ );
+
+ //
+ // Verify that we have enough space (including the padding
+ //
+ if ((UINTN) (PadFile + sizeof (EFI_FFS_FILE_HEADER)) >= (UINTN) FvImage->Eof) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ //
+ // Update the current FV pointer
+ //
+ FvImage->CurrentFilePointer += PadFileSize;
+
+ return EFI_SUCCESS;
+}
+
+BOOLEAN
+IsVtfFile (
+ IN EFI_FFS_FILE_HEADER *FileBuffer
+ )
+/*++
+
+Routine Description:
+
+ This function checks the header to validate if it is a VTF file
+
+Arguments:
+
+ FileBuffer Buffer in which content of a file has been read.
+
+Returns:
+
+ TRUE If this is a VTF file
+ FALSE If this is not a VTF file
+
+--*/
+{
+ EFI_GUID VtfGuid = EFI_FFS_VOLUME_TOP_FILE_GUID;
+ if (!memcmp (&FileBuffer->Name, &VtfGuid, sizeof (EFI_GUID))) {
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
+EFI_STATUS
+FfsRebaseImageRead (
+ IN VOID *FileHandle,
+ IN UINTN FileOffset,
+ IN OUT UINT32 *ReadSize,
+ OUT VOID *Buffer
+ )
+/*++
+
+Routine Description:
+
+ Support routine for the PE/COFF Loader that reads a buffer from a PE/COFF file
+
+Arguments:
+
+ FileHandle - The handle to the PE/COFF file
+
+ FileOffset - The offset, in bytes, into the file to read
+
+ ReadSize - The number of bytes to read from the file starting at FileOffset
+
+ Buffer - A pointer to the buffer to read the data into.
+
+Returns:
+
+ EFI_SUCCESS - ReadSize bytes of data were read into Buffer from the PE/COFF file starting at FileOffset
+
+--*/
+{
+ CHAR8 *Destination8;
+ CHAR8 *Source8;
+ UINT32 Length;
+
+ Destination8 = Buffer;
+ Source8 = (CHAR8 *) ((UINTN) FileHandle + FileOffset);
+ Length = *ReadSize;
+ while (Length--) {
+ *(Destination8++) = *(Source8++);
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+EFI_STATUS
+AddSymFile (
+ IN UINT64 BaseAddress,
+ IN EFI_FFS_FILE_HEADER *FfsFile,
+ IN OUT MEMORY_FILE *SymImage,
+ IN CHAR8 *SourceFileName
+ )
+/*++
+
+Routine Description:
+
+ This function adds the SYM tokens in the source file to the destination file.
+ The SYM tokens are updated to reflect the base address.
+
+Arguments:
+
+ BaseAddress The base address for the new SYM tokens.
+ FfsFile Pointer to the beginning of the FFS file in question.
+ SymImage The memory file to update with symbol information.
+ SourceFileName The source file.
+
+Returns:
+
+ EFI_SUCCESS The function completed successfully.
+ EFI_INVALID_PARAMETER One of the input parameters was invalid.
+ EFI_ABORTED An error occurred.
+
+--*/
+{
+ FILE *SourceFile;
+
+ CHAR8 Buffer[_MAX_PATH];
+ CHAR8 Type[_MAX_PATH];
+ CHAR8 Address[_MAX_PATH];
+ CHAR8 Section[_MAX_PATH];
+ CHAR8 Token[_MAX_PATH];
+ CHAR8 SymFileName[_MAX_PATH];
+ CHAR8 CodeModuleName[_MAX_PATH];
+ CHAR8 *Ptr;
+
+ UINT64 TokenAddress;
+
+ EFI_STATUS Status;
+ EFI_FILE_SECTION_POINTER Pe32Section;
+ UINT32 EntryPoint;
+ UINT32 BaseOfCode;
+ UINT16 MachineType;
+
+ //
+ // Verify input parameters.
+ //
+ if (BaseAddress == 0 || FfsFile == NULL || SymImage == NULL || SourceFileName == NULL) {
+ Error (NULL, 0, 0, "invalid parameter passed to AddSymFile()", NULL);
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // Check if we want to add this file
+ //
+ //
+ // Get the file name
+ //
+ strcpy (Buffer, SourceFileName);
+
+ //
+ // Copy the file name for the path of the sym file and truncate the name portion.
+ //
+ strcpy (SymFileName, Buffer);
+ Ptr = strrchr (SymFileName, '\\');
+ assert (Ptr);
+ Ptr[0] = 0;
+
+ //
+ // Find the file extension and make it lower case
+ //
+ Ptr = strrchr (SymFileName, '.');
+ if (Ptr != NULL) {
+ strlwr (Ptr);
+ }
+ //
+ // Check if it is PEI file
+ //
+ if (strstr (Buffer, ".pei") != NULL) {
+ //
+ // Find the human readable portion
+ //
+ if (!strtok (Buffer, "-") ||
+ !strtok (NULL, "-") ||
+ !strtok (NULL, "-") ||
+ !strtok (NULL, "-") ||
+ !strtok (NULL, "-") ||
+ !strcpy (Buffer, strtok (NULL, "."))
+ ) {
+ Error (NULL, 0, 0, "failed to find human readable portion of the file name in AddSymFile()", NULL);
+ return EFI_ABORTED;
+ }
+ //
+ // Save code module name
+ //
+ strcpy (CodeModuleName, Buffer);
+
+ //
+ // Add the symbol file name and extension to the file path.
+ //
+ strcat (Buffer, ".sym");
+ strcat (SymFileName, "\\");
+ strcat (SymFileName, Buffer);
+ } else {
+ //
+ // Only handle PEIM files.
+ //
+ return EFI_SUCCESS;
+ }
+ //
+ // Find PE32 section
+ //
+ Status = GetSectionByType (FfsFile, EFI_SECTION_PE32, 1, &Pe32Section);
+
+ //
+ // BUGBUG: Assume if no PE32 section it is PIC and hardcode base address
+ //
+ if (Status == EFI_NOT_FOUND) {
+ Status = GetSectionByType (FfsFile, EFI_SECTION_TE, 1, &Pe32Section);
+ }
+
+ if (Status == EFI_SUCCESS) {
+ Status = GetPe32Info (
+ (VOID *) ((UINTN) Pe32Section.Pe32Section + sizeof (EFI_SECTION_PE32)),
+ &EntryPoint,
+ &BaseOfCode,
+ &MachineType
+ );
+ } else if (Status == EFI_NOT_FOUND) {
+ //
+ // For PIC, hardcode.
+ //
+ BaseOfCode = 0x60;
+ Status = EFI_SUCCESS;
+ } else {
+ Error (NULL, 0, 0, "could not parse a PE32 section from the PEI file", NULL);
+ return Status;
+ }
+
+ if (EFI_ERROR (Status)) {
+ Error (NULL, 0, 0, "GetPe32Info() could not get PE32 entry point for PEI file", NULL);
+ return Status;
+ }
+
+ //
+ // Open the source file
+ //
+ SourceFile = fopen (SymFileName, "r");
+ if (SourceFile == NULL) {
+ //
+ // SYM files are not required.
+ //
+ return EFI_SUCCESS;
+ }
+ //
+ // Read the first line
+ //
+ if (fgets (Buffer, _MAX_PATH, SourceFile) == NULL) {
+ Buffer[0] = 0;
+ }
+ //
+ // Make sure it matches the expected sym format
+ //
+ if (strcmp (Buffer, "TEXTSYM format | V1.0\n")) {
+ fclose (SourceFile);
+ Error (NULL, 0, 0, "AddSymFile() found unexpected sym format in input file", NULL);
+ return EFI_ABORTED;
+ }
+ //
+ // Read in the file
+ //
+ while (feof (SourceFile) == 0) {
+ //
+ // Read a line
+ //
+ if (fscanf (
+ SourceFile,
+ "%s | %s | %s | %s\n",
+ Type,
+ Address,
+ Section,
+ Token
+ ) == 4) {
+ //
+ // If the token starts with "??" ignore it
+ //
+ if (Token[0] == '?' && Token[1] == '?') {
+ continue;
+ }
+ //
+ // Get the token address
+ //
+ AsciiStringToUint64 (Address, TRUE, &TokenAddress);
+
+ //
+ // Add the base address
+ //
+ TokenAddress += BaseAddress;
+
+ //
+ // If PE32 or TE section then find the start of code. For PIC it is hardcoded.
+ //
+ if (Pe32Section.Pe32Section) {
+ //
+ // Add the offset of the PE32 section
+ //
+ TokenAddress += (UINTN) Pe32Section.Pe32Section - (UINTN) FfsFile;
+
+ //
+ // Add the size of the PE32 section header
+ //
+ TokenAddress += sizeof (EFI_PE32_SECTION);
+ } else {
+ //
+ // For PIC hardcoded.
+ //
+ TokenAddress += 0x28;
+ }
+
+ //
+ // Add the beginning of the code
+ //
+ TokenAddress += BaseOfCode;
+
+ sprintf (
+ Buffer,
+ "%s | %016I64X | %s | _%s%s\n",
+ Type,
+ TokenAddress,
+ Section,
+ CodeModuleName,
+ Token
+ );
+ memcpy (SymImage->CurrentFilePointer, Buffer, strlen (Buffer) + 1);
+ SymImage->CurrentFilePointer = (UINT8 *) (((UINTN) SymImage->CurrentFilePointer) + strlen (Buffer) + 1);
+ }
+ }
+
+ fclose (SourceFile);
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+AddFile (
+ IN OUT MEMORY_FILE *FvImage,
+ IN FV_INFO *FvInfo,
+ IN UINTN Index,
+ IN OUT EFI_FFS_FILE_HEADER **VtfFileImage,
+ IN OUT MEMORY_FILE *SymImage
+ )
+/*++
+
+Routine Description:
+
+ This function adds a file to the FV image. The file will pad to the
+ appropriate alignment if required.
+
+Arguments:
+
+ FvImage The memory image of the FV to add it to. The current offset
+ must be valid.
+ FvInfo Pointer to information about the FV.
+ Index The file in the FvInfo file list to add.
+ VtfFileImage A pointer to the VTF file within the FvImage. If this is equal
+ to the end of the FvImage then no VTF previously found.
+ SymImage The memory image of the Sym file to update if symbols are present.
+ The current offset must be valid.
+
+Returns:
+
+ EFI_SUCCESS The function completed successfully.
+ EFI_INVALID_PARAMETER One of the input parameters was invalid.
+ EFI_ABORTED An error occurred.
+ EFI_OUT_OF_RESOURCES Insufficient resources exist to complete the add.
+
+--*/
+{
+ FILE *NewFile;
+ UINTN FileSize;
+ UINT8 *FileBuffer;
+ UINTN NumBytesRead;
+ UINT32 CurrentFileAlignment;
+ EFI_STATUS Status;
+ EFI_PHYSICAL_ADDRESS CurrentFileBaseAddress;
+ UINT8 VtfHeaderChecksum;
+ UINT8 VtfFileChecksum;
+ UINT8 FileState;
+ EFI_FFS_FILE_TAIL TailValue;
+ UINT32 TailSize;
+ //
+ // Verify input parameters.
+ //
+ if (FvImage == NULL || FvInfo == NULL || FvInfo->FvFiles[Index][0] == 0 || VtfFileImage == NULL || SymImage == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // Read the file to add
+ //
+ NewFile = fopen (FvInfo->FvFiles[Index], "rb");
+
+ if (NewFile == NULL) {
+ Error (NULL, 0, 0, FvInfo->FvFiles[Index], "failed to open file for reading");
+ return EFI_ABORTED;
+ }
+ //
+ // Get the file size
+ //
+ FileSize = _filelength (fileno (NewFile));
+
+ //
+ // Read the file into a buffer
+ //
+ FileBuffer = malloc (FileSize);
+ if (FileBuffer == NULL) {
+ Error (NULL, 0, 0, "memory allocation failure", NULL);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ NumBytesRead = fread (FileBuffer, sizeof (UINT8), FileSize, NewFile);
+
+ //
+ // Done with the file, from this point on we will just use the buffer read.
+ //
+ fclose (NewFile);
+
+ //
+ // Verify read successful
+ //
+ if (NumBytesRead != sizeof (UINT8) * FileSize) {
+ free (FileBuffer);
+ Error (NULL, 0, 0, FvInfo->FvFiles[Index], "failed to read input file contents");
+ return EFI_ABORTED;
+ }
+ //
+ // Verify space exists to add the file
+ //
+ if (FileSize > (UINTN) ((UINTN) *VtfFileImage - (UINTN) FvImage->CurrentFilePointer)) {
+ Error (NULL, 0, 0, FvInfo->FvFiles[Index], "insufficient space remains to add the file");
+ return EFI_OUT_OF_RESOURCES;
+ }
+ //
+ // Update the file state based on polarity of the FV.
+ //
+ UpdateFfsFileState (
+ (EFI_FFS_FILE_HEADER *) FileBuffer,
+ (EFI_FIRMWARE_VOLUME_HEADER *) FvImage->FileImage
+ );
+
+ //
+ // If we have a VTF file, add it at the top.
+ //
+ if (IsVtfFile ((EFI_FFS_FILE_HEADER *) FileBuffer)) {
+ if ((UINTN) *VtfFileImage == (UINTN) FvImage->Eof) {
+ //
+ // No previous VTF, add this one.
+ //
+ *VtfFileImage = (EFI_FFS_FILE_HEADER *) (UINTN) ((UINTN) FvImage->FileImage + FvInfo->Size - FileSize);
+ //
+ // Sanity check. The file MUST align appropriately
+ //
+ if ((((UINTN) *VtfFileImage) & 0x07) != 0) {
+ Error (NULL, 0, 0, "VTF file does not align on 8-byte boundary", NULL);
+ }
+ //
+ // copy VTF File Header
+ //
+ memcpy (*VtfFileImage, FileBuffer, sizeof (EFI_FFS_FILE_HEADER));
+
+ //
+ // Copy VTF body
+ //
+ memcpy (
+ (UINT8 *) *VtfFileImage + sizeof (EFI_FFS_FILE_HEADER),
+ FileBuffer + sizeof (EFI_FFS_FILE_HEADER),
+ FileSize - sizeof (EFI_FFS_FILE_HEADER)
+ );
+
+ //
+ // re-calculate the VTF File Header
+ //
+ FileState = (*VtfFileImage)->State;
+ (*VtfFileImage)->State = 0;
+ *(UINT32 *) ((*VtfFileImage)->Size) = FileSize;
+ (*VtfFileImage)->IntegrityCheck.Checksum.Header = 0;
+ (*VtfFileImage)->IntegrityCheck.Checksum.File = 0;
+
+ VtfHeaderChecksum = CalculateChecksum8 ((UINT8 *) *VtfFileImage, sizeof (EFI_FFS_FILE_HEADER));
+ (*VtfFileImage)->IntegrityCheck.Checksum.Header = VtfHeaderChecksum;
+ //
+ // Determine if it has a tail
+ //
+ if ((*VtfFileImage)->Attributes & FFS_ATTRIB_TAIL_PRESENT) {
+ TailSize = sizeof (EFI_FFS_FILE_TAIL);
+ } else {
+ TailSize = 0;
+ }
+
+ if ((*VtfFileImage)->Attributes & FFS_ATTRIB_CHECKSUM) {
+ VtfFileChecksum = CalculateChecksum8 ((UINT8 *) *VtfFileImage, FileSize - TailSize);
+ (*VtfFileImage)->IntegrityCheck.Checksum.File = VtfFileChecksum;
+ } else {
+ (*VtfFileImage)->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM;
+ }
+ //
+ // If it has a file tail, update it
+ //
+ if ((*VtfFileImage)->Attributes & FFS_ATTRIB_TAIL_PRESENT) {
+ TailValue = (EFI_FFS_FILE_TAIL) (~((*VtfFileImage)->IntegrityCheck.TailReference));
+ *(EFI_FFS_FILE_TAIL *) (((UINTN) (*VtfFileImage) + GetLength ((*VtfFileImage)->Size) - sizeof (EFI_FFS_FILE_TAIL))) = TailValue;
+ }
+ (*VtfFileImage)->State = FileState;
+ free (FileBuffer);
+ return EFI_SUCCESS;
+ } else {
+ //
+ // Already found a VTF file.
+ //
+ Error (NULL, 0, 0, "multiple VTF files are illegal in a single FV", NULL);
+ free (FileBuffer);
+ return EFI_ABORTED;
+ }
+ }
+ //
+ // Check if alignment is required
+ //
+ Status = ReadFfsAlignment ((EFI_FFS_FILE_HEADER *) FileBuffer, &CurrentFileAlignment);
+ if (EFI_ERROR (Status)) {
+ printf ("ERROR: Could not determine alignment of file %s.\n", FvInfo->FvFiles[Index]);
+ free (FileBuffer);
+ return EFI_ABORTED;
+ }
+ //
+ // Add pad file if necessary
+ //
+ Status = AddPadFile (FvImage, CurrentFileAlignment);
+ if (EFI_ERROR (Status)) {
+ printf ("ERROR: Could not align the file data properly.\n");
+ free (FileBuffer);
+ return EFI_ABORTED;
+ }
+ //
+ // Add file
+ //
+ if ((FvImage->CurrentFilePointer + FileSize) < FvImage->Eof) {
+ //
+ // Copy the file
+ //
+ memcpy (FvImage->CurrentFilePointer, FileBuffer, FileSize);
+
+ //
+ // If the file is XIP, rebase
+ //
+ CurrentFileBaseAddress = FvInfo->BaseAddress + ((UINTN) FvImage->CurrentFilePointer - (UINTN) FvImage->FileImage);
+ //
+ // Status = RebaseFfsFile ((EFI_FFS_FILE_HEADER*) FvImage->CurrentFilePointer, CurrentFileBaseAddress);
+ // if (EFI_ERROR(Status)) {
+ // printf ("ERROR: Could not rebase the file %s.\n", FvInfo->FvFiles[Index]);
+ // return EFI_ABORTED;
+ // }
+ //
+ // Update Symbol file
+ //
+ Status = AddSymFile (
+ CurrentFileBaseAddress,
+ (EFI_FFS_FILE_HEADER *) FvImage->CurrentFilePointer,
+ SymImage,
+ FvInfo->FvFiles[Index]
+ );
+ assert (!EFI_ERROR (Status));
+
+ //
+ // Update the current pointer in the FV image
+ //
+ FvImage->CurrentFilePointer += FileSize;
+ } else {
+ printf ("ERROR: The firmware volume is out of space, could not add file %s.\n", FvInfo->FvFiles[Index]);
+ return EFI_ABORTED;
+ }
+ //
+ // Make next file start at QWord Boundry
+ //
+ while (((UINTN) FvImage->CurrentFilePointer & 0x07) != 0) {
+ FvImage->CurrentFilePointer++;
+ }
+ //
+ // Free allocated memory.
+ //
+ free (FileBuffer);
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+AddVariableBlock (
+ IN UINT8 *FvImage,
+ IN UINTN Size,
+ IN FV_INFO *FvInfo
+ )
+{
+ EFI_FIRMWARE_VOLUME_HEADER *FvHeader;
+ VARIABLE_STORE_HEADER *VarStoreHeader;
+ //
+ // Variable block should exclude FvHeader. Since the length of
+ // FvHeader depends on the block map, which is variable length,
+ // we could only decide the actual variable block length here.
+ //
+ FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) FvImage;
+ FvImage = FvImage + FvHeader->HeaderLength;
+
+ VarStoreHeader = (VARIABLE_STORE_HEADER *) FvImage;
+
+ VarStoreHeader->Signature = VARIABLE_STORE_SIGNATURE;
+ VarStoreHeader->Size = Size - FvHeader->HeaderLength;
+ VarStoreHeader->Format = VARIABLE_STORE_FORMATTED;
+ VarStoreHeader->State = VARIABLE_STORE_HEALTHY;
+ VarStoreHeader->Reserved = 0;
+ VarStoreHeader->Reserved1 = 0;
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+AddEventLogBlock (
+ IN UINT8 *FvImage,
+ IN UINTN Size,
+ IN FV_INFO *FvInfo
+ )
+{
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+AddFTWWorkingBlock (
+ IN UINT8 *FvImage,
+ IN UINTN Size,
+ IN FV_INFO *FvInfo
+ )
+{
+ EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER *FTWHeader;
+ UINT32 Crc32;
+
+ Crc32 = 0;
+ FTWHeader = (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER *) FvImage;
+ memcpy (&FTWHeader->Signature, &(FvInfo->FvGuid), sizeof (EFI_GUID));
+ FTWHeader->WriteQueueSize = Size - sizeof (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER);
+ CalculateCrc32 (FvImage, sizeof (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER), &Crc32);
+ FTWHeader->Crc = Crc32;
+ if (FvInfo->FvAttributes & EFI_FVB_ERASE_POLARITY) {
+ FTWHeader->WorkingBlockValid = 0;
+ FTWHeader->WorkingBlockInvalid = 1;
+ } else {
+ FTWHeader->WorkingBlockValid = 1;
+ FTWHeader->WorkingBlockInvalid = 0;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+AddFTWSpareBlock (
+ IN UINT8 *FvImage,
+ IN UINTN Size,
+ IN FV_INFO *FvInfo
+ )
+{
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+GenNonFFSFv (
+ IN UINT8 *FvImage,
+ IN FV_INFO *FvInfo
+ )
+/*++
+
+Routine Description:
+
+ This function generate the non FFS FV image, such as the working block
+ and spare block. How each component of the FV is built is component
+ specific.
+
+Arguments:
+
+ FvImage The memory image of the FV to add it to. The current offset
+ must be valid.
+ FvInfo Pointer to information about the FV.
+
+Returns:
+
+ EFI_SUCCESS The function completed successfully.
+ EFI_INVALID_PARAMETER One of the input parameters was invalid.
+ EFI_ABORTED An error occurred.
+ EFI_OUT_OF_RESOURCES Insufficient resources exist to complete the add.
+
+--*/
+{
+ UINTN Index;
+ EFI_FIRMWARE_VOLUME_HEADER *FvHeader;
+ UINT64 TotalSize;
+
+ FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) FvImage;
+ TotalSize = 0;
+
+ for (Index = 0; FvInfo->FvComponents[Index].Size != 0; Index++) {
+ if (stricmp (FvInfo->FvComponents[Index].ComponentName, EFI_NV_VARIABLE_STRING) == 0) {
+ AddVariableBlock (FvImage, FvInfo->FvComponents[Index].Size, FvInfo);
+ } else if (stricmp (FvInfo->FvComponents[Index].ComponentName, EFI_NV_EVENT_LOG_STRING) == 0) {
+ AddEventLogBlock (FvImage, FvInfo->FvComponents[Index].Size, FvInfo);
+ } else if (stricmp (FvInfo->FvComponents[Index].ComponentName, EFI_NV_FTW_WORKING_STRING) == 0) {
+ AddFTWWorkingBlock (FvImage, FvInfo->FvComponents[Index].Size, FvInfo);
+ } else if (stricmp (FvInfo->FvComponents[Index].ComponentName, EFI_NV_FTW_SPARE_STRING) == 0) {
+ AddFTWSpareBlock (FvImage, FvInfo->FvComponents[Index].Size, FvInfo);
+ } else {
+ printf ("Error. Unknown Non-FFS block %s \n", FvInfo->FvComponents[Index].ComponentName);
+ return EFI_ABORTED;
+ }
+
+ FvImage = FvImage + FvInfo->FvComponents[Index].Size;
+ TotalSize = TotalSize + FvInfo->FvComponents[Index].Size;
+ }
+ //
+ // Index and TotalSize is zero mean there's no component, so this is an empty fv
+ //
+ if ((Index != 0 || TotalSize != 0) && TotalSize != FvInfo->Size) {
+ printf ("Error. Component size does not sum up to FV size.\n");
+ return EFI_ABORTED;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+PadFvImage (
+ IN MEMORY_FILE *FvImage,
+ IN EFI_FFS_FILE_HEADER *VtfFileImage
+ )
+/*++
+
+Routine Description:
+
+ This function places a pad file between the last file in the FV and the VTF
+ file if the VTF file exists.
+
+Arguments:
+
+ FvImage Memory file for the FV memory image
+ VtfFileImage The address of the VTF file. If this is the end of the FV
+ image, no VTF exists and no pad file is needed.
+
+Returns:
+
+ EFI_SUCCESS Completed successfully.
+ EFI_INVALID_PARAMETER One of the input parameters was NULL.
+
+--*/
+{
+ EFI_FFS_FILE_HEADER *PadFile;
+ UINTN FileSize;
+
+ //
+ // If there is no VTF or the VTF naturally follows the previous file without a
+ // pad file, then there's nothing to do
+ //
+ if ((UINTN) VtfFileImage == (UINTN) FvImage->Eof || (void *) FvImage->CurrentFilePointer == (void *) VtfFileImage) {
+ return EFI_SUCCESS;
+ }
+ //
+ // Pad file starts at beginning of free space
+ //
+ PadFile = (EFI_FFS_FILE_HEADER *) FvImage->CurrentFilePointer;
+
+ //
+ // write header
+ //
+ memset (PadFile, 0, sizeof (EFI_FFS_FILE_HEADER));
+ memcpy (&PadFile->Name, &DefaultFvPadFileNameGuid, sizeof (EFI_GUID));
+ PadFile->Type = EFI_FV_FILETYPE_FFS_PAD;
+ PadFile->Attributes = 0;
+
+ //
+ // FileSize includes the EFI_FFS_FILE_HEADER
+ //
+ FileSize = (UINTN) VtfFileImage - (UINTN) FvImage->CurrentFilePointer;
+ PadFile->Size[0] = (UINT8) (FileSize & 0x000000FF);
+ PadFile->Size[1] = (UINT8) ((FileSize & 0x0000FF00) >> 8);
+ PadFile->Size[2] = (UINT8) ((FileSize & 0x00FF0000) >> 16);
+
+ //
+ // Fill in checksums and state, must be zero during checksum calculation.
+ //
+ PadFile->IntegrityCheck.Checksum.Header = 0;
+ PadFile->IntegrityCheck.Checksum.File = 0;
+ PadFile->State = 0;
+ PadFile->IntegrityCheck.Checksum.Header = CalculateChecksum8 ((UINT8 *) PadFile, sizeof (EFI_FFS_FILE_HEADER));
+ if (PadFile->Attributes & FFS_ATTRIB_CHECKSUM) {
+ PadFile->IntegrityCheck.Checksum.File = CalculateChecksum8 ((UINT8 *) PadFile, FileSize);
+ } else {
+ PadFile->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM;
+ }
+
+ PadFile->State = EFI_FILE_HEADER_CONSTRUCTION | EFI_FILE_HEADER_VALID | EFI_FILE_DATA_VALID;
+
+ UpdateFfsFileState (
+ (EFI_FFS_FILE_HEADER *) PadFile,
+ (EFI_FIRMWARE_VOLUME_HEADER *) FvImage->FileImage
+ );
+ //
+ // Update the current FV pointer
+ //
+ FvImage->CurrentFilePointer = FvImage->Eof;
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+UpdateResetVector (
+ IN MEMORY_FILE *FvImage,
+ IN FV_INFO *FvInfo,
+ IN EFI_FFS_FILE_HEADER *VtfFile
+ )
+/*++
+
+Routine Description:
+
+ This parses the FV looking for the PEI core and then plugs the address into
+ the SALE_ENTRY point of the BSF/VTF for IPF and does BUGBUG TBD action to
+ complete an IA32 Bootstrap FV.
+
+Arguments:
+
+ FvImage Memory file for the FV memory image
+ FvInfo Information read from INF file.
+ VtfFile Pointer to the VTF file in the FV image.
+
+Returns:
+
+ EFI_SUCCESS Function Completed successfully.
+ EFI_ABORTED Error encountered.
+ EFI_INVALID_PARAMETER A required parameter was NULL.
+ EFI_NOT_FOUND PEI Core file not found.
+
+--*/
+{
+ EFI_FFS_FILE_HEADER *PeiCoreFile;
+ EFI_FFS_FILE_HEADER *SecCoreFile;
+ EFI_STATUS Status;
+ EFI_FILE_SECTION_POINTER Pe32Section;
+ UINT32 EntryPoint;
+ UINT32 BaseOfCode;
+ UINT16 MachineType;
+ EFI_PHYSICAL_ADDRESS PeiCorePhysicalAddress;
+ EFI_PHYSICAL_ADDRESS SecCorePhysicalAddress;
+ EFI_PHYSICAL_ADDRESS *SecCoreEntryAddressPtr;
+ UINT32 *Ia32ResetAddressPtr;
+ UINT8 *BytePointer;
+ UINT8 *BytePointer2;
+ UINT16 *WordPointer;
+ UINT16 CheckSum;
+ UINTN Index;
+ EFI_FFS_FILE_STATE SavedState;
+ EFI_FFS_FILE_TAIL TailValue;
+ UINT32 TailSize;
+ UINT64 FitAddress;
+ FIT_TABLE *FitTablePtr;
+
+ //
+ // Verify input parameters
+ //
+ if (FvImage == NULL || FvInfo == NULL || VtfFile == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // Initialize FV library
+ //
+ InitializeFvLib (FvImage->FileImage, (UINTN) FvImage->Eof - (UINTN) FvImage->FileImage);
+
+ //
+ // Verify VTF file
+ //
+ Status = VerifyFfsFile (VtfFile);
+ if (EFI_ERROR (Status)) {
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // Find the PEI Core
+ //
+ Status = GetFileByType (EFI_FV_FILETYPE_PEI_CORE, 1, &PeiCoreFile);
+ if (EFI_ERROR (Status) || PeiCoreFile == NULL) {
+ Error (NULL, 0, 0, "could not find the PEI core in the FV", NULL);
+ return EFI_ABORTED;
+ }
+
+ //
+ // PEI Core found, now find PE32 or TE section
+ //
+ Status = GetSectionByType (PeiCoreFile, EFI_SECTION_PE32, 1, &Pe32Section);
+ if (Status == EFI_NOT_FOUND) {
+ Status = GetSectionByType (PeiCoreFile, EFI_SECTION_TE, 1, &Pe32Section);
+ }
+
+ if (EFI_ERROR (Status)) {
+ Error (NULL, 0, 0, "could not find PE32 or TE section in PEI core file", NULL);
+ return EFI_ABORTED;
+ }
+
+ Status = GetPe32Info (
+ (VOID *) ((UINTN) Pe32Section.Pe32Section + sizeof (EFI_SECTION_PE32)),
+ &EntryPoint,
+ &BaseOfCode,
+ &MachineType
+ );
+
+ if (EFI_ERROR (Status)) {
+ Error (NULL, 0, 0, "could not get PE32 entry point for PEI core", NULL);
+ return EFI_ABORTED;
+ }
+ //
+ // Physical address is FV base + offset of PE32 + offset of the entry point
+ //
+ PeiCorePhysicalAddress = FvInfo->BaseAddress;
+ PeiCorePhysicalAddress += (UINTN) Pe32Section.Pe32Section + sizeof (EFI_SECTION_PE32) - (UINTN) FvImage->FileImage;
+ PeiCorePhysicalAddress += EntryPoint;
+
+ if (MachineType == EFI_IMAGE_MACHINE_IA64) {
+ //
+ // Update PEI_CORE address
+ //
+ //
+ // Set the uncached attribute bit in the physical address
+ //
+ PeiCorePhysicalAddress |= 0x8000000000000000ULL;
+
+ //
+ // Check if address is aligned on a 16 byte boundary
+ //
+ if (PeiCorePhysicalAddress & 0xF) {
+ printf (
+ "ERROR: PEI_CORE entry point is not aligned on a 16 byte boundary, address specified is %Xh.\n",
+ PeiCorePhysicalAddress
+ );
+ return EFI_ABORTED;
+ }
+ //
+ // First Get the FIT table address
+ //
+ FitAddress = (*(UINT64 *) (FvImage->Eof - IPF_FIT_ADDRESS_OFFSET)) & 0xFFFFFFFF;
+
+ FitTablePtr = (FIT_TABLE *) (FvImage->FileImage + (FitAddress - FvInfo->BaseAddress));
+
+ Status = UpdatePeiCoreEntryInFit (FitTablePtr, PeiCorePhysicalAddress);
+
+ if (!EFI_ERROR (Status)) {
+ UpdateFitCheckSum (FitTablePtr);
+ }
+ //
+ // Find the Sec Core
+ //
+ Status = GetFileByType (EFI_FV_FILETYPE_SECURITY_CORE, 1, &SecCoreFile);
+ if (EFI_ERROR (Status) || SecCoreFile == NULL) {
+ Error (NULL, 0, 0, "could not find the Sec core in the FV", NULL);
+ return EFI_ABORTED;
+ }
+ //
+ // Sec Core found, now find PE32 section
+ //
+ Status = GetSectionByType (SecCoreFile, EFI_SECTION_PE32, 1, &Pe32Section);
+ if (EFI_ERROR (Status)) {
+ Error (NULL, 0, 0, "could not find PE32 section in SEC core file", NULL);
+ return EFI_ABORTED;
+ }
+
+ Status = GetPe32Info (
+ (VOID *) ((UINTN) Pe32Section.Pe32Section + sizeof (EFI_SECTION_PE32)),
+ &EntryPoint,
+ &BaseOfCode,
+ &MachineType
+ );
+ if (EFI_ERROR (Status)) {
+ Error (NULL, 0, 0, "could not get PE32 entry point for SEC core", NULL);
+ return EFI_ABORTED;
+ }
+ //
+ // Physical address is FV base + offset of PE32 + offset of the entry point
+ //
+ SecCorePhysicalAddress = FvInfo->BaseAddress;
+ SecCorePhysicalAddress += (UINTN) Pe32Section.Pe32Section + sizeof (EFI_SECTION_PE32) - (UINTN) FvImage->FileImage;
+ SecCorePhysicalAddress += EntryPoint;
+
+ //
+ // Update SEC_CORE address
+ //
+ //
+ // Set the uncached attribute bit in the physical address
+ //
+ SecCorePhysicalAddress |= 0x8000000000000000ULL;
+
+ //
+ // Update the address
+ //
+ SecCoreEntryAddressPtr = (EFI_PHYSICAL_ADDRESS *) ((UINTN) FvImage->Eof - IPF_SALE_ENTRY_ADDRESS_OFFSET);
+ *SecCoreEntryAddressPtr = SecCorePhysicalAddress;
+
+ //
+ // Check if address is aligned on a 16 byte boundary
+ //
+ if (SecCorePhysicalAddress & 0xF) {
+ printf (
+ "ERROR: SALE_ENTRY entry point is not aligned on a 16 byte boundary, address specified is %Xh.\n",
+ SecCorePhysicalAddress
+ );
+ return EFI_ABORTED;
+ }
+ } else if (MachineType == EFI_IMAGE_MACHINE_IA32) {
+ //
+ // Get the location to update
+ //
+ Ia32ResetAddressPtr = (UINT32 *) ((UINTN) FvImage->Eof - IA32_PEI_CORE_ENTRY_OFFSET);
+
+ //
+ // Write lower 32 bits of physical address
+ //
+ *Ia32ResetAddressPtr = (UINT32) PeiCorePhysicalAddress;
+
+ //
+ // Update the BFV base address
+ //
+ Ia32ResetAddressPtr = (UINT32 *) ((UINTN) FvImage->Eof - 4);
+ *Ia32ResetAddressPtr = (UINT32) (FvInfo->BaseAddress);
+
+ CheckSum = 0x0000;
+
+ //
+ // Update the Startup AP in the FVH header block ZeroVector region.
+ //
+ BytePointer = (UINT8 *) ((UINTN) FvImage->FileImage);
+ BytePointer2 = (FvInfo->Size == 0x10000) ? m64kRecoveryStartupApDataArray : m128kRecoveryStartupApDataArray;
+ for (Index = 0; Index < SIZEOF_STARTUP_DATA_ARRAY; Index++) {
+ *BytePointer++ = *BytePointer2++;
+ }
+ //
+ // Calculate the checksum
+ //
+ WordPointer = (UINT16 *) ((UINTN) FvImage->FileImage);
+ for (Index = 0; Index < SIZEOF_STARTUP_DATA_ARRAY / 2; Index++) {
+ CheckSum = (UINT16) (CheckSum + ((UINT16) *WordPointer));
+ WordPointer++;
+ }
+ //
+ // Update the checksum field
+ //
+ BytePointer = (UINT8 *) ((UINTN) FvImage->FileImage);
+ BytePointer += (SIZEOF_STARTUP_DATA_ARRAY - 2);
+ WordPointer = (UINT16 *) BytePointer;
+ *WordPointer = (UINT16) (0x10000 - (UINT32) CheckSum);
+ } else {
+ Error (NULL, 0, 0, "invalid machine type in PEI core", "machine type=0x%X", (UINT32) MachineType);
+ return EFI_ABORTED;
+ }
+ //
+ // Determine if it has an FFS file tail.
+ //
+ if (VtfFile->Attributes & FFS_ATTRIB_TAIL_PRESENT) {
+ TailSize = sizeof (EFI_FFS_FILE_TAIL);
+ } else {
+ TailSize = 0;
+ }
+ //
+ // Now update file checksum
+ //
+ SavedState = VtfFile->State;
+ VtfFile->IntegrityCheck.Checksum.File = 0;
+ VtfFile->State = 0;
+ if (VtfFile->Attributes & FFS_ATTRIB_CHECKSUM) {
+ VtfFile->IntegrityCheck.Checksum.File = CalculateChecksum8 (
+ (UINT8 *) VtfFile,
+ GetLength (VtfFile->Size) - TailSize
+ );
+ } else {
+ VtfFile->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM;
+ }
+
+ VtfFile->State = SavedState;
+
+ //
+ // Update tail if present
+ //
+ if (VtfFile->Attributes & FFS_ATTRIB_TAIL_PRESENT) {
+ TailValue = (EFI_FFS_FILE_TAIL) (~(VtfFile->IntegrityCheck.TailReference));
+ *(EFI_FFS_FILE_TAIL *) (((UINTN) (VtfFile) + GetLength (VtfFile->Size) - sizeof (EFI_FFS_FILE_TAIL))) = TailValue;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+GetPe32Info (
+ IN UINT8 *Pe32,
+ OUT UINT32 *EntryPoint,
+ OUT UINT32 *BaseOfCode,
+ OUT UINT16 *MachineType
+ )
+/*++
+
+Routine Description:
+
+ Retrieves the PE32 entry point offset and machine type from PE image or TeImage.
+ See EfiImage.h for machine types. The entry point offset is from the beginning
+ of the PE32 buffer passed in.
+
+Arguments:
+
+ Pe32 Beginning of the PE32.
+ EntryPoint Offset from the beginning of the PE32 to the image entry point.
+ BaseOfCode Base address of code.
+ MachineType Magic number for the machine type.
+
+Returns:
+
+ EFI_SUCCESS Function completed successfully.
+ EFI_ABORTED Error encountered.
+ EFI_INVALID_PARAMETER A required parameter was NULL.
+ EFI_UNSUPPORTED The operation is unsupported.
+
+--*/
+{
+ EFI_IMAGE_DOS_HEADER *DosHeader;
+ EFI_IMAGE_NT_HEADERS *NtHeader;
+ EFI_TE_IMAGE_HEADER *TeHeader;
+
+ //
+ // Verify input parameters
+ //
+ if (Pe32 == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // First check whether it is one TE Image.
+ //
+ TeHeader = (EFI_TE_IMAGE_HEADER *) Pe32;
+ if (TeHeader->Signature == EFI_TE_IMAGE_HEADER_SIGNATURE) {
+ //
+ // By TeImage Header to get output
+ //
+ *EntryPoint = TeHeader->AddressOfEntryPoint + sizeof (EFI_TE_IMAGE_HEADER) - TeHeader->StrippedSize;
+ *BaseOfCode = TeHeader->BaseOfCode + sizeof (EFI_TE_IMAGE_HEADER) - TeHeader->StrippedSize;
+ *MachineType = TeHeader->Machine;
+ } else {
+
+ //
+ // Then check whether
+ // First is the DOS header
+ //
+ DosHeader = (EFI_IMAGE_DOS_HEADER *) Pe32;
+
+ //
+ // Verify DOS header is expected
+ //
+ if (DosHeader->e_magic != EFI_IMAGE_DOS_SIGNATURE) {
+ printf ("ERROR: Unknown magic number in the DOS header, 0x%04X.\n", DosHeader->e_magic);
+ return EFI_UNSUPPORTED;
+ }
+ //
+ // Immediately following is the NT header.
+ //
+ NtHeader = (EFI_IMAGE_NT_HEADERS *) ((UINTN) Pe32 + DosHeader->e_lfanew);
+
+ //
+ // Verify NT header is expected
+ //
+ if (NtHeader->Signature != EFI_IMAGE_NT_SIGNATURE) {
+ printf ("ERROR: Unrecognized image signature 0x%08X.\n", NtHeader->Signature);
+ return EFI_UNSUPPORTED;
+ }
+ //
+ // Get output
+ //
+ *EntryPoint = NtHeader->OptionalHeader.AddressOfEntryPoint;
+ *BaseOfCode = NtHeader->OptionalHeader.BaseOfCode;
+ *MachineType = NtHeader->FileHeader.Machine;
+ }
+
+ //
+ // Verify machine type is supported
+ //
+ if (*MachineType != EFI_IMAGE_MACHINE_IA32 && *MachineType != EFI_IMAGE_MACHINE_IA64 && *MachineType != EFI_IMAGE_MACHINE_X64 && *MachineType != EFI_IMAGE_MACHINE_EBC) {
+ printf ("ERROR: Unrecognized machine type in the PE32 file.\n");
+ return EFI_UNSUPPORTED;
+ }
+
+ return EFI_SUCCESS;
+}
+//
+// Exposed function implementations (prototypes are defined in GenFvImageLib.h)
+//
+EFI_STATUS
+GenerateFvImage (
+ IN CHAR8 *InfFileImage,
+ IN UINTN InfFileSize,
+ OUT UINT8 **FvImage,
+ OUT UINTN *FvImageSize,
+ OUT CHAR8 **FvFileName,
+ OUT UINT8 **SymImage,
+ OUT UINTN *SymImageSize,
+ OUT CHAR8 **SymFileName
+ )
+/*++
+
+Routine Description:
+
+ This is the main function which will be called from application.
+
+Arguments:
+
+ InfFileImage Buffer containing the INF file contents.
+ InfFileSize Size of the contents of the InfFileImage buffer.
+ FvImage Pointer to the FV image created.
+ FvImageSize Size of the FV image created and pointed to by FvImage.
+ FvFileName Requested name for the FV file.
+ SymImage Pointer to the Sym image created.
+ SymImageSize Size of the Sym image created and pointed to by SymImage.
+ SymFileName Requested name for the Sym file.
+
+Returns:
+
+ EFI_SUCCESS Function completed successfully.
+ EFI_OUT_OF_RESOURCES Could not allocate required resources.
+ EFI_ABORTED Error encountered.
+ EFI_INVALID_PARAMETER A required parameter was NULL.
+
+--*/
+{
+ EFI_STATUS Status;
+ MEMORY_FILE InfMemoryFile;
+ MEMORY_FILE FvImageMemoryFile;
+ MEMORY_FILE SymImageMemoryFile;
+ FV_INFO FvInfo;
+ UINTN Index;
+ EFI_FIRMWARE_VOLUME_HEADER *FvHeader;
+ EFI_FFS_FILE_HEADER *VtfFileImage;
+
+ //
+ // Check for invalid parameter
+ //
+ if (InfFileImage == NULL || FvImage == NULL || FvImageSize == NULL || FvFileName == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // Initialize file structures
+ //
+ InfMemoryFile.FileImage = InfFileImage;
+ InfMemoryFile.CurrentFilePointer = InfFileImage;
+ InfMemoryFile.Eof = InfFileImage + InfFileSize;
+
+ //
+ // Parse the FV inf file for header information
+ //
+ Status = ParseFvInf (&InfMemoryFile, &FvInfo);
+ if (EFI_ERROR (Status)) {
+ printf ("ERROR: Could not parse the input INF file.\n");
+ return EFI_ABORTED;
+ }
+ //
+ // Update the file name return values
+ //
+ strcpy (*FvFileName, FvInfo.FvName);
+ strcpy (*SymFileName, FvInfo.SymName);
+
+ //
+ // Calculate the FV size
+ //
+ *FvImageSize = FvInfo.Size;
+
+ //
+ // Allocate the FV
+ //
+ *FvImage = malloc (*FvImageSize);
+ if (*FvImage == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ //
+ // Allocate space for symbol file storage
+ //
+ *SymImage = malloc (SYMBOL_FILE_SIZE);
+ if (*SymImage == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ //
+ // Initialize the FV to the erase polarity
+ //
+ if (FvInfo.FvAttributes & EFI_FVB_ERASE_POLARITY) {
+ memset (*FvImage, -1, *FvImageSize);
+ } else {
+ memset (*FvImage, 0, *FvImageSize);
+ }
+ //
+ // Initialize FV header
+ //
+ FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) *FvImage;
+
+ //
+ // Initialize the zero vector to all zeros.
+ //
+ memset (FvHeader->ZeroVector, 0, 16);
+
+ //
+ // Copy the FFS GUID
+ //
+ memcpy (&FvHeader->FileSystemGuid, &FvInfo.FvGuid, sizeof (EFI_GUID));
+
+ FvHeader->FvLength = *FvImageSize;
+ FvHeader->Signature = EFI_FVH_SIGNATURE;
+ FvHeader->Attributes = FvInfo.FvAttributes;
+ FvHeader->Revision = EFI_FVH_REVISION;
+ FvHeader->Reserved[0] = 0;
+ FvHeader->Reserved[1] = 0;
+ FvHeader->Reserved[2] = 0;
+
+ //
+ // Copy firmware block map
+ //
+ for (Index = 0; FvInfo.FvBlocks[Index].NumBlocks != 0; Index++) {
+ FvHeader->FvBlockMap[Index].NumBlocks = FvInfo.FvBlocks[Index].NumBlocks;
+ FvHeader->FvBlockMap[Index].BlockLength = FvInfo.FvBlocks[Index].BlockLength;
+ }
+ //
+ // Add block map terminator
+ //
+ FvHeader->FvBlockMap[Index].NumBlocks = 0;
+ FvHeader->FvBlockMap[Index].BlockLength = 0;
+
+ //
+ // Complete the header
+ //
+ FvHeader->HeaderLength = (UINT16) (((UINTN) &(FvHeader->FvBlockMap[Index + 1])) - (UINTN) *FvImage);
+ FvHeader->Checksum = 0;
+ FvHeader->Checksum = CalculateChecksum16 ((UINT16 *) FvHeader, FvHeader->HeaderLength / sizeof (UINT16));
+
+ //
+ // If there is no FFS file, find and generate each components of the FV
+ //
+ if (FvInfo.FvFiles[0][0] == 0) {
+ Status = GenNonFFSFv (*FvImage, &FvInfo);
+ if (EFI_ERROR (Status)) {
+ printf ("ERROR: Could not generate NonFFS FV.\n");
+ free (*FvImage);
+ return EFI_ABORTED;
+ }
+
+ return EFI_SUCCESS;
+ }
+ //
+ // Initialize our "file" view of the buffer
+ //
+ FvImageMemoryFile.FileImage = *FvImage;
+ FvImageMemoryFile.CurrentFilePointer = *FvImage + FvHeader->HeaderLength;
+ FvImageMemoryFile.Eof = *FvImage +*FvImageSize;
+
+ //
+ // Initialize our "file" view of the symbol file.
+ //
+ SymImageMemoryFile.FileImage = *SymImage;
+ SymImageMemoryFile.CurrentFilePointer = *SymImage;
+ SymImageMemoryFile.Eof = *FvImage + SYMBOL_FILE_SIZE;
+
+ //
+ // Initialize the FV library.
+ //
+ InitializeFvLib (FvImageMemoryFile.FileImage, FvInfo.Size);
+
+ //
+ // Files start on 8 byte alignments, so move to the next 8 byte aligned
+ // address. For now, just assert if it isn't. Currently FV header is
+ // always a multiple of 8 bytes.
+ // BUGBUG: Handle this better
+ //
+ assert ((((UINTN) FvImageMemoryFile.CurrentFilePointer) % 8) == 0);
+
+ //
+ // Initialize the VTF file address.
+ //
+ VtfFileImage = (EFI_FFS_FILE_HEADER *) FvImageMemoryFile.Eof;
+
+ //
+ // Add files to FV
+ //
+ for (Index = 0; FvInfo.FvFiles[Index][0] != 0; Index++) {
+ //
+ // Add the file
+ //
+ Status = AddFile (&FvImageMemoryFile, &FvInfo, Index, &VtfFileImage, &SymImageMemoryFile);
+
+ //
+ // Exit if error detected while adding the file
+ //
+ if (EFI_ERROR (Status)) {
+ printf ("ERROR: Could not add file %s.\n", FvInfo.FvFiles[Index]);
+ free (*FvImage);
+ return EFI_ABORTED;
+ }
+ }
+ //
+ // If there is a VTF file, some special actions need to occur.
+ //
+ if ((UINTN) VtfFileImage != (UINTN) FvImageMemoryFile.Eof) {
+ //
+ // Pad from the end of the last file to the beginning of the VTF file.
+ //
+ Status = PadFvImage (&FvImageMemoryFile, VtfFileImage);
+ if (EFI_ERROR (Status)) {
+ printf ("ERROR: Could not create the pad file between the last file and the VTF file.\n");
+ free (*FvImage);
+ return EFI_ABORTED;
+ }
+ //
+ // Update reset vector (SALE_ENTRY for IPF)
+ // Now for IA32 and IA64 platform, the fv which has bsf file must have the
+ // EndAddress of 0xFFFFFFFF. Thus, only this type fv needs to update the
+ // reset vector. If the PEI Core is found, the VTF file will probably get
+ // corrupted by updating the entry point.
+ //
+ if ((FvInfo.BaseAddress + FvInfo.Size) == FV_IMAGES_TOP_ADDRESS) {
+ Status = UpdateResetVector (&FvImageMemoryFile, &FvInfo, VtfFileImage);
+ if (EFI_ERROR(Status)) {
+ printf ("ERROR: Could not update the reset vector.\n");
+ free (*FvImage);
+ return EFI_ABORTED;
+ }
+ }
+ }
+ //
+ // Determine final Sym file size
+ //
+ *SymImageSize = SymImageMemoryFile.CurrentFilePointer - SymImageMemoryFile.FileImage;
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+UpdatePeiCoreEntryInFit (
+ IN FIT_TABLE *FitTablePtr,
+ IN UINT64 PeiCorePhysicalAddress
+ )
+/*++
+
+Routine Description:
+
+ This function is used to update the Pei Core address in FIT, this can be used by Sec core to pass control from
+ Sec to Pei Core
+
+Arguments:
+
+ FitTablePtr - The pointer of FIT_TABLE.
+ PeiCorePhysicalAddress - The address of Pei Core entry.
+
+Returns:
+
+ EFI_SUCCESS - The PEI_CORE FIT entry was updated successfully.
+ EFI_NOT_FOUND - Not found the PEI_CORE FIT entry.
+
+--*/
+{
+ FIT_TABLE *TmpFitPtr;
+ UINTN Index;
+ UINTN NumFitComponents;
+
+ TmpFitPtr = FitTablePtr;
+ NumFitComponents = TmpFitPtr->CompSize;
+
+ for (Index = 0; Index < NumFitComponents; Index++) {
+ if ((TmpFitPtr->CvAndType & FIT_TYPE_MASK) == COMP_TYPE_FIT_PEICORE) {
+ TmpFitPtr->CompAddress = PeiCorePhysicalAddress;
+ return EFI_SUCCESS;
+ }
+
+ TmpFitPtr++;
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+VOID
+UpdateFitCheckSum (
+ IN FIT_TABLE *FitTablePtr
+ )
+/*++
+
+Routine Description:
+
+ This function is used to update the checksum for FIT.
+
+
+Arguments:
+
+ FitTablePtr - The pointer of FIT_TABLE.
+
+Returns:
+
+ None.
+
+--*/
+{
+ if ((FitTablePtr->CvAndType & CHECKSUM_BIT_MASK) >> 7) {
+ FitTablePtr->CheckSum = 0;
+ FitTablePtr->CheckSum = CalculateChecksum8 ((UINT8 *) FitTablePtr, FitTablePtr->CompSize * 16);
+ }
+}
diff --git a/Source/GenFvImage/GenFvImageLib.h b/Source/GenFvImage/GenFvImageLib.h
new file mode 100644
index 0000000..47a5a3b
--- /dev/null
+++ b/Source/GenFvImage/GenFvImageLib.h
@@ -0,0 +1,142 @@
+/*++
+
+Copyright (c) 2004, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ GenFvImageLib.h
+
+Abstract:
+
+ This file contains describes the public interfaces to the GenFvImage Library.
+ The basic purpose of the library is to create Firmware Volume images.
+
+--*/
+
+#ifndef _EFI_GEN_FV_IMAGE_LIB_H
+#define _EFI_GEN_FV_IMAGE_LIB_H
+
+//
+// Include files
+//
+#include <Common/UefiBaseTypes.h>
+#include <Common/MultiPhase.h>
+
+#include "ParseInf.h"
+
+//
+// Following definition is used for FIT in IPF
+//
+#define COMP_TYPE_FIT_PEICORE 0x10
+#define COMP_TYPE_FIT_UNUSED 0x7F
+
+#define FIT_TYPE_MASK 0x7F
+#define CHECKSUM_BIT_MASK 0x80
+
+#pragma pack(1)
+
+typedef struct {
+ UINT64 CompAddress;
+ UINT32 CompSize;
+ UINT16 CompVersion;
+ UINT8 CvAndType;
+ UINT8 CheckSum;
+} FIT_TABLE;
+
+#pragma pack()
+//
+// Exported function prototypes
+//
+EFI_STATUS
+GenerateFvImage (
+ IN CHAR8 *InfFileImage,
+ IN UINTN InfFileSize,
+ OUT UINT8 **FvImage,
+ OUT UINTN *FvImageSize,
+ OUT CHAR8 **FvFileName,
+ OUT UINT8 **SymImage,
+ OUT UINTN *SymImageSize,
+ OUT CHAR8 **SymFileName
+ )
+;
+
+/*++
+
+Routine Description:
+
+ This is the main function which will be called from application.
+
+Arguments:
+
+ InfFileImage Buffer containing the INF file contents.
+ InfFileSize Size of the contents of the InfFileImage buffer.
+ FvImage Pointer to the FV image created.
+ FvImageSize Size of the FV image created and pointed to by FvImage.
+ FvFileName Requested name for the FV file.
+ SymImage Pointer to the Sym image created.
+ SymImageSize Size of the Sym image created and pointed to by SymImage.
+ SymFileName Requested name for the Sym file.
+
+Returns:
+
+ EFI_SUCCESS Function completed successfully.
+ EFI_OUT_OF_RESOURCES Could not allocate required resources.
+ EFI_ABORTED Error encountered.
+ EFI_INVALID_PARAMETER A required parameter was NULL.
+
+--*/
+EFI_STATUS
+UpdatePeiCoreEntryInFit (
+ IN FIT_TABLE *FitTablePtr,
+ IN UINT64 PeiCorePhysicalAddress
+ )
+;
+
+/*++
+
+Routine Description:
+
+ This function is used to update the Pei Core address in FIT, this can be used by Sec core to pass control from
+ Sec to Pei Core
+
+Arguments:
+
+ FitTablePtr - The pointer of FIT_TABLE.
+ PeiCorePhysicalAddress - The address of Pei Core entry.
+
+Returns:
+
+ EFI_SUCCESS - The PEI_CORE FIT entry was updated successfully.
+ EFI_NOT_FOUND - Not found the PEI_CORE FIT entry.
+
+--*/
+VOID
+UpdateFitCheckSum (
+ IN FIT_TABLE *FitTablePtr
+ )
+;
+
+/*++
+
+Routine Description:
+
+ This function is used to update the checksum for FIT.
+
+
+Arguments:
+
+ FitTablePtr - The pointer of FIT_TABLE.
+
+Returns:
+
+ None.
+
+--*/
+#endif
diff --git a/Source/GenFvImage/GenFvImageLibInternal.h b/Source/GenFvImage/GenFvImageLibInternal.h
new file mode 100644
index 0000000..cff3b1a
--- /dev/null
+++ b/Source/GenFvImage/GenFvImageLibInternal.h
@@ -0,0 +1,172 @@
+/*++
+
+Copyright (c) 2004, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ GenFvImageLibInternal.h
+
+Abstract:
+
+ This file contains describes the private declarations for the GenFvImage Library.
+ The basic purpose of the library is to create Firmware Volume images.
+
+--*/
+
+#ifndef _EFI_GEN_FV_IMAGE_LIB_INTERNAL_H
+#define _EFI_GEN_FV_IMAGE_LIB_INTERNAL_H
+
+//
+// Include files
+//
+#include <stdlib.h>
+
+#include <Common/FirmwareVolumeHeader.h>
+
+#include "CommonLib.h"
+#include "GenFvImageLib.h"
+
+//
+// Private data declarations
+//
+//
+// The maximum number of block map entries supported by the library
+//
+#define MAX_NUMBER_OF_FV_BLOCKS 100
+
+//
+// The maximum number of files in the FV supported by the library
+//
+#define MAX_NUMBER_OF_FILES_IN_FV 1000
+#define MAX_NUMBER_OF_COMPONENTS_IN_FV 10
+
+//
+// INF file strings
+//
+#define OPTIONS_SECTION_STRING "[options]"
+#define ATTRIBUTES_SECTION_STRING "[attributes]"
+#define FILES_SECTION_STRING "[files]"
+#define COMPONENT_SECTION_STRING "[components]"
+
+#define EFI_FV_BASE_ADDRESS_STRING "EFI_BASE_ADDRESS"
+#define EFI_FV_FILE_NAME_STRING "EFI_FILE_NAME"
+#define EFI_SYM_FILE_NAME_STRING "EFI_SYM_FILE_NAME"
+#define EFI_NUM_BLOCKS_STRING "EFI_NUM_BLOCKS"
+#define EFI_BLOCK_SIZE_STRING "EFI_BLOCK_SIZE"
+#define EFI_FV_GUID_STRING "EFI_FV_GUID"
+
+#define EFI_FVB_READ_DISABLED_CAP_STRING "EFI_READ_DISABLED_CAP"
+#define EFI_FVB_READ_ENABLED_CAP_STRING "EFI_READ_ENABLED_CAP"
+#define EFI_FVB_READ_STATUS_STRING "EFI_READ_STATUS"
+
+#define EFI_FVB_WRITE_DISABLED_CAP_STRING "EFI_WRITE_DISABLED_CAP"
+#define EFI_FVB_WRITE_ENABLED_CAP_STRING "EFI_WRITE_ENABLED_CAP"
+#define EFI_FVB_WRITE_STATUS_STRING "EFI_WRITE_STATUS"
+
+#define EFI_FVB_LOCK_CAP_STRING "EFI_LOCK_CAP"
+#define EFI_FVB_LOCK_STATUS_STRING "EFI_LOCK_STATUS"
+
+#define EFI_FVB_STICKY_WRITE_STRING "EFI_STICKY_WRITE"
+#define EFI_FVB_MEMORY_MAPPED_STRING "EFI_MEMORY_MAPPED"
+#define EFI_FVB_ERASE_POLARITY_STRING "EFI_ERASE_POLARITY"
+
+#define EFI_FVB_ALIGNMENT_CAP_STRING "EFI_ALIGNMENT_CAP"
+#define EFI_FVB_ALIGNMENT_2_STRING "EFI_ALIGNMENT_2"
+#define EFI_FVB_ALIGNMENT_4_STRING "EFI_ALIGNMENT_4"
+#define EFI_FVB_ALIGNMENT_8_STRING "EFI_ALIGNMENT_8"
+#define EFI_FVB_ALIGNMENT_16_STRING "EFI_ALIGNMENT_16"
+#define EFI_FVB_ALIGNMENT_32_STRING "EFI_ALIGNMENT_32"
+#define EFI_FVB_ALIGNMENT_64_STRING "EFI_ALIGNMENT_64"
+#define EFI_FVB_ALIGNMENT_128_STRING "EFI_ALIGNMENT_128"
+#define EFI_FVB_ALIGNMENT_256_STRING "EFI_ALIGNMENT_256"
+#define EFI_FVB_ALIGNMENT_512_STRING "EFI_ALIGNMENT_512"
+#define EFI_FVB_ALIGNMENT_1K_STRING "EFI_ALIGNMENT_1K"
+#define EFI_FVB_ALIGNMENT_2K_STRING "EFI_ALIGNMENT_2K"
+#define EFI_FVB_ALIGNMENT_4K_STRING "EFI_ALIGNMENT_4K"
+#define EFI_FVB_ALIGNMENT_8K_STRING "EFI_ALIGNMENT_8K"
+#define EFI_FVB_ALIGNMENT_16K_STRING "EFI_ALIGNMENT_16K"
+#define EFI_FVB_ALIGNMENT_32K_STRING "EFI_ALIGNMENT_32K"
+#define EFI_FVB_ALIGNMENT_64K_STRING "EFI_ALIGNMENT_64K"
+
+//
+// Component sections
+//
+#define EFI_NV_VARIABLE_STRING "EFI_NV_VARIABLE"
+#define EFI_NV_EVENT_LOG_STRING "EFI_NV_EVENT_LOG"
+#define EFI_NV_FTW_WORKING_STRING "EFI_NV_FTW_WORKING"
+#define EFI_NV_FTW_SPARE_STRING "EFI_NV_FTW_SPARE"
+
+#define EFI_FILE_NAME_STRING "EFI_FILE_NAME"
+
+#define ONE_STRING "1"
+#define ZERO_STRING "0"
+#define TRUE_STRING "TRUE"
+#define FALSE_STRING "FALSE"
+#define NULL_STRING "NULL"
+
+//
+// Defines to calculate the offset for PEI CORE entry points
+//
+#define IA32_PEI_CORE_ENTRY_OFFSET 0x20
+
+//
+// Defines to calculate the FIT table
+//
+#define IPF_FIT_ADDRESS_OFFSET 0x20
+
+//
+// Defines to calculate the offset for SALE_ENTRY
+//
+#define IPF_SALE_ENTRY_ADDRESS_OFFSET 0x18
+
+//
+// Symbol file definitions, current max size if 512K
+//
+#define SYMBOL_FILE_SIZE 0x80000
+
+#define FV_IMAGES_TOP_ADDRESS 0x100000000ULL
+
+//
+// Private data types
+//
+//
+// Component information
+//
+typedef struct {
+ UINTN Size;
+ CHAR8 ComponentName[_MAX_PATH];
+} COMPONENT_INFO;
+
+//
+// FV information holder
+//
+typedef struct {
+ EFI_PHYSICAL_ADDRESS BaseAddress;
+ EFI_GUID FvGuid;
+ UINTN Size;
+ CHAR8 FvName[_MAX_PATH];
+ CHAR8 SymName[_MAX_PATH];
+ EFI_FV_BLOCK_MAP_ENTRY FvBlocks[MAX_NUMBER_OF_FV_BLOCKS];
+ EFI_FVB_ATTRIBUTES FvAttributes;
+ CHAR8 FvFiles[MAX_NUMBER_OF_FILES_IN_FV][_MAX_PATH];
+ COMPONENT_INFO FvComponents[MAX_NUMBER_OF_COMPONENTS_IN_FV];
+} FV_INFO;
+
+//
+// Private function prototypes
+//
+EFI_STATUS
+ParseFvInf (
+ IN MEMORY_FILE *InfFile,
+ IN FV_INFO *FvInfo
+ )
+;
+
+#endif
diff --git a/Source/GenFvImage/build.xml b/Source/GenFvImage/build.xml
new file mode 100644
index 0000000..421b38f
--- /dev/null
+++ b/Source/GenFvImage/build.xml
@@ -0,0 +1,126 @@
+<?xml version="1.0" ?>
+<!--
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+-->
+<project default="GenTool" basedir=".">
+<!--
+ EDK GenFvImage Tool
+ Copyright (c) 2006, Intel Corporation
+-->
+ <property name="ToolName" value="GenFvImage"/>
+ <property name="FileSet" value="GenFvImageLib.c GenFvImageExe.c"/>
+
+ <taskdef resource="net/sf/antcontrib/antlib.xml"/>
+
+ <property name="LINK_OUTPUT_TYPE" value="static"/>
+ <property name="BUILD_DIR" value="${PACKAGE_DIR}/${ToolName}/tmp"/>
+
+ <target name="GenTool" depends="init, Tool">
+ <echo message="The EDK Tool: ${ToolName} build has completed"/>
+ </target>
+
+ <target name="init">
+ <echo message="Building the EDK Tool: ${ToolName}"/>
+ <mkdir dir="${BUILD_DIR}"/>
+ <if>
+ <istrue value="${OSX}"/>
+ <then>
+ <property name="syslibdirs" value=""/>
+ <property name="syslibs" value=""/>
+ </then>
+ </if>
+
+ <if>
+ <istrue value="${cygwin}"/>
+ <then>
+ <property name="syslibdirs" value="${env.CYGWIN_HOME}/lib/e2fsprogs"/>
+ <property name="syslibs" value="uuid"/>
+ </then>
+ </if>
+
+ <if>
+ <istrue value="${msft}"/>
+ <then>
+ <property name="syslibdirs" value=""/>
+ <property name="syslibs" value="uuid"/>
+ </then>
+ </if>
+
+ <if>
+ <istrue value="${linux}"/>
+ <then>
+ <if>
+ <istrue value="${x86_64_linux}"/>
+ <then>
+ <property name="syslibdirs" value="/lib64"/>
+ </then>
+ <else>
+ <property name="syslibdirs" value="/usr/lib"/>
+ </else>
+ </if>
+ <property name="syslibs" value="uuid"/>
+ </then>
+ </if>
+ <echo message="syslibdirs set to: ${syslibdirs}"/>
+ </target>
+
+ <target name="Tool" depends="init, GenFvImage"/>
+
+ <target name="GenFvImage" >
+ <cc name="${ToolChain}" objdir="${BUILD_DIR}"
+ outfile="${BIN_DIR}/${ToolName}"
+ outtype="executable"
+ debug="true"
+ optimize="speed">
+ <compilerarg value="${ExtraArgus}" if="ExtraArgus" />
+
+ <defineset>
+ <define name="BUILDING_TOOLS"/>
+ <define name="TOOL_BUILD_IA32_TARGET"/>
+ </defineset>
+
+ <fileset dir="${basedir}/${ToolName}"
+ includes="${FileSet}"/>
+
+ <includepath path="${PACKAGE_DIR}/${ToolName}"/>
+ <includepath path="${PACKAGE_DIR}/Include"/>
+ <includepath path="${PACKAGE_DIR}/Include/${HostArch}"/>
+ <includepath path="${PACKAGE_DIR}/Common"/>
+ <libset dir="${LIB_DIR}" libs="CommonTools"/>
+
+ <linkerarg value="/nodefaultlib:libc.lib" if="msft"/>
+ <syslibset dir="${syslibdirs}" libs="${syslibs}" if="cyglinux"/>
+ <syslibset libs="RpcRT4" if="msft"/>
+ </cc>
+ </target>
+
+ <target name="clean">
+ <echo message="Removing Intermediate Files Only"/>
+ <delete>
+ <fileset dir="${BUILD_DIR}" includes="*.obj"/>
+ </delete>
+ </target>
+
+ <target name="cleanall">
+ <echo message="Removing Object Files and the Executable: ${ToolName}${ext_exe}"/>
+ <delete failonerror="false" quiet="true" includeEmptyDirs="true">
+ <fileset dir="${BUILD_DIR}"/>
+ <fileset file="${BIN_DIR}/${ToolName}_Ia32${ext_exe}"/>
+ <fileset file="${BIN_DIR}/${ToolName}_X64${ext_exe}"/>
+ <fileset file="${BIN_DIR}/${ToolName}${ext_exe}"/>
+ <fileset file="${BIN_DIR}/${ToolName}_Ipf${ext_exe}"/>
+ <fileset file="${BIN_DIR}/${ToolName}_Ia32.pdb"/>
+ <fileset file="${BIN_DIR}/${ToolName}_X64.pdb"/>
+ <fileset file="${BIN_DIR}/${ToolName}.pdb"/>
+ <fileset file="${BIN_DIR}/${ToolName}_Ipf.pdb"/>
+ </delete>
+ </target>
+
+</project>
diff --git a/Source/GenSection/GenSection.c b/Source/GenSection/GenSection.c
new file mode 100644
index 0000000..353b1a3
--- /dev/null
+++ b/Source/GenSection/GenSection.c
@@ -0,0 +1,938 @@
+/*++
+
+Copyright (c) 2004, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ GenSection.c
+
+Abstract:
+
+ Creates output file that is a properly formed section per the FV spec.
+
+--*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <Common/UefiBaseTypes.h>
+#include <Common/FirmwareVolumeImageFormat.h>
+#include <Protocol/GuidedSectionExtraction.h>
+
+#include "CommonLib.h"
+#include "EfiCompress.h"
+#include "EfiCustomizedCompress.h"
+#include "Crc32.h"
+#include "EfiUtilityMsgs.h"
+#include "GenSection.h"
+
+
+#define UTILITY_NAME "GenSection"
+
+#define PARAMETER_NOT_SPECIFIED "Parameter not specified"
+#define MAXIMUM_INPUT_FILE_NUM 10
+
+char *SectionTypeName[] = {
+ NULL, // 0x00 - reserved
+ "EFI_SECTION_COMPRESSION", // 0x01
+ "EFI_SECTION_GUID_DEFINED", // 0x02
+ NULL, // 0x03 - reserved
+ NULL, // 0x04 - reserved
+ NULL, // 0x05 - reserved
+ NULL, // 0x06 - reserved
+ NULL, // 0x07 - reserved
+ NULL, // 0x08 - reserved
+ NULL, // 0x09 - reserved
+ NULL, // 0x0A - reserved
+ NULL, // 0x0B - reserved
+ NULL, // 0x0C - reserved
+ NULL, // 0x0D - reserved
+ NULL, // 0x0E - reserved
+ NULL, // 0x0F - reserved
+ "EFI_SECTION_PE32", // 0x10
+ "EFI_SECTION_PIC", // 0x11
+ "EFI_SECTION_TE", // 0x12
+ "EFI_SECTION_DXE_DEPEX", // 0x13
+ "EFI_SECTION_VERSION", // 0x14
+ "EFI_SECTION_USER_INTERFACE", // 0x15
+ "EFI_SECTION_COMPATIBILITY16", // 0x16
+ "EFI_SECTION_FIRMWARE_VOLUME_IMAGE", // 0x17
+ "EFI_SECTION_FREEFORM_SUBTYPE_GUID", // 0x18
+ "EFI_SECTION_RAW", // 0x19
+ NULL, // 0x1A
+ "EFI_SECTION_PEI_DEPEX" // 0x1B
+};
+
+char *CompressionTypeName[] = { "NONE", "STANDARD" };
+char *GUIDedSectionTypeName[] = { "CRC32" };
+EFI_GUID gEfiCrc32SectionGuid = EFI_CRC32_GUIDED_SECTION_EXTRACTION_PROTOCOL_GUID;
+
+static
+VOID
+PrintUsageMessage (
+ VOID
+ )
+{
+ UINTN SectionType;
+ UINTN DisplayCount;
+
+ printf ("Usage: "UTILITY_NAME " -i InputFile -o OutputFile -s SectionType [SectionType params]\n\n");
+ printf (" Where SectionType is one of the following section types:\n\n");
+
+ DisplayCount = 0;
+ for (SectionType = 0; SectionType <= EFI_SECTION_LAST_SECTION_TYPE; SectionType++) {
+ if (SectionTypeName[SectionType] != NULL) {
+ printf (" %s\n", SectionTypeName[SectionType]);
+ }
+ }
+
+ printf ("\n and SectionType dependent parameters are as follows:\n\n");
+ printf (
+ " %s: -t < %s | %s >\n",
+ SectionTypeName[EFI_SECTION_COMPRESSION],
+ CompressionTypeName[EFI_NOT_COMPRESSED],
+ CompressionTypeName[EFI_STANDARD_COMPRESSION]
+ );
+ printf (
+ " %s: -t < %s >\n"" // Currently only CRC32 is supported\n\n",
+ SectionTypeName[EFI_SECTION_GUID_DEFINED],
+ GUIDedSectionTypeName[EFI_SECTION_CRC32_GUID_DEFINED]
+ );
+ printf (
+ " %s: -v VersionNumber\n"" [-a \"Version string\"]\n\n",
+ SectionTypeName[EFI_SECTION_VERSION]
+ );
+ printf (
+ " %s: -a \"Human readable name\"\n\n",
+ SectionTypeName[EFI_SECTION_USER_INTERFACE]
+ );
+}
+
+VOID
+Ascii2UnicodeWriteString (
+ char *String,
+ FILE *OutFile,
+ BOOLEAN WriteLangCode
+ )
+{
+ UINTN Index;
+ UINT8 AsciiNull;
+ //
+ // BUGBUG need to get correct language code...
+ //
+ char *EnglishLangCode = "eng";
+ AsciiNull = 0;
+ //
+ // first write the language code (english only)
+ //
+ if (WriteLangCode) {
+ fwrite (EnglishLangCode, 1, 4, OutFile);
+ }
+ //
+ // Next, write out the string... Convert ASCII to Unicode in the process.
+ //
+ Index = 0;
+ do {
+ fwrite (&String[Index], 1, 1, OutFile);
+ fwrite (&AsciiNull, 1, 1, OutFile);
+ } while (String[Index++] != 0);
+}
+
+STATUS
+GenSectionCommonLeafSection (
+ char **InputFileName,
+ int InputFileNum,
+ UINTN SectionType,
+ FILE *OutFile
+ )
+/*++
+
+Routine Description:
+
+ Generate a leaf section of type other than EFI_SECTION_VERSION
+ and EFI_SECTION_USER_INTERFACE. Input file must be well formed.
+ The function won't validate the input file's contents. For
+ common leaf sections, the input file may be a binary file.
+ The utility will add section header to the file.
+
+Arguments:
+
+ InputFileName - Name of the input file.
+
+ InputFileNum - Number of input files. Should be 1 for leaf section.
+
+ SectionType - A valid section type string
+
+ OutFile - Output file handle
+
+Returns:
+
+ STATUS_ERROR - can't continue
+ STATUS_SUCCESS - successful return
+
+--*/
+{
+ UINT64 InputFileLength;
+ FILE *InFile;
+ UINT8 *Buffer;
+ INTN TotalLength;
+ EFI_COMMON_SECTION_HEADER CommonSect;
+ STATUS Status;
+
+ if (InputFileNum > 1) {
+ Error (NULL, 0, 0, "invalid parameter", "more than one input file specified");
+ return STATUS_ERROR;
+ } else if (InputFileNum < 1) {
+ Error (NULL, 0, 0, "no input file specified", NULL);
+ return STATUS_ERROR;
+ }
+ //
+ // Open the input file
+ //
+ InFile = fopen (InputFileName[0], "rb");
+ if (InFile == NULL) {
+ Error (NULL, 0, 0, InputFileName[0], "failed to open input file");
+ return STATUS_ERROR;
+ }
+
+ Status = STATUS_ERROR;
+ Buffer = NULL;
+ //
+ // Seek to the end of the input file so we can determine its size
+ //
+ fseek (InFile, 0, SEEK_END);
+ fgetpos (InFile, &InputFileLength);
+ fseek (InFile, 0, SEEK_SET);
+ //
+ // Fill in the fields in the local section header structure
+ //
+ CommonSect.Type = (EFI_SECTION_TYPE) SectionType;
+ TotalLength = sizeof (CommonSect) + (INTN) InputFileLength;
+ //
+ // Size must fit in 3 bytes
+ //
+ if (TotalLength >= 0x1000000) {
+ Error (NULL, 0, 0, InputFileName[0], "file size (0x%X) exceeds section size limit", TotalLength);
+ goto Done;
+ }
+ //
+ // Now copy the size into the section header and write out the section header
+ //
+ memcpy (&CommonSect.Size, &TotalLength, 3);
+ fwrite (&CommonSect, sizeof (CommonSect), 1, OutFile);
+ //
+ // Allocate a buffer to read in the contents of the input file. Then
+ // read it in as one block and write it to the output file.
+ //
+ if (InputFileLength != 0) {
+ Buffer = (UINT8 *) malloc ((size_t) InputFileLength);
+ if (Buffer == NULL) {
+ Error (__FILE__, __LINE__, 0, "memory allocation failure", NULL);
+ goto Done;
+ }
+
+ if (fread (Buffer, (size_t) InputFileLength, 1, InFile) != 1) {
+ Error (NULL, 0, 0, InputFileName[0], "failed to read contents of file");
+ goto Done;
+ }
+
+ if (fwrite (Buffer, (size_t) InputFileLength, 1, OutFile) != 1) {
+ Error (NULL, 0, 0, "failed to write to output file", NULL);
+ goto Done;
+ }
+ }
+
+ Status = STATUS_SUCCESS;
+Done:
+ fclose (InFile);
+ if (Buffer != NULL) {
+ free (Buffer);
+ }
+
+ return Status;
+}
+
+EFI_STATUS
+GetSectionContents (
+ char **InputFileName,
+ int InputFileNum,
+ UINT8 *FileBuffer,
+ UINTN *BufferLength
+ )
+/*++
+
+Routine Description:
+
+ Get the contents of all section files specified in InputFileName
+ into FileBuffer.
+
+Arguments:
+
+ InputFileName - Name of the input file.
+
+ InputFileNum - Number of input files. Should be at least 1.
+
+ FileBuffer - Output buffer to contain data
+
+ BufferLength - Actual length of the data
+
+Returns:
+
+ EFI_SUCCESS on successful return
+ EFI_INVALID_PARAMETER if InputFileNum is less than 1
+ EFI_ABORTED if unable to open input file.
+
+--*/
+{
+ UINTN Size;
+ UINTN FileSize;
+ INTN Index;
+ FILE *InFile;
+
+ if (InputFileNum < 1) {
+ Error (NULL, 0, 0, "must specify at least one input file", NULL);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Size = 0;
+ //
+ // Go through our array of file names and copy their contents
+ // to the output buffer.
+ //
+ for (Index = 0; Index < InputFileNum; Index++) {
+ InFile = fopen (InputFileName[Index], "rb");
+ if (InFile == NULL) {
+ Error (NULL, 0, 0, InputFileName[Index], "failed to open input file");
+ return EFI_ABORTED;
+ }
+
+ fseek (InFile, 0, SEEK_END);
+ FileSize = ftell (InFile);
+ fseek (InFile, 0, SEEK_SET);
+ //
+ // Now read the contents of the file into the buffer
+ //
+ if (FileSize > 0) {
+ if (fread (FileBuffer + Size, (size_t) FileSize, 1, InFile) != 1) {
+ Error (NULL, 0, 0, InputFileName[Index], "failed to read contents of input file");
+ fclose (InFile);
+ return EFI_ABORTED;
+ }
+ }
+
+ fclose (InFile);
+ Size += (UINTN) FileSize;
+ //
+ // make sure section ends on a DWORD boundary
+ //
+ while ((Size & 0x03) != 0) {
+ FileBuffer[Size] = 0;
+ Size++;
+ }
+ }
+
+ *BufferLength = Size;
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+GenSectionCompressionSection (
+ char **InputFileName,
+ int InputFileNum,
+ UINTN SectionType,
+ UINTN SectionSubType,
+ FILE *OutFile
+ )
+/*++
+
+Routine Description:
+
+ Generate an encapsulating section of type EFI_SECTION_COMPRESSION
+ Input file must be already sectioned. The function won't validate
+ the input files' contents. Caller should hand in files already
+ with section header.
+
+Arguments:
+
+ InputFileName - Name of the input file.
+
+ InputFileNum - Number of input files. Should be at least 1.
+
+ SectionType - Section type to generate. Should be
+ EFI_SECTION_COMPRESSION
+
+ SectionSubType - Specify the compression algorithm requested.
+
+ OutFile - Output file handle
+
+Returns:
+
+ EFI_SUCCESS on successful return
+ EFI_INVALID_PARAMETER if InputFileNum is less than 1
+ EFI_ABORTED if unable to open input file.
+ EFI_OUT_OF_RESOURCES No resource to complete the operation.
+--*/
+{
+ UINTN TotalLength;
+ UINTN InputLength;
+ UINTN CompressedLength;
+ UINT8 *FileBuffer;
+ UINT8 *OutputBuffer;
+ EFI_STATUS Status;
+ EFI_COMPRESSION_SECTION CompressionSect;
+ COMPRESS_FUNCTION CompressFunction;
+
+ if (SectionType != EFI_SECTION_COMPRESSION) {
+ Error (NULL, 0, 0, "parameter must be EFI_SECTION_COMPRESSION", NULL);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ InputLength = 0;
+ FileBuffer = NULL;
+ OutputBuffer = NULL;
+ CompressedLength = 0;
+ FileBuffer = (UINT8 *) malloc ((1024 * 1024 * 4) * sizeof (UINT8));
+ if (FileBuffer == NULL) {
+ Error (__FILE__, __LINE__, 0, "application error", "failed to allocate memory");
+ return EFI_OUT_OF_RESOURCES;
+ }
+ //
+ // read all input file contents into a buffer
+ //
+ Status = GetSectionContents (
+ InputFileName,
+ InputFileNum,
+ FileBuffer,
+ &InputLength
+ );
+ if (EFI_ERROR (Status)) {
+ free (FileBuffer);
+ return Status;
+ }
+
+ CompressFunction = NULL;
+
+ //
+ // Now data is in FileBuffer, compress the data
+ //
+ switch (SectionSubType) {
+ case EFI_NOT_COMPRESSED:
+ CompressedLength = InputLength;
+ break;
+
+ case EFI_STANDARD_COMPRESSION:
+ CompressFunction = (COMPRESS_FUNCTION) Compress;
+ break;
+
+ case EFI_CUSTOMIZED_COMPRESSION:
+ CompressFunction = (COMPRESS_FUNCTION) CustomizedCompress;
+ break;
+
+ default:
+ Error (NULL, 0, 0, "unknown compression type", NULL);
+ free (FileBuffer);
+ return EFI_ABORTED;
+ }
+
+ if (CompressFunction != NULL) {
+
+ Status = CompressFunction (FileBuffer, InputLength, OutputBuffer, &CompressedLength);
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+ OutputBuffer = malloc (CompressedLength);
+ if (!OutputBuffer) {
+ free (FileBuffer);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Status = CompressFunction (FileBuffer, InputLength, OutputBuffer, &CompressedLength);
+ }
+
+ free (FileBuffer);
+ FileBuffer = OutputBuffer;
+
+ if (EFI_ERROR (Status)) {
+ if (FileBuffer != NULL) {
+ free (FileBuffer);
+ }
+
+ return Status;
+ }
+ }
+
+ TotalLength = CompressedLength + sizeof (EFI_COMPRESSION_SECTION);
+ //
+ // Add the section header for the compressed data
+ //
+ CompressionSect.CommonHeader.Type = (EFI_SECTION_TYPE) SectionType;
+ CompressionSect.CommonHeader.Size[0] = (UINT8) (TotalLength & 0xff);
+ CompressionSect.CommonHeader.Size[1] = (UINT8) ((TotalLength & 0xff00) >> 8);
+ CompressionSect.CommonHeader.Size[2] = (UINT8) ((TotalLength & 0xff0000) >> 16);
+ CompressionSect.CompressionType = (UINT8) SectionSubType;
+ CompressionSect.UncompressedLength = InputLength;
+
+ fwrite (&CompressionSect, sizeof (CompressionSect), 1, OutFile);
+ fwrite (FileBuffer, CompressedLength, 1, OutFile);
+ free (FileBuffer);
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+GenSectionGuidDefinedSection (
+ char **InputFileName,
+ int InputFileNum,
+ UINTN SectionType,
+ UINTN SectionSubType,
+ FILE *OutFile
+ )
+/*++
+
+Routine Description:
+
+ Generate an encapsulating section of type EFI_SECTION_GUID_DEFINED
+ Input file must be already sectioned. The function won't validate
+ the input files' contents. Caller should hand in files already
+ with section header.
+
+Arguments:
+
+ InputFileName - Name of the input file.
+
+ InputFileNum - Number of input files. Should be at least 1.
+
+ SectionType - Section type to generate. Should be
+ EFI_SECTION_GUID_DEFINED
+
+ SectionSubType - Specify the authentication algorithm requested.
+
+ OutFile - Output file handle
+
+Returns:
+
+ EFI_SUCCESS on successful return
+ EFI_INVALID_PARAMETER if InputFileNum is less than 1
+ EFI_ABORTED if unable to open input file.
+ EFI_OUT_OF_RESOURCES No resource to complete the operation.
+
+--*/
+{
+ INTN TotalLength;
+ INTN InputLength;
+ UINT8 *FileBuffer;
+ UINT32 Crc32Checksum;
+ EFI_STATUS Status;
+ CRC32_SECTION_HEADER Crc32GuidSect;
+
+ if (SectionType != EFI_SECTION_GUID_DEFINED) {
+ Error (NULL, 0, 0, "parameter must be EFI_SECTION_GUID_DEFINED", NULL);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ InputLength = 0;
+ FileBuffer = NULL;
+ FileBuffer = (UINT8 *) malloc ((1024 * 1024 * 4) * sizeof (UINT8));
+ if (FileBuffer == NULL) {
+ Error (__FILE__, __LINE__, 0, "application error", "failed to allocate memory");
+ return EFI_OUT_OF_RESOURCES;
+ }
+ //
+ // read all input file contents into a buffer
+ //
+ Status = GetSectionContents (
+ InputFileName,
+ InputFileNum,
+ FileBuffer,
+ &InputLength
+ );
+ if (EFI_ERROR (Status)) {
+ free (FileBuffer);
+ return Status;
+ }
+ //
+ // Now data is in FileBuffer, compress the data
+ //
+ switch (SectionSubType) {
+ case EFI_SECTION_CRC32_GUID_DEFINED:
+ Crc32Checksum = 0;
+ CalculateCrc32 (FileBuffer, InputLength, &Crc32Checksum);
+ if (EFI_ERROR (Status)) {
+ free (FileBuffer);
+ return Status;
+ }
+
+ TotalLength = InputLength + CRC32_SECTION_HEADER_SIZE;
+ Crc32GuidSect.GuidSectionHeader.CommonHeader.Type = (EFI_SECTION_TYPE) SectionType;
+ Crc32GuidSect.GuidSectionHeader.CommonHeader.Size[0] = (UINT8) (TotalLength & 0xff);
+ Crc32GuidSect.GuidSectionHeader.CommonHeader.Size[1] = (UINT8) ((TotalLength & 0xff00) >> 8);
+ Crc32GuidSect.GuidSectionHeader.CommonHeader.Size[2] = (UINT8) ((TotalLength & 0xff0000) >> 16);
+ memcpy (&(Crc32GuidSect.GuidSectionHeader.SectionDefinitionGuid), &gEfiCrc32SectionGuid, sizeof (EFI_GUID));
+ Crc32GuidSect.GuidSectionHeader.Attributes = EFI_GUIDED_SECTION_AUTH_STATUS_VALID;
+ Crc32GuidSect.GuidSectionHeader.DataOffset = CRC32_SECTION_HEADER_SIZE;
+ Crc32GuidSect.CRC32Checksum = Crc32Checksum;
+
+ break;
+
+ default:
+ Error (NULL, 0, 0, "invalid parameter", "unknown GUID defined type");
+ free (FileBuffer);
+ return EFI_ABORTED;
+ }
+
+ fwrite (&Crc32GuidSect, sizeof (Crc32GuidSect), 1, OutFile);
+ fwrite (FileBuffer, InputLength, 1, OutFile);
+
+ free (FileBuffer);
+
+ return EFI_SUCCESS;
+}
+
+int
+main (
+ int argc,
+ char *argv[]
+ )
+/*++
+
+Routine Description:
+
+ Main
+
+Arguments:
+
+ command line parameters
+
+Returns:
+
+ EFI_SUCCESS Section header successfully generated and section concatenated.
+ EFI_ABORTED Could not generate the section
+ EFI_OUT_OF_RESOURCES No resource to complete the operation.
+
+--*/
+{
+ INTN Index;
+ INTN VersionNumber;
+ UINTN SectionType;
+ UINTN SectionSubType;
+ BOOLEAN InputFileRequired;
+ BOOLEAN SubTypeRequired;
+ FILE *InFile;
+ FILE *OutFile;
+ INTN InputFileNum;
+
+ char **InputFileName;
+ char *OutputFileName;
+ char AuxString[500] = { 0 };
+
+ char *ParamSectionType;
+ char *ParamSectionSubType;
+ char *ParamLength;
+ char *ParamVersion;
+ char *ParamDigitalSignature;
+
+ EFI_STATUS Status;
+ EFI_COMMON_SECTION_HEADER CommonSect;
+
+ InputFileName = NULL;
+ OutputFileName = PARAMETER_NOT_SPECIFIED;
+ ParamSectionType = PARAMETER_NOT_SPECIFIED;
+ ParamSectionSubType = PARAMETER_NOT_SPECIFIED;
+ ParamLength = PARAMETER_NOT_SPECIFIED;
+ ParamVersion = PARAMETER_NOT_SPECIFIED;
+ ParamDigitalSignature = PARAMETER_NOT_SPECIFIED;
+ Status = EFI_SUCCESS;
+
+ VersionNumber = 0;
+ SectionType = 0;
+ SectionSubType = 0;
+ InputFileRequired = TRUE;
+ SubTypeRequired = FALSE;
+ InFile = NULL;
+ OutFile = NULL;
+ InputFileNum = 0;
+ Status = EFI_SUCCESS;
+
+ SetUtilityName (UTILITY_NAME);
+ if (argc == 1) {
+ PrintUsageMessage ();
+ return STATUS_ERROR;
+ }
+ //
+ // Parse command line
+ //
+ Index = 1;
+ while (Index < argc) {
+ if (strcmpi (argv[Index], "-i") == 0) {
+ //
+ // Input File found
+ //
+ Index++;
+ InputFileName = (char **) malloc (MAXIMUM_INPUT_FILE_NUM * sizeof (char *));
+ if (InputFileName == NULL) {
+ Error (__FILE__, __LINE__, 0, "application error", "failed to allocate memory");
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ memset (InputFileName, 0, (MAXIMUM_INPUT_FILE_NUM * sizeof (char *)));
+ InputFileName[InputFileNum] = argv[Index];
+ InputFileNum++;
+ Index++;
+ //
+ // Parse subsequent parameters until another switch is encountered
+ //
+ while ((Index < argc) && (argv[Index][0] != '-')) {
+ if ((InputFileNum % MAXIMUM_INPUT_FILE_NUM) == 0) {
+ //
+ // InputFileName buffer too small, need to realloc
+ //
+ InputFileName = (char **) realloc (
+ InputFileName,
+ (InputFileNum + MAXIMUM_INPUT_FILE_NUM) * sizeof (char *)
+ );
+ if (InputFileName == NULL) {
+ Error (__FILE__, __LINE__, 0, "application error", "failed to allocate memory");
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ memset (&(InputFileName[InputFileNum]), 0, (MAXIMUM_INPUT_FILE_NUM * sizeof (char *)));
+ }
+
+ InputFileName[InputFileNum] = argv[Index];
+ InputFileNum++;
+ Index++;
+ }
+
+ }
+
+ if (strcmpi (argv[Index], "-o") == 0) {
+ //
+ // Output file found
+ //
+ Index++;
+ OutputFileName = argv[Index];
+ } else if (strcmpi (argv[Index], "-s") == 0) {
+ //
+ // Section Type found
+ //
+ Index++;
+ ParamSectionType = argv[Index];
+ } else if (strcmpi (argv[Index], "-t") == 0) {
+ //
+ // Compression or Authentication type
+ //
+ Index++;
+ ParamSectionSubType = argv[Index];
+ } else if (strcmpi (argv[Index], "-l") == 0) {
+ //
+ // Length
+ //
+ Index++;
+ ParamLength = argv[Index];
+ } else if (strcmpi (argv[Index], "-v") == 0) {
+ //
+ // VersionNumber
+ //
+ Index++;
+ ParamVersion = argv[Index];
+ } else if (strcmpi (argv[Index], "-a") == 0) {
+ //
+ // Aux string
+ //
+ Index++;
+ //
+ // Note, the MSVC C-Start parses out and consolidates quoted strings from the command
+ // line. Quote characters are stripped. If this tool is ported to other environments
+ // this will need to be taken into account
+ //
+ strncpy (AuxString, argv[Index], 499);
+ } else if (strcmpi (argv[Index], "-d") == 0) {
+ //
+ // Digital signature for EFI_TEST_AUTHENTICAION (must be 0 or 1)
+ //
+ Index++;
+ ParamDigitalSignature = argv[Index];
+ } else if (strcmpi (argv[Index], "-?") == 0) {
+ PrintUsageMessage ();
+ return STATUS_ERROR;
+ } else {
+ Error (NULL, 0, 0, argv[Index], "unknown option");
+ return GetUtilityStatus ();
+ }
+
+ Index++;
+ }
+ //
+ // At this point, all command line parameters are verified as not being totally
+ // bogus. Next verify the command line parameters are complete and make
+ // sense...
+ //
+ if (stricmp (ParamSectionType, SectionTypeName[EFI_SECTION_COMPRESSION]) == 0) {
+ SectionType = EFI_SECTION_COMPRESSION;
+ SubTypeRequired = TRUE;
+ if (stricmp (ParamSectionSubType, CompressionTypeName[EFI_NOT_COMPRESSED]) == 0) {
+ SectionSubType = EFI_NOT_COMPRESSED;
+ } else if (stricmp (ParamSectionSubType, CompressionTypeName[EFI_STANDARD_COMPRESSION]) == 0) {
+ SectionSubType = EFI_STANDARD_COMPRESSION;
+ } else {
+ Error (NULL, 0, 0, ParamSectionSubType, "unknown compression type");
+ PrintUsageMessage ();
+ return GetUtilityStatus ();
+ }
+ } else if (stricmp (ParamSectionType, SectionTypeName[EFI_SECTION_GUID_DEFINED]) == 0) {
+ SectionType = EFI_SECTION_GUID_DEFINED;
+ SubTypeRequired = TRUE;
+ if (stricmp (ParamSectionSubType, GUIDedSectionTypeName[EFI_SECTION_CRC32_GUID_DEFINED]) == 0) {
+ SectionSubType = EFI_SECTION_CRC32_GUID_DEFINED;
+ } else {
+ Error (NULL, 0, 0, ParamSectionSubType, "unknown GUID defined section type", ParamSectionSubType);
+ PrintUsageMessage ();
+ return GetUtilityStatus ();
+ }
+ } else if (stricmp (ParamSectionType, SectionTypeName[EFI_SECTION_PE32]) == 0) {
+ SectionType = EFI_SECTION_PE32;
+ } else if (stricmp (ParamSectionType, SectionTypeName[EFI_SECTION_PIC]) == 0) {
+ SectionType = EFI_SECTION_PIC;
+ } else if (stricmp (ParamSectionType, SectionTypeName[EFI_SECTION_TE]) == 0) {
+ SectionType = EFI_SECTION_TE;
+ } else if (stricmp (ParamSectionType, SectionTypeName[EFI_SECTION_DXE_DEPEX]) == 0) {
+ SectionType = EFI_SECTION_DXE_DEPEX;
+ } else if (stricmp (ParamSectionType, SectionTypeName[EFI_SECTION_VERSION]) == 0) {
+ SectionType = EFI_SECTION_VERSION;
+ InputFileRequired = FALSE;
+ Index = sscanf (ParamVersion, "%d", &VersionNumber);
+ if (Index != 1 || VersionNumber < 0 || VersionNumber > 65565) {
+ Error (NULL, 0, 0, ParamVersion, "illegal version number");
+ PrintUsageMessage ();
+ return GetUtilityStatus ();
+ }
+
+ if (strcmp (AuxString, PARAMETER_NOT_SPECIFIED) == 0) {
+ AuxString[0] = 0;
+ }
+ } else if (stricmp (ParamSectionType, SectionTypeName[EFI_SECTION_USER_INTERFACE]) == 0) {
+ SectionType = EFI_SECTION_USER_INTERFACE;
+ InputFileRequired = FALSE;
+ if (strcmp (AuxString, PARAMETER_NOT_SPECIFIED) == 0) {
+ Error (NULL, 0, 0, "user interface string not specified", NULL);
+ PrintUsageMessage ();
+ return GetUtilityStatus ();
+ }
+ } else if (stricmp (ParamSectionType, SectionTypeName[EFI_SECTION_COMPATIBILITY16]) == 0) {
+ SectionType = EFI_SECTION_COMPATIBILITY16;
+ } else if (stricmp (ParamSectionType, SectionTypeName[EFI_SECTION_FIRMWARE_VOLUME_IMAGE]) == 0) {
+ SectionType = EFI_SECTION_FIRMWARE_VOLUME_IMAGE;
+ } else if (stricmp (ParamSectionType, SectionTypeName[EFI_SECTION_FREEFORM_SUBTYPE_GUID]) == 0) {
+ SectionType = EFI_SECTION_FREEFORM_SUBTYPE_GUID;
+ } else if (stricmp (ParamSectionType, SectionTypeName[EFI_SECTION_RAW]) == 0) {
+ SectionType = EFI_SECTION_RAW;
+ } else if (stricmp (ParamSectionType, SectionTypeName[EFI_SECTION_PEI_DEPEX]) == 0) {
+ SectionType = EFI_SECTION_PEI_DEPEX;
+ } else {
+ Error (NULL, 0, 0, ParamSectionType, "unknown section type");
+ PrintUsageMessage ();
+ return GetUtilityStatus ();
+ }
+ //
+ // Open output file
+ //
+ OutFile = fopen (OutputFileName, "wb");
+ if (OutFile == NULL) {
+ Error (NULL, 0, 0, OutputFileName, "failed to open output file for writing");
+ if (InFile != NULL) {
+ fclose (InFile);
+ }
+
+ return GetUtilityStatus ();
+ }
+ //
+ // At this point, we've fully validated the command line, and opened appropriate
+ // files, so let's go and do what we've been asked to do...
+ //
+ //
+ // Within this switch, build and write out the section header including any
+ // section type specific pieces. If there's an input file, it's tacked on later
+ //
+ switch (SectionType) {
+ case EFI_SECTION_COMPRESSION:
+ Status = GenSectionCompressionSection (
+ InputFileName,
+ InputFileNum,
+ SectionType,
+ SectionSubType,
+ OutFile
+ );
+ break;
+
+ case EFI_SECTION_GUID_DEFINED:
+ Status = GenSectionGuidDefinedSection (
+ InputFileName,
+ InputFileNum,
+ SectionType,
+ SectionSubType,
+ OutFile
+ );
+ break;
+
+ case EFI_SECTION_VERSION:
+ CommonSect.Type = (EFI_SECTION_TYPE) SectionType;
+
+ Index = sizeof (CommonSect);
+ //
+ // 2 characters for the build number
+ //
+ Index += 2;
+ //
+ // Aux string is ascii.. unicode is 2X + 2 bytes for terminating unicode null.
+ //
+ Index += (strlen (AuxString) * 2) + 2;
+ memcpy (&CommonSect.Size, &Index, 3);
+ fwrite (&CommonSect, sizeof (CommonSect), 1, OutFile);
+ fwrite (&VersionNumber, 2, 1, OutFile);
+ Ascii2UnicodeWriteString (AuxString, OutFile, FALSE);
+ break;
+
+ case EFI_SECTION_USER_INTERFACE:
+ CommonSect.Type = (EFI_SECTION_TYPE) SectionType;
+ Index = sizeof (CommonSect);
+ //
+ // Aux string is ascii.. unicode is 2X + 2 bytes for terminating unicode null.
+ //
+ Index += (strlen (AuxString) * 2) + 2;
+ memcpy (&CommonSect.Size, &Index, 3);
+ fwrite (&CommonSect, sizeof (CommonSect), 1, OutFile);
+ Ascii2UnicodeWriteString (AuxString, OutFile, FALSE);
+ break;
+
+ default:
+ //
+ // All other section types are caught by default (they're all the same)
+ //
+ Status = GenSectionCommonLeafSection (
+ InputFileName,
+ InputFileNum,
+ SectionType,
+ OutFile
+ );
+ break;
+ }
+
+ if (InputFileName != NULL) {
+ free (InputFileName);
+ }
+
+ fclose (OutFile);
+ //
+ // If we had errors, then delete the output file
+ //
+ if (GetUtilityStatus () == STATUS_ERROR) {
+ remove (OutputFileName);
+ }
+
+ return GetUtilityStatus ();
+}
diff --git a/Source/GenSection/GenSection.h b/Source/GenSection/GenSection.h
new file mode 100644
index 0000000..3606463
--- /dev/null
+++ b/Source/GenSection/GenSection.h
@@ -0,0 +1,42 @@
+/*++
+
+Copyright (c) 2004, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ GenSection.h
+
+Abstract:
+
+ Header file for GenSection.
+
+--*/
+
+//
+// Module Coded to Tiano Coding Conventions
+//
+#ifndef _EFI_GEN_SECTION_H
+#define _EFI_GEN_SECTION_H
+
+//
+// External Files Referenced
+//
+#include <Common/UefiBaseTypes.h>
+#include <Common/FirmwareVolumeImageFormat.h>
+
+typedef struct {
+ EFI_GUID_DEFINED_SECTION GuidSectionHeader;
+ UINT32 CRC32Checksum;
+} CRC32_SECTION_HEADER;
+
+#define EFI_SECTION_CRC32_GUID_DEFINED 0
+#define CRC32_SECTION_HEADER_SIZE (sizeof (CRC32_SECTION_HEADER))
+
+#endif
diff --git a/Source/GenSection/build.xml b/Source/GenSection/build.xml
new file mode 100644
index 0000000..391028e
--- /dev/null
+++ b/Source/GenSection/build.xml
@@ -0,0 +1,70 @@
+<?xml version="1.0" ?>
+<!--
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+-->
+<project default="GenTool" basedir=".">
+<!--
+ EDK GenSection Tool
+ Copyright (c) 2006, Intel Corporation
+-->
+ <property name="ToolName" value="GenSection"/>
+ <property name="FileSet" value="GenSection.c"/>
+
+ <taskdef resource="net/sf/antcontrib/antlib.xml"/>
+
+ <property name="LINK_OUTPUT_TYPE" value="static"/>
+ <property name="BUILD_DIR" value="${PACKAGE_DIR}/${ToolName}/tmp"/>
+
+ <target name="GenTool" depends="init, Tool">
+ <echo message="The EDK Tool: ${ToolName} build has completed!"/>
+ </target>
+
+ <target name="init">
+ <echo message="Building the EDK Tool: ${ToolName}"/>
+ <mkdir dir="${BUILD_DIR}"/>
+ </target>
+
+ <target name="Tool" depends="init">
+ <cc name="${ToolChain}" objdir="${BUILD_DIR}"
+ outfile="${BIN_DIR}/${ToolName}"
+ outtype="executable"
+ debug="true"
+ optimize="speed">
+ <compilerarg value="${ExtraArgus}" if="ExtraArgus" />
+
+ <fileset dir="${basedir}/${ToolName}"
+ includes="${FileSet}"
+ defaultexcludes="TRUE"
+ excludes="*.xml *.inf"/>
+
+ <includepath path="${PACKAGE_DIR}/Include"/>
+ <includepath path="${PACKAGE_DIR}/Include/${HostArch}"/>
+ <includepath path="${PACKAGE_DIR}/Common"/>
+ <libset dir="${LIB_DIR}" libs="CommonTools CustomizedCompress"/>
+ </cc>
+ </target>
+
+ <target name="clean">
+ <echo message="Removing Intermediate Files Only"/>
+ <delete>
+ <fileset dir="${BUILD_DIR}" includes="*.obj"/>
+ </delete>
+ </target>
+
+ <target name="cleanall">
+ <echo message="Removing Object Files and the Executable: ${ToolName}${ext_exe}"/>
+ <delete failonerror="false" quiet="true" includeEmptyDirs="true">
+ <fileset dir="${BUILD_DIR}"/>
+ <fileset file="${BIN_DIR}/${ToolName}${ext_exe}"/>
+ <fileset file="${BIN_DIR}/${ToolName}.pdb"/>
+ </delete>
+ </target>
+
+</project>
diff --git a/Source/GenTEImage/GenTEImage.c b/Source/GenTEImage/GenTEImage.c
new file mode 100644
index 0000000..90f3b39
--- /dev/null
+++ b/Source/GenTEImage/GenTEImage.c
@@ -0,0 +1,916 @@
+/*++
+
+Copyright (c) 1999-2006 Intel Corporation. All rights reserved
+This program and the accompanying materials are licensed and made available
+under the terms and conditions of the BSD License which accompanies this
+distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ GenTEImage.c
+
+Abstract:
+
+ Utility program to shrink a PE32 image down by replacing
+ the DOS, PE, and optional headers with a minimal header.
+
+--*/
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <Common/UefiBaseTypes.h>
+#include <Common/EfiImage.h> // for PE32 structure definitions
+
+#include "CommonLib.h"
+#include "EfiUtilityMsgs.h"
+
+//
+// Version of this utility
+//
+#define UTILITY_NAME "GenTEImage"
+#define UTILITY_VERSION "v0.11"
+
+//
+// Define the max length of a filename
+//
+#define MAX_PATH 256
+#define DEFAULT_OUTPUT_EXTENSION ".te"
+
+//
+// Use this to track our command-line options and globals
+//
+struct {
+ INT8 OutFileName[MAX_PATH];
+ INT8 InFileName[MAX_PATH];
+ INT8 Verbose;
+ INT8 Dump;
+} mOptions;
+
+//
+// Use these to convert from machine type value to a named type
+//
+typedef struct {
+ UINT16 Value;
+ INT8 *Name;
+} STRING_LOOKUP;
+
+static STRING_LOOKUP mMachineTypes[] = {
+ EFI_IMAGE_MACHINE_IA32,
+ "IA32",
+ EFI_IMAGE_MACHINE_IA64,
+ "IA64",
+ EFI_IMAGE_MACHINE_EBC,
+ "EBC",
+ 0,
+ NULL
+};
+
+static STRING_LOOKUP mSubsystemTypes[] = {
+ EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION,
+ "EFI application",
+ EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER,
+ "EFI boot service driver",
+ EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER,
+ "EFI runtime driver",
+ 0,
+ NULL
+};
+//
+// Function prototypes
+//
+static
+void
+Usage (
+ VOID
+ );
+
+static
+STATUS
+ParseCommandLine (
+ int Argc,
+ char *Argv[]
+ );
+
+static
+STATUS
+CheckPE32File (
+ INT8 *FileName,
+ FILE *Fptr,
+ UINT16 *MachineType,
+ UINT16 *SubSystem
+ );
+
+static
+STATUS
+ProcessFile (
+ INT8 *InFileName,
+ INT8 *OutFileName
+ );
+
+static
+void
+DumpImage (
+ INT8 *FileName
+ );
+
+static
+INT8 *
+GetMachineTypeStr (
+ UINT16 MachineType
+ );
+
+static
+INT8 *
+GetSubsystemTypeStr (
+ UINT16 SubsystemType
+ );
+
+main (
+ int Argc,
+ char *Argv[]
+ )
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+ Argc - standard C main() argument count
+
+ Argv - standard C main() argument list
+
+Returns:
+
+ 0 success
+ non-zero otherwise
+
+--*/
+// GC_TODO: ] - add argument and description to function comment
+{
+ INT8 *Ext;
+ UINT32 Status;
+
+ SetUtilityName (UTILITY_NAME);
+ //
+ // Parse the command line arguments
+ //
+ if (ParseCommandLine (Argc, Argv)) {
+ return STATUS_ERROR;
+ }
+ //
+ // If dumping an image, then do that and quit
+ //
+ if (mOptions.Dump) {
+ DumpImage (mOptions.InFileName);
+ goto Finish;
+ }
+ //
+ // Determine the output filename. Either what they specified on
+ // the command line, or the first input filename with a different extension.
+ //
+ if (!mOptions.OutFileName[0]) {
+ strcpy (mOptions.OutFileName, mOptions.InFileName);
+ //
+ // Find the last . on the line and replace the filename extension with
+ // the default
+ //
+ for (Ext = mOptions.OutFileName + strlen (mOptions.OutFileName) - 1;
+ (Ext >= mOptions.OutFileName) && (*Ext != '.') && (*Ext != '\\');
+ Ext--
+ )
+ ;
+ //
+ // If dot here, then insert extension here, otherwise append
+ //
+ if (*Ext != '.') {
+ Ext = mOptions.OutFileName + strlen (mOptions.OutFileName);
+ }
+
+ strcpy (Ext, DEFAULT_OUTPUT_EXTENSION);
+ }
+ //
+ // Make sure we don't have the same filename for input and output files
+ //
+ if (stricmp (mOptions.OutFileName, mOptions.InFileName) == 0) {
+ Error (NULL, 0, 0, mOptions.OutFileName, "input and output file names must be different");
+ goto Finish;
+ }
+ //
+ // Process the file
+ //
+ ProcessFile (mOptions.InFileName, mOptions.OutFileName);
+Finish:
+ Status = GetUtilityStatus ();
+ return Status;
+}
+
+static
+STATUS
+ProcessFile (
+ INT8 *InFileName,
+ INT8 *OutFileName
+ )
+/*++
+
+Routine Description:
+
+ Process a PE32 EFI file.
+
+Arguments:
+
+ InFileName - the file name pointer to the input file
+ OutFileName - the file name pointer to the output file
+
+Returns:
+
+ STATUS_SUCCESS - the process has been finished successfully
+ STATUS_ERROR - error occured during the processing
+
+--*/
+{
+ STATUS Status;
+ FILE *InFptr;
+ FILE *OutFptr;
+ UINT16 MachineType;
+ UINT16 SubSystem;
+ EFI_TE_IMAGE_HEADER TEImageHeader;
+ UINT32 PESigOffset;
+ EFI_IMAGE_FILE_HEADER FileHeader;
+ EFI_IMAGE_OPTIONAL_HEADER32 OptionalHeader32;
+ EFI_IMAGE_OPTIONAL_HEADER64 OptionalHeader64;
+ UINT32 BytesStripped;
+ UINT32 FileSize;
+ UINT8 *Buffer;
+ long SaveFilePosition;
+
+ InFptr = NULL;
+ OutFptr = NULL;
+ Buffer = NULL;
+ Status = STATUS_ERROR;
+
+ //
+ // Try to open the input file
+ //
+ if ((InFptr = fopen (InFileName, "rb")) == NULL) {
+ Error (NULL, 0, 0, InFileName, "failed to open input file for reading");
+ return STATUS_ERROR;
+ }
+ //
+ // Double-check the file to make sure it's what we expect it to be
+ //
+ if (CheckPE32File (InFileName, InFptr, &MachineType, &SubSystem) != STATUS_SUCCESS) {
+ goto Finish;
+ }
+ //
+ // Initialize our new header
+ //
+ memset (&TEImageHeader, 0, sizeof (EFI_TE_IMAGE_HEADER));
+
+ //
+ // Seek to the end to get the file size
+ //
+ fseek (InFptr, 0, SEEK_END);
+ FileSize = ftell (InFptr);
+ fseek (InFptr, 0, SEEK_SET);
+
+ //
+ // Per the PE/COFF specification, at offset 0x3C in the file is a 32-bit
+ // offset (from the start of the file) to the PE signature, which always
+ // follows the MSDOS stub. The PE signature is immediately followed by the
+ // COFF file header.
+ //
+ //
+ if (fseek (InFptr, 0x3C, SEEK_SET) != 0) {
+ Error (NULL, 0, 0, InFileName, "failed to seek to PE signature in file", NULL);
+ goto Finish;
+ }
+
+ if (fread (&PESigOffset, sizeof (PESigOffset), 1, InFptr) != 1) {
+ Error (NULL, 0, 0, InFileName, "failed to read PE signature offset from file");
+ goto Finish;
+ }
+
+ if (fseek (InFptr, PESigOffset + 4, SEEK_SET) != 0) {
+ Error (NULL, 0, 0, InFileName, "failed to seek to PE signature");
+ goto Finish;
+ }
+ //
+ // We should now be at the COFF file header. Read it in and verify it's
+ // of an image type we support.
+ //
+ if (fread (&FileHeader, sizeof (EFI_IMAGE_FILE_HEADER), 1, InFptr) != 1) {
+ Error (NULL, 0, 0, InFileName, "failed to read file header from image");
+ goto Finish;
+ }
+
+ if ((FileHeader.Machine != EFI_IMAGE_MACHINE_IA32) && (FileHeader.Machine != EFI_IMAGE_MACHINE_IA64)) {
+ Error (NULL, 0, 0, InFileName, "image is of an unsupported machine type 0x%X", (UINT32) FileHeader.Machine);
+ goto Finish;
+ }
+ //
+ // Calculate the total number of bytes we're going to strip off. The '4' is for the
+ // PE signature PE\0\0. Then sanity check the size.
+ //
+ BytesStripped = PESigOffset + 4 + sizeof (EFI_IMAGE_FILE_HEADER) + FileHeader.SizeOfOptionalHeader;
+ if (BytesStripped >= FileSize) {
+ Error (NULL, 0, 0, InFileName, "attempt to strip more bytes than the total file size");
+ goto Finish;
+ }
+
+ if (BytesStripped &~0xFFFF) {
+ Error (NULL, 0, 0, InFileName, "attempt to strip more than 64K bytes", NULL);
+ goto Finish;
+ }
+
+ TEImageHeader.StrippedSize = (UINT16) BytesStripped;
+
+ //
+ // Read in the optional header. Assume PE32, and if not, then re-read as PE32+
+ //
+ SaveFilePosition = ftell (InFptr);
+ if (fread (&OptionalHeader32, sizeof (EFI_IMAGE_OPTIONAL_HEADER32), 1, InFptr) != 1) {
+ Error (NULL, 0, 0, InFileName, "failed to read optional header from input file");
+ goto Finish;
+ }
+
+ if (OptionalHeader32.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
+ //
+ // Fill in our new header with required data directory entries
+ //
+ TEImageHeader.AddressOfEntryPoint = OptionalHeader32.AddressOfEntryPoint;
+ //
+ // - BytesStripped + sizeof (EFI_TE_IMAGE_HEADER);
+ //
+ // We're going to pack the subsystem into 1 byte. Make sure it fits
+ //
+ if (OptionalHeader32.Subsystem &~0xFF) {
+ Error (
+ NULL,
+ 0,
+ 0,
+ InFileName,
+ NULL,
+ "image subsystem 0x%X cannot be packed into 1 byte",
+ (UINT32) OptionalHeader32.Subsystem
+ );
+ goto Finish;
+ }
+
+ TEImageHeader.Subsystem = (UINT8) OptionalHeader32.Subsystem;
+ TEImageHeader.BaseOfCode = OptionalHeader32.BaseOfCode;
+ TEImageHeader.ImageBase = (UINT64) (OptionalHeader32.ImageBase + TEImageHeader.StrippedSize - sizeof (EFI_TE_IMAGE_HEADER));
+ if (OptionalHeader32.NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) {
+ TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = OptionalHeader32.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress;
+ TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size = OptionalHeader32.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size;
+ }
+
+ if (OptionalHeader32.NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG) {
+ TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress = OptionalHeader32.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress;
+ TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].Size = OptionalHeader32.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size;
+ }
+ } else if (OptionalHeader32.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
+ //
+ // Rewind and re-read the optional header
+ //
+ fseek (InFptr, SaveFilePosition, SEEK_SET);
+ if (fread (&OptionalHeader64, sizeof (EFI_IMAGE_OPTIONAL_HEADER64), 1, InFptr) != 1) {
+ Error (NULL, 0, 0, InFileName, "failed to re-read optional header from input file");
+ goto Finish;
+ }
+
+ TEImageHeader.AddressOfEntryPoint = OptionalHeader64.AddressOfEntryPoint;
+ //
+ // - BytesStripped + sizeof (EFI_TE_IMAGE_HEADER);
+ //
+ // We're going to pack the subsystem into 1 byte. Make sure it fits
+ //
+ if (OptionalHeader64.Subsystem &~0xFF) {
+ Error (
+ NULL,
+ 0,
+ 0,
+ InFileName,
+ NULL,
+ "image subsystem 0x%X cannot be packed into 1 byte",
+ (UINT32) OptionalHeader64.Subsystem
+ );
+ goto Finish;
+ }
+
+ TEImageHeader.Subsystem = (UINT8) OptionalHeader64.Subsystem;
+ TEImageHeader.BaseOfCode = OptionalHeader32.BaseOfCode;
+ TEImageHeader.ImageBase = (UINT64) (OptionalHeader64.ImageBase + TEImageHeader.StrippedSize - sizeof (EFI_TE_IMAGE_HEADER));
+ if (OptionalHeader64.NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) {
+ TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = OptionalHeader64.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress;
+ TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size = OptionalHeader64.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size;
+ }
+
+ if (OptionalHeader64.NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG) {
+ TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress = OptionalHeader64.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress;
+ TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].Size = OptionalHeader64.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size;
+ }
+ } else {
+ Error (
+ NULL,
+ 0,
+ 0,
+ InFileName,
+ "unsupported magic number 0x%X found in optional header",
+ (UINT32) OptionalHeader32.Magic
+ );
+ goto Finish;
+ }
+ //
+ // Fill in the remainder of our new image header
+ //
+ TEImageHeader.Signature = EFI_TE_IMAGE_HEADER_SIGNATURE;
+ TEImageHeader.Machine = FileHeader.Machine;
+ //
+ // We're going to pack the number of sections into a single byte. Make sure it fits.
+ //
+ if (FileHeader.NumberOfSections &~0xFF) {
+ Error (
+ NULL,
+ 0,
+ 0,
+ InFileName,
+ NULL,
+ "image's number of sections 0x%X cannot be packed into 1 byte",
+ (UINT32) FileHeader.NumberOfSections
+ );
+ goto Finish;
+ }
+
+ TEImageHeader.NumberOfSections = (UINT8) FileHeader.NumberOfSections;
+
+ //
+ // Now open our output file
+ //
+ if ((OutFptr = fopen (OutFileName, "wb")) == NULL) {
+ Error (NULL, 0, 0, OutFileName, "failed to open output file for writing");
+ goto Finish;
+ }
+ //
+ // Write the TE header
+ //
+ if (fwrite (&TEImageHeader, sizeof (EFI_TE_IMAGE_HEADER), 1, OutFptr) != 1) {
+ Error (NULL, 0, 0, "failed to write image header to output file", NULL);
+ goto Finish;
+ }
+ //
+ // Position into the input file, read the part we're not stripping, and
+ // write it out.
+ //
+ fseek (InFptr, BytesStripped, SEEK_SET);
+ Buffer = (UINT8 *) malloc (FileSize - BytesStripped);
+ if (Buffer == NULL) {
+ Error (NULL, 0, 0, "application error", "failed to allocate memory");
+ goto Finish;
+ }
+
+ if (fread (Buffer, FileSize - BytesStripped, 1, InFptr) != 1) {
+ Error (NULL, 0, 0, InFileName, "failed to read remaining contents of input file");
+ goto Finish;
+ }
+
+ if (fwrite (Buffer, FileSize - BytesStripped, 1, OutFptr) != 1) {
+ Error (NULL, 0, 0, OutFileName, "failed to write all bytes to output file");
+ goto Finish;
+ }
+
+ Status = STATUS_SUCCESS;
+
+Finish:
+ if (InFptr != NULL) {
+ fclose (InFptr);
+ }
+ //
+ // Close the output file. If there was an error, delete the output file so
+ // that a subsequent build will rebuild it.
+ //
+ if (OutFptr != NULL) {
+ fclose (OutFptr);
+ if (GetUtilityStatus () == STATUS_ERROR) {
+ remove (OutFileName);
+ }
+ }
+
+ //
+ // Free up our buffer
+ //
+ if (Buffer != NULL) {
+ free (Buffer);
+ }
+
+ return Status;
+}
+
+static
+STATUS
+CheckPE32File (
+ INT8 *FileName,
+ FILE *Fptr,
+ UINT16 *MachineType,
+ UINT16 *SubSystem
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ FileName - GC_TODO: add argument description
+ Fptr - GC_TODO: add argument description
+ MachineType - GC_TODO: add argument description
+ SubSystem - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+{
+ /*++
+
+Routine Description:
+
+ Given a file pointer to a supposed PE32 image file, verify that it is indeed a
+ PE32 image file, and then return the machine type in the supplied pointer.
+
+Arguments:
+
+ Fptr File pointer to the already-opened PE32 file
+ MachineType Location to stuff the machine type of the PE32 file. This is needed
+ because the image may be Itanium-based, IA32, or EBC.
+
+Returns:
+
+ 0 success
+ non-zero otherwise
+
+--*/
+ EFI_IMAGE_DOS_HEADER DosHeader;
+ EFI_IMAGE_FILE_HEADER FileHdr;
+ EFI_IMAGE_OPTIONAL_HEADER OptionalHdr;
+ UINT32 PESig;
+ STATUS Status;
+
+ Status = STATUS_ERROR;
+ //
+ // Position to the start of the file
+ //
+ fseek (Fptr, 0, SEEK_SET);
+ //
+ // Read the DOS header
+ //
+ if (fread (&DosHeader, sizeof (DosHeader), 1, Fptr) != 1) {
+ Error (NULL, 0, 0, FileName, "failed to read the DOS stub from the input file");
+ goto Finish;
+ }
+ //
+ // Check the magic number (0x5A4D)
+ //
+ if (DosHeader.e_magic != EFI_IMAGE_DOS_SIGNATURE) {
+ Error (NULL, 0, 0, FileName, "input file does not appear to be a PE32 image (magic number)");
+ goto Finish;
+ }
+ //
+ // Position into the file and check the PE signature
+ //
+ fseek (Fptr, (long) DosHeader.e_lfanew, SEEK_SET);
+ if (fread (&PESig, sizeof (PESig), 1, Fptr) != 1) {
+ Error (NULL, 0, 0, FileName, "failed to read PE signature bytes");
+ goto Finish;
+ }
+ //
+ // Check the PE signature in the header "PE\0\0"
+ //
+ if (PESig != EFI_IMAGE_NT_SIGNATURE) {
+ Error (NULL, 0, 0, FileName, "file does not appear to be a PE32 image (signature)");
+ goto Finish;
+ }
+ //
+ // Read the file header
+ //
+ if (fread (&FileHdr, sizeof (FileHdr), 1, Fptr) != 1) {
+ Error (NULL, 0, 0, FileName, "failed to read PE file header from input file");
+ goto Finish;
+ }
+ //
+ // Read the optional header so we can get the subsystem
+ //
+ if (fread (&OptionalHdr, sizeof (OptionalHdr), 1, Fptr) != 1) {
+ Error (NULL, 0, 0, FileName, "failed to read COFF optional header from input file");
+ goto Finish;
+ }
+
+ *SubSystem = OptionalHdr.Subsystem;
+ if (mOptions.Verbose) {
+ fprintf (stdout, " Got subsystem = 0x%X from image\n", (int) *SubSystem);
+ }
+ //
+ // Good to go
+ //
+ Status = STATUS_SUCCESS;
+Finish:
+ fseek (Fptr, 0, SEEK_SET);
+ return Status;
+}
+
+static
+int
+ParseCommandLine (
+ int Argc,
+ char *Argv[]
+ )
+/*++
+
+Routine Description:
+
+ Given the Argc/Argv program arguments, and a pointer to an options structure,
+ parse the command-line options and check their validity.
+
+
+Arguments:
+
+ Argc - standard C main() argument count
+ Argv - standard C main() argument list
+
+Returns:
+
+ STATUS_SUCCESS success
+ non-zero otherwise
+
+--*/
+// GC_TODO: ] - add argument and description to function comment
+{
+ //
+ // Clear out the options
+ //
+ memset ((char *) &mOptions, 0, sizeof (mOptions));
+ //
+ // Skip over the program name
+ //
+ Argc--;
+ Argv++;
+ //
+ // If no arguments, assume they want usage info
+ //
+ if (Argc == 0) {
+ Usage ();
+ return STATUS_ERROR;
+ }
+ //
+ // Process until no more arguments
+ //
+ while ((Argc > 0) && (Argv[0][0] == '-')) {
+ if (stricmp (Argv[0], "-o") == 0) {
+ //
+ // Output filename specified with -o
+ // Make sure there's another parameter
+ //
+ if (Argc > 1) {
+ strcpy (mOptions.OutFileName, Argv[1]);
+ } else {
+ Error (NULL, 0, 0, Argv[0], "missing output file name with option");
+ Usage ();
+ return STATUS_ERROR;
+ }
+
+ Argv++;
+ Argc--;
+ } else if ((stricmp (Argv[0], "-h") == 0) || (strcmp (Argv[0], "-?") == 0)) {
+ //
+ // Help option
+ //
+ Usage ();
+ return STATUS_ERROR;
+ } else if (stricmp (Argv[0], "-v") == 0) {
+ //
+ // -v for verbose
+ //
+ mOptions.Verbose = 1;
+ } else if (stricmp (Argv[0], "-dump") == 0) {
+ //
+ // -dump for dumping an image
+ //
+ mOptions.Dump = 1;
+ } else {
+ Error (NULL, 0, 0, Argv[0], "unrecognized option");
+ Usage ();
+ return STATUS_ERROR;
+ }
+ //
+ // Next argument
+ //
+ Argv++;
+ Argc--;
+ }
+ //
+ // Better be one more arg for input file name
+ //
+ if (Argc == 0) {
+ Error (NULL, 0, 0, "input file name required", NULL);
+ Usage ();
+ return STATUS_ERROR;
+ }
+
+ if (Argc != 1) {
+ Error (NULL, 0, 0, Argv[1], "extra arguments on command line");
+ return STATUS_ERROR;
+ }
+
+ strcpy (mOptions.InFileName, Argv[0]);
+ return STATUS_SUCCESS;
+}
+
+static
+void
+Usage (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Print usage information for this utility.
+
+Arguments:
+
+ None.
+
+Returns:
+
+ Nothing.
+
+--*/
+{
+ int Index;
+ static const char *Msg[] = {
+ UTILITY_NAME " version "UTILITY_VERSION " - TE image utility",
+ " Generate a TE image from an EFI PE32 image",
+ " Usage: "UTILITY_NAME " {-v} {-dump} {-h|-?} {-o OutFileName} InFileName",
+ " [-e|-b] [FileName(s)]",
+ " where:",
+ " -v - for verbose output",
+ " -dump - to dump the input file to a text file",
+ " -h -? - for this help information",
+ " -o OutFileName - to write output to OutFileName rather than InFileName"DEFAULT_OUTPUT_EXTENSION,
+ " InFileName - name of the input PE32 file",
+ "",
+ NULL
+ };
+ for (Index = 0; Msg[Index] != NULL; Index++) {
+ fprintf (stdout, "%s\n", Msg[Index]);
+ }
+}
+
+static
+VOID
+DumpImage (
+ INT8 *FileName
+ )
+/*++
+
+Routine Description:
+
+ Dump a specified image information
+
+Arguments:
+
+ FileName - File name pointer to the image to dump
+
+Returns:
+
+ Nothing.
+
+--*/
+{
+ FILE *InFptr;
+ EFI_TE_IMAGE_HEADER TEImageHeader;
+ INT8 *NamePtr;
+
+ //
+ // Open the input file
+ //
+ InFptr = NULL;
+
+ if ((InFptr = fopen (FileName, "rb")) == NULL) {
+ Error (NULL, 0, 0, FileName, "failed to open input file for reading");
+ return ;
+ }
+
+ if (fread (&TEImageHeader, sizeof (EFI_TE_IMAGE_HEADER), 1, InFptr) != 1) {
+ Error (NULL, 0, 0, FileName, "failed to read image header from input file");
+ goto Finish;
+ }
+
+ if (TEImageHeader.Signature != EFI_TE_IMAGE_HEADER_SIGNATURE) {
+ Error (NULL, 0, 0, FileName, "Image does not appear to be a TE image (bad signature)");
+ goto Finish;
+ }
+ //
+ // Dump the header
+ //
+ fprintf (stdout, "Header (%d bytes):\n", sizeof (EFI_TE_IMAGE_HEADER));
+ fprintf (stdout, " Signature: 0x%04X (TE)\n", (UINT32) TEImageHeader.Signature);
+ NamePtr = GetMachineTypeStr (TEImageHeader.Machine);
+ fprintf (stdout, " Machine: 0x%04X (%s)\n", (UINT32) TEImageHeader.Machine, NamePtr);
+ NamePtr = GetSubsystemTypeStr (TEImageHeader.Subsystem);
+ fprintf (stdout, " Subsystem: 0x%02X (%s)\n", (UINT32) TEImageHeader.Subsystem, NamePtr);
+ fprintf (stdout, " Number of sections 0x%02X\n", (UINT32) TEImageHeader.NumberOfSections);
+ fprintf (stdout, " Stripped size: 0x%04X\n", (UINT32) TEImageHeader.StrippedSize);
+ fprintf (stdout, " Entry point: 0x%08X\n", TEImageHeader.AddressOfEntryPoint);
+ fprintf (stdout, " Base of code: 0x%08X\n", TEImageHeader.BaseOfCode);
+ fprintf (stdout, " Data directories:\n");
+ fprintf (
+ stdout,
+ " %8X [%8X] RVA [size] of Base Relocation Directory\n",
+ TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress,
+ TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size
+ );
+ fprintf (
+ stdout,
+ " %8X [%8X] RVA [size] of Debug Directory\n",
+ TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress,
+ TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].Size
+ );
+
+Finish:
+ if (InFptr != NULL) {
+ fclose (InFptr);
+ }
+}
+
+static
+INT8 *
+GetMachineTypeStr (
+ UINT16 MachineType
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ MachineType - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+{
+ int Index;
+
+ for (Index = 0; mMachineTypes[Index].Name != NULL; Index++) {
+ if (mMachineTypes[Index].Value == MachineType) {
+ return mMachineTypes[Index].Name;
+ }
+ }
+
+ return "unknown";
+}
+
+static
+INT8 *
+GetSubsystemTypeStr (
+ UINT16 SubsystemType
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ SubsystemType - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+{
+ int Index;
+
+ for (Index = 0; mSubsystemTypes[Index].Name != NULL; Index++) {
+ if (mSubsystemTypes[Index].Value == SubsystemType) {
+ return mSubsystemTypes[Index].Name;
+ }
+ }
+
+ return "unknown";
+}
diff --git a/Source/GenTEImage/build.xml b/Source/GenTEImage/build.xml
new file mode 100644
index 0000000..508035b
--- /dev/null
+++ b/Source/GenTEImage/build.xml
@@ -0,0 +1,71 @@
+<?xml version="1.0" ?>
+<!--
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+-->
+<project default="GenTool" basedir=".">
+<!--
+ EDK GenTEImage Tool
+ Copyright (c) 2006, Intel Corporation
+-->
+ <property name="ToolName" value="GenTEImage"/>
+ <property name="FileSet" value="*.c"/>
+
+ <taskdef resource="net/sf/antcontrib/antlib.xml"/>
+
+
+ <property name="LINK_OUTPUT_TYPE" value="static"/>
+ <property name="BUILD_DIR" value="${PACKAGE_DIR}/${ToolName}/tmp"/>
+
+ <target name="GenTool" depends="init, Tool">
+ <echo message="The EDK Tool: ${ToolName} build has completed!"/>
+ </target>
+
+ <target name="init">
+ <echo message="Building the EDK Tool: ${ToolName}"/>
+ <mkdir dir="${BUILD_DIR}"/>
+ </target>
+
+ <target name="Tool" depends="init">
+ <cc name="${ToolChain}" objdir="${BUILD_DIR}"
+ outfile="${BIN_DIR}/${ToolName}"
+ outtype="executable"
+ debug="true"
+ optimize="speed">
+ <compilerarg value="${ExtraArgus}" if="ExtraArgus" />
+
+ <fileset dir="${basedir}/${ToolName}"
+ includes="${FileSet}"
+ defaultexcludes="TRUE"
+ excludes="*.xml *.inf"/>
+
+ <includepath path="${PACKAGE_DIR}/Include"/>
+ <includepath path="${PACKAGE_DIR}/Include/${HostArch}"/>
+ <includepath path="${PACKAGE_DIR}/Common"/>
+ <libset dir="${LIB_DIR}" libs="CommonTools"/>
+ </cc>
+ </target>
+
+ <target name="clean">
+ <echo message="Removing Intermediate Files Only"/>
+ <delete>
+ <fileset dir="${BUILD_DIR}" includes="*.obj"/>
+ </delete>
+ </target>
+
+ <target name="cleanall">
+ <echo message="Removing Object Files and the Executable: ${ToolName}${ext_exe}"/>
+ <delete failonerror="false" quiet="true" includeEmptyDirs="true">
+ <fileset dir="${BUILD_DIR}"/>
+ <fileset file="${BIN_DIR}/${ToolName}${ext_exe}"/>
+ <fileset file="${BIN_DIR}/${ToolName}.pdb"/>
+ </delete>
+ </target>
+
+</project>
diff --git a/Source/GuidChk/CommonUtils.h b/Source/GuidChk/CommonUtils.h
new file mode 100644
index 0000000..f7a331e
--- /dev/null
+++ b/Source/GuidChk/CommonUtils.h
@@ -0,0 +1,57 @@
+/*++
+
+Copyright (c) 2004, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ CommonUtils.h
+
+Abstract:
+
+ Common utility defines and structure definitions.
+
+--*/
+
+#ifndef _COMMON_UTILS_H_
+#define _COMMON_UTILS_H_
+
+//
+// Basic types
+//
+typedef unsigned char UINT8;
+typedef char INT8;
+typedef unsigned short UINT16;
+typedef unsigned int UINT32;
+
+typedef UINT8 BOOLEAN;
+typedef UINT32 STATUS;
+
+#define TRUE 1
+#define FALSE 0
+
+#define STATUS_SUCCESS 0
+#define STATUS_WARNING 1
+#define STATUS_ERROR 2
+
+//
+// Linked list of strings
+//
+typedef struct _STRING_LIST {
+ struct _STRING_LIST *Next;
+ char *Str;
+} STRING_LIST;
+
+int
+CreateGuidList (
+ INT8 *OutFileName
+ )
+;
+
+#endif // #ifndef _COMMON_UTILS_H_
diff --git a/Source/GuidChk/FileSearch.c b/Source/GuidChk/FileSearch.c
new file mode 100644
index 0000000..8b5b58f
--- /dev/null
+++ b/Source/GuidChk/FileSearch.c
@@ -0,0 +1,285 @@
+/*++
+
+Copyright (c) 2004, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ FileSearch.c
+
+Abstract:
+
+ Module used to support file searches on the system.
+
+--*/
+
+#include <stdio.h>
+
+#include "CommonUtils.h"
+#include "FileSearch.h"
+#include "UtilsMsgs.h"
+
+//
+// Internal file search flag for sanity checks
+//
+#define FILE_SEARCH_STARTED 0x8000
+#define FILE_SEARCH_INITED 0x4000
+
+static
+BOOLEAN
+FileSearchMeetsCriteria (
+ FILE_SEARCH_DATA *FSData
+ );
+
+/*****************************************************************************/
+STATUS
+FileSearchInit (
+ FILE_SEARCH_DATA *FSData
+ )
+{
+ memset ((char *) FSData, 0, sizeof (FILE_SEARCH_DATA));
+ FSData->Handle = INVALID_HANDLE_VALUE;
+ FSData->FileSearchFlags = FILE_SEARCH_INITED;
+ FSData->FileName[0] = 0;
+ return STATUS_SUCCESS;
+}
+
+STATUS
+FileSearchStart (
+ FILE_SEARCH_DATA *FSData,
+ char *FileMask,
+ UINT32 SearchFlags
+ )
+{
+ BOOLEAN Done;
+
+ //
+ // Save their flags, and set a flag to indicate that they called this
+ // start function so we can perform extended checking in the other
+ // routines we have in this module.
+ //
+ FSData->FileSearchFlags |= (SearchFlags | FILE_SEARCH_STARTED);
+ FSData->FileName[0] = 0;
+
+ //
+ // Begin the search
+ //
+ FSData->Handle = FindFirstFile (FileMask, &(FSData->FindData));
+ if (FSData->Handle == INVALID_HANDLE_VALUE) {
+ return STATUS_ERROR;
+ }
+ //
+ // Keep looping through until we find a file meeting the caller's
+ // criteria per the search flags
+ //
+ Done = FALSE;
+ while (!Done) {
+ //
+ // If we're done (we found a match) copy the file name found and return
+ //
+ Done = FileSearchMeetsCriteria (FSData);
+ if (Done) {
+ return STATUS_SUCCESS;
+ }
+ //
+ // Go on to next file
+ //
+ if (!FindNextFile (FSData->Handle, &(FSData->FindData))) {
+ return STATUS_NOT_FOUND;
+ }
+ }
+ //
+ // Not reached
+ //
+ return STATUS_NOT_FOUND;
+}
+
+//
+// Find the next file meeting their criteria and return it.
+//
+STATUS
+FileSearchFindNext (
+ FILE_SEARCH_DATA *FSData
+ )
+{
+ BOOLEAN Done;
+
+ Done = FALSE;
+ while (!Done) {
+ if (!FindNextFile (FSData->Handle, &(FSData->FindData))) {
+ return STATUS_NOT_FOUND;
+ }
+ //
+ // See if it matches their criteria
+ //
+ Done = FileSearchMeetsCriteria (FSData);
+ if (Done) {
+ return STATUS_SUCCESS;
+ }
+ }
+ //
+ // Not reached
+ //
+ return STATUS_NOT_FOUND;
+}
+//
+// Perform any cleanup necessary to close down a search
+//
+STATUS
+FileSearchDestroy (
+ FILE_SEARCH_DATA *FSData
+ )
+{
+ if (FSData->Handle != INVALID_HANDLE_VALUE) {
+ FindClose (FSData->Handle);
+ FSData->Handle = INVALID_HANDLE_VALUE;
+ }
+
+ FSData->FileName[0] = 0;
+ FSData->FileSearchFlags = 0;
+ return STATUS_SUCCESS;
+}
+
+static
+BOOLEAN
+FileSearchMeetsCriteria (
+ FILE_SEARCH_DATA *FSData
+ )
+{
+ BOOLEAN Status;
+ STRING_LIST *StrList;
+ UINT32 ExtLen;
+ UINT32 FileNameLen;
+
+ Status = FALSE;
+
+ //
+ // First clear the flag indicating this is neither a file or a
+ // directory.
+ //
+ FSData->FileFlags &= ~(FILE_SEARCH_DIR | FILE_SEARCH_FILE);
+
+ //
+ // We found a file. See if it matches the user's search criteria. First
+ // check for this being a directory, and they want directories, and
+ // it's not "." and it's not ".."
+ //
+ if ((FSData->FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) &&
+ (FSData->FileSearchFlags & FILE_SEARCH_DIR) &&
+ (strcmp (FSData->FindData.cFileName, ".")) &&
+ (strcmp (FSData->FindData.cFileName, ".."))
+ ) {
+ //
+ // Assume we'll make it past this check
+ //
+ Status = TRUE;
+ //
+ // If they have a list of exclude directories, then check for those
+ //
+ StrList = FSData->ExcludeDirs;
+ while (StrList != NULL) {
+ if (stricmp (FSData->FindData.cFileName, StrList->Str) == 0) {
+ Status = FALSE;
+ break;
+ }
+
+ StrList = StrList->Next;
+ }
+ //
+ // If we didn't fail due to excluded directories, then set the dir flag
+ //
+ if (Status) {
+ FSData->FileFlags |= FILE_SEARCH_DIR;
+ }
+ //
+ // Else check for a file, and they want files....
+ //
+ } else if (((FSData->FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0) &&
+ (FSData->FileSearchFlags & FILE_SEARCH_FILE)
+ ) {
+ //
+ // See if it's in our list of excluded files
+ //
+ Status = TRUE;
+ StrList = FSData->ExcludeFiles;
+ while (StrList != NULL) {
+ if (stricmp (FSData->FindData.cFileName, StrList->Str) == 0) {
+ Status = FALSE;
+ break;
+ }
+
+ StrList = StrList->Next;
+ }
+
+ if (Status) {
+ //
+ // See if it's in our list of excluded file extensions
+ //
+ FileNameLen = strlen (FSData->FindData.cFileName);
+ StrList = FSData->ExcludeExtensions;
+ while (StrList != NULL) {
+ ExtLen = strlen (StrList->Str);
+ if (stricmp (
+ FSData->FindData.cFileName + FileNameLen - ExtLen,
+ StrList->Str
+ ) == 0) {
+ Status = FALSE;
+ break;
+ }
+
+ StrList = StrList->Next;
+ }
+ }
+
+ if (Status) {
+ FSData->FileFlags |= FILE_SEARCH_FILE;
+ }
+ }
+ //
+ // If it's a match, copy the filename into another field of the structure
+ // for portability.
+ //
+ if (Status) {
+ strcpy (FSData->FileName, FSData->FindData.cFileName);
+ }
+
+ return Status;
+}
+//
+// Exclude a list of subdirectories.
+//
+STATUS
+FileSearchExcludeDirs (
+ FILE_SEARCH_DATA *FSData,
+ STRING_LIST *StrList
+ )
+{
+ FSData->ExcludeDirs = StrList;
+ return STATUS_SUCCESS;
+}
+
+STATUS
+FileSearchExcludeFiles (
+ FILE_SEARCH_DATA *FSData,
+ STRING_LIST *StrList
+ )
+{
+ FSData->ExcludeFiles = StrList;
+ return STATUS_SUCCESS;
+}
+
+STATUS
+FileSearchExcludeExtensions (
+ FILE_SEARCH_DATA *FSData,
+ STRING_LIST *StrList
+ )
+{
+ FSData->ExcludeExtensions = StrList;
+ return STATUS_SUCCESS;
+}
diff --git a/Source/GuidChk/FileSearch.h b/Source/GuidChk/FileSearch.h
new file mode 100644
index 0000000..bc40265
--- /dev/null
+++ b/Source/GuidChk/FileSearch.h
@@ -0,0 +1,108 @@
+/*++
+
+Copyright (c) 2004, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ FileSearch.h
+
+Abstract:
+
+ Header file to support file searching.
+
+--*/
+
+#ifndef _FILE_SEARCH_H_
+#define _FILE_SEARCH_H_
+
+//
+// Since the file searching routines are OS dependent, put the
+// necessary include paths in this header file so that the non-OS-dependent
+// files don't need to include these windows-specific header files.
+//
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <direct.h>
+#include <windows.h>
+
+//
+// Return codes of some of the file search routines
+//
+#define STATUS_NOT_FOUND 0x1000
+
+//
+// Flags for what to search for. Also used in the FileFlags return field.
+//
+#define FILE_SEARCH_DIR 0x0001
+#define FILE_SEARCH_FILE 0x0002
+
+//
+// Here's our class definition
+//
+typedef struct {
+ HANDLE Handle;
+ WIN32_FIND_DATA FindData;
+ UINT32 FileSearchFlags; // DIRS, FILES, etc
+ UINT32 FileFlags;
+ INT8 FileName[MAX_PATH]; // for portability
+ STRING_LIST *ExcludeDirs;
+ STRING_LIST *ExcludeFiles;
+ STRING_LIST *ExcludeExtensions;
+} FILE_SEARCH_DATA;
+
+//
+// Here's our member functions
+//
+STATUS
+FileSearchInit (
+ FILE_SEARCH_DATA *FSData
+ )
+;
+
+STATUS
+FileSearchDestroy (
+ FILE_SEARCH_DATA *FSData
+ )
+;
+
+STATUS
+FileSearchStart (
+ FILE_SEARCH_DATA *FSData,
+ char *FileMask,
+ UINT32 SearchFlags
+ )
+;
+
+STATUS
+FileSearchFindNext (
+ FILE_SEARCH_DATA *FSData
+ )
+;
+
+STATUS
+FileSearchExcludeDirs (
+ FILE_SEARCH_DATA *FSData,
+ STRING_LIST *StrList
+ )
+;
+STATUS
+FileSearchExcludeExtensions (
+ FILE_SEARCH_DATA *FSData,
+ STRING_LIST *StrList
+ )
+;
+STATUS
+FileSearchExcludeFiles (
+ FILE_SEARCH_DATA *FSData,
+ STRING_LIST *StrList
+ )
+;
+#endif
diff --git a/Source/GuidChk/GuidChk.c b/Source/GuidChk/GuidChk.c
new file mode 100644
index 0000000..de88405
--- /dev/null
+++ b/Source/GuidChk/GuidChk.c
@@ -0,0 +1,2348 @@
+/*++
+
+Copyright (c) 2004, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ GuidChk.c
+
+Abstract:
+
+ Parse files in a directory and subdirectories to find all guid definitions.
+ Then check them against each other to make sure there are no duplicates.
+
+--*/
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+
+#include "CommonUtils.h"
+#include "FileSearch.h"
+#include "UtilsMsgs.h"
+
+#define MAX_LINE_LEN 180 // we concatenate two lines sometimes
+// Define a structure that correlates filename extensions to an enumerated
+// type.
+//
+typedef struct {
+ INT8 *Extension;
+ INT8 ExtensionCode;
+} FILE_TYPE_TABLE_ENTRY;
+
+#define FILE_EXTENSION_UNKNOWN 0
+#define FILE_EXTENSION_C 1
+#define FILE_EXTENSION_H 2
+#define FILE_EXTENSION_IA32_ASM 3
+#define FILE_EXTENSION_IA32_INC 4
+#define FILE_EXTENSION_IA64_ASM 5
+#define FILE_EXTENSION_IA64_INC 6
+#define FILE_EXTENSION_PKG 7
+#define FILE_EXTENSION_INF 8
+
+FILE_TYPE_TABLE_ENTRY FileTypeTable[] = {
+ ".c",
+ FILE_EXTENSION_C,
+ ".h",
+ FILE_EXTENSION_H,
+ ".inc",
+ FILE_EXTENSION_IA32_INC,
+ ".asm",
+ FILE_EXTENSION_IA32_ASM,
+ ".s",
+ FILE_EXTENSION_IA64_ASM,
+ ".pkg",
+ FILE_EXTENSION_PKG,
+ ".inf",
+ FILE_EXTENSION_INF,
+ ".i",
+ FILE_EXTENSION_IA64_INC,
+ NULL,
+ 0
+};
+
+typedef struct EFI_GUID {
+ UINT32 Data1;
+ UINT16 Data2;
+ UINT16 Data3;
+ UINT8 Data4[8];
+} EFI_GUID;
+
+typedef struct {
+ INT8 Data[4];
+ INT8 DataLen;
+} EFI_SIGNATURE;
+
+typedef struct _GUID_RECORD {
+ struct _GUID_RECORD *Next;
+ BOOLEAN Reported;
+ INT8 *FileName;
+ INT8 *SymName;
+ EFI_GUID Guid;
+} GUID_RECORD;
+
+typedef struct _SIGNATURE_RECORD {
+ struct _SIGNATURE_RECORD *Next;
+ BOOLEAN Reported;
+ INT8 *FileName;
+ EFI_SIGNATURE Signature;
+} SIGNATURE_RECORD;
+
+//
+// Utility options
+//
+typedef struct {
+ INT8 DatabaseOutputFileName[MAX_PATH]; // with -b option
+ STRING_LIST *ExcludeDirs; // list of directory names not to process
+ STRING_LIST *ExcludeSubDirs; // list of directory names to not process subdirectories (build)
+ STRING_LIST *ExcludeFiles; // list of files to exclude (make.inf)
+ STRING_LIST *ExcludeExtensions; // list of filename extensions to exclude (.inf, .pkg)
+ BOOLEAN Verbose;
+ BOOLEAN PrintFound;
+ BOOLEAN CheckGuids;
+ BOOLEAN CheckSignatures;
+ BOOLEAN GuidXReference;
+} OPTIONS;
+
+static
+STATUS
+ProcessArgs (
+ int Argc,
+ char *Argv[]
+ );
+
+static
+VOID
+Usage (
+ VOID
+ );
+
+static
+STATUS
+ProcessDirectory (
+ INT8 *Path,
+ INT8 *DirectoryName
+ );
+
+static
+STATUS
+ProcessFile (
+ INT8 *DirectoryName,
+ INT8 *FileName
+ );
+
+static
+UINT32
+GetFileExtension (
+ INT8 *FileName
+ );
+
+static
+UINT32
+SkipWhiteSpace (
+ INT8 *Str
+ );
+
+static
+UINT32
+ValidSymbolName (
+ INT8 *Name
+ );
+
+static
+STATUS
+ProcessCFileGuids (
+ INT8 *FileName
+ );
+
+static
+STATUS
+AddSignature (
+ INT8 *FileName,
+ INT8 *StrDef,
+ UINT32 SigSize
+ );
+
+static
+STATUS
+ProcessCFileSigs (
+ INT8 *FileName
+ );
+
+static
+STATUS
+ProcessINFFileGuids (
+ INT8 *FileName
+ );
+
+static
+STATUS
+ProcessPkgFileGuids (
+ INT8 *FileName
+ );
+
+static
+STATUS
+ProcessIA32FileGuids (
+ INT8 *FileName
+ );
+
+static
+STATUS
+ProcessIA64FileGuids (
+ INT8 *FileName
+ );
+
+static
+BOOLEAN
+IsIA64GuidLine (
+ INT8 *Line,
+ UINT32 *GuidHigh,
+ UINT32 *GuidLow,
+ BOOLEAN *Low,
+ INT8 *SymName
+ );
+
+static
+STATUS
+AddGuid11 (
+ INT8 *FileName,
+ UINT32 *Data,
+ INT8 *SymName
+ );
+
+static
+STATUS
+AddPkgGuid (
+ INT8 *FileName,
+ UINT32 *Data,
+ UINT64 *Data64
+ );
+
+static
+STATUS
+AddGuid16 (
+ INT8 *FileName,
+ UINT32 *Data
+ );
+
+static
+STATUS
+AddGuid64x2 (
+ INT8 *FileName,
+ UINT32 DataHH, // Upper 32-bits of upper 64 bits of guid
+ UINT32 DataHL, // Lower 32-bits of upper 64 bits
+ UINT32 DataLH,
+ UINT32 DataLL
+ );
+
+static
+VOID
+FreeGuids (
+ VOID
+ );
+
+static
+VOID
+FreeSigs (
+ VOID
+ );
+
+static
+STATUS
+CheckDuplicates (
+ VOID
+ );
+
+//
+// static
+// VOID
+// ReportGuid (
+// INT8 *FileName,
+// GUID_RECORD *FileRecord
+// );
+//
+static
+VOID
+FreeOptions (
+ VOID
+ );
+
+static
+BOOLEAN
+CheckGuidData (
+ UINT32 *GuidData,
+ UINT32 DataCount
+ );
+
+/**************************** GLOBALS ****************************************/
+static GUID_RECORD *gGuidList = NULL;
+static SIGNATURE_RECORD *gSignatureList = NULL;
+static OPTIONS gOptions;
+
+/*****************************************************************************/
+int
+main (
+ int Argc,
+ char *Argv[]
+ )
+{
+ INT8 *Cwd;
+ STATUS Status;
+
+ SetUtilityName ("GuidChk");
+ //
+ // Get the current working directory and then process the command line
+ // arguments.
+ //
+ Cwd = _getcwd (NULL, 0);
+ Status = ProcessArgs (Argc, Argv);
+ if (Status != STATUS_SUCCESS) {
+ return Status;
+ }
+
+ if (gOptions.CheckGuids || gOptions.CheckSignatures) {
+ Status = ProcessDirectory (Cwd, NULL);
+ if (Status == STATUS_SUCCESS) {
+ //
+ // Check for duplicates
+ //
+ Status = CheckDuplicates ();
+ }
+ }
+
+ if (gOptions.DatabaseOutputFileName[0] != 0) {
+ CreateGuidList (gOptions.DatabaseOutputFileName);
+ }
+ //
+ // Free up the memory
+ //
+ free (Cwd);
+ FreeGuids ();
+ FreeSigs ();
+ FreeOptions ();
+ return GetUtilityStatus ();
+}
+
+static
+STATUS
+ProcessArgs (
+ int Argc,
+ char *Argv[]
+ )
+{
+ STRING_LIST *StrList;
+
+ memset ((char *) &gOptions, 0, sizeof (gOptions));
+ //
+ // skip over program name
+ //
+ Argc--;
+ Argv++;
+
+ if (Argc == 0) {
+ Usage ();
+ return STATUS_ERROR;
+ }
+
+ while (Argc > 0) {
+ //
+ // Look for options
+ //
+ if ((Argv[0][0] == '-') || (Argv[0][0] == '/')) {
+ switch (Argv[0][1]) {
+ //
+ // Help option
+ //
+ case 'h':
+ case 'H':
+ case '?':
+ Usage ();
+ return STATUS_ERROR;
+ break;
+
+ //
+ // Check guids option
+ //
+ case 'g':
+ case 'G':
+ gOptions.CheckGuids = TRUE;
+ break;
+
+ //
+ // Check signatures option
+ //
+ case 's':
+ case 'S':
+ gOptions.CheckSignatures = TRUE;
+ break;
+
+ //
+ // Print guids found option
+ //
+ case 'p':
+ case 'P':
+ gOptions.PrintFound = TRUE;
+ break;
+
+ //
+ // Exclude files option
+ //
+ case 'f':
+ case 'F':
+ //
+ // Check for another arg
+ //
+ if (Argc < 2) {
+ Error (NULL, 0, 0, Argv[0], "missing argument with option");
+ Usage ();
+ return STATUS_ERROR;
+ }
+
+ StrList = malloc (sizeof (STRING_LIST));
+ if (StrList == NULL) {
+ Error (NULL, 0, 0, "memory allocation failure", NULL);
+ return STATUS_ERROR;
+ }
+
+ memset ((char *) StrList, 0, sizeof (STRING_LIST));
+ StrList->Str = Argv[1];
+ StrList->Next = gOptions.ExcludeFiles;
+ gOptions.ExcludeFiles = StrList;
+ Argc--;
+ Argv++;
+ break;
+
+ //
+ // Exclude directories option
+ //
+ case 'd':
+ case 'D':
+ //
+ // Check for another arg
+ //
+ if (Argc < 2) {
+ Error (NULL, 0, 0, Argv[0], "missing argument with option");
+ Usage ();
+ return STATUS_ERROR;
+ }
+
+ StrList = malloc (sizeof (STRING_LIST));
+ if (StrList == NULL) {
+ Error (NULL, 0, 0, "memory allocation failure", NULL);
+ return STATUS_ERROR;
+ }
+
+ memset ((char *) StrList, 0, sizeof (STRING_LIST));
+ StrList->Str = Argv[1];
+ StrList->Next = gOptions.ExcludeDirs;
+ gOptions.ExcludeDirs = StrList;
+ Argc--;
+ Argv++;
+ break;
+
+ //
+ // -u exclude all subdirectories of a given directory option
+ //
+ case 'u':
+ case 'U':
+ //
+ // Check for another arg
+ //
+ if (Argc < 2) {
+ Error (NULL, 0, 0, Argv[0], "missing argument with option");
+ Usage ();
+ return STATUS_ERROR;
+ }
+
+ StrList = malloc (sizeof (STRING_LIST));
+ if (StrList == NULL) {
+ Error (NULL, 0, 0, "memory allocation failure", NULL);
+ return STATUS_ERROR;
+ }
+
+ memset ((char *) StrList, 0, sizeof (STRING_LIST));
+ StrList->Str = Argv[1];
+ StrList->Next = gOptions.ExcludeSubDirs;
+ gOptions.ExcludeSubDirs = StrList;
+ Argc--;
+ Argv++;
+ break;
+
+ //
+ // -e exclude by filename extension option
+ //
+ case 'e':
+ case 'E':
+ //
+ // Check for another arg
+ //
+ if (Argc < 2) {
+ Error (NULL, 0, 0, Argv[0], "missing argument with option");
+ Usage ();
+ return STATUS_ERROR;
+ }
+
+ StrList = malloc (sizeof (STRING_LIST));
+ if (StrList == NULL) {
+ Error (NULL, 0, 0, "memory allocation failure", NULL);
+ return STATUS_ERROR;
+ }
+
+ memset ((char *) StrList, 0, sizeof (STRING_LIST));
+ //
+ // Let them put a * in front of the filename extension
+ //
+ StrList->Str = Argv[1];
+ if (StrList->Str[0] == '*') {
+ StrList->Str++;
+ }
+
+ StrList->Next = gOptions.ExcludeExtensions;
+ gOptions.ExcludeExtensions = StrList;
+ Argc--;
+ Argv++;
+ break;
+
+ //
+ // Print guid with matching symbol name for guid definitions found
+ //
+ case 'x':
+ case 'X':
+ gOptions.GuidXReference = 1;
+ break;
+
+ //
+ // -b Print the internal database list to a file
+ //
+ case 'b':
+ case 'B':
+ //
+ // Check for one more arg
+ //
+ if (Argc < 2) {
+ Error (NULL, 0, 0, Argv[0], "must specify file name with option");
+ Usage ();
+ return STATUS_ERROR;
+ }
+
+ strcpy (gOptions.DatabaseOutputFileName, Argv[1]);
+ Argc--;
+ Argv++;
+ break;
+
+ default:
+ Error (NULL, 0, 0, Argv[0], "invalid option");
+ Usage ();
+ return STATUS_ERROR;
+ }
+ } else {
+ break;
+ }
+ //
+ // Next arg
+ //
+ Argc--;
+ Argv++;
+ }
+
+ if (Argc > 0) {
+ Error (NULL, 0, 0, Argv[0], "invalid argument");
+ Usage ();
+ return STATUS_ERROR;
+ }
+ //
+ // Have to check signatures, GUIDs, or dump the GUID database.
+ //
+ if ((!gOptions.CheckGuids) && (!gOptions.CheckSignatures) && (gOptions.DatabaseOutputFileName[0] == 0)) {
+ Error (NULL, 0, 0, "nothing to do", "must specify -g, -s, and/or -b");
+ Usage ();
+ return STATUS_ERROR;
+ }
+
+ return STATUS_SUCCESS;
+}
+//
+// Print usage instructions
+//
+static
+VOID
+Usage (
+ VOID
+ )
+{
+ int Index;
+ char *Str[] = {
+ "GuidChk - scan files for duplicate GUID or signature definitions",
+ "",
+ "Usage: GuidChk {options}\n",
+ " Options: ",
+ " -d dirname exclude searching of a directory",
+ " -f filename exclude searching of a file",
+ " -e extension exclude searching of files by extension",
+ " -p print all GUIDS found",
+ " -g check for duplicate guids",
+ " -s check for duplicate signatures",
+ " -x print guid+defined symbol name",
+ " -b outfile write internal GUID+basename list to outfile",
+ " -u dirname exclude searching all subdirectories of a directory",
+ " -h -? print this help text",
+ " ",
+ " Example: GuidChk -g -u build -d fv -f make.inf -e .pkg",
+ "",
+ NULL
+ };
+ for (Index = 0; Str[Index] != NULL; Index++) {
+ fprintf (stdout, "%s\n", Str[Index]);
+ }
+}
+//
+// Process an entire directory by name
+//
+static
+STATUS
+ProcessDirectory (
+ INT8 *Path,
+ INT8 *DirectoryName
+ )
+{
+ FILE_SEARCH_DATA FSData;
+ char *FileMask;
+ BOOLEAN Done;
+ UINT32 Len;
+ BOOLEAN NoSubdirs;
+ STRING_LIST *SLPtr;
+
+ //
+ // Root directory may be null
+ //
+ if (DirectoryName != NULL) {
+ //
+ // printf ("Processing directory: %s\n", DirectoryName);
+ //
+ }
+ //
+ // Initialize our file searching
+ //
+ FileSearchInit (&FSData);
+
+ //
+ // Exclude some directories, files, and extensions
+ //
+ FileSearchExcludeDirs (&FSData, gOptions.ExcludeDirs);
+ FileSearchExcludeExtensions (&FSData, gOptions.ExcludeExtensions);
+ FileSearchExcludeFiles (&FSData, gOptions.ExcludeFiles);
+ //
+ // See if this directory is in the list of directories that they
+ // don't want to process subdirectories of
+ //
+ NoSubdirs = FALSE;
+ if (DirectoryName != NULL) {
+ for (SLPtr = gOptions.ExcludeSubDirs; SLPtr != NULL; SLPtr = SLPtr->Next) {
+ if (stricmp (SLPtr->Str, DirectoryName) == 0) {
+ //
+ // printf ("not processing subdirectories of %s\n", DirectoryName);
+ //
+ NoSubdirs = TRUE;
+ break;
+ }
+ }
+ }
+ //
+ // Create a filemask of files to search for. We'll append "\*.*" on the
+ // end, so allocate some extra bytes.
+ //
+ Len = strlen (Path) + 10;
+ if (DirectoryName != NULL) {
+ Len += strlen (DirectoryName);
+ }
+
+ FileMask = malloc (Len);
+ if (FileMask == NULL) {
+ Error (NULL, 0, 0, "memory allocation failure", NULL);
+ return STATUS_ERROR;
+ }
+ //
+ // Now put it all together
+ //
+ strcpy (FileMask, Path);
+ if ((DirectoryName != NULL) && (strlen (DirectoryName) > 0)) {
+ strcat (FileMask, "\\");
+ strcat (FileMask, DirectoryName);
+ }
+
+ strcat (FileMask, "\\*.*");
+
+ //
+ // Start file searching for files and directories
+ //
+ FileSearchStart (&FSData, FileMask, FILE_SEARCH_FILE | FILE_SEARCH_DIR);
+
+ //
+ // Now hack the "\*.*" off the end of the filemask so we can use it to pass
+ // the full directory path on recursive calls to process directories.
+ //
+ FileMask[strlen (FileMask) - 4] = 0;
+
+ //
+ // Loop until no more files
+ //
+ Done = FALSE;
+ while (!Done) {
+ //
+ // printf ("Found %s...", FSData.FileName);
+ //
+ if (FSData.FileFlags & FILE_SEARCH_DIR) {
+ //
+ // printf ("directory\n");
+ //
+ if (!NoSubdirs) {
+ ProcessDirectory (FileMask, FSData.FileName);
+ }
+ } else if (FSData.FileFlags & FILE_SEARCH_FILE) {
+ //
+ // printf ("file\n");
+ //
+ ProcessFile (FileMask, FSData.FileName);
+ } else {
+ //
+ // printf ("unknown\n");
+ //
+ }
+
+ if (FileSearchFindNext (&FSData) != STATUS_SUCCESS) {
+ Done = TRUE;
+ }
+ }
+ //
+ // Free up allocated memory
+ //
+ free (FileMask);
+
+ //
+ // Free up our file searching
+ //
+ FileSearchDestroy (&FSData);
+
+ return STATUS_SUCCESS;
+}
+//
+// Process a single file.
+//
+static
+STATUS
+ProcessFile (
+ INT8 *DirectoryName,
+ INT8 *FileName
+ )
+{
+ STATUS Status;
+ UINT32 FileExtension;
+ INT8 FullFileName[MAX_PATH];
+
+ Status = STATUS_SUCCESS;
+
+ sprintf (FullFileName, "%s\\%s", DirectoryName, FileName);
+ //
+ // printf ("Found file: %s\n", FullFileName);
+ //
+ FileExtension = GetFileExtension (FileName);
+
+ //
+ // Process these for GUID checks
+ //
+ if (gOptions.CheckGuids) {
+ switch (FileExtension) {
+ case FILE_EXTENSION_C:
+ case FILE_EXTENSION_H:
+ Status = ProcessCFileGuids (FullFileName);
+ break;
+
+ case FILE_EXTENSION_PKG:
+ Status = ProcessPkgFileGuids (FullFileName);
+ break;
+
+ case FILE_EXTENSION_IA32_INC:
+ case FILE_EXTENSION_IA32_ASM:
+ Status = ProcessIA32FileGuids (FullFileName);
+ break;
+
+ case FILE_EXTENSION_INF:
+ Status = ProcessINFFileGuids (FullFileName);
+ break;
+
+ case FILE_EXTENSION_IA64_INC:
+ case FILE_EXTENSION_IA64_ASM:
+ Status = ProcessIA64FileGuids (FullFileName);
+ break;
+
+ default:
+ //
+ // No errors anyway
+ //
+ Status = STATUS_SUCCESS;
+ break;
+ }
+ }
+
+ if (gOptions.CheckSignatures) {
+ switch (FileExtension) {
+ case FILE_EXTENSION_C:
+ case FILE_EXTENSION_H:
+ Status = ProcessCFileSigs (FullFileName);
+ break;
+
+ default:
+ //
+ // No errors anyway
+ //
+ Status = STATUS_SUCCESS;
+ break;
+ }
+ }
+
+ return Status;
+}
+//
+// Return a code indicating the file name extension.
+//
+static
+UINT32
+GetFileExtension (
+ INT8 *FileName
+ )
+{
+ INT8 *Extension;
+ int Index;
+
+ //
+ // Look back for a filename extension
+ //
+ for (Extension = FileName + strlen (FileName) - 1; Extension >= FileName; Extension--) {
+ if (*Extension == '.') {
+ for (Index = 0; FileTypeTable[Index].Extension != NULL; Index++) {
+ if (stricmp (FileTypeTable[Index].Extension, Extension) == 0) {
+ return FileTypeTable[Index].ExtensionCode;
+ }
+ }
+ }
+ }
+
+ return FILE_TYPE_UNKNOWN;
+}
+//
+// Process a .pkg file.
+//
+// Look for FFS_FILEGUID=35b898ca-b6a9-49ce-8c72-904735cc49b7
+//
+static
+STATUS
+ProcessPkgFileGuids (
+ INT8 *FileName
+ )
+{
+ FILE *Fptr;
+ INT8 Line[MAX_LINE_LEN * 2];
+ INT8 *Cptr;
+ INT8 *Cptr2;
+ UINT32 GuidScan[11];
+ UINT64 Guid64;
+
+ if ((Fptr = fopen (FileName, "r")) == NULL) {
+ Error (NULL, 0, 0, FileName, "could not open input file for reading");
+ return STATUS_ERROR;
+ }
+ //
+ // Read lines from the file until done
+ //
+ while (fgets (Line, sizeof (Line), Fptr) != NULL) {
+ Cptr = Line;
+ Cptr += SkipWhiteSpace (Line);
+ if (strncmp (Cptr, "FFS_FILEGUID", 12) == 0) {
+ Cptr += 12;
+ Cptr += SkipWhiteSpace (Cptr);
+ if (*Cptr == '=') {
+ Cptr++;
+ Cptr += SkipWhiteSpace (Cptr + 1);
+ //
+ // Blank out dashes on the line.
+ //
+ for (Cptr2 = Cptr; *Cptr2; Cptr2++) {
+ if (*Cptr2 == '-') {
+ *Cptr2 = ' ';
+ }
+ }
+
+ if (sscanf (
+ Cptr,
+ "%X %X %X %X %I64X",
+ &GuidScan[0],
+ &GuidScan[1],
+ &GuidScan[2],
+ &GuidScan[3],
+ &Guid64
+ ) == 5) {
+ AddPkgGuid (FileName, GuidScan, &Guid64);
+ } else {
+ DebugMsg (NULL, 0, 0, FileName, "GUID scan failed");
+ }
+ }
+ }
+ }
+
+ fclose (Fptr);
+ return STATUS_SUCCESS;
+}
+//
+// Process an IA32 assembly file.
+//
+// Look for:
+// FIND_FD_GUID_VAL equ 01h, 01h, 01h, 01h, 01h, 01h, 01h, 01h, 01h, 01h, 01h, 01h, 01h, 01h, 01h, 01h
+// PEI_GUID_FileNameGuid_Gmch815 equ 081818181h, 08181h, 08181h, 081h, 081h, 081h, 081h, 081h, 081h, 081h, 081h
+//
+static
+STATUS
+ProcessIA32FileGuids (
+ INT8 *FileName
+ )
+{
+ FILE *Fptr;
+ INT8 Line[MAX_LINE_LEN];
+ INT8 *Cptr;
+ INT8 CSave;
+ INT8 *CSavePtr;
+ UINT32 Len;
+ UINT32 GuidData[16];
+ UINT32 Index;
+
+ if ((Fptr = fopen (FileName, "r")) == NULL) {
+ Error (NULL, 0, 0, FileName, "could not open input file for reading");
+ return STATUS_ERROR;
+ }
+ //
+ // Read lines from the file until done
+ //
+ while (fgets (Line, sizeof (Line), Fptr) != NULL) {
+ Cptr = Line;
+ Cptr += SkipWhiteSpace (Line);
+ //
+ // Look for xxxGUIDyyy equ 01h, 02h, 03h, ...
+ //
+ Len = ValidSymbolName (Cptr);
+ if (Len) {
+ //
+ // Terminate the line after the symbol name, then look for "guid" in
+ // the name.
+ //
+ CSavePtr = Cptr + Len;
+ CSave = *CSavePtr;
+ *CSavePtr = 0;
+ while (*Cptr) {
+ if (strnicmp (Cptr, "guid", 4) == 0) {
+ break;
+ }
+
+ Cptr++;
+ }
+ //
+ // If we found the string "guid", continue
+ //
+ if (*Cptr) {
+ //
+ // Restore the character on the line where we null-terminated the symbol
+ //
+ *CSavePtr = CSave;
+ Cptr = CSavePtr;
+ Len = SkipWhiteSpace (Cptr);
+ //
+ // Had to be some white space
+ //
+ if (Len) {
+ Cptr += Len;
+ //
+ // now look for "equ"
+ //
+ if (strnicmp (Cptr, "equ", 3) == 0) {
+ Cptr += 3;
+ Cptr += SkipWhiteSpace (Cptr);
+ //
+ // Now scan all the data
+ //
+ for (Index = 0; Index < 16; Index++) {
+ if (sscanf (Cptr, "%X", &GuidData[Index]) != 1) {
+ break;
+ }
+ //
+ // Skip to next
+ //
+ while (isxdigit (*Cptr)) {
+ Cptr++;
+ }
+
+ if ((*Cptr != 'h') && (*Cptr != 'H')) {
+ break;
+ } else {
+ Cptr++;
+ while (*Cptr && (isspace (*Cptr) || (*Cptr == ','))) {
+ Cptr++;
+ }
+ }
+ }
+ //
+ // Now see which form we had
+ //
+ if (Index == 16) {
+ AddGuid16 (FileName, GuidData);
+ } else if (Index == 11) {
+ AddGuid11 (FileName, GuidData, NULL);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ fclose (Fptr);
+ return STATUS_SUCCESS;
+}
+//
+// Found and parsed an IA32 assembly code guid. Save the 16 bytes off in the list
+// of guids.
+//
+static
+STATUS
+AddGuid16 (
+ INT8 *FileName,
+ UINT32 *Data
+ )
+{
+ GUID_RECORD *NewRec;
+ int Index;
+
+ //
+ // Sanity check the data
+ //
+ if (!CheckGuidData (Data, 16)) {
+ return STATUS_ERROR;
+ }
+ //
+ // Allocate memory for a new guid structure
+ //
+ NewRec = malloc (sizeof (GUID_RECORD));
+ if (NewRec == NULL) {
+ Error (NULL, 0, 0, "memory allocation failure", NULL);
+ return STATUS_ERROR;
+ }
+
+ memset ((char *) NewRec, 0, sizeof (GUID_RECORD));
+ NewRec->FileName = malloc (strlen (FileName) + 1);
+ if (NewRec->FileName == NULL) {
+ free (NewRec);
+ Error (NULL, 0, 0, "memory allocation failure", NULL);
+ return STATUS_ERROR;
+ }
+
+ strcpy (NewRec->FileName, FileName);
+ NewRec->Guid.Data1 = (UINT32) (Data[0] | (Data[1] << 8) | (Data[2] << 16) | (Data[3] << 24));
+ NewRec->Guid.Data2 = (UINT16) (Data[4] | (Data[5] << 8));
+ NewRec->Guid.Data3 = (UINT16) (Data[6] | (Data[7] << 8));
+ for (Index = 0; Index < 8; Index++) {
+ NewRec->Guid.Data4[Index] = (UINT8) Data[Index + 8];
+ }
+ //
+ // Add it to the list
+ //
+ NewRec->Next = gGuidList;
+ gGuidList = NewRec;
+
+ //
+ // Report it
+ // ReportGuid (FileName, NewRec);
+ //
+ return STATUS_SUCCESS;
+}
+//
+// Add a GUID defined as GuidLow: 0x1122334455667788
+// GuidHi: 0x99AABBCCDDEEFF00
+//
+// These are equivalent:
+// { 0x11223344, 0x5566, 0x7788, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0x00 }
+// and:
+// Low: 00FFEEDDCCBBAA99
+// Hi: 7788556611223344
+//
+static
+STATUS
+AddGuid64x2 (
+ INT8 *FileName,
+ UINT32 DataHH, // Upper 32-bits of upper 64 bits of guid
+ UINT32 DataHL, // Lower 32-bits of upper 64 bits
+ UINT32 DataLH,
+ UINT32 DataLL
+ )
+{
+ GUID_RECORD *NewRec;
+ int Index;
+
+ //
+ // Allocate memory for a new guid structure
+ //
+ NewRec = malloc (sizeof (GUID_RECORD));
+ if (NewRec == NULL) {
+ Error (NULL, 0, 0, "memory allocation failure", NULL);
+ return STATUS_ERROR;
+ }
+
+ memset ((char *) NewRec, 0, sizeof (GUID_RECORD));
+ NewRec->FileName = malloc (strlen (FileName) + 1);
+ if (NewRec->FileName == NULL) {
+ free (NewRec);
+ Error (NULL, 0, 0, "memory allocation failure", NULL);
+ return STATUS_ERROR;
+ }
+
+ strcpy (NewRec->FileName, FileName);
+ NewRec->Guid.Data1 = DataHL;
+ NewRec->Guid.Data2 = (UINT16) DataHH;
+ NewRec->Guid.Data3 = (UINT16) (DataHH >> 16);
+ for (Index = 0; Index < 4; Index++) {
+ NewRec->Guid.Data4[Index] = (UINT8) DataLL;
+ DataLL >>= 8;
+ }
+
+ for (Index = 0; Index < 4; Index++) {
+ NewRec->Guid.Data4[Index + 4] = (UINT8) DataLH;
+ DataLH >>= 8;
+ }
+ //
+ // Add it to the list
+ //
+ NewRec->Next = gGuidList;
+ gGuidList = NewRec;
+
+ //
+ // Report it
+ // ReportGuid (FileName, NewRec);
+ //
+ return STATUS_SUCCESS;
+}
+//
+// Process INF files. Look for:
+// FILE_GUID = 240612B6-A063-11d4-9A3A-0090273FC14D
+//
+static
+STATUS
+ProcessINFFileGuids (
+ INT8 *FileName
+ )
+{
+ FILE *Fptr;
+ INT8 Line[MAX_LINE_LEN * 2];
+ INT8 *Cptr;
+ INT8 *Cptr2;
+ UINT32 GuidScan[11];
+ UINT64 Guid64;
+
+ if ((Fptr = fopen (FileName, "r")) == NULL) {
+ Error (NULL, 0, 0, FileName, "could not open input file for reading");
+ return STATUS_ERROR;
+ }
+ //
+ // Read lines from the file until done
+ //
+ while (fgets (Line, sizeof (Line), Fptr) != NULL) {
+ Cptr = Line;
+ Cptr += SkipWhiteSpace (Line);
+ if (strncmp (Cptr, "FILE_GUID", 9) == 0) {
+ Cptr += 9;
+ Cptr += SkipWhiteSpace (Cptr);
+ if (*Cptr == '=') {
+ Cptr++;
+ Cptr += SkipWhiteSpace (Cptr + 1);
+ //
+ // Blank out dashes on the line.
+ //
+ for (Cptr2 = Cptr; *Cptr2; Cptr2++) {
+ if (*Cptr2 == '-') {
+ *Cptr2 = ' ';
+ }
+ }
+
+ if (sscanf (
+ Cptr,
+ "%X %X %X %X %I64X",
+ &GuidScan[0],
+ &GuidScan[1],
+ &GuidScan[2],
+ &GuidScan[3],
+ &Guid64
+ ) == 5) {
+ AddPkgGuid (FileName, GuidScan, &Guid64);
+ } else {
+ DebugMsg (NULL, 0, 0, FileName, "GUID scan failed");
+ }
+ }
+ }
+ }
+
+ fclose (Fptr);
+ return STATUS_SUCCESS;
+}
+//
+// Parse ('g','m','a','p','a','b','c','d')
+//
+static
+STATUS
+AddSignature (
+ INT8 *FileName,
+ INT8 *StrDef,
+ UINT32 SigSize
+ )
+{
+ SIGNATURE_RECORD *NewRec;
+ INT8 *Cptr;
+ UINT32 Index;
+ BOOLEAN Fail;
+
+ //
+ // Allocate memory for the new record
+ //
+ Fail = FALSE;
+ NewRec = malloc (sizeof (SIGNATURE_RECORD));
+ if (NewRec == NULL) {
+ Error (NULL, 0, 0, "memory allocation failure", NULL);
+ return STATUS_ERROR;
+ }
+ //
+ // Allocate memory to save the file name
+ //
+ NewRec->FileName = malloc (strlen (FileName) + 1);
+ if (NewRec->FileName == NULL) {
+ Error (NULL, 0, 0, "memory allocation failure", NULL);
+ free (NewRec);
+ return STATUS_ERROR;
+ }
+ //
+ // Fill in the fields
+ //
+ strcpy (NewRec->FileName, FileName);
+ NewRec->Signature.DataLen = (UINT8) SigSize;
+ //
+ // Skip to open parenthesis
+ //
+ Cptr = StrDef;
+ Cptr += SkipWhiteSpace (Cptr);
+ if (*Cptr != '(') {
+ Fail = TRUE;
+ goto Done;
+ }
+
+ Cptr++;
+ //
+ // Skip to first ' and start processing
+ //
+ while (*Cptr && (*Cptr != '\'')) {
+ Cptr++;
+ }
+
+ for (Index = 0; Index < SigSize; Index++) {
+ if (*Cptr == '\'') {
+ Cptr++;
+ NewRec->Signature.Data[Index] = (INT8) *Cptr;
+ //
+ // Skip to closing quote
+ //
+ Cptr++;
+ if (*Cptr != '\'') {
+ Fail = TRUE;
+ break;
+ }
+ //
+ // Skip over closing quote, go to next one
+ //
+ Cptr++;
+ while (*Cptr && (*Cptr != '\'')) {
+ Cptr++;
+ }
+ } else {
+ Fail = TRUE;
+ DebugMsg (NULL, 0, 0, StrDef, "failed to parse signature");
+ break;
+ }
+ }
+
+Done:
+ if (Fail) {
+ free (NewRec->FileName);
+ free (NewRec);
+ return STATUS_ERROR;
+ }
+
+ NewRec->Next = gSignatureList;
+ gSignatureList = NewRec;
+ return STATUS_SUCCESS;
+}
+//
+// Look for:
+// #define POOL_HEAD_SIGNATURE EFI_SIGNATURE_16('p','h')
+// #define GCD_MEMORY_MAP_SIGNATURE EFI_SIGNATURE_32('g','m','a','p')
+// #define GCD_MEMORY_MAP_SIGNATURE EFI_SIGNATURE_64('g','m','a','p','a','b','c','d')
+//
+static
+STATUS
+ProcessCFileSigs (
+ INT8 *FileName
+ )
+{
+ FILE *Fptr;
+ INT8 Line[MAX_LINE_LEN * 2];
+ INT8 *Cptr;
+ UINT32 Len;
+ UINT32 LineLen;
+
+ if ((Fptr = fopen (FileName, "r")) == NULL) {
+ Error (NULL, 0, 0, FileName, "could not open input file for reading");
+ return STATUS_ERROR;
+ }
+ //
+ // Read lines from the file until done
+ //
+ while (fgets (Line, sizeof (Line), Fptr) != NULL) {
+ Cptr = Line;
+ Cptr += SkipWhiteSpace (Line);
+ //
+ // look for #define xxxGUIDxxx value
+ //
+ if (*Cptr == '#') {
+ Cptr++;
+ Cptr += SkipWhiteSpace (Cptr);
+ //
+ // Look for "define"
+ //
+ if (!strncmp (Cptr, "define", 6)) {
+ Cptr += 6;
+ //
+ // Better be whitespace
+ //
+ Len = SkipWhiteSpace (Cptr);
+ if (Len) {
+ Cptr += Len;
+ //
+ // See if it's a valid symbol name
+ //
+ Len = ValidSymbolName (Cptr);
+ if (Len) {
+ //
+ // It is a valid symbol name. See if there's a line continuation,
+ // and if so, read one more line.
+ // Skip over the symbol name and look for the string "EFI_SIGNATURE_xx"
+ //
+ LineLen = strlen (Line);
+ if ((Line[LineLen - 1] == '\n') && (Line[LineLen - 2] == '\\')) {
+ fgets (Line + LineLen - 2, sizeof (Line) - LineLen, Fptr);
+ } else if (Line[LineLen - 1] == '\\') {
+ fgets (Line + LineLen - 1, sizeof (Line) - LineLen, Fptr);
+ }
+
+ Cptr += Len;
+ Cptr += SkipWhiteSpace (Cptr);
+ if (strncmp (Cptr, "EFI_SIGNATURE_16", 16) == 0) {
+ AddSignature (FileName, Cptr + 16, 2);
+ } else if (strncmp (Cptr, "EFI_SIGNATURE_32", 16) == 0) {
+ AddSignature (FileName, Cptr + 16, 4);
+ } else if (strncmp (Cptr, "EFI_SIGNATURE_64", 16) == 0) {
+ AddSignature (FileName, Cptr + 16, 8);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ fclose (Fptr);
+ return STATUS_SUCCESS;
+}
+//
+// look for #define xxxGUIDyyy { 0x...}
+// xxx EFI_GUID GuidName = { 0x... };
+//
+static
+STATUS
+ProcessCFileGuids (
+ INT8 *FileName
+ )
+{
+ FILE *Fptr;
+ INT8 Line[MAX_LINE_LEN * 2];
+ INT8 *Cptr;
+ INT8 CSave;
+ INT8 *CSavePtr;
+ INT8 *TempCptr;
+ INT8 *SymName;
+ UINT32 Len;
+ UINT32 LineLen;
+ UINT32 GuidScan[11];
+
+ if ((Fptr = fopen (FileName, "r")) == NULL) {
+ Error (NULL, 0, 0, FileName, "could not open input file for reading");
+ return STATUS_ERROR;
+ }
+ //
+ // Read lines from the file until done
+ //
+ while (fgets (Line, sizeof (Line), Fptr) != NULL) {
+ Cptr = Line;
+ Cptr += SkipWhiteSpace (Line);
+ //
+ // look for #define xxxGUIDxxx value
+ //
+ if (*Cptr == '#') {
+ Cptr++;
+ Cptr += SkipWhiteSpace (Cptr);
+ //
+ // Look for "define"
+ //
+ if (!strncmp (Cptr, "define", 6)) {
+ Cptr += 6;
+ //
+ // Better be whitespace
+ //
+ Len = SkipWhiteSpace (Cptr);
+ if (Len) {
+ Cptr += Len;
+ //
+ // See if it's a valid symbol name
+ //
+ Len = ValidSymbolName (Cptr);
+ if (Len) {
+ //
+ // It is a valid symbol name. See if there's a line continuation,
+ // and if so, read one more line.
+ // Then truncate after the symbol name, look for the string "GUID",
+ // and continue.
+ //
+ SymName = Cptr;
+ LineLen = strlen (Line);
+ if ((Line[LineLen - 1] == '\n') && (Line[LineLen - 2] == '\\')) {
+ fgets (Line + LineLen - 2, sizeof (Line) - LineLen, Fptr);
+ } else if (Line[LineLen - 1] == '\\') {
+ fgets (Line + LineLen - 1, sizeof (Line) - LineLen, Fptr);
+ }
+
+ CSavePtr = Cptr + Len;
+ CSave = *CSavePtr;
+ *CSavePtr = 0;
+ while (*Cptr) {
+ if (strncmp (Cptr, "GUID", 4) == 0) {
+ break;
+ }
+
+ Cptr++;
+ }
+ //
+ // If we didn't run out of string, then we found the GUID string.
+ // Now look for { 0x....... }
+ //
+ if (*Cptr) {
+ Cptr = CSavePtr;
+ *CSavePtr = CSave;
+ Cptr += SkipWhiteSpace (Cptr);
+ if (*Cptr == '{') {
+ *Cptr = 0;
+ Cptr++;
+ //
+ // 0x665E3FF6, 0x46CC, 0x11d4, 0x9A, 0x38, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D }
+ // If you have one suffixed with "L", then it doesn't work. So hack off 'L' characters
+ // in the string.
+ //
+ for (TempCptr = Cptr; *TempCptr; TempCptr++) {
+ if (*TempCptr == 'L') {
+ if (*(TempCptr + 1) == ',') {
+ *TempCptr = ',';
+ *(TempCptr + 1) = ' ';
+ }
+ }
+ }
+
+ if (sscanf (
+ Cptr,
+ "%X, %X, %X, %X, %X, %X, %X, %X, %X, %X, %X",
+ &GuidScan[0],
+ &GuidScan[1],
+ &GuidScan[2],
+ &GuidScan[3],
+ &GuidScan[4],
+ &GuidScan[5],
+ &GuidScan[6],
+ &GuidScan[7],
+ &GuidScan[8],
+ &GuidScan[9],
+ &GuidScan[10]
+ ) == 11) {
+ AddGuid11 (FileName, GuidScan, SymName);
+ }
+ }
+ }
+ }
+ }
+ }
+ //
+ // Else look for "static EFI_GUID xxxGUIDxxx = { 0x.... };
+ //
+ } else if ((CSavePtr = strstr (Line, "EFI_GUID")) != NULL) {
+ //
+ // Read the next line if line continuation
+ //
+ LineLen = strlen (Line);
+ if ((Line[LineLen - 1] == '\n') && (Line[LineLen - 2] == '\\')) {
+ fgets (Line + LineLen - 2, sizeof (Line) - LineLen, Fptr);
+ } else if (Line[LineLen - 1] == '\\') {
+ fgets (Line + LineLen - 1, sizeof (Line) - LineLen, Fptr);
+ }
+
+ Cptr = CSavePtr + 8;
+ Cptr += SkipWhiteSpace (Cptr);
+ //
+ // Should be variable name next
+ //
+ Len = ValidSymbolName (Cptr);
+ SymName = Cptr;
+ Cptr += Len;
+ Cptr += SkipWhiteSpace (Cptr);
+ if (*Cptr == '=') {
+ Cptr++;
+ Cptr += SkipWhiteSpace (Cptr);
+ //
+ // Should be open-brace next to define guid
+ //
+ if (*Cptr == '{') {
+ Cptr++;
+ //
+ // 0x665E3FF6, 0x46CC, 0x11d4, 0x9A, 0x38, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D }
+ //
+ if (sscanf (
+ Cptr,
+ "%X, %X, %X, %X, %X, %X, %X, %X, %X, %X, %X",
+ &GuidScan[0],
+ &GuidScan[1],
+ &GuidScan[2],
+ &GuidScan[3],
+ &GuidScan[4],
+ &GuidScan[5],
+ &GuidScan[6],
+ &GuidScan[7],
+ &GuidScan[8],
+ &GuidScan[9],
+ &GuidScan[10]
+ ) == 11) {
+ AddGuid11 (FileName, GuidScan, Cptr);
+ //
+ // printf ("Found guid: %s", Cptr);
+ //
+ }
+ }
+ }
+ }
+ }
+
+ fclose (Fptr);
+ return STATUS_SUCCESS;
+}
+//
+// Process Intel Itanium(TM) GUID definitions. Look for:
+// #define Cs870MemoryTestPEIMGuidL 0x9C2403386E1C8FAA
+// #define Cs870MemoryTestPEIMGuidH 0xE89E95C6180342f0
+// in either order.
+// This function assumes no blank lines between definitions.
+//
+static
+STATUS
+ProcessIA64FileGuids (
+ INT8 *FileName
+ )
+{
+ FILE *Fptr;
+ INT8 Line[MAX_LINE_LEN];
+ UINT32 Guid1H;
+ UINT32 Guid1L;
+ UINT32 Guid2H;
+ UINT32 Guid2L;
+ INT8 SymName1[MAX_LINE_LEN];
+ INT8 SymName2[MAX_LINE_LEN];
+ BOOLEAN Done;
+ BOOLEAN LowFirst;
+ BOOLEAN FoundLow;
+
+ if ((Fptr = fopen (FileName, "r")) == NULL) {
+ Error (NULL, 0, 0, FileName, "could not open input file for reading");
+ return STATUS_ERROR;
+ }
+
+ Done = FALSE;
+ if (fgets (Line, sizeof (Line), Fptr) == NULL) {
+ Done = 1;
+ }
+ //
+ // Read lines from the file until done. Since the guid definition takes
+ // two lines, we read lines in different places to recover gracefully
+ // from mismatches. For example, if you thought you found the first half,
+ // but the next line had a symbol mismatch, then you have to process the
+ // line again in case it's the start of a new definition.
+ //
+ while (!Done) {
+ //
+ // Check current line for GUID definition. Assume low define first.
+ //
+ if (IsIA64GuidLine (Line, &Guid1H, &Guid1L, &FoundLow, SymName1)) {
+ //
+ // Might have to swap guids later. Save off if we found the LOW first
+ //
+ if (FoundLow) {
+ LowFirst = TRUE;
+ } else {
+ LowFirst = FALSE;
+ }
+ //
+ // Read the next line and try for the rest of the guid definition
+ //
+ if (fgets (Line, sizeof (Line), Fptr) == NULL) {
+ Done = 1;
+ } else {
+ if (IsIA64GuidLine (Line, &Guid2H, &Guid2L, &FoundLow, SymName2)) {
+ //
+ // Found another. If the symbol names match, then save it off.
+ //
+ if (strcmp (SymName1, SymName2) == 0) {
+ //
+ // Yea, found one. Save it off.
+ //
+ if (LowFirst) {
+ AddGuid64x2 (FileName, Guid2H, Guid2L, Guid1H, Guid1L);
+ } else {
+ AddGuid64x2 (FileName, Guid1H, Guid1L, Guid2H, Guid2L);
+ }
+ //
+ // Read the next line for processing
+ //
+ if (fgets (Line, sizeof (Line), Fptr) == NULL) {
+ Done = 1;
+ }
+ } else {
+ //
+ // Don't get another line so that we reprocess this line in case it
+ // contains the start of a new definition.
+ // fprintf (stdout, "Symbol name mismatch: %s: %s != %s\n",
+ // FileName, SymName1, SymName2);
+ //
+ }
+ } else {
+ //
+ // Second line was not a guid definition. Get the next line from the
+ // file.
+ //
+ if (fgets (Line, sizeof (Line), Fptr) == NULL) {
+ Done = 1;
+ }
+ }
+ }
+ } else {
+ //
+ // Not a guid define line. Next.
+ //
+ if (fgets (Line, sizeof (Line), Fptr) == NULL) {
+ Done = 1;
+ }
+ }
+ }
+
+ fclose (Fptr);
+ return STATUS_SUCCESS;
+}
+//
+// Given a line from an Itanium-based assembly file, check the line for a guid
+// defininition. One of either:
+// #define Cs870MemoryTestPEIMGuidL 0x9C2403386E1C8FAA
+// #define Cs870MemoryTestPEIMGuidH 0xE89E95C6180342f0
+// Return the defined value as two 32-bit values, and whether it's a high
+// or low guid.
+//
+static
+BOOLEAN
+IsIA64GuidLine (
+ INT8 *Line,
+ UINT32 *GuidHigh,
+ UINT32 *GuidLow,
+ BOOLEAN *FoundLow,
+ INT8 *SymName
+ )
+{
+ INT8 *Cptr;
+ INT8 CSave;
+ INT8 *CSavePtr;
+ INT8 *SymStart;
+ UINT32 Len;
+
+ Cptr = Line;
+ Cptr += SkipWhiteSpace (Cptr);
+ //
+ // look for #define xxxGUID[L|H] 0xHexValue
+ //
+ if (*Cptr == '#') {
+ Cptr++;
+ Cptr += SkipWhiteSpace (Cptr);
+ //
+ // Look for "define"
+ //
+ if (!strncmp (Cptr, "define", 6)) {
+ Cptr += 6;
+ //
+ // Better be whitespace
+ //
+ Len = SkipWhiteSpace (Cptr);
+ if (Len) {
+ Cptr += Len;
+ //
+ // See if it's a valid symbol name
+ //
+ Len = ValidSymbolName (Cptr);
+ if (Len) {
+ //
+ // Save the start so we can copy it to their string if later checks are ok
+ //
+ SymStart = Cptr;
+ //
+ // It is a valid symbol name, look for the string GuidL or GuidH
+ //
+ CSavePtr = Cptr + Len;
+ CSave = *CSavePtr;
+ *CSavePtr = 0;
+ while (*Cptr) {
+ if (strncmp (Cptr, "GuidL", 5) == 0) {
+ *FoundLow = 1;
+ break;
+ } else if (strncmp (Cptr, "GuidH", 5) == 0) {
+ *FoundLow = 0;
+ break;
+ }
+
+ Cptr++;
+ }
+ //
+ // If we didn't run out of string, then we found the GUID string.
+ // Restore the null character we inserted above and continue.
+ // Now look for 0x.......
+ //
+ if (*Cptr) {
+ //
+ // Return symbol name less the "L" or "H"
+ //
+ strcpy (SymName, SymStart);
+ SymName[strlen (SymName) - 1] = 0;
+ Cptr = CSavePtr;
+ *CSavePtr = CSave;
+ Cptr += SkipWhiteSpace (Cptr);
+ if ((*Cptr == '0') && (*(Cptr + 1) == 'x')) {
+ //
+ // skip over "0x"
+ //
+ Cptr += 2;
+ //
+ // 0x0123456789ABCDEF -- null terminate after 8 characters,
+ // scan, replace the character and scan at that point.
+ //
+ CSave = *(Cptr + 8);
+ *(Cptr + 8) = 0;
+ if (sscanf (Cptr, "%X", GuidHigh) == 1) {
+ *(Cptr + 8) = CSave;
+ if (sscanf (Cptr + 8, "%X", GuidLow) == 1) {
+ return TRUE;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return FALSE;
+}
+//
+// Look at the characters in the string and determine if it's a valid
+// symbol name. Basically [a-zA-Z_][a-zA-Z_0-9]*
+//
+static
+UINT32
+ValidSymbolName (
+ INT8 *Name
+ )
+{
+ int Len;
+
+ Len = 0;
+
+ //
+ // Test first character
+ //
+ if (((*Name >= 'a') && (*Name <= 'z')) || ((*Name >= 'A') && (*Name <= 'Z')) || (*Name == '_')) {
+ Name++;
+ Len = 1;
+ while (*Name) {
+ if (((*Name >= 'a') && (*Name <= 'z')) ||
+ ((*Name >= 'A') && (*Name <= 'Z')) ||
+ ((*Name >= '0') && (*Name <= '9')) ||
+ (*Name == '_')
+ ) {
+ Name++;
+ Len++;
+ } else {
+ break;
+ }
+ }
+ }
+
+ return Len;
+}
+
+static
+UINT32
+SkipWhiteSpace (
+ INT8 *Str
+ )
+{
+ UINT32 Len;
+ Len = 0;
+ while (isspace (*Str) && *Str) {
+ Len++;
+ Str++;
+ }
+
+ return Len;
+}
+//
+// found FFS_FILEGUID=35b898ca-b6a9-49ce-8c72-904735cc49b7
+//
+static
+STATUS
+AddPkgGuid (
+ INT8 *FileName,
+ UINT32 *Data,
+ UINT64 *Data64
+ )
+{
+ GUID_RECORD *NewRec;
+ int Index;
+
+ //
+ // Sanity check the data
+ //
+ if ((Data[1] | Data[2] | Data[3]) & 0xFFFF0000) {
+ Error (NULL, 0, 0, "out of range value for GUID data word(s) [1] - [3]", NULL);
+ return STATUS_ERROR;
+ }
+ //
+ // More checks for Data64?
+ // Allocate memory for a new one guid structure
+ //
+ NewRec = malloc (sizeof (GUID_RECORD));
+ if (NewRec == NULL) {
+ Error (NULL, 0, 0, "memory allocation failure", NULL);
+ return STATUS_ERROR;
+ }
+
+ memset ((char *) NewRec, 0, sizeof (GUID_RECORD));
+ NewRec->FileName = malloc (strlen (FileName) + 1);
+ if (NewRec->FileName == NULL) {
+ free (NewRec);
+ Error (NULL, 0, 0, "memory allocation failure", NULL);
+ return STATUS_ERROR;
+ }
+
+ strcpy (NewRec->FileName, FileName);
+ NewRec->Guid.Data1 = Data[0];
+ NewRec->Guid.Data2 = (UINT16) Data[1];
+ NewRec->Guid.Data3 = (UINT16) Data[2];
+ NewRec->Guid.Data4[0] = (UINT8) Data[3];
+ NewRec->Guid.Data4[1] = (UINT8) (Data[3] >> 8);
+ for (Index = 2; Index < 8; Index++) {
+ NewRec->Guid.Data4[Index] = (UINT8) *Data64;
+ *Data64 >>= 8;
+ }
+ //
+ // Add it to the list
+ //
+ NewRec->Next = gGuidList;
+ gGuidList = NewRec;
+
+ //
+ // Report it
+ // ReportGuid (FileName, NewRec);
+ //
+ return STATUS_SUCCESS;
+}
+//
+// Add a guid consisting of 11 fields to our list of guids
+//
+static
+STATUS
+AddGuid11 (
+ INT8 *FileName,
+ UINT32 *Data,
+ INT8 *SymName
+ )
+{
+ GUID_RECORD *NewRec;
+ int Index;
+
+ //
+ // Sanity check the data
+ //
+ if (!CheckGuidData (Data, 11)) {
+ return STATUS_ERROR;
+ }
+ //
+ // Allocate memory for a new one guid structure
+ //
+ NewRec = malloc (sizeof (GUID_RECORD));
+ if (NewRec == NULL) {
+ Error (NULL, 0, 0, "memory allocation failure", NULL);
+ return STATUS_ERROR;
+ }
+
+ memset ((char *) NewRec, 0, sizeof (GUID_RECORD));
+ NewRec->FileName = malloc (strlen (FileName) + 1);
+ if (NewRec->FileName == NULL) {
+ free (NewRec);
+ Error (NULL, 0, 0, "memory allocation failure", NULL);
+ return STATUS_ERROR;
+ }
+
+ strcpy (NewRec->FileName, FileName);
+ if (SymName != NULL) {
+ NewRec->SymName = malloc (strlen (SymName) + 1);
+ if (NewRec->SymName == NULL) {
+ free (NewRec);
+ Error (NULL, 0, 0, "memory allocation failure", NULL);
+ return STATUS_ERROR;
+ }
+ }
+
+ strcpy (NewRec->SymName, SymName);
+
+ NewRec->Guid.Data1 = Data[0];
+ NewRec->Guid.Data2 = (UINT16) Data[1];
+ NewRec->Guid.Data3 = (UINT16) Data[2];
+ for (Index = 0; Index < 8; Index++) {
+ NewRec->Guid.Data4[Index] = (UINT8) Data[3 + Index];
+ }
+ //
+ // Add it to the list
+ //
+ NewRec->Next = gGuidList;
+ gGuidList = NewRec;
+
+ //
+ // Report it
+ // ReportGuid (FileName, NewRec);
+ //
+ return STATUS_SUCCESS;
+}
+//
+// For debug purposes, print each guid found
+//
+// static
+// VOID
+// ReportGuid (
+// INT8 *FileName,
+// GUID_RECORD *NewGuid
+// )
+// {
+// //fprintf (stdout, "%s: 0x%08X\n", FileName, NewGuid->Guid.Data1);
+// }
+//
+// Free up memory we allocated to keep track of guids defined.
+//
+static
+VOID
+FreeGuids (
+ VOID
+ )
+{
+ GUID_RECORD *NextRec;
+ while (gGuidList != NULL) {
+ NextRec = gGuidList->Next;
+ if (gGuidList->FileName != NULL) {
+ free (gGuidList->FileName);
+ }
+
+ if (gGuidList->SymName != NULL) {
+ free (gGuidList->SymName);
+ }
+
+ free (gGuidList);
+ gGuidList = NextRec;
+ }
+}
+
+static
+VOID
+FreeSigs (
+ VOID
+ )
+{
+ SIGNATURE_RECORD *NextRec;
+ while (gSignatureList != NULL) {
+ NextRec = gSignatureList->Next;
+ if (gSignatureList->FileName != NULL) {
+ free (gSignatureList->FileName);
+ }
+
+ free (gSignatureList);
+ gSignatureList = NextRec;
+ }
+}
+//
+// Scan through all guids defined and compare each for duplicates.
+//
+static
+STATUS
+CheckDuplicates (
+ VOID
+ )
+{
+ GUID_RECORD *CurrentFile;
+
+ GUID_RECORD *TempFile;
+ SIGNATURE_RECORD *CurrentSig;
+ SIGNATURE_RECORD *TempSig;
+ STATUS Status;
+ int Index;
+ int DupCount;
+ int Len;
+ BOOLEAN Same;
+ UINT32 GuidSum;
+ INT8 *SymName;
+
+ Status = STATUS_SUCCESS;
+
+ //
+ // If we're checking guids.....
+ //
+ if (gOptions.CheckGuids) {
+ //
+ // If -p option, print all guids found
+ //
+ if (gOptions.PrintFound) {
+ CurrentFile = gGuidList;
+ while (CurrentFile != NULL) {
+ fprintf (
+ stdout,
+ "GUID: 0x%08X 0x%04X 0x%04X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X %s\n",
+ (UINT32) CurrentFile->Guid.Data1,
+ (UINT32) CurrentFile->Guid.Data2,
+ (UINT32) CurrentFile->Guid.Data3,
+ (UINT32) CurrentFile->Guid.Data4[0],
+ (UINT32) CurrentFile->Guid.Data4[1],
+ (UINT32) CurrentFile->Guid.Data4[2],
+ (UINT32) CurrentFile->Guid.Data4[3],
+ (UINT32) CurrentFile->Guid.Data4[4],
+ (UINT32) CurrentFile->Guid.Data4[5],
+ (UINT32) CurrentFile->Guid.Data4[6],
+ (UINT32) CurrentFile->Guid.Data4[7],
+ CurrentFile->FileName
+ );
+ CurrentFile = CurrentFile->Next;
+ }
+ }
+
+ if (gOptions.GuidXReference) {
+ CurrentFile = gGuidList;
+ while (CurrentFile != NULL) {
+ //
+ // If no symbol name, print "unknown"
+ //
+ SymName = CurrentFile->SymName;
+ if (SymName == NULL) {
+ SymName = "unknown";
+ }
+
+ fprintf (
+ stdout,
+ "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X %s\n",
+ (UINT32) CurrentFile->Guid.Data1,
+ (UINT32) CurrentFile->Guid.Data2,
+ (UINT32) CurrentFile->Guid.Data3,
+ (UINT32) CurrentFile->Guid.Data4[0],
+ (UINT32) CurrentFile->Guid.Data4[1],
+ (UINT32) CurrentFile->Guid.Data4[2],
+ (UINT32) CurrentFile->Guid.Data4[3],
+ (UINT32) CurrentFile->Guid.Data4[4],
+ (UINT32) CurrentFile->Guid.Data4[5],
+ (UINT32) CurrentFile->Guid.Data4[6],
+ (UINT32) CurrentFile->Guid.Data4[7],
+ SymName
+ );
+ CurrentFile = CurrentFile->Next;
+ }
+ }
+ //
+ // Now go through all guids and report duplicates.
+ //
+ CurrentFile = gGuidList;
+ while (CurrentFile != NULL) {
+ DupCount = 0;
+ TempFile = CurrentFile->Next;
+ while (TempFile) {
+ //
+ // Compare the guids
+ //
+ if ((CurrentFile->Guid.Data1 == TempFile->Guid.Data1) &&
+ (CurrentFile->Guid.Data2 == TempFile->Guid.Data2) &&
+ (CurrentFile->Guid.Data3 == TempFile->Guid.Data3)
+ ) {
+ //
+ // OR in all the guid bytes so we can ignore NULL-guid definitions.
+ //
+ GuidSum = CurrentFile->Guid.Data1 | CurrentFile->Guid.Data2 | CurrentFile->Guid.Data3;
+ Same = TRUE;
+ for (Index = 0; Index < 8; Index++) {
+ GuidSum |= CurrentFile->Guid.Data4[Index];
+ if (CurrentFile->Guid.Data4[Index] != TempFile->Guid.Data4[Index]) {
+ Same = FALSE;
+ break;
+ }
+ }
+ //
+ // If they're the same, and the guid was non-zero, print a message.
+ //
+ if (Same && GuidSum) {
+ if (DupCount == 0) {
+ Error (NULL, 0, 0, "duplicate GUIDS found", NULL);
+ fprintf (stdout, " FILE1: %s\n", CurrentFile->FileName);
+ }
+
+ DupCount++;
+ fprintf (stdout, " FILE%d: %s\n", DupCount + 1, TempFile->FileName);
+ //
+ // Flag it as reported so we don't report it again if there's three or more
+ //
+ TempFile->Reported = TRUE;
+ }
+ }
+ //
+ // Next one
+ //
+ TempFile = TempFile->Next;
+ }
+ //
+ // Print the guid if we found duplicates
+ //
+ if (DupCount) {
+ fprintf (
+ stdout,
+ " GUID: 0x%08X 0x%04X 0x%04X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X\n",
+ (UINT32) CurrentFile->Guid.Data1,
+ (UINT32) CurrentFile->Guid.Data2,
+ (UINT32) CurrentFile->Guid.Data3,
+ (UINT32) CurrentFile->Guid.Data4[0],
+ (UINT32) CurrentFile->Guid.Data4[1],
+ (UINT32) CurrentFile->Guid.Data4[2],
+ (UINT32) CurrentFile->Guid.Data4[3],
+ (UINT32) CurrentFile->Guid.Data4[4],
+ (UINT32) CurrentFile->Guid.Data4[5],
+ (UINT32) CurrentFile->Guid.Data4[6],
+ (UINT32) CurrentFile->Guid.Data4[7]
+ );
+ //
+ // return STATUS_ERROR;
+ //
+ }
+ //
+ // Find the next one that hasn't been reported
+ //
+ do {
+ CurrentFile = CurrentFile->Next;
+ } while ((CurrentFile != NULL) && (CurrentFile->Reported));
+ }
+ }
+
+ if (gOptions.CheckSignatures) {
+ //
+ // Print ones found if specified
+ //
+ if (gOptions.PrintFound) {
+ CurrentSig = gSignatureList;
+ while (CurrentSig != NULL) {
+ Len = CurrentSig->Signature.DataLen;
+ for (Index = 0; Index < Len; Index++) {
+ fprintf (stdout, "%c", CurrentSig->Signature.Data[Index]);
+ }
+
+ fprintf (stdout, " %s\n", CurrentSig->FileName);
+ CurrentSig = CurrentSig->Next;
+ }
+ }
+
+ CurrentSig = gSignatureList;
+ while (CurrentSig != NULL) {
+ DupCount = 0;
+ TempSig = CurrentSig->Next;
+ Len = CurrentSig->Signature.DataLen;
+ while (TempSig) {
+ //
+ // Check for same length, then do string compare
+ //
+ if (Len == TempSig->Signature.DataLen) {
+ if (strncmp (CurrentSig->Signature.Data, TempSig->Signature.Data, Len) == 0) {
+ //
+ // Print header message if first failure for this sig
+ //
+ if (DupCount == 0) {
+ Error (NULL, 0, 0, "duplicate signatures found", NULL);
+ fprintf (stdout, " FILE1: %s\n", CurrentSig->FileName);
+ }
+
+ DupCount++;
+ fprintf (stdout, " FILE%d: %s\n", DupCount + 1, TempSig->FileName);
+ TempSig->Reported = TRUE;
+ }
+ }
+
+ TempSig = TempSig->Next;
+ }
+
+ if (DupCount) {
+ fprintf (stdout, " SIG: ");
+ for (Index = 0; Index < Len; Index++) {
+ fprintf (stdout, "%c", CurrentSig->Signature.Data[Index]);
+ }
+
+ fprintf (stdout, "\n");
+ }
+ //
+ // On to the next one that hasn't been reported
+ //
+ do {
+ CurrentSig = CurrentSig->Next;
+ } while ((CurrentSig != NULL) && (CurrentSig->Reported));
+ }
+ }
+
+ return Status;
+}
+
+static
+VOID
+FreeOptions (
+ VOID
+ )
+/*++
+
+Routine Description:
+ Free up any memory we allocated when processing command-line options.
+
+Arguments:
+ None.
+
+Returns:
+ NA
+
+Notes:
+ We don't free up the ->Str fields because we did not allocate them.
+ Instead, we just set the pointer to point to the actual parameter
+ from the command line.
+
+--*/
+{
+ STRING_LIST *Ptr;
+ while (gOptions.ExcludeDirs != NULL) {
+ Ptr = gOptions.ExcludeDirs->Next;
+ //
+ // free (gOptions.ExcludeDirs->Str);
+ //
+ free (gOptions.ExcludeDirs);
+ gOptions.ExcludeDirs = Ptr;
+ }
+
+ while (gOptions.ExcludeSubDirs != NULL) {
+ Ptr = gOptions.ExcludeSubDirs->Next;
+ //
+ // free (gOptions.ExcludeSubDirs->Str);
+ //
+ free (gOptions.ExcludeSubDirs);
+ gOptions.ExcludeSubDirs = Ptr;
+ }
+
+ while (gOptions.ExcludeExtensions != NULL) {
+ Ptr = gOptions.ExcludeExtensions->Next;
+ //
+ // free (gOptions.ExcludeExtensions->Str);
+ //
+ free (gOptions.ExcludeExtensions);
+ gOptions.ExcludeExtensions = Ptr;
+ }
+
+ while (gOptions.ExcludeFiles != NULL) {
+ Ptr = gOptions.ExcludeFiles->Next;
+ //
+ // free (gOptions.ExcludeFiles->Str);
+ //
+ free (gOptions.ExcludeFiles);
+ gOptions.ExcludeFiles = Ptr;
+ }
+}
+//
+// Given an array of 32-bit data, validate the data for the given number of
+// guid data. For example, it might have been scanned as 16 bytes of data, or
+// 11 fields of data.
+//
+static
+BOOLEAN
+CheckGuidData (
+ UINT32 *Data,
+ UINT32 DataCount
+ )
+{
+ UINT32 Index;
+
+ if (DataCount == 16) {
+ for (Index = 0; Index < 16; Index++) {
+ if (Data[Index] &~0xFF) {
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+ } else if (DataCount == 11) {
+ //
+ // Data[0] never out of range (32-bit)
+ //
+ if ((Data[1] | Data[2]) &~0xFFFF) {
+ //
+ // Error ("Out of range value for GUID data word(s) [1] and/or [2]");
+ //
+ return FALSE;
+ }
+
+ for (Index = 0; Index < 8; Index++) {
+ if (Data[Index + 3] &~0xFF) {
+ //
+ // Error ("Out of range value for GUID data byte(s) [4] - [11]");
+ //
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
diff --git a/Source/GuidChk/GuidList.c b/Source/GuidChk/GuidList.c
new file mode 100644
index 0000000..bb6a44d
--- /dev/null
+++ b/Source/GuidChk/GuidList.c
@@ -0,0 +1,186 @@
+/*++
+
+Copyright (c) 2004, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ GuidList.c
+
+Abstract:
+
+ Utility to create a GUID-to-name listing file that can
+ be used by other utilities. Basic operation is to take the
+ table of name+GUIDs that we have compiled into this utility,
+ and create a text file that can be parsed by other utilities
+ to do replacement of "name" with "GUID".
+
+Notes:
+ To add a new GUID to this database:
+ 1. Add a "#include EFI_GUID_DEFINITION(name)" statement below
+ 2. Modify the mGuidList[] array below to add the new GUID name
+
+ The only issue that may come up is that, if the source GUID file
+ is not in the standard GUID directory, then this utility won't
+ compile because the #include fails. In this case you'd need
+ to define a new macro (if it's in a standard place) or modify
+ this utility's makefile to add the path to your new .h file.
+
+--*/
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+
+#include <Common/UefiBaseTypes.h>
+#include <Guid/Apriori.h>
+#include <Guid/AcpiTableStorage.h>
+
+#include "EfiUtilityMsgs.h"
+
+
+#define GUID_XREF(varname, guid) { \
+ #varname, #guid, guid \
+ }
+
+#define NULL_GUID \
+ { \
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 \
+ }
+
+typedef struct {
+ INT8 *VariableName;
+ INT8 *DefineName;
+ EFI_GUID Guid;
+} GUID_LIST;
+
+//
+// This is our table of all GUIDs we want to print out to create
+// a GUID-to-name cross reference.
+// Use the #defined name from the GUID definition's source .h file.
+//
+static GUID_LIST mGuidList[] = {
+ GUID_XREF(gAprioriGuid, EFI_APRIORI_GUID),
+ GUID_XREF(gEfiAcpiTableStorageGuid, EFI_ACPI_TABLE_STORAGE_GUID),
+ // FIXME The next line was removed in the port to R9.
+ // GUID_XREF(gEfiDefaultBmpLogoGuid, EFI_DEFAULT_BMP_LOGO_GUID),
+ GUID_XREF(gEfiAcpiTableStorageGuid, EFI_ACPI_TABLE_STORAGE_GUID),
+ //
+ // Terminator
+ //
+ {
+ NULL,
+ NULL,
+ NULL_GUID
+ }
+};
+
+void
+PrintGuidText (
+ FILE *OutFptr,
+ INT8 *VariableName,
+ INT8 *DefineName,
+ EFI_GUID *Guid
+ );
+
+int
+CreateGuidList (
+ INT8 *OutFileName
+ )
+/*++
+
+Routine Description:
+ Print our GUID/name list to the specified output file.
+
+Arguments:
+ OutFileName - name of the output file to write our results to.
+
+Returns:
+ 0 if successful
+ nonzero otherwise
+
+--*/
+{
+ FILE *OutFptr;
+ int Index;
+
+ //
+ // Open output file for writing. If the name is NULL, then write to stdout
+ //
+ if (OutFileName != NULL) {
+ OutFptr = fopen (OutFileName, "w");
+ if (OutFptr == NULL) {
+ Error (NULL, 0, 0, OutFileName, "failed to open output file for writing");
+ return STATUS_ERROR;
+ }
+ } else {
+ OutFptr = stdout;
+ }
+
+ for (Index = 0; mGuidList[Index].VariableName != NULL; Index++) {
+ PrintGuidText (OutFptr, mGuidList[Index].VariableName, mGuidList[Index].DefineName, &mGuidList[Index].Guid);
+ }
+ //
+ // Close the output file if they specified one.
+ //
+ if (OutFileName != NULL) {
+ fclose (OutFptr);
+ }
+
+ return STATUS_SUCCESS;
+}
+
+void
+PrintGuidText (
+ FILE *OutFptr,
+ INT8 *VariableName,
+ INT8 *DefineName,
+ EFI_GUID *Guid
+ )
+/*++
+
+Routine Description:
+ Print a GUID/name combo in INF-style format
+
+ guid-guid-guid-guid DEFINE_NAME gName
+
+Arguments:
+ OutFptr - file pointer to which to write the output
+ VariableName - the GUID variable's name
+ DefineName - the name used in the #define
+ Guid - pointer to the GUID value
+
+Returns:
+ NA
+
+--*/
+{
+ if (OutFptr == NULL) {
+ OutFptr = stdout;
+ }
+
+ fprintf (
+ OutFptr,
+ "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X %s %s\n",
+ Guid->Data1,
+ Guid->Data2,
+ Guid->Data3,
+ Guid->Data4[0],
+ Guid->Data4[1],
+ Guid->Data4[2],
+ Guid->Data4[3],
+ Guid->Data4[4],
+ Guid->Data4[5],
+ Guid->Data4[6],
+ Guid->Data4[7],
+ DefineName,
+ VariableName
+ );
+}
diff --git a/Source/GuidChk/UtilsMsgs.c b/Source/GuidChk/UtilsMsgs.c
new file mode 100644
index 0000000..8aa343f
--- /dev/null
+++ b/Source/GuidChk/UtilsMsgs.c
@@ -0,0 +1,490 @@
+/*++
+
+Copyright (c) 2004, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ UtilsMsgs.c
+
+Abstract:
+
+ EFI tools utility functions to display warning, error, and informational
+ messages.
+
+--*/
+
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <stdarg.h>
+
+#include <Common/UefiBaseTypes.h>
+
+#include "EfiUtilityMsgs.h"
+
+#define MAX_LINE_LEN 200
+
+//
+// Declare module globals for keeping track of the the utility's
+// name and other settings.
+//
+static STATUS mStatus = STATUS_SUCCESS;
+static INT8 mUtilityName[50] = { 0 };
+static INT8 *mSourceFileName = NULL;
+static UINT32 mSourceFileLineNum = 0;
+static UINT32 mErrorCount = 0;
+static UINT32 mWarningCount = 0;
+static UINT32 mDebugMsgMask = 0;
+
+static
+void
+PrintMessage (
+ INT8 *Type,
+ INT8 *FileName,
+ UINT32 LineNumber,
+ UINT32 MessageCode,
+ INT8 *Text,
+ INT8 *MsgFmt,
+ va_list List
+ );
+
+void
+Error (
+ INT8 *FileName,
+ UINT32 LineNumber,
+ UINT32 MessageCode,
+ INT8 *Text,
+ INT8 *MsgFmt,
+ ...
+ )
+/*++
+
+Routine Description:
+ Prints an error message.
+
+Arguments:
+ All arguments are optional, though the printed message may be useless if
+ at least something valid is not specified.
+
+ FileName - name of the file or application. If not specified, then the
+ utilty name (as set by the utility calling SetUtilityName()
+ earlier) is used. Otherwise "Unknown utility" is used.
+
+ LineNumber - the line number of error, typically used by parsers. If the
+ utility is not a parser, then 0 should be specified. Otherwise
+ the FileName and LineNumber info can be used to cause
+ MS Visual Studio to jump to the error.
+
+ MessageCode - an application-specific error code that can be referenced in
+ other documentation.
+
+ Text - the text in question, typically used by parsers.
+
+ MsgFmt - the format string for the error message. Can contain formatting
+ controls for use with the varargs.
+
+Returns:
+ None.
+
+Notes:
+ We print the following (similar to the Warn() and Debug()
+ W
+ Typical error/warning message format:
+
+ bin\VfrCompile.cpp(330) : error C2660: 'AddVfrDataStructField' : function does not take 2 parameters
+
+ BUGBUG -- these three utility functions are almost identical, and
+ should be modified to share code.
+
+ Visual Studio does not find error messages with:
+
+ " error :"
+ " error 1:"
+ " error c1:"
+ " error 1000:"
+ " error c100:"
+
+ It does find:
+ " error c1000:"
+--*/
+{
+ va_list List;
+ mErrorCount++;
+ va_start (List, MsgFmt);
+ PrintMessage ("error", FileName, LineNumber, MessageCode, Text, MsgFmt, List);
+ va_end (List);
+ //
+ // Set status accordingly
+ //
+ if (mStatus < STATUS_ERROR) {
+ mStatus = STATUS_ERROR;
+ }
+}
+
+void
+ParserError (
+ UINT32 MessageCode,
+ INT8 *Text,
+ INT8 *MsgFmt,
+ ...
+ )
+/*++
+
+Routine Description:
+ Print a parser error, using the source file name and line number
+ set by a previous call to SetParserPosition().
+
+Arguments:
+ MessageCode - application-specific error code
+ Text - text to print in the error message
+ MsgFmt - format string to print at the end of the error message
+ ...
+
+Returns:
+ NA
+
+--*/
+{
+ va_list List;
+ mErrorCount++;
+ va_start (List, MsgFmt);
+ PrintMessage ("error", mSourceFileName, mSourceFileLineNum, MessageCode, Text, MsgFmt, List);
+ va_end (List);
+ //
+ // Set status accordingly
+ //
+ if (mStatus < STATUS_ERROR) {
+ mStatus = STATUS_ERROR;
+ }
+}
+
+void
+ParserWarning (
+ UINT32 ErrorCode,
+ INT8 *OffendingText,
+ INT8 *MsgFmt,
+ ...
+ )
+/*++
+
+Routine Description:
+ Print a parser warning, using the source file name and line number
+ set by a previous call to SetParserPosition().
+
+Arguments:
+ ErrorCode - application-specific error code
+ OffendingText - text to print in the warning message
+ MsgFmt - format string to print at the end of the warning message
+ ...
+
+Returns:
+ NA
+
+--*/
+{
+ va_list List;
+ mWarningCount++;
+ va_start (List, MsgFmt);
+ PrintMessage ("warning", mSourceFileName, mSourceFileLineNum, ErrorCode, OffendingText, MsgFmt, List);
+ va_end (List);
+ //
+ // Set status accordingly
+ //
+ if (mStatus < STATUS_WARNING) {
+ mStatus = STATUS_WARNING;
+ }
+}
+
+void
+Warning (
+ INT8 *FileName,
+ UINT32 LineNumber,
+ UINT32 MessageCode,
+ INT8 *Text,
+ INT8 *MsgFmt,
+ ...
+ )
+/*++
+
+Routine Description:
+ Print a warning message.
+
+Arguments:
+ FileName - name of the file where the warning was detected, or the name
+ of the application that detected the warning
+
+ LineNumber - the line number where the warning was detected (parsers).
+ 0 should be specified if the utility is not a parser.
+
+ MessageCode - an application-specific warning code that can be referenced in
+ other documentation.
+
+ Text - the text in question (parsers)
+
+ MsgFmt - the format string for the warning message. Can contain formatting
+ controls for use with varargs.
+
+ ...
+
+Returns:
+ None.
+
+--*/
+{
+ va_list List;
+ mWarningCount++;
+ va_start (List, MsgFmt);
+ PrintMessage ("warning", FileName, LineNumber, MessageCode, Text, MsgFmt, List);
+ va_end (List);
+ //
+ // Set status accordingly
+ //
+ if (mStatus < STATUS_WARNING) {
+ mStatus = STATUS_WARNING;
+ }
+}
+
+void
+DebugMsg (
+ INT8 *FileName,
+ UINT32 LineNumber,
+ UINT32 MsgMask,
+ INT8 *Text,
+ INT8 *MsgFmt,
+ ...
+ )
+/*++
+
+Routine Description:
+ Print a warning message.
+
+Arguments:
+ FileName - typically the name of the utility printing the debug message, but
+ can be the name of a file being parsed.
+
+ LineNumber - the line number in FileName (parsers)
+
+ MsgMask - an application-specific bitmask that, in combination with mDebugMsgMask,
+ determines if the debug message gets printed.
+
+ Text - the text in question (parsers)
+
+ MsgFmt - the format string for the debug message. Can contain formatting
+ controls for use with varargs.
+
+ ...
+Returns:
+ None.
+
+--*/
+{
+ va_list List;
+ //
+ // If the debug mask is not applicable, then do nothing.
+ //
+ if ((MsgMask != 0) && ((mDebugMsgMask & MsgMask) == 0)) {
+ return ;
+ }
+
+ va_start (List, MsgFmt);
+ PrintMessage ("debug", FileName, LineNumber, 0, Text, MsgFmt, List);
+ va_end (List);
+}
+
+static
+void
+PrintMessage (
+ INT8 *Type,
+ INT8 *FileName,
+ UINT32 LineNumber,
+ UINT32 MessageCode,
+ INT8 *Text,
+ INT8 *MsgFmt,
+ va_list List
+ )
+/*++
+
+Routine Description:
+ Worker routine for all the utility printing services. Prints the message in
+ a format that Visual Studio will find when scanning build outputs for
+ errors or warnings.
+
+Arguments:
+ Type - "warning" or "error" string to insert into the message to be
+ printed. The first character of this string (converted to uppercase)
+ is used to preceed the MessageCode value in the output string.
+
+ FileName - name of the file where the warning was detected, or the name
+ of the application that detected the warning
+
+ LineNumber - the line number where the warning was detected (parsers).
+ 0 should be specified if the utility is not a parser.
+
+ MessageCode - an application-specific warning code that can be referenced in
+ other documentation.
+
+ Text - part of the message to print
+
+ MsgFmt - the format string for the message. Can contain formatting
+ controls for use with varargs.
+
+ List - Variable function parameter list.
+Returns:
+ None.
+
+Notes:
+ If FileName == NULL then this utility will use the string passed into SetUtilityName().
+
+ LineNumber is only used if the caller is a parser, in which case FileName refers to the
+ file being parsed.
+
+ Text and MsgFmt are both optional, though it would be of little use calling this function with
+ them both NULL.
+
+ Output will typically be of the form:
+ <FileName>(<LineNumber>) : <Type> <Type[0]><MessageCode>: <Text> : <MsgFmt>
+
+ Parser (LineNumber != 0)
+ VfrCompile.cpp(330) : error E2660: AddVfrDataStructField : function does not take 2 parameters
+ Generic utility (LineNumber == 0)
+ UtilityName : error E1234 : Text string : MsgFmt string and args
+
+--*/
+{
+ INT8 Line[MAX_LINE_LEN];
+ INT8 Line2[MAX_LINE_LEN];
+ INT8 *Cptr;
+ //
+ // If given a filename, then add it (and the line number) to the string.
+ // If there's no filename, then use the program name if provided.
+ //
+ if (FileName != NULL) {
+ Cptr = FileName;
+ } else if (mUtilityName[0] != 0) {
+ Cptr = mUtilityName;
+ } else {
+ Cptr = "Unknown utility";
+ }
+
+ strcpy (Line, Cptr);
+ if (LineNumber != 0) {
+ sprintf (Line2, "(%d)", LineNumber);
+ strcat (Line, Line2);
+ }
+ //
+ // Have to print an error code or Visual Studio won't find the
+ // message for you. It has to be decimal digits too.
+ //
+ sprintf (Line2, " : %s %c%04d", Type, toupper (Type[0]), MessageCode);
+ strcat (Line, Line2);
+ fprintf (stdout, "%s", Line);
+ //
+ // If offending text was provided, then print it
+ //
+ if (Text != NULL) {
+ fprintf (stdout, ": %s ", Text);
+ }
+ //
+ // Print formatted message if provided
+ //
+ if (MsgFmt != NULL) {
+ vsprintf (Line2, MsgFmt, List);
+ fprintf (stdout, ": %s", Line2);
+ }
+
+ fprintf (stdout, "\n");
+}
+
+void
+ParserSetPosition (
+ INT8 *SourceFileName,
+ UINT32 LineNum
+ )
+/*++
+
+Routine Description:
+ Set the position in a file being parsed. This can be used to
+ print error messages deeper down in a parser.
+
+Arguments:
+ SourceFileName - name of the source file being parsed
+ LineNum - line number of the source file being parsed
+
+Returns:
+ NA
+
+--*/
+{
+ mSourceFileName = SourceFileName;
+ mSourceFileLineNum = LineNum;
+}
+
+void
+SetUtilityName (
+ INT8 *UtilityName
+ )
+/*++
+
+Routine Description:
+ All printed error/warning/debug messages follow the same format, and
+ typically will print a filename or utility name followed by the error
+ text. However if a filename is not passed to the print routines, then
+ they'll print the utility name if you call this function early in your
+ app to set the utility name.
+
+Arguments:
+ UtilityName - name of the utility, which will be printed with all
+ error/warning/debug messags.
+
+Returns:
+ NA
+
+--*/
+{
+ //
+ // Save the name of the utility in our local variable. Make sure its
+ // length does not exceed our buffer.
+ //
+ if (UtilityName != NULL) {
+ if (strlen (UtilityName) >= sizeof (mUtilityName)) {
+ Error (UtilityName, 0, 0, "application error", "utility name length exceeds internal buffer size");
+ strncpy (mUtilityName, UtilityName, sizeof (mUtilityName) - 1);
+ mUtilityName[sizeof (mUtilityName) - 1] = 0;
+ return ;
+ } else {
+ strcpy (mUtilityName, UtilityName);
+ }
+ } else {
+ Error (NULL, 0, 0, "application error", "SetUtilityName() called with NULL utility name");
+ }
+}
+
+STATUS
+GetUtilityStatus (
+ VOID
+ )
+/*++
+
+Routine Description:
+ When you call Error() or Warning(), this module keeps track of it and
+ sets a local mStatus to STATUS_ERROR or STATUS_WARNING. When the utility
+ exits, it can call this function to get the status and use it as a return
+ value.
+
+Arguments:
+ None.
+
+Returns:
+ Worst-case status reported, as defined by which print function was called.
+
+--*/
+{
+ return mStatus;
+}
diff --git a/Source/GuidChk/UtilsMsgs.h b/Source/GuidChk/UtilsMsgs.h
new file mode 100644
index 0000000..5f6c701
--- /dev/null
+++ b/Source/GuidChk/UtilsMsgs.h
@@ -0,0 +1,106 @@
+/*++
+
+Copyright (c) 2004, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ UtilsMsgs.h
+
+Abstract:
+
+ Prototypes for the EFI tools utility functions.
+
+--*/
+
+#ifndef _UTILS_MESSAGES_H_
+#define _UTILS_MESSAGES_H_
+
+STATUS
+GetUtilityStatus (
+ VOID
+ )
+;
+
+//
+// If someone prints an error message and didn't specify a source file name,
+// then we print the utility name instead. However they must tell us the
+// utility name early on via this function.
+//
+VOID
+SetUtilityName (
+ INT8 *ProgramName
+ )
+;
+
+void
+Error (
+ INT8 *FileName,
+ UINT32 LineNumber,
+ UINT32 ErrorCode,
+ INT8 *OffendingText,
+ INT8 *MsgFmt,
+ ...
+ )
+;
+
+void
+Warning (
+ INT8 *FileName,
+ UINT32 LineNumber,
+ UINT32 ErrorCode,
+ INT8 *OffendingText,
+ INT8 *MsgFmt,
+ ...
+ )
+;
+
+void
+DebugMsg (
+ INT8 *FileName,
+ UINT32 LineNumber,
+ UINT32 MsgLevel,
+ INT8 *OffendingText,
+ INT8 *MsgFmt,
+ ...
+ )
+;
+
+void
+SetDebugMsgMask (
+ UINT32 MsgMask
+ )
+;
+
+void
+ParserSetPosition (
+ INT8 *SourceFileName,
+ UINT32 LineNum
+ )
+;
+
+void
+ParserError (
+ UINT32 ErrorCode,
+ INT8 *OffendingText,
+ INT8 *MsgFmt,
+ ...
+ )
+;
+
+void
+ParserWarning (
+ UINT32 ErrorCode,
+ INT8 *OffendingText,
+ INT8 *MsgFmt,
+ ...
+ )
+;
+
+#endif
diff --git a/Source/GuidChk/build.xml b/Source/GuidChk/build.xml
new file mode 100644
index 0000000..80f8ef0
--- /dev/null
+++ b/Source/GuidChk/build.xml
@@ -0,0 +1,83 @@
+<?xml version="1.0" ?>
+<!--
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+-->
+<project default="GenTool" basedir=".">
+<!--
+ EDK GuidChk Tool
+ Copyright (c) 2006, Intel Corporation
+-->
+ <property name="ToolName" value="GuidChk"/>
+ <property name="FileSet" value="*.c *.h"/>
+
+ <taskdef resource="net/sf/antcontrib/antlib.xml"/>
+
+ <property name="LINK_OUTPUT_TYPE" value="static"/>
+ <property name="BUILD_DIR" value="${PACKAGE_DIR}/${ToolName}/tmp"/>
+
+ <target name="GenTool" depends="init, Tool">
+ <if>
+ <isfalse value="${gcc}"/>
+ <then>
+ <echo message="The EDK Tool: ${ToolName} build has completed!"/>
+ </then>
+ </if>
+ </target>
+
+ <target name="init">
+ <if>
+ <istrue value="${gcc}"/>
+ <then>
+ <echo message="The EDK Tool: ${ToolName} is not built for GCC!"/>
+ </then>
+ <else>
+ <echo message="Building the EDK Tool: ${ToolName}"/>
+ <mkdir dir="${BUILD_DIR}"/>
+ </else>
+ </if>
+ </target>
+
+ <target name="Tool" depends="init" unless="gcc">
+ <cc name="${ToolChain}" objdir="${BUILD_DIR}"
+ outfile="${BIN_DIR}/${ToolName}"
+ outtype="executable"
+ debug="true"
+ optimize="speed">
+
+ <fileset dir="${basedir}/${ToolName}"
+ includes="${FileSet}"
+ defaultexcludes="TRUE"
+ excludes="*.xml *.inf"/>
+
+ <includepath path="${PACKAGE_DIR}/Include"/>
+ <includepath path="${PACKAGE_DIR}/Include/Ia32"/>
+ <includepath path="${PACKAGE_DIR}/Common"/>
+ <libset dir="${LIB_DIR}" libs="CommonTools"/>
+
+ </cc>
+ </target>
+
+ <target name="clean">
+ <echo message="Removing Intermediate Files Only"/>
+ <delete failonerror="false" quiet="true" includeEmptyDirs="true">
+ <fileset dir="${BUILD_DIR}"/>
+ </delete>
+ </target>
+
+ <target name="cleanall">
+ <echo message="Removing Object Files and the Executable: ${ToolName}${ext_exe}"/>
+ <delete failonerror="false" quiet="true" includeEmptyDirs="true">
+ <fileset dir="${BUILD_DIR}"/>
+ <fileset file="${BIN_DIR}/${ToolName}${ext_exe}"/>
+ <fileset file="${BIN_DIR}/${ToolName}.pdb"/>
+ </delete>
+ </target>
+
+</project>
diff --git a/Source/Include/Common/BaseTypes.h b/Source/Include/Common/BaseTypes.h
new file mode 100644
index 0000000..b87e714
--- /dev/null
+++ b/Source/Include/Common/BaseTypes.h
@@ -0,0 +1,212 @@
+/** @file
+ Processor or Compiler specific defines for all supported processors.
+
+ This file is stand alone self consistent set of definitions.
+
+ Copyright (c) 2006, Intel Corporation
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+ Module Name: BaseTypes.h
+
+**/
+
+#ifndef __BASE_TYPES_H__
+#define __BASE_TYPES_H__
+
+//
+// Include processor specific binding
+//
+#include <ProcessorBind.h>
+#include <stdarg.h>
+
+#define MEMORY_FENCE() MemoryFence ()
+#define BREAKPOINT() CpuBreakpoint ()
+#define DEADLOOP() CpuDeadLoop ()
+
+typedef struct {
+ UINT32 Data1;
+ UINT16 Data2;
+ UINT16 Data3;
+ UINT8 Data4[8];
+} GUID;
+
+
+//
+// Modifiers to absract standard types to aid in debug of problems
+//
+#define CONST const
+#define STATIC static
+#define VOID void
+
+//
+// Modifiers for Data Types used to self document code.
+// This concept is borrowed for UEFI specification.
+//
+#ifndef IN
+//
+// Some other envirnments use this construct, so #ifndef to prevent
+// mulitple definition.
+//
+#define IN
+#define OUT
+#define OPTIONAL
+#endif
+
+//
+// Constants. They may exist in other build structures, so #ifndef them.
+//
+#ifndef TRUE
+//
+// BugBug: UEFI specification claims 1 and 0. We are concerned about the
+// complier portability so we did it this way.
+//
+#define TRUE ((BOOLEAN)(1==1))
+#endif
+
+#ifndef FALSE
+#define FALSE ((BOOLEAN)(0==1))
+#endif
+
+#ifndef NULL
+#define NULL ((VOID *) 0)
+#endif
+
+//
+// Support for variable length argument lists using the ANSI standard.
+//
+// Since we are using the ANSI standard we used the standard nameing and
+// did not folow the coding convention
+//
+// VA_LIST - typedef for argument list.
+// VA_START (VA_LIST Marker, argument before the ...) - Init Marker for use.
+// VA_END (VA_LIST Marker) - Clear Marker
+// VA_ARG (VA_LIST Marker, var arg size) - Use Marker to get an argumnet from
+// the ... list. You must know the size and pass it in this macro.
+//
+// example:
+//
+// UINTN
+// ExampleVarArg (
+// IN UINTN NumberOfArgs,
+// ...
+// )
+// {
+// VA_LIST Marker;
+// UINTN Index;
+// UINTN Result;
+//
+// //
+// // Initialize the Marker
+// //
+// VA_START (Marker, NumberOfArgs);
+// for (Index = 0, Result = 0; Index < NumberOfArgs; Index++) {
+// //
+// // The ... list is a series of UINTN values, so average them up.
+// //
+// Result += VA_ARG (Marker, UINTN);
+// }
+//
+// VA_END (Marker);
+// return Result
+// }
+//
+
+#define _INT_SIZE_OF(n) ((sizeof (n) + sizeof (UINTN) - 1) &~(sizeof (UINTN) - 1))
+
+//
+// Also support coding convention rules for var arg macros
+//
+#ifndef VA_START
+
+// typedef CHAR8 *VA_LIST;
+// #define VA_START(ap, v) (ap = (VA_LIST) & (v) + _INT_SIZE_OF (v))
+// #define VA_ARG(ap, t) (*(t *) ((ap += _INT_SIZE_OF (t)) - _INT_SIZE_OF (t)))
+// #define VA_END(ap) (ap = (VA_LIST) 0)
+// Use the native arguments for tools.
+#define VA_START va_start
+#define VA_ARG va_arg
+#define VA_END va_end
+#define VA_LIST va_list
+
+#endif
+
+///
+/// CONTAINING_RECORD - returns a pointer to the structure
+/// from one of it's elements.
+///
+#define _CR(Record, TYPE, Field) ((TYPE *) ((CHAR8 *) (Record) - (CHAR8 *) &(((TYPE *) 0)->Field)))
+
+///
+/// ALIGN_POINTER - aligns a pointer to the lowest boundry
+///
+#define ALIGN_POINTER(p, s) ((VOID *) ((p) + (((s) - ((UINTN) (p))) & ((s) - 1))))
+
+///
+/// ALIGN_VARIABLE - aligns a variable up to the next natural boundry for int size of a processor
+///
+#define ALIGN_VARIABLE(Value, Adjustment) \
+ Adjustment = 0U; \
+ if ((UINTN) (Value) % sizeof (UINTN)) { \
+ (Adjustment) = (UINTN)(sizeof (UINTN) - ((UINTN) (Value) % sizeof (UINTN))); \
+ } \
+ (Value) = (UINTN)((UINTN) (Value) + (UINTN) (Adjustment))
+
+//
+// EFI Error Codes common to all execution phases
+//
+
+typedef INTN RETURN_STATUS;
+
+///
+/// Set the upper bit to indicate EFI Error.
+///
+#define ENCODE_ERROR(a) (MAX_BIT | (a))
+
+#define ENCODE_WARNING(a) (a)
+#define RETURN_ERROR(a) ((a) < 0)
+
+#define RETURN_SUCCESS 0
+#define RETURN_LOAD_ERROR ENCODE_ERROR (1)
+#define RETURN_INVALID_PARAMETER ENCODE_ERROR (2)
+#define RETURN_UNSUPPORTED ENCODE_ERROR (3)
+#define RETURN_BAD_BUFFER_SIZE ENCODE_ERROR (4)
+#define RETURN_BUFFER_TOO_SMALL ENCODE_ERROR (5)
+#define RETURN_NOT_READY ENCODE_ERROR (6)
+#define RETURN_DEVICE_ERROR ENCODE_ERROR (7)
+#define RETURN_WRITE_PROTECTED ENCODE_ERROR (8)
+#define RETURN_OUT_OF_RESOURCES ENCODE_ERROR (9)
+#define RETURN_VOLUME_CORRUPTED ENCODE_ERROR (10)
+#define RETURN_VOLUME_FULL ENCODE_ERROR (11)
+#define RETURN_NO_MEDIA ENCODE_ERROR (12)
+#define RETURN_MEDIA_CHANGED ENCODE_ERROR (13)
+#define RETURN_NOT_FOUND ENCODE_ERROR (14)
+#define RETURN_ACCESS_DENIED ENCODE_ERROR (15)
+#define RETURN_NO_RESPONSE ENCODE_ERROR (16)
+#define RETURN_NO_MAPPING ENCODE_ERROR (17)
+#define RETURN_TIMEOUT ENCODE_ERROR (18)
+#define RETURN_NOT_STARTED ENCODE_ERROR (19)
+#define RETURN_ALREADY_STARTED ENCODE_ERROR (20)
+#define RETURN_ABORTED ENCODE_ERROR (21)
+#define RETURN_ICMP_ERROR ENCODE_ERROR (22)
+#define RETURN_TFTP_ERROR ENCODE_ERROR (23)
+#define RETURN_PROTOCOL_ERROR ENCODE_ERROR (24)
+#define RETURN_INCOMPATIBLE_VERSION ENCODE_ERROR (25)
+#define RETURN_SECURITY_VIOLATION ENCODE_ERROR (26)
+#define RETURN_CRC_ERROR ENCODE_ERROR (27)
+#define RETURN_END_OF_MEDIA ENCODE_ERROR (28)
+#define RETURN_END_OF_FILE ENCODE_ERROR (31)
+
+#define RETURN_WARN_UNKNOWN_GLYPH ENCODE_WARNING (1)
+#define RETURN_WARN_DELETE_FAILURE ENCODE_WARNING (2)
+#define RETURN_WARN_WRITE_FAILURE ENCODE_WARNING (3)
+#define RETURN_WARN_BUFFER_TOO_SMALL ENCODE_WARNING (4)
+
+typedef UINT64 PHYSICAL_ADDRESS;
+
+#endif
diff --git a/Source/Include/Common/Capsule.h b/Source/Include/Common/Capsule.h
new file mode 100644
index 0000000..0434fdf
--- /dev/null
+++ b/Source/Include/Common/Capsule.h
@@ -0,0 +1,67 @@
+/** @file
+ Defines for the EFI Capsule functionality.
+
+ Copyright (c) 2006, Intel Corporation
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+ Module Name: Capsule.h
+
+ @par Revision Reference:
+ These definitions are from Capsule Spec Version 0.9.
+
+**/
+
+#ifndef _EFI_CAPSULE_H_
+#define _EFI_CAPSULE_H_
+
+//
+// Bits in the flags field of the capsule header
+//
+#define EFI_CAPSULE_HEADER_FLAG_SETUP 0x00000001 // supports setup changes
+
+
+#define CAPSULE_BLOCK_DESCRIPTOR_SIGNATURE EFI_SIGNATURE_32 ('C', 'B', 'D', 'S')
+
+//
+// An array of these describe the blocks that make up a capsule for
+// a capsule update.
+//
+typedef struct {
+ UINT64 Length; // length of the data block
+ EFI_PHYSICAL_ADDRESS Data; // physical address of the data block
+ UINT32 Signature; // CBDS
+ UINT32 CheckSum; // to sum this structure to 0
+} EFI_CAPSULE_BLOCK_DESCRIPTOR;
+
+typedef struct {
+ EFI_GUID OemGuid;
+ UINT32 HeaderSize;
+ //
+ // UINT8 OemHdrData[];
+ //
+} EFI_CAPSULE_OEM_HEADER;
+
+typedef struct {
+ EFI_GUID CapsuleGuid;
+ UINT32 HeaderSize;
+ UINT32 Flags;
+ UINT32 CapsuleImageSize;
+ UINT32 SequenceNumber;
+ EFI_GUID InstanceId;
+ UINT32 OffsetToSplitInformation;
+ UINT32 OffsetToCapsuleBody;
+ UINT32 OffsetToOemDefinedHeader;
+ UINT32 OffsetToAuthorInformation;
+ UINT32 OffsetToRevisionInformation;
+ UINT32 OffsetToShortDescription;
+ UINT32 OffsetToLongDescription;
+ UINT32 OffsetToApplicableDevices;
+} EFI_CAPSULE_HEADER;
+
+#endif // #ifndef _EFI_CAPSULE_H_
diff --git a/Source/Include/Common/Dependency.h b/Source/Include/Common/Dependency.h
new file mode 100644
index 0000000..744027d
--- /dev/null
+++ b/Source/Include/Common/Dependency.h
@@ -0,0 +1,50 @@
+/** @file
+ This module contains data specific to dependency expressions
+ and local function prototypes.
+
+ Copyright (c) 2006, Intel Corporation
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+ Module Name: Dependency.h
+
+**/
+
+#ifndef __DEPENDENCY_H__
+#define __DEPENDENCY_H__
+
+/// EFI_DEP_BEFORE - If present, this must be the first and only opcode
+#define EFI_DEP_BEFORE 0x00
+
+/// EFI_DEP_AFTER - If present, this must be the first and only opcode
+#define EFI_DEP_AFTER 0x01
+
+#define EFI_DEP_PUSH 0x02
+#define EFI_DEP_AND 0x03
+#define EFI_DEP_OR 0x04
+#define EFI_DEP_NOT 0x05
+#define EFI_DEP_TRUE 0x06
+#define EFI_DEP_FALSE 0x07
+#define EFI_DEP_END 0x08
+
+/// EFI_DEP_SOR - If present, this must be the first opcode
+#define EFI_DEP_SOR 0x09
+
+///
+/// EFI_DEP_REPLACE_TRUE - Used to dynamically patch the dependecy expression
+/// to save time. A EFI_DEP_PUSH is evauated one an
+/// replaced with EFI_DEP_REPLACE_TRUE
+///
+#define EFI_DEP_REPLACE_TRUE 0xff
+
+///
+/// Define the initial size of the dependency expression evaluation stack
+///
+#define DEPEX_STACK_SIZE_INCREMENT 0x1000
+
+#endif
diff --git a/Source/Include/Common/EfiImage.h b/Source/Include/Common/EfiImage.h
new file mode 100644
index 0000000..2f5c580
--- /dev/null
+++ b/Source/Include/Common/EfiImage.h
@@ -0,0 +1,716 @@
+/** @file
+ EFI image format for PE32+. Please note some data structures are different
+ for IA-32 and Itanium-based images, look for UINTN and the #ifdef EFI_IA64
+
+ @bug Fix text - doc as defined in MSFT EFI specification.
+
+ Copyright (c) 2006, Intel Corporation
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+ Module Name: EfiImage.h
+
+**/
+
+#ifndef __EFI_IMAGE_H__
+#define __EFI_IMAGE_H__
+
+//
+// PE32+ Subsystem type for EFI images
+//
+#define EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION 10
+#define EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER 11
+#define EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER 12
+#define EFI_IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER 13
+
+//
+// BugBug: Need to get a real answer for this problem. This is not in the
+// PE specification.
+//
+// A SAL runtime driver does not get fixed up when a transition to
+// virtual mode is made. In all other cases it should be treated
+// like a EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER image
+//
+#define EFI_IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER 13
+
+//
+// PE32+ Machine type for EFI images
+//
+#define IMAGE_FILE_MACHINE_I386 0x014c
+#define IMAGE_FILE_MACHINE_IA64 0x0200
+#define IMAGE_FILE_MACHINE_EBC 0x0EBC
+#define IMAGE_FILE_MACHINE_X64 0x8664
+//
+// Support old names for backward compatible
+//
+#define EFI_IMAGE_MACHINE_IA32 IMAGE_FILE_MACHINE_I386
+#define EFI_IMAGE_MACHINE_IA64 IMAGE_FILE_MACHINE_IA64
+#define EFI_IMAGE_MACHINE_IPF IMAGE_FILE_MACHINE_IA64
+#define EFI_IMAGE_MACHINE_EBC IMAGE_FILE_MACHINE_EBC
+#define EFI_IMAGE_MACHINE_X64 IMAGE_FILE_MACHINE_X64
+
+#define EFI_IMAGE_DOS_SIGNATURE 0x5A4D // MZ
+#define EFI_IMAGE_OS2_SIGNATURE 0x454E // NE
+#define EFI_IMAGE_OS2_SIGNATURE_LE 0x454C // LE
+#define EFI_IMAGE_NT_SIGNATURE 0x00004550 // PE00
+#define EFI_IMAGE_EDOS_SIGNATURE 0x44454550 // PEED
+
+///
+/// PE images can start with an optional DOS header, so if an image is run
+/// under DOS it can print an error message.
+///
+typedef struct {
+ UINT16 e_magic; // Magic number
+ UINT16 e_cblp; // Bytes on last page of file
+ UINT16 e_cp; // Pages in file
+ UINT16 e_crlc; // Relocations
+ UINT16 e_cparhdr; // Size of header in paragraphs
+ UINT16 e_minalloc; // Minimum extra paragraphs needed
+ UINT16 e_maxalloc; // Maximum extra paragraphs needed
+ UINT16 e_ss; // Initial (relative) SS value
+ UINT16 e_sp; // Initial SP value
+ UINT16 e_csum; // Checksum
+ UINT16 e_ip; // Initial IP value
+ UINT16 e_cs; // Initial (relative) CS value
+ UINT16 e_lfarlc; // File address of relocation table
+ UINT16 e_ovno; // Overlay number
+ UINT16 e_res[4]; // Reserved words
+ UINT16 e_oemid; // OEM identifier (for e_oeminfo)
+ UINT16 e_oeminfo; // OEM information; e_oemid specific
+ UINT16 e_res2[10]; // Reserved words
+ UINT32 e_lfanew; // File address of new exe header
+} EFI_IMAGE_DOS_HEADER;
+
+///
+/// File header format.
+///
+typedef struct {
+ UINT16 Machine;
+ UINT16 NumberOfSections;
+ UINT32 TimeDateStamp;
+ UINT32 PointerToSymbolTable;
+ UINT32 NumberOfSymbols;
+ UINT16 SizeOfOptionalHeader;
+ UINT16 Characteristics;
+} EFI_IMAGE_FILE_HEADER;
+
+#define EFI_IMAGE_SIZEOF_FILE_HEADER 20
+
+#define EFI_IMAGE_FILE_RELOCS_STRIPPED 0x0001 // Relocation info stripped from file.
+#define EFI_IMAGE_FILE_EXECUTABLE_IMAGE 0x0002 // File is executable (i.e. no unresolved externel references).
+#define EFI_IMAGE_FILE_LINE_NUMS_STRIPPED 0x0004 // Line nunbers stripped from file.
+#define EFI_IMAGE_FILE_LOCAL_SYMS_STRIPPED 0x0008 // Local symbols stripped from file.
+#define EFI_IMAGE_FILE_BYTES_REVERSED_LO 0x0080 // Bytes of machine word are reversed.
+#define EFI_IMAGE_FILE_32BIT_MACHINE 0x0100 // 32 bit word machine.
+#define EFI_IMAGE_FILE_DEBUG_STRIPPED 0x0200 // Debugging info stripped from file in .DBG file
+#define EFI_IMAGE_FILE_SYSTEM 0x1000 // System File.
+#define EFI_IMAGE_FILE_DLL 0x2000 // File is a DLL.
+#define EFI_IMAGE_FILE_BYTES_REVERSED_HI 0x8000 // Bytes of machine word are reversed.
+#define EFI_IMAGE_FILE_MACHINE_UNKNOWN 0
+#define EFI_IMAGE_FILE_MACHINE_I386 0x14c // Intel 386.
+#define EFI_IMAGE_FILE_MACHINE_R3000 0x162 // MIPS* little-endian, 0540 big-endian
+#define EFI_IMAGE_FILE_MACHINE_R4000 0x166 // MIPS* little-endian
+#define EFI_IMAGE_FILE_MACHINE_ALPHA 0x184 // Alpha_AXP*
+#define EFI_IMAGE_FILE_MACHINE_POWERPC 0x1F0 // IBM* PowerPC Little-Endian
+#define EFI_IMAGE_FILE_MACHINE_TAHOE 0x7cc // Intel EM machine
+//
+// * Other names and brands may be claimed as the property of others.
+//
+
+///
+/// Directory format.
+///
+typedef struct {
+ UINT32 VirtualAddress;
+ UINT32 Size;
+} EFI_IMAGE_DATA_DIRECTORY;
+
+#define EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES 16
+
+typedef struct {
+ UINT16 Magic;
+ UINT8 MajorLinkerVersion;
+ UINT8 MinorLinkerVersion;
+ UINT32 SizeOfCode;
+ UINT32 SizeOfInitializedData;
+ UINT32 SizeOfUninitializedData;
+ UINT32 AddressOfEntryPoint;
+ UINT32 BaseOfCode;
+ UINT32 BaseOfData;
+ UINT32 BaseOfBss;
+ UINT32 GprMask;
+ UINT32 CprMask[4];
+ UINT32 GpValue;
+} EFI_IMAGE_ROM_OPTIONAL_HEADER;
+
+#define EFI_IMAGE_ROM_OPTIONAL_HDR_MAGIC 0x107
+#define EFI_IMAGE_SIZEOF_ROM_OPTIONAL_HEADER sizeof (EFI_IMAGE_ROM_OPTIONAL_HEADER)
+
+typedef struct {
+ EFI_IMAGE_FILE_HEADER FileHeader;
+ EFI_IMAGE_ROM_OPTIONAL_HEADER OptionalHeader;
+} EFI_IMAGE_ROM_HEADERS;
+
+///
+/// @attention
+/// EFI_IMAGE_OPTIONAL_HEADER32 and EFI_IMAGE_OPTIONAL_HEADER64
+/// are for use ONLY by tools. All proper EFI code MUST use
+/// EFI_IMAGE_OPTIONAL_HEADER ONLY!!!
+///
+#define EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC 0x10b
+
+typedef struct {
+ //
+ // Standard fields.
+ //
+ UINT16 Magic;
+ UINT8 MajorLinkerVersion;
+ UINT8 MinorLinkerVersion;
+ UINT32 SizeOfCode;
+ UINT32 SizeOfInitializedData;
+ UINT32 SizeOfUninitializedData;
+ UINT32 AddressOfEntryPoint;
+ UINT32 BaseOfCode;
+ UINT32 BaseOfData;
+ //
+ // NT additional fields.
+ //
+ UINT32 ImageBase;
+ UINT32 SectionAlignment;
+ UINT32 FileAlignment;
+ UINT16 MajorOperatingSystemVersion;
+ UINT16 MinorOperatingSystemVersion;
+ UINT16 MajorImageVersion;
+ UINT16 MinorImageVersion;
+ UINT16 MajorSubsystemVersion;
+ UINT16 MinorSubsystemVersion;
+ UINT32 Win32VersionValue;
+ UINT32 SizeOfImage;
+ UINT32 SizeOfHeaders;
+ UINT32 CheckSum;
+ UINT16 Subsystem;
+ UINT16 DllCharacteristics;
+ UINT32 SizeOfStackReserve;
+ UINT32 SizeOfStackCommit;
+ UINT32 SizeOfHeapReserve;
+ UINT32 SizeOfHeapCommit;
+ UINT32 LoaderFlags;
+ UINT32 NumberOfRvaAndSizes;
+ EFI_IMAGE_DATA_DIRECTORY DataDirectory[EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES];
+} EFI_IMAGE_OPTIONAL_HEADER32;
+
+///
+/// @attention
+/// EFI_IMAGE_OPTIONAL_HEADER32 and EFI_IMAGE_OPTIONAL_HEADER64
+/// are for use ONLY by tools. All proper EFI code MUST use
+/// EFI_IMAGE_OPTIONAL_HEADER ONLY!!!
+///
+#define EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC 0x20b
+
+typedef struct {
+ //
+ // Standard fields.
+ //
+ UINT16 Magic;
+ UINT8 MajorLinkerVersion;
+ UINT8 MinorLinkerVersion;
+ UINT32 SizeOfCode;
+ UINT32 SizeOfInitializedData;
+ UINT32 SizeOfUninitializedData;
+ UINT32 AddressOfEntryPoint;
+ UINT32 BaseOfCode;
+ //
+ // NT additional fields.
+ //
+ UINT64 ImageBase;
+ UINT32 SectionAlignment;
+ UINT32 FileAlignment;
+ UINT16 MajorOperatingSystemVersion;
+ UINT16 MinorOperatingSystemVersion;
+ UINT16 MajorImageVersion;
+ UINT16 MinorImageVersion;
+ UINT16 MajorSubsystemVersion;
+ UINT16 MinorSubsystemVersion;
+ UINT32 Win32VersionValue;
+ UINT32 SizeOfImage;
+ UINT32 SizeOfHeaders;
+ UINT32 CheckSum;
+ UINT16 Subsystem;
+ UINT16 DllCharacteristics;
+ UINT64 SizeOfStackReserve;
+ UINT64 SizeOfStackCommit;
+ UINT64 SizeOfHeapReserve;
+ UINT64 SizeOfHeapCommit;
+ UINT32 LoaderFlags;
+ UINT32 NumberOfRvaAndSizes;
+ EFI_IMAGE_DATA_DIRECTORY DataDirectory[EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES];
+} EFI_IMAGE_OPTIONAL_HEADER64;
+
+///
+/// @attention
+/// EFI_IMAGE_NT_HEADERS32 and EFI_IMAGE_HEADERS64 are for use ONLY
+/// by tools. All proper EFI code MUST use EFI_IMAGE_NT_HEADERS ONLY!!!
+///
+typedef struct {
+ UINT32 Signature;
+ EFI_IMAGE_FILE_HEADER FileHeader;
+ EFI_IMAGE_OPTIONAL_HEADER32 OptionalHeader;
+} EFI_IMAGE_NT_HEADERS32;
+
+#define EFI_IMAGE_SIZEOF_NT_OPTIONAL32_HEADER sizeof (EFI_IMAGE_NT_HEADERS32)
+
+typedef struct {
+ UINT32 Signature;
+ EFI_IMAGE_FILE_HEADER FileHeader;
+ EFI_IMAGE_OPTIONAL_HEADER64 OptionalHeader;
+} EFI_IMAGE_NT_HEADERS64;
+
+#define EFI_IMAGE_SIZEOF_NT_OPTIONAL64_HEADER sizeof (EFI_IMAGE_NT_HEADERS64)
+
+//
+// Processor specific definition of EFI_IMAGE_OPTIONAL_HEADER so the
+// type name EFI_IMAGE_OPTIONAL_HEADER is appropriate to the build. Same for
+// EFI_IMAGE_NT_HEADERS. These definitions MUST be used by ALL EFI code.
+//
+#if defined (MDE_CPU_IA32)
+
+typedef EFI_IMAGE_OPTIONAL_HEADER32 EFI_IMAGE_OPTIONAL_HEADER;
+typedef EFI_IMAGE_NT_HEADERS32 EFI_IMAGE_NT_HEADERS;
+
+#define EFI_IMAGE_NT_OPTIONAL_HDR_MAGIC EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
+#define EFI_IMAGE_MACHINE_TYPE_SUPPORTED(Machine) \
+ (((Machine) == EFI_IMAGE_MACHINE_IA32) || ((Machine) == EFI_IMAGE_MACHINE_EBC))
+
+#elif defined (MDE_CPU_IPF)
+
+typedef EFI_IMAGE_OPTIONAL_HEADER64 EFI_IMAGE_OPTIONAL_HEADER;
+typedef EFI_IMAGE_NT_HEADERS64 EFI_IMAGE_NT_HEADERS;
+
+#define EFI_IMAGE_NT_OPTIONAL_HDR_MAGIC EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
+#define EFI_IMAGE_MACHINE_TYPE_SUPPORTED(Machine) \
+ (((Machine) == EFI_IMAGE_MACHINE_IPF) || ((Machine) == EFI_IMAGE_MACHINE_EBC))
+
+#elif defined (MDE_CPU_X64)
+
+typedef EFI_IMAGE_OPTIONAL_HEADER64 EFI_IMAGE_OPTIONAL_HEADER;
+typedef EFI_IMAGE_NT_HEADERS64 EFI_IMAGE_NT_HEADERS;
+
+#define EFI_IMAGE_NT_OPTIONAL_HDR_MAGIC EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
+#define EFI_IMAGE_MACHINE_TYPE_SUPPORTED(Machine) \
+ (((Machine) == EFI_IMAGE_MACHINE_X64) || ((Machine) == EFI_IMAGE_MACHINE_EBC))
+
+#elif defined (MDE_CPU_EBC)
+
+//
+// This is just to make sure you can cross compile with the EBC compiiler.
+// It does not make sense to have a PE loader coded in EBC. You need to
+// understand the basic
+//
+typedef EFI_IMAGE_OPTIONAL_HEADER64 EFI_IMAGE_OPTIONAL_HEADER;
+typedef EFI_IMAGE_NT_HEADERS64 EFI_IMAGE_NT_HEADERS;
+
+#define EFI_IMAGE_NT_OPTIONAL_HDR_MAGIC EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
+#define EFI_IMAGE_MACHINE_TYPE_SUPPORTED(Machine) ((Machine) == EFI_IMAGE_MACHINE_EBC)
+
+#else
+#error Unknown Processor Type
+#endif
+
+
+#define EFI_IMAGE_FIRST_SECTION(ntheader) \
+ ( \
+ (EFI_IMAGE_SECTION_HEADER *) \
+ ( \
+ (UINT32) ntheader + \
+ FIELD_OFFSET (EFI_IMAGE_NT_HEADERS, OptionalHeader) + \
+ ((EFI_IMAGE_NT_HEADERS *) (ntheader))->FileHeader.SizeOfOptionalHeader \
+ ) \
+ )
+
+//
+// Subsystem Values
+//
+#define EFI_IMAGE_SUBSYSTEM_UNKNOWN 0
+#define EFI_IMAGE_SUBSYSTEM_NATIVE 1
+#define EFI_IMAGE_SUBSYSTEM_WINDOWS_GUI 2
+#define EFI_IMAGE_SUBSYSTEM_WINDOWS_CUI 3.
+#define EFI_IMAGE_SUBSYSTEM_OS2_CUI 5
+#define EFI_IMAGE_SUBSYSTEM_POSIX_CUI 7
+
+//
+// Directory Entries
+//
+#define EFI_IMAGE_DIRECTORY_ENTRY_EXPORT 0
+#define EFI_IMAGE_DIRECTORY_ENTRY_IMPORT 1
+#define EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE 2
+#define EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION 3
+#define EFI_IMAGE_DIRECTORY_ENTRY_SECURITY 4
+#define EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC 5
+#define EFI_IMAGE_DIRECTORY_ENTRY_DEBUG 6
+#define EFI_IMAGE_DIRECTORY_ENTRY_COPYRIGHT 7
+#define EFI_IMAGE_DIRECTORY_ENTRY_GLOBALPTR 8
+#define EFI_IMAGE_DIRECTORY_ENTRY_TLS 9
+#define EFI_IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG 10
+
+//
+// Section header format.
+//
+#define EFI_IMAGE_SIZEOF_SHORT_NAME 8
+
+typedef struct {
+ UINT8 Name[EFI_IMAGE_SIZEOF_SHORT_NAME];
+ union {
+ UINT32 PhysicalAddress;
+ UINT32 VirtualSize;
+ } Misc;
+ UINT32 VirtualAddress;
+ UINT32 SizeOfRawData;
+ UINT32 PointerToRawData;
+ UINT32 PointerToRelocations;
+ UINT32 PointerToLinenumbers;
+ UINT16 NumberOfRelocations;
+ UINT16 NumberOfLinenumbers;
+ UINT32 Characteristics;
+} EFI_IMAGE_SECTION_HEADER;
+
+#define EFI_IMAGE_SIZEOF_SECTION_HEADER 40
+
+#define EFI_IMAGE_SCN_TYPE_NO_PAD 0x00000008 // Reserved.
+#define EFI_IMAGE_SCN_CNT_CODE 0x00000020
+#define EFI_IMAGE_SCN_CNT_INITIALIZED_DATA 0x00000040
+#define EFI_IMAGE_SCN_CNT_UNINITIALIZED_DATA 0x00000080
+
+#define EFI_IMAGE_SCN_LNK_OTHER 0x00000100 // Reserved.
+#define EFI_IMAGE_SCN_LNK_INFO 0x00000200 // Section contains comments or some other type of information.
+#define EFI_IMAGE_SCN_LNK_REMOVE 0x00000800 // Section contents will not become part of image.
+#define EFI_IMAGE_SCN_LNK_COMDAT 0x00001000
+
+#define EFI_IMAGE_SCN_ALIGN_1BYTES 0x00100000
+#define EFI_IMAGE_SCN_ALIGN_2BYTES 0x00200000
+#define EFI_IMAGE_SCN_ALIGN_4BYTES 0x00300000
+#define EFI_IMAGE_SCN_ALIGN_8BYTES 0x00400000
+#define EFI_IMAGE_SCN_ALIGN_16BYTES 0x00500000
+#define EFI_IMAGE_SCN_ALIGN_32BYTES 0x00600000
+#define EFI_IMAGE_SCN_ALIGN_64BYTES 0x00700000
+
+#define EFI_IMAGE_SCN_MEM_DISCARDABLE 0x02000000
+#define EFI_IMAGE_SCN_MEM_NOT_CACHED 0x04000000
+#define EFI_IMAGE_SCN_MEM_NOT_PAGED 0x08000000
+#define EFI_IMAGE_SCN_MEM_SHARED 0x10000000
+#define EFI_IMAGE_SCN_MEM_EXECUTE 0x20000000
+#define EFI_IMAGE_SCN_MEM_READ 0x40000000
+#define EFI_IMAGE_SCN_MEM_WRITE 0x80000000
+
+///
+/// Symbol format.
+///
+#define EFI_IMAGE_SIZEOF_SYMBOL 18
+
+//
+// Section values.
+//
+// Symbols have a section number of the section in which they are
+// defined. Otherwise, section numbers have the following meanings:
+//
+#define EFI_IMAGE_SYM_UNDEFINED (UINT16) 0 // Symbol is undefined or is common.
+#define EFI_IMAGE_SYM_ABSOLUTE (UINT16) -1 // Symbol is an absolute value.
+#define EFI_IMAGE_SYM_DEBUG (UINT16) -2 // Symbol is a special debug item.
+//
+// Type (fundamental) values.
+//
+#define EFI_IMAGE_SYM_TYPE_NULL 0 // no type.
+#define EFI_IMAGE_SYM_TYPE_VOID 1 //
+#define EFI_IMAGE_SYM_TYPE_CHAR 2 // type character.
+#define EFI_IMAGE_SYM_TYPE_SHORT 3 // type short integer.
+#define EFI_IMAGE_SYM_TYPE_INT 4
+#define EFI_IMAGE_SYM_TYPE_LONG 5
+#define EFI_IMAGE_SYM_TYPE_FLOAT 6
+#define EFI_IMAGE_SYM_TYPE_DOUBLE 7
+#define EFI_IMAGE_SYM_TYPE_STRUCT 8
+#define EFI_IMAGE_SYM_TYPE_UNION 9
+#define EFI_IMAGE_SYM_TYPE_ENUM 10 // enumeration.
+#define EFI_IMAGE_SYM_TYPE_MOE 11 // member of enumeration.
+#define EFI_IMAGE_SYM_TYPE_BYTE 12
+#define EFI_IMAGE_SYM_TYPE_WORD 13
+#define EFI_IMAGE_SYM_TYPE_UINT 14
+#define EFI_IMAGE_SYM_TYPE_DWORD 15
+
+//
+// Type (derived) values.
+//
+#define EFI_IMAGE_SYM_DTYPE_NULL 0 // no derived type.
+#define EFI_IMAGE_SYM_DTYPE_POINTER 1
+#define EFI_IMAGE_SYM_DTYPE_FUNCTION 2
+#define EFI_IMAGE_SYM_DTYPE_ARRAY 3
+
+//
+// Storage classes.
+//
+#define EFI_IMAGE_SYM_CLASS_END_OF_FUNCTION (UINT8) -1
+#define EFI_IMAGE_SYM_CLASS_NULL 0
+#define EFI_IMAGE_SYM_CLASS_AUTOMATIC 1
+#define EFI_IMAGE_SYM_CLASS_EXTERNAL 2
+#define EFI_IMAGE_SYM_CLASS_STATIC 3
+#define EFI_IMAGE_SYM_CLASS_REGISTER 4
+#define EFI_IMAGE_SYM_CLASS_EXTERNAL_DEF 5
+#define EFI_IMAGE_SYM_CLASS_LABEL 6
+#define EFI_IMAGE_SYM_CLASS_UNDEFINED_LABEL 7
+#define EFI_IMAGE_SYM_CLASS_MEMBER_OF_STRUCT 8
+#define EFI_IMAGE_SYM_CLASS_ARGUMENT 9
+#define EFI_IMAGE_SYM_CLASS_STRUCT_TAG 10
+#define EFI_IMAGE_SYM_CLASS_MEMBER_OF_UNION 11
+#define EFI_IMAGE_SYM_CLASS_UNION_TAG 12
+#define EFI_IMAGE_SYM_CLASS_TYPE_DEFINITION 13
+#define EFI_IMAGE_SYM_CLASS_UNDEFINED_STATIC 14
+#define EFI_IMAGE_SYM_CLASS_ENUM_TAG 15
+#define EFI_IMAGE_SYM_CLASS_MEMBER_OF_ENUM 16
+#define EFI_IMAGE_SYM_CLASS_REGISTER_PARAM 17
+#define EFI_IMAGE_SYM_CLASS_BIT_FIELD 18
+#define EFI_IMAGE_SYM_CLASS_BLOCK 100
+#define EFI_IMAGE_SYM_CLASS_FUNCTION 101
+#define EFI_IMAGE_SYM_CLASS_END_OF_STRUCT 102
+#define EFI_IMAGE_SYM_CLASS_FILE 103
+#define EFI_IMAGE_SYM_CLASS_SECTION 104
+#define EFI_IMAGE_SYM_CLASS_WEAK_EXTERNAL 105
+
+//
+// type packing constants
+//
+#define EFI_IMAGE_N_BTMASK 017
+#define EFI_IMAGE_N_TMASK 060
+#define EFI_IMAGE_N_TMASK1 0300
+#define EFI_IMAGE_N_TMASK2 0360
+#define EFI_IMAGE_N_BTSHFT 4
+#define EFI_IMAGE_N_TSHIFT 2
+
+//
+// Communal selection types.
+//
+#define EFI_IMAGE_COMDAT_SELECT_NODUPLICATES 1
+#define EFI_IMAGE_COMDAT_SELECT_ANY 2
+#define EFI_IMAGE_COMDAT_SELECT_SAME_SIZE 3
+#define EFI_IMAGE_COMDAT_SELECT_EXACT_MATCH 4
+#define EFI_IMAGE_COMDAT_SELECT_ASSOCIATIVE 5
+
+#define EFI_IMAGE_WEAK_EXTERN_SEARCH_NOLIBRARY 1
+#define EFI_IMAGE_WEAK_EXTERN_SEARCH_LIBRARY 2
+#define EFI_IMAGE_WEAK_EXTERN_SEARCH_ALIAS 3
+
+///
+/// Relocation format.
+///
+typedef struct {
+ UINT32 VirtualAddress;
+ UINT32 SymbolTableIndex;
+ UINT16 Type;
+} EFI_IMAGE_RELOCATION;
+
+#define EFI_IMAGE_SIZEOF_RELOCATION 10
+
+//
+// I386 relocation types.
+//
+#define EFI_IMAGE_REL_I386_ABSOLUTE 0 // Reference is absolute, no relocation is necessary
+#define EFI_IMAGE_REL_I386_DIR16 01 // Direct 16-bit reference to the symbols virtual address
+#define EFI_IMAGE_REL_I386_REL16 02 // PC-relative 16-bit reference to the symbols virtual address
+#define EFI_IMAGE_REL_I386_DIR32 06 // Direct 32-bit reference to the symbols virtual address
+#define EFI_IMAGE_REL_I386_DIR32NB 07 // Direct 32-bit reference to the symbols virtual address, base not included
+#define EFI_IMAGE_REL_I386_SEG12 011 // Direct 16-bit reference to the segment-selector bits of a 32-bit virtual address
+#define EFI_IMAGE_REL_I386_SECTION 012
+#define EFI_IMAGE_REL_I386_SECREL 013
+#define EFI_IMAGE_REL_I386_REL32 024 // PC-relative 32-bit reference to the symbols virtual address
+
+///
+/// Based relocation format.
+///
+typedef struct {
+ UINT32 VirtualAddress;
+ UINT32 SizeOfBlock;
+} EFI_IMAGE_BASE_RELOCATION;
+
+#define EFI_IMAGE_SIZEOF_BASE_RELOCATION 8
+
+//
+// Based relocation types.
+//
+#define EFI_IMAGE_REL_BASED_ABSOLUTE 0
+#define EFI_IMAGE_REL_BASED_HIGH 1
+#define EFI_IMAGE_REL_BASED_LOW 2
+#define EFI_IMAGE_REL_BASED_HIGHLOW 3
+#define EFI_IMAGE_REL_BASED_HIGHADJ 4
+#define EFI_IMAGE_REL_BASED_MIPS_JMPADDR 5
+#define EFI_IMAGE_REL_BASED_IA64_IMM64 9
+#define EFI_IMAGE_REL_BASED_DIR64 10
+
+///
+/// Line number format.
+///
+typedef struct {
+ union {
+ UINT32 SymbolTableIndex; // Symbol table index of function name if Linenumber is 0.
+ UINT32 VirtualAddress; // Virtual address of line number.
+ } Type;
+ UINT16 Linenumber; // Line number.
+} EFI_IMAGE_LINENUMBER;
+
+#define EFI_IMAGE_SIZEOF_LINENUMBER 6
+
+//
+// Archive format.
+//
+#define EFI_IMAGE_ARCHIVE_START_SIZE 8
+#define EFI_IMAGE_ARCHIVE_START "!<arch>\n"
+#define EFI_IMAGE_ARCHIVE_END "`\n"
+#define EFI_IMAGE_ARCHIVE_PAD "\n"
+#define EFI_IMAGE_ARCHIVE_LINKER_MEMBER "/ "
+#define EFI_IMAGE_ARCHIVE_LONGNAMES_MEMBER "// "
+
+typedef struct {
+ UINT8 Name[16]; // File member name - `/' terminated.
+ UINT8 Date[12]; // File member date - decimal.
+ UINT8 UserID[6]; // File member user id - decimal.
+ UINT8 GroupID[6]; // File member group id - decimal.
+ UINT8 Mode[8]; // File member mode - octal.
+ UINT8 Size[10]; // File member size - decimal.
+ UINT8 EndHeader[2]; // String to end header.
+} EFI_IMAGE_ARCHIVE_MEMBER_HEADER;
+
+#define EFI_IMAGE_SIZEOF_ARCHIVE_MEMBER_HDR 60
+
+//
+// DLL support.
+//
+
+///
+/// DLL Export Format
+///
+typedef struct {
+ UINT32 Characteristics;
+ UINT32 TimeDateStamp;
+ UINT16 MajorVersion;
+ UINT16 MinorVersion;
+ UINT32 Name;
+ UINT32 Base;
+ UINT32 NumberOfFunctions;
+ UINT32 NumberOfNames;
+ UINT32 AddressOfFunctions;
+ UINT32 AddressOfNames;
+ UINT32 AddressOfNameOrdinals;
+} EFI_IMAGE_EXPORT_DIRECTORY;
+
+///
+/// DLL support.
+/// Import Format
+///
+typedef struct {
+ UINT16 Hint;
+ UINT8 Name[1];
+} EFI_IMAGE_IMPORT_BY_NAME;
+
+typedef struct {
+ union {
+ UINT32 Function;
+ UINT32 Ordinal;
+ EFI_IMAGE_IMPORT_BY_NAME *AddressOfData;
+ } u1;
+} EFI_IMAGE_THUNK_DATA;
+
+#define EFI_IMAGE_ORDINAL_FLAG 0x80000000
+#define EFI_IMAGE_SNAP_BY_ORDINAL(Ordinal) ((Ordinal & EFI_IMAGE_ORDINAL_FLAG) != 0)
+#define EFI_IMAGE_ORDINAL(Ordinal) (Ordinal & 0xffff)
+
+typedef struct {
+ UINT32 Characteristics;
+ UINT32 TimeDateStamp;
+ UINT32 ForwarderChain;
+ UINT32 Name;
+ EFI_IMAGE_THUNK_DATA *FirstThunk;
+} EFI_IMAGE_IMPORT_DESCRIPTOR;
+
+///
+/// Debug Format
+///
+#define EFI_IMAGE_DEBUG_TYPE_CODEVIEW 2
+
+typedef struct {
+ UINT32 Characteristics;
+ UINT32 TimeDateStamp;
+ UINT16 MajorVersion;
+ UINT16 MinorVersion;
+ UINT32 Type;
+ UINT32 SizeOfData;
+ UINT32 RVA;
+ UINT32 FileOffset;
+} EFI_IMAGE_DEBUG_DIRECTORY_ENTRY;
+
+#define CODEVIEW_SIGNATURE_NB10 0x3031424E // "NB10"
+typedef struct {
+ UINT32 Signature; // "NB10"
+ UINT32 Unknown;
+ UINT32 Unknown2;
+ UINT32 Unknown3;
+ //
+ // Filename of .PDB goes here
+ //
+} EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY;
+
+#define CODEVIEW_SIGNATURE_RSDS 0x53445352 // "RSDS"
+typedef struct {
+ UINT32 Signature; // "RSDS"
+ UINT32 Unknown;
+ UINT32 Unknown2;
+ UINT32 Unknown3;
+ UINT32 Unknown4;
+ UINT32 Unknown5;
+ //
+ // Filename of .PDB goes here
+ //
+} EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY;
+
+//
+// .pdata entries for X64
+//
+typedef struct {
+ UINT32 FunctionStartAddress;
+ UINT32 FunctionEndAddress;
+ UINT32 UnwindInfoAddress;
+} RUNTIME_FUNCTION;
+
+typedef struct {
+ UINT8 Version:3;
+ UINT8 Flags:5;
+ UINT8 SizeOfProlog;
+ UINT8 CountOfUnwindCodes;
+ UINT8 FrameRegister:4;
+ UINT8 FrameRegisterOffset:4;
+} UNWIND_INFO;
+
+///
+/// Header format for TE images
+///
+typedef struct {
+ UINT16 Signature; // signature for TE format = "VZ"
+ UINT16 Machine; // from the original file header
+ UINT8 NumberOfSections; // from the original file header
+ UINT8 Subsystem; // from original optional header
+ UINT16 StrippedSize; // how many bytes we removed from the header
+ UINT32 AddressOfEntryPoint; // offset to entry point -- from original optional header
+ UINT32 BaseOfCode; // from original image -- required for ITP debug
+ UINT64 ImageBase; // from original file header
+ EFI_IMAGE_DATA_DIRECTORY DataDirectory[2]; // only base relocation and debug directory
+} EFI_TE_IMAGE_HEADER;
+
+#define EFI_TE_IMAGE_HEADER_SIGNATURE 0x5A56 // "VZ"
+
+//
+// Data directory indexes in our TE image header
+//
+#define EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC 0
+#define EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG 1
+
+#endif
diff --git a/Source/Include/Common/FirmwareFileSystem.h b/Source/Include/Common/FirmwareFileSystem.h
new file mode 100644
index 0000000..5678a95
--- /dev/null
+++ b/Source/Include/Common/FirmwareFileSystem.h
@@ -0,0 +1,98 @@
+/** @file
+ This file defines the data structures that comprise the FFS file system.
+
+ Copyright (c) 2006, Intel Corporation
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+ Module Name: FirmwareFileSystem.h
+
+ @par Revision Reference:
+ These definitions are from Firmware File System Spec 0.9.
+
+**/
+
+#ifndef __EFI_FFS_FILE_SYSTEM_H__
+#define __EFI_FFS_FILE_SYSTEM_H__
+
+///
+/// FFS specific file types
+///
+#define EFI_FV_FILETYPE_FFS_PAD 0xF0
+
+//
+// FFS File Attributes
+//
+#define FFS_ATTRIB_TAIL_PRESENT 0x01
+#define FFS_ATTRIB_RECOVERY 0x02
+#define FFS_ATTRIB_HEADER_EXTENSION 0x04
+#define FFS_ATTRIB_DATA_ALIGNMENT 0x38
+#define FFS_ATTRIB_CHECKSUM 0x40
+
+///
+/// FFS_FIXED_CHECKSUM is the default checksum value used when the
+/// FFS_ATTRIB_CHECKSUM attribute bit is clear
+/// note this is NOT an architecturally defined value, but is in this file for
+/// implementation convenience
+///
+#define FFS_FIXED_CHECKSUM 0x5A
+
+//
+// File state definitions
+//
+#define EFI_FILE_HEADER_CONSTRUCTION 0x01
+#define EFI_FILE_HEADER_VALID 0x02
+#define EFI_FILE_DATA_VALID 0x04
+#define EFI_FILE_MARKED_FOR_UPDATE 0x08
+#define EFI_FILE_DELETED 0x10
+#define EFI_FILE_HEADER_INVALID 0x20
+
+#define EFI_FILE_ALL_STATE_BITS (EFI_FILE_HEADER_CONSTRUCTION | \
+ EFI_FILE_HEADER_VALID | \
+ EFI_FILE_DATA_VALID | \
+ EFI_FILE_MARKED_FOR_UPDATE | \
+ EFI_FILE_DELETED | \
+ EFI_FILE_HEADER_INVALID \
+ )
+
+#define EFI_TEST_FFS_ATTRIBUTES_BIT(FvbAttributes, TestAttributes, Bit) \
+ ( \
+ (BOOLEAN) ( \
+ (FvbAttributes & EFI_FVB_ERASE_POLARITY) ? (((~TestAttributes) & Bit) == Bit) : ((TestAttributes & Bit) == Bit) \
+ ) \
+ )
+
+typedef UINT16 EFI_FFS_FILE_TAIL;
+
+///
+/// FFS file integrity check structure
+///
+typedef union {
+ struct {
+ UINT8 Header;
+ UINT8 File;
+ } Checksum;
+ UINT16 TailReference;
+} EFI_FFS_INTEGRITY_CHECK;
+
+//
+// FFS file header definition
+//
+typedef UINT8 EFI_FFS_FILE_ATTRIBUTES;
+typedef UINT8 EFI_FFS_FILE_STATE;
+
+typedef struct {
+ EFI_GUID Name;
+ EFI_FFS_INTEGRITY_CHECK IntegrityCheck;
+ EFI_FV_FILETYPE Type;
+ EFI_FFS_FILE_ATTRIBUTES Attributes;
+ UINT8 Size[3];
+ EFI_FFS_FILE_STATE State;
+} EFI_FFS_FILE_HEADER;
+
+#endif
diff --git a/Source/Include/Common/FirmwareVolumeHeader.h b/Source/Include/Common/FirmwareVolumeHeader.h
new file mode 100644
index 0000000..038dce6
--- /dev/null
+++ b/Source/Include/Common/FirmwareVolumeHeader.h
@@ -0,0 +1,109 @@
+/** @file
+ Defines data structure that is the volume header found at the beginning of
+ all firmware volumes that are either memory mapped, or have an
+ associated FirmwareVolumeBlock protocol.
+
+ Copyright (c) 2006, Intel Corporation
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+ Module Name: FirmwareVolumeHeader.h
+
+ @par Revision Reference:
+ These definitions are from Firmware Volume Block Spec 0.9.
+
+**/
+
+#ifndef __EFI_FIRMWARE_VOLUME_HEADER_H__
+#define __EFI_FIRMWARE_VOLUME_HEADER_H__
+
+//
+// Firmware Volume Block Attributes definition
+//
+typedef UINT32 EFI_FVB_ATTRIBUTES;
+
+//
+// Firmware Volume Block Attributes bit definitions
+//
+#define EFI_FVB_READ_DISABLED_CAP 0x00000001
+#define EFI_FVB_READ_ENABLED_CAP 0x00000002
+#define EFI_FVB_READ_STATUS 0x00000004
+
+#define EFI_FVB_WRITE_DISABLED_CAP 0x00000008
+#define EFI_FVB_WRITE_ENABLED_CAP 0x00000010
+#define EFI_FVB_WRITE_STATUS 0x00000020
+
+#define EFI_FVB_LOCK_CAP 0x00000040
+#define EFI_FVB_LOCK_STATUS 0x00000080
+
+#define EFI_FVB_STICKY_WRITE 0x00000200
+#define EFI_FVB_MEMORY_MAPPED 0x00000400
+#define EFI_FVB_ERASE_POLARITY 0x00000800
+
+#define EFI_FVB_ALIGNMENT_CAP 0x00008000
+#define EFI_FVB_ALIGNMENT_2 0x00010000
+#define EFI_FVB_ALIGNMENT_4 0x00020000
+#define EFI_FVB_ALIGNMENT_8 0x00040000
+#define EFI_FVB_ALIGNMENT_16 0x00080000
+#define EFI_FVB_ALIGNMENT_32 0x00100000
+#define EFI_FVB_ALIGNMENT_64 0x00200000
+#define EFI_FVB_ALIGNMENT_128 0x00400000
+#define EFI_FVB_ALIGNMENT_256 0x00800000
+#define EFI_FVB_ALIGNMENT_512 0x01000000
+#define EFI_FVB_ALIGNMENT_1K 0x02000000
+#define EFI_FVB_ALIGNMENT_2K 0x04000000
+#define EFI_FVB_ALIGNMENT_4K 0x08000000
+#define EFI_FVB_ALIGNMENT_8K 0x10000000
+#define EFI_FVB_ALIGNMENT_16K 0x20000000
+#define EFI_FVB_ALIGNMENT_32K 0x40000000
+#define EFI_FVB_ALIGNMENT_64K 0x80000000
+
+#define EFI_FVB_CAPABILITIES (EFI_FVB_READ_DISABLED_CAP | \
+ EFI_FVB_READ_ENABLED_CAP | \
+ EFI_FVB_WRITE_DISABLED_CAP | \
+ EFI_FVB_WRITE_ENABLED_CAP | \
+ EFI_FVB_LOCK_CAP \
+ )
+
+#define EFI_FVB_STATUS (EFI_FVB_READ_STATUS | EFI_FVB_WRITE_STATUS | EFI_FVB_LOCK_STATUS)
+
+///
+/// Firmware Volume Header Revision definition
+///
+#define EFI_FVH_REVISION 0x01
+
+///
+/// Firmware Volume Header Signature definition
+///
+#define EFI_FVH_SIGNATURE EFI_SIGNATURE_32 ('_', 'F', 'V', 'H')
+
+///
+/// Firmware Volume Header Block Map Entry definition
+///
+typedef struct {
+ UINT32 NumBlocks;
+ UINT32 BlockLength;
+} EFI_FV_BLOCK_MAP_ENTRY;
+
+///
+/// Firmware Volume Header definition
+///
+typedef struct {
+ UINT8 ZeroVector[16];
+ EFI_GUID FileSystemGuid;
+ UINT64 FvLength;
+ UINT32 Signature;
+ EFI_FVB_ATTRIBUTES Attributes;
+ UINT16 HeaderLength;
+ UINT16 Checksum;
+ UINT8 Reserved[3];
+ UINT8 Revision;
+ EFI_FV_BLOCK_MAP_ENTRY FvBlockMap[1];
+} EFI_FIRMWARE_VOLUME_HEADER;
+
+#endif
diff --git a/Source/Include/Common/FirmwareVolumeImageFormat.h b/Source/Include/Common/FirmwareVolumeImageFormat.h
new file mode 100644
index 0000000..14fa41b
--- /dev/null
+++ b/Source/Include/Common/FirmwareVolumeImageFormat.h
@@ -0,0 +1,277 @@
+/** @file
+ This file defines the data structures that are architecturally defined for file
+ images loaded via the FirmwareVolume protocol. The Firmware Volume specification
+ is the basis for these definitions.
+
+ Copyright (c) 2006, Intel Corporation
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+ Module Name: FimrwareVolumeImageFormat.h
+
+ @par Revision Reference:
+ These definitions are from Firmware Volume Spec 0.9.
+
+**/
+
+#ifndef __FIRMWARE_VOLUME_IMAGE_FORMAT_H__
+#define __FIRMWARE_VOLUME_IMAGE_FORMAT_H__
+
+//
+// pack all data structures since this is actually a binary format and we cannot
+// allow internal padding in the data structures because of some compilerism..
+//
+#pragma pack(1)
+//
+// ////////////////////////////////////////////////////////////////////////////
+//
+// Architectural file types
+//
+typedef UINT8 EFI_FV_FILETYPE;
+
+#define EFI_FV_FILETYPE_ALL 0x00
+#define EFI_FV_FILETYPE_RAW 0x01
+#define EFI_FV_FILETYPE_FREEFORM 0x02
+#define EFI_FV_FILETYPE_SECURITY_CORE 0x03
+#define EFI_FV_FILETYPE_PEI_CORE 0x04
+#define EFI_FV_FILETYPE_DXE_CORE 0x05
+#define EFI_FV_FILETYPE_PEIM 0x06
+#define EFI_FV_FILETYPE_DRIVER 0x07
+#define EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER 0x08
+#define EFI_FV_FILETYPE_APPLICATION 0x09
+//
+// File type 0x0A is reserved and should not be used
+//
+#define EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE 0x0B
+
+//
+// ////////////////////////////////////////////////////////////////////////////
+//
+// Section types
+//
+typedef UINT8 EFI_SECTION_TYPE;
+
+//
+// ************************************************************
+// The section type EFI_SECTION_ALL is a psuedo type. It is
+// used as a wildcard when retrieving sections. The section
+// type EFI_SECTION_ALL matches all section types.
+// ************************************************************
+//
+#define EFI_SECTION_ALL 0x00
+
+//
+// ************************************************************
+// Encapsulation section Type values
+// ************************************************************
+//
+#define EFI_SECTION_COMPRESSION 0x01
+#define EFI_SECTION_GUID_DEFINED 0x02
+
+//
+// ************************************************************
+// Leaf section Type values
+// ************************************************************
+//
+#define EFI_SECTION_FIRST_LEAF_SECTION_TYPE 0x10
+
+#define EFI_SECTION_PE32 0x10
+#define EFI_SECTION_PIC 0x11
+#define EFI_SECTION_TE 0x12
+#define EFI_SECTION_DXE_DEPEX 0x13
+#define EFI_SECTION_VERSION 0x14
+#define EFI_SECTION_USER_INTERFACE 0x15
+#define EFI_SECTION_COMPATIBILITY16 0x16
+#define EFI_SECTION_FIRMWARE_VOLUME_IMAGE 0x17
+#define EFI_SECTION_FREEFORM_SUBTYPE_GUID 0x18
+#define EFI_SECTION_RAW 0x19
+#define EFI_SECTION_PEI_DEPEX 0x1B
+
+#define EFI_SECTION_LAST_LEAF_SECTION_TYPE 0x1B
+#define EFI_SECTION_LAST_SECTION_TYPE 0x1B
+
+//
+// ////////////////////////////////////////////////////////////////////////////
+//
+// Common section header
+//
+typedef struct {
+ UINT8 Size[3];
+ UINT8 Type;
+} EFI_COMMON_SECTION_HEADER;
+
+#define SECTION_SIZE(SectionHeaderPtr) \
+ ((UINT32) (*((UINT32 *) ((EFI_COMMON_SECTION_HEADER *) SectionHeaderPtr)->Size) & 0x00ffffff))
+
+//
+// ////////////////////////////////////////////////////////////////////////////
+//
+// Compression section
+//
+//
+// CompressionType values
+//
+#define EFI_NOT_COMPRESSED 0x00
+#define EFI_STANDARD_COMPRESSION 0x01
+#define EFI_CUSTOMIZED_COMPRESSION 0x02
+
+typedef struct {
+ EFI_COMMON_SECTION_HEADER CommonHeader;
+ UINT32 UncompressedLength;
+ UINT8 CompressionType;
+} EFI_COMPRESSION_SECTION;
+
+//
+// ////////////////////////////////////////////////////////////////////////////
+//
+// GUID defined section
+//
+typedef struct {
+ EFI_COMMON_SECTION_HEADER CommonHeader;
+ EFI_GUID SectionDefinitionGuid;
+ UINT16 DataOffset;
+ UINT16 Attributes;
+} EFI_GUID_DEFINED_SECTION;
+
+//
+// Bit values for Attributes
+//
+#define EFI_GUIDED_SECTION_PROCESSING_REQUIRED 0x01
+#define EFI_GUIDED_SECTION_AUTH_STATUS_VALID 0x02
+
+//
+// Bit values for AuthenticationStatus
+//
+#define EFI_AGGREGATE_AUTH_STATUS_PLATFORM_OVERRIDE 0x000001
+#define EFI_AGGREGATE_AUTH_STATUS_IMAGE_SIGNED 0x000002
+#define EFI_AGGREGATE_AUTH_STATUS_NOT_TESTED 0x000004
+#define EFI_AGGREGATE_AUTH_STATUS_TEST_FAILED 0x000008
+#define EFI_AGGREGATE_AUTH_STATUS_ALL 0x00000f
+
+#define EFI_LOCAL_AUTH_STATUS_PLATFORM_OVERRIDE 0x010000
+#define EFI_LOCAL_AUTH_STATUS_IMAGE_SIGNED 0x020000
+#define EFI_LOCAL_AUTH_STATUS_NOT_TESTED 0x040000
+#define EFI_LOCAL_AUTH_STATUS_TEST_FAILED 0x080000
+#define EFI_LOCAL_AUTH_STATUS_ALL 0x0f0000
+
+//
+// ////////////////////////////////////////////////////////////////////////////
+//
+// PE32+ section
+//
+typedef struct {
+ EFI_COMMON_SECTION_HEADER CommonHeader;
+} EFI_PE32_SECTION;
+
+//
+// ////////////////////////////////////////////////////////////////////////////
+//
+// PIC section
+//
+typedef struct {
+ EFI_COMMON_SECTION_HEADER CommonHeader;
+} EFI_PIC_SECTION;
+
+//
+// ////////////////////////////////////////////////////////////////////////////
+//
+// PEIM header section
+//
+typedef struct {
+ EFI_COMMON_SECTION_HEADER CommonHeader;
+} EFI_PEIM_HEADER_SECTION;
+
+//
+// ////////////////////////////////////////////////////////////////////////////
+//
+// DEPEX section
+//
+typedef struct {
+ EFI_COMMON_SECTION_HEADER CommonHeader;
+} EFI_DEPEX_SECTION;
+
+//
+// ////////////////////////////////////////////////////////////////////////////
+//
+// Version section
+//
+typedef struct {
+ EFI_COMMON_SECTION_HEADER CommonHeader;
+ UINT16 BuildNumber;
+ INT16 VersionString[1];
+} EFI_VERSION_SECTION;
+
+//
+// ////////////////////////////////////////////////////////////////////////////
+//
+// User interface section
+//
+typedef struct {
+ EFI_COMMON_SECTION_HEADER CommonHeader;
+ INT16 FileNameString[1];
+} EFI_USER_INTERFACE_SECTION;
+
+//
+// ////////////////////////////////////////////////////////////////////////////
+//
+// Code16 section
+//
+typedef struct {
+ EFI_COMMON_SECTION_HEADER CommonHeader;
+} EFI_CODE16_SECTION;
+
+//
+// ////////////////////////////////////////////////////////////////////////////
+//
+// Firmware Volume Image section
+//
+typedef struct {
+ EFI_COMMON_SECTION_HEADER CommonHeader;
+} EFI_FIRMWARE_VOLUME_IMAGE_SECTION;
+
+//
+// ////////////////////////////////////////////////////////////////////////////
+//
+// Freeform subtype GUID section
+//
+typedef struct {
+ EFI_COMMON_SECTION_HEADER CommonHeader;
+ EFI_GUID SubTypeGuid;
+} EFI_FREEFORM_SUBTYPE_GUID_SECTION;
+
+//
+// ////////////////////////////////////////////////////////////////////////////
+//
+// Raw section
+//
+typedef struct {
+ EFI_COMMON_SECTION_HEADER CommonHeader;
+} EFI_RAW_SECTION;
+
+//
+// undo the pragma from the beginning...
+//
+#pragma pack()
+
+typedef union {
+ EFI_COMMON_SECTION_HEADER *CommonHeader;
+ EFI_COMPRESSION_SECTION *CompressionSection;
+ EFI_GUID_DEFINED_SECTION *GuidDefinedSection;
+ EFI_PE32_SECTION *Pe32Section;
+ EFI_PIC_SECTION *PicSection;
+ EFI_PEIM_HEADER_SECTION *PeimHeaderSection;
+ EFI_DEPEX_SECTION *DependencySection;
+ EFI_VERSION_SECTION *VersionSection;
+ EFI_USER_INTERFACE_SECTION *UISection;
+ EFI_CODE16_SECTION *Code16Section;
+ EFI_FIRMWARE_VOLUME_IMAGE_SECTION *FVImageSection;
+ EFI_FREEFORM_SUBTYPE_GUID_SECTION *FreeformSubtypeSection;
+ EFI_RAW_SECTION *RawSection;
+} EFI_FILE_SECTION_POINTER;
+
+#endif
diff --git a/Source/Include/Common/InternalFormRepresentation.h b/Source/Include/Common/InternalFormRepresentation.h
new file mode 100644
index 0000000..bf3d824
--- /dev/null
+++ b/Source/Include/Common/InternalFormRepresentation.h
@@ -0,0 +1,422 @@
+/** @file
+ This file defines the encoding for the VFR (Visual Form Representation) language.
+ IFR is primarily consumed by the EFI presentation engine, and produced by EFI
+ internal application and drivers as well as all add-in card option-ROM drivers
+
+ Copyright (c) 2006, Intel Corporation
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+ Module Name: InternalFormRepresentation.h
+
+ @par Revision Reference:
+ These definitions are from Human Interface Infrastructure Spec Version 0.92.
+
+**/
+
+#ifndef __EFI_INTERNAL_FORM_REPRESENTATION_H__
+#define __EFI_INTERNAL_FORM_REPRESENTATION_H__
+
+//
+// The following types are currently defined:
+//
+typedef UINT32 RELOFST;
+typedef CHAR16 *EFI_STRING;
+
+//
+// IFR Op codes
+//
+#define EFI_IFR_FORM_OP 0x01
+#define EFI_IFR_SUBTITLE_OP 0x02
+#define EFI_IFR_TEXT_OP 0x03
+#define EFI_IFR_GRAPHIC_OP 0x04
+#define EFI_IFR_ONE_OF_OP 0x05
+#define EFI_IFR_CHECKBOX_OP 0x06
+#define EFI_IFR_NUMERIC_OP 0x07
+#define EFI_IFR_PASSWORD_OP 0x08
+#define EFI_IFR_ONE_OF_OPTION_OP 0x09 // ONEOF OPTION field
+#define EFI_IFR_SUPPRESS_IF_OP 0x0A
+#define EFI_IFR_END_FORM_OP 0x0B
+#define EFI_IFR_HIDDEN_OP 0x0C
+#define EFI_IFR_END_FORM_SET_OP 0x0D
+#define EFI_IFR_FORM_SET_OP 0x0E
+#define EFI_IFR_REF_OP 0x0F
+#define EFI_IFR_END_ONE_OF_OP 0x10
+#define EFI_IFR_END_OP EFI_IFR_END_ONE_OF_OP
+#define EFI_IFR_INCONSISTENT_IF_OP 0x11
+#define EFI_IFR_EQ_ID_VAL_OP 0x12
+#define EFI_IFR_EQ_ID_ID_OP 0x13
+#define EFI_IFR_EQ_ID_LIST_OP 0x14
+#define EFI_IFR_AND_OP 0x15
+#define EFI_IFR_OR_OP 0x16
+#define EFI_IFR_NOT_OP 0x17
+#define EFI_IFR_END_IF_OP 0x18 // for endif of inconsistentif, suppressif, grayoutif
+#define EFI_IFR_GRAYOUT_IF_OP 0x19
+#define EFI_IFR_DATE_OP 0x1A
+#define EFI_IFR_TIME_OP 0x1B
+#define EFI_IFR_STRING_OP 0x1C
+#define EFI_IFR_LABEL_OP 0x1D
+#define EFI_IFR_SAVE_DEFAULTS_OP 0x1E
+#define EFI_IFR_RESTORE_DEFAULTS_OP 0x1F
+#define EFI_IFR_BANNER_OP 0x20
+#define EFI_IFR_INVENTORY_OP 0x21
+#define EFI_IFR_EQ_VAR_VAL_OP 0x22
+#define EFI_IFR_ORDERED_LIST_OP 0x23
+#define EFI_IFR_VARSTORE_OP 0x24
+#define EFI_IFR_VARSTORE_SELECT_OP 0x25
+#define EFI_IFR_VARSTORE_SELECT_PAIR_OP 0x26
+#define EFI_IFR_TRUE_OP 0x27
+#define EFI_IFR_FALSE_OP 0x28
+#define EFI_IFR_GT_OP 0x29
+#define EFI_IFR_GE_OP 0x2A
+#define EFI_IFR_OEM_DEFINED_OP 0x2B
+#define EFI_IFR_LAST_OPCODE EFI_IFR_OEM_DEFINED_OP
+#define EFI_IFR_OEM_OP 0xFE
+#define EFI_IFR_NV_ACCESS_COMMAND 0xFF
+
+//
+// Define values for the flags fields in some VFR opcodes. These are
+// bitmasks.
+//
+#define EFI_IFR_FLAG_DEFAULT 0x01
+#define EFI_IFR_FLAG_MANUFACTURING 0x02
+#define EFI_IFR_FLAG_INTERACTIVE 0x04
+#define EFI_IFR_FLAG_NV_ACCESS 0x08
+#define EFI_IFR_FLAG_RESET_REQUIRED 0x10
+#define EFI_IFR_FLAG_LATE_CHECK 0x20
+
+#define EFI_NON_DEVICE_CLASS 0x00 // Useful when you do not want something in the Device Manager
+#define EFI_DISK_DEVICE_CLASS 0x01
+#define EFI_VIDEO_DEVICE_CLASS 0x02
+#define EFI_NETWORK_DEVICE_CLASS 0x04
+#define EFI_INPUT_DEVICE_CLASS 0x08
+#define EFI_ON_BOARD_DEVICE_CLASS 0x10
+#define EFI_OTHER_DEVICE_CLASS 0x20
+
+#define EFI_SETUP_APPLICATION_SUBCLASS 0x00
+#define EFI_GENERAL_APPLICATION_SUBCLASS 0x01
+#define EFI_FRONT_PAGE_SUBCLASS 0x02
+#define EFI_SINGLE_USE_SUBCLASS 0x03 // Used to display a single entity and then exit
+
+//
+// Used to flag dynamically created op-codes. This is meaningful to the IFR Library set
+// and the browser since we need to distinguish between compiled NV map data and created data.
+// We do not allow new entries to be created in the NV map dynamically however we still need
+// to display this information correctly. To dynamically create op-codes and assume that their
+// data will be saved, ensure that the NV starting location they refer to is pre-defined in the
+// NV map.
+//
+#define EFI_IFR_FLAG_CREATED 128
+
+#pragma pack(1)
+//
+// IFR Structure definitions
+//
+typedef struct {
+ UINT8 OpCode;
+ UINT8 Length;
+} EFI_IFR_OP_HEADER;
+
+typedef struct {
+ EFI_IFR_OP_HEADER Header;
+ EFI_GUID Guid;
+ STRING_REF FormSetTitle;
+ STRING_REF Help;
+ EFI_PHYSICAL_ADDRESS CallbackHandle;
+ UINT16 Class;
+ UINT16 SubClass;
+ UINT16 NvDataSize; // set once, size of the NV data as defined in the script
+} EFI_IFR_FORM_SET;
+
+typedef struct {
+ EFI_IFR_OP_HEADER Header;
+ UINT16 FormId;
+ STRING_REF FormTitle;
+} EFI_IFR_FORM;
+
+typedef struct {
+ EFI_IFR_OP_HEADER Header;
+ UINT16 LabelId;
+} EFI_IFR_LABEL;
+
+typedef struct {
+ EFI_IFR_OP_HEADER Header;
+ STRING_REF SubTitle;
+} EFI_IFR_SUBTITLE;
+
+typedef struct {
+ EFI_IFR_OP_HEADER Header;
+ STRING_REF Help;
+ STRING_REF Text;
+ STRING_REF TextTwo;
+ UINT8 Flags; // This is included solely for purposes of interactive/dynamic support.
+ UINT16 Key; // Value to be passed to caller to identify this particular op-code
+} EFI_IFR_TEXT;
+
+//
+// goto
+//
+typedef struct {
+ EFI_IFR_OP_HEADER Header;
+ UINT16 FormId;
+ STRING_REF Prompt;
+ STRING_REF Help; // The string Token for the context-help
+ UINT8 Flags; // This is included solely for purposes of interactive/dynamic support.
+ UINT16 Key; // Value to be passed to caller to identify this particular op-code
+} EFI_IFR_REF;
+
+typedef struct {
+ EFI_IFR_OP_HEADER Header;
+} EFI_IFR_END_FORM;
+
+typedef struct {
+ EFI_IFR_OP_HEADER Header;
+} EFI_IFR_END_FORM_SET;
+
+//
+// Also notice that the IFR_ONE_OF and IFR_CHECK_BOX are identical in structure......code assumes this to be true, if this ever
+// changes we need to revisit the InitializeTagStructures code
+//
+typedef struct {
+ EFI_IFR_OP_HEADER Header;
+ UINT16 QuestionId; // The ID designating what the question is about...sucked in from a #define, likely in the form of a variable name
+ UINT8 Width; // The Size of the Data being saved
+ STRING_REF Prompt; // The String Token for the Prompt
+ STRING_REF Help; // The string Token for the context-help
+} EFI_IFR_ONE_OF;
+
+typedef struct {
+ EFI_IFR_OP_HEADER Header;
+ UINT16 QuestionId; // The offset in NV for storage of the data
+ UINT8 MaxEntries; // The maximum number of options in the ordered list (=size of NVStore)
+ STRING_REF Prompt; // The string token for the prompt
+ STRING_REF Help; // The string token for the context-help
+} EFI_IFR_ORDERED_LIST;
+
+typedef struct {
+ EFI_IFR_OP_HEADER Header;
+ UINT16 QuestionId; // The ID designating what the question is about...sucked in from a #define, likely in the form of a variable name
+ UINT8 Width; // The Size of the Data being saved
+ STRING_REF Prompt; // The String Token for the Prompt
+ STRING_REF Help; // The string Token for the context-help
+ UINT8 Flags; // For now, if non-zero, means that it is the default option, - further definition likely
+ UINT16 Key; // Value to be passed to caller to identify this particular op-code
+} EFI_IFR_CHECKBOX, EFI_IFR_CHECK_BOX;
+
+typedef struct {
+ EFI_IFR_OP_HEADER Header;
+ STRING_REF Option; // The string token describing the option
+ UINT16 Value; // The value associated with this option that is stored in the NVRAM if chosen
+ UINT8 Flags; // For now, if non-zero, means that it is the default option, - further definition likely above
+ UINT16 Key; // Value to be passed to caller to identify this particular op-code
+} EFI_IFR_ONE_OF_OPTION;
+
+typedef struct {
+ EFI_IFR_OP_HEADER Header;
+ UINT16 QuestionId; // The ID designating what the question is about...sucked in from a #define, likely in the form of a variable name
+ UINT8 Width; // The Size of the Data being saved
+ STRING_REF Prompt; // The String Token for the Prompt
+ STRING_REF Help; // The string Token for the context-help
+ UINT8 Flags; // This is included solely for purposes of interactive/dynamic support.
+ UINT16 Key; // Value to be passed to caller to identify this particular op-code
+ UINT16 Minimum;
+ UINT16 Maximum;
+ UINT16 Step; // If step is 0, then manual input is specified, otherwise, left/right arrow selection is called for
+ UINT16 Default;
+} EFI_IFR_NUMERIC;
+
+//
+// There is an interesting twist with regards to Time and Date. This is one of the few items which can accept input from
+// a user, however may or may not need to use storage in the NVRAM space. The decided method for determining if NVRAM space
+// will be used (only for a TimeOp or DateOp) is: If .QuestionId == 0 && .Width == 0 (normally an impossibility) then use system
+// resources to store the data away and not NV resources. In other words, the setup engine will call gRT->SetTime, and gRT->SetDate
+// for the saving of data, and the values displayed will be from the gRT->GetXXXX series of calls.
+//
+typedef struct {
+ EFI_IFR_NUMERIC Hour;
+ EFI_IFR_NUMERIC Minute;
+ EFI_IFR_NUMERIC Second;
+} EFI_IFR_TIME;
+
+typedef struct {
+ EFI_IFR_NUMERIC Year;
+ EFI_IFR_NUMERIC Month;
+ EFI_IFR_NUMERIC Day;
+} EFI_IFR_DATE;
+
+typedef struct {
+ EFI_IFR_OP_HEADER Header;
+ UINT16 QuestionId; // The ID designating what the question is about...sucked in from a #define, likely in the form of a variable name
+ UINT8 Width; // The Size of the Data being saved -- BUGBUG -- remove someday
+ STRING_REF Prompt; // The String Token for the Prompt
+ STRING_REF Help; // The string Token for the context-help
+ UINT8 Flags; // This is included solely for purposes of interactive/dynamic support.
+ UINT16 Key; // Value to be passed to caller to identify this particular op-code
+ UINT8 MinSize; // Minimum allowable sized password
+ UINT8 MaxSize; // Maximum allowable sized password
+ UINT16 Encoding;
+} EFI_IFR_PASSWORD;
+
+typedef struct {
+ EFI_IFR_OP_HEADER Header;
+ UINT16 QuestionId; // The ID designating what the question is about...sucked in from a #define, likely in the form of a variable name
+ UINT8 Width; // The Size of the Data being saved -- BUGBUG -- remove someday
+ STRING_REF Prompt; // The String Token for the Prompt
+ STRING_REF Help; // The string Token for the context-help
+ UINT8 Flags; // This is included solely for purposes of interactive/dynamic support.
+ UINT16 Key; // Value to be passed to caller to identify this particular op-code
+ UINT8 MinSize; // Minimum allowable sized password
+ UINT8 MaxSize; // Maximum allowable sized password
+} EFI_IFR_STRING;
+
+typedef struct {
+ EFI_IFR_OP_HEADER Header;
+} EFI_IFR_END_ONE_OF;
+
+typedef struct {
+ EFI_IFR_OP_HEADER Header;
+ UINT16 Value;
+ UINT16 Key;
+} EFI_IFR_HIDDEN;
+
+typedef struct {
+ EFI_IFR_OP_HEADER Header;
+ UINT8 Flags;
+} EFI_IFR_SUPPRESS;
+
+typedef struct {
+ EFI_IFR_OP_HEADER Header;
+ UINT8 Flags;
+} EFI_IFR_GRAY_OUT;
+
+typedef struct {
+ EFI_IFR_OP_HEADER Header;
+ STRING_REF Popup;
+ UINT8 Flags;
+} EFI_IFR_INCONSISTENT;
+
+typedef struct {
+ EFI_IFR_OP_HEADER Header;
+ UINT16 QuestionId; // offset into variable storage
+ UINT8 Width; // size of variable storage
+ UINT16 Value; // value to compare against
+} EFI_IFR_EQ_ID_VAL;
+
+typedef struct {
+ EFI_IFR_OP_HEADER Header;
+ UINT16 QuestionId; // offset into variable storage
+ UINT8 Width; // size of variable storage
+ UINT16 ListLength;
+ UINT16 ValueList[1];
+} EFI_IFR_EQ_ID_LIST;
+
+typedef struct {
+ EFI_IFR_OP_HEADER Header;
+ UINT16 QuestionId1; // offset into variable storage for first value to compare
+ UINT8 Width; // size of variable storage (must be same for both)
+ UINT16 QuestionId2; // offset into variable storage for second value to compare
+} EFI_IFR_EQ_ID_ID;
+
+typedef struct {
+ EFI_IFR_OP_HEADER Header;
+ UINT16 VariableId; // offset into variable storage
+ UINT16 Value; // value to compare against
+} EFI_IFR_EQ_VAR_VAL;
+
+typedef struct {
+ EFI_IFR_OP_HEADER Header;
+} EFI_IFR_AND;
+
+typedef struct {
+ EFI_IFR_OP_HEADER Header;
+} EFI_IFR_OR;
+
+typedef struct {
+ EFI_IFR_OP_HEADER Header;
+} EFI_IFR_NOT;
+
+typedef struct {
+ EFI_IFR_OP_HEADER Header;
+} EFI_IFR_END_EXPR, EFI_IFR_END_IF;
+
+typedef struct {
+ EFI_IFR_OP_HEADER Header;
+ UINT16 FormId;
+ STRING_REF Prompt;
+ STRING_REF Help;
+ UINT8 Flags;
+ UINT16 Key;
+} EFI_IFR_SAVE_DEFAULTS;
+
+typedef struct {
+ EFI_IFR_OP_HEADER Header;
+ STRING_REF Help;
+ STRING_REF Text;
+ STRING_REF TextTwo; // optional text
+} EFI_IFR_INVENTORY;
+
+typedef struct {
+ EFI_IFR_OP_HEADER Header;
+ EFI_GUID Guid; // GUID for the variable
+ UINT16 VarId; // variable store ID, as referenced elsewhere in the form
+ UINT16 Size; // size of the variable storage
+} EFI_IFR_VARSTORE;
+
+typedef struct {
+ EFI_IFR_OP_HEADER Header;
+ UINT16 VarId; // variable store ID, as referenced elsewhere in the form
+} EFI_IFR_VARSTORE_SELECT;
+
+//
+// Used for the ideqid VFR statement where two variable stores may be referenced in the
+// same VFR statement.
+// A browser should treat this as an EFI_IFR_VARSTORE_SELECT statement and assume that all following
+// IFR opcodes use the VarId as defined here.
+//
+typedef struct {
+ EFI_IFR_OP_HEADER Header;
+ UINT16 VarId; // variable store ID, as referenced elsewhere in the form
+ UINT16 SecondaryVarId; // variable store ID, as referenced elsewhere in the form
+} EFI_IFR_VARSTORE_SELECT_PAIR;
+
+typedef struct {
+ EFI_IFR_OP_HEADER Header;
+} EFI_IFR_TRUE;
+
+typedef struct {
+ EFI_IFR_OP_HEADER Header;
+} EFI_IFR_FALSE;
+
+typedef struct {
+ EFI_IFR_OP_HEADER Header;
+} EFI_IFR_GT;
+
+typedef struct {
+ EFI_IFR_OP_HEADER Header;
+} EFI_IFR_GE;
+
+//
+// Save defaults and restore defaults have same structure
+//
+#define EFI_IFR_RESTORE_DEFAULTS EFI_IFR_SAVE_DEFAULTS
+
+typedef struct {
+ EFI_IFR_OP_HEADER Header;
+ STRING_REF Title; // The string token for the banner title
+ UINT16 LineNumber; // 1-based line number
+ UINT8 Alignment; // left, center, or right-aligned
+} EFI_IFR_BANNER;
+
+#define EFI_IFR_BANNER_ALIGN_LEFT 0
+#define EFI_IFR_BANNER_ALIGN_CENTER 1
+#define EFI_IFR_BANNER_ALIGN_RIGHT 2
+#define EFI_IFR_BANNER_TIMEOUT 0xFF
+
+#pragma pack()
+
+#endif
diff --git a/Source/Include/Common/MultiPhase.h b/Source/Include/Common/MultiPhase.h
new file mode 100644
index 0000000..93867a5
--- /dev/null
+++ b/Source/Include/Common/MultiPhase.h
@@ -0,0 +1,84 @@
+/** @file
+ This includes some definitions that will be used in both PEI and DXE phases.
+
+ Copyright (c) 2006, Intel Corporation
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+ Module Name: MultiPhase.h
+
+**/
+
+#ifndef __MULTI_PHASE_H__
+#define __MULTI_PHASE_H__
+
+//
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//
+// Needed EFI defines for PEI
+//
+typedef UINT64 EFI_PHYSICAL_ADDRESS;
+
+typedef enum {
+ EfiReservedMemoryType,
+ EfiLoaderCode,
+ EfiLoaderData,
+ EfiBootServicesCode,
+ EfiBootServicesData,
+ EfiRuntimeServicesCode,
+ EfiRuntimeServicesData,
+ EfiConventionalMemory,
+ EfiUnusableMemory,
+ EfiACPIReclaimMemory,
+ EfiACPIMemoryNVS,
+ EfiMemoryMappedIO,
+ EfiMemoryMappedIOPortSpace,
+ EfiPalCode,
+ EfiMaxMemoryType
+} EFI_MEMORY_TYPE;
+
+typedef UINT32 EFI_STATUS_CODE_TYPE;
+typedef UINT32 EFI_STATUS_CODE_VALUE;
+
+typedef struct {
+ UINT16 HeaderSize;
+ UINT16 Size;
+ EFI_GUID Type;
+} EFI_STATUS_CODE_DATA;
+
+typedef struct {
+ UINT64 Signature;
+ UINT32 Revision;
+ UINT32 HeaderSize;
+ UINT32 CRC32;
+ UINT32 Reserved;
+} EFI_TABLE_HEADER;
+
+#define EFI_PAGE_SIZE 4096
+
+
+typedef VOID *EFI_HANDLE;
+typedef UINT16 EFI_HII_HANDLE;
+typedef UINT16 STRING_REF;
+typedef struct {
+ INT16 Value;
+ INT16 Exponent;
+} EFI_EXP_BASE10_DATA;
+
+//
+// Define macros to build data structure signatures from characters.
+//
+#define EFI_SIGNATURE_16(A, B) ((A) | (B << 8))
+#define EFI_SIGNATURE_32(A, B, C, D) (EFI_SIGNATURE_16 (A, B) | (EFI_SIGNATURE_16 (C, D) << 16))
+#define EFI_SIGNATURE_64(A, B, C, D, E, F, G, H) \
+ (EFI_SIGNATURE_32 (A, B, C, D) | ((UINT64) (EFI_SIGNATURE_32 (E, F, G, H)) << 32))
+
+
+#include <Protocol/DevicePath.h>
+
+#endif
diff --git a/Source/Include/Common/UefiBaseTypes.h b/Source/Include/Common/UefiBaseTypes.h
new file mode 100644
index 0000000..4954c10
--- /dev/null
+++ b/Source/Include/Common/UefiBaseTypes.h
@@ -0,0 +1,85 @@
+/** @file
+ This file makes the BaseTypes.h backward compatible with the ones used in the
+ past for EFI and Tiano development. It's mostly just prepending an EFI_ on the
+ definitions.
+
+ Copyright (c) 2006, Intel Corporation
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+ Module Name: UefiBaseTypes.h
+
+**/
+
+#ifndef __UEFI_BASE_TYPES_H__
+#define __UEFI_BASE_TYPES_H__
+
+#include <Common/BaseTypes.h>
+
+typedef UINT64 EFI_LBA;
+
+#define EFIERR(_a) ENCODE_ERROR(_a)
+
+#define EFI_MAX_BIT MAX_BIT
+#define EFI_MAX_ADDRESS MAX_ADDRESS
+#define EFI_BREAKPOINT() CpuBreakpoint ()
+#define EFI_DEADLOOP() CpuDeadLoop ()
+#define EFI_ERROR(A) RETURN_ERROR(A)
+
+typedef GUID EFI_GUID;
+typedef RETURN_STATUS EFI_STATUS;
+
+#define EFI_SUCCESS RETURN_SUCCESS
+#define EFI_LOAD_ERROR RETURN_LOAD_ERROR
+#define EFI_INVALID_PARAMETER RETURN_INVALID_PARAMETER
+#define EFI_UNSUPPORTED RETURN_UNSUPPORTED
+#define EFI_BAD_BUFFER_SIZE RETURN_BAD_BUFFER_SIZE
+#define EFI_BUFFER_TOO_SMALL RETURN_BUFFER_TOO_SMALL
+#define EFI_NOT_READY RETURN_NOT_READY
+#define EFI_DEVICE_ERROR RETURN_DEVICE_ERROR
+#define EFI_WRITE_PROTECTED RETURN_WRITE_PROTECTED
+#define EFI_OUT_OF_RESOURCES RETURN_OUT_OF_RESOURCES
+#define EFI_VOLUME_CORRUPTED RETURN_VOLUME_CORRUPTED
+#define EFI_VOLUME_FULL RETURN_VOLUME_FULL
+#define EFI_NO_MEDIA RETURN_NO_MEDIA
+#define EFI_MEDIA_CHANGED RETURN_MEDIA_CHANGED
+#define EFI_NOT_FOUND RETURN_NOT_FOUND
+#define EFI_ACCESS_DENIED RETURN_ACCESS_DENIED
+#define EFI_NO_RESPONSE RETURN_NO_RESPONSE
+#define EFI_NO_MAPPING RETURN_NO_MAPPING
+#define EFI_TIMEOUT RETURN_TIMEOUT
+#define EFI_NOT_STARTED RETURN_NOT_STARTED
+#define EFI_ALREADY_STARTED RETURN_ALREADY_STARTED
+#define EFI_ABORTED RETURN_ABORTED
+#define EFI_ICMP_ERROR RETURN_ICMP_ERROR
+#define EFI_TFTP_ERROR RETURN_TFTP_ERROR
+#define EFI_PROTOCOL_ERROR RETURN_PROTOCOL_ERROR
+#define EFI_INCOMPATIBLE_VERSION RETURN_INCOMPATIBLE_VERSION
+#define EFI_SECURITY_VIOLATION RETURN_SECURITY_VIOLATION
+#define EFI_CRC_ERROR RETURN_CRC_ERROR
+#define EFI_END_OF_MEDIA RETURN_END_OF_MEDIA
+#define EFI_END_OF_FILE RETURN_END_OF_FILE
+
+#define EFI_WARN_UNKNOWN_GLYPH RETURN_WARN_UNKNOWN_GLYPH
+#define EFI_WARN_DELETE_FAILURE RETURN_WARN_DELETE_FAILURE
+#define EFI_WARN_WRITE_FAILURE RETURN_WARN_WRITE_FAILURE
+#define EFI_WARN_BUFFER_TOO_SMALL RETURN_WARN_BUFFER_TOO_SMALL
+
+//
+// The EFI memory allocation functions work in units of EFI_PAGEs that are
+// 4K. This should in no way be confused with the page size of the processor.
+// An EFI_PAGE is just the quanta of memory in EFI.
+//
+#define EFI_PAGE_MASK 0xFFF
+#define EFI_PAGE_SHIFT 12
+
+#define EFI_SIZE_TO_PAGES(a) (((a) >> EFI_PAGE_SHIFT) + (((a) & EFI_PAGE_MASK) ? 1 : 0))
+
+#define EFI_PAGES_TO_SIZE(a) ( (a) << EFI_PAGE_SHIFT)
+
+#endif
diff --git a/Source/Include/Common/Variable.h b/Source/Include/Common/Variable.h
new file mode 100644
index 0000000..bc0d640
--- /dev/null
+++ b/Source/Include/Common/Variable.h
@@ -0,0 +1,78 @@
+/*++
+
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ EfiVariable.h
+
+Abstract:
+
+ Header file for EFI Variable Services
+
+--*/
+
+#ifndef _EFI_VARIABLE_H_
+#define _EFI_VARIABLE_H_
+
+#define VARIABLE_STORE_SIGNATURE EFI_SIGNATURE_32 ('$', 'V', 'S', 'S')
+
+#define MAX_VARIABLE_SIZE 1024
+
+#define VARIABLE_DATA 0x55AA
+
+//
+// Variable Store Header flags
+//
+#define VARIABLE_STORE_FORMATTED 0x5a
+#define VARIABLE_STORE_HEALTHY 0xfe
+
+//
+// Variable Store Status
+//
+typedef enum {
+ EfiRaw,
+ EfiValid,
+ EfiInvalid,
+ EfiUnknown
+} VARIABLE_STORE_STATUS;
+
+//
+// Variable State flags
+//
+#define VAR_IN_DELETED_TRANSITION 0xfe // Variable is in obsolete transistion
+#define VAR_DELETED 0xfd // Variable is obsolete
+#define VAR_ADDED 0x7f // Variable has been completely added
+#define IS_VARIABLE_STATE(_c, _Mask) (BOOLEAN) (((~_c) & (~_Mask)) != 0)
+
+#pragma pack(1)
+
+typedef struct {
+ UINT32 Signature;
+ UINT32 Size;
+ UINT8 Format;
+ UINT8 State;
+ UINT16 Reserved;
+ UINT32 Reserved1;
+} VARIABLE_STORE_HEADER;
+
+typedef struct {
+ UINT16 StartId;
+ UINT8 State;
+ UINT8 Reserved;
+ UINT32 Attributes;
+ UINTN NameSize;
+ UINTN DataSize;
+ EFI_GUID VendorGuid;
+} VARIABLE_HEADER;
+
+#pragma pack()
+
+#endif // _EFI_VARIABLE_H_
diff --git a/Source/Include/Common/WorkingBlockHeader.h b/Source/Include/Common/WorkingBlockHeader.h
new file mode 100644
index 0000000..235b740
--- /dev/null
+++ b/Source/Include/Common/WorkingBlockHeader.h
@@ -0,0 +1,47 @@
+/*++
+
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ EfiWorkingBlockHeader.h
+
+Abstract:
+
+ Defines data structure that is the headers found at the runtime
+ updatable firmware volumes, such as the FileSystemGuid of the
+ working block, the header structure of the variable block, FTW
+ working block, or event log block.
+
+--*/
+
+#ifndef _EFI_WORKING_BLOCK_HEADER_H_
+#define _EFI_WORKING_BLOCK_HEADER_H_
+
+//
+// EFI Fault tolerant working block header
+// The header is immediately followed by the write queue.
+//
+typedef struct {
+ EFI_GUID Signature;
+ UINT32 Crc;
+ UINT32 WorkingBlockValid : 1;
+ UINT32 WorkingBlockInvalid : 1;
+#define WORKING_BLOCK_VALID 0x1
+#define WORKING_BLOCK_INVALID 0x2
+ UINT32 Reserved : 6;
+ UINT8 Reserved3[3];
+ UINTN WriteQueueSize;
+ //
+ // UINT8 WriteQueue[WriteQueueSize];
+ //
+} EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER;
+
+#endif
diff --git a/Source/Include/Guid/AcpiTableStorage.h b/Source/Include/Guid/AcpiTableStorage.h
new file mode 100644
index 0000000..80b1154
--- /dev/null
+++ b/Source/Include/Guid/AcpiTableStorage.h
@@ -0,0 +1,30 @@
+/** @file
+ The ACPI table storage file is fully FFS compliant.
+ The file is a number of sections of type EFI_SECTION_RAW.
+ This GUID is used to identify the file as an ACPI table storage file.
+
+ Copyright (c) 2006, Intel Corporation
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+ Module Name: AcpiTableStorage.h
+
+ @par Revision Reference:
+ GUID defined in ACPI Table Storage Spec Version 0.9.
+
+**/
+
+#ifndef _ACPI_TABLE_STORAGE_H_
+#define _ACPI_TABLE_STORAGE_H_
+
+#define EFI_ACPI_TABLE_STORAGE_GUID \
+ { 0x7e374e25, 0x8e01, 0x4fee, {0x87, 0xf2, 0x39, 0xc, 0x23, 0xc6, 0x6, 0xcd } }
+
+extern EFI_GUID gEfiAcpiTableStorageGuid;
+
+#endif
diff --git a/Source/Include/Guid/Apriori.h b/Source/Include/Guid/Apriori.h
new file mode 100644
index 0000000..ba92560
--- /dev/null
+++ b/Source/Include/Guid/Apriori.h
@@ -0,0 +1,32 @@
+/** @file
+ GUID used as an FV filename for A Priori file. The A Priori file contains a
+ list of FV filenames that the DXE dispatcher will schedule reguardless of
+ the dependency grammer.
+
+ Copyright (c) 2006, Intel Corporation
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+ Module Name: Apriori.h
+
+ @par Revision Reference:
+ GUID defined in DXE CIS spec version 0.91B
+
+**/
+
+#ifndef __APRIORI_GUID_H__
+#define __APRIORI_GUID_H__
+
+#define EFI_APRIORI_GUID \
+ { \
+ 0xfc510ee7, 0xffdc, 0x11d4, {0xbd, 0x41, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81 } \
+ }
+
+extern EFI_GUID gAprioriGuid;
+
+#endif
diff --git a/Source/Include/Guid/Capsule.h b/Source/Include/Guid/Capsule.h
new file mode 100644
index 0000000..7864b92
--- /dev/null
+++ b/Source/Include/Guid/Capsule.h
@@ -0,0 +1,43 @@
+/** @file
+ GUIDs used for EFI Capsule
+
+ Copyright (c) 2006, Intel Corporation
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+ Module Name: Capsule.h
+
+ @par Revision Reference:
+ GUIDs defined in Capsule Spec Version 0.9
+
+**/
+
+#ifndef __CAPSULE_GUID_H__
+#define __CAPSULE_GUID_H__
+
+//
+// This is the GUID of the capsule header of the image on disk.
+//
+#define EFI_CAPSULE_GUID \
+ { \
+ 0x3B6686BD, 0x0D76, 0x4030, {0xB7, 0x0E, 0xB5, 0x51, 0x9E, 0x2F, 0xC5, 0xA0 } \
+ }
+
+//
+// This is the GUID of the configuration results file created by the capsule
+// application.
+//
+#define EFI_CONFIG_FILE_NAME_GUID \
+ { \
+ 0x98B8D59B, 0xE8BA, 0x48EE, {0x98, 0xDD, 0xC2, 0x95, 0x39, 0x2F, 0x1E, 0xDB } \
+ }
+
+extern EFI_GUID gEfiCapsuleGuid;
+extern EFI_GUID gEfiConfigFileNameGuid;
+
+#endif
diff --git a/Source/Include/Guid/FirmwareFileSystem.h b/Source/Include/Guid/FirmwareFileSystem.h
new file mode 100644
index 0000000..06bfa7d
--- /dev/null
+++ b/Source/Include/Guid/FirmwareFileSystem.h
@@ -0,0 +1,40 @@
+/** @file
+ Guid used to define the Firmware File System. See the Framework Firmware
+ File System Specification for more details.
+
+ Copyright (c) 2006, Intel Corporation
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+ Module Name: FirmwareFileSystem.h
+
+ @par Revision Reference:
+ Guids defined in Firmware File System Spec 0.9
+
+**/
+
+#ifndef __FIRMWARE_FILE_SYSTEM_GUID_H__
+#define __FIRMWARE_FILE_SYSTEM_GUID_H__
+
+//
+// GUIDs defined by the FFS specification.
+//
+#define EFI_FIRMWARE_FILE_SYSTEM_GUID \
+ { \
+ 0x7A9354D9, 0x0468, 0x444a, {0x81, 0xCE, 0x0B, 0xF6, 0x17, 0xD8, 0x90, 0xDF } \
+ }
+
+#define EFI_FFS_VOLUME_TOP_FILE_GUID \
+ { \
+ 0x1BA0062E, 0xC779, 0x4582, {0x85, 0x66, 0x33, 0x6A, 0xE8, 0xF7, 0x8F, 0x9 } \
+ }
+
+extern EFI_GUID gEfiFirmwareFileSystemGuid;
+extern EFI_GUID gEfiFirmwareVolumeTopFileGuid;
+
+#endif
diff --git a/Source/Include/Ia32/ProcessorBind.h b/Source/Include/Ia32/ProcessorBind.h
new file mode 100644
index 0000000..587d8a6
--- /dev/null
+++ b/Source/Include/Ia32/ProcessorBind.h
@@ -0,0 +1,167 @@
+/** @file
+ Processor or Compiler specific defines and types for x64.
+
+ Copyright (c) 2006, Intel Corporation
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+ Module Name: ProcessorBind.h
+
+**/
+
+#ifndef __PROCESSOR_BIND_H__
+#define __PROCESSOR_BIND_H__
+
+//
+// Define the processor type so other code can make processor based choices
+//
+#define MDE_CPU_IA32
+
+//
+// Make sure we are useing the correct packing rules per EFI specification
+//
+#ifndef __GNUC__
+#pragma pack()
+#endif
+
+#if _MSC_EXTENSIONS
+
+//
+// Disable warning that make it impossible to compile at /W4
+// This only works for Microsoft* tools
+//
+
+//
+// Disabling bitfield type checking warnings.
+//
+#pragma warning ( disable : 4214 )
+
+//
+// Disabling the unreferenced formal parameter warnings.
+//
+#pragma warning ( disable : 4100 )
+
+//
+// Disable slightly different base types warning as CHAR8 * can not be set
+// to a constant string.
+//
+#pragma warning ( disable : 4057 )
+
+//
+// ASSERT(FALSE) or while (TRUE) are legal constructes so supress this warning
+//
+#pragma warning ( disable : 4127 )
+
+
+#endif
+
+
+#if !defined(__GNUC__) && (__STDC_VERSION__ < 199901L)
+ //
+ // No ANSI C 2000 stdint.h integer width declarations, so define equivalents
+ //
+
+ #if _MSC_EXTENSIONS
+
+ //
+ // use Microsoft* C complier dependent interger width types
+ //
+ typedef unsigned __int64 UINT64;
+ typedef __int64 INT64;
+ typedef unsigned __int32 UINT32;
+ typedef __int32 INT32;
+ typedef unsigned short UINT16;
+ typedef unsigned short CHAR16;
+ typedef short INT16;
+ typedef unsigned char BOOLEAN;
+ typedef unsigned char UINT8;
+ typedef char CHAR8;
+ typedef char INT8;
+ #else
+
+ //
+ // Assume standard IA-32 alignment.
+ // BugBug: Need to check portability of long long
+ //
+ typedef unsigned long long UINT64;
+ typedef long long INT64;
+ typedef unsigned int UINT32;
+ typedef int INT32;
+ typedef unsigned short UINT16;
+ typedef unsigned short CHAR16;
+ typedef short INT16;
+ typedef unsigned char BOOLEAN;
+ typedef unsigned char UINT8;
+ typedef char CHAR8;
+ typedef char INT8;
+ #endif
+
+ #define UINT8_MAX 0xff
+
+#else
+ //
+ // Use ANSI C 2000 stdint.h integer width declarations
+ //
+ #include "stdint.h"
+ typedef uint8_t BOOLEAN;
+ typedef int8_t INT8;
+ typedef uint8_t UINT8;
+ typedef int16_t INT16;
+ typedef uint16_t UINT16;
+ typedef int32_t INT32;
+ typedef uint32_t UINT32;
+ typedef int64_t INT64;
+ typedef uint64_t UINT64;
+ typedef char CHAR8;
+ typedef uint16_t CHAR16;
+
+#endif
+
+typedef UINT32 UINTN;
+typedef INT32 INTN;
+
+
+//
+// Processor specific defines
+//
+#define MAX_BIT 0x80000000
+#define MAX_2_BITS 0xC0000000
+
+//
+// Maximum legal IA-32 address
+//
+#define MAX_ADDRESS 0xFFFFFFFF
+
+//
+// Modifier to ensure that all protocol member functions and EFI intrinsics
+// use the correct C calling convention. All protocol member functions and
+// EFI intrinsics are required to modify thier member functions with EFIAPI.
+//
+#if _MSC_EXTENSIONS
+ //
+ // Microsoft* compiler requires _EFIAPI useage, __cdecl is Microsoft* specific C.
+ //
+ #define EFIAPI __cdecl
+#endif
+
+#if __GNUC__
+ #define EFIAPI __attribute__((cdecl))
+#endif
+
+//
+// The Microsoft* C compiler can removed references to unreferenced data items
+// if the /OPT:REF linker option is used. We defined a macro as this is a
+// a non standard extension
+//
+#if _MSC_EXTENSIONS
+ #define GLOBAL_REMOVE_IF_UNREFERENCED __declspec(selectany)
+#else
+ #define GLOBAL_REMOVE_IF_UNREFERENCED
+#endif
+
+#endif
diff --git a/Source/Include/IndustryStandard/pci22.h b/Source/Include/IndustryStandard/pci22.h
new file mode 100644
index 0000000..7fee279
--- /dev/null
+++ b/Source/Include/IndustryStandard/pci22.h
@@ -0,0 +1,481 @@
+/** @file
+ Support for PCI 2.2 standard.
+
+ Copyright (c) 2006, Intel Corporation
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+ Module Name: pci22.h
+
+**/
+
+#ifndef _PCI22_H
+#define _PCI22_H
+
+#define PCI_MAX_SEGMENT 0
+
+#define PCI_MAX_BUS 255
+
+#define PCI_MAX_DEVICE 31
+#define PCI_MAX_FUNC 7
+
+//
+// Command
+//
+#define PCI_VGA_PALETTE_SNOOP_DISABLED 0x20
+
+#pragma pack(push, 1)
+typedef struct {
+ UINT16 VendorId;
+ UINT16 DeviceId;
+ UINT16 Command;
+ UINT16 Status;
+ UINT8 RevisionID;
+ UINT8 ClassCode[3];
+ UINT8 CacheLineSize;
+ UINT8 LatencyTimer;
+ UINT8 HeaderType;
+ UINT8 BIST;
+} PCI_DEVICE_INDEPENDENT_REGION;
+
+typedef struct {
+ UINT32 Bar[6];
+ UINT32 CISPtr;
+ UINT16 SubsystemVendorID;
+ UINT16 SubsystemID;
+ UINT32 ExpansionRomBar;
+ UINT8 CapabilityPtr;
+ UINT8 Reserved1[3];
+ UINT32 Reserved2;
+ UINT8 InterruptLine;
+ UINT8 InterruptPin;
+ UINT8 MinGnt;
+ UINT8 MaxLat;
+} PCI_DEVICE_HEADER_TYPE_REGION;
+
+typedef struct {
+ PCI_DEVICE_INDEPENDENT_REGION Hdr;
+ PCI_DEVICE_HEADER_TYPE_REGION Device;
+} PCI_TYPE00;
+
+typedef struct {
+ UINT32 Bar[2];
+ UINT8 PrimaryBus;
+ UINT8 SecondaryBus;
+ UINT8 SubordinateBus;
+ UINT8 SecondaryLatencyTimer;
+ UINT8 IoBase;
+ UINT8 IoLimit;
+ UINT16 SecondaryStatus;
+ UINT16 MemoryBase;
+ UINT16 MemoryLimit;
+ UINT16 PrefetchableMemoryBase;
+ UINT16 PrefetchableMemoryLimit;
+ UINT32 PrefetchableBaseUpper32;
+ UINT32 PrefetchableLimitUpper32;
+ UINT16 IoBaseUpper16;
+ UINT16 IoLimitUpper16;
+ UINT8 CapabilityPtr;
+ UINT8 Reserved[3];
+ UINT32 ExpansionRomBAR;
+ UINT8 InterruptLine;
+ UINT8 InterruptPin;
+ UINT16 BridgeControl;
+} PCI_BRIDGE_CONTROL_REGISTER;
+
+typedef struct {
+ PCI_DEVICE_INDEPENDENT_REGION Hdr;
+ PCI_BRIDGE_CONTROL_REGISTER Bridge;
+} PCI_TYPE01;
+
+typedef union {
+ PCI_TYPE00 Device;
+ PCI_TYPE01 Bridge;
+} PCI_TYPE_GENERIC;
+
+typedef struct {
+ UINT32 CardBusSocketReg; // Cardus Socket/ExCA Base
+ // Address Register
+ //
+ UINT16 Reserved;
+ UINT16 SecondaryStatus; // Secondary Status
+ UINT8 PciBusNumber; // PCI Bus Number
+ UINT8 CardBusBusNumber; // CardBus Bus Number
+ UINT8 SubordinateBusNumber; // Subordinate Bus Number
+ UINT8 CardBusLatencyTimer; // CardBus Latency Timer
+ UINT32 MemoryBase0; // Memory Base Register 0
+ UINT32 MemoryLimit0; // Memory Limit Register 0
+ UINT32 MemoryBase1;
+ UINT32 MemoryLimit1;
+ UINT32 IoBase0;
+ UINT32 IoLimit0; // I/O Base Register 0
+ UINT32 IoBase1; // I/O Limit Register 0
+ UINT32 IoLimit1;
+ UINT8 InterruptLine; // Interrupt Line
+ UINT8 InterruptPin; // Interrupt Pin
+ UINT16 BridgeControl; // Bridge Control
+} PCI_CARDBUS_CONTROL_REGISTER;
+
+//
+// Definitions of PCI class bytes and manipulation macros.
+//
+#define PCI_CLASS_OLD 0x00
+#define PCI_CLASS_OLD_OTHER 0x00
+#define PCI_CLASS_OLD_VGA 0x01
+
+#define PCI_CLASS_MASS_STORAGE 0x01
+#define PCI_CLASS_MASS_STORAGE_SCSI 0x00
+#define PCI_CLASS_MASS_STORAGE_IDE 0x01 // obsolete
+#define PCI_CLASS_IDE 0x01
+#define PCI_CLASS_MASS_STORAGE_FLOPPY 0x02
+#define PCI_CLASS_MASS_STORAGE_IPI 0x03
+#define PCI_CLASS_MASS_STORAGE_RAID 0x04
+#define PCI_CLASS_MASS_STORAGE_OTHER 0x80
+
+#define PCI_CLASS_NETWORK 0x02
+#define PCI_CLASS_NETWORK_ETHERNET 0x00
+#define PCI_CLASS_ETHERNET 0x00 // obsolete
+#define PCI_CLASS_NETWORK_TOKENRING 0x01
+#define PCI_CLASS_NETWORK_FDDI 0x02
+#define PCI_CLASS_NETWORK_ATM 0x03
+#define PCI_CLASS_NETWORK_ISDN 0x04
+#define PCI_CLASS_NETWORK_OTHER 0x80
+
+#define PCI_CLASS_DISPLAY 0x03
+#define PCI_CLASS_DISPLAY_CTRL 0x03 // obsolete
+#define PCI_CLASS_DISPLAY_VGA 0x00
+#define PCI_CLASS_VGA 0x00 // obsolete
+#define PCI_CLASS_DISPLAY_XGA 0x01
+#define PCI_CLASS_DISPLAY_3D 0x02
+#define PCI_CLASS_DISPLAY_OTHER 0x80
+#define PCI_CLASS_DISPLAY_GFX 0x80
+#define PCI_CLASS_GFX 0x80 // obsolete
+#define PCI_CLASS_BRIDGE 0x06
+#define PCI_CLASS_BRIDGE_HOST 0x00
+#define PCI_CLASS_BRIDGE_ISA 0x01
+#define PCI_CLASS_ISA 0x01 // obsolete
+#define PCI_CLASS_BRIDGE_EISA 0x02
+#define PCI_CLASS_BRIDGE_MCA 0x03
+#define PCI_CLASS_BRIDGE_P2P 0x04
+#define PCI_CLASS_BRIDGE_PCMCIA 0x05
+#define PCI_CLASS_BRIDGE_NUBUS 0x06
+#define PCI_CLASS_BRIDGE_CARDBUS 0x07
+#define PCI_CLASS_BRIDGE_RACEWAY 0x08
+#define PCI_CLASS_BRIDGE_ISA_PDECODE 0x80
+#define PCI_CLASS_ISA_POSITIVE_DECODE 0x80 // obsolete
+#define PCI_CLASS_SERIAL 0x0C
+#define PCI_CLASS_SERIAL_FIREWIRE 0x00
+#define PCI_CLASS_SERIAL_ACCESS_BUS 0x01
+#define PCI_CLASS_SERIAL_SSA 0x02
+#define PCI_CLASS_SERIAL_USB 0x03
+#define PCI_CLASS_SERIAL_FIBRECHANNEL 0x04
+#define PCI_CLASS_SERIAL_SMB 0x05
+
+#define IS_CLASS1(_p, c) ((_p)->Hdr.ClassCode[2] == (c))
+#define IS_CLASS2(_p, c, s) (IS_CLASS1 (_p, c) && ((_p)->Hdr.ClassCode[1] == (s)))
+#define IS_CLASS3(_p, c, s, p) (IS_CLASS2 (_p, c, s) && ((_p)->Hdr.ClassCode[0] == (p)))
+
+#define IS_PCI_DISPLAY(_p) IS_CLASS1 (_p, PCI_CLASS_DISPLAY)
+#define IS_PCI_VGA(_p) IS_CLASS3 (_p, PCI_CLASS_DISPLAY, PCI_CLASS_DISPLAY_VGA, 0)
+#define IS_PCI_8514(_p) IS_CLASS3 (_p, PCI_CLASS_DISPLAY, PCI_CLASS_DISPLAY_VGA, 1)
+#define IS_PCI_GFX(_p) IS_CLASS3 (_p, PCI_CLASS_DISPLAY, PCI_CLASS_DISPLAY_GFX, 0)
+#define IS_PCI_OLD(_p) IS_CLASS1 (_p, PCI_CLASS_OLD)
+#define IS_PCI_OLD_VGA(_p) IS_CLASS2 (_p, PCI_CLASS_OLD, PCI_CLASS_OLD_VGA)
+#define IS_PCI_IDE(_p) IS_CLASS2 (_p, PCI_CLASS_MASS_STORAGE, PCI_CLASS_MASS_STORAGE_IDE)
+#define IS_PCI_SCSI(_p) IS_CLASS3 (_p, PCI_CLASS_MASS_STORAGE, PCI_CLASS_MASS_STORAGE_SCSI, 0)
+#define IS_PCI_RAID(_p) IS_CLASS3 (_p, PCI_CLASS_MASS_STORAGE, PCI_CLASS_MASS_STORAGE_RAID, 0)
+#define IS_PCI_LPC(_p) IS_CLASS3 (_p, PCI_CLASS_BRIDGE, PCI_CLASS_BRIDGE_ISA, 0)
+#define IS_PCI_P2P(_p) IS_CLASS3 (_p, PCI_CLASS_BRIDGE, PCI_CLASS_BRIDGE_P2P, 0)
+#define IS_PCI_P2P_SUB(_p) IS_CLASS3 (_p, PCI_CLASS_BRIDGE, PCI_CLASS_BRIDGE_P2P, 1)
+#define IS_PCI_USB(_p) IS_CLASS2 (_p, PCI_CLASS_SERIAL, PCI_CLASS_SERIAL_USB)
+
+#define HEADER_TYPE_DEVICE 0x00
+#define HEADER_TYPE_PCI_TO_PCI_BRIDGE 0x01
+#define HEADER_TYPE_CARDBUS_BRIDGE 0x02
+
+#define HEADER_TYPE_MULTI_FUNCTION 0x80
+#define HEADER_LAYOUT_CODE 0x7f
+
+#define IS_PCI_BRIDGE(_p) (((_p)->Hdr.HeaderType & HEADER_LAYOUT_CODE) == (HEADER_TYPE_PCI_TO_PCI_BRIDGE))
+#define IS_CARDBUS_BRIDGE(_p) (((_p)->Hdr.HeaderType & HEADER_LAYOUT_CODE) == (HEADER_TYPE_CARDBUS_BRIDGE))
+#define IS_PCI_MULTI_FUNC(_p) ((_p)->Hdr.HeaderType & HEADER_TYPE_MULTI_FUNCTION)
+
+#define PCI_DEVICE_ROMBAR 0x30
+#define PCI_BRIDGE_ROMBAR 0x38
+
+#define PCI_MAX_BAR 6
+#define PCI_MAX_CONFIG_OFFSET 0x100
+//
+// bugbug: this is supported in PCI spec v2.3
+//
+#define PCI_EXP_MAX_CONFIG_OFFSET 0x1000
+
+#define PCI_VENDOR_ID_OFFSET 0x00
+#define PCI_DEVICE_ID_OFFSET 0x02
+#define PCI_COMMAND_OFFSET 0x04
+#define PCI_PRIMARY_STATUS_OFFSET 0x06
+#define PCI_REVISION_ID_OFFSET 0x08
+#define PCI_CLASSCODE_OFFSET 0x09
+#define PCI_CACHELINE_SIZE_OFFSET 0x0C
+#define PCI_LATENCY_TIMER_OFFSET 0x0D
+#define PCI_HEADER_TYPE_OFFSET 0x0E
+#define PCI_BIST_OFFSET 0x0F
+
+#define PCI_BRIDGE_CONTROL_REGISTER_OFFSET 0x3E
+#define PCI_BRIDGE_STATUS_REGISTER_OFFSET 0x1E
+
+#define PCI_BRIDGE_PRIMARY_BUS_REGISTER_OFFSET 0x18
+#define PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET 0x19
+#define PCI_BRIDGE_SUBORDINATE_BUS_REGISTER_OFFSET 0x1a
+
+typedef struct {
+ UINT8 Register;
+ UINT8 Function;
+ UINT8 Device;
+ UINT8 Bus;
+ UINT8 Reserved[4];
+} DEFIO_PCI_ADDR;
+
+typedef union {
+ struct {
+ UINT32 Reg : 8;
+ UINT32 Func : 3;
+ UINT32 Dev : 5;
+ UINT32 Bus : 8;
+ UINT32 Reserved : 7;
+ UINT32 Enable : 1;
+ } Bits;
+ UINT32 Uint32;
+} PCI_CONFIG_ACCESS_CF8;
+
+#pragma pack()
+
+#define EFI_ROOT_BRIDGE_LIST 'eprb'
+#define PCI_EXPANSION_ROM_HEADER_SIGNATURE 0xaa55
+#define EFI_PCI_EXPANSION_ROM_HEADER_EFISIGNATURE 0x0EF1
+#define PCI_DATA_STRUCTURE_SIGNATURE EFI_SIGNATURE_32 ('P', 'C', 'I', 'R')
+#define PCI_CODE_TYPE_PCAT_IMAGE 0x00
+#define PCI_CODE_TYPE_EFI_IMAGE 0x03
+#define EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED 0x0001
+
+#define EFI_PCI_COMMAND_IO_SPACE 0x0001
+#define EFI_PCI_COMMAND_MEMORY_SPACE 0x0002
+#define EFI_PCI_COMMAND_BUS_MASTER 0x0004
+#define EFI_PCI_COMMAND_SPECIAL_CYCLE 0x0008
+#define EFI_PCI_COMMAND_MEMORY_WRITE_AND_INVALIDATE 0x0010
+#define EFI_PCI_COMMAND_VGA_PALETTE_SNOOP 0x0020
+#define EFI_PCI_COMMAND_PARITY_ERROR_RESPOND 0x0040
+#define EFI_PCI_COMMAND_STEPPING_CONTROL 0x0080
+#define EFI_PCI_COMMAND_SERR 0x0100
+#define EFI_PCI_COMMAND_FAST_BACK_TO_BACK 0x0200
+
+#define EFI_PCI_BRIDGE_CONTROL_PARITY_ERROR_RESPONSE 0x0001
+#define EFI_PCI_BRIDGE_CONTROL_SERR 0x0002
+#define EFI_PCI_BRIDGE_CONTROL_ISA 0x0004
+#define EFI_PCI_BRIDGE_CONTROL_VGA 0x0008
+#define EFI_PCI_BRIDGE_CONTROL_VGA_16 0x0010
+#define EFI_PCI_BRIDGE_CONTROL_MASTER_ABORT 0x0020
+#define EFI_PCI_BRIDGE_CONTROL_RESET_SECONDARY_BUS 0x0040
+#define EFI_PCI_BRIDGE_CONTROL_FAST_BACK_TO_BACK 0x0080
+#define EFI_PCI_BRIDGE_CONTROL_PRIMARY_DISCARD_TIMER 0x0100
+#define EFI_PCI_BRIDGE_CONTROL_SECONDARY_DISCARD_TIMER 0x0200
+#define EFI_PCI_BRIDGE_CONTROL_TIMER_STATUS 0x0400
+#define EFI_PCI_BRIDGE_CONTROL_DISCARD_TIMER_SERR 0x0800
+
+//
+// Following are the PCI-CARDBUS bridge control bit
+//
+#define EFI_PCI_BRIDGE_CONTROL_IREQINT_ENABLE 0x0080
+#define EFI_PCI_BRIDGE_CONTROL_RANGE0_MEMORY_TYPE 0x0100
+#define EFI_PCI_BRIDGE_CONTROL_RANGE1_MEMORY_TYPE 0x0200
+#define EFI_PCI_BRIDGE_CONTROL_WRITE_POSTING_ENABLE 0x0400
+
+//
+// Following are the PCI status control bit
+//
+#define EFI_PCI_STATUS_CAPABILITY 0x0010
+#define EFI_PCI_STATUS_66MZ_CAPABLE 0x0020
+#define EFI_PCI_FAST_BACK_TO_BACK_CAPABLE 0x0080
+#define EFI_PCI_MASTER_DATA_PARITY_ERROR 0x0100
+
+#define EFI_PCI_CAPABILITY_PTR 0x34
+#define EFI_PCI_CARDBUS_BRIDGE_CAPABILITY_PTR 0x14
+
+#pragma pack(1)
+typedef struct {
+ UINT16 Signature; // 0xaa55
+ UINT8 Reserved[0x16];
+ UINT16 PcirOffset;
+} PCI_EXPANSION_ROM_HEADER;
+
+typedef struct {
+ UINT16 Signature; // 0xaa55
+ UINT16 InitializationSize;
+ UINT32 EfiSignature; // 0x0EF1
+ UINT16 EfiSubsystem;
+ UINT16 EfiMachineType;
+ UINT16 CompressionType;
+ UINT8 Reserved[8];
+ UINT16 EfiImageHeaderOffset;
+ UINT16 PcirOffset;
+} EFI_PCI_EXPANSION_ROM_HEADER;
+
+typedef struct {
+ UINT16 Signature; // 0xaa55
+ UINT8 Size512;
+ UINT8 Reserved[15];
+ UINT16 PcirOffset;
+} EFI_LEGACY_EXPANSION_ROM_HEADER;
+
+typedef union {
+ UINT8 *Raw;
+ PCI_EXPANSION_ROM_HEADER *Generic;
+ EFI_PCI_EXPANSION_ROM_HEADER *Efi;
+ EFI_LEGACY_EXPANSION_ROM_HEADER *PcAt;
+} EFI_PCI_ROM_HEADER;
+
+typedef struct {
+ UINT32 Signature; // "PCIR"
+ UINT16 VendorId;
+ UINT16 DeviceId;
+ UINT16 Reserved0;
+ UINT16 Length;
+ UINT8 Revision;
+ UINT8 ClassCode[3];
+ UINT16 ImageLength;
+ UINT16 CodeRevision;
+ UINT8 CodeType;
+ UINT8 Indicator;
+ UINT16 Reserved1;
+} PCI_DATA_STRUCTURE;
+
+//
+// PCI Capability List IDs and records
+//
+#define EFI_PCI_CAPABILITY_ID_PMI 0x01
+#define EFI_PCI_CAPABILITY_ID_AGP 0x02
+#define EFI_PCI_CAPABILITY_ID_VPD 0x03
+#define EFI_PCI_CAPABILITY_ID_SLOTID 0x04
+#define EFI_PCI_CAPABILITY_ID_MSI 0x05
+#define EFI_PCI_CAPABILITY_ID_HOTPLUG 0x06
+#define EFI_PCI_CAPABILITY_ID_PCIX 0x07
+//
+// bugbug: this ID is defined in PCI spec v2.3
+//
+#define EFI_PCI_CAPABILITY_ID_PCIEXP 0x10
+
+typedef struct {
+ UINT8 CapabilityID;
+ UINT8 NextItemPtr;
+} EFI_PCI_CAPABILITY_HDR;
+
+//
+// Capability EFI_PCI_CAPABILITY_ID_PMI
+//
+typedef struct {
+ EFI_PCI_CAPABILITY_HDR Hdr;
+ UINT16 PMC;
+ UINT16 PMCSR;
+ UINT8 BridgeExtention;
+ UINT8 Data;
+} EFI_PCI_CAPABILITY_PMI;
+
+//
+// Capability EFI_PCI_CAPABILITY_ID_AGP
+//
+typedef struct {
+ EFI_PCI_CAPABILITY_HDR Hdr;
+ UINT8 Rev;
+ UINT8 Reserved;
+ UINT32 Status;
+ UINT32 Command;
+} EFI_PCI_CAPABILITY_AGP;
+
+//
+// Capability EFI_PCI_CAPABILITY_ID_VPD
+//
+typedef struct {
+ EFI_PCI_CAPABILITY_HDR Hdr;
+ UINT16 AddrReg;
+ UINT32 DataReg;
+} EFI_PCI_CAPABILITY_VPD;
+
+//
+// Capability EFI_PCI_CAPABILITY_ID_SLOTID
+//
+typedef struct {
+ EFI_PCI_CAPABILITY_HDR Hdr;
+ UINT8 ExpnsSlotReg;
+ UINT8 ChassisNo;
+} EFI_PCI_CAPABILITY_SLOTID;
+
+//
+// Capability EFI_PCI_CAPABILITY_ID_MSI
+//
+typedef struct {
+ EFI_PCI_CAPABILITY_HDR Hdr;
+ UINT16 MsgCtrlReg;
+ UINT32 MsgAddrReg;
+ UINT16 MsgDataReg;
+} EFI_PCI_CAPABILITY_MSI32;
+
+typedef struct {
+ EFI_PCI_CAPABILITY_HDR Hdr;
+ UINT16 MsgCtrlReg;
+ UINT32 MsgAddrRegLsdw;
+ UINT32 MsgAddrRegMsdw;
+ UINT16 MsgDataReg;
+} EFI_PCI_CAPABILITY_MSI64;
+
+//
+// Capability EFI_PCI_CAPABILITY_ID_HOTPLUG
+//
+typedef struct {
+ EFI_PCI_CAPABILITY_HDR Hdr;
+ //
+ // not finished - fields need to go here
+ //
+} EFI_PCI_CAPABILITY_HOTPLUG;
+
+//
+// Capability EFI_PCI_CAPABILITY_ID_PCIX
+//
+typedef struct {
+ EFI_PCI_CAPABILITY_HDR Hdr;
+ UINT16 CommandReg;
+ UINT32 StatusReg;
+} EFI_PCI_CAPABILITY_PCIX;
+
+typedef struct {
+ EFI_PCI_CAPABILITY_HDR Hdr;
+ UINT16 SecStatusReg;
+ UINT32 StatusReg;
+ UINT32 SplitTransCtrlRegUp;
+ UINT32 SplitTransCtrlRegDn;
+} EFI_PCI_CAPABILITY_PCIX_BRDG;
+
+#define DEVICE_ID_NOCARE 0xFFFF
+
+#define PCI_ACPI_UNUSED 0
+#define PCI_BAR_NOCHANGE 0
+#define PCI_BAR_OLD_ALIGN 0xFFFFFFFFFFFFFFFFULL
+#define PCI_BAR_EVEN_ALIGN 0xFFFFFFFFFFFFFFFEULL
+#define PCI_BAR_SQUAD_ALIGN 0xFFFFFFFFFFFFFFFDULL
+#define PCI_BAR_DQUAD_ALIGN 0xFFFFFFFFFFFFFFFCULL
+
+#define PCI_BAR_IDX0 0x00
+#define PCI_BAR_IDX1 0x01
+#define PCI_BAR_IDX2 0x02
+#define PCI_BAR_IDX3 0x03
+#define PCI_BAR_IDX4 0x04
+#define PCI_BAR_IDX5 0x05
+#define PCI_BAR_ALL 0xFF
+
+#pragma pack(pop)
+
+#endif
diff --git a/Source/Include/Library/PeCoffLib.h b/Source/Include/Library/PeCoffLib.h
new file mode 100644
index 0000000..08e8195
--- /dev/null
+++ b/Source/Include/Library/PeCoffLib.h
@@ -0,0 +1,131 @@
+/** @file
+ Memory Only PE COFF loader
+
+ Copyright (c) 2006, Intel Corporation
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+ Module Name: PeCoffLib.h
+
+**/
+
+#ifndef __BASE_PE_COFF_LIB_H__
+#define __BASE_PE_COFF_LIB_H__
+
+//
+// Return status codes from the PE/COFF Loader services
+// BUGBUG: Find where used and see if can be replaced by RETURN_STATUS codes
+//
+#define IMAGE_ERROR_SUCCESS 0
+#define IMAGE_ERROR_IMAGE_READ 1
+#define IMAGE_ERROR_INVALID_PE_HEADER_SIGNATURE 2
+#define IMAGE_ERROR_INVALID_MACHINE_TYPE 3
+#define IMAGE_ERROR_INVALID_SUBSYSTEM 4
+#define IMAGE_ERROR_INVALID_IMAGE_ADDRESS 5
+#define IMAGE_ERROR_INVALID_IMAGE_SIZE 6
+#define IMAGE_ERROR_INVALID_SECTION_ALIGNMENT 7
+#define IMAGE_ERROR_SECTION_NOT_LOADED 8
+#define IMAGE_ERROR_FAILED_RELOCATION 9
+#define IMAGE_ERROR_FAILED_ICACHE_FLUSH 10
+
+
+//
+// PE/COFF Loader Read Function passed in by caller
+//
+typedef
+RETURN_STATUS
+(EFIAPI *PE_COFF_LOADER_READ_FILE) (
+ IN VOID *FileHandle,
+ IN UINTN FileOffset,
+ IN OUT UINTN *ReadSize,
+ OUT VOID *Buffer
+ );
+
+//
+// Context structure used while PE/COFF image is being loaded and relocated
+//
+typedef struct {
+ PHYSICAL_ADDRESS ImageAddress;
+ UINT64 ImageSize;
+ PHYSICAL_ADDRESS DestinationAddress;
+ PHYSICAL_ADDRESS EntryPoint;
+ PE_COFF_LOADER_READ_FILE ImageRead;
+ VOID *Handle;
+ VOID *FixupData;
+ UINT32 SectionAlignment;
+ UINT32 PeCoffHeaderOffset;
+ UINT32 DebugDirectoryEntryRva;
+ VOID *CodeView;
+ CHAR8 *PdbPointer;
+ UINTN SizeOfHeaders;
+ UINT32 ImageCodeMemoryType;
+ UINT32 ImageDataMemoryType;
+ UINT32 ImageError;
+ UINTN FixupDataSize;
+ UINT16 Machine;
+ UINT16 ImageType;
+ BOOLEAN RelocationsStripped;
+ BOOLEAN IsTeImage;
+} PE_COFF_LOADER_IMAGE_CONTEXT;
+
+
+/**
+ Retrieves information on a PE/COFF image
+
+ @param ImageContext The context of the image being loaded
+
+ @retval EFI_SUCCESS The information on the PE/COFF image was collected.
+ @retval EFI_INVALID_PARAMETER ImageContext is NULL.
+ @retval EFI_UNSUPPORTED The PE/COFF image is not supported.
+ @retval Otherwise The error status from reading the PE/COFF image using the
+ ImageContext->ImageRead() function
+
+**/
+RETURN_STATUS
+EFIAPI
+PeCoffLoaderGetImageInfo (
+ IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext
+ )
+;
+
+/**
+ Relocates a PE/COFF image in memory
+
+ @param ImageContext Contains information on the loaded image to relocate
+
+ @retval EFI_SUCCESS if the PE/COFF image was relocated
+ @retval EFI_LOAD_ERROR if the image is not a valid PE/COFF image
+ @retval EFI_UNSUPPORTED not support
+
+**/
+RETURN_STATUS
+EFIAPI
+PeCoffLoaderRelocateImage (
+ IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext
+ )
+;
+
+/**
+ Loads a PE/COFF image into memory
+
+ @param ImageContext Contains information on image to load into memory
+
+ @retval EFI_SUCCESS if the PE/COFF image was loaded
+ @retval EFI_BUFFER_TOO_SMALL if the caller did not provide a large enough buffer
+ @retval EFI_LOAD_ERROR if the image is a runtime driver with no relocations
+ @retval EFI_INVALID_PARAMETER if the image address is invalid
+
+**/
+RETURN_STATUS
+EFIAPI
+PeCoffLoaderLoadImage (
+ IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext
+ )
+;
+
+#endif
diff --git a/Source/Include/Library/PrintLib.h b/Source/Include/Library/PrintLib.h
new file mode 100644
index 0000000..9c65459
--- /dev/null
+++ b/Source/Include/Library/PrintLib.h
@@ -0,0 +1,406 @@
+/** @file
+ Library that provides print services
+
+ Copyright (c) 2006, Intel Corporation
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+ Module Name: PrintLib.h
+
+**/
+
+#ifndef __PRINT_LIB_H__
+#define __PRINT_LIB_H__
+
+//
+// Print primitives
+//
+#define LEFT_JUSTIFY 0x01
+#define COMMA_TYPE 0x08
+#define PREFIX_ZERO 0x20
+
+/**
+ Produces a Null-terminated Unicode string in an output buffer based on
+ a Null-terminated Unicode format string and a VA_LIST argument list
+
+ Produces a Null-terminated Unicode string in the output buffer specified by StartOfBuffer
+ and BufferSize.
+ The Unicode string is produced by parsing the format string specified by FormatString.
+ Arguments are pulled from the variable argument list specified by Marker based on the
+ contents of the format string.
+ The length of the produced output buffer is returned.
+ If BufferSize is 0, then no output buffer is produced and 0 is returned.
+
+ If BufferSize is not 0 and StartOfBuffer is NULL, then ASSERT().
+ If BufferSize is not 0 and FormatString is NULL, then ASSERT().
+ If PcdMaximumUnicodeStringLength is not zero, and FormatString contains more than
+ PcdMaximumUnicodeStringLength Unicode characters, then ASSERT().
+ If PcdMaximumUnicodeStringLength is not zero, and produced Null-terminated Unicode string
+ contains more than PcdMaximumUnicodeStringLength Unicode characters, then ASSERT().
+
+ @param StartOfBuffer APointer to the output buffer for the produced Null-terminated
+ Unicode string.
+ @param BufferSize The size, in bytes, of the output buffer specified by StartOfBuffer.
+ @param FormatString Null-terminated Unicode format string.
+ @param Marker VA_LIST marker for the variable argument list.
+
+ @return return Length of the produced output buffer.
+
+**/
+UINTN
+EFIAPI
+UnicodeVSPrint (
+ OUT CHAR16 *StartOfBuffer,
+ IN UINTN BufferSize,
+ IN CONST CHAR16 *FormatString,
+ IN VA_LIST Marker
+ );
+
+/**
+ Produces a Null-terminated Unicode string in an output buffer based on a Null-terminated
+ Unicode format string and variable argument list.
+
+ Produces a Null-terminated Unicode string in the output buffer specified by StartOfBuffer
+ and BufferSize.
+ The Unicode string is produced by parsing the format string specified by FormatString.
+ Arguments are pulled from the variable argument list based on the contents of the format string.
+ The length of the produced output buffer is returned.
+ If BufferSize is 0, then no output buffer is produced and 0 is returned.
+
+ If BufferSize is not 0 and StartOfBuffer is NULL, then ASSERT().
+ If BufferSize is not 0 and FormatString is NULL, then ASSERT().
+ If PcdMaximumUnicodeStringLength is not zero, and FormatString contains more than
+ PcdMaximumUnicodeStringLength Unicode characters, then ASSERT().
+ If PcdMaximumUnicodeStringLength is not zero, and produced Null-terminated Unicode string
+ contains more than PcdMaximumUnicodeStringLength Unicode characters, then ASSERT().
+
+ @param StartOfBuffer APointer to the output buffer for the produced Null-terminated
+ Unicode string.
+ @param BufferSize The size, in bytes, of the output buffer specified by StartOfBuffer.
+ @param FormatString Null-terminated Unicode format string.
+
+ @return Length of the produced output buffer.
+
+**/
+UINTN
+EFIAPI
+UnicodeSPrint (
+ OUT CHAR16 *StartOfBuffer,
+ IN UINTN BufferSize,
+ IN CONST CHAR16 *FormatString,
+ ...
+ );
+
+/**
+ Produces a Null-terminated Unicode string in an output buffer based on a Null-terminated
+ ASCII format string and a VA_LIST argument list
+
+ Produces a Null-terminated Unicode string in the output buffer specified by StartOfBuffer
+ and BufferSize.
+ The Unicode string is produced by parsing the format string specified by FormatString.
+ Arguments are pulled from the variable argument list specified by Marker based on the
+ contents of the format string.
+ The length of the produced output buffer is returned.
+ If BufferSize is 0, then no output buffer is produced and 0 is returned.
+
+ If BufferSize is not 0 and StartOfBuffer is NULL, then ASSERT().
+ If BufferSize is not 0 and FormatString is NULL, then ASSERT().
+ If PcdMaximumUnicodeStringLength is not zero, and FormatString contains more than
+ PcdMaximumUnicodeStringLength Unicode characters, then ASSERT().
+ If PcdMaximumUnicodeStringLength is not zero, and produced Null-terminated Unicode string
+ contains more than PcdMaximumUnicodeStringLength Unicode characters, then ASSERT().
+
+ @param StartOfBuffer APointer to the output buffer for the produced Null-terminated
+ Unicode string.
+ @param BufferSize The size, in bytes, of the output buffer specified by StartOfBuffer.
+ @param FormatString Null-terminated Unicode format string.
+ @param Marker VA_LIST marker for the variable argument list.
+
+ @return Length of the produced output buffer.
+
+**/
+UINTN
+EFIAPI
+UnicodeVSPrintAsciiFormat (
+ OUT CHAR16 *StartOfBuffer,
+ IN UINTN BufferSize,
+ IN CONST CHAR8 *FormatString,
+ IN VA_LIST Marker
+ );
+
+/**
+ Produces a Null-terminated Unicode string in an output buffer based on a Null-terminated
+ ASCII format string and variable argument list.
+
+ Produces a Null-terminated Unicode string in the output buffer specified by StartOfBuffer
+ and BufferSize.
+ The Unicode string is produced by parsing the format string specified by FormatString.
+ Arguments are pulled from the variable argument list based on the contents of the
+ format string.
+ The length of the produced output buffer is returned.
+ If BufferSize is 0, then no output buffer is produced and 0 is returned.
+
+ If BufferSize is not 0 and StartOfBuffer is NULL, then ASSERT().
+ If BufferSize is not 0 and FormatString is NULL, then ASSERT().
+ If PcdMaximumUnicodeStringLength is not zero, and FormatString contains more than
+ PcdMaximumUnicodeStringLength Unicode characters, then ASSERT().
+ If PcdMaximumUnicodeStringLength is not zero, and produced Null-terminated Unicode string
+ contains more than PcdMaximumUnicodeStringLength Unicode characters, then ASSERT().
+
+ @param StartOfBuffer APointer to the output buffer for the produced Null-terminated
+ Unicode string.
+ @param BufferSize The size, in bytes, of the output buffer specified by StartOfBuffer.
+ @param FormatString Null-terminated Unicode format string.
+
+ @return Length of the produced output buffer.
+
+**/
+UINTN
+EFIAPI
+UnicodeSPrintAsciiFormat (
+ OUT CHAR16 *StartOfBuffer,
+ IN UINTN BufferSize,
+ IN CONST CHAR8 *FormatString,
+ ...
+ );
+
+/**
+ Produces a Null-terminated ASCII string in an output buffer based on a Null-terminated
+ ASCII format string and a VA_LIST argument list.
+
+ Produces a Null-terminated ASCII string in the output buffer specified by StartOfBuffer
+ and BufferSize.
+ The ASCII string is produced by parsing the format string specified by FormatString.
+ Arguments are pulled from the variable argument list specified by Marker based on
+ the contents of the format string.
+ The length of the produced output buffer is returned.
+ If BufferSize is 0, then no output buffer is produced and 0 is returned.
+
+ If BufferSize is not 0 and StartOfBuffer is NULL, then ASSERT().
+ If BufferSize is not 0 and FormatString is NULL, then ASSERT().
+ If PcdMaximumUnicodeStringLength is not zero, and FormatString contains more than
+ PcdMaximumUnicodeStringLength ASCII characters, then ASSERT().
+ If PcdMaximumUnicodeStringLength is not zero, and produced Null-terminated Unicode string
+ contains more than PcdMaximumUnicodeStringLength ASCII characters, then ASSERT().
+
+ @param StartOfBuffer APointer to the output buffer for the produced Null-terminated
+ ASCII string.
+ @param BufferSize The size, in bytes, of the output buffer specified by StartOfBuffer.
+ @param FormatString Null-terminated Unicode format string.
+ @param Marker VA_LIST marker for the variable argument list.
+
+ @return Length of the produced output buffer.
+
+**/
+UINTN
+EFIAPI
+AsciiVSPrint (
+ OUT CHAR8 *StartOfBuffer,
+ IN UINTN BufferSize,
+ IN CONST CHAR8 *FormatString,
+ IN VA_LIST Marker
+ );
+
+/**
+ Produces a Null-terminated ASCII string in an output buffer based on a Null-terminated
+ ASCII format string and variable argument list.
+
+ Produces a Null-terminated ASCII string in the output buffer specified by StartOfBuffer
+ and BufferSize.
+ The ASCII string is produced by parsing the format string specified by FormatString.
+ Arguments are pulled from the variable argument list based on the contents of the
+ format string.
+ The length of the produced output buffer is returned.
+ If BufferSize is 0, then no output buffer is produced and 0 is returned.
+
+ If BufferSize is not 0 and StartOfBuffer is NULL, then ASSERT().
+ If BufferSize is not 0 and FormatString is NULL, then ASSERT().
+ If PcdMaximumUnicodeStringLength is not zero, and FormatString contains more than
+ PcdMaximumUnicodeStringLength ASCII characters, then ASSERT().
+ If PcdMaximumUnicodeStringLength is not zero, and produced Null-terminated Unicode string
+ contains more than PcdMaximumUnicodeStringLength ASCII characters, then ASSERT().
+
+ @param StartOfBuffer APointer to the output buffer for the produced Null-terminated
+ ASCII string.
+ @param BufferSize The size, in bytes, of the output buffer specified by StartOfBuffer.
+ @param FormatString Null-terminated Unicode format string.
+
+ @return Length of the produced output buffer.
+
+**/
+UINTN
+EFIAPI
+AsciiSPrint (
+ OUT CHAR8 *StartOfBuffer,
+ IN UINTN BufferSize,
+ IN CONST CHAR8 *FormatString,
+ ...
+ );
+
+/**
+ Produces a Null-terminated ASCII string in an output buffer based on a Null-terminated
+ ASCII format string and a VA_LIST argument list.
+
+ Produces a Null-terminated ASCII string in the output buffer specified by StartOfBuffer
+ and BufferSize.
+ The ASCII string is produced by parsing the format string specified by FormatString.
+ Arguments are pulled from the variable argument list specified by Marker based on
+ the contents of the format string.
+ The length of the produced output buffer is returned.
+ If BufferSize is 0, then no output buffer is produced and 0 is returned.
+
+ If BufferSize is not 0 and StartOfBuffer is NULL, then ASSERT().
+ If BufferSize is not 0 and FormatString is NULL, then ASSERT().
+ If PcdMaximumUnicodeStringLength is not zero, and FormatString contains more than
+ PcdMaximumUnicodeStringLength ASCII characters, then ASSERT().
+ If PcdMaximumUnicodeStringLength is not zero, and produced Null-terminated Unicode string
+ contains more than PcdMaximumUnicodeStringLength ASCII characters, then ASSERT().
+
+ @param StartOfBuffer APointer to the output buffer for the produced Null-terminated
+ ASCII string.
+ @param BufferSize The size, in bytes, of the output buffer specified by StartOfBuffer.
+ @param FormatString Null-terminated Unicode format string.
+ @param Marker VA_LIST marker for the variable argument list.
+
+ @return Length of the produced output buffer.
+
+**/
+UINTN
+EFIAPI
+AsciiVSPrintUnicodeFormat (
+ OUT CHAR8 *StartOfBuffer,
+ IN UINTN BufferSize,
+ IN CONST CHAR16 *FormatString,
+ IN VA_LIST Marker
+ );
+
+/**
+ Produces a Null-terminated ASCII string in an output buffer based on a Null-terminated
+ ASCII format string and variable argument list.
+
+ Produces a Null-terminated ASCII string in the output buffer specified by StartOfBuffer
+ and BufferSize.
+ The ASCII string is produced by parsing the format string specified by FormatString.
+ Arguments are pulled from the variable argument list based on the contents of the
+ format string.
+ The length of the produced output buffer is returned.
+ If BufferSize is 0, then no output buffer is produced and 0 is returned.
+
+ If BufferSize is not 0 and StartOfBuffer is NULL, then ASSERT().
+ If BufferSize is not 0 and FormatString is NULL, then ASSERT().
+ If PcdMaximumUnicodeStringLength is not zero, and FormatString contains more than
+ PcdMaximumUnicodeStringLength ASCII characters, then ASSERT().
+ If PcdMaximumUnicodeStringLength is not zero, and produced Null-terminated Unicode string
+ contains more than PcdMaximumUnicodeStringLength ASCII characters, then ASSERT().
+
+ @param StartOfBuffer APointer to the output buffer for the produced Null-terminated
+ ASCII string.
+ @param BufferSize The size, in bytes, of the output buffer specified by StartOfBuffer.
+ @param FormatString Null-terminated Unicode format string.
+
+ @return Length of the produced output buffer.
+
+**/
+UINTN
+EFIAPI
+AsciiSPrintUnicodeFormat (
+ OUT CHAR8 *StartOfBuffer,
+ IN UINTN BufferSize,
+ IN CONST CHAR16 *FormatString,
+ ...
+ );
+
+/**
+ Converts a decimal value to a Null-terminated Unicode string.
+
+ Converts the decimal number specified by Value to a Null-terminated Unicode
+ string specified by Buffer containing at most Width characters.
+ If Width is 0 then a width of MAXIMUM_VALUE_CHARACTERS is assumed.
+ The total number of characters placed in Buffer is returned.
+ If the conversion contains more than Width characters, then only the first
+ Width characters are returned, and the total number of characters
+ required to perform the conversion is returned.
+ Additional conversion parameters are specified in Flags.
+ The Flags bit LEFT_JUSTIFY is always ignored.
+ All conversions are left justified in Buffer.
+ If Width is 0, PREFIX_ZERO is ignored in Flags.
+ If COMMA_TYPE is set in Flags, then PREFIX_ZERO is ignored in Flags, and commas
+ are inserted every 3rd digit starting from the right.
+ If Value is < 0, then the fist character in Buffer is a '-'.
+ If PREFIX_ZERO is set in Flags and PREFIX_ZERO is not being ignored,
+ then Buffer is padded with '0' characters so the combination of the optional '-'
+ sign character, '0' characters, digit characters for Value, and the Null-terminator
+ add up to Width characters.
+
+ If Buffer is NULL, then ASSERT().
+ If unsupported bits are set in Flags, then ASSERT().
+ If Width >= MAXIMUM_VALUE_CHARACTERS, then ASSERT()
+
+ @param Buffer Pointer to the output buffer for the produced Null-terminated
+ Unicode string.
+ @param Flags The bitmask of flags that specify left justification, zero pad, and commas.
+ @param Value The 64-bit signed value to convert to a string.
+ @param Width The maximum number of Unicode characters to place in Buffer.
+
+ @return Total number of characters required to perform the conversion.
+
+**/
+UINTN
+EFIAPI
+UnicodeValueToString (
+ IN OUT CHAR16 *Buffer,
+ IN UINTN Flags,
+ IN INT64 Value,
+ IN UINTN Width
+ );
+
+/**
+ Converts a decimal value to a Null-terminated ASCII string.
+
+ Converts the decimal number specified by Value to a Null-terminated ASCII string
+ specified by Buffer containing at most Width characters.
+ If Width is 0 then a width of MAXIMUM_VALUE_CHARACTERS is assumed.
+ The total number of characters placed in Buffer is returned.
+ If the conversion contains more than Width characters, then only the first Width
+ characters are returned, and the total number of characters required to perform
+ the conversion is returned.
+ Additional conversion parameters are specified in Flags.
+ The Flags bit LEFT_JUSTIFY is always ignored.
+ All conversions are left justified in Buffer.
+ If Width is 0, PREFIX_ZERO is ignored in Flags.
+ If COMMA_TYPE is set in Flags, then PREFIX_ZERO is ignored in Flags, and commas
+ are inserted every 3rd digit starting from the right.
+ If Value is < 0, then the fist character in Buffer is a '-'.
+ If PREFIX_ZERO is set in Flags and PREFIX_ZERO is not being ignored, then Buffer
+ is padded with '0' characters so the combination of the optional '-'
+ sign character, '0' characters, digit characters for Value, and the
+ Null-terminator add up to Width characters.
+
+ If Buffer is NULL, then ASSERT().
+ If unsupported bits are set in Flags, then ASSERT().
+ If Width >= MAXIMUM_VALUE_CHARACTERS, then ASSERT()
+
+ @param Buffer Pointer to the output buffer for the produced Null-terminated
+ ASCII string.
+ @param Flags The bitmask of flags that specify left justification, zero pad, and commas.
+ @param Value The 64-bit signed value to convert to a string.
+ @param Width The maximum number of ASCII characters to place in Buffer.
+
+ @return Total number of characters required to perform the conversion.
+
+**/
+UINTN
+EFIAPI
+AsciiValueToString (
+ IN OUT CHAR8 *Buffer,
+ IN UINTN Flags,
+ IN INT64 Value,
+ IN UINTN Width
+ );
+
+#endif
diff --git a/Source/Include/Protocol/DevicePath.h b/Source/Include/Protocol/DevicePath.h
new file mode 100644
index 0000000..d019999
--- /dev/null
+++ b/Source/Include/Protocol/DevicePath.h
@@ -0,0 +1,94 @@
+/** @file
+ The device path protocol as defined in EFI 1.0.
+
+ The device path represents a programatic path to a device. It's the view
+ from a software point of view. It also must persist from boot to boot, so
+ it can not contain things like PCI bus numbers that change from boot to boot.
+
+ Copyright (c) 2006, Intel Corporation
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+ Module Name: DevicePath.h
+
+**/
+
+#ifndef __EFI_DEVICE_PATH_PROTOCOL_H__
+#define __EFI_DEVICE_PATH_PROTOCOL_H__
+
+//
+// Device Path protocol
+//
+#define EFI_DEVICE_PATH_PROTOCOL_GUID \
+ { \
+ 0x9576e91, 0x6d3f, 0x11d2, {0x8e, 0x39, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b } \
+ }
+
+#pragma pack(1)
+
+typedef struct {
+ UINT8 Type;
+ UINT8 SubType;
+ UINT8 Length[2];
+} EFI_DEVICE_PATH_PROTOCOL;
+
+#pragma pack()
+
+#define EFI_DP_TYPE_MASK 0x7F
+#define EFI_DP_TYPE_UNPACKED 0x80
+#define END_DEVICE_PATH_TYPE 0x7f
+
+#define EFI_END_ENTIRE_DEVICE_PATH 0xff
+#define EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE 0xff
+#define EFI_END_INSTANCE_DEVICE_PATH 0x01
+#define END_ENTIRE_DEVICE_PATH_SUBTYPE EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE
+#define END_INSTANCE_DEVICE_PATH_SUBTYPE EFI_END_INSTANCE_DEVICE_PATH
+
+#define EFI_END_DEVICE_PATH_LENGTH (sizeof (EFI_DEVICE_PATH_PROTOCOL))
+#define END_DEVICE_PATH_LENGTH EFI_END_DEVICE_PATH_LENGTH
+
+#define DP_IS_END_TYPE(a)
+#define DP_IS_END_SUBTYPE(a) (((a)->SubType == END_ENTIRE_DEVICE_PATH_SUBTYPE)
+#define DevicePathSubType(a) ((a)->SubType)
+#define IsDevicePathUnpacked(a) ((a)->Type & EFI_DP_TYPE_UNPACKED)
+
+#define EfiDevicePathNodeLength(a) (((a)->Length[0]) | ((a)->Length[1] << 8))
+#define DevicePathNodeLength(a) (EfiDevicePathNodeLength(a))
+#define EfiNextDevicePathNode(a) ((EFI_DEVICE_PATH_PROTOCOL *) (((UINT8 *) (a)) + EfiDevicePathNodeLength (a)))
+#define NextDevicePathNode(a) (EfiNextDevicePathNode(a))
+
+#define EfiDevicePathType(a) (((a)->Type) & EFI_DP_TYPE_MASK)
+#define DevicePathType(a) (EfiDevicePathType(a))
+#define EfiIsDevicePathEndType(a) (EfiDevicePathType (a) == END_DEVICE_PATH_TYPE)
+#define IsDevicePathEndType(a) (EfiIsDevicePathEndType(a))
+
+
+#define EfiIsDevicePathEndSubType(a) ((a)->SubType == EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE)
+#define IsDevicePathEndSubType(a) (EfiIsDevicePathEndSubType(a))
+#define EfiIsDevicePathEndInstanceSubType(a) ((a)->SubType == EFI_END_INSTANCE_DEVICE_PATH)
+
+#define EfiIsDevicePathEnd(a) (EfiIsDevicePathEndType (a) && EfiIsDevicePathEndSubType (a))
+#define IsDevicePathEnd(a) (EfiIsDevicePathEnd(a))
+#define EfiIsDevicePathEndInstance(a) (EfiIsDevicePathEndType (a) && EfiIsDevicePathEndInstanceSubType (a))
+
+
+#define SetDevicePathNodeLength(a,l) { \
+ (a)->Length[0] = (UINT8) (l); \
+ (a)->Length[1] = (UINT8) ((l) >> 8); \
+ }
+
+#define SetDevicePathEndNode(a) { \
+ (a)->Type = END_DEVICE_PATH_TYPE; \
+ (a)->SubType = END_ENTIRE_DEVICE_PATH_SUBTYPE; \
+ (a)->Length[0] = sizeof(EFI_DEVICE_PATH_PROTOCOL); \
+ (a)->Length[1] = 0; \
+ }
+
+extern EFI_GUID gEfiDevicePathProtocolGuid;
+
+#endif
diff --git a/Source/Include/Protocol/GuidedSectionExtraction.h b/Source/Include/Protocol/GuidedSectionExtraction.h
new file mode 100644
index 0000000..d98c56a
--- /dev/null
+++ b/Source/Include/Protocol/GuidedSectionExtraction.h
@@ -0,0 +1,102 @@
+/** @file
+ This file declares GUIDed section extraction protocol.
+
+ This interface provides a means of decoding a GUID defined encapsulation
+ section. There may be multiple different GUIDs associated with the GUIDed
+ section extraction protocol. That is, all instances of the GUIDed section
+ extraction protocol must have the same interface structure.
+
+ Copyright (c) 2006, Intel Corporation
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+ Module Name: GuidedSectionExtraction.h
+
+ @par Revision Reference:
+ This protocol is defined in Firmware Volume Specification.
+ Version 0.9
+
+**/
+
+#ifndef __GUIDED_SECTION_EXTRACTION_PROTOCOL_H__
+#define __GUIDED_SECTION_EXTRACTION_PROTOCOL_H__
+
+
+//
+// Protocol GUID definition. Each GUIDed section extraction protocol has the
+// same interface but with different GUID. All the GUIDs is defined here.
+// May add multiple GUIDs here.
+//
+#define EFI_CRC32_GUIDED_SECTION_EXTRACTION_PROTOCOL_GUID \
+ { \
+ 0xFC1BCDB0, 0x7D31, 0x49aa, {0x93, 0x6A, 0xA4, 0x60, 0x0D, 0x9D, 0xD0, 0x83 } \
+ }
+
+//
+// Forward reference for pure ANSI compatability
+//
+typedef struct _EFI_GUIDED_SECTION_EXTRACTION_PROTOCOL EFI_GUIDED_SECTION_EXTRACTION_PROTOCOL;
+
+//
+// Protocol member functions
+//
+/**
+ Processes the input section and returns the data contained therein along
+ with the authentication status.
+
+ @param This Indicates the EFI_GUIDED_SECTION_EXTRACTION_PROTOCOL instance.
+ @param InputSection Buffer containing the input GUIDed section to be processed.
+ @param OutputBuffer *OutputBuffer is allocated from boot services pool memory
+ and contains the new section stream.
+ @param OutputSize A pointer to a caller-allocated UINTN in which the size
+ of *OutputBuffer allocation is stored.
+ @param AuthenticationStatus A pointer to a caller-allocated UINT32 that
+ indicates the authentication status of the output buffer.
+
+ @retval EFI_SUCCESS The InputSection was successfully processed and the
+ section contents were returned.
+ @retval EFI_OUT_OF_RESOURCES The system has insufficient resources to
+ process the request.
+ @retval EFI_INVALID_PARAMETER The GUID in InputSection does not match
+ this instance of the GUIDed Section Extraction Protocol.
+
+**/
+
+typedef
+EFI_STATUS
+(EFIAPI *EFI_EXTRACT_GUIDED_SECTION) (
+ IN EFI_GUIDED_SECTION_EXTRACTION_PROTOCOL *This,
+ IN VOID *InputSection,
+ OUT VOID **OutputBuffer,
+ OUT UINTN *OutputSize,
+ OUT UINT32 *AuthenticationStatus
+ );
+
+//
+// Protocol definition
+//
+/**
+ @par Protocol Description:
+ If a GUID-defined section is encountered when doing section extraction,
+ the section extraction driver calls the appropriate instance of the GUIDed
+ Section Extraction Protocol to extract the section stream contained therein.
+
+ @param ExtractSection
+ Takes the GUIDed section as input and produces the section stream data.
+
+**/
+struct _EFI_GUIDED_SECTION_EXTRACTION_PROTOCOL {
+ EFI_EXTRACT_GUIDED_SECTION ExtractSection;
+};
+
+//
+// may add other GUID here
+//
+extern EFI_GUID gEfiCrc32GuidedSectionExtractionProtocolGuid;
+
+#endif
diff --git a/Source/Include/Protocol/Hii.h b/Source/Include/Protocol/Hii.h
new file mode 100644
index 0000000..ceeba1c
--- /dev/null
+++ b/Source/Include/Protocol/Hii.h
@@ -0,0 +1,1024 @@
+/** @file
+ This file defines the Human Interface Infrastructure protocol which will
+ be used by resources which want to publish IFR/Font/String data and have it
+ collected by the Configuration engine.
+
+ Copyright (c) 2006, Intel Corporation
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+ Module Name: Hii.h
+
+ @par Revision Reference:
+ This protocol is defined in HII spec 0.92.
+
+**/
+
+#ifndef __HII_H__
+#define __HII_H__
+
+
+#define EFI_HII_PROTOCOL_GUID \
+ { \
+ 0xea816d2c, 0xcee5, 0x4f02, {0x99, 0xb5, 0xd3, 0x90, 0x5c, 0xbb, 0xd0, 0x77 } \
+ }
+
+// BugBug:
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// If UGA goes away we need to put this some place. I'm not sure where?
+//
+//typedef struct {
+// UINT8 Blue;
+// UINT8 Green;
+// UINT8 Red;
+// UINT8 Reserved;
+//} EFI_UGA_PIXEL;
+
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//
+
+typedef struct _EFI_HII_PROTOCOL EFI_HII_PROTOCOL;
+
+//
+// Global definition
+//
+#define NARROW_CHAR 0xFFF0
+#define WIDE_CHAR 0xFFF1
+#define NON_BREAKING_CHAR 0xFFF2
+#define GLYPH_WIDTH 8
+#define GLYPH_HEIGHT 19
+
+#define EFI_HII_FONT 1
+#define EFI_HII_STRING 2
+#define EFI_HII_IFR 3
+#define EFI_HII_KEYBOARD 4
+#define EFI_HII_HANDLES 5
+#define EFI_HII_VARIABLE 6
+#define EFI_HII_DEVICE_PATH 7
+
+
+// References to string tokens must use this macro to enable scanning for
+// token usages.
+//
+#define STRING_TOKEN(t) t
+
+//
+// The following types are currently defined:
+//
+typedef UINT16 EFI_FORM_ID;
+typedef UINT16 EFI_FORM_LABEL;
+
+#pragma pack(1)
+
+typedef struct {
+ UINT32 Length;
+ UINT16 Type;
+} EFI_HII_PACK_HEADER;
+
+//
+// A form list consists of a large variety of structure
+// possibilities so to represent the binary blob of data
+// associated with a package of forms, we will assume a
+// pointer to a self-describing data buffer.
+//
+typedef struct {
+ EFI_HII_PACK_HEADER Header;
+} EFI_HII_IFR_PACK;
+
+typedef struct {
+ EFI_HII_PACK_HEADER Header; // Must be filled in
+ EFI_HANDLE ImageHandle; // Must be filled in
+ EFI_HANDLE DeviceHandle; // Optional
+ EFI_HANDLE ControllerHandle; // Optional
+ EFI_HANDLE CallbackHandle; // Optional
+ EFI_HANDLE COBExportHandle; // Optional
+} EFI_HII_HANDLE_PACK;
+
+//
+// ********************************************************
+// EFI_VARIABLE_CONTENTS
+// ********************************************************
+//
+typedef struct {
+ EFI_HII_PACK_HEADER Header;
+ EFI_GUID VariableGuid;
+ UINT32 VariableNameLength;
+ UINT16 VariableId;
+ //
+ // CHAR16 VariableName[]; //Null-terminated
+ //
+} EFI_HII_VARIABLE_PACK;
+
+//
+// ********************************************************
+// EFI_DEVICE_PATH_PACK
+// ********************************************************
+//
+typedef struct {
+ EFI_HII_PACK_HEADER Header;
+ //
+ // EFI_DEVICE_PATH DevicePath[];
+ //
+} EFI_HII_DEVICE_PATH_PACK;
+
+//
+// ********************************************************
+// EFI_HII_DATA_TABLE
+// ********************************************************
+//
+typedef struct {
+ EFI_HII_HANDLE HiiHandle;
+ EFI_GUID PackageGuid;
+ UINT32 DataTableSize;
+ UINT32 IfrDataOffset;
+ UINT32 StringDataOffset;
+ UINT32 VariableDataOffset;
+ UINT32 DevicePathOffset;
+ UINT32 NumberOfVariableData;
+ UINT32 NumberOfLanguages;
+ //
+ // EFI_HII_DEVICE_PATH_PACK DevicePath[];
+ // EFI_HII_VARIABLE_PACK VariableData[];
+ // EFI_HII_IFR_PACK IfrData;
+ // EFI_HII_STRING_PACK StringData[];
+ //
+} EFI_HII_DATA_TABLE;
+
+//
+// ********************************************************
+// EFI_HII_EXPORT_TABLE
+// ********************************************************
+//
+typedef struct {
+ UINT32 NumberOfHiiDataTables;
+ EFI_GUID Revision;
+ //
+ // EFI_HII_DATA_TABLE HiiDataTable[];
+ //
+} EFI_HII_EXPORT_TABLE;
+
+typedef struct {
+ BOOLEAN FormSetUpdate; // If TRUE, next variable is significant
+ EFI_PHYSICAL_ADDRESS FormCallbackHandle; // If not 0, will update Formset with this info
+ BOOLEAN FormUpdate; // If TRUE, next variable is significant
+ UINT16 FormValue; // specify which form is to be updated if FormUpdate value is TRUE.
+ STRING_REF FormTitle; // If not 0, will update Form with this info
+ UINT16 DataCount; // The number of Data entries in this structure
+ UINT8 *Data; // An array of 1+ op-codes, specified by DataCount
+} EFI_HII_UPDATE_DATA;
+
+//
+// String attributes
+//
+#define LANG_RIGHT_TO_LEFT 0x00000001
+
+//
+// A string package is used to localize strings to a particular
+// language. The package is associated with a particular driver
+// or set of drivers. Tools are used to associate tokens with
+// string references in forms and in programs. These tokens are
+// language agnostic. When paired with a language pack (directly
+// or indirectly), the string token resolves into an actual
+// UNICODE string. The NumStringPointers determines how many
+// StringPointers (offset values) there are as well as the total
+// number of Strings that are defined.
+//
+typedef struct {
+ EFI_HII_PACK_HEADER Header;
+ RELOFST LanguageNameString;
+ RELOFST PrintableLanguageName;
+ UINT32 NumStringPointers;
+ UINT32 Attributes;
+ //
+ // RELOFST StringPointers[];
+ // EFI_STRING Strings[];
+ //
+} EFI_HII_STRING_PACK;
+
+//
+// Glyph Attributes
+//
+#define EFI_GLYPH_NON_SPACING 1
+#define EFI_GLYPH_WIDE 2
+
+typedef struct {
+ CHAR16 UnicodeWeight;
+ UINT8 Attributes;
+ UINT8 GlyphCol1[GLYPH_HEIGHT];
+} EFI_NARROW_GLYPH;
+
+typedef struct {
+ CHAR16 UnicodeWeight;
+ UINT8 Attributes;
+ UINT8 GlyphCol1[GLYPH_HEIGHT];
+ UINT8 GlyphCol2[GLYPH_HEIGHT];
+ UINT8 Pad[3];
+} EFI_WIDE_GLYPH;
+
+//
+// A font list consists of a font header followed by a series
+// of glyph structures. Note that fonts are not language specific.
+//
+typedef struct {
+ EFI_HII_PACK_HEADER Header;
+ UINT16 NumberOfNarrowGlyphs;
+ UINT16 NumberOfWideGlyphs;
+} EFI_HII_FONT_PACK;
+
+//
+// The IfrData in the EFI_HII_IFR_PACK structure definition
+// is variable length, and not really part of the header. To
+// simplify from code the size of the header, define an
+// identical structure that does not include the IfrData field.
+// Then use sizeof() this new structure to determine the
+// actual size of the header.
+//
+typedef struct {
+ EFI_HII_PACK_HEADER Header;
+} EFI_HII_IFR_PACK_HEADER;
+
+//
+// pedef EFI_HII_PACK_HEADER EFI_HII_IFR_PACK_HEADER;
+//
+typedef enum {
+ EfiKeyLCtrl,
+ EfiKeyA0,
+ EfiKeyLAlt,
+ EfiKeySpaceBar,
+ EfiKeyA2,
+ EfiKeyA3,
+ EfiKeyA4,
+ EfiKeyRCtrl,
+ EfiKeyLeftArrow,
+ EfiKeyDownArrow,
+ EfiKeyRightArrow,
+ EfiKeyZero,
+ EfiKeyPeriod,
+ EfiKeyEnter,
+ EfiKeyLShift,
+ EfiKeyB0,
+ EfiKeyB1,
+ EfiKeyB2,
+ EfiKeyB3,
+ EfiKeyB4,
+ EfiKeyB5,
+ EfiKeyB6,
+ EfiKeyB7,
+ EfiKeyB8,
+ EfiKeyB9,
+ EfiKeyB10,
+ EfiKeyRshift,
+ EfiKeyUpArrow,
+ EfiKeyOne,
+ EfiKeyTwo,
+ EfiKeyThree,
+ EfiKeyCapsLock,
+ EfiKeyC1,
+ EfiKeyC2,
+ EfiKeyC3,
+ EfiKeyC4,
+ EfiKeyC5,
+ EfiKeyC6,
+ EfiKeyC7,
+ EfiKeyC8,
+ EfiKeyC9,
+ EfiKeyC10,
+ EfiKeyC11,
+ EfiKeyC12,
+ EfiKeyFour,
+ EfiKeyFive,
+ EfiKeySix,
+ EfiKeyPlus,
+ EfiKeyTab,
+ EfiKeyD1,
+ EfiKeyD2,
+ EfiKeyD3,
+ EfiKeyD4,
+ EfiKeyD5,
+ EfiKeyD6,
+ EfiKeyD7,
+ EfiKeyD8,
+ EfiKeyD9,
+ EfiKeyD10,
+ EfiKeyD11,
+ EfiKeyD12,
+ EfiKeyD13,
+ EfiKeyDel,
+ EfiKeyEnd,
+ EfiKeyPgDn,
+ EfiKeySeven,
+ EfiKeyEight,
+ EfiKeyNine,
+ EfiKeyE0,
+ EfiKeyE1,
+ EfiKeyE2,
+ EfiKeyE3,
+ EfiKeyE4,
+ EfiKeyE5,
+ EfiKeyE6,
+ EfiKeyE7,
+ EfiKeyE8,
+ EfiKeyE9,
+ EfiKeyE10,
+ EfiKeyE11,
+ EfiKeyE12,
+ EfiKeyBackSpace,
+ EfiKeyIns,
+ EfiKeyHome,
+ EfiKeyPgUp,
+ EfiKeyNLck,
+ EfiKeySlash,
+ EfiKeyAsterisk,
+ EfiKeyMinus,
+ EfiKeyEsc,
+ EfiKeyF1,
+ EfiKeyF2,
+ EfiKeyF3,
+ EfiKeyF4,
+ EfiKeyF5,
+ EfiKeyF6,
+ EfiKeyF7,
+ EfiKeyF8,
+ EfiKeyF9,
+ EfiKeyF10,
+ EfiKeyF11,
+ EfiKeyF12,
+ EfiKeyPrint,
+ EfiKeySLck,
+ EfiKeyPause
+} EFI_KEY;
+
+typedef struct {
+ EFI_KEY Key;
+ CHAR16 Unicode;
+ CHAR16 ShiftedUnicode;
+ CHAR16 AltGrUnicode;
+ CHAR16 ShiftedAltGrUnicode;
+ UINT16 Modifier;
+} EFI_KEY_DESCRIPTOR;
+
+//
+// This structure allows a sparse set of keys to be redefined
+// or a complete redefinition of the keyboard layout. Most
+// keyboards have a lot of commonality in their layouts, therefore
+// only defining those keys that need to change from the default
+// minimizes the passed in information.
+//
+// Additionally, when an update occurs, the active keyboard layout
+// will be switched to the newly updated keyboard layout. This
+// allows for situations that when a keyboard layout driver is
+// loaded as part of system initialization, the system will default
+// the keyboard behavior to the new layout.
+//
+// Each call to update the keyboard mapping should contain the
+// complete set of key descriptors to be updated, since every
+// call to the HII which contains an EFI_HII_KEYBOARD_PACK will
+// wipe the previous set of overrides. A call to
+//
+typedef struct {
+ EFI_HII_PACK_HEADER Header;
+ EFI_KEY_DESCRIPTOR *Descriptor;
+ UINT8 DescriptorCount;
+} EFI_HII_KEYBOARD_PACK;
+
+//
+// The EFI_HII_PACKAGES can contain different types of packages just
+// after the structure as inline data.
+//
+typedef struct {
+ UINTN NumberOfPackages;
+ EFI_GUID *GuidId;
+ //
+ // EFI_HII_HANDLE_PACK *HandlePack; // Only one pack.
+ // EFI_HII_IFR_PACK *IfrPack; // Only one pack.
+ // EFI_HII_FONT_PACK *FontPack[]; // Multiple packs ok
+ // EFI_HII_STRING_PACK *StringPack[]; // Multiple packs ok
+ // EFI_HII_KEYBOARD_PACK *KeyboardPack[]; // Multiple packs ok
+ //
+} EFI_HII_PACKAGES;
+
+typedef struct _EFI_HII_VARIABLE_PACK_LIST {
+ struct _EFI_HII_VARIABLE_PACK_LIST *NextVariablePack;
+ EFI_HII_VARIABLE_PACK *VariablePack;
+} EFI_HII_VARIABLE_PACK_LIST;
+
+#pragma pack()
+
+/**
+ Registers the various packs that are passed in via the Packages parameter.
+
+ @param This A pointer to the EFI_HII_PROTOCOL instance.
+
+ @param Packages A pointer to an EFI_HII_PACKAGES package instance.
+
+ @param Handle A pointer to the EFI_HII_HANDLE instance.
+
+ @retval EFI_SUCCESS Data was extracted from Packages, the database
+ was updated with the data, and Handle returned successfully.
+
+ @retval EFI_INVALID_PARAMETER The content of Packages was invalid.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_HII_NEW_PACK) (
+ IN EFI_HII_PROTOCOL *This,
+ IN EFI_HII_PACKAGES *Packages,
+ OUT EFI_HII_HANDLE *Handle
+ );
+
+/**
+ Removes a package from the HII database.
+
+ @param This A pointer to the EFI_HII_PROTOCOL instance.
+
+ @param Handle The handle that was registered to the data that is requested
+ for removal.
+
+ @retval EFI_SUCCESS The data associated with the Handle was removed
+ from the HII database.
+
+ @retval EFI_INVALID_PARAMETER The Handle was not valid.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_HII_REMOVE_PACK) (
+ IN EFI_HII_PROTOCOL *This,
+ IN EFI_HII_HANDLE Handle
+ );
+
+/**
+ Determines the handles that are currently active in the database.
+
+ @param This A pointer to the EFI_HII_PROTOCOL instance.
+
+ @param HandleBufferLength On input, a pointer to the length of the handle
+ buffer. On output, the length of the handle buffer that is required
+ for the handles found.
+
+ @param Handle An array of EFI_HII_HANDLE instances returned.
+
+ @retval EFI_SUCCESS Handle was updated successfully.
+
+ @retval EFI_BUFFER_TOO_SMALL The HandleBufferLength parameter indicates
+ that Handle is too small to support the number of handles.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_HII_FIND_HANDLES) (
+ IN EFI_HII_PROTOCOL *This,
+ IN OUT UINT16 *HandleBufferLength,
+ OUT EFI_HII_HANDLE *Handle
+ );
+
+/**
+ Exports the contents of the database into a buffer.
+
+ @param This A pointer to the EFI_HII_PROTOCOL instance.
+
+ @param Handle An EFI_HII_HANDLE that corresponds to the desired
+ handle to export. If the value is 0, the entire database will be exported.
+ In either case, the data will be exported in a format described by the
+ structure definition of EFI_HII_EXPORT_TABLE.
+
+ @param BufferSize
+ On input, a pointer to the length of the buffer. On output, the length
+ of the buffer that is required for the export data.
+
+ @param Buffer A pointer to a buffer that will contain the results of the export function.
+
+ @retval EFI_SUCCESS The buffer was successfully filled with BufferSize amount of data.
+
+ @retval EFI_BUFFER_TOO_SMALL The value in BufferSize was too small to contain the export data.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_HII_EXPORT) (
+ IN EFI_HII_PROTOCOL *This,
+ IN EFI_HII_HANDLE Handle,
+ IN OUT UINTN *BufferSize,
+ OUT VOID *Buffer
+ );
+
+/**
+ Remove any new strings that were added after the initial string export
+ for this handle.
+
+ @param This A pointer to the EFI_HII_PROTOCOL instance.
+
+ @param Handle The handle on which the string resides.
+
+ @retval EFI_SUCCESS Remove strings from the handle successfully.
+
+ @retval EFI_INVALID_PARAMETER The Handle was unknown.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_HII_RESET_STRINGS) (
+ IN EFI_HII_PROTOCOL *This,
+ IN EFI_HII_HANDLE Handle
+ );
+
+/**
+ Tests if all of the characters in a string have corresponding font characters.
+
+ @param This A pointer to the EFI_HII_PROTOCOL instance.
+
+ @param StringToTest A pointer to a Unicode string.
+
+ @param FirstMissing A pointer to an index into the string. On input,
+ the index of the first character in the StringToTest to examine. On exit,
+ the index of the first character encountered for which a glyph is unavailable.
+ If all glyphs in the string are available, the index is the index of the
+ terminator of the string.
+
+ @param GlyphBufferSize A pointer to a value. On output, if the function
+ returns EFI_SUCCESS, it contains the amount of memory that is required to
+ store the string¡¯s glyph equivalent.
+
+ @retval EFI_SUCCESS All glyphs are available. Note that an empty string
+ always returns this value.
+
+ @retval EFI_NOT_FOUND A glyph was not found for a character.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_HII_TEST_STRING) (
+ IN EFI_HII_PROTOCOL *This,
+ IN CHAR16 *StringToTest,
+ IN OUT UINT32 *FirstMissing,
+ OUT UINT32 *GlyphBufferSize
+ );
+
+/**
+ Translates a Unicode character into the corresponding font glyph.
+
+ @param This A pointer to the EFI_HII_PROTOCOL instance.
+
+ @param Source A pointer to a Unicode string.
+
+ @param Index On input, the offset into the string from which to fetch
+ the character.On successful completion, the index is updated to the first
+ character past the character(s) making up the just extracted glyph.
+
+ @param GlyphBuffer Pointer to an array where the glyphs corresponding
+ to the characters in the source may be stored. GlyphBuffer is assumed
+ to be wide enough to accept a wide glyph character.
+
+ @param BitWidth If EFI_SUCCESS was returned, the UINT16 pointed to by
+ this value is filled with the length of the glyph in pixels. It is unchanged
+ if the call was unsuccessful.
+
+ @param InternalStatus The cell pointed to by this parameter must be
+ initialized to zero prior to invoking the call the first time for any string.
+
+ @retval EFI_SUCCESS It worked.
+
+ @retval EFI_NOT_FOUND A glyph for a character was not found.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_HII_GET_GLYPH) (
+ IN EFI_HII_PROTOCOL *This,
+ IN CHAR16 *Source,
+ IN OUT UINT16 *Index,
+ OUT UINT8 **GlyphBuffer,
+ OUT UINT16 *BitWidth,
+ IN OUT UINT32 *InternalStatus
+ );
+
+/**
+ Translates a glyph into the format required for input to the Universal
+ Graphics Adapter (UGA) Block Transfer (BLT) routines.
+
+ @param This A pointer to the EFI_HII_PROTOCOL instance.
+
+ @param GlyphBuffer A pointer to the buffer that contains glyph data.
+
+ @param Foreground The foreground setting requested to be used for the
+ generated BltBuffer data.
+
+ @param Background The background setting requested to be used for the
+ generated BltBuffer data.
+
+ @param Count The entry in the BltBuffer upon which to act.
+
+ @param Width The width in bits of the glyph being converted.
+
+ @param Height The height in bits of the glyph being converted
+
+ @param BltBuffer A pointer to the buffer that contains the data that is
+ ready to be used by the UGA BLT routines.
+
+ @retval EFI_SUCCESS It worked.
+
+ @retval EFI_NOT_FOUND A glyph for a character was not found.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_HII_GLYPH_TO_BLT) (
+ IN EFI_HII_PROTOCOL *This,
+ IN UINT8 *GlyphBuffer,
+ IN EFI_UGA_PIXEL Foreground,
+ IN EFI_UGA_PIXEL Background,
+ IN UINTN Count,
+ IN UINTN Width,
+ IN UINTN Height,
+ IN OUT EFI_UGA_PIXEL *BltBuffer
+ );
+
+/**
+ Allows a new string to be added to an already existing string package.
+
+ @param This A pointer to the EFI_HII_PROTOCOL instance.
+
+ @param Pointer to a NULL-terminated string containing a single ISO 639-2
+ language identifier, indicating the language in which the string is translated.
+
+ @param Handle The handle of the language pack to which the string is to be added.
+
+ @param Reference The identifier of the string to be added. If the reference
+ value is zero, then the string will be assigned a new identifier on that
+ handle for the language specified. Otherwise, the string will be updated
+ with the NewString Value.
+
+ @param NewString The string to be added.
+
+ @retval EFI_SUCCESS The string was effectively registered.
+
+ @retval EFI_INVALID_PARAMETER The Handle was unknown.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_HII_NEW_STRING) (
+ IN EFI_HII_PROTOCOL *This,
+ IN CHAR16 *Language,
+ IN EFI_HII_HANDLE Handle,
+ IN OUT STRING_REF *Reference,
+ IN CHAR16 *NewString
+ );
+
+/**
+ Allows a program to determine the primary languages that are supported
+ on a given handle.
+
+ @param This A pointer to the EFI_HII_PROTOCOL instance.
+
+ @param Handle The handle on which the strings reside.
+
+ @param LanguageString A string allocated by GetPrimaryLanguages() that
+ contains a list of all primary languages registered on the handle.
+
+ @retval EFI_SUCCESS LanguageString was correctly returned.
+
+ @retval EFI_INVALID_PARAMETER The Handle was unknown.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_HII_GET_PRI_LANGUAGES) (
+ IN EFI_HII_PROTOCOL *This,
+ IN EFI_HII_HANDLE Handle,
+ OUT EFI_STRING *LanguageString
+ );
+
+/**
+ Allows a program to determine which secondary languages are supported
+ on a given handle for a given primary language.
+
+ @param This A pointer to the EFI_HII_PROTOCOL instance.
+
+ @param Handle The handle on which the strings reside.
+
+ @param PrimaryLanguage Pointer to a NULL-terminated string containing a single
+ ISO 639-2 language identifier, indicating the primary language.
+
+ @param LanguageString A string allocated by GetSecondaryLanguages()
+ containing a list of all secondary languages registered on the handle.
+
+ @retval EFI_SUCCESS LanguageString was correctly returned.
+
+ @retval EFI_INVALID_PARAMETER The Handle was unknown.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_HII_GET_SEC_LANGUAGES) (
+ IN EFI_HII_PROTOCOL *This,
+ IN EFI_HII_HANDLE Handle,
+ IN CHAR16 *PrimaryLanguage,
+ OUT EFI_STRING *LanguageString
+ );
+
+/**
+ Extracts a string from a package already registered with the EFI HII database.
+
+ @param This A pointer to the EFI_HII_PROTOCOL instance.
+
+ @param Handle The handle on which the string resides.
+
+ @param Token The string token assigned to the string.
+
+ @param Raw If TRUE, the string is returned unedited in the internal
+ storage format described above. If false, the string returned is edited
+ by replacing <cr> with <space> and by removing special characters such
+ as the <wide> prefix.
+
+ @param LanguageString Pointer to a NULL-terminated string containing a
+ single ISO 639-2 language identifier, indicating the language to print.
+ If the LanguageString is empty (starts with a NULL), the default system
+ language will be used to determine the language.
+
+ @param BufferLength Length of the StringBuffer.
+
+ @param StringBuffer The buffer designed to receive the characters in the string.
+
+ @retval EFI_SUCCESS StringBuffer is filled with a NULL-terminated string.
+
+ @retval EFI_INVALID_PARAMETER The handle or string token is unknown.
+
+ @retval EFI_BUFFER_TOO_SMALL The buffer provided was not large enough to
+ allow the entire string to be stored.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_HII_GET_STRING) (
+ IN EFI_HII_PROTOCOL *This,
+ IN EFI_HII_HANDLE Handle,
+ IN STRING_REF Token,
+ IN BOOLEAN Raw,
+ IN CHAR16 *LanguageString,
+ IN OUT UINTN *BufferLength,
+ OUT EFI_STRING StringBuffer
+ );
+
+/**
+ Allows a program to extract a part of a string of not more than a given width.
+
+ @param This A pointer to the EFI_HII_PROTOCOL instance.
+
+ @param Handle The handle on which the string resides.
+
+ @param Token The string token assigned to the string.
+
+ @param Index On input, the offset into the string where the line is to start.
+ On output, the index is updated to point to beyond the last character returned
+ in the call.
+
+ @param LineWidth The maximum width of the line in units of narrow glyphs.
+
+ @param LanguageString Pointer to a NULL-terminated string containing a
+ single ISO 639-2 language identifier, indicating the language to print.
+
+ @param BufferLength Pointer to the length of the StringBuffer.
+
+ @param StringBuffer The buffer designed to receive the characters in the string.
+
+ @retval EFI_SUCCESS StringBuffer filled with characters that will fit on the line.
+
+ @retval EFI_NOT_FOUND The font glyph for at least one of the characters in
+ the string is not in the font database.
+
+ @retval EFI_BUFFER_TOO_SMALL The buffer provided was not large enough
+ to allow the entire string to be stored.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_HII_GET_LINE) (
+ IN EFI_HII_PROTOCOL *This,
+ IN EFI_HII_HANDLE Handle,
+ IN STRING_REF Token,
+ IN OUT UINT16 *Index,
+ IN UINT16 LineWidth,
+ IN CHAR16 *LanguageString,
+ IN OUT UINT16 *BufferLength,
+ OUT EFI_STRING StringBuffer
+ );
+
+/**
+ Allows a program to extract a form or form package that has previously
+ been registered with the HII database.
+
+ @param This A pointer to the EFI_HII_PROTOCOL instance.
+
+ @param Handle Handle on which the form resides.
+
+ @param FormId The ID of the form to return. If the ID is zero,
+ the entire form package is returned.
+
+ @param BufferLength On input, the length of the Buffer. On output,
+ the length of the returned buffer,
+
+ @param Buffer The buffer designed to receive the form(s).
+
+ @retval EFI_SUCCESS Buffer filled with the requested forms. BufferLength
+ was updated.
+
+ @retval EFI_INVALID_PARAMETER The handle is unknown.
+
+ @retval EFI_NOT_FOUND A form on the requested handle cannot be found with
+ the requested FormId.
+
+ @retval EFI_BUFFER_TOO_SMALL The buffer provided was not large enough
+ to allow the form to be stored.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_HII_GET_FORMS) (
+ IN EFI_HII_PROTOCOL *This,
+ IN EFI_HII_HANDLE Handle,
+ IN EFI_FORM_ID FormId,
+ IN OUT UINTN *BufferLength,
+ OUT UINT8 *Buffer
+ );
+
+/**
+ Extracts the defaults that are associated with a given handle in the HII database.
+
+ @param This A pointer to the EFI_HII_PROTOCOL instance.
+
+ @param Handle The HII handle from which will have default data retrieved.
+
+ @param DefaultMask The mask used to specify some type of default override when extracting
+ the default image data.
+
+ @param VariablePackList A indirect pointer to the first entry of a link list with
+ type EFI_HII_VARIABLE_PACK_LIST.
+
+ @retval EFI_SUCCESS The VariablePackList was populated with the appropriate
+ default setting data.
+
+ @retval EFI_NOT_FOUND The IFR does not have any explicit or default map(s).
+
+ @retval EFI_INVALID_PARAMETER The HII database entry associated with Handle
+ contain invalid data.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_HII_GET_DEFAULT_IMAGE) (
+ IN EFI_HII_PROTOCOL *This,
+ IN EFI_HII_HANDLE Handle,
+ IN UINTN DefaultMask,
+ OUT EFI_HII_VARIABLE_PACK_LIST **VariablePackList
+ );
+
+/**
+ Allows the caller to update a form or form package that has previously been
+ registered with the EFI HII database.
+
+ @param This A pointer to the EFI_HII_PROTOCOL instance.
+
+ @param Handle Handle of the package where the form to be updated resides.
+
+ @param Label The label inside the form package where the update is to take place.
+
+ @param AddData If TRUE, adding data at a given Label; otherwise,
+ if FALSE, removing data at a given Label.
+
+ @param Data The buffer containing the new tags to insert after the Label
+
+ @retval EFI_SUCCESS The form was updated with the new tags.
+
+ @retval EFI_INVALID_PARAMETER The buffer for the buffer length does not
+ contain an integral number of tags.
+
+ @retval EFI_NOT_FOUND The Handle, Label, or FormId was not found.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_HII_UPDATE_FORM) (
+ IN EFI_HII_PROTOCOL *This,
+ IN EFI_HII_HANDLE Handle,
+ IN EFI_FORM_LABEL Label,
+ IN BOOLEAN AddData,
+ IN EFI_HII_UPDATE_DATA *Data
+ );
+
+/**
+ Retrieves the current keyboard layout.
+
+ @param This A pointer to the EFI_HII_PROTOCOL instance.
+
+ @param DescriptorCount A pointer to the number of Descriptor entries being
+ described in the keyboard layout being retrieved.
+
+ @param Descriptor A pointer to a buffer containing an array of EFI_KEY_DESCRIPTOR
+ entries. Each entry will reflect the definition of a specific physical key.
+
+ @retval EFI_SUCCESS The keyboard layout was retrieved successfully.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_HII_GET_KEYBOARD_LAYOUT) (
+ IN EFI_HII_PROTOCOL *This,
+ OUT UINT16 *DescriptorCount,
+ OUT EFI_KEY_DESCRIPTOR *Descriptor
+ );
+
+/**
+ @par Protocol Description:
+ The HII Protocol manages the HII database, which is a repository for data
+ having to do with fonts, strings, forms, keyboards, and other future human
+ interface items.
+
+ @param NewPack
+ Extracts the various packs from a package list.
+
+ @param RemovePack
+ Removes a package from the HII database.
+
+ @param FindHandles
+ Determines the handles that are currently active in the database.
+
+ @param ExportDatabase
+ Export the entire contents of the database to a buffer.
+
+ @param TestString
+ Tests if all of the characters in a string have corresponding font characters.
+
+ @param GetGlyph
+ Translates a Unicode character into the corresponding font glyph.
+
+ @param GlyphToBlt
+ Converts a glyph value into a format that is ready for a UGA BLT command.
+
+ @param NewString
+ Allows a new string to be added to an already existing string package.
+
+ @param GetPrimaryLanguages
+ Allows a program to determine the primary languages that are supported
+ on a given handle.
+
+ @param GetSecondaryLanguages
+ Allows a program to determine which secondary languages are supported
+ on a given handle for a given primary language.
+
+ @param GetString
+ Extracts a string from a package that is already registered with the
+ EFI HII database.
+
+ @param ResetString
+ Remove any new strings that were added after the initial string export
+ for this handle.
+
+ @param GetLine
+ Allows a program to extract a part of a string of not more than a given width.
+
+ @param GetForms
+ Allows a program to extract a form or form package that has been previously registered.
+
+ @param GetDefaultImage
+ Allows a program to extract the nonvolatile image that represents the default storage image.
+
+ @param UpdateForm
+ Allows a program to update a previously registered form.
+
+ @param GetKeyboardLayout
+ Allows a program to extract the current keyboard layout.
+
+**/
+struct _EFI_HII_PROTOCOL {
+ EFI_HII_NEW_PACK NewPack;
+ EFI_HII_REMOVE_PACK RemovePack;
+ EFI_HII_FIND_HANDLES FindHandles;
+ EFI_HII_EXPORT ExportDatabase;
+
+ EFI_HII_TEST_STRING TestString;
+ EFI_HII_GET_GLYPH GetGlyph;
+ EFI_HII_GLYPH_TO_BLT GlyphToBlt;
+
+ EFI_HII_NEW_STRING NewString;
+ EFI_HII_GET_PRI_LANGUAGES GetPrimaryLanguages;
+ EFI_HII_GET_SEC_LANGUAGES GetSecondaryLanguages;
+ EFI_HII_GET_STRING GetString;
+ EFI_HII_RESET_STRINGS ResetStrings;
+ EFI_HII_GET_LINE GetLine;
+ EFI_HII_GET_FORMS GetForms;
+ EFI_HII_GET_DEFAULT_IMAGE GetDefaultImage;
+ EFI_HII_UPDATE_FORM UpdateForm;
+
+ EFI_HII_GET_KEYBOARD_LAYOUT GetKeyboardLayout;
+};
+
+extern EFI_GUID gEfiHiiProtocolGuid;
+
+#endif
diff --git a/Source/Include/Protocol/UgaDraw.h b/Source/Include/Protocol/UgaDraw.h
new file mode 100644
index 0000000..5586bdf
--- /dev/null
+++ b/Source/Include/Protocol/UgaDraw.h
@@ -0,0 +1,168 @@
+/** @file
+ UGA Draw protocol from the EFI 1.1 specification.
+
+ Abstraction of a very simple graphics device.
+
+ Copyright (c) 2006, Intel Corporation
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+ Module Name: UgaDraw.h
+
+**/
+
+#ifndef __UGA_DRAW_H__
+#define __UGA_DRAW_H__
+
+#define EFI_UGA_DRAW_PROTOCOL_GUID \
+ { \
+ 0x982c298b, 0xf4fa, 0x41cb, {0xb8, 0x38, 0x77, 0xaa, 0x68, 0x8f, 0xb8, 0x39 } \
+ }
+
+typedef struct _EFI_UGA_DRAW_PROTOCOL EFI_UGA_DRAW_PROTOCOL;
+
+/**
+ Return the current video mode information.
+
+ @param This Protocol instance pointer.
+ @param HorizontalResolution Current video horizontal resolution in pixels
+ @param VerticalResolution Current video vertical resolution in pixels
+ @param ColorDepth Current video color depth in bits per pixel
+ @param RefreshRate Current video refresh rate in Hz.
+
+ @retval EFI_SUCCESS Mode information returned.
+ @retval EFI_NOT_STARTED Video display is not initialized. Call SetMode ()
+ @retval EFI_INVALID_PARAMETER One of the input args was NULL.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_UGA_DRAW_PROTOCOL_GET_MODE) (
+ IN EFI_UGA_DRAW_PROTOCOL *This,
+ OUT UINT32 *HorizontalResolution,
+ OUT UINT32 *VerticalResolution,
+ OUT UINT32 *ColorDepth,
+ OUT UINT32 *RefreshRate
+ )
+;
+
+/**
+ Return the current video mode information.
+
+ @param This Protocol instance pointer.
+ @param HorizontalResolution Current video horizontal resolution in pixels
+ @param VerticalResolution Current video vertical resolution in pixels
+ @param ColorDepth Current video color depth in bits per pixel
+ @param RefreshRate Current video refresh rate in Hz.
+
+ @retval EFI_SUCCESS Mode information returned.
+ @retval EFI_NOT_STARTED Video display is not initialized. Call SetMode ()
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_UGA_DRAW_PROTOCOL_SET_MODE) (
+ IN EFI_UGA_DRAW_PROTOCOL *This,
+ IN UINT32 HorizontalResolution,
+ IN UINT32 VerticalResolution,
+ IN UINT32 ColorDepth,
+ IN UINT32 RefreshRate
+ )
+;
+
+typedef struct {
+ UINT8 Blue;
+ UINT8 Green;
+ UINT8 Red;
+ UINT8 Reserved;
+} EFI_UGA_PIXEL;
+
+typedef union {
+ EFI_UGA_PIXEL Pixel;
+ UINT32 Raw;
+} EFI_UGA_PIXEL_UNION;
+
+typedef enum {
+ EfiUgaVideoFill,
+ EfiUgaVideoToBltBuffer,
+ EfiUgaBltBufferToVideo,
+ EfiUgaVideoToVideo,
+ EfiUgaBltMax
+} EFI_UGA_BLT_OPERATION;
+
+/**
+ Type specifying a pointer to a function to perform an UGA Blt operation.
+
+ The following table defines actions for BltOperations:
+
+ <B>EfiUgaVideoFill</B> - Write data from the BltBuffer pixel (SourceX, SourceY)
+ directly to every pixel of the video display rectangle
+ (DestinationX, DestinationY) (DestinationX + Width, DestinationY + Height).
+ Only one pixel will be used from the BltBuffer. Delta is NOT used.
+
+ <B>EfiUgaVideoToBltBuffer</B> - Read data from the video display rectangle
+ (SourceX, SourceY) (SourceX + Width, SourceY + Height) and place it in
+ the BltBuffer rectangle (DestinationX, DestinationY )
+ (DestinationX + Width, DestinationY + Height). If DestinationX or
+ DestinationY is not zero then Delta must be set to the length in bytes
+ of a row in the BltBuffer.
+
+ <B>EfiUgaBltBufferToVideo</B> - Write data from the BltBuffer rectangle
+ (SourceX, SourceY) (SourceX + Width, SourceY + Height) directly to the
+ video display rectangle (DestinationX, DestinationY)
+ (DestinationX + Width, DestinationY + Height). If SourceX or SourceY is
+ not zero then Delta must be set to the length in bytes of a row in the
+ BltBuffer.
+
+ <B>EfiUgaVideoToVideo</B> - Copy from the video display rectangle (SourceX, SourceY)
+ (SourceX + Width, SourceY + Height) .to the video display rectangle
+ (DestinationX, DestinationY) (DestinationX + Width, DestinationY + Height).
+ The BltBuffer and Delta are not used in this mode.
+
+
+ @param[in] This - Protocol instance pointer.
+ @param[in] BltBuffer - Buffer containing data to blit into video buffer. This
+ buffer has a size of Width*Height*sizeof(EFI_UGA_PIXEL)
+ @param[in] BltOperation - Operation to perform on BlitBuffer and video memory
+ @param[in] SourceX - X coordinate of source for the BltBuffer.
+ @param[in] SourceY - Y coordinate of source for the BltBuffer.
+ @param[in] DestinationX - X coordinate of destination for the BltBuffer.
+ @param[in] DestinationY - Y coordinate of destination for the BltBuffer.
+ @param[in] Width - Width of rectangle in BltBuffer in pixels.
+ @param[in] Height - Hight of rectangle in BltBuffer in pixels.
+ @param[in] Delta - OPTIONAL
+
+ @retval EFI_SUCCESS - The Blt operation completed.
+ @retval EFI_INVALID_PARAMETER - BltOperation is not valid.
+ @retval EFI_DEVICE_ERROR - A hardware error occured writting to the video buffer.
+
+--*/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_UGA_DRAW_PROTOCOL_BLT) (
+ IN EFI_UGA_DRAW_PROTOCOL * This,
+ IN EFI_UGA_PIXEL * BltBuffer, OPTIONAL
+ IN EFI_UGA_BLT_OPERATION BltOperation,
+ IN UINTN SourceX,
+ IN UINTN SourceY,
+ IN UINTN DestinationX,
+ IN UINTN DestinationY,
+ IN UINTN Width,
+ IN UINTN Height,
+ IN UINTN Delta OPTIONAL
+ );
+
+struct _EFI_UGA_DRAW_PROTOCOL {
+ EFI_UGA_DRAW_PROTOCOL_GET_MODE GetMode;
+ EFI_UGA_DRAW_PROTOCOL_SET_MODE SetMode;
+ EFI_UGA_DRAW_PROTOCOL_BLT Blt;
+};
+
+extern EFI_GUID gEfiUgaDrawProtocolGuid;
+
+#endif
diff --git a/Source/Include/X64/ProcessorBind.h b/Source/Include/X64/ProcessorBind.h
new file mode 100644
index 0000000..f865ce8
--- /dev/null
+++ b/Source/Include/X64/ProcessorBind.h
@@ -0,0 +1,193 @@
+/** @file
+ Processor or Compiler specific defines and types x64 (Intel(r) EM64T, AMD64).
+
+ Copyright (c) 2006, Intel Corporation
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+ Module Name: ProcessorBind.h
+
+**/
+
+#ifndef __PROCESSOR_BIND_H__
+#define __PROCESSOR_BIND_H__
+
+//
+// Define the processor type so other code can make processor based choices
+//
+#define MDE_CPU_X64
+
+
+//
+// Make sure we are useing the correct packing rules per EFI specification
+//
+#pragma pack()
+
+
+#if _MSC_EXTENSIONS
+
+//
+// Disable warning that make it impossible to compile at /W4
+// This only works for Microsoft* tools
+//
+
+//
+// Disabling bitfield type checking warnings.
+//
+#pragma warning ( disable : 4214 )
+
+//
+// Disabling the unreferenced formal parameter warnings.
+//
+#pragma warning ( disable : 4100 )
+
+//
+// Disable slightly different base types warning as CHAR8 * can not be set
+// to a constant string.
+//
+#pragma warning ( disable : 4057 )
+
+//
+// ASSERT(FALSE) or while (TRUE) are legal constructes so supress this warning
+//
+#pragma warning ( disable : 4127 )
+
+
+#endif
+
+
+#if (__STDC_VERSION__ < 199901L)
+ //
+ // No ANSI C 2000 stdint.h integer width declarations, so define equivalents
+ //
+
+ #if _MSC_EXTENSIONS
+
+
+ //
+ // use Microsoft C complier dependent interger width types
+ //
+ typedef unsigned __int64 UINT64;
+ typedef __int64 INT64;
+ typedef unsigned __int32 UINT32;
+ typedef __int32 INT32;
+ typedef unsigned short UINT16;
+ typedef unsigned short CHAR16;
+ typedef short INT16;
+ typedef unsigned char BOOLEAN;
+ typedef unsigned char UINT8;
+ typedef char CHAR8;
+ typedef char INT8;
+ #else
+ #ifdef _EFI_P64
+ //
+ // P64 - is Intel Itanium(TM) speak for pointers being 64-bit and longs and ints
+ // are 32-bits
+ //
+ typedef unsigned long long UINT64;
+ typedef long long INT64;
+ typedef unsigned int UINT32;
+ typedef int INT32;
+ typedef unsigned short CHAR16;
+ typedef unsigned short UINT16;
+ typedef short INT16;
+ typedef unsigned char BOOLEAN;
+ typedef unsigned char UINT8;
+ typedef char CHAR8;
+ typedef char INT8;
+ #else
+ //
+ // Assume LP64 - longs and pointers are 64-bit. Ints are 32-bit.
+ //
+ typedef unsigned long UINT64;
+ typedef long INT64;
+ typedef unsigned int UINT32;
+ typedef int INT32;
+ typedef unsigned short UINT16;
+ typedef unsigned short CHAR16;
+ typedef short INT16;
+ typedef unsigned char BOOLEAN;
+ typedef unsigned char UINT8;
+ typedef char CHAR8;
+ typedef char INT8;
+ #endif
+ #endif
+
+ #define UINT8_MAX 0xff
+
+#else
+ //
+ // Use ANSI C 2000 stdint.h integer width declarations
+ //
+ #include <stdint.h>
+ typedef uint8_t BOOLEAN;
+ typedef int8_t INT8;
+ typedef uint8_t UINT8;
+ typedef int16_t INT16;
+ typedef uint16_t UINT16;
+ typedef int32_t INT32;
+ typedef uint32_t UINT32;
+ typedef int64_t INT64;
+ typedef uint64_t UINT64;
+ typedef char CHAR8;
+ typedef uint16_t CHAR16;
+
+#endif
+
+typedef UINT64 UINTN;
+typedef INT64 INTN;
+
+
+//
+// Processor specific defines
+//
+#define MAX_BIT 0x8000000000000000
+#define MAX_2_BITS 0xC000000000000000
+
+//
+// Maximum legal Itanium-based address
+//
+#define MAX_ADDRESS 0xFFFFFFFFFFFFFFFF
+
+//
+// Modifier to ensure that all protocol member functions and EFI intrinsics
+// use the correct C calling convention. All protocol member functions and
+// EFI intrinsics are required to modify thier member functions with EFIAPI.
+//
+#if _MSC_EXTENSIONS
+ ///
+ /// Define the standard calling convention reguardless of optimization level.
+ /// __cdecl is Microsoft* specific C extension.
+ ///
+ #define EFIAPI __cdecl
+#elif __GNUC__
+ ///
+ /// Define the standard calling convention reguardless of optimization level.
+ /// efidecl is an extension to GCC that supports the differnece between x64
+ /// GCC ABI and x64 Microsoft* ABI. EFI is closer to the Microsoft* ABI and
+ /// EFIAPI makes sure the right ABI is used for public interfaces.
+ /// eficecl is a work in progress and we do not yet have the compiler
+ ///
+ #define EFIAPI
+#else
+ #define EFIAPI
+#endif
+
+//
+// The Microsoft* C compiler can removed references to unreferenced data items
+// if the /OPT:REF linker option is used. We defined a macro as this is a
+// a non standard extension
+//
+#if _MSC_EXTENSIONS
+ #define GLOBAL_REMOVE_IF_UNREFERENCED __declspec(selectany)
+#else
+ #define GLOBAL_REMOVE_IF_UNREFERENCED
+#endif
+
+#endif
+
diff --git a/Source/MakeDeps/MakeDeps.c b/Source/MakeDeps/MakeDeps.c
new file mode 100755
index 0000000..3943df0
--- /dev/null
+++ b/Source/MakeDeps/MakeDeps.c
@@ -0,0 +1,1284 @@
+/*++
+
+Copyright (c) 2004, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ MakeDeps.c
+
+Abstract:
+
+ Recursively scan source files to find include files and emit them to
+ create dependency lists.
+
+--*/
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+
+#include <Common/UefiBaseTypes.h>
+
+#include "EfiUtilityMsgs.h"
+#include "CommonLib.h"
+
+//
+// Structure to maintain a linked list of strings
+//
+typedef struct _STRING_LIST {
+ struct _STRING_LIST *Next;
+ char *Str;
+} STRING_LIST;
+
+#define UTILITY_NAME "MakeDeps"
+
+#define MAX_LINE_LEN 2048
+#define MAX_PATH 2048
+#define START_NEST_DEPTH 1
+#define MAX_NEST_DEPTH 1000 // just in case we get in an endless loop.
+//
+// Define the relative paths used by the special #include macros
+//
+#define PROTOCOL_DIR_PATH "Protocol/"
+#define GUID_DIR_PATH "Guid/"
+#define ARCH_PROTOCOL_DIR_PATH "ArchProtocol/"
+#define PPI_PROTOCOL_DIR_PATH "Ppi/"
+
+//
+// Use this structure to keep track of all the special #include forms
+//
+typedef struct {
+ INT8 *IncludeMacroName;
+ INT8 *PathName;
+} INCLUDE_MACRO_CONVERSION;
+
+//
+// This data is used to convert #include macros like:
+// #include EFI_PROTOCOL_DEFINITION(xxx)
+// into
+// #include Protocol/xxx/xxx.h
+//
+static const INCLUDE_MACRO_CONVERSION mMacroConversion[] = {
+ "EFI_PROTOCOL_DEFINITION",
+ PROTOCOL_DIR_PATH,
+ "EFI_GUID_DEFINITION",
+ GUID_DIR_PATH,
+ "EFI_ARCH_PROTOCOL_DEFINITION",
+ ARCH_PROTOCOL_DIR_PATH,
+ "EFI_PROTOCOL_PRODUCER",
+ PROTOCOL_DIR_PATH,
+ "EFI_PROTOCOL_CONSUMER",
+ PROTOCOL_DIR_PATH,
+ "EFI_PROTOCOL_DEPENDENCY",
+ PROTOCOL_DIR_PATH,
+ "EFI_ARCH_PROTOCOL_PRODUCER",
+ ARCH_PROTOCOL_DIR_PATH,
+ "EFI_ARCH_PROTOCOL_CONSUMER",
+ ARCH_PROTOCOL_DIR_PATH,
+ "EFI_ARCH_PROTOCOL_DEPENDENCY",
+ ARCH_PROTOCOL_DIR_PATH,
+ "EFI_PPI_DEFINITION",
+ PPI_PROTOCOL_DIR_PATH,
+ "EFI_PPI_PRODUCER",
+ PPI_PROTOCOL_DIR_PATH,
+ "EFI_PPI_CONSUMER",
+ PPI_PROTOCOL_DIR_PATH,
+ "EFI_PPI_DEPENDENCY",
+ PPI_PROTOCOL_DIR_PATH,
+ NULL,
+ NULL
+};
+
+typedef struct _SYMBOL {
+ struct _SYMBOL *Next;
+ INT8 *Name;
+ INT8 *Value;
+} SYMBOL;
+
+//
+// Here's all our globals. We need a linked list of include paths, a linked
+// list of source files, a linked list of subdirectories (appended to each
+// include path when searching), and flags to keep track of command-line options.
+//
+static struct {
+ STRING_LIST *IncludePaths; // all include paths to search
+ STRING_LIST *SourceFiles; // all source files to parse
+ STRING_LIST *SubDirs; // appended to each include path when searching
+ SYMBOL *SymbolTable; // for replacement strings
+ FILE *OutFptr; // output dependencies to this file
+ BOOLEAN Verbose; // for more detailed output
+ BOOLEAN IgnoreNotFound; // no warnings if files not found
+ BOOLEAN QuietMode; // -q - don't print missing file warnings
+ BOOLEAN NoSystem; // don't process #include <system> files
+ BOOLEAN NeverFail; // always return success
+ BOOLEAN NoDupes; // to not list duplicate dependency files (for timing purposes)
+ BOOLEAN UseSumDeps; // use summary dependency files if found
+ INT8 TargetFileName[MAX_PATH]; // target object filename
+ INT8 SumDepsPath[MAX_PATH]; // path to summary files
+ INT8 *OutFileName; // -o option
+} mGlobals;
+
+static
+STATUS
+ProcessFile (
+ INT8 *TargetFileName,
+ INT8 *FileName,
+ UINT32 NestDepth,
+ STRING_LIST *ProcessedFiles
+ );
+
+static
+FILE *
+FindFile (
+ INT8 *FileName,
+ UINT32 FileNameLen
+ );
+
+static
+void
+PrintDependency (
+ INT8 *Target,
+ INT8 *DependentFile
+ );
+
+static
+void
+ReplaceSymbols (
+ INT8 *Str,
+ UINT32 StrSize
+ );
+
+static
+STATUS
+ProcessArgs (
+ int Argc,
+ char *Argv[]
+ );
+
+static
+void
+Usage (
+ VOID
+ );
+
+static
+void
+FreeLists (
+ VOID
+ );
+
+int
+main (
+ int Argc,
+ char *Argv[]
+ )
+/*++
+
+Routine Description:
+
+ Call the routine to parse the command-line options, then process each file
+ to build dependencies.
+
+Arguments:
+
+ Argc - Standard C main() argc.
+ Argv - Standard C main() argv.
+
+Returns:
+
+ 0 if successful
+ nonzero otherwise
+
+--*/
+{
+ STRING_LIST *File;
+ STRING_LIST ProcessedFiles;
+ STRING_LIST *TempList;
+ STATUS Status;
+ INT8 *Cptr;
+ INT8 TargetFileName[MAX_PATH];
+
+ SetUtilityName (UTILITY_NAME);
+ //
+ // Process the command-line arguments
+ //
+ Status = ProcessArgs (Argc, Argv);
+ if (Status != STATUS_SUCCESS) {
+ return STATUS_ERROR;
+ }
+ //
+ // Go through the list of source files and process each.
+ //
+ memset (&ProcessedFiles, 0, sizeof (STRING_LIST));
+ File = mGlobals.SourceFiles;
+ while (File != NULL) {
+ //
+ // Clear out our list of processed files
+ //
+ TempList = ProcessedFiles.Next;
+ while (ProcessedFiles.Next != NULL) {
+ TempList = ProcessedFiles.Next->Next;
+ free (ProcessedFiles.Next->Str);
+ free (ProcessedFiles.Next);
+ ProcessedFiles.Next = TempList;
+ }
+ //
+ // Replace filename extension with ".obj" if they did not
+ // specifically specify the target file
+ //
+ if (mGlobals.TargetFileName[0] == 0) {
+ strcpy (TargetFileName, File->Str);
+ //
+ // Find the .extension
+ //
+ for (Cptr = TargetFileName + strlen (TargetFileName) - 1;
+ (*Cptr != '\\' && *Cptr != '/') && (Cptr > TargetFileName) && (*Cptr != '.');
+ Cptr--
+ )
+ ;
+ if (Cptr == TargetFileName) {
+ Error (NULL, 0, 0, File->Str, "could not locate extension in filename");
+ goto Finish;
+ }
+ //
+ // Tack on the ".obj"
+ //
+ strcpy (Cptr, ".obj");
+ } else {
+ //
+ // Copy the target filename they specified
+ //
+ strcpy (TargetFileName, mGlobals.TargetFileName);
+ }
+
+ Status = ProcessFile (TargetFileName, File->Str, START_NEST_DEPTH, &ProcessedFiles);
+ if (Status != STATUS_SUCCESS) {
+ goto Finish;
+ }
+
+ File = File->Next;
+ }
+
+Finish:
+ //
+ // Free up memory
+ //
+ FreeLists ();
+ //
+ // Free up our processed files list
+ //
+ TempList = ProcessedFiles.Next;
+ while (ProcessedFiles.Next != NULL) {
+ TempList = ProcessedFiles.Next->Next;
+ free (ProcessedFiles.Next->Str);
+ free (ProcessedFiles.Next);
+ ProcessedFiles.Next = TempList;
+ }
+ //
+ // Close our output file
+ //
+ if ((mGlobals.OutFptr != stdout) && (mGlobals.OutFptr != NULL)) {
+ fprintf(mGlobals.OutFptr, "\t\n"); // file ending flag
+ fclose (mGlobals.OutFptr);
+ }
+
+ if (mGlobals.NeverFail) {
+ return STATUS_SUCCESS;
+ }
+ //
+ // If any errors, then delete our output so that it will get created
+ // again on a rebuild.
+ //
+ if ((GetUtilityStatus () == STATUS_ERROR) && (mGlobals.OutFileName != NULL)) {
+ remove (mGlobals.OutFileName);
+ }
+
+ return GetUtilityStatus ();
+}
+
+static
+STATUS
+ProcessFile (
+ INT8 *TargetFileName,
+ INT8 *FileName,
+ UINT32 NestDepth,
+ STRING_LIST *ProcessedFiles
+ )
+/*++
+
+Routine Description:
+
+ Given a source file name, open the file and parse all #include lines.
+
+Arguments:
+
+ TargetFileName - name of the usually .obj target
+ FileName - name of the file to process
+ NestDepth - how deep we're nested in includes
+ ProcessedFiles - list of processed files.
+
+Returns:
+
+ standard status.
+
+--*/
+{
+ FILE *Fptr;
+ INT8 Line[MAX_LINE_LEN];
+ INT8 *Cptr;
+ INT8 *EndPtr;
+ INT8 *SaveCptr;
+ INT8 EndChar;
+ INT8 FileNameCopy[MAX_PATH];
+ INT8 MacroIncludeFileName[MAX_LINE_LEN];
+ INT8 SumDepsFile[MAX_PATH];
+ STATUS Status;
+ UINT32 Index;
+ UINT32 LineNum;
+ STRING_LIST *ListPtr;
+
+ Status = STATUS_SUCCESS;
+ Fptr = NULL;
+ //
+ // Print the file being processed. Indent so you can tell the include nesting
+ // depth.
+ //
+ if (mGlobals.Verbose) {
+ fprintf (stdout, "%*cProcessing file '%s'\n", NestDepth * 2, ' ', FileName);
+ }
+ //
+ // If we're using summary dependency files, and a matching .dep file is
+ // found for this file, then just emit the summary dependency file as
+ // a dependency and return.
+ //
+ if (mGlobals.UseSumDeps) {
+ strcpy (SumDepsFile, mGlobals.SumDepsPath);
+ strcat (SumDepsFile, FileName);
+ for (Cptr = SumDepsFile + strlen (SumDepsFile) - 1;
+ (*Cptr != '\\' && *Cptr != '/') && (Cptr > SumDepsFile) && (*Cptr != '.');
+ Cptr--
+ )
+ ;
+ if (*Cptr == '.') {
+ strcpy (Cptr, ".dep");
+ } else {
+ strcat (SumDepsFile, ".dep");
+ }
+ //
+ // See if the summary dep file exists. Could use _stat() function, but
+ // it's less portable.
+ //
+ if ((Fptr = fopen (SumDepsFile, "r")) != NULL) {
+ PrintDependency (TargetFileName, SumDepsFile);
+ return STATUS_SUCCESS;
+ }
+ }
+ //
+ // If we're not doing duplicates, and we've already seen this filename,
+ // then return
+ //
+ if (mGlobals.NoDupes) {
+ for (ListPtr = ProcessedFiles->Next; ListPtr != NULL; ListPtr = ListPtr->Next) {
+ if (stricmp (FileName, ListPtr->Str) == 0) {
+ break;
+ }
+ }
+ //
+ // If we found a match, we're done. If we didn't, create a new element
+ // and add it to the list.
+ //
+ if (ListPtr != NULL) {
+ //
+ // Print a message if verbose mode
+ //
+ if (mGlobals.Verbose) {
+ DebugMsg (NULL, 0, 0, FileName, "duplicate include -- not processed again");
+ }
+
+ return STATUS_SUCCESS;
+ }
+
+ ListPtr = malloc (sizeof (STRING_LIST));
+ ListPtr->Str = malloc (strlen (FileName) + 1);
+ strcpy (ListPtr->Str, FileName);
+ ListPtr->Next = ProcessedFiles->Next;
+ ProcessedFiles->Next = ListPtr;
+ }
+
+ //
+ // Make sure we didn't exceed our maximum nesting depth
+ //
+ if (NestDepth > MAX_NEST_DEPTH) {
+ Error (NULL, 0, 0, FileName, "max nesting depth exceeded on file");
+ goto Finish;
+ }
+ //
+ // Make a local copy of the filename. Then we can manipulate it
+ // if we have to.
+ //
+ strcpy (FileNameCopy, FileName);
+ //
+ // Try to open the file locally
+ //
+ if ((Fptr = fopen (FileNameCopy, "r")) == NULL) {
+ //
+ // Try to find it among the paths.
+ //
+ Fptr = FindFile (FileNameCopy, sizeof (FileNameCopy));
+ if (Fptr == NULL) {
+ //
+ // If this is not the top-level file, and the command-line argument
+ // said to ignore missing files, then return ok
+ //
+ if (NestDepth != START_NEST_DEPTH) {
+ if (mGlobals.IgnoreNotFound) {
+ if (!mGlobals.QuietMode) {
+ DebugMsg (NULL, 0, 0, FileNameCopy, "could not find file");
+ }
+
+ return STATUS_SUCCESS;
+ } else {
+ Error (NULL, 0, 0, FileNameCopy, "could not find file");
+ return STATUS_ERROR;
+ }
+ } else {
+ //
+ // Top-level (first) file. Emit an error.
+ //
+ Error (NULL, 0, 0, FileNameCopy, "could not find file");
+ return STATUS_ERROR;
+ }
+ }
+ }
+ //
+ // Print the dependency, with string substitution
+ //
+ PrintDependency (TargetFileName, FileNameCopy);
+
+ //
+ // Now read in lines and find all #include lines. Allow them to indent, and
+ // to put spaces between the # and include.
+ //
+ LineNum = 0;
+ while ((fgets (Line, sizeof (Line), Fptr) != NULL) && (Status == STATUS_SUCCESS)) {
+ LineNum++;
+ Cptr = Line;
+ //
+ // Skip preceeding spaces on the line
+ //
+ while (*Cptr && (isspace (*Cptr))) {
+ Cptr++;
+ }
+ //
+ // Check for # character
+ //
+ if (*Cptr == '#') {
+ Cptr++;
+ //
+ // Check for "include"
+ //
+ while (*Cptr && (isspace (*Cptr))) {
+ Cptr++;
+ }
+
+ if (strncmp (Cptr, "include", 7) == 0) {
+ //
+ // Skip over "include" and move on to filename as "file" or <file>
+ //
+ Cptr += 7;
+ while (*Cptr && (isspace (*Cptr))) {
+ Cptr++;
+ }
+
+ if (*Cptr == '<') {
+ EndChar = '>';
+ } else if (*Cptr == '"') {
+ EndChar = '"';
+ } else {
+ //
+ // Handle special #include MACRO_NAME(file)
+ // Set EndChar to null so we fall through on processing below.
+ //
+ EndChar = 0;
+ //
+ // Look for all the special include macros and convert accordingly.
+ //
+ for (Index = 0; mMacroConversion[Index].IncludeMacroName != NULL; Index++) {
+ //
+ // Save the start of the string in case some macros are substrings
+ // of others.
+ //
+ SaveCptr = Cptr;
+ if (strncmp (
+ Cptr,
+ mMacroConversion[Index].IncludeMacroName,
+ strlen (mMacroConversion[Index].IncludeMacroName)
+ ) == 0) {
+ //
+ // Skip over the macro name
+ //
+ Cptr += strlen (mMacroConversion[Index].IncludeMacroName);
+ //
+ // Skip over open parenthesis, blank spaces, then find closing
+ // parenthesis or blank space
+ //
+ while (*Cptr && (isspace (*Cptr))) {
+ Cptr++;
+ }
+
+ if (*Cptr == '(') {
+ Cptr++;
+ while (*Cptr && (isspace (*Cptr))) {
+ Cptr++;
+ }
+
+ EndPtr = Cptr;
+ while (*EndPtr && !isspace (*EndPtr) && (*EndPtr != ')')) {
+ EndPtr++;
+ }
+
+ *EndPtr = 0;
+ //
+ // Create the path
+ //
+ strcpy (MacroIncludeFileName, mMacroConversion[Index].PathName);
+ strcat (MacroIncludeFileName, Cptr);
+ strcat (MacroIncludeFileName, "/");
+ strcat (MacroIncludeFileName, Cptr);
+ strcat (MacroIncludeFileName, ".h");
+ //
+ // Process immediately, then break out of the outside FOR loop.
+ //
+ Status = ProcessFile (TargetFileName, MacroIncludeFileName, NestDepth + 1, ProcessedFiles);
+ break;
+ }
+ }
+ //
+ // Restore the start
+ //
+ Cptr = SaveCptr;
+ }
+ //
+ // Don't recognize the include line? Ignore it. We assume that the
+ // file compiles anyway.
+ //
+ if (mMacroConversion[Index].IncludeMacroName == NULL) {
+ //
+ // Warning (FileNameCopy, LineNum, 0, "could not parse line", NULL);
+ // Status = STATUS_WARNING;
+ //
+ }
+ }
+ //
+ // Process "normal" includes. If the endchar is 0, then the
+ // file has already been processed. Otherwise look for the
+ // endchar > or ", and process the include file.
+ //
+ if (EndChar != 0) {
+ Cptr++;
+ EndPtr = Cptr;
+ while (*EndPtr && (*EndPtr != EndChar)) {
+ EndPtr++;
+ }
+
+ if (*EndPtr == EndChar) {
+ //
+ // If we're processing it, do it
+ //
+ if ((EndChar != '>') || (!mGlobals.NoSystem)) {
+ //
+ // Null terminate the filename and try to process it.
+ //
+ *EndPtr = 0;
+ Status = ProcessFile (TargetFileName, Cptr, NestDepth + 1, ProcessedFiles);
+ }
+ } else {
+ Warning (FileNameCopy, LineNum, 0, "malformed include", "missing closing %c", EndChar);
+ Status = STATUS_WARNING;
+ goto Finish;
+ }
+ }
+ }
+ }
+ }
+
+Finish:
+ //
+ // Close open files and return status
+ //
+ if (Fptr != NULL) {
+ fclose (Fptr);
+ }
+
+ return Status;
+}
+
+static
+void
+PrintDependency (
+ INT8 *TargetFileName,
+ INT8 *DependentFile
+ )
+/*++
+
+Routine Description:
+
+ Given a target (.obj) file name, and a dependent file name, do any string
+ substitutions (per the command line options) on the file names, then
+ print the dependency line of form:
+
+ TargetFileName : DependentFile
+
+Arguments:
+
+ TargetFileName - build target file name
+ DependentFile - file on which TargetFileName depends
+
+Returns:
+
+ None
+
+--*/
+{
+ INT8 Str[MAX_PATH];
+
+ //
+ // Go through the symbols and do replacements
+ //
+ strcpy (Str, DependentFile);
+ ReplaceSymbols (Str, sizeof (Str));
+ fprintf (mGlobals.OutFptr, "%s\n", Str);
+}
+
+static
+void
+ReplaceSymbols (
+ INT8 *Str,
+ UINT32 StrSize
+ )
+{
+ SYMBOL *Sym;
+ INT8 StrCopy[MAX_LINE_LEN];
+ INT8 *From;
+ INT8 *To;
+ BOOLEAN Replaced;
+
+ //
+ // Go through the entire string to look for replacement strings at
+ // every position.
+ //
+ From = Str;
+ To = StrCopy;
+ while (*From) {
+ //
+ // Copy the character
+ //
+ *To = *From;
+ Replaced = FALSE;
+ //
+ // Go through each symbol and try to find a string substitution
+ //
+ Sym = mGlobals.SymbolTable;
+ while (Sym != NULL) {
+ if (strnicmp (From, Sym->Value, strlen (Sym->Value)) == 0) {
+ //
+ // Replace the string, then advance the pointers past the
+ // replaced strings
+ //
+ strcpy (To, Sym->Name);
+ To += strlen (Sym->Name);
+ From += strlen (Sym->Value);
+ Replaced = TRUE;
+ //
+ // Break from the while()
+ //
+ break;
+ } else {
+ Sym = Sym->Next;
+ }
+ }
+
+ if (!Replaced) {
+ From++;
+ To++;
+ }
+ }
+ //
+ // Null terminate, and return it
+ //
+ *To = 0;
+ if (strlen (StrCopy) < StrSize) {
+ strcpy (Str, StrCopy);
+ }
+}
+//
+// Given a filename, try to find it along the include paths.
+//
+static
+FILE *
+FindFile (
+ INT8 *FileName,
+ UINT32 FileNameLen
+ )
+{
+ FILE *Fptr;
+ STRING_LIST *List;
+ STRING_LIST *SubDir;
+ INT8 FullFileName[MAX_PATH * 2];
+
+ //
+ // Traverse the list of paths and try to find the file
+ //
+ List = mGlobals.IncludePaths;
+ while (List != NULL) {
+ //
+ // Put the path and filename together
+ //
+ if (strlen (List->Str) + strlen (FileName) + 1 > sizeof (FullFileName)) {
+ Error (
+ __FILE__,
+ __LINE__,
+ 0,
+ "application error",
+ "cannot concatenate '%s' + '%s'",
+ List->Str,
+ FileName
+ );
+ return NULL;
+ }
+ //
+ // Append the filename to this include path and try to open the file.
+ //
+ strcpy (FullFileName, List->Str);
+ strcat (FullFileName, FileName);
+ if ((Fptr = fopen (FullFileName, "r")) != NULL) {
+ //
+ // Return the file name
+ //
+ if (FileNameLen <= strlen (FullFileName)) {
+ Error (__FILE__, __LINE__, 0, "application error", "internal path name of insufficient length");
+ //
+ // fprintf (stdout, "File length > %d: %s\n", FileNameLen, FullFileName);
+ //
+ return NULL;
+ }
+
+ strcpy (FileName, FullFileName);
+ return Fptr;
+ }
+ //
+ // Didn't find it there. Now try this directory with every subdirectory
+ // the user specified on the command line
+ //
+ for (SubDir = mGlobals.SubDirs; SubDir != NULL; SubDir = SubDir->Next) {
+ strcpy (FullFileName, List->Str);
+ strcat (FullFileName, SubDir->Str);
+ strcat (FullFileName, FileName);
+ if ((Fptr = fopen (FullFileName, "r")) != NULL) {
+ //
+ // Return the file name
+ //
+ if (FileNameLen <= strlen (FullFileName)) {
+ Error (__FILE__, __LINE__, 0, "application error", "internal path name of insufficient length");
+ return NULL;
+ }
+
+ strcpy (FileName, FullFileName);
+ return Fptr;
+ }
+ }
+
+ List = List->Next;
+ }
+ //
+ // Not found
+ //
+ return NULL;
+}
+//
+// Process the command-line arguments
+//
+static
+STATUS
+ProcessArgs (
+ int Argc,
+ char *Argv[]
+ )
+{
+ STRING_LIST *NewList;
+ STRING_LIST *LastIncludePath;
+ STRING_LIST *LastSourceFile;
+ SYMBOL *Symbol;
+ int Index;
+ //
+ // Clear our globals
+ //
+ memset ((char *) &mGlobals, 0, sizeof (mGlobals));
+ mGlobals.NoDupes = TRUE;
+ //
+ // Skip program name
+ //
+ Argc--;
+ Argv++;
+ //
+ // Initialize locals
+ //
+ LastIncludePath = NULL;
+ LastSourceFile = NULL;
+ //
+ // Process until no more args
+ //
+ while (Argc) {
+ //
+ // -i path add include search path
+ //
+ if (stricmp (Argv[0], "-i") == 0) {
+ //
+ // check for one more arg
+ //
+ if (Argc > 1) {
+ //
+ // Allocate memory for a new list element, fill it in, and
+ // add it to our list of include paths. Always make sure it
+ // has a "\" on the end of it.
+ //
+ NewList = malloc (sizeof (STRING_LIST));
+ if (NewList == NULL) {
+ Error (__FILE__, __LINE__, 0, "memory allocation failure", NULL);
+ return STATUS_ERROR;
+ }
+
+ NewList->Next = NULL;
+ NewList->Str = malloc (strlen (Argv[1]) + 2);
+ if (NewList->Str == NULL) {
+ free (NewList);
+ Error (__FILE__, __LINE__, 0, "memory allocation failure", NULL);
+ return STATUS_ERROR;
+ }
+
+ strcpy (NewList->Str, Argv[1]);
+ if (NewList->Str[strlen (NewList->Str) - 1] != '\\' && NewList->Str[strlen (NewList->Str) - 1] != '/') {
+ strcat (NewList->Str, "/");
+ }
+ //
+ // Add it to the end of the our list of include paths
+ //
+ if (mGlobals.IncludePaths == NULL) {
+ mGlobals.IncludePaths = NewList;
+ } else {
+ LastIncludePath->Next = NewList;
+ }
+
+ LastIncludePath = NewList;
+ //
+ // fprintf (stdout, "Added path: %s\n", NewList->Str);
+ //
+ } else {
+ Error (NULL, 0, 0, Argv[0], "option requires an include path");
+ Usage ();
+ return STATUS_ERROR;
+ }
+
+ Argc--;
+ Argv++;
+ } else if (stricmp (Argv[0], "-f") == 0) {
+ //
+ // Check for one more arg
+ //
+ if (Argc > 1) {
+ //
+ // Allocate memory for a new list element, fill it in, and
+ // add it to our list of source files.
+ //
+ NewList = malloc (sizeof (STRING_LIST));
+ if (NewList == NULL) {
+ Error (__FILE__, __LINE__, 0, "memory allocation failure", NULL);
+ return STATUS_ERROR;
+ }
+
+ NewList->Next = NULL;
+ //
+ // Allocate space to replace ".c" with ".obj", plus null termination
+ //
+ NewList->Str = malloc (strlen (Argv[1]) + 5);
+ if (NewList->Str == NULL) {
+ free (NewList);
+ Error (__FILE__, __LINE__, 0, "memory allocation failure", NULL);
+ return STATUS_ERROR;
+ }
+
+ strcpy (NewList->Str, Argv[1]);
+ if (mGlobals.SourceFiles == NULL) {
+ mGlobals.SourceFiles = NewList;
+ } else {
+ LastSourceFile->Next = NewList;
+ }
+
+ LastSourceFile = NewList;
+ } else {
+ Error (NULL, 0, 0, Argv[0], "option requires a file name");
+ Usage ();
+ return STATUS_ERROR;
+ }
+ //
+ // The C compiler first looks for #include files in the directory where
+ // the source file came from. Add the file's source directory to the
+ // list of include paths.
+ //
+ NewList = malloc (sizeof (STRING_LIST));
+ if (NewList == NULL) {
+ Error (__FILE__, __LINE__, 0, "memory allocation failure", NULL);
+ return STATUS_ERROR;
+ }
+
+ NewList->Next = NULL;
+ NewList->Str = malloc (strlen (Argv[1]) + 3);
+ if (NewList->Str == NULL) {
+ free (NewList);
+ Error (__FILE__, __LINE__, 0, "memory allocation failure", NULL);
+ return STATUS_ERROR;
+ }
+
+ strcpy (NewList->Str, Argv[1]);
+ //
+ // Back up in the source file name to the last backslash and terminate after it.
+ //
+ for (Index = strlen (NewList->Str) - 1; (Index > 0) && (NewList->Str[Index] != '\\' && NewList->Str[Index] != '/'); Index--)
+ ;
+ if (Index < 0) {
+ strcpy (NewList->Str, "./");
+ } else {
+ NewList->Str[Index + 1] = 0;
+ }
+ //
+ // Add it to the end of the our list of include paths
+ //
+ if (mGlobals.IncludePaths == NULL) {
+ mGlobals.IncludePaths = NewList;
+ } else {
+ LastIncludePath->Next = NewList;
+ }
+
+ if (mGlobals.Verbose) {
+ fprintf (stdout, "Adding include path: %s\n", NewList->Str);
+ }
+
+ LastIncludePath = NewList;
+ Argc--;
+ Argv++;
+ } else if (stricmp (Argv[0], "-s") == 0) {
+ //
+ // -s subdir add subdirectory subdir to list of subdirecties to scan.
+ // Check for one more arg first.
+ //
+ if (Argc > 1) {
+ //
+ // Allocate memory for a new list element, fill it in, and
+ // add it to our list of subdirectory include paths. Always
+ // make sure it has a "\" on the end of it.
+ //
+ NewList = malloc (sizeof (STRING_LIST));
+ if (NewList == NULL) {
+ Error (__FILE__, __LINE__, 0, "memory allocation failure", NULL);
+ return STATUS_ERROR;
+ }
+
+ NewList->Str = malloc (strlen (Argv[1]) + 2);
+ if (NewList->Str == NULL) {
+ free (NewList);
+ Error (__FILE__, __LINE__, 0, "memory allocation failure", NULL);
+ return STATUS_ERROR;
+ }
+
+ strcpy (NewList->Str, Argv[1]);
+ if (NewList->Str[strlen (NewList->Str) - 1] != '\\' && NewList->Str[strlen (NewList->Str) - 1] != '/') {
+ strcat (NewList->Str, "/");
+ }
+
+ NewList->Next = mGlobals.SubDirs;
+ mGlobals.SubDirs = NewList;
+ } else {
+ Error (NULL, 0, 0, Argv[0], "option requires a subdirectory name");
+ Usage ();
+ return STATUS_ERROR;
+ }
+
+ Argc--;
+ Argv++;
+ } else if (stricmp (Argv[0], "-sub") == 0) {
+ //
+ // -sub symname symvalue to do string substitution in the output
+ //
+ if (Argc > 2) {
+ //
+ // Allocate memory for the symbol object
+ //
+ Symbol = malloc (sizeof (SYMBOL));
+ if (Symbol == NULL) {
+ Error (__FILE__, __LINE__, 0, "memory allocation failure", NULL);
+ return STATUS_ERROR;
+ }
+ //
+ // Allocate memory for the symbol name and value, then save copies
+ //
+ Symbol->Name = malloc (strlen (Argv[1]) + 1);
+ if (Symbol->Name == NULL) {
+ free (Symbol);
+ Error (__FILE__, __LINE__, 0, "memory allocation failure", NULL);
+ return STATUS_ERROR;
+ }
+
+ strcpy (Symbol->Name, Argv[1]);
+ Symbol->Value = malloc (strlen (Argv[2]) + 1);
+ if (Symbol->Value == NULL) {
+ free (Symbol->Name);
+ free (Symbol);
+ Error (__FILE__, __LINE__, 0, "memory allocation failure", NULL);
+ return STATUS_ERROR;
+ }
+
+ strcpy (Symbol->Value, Argv[2]);
+ //
+ // Add it to the list
+ //
+ Symbol->Next = mGlobals.SymbolTable;
+ mGlobals.SymbolTable = Symbol;
+ } else {
+ Error (NULL, 0, 0, Argv[0], "option requires a symbol name and value");
+ Usage ();
+ return STATUS_ERROR;
+ }
+ //
+ // Skip over args
+ //
+ Argc -= 2;
+ Argv += 2;
+ } else if (stricmp (Argv[0], "-nosystem") == 0) {
+ mGlobals.NoSystem = TRUE;
+ } else if (stricmp (Argv[0], "-nodupes") == 0) {
+ mGlobals.NoDupes = TRUE;
+ } else if (stricmp (Argv[0], "-nodups") == 0) {
+ mGlobals.NoDupes = TRUE;
+ } else if (stricmp (Argv[0], "-target") == 0) {
+ //
+ // -target TargetFileName - Target object file (only one allowed right
+ // now) is TargetFileName rather than SourceFile.obj
+ //
+ if (Argc > 1) {
+ strcpy (mGlobals.TargetFileName, Argv[1]);
+ } else {
+ Error (NULL, 0, 0, Argv[0], "option requires a target file name");
+ Usage ();
+ return STATUS_ERROR;
+ }
+
+ Argc--;
+ Argv++;
+ } else if (stricmp (Argv[0], "-usesumdeps") == 0) {
+ //
+ // -usesumdeps Path - if we find an included file xxx.h, and file
+ // Path/xxx.dep exists, list Path/xxx.dep as a dependency rather than
+ // xxx.h and don't parse xxx.h. This allows you to create a dependency
+ // file for a commonly included file, and have its dependency file updated
+ // only if its included files are updated. Then anyone else including this
+ // common include file can simply have a dependency on that file's .dep file
+ // rather than on all the files included by it. Confusing enough?
+ //
+ mGlobals.UseSumDeps = 1;
+ if (Argc > 1) {
+ strcpy (mGlobals.SumDepsPath, Argv[1]);
+ //
+ // Add slash on end if not there
+ //
+ if (mGlobals.SumDepsPath[strlen (mGlobals.SumDepsPath) - 1] != '\\' && mGlobals.SumDepsPath[strlen (mGlobals.SumDepsPath) - 1] != '/') {
+ strcat (mGlobals.SumDepsPath, "/");
+ }
+ } else {
+ Error (NULL, 0, 0, Argv[0], "option requires path to summary dependency files");
+ Usage ();
+ return STATUS_ERROR;
+ }
+
+ Argc--;
+ Argv++;
+
+ } else if (stricmp (Argv[0], "-o") == 0) {
+ //
+ // -o OutputFileName - specify an output filename for dependency list
+ // check for one more arg
+ //
+ if (Argc > 1) {
+ //
+ // Try to open the file
+ //
+ if ((mGlobals.OutFptr = fopen (Argv[1], "w")) == NULL) {
+ Error (NULL, 0, 0, Argv[1], "could not open file for writing");
+ return STATUS_ERROR;
+ }
+
+ mGlobals.OutFileName = Argv[1];
+ } else {
+ Error (NULL, 0, 0, Argv[0], "option requires output file name");
+ Usage ();
+ return STATUS_ERROR;
+ }
+
+ Argc--;
+ Argv++;
+ } else if (stricmp (Argv[0], "-v") == 0) {
+ mGlobals.Verbose = TRUE;
+ } else if (stricmp (Argv[0], "-neverfail") == 0) {
+ mGlobals.NeverFail = TRUE;
+ } else if (stricmp (Argv[0], "-q") == 0) {
+ mGlobals.QuietMode = TRUE;
+ } else if (stricmp (Argv[0], "-ignorenotfound") == 0) {
+ mGlobals.IgnoreNotFound = TRUE;
+ } else if ((stricmp (Argv[0], "-h") == 0) || (strcmp (Argv[0], "-?") == 0)) {
+ Usage ();
+ return STATUS_ERROR;
+ } else {
+ Error (NULL, 0, 0, Argv[0], "unrecognized option");
+ Usage ();
+ return STATUS_ERROR;
+ }
+
+ Argc--;
+ Argv++;
+ }
+ //
+ // Had to specify at least one source file
+ //
+ if (mGlobals.SourceFiles == NULL) {
+ Error (NULL, 0, 0, "must specify one source file name", NULL);
+ Usage ();
+ return STATUS_ERROR;
+ }
+ //
+ // Assume output to stdout if not specified
+ //
+ if (mGlobals.OutFptr == NULL) {
+ mGlobals.OutFptr = stdout;
+ }
+
+ return STATUS_SUCCESS;
+}
+//
+// Free the global string lists we allocated memory for
+//
+static
+void
+FreeLists (
+ VOID
+ )
+{
+ STRING_LIST *Temp;
+ SYMBOL *NextSym;
+
+ //
+ // printf ("Free lists.....");
+ //
+ // Traverse the include paths, freeing each
+ // printf ("freeing include paths\n");
+ //
+ while (mGlobals.IncludePaths != NULL) {
+ Temp = mGlobals.IncludePaths->Next;
+ //
+ // printf ("Freeing include path string '%s' at 0x%X\n",
+ // mGlobals.IncludePaths->Str, (int)(mGlobals.IncludePaths->Str));
+ //
+ free (mGlobals.IncludePaths->Str);
+ //
+ // printf ("Freeing include path object at 0x%X\n", (int)(mGlobals.IncludePaths));
+ //
+ free (mGlobals.IncludePaths);
+ mGlobals.IncludePaths = Temp;
+ }
+ //
+ // Traverse the source files, freeing each
+ //
+ while (mGlobals.SourceFiles != NULL) {
+ Temp = mGlobals.SourceFiles->Next;
+ free (mGlobals.SourceFiles->Str);
+ free (mGlobals.SourceFiles);
+ mGlobals.SourceFiles = Temp;
+ }
+ //
+ // Traverse the subdirectory list, freeing each
+ //
+ while (mGlobals.SubDirs != NULL) {
+ Temp = mGlobals.SubDirs->Next;
+ free (mGlobals.SubDirs->Str);
+ free (mGlobals.SubDirs);
+ mGlobals.SubDirs = Temp;
+ }
+ //
+ // Free the symbol table
+ //
+ while (mGlobals.SymbolTable != NULL) {
+ NextSym = mGlobals.SymbolTable->Next;
+ free (mGlobals.SymbolTable->Name);
+ free (mGlobals.SymbolTable->Value);
+ mGlobals.SymbolTable = NextSym;
+ }
+ //
+ // printf ("done\n");
+ //
+}
+
+static
+void
+Usage (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Print usage information for this utility.
+
+Arguments:
+
+ None.
+
+Returns:
+
+ Nothing.
+
+--*/
+{
+ int Index;
+ static const char *Str[] = {
+ UTILITY_NAME " -- make dependencies",
+ " Usage: MakeDeps [options]",
+ " Options include:",
+ " -h or -? for this help information",
+ " -f SourceFile add SourceFile to list of files to scan",
+ " -i IncludePath add IncludePath to list of search paths",
+ " -o OutputFile write output dependencies to OutputFile",
+ " -s SubDir for each IncludePath, also search IncludePath\\SubDir",
+ " -v for verbose output",
+ " -ignorenotfound don't warn for files not found",
+ " -target Target for single SourceFile, target is Target, not SourceFile.obj",
+ " -q quiet mode to not report files not found if ignored",
+ " -sub sym str replace all occurrances of 'str' with 'sym' in the output",
+ " -nosystem not process system <include> files",
+ " -neverfail always return a success return code",
+ //
+ // " -nodupes keep track of include files, don't rescan duplicates",
+ //
+ " -usesumdeps path use summary dependency files in 'path' directory.",
+ "",
+ NULL
+ };
+ for (Index = 0; Str[Index] != NULL; Index++) {
+ fprintf (stdout, "%s\n", Str[Index]);
+ }
+}
diff --git a/Source/MakeDeps/build.xml b/Source/MakeDeps/build.xml
new file mode 100755
index 0000000..6c532a1
--- /dev/null
+++ b/Source/MakeDeps/build.xml
@@ -0,0 +1,70 @@
+<?xml version="1.0" ?>
+<!--
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+-->
+<project default="GenTool" basedir=".">
+<!--
+ EDK MakeDeps Tool
+ Copyright (c) 2006, Intel Corporation
+-->
+ <property name="ToolName" value="MakeDeps"/>
+ <property name="FileSet" value="*.c *.h"/>
+
+ <taskdef resource="net/sf/antcontrib/antlib.xml"/>
+
+ <property name="LINK_OUTPUT_TYPE" value="static"/>
+ <property name="BUILD_DIR" value="${PACKAGE_DIR}/${ToolName}/tmp"/>
+
+ <target name="GenTool" depends="init, Tool">
+ <echo message="The EDK Tool: ${ToolName} build has completed!"/>
+ </target>
+
+ <target name="init">
+ <echo message="Building the EDK Tool: ${ToolName}"/>
+ <mkdir dir="${BUILD_DIR}"/>
+ </target>
+
+ <target name="Tool" depends="init">
+ <cc name="${ToolChain}" objdir="${BUILD_DIR}"
+ outfile="${BIN_DIR}/${ToolName}"
+ outtype="executable"
+ debug="true"
+ optimize="speed">
+ <compilerarg value="${ExtraArgus}" if="ExtraArgus" />
+
+ <fileset dir="${basedir}/${ToolName}"
+ includes="${FileSet}"
+ defaultexcludes="TRUE"
+ excludes="*.xml *.inf"/>
+
+ <includepath path="${PACKAGE_DIR}/Include"/>
+ <includepath path="${PACKAGE_DIR}/Include/${HostArch}"/>
+ <includepath path="${PACKAGE_DIR}/Common"/>
+ <libset dir="${LIB_DIR}" libs="CommonTools"/>
+ </cc>
+ </target>
+
+ <target name="clean">
+ <echo message="Removing Intermediate Files Only"/>
+ <delete>
+ <fileset dir="${BUILD_DIR}" includes="*.obj"/>
+ </delete>
+ </target>
+
+ <target name="cleanall">
+ <echo message="Removing Object Files and the Executable: ${ToolName}${ext_exe}"/>
+ <delete failonerror="false" quiet="true" includeEmptyDirs="true">
+ <fileset dir="${BUILD_DIR}"/>
+ <fileset file="${BIN_DIR}/${ToolName}${ext_exe}"/>
+ <fileset file="${BIN_DIR}/${ToolName}.pdb"/>
+ </delete>
+ </target>
+
+</project>
diff --git a/Source/ModifyInf/ModifyInf.c b/Source/ModifyInf/ModifyInf.c
new file mode 100755
index 0000000..6008feb
--- /dev/null
+++ b/Source/ModifyInf/ModifyInf.c
@@ -0,0 +1,321 @@
+/*++
+
+Copyright (c) 1999-2006 Intel Corporation. All rights reserved
+This program and the accompanying materials are licensed and made available
+under the terms and conditions of the BSD License which accompanies this
+distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+
+Module Name:
+
+ ModifyInf.c
+
+Abstract:
+
+ It is a simple tool to modify some fields in a FV inf file
+ and output a new FV inf file.
+
+--*/
+
+#include "stdio.h"
+#include "string.h"
+
+//
+// Read a line into buffer including '\r\n'
+//
+int
+ReadLine (
+ char *LineBuffer,
+ FILE *fp
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ LineBuffer - GC_TODO: add argument description
+ fp - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+{
+ int CharC;
+ char *Line;
+
+ Line = LineBuffer;
+
+ while ((CharC = fgetc (fp)) != EOF) {
+ *Line++ = (char) CharC;
+ if (CharC == 0x0a) {
+ break;
+ }
+ }
+
+ *Line = 0;
+
+ if (CharC == EOF) {
+ return 0;
+ } else {
+ return 1;
+ }
+
+}
+//
+// Write a line into output file
+//
+int
+WriteLine (
+ char *Line,
+ FILE *fp
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ Line - GC_TODO: add argument description
+ fp - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+{
+ fwrite (Line, strlen (Line), 1, fp);
+ return 0;
+}
+//
+// Apply patterns to a line
+// Currently there are 2 patterns to support
+// '==' replace a field value with a new value
+// '+=' append a string at the end of original line
+// '-' prevent the line from applying any patterns
+// it has the highest priority
+//
+int
+ApplyPattern (
+ char *Line,
+ char *argv[],
+ int argc
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ Line - GC_TODO: add argument description
+ ] - GC_TODO: add argument description
+ argc - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+{
+ static char Section[256];
+ char PatternBuffer[256];
+ char *Pattern;
+ char *Pattern1;
+ char *Pattern2;
+ int PatternNum;
+ char *Ptr;
+
+ Pattern = PatternBuffer;
+
+ PatternNum = argc;
+
+ //
+ // For section field
+ // record current scope section into static buffer
+ //
+ Ptr = Line;
+ if (*Ptr == '[') {
+ while (*Ptr != ']') {
+ if (!(*Ptr++)) {
+ return -1;
+ }
+ }
+
+ strcpy (Section, Line);
+ Section[Ptr - Line + 1] = 0;
+ }
+ //
+ // Apply each pattern on the line
+ //
+ while (PatternNum-- > 3) {
+
+ strcpy (Pattern, argv[PatternNum]);
+
+ //
+ // For pattern '-'
+ // keep it unmodified by other patterns
+ //
+ if (*Pattern == '-') {
+ if (strstr (Line, Pattern + 1)) {
+ return 0;
+ } else {
+ continue;
+ }
+ }
+ //
+ // For other patterns
+ // get its section at first if it has
+ //
+ if (*Pattern == '[') {
+ if (strncmp (Section, Pattern, strlen (Section))) {
+ //
+ // This pattern can't be appied for current section
+ //
+ continue;
+ }
+ //
+ // Strip the section field
+ //
+ while (*Pattern != ']') {
+ if (!(*Pattern++)) {
+ return -1;
+ }
+ }
+
+ Pattern++;
+ }
+ //
+ // Apply patterns
+ //
+ Pattern1 = strstr (Pattern, "==");
+ Pattern2 = strstr (Pattern, "+=");
+ if (Pattern1) {
+ //
+ // For pattern '=='
+ // replace the field value with a new string
+ //
+ if (!strncmp (Line, Pattern, Pattern1 - Pattern)) {
+ Pattern1 += 2;
+ Ptr = strstr (Line, "=");
+ if (!Ptr) {
+ return -1;
+ }
+
+ while (*(++Ptr) == ' ')
+ ;
+ *Ptr = 0;
+ strcat (Line, Pattern1);
+ strcat (Line, "\r\n");
+ }
+ } else if (Pattern2) {
+ //
+ // For pattern '+='
+ // append a string at end of the original string
+ //
+ if (!strncmp (Line, Pattern, Pattern2 - Pattern)) {
+ Pattern2 += 2;
+ Ptr = Line;
+ while (*Ptr != 0x0D && *Ptr != 0x0A) {
+ Ptr++;
+ }
+
+ *Ptr = 0;
+ strcat (Line, Pattern2);
+ strcat (Line, "\r\n");
+ }
+ }
+ }
+
+ return 0;
+}
+
+void
+Usage (
+ void
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ None
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+{
+ printf ("ModifyInf InputFVInfFileName OutputFVInfFileName [Pattern strings]\r\n");
+}
+
+int
+main (
+ int argc,
+ char*argv[]
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ argc - GC_TODO: add argument description
+ ] - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+{
+ char LineBuffer[256];
+ FILE *fpin;
+ FILE *fpout;
+
+ if (argc < 3) {
+ Usage ();
+ return -1;
+ }
+
+ fpin = fopen (argv[1], "rb");
+ if (!fpin) {
+ printf ("Can't open input file!\r\n");
+ return -1;
+ }
+
+ fpout = fopen (argv[2], "wb");
+ if (!fpout) {
+ fclose (fpin);
+ printf ("Can't create output file!\r\n");
+ return -1;
+ }
+
+ while (ReadLine (LineBuffer, fpin)) {
+ ApplyPattern (LineBuffer, argv, argc);
+ WriteLine (LineBuffer, fpout);
+ }
+
+ fclose (fpin);
+ fclose (fpout);
+
+ return 0;
+}
diff --git a/Source/ModifyInf/build.xml b/Source/ModifyInf/build.xml
new file mode 100644
index 0000000..f536a98
--- /dev/null
+++ b/Source/ModifyInf/build.xml
@@ -0,0 +1,69 @@
+<?xml version="1.0" ?>
+<!--
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+-->
+<project default="GenTool" basedir=".">
+<!--
+ EDK ModifyInf Tool
+ Copyright (c) 2006, Intel Corporation
+-->
+ <property name="ToolName" value="ModifyInf"/>
+ <property name="FileSet" value="ModifyInf.c"/>
+
+ <taskdef resource="net/sf/antcontrib/antlib.xml"/>
+
+ <property name="LINK_OUTPUT_TYPE" value="static"/>
+ <property name="BUILD_DIR" value="${PACKAGE_DIR}/${ToolName}/tmp"/>
+
+ <target name="GenTool" depends="init, Tool">
+ <echo message="The EDK Tool: ${ToolName} build has completed!"/>
+ </target>
+
+ <target name="init">
+ <echo message="Building the EDK Tool: ${ToolName}"/>
+ <mkdir dir="${BUILD_DIR}"/>
+ </target>
+
+ <target name="Tool" depends="init">
+ <cc name="${ToolChain}" objdir="${BUILD_DIR}"
+ outfile="${BIN_DIR}/${ToolName}"
+ outtype="executable"
+ debug="true"
+ optimize="speed">
+
+ <fileset dir="${basedir}/${ToolName}"
+ includes="${FileSet}"
+ defaultexcludes="TRUE"
+ excludes="*.xml *.inf"/>
+
+ <includepath path="${PACKAGE_DIR}/Include"/>
+ <includepath path="${PACKAGE_DIR}/Include/${HostArch}"/>
+ <includepath path="${PACKAGE_DIR}/Common"/>
+
+ </cc>
+ </target>
+
+ <target name="clean">
+ <echo message="Removing Intermediate Files Only"/>
+ <delete>
+ <fileset dir="${BUILD_DIR}" includes="*.obj"/>
+ </delete>
+ </target>
+
+ <target name="cleanall">
+ <echo message="Removing Object Files and the Executable: ${ToolName}${ext_exe}"/>
+ <delete failonerror="false" quiet="true" includeEmptyDirs="true">
+ <fileset dir="${BUILD_DIR}"/>
+ <fileset file="${BIN_DIR}/${ToolName}${ext_exe}"/>
+ <fileset file="${BIN_DIR}/${ToolName}.pdb"/>
+ </delete>
+ </target>
+
+</project>
diff --git a/Source/Pccts/CHANGES_FROM_131.txt b/Source/Pccts/CHANGES_FROM_131.txt
new file mode 100644
index 0000000..500d84f
--- /dev/null
+++ b/Source/Pccts/CHANGES_FROM_131.txt
@@ -0,0 +1,522 @@
+CHANGES FROM 1.31
+
+This file contains the migration of PCCTS from 1.31 in the order that
+changes were made. 1.32b7 is the last beta before full 1.32.
+Terence Parr, Parr Research Corporation 1995.
+
+
+======================================================================
+1.32b1
+Added Russell Quong to banner, changed banner for output slightly
+Fixed it so that you have before / after actions for C++ in class def
+Fixed bug in optimizer that made it sometimes forget to set internal
+ token pointers. Only showed up when a {...} was in the "wrong spot".
+
+======================================================================
+1.32b2
+Added fixes by Dave Seidel for PC compilers in 32 bit mode (config.h
+and set.h).
+
+======================================================================
+1.32b3
+Fixed hideous bug in code generator for wildcard and for ~token op.
+
+from Dave Seidel
+
+ Added pcnames.bat
+ 1. in antlr/main.c: change strcasecmp() to stricmp()
+
+ 2. in dlg/output.c: use DLEXER_C instead on "DLexer.C"
+
+ 3. in h/PBlackBox.h: use <iostream.h> instead of <stream.h>
+
+======================================================================
+1.32b4
+When the -ft option was used, any path prefix screwed up
+the gate on the .h files
+
+Fixed yet another bug due to the optimizer.
+
+The exception handling thing was a bit wacko:
+
+a : ( A B )? A B
+ | A C
+ ;
+ exception ...
+
+caused an exception if "A C" was the input. In other words,
+it found that A C didn't match the (A B)? pred and caused
+an exception rather than trying the next alt. All I did
+was to change the zzmatch_wsig() macros.
+
+Fixed some problems in gen.c relating to the name of token
+class bit sets in the output.
+
+Added the tremendously cool generalized predicate. For the
+moment, I'll give this bried description.
+
+a : <<predicate>>? blah
+ | foo
+ ;
+
+This implies that (assuming blah and foo are syntactically
+ambiguous) "predicate" indicates the semantic validity of
+applying "blah". If "predicate" is false, "foo" is attempted.
+
+Previously, you had to say:
+
+a : <<LA(1)==ID ? predicate : 1>>? ID
+ | ID
+ ;
+
+Now, you can simply use "predicate" without the ?: operator
+if you turn on ANTLR command line option: "-prc on". This
+tells ANTLR to compute that all by itself. It computes n
+tokens of lookahead where LT(n) or LATEXT(n) is the farthest
+ahead you look.
+
+If you give a predicate using "-prc on" that is followed
+by a construct that can recognize more than one n-sequence,
+you will get a warning from ANTLR. For example,
+
+a : <<isTypeName(LT(1)->getText())>>? (ID|INT)
+ ;
+
+This is wrong because the predicate will be applied to INTs
+as well as ID's. You should use this syntax to make
+the predicate more specific:
+
+a : (ID)? => <<isTypeName(LT(1)->getText())>>? (ID|INT)
+ ;
+
+which says "don't apply the predicate unless ID is the
+current lookahead context".
+
+You cannot currently have anything in the "(context)? =>"
+except sequences such as:
+
+( LPAREN ID | LPAREN SCOPE )? => <<pred>>?
+
+I haven't tested this THAT much, but it does work for the
+C++ grammar.
+
+======================================================================
+1.32b5
+
+Added getLine() to the ANTLRTokenBase and DLGBasedToken classes
+left line() for backward compatibility.
+----
+Removed SORCERER_TRANSFORM from the ast.h stuff.
+-------
+Fixed bug in code gen of ANTLR such that nested syn preds work more
+efficiently now. The ANTLRTokenBuffer was getting very large
+with nested predicates.
+------
+Memory leak is now gone from ANTLRTokenBuf; all tokens are deleted.
+For backward compatibility reasons, you have to say parser->deleteTokens()
+or mytokenbuffer->deleteTokens() but later it will be the default mode.
+Say this after the parser is constructed. E.g.,
+
+ ParserBlackBox<DLGLexer, MyParser, ANTLRToken> p(stdin);
+ p.parser()->deleteTokens();
+ p.parser()->start_symbol();
+
+
+==============================
+1.32b6
+
+Changed so that deleteTokens() will do a delete ((ANTLRTokenBase *))
+on the ptr. This gets the virtual destructor.
+
+Fixed some weird things in the C++ header files (a few return types).
+
+Made the AST routines correspond to the book and SORCERER stuff.
+
+New token stuff: See testcpp/14/test.g
+
+ANTLR accepts a #pragma gc_tokens which says
+[1] Generate label = copy(LT(1)) instead of label=LT(1) for
+ all labeled token references.
+[2] User now has to define ANTLRTokenPtr (as a class or a typedef
+ to just a pointer) as well as the ANTLRToken class itself.
+ See the example.
+
+To delete tokens in token buffer, use deleteTokens() message on parser.
+
+ All tokens that fall off the ANTLRTokenBuffer get deleted
+ which is what currently happens when deleteTokens() message
+ has been sent to token buffer.
+
+We always generate ANTLRTokenPtr instead of 'ANTLRToken *' now.
+Then if no pragma set, ANTLR generates a
+
+ class ANTLRToken;
+ typedef ANTLRToken *ANTLRTokenPtr;
+
+in each file.
+
+Made a warning for x:rule_ref <<$x>>; still no warning for $i's, however.
+class BB {
+
+a : x:b y:A <<$x
+$y>>
+ ;
+
+b : B;
+
+}
+generates
+Antlr parser generator Version 1.32b6 1989-1995
+test.g, line 3: error: There are no token ptrs for rule references: '$x'
+
+===================
+1.32b7:
+
+[With respect to token object garbage collection (GC), 1.32b7
+ backtracks from 1.32b6, but results in better and less intrusive GC.
+ This is the last beta version before full 1.32.]
+
+BIGGEST CHANGES:
+
+o The "#pragma gc_tokens" is no longer used.
+
+o .C files are now .cpp files (hence, makefiles will have to
+ be changed; or you can rerun genmk). This is a good move,
+ but causes some backward incompatibility problems. You can
+ avoid this by changing CPP_FILE_SUFFIX to ".C" in pccts/h/config.h.
+
+o The token object class hierarchy has been flattened to include
+ only three classes: ANTLRAbstractToken, ANTLRCommonToken, and
+ ANTLRCommonNoRefCountToken. The common token now does garbage
+ collection via ref counting.
+
+o "Smart" pointers are now used for garbage collection. That is,
+ ANTLRTokenPtr is used instead of "ANTLRToken *".
+
+o The antlr.1 man page has been cleaned up slightly.
+
+o The SUN C++ compiler now complains less about C++ support code.
+
+o Grammars which subclass ANTLRCommonToken must wrap all token
+ pointer references in mytoken(token_ptr). This is the only
+ serious backward incompatibility. See below.
+
+
+MINOR CHANGES:
+
+--------------------------------------------------------
+1 deleteTokens()
+
+The deleteTokens() message to the parser or token buffer has been changed
+to one of:
+
+ void noGarbageCollectTokens() { inputTokens->noGarbageCollectTokens(); }
+ void garbageCollectTokens() { inputTokens->garbageCollectTokens(); }
+
+The token buffer deletes all non-referenced tokens by default now.
+
+--------------------------------------------------------
+2 makeToken()
+
+The makeToken() message returns a new type. The function should look
+like:
+
+ virtual ANTLRAbstractToken *makeToken(ANTLRTokenType tt,
+ ANTLRChar *txt,
+ int line)
+ {
+ ANTLRAbstractToken *t = new ANTLRCommonToken(tt,txt);
+ t->setLine(line);
+ return t;
+ }
+
+--------------------------------------------------------
+3 TokenType
+
+Changed TokenType-> ANTLRTokenType (often forces changes in AST defs due
+to #[] constructor called to AST(tokentype, string)).
+
+--------------------------------------------------------
+4 AST()
+
+You must define AST(ANTLRTokenPtr t) now in your AST class definition.
+You might also have to include ATokPtr.h above the definition; e.g.,
+if AST is defined in a separate file, such as AST.h, it's a good idea
+to include ATOKPTR_H (ATokPtr.h). For example,
+
+ #include ATOKPTR_H
+ class AST : public ASTBase {
+ protected:
+ ANTLRTokenPtr token;
+ public:
+ AST(ANTLRTokenPtr t) { token = t; }
+ void preorder_action() {
+ char *s = token->getText();
+ printf(" %s", s);
+ }
+ };
+
+Note the use of smart pointers rather than "ANTLRToken *".
+
+--------------------------------------------------------
+5 SUN C++
+
+From robertb oakhill.sps.mot.com Bob Bailey. Changed ANTLR C++ output
+to avoid an error in Sun C++ 3.0.1. Made "public" return value
+structs created to hold multiple return values public.
+
+--------------------------------------------------------
+6 genmk
+
+Fixed genmk so that target List.* is not included anymore. It's
+called SList.* anyway.
+
+--------------------------------------------------------
+7 \r vs \n
+
+Scott Vorthmann <vorth cmu.edu> fixed antlr.g in ANTLR so that \r
+is allowed as the return character as well as \n.
+
+--------------------------------------------------------
+8 Exceptions
+
+Bug in exceptions attached to labeled token/tokclass references. Didn't gen
+code for exceptions. This didn't work:
+
+a : "help" x:ID
+ ;
+ exception[x]
+ catch MismatchedToken : <<printf("eh?\n");>>
+
+Now ANTLR generates (which is kinda big, but necessary):
+
+ if ( !_match_wsig(ID) ) {
+ if ( guessing ) goto fail;
+ _signal=MismatchedToken;
+ switch ( _signal ) {
+ case MismatchedToken :
+ printf("eh?\n");
+ _signal = NoSignal;
+ break;
+ default :
+ goto _handler;
+ }
+ }
+
+which implies that you can recover and continue parsing after a missing/bad
+token reference.
+
+--------------------------------------------------------
+9 genmk
+
+genmk now correctly uses config file for CPP_FILE_SUFFIX stuff.
+
+--------------------------------------------------------
+10 general cleanup / PURIFY
+
+Anthony Green <green vizbiz.com> suggested a bunch of good general
+clean up things for the code; he also suggested a few things to
+help out the "PURIFY" memory allocation checker.
+
+--------------------------------------------------------
+11 $-variable references.
+
+Manuel ORNATO indicated that a $-variable outside of a rule caused
+ANTLR to crash. I fixed this.
+
+12 Tom Moog suggestion
+
+Fail action of semantic predicate needs "{}" envelope. FIXED.
+
+13 references to LT(1).
+
+I have enclosed all assignments such as:
+
+ _t22 = (ANTLRTokenPtr)LT(1);
+
+in "if ( !guessing )" so that during backtracking the reference count
+for token objects is not increased.
+
+
+TOKEN OBJECT GARBAGE COLLECTION
+
+1 INTRODUCTION
+
+The class ANTLRCommonToken is now garbaged collected through a "smart"
+pointer called ANTLRTokenPtr using reference counting. Any token
+object not referenced by your grammar actions is destroyed by the
+ANTLRTokenBuffer when it must make room for more token objects.
+Referenced tokens are then destroyed in your parser when local
+ANTLRTokenPtr objects are deleted. For example,
+
+a : label:ID ;
+
+would be converted to something like:
+
+void yourclass::a(void)
+{
+ zzRULE;
+ ANTLRTokenPtr label=NULL; // used to be ANTLRToken *label;
+ zzmatch(ID);
+ label = (ANTLRTokenPtr)LT(1);
+ consume();
+ ...
+}
+
+When the "label" object is destroyed (it's just a pointer to your
+input token object LT(1)), it decrements the reference count on the
+object created for the ID. If the count goes to zero, the object
+pointed by label is deleted.
+
+To correctly manage the garbage collection, you should use
+ANTLRTokenPtr instead of "ANTLRToken *". Most ANTLR support code
+(visible to the user) has been modified to use the smart pointers.
+
+***************************************************************
+Remember that any local objects that you create are not deleted when a
+lonjmp() is executed. Unfortunately, the syntactic predicates (...)?
+use setjmp()/longjmp(). There are some situations when a few tokens
+will "leak".
+***************************************************************
+
+2 DETAILS
+
+o The default is to perform token object garbage collection.
+ You may use parser->noGarbageCollectTokens() to turn off
+ garbage collection.
+
+
+o The type ANTLRTokenPtr is always defined now (automatically).
+ If you do not wish to use smart pointers, you will have to
+ redefined ANTLRTokenPtr by subclassing, changing the header
+ file or changing ANTLR's code generation (easy enough to
+ do in gen.c).
+
+o If you don't use ParserBlackBox, the new initialization sequence is:
+
+ ANTLRTokenPtr aToken = new ANTLRToken;
+ scan.setToken(mytoken(aToken));
+
+ where mytoken(aToken) gets an ANTLRToken * from the smart pointer.
+
+o Define C++ preprocessor symbol DBG_REFCOUNTTOKEN to see a bunch of
+ debugging stuff for reference counting if you suspect something.
+
+
+3 WHY DO I HAVE TO TYPECAST ALL MY TOKEN POINTERS NOW??????
+
+If you subclass ANTLRCommonToken and then attempt to refer to one of
+your token members via a token pointer in your grammar actions, the
+C++ compiler will complain that your token object does not have that
+member. For example, if you used to do this
+
+<<
+class ANTLRToken : public ANTLRCommonToken {
+ int muck;
+ ...
+};
+>>
+
+class Foo {
+a : t:ID << t->muck = ...; >> ;
+}
+
+Now, you must do change the t->muck reference to:
+
+a : t:ID << mytoken(t)->muck = ...; >> ;
+
+in order to downcast 't' to be an "ANTLRToken *" not the
+"ANTLRAbstractToken *" resulting from ANTLRTokenPtr::operator->().
+The macro is defined as:
+
+/*
+ * Since you cannot redefine operator->() to return one of the user's
+ * token object types, we must down cast. This is a drag. Here's
+ * a macro that helps. template: "mytoken(a-smart-ptr)->myfield".
+ */
+#define mytoken(tp) ((ANTLRToken *)(tp.operator->()))
+
+You have to use macro mytoken(grammar-label) now because smart
+pointers are not specific to a parser's token objects. In other
+words, the ANTLRTokenPtr class has a pointer to a generic
+ANTLRAbstractToken not your ANTLRToken; the ANTLR support code must
+use smart pointers too, but be able to work with any kind of
+ANTLRToken. Sorry about this, but it's C++'s fault not mine. Some
+nebulous future version of the C++ compilers should obviate the need
+to downcast smart pointers with runtime type checking (and by allowing
+different return type of overridden functions).
+
+A way to have backward compatible code is to shut off the token object
+garbage collection; i.e., use parser->noGarbageCollectTokens() and
+change the definition of ANTLRTokenPtr (that's why you get source code
+<wink>).
+
+
+PARSER EXCEPTION HANDLING
+
+I've noticed some weird stuff with the exception handling. I intend
+to give this top priority for the "book release" of ANTLR.
+
+==========
+1.32 Full Release
+
+o Changed Token class hierarchy to be (Thanks to Tom Moog):
+
+ ANTLRAbstractToken
+ ANTLRRefCountToken
+ ANTLRCommonToken
+ ANTLRNoRefCountCommonToken
+
+o Added virtual panic() to ANTLRAbstractToken. Made ANTLRParser::panic()
+ virtual also.
+
+o Cleaned up the dup() stuff in AST hierarchy to use shallowCopy() to
+ make node copies. John Farr at Medtronic suggested this. I.e.,
+ if you want to use dup() with either ANTLR or SORCERER or -transform
+ mode with SORCERER, you must defined shallowCopy() as:
+
+ virtual PCCTS_AST *shallowCopy()
+ {
+ return new AST;
+ p->setDown(NULL);
+ p->setRight(NULL);
+ return p;
+ }
+
+ or
+
+ virtual PCCTS_AST *shallowCopy()
+ {
+ return new AST(*this);
+ }
+
+ if you have defined a copy constructor such as
+
+ AST(const AST &t) // shallow copy constructor
+ {
+ token = t.token;
+ iconst = t.iconst;
+ setDown(NULL);
+ setRight(NULL);
+ }
+
+o Added a warning with -CC and -gk are used together. This is broken,
+ hence a warning is appropriate.
+
+o Added warning when #-stuff is used w/o -gt option.
+
+o Updated MPW installation.
+
+o "Miller, Philip W." <MILLERPW f1groups.fsd.jhuapl.edu> suggested
+ that genmk be use RENAME_OBJ_FLAG RENAME_EXE_FLAG instead of
+ hardcoding "-o" in genmk.c.
+
+o made all exit() calls use EXIT_SUCCESS or EXIT_FAILURE.
+
+===========================================================================
+1.33
+
+EXIT_FAILURE and EXIT_SUCCESS were not always defined. I had to modify
+a bunch of files to use PCCTS_EXIT_XXX, which forces a new version. Sorry
+about that.
+
diff --git a/Source/Pccts/CHANGES_FROM_133.txt b/Source/Pccts/CHANGES_FROM_133.txt
new file mode 100644
index 0000000..2128c4f
--- /dev/null
+++ b/Source/Pccts/CHANGES_FROM_133.txt
@@ -0,0 +1,2448 @@
+=======================================================================
+List of Implemented Fixes and Changes for Maintenance Releases of PCCTS
+=======================================================================
+
+ DISCLAIMER
+
+ The software and these notes are provided "as is". They may include
+ typographical or technical errors and their authors disclaims all
+ liability of any kind or nature for damages due to error, fault,
+ defect, or deficiency regardless of cause. All warranties of any
+ kind, either express or implied, including, but not limited to, the
+ implied warranties of merchantability and fitness for a particular
+ purpose are disclaimed.
+
+
+ -------------------------------------------------------
+ Note: Items #153 to #1 are now in a separate file named
+ CHANGES_FROM_133_BEFORE_MR13.txt
+ -------------------------------------------------------
+
+#312. (Changed in MR33) Bug caused by change #299.
+
+ In change #299 a warning message was suppressed when there was
+ no LT(1) in a semantic predicate and max(k,ck) was 1. The
+ changed caused the code which set a default predicate depth for
+ the semantic predicate to be left as 0 rather than set to 1.
+
+ This manifested as an error at line #1559 of mrhost.c
+
+ Reported by Peter Dulimov.
+
+#311. (Changed in MR33) Added sorcer/lib to Makefile.
+
+ Reported by Dale Martin.
+
+#310. (Changed in MR32) In C mode zzastPush was spelled zzastpush in one case.
+
+ Reported by Jean-Claude Durand
+
+#309. (Changed in MR32) Renamed baseName because of VMS name conflict
+
+ Renamed baseName to pcctsBaseName to avoid library name conflict with
+ VMS library routine. Reported by Jean-François PIÉRONNE.
+
+#308. (Changed in MR32) Used "template" as name of formal in C routine
+
+ In astlib.h routine ast_scan a formal was named "template". This caused
+ problems when the C code was compiled with a C++ compiler. Reported by
+ Sabyasachi Dey.
+
+#307. (Changed in MR31) Compiler dependent bug in function prototype generation
+
+ The code which generated function prototypes contained a bug which
+ was compiler/optimization dependent. Under some circumstance an
+ extra character would be included in portions of a function prototype.
+
+ Reported by David Cook.
+
+#306. (Changed in MR30) Validating predicate following a token
+
+ A validating predicate which immediately followed a token match
+ consumed the token after the predicate rather than before. Prior
+ to this fix (in the following example) isValidTimeScaleValue() in
+ the predicate would test the text for TIMESCALE rather than for
+ NUMBER:
+
+ time_scale :
+ TIMESCALE
+ <<isValidTimeScaleValue(LT(1)->getText())>>?
+ ts:NUMBER
+ ( us:MICROSECOND << tVal = ...>>
+ | ns:NANOSECOND << tVal = ... >>
+ )
+
+ Reported by Adalbert Perbandt.
+
+#305. (Changed in MR30) Alternatives with guess blocks inside (...)* blocks.
+
+ In MR14 change #175 fixed a bug in the prediction expressions for guess
+ blocks which were of the form (alpha)? beta. Unfortunately, this
+ resulted in a new bug as exemplified by the example below, which computed
+ the first set for r as {B} rather than {B C}:
+
+ r : ( (A)? B
+ | C
+ )*
+
+ This example doesn't make any sense as A is not a prefix of B, but it
+ illustrates the problem. This bug did not appear for:
+
+ r : ( (A)?
+ | C
+ )*
+
+ because it does not use the (alpha)? beta form.
+
+ Item #175 fixed an asymmetry in ambiguity messages for the following
+ constructs which appear to have identical ambiguities (between repeating
+ the loop vs. exiting the loop). MR30 retains this fix, but the implementation
+ is slightly different.
+
+ r_star : ( (A B)? )* A ;
+ r_plus : ( (A B)? )+ A ;
+
+ Reported by Arpad Beszedes (beszedes inf.u-szeged.hu).
+
+#304. (Changed in MR30) Crash when mismatch between output value counts.
+
+ For a rule such as:
+
+ r1 : r2>[i,j];
+ r2 >[int i, int j] : A;
+
+ If there were extra actuals for the reference to rule r2 from rule r1
+ there antlr would crash. This bug was introduced by change #276.
+
+ Reported by Sinan Karasu.
+
+#303. (Changed in MR30) DLGLexerBase::replchar
+
+ DLGLexerBase::replchar and the C mode routine zzreplchar did not work
+ properly when the new character was 0.
+
+ Reported with fix by Philippe Laporte
+
+#302. (Changed in MR28) Fix significant problems in initial release of MR27.
+
+#301. (Changed in MR27) Default tab stops set to 2 spaces.
+
+ To have antlr generate true tabs rather than spaces, use "antlr -tab 0".
+ To generate 4 spaces per tab stop use "antlr -tab 4"
+
+#300. (Changed in MR27)
+
+ Consider the following methods of constructing an AST from ID:
+
+ rule1!
+ : id:ID << #0 = #[id]; >> ;
+
+ rule2!
+ : id:ID << #0 = #id; >> ;
+
+ rule3
+ : ID ;
+
+ rule4
+ : id:ID << #0 = #id; >> ;
+
+ For rule_2, the AST corresponding to id would always be NULL. This
+ is because the user explicitly suppressed AST construction using the
+ "!" operator on the rule. In MR27 the use of an AST expression
+ such as #id overrides the "!" operator and forces construction of
+ the AST.
+
+ This fix does not apply to C mode ASTs when the ASTs are referenced
+ using numbers rather than symbols.
+
+ For C mode, this requires that the (optional) function/macro zzmk_ast
+ be defined. This functions copies information from an attribute into
+ a previously allocated AST.
+
+ Reported by Jan Langer (jan langernetz.de)
+
+#299. (Changed in MR27) Don't warn if k=1 and semantic predicate missing LT(i)
+
+ If a semantic does not have a reference to LT(i) or (C mode LATEXT(i))
+ then pccts doesn't know how many lookahead tokens to use for context.
+ However, if max(k,ck) is 1 then there is really only one choice and
+ the warning is unnecessary.
+
+#298. (Changed in MR27) Removed "register" for lastpos in dlgauto.c zzgettok
+
+#297. (Changed in MR27) Incorrect prototypes when used with classic C
+
+ There were a number of errors in function headers when antlr was
+ built with compilers that do not have __STDC__ or __cplusplus set.
+
+ The functions which have variable length argument lists now use
+ PCCTS_USE_STDARG rather than __USE_PROTOTYPES__ to determine
+ whether to use stdargs or varargs.
+
+#296. (Changed in MR27) Complex return types in rules.
+
+ The following return type was not properly handled when
+ unpacking a struct with containing multiple return values:
+
+ rule > [int i, IIR_Bool (IIR_Decl::*constraint)()] : ...
+
+ Instead of using "constraint", the program got lost and used
+ an empty string.
+
+ Reported by P.A. Wilsey.
+
+#295. (Changed in MR27) Extra ";" following zzGUESS_DONE sometimes.
+
+ Certain constructs with guess blocks in MR23 led to extra ";"
+ preceding the "else" clause of an "if".
+
+ Reported by P.A. Wilsey.
+
+#294. (Changed in MR27) Infinite loop in antlr for nested blocks
+
+ An oversight in detecting an empty alternative sometimes led
+ to an infinite loop in antlr when it encountered a rule with
+ nested blocks and guess blocks.
+
+ Reported by P.A. Wilsey.
+
+#293. (Changed in MR27) Sorcerer optimization of _t->type()
+
+ Sorcerer generated code may contain many calls to _t->type() in a
+ single statement. This change introduces a temporary variable
+ to eliminate unnnecesary function calls.
+
+ Change implemented by Tom Molteno (tim videoscript.com).
+
+#292. (Changed in MR27)
+
+ WARNING: Item #267 changes the signature of methods in the AST class.
+
+ **** Be sure to revise your AST functions of the same name ***
+
+#291. (Changed in MR24)
+
+ Fix to serious code generation error in MR23 for (...)+ block.
+
+#290. (Changed in MR23)
+
+ Item #247 describes a change in the way {...} blocks handled
+ an error. Consider:
+
+ r1 : {A} b ;
+ b : B;
+
+ with input "C".
+
+ Prior to change #247, the error would resemble "expected B -
+ found C". This is correct but incomplete, and therefore
+ misleading. In #247 it was changed to "expected A, B - found
+ C". This was fine, except for users of parser exception
+ handling because the exception was generated in the epilogue
+ for {...} block rather than in rule b. This made it difficult
+ for users of parser exception handling because B was not
+ expected in that context. Those not using parser exception
+ handling didn't notice the difference.
+
+ The current change restores the behavior prior to #247 when
+ parser exceptions are present, but retains the revised behavior
+ otherwise. This change should be visible only when exceptions
+ are in use and only for {...} blocks and sub-blocks of the form
+ (something|something | something | epsilon) where epsilon represents
+ an empty production and it is the last alternative of a sub-block.
+ In contrast, (something | epsilon | something) should generate the
+ same code as before, even when exceptions are used.
+
+ Reported by Philippe Laporte (philippe at transvirtual.com).
+
+#289. (Changed in MR23) Bug in matching complement of a #tokclass
+
+ Prior to MR23 when a #tokclass was matched in both its complemented form
+ and uncomplemented form, the bit set generated for its first use was used
+ for both cases. However, the prediction expression was correctly computed
+ in both cases. This meant that the second case would never be matched
+ because, for the second appearance, the prediction expression and the
+ set to be matched would be complements of each other.
+
+ Consider:
+
+ #token A "a"
+ #token B "b"
+ #token C "c"
+ #tokclass AB {A B}
+
+ r1 : AB /* alt 1x */
+ | ~AB /* alt 1y */
+ ;
+
+ Prior to MR23, this resulted in alternative 1y being unreachable. Had it
+ been written:
+
+ r2 : ~AB /* alt 2x */
+ : AB /* alt 2y */
+
+ then alternative 2y would have become unreachable.
+
+ This bug was only for the case of complemented #tokclass. For complemented
+ #token the proper code was generated.
+
+#288. (Changed in MR23) #errclass not restricted to choice points
+
+ The #errclass directive is supposed to allow a programmer to define
+ print strings which should appear in syntax error messages as a replacement
+ for some combinations of tokens. For instance:
+
+ #errclass Operator {PLUS MINUS TIMES DIVIDE}
+
+ If a syntax message includes all four of these tokens, and there is no
+ "better" choice of error class, the word "Operator" will be used rather
+ than a list of the four token names.
+
+ Prior to MR23 the #errclass definitions were used only at choice points
+ (which call the FAIL macro). In other cases where there was no choice
+ (e.g. where a single token or token class were matched) the #errclass
+ information was not used.
+
+ With MR23 the #errclass declarations are used for syntax error messages
+ when matching a #tokclass, a wildcard (i.e. "*"), or the complement of a
+ #token or #tokclass (e.g. ~Operator).
+
+ Please note that #errclass may now be defined using #tokclass names
+ (see Item #284).
+
+ Reported by Philip A. Wilsey.
+
+#287. (Changed in MR23) Print name for #tokclass
+
+ Item #148 describes how to give a print name to a #token so that,for
+ example, #token ID could have the expression "identifier" in syntax
+ error messages. This has been extended to #tokclass:
+
+ #token ID("identifier") "[a-zA-Z]+"
+ #tokclass Primitive("primitive type")
+ {INT, FLOAT, CHAR, FLOAT, DOUBLE, BOOL}
+
+ This is really a cosmetic change, since #tokclass names do not appear
+ in any error messages.
+
+#286. (Changed in MR23) Makefile change to use of cd
+
+ In cases where a pccts subdirectory name matched a directory identified
+ in a $CDPATH environment variable the build would fail. All makefile
+ cd commands have been changed from "cd xyz" to "cd ./xyz" in order
+ to avoid this problem.
+
+#285. (Changed in MR23) Check for null pointers in some dlg structures
+
+ An invalid regular expression can cause dlg to build an invalid
+ structure to represent the regular expression even while it issues
+ error messages. Additional pointer checks were added.
+
+ Reported by Robert Sherry.
+
+#284. (Changed in MR23) Allow #tokclass in #errclass definitions
+
+ Previously, a #tokclass reference in the definition of an
+ #errclass was not handled properly. Instead of being expanded
+ into the set of tokens represented by the #tokclass it was
+ treated somewhat like an #errclass. However, in a later phase
+ when all #errclass were expanded into the corresponding tokens
+ the #tokclass reference was not expanded (because it wasn't an
+ #errclass). In effect the reference was ignored.
+
+ This has been fixed.
+
+ Problem reported by Mike Dimmick (mike dimmick.demon.co.uk).
+
+#283. (Changed in MR23) Option -tmake invoke's parser's tmake
+
+ When the string #(...) appears in an action antlr replaces it with
+ a call to ASTBase::tmake(...) to construct an AST. It is sometimes
+ useful to change the tmake routine so that it has access to information
+ in the parser - something which is not possible with a static method
+ in an application where they may be multiple parsers active.
+
+ The antlr option -tmake replaces the call to ASTBase::tmake with a call
+ to a user supplied tmake routine.
+
+#282. (Changed in MR23) Initialization error for DBG_REFCOUNTTOKEN
+
+ When the pre-processor symbol DBG_REFCOUNTTOKEN is defined
+ incorrect code is generated to initialize ANTLRRefCountToken::ctor and
+ dtor.
+
+ Fix reported by Sven Kuehn (sven sevenkuehn.de).
+
+#281. (Changed in MR23) Addition of -noctor option for Sorcerer
+
+ Added a -noctor option to suppress generation of the blank ctor
+ for users who wish to define their own ctor.
+
+ Contributed by Jan Langer (jan langernetz.de).
+
+#280. (Changed in MR23) Syntax error message for EOF token
+
+ The EOF token now receives special treatment in syntax error messages
+ because there is no text matched by the eof token. The token name
+ of the eof token is used unless it is "@" - in which case the string
+ "<eof>" is used.
+
+ Problem reported by Erwin Achermann (erwin.achermann switzerland.org).
+
+#279. (Changed in MR23) Exception groups
+
+ There was a bug in the way that exception groups were attached to
+ alternatives which caused problems when there was a block contained
+ in an alternative. For instance, in the following rule;
+
+ statement : IF S { ELSE S }
+ exception ....
+ ;
+
+ the exception would be attached to the {...} block instead of the
+ entire alternative because it was attached, in error, to the last
+ alternative instead of the last OPEN alternative.
+
+ Reported by Ty Mordane (tymordane hotmail.com).
+
+#278. (Changed in MR23) makefile changes
+
+ Contributed by Tomasz Babczynski (faster lab05-7.ict.pwr.wroc.pl).
+
+ The -cfile option is not absolutely needed: when extension of
+ source file is one of the well-known C/C++ extensions it is
+ treated as C/C++ source
+
+ The gnu make defines the CXX variable as the default C++ compiler
+ name, so I added a line to copy this (if defined) to the CCC var.
+
+ Added a -sor option: after it any -class command defines the class
+ name for sorcerer, not for ANTLR. A file extended with .sor is
+ treated as sorcerer input. Because sorcerer can be called multiple
+ times, -sor option can be repeated. Any files and classes (one class
+ per group) after each -sor makes one tree parser.
+
+ Not implemented:
+
+ 1. Generate dependences for user c/c++ files.
+ 2. Support for -sor in c mode not.
+
+ I have left the old genmk program in the directory as genmk_old.c.
+
+#277. (Changed in MR23) Change in macro for failed semantic predicates
+
+ In the past, a semantic predicate that failed generated a call to
+ the macro zzfailed_pred:
+
+ #ifndef zzfailed_pred
+ #define zzfailed_pred(_p) \
+ if (guessing) { \
+ zzGUESS_FAIL; \
+ } else { \
+ something(_p)
+ }
+ #endif
+
+ If a user wished to use the failed action option for semantic predicates:
+
+ rule : <<my_predicate>>? [my_fail_action] A
+ | ...
+
+
+ the code for my_fail_action would have to contain logic for handling
+ the guess part of the zzfailed_pred macro. The user should not have
+ to be aware of the guess logic in writing the fail action.
+
+ The zzfailed_pred has been rewritten to have three arguments:
+
+ arg 1: the stringized predicate of the semantic predicate
+ arg 2: 0 => there is no user-defined fail action
+ 1 => there is a user-defined fail action
+ arg 3: the user-defined fail action (if defined)
+ otherwise a no-operation
+
+ The zzfailed_pred macro is now defined as:
+
+ #ifndef zzfailed_pred
+ #define zzfailed_pred(_p,_hasuseraction,_useraction) \
+ if (guessing) { \
+ zzGUESS_FAIL; \
+ } else { \
+ zzfailed_pred_action(_p,_hasuseraction,_useraction) \
+ }
+ #endif
+
+
+ With zzfailed_pred_action defined as:
+
+ #ifndef zzfailed_pred_action
+ #define zzfailed_pred_action(_p,_hasuseraction,_useraction) \
+ if (_hasUserAction) { _useraction } else { failedSemanticPredicate(_p); }
+ #endif
+
+ In C++ mode failedSemanticPredicate() is a virtual function.
+ In C mode the default action is a fprintf statement.
+
+ Suggested by Erwin Achermann (erwin.achermann switzerland.org).
+
+#276. (Changed in MR23) Addition of return value initialization syntax
+
+ In an attempt to reduce the problems caused by the PURIFY macro I have
+ added new syntax for initializing the return value of rules and the
+ antlr option "-nopurify".
+
+ A rule with a single return argument:
+
+ r1 > [Foo f = expr] :
+
+ now generates code that resembles:
+
+ Foo r1(void) {
+ Foo _retv = expr;
+ ...
+ }
+
+ A rule with more than one return argument:
+
+ r2 > [Foo f = expr1, Bar b = expr2 ] :
+
+ generates code that resembles:
+
+ struct _rv1 {
+ Foo f;
+ Bar b;
+ }
+
+ _rv1 r2(void) {
+ struct _rv1 _retv;
+ _retv.f = expr1;
+ _retv.b = expr2;
+ ...
+ }
+
+ C++ style comments appearing in the initialization list may cause problems.
+
+#275. (Changed in MR23) Addition of -nopurify option to antlr
+
+ A long time ago the PURIFY macro was introduced to initialize
+ return value arguments and get rid of annying messages from program
+ that checked for unitialized variables.
+
+ This has caused significant annoyance for C++ users that had
+ classes with virtual functions or non-trivial contructors because
+ it would zero the object, including the pointer to the virtual
+ function table. This could be defeated by redefining
+ the PURIFY macro to be empty, but it was a constant surprise to
+ new C++ users of pccts.
+
+ I would like to remove it, but I fear that some existing programs
+ depend on it and would break. My temporary solution is to add
+ an antlr option -nopurify which disables generation of the PURIFY
+ macro call.
+
+ The PURIFY macro should be avoided in favor of the new syntax
+ for initializing return arguments described in item #275.
+
+ To avoid name clash, the PURIFY macro has been renamed PCCTS_PURIFY.
+
+#274. (Changed in MR23) DLexer.cpp renamed to DLexer.h
+ (Changed in MR23) ATokPtr.cpp renamed to ATokPtrImpl.h
+
+ These two files had .cpp extensions but acted like .h files because
+ there were included in other files. This caused problems for many IDE.
+ I have renamed them. The ATokPtrImpl.h was necessary because there was
+ already an ATokPtr.h.
+
+#273. (Changed in MR23) Default win32 library changed to multi-threaded DLL
+
+ The model used for building the Win32 debug and release libraries has changed
+ to multi-threaded DLL.
+
+ To make this change in your MSVC 6 project:
+
+ Project -> Settings
+ Select the C++ tab in the right pane of the dialog box
+ Select "Category: Code Generation"
+ Under "Use run-time library" select one of the following:
+
+ Multi-threaded DLL
+ Debug Multi-threaded DLL
+
+ Suggested by Bill Menees (bill.menees gogallagher.com)
+
+#272. (Changed in MR23) Failed semantic predicate reported via virtual function
+
+ In the past, a failed semantic predicated reported the problem via a
+ macro which used fprintf(). The macro now expands into a call on
+ the virtual function ANTLRParser::failedSemanticPredicate().
+
+#271. (Changed in MR23) Warning for LT(i), LATEXT(i) in token match actions
+
+ An bug (or at least an oddity) is that a reference to LT(1), LA(1),
+ or LATEXT(1) in an action which immediately follows a token match
+ in a rule refers to the token matched, not the token which is in
+ the lookahead buffer. Consider:
+
+ r : abc <<action alpha>> D <<action beta>> E;
+
+ In this case LT(1) in action alpha will refer to the next token in
+ the lookahead buffer ("D"), but LT(1) in action beta will refer to
+ the token matched by D - the preceding token.
+
+ A warning has been added for users about this when an action
+ following a token match contains a reference to LT(1), LA(1), or LATEXT(1).
+
+ This behavior should be changed, but it appears in too many programs
+ now. Another problem, perhaps more significant, is that the obvious
+ fix (moving the consume() call to before the action) could change the
+ order in which input is requested and output appears in existing programs.
+
+ This problem was reported, along with a fix by Benjamin Mandel
+ (beny sd.co.il). However, I felt that changing the behavior was too
+ dangerous for existing code.
+
+#270. (Changed in MR23) Removed static objects from PCCTSAST.cpp
+
+ There were some statically allocated objects in PCCTSAST.cpp
+ These were changed to non-static.
+
+#269. (Changed in MR23) dlg output for initializing static array
+
+ The output from dlg contains a construct similar to the
+ following:
+
+ struct XXX {
+ static const int size;
+ static int array1[5];
+ };
+
+ const int XXX::size = 4;
+ int XXX::array1[size+1];
+
+
+ The problem is that although the expression "size+1" used in
+ the definition of array1 is equal to 5 (the expression used to
+ declare array), it is not considered equivalent by some compilers.
+
+ Reported with fix by Volker H. Simonis (simonis informatik.uni-tuebingen.de)
+
+#268. (Changed in MR23) syn() routine output when k > 1
+
+ The syn() routine is supposed to print out the text of the
+ token causing the syntax error. It appears that it always
+ used the text from the first lookahead token rather than the
+ appropriate one. The appropriate one is computed by comparing
+ the token codes of lookahead token i (for i = 1 to k) with
+ the FIRST(i) set.
+
+ This has been corrected in ANTLRParser::syn().
+
+ Reported by Bill Menees (bill.menees gogallagher.com)
+
+#267. (Changed in MR23) AST traversal functions client data argument
+
+ The AST traversal functions now take an extra (optional) parameter
+ which can point to client data:
+
+ preorder_action(void* pData = NULL)
+ preorder_before_action(void* pData = NULL)
+ preorder_after_action(void* pData = NULL)
+
+ **** Warning: this changes the AST signature. ***
+ **** Be sure to revise your AST functions of the same name ***
+
+ Bill Menees (bill.menees gogallagher.com)
+
+#266. (Changed in MR23) virtual function printMessage()
+
+ Bill Menees (bill.menees gogallagher.com) has completed the
+ tedious taks of replacing all calls to fprintf() with calls
+ to the virtual function printMessage(). For classes which
+ have a pointer to the parser it forwards the printMessage()
+ call to the parser's printMessage() routine.
+
+ This should make it significanly easier to redirect pccts
+ error and warning messages.
+
+#265. (Changed in MR23) Remove "labase++" in C++ mode
+
+ In C++ mode labase++ is called when a token is matched.
+ It appears that labase is not used in C++ mode at all, so
+ this code has been commented out.
+
+#264. (Changed in MR23) Complete rewrite of ParserBlackBox.h
+
+ The parser black box (PBlackBox.h) was completely rewritten
+ by Chris Uzdavinis (chris atdesk.com) to improve its robustness.
+
+#263. (Changed in MR23) -preamble and -preamble_first rescinded
+
+ Changes for item #253 have been rescinded.
+
+#262. (Changed in MR23) Crash with -alpha option during traceback
+
+ Under some circumstances a -alpha traceback was started at the
+ "wrong" time. As a result, internal data structures were not
+ initialized.
+
+ Reported by Arpad Beszedes (beszedes inf.u-szeged.hu).
+
+#261. (Changed in MR23) Defer token fetch for C++ mode
+
+ Item #216 has been revised to indicate that use of the defer fetch
+ option (ZZDEFER_FETCH) requires dlg option -i.
+
+#260. (MR22) Raise default lex buffer size from 8,000 to 32,000 bytes.
+
+ ZZLEXBUFSIZE is the size (in bytes) of the buffer used by dlg
+ generated lexers. The default value has been raised to 32,000 and
+ the value used by antlr, dlg, and sorcerer has also been raised to
+ 32,000.
+
+#259. (MR22) Default function arguments in C++ mode.
+
+ If a rule is declared:
+
+ rr [int i = 0] : ....
+
+ then the declaration generated by pccts resembles:
+
+ void rr(int i = 0);
+
+ however, the definition must omit the default argument:
+
+ void rr(int i) {...}
+
+ In the past the default value was not omitted. In MR22
+ the generated code resembles:
+
+ void rr(int i /* = 0 */ ) {...}
+
+ Implemented by Volker H. Simonis (simonis informatik.uni-tuebingen.de)
+
+
+ Note: In MR23 this was changed so that nested C style comments
+ ("/* ... */") would not cause problems.
+
+#258. (MR22) Using a base class for your parser
+
+ In item #102 (MR10) the class statement was extended to allow one
+ to specify a base class other than ANTLRParser for the generated
+ parser. It turned out that this was less than useful because
+ the constructor still specified ANTLRParser as the base class.
+
+ The class statement now uses the first identifier appearing after
+ the ":" as the name of the base class. For example:
+
+ class MyParser : public FooParser {
+
+ Generates in MyParser.h:
+
+ class MyParser : public FooParser {
+
+ Generates in MyParser.cpp something that resembles:
+
+ MyParser::MyParser(ANTLRTokenBuffer *input) :
+ FooParser(input,1,0,0,4)
+ {
+ token_tbl = _token_tbl;
+ traceOptionValueDefault=1; // MR10 turn trace ON
+ }
+
+ The base class constructor must have a signature similar to
+ that of ANTLRParser.
+
+#257. (MR21a) Removed dlg statement that -i has no effect in C++ mode.
+
+ This was incorrect.
+
+#256. (MR21a) Malformed syntax graph causes crash after error message.
+
+ In the past, certain kinds of errors in the very first grammar
+ element could cause the construction of a malformed graph
+ representing the grammar. This would eventually result in a
+ fatal internal error. The code has been changed to be more
+ resistant to this particular error.
+
+#255. (MR21a) ParserBlackBox(FILE* f)
+
+ This constructor set openByBlackBox to the wrong value.
+
+ Reported by Kees Bakker (kees_bakker tasking.nl).
+
+#254. (MR21a) Reporting syntax error at end-of-file
+
+ When there was a syntax error at the end-of-file the syntax
+ error routine would substitute "<eof>" for the programmer's
+ end-of-file symbol. This substitution is now done only when
+ the programmer does not define his own end-of-file symbol
+ or the symbol begins with the character "@".
+
+ Reported by Kees Bakker (kees_bakker tasking.nl).
+
+#253. (MR21) Generation of block preamble (-preamble and -preamble_first)
+
+ *** This change was rescinded by item #263 ***
+
+ The antlr option -preamble causes antlr to insert the code
+ BLOCK_PREAMBLE at the start of each rule and block. It does
+ not insert code before rules references, token references, or
+ actions. By properly defining the macro BLOCK_PREAMBLE the
+ user can generate code which is specific to the start of blocks.
+
+ The antlr option -preamble_first is similar, but inserts the
+ code BLOCK_PREAMBLE_FIRST(PreambleFirst_123) where the symbol
+ PreambleFirst_123 is equivalent to the first set defined by
+ the #FirstSetSymbol described in Item #248.
+
+ I have not investigated how these options interact with guess
+ mode (syntactic predicates).
+
+#252. (MR21) Check for null pointer in trace routine
+
+ When some trace options are used when the parser is generated
+ without the trace enabled, the current rule name may be a
+ NULL pointer. A guard was added to check for this in
+ restoreState.
+
+ Reported by Douglas E. Forester (dougf projtech.com).
+
+#251. (MR21) Changes to #define zzTRACE_RULES
+
+ The macro zzTRACE_RULES was being use to pass information to
+ AParser.h. If this preprocessor symbol was not properly
+ set the first time AParser.h was #included, the declaration
+ of zzTRACEdata would be omitted (it is used by the -gd option).
+ Subsequent #includes of AParser.h would be skipped because of
+ the #ifdef guard, so the declaration of zzTracePrevRuleName would
+ never be made. The result was that proper compilation was very
+ order dependent.
+
+ The declaration of zzTRACEdata was made unconditional and the
+ problem of removing unused declarations will be left to optimizers.
+
+ Diagnosed by Douglas E. Forester (dougf projtech.com).
+
+#250. (MR21) Option for EXPERIMENTAL change to error sets for blocks
+
+ The antlr option -mrblkerr turns on an experimental feature
+ which is supposed to provide more accurate syntax error messages
+ for k=1, ck=1 grammars. When used with k>1 or ck>1 grammars the
+ behavior should be no worse than the current behavior.
+
+ There is no problem with the matching of elements or the computation
+ of prediction expressions in pccts. The task is only one of listing
+ the most appropriate tokens in the error message. The error sets used
+ in pccts error messages are approximations of the exact error set when
+ optional elements in (...)* or (...)+ are involved. While entirely
+ correct, the error messages are sometimes not 100% accurate.
+
+ There is also a minor philosophical issue. For example, suppose the
+ grammar expects the token to be an optional A followed by Z, and it
+ is X. X, of course, is neither A nor Z, so an error message is appropriate.
+ Is it appropriate to say "Expected Z" ? It is correct, it is accurate,
+ but it is not complete.
+
+ When k>1 or ck>1 the problem of providing the exactly correct
+ list of tokens for the syntax error messages ends up becoming
+ equivalent to evaluating the prediction expression for the
+ alternatives twice. However, for k=1 ck=1 grammars the prediction
+ expression can be computed easily and evaluated cheaply, so I
+ decided to try implementing it to satisfy a particular application.
+ This application uses the error set in an interactive command language
+ to provide prompts which list the alternatives available at that
+ point in the parser. The user can then enter additional tokens to
+ complete the command line. To do this required more accurate error
+ sets then previously provided by pccts.
+
+ In some cases the default pccts behavior may lead to more robust error
+ recovery or clearer error messages then having the exact set of tokens.
+ This is because (a) features like -ge allow the use of symbolic names for
+ certain sets of tokens, so having extra tokens may simply obscure things
+ and (b) the error set is use to resynchronize the parser, so a good
+ choice is sometimes more important than having the exact set.
+
+ Consider the following example:
+
+ Note: All examples code has been abbreviated
+ to the absolute minimum in order to make the
+ examples concise.
+
+ star1 : (A)* Z;
+
+ The generated code resembles:
+
+ old new (with -mrblkerr)
+ --//----------- --------------------
+ for (;;) { for (;;) {
+ match(A); match(A);
+ } }
+ match(Z); if (! A and ! Z) then
+ FAIL(...{A,Z}...);
+ }
+ match(Z);
+
+
+ With input X
+ old message: Found X, expected Z
+ new message: Found X, expected A, Z
+
+ For the example:
+
+ star2 : (A|B)* Z;
+
+ old new (with -mrblkerr)
+ ------------- --------------------
+ for (;;) { for (;;) {
+ if (!A and !B) break; if (!A and !B) break;
+ if (...) { if (...) {
+ <same ...> <same ...>
+ } }
+ else { else {
+ FAIL(...{A,B,Z}...) FAIL(...{A,B}...);
+ } }
+ } }
+ match(B); if (! A and ! B and !Z) then
+ FAIL(...{A,B,Z}...);
+ }
+ match(B);
+
+ With input X
+ old message: Found X, expected Z
+ new message: Found X, expected A, B, Z
+ With input A X
+ old message: Found X, expected Z
+ new message: Found X, expected A, B, Z
+
+ This includes the choice of looping back to the
+ star block.
+
+ The code for plus blocks:
+
+ plus1 : (A)+ Z;
+
+ The generated code resembles:
+
+ old new (with -mrblkerr)
+ ------------- --------------------
+ do { do {
+ match(A); match(A);
+ } while (A) } while (A)
+ match(Z); if (! A and ! Z) then
+ FAIL(...{A,Z}...);
+ }
+ match(Z);
+
+ With input A X
+ old message: Found X, expected Z
+ new message: Found X, expected A, Z
+
+ This includes the choice of looping back to the
+ plus block.
+
+ For the example:
+
+ plus2 : (A|B)+ Z;
+
+ old new (with -mrblkerr)
+ ------------- --------------------
+ do { do {
+ if (A) { <same>
+ match(A); <same>
+ } else if (B) { <same>
+ match(B); <same>
+ } else { <same>
+ if (cnt > 1) break; <same>
+ FAIL(...{A,B,Z}...) FAIL(...{A,B}...);
+ } }
+ cnt++; <same>
+ } }
+
+ match(Z); if (! A and ! B and !Z) then
+ FAIL(...{A,B,Z}...);
+ }
+ match(B);
+
+ With input X
+ old message: Found X, expected A, B, Z
+ new message: Found X, expected A, B
+ With input A X
+ old message: Found X, expected Z
+ new message: Found X, expected A, B, Z
+
+ This includes the choice of looping back to the
+ star block.
+
+#249. (MR21) Changes for DEC/VMS systems
+
+ Jean-François Piéronne (jfp altavista.net) has updated some
+ VMS related command files and fixed some minor problems related
+ to building pccts under the DEC/VMS operating system. For DEC/VMS
+ users the most important differences are:
+
+ a. Revised makefile.vms
+ b. Revised genMMS for genrating VMS style makefiles.
+
+#248. (MR21) Generate symbol for first set of an alternative
+
+ pccts can generate a symbol which represents the tokens which may
+ appear at the start of a block:
+
+ rr : #FirstSetSymbol(rr_FirstSet) ( Foo | Bar ) ;
+
+ This will generate the symbol rr_FirstSet of type SetWordType with
+ elements Foo and Bar set. The bits can be tested using code similar
+ to the following:
+
+ if (set_el(Foo, &rr_FirstSet)) { ...
+
+ This can be combined with the C array zztokens[] or the C++ routine
+ tokenName() to get the print name of the token in the first set.
+
+ The size of the set is given by the newly added enum SET_SIZE, a
+ protected member of the generated parser's class. The number of
+ elements in the generated set will not be exactly equal to the
+ value of SET_SIZE because of synthetic tokens created by #tokclass,
+ #errclass, the -ge option, and meta-tokens such as epsilon, and
+ end-of-file.
+
+ The #FirstSetSymbol must appear immediately before a block
+ such as (...)+, (...)*, and {...}, and (...). It may not appear
+ immediately before a token, a rule reference, or action. However
+ a token or rule reference can be enclosed in a (...) in order to
+ make the use of #pragma FirstSetSymbol legal.
+
+ rr_bad : #FirstSetSymbol(rr_bad_FirstSet) Foo; // Illegal
+
+ rr_ok : #FirstSetSymbol(rr_ok_FirstSet) (Foo); // Legal
+
+ Do not confuse FirstSetSymbol sets with the sets used for testing
+ lookahead. The sets used for FirstSetSymbol have one element per bit,
+ so the number of bytes is approximately the largest token number
+ divided by 8. The sets used for testing lookahead store 8 lookahead
+ sets per byte, so the length of the array is approximately the largest
+ token number.
+
+ If there is demand, a similar routine for follow sets can be added.
+
+#247. (MR21) Misleading error message on syntax error for optional elements.
+
+ ===================================================
+ The behavior has been revised when parser exception
+ handling is used. See Item #290
+ ===================================================
+
+ Prior to MR21, tokens which were optional did not appear in syntax
+ error messages if the block which immediately followed detected a
+ syntax error.
+
+ Consider the following grammar which accepts Number, Word, and Other:
+
+ rr : {Number} Word;
+
+ For this rule the code resembles:
+
+ if (LA(1) == Number) {
+ match(Number);
+ consume();
+ }
+ match(Word);
+
+ Prior to MR21, the error message for input "$ a" would be:
+
+ line 1: syntax error at "$" missing Word
+
+ With MR21 the message will be:
+
+ line 1: syntax error at "$" expecting Word, Number.
+
+ The generate code resembles:
+
+ if ( (LA(1)==Number) ) {
+ zzmatch(Number);
+ consume();
+ }
+ else {
+ if ( (LA(1)==Word) ) {
+ /* nothing */
+ }
+ else {
+ FAIL(... message for both Number and Word ...);
+ }
+ }
+ match(Word);
+
+ The code generated for optional blocks in MR21 is slightly longer
+ than the previous versions, but it should give better error messages.
+
+ The code generated for:
+
+ { a | b | c }
+
+ should now be *identical* to:
+
+ ( a | b | c | )
+
+ which was not the case prior to MR21.
+
+ Reported by Sue Marvin (sue siara.com).
+
+#246. (Changed in MR21) Use of $(MAKE) for calls to make
+
+ Calls to make from the makefiles were replaced with $(MAKE)
+ because of problems when using gmake.
+
+ Reported with fix by Sunil K.Vallamkonda (sunil siara.com).
+
+#245. (Changed in MR21) Changes to genmk
+
+ The following command line options have been added to genmk:
+
+ -cfiles ...
+
+ To add a user's C or C++ files into makefile automatically.
+ The list of files must be enclosed in apostrophes. This
+ option may be specified multiple times.
+
+ -compiler ...
+
+ The name of the compiler to use for $(CCC) or $(CC). The
+ default in C++ mode is "CC". The default in C mode is "cc".
+
+ -pccts_path ...
+
+ The value for $(PCCTS), the pccts directory. The default
+ is /usr/local/pccts.
+
+ Contributed by Tomasz Babczynski (t.babczynski ict.pwr.wroc.pl).
+
+#244. (Changed in MR21) Rename variable "not" in antlr.g
+
+ When antlr.g is compiled with a C++ compiler, a variable named
+ "not" causes problems. Reported by Sinan Karasu
+ (sinan.karasu boeing.com).
+
+#243 (Changed in MR21) Replace recursion with iteration in zzfree_ast
+
+ Another refinement to zzfree_ast in ast.c to limit recursion.
+
+ NAKAJIMA Mutsuki (muc isr.co.jp).
+
+
+#242. (Changed in MR21) LineInfoFormatStr
+
+ Added an #ifndef/#endif around LineInfoFormatStr in pcctscfg.h.
+
+#241. (Changed in MR21) Changed macro PURIFY to a no-op
+
+ ***********************
+ *** NOT IMPLEMENTED ***
+ ***********************
+
+ The PURIFY macro was changed to a no-op because it was causing
+ problems when passing C++ objects.
+
+ The old definition:
+
+ #define PURIFY(r,s) memset((char *) &(r),'\\0',(s));
+
+ The new definition:
+
+ #define PURIFY(r,s) /* nothing */
+#endif
+
+#240. (Changed in MR21) sorcerer/h/sorcerer.h _MATCH and _MATCHRANGE
+
+ Added test for NULL token pointer.
+
+ Suggested by Peter Keller (keller ebi.ac.uk)
+
+#239. (Changed in MR21) C++ mode AParser::traceGuessFail
+
+ If tracing is turned on when the code has been generated
+ without trace code, a failed guess generates a trace report
+ even though there are no other trace reports. This
+ make the behavior consistent with other parts of the
+ trace system.
+
+ Reported by David Wigg (wiggjd sbu.ac.uk).
+
+#238. (Changed in MR21) Namespace version #include files
+
+ Changed reference from CStdio to cstdio (and other
+ #include file names) in the namespace version of pccts.
+ Should have known better.
+
+#237. (Changed in MR21) ParserBlackBox(FILE*)
+
+ In the past, ParserBlackBox would close the FILE in the dtor
+ even though it was not opened by ParserBlackBox. The problem
+ is that there were two constructors, one which accepted a file
+ name and did an fopen, the other which accepted a FILE and did
+ not do an fopen. There is now an extra member variable which
+ remembers whether ParserBlackBox did the open or not.
+
+ Suggested by Mike Percy (mpercy scires.com).
+
+#236. (Changed in MR21) tmake now reports down pointer problem
+
+ When ASTBase::tmake attempts to update the down pointer of
+ an AST it checks to see if the down pointer is NULL. If it
+ is not NULL it does not do the update and returns NULL.
+ An attempt to update the down pointer is almost always a
+ result of a user error. This can lead to difficult to find
+ problems during tree construction.
+
+ With this change, the routine calls a virtual function
+ reportOverwriteOfDownPointer() which calls panic to
+ report the problem. Users who want the old behavior can
+ redefined the virtual function in their AST class.
+
+ Suggested by Sinan Karasu (sinan.karasu boeing.com)
+
+#235. (Changed in MR21) Made ANTLRParser::resynch() virtual
+
+ Suggested by Jerry Evans (jerry swsl.co.uk).
+
+#234. (Changed in MR21) Implicit int for function return value
+
+ ATokenBuffer:bufferSize() did not specify a type for the
+ return value.
+
+ Reported by Hai Vo-Ba (hai fc.hp.com).
+
+#233. (Changed in MR20) Converted to MSVC 6.0
+
+ Due to external circumstances I have had to convert to MSVC 6.0
+ The MSVC 5.0 project files (.dsw and .dsp) have been retained as
+ xxx50.dsp and xxx50.dsw. The MSVC 6.0 files are named xxx60.dsp
+ and xxx60.dsw (where xxx is the related to the directory/project).
+
+#232. (Changed in MR20) Make setwd bit vectors protected in parser.h
+
+ The access for the setwd array in the parser header was not
+ specified. As a result, it would depend on the code which
+ preceded it. In MR20 it will always have access "protected".
+
+ Reported by Piotr Eljasiak (eljasiak zt.gdansk.tpsa.pl).
+
+#231. (Changed in MR20) Error in token buffer debug code.
+
+ When token buffer debugging is selected via the pre-processor
+ symbol DEBUG_TOKENBUFFER there is an erroneous check in
+ AParser.cpp:
+
+ #ifdef DEBUG_TOKENBUFFER
+ if (i >= inputTokens->bufferSize() ||
+ inputTokens->minTokens() < LLk ) /* MR20 Was "<=" */
+ ...
+ #endif
+
+ Reported by David Wigg (wiggjd sbu.ac.uk).
+
+#230. (Changed in MR20) Fixed problem with #define for -gd option
+
+ There was an error in setting zzTRACE_RULES for the -gd (trace) option.
+
+ Reported by Gary Funck (gary intrepid.com).
+
+#229. (Changed in MR20) Additional "const" for literals
+
+ "const" was added to the token name literal table.
+ "const" was added to some panic() and similar routine
+
+#228. (Changed in MR20) dlg crashes on "()"
+
+ The following token defintion will cause DLG to crash.
+
+ #token "()"
+
+ When there is a syntax error in a regular expression
+ many of the dlg routines return a structure which has
+ null pointers. When this is accessed by callers it
+ generates the crash.
+
+ I have attempted to fix the more common cases.
+
+ Reported by Mengue Olivier (dolmen bigfoot.com).
+
+#227. (Changed in MR20) Array overwrite
+
+ Steveh Hand (sassth unx.sas.com) reported a problem which
+ was traced to a temporary array which was not properly
+ resized for deeply nested blocks. This has been fixed.
+
+#226. (Changed in MR20) -pedantic conformance
+
+ G. Hobbelt (i_a mbh.org) and THM made many, many minor
+ changes to create prototypes for all the functions and
+ bring antlr, dlg, and sorcerer into conformance with
+ the gcc -pedantic option.
+
+ This may require uses to add pccts/h/pcctscfg.h to some
+ files or makefiles in order to have __USE_PROTOS defined.
+
+#225 (Changed in MR20) AST stack adjustment in C mode
+
+ The fix in #214 for AST stack adjustment in C mode missed
+ some cases.
+
+ Reported with fix by Ger Hobbelt (i_a mbh.org).
+
+#224 (Changed in MR20) LL(1) and LL(2) with #pragma approx
+
+ This may take a record for the oldest, most trival, lexical
+ error in pccts. The regular expressions for LL(1) and LL(2)
+ lacked an escape for the left and right parenthesis.
+
+ Reported by Ger Hobbelt (i_a mbh.org).
+
+#223 (Changed in MR20) Addition of IBM_VISUAL_AGE directory
+
+ Build files for antlr, dlg, and sorcerer under IBM Visual Age
+ have been contributed by Anton Sergeev (ags mlc.ru). They have
+ been placed in the pccts/IBM_VISUAL_AGE directory.
+
+#222 (Changed in MR20) Replace __STDC__ with __USE_PROTOS
+
+ Most occurrences of __STDC__ replaced with __USE_PROTOS due to
+ complaints from several users.
+
+#221 (Changed in MR20) Added #include for DLexerBase.h to PBlackBox.
+
+ Added #include for DLexerBase.h to PBlackBox.
+
+#220 (Changed in MR19) strcat arguments reversed in #pred parse
+
+ The arguments to strcat are reversed when creating a print
+ name for a hash table entry for use with #pred feature.
+
+ Problem diagnosed and fix reported by Scott Harrington
+ (seh4 ix.netcom.com).
+
+#219. (Changed in MR19) C Mode routine zzfree_ast
+
+ Changes to reduce use of recursion for AST trees with only right
+ links or only left links in the C mode routine zzfree_ast.
+
+ Implemented by SAKAI Kiyotaka (ksakai isr.co.jp).
+
+#218. (Changed in MR19) Changes to support unsigned char in C mode
+
+ Changes to antlr.h and err.h to fix omissions in use of zzchar_t
+
+ Implemented by SAKAI Kiyotaka (ksakai isr.co.jp).
+
+#217. (Changed in MR19) Error message when dlg -i and -CC options selected
+
+ *** This change was rescinded by item #257 ***
+
+ The parsers generated by pccts in C++ mode are not able to support the
+ interactive lexer option (except, perhaps, when using the deferred fetch
+ parser option.(Item #216).
+
+ DLG now warns when both -i and -CC are selected.
+
+ This warning was suggested by David Venditti (07751870267-0001 t-online.de).
+
+#216. (Changed in MR19) Defer token fetch for C++ mode
+
+ Implemented by Volker H. Simonis (simonis informatik.uni-tuebingen.de)
+
+ Normally, pccts keeps the lookahead token buffer completely filled.
+ This requires max(k,ck) tokens of lookahead. For some applications
+ this can cause deadlock problems. For example, there may be cases
+ when the parser can't tell when the input has been completely consumed
+ until the parse is complete, but the parse can't be completed because
+ the input routines are waiting for additional tokens to fill the
+ lookahead buffer.
+
+ When the ANTLRParser class is built with the pre-processor option
+ ZZDEFER_FETCH defined, the fetch of new tokens by consume() is deferred
+ until LA(i) or LT(i) is called.
+
+ To test whether this option has been built into the ANTLRParser class
+ use "isDeferFetchEnabled()".
+
+ Using the -gd trace option with the default tracein() and traceout()
+ routines will defeat the effort to defer the fetch because the
+ trace routines print out information about the lookahead token at
+ the start of the rule.
+
+ Because the tracein and traceout routines are virtual it is
+ easy to redefine them in your parser:
+
+ class MyParser {
+ <<
+ virtual void tracein(ANTLRChar * ruleName)
+ { fprintf(stderr,"Entering: %s\n", ruleName); }
+ virtual void traceout(ANTLRChar * ruleName)
+ { fprintf(stderr,"Leaving: %s\n", ruleName); }
+ >>
+
+ The originals for those routines are pccts/h/AParser.cpp
+
+ This requires use of the dlg option -i (interactive lexer).
+
+ This is implemented only for C++ mode.
+
+ This is experimental. The interaction with guess mode (syntactic
+ predicates)is not known.
+
+#215. (Changed in MR19) Addition of reset() to DLGLexerBase
+
+ There was no obvious way to reset the lexer for reuse. The
+ reset() method now does this.
+
+ Suggested by David Venditti (07751870267-0001 t-online.de).
+
+#214. (Changed in MR19) C mode: Adjust AST stack pointer at exit
+
+ In C mode the AST stack pointer needs to be reset if there will
+ be multiple calls to the ANTLRx macros.
+
+ Reported with fix by Paul D. Smith (psmith baynetworks.com).
+
+#213. (Changed in MR18) Fatal error with -mrhoistk (k>1 hoisting)
+
+ When rearranging code I forgot to un-comment a critical line of
+ code that handles hoisting of predicates with k>1 lookahead. This
+ is now fixed.
+
+ Reported by Reinier van den Born (reinier vnet.ibm.com).
+
+#212. (Changed in MR17) Mac related changes by Kenji Tanaka
+
+ Kenji Tanaka (kentar osa.att.ne.jp) has made a number of changes for
+ Macintosh users.
+
+ a. The following Macintosh MPW files aid in installing pccts on Mac:
+
+ pccts/MPW_Read_Me
+
+ pccts/install68K.mpw
+ pccts/installPPC.mpw
+
+ pccts/antlr/antlr.r
+ pccts/antlr/antlr68K.make
+ pccts/antlr/antlrPPC.make
+
+ pccts/dlg/dlg.r
+ pccts/dlg/dlg68K.make
+ pccts/dlg/dlgPPC.make
+
+ pccts/sorcerer/sor.r
+ pccts/sorcerer/sor68K.make
+ pccts/sorcerer/sorPPC.make
+
+ They completely replace the previous Mac installation files.
+
+ b. The most significant is a change in the MAC_FILE_CREATOR symbol
+ in pcctscfg.h:
+
+ old: #define MAC_FILE_CREATOR 'MMCC' /* Metrowerks C/C++ Text files */
+ new: #define MAC_FILE_CREATOR 'CWIE' /* Metrowerks C/C++ Text files */
+
+ c. Added calls to special_fopen_actions() where necessary.
+
+#211. (Changed in MR16a) C++ style comment in dlg
+
+ This has been fixed.
+
+#210. (Changed in MR16a) Sor accepts \r\n, \r, or \n for end-of-line
+
+ A user requested that Sorcerer be changed to accept other forms
+ of end-of-line.
+
+#209. (Changed in MR16) Name of files changed.
+
+ Old: CHANGES_FROM_1.33
+ New: CHANGES_FROM_133.txt
+
+ Old: KNOWN_PROBLEMS
+ New: KNOWN_PROBLEMS.txt
+
+#208. (Changed in MR16) Change in use of pccts #include files
+
+ There were problems with MS DevStudio when mixing Sorcerer and
+ PCCTS in the same source file. The problem is caused by the
+ redefinition of setjmp in the MS header file setjmp.h. In
+ setjmp.h the pre-processor symbol setjmp was redefined to be
+ _setjmp. A later effort to execute #include <setjmp.h> resulted
+ in an effort to #include <_setjmp.h>. I'm not sure whether this
+ is a bug or a feature. In any case, I decided to fix it by
+ avoiding the use of pre-processor symbols in #include statements
+ altogether. This has the added benefit of making pre-compiled
+ headers work again.
+
+ I've replaced statements:
+
+ old: #include PCCTS_SETJMP_H
+ new: #include "pccts_setjmp.h"
+
+ Where pccts_setjmp.h contains:
+
+ #ifndef __PCCTS_SETJMP_H__
+ #define __PCCTS_SETJMP_H__
+
+ #ifdef PCCTS_USE_NAMESPACE_STD
+ #include <Csetjmp>
+ #else
+ #include <setjmp.h>
+ #endif
+
+ #endif
+
+ A similar change has been made for other standard header files
+ required by pccts and sorcerer: stdlib.h, stdarg.h, stdio.h, etc.
+
+ Reported by Jeff Vincent (JVincent novell.com) and Dale Davis
+ (DalDavis spectrace.com).
+
+#207. (Changed in MR16) dlg reports an invalid range for: [\0x00-\0xff]
+
+ -----------------------------------------------------------------
+ Note from MR23: This fix does not work. I am investigating why.
+ -----------------------------------------------------------------
+
+ dlg will report that this is an invalid range.
+
+ Diagnosed by Piotr Eljasiak (eljasiak no-spam.zt.gdansk.tpsa.pl):
+
+ I think this problem is not specific to unsigned chars
+ because dlg reports no error for the range [\0x00-\0xfe].
+
+ I've found that information on range is kept in field
+ letter (unsigned char) of Attrib struct. Unfortunately
+ the letter value internally is for some reasons increased
+ by 1, so \0xff is represented here as 0.
+
+ That's why dlg complains about the range [\0x00-\0xff] in
+ dlg_p.g:
+
+ if ($$.letter > $2.letter) {
+ error("invalid range ", zzline);
+ }
+
+ The fix is:
+
+ if ($$.letter > $2.letter && 255 != $$2.letter) {
+ error("invalid range ", zzline);
+ }
+
+#206. (Changed in MR16) Free zzFAILtext in ANTLRParser destructor
+
+ The ANTLRParser destructor now frees zzFAILtext.
+
+ Problem and fix reported by Manfred Kogler (km cast.uni-linz.ac.at).
+
+#205. (Changed in MR16) DLGStringReset argument now const
+
+ Changed: void DLGStringReset(DLGChar *s) {...}
+ To: void DLGStringReset(const DLGChar *s) {...}
+
+ Suggested by Dale Davis (daldavis spectrace.com)
+
+#204. (Changed in MR15a) Change __WATCOM__ to __WATCOMC__ in pcctscfg.h
+
+ Reported by Oleg Dashevskii (olegdash my-dejanews.com).
+
+#203. (Changed in MR15) Addition of sorcerer to distribution kit
+
+ I have finally caved in to popular demand. The pccts 1.33mr15
+ kit will include sorcerer. The separate sorcerer kit will be
+ discontinued.
+
+#202. (Changed) in MR15) Organization of MS Dev Studio Projects in Kit
+
+ Previously there was one workspace that contained projects for
+ all three parts of pccts: antlr, dlg, and sorcerer. Now each
+ part (and directory) has its own workspace/project and there
+ is an additional workspace/project to build a library from the
+ .cpp files in the pccts/h directory.
+
+ The library build will create pccts_debug.lib or pccts_release.lib
+ according to the configuration selected.
+
+ If you don't want to build pccts 1.33MR15 you can download a
+ ready-to-run kit for win32 from http://www.polhode.com/win32.zip.
+ The ready-to-run for win32 includes executables, a pre-built static
+ library for the .cpp files in the pccts/h directory, and a sample
+ application
+
+ You will need to define the environment variable PCCTS to point to
+ the root of the pccts directory hierarchy.
+
+#201. (Changed in MR15) Several fixes by K.J. Cummings (cummings peritus.com)
+
+ Generation of SETJMP rather than SETJMP_H in gen.c.
+
+ (Sor B19) Declaration of ref_vars_inits for ref_var_inits in
+ pccts/sorcerer/sorcerer.h.
+
+#200. (Changed in MR15) Remove operator=() in AToken.h
+
+ User reported that WatCom couldn't handle use of
+ explicit operator =(). Replace with equivalent
+ using cast operator.
+
+#199. (Changed in MR15) Don't allow use of empty #tokclass
+
+ Change antlr.g to disallow empty #tokclass sets.
+
+ Reported by Manfred Kogler (km cast.uni-linz.ac.at).
+
+#198. Revised ANSI C grammar due to efforts by Manuel Kessler
+
+ Manuel Kessler (mlkessler cip.physik.uni-wuerzburg.de)
+
+ Allow trailing ... in function parameter lists.
+ Add bit fields.
+ Allow old-style function declarations.
+ Support cv-qualified pointers.
+ Better checking of combinations of type specifiers.
+ Release of memory for local symbols on scope exit.
+ Allow input file name on command line as well as by redirection.
+
+ and other miscellaneous tweaks.
+
+ This is not part of the pccts distribution kit. It must be
+ downloaded separately from:
+
+ http://www.polhode.com/ansi_mr15.zip
+
+#197. (Changed in MR14) Resetting the lookahead buffer of the parser
+
+ Explanation and fix by Sinan Karasu (sinan.karasu boeing.com)
+
+ Consider the code used to prime the lookahead buffer LA(i)
+ of the parser when init() is called:
+
+ void
+ ANTLRParser::
+ prime_lookahead()
+ {
+ int i;
+ for(i=1;i<=LLk; i++) consume();
+ dirty=0;
+ //lap = 0; // MR14 - Sinan Karasu (sinan.karusu boeing.com)
+ //labase = 0; // MR14
+ labase=lap; // MR14
+ }
+
+ When the parser is instantiated, lap=0,labase=0 is set.
+
+ The "for" loop runs LLk times. In consume(), lap = lap +1 (mod LLk) is
+ computed. Therefore, lap(before the loop) == lap (after the loop).
+
+ Now the only problem comes in when one does an init() of the parser
+ after an Eof has been seen. At that time, lap could be non zero.
+ Assume it was lap==1. Now we do a prime_lookahead(). If LLk is 2,
+ then
+
+ consume()
+ {
+ NLA = inputTokens->getToken()->getType();
+ dirty--;
+ lap = (lap+1)&(LLk-1);
+ }
+
+ or expanding NLA,
+
+ token_type[lap&(LLk-1)]) = inputTokens->getToken()->getType();
+ dirty--;
+ lap = (lap+1)&(LLk-1);
+
+ so now we prime locations 1 and 2. In prime_lookahead it used to set
+ lap=0 and labase=0. Now, the next token will be read from location 0,
+ NOT 1 as it should have been.
+
+ This was never caught before, because if a parser is just instantiated,
+ then lap and labase are 0, the offending assignment lines are
+ basically no-ops, since the for loop wraps around back to 0.
+
+#196. (Changed in MR14) Problems with "(alpha)? beta" guess
+
+ Consider the following syntactic predicate in a grammar
+ with 2 tokens of lookahead (k=2 or ck=2):
+
+ rule : ( alpha )? beta ;
+ alpha : S t ;
+ t : T U
+ | T
+ ;
+ beta : S t Z ;
+
+ When antlr computes the prediction expression with one token
+ of lookahead for alts 1 and 2 of rule t it finds an ambiguity.
+
+ Because the grammar has a lookahead of 2 it tries to compute
+ two tokens of lookahead for alts 1 and 2 of t. Alt 1 clearly
+ has a lookahead of (T U). Alt 2 is one token long so antlr
+ tries to compute the follow set of alt 2, which means finding
+ the things which can follow rule t in the context of (alpha)?.
+ This cannot be computed, because alpha is only part of a rule,
+ and antlr can't tell what part of beta is matched by alpha and
+ what part remains to be matched. Thus it impossible for antlr
+ to properly determine the follow set of rule t.
+
+ Prior to 1.33MR14, the follow of (alpha)? was computed as
+ FIRST(beta) as a result of the internal representation of
+ guess blocks.
+
+ With MR14 the follow set will be the empty set for that context.
+
+ Normally, one expects a rule appearing in a guess block to also
+ appear elsewhere. When the follow context for this other use
+ is "ored" with the empty set, the context from the other use
+ results, and a reasonable follow context results. However if
+ there is *no* other use of the rule, or it is used in a different
+ manner then the follow context will be inaccurate - it was
+ inaccurate even before MR14, but it will be inaccurate in a
+ different way.
+
+ For the example given earlier, a reasonable way to rewrite the
+ grammar:
+
+ rule : ( alpha )? beta
+ alpha : S t ;
+ t : T U
+ | T
+ ;
+ beta : alpha Z ;
+
+ If there are no other uses of the rule appearing in the guess
+ block it will generate a test for EOF - a workaround for
+ representing a null set in the lookahead tests.
+
+ If you encounter such a problem you can use the -alpha option
+ to get additional information:
+
+ line 2: error: not possible to compute follow set for alpha
+ in an "(alpha)? beta" block.
+
+ With the antlr -alpha command line option the following information
+ is inserted into the generated file:
+
+ #if 0
+
+ Trace of references leading to attempt to compute the follow set of
+ alpha in an "(alpha)? beta" block. It is not possible for antlr to
+ compute this follow set because it is not known what part of beta has
+ already been matched by alpha and what part remains to be matched.
+
+ Rules which make use of the incorrect follow set will also be incorrect
+
+ 1 #token T alpha/2 line 7 brief.g
+ 2 end alpha alpha/3 line 8 brief.g
+ 2 end (...)? block at start/1 line 2 brief.g
+
+ #endif
+
+ At the moment, with the -alpha option selected the program marks
+ any rules which appear in the trace back chain (above) as rules with
+ possible problems computing follow set.
+
+ Reported by Greg Knapen (gregory.knapen bell.ca).
+
+#195. (Changed in MR14) #line directive not at column 1
+
+ Under certain circunstances a predicate test could generate
+ a #line directive which was not at column 1.
+
+ Reported with fix by David Kågedal (davidk lysator.liu.se)
+ (http://www.lysator.liu.se/~davidk/).
+
+#194. (Changed in MR14) (C Mode only) Demand lookahead with #tokclass
+
+ In C mode with the demand lookahead option there is a bug in the
+ code which handles matches for #tokclass (zzsetmatch and
+ zzsetmatch_wsig).
+
+ The bug causes the lookahead pointer to get out of synchronization
+ with the current token pointer.
+
+ The problem was reported with a fix by Ger Hobbelt (hobbelt axa.nl).
+
+#193. (Changed in MR14) Use of PCCTS_USE_NAMESPACE_STD
+
+ The pcctscfg.h now contains the following definitions:
+
+ #ifdef PCCTS_USE_NAMESPACE_STD
+ #define PCCTS_STDIO_H <Cstdio>
+ #define PCCTS_STDLIB_H <Cstdlib>
+ #define PCCTS_STDARG_H <Cstdarg>
+ #define PCCTS_SETJMP_H <Csetjmp>
+ #define PCCTS_STRING_H <Cstring>
+ #define PCCTS_ASSERT_H <Cassert>
+ #define PCCTS_ISTREAM_H <istream>
+ #define PCCTS_IOSTREAM_H <iostream>
+ #define PCCTS_NAMESPACE_STD namespace std {}; using namespace std;
+ #else
+ #define PCCTS_STDIO_H <stdio.h>
+ #define PCCTS_STDLIB_H <stdlib.h>
+ #define PCCTS_STDARG_H <stdarg.h>
+ #define PCCTS_SETJMP_H <setjmp.h>
+ #define PCCTS_STRING_H <string.h>
+ #define PCCTS_ASSERT_H <assert.h>
+ #define PCCTS_ISTREAM_H <istream.h>
+ #define PCCTS_IOSTREAM_H <iostream.h>
+ #define PCCTS_NAMESPACE_STD
+ #endif
+
+ The runtime support in pccts/h uses these pre-processor symbols
+ consistently.
+
+ Also, antlr and dlg have been changed to generate code which uses
+ these pre-processor symbols rather than having the names of the
+ #include files hard-coded in the generated code.
+
+ This required the addition of "#include pcctscfg.h" to a number of
+ files in pccts/h.
+
+ It appears that this sometimes causes problems for MSVC 5 in
+ combination with the "automatic" option for pre-compiled headers.
+ In such cases disable the "automatic" pre-compiled headers option.
+
+ Suggested by Hubert Holin (Hubert.Holin Bigfoot.com).
+
+#192. (Changed in MR14) Change setText() to accept "const ANTLRChar *"
+
+ Changed ANTLRToken::setText(ANTLRChar *) to setText(const ANTLRChar *).
+ This allows literal strings to be used to initialize tokens. Since
+ the usual token implementation (ANTLRCommonToken) makes a copy of the
+ input string, this was an unnecessary limitation.
+
+ Suggested by Bob McWhirter (bob netwrench.com).
+
+#191. (Changed in MR14) HP/UX aCC compiler compatibility problem
+
+ Needed to explicitly declare zzINF_DEF_TOKEN_BUFFER_SIZE and
+ zzINF_BUFFER_TOKEN_CHUNK_SIZE as ints in pccts/h/AParser.cpp.
+
+ Reported by David Cook (dcook bmc.com).
+
+#190. (Changed in MR14) IBM OS/2 CSet compiler compatibility problem
+
+ Name conflict with "_cs" in pccts/h/ATokenBuffer.cpp
+
+ Reported by David Cook (dcook bmc.com).
+
+#189. (Changed in MR14) -gxt switch in C mode
+
+ The -gxt switch in C mode didn't work because of incorrect
+ initialization.
+
+ Reported by Sinan Karasu (sinan boeing.com).
+
+#188. (Changed in MR14) Added pccts/h/DLG_stream_input.h
+
+ This is a DLG stream class based on C++ istreams.
+
+ Contributed by Hubert Holin (Hubert.Holin Bigfoot.com).
+
+#187. (Changed in MR14) Rename config.h to pcctscfg.h
+
+ The PCCTS configuration file has been renamed from config.h to
+ pcctscfg.h. The problem with the original name is that it led
+ to name collisions when pccts parsers were combined with other
+ software.
+
+ All of the runtime support routines in pccts/h/* have been
+ changed to use the new name. Existing software can continue
+ to use pccts/h/config.h. The contents of pccts/h/config.h is
+ now just "#include "pcctscfg.h".
+
+ I don't have a record of the user who suggested this.
+
+#186. (Changed in MR14) Pre-processor symbol DllExportPCCTS class modifier
+
+ Classes in the C++ runtime support routines are now declared:
+
+ class DllExportPCCTS className ....
+
+ By default, the pre-processor symbol is defined as the empty
+ string. This if for use by MSVC++ users to create DLL classes.
+
+ Suggested by Manfred Kogler (km cast.uni-linz.ac.at).
+
+#185. (Changed in MR14) Option to not use PCCTS_AST base class for ASTBase
+
+ Normally, the ASTBase class is derived from PCCTS_AST which contains
+ functions useful to Sorcerer. If these are not necessary then the
+ user can define the pre-processor symbol "PCCTS_NOT_USING_SOR" which
+ will cause the ASTBase class to replace references to PCCTS_AST with
+ references to ASTBase where necessary.
+
+ The class ASTDoublyLinkedBase will contain a pure virtual function
+ shallowCopy() that was formerly defined in class PCCTS_AST.
+
+ Suggested by Bob McWhirter (bob netwrench.com).
+
+#184. (Changed in MR14) Grammars with no tokens generate invalid tokens.h
+
+ Reported by Hubert Holin (Hubert.Holin bigfoot.com).
+
+#183. (Changed in MR14) -f to specify file with names of grammar files
+
+ In DEC/VMS it is difficult to specify very long command lines.
+ The -f option allows one to place the names of the grammar files
+ in a data file in order to bypass limitations of the DEC/VMS
+ command language interpreter.
+
+ Addition supplied by Bernard Giroud (b_giroud decus.ch).
+
+#182. (Changed in MR14) Output directory option for DEC/VMS
+
+ Fix some problems with the -o option under DEC/VMS.
+
+ Fix supplied by Bernard Giroud (b_giroud decus.ch).
+
+#181. (Changed in MR14) Allow chars > 127 in DLGStringInput::nextChar()
+
+ Changed DLGStringInput to cast the character using (unsigned char)
+ so that languages with character codes greater than 127 work
+ without changes.
+
+ Suggested by Manfred Kogler (km cast.uni-linz.ac.at).
+
+#180. (Added in MR14) ANTLRParser::getEofToken()
+
+ Added "ANTLRToken ANTLRParser::getEofToken() const" to match the
+ setEofToken routine.
+
+ Requested by Manfred Kogler (km cast.uni-linz.ac.at).
+
+#179. (Fixed in MR14) Memory leak for BufFileInput subclass of DLGInputStream
+
+ The BufFileInput class described in Item #142 neglected to release
+ the allocated buffer when an instance was destroyed.
+
+ Reported by Manfred Kogler (km cast.uni-linz.ac.at).
+
+#178. (Fixed in MR14) Bug in "(alpha)? beta" guess blocks first sets
+
+ In 1.33 vanilla, and all maintenance releases prior to MR14
+ there is a bug in the handling of guess blocks which use the
+ "long" form:
+
+ (alpha)? beta
+
+ inside a (...)*, (...)+, or {...} block.
+
+ This problem does *not* apply to the case where beta is omitted
+ or when the syntactic predicate is on the leading edge of an
+ alternative.
+
+ The problem is that both alpha and beta are stored in the
+ syntax diagram, and that some analysis routines would fail
+ to skip the alpha portion when it was not on the leading edge.
+ Consider the following grammar with -ck 2:
+
+ r : ( (A)? B )* C D
+
+ | A B /* forces -ck 2 computation for old antlr */
+ /* reports ambig for alts 1 & 2 */
+
+ | B C /* forces -ck 2 computation for new antlr */
+ /* reports ambig for alts 1 & 3 */
+ ;
+
+ The prediction expression for the first alternative should be
+ LA(1)={B C} LA(2)={B C D}, but previous versions of antlr
+ would compute the prediction expression as LA(1)={A C} LA(2)={B D}
+
+ Reported by Arpad Beszedes (beszedes inf.u-szeged.hu) who provided
+ a very clear example of the problem and identified the probable cause.
+
+#177. (Changed in MR14) #tokdefs and #token with regular expression
+
+ In MR13 the change described by Item #162 caused an existing
+ feature of antlr to fail. Prior to the change it was possible
+ to give regular expression definitions and actions to tokens
+ which were defined via the #tokdefs directive.
+
+ This now works again.
+
+ Reported by Manfred Kogler (km cast.uni-linz.ac.at).
+
+#176. (Changed in MR14) Support for #line in antlr source code
+
+ Note: this was implemented by Arpad Beszedes (beszedes inf.u-szeged.hu).
+
+ In 1.33MR14 it is possible for a pre-processor to generate #line
+ directives in the antlr source and have those line numbers and file
+ names used in antlr error messages and in the #line directives
+ generated by antlr.
+
+ The #line directive may appear in the following forms:
+
+ #line ll "sss" xx xx ...
+
+ where ll represents a line number, "sss" represents the name of a file
+ enclosed in quotation marks, and xxx are arbitrary integers.
+
+ The following form (without "line") is not supported at the moment:
+
+ # ll "sss" xx xx ...
+
+ The result:
+
+ zzline
+
+ is replaced with ll from the # or #line directive
+
+ FileStr[CurFile]
+
+ is updated with the contents of the string (if any)
+ following the line number
+
+ Note
+ ----
+ The file-name string following the line number can be a complete
+ name with a directory-path. Antlr generates the output files from
+ the input file name (by replacing the extension from the file-name
+ with .c or .cpp).
+
+ If the input file (or the file-name from the line-info) contains
+ a path:
+
+ "../grammar.g"
+
+ the generated source code will be placed in "../grammar.cpp" (i.e.
+ in the parent directory). This is inconvenient in some cases
+ (even the -o switch can not be used) so the path information is
+ removed from the #line directive. Thus, if the line-info was
+
+ #line 2 "../grammar.g"
+
+ then the current file-name will become "grammar.g"
+
+ In this way, the generated source code according to the grammar file
+ will always be in the current directory, except when the -o switch
+ is used.
+
+#175. (Changed in MR14) Bug when guess block appears at start of (...)*
+
+ In 1.33 vanilla and all maintenance releases prior to 1.33MR14
+ there is a bug when a guess block appears at the start of a (...)+.
+ Consider the following k=1 (ck=1) grammar:
+
+ rule :
+ ( (STAR)? ZIP )* ID ;
+
+ Prior to 1.33MR14, the generated code resembled:
+
+ ...
+ zzGUESS_BLOCK
+ while ( 1 ) {
+ if ( ! LA(1)==STAR) break;
+ zzGUESS
+ if ( !zzrv ) {
+ zzmatch(STAR);
+ zzCONSUME;
+ zzGUESS_DONE
+ zzmatch(ZIP);
+ zzCONSUME;
+ ...
+
+ Note that the routine uses STAR for the prediction expression
+ rather than ZIP. With 1.33MR14 the generated code resembles:
+
+ ...
+ while ( 1 ) {
+ if ( ! LA(1)==ZIP) break;
+ ...
+
+ This problem existed only with (...)* blocks and was caused
+ by the slightly more complicated graph which represents (...)*
+ blocks. This caused the analysis routine to compute the first
+ set for the alpha part of the "(alpha)? beta" rather than the
+ beta part.
+
+ Both (...)+ and {...} blocks handled the guess block correctly.
+
+ Reported by Arpad Beszedes (beszedes inf.u-szeged.hu) who provided
+ a very clear example of the problem and identified the probable cause.
+
+#174. (Changed in MR14) Bug when action precedes syntactic predicate
+
+ In 1.33 vanilla, and all maintenance releases prior to MR14,
+ there was a bug when a syntactic predicate was immediately
+ preceded by an action. Consider the following -ck 2 grammar:
+
+ rule :
+ <<int i;>>
+ (alpha)? beta C
+ | A B
+ ;
+
+ alpha : A ;
+ beta : A B;
+
+ Prior to MR14, the code generated for the first alternative
+ resembled:
+
+ ...
+ zzGUESS
+ if ( !zzrv && LA(1)==A && LA(2)==A) {
+ alpha();
+ zzGUESS_DONE
+ beta();
+ zzmatch(C);
+ zzCONSUME;
+ } else {
+ ...
+
+ The prediction expression (i.e. LA(1)==A && LA(2)==A) is clearly
+ wrong because LA(2) should be matched to B (first[2] of beta is {B}).
+
+ With 1.33MR14 the prediction expression is:
+
+ ...
+ if ( !zzrv && LA(1)==A && LA(2)==B) {
+ alpha();
+ zzGUESS_DONE
+ beta();
+ zzmatch(C);
+ zzCONSUME;
+ } else {
+ ...
+
+ This will only affect users in which alpha is shorter than
+ than max(k,ck) and there is an action immediately preceding
+ the syntactic predicate.
+
+ This problem was reported by reported by Arpad Beszedes
+ (beszedes inf.u-szeged.hu) who provided a very clear example
+ of the problem and identified the presence of the init-action
+ as the likely culprit.
+
+#173. (Changed in MR13a) -glms for Microsoft style filenames with -gl
+
+ With the -gl option antlr generates #line directives using the
+ exact name of the input files specified on the command line.
+ An oddity of the Microsoft C and C++ compilers is that they
+ don't accept file names in #line directives containing "\"
+ even though these are names from the native file system.
+
+ With -glms option, the "\" in file names appearing in #line
+ directives is replaced with a "/" in order to conform to
+ Microsoft compiler requirements.
+
+ Reported by Erwin Achermann (erwin.achermann switzerland.org).
+
+#172. (Changed in MR13) \r\n in antlr source counted as one line
+
+ Some MS software uses \r\n to indicate a new line. Antlr
+ now recognizes this in counting lines.
+
+ Reported by Edward L. Hepler (elh ece.vill.edu).
+
+#171. (Changed in MR13) #tokclass L..U now allowed
+
+ The following is now allowed:
+
+ #tokclass ABC { A..B C }
+
+ Reported by Dave Watola (dwatola amtsun.jpl.nasa.gov)
+
+#170. (Changed in MR13) Suppression for predicates with lookahead depth >1
+
+ In MR12 the capability for suppression of predicates with lookahead
+ depth=1 was introduced. With MR13 this had been extended to
+ predicates with lookahead depth > 1 and released for use by users
+ on an experimental basis.
+
+ Consider the following grammar with -ck 2 and the predicate in rule
+ "a" with depth 2:
+
+ r1 : (ab)* "@"
+ ;
+
+ ab : a
+ | b
+ ;
+
+ a : (A B)? => <<p(LATEXT(2))>>? A B C
+ ;
+
+ b : A B C
+ ;
+
+ Normally, the predicate would be hoisted into rule r1 in order to
+ determine whether to call rule "ab". However it should *not* be
+ hoisted because, even if p is false, there is a valid alternative
+ in rule b. With "-mrhoistk on" the predicate will be suppressed.
+
+ If "-info p" command line option is present the following information
+ will appear in the generated code:
+
+ while ( (LA(1)==A)
+ #if 0
+
+ Part (or all) of predicate with depth > 1 suppressed by alternative
+ without predicate
+
+ pred << p(LATEXT(2))>>?
+ depth=k=2 ("=>" guard) rule a line 8 t1.g
+ tree context:
+ (root = A
+ B
+ )
+
+ The token sequence which is suppressed: ( A B )
+ The sequence of references which generate that sequence of tokens:
+
+ 1 to ab r1/1 line 1 t1.g
+ 2 ab ab/1 line 4 t1.g
+ 3 to b ab/2 line 5 t1.g
+ 4 b b/1 line 11 t1.g
+ 5 #token A b/1 line 11 t1.g
+ 6 #token B b/1 line 11 t1.g
+
+ #endif
+
+ A slightly more complicated example:
+
+ r1 : (ab)* "@"
+ ;
+
+ ab : a
+ | b
+ ;
+
+ a : (A B)? => <<p(LATEXT(2))>>? (A B | D E)
+ ;
+
+ b : <<q(LATEXT(2))>>? D E
+ ;
+
+
+ In this case, the sequence (D E) in rule "a" which lies behind
+ the guard is used to suppress the predicate with context (D E)
+ in rule b.
+
+ while ( (LA(1)==A || LA(1)==D)
+ #if 0
+
+ Part (or all) of predicate with depth > 1 suppressed by alternative
+ without predicate
+
+ pred << q(LATEXT(2))>>?
+ depth=k=2 rule b line 11 t2.g
+ tree context:
+ (root = D
+ E
+ )
+
+ The token sequence which is suppressed: ( D E )
+ The sequence of references which generate that sequence of tokens:
+
+ 1 to ab r1/1 line 1 t2.g
+ 2 ab ab/1 line 4 t2.g
+ 3 to a ab/1 line 4 t2.g
+ 4 a a/1 line 8 t2.g
+ 5 #token D a/1 line 8 t2.g
+ 6 #token E a/1 line 8 t2.g
+
+ #endif
+ &&
+ #if 0
+
+ pred << p(LATEXT(2))>>?
+ depth=k=2 ("=>" guard) rule a line 8 t2.g
+ tree context:
+ (root = A
+ B
+ )
+
+ #endif
+
+ (! ( LA(1)==A && LA(2)==B ) || p(LATEXT(2)) ) {
+ ab();
+ ...
+
+#169. (Changed in MR13) Predicate test optimization for depth=1 predicates
+
+ When the MR12 generated a test of a predicate which had depth 1
+ it would use the depth >1 routines, resulting in correct but
+ inefficient behavior. In MR13, a bit test is used.
+
+#168. (Changed in MR13) Token expressions in context guards
+
+ The token expressions appearing in context guards such as:
+
+ (A B)? => <<test(LT(1))>>? someRule
+
+ are computed during an early phase of antlr processing. As
+ a result, prior to MR13, complex expressions such as:
+
+ ~B
+ L..U
+ ~L..U
+ TokClassName
+ ~TokClassName
+
+ were not computed properly. This resulted in incorrect
+ context being computed for such expressions.
+
+ In MR13 these context guards are verified for proper semantics
+ in the initial phase and then re-evaluated after complex token
+ expressions have been computed in order to produce the correct
+ behavior.
+
+ Reported by Arpad Beszedes (beszedes inf.u-szeged.hu).
+
+#167. (Changed in MR13) ~L..U
+
+ Prior to MR13, the complement of a token range was
+ not properly computed.
+
+#166. (Changed in MR13) token expression L..U
+
+ The token U was represented as an unsigned char, restricting
+ the use of L..U to cases where U was assigned a token number
+ less than 256. This is corrected in MR13.
+
+#165. (Changed in MR13) option -newAST
+
+ To create ASTs from an ANTLRTokenPtr antlr usually calls
+ "new AST(ANTLRTokenPtr)". This option generates a call
+ to "newAST(ANTLRTokenPtr)" instead. This allows a user
+ to define a parser member function to create an AST object.
+
+ Similar changes for ASTBase::tmake and ASTBase::link were not
+ thought necessary since they do not create AST objects, only
+ use existing ones.
+
+#164. (Changed in MR13) Unused variable _astp
+
+ For many compilations, we have lived with warnings about
+ the unused variable _astp. It turns out that this varible
+ can *never* be used because the code which references it was
+ commented out.
+
+ This investigation was sparked by a note from Erwin Achermann
+ (erwin.achermann switzerland.org).
+
+#163. (Changed in MR13) Incorrect makefiles for testcpp examples
+
+ All the examples in pccts/testcpp/* had incorrect definitions
+ in the makefiles for the symbol "CCC". Instead of CCC=CC they
+ had CC=$(CCC).
+
+ There was an additional problem in testcpp/1/test.g due to the
+ change in ANTLRToken::getText() to a const member function
+ (Item #137).
+
+ Reported by Maurice Mass (maas cuci.nl).
+
+#162. (Changed in MR13) Combining #token with #tokdefs
+
+ When it became possible to change the print-name of a
+ #token (Item #148) it became useful to give a #token
+ statement whose only purpose was to giving a print name
+ to the #token. Prior to this change this could not be
+ combined with the #tokdefs feature.
+
+#161. (Changed in MR13) Switch -gxt inhibits generation of tokens.h
+
+#160. (Changed in MR13) Omissions in list of names for remap.h
+
+ When a user selects the -gp option antlr creates a list
+ of macros in remap.h to rename some of the standard
+ antlr routines from zzXXX to userprefixXXX.
+
+ There were number of omissions from the remap.h name
+ list related to the new trace facility. This was reported,
+ along with a fix, by Bernie Solomon (bernard ug.eds.com).
+
+#159. (Changed in MR13) Violations of classic C rules
+
+ There were a number of violations of classic C style in
+ the distribution kit. This was reported, along with fixes,
+ by Bernie Solomon (bernard ug.eds.com).
+
+#158. (Changed in MR13) #header causes problem for pre-processors
+
+ A user who runs the C pre-processor on antlr source suggested
+ that another syntax be allowed. With MR13 such directives
+ such as #header, #pragma, etc. may be written as "\#header",
+ "\#pragma", etc. For escaping pre-processor directives inside
+ a #header use something like the following:
+
+ \#header
+ <<
+ \#include <stdio.h>
+ >>
+
+#157. (Fixed in MR13) empty error sets for rules with infinite recursion
+
+ When the first set for a rule cannot be computed due to infinite
+ left recursion and it is the only alternative for a block then
+ the error set for the block would be empty. This would result
+ in a fatal error.
+
+ Reported by Darin Creason (creason genedax.com)
+
+#156. (Changed in MR13) DLGLexerBase::getToken() now public
+
+#155. (Changed in MR13) Context behind predicates can suppress
+
+ With -mrhoist enabled the context behind a guarded predicate can
+ be used to suppress other predicates. Consider the following grammar:
+
+ r0 : (r1)+;
+
+ r1 : rp
+ | rq
+ ;
+ rp : <<p LATEXT(1)>>? B ;
+ rq : (A)? => <<q LATEXT(1)>>? (A|B);
+
+ In earlier versions both predicates "p" and "q" would be hoisted into
+ rule r0. With MR12c predicate p is suppressed because the context which
+ follows predicate q includes "B" which can "cover" predicate "p". In
+ other words, in trying to decide in r0 whether to call r1, it doesn't
+ really matter whether p is false or true because, either way, there is
+ a valid choice within r1.
+
+#154. (Changed in MR13) Making hoist suppression explicit using <<nohoist>>
+
+ A common error, even among experienced pccts users, is to code
+ an init-action to inhibit hoisting rather than a leading action.
+ An init-action does not inhibit hoisting.
+
+ This was coded:
+
+ rule1 : <<;>> rule2
+
+ This is what was meant:
+
+ rule1 : <<;>> <<;>> rule2
+
+ With MR13, the user can code:
+
+ rule1 : <<;>> <<nohoist>> rule2
+
+ The following will give an error message:
+
+ rule1 : <<nohoist>> rule2
+
+ If the <<nohoist>> appears as an init-action rather than a leading
+ action an error message is issued. The meaning of an init-action
+ containing "nohoist" is unclear: does it apply to just one
+ alternative or to all alternatives ?
+
+
+
+
+
+
+
+
+ -------------------------------------------------------
+ Note: Items #153 to #1 are now in a separate file named
+ CHANGES_FROM_133_BEFORE_MR13.txt
+ -------------------------------------------------------
diff --git a/Source/Pccts/CHANGES_FROM_133_BEFORE_MR13.txt b/Source/Pccts/CHANGES_FROM_133_BEFORE_MR13.txt
new file mode 100644
index 0000000..bba5ecd
--- /dev/null
+++ b/Source/Pccts/CHANGES_FROM_133_BEFORE_MR13.txt
@@ -0,0 +1,3666 @@
+
+ ------------------------------------------------------------
+ This is the second part of a two part file.
+ This is a list of changes to pccts 1.33 prior to MR13
+ For more recent information see CHANGES_FROM_133.txt
+ ------------------------------------------------------------
+
+ DISCLAIMER
+
+ The software and these notes are provided "as is". They may include
+ typographical or technical errors and their authors disclaims all
+ liability of any kind or nature for damages due to error, fault,
+ defect, or deficiency regardless of cause. All warranties of any
+ kind, either express or implied, including, but not limited to, the
+ implied warranties of merchantability and fitness for a particular
+ purpose are disclaimed.
+
+
+#153. (Changed in MR12b) Bug in computation of -mrhoist suppression set
+
+ Consider the following grammar with k=1 and "-mrhoist on":
+
+ r1 : (A)? => ((p>>? x /* l1 */
+ | r2 /* l2 */
+ ;
+ r2 : A /* l4 */
+ | (B)? => <<q>>? y /* l5 */
+ ;
+
+ In earlier versions the mrhoist routine would see that both l1 and
+ l2 contained predicates and would assume that this prevented either
+ from acting to suppress the other predicate. In the example above
+ it didn't realize the A at line l4 is capable of suppressing the
+ predicate at l1 even though alt l2 contains (indirectly) a predicate.
+
+ This is fixed in MR12b.
+
+ Reported by Reinier van den Born (reinier@vnet.ibm.com)
+
+#153. (Changed in MR12a) Bug in computation of -mrhoist suppression set
+
+ An oversight similar to that described in Item #152 appeared in
+ the computation of the set that "covered" a predicate. If a
+ predicate expression included a term such as p=AND(q,r) the context
+ of p was taken to be context(q) & context(r), when it should have
+ been context(q) | context(r). This is fixed in MR12a.
+
+#152. (Changed in MR12) Bug in generation of predicate expressions
+
+ The primary purpose for MR12 is to make quite clear that MR11 is
+ obsolete and to fix the bug related to predicate expressions.
+
+ In MR10 code was added to optimize the code generated for
+ predicate expression tests. Unfortunately, there was a
+ significant oversight in the code which resulted in a bug in
+ the generation of code for predicate expression tests which
+ contained predicates combined using AND:
+
+ r0 : (r1)* "@" ;
+ r1 : (AAA)? => <<p LATEXT(1)>>? r2 ;
+ r2 : (BBB)? => <<q LATEXT(1)>>? Q
+ | (BBB)? => <<r LATEXT(1)>>? Q
+ ;
+
+ In MR11 (and MR10 when using "-mrhoist on") the code generated
+ for r0 to predict r1 would be equivalent to:
+
+ if ( LA(1)==Q &&
+ (LA(1)==AAA && LA(1)==BBB) &&
+ ( p && ( q || r )) ) {
+
+ This is incorrect because it expresses the idea that LA(1)
+ *must* be AAA in order to attempt r1, and *must* be BBB to
+ attempt r2. The result was that r1 became unreachable since
+ both condition can not be simultaneously true.
+
+ The general philosophy of code generation for predicates
+ can be summarized as follows:
+
+ a. If the context is true don't enter an alt
+ for which the corresponding predicate is false.
+
+ If the context is false then it is okay to enter
+ the alt without evaluating the predicate at all.
+
+ b. A predicate created by ORing of predicates has
+ context which is the OR of their individual contexts.
+
+ c. A predicate created by ANDing of predicates has
+ (surprise) context which is the OR of their individual
+ contexts.
+
+ d. Apply these rules recursively.
+
+ e. Remember rule (a)
+
+ The correct code should express the idea that *if* LA(1) is
+ AAA then p must be true to attempt r1, but if LA(1) is *not*
+ AAA then it is okay to attempt r1, provided that *if* LA(1) is
+ BBB then one of q or r must be true.
+
+ if ( LA(1)==Q &&
+ ( !(LA(1)==AAA || LA(1)==BBB) ||
+ ( ! LA(1) == AAA || p) &&
+ ( ! LA(1) == BBB || q || r ) ) ) {
+
+ I believe this is fixed in MR12.
+
+ Reported by Reinier van den Born (reinier@vnet.ibm.com)
+
+#151a. (Changed in MR12) ANTLRParser::getLexer()
+
+ As a result of several requests, I have added public methods to
+ get a pointer to the lexer belonging to a parser.
+
+ ANTLRTokenStream *ANTLRParser::getLexer() const
+
+ Returns a pointer to the lexer being used by the
+ parser. ANTLRTokenStream is the base class of
+ DLGLexer
+
+ ANTLRTokenStream *ANTLRTokenBuffer::getLexer() const
+
+ Returns a pointer to the lexer being used by the
+ ANTLRTokenBuffer. ANTLRTokenStream is the base
+ class of DLGLexer
+
+ You must manually cast the ANTLRTokenStream to your program's
+ lexer class. Because the name of the lexer's class is not fixed.
+ Thus it is impossible to incorporate it into the DLGLexerBase
+ class.
+
+#151b.(Changed in MR12) ParserBlackBox member getLexer()
+
+ The template class ParserBlackBox now has a member getLexer()
+ which returns a pointer to the lexer.
+
+#150. (Changed in MR12) syntaxErrCount and lexErrCount now public
+
+ See Item #127 for more information.
+
+#149. (Changed in MR12) antlr option -info o (letter o for orphan)
+
+ If there is more than one rule which is not referenced by any
+ other rule then all such rules are listed. This is useful for
+ alerting one to rules which are not used, but which can still
+ contribute to ambiguity. For example:
+
+ start : a Z ;
+ unused: a A ;
+ a : (A)+ ;
+
+ will cause an ambiguity report for rule "a" which will be
+ difficult to understand if the user forgets about rule "unused"
+ simply because it is not used in the grammar.
+
+#148. (Changed in MR11) #token names appearing in zztokens,token_tbl
+
+ In a #token statement like the following:
+
+ #token Plus "\+"
+
+ the string "Plus" appears in the zztokens array (C mode) and
+ token_tbl (C++ mode). This string is used in most error
+ messages. In MR11 one has the option of using some other string,
+ (e.g. "+") in those tables.
+
+ In MR11 one can write:
+
+ #token Plus ("+") "\+"
+ #token RP ("(") "\("
+ #token COM ("comment begin") "/\*"
+
+ A #token statement is allowed to appear in more than one #lexclass
+ with different regular expressions. However, the token name appears
+ only once in the zztokens/token_tbl array. This means that only
+ one substitute can be specified for a given #token name. The second
+ attempt to define a substitute name (different from the first) will
+ result in an error message.
+
+#147. (Changed in MR11) Bug in follow set computation
+
+ There is a bug in 1.33 vanilla and all maintenance releases
+ prior to MR11 in the computation of the follow set. The bug is
+ different than that described in Item #82 and probably more
+ common. It was discovered in the ansi.g grammar while testing
+ the "ambiguity aid" (Item #119). The search for a bug started
+ when the ambiguity aid was unable to discover the actual source
+ of an ambiguity reported by antlr.
+
+ The problem appears when an optimization of the follow set
+ computation is used inappropriately. The result is that the
+ follow set used is the "worst case". In other words, the error
+ can lead to false reports of ambiguity. The good news is that
+ if you have a grammar in which you have addressed all reported
+ ambiguities you are ok. The bad news is that you may have spent
+ time fixing ambiguities that were not real, or used k=2 when
+ ck=2 might have been sufficient, and so on.
+
+ The following grammar demonstrates the problem:
+
+ ------------------------------------------------------------
+ expr : ID ;
+
+ start : stmt SEMI ;
+
+ stmt : CASE expr COLON
+ | expr SEMI
+ | plain_stmt
+ ;
+
+ plain_stmt : ID COLON ;
+ ------------------------------------------------------------
+
+ When compiled with k=1 and ck=2 it will report:
+
+ warning: alts 2 and 3 of the rule itself ambiguous upon
+ { IDENTIFIER }, { COLON }
+
+ When antlr analyzes "stmt" it computes the first[1] set of all
+ alternatives. It finds an ambiguity between alts 2 and 3 for ID.
+ It then computes the first[2] set for alternatives 2 and 3 to resolve
+ the ambiguity. In computing the first[2] set of "expr" (which is
+ only one token long) it needs to determine what could follow "expr".
+ Under a certain combination of circumstances antlr forgets that it
+ is trying to analyze "stmt" which can only be followed by SEMI and
+ adds to the first[2] set of "expr" the "global" follow set (including
+ "COLON") which could follow "expr" (under other conditions) in the
+ phrase "CASE expr COLON".
+
+#146. (Changed in MR11) Option -treport for locating "difficult" alts
+
+ It can be difficult to determine which alternatives are causing
+ pccts to work hard to resolve an ambiguity. In some cases the
+ ambiguity is successfully resolved after much CPU time so there
+ is no message at all.
+
+ A rough measure of the amount of work being peformed which is
+ independent of the CPU speed and system load is the number of
+ tnodes created. Using "-info t" gives information about the
+ total number of tnodes created and the peak number of tnodes.
+
+ Tree Nodes: peak 1300k created 1416k lost 0
+
+ It also puts in the generated C or C++ file the number of tnodes
+ created for a rule (at the end of the rule). However this
+ information is not sufficient to locate the alternatives within
+ a rule which are causing the creation of tnodes.
+
+ Using:
+
+ antlr -treport 100000 ....
+
+ causes antlr to list on stdout any alternatives which require the
+ creation of more than 100,000 tnodes, along with the lookahead sets
+ for those alternatives.
+
+ The following is a trivial case from the ansi.g grammar which shows
+ the format of the report. This report might be of more interest
+ in cases where 1,000,000 tuples were created to resolve the ambiguity.
+
+ -------------------------------------------------------------------------
+ There were 0 tuples whose ambiguity could not be resolved
+ by full lookahead
+ There were 157 tnodes created to resolve ambiguity between:
+
+ Choice 1: statement/2 line 475 file ansi.g
+ Choice 2: statement/3 line 476 file ansi.g
+
+ Intersection of lookahead[1] sets:
+
+ IDENTIFIER
+
+ Intersection of lookahead[2] sets:
+
+ LPARENTHESIS COLON AMPERSAND MINUS
+ STAR PLUSPLUS MINUSMINUS ONESCOMPLEMENT
+ NOT SIZEOF OCTALINT DECIMALINT
+ HEXADECIMALINT FLOATONE FLOATTWO IDENTIFIER
+ STRING CHARACTER
+ -------------------------------------------------------------------------
+
+#145. (Documentation) Generation of Expression Trees
+
+ Item #99 was misleading because it implied that the optimization
+ for tree expressions was available only for trees created by
+ predicate expressions and neglected to mention that it required
+ the use of "-mrhoist on". The optimization applies to tree
+ expressions created for grammars with k>1 and for predicates with
+ lookahead depth >1.
+
+ In MR11 the optimized version is always used so the -mrhoist on
+ option need not be specified.
+
+#144. (Changed in MR11) Incorrect test for exception group
+
+ In testing for a rule's exception group the label a pointer
+ is compared against '\0'. The intention is "*pointer".
+
+ Reported by Jeffrey C. Fried (Jeff@Fried.net).
+
+#143. (Changed in MR11) Optional ";" at end of #token statement
+
+ Fixes problem of:
+
+ #token X "x"
+
+ <<
+ parser action
+ >>
+
+ Being confused with:
+
+ #token X "x" <<lexical action>>
+
+#142. (Changed in MR11) class BufFileInput subclass of DLGInputStream
+
+ Alexey Demakov (demakov@kazbek.ispras.ru) has supplied class
+ BufFileInput derived from DLGInputStream which provides a
+ function lookahead(char *string) to test characters in the
+ input stream more than one character ahead.
+
+ The default amount of lookahead is specified by the constructor
+ and defaults to 8 characters. This does *not* include the one
+ character of lookahead maintained internally by DLG in member "ch"
+ and which is not available for testing via BufFileInput::lookahead().
+
+ This is a useful class for overcoming the one-character-lookahead
+ limitation of DLG without resorting to a lexer capable of
+ backtracking (like flex) which is not integrated with antlr as is
+ DLG.
+
+ There are no restrictions on copying or using BufFileInput.* except
+ that the authorship and related information must be retained in the
+ source code.
+
+ The class is located in pccts/h/BufFileInput.* of the kit.
+
+#141. (Changed in MR11) ZZDEBUG_CONSUME for ANTLRParser::consume()
+
+ A debug aid has been added to file ANTLRParser::consume() in
+ file AParser.cpp:
+
+ #ifdef ZZDEBUG_CONSUME_ACTION
+ zzdebug_consume_action();
+ #endif
+
+ Suggested by Sramji Ramanathan (ps@kumaran.com).
+
+#140. (Changed in MR11) #pred to define predicates
+
+ +---------------------------------------------------+
+ | Note: Assume "-prc on" for this entire discussion |
+ +---------------------------------------------------+
+
+ A problem with predicates is that each one is regarded as
+ unique and capable of disambiguating cases where two
+ alternatives have identical lookahead. For example:
+
+ rule : <<pred(LATEXT(1))>>? A
+ | <<pred(LATEXT(1))>>? A
+ ;
+
+ will not cause any error messages or warnings to be issued
+ by earlier versions of pccts. To compare the text of the
+ predicates is an incomplete solution.
+
+ In 1.33MR11 I am introducing the #pred statement in order to
+ solve some problems with predicates. The #pred statement allows
+ one to give a symbolic name to a "predicate literal" or a
+ "predicate expression" in order to refer to it in other predicate
+ expressions or in the rules of the grammar.
+
+ The predicate literal associated with a predicate symbol is C
+ or C++ code which can be used to test the condition. A
+ predicate expression defines a predicate symbol in terms of other
+ predicate symbols using "!", "&&", and "||". A predicate symbol
+ can be defined in terms of a predicate literal, a predicate
+ expression, or *both*.
+
+ When a predicate symbol is defined with both a predicate literal
+ and a predicate expression, the predicate literal is used to generate
+ code, but the predicate expression is used to check for two
+ alternatives with identical predicates in both alternatives.
+
+ Here are some examples of #pred statements:
+
+ #pred IsLabel <<isLabel(LATEXT(1))>>?
+ #pred IsLocalVar <<isLocalVar(LATEXT(1))>>?
+ #pred IsGlobalVar <<isGlobalVar(LATEXT(1)>>?
+ #pred IsVar <<isVar(LATEXT(1))>>? IsLocalVar || IsGlobalVar
+ #pred IsScoped <<isScoped(LATEXT(1))>>? IsLabel || IsLocalVar
+
+ I hope that the use of EBNF notation to describe the syntax of the
+ #pred statement will not cause problems for my readers (joke).
+
+ predStatement : "#pred"
+ CapitalizedName
+ (
+ "<<predicate_literal>>?"
+ | "<<predicate_literal>>?" predOrExpr
+ | predOrExpr
+ )
+ ;
+
+ predOrExpr : predAndExpr ( "||" predAndExpr ) * ;
+
+ predAndExpr : predPrimary ( "&&" predPrimary ) * ;
+
+ predPrimary : CapitalizedName
+ | "!" predPrimary
+ | "(" predOrExpr ")"
+ ;
+
+ What is the purpose of this nonsense ?
+
+ To understand how predicate symbols help, you need to realize that
+ predicate symbols are used in two different ways with two different
+ goals.
+
+ a. Allow simplification of predicates which have been combined
+ during predicate hoisting.
+
+ b. Allow recognition of identical predicates which can't disambiguate
+ alternatives with common lookahead.
+
+ First we will discuss goal (a). Consider the following rule:
+
+ rule0: rule1
+ | ID
+ | ...
+ ;
+
+ rule1: rule2
+ | rule3
+ ;
+
+ rule2: <<isX(LATEXT(1))>>? ID ;
+ rule3: <<!isX(LATEXT(1)>>? ID ;
+
+ When the predicates in rule2 and rule3 are combined by hoisting
+ to create a prediction expression for rule1 the result is:
+
+ if ( LA(1)==ID
+ && ( isX(LATEXT(1) || !isX(LATEXT(1) ) ) { rule1(); ...
+
+ This is inefficient, but more importantly, can lead to false
+ assumptions that the predicate expression distinguishes the rule1
+ alternative with some other alternative with lookahead ID. In
+ MR11 one can write:
+
+ #pred IsX <<isX(LATEXT(1))>>?
+
+ ...
+
+ rule2: <<IsX>>? ID ;
+ rule3: <<!IsX>>? ID ;
+
+ During hoisting MR11 recognizes this as a special case and
+ eliminates the predicates. The result is a prediction
+ expression like the following:
+
+ if ( LA(1)==ID ) { rule1(); ...
+
+ Please note that the following cases which appear to be equivalent
+ *cannot* be simplified by MR11 during hoisting because the hoisting
+ logic only checks for a "!" in the predicate action, not in the
+ predicate expression for a predicate symbol.
+
+ *Not* equivalent and is not simplified during hoisting:
+
+ #pred IsX <<isX(LATEXT(1))>>?
+ #pred NotX <<!isX(LATEXT(1))>>?
+ ...
+ rule2: <<IsX>>? ID ;
+ rule3: <<NotX>>? ID ;
+
+ *Not* equivalent and is not simplified during hoisting:
+
+ #pred IsX <<isX(LATEXT(1))>>?
+ #pred NotX !IsX
+ ...
+ rule2: <<IsX>>? ID ;
+ rule3: <<NotX>>? ID ;
+
+ Now we will discuss goal (b).
+
+ When antlr discovers that there is a lookahead ambiguity between
+ two alternatives it attempts to resolve the ambiguity by searching
+ for predicates in both alternatives. In the past any predicate
+ would do, even if the same one appeared in both alternatives:
+
+ rule: <<p(LATEXT(1))>>? X
+ | <<p(LATEXT(1))>>? X
+ ;
+
+ The #pred statement is a start towards solving this problem.
+ During ambiguity resolution (*not* predicate hoisting) the
+ predicates for the two alternatives are expanded and compared.
+ Consider the following example:
+
+ #pred Upper <<isUpper(LATEXT(1))>>?
+ #pred Lower <<isLower(LATEXT(1))>>?
+ #pred Alpha <<isAlpha(LATEXT(1))>>? Upper || Lower
+
+ rule0: rule1
+ | <<Alpha>>? ID
+ ;
+
+ rule1:
+ | rule2
+ | rule3
+ ...
+ ;
+
+ rule2: <<Upper>>? ID;
+ rule3: <<Lower>>? ID;
+
+ The definition of #pred Alpha expresses:
+
+ a. to test the predicate use the C code "isAlpha(LATEXT(1))"
+
+ b. to analyze the predicate use the information that
+ Alpha is equivalent to the union of Upper and Lower,
+
+ During ambiguity resolution the definition of Alpha is expanded
+ into "Upper || Lower" and compared with the predicate in the other
+ alternative, which is also "Upper || Lower". Because they are
+ identical MR11 will report a problem.
+
+ -------------------------------------------------------------------------
+ t10.g, line 5: warning: the predicates used to disambiguate rule rule0
+ (file t10.g alt 1 line 5 and alt 2 line 6)
+ are identical when compared without context and may have no
+ resolving power for some lookahead sequences.
+ -------------------------------------------------------------------------
+
+ If you use the "-info p" option the output file will contain:
+
+ +----------------------------------------------------------------------+
+ |#if 0 |
+ | |
+ |The following predicates are identical when compared without |
+ | lookahead context information. For some ambiguous lookahead |
+ | sequences they may not have any power to resolve the ambiguity. |
+ | |
+ |Choice 1: rule0/1 alt 1 line 5 file t10.g |
+ | |
+ | The original predicate for choice 1 with available context |
+ | information: |
+ | |
+ | OR expr |
+ | |
+ | pred << Upper>>? |
+ | depth=k=1 rule rule2 line 14 t10.g |
+ | set context: |
+ | ID |
+ | |
+ | pred << Lower>>? |
+ | depth=k=1 rule rule3 line 15 t10.g |
+ | set context: |
+ | ID |
+ | |
+ | The predicate for choice 1 after expansion (but without context |
+ | information): |
+ | |
+ | OR expr |
+ | |
+ | pred << isUpper(LATEXT(1))>>? |
+ | depth=k=1 rule line 1 t10.g |
+ | |
+ | pred << isLower(LATEXT(1))>>? |
+ | depth=k=1 rule line 2 t10.g |
+ | |
+ | |
+ |Choice 2: rule0/2 alt 2 line 6 file t10.g |
+ | |
+ | The original predicate for choice 2 with available context |
+ | information: |
+ | |
+ | pred << Alpha>>? |
+ | depth=k=1 rule rule0 line 6 t10.g |
+ | set context: |
+ | ID |
+ | |
+ | The predicate for choice 2 after expansion (but without context |
+ | information): |
+ | |
+ | OR expr |
+ | |
+ | pred << isUpper(LATEXT(1))>>? |
+ | depth=k=1 rule line 1 t10.g |
+ | |
+ | pred << isLower(LATEXT(1))>>? |
+ | depth=k=1 rule line 2 t10.g |
+ | |
+ | |
+ |#endif |
+ +----------------------------------------------------------------------+
+
+ The comparison of the predicates for the two alternatives takes
+ place without context information, which means that in some cases
+ the predicates will be considered identical even though they operate
+ on disjoint lookahead sets. Consider:
+
+ #pred Alpha
+
+ rule1: <<Alpha>>? ID
+ | <<Alpha>>? Label
+ ;
+
+ Because the comparison of predicates takes place without context
+ these will be considered identical. The reason for comparing
+ without context is that otherwise it would be necessary to re-evaluate
+ the entire predicate expression for each possible lookahead sequence.
+ This would require more code to be written and more CPU time during
+ grammar analysis, and it is not yet clear whether anyone will even make
+ use of the new #pred facility.
+
+ A temporary workaround might be to use different #pred statements
+ for predicates you know have different context. This would avoid
+ extraneous warnings.
+
+ The above example might be termed a "false positive". Comparison
+ without context will also lead to "false negatives". Consider the
+ following example:
+
+ #pred Alpha
+ #pred Beta
+
+ rule1: <<Alpha>>? A
+ | rule2
+ ;
+
+ rule2: <<Alpha>>? A
+ | <<Beta>>? B
+ ;
+
+ The predicate used for alt 2 of rule1 is (Alpha || Beta). This
+ appears to be different than the predicate Alpha used for alt1.
+ However, the context of Beta is B. Thus when the lookahead is A
+ Beta will have no resolving power and Alpha will be used for both
+ alternatives. Using the same predicate for both alternatives isn't
+ very helpful, but this will not be detected with 1.33MR11.
+
+ To properly handle this the predicate expression would have to be
+ evaluated for each distinct lookahead context.
+
+ To determine whether two predicate expressions are identical is
+ difficult. The routine may fail to identify identical predicates.
+
+ The #pred feature also compares predicates to see if a choice between
+ alternatives which is resolved by a predicate which makes the second
+ choice unreachable. Consider the following example:
+
+ #pred A <<A(LATEXT(1)>>?
+ #pred B <<B(LATEXT(1)>>?
+ #pred A_or_B A || B
+
+ r : s
+ | t
+ ;
+ s : <<A_or_B>>? ID
+ ;
+ t : <<A>>? ID
+ ;
+
+ ----------------------------------------------------------------------------
+ t11.g, line 5: warning: the predicate used to disambiguate the
+ first choice of rule r
+ (file t11.g alt 1 line 5 and alt 2 line 6)
+ appears to "cover" the second predicate when compared without context.
+ The second predicate may have no resolving power for some lookahead
+ sequences.
+ ----------------------------------------------------------------------------
+
+#139. (Changed in MR11) Problem with -gp in C++ mode
+
+ The -gp option to add a prefix to rule names did not work in
+ C++ mode. This has been fixed.
+
+ Reported by Alexey Demakov (demakov@kazbek.ispras.ru).
+
+#138. (Changed in MR11) Additional makefiles for non-MSVC++ MS systems
+
+ Sramji Ramanathan (ps@kumaran.com) has supplied makefiles for
+ building antlr and dlg with Win95/NT development tools that
+ are not based on MSVC5. They are pccts/antlr/AntlrMS.mak and
+ pccts/dlg/DlgMS.mak.
+
+ The first line of the makefiles require a definition of PCCTS_HOME.
+
+ These are in additiion to the AntlrMSVC50.* and DlgMSVC50.*
+ supplied by Jeff Vincent (JVincent@novell.com).
+
+#137. (Changed in MR11) Token getType(), getText(), getLine() const members
+
+ --------------------------------------------------------------------
+ If you use ANTLRCommonToken this change probably does not affect you.
+ --------------------------------------------------------------------
+
+ For a long time it has bothered me that these accessor functions
+ in ANTLRAbstractToken were not const member functions. I have
+ refrained from changing them because it require users to modify
+ existing token class definitions which are derived directly
+ from ANTLRAbstractToken. I think it is now time.
+
+ For those who are not used to C++, a "const member function" is a
+ member function which does not modify its own object - the thing
+ to which "this" points. This is quite different from a function
+ which does not modify its arguments
+
+ Most token definitions based on ANTLRAbstractToken have something like
+ the following in order to create concrete definitions of the pure
+ virtual methods in ANTLRAbstractToken:
+
+ class MyToken : public ANTLRAbstractToken {
+ ...
+ ANTLRTokenType getType() {return _type; }
+ int getLine() {return _line; }
+ ANTLRChar * getText() {return _text; }
+ ...
+ }
+
+ The required change is simply to put "const" following the function
+ prototype in the header (.h file) and the definition file (.cpp if
+ it is not inline):
+
+ class MyToken : public ANTLRAbstractToken {
+ ...
+ ANTLRTokenType getType() const {return _type; }
+ int getLine() const {return _line; }
+ ANTLRChar * getText() const {return _text; }
+ ...
+ }
+
+ This was originally proposed a long time ago by Bruce
+ Guenter (bruceg@qcc.sk.ca).
+
+#136. (Changed in MR11) Added getLength() to ANTLRCommonToken
+
+ Classes ANTLRCommonToken and ANTLRCommonTokenNoRefCountToken
+ now have a member function:
+
+ int getLength() const { return strlen(getText()) }
+
+ Suggested by Sramji Ramanathan (ps@kumaran.com).
+
+#135. (Changed in MR11) Raised antlr's own default ZZLEXBUFSIZE to 8k
+
+#134a. (ansi_mr10.zip) T.J. Parr's ANSI C grammar made 1.33MR11 compatible
+
+ There is a typographical error in the definition of BITWISEOREQ:
+
+ #token BITWISEOREQ "!=" should be "\|="
+
+ When this change is combined with the bugfix to the follow set cache
+ problem (Item #147) and a minor rearrangement of the grammar
+ (Item #134b) it becomes a k=1 ck=2 grammar.
+
+#134b. (ansi_mr10.zip) T.J. Parr's ANSI C grammar made 1.33MR11 compatible
+
+ The following changes were made in the ansi.g grammar (along with
+ using -mrhoist on):
+
+ ansi.g
+ ======
+ void tracein(char *) ====> void tracein(const char *)
+ void traceout(char *) ====> void traceout(const char *)
+
+ <LT(1)->getType()==IDENTIFIER ? isTypeName(LT(1)->getText()) : 1>>?
+ ====> <<isTypeName(LT(1)->getText())>>?
+
+ <<(LT(1)->getType()==LPARENTHESIS && LT(2)->getType()==IDENTIFIER) ? \
+ isTypeName(LT(2)->getText()) : 1>>?
+ ====> (LPARENTHESIS IDENTIFIER)? => <<isTypeName(LT(2)->getText())>>?
+
+ <<(LT(1)->getType()==LPARENTHESIS && LT(2)->getType()==IDENTIFIER) ? \
+ isTypeName(LT(2)->getText()) : 1>>?
+ ====> (LPARENTHESIS IDENTIFIER)? => <<isTypeName(LT(2)->getText())>>?
+
+ added to init(): traceOptionValueDefault=0;
+ added to init(): traceOption(-1);
+
+ change rule "statement":
+
+ statement
+ : plain_label_statement
+ | case_label_statement
+ | <<;>> expression SEMICOLON
+ | compound_statement
+ | selection_statement
+ | iteration_statement
+ | jump_statement
+ | SEMICOLON
+ ;
+
+ plain_label_statement
+ : IDENTIFIER COLON statement
+ ;
+
+ case_label_statement
+ : CASE constant_expression COLON statement
+ | DEFAULT COLON statement
+ ;
+
+ support.cpp
+ ===========
+ void tracein(char *) ====> void tracein(const char *)
+ void traceout(char *) ====> void traceout(const char *)
+
+ added to tracein(): ANTLRParser::tracein(r); // call superclass method
+ added to traceout(): ANTLRParser::traceout(r); // call superclass method
+
+ Makefile
+ ========
+ added to AFLAGS: -mrhoist on -prc on
+
+#133. (Changed in 1.33MR11) Make trace options public in ANTLRParser
+
+ In checking T.J. Parr's ANSI C grammar for compatibility with
+ 1.33MR11 discovered that it was inconvenient to have the
+ trace facilities with protected access.
+
+#132. (Changed in 1.33MR11) Recognition of identical predicates in alts
+
+ Prior to 1.33MR11, there would be no ambiguity warning when the
+ very same predicate was used to disambiguate both alternatives:
+
+ test: ref B
+ | ref C
+ ;
+
+ ref : <<pred(LATEXT(1)>>? A
+
+ In 1.33MR11 this will cause the warning:
+
+ warning: the predicates used to disambiguate rule test
+ (file v98.g alt 1 line 1 and alt 2 line 2)
+ are identical and have no resolving power
+
+ ----------------- Note -----------------
+
+ This is different than the following case
+
+ test: <<pred(LATEXT(1))>>? A B
+ | <<pred(LATEXT(1)>>? A C
+ ;
+
+ In this case there are two distinct predicates
+ which have exactly the same text. In the first
+ example there are two references to the same
+ predicate. The problem represented by this
+ grammar will be addressed later.
+
+#131. (Changed in 1.33MR11) Case insensitive command line options
+
+ Command line switches like "-CC" and keywords like "on", "off",
+ and "stdin" are no longer case sensitive in antlr, dlg, and sorcerer.
+
+#130. (Changed in 1.33MR11) Changed ANTLR_VERSION to int from string
+
+ The ANTLR_VERSION was not an integer, making it difficult to
+ perform conditional compilation based on the antlr version.
+
+ Henceforth, ANTLR_VERSION will be:
+
+ (base_version * 10000) + release number
+
+ thus 1.33MR11 will be: 133*100+11 = 13311
+
+ Suggested by Rainer Janssen (Rainer.Janssen@Informatik.Uni-Oldenburg.DE).
+
+#129. (Changed in 1.33MR11) Addition of ANTLR_VERSION to <parserName>.h
+
+ The following code is now inserted into <parserName>.h amd
+ stdpccts.h:
+
+ #ifndef ANTLR_VERSION
+ #define ANTLR_VERSION 13311
+ #endif
+
+ Suggested by Rainer Janssen (Rainer.Janssen@Informatik.Uni-Oldenburg.DE)
+
+#128. (Changed in 1.33MR11) Redundant predicate code in (<<pred>>? ...)+
+
+ Prior to 1.33MR11, the following grammar would generate
+ redundant tests for the "while" condition.
+
+ rule2 : (<<pred>>? X)+ X
+ | B
+ ;
+
+ The code would resemble:
+
+ if (LA(1)==X) {
+ if (pred) {
+ do {
+ if (!pred) {zzfailed_pred(" pred");}
+ zzmatch(X); zzCONSUME;
+ } while (LA(1)==X && pred && pred);
+ } else {...
+
+ With 1.33MR11 the redundant predicate test is omitted.
+
+#127. (Changed in 1.33MR11)
+
+ Count Syntax Errors Count DLG Errors
+ ------------------- ----------------
+
+ C++ mode ANTLRParser:: DLGLexerBase::
+ syntaxErrCount lexErrCount
+ C mode zzSyntaxErrCount zzLexErrCount
+
+ The C mode variables are global and initialized to 0.
+ They are *not* reset to 0 automatically when antlr is
+ restarted.
+
+ The C++ mode variables are public. They are initialized
+ to 0 by the constructors. They are *not* reset to 0 by the
+ ANTLRParser::init() method.
+
+ Suggested by Reinier van den Born (reinier@vnet.ibm.com).
+
+#126. (Changed in 1.33MR11) Addition of #first <<...>>
+
+ The #first <<...>> inserts the specified text in the output
+ files before any other #include statements required by pccts.
+ The only things before the #first text are comments and
+ a #define ANTLR_VERSION.
+
+ Requested by and Esa Pulkkinen (esap@cs.tut.fi) and Alexin
+ Zoltan (alexin@inf.u-szeged.hu).
+
+#125. (Changed in 1.33MR11) Lookahead for (guard)? && <<p>>? predicates
+
+ When implementing the new style of guard predicate (Item #113)
+ in 1.33MR10 I decided to temporarily ignore the problem of
+ computing the "narrowest" lookahead context.
+
+ Consider the following k=1 grammar:
+
+ start : a
+ | b
+ ;
+
+ a : (A)? && <<pred1(LATEXT(1))>>? ab ;
+ b : (B)? && <<pred2(LATEXT(1))>>? ab ;
+
+ ab : A | B ;
+
+ In MR10 the context for both "a" and "b" was {A B} because this is
+ the first set of rule "ab". Normally, this is not a problem because
+ the predicate which follows the guard inhibits any ambiguity report
+ by antlr.
+
+ In MR11 the first set for rule "a" is {A} and for rule "b" it is {B}.
+
+#124. A Note on the New "&&" Style Guarded Predicates
+
+ I've been asked several times, "What is the difference between
+ the old "=>" style guard predicates and the new style "&&" guard
+ predicates, and how do you choose one over the other" ?
+
+ The main difference is that the "=>" does not apply the
+ predicate if the context guard doesn't match, whereas
+ the && form always does. What is the significance ?
+
+ If you have a predicate which is not on the "leading edge"
+ it cannot be hoisted. Suppose you need a predicate that
+ looks at LA(2). You must introduce it manually. The
+ classic example is:
+
+ castExpr :
+ LP typeName RP
+ | ....
+ ;
+
+ typeName : <<isTypeName(LATEXT(1))>>? ID
+ | STRUCT ID
+ ;
+
+ The problem is that typeName isn't on the leading edge
+ of castExpr, so the predicate isTypeName won't be hoisted into
+ castExpr to help make a decision on which production to choose.
+
+ The *first* attempt to fix it is this:
+
+ castExpr :
+ <<isTypeName(LATEXT(2))>>?
+ LP typeName RP
+ | ....
+ ;
+
+ Unfortunately, this won't work because it ignores
+ the problem of STRUCT. The solution is to apply
+ isTypeName() in castExpr if LA(2) is an ID and
+ don't apply it when LA(2) is STRUCT:
+
+ castExpr :
+ (LP ID)? => <<isTypeName(LATEXT(2))>>?
+ LP typeName RP
+ | ....
+ ;
+
+ In conclusion, the "=>" style guarded predicate is
+ useful when:
+
+ a. the tokens required for the predicate
+ are not on the leading edge
+ b. there are alternatives in the expression
+ selected by the predicate for which the
+ predicate is inappropriate
+
+ If (b) were false, then one could use a simple
+ predicate (assuming "-prc on"):
+
+ castExpr :
+ <<isTypeName(LATEXT(2))>>?
+ LP typeName RP
+ | ....
+ ;
+
+ typeName : <<isTypeName(LATEXT(1))>>? ID
+ ;
+
+ So, when do you use the "&&" style guarded predicate ?
+
+ The new-style "&&" predicate should always be used with
+ predicate context. The context guard is in ADDITION to
+ the automatically computed context. Thus it useful for
+ predicates which depend on the token type for reasons
+ other than context.
+
+ The following example is contributed by Reinier van den Born
+ (reinier@vnet.ibm.com).
+
+ +-------------------------------------------------------------------------+
+ | This grammar has two ways to call functions: |
+ | |
+ | - a "standard" call syntax with parens and comma separated args |
+ | - a shell command like syntax (no parens and spacing separated args) |
+ | |
+ | The former also allows a variable to hold the name of the function, |
+ | the latter can also be used to call external commands. |
+ | |
+ | The grammar (simplified) looks like this: |
+ | |
+ | fun_call : ID "(" { expr ("," expr)* } ")" |
+ | /* ID is function name */ |
+ | | "@" ID "(" { expr ("," expr)* } ")" |
+ | /* ID is var containing fun name */ |
+ | ; |
+ | |
+ | command : ID expr* /* ID is function name */ |
+ | | path expr* /* path is external command name */ |
+ | ; |
+ | |
+ | path : ID /* left out slashes and such */ |
+ | | "@" ID /* ID is environment var */ |
+ | ; |
+ | |
+ | expr : .... |
+ | | "(" expr ")"; |
+ | |
+ | call : fun_call |
+ | | command |
+ | ; |
+ | |
+ | Obviously the call is wildly ambiguous. This is more or less how this |
+ | is to be resolved: |
+ | |
+ | A call begins with an ID or an @ followed by an ID. |
+ | |
+ | If it is an ID and if it is an ext. command name -> command |
+ | if followed by a paren -> fun_call |
+ | otherwise -> command |
+ | |
+ | If it is an @ and if the ID is a var name -> fun_call |
+ | otherwise -> command |
+ | |
+ | One can implement these rules quite neatly using && predicates: |
+ | |
+ | call : ("@" ID)? && <<isVarName(LT(2))>>? fun_call |
+ | | (ID)? && <<isExtCmdName>>? command |
+ | | (ID "(")? fun_call |
+ | | command |
+ | ; |
+ | |
+ | This can be done better, so it is not an ideal example, but it |
+ | conveys the principle. |
+ +-------------------------------------------------------------------------+
+
+#123. (Changed in 1.33MR11) Correct definition of operators in ATokPtr.h
+
+ The return value of operators in ANTLRTokenPtr:
+
+ changed: unsigned ... operator !=(...)
+ to: int ... operator != (...)
+ changed: unsigned ... operator ==(...)
+ to: int ... operator == (...)
+
+ Suggested by R.A. Nelson (cowboy@VNET.IBM.COM)
+
+#122. (Changed in 1.33MR11) Member functions to reset DLG in C++ mode
+
+ void DLGFileReset(FILE *f) { input = f; found_eof = 0; }
+ void DLGStringReset(DLGChar *s) { input = s; p = &input[0]; }
+
+ Supplied by R.A. Nelson (cowboy@VNET.IBM.COM)
+
+#121. (Changed in 1.33MR11) Another attempt to fix -o (output dir) option
+
+ Another attempt is made to improve the -o option of antlr, dlg,
+ and sorcerer. This one by JVincent (JVincent@novell.com).
+
+ The current rule:
+
+ a. If -o is not specified than any explicit directory
+ names are retained.
+
+ b. If -o is specified than the -o directory name overrides any
+ explicit directory names.
+
+ c. The directory name of the grammar file is *not* stripped
+ to create the main output file. However it is stil subject
+ to override by the -o directory name.
+
+#120. (Changed in 1.33MR11) "-info f" output to stdout rather than stderr
+
+ Added option 0 (e.g. "-info 0") which is a noop.
+
+#119. (Changed in 1.33MR11) Ambiguity aid for grammars
+
+ The user can ask for additional information on ambiguities reported
+ by antlr to stdout. At the moment, only one ambiguity report can
+ be created in an antlr run.
+
+ This feature is enabled using the "-aa" (Ambiguity Aid) option.
+
+ The following options control the reporting of ambiguities:
+
+ -aa ruleName Selects reporting by name of rule
+ -aa lineNumber Selects reporting by line number
+ (file name not compared)
+
+ -aam Selects "multiple" reporting for a token
+ in the intersection set of the
+ alternatives.
+
+ For instance, the token ID may appear dozens
+ of times in various paths as the program
+ explores the rules which are reachable from
+ the point of an ambiguity. With option -aam
+ every possible path the search program
+ encounters is reported.
+
+ Without -aam only the first encounter is
+ reported. This may result in incomplete
+ information, but the information may be
+ sufficient and much shorter.
+
+ -aad depth Selects the depth of the search.
+ The default value is 1.
+
+ The number of paths to be searched, and the
+ size of the report can grow geometrically
+ with the -ck value if a full search for all
+ contributions to the source of the ambiguity
+ is explored.
+
+ The depth represents the number of tokens
+ in the lookahead set which are matched against
+ the set of ambiguous tokens. A depth of 1
+ means that the search stops when a lookahead
+ sequence of just one token is matched.
+
+ A k=1 ck=6 grammar might generate 5,000 items
+ in a report if a full depth 6 search is made
+ with the Ambiguity Aid. The source of the
+ problem may be in the first token and obscured
+ by the volume of data - I hesitate to call
+ it information.
+
+ When the user selects a depth > 1, the search
+ is first performed at depth=1 for both
+ alternatives, then depth=2 for both alternatives,
+ etc.
+
+ Sample output for rule grammar in antlr.g itself:
+
+ +---------------------------------------------------------------------+
+ | Ambiguity Aid |
+ | |
+ | Choice 1: grammar/70 line 632 file a.g |
+ | Choice 2: grammar/82 line 644 file a.g |
+ | |
+ | Intersection of lookahead[1] sets: |
+ | |
+ | "\}" "class" "#errclass" "#tokclass" |
+ | |
+ | Choice:1 Depth:1 Group:1 ("#errclass") |
+ | 1 in (...)* block grammar/70 line 632 a.g |
+ | 2 to error grammar/73 line 635 a.g |
+ | 3 error error/1 line 894 a.g |
+ | 4 #token "#errclass" error/2 line 895 a.g |
+ | |
+ | Choice:1 Depth:1 Group:2 ("#tokclass") |
+ | 2 to tclass grammar/74 line 636 a.g |
+ | 3 tclass tclass/1 line 937 a.g |
+ | 4 #token "#tokclass" tclass/2 line 938 a.g |
+ | |
+ | Choice:1 Depth:1 Group:3 ("class") |
+ | 2 to class_def grammar/75 line 637 a.g |
+ | 3 class_def class_def/1 line 669 a.g |
+ | 4 #token "class" class_def/3 line 671 a.g |
+ | |
+ | Choice:1 Depth:1 Group:4 ("\}") |
+ | 2 #token "\}" grammar/76 line 638 a.g |
+ | |
+ | Choice:2 Depth:1 Group:5 ("#errclass") |
+ | 1 in (...)* block grammar/83 line 645 a.g |
+ | 2 to error grammar/93 line 655 a.g |
+ | 3 error error/1 line 894 a.g |
+ | 4 #token "#errclass" error/2 line 895 a.g |
+ | |
+ | Choice:2 Depth:1 Group:6 ("#tokclass") |
+ | 2 to tclass grammar/94 line 656 a.g |
+ | 3 tclass tclass/1 line 937 a.g |
+ | 4 #token "#tokclass" tclass/2 line 938 a.g |
+ | |
+ | Choice:2 Depth:1 Group:7 ("class") |
+ | 2 to class_def grammar/95 line 657 a.g |
+ | 3 class_def class_def/1 line 669 a.g |
+ | 4 #token "class" class_def/3 line 671 a.g |
+ | |
+ | Choice:2 Depth:1 Group:8 ("\}") |
+ | 2 #token "\}" grammar/96 line 658 a.g |
+ +---------------------------------------------------------------------+
+
+ For a linear lookahead set ambiguity (where k=1 or for k>1 but
+ when all lookahead sets [i] with i<k all have degree one) the
+ reports appear in the following order:
+
+ for (depth=1 ; depth <= "-aad depth" ; depth++) {
+ for (alternative=1; alternative <=2 ; alternative++) {
+ while (matches-are-found) {
+ group++;
+ print-report
+ };
+ };
+ };
+
+ For reporting a k-tuple ambiguity, the reports appear in the
+ following order:
+
+ for (depth=1 ; depth <= "-aad depth" ; depth++) {
+ while (matches-are-found) {
+ for (alternative=1; alternative <=2 ; alternative++) {
+ group++;
+ print-report
+ };
+ };
+ };
+
+ This is because matches are generated in different ways for
+ linear lookahead and k-tuples.
+
+#118. (Changed in 1.33MR11) DEC VMS makefile and VMS related changes
+
+ Revised makefiles for DEC/VMS operating system for antlr, dlg,
+ and sorcerer.
+
+ Reduced names of routines with external linkage to less than 32
+ characters to conform to DEC/VMS linker limitations.
+
+ Jean-Francois Pieronne discovered problems with dlg and antlr
+ due to the VMS linker not being case sensitive for names with
+ external linkage. In dlg the problem was with "className" and
+ "ClassName". In antlr the problem was with "GenExprSets" and
+ "genExprSets".
+
+ Added genmms, a version of genmk for the DEC/VMS version of make.
+ The source is in directory pccts/support/DECmms.
+
+ All VMS contributions by Jean-Francois Pieronne (jfp@iname.com).
+
+#117. (Changed in 1.33MR10) new EXPERIMENTAL predicate hoisting code
+
+ The hoisting of predicates into rules to create prediction
+ expressions is a problem in antlr. Consider the following
+ example (k=1 with -prc on):
+
+ start : (a)* "@" ;
+ a : b | c ;
+ b : <<isUpper(LATEXT(1))>>? A ;
+ c : A ;
+
+ Prior to 1.33MR10 the code generated for "start" would resemble:
+
+ while {
+ if (LA(1)==A &&
+ (!LA(1)==A || isUpper())) {
+ a();
+ }
+ };
+
+ This code is wrong because it makes rule "c" unreachable from
+ "start". The essence of the problem is that antlr fails to
+ recognize that there can be a valid alternative within "a" even
+ when the predicate <<isUpper(LATEXT(1))>>? is false.
+
+ In 1.33MR10 with -mrhoist the hoisting of the predicate into
+ "start" is suppressed because it recognizes that "c" can
+ cover all the cases where the predicate is false:
+
+ while {
+ if (LA(1)==A) {
+ a();
+ }
+ };
+
+ With the antlr "-info p" switch the user will receive information
+ about the predicate suppression in the generated file:
+
+ --------------------------------------------------------------
+ #if 0
+
+ Hoisting of predicate suppressed by alternative without predicate.
+ The alt without the predicate includes all cases where
+ the predicate is false.
+
+ WITH predicate: line 7 v1.g
+ WITHOUT predicate: line 7 v1.g
+
+ The context set for the predicate:
+
+ A
+
+ The lookahead set for the alt WITHOUT the semantic predicate:
+
+ A
+
+ The predicate:
+
+ pred << isUpper(LATEXT(1))>>?
+ depth=k=1 rule b line 9 v1.g
+ set context:
+ A
+ tree context: null
+
+ Chain of referenced rules:
+
+ #0 in rule start (line 5 v1.g) to rule a
+ #1 in rule a (line 7 v1.g)
+
+ #endif
+ --------------------------------------------------------------
+
+ A predicate can be suppressed by a combination of alternatives
+ which, taken together, cover a predicate:
+
+ start : (a)* "@" ;
+
+ a : b | ca | cb | cc ;
+
+ b : <<isUpper(LATEXT(1))>>? ( A | B | C ) ;
+
+ ca : A ;
+ cb : B ;
+ cc : C ;
+
+ Consider a more complex example in which "c" covers only part of
+ a predicate:
+
+ start : (a)* "@" ;
+
+ a : b
+ | c
+ ;
+
+ b : <<isUpper(LATEXT(1))>>?
+ ( A
+ | X
+ );
+
+ c : A
+ ;
+
+ Prior to 1.33MR10 the code generated for "start" would resemble:
+
+ while {
+ if ( (LA(1)==A || LA(1)==X) &&
+ (! (LA(1)==A || LA(1)==X) || isUpper()) {
+ a();
+ }
+ };
+
+ With 1.33MR10 and -mrhoist the predicate context is restricted to
+ the non-covered lookahead. The code resembles:
+
+ while {
+ if ( (LA(1)==A || LA(1)==X) &&
+ (! (LA(1)==X) || isUpper()) {
+ a();
+ }
+ };
+
+ With the antlr "-info p" switch the user will receive information
+ about the predicate restriction in the generated file:
+
+ --------------------------------------------------------------
+ #if 0
+
+ Restricting the context of a predicate because of overlap
+ in the lookahead set between the alternative with the
+ semantic predicate and one without
+ Without this restriction the alternative without the predicate
+ could not be reached when input matched the context of the
+ predicate and the predicate was false.
+
+ WITH predicate: line 11 v4.g
+ WITHOUT predicate: line 12 v4.g
+
+ The original context set for the predicate:
+
+ A X
+
+ The lookahead set for the alt WITHOUT the semantic predicate:
+
+ A
+
+ The intersection of the two sets
+
+ A
+
+ The original predicate:
+
+ pred << isUpper(LATEXT(1))>>?
+ depth=k=1 rule b line 15 v4.g
+ set context:
+ A X
+ tree context: null
+
+ The new (modified) form of the predicate:
+
+ pred << isUpper(LATEXT(1))>>?
+ depth=k=1 rule b line 15 v4.g
+ set context:
+ X
+ tree context: null
+
+ #endif
+ --------------------------------------------------------------
+
+ The bad news about -mrhoist:
+
+ (a) -mrhoist does not analyze predicates with lookahead
+ depth > 1.
+
+ (b) -mrhoist does not look past a guarded predicate to
+ find context which might cover other predicates.
+
+ For these cases you might want to use syntactic predicates.
+ When a semantic predicate fails during guess mode the guess
+ fails and the next alternative is tried.
+
+ Limitation (a) is illustrated by the following example:
+
+ start : (stmt)* EOF ;
+
+ stmt : cast
+ | expr
+ ;
+ cast : <<isTypename(LATEXT(2))>>? LP ID RP ;
+
+ expr : LP ID RP ;
+
+ This is not much different from the first example, except that
+ it requires two tokens of lookahead context to determine what
+ to do. This predicate is NOT suppressed because the current version
+ is unable to handle predicates with depth > 1.
+
+ A predicate can be combined with other predicates during hoisting.
+ In those cases the depth=1 predicates are still handled. Thus,
+ in the following example the isUpper() predicate will be suppressed
+ by line #4 when hoisted from "bizarre" into "start", but will still
+ be present in "bizarre" in order to predict "stmt".
+
+ start : (bizarre)* EOF ; // #1
+ // #2
+ bizarre : stmt // #3
+ | A // #4
+ ;
+
+ stmt : cast
+ | expr
+ ;
+
+ cast : <<isTypename(LATEXT(2))>>? LP ID RP ;
+
+ expr : LP ID RP ;
+ | <<isUpper(LATEXT(1))>>? A
+
+ Limitation (b) is illustrated by the following example of a
+ context guarded predicate:
+
+ rule : (A)? <<p>>? // #1
+ (A // #2
+ |B // #3
+ ) // #4
+ | <<q>> B // #5
+ ;
+
+ Recall that this means that when the lookahead is NOT A then
+ the predicate "p" is ignored and it attempts to match "A|B".
+ Ideally, the "B" at line #3 should suppress predicate "q".
+ However, the current version does not attempt to look past
+ the guard predicate to find context which might suppress other
+ predicates.
+
+ In some cases -mrhoist will lead to the reporting of ambiguities
+ which were not visible before:
+
+ start : (a)* "@";
+ a : bc | d;
+ bc : b | c ;
+
+ b : <<isUpper(LATEXT(1))>>? A;
+ c : A ;
+
+ d : A ;
+
+ In this case there is a true ambiguity in "a" between "bc" and "d"
+ which can both match "A". Without -mrhoist the predicate in "b"
+ is hoisted into "a" and there is no ambiguity reported. However,
+ with -mrhoist, the predicate in "b" is suppressed by "c" (as it
+ should be) making the ambiguity in "a" apparent.
+
+ The motivations for these changes were hoisting problems reported
+ by Reinier van den Born (reinier@vnet.ibm.com) and several others.
+
+#116. (Changed in 1.33MR10) C++ mode: tracein/traceout rule name is (const char *)
+
+ The prototype for C++ mode routine tracein (and traceout) has changed from
+ "char *" to "const char *".
+
+#115. (Changed in 1.33MR10) Using guess mode with exception handlers in C mode
+
+ The definition of the C mode macros zzmatch_wsig and zzsetmatch_wsig
+ neglected to consider guess mode. When control passed to the rule's
+ parse exception handler the routine would exit without ever closing the
+ guess block. This would lead to unpredictable behavior.
+
+ In 1.33MR10 the behavior of exceptions in C mode and C++ mode should be
+ identical.
+
+#114. (Changed in 1.33MR10) difference in [zz]resynch() between C and C++ modes
+
+ There was a slight difference in the way C and C++ mode resynchronized
+ following a parsing error. The C routine would sometimes skip an extra
+ token before attempting to resynchronize.
+
+ The C routine was changed to match the C++ routine.
+
+#113. (Changed in 1.33MR10) new context guarded pred: (g)? && <<p>>? expr
+
+ The existing context guarded predicate:
+
+ rule : (guard)? => <<p>>? expr
+ | next_alternative
+ ;
+
+ generates code which resembles:
+
+ if (lookahead(expr) && (!guard || pred)) {
+ expr()
+ } else ....
+
+ This is not suitable for some applications because it allows
+ expr() to be invoked when the predicate is false. This is
+ intentional because it is meant to mimic automatically computed
+ predicate context.
+
+ The new context guarded predicate uses the guard information
+ differently because it has a different goal. Consider:
+
+ rule : (guard)? && <<p>>? expr
+ | next_alternative
+ ;
+
+ The new style of context guarded predicate is equivalent to:
+
+ rule : <<guard==true && pred>>? expr
+ | next_alternative
+ ;
+
+ It generates code which resembles:
+
+ if (lookahead(expr) && guard && pred) {
+ expr();
+ } else ...
+
+ Both forms of guarded predicates severely restrict the form of
+ the context guard: it can contain no rule references, no
+ (...)*, no (...)+, and no {...}. It may contain token and
+ token class references, and alternation ("|").
+
+ Addition for 1.33MR11: in the token expression all tokens must
+ be at the same height of the token tree:
+
+ (A ( B | C))? && ... is ok (all height 2)
+ (A ( B | ))? && ... is not ok (some 1, some 2)
+ (A B C D | E F G H)? && ... is ok (all height 4)
+ (A B C D | E )? && ... is not ok (some 4, some 1)
+
+ This restriction is required in order to properly compute the lookahead
+ set for expressions like:
+
+ rule1 : (A B C)? && <<pred>>? rule2 ;
+ rule2 : (A|X) (B|Y) (C|Z);
+
+ This addition was suggested by Rienier van den Born (reinier@vnet.ibm.com)
+
+#112. (Changed in 1.33MR10) failed validation predicate in C guess mode
+
+ John Lilley (jlilley@empathy.com) suggested that failed validation
+ predicates abort a guess rather than reporting a failed error.
+ This was installed in C++ mode (Item #4). Only now was it noticed
+ that the fix was never installed for C mode.
+
+#111. (Changed in 1.33MR10) moved zzTRACEIN to before init action
+
+ When the antlr -gd switch is present antlr generates calls to
+ zzTRACEIN at the start of a rule and zzTRACEOUT at the exit
+ from a rule. Prior to 1.33MR10 Tthe call to zzTRACEIN was
+ after the init-action, which could cause confusion because the
+ init-actions were reported with the name of the enclosing rule,
+ rather than the active rule.
+
+#110. (Changed in 1.33MR10) antlr command line copied to generated file
+
+ The antlr command line is now copied to the generated file near
+ the start.
+
+#109. (Changed in 1.33MR10) improved trace information
+
+ The quality of the trace information provided by the "-gd"
+ switch has been improved significantly. Here is an example
+ of the output from a test program. It shows the rule name,
+ the first token of lookahead, the call depth, and the guess
+ status:
+
+ exit rule gusxx {"?"} depth 2
+ enter rule gusxx {"?"} depth 2
+ enter rule gus1 {"o"} depth 3 guessing
+ guess done - returning to rule gus1 {"o"} at depth 3
+ (guess mode continues - an enclosing guess is still active)
+ guess done - returning to rule gus1 {"Z"} at depth 3
+ (guess mode continues - an enclosing guess is still active)
+ exit rule gus1 {"Z"} depth 3 guessing
+ guess done - returning to rule gusxx {"o"} at depth 2 (guess mode ends)
+ enter rule gus1 {"o"} depth 3
+ guess done - returning to rule gus1 {"o"} at depth 3 (guess mode ends)
+ guess done - returning to rule gus1 {"Z"} at depth 3 (guess mode ends)
+ exit rule gus1 {"Z"} depth 3
+ line 1: syntax error at "Z" missing SC
+ ...
+
+ Rule trace reporting is controlled by the value of the integer
+ [zz]traceOptionValue: when it is positive tracing is enabled,
+ otherwise it is disabled. Tracing during guess mode is controlled
+ by the value of the integer [zz]traceGuessOptionValue. When
+ it is positive AND [zz]traceOptionValue is positive rule trace
+ is reported in guess mode.
+
+ The values of [zz]traceOptionValue and [zz]traceGuessOptionValue
+ can be adjusted by subroutine calls listed below.
+
+ Depending on the presence or absence of the antlr -gd switch
+ the variable [zz]traceOptionValueDefault is set to 0 or 1. When
+ the parser is initialized or [zz]traceReset() is called the
+ value of [zz]traceOptionValueDefault is copied to [zz]traceOptionValue.
+ The value of [zz]traceGuessOptionValue is always initialzed to 1,
+ but, as noted earlier, nothing will be reported unless
+ [zz]traceOptionValue is also positive.
+
+ When the parser state is saved/restored the value of the trace
+ variables are also saved/restored. If a restore causes a change in
+ reporting behavior from on to off or vice versa this will be reported.
+
+ When the -gd option is selected, the macro "#define zzTRACE_RULES"
+ is added to appropriate output files.
+
+ C++ mode
+ --------
+ int traceOption(int delta)
+ int traceGuessOption(int delta)
+ void traceReset()
+ int traceOptionValueDefault
+
+ C mode
+ --------
+ int zzTraceOption(int delta)
+ int zzTraceGuessOption(int delta)
+ void zzTraceReset()
+ int zzTraceOptionValueDefault
+
+ The argument "delta" is added to the traceOptionValue. To
+ turn on trace when inside a particular rule one:
+
+ rule : <<traceOption(+1);>>
+ (
+ rest-of-rule
+ )
+ <<traceOption(-1);>>
+ ; /* fail clause */ <<traceOption(-1);>>
+
+ One can use the same idea to turn *off* tracing within a
+ rule by using a delta of (-1).
+
+ An improvement in the rule trace was suggested by Sramji
+ Ramanathan (ps@kumaran.com).
+
+#108. A Note on Deallocation of Variables Allocated in Guess Mode
+
+ NOTE
+ ------------------------------------------------------
+ This mechanism only works for heap allocated variables
+ ------------------------------------------------------
+
+ The rewrite of the trace provides the machinery necessary
+ to properly free variables or undo actions following a
+ failed guess.
+
+ The macro zzUSER_GUESS_HOOK(guessSeq,zzrv) is expanded
+ as part of the zzGUESS macro. When a guess is opened
+ the value of zzrv is 0. When a longjmp() is executed to
+ undo the guess, the value of zzrv will be 1.
+
+ The macro zzUSER_GUESS_DONE_HOOK(guessSeq) is expanded
+ as part of the zzGUESS_DONE macro. This is executed
+ whether the guess succeeds or fails as part of closing
+ the guess.
+
+ The guessSeq is a sequence number which is assigned to each
+ guess and is incremented by 1 for each guess which becomes
+ active. It is needed by the user to associate the start of
+ a guess with the failure and/or completion (closing) of a
+ guess.
+
+ Guesses are nested. They must be closed in the reverse
+ of the order that they are opened.
+
+ In order to free memory used by a variable during a guess
+ a user must write a routine which can be called to
+ register the variable along with the current guess sequence
+ number provided by the zzUSER_GUESS_HOOK macro. If the guess
+ fails, all variables tagged with the corresponding guess
+ sequence number should be released. This is ugly, but
+ it would require a major rewrite of antlr 1.33 to use
+ some mechanism other than setjmp()/longjmp().
+
+ The order of calls for a *successful* guess would be:
+
+ zzUSER_GUESS_HOOK(guessSeq,0);
+ zzUSER_GUESS_DONE_HOOK(guessSeq);
+
+ The order of calls for a *failed* guess would be:
+
+ zzUSER_GUESS_HOOK(guessSeq,0);
+ zzUSER_GUESS_HOOK(guessSeq,1);
+ zzUSER_GUESS_DONE_HOOK(guessSeq);
+
+ The default definitions of these macros are empty strings.
+
+ Here is an example in C++ mode. The zzUSER_GUESS_HOOK and
+ zzUSER_GUESS_DONE_HOOK macros and myGuessHook() routine
+ can be used without change in both C and C++ versions.
+
+ ----------------------------------------------------------------------
+ <<
+
+ #include "AToken.h"
+
+ typedef ANTLRCommonToken ANTLRToken;
+
+ #include "DLGLexer.h"
+
+ int main() {
+
+ {
+ DLGFileInput in(stdin);
+ DLGLexer lexer(&in,2000);
+ ANTLRTokenBuffer pipe(&lexer,1);
+ ANTLRCommonToken aToken;
+ P parser(&pipe);
+
+ lexer.setToken(&aToken);
+ parser.init();
+ parser.start();
+ };
+
+ fclose(stdin);
+ fclose(stdout);
+ return 0;
+ }
+
+ >>
+
+ <<
+ char *s=NULL;
+
+ #undef zzUSER_GUESS_HOOK
+ #define zzUSER_GUESS_HOOK(guessSeq,zzrv) myGuessHook(guessSeq,zzrv);
+ #undef zzUSER_GUESS_DONE_HOOK
+ #define zzUSER_GUESS_DONE_HOOK(guessSeq) myGuessHook(guessSeq,2);
+
+ void myGuessHook(int guessSeq,int zzrv) {
+ if (zzrv == 0) {
+ fprintf(stderr,"User hook: starting guess #%d\n",guessSeq);
+ } else if (zzrv == 1) {
+ free (s);
+ s=NULL;
+ fprintf(stderr,"User hook: failed guess #%d\n",guessSeq);
+ } else if (zzrv == 2) {
+ free (s);
+ s=NULL;
+ fprintf(stderr,"User hook: ending guess #%d\n",guessSeq);
+ };
+ }
+
+ >>
+
+ #token A "a"
+ #token "[\t \ \n]" <<skip();>>
+
+ class P {
+
+ start : (top)+
+ ;
+
+ top : (which) ? <<fprintf(stderr,"%s is a which\n",s); free(s); s=NULL; >>
+ | other <<fprintf(stderr,"%s is an other\n",s); free(s); s=NULL; >>
+ ; <<if (s != NULL) free(s); s=NULL; >>
+
+ which : which2
+ ;
+
+ which2 : which3
+ ;
+ which3
+ : (label)? <<fprintf(stderr,"%s is a label\n",s);>>
+ | (global)? <<fprintf(stderr,"%s is a global\n",s);>>
+ | (exclamation)? <<fprintf(stderr,"%s is an exclamation\n",s);>>
+ ;
+
+ label : <<s=strdup(LT(1)->getText());>> A ":" ;
+
+ global : <<s=strdup(LT(1)->getText());>> A "::" ;
+
+ exclamation : <<s=strdup(LT(1)->getText());>> A "!" ;
+
+ other : <<s=strdup(LT(1)->getText());>> "other" ;
+
+ }
+ ----------------------------------------------------------------------
+
+ This is a silly example, but illustrates the idea. For the input
+ "a ::" with tracing enabled the output begins:
+
+ ----------------------------------------------------------------------
+ enter rule "start" depth 1
+ enter rule "top" depth 2
+ User hook: starting guess #1
+ enter rule "which" depth 3 guessing
+ enter rule "which2" depth 4 guessing
+ enter rule "which3" depth 5 guessing
+ User hook: starting guess #2
+ enter rule "label" depth 6 guessing
+ guess failed
+ User hook: failed guess #2
+ guess done - returning to rule "which3" at depth 5 (guess mode continues
+ - an enclosing guess is still active)
+ User hook: ending guess #2
+ User hook: starting guess #3
+ enter rule "global" depth 6 guessing
+ exit rule "global" depth 6 guessing
+ guess done - returning to rule "which3" at depth 5 (guess mode continues
+ - an enclosing guess is still active)
+ User hook: ending guess #3
+ enter rule "global" depth 6 guessing
+ exit rule "global" depth 6 guessing
+ exit rule "which3" depth 5 guessing
+ exit rule "which2" depth 4 guessing
+ exit rule "which" depth 3 guessing
+ guess done - returning to rule "top" at depth 2 (guess mode ends)
+ User hook: ending guess #1
+ enter rule "which" depth 3
+ .....
+ ----------------------------------------------------------------------
+
+ Remember:
+
+ (a) Only init-actions are executed during guess mode.
+ (b) A rule can be invoked multiple times during guess mode.
+ (c) If the guess succeeds the rule will be called once more
+ without guess mode so that normal actions will be executed.
+ This means that the init-action might need to distinguish
+ between guess mode and non-guess mode using the variable
+ [zz]guessing.
+
+#107. (Changed in 1.33MR10) construction of ASTs in guess mode
+
+ Prior to 1.33MR10, when using automatic AST construction in C++
+ mode for a rule, an AST would be constructed for elements of the
+ rule even while in guess mode. In MR10 this no longer occurs.
+
+#106. (Changed in 1.33MR10) guess variable confusion
+
+ In C++ mode a guess which failed always restored the parser state
+ using zzGUESS_DONE as part of zzGUESS_FAIL. Prior to 1.33MR10,
+ C mode required an explicit call to zzGUESS_DONE after the
+ call to zzGUESS_FAIL.
+
+ Consider:
+
+ rule : (alpha)? beta
+ | ...
+ ;
+
+ The generated code resembles:
+
+ zzGUESS
+ if (!zzrv && LA(1)==ID) { <==== line #1
+ alpha
+ zzGUESS_DONE
+ beta
+ } else {
+ if (! zzrv) zzGUESS_DONE <==== line #2a
+ ....
+
+ However, in some cases line #2 was rendered:
+
+ if (guessing) zzGUESS_DONE <==== line #2b
+
+ This would work for simple test cases, but would fail in
+ some cases where there was a guess while another guess was active.
+ One kind of failure would be to match up the zzGUESS_DONE at line
+ #2b with the "outer" guess which was still active. The outer
+ guess would "succeed" when only the inner guess should have
+ succeeded.
+
+ In 1.33MR10 the behavior of zzGUESS and zzGUESS_FAIL in C and
+ and C++ mode should be identical.
+
+ The same problem appears in 1.33 vanilla in some places. For
+ example:
+
+ start : { (sub)? } ;
+
+ or:
+
+ start : (
+ B
+ | ( sub )?
+ | C
+ )+
+ ;
+
+ generates incorrect code.
+
+ The general principle is:
+
+ (a) use [zz]guessing only when deciding between a call to zzFAIL
+ or zzGUESS_FAIL
+
+ (b) use zzrv in all other cases
+
+ This problem was discovered while testing changes to item #105.
+ I believe this is now fixed. My apologies.
+
+#105. (Changed in 1.33MR10) guess block as single alt of (...)+
+
+ Prior to 1.33MR10 the following constructs:
+
+ rule_plus : (
+ (sub)?
+ )+
+ ;
+
+ rule_star : (
+ (sub)?
+ )*
+ ;
+
+ generated incorrect code for the guess block (which could result
+ in runtime errors) because of an incorrect optimization of a
+ block with only a single alternative.
+
+ The fix caused some changes to the fix described in Item #49
+ because there are now three code generation sequences for (...)+
+ blocks containing a guess block:
+
+ a. single alternative which is a guess block
+ b. multiple alternatives in which the last is a guess block
+ c. all other cases
+
+ Forms like "rule_star" can have unexpected behavior when there
+ is a syntax error: if the subrule "sub" is not matched *exactly*
+ then "rule_star" will consume no tokens.
+
+ Reported by Esa Pulkkinen (esap@cs.tut.fi).
+
+#104. (Changed in 1.33MR10) -o option for dlg
+
+ There was problem with the code added by item #74 to handle the
+ -o option of dlg. This should fix it.
+
+#103. (Changed in 1.33MR10) ANDed semantic predicates
+
+ Rescinded.
+
+ The optimization was a mistake.
+ The resulting problem is described in Item #150.
+
+#102. (Changed in 1.33MR10) allow "class parser : .... {"
+
+ The syntax of the class statement ("class parser-name {")
+ has been extended to allow for the specification of base
+ classes. An arbirtrary number of tokens may now appear
+ between the class name and the "{". They are output
+ again when the class declaration is generated. For
+ example:
+
+ class Parser : public MyBaseClassANTLRparser {
+
+ This was suggested by a user, but I don't have a record
+ of who it was.
+
+#101. (Changed in 1.33MR10) antlr -info command line switch
+
+ -info
+
+ p - extra predicate information in generated file
+
+ t - information about tnode use:
+ at the end of each rule in generated file
+ summary on stderr at end of program
+
+ m - monitor progress
+ prints name of each rule as it is started
+ flushes output at start of each rule
+
+ f - first/follow set information to stdout
+
+ 0 - no operation (added in 1.33MR11)
+
+ The options may be combined and may appear in any order.
+ For example:
+
+ antlr -info ptm -CC -gt -mrhoist on mygrammar.g
+
+#100a. (Changed in 1.33MR10) Predicate tree simplification
+
+ When the same predicates can be referenced in more than one
+ alternative of a block large predicate trees can be formed.
+
+ The difference that these optimizations make is so dramatic
+ that I have decided to use it even when -mrhoist is not selected.
+
+ Consider the following grammar:
+
+ start : ( all )* ;
+
+ all : a
+ | d
+ | e
+ | f
+ ;
+
+ a : c A B
+ | c A C
+ ;
+
+ c : <<AAA(LATEXT(2))>>?
+ ;
+
+ d : <<BBB(LATEXT(2))>>? B C
+ ;
+
+ e : <<CCC(LATEXT(2))>>? B C
+ ;
+
+ f : e X Y
+ ;
+
+ In rule "a" there is a reference to rule "c" in both alternatives.
+ The length of the predicate AAA is k=2 and it can be followed in
+ alternative 1 only by (A B) while in alternative 2 it can be
+ followed only by (A C). Thus they do not have identical context.
+
+ In rule "all" the alternatives which refer to rules "e" and "f" allow
+ elimination of the duplicate reference to predicate CCC.
+
+ The table below summarized the kind of simplification performed by
+ 1.33MR10. In the table, X and Y stand for single predicates
+ (not trees).
+
+ (OR X (OR Y (OR Z))) => (OR X Y Z)
+ (AND X (AND Y (AND Z))) => (AND X Y Z)
+
+ (OR X (... (OR X Y) ... )) => (OR X (... Y ... ))
+ (AND X (... (AND X Y) ... )) => (AND X (... Y ... ))
+ (OR X (... (AND X Y) ... )) => (OR X (... ... ))
+ (AND X (... (OR X Y) ... )) => (AND X (... ... ))
+
+ (AND X) => X
+ (OR X) => X
+
+ In a test with a complex grammar for a real application, a predicate
+ tree with six OR nodes and 12 leaves was reduced to "(OR X Y Z)".
+
+ In 1.33MR10 there is a greater effort to release memory used
+ by predicates once they are no longer in use.
+
+#100b. (Changed in 1.33MR10) Suppression of extra predicate tests
+
+ The following optimizations require that -mrhoist be selected.
+
+ It is relatively easy to optimize the code generated for predicate
+ gates when they are of the form:
+
+ (AND X Y Z ...)
+ or (OR X Y Z ...)
+
+ where X, Y, Z, and "..." represent individual predicates (leaves) not
+ predicate trees.
+
+ If the predicate is an AND the contexts of the X, Y, Z, etc. are
+ ANDed together to create a single Tree context for the group and
+ context tests for the individual predicates are suppressed:
+
+ --------------------------------------------------
+ Note: This was incorrect. The contexts should be
+ ORed together. This has been fixed. A more
+ complete description is available in item #152.
+ ---------------------------------------------------
+
+ Optimization 1: (AND X Y Z ...)
+
+ Suppose the context for Xtest is LA(1)==LP and the context for
+ Ytest is LA(1)==LP && LA(2)==ID.
+
+ Without the optimization the code would resemble:
+
+ if (lookaheadContext &&
+ !(LA(1)==LP && LA(1)==LP && LA(2)==ID) ||
+ ( (! LA(1)==LP || Xtest) &&
+ (! (LA(1)==LP || LA(2)==ID) || Xtest)
+ )) {...
+
+ With the -mrhoist optimization the code would resemble:
+
+ if (lookaheadContext &&
+ ! (LA(1)==LP && LA(2)==ID) || (Xtest && Ytest) {...
+
+ Optimization 2: (OR X Y Z ...) with identical contexts
+
+ Suppose the context for Xtest is LA(1)==ID and for Ytest
+ the context is also LA(1)==ID.
+
+ Without the optimization the code would resemble:
+
+ if (lookaheadContext &&
+ ! (LA(1)==ID || LA(1)==ID) ||
+ (LA(1)==ID && Xtest) ||
+ (LA(1)==ID && Ytest) {...
+
+ With the -mrhoist optimization the code would resemble:
+
+ if (lookaheadContext &&
+ (! LA(1)==ID) || (Xtest || Ytest) {...
+
+ Optimization 3: (OR X Y Z ...) with distinct contexts
+
+ Suppose the context for Xtest is LA(1)==ID and for Ytest
+ the context is LA(1)==LP.
+
+ Without the optimization the code would resemble:
+
+ if (lookaheadContext &&
+ ! (LA(1)==ID || LA(1)==LP) ||
+ (LA(1)==ID && Xtest) ||
+ (LA(1)==LP && Ytest) {...
+
+ With the -mrhoist optimization the code would resemble:
+
+ if (lookaheadContext &&
+ (zzpf=0,
+ (LA(1)==ID && (zzpf=1) && Xtest) ||
+ (LA(1)==LP && (zzpf=1) && Ytest) ||
+ !zzpf) {
+
+ These may appear to be of similar complexity at first,
+ but the non-optimized version contains two tests of each
+ context while the optimized version contains only one
+ such test, as well as eliminating some of the inverted
+ logic (" !(...) || ").
+
+ Optimization 4: Computation of predicate gate trees
+
+ When generating code for the gates of predicate expressions
+ antlr 1.33 vanilla uses a recursive procedure to generate
+ "&&" and "||" expressions for testing the lookahead. As each
+ layer of the predicate tree is exposed a new set of "&&" and
+ "||" expressions on the lookahead are generated. In many
+ cases the lookahead being tested has already been tested.
+
+ With -mrhoist a lookahead tree is computed for the entire
+ lookahead expression. This means that predicates with identical
+ context or context which is a subset of another predicate's
+ context disappear.
+
+ This is especially important for predicates formed by rules
+ like the following:
+
+ uppperCaseVowel : <<isUpperCase(LATEXT(1))>>? vowel;
+ vowel: : <<isVowel(LATEXT(1))>>? LETTERS;
+
+ These predicates are combined using AND since both must be
+ satisfied for rule upperCaseVowel. They have identical
+ context which makes this optimization very effective.
+
+ The affect of Items #100a and #100b together can be dramatic. In
+ a very large (but real world) grammar one particular predicate
+ expression was reduced from an (unreadable) 50 predicate leaves,
+ 195 LA(1) terms, and 5500 characters to an (easily comprehensible)
+ 3 predicate leaves (all different) and a *single* LA(1) term.
+
+#99. (Changed in 1.33MR10) Code generation for expression trees
+
+ Expression trees are used for k>1 grammars and predicates with
+ lookahead depth >1. This optimization must be enabled using
+ "-mrhoist on". (Clarification added for 1.33MR11).
+
+ In the processing of expression trees, antlr can generate long chains
+ of token comparisons. Prior to 1.33MR10 there were many redundant
+ parenthesis which caused problems for compilers which could handle
+ expressions of only limited complexity. For example, to test an
+ expression tree (root R A B C D), antlr would generate something
+ resembling:
+
+ (LA(1)==R && (LA(2)==A || (LA(2)==B || (LA(2)==C || LA(2)==D)))))
+
+ If there were twenty tokens to test then there would be twenty
+ parenthesis at the end of the expression.
+
+ In 1.33MR10 the generated code for tree expressions resembles:
+
+ (LA(1)==R && (LA(2)==A || LA(2)==B || LA(2)==C || LA(2)==D))
+
+ For "complex" expressions the output is indented to reflect the LA
+ number being tested:
+
+ (LA(1)==R
+ && (LA(2)==A || LA(2)==B || LA(2)==C || LA(2)==D
+ || LA(2)==E || LA(2)==F)
+ || LA(1)==S
+ && (LA(2)==G || LA(2)==H))
+
+
+ Suggested by S. Bochnak (S.Bochnak@@microTool.com.pl),
+
+#98. (Changed in 1.33MR10) Option "-info p"
+
+ When the user selects option "-info p" the program will generate
+ detailed information about predicates. If the user selects
+ "-mrhoist on" additional detail will be provided explaining
+ the promotion and suppression of predicates. The output is part
+ of the generated file and sandwiched between #if 0/#endif statements.
+
+ Consider the following k=1 grammar:
+
+ start : ( all ) * ;
+
+ all : ( a
+ | b
+ )
+ ;
+
+ a : c B
+ ;
+
+ c : <<LATEXT(1)>>?
+ | B
+ ;
+
+ b : <<LATEXT(1)>>? X
+ ;
+
+ Below is an excerpt of the output for rule "start" for the three
+ predicate options (off, on, and maintenance release style hoisting).
+
+ For those who do not wish to use the "-mrhoist on" option for code
+ generation the option can be used in a "diagnostic" mode to provide
+ valuable information:
+
+ a. where one should insert null actions to inhibit hoisting
+ b. a chain of rule references which shows where predicates are
+ being hoisted
+
+ ======================================================================
+ Example of "-info p" with "-mrhoist on"
+ ======================================================================
+ #if 0
+
+ Hoisting of predicate suppressed by alternative without predicate.
+ The alt without the predicate includes all cases where the
+ predicate is false.
+
+ WITH predicate: line 11 v36.g
+ WITHOUT predicate: line 12 v36.g
+
+ The context set for the predicate:
+
+ B
+
+ The lookahead set for alt WITHOUT the semantic predicate:
+
+ B
+
+ The predicate:
+
+ pred << LATEXT(1)>>? depth=k=1 rule c line 11 v36.g
+
+ set context:
+ B
+ tree context: null
+
+ Chain of referenced rules:
+
+ #0 in rule start (line 1 v36.g) to rule all
+ #1 in rule all (line 3 v36.g) to rule a
+ #2 in rule a (line 8 v36.g) to rule c
+ #3 in rule c (line 11 v36.g)
+
+ #endif
+ &&
+ #if 0
+
+ pred << LATEXT(1)>>? depth=k=1 rule b line 15 v36.g
+
+ set context:
+ X
+ tree context: null
+
+ #endif
+ ======================================================================
+ Example of "-info p" with the default -prc setting ( "-prc off")
+ ======================================================================
+ #if 0
+
+ OR
+ pred << LATEXT(1)>>? depth=k=1 rule c line 11 v36.g
+
+ set context:
+ nil
+ tree context: null
+
+ pred << LATEXT(1)>>? depth=k=1 rule b line 15 v36.g
+
+ set context:
+ nil
+ tree context: null
+
+ #endif
+ ======================================================================
+ Example of "-info p" with "-prc on" and "-mrhoist off"
+ ======================================================================
+ #if 0
+
+ OR
+ pred << LATEXT(1)>>? depth=k=1 rule c line 11 v36.g
+
+ set context:
+ B
+ tree context: null
+
+ pred << LATEXT(1)>>? depth=k=1 rule b line 15 v36.g
+
+ set context:
+ X
+ tree context: null
+
+ #endif
+ ======================================================================
+
+#97. (Fixed in 1.33MR10) "Predicate applied for more than one ... "
+
+ In 1.33 vanilla, the grammar listed below produced this message for
+ the first alternative (only) of rule "b":
+
+ warning: predicate applied for >1 lookahead 1-sequences
+ [you may only want one lookahead 1-sequence to apply.
+ Try using a context guard '(...)? =>'
+
+ In 1.33MR10 the message is issued for both alternatives.
+
+ top : (a)*;
+ a : b | c ;
+
+ b : <<PPP(LATEXT(1))>>? ( AAA | BBB )
+ | <<QQQ(LATEXT(1))>>? ( XXX | YYY )
+ ;
+
+ c : AAA | XXX;
+
+#96. (Fixed in 1.33MR10) Guard predicates ignored when -prc off
+
+ Prior to 1.33MR10, guard predicate code was not generated unless
+ "-prc on" was selected.
+
+ This was incorrect, since "-prc off" (the default) is supposed to
+ disable only AUTOMATIC computation of predicate context, not the
+ programmer specified context supplied by guard predicates.
+
+#95. (Fixed in 1.33MR10) Predicate guard context length was k, not max(k,ck)
+
+ Prior to 1.33MR10, predicate guards were computed to k tokens rather
+ than max(k,ck). Consider the following grammar:
+
+ a : ( A B C)? => <<AAA(LATEXT(1))>>? (A|X) (B|Y) (C|Z) ;
+
+ The code generated by 1.33 vanilla with "-k 1 -ck 3 -prc on"
+ for the predicate in "a" resembles:
+
+ if ( (! LA(1)==A) || AAA(LATEXT(1))) {...
+
+ With 1.33MR10 and the same options the code resembles:
+
+ if ( (! (LA(1)==A && LA(2)==B && LA(3)==C) || AAA(LATEXT(1))) {...
+
+#94. (Fixed in 1.33MR10) Predicates followed by rule references
+
+ Prior to 1.33MR10, a semantic predicate which referenced a token
+ which was off the end of the rule caused an incomplete context
+ to be computed (with "-prc on") for the predicate under some circum-
+ stances. In some cases this manifested itself as illegal C code
+ (e.g. "LA(2)==[Ep](1)" in the k=2 examples below:
+
+ all : ( a ) *;
+
+ a : <<AAA(LATEXT(2))>>? ID X
+ | <<BBB(LATEXT(2))>>? Y
+ | Z
+ ;
+
+ This might also occur when the semantic predicate was followed
+ by a rule reference which was shorter than the length of the
+ semantic predicate:
+
+ all : ( a ) *;
+
+ a : <<AAA(LATEXT(2))>>? ID X
+ | <<BBB(LATEXT(2))>>? y
+ | Z
+ ;
+
+ y : Y ;
+
+ Depending on circumstance, the resulting context might be too
+ generous because it was too short, or too restrictive because
+ of missing alternatives.
+
+#93. (Changed in 1.33MR10) Definition of Purify macro
+
+ Ofer Ben-Ami (gremlin@cs.huji.ac.il) has supplied a definition
+ for the Purify macro:
+
+ #define PURIFY(r, s) memset((char *) &(r), '\0', (s));
+
+ Note: This may not be the right thing to do for C++ objects that
+ have constructors. Reported by Bonny Rais (bonny@werple.net.au).
+
+ For those cases one should #define PURIFY to an empty macro in the
+ #header or #first actions.
+
+#92. (Fixed in 1.33MR10) Guarded predicates and hoisting
+
+ When a guarded predicate participates in hoisting it is linked into
+ a predicate expression tree. Prior to 1.33MR10 this link was never
+ cleared and the next time the guard was used to construct a new
+ tree the link could contain a spurious reference to another element
+ which had previosly been joined to it in the semantic predicate tree.
+
+ For example:
+
+ start : ( all ) *;
+ all : ( a | b ) ;
+
+ start2 : ( all2 ) *;
+ all2 : ( a ) ;
+
+ a : (A)? => <<AAA(LATEXT(1))>>? A ;
+ b : (B)? => <<BBB(LATEXT(1))>>? B ;
+
+ Prior to 1.33MR10 the code for "start2" would include a spurious
+ reference to the BBB predicate which was left from constructing
+ the predicate tree for rule "start" (i.e. or(AAA,BBB) ).
+
+ In 1.33MR10 this problem is avoided by cloning the original guard
+ each time it is linked into a predicate tree.
+
+#91. (Changed in 1.33MR10) Extensive changes to semantic pred hoisting
+
+ ============================================
+ This has been rendered obsolete by Item #117
+ ============================================
+
+#90. (Fixed in 1.33MR10) Semantic pred with LT(i) and i>max(k,ck)
+
+ There is a bug in antlr 1.33 vanilla and all maintenance releases
+ prior to 1.33MR10 which allows semantic predicates to reference
+ an LT(i) or LATEXT(i) where i is larger than max(k,ck). When
+ this occurs antlr will attempt to mark the ith element of an array
+ in which there are only max(k,ck) elements. The result cannot
+ be predicted.
+
+ Using LT(i) or LATEXT(i) for i>max(k,ck) is reported as an error
+ in 1.33MR10.
+
+#89. Rescinded
+
+#88. (Fixed in 1.33MR10) Tokens used in semantic predicates in guess mode
+
+ Consider the behavior of a semantic predicate during guess mode:
+
+ rule : a:A (
+ <<test($a)>>? b:B
+ | c:C
+ );
+
+ Prior to MR10 the assignment of the token or attribute to
+ $a did not occur during guess mode, which would cause the
+ semantic predicate to misbehave because $a would be null.
+
+ In 1.33MR10 a semantic predicate with a reference to an
+ element label (such as $a) forces the assignment to take
+ place even in guess mode.
+
+ In order to work, this fix REQUIRES use of the $label format
+ for token pointers and attributes referenced in semantic
+ predicates.
+
+ The fix does not apply to semantic predicates using the
+ numeric form to refer to attributes (e.g. <<test($1)>>?).
+ The user will receive a warning for this case.
+
+ Reported by Rob Trout (trout@mcs.cs.kent.edu).
+
+#87. (Fixed in 1.33MR10) Malformed guard predicates
+
+ Context guard predicates may contain only references to
+ tokens. They may not contain references to (...)+ and
+ (...)* blocks. This is now checked. This replaces the
+ fatal error message in item #78 with an appropriate
+ (non-fatal) error messge.
+
+ In theory, context guards should be allowed to reference
+ rules. However, I have not had time to fix this.
+ Evaluation of the guard takes place before all rules have
+ been read, making it difficult to resolve a forward reference
+ to rule "zzz" - it hasn't been read yet ! To postpone evaluation
+ of the guard until all rules have been read is too much
+ for the moment.
+
+#86. (Fixed in 1.33MR10) Unequal set size in set_sub
+
+ Routine set_sub() in pccts/support/set/set.h did not work
+ correctly when the sets were of unequal sizes. Rewrote
+ set_equ to make it simpler and remove unnecessary and
+ expensive calls to set_deg(). This routine was not used
+ in 1.33 vanila.
+
+#85. (Changed in 1.33MR10) Allow redefinition of MaxNumFiles
+
+ Raised the maximum number of input files to 99 from 20.
+ Put a #ifndef/#endif around the "#define MaxNumFiles 99".
+
+#84. (Fixed in 1.33MR10) Initialize zzBadTok in macro zzRULE
+
+ Initialize zzBadTok to NULL in zzRULE macro of AParser.h.
+ in order to get rid of warning messages.
+
+#83. (Fixed in 1.33MR10) False warnings with -w2 for #tokclass
+
+ When -w2 is selected antlr gives inappropriate warnings about
+ #tokclass names not having any associated regular expressions.
+ Since a #tokclass is not a "real" token it will never have an
+ associated regular expression and there should be no warning.
+
+ Reported by Derek Pappas (derek.pappas@eng.sun.com)
+
+#82. (Fixed in 1.33MR10) Computation of follow sets with multiple cycles
+
+ Reinier van den Born (reinier@vnet.ibm.com) reported a problem
+ in the computation of follow sets by antlr. The problem (bug)
+ exists in 1.33 vanilla and all maintenance releases prior to 1.33MR10.
+
+ The problem involves the computation of follow sets when there are
+ cycles - rules which have mutual references. I believe the problem
+ is restricted to cases where there is more than one cycle AND
+ elements of those cycles have rules in common. Even when this
+ occurs it may not affect the code generated - but it might. It
+ might also lead to undetected ambiguities.
+
+ There were no changes in antlr or dlg output from the revised version.
+
+ The following fragment demonstates the problem by giving different
+ follow sets (option -pa) for var_access when built with k=1 and ck=2 on
+ 1.33 vanilla and 1.33MR10:
+
+ echo_statement : ECHO ( echo_expr )*
+ ;
+
+ echo_expr : ( command )?
+ | expression
+ ;
+
+ command : IDENTIFIER
+ { concat }
+ ;
+
+ expression : operand ( OPERATOR operand )*
+ ;
+
+ operand : value
+ | START command END
+ ;
+
+ value : concat
+ | TYPE operand
+ ;
+
+ concat : var_access { CONCAT value }
+ ;
+
+ var_access : IDENTIFIER { INDEX }
+
+ ;
+#81. (Changed in 1.33MR10) C mode use of attributes and ASTs
+
+ Reported by Isaac Clark (irclark@mindspring.com).
+
+ C mode code ignores attributes returned by rules which are
+ referenced using element labels when ASTs are enabled (-gt option).
+
+ 1. start : r:rule t:Token <<$start=$r;>>
+
+ The $r refrence will not work when combined with
+ the -gt option.
+
+ 2. start : t:Token <<$start=$t;>>
+
+ The $t reference works in all cases.
+
+ 3. start : rule <<$0=$1;>>
+
+ Numeric labels work in all cases.
+
+ With MR10 the user will receive an error message for case 1 when
+ the -gt option is used.
+
+#80. (Fixed in 1.33MR10) (...)? as last alternative of block
+
+ A construct like the following:
+
+ rule : a
+ | (b)?
+ ;
+
+ does not make sense because there is no alternative when
+ the guess block fails. This is now reported as a warning
+ to the user.
+
+ Previously, there was a code generation error for this case:
+ the guess block was not "closed" when the guess failed.
+ This could cause an infinite loop or other problems. This
+ is now fixed.
+
+ Example problem:
+
+ #header<<
+ #include <stdio.h>
+ #include "charptr.h"
+ >>
+
+ <<
+ #include "charptr.c"
+ main ()
+ {
+ ANTLR(start(),stdin);
+ }
+ >>
+
+ #token "[\ \t]+" << zzskip(); >>
+ #token "[\n]" << zzline++; zzskip(); >>
+
+ #token Word "[a-z]+"
+ #token Number "[0-9]+"
+
+
+ start : (test1)?
+ | (test2)?
+ ;
+ test1 : (Word Word Word Word)?
+ | (Word Word Word Number)?
+ ;
+ test2 : (Word Word Number Word)?
+ | (Word Word Number Number)?
+ ;
+
+ Test data which caused infinite loop:
+
+ a 1 a a
+
+#79. (Changed in 1.33MR10) Use of -fh with multiple parsers
+
+ Previously, antlr always used the pre-processor symbol
+ STDPCCTS_H as a gate for the file stdpccts.h. This
+ caused problems when there were multiple parsers defined
+ because they used the same gate symbol.
+
+ In 1.33MR10, the -fh filename is used to generate the
+ gate file for stdpccts.h. For instance:
+
+ antlr -fh std_parser1.h
+
+ generates the pre-processor symbol "STDPCCTS_std_parser1_H".
+
+ Reported by Ramanathan Santhanam (ps@kumaran.com).
+
+#78. (Changed in 1.33MR9) Guard predicates that refer to rules
+
+ ------------------------
+ Please refer to Item #87
+ ------------------------
+
+ Guard predicates are processed during an early phase
+ of antlr (during parsing) before all data structures
+ are completed.
+
+ There is an apparent bug in earlier versions of 1.33
+ which caused guard predicates which contained references
+ to rules (rather than tokens) to reference a structure
+ which hadn't yet been initialized.
+
+ In some cases (perhaps all cases) references to rules
+ in guard predicates resulted in the use of "garbage".
+
+#79. (Changed in 1.33MR9) Jeff Vincent (JVincent@novell.com)
+
+ Previously, the maximum length file name was set
+ arbitrarily to 300 characters in antlr, dlg, and sorcerer.
+
+ The config.h file now attempts to define the maximum length
+ filename using _MAX_PATH from stdlib.h before falling back
+ to using the value 300.
+
+#78. (Changed in 1.33MR9) Jeff Vincent (JVincent@novell.com)
+
+ Put #ifndef/#endif around definition of ZZLEXBUFSIZE in
+ antlr.
+
+#77. (Changed in 1.33MR9) Arithmetic overflow for very large grammars
+
+ In routine HandleAmbiguities() antlr attempts to compute the
+ number of possible elements in a set that is order of
+ number-of-tokens raised to the number-of-lookahead-tokens power.
+ For large grammars or large lookahead (e.g. -ck 7) this can
+ cause arithmetic overflow.
+
+ With 1.33MR9, arithmetic overflow in this computation is reported
+ the first time it happens. The program continues to run and
+ the program branches based on the assumption that the computed
+ value is larger than any number computed by counting actual cases
+ because 2**31 is larger than the number of bits in most computers.
+
+ Before 1.33MR9 overflow was not reported. The behavior following
+ overflow is not predictable by anyone but the original author.
+
+ NOTE
+
+ In 1.33MR10 the warning message is suppressed.
+ The code which detects the overflow allows the
+ computation to continue without an error. The
+ error message itself made made users worry.
+
+#76. (Changed in 1.33MR9) Jeff Vincent (JVincent@novell.com)
+
+ Jeff Vincent has convinced me to make ANTLRCommonToken and
+ ANTLRCommonNoRefCountToken use variable length strings
+ allocated from the heap rather than fixed length strings.
+ By suitable definition of setText(), the copy constructor,
+ and operator =() it is possible to maintain "copy" semantics.
+ By "copy" semantics I mean that when a token is copied from
+ an existing token it receives its own, distinct, copy of the
+ text allocated from the heap rather than simply a pointer
+ to the original token's text.
+
+ ============================================================
+ W * A * R * N * I * N * G
+ ============================================================
+
+ It is possible that this may cause problems for some users.
+ For those users I have included the old version of AToken.h as
+ pccts/h/AToken_traditional.h.
+
+#75. (Changed in 1.33MR9) Bruce Guenter (bruceg@qcc.sk.ca)
+
+ Make DLGStringInput const correct. Since this is infrequently
+ subclassed, it should affect few users, I hope.
+
+#74. (Changed in 1.33MR9) -o (output directory) option
+
+ Antlr does not properly handle the -o output directory option
+ when the filename of the grammar contains a directory part. For
+ example:
+
+ antlr -o outdir pccts_src/myfile.g
+
+ causes antlr create a file called "outdir/pccts_src/myfile.cpp.
+ It SHOULD create outdir/myfile.cpp
+
+ The suggested code fix has been installed in antlr, dlg, and
+ Sorcerer.
+
+#73. (Changed in 1.33MR9) Hoisting of semantic predicates and -mrhoist
+
+ ============================================
+ This has been rendered obsolete by Item #117
+ ============================================
+
+#72. (Changed in 1.33MR9) virtual saveState()/restoreState()/guess_XXX
+
+ The following methods in ANTLRParser were made virtual at
+ the request of S. Bochnak (S.Bochnak@microTool.com.pl):
+
+ saveState() and restoreState()
+ guess(), guess_fail(), and guess_done()
+
+#71. (Changed in 1.33MR9) Access to omitted command line argument
+
+ If a switch requiring arguments is the last thing on the
+ command line, and the argument is omitted, antlr would core.
+
+ antlr test.g -prc
+
+ instead of
+
+ antlr test.g -prc off
+
+#70. (Changed in 1.33MR9) Addition of MSVC .dsp and .mak build files
+
+ The following MSVC .dsp and .mak files for pccts and sorcerer
+ were contributed by Stanislaw Bochnak (S.Bochnak@microTool.com.pl)
+ and Jeff Vincent (JVincent@novell.com)
+
+ PCCTS Distribution Kit
+ ----------------------
+ pccts/PCCTSMSVC50.dsw
+
+ pccts/antlr/AntlrMSVC50.dsp
+ pccts/antlr/AntlrMSVC50.mak
+
+ pccts/dlg/DlgMSVC50.dsp
+ pccts/dlg/DlgMSVC50.mak
+
+ pccts/support/msvc.dsp
+
+ Sorcerer Distribution Kit
+ -------------------------
+ pccts/sorcerer/SorcererMSVC50.dsp
+ pccts/sorcerer/SorcererMSVC50.mak
+
+ pccts/sorcerer/lib/msvc.dsp
+
+#69. (Changed in 1.33MR9) Change "unsigned int" to plain "int"
+
+ Declaration of max_token_num in misc.c as "unsigned int"
+ caused comparison between signed and unsigned ints giving
+ warning message without any special benefit.
+
+#68. (Changed in 1.33MR9) Add void return for dlg internal_error()
+
+ Get rid of "no return value" message in internal_error()
+ in file dlg/support.c and dlg/dlg.h.
+
+#67. (Changed in Sor) sor.g: lisp() has no return value
+
+ Added a "void" for the return type.
+
+#66. (Added to Sor) sor.g: ZZLEXBUFSIZE enclosed in #ifndef/#endif
+
+ A user needed to be able to change the ZZLEXBUFSIZE for
+ sor. Put the definition of ZZLEXBUFSIZE inside #ifndef/#endif
+
+#65. (Changed in 1.33MR9) PCCTSAST::deepCopy() and ast_dup() bug
+
+ Jeff Vincent (JVincent@novell.com) found that deepCopy()
+ made new copies of only the direct descendents. No new
+ copies were made of sibling nodes, Sibling pointers are
+ set to zero by shallowCopy().
+
+ PCCTS_AST::deepCopy() has been changed to make a
+ deep copy in the traditional sense.
+
+ The deepCopy() routine depends on the behavior of
+ shallowCopy(). In all sor examples I've found,
+ shallowCopy() zeroes the right and down pointers.
+
+ Original Tree Original deepCopy() Revised deepCopy
+ ------------- ------------------- ----------------
+ a->b->c A A
+ | | |
+ d->e->f D D->E->F
+ | | |
+ g->h->i G G->H->I
+ | |
+ j->k J->K
+
+ While comparing deepCopy() for C++ mode with ast_dup for
+ C mode I found a problem with ast_dup().
+
+ Routine ast_dup() has been changed to make a deep copy
+ in the traditional sense.
+
+ Original Tree Original ast_dup() Revised ast_dup()
+ ------------- ------------------- ----------------
+ a->b->c A->B->C A
+ | | |
+ d->e->f D->E->F D->E->F
+ | | |
+ g->h->i G->H->I G->H->I
+ | | |
+ j->k J->K J->K
+
+
+ I believe this affects transform mode sorcerer programs only.
+
+#64. (Changed in 1.33MR9) anltr/hash.h prototype for killHashTable()
+
+#63. (Changed in 1.33MR8) h/charptr.h does not zero pointer after free
+
+ The charptr.h routine now zeroes the pointer after free().
+
+ Reported by Jens Tingleff (jensting@imaginet.fr)
+
+#62. (Changed in 1.33MR8) ANTLRParser::resynch had static variable
+
+ The static variable "consumed" in ANTLRParser::resynch was
+ changed into an instance variable of the class with the
+ name "resynchConsumed".
+
+ Reported by S.Bochnak@microTool.com.pl
+
+#61. (Changed in 1.33MR8) Using rule>[i,j] when rule has no return values
+
+ Previously, the following code would cause antlr to core when
+ it tried to generate code for rule1 because rule2 had no return
+ values ("upward inheritance"):
+
+ rule1 : <<int i; int j>>
+ rule2 > [i,j]
+ ;
+
+ rule2 : Anything ;
+
+ Reported by S.Bochnak@microTool.com.pl
+
+ Verified correct operation of antlr MR8 when missing or extra
+ inheritance arguments for all combinations. When there are
+ missing or extra arguments code will still be generated even
+ though this might cause the invocation of a subroutine with
+ the wrong number of arguments.
+
+#60. (Changed in 1.33MR7) Major changes to exception handling
+
+ There were significant problems in the handling of exceptions
+ in 1.33 vanilla. The general problem is that it can only
+ process one level of exception handler. For example, a named
+ exception handler, an exception handler for an alternative, or
+ an exception for a subrule always went to the rule's exception
+ handler if there was no "catch" which matched the exception.
+
+ In 1.33MR7 the exception handlers properly "nest". If an
+ exception handler does not have a matching "catch" then the
+ nextmost outer exception handler is checked for an appropriate
+ "catch" clause, and so on until an exception handler with an
+ appropriate "catch" is found.
+
+ There are still undesirable features in the way exception
+ handlers are implemented, but I do not have time to fix them
+ at the moment:
+
+ The exception handlers for alternatives are outside the
+ block containing the alternative. This makes it impossible
+ to access variables declared in a block or to resume the
+ parse by "falling through". The parse can still be easily
+ resumed in other ways, but not in the most natural fashion.
+
+ This results in an inconsistentcy between named exception
+ handlers and exception handlers for alternatives. When
+ an exception handler for an alternative "falls through"
+ it goes to the nextmost outer handler - not the "normal
+ action".
+
+ A major difference between 1.33MR7 and 1.33 vanilla is
+ the default action after an exception is caught:
+
+ 1.33 Vanilla
+ ------------
+ In 1.33 vanilla the signal value is set to zero ("NoSignal")
+ and the code drops through to the code following the exception.
+ For named exception handlers this is the "normal action".
+ For alternative exception handlers this is the rule's handler.
+
+ 1.33MR7
+ -------
+ In 1.33MR7 the signal value is NOT automatically set to zero.
+
+ There are two cases:
+
+ For named exception handlers: if the signal value has been
+ set to zero the code drops through to the "normal action".
+
+ For all other cases the code branches to the nextmost outer
+ exception handler until it reaches the handler for the rule.
+
+ The following macros have been defined for convenience:
+
+ C/C++ Mode Name
+ --------------------
+ (zz)suppressSignal
+ set signal & return signal arg to 0 ("NoSignal")
+ (zz)setSignal(intValue)
+ set signal & return signal arg to some value
+ (zz)exportSignal
+ copy the signal value to the return signal arg
+
+ I'm not sure why PCCTS make a distinction between the local
+ signal value and the return signal argument, but I'm loathe
+ to change the code. The burden of copying the local signal
+ value to the return signal argument can be given to the
+ default signal handler, I suppose.
+
+#59. (Changed in 1.33MR7) Prototypes for some functions
+
+ Added prototypes for the following functions to antlr.h
+
+ zzconsumeUntil()
+ zzconsumeUntilToken()
+
+#58. (Changed in 1.33MR7) Added defintion of zzbufsize to dlgauto.h
+
+#57. (Changed in 1.33MR7) Format of #line directive
+
+ Previously, the -gl directive for line 1234 would
+ resemble: "# 1234 filename.g". This caused problems
+ for some compilers/pre-processors. In MR7 it generates
+ "#line 1234 filename.g".
+
+#56. (Added in 1.33MR7) Jan Mikkelsen <janm@zeta.org.au>
+
+ Move PURIFY macro invocaton to after rule's init action.
+
+#55. (Fixed in 1.33MR7) Unitialized variables in ANTLRParser
+
+ Member variables inf_labase and inf_last were not initialized.
+ (See item #50.)
+
+#54. (Fixed in 1.33MR6) Brad Schick (schick@interacess.com)
+
+ Previously, the following constructs generated the same
+ code:
+
+ rule1 : (A B C)?
+ | something-else
+ ;
+
+ rule2 : (A B C)? ()
+ | something-else
+ ;
+
+ In all versions of pccts rule1 guesses (A B C) and then
+ consume all three tokens if the guess succeeds. In MR6
+ rule2 guesses (A B C) but consumes NONE of the tokens
+ when the guess succeeds because "()" matches epsilon.
+
+#53. (Explanation for 1.33MR6) What happens after an exception is caught ?
+
+ The Book is silent about what happens after an exception
+ is caught.
+
+ The following code fragment prints "Error Action" followed
+ by "Normal Action".
+
+ test : Word ex:Number <<printf("Normal Action\n");>>
+ exception[ex]
+ catch NoViableAlt:
+ <<printf("Error Action\n");>>
+ ;
+
+ The reason for "Normal Action" is that the normal flow of the
+ program after a user-written exception handler is to "drop through".
+ In the case of an exception handler for a rule this results in
+ the exection of a "return" statement. In the case of an
+ exception handler attached to an alternative, rule, or token
+ this is the code that would have executed had there been no
+ exception.
+
+ The user can achieve the desired result by using a "return"
+ statement.
+
+ test : Word ex:Number <<printf("Normal Action\n");>>
+ exception[ex]
+ catch NoViableAlt:
+ <<printf("Error Action\n"); return;>>
+ ;
+
+ The most powerful mechanism for recovery from parse errors
+ in pccts is syntactic predicates because they provide
+ backtracking. Exceptions allow "return", "break",
+ "consumeUntil(...)", "goto _handler", "goto _fail", and
+ changing the _signal value.
+
+#52. (Fixed in 1.33MR6) Exceptions without syntactic predicates
+
+ The following generates bad code in 1.33 if no syntactic
+ predicates are present in the grammar.
+
+ test : Word ex:Number <<printf("Normal Action\n");>>
+ exception[ex]
+ catch NoViableAlt:
+ <<printf("Error Action\n");>>
+
+ There is a reference to a guess variable. In C mode
+ this causes a compiler error. In C++ mode it generates
+ an extraneous check on member "guessing".
+
+ In MR6 correct code is generated for both C and C++ mode.
+
+#51. (Added to 1.33MR6) Exception operator "@" used without exceptions
+
+ In MR6 added a warning when the exception operator "@" is
+ used and no exception group is defined. This is probably
+ a case where "\@" or "@" is meant.
+
+#50. (Fixed in 1.33MR6) Gunnar Rxnning (gunnar@candleweb.no)
+ http://www.candleweb.no/~gunnar/
+
+ Routines zzsave_antlr_state and zzrestore_antlr_state don't
+ save and restore all the data needed when switching states.
+
+ Suggested patch applied to antlr.h and err.h for MR6.
+
+#49. (Fixed in 1.33MR6) Sinan Karasu (sinan@boeing.com)
+
+ Generated code failed to turn off guess mode when leaving a
+ (...)+ block which contained a guess block. The result was
+ an infinite loop. For example:
+
+ rule : (
+ (x)?
+ | y
+ )+
+
+ Suggested code fix implemented in MR6. Replaced
+
+ ... else if (zzcnt>1) break;
+
+ with:
+
+ C++ mode:
+ ... else if (zzcnt>1) {if (!zzrv) zzGUESS_DONE; break;};
+ C mode:
+ ... else if (zzcnt>1) {if (zzguessing) zzGUESS_DONE; break;};
+
+#48. (Fixed in 1.33MR6) Invalid exception element causes core
+
+ A label attached to an invalid construct can cause
+ pccts to crash while processing the exception associated
+ with the label. For example:
+
+ rule : t:(B C)
+ exception[t] catch MismatchedToken: <<printf(...);>>
+
+ Version MR6 generates the message:
+
+ reference in exception handler to undefined label 't'
+
+#47. (Fixed in 1.33MR6) Manuel Ornato
+
+ Under some circumstances involving a k >1 or ck >1
+ grammar and a loop block (i.e. (...)* ) pccts will
+ fail to detect a syntax error and loop indefinitely.
+ The problem did not exist in 1.20, but has existed
+ from 1.23 to the present.
+
+ Fixed in MR6.
+
+ ---------------------------------------------------
+ Complete test program
+ ---------------------------------------------------
+ #header<<
+ #include <stdio.h>
+ #include "charptr.h"
+ >>
+
+ <<
+ #include "charptr.c"
+ main ()
+ {
+ ANTLR(global(),stdin);
+ }
+ >>
+
+ #token "[\ \t]+" << zzskip(); >>
+ #token "[\n]" << zzline++; zzskip(); >>
+
+ #token B "b"
+ #token C "c"
+ #token D "d"
+ #token E "e"
+ #token LP "\("
+ #token RP "\)"
+
+ #token ANTLREOF "@"
+
+ global : (
+ (E liste)
+ | liste
+ | listed
+ ) ANTLREOF
+ ;
+
+ listeb : LP ( B ( B | C )* ) RP ;
+ listec : LP ( C ( B | C )* ) RP ;
+ listed : LP ( D ( B | C )* ) RP ;
+ liste : ( listeb | listec )* ;
+
+ ---------------------------------------------------
+ Sample data causing infinite loop
+ ---------------------------------------------------
+ e (d c)
+ ---------------------------------------------------
+
+#46. (Fixed in 1.33MR6) Robert Richter
+ (Robert.Richter@infotech.tu-chemnitz.de)
+
+ This item from the list of known problems was
+ fixed by item #18 (below).
+
+#45. (Fixed in 1.33MR6) Brad Schick (schick@interaccess.com)
+
+ The dependency scanner in VC++ mistakenly sees a
+ reference to an MPW #include file even though properly
+ #ifdef/#endif in config.h. The suggested workaround
+ has been implemented:
+
+ #ifdef MPW
+ .....
+ #define MPW_CursorCtl_Header <CursorCtl.h>
+ #include MPW_CursorCtl_Header
+ .....
+ #endif
+
+#44. (Fixed in 1.33MR6) cast malloc() to (char *) in charptr.c
+
+ Added (char *) cast for systems where malloc returns "void *".
+
+#43. (Added to 1.33MR6) Bruce Guenter (bruceg@qcc.sk.ca)
+
+ Add setLeft() and setUp methods to ASTDoublyLinkedBase
+ for symmetry with setRight() and setDown() methods.
+
+#42. (Fixed in 1.33MR6) Jeff Katcher (jkatcher@nortel.ca)
+
+ C++ style comment in antlr.c corrected.
+
+#41. (Added in 1.33MR6) antlr -stdout
+
+ Using "antlr -stdout ..." forces the text that would
+ normally go to the grammar.c or grammar.cpp file to
+ stdout.
+
+#40. (Added in 1.33MR6) antlr -tab to change tab stops
+
+ Using "antlr -tab number ..." changes the tab stops
+ for the grammar.c or grammar.cpp file. The number
+ must be between 0 and 8. Using 0 gives tab characters,
+ values between 1 and 8 give the appropriate number of
+ space characters.
+
+#39. (Fixed in 1.33MR5) Jan Mikkelsen <janm@zeta.org.au>
+
+ Commas in function prototype still not correct under
+ some circumstances. Suggested code fix installed.
+
+#38. (Fixed in 1.33MR5) ANTLRTokenBuffer constructor
+
+ Have ANTLRTokenBuffer ctor initialize member "parser" to null.
+
+#37. (Fixed in 1.33MR4) Bruce Guenter (bruceg@qcc.sk.ca)
+
+ In ANTLRParser::FAIL(int k,...) released memory pointed to by
+ f[i] (as well as f itself. Should only free f itself.
+
+#36. (Fixed in 1.33MR3) Cortland D. Starrett (cort@shay.ecn.purdue.edu)
+
+ Neglected to properly declare isDLGmaxToken() when fixing problem
+ reported by Andreas Magnusson.
+
+ Undo "_retv=NULL;" change which caused problems for return values
+ from rules whose return values weren't pointers.
+
+ Failed to create bin directory if it didn't exist.
+
+#35. (Fixed in 1.33MR2) Andreas Magnusson
+(Andreas.Magnusson@mailbox.swipnet.se)
+
+ Repair bug introduced by 1.33MR1 for #tokdefs. The original fix
+ placed "DLGmaxToken=9999" and "DLGminToken=0" in the TokenType enum
+ in order to fix a problem with an aggresive compiler assigning an 8
+ bit enum which might be too narrow. This caused #tokdefs to assume
+ that there were 9999 real tokens. The repair to the fix causes antlr to
+ ignore TokenTypes "DLGmaxToken" and "DLGminToken" in a #tokdefs file.
+
+#34. (Added to 1.33MR1) Add public DLGLexerBase::set_line(int newValue)
+
+ Previously there was no public function for changing the line
+ number maintained by the lexer.
+
+#33. (Fixed in 1.33MR1) Franklin Chen (chen@adi.com)
+
+ Accidental use of EXIT_FAILURE rather than PCCTS_EXIT_FAILURE
+ in pccts/h/AParser.cpp.
+
+#32. (Fixed in 1.33MR1) Franklin Chen (chen@adi.com)
+
+ In PCCTSAST.cpp lines 405 and 466: Change
+
+ free (t)
+ to
+ free ( (char *)t );
+
+ to match prototype.
+
+#31. (Added to 1.33MR1) Pointer to parser in ANTLRTokenBuffer
+ Pointer to parser in DLGLexerBase
+
+ The ANTLRTokenBuffer class now contains a pointer to the
+ parser which is using it. This is established by the
+ ANTLRParser constructor calling ANTLRTokenBuffer::
+ setParser(ANTLRParser *p).
+
+ When ANTLRTokenBuffer::setParser(ANTLRParser *p) is
+ called it saves the pointer to the parser and then
+ calls ANTLRTokenStream::setParser(ANTLRParser *p)
+ so that the lexer can also save a pointer to the
+ parser.
+
+ There is also a function getParser() in each class
+ with the obvious purpose.
+
+ It is possible that these functions will return NULL
+ under some circumstances (e.g. a non-DLG lexer is used).
+
+#30. (Added to 1.33MR1) function tokenName(int token) standard
+
+ The generated parser class now includes the
+ function:
+
+ static const ANTLRChar * tokenName(int token)
+
+ which returns a pointer to the "name" corresponding
+ to the token.
+
+ The base class (ANTLRParser) always includes the
+ member function:
+
+ const ANTLRChar * parserTokenName(int token)
+
+ which can be accessed by objects which have a pointer
+ to an ANTLRParser, but do not know the name of the
+ parser class (e.g. ANTLRTokenBuffer and DLGLexerBase).
+
+#29. (Added to 1.33MR1) Debugging DLG lexers
+
+ If the pre-processor symbol DEBUG_LEXER is defined
+ then DLexerBase will include code for printing out
+ key information about tokens which are recognized.
+
+ The debug feature of the lexer is controlled by:
+
+ int previousDebugValue=lexer.debugLexer(newValue);
+
+ a value of 0 disables output
+ a value of 1 enables output
+
+ Even if the lexer debug code is compiled into DLexerBase
+ it must be enabled before any output is generated. For
+ example:
+
+ DLGFileInput in(stdin);
+ MyDLG lexer(&in,2000);
+
+ lexer.setToken(&aToken);
+
+ #if DEBUG_LEXER
+ lexer.debugLexer(1); // enable debug information
+ #endif
+
+#28. (Added to 1.33MR1) More control over DLG header
+
+ Version 1.33MR1 adds the following directives to PCCTS
+ for C++ mode:
+
+ #lexprefix <<source code>>
+
+ Adds source code to the DLGLexer.h file
+ after the #include "DLexerBase.h" but
+ before the start of the class definition.
+
+ #lexmember <<source code>>
+
+ Adds source code to the DLGLexer.h file
+ as part of the DLGLexer class body. It
+ appears immediately after the start of
+ the class and a "public: statement.
+
+#27. (Fixed in 1.33MR1) Comments in DLG actions
+
+ Previously, DLG would not recognize comments as a special case.
+ Thus, ">>" in the comments would cause errors. This is fixed.
+
+#26. (Fixed in 1.33MR1) Removed static variables from error routines
+
+ Previously, the existence of statically allocated variables
+ in some of the parser's member functions posed a danger when
+ there was more than one parser active.
+
+ Replaced with dynamically allocated/freed variables in 1.33MR1.
+
+#25. (Fixed in 1.33MR1) Use of string literals in semantic predicates
+
+ Previously, it was not possible to place a string literal in
+ a semantic predicate because it was not properly "stringized"
+ for the report of a failed predicate.
+
+#24. (Fixed in 1.33MR1) Continuation lines for semantic predicates
+
+ Previously, it was not possible to continue semantic
+ predicates across a line because it was not properly
+ "stringized" for the report of a failed predicate.
+
+ rule : <<ifXYZ()>>?[ a very
+ long statement ]
+
+#23. (Fixed in 1.33MR1) {...} envelope for failed semantic predicates
+
+ Previously, there was a code generation error for failed
+ semantic predicates:
+
+ rule : <<xyz()>>?[ stmt1; stmt2; ]
+
+ which generated code which resembled:
+
+ if (! xyz()) stmt1; stmt2;
+
+ It now puts the statements in a {...} envelope:
+
+ if (! xyz()) { stmt1; stmt2; };
+
+#22. (Fixed in 1.33MR1) Continuation of #token across lines using "\"
+
+ Previously, it was not possible to continue a #token regular
+ expression across a line. The trailing "\" and newline caused
+ a newline to be inserted into the regular expression by DLG.
+
+ Fixed in 1.33MR1.
+
+#21. (Fixed in 1.33MR1) Use of ">>" (right shift operator in DLG actions
+
+ It is now possible to use the C++ right shift operator ">>"
+ in DLG actions by using the normal escapes:
+
+ #token "shift-right" << value=value \>\> 1;>>
+
+#20. (Version 1.33/19-Jan-97 Karl Eccleson <karle@microrobotics.co.uk>
+ P.A. Keller (P.A.Keller@bath.ac.uk)
+
+ There is a problem due to using exceptions with the -gh option.
+
+ Suggested fix now in 1.33MR1.
+
+#19. (Fixed in 1.33MR1) Tom Piscotti and John Lilley
+
+ There were problems suppressing messages to stdin and stdout
+ when running in a window environment because some functions
+ which uses fprint were not virtual.
+
+ Suggested change now in 1.33MR1.
+
+ I believe all functions containing error messages (excluding those
+ indicating internal inconsistency) have been placed in functions
+ which are virtual.
+
+#18. (Version 1.33/ 22-Nov-96) John Bair (jbair@iftime.com)
+
+ Under some combination of options a required "return _retv" is
+ not generated.
+
+ Suggested fix now in 1.33MR1.
+
+#17. (Version 1.33/3-Sep-96) Ron House (house@helios.usq.edu.au)
+
+ The routine ASTBase::predorder_action omits two "tree->"
+ prefixes, which results in the preorder_action belonging
+ to the wrong node to be invoked.
+
+ Suggested fix now in 1.33MR1.
+
+#16. (Version 1.33/7-Jun-96) Eli Sternheim <eli@interhdl.com>
+
+ Routine consumeUntilToken() does not check for end-of-file
+ condition.
+
+ Suggested fix now in 1.33MR1.
+
+#15. (Version 1.33/8 Apr 96) Asgeir Olafsson <olafsson@cstar.ac.com>
+
+ Problem with tree duplication of doubly linked ASTs in ASTBase.cpp.
+
+ Suggested fix now in 1.33MR1.
+
+#14. (Version 1.33/28-Feb-96) Andreas.Magnusson@mailbox.swipnet.se
+
+ Problem with definition of operator = (const ANTLRTokenPtr rhs).
+
+ Suggested fix now in 1.33MR1.
+
+#13. (Version 1.33/13-Feb-96) Franklin Chen (chen@adi.com)
+
+ Sun C++ Compiler 3.0.1 can't compile testcpp/1 due to goto in
+ block with destructors.
+
+ Apparently fixed. Can't locate "goto".
+
+#12. (Version 1.33/10-Nov-95) Minor problems with 1.33 code
+
+ The following items have been fixed in 1.33MR1:
+
+ 1. pccts/antlr/main.c line 142
+
+ "void" appears in classic C code
+
+ 2. no makefile in support/genmk
+
+ 3. EXIT_FAILURE/_SUCCESS instead of PCCTS_EXIT_FAILURE/_SUCCESS
+
+ pccts/h/PCCTSAST.cpp
+ pccts/h/DLexerBase.cpp
+ pccts/testcpp/6/test.g
+
+ 4. use of "signed int" isn't accepted by AT&T cfront
+
+ pccts/h/PCCTSAST.h line 42
+
+ 5. in call to ANTLRParser::FAIL the var arg err_k is passed as
+ "int" but is declared "unsigned int".
+
+ 6. I believe that a failed validation predicate still does not
+ get put in a "{...}" envelope, despite the release notes.
+
+ 7. The #token ">>" appearing in the DLG grammar description
+ causes DLG to generate the string literal "\>\>" which
+ is non-conforming and will cause some compilers to
+ complain (scan.c function act10 line 143 of source code).
+
+#11. (Version 1.32b6) Dave Kuhlman (dkuhlman@netcom.com)
+
+ Problem with file close in gen.c. Already fixed in 1.33.
+
+#10. (Version 1.32b6/29-Aug-95)
+
+ pccts/antlr/main.c contains a C++ style comments on lines 149
+ and 176 which causes problems for most C compilers.
+
+ Already fixed in 1.33.
+
+#9. (Version 1.32b4/14-Mar-95) dlgauto.h #include "config.h"
+
+ The file pccts/h/dlgauto.h should probably contain a #include
+ "config.h" as it uses the #define symbol __USE_PROTOS.
+
+ Added to 1.33MR1.
+
+#8. (Version 1.32b4/6-Mar-95) Michael T. Richter (mtr@igs.net)
+
+ In C++ output mode anonymous tokens from in-line regular expressions
+ can create enum values which are too wide for the datatype of the enum
+ assigned by the C++ compiler.
+
+ Fixed in 1.33MR1.
+
+#7. (Version 1.32b4/6-Mar-95) C++ does not imply __STDC__
+
+ In err.h the combination of # directives assumes that a C++
+ compiler has __STDC__ defined. This is not necessarily true.
+
+ This problem also appears in the use of __USE_PROTOS which
+ is appropriate for both Standard C and C++ in antlr/gen.c
+ and antlr/lex.c
+
+ Fixed in 1.33MR1.
+
+#6. (Version 1.32 ?/15-Feb-95) Name conflict for "TokenType"
+
+ Already fixed in 1.33.
+
+#5. (23-Jan-95) Douglas_Cuthbertson.JTIDS@jtids_qmail.hanscom.af.mil
+
+ The fail action following a semantic predicate is not enclosed in
+ "{...}". This can lead to problems when the fail action contains
+ more than one statement.
+
+ Fixed in 1.33MR1.
+
+#4 . (Version 1.33/31-Mar-96) jlilley@empathy.com (John Lilley)
+
+ Put briefly, a semantic predicate ought to abort a guess if it fails.
+
+ Correction suggested by J. Lilley has been added to 1.33MR1.
+
+#3 . (Version 1.33) P.A.Keller@bath.ac.uk
+
+ Extra commas are placed in the K&R style argument list for rules
+ when using both exceptions and ASTs.
+
+ Fixed in 1.33MR1.
+
+#2. (Version 1.32b6/2-Oct-95) Brad Schick <schick@interaccess.com>
+
+ Construct #[] generates zzastnew() in C++ mode.
+
+ Already fixed in 1.33.
+
+#1. (Version 1.33) Bob Bailey (robert@oakhill.sps.mot.com)
+
+ Previously, config.h assumed that all PC systems required
+ "short" file names. The user can now override that
+ assumption with "#define LONGFILENAMES".
+
+ Added to 1.33MR1.
diff --git a/Source/Pccts/CHANGES_SUMMARY.txt b/Source/Pccts/CHANGES_SUMMARY.txt
new file mode 100644
index 0000000..91defae
--- /dev/null
+++ b/Source/Pccts/CHANGES_SUMMARY.txt
@@ -0,0 +1,2049 @@
+======================================================================
+
+ CHANGES_SUMMARY.TXT
+
+ A QUICK overview of changes from 1.33 in reverse order
+
+ A summary of additions rather than bug fixes and minor code changes.
+
+ Numbers refer to items in CHANGES_FROM_133*.TXT
+ which may contain additional information.
+
+ DISCLAIMER
+
+ The software and these notes are provided "as is". They may include
+ typographical or technical errors and their authors disclaims all
+ liability of any kind or nature for damages due to error, fault,
+ defect, or deficiency regardless of cause. All warranties of any
+ kind, either express or implied, including, but not limited to, the
+ implied warranties of merchantability and fitness for a particular
+ purpose are disclaimed.
+
+======================================================================
+
+#258. You can specify a user-defined base class for your parser
+
+ The base class must constructor must have a signature similar to
+ that of ANTLRParser.
+
+#253. Generation of block preamble (-preamble and -preamble_first)
+
+ The antlr option -preamble causes antlr to insert the code
+ BLOCK_PREAMBLE at the start of each rule and block.
+
+ The antlr option -preamble_first is similar, but inserts the
+ code BLOCK_PREAMBLE_FIRST(PreambleFirst_123) where the symbol
+ PreambleFirst_123 is equivalent to the first set defined by
+ the #FirstSetSymbol described in Item #248.
+
+#248. Generate symbol for first set of an alternative
+
+ rr : #FirstSetSymbol(rr_FirstSet) ( Foo | Bar ) ;
+
+#216. Defer token fetch for C++ mode
+
+ When the ANTLRParser class is built with the pre-processor option
+ ZZDEFER_FETCH defined, the fetch of new tokens by consume() is deferred
+ until LA(i) or LT(i) is called.
+
+#215. Use reset() to reset DLGLexerBase
+#188. Added pccts/h/DLG_stream_input.h
+#180. Added ANTLRParser::getEofToken()
+#173. -glms for Microsoft style filenames with -gl
+#170. Suppression for predicates with lookahead depth >1
+
+ Consider the following grammar with -ck 2 and the predicate in rule
+ "a" with depth 2:
+
+ r1 : (ab)* "@"
+ ;
+
+ ab : a
+ | b
+ ;
+
+ a : (A B)? => <<p(LATEXT(2))>>? A B C
+ ;
+
+ b : A B C
+ ;
+
+ Normally, the predicate would be hoisted into rule r1 in order to
+ determine whether to call rule "ab". However it should *not* be
+ hoisted because, even if p is false, there is a valid alternative
+ in rule b. With "-mrhoistk on" the predicate will be suppressed.
+
+ If "-info p" command line option is present the following information
+ will appear in the generated code:
+
+ while ( (LA(1)==A)
+ #if 0
+
+ Part (or all) of predicate with depth > 1 suppressed by alternative
+ without predicate
+
+ pred << p(LATEXT(2))>>?
+ depth=k=2 ("=>" guard) rule a line 8 t1.g
+ tree context:
+ (root = A
+ B
+ )
+
+ The token sequence which is suppressed: ( A B )
+ The sequence of references which generate that sequence of tokens:
+
+ 1 to ab r1/1 line 1 t1.g
+ 2 ab ab/1 line 4 t1.g
+ 3 to b ab/2 line 5 t1.g
+ 4 b b/1 line 11 t1.g
+ 5 #token A b/1 line 11 t1.g
+ 6 #token B b/1 line 11 t1.g
+
+ #endif
+
+ A slightly more complicated example:
+
+ r1 : (ab)* "@"
+ ;
+
+ ab : a
+ | b
+ ;
+
+ a : (A B)? => <<p(LATEXT(2))>>? (A B | D E)
+ ;
+
+ b : <<q(LATEXT(2))>>? D E
+ ;
+
+
+ In this case, the sequence (D E) in rule "a" which lies behind
+ the guard is used to suppress the predicate with context (D E)
+ in rule b.
+
+ while ( (LA(1)==A || LA(1)==D)
+ #if 0
+
+ Part (or all) of predicate with depth > 1 suppressed by alternative
+ without predicate
+
+ pred << q(LATEXT(2))>>?
+ depth=k=2 rule b line 11 t2.g
+ tree context:
+ (root = D
+ E
+ )
+
+ The token sequence which is suppressed: ( D E )
+ The sequence of references which generate that sequence of tokens:
+
+ 1 to ab r1/1 line 1 t2.g
+ 2 ab ab/1 line 4 t2.g
+ 3 to a ab/1 line 4 t2.g
+ 4 a a/1 line 8 t2.g
+ 5 #token D a/1 line 8 t2.g
+ 6 #token E a/1 line 8 t2.g
+
+ #endif
+ &&
+ #if 0
+
+ pred << p(LATEXT(2))>>?
+ depth=k=2 ("=>" guard) rule a line 8 t2.g
+ tree context:
+ (root = A
+ B
+ )
+
+ #endif
+
+ (! ( LA(1)==A && LA(2)==B ) || p(LATEXT(2)) ) {
+ ab();
+ ...
+
+#165. (Changed in MR13) option -newAST
+
+ To create ASTs from an ANTLRTokenPtr antlr usually calls
+ "new AST(ANTLRTokenPtr)". This option generates a call
+ to "newAST(ANTLRTokenPtr)" instead. This allows a user
+ to define a parser member function to create an AST object.
+
+#161. (Changed in MR13) Switch -gxt inhibits generation of tokens.h
+
+#158. (Changed in MR13) #header causes problem for pre-processors
+
+ A user who runs the C pre-processor on antlr source suggested
+ that another syntax be allowed. With MR13 such directives
+ such as #header, #pragma, etc. may be written as "\#header",
+ "\#pragma", etc. For escaping pre-processor directives inside
+ a #header use something like the following:
+
+ \#header
+ <<
+ \#include <stdio.h>
+ >>
+
+#155. (Changed in MR13) Context behind predicates can suppress
+
+ With -mrhoist enabled the context behind a guarded predicate can
+ be used to suppress other predicates. Consider the following grammar:
+
+ r0 : (r1)+;
+
+ r1 : rp
+ | rq
+ ;
+ rp : <<p LATEXT(1)>>? B ;
+ rq : (A)? => <<q LATEXT(1)>>? (A|B);
+
+ In earlier versions both predicates "p" and "q" would be hoisted into
+ rule r0. With MR12c predicate p is suppressed because the context which
+ follows predicate q includes "B" which can "cover" predicate "p". In
+ other words, in trying to decide in r0 whether to call r1, it doesn't
+ really matter whether p is false or true because, either way, there is
+ a valid choice within r1.
+
+#154. (Changed in MR13) Making hoist suppression explicit using <<nohoist>>
+
+ A common error, even among experienced pccts users, is to code
+ an init-action to inhibit hoisting rather than a leading action.
+ An init-action does not inhibit hoisting.
+
+ This was coded:
+
+ rule1 : <<;>> rule2
+
+ This is what was meant:
+
+ rule1 : <<;>> <<;>> rule2
+
+ With MR13, the user can code:
+
+ rule1 : <<;>> <<nohoist>> rule2
+
+ The following will give an error message:
+
+ rule1 : <<nohoist>> rule2
+
+ If the <<nohoist>> appears as an init-action rather than a leading
+ action an error message is issued. The meaning of an init-action
+ containing "nohoist" is unclear: does it apply to just one
+ alternative or to all alternatives ?
+
+#151a. Addition of ANTLRParser::getLexer(), ANTLRTokenStream::getLexer()
+
+ You must manually cast the ANTLRTokenStream to your program's
+ lexer class. Because the name of the lexer's class is not fixed.
+ Thus it is impossible to incorporate it into the DLGLexerBase
+ class.
+
+#151b.(Changed in MR12) ParserBlackBox member getLexer()
+
+#150. (Changed in MR12) syntaxErrCount and lexErrCount now public
+
+#149. (Changed in MR12) antlr option -info o (letter o for orphan)
+
+ If there is more than one rule which is not referenced by any
+ other rule then all such rules are listed. This is useful for
+ alerting one to rules which are not used, but which can still
+ contribute to ambiguity.
+
+#148. (Changed in MR11) #token names appearing in zztokens,token_tbl
+
+ One can write:
+
+ #token Plus ("+") "\+"
+ #token RP ("(") "\("
+ #token COM ("comment begin") "/\*"
+
+ The string in parenthesis will be used in syntax error messages.
+
+#146. (Changed in MR11) Option -treport for locating "difficult" alts
+
+ It can be difficult to determine which alternatives are causing
+ pccts to work hard to resolve an ambiguity. In some cases the
+ ambiguity is successfully resolved after much CPU time so there
+ is no message at all.
+
+ A rough measure of the amount of work being peformed which is
+ independent of the CPU speed and system load is the number of
+ tnodes created. Using "-info t" gives information about the
+ total number of tnodes created and the peak number of tnodes.
+
+ Tree Nodes: peak 1300k created 1416k lost 0
+
+ It also puts in the generated C or C++ file the number of tnodes
+ created for a rule (at the end of the rule). However this
+ information is not sufficient to locate the alternatives within
+ a rule which are causing the creation of tnodes.
+
+ Using:
+
+ antlr -treport 100000 ....
+
+ causes antlr to list on stdout any alternatives which require the
+ creation of more than 100,000 tnodes, along with the lookahead sets
+ for those alternatives.
+
+ The following is a trivial case from the ansi.g grammar which shows
+ the format of the report. This report might be of more interest
+ in cases where 1,000,000 tuples were created to resolve the ambiguity.
+
+ -------------------------------------------------------------------------
+ There were 0 tuples whose ambiguity could not be resolved
+ by full lookahead
+ There were 157 tnodes created to resolve ambiguity between:
+
+ Choice 1: statement/2 line 475 file ansi.g
+ Choice 2: statement/3 line 476 file ansi.g
+
+ Intersection of lookahead[1] sets:
+
+ IDENTIFIER
+
+ Intersection of lookahead[2] sets:
+
+ LPARENTHESIS COLON AMPERSAND MINUS
+ STAR PLUSPLUS MINUSMINUS ONESCOMPLEMENT
+ NOT SIZEOF OCTALINT DECIMALINT
+ HEXADECIMALINT FLOATONE FLOATTWO IDENTIFIER
+ STRING CHARACTER
+ -------------------------------------------------------------------------
+
+#143. (Changed in MR11) Optional ";" at end of #token statement
+
+ Fixes problem of:
+
+ #token X "x"
+
+ <<
+ parser action
+ >>
+
+ Being confused with:
+
+ #token X "x" <<lexical action>>
+
+#142. (Changed in MR11) class BufFileInput subclass of DLGInputStream
+
+ Alexey Demakov (demakov@kazbek.ispras.ru) has supplied class
+ BufFileInput derived from DLGInputStream which provides a
+ function lookahead(char *string) to test characters in the
+ input stream more than one character ahead.
+ The class is located in pccts/h/BufFileInput.* of the kit.
+
+#140. #pred to define predicates
+
+ +---------------------------------------------------+
+ | Note: Assume "-prc on" for this entire discussion |
+ +---------------------------------------------------+
+
+ A problem with predicates is that each one is regarded as
+ unique and capable of disambiguating cases where two
+ alternatives have identical lookahead. For example:
+
+ rule : <<pred(LATEXT(1))>>? A
+ | <<pred(LATEXT(1))>>? A
+ ;
+
+ will not cause any error messages or warnings to be issued
+ by earlier versions of pccts. To compare the text of the
+ predicates is an incomplete solution.
+
+ In 1.33MR11 I am introducing the #pred statement in order to
+ solve some problems with predicates. The #pred statement allows
+ one to give a symbolic name to a "predicate literal" or a
+ "predicate expression" in order to refer to it in other predicate
+ expressions or in the rules of the grammar.
+
+ The predicate literal associated with a predicate symbol is C
+ or C++ code which can be used to test the condition. A
+ predicate expression defines a predicate symbol in terms of other
+ predicate symbols using "!", "&&", and "||". A predicate symbol
+ can be defined in terms of a predicate literal, a predicate
+ expression, or *both*.
+
+ When a predicate symbol is defined with both a predicate literal
+ and a predicate expression, the predicate literal is used to generate
+ code, but the predicate expression is used to check for two
+ alternatives with identical predicates in both alternatives.
+
+ Here are some examples of #pred statements:
+
+ #pred IsLabel <<isLabel(LATEXT(1))>>?
+ #pred IsLocalVar <<isLocalVar(LATEXT(1))>>?
+ #pred IsGlobalVar <<isGlobalVar(LATEXT(1)>>?
+ #pred IsVar <<isVar(LATEXT(1))>>? IsLocalVar || IsGlobalVar
+ #pred IsScoped <<isScoped(LATEXT(1))>>? IsLabel || IsLocalVar
+
+ I hope that the use of EBNF notation to describe the syntax of the
+ #pred statement will not cause problems for my readers (joke).
+
+ predStatement : "#pred"
+ CapitalizedName
+ (
+ "<<predicate_literal>>?"
+ | "<<predicate_literal>>?" predOrExpr
+ | predOrExpr
+ )
+ ;
+
+ predOrExpr : predAndExpr ( "||" predAndExpr ) * ;
+
+ predAndExpr : predPrimary ( "&&" predPrimary ) * ;
+
+ predPrimary : CapitalizedName
+ | "!" predPrimary
+ | "(" predOrExpr ")"
+ ;
+
+ What is the purpose of this nonsense ?
+
+ To understand how predicate symbols help, you need to realize that
+ predicate symbols are used in two different ways with two different
+ goals.
+
+ a. Allow simplification of predicates which have been combined
+ during predicate hoisting.
+
+ b. Allow recognition of identical predicates which can't disambiguate
+ alternatives with common lookahead.
+
+ First we will discuss goal (a). Consider the following rule:
+
+ rule0: rule1
+ | ID
+ | ...
+ ;
+
+ rule1: rule2
+ | rule3
+ ;
+
+ rule2: <<isX(LATEXT(1))>>? ID ;
+ rule3: <<!isX(LATEXT(1)>>? ID ;
+
+ When the predicates in rule2 and rule3 are combined by hoisting
+ to create a prediction expression for rule1 the result is:
+
+ if ( LA(1)==ID
+ && ( isX(LATEXT(1) || !isX(LATEXT(1) ) ) { rule1(); ...
+
+ This is inefficient, but more importantly, can lead to false
+ assumptions that the predicate expression distinguishes the rule1
+ alternative with some other alternative with lookahead ID. In
+ MR11 one can write:
+
+ #pred IsX <<isX(LATEXT(1))>>?
+
+ ...
+
+ rule2: <<IsX>>? ID ;
+ rule3: <<!IsX>>? ID ;
+
+ During hoisting MR11 recognizes this as a special case and
+ eliminates the predicates. The result is a prediction
+ expression like the following:
+
+ if ( LA(1)==ID ) { rule1(); ...
+
+ Please note that the following cases which appear to be equivalent
+ *cannot* be simplified by MR11 during hoisting because the hoisting
+ logic only checks for a "!" in the predicate action, not in the
+ predicate expression for a predicate symbol.
+
+ *Not* equivalent and is not simplified during hoisting:
+
+ #pred IsX <<isX(LATEXT(1))>>?
+ #pred NotX <<!isX(LATEXT(1))>>?
+ ...
+ rule2: <<IsX>>? ID ;
+ rule3: <<NotX>>? ID ;
+
+ *Not* equivalent and is not simplified during hoisting:
+
+ #pred IsX <<isX(LATEXT(1))>>?
+ #pred NotX !IsX
+ ...
+ rule2: <<IsX>>? ID ;
+ rule3: <<NotX>>? ID ;
+
+ Now we will discuss goal (b).
+
+ When antlr discovers that there is a lookahead ambiguity between
+ two alternatives it attempts to resolve the ambiguity by searching
+ for predicates in both alternatives. In the past any predicate
+ would do, even if the same one appeared in both alternatives:
+
+ rule: <<p(LATEXT(1))>>? X
+ | <<p(LATEXT(1))>>? X
+ ;
+
+ The #pred statement is a start towards solving this problem.
+ During ambiguity resolution (*not* predicate hoisting) the
+ predicates for the two alternatives are expanded and compared.
+ Consider the following example:
+
+ #pred Upper <<isUpper(LATEXT(1))>>?
+ #pred Lower <<isLower(LATEXT(1))>>?
+ #pred Alpha <<isAlpha(LATEXT(1))>>? Upper || Lower
+
+ rule0: rule1
+ | <<Alpha>>? ID
+ ;
+
+ rule1:
+ | rule2
+ | rule3
+ ...
+ ;
+
+ rule2: <<Upper>>? ID;
+ rule3: <<Lower>>? ID;
+
+ The definition of #pred Alpha expresses:
+
+ a. to test the predicate use the C code "isAlpha(LATEXT(1))"
+
+ b. to analyze the predicate use the information that
+ Alpha is equivalent to the union of Upper and Lower,
+
+ During ambiguity resolution the definition of Alpha is expanded
+ into "Upper || Lower" and compared with the predicate in the other
+ alternative, which is also "Upper || Lower". Because they are
+ identical MR11 will report a problem.
+
+ -------------------------------------------------------------------------
+ t10.g, line 5: warning: the predicates used to disambiguate rule rule0
+ (file t10.g alt 1 line 5 and alt 2 line 6)
+ are identical when compared without context and may have no
+ resolving power for some lookahead sequences.
+ -------------------------------------------------------------------------
+
+ If you use the "-info p" option the output file will contain:
+
+ +----------------------------------------------------------------------+
+ |#if 0 |
+ | |
+ |The following predicates are identical when compared without |
+ | lookahead context information. For some ambiguous lookahead |
+ | sequences they may not have any power to resolve the ambiguity. |
+ | |
+ |Choice 1: rule0/1 alt 1 line 5 file t10.g |
+ | |
+ | The original predicate for choice 1 with available context |
+ | information: |
+ | |
+ | OR expr |
+ | |
+ | pred << Upper>>? |
+ | depth=k=1 rule rule2 line 14 t10.g |
+ | set context: |
+ | ID |
+ | |
+ | pred << Lower>>? |
+ | depth=k=1 rule rule3 line 15 t10.g |
+ | set context: |
+ | ID |
+ | |
+ | The predicate for choice 1 after expansion (but without context |
+ | information): |
+ | |
+ | OR expr |
+ | |
+ | pred << isUpper(LATEXT(1))>>? |
+ | depth=k=1 rule line 1 t10.g |
+ | |
+ | pred << isLower(LATEXT(1))>>? |
+ | depth=k=1 rule line 2 t10.g |
+ | |
+ | |
+ |Choice 2: rule0/2 alt 2 line 6 file t10.g |
+ | |
+ | The original predicate for choice 2 with available context |
+ | information: |
+ | |
+ | pred << Alpha>>? |
+ | depth=k=1 rule rule0 line 6 t10.g |
+ | set context: |
+ | ID |
+ | |
+ | The predicate for choice 2 after expansion (but without context |
+ | information): |
+ | |
+ | OR expr |
+ | |
+ | pred << isUpper(LATEXT(1))>>? |
+ | depth=k=1 rule line 1 t10.g |
+ | |
+ | pred << isLower(LATEXT(1))>>? |
+ | depth=k=1 rule line 2 t10.g |
+ | |
+ | |
+ |#endif |
+ +----------------------------------------------------------------------+
+
+ The comparison of the predicates for the two alternatives takes
+ place without context information, which means that in some cases
+ the predicates will be considered identical even though they operate
+ on disjoint lookahead sets. Consider:
+
+ #pred Alpha
+
+ rule1: <<Alpha>>? ID
+ | <<Alpha>>? Label
+ ;
+
+ Because the comparison of predicates takes place without context
+ these will be considered identical. The reason for comparing
+ without context is that otherwise it would be necessary to re-evaluate
+ the entire predicate expression for each possible lookahead sequence.
+ This would require more code to be written and more CPU time during
+ grammar analysis, and it is not yet clear whether anyone will even make
+ use of the new #pred facility.
+
+ A temporary workaround might be to use different #pred statements
+ for predicates you know have different context. This would avoid
+ extraneous warnings.
+
+ The above example might be termed a "false positive". Comparison
+ without context will also lead to "false negatives". Consider the
+ following example:
+
+ #pred Alpha
+ #pred Beta
+
+ rule1: <<Alpha>>? A
+ | rule2
+ ;
+
+ rule2: <<Alpha>>? A
+ | <<Beta>>? B
+ ;
+
+ The predicate used for alt 2 of rule1 is (Alpha || Beta). This
+ appears to be different than the predicate Alpha used for alt1.
+ However, the context of Beta is B. Thus when the lookahead is A
+ Beta will have no resolving power and Alpha will be used for both
+ alternatives. Using the same predicate for both alternatives isn't
+ very helpful, but this will not be detected with 1.33MR11.
+
+ To properly handle this the predicate expression would have to be
+ evaluated for each distinct lookahead context.
+
+ To determine whether two predicate expressions are identical is
+ difficult. The routine may fail to identify identical predicates.
+
+ The #pred feature also compares predicates to see if a choice between
+ alternatives which is resolved by a predicate which makes the second
+ choice unreachable. Consider the following example:
+
+ #pred A <<A(LATEXT(1)>>?
+ #pred B <<B(LATEXT(1)>>?
+ #pred A_or_B A || B
+
+ r : s
+ | t
+ ;
+ s : <<A_or_B>>? ID
+ ;
+ t : <<A>>? ID
+ ;
+
+ ----------------------------------------------------------------------------
+ t11.g, line 5: warning: the predicate used to disambiguate the
+ first choice of rule r
+ (file t11.g alt 1 line 5 and alt 2 line 6)
+ appears to "cover" the second predicate when compared without context.
+ The second predicate may have no resolving power for some lookahead
+ sequences.
+ ----------------------------------------------------------------------------
+
+#132. (Changed in 1.33MR11) Recognition of identical predicates in alts
+
+ Prior to 1.33MR11, there would be no ambiguity warning when the
+ very same predicate was used to disambiguate both alternatives:
+
+ test: ref B
+ | ref C
+ ;
+
+ ref : <<pred(LATEXT(1)>>? A
+
+ In 1.33MR11 this will cause the warning:
+
+ warning: the predicates used to disambiguate rule test
+ (file v98.g alt 1 line 1 and alt 2 line 2)
+ are identical and have no resolving power
+
+ ----------------- Note -----------------
+
+ This is different than the following case
+
+ test: <<pred(LATEXT(1))>>? A B
+ | <<pred(LATEXT(1)>>? A C
+ ;
+
+ In this case there are two distinct predicates
+ which have exactly the same text. In the first
+ example there are two references to the same
+ predicate. The problem represented by this
+ grammar will be addressed later.
+
+
+#127. (Changed in 1.33MR11)
+
+ Count Syntax Errors Count DLG Errors
+ ------------------- ----------------
+
+ C++ mode ANTLRParser:: DLGLexerBase::
+ syntaxErrCount lexErrCount
+ C mode zzSyntaxErrCount zzLexErrCount
+
+ The C mode variables are global and initialized to 0.
+ They are *not* reset to 0 automatically when antlr is
+ restarted.
+
+ The C++ mode variables are public. They are initialized
+ to 0 by the constructors. They are *not* reset to 0 by the
+ ANTLRParser::init() method.
+
+ Suggested by Reinier van den Born (reinier@vnet.ibm.com).
+
+#126. (Changed in 1.33MR11) Addition of #first <<...>>
+
+ The #first <<...>> inserts the specified text in the output
+ files before any other #include statements required by pccts.
+ The only things before the #first text are comments and
+ a #define ANTLR_VERSION.
+
+ Requested by and Esa Pulkkinen (esap@cs.tut.fi) and Alexin
+ Zoltan (alexin@inf.u-szeged.hu).
+
+#124. A Note on the New "&&" Style Guarded Predicates
+
+ I've been asked several times, "What is the difference between
+ the old "=>" style guard predicates and the new style "&&" guard
+ predicates, and how do you choose one over the other" ?
+
+ The main difference is that the "=>" does not apply the
+ predicate if the context guard doesn't match, whereas
+ the && form always does. What is the significance ?
+
+ If you have a predicate which is not on the "leading edge"
+ it is cannot be hoisted. Suppose you need a predicate that
+ looks at LA(2). You must introduce it manually. The
+ classic example is:
+
+ castExpr :
+ LP typeName RP
+ | ....
+ ;
+
+ typeName : <<isTypeName(LATEXT(1))>>? ID
+ | STRUCT ID
+ ;
+
+ The problem is that isTypeName() isn't on the leading edge
+ of typeName, so it won't be hoisted into castExpr to help
+ make a decision on which production to choose.
+
+ The *first* attempt to fix it is this:
+
+ castExpr :
+ <<isTypeName(LATEXT(2))>>?
+ LP typeName RP
+ | ....
+ ;
+
+ Unfortunately, this won't work because it ignores
+ the problem of STRUCT. The solution is to apply
+ isTypeName() in castExpr if LA(2) is an ID and
+ don't apply it when LA(2) is STRUCT:
+
+ castExpr :
+ (LP ID)? => <<isTypeName(LATEXT(2))>>?
+ LP typeName RP
+ | ....
+ ;
+
+ In conclusion, the "=>" style guarded predicate is
+ useful when:
+
+ a. the tokens required for the predicate
+ are not on the leading edge
+ b. there are alternatives in the expression
+ selected by the predicate for which the
+ predicate is inappropriate
+
+ If (b) were false, then one could use a simple
+ predicate (assuming "-prc on"):
+
+ castExpr :
+ <<isTypeName(LATEXT(2))>>?
+ LP typeName RP
+ | ....
+ ;
+
+ typeName : <<isTypeName(LATEXT(1))>>? ID
+ ;
+
+ So, when do you use the "&&" style guarded predicate ?
+
+ The new-style "&&" predicate should always be used with
+ predicate context. The context guard is in ADDITION to
+ the automatically computed context. Thus it useful for
+ predicates which depend on the token type for reasons
+ other than context.
+
+ The following example is contributed by Reinier van den Born
+ (reinier@vnet.ibm.com).
+
+ +-------------------------------------------------------------------------+
+ | This grammar has two ways to call functions: |
+ | |
+ | - a "standard" call syntax with parens and comma separated args |
+ | - a shell command like syntax (no parens and spacing separated args) |
+ | |
+ | The former also allows a variable to hold the name of the function, |
+ | the latter can also be used to call external commands. |
+ | |
+ | The grammar (simplified) looks like this: |
+ | |
+ | fun_call : ID "(" { expr ("," expr)* } ")" |
+ | /* ID is function name */ |
+ | | "@" ID "(" { expr ("," expr)* } ")" |
+ | /* ID is var containing fun name */ |
+ | ; |
+ | |
+ | command : ID expr* /* ID is function name */ |
+ | | path expr* /* path is external command name */ |
+ | ; |
+ | |
+ | path : ID /* left out slashes and such */ |
+ | | "@" ID /* ID is environment var */ |
+ | ; |
+ | |
+ | expr : .... |
+ | | "(" expr ")"; |
+ | |
+ | call : fun_call |
+ | | command |
+ | ; |
+ | |
+ | Obviously the call is wildly ambiguous. This is more or less how this |
+ | is to be resolved: |
+ | |
+ | A call begins with an ID or an @ followed by an ID. |
+ | |
+ | If it is an ID and if it is an ext. command name -> command |
+ | if followed by a paren -> fun_call |
+ | otherwise -> command |
+ | |
+ | If it is an @ and if the ID is a var name -> fun_call |
+ | otherwise -> command |
+ | |
+ | One can implement these rules quite neatly using && predicates: |
+ | |
+ | call : ("@" ID)? && <<isVarName(LT(2))>>? fun_call |
+ | | (ID)? && <<isExtCmdName>>? command |
+ | | (ID "(")? fun_call |
+ | | command |
+ | ; |
+ | |
+ | This can be done better, so it is not an ideal example, but it |
+ | conveys the principle. |
+ +-------------------------------------------------------------------------+
+
+#122. (Changed in 1.33MR11) Member functions to reset DLG in C++ mode
+
+ void DLGFileReset(FILE *f) { input = f; found_eof = 0; }
+ void DLGStringReset(DLGChar *s) { input = s; p = &input[0]; }
+
+ Supplied by R.A. Nelson (cowboy@VNET.IBM.COM)
+
+#119. (Changed in 1.33MR11) Ambiguity aid for grammars
+
+ The user can ask for additional information on ambiguities reported
+ by antlr to stdout. At the moment, only one ambiguity report can
+ be created in an antlr run.
+
+ This feature is enabled using the "-aa" (Ambiguity Aid) option.
+
+ The following options control the reporting of ambiguities:
+
+ -aa ruleName Selects reporting by name of rule
+ -aa lineNumber Selects reporting by line number
+ (file name not compared)
+
+ -aam Selects "multiple" reporting for a token
+ in the intersection set of the
+ alternatives.
+
+ For instance, the token ID may appear dozens
+ of times in various paths as the program
+ explores the rules which are reachable from
+ the point of an ambiguity. With option -aam
+ every possible path the search program
+ encounters is reported.
+
+ Without -aam only the first encounter is
+ reported. This may result in incomplete
+ information, but the information may be
+ sufficient and much shorter.
+
+ -aad depth Selects the depth of the search.
+ The default value is 1.
+
+ The number of paths to be searched, and the
+ size of the report can grow geometrically
+ with the -ck value if a full search for all
+ contributions to the source of the ambiguity
+ is explored.
+
+ The depth represents the number of tokens
+ in the lookahead set which are matched against
+ the set of ambiguous tokens. A depth of 1
+ means that the search stops when a lookahead
+ sequence of just one token is matched.
+
+ A k=1 ck=6 grammar might generate 5,000 items
+ in a report if a full depth 6 search is made
+ with the Ambiguity Aid. The source of the
+ problem may be in the first token and obscured
+ by the volume of data - I hesitate to call
+ it information.
+
+ When the user selects a depth > 1, the search
+ is first performed at depth=1 for both
+ alternatives, then depth=2 for both alternatives,
+ etc.
+
+ Sample output for rule grammar in antlr.g itself:
+
+ +---------------------------------------------------------------------+
+ | Ambiguity Aid |
+ | |
+ | Choice 1: grammar/70 line 632 file a.g |
+ | Choice 2: grammar/82 line 644 file a.g |
+ | |
+ | Intersection of lookahead[1] sets: |
+ | |
+ | "\}" "class" "#errclass" "#tokclass" |
+ | |
+ | Choice:1 Depth:1 Group:1 ("#errclass") |
+ | 1 in (...)* block grammar/70 line 632 a.g |
+ | 2 to error grammar/73 line 635 a.g |
+ | 3 error error/1 line 894 a.g |
+ | 4 #token "#errclass" error/2 line 895 a.g |
+ | |
+ | Choice:1 Depth:1 Group:2 ("#tokclass") |
+ | 2 to tclass grammar/74 line 636 a.g |
+ | 3 tclass tclass/1 line 937 a.g |
+ | 4 #token "#tokclass" tclass/2 line 938 a.g |
+ | |
+ | Choice:1 Depth:1 Group:3 ("class") |
+ | 2 to class_def grammar/75 line 637 a.g |
+ | 3 class_def class_def/1 line 669 a.g |
+ | 4 #token "class" class_def/3 line 671 a.g |
+ | |
+ | Choice:1 Depth:1 Group:4 ("\}") |
+ | 2 #token "\}" grammar/76 line 638 a.g |
+ | |
+ | Choice:2 Depth:1 Group:5 ("#errclass") |
+ | 1 in (...)* block grammar/83 line 645 a.g |
+ | 2 to error grammar/93 line 655 a.g |
+ | 3 error error/1 line 894 a.g |
+ | 4 #token "#errclass" error/2 line 895 a.g |
+ | |
+ | Choice:2 Depth:1 Group:6 ("#tokclass") |
+ | 2 to tclass grammar/94 line 656 a.g |
+ | 3 tclass tclass/1 line 937 a.g |
+ | 4 #token "#tokclass" tclass/2 line 938 a.g |
+ | |
+ | Choice:2 Depth:1 Group:7 ("class") |
+ | 2 to class_def grammar/95 line 657 a.g |
+ | 3 class_def class_def/1 line 669 a.g |
+ | 4 #token "class" class_def/3 line 671 a.g |
+ | |
+ | Choice:2 Depth:1 Group:8 ("\}") |
+ | 2 #token "\}" grammar/96 line 658 a.g |
+ +---------------------------------------------------------------------+
+
+ For a linear lookahead set ambiguity (where k=1 or for k>1 but
+ when all lookahead sets [i] with i<k all have degree one) the
+ reports appear in the following order:
+
+ for (depth=1 ; depth <= "-aad depth" ; depth++) {
+ for (alternative=1; alternative <=2 ; alternative++) {
+ while (matches-are-found) {
+ group++;
+ print-report
+ };
+ };
+ };
+
+ For reporting a k-tuple ambiguity, the reports appear in the
+ following order:
+
+ for (depth=1 ; depth <= "-aad depth" ; depth++) {
+ while (matches-are-found) {
+ for (alternative=1; alternative <=2 ; alternative++) {
+ group++;
+ print-report
+ };
+ };
+ };
+
+ This is because matches are generated in different ways for
+ linear lookahead and k-tuples.
+
+#117. (Changed in 1.33MR10) new EXPERIMENTAL predicate hoisting code
+
+ The hoisting of predicates into rules to create prediction
+ expressions is a problem in antlr. Consider the following
+ example (k=1 with -prc on):
+
+ start : (a)* "@" ;
+ a : b | c ;
+ b : <<isUpper(LATEXT(1))>>? A ;
+ c : A ;
+
+ Prior to 1.33MR10 the code generated for "start" would resemble:
+
+ while {
+ if (LA(1)==A &&
+ (!LA(1)==A || isUpper())) {
+ a();
+ }
+ };
+
+ This code is wrong because it makes rule "c" unreachable from
+ "start". The essence of the problem is that antlr fails to
+ recognize that there can be a valid alternative within "a" even
+ when the predicate <<isUpper(LATEXT(1))>>? is false.
+
+ In 1.33MR10 with -mrhoist the hoisting of the predicate into
+ "start" is suppressed because it recognizes that "c" can
+ cover all the cases where the predicate is false:
+
+ while {
+ if (LA(1)==A) {
+ a();
+ }
+ };
+
+ With the antlr "-info p" switch the user will receive information
+ about the predicate suppression in the generated file:
+
+ --------------------------------------------------------------
+ #if 0
+
+ Hoisting of predicate suppressed by alternative without predicate.
+ The alt without the predicate includes all cases where
+ the predicate is false.
+
+ WITH predicate: line 7 v1.g
+ WITHOUT predicate: line 7 v1.g
+
+ The context set for the predicate:
+
+ A
+
+ The lookahead set for the alt WITHOUT the semantic predicate:
+
+ A
+
+ The predicate:
+
+ pred << isUpper(LATEXT(1))>>?
+ depth=k=1 rule b line 9 v1.g
+ set context:
+ A
+ tree context: null
+
+ Chain of referenced rules:
+
+ #0 in rule start (line 5 v1.g) to rule a
+ #1 in rule a (line 7 v1.g)
+
+ #endif
+ --------------------------------------------------------------
+
+ A predicate can be suppressed by a combination of alternatives
+ which, taken together, cover a predicate:
+
+ start : (a)* "@" ;
+
+ a : b | ca | cb | cc ;
+
+ b : <<isUpper(LATEXT(1))>>? ( A | B | C ) ;
+
+ ca : A ;
+ cb : B ;
+ cc : C ;
+
+ Consider a more complex example in which "c" covers only part of
+ a predicate:
+
+ start : (a)* "@" ;
+
+ a : b
+ | c
+ ;
+
+ b : <<isUpper(LATEXT(1))>>?
+ ( A
+ | X
+ );
+
+ c : A
+ ;
+
+ Prior to 1.33MR10 the code generated for "start" would resemble:
+
+ while {
+ if ( (LA(1)==A || LA(1)==X) &&
+ (! (LA(1)==A || LA(1)==X) || isUpper()) {
+ a();
+ }
+ };
+
+ With 1.33MR10 and -mrhoist the predicate context is restricted to
+ the non-covered lookahead. The code resembles:
+
+ while {
+ if ( (LA(1)==A || LA(1)==X) &&
+ (! (LA(1)==X) || isUpper()) {
+ a();
+ }
+ };
+
+ With the antlr "-info p" switch the user will receive information
+ about the predicate restriction in the generated file:
+
+ --------------------------------------------------------------
+ #if 0
+
+ Restricting the context of a predicate because of overlap
+ in the lookahead set between the alternative with the
+ semantic predicate and one without
+ Without this restriction the alternative without the predicate
+ could not be reached when input matched the context of the
+ predicate and the predicate was false.
+
+ WITH predicate: line 11 v4.g
+ WITHOUT predicate: line 12 v4.g
+
+ The original context set for the predicate:
+
+ A X
+
+ The lookahead set for the alt WITHOUT the semantic predicate:
+
+ A
+
+ The intersection of the two sets
+
+ A
+
+ The original predicate:
+
+ pred << isUpper(LATEXT(1))>>?
+ depth=k=1 rule b line 15 v4.g
+ set context:
+ A X
+ tree context: null
+
+ The new (modified) form of the predicate:
+
+ pred << isUpper(LATEXT(1))>>?
+ depth=k=1 rule b line 15 v4.g
+ set context:
+ X
+ tree context: null
+
+ #endif
+ --------------------------------------------------------------
+
+ The bad news about -mrhoist:
+
+ (a) -mrhoist does not analyze predicates with lookahead
+ depth > 1.
+
+ (b) -mrhoist does not look past a guarded predicate to
+ find context which might cover other predicates.
+
+ For these cases you might want to use syntactic predicates.
+ When a semantic predicate fails during guess mode the guess
+ fails and the next alternative is tried.
+
+ Limitation (a) is illustrated by the following example:
+
+ start : (stmt)* EOF ;
+
+ stmt : cast
+ | expr
+ ;
+ cast : <<isTypename(LATEXT(2))>>? LP ID RP ;
+
+ expr : LP ID RP ;
+
+ This is not much different from the first example, except that
+ it requires two tokens of lookahead context to determine what
+ to do. This predicate is NOT suppressed because the current version
+ is unable to handle predicates with depth > 1.
+
+ A predicate can be combined with other predicates during hoisting.
+ In those cases the depth=1 predicates are still handled. Thus,
+ in the following example the isUpper() predicate will be suppressed
+ by line #4 when hoisted from "bizarre" into "start", but will still
+ be present in "bizarre" in order to predict "stmt".
+
+ start : (bizarre)* EOF ; // #1
+ // #2
+ bizarre : stmt // #3
+ | A // #4
+ ;
+
+ stmt : cast
+ | expr
+ ;
+
+ cast : <<isTypename(LATEXT(2))>>? LP ID RP ;
+
+ expr : LP ID RP ;
+ | <<isUpper(LATEXT(1))>>? A
+
+ Limitation (b) is illustrated by the following example of a
+ context guarded predicate:
+
+ rule : (A)? <<p>>? // #1
+ (A // #2
+ |B // #3
+ ) // #4
+ | <<q>> B // #5
+ ;
+
+ Recall that this means that when the lookahead is NOT A then
+ the predicate "p" is ignored and it attempts to match "A|B".
+ Ideally, the "B" at line #3 should suppress predicate "q".
+ However, the current version does not attempt to look past
+ the guard predicate to find context which might suppress other
+ predicates.
+
+ In some cases -mrhoist will lead to the reporting of ambiguities
+ which were not visible before:
+
+ start : (a)* "@";
+ a : bc | d;
+ bc : b | c ;
+
+ b : <<isUpper(LATEXT(1))>>? A;
+ c : A ;
+
+ d : A ;
+
+ In this case there is a true ambiguity in "a" between "bc" and "d"
+ which can both match "A". Without -mrhoist the predicate in "b"
+ is hoisted into "a" and there is no ambiguity reported. However,
+ with -mrhoist, the predicate in "b" is suppressed by "c" (as it
+ should be) making the ambiguity in "a" apparent.
+
+ The motivations for these changes were hoisting problems reported
+ by Reinier van den Born (reinier@vnet.ibm.com) and several others.
+
+#113. (Changed in 1.33MR10) new context guarded pred: (g)? && <<p>>? expr
+
+ The existing context guarded predicate:
+
+ rule : (guard)? => <<p>>? expr
+ | next_alternative
+ ;
+
+ generates code which resembles:
+
+ if (lookahead(expr) && (!guard || pred)) {
+ expr()
+ } else ....
+
+ This is not suitable for some applications because it allows
+ expr() to be invoked when the predicate is false. This is
+ intentional because it is meant to mimic automatically computed
+ predicate context.
+
+ The new context guarded predicate uses the guard information
+ differently because it has a different goal. Consider:
+
+ rule : (guard)? && <<p>>? expr
+ | next_alternative
+ ;
+
+ The new style of context guarded predicate is equivalent to:
+
+ rule : <<guard==true && pred>>? expr
+ | next_alternative
+ ;
+
+ It generates code which resembles:
+
+ if (lookahead(expr) && guard && pred) {
+ expr();
+ } else ...
+
+ Both forms of guarded predicates severely restrict the form of
+ the context guard: it can contain no rule references, no
+ (...)*, no (...)+, and no {...}. It may contain token and
+ token class references, and alternation ("|").
+
+ Addition for 1.33MR11: in the token expression all tokens must
+ be at the same height of the token tree:
+
+ (A ( B | C))? && ... is ok (all height 2)
+ (A ( B | ))? && ... is not ok (some 1, some 2)
+ (A B C D | E F G H)? && ... is ok (all height 4)
+ (A B C D | E )? && ... is not ok (some 4, some 1)
+
+ This restriction is required in order to properly compute the lookahead
+ set for expressions like:
+
+ rule1 : (A B C)? && <<pred>>? rule2 ;
+ rule2 : (A|X) (B|Y) (C|Z);
+
+ This addition was suggested by Rienier van den Born (reinier@vnet.ibm.com)
+
+#109. (Changed in 1.33MR10) improved trace information
+
+ The quality of the trace information provided by the "-gd"
+ switch has been improved significantly. Here is an example
+ of the output from a test program. It shows the rule name,
+ the first token of lookahead, the call depth, and the guess
+ status:
+
+ exit rule gusxx {"?"} depth 2
+ enter rule gusxx {"?"} depth 2
+ enter rule gus1 {"o"} depth 3 guessing
+ guess done - returning to rule gus1 {"o"} at depth 3
+ (guess mode continues - an enclosing guess is still active)
+ guess done - returning to rule gus1 {"Z"} at depth 3
+ (guess mode continues - an enclosing guess is still active)
+ exit rule gus1 {"Z"} depth 3 guessing
+ guess done - returning to rule gusxx {"o"} at depth 2 (guess mode ends)
+ enter rule gus1 {"o"} depth 3
+ guess done - returning to rule gus1 {"o"} at depth 3 (guess mode ends)
+ guess done - returning to rule gus1 {"Z"} at depth 3 (guess mode ends)
+ exit rule gus1 {"Z"} depth 3
+ line 1: syntax error at "Z" missing SC
+ ...
+
+ Rule trace reporting is controlled by the value of the integer
+ [zz]traceOptionValue: when it is positive tracing is enabled,
+ otherwise it is disabled. Tracing during guess mode is controlled
+ by the value of the integer [zz]traceGuessOptionValue. When
+ it is positive AND [zz]traceOptionValue is positive rule trace
+ is reported in guess mode.
+
+ The values of [zz]traceOptionValue and [zz]traceGuessOptionValue
+ can be adjusted by subroutine calls listed below.
+
+ Depending on the presence or absence of the antlr -gd switch
+ the variable [zz]traceOptionValueDefault is set to 0 or 1. When
+ the parser is initialized or [zz]traceReset() is called the
+ value of [zz]traceOptionValueDefault is copied to [zz]traceOptionValue.
+ The value of [zz]traceGuessOptionValue is always initialzed to 1,
+ but, as noted earlier, nothing will be reported unless
+ [zz]traceOptionValue is also positive.
+
+ When the parser state is saved/restored the value of the trace
+ variables are also saved/restored. If a restore causes a change in
+ reporting behavior from on to off or vice versa this will be reported.
+
+ When the -gd option is selected, the macro "#define zzTRACE_RULES"
+ is added to appropriate output files.
+
+ C++ mode
+ --------
+ int traceOption(int delta)
+ int traceGuessOption(int delta)
+ void traceReset()
+ int traceOptionValueDefault
+
+ C mode
+ --------
+ int zzTraceOption(int delta)
+ int zzTraceGuessOption(int delta)
+ void zzTraceReset()
+ int zzTraceOptionValueDefault
+
+ The argument "delta" is added to the traceOptionValue. To
+ turn on trace when inside a particular rule one:
+
+ rule : <<traceOption(+1);>>
+ (
+ rest-of-rule
+ )
+ <<traceOption(-1);>>
+ ; /* fail clause */ <<traceOption(-1);>>
+
+ One can use the same idea to turn *off* tracing within a
+ rule by using a delta of (-1).
+
+ An improvement in the rule trace was suggested by Sramji
+ Ramanathan (ps@kumaran.com).
+
+#108. A Note on Deallocation of Variables Allocated in Guess Mode
+
+ NOTE
+ ------------------------------------------------------
+ This mechanism only works for heap allocated variables
+ ------------------------------------------------------
+
+ The rewrite of the trace provides the machinery necessary
+ to properly free variables or undo actions following a
+ failed guess.
+
+ The macro zzUSER_GUESS_HOOK(guessSeq,zzrv) is expanded
+ as part of the zzGUESS macro. When a guess is opened
+ the value of zzrv is 0. When a longjmp() is executed to
+ undo the guess, the value of zzrv will be 1.
+
+ The macro zzUSER_GUESS_DONE_HOOK(guessSeq) is expanded
+ as part of the zzGUESS_DONE macro. This is executed
+ whether the guess succeeds or fails as part of closing
+ the guess.
+
+ The guessSeq is a sequence number which is assigned to each
+ guess and is incremented by 1 for each guess which becomes
+ active. It is needed by the user to associate the start of
+ a guess with the failure and/or completion (closing) of a
+ guess.
+
+ Guesses are nested. They must be closed in the reverse
+ of the order that they are opened.
+
+ In order to free memory used by a variable during a guess
+ a user must write a routine which can be called to
+ register the variable along with the current guess sequence
+ number provided by the zzUSER_GUESS_HOOK macro. If the guess
+ fails, all variables tagged with the corresponding guess
+ sequence number should be released. This is ugly, but
+ it would require a major rewrite of antlr 1.33 to use
+ some mechanism other than setjmp()/longjmp().
+
+ The order of calls for a *successful* guess would be:
+
+ zzUSER_GUESS_HOOK(guessSeq,0);
+ zzUSER_GUESS_DONE_HOOK(guessSeq);
+
+ The order of calls for a *failed* guess would be:
+
+ zzUSER_GUESS_HOOK(guessSeq,0);
+ zzUSER_GUESS_HOOK(guessSeq,1);
+ zzUSER_GUESS_DONE_HOOK(guessSeq);
+
+ The default definitions of these macros are empty strings.
+
+ Here is an example in C++ mode. The zzUSER_GUESS_HOOK and
+ zzUSER_GUESS_DONE_HOOK macros and myGuessHook() routine
+ can be used without change in both C and C++ versions.
+
+ ----------------------------------------------------------------------
+ <<
+
+ #include "AToken.h"
+
+ typedef ANTLRCommonToken ANTLRToken;
+
+ #include "DLGLexer.h"
+
+ int main() {
+
+ {
+ DLGFileInput in(stdin);
+ DLGLexer lexer(&in,2000);
+ ANTLRTokenBuffer pipe(&lexer,1);
+ ANTLRCommonToken aToken;
+ P parser(&pipe);
+
+ lexer.setToken(&aToken);
+ parser.init();
+ parser.start();
+ };
+
+ fclose(stdin);
+ fclose(stdout);
+ return 0;
+ }
+
+ >>
+
+ <<
+ char *s=NULL;
+
+ #undef zzUSER_GUESS_HOOK
+ #define zzUSER_GUESS_HOOK(guessSeq,zzrv) myGuessHook(guessSeq,zzrv);
+ #undef zzUSER_GUESS_DONE_HOOK
+ #define zzUSER_GUESS_DONE_HOOK(guessSeq) myGuessHook(guessSeq,2);
+
+ void myGuessHook(int guessSeq,int zzrv) {
+ if (zzrv == 0) {
+ fprintf(stderr,"User hook: starting guess #%d\n",guessSeq);
+ } else if (zzrv == 1) {
+ free (s);
+ s=NULL;
+ fprintf(stderr,"User hook: failed guess #%d\n",guessSeq);
+ } else if (zzrv == 2) {
+ free (s);
+ s=NULL;
+ fprintf(stderr,"User hook: ending guess #%d\n",guessSeq);
+ };
+ }
+
+ >>
+
+ #token A "a"
+ #token "[\t \ \n]" <<skip();>>
+
+ class P {
+
+ start : (top)+
+ ;
+
+ top : (which) ? <<fprintf(stderr,"%s is a which\n",s); free(s); s=NULL; >>
+ | other <<fprintf(stderr,"%s is an other\n",s); free(s); s=NULL; >>
+ ; <<if (s != NULL) free(s); s=NULL; >>
+
+ which : which2
+ ;
+
+ which2 : which3
+ ;
+ which3
+ : (label)? <<fprintf(stderr,"%s is a label\n",s);>>
+ | (global)? <<fprintf(stderr,"%s is a global\n",s);>>
+ | (exclamation)? <<fprintf(stderr,"%s is an exclamation\n",s);>>
+ ;
+
+ label : <<s=strdup(LT(1)->getText());>> A ":" ;
+
+ global : <<s=strdup(LT(1)->getText());>> A "::" ;
+
+ exclamation : <<s=strdup(LT(1)->getText());>> A "!" ;
+
+ other : <<s=strdup(LT(1)->getText());>> "other" ;
+
+ }
+ ----------------------------------------------------------------------
+
+ This is a silly example, but illustrates the idea. For the input
+ "a ::" with tracing enabled the output begins:
+
+ ----------------------------------------------------------------------
+ enter rule "start" depth 1
+ enter rule "top" depth 2
+ User hook: starting guess #1
+ enter rule "which" depth 3 guessing
+ enter rule "which2" depth 4 guessing
+ enter rule "which3" depth 5 guessing
+ User hook: starting guess #2
+ enter rule "label" depth 6 guessing
+ guess failed
+ User hook: failed guess #2
+ guess done - returning to rule "which3" at depth 5 (guess mode continues
+ - an enclosing guess is still active)
+ User hook: ending guess #2
+ User hook: starting guess #3
+ enter rule "global" depth 6 guessing
+ exit rule "global" depth 6 guessing
+ guess done - returning to rule "which3" at depth 5 (guess mode continues
+ - an enclosing guess is still active)
+ User hook: ending guess #3
+ enter rule "global" depth 6 guessing
+ exit rule "global" depth 6 guessing
+ exit rule "which3" depth 5 guessing
+ exit rule "which2" depth 4 guessing
+ exit rule "which" depth 3 guessing
+ guess done - returning to rule "top" at depth 2 (guess mode ends)
+ User hook: ending guess #1
+ enter rule "which" depth 3
+ .....
+ ----------------------------------------------------------------------
+
+ Remember:
+
+ (a) Only init-actions are executed during guess mode.
+ (b) A rule can be invoked multiple times during guess mode.
+ (c) If the guess succeeds the rule will be called once more
+ without guess mode so that normal actions will be executed.
+ This means that the init-action might need to distinguish
+ between guess mode and non-guess mode using the variable
+ [zz]guessing.
+
+#101. (Changed in 1.33MR10) antlr -info command line switch
+
+ -info
+
+ p - extra predicate information in generated file
+
+ t - information about tnode use:
+ at the end of each rule in generated file
+ summary on stderr at end of program
+
+ m - monitor progress
+ prints name of each rule as it is started
+ flushes output at start of each rule
+
+ f - first/follow set information to stdout
+
+ 0 - no operation (added in 1.33MR11)
+
+ The options may be combined and may appear in any order.
+ For example:
+
+ antlr -info ptm -CC -gt -mrhoist on mygrammar.g
+
+#100a. (Changed in 1.33MR10) Predicate tree simplification
+
+ When the same predicates can be referenced in more than one
+ alternative of a block large predicate trees can be formed.
+
+ The difference that these optimizations make is so dramatic
+ that I have decided to use it even when -mrhoist is not selected.
+
+ Consider the following grammar:
+
+ start : ( all )* ;
+
+ all : a
+ | d
+ | e
+ | f
+ ;
+
+ a : c A B
+ | c A C
+ ;
+
+ c : <<AAA(LATEXT(2))>>?
+ ;
+
+ d : <<BBB(LATEXT(2))>>? B C
+ ;
+
+ e : <<CCC(LATEXT(2))>>? B C
+ ;
+
+ f : e X Y
+ ;
+
+ In rule "a" there is a reference to rule "c" in both alternatives.
+ The length of the predicate AAA is k=2 and it can be followed in
+ alternative 1 only by (A B) while in alternative 2 it can be
+ followed only by (A C). Thus they do not have identical context.
+
+ In rule "all" the alternatives which refer to rules "e" and "f" allow
+ elimination of the duplicate reference to predicate CCC.
+
+ The table below summarized the kind of simplification performed by
+ 1.33MR10. In the table, X and Y stand for single predicates
+ (not trees).
+
+ (OR X (OR Y (OR Z))) => (OR X Y Z)
+ (AND X (AND Y (AND Z))) => (AND X Y Z)
+
+ (OR X (... (OR X Y) ... )) => (OR X (... Y ... ))
+ (AND X (... (AND X Y) ... )) => (AND X (... Y ... ))
+ (OR X (... (AND X Y) ... )) => (OR X (... ... ))
+ (AND X (... (OR X Y) ... )) => (AND X (... ... ))
+
+ (AND X) => X
+ (OR X) => X
+
+ In a test with a complex grammar for a real application, a predicate
+ tree with six OR nodes and 12 leaves was reduced to "(OR X Y Z)".
+
+ In 1.33MR10 there is a greater effort to release memory used
+ by predicates once they are no longer in use.
+
+#100b. (Changed in 1.33MR10) Suppression of extra predicate tests
+
+ The following optimizations require that -mrhoist be selected.
+
+ It is relatively easy to optimize the code generated for predicate
+ gates when they are of the form:
+
+ (AND X Y Z ...)
+ or (OR X Y Z ...)
+
+ where X, Y, Z, and "..." represent individual predicates (leaves) not
+ predicate trees.
+
+ If the predicate is an AND the contexts of the X, Y, Z, etc. are
+ ANDed together to create a single Tree context for the group and
+ context tests for the individual predicates are suppressed:
+
+ --------------------------------------------------
+ Note: This was incorrect. The contexts should be
+ ORed together. This has been fixed. A more
+ complete description is available in item #152.
+ ---------------------------------------------------
+
+ Optimization 1: (AND X Y Z ...)
+
+ Suppose the context for Xtest is LA(1)==LP and the context for
+ Ytest is LA(1)==LP && LA(2)==ID.
+
+ Without the optimization the code would resemble:
+
+ if (lookaheadContext &&
+ !(LA(1)==LP && LA(1)==LP && LA(2)==ID) ||
+ ( (! LA(1)==LP || Xtest) &&
+ (! (LA(1)==LP || LA(2)==ID) || Xtest)
+ )) {...
+
+ With the -mrhoist optimization the code would resemble:
+
+ if (lookaheadContext &&
+ ! (LA(1)==LP && LA(2)==ID) || (Xtest && Ytest) {...
+
+ Optimization 2: (OR X Y Z ...) with identical contexts
+
+ Suppose the context for Xtest is LA(1)==ID and for Ytest
+ the context is also LA(1)==ID.
+
+ Without the optimization the code would resemble:
+
+ if (lookaheadContext &&
+ ! (LA(1)==ID || LA(1)==ID) ||
+ (LA(1)==ID && Xtest) ||
+ (LA(1)==ID && Ytest) {...
+
+ With the -mrhoist optimization the code would resemble:
+
+ if (lookaheadContext &&
+ (! LA(1)==ID) || (Xtest || Ytest) {...
+
+ Optimization 3: (OR X Y Z ...) with distinct contexts
+
+ Suppose the context for Xtest is LA(1)==ID and for Ytest
+ the context is LA(1)==LP.
+
+ Without the optimization the code would resemble:
+
+ if (lookaheadContext &&
+ ! (LA(1)==ID || LA(1)==LP) ||
+ (LA(1)==ID && Xtest) ||
+ (LA(1)==LP && Ytest) {...
+
+ With the -mrhoist optimization the code would resemble:
+
+ if (lookaheadContext &&
+ (zzpf=0,
+ (LA(1)==ID && (zzpf=1) && Xtest) ||
+ (LA(1)==LP && (zzpf=1) && Ytest) ||
+ !zzpf) {
+
+ These may appear to be of similar complexity at first,
+ but the non-optimized version contains two tests of each
+ context while the optimized version contains only one
+ such test, as well as eliminating some of the inverted
+ logic (" !(...) || ").
+
+ Optimization 4: Computation of predicate gate trees
+
+ When generating code for the gates of predicate expressions
+ antlr 1.33 vanilla uses a recursive procedure to generate
+ "&&" and "||" expressions for testing the lookahead. As each
+ layer of the predicate tree is exposed a new set of "&&" and
+ "||" expressions on the lookahead are generated. In many
+ cases the lookahead being tested has already been tested.
+
+ With -mrhoist a lookahead tree is computed for the entire
+ lookahead expression. This means that predicates with identical
+ context or context which is a subset of another predicate's
+ context disappear.
+
+ This is especially important for predicates formed by rules
+ like the following:
+
+ uppperCaseVowel : <<isUpperCase(LATEXT(1))>>? vowel;
+ vowel: : <<isVowel(LATEXT(1))>>? LETTERS;
+
+ These predicates are combined using AND since both must be
+ satisfied for rule upperCaseVowel. They have identical
+ context which makes this optimization very effective.
+
+ The affect of Items #100a and #100b together can be dramatic. In
+ a very large (but real world) grammar one particular predicate
+ expression was reduced from an (unreadable) 50 predicate leaves,
+ 195 LA(1) terms, and 5500 characters to an (easily comprehensible)
+ 3 predicate leaves (all different) and a *single* LA(1) term.
+
+#98. (Changed in 1.33MR10) Option "-info p"
+
+ When the user selects option "-info p" the program will generate
+ detailed information about predicates. If the user selects
+ "-mrhoist on" additional detail will be provided explaining
+ the promotion and suppression of predicates. The output is part
+ of the generated file and sandwiched between #if 0/#endif statements.
+
+ Consider the following k=1 grammar:
+
+ start : ( all ) * ;
+
+ all : ( a
+ | b
+ )
+ ;
+
+ a : c B
+ ;
+
+ c : <<LATEXT(1)>>?
+ | B
+ ;
+
+ b : <<LATEXT(1)>>? X
+ ;
+
+ Below is an excerpt of the output for rule "start" for the three
+ predicate options (off, on, and maintenance release style hoisting).
+
+ For those who do not wish to use the "-mrhoist on" option for code
+ generation the option can be used in a "diagnostic" mode to provide
+ valuable information:
+
+ a. where one should insert null actions to inhibit hoisting
+ b. a chain of rule references which shows where predicates are
+ being hoisted
+
+ ======================================================================
+ Example of "-info p" with "-mrhoist on"
+ ======================================================================
+ #if 0
+
+ Hoisting of predicate suppressed by alternative without predicate.
+ The alt without the predicate includes all cases where the
+ predicate is false.
+
+ WITH predicate: line 11 v36.g
+ WITHOUT predicate: line 12 v36.g
+
+ The context set for the predicate:
+
+ B
+
+ The lookahead set for alt WITHOUT the semantic predicate:
+
+ B
+
+ The predicate:
+
+ pred << LATEXT(1)>>? depth=k=1 rule c line 11 v36.g
+
+ set context:
+ B
+ tree context: null
+
+ Chain of referenced rules:
+
+ #0 in rule start (line 1 v36.g) to rule all
+ #1 in rule all (line 3 v36.g) to rule a
+ #2 in rule a (line 8 v36.g) to rule c
+ #3 in rule c (line 11 v36.g)
+
+ #endif
+ &&
+ #if 0
+
+ pred << LATEXT(1)>>? depth=k=1 rule b line 15 v36.g
+
+ set context:
+ X
+ tree context: null
+
+ #endif
+ ======================================================================
+ Example of "-info p" with the default -prc setting ( "-prc off")
+ ======================================================================
+ #if 0
+
+ OR
+ pred << LATEXT(1)>>? depth=k=1 rule c line 11 v36.g
+
+ set context:
+ nil
+ tree context: null
+
+ pred << LATEXT(1)>>? depth=k=1 rule b line 15 v36.g
+
+ set context:
+ nil
+ tree context: null
+
+ #endif
+ ======================================================================
+ Example of "-info p" with "-prc on" and "-mrhoist off"
+ ======================================================================
+ #if 0
+
+ OR
+ pred << LATEXT(1)>>? depth=k=1 rule c line 11 v36.g
+
+ set context:
+ B
+ tree context: null
+
+ pred << LATEXT(1)>>? depth=k=1 rule b line 15 v36.g
+
+ set context:
+ X
+ tree context: null
+
+ #endif
+ ======================================================================
+
+#60. (Changed in 1.33MR7) Major changes to exception handling
+
+ There were significant problems in the handling of exceptions
+ in 1.33 vanilla. The general problem is that it can only
+ process one level of exception handler. For example, a named
+ exception handler, an exception handler for an alternative, or
+ an exception for a subrule always went to the rule's exception
+ handler if there was no "catch" which matched the exception.
+
+ In 1.33MR7 the exception handlers properly "nest". If an
+ exception handler does not have a matching "catch" then the
+ nextmost outer exception handler is checked for an appropriate
+ "catch" clause, and so on until an exception handler with an
+ appropriate "catch" is found.
+
+ There are still undesirable features in the way exception
+ handlers are implemented, but I do not have time to fix them
+ at the moment:
+
+ The exception handlers for alternatives are outside the
+ block containing the alternative. This makes it impossible
+ to access variables declared in a block or to resume the
+ parse by "falling through". The parse can still be easily
+ resumed in other ways, but not in the most natural fashion.
+
+ This results in an inconsistentcy between named exception
+ handlers and exception handlers for alternatives. When
+ an exception handler for an alternative "falls through"
+ it goes to the nextmost outer handler - not the "normal
+ action".
+
+ A major difference between 1.33MR7 and 1.33 vanilla is
+ the default action after an exception is caught:
+
+ 1.33 Vanilla
+ ------------
+ In 1.33 vanilla the signal value is set to zero ("NoSignal")
+ and the code drops through to the code following the exception.
+ For named exception handlers this is the "normal action".
+ For alternative exception handlers this is the rule's handler.
+
+ 1.33MR7
+ -------
+ In 1.33MR7 the signal value is NOT automatically set to zero.
+
+ There are two cases:
+
+ For named exception handlers: if the signal value has been
+ set to zero the code drops through to the "normal action".
+
+ For all other cases the code branches to the nextmost outer
+ exception handler until it reaches the handler for the rule.
+
+ The following macros have been defined for convenience:
+
+ C/C++ Mode Name
+ --------------------
+ (zz)suppressSignal
+ set signal & return signal arg to 0 ("NoSignal")
+ (zz)setSignal(intValue)
+ set signal & return signal arg to some value
+ (zz)exportSignal
+ copy the signal value to the return signal arg
+
+ I'm not sure why PCCTS make a distinction between the local
+ signal value and the return signal argument, but I'm loathe
+ to change the code. The burden of copying the local signal
+ value to the return signal argument can be given to the
+ default signal handler, I suppose.
+
+#53. (Explanation for 1.33MR6) What happens after an exception is caught ?
+
+ The Book is silent about what happens after an exception
+ is caught.
+
+ The following code fragment prints "Error Action" followed
+ by "Normal Action".
+
+ test : Word ex:Number <<printf("Normal Action\n");>>
+ exception[ex]
+ catch NoViableAlt:
+ <<printf("Error Action\n");>>
+ ;
+
+ The reason for "Normal Action" is that the normal flow of the
+ program after a user-written exception handler is to "drop through".
+ In the case of an exception handler for a rule this results in
+ the exection of a "return" statement. In the case of an
+ exception handler attached to an alternative, rule, or token
+ this is the code that would have executed had there been no
+ exception.
+
+ The user can achieve the desired result by using a "return"
+ statement.
+
+ test : Word ex:Number <<printf("Normal Action\n");>>
+ exception[ex]
+ catch NoViableAlt:
+ <<printf("Error Action\n"); return;>>
+ ;
+
+ The most powerful mechanism for recovery from parse errors
+ in pccts is syntactic predicates because they provide
+ backtracking. Exceptions allow "return", "break",
+ "consumeUntil(...)", "goto _handler", "goto _fail", and
+ changing the _signal value.
+
+#41. (Added in 1.33MR6) antlr -stdout
+
+ Using "antlr -stdout ..." forces the text that would
+ normally go to the grammar.c or grammar.cpp file to
+ stdout.
+
+#40. (Added in 1.33MR6) antlr -tab to change tab stops
+
+ Using "antlr -tab number ..." changes the tab stops
+ for the grammar.c or grammar.cpp file. The number
+ must be between 0 and 8. Using 0 gives tab characters,
+ values between 1 and 8 give the appropriate number of
+ space characters.
+
+#34. (Added to 1.33MR1) Add public DLGLexerBase::set_line(int newValue)
+
+ Previously there was no public function for changing the line
+ number maintained by the lexer.
+
+#28. (Added to 1.33MR1) More control over DLG header
+
+ Version 1.33MR1 adds the following directives to PCCTS
+ for C++ mode:
+
+ #lexprefix <<source code>>
+
+ Adds source code to the DLGLexer.h file
+ after the #include "DLexerBase.h" but
+ before the start of the class definition.
+
+ #lexmember <<source code>>
+
+ Adds source code to the DLGLexer.h file
+ as part of the DLGLexer class body. It
+ appears immediately after the start of
+ the class and a "public: statement.
+
diff --git a/Source/Pccts/KNOWN_PROBLEMS.txt b/Source/Pccts/KNOWN_PROBLEMS.txt
new file mode 100644
index 0000000..5a9b22e
--- /dev/null
+++ b/Source/Pccts/KNOWN_PROBLEMS.txt
@@ -0,0 +1,241 @@
+
+ =======================================================
+ Known Problems In PCCTS - Last revised 14 November 1998
+ =======================================================
+
+#17. The dlg fix for handling characters up to 255 is incorrect.
+
+ See item #207.
+
+ Reported by Frank Hartmann.
+
+#16. A note about "&&" predicates (Mike Dimmick)
+
+ Mike Dimmick has pointed out a potential pitfall in the use of the
+ "&&" style predicate. Consider:
+
+ r0: (g)? => <<P>>? r1
+ | ...
+ ;
+ r1: A | B;
+
+ If the context guard g is not a subset of the lookahead context for r1
+ (in other words g is neither A nor B) then the code may execute r1
+ even when the lookahead context is not satisfied. This is an error
+ by the person coding the grammer, and the error should be reported to
+ the user, but it isn't. expect. Some examples I've run seem to
+ indicate that such an error actually results in the rule becoming
+ unreachable.
+
+ When g is properly coded the code is correct, the problem is when g
+ is not properly coded.
+
+ A second problem reported by Mike Dimmick is that the test for a
+ failed validation predicate is equivalent to a test on the predicate
+ along. In other words, if the "&&" has not been hoisted then it may
+ falsely report a validation error.
+
+#15. (Changed in MR23) Warning for LT(i), LATEXT(i) in token match actions
+
+ An bug (or at least an oddity) is that a reference to LT(1), LA(1),
+ or LATEXT(1) in an action which immediately follows a token match
+ in a rule refers to the token matched, not the token which is in
+ the lookahead buffer. Consider:
+
+ r : abc <<action alpha>> D <<action beta>> E;
+
+ In this case LT(1) in action alpha will refer to the next token in
+ the lookahead buffer ("D"), but LT(1) in action beta will refer to
+ the token matched by D - the preceding token.
+
+ A warning has been added which warns users about this when an action
+ following a token match contains a reference to LT(1), LA(1), or LATEXT(1).
+
+ This behavior should be changed, but it appears in too many programs
+ now. Another problem, perhaps more significant, is that the obvious
+ fix (moving the consume() call to before the action) could change the
+ order in which input is requested and output appears in existing programs.
+
+ This problem was reported, along with a fix by Benjamin Mandel
+ (beny@sd.co.il). However, I felt that changing the behavior was too
+ dangerous for existing code.
+
+#14. Parsing bug in dlg
+
+ THM: I have been unable to reproduce this problem.
+
+ Reported by Rick Howard Mijenix Corporation (rickh@mijenix.com).
+
+ The regular expression parser (in rexpr.c) fails while
+ trying to parse the following regular expression:
+
+ {[a-zA-Z]:}(\\\\[a-zA-Z0-9]*)+
+
+ See my comment in the following excerpt from rexpr.c:
+
+ /*
+ * <regExpr> ::= <andExpr> ( '|' {<andExpr>} )*
+ *
+ * Return -1 if syntax error
+ * Return 0 if none found
+ * Return 1 if a regExrp was found
+ */
+ static
+ regExpr(g)
+ GraphPtr g;
+ {
+ Graph g1, g2;
+
+ if ( andExpr(&g1) == -1 )
+ {
+ return -1;
+ }
+
+ while ( token == '|' )
+ {
+ int a;
+ next();
+ a = andExpr(&g2);
+ if ( a == -1 ) return -1; /* syntax error below */
+ else if ( !a ) return 1; /* empty alternative */
+ g1 = BuildNFA_AorB(g1, g2);
+ }
+
+ if ( token!='\0' ) return -1;
+ *****
+ ***** It appears to fail here becuause token is 125 - the closing '}'
+ ***** If I change it to:
+ ***** if ( token!='\0' && token!='}' && token!= ')' ) return -1;
+ *****
+ ***** It succeeds, but I'm not sure this is the corrrect approach.
+ *****
+ *g = g1;
+ return 1;
+ }
+
+#13. dlg reports an invalid range for: [\0x00-\0xff]
+
+ Diagnosed by Piotr Eljasiak (eljasiak@no-spam.zt.gdansk.tpsa.pl):
+
+ Fixed in MR16.
+
+#12. Strings containing comment actions
+
+ Sequences that looked like C style comments appearing in string
+ literals are improperly parsed by antlr/dlg.
+
+ << fprintf(out," /* obsolete */ ");
+
+ For this case use:
+
+ << fprintf(out," \/\* obsolete \*\/ ");
+
+ Reported by K.J. Cummings (cummings@peritus.com).
+
+#11. User hook for deallocation of variables on guess fail
+
+ The mechanism outlined in Item #108 works only for
+ heap allocated variables.
+
+#10. Label re-initialization in ( X {y:Y} )*
+
+ If a label assignment is optional and appears in a
+ (...)* or (...)+ block it will not be reset to NULL
+ when it is skipped by a subsequent iteration.
+
+ Consider the example:
+
+ ( X { y:Y })* Z
+
+ with input:
+
+ X Y X Z
+
+ The first time through the block Y will be matched and
+ y will be set to point to the token. On the second
+ iteration of the (...)* block there is no match for Y.
+ But y will not be reset to NULL, as the user might
+ expect, it will contain a reference to the Y that was
+ matched in the first iteration.
+
+ The work-around is to manually reset y:
+
+ ( X << y = NULL; >> { y:Y } )* Z
+
+ or
+
+ ( X ( y:Y | << y = NULL; >> /* epsilon */ ) )* Z
+
+ Reported by Jeff Vincent (JVincent@novell.com).
+
+#9. PCCTAST.h PCCTSAST::setType() is a noop
+
+#8. #tokdefs with ~Token and .
+
+ THM: I have been unable to reproduce this problem.
+
+ When antlr uses #tokdefs to define tokens the fields of
+ #errclass and #tokclass do not get properly defined.
+ When it subsequently attempts to take the complement of
+ the set of tokens (using ~Token or .) it can refer to
+ tokens which don't have names, generating a fatal error.
+
+#7. DLG crashes on some invalid inputs
+
+ THM: In MR20 have fixed the most common cases.
+
+ The following token defintion will cause DLG to crash.
+
+ #token "()"
+
+ Reported by Mengue Olivier (dolmen@bigfoot.com).
+
+#6. On MS systems \n\r is treated as two new lines
+
+ Fixed.
+
+#5. Token expressions in #tokclass
+
+ #errclass does not support TOK1..TOK2 or ~TOK syntax.
+ #tokclass does not support ~TOKEN syntax
+
+ A workaround for #errclass TOK1..TOK2 is to use a
+ #tokclass.
+
+ Reported by Dave Watola (dwatola@amtsun.jpl.nasa.gov)
+
+#4. A #tokdef must appear "early" in the grammar file.
+
+ The "early" section of the grammar file is the only
+ place where the following directives may appear:
+
+ #header
+ #first
+ #tokdefs
+ #parser
+
+ Any other kind of statement signifiies the end of the
+ "early" section.
+
+#3. Use of PURIFY macro for C++ mode
+
+ Item #93 of the CHANGES_FROM_1.33 describes the use of
+ the PURIFY macro to zero arguments to be passed by
+ upward inheritance.
+
+ #define PURIFY(r, s) memset((char *) &(r), '\0', (s));
+
+ This may not be the right thing to do for C++ objects that
+ have constructors. Reported by Bonny Rais (bonny@werple.net.au).
+
+ For those cases one should #define PURIFY to be an empty macro
+ in the #header or #first actions.
+
+#2. Fixed in 1.33MR10 - See CHANGES_FROM_1.33 Item #80.
+
+#1. The quality of support for systems with 8.3 file names leaves
+ much to be desired. Since the kit is distributed using the
+ long file names and the make file uses long file names it requires
+ some effort to generate. This will probably not be changed due
+ to the large number of systems already written using the long
+ file names.
diff --git a/Source/Pccts/MPW_Read_Me b/Source/Pccts/MPW_Read_Me
new file mode 100644
index 0000000..70a9d1b
--- /dev/null
+++ b/Source/Pccts/MPW_Read_Me
@@ -0,0 +1,21 @@
+
+1. You can control the creator type of generated files by changing a value of
+ #if control statement.
+
+
+ pccts:h:pcctscfg.h
+
+ line 225-231
+
+ #if 0
+ #define MAC_FILE_CREATOR 'MPS ' /* MPW Text files */
+ #endif
+ #if 0
+ #define MAC_FILE_CREATOR 'KAHL' /* THINK C/Symantec C++ Text files */
+ #endif
+ #if 0
+ #define MAC_FILE_CREATOR 'CWIE' /* Metrowerks C/C++ Text files */
+ #endif
+
+2. If you want to build 68K version. You must convert all source files to Macintosh
+ format before compile.
diff --git a/Source/Pccts/NOTES.bcc b/Source/Pccts/NOTES.bcc
new file mode 100644
index 0000000..1ac05b1
--- /dev/null
+++ b/Source/Pccts/NOTES.bcc
@@ -0,0 +1,184 @@
+March 95
+Version 1.32 of pccts
+
+At the moment this file is available via anonymous FTP at
+
+ Node: marvin.ecn.purdue.edu
+ File: pub/pccts/1.32/NOTES.BCC
+
+Mail corrections or additions to David Seidel <71333.1575@compuserve.com>
+===============================================================================
+Notes on Building PCCTS 1.32 with Borland C++
+
+David Seidel, Innovative Data Concepts Incorporated
+CompuServe: 71333,1575
+Internet: 71333.1575@compuserve.com
+ dseidel@delphi.com
+
+I have gotten ANTLR and DLG to succesfully build with BCC 4.0, but have found
+from experience that ANTLR, in particular, is likely to run out of memory
+with grammars over a certain size, or with larger values for the -k and -ck
+options. Now that BCC 4.02 and the new Borland Power Pack for DOS is now
+available, I feel that there is no excuse not to build these tools as
+32-bit executables, as they ought to be.
+
+For people without the Power Pack, the makefiles below should be fairly easily
+modified to build 16-bit real-mode executables, but I don't really recommend
+it. As an alternative, you might consider the highly regarded DJGPP compiler
+(a DOS port of the Gnu GCC compiler, with a DOS extender included). Hopefully
+some other PCCTS who has DJGPP can provode whatever advice is necessary. The
+Watcom compiler is also an excellent possibility (albeit a commercial one),
+and I hope to make available Watcom makefiles in the near future.
+
+Here are the makefiles I am using. Both makefiles use a compiler configuration
+file that contains compiler switches such as optimization settings. I call
+this file bor32.cfg and keep a copy in both the ANTLR and DLG subdirectories.
+
+==== File: bor32.cfg (cut here) ===============================================
+-w-
+-RT-
+-x-
+-N-
+-k-
+-d
+-O2-e-l
+-Z
+-D__STDC__=1
+==== End of file bor32.cfg (cut here) =========================================
+
+==== File: antlr\bor32.mak (cut here) =========================================
+#
+# ANTLR 1.32 Makefile for Borland C++ 4.02 with DPMI 32-bit DOS extender by
+# David Seidel
+# Innovative Data Concepts Incorporated
+# 71333.1575@compuserve.com (or) dseidel@delphi.com
+#
+# Notes: 1. Compiler switches (optimization etc.) are contained in the
+# file bor32.cfg.
+# 2. This makefile requires Borland C++ 4.02 or greater with
+# the DOS Power Pack add-on package.
+# 3. Change the BCCDIR macro below to the topmost directory in
+# which BCC is installed on your system.
+#
+
+BCCDIR = d:\bc4
+CC = bcc32
+SET = ..\support\set
+PCCTS_H = ..\h
+ANTLR = ..\bin\antlr
+DLG = ..\bin\dlg
+CFLAGS = -I$(BCCDIR)\include -I. -I$(SET) -I$(PCCTS_H) -DUSER_ZZSYN \
+ +bor32.cfg
+LIBS = dpmi32 cw32
+OBJ_EXT = obj
+OBJS = antlr.obj scan.obj err.obj bits.obj build.obj fset2.obj fset.obj \
+ gen.obj globals.obj hash.obj lex.obj main.obj misc.obj pred.obj dialog.obj \
+ set.obj
+
+.c.obj:
+ $(CC) -c $(CFLAGS) {$&.c }
+
+antlr.exe: $(OBJS)
+ tlink32 @&&|
+-Tpe -ax -c -s -L$(BCCDIR)\lib +
+$(BCCDIR)\lib\c0x32 $**
+$@
+
+$(LIBS)
+;
+|
+ copy *.exe ..\bin
+
+
+# *********** Target list of PC machines ***********
+#
+# Don't worry about the ambiguity messages coming from antlr
+# for making antlr.c etc... [should be 10 of them, I think]
+#
+
+# leave this commented out for initial build!
+#antlr.c stdpccts.h parser.dlg tokens.h err.c : antlr.g
+# $(ANTLR) antlr.g
+
+antlr.$(OBJ_EXT): antlr.c mode.h tokens.h
+
+scan.$(OBJ_EXT): scan.c mode.h tokens.h
+
+# leave this commented out for initial build!
+#scan.c mode.h: parser.dlg
+# $(DLG) -C2 parser.dlg scan.c
+
+set.$(OBJ_EXT): $(SET)\set.c
+ $(CC) -c $(CFLAGS) $(SET)\set.c
+
+==== End of file antlr\bor32.mak (cut here) ===================================
+
+==== File: dlg\bor32.mak (cut here) ===========================================
+#
+# DLG 1.32 Makefile for Borland C++ 4.02 with DPMI 32-bit DOS extender by
+# David Seidel
+# Innovative Data Concepts Incorporated
+# 71333.1575@compuserve.com (or) dseidel@delphi.com
+#
+# Notes: 1. Compiler switches (optimization etc.) are contained in the
+# file bor32.cfg.
+# 2. This makefile requires Borland C++ 4.02 or greater with
+# the DOS Power Pack add-on package.
+# 3. Change the BCCDIR macro below to the topmost directory in
+# which BCC is installed on your system.
+#
+
+
+BCCDIR = d:\bc4
+CC = bcc32
+SET = ..\support\set
+PCCTS_H = ..\h
+ANTLR = ..\bin\antlr
+DLG = ..\bin\dlg
+CFLAGS = -I$(BCCDIR)\include -I. -I$(SET) -I$(PCCTS_H) -DUSER_ZZSYN \
+ +bor32.cfg
+LIBS = dpmi32 cw32
+OBJ_EXT = obj
+OBJS = dlg_p.obj dlg_a.obj main.obj err.obj support.obj \
+ output.obj relabel.obj automata.obj set.obj
+
+.c.obj:
+ $(CC) -c $(CFLAGS) {$&.c }
+
+dlg.exe : $(OBJS)
+ tlink32 @&&|
+-Tpe -ax -c -s -L$(BCCDIR)\lib +
+c0x32 $**
+$@
+
+$(LIBS)
+;
+|
+ copy *.exe ..\bin
+
+dlg_p.obj: dlg_p.c
+
+dlg_a.obj: dlg_a.c
+
+main.obj: main.c
+
+err.obj: err.c
+
+support.obj: support.c
+
+output.obj: output.c
+
+relabel.obj: relabel.c
+
+automata.obj: automata.c
+
+set.$(OBJ_EXT): $(SET)\set.c
+ $(CC) -c $(CFLAGS) $(SET)\set.c
+
+==== End of file dlg\bor32.mak (cut here) =====================================
+
+
+
+
+
+
diff --git a/Source/Pccts/NOTES.msvc b/Source/Pccts/NOTES.msvc
new file mode 100644
index 0000000..86f8ed6
--- /dev/null
+++ b/Source/Pccts/NOTES.msvc
@@ -0,0 +1,189 @@
+
+ Microsoft Visual C Stuff
+
+
+[Tom Moog 2-Oct-98
+
+ Users of Microsoft Visual C++ should download a separate
+ ready-to-run zip file from my web site. It contains
+ binaries, static library, and a sample project.
+]
+
+[
+ Two notes added by Tom Moog 23-Sep-97. I believe the *.dsp and
+ *.mak files that were once at the end of this file are now obsolete.
+
+ The following MSVC .dsp and .mak files for pccts and sorcerer
+ were contributed by Stanislaw Bochnak (S.Bochnak@microtool.com.pl)
+ and Jeff Vincent (jvincent@novell.com)
+
+ PCCTS Distribution Kit
+ ----------------------
+ pccts/antlr/AntlrMSVC50.dsp
+ pccts/antlr/AntlrMSVC50.mak
+
+ pccts/dlg/DlgMSVC50.dsp
+ pccts/dlg/DlgMSVC50.mak
+
+ pccts/support/genmk/watgenmk.mak
+ pccts/support/msvc.dsp
+
+ Sorcerer Distribution Kit
+ -------------------------
+ pccts/sorcerer/SorcererMSVC50.dsp
+ pccts/sorcerer/SorcererMSVC50.mak
+
+ pccts/sorcerer/lib/msvc.dsp
+
+ I do not have an MS based computer. If you discover problems
+ please report them so as to save trouble for others in the future.
+]
+
+[
+ Modified by Terence Parr (September 1995) to change .C to .cpp
+]
+
+[
+ This file contains notes on MSVC for Windows NT console execs by Dave
+ Seidel and an explanation of flags etc.. by John Hall; good luck,
+ Terence
+]
+
+===============================================================================
+Date: Sat, 31 Dec 1994 11:40:36 -0500 (EST)
+From: David Seidel <75342.2034@compuserve.com>
+
+I've succesfully build 1.31b3 with djgpp for DOS and MSVC 2.0 for Windows
+NT. The only (minor) problem I had was that GNU make (version 3.71, in the
+djgpp port) complained about "multiple targets" in both the antlr and dlg
+makefiles. I got around the error by, in each makefile, commenting out the
+$(SRC) dependency, for example:
+
+ antlr: $(OBJ) #$(SRC)
+
+I don't know why this is happenning, since you haven't changed that part of
+the makefile at all, and I think this used to work ok...
+
+Here are the makefiles I built from within the MSVC 2.0 environment for antlr
+and dlg and Windows NT console executables. Please feel free to pass them
+on. Of course, as soon as 1.31 "goes gold", I will send you nice new
+binaries. I'm not going to bother to keep doing both Borland and djgpp for
+DOS however. Instead, I'll just keep the djgpp version up to date and also
+provide WinNT binaries.
+
+Dave
+===============================================================================
+
+ How to port PCCTS 1.10 (and 1.32 hopefully) to Visual C++
+
+ By
+
+ John Hall <jhall@ivy.wpi.edu>
+
+Here is how to compile an ANTLR grammar in Visual C++. These steps
+describe how to have your ANTLR grammar parse the input file the user
+selects when they choose File Open in your Windows application. (Even
+if you aren't using Visual C++, the steps should be portable enough to
+other compilers.)
+
+ * Make sure that ANTLR and DLG generate ANSI code (use the -ga
+ switch).
+
+ * Set the following compiler flags in Visual C++ (these are in the
+ Memory Model category of the compiler options in the Project
+ Options menu):
+
+ FLAG MEANING
+ ==== ==============================================================
+ /AL Large memory model (multiple data segments; data items must be
+ smaller than 64K).
+
+ /Gtn Allocates all items whose size is greater than or equal to n
+ in a new data segment. (I let n be 256: /Gt256.)
+
+ /Gx- All references to data items are done with far addressing in
+ case they are placed in a far segment.
+
+ * Add the following member variable to the attributes section of your
+ derived CDocument class (you will need to make sure you also
+ include stdio.h):
+
+ FILE *fp;
+
+ * Add the following method to your derived CDocument class:
+
+ BOOL CAppDoc::OnOpenDocument(const char* pszPathName)
+ {
+ // Call CDocument's OnOpenDocument to do housekeeping for us
+ // DON'T add anything to the loading section of Serialize
+ if (!CDocument::OnOpenDocument(pszPathName))
+ return FALSE;
+
+ // Open input file
+ if ((fp = fopen(pszPathName, "r")) == NULL)
+ return FALSE;
+
+ // Parse input file
+ ANTLR(start(), fp);
+
+ // Close input file
+ fclose(fp);
+ return TRUE;
+ }
+
+ (Note: additional code may be necessary, depending on your parser.
+ For example, if your parser uses PCCTS's symbol table library, you
+ will need to insert calls to zzs_init and zzs_done.)
+
+ * Compile the generated C files as C++ files. (I renamed the files
+ to have a .CPP extension to fool Visual C++ into thinking they were
+ C++ files. One might also use the /Tp switch, but that switch
+ requires you separately include the filename.) [I used this step
+ as an easy out for all the external linking errors I was getting
+ that I couldn't fix by declaring things extern "C".]
+
+ * Make sure the __STDC__ portion of the generated files gets
+ compiled. (Either define __STDC__ yourself or else change all
+ occurrences of __STDC__ to __cplusplus in the generated files. You
+ can define __STDC__ in the Preprocessor category of the compiler
+ options.)
+
+ ================================================================
+ = Note 23-Sep-97: This is probably not necessary any more. =
+ = With 1.33MRxxx the use of __STDC__ was replaced with the =
+ = macro __USE_PROTOS to control the compilation of prototypes. =
+ ================================================================
+
+That last step is important for Visual C++, but may not apply to other
+compilers. For C++ compilers, whether __STDC__ is defined is
+implementation dependent (ARM, page 379). Apparently, Visual C++ does
+not to define it; it also does not support "old style" C function
+definitions (which is okay, according to page 404 of the ARM). Those
+two things together caused problems when trying to port the code.
+When it saw this:
+
+#ifdef __STDC__
+void
+globals(AST **_root)
+#else
+globals(_root)
+AST **_root;
+#endif
+
+it skipped the __STDC__ section and tried to process the "old style"
+function definition, where it choked.
+
+When you finally get your parser to compile and link without error,
+you may get General Protection Fault errors at run time. The problem
+I had was that a NULL was passed to a variable argument function
+without an explicit cast. The function grabbed a pointer (32-bits)
+off the stack using va_arg, but the NULL was passed silently as the
+integer 0 (16 bits), making the resulting pointer was invalid. (This
+was in PCCTS's sample C parser.)
+
+There is one other thing I might suggest to help you avoid a run-time
+error. Make sure you redefine the default error reporting function,
+zzsyn. To do this, put "#define USER_ZZSYN" in your #header section
+and put your own zzsyn somewhere. You can then pop up a MessageBox or
+print the error to some output window.
+===============================================================================
diff --git a/Source/Pccts/README b/Source/Pccts/README
new file mode 100644
index 0000000..d089b63
--- /dev/null
+++ b/Source/Pccts/README
@@ -0,0 +1,159 @@
+
+ Parr Research Corporation
+ with
+ Purdue University Electrical Engineering
+ and
+ University of Minnesota, AHPCRC
+
+ Terence Parr
+ Russell Quong
+ Will Cohen
+ Hank Dietz
+
+
+A central place for information about PCCTS 1.33 is:
+
+ http://www.polhode.com/pccts.html
+
+The maintenance release is available from:
+
+ http://www.polhode.com/pccts133mr.zip
+
+There is a ready-to-run version for win32 for Microsoft Visual Studio
+at the same site. It is available from:
+
+ http://www.polhode.com/win32.zip
+
+New users should visit http://www.polhode.com/pccts.html in
+order to get the following document:
+
+ "Notes For New Users of PCCTS"
+
+This is a Postscript file of about 40 pages which is extremely
+useful for someone starting out. It is a based on 1.33mr21
+
+When you have a little more experience, be sure to review the
+following documents in the distribution kit:
+
+ CHANGES_FROM_133.txt
+ CHANGES_FROM_133_BEFORE_MR13.txt
+ KNOWN_PROBLEMS.txt
+
+-------------------------------------------------------------------------
+ INSTALLATION (Unix)
+-------------------------------------------------------------------------
+0. Download http://www.polhode.com/pccts133mr.zip
+
+1. Unzip the distribution kit to your preferred location.
+ If there are newline problems try using zip -a ...
+
+2. cd to the main pccts directory.
+
+3. make
+
+ This will create:
+
+ antlr
+ dlg
+ sorcerer
+ genmk
+
+4. Copy to /usr/local/bin or /usr/local/bin if you like. If you
+ don't wish to then add pccts/bin to your path.
+
+5. To get an up-to-date list of program options execute the
+ program with no command line options. To get up-to-date
+ documentation read CHANGES_FROM_133*.txt and KNOWN_PROBLEMS.txt
+ at:
+
+ http://www.polhode.com/pccts.html
+
+6. You need not create a library. The makefile created by genmk
+ assumes that the files are not part of a library.
+
+ If you wish to create a library from elements of pccts/h:
+
+ If the first letter of the filename is lowercase (uppercase) it is
+ related to the code generated using the pccts C mode (C++ mode).
+ Some of the .c and .cpp files in the h directory are not meant to
+ be placed in a library and will not compile because they are meant
+ to be #include in pccts generated files which are grammar specific.
+
+ For C++ users place the following elements in the library:
+
+ AParser.cpp
+ ASTBase.cpp
+ ATokenBuffer.cpp
+ BufFileInput.cpp (optional)
+ DLexerBase.cpp
+ PCCTSAST.cpp
+ SList.cpp
+
+-------------------------------------------------------------------------
+ INSTALLATION (Win32)
+-------------------------------------------------------------------------
+
+I've tried to keep the win32 kit to the minimum necessary to get
+up and running. The complete kit contains additional information
+(some historical), source code, and DevStudio projects for
+rebuilding pccts from the source code.
+
+The kit is now distributed with both MSVC 5 and MSVC6 style projects.
+
+0. Download http://www.polhode.com/win32.zip.
+
+ You may also wish to download:
+
+ http://www.polhode.com/CHANGES_FROM_133.txt
+ http://www.polhode.com/CHANGES_FROM_133_BEFORE_MR13.txt
+ http://www.polhode.com/KNOWN_PROBLEMS.txt
+
+1. Unzip the distribution kit to your preferred location.
+
+ This will create:
+
+ a pccts directory tree
+ pccts/bin/*.exe
+ pccts/lib/*.lib
+ pccts/h/*
+ sorcerer/lib/*
+ sorcerer/h/*
+
+ an example directory tree
+ pccts\example\calcAST\*
+ pccts\example\simple\*
+
+2. Define the environment variable PCCTS to point to the main
+ pccts directory.
+
+3. Try building the simple project: pccts\example\simple\simple50.dsw
+ or simple60.dsw.
+
+4. Try building the complex project: pccts\example\calcAST\calcAST50.dsw
+ or calcAST60.dsw.
+
+-------------------------------------------------------------------------
+ INSTALLATION (DEC/VMS)
+-------------------------------------------------------------------------
+
+DEC/VMS support added by Piéronne Jean-François (jfp@altavista.net)
+
+0. Download http://www.polhode.com/pccts133mr.zip
+
+1. Unzip the distribution kit to your preferred location.
+
+2. set default to the main pccts directory.
+
+3. @makefile.vms
+
+ This will create in directory [.bin]:
+
+ antlr.exe
+ dlg.exe
+ sorcerer.exe
+ genmk.exe
+
+5. To get an up-to-date list of program options execute the
+ program with no command line options. To get up-to-date
+ documentation read CHANGES_FROM_133*.txt and KNOWN_PROBLEMS.txt
+ at http://www.polhode.com/pccts.html.
diff --git a/Source/Pccts/RIGHTS b/Source/Pccts/RIGHTS
new file mode 100644
index 0000000..9db175f
--- /dev/null
+++ b/Source/Pccts/RIGHTS
@@ -0,0 +1,26 @@
+
+SOFTWARE RIGHTS
+
+We reserve no LEGAL rights to the Purdue Compiler Construction Tool
+Set (PCCTS) -- PCCTS is in the public domain. An individual or
+company may do whatever they wish with source code distributed with
+PCCTS or the code generated by PCCTS, including the incorporation of
+PCCTS, or its output, into commerical software.
+
+We encourage users to develop software with PCCTS. However, we do ask
+that credit is given to us for developing PCCTS. By "credit", we mean
+that if you incorporate our source code into one of your programs
+(commercial product, research project, or otherwise) that you
+acknowledge this fact somewhere in the documentation, research report,
+etc... If you like PCCTS and have developed a nice tool with the
+output, please mention that you developed it using PCCTS. In
+addition, we ask that this header remain intact in our source code.
+As long as these guidelines are kept, we expect to continue enhancing
+this system and expect to make other tools available as they are
+completed.
+
+ANTLR 1.33
+Terence Parr
+Parr Research Corporation
+with Purdue University and AHPCRC, University of Minnesota
+1989-1995
diff --git a/Source/Pccts/antlr/AntlrMS.mak b/Source/Pccts/antlr/AntlrMS.mak
new file mode 100644
index 0000000..7342d99
--- /dev/null
+++ b/Source/Pccts/antlr/AntlrMS.mak
@@ -0,0 +1,233 @@
+# PCCTS directory
+
+# You will need to set the LIB variable similar to this.
+# LIB="C:/Program Files/Microsoft Visual Studio .NET 2003/Vc7/lib;c:/Microsoft Visual Studio .NET 2003/Vc7/PlatformSDK/Lib"
+
+# PCCTS_HOME=<your PCCTS_HOME>
+PCCTS_HOME=$(WORKSPACE)\Tools\CCode\Source\Pccts
+ANTLR_SRC=$(PCCTS_HOME)\antlr
+PCCTS_H=$(PCCTS_HOME)\h
+
+
+# Support directories
+SET=$(PCCTS_HOME)\support\set
+
+
+# Compiler stuff
+CC = cl
+CFLAGS = /nologo -I "." -I "$(PCCTS_H)" -I "$(SET)" -D "USER_ZZSYN" -D "PC" \
+ -D "ZZLEXBUFSIZE=65536" /D "LONGFILENAMES" /Zi /W3 -D__USE_PROTOS /wd4700
+
+ANTLR_OBJS = antlr.obj scan.obj err.obj bits.obj build.obj fset2.obj \
+ fset.obj gen.obj globals.obj hash.obj lex.obj main.obj \
+ misc.obj pred.obj egman.obj mrhoist.obj fcache.obj
+
+SUPPORT_OBJS = set.obj
+
+# Dependencies
+
+$(WORKSPACE)\Tools\bin\antlr.exe: $(ANTLR_OBJS) $(SUPPORT_OBJS)
+ $(CC) $(CFLAGS) -o antlr.exe $(ANTLR_OBJS) $(SUPPORT_OBJS)
+ del *.obj
+ move antlr.exe $(WORKSPACE)\Tools\bin
+
+
+antlr.obj: $(ANTLR_SRC)\antlr.c \
+ $(PCCTS_H)\antlr.h \
+ $(PCCTS_H)\config.h \
+ $(PCCTS_H)\dlgdef.h \
+ $(SET)\set.h \
+ $(ANTLR_SRC)\generic.h \
+ $(ANTLR_SRC)\hash.h \
+ $(ANTLR_SRC)\mode.h \
+ $(ANTLR_SRC)\proto.h \
+ $(ANTLR_SRC)\syn.h \
+ $(ANTLR_SRC)\tokens.h \
+
+ $(CC) -c $(CFLAGS) $(ANTLR_SRC)\antlr.c
+
+scan.obj: $(ANTLR_SRC)\scan.c \
+ $(PCCTS_H)\antlr.h \
+ $(PCCTS_H)\config.h \
+ $(PCCTS_H)\dlgauto.h \
+ $(PCCTS_H)\dlgdef.h \
+ $(SET)\set.h \
+ $(ANTLR_SRC)\generic.h \
+ $(ANTLR_SRC)\hash.h \
+ $(ANTLR_SRC)\mode.h \
+ $(ANTLR_SRC)\proto.h \
+ $(ANTLR_SRC)\syn.h \
+ $(ANTLR_SRC)\tokens.h \
+
+ $(CC) -c $(CFLAGS) $(ANTLR_SRC)\scan.c
+
+err.obj: $(ANTLR_SRC)\err.c \
+ $(PCCTS_H)\antlr.h \
+ $(PCCTS_H)\config.h \
+ $(PCCTS_H)\dlgdef.h \
+ $(PCCTS_H)\err.h \
+ $(SET)\set.h \
+ $(ANTLR_SRC)\generic.h \
+ $(ANTLR_SRC)\hash.h \
+ $(ANTLR_SRC)\proto.h \
+ $(ANTLR_SRC)\syn.h \
+ $(ANTLR_SRC)\tokens.h \
+
+ $(CC) -c $(CFLAGS) $(ANTLR_SRC)\err.c
+
+bits.obj: $(ANTLR_SRC)\bits.c \
+ $(PCCTS_H)\config.h \
+ $(PCCTS_H)\dlgdef.h \
+ $(SET)\set.h \
+ $(ANTLR_SRC)\generic.h \
+ $(ANTLR_SRC)\hash.h \
+ $(ANTLR_SRC)\proto.h \
+ $(ANTLR_SRC)\syn.h \
+
+ $(CC) -c $(CFLAGS) $(ANTLR_SRC)\bits.c
+
+build.obj: $(ANTLR_SRC)\build.c \
+ $(PCCTS_H)\config.h \
+ $(PCCTS_H)\dlgdef.h \
+ $(SET)\set.h \
+ $(ANTLR_SRC)\generic.h \
+ $(ANTLR_SRC)\hash.h \
+ $(ANTLR_SRC)\proto.h \
+ $(ANTLR_SRC)\syn.h \
+
+ $(CC) -c $(CFLAGS) $(ANTLR_SRC)\build.c
+
+fset2.obj: $(ANTLR_SRC)\fset2.c \
+ $(PCCTS_H)\config.h \
+ $(PCCTS_H)\dlgdef.h \
+ $(SET)\set.h \
+ $(ANTLR_SRC)\generic.h \
+ $(ANTLR_SRC)\hash.h \
+ $(ANTLR_SRC)\proto.h \
+ $(ANTLR_SRC)\syn.h \
+
+ $(CC) -c $(CFLAGS) $(ANTLR_SRC)\fset2.c
+
+fset.obj: $(ANTLR_SRC)\fset.c \
+ $(PCCTS_H)\config.h \
+ $(PCCTS_H)\dlgdef.h \
+ $(SET)\set.h \
+ $(ANTLR_SRC)\generic.h \
+ $(ANTLR_SRC)\hash.h \
+ $(ANTLR_SRC)\proto.h \
+ $(ANTLR_SRC)\syn.h \
+
+ $(CC) -c $(CFLAGS) $(ANTLR_SRC)\fset.c
+
+gen.obj: $(ANTLR_SRC)\gen.c \
+ $(PCCTS_H)\config.h \
+ $(PCCTS_H)\dlgdef.h \
+ $(SET)\set.h \
+ $(ANTLR_SRC)\generic.h \
+ $(ANTLR_SRC)\hash.h \
+ $(ANTLR_SRC)\proto.h \
+ $(ANTLR_SRC)\syn.h \
+
+ $(CC) -c $(CFLAGS) $(ANTLR_SRC)\gen.c
+
+globals.obj: $(ANTLR_SRC)\globals.c \
+ $(PCCTS_H)\config.h \
+ $(SET)\set.h \
+ $(ANTLR_SRC)\generic.h \
+ $(ANTLR_SRC)\hash.h \
+ $(ANTLR_SRC)\proto.h \
+ $(ANTLR_SRC)\syn.h \
+
+ $(CC) -c $(CFLAGS) $(ANTLR_SRC)\globals.c
+
+hash.obj: $(ANTLR_SRC)\hash.c \
+ $(PCCTS_H)\config.h \
+ $(ANTLR_SRC)\hash.h \
+
+ $(CC) -c $(CFLAGS) $(ANTLR_SRC)\hash.c
+
+lex.obj: $(ANTLR_SRC)\lex.c \
+ $(PCCTS_H)\config.h \
+ $(SET)\set.h \
+ $(ANTLR_SRC)\generic.h \
+ $(ANTLR_SRC)\hash.h \
+ $(ANTLR_SRC)\proto.h \
+ $(ANTLR_SRC)\syn.h \
+
+ $(CC) -c $(CFLAGS) $(ANTLR_SRC)\lex.c
+
+main.obj: $(ANTLR_SRC)\main.c \
+ $(PCCTS_H)\antlr.h \
+ $(PCCTS_H)\config.h \
+ $(PCCTS_H)\dlgdef.h \
+ $(SET)\set.h \
+ $(ANTLR_SRC)\generic.h \
+ $(ANTLR_SRC)\hash.h \
+ $(ANTLR_SRC)\mode.h \
+ $(ANTLR_SRC)\proto.h \
+ $(ANTLR_SRC)\stdpccts.h \
+ $(ANTLR_SRC)\syn.h \
+ $(ANTLR_SRC)\tokens.h \
+
+ $(CC) -c $(CFLAGS) $(ANTLR_SRC)\main.c
+
+misc.obj: $(ANTLR_SRC)\misc.c \
+ $(PCCTS_H)\config.h \
+ $(PCCTS_H)\dlgdef.h \
+ $(SET)\set.h \
+ $(ANTLR_SRC)\generic.h \
+ $(ANTLR_SRC)\hash.h \
+ $(ANTLR_SRC)\proto.h \
+ $(ANTLR_SRC)\syn.h \
+
+ $(CC) -c $(CFLAGS) $(ANTLR_SRC)\misc.c
+
+pred.obj: $(ANTLR_SRC)\pred.c \
+ $(PCCTS_H)\config.h \
+ $(PCCTS_H)\dlgdef.h \
+ $(SET)\set.h \
+ $(ANTLR_SRC)\generic.h \
+ $(ANTLR_SRC)\hash.h \
+ $(ANTLR_SRC)\proto.h \
+ $(ANTLR_SRC)\syn.h \
+
+ $(CC) -c $(CFLAGS) $(ANTLR_SRC)\pred.c
+
+egman.obj: $(ANTLR_SRC)\egman.c \
+ $(PCCTS_H)\config.h \
+ $(SET)\set.h \
+ $(ANTLR_SRC)\generic.h \
+ $(ANTLR_SRC)\hash.h \
+ $(ANTLR_SRC)\proto.h \
+ $(ANTLR_SRC)\syn.h \
+
+ $(CC) -c $(CFLAGS) $(ANTLR_SRC)\egman.c
+
+mrhoist.obj: $(ANTLR_SRC)\mrhoist.c \
+ $(ANTLR_SRC)\generic.h \
+ $(ANTLR_SRC)\hash.h \
+ $(ANTLR_SRC)\proto.h \
+ $(ANTLR_SRC)\syn.h \
+
+ $(CC) -c $(CFLAGS) $(ANTLR_SRC)\mrhoist.c
+
+fcache.obj: $(ANTLR_SRC)\fcache.c \
+ $(ANTLR_SRC)\generic.h \
+ $(ANTLR_SRC)\hash.h \
+ $(ANTLR_SRC)\proto.h \
+ $(ANTLR_SRC)\syn.h \
+
+ $(CC) -c $(CFLAGS) $(ANTLR_SRC)\fcache.c
+
+set.obj: $(SET)\set.c \
+ $(PCCTS_H)\config.h \
+ $(SET)\set.h \
+
+ $(CC) -c $(CFLAGS) $(SET)\set.c
+
+clean:
+ del *.obj
+
+distclean:
+ del *.obj
+ del $(WORKSPACE)\Tools\bin\antlr.exe
diff --git a/Source/Pccts/antlr/AntlrPPC.mak b/Source/Pccts/antlr/AntlrPPC.mak
new file mode 100644
index 0000000..9ede60d
--- /dev/null
+++ b/Source/Pccts/antlr/AntlrPPC.mak
@@ -0,0 +1,101 @@
+# Target: antlrPPC
+# Sources: ::support:set:set.c
+# antlr.c
+# bits.c
+# build.c
+# egman.c
+# err.c
+# fcache.c
+# fset2.c
+# fset.c
+# gen.c
+# globals.c
+# hash.c
+# lex.c
+# main.c
+# misc.c
+# mrhoist.c
+# pred.c
+# scan.c
+# Created: Sunday, May 17, 1998 10:24:53 PM
+# Author: Kenji Tanaka
+MAKEFILE = antlrPPC.make
+¥MondoBuild¥ = {MAKEFILE} # Make blank to avoid rebuilds when makefile is modified
+Includes = ¶
+ -i "::h:" ¶
+ -i "::support:set:"
+Sym¥PPC =
+ObjDir¥PPC = :Obj:
+PPCCOptions = {Includes} {Sym¥PPC} -w off -d MPW -d __STDC__=1 -d USER_ZZSYN
+Objects¥PPC = ¶
+ "{ObjDir¥PPC}set.c.x" ¶
+ "{ObjDir¥PPC}antlr.c.x" ¶
+ "{ObjDir¥PPC}bits.c.x" ¶
+ "{ObjDir¥PPC}build.c.x" ¶
+ "{ObjDir¥PPC}egman.c.x" ¶
+ "{ObjDir¥PPC}err.c.x" ¶
+ "{ObjDir¥PPC}fcache.c.x" ¶
+ "{ObjDir¥PPC}fset2.c.x" ¶
+ "{ObjDir¥PPC}fset.c.x" ¶
+ "{ObjDir¥PPC}gen.c.x" ¶
+ "{ObjDir¥PPC}globals.c.x" ¶
+ "{ObjDir¥PPC}hash.c.x" ¶
+ "{ObjDir¥PPC}lex.c.x" ¶
+ "{ObjDir¥PPC}main.c.x" ¶
+ "{ObjDir¥PPC}misc.c.x" ¶
+ "{ObjDir¥PPC}mrhoist.c.x" ¶
+ "{ObjDir¥PPC}pred.c.x" ¶
+ "{ObjDir¥PPC}scan.c.x"
+antlrPPC ÄÄ {¥MondoBuild¥} {Objects¥PPC}
+ PPCLink ¶
+ -o {Targ} {Sym¥PPC} ¶
+ {Objects¥PPC} ¶
+ -t 'MPST' ¶
+ -c 'MPS ' ¶
+ "{SharedLibraries}InterfaceLib" ¶
+ "{SharedLibraries}StdCLib" ¶
+ #"{SharedLibraries}MathLib" ¶
+ "{PPCLibraries}StdCRuntime.o" ¶
+ "{PPCLibraries}PPCCRuntime.o" ¶
+ "{PPCLibraries}PPCToolLibs.o"
+"{ObjDir¥PPC}set.c.x" Ä {¥MondoBuild¥} "::support:set:set.c"
+ {PPCC} "::support:set:set.c" -o {Targ} {PPCCOptions}
+"{ObjDir¥PPC}antlr.c.x" Ä {¥MondoBuild¥} antlr.c
+ {PPCC} antlr.c -o {Targ} {PPCCOptions}
+"{ObjDir¥PPC}bits.c.x" Ä {¥MondoBuild¥} bits.c
+ {PPCC} bits.c -o {Targ} {PPCCOptions}
+"{ObjDir¥PPC}build.c.x" Ä {¥MondoBuild¥} build.c
+ {PPCC} build.c -o {Targ} {PPCCOptions}
+"{ObjDir¥PPC}egman.c.x" Ä {¥MondoBuild¥} egman.c
+ {PPCC} egman.c -o {Targ} {PPCCOptions}
+"{ObjDir¥PPC}err.c.x" Ä {¥MondoBuild¥} err.c
+ {PPCC} err.c -o {Targ} {PPCCOptions}
+"{ObjDir¥PPC}fcache.c.x" Ä {¥MondoBuild¥} fcache.c
+ {PPCC} fcache.c -o {Targ} {PPCCOptions}
+"{ObjDir¥PPC}fset2.c.x" Ä {¥MondoBuild¥} fset2.c
+ {PPCC} fset2.c -o {Targ} {PPCCOptions}
+"{ObjDir¥PPC}fset.c.x" Ä {¥MondoBuild¥} fset.c
+ {PPCC} fset.c -o {Targ} {PPCCOptions}
+"{ObjDir¥PPC}gen.c.x" Ä {¥MondoBuild¥} gen.c
+ {PPCC} gen.c -o {Targ} {PPCCOptions}
+"{ObjDir¥PPC}globals.c.x" Ä {¥MondoBuild¥} globals.c
+ {PPCC} globals.c -o {Targ} {PPCCOptions}
+"{ObjDir¥PPC}hash.c.x" Ä {¥MondoBuild¥} hash.c
+ {PPCC} hash.c -o {Targ} {PPCCOptions}
+"{ObjDir¥PPC}lex.c.x" Ä {¥MondoBuild¥} lex.c
+ {PPCC} lex.c -o {Targ} {PPCCOptions}
+"{ObjDir¥PPC}main.c.x" Ä {¥MondoBuild¥} main.c
+ {PPCC} main.c -o {Targ} {PPCCOptions}
+"{ObjDir¥PPC}misc.c.x" Ä {¥MondoBuild¥} misc.c
+ {PPCC} misc.c -o {Targ} {PPCCOptions}
+"{ObjDir¥PPC}mrhoist.c.x" Ä {¥MondoBuild¥} mrhoist.c
+ {PPCC} mrhoist.c -o {Targ} {PPCCOptions}
+"{ObjDir¥PPC}pred.c.x" Ä {¥MondoBuild¥} pred.c
+ {PPCC} pred.c -o {Targ} {PPCCOptions}
+"{ObjDir¥PPC}scan.c.x" Ä {¥MondoBuild¥} scan.c
+ {PPCC} scan.c -o {Targ} {PPCCOptions}
+
+antlrPPC ÄÄ antlr.r
+ Rez antlr.r -o antlrPPC -a
+Install Ä antlrPPC
+ Duplicate -y antlrPPC "{MPW}"Tools:antlr
diff --git a/Source/Pccts/antlr/README b/Source/Pccts/antlr/README
new file mode 100644
index 0000000..d7fc959
--- /dev/null
+++ b/Source/Pccts/antlr/README
@@ -0,0 +1,19 @@
+ ANTLR 1.33
+
+This directory contains the files necessary to build ANTLR.
+
+If you do a "make scrub", ANTLR will have to run on antlr.g and DLG
+will have to run on parser.dlg. Either
+
+(1) ANTLR uses the previous antlr in that directory to rebuild itself
+(2) Needs to find antlr on the search path
+
+You will find that running "antlr -gh antlr.g" will result in about
+10 ambiguity warnings. These are normal. Don't worry.
+
+If you do a "make clean" right after installation, ANTLR and DLG should
+not need to run; only the C files will compile.
+
+Don't forget to go into the makefile to uncomment the appropriate
+definitions for your OS/architecture/compiler or see the appropriate
+NOTES.?? file.
diff --git a/Source/Pccts/antlr/antlr.1 b/Source/Pccts/antlr/antlr.1
new file mode 100644
index 0000000..acfa85b
--- /dev/null
+++ b/Source/Pccts/antlr/antlr.1
@@ -0,0 +1,209 @@
+.TH ANTLR 1 "September 1995" "ANTLR" "PCCTS Manual Pages"
+.SH NAME
+antlr \- ANother Tool for Language Recognition
+.SH SYNTAX
+.LP
+\fBantlr\fR [\fIoptions\fR] \fIgrammar_files\fR
+.SH DESCRIPTION
+.PP
+\fIAntlr\fP converts an extended form of context-free grammar into a
+set of C functions which directly implement an efficient form of
+deterministic recursive-descent LL(k) parser. Context-free grammars
+may be augmented with predicates to allow semantics to influence
+parsing; this allows a form of context-sensitive parsing. Selective
+backtracking is also available to handle non-LL(k) and even
+non-LALR(k) constructs. \fIAntlr\fP also produces a definition of a
+lexer which can be automatically converted into C code for a DFA-based
+lexer by \fIdlg\fR. Hence, \fIantlr\fR serves a function much like
+that of \fIyacc\fR, however, it is notably more flexible and is more
+integrated with a lexer generator (\fIantlr\fR directly generates
+\fIdlg\fR code, whereas \fIyacc\fR and \fIlex\fR are given independent
+descriptions). Unlike \fIyacc\fR which accepts LALR(1) grammars,
+\fIantlr\fR accepts LL(k) grammars in an extended BNF notation \(em
+which eliminates the need for precedence rules.
+.PP
+Like \fIyacc\fR grammars, \fIantlr\fR grammars can use
+automatically-maintained symbol attribute values referenced as dollar
+variables. Further, because \fIantlr\fR generates top-down parsers,
+arbitrary values may be inherited from parent rules (passed like
+function parameters). \fIAntlr\fP also has a mechanism for creating
+and manipulating abstract-syntax-trees.
+.PP
+There are various other niceties in \fIantlr\fR, including the ability to
+spread one grammar over multiple files or even multiple grammars in a single
+file, the ability to generate a version of the grammar with actions stripped
+out (for documentation purposes), and lots more.
+.SH OPTIONS
+.IP "\fB-ck \fIn\fR"
+Use up to \fIn\fR symbols of lookahead when using compressed (linear
+approximation) lookahead. This type of lookahead is very cheap to
+compute and is attempted before full LL(k) lookahead, which is of
+exponential complexity in the worst case. In general, the compressed
+lookahead can be much deeper (e.g, \f(CW-ck 10\fP) than the full
+lookahead (which usually must be less than 4).
+.IP \fB-CC\fP
+Generate C++ output from both ANTLR and DLG.
+.IP \fB-cr\fP
+Generate a cross-reference for all rules. For each rule, print a list
+of all other rules that reference it.
+.IP \fB-e1\fP
+Ambiguities/errors shown in low detail (default).
+.IP \fB-e2\fP
+Ambiguities/errors shown in more detail.
+.IP \fB-e3\fP
+Ambiguities/errors shown in excruciating detail.
+.IP "\fB-fe\fP file"
+Rename \fBerr.c\fP to file.
+.IP "\fB-fh\fP file"
+Rename \fBstdpccts.h\fP header (turns on \fB-gh\fP) to file.
+.IP "\fB-fl\fP file"
+Rename lexical output, \fBparser.dlg\fP, to file.
+.IP "\fB-fm\fP file"
+Rename file with lexical mode definitions, \fBmode.h\fP, to file.
+.IP "\fB-fr\fP file"
+Rename file which remaps globally visible symbols, \fBremap.h\fP, to file.
+.IP "\fB-ft\fP file"
+Rename \fBtokens.h\fP to file.
+.IP \fB-ga\fP
+Generate ANSI-compatible code (default case). This has not been
+rigorously tested to be ANSI XJ11 C compliant, but it is close. The
+normal output of \fIantlr\fP is currently compilable under both K&R,
+ANSI C, and C++\(emthis option does nothing because \fIantlr\fP
+generates a bunch of #ifdef's to do the right thing depending on the
+language.
+.IP \fB-gc\fP
+Indicates that \fIantlr\fP should generate no C code, i.e., only
+perform analysis on the grammar.
+.IP \fB-gd\fP
+C code is inserted in each of the \fIantlr\fR generated parsing functions to
+provide for user-defined handling of a detailed parse trace. The inserted
+code consists of calls to the user-supplied macros or functions called
+\fBzzTRACEIN\fR and \fBzzTRACEOUT\fP. The only argument is a
+\fIchar *\fR pointing to a C-style string which is the grammar rule
+recognized by the current parsing function. If no definition is given
+for the trace functions, upon rule entry and exit, a message will be
+printed indicating that a particular rule as been entered or exited.
+.IP \fB-ge\fP
+Generate an error class for each non-terminal.
+.IP \fB-gh\fP
+Generate \fBstdpccts.h\fP for non-ANTLR-generated files to include.
+This file contains all defines needed to describe the type of parser
+generated by \fIantlr\fP (e.g. how much lookahead is used and whether
+or not trees are constructed) and contains the \fBheader\fP action
+specified by the user.
+.IP \fB-gk\fP
+Generate parsers that delay lookahead fetches until needed. Without
+this option, \fIantlr\fP generates parsers which always have \fIk\fP
+tokens of lookahead available.
+.IP \fB-gl\fP
+Generate line info about grammar actions in C parser of the form
+\fB#\ \fIline\fP\ "\fIfile\fP"\fR which makes error messages from
+the C/C++ compiler make more sense as they will \*Qpoint\*U into the
+grammar file not the resulting C file. Debugging is easier as well,
+because you will step through the grammar not C file.
+.IP \fB-gs\fR
+Do not generate sets for token expression lists; instead generate a
+\fB||\fP-separated sequence of \fBLA(1)==\fItoken_number\fR. The
+default is to generate sets.
+.IP \fB-gt\fP
+Generate code for Abstract-Syntax Trees.
+.IP \fB-gx\fP
+Do not create the lexical analyzer files (dlg-related). This option
+should be given when the user wishes to provide a customized lexical
+analyzer. It may also be used in \fImake\fR scripts to cause only the
+parser to be rebuilt when a change not affecting the lexical structure
+is made to the input grammars.
+.IP "\fB-k \fIn\fR"
+Set k of LL(k) to \fIn\fR; i.e. set tokens of look-ahead (default==1).
+.IP "\fB-o\fP dir
+Directory where output files should go (default="."). This is very
+nice for keeping the source directory clear of ANTLR and DLG spawn.
+.IP \fB-p\fP
+The complete grammar, collected from all input grammar files and
+stripped of all comments and embedded actions, is listed to
+\fBstdout\fP. This is intended to aid in viewing the entire grammar
+as a whole and to eliminate the need to keep actions concisely stated
+so that the grammar is easier to read. Hence, it is preferable to
+embed even complex actions directly in the grammar, rather than to
+call them as subroutines, since the subroutine call overhead will be
+saved.
+.IP \fB-pa\fP
+This option is the same as \fB-p\fP except that the output is
+annotated with the first sets determined from grammar analysis.
+.IP "\fB-prc on\fR
+Turn on the computation and hoisting of predicate context.
+.IP "\fB-prc off\fR
+Turn off the computation and hoisting of predicate context. This
+option makes 1.10 behave like the 1.06 release with option \fB-pr\fR
+on. Context computation is off by default.
+.IP "\fB-rl \fIn\fR
+Limit the maximum number of tree nodes used by grammar analysis to
+\fIn\fP. Occasionally, \fIantlr\fP is unable to analyze a grammar
+submitted by the user. This rare situation can only occur when the
+grammar is large and the amount of lookahead is greater than one. A
+nonlinear analysis algorithm is used by PCCTS to handle the general
+case of LL(k) parsing. The average complexity of analysis, however, is
+near linear due to some fancy footwork in the implementation which
+reduces the number of calls to the full LL(k) algorithm. An error
+message will be displayed, if this limit is reached, which indicates
+the grammar construct being analyzed when \fIantlr\fP hit a
+non-linearity. Use this option if \fIantlr\fP seems to go out to
+lunch and your disk start thrashing; try \fIn\fP=10000 to start. Once
+the offending construct has been identified, try to remove the
+ambiguity that \fIantlr\fP was trying to overcome with large lookahead
+analysis. The introduction of (...)? backtracking blocks eliminates
+some of these problems\ \(em \fIantlr\fP does not analyze alternatives
+that begin with (...)? (it simply backtracks, if necessary, at run
+time).
+.IP \fB-w1\fR
+Set low warning level. Do not warn if semantic predicates and/or
+(...)? blocks are assumed to cover ambiguous alternatives.
+.IP \fB-w2\fR
+Ambiguous parsing decisions yield warnings even if semantic predicates
+or (...)? blocks are used. Warn if predicate context computed and
+semantic predicates incompletely disambiguate alternative productions.
+.IP \fB-\fR
+Read grammar from standard input and generate \fBstdin.c\fP as the
+parser file.
+.SH "SPECIAL CONSIDERATIONS"
+.PP
+\fIAntlr\fP works... we think. There is no implicit guarantee of
+anything. We reserve no \fBlegal\fP rights to the software known as
+the Purdue Compiler Construction Tool Set (PCCTS) \(em PCCTS is in the
+public domain. An individual or company may do whatever they wish
+with source code distributed with PCCTS or the code generated by
+PCCTS, including the incorporation of PCCTS, or its output, into
+commercial software. We encourage users to develop software with
+PCCTS. However, we do ask that credit is given to us for developing
+PCCTS. By "credit", we mean that if you incorporate our source code
+into one of your programs (commercial product, research project, or
+otherwise) that you acknowledge this fact somewhere in the
+documentation, research report, etc... If you like PCCTS and have
+developed a nice tool with the output, please mention that you
+developed it using PCCTS. As long as these guidelines are followed,
+we expect to continue enhancing this system and expect to make other
+tools available as they are completed.
+.SH FILES
+.IP *.c
+output C parser.
+.IP *.cpp
+output C++ parser when C++ mode is used.
+.IP \fBparser.dlg\fP
+output \fIdlg\fR lexical analyzer.
+.IP \fBerr.c\fP
+token string array, error sets and error support routines. Not used in
+C++ mode.
+.IP \fBremap.h\fP
+file that redefines all globally visible parser symbols. The use of
+the #parser directive creates this file. Not used in
+C++ mode.
+.IP \fBstdpccts.h\fP
+list of definitions needed by C files, not generated by PCCTS, that
+reference PCCTS objects. This is not generated by default. Not used in
+C++ mode.
+.IP \fBtokens.h\fP
+output \fI#defines\fR for tokens used and function prototypes for
+functions generated for rules.
+.SH "SEE ALSO"
+.LP
+dlg(1), pccts(1)
diff --git a/Source/Pccts/antlr/antlr.c b/Source/Pccts/antlr/antlr.c
new file mode 100644
index 0000000..8aaef79
--- /dev/null
+++ b/Source/Pccts/antlr/antlr.c
@@ -0,0 +1,3564 @@
+/*
+ * A n t l r T r a n s l a t i o n H e a d e r
+ *
+ * Terence Parr, Will Cohen, and Hank Dietz: 1989-2001
+ * Purdue University Electrical Engineering
+ * With AHPCRC, University of Minnesota
+ * ANTLR Version 1.33MR33
+ *
+ * ..\bin\antlr -gh antlr.g
+ *
+ */
+
+#define ANTLR_VERSION 13333
+#include "pcctscfg.h"
+#include "pccts_stdio.h"
+
+#include "pcctscfg.h"
+#include "set.h"
+#include <ctype.h>
+#include "syn.h"
+#include "hash.h"
+#include "generic.h"
+#define zzcr_attr(attr,tok,t)
+#define zzSET_SIZE 20
+#include "antlr.h"
+#include "tokens.h"
+#include "dlgdef.h"
+#include "mode.h"
+
+/* MR23 In order to remove calls to PURIFY use the antlr -nopurify option */
+
+#ifndef PCCTS_PURIFY
+#define PCCTS_PURIFY(r,s) memset((char *) &(r),'\0',(s));
+#endif
+
+ANTLR_INFO
+
+
+/* MR20 G. Hobbelt For Borland C++ 4.x & 5.x compiling with ALL warnings enabled */
+#if defined(__TURBOC__)
+#pragma warn -aus /* unused assignment of 'xxx' */
+#endif
+
+
+#ifdef __USE_PROTOS
+static void chkToken(char *, char *, char *, int);
+#else
+static void chkToken();
+#endif
+
+#ifdef __USE_PROTOS
+static int isDLGmaxToken(char *Token); /* MR3 */
+#else
+static int isDLGmaxToken(); /* MR3 */
+#endif
+
+static int class_nest_level = 0;
+
+/* MR20 G. Hobbelt extern definitions moved to antlr.h */
+
+
+
+void
+#ifdef __USE_PROTOS
+grammar(void)
+#else
+grammar()
+#endif
+{
+ zzRULE;
+ zzBLOCK(zztasp1);
+ zzMake0;
+ {
+ Graph g;
+ {
+ zzBLOCK(zztasp2);
+ zzMake0;
+ {
+ for (;;) {
+ if ( !((setwd1[LA(1)]&0x1))) break;
+ if ( (LA(1)==94) ) {
+ zzmatch(94); zzCONSUME;
+ zzmatch(Action);
+
+ if ( HdrAction==NULL ) {
+ HdrAction = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char));
+ require(HdrAction!=NULL, "rule grammar: cannot allocate header action");
+ strcpy(HdrAction, LATEXT(1));
+ }
+ else warn("additional #header statement ignored");
+ zzCONSUME;
+
+ }
+ else {
+ if ( (LA(1)==95) ) {
+ zzmatch(95); zzCONSUME;
+ zzmatch(Action);
+
+ if ( FirstAction==NULL ) {
+ FirstAction = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char));
+ require(FirstAction!=NULL, "rule grammar: cannot allocate #first action");
+ strcpy(FirstAction, LATEXT(1));
+ } else {
+ warn("additional #first statement ignored");
+ };
+ zzCONSUME;
+
+ }
+ else {
+ if ( (LA(1)==96) ) {
+ zzmatch(96); zzCONSUME;
+ zzmatch(QuotedTerm);
+
+ if ( GenCC ) {
+ warn("#parser meta-op incompatible with -CC; ignored");
+ }
+ else {
+ if ( strcmp(ParserName,"zzparser")==0 ) {
+ ParserName=StripQuotes(mystrdup(LATEXT(1)));
+ if ( RulePrefix[0]!='\0' )
+ {
+ warn("#parser meta-op incompatible with '-gp prefix'; '-gp' ignored");
+ RulePrefix[0]='\0';
+ }
+ }
+ else warn("additional #parser statement ignored");
+ }
+ zzCONSUME;
+
+ }
+ else {
+ if ( (LA(1)==97) ) {
+ zzmatch(97); zzCONSUME;
+ zzmatch(QuotedTerm);
+ {
+ char *fname;
+ zzantlr_state st; FILE *f; struct zzdlg_state dst;
+ UserTokenDefsFile = mystrdup(LATEXT(1));
+ zzsave_antlr_state(&st);
+ zzsave_dlg_state(&dst);
+ fname = mystrdup(LATEXT(1));
+ f = fopen(StripQuotes(fname), "r");
+ if ( f==NULL ) {warn(eMsg1("cannot open token defs file '%s'", fname+1));}
+ else {
+ ANTLRm(enum_file(fname+1), f, PARSE_ENUM_FILE);
+ UserDefdTokens = 1;
+ }
+ zzrestore_antlr_state(&st);
+ zzrestore_dlg_state(&dst);
+ }
+ zzCONSUME;
+
+ }
+ else break; /* MR6 code for exiting loop "for sure" */
+ }
+ }
+ }
+ zzLOOP(zztasp2);
+ }
+ zzEXIT(zztasp2);
+ }
+ }
+ {
+ zzBLOCK(zztasp2);
+ zzMake0;
+ {
+ for (;;) {
+ if ( !((setwd1[LA(1)]&0x2))) break;
+ if ( (LA(1)==Action) ) {
+ zzmatch(Action);
+ {
+ UserAction *ua = newUserAction(LATEXT(1));
+ ua->file = action_file; ua->line = action_line;
+ if ( class_nest_level>0 ) list_add(&class_before_actions, ua);
+ else list_add(&BeforeActions, ua);
+ }
+ zzCONSUME;
+
+ }
+ else {
+ if ( (LA(1)==108) ) {
+ laction();
+ }
+ else {
+ if ( (LA(1)==109) ) {
+ lmember();
+ }
+ else {
+ if ( (LA(1)==110) ) {
+ lprefix();
+ }
+ else {
+ if ( (LA(1)==116) ) {
+ aLexclass();
+ }
+ else {
+ if ( (LA(1)==120) ) {
+ token();
+ }
+ else {
+ if ( (LA(1)==117) ) {
+ error();
+ }
+ else {
+ if ( (LA(1)==118) ) {
+ tclass();
+ }
+ else {
+ if ( (LA(1)==111) ) {
+ aPred();
+ }
+ else {
+ if ( (LA(1)==133) ) {
+ default_exception_handler();
+ }
+ else {
+ if ( (LA(1)==99) ) {
+ class_def();
+ }
+ else {
+ if ( (LA(1)==98) ) {
+ zzmatch(98);
+
+ if ( class_nest_level==0 )
+ warn("missing class definition for trailing '}'");
+ class_nest_level--;
+ zzCONSUME;
+
+ }
+ else break; /* MR6 code for exiting loop "for sure" */
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ zzLOOP(zztasp2);
+ }
+ zzEXIT(zztasp2);
+ }
+ }
+ rule();
+ g=zzaArg(zztasp1,3); SynDiag = (Junction *) zzaArg(zztasp1,3 ).left;
+ {
+ zzBLOCK(zztasp2);
+ zzMake0;
+ {
+ for (;;) {
+ if ( !((setwd1[LA(1)]&0x4))) break;
+ if ( (LA(1)==NonTerminal) ) {
+ rule();
+ if ( zzaArg(zztasp2,1 ).left!=NULL ) {
+ g.right = NULL;
+
+/* MR21a */ /* Avoid use of a malformed graph when CannotContinue */
+ /* MR21a */ /* is already set */
+ /* MR21a */
+ /* MR21a */ if (! (CannotContinue && g.left == NULL)) {
+ /* MR21a */ g = Or(g, zzaArg(zztasp2,1));
+ /* MR21a */ }
+ /* MR21a */ }
+ }
+ else {
+ if ( (LA(1)==116) ) {
+ aLexclass();
+ }
+ else {
+ if ( (LA(1)==120) ) {
+ token();
+ }
+ else {
+ if ( (LA(1)==117) ) {
+ error();
+ }
+ else {
+ if ( (LA(1)==118) ) {
+ tclass();
+ }
+ else {
+ if ( (LA(1)==111) ) {
+ aPred();
+ }
+ else {
+ if ( (LA(1)==99) ) {
+ class_def();
+ }
+ else {
+ if ( (LA(1)==98) ) {
+ zzmatch(98);
+
+ if ( class_nest_level==0 )
+ warn("missing class definition for trailing '}'");
+ class_nest_level--;
+ zzCONSUME;
+
+ }
+ else break; /* MR6 code for exiting loop "for sure" */
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ zzLOOP(zztasp2);
+ }
+ zzEXIT(zztasp2);
+ }
+ }
+ {
+ zzBLOCK(zztasp2);
+ zzMake0;
+ {
+ for (;;) {
+ if ( !((setwd1[LA(1)]&0x8))) break;
+ if ( (LA(1)==Action) ) {
+ zzmatch(Action);
+ {
+ UserAction *ua = newUserAction(LATEXT(1));
+ ua->file = action_file; ua->line = action_line;
+ if ( class_nest_level>0 ) list_add(&class_after_actions, ua);
+ else list_add(&AfterActions, ua);
+ }
+ zzCONSUME;
+
+ }
+ else {
+ if ( (LA(1)==108) ) {
+ laction();
+ }
+ else {
+ if ( (LA(1)==109) ) {
+ lmember();
+ }
+ else {
+ if ( (LA(1)==110) ) {
+ lprefix();
+ }
+ else {
+ if ( (LA(1)==117) ) {
+ error();
+ }
+ else {
+ if ( (LA(1)==118) ) {
+ tclass();
+ }
+ else {
+ if ( (LA(1)==99) ) {
+ class_def();
+ }
+ else {
+ if ( (LA(1)==111) ) {
+ aPred();
+ }
+ else {
+ if ( (LA(1)==98) ) {
+ zzmatch(98);
+
+ if ( class_nest_level==0 )
+ warn("missing class definition for trailing '}'");
+ class_nest_level--;
+ zzCONSUME;
+
+ }
+ else break; /* MR6 code for exiting loop "for sure" */
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ zzLOOP(zztasp2);
+ }
+ zzEXIT(zztasp2);
+ }
+ }
+ zzmatch(Eof); zzCONSUME;
+ zzEXIT(zztasp1);
+ return;
+fail:
+ zzEXIT(zztasp1);
+ CannotContinue=TRUE;
+ zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText);
+ zzresynch(setwd1, 0x10);
+ }
+}
+
+void
+#ifdef __USE_PROTOS
+class_def(void)
+#else
+class_def()
+#endif
+{
+ zzRULE;
+ zzBLOCK(zztasp1);
+ zzMake0;
+ {
+ int go=1; char name[MaxRuleName+1];
+ zzmatch(99); zzCONSUME;
+ {
+ zzBLOCK(zztasp2);
+ zzMake0;
+ {
+ if ( (LA(1)==NonTerminal) ) {
+ zzmatch(NonTerminal);
+ if(go) strncpy(name,LATEXT(1),MaxRuleName);
+ zzCONSUME;
+
+ }
+ else {
+ if ( (LA(1)==TokenTerm) ) {
+ zzmatch(TokenTerm);
+ if(go) strncpy(name,LATEXT(1),MaxRuleName);
+ zzCONSUME;
+
+ }
+ else {zzFAIL(1,zzerr1,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}
+ }
+ zzEXIT(zztasp2);
+ }
+ }
+
+ if ( CurrentClassName[0]!='\0' && strcmp(CurrentClassName,name)!=0
+ && GenCC ) {
+ err("only one grammar class allowed in this release");
+ go = 0;
+ }
+ else strcpy(CurrentClassName, name);
+ if ( !GenCC ) { err("class meta-op used without C++ option"); }
+ {
+ zzBLOCK(zztasp2);
+ zzMake0;
+ {
+ while ( (setwd1[LA(1)]&0x20) ) {
+ zzsetmatch(zzerr2, zzerr3);
+ if (ClassDeclStuff == NULL) {
+ /* MR10 */ ClassDeclStuff=(char *)calloc(MaxClassDeclStuff+1,sizeof(char));
+ /* MR10 */ };
+ /* MR10 */ strncat(ClassDeclStuff," ",MaxClassDeclStuff);
+ /* MR10 */ strncat(ClassDeclStuff,LATEXT(1),MaxClassDeclStuff);
+ /* MR22 */ do {
+ /* MR22 */ if (0 == strcmp(LATEXT(1),"public")) break;
+ /* MR22 */ if (0 == strcmp(LATEXT(1),"private")) break;
+ /* MR22 */ if (0 == strcmp(LATEXT(1),"protected")) break;
+ /* MR22 */ if (0 == strcmp(LATEXT(1),"virtual")) break;
+ /* MR22 */ if (0 == strcmp(LATEXT(1),",")) break;
+ /* MR22 */ if (0 == strcmp(LATEXT(1),":")) break;
+ /* MR22 */ if (BaseClassName != NULL) break;
+ /* MR22 */ BaseClassName=(char *)calloc(strlen(LATEXT(1))+1,sizeof(char));
+ /* MR22 */ require(BaseClassName!=NULL, "rule grammar: cannot allocate base class name");
+ /* MR22 */ strcpy(BaseClassName,LATEXT(1));
+ /* MR22 */ } while (0);
+ /* MR10 */
+ zzCONSUME;
+
+ zzLOOP(zztasp2);
+ }
+ zzEXIT(zztasp2);
+ }
+ }
+ zzmatch(102);
+
+ no_classes_found = 0;
+ if ( class_nest_level>=1 ) {warn("cannot have nested classes");}
+ else class_nest_level++;
+ zzCONSUME;
+
+ zzEXIT(zztasp1);
+ return;
+fail:
+ zzEXIT(zztasp1);
+ CannotContinue=TRUE;
+ zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText);
+ zzresynch(setwd1, 0x40);
+ }
+}
+
+void
+#ifdef __USE_PROTOS
+rule(void)
+#else
+rule()
+#endif
+{
+ zzRULE;
+ zzBLOCK(zztasp1);
+ zzMake0;
+ {
+
+
+ ExceptionGroup *eg;
+ RuleEntry *q; Junction *p; Graph r; int f, l; ECnode *e;
+ set toksrefd, rulesrefd;
+ char *pdecl=NULL, *ret=NULL, *a; CurRetDef = CurParmDef = NULL;
+ CurExGroups = NULL;
+ CurElementLabels = NULL;
+ CurAstLabelsInActions = NULL; /* MR27 */
+ /* We want a new element label hash table for each rule */
+ if ( Elabel!=NULL ) killHashTable(Elabel);
+ Elabel = newHashTable();
+ attribsRefdFromAction = empty;
+ zzmatch(NonTerminal);
+ q=NULL;
+ if ( hash_get(Rname, LATEXT(1))!=NULL ) {
+ err(eMsg1("duplicate rule definition: '%s'",LATEXT(1)));
+ CannotContinue=TRUE;
+ }
+ else
+ {
+ q = (RuleEntry *)hash_add(Rname,
+ LATEXT(1),
+ (Entry *)newRuleEntry(LATEXT(1)));
+ CurRule = q->str;
+ }
+ CurRuleNode = q;
+ f = CurFile; l = zzline;
+ NumRules++;
+ zzCONSUME;
+
+ {
+ zzBLOCK(zztasp2);
+ zzMake0;
+ {
+ if ( (LA(1)==103) ) {
+ zzmatch(103);
+ if ( q!=NULL ) q->noAST = TRUE;
+ zzCONSUME;
+
+ }
+ else {
+ if ( (setwd1[LA(1)]&0x80) ) {
+ }
+ else {zzFAIL(1,zzerr4,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}
+ }
+ zzEXIT(zztasp2);
+ }
+ }
+ {
+ zzBLOCK(zztasp2);
+ zzMake0;
+ {
+ ;
+ if ( (setwd2[LA(1)]&0x1) ) {
+ {
+ zzBLOCK(zztasp3);
+ zzMake0;
+ {
+ if ( (LA(1)==104) ) {
+ zzmatch(104); zzCONSUME;
+ }
+ else {
+ if ( (LA(1)==PassAction) ) {
+ }
+ else {zzFAIL(1,zzerr5,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}
+ }
+ zzEXIT(zztasp3);
+ }
+ }
+ zzmatch(PassAction);
+ pdecl = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char));
+ require(pdecl!=NULL, "rule rule: cannot allocate param decl");
+ strcpy(pdecl, LATEXT(1));
+ CurParmDef = pdecl;
+ zzCONSUME;
+
+ }
+ else {
+ if ( (setwd2[LA(1)]&0x2) ) {
+ }
+ else {zzFAIL(1,zzerr6,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}
+ }
+ zzEXIT(zztasp2);
+ }
+ }
+ {
+ zzBLOCK(zztasp2);
+ zzMake0;
+ {
+ if ( (LA(1)==105) ) {
+ zzmatch(105); zzCONSUME;
+ zzmatch(PassAction);
+ ret = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char));
+ require(ret!=NULL, "rule rule: cannot allocate ret type");
+ strcpy(ret, LATEXT(1));
+ CurRetDef = ret;
+ zzCONSUME;
+
+ }
+ else {
+ if ( (setwd2[LA(1)]&0x4) ) {
+ }
+ else {zzFAIL(1,zzerr7,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}
+ }
+ zzEXIT(zztasp2);
+ }
+ }
+ {
+ zzBLOCK(zztasp2);
+ zzMake0;
+ {
+ if ( (LA(1)==QuotedTerm) ) {
+ zzmatch(QuotedTerm);
+ if ( q!=NULL ) q->egroup=mystrdup(LATEXT(1));
+ zzCONSUME;
+
+ }
+ else {
+ if ( (LA(1)==106) ) {
+ }
+ else {zzFAIL(1,zzerr8,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}
+ }
+ zzEXIT(zztasp2);
+ }
+ }
+
+ if ( GenEClasseForRules && q!=NULL ) {
+ e = newECnode;
+ require(e!=NULL, "cannot allocate error class node");
+ if ( q->egroup == NULL ) {a = q->str; a[0] = (char)toupper(a[0]);}
+ else a = q->egroup;
+ if ( Tnum( a ) == 0 )
+ {
+ e->tok = addTname( a );
+ list_add(&eclasses, (char *)e);
+ if ( q->egroup == NULL ) a[0] = (char)tolower(a[0]);
+ /* refers to itself */
+ list_add(&(e->elist), mystrdup(q->str));
+ }
+ else {
+ warn(eMsg1("default errclass for '%s' would conflict with token/errclass/tokclass",a));
+ if ( q->egroup == NULL ) a[0] = (char)tolower(a[0]);
+ free((char *)e);
+ }
+ }
+ BlkLevel++;
+ if (BlkLevel >= MAX_BLK_LEVEL) fatal("Blocks nested too deeply");
+ /* MR23 */ CurBlockID_array[BlkLevel] = CurBlockID;
+ /* MR23 */ CurAltNum_array[BlkLevel] = CurAltNum;
+ zzmatch(106);
+ inAlt=1;
+ zzCONSUME;
+
+ block( &toksrefd, &rulesrefd );
+ r = makeBlk(zzaArg(zztasp1,7),0, NULL /* pFirstSetSymbol */ );
+ CurRuleBlk = (Junction *)r.left;
+ CurRuleBlk->blockid = CurBlockID;
+ CurRuleBlk->jtype = RuleBlk;
+ if ( q!=NULL ) CurRuleBlk->rname = q->str;
+ CurRuleBlk->file = f;
+ CurRuleBlk->line = l;
+ CurRuleBlk->pdecl = pdecl;
+ CurRuleBlk->ret = ret;
+ CurRuleBlk->lock = makelocks();
+ CurRuleBlk->pred_lock = makelocks();
+ CurRuleBlk->tokrefs = toksrefd;
+ CurRuleBlk->rulerefs = rulesrefd;
+ p = newJunction(); /* add EndRule Node */
+ ((Junction *)r.right)->p1 = (Node *)p;
+ r.right = (Node *) p;
+ p->jtype = EndRule;
+ p->lock = makelocks();
+ p->pred_lock = makelocks();
+ CurRuleBlk->end = p;
+ if ( q!=NULL ) q->rulenum = NumRules;
+ zzaArg(zztasp1,7) = r;
+
+ /* MR23 */ CurBlockID_array[BlkLevel] = (-1);
+ /* MR23 */ CurAltNum_array[BlkLevel] = (-1);
+ --BlkLevel;
+ altFixup();leFixup();egFixup();
+ zzmatch(107);
+ inAlt=0;
+ zzCONSUME;
+
+ {
+ zzBLOCK(zztasp2);
+ zzMake0;
+ {
+ if ( (LA(1)==Action) ) {
+ zzmatch(Action);
+ a = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char));
+ require(a!=NULL, "rule rule: cannot allocate error action");
+ strcpy(a, LATEXT(1));
+ CurRuleBlk->erraction = a;
+ zzCONSUME;
+
+ }
+ else {
+ if ( (setwd2[LA(1)]&0x8) ) {
+ }
+ else {zzFAIL(1,zzerr9,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}
+ }
+ zzEXIT(zztasp2);
+ }
+ }
+ {
+ zzBLOCK(zztasp2);
+ zzMake0;
+ {
+ while ( (LA(1)==133) ) {
+ eg = exception_group();
+
+ if ( eg!=NULL ) {
+ list_add(&CurExGroups, (void *)eg);
+ if (eg->label == NULL || *eg->label=='\0' ) q->has_rule_exception = 1;
+ }
+ zzLOOP(zztasp2);
+ }
+ zzEXIT(zztasp2);
+ }
+ }
+ if ( q==NULL ) zzaArg(zztasp1,0 ).left = NULL; else zzaArg(zztasp1,0) = zzaArg(zztasp1,7);
+ CurRuleBlk->exceptions = CurExGroups;
+ CurRuleBlk->el_labels = CurElementLabels;
+ CurRuleNode->ast_labels_in_actions = CurAstLabelsInActions;
+ CurRuleNode = NULL;
+ zzEXIT(zztasp1);
+ return;
+fail:
+ zzEXIT(zztasp1);
+ CannotContinue=TRUE;
+ zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText);
+ zzresynch(setwd2, 0x10);
+ }
+}
+
+void
+#ifdef __USE_PROTOS
+laction(void)
+#else
+laction()
+#endif
+{
+ zzRULE;
+ zzBLOCK(zztasp1);
+ zzMake0;
+ {
+ char *a;
+ zzmatch(108); zzCONSUME;
+ zzmatch(Action);
+
+ a = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char));
+ require(a!=NULL, "rule laction: cannot allocate action");
+ strcpy(a, LATEXT(1));
+ list_add(&LexActions, a);
+ zzCONSUME;
+
+ zzEXIT(zztasp1);
+ return;
+fail:
+ zzEXIT(zztasp1);
+ CannotContinue=TRUE;
+ zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText);
+ zzresynch(setwd2, 0x20);
+ }
+}
+
+void
+#ifdef __USE_PROTOS
+lmember(void)
+#else
+lmember()
+#endif
+{
+ zzRULE;
+ zzBLOCK(zztasp1);
+ zzMake0;
+ {
+ char *a;
+ zzmatch(109); zzCONSUME;
+ zzmatch(Action);
+
+ /* MR1 */ if (! GenCC) {
+ /* MR1 */ err("Use #lexmember only in C++ mode (to insert code in DLG class header");
+ /* MR1 */ } else {
+ /* MR1 */ a = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char));
+ /* MR1 */ require(a!=NULL, "rule lmember: cannot allocate action");
+ /* MR1 */ strcpy(a, LATEXT(1));
+ /* MR1 */ list_add(&LexMemberActions, a);
+ /* MR1 */ };
+ /* MR1 */
+ zzCONSUME;
+
+ zzEXIT(zztasp1);
+ return;
+fail:
+ zzEXIT(zztasp1);
+ CannotContinue=TRUE;
+ zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText);
+ zzresynch(setwd2, 0x40);
+ }
+}
+
+void
+#ifdef __USE_PROTOS
+lprefix(void)
+#else
+lprefix()
+#endif
+{
+ zzRULE;
+ zzBLOCK(zztasp1);
+ zzMake0;
+ {
+ char *a;
+ zzmatch(110); zzCONSUME;
+ zzmatch(Action);
+
+ /* MR1 */ if (! GenCC) {
+ /* MR1 */ err("Use #lexprefix only in C++ mode (to insert code in DLG class header");
+ /* MR1 */ } else {
+ /* MR1 */ a = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char));
+ /* MR1 */ require(a!=NULL, "rule lprefix: cannot allocate action");
+ /* MR1 */ strcpy(a, LATEXT(1));
+ /* MR1 */ list_add(&LexPrefixActions, a);
+ /* MR1 */ };
+ /* MR1 */
+ zzCONSUME;
+
+ zzEXIT(zztasp1);
+ return;
+fail:
+ zzEXIT(zztasp1);
+ CannotContinue=TRUE;
+ zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText);
+ zzresynch(setwd2, 0x80);
+ }
+}
+
+void
+#ifdef __USE_PROTOS
+aPred(void)
+#else
+aPred()
+#endif
+{
+ zzRULE;
+ zzBLOCK(zztasp1);
+ zzMake0;
+ {
+ PredEntry *predEntry=NULL;
+ char *name=NULL;
+ Predicate *predExpr=NULL;
+ char *predLiteral=NULL;
+ int save_file;
+ int save_line;
+ int predExprPresent=0;
+ zzmatch(111);
+
+ MR_usingPredNames=1; /* will need to use -mrhoist version of genPredTree */
+ zzCONSUME;
+
+ zzmatch(TokenTerm);
+ name=mystrdup(LATEXT(1));
+ zzCONSUME;
+
+
+ /* don't free - referenced in predicates */
+
+ CurPredName=(char *)calloc(1,strlen(name) + 10);
+ strcat(CurPredName,"#pred ");
+ strcat(CurPredName,name);
+
+ predEntry=(PredEntry *) hash_get(Pname,name);
+ if (predEntry != NULL) {
+ warnFL(eMsg1("#pred %s previously defined - ignored",name),
+ FileStr[action_file],action_line);
+ name=NULL;
+};
+ {
+ zzBLOCK(zztasp2);
+ zzMake0;
+ {
+ if ( (LA(1)==Pred) ) {
+ zzmatch(Pred);
+ predLiteral=mystrdup(LATEXT(1));
+ save_line=action_line;
+ save_file=action_file;
+ zzCONSUME;
+
+ {
+ zzBLOCK(zztasp3);
+ zzMake0;
+ {
+ if ( (setwd3[LA(1)]&0x1) ) {
+ predExpr = predOrExpr();
+
+ predExprPresent=1;
+ }
+ else {
+ if ( (setwd3[LA(1)]&0x2) ) {
+ }
+ else {zzFAIL(1,zzerr10,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}
+ }
+ zzEXIT(zztasp3);
+ }
+ }
+ if (predLiteral != NULL && name != NULL) {
+
+ /*
+ * predExpr may be NULL due to syntax errors
+ * or simply omitted by the user
+ */
+
+ predEntry=newPredEntry(name);
+ predEntry->file=save_file;
+ predEntry->line=save_line;
+ predExpr=MR_predFlatten(predExpr);
+ predEntry->predLiteral=predLiteral;
+ if (! predExprPresent || predExpr == NULL) {
+ predExpr=new_pred();
+ predExpr->expr=predLiteral;
+ predExpr->source=newActionNode();
+ predExpr->source->action=predExpr->expr;
+ predExpr->source->rname=CurPredName;
+ predExpr->source->line=action_line;
+ predExpr->source->file=action_file;
+ predExpr->source->is_predicate=1;
+ predExpr->k=predicateLookaheadDepth(predExpr->source);
+ };
+ predEntry->pred=predExpr;
+ hash_add(Pname,name,(Entry *)predEntry);
+ predExpr=NULL;
+ };
+ predicate_free(predExpr);
+ }
+ else {
+ if ( (setwd3[LA(1)]&0x4) ) {
+ save_line=zzline; save_file=CurFile;
+ predExpr = predOrExpr();
+
+ if (predExpr != NULL && name != NULL) {
+ predEntry=newPredEntry(name);
+ predEntry->file=CurFile;
+ predEntry->line=zzline;
+ predExpr=MR_predFlatten(predExpr);
+ predEntry->pred=predExpr;
+ hash_add(Pname,name,(Entry *)predEntry);
+ predExpr=NULL;
+ };
+ predicate_free(predExpr);
+ }
+ else {zzFAIL(1,zzerr11,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}
+ }
+ zzEXIT(zztasp2);
+ }
+ }
+ {
+ zzBLOCK(zztasp2);
+ zzMake0;
+ {
+ if ( (LA(1)==107) ) {
+ zzmatch(107); zzCONSUME;
+ }
+ else {
+ if ( (setwd3[LA(1)]&0x8) ) {
+ }
+ else {zzFAIL(1,zzerr12,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}
+ }
+ zzEXIT(zztasp2);
+ }
+ }
+ zzEXIT(zztasp1);
+ return;
+fail:
+ zzEXIT(zztasp1);
+ predicate_free(predExpr);
+ zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText);
+ zzresynch(setwd3, 0x10);
+ }
+}
+
+Predicate *
+#ifdef __USE_PROTOS
+predOrExpr(void)
+#else
+predOrExpr()
+#endif
+{
+ Predicate * _retv;
+ zzRULE;
+ zzBLOCK(zztasp1);
+ PCCTS_PURIFY(_retv,sizeof(Predicate * ))
+ zzMake0;
+ {
+ Predicate *ORnode;
+ Predicate *predExpr;
+ Predicate **tail=NULL;
+ predExpr = predAndExpr();
+
+
+ ORnode=new_pred();
+ ORnode->expr=PRED_OR_LIST;
+ if (predExpr != NULL) {
+ ORnode->down=predExpr;
+ tail=&predExpr->right;
+ };
+ {
+ zzBLOCK(zztasp2);
+ zzMake0;
+ {
+ while ( (LA(1)==112) ) {
+ zzmatch(112); zzCONSUME;
+ predExpr = predAndExpr();
+
+
+ if (predExpr != NULL) {
+ *tail=predExpr;
+ tail=&predExpr->right;
+ };
+ zzLOOP(zztasp2);
+ }
+ zzEXIT(zztasp2);
+ }
+ }
+
+ _retv=ORnode;
+ ORnode=NULL;
+ zzEXIT(zztasp1);
+ return _retv;
+fail:
+ zzEXIT(zztasp1);
+ predicate_free(ORnode);
+ zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText);
+ zzresynch(setwd3, 0x20);
+ return _retv;
+ }
+}
+
+Predicate *
+#ifdef __USE_PROTOS
+predAndExpr(void)
+#else
+predAndExpr()
+#endif
+{
+ Predicate * _retv;
+ zzRULE;
+ zzBLOCK(zztasp1);
+ PCCTS_PURIFY(_retv,sizeof(Predicate * ))
+ zzMake0;
+ {
+ Predicate *ANDnode;
+ Predicate *predExpr;
+ Predicate **tail=NULL;
+ predExpr = predPrimary();
+
+
+ ANDnode=new_pred();
+ ANDnode->expr=PRED_AND_LIST;
+ if (predExpr != NULL) {
+ ANDnode->down=predExpr;
+ tail=&predExpr->right;
+ };
+ {
+ zzBLOCK(zztasp2);
+ zzMake0;
+ {
+ while ( (LA(1)==113) ) {
+ zzmatch(113); zzCONSUME;
+ predExpr = predPrimary();
+
+
+ if (predExpr != NULL) {
+ *tail=predExpr;
+ tail=&predExpr->right;
+ };
+ zzLOOP(zztasp2);
+ }
+ zzEXIT(zztasp2);
+ }
+ }
+
+ _retv=ANDnode;
+ ANDnode=NULL;
+ zzEXIT(zztasp1);
+ return _retv;
+fail:
+ zzEXIT(zztasp1);
+ predicate_free(ANDnode);
+ zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText);
+ zzresynch(setwd3, 0x40);
+ return _retv;
+ }
+}
+
+Predicate *
+#ifdef __USE_PROTOS
+predPrimary(void)
+#else
+predPrimary()
+#endif
+{
+ Predicate * _retv;
+ zzRULE;
+ zzBLOCK(zztasp1);
+ PCCTS_PURIFY(_retv,sizeof(Predicate * ))
+ zzMake0;
+ {
+
+ char *name=NULL;
+ PredEntry *predEntry=NULL;
+ Predicate *predExpr=NULL;
+ if ( (LA(1)==TokenTerm) ) {
+ zzmatch(TokenTerm);
+ name=mystrdup(LATEXT(1));
+ zzCONSUME;
+
+
+ predEntry=(PredEntry *) hash_get(Pname,name);
+ if (predEntry == NULL) {
+ warnFL(eMsg1("no previously defined #pred with name \"%s\"",name),
+ FileStr[CurFile],zzline);
+ name=NULL;
+ _retv=NULL;
+ } else {
+ predExpr=predicate_dup(predEntry->pred);
+ predExpr->predEntry=predEntry;
+ _retv=predExpr;
+ };
+ }
+ else {
+ if ( (LA(1)==114) ) {
+ zzmatch(114); zzCONSUME;
+ predExpr = predOrExpr();
+
+ zzmatch(115);
+
+ _retv=predExpr;
+ zzCONSUME;
+
+ }
+ else {
+ if ( (LA(1)==103) ) {
+ zzmatch(103); zzCONSUME;
+ predExpr = predPrimary();
+
+
+ predExpr->inverted=!predExpr->inverted;
+ _retv=predExpr;
+ }
+ else {zzFAIL(1,zzerr13,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}
+ }
+ }
+ zzEXIT(zztasp1);
+ return _retv;
+fail:
+ zzEXIT(zztasp1);
+
+ predicate_free(predExpr);
+ zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText);
+ zzresynch(setwd3, 0x80);
+ return _retv;
+ }
+}
+
+void
+#ifdef __USE_PROTOS
+aLexclass(void)
+#else
+aLexclass()
+#endif
+{
+ zzRULE;
+ zzBLOCK(zztasp1);
+ zzMake0;
+ {
+ zzmatch(116); zzCONSUME;
+ zzmatch(TokenTerm);
+ lexclass(mystrdup(LATEXT(1)));
+ zzCONSUME;
+
+ zzEXIT(zztasp1);
+ return;
+fail:
+ zzEXIT(zztasp1);
+ CannotContinue=TRUE;
+ zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText);
+ zzresynch(setwd4, 0x1);
+ }
+}
+
+void
+#ifdef __USE_PROTOS
+error(void)
+#else
+error()
+#endif
+{
+ zzRULE;
+ zzBLOCK(zztasp1);
+ zzMake0;
+ {
+ char *t=NULL; ECnode *e; int go=1; TermEntry *p;
+ zzmatch(117); zzCONSUME;
+ {
+ zzBLOCK(zztasp2);
+ zzMake0;
+ {
+ ;
+ if ( (LA(1)==TokenTerm) ) {
+ zzmatch(TokenTerm);
+ t=mystrdup(LATEXT(1));
+ zzCONSUME;
+
+ }
+ else {
+ if ( (LA(1)==QuotedTerm) ) {
+ zzmatch(QuotedTerm);
+ t=mystrdup(LATEXT(1));
+ zzCONSUME;
+
+ }
+ else {zzFAIL(1,zzerr14,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}
+ }
+ zzEXIT(zztasp2);
+ }
+ }
+ e = newECnode;
+ require(e!=NULL, "cannot allocate error class node");
+ e->lexclass = CurrentLexClass;
+ if ( Tnum( (t=StripQuotes(t)) ) == 0 )
+ {
+ if ( hash_get(Texpr, t) != NULL )
+ warn(eMsg1("errclass name conflicts with regular expression '%s'",t));
+ e->tok = addTname( t );
+ set_orel(e->tok, &imag_tokens);
+ require((p=(TermEntry *)hash_get(Tname, t)) != NULL,
+ "hash table mechanism is broken");
+ p->classname = 1; /* entry is errclass name, not token */
+ list_add(&eclasses, (char *)e);
+ }
+ else
+ {
+ warn(eMsg1("redefinition of errclass or conflict w/token or tokclass '%s'; ignored",t));
+ free( (char *)e );
+ go=0;
+}
+ zzmatch(102); zzCONSUME;
+ {
+ zzBLOCK(zztasp2);
+ zzMake0;
+ {
+ if ( (LA(1)==NonTerminal) ) {
+ zzmatch(NonTerminal);
+ if ( go ) t=mystrdup(LATEXT(1));
+ zzCONSUME;
+
+ }
+ else {
+ if ( (LA(1)==TokenTerm) ) {
+ zzmatch(TokenTerm);
+ if ( go ) t=mystrdup(LATEXT(1));
+ zzCONSUME;
+
+ }
+ else {
+ if ( (LA(1)==QuotedTerm) ) {
+ zzmatch(QuotedTerm);
+ if ( go ) t=mystrdup(LATEXT(1));
+ zzCONSUME;
+
+ }
+ else {zzFAIL(1,zzerr15,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}
+ }
+ }
+ zzEXIT(zztasp2);
+ }
+ }
+ if ( go ) list_add(&(e->elist), t);
+ {
+ zzBLOCK(zztasp2);
+ zzMake0;
+ {
+ while ( (setwd4[LA(1)]&0x2) ) {
+ {
+ zzBLOCK(zztasp3);
+ zzMake0;
+ {
+ if ( (LA(1)==NonTerminal) ) {
+ zzmatch(NonTerminal);
+ if ( go ) t=mystrdup(LATEXT(1));
+ zzCONSUME;
+
+ }
+ else {
+ if ( (LA(1)==TokenTerm) ) {
+ zzmatch(TokenTerm);
+ if ( go ) t=mystrdup(LATEXT(1));
+ zzCONSUME;
+
+ }
+ else {
+ if ( (LA(1)==QuotedTerm) ) {
+ zzmatch(QuotedTerm);
+ if ( go ) t=mystrdup(LATEXT(1));
+ zzCONSUME;
+
+ }
+ else {zzFAIL(1,zzerr16,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}
+ }
+ }
+ zzEXIT(zztasp3);
+ }
+ }
+ if ( go ) list_add(&(e->elist), t);
+ zzLOOP(zztasp2);
+ }
+ zzEXIT(zztasp2);
+ }
+ }
+ zzmatch(98); zzCONSUME;
+ zzEXIT(zztasp1);
+ return;
+fail:
+ zzEXIT(zztasp1);
+ CannotContinue=TRUE;
+ zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText);
+ zzresynch(setwd4, 0x4);
+ }
+}
+
+void
+#ifdef __USE_PROTOS
+tclass(void)
+#else
+tclass()
+#endif
+{
+ zzRULE;
+ zzBLOCK(zztasp1);
+ zzMake0;
+ {
+ char *t=NULL; TCnode *e; int go=1,tok,totok; TermEntry *p, *term, *toterm;
+ char *akaString=NULL; int save_file; int save_line;
+ char *totext=NULL;
+ zzmatch(118); zzCONSUME;
+ zzmatch(TokenTerm);
+ t=mystrdup(LATEXT(1));
+ zzCONSUME;
+
+ e = newTCnode;
+ require(e!=NULL, "cannot allocate token class node");
+ e->lexclass = CurrentLexClass;
+ if ( Tnum( t ) == 0 )
+ {
+ e->tok = addTname( t );
+ set_orel(e->tok, &imag_tokens);
+ set_orel(e->tok, &tokclasses);
+ require((p=(TermEntry *)hash_get(Tname, t)) != NULL,
+ "hash table mechanism is broken");
+ p->classname = 1; /* entry is class name, not token */
+ p->tclass = e; /* save ptr to this tclass def */
+ list_add(&tclasses, (char *)e);
+ }
+ else
+ {
+ warn(eMsg1("redefinition of tokclass or conflict w/token '%s'; ignored",t));
+ free( (char *)e );
+ go=0;
+}
+ {
+ zzBLOCK(zztasp2);
+ zzMake0;
+ {
+ if ( (LA(1)==114) ) {
+ zzmatch(114); zzCONSUME;
+ zzmatch(QuotedTerm);
+ akaString=mystrdup(StripQuotes(LATEXT(1)));
+ /* MR11 */ save_file=CurFile;save_line=zzline;
+ /* MR23 */
+ zzCONSUME;
+
+ zzmatch(115); zzCONSUME;
+ }
+ else {
+ if ( (LA(1)==102) ) {
+ }
+ else {zzFAIL(1,zzerr17,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}
+ }
+ zzEXIT(zztasp2);
+ }
+ }
+
+ /* MR23 */ if (p!= NULL && akaString != NULL) {
+ /* MR23 */ if (p->akaString != NULL) {
+ /* MR23 */ if (strcmp(p->akaString,akaString) != 0) {
+ /* MR23 */ warnFL(eMsg2("this #tokclass statment conflicts with a previous #tokclass %s(\"%s\") statement",
+ /* MR23 */ t,p->akaString),
+ /* MR23 */ FileStr[save_file],save_line);
+ /* MR23 */ };
+ /* MR23 */ } else {
+ /* MR23 */ p->akaString=akaString;
+ /* MR23 */ };
+ /* MR23 */ };
+ /* MR23 */
+ zzmatch(102); zzCONSUME;
+ {
+ zzBLOCK(zztasp2);
+ int zzcnt=1;
+ zzMake0;
+ {
+ do {
+ {
+ zzBLOCK(zztasp3);
+ zzMake0;
+ {
+ if ( (LA(1)==TokenTerm) ) {
+ zzmatch(TokenTerm);
+ if ( go ) {
+ term = (TermEntry *) hash_get(Tname, LATEXT(1));
+ if ( term==NULL && UserDefdTokens ) {
+ err("implicit token definition not allowed with #tokdefs");
+ go = 0;
+ }
+ else {t=mystrdup(LATEXT(1)); tok=addTname(LATEXT(1));}
+ }
+ zzCONSUME;
+
+ {
+ zzBLOCK(zztasp4);
+ zzMake0;
+ {
+ if ( (LA(1)==119) ) {
+ zzmatch(119); zzCONSUME;
+ zzmatch(TokenTerm);
+ if ( go ) {
+ toterm = (TermEntry *) hash_get(Tname, LATEXT(1));
+ if ( toterm==NULL && UserDefdTokens ) {
+ err("implicit token definition not allowed with #tokdefs");
+ go = 0;
+ } else {
+ totext=mystrdup(LATEXT(1)); totok=addTname(LATEXT(1));
+ }
+ }
+ zzCONSUME;
+
+ }
+ else {
+ if ( (setwd4[LA(1)]&0x8) ) {
+ }
+ else {zzFAIL(1,zzerr18,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}
+ }
+ zzEXIT(zztasp4);
+ }
+ }
+ }
+ else {
+ if ( (LA(1)==QuotedTerm) ) {
+ zzmatch(QuotedTerm);
+ if ( go ) {
+ term = (TermEntry *) hash_get(Texpr, LATEXT(1));
+ if ( term==NULL && UserDefdTokens ) {
+ err("implicit token definition not allowed with #tokdefs");
+ go = 0;
+ }
+ else {t=mystrdup(LATEXT(1)); tok=addTexpr(LATEXT(1));}
+ }
+ zzCONSUME;
+
+ }
+ else {zzFAIL(1,zzerr19,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}
+ }
+ zzEXIT(zztasp3);
+ }
+ }
+ if ( go ) {
+ if (totext == NULL) {
+ list_add(&(e->tlist), t);
+ } else {
+ list_add(&(e->tlist),"..");
+ list_add(&(e->tlist),t);
+ list_add(&(e->tlist),totext);
+ }
+ totext=NULL;
+ }
+ zzLOOP(zztasp2);
+ } while ( (setwd4[LA(1)]&0x10) );
+ zzEXIT(zztasp2);
+ }
+ }
+ zzmatch(98); zzCONSUME;
+ zzEXIT(zztasp1);
+ return;
+fail:
+ zzEXIT(zztasp1);
+ CannotContinue=TRUE;
+ zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText);
+ zzresynch(setwd4, 0x20);
+ }
+}
+
+void
+#ifdef __USE_PROTOS
+token(void)
+#else
+token()
+#endif
+{
+ zzRULE;
+ zzBLOCK(zztasp1);
+ zzMake0;
+ {
+ char *t=NULL, *e=NULL, *a=NULL; int tnum=0;
+ char *akaString=NULL; TermEntry *te;int save_file=0,save_line=0;
+ zzmatch(120);
+ tokenActionActive=1;
+ zzCONSUME;
+
+ {
+ zzBLOCK(zztasp2);
+ zzMake0;
+ {
+ if ( (LA(1)==TokenTerm) ) {
+ zzmatch(TokenTerm);
+ t=mystrdup(LATEXT(1));
+ zzCONSUME;
+
+ {
+ zzBLOCK(zztasp3);
+ zzMake0;
+ {
+ if ( (LA(1)==114) ) {
+ zzmatch(114); zzCONSUME;
+ zzmatch(QuotedTerm);
+ akaString=mystrdup(StripQuotes(LATEXT(1)));
+ /* MR11 */ save_file=CurFile;save_line=zzline;
+ /* MR11 */
+ zzCONSUME;
+
+ zzmatch(115); zzCONSUME;
+ }
+ else {
+ if ( (setwd4[LA(1)]&0x40) ) {
+ }
+ else {zzFAIL(1,zzerr20,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}
+ }
+ zzEXIT(zztasp3);
+ }
+ }
+ {
+ zzBLOCK(zztasp3);
+ zzMake0;
+ {
+ if ( (LA(1)==121) ) {
+ zzmatch(121); zzCONSUME;
+ zzmatch(122);
+ tnum = atoi(LATEXT(1));
+ zzCONSUME;
+
+ }
+ else {
+ if ( (setwd4[LA(1)]&0x80) ) {
+ }
+ else {zzFAIL(1,zzerr21,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}
+ }
+ zzEXIT(zztasp3);
+ }
+ }
+ }
+ else {
+ if ( (setwd5[LA(1)]&0x1) ) {
+ }
+ else {zzFAIL(1,zzerr22,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}
+ }
+ zzEXIT(zztasp2);
+ }
+ }
+ {
+ zzBLOCK(zztasp2);
+ zzMake0;
+ {
+ if ( (LA(1)==QuotedTerm) ) {
+ zzmatch(QuotedTerm);
+ e=mystrdup(LATEXT(1));
+ zzCONSUME;
+
+ }
+ else {
+ if ( (setwd5[LA(1)]&0x2) ) {
+ }
+ else {zzFAIL(1,zzerr23,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}
+ }
+ zzEXIT(zztasp2);
+ }
+ }
+ {
+ zzBLOCK(zztasp2);
+ zzMake0;
+ {
+ if ( (LA(1)==Action) ) {
+ zzmatch(Action);
+
+ a = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char));
+ require(a!=NULL, "rule token: cannot allocate action");
+ strcpy(a, LATEXT(1));
+ zzCONSUME;
+
+ }
+ else {
+ if ( (setwd5[LA(1)]&0x4) ) {
+ }
+ else {zzFAIL(1,zzerr24,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}
+ }
+ zzEXIT(zztasp2);
+ }
+ }
+ {
+ zzBLOCK(zztasp2);
+ zzMake0;
+ {
+ if ( (LA(1)==107) ) {
+ zzmatch(107); zzCONSUME;
+ }
+ else {
+ if ( (setwd5[LA(1)]&0x8) ) {
+ }
+ else {zzFAIL(1,zzerr25,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}
+ }
+ zzEXIT(zztasp2);
+ }
+ }
+ chkToken(t, e, a, tnum);
+ if (t != NULL) {
+ te=(TermEntry *)hash_get(Tname,t);
+ if (te != NULL && akaString != NULL) {
+ if (te->akaString != NULL) {
+ if (strcmp(te->akaString,akaString) != 0) {
+ warnFL(eMsg2("this #token statment conflicts with a previous #token %s(\"%s\") statement",
+ t,te->akaString),
+ FileStr[save_file],save_line);
+ };
+ } else {
+ te->akaString=akaString;
+ };
+ };
+ };
+ zzEXIT(zztasp1);
+ return;
+fail:
+ zzEXIT(zztasp1);
+ CannotContinue=TRUE;
+ zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText);
+ zzresynch(setwd5, 0x10);
+ }
+}
+
+void
+#ifdef __USE_PROTOS
+block(set * toksrefd,set * rulesrefd)
+#else
+block(toksrefd,rulesrefd)
+ set *toksrefd;
+set *rulesrefd ;
+#endif
+{
+ zzRULE;
+ zzBLOCK(zztasp1);
+ zzMake0;
+ {
+
+ Graph g, b;
+ set saveblah;
+ int saveinalt = inAlt;
+ ExceptionGroup *eg;
+ * toksrefd = empty;
+ * rulesrefd = empty;
+ set_clr(AST_nodes_refd_in_actions);
+ CurBlockID++;
+ /* MR23 */ CurBlockID_array[BlkLevel] = CurBlockID;
+ CurAltNum = 1;
+ /* MR23 */ CurAltNum_array[BlkLevel] = CurAltNum;
+ saveblah = attribsRefdFromAction;
+ attribsRefdFromAction = empty;
+ alt( toksrefd,rulesrefd );
+ b = g = zzaArg(zztasp1,1);
+
+ if ( ((Junction *)g.left)->p1->ntype == nAction )
+ {
+ ActionNode *actionNode=(ActionNode *)
+ ( ( (Junction *)g.left) ->p1);
+ if (!actionNode->is_predicate )
+ {
+ actionNode->init_action = TRUE;
+ /* MR12c */ if (actionNode->noHoist) {
+ /* MR12c */ errFL("<<nohoist>> appears as init-action - use <<>> <<nohoist>>",
+ /* MR12c */ FileStr[actionNode->file],actionNode->line);
+ /* MR12c */ };
+ }
+ }
+ ((Junction *)g.left)->blockid = CurBlockID;
+ {
+ zzBLOCK(zztasp2);
+ zzMake0;
+ {
+ while ( (LA(1)==133) ) {
+ eg = exception_group();
+
+
+ if ( eg!=NULL ) {
+ /* MR7 ***** eg->altID = makeAltID(CurBlockID,CurAltNum); *****/
+ /* MR7 ***** CurAltStart->exception_label = eg->altID; *****/
+ list_add(&CurExGroups, (void *)eg);
+ }
+ zzLOOP(zztasp2);
+ }
+ zzEXIT(zztasp2);
+ }
+ }
+ CurAltNum++;
+ /* MR23 */ CurAltNum_array[BlkLevel] = CurAltNum;
+ {
+ zzBLOCK(zztasp2);
+ zzMake0;
+ {
+ while ( (LA(1)==123) ) {
+ zzmatch(123);
+ inAlt=1;
+ zzCONSUME;
+
+ alt( toksrefd,rulesrefd );
+ g = Or(g, zzaArg(zztasp2,2));
+
+ ((Junction *)g.left)->blockid = CurBlockID;
+ {
+ zzBLOCK(zztasp3);
+ zzMake0;
+ {
+ while ( (LA(1)==133) ) {
+ eg = exception_group();
+
+
+ if ( eg!=NULL ) {
+ /* MR7 ***** eg->altID = makeAltID(CurBlockID,CurAltNum); *****/
+ /* MR7 ***** CurAltStart->exception_label = eg->altID; *****/
+ list_add(&CurExGroups, (void *)eg);
+ }
+ zzLOOP(zztasp3);
+ }
+ zzEXIT(zztasp3);
+ }
+ }
+ CurAltNum++;
+ /* MR23 */ CurAltNum_array[BlkLevel] = CurAltNum;
+ zzLOOP(zztasp2);
+ }
+ zzEXIT(zztasp2);
+ }
+ }
+ zzaArg(zztasp1,0) = b;
+ attribsRefdFromAction = saveblah; inAlt = saveinalt;
+ zzEXIT(zztasp1);
+ return;
+fail:
+ zzEXIT(zztasp1);
+ CannotContinue=TRUE;
+ zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText);
+ zzresynch(setwd5, 0x20);
+ }
+}
+
+void
+#ifdef __USE_PROTOS
+alt(set * toksrefd,set * rulesrefd)
+#else
+alt(toksrefd,rulesrefd)
+ set *toksrefd;
+set *rulesrefd ;
+#endif
+{
+ zzRULE;
+ zzBLOCK(zztasp1);
+ zzMake0;
+ {
+ int n=0; Graph g; int e_num=0, old_not=0; Node *node; set elems, dif;
+ int first_on_line = 1, use_def_MT_handler = 0;
+ g.left=NULL; g.right=NULL;
+
+ CurAltStart = NULL;
+ elems = empty;
+ inAlt = 1;
+ {
+ zzBLOCK(zztasp2);
+ zzMake0;
+ {
+ if ( (LA(1)==88) ) {
+ zzmatch(88);
+ use_def_MT_handler = 1;
+ zzCONSUME;
+
+ }
+ else {
+ if ( (setwd5[LA(1)]&0x40) ) {
+ }
+ else {zzFAIL(1,zzerr26,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}
+ }
+ zzEXIT(zztasp2);
+ }
+ }
+ {
+ zzBLOCK(zztasp2);
+ zzMake0;
+ {
+ ;
+ while ( (setwd5[LA(1)]&0x80) ) {
+ {
+ zzBLOCK(zztasp3);
+ zzMake0;
+ {
+ old_not=0;
+ if ( (LA(1)==124) ) {
+ zzmatch(124);
+ old_not=1;
+ zzCONSUME;
+
+ }
+ else {
+ if ( (setwd6[LA(1)]&0x1) ) {
+ }
+ else {zzFAIL(1,zzerr27,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}
+ }
+ zzEXIT(zztasp3);
+ }
+ }
+ node = element( old_not, first_on_line, use_def_MT_handler );
+
+ if ( node!=NULL && node->ntype!=nAction ) first_on_line = 0;
+
+ if ( zzaArg(zztasp2,2 ).left!=NULL ) {
+ g = Cat(g, zzaArg(zztasp2,2));
+ n++;
+ if ( node!=NULL ) {
+ if ( node->ntype!=nAction ) e_num++;
+ /* record record number of all rule and token refs */
+ if ( node->ntype==nToken ) {
+ TokNode *tk = (TokNode *)((Junction *)zzaArg(zztasp2,2 ).left)->p1;
+ tk->elnum = e_num;
+ set_orel(e_num, &elems);
+ }
+ else if ( node->ntype==nRuleRef ) {
+ RuleRefNode *rn = (RuleRefNode *)((Junction *)zzaArg(zztasp2,2 ).left)->p1;
+ rn->elnum = e_num;
+ set_orel(e_num, rulesrefd);
+ }
+ }
+ }
+ zzLOOP(zztasp2);
+ }
+ zzEXIT(zztasp2);
+ }
+ }
+ if ( n == 0 ) g = emptyAlt();
+ zzaArg(zztasp1,0) = g;
+ /* We want to reduce number of LT(i) calls and the number of
+ * local attribute variables in C++ mode (for moment, later we'll
+ * do for C also). However, if trees are being built, they
+ * require most of the attrib variables to create the tree nodes
+ * with; therefore, we gen a token ptr for each token ref in C++
+ */
+ if ( GenCC && !GenAST )
+ {
+ /* This now free's the temp set -ATG 5/6/95 */
+ set temp;
+ temp = set_and(elems, attribsRefdFromAction);
+ set_orin( toksrefd, temp);
+ set_free(temp);
+}
+else set_orin( toksrefd, elems);
+if ( GenCC ) {
+ dif = set_dif(attribsRefdFromAction, elems);
+ if ( set_deg(dif)>0 )
+ err("one or more $i in action(s) refer to non-token elements");
+ set_free(dif);
+}
+set_free(elems);
+set_free(attribsRefdFromAction);
+inAlt = 0;
+ zzEXIT(zztasp1);
+ return;
+fail:
+ zzEXIT(zztasp1);
+ CannotContinue=TRUE;
+ zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText);
+ zzresynch(setwd6, 0x2);
+ }
+}
+
+LabelEntry *
+#ifdef __USE_PROTOS
+element_label(void)
+#else
+element_label()
+#endif
+{
+ LabelEntry * _retv;
+ zzRULE;
+ zzBLOCK(zztasp1);
+ PCCTS_PURIFY(_retv,sizeof(LabelEntry * ))
+ zzMake0;
+ {
+ TermEntry *t=NULL; LabelEntry *l=NULL; RuleEntry *r=NULL; char *lab;
+ zzmatch(LABEL);
+ lab = mystrdup(LATEXT(1));
+ zzCONSUME;
+
+
+ UsedNewStyleLabel = 1;
+ if ( UsedOldStyleAttrib ) err("cannot mix with new-style labels with old-style $i");
+ t = (TermEntry *) hash_get(Tname, lab);
+ if ( t==NULL ) t = (TermEntry *) hash_get(Texpr, lab);
+ if ( t==NULL ) r = (RuleEntry *) hash_get(Rname, lab);
+ if ( t!=NULL ) {
+ err(eMsg1("label definition clashes with token/tokclass definition: '%s'", lab));
+ _retv = NULL;
+ }
+ else if ( r!=NULL ) {
+ err(eMsg1("label definition clashes with rule definition: '%s'", lab));
+ _retv = NULL;
+ }
+ else {
+ /* we don't clash with anybody else */
+ l = (LabelEntry *) hash_get(Elabel, lab);
+ if ( l==NULL ) { /* ok to add new element label */
+ l = (LabelEntry *)hash_add(Elabel,
+ lab,
+ (Entry *)newLabelEntry(lab));
+ /* add to list of element labels for this rule */
+ list_add(&CurElementLabels, (void *)lab);
+ /* MR7 */ leAdd(l); /* list of labels waiting for exception group definitions */
+ _retv = l;
+ }
+ else {
+ err(eMsg1("label definitions must be unique per rule: '%s'", lab));
+ _retv = NULL;
+}
+}
+ zzmatch(106); zzCONSUME;
+ zzEXIT(zztasp1);
+ return _retv;
+fail:
+ zzEXIT(zztasp1);
+ zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText);
+ zzresynch(setwd6, 0x4);
+ return _retv;
+ }
+}
+
+Node *
+#ifdef __USE_PROTOS
+element(int old_not,int first_on_line,int use_def_MT_handler)
+#else
+element(old_not,first_on_line,use_def_MT_handler)
+ int old_not;
+int first_on_line;
+int use_def_MT_handler ;
+#endif
+{
+ Node * _retv;
+ zzRULE;
+ zzBLOCK(zztasp1);
+ PCCTS_PURIFY(_retv,sizeof(Node * ))
+ zzMake0;
+ {
+
+ Attrib blk;
+ Predicate *pred = NULL;
+ int local_use_def_MT_handler=0;
+ ActionNode *act;
+ RuleRefNode *rr;
+ set toksrefd, rulesrefd;
+ TermEntry *term;
+ TokNode *p=NULL; RuleRefNode *q; int approx=0;
+ LabelEntry *label=NULL;
+ int predMsgDone=0;
+ int semDepth=0;
+ int ampersandStyle;
+ int height; /* MR11 */
+ int equal_height; /* MR11 */
+
+ char* pFirstSetSymbol = NULL; /* MR21 */
+
+ _retv = NULL;
+ if ( (setwd6[LA(1)]&0x8) ) {
+ {
+ zzBLOCK(zztasp2);
+ zzMake0;
+ {
+ if ( (LA(1)==LABEL) ) {
+ label = element_label();
+
+ }
+ else {
+ if ( (setwd6[LA(1)]&0x10) ) {
+ }
+ else {zzFAIL(1,zzerr28,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}
+ }
+ zzEXIT(zztasp2);
+ }
+ }
+ {
+ zzBLOCK(zztasp2);
+ zzMake0;
+ {
+ if ( (LA(1)==TokenTerm) ) {
+ zzmatch(TokenTerm);
+
+ term = (TermEntry *) hash_get(Tname, LATEXT(1));
+ if ( term==NULL && UserDefdTokens ) {
+ err("implicit token definition not allowed with #tokdefs");
+ zzaRet.left = zzaRet.right = NULL;
+ }
+ else {
+ zzaRet = buildToken(LATEXT(1));
+ p=((TokNode *)((Junction *)zzaRet.left)->p1);
+ term = (TermEntry *) hash_get(Tname, LATEXT(1));
+ require( term!= NULL, "hash table mechanism is broken");
+ p->tclass = term->tclass;
+ p->complement = old_not;
+ if ( label!=NULL ) {
+ p->el_label = label->str;
+ label->elem = (Node *)p;
+ }
+ }
+ zzCONSUME;
+
+ {
+ zzBLOCK(zztasp3);
+ zzMake0;
+ {
+ if ( (LA(1)==119) ) {
+ zzmatch(119); zzCONSUME;
+ {
+ zzBLOCK(zztasp4);
+ zzMake0;
+ {
+ if ( (LA(1)==QuotedTerm) ) {
+ zzmatch(QuotedTerm);
+ if ( p!=NULL ) setUpperRange(p, LATEXT(1));
+ zzCONSUME;
+
+ }
+ else {
+ if ( (LA(1)==TokenTerm) ) {
+ zzmatch(TokenTerm);
+ if ( p!=NULL ) setUpperRange(p, LATEXT(1));
+ zzCONSUME;
+
+ }
+ else {zzFAIL(1,zzerr29,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}
+ }
+ zzEXIT(zztasp4);
+ }
+ }
+ }
+ else {
+ if ( (setwd6[LA(1)]&0x20) ) {
+ }
+ else {zzFAIL(1,zzerr30,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}
+ }
+ zzEXIT(zztasp3);
+ }
+ }
+
+ if ( p!=NULL && (p->upper_range!=0 || p->tclass || old_not) )
+ list_add(&MetaTokenNodes, (void *)p);
+ {
+ zzBLOCK(zztasp3);
+ zzMake0;
+ {
+ if ( (LA(1)==125) ) {
+ zzmatch(125);
+ if ( p!=NULL ) p->astnode=ASTroot;
+ zzCONSUME;
+
+ }
+ else {
+ if ( (setwd6[LA(1)]&0x40) ) {
+ if ( p!=NULL ) p->astnode=ASTchild;
+ }
+ else {
+ if ( (LA(1)==103) ) {
+ zzmatch(103);
+ if ( p!=NULL ) p->astnode=ASTexclude;
+ zzCONSUME;
+
+ }
+ else {zzFAIL(1,zzerr31,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}
+ }
+ }
+ zzEXIT(zztasp3);
+ }
+ }
+ {
+ zzBLOCK(zztasp3);
+ zzMake0;
+ {
+ if ( (LA(1)==88) ) {
+ zzmatch(88);
+ local_use_def_MT_handler = 1;
+ zzCONSUME;
+
+ }
+ else {
+ if ( (setwd6[LA(1)]&0x80) ) {
+ }
+ else {zzFAIL(1,zzerr32,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}
+ }
+ zzEXIT(zztasp3);
+ }
+ }
+
+ if ( p!=NULL && first_on_line ) {
+ CurAltStart = (Junction *)zzaRet.left;
+ altAdd(CurAltStart); /* MR7 */
+ p->altstart = CurAltStart;
+ }
+ if ( p!=NULL )
+ p->use_def_MT_handler = use_def_MT_handler || local_use_def_MT_handler;
+ _retv = (Node *)p;
+ }
+ else {
+ if ( (LA(1)==QuotedTerm) ) {
+ zzmatch(QuotedTerm);
+
+ term = (TermEntry *) hash_get(Texpr, LATEXT(1));
+ if ( term==NULL && UserDefdTokens ) {
+ err("implicit token definition not allowed with #tokdefs");
+ zzaRet.left = zzaRet.right = NULL;
+ }
+ else {
+ zzaRet = buildToken(LATEXT(1)); p=((TokNode *)((Junction *)zzaRet.left)->p1);
+ p->complement = old_not;
+ if ( label!=NULL ) {
+ p->el_label = label->str;
+ label->elem = (Node *)p;
+ }
+ }
+ zzCONSUME;
+
+ {
+ zzBLOCK(zztasp3);
+ zzMake0;
+ {
+ if ( (LA(1)==119) ) {
+ zzmatch(119); zzCONSUME;
+ {
+ zzBLOCK(zztasp4);
+ zzMake0;
+ {
+ if ( (LA(1)==QuotedTerm) ) {
+ zzmatch(QuotedTerm);
+ if ( p!=NULL ) setUpperRange(p, LATEXT(1));
+ zzCONSUME;
+
+ }
+ else {
+ if ( (LA(1)==TokenTerm) ) {
+ zzmatch(TokenTerm);
+ if ( p!=NULL ) setUpperRange(p, LATEXT(1));
+ zzCONSUME;
+
+ }
+ else {zzFAIL(1,zzerr33,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}
+ }
+ zzEXIT(zztasp4);
+ }
+ }
+ }
+ else {
+ if ( (setwd7[LA(1)]&0x1) ) {
+ }
+ else {zzFAIL(1,zzerr34,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}
+ }
+ zzEXIT(zztasp3);
+ }
+ }
+ {
+ zzBLOCK(zztasp3);
+ zzMake0;
+ {
+ if ( (LA(1)==125) ) {
+ zzmatch(125);
+ if ( p!=NULL ) p->astnode=ASTroot;
+ zzCONSUME;
+
+ }
+ else {
+ if ( (setwd7[LA(1)]&0x2) ) {
+ if ( p!=NULL ) p->astnode=ASTchild;
+ }
+ else {
+ if ( (LA(1)==103) ) {
+ zzmatch(103);
+ if ( p!=NULL ) p->astnode=ASTexclude;
+ zzCONSUME;
+
+ }
+ else {zzFAIL(1,zzerr35,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}
+ }
+ }
+ zzEXIT(zztasp3);
+ }
+ }
+ {
+ zzBLOCK(zztasp3);
+ zzMake0;
+ {
+ if ( (LA(1)==88) ) {
+ zzmatch(88);
+ local_use_def_MT_handler = 1;
+ zzCONSUME;
+
+ }
+ else {
+ if ( (setwd7[LA(1)]&0x4) ) {
+ }
+ else {zzFAIL(1,zzerr36,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}
+ }
+ zzEXIT(zztasp3);
+ }
+ }
+
+ if ( p!=NULL && (p->upper_range!=0 || p->tclass || old_not) )
+ list_add(&MetaTokenNodes, (void *)p);
+
+ if ( first_on_line ) {
+ CurAltStart = (Junction *)zzaRet.left;
+ altAdd(CurAltStart); /* MR7 */
+ p->altstart = CurAltStart;
+ }
+ if ( p!=NULL )
+ p->use_def_MT_handler = use_def_MT_handler || local_use_def_MT_handler;
+ _retv = (Node *)p;
+ }
+ else {
+ if ( (LA(1)==WildCard) ) {
+ if ( old_not ) warn("~ WILDCARD is an undefined operation (implies 'nothing')");
+ zzmatch(WildCard);
+ zzaRet = buildWildCard(LATEXT(1)); p=((TokNode *)((Junction *)zzaRet.left)->p1);
+ zzCONSUME;
+
+ {
+ zzBLOCK(zztasp3);
+ zzMake0;
+ {
+ if ( (LA(1)==125) ) {
+ zzmatch(125);
+ p->astnode=ASTroot;
+ zzCONSUME;
+
+ }
+ else {
+ if ( (setwd7[LA(1)]&0x8) ) {
+ p->astnode=ASTchild;
+ }
+ else {
+ if ( (LA(1)==103) ) {
+ zzmatch(103);
+ p->astnode=ASTexclude;
+ zzCONSUME;
+
+ }
+ else {zzFAIL(1,zzerr37,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}
+ }
+ }
+ zzEXIT(zztasp3);
+ }
+ }
+ list_add(&MetaTokenNodes, (void *)p);
+
+ if ( first_on_line ) {
+ CurAltStart = (Junction *)zzaRet.left;
+ altAdd(CurAltStart); /* MR7 */
+ p->altstart = CurAltStart;
+ if ( label!=NULL ) {
+ p->el_label = label->str;
+ label->elem = (Node *)p;
+ }
+ }
+ _retv = (Node *)p;
+ }
+ else {
+ if ( (LA(1)==NonTerminal) ) {
+ if ( old_not ) warn("~ NONTERMINAL is an undefined operation");
+ zzmatch(NonTerminal);
+ zzaRet = buildRuleRef(LATEXT(1));
+ zzCONSUME;
+
+ {
+ zzBLOCK(zztasp3);
+ zzMake0;
+ {
+ if ( (LA(1)==103) ) {
+ zzmatch(103);
+ q = (RuleRefNode *) ((Junction *)zzaRet.left)->p1;
+ q->astnode=ASTexclude;
+ zzCONSUME;
+
+ }
+ else {
+ if ( (setwd7[LA(1)]&0x10) ) {
+ }
+ else {zzFAIL(1,zzerr38,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}
+ }
+ zzEXIT(zztasp3);
+ }
+ }
+ {
+ zzBLOCK(zztasp3);
+ zzMake0;
+ {
+ if ( (setwd7[LA(1)]&0x20) ) {
+ {
+ zzBLOCK(zztasp4);
+ zzMake0;
+ {
+ if ( (LA(1)==104) ) {
+ zzmatch(104); zzCONSUME;
+ }
+ else {
+ if ( (LA(1)==PassAction) ) {
+ }
+ else {zzFAIL(1,zzerr39,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}
+ }
+ zzEXIT(zztasp4);
+ }
+ }
+ zzmatch(PassAction);
+ addParm(((Junction *)zzaRet.left)->p1, LATEXT(1));
+ zzCONSUME;
+
+ }
+ else {
+ if ( (setwd7[LA(1)]&0x40) ) {
+ }
+ else {zzFAIL(1,zzerr40,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}
+ }
+ zzEXIT(zztasp3);
+ }
+ }
+ rr=(RuleRefNode *) ((Junction *)zzaRet.left)->p1;
+ {
+ zzBLOCK(zztasp3);
+ zzMake0;
+ {
+ char *a;
+ if ( (LA(1)==105) ) {
+ zzmatch(105); zzCONSUME;
+ zzmatch(PassAction);
+
+ a = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char));
+ require(a!=NULL, "rule element: cannot allocate assignment");
+ strcpy(a, LATEXT(1));
+ rr->assign = a;
+ zzCONSUME;
+
+ }
+ else {
+ if ( (setwd7[LA(1)]&0x80) ) {
+ }
+ else {zzFAIL(1,zzerr41,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}
+ }
+ zzEXIT(zztasp3);
+ }
+ }
+
+ if ( label!=NULL ) {
+ rr->el_label = label->str;
+ label->elem = (Node *)rr;
+ }
+ if ( first_on_line ) {
+ CurAltStart = (Junction *)zzaRet.left;
+ altAdd(CurAltStart); /* MR7 */
+ ((RuleRefNode *)((Junction *)zzaRet.left)->p1)->altstart = CurAltStart;
+ }
+ _retv = (Node *)rr;
+ }
+ else {zzFAIL(1,zzerr42,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}
+ }
+ }
+ }
+ zzEXIT(zztasp2);
+ }
+ }
+ }
+ else {
+ if ( (LA(1)==Action) ) {
+ if ( old_not ) warn("~ ACTION is an undefined operation");
+ zzmatch(Action);
+ zzaArg(zztasp1,0) = buildAction(LATEXT(1),action_file,action_line, 0);
+ zzCONSUME;
+
+ if ( first_on_line ) { /* MR7 */
+ CurAltStart = (Junction *)zzaArg(zztasp1,0 ).left; /* MR7 */
+ altAdd(CurAltStart); /* MR7 */
+ };
+ _retv = (Node *) ((Junction *)zzaArg(zztasp1,0 ).left)->p1;
+ }
+ else {
+ if ( (LA(1)==Pred) ) {
+ if ( old_not ) warn("~ SEMANTIC-PREDICATE is an undefined operation");
+ zzmatch(Pred);
+ zzaArg(zztasp1,0) = buildAction(LATEXT(1),action_file,action_line, 1);
+ zzCONSUME;
+
+ act = (ActionNode *) ((Junction *)zzaArg(zztasp1,0 ).left)->p1;
+ if (numericActionLabel) { /* MR10 */
+ list_add(&NumericPredLabels,act); /* MR10 */
+ numericActionLabel=0; /* MR10 */
+ }; /* MR10 */
+ {
+ zzBLOCK(zztasp2);
+ zzMake0;
+ {
+ char *a;
+ if ( (LA(1)==PassAction) ) {
+ zzmatch(PassAction);
+
+ a = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char));
+ require(a!=NULL, "rule element: cannot allocate predicate fail action");
+ strcpy(a, LATEXT(1));
+ act->pred_fail = a;
+ zzCONSUME;
+
+ }
+ else {
+ if ( (setwd8[LA(1)]&0x1) ) {
+ }
+ else {zzFAIL(1,zzerr43,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}
+ }
+ zzEXIT(zztasp2);
+ }
+ }
+ if ( first_on_line ) { /* MR7 */
+ CurAltStart = (Junction *)zzaArg(zztasp1,0 ).left; /* MR7 */
+ altAdd(CurAltStart); /* MR7 */
+ };
+ _retv = (Node *)act;
+ }
+ else {
+ if ( (setwd8[LA(1)]&0x2) ) {
+ if ( old_not ) warn("~ BLOCK is an undefined operation");
+ BlkLevel++;
+ if (BlkLevel >= MAX_BLK_LEVEL) fatal("Blocks nested too deeply");
+ /* MR23 */ CurBlockID_array[BlkLevel] = CurBlockID;
+ /* MR23 */ CurAltNum_array[BlkLevel] = CurAltNum;
+ {
+ zzBLOCK(zztasp2);
+ zzMake0;
+ {
+ if ( (LA(1)==Pragma) ) {
+ zzmatch(Pragma); zzCONSUME;
+ {
+ zzBLOCK(zztasp3);
+ zzMake0;
+ {
+ if ( (LA(1)==126) ) {
+ zzmatch(126);
+ approx=LL_k;
+ zzCONSUME;
+
+ }
+ else {
+ if ( (LA(1)==127) ) {
+ zzmatch(127);
+ approx = 1;
+ zzCONSUME;
+
+ }
+ else {
+ if ( (LA(1)==128) ) {
+ zzmatch(128);
+ approx = 2;
+ zzCONSUME;
+
+ }
+ else {zzFAIL(1,zzerr44,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}
+ }
+ }
+ zzEXIT(zztasp3);
+ }
+ }
+ }
+ else {
+ if ( (setwd8[LA(1)]&0x4) ) {
+ }
+ else {zzFAIL(1,zzerr45,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}
+ }
+ zzEXIT(zztasp2);
+ }
+ }
+ {
+ zzBLOCK(zztasp2);
+ zzMake0;
+ {
+ if ( (LA(1)==FirstSetSymbol) ) {
+ zzmatch(FirstSetSymbol); zzCONSUME;
+ zzmatch(114); zzCONSUME;
+ {
+ zzBLOCK(zztasp3);
+ zzMake0;
+ {
+ if ( (LA(1)==NonTerminal) ) {
+ zzmatch(NonTerminal);
+
+ /* MR21 */ pFirstSetSymbol = (char *) calloc(strlen(LATEXT(1))+1,
+ /* MR21 */ sizeof(char));
+ /* MR21 */ require(pFirstSetSymbol!=NULL,
+ /* MR21 */ "cannot allocate first set name");
+ /* MR21 */ strcpy(pFirstSetSymbol, LATEXT(1));
+ /* MR21 */
+ zzCONSUME;
+
+ }
+ else {
+ if ( (LA(1)==TokenTerm) ) {
+ zzmatch(TokenTerm);
+
+ /* MR21 */ pFirstSetSymbol = (char *) calloc(strlen(LATEXT(1))+1,
+ /* MR21 */ sizeof(char));
+ /* MR21 */ require(pFirstSetSymbol!=NULL,
+ /* MR21 */ "cannot allocate first set name");
+ /* MR21 */ strcpy(pFirstSetSymbol, LATEXT(1));
+ /* MR21 */
+ zzCONSUME;
+
+ }
+ else {zzFAIL(1,zzerr46,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}
+ }
+ zzEXIT(zztasp3);
+ }
+ }
+ zzmatch(115); zzCONSUME;
+ }
+ else {
+ if ( (setwd8[LA(1)]&0x8) ) {
+ }
+ else {zzFAIL(1,zzerr47,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}
+ }
+ zzEXIT(zztasp2);
+ }
+ }
+ {
+ zzBLOCK(zztasp2);
+ zzMake0;
+ {
+ if ( (LA(1)==114) ) {
+ zzmatch(114); zzCONSUME;
+ block( &toksrefd,&rulesrefd );
+ zzmatch(115);
+ blk = zzaRet = zzaArg(zztasp2,2);
+ /* MR23 */ CurBlockID_array[BlkLevel] = (-1);
+ /* MR23 */ CurAltNum_array[BlkLevel] = (-1);
+ --BlkLevel;
+ zzCONSUME;
+
+ {
+ zzBLOCK(zztasp3);
+ zzMake0;
+ {
+ if ( (LA(1)==129) ) {
+ zzmatch(129);
+ zzaRet = makeLoop(zzaRet,approx,pFirstSetSymbol);
+ zzCONSUME;
+
+ }
+ else {
+ if ( (LA(1)==130) ) {
+ zzmatch(130);
+ zzaRet = makePlus(zzaRet,approx,pFirstSetSymbol);
+ zzCONSUME;
+
+ }
+ else {
+ if ( (LA(1)==131) ) {
+ zzmatch(131); zzCONSUME;
+ {
+ zzBLOCK(zztasp4);
+ zzMake0;
+ {
+ if ( (setwd8[LA(1)]&0x10) ) {
+ {
+ zzBLOCK(zztasp5);
+ zzMake0;
+ {
+ if ( (LA(1)==132) ) {
+ zzmatch(132);
+ ampersandStyle=0;
+ zzCONSUME;
+
+ }
+ else {
+ if ( (LA(1)==113) ) {
+ zzmatch(113);
+ ampersandStyle=1;
+ zzCONSUME;
+
+ }
+ else {zzFAIL(1,zzerr48,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}
+ }
+ zzEXIT(zztasp5);
+ }
+ }
+ zzmatch(Pred);
+ zzaRet = buildAction(LATEXT(1),action_file,action_line,1);
+ zzCONSUME;
+
+ act = (ActionNode *) ((Junction *)zzaRet.left)->p1;
+ semDepth=predicateLookaheadDepth(act);
+ if (numericActionLabel) { /* MR10 */
+ list_add(&NumericPredLabels,act); /* MR10 */
+ numericActionLabel=0; /* MR10 */
+ }; /* MR10 */
+ {
+ zzBLOCK(zztasp5);
+ zzMake0;
+ {
+ char *a;
+ if ( (LA(1)==PassAction) ) {
+ zzmatch(PassAction);
+
+ a = (char *)calloc(strlen(LATEXT(1))+1, sizeof(char));
+ require(a!=NULL, "rule element: cannot allocate predicate fail action");
+ strcpy(a, LATEXT(1));
+ act->pred_fail = a;
+ zzCONSUME;
+
+ }
+ else {
+ if ( (setwd8[LA(1)]&0x20) ) {
+ }
+ else {zzFAIL(1,zzerr49,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}
+ }
+ zzEXIT(zztasp5);
+ }
+ }
+ if ( first_on_line) { /* MR7 */
+ CurAltStart=(Junction *)zzaRet.left; /* MR7 */
+ altAdd(CurAltStart); /* MR7 */
+ };
+ _retv = (Node *)act;
+
+ pred = computePredFromContextGuard(blk,&predMsgDone); /* MR10 */
+ if ( pred==NULL) { /* MR10 */
+ if ( !predMsgDone) err("invalid or missing context guard"); /* MR10 */
+ predMsgDone=1; /* MR10 */
+ } else { /* MR10 */
+ act->guardNodes=(Junction *)blk.left; /* MR11 */
+ pred->expr = act->action;
+ pred->source = act;
+ /* MR10 */ pred->ampersandStyle = ampersandStyle; /* 0 means (g)? => ... 1 means (g)? && ... */
+ /* MR13 */ if (pred->tcontext != NULL) {
+ /* MR13 */ height=MR_max_height_of_tree(pred->tcontext);
+ /* MR13 */ equal_height=MR_all_leaves_same_height(pred->tcontext,height);
+ /* MR13 */ if (! equal_height) {
+ /* MR13 */ errFL("in guarded predicates all tokens in the guard must be at the same height",
+ /* MR13 */ FileStr[act->file],act->line);
+ /* MR13 */ };
+ /* MR13 */ }
+ /* MR10 */ if (ampersandStyle) {
+ /* MR10 */ act->ampersandPred = pred;
+ /* MR11 */ if (! HoistPredicateContext) {
+ /* MR11 */ errFL("without \"-prc on\" (guard)? && <<pred>>? ... doesn't make sense",
+ /* MR11 */ FileStr[act->file],act->line);
+ /* MR11 */ };
+ /* MR10 */ } else {
+ /* MR10 */ act->guardpred = pred;
+ /* MR10 */ };
+ /* MR10 */ if (pred->k != semDepth) {
+ /* MR10 */ warn(eMsgd2("length of guard (%d) does not match the length of semantic predicate (%d)",
+ /* MR10 */ pred->k,semDepth));
+ /* MR10 */ };
+ }
+ }
+ else {
+ if ( (setwd8[LA(1)]&0x40) ) {
+ zzaRet = makeBlk(zzaRet,approx,pFirstSetSymbol);
+ FoundGuessBlk = 1;
+ ((Junction *) ((Junction *)zzaRet.left)->p1)->guess=1;
+ if ( ! first_on_line ) {
+ err("(...)? predicate must be first element of production");
+ }
+ }
+ else {zzFAIL(1,zzerr50,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}
+ }
+ zzEXIT(zztasp4);
+ }
+ }
+ }
+ else {
+ if ( (setwd8[LA(1)]&0x80) ) {
+ zzaRet = makeBlk(zzaRet,approx,pFirstSetSymbol);
+ }
+ else {zzFAIL(1,zzerr51,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}
+ }
+ }
+ }
+ zzEXIT(zztasp3);
+ }
+ }
+
+ if ( pred==NULL && !predMsgDone) { /* MR10 */
+ ((Junction *)((Junction *)zzaRet.left)->p1)->blockid = CurBlockID;
+ ((Junction *)((Junction *)zzaRet.left)->p1)->tokrefs = toksrefd;
+ ((Junction *)((Junction *)zzaRet.left)->p1)->rulerefs = rulesrefd;
+ if ( first_on_line ) { /* MR7 */
+ CurAltStart = (Junction *)((Junction *)((Junction *)zzaRet.left)->p1); /* MR7 */
+ altAdd(CurAltStart); /* MR7 */
+ }; /* MR7 */
+ _retv = (Node *) ((Junction *)zzaRet.left)->p1;
+ }
+ }
+ else {
+ if ( (LA(1)==102) ) {
+ zzmatch(102); zzCONSUME;
+ block( &toksrefd,&rulesrefd );
+ zzaRet = makeOpt(zzaArg(zztasp2,2),approx,pFirstSetSymbol);
+ /* MR23 */ CurBlockID_array[BlkLevel] = (-1);
+ /* MR23 */ CurAltNum_array[BlkLevel] = (-1);
+ --BlkLevel;
+ zzmatch(98);
+
+ ((Junction *)((Junction *)zzaRet.left)->p1)->blockid = CurBlockID;
+ ((Junction *)((Junction *)zzaRet.left)->p1)->tokrefs = toksrefd;
+ ((Junction *)((Junction *)zzaRet.left)->p1)->rulerefs = rulesrefd;
+ zzCONSUME;
+
+ if ( first_on_line ) { /* MR7 */
+ CurAltStart = (Junction *) ((Junction *)((Junction *)zzaRet.left)->p1); /* MR7 */
+ altAdd(CurAltStart); /* MR7 */
+ };
+ _retv = (Node *) ((Junction *)zzaRet.left)->p1;
+ }
+ else {zzFAIL(1,zzerr52,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}
+ }
+ zzEXIT(zztasp2);
+ }
+ }
+ }
+ else {
+ if ( (LA(1)==129) ) {
+ zzmatch(129);
+ warn("don't you want a ')' with that '*'?"); CannotContinue=TRUE;
+ zzCONSUME;
+
+ }
+ else {
+ if ( (LA(1)==130) ) {
+ zzmatch(130);
+ warn("don't you want a ')' with that '+'?"); CannotContinue=TRUE;
+ zzCONSUME;
+
+ }
+ else {
+ if ( (LA(1)==105) ) {
+ zzmatch(105);
+ warn("'>' can only appear after a nonterminal"); CannotContinue=TRUE;
+ zzCONSUME;
+
+ }
+ else {
+ if ( (LA(1)==PassAction) ) {
+ zzmatch(PassAction);
+ warn("[...] out of context 'rule > [...]'");
+ CannotContinue=TRUE;
+ zzCONSUME;
+
+ }
+ else {zzFAIL(1,zzerr53,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ zzEXIT(zztasp1);
+ return _retv;
+fail:
+ zzEXIT(zztasp1);
+ CannotContinue=TRUE;
+ zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText);
+ zzresynch(setwd9, 0x1);
+ return _retv;
+ }
+}
+
+void
+#ifdef __USE_PROTOS
+default_exception_handler(void)
+#else
+default_exception_handler()
+#endif
+{
+ zzRULE;
+ zzBLOCK(zztasp1);
+ zzMake0;
+ {
+ DefaultExGroup = exception_group();
+
+ zzEXIT(zztasp1);
+ return;
+fail:
+ zzEXIT(zztasp1);
+ zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText);
+ zzresynch(setwd9, 0x2);
+ }
+}
+
+ExceptionGroup *
+#ifdef __USE_PROTOS
+exception_group(void)
+#else
+exception_group()
+#endif
+{
+ ExceptionGroup * _retv;
+ zzRULE;
+ zzBLOCK(zztasp1);
+ PCCTS_PURIFY(_retv,sizeof(ExceptionGroup * ))
+ zzMake0;
+ {
+ ExceptionHandler *h; LabelEntry *label=NULL; /* MR6 */
+ FoundException = 1; FoundExceptionGroup = 1;
+ zzmatch(133);
+ _retv = (ExceptionGroup *)calloc(1, sizeof(ExceptionGroup));
+ zzCONSUME;
+
+ {
+ zzBLOCK(zztasp2);
+ zzMake0;
+ {
+ char *p;
+ if ( (LA(1)==PassAction) ) {
+ zzmatch(PassAction);
+
+ p = LATEXT(1)+1;
+ p[strlen(p)-1] = '\0'; /* kill trailing space */
+ label = (LabelEntry *) hash_get(Elabel, LATEXT(1)+1);
+ if ( label==NULL )
+ {
+ err(eMsg1("unknown label in exception handler: '%s'", LATEXT(1)+1));
+ }
+ zzCONSUME;
+
+ }
+ else {
+ if ( (setwd9[LA(1)]&0x4) ) {
+ }
+ else {zzFAIL(1,zzerr54,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}
+ }
+ zzEXIT(zztasp2);
+ }
+ }
+ {
+ zzBLOCK(zztasp2);
+ zzMake0;
+ {
+ while ( (LA(1)==135) ) {
+ h = exception_handler();
+
+ list_add(&(_retv->handlers), (void *)h);
+ zzLOOP(zztasp2);
+ }
+ zzEXIT(zztasp2);
+ }
+ }
+ {
+ zzBLOCK(zztasp2);
+ zzMake0;
+ {
+ if ( (LA(1)==134) ) {
+ zzmatch(134); zzCONSUME;
+ zzmatch(106); zzCONSUME;
+ zzmatch(Action);
+ {
+ ExceptionHandler *eh = (ExceptionHandler *)
+ calloc(1, sizeof(ExceptionHandler));
+ char *a = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char));
+ require(eh!=NULL, "exception: cannot allocate handler");
+ require(a!=NULL, "exception: cannot allocate action");
+ strcpy(a, LATEXT(1));
+ eh->action = a;
+ eh->signalname = (char *) calloc(strlen("default")+1, sizeof(char));
+ require(eh->signalname!=NULL, "exception: cannot allocate sig name");
+ strcpy(eh->signalname, "default");
+ list_add(&(_retv->handlers), (void *)eh);
+ }
+ zzCONSUME;
+
+ }
+ else {
+ if ( (setwd9[LA(1)]&0x8) ) {
+ }
+ else {zzFAIL(1,zzerr55,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}
+ }
+ zzEXIT(zztasp2);
+ }
+ }
+
+ if ( label!=NULL ) {
+ /* Record ex group in sym tab for this label */
+ if ( label->ex_group!=NULL ) {
+ err(eMsg1("duplicate exception handler for label '%s'",label->str));
+ } else {
+ label->ex_group = _retv;
+ /* Label the exception group itself */
+ _retv->label = label->str;
+ /* Make the labelled element pt to the exception also */
+ /* MR6 */ if (label->elem == NULL) {
+ /* MR6 */ err(eMsg1("reference in exception handler to undefined label '%s'",label->str));
+ /* MR6 */ } else {
+ switch ( label->elem->ntype ) {
+ case nRuleRef :
+ {
+ RuleRefNode *r = (RuleRefNode *)label->elem;
+ r->ex_group = _retv;
+ break;
+ }
+ case nToken :
+ {
+ TokNode *t = (TokNode *)label->elem;
+ t->ex_group = _retv;
+ break;
+ }
+ } /* end switch */
+ /* MR6 */ }; /* end test on label->elem */
+ } /* end test on label->ex_group */
+
+ } /* end test on exception label */
+
+/* MR7 */
+ /* MR7 */ if (BlkLevel == 1 && label == NULL) {
+ /* MR7 */ _retv->forRule=1;
+ /* MR7 */ } else if (label == NULL) {
+ /* MR7 */ _retv->altID = makeAltID(CurBlockID_array[BlkLevel], CurAltNum_array[BlkLevel]);
+ /* MR7 */ egAdd(_retv);
+ /* MR7 */ } else {
+ /* MR7 */ _retv->labelEntry=label;
+ /* MR7 */ };
+ /* MR7 */
+ /* MR7 */ /* You may want to remove this exc from the rule list */
+ /* MR7 */ /* and handle at the labeled element site. */
+ /* MR7 */
+ /* MR7 */ if (label != NULL) {
+ /* MR7 */ _retv = NULL;
+ /* MR7 */ };
+ zzEXIT(zztasp1);
+ return _retv;
+fail:
+ zzEXIT(zztasp1);
+ CannotContinue=TRUE;
+ zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText);
+ zzresynch(setwd9, 0x10);
+ return _retv;
+ }
+}
+
+ExceptionHandler *
+#ifdef __USE_PROTOS
+exception_handler(void)
+#else
+exception_handler()
+#endif
+{
+ ExceptionHandler * _retv;
+ zzRULE;
+ zzBLOCK(zztasp1);
+ PCCTS_PURIFY(_retv,sizeof(ExceptionHandler * ))
+ zzMake0;
+ {
+ ;
+ zzmatch(135);
+
+ _retv = (ExceptionHandler *)calloc(1, sizeof(ExceptionHandler));
+ require(_retv!=NULL, "exception: cannot allocate handler");
+ zzCONSUME;
+
+ {
+ zzBLOCK(zztasp2);
+ zzMake0;
+ {
+ if ( (LA(1)==NonTerminal) ) {
+ zzmatch(NonTerminal);
+
+ _retv->signalname = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char));
+ require(_retv->signalname!=NULL, "exception: cannot allocate sig name");
+ strcpy(_retv->signalname, LATEXT(1));
+ zzCONSUME;
+
+ }
+ else {
+ if ( (LA(1)==TokenTerm) ) {
+ zzmatch(TokenTerm);
+
+ _retv->signalname = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char));
+ require(_retv->signalname!=NULL, "exception: cannot allocate sig name");
+ strcpy(_retv->signalname, LATEXT(1));
+ zzCONSUME;
+
+ }
+ else {zzFAIL(1,zzerr56,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}
+ }
+ zzEXIT(zztasp2);
+ }
+ }
+ zzmatch(106); zzCONSUME;
+ {
+ zzBLOCK(zztasp2);
+ zzMake0;
+ {
+ _retv->action = NULL;
+ if ( (LA(1)==Action) ) {
+ zzmatch(Action);
+
+ _retv->action = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char));
+ require(_retv->action!=NULL, "exception: cannot allocate action");
+ strcpy(_retv->action, LATEXT(1));
+ zzCONSUME;
+
+ }
+ else {
+ if ( (setwd9[LA(1)]&0x20) ) {
+ }
+ else {zzFAIL(1,zzerr57,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}
+ }
+ zzEXIT(zztasp2);
+ }
+ }
+ zzEXIT(zztasp1);
+ return _retv;
+fail:
+ zzEXIT(zztasp1);
+ CannotContinue=TRUE;
+ zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText);
+ zzresynch(setwd9, 0x40);
+ return _retv;
+ }
+}
+
+void
+#ifdef __USE_PROTOS
+enum_file(char * fname)
+#else
+enum_file(fname)
+ char *fname ;
+#endif
+{
+ zzRULE;
+ zzBLOCK(zztasp1);
+ zzMake0;
+ {
+ if ( (setwd9[LA(1)]&0x80) ) {
+ {
+ zzBLOCK(zztasp2);
+ zzMake0;
+ {
+ if ( (LA(1)==143) ) {
+ zzmatch(143); zzCONSUME;
+ zzmatch(ID); zzCONSUME;
+ {
+ zzBLOCK(zztasp3);
+ zzMake0;
+ {
+ if ( (LA(1)==149) ) {
+ zzmatch(149); zzCONSUME;
+ zzmatch(ID); zzCONSUME;
+ }
+ else {
+ if ( (setwd10[LA(1)]&0x1) ) {
+ }
+ else {zzFAIL(1,zzerr58,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}
+ }
+ zzEXIT(zztasp3);
+ }
+ }
+ }
+ else {
+ if ( (setwd10[LA(1)]&0x2) ) {
+ }
+ else {zzFAIL(1,zzerr59,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}
+ }
+ zzEXIT(zztasp2);
+ }
+ }
+ {
+ zzBLOCK(zztasp2);
+ zzMake0;
+ {
+ if ( (LA(1)==151) ) {
+ {
+ zzBLOCK(zztasp3);
+ int zzcnt=1;
+ zzMake0;
+ {
+ do {
+ enum_def( fname );
+ zzLOOP(zztasp3);
+ } while ( (LA(1)==151) );
+ zzEXIT(zztasp3);
+ }
+ }
+ }
+ else {
+ if ( (LA(1)==149) ) {
+ defines( fname );
+ }
+ else {zzFAIL(1,zzerr60,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}
+ }
+ zzEXIT(zztasp2);
+ }
+ }
+ }
+ else {
+ if ( (LA(1)==Eof) ) {
+ }
+ else {zzFAIL(1,zzerr61,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}
+ }
+ zzEXIT(zztasp1);
+ return;
+fail:
+ zzEXIT(zztasp1);
+ zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText);
+ zzresynch(setwd10, 0x4);
+ }
+}
+
+void
+#ifdef __USE_PROTOS
+defines(char * fname)
+#else
+defines(fname)
+ char *fname ;
+#endif
+{
+ zzRULE;
+ zzBLOCK(zztasp1);
+ zzMake0;
+ {
+ int v; int maxt=(-1); char *t;
+ {
+ zzBLOCK(zztasp2);
+ int zzcnt=1;
+ zzMake0;
+ {
+ do {
+ zzmatch(149); zzCONSUME;
+ zzmatch(ID);
+ t = mystrdup(LATEXT(1));
+ zzCONSUME;
+
+ zzmatch(INT);
+
+ v = atoi(LATEXT(1));
+ /* fprintf(stderr, "#token %s=%d\n", t, v);*/
+
+ /* MR2 Andreas Magnusson (Andreas.Magnusson@mailbox.swipnet.se) */
+ /* MR2 Fix to bug introduced by 1.33MR1 for #tokdefs */
+ /* MR2 Don't let #tokdefs be confused by */
+ /* MR2 DLGminToken and DLGmaxToken */
+
+ if ( ! isDLGmaxToken(t)) { /* MR2 */
+ TokenNum = v;
+ if ( v>maxt ) maxt=v;
+ if ( Tnum( t ) == 0 ) {
+ addForcedTname( t, v );
+ } else {
+ warnFL(eMsg1("redefinition of token %s; ignored",t), fname,zzline);
+ };
+};
+ zzCONSUME;
+
+ zzLOOP(zztasp2);
+ } while ( (LA(1)==149) );
+ zzEXIT(zztasp2);
+ }
+ }
+ TokenNum = maxt + 1;
+ zzEXIT(zztasp1);
+ return;
+fail:
+ zzEXIT(zztasp1);
+ zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText);
+ zzresynch(setwd10, 0x8);
+ }
+}
+
+void
+#ifdef __USE_PROTOS
+enum_def(char * fname)
+#else
+enum_def(fname)
+ char *fname ;
+#endif
+{
+ zzRULE;
+ zzBLOCK(zztasp1);
+ zzMake0;
+ {
+ int v= 0; int maxt=(-1); char *t;
+ zzmatch(151); zzCONSUME;
+ zzmatch(ID); zzCONSUME;
+ zzmatch(152); zzCONSUME;
+ zzmatch(ID);
+ t = mystrdup(LATEXT(1));
+ zzCONSUME;
+
+ {
+ zzBLOCK(zztasp2);
+ zzMake0;
+ {
+ if ( (LA(1)==153) ) {
+ zzmatch(153); zzCONSUME;
+ zzmatch(INT);
+ v=atoi(LATEXT(1));
+ zzCONSUME;
+
+ }
+ else {
+ if ( (setwd10[LA(1)]&0x10) ) {
+ v++;
+ }
+ else {zzFAIL(1,zzerr62,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}
+ }
+ zzEXIT(zztasp2);
+ }
+ }
+
+ /* fprintf(stderr, "#token %s=%d\n", t, v);*/
+ TokenNum = v;
+ if ( v>maxt ) maxt=v; /* MR3 */
+ if ( Tnum( t ) == 0 ) addForcedTname( t, v );
+ else {
+ warnFL(eMsg1("redefinition of token %s; ignored",t), fname,zzline);
+ }
+ {
+ zzBLOCK(zztasp2);
+ zzMake0;
+ {
+ while ( (LA(1)==154) ) {
+ zzmatch(154); zzCONSUME;
+ {
+ zzBLOCK(zztasp3);
+ zzMake0;
+ {
+ if ( (LA(1)==ID)&&(isDLGmaxToken(LATEXT(1))) ) {
+ if (!(isDLGmaxToken(LATEXT(1))) ) {zzfailed_pred(" isDLGmaxToken(LATEXT(1))",0 /* report */, { 0; /* no user action */ } );}
+ zzmatch(ID); zzCONSUME;
+ {
+ zzBLOCK(zztasp4);
+ zzMake0;
+ {
+ if ( (LA(1)==153) ) {
+ zzmatch(153); zzCONSUME;
+ zzmatch(INT); zzCONSUME;
+ }
+ else {
+ if ( (setwd10[LA(1)]&0x20) ) {
+ }
+ else {zzFAIL(1,zzerr63,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}
+ }
+ zzEXIT(zztasp4);
+ }
+ }
+ }
+ else {
+ if ( (LA(1)==ID) ) {
+ zzmatch(ID);
+ t = mystrdup(LATEXT(1));
+ zzCONSUME;
+
+ {
+ zzBLOCK(zztasp4);
+ zzMake0;
+ {
+ if ( (LA(1)==153) ) {
+ zzmatch(153); zzCONSUME;
+ zzmatch(INT);
+ v=atoi(LATEXT(1));
+ zzCONSUME;
+
+ }
+ else {
+ if ( (setwd10[LA(1)]&0x40) ) {
+ v++;
+ }
+ else {zzFAIL(1,zzerr64,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}
+ }
+ zzEXIT(zztasp4);
+ }
+ }
+
+ /* fprintf(stderr, "#token %s=%d\n", t, v);*/
+ TokenNum = v;
+ if ( v>maxt ) maxt=v; /* MR3 */
+ if ( Tnum( t ) == 0 ) addForcedTname( t, v );
+ else {
+ warnFL(eMsg1("redefinition of token %s; ignored",t), fname,zzline);
+ }
+ }
+ else {
+ if ( (setwd10[LA(1)]&0x80) ) {
+ }
+ else {zzFAIL(1,zzerr65,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}
+ }
+ }
+ zzEXIT(zztasp3);
+ }
+ }
+ zzLOOP(zztasp2);
+ }
+ zzEXIT(zztasp2);
+ }
+ }
+ zzmatch(155); zzCONSUME;
+ zzmatch(156);
+ TokenNum = maxt + 1;
+ zzCONSUME;
+
+ zzEXIT(zztasp1);
+ return;
+fail:
+ zzEXIT(zztasp1);
+ zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText);
+ zzresynch(setwd11, 0x1);
+ }
+}
+
+
+/* MR2 Andreas Magnusson (Andreas.Magnusson@mailbox.swipnet.se) */
+/* MR2 Fix to bug introduced by 1.33MR1 for #tokdefs */
+/* MR2 Don't let #tokdefs be confused by */
+/* MR2 DLGminToken and DLGmaxToken */
+
+/* semantic check on DLGminToken and DLGmaxmaxToken in #tokdefs */
+
+#ifdef __USE_PROTOS
+static int isDLGmaxToken(char *Token)
+#else
+static int isDLGmaxToken(Token)
+char * Token;
+#endif
+{
+static char checkStr1[] = "DLGmaxToken";
+static char checkStr2[] = "DLGminToken";
+
+ if (strcmp(Token, checkStr1) == 0)
+return 1;
+else if (strcmp(Token, checkStr2) == 0)
+return 1;
+else
+return 0;
+}
+
+/* semantics of #token */
+static void
+#ifdef __USE_PROTOS
+chkToken(char *t, char *e, char *a, int tnum)
+#else
+chkToken(t,e,a,tnum)
+char *t, *e, *a;
+int tnum;
+#endif
+{
+TermEntry *p;
+
+ /* check to see that they don't try to redefine a token as a token class */
+if ( t!=NULL ) {
+p = (TermEntry *) hash_get(Tname, t);
+if ( p!=NULL && p->classname ) {
+ err(eMsg1("redefinition of #tokclass '%s' to #token not allowed; ignored",t));
+ if ( a!=NULL ) free((char *)a);
+ return;
+}
+}
+
+ if ( t==NULL && e==NULL ) { /* none found */
+err("#token requires at least token name or rexpr");
+}
+else if ( t!=NULL && e!=NULL ) { /* both found */
+if ( UserDefdTokens ) { /* if #tokdefs, must not define new */
+ p = (TermEntry *) hash_get(Tname, t);
+ if ( p == NULL) {
+ err(eMsg1("new token definition '%s' not allowed - only #token with name already defined by #tokdefs file allowed",t));
+ return;
+ };
+}
+Tklink(t, e);
+if ( a!=NULL ) {
+ if ( hasAction(e) ) {
+ err(eMsg1("redefinition of action for %s; ignored",e));
+ }
+ else setHasAction(e, a);
+}
+}
+else if ( t!=NULL ) { /* only one found */
+if ( UserDefdTokens ) {
+ p = (TermEntry *) hash_get(Tname, t);
+ if (p == NULL) {
+ err(eMsg1("new token definition '%s' not allowed - only #token with name already defined by #tokdefs file allowed",t));
+ };
+ return;
+}
+if ( Tnum( t ) == 0 ) addTname( t );
+else {
+ err(eMsg1("redefinition of token %s; ignored",t));
+}
+if ( a!=NULL ) {
+ err(eMsg1("action cannot be attached to a token name (%s); ignored",t));
+ free((char *)a);
+}
+}
+else if ( e!=NULL ) {
+if ( Tnum( e ) == 0 ) addTexpr( e );
+else {
+ if ( hasAction(e) ) {
+ err(eMsg1("redefinition of action for expr %s; ignored",e));
+ }
+ else if ( a==NULL ) {
+ err(eMsg1("redefinition of expr %s; ignored",e));
+ }
+}
+if ( a!=NULL ) setHasAction(e, a);
+}
+
+ /* if a token type number was specified, then add the token ID and 'tnum'
+* pair to the ForcedTokens list. (only applies if an id was given)
+*/
+if ( t!=NULL && tnum>0 )
+{
+if ( set_el(tnum, reserved_positions) )
+{
+ err(eMsgd("a token has already been forced to token number %d; ignored", tnum));
+}
+else
+{
+ list_add(&ForcedTokens, newForcedToken(t,tnum));
+ set_orel(tnum, &reserved_positions);
+}
+}
+}
+
+static int
+#ifdef __USE_PROTOS
+match_token(char *s, char **nxt)
+#else
+match_token(s,nxt)
+char *s;
+char **nxt;
+#endif
+{
+ if ( !(*s>='A' && *s<='Z') ) return 0;
+ s++;
+ while ( (*s>='a' && *s<='z') ||
+ (*s>='A' && *s<='Z') ||
+ (*s>='0' && *s<='9') ||
+ *s=='_' )
+ {
+ s++;
+ }
+ if ( *s!=' ' && *s!='}' ) return 0;
+ *nxt = s;
+ return 1;
+}
+
+static int
+#ifdef __USE_PROTOS
+match_rexpr(char *s, char **nxt)
+#else
+match_rexpr(s,nxt)
+char *s;
+char **nxt;
+#endif
+{
+ if ( *s!='"' ) return 0;
+ s++;
+ while ( *s!='"' )
+ {
+ if ( *s=='\n' || *s=='\r' ) /* MR13 */
+ warn("eoln found in regular expression");
+ if ( *s=='\\' ) s++;
+ s++;
+ }
+ *nxt = s+1;
+ return 1;
+}
+
+/*
+* Walk a string "{ A .. Z }" where A..Z is a space separated list
+* of token references (either labels or reg exprs). Return a
+* string "inlineX_set" for some unique integer X. Basically,
+* we pretend as if we had seen "#tokclass inlineX { A .. Z }"
+* on the input stream outside of an action.
+*/
+char *
+#ifdef __USE_PROTOS
+inline_set(char *s)
+#else
+inline_set(s)
+char *s;
+#endif
+{
+ char *nxt;
+ fprintf(stderr, "found consumeUntil( {...} )\n");
+ while ( *s==' ' || *s=='\t' || *s=='\n' || *s=='\r' ) {s++;}
+ if ( *s!='{' )
+ {
+ err("malformed consumeUntil( {...} ); missing '{'");
+ return "bad_set";
+ }
+ s++;
+ while ( *s==' ' || *s=='\t' || *s=='\n' || *s=='\r' ) {s++;}
+ while ( *s!='}' )
+ {
+ if ( match_token(s,&nxt) ) fprintf(stderr, "found token %s\n", s);
+ else if ( match_rexpr(s,&nxt) ) fprintf(stderr, "found rexpr %s\n", s);
+ else {
+ err("invalid element in consumeUntil( {...} )");
+ return "bad_set";
+ }
+ s = nxt;
+ while ( *s==' ' || *s=='\t' || *s=='\n' || *s=='\r' ) {s++;}
+ }
+ return "inlineX_set";
+}
+
+/* ANTLR-specific syntax error message generator
+* (define USER_ZZSYN when compiling so don't get 2 definitions)
+*/
+void
+#ifdef __USE_PROTOS
+zzsyn(char *text, int tok, char *egroup, SetWordType *eset, int etok,
+int k, char *bad_text)
+#else
+zzsyn(text, tok, egroup, eset, etok, k, bad_text)
+char *text, *egroup, *bad_text;
+int tok;
+int etok;
+int k;
+SetWordType *eset;
+#endif
+{
+fprintf(stderr, ErrHdr, FileStr[CurFile]!=NULL?FileStr[CurFile]:"stdin", zzline);
+fprintf(stderr, " syntax error at \"%s\"", (tok==zzEOF_TOKEN)?"EOF":text);
+if ( !etok && !eset ) {fprintf(stderr, "\n"); return;}
+if ( k==1 ) fprintf(stderr, " missing");
+else
+{
+fprintf(stderr, "; \"%s\" not", bad_text);
+if ( zzset_deg(eset)>1 ) fprintf(stderr, " in");
+}
+if ( zzset_deg(eset)>0 ) zzedecode(eset);
+else fprintf(stderr, " %s", zztokens[etok]);
+if ( strlen(egroup) > (size_t)0 ) fprintf(stderr, " in %s", egroup);
+fprintf(stderr, "\n");
+}
diff --git a/Source/Pccts/antlr/antlr.g b/Source/Pccts/antlr/antlr.g
new file mode 100644
index 0000000..e6eda60
--- /dev/null
+++ b/Source/Pccts/antlr/antlr.g
@@ -0,0 +1,2586 @@
+/*
+ * antlr.g -- PCCTS Version 1.xx ANTLR
+ *
+ * Parse an antlr input grammar and build a syntax-diagram.
+ *
+ * Written in itself (needs at least 1.06 to work)
+ *
+ * SOFTWARE RIGHTS
+ *
+ * We reserve no LEGAL rights to the Purdue Compiler Construction Tool
+ * Set (PCCTS) -- PCCTS is in the public domain. An individual or
+ * company may do whatever they wish with source code distributed with
+ * PCCTS or the code generated by PCCTS, including the incorporation of
+ * PCCTS, or its output, into commerical software.
+ *
+ * We encourage users to develop software with PCCTS. However, we do ask
+ * that credit is given to us for developing PCCTS. By "credit",
+ * we mean that if you incorporate our source code into one of your
+ * programs (commercial product, research project, or otherwise) that you
+ * acknowledge this fact somewhere in the documentation, research report,
+ * etc... If you like PCCTS and have developed a nice tool with the
+ * output, please mention that you developed it using PCCTS. In
+ * addition, we ask that this header remain intact in our source code.
+ * As long as these guidelines are kept, we expect to continue enhancing
+ * this system and expect to make other tools available as they are
+ * completed.
+ *
+ * ANTLR 1.33
+ * Terence Parr
+ * Parr Research Corporation
+ * with Purdue University and AHPCRC, University of Minnesota
+ * 1989-1995
+ */
+
+/* MR1 */
+/* MR1 10-Apr-97 MR1 Replace #if logic with #include "pcctscfg.h" */
+/* MR1 */
+
+#header <<
+ #include "pcctscfg.h"
+ #include "set.h"
+ #include <ctype.h>
+ #include "syn.h"
+ #include "hash.h"
+ #include "generic.h"
+ #define zzcr_attr(attr,tok,t)
+ >>
+
+<<
+
+/* MR20 G. Hobbelt For Borland C++ 4.x & 5.x compiling with ALL warnings enabled */
+#if defined(__TURBOC__)
+#pragma warn -aus /* unused assignment of 'xxx' */
+#endif
+
+
+#ifdef __USE_PROTOS
+static void chkToken(char *, char *, char *, int);
+#else
+static void chkToken();
+#endif
+
+#ifdef __USE_PROTOS
+static int isDLGmaxToken(char *Token); /* MR3 */
+#else
+static int isDLGmaxToken(); /* MR3 */
+#endif
+
+static int class_nest_level = 0;
+
+/* MR20 G. Hobbelt extern definitions moved to antlr.h */
+
+>>
+
+#lexaction <<
+/* maintained, but not used for now */
+set AST_nodes_refd_in_actions = set_init;
+int inAlt = 0;
+set attribsRefdFromAction = set_init; /* MR20 */
+int UsedOldStyleAttrib = 0;
+int UsedNewStyleLabel = 0;
+#ifdef __USE_PROTOS
+char *inline_set(char *);
+#else
+char *inline_set();
+#endif
+
+/* MR1 10-Apr-97 MR1 Previously unable to put right shift operator */
+/* MR1 in DLG action */
+
+int tokenActionActive=0; /* MR1 */
+
+>>
+
+#lexclass STRINGS
+#token QuotedTerm "\"" << zzmode(START); >>
+#token "\n|\r|\r\n" <<
+ zzline++;
+ warn("eoln found in string");
+ zzskip();
+ >>
+#token "\\(\n|\r|\r\n)" << zzline++; zzmore(); >>
+#token "\\~[]" << zzmore(); >>
+#token "~[\n\r\"\\]+" << zzmore(); >>
+
+#lexclass ACTION_STRINGS
+#token "\"" << zzmode(ACTIONS); zzmore(); >>
+#token "\n|\r|\r\n" <<
+ zzline++;
+ warn("eoln found in string (in user action)");
+ zzskip();
+ >>
+#token "\\(\n|\r|\r\n)" << zzline++; zzmore(); >>
+#token "\\~[]" << zzmore(); >>
+#token "~[\n\r\"\\]+" << zzmore(); >>
+
+#lexclass ACTION_CHARS
+#token "'" << zzmode(ACTIONS); zzmore(); >>
+#token "\n|\r|\r\n" <<
+ zzline++;
+ warn("eoln found in char literal (in user action)");
+ zzskip();
+ >>
+#token "\\~[]" << zzmore(); >>
+#token "~[\n\r'\\]+" << zzmore(); >>
+
+#lexclass ACTION_COMMENTS
+#token "\*/" << zzmode(ACTIONS); zzmore(); >>
+#token "\*" << zzmore(); >>
+#token "\n|\r|\r\n" << zzline++; zzmore(); DAWDLE; >>
+#token "~[\n\r\*]+" << zzmore(); >>
+
+#lexclass TOK_DEF_COMMENTS
+#token "\*/" << zzmode(PARSE_ENUM_FILE);
+ zzmore(); >>
+#token "\*" << zzmore(); >>
+#token "\n|\r|\r\n" << zzline++; zzmore(); DAWDLE; >>
+#token "~[\n\r\*]+" << zzmore(); >>
+
+#lexclass TOK_DEF_CPP_COMMENTS
+#token "\n|\r|\r\n" << zzline++; zzmode(PARSE_ENUM_FILE); zzskip(); DAWDLE; >>
+#token "~[\n\r]+" << zzskip(); >>
+
+#lexclass ACTION_CPP_COMMENTS
+#token "\n|\r|\r\n" << zzline++; zzmode(ACTIONS); zzmore(); DAWDLE; >>
+#token "~[\n\r]+" << zzmore(); >>
+
+#lexclass CPP_COMMENTS
+#token "\n|\r|\r\n" << zzline++; zzmode(START); zzskip(); DAWDLE; >>
+#token "~[\n\r]+" << zzskip(); >>
+
+#lexclass COMMENTS
+#token "\*/" << zzmode(START); zzskip(); >>
+#token "\*" << zzskip(); >>
+#token "\n|\r|\r\n" << zzline++; zzskip(); DAWDLE; >>
+#token "~[\n\r\*]+" << zzskip(); >>
+
+/*
+ * This lexical class accepts actions of type [..] and <<..>>
+ *
+ * It translates the following special items for C:
+ *
+ * $j --> "zzaArg(current zztasp, j)"
+ * $i.j --> "zzaArg(zztaspi, j)"
+ * $i.nondigit> "zzaArg(current zztasp, i).nondigit"
+ * $$ --> "zzaRet"
+ * $alnum --> "alnum" (used to ref parameters)
+ * $rule --> "zzaRet"
+ * $retval --> "_retv.retval" if > 1 return values else "_retv"
+ * $[token, text] --> "zzconstr_attr(token, text)"
+ * $[] --> "zzempty_attr()"
+ *
+ * It translates the following special items for C++:
+ * (attributes are now stored with 'Token' and $i's are only
+ * pointers to the Tokens. Rules don't have attributes now.)
+ *
+ * $j --> "_tbj" where b is the block level
+ * $i.j --> "_tij"
+ * $j->nondigit> "_tbj->nondigit"
+ * $$ --> "$$"
+ * $alnum --> "alnum" (used to ref parameters)
+ * $rule --> "$rule"
+ * $retval --> "_retv.retval" if > 1 return values else "_retv"
+ * $[token, text] --> invalid
+ * $[] --> invalid
+ *
+ * And, for trees:
+ *
+ * #0 --> "(*_root)"
+ * #i --> "zzastArg(i)"
+ * #[args] --> "zzmk_ast(zzastnew(), args)"
+ * #[] --> "zzastnew()"
+ * #( root, child1, ..., childn )
+ * --> "zztmake(root, child1, ...., childn, NULL)"
+ * #() --> "NULL"
+ *
+ * For C++, ...
+ *
+ * #0 --> "(*_root)"
+ * #i --> "_astbi" where b is the block level
+ * #alnum --> "alnum_ast" (used to ref #label)
+ * #[args] --> "new AST(args)"
+ * #[] --> "new AST"
+ * #( root, child1, ..., childn )
+ * --> "AST::tmake(root, child1, ...., childn, NULL)"
+ * #() --> "NULL"
+ *
+ * To escape,
+ *
+ * \] --> ]
+ * \) --> )
+ * \$ --> $
+ * \# --> #
+ *
+ * A stack is used to nest action terminators because they can be nested
+ * like crazy: << #[$[..],..] >>
+ */
+#lexclass ACTIONS
+#token Action "\>\>" << /* these do not nest */
+ zzmode(START);
+ NLATEXT[0] = ' ';
+ NLATEXT[1] = ' ';
+ zzbegexpr[0] = ' ';
+ zzbegexpr[1] = ' ';
+ if ( zzbufovf ) {
+ err( eMsgd("action buffer overflow; size %d",ZZLEXBUFSIZE));
+ }
+
+/* MR1 10-Apr-97 MR1 Previously unable to put right shift operator */
+/* MR1 in DLG action */
+/* MR1 Doesn't matter what kind of action it is - reset*/
+
+ tokenActionActive=0; /* MR1 */
+ >>
+#token Pred "\>\>?" << /* these do not nest */
+ zzmode(START);
+ NLATEXT[0] = ' ';
+ NLATEXT[1] = ' ';
+ zzbegexpr[0] = '\0';
+ if ( zzbufovf ) {
+ err( eMsgd("predicate buffer overflow; size %d",ZZLEXBUFSIZE));
+ };
+#ifdef __cplusplus__
+/* MR10 */ list_apply(CurActionLabels, (void (*)(void *))mark_label_used_in_sem_pred);
+#else
+#ifdef __STDC__
+/* MR10 */ list_apply(CurActionLabels, (void (*)(void *))mark_label_used_in_sem_pred);
+#else
+#ifdef __USE_PROTOS
+/* MRxx */ list_apply(CurActionLabels, (void (*)(void *))mark_label_used_in_sem_pred);
+#else
+/* MR10 */ list_apply(CurActionLabels,mark_label_used_in_sem_pred);
+#endif
+#endif
+#endif
+ >>
+#token PassAction "\]" << if ( topint() == ']' ) {
+ popint();
+ if ( istackempty() ) /* terminate action */
+ {
+ zzmode(START);
+ NLATEXT[0] = ' ';
+ zzbegexpr[0] = ' ';
+ if ( zzbufovf ) {
+ err( eMsgd("parameter buffer overflow; size %d",ZZLEXBUFSIZE));
+ }
+ }
+ else {
+ /* terminate $[..] and #[..] */
+ if ( GenCC ) zzreplstr("))");
+ else zzreplstr(")");
+ zzmore();
+ }
+ }
+ else if ( topint() == '|' ) { /* end of simple [...] */
+ popint();
+ zzmore();
+ }
+ else zzmore();
+ >>
+#token "consumeUntil\( [\ \t]* \{~[\}]+\} [\ \t]* \)"
+ <<
+ zzmore();
+ zzreplstr(inline_set(zzbegexpr+
+ strlen("consumeUntil(")));
+ >>
+#token "consumeUntil\( ~[\)]+ \)"
+ << zzmore(); >>
+#token "\n|\r|\r\n" << zzline++; zzmore(); DAWDLE; >>
+#token "\>" << zzmore(); >>
+#token "$" << zzmore(); >>
+#token "$$" << if ( !GenCC ) {zzreplstr("zzaRet"); zzmore();}
+ else err("$$ use invalid in C++ mode"); >>
+
+#token "$\[\]" << if ( !GenCC ) {zzreplstr("zzempty_attr"); zzmore();}
+ else err("$[] use invalid in C++ mode"); >>
+#token "$\[" <<
+ pushint(']');
+ if ( !GenCC ) zzreplstr("zzconstr_attr(");
+ else err("$[..] use invalid in C++ mode");
+ zzmore();
+ >>
+#token "$[0-9]+" <<{
+ static char buf[100];
+ numericActionLabel=1; /* MR10 */
+ if ( strlen(zzbegexpr)>(size_t)85 )
+ fatal("$i attrib ref too big");
+ set_orel(atoi(zzbegexpr+1), &attribsRefdFromAction);
+ if ( !GenCC ) sprintf(buf,"zzaArg(zztasp%d,%s)",
+ BlkLevel-1,zzbegexpr+1);
+ else sprintf(buf,"_t%d%s",
+ BlkLevel-1,zzbegexpr+1);
+ zzreplstr(buf);
+ zzmore();
+ UsedOldStyleAttrib = 1;
+ if ( UsedNewStyleLabel )
+ err("cannot mix old-style $i with new-style labels");
+ }
+ >>
+#token "$[0-9]+." <<{
+ static char buf[100];
+ numericActionLabel=1; /* MR10 */
+ if ( strlen(zzbegexpr)>(size_t)85 )
+ fatal("$i.field attrib ref too big");
+ zzbegexpr[strlen(zzbegexpr)-1] = ' ';
+ set_orel(atoi(zzbegexpr+1), &attribsRefdFromAction);
+ if ( !GenCC ) sprintf(buf,"zzaArg(zztasp%d,%s).",
+ BlkLevel-1,zzbegexpr+1);
+ else sprintf(buf,"_t%d%s.",
+ BlkLevel-1,zzbegexpr+1);
+ zzreplstr(buf);
+ zzmore();
+ UsedOldStyleAttrib = 1;
+ if ( UsedNewStyleLabel )
+ err("cannot mix old-style $i with new-style labels");
+ }
+ >>
+#token "$[0-9]+.[0-9]+" <<{
+ static char buf[100];
+ static char i[20], j[20];
+ char *p,*q;
+ numericActionLabel=1; /* MR10 */
+ if (strlen(zzbegexpr)>(size_t)85) fatal("$i.j attrib ref too big");
+ for (p=zzbegexpr+1,q= &i[0]; *p!='.'; p++) {
+ if ( q == &i[20] )
+ fatalFL("i of $i.j attrib ref too big",
+ FileStr[CurFile], zzline );
+ *q++ = *p;
+ }
+ *q = '\0';
+ for (p++, q= &j[0]; *p!='\0'; p++) {
+ if ( q == &j[20] )
+ fatalFL("j of $i.j attrib ref too big",
+ FileStr[CurFile], zzline );
+ *q++ = *p;
+ }
+ *q = '\0';
+ if ( !GenCC ) sprintf(buf,"zzaArg(zztasp%s,%s)",i,j);
+ else sprintf(buf,"_t%s%s",i,j);
+ zzreplstr(buf);
+ zzmore();
+ UsedOldStyleAttrib = 1;
+ if ( UsedNewStyleLabel )
+ err("cannot mix old-style $i with new-style labels");
+ }
+ >>
+#token "$[_a-zA-Z][_a-zA-Z0-9]*"
+ <<{ static char buf[300]; LabelEntry *el;
+ zzbegexpr[0] = ' ';
+ if ( CurRule != NULL &&
+ strcmp(CurRule, &zzbegexpr[1])==0 ) {
+ if ( !GenCC ) zzreplstr("zzaRet");
+ }
+ else if ( CurRetDef != NULL &&
+ strmember(CurRetDef, &zzbegexpr[1])) {
+ if ( hasMultipleOperands( CurRetDef ) ) {
+ require (strlen(zzbegexpr)<=(size_t)285,
+ "$retval attrib ref too big");
+ sprintf(buf,"_retv.%s",&zzbegexpr[1]);
+ zzreplstr(buf);
+ }
+ else zzreplstr("_retv");
+ }
+ else if ( CurParmDef != NULL &&
+ strmember(CurParmDef, &zzbegexpr[1])) {
+ ;
+ }
+ else if ( Elabel==NULL ) {
+ { err("$-variables in actions outside of rules are not allowed"); }
+ } else if ( (el=(LabelEntry *)hash_get(Elabel, &zzbegexpr[1]))!=NULL ) {
+/* MR10 */
+/* MR10 */ /* element labels might exist without an elem when */
+/* MR10 */ /* it is a forward reference (to a rule) */
+/* MR10 */
+/* MR10 */ if ( GenCC && (el->elem == NULL || el->elem->ntype==nRuleRef) )
+/* MR10 */ { err(eMsg1("There are no token ptrs for rule references: '$%s'",&zzbegexpr[1])); }
+/* MR10 */
+/* MR10 */ if ( !GenCC && (el->elem == NULL || el->elem->ntype==nRuleRef) && GenAST) {
+/* MR10 */ err("You can no longer use attributes returned by rules when also using ASTs");
+/* MR10 */ err(" Use upward inheritance (\"rule >[Attrib a] : ... <<$a=...\>\>\")");
+/* MR10 */ };
+/* MR10 */
+/* MR10 */ /* keep track of <<... $label ...>> for semantic predicates in guess mode */
+/* MR10 */ /* element labels contain pointer to the owners node */
+/* MR10 */
+/* MR10 */ if (el->elem != NULL && el->elem->ntype == nToken) {
+/* MR10 */ list_add(&CurActionLabels,el);
+/* MR10 */ };
+ }
+ else
+ warn(eMsg1("$%s not parameter, return value, (defined) element label",&zzbegexpr[1]));
+ }
+ zzmore();
+ >>
+#token "#0" << zzreplstr("(*_root)"); zzmore(); chkGTFlag(); >>
+#token "#\[\]" << if ( GenCC ) {
+ if (NewAST) zzreplstr("(newAST)");
+ else zzreplstr("(new AST)");}
+ else {zzreplstr("zzastnew()");} zzmore();
+ chkGTFlag();
+ >>
+#token "#\(\)" << zzreplstr("NULL"); zzmore(); chkGTFlag(); >>
+#token "#[0-9]+" <<{
+ static char buf[100];
+ if ( strlen(zzbegexpr)>(size_t)85 )
+ fatal("#i AST ref too big");
+ if ( GenCC ) sprintf(buf,"_ast%d%s",BlkLevel-1,zzbegexpr+1);
+ else sprintf(buf,"zzastArg(%s)",zzbegexpr+1);
+ zzreplstr(buf);
+ zzmore();
+ set_orel(atoi(zzbegexpr+1), &AST_nodes_refd_in_actions);
+ chkGTFlag();
+ }
+ >>
+
+/* MR14 Arpad Beszedes 26-May-98
+ Add support for #line directives when antlr source is pre-processed
+ #lexclass ACTIONS
+*/
+
+#token "#line[\ \t]* [0-9]+ {[\ \t]* \"~[\"]+\" ([\ \t]* [0-9]*)* } (\n|\r|\r\n)"
+ <<
+ zzline = atoi(zzbegexpr+5) - 1; zzline++; zzmore();
+ getFileNameFromTheLineInfo(FileStr[CurFile], zzbegexpr);
+ >>
+
+#token "#line ~[\n\r]* (\n|\r|\r\n)"
+ <<
+ zzline++; zzmore();
+ >>
+
+/* MR14 end of a block to support #line in antlr source code */
+
+#token "#[_a-zA-Z][_a-zA-Z0-9]*"
+ <<
+ if ( !(strcmp(zzbegexpr, "#ifdef")==0 ||
+ strcmp(zzbegexpr, "#if")==0 ||
+ strcmp(zzbegexpr, "#else")==0 ||
+ strcmp(zzbegexpr, "#endif")==0 ||
+ strcmp(zzbegexpr, "#ifndef")==0 ||
+ strcmp(zzbegexpr, "#define")==0 ||
+ strcmp(zzbegexpr, "#pragma")==0 ||
+ strcmp(zzbegexpr, "#undef")==0 ||
+ strcmp(zzbegexpr, "#import")==0 ||
+ strcmp(zzbegexpr, "#line")==0 ||
+ strcmp(zzbegexpr, "#include")==0 ||
+ strcmp(zzbegexpr, "#error")==0) )
+ {
+ static char buf[100];
+ sprintf(buf, "%s_ast", zzbegexpr+1);
+/* MR27 */ list_add(&CurAstLabelsInActions, mystrdup(zzbegexpr+1));
+ zzreplstr(buf);
+ chkGTFlag();
+ }
+ zzmore();
+ >>
+#token "#\[" <<
+ pushint(']');
+ if ( GenCC ) {
+ if (NewAST) zzreplstr("(newAST(");
+ else zzreplstr("(new AST("); }
+ else zzreplstr("zzmk_ast(zzastnew(),");
+ zzmore();
+ chkGTFlag();
+ >>
+#token "#\(" <<
+ pushint('}');
+ if ( GenCC ) {
+ if (tmakeInParser) {
+ zzreplstr("tmake(");
+ }
+ else {
+ zzreplstr("ASTBase::tmake(");
+ }
+ }
+ else {
+ zzreplstr("zztmake(");
+ }
+ zzmore();
+ chkGTFlag();
+ >>
+#token "#" << zzmore(); >>
+#token "\)" <<
+ if ( istackempty() )
+ zzmore();
+ else if ( topint()==')' ) {
+ popint();
+ }
+ else if ( topint()=='}' ) {
+ popint();
+ /* terminate #(..) */
+ zzreplstr(", NULL)");
+ }
+ zzmore();
+ >>
+#token "\[" <<
+ pushint('|'); /* look for '|' to terminate simple [...] */
+ zzmore();
+ >>
+#token "\(" <<
+ pushint(')');
+ zzmore();
+ >>
+
+#token "\\\]" << zzreplstr("]"); zzmore(); >>
+#token "\\\)" << zzreplstr(")"); zzmore(); >>
+
+/* MR1 10-Apr-97 MR1 Previously unable to put right shift operator */
+/* MR1 in DLG action */
+
+#token "\\>" << if (! tokenActionActive) zzreplstr(">"); /* MR1 */
+ zzmore(); /* MR1 */
+ >> /* MR1 */
+
+
+#token "'" << zzmode(ACTION_CHARS); zzmore();>>
+#token "\"" << zzmode(ACTION_STRINGS); zzmore();>>
+#token "\\$" << zzreplstr("$"); zzmore(); >>
+#token "\\#" << zzreplstr("#"); zzmore(); >>
+#token "\\(\n|\r|\r\n)" << zzline++; zzmore(); >>
+#token "\\~[\]\)>$#]" << zzmore(); >> /* escaped char, always ignore */
+#token "/" << zzmore(); >>
+#token "/\*" << zzmode(ACTION_COMMENTS); zzmore(); >>
+#token "\*/" << warn("Missing /*; found dangling */ in action"); zzmore(); >>
+#token "//" << zzmode(ACTION_CPP_COMMENTS); zzmore(); >>
+#token "~[\n\r\)\(\\$#\>\]\[\"'/]+" << zzmore(); >>
+
+#lexclass START
+#token "[\t\ ]+" << zzskip(); >> /* Ignore White */
+#token "\n|\r|\r\n" << zzline++; zzskip(); >> /* Track Line # */
+#token "\[" << zzmode(ACTIONS); zzmore();
+ istackreset();
+ pushint(']'); >>
+#token "\<\<" << action_file=CurFile; action_line=zzline;
+ zzmode(ACTIONS); zzmore();
+ list_free(&CurActionLabels,0); /* MR10 */
+ numericActionLabel=0; /* MR10 */
+ istackreset();
+ pushint('>'); >>
+#token "\"" << zzmode(STRINGS); zzmore(); >>
+#token "/\*" << zzmode(COMMENTS); zzskip(); >>
+#token "\*/" << warn("Missing /*; found dangling */"); zzskip(); >>
+#token "//" << zzmode(CPP_COMMENTS); zzskip(); >>
+
+/* MR14 Arpad Beszedes 26-May-98
+ Add support for #line directives when antlr source is pre-processed
+ #lexclass START
+*/
+
+#token "#line[\ \t]* [0-9]+ {[\ \t]* \"~[\"]+\" ([\ \t]* [0-9]*)* } (\n|\r|\r\n)"
+ <<
+ zzline = atoi(zzbegexpr+5) - 1; zzline++; zzmore();
+ getFileNameFromTheLineInfo(FileStr[CurFile], zzbegexpr);
+ >>
+
+#token "#line ~[\n\r]* (\n|\r|\r\n)"
+ <<
+ zzline++; zzmore();
+ >>
+
+/* MR14 end of a block to support #line in antlr source code */
+
+/* */
+/* 8-Apr-97 Regularize escape sequence for ">>" */
+/* appearing in string literals */
+/* */
+
+#token "\>\>" << warn("Missing <<; found dangling \>\>"); zzskip(); >> /* MR1 */
+#token WildCard "."
+#token "\@" <<FoundException = 1; /* MR6 */
+ FoundAtOperator = 1;>> /* MR6 */
+#token Eof "@"
+ << /* L o o k F o r A n o t h e r F i l e */
+ {
+ FILE *new_input;
+ new_input = NextFile();
+ if ( new_input == NULL ) { NLA=Eof; return; }
+ fclose( input );
+ input = new_input;
+ zzrdstream( input );
+ zzskip(); /* Skip the Eof (@) char i.e continue */
+ }
+ >>
+
+#token LABEL
+
+#errclass "grammar-element" { element }
+#errclass "meta-symbol" { "\}" "!" ";" "\|" "\~" "^" "\)" }
+
+#token Pragma "{\\}#pragma" /* MR21 */
+#token FirstSetSymbol "{\\}#FirstSetSymbol" /* MR21 */
+/*
+ * Get a grammar -- Build a list of rules like:
+ *
+ * o-->Rule1--o
+ * |
+ * o-->Rule2--o
+ * |
+ * ...
+ * |
+ * o-->RuleN--o
+ */
+
+/* rule grammar */
+
+grammar : <<Graph g;>>
+ ( "{\\}#header" Action /* MR13 */
+ <<
+ if ( HdrAction==NULL ) {
+ HdrAction = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char));
+ require(HdrAction!=NULL, "rule grammar: cannot allocate header action");
+ strcpy(HdrAction, LATEXT(1));
+ }
+ else warn("additional #header statement ignored");
+ >>
+ | "{\\}#first" Action
+ <<
+ if ( FirstAction==NULL ) {
+ FirstAction = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char));
+ require(FirstAction!=NULL, "rule grammar: cannot allocate #first action");
+ strcpy(FirstAction, LATEXT(1));
+ } else {
+ warn("additional #first statement ignored");
+ };
+ >>
+
+ | "{\\}#parser" QuotedTerm
+ <<
+ if ( GenCC ) {
+ warn("#parser meta-op incompatible with -CC; ignored");
+ }
+ else {
+ if ( strcmp(ParserName,"zzparser")==0 ) {
+ ParserName=StripQuotes(mystrdup(LATEXT(1)));
+ if ( RulePrefix[0]!='\0' )
+ {
+ warn("#parser meta-op incompatible with '-gp prefix'; '-gp' ignored");
+ RulePrefix[0]='\0';
+ }
+ }
+ else warn("additional #parser statement ignored");
+ }
+ >>
+ | "{\\}#tokdefs" QuotedTerm
+ <<{
+ char *fname;
+ zzantlr_state st; FILE *f; struct zzdlg_state dst;
+ UserTokenDefsFile = mystrdup(LATEXT(1));
+ zzsave_antlr_state(&st);
+ zzsave_dlg_state(&dst);
+ fname = mystrdup(LATEXT(1));
+ f = fopen(StripQuotes(fname), "r");
+ if ( f==NULL ) {warn(eMsg1("cannot open token defs file '%s'", fname+1));}
+ else {
+ ANTLRm(enum_file(fname+1), f, PARSE_ENUM_FILE);
+ UserDefdTokens = 1;
+ }
+ zzrestore_antlr_state(&st);
+ zzrestore_dlg_state(&dst);
+ }>>
+ )*
+ ( Action
+ <<{
+ UserAction *ua = newUserAction(LATEXT(1));
+ ua->file = action_file; ua->line = action_line;
+ if ( class_nest_level>0 ) list_add(&class_before_actions, ua);
+ else list_add(&BeforeActions, ua);
+ }>>
+ | laction
+ | lmember /* MR1 */
+ | lprefix /* MR1 */
+ | aLexclass
+ | token
+ | error
+ | tclass
+ | aPred /* MR11 */
+ | default_exception_handler
+ | class_def
+ | "\}"
+ <<
+ if ( class_nest_level==0 )
+ warn("missing class definition for trailing '}'");
+ class_nest_level--;
+ >>
+ )*
+
+ rule <<g=$3; SynDiag = (Junction *) $3.left;>>
+ ( rule
+
+ <<if ( $1.left!=NULL ) {
+ g.right = NULL;
+
+/* MR21a */ /* Avoid use of a malformed graph when CannotContinue */
+/* MR21a */ /* is already set */
+/* MR21a */
+/* MR21a */ if (! (CannotContinue && g.left == NULL)) {
+/* MR21a */ g = Or(g, $1);
+/* MR21a */ }
+/* MR21a */ }
+ >>
+
+ | aLexclass
+ | token
+ | error
+ | tclass
+ | aPred /* MR11 */
+ | class_def
+ | "\}"
+ <<
+ if ( class_nest_level==0 )
+ warn("missing class definition for trailing '}'");
+ class_nest_level--;
+ >>
+ )*
+ ( Action
+ <<{
+ UserAction *ua = newUserAction(LATEXT(1));
+ ua->file = action_file; ua->line = action_line;
+ if ( class_nest_level>0 ) list_add(&class_after_actions, ua);
+ else list_add(&AfterActions, ua);
+ }>>
+ | laction
+ | lmember /* MR1 */
+ | lprefix /* MR1 */
+ | error
+ | tclass
+ | class_def
+ | aPred /* MR11 */
+ | "\}"
+ <<
+ if ( class_nest_level==0 )
+ warn("missing class definition for trailing '}'");
+ class_nest_level--;
+ >>
+ )*
+ Eof
+ ;
+ <<CannotContinue=TRUE;>>
+
+/* rule class_def */
+
+class_def
+ : <<int go=1; char name[MaxRuleName+1];>>
+ "class"
+ ( NonTerminal <<if(go) strncpy(name,LATEXT(1),MaxRuleName);>>
+ | TokenTerm <<if(go) strncpy(name,LATEXT(1),MaxRuleName);>>
+ )
+ <<
+ if ( CurrentClassName[0]!='\0' && strcmp(CurrentClassName,name)!=0
+ && GenCC ) {
+ err("only one grammar class allowed in this release");
+ go = 0;
+ }
+ else strcpy(CurrentClassName, name);
+ >>
+ <<if ( !GenCC ) { err("class meta-op used without C++ option"); }>>
+
+/* MR10 */ (~ "\{"
+/* MR10 */ <<if (ClassDeclStuff == NULL) {
+/* MR10 */ ClassDeclStuff=(char *)calloc(MaxClassDeclStuff+1,sizeof(char));
+/* MR10 */ };
+/* MR10 */ strncat(ClassDeclStuff," ",MaxClassDeclStuff);
+/* MR10 */ strncat(ClassDeclStuff,LATEXT(1),MaxClassDeclStuff);
+/* MR22 */ do {
+/* MR22 */ if (0 == strcmp(LATEXT(1),"public")) break;
+/* MR22 */ if (0 == strcmp(LATEXT(1),"private")) break;
+/* MR22 */ if (0 == strcmp(LATEXT(1),"protected")) break;
+/* MR22 */ if (0 == strcmp(LATEXT(1),"virtual")) break;
+/* MR22 */ if (0 == strcmp(LATEXT(1),",")) break;
+/* MR22 */ if (0 == strcmp(LATEXT(1),":")) break;
+/* MR22 */ if (BaseClassName != NULL) break;
+/* MR22 */ BaseClassName=(char *)calloc(strlen(LATEXT(1))+1,sizeof(char));
+/* MR22 */ require(BaseClassName!=NULL, "rule grammar: cannot allocate base class name");
+/* MR22 */ strcpy(BaseClassName,LATEXT(1));
+/* MR22 */ } while (0);
+/* MR10 */ >>
+/* MR10 */ )*
+
+ "\{"
+ <<
+ no_classes_found = 0;
+ if ( class_nest_level>=1 ) {warn("cannot have nested classes");}
+ else class_nest_level++;
+ >>
+ ;
+ <<CannotContinue=TRUE;>>
+
+/*
+ * Build -o-->o-R-o-->o- where -o-R-o- is the block from rule 'block'.
+ * Construct the RuleBlk front and EndRule node on the end of the
+ * block. This is used to add FOLLOW pointers to the rule end. Add the
+ * new rule name to the Rname hash table and sets its rulenum.
+ * Store the parameter definitions if any are found.
+ *
+ * Note that locks are required on the RuleBlk and EndRule nodes to thwart
+ * infinite recursion.
+ *
+ * Return the left graph pointer == NULL to indicate error/dupl rule def.
+ */
+
+/* rule rule */
+
+rule : <<
+
+ ExceptionGroup *eg;
+ RuleEntry *q; Junction *p; Graph r; int f, l; ECnode *e;
+ set toksrefd, rulesrefd;
+ char *pdecl=NULL, *ret=NULL, *a; CurRetDef = CurParmDef = NULL;
+ CurExGroups = NULL;
+ CurElementLabels = NULL;
+ CurAstLabelsInActions = NULL; /* MR27 */
+ /* We want a new element label hash table for each rule */
+ if ( Elabel!=NULL ) killHashTable(Elabel);
+ Elabel = newHashTable();
+ attribsRefdFromAction = empty;
+ >>
+ NonTerminal
+ <<q=NULL;
+ if ( hash_get(Rname, LATEXT(1))!=NULL ) {
+ err(eMsg1("duplicate rule definition: '%s'",LATEXT(1)));
+ CannotContinue=TRUE;
+ }
+ else
+ {
+ q = (RuleEntry *)hash_add(Rname,
+ LATEXT(1),
+ (Entry *)newRuleEntry(LATEXT(1)));
+ CurRule = q->str;
+ }
+ CurRuleNode = q;
+ f = CurFile; l = zzline;
+ NumRules++;
+ >>
+ { "!" <<if ( q!=NULL ) q->noAST = TRUE;>> }
+ { <<;>>
+ {"\<"}
+ PassAction
+ << pdecl = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char));
+ require(pdecl!=NULL, "rule rule: cannot allocate param decl");
+ strcpy(pdecl, LATEXT(1));
+ CurParmDef = pdecl;
+ >>
+ }
+ { "\>"
+ PassAction
+ << ret = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char));
+ require(ret!=NULL, "rule rule: cannot allocate ret type");
+ strcpy(ret, LATEXT(1));
+ CurRetDef = ret;
+ >>
+ }
+ { QuotedTerm <<if ( q!=NULL ) q->egroup=mystrdup(LATEXT(1));>> }
+ <<
+ if ( GenEClasseForRules && q!=NULL ) {
+ e = newECnode;
+ require(e!=NULL, "cannot allocate error class node");
+ if ( q->egroup == NULL ) {a = q->str; a[0] = (char)toupper(a[0]);}
+ else a = q->egroup;
+ if ( Tnum( a ) == 0 )
+ {
+ e->tok = addTname( a );
+ list_add(&eclasses, (char *)e);
+ if ( q->egroup == NULL ) a[0] = (char)tolower(a[0]);
+ /* refers to itself */
+ list_add(&(e->elist), mystrdup(q->str));
+ }
+ else {
+ warn(eMsg1("default errclass for '%s' would conflict with token/errclass/tokclass",a));
+ if ( q->egroup == NULL ) a[0] = (char)tolower(a[0]);
+ free((char *)e);
+ }
+ }
+ >>
+ <<BlkLevel++;
+ if (BlkLevel >= MAX_BLK_LEVEL) fatal("Blocks nested too deeply");
+/* MR23 */ CurBlockID_array[BlkLevel] = CurBlockID;
+/* MR23 */ CurAltNum_array[BlkLevel] = CurAltNum;
+ >>
+
+ ":" <<inAlt=1;>>
+ block[&toksrefd, &rulesrefd]
+ <<r = makeBlk($7,0, NULL /* pFirstSetSymbol */ );
+ CurRuleBlk = (Junction *)r.left;
+ CurRuleBlk->blockid = CurBlockID;
+ CurRuleBlk->jtype = RuleBlk;
+ if ( q!=NULL ) CurRuleBlk->rname = q->str;
+ CurRuleBlk->file = f;
+ CurRuleBlk->line = l;
+ CurRuleBlk->pdecl = pdecl;
+ CurRuleBlk->ret = ret;
+ CurRuleBlk->lock = makelocks();
+ CurRuleBlk->pred_lock = makelocks();
+ CurRuleBlk->tokrefs = toksrefd;
+ CurRuleBlk->rulerefs = rulesrefd;
+ p = newJunction(); /* add EndRule Node */
+ ((Junction *)r.right)->p1 = (Node *)p;
+ r.right = (Node *) p;
+ p->jtype = EndRule;
+ p->lock = makelocks();
+ p->pred_lock = makelocks();
+ CurRuleBlk->end = p;
+ if ( q!=NULL ) q->rulenum = NumRules;
+ $7 = r;
+ >>
+ <<
+ /* MR23 */ CurBlockID_array[BlkLevel] = (-1);
+ /* MR23 */ CurAltNum_array[BlkLevel] = (-1);
+ --BlkLevel;
+ >>
+ <<altFixup();leFixup();egFixup();>> /* MR7 */
+ ";" <<inAlt=0;>>
+ { Action
+ << a = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char));
+ require(a!=NULL, "rule rule: cannot allocate error action");
+ strcpy(a, LATEXT(1));
+ CurRuleBlk->erraction = a;
+ >>
+ }
+ ( exception_group > [eg]
+ <<if ( eg!=NULL ) {
+ list_add(&CurExGroups, (void *)eg);
+ if (eg->label == NULL || *eg->label=='\0' ) q->has_rule_exception = 1;
+ }
+ >>
+ )*
+ <<if ( q==NULL ) $0.left = NULL; else $0 = $7;>>
+ <<CurRuleBlk->exceptions = CurExGroups;>>
+ <<CurRuleBlk->el_labels = CurElementLabels;>>
+ <<CurRuleNode->ast_labels_in_actions = CurAstLabelsInActions;>> /* MR27 */
+ <<CurRuleNode = NULL;>> /* MR27 Moved */
+ ;
+ <<CannotContinue=TRUE;>>
+
+/*
+ * pragma : "{\\}#pragma" "dup\-labeled\-tokens"
+ * <<Pragma_DupLabeledTokens=1;>>
+ * ;
+ */
+
+/* rule laction */
+
+laction : <<char *a;>>
+
+ "{\\}#lexaction"
+ Action
+ <<
+ a = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char));
+ require(a!=NULL, "rule laction: cannot allocate action");
+ strcpy(a, LATEXT(1));
+ list_add(&LexActions, a);
+ >>
+ ;
+ <<CannotContinue=TRUE;>>
+
+/* MR1 */
+/* MR1 11-Apr-97 Provide mechanism for inserting code into DLG class */
+/* MR1 via #lexmember <<....>> & #lexprefix <<...>> */
+/* MR1 */
+
+/* rule lmember */
+
+lmember: <<char *a;>> /* MR1 */
+
+/* MR1 */ "{\\}#lexmember"
+/* MR1 */ Action
+/* MR1 */ <<
+/* MR1 */ if (! GenCC) {
+/* MR1 */ err("Use #lexmember only in C++ mode (to insert code in DLG class header");
+/* MR1 */ } else {
+/* MR1 */ a = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char));
+/* MR1 */ require(a!=NULL, "rule lmember: cannot allocate action");
+/* MR1 */ strcpy(a, LATEXT(1));
+/* MR1 */ list_add(&LexMemberActions, a);
+/* MR1 */ };
+/* MR1 */ >>
+/* MR1 */ ;
+/* MR1 */ <<CannotContinue=TRUE;>>
+
+/* rule lprefix */
+
+lprefix: <<char *a;>> /* MR1 */
+
+/* MR1 */ "{\\}#lexprefix"
+/* MR1 */ Action
+/* MR1 */ <<
+/* MR1 */ if (! GenCC) {
+/* MR1 */ err("Use #lexprefix only in C++ mode (to insert code in DLG class header");
+/* MR1 */ } else {
+/* MR1 */ a = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char));
+/* MR1 */ require(a!=NULL, "rule lprefix: cannot allocate action");
+/* MR1 */ strcpy(a, LATEXT(1));
+/* MR1 */ list_add(&LexPrefixActions, a);
+/* MR1 */ };
+/* MR1 */ >>
+/* MR1 */ ;
+/* MR1 */ <<CannotContinue=TRUE;>>
+
+/*
+ * #pred upper <<isupper()>>? predicate literal
+ * #pred lower <<islower()>>? predicate literal
+ * #pred up_or_low upper || lower predicate expression
+ * concealed interdependence
+ * #pred up_or_low_2 <<isletter()>>? A || B predicate literal equals predicate expr
+ * analyze using lower||upper
+ * generate using isLetter()
+ */
+
+/* rule aPref */
+
+aPred: <<PredEntry *predEntry=NULL;
+ char *name=NULL;
+ Predicate *predExpr=NULL;
+ char *predLiteral=NULL;
+ int save_file;
+ int save_line;
+ int predExprPresent=0;
+ >>
+
+ "{\\}#pred"
+
+ <<
+ MR_usingPredNames=1; /* will need to use -mrhoist version of genPredTree */
+ >>
+
+ /* used to allow NonTerminal but it caused problems
+ when a rule name immediately followed a #pred statement */
+
+ TokenTerm <<name=mystrdup(LATEXT(1));>>
+
+ <<
+ /* don't free - referenced in predicates */
+
+ CurPredName=(char *)calloc(1,strlen(name) + 10);
+ strcat(CurPredName,"#pred ");
+ strcat(CurPredName,name);
+
+ predEntry=(PredEntry *) hash_get(Pname,name);
+ if (predEntry != NULL) {
+ warnFL(eMsg1("#pred %s previously defined - ignored",name),
+ FileStr[action_file],action_line);
+ name=NULL;
+ };
+ >>
+
+ (
+
+ Pred <<predLiteral=mystrdup(LATEXT(1));
+ save_line=action_line;
+ save_file=action_file;
+ >>
+
+ {
+ predOrExpr>[predExpr] <<predExprPresent=1;>>
+ }
+
+ <<if (predLiteral != NULL && name != NULL) {
+
+ /*
+ * predExpr may be NULL due to syntax errors
+ * or simply omitted by the user
+ */
+
+ predEntry=newPredEntry(name);
+ predEntry->file=save_file;
+ predEntry->line=save_line;
+ predExpr=MR_predFlatten(predExpr);
+ predEntry->predLiteral=predLiteral;
+ if (! predExprPresent || predExpr == NULL) {
+ predExpr=new_pred();
+ predExpr->expr=predLiteral;
+ predExpr->source=newActionNode();
+ predExpr->source->action=predExpr->expr;
+ predExpr->source->rname=CurPredName;
+ predExpr->source->line=action_line;
+ predExpr->source->file=action_file;
+ predExpr->source->is_predicate=1;
+ predExpr->k=predicateLookaheadDepth(predExpr->source);
+ };
+ predEntry->pred=predExpr;
+ hash_add(Pname,name,(Entry *)predEntry);
+ predExpr=NULL;
+ };
+ predicate_free(predExpr);
+ >>
+
+ |
+ <<save_line=zzline; save_file=CurFile;>>
+
+ predOrExpr>[predExpr]
+
+ <<if (predExpr != NULL && name != NULL) {
+ predEntry=newPredEntry(name);
+ predEntry->file=CurFile;
+ predEntry->line=zzline;
+ predExpr=MR_predFlatten(predExpr);
+ predEntry->pred=predExpr;
+ hash_add(Pname,name,(Entry *)predEntry);
+ predExpr=NULL;
+ };
+ predicate_free(predExpr);
+ >>
+ )
+ {";"}
+;
+
+/* fail */
+
+<<predicate_free(predExpr);
+>>
+
+/* rule predOrExpr */
+
+predOrExpr>[Predicate *result] :
+ <<Predicate *ORnode;
+ Predicate *predExpr;
+ Predicate **tail=NULL;
+ >>
+ predAndExpr>[predExpr]
+ <<
+ ORnode=new_pred();
+ ORnode->expr=PRED_OR_LIST;
+ if (predExpr != NULL) {
+ ORnode->down=predExpr;
+ tail=&predExpr->right;
+ };
+ >>
+ ( "\|\|" predAndExpr>[predExpr]
+ <<
+ if (predExpr != NULL) {
+ *tail=predExpr;
+ tail=&predExpr->right;
+ };
+ >>
+ )*
+ <<
+ $result=ORnode;
+ ORnode=NULL;
+ >>
+;
+
+/* fail */
+
+<<predicate_free(ORnode);>>
+
+/* rule predAndExpr */
+
+predAndExpr>[Predicate *result] :
+ <<Predicate *ANDnode;
+ Predicate *predExpr;
+ Predicate **tail=NULL;
+ >>
+ predPrimary>[predExpr]
+ <<
+ ANDnode=new_pred();
+ ANDnode->expr=PRED_AND_LIST;
+ if (predExpr != NULL) {
+ ANDnode->down=predExpr;
+ tail=&predExpr->right;
+ };
+ >>
+ ( "&&" predPrimary>[predExpr]
+ <<
+ if (predExpr != NULL) {
+ *tail=predExpr;
+ tail=&predExpr->right;
+ };
+ >>
+ )*
+ <<
+ $result=ANDnode;
+ ANDnode=NULL;
+ >>
+;
+
+/* fail */
+
+<<predicate_free(ANDnode);>>
+
+
+/* rule predPrimary */
+
+predPrimary>[Predicate *result] :
+ <<
+ char *name=NULL;
+ PredEntry *predEntry=NULL;
+ Predicate *predExpr=NULL;
+ >>
+
+ TokenTerm <<name=mystrdup(LATEXT(1));>>
+
+ <<
+ predEntry=(PredEntry *) hash_get(Pname,name);
+ if (predEntry == NULL) {
+ warnFL(eMsg1("no previously defined #pred with name \"%s\"",name),
+ FileStr[CurFile],zzline);
+ name=NULL;
+ $result=NULL;
+ } else {
+ predExpr=predicate_dup(predEntry->pred);
+ predExpr->predEntry=predEntry;
+ $result=predExpr;
+ };
+ >>
+
+ | "\(" predOrExpr>[predExpr] "\)"
+ <<
+ $result=predExpr;
+ >>
+
+ | "!" predPrimary>[predExpr]
+ <<
+ predExpr->inverted=!predExpr->inverted;
+ $result=predExpr;
+ >>
+;
+
+/* fail */ <<
+ predicate_free(predExpr);
+ >>
+
+/* rule aLexclass */
+
+aLexclass: "{\\}#lexclass" TokenTerm <<lexclass(mystrdup(LATEXT(1)));>>
+ ;
+ <<CannotContinue=TRUE;>>
+
+/* rule error */
+
+error : <<char *t=NULL; ECnode *e; int go=1; TermEntry *p;>>
+ "{\\}#errclass"
+ (<<;>> TokenTerm <<t=mystrdup(LATEXT(1));>>
+ | QuotedTerm <<t=mystrdup(LATEXT(1));>>
+ )
+ <<e = newECnode;
+ require(e!=NULL, "cannot allocate error class node");
+ e->lexclass = CurrentLexClass;
+ if ( Tnum( (t=StripQuotes(t)) ) == 0 )
+ {
+ if ( hash_get(Texpr, t) != NULL )
+ warn(eMsg1("errclass name conflicts with regular expression '%s'",t));
+ e->tok = addTname( t );
+ set_orel(e->tok, &imag_tokens);
+ require((p=(TermEntry *)hash_get(Tname, t)) != NULL,
+ "hash table mechanism is broken");
+ p->classname = 1; /* entry is errclass name, not token */
+ list_add(&eclasses, (char *)e);
+ }
+ else
+ {
+ warn(eMsg1("redefinition of errclass or conflict w/token or tokclass '%s'; ignored",t));
+ free( (char *)e );
+ go=0;
+ }
+ >>
+ "\{"
+ ( NonTerminal <<if ( go ) t=mystrdup(LATEXT(1));>>
+ | TokenTerm <<if ( go ) t=mystrdup(LATEXT(1));>>
+ | QuotedTerm <<if ( go ) t=mystrdup(LATEXT(1));>>
+ )
+ <<if ( go ) list_add(&(e->elist), t);>>
+ (
+ ( NonTerminal <<if ( go ) t=mystrdup(LATEXT(1));>>
+ | TokenTerm <<if ( go ) t=mystrdup(LATEXT(1));>>
+ | QuotedTerm <<if ( go ) t=mystrdup(LATEXT(1));>>
+ )
+ <<if ( go ) list_add(&(e->elist), t);>>
+ )*
+ "\}"
+ ;
+ <<CannotContinue=TRUE;>>
+
+/* rule tclass */
+
+tclass : <<char *t=NULL; TCnode *e; int go=1,tok,totok; TermEntry *p, *term, *toterm;>>
+ <<char *akaString=NULL; int save_file; int save_line;>>
+ <<char *totext=NULL; >>
+ "{\\}#tokclass" TokenTerm <<t=mystrdup(LATEXT(1));>>
+ <<e = newTCnode;
+ require(e!=NULL, "cannot allocate token class node");
+ e->lexclass = CurrentLexClass;
+ if ( Tnum( t ) == 0 )
+ {
+ e->tok = addTname( t );
+ set_orel(e->tok, &imag_tokens);
+ set_orel(e->tok, &tokclasses);
+ require((p=(TermEntry *)hash_get(Tname, t)) != NULL,
+ "hash table mechanism is broken");
+ p->classname = 1; /* entry is class name, not token */
+ p->tclass = e; /* save ptr to this tclass def */
+ list_add(&tclasses, (char *)e);
+ }
+ else
+ {
+ warn(eMsg1("redefinition of tokclass or conflict w/token '%s'; ignored",t));
+ free( (char *)e );
+ go=0;
+ }
+ >>
+/* MR23 */ {
+/* MR23 */ "\("
+/* MR23 */ QuotedTerm
+/* MR23 */ <<akaString=mystrdup(StripQuotes(LATEXT(1)));
+/* MR11 */ save_file=CurFile;save_line=zzline;
+/* MR23 */ >>
+/* MR23 */ "\)"
+/* MR23 */ }
+/* MR23 */
+/* MR23 */
+/* MR23 */ <<
+/* MR23 */ if (p!= NULL && akaString != NULL) {
+/* MR23 */ if (p->akaString != NULL) {
+/* MR23 */ if (strcmp(p->akaString,akaString) != 0) {
+/* MR23 */ warnFL(eMsg2("this #tokclass statment conflicts with a previous #tokclass %s(\"%s\") statement",
+/* MR23 */ t,p->akaString),
+/* MR23 */ FileStr[save_file],save_line);
+/* MR23 */ };
+/* MR23 */ } else {
+/* MR23 */ p->akaString=akaString;
+/* MR23 */ };
+/* MR23 */ };
+/* MR23 */ >>
+
+ "\{"
+ (
+ ( TokenTerm
+ <<if ( go ) {
+ term = (TermEntry *) hash_get(Tname, LATEXT(1));
+ if ( term==NULL && UserDefdTokens ) {
+ err("implicit token definition not allowed with #tokdefs");
+ go = 0;
+ }
+ else {t=mystrdup(LATEXT(1)); tok=addTname(LATEXT(1));}
+ }>>
+
+ {
+ ".."
+ TokenTerm
+
+ <<if ( go ) {
+ toterm = (TermEntry *) hash_get(Tname, LATEXT(1));
+ if ( toterm==NULL && UserDefdTokens ) {
+ err("implicit token definition not allowed with #tokdefs");
+ go = 0;
+ } else {
+ totext=mystrdup(LATEXT(1)); totok=addTname(LATEXT(1));
+ }
+ }
+ >>
+ }
+
+ | QuotedTerm
+ <<if ( go ) {
+ term = (TermEntry *) hash_get(Texpr, LATEXT(1));
+ if ( term==NULL && UserDefdTokens ) {
+ err("implicit token definition not allowed with #tokdefs");
+ go = 0;
+ }
+ else {t=mystrdup(LATEXT(1)); tok=addTexpr(LATEXT(1));}
+ }>>
+ )
+ <<if ( go ) {
+ if (totext == NULL) {
+ list_add(&(e->tlist), t);
+ } else {
+ list_add(&(e->tlist),"..");
+ list_add(&(e->tlist),t);
+ list_add(&(e->tlist),totext);
+ }
+ totext=NULL;
+ }
+ >>
+ )+ // MR15 Manfred Kogler - forbid empty #tokclass sets (was "+")
+ "\}"
+ ;
+ <<CannotContinue=TRUE;>>
+
+/* rule token */
+
+token : <<char *t=NULL, *e=NULL, *a=NULL; int tnum=0;>>
+ <<char *akaString=NULL; TermEntry *te;int save_file=0,save_line=0;>> /* MR11 */
+ "{\\}#token"
+
+/* MR1 10-Apr-97 MR1 Allow shift right operator in DLG actions */
+/* MR1 Danger when parser feedback to lexer */
+/* MR1 */
+
+ <<tokenActionActive=1;>> /* MR1 */
+ { TokenTerm <<t=mystrdup(LATEXT(1));>>
+
+/* MR11 */ {
+/* MR11 */ "\("
+/* MR11 */ QuotedTerm
+/* MR11 */ <<akaString=mystrdup(StripQuotes(LATEXT(1)));
+/* MR11 */ save_file=CurFile;save_line=zzline;
+/* MR11 */ >>
+/* MR11 */ "\)"
+/* MR11 */ }
+
+ { "=" "[0-9]+" /* define the token type number */
+ <<tnum = atoi(LATEXT(1));>>
+ }
+ }
+ { QuotedTerm <<e=mystrdup(LATEXT(1));>> }
+ { Action
+ <<
+ a = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char));
+ require(a!=NULL, "rule token: cannot allocate action");
+ strcpy(a, LATEXT(1));
+ >>
+ }
+
+ { ";" } /* MR11 */
+
+ <<chkToken(t, e, a, tnum);>>
+
+ <<if (t != NULL) {
+ te=(TermEntry *)hash_get(Tname,t);
+ if (te != NULL && akaString != NULL) {
+ if (te->akaString != NULL) {
+ if (strcmp(te->akaString,akaString) != 0) {
+ warnFL(eMsg2("this #token statment conflicts with a previous #token %s(\"%s\") statement",
+ t,te->akaString),
+ FileStr[save_file],save_line);
+ };
+ } else {
+ te->akaString=akaString;
+ };
+ };
+ };
+ >>
+ ;
+ <<CannotContinue=TRUE;>>
+
+/* rule block */
+
+block[set *toksrefd, set *rulesrefd]
+ : <<
+ Graph g, b;
+ set saveblah;
+ int saveinalt = inAlt;
+ ExceptionGroup *eg;
+ *$toksrefd = empty;
+ *$rulesrefd = empty;
+ set_clr(AST_nodes_refd_in_actions);
+ CurBlockID++;
+/* MR23 */ CurBlockID_array[BlkLevel] = CurBlockID;
+ CurAltNum = 1;
+/* MR23 */ CurAltNum_array[BlkLevel] = CurAltNum;
+ saveblah = attribsRefdFromAction;
+ attribsRefdFromAction = empty;
+ >>
+
+ alt[toksrefd,rulesrefd] <<b = g = $1;>>
+
+ <<
+ if ( ((Junction *)g.left)->p1->ntype == nAction )
+ {
+ ActionNode *actionNode=(ActionNode *)
+ ( ( (Junction *)g.left) ->p1);
+ if (!actionNode->is_predicate )
+ {
+ actionNode->init_action = TRUE;
+/* MR12c */ if (actionNode->noHoist) {
+/* MR12c */ errFL("<<nohoist>> appears as init-action - use <<>> <<nohoist>>",
+/* MR12c */ FileStr[actionNode->file],actionNode->line);
+/* MR12c */ };
+ }
+ }
+ ((Junction *)g.left)->blockid = CurBlockID;
+ >>
+
+ ( exception_group > [eg]
+ <<
+ if ( eg!=NULL ) {
+/* MR7 ***** eg->altID = makeAltID(CurBlockID,CurAltNum); *****/
+/* MR7 ***** CurAltStart->exception_label = eg->altID; *****/
+ list_add(&CurExGroups, (void *)eg);
+ }
+ >>
+ )*
+ <<CurAltNum++;
+/* MR23 */ CurAltNum_array[BlkLevel] = CurAltNum;
+ >>
+
+ ( "\|" <<inAlt=1;>>
+ alt[toksrefd,rulesrefd] <<g = Or(g, $2);>>
+ <<
+ ((Junction *)g.left)->blockid = CurBlockID;
+ >>
+
+ ( exception_group > [eg]
+ <<
+ if ( eg!=NULL ) {
+/* MR7 ***** eg->altID = makeAltID(CurBlockID,CurAltNum); *****/
+/* MR7 ***** CurAltStart->exception_label = eg->altID; *****/
+ list_add(&CurExGroups, (void *)eg);
+ }
+ >>
+ )*
+
+ <<CurAltNum++;
+/* MR23 */ CurAltNum_array[BlkLevel] = CurAltNum;
+ >>
+
+ )*
+ <<$0 = b;>>
+ <<attribsRefdFromAction = saveblah; inAlt = saveinalt;>>
+ ;
+ <<CannotContinue=TRUE;>>
+
+/* rule alt */
+
+alt[set *toksrefd, set *rulesrefd]
+ : <<int n=0; Graph g; int e_num=0, old_not=0; Node *node; set elems, dif;
+ int first_on_line = 1, use_def_MT_handler = 0;
+ g.left=NULL; g.right=NULL;
+
+ CurAltStart = NULL;
+ elems = empty;
+ inAlt = 1;
+ >>
+ { "\@" /* handle MismatchedToken signals with default handler */
+ <<use_def_MT_handler = 1;>>
+ }
+
+ ( <<;>> /* MR9 Removed unreferenced variable "tok" */
+ { <<old_not=0;>> "\~" <<old_not=1;>> }
+ element[old_not, first_on_line, use_def_MT_handler] > [node]
+ <<if ( node!=NULL && node->ntype!=nAction ) first_on_line = 0;>>
+ <<
+ if ( $2.left!=NULL ) {
+ g = Cat(g, $2);
+ n++;
+ if ( node!=NULL ) {
+ if ( node->ntype!=nAction ) e_num++;
+ /* record record number of all rule and token refs */
+ if ( node->ntype==nToken ) {
+ TokNode *tk = (TokNode *)((Junction *)$2.left)->p1;
+ tk->elnum = e_num;
+ set_orel(e_num, &elems);
+ }
+ else if ( node->ntype==nRuleRef ) {
+ RuleRefNode *rn = (RuleRefNode *)((Junction *)$2.left)->p1;
+ rn->elnum = e_num;
+ set_orel(e_num, $rulesrefd);
+ }
+ }
+ }
+ >>
+ )*
+ <<if ( n == 0 ) g = emptyAlt();
+ $0 = g;
+ /* We want to reduce number of LT(i) calls and the number of
+ * local attribute variables in C++ mode (for moment, later we'll
+ * do for C also). However, if trees are being built, they
+ * require most of the attrib variables to create the tree nodes
+ * with; therefore, we gen a token ptr for each token ref in C++
+ */
+ if ( GenCC && !GenAST )
+ {
+ /* This now free's the temp set -ATG 5/6/95 */
+ set temp;
+ temp = set_and(elems, attribsRefdFromAction);
+ set_orin($toksrefd, temp);
+ set_free(temp);
+ }
+ else set_orin($toksrefd, elems);
+ if ( GenCC ) {
+ dif = set_dif(attribsRefdFromAction, elems);
+ if ( set_deg(dif)>0 )
+ err("one or more $i in action(s) refer to non-token elements");
+ set_free(dif);
+ }
+ set_free(elems);
+ set_free(attribsRefdFromAction);
+ inAlt = 0;
+ >>
+ ;
+ <<CannotContinue=TRUE;>>
+
+/* rule element_label */
+
+element_label > [LabelEntry *label]
+ : <<TermEntry *t=NULL; LabelEntry *l=NULL; RuleEntry *r=NULL; char *lab;>>
+ LABEL <<lab = mystrdup(LATEXT(1));>>
+ <<
+ UsedNewStyleLabel = 1;
+ if ( UsedOldStyleAttrib ) err("cannot mix with new-style labels with old-style $i");
+ t = (TermEntry *) hash_get(Tname, lab);
+ if ( t==NULL ) t = (TermEntry *) hash_get(Texpr, lab);
+ if ( t==NULL ) r = (RuleEntry *) hash_get(Rname, lab);
+ if ( t!=NULL ) {
+ err(eMsg1("label definition clashes with token/tokclass definition: '%s'", lab));
+ $label = NULL;
+ }
+ else if ( r!=NULL ) {
+ err(eMsg1("label definition clashes with rule definition: '%s'", lab));
+ $label = NULL;
+ }
+ else {
+ /* we don't clash with anybody else */
+ l = (LabelEntry *) hash_get(Elabel, lab);
+ if ( l==NULL ) { /* ok to add new element label */
+ l = (LabelEntry *)hash_add(Elabel,
+ lab,
+ (Entry *)newLabelEntry(lab));
+ /* add to list of element labels for this rule */
+ list_add(&CurElementLabels, (void *)lab);
+/* MR7 */ leAdd(l); /* list of labels waiting for exception group definitions */
+ $label = l;
+ }
+ else {
+ err(eMsg1("label definitions must be unique per rule: '%s'", lab));
+ $label = NULL;
+ }
+ }
+ >>
+ ":"
+ ;
+
+/* rule element */
+
+element[int old_not, int first_on_line, int use_def_MT_handler] > [Node *node]
+ : <<
+ Attrib blk;
+ Predicate *pred = NULL;
+ int local_use_def_MT_handler=0;
+ ActionNode *act;
+ RuleRefNode *rr;
+ set toksrefd, rulesrefd;
+ TermEntry *term;
+ TokNode *p=NULL; RuleRefNode *q; int approx=0;
+ LabelEntry *label=NULL;
+ int predMsgDone=0;
+ int semDepth=0;
+ int ampersandStyle;
+ int height; /* MR11 */
+ int equal_height; /* MR11 */
+
+ char* pFirstSetSymbol = NULL; /* MR21 */
+
+ $node = NULL;
+ >>
+ {element_label>[label]}
+ ( TokenTerm
+ <<
+ term = (TermEntry *) hash_get(Tname, LATEXT(1));
+ if ( term==NULL && UserDefdTokens ) {
+ err("implicit token definition not allowed with #tokdefs");
+ $$.left = $$.right = NULL;
+ }
+ else {
+ $$ = buildToken(LATEXT(1));
+ p=((TokNode *)((Junction *)$$.left)->p1);
+ term = (TermEntry *) hash_get(Tname, LATEXT(1));
+ require( term!= NULL, "hash table mechanism is broken");
+ p->tclass = term->tclass;
+ p->complement = $old_not;
+ if ( label!=NULL ) {
+ p->el_label = label->str;
+ label->elem = (Node *)p;
+ }
+ }
+ >>
+ { ".."
+ ( QuotedTerm
+ <<if ( p!=NULL ) setUpperRange(p, LATEXT(1));>>
+ | TokenTerm
+ <<if ( p!=NULL ) setUpperRange(p, LATEXT(1));>>
+ )
+ }
+ <<
+ if ( p!=NULL && (p->upper_range!=0 || p->tclass || $old_not) )
+ list_add(&MetaTokenNodes, (void *)p);
+ >>
+ ( "^" <<if ( p!=NULL ) p->astnode=ASTroot;>>
+ | <<if ( p!=NULL ) p->astnode=ASTchild;>>
+ | "!" <<if ( p!=NULL ) p->astnode=ASTexclude;>>
+ )
+ { "\@" <<local_use_def_MT_handler = 1;>> }
+ <<
+ if ( p!=NULL && $first_on_line ) {
+ CurAltStart = (Junction *)$$.left;
+ altAdd(CurAltStart); /* MR7 */
+ p->altstart = CurAltStart;
+ }
+ if ( p!=NULL )
+ p->use_def_MT_handler = $use_def_MT_handler || local_use_def_MT_handler;
+ $node = (Node *)p;
+ >>
+ | QuotedTerm
+ <<
+ term = (TermEntry *) hash_get(Texpr, LATEXT(1));
+ if ( term==NULL && UserDefdTokens ) {
+ err("implicit token definition not allowed with #tokdefs");
+ $$.left = $$.right = NULL;
+ }
+ else {
+ $$ = buildToken(LATEXT(1)); p=((TokNode *)((Junction *)$$.left)->p1);
+ p->complement = $old_not;
+ if ( label!=NULL ) {
+ p->el_label = label->str;
+ label->elem = (Node *)p;
+ }
+ }
+ >>
+ { ".."
+ ( QuotedTerm
+ <<if ( p!=NULL ) setUpperRange(p, LATEXT(1));>>
+ | TokenTerm
+ <<if ( p!=NULL ) setUpperRange(p, LATEXT(1));>>
+ )
+ }
+ ( "^" <<if ( p!=NULL ) p->astnode=ASTroot;>>
+ | <<if ( p!=NULL ) p->astnode=ASTchild;>>
+ | "!" <<if ( p!=NULL ) p->astnode=ASTexclude;>>
+ )
+ { "\@" <<local_use_def_MT_handler = 1;>> }
+ <<
+ if ( p!=NULL && (p->upper_range!=0 || p->tclass || $old_not) )
+ list_add(&MetaTokenNodes, (void *)p);
+ >>
+ <<
+ if ( $first_on_line ) {
+ CurAltStart = (Junction *)$$.left;
+ altAdd(CurAltStart); /* MR7 */
+ p->altstart = CurAltStart;
+ }
+ if ( p!=NULL )
+ p->use_def_MT_handler = $use_def_MT_handler || local_use_def_MT_handler;
+ $node = (Node *)p;
+ >>
+
+ | <<if ( $old_not ) warn("~ WILDCARD is an undefined operation (implies 'nothing')");>>
+ "."
+ <<$$ = buildWildCard(LATEXT(1)); p=((TokNode *)((Junction *)$$.left)->p1);>>
+ ( "^" <<p->astnode=ASTroot;>>
+ | <<p->astnode=ASTchild;>>
+ | "!" <<p->astnode=ASTexclude;>>
+ )
+ <<list_add(&MetaTokenNodes, (void *)p);>>
+ <<
+ if ( $first_on_line ) {
+ CurAltStart = (Junction *)$$.left;
+ altAdd(CurAltStart); /* MR7 */
+ p->altstart = CurAltStart;
+ if ( label!=NULL ) {
+ p->el_label = label->str;
+ label->elem = (Node *)p;
+ }
+ }
+ $node = (Node *)p;
+ >>
+
+ | <<if ( $old_not ) warn("~ NONTERMINAL is an undefined operation");>>
+ NonTerminal
+ <<$$ = buildRuleRef(LATEXT(1));>>
+ { "!" <<q = (RuleRefNode *) ((Junction *)$$.left)->p1;
+ q->astnode=ASTexclude;>>
+ }
+ { {"\<"}
+ PassAction <<addParm(((Junction *)$$.left)->p1, LATEXT(1));>>
+ }
+ <<rr=(RuleRefNode *) ((Junction *)$$.left)->p1;>>
+ { <<char *a;>>
+ "\>"
+ PassAction
+ <<
+ a = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char));
+ require(a!=NULL, "rule element: cannot allocate assignment");
+ strcpy(a, LATEXT(1));
+ rr->assign = a;
+ >>
+ }
+ <<
+ if ( label!=NULL ) {
+ rr->el_label = label->str;
+ label->elem = (Node *)rr;
+ }
+ if ( $first_on_line ) {
+ CurAltStart = (Junction *)$$.left;
+ altAdd(CurAltStart); /* MR7 */
+ ((RuleRefNode *)((Junction *)$$.left)->p1)->altstart = CurAltStart;
+ }
+ $node = (Node *)rr;
+ >>
+ )
+
+ | <<if ( $old_not ) warn("~ ACTION is an undefined operation");>>
+ Action <<$0 = buildAction(LATEXT(1),action_file,action_line, 0);>>
+ <<if ( $first_on_line ) { /* MR7 */
+ CurAltStart = (Junction *)$0.left; /* MR7 */
+ altAdd(CurAltStart); /* MR7 */
+ };>> /* MR7 */
+ <<$node = (Node *) ((Junction *)$0.left)->p1;>>
+
+ | <<if ( $old_not ) warn("~ SEMANTIC-PREDICATE is an undefined operation");>>
+ Pred <<$0 = buildAction(LATEXT(1),action_file,action_line, 1);>>
+ <<act = (ActionNode *) ((Junction *)$0.left)->p1;>>
+ <<if (numericActionLabel) { /* MR10 */
+ list_add(&NumericPredLabels,act); /* MR10 */
+ numericActionLabel=0; /* MR10 */
+ }; /* MR10 */
+ >>
+ { <<char *a;>>
+ PassAction
+ <<
+ a = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char));
+ require(a!=NULL, "rule element: cannot allocate predicate fail action");
+ strcpy(a, LATEXT(1));
+ act->pred_fail = a;
+ >>
+ }
+ <<if ( $first_on_line ) { /* MR7 */
+ CurAltStart = (Junction *)$0.left; /* MR7 */
+ altAdd(CurAltStart); /* MR7 */
+ };>> /* MR7 */
+ <<$node = (Node *)act;>>
+
+ | <<if ( $old_not ) warn("~ BLOCK is an undefined operation");>>
+ <<BlkLevel++;
+ if (BlkLevel >= MAX_BLK_LEVEL) fatal("Blocks nested too deeply");
+/* MR23 */ CurBlockID_array[BlkLevel] = CurBlockID;
+/* MR23 */ CurAltNum_array[BlkLevel] = CurAltNum;
+ >>
+ { Pragma
+ ( "approx" <<approx=LL_k;>>
+ | "LL\(1\)" <<approx = 1;>> /* MR20 */
+ | "LL\(2\)" <<approx = 2;>> /* MR20 */
+ )
+ }
+
+/* MR21 */ { FirstSetSymbol
+/* MR21 */ "\("
+/* MR21 */ ( NonTerminal
+/* MR21 */ <<
+/* MR21 */ pFirstSetSymbol = (char *) calloc(strlen(LATEXT(1))+1,
+/* MR21 */ sizeof(char));
+/* MR21 */ require(pFirstSetSymbol!=NULL,
+/* MR21 */ "cannot allocate first set name");
+/* MR21 */ strcpy(pFirstSetSymbol, LATEXT(1));
+/* MR21 */ >>
+/* MR21 */ | TokenTerm
+/* MR21 */ <<
+/* MR21 */ pFirstSetSymbol = (char *) calloc(strlen(LATEXT(1))+1,
+/* MR21 */ sizeof(char));
+/* MR21 */ require(pFirstSetSymbol!=NULL,
+/* MR21 */ "cannot allocate first set name");
+/* MR21 */ strcpy(pFirstSetSymbol, LATEXT(1));
+/* MR21 */ >>
+/* MR21 */ )
+/* MR21 */ "\)"
+/* MR21 */ }
+
+ (
+
+ "\(" block[&toksrefd,&rulesrefd] "\)"
+ <<blk = $$ = $2;
+ /* MR23 */ CurBlockID_array[BlkLevel] = (-1);
+ /* MR23 */ CurAltNum_array[BlkLevel] = (-1);
+ --BlkLevel;
+ >>
+
+ ( "\*" <<$$ = makeLoop($$,approx,pFirstSetSymbol);>>
+ | "\+" <<$$ = makePlus($$,approx,pFirstSetSymbol);>>
+ | "?"
+ (
+ ( "=>" <<ampersandStyle=0;>>
+ | "&&" <<ampersandStyle=1;>> /* MR10 (g)? && <<p>>? */
+ )
+ Pred /* generalized predicate */
+ /* first make into a predicate */
+ <<$$ = buildAction(LATEXT(1),action_file,action_line,1);>>
+ <<act = (ActionNode *) ((Junction *)$$.left)->p1;>>
+ <<semDepth=predicateLookaheadDepth(act);>> /* MR10 */
+ <<if (numericActionLabel) { /* MR10 */
+ list_add(&NumericPredLabels,act); /* MR10 */
+ numericActionLabel=0; /* MR10 */
+ }; /* MR10 */
+ >>
+ { <<char *a;>>
+ PassAction
+ <<
+ a = (char *)calloc(strlen(LATEXT(1))+1, sizeof(char));
+ require(a!=NULL, "rule element: cannot allocate predicate fail action");
+ strcpy(a, LATEXT(1));
+ act->pred_fail = a;
+ >>
+ }
+ <<if ($first_on_line) { /* MR7 */
+ CurAltStart=(Junction *)$$.left; /* MR7 */
+ altAdd(CurAltStart); /* MR7 */
+ };>>
+ <<$node = (Node *)act;>>
+
+ /* for now, just snag context */
+ <<
+ pred = computePredFromContextGuard(blk,&predMsgDone); /* MR10 */
+ if ( pred==NULL) { /* MR10 */
+ if ( !predMsgDone) err("invalid or missing context guard"); /* MR10 */
+ predMsgDone=1; /* MR10 */
+ } else { /* MR10 */
+ act->guardNodes=(Junction *)blk.left; /* MR11 */
+ pred->expr = act->action;
+ pred->source = act;
+/* MR10 */ pred->ampersandStyle = ampersandStyle; /* 0 means (g)? => ... 1 means (g)? && ... */
+/* MR13 */ if (pred->tcontext != NULL) {
+/* MR13 */ height=MR_max_height_of_tree(pred->tcontext);
+/* MR13 */ equal_height=MR_all_leaves_same_height(pred->tcontext,height);
+/* MR13 */ if (! equal_height) {
+/* MR13 */ errFL("in guarded predicates all tokens in the guard must be at the same height",
+/* MR13 */ FileStr[act->file],act->line);
+/* MR13 */ };
+/* MR13 */ }
+/* MR10 */ if (ampersandStyle) {
+/* MR10 */ act->ampersandPred = pred;
+/* MR11 */ if (! HoistPredicateContext) {
+/* MR11 */ errFL("without \"-prc on\" (guard)? && <<pred>>? ... doesn't make sense",
+/* MR11 */ FileStr[act->file],act->line);
+/* MR11 */ };
+/* MR10 */ } else {
+/* MR10 */ act->guardpred = pred;
+/* MR10 */ };
+/* MR10 */ if (pred->k != semDepth) {
+/* MR10 */ warn(eMsgd2("length of guard (%d) does not match the length of semantic predicate (%d)",
+/* MR10 */ pred->k,semDepth));
+/* MR10 */ };
+ }
+ >>
+ | <<$$ = makeBlk($$,approx,pFirstSetSymbol);
+ FoundGuessBlk = 1;
+ ((Junction *) ((Junction *)$$.left)->p1)->guess=1;
+ if ( !$first_on_line ) {
+ err("(...)? predicate must be first element of production");
+ }
+ >>
+ )
+ | <<$$ = makeBlk($$,approx,pFirstSetSymbol);>>
+ )
+ <<
+ if ( pred==NULL && !predMsgDone) { /* MR10 */
+ ((Junction *)((Junction *)$$.left)->p1)->blockid = CurBlockID;
+ ((Junction *)((Junction *)$$.left)->p1)->tokrefs = toksrefd;
+ ((Junction *)((Junction *)$$.left)->p1)->rulerefs = rulesrefd;
+ if ( $first_on_line ) { /* MR7 */
+ CurAltStart = (Junction *)((Junction *)((Junction *)$$.left)->p1); /* MR7 */
+ altAdd(CurAltStart); /* MR7 */
+ }; /* MR7 */
+ $node = (Node *) ((Junction *)$$.left)->p1;
+ }
+ >>
+
+ | "\{" block[&toksrefd,&rulesrefd]
+ <<$$ = makeOpt($2,approx,pFirstSetSymbol);
+ /* MR23 */ CurBlockID_array[BlkLevel] = (-1);
+ /* MR23 */ CurAltNum_array[BlkLevel] = (-1);
+ --BlkLevel;
+ >>
+ "\}"
+ <<
+ ((Junction *)((Junction *)$$.left)->p1)->blockid = CurBlockID;
+ ((Junction *)((Junction *)$$.left)->p1)->tokrefs = toksrefd;
+ ((Junction *)((Junction *)$$.left)->p1)->rulerefs = rulesrefd;
+ >>
+ <<if ( $first_on_line ) { /* MR7 */
+ CurAltStart = (Junction *) ((Junction *)((Junction *)$$.left)->p1); /* MR7 */
+ altAdd(CurAltStart); /* MR7 */
+ };
+ >>
+ <<$node = (Node *) ((Junction *)$$.left)->p1;>>
+
+ )
+
+/* Error catching alternatives */
+ | "\*" <<warn("don't you want a ')' with that '*'?"); CannotContinue=TRUE;>>
+ | "\+" <<warn("don't you want a ')' with that '+'?"); CannotContinue=TRUE;>>
+ | "\>" <<warn("'>' can only appear after a nonterminal"); CannotContinue=TRUE;>>
+ | PassAction <<warn("[...] out of context 'rule > [...]'");
+ CannotContinue=TRUE;>>
+ ;
+ <<CannotContinue=TRUE;>>
+
+/* rule default_exception_handler */
+
+default_exception_handler
+ : exception_group > [DefaultExGroup]
+ ;
+
+/* rule exception_group */
+
+exception_group > [ExceptionGroup *eg]
+ : <<ExceptionHandler *h; LabelEntry *label=NULL; /* MR6 */
+ FoundException = 1; FoundExceptionGroup = 1;>> /* MR6 */
+
+ "exception" <<$eg = (ExceptionGroup *)calloc(1, sizeof(ExceptionGroup));>>
+ { <<char *p;>>
+ PassAction /* did they attach a label? */
+ <<
+ p = LATEXT(1)+1;
+ p[strlen(p)-1] = '\0'; /* kill trailing space */
+ label = (LabelEntry *) hash_get(Elabel, LATEXT(1)+1);
+ if ( label==NULL )
+ {
+ err(eMsg1("unknown label in exception handler: '%s'", LATEXT(1)+1));
+ }
+ >>
+ }
+ ( exception_handler > [h]
+ <<list_add(&($eg->handlers), (void *)h);>>
+ )*
+ { "default" ":" Action
+ <<{
+ ExceptionHandler *eh = (ExceptionHandler *)
+ calloc(1, sizeof(ExceptionHandler));
+ char *a = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char));
+ require(eh!=NULL, "exception: cannot allocate handler");
+ require(a!=NULL, "exception: cannot allocate action");
+ strcpy(a, LATEXT(1));
+ eh->action = a;
+ eh->signalname = (char *) calloc(strlen("default")+1, sizeof(char));
+ require(eh->signalname!=NULL, "exception: cannot allocate sig name");
+ strcpy(eh->signalname, "default");
+ list_add(&($eg->handlers), (void *)eh);
+ }>>
+ }
+
+ <<
+ if ( label!=NULL ) {
+ /* Record ex group in sym tab for this label */
+ if ( label->ex_group!=NULL ) {
+ err(eMsg1("duplicate exception handler for label '%s'",label->str));
+ } else {
+ label->ex_group = $eg;
+ /* Label the exception group itself */
+ $eg->label = label->str;
+ /* Make the labelled element pt to the exception also */
+/* MR6 */ if (label->elem == NULL) {
+/* MR6 */ err(eMsg1("reference in exception handler to undefined label '%s'",label->str));
+/* MR6 */ } else {
+ switch ( label->elem->ntype ) {
+ case nRuleRef :
+ {
+ RuleRefNode *r = (RuleRefNode *)label->elem;
+ r->ex_group = $eg;
+ break;
+ }
+ case nToken :
+ {
+ TokNode *t = (TokNode *)label->elem;
+ t->ex_group = $eg;
+ break;
+ }
+ } /* end switch */
+/* MR6 */ }; /* end test on label->elem */
+ } /* end test on label->ex_group */
+
+ } /* end test on exception label */
+
+/* MR7 */
+/* MR7 */ if (BlkLevel == 1 && label == NULL) {
+/* MR7 */ $eg->forRule=1;
+/* MR7 */ } else if (label == NULL) {
+/* MR7 */ $eg->altID = makeAltID(CurBlockID_array[BlkLevel], CurAltNum_array[BlkLevel]);
+/* MR7 */ egAdd($eg);
+/* MR7 */ } else {
+/* MR7 */ $eg->labelEntry=label;
+/* MR7 */ };
+/* MR7 */
+/* MR7 */ /* You may want to remove this exc from the rule list */
+/* MR7 */ /* and handle at the labeled element site. */
+/* MR7 */
+/* MR7 */ if (label != NULL) {
+/* MR7 */ $eg = NULL;
+/* MR7 */ };
+
+ >>
+ ;
+ <<CannotContinue=TRUE;>>
+
+/* rule exception_handler */
+
+exception_handler > [ExceptionHandler *eh]
+ : <<;>> /* MR9 Removed unreferenced variable "a" */
+ "catch"
+ <<
+ $eh = (ExceptionHandler *)calloc(1, sizeof(ExceptionHandler));
+ require($eh!=NULL, "exception: cannot allocate handler");
+ >>
+ ( NonTerminal
+ <<
+ $eh->signalname = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char));
+ require($eh->signalname!=NULL, "exception: cannot allocate sig name");
+ strcpy($eh->signalname, LATEXT(1));
+ >>
+ | TokenTerm
+ <<
+ $eh->signalname = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char));
+ require($eh->signalname!=NULL, "exception: cannot allocate sig name");
+ strcpy($eh->signalname, LATEXT(1));
+ >>
+ )
+ ":"
+ { <<$eh->action = NULL;>>
+ Action
+ <<
+ $eh->action = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char));
+ require($eh->action!=NULL, "exception: cannot allocate action");
+ strcpy($eh->action, LATEXT(1));
+ >>
+ }
+ ;
+ <<CannotContinue=TRUE;>>
+
+#token NonTerminal "[a-z] [A-Za-z0-9_]*"
+ <<
+ while ( zzchar==' ' || zzchar=='\t' ) {
+ zzadvance();
+ }
+ if ( zzchar == ':' && inAlt ) NLA = LABEL;
+ >>
+#token TokenTerm "[A-Z] [A-Za-z0-9_]*"
+ <<
+ while ( zzchar==' ' || zzchar=='\t' ) {
+ zzadvance();
+ }
+ if ( zzchar == ':' && inAlt ) NLA = LABEL;
+ >>
+#token "{\\}#[A-Za-z0-9_]*" <<warn(eMsg1("unknown meta-op: %s",LATEXT(1))); zzskip(); >>
+
+#lexclass PARSE_ENUM_FILE
+
+#token "[\t\ ]+" << zzskip(); >> /* Ignore White */
+#token "\n|\r|\r\n" << zzline++; zzskip(); >> /* Track Line # */
+#token "//" << zzmode(TOK_DEF_CPP_COMMENTS); zzmore(); >>
+#token "/\*" << zzmode(TOK_DEF_COMMENTS); zzskip(); >>
+#token "#ifdef" << zzmode(TOK_DEF_CPP_COMMENTS); zzskip(); >>
+#token "#if" << zzmode(TOK_DEF_CPP_COMMENTS); zzskip(); >>
+#token "#ifndef" << ; >>
+#token "#else" << zzmode(TOK_DEF_CPP_COMMENTS); zzskip(); >>
+#token "#endif" << zzmode(TOK_DEF_CPP_COMMENTS); zzskip(); >>
+#token "#undef" << zzmode(TOK_DEF_CPP_COMMENTS); zzskip(); >>
+#token "#import" << zzmode(TOK_DEF_CPP_COMMENTS); zzskip(); >>
+#token "@" << ; >>
+
+/* rule enum_file */
+
+enum_file[char *fname]
+ : { "#ifndef" ID
+ { "#define" ID /* ignore if it smells like a gate */
+ /* First #define after the first #ifndef (if any) is ignored */
+ }
+ }
+ ( ( enum_def[$fname] )+
+ | defines[$fname]
+ )
+ |
+ ;
+
+/* rule defines */
+
+defines[char *fname]
+ : <<int v; int maxt=(-1); char *t;>> /* MR3 */
+ (
+ "#define" ID
+ <<t = mystrdup(LATEXT(1));>>
+ INT
+ <<
+ v = atoi(LATEXT(1));
+/* fprintf(stderr, "#token %s=%d\n", t, v);*/
+
+ /* MR2 Andreas Magnusson (Andreas.Magnusson@mailbox.swipnet.se) */
+ /* MR2 Fix to bug introduced by 1.33MR1 for #tokdefs */
+ /* MR2 Don't let #tokdefs be confused by */
+ /* MR2 DLGminToken and DLGmaxToken */
+
+ if ( ! isDLGmaxToken(t)) { /* MR2 */
+ TokenNum = v;
+ if ( v>maxt ) maxt=v;
+ if ( Tnum( t ) == 0 ) {
+ addForcedTname( t, v );
+ } else {
+ warnFL(eMsg1("redefinition of token %s; ignored",t),$fname,zzline);
+ };
+ };
+ >>
+ )+
+ <<TokenNum = maxt + 1;>>
+ ;
+
+/* rule enum_def */
+
+enum_def[char *fname]
+ : <<int v= 0; int maxt=(-1); char *t;>> /* MR3 */
+ "enum" ID
+ "\{"
+ ID
+ <<t = mystrdup(LATEXT(1));>>
+ ( "=" INT <<v=atoi(LATEXT(1));>>
+ | <<v++;>>
+ )
+ <<
+/* fprintf(stderr, "#token %s=%d\n", t, v);*/
+ TokenNum = v;
+ if ( v>maxt ) maxt=v; /* MR3 */
+ if ( Tnum( t ) == 0 ) addForcedTname( t, v );
+ else {
+ warnFL(eMsg1("redefinition of token %s; ignored",t),$fname,zzline);
+ }
+ >>
+ ( ","
+
+ /* MR2 Andreas Magnusson (Andreas.Magnusson@mailbox.swipnet.se) */
+ /* MR2 Fix to bug introduced by 1.33MR1 for #tokdefs */
+ /* MR2 Don't let #tokdefs be confused by */
+ /* MR2 DLGminToken and DLGmaxToken */
+
+ {
+ <<isDLGmaxToken(LATEXT(1))>>? ID { "=" INT } /* MR2 */
+ | ID /* MR2 */
+ <<t = mystrdup(LATEXT(1));>>
+ ( "=" INT <<v=atoi(LATEXT(1));>>
+ | <<v++;>>
+ )
+ <<
+/* fprintf(stderr, "#token %s=%d\n", t, v);*/
+ TokenNum = v;
+ if ( v>maxt ) maxt=v; /* MR3 */
+ if ( Tnum( t ) == 0 ) addForcedTname( t, v );
+ else {
+ warnFL(eMsg1("redefinition of token %s; ignored",t),$fname,zzline);
+ }
+ >>
+ }
+ )*
+ "\}"
+ ";"
+ <<TokenNum = maxt + 1;>> /* MR3 */
+ ;
+
+#token INT "[0-9]+"
+#token ID "[a-zA-Z_][_a-zA-Z0-9]*"
+
+#lexclass START
+
+/* MR14 Arpad Beszedes 26-May-98
+ Add support for #line directives when antlr source is pre-processed
+*/
+
+#lexaction
+<<
+
+static char *
+#ifdef __USE_PROTOS
+getFileNameFromTheLineInfo(char *toStr, char *fromStr)
+#else
+getFileNameFromTheLineInfo(toStr, fromStr)
+char *toStr, *fromStr;
+#endif
+{
+ int i, j, k;
+
+ if (!fromStr || !toStr) return toStr;
+
+ /* find the first " */
+
+ for (i=0;
+ (i<MaxFileName) &&
+ (fromStr[i] != '\n') &&
+ (fromStr[i] != '\r') &&
+ (fromStr[i] != '\"');
+ i++) /* nothing */ ;
+
+ if ( (i == MaxFileName) ||
+ (fromStr[i] == '\n') ||
+ (fromStr[i] == '\r') ) {
+ return toStr;
+ }
+
+ /* find the second " */
+
+ for (j=i+1;
+ (j<MaxFileName) &&
+ (fromStr[j] != '\n') &&
+ (fromStr[j] != '\r') &&
+ (fromStr[j] != '\"');
+ j++) /* nothing */ ;
+
+ if ((j == MaxFileName) ||
+ (fromStr[j] == '\n') ||
+ (fromStr[j] == '\r') ) {
+ return toStr;
+ }
+
+ /* go back until the last / or \ */
+
+ for (k=j-1;
+ (fromStr[k] != '\"') &&
+ (fromStr[k] != '/') &&
+ (fromStr[k] != '\\');
+ k--) /* nothing */ ;
+
+ /* copy the string after " / or \ into toStr */
+
+ for (i=k+1; fromStr[i] != '\"'; i++) {
+ toStr[i-k-1] = fromStr[i];
+ }
+
+ toStr[i-k-1] = '\0';
+
+ return toStr;
+}
+
+/* MR14 end of a block to support #line in antlr source code */
+
+>>
+
+<<
+
+/* MR2 Andreas Magnusson (Andreas.Magnusson@mailbox.swipnet.se) */
+/* MR2 Fix to bug introduced by 1.33MR1 for #tokdefs */
+/* MR2 Don't let #tokdefs be confused by */
+/* MR2 DLGminToken and DLGmaxToken */
+
+/* semantic check on DLGminToken and DLGmaxmaxToken in #tokdefs */
+
+#ifdef __USE_PROTOS
+static int isDLGmaxToken(char *Token)
+#else
+static int isDLGmaxToken(Token)
+ char * Token;
+#endif
+{
+ static char checkStr1[] = "DLGmaxToken";
+ static char checkStr2[] = "DLGminToken";
+
+ if (strcmp(Token, checkStr1) == 0)
+ return 1;
+ else if (strcmp(Token, checkStr2) == 0)
+ return 1;
+ else
+ return 0;
+}
+
+/* semantics of #token */
+static void
+#ifdef __USE_PROTOS
+chkToken(char *t, char *e, char *a, int tnum)
+#else
+chkToken(t,e,a,tnum)
+char *t, *e, *a;
+int tnum;
+#endif
+{
+ TermEntry *p;
+
+ /* check to see that they don't try to redefine a token as a token class */
+ if ( t!=NULL ) {
+ p = (TermEntry *) hash_get(Tname, t);
+ if ( p!=NULL && p->classname ) {
+ err(eMsg1("redefinition of #tokclass '%s' to #token not allowed; ignored",t));
+ if ( a!=NULL ) free((char *)a);
+ return;
+ }
+ }
+
+ if ( t==NULL && e==NULL ) { /* none found */
+ err("#token requires at least token name or rexpr");
+ }
+ else if ( t!=NULL && e!=NULL ) { /* both found */
+ if ( UserDefdTokens ) { /* if #tokdefs, must not define new */
+ p = (TermEntry *) hash_get(Tname, t);
+ if ( p == NULL) {
+err(eMsg1("new token definition '%s' not allowed - only #token with name already defined by #tokdefs file allowed",t));
+ return;
+ };
+ }
+ Tklink(t, e);
+ if ( a!=NULL ) {
+ if ( hasAction(e) ) {
+ err(eMsg1("redefinition of action for %s; ignored",e));
+ }
+ else setHasAction(e, a);
+ }
+ }
+ else if ( t!=NULL ) { /* only one found */
+ if ( UserDefdTokens ) {
+ p = (TermEntry *) hash_get(Tname, t);
+ if (p == NULL) {
+err(eMsg1("new token definition '%s' not allowed - only #token with name already defined by #tokdefs file allowed",t));
+ };
+ return;
+ }
+ if ( Tnum( t ) == 0 ) addTname( t );
+ else {
+ err(eMsg1("redefinition of token %s; ignored",t));
+ }
+ if ( a!=NULL ) {
+ err(eMsg1("action cannot be attached to a token name (%s); ignored",t));
+ free((char *)a);
+ }
+ }
+ else if ( e!=NULL ) {
+ if ( Tnum( e ) == 0 ) addTexpr( e );
+ else {
+ if ( hasAction(e) ) {
+ err(eMsg1("redefinition of action for expr %s; ignored",e));
+ }
+ else if ( a==NULL ) {
+ err(eMsg1("redefinition of expr %s; ignored",e));
+ }
+ }
+ if ( a!=NULL ) setHasAction(e, a);
+ }
+
+ /* if a token type number was specified, then add the token ID and 'tnum'
+ * pair to the ForcedTokens list. (only applies if an id was given)
+ */
+ if ( t!=NULL && tnum>0 )
+ {
+ if ( set_el(tnum, reserved_positions) )
+ {
+ err(eMsgd("a token has already been forced to token number %d; ignored", tnum));
+ }
+ else
+ {
+ list_add(&ForcedTokens, newForcedToken(t,tnum));
+ set_orel(tnum, &reserved_positions);
+ }
+ }
+}
+>>
+
+<<
+static int
+#ifdef __USE_PROTOS
+match_token(char *s, char **nxt)
+#else
+match_token(s,nxt)
+char *s;
+char **nxt;
+#endif
+{
+ if ( !(*s>='A' && *s<='Z') ) return 0;
+ s++;
+ while ( (*s>='a' && *s<='z') ||
+ (*s>='A' && *s<='Z') ||
+ (*s>='0' && *s<='9') ||
+ *s=='_' )
+ {
+ s++;
+ }
+ if ( *s!=' ' && *s!='}' ) return 0;
+ *nxt = s;
+ return 1;
+}
+
+static int
+#ifdef __USE_PROTOS
+match_rexpr(char *s, char **nxt)
+#else
+match_rexpr(s,nxt)
+char *s;
+char **nxt;
+#endif
+{
+ if ( *s!='"' ) return 0;
+ s++;
+ while ( *s!='"' )
+ {
+ if ( *s=='\n' || *s=='\r' ) /* MR13 */
+ warn("eoln found in regular expression");
+ if ( *s=='\\' ) s++;
+ s++;
+ }
+ *nxt = s+1;
+ return 1;
+}
+
+/*
+ * Walk a string "{ A .. Z }" where A..Z is a space separated list
+ * of token references (either labels or reg exprs). Return a
+ * string "inlineX_set" for some unique integer X. Basically,
+ * we pretend as if we had seen "#tokclass inlineX { A .. Z }"
+ * on the input stream outside of an action.
+ */
+char *
+#ifdef __USE_PROTOS
+inline_set(char *s)
+#else
+inline_set(s)
+char *s;
+#endif
+{
+ char *nxt;
+ fprintf(stderr, "found consumeUntil( {...} )\n");
+ while ( *s==' ' || *s=='\t' || *s=='\n' || *s=='\r' ) {s++;}
+ if ( *s!='{' )
+ {
+ err("malformed consumeUntil( {...} ); missing '{'");
+ return "bad_set";
+ }
+ s++;
+ while ( *s==' ' || *s=='\t' || *s=='\n' || *s=='\r' ) {s++;}
+ while ( *s!='}' )
+ {
+ if ( match_token(s,&nxt) ) fprintf(stderr, "found token %s\n", s);
+ else if ( match_rexpr(s,&nxt) ) fprintf(stderr, "found rexpr %s\n", s);
+ else {
+ err("invalid element in consumeUntil( {...} )");
+ return "bad_set";
+ }
+ s = nxt;
+ while ( *s==' ' || *s=='\t' || *s=='\n' || *s=='\r' ) {s++;}
+ }
+ return "inlineX_set";
+}
+>>
+
+<<
+/* ANTLR-specific syntax error message generator
+ * (define USER_ZZSYN when compiling so don't get 2 definitions)
+ */
+void
+#ifdef __USE_PROTOS
+zzsyn(char *text, int tok, char *egroup, SetWordType *eset, int etok,
+int k, char *bad_text)
+#else
+zzsyn(text, tok, egroup, eset, etok, k, bad_text)
+char *text, *egroup, *bad_text;
+int tok;
+int etok;
+int k;
+SetWordType *eset;
+#endif
+{
+ fprintf(stderr, ErrHdr, FileStr[CurFile]!=NULL?FileStr[CurFile]:"stdin", zzline);
+ fprintf(stderr, " syntax error at \"%s\"", (tok==zzEOF_TOKEN)?"EOF":text);
+ if ( !etok && !eset ) {fprintf(stderr, "\n"); return;}
+ if ( k==1 ) fprintf(stderr, " missing");
+ else
+ {
+ fprintf(stderr, "; \"%s\" not", bad_text);
+ if ( zzset_deg(eset)>1 ) fprintf(stderr, " in");
+ }
+ if ( zzset_deg(eset)>0 ) zzedecode(eset);
+ else fprintf(stderr, " %s", zztokens[etok]);
+ if ( strlen(egroup) > (size_t)0 ) fprintf(stderr, " in %s", egroup);
+ fprintf(stderr, "\n");
+}
+>>
+
+#lexaction <<
+#ifdef __USE_PROTOS
+void mark_label_used_in_sem_pred(LabelEntry *le) /* MR10 */
+#else
+void mark_label_used_in_sem_pred(le) /* MR10 */
+ LabelEntry *le;
+#endif
+{
+ TokNode *tn;
+ require (le->elem->ntype == nToken,"mark_label_used... ntype != nToken");
+ tn=(TokNode *)le->elem;
+ require (tn->label != 0,"mark_label_used... TokNode has no label");
+ tn->label_used_in_semantic_pred=1;
+}
+>>
diff --git a/Source/Pccts/antlr/antlr.r b/Source/Pccts/antlr/antlr.r
new file mode 100644
index 0000000..e3de387
--- /dev/null
+++ b/Source/Pccts/antlr/antlr.r
@@ -0,0 +1,787 @@
+/*
+ File: antlrMPW.r
+ Target: antlr 133MR
+ Created: Monday, June 15, 1998 4:41:11 AM
+ Author: Kenji Tanaka (kentar@osa.att.ne.jp)
+*/
+
+#include "cmdo.r"
+
+resource 'cmdo' (128, "Antlr") {
+ { /* array dialogs: 5 elements */
+ /* [1] */
+ 295,
+ "ANTLR -- Purdue Compiler Construction To"
+ "ol Set (PCCTS) LL(k) parser generator.",
+ { /* array itemArray: 12 elements */
+ /* [1] */
+ NotDependent {
+
+ },
+ CheckOption {
+ NotSet,
+ {18, 23, 33, 223},
+ "Read grammar from stdin",
+ "-",
+ "Read grammar from stdin."
+ },
+ /* [2] */
+ NotDependent {
+
+ },
+ CheckOption {
+ NotSet,
+ {38, 23, 53, 310},
+ "Send grammar.c/grammar.cpp to stdout",
+ "-stdout",
+ "Send grammar.c/grammar.cpp to stdout."
+ },
+ /* [3] */
+ NotDependent {
+
+ },
+ MultiFiles {
+ "Grammar File(s)É",
+ "Choose the grammar specification files y"
+ "ou wish to have ANTLR process.",
+ {79, 22, 98, 152},
+ "Grammar specification:",
+ "",
+ MultiInputFiles {
+ { /* array MultiTypesArray: 1 elements */
+ /* [1] */
+ text
+ },
+ ".g",
+ "Files ending in .g",
+ "All text files"
+ }
+ },
+ /* [4] */
+ NotDependent {
+
+ },
+ Files {
+ DirOnly,
+ OptionalFile {
+ {58, 168, 74, 298},
+ {79, 169, 98, 299},
+ "Output Directory",
+ ":",
+ "-o",
+ "",
+ "Choose the directory where ANTLR will pu"
+ "t its output.",
+ dim,
+ "Output DirectoryÉ",
+ "",
+ ""
+ },
+ NoMore {
+
+ }
+ },
+ /* [5] */
+ NotDependent {
+
+ },
+ Redirection {
+ StandardOutput,
+ {126, 27}
+ },
+ /* [6] */
+ NotDependent {
+
+ },
+ Redirection {
+ DiagnosticOutput,
+ {126, 178}
+ },
+ /* [7] */
+ NotDependent {
+
+ },
+ TextBox {
+ gray,
+ {117, 20, 167, 300},
+ "Redirection"
+ },
+ /* [8] */
+ NotDependent {
+
+ },
+ NestedDialog {
+ 5,
+ {20, 324, 40, 460},
+ "Parse OptionsÉ",
+ "Parse control options may be set with th"
+ "is button."
+ },
+ /* [9] */
+ NotDependent {
+
+ },
+ NestedDialog {
+ 2,
+ {50, 324, 70, 460},
+ "Generate OptionsÉ",
+ "Various command line options may be set "
+ "with this button."
+ },
+ /* [10] */
+ NotDependent {
+
+ },
+ NestedDialog {
+ 3,
+ {78, 324, 98, 460},
+ "More OptionsÉ",
+ "Antlr has ALOT of options. There are eve"
+ "n more to be found with this button."
+ },
+ /* [11] */
+ NotDependent {
+
+ },
+ NestedDialog {
+ 4,
+ {106, 324, 126, 460},
+ "Rename OptionsÉ",
+ "Options for renaming output files may be"
+ " set with this button."
+ },
+ /* [12] */
+ NotDependent {
+
+ },
+ VersionDialog {
+ VersionString {
+ "1.33MR"
+ },
+ "PCCTS was written by Terence Parr, Russe"
+ "ll Quong, Will Cohen, and Hank Dietz: 19"
+ "89-1998. MPW port by Scott Haney.",
+ noDialog
+ }
+ },
+ /* [2] */
+ 295,
+ "Use this dialog to specify command line "
+ "Generate Options.",
+ { /* array itemArray: 15 elements */
+ /* [1] */
+ NotDependent {
+
+ },
+ CheckOption {
+ NotSet,
+ {18, 25, 33, 225},
+ "Generate C++ code",
+ "-CC",
+ "Generate C++ output from both ANTLR and "
+ "DLG."
+ },
+ /* [2] */
+ NotDependent {
+
+ },
+ CheckOption {
+ NotSet,
+ {38, 25, 53, 225},
+ "Generate ASTs",
+ "-gt",
+ "Generate code for Abstract-Syntax-Trees "
+ "(ASTs)."
+ },
+ /* [3] */
+ NotDependent {
+
+ },
+ CheckOption {
+ NotSet,
+ {58, 25, 73, 225},
+ "Generate line info",
+ "-gl",
+ "If this option is checked, ANTLR will ge"
+ "nerate line info about grammaractions, t"
+ "hereby making debugging easier since com"
+ "pile errors will point to the grammar fi"
+ "le."
+ },
+ /* [4] */
+ NotDependent {
+
+ },
+ CheckOption {
+ NotSet,
+ {78, 25, 93, 225},
+ "Generate error classes",
+ "-ge",
+ "If this option is checked, ANTLR will ge"
+ "nerate an error class foreach non-termin"
+ "al."
+ },
+ /* [5] */
+ NotDependent {
+
+ },
+ CheckOption {
+ NotSet,
+ {98, 25, 113, 225},
+ "Don't generate Code",
+ "-gc",
+ "If this option is checked, ANTLR will ge"
+ "nerate no code, i.e. it will only perfor"
+ "m analysis on the grammar."
+ },
+ /* [6] */
+ NotDependent {
+
+ },
+ CheckOption {
+ NotSet,
+ {118, 25, 133, 225},
+ "Delay lookahead fetches",
+ "-gk",
+ "If this option is checked, ANTLR will ge"
+ "nerate a parser that delays lookahead fe"
+ "tches until needed."
+ },
+ /* [7] */
+ NotDependent {
+
+ },
+ CheckOption {
+ NotSet,
+ {138, 25, 153, 225},
+ "Use newAST(...)",
+ "-newAST",
+ "In C++ mode use \"newAST(...)\" rather tha"
+ "n \"new AST(...)\""
+ },
+ /* [8] */
+ NotDependent {
+
+ },
+ CheckOption {
+ NotSet,
+ {18, 235, 33, 435},
+ "Support parse traces",
+ "-gd",
+ "If this option is checked, ANTLR inserts"
+ " code in each parsing function to provid"
+ "e for user-defined handling of a detaile"
+ "d parse trace. The code consists of call"
+ "s to zzTRACEIN and zzTRACEOUT."
+ },
+ /* [9] */
+ NotDependent {
+
+ },
+ CheckOption {
+ NotSet,
+ {38, 235, 53, 435},
+ "Generate cross-references",
+ "-cr",
+ "If this option is checked, ANTLR will ge"
+ "nerate a cross reference for all rules. "
+ "For each rule it will print a list of al"
+ "l other rules that refrence it."
+ },
+ /* [10] */
+ NotDependent {
+
+ },
+ CheckOption {
+ NotSet,
+ {58, 235, 73, 435},
+ "Don't create Lexer files",
+ "-gx",
+ "If this option is checked, ANTLR will no"
+ "t generate DLG-related output files. Thi"
+ "s option should be used if one wants a c"
+ "ustom lexical analyzer or if one has mad"
+ "e changes to the grammar not affecting t"
+ "he lexical structure."
+ },
+ /* [11] */
+ NotDependent {
+
+ },
+ CheckOption {
+ NotSet,
+ {78, 235, 93, 460},
+ "Don't generate token expr sets",
+ "-gs",
+ "If this option is checked, ANTLR will no"
+ "t generate sets for token expression set"
+ "s; instead, it will generate a || separa"
+ "ted sequence of LA(1)==token #. "
+ },
+ /* [12] */
+ NotDependent {
+
+ },
+ CheckOption {
+ NotSet,
+ {98, 235, 113, 460},
+ "Generate ANSI-compatible",
+ "-ga",
+ "Generate ANSI-compatible code (default=F"
+ "ALSE)"
+ },
+ /* [13] */
+ NotDependent {
+
+ },
+ CheckOption {
+ NotSet,
+ {118, 235, 133, 460},
+ "Don't generate tokens.h",
+ "-gxt",
+ "Do not generate tokens.h (default=FALSE)"
+ },
+ /* [13] */
+ NotDependent {
+
+ },
+ CheckOption {
+ NotSet,
+ {138, 235, 153, 460},
+ "Provide \"(alpha)? beta\" info",
+ "-alpha",
+ "Provide additional information for \"(alpha)? beta\" error messages"
+ },
+ /* [14] */
+ NotDependent {
+
+ },
+ RegularEntry {
+ "Tabs(1 to 8):",
+ {162, 23, 177, 117},
+ {163, 125, 179, 196},
+ "",
+ keepCase,
+ "-tab",
+ "Width of tabs (1 to 8) for grammar.c/gra"
+ "mmar.cpp files."
+ },
+ /* [15] */
+ NotDependent {
+
+ },
+ RegularEntry {
+ "Function Prefix:",
+ {161, 236, 177, 342},
+ {162, 345, 177, 454},
+ "",
+ keepCase,
+ "-gp",
+ "Prefix all generated rule functions with"
+ " a string."
+ }
+ },
+ /* [3] */
+ 295,
+ "Use this dialog to specify still more co"
+ "mmand line options.",
+ { /* array itemArray: 12 elements */
+ /* [1] */
+ NotDependent {
+
+ },
+ RadioButtons {
+ { /* array radioArray: 3 elements */
+ /* [1] */
+ {38, 25, 53, 85}, "None", "", Set, "When this option is selected, ANTLR will"
+ " not print the grammar to stdout.",
+ /* [2] */
+ {38, 100, 53, 160}, "Yes", "-p", NotSet, "When this option is selected, ANTLR will"
+ " print the grammar, stripped of all acti"
+ "ons and comments, to stdout.",
+ /* [3] */
+ {38, 175, 53, 235}, "More", "-pa", NotSet, "When this option is selected, ANTLR will"
+ " print the grammar, stripped of all acti"
+ "ons and comments, to stdout. It will als"
+ "o annotate the output with the first set"
+ "s determined from grammar analysis."
+ }
+ },
+ /* [2] */
+ NotDependent {
+
+ },
+ TextBox {
+ gray,
+ {28, 15, 60, 250},
+ "Grammar Printing"
+ },
+ /* [3] */
+ NotDependent {
+
+ },
+ RadioButtons {
+ { /* array radioArray: 3 elements */
+ /* [1] */
+ {88, 25, 103, 85}, "Low", "", Set, "When this option is selected, ANTLR will"
+ " show ambiguities/errors in low detail.",
+ /* [2] */
+ {88, 100, 103, 160}, "Medium", "-e2", NotSet, "When this option is selected, ANTLR will"
+ " show ambiguities/errors in more detail.",
+ /* [3] */
+ {88, 175, 103, 235}, "High", "-e3", NotSet, "When this option is selected, ANTLR will"
+ " show ambiguities/errors in excruciating"
+ " detail."
+ }
+ },
+ /* [4] */
+ NotDependent {
+
+ },
+ TextBox {
+ gray,
+ {78, 15, 110, 250},
+ "Error reporting"
+ },
+ /* [5] */
+ NotDependent {
+
+ },
+ CheckOption {
+ NotSet,
+ {130, 22, 145, 222},
+ "More warnings",
+ "-w2",
+ "If this option is checked, ANTLR will wa"
+ "rn if semantic predicates and/or (É)? bl"
+ "ocks are assumed to cover ambiguous alte"
+ "rnatives."
+ },
+ /* [6] */
+ NotDependent {
+
+ },
+ RegularEntry {
+ "Report when tnode usage exceeds:",
+ {162, 23, 180, 253},
+ {162, 255, 178, 326},
+ "",
+ keepCase,
+ "-treport",
+ "Report when tnode usage exceeds value du"
+ "ring ambiguity resolution."
+ },
+ /* [7] */
+ NotDependent {
+
+ },
+ CheckOption {
+ NotSet,
+ {40, 292, 55, 431},
+ "Predicate",
+ "-info p",
+ "With the antlr \"-info p\" switch the user"
+ " will receive information about the pred"
+ "icate suppression in the generated file."
+ },
+ /* [8] */
+ NotDependent {
+
+ },
+ CheckOption {
+ NotSet,
+ {60, 292, 75, 430},
+ "Tree Nodes",
+ "-info t",
+ "Using \"-info t\" gives information about "
+ "the total number of tnodes created and t"
+ "he peak number of tnodes."
+ },
+ /* [9] */
+ NotDependent {
+
+ },
+ CheckOption {
+ NotSet,
+ {80, 292, 95, 425},
+ "First/follow",
+ "-info f",
+ "first/follow set information."
+ },
+ /* [10] */
+ NotDependent {
+
+ },
+ CheckOption {
+ NotSet,
+ {100, 292, 115, 425},
+ "Monitor progress",
+ "-info m",
+ "prints name of each rule as it is starte"
+ "d and flushes output at start of each rule."
+ },
+ /* [11] */
+ NotDependent {
+
+ },
+ CheckOption {
+ NotSet,
+ {120, 292, 135, 416},
+ "Orphan rules",
+ "-info o",
+ "If there is more than one rule which is "
+ "not referenced by any other rule then al"
+ "l such rules are listed."
+ },
+ /* [12] */
+ NotDependent {
+
+ },
+ TextBox {
+ gray,
+ {28, 279, 147, 451},
+ "Extra info"
+ }
+ },
+ /* [4] */
+ 295,
+ "Use this dialog to specify command line "
+ "options relating to renaming output file"
+ "s.",
+ { /* array itemArray: 7 elements */
+ /* [1] */
+ NotDependent {
+
+ },
+ RegularEntry {
+ "Errors file name:",
+ {35, 25, 50, 205},
+ {35, 205, 51, 300},
+ "err.c",
+ keepCase,
+ "-fe",
+ "This entry specifies the name ANTLR uses"
+ " for the errors file."
+ },
+ /* [2] */
+ NotDependent {
+
+ },
+ RegularEntry {
+ "Lexical output name:",
+ {60, 25, 75, 205},
+ {60, 205, 76, 300},
+ "parser.dlg",
+ keepCase,
+ "-fl",
+ "This entry specifies the name ANTLR uses"
+ " for the lexical output file."
+ },
+ /* [3] */
+ NotDependent {
+
+ },
+ RegularEntry {
+ "Lexical modes name:",
+ {85, 25, 100, 205},
+ {85, 205, 101, 300},
+ "mode.h",
+ keepCase,
+ "-fm",
+ "This entry specifies the name ANTLR uses"
+ " for the lexical mode definitions file."
+ },
+ /* [4] */
+ NotDependent {
+
+ },
+ RegularEntry {
+ "Remap file name:",
+ {110, 25, 125, 205},
+ {110, 205, 126, 300},
+ "remap.h",
+ keepCase,
+ "-fr",
+ "This entry specifies the name ANTLR uses"
+ " for the file that remaps globally visib"
+ "le symbols."
+ },
+ /* [5] */
+ NotDependent {
+
+ },
+ RegularEntry {
+ "Tokens file name:",
+ {135, 25, 150, 205},
+ {135, 205, 151, 300},
+ "tokens.h",
+ keepCase,
+ "-ft",
+ "This entry specifies the name ANTLR uses"
+ " for the tokens file."
+ },
+ /* [6] */
+ NotDependent {
+
+ },
+ CheckOption {
+ NotSet,
+ {160, 25, 175, 175},
+ "Create std header",
+ "-gh",
+ "If this option is checked, ANTLR will cr"
+ "eate a standard header file named, by de"
+ "fault 'stdpccts.h'. This name can be alt"
+ "ered using the entry right next door."
+ },
+ /* [7] */
+ Or {
+ { /* array OrArray: 1 elements */
+ /* [1] */
+ 6
+ }
+ },
+ RegularEntry {
+ "Std header file name:",
+ {160, 175, 175, 355},
+ {160, 355, 176, 450},
+ "stdpccts.h",
+ keepCase,
+ "-fh",
+ "This entry specifies the name ANTLR uses"
+ " for the standard header file."
+ }
+ },
+ /* [5] */
+ 295,
+ "Use this dialog to specify parse options"
+ ".",
+ { /* array itemArray: 9 elements */
+ /* [1] */
+ NotDependent {
+
+ },
+ RegularEntry {
+ "Lookahead:",
+ {23, 27, 38, 152},
+ {46, 29, 62, 154},
+ "1",
+ keepCase,
+ "-k",
+ "This entry specifies the number of token"
+ "s of lookahead."
+ },
+ /* [2] */
+ NotDependent {
+
+ },
+ RegularEntry {
+ "Compr lookahead:",
+ {22, 167, 37, 292},
+ {46, 172, 62, 297},
+ "",
+ keepCase,
+ "-ck",
+ "This entry specifies the number of token"
+ "s of lookahead when using compressed (li"
+ "near approximation) lookahead. In genera"
+ "l, the compressed lookahead is much deep"
+ "er than the full lookahead."
+ },
+ /* [3] */
+ NotDependent {
+
+ },
+ RegularEntry {
+ "Max tree nodes:",
+ {22, 312, 37, 437},
+ {46, 315, 62, 445},
+ "",
+ keepCase,
+ "-rl",
+ "This entry specifies the maximum number "
+ "of tokens of tree nodes used by the gram"
+ "mar analysis."
+ },
+ /* [4] */
+ NotDependent {
+
+ },
+ CheckOption {
+ NotSet,
+ {76, 25, 91, 350},
+ "Maintenance Release style hoisting",
+ "-mrhoist",
+ "Turn on/off k=1 Maintenance Release styl"
+ "e hoisting."
+ },
+ /* [5] */
+ NotDependent {
+
+ },
+ CheckOption {
+ NotSet,
+ {96, 25, 111, 431},
+ "EXPERIMENTAL Maintenance Release style h"
+ "oisting",
+ "-mrhoistk",
+ "Turn on/off k>1 EXPERIMENTAL Maintenance"
+ " Release style hoisting."
+ },
+ /* [6] */
+ NotDependent {
+
+ },
+ CheckOption {
+ NotSet,
+ {116, 25, 131, 363},
+ "Compute context for hoisted predicates",
+ "-prc on",
+ "Turn on/off computation of context for h"
+ "oisted predicates."
+ },
+ /* [7] */
+ NotDependent {
+
+ },
+ RegularEntry {
+ "Ambiguity aid:",
+ {140, 27, 155, 125},
+ {141, 135, 155, 209},
+ "",
+ keepCase,
+ "-aa",
+ "Ambiguity aid for a rule (rule name or l"
+ "ine number)."
+ },
+ /* [8] */
+ NotDependent {
+
+ },
+ RegularEntry {
+ "Limits exp growth:",
+ {140, 236, 155, 361},
+ {139, 372, 155, 452},
+ "",
+ keepCase,
+ "-aad",
+ "Limits exp growth of -aa listing - defau"
+ "lt=1 (max=ck value)."
+ },
+ /* [9] */
+ NotDependent {
+
+ },
+ CheckOption {
+ NotSet,
+ {164, 26, 179, 366},
+ "Lookahead token may appear multiple time"
+ "s",
+ "-aam",
+ "Lookahead token may appear multiple time"
+ "s in -aa listing."
+ }
+ }
+ }
+};
+
diff --git a/Source/Pccts/antlr/antlr1.txt b/Source/Pccts/antlr/antlr1.txt
new file mode 100644
index 0000000..4a7d22e
--- /dev/null
+++ b/Source/Pccts/antlr/antlr1.txt
@@ -0,0 +1,264 @@
+
+
+
+ANTLR(1) PCCTS Manual Pages ANTLR(1)
+
+
+
+NAME
+ antlr - ANother Tool for Language Recognition
+
+SYNTAX
+ antlr [_o_p_t_i_o_n_s] _g_r_a_m_m_a_r__f_i_l_e_s
+
+DESCRIPTION
+ _A_n_t_l_r converts an extended form of context-free grammar into
+ a set of C functions which directly implement an efficient
+ form of deterministic recursive-descent LL(k) parser.
+ Context-free grammars may be augmented with predicates to
+ allow semantics to influence parsing; this allows a form of
+ context-sensitive parsing. Selective backtracking is also
+ available to handle non-LL(k) and even non-LALR(k) con-
+ structs. _A_n_t_l_r also produces a definition of a lexer which
+ can be automatically converted into C code for a DFA-based
+ lexer by _d_l_g. Hence, _a_n_t_l_r serves a function much like that
+ of _y_a_c_c, however, it is notably more flexible and is more
+ integrated with a lexer generator (_a_n_t_l_r directly generates
+ _d_l_g code, whereas _y_a_c_c and _l_e_x are given independent
+ descriptions). Unlike _y_a_c_c which accepts LALR(1) grammars,
+ _a_n_t_l_r accepts LL(k) grammars in an extended BNF notation -
+ which eliminates the need for precedence rules.
+
+ Like _y_a_c_c grammars, _a_n_t_l_r grammars can use automatically-
+ maintained symbol attribute values referenced as dollar
+ variables. Further, because _a_n_t_l_r generates top-down
+ parsers, arbitrary values may be inherited from parent rules
+ (passed like function parameters). _A_n_t_l_r also has a mechan-
+ ism for creating and manipulating abstract-syntax-trees.
+
+ There are various other niceties in _a_n_t_l_r, including the
+ ability to spread one grammar over multiple files or even
+ multiple grammars in a single file, the ability to generate
+ a version of the grammar with actions stripped out (for
+ documentation purposes), and lots more.
+
+OPTIONS
+ -ck _n
+ Use up to _n symbols of lookahead when using compressed
+ (linear approximation) lookahead. This type of looka-
+ head is very cheap to compute and is attempted before
+ full LL(k) lookahead, which is of exponential complex-
+ ity in the worst case. In general, the compressed loo-
+ kahead can be much deeper (e.g, -ck 10) _t_h_a_n _t_h_e _f_u_l_l
+ _l_o_o_k_a_h_e_a_d (_w_h_i_c_h _u_s_u_a_l_l_y _m_u_s_t _b_e _l_e_s_s _t_h_a_n _4).
+
+ -CC Generate C++ output from both ANTLR and DLG.
+
+ -cr Generate a cross-reference for all rules. For each
+ rule, print a list of all other rules that reference
+ it.
+
+ -e1 Ambiguities/errors shown in low detail (default).
+
+ -e2 Ambiguities/errors shown in more detail.
+
+ -e3 Ambiguities/errors shown in excruciating detail.
+
+ -fe file
+ Rename err.c to file.
+
+ -fh file
+ Rename stdpccts.h header (turns on -gh) to file.
+
+ -fl file
+ Rename lexical output, parser.dlg, to file.
+
+ -fm file
+ Rename file with lexical mode definitions, mode.h, to
+ file.
+
+ -fr file
+ Rename file which remaps globally visible symbols,
+ remap.h, to file.
+
+ -ft file
+ Rename tokens.h to file.
+
+ -ga Generate ANSI-compatible code (default case). This has
+ not been rigorously tested to be ANSI XJ11 C compliant,
+ but it is close. The normal output of _a_n_t_l_r is
+ currently compilable under both K&R, ANSI C, and C++-
+ this option does nothing because _a_n_t_l_r generates a
+ bunch of #ifdef's to do the right thing depending on
+ the language.
+
+ -gc Indicates that _a_n_t_l_r should generate no C code, i.e.,
+ only perform analysis on the grammar.
+
+ -gd C code is inserted in each of the _a_n_t_l_r generated pars-
+ ing functions to provide for user-defined handling of a
+ detailed parse trace. The inserted code consists of
+ calls to the user-supplied macros or functions called
+ zzTRACEIN and zzTRACEOUT. The only argument is a _c_h_a_r
+ * pointing to a C-style string which is the grammar
+ rule recognized by the current parsing function. If no
+ definition is given for the trace functions, upon rule
+ entry and exit, a message will be printed indicating
+ that a particular rule as been entered or exited.
+
+ -ge Generate an error class for each non-terminal.
+
+ -gh Generate stdpccts.h for non-ANTLR-generated files to
+ include. This file contains all defines needed to
+ describe the type of parser generated by _a_n_t_l_r (e.g.
+ how much lookahead is used and whether or not trees are
+ constructed) and contains the header action specified
+ by the user.
+
+ -gk Generate parsers that delay lookahead fetches until
+ needed. Without this option, _a_n_t_l_r generates parsers
+ which always have _k tokens of lookahead available.
+
+ -gl Generate line info about grammar actions in C parser of
+ the form # _l_i_n_e "_f_i_l_e" which makes error messages from
+ the C/C++ compiler make more sense as they will point
+ into the grammar file not the resulting C file.
+ Debugging is easier as well, because you will step
+ through the grammar not C file.
+
+ -gs Do not generate sets for token expression lists;
+ instead generate a ||-separated sequence of
+ LA(1)==_t_o_k_e_n__n_u_m_b_e_r. The default is to generate sets.
+
+ -gt Generate code for Abstract-Syntax Trees.
+
+ -gx Do not create the lexical analyzer files (dlg-related).
+ This option should be given when the user wishes to
+ provide a customized lexical analyzer. It may also be
+ used in _m_a_k_e scripts to cause only the parser to be
+ rebuilt when a change not affecting the lexical struc-
+ ture is made to the input grammars.
+
+ -k _n Set k of LL(k) to _n; i.e. set tokens of look-ahead
+ (default==1).
+
+ -o dir
+ Directory where output files should go (default=".").
+ This is very nice for keeping the source directory
+ clear of ANTLR and DLG spawn.
+
+ -p The complete grammar, collected from all input grammar
+ files and stripped of all comments and embedded
+ actions, is listed to stdout. This is intended to aid
+ in viewing the entire grammar as a whole and to elim-
+ inate the need to keep actions concisely stated so that
+ the grammar is easier to read. Hence, it is preferable
+ to embed even complex actions directly in the grammar,
+ rather than to call them as subroutines, since the sub-
+ routine call overhead will be saved.
+
+ -pa This option is the same as -p except that the output is
+ annotated with the first sets determined from grammar
+ analysis.
+
+ -prc on
+ Turn on the computation and hoisting of predicate con-
+ text.
+
+ -prc off
+ Turn off the computation and hoisting of predicate con-
+ text. This option makes 1.10 behave like the 1.06
+ release with option -pr on. Context computation is off
+ by default.
+
+ -rl _n
+ Limit the maximum number of tree nodes used by grammar
+ analysis to _n. Occasionally, _a_n_t_l_r is unable to
+ analyze a grammar submitted by the user. This rare
+ situation can only occur when the grammar is large and
+ the amount of lookahead is greater than one. A non-
+ linear analysis algorithm is used by PCCTS to handle
+ the general case of LL(k) parsing. The average com-
+ plexity of analysis, however, is near linear due to
+ some fancy footwork in the implementation which reduces
+ the number of calls to the full LL(k) algorithm. An
+ error message will be displayed, if this limit is
+ reached, which indicates the grammar construct being
+ analyzed when _a_n_t_l_r hit a non-linearity. Use this
+ option if _a_n_t_l_r seems to go out to lunch and your disk
+ start thrashing; try _n=10000 to start. Once the
+ offending construct has been identified, try to remove
+ the ambiguity that _a_n_t_l_r was trying to overcome with
+ large lookahead analysis. The introduction of (...)?
+ backtracking blocks eliminates some of these problems -
+ _a_n_t_l_r does not analyze alternatives that begin with
+ (...)? (it simply backtracks, if necessary, at run
+ time).
+
+ -w1 Set low warning level. Do not warn if semantic
+ predicates and/or (...)? blocks are assumed to cover
+ ambiguous alternatives.
+
+ -w2 Ambiguous parsing decisions yield warnings even if
+ semantic predicates or (...)? blocks are used. Warn if
+ predicate context computed and semantic predicates
+ incompletely disambiguate alternative productions.
+
+ - Read grammar from standard input and generate stdin.c
+ as the parser file.
+
+SPECIAL CONSIDERATIONS
+ _A_n_t_l_r works... we think. There is no implicit guarantee of
+ anything. We reserve no legal rights to the software known
+ as the Purdue Compiler Construction Tool Set (PCCTS) - PCCTS
+ is in the public domain. An individual or company may do
+ whatever they wish with source code distributed with PCCTS
+ or the code generated by PCCTS, including the incorporation
+ of PCCTS, or its output, into commercial software. We
+ encourage users to develop software with PCCTS. However, we
+ do ask that credit is given to us for developing PCCTS. By
+ "credit", we mean that if you incorporate our source code
+ into one of your programs (commercial product, research pro-
+ ject, or otherwise) that you acknowledge this fact somewhere
+ in the documentation, research report, etc... If you like
+ PCCTS and have developed a nice tool with the output, please
+ mention that you developed it using PCCTS. As long as these
+ guidelines are followed, we expect to continue enhancing
+ this system and expect to make other tools available as they
+ are completed.
+
+FILES
+ *.c output C parser.
+
+ *.cpp
+ output C++ parser when C++ mode is used.
+
+ parser.dlg
+ output _d_l_g lexical analyzer.
+
+ err.c
+ token string array, error sets and error support rou-
+ tines. Not used in C++ mode.
+
+ remap.h
+ file that redefines all globally visible parser sym-
+ bols. The use of the #parser directive creates this
+ file. Not used in C++ mode.
+
+ stdpccts.h
+ list of definitions needed by C files, not generated by
+ PCCTS, that reference PCCTS objects. This is not gen-
+ erated by default. Not used in C++ mode.
+
+ tokens.h
+ output #_d_e_f_i_n_e_s for tokens used and function prototypes
+ for functions generated for rules.
+
+
+SEE ALSO
+ dlg(1), pccts(1)
+
+
+
+
+
diff --git a/Source/Pccts/antlr/bits.c b/Source/Pccts/antlr/bits.c
new file mode 100644
index 0000000..ddd9bd6
--- /dev/null
+++ b/Source/Pccts/antlr/bits.c
@@ -0,0 +1,1025 @@
+/* bits.c -- manage creation and output of bit sets used by the parser.
+ *
+ * SOFTWARE RIGHTS
+ *
+ * We reserve no LEGAL rights to the Purdue Compiler Construction Tool
+ * Set (PCCTS) -- PCCTS is in the public domain. An individual or
+ * company may do whatever they wish with source code distributed with
+ * PCCTS or the code generated by PCCTS, including the incorporation of
+ * PCCTS, or its output, into commerical software.
+ *
+ * We encourage users to develop software with PCCTS. However, we do ask
+ * that credit is given to us for developing PCCTS. By "credit",
+ * we mean that if you incorporate our source code into one of your
+ * programs (commercial product, research project, or otherwise) that you
+ * acknowledge this fact somewhere in the documentation, research report,
+ * etc... If you like PCCTS and have developed a nice tool with the
+ * output, please mention that you developed it using PCCTS. In
+ * addition, we ask that this header remain intact in our source code.
+ * As long as these guidelines are kept, we expect to continue enhancing
+ * this system and expect to make other tools available as they are
+ * completed.
+ *
+ * ANTLR 1.33
+ * Terence Parr
+ * Parr Research Corporation
+ * with Purdue University and AHPCRC, University of Minnesota
+ * 1989-2001
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <assert.h>
+#include "pcctscfg.h"
+#include "set.h"
+#include "syn.h"
+#include "hash.h"
+#include "generic.h"
+#include "dlgdef.h"
+
+/* char is only thing that is pretty much always known == 8 bits
+ * This allows output of antlr (set stuff, anyway) to be androgynous (portable)
+ */
+typedef unsigned char SetWordType;
+#define BitsPerByte 8
+#define BitsPerWord BitsPerByte*sizeof(SetWordType)
+
+static SetWordType *setwd = NULL;
+int setnum = -1;
+int wordnum = 0;
+
+int esetnum = 0;
+
+/* Used to convert native wordsize, which ANTLR uses (via set.c) to manipulate sets,
+ to bytes that are most portable size-wise.
+ */
+void
+#ifdef __USE_PROTOS
+DumpIntAsChars( FILE *f, char *format, unsigned wd )
+#else
+DumpIntAsChars( f, format, wd )
+FILE *f;
+char *format;
+unsigned wd;
+#endif
+{
+ int i;
+ /* uses max of 32 bit unsigned integer for the moment */
+ static unsigned long byte_mask[sizeof(unsigned long)] =
+ { 0xFF, 0xFF00UL, 0xFF0000UL, 0xFF000000UL }; /* MR20 G. Hobbelt */
+/* 0xFF00000000, 0xFF0000000000, 0xFF000000000000, 0xFF00000000000000 };*/
+
+ /* for each byte in the word */
+ assert(sizeof(unsigned) <= 4); /* M20 G. Hobbelt Sanity check */
+ for (i=0; i<sizeof(unsigned); i++)
+ {
+ /* mask out the ith byte and shift down to the first 8 bits */
+ fprintf(f, format, (wd&byte_mask[i])>>(i*BitsPerByte));
+ if ( i<sizeof(unsigned)-1) fprintf(f, ",");
+ }
+}
+
+/* Create a new setwd (ignoring [Ep] token on end) */
+void
+#ifdef __USE_PROTOS
+NewSetWd( void )
+#else
+NewSetWd( )
+#endif
+{
+ SetWordType *p;
+
+ if ( setwd == NULL )
+ {
+ setwd = (SetWordType *) calloc(TokenNum, sizeof(SetWordType));
+ require(setwd!=NULL, "NewSetWd: cannot alloc set wd\n");
+ }
+ for (p = setwd; p<&(setwd[TokenNum]); p++) {*p=0;}
+ wordnum++;
+}
+
+void
+#ifdef __USE_PROTOS
+DumpSetWd( void )
+#else
+DumpSetWd( )
+#endif
+{
+ if ( GenCC ) DumpSetWdForCC();
+ else DumpSetWdForC();
+}
+
+/* Dump the current setwd to ErrFile. 0..MaxTokenVal */
+void
+#ifdef __USE_PROTOS
+DumpSetWdForC( void )
+#else
+DumpSetWdForC( )
+#endif
+{
+ int i,c=1;
+
+ if ( setwd==NULL ) return;
+ fprintf(DefFile, "extern SetWordType setwd%d[];\n", wordnum);
+ fprintf(ErrFile,
+ "SetWordType setwd%d[%d] = {", wordnum, TokenNum-1);
+ for (i=0; i<TokenNum-1; i++)
+ {
+ DAWDLE;
+ if ( i!=0 ) fprintf(ErrFile, ",");
+ if ( c == 8 ) {fprintf(ErrFile, "\n\t"); c=1;} else c++;
+ fprintf(ErrFile, "0x%x", setwd[i]);
+ }
+ fprintf(ErrFile, "};\n");
+}
+
+/* Dump the current setwd to Parser.C file. 0..MaxTokenVal;
+ * Only used if -CC on.
+ */
+void
+#ifdef __USE_PROTOS
+DumpSetWdForCC( void )
+#else
+DumpSetWdForCC( )
+#endif
+{
+ int i,c=1;
+
+ if ( setwd==NULL ) return;
+ fprintf(Parser_h, "\tstatic SetWordType setwd%d[%d];\n", wordnum, TokenNum-1);
+ fprintf(Parser_c,
+ "SetWordType %s::setwd%d[%d] = {", CurrentClassName, wordnum,
+ TokenNum-1);
+ for (i=0; i<TokenNum-1; i++)
+ {
+ DAWDLE;
+ if ( i!=0 ) fprintf(Parser_c, ",");
+ if ( c == 8 ) {fprintf(Parser_c, "\n\t"); c=1;} else c++;
+ fprintf(Parser_c, "0x%x", setwd[i]);
+ }
+ fprintf(Parser_c, "};\n");
+}
+
+/* Make a new set. Dump old setwd and create new setwd if current setwd is full */
+void
+#ifdef __USE_PROTOS
+NewSet( void )
+#else
+NewSet( )
+#endif
+{
+ setnum++;
+ if ( setnum==BitsPerWord ) /* is current setwd full? */
+ {
+ DumpSetWd(); NewSetWd(); setnum = 0;
+ }
+}
+
+/* s is a set of tokens. Turn on bit at each token position in set 'setnum' */
+void
+#ifdef __USE_PROTOS
+FillSet( set s )
+#else
+FillSet( s )
+set s;
+#endif
+{
+ SetWordType mask=(((unsigned)1)<<setnum);
+ unsigned int e;
+
+ while ( !set_nil(s) )
+ {
+ e = set_int(s);
+ set_rm(e, s);
+ setwd[e] |= mask;
+ }
+}
+
+ /* E r r o r C l a s s S t u f f */
+
+/* compute the FIRST of a rule for the error class stuff */
+static set
+#ifdef __USE_PROTOS
+Efirst( char *rule, ECnode *eclass )
+#else
+Efirst( rule, eclass )
+char *rule;
+ECnode *eclass;
+#endif
+{
+ set rk, a;
+ Junction *r;
+ RuleEntry *q = (RuleEntry *) hash_get(Rname, rule);
+
+ if ( q == NULL )
+ {
+ warnNoFL(eMsg2("undefined rule '%s' referenced in errclass '%s'; ignored",
+ rule, TokenString(eclass->tok)));
+ return empty;
+ }
+ r = RulePtr[q->rulenum];
+ r->end->halt = TRUE; /* don't let reach fall off end of rule here */
+ rk = empty;
+ REACH(r, 1, &rk, a);
+ r->end->halt = FALSE;
+ return a;
+}
+
+/*
+ * scan the list of tokens/eclasses/nonterminals filling the new eclass
+ * with the set described by the list. Note that an eclass can be
+ * quoted to allow spaces etc... However, an eclass must not conflict
+ * with a reg expr found elsewhere. The reg expr will be taken over
+ * the eclass name.
+ */
+static void
+#ifdef __USE_PROTOS
+doEclass( char *eclass )
+#else
+doEclass( eclass )
+char *eclass;
+#endif
+{
+ TermEntry *q;
+ ECnode *p;
+ TCnode *tcnode;
+ ListNode *e;
+ unsigned int t;
+ unsigned deg=0;
+ set a;
+ require(eclass!=NULL, "doEclass: NULL eset");
+
+ p = (ECnode *) eclass;
+ lexmode(p->lexclass); /* switch to lexclass where errclass is defined */
+ p->eset = empty;
+ for (e = (p->elist)->next; e!=NULL; e=e->next)
+ {
+ q = NULL; /* MR23 */
+
+ if ( islower( *((char *)e->elem) ) ) /* is it a rule ref? (alias FIRST request) */
+ {
+ a = Efirst((char *)e->elem, p);
+ set_orin(&p->eset, a);
+ deg += set_deg(a);
+ set_free( a );
+ continue;
+ }
+ else if ( *((char *)e->elem)=='"' )
+ {
+ t = 0;
+ q = (TermEntry *) hash_get(Texpr, (char *) e->elem);
+ if ( q == NULL )
+ {
+ /* if quoted and not an expr look for eclass name */
+ q = (TermEntry *) hash_get(Tname, *((char **)&(e->elem))=StripQuotes((char *)e->elem));
+ if ( q != NULL ) t = q->token;
+ }
+ else t = q->token;
+ }
+ else /* labelled token/eclass/tokclass */
+ {
+ q = (TermEntry *) hash_get(Tname, (char *)e->elem);
+ if ( q != NULL )
+ {
+ if ( strcmp((char *)e->elem, TokenString(p->tok))==0 )
+ {
+ warnNoFL(eMsg1("self-referential error class '%s'; ignored",
+ (char *)e->elem));
+ continue;
+ }
+ else
+ t = q->token;
+ }
+ else t=0;
+ }
+ if ( t!=0 )
+ {
+ if (isTermEntryTokClass(q)) { /* MR23 */
+ tcnode = q->tclass; /* MR23 */
+ set_orin(&p->eset, tcnode->tset); /* MR23 */
+ deg = set_deg(p->eset); /* MR23 */
+ } /* MR23 */
+ else {
+ set_orel(t, &p->eset);
+ deg++;
+ }
+ }
+ else warnNoFL(eMsg2("undefined token '%s' referenced in errclass '%s'; ignored",
+ (char *)e->elem, TokenString(p->tok)));
+ }
+ p->setdeg = deg;
+}
+
+void
+#ifdef __USE_PROTOS
+ComputeErrorSets( void )
+#else
+ComputeErrorSets( )
+#endif
+{
+#ifdef __cplusplus
+ list_apply(eclasses, (void (*)(void *)) doEclass);
+#else
+#ifdef __USE_PROTOS
+ list_apply(eclasses, (void (*)(void *)) doEclass);
+#else
+ list_apply(eclasses, doEclass);
+#endif
+#endif
+}
+
+void
+#ifdef __USE_PROTOS
+ComputeTokSets( void )
+#else
+ComputeTokSets( )
+#endif
+{
+ ListNode *t, *e = NULL, *e1, *e2;
+ int something_changed;
+ int i;
+ TCnode *p;
+ TermEntry *q, *q1, *q2;
+
+ if ( tclasses == NULL ) return;
+
+ /* turn lists of token/tokclass references into sets */
+ for (t = tclasses->next; t!=NULL; t=t->next)
+ {
+ p = (TCnode *) t->elem;
+
+ /* if wild card, then won't have entries in tclass, assume all_tokens */
+ if ( p->tok == WildCardToken )
+ {
+ p->tset = set_dup(all_tokens);
+ continue;
+ }
+
+ lexmode(p->lexclass); /* switch to lexclass where tokclass is defined */
+ p->tset = empty;
+
+ /* instantiate all tokens/token_classes into the tset */
+ for (e = (p->tlist)->next; e!=NULL; e=e->next)
+ {
+ char *tokstr;
+ tokstr = (char *)e->elem;
+ if ( *tokstr == '"' ) {
+ q = (TermEntry *) hash_get(Texpr, tokstr);
+ require(q!=NULL, "ComputeTokSets: no token def");
+ set_orel(q->token, &p->tset);
+ } else if (tokstr[0] == '.') {
+ e1=e->next;
+ e2=e1->next;
+ e=e2;
+ q1= (TermEntry *) hash_get(Tname, (char *)e1->elem);
+ require(q1!=NULL, "ComputeTokSets: no token def");
+ q2= (TermEntry *) hash_get(Tname, (char *)e2->elem);
+ require(q2!=NULL, "ComputeTokSets: no token def");
+
+ if (set_el(q1->token,imag_tokens)) {
+errNoFL(eMsg2("can't define #tokclass %s using #tokclass or #errclass %s",
+ TokenString(p->tok),(char *)e1->elem) );
+ }
+ if (set_el(q2->token,imag_tokens)) {
+errNoFL(eMsg2("can't define #tokclass %s using #tokclass or #errclass %s",
+ TokenString(p->tok),(char *)e2->elem) );
+ }
+ if (q1->token > q2->token) {
+errNoFL(eMsg3("for #tokclass %s %s..%s - first token number > second token number",
+ TokenString(p->tok),(char *)e1->elem,(char *)e2->elem) );
+ for (i=q2->token; i<=q1->token; i++) { set_orel(i, &p->tset); }
+ } else {
+ for (i=q1->token; i<=q2->token; i++) { set_orel(i, &p->tset); }
+ }
+ } else {
+ q = (TermEntry *) hash_get(Tname, tokstr);
+ require(q!=NULL, "ComputeTokSets: no token def");
+ set_orel(q->token, &p->tset);
+ }
+ }
+ }
+
+ /* Go thru list of tokclasses again looking for tokclasses in sets */
+again:
+ something_changed = 0;
+ for (t = tclasses->next; t!=NULL; t=t->next)
+ {
+ set tcl;
+ p = (TCnode *) t->elem;
+ tcl = set_and(p->tset, tokclasses);
+ if ( !set_nil(tcl) )
+ {
+ int tk;
+ /* replace refs to tokclasses with the associated set of tokens */
+ something_changed = 1;
+ while ( !set_nil(tcl) )
+ {
+ tk = set_int(tcl); /* grab one of the tok class refs */
+ set_rm(tk, tcl);
+ if ( p->tok != tk ) /* tokclass ref to yourself? */
+ {
+ q = (TermEntry *) hash_get(Tname, TokenString(tk));
+ require(q!=NULL, "#tokclass not in hash table");
+ set_orin(&p->tset, q->tclass->tset);
+ }
+ set_rm(tk, p->tset); /* remove ref that we replaced */
+ }
+ }
+ set_free(tcl);
+ }
+ if ( something_changed ) goto again;
+}
+
+void
+#ifdef __USE_PROTOS
+DumpRemainingTokSets(void)
+#else
+DumpRemainingTokSets()
+#endif
+{
+ TCnode *p;
+ ListNode *t;
+
+ /* Go thru tclasses (for the last time) and dump the sets not dumped
+ * during code gen; yes, this is a bogus way to do this, but ComputeTokSets()
+ * can't dump the defs as the error file and tok file has not been created
+ * yet etc...
+ */
+ if ( tclasses==NULL ) return;
+ for (t = tclasses->next; t!=NULL; t=t->next)
+ {
+ unsigned e;
+ p = (TCnode *) t->elem;
+ if ( p->dumped ) continue;
+ e = DefErrSet(&(p->tset), 0, TokenString(p->tok));
+ p->dumped = 1;
+ p->setnum = e;
+ }
+}
+
+
+/* replace a subset of an error set with an error class name if a subset is found
+ * repeat process until no replacements made
+ */
+void
+#ifdef __USE_PROTOS
+SubstErrorClass( set *f )
+#else
+SubstErrorClass( f )
+set *f;
+#endif
+{
+ int max, done = 0;
+ ListNode *p;
+ ECnode *ec, *maxclass = NULL;
+ set a;
+ require(f!=NULL, "SubstErrorClass: NULL eset");
+
+ if ( eclasses == NULL ) return;
+ while ( !done )
+ {
+ max = 0;
+ maxclass = NULL;
+ for (p=eclasses->next; p!=NULL; p=p->next) /* chk all error classes */
+ {
+ ec = (ECnode *) p->elem;
+ if ( ec->setdeg > max )
+ {
+ if ( set_sub(ec->eset, *f) || set_equ(ec->eset, *f) )
+ {maxclass = ec; max=ec->setdeg;}
+ }
+ }
+ if ( maxclass != NULL ) /* if subset found, replace with token */
+ {
+ a = set_dif(*f, maxclass->eset);
+ set_orel((unsigned)maxclass->tok, &a);
+ set_free(*f);
+ *f = a;
+ }
+ else done = 1;
+ }
+}
+
+int
+#ifdef __USE_PROTOS
+DefErrSet1(int nilOK, set *f, int subst, char *name )
+#else
+DefErrSet1(nilOK, f, subst, name )
+int nilOK;
+set *f;
+int subst; /* should be substitute error classes? */
+char *name;
+#endif
+{
+ if ( GenCC ) return DefErrSetForCC1(nilOK, f, subst, name, "_set");
+ else return DefErrSetForC1(nilOK, f, subst, name, "_set");
+}
+
+int
+#ifdef __USE_PROTOS
+DefErrSet( set *f, int subst, char *name )
+#else
+DefErrSet( f, subst, name )
+set *f;
+int subst; /* should be substitute error classes? */
+char *name;
+#endif
+{
+ return DefErrSet1(0,f,subst,name);
+}
+
+int
+#ifdef __USE_PROTOS
+DefErrSetWithSuffix(int nilOK, set *f, int subst, char *name, const char* suffix)
+#else
+DefErrSetWithSuffix(nilOK, f, subst, name, suffix )
+int nilOK;
+set *f;
+int subst; /* should be substitute error classes? */
+char *name;
+char *suffix;
+#endif
+{
+ if ( GenCC ) return DefErrSetForCC1(nilOK, f, subst, name, suffix );
+ else return DefErrSetForC1(nilOK, f, subst, name, suffix);
+}
+
+/* Define a new error set. WARNING...set-implementation dependent.
+ */
+int
+#ifdef __USE_PROTOS
+DefErrSetForC1(int nilOK, set *f, int subst, char * name, const char * suffix)
+#else
+DefErrSetForC1(nilOK, f, subst, name, suffix)
+int nilOK; /* MR13 */
+set *f;
+int subst; /* should be substitute error classes? */
+char *name;
+const char *suffix;
+#endif
+{
+ unsigned *p, *endp;
+ int e=1;
+
+ if (!nilOK) require(!set_nil(*f), "DefErrSetForC1: nil set to dump?");
+
+ if ( subst ) SubstErrorClass(f);
+ p = f->setword;
+ endp = &(f->setword[f->n]);
+ esetnum++;
+ if ( name!=NULL )
+ fprintf(DefFile, "extern SetWordType %s%s[];\n", name, suffix);
+ else
+ fprintf(DefFile, "extern SetWordType zzerr%d[];\n", esetnum);
+ if ( name!=NULL ) {
+ fprintf(ErrFile, "SetWordType %s%s[%d] = {",
+ name,
+ suffix,
+ NumWords(TokenNum-1)*sizeof(unsigned));
+ }
+ else {
+ fprintf(ErrFile, "SetWordType zzerr%d[%d] = {",
+ esetnum,
+ NumWords(TokenNum-1)*sizeof(unsigned));
+ }
+ while ( p < endp )
+ {
+ if ( e > 1 ) fprintf(ErrFile, ", ");
+ DumpIntAsChars(ErrFile, "0x%x", *p++);
+ if ( e == 3 )
+ {
+ DAWDLE;
+ if ( p < endp ) fprintf(ErrFile, ",");
+ fprintf(ErrFile, "\n\t");
+ e=1;
+ }
+ else e++;
+ }
+ fprintf(ErrFile, "};\n");
+
+ return esetnum;
+}
+
+int
+#ifdef __USE_PROTOS
+DefErrSetForC( set *f, int subst, char *name )
+#else
+DefErrSetForC( f, subst, name )
+set *f;
+int subst; /* should be substitute error classes? */
+char *name;
+#endif
+{
+ return DefErrSetForC1(0,f,subst,name, "_set");
+}
+
+/* Define a new error set. WARNING...set-implementation dependent;
+ * Only used when -CC on.
+ */
+
+int
+#ifdef __USE_PROTOS
+DefErrSetForCC1(int nilOK, set *f, int subst, char *name, const char *suffix )
+#else
+DefErrSetForCC1(nilOK, f, subst, name, suffix )
+int nilOK; /* MR13 */
+set *f;
+int subst; /* should be substitute error classes? */
+char *name;
+const char *suffix;
+#endif
+{
+ unsigned *p, *endp;
+ int e=1;
+
+ if (!nilOK) require(!set_nil(*f), "DefErrSetForCC1: nil set to dump?");
+
+ if ( subst ) SubstErrorClass(f);
+ p = f->setword;
+ endp = &(f->setword[f->n]);
+ esetnum++;
+
+ if ( name!=NULL ) {
+ fprintf(Parser_h, "\tstatic SetWordType %s%s[%d];\n", name, suffix,
+ NumWords(TokenNum-1)*sizeof(unsigned));
+ fprintf(Parser_c, "SetWordType %s::%s%s[%d] = {",
+ CurrentClassName,
+ name,
+ suffix,
+ NumWords(TokenNum-1)*sizeof(unsigned));
+ }
+ else {
+ fprintf(Parser_c, "SetWordType %s::err%d[%d] = {",
+ CurrentClassName,
+ esetnum,
+ NumWords(TokenNum-1)*sizeof(unsigned));
+ fprintf(Parser_h, "\tstatic SetWordType err%d[%d];\n", esetnum,
+ NumWords(TokenNum-1)*sizeof(unsigned));
+ }
+
+ while ( p < endp )
+ {
+ if ( e > 1 ) fprintf(Parser_c, ", ");
+ DumpIntAsChars(Parser_c, "0x%x", *p++);
+ if ( e == 3 )
+ {
+ if ( p < endp ) fprintf(Parser_c, ",");
+ fprintf(Parser_c, "\n\t");
+ e=1;
+ }
+ else e++;
+ }
+ fprintf(Parser_c, "};\n");
+
+ return esetnum;
+}
+
+int
+#ifdef __USE_PROTOS
+DefErrSetForCC( set *f, int subst, char *name )
+#else
+DefErrSetForCC( f, subst, name )
+set *f;
+int subst; /* should be substitute error classes? */
+char *name;
+#endif
+{
+ return DefErrSetForCC1(0,f,subst,name, "_set");
+}
+
+void
+#ifdef __USE_PROTOS
+GenParser_c_Hdr(void)
+#else
+GenParser_c_Hdr()
+#endif
+{
+ int i,j;
+ TermEntry *te;
+ char * hasAkaName = NULL; /* MR23 */
+
+ hasAkaName = (char *) malloc(TokenNum+1); /* MR23 */
+ require(hasAkaName!=NULL, "Cannot alloc hasAkaName\n"); /* MR23 */
+ for (i = 0; i < TokenNum; i++) hasAkaName[i]='0'; /* MR23 */
+ hasAkaName[TokenNum] = 0; /* MR23 */
+
+ fprintf(Parser_c, "/*\n");
+ fprintf(Parser_c, " * %s: P a r s e r S u p p o r t\n", CurrentClassName);
+ fprintf(Parser_c, " *\n");
+ fprintf(Parser_c, " * Generated from:");
+ for (i=0; i<NumFiles; i++) fprintf(Parser_c, " %s", FileStr[i]);
+ fprintf(Parser_c, "\n");
+ fprintf(Parser_c, " *\n");
+ fprintf(Parser_c, " * Terence Parr, Russell Quong, Will Cohen, and Hank Dietz: 1989-2001\n");
+ fprintf(Parser_c, " * Parr Research Corporation\n");
+ fprintf(Parser_c, " * with Purdue University Electrical Engineering\n");
+ fprintf(Parser_c, " * with AHPCRC, University of Minnesota\n");
+ fprintf(Parser_c, " * ANTLR Version %s\n", Version);
+ fprintf(Parser_c, " */\n\n");
+
+ if ( FirstAction != NULL ) dumpAction(FirstAction,Parser_c, 0, -1, 0, 1); /* MR11 MR15b */
+
+ fprintf(Parser_c, "#define ANTLR_VERSION %s\n", VersionDef);
+
+ fprintf(Parser_c, "#include \"pcctscfg.h\"\n");
+ fprintf(Parser_c, "#include \"pccts_stdio.h\"\n");
+ fprintf(Parser_c, "#define ANTLR_SUPPORT_CODE\n");
+ if ( UserTokenDefsFile != NULL )
+ fprintf(Parser_c, "#include %s\n", UserTokenDefsFile);
+ else
+ fprintf(Parser_c, "#include \"%s\"\n", DefFileName);
+
+ fprintf(Parser_c, "#include \"%s.h\"\n\n", CurrentClassName);
+
+ fprintf(Parser_c, "const ANTLRChar *%s::tokenName(int tok) ", /* MR1 */
+ CurrentClassName); /* MR1 */
+ fprintf(Parser_c, " { return _token_tbl[tok]; }\n"); /* MR1 */ /* MR10 */
+ /* Dump a Parser::tokens for each automaton */
+ fprintf(Parser_c, "\nconst ANTLRChar *%s::_token_tbl[]={\n",
+ CurrentClassName); /* MR20 */
+ fprintf(Parser_c, "\t/* 00 */\t\"Invalid\"");
+
+ for (i=1; i<TokenNum-1; i++)
+ {
+ DAWDLE;
+ if ( i == EpToken ) continue;
+ /* remapped to invalid token? */
+ if ( TokenInd!=NULL && TokenInd[i]>=LastTokenCounted )
+ {
+ fprintf(Parser_c, ",\n\t/* %02d */\t\"invalid\"", i);
+ continue;
+ }
+ if ( TokenString(i) != NULL ) {
+ te=(TermEntry *) hash_get(Tname,TokenString(i)); /* MR11 */
+ if (te == NULL || te->akaString == NULL) { /* MR11 */
+ fprintf(Parser_c, ",\n\t/* %02d */\t\"%s\"", i, TokenString(i));
+ } else {
+ hasAkaName[i] = '1'; /* MR23 */
+ fprintf(Parser_c, ",\n\t/* %02d */\t\"%s\"", i, te->akaString); /* MR11 */
+ }
+ }
+ else
+ {
+ /* look in all lexclasses for the reg expr */
+ for (j=0; j<NumLexClasses; j++)
+ {
+ lexmode(j);
+ if ( ExprString(i) != NULL )
+ {
+ fprintf(Parser_c, ",\n\t/* %02d */\t", i);
+ dumpExpr(Parser_c, ExprString(i));
+ break;
+ }
+ }
+ if ( j>=NumLexClasses )
+ {
+ if ( UserDefdTokens )
+ {
+ fprintf(Parser_c, ",\n\t/* %02d */\t\"\"", i);
+ }
+ else
+ fatal_internal(eMsgd("No label or expr for token %d",i));
+ }
+ }
+ }
+ fprintf(Parser_c, "\n};\n");
+
+ /* Build constructors */
+ fprintf(Parser_c, "\n%s::", CurrentClassName);
+ fprintf(Parser_c, "%s(ANTLRTokenBuffer *input) : %s(input,%d,%d,%d,%d)\n",
+ CurrentClassName,
+ (BaseClassName == NULL ? "ANTLRParser" : BaseClassName),
+ OutputLL_k,
+ FoundGuessBlk,
+ DemandLookahead,
+ NumWords(TokenNum-1)*sizeof(unsigned));
+ fprintf(Parser_c, "{\n");
+ fprintf(Parser_c, "\ttoken_tbl = _token_tbl;\n");
+ if (TraceGen) {
+ fprintf(Parser_c, "\ttraceOptionValueDefault=1;\t\t// MR10 turn trace ON\n");
+ } else {
+ fprintf(Parser_c, "\ttraceOptionValueDefault=0;\t\t// MR10 turn trace OFF\n");
+ };
+ fprintf(Parser_c, "}\n\n");
+ free ( (void *) hasAkaName);
+}
+
+void
+#ifdef __USE_PROTOS
+GenParser_h_Hdr(void)
+#else
+GenParser_h_Hdr()
+#endif
+{
+ int i;
+
+ fprintf(Parser_h, "/*\n");
+ fprintf(Parser_h, " * %s: P a r s e r H e a d e r \n", CurrentClassName);
+ fprintf(Parser_h, " *\n");
+ fprintf(Parser_h, " * Generated from:");
+ for (i=0; i<NumFiles; i++) fprintf(Parser_h, " %s", FileStr[i]);
+ fprintf(Parser_h, "\n");
+ fprintf(Parser_h, " *\n");
+ fprintf(Parser_h, " * Terence Parr, Russell Quong, Will Cohen, and Hank Dietz: 1989-2001\n");
+ fprintf(Parser_h, " * Parr Research Corporation\n");
+ fprintf(Parser_h, " * with Purdue University Electrical Engineering\n");
+ fprintf(Parser_h, " * with AHPCRC, University of Minnesota\n");
+ fprintf(Parser_h, " * ANTLR Version %s\n", Version);
+ fprintf(Parser_h, " */\n\n");
+
+ if ( FirstAction != NULL ) dumpAction( FirstAction, Parser_h, 0, -1, 0, 1); /* MR11 MR15b */
+
+ fprintf(Parser_h, "#ifndef %s_h\n", CurrentClassName);
+ fprintf(Parser_h, "#define %s_h\n\n", CurrentClassName);
+
+ fprintf(Parser_h, "#ifndef ANTLR_VERSION\n");
+ fprintf(Parser_h, "#define ANTLR_VERSION %s\n",VersionDef);
+ fprintf(Parser_h, "#endif\n\n");
+
+ if ( GenAST ) fprintf(Parser_h, "class ASTBase;\n");
+ if (TraceGen) {
+ fprintf(Parser_h,"#ifndef zzTRACE_RULES\n"); /* MR20 */
+ fprintf(Parser_h,"#define zzTRACE_RULES\n"); /* MR20 */
+ fprintf(Parser_h,"#endif\n"); /* MR22 */
+ };
+ fprintf(Parser_h, "#include \"%s\"\n\n", APARSER_H);
+
+ if ( HdrAction != NULL ) dumpAction( HdrAction, Parser_h, 0, -1, 0, 1);
+
+/* MR10 */ if (ClassDeclStuff == NULL) {
+/* MR10 */ fprintf(Parser_h, "class %s : public ANTLRParser {\n", CurrentClassName);
+/* MR10 */ } else {
+/* MR10 */ fprintf(Parser_h, "class %s %s {\n",CurrentClassName,ClassDeclStuff);
+/* MR10 */ };
+
+ fprintf(Parser_h, "public:\n"); /* MR1 */
+ fprintf(Parser_h, "\tstatic const ANTLRChar *tokenName(int tk);\n");/* MR1 */
+ fprintf(Parser_h, "\tenum { SET_SIZE = %i };\n",TokenNum-1); /* MR21 */
+ fprintf(Parser_h, "protected:\n");
+ fprintf(Parser_h, "\tstatic const ANTLRChar *_token_tbl[];\n"); /* MR20 */
+ fprintf(Parser_h, "private:\n");
+}
+
+/* Currently, this is only used in !GenCC mode */
+void
+#ifdef __USE_PROTOS
+GenErrHdr( void )
+#else
+GenErrHdr( )
+#endif
+{
+ int i, j;
+ TermEntry *te;
+
+ fprintf(ErrFile, "/*\n");
+ fprintf(ErrFile, " * A n t l r S e t s / E r r o r F i l e H e a d e r\n");
+ fprintf(ErrFile, " *\n");
+ fprintf(ErrFile, " * Generated from:");
+ for (i=0; i<NumFiles; i++) fprintf(ErrFile, " %s", FileStr[i]);
+ fprintf(ErrFile, "\n");
+ fprintf(ErrFile, " *\n");
+ fprintf(ErrFile, " * Terence Parr, Russell Quong, Will Cohen, and Hank Dietz: 1989-2001\n");
+ fprintf(ErrFile, " * Parr Research Corporation\n");
+ fprintf(ErrFile, " * with Purdue University Electrical Engineering\n");
+ fprintf(ErrFile, " * With AHPCRC, University of Minnesota\n");
+ fprintf(ErrFile, " * ANTLR Version %s\n", Version);
+ fprintf(ErrFile, " */\n\n");
+
+ if ( FirstAction != NULL ) dumpAction( FirstAction, ErrFile, 0, -1, 0, 1); /* MR11 MR15b */
+
+ fprintf(ErrFile, "#define ANTLR_VERSION %s\n", VersionDef);
+
+ fprintf(ErrFile, "#include \"pcctscfg.h\"\n");
+ fprintf(ErrFile, "#include \"pccts_stdio.h\"\n");
+ if ( strcmp(ParserName, DefaultParserName)!=0 )
+ fprintf(ErrFile, "#define %s %s\n", DefaultParserName, ParserName);
+ if ( strcmp(ParserName, DefaultParserName)!=0 )
+ fprintf(ErrFile, "#include \"%s\"\n", RemapFileName);
+ if ( HdrAction != NULL ) dumpAction( HdrAction, ErrFile, 0, -1, 0, 1 );
+ if ( FoundGuessBlk )
+ {
+ fprintf(ErrFile, "#define ZZCAN_GUESS\n");
+ fprintf(ErrFile, "#include \"pccts_setjmp.h\"\n");
+ }
+ if (TraceGen) {
+ fprintf(ErrFile,"#ifndef zzTRACE_RULES\n"); /* MR20 */
+ fprintf(ErrFile,"#define zzTRACE_RULES\n"); /* MR20 */
+ fprintf(ErrFile,"#endif\n"); /* MR22 */
+ };
+
+ if ( OutputLL_k > 1 ) fprintf(ErrFile, "#define LL_K %d\n", OutputLL_k);
+#ifdef DUM
+ if ( LexGen ) fprintf(ErrFile, "#define zzEOF_TOKEN %d\n", (TokenInd!=NULL?TokenInd[EofToken]:EofToken));
+#endif
+ fprintf(ErrFile, "#define zzSET_SIZE %d\n", NumWords(TokenNum-1)*sizeof(unsigned));
+ if ( DemandLookahead ) fprintf(ErrFile, "#define DEMAND_LOOK\n");
+ fprintf(ErrFile, "#include \"antlr.h\"\n");
+ if ( GenAST ) fprintf(ErrFile, "#include \"ast.h\"\n");
+
+ if ( UserDefdTokens ) fprintf(ErrFile, "#include %s\n", UserTokenDefsFile);
+ /* still need this one as it has the func prototypes */
+ fprintf(ErrFile, "#include \"%s\"\n", DefFileName);
+ fprintf(ErrFile, "#include \"dlgdef.h\"\n");
+ fprintf(ErrFile, "#include \"err.h\"\n\n");
+
+ /* Dump a zztokens for each automaton */
+ if ( strcmp(ParserName, DefaultParserName)!=0 )
+ {
+ fprintf(ErrFile, "ANTLRChar *%s_zztokens[%d]={\n", ParserName, TokenNum-1);
+ }
+ else
+ {
+ fprintf(ErrFile, "ANTLRChar *zztokens[%d]={\n", TokenNum-1);
+ }
+ fprintf(ErrFile, "\t/* 00 */\t\"Invalid\"");
+ for (i=1; i<TokenNum-1; i++)
+ {
+ DAWDLE;
+ if ( i == EpToken ) continue;
+ /* remapped to invalid token? */
+ if ( TokenInd!=NULL && TokenInd[i]>=LastTokenCounted )
+ {
+ fprintf(ErrFile, ",\n\t/* %02d */\t\"invalid\"", i);
+ continue;
+ }
+ if ( TokenString(i) != NULL ) {
+ te=(TermEntry *) hash_get(Tname,TokenString(i)); /* MR11 */
+ if (te == NULL || te->akaString == NULL) { /* MR11 */
+ fprintf(ErrFile, ",\n\t/* %02d */\t\"%s\"", i, TokenString(i));
+ } else {
+ fprintf(ErrFile, ",\n\t/* %02d */\t\"%s\"", i, te->akaString); /* MR11 */
+ }
+ }
+ else
+ {
+ /* look in all lexclasses for the reg expr */
+ for (j=0; j<NumLexClasses; j++)
+ {
+ lexmode(j);
+ if ( ExprString(i) != NULL )
+ {
+ fprintf(ErrFile, ",\n\t/* %02d */\t", i);
+ dumpExpr(ErrFile, ExprString(i));
+ break;
+ }
+ }
+ if ( j>=NumLexClasses )
+ {
+ if ( UserDefdTokens )
+ {
+ fprintf(ErrFile, ",\n\t/* %02d */\t\"\"", i);
+ }
+ else
+ fatal_internal(eMsgd("No label or expr for token %d",i));
+ }
+ }
+ }
+ fprintf(ErrFile, "\n};\n");
+}
+
+void
+#ifdef __USE_PROTOS
+dumpExpr( FILE *f, char *e )
+#else
+dumpExpr( f, e )
+FILE *f;
+char *e;
+#endif
+{
+ while ( *e!='\0' )
+ {
+ if ( *e=='\\' && *(e+1)=='\\' )
+ {putc('\\', f); putc('\\', f); e+=2;}
+ else if ( *e=='\\' && *(e+1)=='"' )
+ {putc('\\', f); putc('"', f); e+=2;}
+ else if ( *e=='\\' ) {putc('\\', f); putc('\\', f); e++;}
+ else {putc(*e, f); e++;}
+ }
+}
+
+int
+#ifdef __USE_PROTOS
+isTermEntryTokClass(TermEntry *te)
+#else
+isTermEntryTokClass(te)
+TermEntry *te;
+#endif
+{
+ ListNode *t;
+ TCnode *p;
+ TermEntry *q;
+ char *tokstr;
+
+ if (tclasses == NULL) return 0;
+
+ for (t = tclasses->next; t!=NULL; t=t->next)
+ {
+ p = (TCnode *) t->elem;
+ tokstr = TokenString(p->tok);
+ lexmode(p->lexclass); /* switch to lexclass where tokclass is defined */
+ q = (TermEntry *) hash_get(Tname, tokstr);
+ if (q == te) return 1;
+ }
+ return 0;
+}
diff --git a/Source/Pccts/antlr/build.c b/Source/Pccts/antlr/build.c
new file mode 100644
index 0000000..4eb3b02
--- /dev/null
+++ b/Source/Pccts/antlr/build.c
@@ -0,0 +1,813 @@
+/*
+ * build.c -- functions associated with building syntax diagrams.
+ *
+ * SOFTWARE RIGHTS
+ *
+ * We reserve no LEGAL rights to the Purdue Compiler Construction Tool
+ * Set (PCCTS) -- PCCTS is in the public domain. An individual or
+ * company may do whatever they wish with source code distributed with
+ * PCCTS or the code generated by PCCTS, including the incorporation of
+ * PCCTS, or its output, into commerical software.
+ *
+ * We encourage users to develop software with PCCTS. However, we do ask
+ * that credit is given to us for developing PCCTS. By "credit",
+ * we mean that if you incorporate our source code into one of your
+ * programs (commercial product, research project, or otherwise) that you
+ * acknowledge this fact somewhere in the documentation, research report,
+ * etc... If you like PCCTS and have developed a nice tool with the
+ * output, please mention that you developed it using PCCTS. In
+ * addition, we ask that this header remain intact in our source code.
+ * As long as these guidelines are kept, we expect to continue enhancing
+ * this system and expect to make other tools available as they are
+ * completed.
+ *
+ * ANTLR 1.33
+ * Terence Parr
+ * Parr Research Corporation
+ * with Purdue University and AHPCRC, University of Minnesota
+ * 1989-2001
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include "pcctscfg.h"
+#include "set.h"
+#include "syn.h"
+#include "hash.h"
+#include "generic.h"
+#include "dlgdef.h"
+
+#define SetBlk(g, t, approx, first_set_symbol) { \
+ ((Junction *)g.left)->jtype = t; \
+ ((Junction *)g.left)->approx = approx; \
+ ((Junction *)g.left)->pFirstSetSymbol = first_set_symbol; \
+ ((Junction *)g.left)->end = (Junction *) g.right; \
+ ((Junction *)g.right)->jtype = EndBlk;}
+
+/* Add the parameter string 'parm' to the parms field of a block-type junction
+ * g.left points to the sentinel node on a block. i.e. g.left->p1 points to
+ * the actual junction with its jtype == some block-type.
+ */
+void
+#ifdef __USE_PROTOS
+addParm( Node *p, char *parm )
+#else
+addParm( p, parm )
+Node *p;
+char *parm;
+#endif
+{
+ char *q = (char *) malloc( strlen(parm) + 1 );
+ require(p!=NULL, "addParm: NULL object\n");
+ require(q!=NULL, "addParm: unable to alloc parameter\n");
+
+ strcpy(q, parm);
+ if ( p->ntype == nRuleRef )
+ {
+ ((RuleRefNode *)p)->parms = q;
+ }
+ else if ( p->ntype == nJunction )
+ {
+ ((Junction *)p)->parm = q; /* only one parameter allowed on subrules */
+ }
+ else fatal_internal("addParm: invalid node for adding parm");
+}
+
+/*
+ * Build an action node for the syntax diagram
+ *
+ * buildAction(ACTION) ::= --o-->ACTION-->o--
+ *
+ * Where o is a junction node.
+ */
+Graph
+#ifdef __USE_PROTOS
+buildAction( char *action, int file, int line, int is_predicate )
+#else
+buildAction( action, file, line, is_predicate )
+char *action;
+int file;
+int line;
+int is_predicate;
+#endif
+{
+ Junction *j1, *j2;
+ Graph g;
+ ActionNode *a;
+ require(action!=NULL, "buildAction: invalid action");
+
+ j1 = newJunction();
+ j2 = newJunction();
+ a = newActionNode();
+ a->action = (char *) malloc( strlen(action)+1 );
+ require(a->action!=NULL, "buildAction: cannot alloc space for action\n");
+ strcpy(a->action, action);
+ j1->p1 = (Node *) a;
+ a->next = (Node *) j2;
+ a->is_predicate = is_predicate;
+
+ if (is_predicate) {
+ PredEntry *predEntry;
+ char *t;
+ char *key;
+ char *u;
+ int inverted=0;
+
+ t=key=(char *)calloc(1,strlen(a->action)+1);
+
+ for (u=a->action; *u != '\0' ; u++) {
+ if (*u != ' ') {
+ if (t==key && *u=='!') {
+ inverted=!inverted;
+ } else {
+ *t++=*u;
+ };
+ };
+ };
+
+ *t='\0';
+
+
+ predEntry=(PredEntry *)hash_get(Pname,key);
+ a->predEntry=predEntry;
+ if (predEntry != NULL) a->inverted=inverted;
+ } else {
+/* MR12c */ char *strStart=a->action;
+/* MR12c */ char *strEnd;
+/* MR12c */ strEnd=strStart+strlen(strStart)-1;
+/* MR12c */ for ( ; strEnd >= strStart && isspace(*strEnd); strEnd--) *strEnd=0;
+/* MR12c */ while (*strStart != '\0' && isspace(*strStart)) strStart++;
+/* MR12c */ if (ci_strequ(strStart,"nohoist")) {
+/* MR12c */ a->noHoist=1;
+/* MR12c */ }
+ }
+
+ g.left = (Node *) j1; g.right = (Node *) j2;
+ a->file = file;
+ a->line = line;
+ a->rname = CurRule; /* MR10 */
+ return g;
+}
+
+/*
+ * Build a token node for the syntax diagram
+ *
+ * buildToken(TOKEN) ::= --o-->TOKEN-->o--
+ *
+ * Where o is a junction node.
+ */
+Graph
+#ifdef __USE_PROTOS
+buildToken( char *text )
+#else
+buildToken( text )
+char *text;
+#endif
+{
+ Junction *j1, *j2;
+ Graph g;
+ TokNode *t;
+ require(text!=NULL, "buildToken: invalid token name");
+
+ j1 = newJunction();
+ j2 = newJunction();
+ t = newTokNode();
+ t->altstart = CurAltStart;
+ if ( *text == '"' ) {t->label=FALSE; t->token = addTexpr( text );}
+ else {t->label=TRUE; t->token = addTname( text );}
+ j1->p1 = (Node *) t;
+ t->next = (Node *) j2;
+ g.left = (Node *) j1; g.right = (Node *) j2;
+ return g;
+}
+
+/*
+ * Build a wild-card node for the syntax diagram
+ *
+ * buildToken(TOKEN) ::= --o-->'.'-->o--
+ *
+ * Where o is a junction node.
+ */
+Graph
+#ifdef __USE_PROTOS
+buildWildCard( char *text )
+#else
+buildWildCard( text )
+char *text;
+#endif
+{
+ Junction *j1, *j2;
+ Graph g;
+ TokNode *t;
+ TCnode *w;
+ TermEntry *p;
+ require(text!=NULL, "buildWildCard: invalid token name");
+
+ j1 = newJunction();
+ j2 = newJunction();
+ t = newTokNode();
+
+ /* If the ref a wild card, make a token class for it */
+ if ( Tnum(WildCardString) == 0 )
+ {
+ w = newTCnode;
+ w->tok = addTname( WildCardString );
+ set_orel(w->tok, &imag_tokens);
+ set_orel(w->tok, &tokclasses);
+ WildCardToken = w->tok;
+ require((p=(TermEntry *)hash_get(Tname, WildCardString)) != NULL,
+ "hash table mechanism is broken");
+ p->classname = 1; /* entry is class name, not token */
+ p->tclass = w; /* save ptr to this tclass def */
+ list_add(&tclasses, (char *)w);
+ }
+ else {
+ p=(TermEntry *)hash_get(Tname, WildCardString);
+ require( p!= NULL, "hash table mechanism is broken");
+ w = p->tclass;
+ }
+
+ t->token = w->tok;
+ t->wild_card = 1;
+ t->tclass = w;
+
+ t->altstart = CurAltStart;
+ j1->p1 = (Node *) t;
+ t->next = (Node *) j2;
+ g.left = (Node *) j1; g.right = (Node *) j2;
+ return g;
+}
+
+void
+#ifdef __USE_PROTOS
+setUpperRange(TokNode *t, char *text)
+#else
+setUpperRange(t, text)
+TokNode *t;
+char *text;
+#endif
+{
+ require(t!=NULL, "setUpperRange: NULL token node");
+ require(text!=NULL, "setUpperRange: NULL token string");
+
+ if ( *text == '"' ) {t->upper_range = addTexpr( text );}
+ else {t->upper_range = addTname( text );}
+}
+
+/*
+ * Build a rule reference node of the syntax diagram
+ *
+ * buildRuleRef(RULE) ::= --o-->RULE-->o--
+ *
+ * Where o is a junction node.
+ *
+ * If rule 'text' has been defined already, don't alloc new space to store string.
+ * Set r->text to point to old copy in string table.
+ */
+Graph
+#ifdef __USE_PROTOS
+buildRuleRef( char *text )
+#else
+buildRuleRef( text )
+char *text;
+#endif
+{
+ Junction *j1, *j2;
+ Graph g;
+ RuleRefNode *r;
+ RuleEntry *p;
+ require(text!=NULL, "buildRuleRef: invalid rule name");
+
+ j1 = newJunction();
+ j2 = newJunction();
+ r = newRNode();
+ r->altstart = CurAltStart;
+ r->assign = NULL;
+ if ( (p=(RuleEntry *)hash_get(Rname, text)) != NULL ) r->text = p->str;
+ else r->text = mystrdup( text );
+ j1->p1 = (Node *) r;
+ r->next = (Node *) j2;
+ g.left = (Node *) j1; g.right = (Node *) j2;
+ return g;
+}
+
+/*
+ * Or two subgraphs into one graph via:
+ *
+ * Or(G1, G2) ::= --o-G1-o--
+ * | ^
+ * v |
+ * o-G2-o
+ *
+ * Set the altnum of junction starting G2 to 1 + altnum of junction starting G1.
+ * If, however, the G1 altnum is 0, make it 1 and then
+ * make G2 altnum = G1 altnum + 1.
+ */
+Graph
+#ifdef __USE_PROTOS
+Or( Graph g1, Graph g2 )
+#else
+Or( g1, g2 )
+Graph g1;
+Graph g2;
+#endif
+{
+ Graph g;
+ require(g1.left != NULL, "Or: invalid graph");
+ require(g2.left != NULL && g2.right != NULL, "Or: invalid graph");
+
+ ((Junction *)g1.left)->p2 = g2.left;
+ ((Junction *)g2.right)->p1 = g1.right;
+ /* set altnums */
+ if ( ((Junction *)g1.left)->altnum == 0 ) ((Junction *)g1.left)->altnum = 1;
+ ((Junction *)g2.left)->altnum = ((Junction *)g1.left)->altnum + 1;
+ g.left = g2.left;
+ g.right = g1.right;
+ return g;
+}
+
+/*
+ * Catenate two subgraphs
+ *
+ * Cat(G1, G2) ::= --o-G1-o-->o-G2-o--
+ * Cat(NULL,G2)::= --o-G2-o--
+ * Cat(G1,NULL)::= --o-G1-o--
+ */
+Graph
+#ifdef __USE_PROTOS
+Cat( Graph g1, Graph g2 )
+#else
+Cat( g1, g2 )
+Graph g1;
+Graph g2;
+#endif
+{
+ Graph g;
+
+ if ( g1.left == NULL && g1.right == NULL ) return g2;
+ if ( g2.left == NULL && g2.right == NULL ) return g1;
+ ((Junction *)g1.right)->p1 = g2.left;
+ g.left = g1.left;
+ g.right = g2.right;
+ return g;
+}
+
+/*
+ * Make a subgraph an optional block
+ *
+ * makeOpt(G) ::= --o-->o-G-o-->o--
+ * | ^
+ * v |
+ * o-------o
+ *
+ * Note that this constructs {A|B|...|Z} as if (A|B|...|Z|) was found.
+ *
+ * The node on the far right is added so that every block owns its own
+ * EndBlk node.
+ */
+Graph
+#ifdef __USE_PROTOS
+makeOpt( Graph g1, int approx, char * pFirstSetSymbol )
+#else
+makeOpt( g1, approx, pFirstSetSymbol )
+Graph g1;
+int approx;
+char * pFirstSetSymbol;
+#endif
+{
+ Junction *j1,*j2,*p;
+ Graph g;
+ require(g1.left != NULL && g1.right != NULL, "makeOpt: invalid graph");
+
+ j1 = newJunction();
+ j2 = newJunction();
+ ((Junction *)g1.right)->p1 = (Node *) j2; /* add node to G at end */
+
+ /* MR21
+ *
+ * There is code in genBlk which recognizes the node created
+ * by emptyAlt() as a special case and bypasses it. We don't
+ * want this to happen for the optBlk.
+ */
+
+ g = emptyAlt3(); /* MR21 */
+ if ( ((Junction *)g1.left)->altnum == 0 ) ((Junction *)g1.left)->altnum = 1;
+ ((Junction *)g.left)->altnum = ((Junction *)g1.left)->altnum + 1;
+ for(p=(Junction *)g1.left; p->p2!=NULL; p=(Junction *)p->p2)
+ {;} /* find last alt */
+ p->p2 = g.left; /* add optional alternative */
+ ((Junction *)g.right)->p1 = (Node *)j2; /* opt alt points to EndBlk */
+ g1.right = (Node *)j2;
+ SetBlk(g1, aOptBlk, approx, pFirstSetSymbol);
+ j1->p1 = g1.left; /* add generic node in front */
+ g.left = (Node *) j1;
+ g.right = g1.right;
+ return g;
+}
+
+/*
+ * Make a graph into subblock
+ *
+ * makeBlk(G) ::= --o-->o-G-o-->o--
+ *
+ * The node on the far right is added so that every block owns its own
+ * EndBlk node.
+ */
+Graph
+#ifdef __USE_PROTOS
+makeBlk( Graph g1, int approx, char * pFirstSetSymbol )
+#else
+makeBlk( g1, approx, pFirstSetSymbol )
+Graph g1;
+int approx;
+char * pFirstSetSymbol;
+#endif
+{
+ Junction *j,*j2;
+ Graph g;
+ require(g1.left != NULL && g1.right != NULL, "makeBlk: invalid graph");
+
+ j = newJunction();
+ j2 = newJunction();
+ ((Junction *)g1.right)->p1 = (Node *) j2; /* add node to G at end */
+ g1.right = (Node *)j2;
+ SetBlk(g1, aSubBlk, approx, pFirstSetSymbol);
+ j->p1 = g1.left; /* add node in front */
+ g.left = (Node *) j;
+ g.right = g1.right;
+
+ return g;
+}
+
+/*
+ * Make a subgraph into a loop (closure) block -- (...)*
+ *
+ * makeLoop(G) ::= |---|
+ * v |
+ * --o-->o-->o-G-o-->o--
+ * | ^
+ * v |
+ * o-----------o
+ *
+ * After making loop, always place generic node out front. It becomes
+ * the start of enclosing block. The aLoopBlk is the target of the loop.
+ *
+ * Loop blks have TWO EndBlk nodes--the far right and the node that loops back
+ * to the aLoopBlk node. Node with which we can branch past loop == aLoopBegin and
+ * one which is loop target == aLoopBlk.
+ * The branch-past (initial) aLoopBegin node has end
+ * pointing to the last EndBlk node. The loop-target node has end==NULL.
+ *
+ * Loop blocks have a set of locks (from 1..CLL_k) on the aLoopBlk node.
+ */
+Graph
+#ifdef __USE_PROTOS
+makeLoop( Graph g1, int approx, char * pFirstSetSymbol )
+#else
+makeLoop( g1, approx, pFirstSetSymbol)
+Graph g1;
+int approx;
+char * pFirstSetSymbol;
+#endif
+{
+ Junction *back, *front, *begin;
+ Graph g;
+ require(g1.left != NULL && g1.right != NULL, "makeLoop: invalid graph");
+
+ back = newJunction();
+ front = newJunction();
+ begin = newJunction();
+ g = emptyAlt3();
+ ((Junction *)g1.right)->p2 = g1.left; /* add loop branch to G */
+ ((Junction *)g1.right)->p1 = (Node *) back; /* add node to G at end */
+ ((Junction *)g1.right)->jtype = EndBlk; /* mark 1st EndBlk node */
+ ((Junction *)g1.left)->jtype = aLoopBlk; /* mark 2nd aLoopBlk node */
+ ((Junction *)g1.left)->end = (Junction *) g1.right;
+ ((Junction *)g1.left)->lock = makelocks();
+ ((Junction *)g1.left)->pred_lock = makelocks();
+ g1.right = (Node *) back;
+ begin->p1 = (Node *) g1.left;
+ g1.left = (Node *) begin;
+ begin->p2 = (Node *) g.left; /* make bypass arc */
+ ((Junction *)g.right)->p1 = (Node *) back;
+ SetBlk(g1, aLoopBegin, approx, pFirstSetSymbol);
+ front->p1 = g1.left; /* add node to front */
+ g1.left = (Node *) front;
+
+ return g1;
+}
+
+/*
+ * Make a subgraph into a plus block -- (...)+ -- 1 or more times
+ *
+ * makePlus(G) ::= |---|
+ * v |
+ * --o-->o-G-o-->o--
+ *
+ * After making loop, always place generic node out front. It becomes
+ * the start of enclosing block. The aPlusBlk is the target of the loop.
+ *
+ * Plus blks have TWO EndBlk nodes--the far right and the node that loops back
+ * to the aPlusBlk node.
+ *
+ * Plus blocks have a set of locks (from 1..CLL_k) on the aPlusBlk node.
+ */
+Graph
+#ifdef __USE_PROTOS
+makePlus( Graph g1, int approx, char * pFirstSetSymbol)
+#else
+makePlus( g1, approx, pFirstSetSymbol)
+Graph g1;
+int approx;
+char * pFirstSetSymbol;
+#endif
+{
+ int has_empty_alt_already = 0;
+ Graph g;
+ Junction *j2, *j3, *first_alt;
+ Junction *last_alt=NULL, *p;
+ require(g1.left != NULL && g1.right != NULL, "makePlus: invalid graph");
+
+ first_alt = (Junction *)g1.left;
+ j2 = newJunction();
+ j3 = newJunction();
+ if ( ((Junction *)g1.left)->altnum == 0 ) ((Junction *)g1.left)->altnum = 1;
+ ((Junction *)g1.right)->p2 = g1.left; /* add loop branch to G */
+ ((Junction *)g1.right)->p1 = (Node *) j2; /* add node to G at end */
+ ((Junction *)g1.right)->jtype = EndBlk; /* mark 1st EndBlk node */
+ g1.right = (Node *) j2;
+ SetBlk(g1, aPlusBlk, approx, pFirstSetSymbol);
+ ((Junction *)g1.left)->lock = makelocks();
+ ((Junction *)g1.left)->pred_lock = makelocks();
+ j3->p1 = g1.left; /* add node to front */
+ g1.left = (Node *) j3;
+
+ /* add an optional branch which is the "exit" branch of loop */
+ /* FIRST, check to ensure that there does not already exist
+ * an optional path.
+ */
+ /* find last alt */
+ for(p=first_alt; p!=NULL; p=(Junction *)p->p2)
+ {
+ if ( p->p1->ntype == nJunction &&
+ p->p1!=NULL &&
+ ((Junction *)p->p1)->jtype==Generic &&
+ ((Junction *)p->p1)->p1!=NULL &&
+ ((Junction *)((Junction *)p->p1)->p1)->jtype==EndBlk )
+ {
+ has_empty_alt_already = 1;
+ }
+ last_alt = p;
+ }
+ if ( !has_empty_alt_already )
+ {
+ require(last_alt!=NULL, "last_alt==NULL; bad (..)+");
+ g = emptyAlt();
+ last_alt->p2 = g.left;
+ ((Junction *)g.right)->p1 = (Node *) j2;
+
+ /* make sure lookahead computation ignores this alt for
+ * FIRST("(..)+"); but it's still used for computing the FIRST
+ * of each alternative.
+ */
+ ((Junction *)g.left)->ignore = 1;
+ }
+
+ return g1;
+}
+
+/*
+ * Return an optional path: --o-->o--
+ */
+
+Graph
+#ifdef __USE_PROTOS
+emptyAlt( void )
+#else
+emptyAlt( )
+#endif
+{
+ Junction *j1, *j2;
+ Graph g;
+
+ j1 = newJunction();
+ j2 = newJunction();
+ j1->p1 = (Node *) j2;
+ g.left = (Node *) j1;
+ g.right = (Node *) j2;
+
+ return g;
+}
+
+/* MR21
+ *
+ * There is code in genBlk which recognizes the node created
+ * by emptyAlt() as a special case and bypasses it. We don't
+ * want this to happen for the optBlk.
+ */
+
+Graph
+#ifdef __USE_PROTOS
+emptyAlt3( void )
+#else
+emptyAlt3( )
+#endif
+{
+ Junction *j1, *j2, *j3;
+ Graph g;
+
+ j1 = newJunction();
+ j2 = newJunction();
+ j3 = newJunction();
+ j1->p1 = (Node *) j2;
+ j2->p1 = (Node *) j3;
+ g.left = (Node *) j1;
+ g.right = (Node *) j3;
+
+ return g;
+}
+
+/* N o d e A l l o c a t i o n */
+
+TokNode *
+#ifdef __USE_PROTOS
+newTokNode( void )
+#else
+newTokNode( )
+#endif
+{
+ static TokNode *FreeList = NULL;
+ TokNode *p, *newblk;
+
+ if ( FreeList == NULL )
+ {
+ newblk = (TokNode *)calloc(TokenBlockAllocSize, sizeof(TokNode));
+ if ( newblk == NULL )
+ fatal_internal(eMsg1("out of memory while building rule '%s'",CurRule));
+ for (p=newblk; p<&(newblk[TokenBlockAllocSize]); p++)
+ {
+ p->next = (Node *)FreeList; /* add all new token nodes to FreeList */
+ FreeList = p;
+ }
+ }
+ p = FreeList;
+ FreeList = (TokNode *)FreeList->next;/* remove a TokNode node */
+ p->next = NULL; /* NULL the ptr we used */
+ memset( (char *) p, 0, sizeof(TokNode)); /* MR10 */
+ p->ntype = nToken;
+ p->rname = CurRule;
+ p->file = CurFile;
+ p->line = zzline;
+ p->altstart = NULL;
+
+ return p;
+}
+
+RuleRefNode *
+#ifdef __USE_PROTOS
+newRNode( void )
+#else
+newRNode( )
+#endif
+{
+ static RuleRefNode *FreeList = NULL;
+ RuleRefNode *p, *newblk;
+
+ if ( FreeList == NULL )
+ {
+ newblk = (RuleRefNode *)calloc(RRefBlockAllocSize, sizeof(RuleRefNode));
+ if ( newblk == NULL )
+ fatal_internal(eMsg1("out of memory while building rule '%s'",CurRule));
+ for (p=newblk; p<&(newblk[RRefBlockAllocSize]); p++)
+ {
+ p->next = (Node *)FreeList; /* add all new rref nodes to FreeList */
+ FreeList = p;
+ }
+ }
+ p = FreeList;
+ FreeList = (RuleRefNode *)FreeList->next;/* remove a Junction node */
+ p->next = NULL; /* NULL the ptr we used */
+ memset( (char *) p, 0, sizeof(RuleRefNode)); /* MR10 */
+ p->ntype = nRuleRef;
+ p->rname = CurRule;
+ p->file = CurFile;
+ p->line = zzline;
+ p->astnode = ASTinclude;
+ p->altstart = NULL;
+
+ return p;
+}
+
+static int junctionSeqNumber=0; /* MR10 */
+
+Junction *
+#ifdef __USE_PROTOS
+newJunction( void )
+#else
+newJunction( )
+#endif
+{
+ static Junction *FreeList = NULL;
+ Junction *p, *newblk;
+
+ if ( FreeList == NULL )
+ {
+ newblk = (Junction *)calloc(JunctionBlockAllocSize, sizeof(Junction));
+ if ( newblk == NULL )
+ fatal_internal(eMsg1("out of memory while building rule '%s'",CurRule));
+ for (p=newblk; p<&(newblk[JunctionBlockAllocSize]); p++)
+ {
+ p->p1 = (Node *)FreeList; /* add all new Junction nodes to FreeList */
+ FreeList = p;
+ }
+ }
+ p = FreeList;
+ FreeList = (Junction *)FreeList->p1;/* remove a Junction node */
+ p->p1 = NULL; /* NULL the ptr we used */
+ memset( (char *) p, 0, sizeof(Junction)); /* MR10 */
+ p->ntype = nJunction;
+ p->visited = 0;
+ p->jtype = Generic;
+ p->rname = CurRule;
+ p->file = CurFile;
+ p->line = zzline;
+ p->exception_label = NULL;
+ p->fset = (set *) calloc(CLL_k+1, sizeof(set));
+ require(p->fset!=NULL, "cannot allocate fset in newJunction");
+ p->seq=++junctionSeqNumber; /* MR10 */
+
+ return p;
+}
+
+ActionNode *
+#ifdef __USE_PROTOS
+newActionNode( void )
+#else
+newActionNode( )
+#endif
+{
+ static ActionNode *FreeList = NULL;
+ ActionNode *p, *newblk;
+
+ if ( FreeList == NULL )
+ {
+ newblk = (ActionNode *)calloc(ActionBlockAllocSize, sizeof(ActionNode));
+ if ( newblk == NULL )
+ fatal_internal(eMsg1("out of memory while building rule '%s'",CurRule));
+ for (p=newblk; p<&(newblk[ActionBlockAllocSize]); p++)
+ {
+ p->next = (Node *)FreeList; /* add all new Action nodes to FreeList */
+ FreeList = p;
+ }
+ }
+ p = FreeList;
+ FreeList = (ActionNode *)FreeList->next;/* remove an Action node */
+ memset( (char *) p, 0, sizeof(ActionNode)); /* MR10 */
+ p->ntype = nAction;
+ p->next = NULL; /* NULL the ptr we used */
+ p->done = 0;
+ p->pred_fail = NULL;
+ p->guardpred = NULL;
+ p->ampersandPred = NULL;
+ return p;
+}
+
+/*
+ * allocate the array of locks (1..CLL_k) used to inhibit infinite recursion.
+ * Infinite recursion can occur in (..)* blocks, FIRST calcs and FOLLOW calcs.
+ * Therefore, we need locks on aLoopBlk, RuleBlk, EndRule nodes.
+ *
+ * if ( lock[k]==TRUE ) then we have been here before looking for k tokens
+ * of lookahead.
+ */
+char *
+#ifdef __USE_PROTOS
+makelocks( void )
+#else
+makelocks( )
+#endif
+{
+ char *p = (char *) calloc(CLL_k+1, sizeof(char));
+ require(p!=NULL, "cannot allocate lock array");
+
+ return p;
+}
+
+#if 0
+** #ifdef __USE_PROTOS
+** void my_memset(char *p,char value,int count)
+** #else
+** void my_memset(p,value,count)
+** char *p;
+** char value;
+** int count;
+** #endif
+** {
+** int i;
+**
+** for (i=0; i<count; i++) {
+** p[i]=value;
+** };
+** }
+#endif
diff --git a/Source/Pccts/antlr/build.xml b/Source/Pccts/antlr/build.xml
new file mode 100644
index 0000000..7ea7458
--- /dev/null
+++ b/Source/Pccts/antlr/build.xml
@@ -0,0 +1,136 @@
+<?xml version="1.0" ?>
+<!--
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+-->
+<project default="GenTool" basedir=".">
+<!--
+ EDK antlr Tool
+ Copyright (c) 2006, Intel Corporation
+-->
+ <property name="ToolName" value="antlr"/>
+
+ <taskdef resource="net/sf/antcontrib/antlib.xml"/>
+
+ <target name="init">
+ <condition property="CheckDepends">
+ <uptodate targetfile="${WORKSPACE}/Tools/bin/antlr.exe">
+ <srcfiles dir="." includes="*.c *.h *.g"/>
+ </uptodate>
+ </condition>
+ <if>
+ <equals arg1="${CheckDepends}" arg2="true"/>
+ <then>
+ <echo message="Executable, antlr.exe, is up to date."/>
+ </then>
+ <else>
+ <echo message="Building the EDK Pccts Tool: ${ToolName}"/>
+ </else>
+ </if>
+ </target>
+
+ <target name="GenTool" depends="init" unless="CheckDepends">
+ <if>
+ <equals arg1="${ToolChain}" arg2="msvc"/>
+ <then>
+ <exec dir="${PACKAGE_DIR}/Pccts/antlr" executable="nmake" failonerror="TRUE">
+ <arg line="/NOLOGO"/>
+ <arg line="-f AntlrMS.mak"/>
+ </exec>
+ </then>
+ <elseif>
+ <istrue value="${cygwin}"/>
+ <then>
+ <exec dir="${PACKAGE_DIR}/Pccts/antlr" executable="make" failonerror="TRUE">
+ <arg line="-f makefile.cygwin"/>
+ </exec>
+ </then>
+ </elseif>
+ <elseif>
+ <istrue value="${gcc}"/>
+ <then>
+ <exec dir="${PACKAGE_DIR}/Pccts/antlr" executable="make" failonerror="TRUE">
+ <arg line="-s"/>
+ <arg line="-f makefile BIN_DIR=${BIN_DIR}"/>
+ </exec>
+ </then>
+ </elseif>
+ </if>
+ <echo message="The EDK Tool: ${ToolName} build has completed!"/>
+ </target>
+
+ <target name="clean">
+ <echo message="Removing Intermediate Files Only"/>
+ <if>
+ <equals arg1="${ToolChain}" arg2="msvc"/>
+ <then>
+ <exec dir="${PACKAGE_DIR}/Pccts/antlr" executable="nmake" failonerror="TRUE">
+ <arg line="/C"/>
+ <arg line="/NOLOGO"/>
+ <arg line="-f AntlrMS.mak clean"/>
+ </exec>
+ </then>
+ <elseif>
+ <istrue value="${cygwin}"/>
+ <then>
+ <exec dir="${PACKAGE_DIR}/Pccts/antlr" executable="make" failonerror="TRUE">
+ <arg line="-f makefile.cygwin clean"/>
+ </exec>
+ </then>
+ </elseif>
+ <elseif>
+ <istrue value="${gcc}"/>
+ <then>
+ <exec dir="${PACKAGE_DIR}/Pccts/antlr" executable="make" failonerror="TRUE">
+ <arg line="-s"/>
+ <arg line="-f makefile clean"/>
+ </exec>
+ </then>
+ </elseif>
+ </if>
+ </target>
+
+ <target name="cleanall">
+ <echo message="Removing Object Files and the Executable: ${ToolName}${ext_exe}"/>
+ <if>
+ <equals arg1="${ToolChain}" arg2="msvc"/>
+ <then>
+ <exec dir="${PACKAGE_DIR}/Pccts/antlr" executable="nmake" failonerror="FALSE">
+ <arg line="/C"/>
+ <arg line="/NOLOGO"/>
+ <arg line="/f AntlrMS.mak clean"/>
+ </exec>
+ </then>
+ <elseif>
+ <istrue value="${cygwin}"/>
+ <then>
+ <echo message="Building antlr with cygwin gcc"/>
+ <exec dir="${PACKAGE_DIR}/Pccts/antlr" executable="make" failonerror="FALSE">
+ <arg line="-s"/>
+ <arg line="-f makefile.cygwin clean"/>
+ </exec>
+ </then>
+ </elseif>
+ <elseif>
+ <istrue value="${gcc}"/>
+ <then>
+ <echo message="Building antlr with gcc"/>
+ <exec dir="${PACKAGE_DIR}/Pccts/antlr" executable="make" failonerror="FALSE">
+ <arg line="-s"/>
+ <arg line="-f makefile clean"/>
+ </exec>
+ </then>
+ </elseif>
+ </if>
+ <delete failonerror="false" quiet="true" includeEmptyDirs="true">
+ <fileset file="${BIN_DIR}/${ToolName}${ext_exe}"/>
+ </delete>
+ </target>
+
+</project>
diff --git a/Source/Pccts/antlr/dumpcycles.c b/Source/Pccts/antlr/dumpcycles.c
new file mode 100644
index 0000000..8156159
--- /dev/null
+++ b/Source/Pccts/antlr/dumpcycles.c
@@ -0,0 +1,67 @@
+#include <stdio.h>
+#include <ctype.h>
+
+#include "set.h"
+#include "syn.h"
+#include "hash.h"
+#include "generic.h"
+
+void
+#ifdef __USE_PROTOS
+dumpcycles(void)
+#else
+dumpcycles()
+#endif
+{
+ Cycle *c;
+ CacheEntry *f;
+ ListNode *p;
+ int i=0;
+ int k;
+ int degree;
+
+ for (k=1; k <= CLL_k; k++) {
+ if (Cycles[k] == NULL) continue;
+
+ for (p = Cycles[k]->next; p!=NULL; p=p->next) {
+ c = (Cycle *) p->elem;
+ degree=set_deg(c->cyclicDep);
+ fprintf(stderr,"Cycle %d: (degree %d) %s -->\n", i++, degree, RulePtr[c->croot]->rname);
+ fprintf(stderr," *self*\n");
+ MR_dumpRuleSet(c->cyclicDep);
+ fprintf(stderr,"\n");
+ f = (CacheEntry *)
+ hash_get(Fcache,Fkey(RulePtr[c->croot]->rname,'o',k));
+ if (f == NULL) {
+ fprintf(stderr," *** FOLLOW(%s) must be in cache but isn't ***\n",
+ RulePtr[c->croot]->rname);
+ };
+ };
+ };
+}
+
+void
+#ifdef __USE_PROTOS
+dumpfostack(int k)
+#else
+dumpfostack(k)
+int k;
+#endif
+{
+ int i=0;
+ int *pi;
+
+ fprintf(stderr,"\n");
+ if (FoStack[k] == NULL) {
+ fprintf(stderr,"FoStack[%d] is null\n",k);
+ };
+ if (FoTOS[k] == NULL) {
+ fprintf(stderr,"FoTOS[%d] is null\n",k);
+ }
+ if (FoTOS[k] != NULL && FoStack[k] != NULL) {
+ for (pi=FoStack[k]; pi <= FoTOS[k]; pi++) {
+ i++;
+ fprintf(stderr,"#%d rule %d %s\n",i,*pi,RulePtr[*pi]->rname);
+ }
+ }
+}
diff --git a/Source/Pccts/antlr/dumpnode.c b/Source/Pccts/antlr/dumpnode.c
new file mode 100644
index 0000000..2a34c6f
--- /dev/null
+++ b/Source/Pccts/antlr/dumpnode.c
@@ -0,0 +1,423 @@
+#include <stdio.h>
+#include <ctype.h>
+
+#include "set.h"
+#include "syn.h"
+#include "hash.h"
+#include "generic.h"
+
+#ifdef __USE_PROTOS
+void dumpset1(set s)
+#else
+void dumpset1(s)
+ set s;
+#endif
+{
+ if (set_nil(s)) {
+ fprintf(stderr,"{}");
+ } else {
+ s_fprT(stderr,s);
+ };
+}
+
+#ifdef __USE_PROTOS
+void dumpset(set s)
+#else
+void dumpset(s)
+ set s;
+#endif
+{
+ dumpset1(s);
+ fprintf(stderr,"\n");
+}
+
+#ifdef __USE_PROTOS
+int isEndRule(Node * p)
+#else
+int isEndRule(p)
+ Node * p;
+#endif
+{
+ int result=0;
+ if ( p->ntype == nJunction &&
+ ( (Junction *) p)->jtype == EndRule) {
+ result=1;
+ };
+ return result;
+}
+
+#ifdef __USE_PROTOS
+void dumppred1(int depth,Predicate *p)
+#else
+void dumppred1(depth,p)
+ int depth;
+ Predicate *p;
+#endif
+{
+ int i;
+ int k;
+
+ for (i=0; i<depth ; i++) {
+ fprintf(stderr," ");
+ };
+ if (p->expr == PRED_AND_LIST ||
+ p->expr == PRED_OR_LIST) {
+ fprintf(stderr," %s", (p->expr == NULL ? "null expr" : p->expr));
+ if (p->inverted) fprintf(stderr," predicate inverted !");
+ if (p->redundant) {
+ fprintf(stderr," Redundant!");
+ };
+ if (p->isConst) fprintf(stderr," const %d !",p->constValue);
+ fprintf(stderr,"\n");
+ } else {
+ fprintf(stderr,"predicate k=%d",p->k);
+ k=set_int(p->completionSet);
+ if (k >= 0) {
+ fprintf(stderr," Incomplete Set=%d !",k);
+ };
+ k=set_int(p->completionTree);
+ if (k >= 0) {
+ fprintf(stderr," Incomplete Tree=%d !",k);
+ };
+ if (p->redundant) {
+ fprintf(stderr," Redundant!");
+ };
+ fprintf(stderr," \"%s\" (%x)", (p->expr == NULL ? "null expr" : p->expr) ,p);
+ if (p->source != NULL) {
+ fprintf(stderr,"line %d",p->source->line);
+ };
+ if (p->inverted) fprintf(stderr," predicate inverted !");
+ fprintf(stderr,"\n");
+ for (i=0; i<depth ; i++) {
+ fprintf(stderr," ");
+ };
+ fprintf(stderr,"scontext: ");
+ dumpset(p->scontext[1]);
+ for (i=0; i<depth ; i++) {
+ fprintf(stderr," ");
+ };
+ fprintf(stderr,"tcontext: ");
+ preorder(p->tcontext);
+ fprintf(stderr,"\n");
+ };
+ fprintf(stderr,"\n");
+ if (p->down != NULL) {
+ dumppred1(depth+1,p->down);
+ };
+ if (p->right != NULL) {
+ dumppred1(depth,p->right);
+ };
+}
+
+#ifdef __USE_PROTOS
+void dumppred(Predicate *p)
+#else
+void dumppred(p)
+ Predicate *p;
+#endif
+{
+ fprintf(stderr,"---------------------------------\n");
+ dumppred1(0,p);
+ fprintf(stderr,"\n");
+}
+
+#ifdef __USE_PROTOS
+void dumppredtree(Predicate *p)
+#else
+void dumppredtree(p)
+ Predicate *p;
+#endif
+{
+ fprintf(stderr,"predicate k=%d \"%s\" line %d\n",p->k,p->expr,p->source->line);
+ dumpset(p->scontext[1]);
+}
+
+#ifdef __USE_PROTOS
+void dumppredexpr(Predicate *p)
+#else
+void dumppredexpr(p)
+ Predicate *p;
+#endif
+{
+ fprintf(stderr," pred expr \"%s\"\n",p->expr);
+}
+
+#ifdef __USE_PROTOS
+void dt(Tree *t)
+#else
+void dt(t)
+ Tree *t;
+#endif
+{
+ MR_dumpTreeF(stderr,0,t,5);
+}
+
+#ifdef __USE_PROTOS
+void d(Node * p)
+#else
+void d(p)
+ Node * p;
+#endif
+{
+
+ Junction *j;
+ RuleRefNode *r;
+ TokNode *t;
+ ActionNode *a;
+
+ if (p==NULL) {
+ fprintf(stderr,"dumpNode: Node is NULL");
+ return;
+ };
+
+ switch (p->ntype) {
+ case nJunction :
+ j = (Junction *) p;
+ fprintf(stderr, "Junction (#%d in rule %s line %d) ",j->seq,j->rname,j->line);
+ if (j->guess) fprintf(stderr,"guess block ");
+ switch (j->jtype ) {
+ case aSubBlk :
+ fprintf(stderr,"aSubBlk");
+ break;
+ case aOptBlk :
+ fprintf(stderr,"aOptBlk");
+ break;
+ case aLoopBegin :
+ fprintf(stderr,"aLoopBeginBlk");
+ break;
+ case aLoopBlk :
+ fprintf(stderr,"aLoopBlk");
+ break;
+ case aPlusBlk :
+ fprintf(stderr,"aPlusBlk");
+ break;
+ case EndBlk :
+ fprintf(stderr,"EndBlk");
+ break;
+ case RuleBlk :
+ fprintf(stderr,"RuleBlk");
+ break;
+ case Generic :
+ fprintf(stderr,"Generic");
+ break;
+ case EndRule :
+ fprintf(stderr,"EndRule");
+ break;
+ };
+ if (j->halt) fprintf(stderr," halt!");
+ if (j->p1) fprintf(stderr," p1 valid");
+ if (j->p2) {
+ if (j->p2->ntype == nJunction) {
+ fprintf(stderr," (p2=#%d)",( (Junction *) j->p2)->seq);
+ } else {
+ fprintf(stderr," (p2 valid)");
+ };
+ };
+ if (j->ignore) fprintf(stderr, " ignore/plus-block-bypass");
+ if (j->fset != NULL && set_deg(*j->fset) != 0) {
+ fprintf(stderr,"\nfset:\n");
+ dumpset(*j->fset);
+ };
+ if (j->ftree != NULL) {
+ fprintf(stderr,"\nftree:\n");
+ preorder(j->ftree);
+ };
+ fprintf(stderr,"\n");
+ break;
+ case nRuleRef :
+ r = (RuleRefNode *) p;
+ fprintf(stderr, "RuleRefNode (in rule %s line %d) to rule %s\n", r->rname,r->line,r->text);
+ break;
+ case nToken :
+ t = (TokNode *) p;
+ fprintf(stderr, "TokNode (in rule %s line %d) token %s\n",t->rname,t->line,TerminalString(t->token));
+ break;
+ case nAction :
+ a =(ActionNode *) p;
+ if (a->is_predicate) {
+ fprintf(stderr, "Predicate (in rule %s line %d) %s",a->rname,a->line,a->action);
+ if (a->inverted) fprintf(stderr," action inverted !");
+ if (a->guardpred != NULL) {
+ fprintf(stderr," guarded");
+ dumppredexpr(a->guardpred);
+ if (a->ampersandPred) {
+ fprintf(stderr," \"&&\" style");
+ } else {
+ fprintf(stderr," \"=>\" style");
+ };
+ };
+ if (a->predEntry != NULL) fprintf(stderr," predEntry \"%s\" ",a->predEntry->str);
+ fprintf(stderr,"\n");
+ } else if (a->init_action) {
+ fprintf(stderr, "Init-Action (in rule %s line %d) %s\n",a->rname,a->line,a->action);
+ } else {
+ fprintf(stderr, "Action (in rule %s line %d) %s\n",a->rname,a->line,a->action);
+ };
+ break;
+ };
+}
+
+#ifdef __USE_PROTOS
+Node * dp1(Node * p)
+#else
+Node * dp1(p)
+ Node * p;
+#endif
+{
+ Node *result=NULL;
+
+ if (p->ntype == nJunction) {
+ result=( (Junction *) p )->p1;
+ d(result);
+ } else {
+ fprintf(stderr,"dp1: Not a Junction node");
+ };
+ return result;
+}
+
+#ifdef __USE_PROTOS
+Node * dp2(Node * p)
+#else
+Node * dp2(p)
+ Node * p;
+#endif
+{
+ Node *result=NULL;
+
+ if (p->ntype == nJunction) {
+ result=( (Junction *) p )->p2;
+ d(result);
+ } else {
+ fprintf(stderr,"dp2: Not a Junction node");
+ };
+ return result;
+}
+
+#ifdef __USE_PROTOS
+Node * dn(Node * p)
+#else
+Node * dn(p)
+ Node * p;
+#endif
+
+{
+ Node *result=NULL;
+
+ if (p->ntype == nRuleRef) {
+ result=( (RuleRefNode *)p )->next;
+ } else if (p->ntype == nAction) {
+ result=( (ActionNode *)p )->next;
+ } else if (p->ntype == nToken) {
+ result=( (TokNode *)p )->next;
+ } else {
+ fprintf(stderr,"No next field: Neither a RuleRefNode, ActionNode, nor TokNode");
+ };
+ if (result != NULL) d(result);
+ return result;
+}
+
+#ifdef __USE_PROTOS
+void df(Node * p)
+#else
+void df(p)
+ Node * p;
+#endif
+{
+ int count=0;
+ Node *next;
+
+ fprintf(stderr,"\n#%d ",++count);
+ d(p);
+
+ for (next=p; next != NULL && !isEndRule(next) ; ) {
+ fprintf(stderr,"#%d ",++count);
+ if (next->ntype == nJunction) {
+ next=dp1(next);
+ } else {
+ next=dn(next);
+ };
+ };
+}
+
+#ifdef __USE_PROTOS
+Node * dfn(Node * p,int target)
+#else
+Node * dfn(p,target)
+ Node * p;
+ int target;
+#endif
+{
+ Node *result=NULL;
+ int count=0;
+ Node *next;
+
+ fprintf(stderr,"#%d ",++count);
+ d(p);
+
+ for (next=p; next != NULL && !isEndRule(next) ; ) {
+ fprintf(stderr,"#%d ",++count);
+ if (next->ntype == nJunction) {
+ next=dp1(next);
+ } else {
+ next=dn(next);
+ };
+ if (count == target) {
+ result=next;
+ break;
+ };
+ };
+ return result;
+}
+
+
+static int findnodeMatch;
+
+#ifdef __USE_PROTOS
+Junction *findnode1(Node *n)
+#else
+Junction *findnode1(n)
+ Node *n;
+#endif
+{
+ Node *next;
+ Junction *j;
+ Junction *match;
+
+ if (n == NULL) return NULL;
+ if (n->ntype == nJunction) {
+ j=(Junction *) n;
+ if (j->seq == findnodeMatch) return j;
+ if (j->jtype == EndRule) return NULL;
+ if (j->jtype != RuleBlk && j->jtype != EndBlk) {
+ if (j->p2 != NULL && !j->ignore) {
+ match=findnode1(j->p2);
+ if (match != NULL) return match;
+ };
+ };
+ };
+ next=MR_advance(n);
+ return findnode1(next);
+}
+
+#ifdef __USE_PROTOS
+Junction *findnode(int match)
+#else
+Junction *findnode(match)
+ int match;
+#endif
+{
+ Junction *j;
+ Junction *result=NULL;
+
+ findnodeMatch=match;
+
+ for (j=SynDiag; j != NULL; j=(Junction *)j->p2) {
+ require (j->ntype == nJunction && j->jtype == RuleBlk,"Not a rule block");
+ result=findnode1( (Node *) j);
+ if (result != NULL) break;
+ };
+ if (result != NULL) {
+ d( (Node *) result);
+ };
+ return result;
+}
diff --git a/Source/Pccts/antlr/egman.c b/Source/Pccts/antlr/egman.c
new file mode 100644
index 0000000..c8a633f
--- /dev/null
+++ b/Source/Pccts/antlr/egman.c
@@ -0,0 +1,328 @@
+/*
+ * egman.c
+ *
+ * SOFTWARE RIGHTS
+ *
+ * We reserve no LEGAL rights to the Purdue Compiler Construction Tool
+ * Set (PCCTS) -- PCCTS is in the public domain. An individual or
+ * company may do whatever they wish with source code distributed with
+ * PCCTS or the code generated by PCCTS, including the incorporation of
+ * PCCTS, or its output, into commerical software.
+ *
+ * We encourage users to develop software with PCCTS. However, we do ask
+ * that credit is given to us for developing PCCTS. By "credit",
+ * we mean that if you incorporate our source code into one of your
+ * programs (commercial product, research project, or otherwise) that you
+ * acknowledge this fact somewhere in the documentation, research report,
+ * etc... If you like PCCTS and have developed a nice tool with the
+ * output, please mention that you developed it using PCCTS. In
+ * addition, we ask that this header remain intact in our source code.
+ * As long as these guidelines are kept, we expect to continue enhancing
+ * this system and expect to make other tools available as they are
+ * completed.
+ *
+ * ANTLR 1.33MR10
+ * 2001
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "set.h"
+#include "syn.h"
+#include "hash.h"
+#include "generic.h"
+#include "proto.h"
+
+static ExceptionGroup **egArray=NULL; /* ExceptionGroup by BlkLevel */
+static LabelEntry **leArray=NULL; /* LabelEntry by BlkLevel */
+static Junction **altArray=NULL; /* start of alternates */
+static int arraySize=0;
+static int highWater=0;
+static ExceptionGroup *lastEG=NULL; /* used in altFixup() */
+static int lastBlkLevel=0; /* used in altFixup() */
+
+#ifdef __USE_PROTOS
+static void arrayCheck(void);
+#else
+static void arrayCheck();
+#endif
+
+/* Called to add an exception group for an alternative EG */
+
+#ifdef __USE_PROTOS
+void egAdd(ExceptionGroup * eg)
+#else
+void egAdd(eg)
+ExceptionGroup *eg;
+#endif
+{
+ int i;
+
+ ExceptionGroup *nextEG;
+ ExceptionGroup *innerEG;
+
+ LabelEntry *nextLE;
+ LabelEntry *innerLE;
+
+ Junction *nextAlt;
+ Junction *innerAlt;
+
+ lastEG=eg;
+ lastBlkLevel=BlkLevel;
+
+ arrayCheck();
+ eg->pendingLink=egArray[BlkLevel];
+ egArray[BlkLevel]=eg;
+
+ /* EG for alternates already have their altID filled in */
+
+ for (i=BlkLevel+1; i<=highWater ; i++) {
+ for (innerEG=egArray[i]; innerEG != NULL ; innerEG=nextEG) {
+ nextEG=innerEG->pendingLink;
+ innerEG->pendingLink=NULL;
+ innerEG->outerEG=eg;
+ };
+ egArray[i]=NULL;
+ };
+
+ /*
+ * for patching up the LabelEntry you might use an EG for the
+ * current alternative - unlike patching up an alternative EG
+ * i.e. start the loop at BlkLevel rather than (BlkLevel+1)
+ * fill it in only if the EG and the LE are for the very
+ * same alternative if they're at the same BlkLevel
+ * it's easier to leave the LE on this list (filled in) rather than
+ * trying to selectively remove it. It will eventually be
+ * removed anyway when the BlkLevel gets small enough.
+ */
+
+ for (i=BlkLevel; i<=highWater ; i++) {
+ for (innerLE=leArray[i]; innerLE != NULL ; innerLE=nextLE) {
+ nextLE=innerLE->pendingLink;
+ if (BlkLevel != i ||
+ innerLE->curAltNum == CurAltNum_array[BlkLevel]) {
+ if (innerLE->outerEG == NULL) {
+ innerLE->outerEG=eg;
+ };
+ };
+ };
+ if (BlkLevel != i) leArray[i]=NULL;
+ };
+
+/*
+ * For the start of alternatives it is necessary to make a
+ * distinction between the exception group for the current
+ * alternative and the "fallback" EG for the block which
+ * contains the alternative
+ *
+ * The fallback outerEG is used to handle the case where
+ * no alternative of a block matches. In that case the
+ * signal is "NoViableAlt" (or "NoSemViableAlt" and the
+ * generator needs the EG of the block CONTAINING the
+ * current one.
+ *
+ * rule: ( ( ( a
+ * | b
+ * )
+ * | c
+ * )
+ * | d
+ * );
+ */
+
+ for (i=BlkLevel; i <= highWater ; i++) {
+ for (innerAlt=altArray[i]; innerAlt != NULL ; innerAlt=nextAlt) {
+ nextAlt=innerAlt->pendingLink;
+
+ /* first fill in the EG for the current alternative */
+ /* but leave it on the list in order to get the fallback EG */
+ /* if the EG is at the same LEVEL as the alternative then */
+ /* fill it in only if in the very same alternative */
+ /* */
+ /* rule: ( a */
+ /* | b */
+ /* | c exception ... */
+ /* ) */
+ /* */
+ /* if the EG is outside the alternative (e.g. BlkLevel < i) */
+ /* then it doesn't matter about the alternative */
+ /* */
+ /* rule: ( a */
+ /* | b */
+ /* | c */
+ /* ) exception ... */
+ /* */
+
+#if 0
+ printf("BlkLevel=%d i=%d altnum=%d CurAltNum=%d altID=%s\n",
+ BlkLevel,i,innerAlt->curAltNum,CurAltNum_array[BlkLevel],eg->altID);
+#endif
+ if (BlkLevel != i ||
+ innerAlt->curAltNum == CurAltNum_array[BlkLevel]) {
+ if (innerAlt->exception_label == NULL) {
+ innerAlt->exception_label=eg->altID;
+ };
+ };
+
+ /* ocurs at a later pass then for the exception_label */
+ /* if an outerEG has been found then fill in the outer EG */
+ /* remove if from the list when the BlkLevel gets smaller */
+
+ if (BlkLevel != i) {
+ if (innerAlt->outerEG == NULL) {
+ innerAlt->outerEG=eg;
+ };
+ };
+ };
+ if (BlkLevel != i) altArray[i]=NULL;
+ };
+}
+
+#ifdef __USE_PROTOS
+void leAdd(LabelEntry * le)
+#else
+void leAdd(le)
+LabelEntry *le;
+#endif
+
+{
+ arrayCheck();
+ le->pendingLink=leArray[BlkLevel];
+ le->curAltNum=CurAltNum_array[BlkLevel];
+ leArray[BlkLevel]=le;
+}
+
+#ifdef __USE_PROTOS
+void altAdd(Junction *alt)
+#else
+void altAdd(alt)
+Junction *alt;
+#endif
+
+{
+ arrayCheck();
+#if 0
+ printf("BlkLevel=%d CurAltNum=%d\n",
+ BlkLevel,CurAltNum_array[BlkLevel]);
+#endif
+ alt->curAltNum=CurAltNum_array[BlkLevel];
+ alt->pendingLink=altArray[BlkLevel];
+ altArray[BlkLevel]=alt;
+}
+
+static void
+#ifdef __USE_PROTOS
+arrayCheck(void)
+#else
+arrayCheck()
+#endif
+{
+ ExceptionGroup **egArrayNew;
+ LabelEntry **leArrayNew;
+ Junction **altArrayNew;
+ int arraySizeNew;
+ int i;
+
+ if (BlkLevel > highWater) highWater=BlkLevel;
+
+ if (BlkLevel >= arraySize) {
+ arraySizeNew=BlkLevel+5; /* MR20 */
+ egArrayNew=(ExceptionGroup **)
+ calloc(arraySizeNew,sizeof(ExceptionGroup *));
+ leArrayNew=(LabelEntry **)
+ calloc(arraySizeNew,sizeof(LabelEntry *));
+ altArrayNew=(Junction **)
+ calloc(arraySizeNew,sizeof(Junction *));
+ for (i=0; i<arraySize ; i++) {
+ egArrayNew[i]=egArray[i];
+ leArrayNew[i]=leArray[i];
+ altArrayNew[i]=altArray[i];
+ };
+ arraySize=arraySizeNew;
+ if (egArray != NULL) free( (char *) egArray);
+ if (leArray != NULL) free( (char *) leArray);
+ if (altArray != NULL) free( (char *) altArray);
+ egArray=egArrayNew;
+ leArray=leArrayNew;
+ altArray=altArrayNew;
+ };
+}
+
+/* always call leFixup() BEFORE egFixup() */
+
+void
+#ifdef __USE_PROTOS
+egFixup(void)
+#else
+egFixup()
+#endif
+{
+ int i;
+ ExceptionGroup *nextEG;
+ ExceptionGroup *innerEG;
+
+ for (i=1; i<=highWater ; i++) {
+ for (innerEG=egArray[i]; innerEG != NULL ; innerEG=nextEG) {
+ nextEG=innerEG->pendingLink;
+ innerEG->pendingLink=NULL;
+ };
+ egArray[i]=NULL;
+ };
+ lastEG=NULL;
+ lastBlkLevel=0;
+}
+
+/* always call leFixup() BEFORE egFixup() */
+
+#ifdef __USE_PROTOS
+void leFixup(void)
+#else
+void leFixup()
+#endif
+{
+
+ int i;
+ LabelEntry *nextLE;
+ LabelEntry *innerLE;
+
+ for (i=BlkLevel; i<=highWater ; i++) {
+ for (innerLE=leArray[i]; innerLE != NULL ; innerLE=nextLE) {
+ nextLE=innerLE->pendingLink;
+ innerLE->pendingLink=NULL;
+ };
+ leArray[i]=NULL;
+ };
+}
+
+/* always call altFixup() BEFORE egFixup() */
+
+#ifdef __USE_PROTOS
+void altFixup(void)
+#else
+void altFixup()
+#endif
+{
+
+ int i;
+ Junction *nextAlt;
+ Junction *innerAlt;
+
+ for (i=BlkLevel; i<=highWater ; i++) {
+ for (innerAlt=altArray[i]; innerAlt != NULL ; innerAlt=nextAlt) {
+
+ /* if an outerEG has been found then fill in the outer EG */
+
+ if (lastBlkLevel <= i) {
+ if (innerAlt->outerEG == NULL) {
+ innerAlt->outerEG=lastEG;
+ };
+ };
+ nextAlt=innerAlt->pendingLink;
+ innerAlt->pendingLink=NULL;
+ };
+ altArray[i]=NULL;
+ };
+}
+
diff --git a/Source/Pccts/antlr/err.c b/Source/Pccts/antlr/err.c
new file mode 100644
index 0000000..ca23939
--- /dev/null
+++ b/Source/Pccts/antlr/err.c
@@ -0,0 +1,538 @@
+/*
+ * A n t l r S e t s / E r r o r F i l e H e a d e r
+ *
+ * Generated from: antlr.g
+ *
+ * Terence Parr, Russell Quong, Will Cohen, and Hank Dietz: 1989-2001
+ * Parr Research Corporation
+ * with Purdue University Electrical Engineering
+ * With AHPCRC, University of Minnesota
+ * ANTLR Version 1.33MR33
+ */
+
+#define ANTLR_VERSION 13333
+#include "pcctscfg.h"
+#include "pccts_stdio.h"
+
+#include "pcctscfg.h"
+#include "set.h"
+#include <ctype.h>
+#include "syn.h"
+#include "hash.h"
+#include "generic.h"
+#define zzcr_attr(attr,tok,t)
+#define zzSET_SIZE 20
+#include "antlr.h"
+#include "tokens.h"
+#include "dlgdef.h"
+#include "err.h"
+
+ANTLRChar *zztokens[157]={
+ /* 00 */ "Invalid",
+ /* 01 */ "Eof",
+ /* 02 */ "QuotedTerm",
+ /* 03 */ "\\n|\\r|\\r\\n",
+ /* 04 */ "\\(\\n|\\r|\\r\\n)",
+ /* 05 */ "\\~[]",
+ /* 06 */ "~[\\n\\r\"\\]+",
+ /* 07 */ "\"",
+ /* 08 */ "\\n|\\r|\\r\\n",
+ /* 09 */ "\\(\\n|\\r|\\r\\n)",
+ /* 10 */ "\\~[]",
+ /* 11 */ "~[\\n\\r\"\\]+",
+ /* 12 */ "'",
+ /* 13 */ "\\n|\\r|\\r\\n",
+ /* 14 */ "\\~[]",
+ /* 15 */ "~[\\n\\r'\\]+",
+ /* 16 */ "\\*/",
+ /* 17 */ "\\*",
+ /* 18 */ "\\n|\\r|\\r\\n",
+ /* 19 */ "~[\\n\\r\\*]+",
+ /* 20 */ "\\*/",
+ /* 21 */ "\\*",
+ /* 22 */ "\\n|\\r|\\r\\n",
+ /* 23 */ "~[\\n\\r\\*]+",
+ /* 24 */ "\\n|\\r|\\r\\n",
+ /* 25 */ "~[\\n\\r]+",
+ /* 26 */ "\\n|\\r|\\r\\n",
+ /* 27 */ "~[\\n\\r]+",
+ /* 28 */ "\\n|\\r|\\r\\n",
+ /* 29 */ "~[\\n\\r]+",
+ /* 30 */ "\\*/",
+ /* 31 */ "\\*",
+ /* 32 */ "\\n|\\r|\\r\\n",
+ /* 33 */ "~[\\n\\r\\*]+",
+ /* 34 */ "Action",
+ /* 35 */ "Pred",
+ /* 36 */ "PassAction",
+ /* 37 */ "consumeUntil\\( [\\ \\t]* \\{~[\\}]+\\} [\\ \\t]* \\)",
+ /* 38 */ "consumeUntil\\( ~[\\)]+ \\)",
+ /* 39 */ "\\n|\\r|\\r\\n",
+ /* 40 */ "\\>",
+ /* 41 */ "$",
+ /* 42 */ "$$",
+ /* 43 */ "$\\[\\]",
+ /* 44 */ "$\\[",
+ /* 45 */ "$[0-9]+",
+ /* 46 */ "$[0-9]+.",
+ /* 47 */ "$[0-9]+.[0-9]+",
+ /* 48 */ "$[_a-zA-Z][_a-zA-Z0-9]*",
+ /* 49 */ "#0",
+ /* 50 */ "#\\[\\]",
+ /* 51 */ "#\\(\\)",
+ /* 52 */ "#[0-9]+",
+ /* 53 */ "#line[\\ \\t]* [0-9]+ {[\\ \\t]* \"~[\"]+\" ([\\ \\t]* [0-9]*)* } (\\n|\\r|\\r\\n)",
+ /* 54 */ "#line ~[\\n\\r]* (\\n|\\r|\\r\\n)",
+ /* 55 */ "#[_a-zA-Z][_a-zA-Z0-9]*",
+ /* 56 */ "#\\[",
+ /* 57 */ "#\\(",
+ /* 58 */ "#",
+ /* 59 */ "\\)",
+ /* 60 */ "\\[",
+ /* 61 */ "\\(",
+ /* 62 */ "\\\\]",
+ /* 63 */ "\\\\)",
+ /* 64 */ "\\>",
+ /* 65 */ "'",
+ /* 66 */ "\"",
+ /* 67 */ "\\$",
+ /* 68 */ "\\#",
+ /* 69 */ "\\(\\n|\\r|\\r\\n)",
+ /* 70 */ "\\~[\\]\\)>$#]",
+ /* 71 */ "/",
+ /* 72 */ "/\\*",
+ /* 73 */ "\\*/",
+ /* 74 */ "//",
+ /* 75 */ "~[\\n\\r\\)\\(\\$#\\>\\]\\[\"'/]+",
+ /* 76 */ "[\\t\\ ]+",
+ /* 77 */ "\\n|\\r|\\r\\n",
+ /* 78 */ "\\[",
+ /* 79 */ "\\<\\<",
+ /* 80 */ "\"",
+ /* 81 */ "/\\*",
+ /* 82 */ "\\*/",
+ /* 83 */ "//",
+ /* 84 */ "#line[\\ \\t]* [0-9]+ {[\\ \\t]* \"~[\"]+\" ([\\ \\t]* [0-9]*)* } (\\n|\\r|\\r\\n)",
+ /* 85 */ "#line ~[\\n\\r]* (\\n|\\r|\\r\\n)",
+ /* 86 */ "\\>\\>",
+ /* 87 */ "WildCard",
+ /* 88 */ "\\@",
+ /* 89 */ "LABEL",
+ /* 90 */ "grammar-element",
+ /* 91 */ "meta-symbol",
+ /* 92 */ "Pragma",
+ /* 93 */ "FirstSetSymbol",
+ /* 94 */ "{\\}#header",
+ /* 95 */ "{\\}#first",
+ /* 96 */ "{\\}#parser",
+ /* 97 */ "{\\}#tokdefs",
+ /* 98 */ "\\}",
+ /* 99 */ "class",
+ /* 100 */ "NonTerminal",
+ /* 101 */ "TokenTerm",
+ /* 102 */ "\\{",
+ /* 103 */ "!",
+ /* 104 */ "\\<",
+ /* 105 */ "\\>",
+ /* 106 */ ":",
+ /* 107 */ ";",
+ /* 108 */ "{\\}#lexaction",
+ /* 109 */ "{\\}#lexmember",
+ /* 110 */ "{\\}#lexprefix",
+ /* 111 */ "{\\}#pred",
+ /* 112 */ "\\|\\|",
+ /* 113 */ "&&",
+ /* 114 */ "\\(",
+ /* 115 */ "\\)",
+ /* 116 */ "{\\}#lexclass",
+ /* 117 */ "{\\}#errclass",
+ /* 118 */ "{\\}#tokclass",
+ /* 119 */ "..",
+ /* 120 */ "{\\}#token",
+ /* 121 */ "=",
+ /* 122 */ "[0-9]+",
+ /* 123 */ "\\|",
+ /* 124 */ "\\~",
+ /* 125 */ "^",
+ /* 126 */ "approx",
+ /* 127 */ "LL\\(1\\)",
+ /* 128 */ "LL\\(2\\)",
+ /* 129 */ "\\*",
+ /* 130 */ "\\+",
+ /* 131 */ "?",
+ /* 132 */ "=>",
+ /* 133 */ "exception",
+ /* 134 */ "default",
+ /* 135 */ "catch",
+ /* 136 */ "{\\}#[A-Za-z0-9_]*",
+ /* 137 */ "[\\t\\ ]+",
+ /* 138 */ "\\n|\\r|\\r\\n",
+ /* 139 */ "//",
+ /* 140 */ "/\\*",
+ /* 141 */ "#ifdef",
+ /* 142 */ "#if",
+ /* 143 */ "#ifndef",
+ /* 144 */ "#else",
+ /* 145 */ "#endif",
+ /* 146 */ "#undef",
+ /* 147 */ "#import",
+ /* 148 */ "ID",
+ /* 149 */ "#define",
+ /* 150 */ "INT",
+ /* 151 */ "enum",
+ /* 152 */ "\\{",
+ /* 153 */ "=",
+ /* 154 */ ",",
+ /* 155 */ "\\}",
+ /* 156 */ ";"
+};
+SetWordType zzerr1[20] = {0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0,
+ 0x30,0x0,0x0,0x0, 0x0,0x0,0x0,0x0};
+SetWordType zzerr2[20] = {0xfc,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xf3,
+ 0xbf,0xff,0xff,0xff, 0xff,0xff,0xff,0x1f};
+SetWordType zzerr3[20] = {0xfc,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xfb,
+ 0x3b,0xf7,0xf7,0xc7, 0xff,0xff,0xff,0x1f};
+SetWordType zzerr4[20] = {0x4,0x0,0x0,0x0, 0x10,0x0,0x0,0x0, 0x0,0x0,0x0,0x0,
+ 0x80,0x7,0x0,0x0, 0x0,0x0,0x0,0x0};
+SetWordType setwd1[157] = {0x0,0x50,0xa0,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x6a,0x20,0xa0,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x0,0x0,0x20,0x20,0x21,
+ 0x21,0x21,0x21,0x6e,0x6e,0x64,0x20,0x0,
+ 0x20,0xa0,0xa0,0xa0,0x20,0x6a,0x6a,0x6a,
+ 0x6e,0x20,0x20,0x20,0x20,0x66,0x6e,0x6e,
+ 0x20,0x66,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x62,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x20};
+SetWordType zzerr5[20] = {0x0,0x0,0x0,0x0, 0x10,0x0,0x0,0x0, 0x0,0x0,0x0,0x0,
+ 0x0,0x1,0x0,0x0, 0x0,0x0,0x0,0x0};
+SetWordType zzerr6[20] = {0x4,0x0,0x0,0x0, 0x10,0x0,0x0,0x0, 0x0,0x0,0x0,0x0,
+ 0x0,0x7,0x0,0x0, 0x0,0x0,0x0,0x0};
+SetWordType zzerr7[20] = {0x4,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0,
+ 0x0,0x6,0x0,0x0, 0x0,0x0,0x0,0x0};
+SetWordType zzerr8[20] = {0x4,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0,
+ 0x0,0x4,0x0,0x0, 0x0,0x0,0x0,0x0};
+SetWordType zzerr9[20] = {0x2,0x0,0x0,0x0, 0x4,0x0,0x0,0x0, 0x0,0x0,0x0,0x0,
+ 0x1c,0xf0,0x70,0x1, 0x20,0x0,0x0,0x0};
+SetWordType setwd2[157] = {0x0,0xf8,0x6,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0xf8,0x0,0x1,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0xf8,0xf8,0xf8,0x0,0x0,
+ 0x0,0x1,0x2,0x6,0x0,0xf8,0xf8,0xf8,
+ 0xf8,0x0,0x0,0x0,0x0,0xf8,0xf8,0xf8,
+ 0x0,0xf8,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0xe8,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0};
+SetWordType zzerr10[20] = {0x2,0x0,0x0,0x0, 0x4,0x0,0x0,0x0, 0x0,0x0,0x0,0x0,
+ 0xbc,0xf8,0x74,0x1, 0x20,0x0,0x0,0x0};
+SetWordType zzerr11[20] = {0x0,0x0,0x0,0x0, 0x8,0x0,0x0,0x0, 0x0,0x0,0x0,0x0,
+ 0xa0,0x0,0x4,0x0, 0x0,0x0,0x0,0x0};
+SetWordType zzerr12[20] = {0x2,0x0,0x0,0x0, 0x4,0x0,0x0,0x0, 0x0,0x0,0x0,0x0,
+ 0x1c,0xf8,0x70,0x1, 0x20,0x0,0x0,0x0};
+SetWordType zzerr13[20] = {0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0,
+ 0xa0,0x0,0x4,0x0, 0x0,0x0,0x0,0x0};
+SetWordType setwd3[157] = {0x0,0xfa,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0xfa,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0xfa,0xfa,0xfa,0x5,0x0,
+ 0x5,0x0,0x0,0x0,0xe2,0xfa,0xfa,0xfa,
+ 0xfa,0xc0,0x80,0x5,0xe0,0xfa,0xfa,0xfa,
+ 0x0,0xfa,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0xfa,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0};
+SetWordType zzerr14[20] = {0x4,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0,
+ 0x20,0x0,0x0,0x0, 0x0,0x0,0x0,0x0};
+SetWordType zzerr15[20] = {0x4,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0,
+ 0x30,0x0,0x0,0x0, 0x0,0x0,0x0,0x0};
+SetWordType zzerr16[20] = {0x4,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0,
+ 0x30,0x0,0x0,0x0, 0x0,0x0,0x0,0x0};
+SetWordType zzerr17[20] = {0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0,
+ 0x40,0x0,0x4,0x0, 0x0,0x0,0x0,0x0};
+SetWordType zzerr18[20] = {0x4,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0,
+ 0x24,0x0,0x80,0x0, 0x0,0x0,0x0,0x0};
+SetWordType zzerr19[20] = {0x4,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0,
+ 0x20,0x0,0x0,0x0, 0x0,0x0,0x0,0x0};
+SetWordType zzerr20[20] = {0x6,0x0,0x0,0x0, 0x4,0x0,0x0,0x0, 0x0,0x0,0x0,0x0,
+ 0x1c,0xf8,0x74,0x3, 0x20,0x0,0x0,0x0};
+SetWordType zzerr21[20] = {0x6,0x0,0x0,0x0, 0x4,0x0,0x0,0x0, 0x0,0x0,0x0,0x0,
+ 0x1c,0xf8,0x70,0x3, 0x20,0x0,0x0,0x0};
+SetWordType setwd4[157] = {0x0,0xe5,0xda,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0xe5,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0xed,0xe5,0xe7,0x1a,0x0,
+ 0x0,0x0,0x0,0x0,0xc0,0xe5,0xe5,0xe5,
+ 0xe5,0x0,0x0,0x0,0x0,0xe5,0xe5,0xe5,
+ 0x0,0xe5,0x40,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0xe5,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0};
+SetWordType zzerr22[20] = {0x6,0x0,0x0,0x0, 0x4,0x0,0x0,0x0, 0x0,0x0,0x0,0x0,
+ 0x3c,0xf8,0x70,0x1, 0x20,0x0,0x0,0x0};
+SetWordType zzerr23[20] = {0x6,0x0,0x0,0x0, 0x4,0x0,0x0,0x0, 0x0,0x0,0x0,0x0,
+ 0x1c,0xf8,0x70,0x1, 0x20,0x0,0x0,0x0};
+SetWordType zzerr24[20] = {0x2,0x0,0x0,0x0, 0x4,0x0,0x0,0x0, 0x0,0x0,0x0,0x0,
+ 0x1c,0xf8,0x70,0x1, 0x20,0x0,0x0,0x0};
+SetWordType zzerr25[20] = {0x2,0x0,0x0,0x0, 0x4,0x0,0x0,0x0, 0x0,0x0,0x0,0x0,
+ 0x1c,0xf8,0x70,0x1, 0x20,0x0,0x0,0x0};
+SetWordType zzerr26[20] = {0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x5,
+ 0x4,0x8,0x8,0x18, 0x20,0x0,0x0,0x0};
+SetWordType setwd5[157] = {0x0,0x1f,0xc1,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0xdf,0xc0,0xc0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0xc0,0x0,0xc0,0x0,0x0,0xc0,0xc0,0x0,
+ 0x0,0x0,0x0,0x7f,0x1f,0xdf,0xc0,0xc0,
+ 0x0,0x0,0xc0,0x0,0x67,0x1f,0x1f,0x1f,
+ 0x1f,0x0,0x0,0xc0,0x60,0x1f,0x1f,0x1f,
+ 0x0,0x1f,0x0,0x0,0x40,0xc0,0x0,0x0,
+ 0x0,0x0,0xc0,0xc0,0x0,0x0,0x5f,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0};
+SetWordType zzerr27[20] = {0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x4,
+ 0x0,0x0,0x0,0x10, 0x0,0x0,0x0,0x0};
+SetWordType zzerr28[20] = {0x4,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x80,0x2,
+ 0x30,0x0,0x0,0x0, 0x0,0x0,0x0,0x0};
+SetWordType zzerr29[20] = {0x4,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0,
+ 0x20,0x0,0x0,0x0, 0x0,0x0,0x0,0x0};
+SetWordType zzerr30[20] = {0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0xd,
+ 0x0,0x0,0x80,0x0, 0x20,0x0,0x0,0x0};
+SetWordType zzerr31[20] = {0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0xd,
+ 0x0,0x0,0x0,0x0, 0x20,0x0,0x0,0x0};
+SetWordType zzerr32[20] = {0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x5,
+ 0x4,0x8,0x8,0x18, 0x20,0x0,0x0,0x0};
+SetWordType zzerr33[20] = {0x4,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0,
+ 0x20,0x0,0x0,0x0, 0x0,0x0,0x0,0x0};
+SetWordType setwd6[157] = {0x0,0x0,0xfd,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0xe1,0xe1,0xe1,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0xfd,0x60,0xe9,0x0,0x0,0xe1,0xe1,0x0,
+ 0x0,0x0,0x0,0xe2,0x0,0xfd,0xfd,0xe1,
+ 0x20,0x0,0xe1,0x0,0xe2,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0xe1,0xe2,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0xe2,0xe0,0x20,0x0,
+ 0x0,0x0,0xe1,0xe1,0x0,0x0,0xe2,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0};
+SetWordType zzerr34[20] = {0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0xd,
+ 0x0,0x0,0x80,0x0, 0x20,0x0,0x0,0x0};
+SetWordType zzerr35[20] = {0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0xd,
+ 0x0,0x0,0x0,0x0, 0x20,0x0,0x0,0x0};
+SetWordType zzerr36[20] = {0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x5,
+ 0x4,0x8,0x8,0x18, 0x20,0x0,0x0,0x0};
+SetWordType zzerr37[20] = {0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0xc,
+ 0x0,0x0,0x0,0x0, 0x20,0x0,0x0,0x0};
+SetWordType zzerr38[20] = {0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x4,
+ 0x84,0x9,0x8,0x18, 0x20,0x0,0x0,0x0};
+SetWordType zzerr39[20] = {0x0,0x0,0x0,0x0, 0x10,0x0,0x0,0x0, 0x0,0x0,0x0,0x0,
+ 0x0,0x1,0x0,0x0, 0x0,0x0,0x0,0x0};
+SetWordType zzerr40[20] = {0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x4,
+ 0x4,0x9,0x8,0x18, 0x20,0x0,0x0,0x0};
+SetWordType zzerr41[20] = {0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x4,
+ 0x4,0x8,0x8,0x18, 0x20,0x0,0x0,0x0};
+SetWordType zzerr42[20] = {0x4,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x80,0x0,
+ 0x30,0x0,0x0,0x0, 0x0,0x0,0x0,0x0};
+SetWordType setwd7[157] = {0x0,0x0,0xdf,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0xdf,0xdf,0xff,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0xdf,0x3,0xdf,0x0,0x0,0xdf,0xdf,0x0,
+ 0x0,0x0,0x0,0xdf,0x0,0xdf,0xdf,0xdf,
+ 0x1,0x30,0xdf,0x0,0xdf,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0xdf,0xdf,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0xdf,0xdf,0x1,0x0,
+ 0x0,0x0,0xdf,0xdf,0x0,0x0,0xdf,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0};
+SetWordType zzerr43[20] = {0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x4,
+ 0x4,0x8,0x8,0x18, 0x20,0x0,0x0,0x0};
+SetWordType zzerr44[20] = {0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0xc0, 0x1,0x0,0x0,0x0};
+SetWordType zzerr45[20] = {0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x30,
+ 0x40,0x0,0x4,0x0, 0x0,0x0,0x0,0x0};
+SetWordType zzerr46[20] = {0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0,
+ 0x30,0x0,0x0,0x0, 0x0,0x0,0x0,0x0};
+SetWordType zzerr47[20] = {0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x20,
+ 0x40,0x0,0x4,0x0, 0x0,0x0,0x0,0x0};
+SetWordType zzerr48[20] = {0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x2,0x0, 0x10,0x0,0x0,0x0};
+SetWordType zzerr49[20] = {0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x4,
+ 0x4,0x8,0x8,0x18, 0x20,0x0,0x0,0x0};
+SetWordType zzerr50[20] = {0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x4,
+ 0x4,0x8,0xa,0x18, 0x30,0x0,0x0,0x0};
+SetWordType zzerr51[20] = {0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x4,
+ 0x4,0x8,0x8,0x18, 0x28,0x0,0x0,0x0};
+SetWordType zzerr52[20] = {0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0,
+ 0x40,0x0,0x4,0x0, 0x0,0x0,0x0,0x0};
+SetWordType zzerr53[20] = {0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x4,
+ 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0};
+SetWordType setwd8[157] = {0x0,0x0,0xe1,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0xe1,0xe1,0xe1,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0xe1,0x0,0xe1,0x0,0x0,0xe3,0xe7,0x0,
+ 0x0,0x0,0x0,0xe1,0x0,0xe1,0xe1,0xef,
+ 0x0,0x0,0xe1,0x0,0xe1,0x0,0x0,0x0,
+ 0x0,0x0,0x10,0xef,0xe1,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0xe1,0xe1,0x0,0x0,
+ 0x0,0x0,0xe1,0xe1,0x0,0x10,0xe1,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0};
+SetWordType zzerr54[20] = {0x2,0x0,0x0,0x0, 0x14,0x0,0x0,0x0, 0x0,0x0,0x0,0x0,
+ 0x1c,0xf8,0x78,0x9, 0xe0,0x0,0x0,0x0};
+SetWordType zzerr55[20] = {0x2,0x0,0x0,0x0, 0x4,0x0,0x0,0x0, 0x0,0x0,0x0,0x0,
+ 0x1c,0xf8,0x78,0x9, 0x60,0x0,0x0,0x0};
+SetWordType zzerr56[20] = {0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0,
+ 0x30,0x0,0x0,0x0, 0x0,0x0,0x0,0x0};
+SetWordType zzerr57[20] = {0x2,0x0,0x0,0x0, 0x4,0x0,0x0,0x0, 0x0,0x0,0x0,0x0,
+ 0x1c,0xf8,0x78,0x9, 0xe0,0x0,0x0,0x0};
+SetWordType setwd9[157] = {0x0,0x7c,0x1,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x7f,0x1,0x1,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x1,0x0,0x1,0x0,0x0,0x1,0x1,0x0,
+ 0x0,0x0,0x0,0x7f,0x7e,0x7f,0x1,0x1,
+ 0x0,0x0,0x1,0x0,0x7d,0x7e,0x7e,0x7e,
+ 0x7e,0x0,0x0,0x1,0x7d,0x7e,0x7e,0x7e,
+ 0x0,0x7e,0x0,0x0,0x7d,0x1,0x0,0x0,
+ 0x0,0x0,0x1,0x1,0x0,0x0,0x7f,0x64,
+ 0x64,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x80,0x0,0x0,0x0,0x0,0x0,0x80,0x0,
+ 0x80,0x0,0x0,0x0,0x0,0x0};
+SetWordType zzerr58[20] = {0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0, 0x0,0x0,0xa0,0x0};
+SetWordType zzerr59[20] = {0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0, 0x0,0x80,0xa0,0x0};
+SetWordType zzerr60[20] = {0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0, 0x0,0x0,0xa0,0x0};
+SetWordType zzerr61[20] = {0x2,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0, 0x0,0x80,0xa0,0x0};
+SetWordType zzerr62[20] = {0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0xe};
+SetWordType zzerr63[20] = {0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0xe};
+SetWordType zzerr64[20] = {0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0xe};
+SetWordType zzerr65[20] = {0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0, 0x0,0x0,0x10,0xc};
+SetWordType setwd10[157] = {0x0,0xc,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x3,0x0,
+ 0x3,0x0,0x0,0xf0,0xf0,0x0};
+SetWordType setwd11[157] = {0x0,0x1,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x1,0x0,0x0,0x0,0x0,0x0};
diff --git a/Source/Pccts/antlr/fcache.c b/Source/Pccts/antlr/fcache.c
new file mode 100644
index 0000000..ff7dcdf
--- /dev/null
+++ b/Source/Pccts/antlr/fcache.c
@@ -0,0 +1,123 @@
+/*
+ * fcache.c
+ *
+ * SOFTWARE RIGHTS
+ *
+ * We reserve no LEGAL rights to the Purdue Compiler Construction Tool
+ * Set (PCCTS) -- PCCTS is in the public domain. An individual or
+ * company may do whatever they wish with source code distributed with
+ * PCCTS or the code generated by PCCTS, including the incorporation of
+ * PCCTS, or its output, into commerical software.
+ *
+ * We encourage users to develop software with PCCTS. However, we do ask
+ * that credit is given to us for developing PCCTS. By "credit",
+ * we mean that if you incorporate our source code into one of your
+ * programs (commercial product, research project, or otherwise) that you
+ * acknowledge this fact somewhere in the documentation, research report,
+ * etc... If you like PCCTS and have developed a nice tool with the
+ * output, please mention that you developed it using PCCTS. In
+ * addition, we ask that this header remain intact in our source code.
+ * As long as these guidelines are kept, we expect to continue enhancing
+ * this system and expect to make other tools available as they are
+ * completed.
+ *
+ * ANTLR 1.33MR10
+ *
+ */
+
+#include <stdio.h>
+#include <ctype.h>
+
+#include "pcctscfg.h"
+
+#include "set.h"
+#include "syn.h"
+#include "hash.h"
+#include "generic.h"
+
+#ifdef __USE_PROTOS
+CacheEntry *dumpFcache1(char *prev)
+#else
+CacheEntry *dumpFcache1(prev)
+ char *prev;
+#endif
+{
+ Entry **table=Fcache;
+
+ int low=0;
+ int hi=0;
+
+ CacheEntry *least=NULL;
+
+ Entry **p;
+
+ for (p=table; p<&(table[HashTableSize]); p++) {
+
+ CacheEntry *q =(CacheEntry *) *p;
+
+ if ( q != NULL && low==0 ) low = p-table;
+ while ( q != NULL ) {
+ if (strcmp(q->str,prev) > 0) {
+ if (least == NULL) {
+ least=q;
+ } else {
+ if (strcmp(q->str,least->str) < 0) {
+ least=q;
+ };
+ };
+ };
+ q = q->next;
+ };
+
+ if ( *p != NULL ) hi = p-table;
+ }
+ return least;
+}
+
+#ifdef __USE_PROTOS
+void reportFcache(CacheEntry *q)
+#else
+void reportFcache(q)
+ CacheEntry *q;
+#endif
+{
+ char *qstr;
+
+ fprintf(stdout,"\nrule ");
+ for (qstr=q->str; *qstr != '*' ; qstr++) {
+ fprintf(stdout,"%c",*qstr);
+ };
+
+ qstr++;
+ if (*qstr == 'i') fprintf(stdout," First[");
+ if (*qstr == 'o') fprintf(stdout," Follow[");
+ qstr++;
+ fprintf(stdout,"%s]",qstr);
+ if (q->incomplete) fprintf(stdout," *** incomplete ***");
+ fprintf(stdout,"\n");
+ MR_dumpTokenSet(stdout,1,q->fset);
+}
+
+void
+#ifdef __USE_PROTOS
+DumpFcache(void)
+#else
+DumpFcache()
+#endif
+{
+
+ char *prev="";
+ int n=0;
+ CacheEntry *next;
+
+ fprintf(stdout,"\n\nDump of First/Follow Cache\n");
+
+ for(;;) {
+ next=dumpFcache1(prev);
+ if (next == NULL) break;
+ reportFcache(next);
+ ++n;
+ prev=next->str;
+ };
+ fprintf(stdout,"\nEnd dump of First/Follow Cache\n");
+}
diff --git a/Source/Pccts/antlr/fset.c b/Source/Pccts/antlr/fset.c
new file mode 100644
index 0000000..e1a76ec
--- /dev/null
+++ b/Source/Pccts/antlr/fset.c
@@ -0,0 +1,1555 @@
+/*
+ * fset.c
+ *
+ * Compute FIRST and FOLLOW sets.
+ *
+ * SOFTWARE RIGHTS
+ *
+ * We reserve no LEGAL rights to the Purdue Compiler Construction Tool
+ * Set (PCCTS) -- PCCTS is in the public domain. An individual or
+ * company may do whatever they wish with source code distributed with
+ * PCCTS or the code generated by PCCTS, including the incorporation of
+ * PCCTS, or its output, into commerical software.
+ *
+ * We encourage users to develop software with PCCTS. However, we do ask
+ * that credit is given to us for developing PCCTS. By "credit",
+ * we mean that if you incorporate our source code into one of your
+ * programs (commercial product, research project, or otherwise) that you
+ * acknowledge this fact somewhere in the documentation, research report,
+ * etc... If you like PCCTS and have developed a nice tool with the
+ * output, please mention that you developed it using PCCTS. In
+ * addition, we ask that this header remain intact in our source code.
+ * As long as these guidelines are kept, we expect to continue enhancing
+ * this system and expect to make other tools available as they are
+ * completed.
+ *
+ * ANTLR 1.33
+ * Terence Parr
+ * Parr Research Corporation
+ * with Purdue University and AHPCRC, University of Minnesota
+ * 1989-2001
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "pcctscfg.h"
+
+#include "set.h"
+#include "syn.h"
+#include "hash.h"
+#include "generic.h"
+#include "dlgdef.h"
+#include "limits.h"
+
+#ifdef __USE_PROTOS
+static void ensure_predicates_cover_ambiguous_lookahead_sequences
+ (Junction *, Junction *, char *, Tree *);
+#else
+static void ensure_predicates_cover_ambiguous_lookahead_sequences();
+#endif
+
+/*
+ * What tokens are k tokens away from junction q?
+ *
+ * Follow both p1 and p2 paths (unless RuleBlk) to collect the tokens k away from this
+ * node.
+ * We lock the junction according to k--the lookahead. If we have been at this
+ * junction before looking for the same, k, number of lookahead tokens, we will
+ * do it again and again...until we blow up the stack. Locks are only used on aLoopBlk,
+ * RuleBlk, aPlusBlk and EndRule junctions to remove/detect infinite recursion from
+ * FIRST and FOLLOW calcs.
+ *
+ * If p->jtype == EndRule we are going to attempt a FOLLOW. (FOLLOWs are really defined
+ * in terms of FIRST's, however). To proceed with the FOLLOW, p->halt cannot be
+ * set. p->halt is set to indicate that a reference to the current rule is in progress
+ * and the FOLLOW is not desirable.
+ *
+ * If we attempt a FOLLOW and find that there is no FOLLOW or REACHing beyond the EndRule
+ * junction yields an empty set, replace the empty set with EOF. No FOLLOW means that
+ * only EOF can follow the current rule. This normally occurs only on the start symbol
+ * since all other rules are referenced by another rule somewhere.
+ *
+ * Normally, both p1 and p2 are followed. However, checking p2 on a RuleBlk node is
+ * the same as checking the next rule which is clearly incorrect.
+ *
+ * Cycles in the FOLLOW sense are possible. e.g. Fo(c) requires Fo(b) which requires
+ * Fo(c). Both Fo(b) and Fo(c) are defined to be Fo(b) union Fo(c). Let's say
+ * Fo(c) is attempted first. It finds all of the FOLLOW symbols and then attempts
+ * to do Fo(b) which finds of its FOLLOW symbols. So, we have:
+ *
+ * Fo(c)
+ * / \
+ * a set Fo(b)
+ * / \
+ * a set Fo(c) .....Hmmmm..... Infinite recursion!
+ *
+ * The 2nd Fo(c) is not attempted and Fo(b) is left deficient, but Fo(c) is now
+ * correctly Fo(c) union Fo(b). We wish to pick up where we left off, so the fact
+ * that Fo(b) terminated early means that we lack Fo(c) in the Fo(b) set already
+ * laying around. SOOOOoooo, we track FOLLOW cycles. All FOLLOW computations are
+ * cached in a hash table. After the sequence of FOLLOWs finish, we reconcile all
+ * cycles --> correct all Fo(rule) sets in the cache.
+ *
+ * Confused? Good! Read my MS thesis [Purdue Technical Report TR90-30].
+ * TJP 8/93 -- can now read PhD thesis from Purdue.
+ *
+ * Also, FIRST sets are cached in the hash table. Keys are (rulename,Fi/Fo,k).
+ * Only FIRST sets, for which the FOLLOW is not included, are stored.
+ *
+ * SPECIAL CASE of (...)+ blocks:
+ * I added an optional alt so that the alts could see what
+ * was behind the (...)+ block--thus using enough lookahead
+ * to branch out rather than just enough to distinguish
+ * between alts in the (...)+. However, when the FIRST("(...)+") is
+ * is needed, must not use this last "optional" alt. This routine
+ * turns off this path by setting a new 'ignore' flag for
+ * the alt and then resetting it afterwards.
+ */
+
+set
+#ifdef __USE_PROTOS
+rJunc( Junction *p, int k, set *rk )
+#else
+rJunc( p, k, rk )
+Junction *p;
+int k;
+set *rk;
+#endif
+{
+ set a, b;
+
+ require(p!=NULL, "rJunc: NULL node");
+ require(p->ntype==nJunction, "rJunc: not junction");
+
+#ifdef DBG_LL1
+ if ( p->jtype == RuleBlk ) fprintf(stderr, "FIRST(%s,%d) \n",((Junction *)p)->rname,k);
+ else fprintf(stderr, "rJunc: %s in rule %s\n",
+ decodeJType[p->jtype], ((Junction *)p)->rname);
+#endif
+ /* if this is one of the added optional alts for (...)+ then return */
+
+ /* no need to pop backtrace - hasn't been pushed */
+
+ if ( p->ignore ) return empty;
+
+ if (MR_MaintainBackTrace) MR_pointerStackPush(&MR_BackTraceStack,p);
+
+/* MR14 */ if (AlphaBetaTrace && p->alpha_beta_guess_end) {
+/* MR14 */ warnFL(
+/* MR14 */ "not possible to compute follow set for alpha in an \"(alpha)? beta\" block. ",
+/* MR14 */ FileStr[p->file],p->line);
+/* MR14 */ MR_alphaBetaTraceReport();
+/* MR14 */ };
+
+/* MR14 */ if (p->alpha_beta_guess_end) {
+/* MR14 */ if (MR_MaintainBackTrace) MR_pointerStackPop(&MR_BackTraceStack);
+/* MR14 */ return empty;
+/* MR14 */ }
+
+ /* locks are valid for aLoopBlk,aPlusBlk,RuleBlk,EndRule junctions only */
+ if ( p->jtype==aLoopBlk || p->jtype==RuleBlk ||
+ p->jtype==aPlusBlk || p->jtype==EndRule )
+ {
+ require(p->lock!=NULL, "rJunc: lock array is NULL");
+ if ( p->lock[k] )
+ {
+ if ( p->jtype == EndRule ) /* FOLLOW cycle? */
+ {
+#ifdef DBG_LL1
+ fprintf(stderr, "FOLLOW cycle to %s: panic!\n", p->rname);
+#endif
+ if (! MR_AmbSourceSearch) RegisterCycle(p->rname, k);
+ }
+ if (MR_MaintainBackTrace) MR_pointerStackPop(&MR_BackTraceStack);
+ return empty;
+ }
+ if ( p->jtype == RuleBlk &&
+ p->end->halt &&
+ ! MR_AmbSourceSearch) /* check for FIRST cache */
+ {
+ CacheEntry *q = (CacheEntry *) hash_get(Fcache, Fkey(p->rname,'i',k));
+ if ( q != NULL )
+ {
+ set_orin(rk, q->rk);
+ if (MR_MaintainBackTrace) MR_pointerStackPop(&MR_BackTraceStack);
+ return set_dup( q->fset );
+ }
+ }
+ if ( p->jtype == EndRule &&
+ !p->halt && /* MR11 was using cache even when halt set */
+ ! MR_AmbSourceSearch) /* FOLLOW set cached already? */
+ {
+ CacheEntry *q = (CacheEntry *) hash_get(Fcache, Fkey(p->rname,'o',k));
+ if ( q != NULL )
+ {
+#ifdef DBG_LL1
+ fprintf(stderr, "cache for FOLLOW(%s,%d):", p->rname,k);
+ s_fprT(stderr, q->fset);
+ if ( q->incomplete ) fprintf(stderr, " (incomplete)");
+ fprintf(stderr, "\n");
+#endif
+ if ( !q->incomplete )
+ {
+ if (MR_MaintainBackTrace) MR_pointerStackPop(&MR_BackTraceStack);
+ return set_dup( q->fset );
+ }
+ }
+ }
+ p->lock[k] = TRUE; /* This rule is busy */
+ }
+
+ a = b = empty;
+
+ if ( p->jtype == EndRule )
+ {
+ if (p->halt ) /* don't want FOLLOW here? */ /* unless MR10 hoisting */
+ {
+ p->lock[k] = FALSE;
+ set_orel(k, rk); /* indicate this k value needed */
+ if (MR_MaintainBackTrace) MR_pointerStackPop(&MR_BackTraceStack);
+ return empty;
+ }
+ if (! MR_AmbSourceSearch) FoPush(p->rname, k); /* Attempting FOLLOW */
+ if ( p->p1 == NULL ) set_orel((TokenInd!=NULL?TokenInd[EofToken]:EofToken), &a);/* if no FOLLOW assume EOF */
+#ifdef DBG_LL1
+ fprintf(stderr, "-->FOLLOW(%s,%d)\n", p->rname,k);
+#endif
+ }
+
+ if ( p->p1 != NULL ) {
+/* MR14 */ if (p->guess) {
+/* MR14 */ if (p->guess_analysis_point == NULL) {
+/* MR14 */ Node * guess_point;
+/* MR14 */ guess_point=(Node *)analysis_point(p);
+/* MR14 */ if (guess_point == (Node *)p) {
+/* MR14 */ guess_point=p->p1;
+/* MR14 */ }
+/* MR14 */ p->guess_analysis_point=guess_point;
+/* MR14 */ }
+/* MR14 */ REACH(p->guess_analysis_point, k, rk, a);
+ } else {
+ REACH(p->p1, k, rk, a);
+ }
+ }
+
+ /* C a c h e R e s u l t s */
+
+ if ( p->jtype == RuleBlk && p->end->halt && ! MR_AmbSourceSearch) /* can save FIRST set? */
+ {
+ CacheEntry *q = newCacheEntry( Fkey(p->rname,'i',k) );
+ /*fprintf(stderr, "Caching %s FIRST %d\n", p->rname, k);*/
+ hash_add(Fcache, Fkey(p->rname,'i',k), (Entry *)q);
+ q->fset = set_dup( a );
+ q->rk = set_dup( *rk );
+ }
+
+ if ( p->jtype == EndRule &&
+ !p->halt && /* MR11 was using cache even with halt set */
+ ! MR_AmbSourceSearch) /* just completed FOLLOW? */
+ {
+ /* Cache Follow set */
+ CacheEntry *q = (CacheEntry *) hash_get(Fcache, Fkey(p->rname,'o',k));
+ if ( q==NULL )
+ {
+ q = newCacheEntry( Fkey(p->rname,'o',k) );
+ hash_add(Fcache, Fkey(p->rname,'o',k), (Entry *)q);
+ }
+ /*fprintf(stderr, "Caching %s FOLLOW %d\n", p->rname, k);*/
+ if ( set_nil(a) && !q->incomplete )
+ {
+ /* Don't ever save a nil set as complete.
+ * Turn it into an eof set.
+ */
+ set_orel(EofToken, &a);
+ }
+ set_orin(&(q->fset), a);
+ FoPop( k );
+ if ( FoTOS[k] == NULL && Cycles[k] != NULL ) ResolveFoCycles(k);
+#ifdef DBG_LL1
+ fprintf(stderr, "saving FOLLOW(%s,%d):", p->rname, k);
+ s_fprT(stderr, q->fset);
+ if ( q->incomplete ) fprintf(stderr, " (incomplete)");
+ fprintf(stderr, "\n");
+#endif
+ }
+
+ if (p->jtype != RuleBlk && p->p2 != NULL && /* MR14 */ ! p->guess) {
+ REACH(p->p2, k, rk, b);
+ }
+
+ if ( p->jtype==aLoopBlk || p->jtype==RuleBlk ||
+ p->jtype==aPlusBlk || p->jtype==EndRule )
+ p->lock[k] = FALSE; /* unlock node */
+
+ set_orin(&a, b);
+ set_free(b);
+ if (MR_MaintainBackTrace) MR_pointerStackPop(&MR_BackTraceStack);
+ return a;
+}
+
+set
+#ifdef __USE_PROTOS
+rRuleRef( RuleRefNode *p, int k, set *rk_out )
+#else
+rRuleRef( p, k, rk_out )
+RuleRefNode *p;
+int k;
+set *rk_out;
+#endif
+{
+ set rk;
+ Junction *r;
+ int k2;
+ set a, rk2, b;
+ int save_halt;
+ RuleEntry *q = (RuleEntry *) hash_get(Rname, p->text);
+ require(p!=NULL, "rRuleRef: NULL node");
+ require(p->ntype==nRuleRef, "rRuleRef: not rule ref");
+
+#ifdef DBG_LL1
+ fprintf(stderr, "rRuleRef: %s\n", p->text);
+#endif
+
+ if (MR_MaintainBackTrace) MR_pointerStackPush(&MR_BackTraceStack,p);
+
+ if ( q == NULL )
+ {
+ warnFL( eMsg1("rule %s not defined",p->text), FileStr[p->file], p->line );
+ REACH(p->next, k, rk_out, a);
+ if (MR_MaintainBackTrace) MR_pointerStackPop(&MR_BackTraceStack);
+ return a;
+ }
+ rk2 = empty;
+
+/* MR9 Problems with rule references in guarded predicates */
+/* MR9 Perhaps can use hash table to find rule ? */
+
+/* MR9 */ if (RulePtr == NULL) {
+/* MR9 */ fatalFL(eMsg2("Rule %s uses rule %s via RulePtr before it has been initialized",
+/* MR9 */ p->rname,q->str),FileStr[p->file],p->line);
+/* MR9 */ };
+
+ r = RulePtr[q->rulenum];
+ if ( r->lock[k] )
+ {
+ errNoFL( eMsg2("infinite left-recursion to rule %s from rule %s",
+ r->rname, p->rname) );
+
+ if (MR_MaintainBackTrace) MR_pointerStackPop(&MR_BackTraceStack);
+
+ return empty;
+ }
+
+ save_halt = r->end->halt;
+ r->end->halt = TRUE; /* don't let reach fall off end of rule here */
+ rk = empty;
+ REACH(r, k, &rk, a);
+ r->end->halt = save_halt;
+ while ( !set_nil(rk) ) {
+ k2 = set_int(rk); /* MR11 this messes up the ambiguity search routine */
+ set_rm(k2, rk);
+ REACH(p->next, k2, &rk2, b); /* MR11 by changing the value of k */
+ set_orin(&a, b);
+ set_free(b);
+ }
+ set_free(rk); /* this has no members, but free it's memory */
+ set_orin(rk_out, rk2); /* remember what we couldn't do */
+ set_free(rk2);
+ if (MR_MaintainBackTrace) MR_pointerStackPop(&MR_BackTraceStack);
+ return a;
+}
+
+/*
+ * Return FIRST sub k ( token_node )
+ *
+ * TJP 10/11/93 modified this so that token nodes that are actually
+ * ranges (T1..T2) work.
+ */
+set
+#ifdef __USE_PROTOS
+rToken( TokNode *p, int k, set *rk )
+#else
+rToken( p, k, rk )
+TokNode *p;
+int k;
+set *rk;
+#endif
+{
+ set a;
+
+ require(p!=NULL, "rToken: NULL node");
+ require(p->ntype==nToken, "rToken: not token node");
+
+#ifdef DBG_LL1
+ fprintf(stderr, "rToken: %s\n", (TokenString(p->token)!=NULL)?TokenString(p->token):
+ ExprString(p->token));
+#endif
+
+
+ if (MR_MaintainBackTrace) MR_pointerStackPush(&MR_BackTraceStack,p);
+
+ if (MR_AmbSourceSearch && (k-1) == 0) {
+
+ set localConstrain;
+ set intersection;
+
+ localConstrain=fset[maxk-k+1];
+
+ if (! set_nil(p->tset)) {
+ intersection=set_and(localConstrain,p->tset);
+ if (! set_nil(intersection)) {
+ MR_backTraceReport();
+ };
+ set_free(intersection);
+ } else {
+ if (set_el( (unsigned) p->token,localConstrain)) {
+ MR_backTraceReport();
+ }
+ };
+ };
+
+ if ( k-1 == 0 ) {
+
+ if (MR_MaintainBackTrace) MR_pointerStackPop(&MR_BackTraceStack);
+
+ if ( !set_nil(p->tset) ) {
+ return set_dup(p->tset);
+ } else {
+ return set_of(p->token);
+ };
+ }
+
+ REACH(p->next, k-1, rk, a);
+
+ if (MR_MaintainBackTrace) MR_pointerStackPop(&MR_BackTraceStack);
+
+ return a;
+}
+
+set
+#ifdef __USE_PROTOS
+rAction( ActionNode *p, int k, set *rk )
+#else
+rAction( p, k, rk )
+ActionNode *p;
+int k;
+set *rk;
+#endif
+{
+ set a;
+
+ require(p!=NULL, "rJunc: NULL node");
+ require(p->ntype==nAction, "rJunc: not action");
+
+/* MR11 */ if (p->is_predicate && p->ampersandPred != NULL) {
+/* MR11 */ Predicate *pred=p->ampersandPred;
+/* MR11 */ if (k <= pred->k) {
+/* MR11 */ REACH(p->guardNodes,k,rk,a);
+/* MR11 */ return a;
+/* MR11 */ };
+/* MR11 */ };
+
+ /* it might be a good idea when doing an MR_AmbSourceSearch
+ to *not* look behind predicates under some circumstances
+ we'll look into that later
+ */
+
+ REACH(p->next, k, rk, a); /* ignore actions */
+ return a;
+}
+
+ /* A m b i g u i t y R e s o l u t i o n */
+
+
+void
+#ifdef __USE_PROTOS
+dumpAmbigMsg( set *fset, FILE *f, int want_nls )
+#else
+dumpAmbigMsg( fset, f, want_nls )
+set *fset;
+FILE *f;
+int want_nls;
+#endif
+{
+ int i;
+
+ set copy; /* MR11 */
+
+ if ( want_nls ) fprintf(f, "\n\t");
+ else fprintf(f, " ");
+
+ for (i=1; i<=CLL_k; i++)
+ {
+ copy=set_dup(fset[i]); /* MR11 */
+
+ if ( i>1 )
+ {
+ if ( !want_nls ) fprintf(f, ", ");
+ }
+ if ( set_deg(copy) > 3 && elevel == 1 )
+ {
+ int e,m;
+ fprintf(f, "{");
+ for (m=1; m<=3; m++)
+ {
+ e=set_int(copy);
+ fprintf(f, " %s", TerminalString(e));
+ set_rm(e, copy);
+ }
+ fprintf(f, " ... }");
+ }
+ else s_fprT(f, copy);
+ if ( want_nls ) fprintf(f, "\n\t");
+ set_free(copy);
+ }
+ fprintf(f, "\n");
+
+}
+
+static void
+#ifdef __USE_PROTOS
+verify_context(Predicate *predicate)
+#else
+verify_context(predicate)
+Predicate *predicate;
+#endif
+{
+ if ( predicate == NULL ) return;
+
+ if ( predicate->expr == PRED_OR_LIST ||
+ predicate->expr == PRED_AND_LIST )
+ {
+ verify_context(predicate->down);
+ verify_context(predicate->right); /* MR10 */
+ return;
+ }
+
+ if ( !predicate->source->ctxwarned && predicate->source->guardpred==NULL &&
+ ((predicate->k > 1 &&
+ !is_single_tuple(predicate->tcontext)) ||
+ ( predicate->k == 1 &&
+ set_deg(predicate->scontext[1])>1 )) )
+ {
+
+/* MR9 Suppress annoying messages caused by our own clever(?) fix */
+
+ fprintf(stderr, ErrHdr, FileStr[predicate->source->file],
+ predicate->source->line);
+ fprintf(stderr, " warning: predicate applied for >1 lookahead %d-sequences\n", predicate->k);
+ fprintf(stderr, ErrHdr, FileStr[predicate->source->file],
+ predicate->source->line);
+ fprintf(stderr, " predicate text: \"%s\"\n",
+ (predicate->expr == NULL ? "(null)" : predicate->expr) );
+ fprintf(stderr, ErrHdr, FileStr[predicate->source->file],
+ predicate->source->line);
+ fprintf(stderr, " You may only want one lookahead %d-sequence to apply\n", predicate->k);
+ fprintf(stderr, ErrHdr, FileStr[predicate->source->file],
+ predicate->source->line);
+ fprintf(stderr, " Try using a context guard '(...)? =>'\n");
+ predicate->source->ctxwarned = 1;
+ }
+ verify_context(predicate->right); /* MR10 */
+}
+
+/*
+ * If delta is the set of ambiguous lookahead sequences, then make sure that
+ * the predicate(s) for productions alt1,alt2 cover the sequences in delta.
+ *
+ * For example,
+ * a : <<PRED1>>? (A B|A C)
+ * | b
+ * ;
+ * b : <<PRED2>>? A B
+ * | A C
+ * ;
+ *
+ * This should give a warning that (A C) predicts both productions and alt2
+ * does not have a predicate in the production that generates (A C).
+ *
+ * The warning detection is simple. Let delta = LOOK(alt1) intersection LOOK(alt2).
+ * Now, if ( delta set-difference context(predicates-for-alt1) != empty then
+ * alt1 does not "cover" all ambiguous sequences.
+ *
+ * If ambig is nonempty, then ambig in LL(k) sense -> use tree info; else use fset
+ * info. Actually, sets are used only if k=1 for this grammar.
+ */
+static void
+#ifdef __USE_PROTOS
+ensure_predicates_cover_ambiguous_lookahead_sequences
+ ( Junction *alt1, Junction *alt2, char *sub, Tree *ambig )
+#else
+ensure_predicates_cover_ambiguous_lookahead_sequences( alt1, alt2, sub, ambig )
+Junction *alt1;
+Junction *alt2;
+char *sub;
+Tree *ambig;
+#endif
+{
+ if ( !ParseWithPredicates ) return;
+
+ if ( ambig!=NULL )
+ {
+ Tree *non_covered = NULL;
+ if ( alt1->predicate!=NULL )
+ non_covered = tdif(ambig, alt1->predicate, alt1->fset, alt2->fset);
+ if ( (non_covered!=NULL || alt1->predicate==NULL) && WarningLevel>1 )
+ {
+ fprintf(stderr, ErrHdr, FileStr[alt1->file], alt1->line);
+ fprintf(stderr, " warning: alt %d %shas no predicate to resolve ambiguity",
+ alt1->altnum, sub);
+ if ( alt1->predicate!=NULL && non_covered!=NULL )
+ {
+ fprintf(stderr, " upon");
+ preorder(non_covered);
+ }
+ else if ( alt1->predicate==NULL )
+ {
+ fprintf(stderr, " upon");
+ preorder(ambig->down);
+ }
+ fprintf(stderr, "\n");
+ }
+ Tfree(non_covered);
+ non_covered = NULL;
+ if ( alt2->predicate!=NULL )
+ non_covered = tdif(ambig, alt2->predicate, alt1->fset, alt2->fset);
+ if ( (non_covered!=NULL || alt2->predicate==NULL) && WarningLevel>1 )
+ {
+ fprintf(stderr, ErrHdr, FileStr[alt2->file], alt2->line);
+ fprintf(stderr, " warning: alt %d %shas no predicate to resolve ambiguity",
+ alt2->altnum, sub);
+ if ( alt2->predicate!=NULL && non_covered!=NULL )
+ {
+ fprintf(stderr, " upon");
+ preorder(non_covered);
+ }
+ else if ( alt2->predicate==NULL )
+ {
+ fprintf(stderr, " upon");
+ preorder(ambig->down);
+ }
+ fprintf(stderr, "\n");
+ }
+ Tfree(non_covered);
+ }
+ else if ( !set_nil(alt1->fset[1]) )
+ {
+ set delta, non_covered;
+ delta = set_and(alt1->fset[1], alt2->fset[1]);
+ non_covered = set_dif(delta, covered_set(alt1->predicate));
+ if ( set_deg(non_covered)>0 && WarningLevel>1 )
+ {
+ fprintf(stderr, ErrHdr, FileStr[alt1->file], alt1->line);
+ fprintf(stderr, " warning: alt %d %shas no predicate to resolve ambiguity",
+ alt1->altnum, sub);
+ if ( alt1->predicate!=NULL )
+ {
+ fprintf(stderr, " upon ");
+ s_fprT(stderr, non_covered);
+ }
+ fprintf(stderr, "\n");
+ }
+ set_free( non_covered );
+ non_covered = set_dif(delta, covered_set(alt2->predicate));
+ if ( set_deg(non_covered)>0 && WarningLevel>1 )
+ {
+ fprintf(stderr, ErrHdr, FileStr[alt2->file], alt2->line);
+ fprintf(stderr, " warning: alt %d %shas no predicate to resolve ambiguity",
+ alt2->altnum, sub);
+ if ( alt2->predicate!=NULL )
+ {
+ fprintf(stderr, " upon ");
+ s_fprT(stderr, non_covered);
+ }
+ fprintf(stderr, "\n");
+ }
+ set_free( non_covered );
+ set_free( delta );
+ }
+ else fatal_internal("productions have no lookahead in predicate checking routine");
+}
+
+#ifdef __USE_PROTOS
+void MR_doPredicatesHelp(int inGuessBlock,Junction *alt1,Junction *alt2,int jtype,char *sub)
+#else
+void MR_doPredicatesHelp(inGuessBlock,alt1,alt2,jtype,sub)
+ int inGuessBlock;
+ Junction *alt1;
+ Junction *alt2;
+ int jtype;
+ char *sub;
+#endif
+{
+ Predicate *p1;
+ Predicate *p2;
+
+ Junction *parentRule=MR_nameToRuleBlk(alt1->rname);
+
+ if (inGuessBlock && WarningLevel <= 1) return;
+
+ /* let antlr give the usual error message */
+
+ if (alt1->predicate == NULL && alt2->predicate == NULL) return;
+
+ if ( (jtype == RuleBlk || jtype == aSubBlk)
+ && (alt1->predicate == NULL && alt2->predicate != NULL)) {
+ fprintf(stderr, ErrHdr, FileStr[parentRule->file],parentRule->line);
+ fprintf(stderr," warning: alt %d line %d and alt %d line %d of %s\n%s%s%s",
+ alt1->altnum,
+ alt1->line,
+ alt2->altnum,
+ alt2->line,
+ sub,
+ " These alts have ambig lookahead sequences resolved by a predicate for\n",
+ " the second choice. The second choice may not be reachable.\n",
+ " You may want to use a complementary predicate or rearrange the alts\n"
+ );
+ return;
+ };
+
+ /* first do the easy comparison. then do the hard one */
+
+ if (MR_comparePredicates(alt1->predicate,alt2->predicate)) {
+
+ if (jtype == aLoopBegin || jtype == aPlusBlk ) {
+
+ /* I'm not sure this code is reachable.
+ Predicates following a (...)+ or (...)* block are probably
+ considered validation predicates and therefore not
+ participate in the predication expression
+ */
+
+ fprintf(stderr, ErrHdr,FileStr[parentRule->file],parentRule->line);
+ fprintf(stderr," warning: %s of %s in rule %s\n (file %s alt %d line %d and alt %d line %d)\n%s",
+ "the predicates used to disambiguate optional/exit paths of ",
+ sub,
+ CurRule,
+ FileStr[alt1->file],
+ alt1->altnum,
+ alt1->line,
+ alt2->altnum,
+ alt2->line,
+ " are identical and have no resolving power\n");
+ } else {
+ fprintf(stderr, ErrHdr, FileStr[parentRule->file], parentRule->line);
+ fprintf(stderr," warning: %s rule %s\n (file %s alt %d line %d and alt %d line %d)\n%s",
+ "the predicates used to disambiguate",
+ CurRule,
+ FileStr[alt1->file],
+ alt1->altnum,
+ alt1->line,
+ alt2->altnum,
+ alt2->line,
+ " are identical and have no resolving power\n");
+ };
+ } else {
+ p1=predicate_dup_without_context(alt1->predicate);
+ p1=MR_unfold(p1);
+ MR_clearPredEntry(p1);
+ MR_simplifyInverted(p1,0);
+ p1=MR_predSimplifyALL(p1);
+ p2=predicate_dup_without_context(alt2->predicate);
+ p2=MR_unfold(p2);
+ MR_clearPredEntry(p2);
+ MR_simplifyInverted(p2,0);
+ p2=MR_predSimplifyALL(p2);
+ if (MR_comparePredicates(p1,p2)) {
+ if (jtype == aLoopBegin || jtype == aPlusBlk ) {
+ fprintf(stderr, ErrHdr, FileStr[parentRule->file], parentRule->line);
+ fprintf(stderr," warning: %s of %s in rule %s\n (file %s alt %d line %d and alt %d line %d)\n%s%s",
+ "the predicates used to disambiguate optional/exit paths of ",
+ sub,
+ CurRule,
+ FileStr[alt1->file],
+ alt1->altnum,
+ alt1->line,
+ alt2->altnum,
+ alt2->line,
+ " are identical when compared without context and may have no\n",
+ " resolving power for some lookahead sequences.\n");
+ } else {
+ fprintf(stderr, ErrHdr, FileStr[parentRule->file], parentRule->line);
+ fprintf(stderr," warning: %s rule %s\n (file %s alt %d line %d and alt %d line %d)\n%s%s",
+ "the predicates used to disambiguate",
+ CurRule,
+ FileStr[alt1->file],
+ alt1->altnum,
+ alt1->line,
+ alt2->altnum,
+ alt2->line,
+ " are identical when compared without context and may have no\n",
+ " resolving power for some lookahead sequences.\n");
+ };
+ if (InfoP) {
+ fprintf(output,"\n#if 0\n\n");
+ fprintf(output,"The following predicates are identical when compared without\n");
+ fprintf(output," lookahead context information. For some ambiguous lookahead\n");
+ fprintf(output," sequences they may not have any power to resolve the ambiguity.\n");
+ fprintf(output,"\n");
+
+ fprintf(output,"Choice 1: %s alt %d line %d file %s\n\n",
+ MR_ruleNamePlusOffset( (Node *) alt1),
+ alt1->altnum,
+ alt1->line,
+ FileStr[alt1->file]);
+ fprintf(output," The original predicate for choice 1 with available context information:\n\n");
+ MR_dumpPred1(2,alt1->predicate,1);
+ fprintf(output," The predicate for choice 1 after expansion (but without context information):\n\n");
+ MR_dumpPred1(2,p1,0);
+ if (p1 == NULL) {
+ Predicate *phelp;
+ fprintf(output," The predicate for choice 1 after expansion (but before simplification)\n\n");
+ phelp=predicate_dup_without_context(alt1->predicate);
+ phelp=MR_unfold(phelp);
+ MR_clearPredEntry(phelp);
+ MR_simplifyInverted(phelp,0);
+ phelp=MR_predSimplifyALLX(phelp,1);
+ MR_dumpPred1(2,phelp,0);
+ predicate_free(phelp);
+ };
+ fprintf(output,"\n");
+
+ fprintf(output,"Choice 2: %s alt %d line %d file %s\n\n",
+ MR_ruleNamePlusOffset( (Node *) alt2),
+ alt2->altnum,
+ alt2->line,
+ FileStr[alt2->file]);
+ fprintf(output," The original predicate for choice 2 with available context information:\n\n");
+ MR_dumpPred1(1,alt2->predicate,1);
+ fprintf(output," The predicate for choice 2 after expansion (but without context information):\n\n");
+ MR_dumpPred1(1,p2,0);
+ if (p2 == NULL) {
+ Predicate *phelp;
+ fprintf(output," The predicate for choice 2 after expansion (but before simplification)\n\n");
+ phelp=predicate_dup_without_context(alt2->predicate);
+ phelp=MR_unfold(phelp);
+ MR_clearPredEntry(phelp);
+ MR_simplifyInverted(phelp,0);
+ phelp=MR_predSimplifyALLX(phelp,1);
+ MR_dumpPred1(2,phelp,0);
+ predicate_free(phelp);
+ };
+ fprintf(output,"\n#endif\n");
+ };
+ } else if (MR_secondPredicateUnreachable(p1,p2)) {
+ if (jtype == aLoopBegin || jtype == aPlusBlk ) {
+ fprintf(stderr, ErrHdr, FileStr[parentRule->file], parentRule->line);
+ fprintf(stderr," warning: %s of %s in rule %s\n (file %s alt %d line %d and alt %d line %d)\n%s%s",
+ "the predicate used to disambiguate the first choice of the optional/exit paths of ",
+ sub,
+ CurRule,
+ FileStr[alt1->file],
+ alt1->altnum,
+ alt1->line,
+ alt2->altnum,
+ alt2->line,
+ " appears to \"cover\" the second predicate when compared without context.\n",
+ " The second predicate may have no resolving power for some lookahead sequences.\n");
+ } else {
+ fprintf(stderr, ErrHdr, FileStr[parentRule->file], parentRule->line);
+ fprintf(stderr," warning: %s rule %s\n (file %s alt %d line %d and alt %d line %d)\n%s%s",
+ "the predicate used to disambiguate the first choice of",
+ CurRule,
+ FileStr[alt1->file],
+ alt1->altnum,
+ alt1->line,
+ alt2->altnum,
+ alt2->line,
+ " appears to \"cover\" the second predicate when compared without context.\n",
+ " The second predicate may have no resolving power for some lookahead sequences.\n");
+ };
+ if (InfoP) {
+ fprintf(output,"\n#if 0\n\n");
+ fprintf(output,"The first predicate appears to \"cover\" the second predicate when they\n");
+ fprintf(output," are compared without lookahead context information. For some ambiguous\n");
+ fprintf(output," lookahead sequences the second predicate may not have any power to\n");
+ fprintf(output," resolve the ambiguity.\n");
+ fprintf(output,"\n");
+ fprintf(output,"Choice 1: %s alt %d line %d file %s\n\n",
+ MR_ruleNamePlusOffset( (Node *) alt1),
+ alt1->altnum,
+ alt1->line,
+ FileStr[alt1->file]);
+ fprintf(output," The original predicate for choice 1 with available context information:\n\n");
+ MR_dumpPred1(2,alt1->predicate,1);
+ fprintf(output," The predicate for choice 1 after expansion (but without context information):\n\n");
+ MR_dumpPred1(2,p1,0);
+ if (p1 == NULL) {
+ Predicate *phelp;
+ fprintf(output," The predicate for choice 1 after expansion (but before simplification)\n\n");
+ phelp=predicate_dup_without_context(alt1->predicate);
+ phelp=MR_unfold(phelp);
+ MR_clearPredEntry(phelp);
+ MR_simplifyInverted(phelp,0);
+ phelp=MR_predSimplifyALLX(phelp,1);
+ MR_dumpPred1(2,phelp,0);
+ predicate_free(phelp);
+ };
+ fprintf(output,"\n");
+
+ fprintf(output,"Choice 2: %s alt %d line %d file %s\n\n",
+ MR_ruleNamePlusOffset( (Node *) alt2),
+ alt2->altnum,
+ alt2->line,
+ FileStr[alt2->file]);
+ fprintf(output," The original predicate for choice 2 with available context information:\n\n");
+ MR_dumpPred1(1,alt2->predicate,1);
+ fprintf(output," The predicate for choice 2 after expansion (but without context information):\n\n");
+ MR_dumpPred1(1,p2,0);
+ if (p2 == NULL) {
+ Predicate *phelp;
+ fprintf(output," The predicate for choice 2 after expansion (but before simplification)\n\n");
+ phelp=predicate_dup_without_context(alt2->predicate);
+ phelp=MR_unfold(phelp);
+ MR_clearPredEntry(phelp);
+ MR_simplifyInverted(phelp,0);
+ phelp=MR_predSimplifyALLX(phelp,1);
+ MR_dumpPred1(2,phelp,0);
+ predicate_free(phelp);
+ };
+ fprintf(output,"\n#endif\n");
+ };
+ };
+ predicate_free(p1);
+ predicate_free(p2);
+ };
+}
+
+static int totalOverflow=0; /* MR9 */
+
+void
+#ifdef __USE_PROTOS
+HandleAmbiguity( Junction *block, Junction *alt1, Junction *alt2, int jtype )
+#else
+HandleAmbiguity( block, alt1, alt2, jtype )
+Junction *block;
+Junction *alt1;
+Junction *alt2;
+int jtype;
+#endif
+{
+ unsigned **ftbl;
+ set *fset, b;
+ int i, numAmbig,n2;
+ Tree *ambig=NULL, *t, *u;
+ char *sub = "";
+ long n;
+ int thisOverflow=0; /* MR9 */
+ long set_deg_value; /* MR10 */
+ long threshhold; /* MR10 */
+
+ require(block!=NULL, "NULL block");
+ require(block->ntype==nJunction, "invalid block");
+
+ /* These sets are used to constrain LL_k set, but are made CLL_k long anyway */
+ fset = (set *) calloc(CLL_k+1, sizeof(set));
+ require(fset!=NULL, "cannot allocate fset");
+ ftbl = (unsigned **) calloc(CLL_k+1, sizeof(unsigned *));
+ require(ftbl!=NULL, "cannot allocate ftbl");
+
+ /* create constraint table and count number of possible ambiguities (use<=LL_k) */
+ for (n=1,i=1; i<=CLL_k; i++)
+ {
+ b = set_and(alt1->fset[i], alt2->fset[i]);
+/* MR9 */ set_deg_value = set_deg(b);
+/* MR10 */ if (n > 0) {
+/* MR10 */ threshhold = LONG_MAX / n;
+/* MR10 */ if (set_deg_value <= threshhold) {
+/* MR10 */ n *= set_deg_value;
+/* MR10 */ } else {
+/* MR10 */ n=LONG_MAX;
+/* MR9 */ if (totalOverflow == 0) {
+#if 0
+ /* MR10 comment this out because it just makes users worry */
+
+/* MR9 */ warnNoFL("Overflow in computing number of possible ambiguities in HandleAmbiguity\n");
+#endif
+/* MR9 */ };
+/* MR9 */ thisOverflow++;
+/* MR9 */ totalOverflow++;
+/* MR9 */ };
+/* MR10 */ } else {
+/* MR10 */ n *= set_deg_value;
+/* MR9 */ };
+ fset[i] = set_dup(b);
+ ftbl[i] = set_pdq(b);
+ set_free(b);
+ }
+
+ switch ( jtype )
+ {
+ case aSubBlk: sub = "of (..) "; break;
+ case aOptBlk: sub = "of {..} "; break;
+ case aLoopBegin: sub = "of (..)* "; break;
+ case aLoopBlk: sub = "of (..)* "; break;
+ case aPlusBlk: sub = "of (..)+ "; break;
+ case RuleBlk: sub = "of the rule itself "; break;
+ default : sub = ""; break;
+ }
+
+ /* If the block is marked as a compressed lookahead only block, then
+ * simply return; ambiguity warning is given only at warning level 2.
+ */
+ if ( block->approx>0 )
+ {
+ if ( ParseWithPredicates )
+ {
+ if (alt1->predicate != NULL) predicate_free(alt1->predicate); /* MR12 */
+ if (alt2->predicate != NULL) predicate_free(alt2->predicate); /* MR12 */
+
+ require(MR_PredRuleRefStack.count == 0,"PredRuleRef stack not empty");
+ alt1->predicate = MR_find_predicates_and_supp((Node *)alt1->p1);
+ require(MR_PredRuleRefStack.count == 0,"PredRuleRef stack not empty");
+ require (MR_predicate_context_completed(alt1->predicate),"predicate alt 1 not completed");
+ alt1->predicate=MR_predSimplifyALL(alt1->predicate);
+
+ require(MR_PredRuleRefStack.count == 0,"PredRuleRef stack not empty");
+ alt2->predicate = MR_find_predicates_and_supp((Node *)alt2->p1);
+ require(MR_PredRuleRefStack.count == 0,"PredRuleRef stack not empty");
+ require (MR_predicate_context_completed(alt2->predicate),"predicate alt 2 not completed");
+ alt2->predicate=MR_predSimplifyALL(alt2->predicate);
+
+ MR_doPredicatesHelp(0,alt1,alt2,jtype,sub);
+
+ if ( HoistPredicateContext
+ && (alt1->predicate!=NULL||alt2->predicate!=NULL) )
+ {
+ verify_context(alt1->predicate);
+ verify_context(alt2->predicate);
+ }
+
+ if ( HoistPredicateContext
+ && (alt1->predicate!=NULL||alt2->predicate!=NULL)
+ && WarningLevel>1 )
+ ensure_predicates_cover_ambiguous_lookahead_sequences(alt1, alt2, sub, ambig);
+ }
+
+ if ( WarningLevel>1 )
+ {
+ fprintf(stderr, ErrHdr, FileStr[alt1->file], alt1->line);
+ if ( jtype == aLoopBegin || jtype == aPlusBlk )
+ fprintf(stderr, " warning: optional/exit path and alt(s) %sambiguous upon", sub);
+ else
+ fprintf(stderr, " warning(approx): alts %d and %d %sambiguous upon",
+ alt1->altnum, alt2->altnum, sub);
+ dumpAmbigMsg(fset, stderr, 0);
+ MR_traceAmbSource(fset,alt1,alt2);
+ }
+ for (i=1; i<=CLL_k; i++) set_free( fset[i] );
+ free((char *)fset);
+ for (i=1; i<=CLL_k; i++) free( (char *)ftbl[i] );
+ free((char *)ftbl);
+ return;
+ }
+
+ /* if all sets have degree 1 for k<LL_k, then must be ambig upon >=1 permutation;
+ * don't bother doing full LL(k) analysis.
+ * (This "if" block handles the LL(1) case)
+ */
+
+ n2 = 0;
+ for (i=1; i<LL_k; i++) n2 += set_deg(alt1->fset[i])+set_deg(alt2->fset[i]);
+
+ /* here STARTS the special case in which the lookahead sets for alt1 and alt2
+ all have degree 1 for k<LL_k (including LL_k=1)
+ */
+
+ if ( n2==2*(LL_k-1) )
+ {
+
+ /* TJP: added to fix the case where LL(1) and syntactic predicates didn't
+ * work. It now recognizes syntactic predicates, but does not like combo:
+ * LL(1)/syn/sem predicates. (10/24/93)
+ */
+
+ if ( first_item_is_guess_block_extra((Junction *)alt1->p1)!=NULL )
+ {
+ if ( WarningLevel==1 )
+ {
+ for (i=1; i<=CLL_k; i++) set_free( fset[i] );
+ free((char *)fset);
+ for (i=1; i<=CLL_k; i++) free( (char *)ftbl[i] );
+ free((char *)ftbl);
+ return;
+ }
+
+ fprintf(stderr, ErrHdr, FileStr[alt1->file], alt1->line);
+ if ( jtype == aLoopBegin || jtype == aPlusBlk )
+ fprintf(stderr, " warning: optional/exit path and alt(s) %sambiguous upon", sub);
+ else
+ fprintf(stderr, " warning: alts %d and %d %sambiguous upon",
+ alt1->altnum, alt2->altnum, sub);
+ dumpAmbigMsg(fset, stderr, 0);
+ MR_traceAmbSource(fset,alt1,alt2);
+ }
+
+ ambig = NULL;
+ if ( LL_k>1 ) ambig = make_tree_from_sets(alt1->fset, alt2->fset);
+ if ( ParseWithPredicates )
+ {
+ if (alt1->predicate != NULL) predicate_free(alt1->predicate); /* MR12 */
+ if (alt2->predicate != NULL) predicate_free(alt2->predicate); /* MR12 */
+
+ require(MR_PredRuleRefStack.count == 0,"PredRuleRef stack not empty");
+ alt1->predicate = MR_find_predicates_and_supp((Node *)alt1->p1);
+ require(MR_PredRuleRefStack.count == 0,"PredRuleRef stack not empty");
+ require (MR_predicate_context_completed(alt1->predicate),"predicate alt 1 not completed");
+ alt1->predicate=MR_predSimplifyALL(alt1->predicate);
+
+ require(MR_PredRuleRefStack.count == 0,"PredRuleRef stack not empty");
+ alt2->predicate = MR_find_predicates_and_supp((Node *)alt2->p1);
+ require(MR_PredRuleRefStack.count == 0,"PredRuleRef stack not empty");
+ require (MR_predicate_context_completed(alt2->predicate),"predicate alt 2 not completed");
+ alt2->predicate=MR_predSimplifyALL(alt2->predicate);
+
+ MR_doPredicatesHelp(0,alt1,alt2,jtype,sub);
+
+ if ( HoistPredicateContext && (alt1->predicate!=NULL||alt2->predicate!=NULL) )
+ {
+ verify_context(alt1->predicate);
+ verify_context(alt2->predicate);
+ }
+ if (HoistPredicateContext&&(alt1->predicate!=NULL||alt2->predicate!=NULL) && WarningLevel>1)
+ ensure_predicates_cover_ambiguous_lookahead_sequences(alt1, alt2, sub, ambig);
+ if ( WarningLevel == 1 &&
+ (alt1->predicate!=NULL||alt2->predicate!=NULL))
+ {
+ for (i=1; i<=CLL_k; i++) set_free( fset[i] );
+ free((char *)fset);
+ for (i=1; i<=CLL_k; i++) free( (char *)ftbl[i] );
+ free((char *)ftbl);
+ Tfree(ambig);
+ return;
+ }
+ }
+/* end TJP (10/24/93) */
+
+ fprintf(stderr, ErrHdr, FileStr[alt1->file], alt1->line);
+ if ( jtype == aLoopBegin || jtype == aPlusBlk )
+ fprintf(stderr, " warning: optional/exit path and alt(s) %sambiguous upon", sub);
+ else
+ fprintf(stderr, " warning: alts %d and %d %sambiguous upon",
+ alt1->altnum, alt2->altnum, sub);
+ if ( elevel == 3 && LL_k>1 )
+ {
+ preorder(ambig);
+ fprintf(stderr, "\n");
+ for (i=1; i<=CLL_k; i++) set_free( fset[i] );
+ free((char *)fset);
+ for (i=1; i<=CLL_k; i++) free( (char *)ftbl[i] );
+ free((char *)ftbl);
+ Tfree(ambig);
+ return;
+ };
+
+ Tfree(ambig);
+ dumpAmbigMsg(fset, stderr, 0);
+
+ /* because this is a special case in which both alt1 and alt2 have
+ lookahead sets of degree 1 for k<LL_k (including k=1) the linear
+ lookahead style search is adequate
+ */
+
+ MR_traceAmbSource(fset,alt1,alt2);
+
+ for (i=1; i<=CLL_k; i++) set_free( fset[i] );
+ free((char *)fset);
+ for (i=1; i<=CLL_k; i++) free( (char *)ftbl[i] );
+ free((char *)ftbl);
+ return;
+ }
+
+ /* here ENDS the special case in which the lookahead sets for alt1 and alt2
+ all have degree 1 for k<LL_k (including LL_k=1)
+ */
+
+ /* in case tree construction runs out of memory, set info to make good err msg */
+
+ CurAmbigAlt1 = alt1->altnum;
+ CurAmbigAlt2 = alt2->altnum;
+ CurAmbigbtype = sub;
+ CurAmbigfile = alt1->file;
+ CurAmbigline = alt1->line;
+
+ /* Don't do full LL(n) analysis if (...)? block because the block,
+ by definition, defies LL(n) analysis.
+ If guess (...)? block and ambiguous then don't remove anything from
+ 2nd alt to resolve ambig.
+ Want to predict with LL sup 1 ( n ) decision not LL(n) if guess block
+ since it is much cheaper than LL(n). LL sup 1 ( n ) "covers" the LL(n)
+ lookahead information.
+
+ Note: LL(n) context cannot be computed for semantic predicates when
+ followed by (..)?.
+
+ If (..)? then we scream "AAAHHHH! No LL(n) analysis will help"
+
+ Is 'ambig' always defined if we enter this if? I hope so
+ because the 'ensure...()' func references it. TJP Nov 1993.
+ */
+
+ /* THM MR30: Instead of using first_item_is_guss_block we use
+ first_item_is_guess_block_extra which will look inside a
+ loop block for a guess block. In other words ( (...)? )*.
+ It there is an ambiguity in this circumstance then we suppress
+ the normal methods of resolving ambiguities.
+ */
+
+ if ( first_item_is_guess_block_extra((Junction *)alt1->p1)!=NULL )
+ {
+ if ( ParseWithPredicates )
+ {
+ if (alt1->predicate != NULL) predicate_free(alt1->predicate); /* MR12 */
+ if (alt2->predicate != NULL) predicate_free(alt2->predicate); /* MR12 */
+ require(MR_PredRuleRefStack.count == 0,"PredRuleRef stack not empty");
+ alt1->predicate = MR_find_predicates_and_supp((Node *)alt1->p1);
+ require(MR_PredRuleRefStack.count == 0,"PredRuleRef stack not empty");
+ require (MR_predicate_context_completed(alt1->predicate),"predicate alt 1 not completed");
+ alt1->predicate=MR_predSimplifyALL(alt1->predicate);
+
+ require(MR_PredRuleRefStack.count == 0,"PredRuleRef stack not empty");
+ alt2->predicate = MR_find_predicates_and_supp((Node *)alt2->p1);
+ require(MR_PredRuleRefStack.count == 0,"PredRuleRef stack not empty");
+ require (MR_predicate_context_completed(alt2->predicate),"predicate alt 2 not completed");
+ alt2->predicate=MR_predSimplifyALL(alt2->predicate);
+
+ MR_doPredicatesHelp(1,alt1,alt2,jtype,sub);
+
+ if ( HoistPredicateContext && (alt1->predicate!=NULL||alt2->predicate!=NULL) )
+ {
+ verify_context(alt1->predicate);
+ verify_context(alt2->predicate);
+ }
+ if ( HoistPredicateContext && (alt1->predicate!=NULL||alt2->predicate!=NULL) && WarningLevel>1 )
+ ensure_predicates_cover_ambiguous_lookahead_sequences(alt1, alt2, sub, ambig);
+ if ( WarningLevel==1 &&
+ (alt1->predicate!=NULL||alt2->predicate!=NULL))
+ {
+ for (i=1; i<=CLL_k; i++) set_free( fset[i] );
+ free((char *)fset);
+ for (i=1; i<=CLL_k; i++) free( (char *)ftbl[i] );
+ free((char *)ftbl);
+ return;
+ }
+ }
+
+ if ( WarningLevel>1 )
+ {
+ fprintf(stderr, ErrHdr, FileStr[alt1->file], alt1->line);
+ if ( jtype == aLoopBegin || jtype == aPlusBlk )
+ fprintf(stderr, " warning: optional/exit path and alt(s) %sambiguous upon", sub);
+ else
+ fprintf(stderr, " warning: alts %d and %d %sambiguous upon",
+ alt1->altnum, alt2->altnum, sub);
+ dumpAmbigMsg(fset, stderr, 0);
+ MR_traceAmbSource(fset,alt1,alt2);
+ }
+
+ for (i=1; i<=CLL_k; i++) set_free( fset[i] );
+ free((char *)fset);
+ for (i=1; i<=CLL_k; i++) free( (char *)ftbl[i] );
+ free((char *)ftbl);
+ return;
+ }
+
+ /* Not resolved with (..)? block. Do full LL(n) analysis */
+
+ /* ambig is the set of k-tuples truly in common between alt 1 and alt 2 */
+ /* MR11 VerifyAmbig once used fset destructively */
+
+ ambig = VerifyAmbig(alt1, alt2, ftbl, fset, &t, &u, &numAmbig);
+
+ /* are all things in intersection really ambigs? */
+
+ if (thisOverflow || numAmbig < n ) /* MR9 */
+ {
+ Tree *v;
+
+ /* remove ambig permutation from 2nd alternative to resolve ambig;
+ * We want to compute the set of artificial tuples, arising from
+ * LL sup 1 (n) compression, that collide with real tuples from the
+ * 2nd alternative. This is the set of "special case" tuples that
+ * the LL sup 1 (n) decision template maps incorrectly.
+ */
+
+ /* when generating code in genExpr() it does
+ *
+ * if ( genExprSets(j->fset) && !genExprTree(j->ftree)) {...
+ *
+ * Sooooo the j->ftree is the tree of alt2
+ * after removal of conflicts, not alt1 !
+ */
+
+ if ( ambig!=NULL )
+ {
+ /* at the top of ambig is an ALT node */
+
+ for (v=ambig->down; v!=NULL; v=v->right)
+ {
+ u = trm_perm(u, v); /* remove v FROM u */
+ }
+/* fprintf(stderr, "after rm alt2:"); preorder(u); fprintf(stderr, "\n");*/
+ }
+ Tfree( t );
+ alt1->ftree = tappend(alt1->ftree, u);
+ alt1->ftree = tleft_factor(alt1->ftree);
+ }
+
+ if ( ambig==NULL )
+ {
+ for (i=1; i<=CLL_k; i++) set_free( fset[i] );
+ free((char *)fset);
+ for (i=1; i<=CLL_k; i++) free( (char *)ftbl[i] );
+ free((char *)ftbl);
+ return;
+ }
+
+ ambig = tleft_factor(ambig);
+
+/* TJP:
+ * At this point, we surely have an LL(k) ambiguity. Check for predicates
+ */
+ if ( ParseWithPredicates )
+ {
+ if (alt1->predicate != NULL) predicate_free(alt1->predicate); /* MR12 */
+ if (alt2->predicate != NULL) predicate_free(alt2->predicate); /* MR12 */
+ require(MR_PredRuleRefStack.count == 0,"PredRuleRef stack not empty");
+ alt1->predicate = MR_find_predicates_and_supp((Node *)alt1->p1);
+ require(MR_PredRuleRefStack.count == 0,"PredRuleRef stack not empty");
+ require (MR_predicate_context_completed(alt1->predicate),"predicate alt 1 not completed");
+ alt1->predicate=MR_predSimplifyALL(alt1->predicate);
+
+ require(MR_PredRuleRefStack.count == 0,"PredRuleRef stack not empty");
+ alt2->predicate = MR_find_predicates_and_supp((Node *)alt2->p1);
+ require(MR_PredRuleRefStack.count == 0,"PredRuleRef stack not empty");
+ require (MR_predicate_context_completed(alt2->predicate),"predicate alt 2 not completed");
+ alt2->predicate=MR_predSimplifyALL(alt2->predicate);
+
+ MR_doPredicatesHelp(0,alt1,alt2,jtype,sub);
+
+ if ( HoistPredicateContext && (alt1->predicate!=NULL||alt2->predicate!=NULL) )
+ {
+ verify_context(alt1->predicate);
+ verify_context(alt2->predicate);
+ }
+ if ( HoistPredicateContext && (alt1->predicate!=NULL||alt2->predicate!=NULL) && WarningLevel>1 )
+ ensure_predicates_cover_ambiguous_lookahead_sequences(alt1, alt2, sub, ambig);
+ if ( WarningLevel==1 &&
+ (alt1->predicate!=NULL||alt2->predicate!=NULL))
+ {
+
+ /* We found at least one pred for at least one of the alts;
+ * If warnings are low, just return.
+ */
+
+ Tfree(ambig);
+ for (i=1; i<=CLL_k; i++) set_free( fset[i] );
+ free((char *)fset);
+ for (i=1; i<=CLL_k; i++) free( (char *)ftbl[i] );
+ free((char *)ftbl);
+ return;
+ }
+ /* else we're gonna give a warning */
+ }
+/* end TJP addition */
+
+ fprintf(stderr, ErrHdr, FileStr[alt1->file], alt1->line);
+ if ( jtype == aLoopBegin || jtype == aPlusBlk )
+ fprintf(stderr, " warning: optional/exit path and alt(s) %sambiguous upon", sub);
+ else
+ fprintf(stderr, " warning: alts %d and %d %sambiguous upon",
+ alt1->altnum, alt2->altnum, sub);
+ if ( elevel == 3 )
+ {
+ preorder(ambig->down); /* <===== k>1 ambiguity message data */
+ fprintf(stderr, "\n");
+ } else {
+ MR_skipped_e3_report=1;
+ dumpAmbigMsg(fset, stderr, 0);
+ };
+
+ MR_traceAmbSourceK(ambig,alt1,alt2); /* <====== k>1 ambiguity aid */
+
+ Tfree(ambig);
+
+ for (i=1; i<=CLL_k; i++) set_free( fset[i] );
+ free((char *)fset);
+ for (i=1; i<=CLL_k; i++) free( (char *)ftbl[i] );
+ free((char *)ftbl);
+}
+
+/* Don't analyze alpha block of (alpha)?beta; if (alpha)? then analyze
+ * Return the 1st node of the beta block if present else return j.
+ */
+Junction *
+#ifdef __USE_PROTOS
+analysis_point( Junction *j )
+#else
+analysis_point( j )
+Junction *j;
+#endif
+{
+ Junction *gblock;
+
+ /* MR13b When there was an action/predicate preceding a guess block
+ the guess block became invisible at the analysis_point.
+
+ first_item_is_guess_block accepts any kind of node,
+ despite the fact that the formal is a junction. But
+ I don't want to have to change it all over the place
+ until I know it works.
+ */
+
+ if ( j->ntype != nJunction && j->ntype != nAction) return j;
+
+ gblock = first_item_is_guess_block((Junction *)j);
+
+ if ( gblock!=NULL )
+ {
+ Junction *past = gblock->end;
+ Junction *p;
+ require(past!=NULL, "analysis_point: no end block on (...)? block");
+
+ for (p=(Junction *)past->p1; p!=NULL; )
+ {
+ if ( p->ntype==nAction )
+ {
+ p=(Junction *)((ActionNode *)p)->next;
+ continue;
+ }
+ if ( p->ntype!=nJunction )
+ {
+ past->alpha_beta_guess_end=1; /* MR14 */
+ return (Junction *)past->p1;
+ }
+ if ( p->jtype==EndBlk || p->jtype==EndRule )
+ {
+ return j;
+ }
+/* MR6 */
+/* MR6 A guess block is of the form "(alpha)? beta" or "(alpha)?". */
+/* MR6 When beta is omitted (second form) this means "(alpha)? alpha". */
+/* MR6 The program does not store another copy of alpha in this case. */
+/* MR6 During analysis when the program needs to know what follows the */
+/* MR6 guess clause. It calls this routine. */
+/* MR6 */
+/* MR6 If it is of the form "(alpha)? beta" it returns a pointer to beta.*/
+/* MR6 */
+/* MR6 If it is of the form "(alpha)?" it returns a pointer to the guess */
+/* MR6 block itself thereby reusing the junction tree. */
+/* MR6 */
+/* MR6 It works by searching the "next in sequence" chain (skipping actions) */
+/* MR6 searching for a RuleRef or Token node. (Those are the only 4 kinds */
+/* MR6 of nodes: Junctions, RuleRef, Token, and Action.) */
+/* MR6 */
+/* MR6 This won't work for the special case "(alpha)? ()" because it has no */
+/* MR6 rule references or token nodes. It eventually encounters a */
+/* MR6 junction of type EndBlk or EndRule and says to its caller: nothing */
+/* MR6 more here to analyze - must be of the form "(alpha)?". */
+/* MR6 */
+/* MR6 In the case of "(alpha)? ()" it should return a pointer to "()" */
+/* MR6 */
+/* MR6 I think. */
+/* MR6 */
+ if ( p->jtype!=Generic) { /* MR6 */
+ past->alpha_beta_guess_end=1; /* MR14 */
+ return (Junction *)past->p1; /* MR6 */
+ }; /* MR6 */
+ p=(Junction *)p->p1;
+ }
+ }
+ return j;
+}
+
+set
+#ifdef __USE_PROTOS
+First( Junction *j, int k, int jtype, int *max_k )
+#else
+First( j, k, jtype, max_k )
+Junction *j;
+int k;
+int jtype;
+int *max_k;
+#endif
+{
+ Junction *alt1, *alt2;
+ set a, rk, fCurBlk;
+ int savek;
+ int p1, p2;
+
+ int save_maintainBackTrace;
+
+ require(j->ntype==nJunction, "First: non junction passed");
+
+ /* C o m p u t e F I R S T s e t w i t h k l o o k a h e a d */
+ fCurBlk = rk = empty;
+ for (alt1=j; alt1!=NULL; alt1 = (Junction *)alt1->p2 )
+ {
+ Junction * p = NULL;
+ Junction * p1junction = NULL;
+ p = analysis_point((Junction *)alt1->p1);
+ p1junction = (Junction *) (alt1->p1);
+#if 0
+ if (p != p1junction) {
+ fprintf(stdout,"Analysis point for #%d is #%d", p1junction->seq, p->seq); /* debug */
+ }
+#endif
+ REACH(p, k, &rk, alt1->fset[k]);
+ require(set_nil(rk), "rk != nil");
+ set_free(rk);
+ set_orin(&fCurBlk, alt1->fset[k]);
+ }
+
+ /* D e t e c t A m b i g u i t i e s */
+ *max_k = 1;
+ for (p1=1,alt1=j; alt1!=NULL; alt1 = (Junction *)alt1->p2, p1++)
+ {
+ for (p2=1,alt2=(Junction *)alt1->p2; alt2!=NULL; alt2 = (Junction *)alt2->p2, p2++)
+ {
+ savek = k;
+ a = set_and(alt1->fset[k], alt2->fset[k]);
+ while ( !set_nil(a) )
+ {
+ /* if we have hit the max k requested, just give warning */
+ if ( j->approx==k ) {
+ }
+
+ if ( k==CLL_k )
+ {
+#ifdef NOT_USED
+*** int save_LL_k = LL_k;
+*** int save_CLL_k = CLL_k;
+*** /* Get new LL_k from interactive feature if enabled */
+*** if ( AImode )
+*** AmbiguityDialog(j, jtype, alt1, alt2, &CLL_k, &LL_k);
+#endif
+ *max_k = CLL_k;
+ save_maintainBackTrace=MR_MaintainBackTrace;
+ if (AlphaBetaTrace) MR_MaintainBackTrace=0;
+ HandleAmbiguity(j, alt1, alt2, jtype);
+ MR_MaintainBackTrace=save_maintainBackTrace;
+ break;
+ }
+ else
+ {
+ Junction *p = analysis_point((Junction *)alt1->p1);
+ Junction *q = analysis_point((Junction *)alt2->p1);
+ k++; /* attempt ambig alts again with more lookahead */
+
+ REACH(p, k, &rk, alt1->fset[k]);
+ require(set_nil(rk), "rk != nil");
+ REACH(q, k, &rk, alt2->fset[k]);
+ require(set_nil(rk), "rk != nil");
+ set_free(a);
+ a = set_and(alt1->fset[k], alt2->fset[k]);
+ if ( k > *max_k ) *max_k = k;
+ }
+ }
+ set_free(a);
+ k = savek;
+ }
+ }
+
+ return fCurBlk;
+}
diff --git a/Source/Pccts/antlr/fset2.c b/Source/Pccts/antlr/fset2.c
new file mode 100644
index 0000000..7f686a5
--- /dev/null
+++ b/Source/Pccts/antlr/fset2.c
@@ -0,0 +1,2250 @@
+/*
+ * fset2.c
+ *
+ * Compute FIRST sets for full LL(k)
+ *
+ * SOFTWARE RIGHTS
+ *
+ * We reserve no LEGAL rights to the Purdue Compiler Construction Tool
+ * Set (PCCTS) -- PCCTS is in the public domain. An individual or
+ * company may do whatever they wish with source code distributed with
+ * PCCTS or the code generated by PCCTS, including the incorporation of
+ * PCCTS, or its output, into commerical software.
+ *
+ * We encourage users to develop software with PCCTS. However, we do ask
+ * that credit is given to us for developing PCCTS. By "credit",
+ * we mean that if you incorporate our source code into one of your
+ * programs (commercial product, research project, or otherwise) that you
+ * acknowledge this fact somewhere in the documentation, research report,
+ * etc... If you like PCCTS and have developed a nice tool with the
+ * output, please mention that you developed it using PCCTS. In
+ * addition, we ask that this header remain intact in our source code.
+ * As long as these guidelines are kept, we expect to continue enhancing
+ * this system and expect to make other tools available as they are
+ * completed.
+ *
+ * ANTLR 1.33
+ * Terence Parr
+ * Parr Research Corporation
+ * with Purdue University and AHPCRC, University of Minnesota
+ * 1989-2001
+ */
+
+#include <stdio.h>
+#include "pcctscfg.h"
+#include <stdlib.h>
+
+#ifdef PCCTS_USE_STDARG
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+
+#include "set.h"
+#include "syn.h"
+#include "hash.h"
+#include "generic.h"
+#include "dlgdef.h"
+
+/* ick! globals. Used by permute() to track which elements of a set have been used */
+
+static int *findex;
+set *fset; /* MR11 make global */
+static unsigned **ftbl;
+static set *constrain; /* pts into fset. constrains tToken() to 'constrain' */
+int ConstrainSearch;
+int maxk; /* set to initial k upon tree construction request */
+ /* MR11 make global */
+static Tree *FreeList = NULL;
+
+#ifdef __USE_PROTOS
+static int tmember_of_context(Tree *, Predicate *);
+#else
+static int tmember_of_context();
+#endif
+
+#if TREE_DEBUG
+set set_of_tnodes_in_use;
+int stop_on_tnode_seq_number=(-1); /* (-1) to disable */
+#endif
+
+/* Do root
+ * Then each sibling
+ */
+
+void
+#ifdef __USE_PROTOS
+preorder( Tree *tree )
+#else
+preorder( tree )
+Tree *tree;
+#endif
+{
+ if ( tree == NULL ) return;
+ if ( tree->down != NULL ) fprintf(stderr, " (");
+ if ( tree->token == ALT ) fprintf(stderr, " ALT");
+ else fprintf(stderr, " %s", TerminalString(tree->token));
+ if ( tree->token==EpToken ) fprintf(stderr, "(%d)", tree->v.rk);
+ preorder(tree->down);
+ if ( tree->down != NULL ) fprintf(stderr, " )");
+ preorder(tree->right);
+}
+
+#ifdef __USE_PROTOS
+int MR_tree_matches_constraints(int k,set * constrain,Tree *t)
+#else
+int MR_tree_matches_constraints(k,constrain,t)
+ int k;
+ set * constrain;
+ Tree * t;
+#endif
+{
+ int i;
+ Tree *u;
+
+ if (k == 0) return 1;
+
+ /* for testing guard predicates: if the guard tree is shorter
+ than the constraint then it is a match. The reason is that
+ a guard of (A B) should be equivalent to a guard of (A B . . .)
+ where "." matches every token. Thus a match which runs out
+ of tree before constraint is a match.
+ */
+
+ if (t == NULL) return 1;
+ require (set_deg(constrain[0]) == 1,
+ "MR_tree_matches_constraints: set_deg != 1");
+ i=set_int(constrain[0]);
+ if (t->token != i) return 0;
+ if (k-1 == 0) return 1;
+ for (u=t->down; u != NULL; u=u->right) {
+ if (MR_tree_matches_constraints(k-1,&constrain[1],u)) {
+ return 1;
+ };
+ };
+ return 0;
+}
+
+/* check the depth of each primary sibling to see that it is exactly
+ * k deep. e.g.;
+ *
+ * ALT
+ * |
+ * A ------- B
+ * | |
+ * C -- D E
+ *
+ * Remove all branches <= k deep.
+ *
+ * Added by TJP 9-23-92 to make the LL(k) constraint mechanism to work.
+ */
+
+static int pruneCount=0;
+static int prunePeak=200;
+
+Tree *
+#ifdef __USE_PROTOS
+prune( Tree *t, int k )
+#else
+prune( t, k )
+Tree *t;
+int k;
+#endif
+{
+ pruneCount++;
+ if (pruneCount > prunePeak+100) {
+ prunePeak=pruneCount;
+#if 0
+*** fprintf(stderr,"pruneCount=%d\n",pruneCount);
+/*** preorder(t); ***/
+*** fprintf(stderr,"\n",pruneCount);
+#endif
+ };
+ if ( t == NULL ) {
+ pruneCount--;
+ return NULL;
+ };
+ if ( t->token == ALT ) fatal_internal("prune: ALT node in FIRST tree");
+ if ( t->right!=NULL ) t->right = prune(t->right, k);
+ if ( k>1 )
+ {
+ if ( t->down!=NULL ) t->down = prune(t->down, k-1);
+ if ( t->down == NULL )
+ {
+ Tree *r = t->right;
+ t->right = NULL;
+ Tfree(t);
+ pruneCount--;
+ return r;
+ }
+ }
+ pruneCount--;
+ return t;
+}
+
+/* build a tree (root child1 child2 ... NULL) */
+#ifdef PCCTS_USE_STDARG
+Tree *tmake(Tree *root, ...)
+#else
+Tree *tmake(va_alist)
+va_dcl
+#endif
+{
+ Tree *w;
+ va_list ap;
+ Tree *child, *sibling=NULL, *tail=NULL;
+#ifndef PCCTS_USE_STDARG
+ Tree *root;
+#endif
+
+#ifdef PCCTS_USE_STDARG
+ va_start(ap, root);
+#else
+ va_start(ap);
+ root = va_arg(ap, Tree *);
+#endif
+ child = va_arg(ap, Tree *);
+ while ( child != NULL )
+ {
+#ifdef DUM
+ /* added "find end of child" thing TJP March 1994 */
+ for (w=child; w->right!=NULL; w=w->right) {;} /* find end of child */
+#else
+ w = child;
+#endif
+
+ if ( sibling == NULL ) {sibling = child; tail = w;}
+ else {tail->right = child; tail = w;}
+ child = va_arg(ap, Tree *);
+ }
+
+ /* was "root->down = sibling;" */
+ if ( root==NULL ) root = sibling;
+ else root->down = sibling;
+
+ va_end(ap);
+ return root;
+}
+
+Tree *
+#ifdef __USE_PROTOS
+tnode( int tok )
+#else
+tnode( tok )
+int tok;
+#endif
+{
+ Tree *p, *newblk;
+ static int n=0;
+
+ if ( FreeList == NULL )
+ {
+ /*fprintf(stderr, "tnode: %d more nodes\n", TreeBlockAllocSize);*/
+ if ( TreeResourceLimit > 0 )
+ {
+ if ( (n+TreeBlockAllocSize) >= TreeResourceLimit )
+ {
+ fprintf(stderr, ErrHdr, FileStr[CurAmbigfile], CurAmbigline);
+ fprintf(stderr, " hit analysis resource limit while analyzing alts %d and %d %s\n",
+ CurAmbigAlt1,
+ CurAmbigAlt2,
+ CurAmbigbtype);
+ exit(PCCTS_EXIT_FAILURE);
+ }
+ }
+ newblk = (Tree *)calloc(TreeBlockAllocSize, sizeof(Tree));
+ if ( newblk == NULL )
+ {
+ fprintf(stderr, ErrHdr, FileStr[CurAmbigfile], CurAmbigline);
+ fprintf(stderr, " out of memory while analyzing alts %d and %d %s\n",
+ CurAmbigAlt1,
+ CurAmbigAlt2,
+ CurAmbigbtype);
+ exit(PCCTS_EXIT_FAILURE);
+ }
+ n += TreeBlockAllocSize;
+ for (p=newblk; p<&(newblk[TreeBlockAllocSize]); p++)
+ {
+ p->right = FreeList; /* add all new Tree nodes to Free List */
+ FreeList = p;
+ }
+ }
+ p = FreeList;
+ FreeList = FreeList->right; /* remove a tree node */
+ p->right = NULL; /* zero out ptrs */
+ p->down = NULL;
+ p->token = tok;
+
+ TnodesAllocated++; /* MR10 */
+ TnodesInUse++; /* MR10 */
+ if (TnodesInUse > TnodesPeak) TnodesPeak=TnodesInUse; /* MR10 */
+
+#ifdef TREE_DEBUG
+ require(!p->in_use, "tnode: node in use!");
+ p->in_use = 1;
+ p->seq=TnodesAllocated;
+ set_orel( (unsigned) TnodesAllocated,&set_of_tnodes_in_use);
+ if (stop_on_tnode_seq_number == p->seq) {
+ fprintf(stderr,"\n*** just allocated tnode #%d ***\n",
+ stop_on_tnode_seq_number);
+ };
+#endif
+ return p;
+}
+
+static Tree *
+#ifdef __USE_PROTOS
+eofnode( int k )
+#else
+eofnode( k )
+int k;
+#endif
+{
+ Tree *t=NULL;
+ int i;
+
+ for (i=1; i<=k; i++)
+ {
+ t = tmake(tnode((TokenInd!=NULL?TokenInd[EofToken]:EofToken)), t, NULL);
+ }
+ return t;
+}
+
+
+
+void
+#ifdef __USE_PROTOS
+_Tfree( Tree *t )
+#else
+_Tfree( t )
+Tree *t;
+#endif
+{
+ if ( t!=NULL )
+ {
+#ifdef TREE_DEBUG
+ if (t->seq == stop_on_tnode_seq_number) {
+ fprintf(stderr,"\n*** just freed tnode #%d ***\n",t->seq);
+ };
+ require(t->in_use, "_Tfree: node not in use!");
+ t->in_use = 0;
+ set_rm( (unsigned) t->seq,set_of_tnodes_in_use);
+#endif
+ t->right = FreeList;
+ FreeList = t;
+ TnodesInUse--; /* MR10 */
+ }
+}
+
+/* tree duplicate */
+Tree *
+#ifdef __USE_PROTOS
+tdup( Tree *t )
+#else
+tdup( t )
+Tree *t;
+#endif
+{
+ Tree *u;
+
+ if ( t == NULL ) return NULL;
+ u = tnode(t->token);
+ u->v.rk = t->v.rk;
+ u->right = tdup(t->right);
+ u->down = tdup(t->down);
+ return u;
+}
+
+/* tree duplicate (assume tree is a chain downwards) */
+Tree *
+#ifdef __USE_PROTOS
+tdup_chain( Tree *t )
+#else
+tdup_chain( t )
+Tree *t;
+#endif
+{
+ Tree *u;
+
+ if ( t == NULL ) return NULL;
+ u = tnode(t->token);
+ u->v.rk = t->v.rk;
+ u->down = tdup(t->down);
+ return u;
+}
+
+Tree *
+#ifdef __USE_PROTOS
+tappend( Tree *t, Tree *u )
+#else
+tappend( t, u )
+Tree *t;
+Tree *u;
+#endif
+{
+ Tree *w;
+
+/*** fprintf(stderr, "tappend(");
+ *** preorder(t); fprintf(stderr, ",");
+ *** preorder(u); fprintf(stderr, " )\n");
+*/
+ if ( t == NULL ) return u;
+ if ( t->token == ALT && t->right == NULL ) return tappend(t->down, u);
+ for (w=t; w->right!=NULL; w=w->right) {;}
+ w->right = u;
+ return t;
+}
+
+/* dealloc all nodes in a tree */
+void
+#ifdef __USE_PROTOS
+Tfree( Tree *t )
+#else
+Tfree( t )
+Tree *t;
+#endif
+{
+ if ( t == NULL ) return;
+ Tfree( t->down );
+ Tfree( t->right );
+ _Tfree( t );
+}
+
+/* find all children (alts) of t that require remaining_k nodes to be LL_k
+ * tokens long.
+ *
+ * t-->o
+ * |
+ * a1--a2--...--an <-- LL(1) tokens
+ * | | |
+ * b1 b2 ... bn <-- LL(2) tokens
+ * | | |
+ * . . .
+ * . . .
+ * z1 z2 ... zn <-- LL(LL_k) tokens
+ *
+ * We look for all [Ep] needing remaining_k nodes and replace with u.
+ * u is not destroyed or actually used by the tree (a copy is made).
+ */
+Tree *
+#ifdef __USE_PROTOS
+tlink( Tree *t, Tree *u, int remaining_k )
+#else
+tlink( t, u, remaining_k )
+Tree *t;
+Tree *u;
+int remaining_k;
+#endif
+{
+ Tree *p;
+ require(remaining_k!=0, "tlink: bad tree");
+
+ if ( t==NULL ) return NULL;
+ /*fprintf(stderr, "tlink: u is:"); preorder(u); fprintf(stderr, "\n");*/
+ if ( t->token == EpToken && t->v.rk == remaining_k )
+ {
+ require(t->down==NULL, "tlink: invalid tree");
+ if ( u == NULL ) {
+/* MR10 */ Tree *tt=t->right;
+/* MR10 */ _Tfree(t);
+/* MR10 */ return tt;
+ };
+ p = tdup( u );
+ p->right = t->right;
+ _Tfree( t );
+ return p;
+ }
+ t->down = tlink(t->down, u, remaining_k);
+ t->right = tlink(t->right, u, remaining_k);
+ return t;
+}
+
+/* remove as many ALT nodes as possible while still maintaining semantics */
+Tree *
+#ifdef __USE_PROTOS
+tshrink( Tree *t )
+#else
+tshrink( t )
+Tree *t;
+#endif
+{
+ if ( t == NULL ) return NULL;
+ t->down = tshrink( t->down );
+ t->right = tshrink( t->right );
+ if ( t->down == NULL )
+ {
+ if ( t->token == ALT )
+ {
+ Tree *u = t->right;
+ _Tfree(t);
+ return u; /* remove useless alts */
+ }
+ return t;
+ }
+
+ /* (? (ALT (? ...)) s) ==> (? (? ...) s) where s = sibling, ? = match any */
+ if ( t->token == ALT && t->down->right == NULL)
+ {
+ Tree *u = t->down;
+ u->right = t->right;
+ _Tfree( t );
+ return u;
+ }
+ /* (? (A (ALT t)) s) ==> (? (A t) s) where A is a token; s,t siblings */
+ if ( t->token != ALT && t->down->token == ALT && t->down->right == NULL )
+ {
+ Tree *u = t->down->down;
+ _Tfree( t->down );
+ t->down = u;
+ return t;
+ }
+ return t;
+}
+
+Tree *
+#ifdef __USE_PROTOS
+tflatten( Tree *t )
+#else
+tflatten( t )
+Tree *t;
+#endif
+{
+ if ( t == NULL ) return NULL;
+ t->down = tflatten( t->down );
+ t->right = tflatten( t->right );
+ if ( t->down == NULL ) return t;
+
+ if ( t->token == ALT )
+ {
+ Tree *u;
+ /* find tail of children */
+ for (u=t->down; u->right!=NULL; u=u->right) {;}
+ u->right = t->right;
+ u = t->down;
+ _Tfree( t );
+ return u;
+ }
+ return t;
+}
+
+Tree *
+#ifdef __USE_PROTOS
+tJunc( Junction *p, int k, set *rk )
+#else
+tJunc( p, k, rk )
+Junction *p;
+int k;
+set *rk;
+#endif
+{
+ Tree *t=NULL, *u=NULL;
+ Junction *alt;
+ Tree *tail=NULL, *r;
+
+#ifdef DBG_TRAV
+ fprintf(stderr, "tJunc(%d): %s in rule %s\n", k,
+ decodeJType[p->jtype], ((Junction *)p)->rname);
+#endif
+
+/* MR14 */ if (AlphaBetaTrace && p->alpha_beta_guess_end) {
+/* MR14 */ warnFL(
+/* MR14 */ "not possible to compute follow set for alpha in an \"(alpha)? beta\" block. ",
+/* MR14 */ FileStr[p->file],p->line);
+/* MR14 */ MR_alphaBetaTraceReport();
+/* MR14 */ };
+
+/* MR14 */ if (p->alpha_beta_guess_end) {
+/* MR14 */ return NULL;
+/* MR14 */ }
+
+ if ( p->jtype==aLoopBlk || p->jtype==RuleBlk ||
+ p->jtype==aPlusBlk || p->jtype==aSubBlk || p->jtype==aOptBlk )
+ {
+ if ( p->jtype!=aSubBlk && p->jtype!=aOptBlk ) {
+ require(p->lock!=NULL, "rJunc: lock array is NULL");
+ if ( p->lock[k] ) return NULL;
+ p->lock[k] = TRUE;
+ }
+
+/* MR10 */ if (MR_MaintainBackTrace) {
+/* MR10 */ if (p->jtype != Generic) MR_pointerStackPush(&MR_BackTraceStack,p);
+/* MR10 */ };
+
+ TRAV(p->p1, k, rk, tail);
+
+/* MR10 */ if (MR_MaintainBackTrace) {
+/* MR10 */ if (p->jtype != Generic) MR_pointerStackPop(&MR_BackTraceStack);
+/* MR10 */ };
+
+ if ( p->jtype==RuleBlk ) {p->lock[k] = FALSE; return tail;}
+ r = tmake(tnode(ALT), tail, NULL);
+ for (alt=(Junction *)p->p2; alt!=NULL; alt = (Junction *)alt->p2)
+ {
+ /* if this is one of the added optional alts for (...)+ then break */
+ if ( alt->ignore ) break;
+
+ if ( tail==NULL ) {TRAV(alt->p1, k, rk, tail); r->down = tail;}
+ else
+ {
+/* MR10 */ if (MR_MaintainBackTrace) {
+/* MR10 */ if (p->jtype != Generic) MR_pointerStackPush(&MR_BackTraceStack,p);
+/* MR10 */ };
+
+ TRAV(alt->p1, k, rk, tail->right);
+
+/* MR10 */ if (MR_MaintainBackTrace) {
+/* MR10 */ if (p->jtype != Generic) MR_pointerStackPop(&MR_BackTraceStack);
+/* MR10 */ };
+ if ( tail->right != NULL ) tail = tail->right;
+ }
+ }
+ if ( p->jtype!=aSubBlk && p->jtype!=aOptBlk ) p->lock[k] = FALSE;
+#ifdef DBG_TREES
+ fprintf(stderr, "blk(%s) returns:",((Junction *)p)->rname); preorder(r); fprintf(stderr, "\n");
+#endif
+ if ( r->down == NULL ) {_Tfree(r); return NULL;}
+ return r;
+ }
+
+ if ( p->jtype==EndRule )
+ {
+ if ( p->halt ) /* don't want FOLLOW here? */
+ {
+/**** if ( ContextGuardTRAV ) return NULL; ****/
+ set_orel( (unsigned) k, rk); /* indicate this k value needed */ /* MR10 cast */
+ t = tnode(EpToken);
+ t->v.rk = k;
+ return t;
+ }
+ require(p->lock!=NULL, "rJunc: lock array is NULL");
+ if ( p->lock[k] ) return NULL;
+ /* if no FOLLOW assume k EOF's */
+ if ( p->p1 == NULL ) return eofnode(k);
+ p->lock[k] = TRUE;
+ }
+
+/* MR14 */ if (p->p1 != NULL && p->guess && p->guess_analysis_point == NULL) {
+/* MR14 */ Node * guess_point;
+/* MR14 */ guess_point=(Node *)analysis_point(p);
+/* MR14 */ if (guess_point == (Node *)p) {
+/* MR14 */ guess_point=p->p1;
+/* MR14 */ }
+/* MR14 */ p->guess_analysis_point=guess_point;
+/* MR14 */ }
+
+ if ( p->p2 == NULL )
+ {
+
+/* MR10 */ if (MR_MaintainBackTrace) {
+/* MR10 */ if (p->jtype != Generic) MR_pointerStackPush(&MR_BackTraceStack,p);
+/* MR10 */ };
+
+/* M14 */ if (p->guess_analysis_point != NULL) {
+/* M14 */ TRAV(p->guess_analysis_point, k, rk,t);
+/* M14 */ } else {
+ TRAV(p->p1, k, rk,t);
+/* M14 */ }
+
+/* MR10 */ if (MR_MaintainBackTrace) {
+/* MR10 */ if (p->jtype != Generic) MR_pointerStackPop(&MR_BackTraceStack);
+/* MR10 */ };
+
+ if ( p->jtype==EndRule ) p->lock[k]=FALSE;
+ return t;
+ }
+
+/* MR10 */ if (MR_MaintainBackTrace) {
+/* MR10 */ if (p->jtype != Generic) MR_pointerStackPush(&MR_BackTraceStack,p);
+/* MR10 */ };
+
+/* M14 */ if (p->guess_analysis_point != NULL) {
+/* M14 */ TRAV(p->guess_analysis_point, k, rk,t);
+/* M14 */ } else {
+ TRAV(p->p1, k, rk,t);
+/* M14 */ }
+
+/* MR10 */ if (MR_MaintainBackTrace) {
+/* MR10 */ if (p->jtype != Generic) MR_pointerStackPop(&MR_BackTraceStack);
+/* MR10 */ };
+
+ if ( p->jtype!=RuleBlk && /* MR14 */ !p->guess) TRAV(p->p2, k, rk, u);
+
+ if ( p->jtype==EndRule ) p->lock[k] = FALSE;/* unlock node */
+
+ if ( t==NULL ) return tmake(tnode(ALT), u, NULL);
+ return tmake(tnode(ALT), t, u, NULL);
+}
+
+Tree *
+#ifdef __USE_PROTOS
+tRuleRef( RuleRefNode *p, int k, set *rk_out )
+#else
+tRuleRef( p, k, rk_out )
+RuleRefNode *p;
+int k;
+set *rk_out;
+#endif
+{
+ int k2;
+ Tree *t=NULL, *u=NULL;
+ Junction *r;
+ set rk, rk2;
+ int save_halt;
+ RuleEntry *q = (RuleEntry *) hash_get(Rname, p->text);
+
+#ifdef DBG_TRAV
+ fprintf(stderr, "tRuleRef: %s\n", p->text);
+#endif
+ if ( q == NULL )
+ {
+ TRAV(p->next, k, rk_out, t);/* ignore undefined rules */
+ return t;
+ }
+ rk = rk2 = empty;
+ if (RulePtr == NULL) fatal("RulePtr==NULL");
+ r = RulePtr[q->rulenum];
+ if ( r->lock[k] ) return NULL;
+ save_halt = r->end->halt;
+ r->end->halt = TRUE; /* don't let reach fall off end of rule here */
+
+/* MR10 */ if (MR_MaintainBackTrace) {
+/* MR10 */ MR_pointerStackPush(&MR_BackTraceStack,p);
+/* MR10 */ };
+
+ TRAV(r, k, &rk, t);
+
+/* MR10 */ if (MR_MaintainBackTrace) {
+/* MR10 */ MR_pointerStackPop(&MR_BackTraceStack);
+/* MR10 */ };
+
+ r->end->halt = save_halt;
+#ifdef DBG_TREES
+ fprintf(stderr, "after ruleref, t is:"); preorder(t); fprintf(stderr, "\n");
+#endif
+ t = tshrink( t );
+ while ( !set_nil(rk) ) { /* any k left to do? if so, link onto tree */
+ k2 = set_int(rk);
+ set_rm(k2, rk);
+
+/* MR10 */ if (MR_MaintainBackTrace) {
+/* MR10 */ MR_pointerStackPush(&MR_BackTraceStack,p);
+/* MR10 */ };
+
+ TRAV(p->next, k2, &rk2, u);
+
+/* MR10 */ if (MR_MaintainBackTrace) {
+/* MR10 */ MR_pointerStackPop(&MR_BackTraceStack);
+/* MR10 */ };
+
+ t = tlink(t, u, k2); /* any alts missing k2 toks, add u onto end */
+ Tfree(u); /* MR10 */
+ }
+ set_free(rk); /* rk is empty, but free it's memory */
+ set_orin(rk_out, rk2); /* remember what we couldn't do */
+ set_free(rk2);
+ return t;
+}
+
+Tree *
+#ifdef __USE_PROTOS
+tToken( TokNode *p, int k, set *rk )
+#else
+tToken( p, k, rk )
+TokNode *p;
+int k;
+set *rk;
+#endif
+{
+ Tree *t=NULL, *tset=NULL, *u;
+
+ if (ConstrainSearch) {
+ if (MR_AmbSourceSearch) {
+ require(constrain>=fset&&constrain<=&(fset[CLL_k]),"tToken: constrain is not a valid set");
+ } else {
+ require(constrain>=fset&&constrain<=&(fset[LL_k]),"tToken: constrain is not a valid set");
+ };
+ constrain = &fset[maxk-k+1];
+ }
+
+#ifdef DBG_TRAV
+ fprintf(stderr, "tToken(%d): %s\n", k, TerminalString(p->token));
+ if ( ConstrainSearch ) {
+ fprintf(stderr, "constrain is:"); s_fprT(stderr, *constrain); fprintf(stderr, "\n");
+ }
+#endif
+
+ /* is it a meta token (set of tokens)? */
+
+ if ( !set_nil(p->tset) )
+ {
+ unsigned e=0;
+ set a;
+ Tree *n, *tail = NULL;
+
+ if ( ConstrainSearch ) {
+ a = set_and(p->tset, *constrain);
+ if (set_nil(a)) { /* MR10 */
+ set_free(a); /* MR11 */
+ return NULL; /* MR10 */
+ }; /* MR10 */
+ } else {
+ a = set_dup(p->tset);
+ };
+
+ for (; !set_nil(a); set_rm(e, a))
+ {
+ e = set_int(a);
+ n = tnode(e);
+ if ( tset==NULL ) { tset = n; tail = n; }
+ else { tail->right = n; tail = n; }
+ }
+ set_free( a );
+ }
+ else if ( ConstrainSearch && !set_el(p->token, *constrain) )
+ {
+/* fprintf(stderr, "ignoring token %s(%d)\n", TerminalString(p->token),
+ k);*/
+ return NULL;
+ }
+ else {
+ tset = tnode( p->token );
+ };
+
+/* MR10 */ if (MR_MaintainBackTrace) {
+/* MR10 */ if (k == 1) {
+/* MR10 */ MR_pointerStackPush(&MR_BackTraceStack,p);
+/* MR13 */ if (MR_SuppressSearch) {
+/* MR13 */ MR_suppressSearchReport();
+/* MR13 */ } else {
+/* MR10 */ MR_backTraceReport();
+/* MR13 */ };
+/* MR10 */ MR_pointerStackPop(&MR_BackTraceStack);
+/* MR11 */ Tfree(tset);
+/* MR11 */ return NULL;
+/* MR10 */ };
+/* MR10 */ };
+
+ if ( k == 1 ) return tset;
+
+ if (MR_MaintainBackTrace) {
+ MR_pointerStackPush(&MR_BackTraceStack,p);
+ };
+
+ TRAV(p->next, k-1, rk, t);
+
+ if (MR_MaintainBackTrace) {
+ Tfree(t);
+ Tfree(tset);
+ MR_pointerStackPop(&MR_BackTraceStack);
+ return NULL;
+ };
+
+ /* here, we are positive that, at least, this tree will not contribute
+ * to the LL(2) tree since it will be too shallow, IF t==NULL.
+ * If doing a context guard walk, then don't prune.
+ */
+ if ( t == NULL && !ContextGuardTRAV ) /* tree will be too shallow */
+ {
+ if ( tset!=NULL ) Tfree( tset );
+ return NULL;
+ }
+#ifdef DBG_TREES
+ fprintf(stderr, "tToken(%d)->next:",k); preorder(t); fprintf(stderr, "\n");
+#endif
+
+ /* if single token root, then just make new tree and return */
+ /* MR10 - set_nil(p->tset) isn't a good test because of ConstraintSearch */
+
+ if (tset->right == NULL) return tmake(tset, t, NULL); /* MR10 */
+
+ /* here we must make a copy of t as a child of each element of the tset;
+ * e.g., "T1..T3 A" would yield ( nil ( T1 A ) ( T2 A ) ( T3 A ) )
+ */
+ for (u=tset; u!=NULL; u=u->right)
+ {
+ /* make a copy of t and hook it onto bottom of u */
+ u->down = tdup(t);
+ }
+ Tfree( t );
+#ifdef DBG_TREES
+ fprintf(stderr, "range is:"); preorder(tset); fprintf(stderr, "\n");
+#endif
+ return tset;
+}
+
+Tree *
+#ifdef __USE_PROTOS
+tAction( ActionNode *p, int k, set *rk )
+#else
+tAction( p, k, rk )
+ActionNode *p;
+int k;
+set *rk;
+#endif
+{
+ Tree *t=NULL;
+ set *save_fset=NULL;
+ int i;
+
+ /* fprintf(stderr, "tAction\n"); */
+
+/* An MR_SuppressSearch is looking for things that can be
+ reached even when the predicate is false.
+
+ There are three kinds of predicates:
+ plain: r1: <<p>>? r2
+ guarded: r1: (A)? => <<p>>? r2
+ ampersand style: r1: (A)? && <<p>>? r2
+
+ Of the three kinds of predicates, only a guard predicate
+ has things which are reachable even when the predicate
+ is false. To be reachable the constraint must *not*
+ match the guard.
+
+*/
+
+ if (p->is_predicate && MR_SuppressSearch) {
+
+ Predicate *pred=p->guardpred;
+
+ if (pred == NULL) {
+ t=NULL;
+ goto EXIT;
+ };
+ constrain = &fset[maxk-k+1];
+ if (pred->k == 1) {
+ set dif;
+ dif=set_dif(*constrain,pred->scontext[1]);
+ if (set_nil(dif)) {
+ set_free(dif);
+ t=NULL;
+ goto EXIT;
+ };
+ set_free(dif);
+ } else {
+ if (MR_tree_matches_constraints(k,constrain,pred->tcontext)) {
+ t=NULL;
+ goto EXIT;
+ };
+ }
+ };
+
+ /* The ampersand predicate differs from the
+ other predicates because its first set
+ is a subset of the first set behind the predicate
+
+ r1: (A)? && <<p>>? r2 ;
+ r2: A | B;
+
+ In this case first[1] of r1 is A, even
+ though first[1] of r2 is {A B}.
+ */
+
+ if (p->is_predicate && p->ampersandPred != NULL) {
+
+ Predicate *pred=p->ampersandPred;
+ Tree *tAND;
+ Tree *tset;
+
+ if (k <= pred->k) {
+ if (MR_MaintainBackTrace) MR_pointerStackPush(&MR_BackTraceStack,p);
+ TRAV(p->guardNodes,k,rk,t);
+ if (MR_MaintainBackTrace) MR_pointerStackPop(&MR_BackTraceStack);
+ return t;
+ } else {
+ require (k>1,"tAction for ampersandpred: k <= 1");
+ if (ConstrainSearch) {
+ if (MR_AmbSourceSearch) {
+ require(constrain>=fset&&constrain<=&(fset[CLL_k]),
+ "tToken: constrain is not a valid set");
+ } else {
+ require(constrain>=fset&&constrain<=&(fset[LL_k]),
+ "tToken: constrain is not a valid set");
+ };
+ save_fset=(set *) calloc (CLL_k+1,sizeof(set));
+ require (save_fset != NULL,"tAction save_fset alloc");
+ for (i=1; i <= CLL_k ; i++) {
+ save_fset[i]=set_dup(fset[i]);
+ };
+ if (pred->k == 1) {
+ constrain = &fset[maxk-k+1];
+ set_andin(constrain,pred->scontext[1]);
+ if (set_nil(*constrain)) {
+ t=NULL;
+ goto EXIT;
+ };
+ } else {
+ constrain = &fset[maxk-k+1];
+ if (! MR_tree_matches_constraints(pred->k,constrain,pred->tcontext)) {
+ t=NULL;
+ goto EXIT;
+ }; /* end loop on i */
+ }; /* end loop on pred scontext/tcontext */
+ }; /* end if on k > pred->k */
+ }; /* end if on constrain search */
+
+ TRAV(p->next,k,rk,t);
+
+ if (t != NULL) {
+ t=tshrink(t);
+ t=tflatten(t);
+ t=tleft_factor(t);
+ if (pred->tcontext != NULL) {
+ tAND=MR_computeTreeAND(t,pred->tcontext);
+ } else {
+ tset=MR_make_tree_from_set(pred->scontext[1]);
+ tAND=MR_computeTreeAND(t,tset);
+ Tfree(tset);
+ };
+ Tfree(t);
+ t=tAND;
+ };
+ goto EXIT;
+
+ }; /* end if on ampersand predicate */
+
+ TRAV(p->next,k,rk,t);
+
+EXIT:
+ if (save_fset != NULL) {
+ for (i=1 ; i <= CLL_k ; i++) {
+ set_free(fset[i]);
+ fset[i]=save_fset[i];
+ };
+ free ( (char *) save_fset);
+ };
+ return t;
+}
+
+/* see if e exists in s as a possible input permutation (e is always a chain) */
+
+int
+#ifdef __USE_PROTOS
+tmember( Tree *e, Tree *s )
+#else
+tmember( e, s )
+Tree *e;
+Tree *s;
+#endif
+{
+ if ( e==NULL||s==NULL ) return 0;
+/** fprintf(stderr, "tmember(");
+*** preorder(e); fprintf(stderr, ",");
+*** preorder(s); fprintf(stderr, " )\n");
+*/
+ if ( s->token == ALT && s->right == NULL ) return tmember(e, s->down);
+ if ( e->token!=s->token )
+ {
+ if ( s->right==NULL ) return 0;
+ return tmember(e, s->right);
+ }
+ if ( e->down==NULL && s->down == NULL ) return 1;
+ if ( tmember(e->down, s->down) ) return 1;
+ if ( s->right==NULL ) return 0;
+ return tmember(e, s->right);
+}
+
+/* see if e exists in s as a possible input permutation (e is always a chain);
+ * Only check s to the depth of e. In other words, 'e' can be a shorter
+ * sequence than s.
+ */
+int
+#ifdef __USE_PROTOS
+tmember_constrained( Tree *e, Tree *s)
+#else
+tmember_constrained( e, s )
+Tree *e;
+Tree *s;
+#endif
+{
+ if ( e==NULL||s==NULL ) return 0;
+/** fprintf(stderr, "tmember_constrained(");
+*** preorder(e); fprintf(stderr, ",");
+*** preorder(s); fprintf(stderr, " )\n");
+**/
+ if ( s->token == ALT && s->right == NULL )
+ return tmember_constrained(e, s->down);
+ if ( e->token!=s->token )
+ {
+ if ( s->right==NULL ) return 0;
+ return tmember_constrained(e, s->right);
+ }
+ if ( e->down == NULL ) return 1; /* if s is matched to depth of e return */
+ if ( tmember_constrained(e->down, s->down) ) return 1;
+ if ( s->right==NULL ) return 0;
+ return tmember_constrained(e, s->right);
+}
+
+/* combine (? (A t) ... (A u) ...) into (? (A t u)) */
+Tree *
+#ifdef __USE_PROTOS
+tleft_factor( Tree *t )
+#else
+tleft_factor( t )
+Tree *t;
+#endif
+{
+ Tree *u, *v, *trail, *w;
+
+ /* left-factor what is at this level */
+ if ( t == NULL ) return NULL;
+ for (u=t; u!=NULL; u=u->right)
+ {
+ trail = u;
+ v=u->right;
+ while ( v!=NULL )
+ {
+ if ( u->token == v->token )
+ {
+ if ( u->down!=NULL )
+ {
+ for (w=u->down; w->right!=NULL; w=w->right) {;}
+ w->right = v->down; /* link children together */
+ }
+ else u->down = v->down;
+ trail->right = v->right; /* unlink factored node */
+ _Tfree( v );
+ v = trail->right;
+ }
+ else {trail = v; v=v->right;}
+ }
+ }
+ /* left-factor what is below */
+ for (u=t; u!=NULL; u=u->right) u->down = tleft_factor( u->down );
+ return t;
+}
+
+/* remove the permutation p from t if present */
+Tree *
+#ifdef __USE_PROTOS
+trm_perm( Tree *t, Tree *p )
+#else
+trm_perm( t, p )
+Tree *t;
+Tree *p;
+#endif
+{
+ /*
+ fprintf(stderr, "trm_perm(");
+ preorder(t); fprintf(stderr, ",");
+ preorder(p); fprintf(stderr, " )\n");
+ */
+ if ( t == NULL || p == NULL ) return NULL;
+ if ( t->token == ALT )
+ {
+ t->down = trm_perm(t->down, p);
+ if ( t->down == NULL ) /* nothing left below, rm cur node */
+ {
+ Tree *u = t->right;
+ _Tfree( t );
+ return trm_perm(u, p);
+ }
+ t->right = trm_perm(t->right, p); /* look for more instances of p */
+ return t;
+ }
+ if ( p->token != t->token ) /* not found, try a sibling */
+ {
+ t->right = trm_perm(t->right, p);
+ return t;
+ }
+ t->down = trm_perm(t->down, p->down);
+ if ( t->down == NULL ) /* nothing left below, rm cur node */
+ {
+ Tree *u = t->right;
+ _Tfree( t );
+ return trm_perm(u, p);
+ }
+ t->right = trm_perm(t->right, p); /* look for more instances of p */
+ return t;
+}
+
+/* add the permutation 'perm' to the LL_k sets in 'fset' */
+void
+#ifdef __USE_PROTOS
+tcvt( set *fset, Tree *perm )
+#else
+tcvt( fset, perm )
+set *fset;
+Tree *perm;
+#endif
+{
+ if ( perm==NULL ) return;
+ set_orel(perm->token, fset);
+ tcvt(fset+1, perm->down);
+}
+
+/* for each element of ftbl[k], make it the root of a tree with permute(ftbl[k+1])
+ * as a child.
+ */
+Tree *
+#ifdef __USE_PROTOS
+permute( int k, int max_k )
+#else
+permute( k, max_k )
+int k, max_k;
+#endif
+{
+ Tree *t, *u;
+
+ if ( k>max_k ) return NULL;
+ if ( ftbl[k][findex[k]] == nil ) return NULL;
+ t = permute(k+1, max_k);
+ if ( t==NULL&&k<max_k ) /* no permutation left below for k+1 tokens? */
+ {
+ findex[k+1] = 0;
+ (findex[k])++; /* try next token at this k */
+ return permute(k, max_k);
+ }
+
+ u = tmake(tnode(ftbl[k][findex[k]]), t, NULL);
+ if ( k == max_k ) (findex[k])++;
+ return u;
+}
+
+/* Compute LL(k) trees for alts alt1 and alt2 of p.
+ * function result is tree of ambiguous input permutations
+ *
+ * ALGORITHM may change to look for something other than LL_k size
+ * trees ==> maxk will have to change.
+ */
+Tree *
+#ifdef __USE_PROTOS
+VerifyAmbig( Junction *alt1, Junction *alt2, unsigned **ft, set *fs, Tree **t, Tree **u, int *numAmbig )
+#else
+VerifyAmbig( alt1, alt2, ft, fs, t, u, numAmbig )
+Junction *alt1;
+Junction *alt2;
+unsigned **ft;
+set *fs;
+Tree **t;
+Tree **u;
+int *numAmbig;
+#endif
+{
+ set rk;
+ Tree *perm, *ambig=NULL;
+ Junction *p;
+ int k;
+ int tnodes_at_start=TnodesAllocated;
+ int tnodes_at_end;
+ int tnodes_used;
+ set *save_fs;
+ int j;
+
+ save_fs=(set *) calloc(CLL_k+1,sizeof(set));
+ require(save_fs != NULL,"save_fs calloc");
+
+ for (j=0; j <= CLL_k ; j++) save_fs[j]=set_dup(fs[j]);
+
+ maxk = LL_k; /* NOTE: for now, we look for LL_k */
+ ftbl = ft;
+ fset = fs;
+ constrain = &(fset[1]);
+ findex = (int *) calloc(LL_k+1, sizeof(int));
+ if ( findex == NULL )
+ {
+ fprintf(stderr, ErrHdr, FileStr[CurAmbigfile], CurAmbigline);
+ fprintf(stderr, " out of memory while analyzing alts %d and %d of %s\n",
+ CurAmbigAlt1,
+ CurAmbigAlt2,
+ CurAmbigbtype);
+ exit(PCCTS_EXIT_FAILURE);
+ }
+ for (k=1; k<=LL_k; k++) findex[k] = 0;
+
+ rk = empty;
+ ConstrainSearch = 1; /* consider only tokens in ambig sets */
+
+ p = analysis_point((Junction *)alt1->p1);
+ TRAV(p, LL_k, &rk, *t);
+ *t = tshrink( *t );
+ *t = tflatten( *t );
+ *t = tleft_factor( *t ); /* MR10 */
+ *t = prune(*t, LL_k);
+ *t = tleft_factor( *t );
+
+/*** fprintf(stderr, "after shrink&flatten&prune&left_factor:"); preorder(*t); fprintf(stderr, "\n");*/
+ if ( *t == NULL )
+ {
+/*** fprintf(stderr, "TreeIncomplete --> no LL(%d) ambiguity\n", LL_k);*/
+ Tfree( *t ); /* kill if impossible to have ambig */
+ *t = NULL;
+ }
+
+ p = analysis_point((Junction *)alt2->p1);
+
+ TRAV(p, LL_k, &rk, *u);
+ *u = tshrink( *u );
+ *u = tflatten( *u );
+ *t = tleft_factor( *t ); /* MR10 */
+ *u = prune(*u, LL_k);
+ *u = tleft_factor( *u );
+/* fprintf(stderr, "after shrink&flatten&prune&lfactor:"); preorder(*u); fprintf(stderr, "\n");*/
+ if ( *u == NULL )
+ {
+/* fprintf(stderr, "TreeIncomplete --> no LL(%d) ambiguity\n", LL_k);*/
+ Tfree( *u );
+ *u = NULL;
+ }
+
+ for (k=1; k<=LL_k; k++) set_clr( fs[k] );
+
+ ambig = tnode(ALT);
+ k = 0;
+ if ( *t!=NULL && *u!=NULL )
+ {
+ while ( (perm=permute(1,LL_k))!=NULL )
+ {
+/* fprintf(stderr, "chk perm:"); preorder(perm); fprintf(stderr, "\n");*/
+ if ( tmember(perm, *t) && tmember(perm, *u) )
+ {
+/* fprintf(stderr, "ambig upon"); preorder(perm); fprintf(stderr, "\n");*/
+
+ k++;
+ perm->right = ambig->down;
+ ambig->down = perm;
+ tcvt(&(fs[1]), perm);
+ }
+ else Tfree( perm );
+ }
+ }
+
+ for (j=0; j <= CLL_k ; j++) fs[j]=save_fs[j];
+ free( (char *) save_fs);
+
+ tnodes_at_end=TnodesAllocated;
+ tnodes_used=tnodes_at_end - tnodes_at_start;
+
+ if (TnodesReportThreshold > 0 && tnodes_used > TnodesReportThreshold) {
+ fprintf(stdout,"There were %d tuples whose ambiguity could not be resolved by full lookahead\n",k);
+ fprintf(stdout,"There were %d tnodes created to resolve ambiguity between:\n\n",tnodes_used);
+ fprintf(stdout," Choice 1: %s line %d file %s\n",
+ MR_ruleNamePlusOffset( (Node *) alt1),alt1->line,FileStr[alt1->file]);
+ fprintf(stdout," Choice 2: %s line %d file %s\n",
+ MR_ruleNamePlusOffset( (Node *) alt2),alt2->line,FileStr[alt2->file]);
+ for (j=1; j <= CLL_k ; j++) {
+ fprintf(stdout,"\n Intersection of lookahead[%d] sets:\n",j);
+ MR_dumpTokenSet(stdout,2,fs[j]);
+ };
+ fprintf(stdout,"\n");
+ };
+
+ *numAmbig = k;
+ if ( ambig->down == NULL ) {_Tfree(ambig); ambig = NULL;}
+ free( (char *)findex );
+/* fprintf(stderr, "final ambig:"); preorder(ambig); fprintf(stderr, "\n");*/
+ return ambig;
+}
+
+static Tree *
+#ifdef __USE_PROTOS
+bottom_of_chain( Tree *t )
+#else
+bottom_of_chain( t )
+Tree *t;
+#endif
+{
+ if ( t==NULL ) return NULL;
+ for (; t->down != NULL; t=t->down) {;}
+ return t;
+}
+
+/*
+ * Make a tree from k sets where the degree of the first k-1 sets is 1.
+ */
+Tree *
+#ifdef __USE_PROTOS
+make_tree_from_sets( set *fset1, set *fset2 )
+#else
+make_tree_from_sets( fset1, fset2 )
+set *fset1;
+set *fset2;
+#endif
+{
+ set inter;
+ int i;
+ Tree *t=NULL, *n, *u;
+ unsigned *p,*q;
+ require(LL_k>1, "make_tree_from_sets: LL_k must be > 1");
+
+ /* do the degree 1 sets first */
+ for (i=1; i<=LL_k-1; i++)
+ {
+ inter = set_and(fset1[i], fset2[i]);
+ require(set_deg(inter)==1, "invalid set to tree conversion");
+ n = tnode(set_int(inter));
+ if (t==NULL) t=n; else tmake(t, n, NULL);
+ set_free(inter);
+ }
+
+ /* now add the chain of tokens at depth k */
+ u = bottom_of_chain(t);
+ inter = set_and(fset1[LL_k], fset2[LL_k]);
+ if ( (q=p=set_pdq(inter)) == NULL ) fatal_internal("Can't alloc space for set_pdq");
+ /* first one is linked to bottom, then others are sibling linked */
+ n = tnode(*p++);
+ u->down = n;
+ u = u->down;
+ while ( *p != nil )
+ {
+ n = tnode(*p);
+ u->right = n;
+ u = u->right;
+ p++;
+ }
+ free((char *)q);
+
+ return t;
+}
+
+/* create and return the tree of lookahead k-sequences that are in t, but not
+ * in the context of predicates in predicate list p.
+ */
+Tree *
+#ifdef __USE_PROTOS
+tdif( Tree *ambig_tuples, Predicate *p, set *fset1, set *fset2 )
+#else
+tdif( ambig_tuples, p, fset1, fset2 )
+Tree *ambig_tuples;
+Predicate *p;
+set *fset1;
+set *fset2;
+#endif
+{
+ unsigned **ft;
+ Tree *dif=NULL;
+ Tree *perm;
+ set b;
+ int i,k;
+
+ if ( p == NULL ) return tdup(ambig_tuples);
+
+ ft = (unsigned **) calloc(CLL_k+1, sizeof(unsigned *));
+ require(ft!=NULL, "cannot allocate ft");
+ for (i=1; i<=CLL_k; i++)
+ {
+ b = set_and(fset1[i], fset2[i]);
+ ft[i] = set_pdq(b);
+ set_free(b);
+ }
+ findex = (int *) calloc(LL_k+1, sizeof(int));
+ if ( findex == NULL )
+ {
+ fatal_internal("out of memory in tdif while checking predicates");
+ }
+ for (k=1; k<=LL_k; k++) findex[k] = 0;
+
+#ifdef DBG_TRAV
+ fprintf(stderr, "tdif_%d[", p->k);
+ preorder(ambig_tuples);
+ fprintf(stderr, ",");
+ preorder(p->tcontext);
+ fprintf(stderr, "] =");
+#endif
+
+ ftbl = ft;
+ while ( (perm=permute(1,p->k))!=NULL )
+ {
+#ifdef DBG_TRAV
+ fprintf(stderr, "test perm:"); preorder(perm); fprintf(stderr, "\n");
+#endif
+ if ( tmember_constrained(perm, ambig_tuples) &&
+ !tmember_of_context(perm, p) )
+ {
+#ifdef DBG_TRAV
+ fprintf(stderr, "satisfied upon"); preorder(perm); fprintf(stderr, "\n");
+#endif
+ k++;
+ if ( dif==NULL ) dif = perm;
+ else
+ {
+ perm->right = dif;
+ dif = perm;
+ }
+ }
+ else Tfree( perm );
+ }
+
+#ifdef DBG_TRAV
+ preorder(dif);
+ fprintf(stderr, "\n");
+#endif
+
+ for (i=1; i<=CLL_k; i++) free( (char *)ft[i] );
+ free((char *)ft);
+ free((char *)findex);
+
+ return dif;
+}
+
+/* is lookahead sequence t a member of any context tree for any
+ * predicate in p?
+ */
+static int
+#ifdef __USE_PROTOS
+tmember_of_context( Tree *t, Predicate *p )
+#else
+tmember_of_context( t, p )
+Tree *t;
+Predicate *p;
+#endif
+{
+ for (; p!=NULL; p=p->right)
+ {
+ if ( p->expr==PRED_AND_LIST || p->expr==PRED_OR_LIST )
+ return tmember_of_context(t, p->down);
+ if ( tmember_constrained(t, p->tcontext) ) return 1;
+ if ( tmember_of_context(t, p->down) ) return 1;
+ }
+ return 0;
+}
+
+int
+#ifdef __USE_PROTOS
+is_single_tuple( Tree *t )
+#else
+is_single_tuple( t )
+Tree *t;
+#endif
+{
+ if ( t == NULL ) return 0;
+ if ( t->right != NULL ) return 0;
+ if ( t->down == NULL ) return 1;
+ return is_single_tuple(t->down);
+}
+
+
+/* MR10 Check that a context guard contains only allowed things */
+/* MR10 (mainly token references). */
+
+#ifdef __USE_PROTOS
+int contextGuardOK(Node *p,int h,int *hmax)
+#else
+int contextGuardOK(p,h,hmax)
+ Node *p;
+ int h;
+ int *hmax;
+#endif
+{
+ Junction *j;
+ TokNode *tn;
+
+ if (p == NULL) return 1;
+ if (p->ntype == nToken) {
+ h++;
+ if (h > *hmax) *hmax=h;
+ tn=(TokNode *)p;
+ if (tn->el_label != NULL) {
+ warnFL(eMsg1("a label (\"%s\") for a context guard element is meaningless",tn->el_label),
+ FileStr[p->file],p->line);
+ };
+ return contextGuardOK( ( (TokNode *) p)->next,h,hmax);
+ } else if (p->ntype == nAction) {
+ goto Fail;
+ } else if (p->ntype == nRuleRef) {
+ goto Fail;
+ } else {
+ require (p->ntype == nJunction,"Unexpected ntype");
+ j=(Junction *) p;
+ if (j->jtype != Generic &&
+ j->jtype != aSubBlk && /* pretty sure this one is allowed */
+/**** j->jtype != aOptBlk && ****/ /* pretty sure this one is allowed */ /* MR11 not any more ! */
+ j->jtype != EndBlk) {
+ errFL("A context guard may not contain an option block: {...} or looping block: (...)* or (...)+",
+ FileStr[p->file],p->line);
+ contextGuardOK(j->p1,h,hmax);
+ return 0;
+ };
+ /* do both p1 and p2 so use | rather than || */
+ return contextGuardOK(j->p2,h,hmax) | contextGuardOK(j->p1,h,hmax);
+ };
+Fail:
+ errFL("A context guard may contain only Token references - guard will be ignored",
+ FileStr[p->file],p->line);
+ contextGuardOK( ( (ActionNode *) p)->next,h,hmax);
+ return 0;
+}
+
+/*
+ * Look at a (...)? generalized-predicate context-guard and compute
+ * either a lookahead set (k==1) or a lookahead tree for k>1. The
+ * k level is determined by the guard itself rather than the LL_k
+ * variable. For example, ( A B )? is an LL(2) guard and ( ID )?
+ * is an LL(1) guard. For the moment, you can only have a single
+ * tuple in the guard. Physically, the block must look like this
+ * --o-->TOKEN-->o-->o-->TOKEN-->o-- ... -->o-->TOKEN-->o--
+ * An error is printed for any other type.
+ */
+Predicate *
+#ifdef __USE_PROTOS
+computePredFromContextGuard(Graph blk,int *msgDone) /* MR10 */
+#else
+computePredFromContextGuard(blk,msgDone) /* MR10 */
+ Graph blk;
+ int *msgDone; /* MR10 */
+#endif
+{
+ Junction *junc = (Junction *)blk.left, *p;
+ Tree *t=NULL;
+ Predicate *pred = NULL;
+ set scontext, rk;
+ int ok;
+ int hmax=0;
+
+ require(junc!=NULL && junc->ntype == nJunction, "bad context guard");
+
+/* MR10 Check for anything other than Tokens and generic junctions */
+
+ *msgDone=0; /* MR10 */
+ ok=contextGuardOK( (Node *)junc,0,&hmax); /* MR10 */
+ if (! ok) { /* MR10 */
+ *msgDone=1; /* MR10 */
+ return NULL; /* MR10 */
+ }; /* MR10 */
+ if (hmax == 0) {
+errFL("guard is 0 tokens long",FileStr[junc->file],junc->line); /* MR11 */
+ *msgDone=1;
+ return NULL;
+ };
+ if (hmax > CLL_k) { /* MR10 */
+errFL(eMsgd2("guard is %d tokens long - lookahead is limited to max(k,ck)==%d", /* MR10 */
+ hmax,CLL_k), /* MR10 */
+ FileStr[junc->file],junc->line); /* MR10 */
+ *msgDone=1; /* MR10 */
+ return NULL; /* MR10 */
+ }; /* MR10 */
+
+ rk = empty;
+ p = junc;
+ pred = new_pred();
+ pred->k = hmax; /* MR10 should be CLL_k, not LLK ? */
+ if (hmax > 1 ) /* MR10 was LL_k */
+ {
+ ConstrainSearch = 0;
+ ContextGuardTRAV = 1;
+ TRAV(p, hmax, &rk, t); /* MR10 was LL_k */
+ ContextGuardTRAV = 0;
+ set_free(rk);
+ t = tshrink( t );
+ t = tflatten( t );
+ t = tleft_factor( t );
+/*
+ fprintf(stderr, "ctx guard:");
+ preorder(t);
+ fprintf(stderr, "\n");
+*/
+ pred->tcontext = t;
+ }
+ else
+ {
+ REACH(p, 1, &rk, scontext);
+ require(set_nil(rk), "rk != nil");
+ set_free(rk);
+/*
+ fprintf(stderr, "LL(1) ctx guard is:");
+ s_fprT(stderr, scontext);
+ fprintf(stderr, "\n");
+*/
+ pred->scontext[1] = scontext;
+ }
+
+ list_add(&ContextGuardPredicateList,pred); /* MR13 */
+
+ return pred;
+}
+
+/* MR13
+ When the context guard is originally computed the
+ meta-tokens are not known.
+*/
+
+#ifdef __USE_PROTOS
+void recomputeContextGuard(Predicate *pred)
+#else
+void recomputeContextGuard(pred)
+ Predicate *pred;
+#endif
+{
+ Tree * t=NULL;
+ set scontext;
+ set rk;
+ ActionNode * actionNode;
+ Junction * p;
+
+ actionNode=pred->source;
+ require (actionNode != NULL,"context predicate's source == NULL");
+
+ p=actionNode->guardNodes;
+ require (p != NULL,"context predicate's guardNodes == NULL");
+
+ rk = empty;
+ if (pred->k > 1 )
+ {
+ ConstrainSearch = 0;
+ ContextGuardTRAV = 1;
+ TRAV(p, pred->k, &rk, t);
+ ContextGuardTRAV = 0;
+ set_free(rk);
+ t = tshrink( t );
+ t = tflatten( t );
+ t = tleft_factor( t );
+ Tfree(pred->tcontext);
+ pred->tcontext = t;
+ }
+ else
+ {
+ REACH(p, 1, &rk, scontext);
+ require(set_nil(rk), "rk != nil");
+ set_free(rk);
+ set_free(pred->scontext[1]);
+ pred->scontext[1] = scontext;
+ }
+}
+
+/* MR11 - had enough of flags yet ? */
+
+int MR_AmbSourceSearch=0;
+int MR_AmbSourceSearchGroup=0;
+int MR_AmbSourceSearchChoice=0;
+int MR_AmbSourceSearchLimit=0;
+int MR_matched_AmbAidRule=0;
+
+static set *matchSets[2]={NULL,NULL};
+static int *tokensInChain=NULL;
+static Junction *MR_AmbSourceSearchJ[2];
+
+void MR_traceAmbSourceKclient()
+{
+ int i;
+ set *save_fset;
+ int save_ConstrainSearch;
+ set incomplete;
+ Tree *t;
+
+ if (matchSets[0] == NULL) {
+ matchSets[0]=(set *) calloc (CLL_k+1,sizeof(set));
+ require (matchSets[0] != NULL,"matchSets[0] alloc");
+ matchSets[1]=(set *) calloc (CLL_k+1,sizeof(set));
+ require (matchSets[1] != NULL,"matchSets[1] alloc");
+ };
+
+ for (i=1 ; i <= MR_AmbSourceSearchLimit ; i++) {
+ set_clr(matchSets[0][i]);
+ set_orel( (unsigned) tokensInChain[i],
+ &matchSets[0][i]);
+ set_clr(matchSets[1][i]);
+ set_orel( (unsigned) tokensInChain[i],
+ &matchSets[1][i]);
+ };
+
+ save_fset=fset;
+ save_ConstrainSearch=ConstrainSearch;
+
+
+
+ for (i=0 ; i < 2 ; i++) {
+
+#if 0
+** fprintf(stdout," Choice:%d Depth:%d ",i+1,MR_AmbSourceSearchLimit);
+** fprintf(stdout,"(");
+** for (j=1 ; j <= MR_AmbSourceSearchLimit ; j++) {
+** if (j != 1) fprintf(stdout," ");
+** fprintf(stdout,"%s",TerminalString(tokensInChain[j]));
+** };
+** fprintf(stdout,")\n\n");
+#endif
+
+ fset=matchSets[i];
+
+ MR_AmbSourceSearch=1;
+ MR_MaintainBackTrace=1;
+ MR_AmbSourceSearchChoice=i;
+ ConstrainSearch=1;
+
+ maxk = MR_AmbSourceSearchLimit;
+
+ incomplete=empty;
+ t=NULL;
+
+ constrain = &(fset[1]);
+ MR_pointerStackReset(&MR_BackTraceStack);
+
+ TRAV(MR_AmbSourceSearchJ[i],maxk,&incomplete,t);
+
+ Tfree(t);
+
+ require (set_nil(incomplete),"MR_traceAmbSourceK TRAV incomplete");
+ require (MR_BackTraceStack.count == 0,"K: MR_BackTraceStack.count != 0");
+
+ set_free(incomplete);
+ };
+
+ ConstrainSearch=save_ConstrainSearch;
+ fset=save_fset;
+ MR_AmbSourceSearch=0;
+ MR_MaintainBackTrace=0;
+ MR_AmbSourceSearchChoice=0;
+}
+
+#ifdef __USE_PROTOS
+Tree *tTrunc(Tree *t,int depth)
+#else
+Tree *tTrunc(t,depth)
+ Tree *t;
+#endif
+{
+ Tree *u;
+
+ require ( ! (t == NULL && depth > 0),"tree too short");
+
+ if (depth == 0) return NULL;
+
+ if (t->token == ALT) {
+ u=tTrunc(t->down,depth);
+ } else {
+ u=tnode(t->token);
+ u->down=tTrunc(t->down,depth-1);
+ };
+ if (t->right != NULL) u->right=tTrunc(t->right,depth);
+ return u;
+}
+
+#ifdef __USE_PROTOS
+void MR_iterateOverTree(Tree *t,int chain[])
+#else
+void MR_iterateOverTree(t,chain)
+ Tree *t;
+ int chain[];
+#endif
+{
+ if (t == NULL) return;
+ chain[0]=t->token;
+ if (t->down != NULL) {
+ MR_iterateOverTree(t->down,&chain[1]);
+ } else {
+ MR_traceAmbSourceKclient();
+ };
+ MR_iterateOverTree(t->right,&chain[0]);
+ chain[0]=0;
+}
+
+#ifdef __USE_PROTOS
+void MR_traceAmbSourceK(Tree *t,Junction *alt1,Junction *alt2)
+#else
+void MR_traceAmbSourceK(t,alt1,alt2)
+ Tree *t;
+ Junction *alt1;
+ Junction *alt2;
+#endif
+{
+ int i;
+ int depth;
+ int maxDepth;
+ Tree *truncatedTree;
+
+ if (MR_AmbAidRule == NULL) return;
+
+ if ( ! (
+ strcmp(MR_AmbAidRule,alt1->rname) == 0 ||
+ strcmp(MR_AmbAidRule,alt2->rname) == 0 ||
+ MR_AmbAidLine==alt1->line ||
+ MR_AmbAidLine==alt2->line
+ )
+ ) return;
+
+ MR_matched_AmbAidRule++;
+
+ /* there are no token sets in trees, only in TokNodes */
+
+ MR_AmbSourceSearchJ[0]=analysis_point( (Junction *) alt1->p1);
+ MR_AmbSourceSearchJ[1]=analysis_point( (Junction *) alt2->p1);
+
+ if (tokensInChain == NULL) {
+ tokensInChain=(int *) calloc (CLL_k+1,sizeof(int));
+ require (tokensInChain != NULL,"tokensInChain alloc");
+ };
+
+ MR_AmbSourceSearchGroup=0;
+
+ fprintf(stdout,"\n");
+ fprintf(stdout," Ambiguity Aid ");
+ fprintf(stdout,
+ (MR_AmbAidDepth <= LL_k ?
+ "(-k %d -aa %s %s -aad %d)\n\n" :
+ "(-k %d -aa %s %s [-k value limits -aad %d])\n\n"),
+ LL_k,
+ MR_AmbAidRule,
+ (MR_AmbAidMultiple ? "-aam" : ""),
+ MR_AmbAidDepth);
+
+ for (i=0 ; i < 2 ; i++) {
+ fprintf(stdout," Choice %d: %-25s line %d file %s\n",
+ (i+1),
+ MR_ruleNamePlusOffset( (Node *) MR_AmbSourceSearchJ[i]),
+ MR_AmbSourceSearchJ[i]->line,
+ FileStr[MR_AmbSourceSearchJ[i]->file]);
+ };
+
+ fprintf(stdout,"\n");
+
+ if (MR_AmbAidDepth < LL_k) {
+ maxDepth=MR_AmbAidDepth;
+ } else {
+ maxDepth=LL_k;
+ };
+
+ for (depth=1 ; depth <= maxDepth; depth++) {
+ MR_AmbSourceSearchLimit=depth;
+ if (depth < LL_k) {
+ truncatedTree=tTrunc(t,depth);
+ truncatedTree=tleft_factor(truncatedTree);
+ MR_iterateOverTree(truncatedTree,&tokensInChain[1]); /* <===== */
+ Tfree(truncatedTree);
+ } else {
+ MR_iterateOverTree(t,tokensInChain); /* <===== */
+ };
+ fflush(stdout);
+ fflush(stderr);
+ };
+
+ fprintf(stdout,"\n");
+ MR_AmbSourceSearch=0;
+ MR_MaintainBackTrace=0;
+ MR_AmbSourceSearchGroup=0;
+ MR_AmbSourceSearchChoice=0;
+ MR_AmbSourceSearchLimit=0;
+
+}
+
+
+/* this if for k=1 grammars only
+
+ this is approximate only because of the limitations of linear
+ approximation lookahead. Don't want to do a k=3 search when
+ the user only specified a ck=3 grammar
+*/
+
+#ifdef __USE_PROTOS
+void MR_traceAmbSource(set *matchSets,Junction *alt1, Junction *alt2)
+#else
+void MR_traceAmbSource(matchSets,alt1,alt2)
+ set *matchSets;
+ Junction *alt1;
+ Junction *alt2;
+#endif
+{
+ set *save_fset;
+ Junction *p[2];
+ int i;
+ int j;
+ set *dup_matchSets;
+ set intersection;
+ set incomplete;
+ set tokensUsed;
+ int depth;
+
+ if (MR_AmbAidRule == NULL) return;
+ if ( ! (
+ strcmp(MR_AmbAidRule,alt1->rname) == 0 ||
+ strcmp(MR_AmbAidRule,alt2->rname) == 0 ||
+ MR_AmbAidLine==alt1->line ||
+ MR_AmbAidLine==alt2->line
+ )
+ ) return;
+
+ MR_matched_AmbAidRule++;
+
+ save_fset=fset;
+
+ dup_matchSets=(set *) calloc(CLL_k+1,sizeof(set));
+ require (dup_matchSets != NULL,"Can't allocate dup_matchSets");
+
+ p[0]=analysis_point( (Junction *) alt1->p1);
+ p[1]=analysis_point( (Junction *) alt2->p1);
+
+ fprintf(stdout,"\n");
+
+ fprintf(stdout," Ambiguity Aid ");
+ fprintf(stdout,
+ (MR_AmbAidDepth <= CLL_k ?
+ "(-ck %d -aa %s %s -aad %d)\n\n" :
+ "(-ck %d -aa %s %s [-ck value limits -aad %d])\n\n"),
+ CLL_k,
+ MR_AmbAidRule,
+ (MR_AmbAidMultiple ? "-aam" : ""),
+ MR_AmbAidDepth);
+
+ for (i=0 ; i < 2 ; i++) {
+ fprintf(stdout," Choice %d: %-25s line %d file %s\n",
+ (i+1),
+ MR_ruleNamePlusOffset( (Node *) p[i]),
+ p[i]->line,FileStr[p[i]->file]);
+ };
+
+ for (j=1; j <= CLL_k ; j++) {
+ fprintf(stdout,"\n Intersection of lookahead[%d] sets:\n",j);
+ intersection=set_and(alt1->fset[j],alt2->fset[j]);
+ MR_dumpTokenSet(stdout,2,intersection);
+ set_free(intersection);
+ };
+
+ fprintf(stdout,"\n");
+
+ require (1 <= MR_AmbAidDepth && MR_AmbAidDepth <= CLL_k,
+ "illegal MR_AmbAidDepth");
+
+ MR_AmbSourceSearchGroup=0;
+ for (depth=1; depth <= MR_AmbAidDepth; depth++) {
+ MR_AmbSourceSearchLimit=depth;
+ for (i=0 ; i < 2 ; i++) {
+
+/*** fprintf(stdout," Choice:%d Depth:%d\n\n",i+1,depth); ***/
+
+ for (j=0 ; j <= CLL_k ; j++) { dup_matchSets[j]=set_dup(matchSets[j]); };
+ fset=dup_matchSets;
+
+ fflush(output);
+ fflush(stdout);
+
+ MR_AmbSourceSearch=1;
+ MR_MaintainBackTrace=1;
+ MR_AmbSourceSearchChoice=i;
+
+ maxk = depth;
+ tokensUsed=empty;
+ incomplete=empty;
+
+ constrain = &(fset[1]);
+ MR_pointerStackReset(&MR_BackTraceStack);
+
+ REACH(p[i],depth,&incomplete,tokensUsed);
+
+ fflush(output);
+ fflush(stdout);
+
+ require (set_nil(incomplete),"MR_traceAmbSource REACH incomplete");
+ require (MR_BackTraceStack.count == 0,"1: MR_BackTraceStack.count != 0");
+
+ set_free(incomplete);
+ set_free(tokensUsed);
+
+ for (j=0 ; j <= CLL_k ; j++) { set_free(dup_matchSets[j]); };
+ };
+ };
+
+ fprintf(stdout,"\n");
+
+ MR_AmbSourceSearch=0;
+ MR_MaintainBackTrace=0;
+ MR_AmbSourceSearchGroup=0;
+ MR_AmbSourceSearchChoice=0;
+ MR_AmbSourceSearchLimit=0;
+
+ fset=save_fset;
+ free ( (char *) dup_matchSets);
+}
+
+static int itemCount;
+
+void MR_backTraceDumpItemReset() {
+ itemCount=0;
+}
+
+#ifdef __USE_PROTOS
+void MR_backTraceDumpItem(FILE *f,int skip,Node *n)
+#else
+void MR_backTraceDumpItem(f,skip,n)
+ FILE *f;
+ int skip;
+ Node *n;
+#endif
+{
+ TokNode *tn;
+ RuleRefNode *rrn;
+ Junction *j;
+ ActionNode *a;
+
+ switch (n->ntype) {
+ case nToken:
+ itemCount++; if (skip) goto EXIT;
+ tn=(TokNode *)n;
+ if (set_nil(tn->tset)) {
+ fprintf(f," %2d #token %-23s",itemCount,TerminalString(tn->token));
+ } else {
+ fprintf(f," %2d #tokclass %-20s",itemCount,TerminalString(tn->token));
+ };
+ break;
+ case nRuleRef:
+ itemCount++; if (skip) goto EXIT;
+ rrn=(RuleRefNode *)n;
+ fprintf(f," %2d to %-27s",itemCount,rrn->text);
+ break;
+ case nAction:
+ a=(ActionNode *)n;
+ goto EXIT;
+ case nJunction:
+
+ j=(Junction *)n;
+
+ switch (j->jtype) {
+ case aSubBlk:
+ if (j->guess) {
+ itemCount++; if (skip) goto EXIT;
+ fprintf(f," %2d %-30s",itemCount,"in (...)? block at");
+ break;
+ };
+/****** fprintf(f," %2d %-32s",itemCount,"in (...) block at"); *******/
+/****** break; *******/
+ goto EXIT;
+ case aOptBlk:
+ itemCount++; if (skip) goto EXIT;
+ fprintf(f," %2d %-30s",itemCount,"in {...} block");
+ break;
+ case aLoopBlk:
+ itemCount++; if (skip) goto EXIT;
+ fprintf(f," %2d %-30s",itemCount,"in (...)* block");
+ break;
+ case EndBlk:
+ if (j->alpha_beta_guess_end) {
+ itemCount++; if (skip) goto EXIT;
+ fprintf(f," %2d %-30s",itemCount,"end (...)? block at");
+ break;
+ };
+ goto EXIT;
+/****** fprintf(f," %2d %-32s",itemCount,"end of a block at"); *****/
+/****** break; *****/
+ case RuleBlk:
+ itemCount++; if (skip) goto EXIT;
+ fprintf(f," %2d %-30s",itemCount,j->rname);
+ break;
+ case Generic:
+ goto EXIT;
+ case EndRule:
+ itemCount++; if (skip) goto EXIT;
+ fprintf (f," %2d end %-26s",itemCount,j->rname);
+ break;
+ case aPlusBlk:
+ itemCount++; if (skip) goto EXIT;
+ fprintf(f," %2d %-30s",itemCount,"in (...)+ block");
+ break;
+ case aLoopBegin:
+ goto EXIT;
+ };
+ break;
+ };
+ fprintf(f," %-23s line %-4d %s\n",MR_ruleNamePlusOffset(n),n->line,FileStr[n->file]);
+EXIT:
+ return;
+}
+
+
+static PointerStack previousBackTrace={0,0,NULL};
+
+#ifdef __USE_PROTOS
+void MR_backTraceReport(void)
+#else
+void MR_backTraceReport()
+#endif
+{
+ int i;
+ int match = 0;
+ int limitMatch;
+
+ Node *p;
+ TokNode *tn;
+ set remainder;
+ int depth;
+
+ /* Even when doing a k=2 search this routine can get
+ called when there is only 1 token on the stack.
+ This is because something like rRuleRef can change
+ the search value of k from 2 to 1 temporarily.
+ It does this because the it wants to know the k=1
+ first set before it does a k=2 search
+ */
+
+ depth=0;
+ for (i=0; i < MR_BackTraceStack.count ; i++) {
+ p=(Node *) MR_BackTraceStack.data[i];
+ if (p->ntype == nToken) depth++;
+ };
+
+/* MR14 */ if (MR_AmbSourceSearch) {
+/* MR14 */ require (depth <= MR_AmbSourceSearchLimit,"depth > MR_AmbSourceSearchLimit");
+/* MR14 */ }
+
+ /* MR23 THM - Traceback report was being called at the wrong time for -alpha reports */
+ /* Reported by Arpad Beszedes (beszedes@inf.u-szeged.hu) */
+
+ if (MR_AmbSourceSearchLimit == 0 || depth < MR_AmbSourceSearchLimit) {
+ return;
+ };
+
+ MR_backTraceDumpItemReset();
+
+ limitMatch=MR_BackTraceStack.count;
+ if (limitMatch > previousBackTrace.count) {
+ limitMatch=previousBackTrace.count;
+ };
+
+ for (match=0; match < limitMatch; match++) {
+ if (MR_BackTraceStack.data[match] !=
+ previousBackTrace.data[match]) {
+ break;
+ };
+ };
+
+ /* not sure at the moment why there would be duplicates */
+
+ if (match != MR_BackTraceStack.count) {
+
+ fprintf(stdout," Choice:%d Depth:%d Group:%d",
+ (MR_AmbSourceSearchChoice+1),
+ MR_AmbSourceSearchLimit,
+ ++MR_AmbSourceSearchGroup);
+
+ depth=0;
+ fprintf(stdout," (");
+ for (i=0; i < MR_BackTraceStack.count ; i++) {
+ p=(Node *) MR_BackTraceStack.data[i];
+ if (p->ntype != nToken) continue;
+ tn=(TokNode *)p;
+ if (depth != 0) fprintf(stdout," ");
+ fprintf(stdout,TerminalString(tn->token));
+ depth++;
+ if (! MR_AmbAidMultiple) {
+ if (set_nil(tn->tset)) {
+ set_rm( (unsigned) tn->token,fset[depth]);
+ } else {
+ remainder=set_dif(fset[depth],tn->tset);
+ set_free(fset[depth]);
+ fset[depth]=remainder;
+ };
+ };
+ };
+ fprintf(stdout,")\n");
+
+ for (i=0; i < MR_BackTraceStack.count ; i++) {
+ MR_backTraceDumpItem(stdout, (i<match) ,(Node *) MR_BackTraceStack.data[i]);
+ };
+ fprintf(stdout,"\n");
+ fflush(stdout);
+
+ MR_pointerStackReset(&previousBackTrace);
+
+ for (i=0; i < MR_BackTraceStack.count ; i++) {
+ MR_pointerStackPush(&previousBackTrace,MR_BackTraceStack.data[i]);
+ };
+
+ };
+}
+
+#ifdef __USE_PROTOS
+void MR_setConstrainPointer(set * newConstrainValue)
+#else
+void MR_setConstrainPointer(newConstrainValue)
+ set * newConstrainValue;
+#endif
+{
+ constrain=newConstrainValue;
+}
diff --git a/Source/Pccts/antlr/gen.c b/Source/Pccts/antlr/gen.c
new file mode 100644
index 0000000..368a96b
--- /dev/null
+++ b/Source/Pccts/antlr/gen.c
@@ -0,0 +1,4797 @@
+/*
+ * gen.c
+ *
+ * Generate C code (ANSI, K&R, C++)
+ *
+ * SOFTWARE RIGHTS
+ *
+ * We reserve no LEGAL rights to the Purdue Compiler Construction Tool
+ * Set (PCCTS) -- PCCTS is in the public domain. An individual or
+ * company may do whatever they wish with source code distributed with
+ * PCCTS or the code generated by PCCTS, including the incorporation of
+ * PCCTS, or its output, into commerical software.
+ *
+ * We encourage users to develop software with PCCTS. However, we do ask
+ * that credit is given to us for developing PCCTS. By "credit",
+ * we mean that if you incorporate our source code into one of your
+ * programs (commercial product, research project, or otherwise) that you
+ * acknowledge this fact somewhere in the documentation, research report,
+ * etc... If you like PCCTS and have developed a nice tool with the
+ * output, please mention that you developed it using PCCTS. In
+ * addition, we ask that this header remain intact in our source code.
+ * As long as these guidelines are kept, we expect to continue enhancing
+ * this system and expect to make other tools available as they are
+ * completed.
+ *
+ * ANTLR 1.33
+ * Terence Parr
+ * Parr Research Corporation
+ * with Purdue University and AHPCRC, University of Minnesota
+ * 1989-2001
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include "pcctscfg.h"
+#include "set.h"
+#include "syn.h"
+#include "hash.h"
+#include "generic.h"
+#include "dlgdef.h"
+
+#define NumExprPerLine 4
+static int on1line=0;
+static set tokensRefdInBlock;
+
+ /* T r a n s l a t i o n T a b l e s */
+
+/* C_Trans[node type] == pointer to function that knows how to translate that node. */
+#ifdef __cplusplus
+void (*C_Trans[NumNodeTypes+1])(...) = {
+ NULL,
+ NULL, /* See next table.
+Junctions have many types */
+ (void (*)(...)) genRuleRef,
+ (void (*)(...)) genToken,
+ (void (*)(...)) genAction
+ };
+#else
+void (*C_Trans[NumNodeTypes+1])() = {
+ NULL,
+ NULL, /* See next table.
+Junctions have many types */
+ genRuleRef,
+ genToken,
+ genAction
+ };
+#endif
+
+/* C_JTrans[Junction type] == pointer to function that knows how to translate that
+ * kind of junction node.
+ */
+#ifdef __cplusplus
+void (*C_JTrans[NumJuncTypes+1])(...) = {
+ NULL,
+ (void (*)(...)) genSubBlk,
+ (void (*)(...)) genOptBlk,
+ (void (*)(...)) genLoopBlk,
+ (void (*)(...)) genEndBlk,
+ (void (*)(...)) genRule,
+ (void (*)(...)) genJunction,
+ (void (*)(...)) genEndRule,
+ (void (*)(...)) genPlusBlk,
+ (void (*)(...)) genLoopBegin
+ };
+#else
+void (*C_JTrans[NumJuncTypes+1])() = {
+ NULL,
+ genSubBlk,
+ genOptBlk,
+ genLoopBlk,
+ genEndBlk,
+ genRule,
+ genJunction,
+ genEndRule,
+ genPlusBlk,
+ genLoopBegin
+ };
+#endif
+
+#define PastWhiteSpace(s) while (*(s) == ' ' || *(s) == '\t') {s++;}
+
+static int tabs = 0;
+
+/* MR6 Got tired of text running off page when using standard tab stops */
+
+#define TAB { int i; \
+ if (TabWidth==0) { \
+ for (i=0; i<tabs; i++) fputc('\t', output); \
+ } else { \
+ for (i=0; i<tabs*TabWidth; i++) fputc(' ',output); \
+ }; \
+ }
+
+static void
+#ifdef __USE_PROTOS
+tab( void )
+#else
+tab( )
+#endif
+TAB
+
+#ifdef __USE_PROTOS
+static char *tokenFollowSet(TokNode *);
+static ActionNode *findImmedAction( Node * );
+static void dumpRetValAssign(char *, char *, RuleRefNode *); /* MR30 */
+static void dumpAfterActions(FILE *output);
+static set ComputeErrorSet(Junction *, int, int);
+static void makeErrorClause(Junction *, set, int, int);
+static void DumpFuncHeader( Junction *, RuleEntry * );
+static int has_guess_block_as_first_item(Junction *);
+static int genExprSets(set *, int);
+static void genExprTree( Tree *t, int k );
+static void genExprTreeOriginal( Tree *t, int k ); /* MR10 */
+static char * findOuterHandlerLabel(ExceptionGroup *eg); /* MR7 */
+static void OutLineInfo(FILE *file,int line,char *fileName); /* MR14 */
+#else
+static char *tokenFollowSet();
+static ActionNode *findImmedAction();
+static void dumpRetValAssign();
+static void dumpAfterActions();
+static set ComputeErrorSet();
+static void makeErrorClause();
+static void DumpFuncHeader();
+static int has_guess_block_as_first_item();
+static int genExprSets();
+static void genExprTree();
+static void genExprTreeOriginal(); /* MR10 */
+static char * findOuterHandlerLabel(); /* MR7 */
+static void OutLineInfo(); /* MR14 */
+#endif
+
+#define gen(s) {tab(); fprintf(output, s);}
+#define gen1(s,a) {tab(); fprintf(output, s,a);}
+#define gen2(s,a,b) {tab(); fprintf(output, s,a,b);}
+#define gen3(s,a,b,c) {tab(); fprintf(output, s,a,b,c);}
+#define gen4(s,a,b,c,d) {tab(); fprintf(output, s,a,b,c,d);}
+#define gen5(s,a,b,c,d,e) {tab(); fprintf(output, s,a,b,c,d,e);}
+#define gen6(s,a,b,c,d,e,f) {tab(); fprintf(output, s,a,b,c,d,e,f);}
+#define gen7(s,a,b,c,d,e,f,g) {tab(); fprintf(output, s,a,b,c,d,e,f,g);}
+
+#define _gen(s) {fprintf(output, s);}
+#define _gen1(s,a) {fprintf(output, s,a);}
+#define _gen2(s,a,b) {fprintf(output, s,a,b);}
+#define _gen3(s,a,b,c) {fprintf(output, s,a,b,c);}
+#define _gen4(s,a,b,c,d){fprintf(output, s,a,b,c,d);}
+#define _gen5(s,a,b,c,d,e){fprintf(output, s,a,b,c,d,e);}
+#define _gen6(s,a,b,c,d,e,f){fprintf(output, s,a,b,c,d,e,f);}
+#define _gen7(s,a,b,c,d,e,f,g){fprintf(output, s,a,b,c,d,e,f,g);}
+
+
+/* MR11 a convenient place to set a break point */
+
+#ifdef __USE_PROTOS
+void MR_break(void)
+#else
+void MR_break()
+#endif
+{
+ return;
+}
+
+/* MR10 genTraceOut(Junction *) */
+
+#ifdef __USE_PROTOS
+static void genTraceOut(Junction *q)
+#else
+static void genTraceOut(q)
+ Junction *q;
+#endif
+{
+ if ( TraceGen ) {
+ if ( GenCC ) {gen1("zzTRACEOUT(\"%s\");\n", q->rname);}
+ else gen1("zzTRACEOUT((ANTLRChar *)\"%s\");\n", q->rname);
+ }
+}
+
+static void
+#ifdef __USE_PROTOS
+warn_about_using_gk_option(void)
+#else
+warn_about_using_gk_option()
+#endif
+{
+ static int warned_already=0;
+
+ if ( !DemandLookahead || warned_already ) return;
+ warned_already = 1;
+ warnNoFL("-gk option could cause trouble for <<...>>? predicates");
+}
+
+void
+#ifdef __USE_PROTOS
+freeBlkFsets( Junction *q )
+#else
+freeBlkFsets( q )
+Junction *q;
+#endif
+{
+ int i;
+ Junction *alt;
+ require(q!=NULL, "freeBlkFsets: invalid node");
+
+ for (alt=q; alt != NULL; alt= (Junction *) alt->p2 )
+ {
+ for (i=1; i<=CLL_k; i++) set_free(alt->fset[i]);
+ }
+}
+
+/*
+ * Generate a local variable allocation for each token references
+ * in this block.
+ */
+static void
+#ifdef __USE_PROTOS
+genTokenPointers( Junction *q )
+#else
+genTokenPointers( q )
+Junction *q;
+#endif
+{
+ /* Rule refs are counted and can be referenced, but their
+ * value is not set to anything useful ever.
+ *
+ * The ptrs are to be named _tij where i is the current level
+ * and j is the element number within an alternative.
+ */
+ int first=1, t=0;
+ set a;
+ tokensRefdInBlock = q->tokrefs;
+
+ if ( set_deg(q->tokrefs) == 0 ) return;
+ a = set_dup(q->tokrefs);
+ gen("ANTLRTokenPtr ");
+ for (; !set_nil(a); set_rm(t, a))
+ {
+ t = set_int(a);
+ if ( first ) first = 0;
+ else _gen(",");
+ if ( !DontCopyTokens ) _gen2("_tv%d%d,", BlkLevel, t);
+ _gen2("_t%d%d", BlkLevel, t);
+ if ( !DontCopyTokens ) {_gen2("= &_tv%d%d", BlkLevel, t);}
+ else _gen("=NULL");
+ }
+ _gen(";\n");
+ set_free(a);
+}
+
+static int
+#ifdef __USE_PROTOS
+hasDefaultException(ExceptionGroup *eg)
+#else
+hasDefaultException(eg)
+ExceptionGroup *eg;
+#endif
+{
+ ListNode *q;
+
+ for (q = eg->handlers->next; q!=NULL; q=q->next)
+ {
+ ExceptionHandler *eh = (ExceptionHandler *)q->elem;
+ if ( strcmp("default", eh->signalname)==0 ) {
+ return 1;
+ }
+ }
+ return 0;
+}
+static void
+#ifdef __USE_PROTOS
+dumpException(ExceptionGroup *eg, int no_default_case)
+#else
+dumpException(eg, no_default_case)
+ExceptionGroup *eg;
+int no_default_case;
+#endif
+{
+ char *outerLabel; /* MR7 */
+ int altHandler=0; /* MR7 */
+ int namedHandler=0; /* MR7 */
+
+ outerLabel=findOuterHandlerLabel(eg); /* MR7 */
+
+ if (eg->label != NULL) { /* MR7 */
+ namedHandler=1; /* MR7 */
+ } else if (eg->forRule) { /* MR7 */
+ /* nothing */ /* MR20 */
+ } else { /* MR7 */
+ altHandler=1; /* MR7 */
+ }; /* MR7 */
+
+#if 0
+** if (! eg->used) { /* MR7 */
+** warnFL("exception group never used", /* MR7 */
+** FileStr[eg->altstart->file],eg->altstart->line); /* MR7 */
+** }; /* MR7 */
+#endif
+
+ if (namedHandler) { /* MR7 */
+ gen1("switch ( _signal ) { /* [%s] */\n",eg->label); /* MR7 */
+ } else { /* MR7 */
+ gen("switch ( _signal ) {\n"); /* MR7 */
+ gen("case NoSignal: break; /* MR7 */\n"); /* MR7 */
+ }; /* MR7 */
+ {
+ ListNode *q;
+ for (q = eg->handlers->next; q!=NULL; q=q->next)
+ {
+ ExceptionHandler *eh = (ExceptionHandler *)q->elem;
+ if ( strcmp("default", eh->signalname)==0 ) {
+ gen("default :\n");
+ tabs++;
+ dumpAction(eh->action, output, tabs, -1, 1, 1);
+ gen("_signal=NoSignal; /* MR7 */\n"); /* MR7 */
+ gen("break; /* MR7 */\n"); /* MR7 */
+ tabs--;
+ gen("}\n");
+
+ /* copied from later code in dumpException */ /* MR7 */
+
+ if (namedHandler) { /* MR7 */
+ gen("if (_signal != NoSignal)"); /* MR7 */
+ _gen1(" goto %s_handler; /* MR7 */\n",outerLabel);/* MR7 */
+ } else if (altHandler) { /* MR7 */
+ gen1("goto %s_handler; /* MR7 */\n",outerLabel); /* MR7 */
+ };
+ return;
+ }
+ gen1("case %s :\n", eh->signalname);
+ tabs++;
+ if ( eh->action != NULL )
+ {
+ dumpAction(eh->action, output, tabs, -1, 1, 1);
+ gen("break; /* MR7 */\n"); /* MR7 */
+ }
+ tabs--;
+ }
+ }
+ if ( no_default_case ) return;
+
+ gen("default :\n");
+ tabs++; /* MR7 */
+ gen("break; /* MR7 */\n"); /* MR7 */
+ tabs--; /* MR7 */
+
+ tabs++;
+/***** gen("*_retsignal = _signal;\n"); *****/
+
+ tabs--;
+ gen("}\n");
+
+ if (namedHandler) { /* MR7 */
+ gen("if (_signal != NoSignal)"); /* MR7 */
+ _gen1(" goto %s_handler; /* MR7 */\n",outerLabel); /* MR7 */
+ } else if (altHandler) { /* MR7 */
+ gen1("goto %s_handler; /* MR7 */\n",outerLabel); /* MR7 */
+ };
+
+}
+
+static void
+#ifdef __USE_PROTOS
+dumpExceptions(ListNode *list)
+#else
+dumpExceptions(list)
+ListNode *list;
+#endif
+{
+ ListNode *p;
+
+ for (p = list->next; p!=NULL; p=p->next)
+ {
+ ExceptionGroup *eg = (ExceptionGroup *) p->elem;
+ _gen2("%s%s_handler:\n",
+ eg->label==NULL?"":eg->label,
+ eg->altID==NULL?"":eg->altID);
+ if ( eg->altID!=NULL ) dumpException(eg, 0);
+ else {
+ /* This must be the rule exception handler */
+ dumpException(eg, 1);
+ if ( !hasDefaultException(eg) )
+ {
+ gen("default :\n");
+ tabs++;
+ gen("zzdflthandlers(_signal,_retsignal);\n");
+ tabs--;
+ gen("}\n");
+ }
+ }
+ }
+}
+
+/* For each element label that is found in a rule, generate a unique
+ * Attribute (and AST pointer if GenAST) variable.
+ */
+void
+#ifdef __USE_PROTOS
+genElementLabels(ListNode *list)
+#else
+genElementLabels(list)
+ListNode *list;
+#endif
+{
+ int first=1;
+ ListNode *p;
+
+ if ( GenCC ) {gen("ANTLRTokenPtr");}
+ else {gen("Attrib");}
+ for (p = list->next; p!=NULL; p=p->next)
+ {
+ char *ep = (char *)p->elem;
+ if ( first ) first = 0;
+ else _gen(",");
+ if ( GenCC ) {_gen1(" %s=NULL",ep);}
+ else {_gen1(" %s",ep);}
+ }
+ _gen(";\n");
+
+ if ( !GenAST ) return;
+
+ first = 1;
+ gen("AST");
+ for (p = list->next; p!=NULL; p=p->next)
+ {
+ char *ep = (char *)p->elem;
+ if ( first ) first = 0;
+ else _gen(",");
+ _gen1(" *%s_ast=NULL",ep);
+ }
+ _gen(";\n");
+}
+
+/*
+ * Generate a local variable allocation for each token or rule reference
+ * in this block.
+ */
+static void
+#ifdef __USE_PROTOS
+genASTPointers( Junction *q )
+#else
+genASTPointers( q )
+Junction *q;
+#endif
+{
+ int first=1, t;
+ set a;
+
+ a = set_or(q->tokrefs, q->rulerefs);
+ if ( set_deg(a) > 0 )
+ {
+ gen("AST ");
+ for (; !set_nil(a); set_rm(t, a))
+ {
+ t = set_int(a);
+ if ( first ) first = 0;
+ else _gen(",");
+ _gen2("*_ast%d%d=NULL", BlkLevel, t);
+ }
+ set_free(a);
+ }
+ _gen(";\n");
+}
+
+static void
+#ifdef __USE_PROTOS
+BLOCK_Head( void )
+#else
+BLOCK_Head( )
+#endif
+{
+ gen("{\n");
+ tabs++;
+ if ( !GenCC ) gen1("zzBLOCK(zztasp%d);\n", BlkLevel);
+}
+
+static void
+#ifdef __USE_PROTOS
+BLOCK_Tail( void )
+#else
+BLOCK_Tail( )
+#endif
+{
+ if ( !GenCC ) gen1("zzEXIT(zztasp%d);\n", BlkLevel);
+ if ( !GenCC ) gen("}\n");
+ tabs--;
+ gen("}\n");
+}
+
+static void
+#ifdef __USE_PROTOS
+BLOCK_Preamble( Junction *q )
+#else
+BLOCK_Preamble( q )
+Junction *q;
+#endif
+{
+ ActionNode *a;
+ Junction *begin;
+
+ BLOCK_Head();
+ if ( GenCC ) genTokenPointers(q);
+ if ( GenCC&&GenAST ) genASTPointers(q);
+ if ( q->jtype == aPlusBlk ) gen("int zzcnt=1;\n");
+ if ( q->parm != NULL && !q->predparm ) gen1("zzaPush(%s);\n", q->parm)
+ else if ( !GenCC ) gen("zzMake0;\n");
+ if ( !GenCC ) gen("{\n");
+ if ( q->jtype == aLoopBegin ) begin = (Junction *) ((Junction *)q->p1);
+ else begin = q;
+ if ( has_guess_block_as_first_item(begin) )
+ {
+ gen("zzGUESS_BLOCK\n");
+ }
+ if ( q->jtype == aLoopBegin )
+ a = findImmedAction( ((Junction *)q->p1)->p1 ); /* look at aLoopBlk */
+ else
+ a = findImmedAction( q->p1 );
+ if ( a!=NULL && !a->is_predicate) {
+/* MR21 */ if (!a->noHoist) dumpActionPlus(a, a->action, output, tabs, a->file, a->line, 1);
+ a->done = 1; /* remove action. We have already handled it */
+ }
+}
+
+void
+#ifdef __USE_PROTOS
+genCombinedPredTreeContextOrig( Predicate *p )
+#else
+genCombinedPredTreeContextOrig( p )
+Predicate *p;
+#endif
+{
+ static set *ctx=NULL; /* genExprSets() is destructive, make copy*/
+ require(p!=NULL, "can't make context tree for NULL pred tree");
+
+#ifdef DBG_PRED
+ fprintf(stderr, "enter genCombinedPredTreeContextOrig(%s,0x%x) with sets:\n", p->expr, p);
+ s_fprT(stderr, p->scontext[1]);
+ fprintf(stderr, "\n");
+#endif
+ if ( p->down == NULL )
+ {
+/*** if ( p->k>1 && p->tcontext!=NULL ) ***/
+ if ( p->tcontext!=NULL )
+ {
+ _gen("(");
+ genExprTree(p->tcontext, 1);
+ _gen(")");
+ }
+/*** else if ( p->k==1 && set_deg(p->scontext[1])>0 ) ***/
+ else if ( set_deg(p->scontext[1])>0 )
+ {
+ if ( ctx==NULL ) ctx = (set *)calloc(CLL_k+1, sizeof(set));
+ require(ctx!=NULL, "ctx cannot allocate");
+ ctx[0]=empty;
+ ctx[1]=set_dup(p->scontext[1]);
+ _gen("(");
+ genExprSets(&(ctx[0]), p->k);
+ _gen(")");
+ set_free(ctx[1]);
+ }
+ else if ( p->expr==PRED_AND_LIST || p->expr==PRED_OR_LIST ) {
+ fatal_internal("pred tree is orphan OR or AND list");
+ }
+ else {
+ if (! HoistPredicateContext) {
+ _gen(" 1 /* no context: prc is off */ ");
+ } else {
+ fatal_internal("pred tree context is empty");
+ };
+ }
+ return;
+ }
+
+/* MR10 - make AND just like OR */
+
+ if ( p->expr == PRED_AND_LIST )
+ {
+ Predicate *list = p->down;
+ for (; list!=NULL; list=list->right)
+ {
+ genCombinedPredTreeContextOrig(list);
+ if ( list->right!=NULL ) _gen("|| /* MR10 was wrong */ ");
+ };
+ return;
+ }
+
+ if ( p->expr == PRED_OR_LIST )
+ {
+ Predicate *list = p->down;
+ for (; list!=NULL; list=list->right)
+ {
+ genCombinedPredTreeContextOrig(list);
+ if ( list->right!=NULL ) _gen("||");
+ };
+ return;
+ };
+
+ fatal("pred tree is really wacked");
+}
+
+/* [genCombinedPredTreeContext] */
+
+void
+#ifdef __USE_PROTOS
+genCombinedPredTreeContext( Predicate *p )
+#else
+genCombinedPredTreeContext( p )
+Predicate *p;
+#endif
+{
+ Tree *t;
+ int predDepth=0;
+
+ if (0 && ! MR_usingPredNames && ! MRhoisting) {
+ genCombinedPredTreeContextOrig(p);
+ } else {
+/* MR13 */ MR_pred_depth(p,&predDepth);
+/* MR13 */ if (predDepth == 1) {
+/* MR13 */
+/* MR13 */ set scontext[2];
+/* MR13 */ scontext[0]=empty;
+/* MR13 */ scontext[1]=MR_compute_pred_set(p);
+/* MR13 */ if (set_nil(scontext[1])) {
+/* MR13 */ _gen(" 1 /* MR12 no context (-prc off) */ ");
+/* MR13 */ } else {
+/* MR13 */ _gen("(");
+/* MR13 */ genExprSets(&scontext[0], 1);
+/* MR13 */ set_free(scontext[1]);
+/* MR13 */ _gen(")");
+/* MR13 */ };
+
+ } else {
+ t=MR_compute_pred_tree_context(p);
+ if (t == NULL) {
+ _gen(" 1 /* MR12 no context (-prc off) */ ");
+ } else {
+ _gen("(");
+ genExprTree(t, 1);
+ Tfree(t); /* MR10 */
+ _gen(")");
+ };
+ };
+ };
+}
+
+/* [genPredTreeGate] */
+
+void
+#ifdef __USE_PROTOS
+genPredTreeGate( Predicate *p, int in_and_expr )
+#else
+genPredTreeGate( p, in_and_expr )
+Predicate *p;
+int in_and_expr;
+#endif
+{
+ if ( in_and_expr )
+ {
+ _gen("!(");
+ genCombinedPredTreeContext(p);
+ _gen(")||");
+ if ( p->down!=NULL ) _gen("\n");
+ }
+ else
+ {
+ _gen("(");
+ genCombinedPredTreeContext(p);
+ _gen(")&&");
+ if ( p->down!=NULL ) _gen("\n");
+ }
+}
+
+#ifdef __USE_PROTOS
+void genPredEntry(Predicate *p,int outer)
+#else
+void genPredEntry(p,outer)
+ Predicate *p;
+ int outer;
+#endif
+{
+ int inverted=0;
+ Predicate *q;
+ int localOuter=outer;
+ int needRP=0;
+
+ if (p == NULL) return;
+
+ if (p->predEntry != NULL && p->predEntry->predLiteral != NULL) {
+ if (p->inverted != p->predEntry->pred->inverted) {
+ _gen("! /* inverted pred */ (");
+ needRP=1;
+ } else {
+ if (!localOuter) _gen("(");
+ needRP=1;
+ };
+ dumpAction(p->predEntry->predLiteral,output,0,p->source->file,p->source->line,0);
+ if (needRP) _gen(")");
+ return;
+ };
+
+ inverted=p->inverted;
+
+ if (inverted) {
+ _gen(" ! /* inverted pred */ (");
+ localOuter=1;
+ };
+
+ if (p->expr == PRED_OR_LIST) {
+ if (!localOuter) _gen("(");
+ for (q=p->down; q != NULL ; q=q->right) {
+ genPredEntry(q,0);
+ if (q->right != NULL) _gen(" || ");
+ };
+ if (!localOuter) _gen(")");
+ } else if (p->expr == PRED_AND_LIST) {
+ if (!localOuter) _gen("(");
+ for (q=p->down; q != NULL ; q=q->right) {
+ genPredEntry(q,0);
+ if (q->right != NULL) _gen(" && ");
+ };
+ if (!localOuter) _gen(")");
+ } else {
+ if (!localOuter) _gen("(");
+ require (p->source != NULL,"predEntry->source == NULL");
+ require (p->source->inverted == 0,"dumpPredEntry p->source->inverted != 0");
+ dumpAction(p->source->action,output,0,p->source->file,p->source->line,0);
+ if (!localOuter) _gen(")");
+ };
+
+ if (inverted) {
+ _gen(")");
+ }
+}
+
+void
+#ifdef __USE_PROTOS
+dumpPredAction(ActionNode *anode,
+ char *s,FILE *output,int tabs,int file,int line,int final_newline)
+#else
+dumpPredAction(anode,
+ s,output,tabs,file,line,final_newline)
+
+ ActionNode *anode;
+ char *s;
+ FILE *output;
+ int tabs;
+ int file;
+ int line;
+ int final_newline;
+#endif
+{
+ PredEntry *predEntry=anode->predEntry;
+ int inverted=anode->inverted;
+ Predicate *workPred;
+
+ if (predEntry == NULL) {
+
+ /* inline predicate literal */
+
+ require(inverted == 0,"dumpPredAction action->inverted");
+ dumpAction(s,output,tabs,file,line,final_newline);
+
+ } else {
+
+ /* a reference to a predicate - possibly with an inverted source */
+
+ if (predEntry->predLiteral != NULL) {
+ if (inverted) _gen("! /* inverted pred */ (");
+ dumpAction(predEntry->predLiteral,output,0,anode->file,anode->line,0);
+ if (inverted) _gen(")");
+ } else {
+ workPred=predicate_dup(predEntry->pred);
+ if (inverted) workPred->inverted=!workPred->inverted;
+ genPredEntry(workPred,1);
+ predicate_free(workPred);
+ };
+ };
+}
+
+/* [genPred] */
+
+void
+#ifdef __USE_PROTOS
+genPred(Predicate *p, Node *j,int suppress_sva)
+#else
+genPred(p,j,suppress_sva)
+ Predicate *p;
+ Node *j;
+ int suppress_sva;
+#endif
+{
+ if ( FoundException && !suppress_sva) {_gen("(_sva=(");} /* MR11 suppress_sva */
+ else {_gen("(");}
+ if ( GenLineInfo && j->file != -1 ) _gen("\n");
+ if (p->source != NULL && p->source->ampersandPred != NULL) {
+ if (p->source->ampersandPred->k == 1) {
+
+ set ctx[2];
+
+ ctx[0]=empty;
+ ctx[1]=set_dup(p->source->ampersandPred->scontext[1]);
+
+ _gen("(");
+ genExprSets(&(ctx[0]), p->k);
+ _gen(") && ");
+ set_free(ctx[1]);
+ } else {
+ _gen("( ");
+ genExprTree(p->source->ampersandPred->tcontext,1);
+ _gen(" ) && ");
+ };
+ };
+
+ dumpPredAction((ActionNode *)p->source,
+ p->expr, output, 0, -1 /*indicates no line info*/, j->line, 0);
+
+ if ( FoundException && !suppress_sva) /* MR11 suppress_sva */
+ {_gen("),_sva)");} /* MR10 - get red of "meant ==" messages */
+ else {_gen(")");}
+}
+
+void
+#ifdef __USE_PROTOS
+MR_distinctORcontextOpt(Predicate *p,Node *j,int in_and_expr)
+#else
+MR_distinctORcontextOpt(p,j,in_and_expr)
+ Predicate *p;
+ Node *j;
+ int in_and_expr;
+#endif
+{
+ Predicate *q;
+
+ _gen(" /* MR10 Distinct OR context optimization */ \n");
+
+ if (in_and_expr) {
+ gen("zzpf=0,\n");
+ for (q=p->down; q != NULL; q=q->right) {
+ gen("( ");
+ genCombinedPredTreeContext(q);
+ _gen(" && (zzpf=1, ");
+ genPred(q,j,0);
+ _gen(" )) ||\n");
+ };
+ gen("!zzpf)");
+ } else {
+ require (0,
+ "MR_distinctORcontextOpt: can't get here when using MR_predSimplify");
+#if 0
+** for (q=p->down; q != NULL; q=q->right) {
+** gen("( ");
+** genCombinedPredTreeContext(q);
+** _gen(" && ");
+** genPred(q,j);
+** if (q->right != NULL) {
+** _gen(" ) ||\n");
+** };
+** };
+** gen(")");
+#endif
+ };
+}
+
+void
+#ifdef __USE_PROTOS
+genPredTreeOrig( Predicate *p, Node *j, int in_and_expr )
+#else
+genPredTreeOrig( p, j, in_and_expr )
+Predicate *p;
+Node *j;
+int in_and_expr;
+#endif
+{
+
+/* MR10 */ int allHaveContext=1;
+/* MR10 */ int noneHaveContext=1;
+
+/* MR10 */ MR_predContextPresent(p,&allHaveContext,&noneHaveContext);
+
+ if ( ! noneHaveContext ) /* MR10 context guards ignored when -prc off */
+ {
+ _gen("(");
+ genPredTreeGate(p, in_and_expr);
+ }
+
+ /* if leaf node, just gen predicate */
+
+ if ( p->down==NULL )
+ {
+ genPred(p,j,0);
+ if ( ! noneHaveContext ) _gen(")"); /* MR10 context guards ignored when -prc off */
+ return;
+ }
+
+ /* if AND list, do both preds (only two possible) */
+ if ( p->expr == PRED_AND_LIST )
+ {
+#if 0
+** _gen("(");
+** genPredTreeOrig(p->down, j, 1);
+** _gen("&&");
+** genPredTreeOrig(p->down->right, j, 1);
+** _gen(")");
+** if ( ! noneHaveContext ) _gen(")"); /* MR10 context guards ignored when -prc off */
+** return;
+#endif
+ /* MR11 - make it work with AND with more than two children - like OR */
+
+ Predicate *list;
+ _gen("(");
+ list = p->down;
+ for (; list!=NULL; list=list->right)
+ {
+ genPredTreeOrig(list, j, 1);
+ if ( list->right!=NULL ) _gen("&&");
+ }
+ _gen(")");
+ if ( ! noneHaveContext ) _gen(")"); /* MR10 context guards ignored when -prc off */
+ return;
+ };
+
+ if ( p->expr == PRED_OR_LIST )
+ {
+ Predicate *list;
+ _gen("(");
+ list = p->down;
+ for (; list!=NULL; list=list->right)
+ {
+ genPredTreeOrig(list, j, 0);
+ if ( list->right!=NULL ) _gen("||");
+ }
+ _gen(")");
+ if ( ! noneHaveContext ) _gen(")"); /* MR10 context guards ignored when -prc off */
+ return;
+ }
+
+ fatal_internal("genPredTreeOrig: predicate tree is wacked");
+}
+
+#if 0
+** Predicate member dummyPredDepth is no longer used in MR10
+** but we might need it again in the future
+**
+** if (MRhoisting) {
+** if ( !noneHaveContext &&
+** ! in_and_expr &&
+** p->source != NULL &&
+** p->source->dummyPredicateDepth > 0 &&
+** p->down == NULL) {
+** _gen("(");
+** genCombinedPredTreeContext(p);
+** _gen(" )\n");
+** return;
+** };
+** };
+#endif
+
+/* [genPredTree] */
+
+/* in_and_expr
+
+ what to do if the context is wrong
+ what to do if the context is correct but the predicate is false
+
+ remember: if the context is wrong it's the same as if the
+ predicate is true as far as enabling an alternative
+
+ Consider (AND p q r)
+
+ if in an ... && ... expression then you don't want
+ the entire predicate chain to fail just because the
+ context for one component is wrong: so return true
+
+ Consider (OR p q r)
+
+ if in an ... || ... expression then you don't want
+ the entire predicate chain to succeed just because
+ the context for one component is correct when the
+ corresponding test is false: so return false when
+ the context is correct but the test is false.
+*/
+
+void
+#ifdef __USE_PROTOS
+genPredTree( Predicate *p, Node *j, int in_and_expr, int suppress_sva )
+#else
+genPredTree( p, j, in_and_expr, suppress_sva)
+ Predicate *p;
+ Node *j;
+ int in_and_expr;
+ int suppress_sva;
+#endif
+{
+
+ int allHaveContext=1;
+ int noneHaveContext=1;
+ Tree *groupTree;
+ Tree *oneTree;
+ Predicate *q;
+ int identicalORcontextOptimization=0;
+ int identicalANDcontextOptimization=0;
+
+ if (0 && !MR_usingPredNames && !MRhoisting) {
+ genPredTreeOrig(p,j,in_and_expr);
+ return;
+ };
+
+ MR_predContextPresent(p,&allHaveContext,&noneHaveContext);
+
+ if ( ! noneHaveContext ) { /* MR10 context guards ignored when -prc off */
+
+ _gen("(");
+
+ /* MR10 optimize OR predicates which are all leaves */
+
+ if (p->expr == PRED_OR_LIST && MR_allPredLeaves(p->down)) {
+ groupTree=MR_compute_pred_tree_context(p);
+ for (q=p->down ; q != NULL ; q=q->right) {
+ oneTree=MR_compute_pred_tree_context(q);
+ if (! MR_tree_equ(groupTree,oneTree)) {
+ Tfree(oneTree);
+ break;
+ };
+ Tfree(oneTree);
+ };
+ Tfree(groupTree);
+ if (q == NULL) {
+ _gen("/* MR10 individual OR gates suppressed when all predicates are leaves");
+ _gen(" with identical context */\n");
+ genPredTreeGate(p,in_and_expr); /* use the parent's in_and_expr for this gate */
+ identicalORcontextOptimization=1;
+ } else {
+ MR_distinctORcontextOpt(p,j,in_and_expr);
+ return;
+ };
+ } else if (p->expr == PRED_AND_LIST && MR_allPredLeaves(p->down)) {
+
+ /* MR12 optimize AND predicates which are all leaves */
+
+ groupTree=MR_compute_pred_tree_context(p);
+ for (q=p->down ; q != NULL ; q=q->right) {
+ oneTree=MR_compute_pred_tree_context(q);
+ if (! MR_tree_equ(groupTree,oneTree)) {
+ Tfree(oneTree);
+ break;
+ };
+ Tfree(oneTree);
+ };
+ Tfree(groupTree);
+ if (q == NULL) {
+ _gen("/* MR12 individual AND gates suppressed when all predicates are leaves");
+ _gen(" with identical context */\n");
+ genPredTreeGate(p,in_and_expr); /* use the parent's in_and_expr for this gate */
+ identicalANDcontextOptimization=1;
+ } else {
+ genPredTreeGate(p, in_and_expr);
+ };
+ } else {
+ genPredTreeGate(p, in_and_expr);
+ };
+ }
+
+ /* if leaf node, just gen predicate */
+
+ if ( p->down==NULL )
+ {
+ genPred(p,j,suppress_sva);
+ if ( ! noneHaveContext ) _gen(")"); /* MR10 context guards ignored when -prc off */
+ return;
+ }
+
+ /* if AND list, do both preds (only two possible) */
+ /* MR10 not any more ! */
+
+ if ( p->expr == PRED_AND_LIST )
+ {
+ Predicate *list;
+ _gen("(");
+ list = p->down;
+ for (; list != NULL; list=list->right) {
+ if (identicalANDcontextOptimization) {
+ genPred(list, j,suppress_sva);
+ } else {
+ genPredTree(list, j, 1, suppress_sva); /* in and context */
+ };
+ if ( list->right!=NULL ) _gen("&&");
+ };
+ _gen(")");
+ if ( ! noneHaveContext ) _gen(")"); /* MR10 context guards ignored when -prc off */
+ return;
+ }
+
+ if ( p->expr == PRED_OR_LIST )
+ {
+ Predicate *list;
+ _gen("(");
+ list = p->down;
+ for (; list!=NULL; list=list->right)
+ {
+ if (identicalORcontextOptimization) {
+ genPred(list, j,suppress_sva);
+ } else {
+ genPredTree(list, j, 0, suppress_sva);
+ };
+ if ( list->right!=NULL ) _gen("||");
+ }
+ _gen(")");
+ if ( ! noneHaveContext ) _gen(")"); /* MR10 context guards ignored when -prc off */
+ return;
+ }
+
+ fatal_internal("predicate tree is wacked");
+}
+
+/* [genPredTreeMainXX] */
+
+Predicate * /* MR10 */
+#ifdef __USE_PROTOS
+genPredTreeMainXX( Predicate *p, Node *j ,int in_and_expr)
+#else
+genPredTreeMainXX( p, j ,in_and_expr)
+ Predicate *p;
+ Node *j;
+ int in_and_expr;
+#endif
+{
+
+ int allHaveContext=1;
+ int noneHaveContext=1;
+
+#if 0
+ fprintf(stderr,"Pred before\n");
+ dumppred(p);
+ fprintf(stderr,"\n");
+ fprintf(stderr,"Pred after\n");
+ dumppred(p);
+ fprintf(stderr,"\n");
+#endif
+
+ p=MR_predSimplifyALL(p); /* MR10 */
+
+ require (MR_predicate_context_completed(p),"predicate context is not complete");
+
+ MR_cleanup_pred_trees(p); /* MR10 */
+
+ MR_predContextPresent(p,&allHaveContext,&noneHaveContext);
+ if (!noneHaveContext & !allHaveContext) {
+ warnFL("predicate contains elements both with and without context",
+ FileStr[j->file],j->line);
+ };
+
+ if (InfoP) {
+ _gen("\n#if 0\n\n");
+ MR_dumpPred(p,1);
+ _gen("#endif\n");
+ };
+ genPredTree(p,j,in_and_expr,0);
+ return p;
+}
+
+Predicate * /* MR10 */
+#ifdef __USE_PROTOS
+genPredTreeMain( Predicate *p, Node *j)
+#else
+genPredTreeMain( p, j)
+ Predicate *p;
+ Node *j;
+#endif
+{
+ return genPredTreeMainXX(p,j,1);
+}
+
+static void
+#ifdef __USE_PROTOS
+genExprTreeOriginal( Tree *t, int k )
+#else
+genExprTreeOriginal( t, k )
+Tree *t;
+int k;
+#endif
+{
+ require(t!=NULL, "genExprTreeOriginal: NULL tree");
+
+ if ( t->token == ALT )
+ {
+ _gen("("); genExprTreeOriginal(t->down, k); _gen(")");
+ if ( t->right!=NULL )
+ {
+ _gen("||");
+ on1line++;
+ if ( on1line > NumExprPerLine ) { on1line=0; _gen("\n"); }
+ _gen("("); genExprTreeOriginal(t->right, k); _gen(")");
+ }
+ return;
+ }
+ if ( t->down!=NULL ) _gen("(");
+ _gen1("LA(%d)==",k);
+ if ( TokenString(t->token) == NULL ) _gen1("%d", t->token)
+ else _gen1("%s", TokenString(t->token));
+ if ( t->down!=NULL )
+ {
+ _gen("&&");
+ on1line++;
+ if ( on1line > NumExprPerLine ) { on1line=0; _gen("\n"); }
+ _gen("("); genExprTreeOriginal(t->down, k+1); _gen(")");
+ }
+ if ( t->down!=NULL ) _gen(")");
+ if ( t->right!=NULL )
+ {
+ _gen("||");
+ on1line++;
+ if ( on1line > NumExprPerLine ) { on1line=0; _gen("\n"); }
+ _gen("("); genExprTreeOriginal(t->right, k); _gen(")");
+ }
+}
+
+#ifdef __USE_PROTOS
+static void MR_LAtokenString(int k,int token)
+#else
+static void MR_LAtokenString(k,token)
+ int k;
+ int token;
+#endif
+{
+ char *ts;
+
+ ts=TokenString(token);
+ if (ts == NULL) {
+ _gen2(" LA(%d)==%d",k,token);
+ } else {
+ _gen2(" LA(%d)==%s",k,ts);
+ };
+}
+
+
+#ifdef __USE_PROTOS
+static int MR_countLeaves(Tree *t)
+#else
+static int MR_countLeaves(t)
+ Tree *t;
+#endif
+{
+ if (t == NULL) return 0;
+ if (t->token == ALT) {
+ return MR_countLeaves(t->down)+MR_countLeaves(t->right);
+ } else {
+ return 1+MR_countLeaves(t->down)+MR_countLeaves(t->right);
+ };
+}
+
+#ifdef __USE_PROTOS
+static void MR_genOneLine(Tree *tree,int k)
+#else
+static void MR_genOneLine(tree,k)
+ Tree *tree;
+ int k;
+#endif
+{
+ if (tree == NULL) return;
+ if (tree->token == ALT) {
+ MR_genOneLine(tree->down,k);
+ } else {
+ MR_LAtokenString(k,tree->token);
+ if (tree->down != NULL &&
+ tree->down->right == NULL) {
+ _gen(" &&");
+ MR_genOneLine(tree->down,k+1);
+ } else if (tree->down != NULL) {
+ _gen(" && (");
+ MR_genOneLine(tree->down,k+1);
+ _gen(")");
+ };
+ };
+ if (tree->right != NULL) {
+ _gen(" ||");
+ MR_genOneLine(tree->right,k);
+ };
+}
+
+static int across;
+static int depth;
+static int lastkonline;
+
+#ifdef __USE_PROTOS
+static void MR_genMultiLine(Tree *tree,int k)
+#else
+static void MR_genMultiLine(tree,k)
+ Tree *tree;
+ int k;
+#endif
+{
+ int i;
+
+ if (tree == NULL) return;
+ if (tree->token == ALT) {
+ MR_genMultiLine(tree,k);
+ } else {
+ MR_LAtokenString(k,tree->token);
+ lastkonline=k;
+ across++;
+ if (tree->down != NULL && tree->down->right == NULL) {
+ if (across > 3) {
+ _gen("\n");
+ across=0;
+ lastkonline=0;
+ for (i=0 ; i < depth+k ; i++) _gen(" ");
+ _gen("&&");
+ } else {
+ _gen(" &&");
+ };
+ MR_genMultiLine(tree->down,k+1);
+ } else if (tree->down != NULL) {
+ _gen("\n");
+ lastkonline=0;
+ across=0;
+ for (i=0 ; i < depth+k ; i++) _gen(" ");
+ _gen("&& (");
+ MR_genMultiLine(tree->down,k+1);
+ _gen(")");
+ };
+ };
+ if (tree->right != NULL) {
+ if (k < lastkonline) {
+ _gen("\n");
+ across=0;
+ lastkonline=0;
+ for (i=0; i < depth+k-1 ; i++) _gen(" ");
+ _gen("||");
+ } else if (across > 3 ) {
+ _gen("\n");
+ across=0;
+ lastkonline=0;
+ for (i=0; i < depth+k ; i++) _gen(" ");
+ _gen("||");
+ } else {
+ _gen(" ||");
+ };
+ MR_genMultiLine(tree->right,k);
+ };
+}
+
+#ifdef __USE_PROTOS
+static void genExprTree(Tree *tree,int k)
+#else
+static void genExprTree(tree,k)
+ Tree *tree;
+ int k;
+#endif
+{
+ int count;
+
+#if 0
+ /* MR20 THM This was probably an error.
+ The routine should probably reference that static
+ "across" and this declaration hides it.
+ */
+
+ int across;
+#endif
+
+ require (tree != NULL,"genExprTree: tree is NULL");
+ require (k > 0,"genExprTree: k <= 0");
+
+ if (0 && !MRhoisting) { /* MR11 make new version standard */
+ genExprTreeOriginal(tree,k);
+ } else {
+ count=MR_countLeaves(tree);
+ if (count < 5) {
+ MR_genOneLine(tree,k);
+ } else {
+ _gen("\n");
+ across=0;
+ depth=0;
+ lastkonline=0;
+ MR_genMultiLine(tree,k);
+ _gen("\n");
+ };
+ };
+}
+
+
+/*
+ * Generate LL(k) type expressions of the form:
+ *
+ * (LA(1) == T1 || LA(1) == T2 || ... || LA(1) == Tn) &&
+ * (LA(2) == T1 || LA(2) == T2 || ... || LA(2) == Tn) &&
+ * .....
+ * (LA(k) == T1 || LA(k) == T2 || ... || LA(k) == Tn)
+ *
+ * If GenExprSetsOpt generate:
+ *
+ * (setwdi[LA(1)]&(1<<j)) && (setwdi[LA(2)]&(1<<j)) ...
+ *
+ * where n is set_deg(expr) and Ti is some random token and k is the last nonempty
+ * set in fset <=CLL_k.
+ * k=1..CLL_k where CLL_k >= 1.
+ *
+ * This routine is visible only to this file and cannot answer a TRANS message.
+ *
+ */
+
+/* [genExpr] */
+
+static int
+#ifdef __USE_PROTOS
+genExpr( Junction *j )
+#else
+genExpr( j )
+Junction *j;
+#endif
+{
+ int max_k;
+
+ /* if full LL(k) is sufficient, then don't use approximate (-ck) lookahead
+ * from CLL_k..LL_k
+ */
+ {
+ int limit;
+ if ( j->ftree!=NULL ) limit = LL_k;
+ else limit = CLL_k;
+ max_k = genExprSets(j->fset, limit);
+ }
+
+ /* Do tests for real tuples from other productions that conflict with
+ * artificial tuples generated by compression (using sets of tokens
+ * rather than k-trees).
+ */
+ if ( j->ftree != NULL )
+ {
+ _gen(" && !("); genExprTree(j->ftree, 1); _gen(")");
+ }
+
+ if ( ParseWithPredicates && j->predicate!=NULL )
+ {
+ Predicate *p = j->predicate;
+ warn_about_using_gk_option();
+ _gen("&&");
+ j->predicate=genPredTreeMain(p, (Node *)j); /* MR10 */
+ }
+
+ return max_k;
+}
+
+static int
+#ifdef __USE_PROTOS
+genExprSets( set *fset, int limit )
+#else
+genExprSets( fset, limit )
+set *fset;
+int limit;
+#endif
+{
+ int k = 1;
+ int max_k = 0;
+ unsigned *e, *g, firstTime=1;
+
+ if (set_nil(fset[1])) {
+ _gen(" 0 /* MR13 empty set expression - undefined rule ? infinite left recursion ? */ ");
+ MR_BadExprSets++;
+ };
+
+ if ( GenExprSetsOpt )
+ {
+ while ( k <= limit && !set_nil(fset[k]) ) /* MR11 */
+ {
+ if ( set_deg(fset[k])==1 ) /* too simple for a set? */
+ {
+ int e;
+ _gen1("(LA(%d)==",k);
+ e = set_int(fset[k]);
+ if ( TokenString(e) == NULL ) _gen1("%d)", e)
+ else _gen1("%s)", TokenString(e));
+ }
+ else
+ {
+ NewSet();
+ FillSet( fset[k] );
+ _gen3("(setwd%d[LA(%d)]&0x%x)", wordnum, k, 1<<setnum);
+ }
+ if ( k>max_k ) max_k = k;
+ if ( k == CLL_k ) break;
+ k++;
+ if ( k<=limit && !set_nil(fset[k]) ) _gen(" && "); /* MR11 */
+ on1line++;
+ if ( on1line > NumExprPerLine ) { on1line=0; _gen("\n"); }
+ }
+ return max_k;
+ }
+
+ while ( k<= limit && !set_nil(fset[k]) ) /* MR11 */
+ {
+ if ( (e=g=set_pdq(fset[k])) == NULL ) fatal_internal("genExpr: cannot allocate IF expr pdq set");
+ for (; *e!=nil; e++)
+ {
+ if ( !firstTime ) _gen(" || ") else { _gen("("); firstTime = 0; }
+ on1line++;
+ if ( on1line > NumExprPerLine ) { on1line=0; _gen("\n"); }
+ _gen1("LA(%d)==",k);
+ if ( TokenString(*e) == NULL ) _gen1("%d", *e)
+ else _gen1("%s", TokenString(*e));
+ }
+ free( (char *)g );
+ _gen(")");
+ if ( k>max_k ) max_k = k;
+ if ( k == CLL_k ) break;
+ k++;
+ if ( k <= limit && !set_nil(fset[k]) ) { firstTime=1; _gen(" && "); } /* MR11 */
+ on1line++;
+ if ( on1line > NumExprPerLine ) { on1line=0; _gen("\n"); }
+ }
+ return max_k;
+}
+
+/*
+ * Generate code for any type of block. If the last alternative in the block is
+ * empty (not even an action) don't bother doing it. This permits us to handle
+ * optional and loop blocks as well.
+ *
+ * Only do this block, return after completing the block.
+ * This routine is visible only to this file and cannot answer a TRANS message.
+ */
+static set
+#ifdef __USE_PROTOS
+genBlk( Junction *q, int jtype, int *max_k, int *need_right_curly, int * lastAltEmpty /* MR23 */)
+#else
+genBlk( q, jtype, max_k, need_right_curly, lastAltEmpty /* MR23 */)
+Junction *q;
+int jtype;
+int *max_k;
+int *need_right_curly;
+int *lastAltEmpty; /* MR23 */
+#endif
+{
+ set f;
+ Junction *alt;
+ int a_guess_in_block = 0;
+ require(q!=NULL, "genBlk: invalid node");
+ require(q->ntype == nJunction, "genBlk: not junction");
+ *need_right_curly=0;
+ *lastAltEmpty = 0; /* MR23 */
+ if ( q->p2 == NULL ) /* only one alternative? Then don't need if */
+ {
+ if (first_item_is_guess_block((Junction *)q->p1)!=NULL )
+ {
+ if (jtype != aLoopBlk && jtype != aOptBlk && jtype != aPlusBlk) {
+ warnFL("(...)? as only alternative of block is unnecessary", FileStr[q->file], q->line);
+ };
+ gen("zzGUESS\n"); /* guess anyway to make output code consistent */
+/* MR10 disable */ /**** gen("if ( !zzrv )\n"); ****/
+/* MR10 */ gen("if ( !zzrv ) {\n"); tabs++; (*need_right_curly)++;
+ };
+ TRANS(q->p1);
+ return empty; /* no decision to be made-->no error set */
+ }
+
+ f = First(q, 1, jtype, max_k);
+ for (alt=q; alt != NULL; alt= (Junction *) alt->p2 )
+ {
+ if ( alt->p2 == NULL ) /* chk for empty alt */
+ {
+ Node *p = alt->p1;
+ if ( p->ntype == nJunction )
+ {
+ /* we have empty alt */
+/* MR23
+ There is a conflict between giving good error information for non-exceptions
+ and making life easy for those using parser exception handling. Consider:
+
+ r: { A } b;
+ b: B;
+
+ with input "C"
+
+ Before MR21 the error message would be "expecting B - found C". After MR21
+ the error message would be "expcect A, B - found C". This was good, but it
+ caused problems for those using parser exceptions because the reference to
+ B was generated inside the {...} where B really wasn't part of the block.
+
+ In MR23 this has been changed for the case where exceptions are in use to
+ not generate the extra check in the tail of the {A} block.
+*/
+
+
+/* MR23 */ if (isEmptyAlt( ((Junction *)p)->p1, (Node *)q->end)) {
+/* MR23 */ *lastAltEmpty = 1;
+/* MR23 */ if (FoundException) {
+/* MR23 */ /* code to restore state if a prev alt didn't follow guess */
+/* MR23 */ if ( a_guess_in_block && jtype != aPlusBlk) {
+/* MR23 */ gen("if ( !zzrv ) zzGUESS_DONE; /* MR28 */\n");
+/* MR23 */ }
+/* MR23 */ break;
+/* MR23 */ };
+/* MR28 */ if (jtype == aPlusBlk) {
+/* MR28 */ break;
+/* MR28 */ }
+/* MR23 */ }
+ }
+ } /* end of for loop on alt */
+
+/* MR10 */ if (alt->p2 == NULL &&
+/* MR10 */ ( q->jtype == aSubBlk || q->jtype == RuleBlk) ) {
+/* MR10 */ if (first_item_is_guess_block(alt)) {
+/* MR10 */ warnFL("(...)? as last alternative of block is unnecessary",
+/* MR10 */ FileStr[alt->file],alt->line);
+/* MR10 */ };
+/* MR10 */ };
+
+ if ( alt != q ) gen("else ")
+ else
+ {
+ if ( DemandLookahead ) {
+ if ( !GenCC ) {gen1("LOOK(%d);\n", *max_k);}
+ else gen1("look(%d);\n", *max_k);
+ }
+ }
+
+ if ( alt!=q )
+ {
+ _gen("{\n");
+ tabs++;
+ (*need_right_curly)++;
+ /* code to restore state if a prev alt didn't follow guess */
+ if ( a_guess_in_block )
+ gen("if ( !zzrv ) zzGUESS_DONE;\n");
+ }
+ if ( first_item_is_guess_block((Junction *)alt->p1)!=NULL )
+ {
+ a_guess_in_block = 1;
+ gen("zzGUESS\n");
+ }
+ gen("if ( ");
+ if ( first_item_is_guess_block((Junction *)alt->p1)!=NULL ) _gen("!zzrv && ");
+ genExpr(alt);
+ _gen(" ) ");
+ _gen("{\n");
+ tabs++;
+ TRANS(alt->p1);
+ --tabs;
+ gen("}\n");
+/* MR10 */ if (alt->p2 == NULL) {
+/* MR10 */ if (first_item_is_guess_block(alt)) {
+/* MR10 */ gen("/* MR10 */ else {\n");
+/* MR10 */ tabs++;
+/* MR10 */ (*need_right_curly)++;
+/* MR10 */ /* code to restore state if a prev alt didn't follow guess */
+/* MR10 */ gen("/* MR10 */ if ( !zzrv ) zzGUESS_DONE;\n");
+/* MR10 */ gen("/* MR10 */ if (0) {} /* last alternative of block is guess block */\n");
+/* MR10 */ };
+/* MR10 */ };
+ }
+ return f;
+}
+
+static int
+#ifdef __USE_PROTOS
+has_guess_block_as_first_item( Junction *q )
+#else
+has_guess_block_as_first_item( q )
+Junction *q;
+#endif
+{
+ Junction *alt;
+
+ for (alt=q; alt != NULL; alt= (Junction *) alt->p2 )
+ {
+ if ( first_item_is_guess_block((Junction *)alt->p1)!=NULL ) return 1;
+ }
+ return 0;
+}
+
+static int
+#ifdef __USE_PROTOS
+has_guess_block_as_last_item( Junction *q )
+#else
+has_guess_block_as_last_item( q )
+Junction *q;
+#endif
+{
+ Junction *alt;
+
+ if (q == NULL) return 0;
+ for (alt=q; alt->p2 != NULL && !( (Junction *) alt->p2)->ignore; alt= (Junction *) alt->p2 ) {};
+ return first_item_is_guess_block( (Junction *) alt->p1) != NULL;
+}
+
+/* MR30 See description of first_item_is_guess_block for background */
+
+Junction *
+#ifdef __USE_PROTOS
+first_item_is_guess_block_extra(Junction *q )
+#else
+first_item_is_guess_block_extra(q)
+Junction *q;
+#endif
+{
+ while ( q!=NULL &&
+ ( ( q->ntype==nAction ) ||
+ ( q->ntype==nJunction &&
+ (q->jtype==Generic || q->jtype == aLoopBlk)
+ )
+ )
+ )
+ {
+ if ( q->ntype==nJunction ) q = (Junction *)q->p1;
+ else q = (Junction *) ((ActionNode *)q)->next;
+ }
+
+ if ( q==NULL ) return NULL;
+ if ( q->ntype!=nJunction ) return NULL;
+ if ( q->jtype!=aSubBlk ) return NULL;
+ if ( !q->guess ) return NULL;
+
+ return q;
+}
+
+/* return NULL if 1st item of alt is NOT (...)? block; else return ptr to aSubBlk node
+ * of (...)?; This function ignores actions and predicates.
+ */
+
+Junction *
+#ifdef __USE_PROTOS
+first_item_is_guess_block( Junction *q )
+#else
+first_item_is_guess_block( q )
+Junction *q;
+#endif
+{
+ Junction * qOriginal = q; /* DEBUG */
+
+ /* MR14 Couldn't find aSubBlock which was a guess block when it lay
+ behind aLoopBlk. The aLoopBlk only appear in conjunction with
+ aLoopBegin, but the routine didn't know that. I think.
+
+ MR14a Added extra parentheses to clarify precedence
+
+ MR30 This appears to have been a mistake. The First set was then
+ computed incorrectly for:
+
+ r : ( (A)? B
+ | C
+ )*
+
+ The routine analysis_point was seeing the guess block when
+ it was still analyzing the loopBegin block. As a consequence,
+ when it looked for the analysis_point it was processing the B, but
+ skipping over the C alternative altogether because it thought
+ it was looking at a guess block, not realizing there was a loop
+ block in front of the loopBegin.
+
+ loopBegin loopBlk subBlk/guess A G EB G B EB EB EB ER
+ | | | ^ ^
+ | | | |
+ | +-> G C G ----------------------+ |
+ | |
+ +--- G G G -------------------------------------+
+
+ Reported by Arpad Beszedes (beszedes@inf.u-szeged.hu).
+
+ MR30 This is still more complicated. This fix caused ambiguity messages
+ to be reported for "( (A B)? )* A B" but not for "( (A B)? )+". Why is
+ there a difference when these are outwardly identical ? It is because the
+ start of a (...)* block is represented by two nodes: a loopBegin block
+ followed by a loopBlock whereas the start of a (...)+ block is
+ represented as a single node: a plusBlock. So if first_item_is_guess_block
+ is called when the current node is a loopBegin it starts with the
+ loop block rather than the the sub block which follows the loop block.
+ However, we can't just skip past the loop block because some routines
+ depend on the old implementation. So, we provide a new implementation
+ which does skip the loopBlock. However, which should be called when ?
+ I'm not sure, but my guess is that first_item_is_guess_block_extra (the
+ new one) should only be called for the ambiguity routines.
+
+ */
+
+ while ( q!=NULL &&
+ ( ( q->ntype==nAction ) ||
+ ( q->ntype==nJunction &&
+ (q->jtype==Generic /*** || q->jtype == aLoopBlk ***/ ) /*** MR30 Undo MR14 change ***/
+ )
+ )
+ )
+ {
+ if ( q->ntype==nJunction ) q = (Junction *)q->p1;
+ else q = (Junction *) ((ActionNode *)q)->next;
+ }
+
+ if ( q==NULL ) return NULL;
+ if ( q->ntype!=nJunction ) return NULL;
+ if ( q->jtype!=aSubBlk ) return NULL;
+ if ( !q->guess ) return NULL;
+
+ return q;
+}
+
+/* MR1 */
+/* MR1 10-Apr-97 MR1 Routine to stringize failed semantic predicates msgs */
+/* MR1 */
+
+#define STRINGIZEBUFSIZE 1024
+
+static char stringizeBuf[STRINGIZEBUFSIZE];
+char *
+#ifdef __USE_PROTOS
+stringize(char * s)
+#else
+stringize(s)
+char *s;
+#endif
+
+{
+ char *p;
+ char *stop;
+
+ p=stringizeBuf;
+ stop=&stringizeBuf[1015];
+
+ if (s != 0) {
+ while (*s != 0) {
+ if (p >= stop) {
+ goto stringizeStop;
+ } else if (*s == '\n') {
+ *p++='\\';
+ *p++='n';
+ *p++='\\';
+ *p++=*s++;
+ } else if (*s == '\\') {
+ *p++=*s;
+ *p++=*s++;
+ } else if (*s == '\"') {
+ *p++='\\';
+ *p++=*s++;
+ while (*s != 0) {
+ if (p >= stop) {
+ goto stringizeStop;
+ } else if (*s == '\n') {
+ *p++='\\';
+ *p++=*s++;
+ } else if (*s == '\\') {
+ *p++=*s++;
+ *p++=*s++;
+ } else if (*s == '\"') {
+ *p++='\\';
+ *p++=*s++;
+ break;
+ } else {
+ *p++=*s++;
+ };
+ };
+ } else if (*s == '\'') {
+ *p++=*s++;
+ while (*s != 0) {
+ if (p >= stop) {
+ goto stringizeStop;
+ } else if (*s == '\'') {
+ *p++=*s++;
+ break;
+ } else if (*s == '\\') {
+ *p++=*s++;
+ *p++=*s++;
+ } else if (*s == '\"') {
+ *p++='\\';
+ *p++=*s++;
+ break;
+ } else {
+ *p++=*s++;
+ };
+ };
+ } else {
+ *p++=*s++;
+ };
+ };
+ };
+ goto stringizeExit;
+stringizeStop:
+ *p++='.';
+ *p++='.';
+ *p++='.';
+stringizeExit:
+ *p=0;
+ return stringizeBuf;
+}
+
+#ifdef __USE_PROTOS
+int isNullAction(char *s)
+#else
+int isNullAction(s)
+ char *s;
+#endif
+{
+ char *p;
+ for (p=s; *p != '\0' ; p++) {
+ if (*p != ';' && *p !=' ') return 0;
+ };
+ return 1;
+}
+/* MR1 */
+/* MR1 End of Routine to stringize code for failed predicates msgs */
+/* MR1 */
+
+/* Generate an action. Don't if action is NULL which means that it was already
+ * handled as an init action.
+ */
+void
+#ifdef __USE_PROTOS
+genAction( ActionNode *p )
+#else
+genAction( p )
+ActionNode *p;
+#endif
+{
+ require(p!=NULL, "genAction: invalid node and/or rule");
+ require(p->ntype==nAction, "genAction: not action");
+
+ if ( !p->done ) /* MR10 */ /* MR11 */
+ {
+ if ( p->is_predicate)
+ {
+ if ( p->guardpred != NULL )
+ {
+ Predicate *guardDup=predicate_dup(p->guardpred); /* MR10 */
+ gen("if (!");
+ guardDup=genPredTreeMain(guardDup, (Node *)p);
+ predicate_free(guardDup);
+ }
+/* MR10 */ else if (p->ampersandPred != NULL) {
+/* MR10 */ gen("if (!");
+/* MR10 */ p->ampersandPred=genPredTreeMain(p->ampersandPred, (Node *)p);
+/* MR10 */ }
+ else
+ {
+ gen("if (!(");
+ /* make sure that '#line n' is on front of line */
+ if ( GenLineInfo && p->file != -1 ) _gen("\n");
+ dumpPredAction(p,p->action, output, 0, p->file, p->line, 0);
+ _gen(")");
+ }
+
+/* MR23 Change failed predicate macro to have three arguments:
+
+ macro arg 1: The stringized predicate itself
+ macro arg 2: 0 => no user-defined error action
+ 1 => user-defined error action
+ macro arg 3: The user-defined error action
+
+ This gives the user more control of the error action.
+*/
+ tabs++;
+ gen3(") {zzfailed_pred(\"%s\",%s, { %s } );}\n", /* MR23 */
+ stringize(p->action), /* MR23 */
+ (p->pred_fail == NULL ? /* MR23/MR27 */
+ "0 /* report */" : "1 /* user action */"), /* MR23/MR27 */
+ (p->pred_fail == NULL ? /* MR23 */
+ "0; /* no user action */" : p->pred_fail)); /* MR23 */
+ tabs--;
+ }
+ else /* not a predicate */
+ {
+ if (! isNullAction(p->action) && !p->noHoist) {
+ if ( FoundGuessBlk ) {
+ if ( GenCC ) {
+ gen("if ( !guessing ) {\n");
+ } else {
+ gen("zzNON_GUESS_MODE {\n");
+ };
+ };
+ dumpActionPlus(p, p->action, output, tabs, p->file, p->line, 1); /* MR21 */
+ if ( FoundGuessBlk ) gen("}\n");
+ };
+ }
+ }
+ TRANS(p->next)
+}
+
+/*
+ * if invoking rule has !noAST pass zzSTR to rule ref and zzlink it in
+ * else pass addr of temp root ptr (&_ast) (don't zzlink it in).
+ *
+ * if ! modifies rule-ref, then never link it in and never pass zzSTR.
+ * Always pass address of temp root ptr.
+ */
+void
+#ifdef __USE_PROTOS
+genRuleRef( RuleRefNode *p )
+#else
+genRuleRef( p )
+RuleRefNode *p;
+#endif
+{
+ Junction *q;
+ char *handler_id = "";
+ RuleEntry *r, *r2;
+ char *parm = "", *exsig = "";
+
+ int genRuleRef_emittedGuessGuard=0; /* MR10 */
+
+ require(p!=NULL, "genRuleRef: invalid node and/or rule");
+ require(p->ntype==nRuleRef, "genRuleRef: not rule reference");
+
+ if ( p->altstart!=NULL && p->altstart->exception_label!=NULL )
+ handler_id = p->altstart->exception_label;
+
+ r = (RuleEntry *) hash_get(Rname, p->text);
+ if ( r == NULL )
+ {
+ warnFL( eMsg1("rule %s not defined",
+ p->text), FileStr[p->file], p->line );
+ return;
+ }
+
+/* MR8 5-Aug-97 Reported by S.Bochnak@microtool.com.pl */
+/* Don't do assign when no return values declared */
+/* Move definition of q up and use it to guard p->assign */
+
+ q = RulePtr[r->rulenum]; /* find definition of ref'd rule */ /* MR8 */
+
+ r2 = (RuleEntry *) hash_get(Rname, p->rname);
+ if ( r2 == NULL ) {warnNoFL("Rule hash table is screwed up beyond belief"); return;}
+
+ OutLineInfo(output,p->line,FileStr[p->file]);
+
+ if ( GenCC && GenAST ) {
+ gen("_ast = NULL;\n");
+ }
+
+ if ( FoundGuessBlk && p->assign!=NULL && q->ret != NULL ) { /* MR8 */
+ if ( GenCC ) {
+ gen("if ( !guessing ) {\n");
+ } else {
+ gen("zzNON_GUESS_MODE {\n");
+ };
+ tabs++; /* MR11 */
+ genRuleRef_emittedGuessGuard=1; /* MR11 */
+ };
+
+ if ( FoundException ) exsig = "&_signal";
+
+ tab();
+ if ( GenAST )
+ {
+ if ( GenCC ) {
+/**** if ( r2->noAST || p->astnode==ASTexclude )
+****/
+ {
+/**** _gen("_ast = NULL;\n");
+****/
+ parm = "&_ast";
+ }
+/*** we always want to set just a pointer now, then set correct
+pointer after
+
+ else {
+ _gen("_astp =
+(_tail==NULL)?(&_sibling):(&(_tail->_right));\n");
+ parm = "_astp";
+ }
+****/
+ }
+ else {
+ if ( r2->noAST || p->astnode==ASTexclude )
+ {
+ _gen("_ast = NULL; ");
+ parm = "&_ast";
+ }
+ else parm = "zzSTR";
+ }
+ if ( p->assign!=NULL && q->ret!=NULL ) /* MR8 */
+ {
+ if ( !hasMultipleOperands(p->assign) ) {_gen1("%s = ",p->assign);} /* MR23 */
+ else _gen1("{ struct _rv%d _trv; _trv = ", r->rulenum);
+ }
+ if ( FoundException ) {
+ _gen5("%s%s(%s,&_signal%s%s); ",
+ RulePrefix,
+ p->text,
+ parm,
+ (p->parms!=NULL)?",":"",
+ (p->parms!=NULL)?p->parms:"");
+ if ( p->ex_group!=NULL ) {
+ _gen("\n");
+ gen("if (_signal) {\n");
+ tabs++;
+ dumpException(p->ex_group, 0);
+ tabs--;
+ gen("}");
+ }
+ else {
+ _gen1("if (_signal) goto %s_handler;", handler_id);
+ }
+ }
+ else {
+ _gen5("%s%s(%s%s%s);",
+ RulePrefix,
+ p->text,
+ parm,
+ (p->parms!=NULL)?",":"",
+ (p->parms!=NULL)?p->parms:"");
+ }
+ if ( GenCC && (r2->noAST || p->astnode==ASTexclude) )
+ {
+ /* rule has a ! or element does */
+ /* still need to assign to #i so we can play with it */
+ _gen("\n");
+ gen2("_ast%d%d = (AST *)_ast;", BlkLevel-1, p->elnum);
+ }
+ else if ( !r2->noAST && p->astnode == ASTinclude )
+ {
+ /* rule doesn't have a ! and neither does element */
+/* MR10 */ if (FoundGuessBlk && !genRuleRef_emittedGuessGuard) {
+/* MR10 */ _gen("\n");
+/* MR10 */ if (GenCC) gen ("if (!guessing) { /* MR10 */")
+/* MR10 */ else gen ("if (!zzguessing) { /* MR10 */\n");
+/* MR10 */ tabs++;
+/* MR10 */ };
+ if ( GenCC ) {
+ _gen("\n");
+ gen("if ( _tail==NULL ) _sibling = _ast; else _tail->setRight(_ast);\n");
+ gen2("_ast%d%d = (AST *)_ast;\n", BlkLevel-1, p->elnum);
+ tab();
+ }
+ else _gen(" ");
+ if ( GenCC ) {
+ _gen("ASTBase::"); }
+ else _gen("zz");
+ _gen("link(_root, &_sibling, &_tail);");
+
+/* MR10 */ if (FoundGuessBlk && !genRuleRef_emittedGuessGuard) { /* MR10 */
+/* MR10 */ _gen("\n");
+/* MR10 */ tabs--;
+/* MR10 */ if (GenCC) gen ("}; /* MR10 */")
+/* MR10 */ else gen ("}; /* MR10 */");
+/* MR10 */ };
+ }
+ }
+ else
+ {
+ if ( p->assign!=NULL && q->ret!=NULL ) /* MR8 */
+ {
+ if ( !hasMultipleOperands(p->assign) ) {_gen1("%s = ",p->assign);} /* MR23 */
+ else _gen1("{ struct _rv%d _trv; _trv = ", r->rulenum);
+ }
+ if ( FoundException ) {
+ _gen4("%s%s(&_signal%s%s); ",
+ RulePrefix,
+ p->text,
+ (p->parms!=NULL)?",":"",
+ (p->parms!=NULL)?p->parms:"");
+ if ( p->ex_group!=NULL ) {
+ _gen("\n");
+ gen("if (_signal) {\n");
+ tabs++;
+ dumpException(p->ex_group, 0);
+ tabs--;
+ gen("}");
+ }
+ else {
+ _gen1("if (_signal) goto %s_handler;", handler_id);
+ }
+ }
+ else {
+ _gen3("%s%s(%s);",
+ RulePrefix,
+ p->text,
+ (p->parms!=NULL)?p->parms:"");
+ }
+ if ( p->assign!=NULL && q->ret!=NULL ) _gen("\n"); /* MR8 */
+ }
+
+ if ( p->assign!=NULL && q->ret!=NULL) { /* MR8 */
+ if ( hasMultipleOperands(p->assign) ) /* MR23 */
+ {
+ _gen("\n");
+ dumpRetValAssign(p->assign, q->ret, p); /* MR30 */
+ _gen("}");
+ }
+ }
+ _gen("\n");
+
+ /* Handle element labels now */
+ if ( p->el_label!=NULL )
+ {
+ if ( GenAST )
+ {
+ if ( GenCC ) {
+ gen3("%s_ast = _ast%d%d;\n", p->el_label, BlkLevel-1, p->elnum);
+ }
+ else {gen1("%s_ast = zzastCur;\n", p->el_label);}
+ }
+ else if (!GenCC ) {
+ gen1("%s = zzaCur;\n", p->el_label);
+ }
+ }
+
+ if ( FoundGuessBlk && p->assign!=NULL && q->ret!=NULL ) { /* MR8 */
+ /* in guessing mode, don't branch to handler upon error */
+ tabs--; /* MR11 */
+ gen("} else {\n");
+ tabs++; /* MR11 */
+ if ( FoundException ) {
+ gen6("%s%s(%s%s&_signal%s%s);\n",
+ RulePrefix,
+ p->text,
+ parm,
+ (*parm!='\0')?",":"",
+ (p->parms!=NULL)?",":"",
+ (p->parms!=NULL)?p->parms:"");
+ }
+ else {
+ gen5("%s%s(%s%s%s);\n",
+ RulePrefix,
+ p->text,
+ parm,
+ (p->parms!=NULL && *parm!='\0')?",":"",
+ (p->parms!=NULL)?p->parms:"");
+ }
+ tabs--; /* MR11 */
+ gen("}\n");
+ }
+ TRANS(p->next)
+}
+
+/*
+ * Generate code to match a token.
+ *
+ * Getting the next token is tricky. We want to ensure that any action
+ * following a token is executed before the next GetToken();
+ */
+void
+#ifdef __USE_PROTOS
+genToken( TokNode *p )
+#else
+genToken( p )
+TokNode *p;
+#endif
+{
+ RuleEntry *r;
+ char *handler_id = "";
+ ActionNode *a;
+ char *set_name;
+ char *set_nameErrSet;
+ int complement;
+ int ast_label_in_action = 0; /* MR27 */
+ int pushedCmodeAST = 0; /* MR27 */
+
+ require(p!=NULL, "genToken: invalid node and/or rule");
+ require(p->ntype==nToken, "genToken: not token");
+ if ( p->altstart!=NULL && p->altstart->exception_label!=NULL )
+ handler_id = p->altstart->exception_label;
+
+ r = (RuleEntry *) hash_get(Rname, p->rname);
+ if ( r == NULL ) {warnNoFL("Rule hash table is screwed up beyond belief"); return;}
+
+/*
+ * MR27 Has the element label been referenced as an AST (with the # operator) ?
+ * If so, then we'll want to build the AST even though the user has used
+ * the ! operator.
+ */
+/* MR27 */ if (GenAST && p->el_label != NULL) {
+/* MR27 */ ast_label_in_action = list_search_cstring(r->ast_labels_in_actions,
+/* MR27 */ p->el_label);
+/* MR27 */ }
+
+ OutLineInfo(output,p->line,FileStr[p->file]);
+
+ if ( !set_nil(p->tset) ) /* implies '.', ~Tok, or tokenclass */
+ {
+ unsigned e;
+ unsigned eErrSet = 0;
+ set b;
+ set bErrSet; /* MR23 */
+ b = set_dup(p->tset);
+ bErrSet = set_dup(p->tset); /* MR23 */
+ complement = p->complement; /* MR23 */
+ if ( p->tclass!=NULL && complement == 0 /* MR23 */) { /* token class not complemented*/
+ static char buf[MaxRuleName+20]; /* MR23 */
+ static char bufErrSet[MaxRuleName+20]; /* MR23 */
+ if ( p->tclass->dumped ) {
+ e = p->tclass->setnum;
+ eErrSet = p->tclass->setnumErrSet;
+ }
+ else {
+ e = DefErrSet(&b, 0, TokenString(p->token));
+ eErrSet = DefErrSetWithSuffix(0, &bErrSet, 1, TokenString(p->token), "_errset");
+ p->tclass->dumped = 1; /* indicate set has been created */
+ p->tclass->setnum = e;
+ p->tclass->setnumErrSet = eErrSet; /* MR23 */
+ }
+ sprintf(buf, "%s_set", TokenString(p->token));
+ sprintf(bufErrSet, "%s_errset", TokenString(p->token)); /* MR23 */
+ set_name = buf;
+ set_nameErrSet = bufErrSet; /* MR23 */
+ }
+
+ /* MR23 - Forgot about the case of ~TOKCLASS. */
+
+ else if ( p->tclass!=NULL && complement != 0 /* MR23 */)
+ {
+ static char buf[MaxRuleName+20]; /* MR23 */
+ static char bufErrSet[MaxRuleName+20]; /* MR23 */
+ if ( p->tclass->dumpedComplement ) {
+ e = p->tclass->setnumComplement;
+ eErrSet = p->tclass->setnumErrSetComplement;
+ }
+ else {
+ e = DefErrSetWithSuffix(0, &b, 0, TokenString(p->token), "_setbar");
+ eErrSet = DefErrSetWithSuffix(0, &bErrSet, 1, TokenString(p->token), "_errsetbar");
+ p->tclass->dumpedComplement = 1; /* indicate set has been created */
+ p->tclass->setnumComplement = e;
+ p->tclass->setnumErrSetComplement = eErrSet; /* MR23 */
+ }
+ sprintf(buf, "%s_setbar", TokenString(p->token));
+ sprintf(bufErrSet, "%s_errsetbar", TokenString(p->token)); /* MR23 */
+ set_name = buf;
+ set_nameErrSet = bufErrSet; /* MR23 */
+ }
+ else { /* wild card */
+ static char buf[sizeof("zzerr")+10];
+ static char bufErrSet[sizeof("zzerr")+10];
+ int n = DefErrSet( &b, 0, NULL );
+ int nErrSet = DefErrSetWithSuffix(0, &bErrSet, 1, NULL, "_set");
+ if ( GenCC ) sprintf(buf, "err%d", n);
+ else sprintf(buf, "zzerr%d", n);
+ if ( GenCC ) sprintf(bufErrSet, "err%d", nErrSet);
+ else sprintf(bufErrSet, "zzerr%d", nErrSet);
+ set_name = buf;
+ set_nameErrSet = bufErrSet;
+ }
+
+ if ( !FoundException ) {
+/* MR23 */ gen2("zzsetmatch(%s, %s);", set_name, set_nameErrSet);
+ }
+ else if ( p->ex_group==NULL ) {
+ if ( p->use_def_MT_handler )
+ gen3("zzsetmatch_wdfltsig(%s,(ANTLRTokenType)%d,%s);",
+ set_name,
+ p->token,
+ tokenFollowSet(p))
+ else
+ gen2("zzsetmatch_wsig(%s, %s_handler);",
+ set_name,
+ handler_id);
+ }
+ else
+ {
+ gen1("if ( !_setmatch_wsig(%s) ) {\n", set_name);
+ tabs++;
+/* MR6 */ if (FoundGuessBlk) {
+/* MR6 */ if ( GenCC ) {gen("if ( guessing ) goto fail;\n");}
+/* MR6 */ else gen("if ( zzguessing ) goto fail;\n");
+/* MR6 */ };
+ gen("_signal=MismatchedToken;\n");
+ dumpException(p->ex_group, 0);
+ tabs--;
+ gen("}\n");
+ }
+ set_free(b);
+ set_free(bErrSet);
+ }
+ else if ( TokenString(p->token)!=NULL )
+ {
+ if ( FoundException ) {
+ if ( p->use_def_MT_handler )
+ gen2("zzmatch_wdfltsig(%s,%s);",TokenString(p->token),tokenFollowSet(p))
+ else if ( p->ex_group==NULL )
+ {
+ gen2("zzmatch_wsig(%s, %s_handler);",
+ TokenString(p->token),
+ handler_id);
+ }
+ else
+ {
+/* MR6 */ if (GenCC) {
+/* MR6 */ gen1("if ( !_match_wsig(%s) ) {\n", TokenString(p->token));
+/* MR6 */ } else {
+/* MR6 */ gen1("if ( !_zzmatch_wsig(%s) ) {\n", TokenString(p->token));
+/* MR6 */ };
+ tabs++;
+/* MR6 */ if (FoundGuessBlk) {
+/* MR6 */ if ( GenCC ) {gen("if ( guessing ) goto fail;\n");}
+/* MR6 */ else gen("if ( zzguessing ) goto fail;\n");
+/* MR6 */ };
+ gen("_signal=MismatchedToken;\n");
+ dumpException(p->ex_group, 0);
+ tabs--;
+ gen("}\n");
+ }
+ }
+ else gen1("zzmatch(%s);", TokenString(p->token));
+ }
+ else {
+ if ( FoundException ) {
+ if ( p->use_def_MT_handler )
+ gen2("zzmatch_wdfltsig((ANTLRTokenType)%d,%s);",
+ p->token,tokenFollowSet(p))
+ else
+ gen2("zzmatch_wsig(%d,%s_handler);",p->token,handler_id);
+ }
+ else {gen1("zzmatch(%d);", p->token);}
+ }
+
+ a = findImmedAction( p->next );
+ /* generate the token labels */
+ if ( GenCC && p->elnum>0 )
+ {
+ /* If building trees in C++, always gen the LT() assigns */
+ if ( set_el(p->elnum, tokensRefdInBlock) || GenAST )
+ {
+/* MR10 */ if ( FoundGuessBlk ) {
+/* MR10 */ gen("\n");
+/* MR10 */ if (p->label_used_in_semantic_pred) {
+/* MR10 */ gen2(" _t%d%d = (ANTLRTokenPtr)LT(1); /* MR10 */\n", BlkLevel-1, p->elnum);
+/* MR10 */ } else {
+/* MR10 */ gen("if ( !guessing ) {\n"); tab();
+/* MR10 */ _gen2(" _t%d%d = (ANTLRTokenPtr)LT(1);\n", BlkLevel-1, p->elnum);
+/* MR10 */ gen("}\n");
+/* MR10 */ };
+/* MR10 */ } else {
+/* MR10 */ _gen2(" _t%d%d = (ANTLRTokenPtr)LT(1);", BlkLevel-1, p->elnum);
+/* MR10 */ };
+/* MR10 */
+ }
+
+/*
+ * MR23 labase is never used in the C++ runtime library.
+ * and this code is generated only in C++ mode
+ */
+
+/*** if ( LL_k>1 ) / * MR23 disabled */
+/*** if ( !DemandLookahead ) _gen(" labase++;"); / * MR23 disabled */
+/*** _gen("\n"); / * MR23 disabled */
+/*** tab(); / * MR23 disabled */
+ }
+ if ( GenAST )
+ {
+ if ( FoundGuessBlk &&
+ (ast_label_in_action || !(p->astnode == ASTexclude || r->noAST)) )
+ {
+ if ( GenCC ) {_gen("if ( !guessing ) {\n"); tab();}
+ else {_gen("zzNON_GUESS_MODE {\n"); tab();}
+ }
+
+/* MR27 addition when labels referenced when operator ! used */
+
+ pushedCmodeAST = 0; /* MR27 */
+ if (ast_label_in_action && (p->astnode == ASTexclude || r->noAST)) {
+ _gen("\n");
+ if (GenCC) {
+/* MR13 */ if (NewAST) {
+/* MR13 */ gen4("_ast%d%d = newAST(_t%d%d); /* MR27 */\n", BlkLevel-1, p->elnum, BlkLevel-1, p->elnum);
+/* MR13 */ } else {
+/* MR13 */ gen4("_ast%d%d = new AST(_t%d%d); /* MR27 */\n", BlkLevel-1, p->elnum, BlkLevel-1, p->elnum);
+/* MR13 */ }
+ }
+ else {
+ pushedCmodeAST = 1;
+ gen("zzastPush(zzmk_ast(zzastnew(),zzaCur)); /* MR27 */");
+ }
+ }
+
+/* end MR27 addition for labels referenced when operator ! used */
+
+ if (!r->noAST )
+ {
+ if (GenCC && !(p->astnode == ASTexclude) ) {
+ _gen("\n");
+/* MR13 */ if (NewAST) {
+/* MR13 */ gen4("_ast%d%d = newAST(_t%d%d);\n", BlkLevel-1, p->elnum, BlkLevel-1, p->elnum);
+/* MR13 */ } else {
+/* MR13 */ gen4("_ast%d%d = new AST(_t%d%d);\n", BlkLevel-1, p->elnum, BlkLevel-1, p->elnum);
+/* MR13 */ }
+ tab();
+ }
+ if ( GenCC && !(p->astnode == ASTexclude) )
+ {_gen2("_ast%d%d->", BlkLevel-1, p->elnum);}
+ else _gen(" ");
+ if ( p->astnode==ASTchild ) {
+ if ( !GenCC ) _gen("zz");
+ _gen("subchild(_root, &_sibling, &_tail);");
+ }
+ else if ( p->astnode==ASTroot ) {
+ if ( !GenCC ) _gen("zz");
+ _gen("subroot(_root, &_sibling, &_tail);");
+ }
+ if ( GenCC && !(p->astnode == ASTexclude) ) {
+ _gen("\n");
+ tab();
+ }
+ }
+ else if ( !GenCC ) {
+ if (! pushedCmodeAST) _gen(" zzastDPush;");
+ }
+ if ( FoundGuessBlk &&
+ (ast_label_in_action || !(p->astnode == ASTexclude || r->noAST)) )
+ {gen("}\n"); tab();}
+ }
+
+ /* Handle element labels now */
+ if ( p->el_label!=NULL )
+ {
+ int done_NON_GUESSMODE=0;
+
+ _gen("\n");
+
+/* MR10 */ /* do Attrib / Token ptr for token label used in semantic pred */
+/* MR10 */ /* for these cases do assign even in guess mode */
+/* MR10 */
+/* MR10 */ if (p->label_used_in_semantic_pred) {
+/* MR10 */ if ( GenCC ) {
+/* MR10 */ if ( set_el(p->elnum, tokensRefdInBlock) || GenAST ) {
+/* MR10 */ gen3("%s = _t%d%d;", p->el_label, BlkLevel-1, p->elnum);
+/* MR10 */ } else {
+/* MR10 */ gen1("%s = (ANTLRTokenPtr)LT(1);\n", p->el_label);
+/* MR10 */ };
+/* MR10 */ } else {
+/* MR10 */ gen1("%s = zzaCur;", p->el_label);
+/* MR10 */ };
+/* MR10 */ if (FoundGuessBlk) _gen(" /* MR10 */");
+/* MR10 */ _gen("\n");
+/* MR10 */ };
+
+ /* Do Attrib / Token ptr */
+
+/* MR10 */ if (! p->label_used_in_semantic_pred) {
+/* MR10 */
+/* MR10 */ if ( FoundGuessBlk ) {
+/* MR10 */ if (! done_NON_GUESSMODE) {
+/* MR10 */ done_NON_GUESSMODE=1;
+/* MR10 */ if ( GenCC ) {gen("if ( !guessing ) {\n"); tab();}
+/* MR10 */ else {gen("zzNON_GUESS_MODE {\n"); tab();}
+/* MR10 */ };
+/* MR10 */ };
+/* MR10 */
+/* MR10 */ if ( GenCC ) {
+/* MR10 */ if ( set_el(p->elnum, tokensRefdInBlock) || GenAST ) {
+/* MR10 */ gen3("%s = _t%d%d;\n", p->el_label, BlkLevel-1, p->elnum);
+/* MR10 */ } else {
+/* MR10 */ gen1("%s = (ANTLRTokenPtr)LT(1);\n", p->el_label);
+/* MR10 */ };
+/* MR10 */ } else {
+/* MR10 */ gen1("%s = zzaCur;\n", p->el_label);
+/* MR10 */ };
+/* MR10 */ };
+
+ /* Do AST ptr */
+
+ if (GenAST && (ast_label_in_action || !(p->astnode == ASTexclude || r->noAST) )) /* MR27 */
+ {
+
+/* MR10 */ if ( FoundGuessBlk ) {
+/* MR10 */ if (! done_NON_GUESSMODE) {
+/* MR10 */ done_NON_GUESSMODE=1;
+/* MR10 */ if ( GenCC ) {gen("if ( !guessing ) {\n"); tab();}
+/* MR10 */ else {gen("zzNON_GUESS_MODE {\n"); tab();}
+/* MR10 */ };
+/* MR10 */ };
+
+ if ( GenCC ) {
+ gen3("%s_ast = _ast%d%d;\n", p->el_label, BlkLevel-1, p->elnum);
+ }
+ else {gen1("%s_ast = zzastCur;\n", p->el_label);}
+ }
+
+/* MR10 */ if (done_NON_GUESSMODE) {
+/* MR10 */ gen("}\n"); tab();
+/* MR10 */ };
+
+ }
+
+ /* Handle any actions immediately following action */
+ if ( a != NULL ) /* MR10 */ /* MR11 */
+ {
+ /* delay next token fetch until after action */
+ _gen("\n");
+ if ( a->is_predicate)
+ {
+#if 0
+/* Disabled in MR30 ************************************************************
+ And moved into genAction
+ *****************************************************************************
+*/
+
+ gen("if (!(");
+
+ /* make sure that '#line n' is on front of line */ /* MR14 */
+ if ( GenLineInfo && p->file != -1 ) _gen("\n"); /* MR14 */
+ dumpPredAction(a,a->action, output, 0, a->file, a->line, 0);
+
+/* MR23 Change failed predicate macro to have three arguments:
+
+ macro arg 1: The stringized predicate itself
+ macro arg 2: 0 => no user-defined error action
+ 1 => user-defined error action
+ macro arg 3: The user-defined error action
+
+ This gives the user more control of the error action.
+*/
+ _gen(")) \n");
+ tabs++;
+ gen3(" {zzfailed_pred(\"%s\",%s,{ %s } );}\n", /* MR23 */
+ stringize(a->action), /* MR23 */
+ (a->pred_fail == NULL ? /* MR23/MR27 */
+ "0 /* report */" : "1 /* user action */"), /* MR23/MR27 */
+ (a->pred_fail == NULL ? /* MR23 */
+ "0; /* no user action */" : a->pred_fail)); /* MR23 */
+ tabs--;
+/* Disabled in MR30 ************************************************************
+ And moved into genAction
+ *****************************************************************************
+*/
+#endif
+ }
+ else /* MR9 a regular action - not a predicate action */
+ {
+
+/* MR23: Search an action which is not a predicate for LT(i),
+ LA(i), or LATEXT(i) in order to warn novice users that
+ it refers to the previous matched token, not the next
+ one. This is different than the case for semantic
+ predicates.
+*/
+
+/* MR23 */ if (GenCC) {
+/* MR23 */ if (strstr(a->action, "LT(") != NULL) LTinTokenAction = 1;
+/* MR23 */ }
+/* MR23 */ else {
+/* MR23 */ if (strstr(a->action, "LA(") != NULL) LTinTokenAction = 1;
+/* MR23 */ if (strstr(a->action, "LATEXT(") != NULL) LTinTokenAction = 1;
+/* MR23 */ }
+
+ if ( FoundGuessBlk ) {
+ if ( GenCC ) {gen("if ( !guessing ) {\n");}
+ else gen("zzNON_GUESS_MODE {\n");
+ }
+ dumpActionPlus(a, a->action, output, tabs, a->file, a->line, 1); /* MR21 */
+ if ( FoundGuessBlk ) gen("}\n");
+ a->done = 1; /* MR30 */
+ }
+/*** a->done = 1; MR30 Moved up into then branch for true actions, but not predicates ***/
+ if ( !DemandLookahead ) {
+ if ( GenCC ) {
+ if ( FoundException && p->use_def_MT_handler ) gen("if (!_signal)");
+ _gen(" consume();")
+ if ( FoundException && p->use_def_MT_handler )
+ _gen(" _signal=NoSignal;");
+ _gen("\n");
+ }
+ else
+ {
+ if ( FoundException && p->use_def_MT_handler ) _gen("if (!_signal)");
+ _gen(" zzCONSUME;\n");
+ if ( FoundException && p->use_def_MT_handler ) _gen(" _signal=NoSignal;");
+ _gen("\n");
+ }
+ }
+ else gen("\n");
+ if (a->done) { /* MR30 */
+ TRANS( a->next ); /* MR30 */
+ } /* MR30 */
+ else { /* MR30 */
+ TRANS( p->next ); /* MR30 */
+ } /* MR30 */
+ }
+ else
+ {
+ if ( !DemandLookahead ) {
+ if ( GenCC ) {
+ if (FoundException && p->use_def_MT_handler) _gen("if (!_signal)");
+ _gen(" consume();")
+ if (FoundException&&p->use_def_MT_handler) _gen(" _signal=NoSignal;");
+ _gen("\n");
+ }
+ else {
+ if (FoundException && p->use_def_MT_handler) _gen("if (!_signal)");
+ _gen(" zzCONSUME;");
+ if ( FoundException && p->use_def_MT_handler ) _gen(" _signal=NoSignal;");
+ _gen("\n");
+ }
+ }
+ else _gen("\n");
+ TRANS(p->next);
+ }
+}
+
+/* MR21
+ *
+ * There was a bug in the code generation for {...} which causes it
+ * to omit the optional tokens from the error messages. The easiest
+ * way to fix this was to make the opt block look like a sub block:
+ *
+ * { a | b | c }
+ *
+ * becomes (internally):
+ *
+ * ( a | b | c | )
+ *
+ * The code for genOptBlk is now identical to genSubBlk except for
+ * cosmetic changes.
+ */
+
+void
+#ifdef __USE_PROTOS
+genOptBlk( Junction *q )
+#else
+genOptBlk( q )
+Junction *q;
+#endif
+{
+ int max_k;
+ set f;
+ int need_right_curly;
+ set savetkref;
+ int lastAltEmpty; /* MR23 */
+ savetkref = tokensRefdInBlock;
+ require(q->ntype == nJunction, "genOptBlk: not junction");
+ require(q->jtype == aOptBlk, "genOptBlk: not opt block");
+
+ OutLineInfo(output,q->line,FileStr[q->file]);
+ BLOCK_Preamble(q);
+ BlkLevel++;
+ BlockPreambleOption(q,q->pFirstSetSymbol); /* MR21 */
+ f = genBlk(q, aOptBlk, &max_k, &need_right_curly, &lastAltEmpty /* MR23 */);
+/* MR23
+ Bypass error clause generation when exceptions are used in {...} block
+ See multi-line note in genBlk near call to isEmptyAlt.
+*/
+ if (! FoundException) {
+ if ( q->p2 != NULL ) {tab(); makeErrorClause(q,f,max_k,0 /* use plus block bypass ? */ );}
+ }
+ else {
+ gen("/* MR23 skip error clause for {...} when exceptions in use */\n");
+ }
+ { int i; for (i=1; i<=need_right_curly; i++) {tabs--; gen("}\n");} }
+ freeBlkFsets(q);
+ --BlkLevel;
+ BLOCK_Tail();
+
+ if ( q->guess )
+ {
+ gen("zzGUESS_DONE\n");
+ }
+
+ /* must duplicate if (alpha)?; one guesses (validates), the
+ * second pass matches */
+ if ( q->guess && analysis_point(q)==q )
+ {
+ OutLineInfo(output,q->line,FileStr[q->file]);
+ BLOCK_Preamble(q);
+ BlkLevel++;
+ f = genBlk(q, aSubBlk, &max_k, &need_right_curly, &lastAltEmpty /* MR23 */);
+ if ( q->p2 != NULL ) {tab(); makeErrorClause(q,f,max_k,0 /* use plus block bypass ? */ );}
+ { int i; for (i=1; i<=need_right_curly; i++) {tabs--; gen("}\n");} }
+ freeBlkFsets(q);
+ --BlkLevel;
+ BLOCK_Tail();
+ }
+
+ tokensRefdInBlock = savetkref;
+ if (q->end->p1 != NULL) TRANS(q->end->p1);
+}
+
+/*
+ * Generate code for a loop blk of form:
+ *
+ * |---|
+ * v |
+ * --o-G-o-->o--
+ */
+void
+#ifdef __USE_PROTOS
+genLoopBlk( Junction *begin, Junction *q, Junction *start, int max_k )
+#else
+genLoopBlk( begin, q, start, max_k )
+Junction *begin;
+Junction *q;
+Junction *start; /* where to start generating code from */
+int max_k;
+#endif
+{
+ set f;
+ int need_right_curly;
+ set savetkref;
+ Junction *guessBlock; /* MR10 */
+ int singleAlt; /* MR10 */
+ int lastAltEmpty; /* MR23 */
+
+ savetkref = tokensRefdInBlock;
+ require(q->ntype == nJunction, "genLoopBlk: not junction");
+ require(q->jtype == aLoopBlk, "genLoopBlk: not loop block");
+
+ if ( q->visited ) return;
+ q->visited = TRUE;
+
+ /* first_item_is_guess_block doesn't care what kind of node it is */
+
+ guessBlock=first_item_is_guess_block( (Junction *) q->p1); /* MR10 */
+ singleAlt=q->p2==NULL; /* MR10 */
+
+ if (singleAlt && !guessBlock) /* MR10 */ /* only one alternative? */
+ {
+ if ( DemandLookahead ) {
+ if ( !GenCC ) {gen1("LOOK(%d);\n", max_k);}
+ else gen1("look(%d);\n", max_k);
+ }
+ gen("while ( ");
+ if ( begin!=NULL ) genExpr(begin);
+ else genExpr(q);
+ /* if no predicates have been hoisted for this single alt (..)*
+ * do so now
+ */
+ require(MR_PredRuleRefStack.count == 0,"PredRuleRef stack not empty");
+ if ( ParseWithPredicates && begin->predicate==NULL )
+ {
+ Predicate *a = MR_find_predicates_and_supp((Node *)q->p1);
+ require(MR_PredRuleRefStack.count == 0,"PredRuleRef stack not empty");
+
+ if ( a!=NULL )
+ {
+ _gen("&&");
+ a=genPredTreeMain(a, (Node *)q); /* MR10 */
+ }
+/* MR10 */ if (MRhoisting) {
+/* MR10 */ predicate_free(a);
+/* MR10 */ };
+ }
+ _gen(" ) {\n");
+ tabs++;
+ TRANS(q->p1);
+ if ( !GenCC ) gen1("zzLOOP(zztasp%d);\n", BlkLevel-1);
+ if ( DemandLookahead ) {
+ if ( !GenCC ) {gen1("LOOK(%d);\n", max_k);}
+ else gen1("look(%d);\n", max_k);
+ }
+ --tabs;
+ gen("}\n");
+ freeBlkFsets(q);
+ q->visited = FALSE;
+ tokensRefdInBlock = savetkref;
+ return;
+ }
+ gen("for (;;) {\n"); /* MR20 G. Hobbelt */
+ tabs++;
+/* MR6 */
+/* MR6 "begin" can never be null when called from genLoopBegin */
+/* MR6 because q==(Junction *)begin->p1 and we know q is valid */
+/* MR6 */
+/* MR6 from genLoopBegin: */
+/* MR6 */
+/* MR6 if ( LL_k>1 && !set_nil(q->fset[2]) ) */
+/* MR6 genLoopBlk( q, (Junction *)q->p1, q, max_k ); */
+/* MR6 else genLoopBlk( q, (Junction *)q->p1, NULL, max_k ); */
+/* MR6 */
+ if ( begin!=NULL )
+ {
+ if ( DemandLookahead )
+ {
+ if ( !GenCC ) {gen1("LOOK(%d);\n", max_k);}
+ else gen1("look(%d);\n", max_k);
+ }
+ /* The bypass arc of the (...)* predicts what to do when you fail, but
+ * ONLY after having tested the loop start expression. To avoid this,
+ * we simply break out of the (...)* loop when we find something that
+ * is not in the prediction of the loop (all alts thereof).
+ */
+ gen("if ( !(");
+
+/*** TJP says: It used to use the prediction expression for the bypass arc
+ of the (...)*. HOWEVER, if a non LL^1(k) decision was found, this
+ thing would miss the ftree stored in the aLoopBegin node and generate
+ an LL^1(k) decision anyway.
+
+ *** genExpr((Junction *)begin->p2);
+ ***/
+
+ genExpr((Junction *)begin);
+ _gen(")) break;\n");
+
+ }
+
+ /* generate code for terminating loop (this is optional branch) */
+
+ f = genBlk(q, aLoopBlk, &max_k, &need_right_curly, &lastAltEmpty /* MR23 */);
+ set_free(f);
+ freeBlkFsets(q);
+
+ /* generate code for terminating loop (this is optional branch) */
+
+/* MR6 */
+/* MR6 30-May-97 Bug reported by Manuel Ornato */
+/* MR6 A definite bug involving the exit from a loop block */
+/* MR6 In 1.23 and later versions (including 1.33) Instead */
+/* MR6 exiting the block and reporting a syntax error the */
+/* MR6 code loops forever. */
+/* MR6 Looking at 1.20 which generates proper code it is not */
+/* MR6 clear which of two changes should be undone. */
+/* MR6 This is my best guess. */
+/* MR6 From earlier MR6 note we know that begin can never be */
+/* MR6 null when genLoopBlk called from genLoopBegin */
+/* MR6 */
+/* MR6 */ if ( begin==NULL) {
+/* MR6 */ /* code for exiting loop "for sure" */
+/* MR6 */ gen("/* Suppressed by MR6 */ /*** else break; ***/\n");
+/* MR6 */ };
+
+/* MR10 */if (singleAlt && guessBlock) {
+/* MR10 */ tabs--;
+/* MR6 */ gen("} else break; /* MR6 code for exiting loop \"for sure\" */\n");
+/* MR10 */ need_right_curly--;
+/* MR10 */ } else {
+/* MR6 */ gen("else break; /* MR6 code for exiting loop \"for sure\" */\n");
+/* MR10 */ };
+
+ { int i; for (i=1; i<=need_right_curly; i++) {tabs--; gen("}\n");} }
+ if ( !GenCC ) gen1("zzLOOP(zztasp%d);\n", BlkLevel-1);
+ --tabs;
+ gen("}\n");
+ q->visited = FALSE;
+ tokensRefdInBlock = savetkref;
+}
+
+/*
+ * Generate code for a loop blk of form:
+ *
+ * |---|
+ * v |
+ * --o-->o-->o-G-o-->o--
+ * | ^
+ * v |
+ * o-----------o
+ *
+ * q->end points to the last node (far right) in the blk.
+ *
+ * Note that q->end->jtype must be 'EndBlk'.
+ *
+ * Generate code roughly of the following form:
+ *
+ * do {
+ * ... code for alternatives ...
+ * } while ( First Set of aLoopBlk );
+ *
+ * OR if > 1 alternative
+ *
+ * do {
+ * ... code for alternatives ...
+ * else break;
+ * } while ( 1 );
+ */
+void
+#ifdef __USE_PROTOS
+genLoopBegin( Junction *q )
+#else
+genLoopBegin( q )
+Junction *q;
+#endif
+{
+ set f;
+ int i;
+ int max_k;
+ set savetkref;
+ savetkref = tokensRefdInBlock;
+ require(q!=NULL, "genLoopBegin: invalid node and/or rule");
+ require(q->ntype == nJunction, "genLoopBegin: not junction");
+ require(q->jtype == aLoopBegin, "genLoopBegin: not loop block");
+ require(q->p2!=NULL, "genLoopBegin: invalid Loop Graph");
+
+ OutLineInfo(output,q->line,FileStr[q->file]);
+
+ BLOCK_Preamble(q);
+ BlkLevel++;
+ BlockPreambleOption(q,q->pFirstSetSymbol); /* MR21 */
+ f = First(q, 1, aLoopBegin, &max_k);
+ /* If not simple LL(1), must specify to start at LoopBegin, not LoopBlk */
+ if ( LL_k>1 && !set_nil(q->fset[2]) )
+ genLoopBlk( q, (Junction *)q->p1, q, max_k );
+ else genLoopBlk( q, (Junction *)q->p1, NULL, max_k );
+
+ for (i=1; i<=CLL_k; i++) set_free(q->fset[i]);
+ for (i=1; i<=CLL_k; i++) set_free(((Junction *)q->p2)->fset[i]);
+ --BlkLevel;
+ BLOCK_Tail();
+ set_free(f);
+ tokensRefdInBlock = savetkref;
+/* MR21 */ if (MR_BlkErr) {
+/* MR21 */ set f, fArray[2];
+/* MR21 */ f = ComputeErrorSet(q,1,0 /* use plus block bypass ? */ );
+/* MR21 */ fArray[0]= empty;
+/* MR21 */ fArray[1]= set_dup(f);
+/* MR21 */ gen("if (");
+/* MR21 */ genExprSets(fArray,1); /* note: destroys set arguments */
+/* MR21 */ _gen(") { /* MR21 option -mrblksynerr */\n");
+/* MR21 */ tabs++;
+/* MR21 */ tab();
+/* MR21 */ _gen("/* nothing */ }\n");
+/* MR21 */ tab();
+/* MR21 */ makeErrorClause(q,f,1,0 /* use plus block bypass ? */ ); /* frees set */
+/* MR21 */ tabs--;
+/* MR21 */ };
+ if (q->end->p1 != NULL) TRANS(q->end->p1);
+}
+
+/*
+ * Generate code for a loop blk of form:
+ *
+ * |---|
+ * v |
+ * --o-G-o-->o--
+ *
+ * q->end points to the last node (far right) in the blk.
+ * Note that q->end->jtype must be 'EndBlk'.
+ *
+ * Generate code roughly of the following form:
+ *
+ * do {
+ * ... code for alternatives ...
+ * } while ( First Set of aPlusBlk );
+ *
+ * OR if > 1 alternative
+ *
+ * do {
+ * ... code for alternatives ...
+ * else if not 1st time through, break;
+ * } while ( 1 );
+ */
+void
+#ifdef __USE_PROTOS
+genPlusBlk( Junction *q )
+#else
+genPlusBlk( q )
+Junction *q;
+#endif
+{
+ int max_k;
+ set f;
+ int need_right_curly;
+ int lastAltEmpty; /* MR23 */
+ set savetkref;
+ Junction *guessBlock; /* MR10 */
+ int singleAlt; /* MR10 */
+
+ savetkref = tokensRefdInBlock;
+ require(q!=NULL, "genPlusBlk: invalid node and/or rule");
+ require(q->ntype == nJunction, "genPlusBlk: not junction");
+ require(q->jtype == aPlusBlk, "genPlusBlk: not Plus block");
+ require(q->p2 != NULL, "genPlusBlk: not a valid Plus block");
+
+ if ( q->visited ) return;
+ q->visited = TRUE;
+ OutLineInfo(output,q->line,FileStr[q->file]);
+ BLOCK_Preamble(q);
+ BlkLevel++;
+
+ BlockPreambleOption((Junction *)q, q->pFirstSetSymbol); /* MR21 */
+
+ /* first_item_is_guess_block doesn't care what kind of node it is */
+
+ guessBlock=first_item_is_guess_block( (Junction *)q->p1); /* MR10 */
+
+ /* if the ignore flag is set on the 2nd alt and that alt is empty,
+ * then it is the implied optional alternative that we added for (...)+
+ * and, hence, only 1 alt.
+ */
+
+/* MR10 Reported by Pulkkinen Esa (esap@cs.tut.fi)
+ * Outer code for guess blocks ignored when there is only one alt
+ * for a (...)+ block.
+ * Force use of regular code rather than "optimized" code for that case
+ */
+
+ singleAlt=( ( (Junction *) q->p2)->p2 == NULL) &&
+ ( ( (Junction *) q->p2)->ignore ); /* only one alternative? */
+
+ if (singleAlt && !guessBlock) /* MR10 */
+ {
+
+ Predicate *a=NULL;
+ /* if the only alt has a semantic predicate, hoist it; must test before
+ * entering loop.
+ */
+ if ( ParseWithPredicates )
+ {
+ require(MR_PredRuleRefStack.count == 0,"PredRuleRef stack not empty");
+ a = MR_find_predicates_and_supp((Node *)q);
+ require(MR_PredRuleRefStack.count == 0,"PredRuleRef stack not empty");
+
+ if ( a!=NULL ) {
+ gen("if (");
+ a=genPredTreeMain(a, (Node *)q); /* MR10 */
+ _gen(") {\n");
+ }
+ }
+ gen("do {\n");
+ tabs++;
+ TRANS(q->p1);
+ if ( !GenCC ) gen1("zzLOOP(zztasp%d);\n", BlkLevel-1);
+ f = First(q, 1, aPlusBlk, &max_k);
+ if ( DemandLookahead ) {
+ if ( !GenCC ) {gen1("LOOK(%d);\n", max_k);}
+ else gen1("look(%d);\n", max_k);
+ }
+ --tabs;
+ gen("} while ( ");
+ if ( q->parm!=NULL && q->predparm ) _gen1("(%s) && ", q->parm);
+ genExpr(q);
+ if ( ParseWithPredicates && a!=NULL )
+ {
+ if (! MR_comparePredicates(q->predicate,a)) {
+ _gen("&&");
+ a=genPredTreeMain(a, (Node *)q); /* MR10 */
+ };
+ }
+ _gen(" );\n");
+ if ( ParseWithPredicates && a!=NULL ) gen("}\n");
+ --BlkLevel;
+ BLOCK_Tail();
+ q->visited = FALSE;
+ freeBlkFsets(q);
+ set_free(f);
+ tokensRefdInBlock = savetkref;
+/* MR21 */ if (MR_BlkErr) {
+/* MR21 */ set f, fArray[2];
+/* MR21 */ f = ComputeErrorSet(q,1,1 /* use plus block bypass ? */ );
+/* MR21 */ fArray[0]= empty;
+/* MR21 */ fArray[1]= set_dup(f);
+/* MR21 */ gen("if (");
+/* MR21 */ genExprSets(fArray,1); /* note: destroys set arguments */
+/* MR21 */ _gen(") { /* MR21 option -mrblksynerr */\n");
+/* MR21 */ tabs++;
+/* MR21 */ tab();
+/* MR21 */ _gen("/* nothing */ }\n");
+/* MR21 */ tab();
+/* MR21 */ makeErrorClause(q,f,1,1 /* use plus block bypass ? */ ); /* frees set */
+/* MR21 */ tabs--;
+/* MR21 */ };
+ if (q->end->p1 != NULL) TRANS(q->end->p1);
+/* MR10 */ if (MRhoisting) {
+/* MR10 */ predicate_free(a);
+/* MR10 */ };
+ return;
+ }
+ gen("do {\n");
+ tabs++;
+ f = genBlk(q, aPlusBlk, &max_k, &need_right_curly, &lastAltEmpty /* MR23 */);
+/* MR6 */
+/* MR6 Sinan Karasu (sinan@tardis.ds.boeing.com) */
+/* MR6 Failed to turn off guess mode when leaving block */
+/* MR6 */
+/* MR6 */ if ( has_guess_block_as_last_item(q) ) {
+/* MR10 */ gen("/* MR10 ()+ */ else {\n");
+/* MR10 */ tabs++;
+/* MR10 */ need_right_curly++;
+/* MR10 */ gen("/* MR10 ()+ */ if ( !zzrv ) zzGUESS_DONE;\n");
+/* MR6 */ gen("/* MR10 ()+ */ if ( zzcnt > 1 ) break;\n");
+/* MR10 */ } else {
+/* MR10 */ gen("/* MR10 ()+ */ else {\n");
+/* MR10 */ tabs++;
+/* MR10 */ need_right_curly++;
+/* MR10 */ gen("if ( zzcnt > 1 ) break;\n");
+/* MR10 */ };
+
+/* MR21 */ if (MR_BlkErr && 1 >= max_k) {
+/* MR21 */ set f;
+/* MR21 */ f = ComputeErrorSet(q,1,0 /* use plus block bypass ? */ );
+/* MR21 */ tabs++;
+/* MR21 */ tab();
+/* MR21 */ makeErrorClause(q,f,1,0 /* use plus block bypass ? */ ); /* frees set */
+/* MR21 */ tabs--;
+/* MR21 */ }
+/* MR21 */ else {
+ tab();
+ makeErrorClause(q,f,max_k,1 /* use plus block bypass ? */);
+ /* MR21 I think this generates the wrong set ? */
+ /* MR21 because it includes the plus block bypass ? */
+ /* MR21 but I'm afraid to change it without additional checking */
+ }
+
+ { int i; for (i=1; i<=need_right_curly; i++) {tabs--; gen("}\n");} }
+ freeBlkFsets(q);
+ gen("zzcnt++;");
+ if ( !GenCC ) _gen1(" zzLOOP(zztasp%d);", BlkLevel-1);
+ _gen("\n");
+ if ( DemandLookahead ) {
+ if ( !GenCC ) {gen1("LOOK(%d);\n", max_k);}
+ else gen1("look(%d);\n", max_k);
+ }
+ --tabs;
+ if ( q->parm!=NULL && q->predparm ) {gen1("} while (%s);\n", q->parm);}
+ else gen("} while ( 1 );\n");
+ --BlkLevel;
+ BLOCK_Tail();
+ q->visited = FALSE;
+ tokensRefdInBlock = savetkref;
+/* MR21 */ if (MR_BlkErr) {
+/* MR21 */ set f, fArray[2];
+/* MR21 */ f = ComputeErrorSet(q,1,1 /* use plus block bypass ? */ );
+/* MR21 */ fArray[0]= empty;
+/* MR21 */ fArray[1]= set_dup(f);
+/* MR21 */ gen("if (");
+/* MR21 */ genExprSets(fArray,1); /* note: destroys set arguments */
+/* MR21 */ _gen(") { /* MR21 option -mrblksynerr */\n");
+/* MR21 */ tabs++;
+/* MR21 */ tab();
+/* MR21 */ _gen("/* nothing */ }\n");
+/* MR21 */ tab();
+/* MR21 */ makeErrorClause(q,f,1,1 /* use plus block bypass ? */ ); /* frees set */
+/* MR21 */ tabs--;
+/* MR21 */ };
+ if (q->end->p1 != NULL) TRANS(q->end->p1);
+}
+
+/*
+ * Generate code for a sub blk of alternatives of form:
+ *
+ * --o-G1--o--
+ * | ^
+ * v /|
+ * o-G2-o|
+ * | ^
+ * v |
+ * ..........
+ * | ^
+ * v /
+ * o-Gn-o
+ *
+ * q points to the 1st junction of blk (upper-left).
+ * q->end points to the last node (far right) in the blk.
+ * Note that q->end->jtype must be 'EndBlk'.
+ * The last node in every alt points to q->end.
+ *
+ * Generate code of the following form:
+ * if ( First(G1) ) {
+ * ...code for G1...
+ * }
+ * else if ( First(G2) ) {
+ * ...code for G2...
+ * }
+ * ...
+ * else {
+ * ...code for Gn...
+ * }
+ */
+
+void
+#ifdef __USE_PROTOS
+genSubBlk( Junction *q )
+#else
+genSubBlk( q )
+Junction *q;
+#endif
+{
+ int max_k;
+ set f;
+ int need_right_curly;
+ int lastAltEmpty; /* MR23 */
+ set savetkref;
+ savetkref = tokensRefdInBlock;
+ require(q->ntype == nJunction, "genSubBlk: not junction");
+ require(q->jtype == aSubBlk, "genSubBlk: not subblock");
+
+ OutLineInfo(output,q->line,FileStr[q->file]);
+ BLOCK_Preamble(q);
+ BlkLevel++;
+ BlockPreambleOption(q,q->pFirstSetSymbol); /* MR21 */
+ f = genBlk(q, aSubBlk, &max_k, &need_right_curly, &lastAltEmpty /* MR23 */);
+
+/* MR23
+ Bypass error clause generation when exceptions are used in a sub block
+ in which the last alternative is epsilon. Example: "(A | B | )".
+ See multi-line note in genBlk near call to isEmptyAlt.
+*/
+ if (FoundException && lastAltEmpty) {
+ gen("/* MR23 skip error clause for (...| epsilon) when exceptions in use */\n");
+ }
+ else {
+ if ( q->p2 != NULL ) {tab(); makeErrorClause(q,f,max_k,0 /* use plus block bypass ? */ );}
+ }
+
+ { int i; for (i=1; i<=need_right_curly; i++) {tabs--; gen("}\n");} }
+ freeBlkFsets(q);
+ --BlkLevel;
+ BLOCK_Tail();
+
+ if ( q->guess )
+ {
+ gen("zzGUESS_DONE\n");
+ }
+
+ /* must duplicate if (alpha)?; one guesses (validates), the
+ * second pass matches */
+ if ( q->guess && analysis_point(q)==q )
+ {
+ OutLineInfo(output,q->line,FileStr[q->file]);
+ BLOCK_Preamble(q);
+ BlkLevel++;
+ f = genBlk(q, aSubBlk, &max_k, &need_right_curly, &lastAltEmpty /* MR23 */);
+ if ( q->p2 != NULL ) {tab(); makeErrorClause(q,f,max_k,0 /* use plus block bypass ? */);}
+ { int i; for (i=1; i<=need_right_curly; i++) {tabs--; gen("}\n");} }
+ freeBlkFsets(q);
+ --BlkLevel;
+ BLOCK_Tail();
+ }
+
+ tokensRefdInBlock = savetkref;
+ if (q->end->p1 != NULL) TRANS(q->end->p1);
+}
+
+static int TnodesAllocatedPrevRule=0;
+
+/*
+ * Generate code for a rule.
+ *
+ * rule--> o-->o-Alternatives-o-->o
+ * Or,
+ * rule--> o-->o-Alternative-o-->o
+ *
+ * The 1st junction is a RuleBlk. The second can be a SubBlk or just a junction
+ * (one alternative--no block), the last is EndRule.
+ * The second to last is EndBlk if more than one alternative exists in the rule.
+ *
+ * To get to the init-action for a rule, we must bypass the RuleBlk,
+ * and possible SubBlk.
+ * Mark any init-action as generated so genBlk() does not regenerate it.
+ */
+void
+#ifdef __USE_PROTOS
+genRule( Junction *q )
+#else
+genRule( q )
+Junction *q;
+#endif
+{
+
+ const char * returnValueInitializer;
+
+do { /* MR10 Change recursion into iteration */
+
+ int max_k;
+ set follow, rk, f;
+ ActionNode *a;
+ RuleEntry *r;
+ int lastAltEmpty; /* MR23 */
+ static int file = -1;
+ int need_right_curly;
+ require(q->ntype == nJunction, "genRule: not junction");
+ require(q->jtype == RuleBlk, "genRule: not rule");
+
+/* MR14 */ require (MR_BackTraceStack.count == 0,"-alpha MR_BackTraceStack.count != 0");
+/* MR14 */ MR_pointerStackReset(&MR_BackTraceStack);
+/* MR14 */ if (AlphaBetaTrace) MR_MaintainBackTrace=1;
+
+ CurRule=q->rname; /* MR11 */
+
+ r = (RuleEntry *) hash_get(Rname, q->rname);
+ if ( r == NULL ) warnNoFL("Rule hash table is screwed up beyond belief");
+ if ( q->file != file ) /* open new output file if need to */
+ {
+/* MR6 */
+/* MR6 Simpler to debug when output goes to stdout rather than a file */
+/* MR6 */
+/* MR6 */ if (UseStdout) {
+/* MR6 */ output = stdout;
+/* MR6 */ } else {
+/* MR6 */ if ( output != NULL) fclose( output );
+/* MR6 */ output = fopen(OutMetaName(outname(FileStr[q->file])), "w");
+/* MR6 */ };
+ require(output != NULL, "genRule: can't open output file");
+
+#ifdef SPECIAL_FOPEN
+ special_fopen_actions(OutMetaName(outname(FileStr[q->file]))); /* MR1 */
+#endif
+ if ( file == -1 ) genHdr1(q->file);
+ else genHdr(q->file);
+ file = q->file;
+ }
+
+ if (InfoM) {
+ fprintf(stderr," rule %s\n",q->rname);
+ fflush(output);
+ };
+
+#if 0
+ if (strcmp(q->rname,"***debug***") == 0) {
+ fprintf(stderr,"***debug*** %s reached\n",q->rname);
+ MR_break();
+ };
+#endif
+
+ DumpFuncHeader(q,r);
+ tabs++;
+
+ /* MR23
+
+ If there is a single return value then it can be initialized in
+ the declaration using assignment syntax. If there are multiple
+ return values then antlr creates a struct and initialization takes
+ place element by element for each element of the struct. For
+ multiple elements the initialization is by assignment so we have
+ to wait until all declarations are done before emitting that code -
+ because of restrictions in C which don't exist in C++.
+
+ In the past (before MR23) the only kind of initialization was
+ the PURIFY macro which was just a memset() of 0. Now we allow
+ the user to specify an initial value. PURIFY is still used in C
+ mode because C does not have constructors. However, PURIFY is
+ not used in C++ mode because it might overwrite information created
+ by elements which have their own ctor.
+
+ */
+
+ if ( q->ret!=NULL )
+ {
+ if ( hasMultipleOperands(q->ret) ) /* MR23 */
+ {
+
+ /* Emit initialization code later. */
+
+ gen1("struct _rv%d _retv;\n",r->rulenum);
+ }
+ else
+ {
+ /* Emit initialization code now. */
+
+ tab();
+ DumpType(q->ret, output);
+ returnValueInitializer = getInitializer(q->ret);
+ if (returnValueInitializer == NULL) { /* MR23 */
+ gen(" _retv;\n"); /* MR1 MR3 */
+ } /* MR23 */
+ else { /* MR23 */
+ gen1(" _retv = %s;\n", returnValueInitializer); /* MR23 */
+ } /* MR23 */
+ }
+ }
+
+ OutLineInfo(output,q->line,FileStr[q->file]);
+
+ if (InfoM) {
+ fflush(output);
+ };
+
+ gen("zzRULE;\n");
+ if ( FoundException )
+ {
+ gen("int _sva=1;\n");
+ }
+ if ( GenCC && GenAST )
+ gen("ASTBase *_ast = NULL, *_sibling = NULL, *_tail = NULL;\n");
+ if ( GenCC ) genTokenPointers(q);
+ if ( GenCC&&GenAST ) genASTPointers(q);
+ if ( q->el_labels!=NULL ) genElementLabels(q->el_labels);
+ if ( FoundException ) gen("int _signal=NoSignal;\n");
+
+ if ( !GenCC ) gen1("zzBLOCK(zztasp%d);\n", BlkLevel);
+
+/* MR10 */ /* move zzTRACEIN to before init action */
+
+/* MR10 */ if ( TraceGen ) {
+/* MR10 */ if ( GenCC ) {gen1("zzTRACEIN(\"%s\");\n", q->rname);}
+/* MR10 */ else gen1("zzTRACEIN((ANTLRChar *)\"%s\");\n", q->rname);
+/* MR10 */ }
+
+/* MR7 Moved PURIFY() to after all local variables have been declared */
+/* MR7 so that the generated code is valid C as well as C++ */
+/* MR7 Jan Mikkelsen 10-June-1997 */
+
+
+ /*
+ MR23 Do the PURIFY macro only for C mode.
+ C++ users should use constructors or initialization expressions.
+ */
+
+ if ( q->ret != NULL ) /* MR7 */
+ { /* MR7 */
+ if (hasMultipleOperands(q->ret)) { /* MR23 */
+ if (PURIFY == TRUE) {
+ gen1("PCCTS_PURIFY(_retv,sizeof(struct _rv%d))\n",r->rulenum); /* MR23 */
+ }
+ } /* MR7 */
+ else { /* MR7 */
+
+ /* MR23
+ If there were only one return value operand and
+ it had an initializer then it would have been
+ initiailized in the declaration.
+ */
+
+ returnValueInitializer = getInitializer(q->ret); /* MR23 */
+ if (returnValueInitializer == NULL) { /* MR23 */
+ if (PURIFY == TRUE) {
+ gen("PCCTS_PURIFY(_retv,sizeof("); /* MR23 */
+ DumpType(q->ret, output); /* MR7 */
+ gen("))\n"); /* MR7 */
+ }
+ } /* MR23 */
+ } /* MR7 */
+
+ if (hasMultipleOperands(q->ret)) { /* MR23 */
+ DumpInitializers(output, r, q->ret); /* MR23 */
+ }
+
+ }
+ if ( !GenCC ) gen("zzMake0;\n");
+ if ( FoundException ) gen("*_retsignal = NoSignal;\n");
+
+ if ( !GenCC ) gen("{\n");
+
+ if ( has_guess_block_as_first_item((Junction *)q->p1) )
+ {
+ gen("zzGUESS_BLOCK\n");
+ }
+
+ /* L o o k F o r I n i t A c t i o n */
+ if ( ((Junction *)q->p1)->jtype == aSubBlk )
+ a = findImmedAction( ((Junction *)q->p1)->p1 );
+ else
+ a = findImmedAction( q->p1 ); /* only one alternative in rule */
+ if ( a!=NULL && !a->is_predicate)
+ {
+ /* MR21 */ if (!a->noHoist) dumpActionPlus(a, a->action, output, tabs, a->file, a->line, 1);
+ a->done = 1; /* ignore action. We have already handled it */
+ }
+
+ BlkLevel++;
+ q->visited = TRUE; /* mark RULE as visited for FIRST/FOLLOW */
+ BlockPreambleOption((Junction *)q->p1, NULL); /* MR21 */
+ f = genBlk((Junction *)q->p1, RuleBlk, &max_k, &need_right_curly, &lastAltEmpty /* MR23 */);
+ if ( q->p1 != NULL )
+ if ( ((Junction *)q->p1)->p2 != NULL )
+ {tab(); makeErrorClause((Junction *)q->p1,f,max_k,0 /* use plus block bypass ? */);}
+ { int i; for (i=1; i<=need_right_curly; i++) {tabs--; gen("}\n");} }
+ freeBlkFsets((Junction *)q->p1);
+ q->visited = FALSE;
+ --BlkLevel;
+ if ( !GenCC ) gen1("zzEXIT(zztasp%d);\n", BlkLevel);
+
+ genTraceOut(q);
+
+ if ( q->ret!=NULL ) gen("return _retv;\n") else gen("return;\n");
+ /* E r r o r R e c o v e r y */
+ NewSet();
+ rk = empty;
+
+/* MR14 */ if (r->dontComputeErrorSet) {
+/* MR14 */ follow=empty;
+ } else {
+ MR_pointerStackReset(&MR_BackTraceStack); /* MR14 */
+ MR_ErrorSetComputationActive=1;
+ REACH(q->end, 1, &rk, follow);
+ MR_ErrorSetComputationActive=0;
+ require (MR_BackTraceStack.count == 0,"K: MR_BackTraceStack.count != 0");
+ }
+
+ FillSet( follow );
+ set_free( follow );
+
+ /* MR20 G. Hobbelt
+ Isn't it so that "fail:" is ONLY referenced when:
+
+ !FoundException || FoundGuessBlk ?
+
+ Therefore add the "if" around this piece of code generation...
+
+ Should guessing mode also use _handler label instead of "fail"
+ when exception handling is active? gen can automatically put
+ "if (guessing)" there so as to skip all kinds of user code.
+
+ */
+
+ if ( !FoundException || FoundGuessBlk ) /* MR20 G. Hobbelt */
+ { /* MR20 G. Hobbelt */
+ _gen("fail:\n");
+ if ( !GenCC ) gen("zzEXIT(zztasp1);\n");
+ if ( FoundGuessBlk ) {
+ if ( !GenCC ) {gen("if ( zzguessing ) zzGUESS_FAIL;\n");}
+ else gen("if ( guessing ) zzGUESS_FAIL;\n");
+ }
+ if ( q->erraction!=NULL )
+ dumpAction(q->erraction, output, tabs, q->file, q->line, 1);
+ if ( GenCC )
+ {
+ gen1("syn(zzBadTok, %s, zzMissSet, zzMissTok, zzErrk);\n",
+ r->egroup==NULL?"(ANTLRChar *)\"\"":r->egroup);
+ }
+ else
+ {
+ gen1("zzsyn(zzMissText, zzBadTok, %s, zzMissSet, zzMissTok, zzErrk, zzBadText);\n",
+ r->egroup==NULL?"(ANTLRChar *)\"\"":r->egroup);
+ }
+ gen3("%sresynch(setwd%d, 0x%x);\n", GenCC?"":"zz", wordnum, 1<<setnum);
+
+ if ( q->ret!=NULL ) {
+ genTraceOut(q);
+ gen("return _retv;\n");
+ } else if ( q->exceptions!=NULL ) {
+ genTraceOut(q);
+ gen("return;\n");
+ } else if (!FoundException) { /* MR10 */
+ genTraceOut(q); /* MR10 */
+ };
+
+ } /* MR20 G. Hobbelt */
+
+ if ( !GenCC ) gen("}\n");
+
+ /* Gen code for exception handlers */
+ /* make sure each path out contains genTraceOut() */
+
+ if ( q->exceptions!=NULL )
+ {
+
+ gen("/* exception handlers */\n");
+
+ dumpExceptions(q->exceptions);
+
+ if ( !r->has_rule_exception )
+ {
+ _gen("_handler:\n");
+ gen("zzdflthandlers(_signal,_retsignal);\n");
+ }
+/* MR20 G. Gobbelt The label "adios" is never referenced */
+
+#if 0
+ _gen("_adios:\n");
+#endif
+ if ( q->ret!=NULL ) {
+ genTraceOut(q);
+ gen("return _retv;\n");
+ }
+ else {
+ genTraceOut(q);
+ gen("return;\n");
+ }
+ }
+ else if ( FoundException )
+ {
+ _gen("_handler:\n");
+ gen("zzdflthandlers(_signal,_retsignal);\n");
+
+/* MR1 */
+/* MR1 7-Apr-97 Fix suggested by: John Bair (jbair@iftime.com) */
+/* MR1 */
+
+ if ( q->ret != NULL) { /* MR1 */
+ genTraceOut(q); /* MR10 */
+ gen("return _retv;\n"); /* MR1 */
+ } else { /* MR1 */
+ genTraceOut(q); /* MR10 */
+ gen("return;\n") ; /* MR1 */
+ }; /* MR1 */
+ }
+
+ tabs--;
+ gen("}\n");
+
+/* MR10 Tired of looking at stacks that are as deep as the number of */
+/* MR10 rules. Changes recursion to iteration. */
+
+ MR_releaseResourcesUsedInRule( (Node *) q ); /* MR10 */
+
+ if (InfoT) {
+ fprintf(output,"\n/* tnodes created for rule %s: %d */\n",
+ q->rname, (TnodesAllocated-TnodesAllocatedPrevRule) );
+ };
+
+ TnodesAllocatedPrevRule=TnodesAllocated;
+
+ if (q->p2 == NULL) dumpAfterActions( output );
+ q=(Junction *)q->p2;
+ require(q==NULL || q->jtype==RuleBlk,"RuleBlk p2 does not point to another RuleBlk");
+
+} while (q != NULL);
+
+/**** The old code ****/
+/**** if ( q->p2 != NULL ) {TRANS(q->p2);} ****/ /* generate code for next rule too */
+/**** else dumpAfterActions( output ); ****/
+
+}
+
+
+/* This is for the function definition, not the declaration. */
+
+static void
+#ifdef __USE_PROTOS
+DumpFuncHeader( Junction *q, RuleEntry *r )
+#else
+DumpFuncHeader( q, r )
+Junction *q;
+RuleEntry *r;
+#endif
+{
+/* */
+/* MR1 10-Apr-97 MR1 Simplify insertion of commas in function header */
+/* */
+ int needComma; /* MR1 */
+
+
+ /* A N S I */
+ _gen("\n");
+ if ( q->ret!=NULL )
+ {
+ if ( hasMultipleOperands(q->ret) ) /* MR23 */
+ {
+ if (GenCC) gen2("%s::_rv%d\n", CurrentClassName, r->rulenum)
+ else gen1("struct _rv%d\n",r->rulenum);
+ }
+ else
+ {
+ DumpType(q->ret, output);
+ gen("\n");
+ }
+ }
+ else
+ {
+ _gen("void\n");
+ }
+/* MR1 */
+/* MR1 10-Apr-97 133MR1 Replace __STDC__ with __USE_PROTOS */
+/* MR1 */
+ if ( !GenCC ) _gen("#ifdef __USE_PROTOS\n"); /* MR1 */
+ if ( !GenCC ) gen2("%s%s(", RulePrefix, q->rname)
+ else gen3("%s::%s%s(", CurrentClassName, RulePrefix,q->rname);
+
+ /* If we generate C++ method names, we must hide default arguments */
+ /* which can appear in the parameter declaration list. */
+ /* NOTICE: this is done only here, for the method definition, but */
+ /* not for the method declaration inside the class */
+ /* definition. This is exactly the behaviour defined in */
+ /* C++ standard for default paramters. */
+
+ DumpANSIFunctionArgDef(output,q, 0 /* emit initializers ? */);
+ _gen("\n");
+
+ if ( GenCC ) {
+ gen("{\n");
+ return;
+ }
+
+ /* K & R */
+ gen("#else\n");
+ gen2("%s%s(", RulePrefix, q->rname);
+ needComma=0; /* MR1 */
+ if ( GenAST ) /* MR1 */
+ { /* MR1 */
+ _gen("_root"); /* MR1 */
+ needComma=1; /* MR1 */
+ } /* MR1 */
+ if ( FoundException ) /* MR1 */
+ { /* MR1 */
+ if (needComma) {_gen(",");needComma=0;}; /* MR1 */
+ _gen("_retsignal"); /* MR1 */
+ needComma=1; /* MR1 */
+ } /* MR1 */
+/* MR5 Change below by Jan Mikkelsen (janm@zeta.org.au) 26-May-97 MR5 */
+ DumpListOfParmNames( q->pdecl, output, needComma ); /* MR5 */
+ gen(")\n");
+ if ( GenAST ) gen("AST **_root;\n");
+ if ( FoundException ) gen("int *_retsignal;\n");
+ DumpOldStyleParms( q->pdecl, output );
+ gen("#endif\n");
+ gen("{\n");
+}
+
+void
+#ifdef __USE_PROTOS
+DumpANSIFunctionArgDef(FILE *f, Junction *q, int bInitializer)
+#else
+DumpANSIFunctionArgDef(f,q,bInitializer)
+FILE *f;
+Junction *q;
+int bInitializer;
+#endif
+{
+ if ( GenAST )
+ {
+ if ( GenCC ) {fprintf(f,"ASTBase **_root");}
+ else fprintf(f,"AST**_root");
+ if ( !FoundException && q->pdecl!=NULL ) fprintf(f,",");
+ }
+ if ( FoundException )
+ {
+ if ( GenAST ) fprintf(f,",");
+ fprintf(f,"int *_retsignal");
+ if ( q->pdecl!=NULL ) {
+ fprintf(f,",");
+ }
+ }
+ if ( q->pdecl!=NULL ) {
+ DumpFormals(f, q->pdecl, bInitializer); /* MR23 */
+ }
+ else {
+ if ( !GenAST && !FoundException ) {
+ fprintf(f,"void");
+ }
+ }
+ fprintf(f,")");
+}
+
+void
+#ifdef __USE_PROTOS
+genJunction( Junction *q )
+#else
+genJunction( q )
+Junction *q;
+#endif
+{
+ require(q->ntype == nJunction, "genJunction: not junction");
+ require(q->jtype == Generic, "genJunction: not generic junction");
+
+ if ( q->p1 != NULL ) TRANS(q->p1);
+ if ( q->p2 != NULL ) TRANS(q->p2);
+}
+
+void
+#ifdef __USE_PROTOS
+genEndBlk( Junction *q )
+#else
+genEndBlk( q )
+Junction *q;
+#endif
+{
+}
+
+void
+#ifdef __USE_PROTOS
+genEndRule( Junction *q )
+#else
+genEndRule( q )
+Junction *q;
+#endif
+{
+}
+
+void
+#ifdef __USE_PROTOS
+genHdr( int file )
+#else
+genHdr( file )
+int file;
+#endif
+{
+ int i;
+
+ _gen("/*\n");
+ _gen(" * A n t l r T r a n s l a t i o n H e a d e r\n");
+ _gen(" *\n");
+ _gen(" * Terence Parr, Will Cohen, and Hank Dietz: 1989-2001\n");
+ _gen(" * Purdue University Electrical Engineering\n");
+ _gen(" * With AHPCRC, University of Minnesota\n");
+ _gen1(" * ANTLR Version %s\n", Version);
+ _gen(" *\n");
+/* MR10 */ _gen(" * ");
+/* MR10 */ for (i=0 ; i < Save_argc ; i++) {
+/* MR10 */ _gen(" ");
+/* MR10 */ _gen(Save_argv[i]);
+/* MR10 */ };
+ _gen("\n");
+ _gen(" *\n");
+ _gen(" */\n\n");
+ if (FirstAction != NULL ) dumpAction( FirstAction, output, 0, -1, 0, 1); /* MR11 MR15b */
+ _gen1("#define ANTLR_VERSION %s\n", VersionDef);
+ _gen("#include \"pcctscfg.h\"\n");
+ _gen("#include \"pccts_stdio.h\"\n");
+ if ( strcmp(ParserName, DefaultParserName)!=0 )
+ _gen2("#define %s %s\n", DefaultParserName, ParserName);
+ if ( strcmp(ParserName, DefaultParserName)!=0 )
+ {_gen1("#include \"%s\"\n", RemapFileName);}
+ OutLineInfo(output,1,FileStr[file]);
+ if ( GenCC ) {
+ if ( UserTokenDefsFile != NULL )
+ fprintf(output, "#include %s\n", UserTokenDefsFile);
+ else
+ fprintf(output, "#include \"%s\"\n", DefFileName);
+ }
+
+ if ( HdrAction != NULL ) dumpAction( HdrAction, output, 0, -1, 0, 1);
+ if ( !GenCC && FoundGuessBlk )
+ {
+ _gen("#define ZZCAN_GUESS\n");
+ _gen("#include \"pccts_setjmp.h\"\n"); /* MR15 K.J. Cummings (cummings@peritus.com) */
+ }
+ if ( FoundException )
+ {
+ _gen("#define EXCEPTION_HANDLING\n");
+ _gen1("#define NUM_SIGNALS %d\n", NumSignals);
+ }
+ if ( !GenCC && OutputLL_k > 1 ) _gen1("#define LL_K %d\n", OutputLL_k);
+ if ( GenAST&&!GenCC ) _gen("#define GENAST\n\n");
+ if ( GenAST ) {
+ if ( GenCC ) {_gen1("#include \"%s\"\n\n", ASTBASE_H);}
+ else _gen("#include \"ast.h\"\n\n");
+ }
+ if ( !GenCC && DemandLookahead ) _gen("#define DEMAND_LOOK\n\n");
+#ifdef DUM
+ if ( !GenCC && LexGen ) {
+ _gen1("#define zzEOF_TOKEN %d\n", (TokenInd!=NULL?TokenInd[EofToken]:EofToken));
+ }
+#endif
+ /* ###WARNING: This will have to change when SetWordSize changes */
+ if ( !GenCC ) _gen1("#define zzSET_SIZE %d\n", NumWords(TokenNum-1)*sizeof(unsigned));
+ if (TraceGen) {
+ _gen("#ifndef zzTRACE_RULES\n"); /* MR20 */
+ _gen("#define zzTRACE_RULES\n"); /* MR20 */
+ _gen("#endif\n"); /* MR22 */
+ };
+ if ( !GenCC ) {_gen("#include \"antlr.h\"\n");}
+ else {
+ _gen1("#include \"%s\"\n", APARSER_H);
+ _gen1("#include \"%s.h\"\n", CurrentClassName);
+ }
+ if ( !GenCC ) {
+ if ( UserDefdTokens )
+ {_gen1("#include %s\n", UserTokenDefsFile);}
+ /* still need this one as it has the func prototypes */
+ _gen1("#include \"%s\"\n", DefFileName);
+ }
+ /* still need this one as it defines the DLG interface */
+ if ( !GenCC ) _gen("#include \"dlgdef.h\"\n");
+ if ( LexGen && GenCC ) _gen1("#include \"%s\"\n", DLEXERBASE_H);
+ if ( GenCC ) _gen1("#include \"%s\"\n", ATOKPTR_H);
+ if ( !GenCC && LexGen ) _gen1("#include \"%s\"\n", ModeFileName);
+
+/* MR10 Ofer Ben-Ami (gremlin@cs.huji.ac.il) */
+/* MR10 Finally, a definition of the Purify macro */
+
+ if (PURIFY == TRUE) { /* MR23 */
+ _gen("\n/* MR23 In order to remove calls to PURIFY use the antlr"); /* MR23 */
+ _gen(" -nopurify option */\n\n"); /* MR23 */
+ _gen("#ifndef PCCTS_PURIFY\n");
+ _gen("#define PCCTS_PURIFY(r,s) memset((char *) &(r),'\\0',(s));\n");
+ _gen("#endif\n\n");
+ } /* MR23 */
+}
+
+void
+#ifdef __USE_PROTOS
+genHdr1( int file )
+#else
+genHdr1( file )
+int file;
+#endif
+{
+ ListNode *p;
+
+ genHdr(file);
+ if ( GenAST )
+ {
+ if ( !GenCC ) {
+ _gen("#include \"ast.c\"\n");
+ _gen("zzASTgvars\n\n");
+ }
+ }
+ if ( !GenCC ) _gen("ANTLR_INFO\n");
+ if ( BeforeActions != NULL )
+ {
+ for (p = BeforeActions->next; p!=NULL; p=p->next)
+ {
+ UserAction *ua = (UserAction *)p->elem;
+ dumpAction( ua->action, output, 0, ua->file, ua->line, 1);
+ }
+ }
+
+ if ( !FoundException ) return;
+
+ if ( GenCC )
+ {
+ _gen1("\nvoid %s::\n", CurrentClassName);
+ _gen("zzdflthandlers( int _signal, int *_retsignal )\n");
+ _gen("{\n");
+ }
+ else
+ {
+ _gen("\nvoid\n");
+/* MR1 */
+/* MR1 10-Apr-97 133MR1 Replace __STDC__ with __USE_PROTOS */
+/* MR1 */
+ _gen("#ifdef __USE_PROTOS\n"); /* MR1 */
+ _gen("zzdflthandlers( int _signal, int *_retsignal )\n");
+ _gen("#else\n");
+ _gen("zzdflthandlers( _signal, _retsignal )\n");
+ _gen("int _signal;\n");
+ _gen("int *_retsignal;\n");
+ _gen("#endif\n");
+ _gen("{\n");
+ }
+ tabs++;
+ if ( DefaultExGroup!=NULL )
+ {
+ dumpException(DefaultExGroup, 1);
+ if ( !hasDefaultException(DefaultExGroup) )
+ {
+ gen("default :\n");
+ tabs++;
+ gen("*_retsignal = _signal;\n");
+ tabs--;
+ gen("}\n");
+ }
+ }
+ else {
+ gen("*_retsignal = _signal;\n");
+ }
+
+ tabs--;
+ _gen("}\n\n");
+}
+
+void
+#ifdef __USE_PROTOS
+genStdPCCTSIncludeFile( FILE *f,char *gate ) /* MR10 */
+#else
+genStdPCCTSIncludeFile( f , gate) /* MR10 */
+FILE *f;
+char * gate; /* MR10 */
+#endif
+{
+/* MR10 Ramanathan Santhanam (ps@kumaran.com) */
+/* MR10 Same preprocessor symbol use to gate stdpccts.h */
+/* MR10 even when two grammars are in use. */
+/* MR10 Derive gate symbol from -fh filename */
+
+ if (gate == NULL) {
+ fprintf(f,"#ifndef STDPCCTS_H\n"); /* MR10 */
+ fprintf(f,"#define STDPCCTS_H\n"); /* MR10 */
+ } else {
+ fprintf(f,"#ifndef STDPCCTS_%s_H\n",gate); /* MR10 */
+ fprintf(f,"#define STDPCCTS_%s_H\n",gate); /* MR10 */
+ };
+ fprintf(f,"/*\n");
+ if (gate == NULL) {
+ fprintf(f," * %s -- P C C T S I n c l u d e\n", stdpccts);
+ } else {
+ fprintf(f," * Standard PCCTS include file with -fh %s -- P C C T S I n c l u d e\n", stdpccts);
+ }
+ fprintf(f," *\n");
+ fprintf(f," * Terence Parr, Will Cohen, and Hank Dietz: 1989-2001\n");
+ fprintf(f," * Purdue University Electrical Engineering\n");
+ fprintf(f," * With AHPCRC, University of Minnesota\n");
+ fprintf(f," * ANTLR Version %s\n", Version);
+ fprintf(f," */\n\n");
+
+ fprintf(f,"#ifndef ANTLR_VERSION\n");
+ fprintf(f,"#define ANTLR_VERSION %s\n", VersionDef);
+ fprintf(f,"#endif\n\n");
+
+ if (FirstAction != NULL ) dumpAction(FirstAction, f, 0, -1, 0, 1); /* MR11 */
+
+ fprintf(f,"#include \"pcctscfg.h\"\n");
+ fprintf(f,"#include \"pccts_stdio.h\"\n");
+ if ( GenCC )
+ {
+ if ( UserDefdTokens )
+ fprintf(f, "#include %s\n", UserTokenDefsFile);
+ else {
+ fprintf(f, "#include \"%s\"\n", DefFileName);
+ }
+
+ fprintf(f, "#include \"%s\"\n", ATOKEN_H);
+
+ if ( HdrAction != NULL ) dumpAction( HdrAction, f, 0, -1, 0, 1);
+
+ fprintf(f, "#include \"%s\"\n", ATOKENBUFFER_H);
+
+ if ( OutputLL_k > 1 ) fprintf(f,"static const unsigned LL_K=%d;\n", OutputLL_k);
+ if ( GenAST ) {
+ fprintf(f, "#include \"%s\"\n", ASTBASE_H);
+ }
+
+ if (TraceGen) {
+ fprintf(f,"#ifndef zzTRACE_RULES\n"); /* MR20 */
+ fprintf(f,"#define zzTRACE_RULES\n"); /* MR20 */
+ fprintf(f,"#endif\n"); /* MR22 */
+ };
+
+ fprintf(f,"#include \"%s\"\n", APARSER_H);
+ fprintf(f,"#include \"%s.h\"\n", CurrentClassName);
+ if ( LexGen ) fprintf(f,"#include \"%s\"\n", DLEXERBASE_H);
+ fprintf(f, "#endif\n");
+ return;
+ }
+
+ if ( strcmp(ParserName, DefaultParserName)!=0 )
+ fprintf(f, "#define %s %s\n", DefaultParserName, ParserName);
+ if ( strcmp(ParserName, DefaultParserName)!=0 )
+ fprintf(f, "#include \"%s\"\n", RemapFileName);
+ if ( UserTokenDefsFile != NULL )
+ fprintf(f, "#include %s\n", UserTokenDefsFile);
+ if ( HdrAction != NULL ) dumpAction( HdrAction, f, 0, -1, 0, 1);
+ if ( FoundGuessBlk )
+ {
+ fprintf(f,"#define ZZCAN_GUESS\n");
+ fprintf(f,"#include \"pccts_setjmp.h\"\n");
+ }
+ if (TraceGen) {
+ fprintf(f,"#ifndef zzTRACE_RULES\n"); /* MR20 */
+ fprintf(f,"#define zzTRACE_RULES\n"); /* MR20 */
+ fprintf(f,"#endif\n"); /* MR22 */
+ };
+ if ( OutputLL_k > 1 ) fprintf(f,"#define LL_K %d\n", OutputLL_k);
+ if ( GenAST ) fprintf(f,"#define GENAST\n");
+ if ( FoundException )
+ {
+/* MR1 7-Apr-97 1.33MR1 */
+/* MR1 Fix suggested by: */
+/* MR1 Francois-Xavier Fontaine (fontaine_f@istvax.ist.lu) */
+
+ fprintf(f,"#define EXCEPTION_HANDLING\n"); /* MR1 */
+ fprintf(f,"#define NUM_SIGNALS %d\n", NumSignals); /* MR1 */
+ }
+ if ( DemandLookahead ) fprintf(f,"#define DEMAND_LOOK\n");
+#ifdef DUM
+ if ( LexGen ) fprintf(f, "#define zzEOF_TOKEN %d\n", (TokenInd!=NULL?TokenInd[EofToken]:EofToken));
+#endif
+ /* ###WARNING: This will have to change when SetWordSize changes */
+ fprintf(f, "#define zzSET_SIZE %d\n", NumWords(TokenNum-1)*sizeof(unsigned));
+ if (TraceGen) {
+ fprintf(f,"#ifndef zzTRACE_RULES\n"); /* MR20 */
+ fprintf(f,"#define zzTRACE_RULES\n"); /* MR20 */
+ fprintf(f,"#endif\n"); /* MR22 */
+ };
+ fprintf(f,"#include \"antlr.h\"\n");
+ if ( GenAST ) fprintf(f,"#include \"ast.h\"\n");
+ if ( UserDefdTokens )
+ fprintf(f, "#include %s\n", UserTokenDefsFile);
+ /* still need this one as it has the func prototypes */
+ fprintf(f, "#include \"%s\"\n", DefFileName);
+ /* still need this one as it defines the DLG interface */
+ fprintf(f,"#include \"dlgdef.h\"\n");
+ /* don't need this one unless DLG is used */
+ if ( LexGen ) fprintf(f,"#include \"%s\"\n", ModeFileName);
+ fprintf(f,"#endif\n");
+}
+
+/* dump action 's' to file 'output' starting at "local" tab 'tabs'
+ Dump line information in front of action if GenLineInfo is set
+ If file == -1 then GenLineInfo is ignored.
+ The user may redefine the LineInfoFormatStr to his/her liking
+ most compilers will like the default, however.
+
+ June '93; changed so that empty lines are left alone so that
+ line information is correct for the compiler/debuggers.
+*/
+void
+#ifdef __USE_PROTOS
+dumpAction( char *s, FILE *output, int tabs, int file, int line,
+int final_newline )
+#else
+dumpAction( s, output, tabs, file, line, final_newline )
+char *s;
+FILE *output;
+int tabs;
+int file;
+int line;
+int final_newline;
+#endif
+{
+ int inDQuote, inSQuote;
+ require(s!=NULL, "dumpAction: NULL action");
+ require(output!=NULL, eMsg1("dumpAction: output FILE is NULL for %s",s));
+
+ if ( GenLineInfo && file != -1 )
+ {
+ OutLineInfo(output,line,FileStr[file]);
+ }
+ PastWhiteSpace( s );
+ /* don't print a tab if first non-white char is a # (preprocessor command) */
+ if ( *s!='#' ) {TAB;}
+ inDQuote = inSQuote = FALSE;
+ while ( *s != '\0' )
+ {
+ if ( *s == '\\' )
+ {
+ fputc( *s++, output ); /* Avoid '"' Case */
+ if ( *s == '\0' ) return;
+ if ( *s == '\'' ) fputc( *s++, output );
+ if ( *s == '\"' ) fputc( *s++, output );
+ }
+ if ( *s == '\'' )
+ {
+ if ( !inDQuote ) inSQuote = !inSQuote;
+ }
+ if ( *s == '"' )
+ {
+ if ( !inSQuote ) inDQuote = !inDQuote;
+ }
+ if ( *s == '\n' )
+ {
+ fputc('\n', output);
+ s++;
+ PastWhiteSpace( s );
+ if ( *s == '}' )
+ {
+ --tabs;
+ TAB;
+ fputc( *s++, output );
+ continue;
+ }
+ if ( *s == '\0' ) return;
+ if ( *s != '#' ) /* #define, #endif etc.. start at col 1 */
+ {
+ TAB;
+ }
+ }
+ if ( *s == '}' && !(inSQuote || inDQuote) )
+ {
+ --tabs; /* Indent one fewer */
+ }
+ if ( *s == '{' && !(inSQuote || inDQuote) )
+ {
+ tabs++; /* Indent one more */
+ }
+ fputc( *s, output );
+ s++;
+ }
+ if ( final_newline ) fputc('\n', output);
+}
+
+static void
+#ifdef __USE_PROTOS
+dumpAfterActions( FILE *output )
+#else
+dumpAfterActions( output )
+FILE *output;
+#endif
+{
+ ListNode *p;
+ require(output!=NULL, "dumpAfterActions: output file was NULL for some reason");
+ if ( AfterActions != NULL )
+ {
+ for (p = AfterActions->next; p!=NULL; p=p->next)
+ {
+ UserAction *ua = (UserAction *)p->elem;
+ dumpAction( ua->action, output, 0, ua->file, ua->line, 1);
+ }
+ }
+ fclose( output );
+}
+
+/*
+ * Find the next action in the stream of execution. Do not pass
+ * junctions with more than one path leaving them.
+ * Only pass generic junctions.
+ *
+ * Scan forward while (generic junction with p2==NULL)
+ * If we stop on an action, return ptr to the action
+ * else return NULL;
+ */
+static ActionNode *
+#ifdef __USE_PROTOS
+findImmedAction( Node *q )
+#else
+findImmedAction( q )
+Node *q;
+#endif
+{
+ Junction *j;
+ require(q!=NULL, "findImmedAction: NULL node");
+ require(q->ntype>=1 && q->ntype<=NumNodeTypes, "findImmedAction: invalid node");
+
+ while ( q->ntype == nJunction )
+ {
+ j = (Junction *)q;
+ if ( j->jtype != Generic || j->p2 != NULL ) return NULL;
+ q = j->p1;
+ if ( q == NULL ) return NULL;
+ }
+ if ( q->ntype == nAction ) return (ActionNode *)q;
+ return NULL;
+}
+
+static void
+#ifdef __USE_PROTOS
+dumpRetValAssign( char *retval, char *ret_def, RuleRefNode * ruleRef /* MR30 */)
+#else
+dumpRetValAssign( retval, ret_def, ruleRef /* MR30 */)
+char *retval;
+char *ret_def;
+RuleRefNode *ruleRefNode;
+#endif
+{
+ char *q = ret_def;
+
+ tab();
+ while ( *retval != '\0' && *q != '\0')
+ {
+ while ( isspace((*retval)) ) retval++;
+ while ( *retval!=',' && *retval!='\0' ) fputc(*retval++, output);
+ fprintf(output, " = _trv.");
+
+ DumpNextNameInDef(&q, output);
+ while ( isspace(*q) ) q++;
+ fputc(';', output); fputc(' ', output);
+ if ( *retval == ',' ) retval++;
+ }
+ if (*retval == '\0' && *q != '\0') {
+/* MR30 */ errFL("Fewer output values than output formals for rule reference",
+/* MR30 */ FileStr[ruleRef->file],ruleRef->line);
+ }
+ if (*retval != '\0' && *q == '\0') {
+/* MR30 */ errFL("More output actuals than output formals for rule reference",
+/* MR30 */ FileStr[ruleRef->file],ruleRef->line);
+ }
+}
+
+/* This function computes the set of tokens that can possibly be seen k
+ * tokens in the future from point j
+ */
+
+static set
+#ifdef __USE_PROTOS
+ComputeErrorSet( Junction *j, int k, int usePlusBlockBypass)
+#else
+ComputeErrorSet( j, k, usePlusBlockBypass )
+Junction *j;
+int k;
+int usePlusBlockBypass;
+#endif
+{
+ Junction *alt1;
+ set a, rk, f;
+ require(j->ntype==nJunction, "ComputeErrorSet: non junction passed");
+
+ f = rk = empty;
+ for (alt1=j; alt1!=NULL; alt1 = (Junction *)alt1->p2)
+ {
+ if (alt1->ignore && ! usePlusBlockBypass) continue; /* MR21 - Ignore aPlusBlk forward p2 */
+ REACH(alt1->p1, k, &rk, a);
+ require(set_nil(rk), "ComputeErrorSet: rk != nil");
+ set_free(rk);
+ set_orin(&f, a);
+ set_free(a);
+ }
+ return f;
+}
+
+static char *
+#ifdef __USE_PROTOS
+tokenFollowSet(TokNode *p)
+#else
+tokenFollowSet(p)
+TokNode *p;
+#endif
+{
+ static char buf[100];
+ set rk, a;
+ int n;
+ rk = empty;
+
+ REACH(p->next, 1, &rk, a);
+ require(set_nil(rk), "rk != nil");
+ set_free(rk);
+ n = DefErrSet( &a, 0, NULL );
+ set_free(a);
+ if ( GenCC )
+ sprintf(buf, "err%d", n);
+ else
+ sprintf(buf, "zzerr%d", n);
+ return buf;
+}
+
+static void
+#ifdef __USE_PROTOS
+makeErrorClause( Junction *q, set f, int max_k, int usePlusBlockBypass )
+#else
+makeErrorClause( q, f, max_k, usePlusBlockBypass )
+Junction *q;
+set f;
+int max_k;
+int usePlusBlockBypass;
+#endif
+{
+ char * handler_id=""; /* MR7 */
+ int nilf=0; /* MR13 */
+ RuleEntry *ruleEntry; /* MR14 */
+
+ if ( FoundException )
+ {
+ _gen("else {\n");
+ tabs++;
+ if ( FoundGuessBlk )
+ {
+ if ( GenCC ) {gen("if ( guessing ) goto fail;\n");}
+ else gen("if ( zzguessing ) goto fail;\n");
+ }
+ gen("if (_sva) _signal=NoViableAlt;\n");
+ gen("else _signal=NoSemViableAlt;\n");
+ if (q->outerEG != NULL) {
+ handler_id=q->outerEG->altID;
+#if 0
+ } else {
+ printf("q->curAltNum=%d q->exception_label=%s\n",q->curAltNum,q->exception_label);
+ gen("*** DEBUG *** outerEG==NULL\n");
+#endif
+ };
+ gen1("goto %s_handler; /* MR7 */\n",handler_id); /* MR7 */
+ tabs--;
+ gen("}\n");
+ return;
+ }
+
+ if ( max_k == 1 )
+ {
+/* MR13 */ nilf=set_nil(f);
+ if ( GenCC ) {
+ _gen1("else {FAIL(1,err%d", DefErrSet1(1,&f,1,NULL));
+ } else {
+ _gen1("else {zzFAIL(1,zzerr%d", DefErrSet1(1,&f,1,NULL));
+ };
+ set_free(f);
+ }
+ else
+ {
+ int i;
+ set_free(f);
+ if ( GenCC ) {_gen1("else {FAIL(%d", max_k);}
+ else _gen1("else {zzFAIL(%d", max_k);
+
+ ruleEntry = (RuleEntry *) hash_get(Rname,q->rname);
+
+ for (i=1; i<=max_k; i++)
+ {
+/* MR14 */ if (ruleEntry->dontComputeErrorSet) {
+/* MR14 */ f=empty;
+ } else {
+ f = ComputeErrorSet(q, i, usePlusBlockBypass /* use plus block bypass ? */ );
+ }
+
+ if ( GenCC ) {_gen1(",err%d", DefErrSet( &f, 1, NULL ));}
+ else _gen1(",zzerr%d", DefErrSet( &f, 1, NULL ));
+
+ set_free(f);
+ }
+ }
+ _gen(",&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}\n");
+/* MR13 */ if (nilf) {
+/* MR13 */ errFL("empty error set for alt - probably because of undefined rule or infinite left recursion",
+/* MR13 */ FileStr[q->file],q->line);
+/* MR13 */ gen(" /* MR13 empty error set for this alt - undef rule ? infinite left recursion ? */");
+/* MR13 */ };
+}
+
+static /* MR7 */
+#ifdef __USE_PROTOS
+char * findOuterHandlerLabel(ExceptionGroup *eg) /* MR7 */
+#else
+char * findOuterHandlerLabel(eg) /* MR7 */
+ExceptionGroup *eg; /* MR7 */
+#endif
+{
+ char *label=NULL; /* MR7 */
+ ExceptionGroup *outerEG; /* MR7 */
+
+ if (eg->forRule == 0) { /* MR7 */
+ if (eg->labelEntry != NULL) { /* MR7 */
+ outerEG=eg->labelEntry->outerEG; /* MR7 */
+ if (outerEG != NULL) { /* MR7 */
+ label=outerEG->altID; /* MR7 */
+ outerEG->used=1; /* MR7 */
+ }; /* MR7 */
+ } else if (eg->outerEG != NULL) { /* MR7 */
+ outerEG=eg->outerEG; /* MR7 */
+ label=outerEG->altID; /* MR7 */
+ outerEG->used=1; /* MR7 */
+ }; /* MR7 */
+ }; /* MR7 */
+ return (label==NULL ? "" : label); /* MR7 */
+} /* MR7 */
+
+/*** debug ***/
+#if 0
+** static /* MR7 */
+** #ifdef __USE_PROTOS
+** char * findOuterAltHandlerLabel(Junction *startJ) /* MR7 */
+** #else
+** char * findOuterAltHandlerLabel(startJ) /* MR7 */
+** Junction *startJ; /* MR7 */
+** #endif
+** { /* MR7 */
+** char *label=NULL; /* MR7 */
+** Junction *alt; /* MR7 */
+** /* MR7 */
+** for (alt=startJ; alt != NULL; alt=alt->outerAltstart) { /* MR7 */
+** label=alt->exception_label; /* MR7 */
+** if (label != NULL) break; /* MR7 */
+** }; /* MR7 */
+** return (label==NULL ? "" : label); /* MR7 */
+** } /* MR7 */
+#endif
+
+#ifdef __USE_PROTOS
+static void OutLineInfo(FILE *file,int line,char *fileName)
+#else
+static void OutLineInfo(file,line,fileName)
+ FILE * file;
+ int line;
+ char * fileName;
+#endif
+{
+ static char * prevFileName=NULL;
+ static char * prevFileNameMS=NULL;
+
+ char * p;
+ char * q;
+
+ if (! GenLineInfo) return;
+
+ if (!GenLineInfoMS) {
+ fprintf(file, LineInfoFormatStr,line,fileName);
+ } else {
+ if (fileName == prevFileName) {
+ fprintf(file, LineInfoFormatStr,line,prevFileNameMS);
+ } else {
+ if (prevFileNameMS != NULL) free (prevFileNameMS);
+ prevFileNameMS=(char *)calloc(1,strlen(fileName)+1);
+ require(prevFileNameMS != NULL,"why not do this in calloc wrapper");
+ q=prevFileNameMS;
+ for (p=fileName; *p != 0; p++) {
+ *q=*p;
+ if (*q == '\\') *q='/';
+ q++;
+ }
+ }
+ prevFileName=fileName;
+ };
+}
+
+#if 0
+
+/* MR21 */
+
+#ifdef __USE_PROTOS
+void OutFirstSetSymbol(Junction *q, char * pSymbol)
+#else
+void OutFirstSetSymbol(q, pSymbol)
+ Junction* q;
+ char * pSymbol
+#endif
+{
+
+ set f;
+ if (pSymbol == NULL) return;
+ gen1("/** #FirstSetSymbol(%s) **/\n",pSymbol);
+ f = ComputeErrorSet(q, 1, 0 /* use plus block bypass ? */);
+ DefErrSetWithSuffix (0 /* nil ok */, &f,0 /* no substitute */, pSymbol, "");
+ set_free(f);
+}
+#endif
+
+/* MR21 */
+
+#ifdef __USE_PROTOS
+void BlockPreambleOption(Junction *q, char * pSymbol)
+#else
+void BlockPreambleOption(q, pSymbol)
+ Junction* q;
+ char * pSymbol;
+#endif
+{
+ set f = empty;
+ if (pSymbol != NULL) {
+ f = ComputeErrorSet(q, 1, 0 /* use plus block bypass ? */);
+ gen1("/** #FirstSetSymbol(%s) **/\n",pSymbol);
+ DefErrSetWithSuffix (0 /* nil ok */, &f,0 /* no substitute */, pSymbol, "");
+ }
+ set_free(f);
+}
+
+/* MR21 */
+
+void
+#ifdef __USE_PROTOS
+dumpActionPlus(ActionNode *a, char *s, FILE *output, int tabs, int file, int line,
+int final_newline )
+#else
+dumpActionPlus(a, s, output, tabs, file, line, final_newline )
+ActionNode *a;
+char *s;
+FILE *output;
+int tabs;
+int file;
+int line;
+int final_newline;
+#endif
+{
+ dumpAction(s,output,tabs,file,line,final_newline);
+}
+
+
+#if 0
+** #ifdef __USE_PROTOS
+** void MR_ErrorSets(Junction *q, int max_k, int usePlusBlockBypass)
+** #else
+** void MR_ErrorSets(q, max_k, usePlusBlockBypass)
+** Junction *q;
+** int max_k;
+** int usePlusBlockBypass;
+** #endif
+** {
+** int k;
+** set setResult;
+** Junction* alt1;
+** Junction* p;
+** set rk;
+**
+** require (max_k <= CLL_k, "k > CLL_k");
+**
+**
+** for (k = 1; k <= CLL_k; k++) {set_clr(q->fset[k]); }
+**
+** for (k = 1; k <= max_k; k++) {
+** for (alt1=q; alt1 != NULL; alt1 = (Junction *)alt1->p2)
+** {
+** if (alt1->ignore && ! usePlusBlockBypass) continue;
+** p = analysis_point((Junction *)alt1->p1);
+** REACH(p, k, &rk, setResult);
+** require(set_nil(rk), "rk != nil");
+** set_orin(&q->fset[k], setResult);
+** }
+** }
+** }
+#endif
+
+
+#ifdef __USE_PROTOS
+void DumpInitializers(FILE* output, RuleEntry *r, char * pReturn)
+#else
+void DumpInitializers(output, r, pReturn)
+FILE* output;
+RuleEntry *r;
+char * pReturn;
+#endif
+{
+ char *p = pReturn;
+ char *pDataType;
+ char *pSymbol;
+ char *pEqualSign;
+ char *pValue;
+ char *pSeparator;
+ int nest = 0;
+ char *q;
+
+ require(pReturn!=NULL, "DumpInitializer: invalid string");
+
+ while (*p != 0) {
+ p = endFormal(p,
+ &pDataType,
+ &pSymbol,
+ &pEqualSign,
+ &pValue,
+ &pSeparator,
+ &nest);
+ if (nest != 0) return;
+ if (pValue != NULL) {
+ tab();
+ q = strBetween(pSymbol, pEqualSign, pSeparator);
+ fprintf(output, "_retv.%s", q);
+ q = strBetween(pValue, NULL, pSeparator);
+ fprintf(output, " = %s;\n", q);
+ }
+ }
+}
+
+#ifdef __USE_PROTOS
+void DumpFormals(FILE* output, char * pReturn, int bInitializer)
+#else
+void DumpFormals(output, pReturn, bInitializer)
+FILE* output;
+char * pReturn;
+int bInitializer;
+#endif
+{
+ char *p = pReturn;
+ char *pDataType;
+ char *pSymbol;
+ char *pEqualSign;
+ char *pValue;
+ char *pSeparator;
+ int nest = 0;
+ char *q;
+ int count = 0;
+
+ require(pReturn!=NULL, "DumpFormals: invalid string");
+
+ while (*p != 0) {
+ p = endFormal(p,
+ &pDataType,
+ &pSymbol,
+ &pEqualSign,
+ &pValue,
+ &pSeparator,
+ &nest);
+ if (nest != 0) return;
+ if (count > 0) fprintf(output,",");
+ if (pDataType != NULL && pSymbol != NULL) {
+ q = strBetween(pDataType, pSymbol, pSeparator);
+ fprintf(output, "%s", q);
+ q = strBetween(pSymbol, pEqualSign, pSeparator);
+ fprintf(output," %s",q);
+ if (pValue != NULL) {
+ q = strBetween(pValue, NULL, pSeparator);
+ if (bInitializer != 0) {
+ fprintf(output, " = %s", q);
+ }
+ }
+ }
+ count++;
+ }
+}
+
+/* MR23 Check for empty alt in a more intelligent way.
+ Previously, an empty alt for genBlk had to point directly
+ to the endBlock. This did not work once I changed {...}
+ blocks to look like (...|...| epsilon) since there were
+ intervening generics. This fixes the problem for this
+ particular case. Things like actions or empty blocks of
+ various kinds will still cause problems, but I wasnt't
+ prepared to handle pathological cases like (A|()*). It
+ does handle (A | ()), which is a recommended idiom for
+ epsilon.
+
+ Actually, this isn't quite correct since it doesn't handle
+ the case of the ignore bit in the plus block bypass, but
+ I'm too tired to figure out the correct fix, and will just
+ work around it.
+*/
+
+#ifdef __USE_PROTOS
+int isEmptyAlt(Node * alt, Node * endBlock)
+#else
+int isEmptyAlt(alt, endBlock)
+Node * alt;
+Node * endBlock;
+#endif
+{
+ Node * n = alt;
+ Junction * j;
+ while (n != endBlock) {
+ switch (n->ntype) {
+
+ case nRuleRef:
+ return 0;
+
+ case nToken:
+ return 0;
+
+ case nAction:
+ return 0;
+
+ case nJunction:
+ goto JUNCTION;
+
+ default:
+ fatal_internal("Invalid node type");
+ return 0;
+ }
+JUNCTION:
+ j = (Junction *) n;
+
+ switch (j->jtype) {
+ case Generic:
+ {
+ n = j->p1;
+ goto NEXT;
+ }
+
+ case aSubBlk:
+ {
+ n = j->p1; /* MR26 */
+ goto NEXT; /* MR26 */
+ }
+
+ case EndBlk:
+ return 0;
+
+ case EndRule:
+ return 1;
+
+ default:
+ return 0;
+ }
+NEXT: continue;
+ }
+ return 1;
+}
diff --git a/Source/Pccts/antlr/generic.h b/Source/Pccts/antlr/generic.h
new file mode 100644
index 0000000..8d736d5
--- /dev/null
+++ b/Source/Pccts/antlr/generic.h
@@ -0,0 +1,286 @@
+/*
+ * generic.h -- generic include stuff for new PCCTS ANTLR.
+ *
+ * SOFTWARE RIGHTS
+ *
+ * We reserve no LEGAL rights to the Purdue Compiler Construction Tool
+ * Set (PCCTS) -- PCCTS is in the public domain. An individual or
+ * company may do whatever they wish with source code distributed with
+ * PCCTS or the code generated by PCCTS, including the incorporation of
+ * PCCTS, or its output, into commerical software.
+ *
+ * We encourage users to develop software with PCCTS. However, we do ask
+ * that credit is given to us for developing PCCTS. By "credit",
+ * we mean that if you incorporate our source code into one of your
+ * programs (commercial product, research project, or otherwise) that you
+ * acknowledge this fact somewhere in the documentation, research report,
+ * etc... If you like PCCTS and have developed a nice tool with the
+ * output, please mention that you developed it using PCCTS. In
+ * addition, we ask that this header remain intact in our source code.
+ * As long as these guidelines are kept, we expect to continue enhancing
+ * this system and expect to make other tools available as they are
+ * completed.
+ *
+ * ANTLR 1.33
+ * Terence Parr
+ * Parr Research Corporation
+ * with Purdue University and AHPCRC, University of Minnesota
+ * 1989-2001
+ */
+
+#define StrSame 0
+
+#define DefaultParserName "zzparser"
+
+/* MR9 JVincent@novell.com Allow user to override default ZZLEXBUFSIZE */
+/* MR11 thm Raise antlr's own default ZZLEXBUFSIZE to 8k */
+/* MR22 thm Raise antlr's own default ZZLEXBUFSIZE to 32k */
+
+#ifndef ZZLEXBUFSIZE
+#define ZZLEXBUFSIZE 32000
+#endif
+
+/* Tree/FIRST/FOLLOW defines -- valid only after all grammar has been read */
+#define ALT TokenNum+1
+#define SET TokenNum+2
+#define TREE_REF TokenNum+3
+
+ /* E r r o r M a c r o s */
+
+#define fatal(err) fatalFL(err, __FILE__, __LINE__)
+#define fatal_internal(err) fatal_intern(err, __FILE__, __LINE__)
+
+
+#define eMsg1(s,a) eMsg3(s,a,NULL,NULL)
+#define eMsg2(s,a,b) eMsg3(s,a,b,NULL)
+
+ /* S a n i t y C h e c k i n g */
+
+#ifndef require
+#define require(expr, err) {if ( !(expr) ) fatal_internal(err);}
+#endif
+
+ /* L i s t N o d e s */
+
+typedef struct _ListNode {
+ void *elem; /* pointer to any kind of element */
+ struct _ListNode *next;
+ } ListNode;
+
+/* Define a Cycle node which is used to track lists of cycles for later
+ * reconciliation by ResolveFoCycles().
+ */
+typedef struct _c {
+ int croot; /* cycle root */
+ set cyclicDep; /* cyclic dependents */
+ unsigned deg; /* degree of FOLLOW set of croot */
+ } Cycle;
+
+typedef struct _e {
+ int tok; /* error class name == TokenStr[tok] */
+ ListNode *elist; /* linked list of elements in error set */
+ set eset;
+ int setdeg; /* how big is the set */
+ int lexclass; /* which lex class is it in? */
+ } ECnode;
+
+typedef struct _TCnode {
+ int tok; /* token class name */
+ ListNode *tlist; /* linked list of elements in token set */
+ set tset;
+ int lexclass; /* which lex class is it in? */
+ unsigned char dumped; /* this def has been been dumped */
+ unsigned char dumpedComplement; /* this def has been been dumped */
+ unsigned setnum; /* which set number is this guy? (if dumped) */
+ unsigned setnumComplement; /* MR23 */
+ unsigned setnumErrSet; /* MR23 which set is this #tokclass error set (if dumped) */
+ unsigned setnumErrSetComplement; /* MR23 */
+ } TCnode;
+
+typedef struct _ft {
+ char *token; /* id of token type to remap */
+ int tnum; /* move token type to which token position */
+ } ForcedToken;
+
+typedef struct _ContextGuardPredicates { /* MR13 */
+ Predicate *pred; /* MR13 */
+ } ContextGuardPredicates; /* MR13 */
+
+#define newListNode (ListNode *) calloc(1, sizeof(ListNode));
+#define newCycle (Cycle *) calloc(1, sizeof(Cycle));
+#define newECnode (ECnode *) calloc(1, sizeof(ECnode));
+#define newTCnode (TCnode *) calloc(1, sizeof(TCnode));
+
+
+ /* H a s h T a b l e E n t r i e s */
+
+typedef struct _t { /* Token name or expression */
+ char *str;
+ struct _t *next;
+ int token; /* token number */
+ unsigned char classname; /* is it a err/tok class name or token */
+ TCnode *tclass; /* ptr to token class */
+ char *action;
+ char *akaString;
+ } TermEntry;
+
+typedef struct _r { /* Rule name and ptr to start of rule */
+ char *str;
+ struct _t *next;
+ int rulenum; /* RulePtr[rulenum]== ptr to RuleBlk junction */
+ unsigned char noAST;/* gen AST construction code? (def==gen code) */
+ char *egroup; /* which error group (err reporting stuff) */
+#if 0
+ /* MR27 This appears to never be used. Delete this code later. */
+
+ ListNode *el_labels;/* list of element labels ref in all of rule */
+#endif
+ ListNode *ast_labels_in_actions; /* MR27 */
+ unsigned char has_rule_exception;
+ char dontComputeErrorSet; /* MR14 - don't compute error set
+ special for rule in alpha part of
+ (alpha)? beta block */
+ } RuleEntry;
+
+typedef struct _f { /* cache Fi/Fo set */
+ char *str; /* key == (rulename, computation, k) */
+ struct _f *next;
+ set fset; /* First/Follow of rule */
+ set rk; /* set of k's remaining to be done after ruleref */
+ int incomplete; /* only w/FOLLOW sets. Use only if complete */
+ } CacheEntry;
+
+typedef struct _LabelEntry { /* element labels */
+ char *str;
+ struct _f *next;
+ Node *elem; /* which element does it point to? */
+ ExceptionGroup *ex_group;
+ /* Is there an exception attached to label? */
+ ExceptionGroup *outerEG; /* MR7 */
+ /* next EG if ex_group doesn't catch it MR7 */
+ struct _LabelEntry *pendingLink; /* MR7 */
+ /* too lazy to use ListNode ? MR7 */
+ int curAltNum; /* MR7 */
+ } LabelEntry;
+
+typedef struct _SignalEntry {
+ char *str;
+ struct _f *next;
+ int signum; /* unique signal number */
+ } SignalEntry;
+
+typedef struct _PredEntry { /* MR11 predicate name and ptr to string */
+ char *str;
+ struct _PredEntry *next;
+ int file;
+ int line;
+ Predicate *pred;
+ char *predLiteral;
+ } PredEntry;
+
+typedef struct _PointerStack { /* MR10 */
+ int count;
+ int size;
+ void **data;
+ } PointerStack;
+
+#define newTermEntry(s) (TermEntry *) newEntry(s, sizeof(TermEntry))
+#define newRuleEntry(s) (RuleEntry *) newEntry(s, sizeof(RuleEntry))
+#define newCacheEntry(s) (CacheEntry *) newEntry(s, sizeof(CacheEntry))
+#define newLabelEntry(s) (LabelEntry *) newEntry(s, sizeof(LabelEntry))
+#define newSignalEntry(s) (SignalEntry *) newEntry(s, sizeof(SignalEntry))
+#define newPredEntry(s) (PredEntry *) newEntry(s,sizeof(PredEntry))
+
+typedef struct _UserAction {
+ char *action;
+ int file, line;
+ } UserAction;
+
+
+ /* L e x i c a l C l a s s */
+
+/* to switch lex classes, switch ExprStr and Texpr (hash table) */
+typedef struct _lc {
+ char *classnum, **exprs;
+ Entry **htable;
+ } LClass;
+
+typedef struct _exprOrder {
+ char *expr;
+ int lclass;
+ } Expr;
+
+
+typedef Graph Attrib;
+
+ /* M a x i m u m s */
+
+/* MR20 Note G. Hobbelt These values are superceded by values in hash.h */
+
+#ifndef HashTableSize
+#define HashTableSize 253
+#endif
+#ifndef StrTableSize
+#define StrTableSize 15000 /* all tokens, nonterminals, rexprs stored here */
+#endif
+#define MaxLexClasses 50 /* how many automatons */
+/* TokenStart and EofToken are ignored if #tokdefs meta-op is used */
+#define TokenStart 2 /* MUST be in 1 + EofToken */
+#define EofToken 1 /* Always predefined to be 1 */
+
+#ifndef MaxNumFiles
+#define MaxNumFiles 99
+#endif
+
+/**** MR9 JVincent@novell.com Move to pcctscfg.h */
+/**** #define MaxFileName 300 ****/ /* MR9 Move to pcctscfg.h */ /* largest file name size */
+
+#define MaxRuleName 100 /* largest rule name size */
+#define TSChunk 100 /* how much to expand TokenStr/ExprStr each time */
+#define TIChunk TSChunk /* expand TokenInd by same as TokenStr to mirror them */
+#define FoStackSize 100 /* deepest FOLLOW recursion possible */
+
+#define MaxClassDeclStuff 256 /* MR10 */
+
+#define NumPredefinedSignals 3
+
+ /* S t a n d a r d S i g n a l s */
+
+#define sigNoSignal 0
+#define sigMismatchedToken 1
+#define sigNoViableAlt 2
+#define sigNoSemViableAlt 3
+
+
+
+/* AST token types */
+#define ASTexclude 0
+#define ASTchild 1
+#define ASTroot 2
+#define ASTinclude 3 /* include subtree made by rule ref */
+
+
+#define PredictionVariable "zzpr_expr"
+#define PredictionLexClassSuffix "_zzpred"
+
+#define WildCardString "WildCard"
+
+#if 0
+ /* Removed in version 1.33MR19
+ Don't understand why this never caused problems before
+ */
+
+ /*********************************************************
+ #ifndef ANTLRm
+ #define ANTLRm(st, f, _m) zzbufsize = ZZLEXBUFSIZE;\
+ zzmode(_m); \
+ zzenterANTLR(f); \
+ st; ++zzasp; \
+ zzleaveANTLR(f);
+ #endif
+ *********************************************************/
+#endif
+
+#include "proto.h"
+#include "pcctscfg.h" /* MR14 */
+#include <string.h>
diff --git a/Source/Pccts/antlr/globals.c b/Source/Pccts/antlr/globals.c
new file mode 100644
index 0000000..59d0032
--- /dev/null
+++ b/Source/Pccts/antlr/globals.c
@@ -0,0 +1,484 @@
+/*
+ * globals.c -- File containing all variables/tables visible to all files.
+ *
+ * SOFTWARE RIGHTS
+ *
+ * We reserve no LEGAL rights to the Purdue Compiler Construction Tool
+ * Set (PCCTS) -- PCCTS is in the public domain. An individual or
+ * company may do whatever they wish with source code distributed with
+ * PCCTS or the code generated by PCCTS, including the incorporation of
+ * PCCTS, or its output, into commerical software.
+ *
+ * We encourage users to develop software with PCCTS. However, we do ask
+ * that credit is given to us for developing PCCTS. By "credit",
+ * we mean that if you incorporate our source code into one of your
+ * programs (commercial product, research project, or otherwise) that you
+ * acknowledge this fact somewhere in the documentation, research report,
+ * etc... If you like PCCTS and have developed a nice tool with the
+ * output, please mention that you developed it using PCCTS. In
+ * addition, we ask that this header remain intact in our source code.
+ * As long as these guidelines are kept, we expect to continue enhancing
+ * this system and expect to make other tools available as they are
+ * completed.
+ *
+ * ANTLR 1.33
+ * Terence Parr
+ * Parr Research Corporation
+ * with Purdue University and AHPCRC, University of Minnesota
+ * 1989-2001
+ */
+
+#include <stdio.h>
+
+#include "pcctscfg.h"
+
+#include "set.h"
+#include "syn.h"
+#include "hash.h"
+#include "generic.h"
+
+char Version[] = "1.33MR33" ; /* PCCTS version number */ /* MRXXX */
+char VersionDef[] = "13333"; /* same (except int equiv for preproc symbol) */ /* MRXXX */
+
+char LexStartSymbol[] = "START";/* Name of starting lexical class/automaton */
+char *RemapFileName = "remap.h";
+char *DlgFileName = "parser.dlg";
+char *DefFileName = "tokens.h";
+char *ErrFileName = "err.c";
+char *ModeFileName = "mode.h";
+char *StdMsgName = NULL;
+
+char *ParserName = DefaultParserName;
+
+/* list of PCCTS supplied support symbols; these are renamed when more than
+ * one ANTLR-generated parsers are linked together to avoid name conflicts.
+ * Can't use '##' ANSIC preprocessor concat operator with K&R and:
+ * #define zzskip zzparser ## skip
+ * will not work for ANSI/C++ as 'zzparserskip' is created w/o zzparser
+ * being substituted--ack!!!
+ */
+char *StandardSymbols[] = {
+/* ANTLR stuff */
+ "zzStackOvfMsg",
+ "zzasp",
+ "zzaStack",
+ "inf_tokens",
+ "inf_text",
+ "inf_text_buffer",
+ "inf_text_buffer_ptr",
+ "inf_text_buffer_size",
+ "inf_labase",
+ "inf_last",
+ "inf_lap",
+ "zztokenLA",
+ "zztextLA",
+ "zzlap",
+ "zzlabase",
+ "zztoktext",
+ "zztoken",
+ "zzdirty",
+ "zzguessing",
+ "zzguess_start",
+ "zzresynch",
+ "zzinf_tokens",
+ "zzinf_text",
+ "zzinf_text_buffer",
+ "zzinf_labase",
+ "zzinf_last",
+ "zzfill_inf_look",
+ "zzFAIL",
+ "zzsave_antlr_state",
+ "zzrestore_antlr_state",
+ "zzsyn",
+ "zzset_el",
+ "zzset_deg",
+ "zzedecode",
+ "_zzsetmatch",
+ "_zzmatch",
+ "_inf_zzgettok",
+ "zzconsumeUntil",
+ "zzconsumeUntilToken",
+ "_zzmatch_wsig",
+ "_zzsetmatch_wsig",
+ "_zzmatch_wdfltsig",
+ "_zzsetmatch_wdfltsig",
+ "zzdflthandlers",
+/* DLG stuff */
+ "zzreal_line",
+ "zzcharfull",
+ "zzerr",
+ "zzlextext",
+ "zzbegexpr",
+ "zzendexpr",
+ "zzbufsize",
+ "zzbegcol",
+ "zzendcol",
+ "zzline",
+ "zzchar",
+ "zzbufovf",
+ "zzrdstream",
+ "zzrdfunc",
+ "zzrdstr",
+ "zzclose_stream",
+ "zzsave_dlg_state",
+ "zzrestore_dlg_state",
+ "zzmode",
+ "zzskip",
+ "zzmore",
+ "zzreplchar",
+ "zzreplstr",
+ "zzgettok",
+ "zzadvance",
+ "zzerrstd",
+ "zzerr_in",
+ "zzconstr_attr",
+ "zzempty_attr",
+ "zzerraction",
+ "zztokens", /* list of token regular expressions */
+ "dfa",
+ "accepts",
+ "actions",
+ "zzTraceOptionValue", /* MR10 */
+ "zzTraceGuessOptionValue", /* MR10 */
+ "zzTraceCurrentRuleName", /* MR10 */
+ "zzTraceDepth", /* MR10 */
+ "zzGuessSeq", /* MR10 */
+ "zzSyntaxErrCount", /* MR11 */
+ "zzLexErrCount", /* MR11 */
+ "zzTraceGuessDone", /* MR13 - BJS */
+ "zzTraceGuessFail", /* MR13 - BJS */
+ "zzTraceGuessOption", /* MR13 - BJS */
+ "zzTraceIn", /* MR13 - BJS */
+ "zzTraceOption", /* MR13 - BJS */
+ "zzTraceOut", /* MR13 - BJS */
+ "zzTraceReset", /* MR13 - BJS */
+ NULL /* must be present */
+};
+
+/* list of PCCTS supplied support functions; these are renamed when more than
+ * one ANTLR-generated parsers are linked together to avoid name conflicts.
+ */
+char *ASTSymbols[] = {
+ "AST",
+ "zzast_sp",
+ "zzastStack",
+ "zzlink",
+ "zzastnew",
+ "zzsubchild",
+ "zzsubroot",
+ "zzpre_ast",
+ "zzfree_ast",
+ "zztmake",
+ "zzdup_ast",
+ "zztfree",
+ "zzdouble_link",
+ NULL /* must be present */
+};
+
+/* Current ambiguity examination information */
+int CurAmbigAlt1, CurAmbigAlt2, CurAmbigline, CurAmbigfile;
+char *CurAmbigbtype;
+
+
+ /* M e t h o d T a b l e s */
+/*
+ * The following tables are used to fill syntax diagram nodes with the correct
+ * function pointers for computing FIRST sets and printing themselves.
+ */
+
+/* fpTraverse[node type] == pointer to function that calculates trees
+ * representing the FIRST sets for that node (maintains spatial info).
+ * We use 'struct _tree' not 'tree' due to a g++ 2.4.3 bug.
+ */
+#ifdef __cplusplus
+struct _tree *(*fpTraverse[NumNodeTypes+1])(... /* Node *, int, set * */) = {
+ NULL,
+ (struct _tree *(*)(...)) tJunc,
+ (struct _tree *(*)(...)) tRuleRef,
+ (struct _tree *(*)(...)) tToken,
+ (struct _tree *(*)(...)) tAction
+};
+#else
+Tree *(*fpTraverse[NumNodeTypes+1])() = {
+ NULL,
+ tJunc,
+ tRuleRef,
+ tToken,
+ tAction
+};
+#endif
+
+/* fpReach[node type] == pointer to function that calculates FIRST set for
+ * that node. (r stands for reach). We use 'struct _set' not 'set'
+ * due to a g++ 2.4.3 bug.
+ */
+#ifdef __cplusplus
+struct _set (*fpReach[NumNodeTypes+1])(... /* Node *, int, set * */) = {
+ NULL,
+ (struct _set (*)(...)) rJunc,
+ (struct _set (*)(...)) rRuleRef,
+ (struct _set (*)(...)) rToken,
+ (struct _set (*)(...)) rAction
+};
+#else
+set (*fpReach[NumNodeTypes+1])() = {
+ NULL,
+ rJunc,
+ rRuleRef,
+ rToken,
+ rAction
+};
+#endif
+
+/* fpPrint[node type] == pointer to function that knows how to print that node. */
+#ifdef __cplusplus
+void (*fpPrint[NumNodeTypes+1])(... /* Node * */) = {
+ NULL,
+ (void (*)(...)) pJunc,
+ (void (*)(...)) pRuleRef,
+ (void (*)(...)) pToken,
+ (void (*)(...)) pAction
+};
+#else
+void (*fpPrint[NumNodeTypes+1])() = {
+ NULL,
+ pJunc,
+ pRuleRef,
+ pToken,
+ pAction
+};
+#endif
+
+char *decodeJType[] = {
+ "invalid",
+ "aSubBlk",
+ "aOptBlk",
+ "aLoopBlk",
+ "EndBlk",
+ "RuleBlk",
+ "Generic",
+ "EndRule",
+ "aPlusBlk",
+ "aLoopBegin"
+};
+
+
+ /* H a s h T a b l e s */
+
+Entry **Tname, /* Table of all token names (maps name to tok num)*/
+ **Texpr, /* Table of all token expressions
+ (maps expr to tok num) */
+ **Rname, /* Table of all Rules (has ptr to start of rule) */
+ **Fcache, /* Cache of First/Follow Computations */
+ **Tcache; /* Tree cache; First/Follow for permute trees */
+Entry **Elabel; /* Table of all element label names */
+Entry **Sname; /* Signal names */
+Entry **Pname; /* symbolic predicate names MR11 */
+
+
+ /* V a r i a b l e s */
+
+int Save_argc; /* MR10 */
+char **Save_argv; /* MR10 */
+int EpToken=0; /* Imaginary Epsilon token number */
+int WildCardToken=0;
+int CurFile= -1; /* Index into FileStr table */
+char *CurPredName=NULL; /* MR11 */
+char *CurRule=NULL; /* Pointer to current rule name */
+int CurRuleDebug=0; /* MR13 debug flag */
+RuleEntry *CurRuleNode=NULL;/* Pointer to current rule node in syntax tree */
+char *CurRetDef=NULL; /* Pointer to current return type definition */
+char *CurParmDef=NULL; /* Pointer to current parameter definition */
+Junction *CurRuleBlk=NULL; /* Pointer to current block node for enclosing block */
+ListNode *CurExGroups=NULL; /* Current list of exception groups for rule/alts */
+ListNode *CurElementLabels=NULL;
+ListNode *CurAstLabelsInActions=NULL; /* MR27 */
+
+/* MR10 used by <<>>? to set "label_used_in_semantic_pred" */
+/* MR10 this will force LT(i) assignment even in guess mode */
+
+ListNode *CurActionLabels=NULL; /* MR10 Element Labels appearing in last action */
+int numericActionLabel=0 ; /* MR10 << ... $1 ... >> or << ... $1 ... >>? */
+ListNode *NumericPredLabels=NULL; /* MR10 << ... $1 ... >>? ONLY */
+ListNode *ContextGuardPredicateList=NULL; /* MR13 for re-evaluating predicates
+ after meta tokens are defined */
+
+int CurBlockID=0; /* Unique int for each block */
+int CurAltNum=0;
+Junction *CurAltStart = NULL; /* Junction node that starts the alt */
+Junction *OuterAltStart = NULL; /* For chaining exception groups MR7 */
+int NumRules=0; /* Rules are from 1 to n */
+FILE *output=NULL; /* current parser output file */
+FILE *input=NULL; /* current grammar input file */
+char *FileStr[MaxNumFiles];/* Ptr to array of file names on command-line */
+int NumFiles=0; /* current grammar file number */
+#ifdef __cplusplus
+void (**fpTrans)(...), /* array of ptrs to funcs that translate nodes */
+ (**fpJTrans)(...); /* ... that translate junctions */
+#else
+void (**fpTrans)(), /* array of ptrs to funcs that translate nodes */
+ (**fpJTrans)(); /* ... that translate junctions */
+#endif
+int **FoStack; /* Array of LL_k ptrs to stacks of rule numbers */
+int **FoTOS; /* FOLLOW stack top-of-stack pointers */
+Junction *SynDiag = NULL; /* Pointer to start of syntax diagram */
+int BlkLevel=1; /* Current block level. Set by antlr.g, used by
+ * scanner to translate $i.j attributes */
+set reserved_positions; /* set of token positions reserved by '#token T=i' cmds */
+set all_tokens; /* set of all token types */
+set imag_tokens; /* set of all imaginary token types (EpToken, errclasses...) */
+set tokclasses; /* set of all token class token types */
+ListNode *ForcedTokens = 0; /* list of token_id/token_num pairs to remap */
+ListNode *MetaTokenNodes=NULL; /* list of meta token refs such as token classes etc... */
+int *TokenInd=NULL; /* an indirection level between token num and position
+ * of that token def in TokenStr and ExprStr */
+int LastTokenCounted=0; /* ==TokenNum if no token renumbering (same as old TokenNum) */
+int TokenNum=TokenStart;
+char **TokenStr=NULL; /* map token # to token name */
+char **ExprStr=NULL; /* map token # to expr */
+Junction **RulePtr=NULL; /* map rule # to RuleBlk node of rule */
+ListNode *ExprOrder=NULL; /* list of exprs as they are found in grammar */
+ListNode *BeforeActions=NULL;/* list of grammar actions before rules */
+ListNode *AfterActions=NULL;/* list of grammar actions after rules */
+ListNode *LexActions=NULL; /* list of lexical actions */
+
+/* MR1 */
+/* MR1 11-Apr-97 Provide mechanism for inserting code into DLG class */
+/* MR1 via #lexmember <<....>> */
+/* MR1 via #lexprefix <<....>> */
+/* MR1 */
+
+ListNode *LexMemberActions=NULL;/* list of lexical header member decl MR1 */
+ListNode *LexPrefixActions=NULL;/* list of lexical header #include decl MR1 */
+ListNode **Cycles=NULL; /* list of cycles (for each k) found when
+ doing FOLLOWs */
+ListNode *eclasses=NULL; /* list of error classes */
+ListNode *tclasses=NULL; /* list of token classes */
+LClass lclass[MaxLexClasses]; /* array of lex class definitions */
+int CurrentLexClass; /* index into lclass */
+int NumLexClasses=0; /* in range 1..MaxLexClasses (init 0) */
+
+char *HdrAction=NULL; /* action defined with #header */
+char *FirstAction=NULL; /* action defined with #first MR11 */
+FILE *ErrFile; /* sets and error recovery stuff */
+FILE *DefFile=NULL; /* list of tokens, return value structs, setwd defs */
+FILE *MRinfoFile=NULL; /* MR10 information file */
+int MRinfo=0; /* MR10 */
+int MRinfoSeq=0; /* MR10 */
+int InfoP=0; /* MR10 predicates */
+int InfoT=0; /* MR10 tnodes */
+int InfoF=0; /* MR10 first/follow sets */
+int InfoM=0; /* MR10 monitor progress */
+int InfoO=0; /* MR12 orphan rules */
+int TnodesInUse=0; /* MR10 */
+int TnodesPeak=0; /* MR10 */
+int TnodesAllocated=0; /* MR10 */
+int TnodesReportThreshold=0; /* MR11 */
+int PotentialSuppression=0; /* MR10 */
+int PotentialDummy=0; /* MR10 */
+int CannotContinue=FALSE;
+int OutputLL_k = 1; /* LL_k for parsing must be power of 2 */
+int action_file; /* used to track start of action */
+int action_line;
+int FoundGuessBlk=0; /* there is a (...)? block somewhere in grammar */
+int FoundException=0; /* there is an exception somewhere in grammar */
+/* MR6 Distinguish between @ operator and real exception */
+/* MR6 by keeping separate flags for @ operator and real exceptions */
+int FoundAtOperator=0; /* MR6 */
+int FoundExceptionGroup=0; /* MR6 */
+int pLevel=0; /* print Level */
+int pAlt1,pAlt2; /* print "==>" in front of these alts */
+
+/* C++ output stuff */
+FILE *Parser_h, /* where subclass of ANTLRParser goes */
+ *Parser_c; /* where code for subclass of ANTLRParser goes */
+char Parser_h_Name[MaxFileName+1] = "";
+char Parser_c_Name[MaxFileName+1] = "";
+char MRinfoFile_Name[MaxFileName+1] = ""; /* MR10 */
+char *ClassDeclStuff=NULL; /* MR10 */
+char *BaseClassName=NULL; /* MR22 */
+/* list of actions inside the #class {...} defs */
+ListNode *class_before_actions=NULL;
+ListNode *class_after_actions=NULL;
+
+char CurrentClassName[MaxRuleName]="";
+int no_classes_found=1;
+char *UserTokenDefsFile;
+int UserDefdTokens=0; /* found #tokdefs? */
+char *OutputDirectory=TopDirectory;
+ExceptionGroup *DefaultExGroup = NULL;
+int NumSignals = NumPredefinedSignals;
+int ContextGuardTRAV=0;
+
+char *MR_AmbAidRule=NULL; /* MR11 */
+int MR_AmbAidLine=0; /* MR11 */
+int MR_AmbAidDepth=0; /* MR11 */
+int MR_AmbAidMultiple=0; /* MR11 */
+int MR_skipped_e3_report=0; /* MR11 */
+int MR_usingPredNames=0; /* MR11 */
+int MR_BadExprSets=0; /* MR13 */
+int MR_Inhibit_Tokens_h_Gen=0; /* MR13 */
+int NewAST=0; /* MR13 */
+int tmakeInParser=0; /* MR23 */
+int AlphaBetaTrace=0; /* MR14 */
+int MR_BlkErr=0; /* MR21 */
+int MR_AlphaBetaMessageCount=0; /* MR14 */
+int MR_AlphaBetaWarning=0; /* MR14 */
+int MR_ErrorSetComputationActive=0; /* MR14 */
+int MR_MaintainBackTrace=0; /* MR14 */
+set MR_CompromisedRules; /* MR14 */
+
+Junction *MR_RuleBlkWithHalt; /* MR10 */
+
+ /* C m d - L i n e O p t i o n s */
+
+int LL_k=1; /* how many tokens of full lookahead */
+int CLL_k= -1; /* how many tokens of compressed lookahead */
+int PrintOut = FALSE; /* print out the grammar */
+int PrintAnnotate = FALSE;/* annotate printout with FIRST sets */
+int CodeGen=TRUE; /* Generate output code? */
+int LexGen=TRUE; /* Generate lexical files? (tokens.h, parser.dlg) */
+int GenAST=FALSE; /* Generate AST's? */
+int GenANSI=FALSE; /* Generate ANSI code where necessary */
+int GenExprSetsOpt=TRUE;/* use sets not (LA(1)==tok) expression lists */
+int GenCR=FALSE; /* Generate cross reference? */
+int GenLineInfo=FALSE; /* Generate # line "file" stuff? */
+int GenLineInfoMS=FALSE;/* Like -gl but replace "\" with "/" for MS C/C++ systems */
+int TraceGen=FALSE; /* Generate code to trace rule invocation */
+int elevel=1; /* error level for ambiguity messages */
+int GenEClasseForRules=0;/* don't generate eclass for each rule */
+int TreeResourceLimit= -1;/* don't limit tree resource */
+int DemandLookahead = 0;/* demand/delayed lookahead or not */
+char *RulePrefix = ""; /* prefix each generated rule with this */
+char *stdpccts = "stdpccts.h";/* where to generate std pccts include file */
+int GenStdPccts = 0; /* don't gen stdpccts.h? */
+int ParseWithPredicates = 1;
+int WarningLevel = 1;
+int UseStdout = 0; /* MR6 */
+int TabWidth = 2; /* MR6 */ /* MR27 */
+int HoistPredicateContext = 0;
+int MRhoisting = 0; /* MR9 */
+int MRhoistingk = 0; /* MR13 */
+int MR_debugGenRule=0; /* MR11 */
+
+int GenCC = 0; /* Generate C++ output */
+
+PointerStack MR_BackTraceStack={0,0,NULL}; /* MR10 */
+PointerStack MR_PredRuleRefStack={0,0,NULL}; /* MR10 */
+PointerStack MR_RuleBlkWithHaltStack={0,0,NULL}; /* MR10 */
+
+/* DontCopyTokens and Pragma_DupLabeledTokens were a bad idea. I've just
+ turned them off rather than backpatching the code. Who knows? We
+ may need them in the future.
+ */
+int DontCopyTokens = 1; /* in C++, don't copy ANTLRToken passed to ANTLR */
+
+/* Remember if LT(i), LA(i), or LATEXT(i) used in an action which is not
+ a predicate. If so, give a warning for novice users.
+*/
+
+int LTinTokenAction = 0; /* MR23 */
+int PURIFY = 1; /* MR23 */
+
+int CurBlockID_array[MAX_BLK_LEVEL]; /* MR23 */
+int CurAltNum_array[MAX_BLK_LEVEL]; /* MR23 */
diff --git a/Source/Pccts/antlr/hash.c b/Source/Pccts/antlr/hash.c
new file mode 100644
index 0000000..68fe8fd
--- /dev/null
+++ b/Source/Pccts/antlr/hash.c
@@ -0,0 +1,221 @@
+/*
+ * hash.c
+ *
+ * Manage hash tables.
+ *
+ * The following functions are visible:
+ *
+ * char *mystrdup(char *); Make space and copy string
+ * Entry **newHashTable(); Create and return initialized hash table
+ * Entry *hash_add(Entry **, char *, Entry *)
+ * Entry *hash_get(Entry **, char *)
+ *
+ * SOFTWARE RIGHTS
+ *
+ * We reserve no LEGAL rights to the Purdue Compiler Construction Tool
+ * Set (PCCTS) -- PCCTS is in the public domain. An individual or
+ * company may do whatever they wish with source code distributed with
+ * PCCTS or the code generated by PCCTS, including the incorporation of
+ * PCCTS, or its output, into commerical software.
+ *
+ * We encourage users to develop software with PCCTS. However, we do ask
+ * that credit is given to us for developing PCCTS. By "credit",
+ * we mean that if you incorporate our source code into one of your
+ * programs (commercial product, research project, or otherwise) that you
+ * acknowledge this fact somewhere in the documentation, research report,
+ * etc... If you like PCCTS and have developed a nice tool with the
+ * output, please mention that you developed it using PCCTS. In
+ * addition, we ask that this header remain intact in our source code.
+ * As long as these guidelines are kept, we expect to continue enhancing
+ * this system and expect to make other tools available as they are
+ * completed.
+ *
+ * ANTLR 1.33
+ * Terence Parr
+ * Parr Research Corporation
+ * with Purdue University and AHPCRC, University of Minnesota
+ * 1989-2001
+ */
+
+#include <stdio.h>
+#include "pcctscfg.h"
+#include "hash.h"
+
+#ifdef __USE_PROTOS
+#include <stdlib.h>
+#else
+#ifdef VAXC
+#include <stdlib.h>
+#else
+#include <malloc.h>
+#endif
+#endif
+#include <string.h>
+
+#define StrSame 0
+
+#define fatal(err) \
+ {fprintf(stderr, "%s(%d):", __FILE__, __LINE__); \
+ fprintf(stderr, " %s\n", err); exit(PCCTS_EXIT_FAILURE);}
+#define require(expr, err) {if ( !(expr) ) fatal(err);}
+
+static unsigned size = HashTableSize;
+static char *strings = NULL;
+static char *strp;
+static unsigned strsize = StrTableSize;
+
+/* create the hash table and string table for terminals (string table only once) */
+Entry **
+#ifdef __USE_PROTOS
+newHashTable( void )
+#else
+newHashTable( )
+#endif
+{
+ Entry **table;
+
+ table = (Entry **) calloc(size, sizeof(Entry *));
+ require( table != NULL, "cannot allocate hash table");
+ if ( strings == NULL )
+ {
+ strings = (char *) calloc(strsize, sizeof(char));
+ require( strings != NULL, "cannot allocate string table");
+ strp = strings;
+ }
+ return table;
+}
+
+void
+#ifdef __USE_PROTOS
+killHashTable( Entry **table )
+#else
+killHashTable( table )
+Entry **table;
+#endif
+{
+ /* for now, just free table, forget entries */
+ free( (char *) table ); /* MR10 cast */
+}
+
+/* Given a table, add 'rec' with key 'key' (add to front of list). return ptr to entry */
+Entry *
+#ifdef __USE_PROTOS
+hash_add( Entry **table, char *key, Entry *rec )
+#else
+hash_add( table, key, rec )
+Entry **table;
+char *key;
+Entry *rec;
+#endif
+{
+ unsigned h=0;
+ char *p=key;
+ require(table!=NULL && key!=NULL && rec!=NULL, "add: invalid addition");
+
+ Hash(p,h,size);
+ rec->next = table[h]; /* Add to singly-linked list */
+ table[h] = rec;
+ return rec;
+}
+
+/* Return ptr to 1st entry found in table under key (return NULL if none found) */
+Entry *
+#ifdef __USE_PROTOS
+hash_get( Entry **table, char *key )
+#else
+hash_get( table, key )
+Entry **table;
+char *key;
+#endif
+{
+ unsigned h=0;
+ char *p=key;
+ Entry *q;
+/* require(table!=NULL && key!=NULL, "get: invalid table and/or key");*/
+ if ( !(table!=NULL && key!=NULL) ) *((char *) 34) = 3;
+
+ Hash(p,h,size);
+ for (q = table[h]; q != NULL; q = q->next)
+ {
+ if ( strcmp(key, q->str) == StrSame ) return( q );
+ }
+ return( NULL );
+}
+
+#ifdef DEBUG_HASH
+void
+#ifdef __USE_PROTOS
+hashStat( Entry **table )
+#else
+hashStat( table )
+Entry **table;
+#endif
+{
+ static unsigned short count[20];
+ int i,n=0,low=0, hi=0;
+ Entry **p;
+ float avg=0.0;
+
+ for (i=0; i<20; i++) count[i] = 0;
+ for (p=table; p<&(table[size]); p++)
+ {
+ Entry *q = *p;
+ int len;
+
+ if ( q != NULL && low==0 ) low = p-table;
+ len = 0;
+ if ( q != NULL ) fprintf(stderr, "[%d]", p-table);
+ while ( q != NULL )
+ {
+ len++;
+ n++;
+ fprintf(stderr, " %s", q->str);
+ q = q->next;
+ if ( q == NULL ) fprintf(stderr, "\n");
+ }
+ count[len]++;
+ if ( *p != NULL ) hi = p-table;
+ }
+
+ fprintf(stderr, "Storing %d recs used %d hash positions out of %d\n",
+ n, size-count[0], size);
+ fprintf(stderr, "%f %% utilization\n",
+ ((float)(size-count[0]))/((float)size));
+ for (i=0; i<20; i++)
+ {
+ if ( count[i] != 0 )
+ {
+ avg += (((float)(i*count[i]))/((float)n)) * i;
+ fprintf(stderr, "Bucket len %d == %d (%f %% of recs)\n",
+ i, count[i], ((float)(i*count[i]))/((float)n));
+ }
+ }
+ fprintf(stderr, "Avg bucket length %f\n", avg);
+ fprintf(stderr, "Range of hash function: %d..%d\n", low, hi);
+}
+#endif
+
+/* Add a string to the string table and return a pointer to it.
+ * Bump the pointer into the string table to next avail position.
+ */
+char *
+#ifdef __USE_PROTOS
+mystrdup( char *s )
+#else
+mystrdup( s )
+char *s;
+#endif
+{
+ char *start=strp;
+ require(s!=NULL, "mystrdup: NULL string");
+
+ while ( *s != '\0' )
+ {
+ require( strp <= &(strings[strsize-2]),
+ "string table overflow\nIncrease StrTableSize in hash.h and recompile hash.c\n");
+ *strp++ = *s++;
+ }
+ *strp++ = '\0';
+
+ return( start );
+}
diff --git a/Source/Pccts/antlr/hash.h b/Source/Pccts/antlr/hash.h
new file mode 100644
index 0000000..3969c40
--- /dev/null
+++ b/Source/Pccts/antlr/hash.h
@@ -0,0 +1,73 @@
+/*
+ * hash.h -- define hash table entries, sizes, hash function...
+ *
+ * SOFTWARE RIGHTS
+ *
+ * We reserve no LEGAL rights to the Purdue Compiler Construction Tool
+ * Set (PCCTS) -- PCCTS is in the public domain. An individual or
+ * company may do whatever they wish with source code distributed with
+ * PCCTS or the code generated by PCCTS, including the incorporation of
+ * PCCTS, or its output, into commerical software.
+ *
+ * We encourage users to develop software with PCCTS. However, we do ask
+ * that credit is given to us for developing PCCTS. By "credit",
+ * we mean that if you incorporate our source code into one of your
+ * programs (commercial product, research project, or otherwise) that you
+ * acknowledge this fact somewhere in the documentation, research report,
+ * etc... If you like PCCTS and have developed a nice tool with the
+ * output, please mention that you developed it using PCCTS. In
+ * addition, we ask that this header remain intact in our source code.
+ * As long as these guidelines are kept, we expect to continue enhancing
+ * this system and expect to make other tools available as they are
+ * completed.
+ *
+ * ANTLR 1.33
+ * Terence Parr
+ * Parr Research Corporation
+ * with Purdue University and AHPCRC, University of Minnesota
+ * 1989-2001
+ */
+
+ /* H a s h T a b l e S t u f f */
+
+#ifndef HashTableSize
+#define HashTableSize 553
+#endif
+
+#ifndef StrTableSize
+#ifdef PC32
+#define StrTableSize 1000000
+#endif
+#endif
+
+#ifndef StrTableSize
+#ifdef PC
+#define StrTableSize 655200
+#endif
+#endif
+
+#ifndef StrTableSize
+#define StrTableSize 1000000
+#endif
+
+typedef struct _entry { /* Minimum hash table entry -- superclass */
+ char *str;
+ struct _entry *next;
+ } Entry;
+
+/* Hash 's' using 'size', place into h (s is modified) */
+#define Hash(s,h,size) \
+ {while ( *s != '\0' ) h = (h<<1) + *s++; \
+ h %= size;}
+
+#ifdef __USE_PROTOS
+Entry *hash_get(Entry **, char *),
+ **newHashTable(void),
+ *hash_add(Entry **, char *, Entry *);
+
+void killHashTable(Entry **);
+
+#else
+Entry *hash_get(), **newHashTable(), *hash_add();
+void killHashTable(); /* MR9 23-Sep-97 */
+#endif
diff --git a/Source/Pccts/antlr/lex.c b/Source/Pccts/antlr/lex.c
new file mode 100644
index 0000000..8c524fe
--- /dev/null
+++ b/Source/Pccts/antlr/lex.c
@@ -0,0 +1,878 @@
+/*
+ * lex.c -- Generate all of the lexical type files: parser.dlg tokens.h
+ *
+ * SOFTWARE RIGHTS
+ *
+ * We reserve no LEGAL rights to the Purdue Compiler Construction Tool
+ * Set (PCCTS) -- PCCTS is in the public domain. An individual or
+ * company may do whatever they wish with source code distributed with
+ * PCCTS or the code generated by PCCTS, including the incorporation of
+ * PCCTS, or its output, into commerical software.
+ *
+ * We encourage users to develop software with PCCTS. However, we do ask
+ * that credit is given to us for developing PCCTS. By "credit",
+ * we mean that if you incorporate our source code into one of your
+ * programs (commercial product, research project, or otherwise) that you
+ * acknowledge this fact somewhere in the documentation, research report,
+ * etc... If you like PCCTS and have developed a nice tool with the
+ * output, please mention that you developed it using PCCTS. In
+ * addition, we ask that this header remain intact in our source code.
+ * As long as these guidelines are kept, we expect to continue enhancing
+ * this system and expect to make other tools available as they are
+ * completed.
+ *
+ * ANTLR 1.33
+ * Terence Parr
+ * Parr Research Corporation
+ * with Purdue University and AHPCRC, University of Minnesota
+ * 1989-2001
+ */
+
+#include <stdio.h>
+#include <ctype.h>
+/* MR1 */
+/* MR1 10-Apr-97 MR1 Replace use of __STDC__ with __USE_PROTOS */
+/* MR1 */
+#include "pcctscfg.h"
+#include "set.h"
+#include "syn.h"
+#include "hash.h"
+#include "generic.h"
+
+#define DLGErrorString "invalid token"
+
+/* Generate a complete lexical description of the lexemes found in the grammar */
+void
+#ifdef __USE_PROTOS
+genLexDescr( void )
+#else
+genLexDescr( )
+#endif
+{
+ ListNode *p;
+ FILE *dlgFile = fopen(OutMetaName(DlgFileName), "w");
+ require(dlgFile!=NULL, eMsg1("genLexFile: cannot open %s", OutMetaName(DlgFileName)) );
+#ifdef SPECIAL_FOPEN
+ special_fopen_actions(OutMetaName(DlgFileName)); /* MR1 */
+#endif
+ fprintf(dlgFile, "<<\n");
+ fprintf(dlgFile, "/* %s -- DLG Description of scanner\n", DlgFileName);
+ fprintf(dlgFile, " *\n");
+ fprintf(dlgFile, " * Generated from:");
+ {int i; for (i=0; i<NumFiles; i++) fprintf(dlgFile, " %s", FileStr[i]);}
+ fprintf(dlgFile, "\n");
+ fprintf(dlgFile, " *\n");
+ fprintf(dlgFile, " * Terence Parr, Will Cohen, and Hank Dietz: 1989-2001\n");
+ fprintf(dlgFile, " * Purdue University Electrical Engineering\n");
+ fprintf(dlgFile, " * With AHPCRC, University of Minnesota\n");
+ fprintf(dlgFile, " * ANTLR Version %s\n", Version);
+ fprintf(dlgFile, " */\n\n");
+ if (FirstAction != NULL ) dumpAction( FirstAction, dlgFile, 0, -1, 0, 1 ); /* MR11 MR15b */
+ fprintf(dlgFile, "#define ANTLR_VERSION %s\n", VersionDef);
+ if ( GenCC )
+ {
+ if ( !UserDefdTokens ) fprintf(dlgFile, "#include \"%s\"\n", DefFileName);
+ else fprintf(dlgFile, "#include %s\n", UserTokenDefsFile);
+ fprintf(dlgFile, "#include \"%s\"\n", ATOKEN_H);
+ if ( GenAST ) fprintf(dlgFile, "#include \"%s\"\n", ASTBASE_H);
+ if ( HdrAction != NULL ) dumpAction( HdrAction, dlgFile, 0, -1, 0, 1 );
+ }
+ else
+ {
+ fprintf(dlgFile, "#include \"pcctscfg.h\"\n");
+ fprintf(dlgFile, "#include \"pccts_stdio.h\"\n");
+ if ( strcmp(ParserName, DefaultParserName)!=0 )
+ fprintf(dlgFile, "#define %s %s\n", DefaultParserName, ParserName);
+ if ( strcmp(ParserName, DefaultParserName)!=0 )
+ fprintf(dlgFile, "#include \"%s\"\n", RemapFileName);
+ if ( HdrAction != NULL ) dumpAction( HdrAction, dlgFile, 0, -1, 0, 1 );
+ if ( FoundGuessBlk )
+ {
+ fprintf(dlgFile, "#define ZZCAN_GUESS\n");
+ fprintf(dlgFile, "#include \"pccts_setjmp.h\"\n");
+ }
+ if ( OutputLL_k > 1 ) fprintf(dlgFile, "#define LL_K %d\n", OutputLL_k);
+ if ( DemandLookahead ) fprintf(dlgFile, "#define DEMAND_LOOK\n");
+ if (TraceGen) {
+ fprintf(dlgFile,"#ifndef zzTRACE_RULES\n"); /* MR20 */
+ fprintf(dlgFile,"#define zzTRACE_RULES\n"); /* MR20 */
+ fprintf(dlgFile,"#endif\n"); /* MR22 */
+ };
+ fprintf(dlgFile, "#include \"antlr.h\"\n");
+ if ( GenAST ) {
+ fprintf(dlgFile, "#include \"ast.h\"\n");
+ }
+ if ( UserDefdTokens )
+ fprintf(dlgFile, "#include %s\n", UserTokenDefsFile);
+ /* still need this one as it has the func prototypes */
+ fprintf(dlgFile, "#include \"%s\"\n", DefFileName);
+ fprintf(dlgFile, "#include \"dlgdef.h\"\n");
+ fprintf(dlgFile, "LOOKAHEAD\n");
+ fprintf(dlgFile, "\n");
+ fprintf(dlgFile, "void\n");
+ fprintf(dlgFile, "#ifdef __USE_PROTOS\n");
+ fprintf(dlgFile, "zzerraction(void)\n");
+ fprintf(dlgFile, "#else\n");
+ fprintf(dlgFile, "zzerraction()\n");
+ fprintf(dlgFile, "#endif\n");
+ fprintf(dlgFile, "{\n");
+ fprintf(dlgFile, "\t(*zzerr)(\"%s\");\n", DLGErrorString);
+ fprintf(dlgFile, "\tzzadvance();\n");
+ fprintf(dlgFile, "\tzzskip();\n");
+ fprintf(dlgFile, "}\n");
+ }
+ fprintf(dlgFile, ">>\n\n");
+
+ /* dump all actions */
+
+/* MR1 */
+/* MR1 11-Apr-97 Provide mechanism for inserting code into DLG class */
+/* MR1 via <<%%lexmember ....>> & <<%%lexprefix ...>> */
+/* MR1 */
+ if (LexActions != NULL) {
+ for (p = LexActions->next; p!=NULL; p=p->next)
+ {
+/* MR1 */ fprintf(dlgFile, "<<%%%%lexaction\n");
+ dumpAction( (char *)p->elem, dlgFile, 0, -1, 0, 1 );
+ fprintf(dlgFile, ">>\n\n");
+ }
+ };
+
+/* MR1 */ if (GenCC) {
+/* MR1 */ fprintf(dlgFile,"<<%%%%parserclass %s>>\n\n",CurrentClassName);
+/* MR1 */ };
+
+/* MR1 */ if (LexPrefixActions != NULL) {
+/* MR1 */ for (p = LexPrefixActions->next; p!=NULL; p=p->next)
+/* MR1 */ {
+/* MR1 */ fprintf(dlgFile, "<<%%%%lexprefix\n");
+/* MR1 */ dumpAction( (char *)p->elem, dlgFile, 0, -1, 0, 1 );
+/* MR1 */ fprintf(dlgFile, ">>\n\n");
+/* MR1 */ }
+/* MR1 */ };
+
+/* MR1 */ if (LexMemberActions != NULL) {
+/* MR1 */ for (p = LexMemberActions->next; p!=NULL; p=p->next)
+/* MR1 */ {
+/* MR1 */ fprintf(dlgFile, "<<%%%%lexmember\n");
+/* MR1 */ dumpAction( (char *)p->elem, dlgFile, 0, -1, 0, 1 );
+/* MR1 */ fprintf(dlgFile, ">>\n\n");
+/* MR1 */ }
+/* MR1 */ };
+
+ /* dump all regular expression rules/actions (skip sentinel node) */
+ if ( ExprOrder == NULL ) {
+ warnNoFL("no regular expressions found in grammar");
+ }
+ else dumpLexClasses(dlgFile);
+ fprintf(dlgFile, "%%%%\n");
+ fclose( dlgFile );
+}
+
+/* For each lexical class, scan ExprOrder looking for expressions
+ * in that lexical class. Print out only those that match.
+ * Each element of the ExprOrder list has both an expr and an lclass
+ * field.
+ */
+void
+#ifdef __USE_PROTOS
+dumpLexClasses( FILE *dlgFile )
+#else
+dumpLexClasses( dlgFile )
+FILE *dlgFile;
+#endif
+{
+ int i;
+ TermEntry *t;
+ ListNode *p;
+ Expr *q;
+
+ for (i=0; i<NumLexClasses; i++)
+ {
+ fprintf(dlgFile, "\n%%%%%s\n\n", lclass[i].classnum);
+ for (p=ExprOrder->next; p!=NULL; p=p->next)
+ {
+ q = (Expr *) p->elem;
+ if ( q->lclass != i ) continue;
+ lexmode(i);
+ t = (TermEntry *) hash_get(Texpr, q->expr);
+ require(t!=NULL, eMsg1("genLexDescr: rexpr %s not in hash table",q->expr) );
+ if ( t->token == EpToken ) continue;
+ fprintf(dlgFile, "%s\n\t<<\n", StripQuotes(q->expr));
+ /* replace " killed by StripQuotes() */
+ q->expr[ strlen(q->expr) ] = '"';
+ if ( !GenCC ) {
+ if ( TokenString(t->token) != NULL )
+ fprintf(dlgFile, "\t\tNLA = %s;\n", TokenString(t->token));
+ else
+ fprintf(dlgFile, "\t\tNLA = %d;\n", t->token);
+ }
+ if ( t->action != NULL ) dumpAction( t->action, dlgFile, 2,-1,0,1 );
+ if ( GenCC ) {
+ if ( TokenString(t->token) != NULL )
+ fprintf(dlgFile, "\t\treturn %s;\n", TokenString(t->token));
+ else
+ fprintf(dlgFile, "\t\treturn (ANTLRTokenType)%d;\n", t->token);
+ }
+ fprintf(dlgFile, "\t>>\n\n");
+ }
+ }
+}
+
+/* Strip the leading path (if any) from a filename */
+char *
+#ifdef __USE_PROTOS
+StripPath( char *fileName )
+#else
+StripPath( fileName )
+char *fileName;
+#endif
+{
+ char *p;
+ static char dirSym[2] = DirectorySymbol;
+
+ if(NULL != (p = strrchr(fileName, dirSym[0])))
+ p++;
+ else
+ p = fileName;
+
+ return(p);
+}
+
+/* Generate a list of #defines && list of struct definitions for
+ * aggregate retv's */
+void
+#ifdef __USE_PROTOS
+genDefFile( void )
+#else
+genDefFile( )
+#endif
+{
+ int i;
+
+ /* If C++ mode and #tokdef used, then don't need anything in here since
+ * C++ puts all definitions in the class file name.
+ */
+ if ( GenCC && UserTokenDefsFile ) return;
+ if ( MR_Inhibit_Tokens_h_Gen) return;
+
+ DefFile = fopen(OutMetaName(DefFileName), "w");
+ require(DefFile!=NULL, eMsg1("genDefFile: cannot open %s", OutMetaName(DefFileName)) );
+#ifdef SPECIAL_FOPEN
+ special_fopen_actions(OutMetaName(DefFileName)); /* MR1 */
+#endif
+ fprintf(DefFile, "#ifndef %s\n", StripPath(gate_symbol(DefFileName)));
+ fprintf(DefFile, "#define %s\n", StripPath(gate_symbol(DefFileName)));
+
+ fprintf(DefFile, "/* %s -- List of labelled tokens and stuff\n", DefFileName);
+ fprintf(DefFile, " *\n");
+ fprintf(DefFile, " * Generated from:");
+ for (i=0; i<NumFiles; i++) fprintf(DefFile, " %s", FileStr[i]);
+ fprintf(DefFile, "\n");
+ fprintf(DefFile, " *\n");
+ fprintf(DefFile, " * Terence Parr, Will Cohen, and Hank Dietz: 1989-2001\n");
+ fprintf(DefFile, " * Purdue University Electrical Engineering\n");
+ fprintf(DefFile, " * ANTLR Version %s\n", Version);
+ fprintf(DefFile, " */\n");
+
+ if ( !GenCC && LexGen ) {
+ fprintf(DefFile,"#define zzEOF_TOKEN %d\n",
+ TokenInd!=NULL?TokenInd[EofToken]:EofToken);
+ }
+
+ if ( !UserDefdTokens )
+ {
+ int first=1;
+
+ if ( GenCC ) fprintf(DefFile, "enum ANTLRTokenType {\n");
+ for (i=1; i<TokenNum; i++)
+ {
+ /* Don't do EpToken or expr w/o labels */
+ if ( TokenString(i)!=NULL && i != EpToken )
+ {
+ TermEntry *p;
+
+ if ( WarningLevel>1 )
+ {
+ int j;
+ /* look in all lexclasses for the reg expr */
+
+/* MR10 Derek Pappas */
+/* MR10 A #tokclass doesn't have associated regular expressiones */
+/* MR10 so don't warn user about it's omission */
+
+ p = (TermEntry *) hash_get(Tname, TokenString(i));
+
+ if (p != NULL && ! p->classname) {
+ for (j=0; j<NumLexClasses; j++)
+ {
+ lexmode(j);
+ if ( ExprString(i)!=NULL ) break;
+ }
+ if ( j>=NumLexClasses )
+ {
+ warnNoFL(eMsg1("token label has no associated rexpr: %s",TokenString(i)));
+ }
+ };
+ }
+ require((p=(TermEntry *)hash_get(Tname, TokenString(i))) != NULL,
+ "token not in sym tab when it should be");
+ if ( !p->classname )
+ {
+ if ( GenCC ) {
+ if ( !first ) fprintf(DefFile, ",\n");
+ first = 0;
+ fprintf(DefFile, "\t%s=%d", TokenString(i), i);
+ }
+ else
+ fprintf(DefFile, "#define %s %d\n", TokenString(i), i);
+ }
+ }
+ }
+/* MR1 */
+/* MR1 10-Apr-97 133MR1 Prevent use of varying sizes of integer */
+/* MR1 for the enum ANTLRTokenType */
+/* MR1 */
+ if ( GenCC ) { /* MR1 */
+ if ( !first ) fprintf(DefFile, ",\n"); /* MR14 */
+ fprintf(DefFile, "\tDLGminToken=0"); /* MR1 */
+ fprintf(DefFile, ",\n\tDLGmaxToken=9999};\n"); /* MR1 */
+ }; /* MR1 */
+ }
+
+ if ( !GenCC ) GenRulePrototypes(DefFile, SynDiag);
+
+ fprintf(DefFile, "\n#endif\n");
+}
+
+void
+#ifdef __USE_PROTOS
+GenRemapFile( void )
+#else
+GenRemapFile( )
+#endif
+{
+ if ( strcmp(ParserName, DefaultParserName)!=0 )
+ {
+ FILE *f;
+ int i;
+
+ f = fopen(OutMetaName(RemapFileName), "w");
+ require(f!=NULL, eMsg1("GenRemapFile: cannot open %s", OutMetaName(RemapFileName)) );
+#ifdef SPECIAL_FOPEN
+ special_fopen_actions(OutMetaName(RemapFileName)); /* MR1 */
+#endif
+ fprintf(f, "/* %s -- List of symbols to remap\n", RemapFileName);
+ fprintf(f, " *\n");
+ fprintf(f, " * Generated from:");
+ for (i=0; i<NumFiles; i++) fprintf(f, " %s", FileStr[i]);
+ fprintf(f, "\n");
+ fprintf(f, " *\n");
+ fprintf(f, " * Terence Parr, Will Cohen, and Hank Dietz: 1989-2001\n");
+ fprintf(f, " * Purdue University Electrical Engineering\n");
+ fprintf(f, " * ANTLR Version %s\n", Version);
+ fprintf(f, " */\n");
+
+ GenRuleFuncRedefs(f, SynDiag);
+ GenPredefinedSymbolRedefs(f);
+ if ( GenAST ) GenASTSymbolRedefs(f);
+ GenSetRedefs(f);
+
+ fclose(f);
+ }
+}
+
+/* Generate a bunch of #defines that rename all functions to be "ParserName_func" */
+void
+#ifdef __USE_PROTOS
+GenRuleFuncRedefs( FILE *f, Junction *p )
+#else
+GenRuleFuncRedefs( f, p )
+FILE *f;
+Junction *p;
+#endif
+{
+ fprintf(f, "\n/* rename rule functions to be 'ParserName_func' */\n");
+ while ( p!=NULL )
+ {
+ fprintf(f, "#define %s %s_%s\n", p->rname, ParserName, p->rname);
+ p = (Junction *)p->p2;
+ }
+}
+
+/* Generate a bunch of #defines that rename all standard symbols to be
+ * "ParserName_symbol". The list of standard symbols to change is in
+ * globals.c.
+ */
+void
+#ifdef __USE_PROTOS
+GenPredefinedSymbolRedefs( FILE *f )
+#else
+GenPredefinedSymbolRedefs( f )
+FILE *f;
+#endif
+{
+ char **p;
+
+ fprintf(f, "\n/* rename PCCTS-supplied symbols to be 'ParserName_symbol' */\n");
+ for (p = &StandardSymbols[0]; *p!=NULL; p++)
+ {
+ fprintf(f, "#define %s %s_%s\n", *p, ParserName, *p);
+ }
+}
+
+/* Generate a bunch of #defines that rename all AST symbols to be
+ * "ParserName_symbol". The list of AST symbols to change is in
+ * globals.c.
+ */
+void
+#ifdef __USE_PROTOS
+GenASTSymbolRedefs( FILE *f )
+#else
+GenASTSymbolRedefs( f )
+FILE *f;
+#endif
+{
+ char **p;
+
+ fprintf(f, "\n/* rename PCCTS-supplied AST symbols to be 'ParserName_symbol' */\n");
+ for (p = &ASTSymbols[0]; *p!=NULL; p++)
+ {
+ fprintf(f, "#define %s %s_%s\n", *p, ParserName, *p);
+ }
+}
+
+/* redefine all sets generated by ANTLR; WARNING: 'zzerr', 'setwd' must match
+ * use in bits.c (DumpSetWd() etc...)
+ */
+void
+#ifdef __USE_PROTOS
+GenSetRedefs( FILE *f )
+#else
+GenSetRedefs( f )
+FILE *f;
+#endif
+{
+ int i;
+
+ for (i=1; i<=wordnum; i++)
+ {
+ fprintf(f, "#define setwd%d %s_setwd%d\n", i, ParserName, i);
+ }
+ for (i=1; i<=esetnum; i++)
+ {
+ fprintf(f, "#define zzerr%d %s_err%d\n", i, ParserName, i);
+ }
+}
+
+/* Find all return types/parameters that require structs and def
+ * all rules with ret types.
+ *
+ * This is for the declaration, not the definition.
+ */
+void
+#ifdef __USE_PROTOS
+GenRulePrototypes( FILE *f, Junction *p )
+#else
+GenRulePrototypes( f, p )
+FILE *f;
+Junction *p;
+#endif
+{
+ int i;
+
+ i = 1;
+ while ( p!=NULL )
+ {
+ if ( p->ret != NULL )
+ {
+/* MR23 */ if ( hasMultipleOperands(p->ret) )
+ {
+ DumpRetValStruct(f, p->ret, i);
+ }
+ fprintf(f, "\n#ifdef __USE_PROTOS\n");
+/* MR23 */ if ( hasMultipleOperands(p->ret) )
+ {
+ fprintf(f, "extern struct _rv%d", i);
+ }
+ else
+ {
+ fprintf(f, "extern ");
+ DumpType(p->ret, f);
+ }
+ fprintf(f, " %s%s(", RulePrefix, p->rname);
+ DumpANSIFunctionArgDef(f,p,1 /* emit initializers ? */);
+ fprintf(f, ";\n");
+ fprintf(f, "#else\n");
+/* MR23 */ if ( hasMultipleOperands(p->ret) )
+ {
+ fprintf(f, "extern struct _rv%d", i);
+ }
+ else
+ {
+ fprintf(f, "extern ");
+ DumpType(p->ret, f);
+ }
+ fprintf(f, " %s%s();\n", RulePrefix, p->rname);
+ fprintf(f, "#endif\n");
+ }
+ else
+ {
+ fprintf(f, "\n#ifdef __USE_PROTOS\n");
+ fprintf(f, "void %s%s(", RulePrefix, p->rname);
+ DumpANSIFunctionArgDef(f,p, 1 /* emit initializers ? */ );
+ fprintf(f, ";\n");
+#ifdef OLD
+ if ( p->pdecl != NULL || GenAST )
+ {
+ if ( GenAST ) {
+ fprintf(f, "AST **%s",(p->pdecl!=NULL)?",":"");
+ }
+ if ( p->pdecl!=NULL ) fprintf(f, "%s", p->pdecl);
+ }
+ else fprintf(f, "void");
+ fprintf(f, ");\n");
+#endif
+ fprintf(f, "#else\n");
+ fprintf(f, "extern void %s%s();\n", RulePrefix, p->rname);
+ fprintf(f, "#endif\n");
+ }
+ i++;
+ p = (Junction *)p->p2;
+ }
+}
+
+/* Define all rules in the class.h file; generate any required
+ * struct definitions first, however.
+ */
+void
+#ifdef __USE_PROTOS
+GenRuleMemberDeclarationsForCC( FILE *f, Junction *q )
+#else
+GenRuleMemberDeclarationsForCC( f, q )
+FILE *f;
+Junction *q;
+#endif
+{
+ Junction *p = q;
+ int i;
+
+ fprintf(f, "private:\n");
+
+ /* Dump dflt handler declaration */
+ fprintf(f, "\tvoid zzdflthandlers( int _signal, int *_retsignal );\n\n");
+
+ fprintf(f, "public:\n");
+
+ /* Dump return value structs */
+ i = 1;
+ while ( p!=NULL )
+ {
+ if ( p->ret != NULL )
+ {
+/* MR23 */ if ( hasMultipleOperands(p->ret) )
+ {
+ DumpRetValStruct(f, p->ret, i);
+ }
+ }
+ i++;
+ p = (Junction *)p->p2;
+ }
+
+ /* Dump member func defs && CONSTRUCTOR */
+ fprintf(f, "\t%s(ANTLRTokenBuffer *input);\n", CurrentClassName);
+/*
+ fprintf(f, "\t%s(ANTLRTokenBuffer *input, ANTLRTokenType eof);\n",
+ CurrentClassName);
+*/
+
+ i = 1;
+ p = q;
+ while ( p!=NULL )
+ {
+ if ( p->ret != NULL )
+ {
+/* MR23 */ if ( hasMultipleOperands(p->ret) )
+ {
+ fprintf(f, "\tstruct _rv%d", i);
+ }
+ else
+ {
+ fprintf(f, "\t");
+ DumpType(p->ret, f);
+ }
+ fprintf(f, " %s%s(",RulePrefix,p->rname);
+ DumpANSIFunctionArgDef(f,p, 1 /* emit initializers ? */ );
+ fprintf(f, ";\n");
+#ifdef OLD
+ if ( p->pdecl != NULL || GenAST )
+ {
+ if ( GenAST ) fprintf(f, "ASTBase **%s",(p->pdecl!=NULL)?",":"");
+ if ( p->pdecl!=NULL ) fprintf(f, "%s", p->pdecl);
+ }
+ fprintf(f, ");\n");
+#endif
+ }
+ else
+ {
+ fprintf(f, "\tvoid %s%s(",RulePrefix,p->rname);
+ DumpANSIFunctionArgDef(f,p, 1 /* emit initializers ? */);
+ fprintf(f, ";\n");
+#ifdef OLD
+ if ( p->pdecl != NULL || GenAST )
+ {
+ if ( GenAST ) fprintf(f, "ASTBase **%s",(p->pdecl!=NULL)?",":"");
+ if ( p->pdecl!=NULL ) fprintf(f, "%s", p->pdecl);
+ }
+ fprintf(f, ");\n");
+#endif
+ }
+ i++;
+ p = (Junction *)p->p2;
+ }
+}
+
+/* Given a list of ANSI-style parameter declarations, print out a
+ * comma-separated list of the symbols (w/o types).
+ * Basically, we look for a comma, then work backwards until start of
+ * the symbol name. Then print it out until 1st non-alnum char. Now,
+ * move on to next parameter.
+ *
+ */
+
+/* MR5 Jan Mikkelsen 26-May-97 - added initalComma parameter */
+
+void
+#ifdef __USE_PROTOS
+DumpListOfParmNames(char *pdecl, FILE *output, int initialComma) /* MR5 */
+#else
+DumpListOfParmNames(pdecl, output, initialComma) /* MR5 */
+char *pdecl; /* MR5 */
+FILE *output; /* MR5 */
+int initialComma; /* MR5 */
+#endif
+{
+ int firstTime = 1, done = 0;
+ require(output!=NULL, "DumpListOfParmNames: NULL parm");
+
+ if ( pdecl == NULL ) return;
+ while ( !done )
+ {
+ if ( !firstTime || initialComma ) putc(',', output); /* MR5 */
+ done = DumpNextNameInDef(&pdecl, output);
+ firstTime = 0;
+ }
+}
+
+/* given a list of parameters or return values, dump the next
+ * name to output. Return 1 if last one just printed, 0 if more to go.
+ */
+
+/* MR23 Total rewrite */
+
+int
+#ifdef __USE_PROTOS
+DumpNextNameInDef( char **q, FILE *output )
+#else
+DumpNextNameInDef( q, output )
+char **q;
+FILE *output;
+#endif
+{
+ char *p;
+ char *t;
+ char *pDataType;
+ char *pSymbol;
+ char *pEqualSign;
+ char *pValue;
+ char *pSeparator;
+ int nest = 0;
+
+ p = endFormal(*q,
+ &pDataType,
+ &pSymbol,
+ &pEqualSign,
+ &pValue,
+ &pSeparator,
+ &nest);
+
+ /* MR26 Handle rule arguments such as: IIR_Bool (IIR_Decl::*contstraint)()
+ For this we need to strip off anything which follows the symbol.
+ */
+
+/* MR26 */ t = pSymbol;
+/* MR26 */ if (t != NULL) {
+/* MR26 */ for (t = pSymbol; *t != 0; t++) {
+/* MR26 */ if (! (isalpha(*t) || isdigit(*t) || *t == '_' || *t == '$')) break;
+/* MR26 */ }
+/* MR26 */ }
+/* MR26 */ fprintf(output,strBetween(pSymbol, t, pSeparator));
+
+ *q = p;
+ return (*pSeparator == 0);
+}
+
+/* Given a list of ANSI-style parameter declarations, dump K&R-style
+ * declarations, one per line for each parameter. Basically, convert
+ * comma to semi-colon, newline.
+ */
+void
+#ifdef __USE_PROTOS
+DumpOldStyleParms( char *pdecl, FILE *output )
+#else
+DumpOldStyleParms( pdecl, output )
+char *pdecl;
+FILE *output;
+#endif
+{
+ require(output!=NULL, "DumpOldStyleParms: NULL parm");
+
+ if ( pdecl == NULL ) return;
+ while ( *pdecl != '\0' )
+ {
+ if ( *pdecl == ',' )
+ {
+ pdecl++;
+ putc(';', output); putc('\n', output);
+ while ( *pdecl==' ' || *pdecl=='\t' || *pdecl=='\n' ) pdecl++;
+ }
+ else {putc(*pdecl, output); pdecl++;}
+ }
+ putc(';', output);
+ putc('\n', output);
+}
+
+/* Take in a type definition (type + symbol) and print out type only */
+/* MR23 Total rewrite */
+
+void
+#ifdef __USE_PROTOS
+DumpType( char *s, FILE *f )
+#else
+DumpType( s, f )
+char *s;
+FILE *f;
+#endif
+{
+ char *p;
+ char *pDataType;
+ char *pSymbol;
+ char *pEqualSign;
+ char *pValue;
+ char *pSeparator;
+ int nest = 0;
+
+ require(s!=NULL, "DumpType: invalid type string");
+
+ p = endFormal(s,
+ &pDataType,
+ &pSymbol,
+ &pEqualSign,
+ &pValue,
+ &pSeparator,
+ &nest);
+ fprintf(f,strBetween(pDataType, pSymbol, pSeparator));
+}
+
+/* check to see if string e is a word in string s */
+int
+#ifdef __USE_PROTOS
+strmember( char *s, char *e )
+#else
+strmember( s, e )
+char *s;
+char *e;
+#endif
+{
+ register char *p;
+ require(s!=NULL&&e!=NULL, "strmember: NULL string");
+
+ if ( *e=='\0' ) return 1; /* empty string is always member */
+ do {
+ while ( *s!='\0' && !isalnum(*s) && *s!='_' )
+ ++s;
+ p = e;
+ while ( *p!='\0' && *p==*s ) {p++; s++;}
+ if ( *p=='\0' ) {
+ if ( *s=='\0' ) return 1;
+ if ( !isalnum (*s) && *s != '_' ) return 1;
+ }
+ while ( isalnum(*s) || *s == '_' )
+ ++s;
+ } while ( *s!='\0' );
+ return 0;
+}
+
+#if 0
+
+/* MR23 Replaced by hasMultipleOperands() */
+
+int
+#ifdef __USE_PROTOS
+HasComma( char *s )
+#else
+HasComma( s )
+char *s;
+#endif
+{
+ while (*s!='\0')
+ if ( *s++ == ',' ) return 1;
+ return 0;
+}
+#endif
+
+
+/* MR23 Total rewrite */
+
+void
+#ifdef __USE_PROTOS
+DumpRetValStruct( FILE *f, char *ret, int i )
+#else
+DumpRetValStruct( f, ret, i )
+FILE *f;
+char *ret;
+int i;
+#endif
+{
+ char *p = ret;
+ char *pDataType;
+ char *pSymbol;
+ char *pEqualSign;
+ char *pValue;
+ char *pSeparator;
+ int nest = 0;
+
+ fprintf(f, "\nstruct _rv%d {\n", i);
+ while (*p != 0 && nest == 0) {
+ p = endFormal(p,
+ &pDataType,
+ &pSymbol,
+ &pEqualSign,
+ &pValue,
+ &pSeparator,
+ &nest);
+ fprintf(f,"\t");
+ fprintf(f,strBetween(pDataType, pSymbol, pSeparator));
+ fprintf(f," ");
+ fprintf(f,strBetween(pSymbol, pEqualSign, pSeparator));
+ fprintf(f,";\n");
+ }
+ fprintf(f,"};\n");
+}
+
+/* given "s" yield s -- DESTRUCTIVE (we modify s if starts with " else return s) */
+char *
+#ifdef __USE_PROTOS
+StripQuotes( char *s )
+#else
+StripQuotes( s )
+char *s;
+#endif
+{
+ if ( *s == '"' )
+ {
+ s[ strlen(s)-1 ] = '\0'; /* remove last quote */
+ return( s+1 ); /* return address past initial quote */
+ }
+ return( s );
+}
diff --git a/Source/Pccts/antlr/main.c b/Source/Pccts/antlr/main.c
new file mode 100644
index 0000000..051ee4e
--- /dev/null
+++ b/Source/Pccts/antlr/main.c
@@ -0,0 +1,1747 @@
+/*
+ * main.c -- main program for PCCTS ANTLR.
+ *
+ * SOFTWARE RIGHTS
+ *
+ * We reserve no LEGAL rights to the Purdue Compiler Construction Tool
+ * Set (PCCTS) -- PCCTS is in the public domain. An individual or
+ * company may do whatever they wish with source code distributed with
+ * PCCTS or the code generated by PCCTS, including the incorporation of
+ * PCCTS, or its output, into commerical software.
+ *
+ * We encourage users to develop software with PCCTS. However, we do ask
+ * that credit is given to us for developing PCCTS. By "credit",
+ * we mean that if you incorporate our source code into one of your
+ * programs (commercial product, research project, or otherwise) that you
+ * acknowledge this fact somewhere in the documentation, research report,
+ * etc... If you like PCCTS and have developed a nice tool with the
+ * output, please mention that you developed it using PCCTS. In
+ * addition, we ask that this header remain intact in our source code.
+ * As long as these guidelines are kept, we expect to continue enhancing
+ * this system and expect to make other tools available as they are
+ * completed.
+ *
+ * ANTLR 1.33
+ * Terence Parr
+ * Parr Research Corporation
+ * with Purdue University and AHPCRC, University of Minnesota
+ * 1989-2001
+ */
+
+/* To set a breakpoint just before exit look for "cleanUp". */
+/* To set a breakpoint for fatal error look for "fatal_intern" */
+
+#include <stdio.h>
+
+#include "pcctscfg.h"
+#include "stdpccts.h"
+
+#define MAX_INT_STACK 50
+static int istack[MAX_INT_STACK]; /* Int stack */
+static int isp = MAX_INT_STACK;
+
+static int DontAcceptFiles = 0; /* if stdin, don't read files */
+static int DontAcceptStdin = 0; /* if files seen first, don't accept stdin */
+
+static int tnodes_used_in_guard_predicates_etc; /* MR10 */
+
+ /* C m d - L i n e O p t i o n S t r u c t & F u n c s */
+
+typedef struct _Opt {
+ char *option;
+ int arg;
+#ifdef __cplusplus
+ void (*process)(...);
+#else
+ void (*process)();
+#endif
+ char *descr;
+ } Opt;
+
+#ifdef __USE_PROTOS
+extern void ProcessArgs(int, char **, Opt *);
+#else
+extern void ProcessArgs();
+#endif
+
+#ifdef __USE_PROTOS
+int ci_strequ(char *a,char *b)
+#else
+int ci_strequ(a,b)
+ char *a;
+ char *b;
+#endif
+{
+ for ( ;*a != 0 && *b != 0; a++, b++) {
+ if (toupper(*a) != toupper(*b)) return 0;
+ }
+ return (*a == *b);
+}
+
+static void
+#ifdef __USE_PROTOS
+pStdin( void )
+#else
+pStdin( )
+#endif
+{
+ if ( DontAcceptStdin )
+ {
+ warnNoFL("'-' (stdin) ignored as files were specified first");
+ return;
+ }
+
+ require(NumFiles<MaxNumFiles,"exceeded max # of input files");
+ FileStr[NumFiles++] = "stdin";
+ DontAcceptFiles = 1;
+}
+
+static void
+#ifdef __USE_PROTOS
+pFile( char *s )
+#else
+pFile( s )
+char *s;
+#endif
+{
+ if ( *s=='-' ) { warnNoFL( eMsg1("invalid option: '%s'",s) ); return; }
+ if ( DontAcceptFiles )
+ {
+ warnNoFL(eMsg1("file '%s' ignored as '-' (stdin option) was specified first",s));
+ return;
+ }
+
+ require(NumFiles<MaxNumFiles,"exceeded max # of input files");
+ FileStr[NumFiles++] = s;
+ DontAcceptStdin = 1;
+}
+
+/* MR14
+ Allow input to be a file containing a list of files
+ Bernard Giroud (b_giroud@decus.ch)
+*/
+
+static void
+#ifdef __USE_PROTOS
+pFileList( char *s, char *t )
+#else
+pFileList( s, t )
+char *s;
+char *t;
+#endif
+{
+#define MaxFLArea 1024
+ FILE *fl;
+ static char Fn_in_Fl[MaxFLArea] = "";
+ char one_fn[MaxFileName];
+ char *flp = &Fn_in_Fl[0];
+ int fnl, left = MaxFLArea, i;
+
+ if ( *t=='-' ) { warnNoFL( eMsg1("invalid option: '%s'",t) ); return; }
+ if ( DontAcceptFiles )
+ {
+ warnNoFL(eMsg1("file '%s' ignored as '-' (stdin option) was specified first",t));
+ return;
+ }
+
+ if ((fl = fopen(t, "r")) == NULL)
+ {
+ warnNoFL(eMsg1("file '%s' can't be opened", t));
+ return;
+ }
+ for (;;)
+ {
+ if (fgets(one_fn, 128 - 1, fl) == NULL)
+ break;
+ fnl = strlen(one_fn);
+ require(fnl<=left, "no more room in File List Area");
+ /* drop the trailing LF */
+ if (one_fn[fnl - 1] == 0x0a) one_fn[fnl - 1] = ' ';
+ strcat(Fn_in_Fl, one_fn);
+ left = left - fnl;
+ require(NumFiles<MaxNumFiles,"exceeded max # of input files");
+ FileStr[NumFiles++] = flp;
+ flp = flp + fnl;
+ }
+ fclose(fl);
+ for (i=0;i < MaxFLArea;i++) if (Fn_in_Fl[i] == ' ') Fn_in_Fl[i] = '\0';
+ DontAcceptStdin = 1;
+}
+
+static void
+#ifdef __USE_PROTOS
+pLLK( char *s, char *t )
+#else
+pLLK( s, t )
+char *s;
+char *t;
+#endif
+{
+ LL_k = atoi(t);
+ if ( LL_k <= 0 ) {
+ warnNoFL("must have at least one token of lookahead (setting to 1)");
+ LL_k = 1;
+ }
+}
+
+static void
+#ifdef __USE_PROTOS
+pCk( char *s, char *t )
+#else
+pCk( s, t )
+char *s;
+char *t;
+#endif
+{
+ CLL_k = atoi(t);
+ if ( CLL_k <= 0 ) {
+ warnNoFL("must have at least one token of look-ahead (setting to 1)");
+ CLL_k = 1;
+ }
+}
+
+static void /* MR6 */
+#ifdef __USE_PROTOS
+pTab( char *s, char *t ) /* MR6 */
+#else
+pTab( s, t ) /* MR6 */
+char *s; /* MR6 */
+char *t; /* MR6 */
+#endif
+{ /* MR6 */
+ TabWidth = atoi(t); /* MR6 */
+ if ( TabWidth < 0 || TabWidth > 8 ) { /* MR6 */
+ warnNoFL("tab width must be between 1 and 8"); /* MR6 */
+ TabWidth=0; /* MR6 */
+ } /* MR6 */
+} /* MR6 */
+
+static int ambAidDepthSpecified=0; /* MR11 */
+
+static void /* MR11 */
+#ifdef __USE_PROTOS
+pAAd( char *s, char *t ) /* MR11 */
+#else
+pAAd( s, t ) /* MR11 */
+char *s; /* MR11 */
+char *t; /* MR11 */
+#endif
+{ /* MR11 */
+ ambAidDepthSpecified=1; /* MR11 */
+ MR_AmbAidDepth = atoi(t); /* MR11 */
+} /* MR11 */
+
+static void /* MR11 */
+#ifdef __USE_PROTOS
+pTreport( char *s, char *t ) /* MR11 */
+#else
+pTreport( s, t ) /* MR11 */
+ char *s; /* MR11 */
+ char *t; /* MR11 */
+#endif
+{ /* MR11 */
+ TnodesReportThreshold = atoi(t); /* MR11 */
+} /* MR11 */
+
+#ifdef __USE_PROTOS
+void chkGTFlag(void) /* 7-Apr-97 MR1 */
+#else
+void chkGTFlag() /* 7-Apr-97 MR1 */
+#endif
+{
+ if ( !GenAST )
+ warn("#-variable or other AST item referenced w/o -gt option");
+}
+
+
+#ifdef __USE_PROTOS
+static void pInfo(char *s, char *t) /* MR10 */
+#else
+static void pInfo(s,t) /* MR10 */
+ char *s;
+ char *t;
+#endif
+{
+ char *p;
+ int q;
+ for (p=t; *p != 0; p++) {
+ q=tolower(*p);
+ if (q=='t') {
+ InfoT=1;
+ } else if (q=='p') {
+ InfoP=1;
+ } else if (q=='m') {
+ InfoM=1;
+ } else if (q=='o') {
+ InfoO=1;
+ } else if (q=='0') {
+ ; /* nothing */
+ } else if (q=='f') {
+ InfoF=1;
+ } else {
+ warnNoFL(eMsgd("unrecognized -info option \"%c\"",(int)*p));
+ };
+ };
+}
+
+#ifdef __USE_PROTOS
+static void pCGen(void) { CodeGen = FALSE; LexGen = FALSE; }
+static void pLGen(void) { LexGen = FALSE; }
+static void pXTGen(void){ MR_Inhibit_Tokens_h_Gen = TRUE; }
+static void pTGen(void) { TraceGen = TRUE; }
+static void pSGen(void) { GenExprSetsOpt = FALSE; }
+static void pPrt(void) { PrintOut = TRUE; pCGen(); pLGen(); }
+static void pPrtA(void) { PrintOut = TRUE; PrintAnnotate = TRUE; pCGen(); pLGen(); }
+static void pAst(void) { GenAST = TRUE; }
+static void pANSI(void) { GenANSI = TRUE; }
+static void pCr(void) { GenCR = TRUE; }
+static void pNOPURIFY(void) { PURIFY = FALSE; }
+/*static void pCt(void) { warnNoFL("-ct option is now the default"); }*/
+static void pLI(void) { GenLineInfo = TRUE; GenLineInfoMS = FALSE; } /* MR14 */
+static void pLIms(void) { GenLineInfo = TRUE; GenLineInfoMS = TRUE; } /* MR14 */
+static void pFr(char *s, char *t) {RemapFileName = t;}
+static void pFe(char *s, char *t) {ErrFileName = t;}
+static void pFl(char *s, char *t) {DlgFileName = t;}
+static void pFm(char *s, char *t) {ModeFileName = t;}
+static void pFt(char *s, char *t) {DefFileName = t;}
+
+static void pE1(void) { elevel = 1; }
+static void pE2(void) { elevel = 2; }
+static void pE3(void) { elevel = 3; }
+static void pEGen(void) { GenEClasseForRules = 1; }
+static void pDL(void)
+ {
+ DemandLookahead = 1;
+ if ( GenCC ) {
+ warnNoFL("-gk does not work currently in C++ mode; -gk turned off");
+ DemandLookahead = 0;
+ }
+ }
+
+static void pAA(char *s,char *t) {MR_AmbAidRule = t;} /* MR11 */
+static void pAAm(char *s){MR_AmbAidMultiple = 1;} /* MR11 */
+static void pGHdr(void) { GenStdPccts = 1; }
+static void pFHdr(char *s, char *t) { stdpccts = t; pGHdr(); }
+static void pW1(void) { WarningLevel = 1; }
+static void pNewAST(void) { NewAST = 1; } /* MR13 */
+static void ptmakeInParser(void) { tmakeInParser = 1; } /* MR23 */
+static void pAlpha(void) { AlphaBetaTrace = 1; } /* MR14 */
+static void pMR_BlkErr(void) { MR_BlkErr = 1; } /* MR21 */
+static void pStdout(void) {UseStdout = 1; } /* MR6 */
+static void pW2(void) { WarningLevel = 2; }
+static void pCC(void) { GenCC = TRUE; }
+#else
+static void pCGen() { CodeGen = FALSE; LexGen = FALSE; }
+static void pLGen() { LexGen = FALSE; }
+static void pXTGen(){ MR_Inhibit_Tokens_h_Gen = TRUE; } /* MR14 */
+static void pTGen() { TraceGen = TRUE; }
+static void pSGen() { GenExprSetsOpt = FALSE; }
+static void pPrt() { PrintOut = TRUE; pCGen(); pLGen(); }
+static void pPrtA() { PrintOut = TRUE; PrintAnnotate = TRUE; pCGen(); pLGen(); }
+static void pAst() { GenAST = TRUE; }
+static void pANSI() { GenANSI = TRUE; }
+static void pCr() { GenCR = TRUE; }
+static void pNOPURIFY() { PURIFY = FALSE; }
+
+/*static void pCt() { warnNoFL("-ct option is now the default"); }*/
+static void pLI() { GenLineInfo = TRUE; GenLineInfoMS = FALSE; } /* MR14 */
+static void pLIms() { GenLineInfo = TRUE; GenLineInfoMS = TRUE; } /* MR14 */
+static void pFr(s,t) char *s, *t; {RemapFileName = t;}
+static void pFe(s,t) char *s, *t; {ErrFileName = t;}
+static void pFl(s,t) char *s, *t; {DlgFileName = t;}
+static void pFm(s,t) char *s, *t; {ModeFileName = t;}
+static void pFt(s,t) char *s, *t; {DefFileName = t;}
+
+static void pE1() { elevel = 1; }
+static void pE2() { elevel = 2; }
+static void pE3() { elevel = 3; }
+static void pEGen() { GenEClasseForRules = 1; }
+static void pDL()
+ {
+ DemandLookahead = 1;
+ if ( GenCC ) {
+ warnNoFL("-gk does not work currently in C++ mode; -gk turned off");
+ DemandLookahead = 0;
+ }
+ }
+
+static void pAA(s,t) char *s; char *t; {MR_AmbAidRule = t;} /* MR11 BJS 20-Mar-98 */
+static void pAAm(s) char *s; {MR_AmbAidMultiple = 1;} /* MR11 BJS 20-Mar-98 */
+static void pGHdr() { GenStdPccts = 1; }
+static void pFHdr(s,t) char *s, *t; { stdpccts = t; pGHdr(); }
+static void pW1() { WarningLevel = 1; }
+static void pNewAST() { NewAST = 1; } /* MR13 */
+static void ptmakeInParser() { tmakeInParser = 1; } /* MR23 */
+static void pAlpha() { AlphaBetaTrace = 1; } /* MR14 */
+static void pMR_BlkErr() { MR_BlkErr = 1; } /* MR21 */
+static void pStdout() {UseStdout = 1; } /* MR6 */
+static void pW2() { WarningLevel = 2; }
+static void pCC() { GenCC = TRUE; }
+#endif
+
+static void
+#ifdef __USE_PROTOS
+pPre( char *s, char *t )
+#else
+pPre( s, t )
+char *s;
+char *t;
+#endif
+{
+ RulePrefix = t;
+}
+
+static void
+#ifdef __USE_PROTOS
+pOut( char *s, char *t )
+#else
+pOut( s, t )
+char *s;
+char *t;
+#endif
+{
+ OutputDirectory = t;
+}
+
+static void
+#ifdef __USE_PROTOS
+pPred( void )
+#else
+pPred( )
+#endif
+{
+ warnNoFL("-pr is no longer used (predicates employed if present); see -prc, -mrhoist, -mrhoistk");
+/*
+** if ( DemandLookahead )
+** warnNoFL("-gk conflicts with -pr; -gk turned off");
+** DemandLookahead = 0;
+** HoistPredicateContext = 0;
+*/
+}
+
+static void
+#ifdef __USE_PROTOS
+pPredCtx( char *s, char *t )
+#else
+pPredCtx(s,t)
+char *s;
+char *t;
+#endif
+{
+ if ( ci_strequ(t,"on")) HoistPredicateContext = 1;
+ else if ( ci_strequ(t,"off")) HoistPredicateContext = 0;
+ if ( DemandLookahead )
+ {
+ warnNoFL("-gk incompatible with semantic predicate usage; -gk turned off");
+ DemandLookahead = 0;
+ }
+}
+
+static void
+#ifdef __USE_PROTOS
+pMRhoist( char *s, char *t )
+#else
+pMRhoist(s,t)
+char *s;
+char *t;
+#endif
+{
+ if ( ci_strequ(t,"on")) MRhoisting = 1;
+ else if ( ci_strequ(t,"off")==0 ) MRhoisting = 0;
+ if (MRhoisting) {
+ fprintf(stderr,"Maintenance Release style hoisting enabled for predicates with lookahead depth = 1\n");
+ fprintf(stderr," No longer considered experimental\n");
+ fprintf(stderr," Can't consider suppression for predicates with lookahead depth > 1\n");
+ fprintf(stderr," Implies -prc on but does *not* imply -mrhoistk for k>1 predicates\n");
+ fprintf(stderr," This is a reminder, not a warning or error.\n");
+ };
+}
+
+static void
+#ifdef __USE_PROTOS
+pMRhoistk( char *s, char *t )
+#else
+pMRhoistk(s,t)
+char *s;
+char *t;
+#endif
+{
+ if ( ci_strequ(t,"on")) MRhoistingk = 1;
+ else if ( ci_strequ(t,"off")==0 ) MRhoistingk = 0;
+ if (MRhoistingk) {
+ fprintf(stderr,"EXPERIMENTAL Maintenance Release style hoisting enabled\n");
+ fprintf(stderr," Applies to predicates with lookahead depth > 1\n");
+ fprintf(stderr," Implies -prc on and -mrhoist on\n");
+ };
+}
+
+static void
+#ifdef __USE_PROTOS
+pTRes( char *s, char *t )
+#else
+pTRes( s, t )
+char *s;
+char *t;
+#endif
+{
+ TreeResourceLimit = atoi(t);
+ if ( TreeResourceLimit <= 0 )
+ {
+ warnNoFL("analysis resource limit (# of tree nodes) must be greater than 0");
+ TreeResourceLimit = -1; /* set to no limit */
+ }
+}
+
+Opt options[] = {
+#ifdef __cplusplus
+ { "-CC", 0, (void (*)(...)) pCC, "Generate C++ output (default=FALSE)"},
+ { "-ck", 1, (void (*)(...)) pCk, "Set compressed lookahead depth; fast approximate lookahead"},
+ { "-cr", 0, (void (*)(...)) pCr, "Generate cross reference (default=FALSE)"},
+ { "-e1", 0, (void (*)(...)) pE1, "Ambiguities/errors shown in low detail (default)"},
+ { "-e2", 0, (void (*)(...)) pE2, "Ambiguities/errors shown in more detail"},
+ { "-e3", 0, (void (*)(...)) pE3,
+ "Ambiguities for k>1 grammars shown with exact tuples (not lookahead sets)"},
+ { "-f", 1, (void (*)(...)) pFileList,"Read names of grammar files from specified file"}, /* MR14 */
+ { "-fe", 1, (void (*)(...)) pFe, "Rename err.c"},
+ { "-fh", 1, (void (*)(...)) pFHdr, "Rename stdpccts.h header (turns on -gh)"},
+ { "-fl", 1, (void (*)(...)) pFl, "Rename lexical output--parser.dlg"},
+ { "-fm", 1, (void (*)(...)) pFm, "Rename mode.h"},
+ { "-fr", 1, (void (*)(...)) pFr, "Rename remap.h"},
+ { "-ft", 1, (void (*)(...)) pFt, "Rename tokens.h"},
+ { "-ga", 0, (void (*)(...)) pANSI, "Generate ANSI-compatible code (default=FALSE)"},
+ { "-gc", 0, (void (*)(...)) pCGen, "Do not generate output parser code (default=FALSE)"},
+ { "-gd", 0, (void (*)(...)) pTGen, "Generate code to trace rule invocation (default=FALSE)"},
+ { "-ge", 0, (void (*)(...)) pEGen, "Generate an error class for each non-terminal (default=FALSE)"},
+ { "-gh", 0, (void (*)(...)) pGHdr, "Generate stdpccts.h for non-ANTLR-generated-files to include"},
+ { "-gk", 0, (void (*)(...)) pDL, "Generate parsers that delay lookahead fetches until needed"},
+ { "-gl", 0, (void (*)(...)) pLI, "Generate line info about grammar actions in parser"},
+ { "-glms", 0, (void (*)(...)) pLIms,"Like -gl but replace '\\' with '/' in #line filenames for MS C/C++ systems"},
+ { "-gp", 1, (void (*)(...)) pPre, "Prefix all generated rule functions with a string"},
+ { "-gs", 0, (void (*)(...)) pSGen, "Do not generate sets for token expression lists (default=FALSE)"},
+ { "-gt", 0, (void (*)(...)) pAst, "Generate code for Abstract-Syntax-Trees (default=FALSE)"},
+ { "-gx", 0, (void (*)(...)) pLGen, "Do not generate lexical (dlg-related) files (default=FALSE)"},
+ { "-gxt",0, (void (*)(...)) pXTGen, "Do not generate tokens.h (default=FALSE)"},
+ { "-k", 1, (void (*)(...)) pLLK, "Set full LL(k) lookahead depth (default==1)"},
+ { "-o", 1, (void (*)(...)) pOut, OutputDirectoryOption},
+ { "-p", 0, (void (*)(...)) pPrt, "Print out the grammar w/o actions (default=no)"},
+ { "-pa", 0, (void (*)(...)) pPrtA, "Print out the grammar w/o actions & w/FIRST sets (default=no)"},
+ { "-pr",0, (void (*)(...)) pPred, "no longer used; predicates employed if present"},
+ { "-prc", 1, (void (*)(...)) pPredCtx,"Turn on/off computation of context for hoisted predicates"},
+ { "-rl", 1, (void (*)(...)) pTRes, "Limit max # of tree nodes used by grammar analysis"},
+ { "-stdout",0, (void (*)(...)) pStdout,"Send grammar.c/grammar.cpp to stdout"}, /* MR6 */
+ { "-tab", 1, (void (*)(...)) pTab, "Width of tabs (1 to 8) for grammar.c/grammar.cpp files"}, /* MR6 */
+ { "-w1", 0, (void (*)(...)) pW1, "Set the warning level to 1 (default)"},
+ { "-w2", 0, (void (*)(...)) pW2, "Ambiguities yield warnings even if predicates or (...)? block"},
+ { "-", 0, (void (*)(...)) pStdin, "Read grammar from stdin" },
+ { "-mrhoist",1, (void (*)(...)) pMRhoist, /* MR9 */
+ "Turn on/off k=1 Maintenance Release style hoisting"}, /* MR9 */
+ { "-mrhoistk",1, (void (*)(...)) pMRhoistk, /* MR9 */
+ "Turn on/off EXPERIMENTAL k>1 Maintenance Release style hoisting"}, /* MR13 */
+ { "-aa" , 1, (void (*)(...)) pAA, "Ambiguity aid for a rule (rule name or line number)"}, /* MR11 */
+ { "-aam" , 0, (void (*)(...)) pAAm,
+ "Lookahead token may appear multiple times in -aa listing"}, /* MR11 */
+ { "-aad" , 1, (void (*)(...)) pAAd,
+ "Limits exp growth of -aa listing - default=1 (max=ck value)"}, /* MR11 */
+ { "-info", 1, (void (*)(...)) pInfo,
+ "Extra info: p=pred t=tnodes f=first/follow m=monitor o=orphans 0=noop"}, /* MR12 */
+ { "-treport",1,(void (*)(...)) pTreport,
+ "Report when tnode usage exceeds value during ambiguity resolution"}, /* MR11 */
+ { "-newAST", 0, (void (*)(...)) pNewAST,
+ "In C++ mode use \"newAST(...)\" rather than \"new AST(...)\""}, /* MR13 */
+ { "-tmake", 0, (void (*)(...)) ptmakeInParser,
+ "In C++ mode use parser's tmake method rather than \"ASTBase::tmake(...)\""}, /* MR23 */
+ { "-alpha",0,(void (*)(...)) pAlpha,
+ "Provide additional information for \"(alpha)? beta\" error messages"}, /* MR14 */
+ { "-mrblkerr",0,(void (*)(...)) pMR_BlkErr, /* MR21 */
+ "EXPERIMENTAL change to (...)* and (...)+ syntax error sets"}, /* MR21 */
+ { "-nopurify",0,(void (*)(...)) pNOPURIFY,
+ "Don't use the notorious PURIFY macro (replaced by MR23 initial value syntax) to zero return arguments of rules"}, /* MR23 */
+ { "*", 0, (void (*)(...)) pFile, "" }, /* anything else is a file */
+#else
+ { "-CC", 0, pCC, "Generate C++ output (default=FALSE)"},
+ { "-cr", 0, pCr, "Generate cross reference (default=FALSE)"},
+ { "-ck", 1, pCk, "Set compressed lookahead depth; fast approximate lookahead"},
+ { "-e1", 0, pE1, "Ambiguities/errors shown in low detail (default)"},
+ { "-e2", 0, pE2, "Ambiguities/errors shown in more detail"},
+ { "-e3", 0, pE3, "Ambiguities for k>1 grammars shown with exact tuples (not lookahead sets)"},
+ { "-f", 1, pFileList,"Read names of grammar files from specified file"}, /* MR14 */
+ { "-fe", 1, pFe, "Rename err.c"},
+ { "-fh", 1, pFHdr, "Rename stdpccts.h header (turns on -gh)"},
+ { "-fl", 1, pFl, "Rename lexical output--parser.dlg"},
+ { "-fm", 1, pFm, "Rename mode.h"},
+ { "-fr", 1, pFr, "Rename remap.h"},
+ { "-ft", 1, pFt, "Rename tokens.h"},
+ { "-ga", 0, pANSI, "Generate ANSI-compatible code (default=FALSE)"},
+ { "-gc", 0, pCGen, "Do not generate output parser code (default=FALSE)"},
+ { "-gd", 0, pTGen, "Generate code to trace rule invocation (default=FALSE)"},
+ { "-ge", 0, pEGen, "Generate an error class for each non-terminal (default=FALSE)"},
+ { "-gh", 0, pGHdr, "Generate stdpccts.h for non-ANTLR-generated-files to include"},
+ { "-gk", 0, pDL, "Generate parsers that delay lookahead fetches until needed"},
+ { "-gl", 0, pLI, "Generate line info about grammar actions in C parser"},
+ { "-glms", 0, pLIms,"Like -gl but replace '\\' with '/' in #line filenames for MS C/C++ systems"},
+ { "-gp", 1, pPre, "Prefix all generated rule functions with a string"},
+ { "-gs", 0, pSGen, "Do not generate sets for token expression lists (default=FALSE)"},
+ { "-gt", 0, pAst, "Generate code for Abstract-Syntax-Trees (default=FALSE)"},
+ { "-gx", 0, pLGen, "Do not generate lexical (dlg-related) files (default=FALSE)"},
+ { "-gxt",0, pXTGen, "Do not generate tokens.h (default=FALSE)"},
+ { "-k", 1, pLLK, "Set full LL(k) lookahead depth (default==1)"},
+ { "-o", 1, pOut, OutputDirectoryOption},
+ { "-p", 0, pPrt, "Print out the grammar w/o actions (default=no)"},
+ { "-pa", 0, pPrtA, "Print out the grammar w/o actions & w/FIRST sets (default=no)"},
+ { "-pr",0, pPred, "no longer used; predicates employed if present"},
+ { "-prc", 1, pPredCtx,"Turn on/off computation of context for hoisted predicates"},
+ { "-rl", 1, pTRes, "Limit max # of tree nodes used by grammar analysis"},
+ { "-stdout",0, pStdout, "Send grammar.c/grammar.cpp to stdout"}, /* MR6 */
+ { "-tab", 1, pTab, "Width of tabs (1 to 8) for grammar.c/grammar.cpp files"}, /* MR6 */
+ { "-w1", 0, pW1, "Set the warning level to 1 (default)"},
+ { "-w2", 0, pW2, "Ambiguities yield warnings even if predicates or (...)? block"},
+ { "-mrhoist",1,pMRhoist, /* MR9 */
+ "Turn on/off k=1 Maintenance Release style hoisting"}, /* MR9 */
+ { "-mrhoistk",1,pMRhoistk, /* MR13 */
+ "Turn on/off k>1 EXPERIMENTAL Maintenance Release style hoisting"}, /* MR13 */
+ { "-aa" ,1,pAA, "Ambiguity aid for a rule (rule name or line number)"}, /* MR11 */
+ { "-aam" ,0,pAAm,
+ "Lookahead token may appear multiple times in -aa listing"}, /* MR11 */
+ { "-aad" ,1,pAAd,
+ "Limits exp growth of -aa listing - default=1 (max=ck value)"}, /* MR11 */
+ { "-info",1,pInfo,
+ "Extra info: p=pred t=tnodes f=first/follow m=monitor o=orphans 0=noop"}, /* MR11 */
+ { "-treport",1,pTreport,
+ "Report when tnode usage exceeds value during ambiguity resolution"}, /* MR11 */
+ { "-newAST", 0, pNewAST,
+ "In C++ mode use \"newAST(...)\" rather than \"new AST(...)\""}, /* MR13 */
+ { "-tmake", 0, ptmakeInParser,
+ "In C++ mode use parser's tmake method rather than \"ASTBase::tmake(...)\""}, /* MR23 */
+ { "-alpha",0, pAlpha,
+ "Provide additional information for \"(alpha)? beta\" error messages"}, /* MR14 */
+ { "-mrblkerr",0,pMR_BlkErr, /* MR21 */
+ "EXPERIMENTAL change to (...)* and (...)+ syntax error sets"}, /* MR21 */
+ { "-nopurify",0,pNOPURIFY,
+ "Don't use the notorious PURIFY macro (replaced by MR23 initial value syntax) to zero return arguments of rules"}, /* MR23 */
+ { "-", 0, pStdin, "Read grammar from stdin" },
+ { "*", 0, pFile, "" }, /* anything else is a file */
+#endif
+ { NULL, 0, NULL }
+ };
+
+void readDescr();
+void cleanUp();
+
+#ifdef __USE_PROTOS
+static void buildRulePtr( void );
+static void help( void );
+static void init( void );
+static void CompleteTokenSetRefs( void );
+static void ensure_no_C_file_collisions(char *);
+static void CompleteContextGuards(void);
+#else
+static void buildRulePtr( );
+static void help( );
+static void init( );
+static void CompleteTokenSetRefs( );
+static void ensure_no_C_file_collisions();
+static void CompleteContextGuards();
+#endif
+
+static void
+#ifdef __USE_PROTOS /* <BJS> */
+report_numericPredLabels(ActionNode *a)
+#else
+report_numericPredLabels(a)
+ActionNode *a;
+#endif
+{ /* MR10 */
+ warnFL("numeric references to attributes (e.g. $i or $i.j) in semantic pred will be null during guess mode", /* MR10 */
+ FileStr[a->file],a->line); /* MR10 */
+} /* MR10 */
+
+ /* M a i n */
+
+int
+#ifdef __USE_PROTOS
+main( int argc, char *argv[] )
+#else
+main( argc, argv )
+int argc;
+char *argv[];
+#endif
+{
+ int i;
+ static char EPSTR[] = "[Ep]";
+
+ Save_argc=argc; /* MR10 */
+ Save_argv=argv; /* MR10 */
+
+/* malloc_debug(8);*/
+
+#ifdef SPECIAL_INITS
+ special_inits(); /* MR1 */
+#endif
+ fprintf(stderr, "Antlr parser generator Version %s 1989-2001\n", Version);
+ if ( argc == 1 ) { help(); zzDIE; }
+ ProcessArgs(argc-1, &(argv[1]), options);
+
+/* MR14 */ if (MR_AmbAidRule && AlphaBetaTrace) {
+/* MR14 */ fatal("Can't specify both -aa (ambiguity aid) and -alpha (\"(alpha)? beta\" aid)");
+/* MR14 */ }
+
+ if (MRhoistingk) { /* MR13 */
+ HoistPredicateContext=1; /* MR13 */
+ MRhoisting=1; /* MR13 */
+ }; /* MR13 */
+ if (MRhoisting && ! HoistPredicateContext) {
+/*** warnNoFL("Using \"-mrhoist\" forces \"-prc on\""); ***/
+ HoistPredicateContext=1;
+ };
+ if (HoistPredicateContext && ! MRhoisting) {
+ warnNoFL("When using predicate context (-prc on) -mrhoist on is recommended");
+ }
+ /* Fix lookahead depth */
+ /* Compressed lookahead must always be larger than or equal to full lookahead */
+ if ( CLL_k < LL_k && CLL_k>0 )
+ {
+ warnNoFL("must have compressed lookahead >= full LL(k) lookahead (setting -ck to -k)");
+ CLL_k = LL_k;
+ }
+ if ( CLL_k == -1 ) CLL_k = LL_k;
+ OutputLL_k = CLL_k;
+ if ( ((CLL_k-1)&CLL_k)!=0 ) { /* output ll(k) must be power of 2 */
+ int n;
+ for(n=1; n<CLL_k; n<<=1) {;}
+ OutputLL_k = n;
+ };
+
+ if (MR_BlkErr) {
+ warnNoFL("The -mrblkerr option is EXPERIMENTAL");
+ if (LL_k > 1) {
+ warnNoFL("The -mrblkerr option is designed only for k=1 ck=1 grammars");
+ }
+ };
+
+ if ( ! ambAidDepthSpecified) {
+ MR_AmbAidDepth=1;
+ } else {
+ if (MR_AmbAidDepth > CLL_k || MR_AmbAidDepth <= 0) {
+ warnNoFL(eMsgd(
+ "Ambiguity aid depth (\"-aad ...\") must be a number between 1 and max(k,ck)=%d",CLL_k));
+ MR_AmbAidDepth=1;
+ };
+ if (MR_AmbAidDepth == 0) {
+ MR_AmbAidDepth=2;
+ };
+ };
+
+ if (MR_AmbAidRule != NULL) MR_AmbAidLine=atoi(MR_AmbAidRule);
+
+ fpTrans = &(C_Trans[0]); /* Translate to C Language */
+ fpJTrans = &(C_JTrans[0]);
+ init();
+ lexclass(LexStartSymbol);
+
+ readDescr();
+ LastTokenCounted = TokenNum;
+ RemapForcedTokens();
+ if ( CannotContinue ) {cleanUp(); zzDIE;}
+ if ( GenCC && no_classes_found ) fatal("required grammar class not found (exiting...)");
+ if ( WarningLevel>1 && HdrAction == NULL )
+ warnNoFL("no #header action was found");
+ if ( FoundAtOperator && ! FoundExceptionGroup) {
+ warnNoFL("found the exception operator '@' - but no exception group was found");
+ };
+ EpToken = addTname(EPSTR); /* add imaginary token epsilon */
+ set_orel(EpToken, &imag_tokens);
+
+ /* this won't work for hand-built scanners since EofToken is not
+ * known. Forces EOF to be token type 1.
+ */
+ set_orel(EofToken, &imag_tokens);
+
+ set_size(NumWords(TokenNum-1));
+
+ /* compute the set of all known token types
+ * It represents the set of tokens from 1 to last_token_num + the
+ * reserved positions above that (if any). Don't include the set of
+ * imaginary tokens such as the token/error classes or EOF.
+ */
+ {
+ set a;
+ a = set_dup(reserved_positions);
+ for (i=1; i<TokenNum; i++) { set_orel(i, &a); }
+ all_tokens = set_dif(a, imag_tokens);
+ set_free(a);
+ }
+
+ ComputeTokSets(); /* Compute #tokclass sets */
+ CompleteTokenSetRefs(); /* Change complex nodes in syn diag */
+ CompleteContextGuards(); /* MR13 */
+
+ if ( CodeGen ) genDefFile(); /* create tokens.h */
+ if ( LexGen ) genLexDescr(); /* create parser.dlg */
+
+ if ( GenStdPccts )
+ {
+ FILE *f = fopen(OutMetaName(stdpccts), "w");
+ if ( f==NULL ) {warnNoFL( eMsg1("can't create %s",OutMetaName(stdpccts)) );}
+ else
+ {
+#ifdef SPECIAL_FOPEN
+ special_fopen_actions(OutMetaName(stdpccts)); /* MR1 */
+#endif
+ if (strcmp(stdpccts,"stdpccts.h") == 0) { /* MR10 */
+ genStdPCCTSIncludeFile(f,NULL); /* MR10 */
+ } else { /* MR10 */
+ genStdPCCTSIncludeFile(f,pcctsBaseName(stdpccts)); /* MR32 */
+ };
+ fclose(f);
+ }
+ }
+
+ buildRulePtr(); /* create mapping from rule # to RuleBlk junction */
+ ComputeErrorSets();
+ FoLink( (Node *)SynDiag ); /* add follow links to end of all rules */
+
+ if ( GenCR ) GenCrossRef( SynDiag );
+
+ if ( CodeGen )
+ {
+ if ( SynDiag == NULL )
+ {
+ warnNoFL("no grammar description recognized");
+ cleanUp();
+ zzDIE;
+ }
+ else if ( !GenCC ) {
+ ErrFile = fopen(OutMetaName(ErrFileName), "w");
+ require(ErrFile != NULL, "main: can't open err file");
+#ifdef SPECIAL_FOPEN
+ special_fopen_actions(OutMetaName(ErrFileName)); /* MR1 */
+#endif
+ NewSetWd();
+ GenErrHdr();
+ TRANS(SynDiag); /* Translate to the target language */
+ DumpSetWd();
+ DumpRemainingTokSets();
+ fclose( ErrFile );
+ }
+ else {
+ strcpy(Parser_h_Name, CurrentClassName);
+ strcat(Parser_h_Name, ".h");
+ strcpy(Parser_c_Name, CurrentClassName);
+ strcat(Parser_c_Name, CPP_FILE_SUFFIX);
+ ensure_no_C_file_collisions(Parser_c_Name);
+ Parser_h = fopen(OutMetaName(Parser_h_Name), "w");
+ require(Parser_h != NULL, "main: can't open class Parserx.h file");
+#ifdef SPECIAL_FOPEN
+ special_fopen_actions(OutMetaName(Parser_h_Name)); /* MR1 */
+#endif
+ Parser_c = fopen(OutMetaName(Parser_c_Name), "w");
+ require(Parser_c != NULL, "main: can't open class Parserx.c file");
+#ifdef SPECIAL_FOPEN
+ special_fopen_actions(OutMetaName(Parser_c_Name)); /* MR1 */
+#endif
+ GenParser_h_Hdr();
+ if ( class_before_actions != NULL )
+ {
+ ListNode *p;
+ for (p = class_before_actions->next; p!=NULL; p=p->next)
+ {
+ UserAction *ua = (UserAction *)p->elem;
+ dumpAction( ua->action, Parser_h, 0, ua->file, ua->line, 1);
+ }
+ }
+ GenParser_c_Hdr();
+ fprintf(Parser_h, "protected:\n"); /* MR20 */
+ NewSetWd();
+ TRANS(SynDiag); /* Translate to the target language */
+ DumpSetWd();
+ GenRuleMemberDeclarationsForCC(Parser_h, SynDiag);
+ if ( class_after_actions != NULL )
+ {
+ ListNode *p;
+ for (p = class_after_actions->next; p!=NULL; p=p->next)
+ {
+ UserAction *ua = (UserAction *)p->elem;
+ dumpAction( ua->action, Parser_h, 0, ua->file, ua->line, 1);
+ }
+ }
+ DumpRemainingTokSets();
+ fprintf(Parser_h, "};\n");
+ fprintf(Parser_h, "\n#endif /* %s_h */\n", CurrentClassName);
+ fclose( Parser_h );
+ fclose( Parser_c );
+ }
+ }
+
+ MR_orphanRules(stderr);
+ if (LTinTokenAction && WarningLevel >= 2) {
+ if (GenCC) {
+ warnNoFL("At least one <<action>> following a token match contains a reference to LT(...)\n this will reference the immediately preceding token,\n not the one which follows as is the case with semantic predicates.");
+ }
+ warnNoFL("At least one <<action>> following a token match contains a reference to LA(...) or LATEXT(...)\n this will reference the immediately preceding token,\n not the one which follows as is the case with semantic predicates.");
+ }
+
+ if ( PrintOut )
+ {
+ if ( SynDiag == NULL ) {warnNoFL("no grammar description recognized");}
+ else PRINT(SynDiag);
+ }
+
+#ifdef DBG_LL1
+#endif
+ GenRemapFile(); /* create remap.h */
+/* MR10 */ if (FoundGuessBlk) {
+#ifdef __cplusplus__
+/* MR10 */ list_apply(NumericPredLabels, (void (*)(void *))report_numericPredLabels);
+#else
+#ifdef __USE_PROTOS
+/* MR10 */ list_apply(NumericPredLabels, (void (*)(void *))report_numericPredLabels);
+#else
+/* MR10 */ list_apply(NumericPredLabels,report_numericPredLabels);
+#endif
+#endif
+/* MR10 */ };
+
+ if (InfoT && TnodesAllocated > 0) {
+ if (TnodesPeak > 10000) {
+ fprintf(stdout,"\nTree Nodes: peak %dk created %dk lost %d\n",
+ (TnodesPeak/1000),
+ (TnodesAllocated/1000),
+ TnodesInUse-tnodes_used_in_guard_predicates_etc);
+ } else {
+ fprintf(stdout,"\nTree Nodes: peak %d created %d lost %d\n",
+ TnodesPeak,
+ TnodesAllocated,
+ TnodesInUse-tnodes_used_in_guard_predicates_etc);
+ };
+ };
+ if (InfoF) {
+ DumpFcache();
+ };
+ if (MR_skipped_e3_report) {
+ fprintf(stderr,"note: use -e3 to get exact information on ambiguous tuples\n");
+ };
+ if (MR_BadExprSets != 0) {
+ fprintf(stderr,"note: Unreachable C or C++ code was generated for empty expression sets,\n");
+ fprintf(stderr," probably due to undefined rules or infinite left recursion.\n");
+ fprintf(stderr," To locate: search the generated code for \"empty set expression\"\n");
+ };
+ if (MR_AmbAidRule != NULL && MR_matched_AmbAidRule==0) {
+ RuleEntry *q = (RuleEntry *) hash_get(Rname,MR_AmbAidRule);
+ if (MR_AmbAidLine == 0 && q == NULL) {
+ warnNoFL(eMsg2("there is no rule \"%s\" so \"-aa %s\" will never match",
+ MR_AmbAidRule,MR_AmbAidRule));
+ } else {
+ warnNoFL(eMsg1("there was no ambiguity that matched \"-aa %s\"",MR_AmbAidRule));
+ };
+ };
+ if (AlphaBetaTrace) {
+
+ if (MR_AlphaBetaMessageCount == 0) {
+ fprintf(stderr,"note: there were no messages about \"(alpha)? beta\" blocks added to the generated code\n");
+ } else {
+ fprintf(stderr,"note: there were %d messages about \"(alpha)? beta\" blocks added to the generated code\n",
+ MR_AlphaBetaMessageCount);
+ }
+
+ if (set_null(MR_CompromisedRules)) {
+ fprintf(stderr,"note: the list of rules with compromised follow sets is empty\n");
+ } else {
+ fprintf(stderr,"note: the following is a list of rules which *may* have incorrect\n");
+ fprintf(stderr," follow sets computed as a result of an \"(alpha)? beta\" block\n");
+ fprintf(stderr,"\n");
+ MR_dumpRuleSet(MR_CompromisedRules);
+ fprintf(stderr,"\n");
+ }
+ }
+ cleanUp();
+ exit(PCCTS_EXIT_SUCCESS);
+ return 0; /* MR11 make compilers happy */
+}
+
+static void
+#ifdef __USE_PROTOS
+init( void )
+#else
+init( )
+#endif
+{
+ SignalEntry *q;
+
+ Tname = newHashTable();
+ Rname = newHashTable();
+ Fcache = newHashTable();
+ Tcache = newHashTable();
+ Sname = newHashTable();
+ Pname = newHashTable(); /* MR11 */
+
+ /* Add default signal names */
+ q = (SignalEntry *)hash_add(Sname,
+ "NoViableAlt",
+ (Entry *)newSignalEntry("NoViableAlt"));
+ require(q!=NULL, "cannot alloc signal entry");
+ q->signum = sigNoViableAlt;
+ q = (SignalEntry *)hash_add(Sname,
+ "MismatchedToken",
+ (Entry *)newSignalEntry("MismatchedToken"));
+ require(q!=NULL, "cannot alloc signal entry");
+ q->signum = sigMismatchedToken;
+ q = (SignalEntry *)hash_add(Sname,
+ "NoSemViableAlt",
+ (Entry *)newSignalEntry("NoSemViableAlt"));
+ require(q!=NULL, "cannot alloc signal entry");
+ q->signum = sigNoSemViableAlt;
+
+ reserved_positions = empty;
+ all_tokens = empty;
+ imag_tokens = empty;
+ tokclasses = empty;
+ TokenStr = (char **) calloc(TSChunk, sizeof(char *));
+ require(TokenStr!=NULL, "main: cannot allocate TokenStr");
+ FoStack = (int **) calloc(CLL_k+1, sizeof(int *));
+ require(FoStack!=NULL, "main: cannot allocate FoStack");
+ FoTOS = (int **) calloc(CLL_k+1, sizeof(int *));
+ require(FoTOS!=NULL, "main: cannot allocate FoTOS");
+ Cycles = (ListNode **) calloc(CLL_k+1, sizeof(ListNode *));
+ require(Cycles!=NULL, "main: cannot allocate Cycles List");
+ MR_CompromisedRules=empty; /* MR14 */
+}
+
+static void
+#ifdef __USE_PROTOS
+help( void )
+#else
+help( )
+#endif
+{
+ Opt *p = options;
+ fprintf(stderr, "antlr [options] f1 f2 ... fn\n");
+ while ( *(p->option) != '*' )
+ {
+ fprintf(stderr, " %-9s%s %s\n",
+ p->option,
+ (p->arg)?"___":" ",
+ p->descr);
+ p++;
+ }
+}
+
+/* The RulePtr array is filled in here. RulePtr exists primarily
+ * so that sets of rules can be maintained for the FOLLOW caching
+ * mechanism found in rJunc(). RulePtr maps a rule num from 1 to n
+ * to a pointer to its RuleBlk junction where n is the number of rules.
+ */
+static void
+#ifdef __USE_PROTOS
+buildRulePtr( void )
+#else
+buildRulePtr( )
+#endif
+{
+ int r=1;
+ Junction *p = SynDiag;
+ RulePtr = (Junction **) calloc(NumRules+1, sizeof(Junction *));
+ require(RulePtr!=NULL, "cannot allocate RulePtr array");
+
+ while ( p!=NULL )
+ {
+ require(r<=NumRules, "too many rules???");
+ RulePtr[r++] = p;
+ p = (Junction *)p->p2;
+ }
+}
+
+void
+#ifdef __USE_PROTOS
+dlgerror(const char *s)
+#else
+dlgerror(s)
+char *s;
+#endif
+{
+ fprintf(stderr, ErrHdr, FileStr[CurFile], zzline);
+ fprintf(stderr, " lexical error: %s (text was '%s')\n",
+ ((s == NULL) ? "Lexical error" : s), zzlextext);
+}
+
+void
+#ifdef __USE_PROTOS
+readDescr( void )
+#else
+readDescr( )
+#endif
+{
+ zzerr = dlgerror;
+ input = NextFile();
+ if ( input==NULL ) fatal("No grammar description found (exiting...)");
+ ANTLR(grammar(), input);
+ tnodes_used_in_guard_predicates_etc=TnodesInUse; /* MR10 */
+}
+
+FILE *
+#ifdef __USE_PROTOS
+NextFile( void )
+#else
+NextFile( )
+#endif
+{
+ FILE *f;
+
+ for (;;)
+ {
+ CurFile++;
+ if ( CurFile >= NumFiles ) return(NULL);
+ if ( ci_strequ(FileStr[CurFile],"stdin")) return stdin;
+ f = fopen(FileStr[CurFile], "r");
+ if ( f == NULL )
+ {
+ warnNoFL( eMsg1("file %s doesn't exist; ignored", FileStr[CurFile]) );
+ }
+ else
+ {
+ return(f);
+ }
+ }
+}
+
+/*
+ * Return a string corresponding to the output file name associated
+ * with the input file name passed in.
+ *
+ * Observe the following rules:
+ *
+ * f.e --> f".c"
+ * f --> f".c"
+ * f. --> f".c"
+ * f.e.g --> f.e".c"
+ *
+ * Where f,e,g are arbitrarily long sequences of characters in a file
+ * name.
+ *
+ * In other words, if a ".x" appears on the end of a file name, make it
+ * ".c". If no ".x" appears, append ".c" to the end of the file name.
+ *
+ * C++ mode using .cpp not .c.
+ *
+ * Use malloc() for new string.
+ */
+
+char *
+#ifdef __USE_PROTOS
+outname( char *fs )
+#else
+outname( fs )
+char *fs;
+#endif
+{
+ if ( GenCC) {
+ return outnameX(fs,CPP_FILE_SUFFIX);
+ } else {
+ return outnameX(fs,".c");
+ };
+}
+
+char *
+#ifdef __USE_PROTOS
+outnameX( char *fs ,char *suffix)
+#else
+outnameX( fs , suffix )
+char *fs;
+char *suffix;
+#endif
+{
+ static char buf[MaxFileName+1];
+ char *p;
+ require(fs!=NULL&&*fs!='\0', "outname: NULL filename");
+
+ p = buf;
+ strcpy(buf, fs);
+ while ( *p != '\0' ) {p++;} /* Stop on '\0' */
+ while ( *p != '.' && p != buf ) {--p;} /* Find '.' */
+ if ( p != buf ) *p = '\0'; /* Found '.' */
+ require(strlen(buf) + 2 < (size_t)MaxFileName, "outname: filename too big");
+ strcat(buf,suffix);
+ return( buf );
+}
+
+void
+#ifdef __USE_PROTOS
+fatalFL( char *err_, char *f, int l )
+#else
+fatalFL( err_, f, l )
+char *err_;
+char *f;
+int l;
+#endif
+{
+ fprintf(stderr, ErrHdr, f, l);
+ fprintf(stderr, " %s\n", err_);
+ cleanUp();
+ exit(PCCTS_EXIT_FAILURE);
+}
+
+void
+#ifdef __USE_PROTOS
+fatal_intern( char *err_, char *f, int l )
+#else
+fatal_intern( err_, f, l )
+char *err_;
+char *f;
+int l;
+#endif
+{
+ fprintf(stderr, ErrHdr, f, l);
+ fprintf(stderr, " #$%%*&@# internal error: %s\n", err_);
+ fprintf(stderr, ErrHdr, f, l);
+ fprintf(stderr, " [complain to nearest government official\n");
+ fprintf(stderr, ErrHdr, f, l);
+ fprintf(stderr, " or send hate-mail to parrt@parr-research.com;\n");
+ fprintf(stderr, ErrHdr, f, l);
+ fprintf(stderr, " please pray to the ``bug'' gods that there is a trival fix.]\n");
+ cleanUp();
+ exit(PCCTS_EXIT_FAILURE);
+}
+
+void
+#ifdef __USE_PROTOS
+cleanUp( void )
+#else
+cleanUp( )
+#endif
+{
+ if ( DefFile != NULL) fclose( DefFile );
+}
+
+/* sprintf up to 3 strings */
+char *
+#ifdef __USE_PROTOS
+eMsg3( char *s, char *a1, char *a2, char *a3 )
+#else
+eMsg3( s, a1, a2, a3 )
+char *s;
+char *a1;
+char *a2;
+char *a3;
+#endif
+{
+ static char buf[250]; /* DANGEROUS as hell !!!!!! */
+
+ sprintf(buf, s, a1, a2, a3);
+ return( buf );
+}
+
+/* sprintf a decimal */
+char *
+#ifdef __USE_PROTOS
+eMsgd( char *s, int d )
+#else
+eMsgd( s, d )
+char *s;
+int d;
+#endif
+{
+ static char buf[250]; /* DANGEROUS as hell !!!!!! */
+
+ sprintf(buf, s, d);
+ return( buf );
+}
+
+char *
+#ifdef __USE_PROTOS
+eMsgd2( char *s, int d1,int d2)
+#else
+eMsgd2( s, d1, d2 )
+char *s;
+int d1;
+int d2;
+#endif
+{
+ static char buf[250]; /* DANGEROUS as hell !!!!!! */
+
+ sprintf(buf, s, d1, d2);
+ return( buf );
+}
+
+void
+#ifdef __USE_PROTOS
+s_fprT( FILE *f, set e )
+#else
+s_fprT( f, e )
+FILE *f;
+set e;
+#endif
+{
+ register unsigned *p;
+ unsigned *q;
+
+ if ( set_nil(e) ) return;
+ if ( (q=p=set_pdq(e)) == NULL ) fatal_internal("Can't alloc space for set_pdq");
+ fprintf(f, "{");
+ while ( *p != nil )
+ {
+ fprintf(f, " %s", TerminalString(*p));
+ p++;
+ }
+ fprintf(f, " }");
+ free((char *)q);
+}
+
+/* Return the token name or regular expression for a token number. */
+char *
+#ifdef __USE_PROTOS
+TerminalString( int token )
+#else
+TerminalString( token )
+int token;
+#endif
+{
+ int j;
+ static char imag_name[20];
+
+ /* look in all lexclasses for the token */
+ if ( TokenString(token) != NULL ) return TokenString(token);
+ for (j=0; j<NumLexClasses; j++)
+ {
+ lexmode(j);
+ if ( ExprString(token) != NULL ) return ExprString(token);
+ }
+
+ if (1) {
+ sprintf(imag_name,"UnknownToken#%d",token); /* MR13 */
+ return imag_name; /* MR13 */
+ }
+
+ require(j<NumLexClasses, eMsgd("No label or expr for token %d",token));
+ return "invalid";
+}
+
+ /* S i m p l e I n t S t a c k */
+
+void
+#ifdef __USE_PROTOS
+pushint( int i )
+#else
+pushint( i )
+int i;
+#endif
+{
+ require(isp>0, "pushint: stack overflow");
+ istack[--isp] = i;
+}
+
+int
+#ifdef __USE_PROTOS
+popint( void )
+#else
+popint( )
+#endif
+{
+ require(isp<MAX_INT_STACK, "popint: stack underflow");
+ return istack[isp++];
+}
+
+int
+#ifdef __USE_PROTOS
+istacksize( void )
+#else
+istacksize( )
+#endif
+{
+ return MAX_INT_STACK-isp;
+}
+
+void
+#ifdef __USE_PROTOS
+istackreset( void )
+#else
+istackreset( )
+#endif
+{
+ isp = MAX_INT_STACK;
+}
+
+int
+#ifdef __USE_PROTOS
+istackempty( void )
+#else
+istackempty( )
+#endif
+{
+ return isp==MAX_INT_STACK;
+}
+
+int
+#ifdef __USE_PROTOS
+topint( void )
+#else
+topint( )
+#endif
+{
+ require(isp<MAX_INT_STACK, "topint: stack underflow");
+ return istack[isp];
+}
+
+void
+#ifdef __USE_PROTOS
+ProcessArgs( int argc, char **argv, Opt *options )
+#else
+ProcessArgs( argc, argv, options )
+int argc;
+char **argv;
+Opt *options;
+#endif
+{
+ Opt *p;
+ require(argv!=NULL, "ProcessArgs: command line NULL");
+
+ while ( argc-- > 0 )
+ {
+ p = options;
+ while ( p->option != NULL )
+ {
+ if ( strcmp(p->option, "*") == 0 ||
+ ci_strequ(p->option, *argv) == 1 )
+ {
+ if ( p->arg )
+ {
+/* MR9 26-Sep-97 Check for argv valid */
+ if (argc-- > 0) {
+ (*p->process)( *argv, *(argv+1) );
+ argv++;
+ } else {
+fprintf(stderr,"error: required argument for option %s omitted\n",*argv);
+exit(PCCTS_EXIT_FAILURE);
+ };
+ }
+ else
+ (*p->process)( *argv );
+ break;
+ }
+ p++;
+ }
+ argv++;
+ }
+}
+
+static void
+#ifdef __USE_PROTOS
+CompleteContextGuards(void)
+#else
+CompleteContextGuards()
+#endif
+{
+ ListNode * p;
+ Predicate * pred;
+
+ if (ContextGuardPredicateList == NULL) return;
+
+ for (p=ContextGuardPredicateList->next; p != NULL; p=p->next) {
+ pred=(Predicate *)p->elem;
+ recomputeContextGuard(pred);
+ }
+}
+
+/* Go back into the syntax diagram and compute all meta tokens; i.e.
+ * turn all '.', ranges, token class refs etc... into actual token sets
+ */
+static void
+#ifdef __USE_PROTOS
+CompleteTokenSetRefs(void)
+#else
+CompleteTokenSetRefs()
+#endif
+{
+ ListNode *p;
+
+ if ( MetaTokenNodes==NULL ) return;
+ for (p = MetaTokenNodes->next; p!=NULL; p=p->next)
+ {
+ set a,b;
+
+ TokNode *q = (TokNode *)p->elem;
+ if ( q->wild_card )
+ {
+ q->tset = all_tokens;
+ }
+ else if ( q->tclass!=NULL )
+ {
+ if ( q->complement ) q->tset = set_dif(all_tokens, q->tclass->tset);
+ else q->tset = q->tclass->tset;
+ }
+ else if ( q->upper_range!=0 )
+ {
+ /* we have a range on our hands: make a set from q->token .. q->upper_range */
+ int i;
+ a = empty;
+ for (i=q->token; i<=q->upper_range; i++) { set_orel(i, &a); } /* MR13 */
+
+/* MR13 */ if (q->complement) {
+/* MR13 */ q->tset = set_dif(all_tokens, a);
+/* MR13 */ set_free(a);
+/* MR13 */ } else {
+/* MR13 */ q->tset = a;
+/* MR13 */ }
+
+ }
+
+ /* at this point, it can only be a complemented single token */
+ else if ( q->complement )
+ {
+ a = set_of(q->token);
+ b = set_dif(all_tokens, a);
+ set_free(a);
+ q->tset=b;
+ }
+ else fatal("invalid meta token");
+ }
+}
+
+/* MR10: Jeff Vincent
+ MR10: Changed to remove directory information from n only if
+ MR10: if OutputDirectory was changed by user (-o option)
+*/
+
+char *
+#ifdef __USE_PROTOS
+OutMetaName(char *n)
+#else
+OutMetaName(n)
+char *n;
+#endif
+{
+ static char *dir_sym = DirectorySymbol;
+ static char newname[MaxFileName+1];
+ char *p;
+
+ /* If OutputDirectory is same as TopDirectory (platform default) then leave n alone. */
+ if (strcmp(OutputDirectory, TopDirectory) == 0) /* TopDirectory is "." on Unix. */
+ return n;
+
+ /* p will point to filename without path information */
+ if ((p = strrchr(n, *dir_sym)) != NULL) /* Directory symbol is "/" on Unix. */
+ p++;
+ else
+ p = n;
+
+ /* Copy new output directory into newname[] */
+ strcpy(newname, OutputDirectory);
+
+ /* if new output directory does not have trailing dir_sym, add it! */
+ if (newname[strlen(newname)-1] != *dir_sym) {
+ strcat(newname, dir_sym);
+ }
+ strcat(newname, p);
+ return newname;
+}
+
+char *
+#ifdef __USE_PROTOS
+pcctsBaseName(char *n) /* MR32 */
+#else
+pcctsBaseName(n)
+char *n;
+#endif
+{
+ static char newname[MaxFileName+1];
+ static char* dir_sym = DirectorySymbol;
+ int count = 0;
+ char *p;
+
+ p = n;
+
+ while ( *p != '\0' ) {p++;} /* go to end of string */
+ while ( (*p != *dir_sym) && (p != n) ) {--p;} /* Find last DirectorySymbol */
+ while ( *p == *dir_sym) p++; /* step forward if we're on a dir symbol */
+ while ( *p != '\0' && *p != '.')
+ {
+ newname[count++] = *p;
+ p++;
+ } /* create a new name */
+ newname[count] = '\0';
+ return newname;
+}
+
+static void
+#ifdef __USE_PROTOS
+ensure_no_C_file_collisions(char *class_c_file)
+#else
+ensure_no_C_file_collisions(class_c_file)
+char *class_c_file;
+#endif
+{
+ int i;
+
+ for (i=0; i<NumFiles; i++)
+ {
+
+#ifdef PCCTS_CASE_INSENSITIVE_FILE_NAME
+ /* assume that file names are case insensitive */
+ if ( STRICMP(outname(FileStr[i]), class_c_file)==0 )
+#else
+ if ( strcmp(outname(FileStr[i]), class_c_file)==0 )
+#endif
+ {
+ fatal(eMsg1("class def output file conflicts with parser output file: %s",
+ outname(FileStr[i])));
+ }
+ }
+}
+
+void
+#ifdef __USE_PROTOS
+warnNoFL(char *err)
+#else
+warnNoFL(err)
+char *err;
+#endif
+{
+ fprintf(stderr, "warning: %s\n", err);
+}
+
+void
+#ifdef __USE_PROTOS
+warnFL(char *err,char *f,int l)
+#else
+warnFL(err,f,l)
+char *f;
+int l;
+char *err;
+#endif
+{
+ fprintf(stderr, ErrHdr, f, l);
+ fprintf(stderr, " warning: %s\n", err);
+}
+
+void
+#ifdef __USE_PROTOS
+warn(char *err)
+#else
+warn(err)
+char *err;
+#endif
+{
+ /* back up the file number if we hit an error at the end of the last file */
+ if ( CurFile >= NumFiles && CurFile >= 1 ) CurFile--;
+ fprintf(stderr, ErrHdr, FileStr[CurFile], zzline);
+ fprintf(stderr, " warning: %s\n", err);
+}
+
+void
+#ifdef __USE_PROTOS
+warnNoCR( char *err )
+#else
+warnNoCR( err )
+char *err;
+#endif
+{
+ /* back up the file number if we hit an error at the end of the last file */
+ if ( CurFile >= NumFiles && CurFile >= 1 ) CurFile--;
+ fprintf(stderr, ErrHdr, FileStr[CurFile], zzline);
+ fprintf(stderr, " warning: %s", err);
+}
+
+void
+#ifdef __USE_PROTOS
+errNoFL(char *err)
+#else
+errNoFL(err)
+char *err;
+#endif
+{
+ fprintf(stderr, "error: %s\n", err);
+}
+
+void
+#ifdef __USE_PROTOS
+errFL(char *err,char *f,int l)
+#else
+errFL(err,f,l)
+char *err;
+char *f;
+int l;
+#endif
+{
+ fprintf(stderr, ErrHdr, f, l);
+ fprintf(stderr, " error: %s\n", err);
+}
+
+void
+#ifdef __USE_PROTOS
+err(char *err)
+#else
+err(err)
+char *err;
+#endif
+{
+ /* back up the file number if we hit an error at the end of the last file */
+ if ( CurFile >= NumFiles && CurFile >= 1 ) CurFile--;
+ fprintf(stderr, ErrHdr, FileStr[CurFile], zzline);
+ fprintf(stderr, " error: %s\n", err);
+}
+
+void
+#ifdef __USE_PROTOS
+errNoCR( char *err )
+#else
+errNoCR( err )
+char *err;
+#endif
+{
+ /* back up the file number if we hit an error at the end of the last file */
+ if ( CurFile >= NumFiles && CurFile >= 1 ) CurFile--;
+ fprintf(stderr, ErrHdr, FileStr[CurFile], zzline);
+ fprintf(stderr, " error: %s", err);
+}
+
+UserAction *
+#ifdef __USE_PROTOS
+newUserAction(char *s)
+#else
+newUserAction(s)
+char *s;
+#endif
+{
+ UserAction *ua = (UserAction *) calloc(1, sizeof(UserAction));
+ require(ua!=NULL, "cannot allocate UserAction");
+
+ ua->action = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char));
+ strcpy(ua->action, s);
+ return ua;
+}
+
+/* Added by TJP September 1994 */
+/* Take in file.h and return file_h; names w/o '.'s are left alone */
+char *
+#ifdef __USE_PROTOS
+gate_symbol(char *name)
+#else
+gate_symbol(name)
+char *name;
+#endif
+{
+ static char buf[100];
+ char *p;
+ sprintf(buf, "%s", name);
+
+ for (p=buf; *p!='\0'; p++)
+ {
+ if ( *p=='.' ) *p = '_';
+ }
+ return buf;
+}
+
+char *
+#ifdef __USE_PROTOS
+makeAltID(int blockid, int altnum)
+#else
+makeAltID(blockid, altnum)
+int blockid;
+int altnum;
+#endif
+{
+ static char buf[100];
+ char *p;
+ sprintf(buf, "_blk%d_alt%d", blockid, altnum);
+ p = (char *)malloc(strlen(buf)+1);
+ strcpy(p, buf);
+ return p;
+}
diff --git a/Source/Pccts/antlr/makefile b/Source/Pccts/antlr/makefile
new file mode 100644
index 0000000..2aa6cdf
--- /dev/null
+++ b/Source/Pccts/antlr/makefile
@@ -0,0 +1,218 @@
+#
+# Makefile for ANTLR 1.33
+#
+# SOFTWARE RIGHTS
+#
+# We reserve no LEGAL rights to the Purdue Compiler Construction Tool
+# Set (PCCTS) -- PCCTS is in the public domain. An individual or
+# company may do whatever they wish with source code distributed with
+# PCCTS or the code generated by PCCTS, including the incorporation of
+# PCCTS, or its output, into commerical software.
+#
+# We encourage users to develop software with PCCTS. However, we do ask
+# that credit is given to us for developing PCCTS. By "credit",
+# we mean that if you incorporate our source code into one of your
+# programs (commercial product, research project, or otherwise) that you
+# acknowledge this fact somewhere in the documentation, research report,
+# etc... If you like PCCTS and have developed a nice tool with the
+# output, please mention that you developed it using PCCTS. In
+# addition, we ask that this header remain intact in our source code.
+# As long as these guidelines are kept, we expect to continue enhancing
+# this system and expect to make other tools available as they are
+# completed.
+#
+# ANTLR 1.33
+# Terence Parr
+# Parr Research Corporation
+# with Purdue University
+# and AHPCRC, University of Minnesota
+# 1989-1995
+#
+# Ported to Borland C++, IBM C-Set/2 and Microsoft 6.0 by
+# Ed Harfmann
+# Micro Data Base Systems
+# Lafayette, Indiana
+#
+SET=../support/set
+PCCTS_H=../h
+
+##
+## Uncomment the appropriate section to build
+## (both targets and 'make' variable definitions)
+## Note that UNIX is the default
+##
+
+#
+# OS/2 & DOS 16 bit using MSC 6.0
+#
+#CC=cl
+#ANTLR=..\bin\antlr
+#DLG=..\bin\dlg
+#CFLAGS= -I. -I$(SET) -I$(PCCTS_H) /AL /Za /W3 -DPC -DUSER_ZZSYN
+#OUT_OBJ = -Fo
+#LIBS=/NOD:LLIBCE LLIBCEP
+#OBJ_EXT = obj
+#
+#antlr.exe: antlr.obj scan.obj err.obj bits.obj build.obj fset2.obj \
+# fset.obj gen.obj globals.obj hash.obj lex.obj main.obj \
+# misc.obj set.obj pred.obj egamn.obj
+# link @<<
+#$** /NOI
+#$@ /STACK:14336
+#
+#$(LIBS: = +^
+#)
+#$(DEF_FILE) $(LFLAGS) ;
+#<<
+# bind $@ c:\os2\doscalls.lib
+# copy *.exe ..\bin
+#
+
+#
+# Borland C++ for DOS
+#
+#CC=bcc
+#ANTLR=..\bin\antlr
+#DLG=..\bin\dlg
+#CFLAGS= -I. -I$(SET) -I$(PCCTS_H) -ml -ff- -w- -DPC -DUSER_ZZSYN
+#OUT_OBJ = -o
+#LIBS= emu mathl cl
+#OBJ_EXT = obj
+#
+#antlr.exe: antlr.obj scan.obj err.obj bits.obj build.obj fset2.obj \
+# fset.obj gen.obj globals.obj hash.obj lex.obj main.obj \
+# misc.obj set.obj pred.obj egman.obj mrhoist.obj fcache.obj
+# tlink @&&|
+#C0L $**
+#$@ /Tde /c
+#
+#$(LIBS)
+#$(DEF_FILE) $(LFLAGS) ;
+#|
+# copy *.exe ..\bin
+#
+
+#
+# C-Set/2 for OS/2
+#
+#CC=icc
+#CFLAGS= -I. -I$(SET) -I$(PCCTS_H) /Sa /W3 -DUSER_ZZSYN -D__STDC__
+#OUT_OBJ = -Fo
+#LIBS=
+#ANTLR=..\bin\antlr
+#DLG=..\bin\dlg
+#OBJ_EXT = obj
+#
+#antlr.exe: antlr.obj scan.obj err.obj bits.obj build.obj fset2.obj \
+# fset.obj gen.obj globals.obj hash.obj lex.obj main.obj \
+# misc.obj set.obj pred.obj egman.obj mrhoist.obj fcache.obj
+# link386 @<<
+#$** /NOI
+#$@ /STACK:32768
+#
+#$(LIBS: = +^
+#)
+#$(DEF_FILE) $(LFLAGS) ;
+#<<
+# copy *.exe ..\bin
+#
+
+#
+# Borland C++ for OS/2
+#
+#CC=bcc
+#CFLAGS= -I. -I$(SET) -I$(PCCTS_H) -w- -v -DUSER_ZZSYN
+#OUT_OBJ = -o
+#LIBS= c2 os2
+#
+#ANTLR=..\bin\antlr
+#DLG=..\bin\dlg
+#OBJ_EXT = obj
+#antlr.exe: antlr.obj scan.obj err.obj bits.obj build.obj fset2.obj \
+# fset.obj gen.obj globals.obj hash.obj lex.obj main.obj \
+# misc.obj set.obj pred.obj egman.obj mrhoist.obj fcache.obj
+# tlink @&&|
+#c02 $** -c -v
+#antlr.exe
+#
+#C2 os2
+#
+#|
+# copy *.exe ..\bin
+#
+
+# *********** Target list of PC machines ***********
+#
+# Don't worry about the ambiguity messages coming from antlr
+# for making antlr.c etc... [should be 10 of them, I think]
+#
+#antlr.c stdpccts.h parser.dlg tokens.h err.c : antlr.g
+# $(ANTLR) antlr.g
+#
+#antlr.$(OBJ_EXT): antlr.c mode.h tokens.h
+#
+#scan.$(OBJ_EXT): scan.c mode.h tokens.h
+#
+#scan.c mode.h: parser.dlg
+# $(DLG) -C2 parser.dlg scan.c
+#
+#set.$(OBJ_EXT): $(SET)/set.c
+# $(CC) $(CFLAGS) -c $(OUT_OBJ)set.$(OBJ_EXT) $(SET)/set.c
+
+
+
+#
+# UNIX (default)
+#
+CC=gcc
+COPT=-O
+ANTLR=${BIN_DIR}/antlr
+DLG=${BIN_DIR}/dlg
+OBJ_EXT=o
+OUT_OBJ = -o
+CFLAGS= $(COPT) -I. -I$(SET) -I$(PCCTS_H) -DUSER_ZZSYN $(COTHER) -DZZLEXBUFSIZE=65536
+#
+# SGI Users, use this CFLAGS
+#
+#CFLAGS= -O -I. -I$(SET) -I$(PCCTS_H) -DUSER_ZZSYN -woff 3262
+OBJ=antlr.o scan.o err.o bits.o build.o fset2.o fset.o gen.o \
+ globals.o hash.o lex.o main.o misc.o set.o pred.o egman.o mrhoist.o fcache.o
+
+antlr : $(OBJ) $(SRC)
+ $(CC) $(CFLAGS) -o $(BIN_DIR)/antlr $(OBJ)
+
+# what files does PCCTS generate (both ANTLR and DLG)
+PCCTS_GEN=antlr.c scan.c err.c tokens.h mode.h parser.dlg stdpccts.h remap.h
+
+SRC=antlr.c scan.c err.c bits.c build.c fset2.c fset.c gen.c globals.c \
+ hash.c lex.c main.c misc.c $(SET)/set.c pred.c egman.c mrhoist.c fcache.c
+
+#
+# Don't worry about the ambiguity messages coming from antlr
+# for making antlr.c etc... [should be 10 of them, I think]
+#
+#antlr.c stdpccts.h parser.dlg tokens.h err.c : antlr.g
+# $(ANTLR) -gh antlr.g
+
+antlr.o : antlr.c mode.h tokens.h
+
+scan.o : scan.c mode.h tokens.h
+
+#scan.c mode.h: parser.dlg
+# $(DLG) -C2 parser.dlg scan.c
+
+set.o : $(SET)/set.c
+ $(CC) $(CFLAGS) -c -o set.o $(SET)/set.c
+
+
+#
+# ****** These next targets are common to UNIX and PC world ********
+#
+
+#clean up all the intermediate files
+clean:
+ rm -f *.$(OBJ_EXT) core
+
+#remove everything in clean plus the PCCTS files generated
+scrub:
+ rm -f $(PCCTS_GEN) *.$(OBJ_EXT) core
diff --git a/Source/Pccts/antlr/makefile.cygwin b/Source/Pccts/antlr/makefile.cygwin
new file mode 100644
index 0000000..956de0b
--- /dev/null
+++ b/Source/Pccts/antlr/makefile.cygwin
@@ -0,0 +1,219 @@
+#
+# Makefile for ANTLR 1.33
+#
+# SOFTWARE RIGHTS
+#
+# We reserve no LEGAL rights to the Purdue Compiler Construction Tool
+# Set (PCCTS) -- PCCTS is in the public domain. An individual or
+# company may do whatever they wish with source code distributed with
+# PCCTS or the code generated by PCCTS, including the incorporation of
+# PCCTS, or its output, into commerical software.
+#
+# We encourage users to develop software with PCCTS. However, we do ask
+# that credit is given to us for developing PCCTS. By "credit",
+# we mean that if you incorporate our source code into one of your
+# programs (commercial product, research project, or otherwise) that you
+# acknowledge this fact somewhere in the documentation, research report,
+# etc... If you like PCCTS and have developed a nice tool with the
+# output, please mention that you developed it using PCCTS. In
+# addition, we ask that this header remain intact in our source code.
+# As long as these guidelines are kept, we expect to continue enhancing
+# this system and expect to make other tools available as they are
+# completed.
+#
+# ANTLR 1.33
+# Terence Parr
+# Parr Research Corporation
+# with Purdue University
+# and AHPCRC, University of Minnesota
+# 1989-1995
+#
+# Ported to Borland C++, IBM C-Set/2 and Microsoft 6.0 by
+# Ed Harfmann
+# Micro Data Base Systems
+# Lafayette, Indiana
+#
+SET=../support/set
+PCCTS_H=../h
+
+##
+## Uncomment the appropriate section to build
+## (both targets and 'make' variable definitions)
+## Note that UNIX is the default
+##
+
+#
+# OS/2 & DOS 16 bit using MSC 6.0
+#
+#CC=cl
+#ANTLR=..\bin\antlr
+#DLG=..\bin\dlg
+#CFLAGS= -I. -I$(SET) -I$(PCCTS_H) /AL /Za /W3 -DPC -DUSER_ZZSYN
+#OUT_OBJ = -Fo
+#LIBS=/NOD:LLIBCE LLIBCEP
+#OBJ_EXT = obj
+#
+#antlr.exe: antlr.obj scan.obj err.obj bits.obj build.obj fset2.obj \
+# fset.obj gen.obj globals.obj hash.obj lex.obj main.obj \
+# misc.obj set.obj pred.obj egamn.obj
+# link @<<
+#$** /NOI
+#$@ /STACK:14336
+#
+#$(LIBS: = +^
+#)
+#$(DEF_FILE) $(LFLAGS) ;
+#<<
+# bind $@ c:\os2\doscalls.lib
+# copy *.exe ..\bin
+#
+
+#
+# Borland C++ for DOS
+#
+#CC=bcc
+#ANTLR=..\bin\antlr
+#DLG=..\bin\dlg
+#CFLAGS= -I. -I$(SET) -I$(PCCTS_H) -ml -ff- -w- -DPC -DUSER_ZZSYN
+#OUT_OBJ = -o
+#LIBS= emu mathl cl
+#OBJ_EXT = obj
+#
+#antlr.exe: antlr.obj scan.obj err.obj bits.obj build.obj fset2.obj \
+# fset.obj gen.obj globals.obj hash.obj lex.obj main.obj \
+# misc.obj set.obj pred.obj egman.obj mrhoist.obj fcache.obj
+# tlink @&&|
+#C0L $**
+#$@ /Tde /c
+#
+#$(LIBS)
+#$(DEF_FILE) $(LFLAGS) ;
+#|
+# copy *.exe ..\bin
+#
+
+#
+# C-Set/2 for OS/2
+#
+#CC=icc
+#CFLAGS= -I. -I$(SET) -I$(PCCTS_H) /Sa /W3 -DUSER_ZZSYN -D__STDC__
+#OUT_OBJ = -Fo
+#LIBS=
+#ANTLR=..\bin\antlr
+#DLG=..\bin\dlg
+#OBJ_EXT = obj
+#
+#antlr.exe: antlr.obj scan.obj err.obj bits.obj build.obj fset2.obj \
+# fset.obj gen.obj globals.obj hash.obj lex.obj main.obj \
+# misc.obj set.obj pred.obj egman.obj mrhoist.obj fcache.obj
+# link386 @<<
+#$** /NOI
+#$@ /STACK:32768
+#
+#$(LIBS: = +^
+#)
+#$(DEF_FILE) $(LFLAGS) ;
+#<<
+# copy *.exe ..\bin
+#
+
+#
+# Borland C++ for OS/2
+#
+#CC=bcc
+#CFLAGS= -I. -I$(SET) -I$(PCCTS_H) -w- -v -DUSER_ZZSYN
+#OUT_OBJ = -o
+#LIBS= c2 os2
+#
+#ANTLR=..\bin\antlr
+#DLG=..\bin\dlg
+#OBJ_EXT = obj
+#antlr.exe: antlr.obj scan.obj err.obj bits.obj build.obj fset2.obj \
+# fset.obj gen.obj globals.obj hash.obj lex.obj main.obj \
+# misc.obj set.obj pred.obj egman.obj mrhoist.obj fcache.obj
+# tlink @&&|
+#c02 $** -c -v
+#antlr.exe
+#
+#C2 os2
+#
+#|
+# copy *.exe ..\bin
+#
+
+# *********** Target list of PC machines ***********
+#
+# Don't worry about the ambiguity messages coming from antlr
+# for making antlr.c etc... [should be 10 of them, I think]
+#
+#antlr.c stdpccts.h parser.dlg tokens.h err.c : antlr.g
+# $(ANTLR) antlr.g
+#
+#antlr.$(OBJ_EXT): antlr.c mode.h tokens.h
+#
+#scan.$(OBJ_EXT): scan.c mode.h tokens.h
+#
+#scan.c mode.h: parser.dlg
+# $(DLG) -C2 parser.dlg scan.c
+#
+#set.$(OBJ_EXT): $(SET)/set.c
+# $(CC) $(CFLAGS) -c $(OUT_OBJ)set.$(OBJ_EXT) $(SET)/set.c
+
+
+
+#
+# UNIX (default)
+#
+BIN_DIR=../../../../bin
+CC=gcc
+COPT=-O
+ANTLR=$(BIN_DIR)/antlr.exe
+DLG=${BIN_DIR}/dlg.exe
+OBJ_EXT=o
+OUT_OBJ = -o
+CFLAGS= $(COPT) -I. -I$(SET) -I$(PCCTS_H) -DUSER_ZZSYN $(COTHER) -DZZLEXBUFSIZE=65536
+#
+# SGI Users, use this CFLAGS
+#
+#CFLAGS= -O -I. -I$(SET) -I$(PCCTS_H) -DUSER_ZZSYN -woff 3262
+OBJ=antlr.o scan.o err.o bits.o build.o fset2.o fset.o gen.o \
+ globals.o hash.o lex.o main.o misc.o set.o pred.o egman.o mrhoist.o fcache.o
+
+antlr : $(OBJ) $(SRC)
+ $(CC) $(CFLAGS) -o $(BIN_DIR)/antlr.exe $(OBJ)
+
+# what files does PCCTS generate (both ANTLR and DLG)
+PCCTS_GEN=antlr.c scan.c err.c tokens.h mode.h parser.dlg stdpccts.h remap.h
+
+SRC=antlr.c scan.c err.c bits.c build.c fset2.c fset.c gen.c globals.c \
+ hash.c lex.c main.c misc.c $(SET)/set.c pred.c egman.c mrhoist.c fcache.c
+
+#
+# Don't worry about the ambiguity messages coming from antlr
+# for making antlr.c etc... [should be 10 of them, I think]
+#
+#antlr.c stdpccts.h parser.dlg tokens.h err.c : antlr.g
+# $(ANTLR) -gh antlr.g
+
+antlr.o : antlr.c mode.h tokens.h
+
+scan.o : scan.c mode.h tokens.h
+
+#scan.c mode.h: parser.dlg
+# $(DLG) -C2 parser.dlg scan.c
+
+set.o : $(SET)/set.c
+ $(CC) $(CFLAGS) -c -o set.o $(SET)/set.c
+
+
+#
+# ****** These next targets are common to UNIX and PC world ********
+#
+
+#clean up all the intermediate files
+clean:
+ rm -f *.$(OBJ_EXT) core
+
+#remove everything in clean plus the PCCTS files generated
+scrub:
+ rm -f $(PCCTS_GEN) *.$(OBJ_EXT) core
diff --git a/Source/Pccts/antlr/makefile1 b/Source/Pccts/antlr/makefile1
new file mode 100644
index 0000000..dffc709
--- /dev/null
+++ b/Source/Pccts/antlr/makefile1
@@ -0,0 +1,96 @@
+#
+# Makefile for ANTLR 1.33
+#
+# SOFTWARE RIGHTS
+#
+# We reserve no LEGAL rights to the Purdue Compiler Construction Tool
+# Set (PCCTS) -- PCCTS is in the public domain. An individual or
+# company may do whatever they wish with source code distributed with
+# PCCTS or the code generated by PCCTS, including the incorporation of
+# PCCTS, or its output, into commerical software.
+#
+# We encourage users to develop software with PCCTS. However, we do ask
+# that credit is given to us for developing PCCTS. By "credit",
+# we mean that if you incorporate our source code into one of your
+# programs (commercial product, research project, or otherwise) that you
+# acknowledge this fact somewhere in the documentation, research report,
+# etc... If you like PCCTS and have developed a nice tool with the
+# output, please mention that you developed it using PCCTS. In
+# addition, we ask that this header remain intact in our source code.
+# As long as these guidelines are kept, we expect to continue enhancing
+# this system and expect to make other tools available as they are
+# completed.
+#
+# ANTLR 1.33
+# Terence Parr
+# Parr Research Corporation
+# with Purdue University
+# and AHPCRC, University of Minnesota
+# 1989-1995
+#
+# Ported to Borland C++, IBM C-Set/2 and Microsoft 6.0 by
+# Ed Harfmann
+# Micro Data Base Systems
+# Lafayette, Indiana
+#
+SET=../support/set
+PCCTS_H=../h
+
+#
+# UNIX (default)
+#
+CC=cc
+ANTLR=${WORKSPACE}/Tools/bin/antlr
+DLG=${WORKSPACE}/Tools/bin/dlg
+OBJ_EXT=o
+OUT_OBJ = -o
+ANSI=-ansi
+AOTHER=
+CFLAGS= -O0 -g -I. -I$(SET) -I$(PCCTS_H) -DUSER_ZZSYN $(COTHER) $(ANSI) -DZZLEXBUFSIZE=32000
+#
+# SGI Users, use this CFLAGS
+#
+#CFLAGS= -O -I. -I$(SET) -I$(PCCTS_H) -DUSER_ZZSYN -woff 3262
+
+OBJ=antlr.o scan.o err.o bits.o build.o fset2.o fset.o gen.o \
+ globals.o hash.o lex.o main.o misc.o set.o pred.o egman.o mrhoist.o fcache.o $(OBJOTHER)
+
+antlr : $(OBJ) $(SRC)
+ $(CC) $(CFLAGS) -o antlr $(OBJ)
+ mv antlr ${WORKSPACE}/Tools/bin
+
+# what files does PCCTS generate (both ANTLR and DLG)
+PCCTS_GEN=antlr.c scan.c err.c tokens.h mode.h parser.dlg stdpccts.h remap.h
+
+SRC=antlr.c scan.c err.c bits.c build.c fset2.c fset.c gen.c globals.c \
+ hash.c lex.c main.c misc.c $(SET)/set.c pred.c egman.c mrhoist.c fcache.c
+
+#
+# Don't worry about the ambiguity messages coming from antlr
+# for making antlr.c etc... [should be 10 of them, I think]
+#
+antlr.c stdpccts.h parser.dlg tokens.h err.c : antlr.g
+ $(ANTLR) -gh antlr.g $(AOTHER)
+
+antlr.o : antlr.c mode.h tokens.h
+
+scan.o : scan.c mode.h tokens.h
+
+scan.c mode.h: parser.dlg
+ $(DLG) -C2 parser.dlg scan.c
+
+set.o : $(SET)/set.c
+ $(CC) $(CFLAGS) -c -o set.o $(SET)/set.c
+
+
+#
+# ****** These next targets are common to UNIX and PC world ********
+#
+
+#clean up all the intermediate files
+clean:
+ rm -f *.$(OBJ_EXT) core
+
+#remove everything in clean plus the PCCTS files generated
+scrub:
+ rm -f $(PCCTS_GEN) *.$(OBJ_EXT) core
diff --git a/Source/Pccts/antlr/misc.c b/Source/Pccts/antlr/misc.c
new file mode 100644
index 0000000..3f58da3
--- /dev/null
+++ b/Source/Pccts/antlr/misc.c
@@ -0,0 +1,1864 @@
+/*
+ * misc.c
+ *
+ * Manage tokens, regular expressions.
+ * Print methods for debugging
+ * Compute follow lists onto tail ends of rules.
+ *
+ * The following functions are visible:
+ *
+ * int addTname(char *); Add token name
+ * int addTexpr(char *); Add token expression
+ * int Tnum(char *); Get number of expr/token
+ * void Tklink(char *, char *); Link a name with an expression
+ * int hasAction(expr); Does expr already have action assigned?
+ * void setHasAction(expr); Indicate that expr now has an action
+ * Entry *newEntry(char *,int); Create new table entry with certain size
+ * void list_add(ListNode **list, char *e)
+ * void list_free(ListNode **list, int freeData); *** MR10 ***
+ * void list_apply(ListNode *list, void (*f)())
+ * void lexclass(char *m); switch to new/old lexical class
+ * void lexmode(int i); switch to old lexical class i
+ *
+ * SOFTWARE RIGHTS
+ *
+ * We reserve no LEGAL rights to the Purdue Compiler Construction Tool
+ * Set (PCCTS) -- PCCTS is in the public domain. An individual or
+ * company may do whatever they wish with source code distributed with
+ * PCCTS or the code generated by PCCTS, including the incorporation of
+ * PCCTS, or its output, into commerical software.
+ *
+ * We encourage users to develop software with PCCTS. However, we do ask
+ * that credit is given to us for developing PCCTS. By "credit",
+ * we mean that if you incorporate our source code into one of your
+ * programs (commercial product, research project, or otherwise) that you
+ * acknowledge this fact somewhere in the documentation, research report,
+ * etc... If you like PCCTS and have developed a nice tool with the
+ * output, please mention that you developed it using PCCTS. In
+ * addition, we ask that this header remain intact in our source code.
+ * As long as these guidelines are kept, we expect to continue enhancing
+ * this system and expect to make other tools available as they are
+ * completed.
+ *
+ * ANTLR 1.33
+ * Terence Parr
+ * Parr Research Corporation
+ * with Purdue University and AHPCRC, University of Minnesota
+ * 1989-2001
+ */
+
+#include <stdio.h>
+#include "pcctscfg.h"
+#include "set.h"
+#include "syn.h"
+#include "hash.h"
+#include "generic.h"
+#include "dlgdef.h"
+#include <ctype.h>
+
+static int tsize=TSChunk; /* size of token str arrays */
+
+static void
+#ifdef __USE_PROTOS
+RemapForcedTokensInSyntaxDiagram(Node *);
+#else
+RemapForcedTokensInSyntaxDiagram();
+#endif
+
+ /* T o k e n M a n i p u l a t i o n */
+
+/*
+ * add token 't' to the TokenStr/Expr array. Make more room if necessary.
+ * 't' is either an expression or a token name.
+ *
+ * There is only one TokenStr array, but multiple ExprStr's. Therefore,
+ * for each lex class (element of lclass) we must extend the ExprStr array.
+ * ExprStr's and TokenStr are always all the same size.
+ *
+ * Also, there is a Texpr hash table for each automaton.
+ */
+static void
+#ifdef __USE_PROTOS
+Ttrack( char *t )
+#else
+Ttrack( t )
+char *t;
+#endif
+{
+ if ( TokenNum >= tsize ) /* terminal table overflow? */
+ {
+ char **p;
+ int i, more, j;
+
+ more = TSChunk * (1 + ((TokenNum-tsize) / TSChunk));
+ tsize += more;
+ TokenStr = (char **) realloc((char *)TokenStr, tsize*sizeof(char *));
+ require(TokenStr != NULL, "Ttrack: can't extend TokenStr");
+ for (i=0; i<NumLexClasses; i++)
+ {
+ lclass[i].exprs = (char **)
+ realloc((char *)lclass[i].exprs, tsize*sizeof(char *));
+ require(lclass[i].exprs != NULL, "Ttrack: can't extend ExprStr");
+ for (p= &lclass[i].exprs[tsize-more],j=1; j<=more; j++) *p++ = NULL;
+ }
+ for (p= &TokenStr[tsize-more],i=1; i<=more; i++) *p++ = NULL;
+ lexmode( CurrentLexClass ); /* reset ExprStr in case table moved */
+ }
+ /* note: we use the actual ExprStr/TokenStr array
+ * here as TokenInd doesn't exist yet
+ */
+ if ( *t == '"' ) ExprStr[TokenNum] = t;
+ else TokenStr[TokenNum] = t;
+}
+
+static Expr *
+#ifdef __USE_PROTOS
+newExpr( char *e )
+#else
+newExpr( e )
+char *e;
+#endif
+{
+ Expr *p = (Expr *) calloc(1, sizeof(Expr));
+ require(p!=NULL, "newExpr: cannot alloc Expr node");
+
+ p->expr = e;
+ p->lclass = CurrentLexClass;
+ return p;
+}
+
+/* switch to lexical class/mode m. This amounts to creating a new
+ * lex mode if one does not already exist and making ExprStr point
+ * to the correct char string array. We must also switch Texpr tables.
+ *
+ * BTW, we need multiple ExprStr arrays because more than one automaton
+ * may have the same label for a token, but with different expressions.
+ * We need to track an expr for each automaton. If we disallowed this
+ * feature, only one ExprStr would be required.
+ */
+void
+#ifdef __USE_PROTOS
+lexclass( char *m )
+#else
+lexclass( m )
+char *m;
+#endif
+{
+ int i;
+ TermEntry *p;
+ static char EOFSTR[] = "\"@\"";
+
+ if ( hash_get(Tname, m) != NULL )
+ {
+ warn(eMsg1("lexclass name conflicts with token/errclass label '%s'",m));
+ }
+ /* does m already exist? */
+ i = LexClassIndex(m);
+ if ( i != -1 ) {lexmode(i); return;}
+ /* must make new one */
+ NumLexClasses++;
+ CurrentLexClass = NumLexClasses-1;
+ require(NumLexClasses<=MaxLexClasses, "number of allowable lexclasses exceeded\nIncrease MaxLexClasses in generic.h and recompile all C files");
+ lclass[CurrentLexClass].classnum = m;
+ lclass[CurrentLexClass].exprs = (char **) calloc(tsize, sizeof(char *));
+ require(lclass[CurrentLexClass].exprs!=NULL,
+ "lexclass: cannot allocate ExprStr");
+ lclass[CurrentLexClass].htable = newHashTable();
+ ExprStr = lclass[CurrentLexClass].exprs;
+ Texpr = lclass[CurrentLexClass].htable;
+ /* define EOF for each automaton */
+ p = newTermEntry( EOFSTR );
+ p->token = EofToken; /* couldn't have remapped tokens yet, use EofToken */
+ hash_add(Texpr, EOFSTR, (Entry *)p);
+ list_add(&ExprOrder, (void *)newExpr(EOFSTR));
+ /* note: we use the actual ExprStr array
+ * here as TokenInd doesn't exist yet
+ */
+ ExprStr[EofToken] = EOFSTR;
+}
+
+void
+#ifdef __USE_PROTOS
+lexmode( int i )
+#else
+lexmode( i )
+int i;
+#endif
+{
+ require(i<NumLexClasses, "lexmode: invalid mode");
+ ExprStr = lclass[i].exprs;
+ Texpr = lclass[i].htable;
+ CurrentLexClass = i;
+}
+
+/* return index into lclass array of lexical class. return -1 if nonexistent */
+int
+#ifdef __USE_PROTOS
+LexClassIndex( char *cl )
+#else
+LexClassIndex( cl )
+char *cl;
+#endif
+{
+ int i;
+
+ for (i=0; i<NumLexClasses; i++)
+ {
+ if ( strcmp(lclass[i].classnum, cl) == 0 ) return i;
+ }
+ return -1;
+}
+
+int
+#ifdef __USE_PROTOS
+hasAction( char *expr )
+#else
+hasAction( expr )
+char *expr;
+#endif
+{
+ TermEntry *p;
+ require(expr!=NULL, "hasAction: invalid expr");
+
+ p = (TermEntry *) hash_get(Texpr, expr);
+ require(p!=NULL, eMsg1("hasAction: expr '%s' doesn't exist",expr));
+ return (p->action!=NULL);
+}
+
+void
+#ifdef __USE_PROTOS
+setHasAction( char *expr, char *action )
+#else
+setHasAction( expr, action )
+char *expr;
+char *action;
+#endif
+{
+ TermEntry *p;
+ require(expr!=NULL, "setHasAction: invalid expr");
+
+ p = (TermEntry *) hash_get(Texpr, expr);
+ require(p!=NULL, eMsg1("setHasAction: expr '%s' doesn't exist",expr));
+ p->action = action;
+}
+
+ForcedToken *
+#ifdef __USE_PROTOS
+newForcedToken(char *token, int tnum)
+#else
+newForcedToken(token, tnum)
+char *token;
+int tnum;
+#endif
+{
+ ForcedToken *ft = (ForcedToken *) calloc(1, sizeof(ForcedToken));
+ require(ft!=NULL, "out of memory");
+ ft->token = token;
+ ft->tnum = tnum;
+ return ft;
+}
+
+/*
+ * Make a token indirection array that remaps token numbers and then walk
+ * the appropriate symbol tables and SynDiag to change token numbers
+ */
+void
+#ifdef __USE_PROTOS
+RemapForcedTokens(void)
+#else
+RemapForcedTokens()
+#endif
+{
+ ListNode *p;
+ ForcedToken *q;
+ int max_token_number=0; /* MR9 23-Sep-97 Removed "unsigned" */
+ int i;
+
+ if ( ForcedTokens == NULL ) return;
+
+ /* find max token num */
+ for (p = ForcedTokens->next; p!=NULL; p=p->next)
+ {
+ q = (ForcedToken *) p->elem;
+ if ( q->tnum > max_token_number ) max_token_number = q->tnum;
+ }
+ fprintf(stderr, "max token number is %d\n", max_token_number);
+
+ /* make token indirection array */
+ TokenInd = (int *) calloc(max_token_number+1, sizeof(int));
+ LastTokenCounted = TokenNum;
+ TokenNum = max_token_number+1;
+ require(TokenInd!=NULL, "RemapForcedTokens: cannot allocate TokenInd");
+
+ /* fill token indirection array and change token id htable ; swap token indices */
+ for (i=1; i<TokenNum; i++) TokenInd[i] = i;
+ for (p = ForcedTokens->next; p!=NULL; p=p->next)
+ {
+ TermEntry *te;
+ int old_pos, t;
+
+ q = (ForcedToken *) p->elem;
+ fprintf(stderr, "%s forced to %d\n", q->token, q->tnum);
+ te = (TermEntry *) hash_get(Tname, q->token);
+ require(te!=NULL, "RemapForcedTokens: token not in hash table");
+ old_pos = te->token;
+ fprintf(stderr, "Before: TokenInd[old_pos==%d] is %d\n", old_pos, TokenInd[old_pos]);
+ fprintf(stderr, "Before: TokenInd[target==%d] is %d\n", q->tnum, TokenInd[q->tnum]);
+ q = (ForcedToken *) p->elem;
+ t = TokenInd[old_pos];
+ TokenInd[old_pos] = q->tnum;
+ TokenInd[q->tnum] = t;
+ te->token = q->tnum; /* update token type id symbol table */
+ fprintf(stderr, "After: TokenInd[old_pos==%d] is %d\n", old_pos, TokenInd[old_pos]);
+ fprintf(stderr, "After: TokenInd[target==%d] is %d\n", q->tnum, TokenInd[q->tnum]);
+
+ /* Change the token number in the sym tab entry for the exprs
+ * at the old position of the token id and the target position
+ */
+ /* update expr at target (if any) of forced token id */
+ if ( q->tnum < TokenNum ) /* is it a valid position? */
+ {
+ for (i=0; i<NumLexClasses; i++)
+ {
+ if ( lclass[i].exprs[q->tnum]!=NULL )
+ {
+ /* update the symbol table for this expr */
+ TermEntry *e = (TermEntry *) hash_get(lclass[i].htable, lclass[i].exprs[q->tnum]);
+ require(e!=NULL, "RemapForcedTokens: expr not in hash table");
+ e->token = old_pos;
+ fprintf(stderr, "found expr '%s' at target %d in lclass[%d]; changed to %d\n",
+ lclass[i].exprs[q->tnum], q->tnum, i, old_pos);
+ }
+ }
+ }
+ /* update expr at old position (if any) of forced token id */
+ for (i=0; i<NumLexClasses; i++)
+ {
+ if ( lclass[i].exprs[old_pos]!=NULL )
+ {
+ /* update the symbol table for this expr */
+ TermEntry *e = (TermEntry *) hash_get(lclass[i].htable, lclass[i].exprs[old_pos]);
+ require(e!=NULL, "RemapForcedTokens: expr not in hash table");
+ e->token = q->tnum;
+ fprintf(stderr, "found expr '%s' for id %s in lclass[%d]; changed to %d\n",
+ lclass[i].exprs[old_pos], q->token, i, q->tnum);
+ }
+ }
+ }
+
+ /* Update SynDiag */
+ RemapForcedTokensInSyntaxDiagram((Node *)SynDiag);
+}
+
+static void
+#ifdef __USE_PROTOS
+RemapForcedTokensInSyntaxDiagram(Node *p)
+#else
+RemapForcedTokensInSyntaxDiagram(p)
+Node *p;
+#endif
+{
+ Junction *j = (Junction *) p;
+ RuleRefNode *r = (RuleRefNode *) p;
+ TokNode *t = (TokNode *)p;
+
+ if ( p==NULL ) return;
+ require(p->ntype>=1 && p->ntype<=NumNodeTypes, "Remap...: invalid diagram node");
+ switch ( p->ntype )
+ {
+ case nJunction :
+ if ( j->visited ) return;
+ if ( j->jtype == EndRule ) return;
+ j->visited = TRUE;
+ RemapForcedTokensInSyntaxDiagram( j->p1 );
+ RemapForcedTokensInSyntaxDiagram( j->p2 );
+ j->visited = FALSE;
+ return;
+ case nRuleRef :
+ RemapForcedTokensInSyntaxDiagram( r->next );
+ return;
+ case nToken :
+ if ( t->remapped ) return; /* we've been here before */
+ t->remapped = 1;
+ fprintf(stderr, "remapping %d to %d\n", t->token, TokenInd[t->token]);
+ t->token = TokenInd[t->token];
+ RemapForcedTokensInSyntaxDiagram( t->next );
+ return;
+ case nAction :
+ RemapForcedTokensInSyntaxDiagram( ((ActionNode *)p)->next );
+ return;
+ default :
+ fatal_internal("invalid node type");
+ }
+}
+
+/*
+ * Add a token name. Return the token number associated with it. If it already
+ * exists, then return the token number assigned to it.
+ *
+ * Track the order in which tokens are found so that the DLG output maintains
+ * that order. It also lets us map token numbers to strings.
+ */
+int
+#ifdef __USE_PROTOS
+addTname( char *token )
+#else
+addTname( token )
+char *token;
+#endif
+{
+ TermEntry *p;
+ require(token!=NULL, "addTname: invalid token name");
+
+ if ( (p=(TermEntry *)hash_get(Tname, token)) != NULL ) return p->token;
+ p = newTermEntry( token );
+ Ttrack( p->str );
+ p->token = TokenNum++;
+ hash_add(Tname, token, (Entry *)p);
+ return p->token;
+}
+
+/* This is the same as addTname except we force the TokenNum to be tnum.
+ * We don't have to use the Forced token stuff as no tokens will have
+ * been defined with #tokens when this is called. This is only called
+ * when a #tokdefs meta-op is used.
+ */
+int
+#ifdef __USE_PROTOS
+addForcedTname( char *token, int tnum )
+#else
+addForcedTname( token, tnum )
+char *token;
+int tnum;
+#endif
+{
+ TermEntry *p;
+ require(token!=NULL, "addTname: invalid token name");
+
+ if ( (p=(TermEntry *)hash_get(Tname, token)) != NULL ) return p->token;
+ p = newTermEntry( token );
+ Ttrack( p->str );
+ p->token = tnum;
+ hash_add(Tname, token, (Entry *)p);
+ return p->token;
+}
+
+/*
+ * Add a token expr. Return the token number associated with it. If it already
+ * exists, then return the token number assigned to it.
+ */
+int
+#ifdef __USE_PROTOS
+addTexpr( char *expr )
+#else
+addTexpr( expr )
+char *expr;
+#endif
+{
+ TermEntry *p;
+ require(expr!=NULL, "addTexpr: invalid regular expression");
+
+ if ( (p=(TermEntry *)hash_get(Texpr, expr)) != NULL ) return p->token;
+ p = newTermEntry( expr );
+ Ttrack( p->str );
+ /* track the order in which they occur */
+ list_add(&ExprOrder, (void *)newExpr(p->str));
+ p->token = TokenNum++;
+ hash_add(Texpr, expr, (Entry *)p);
+ return p->token;
+}
+
+/* return the token number of 'term'. Return 0 if no 'term' exists */
+int
+#ifdef __USE_PROTOS
+Tnum( char *term )
+#else
+Tnum( term )
+char *term;
+#endif
+{
+ TermEntry *p;
+ require(term!=NULL, "Tnum: invalid terminal");
+
+ if ( *term=='"' ) p = (TermEntry *) hash_get(Texpr, term);
+ else p = (TermEntry *) hash_get(Tname, term);
+ if ( p == NULL ) return 0;
+ else return p->token;
+}
+
+/* associate a Name with an expr. If both have been already assigned
+ * token numbers, then an error is reported. Add the token or expr
+ * that has not been added if no error. This 'represents' the #token
+ * ANTLR pseudo-op. If both have not been defined, define them both
+ * linked to same token number.
+ */
+void
+#ifdef __USE_PROTOS
+Tklink( char *token, char *expr )
+#else
+Tklink( token, expr )
+char *token;
+char *expr;
+#endif
+{
+ TermEntry *p, *q;
+ require(token!=NULL && expr!=NULL, "Tklink: invalid token name and/or expr");
+
+ p = (TermEntry *) hash_get(Tname, token);
+ q = (TermEntry *) hash_get(Texpr, expr);
+ if ( p != NULL && q != NULL ) /* both defined */
+ {
+ warn( eMsg2("token name %s and rexpr %s already defined; ignored",
+ token, expr) );
+ return;
+ }
+ if ( p==NULL && q==NULL ) /* both not defined */
+ {
+ int t = addTname( token );
+ q = newTermEntry( expr );
+ hash_add(Texpr, expr, (Entry *)q);
+ q->token = t;
+ /* note: we use the actual ExprStr array
+ * here as TokenInd doesn't exist yet
+ */
+ ExprStr[t] = q->str;
+ /* track the order in which they occur */
+ list_add(&ExprOrder, (void *)newExpr(q->str));
+ return;
+ }
+ if ( p != NULL ) /* one is defined, one is not */
+ {
+ q = newTermEntry( expr );
+ hash_add(Texpr, expr, (Entry *)q);
+ q->token = p->token;
+ ExprStr[p->token] = q->str; /* both expr and token str defined now */
+ list_add(&ExprOrder, (void *)newExpr(q->str));
+ }
+ else /* trying to associate name with expr here*/
+ {
+ p = newTermEntry( token );
+ hash_add(Tname, token, (Entry *)p);
+ p->token = q->token;
+ TokenStr[p->token] = p->str;/* both expr and token str defined now */
+ }
+}
+
+/*
+ * Given a string, this function allocates and returns a pointer to a
+ * hash table record of size 'sz' whose "str" pointer is reset to a position
+ * in the string table.
+ */
+Entry *
+#ifdef __USE_PROTOS
+newEntry( char *text, int sz )
+#else
+newEntry( text, sz )
+char *text;
+int sz;
+#endif
+{
+ Entry *p;
+ require(text!=NULL, "new: NULL terminal");
+
+ if ( (p = (Entry *) calloc(1,sz)) == 0 )
+ {
+ fatal_internal("newEntry: out of memory for terminals\n");
+ exit(PCCTS_EXIT_FAILURE);
+ }
+ p->str = mystrdup(text);
+
+ return(p);
+}
+
+/*
+ * add an element to a list.
+ *
+ * Any non-empty list has a sentinel node whose 'elem' pointer is really
+ * a pointer to the last element. (i.e. length(list) = #elemIn(list)+1).
+ * Elements are appended to the list.
+ */
+void
+#ifdef __USE_PROTOS
+list_add( ListNode **list, void *e )
+#else
+list_add( list, e )
+ListNode **list;
+void *e;
+#endif
+{
+ ListNode *p, *tail;
+ require(e!=NULL, "list_add: attempting to add NULL list element");
+
+ p = newListNode;
+ require(p!=NULL, "list_add: cannot alloc new list node");
+ p->elem = e;
+ if ( *list == NULL )
+ {
+ ListNode *sentinel = newListNode;
+ require(sentinel!=NULL, "list_add: cannot alloc sentinel node");
+ *list=sentinel;
+ sentinel->next = p;
+ sentinel->elem = (char *)p; /* set tail pointer */
+ }
+ else /* find end of list */
+ {
+ tail = (ListNode *) (*list)->elem; /* get tail pointer */
+ tail->next = p;
+ (*list)->elem = (char *) p; /* reset tail */
+ }
+}
+
+/* MR10 list_free() frees the ListNode elements in the list */
+/* MR10 if freeData then free the data elements of the list too */
+
+void
+#ifdef __USE_PROTOS
+list_free(ListNode **list,int freeData)
+#else
+list_free(list,freeData)
+ ListNode **list;
+ int freeData;
+#endif
+{
+ ListNode *p;
+ ListNode *next;
+
+ if (list == NULL) return;
+ if (*list == NULL) return;
+ for (p=*list; p != NULL; p=next) {
+ next=p->next;
+ if (freeData && p->elem != NULL) {
+ free( (char *) p->elem);
+ };
+ free( (char *) p);
+ };
+ *list=NULL;
+}
+
+void
+#ifdef __USE_PROTOS
+list_apply( ListNode *list, void (*f)(void *) )
+#else
+list_apply( list, f )
+ListNode *list;
+void (*f)();
+#endif
+{
+ ListNode *p;
+ require(f!=NULL, "list_apply: NULL function to apply");
+
+ if ( list == NULL ) return;
+ for (p = list->next; p!=NULL; p=p->next) (*f)( p->elem );
+}
+
+/* MR27 */
+
+#ifdef __USE_PROTOS
+int list_search_cstring(ListNode *list, char * cstring)
+#else
+int list_search_cstring(list, cstring)
+ ListNode * list;
+ char * cstring;
+#endif
+{
+ ListNode *p;
+ if (list == NULL ) return 0;
+ for (p = list->next; p!=NULL; p=p->next) {
+ if (p->elem == NULL) continue;
+ if (0 == strcmp((char *) p->elem , cstring)) return 1;
+ }
+ return 0;
+}
+
+ /* F O L L O W C y c l e S t u f f */
+
+/* make a key based upon (rulename, computation, k value).
+ * Computation values are 'i'==FIRST, 'o'==FOLLOW.
+ */
+
+/* MR10 Make the key all characters so it can be read easily */
+/* MR10 by a simple dump program. Also, separates */
+/* MR10 'o' and 'i' from rule name */
+
+char *
+#ifdef __USE_PROTOS
+Fkey( char *rule, int computation, int k )
+#else
+Fkey( rule, computation, k )
+char *rule;
+int computation;
+int k;
+#endif
+{
+ static char key[MaxRuleName+2+2+1]; /* MR10 */
+ int i;
+
+ if ( k > 99 ) /* MR10 */
+ fatal("k>99 is too big for this implementation of ANTLR!\n"); /* MR10 */
+ if ( (i=strlen(rule)) > MaxRuleName ) /* MR10 */
+ fatal( eMsgd("rule name > max of %d\n", MaxRuleName) ); /* MR10 */
+ strcpy(key,rule);
+
+/* MR10 */ key[i]='*';
+/* MR10 */ key[i+1] = (char) computation; /* MR20 G. Hobbelt */
+/* MR10 */ if (k < 10) {
+/* MR10 */ key[i+2] = (char) ( '0' + k);
+/* MR10 */ key[i+3] = '\0';
+/* MR10 */ } else {
+/* MR10 */ key[i+2] = (char) ( '0' + k/10);
+/* MR10 */ key[i+3] = (char) ( '0' + k % 10);
+/* MR10 */ key[i+4] = '\0';
+/* MR10 */ };
+
+ return key;
+}
+
+/* Push a rule onto the kth FOLLOW stack */
+void
+#ifdef __USE_PROTOS
+FoPush( char *rule, int k )
+#else
+FoPush( rule, k )
+char *rule;
+int k;
+#endif
+{
+ RuleEntry *r;
+ require(rule!=NULL, "FoPush: tried to push NULL rule");
+ require(k<=CLL_k, "FoPush: tried to access non-existent stack");
+
+ /*fprintf(stderr, "FoPush(%s)\n", rule);*/
+ r = (RuleEntry *) hash_get(Rname, rule);
+ if ( r == NULL ) {fatal_internal( eMsg1("rule %s must be defined but isn't", rule) );}
+ if ( FoStack[k] == NULL ) /* Does the kth stack exist yet? */
+ {
+ /*fprintf(stderr, "allocating FoStack\n");*/
+ FoStack[k] = (int *) calloc(FoStackSize, sizeof(int));
+ require(FoStack[k]!=NULL, "FoPush: cannot allocate FOLLOW stack\n");
+ }
+ if ( FoTOS[k] == NULL )
+ {
+ FoTOS[k]=FoStack[k];
+ *(FoTOS[k]) = r->rulenum;
+ }
+ else
+ {
+#ifdef MEMCHK
+ require(valid(FoStack[k]), "FoPush: invalid FoStack");
+#endif
+ if ( FoTOS[k] >= &(FoStack[k][FoStackSize-1]) )
+ fatal( eMsgd("exceeded max depth of FOLLOW recursion (%d)\n",
+ FoStackSize) );
+ require(FoTOS[k]>=FoStack[k],
+ eMsg1("FoPush: FoStack stack-ptr is playing out of its sandbox",
+ rule));
+ ++(FoTOS[k]);
+ *(FoTOS[k]) = r->rulenum;
+ }
+ {
+ /*
+**** int *p;
+**** fprintf(stderr, "FoStack[k=%d]:\n", k);
+**** for (p=FoStack[k]; p<=FoTOS[k]; p++)
+**** {
+**** fprintf(stderr, "\t%s\n", RulePtr[*p]->rname);
+**** }
+ */
+ }
+}
+
+/* Pop one rule off of the FOLLOW stack. TOS ptr is NULL if empty. */
+void
+#ifdef __USE_PROTOS
+FoPop( int k )
+#else
+FoPop( k )
+int k;
+#endif
+{
+ require(k<=CLL_k, "FoPop: tried to access non-existent stack");
+ /*fprintf(stderr, "FoPop\n");*/
+ require(FoTOS[k]>=FoStack[k]&&FoTOS[k]<=&(FoStack[k][FoStackSize-1]),
+ "FoPop: FoStack stack-ptr is playing out of its sandbox");
+ if ( FoTOS[k] == FoStack[k] ) FoTOS[k] = NULL;
+ else (FoTOS[k])--;
+}
+
+/* Compute FOLLOW cycle.
+ * Mark all FOLLOW sets for rules in cycle as incomplete.
+ * Then, save cycle on the cycle list (Cycles) for later resolution.
+ * The Cycle is stored in the form:
+ * (head of cycle==croot, rest of rules in cycle==cyclicDep)
+ *
+ * e.g. (Fo means "FOLLOW of", "-->" means requires or depends on)
+ *
+ * Fo(x)-->Fo(a)-->Fo(b)-->Fo(c)-->Fo(x)
+ * ^----Infinite recursion (cycle)
+ *
+ * the cycle would be: x -> {a,b,c} or stored as (x,{a,b,c}). Fo(x) depends
+ * on the FOLLOW of a,b, and c. The root of a cycle is always complete after
+ * Fo(x) finishes. Fo(a,b,c) however are not. It turns out that all rules
+ * in a FOLLOW cycle have the same FOLLOW set.
+ */
+void
+#ifdef __USE_PROTOS
+RegisterCycle( char *rule, int k )
+#else
+RegisterCycle( rule, k )
+char *rule;
+int k;
+#endif
+{
+ CacheEntry *f;
+ Cycle *c;
+ int *p;
+ RuleEntry *r;
+ require(rule!=NULL, "RegisterCycle: tried to register NULL rule");
+ require(k<=CLL_k, "RegisterCycle: tried to access non-existent stack");
+
+ /*fprintf(stderr, "RegisterCycle(%s)\n", rule);*/
+ /* Find cycle start */
+ r = (RuleEntry *) hash_get(Rname, rule);
+ require(r!=NULL,eMsg1("rule %s must be defined but isn't", rule));
+ require(FoTOS[k]>=FoStack[k]&&FoTOS[k]<=&(FoStack[k][FoStackSize-1]),
+ eMsg1("RegisterCycle(%s): FoStack stack-ptr is playing out of its sandbox",
+ rule));
+/*** if ( FoTOS[k]<FoStack[k]||FoTOS[k]>&(FoStack[k][FoStackSize-1]) )
+**** {
+**** fprintf(stderr, "RegisterCycle(%s): FoStack stack-ptr is playing out of its sandbox\n",
+**** rule);
+**** fprintf(stderr, "RegisterCycle: sp==0x%x out of bounds 0x%x...0x%x\n",
+**** FoTOS[k], FoStack[k], &(FoStack[k][FoStackSize-1]));
+**** exit(PCCTS_EXIT_FAILURE);
+**** }
+****/
+
+#ifdef MEMCHK
+ require(valid(FoStack[k]), "RegisterCycle: invalid FoStack");
+#endif
+ for (p=FoTOS[k]; *p != r->rulenum && p >= FoStack[k]; --p) {;}
+ require(p>=FoStack[k], "RegisterCycle: FoStack is screwed up beyond belief");
+ if ( p == FoTOS[k] ) return; /* don't worry about cycles to oneself */
+
+ /* compute cyclic dependents (rules in cycle except head) */
+ c = newCycle;
+ require(c!=NULL, "RegisterCycle: couldn't alloc new cycle");
+ c->cyclicDep = empty;
+ c->croot = *p++; /* record root of cycle */
+ for (; p<=FoTOS[k]; p++)
+ {
+ /* Mark all dependent rules as incomplete */
+ f = (CacheEntry *) hash_get(Fcache, Fkey(RulePtr[*p]->rname,'o',k));
+ if ( f==NULL )
+ {
+ f = newCacheEntry( Fkey(RulePtr[*p]->rname,'o',k) );
+ hash_add(Fcache, Fkey(RulePtr[*p]->rname,'o',k), (Entry *)f);
+ }
+ f->incomplete = TRUE;
+
+ set_orel(*p, &(c->cyclicDep)); /* mark rule as dependent of croot */
+ }
+ list_add(&(Cycles[k]), (void *)c);
+}
+
+/* make all rules in cycle complete
+ *
+ * while ( some set has changed ) do
+ * for each cycle do
+ * if degree of FOLLOW set for croot > old degree then
+ * update all FOLLOW sets for rules in cyclic dependency
+ * change = TRUE
+ * endif
+ * endfor
+ * endwhile
+ */
+void
+#ifdef __USE_PROTOS
+ResolveFoCycles( int k )
+#else
+ResolveFoCycles( k )
+int k;
+#endif
+{
+ ListNode *p, *q;
+ Cycle *c;
+ int changed = 1;
+ CacheEntry *f,*g;
+ int r;
+/* int i; */ /* MR10 not useful */
+ unsigned d;
+
+ unsigned *cursor; /* MR10 */
+ unsigned *origin; /* MR10 */
+
+ /*fprintf(stderr, "Resolving following cycles for %d\n", k);*/
+ while ( changed )
+ {
+ changed = 0;
+/* MR10 i = 0; */
+ for (p = Cycles[k]->next; p!=NULL; p=p->next)
+ {
+ c = (Cycle *) p->elem;
+ /*fprintf(stderr, "cycle %d: %s -->", i++, RulePtr[c->croot]->rname);*/
+ /*s_fprT(stderr, c->cyclicDep);*/
+ /*fprintf(stderr, "\n");*/
+ f = (CacheEntry *)
+ hash_get(Fcache, Fkey(RulePtr[c->croot]->rname,'o',k));
+ require(f!=NULL, eMsg1("FOLLOW(%s) must be in cache but isn't", RulePtr[c->croot]->rname) );
+ if ( (d=set_deg(f->fset)) > c->deg )
+ {
+ /*fprintf(stderr, "Fo(%s) has changed\n", RulePtr[c->croot]->rname);*/
+ changed = 1;
+ c->deg = d; /* update cycle FOLLOW set degree */
+
+/* MR10 */ origin=set_pdq(c->cyclicDep);
+/* MR10 */ for (cursor=origin; *cursor != nil; cursor++) {
+/* MR10 */ r=*cursor;
+
+/******** while ( !set_nil(c->cyclicDep) ) { *****/
+/******** r = set_int(c->cyclicDep); *****/
+/******** set_rm(r, c->cyclicDep); *****/
+
+ /*fprintf(stderr, "updating Fo(%s)\n", RulePtr[r]->rname);*/
+ g = (CacheEntry *)
+ hash_get(Fcache, Fkey(RulePtr[r]->rname,'o',k));
+ require(g!=NULL, eMsg1("FOLLOW(%s) must be in cache but isn't", RulePtr[r]->rname) );
+ set_orin(&(g->fset), f->fset);
+ g->incomplete = FALSE;
+ }
+/* MR10 */ free( (char *) origin);
+/* MR10 */ origin=NULL;
+ }
+ }
+/* MR10 - this if statement appears to be meaningless since i is always 0 */
+/* MR10 if ( i == 1 ) changed = 0; */ /* if only 1 cycle, no need to repeat */
+ }
+ /* kill Cycle list */
+ for (q = Cycles[k]->next; q != NULL; q=p)
+ {
+ p = q->next;
+ set_free( ((Cycle *)q->elem)->cyclicDep );
+ free((char *)q);
+ }
+ free( (char *)Cycles[k] );
+ Cycles[k] = NULL;
+}
+
+
+ /* P r i n t i n g S y n t a x D i a g r a m s */
+
+static void
+#ifdef __USE_PROTOS
+pBlk( Junction *q, int btype )
+#else
+pBlk( q, btype )
+Junction *q;
+int btype;
+#endif
+{
+ int k,a;
+ Junction *alt, *p;
+
+ q->end->pvisited = TRUE;
+ if ( btype == aLoopBegin )
+ {
+ require(q->p2!=NULL, "pBlk: invalid ()* block");
+ PRINT(q->p1);
+ alt = (Junction *)q->p2;
+ PRINT(alt->p1);
+ if ( PrintAnnotate )
+ {
+ printf(" /* Opt ");
+ k = 1;
+ while ( !set_nil(alt->fset[k]) )
+ {
+ s_fprT(stdout, alt->fset[k]);
+ if ( k++ == CLL_k ) break;
+ if ( !set_nil(alt->fset[k]) ) printf(", ");
+ }
+ printf(" */\n");
+ }
+ return;
+ }
+ for (a=1,alt=q; alt != NULL; alt= (Junction *) alt->p2, a++)
+ {
+ if ( alt->p1 != NULL ) PRINT(alt->p1);
+ if ( PrintAnnotate )
+ {
+ printf( " /* [%d] ", alt->altnum);
+ k = 1;
+ while ( !set_nil(alt->fset[k]) )
+ {
+ s_fprT(stdout, alt->fset[k]);
+ if ( k++ == CLL_k ) break;
+ if ( !set_nil(alt->fset[k]) ) printf(", ");
+ }
+ if ( alt->p2 == NULL && btype == aOptBlk )
+ printf( " (optional branch) */\n");
+ else printf( " */\n");
+ }
+
+ /* ignore implied empty alt of Plus blocks */
+ if ( alt->p2 != NULL && ((Junction *)alt->p2)->ignore ) break;
+
+ if ( alt->p2 != NULL && !(((Junction *)alt->p2)->p2==NULL && btype == aOptBlk) )
+ {
+ if ( pLevel == 1 )
+ {
+ printf("\n");
+ if ( a+1==pAlt1 || a+1==pAlt2 ) printf("=>");
+ printf("\t");
+ }
+ else printf(" ");
+ printf("|");
+ if ( pLevel == 1 )
+ {
+ p = (Junction *) ((Junction *)alt->p2)->p1;
+ while ( p!=NULL )
+ {
+ if ( p->ntype==nAction )
+ {
+ p=(Junction *)((ActionNode *)p)->next;
+ continue;
+ }
+ if ( p->ntype!=nJunction )
+ {
+ break;
+ }
+ if ( p->jtype==EndBlk || p->jtype==EndRule )
+ {
+ p = NULL;
+ break;
+ }
+ p = (Junction *)p->p1;
+ }
+ if ( p==NULL ) printf("\n\t"); /* Empty alt? */
+ }
+ }
+ }
+ q->end->pvisited = FALSE;
+}
+
+/* How to print out a junction */
+void
+#ifdef __USE_PROTOS
+pJunc( Junction *q )
+#else
+pJunc( q )
+Junction *q;
+#endif
+{
+ int dum_k;
+ int doing_rule;
+ require(q!=NULL, "pJunc: NULL node");
+ require(q->ntype==nJunction, "pJunc: not junction");
+
+ if ( q->pvisited == TRUE ) return;
+ q->pvisited = TRUE;
+ switch ( q->jtype )
+ {
+ case aSubBlk :
+ if ( PrintAnnotate ) First(q, 1, q->jtype, &dum_k);
+ if ( q->end->p1 != NULL && ((Junction *)q->end->p1)->ntype==nJunction &&
+ ((Junction *)q->end->p1)->jtype == EndRule ) doing_rule = 1;
+ else doing_rule = 0;
+ pLevel++;
+ if ( pLevel==1 )
+ {
+ if ( pAlt1==1 ) printf("=>");
+ printf("\t");
+ }
+ else printf(" ");
+ if ( doing_rule )
+ {
+ if ( pLevel==1 ) printf(" ");
+ pBlk(q,q->jtype);
+ }
+ else {
+ printf("(");
+ if ( pLevel==1 ) printf(" ");
+ pBlk(q,q->jtype);
+ if ( pLevel>1 ) printf(" ");
+ printf(")");
+ }
+ if ( q->guess ) printf("?");
+ pLevel--;
+ if ( PrintAnnotate ) freeBlkFsets(q);
+ if ( q->end->p1 != NULL ) PRINT(q->end->p1);
+ break;
+ case aOptBlk :
+ if ( PrintAnnotate ) First(q, 1, q->jtype, &dum_k);
+ pLevel++;
+ if ( pLevel==1 )
+ {
+ if ( pAlt1==1 ) printf("=>");
+ printf("\t");
+ }
+ else printf(" ");
+ printf("{");
+ if ( pLevel==1 ) printf(" ");
+ pBlk(q,q->jtype);
+ if ( pLevel>1 ) printf(" ");
+ else printf("\n\t");
+ printf("}");
+ pLevel--;
+ if ( PrintAnnotate ) freeBlkFsets(q);
+ if ( q->end->p1 != NULL ) PRINT(q->end->p1);
+ break;
+ case aLoopBegin :
+ if ( PrintAnnotate ) First(q, 1, q->jtype, &dum_k);
+ pLevel++;
+ if ( pLevel==1 )
+ {
+ if ( pAlt1==1 ) printf("=>");
+ printf("\t");
+ }
+ else printf(" ");
+ printf("(");
+ if ( pLevel==1 ) printf(" ");
+ pBlk(q,q->jtype);
+ if ( pLevel>1 ) printf(" ");
+ else printf("\n\t");
+ printf(")*");
+ pLevel--;
+ if ( PrintAnnotate ) freeBlkFsets(q);
+ if ( q->end->p1 != NULL ) PRINT(q->end->p1);
+ break;
+ case aLoopBlk :
+ if ( PrintAnnotate ) First(q, 1, q->jtype, &dum_k);
+ pBlk(q,q->jtype);
+ if ( PrintAnnotate ) freeBlkFsets(q);
+ break;
+ case aPlusBlk :
+ if ( PrintAnnotate ) First(q, 1, q->jtype, &dum_k);
+ pLevel++;
+ if ( pLevel==1 )
+ {
+ if ( pAlt1==1 ) printf("=>");
+ printf("\t");
+ }
+ else printf(" ");
+ printf("(");
+ if ( pLevel==1 ) printf(" ");
+ pBlk(q,q->jtype);
+ if ( pLevel>1 ) printf(" ");
+ printf(")+");
+ pLevel--;
+ if ( PrintAnnotate ) freeBlkFsets(q);
+ if ( q->end->p1 != NULL ) PRINT(q->end->p1);
+ break;
+ case EndBlk :
+ break;
+ case RuleBlk :
+ printf( "\n%s :\n", q->rname);
+ PRINT(q->p1);
+ if ( q->p2 != NULL ) PRINT(q->p2);
+ break;
+ case Generic :
+ if ( q->p1 != NULL ) PRINT(q->p1);
+ q->pvisited = FALSE;
+ if ( q->p2 != NULL ) PRINT(q->p2);
+ break;
+ case EndRule :
+ printf( "\n\t;\n");
+ break;
+ }
+ q->pvisited = FALSE;
+}
+
+/* How to print out a rule reference node */
+void
+#ifdef __USE_PROTOS
+pRuleRef( RuleRefNode *p )
+#else
+pRuleRef( p )
+RuleRefNode *p;
+#endif
+{
+ require(p!=NULL, "pRuleRef: NULL node");
+ require(p->ntype==nRuleRef, "pRuleRef: not rule ref node");
+
+ printf( " %s", p->text);
+ PRINT(p->next);
+}
+
+/* How to print out a terminal node */
+void
+#ifdef __USE_PROTOS
+pToken( TokNode *p )
+#else
+pToken( p )
+TokNode *p;
+#endif
+{
+ require(p!=NULL, "pToken: NULL node");
+ require(p->ntype==nToken, "pToken: not token node");
+
+ if ( p->wild_card ) printf(" .");
+ printf( " %s", TerminalString(p->token));
+ PRINT(p->next);
+}
+
+/* How to print out a terminal node */
+void
+#ifdef __USE_PROTOS
+pAction( ActionNode *p )
+#else
+pAction( p )
+ActionNode *p;
+#endif
+{
+ require(p!=NULL, "pAction: NULL node");
+ require(p->ntype==nAction, "pAction: not action node");
+
+ PRINT(p->next);
+}
+
+ /* F i l l F o l l o w L i s t s */
+
+/*
+ * Search all rules for all rule reference nodes, q to rule, r.
+ * Add q->next to follow list dangling off of rule r.
+ * i.e.
+ *
+ * r: -o-R-o-->o--> Ptr to node following rule r in another rule
+ * |
+ * o--> Ptr to node following another reference to r.
+ *
+ * This is the data structure employed to avoid FOLLOW set computation. We
+ * simply compute the FIRST (reach) of the EndRule Node which follows the
+ * list found at the end of all rules which are referenced elsewhere. Rules
+ * not invoked by other rules have no follow list (r->end->p1==NULL).
+ * Generally, only start symbols are not invoked by another rule.
+ *
+ * Note that this mechanism also gives a free cross-reference mechanism.
+ *
+ * The entire syntax diagram is layed out like this:
+ *
+ * SynDiag
+ * |
+ * v
+ * o-->R1--o
+ * |
+ * o-->R2--o
+ * |
+ * ...
+ * |
+ * o-->Rn--o
+ *
+ */
+void
+#ifdef __USE_PROTOS
+FoLink( Node *p )
+#else
+FoLink( p )
+Node *p;
+#endif
+{
+ RuleEntry *q;
+ Junction *j = (Junction *) p;
+ RuleRefNode *r = (RuleRefNode *) p;
+
+ if ( p==NULL ) return;
+ require(p->ntype>=1 && p->ntype<=NumNodeTypes,
+ eMsgd("FoLink: invalid diagram node: ntype==%d",p->ntype));
+ switch ( p->ntype )
+ {
+ case nJunction :
+ if ( j->fvisited ) return;
+ if ( j->jtype == EndRule ) return;
+ j->fvisited = TRUE;
+ FoLink( j->p1 );
+ FoLink( j->p2 );
+/* MR14 */
+/* MR14 */ /* Need to determine whether the guess block is an */
+/* MR14 */ /* of the form (alpha)? beta before follow sets are */
+/* MR14 */ /* computed. This is necessary to solve problem */
+/* MR14 */ /* of doing follow on the alpha of an (alpha)? beta block. */
+/* MR14 */
+/* MR14 */ /* This is performed by analysis_point as a side-effect. */
+/* MR14 */
+/* MR14 */
+/* MR14 */ if (j->jtype == aSubBlk && j->guess) {
+/* MR14 */ Junction *ignore;
+/* MR14 */ ignore=analysis_point(j);
+/* MR14 */ }
+/* MR14 */
+ return;
+ case nRuleRef :
+ if ( r->linked ) return;
+ q = (RuleEntry *) hash_get(Rname, r->text);
+ if ( q == NULL )
+ {
+ warnFL( eMsg1("rule %s not defined",r->text), FileStr[r->file], r->line );
+ }
+ else
+ {
+ if ( r->parms!=NULL && RulePtr[q->rulenum]->pdecl==NULL )
+ {
+ warnFL( eMsg1("rule %s accepts no parameter(s)", r->text),
+ FileStr[r->file], r->line );
+ }
+ if ( r->parms==NULL && RulePtr[q->rulenum]->pdecl!=NULL )
+ {
+ warnFL( eMsg1("rule %s requires parameter(s)", r->text),
+ FileStr[r->file], r->line );
+ }
+ if ( r->assign!=NULL && RulePtr[q->rulenum]->ret==NULL )
+ {
+ warnFL( eMsg1("rule %s yields no return value(s)", r->text),
+ FileStr[r->file], r->line );
+ }
+ if ( r->assign==NULL && RulePtr[q->rulenum]->ret!=NULL )
+ {
+ warnFL( eMsg1("rule %s returns a value(s)", r->text),
+ FileStr[r->file], r->line );
+ }
+ if ( !r->linked )
+ {
+ addFoLink( r->next, r->rname, RulePtr[q->rulenum] );
+ r->linked = TRUE;
+ }
+ }
+ FoLink( r->next );
+ return;
+ case nToken :
+ FoLink( ((TokNode *)p)->next );
+ return;
+ case nAction :
+ FoLink( ((ActionNode *)p)->next );
+ return;
+ default :
+ fatal_internal("invalid node type");
+ }
+}
+
+/*
+ * Add a reference to the end of a rule.
+ *
+ * 'r' points to the RuleBlk node in a rule. r->end points to the last node
+ * (EndRule jtype) in a rule.
+ *
+ * Initial:
+ * r->end --> o
+ *
+ * After:
+ * r->end --> o-->o--> Ptr to node following rule r in another rule
+ * |
+ * o--> Ptr to node following another reference to r.
+ *
+ * Note that the links are added to the head of the list so that r->end->p1
+ * always points to the most recently added follow-link. At the end, it should
+ * point to the last reference found in the grammar (starting from the 1st rule).
+ */
+void
+#ifdef __USE_PROTOS
+addFoLink( Node *p, char *rname, Junction *r )
+#else
+addFoLink( p, rname, r )
+Node *p;
+char *rname;
+Junction *r;
+#endif
+{
+ Junction *j;
+ require(r!=NULL, "addFoLink: incorrect rule graph");
+ require(r->end!=NULL, "addFoLink: incorrect rule graph");
+ require(r->end->jtype==EndRule, "addFoLink: incorrect rule graph");
+ require(p!=NULL, "addFoLink: NULL FOLLOW link");
+
+ j = newJunction();
+ j->rname = rname; /* rname on follow links point to target rule */
+ j->p1 = p; /* link to other rule */
+ j->p2 = (Node *) r->end->p1;/* point to head of list */
+ r->end->p1 = (Node *) j; /* reset head to point to new node */
+}
+
+void
+#ifdef __USE_PROTOS
+GenCrossRef( Junction *p )
+#else
+GenCrossRef( p )
+Junction *p;
+#endif
+{
+ set a;
+ Junction *j;
+ RuleEntry *q;
+ unsigned e;
+ require(p!=NULL, "GenCrossRef: why are you passing me a null grammar?");
+
+ printf("Cross Reference:\n\n");
+ a = empty;
+ for (; p!=NULL; p = (Junction *)p->p2)
+ {
+ printf("Rule %20s referenced by {", p->rname);
+ /* make a set of rules for uniqueness */
+ for (j = (Junction *)(p->end)->p1; j!=NULL; j = (Junction *)j->p2)
+ {
+ q = (RuleEntry *) hash_get(Rname, j->rname);
+ require(q!=NULL, "GenCrossRef: FoLinks are screwed up");
+ set_orel(q->rulenum, &a);
+ }
+ for (; !set_nil(a); set_rm(e, a))
+ {
+ e = set_int(a);
+ printf(" %s", RulePtr[e]->rname);
+ }
+ printf(" }\n");
+ }
+ set_free( a );
+}
+
+/*
+ The single argument is a pointer to the start of an element of a
+ C++ style function prototypet list. Given a pointer to the start of
+ an formal we must locate the comma (or the end of the string)
+ and locate the datatype, formal name, and initial value expression.
+
+ The function returns a pointer to the character following the comma
+ which terminates the formal declaration, or a pointer to the end of
+ the string if none was found.
+
+ I thought we were parsing specialists, how come I'm doing this by
+ hand written code ?
+
+ Examples of input:
+
+ Foo f,
+ Foo f = Foo(1),
+ Foo f = Foo(1,2),
+ Foo f = &farray[1,2],
+ Foo f = ",",
+ Foo f = ',',
+ TFoo<int,char> f = TFoo<int,char>(1,2),
+
+ A non-zero value for nesting indicates a problem matching '(' and ')',
+ '[' and ']', '<' and '>', '{' and '}', or improperly terminated string
+ or character literal.
+
+*/
+
+
+/*
+ * Don't care if it is a valid string literal or not, just find the end
+ * Start with pointer to leading "\""
+ */
+
+#ifdef __USE_PROTOS
+char * skipStringLiteral(char *pCurrent)
+#else
+char * skipStringLiteral(pCurrent)
+char *pCurrent;
+#endif
+{
+ char *p = pCurrent;
+ if (*p == 0) return p;
+ require (*p == '\"', "skipStringLiteral")
+ p++;
+ for (p = p; *p != 0; p++) {
+ if (*p == '\\') {
+ p++;
+ if (*p == 0) break;
+ p++;
+ }
+ if (*p == '\"') {
+ p++;
+ break;
+ }
+ }
+ return p;
+}
+
+/*
+ * Don't care if it is a valid character literal or not, just find the end
+ * Start with pointer to leading "'"
+ */
+
+#ifdef __USE_PROTOS
+char * skipCharLiteral(char *pStart)
+#else
+char * skipCharLiteral(pStart)
+ char *pStart;
+#endif
+{
+ char *p = pStart;
+ if (*p == 0) return p;
+ require (*p == '\'', "skipCharLiteral")
+ p++;
+ for (p = p; *p != 0; p++) {
+ if (*p == '\\') {
+ p++;
+ if (*p == 0) break;
+ p++;
+ }
+ if (*p == '\'') {
+ p++;
+ break;
+ }
+ }
+ return p;
+}
+
+#ifdef __USE_PROTOS
+char * skipSpaces(char *pStart)
+#else
+char * skipSpaces(pStart)
+char * pStart;
+#endif
+{
+ char *p = pStart;
+ while (*p != 0 && isspace(*p)) p++;
+ return p;
+}
+
+#ifdef __USE_PROTOS
+char * skipToSeparatorOrEqualSign(char *pStart, int *pNest)
+#else
+char * skipToSeparatorOrEqualSign(pStart, pNest)
+char *pStart;
+int *pNest;
+#endif
+{
+ char *p = pStart;
+
+ int nest = 0;
+
+ *pNest = (-1);
+
+ while (*p != 0) {
+ switch (*p) {
+
+ case '(' :
+ case '[' :
+ case '<' :
+ case '{' :
+ nest++;
+ p++;
+ break;
+
+ case ')' :
+ case ']' :
+ case '>' :
+ case '}' :
+ nest--;
+ p++;
+ break;
+
+ case '"' :
+ p = skipStringLiteral(p);
+ break;
+
+ case '\'' :
+ p = skipCharLiteral(p);
+ break;
+
+ case '\\':
+ p++;
+ if (*p == 0) goto EXIT;
+ p++;
+ break;
+
+ case ',':
+ case '=':
+ if (nest == 0) goto EXIT;
+ p++;
+ break;
+
+ default:
+ p++;
+ }
+ }
+EXIT:
+ *pNest = nest;
+ return p;
+}
+
+#ifdef __USE_PROTOS
+char * skipToSeparator(char *pStart, int *pNest)
+#else
+char * skipToSeparator(pStart, pNest)
+char *pStart;
+int *pNest;
+#endif
+{
+ char * p = pStart;
+ for ( ; ; ) {
+ p = skipToSeparatorOrEqualSign(p, pNest);
+ if (*pNest != 0) return p;
+ if (*p == ',') return p;
+ if (*p == 0) return p;
+ p++;
+ }
+}
+
+/* skip to just past the "=" separating the declaration from the initialization value */
+
+#ifdef __USE_PROTOS
+char * getInitializer(char *pStart)
+#else
+char * getInitializer(pStart)
+char * pStart;
+#endif
+{
+ char *p;
+ char *pDataType;
+ char *pSymbol;
+ char *pEqualSign;
+ char *pValue;
+ char *pSeparator;
+ int nest = 0;
+
+ require(pStart!=NULL, "getInitializer: invalid string");
+
+ p = endFormal(pStart,
+ &pDataType,
+ &pSymbol,
+ &pEqualSign,
+ &pValue,
+ &pSeparator,
+ &nest);
+ if (nest != 0) return NULL;
+ if (pEqualSign == NULL) return NULL;
+ if (pValue == NULL) return NULL;
+ return strBetween(pValue, NULL, pSeparator);
+}
+
+/*
+ Examines the string from pStart to pEnd-1.
+ If the string has 0 length or is entirely white space
+ returns 1. Otherwise 0.
+*/
+
+#ifdef __USE_PROTOS
+int isWhiteString(const char *pStart, const char *pEnd)
+#else
+int isWhiteString(pStart, pEnd)
+const char *pStart;
+const char *pEnd;
+#endif
+{
+ const char *p;
+ for (p = pStart; p < pEnd; p++) {
+ if (! isspace(*p)) return 0;
+ }
+ return 1;
+}
+
+/*
+ This replaces HasComma() which couldn't distinguish
+
+ foo ["a,b"]
+
+ from:
+
+ foo[a,b]
+
+*/
+
+#ifdef __USE_PROTOS
+int hasMultipleOperands(char *pStart)
+#else
+int hasMultipleOperands(pStart)
+char *pStart;
+#endif
+{
+ char *p = pStart;
+ int nest = 0;
+
+ p = skipSpaces(p);
+ if (*p == 0) return 0;
+ p = skipToSeparator(p, &nest);
+ if (nest == 0 && *p == ',') return 1;
+ return 0;
+}
+
+
+#define MAX_STR_BETWEEN_WORK_AREA 1000
+
+static char strBetweenWorkArea[MAX_STR_BETWEEN_WORK_AREA];
+
+
+/*
+ strBetween(pStart, pNext, pStop)
+
+ Creates a null terminated string by copying the text between two pointers
+ to a work area. The start of the string is pStart. The end of the string
+ is the character before pNext, or if pNext is null then the character before
+ pStop. Trailing spaces are not included in the copy operation.
+
+ This is used when a string contains several parts. The pNext part may be
+ optional. The pStop will stop the scan when the optional part is not present
+ (is a null pointer).
+*/
+
+#ifdef __USE_PROTOS
+char *strBetween(char *pStart, char *pNext, char *pStop)
+#else
+char *strBetween(pStart, pNext, pStop)
+char *pStart;
+char *pNext;
+char *pStop;
+#endif
+{
+ char *p;
+ char *q = strBetweenWorkArea;
+ const char *pEnd;
+
+ pEnd = (pNext != NULL) ? pNext : pStop;
+
+ require (pEnd != NULL, "pEnd == NULL");
+ require (pEnd >= pStart, "pEnd < pStart");
+ for (pEnd--; pEnd >= pStart; pEnd--) { /* MR31 */
+ if (! isspace(*pEnd)) break;
+ }
+ for (p = pStart;
+ p <= pEnd && q < &strBetweenWorkArea[MAX_STR_BETWEEN_WORK_AREA-2];
+ p++, q++) {
+ *q = *p;
+ }
+ *q = 0;
+ return strBetweenWorkArea;
+}
+
+/*
+ function Returns pointer to character following separator at
+ value which to continue search for next formal. If at the
+ end of the string a pointer to the null byte at the
+ end of the string is returned.
+
+ pStart Pointer to the starting position of the formal list
+
+ This may be the middle of a longer string, for example
+ when looking for the end of formal #3 starting from
+ the middle of the complete formal list.
+
+ ppDataType Returns a pointer to the start of the data type in the
+ formal. Example: pointer to "Foo".
+
+ ppSymbol Returns a pointer to the start of the formal symbol.
+ Example: pointer to "f".
+
+ ppEqualSign Returns a pointer to the equal sign separating the
+ formal symbol from the initial value. If there is
+ no "=" then this will be NULL.
+
+ ppValue Returns a pointer to the initial value part of the
+ formal declaration. Example: pointer to "&farray[1,2]"
+
+ ppSeparator Returns a pointer to the character which terminated the
+ scan. This should be a pointer to a comma or a null
+ byte which terminates the string.
+
+ pNest Returns the nesting level when a separator was found.
+ This is non-zero for any kind of error. This is zero
+ for a successful parse of this portion of the formal
+ list.
+
+*/
+
+#ifdef __USE_PROTOS
+char * endFormal(char *pStart,
+ char **ppDataType,
+ char **ppSymbol,
+ char **ppEqualSign,
+ char **ppValue,
+ char **ppSeparator,
+ int *pNest)
+#else
+char * endFormal(pStart,
+ ppDataType,
+ ppSymbol,
+ ppEqualSign,
+ ppValue,
+ ppSeparator,
+ pNest)
+char *pStart;
+char **ppDataType;
+char **ppSymbol;
+char **ppEqualSign;
+char **ppValue;
+char **ppSeparator;
+int *pNest;
+
+#endif
+{
+ char *p = pStart;
+ char *q;
+
+ *ppDataType = NULL;
+ *ppSymbol = NULL;
+ *ppEqualSign = NULL;
+ *ppValue = NULL;
+ *ppSeparator = NULL;
+
+ *pNest = 0;
+
+ /* The first non-blank is the start of the datatype */
+
+ p = skipSpaces(p);
+ if (*p == 0) goto EXIT;
+ *ppDataType = p;
+
+ /* We are not looking for the symbol, we are looking
+ for the separator that follows the symbol. Then
+ we'll back up.
+
+ Search for the ',' or '=" or null terminator.
+ */
+
+ p = skipToSeparatorOrEqualSign(p, pNest);
+
+ if (*pNest != 0) goto EXIT;
+
+ /*
+ Work backwards to find start of symbol
+ Skip spaces between the end of symbol and separator
+ Assume that there are no spaces in the formal, but
+ there is a space preceding the formal
+ */
+
+ for (q = &p[-1]; q >= *ppDataType; q--) {
+ if (! isspace(*q)) break;
+ }
+ if (q < *ppDataType) goto EXIT;
+
+ /*
+ MR26 Handle things like: IIR_Bool (IIR_Decl::*constraint)()
+ Backup until we hit the end of a symbol string, then find the
+ start of the symbol string. This wont' work for functions
+ with prototypes, but works for the most common cases. For
+ others, use typedef names.
+ */
+
+/* MR26 */ for (q = q; q >= *ppDataType; q--) {
+/* MR26 */ if (isalpha(*q) || isdigit(*q) || *q == '_' || *q == '$') break;
+/* MR26 */ }
+/* MR26 */ if (q < *ppDataType) goto EXIT;
+
+ for (q = q; q >= *ppDataType; q--) {
+ if ( ! (isalpha(*q) || isdigit(*q) || *q == '_' || *q == '$')) break;
+ }
+
+ *ppSymbol = &q[1];
+
+ if (*p == ',' || *p == 0) {
+ *ppSeparator = p;
+ goto EXIT;
+ }
+
+ *ppEqualSign = p;
+ p = skipSpaces(++p);
+ *ppValue = p;
+ if (*p == 0) goto EXIT;
+
+
+ while (*p != 0 && *pNest == 0 && *p != ',') {
+ p = skipToSeparator(p, pNest);
+ }
+ if (*pNest == 0) *ppSeparator = p;
+
+EXIT:
+ if (*p == ',') p++;
+ return p;
+}
diff --git a/Source/Pccts/antlr/mode.h b/Source/Pccts/antlr/mode.h
new file mode 100644
index 0000000..c08bf31
--- /dev/null
+++ b/Source/Pccts/antlr/mode.h
@@ -0,0 +1,12 @@
+#define START 0
+#define STRINGS 1
+#define ACTION_STRINGS 2
+#define ACTION_CHARS 3
+#define ACTION_COMMENTS 4
+#define TOK_DEF_COMMENTS 5
+#define TOK_DEF_CPP_COMMENTS 6
+#define ACTION_CPP_COMMENTS 7
+#define CPP_COMMENTS 8
+#define COMMENTS 9
+#define ACTIONS 10
+#define PARSE_ENUM_FILE 11
diff --git a/Source/Pccts/antlr/mrhoist.c b/Source/Pccts/antlr/mrhoist.c
new file mode 100644
index 0000000..110bf59
--- /dev/null
+++ b/Source/Pccts/antlr/mrhoist.c
@@ -0,0 +1,3030 @@
+/*
+ * mrhoist.c
+ *
+ * SOFTWARE RIGHTS
+ *
+ * We reserve no LEGAL rights to the Purdue Compiler Construction Tool
+ * Set (PCCTS) -- PCCTS is in the public domain. An individual or
+ * company may do whatever they wish with source code distributed with
+ * PCCTS or the code generated by PCCTS, including the incorporation of
+ * PCCTS, or its output, into commerical software.
+ *
+ * We encourage users to develop software with PCCTS. However, we do ask
+ * that credit is given to us for developing PCCTS. By "credit",
+ * we mean that if you incorporate our source code into one of your
+ * programs (commercial product, research project, or otherwise) that you
+ * acknowledge this fact somewhere in the documentation, research report,
+ * etc... If you like PCCTS and have developed a nice tool with the
+ * output, please mention that you developed it using PCCTS. In
+ * addition, we ask that this header remain intact in our source code.
+ * As long as these guidelines are kept, we expect to continue enhancing
+ * this system and expect to make other tools available as they are
+ * completed.
+ *
+ * ANTLR 1.33MR10
+ *
+ */
+
+#include <stdio.h>
+
+#include "pcctscfg.h"
+
+#include "set.h"
+#include "syn.h"
+#include "hash.h"
+#include "generic.h"
+#include "dlgdef.h"
+#include <ctype.h>
+
+#ifdef __USE_PROTOS
+void dumppred(Predicate *);
+#else
+void dumppred();
+#endif
+
+/*
+ Try to determine whether predicate "first" is true for
+ all cases where "second" is true. Comparison takes place
+ without regard to context.
+ Assumes that predicate symbols have been expanded.
+ Assumes that there are no NAND or NOR nodes
+
+*/
+
+#ifdef __USE_PROTOS
+int MR_secondPredicateUnreachable(Predicate *first,Predicate *second)
+#else
+int MR_secondPredicateUnreachable(first,second)
+ Predicate *first;
+ Predicate *second;
+#endif
+{
+ Predicate *f;
+ Predicate *s;
+
+ if (first == NULL) {
+ return 1;
+ } else if (second == NULL) {
+ return 0;
+ } else if (first->down == NULL && second->down == NULL) {
+ if (first->source == second->source &&
+ first->inverted == second->inverted) {
+ return 1; /* look identical - will never reach alt2 */
+ } else {
+ return 0; /* look different */
+ };
+ } else if (first->down == NULL && second->down != NULL) {
+
+ if (second->expr == PRED_AND_LIST) {
+
+ /* unreachable if first covers any child of second */
+
+ for (s=second->down; s != NULL; s=s->right) {
+ if (MR_secondPredicateUnreachable(first,s)) {
+ return 1;
+ };
+ };
+ return 0;
+ } else if (second->expr == PRED_OR_LIST) {
+
+ /* unreachable if first covers every child of second */
+
+ for (s=second->down; s != NULL; s=s->right) {
+ if (!MR_secondPredicateUnreachable(first,s)) {
+ return 0;
+ };
+ };
+ return 1;
+ } else {
+ require (0,"Illegal pred->expr");
+ return 0; /* MR20 Make compiler happy */
+ };
+ } else if (first->down != NULL && second->down == NULL) {
+ if (first->expr == PRED_AND_LIST) {
+
+ /* unreachable if every child of first covers second */
+
+ for (f=first->down; f != NULL; f=f->right) {
+ if (!MR_secondPredicateUnreachable(f,second)) {
+ return 0;
+ };
+ };
+ return 1;
+ } else if (first->expr == PRED_OR_LIST) {
+
+ /* unreachable if any child of first covers second */
+
+ for (f=first->down; f != NULL; f=f->right) {
+ if (MR_secondPredicateUnreachable(f,second)) {
+ return 1;
+ };
+ };
+ return 0;
+ } else {
+ require (0,"Illegal predicate->expr");
+ return 0; /* MR20 Make compiler happy */
+ };
+ } else {
+
+ if (first->expr == PRED_AND_LIST && second->expr == PRED_AND_LIST) {
+
+ /* unreachable if each child of first covers at least one child of second */
+
+ for (f=first->down; f != NULL ; f=f->right) {
+ for (s=second->down; s != NULL ; s=s->right) {
+ if (MR_secondPredicateUnreachable(f,s)) goto A_next_f;
+ };
+ return 0;
+A_next_f:
+ continue;
+ };
+ return 1;
+
+ } else if (first->expr == PRED_AND_LIST && second->expr == PRED_OR_LIST) {
+
+ /* unreachable if each child of first covers ALL of second's children */
+
+ for (f=first->down; f != NULL ; f=f->right) {
+ for (s=second->down; s != NULL ; s=s->right) {
+ if (!MR_secondPredicateUnreachable(f,s)) return 0;
+ };
+ };
+ return 1;
+
+ } else if (first->expr == PRED_OR_LIST && second->expr == PRED_AND_LIST) {
+
+ /* unreachable if any child of second is covered by any child of first */
+
+ for (f=first->down; f != NULL ; f=f->right) {
+ for (s=second->down; s != NULL ; s=s->right) {
+ if (MR_secondPredicateUnreachable(f,s)) return 1;
+ };
+ };
+ return 0;
+
+ } else if (first->expr == PRED_OR_LIST && second->expr == PRED_OR_LIST) {
+
+ /* unreachable if every child of second is covered by some child of first */
+
+ for (f=first->down; f != NULL ; f=f->right) {
+ for (s=second->down; s != NULL ; s=s->right) {
+ if (MR_secondPredicateUnreachable(f,s)) goto B_next_f;
+ };
+ return 0;
+B_next_f:
+ continue;
+ };
+ return 1;
+
+ } else {
+ require (0,"Illegal predicate->expr");
+ return 0; /* MR20 Make compiler happy */
+ };
+ };
+ return 0; /* MR20 MSVC 5.0 complains about missing return statement */
+}
+
+#ifdef __USE_PROTOS
+void MR_xxxIndent(FILE *f,int depth)
+#else
+void MR_xxxIndent(f,depth)
+ FILE *f;
+ int depth;
+#endif
+{
+ int i;
+
+ for (i=0; i<depth ; i++) {
+ fprintf(f," ");
+ };
+}
+
+#ifdef __USE_PROTOS
+void MR_stderrIndent(int depth)
+#else
+void MR_stderrIndent(depth)
+ int depth;
+#endif
+{
+ MR_xxxIndent(stderr,depth);
+}
+
+#ifdef __USE_PROTOS
+void MR_outputIndent(int depth)
+#else
+void MR_outputIndent(depth)
+ int depth;
+#endif
+{
+ MR_xxxIndent(output,depth);
+}
+
+#ifdef __USE_PROTOS
+void MR_set_reuse(set *s)
+#else
+void MR_set_reuse(s)
+ set *s;
+#endif
+{
+ set_free(*s);
+ *s=empty;
+}
+
+#ifdef __USE_PROTOS
+void MR_dumpPredRuleRefStack(FILE *iounit,int indent)
+#else
+void MR_dumpPredRuleRefStack(iounit,indent)
+ FILE *iounit;
+ int indent;
+#endif
+{
+ int i;
+ int j;
+ int count=MR_PredRuleRefStack.count;
+ RuleRefNode *rrn=NULL;
+ Junction *lastOne;
+
+ if (count == 0) {
+ fprintf(iounit,"empty\n");
+ return;
+ };
+ for (i=0; i < count; i++) {
+ rrn=(RuleRefNode *) MR_PredRuleRefStack.data[i];
+ for (j=0; j<indent; j++) fprintf(iounit," ");
+ fprintf(iounit,"#%-2d in rule %s (line %d %s) to rule %s\n",
+ i,rrn->rname,rrn->line,FileStr[rrn->file],rrn->text);
+ };
+ lastOne=MR_ruleReferenced(rrn);
+ if (lastOne != NULL) {
+ for (j=0; j<indent; j++) fprintf(iounit," ");
+ fprintf(iounit,"#%-2d in rule %s (line %d %s)\n",
+ count,lastOne->rname,lastOne->line,FileStr[lastOne->file]);
+ };
+}
+
+#ifdef __USE_PROTOS
+void MR_dumpTreeF(FILE *f,int depth,Tree *tree,int across)
+#else
+void MR_dumpTreeF(f,depth,tree,across)
+ FILE *f;
+ Tree *tree;
+ int depth;
+ int across;
+#endif
+{
+ int newAcross=across;
+
+ if (tree == NULL ) return;
+ if (tree->down != NULL ) {
+ fprintf(output,"\n");
+ MR_outputIndent(depth);
+ fprintf(output, "(root =");
+ };
+ if (tree->token == ALT ) {
+ fprintf(output," %-16s","Alt");
+ } else if (tree->token==EpToken ) {
+ fprintf(output,"(%d)%13s",tree->v.rk," ");
+ } else {
+ fprintf(output," %-16s",TerminalString(tree->token));
+ };
+ if (tree->down != NULL) {
+ fprintf(output,"\n");
+ MR_outputIndent(depth+1);
+ MR_dumpTreeF(f,depth+1,tree->down,1);
+ newAcross=0;
+ fprintf(output,"\n");
+ MR_outputIndent(depth);
+ fprintf(output,")");
+ };
+ if (newAcross > 3) {
+ fprintf(output,"\n");
+ MR_outputIndent(depth);
+ newAcross=0;
+ };
+ MR_dumpTreeF(f,depth,tree->right,newAcross+1);
+}
+
+#ifdef __USE_PROTOS
+void MR_dumpTreeX(int depth,Tree *tree,int across)
+#else
+void MR_dumpTreeX(depth,tree,across)
+ Tree *tree;
+ int depth;
+ int across;
+#endif
+{
+ MR_dumpTreeF(output,depth,tree,across);
+}
+
+#ifdef __USE_PROTOS
+void MR_dumpTokenSet(FILE *f,int depth,set s)
+#else
+void MR_dumpTokenSet(f,depth,s)
+ FILE *f;
+ int depth;
+ set s;
+#endif
+{
+ int i;
+ int j;
+
+ unsigned *pdq;
+
+ if (set_nil(s)) {
+ fprintf(f,"\n");
+ MR_xxxIndent(f,depth+1);
+ fprintf(f,"nil\n");
+ return;
+ };
+
+ pdq=set_pdq(s);
+ require(pdq != NULL,"set_pdq failed");
+ i=0;
+ for (i=0 ; ; i=i+4) {
+ fprintf(f,"\n");
+ MR_xxxIndent(f,depth+1);
+ for (j=0; j < 4 ; j++) {
+ if (pdq[i+j] == nil) break;
+ fprintf(f," %-16s",TerminalString(pdq[i+j]));
+ };
+ if (pdq[i+j] == nil) break;
+ };
+ fprintf(f,"\n");
+ free( (char *) pdq);
+}
+
+#ifdef __USE_PROTOS
+void MR_dumpPred1(int depth,Predicate *p,int withContext)
+#else
+void MR_dumpPred1(depth,p,withContext)
+ int depth;
+ Predicate *p;
+ int withContext;
+#endif
+{
+ unsigned k;
+
+ if (p == NULL) {
+ MR_outputIndent(depth);
+ fprintf(output,"The predicate is empty (or always true)\n\n");
+ return;
+ };
+ if (p->down != NULL) {
+ MR_outputIndent(depth);
+ if (p->inverted) {
+
+ /* MR14a Left out print expression in fprintf
+ Reported by Manuel Kessler (mlkessle@cip.physik.uni-wuerzburg.de)
+ */
+
+ if (p->expr == PRED_AND_LIST) fprintf(output,"%s NAND (not AND) expr\n\n",p->expr);
+ if (p->expr == PRED_OR_LIST) fprintf(output,"%s NOR (not OR) expr\n\n",p->expr);
+ } else {
+ fprintf(output,"%s expr\n\n",p->expr);
+ };
+ } else {
+ MR_outputIndent(depth);
+ fprintf(output,"pred %s <<%s>>?\n",
+ (p->inverted ? " *not*" : ""),
+ (p->expr == NULL ? "null expr" : p->expr));
+ MR_outputIndent(depth+1);
+ fprintf(output," ");
+ fprintf(output," depth=k=%d",p->k);
+ if (p->source != NULL && p->source->guardpred) {
+ fprintf(output," (\"=>\" guard)");
+ }
+ if (p->source != NULL && p->source->ampersandPred != NULL) {
+ fprintf(output," (\"&&\" guard)");
+ };
+ k=set_int(p->completionSet);
+ if (k != nil) {
+ fprintf(output," Incomplete Set at k=%d !",k);
+ };
+ k=set_int(p->completionTree);
+ if (k != nil) {
+ fprintf(output," Incomplete Tree at k=%d !",k);
+ };
+ if (p->source != NULL) {
+ fprintf(output," rule %s line %d %s",
+ p->source->rname,p->source->line,FileStr[p->source->file]);
+ };
+ fprintf(output,"\n");
+ if (withContext &&
+ (HoistPredicateContext ||
+ ! set_nil(p->scontext[1]) ||
+ p->tcontext != NULL)) {
+ if (p->k == 1) {
+ MR_outputIndent(depth+1);
+ fprintf(output,"set context: ");
+ MR_dumpTokenSet(output,depth+1,p->scontext[1]);
+ }
+ if (p->k != 1) {
+ MR_outputIndent(depth+1);
+ fprintf(output,"tree context:");
+ if (p->tcontext == NULL) {
+ fprintf(output," null");
+ } else {
+ MR_dumpTreeX(depth+2,p->tcontext,0);
+ };
+ fprintf(output,"\n");
+ };
+ };
+ fprintf(output,"\n");
+ };
+ if (p->down != NULL) {
+ MR_dumpPred1(depth+1,p->down,withContext);
+ };
+ if (p->right != NULL) {
+ MR_dumpPred1(depth,p->right,withContext);
+ };
+}
+
+#ifdef __USE_PROTOS
+void MR_dumpPred(Predicate *p,int withContext)
+#else
+void MR_dumpPred(p,withContext)
+ Predicate *p;
+ int withContext;
+#endif
+{
+ MR_dumpPred1(0,p,withContext);
+}
+
+#ifdef __USE_PROTOS
+Tree * MR_make_tree_from_set(set s)
+#else
+Tree * MR_make_tree_from_set(s)
+ set s;
+#endif
+{
+ Tree *t=NULL;
+ Tree *node;
+ Tree **tp=&t;
+ int i;
+
+ unsigned *pdq=set_pdq(s);
+
+ if (pdq != NULL) {
+ for (i=0 ; pdq[i] != nil ; i++) {
+ node=tnode( (int) pdq[i]);
+ *tp=node;
+ tp=&(node->right);
+ };
+ *tp=NULL;
+ free ( (char *) pdq);
+ };
+ return t;
+}
+
+#ifdef __USE_PROTOS
+void MR_check_pred_too_long(Predicate *p,set completion)
+#else
+void MR_check_pred_too_long(p,completion)
+ Predicate *p;
+ set completion;
+#endif
+{
+ if (p != NULL &&
+ p->source != NULL &&
+ ! p->source->predTooLong) {
+ if ( !set_nil(completion)) {
+ p->source->predTooLong=1;
+warnFL("It is unusual (but ok) for a semantic predicate to test context past the end of its own rule",
+ FileStr[p->source->file],p->source->line);
+ };
+ };
+}
+
+#ifdef __USE_PROTOS
+int MR_predicate_context_completed(Predicate *p)
+#else
+int MR_predicate_context_completed(p)
+ Predicate *p;
+#endif
+{
+ if (p == NULL) return 1;
+ if (p->expr != PRED_AND_LIST &&
+ p->expr != PRED_OR_LIST) {
+ if ( ! set_nil(p->completionSet)) return 0;
+ if ( ! set_nil(p->completionTree)) return 0;
+ };
+ return MR_predicate_context_completed(p->down) &
+ MR_predicate_context_completed(p->right);
+}
+
+#ifdef __USE_PROTOS
+Node * MR_advance(Node *n)
+#else
+Node * MR_advance(n)
+ Node *n;
+#endif
+{
+ if (n == NULL) return NULL;
+ switch (n->ntype) {
+ case nJunction: return ((Junction *)n)->p1;
+ case nToken: return ((TokNode *)n)->next;
+ case nRuleRef: return ((RuleRefNode *)n)->next;
+ case nAction: return ((ActionNode *)n)->next;
+ default: return NULL;
+ };
+ return NULL; /* MSVC 5.0 complains about missing return statement */
+}
+
+#ifdef __USE_PROTOS
+Junction * MR_find_endRule(Node *n)
+#else
+Junction * MR_find_endRule(n)
+ Node *n;
+#endif
+{
+ Node *next;
+ if (n == NULL) return NULL;
+ for (next=n; next != NULL; next=MR_advance(next)) {
+ if (next->ntype == nJunction &&
+ ( (Junction *) next)->jtype == EndRule) {
+ break;
+ };
+ };
+ return (Junction *)next;
+}
+
+/*
+ Intersection: a branch which is shorter is chosen
+ over one which is longer: (A B C) intersect (A B) yields (A B).
+
+ AND: a branch which is longer is chosen over the one
+ which is shorter: (A B C) AND (A B) yields (A B C)
+
+*/
+
+#ifdef __USE_PROTOS
+Tree *MR_computeTreeIntersection(Tree *l,Tree *r)
+#else
+Tree *MR_computeTreeIntersection(l,r)
+ Tree *l;
+ Tree *r;
+#endif
+{
+ Tree *result=NULL;
+ Tree **tail;
+ Tree *p;
+ Tree *q;
+ Tree *match;
+
+ if (l == NULL || r == NULL) return NULL;
+ for (p=l; p != NULL; p=p->right) {
+ require(p->token != EpToken,"MR_computeTreeIntersection: p->EpToken unexpected\n");
+ require (p->token != ALT,"MR_computeTreeIntersection: p->ALT unexpected\n");
+ };
+ for (q=r; q != NULL; q=q->right) {
+ require(q->token != EpToken,"MR_computeTreeIntersection: q->EpToken unexpected\n");
+ require(q->token != ALT,"MR_computeTreeIntersection: q->ALT unexpected\n");
+ };
+
+ result=tnode(ALT);
+ tail=&(result->down);
+
+ for (p=l; p != NULL ; p=p->right) {
+ for (q=r; q != NULL ; q=q->right) {
+ if (p->token == q->token) {
+ match=tnode(p->token);
+ match->down=MR_computeTreeIntersection(p->down,q->down);
+ *tail=match;
+ tail=&(match->right);
+ };
+ };
+ };
+
+ *tail=NULL;
+ result=tshrink(result);
+ result=tflatten( result );
+ result=tleft_factor( result );
+ return result;
+}
+
+/* the predicates which are ANDed together have a common
+ context: they must all have common roots. Thus the
+ AND operation is more like an OR operation because
+ branches which are longer are grafted onto shorter
+ branches of the AND tree. For instance combining
+ (A B C) with (A B C D) gives (A B C D). There
+ should never be a case of (A B C) and (A B D) because
+ they have the same context.
+
+ Actually, this may not be true once one throws in
+ guard predicates which are defined by the user, not
+ the context.
+*/
+
+/* requires input trees to be in "canonical" format */
+
+#ifdef __USE_PROTOS
+Tree *MR_computeTreeAND(Tree *l,Tree *r)
+#else
+Tree *MR_computeTreeAND(l,r)
+ Tree *l;
+ Tree *r;
+#endif
+{
+ Tree *result=NULL;
+ Tree **tail;
+ Tree *p;
+ Tree *q;
+ Tree *match;
+
+ if (l == NULL) return tdup(r);
+ if (r == NULL) return tdup(l);
+
+ for (p=l; p != NULL; p=p->right) {
+/**** require(p->token != EpToken,"MR_computeTreeAND: p->EpToken unexpected\n"); ****/
+ require (p->token != ALT,"MR_computeTreeAND: p->ALT unexpected\n");
+ };
+ for (q=r; q != NULL; q=q->right) {
+/**** require(q->token != EpToken,"MR_computeTreeAND: q->EpToken unexpected\n"); ****/
+ require(q->token != ALT,"MR_computeTreeAND: q->ALT unexpected\n");
+ };
+
+ result=tnode(ALT);
+ tail=&(result->down);
+
+ for (p=l; p != NULL ; p=p->right) {
+ for (q=r; q != NULL ; q=q->right) {
+ if (p->token == q->token) {
+ match=tnode(p->token);
+ match->down=MR_computeTreeAND(p->down,q->down);
+ *tail=match;
+ tail=&(match->right);
+ };
+ };
+ };
+
+ *tail=NULL;
+ result=tshrink(result);
+ result=tflatten( result );
+ result=tleft_factor( result );
+ return result;
+}
+
+#ifdef __USE_PROTOS
+void MR_union_plain_sets1(Predicate *p,set *theUnion)
+#else
+void MR_union_plain_sets1(p,theUnion)
+ Predicate *p;
+ set *theUnion;
+#endif
+{
+ if (p == NULL) return;
+ MR_union_plain_sets1(p->down,theUnion);
+ MR_union_plain_sets1(p->right,theUnion);
+ set_orin(theUnion,p->plainSet);
+ return;
+}
+
+#ifdef __USE_PROTOS
+set MR_union_plain_sets(Predicate *p)
+#else
+set MR_union_plain_sets(p)
+ Predicate *p;
+#endif
+{
+ set theUnion;
+
+ theUnion=empty;
+
+ MR_union_plain_sets1(p,&theUnion);
+ return theUnion;
+}
+
+/* does NOT left factor: do not want to merge
+ (A B) with (A) to get (A B)
+ in fact the opposite: (A B) with (A) gives (A)
+*/
+
+#ifdef __USE_PROTOS
+Tree *MR_compute_pred_tree_ctxXX(Predicate *p)
+#else
+Tree *MR_compute_pred_tree_ctxXX(p)
+ Predicate *p;
+#endif
+{
+ Tree *result=NULL;
+ Predicate *q;
+ Tree *t;
+
+ if (p == NULL) return NULL;
+
+/* this appears strange: why do we OR the context
+ of and AND predicate ? It is because of the way
+ that predicates are evaluated: if the context is
+ wrong then it's the same as if the predicate was
+ true. That means that even when one leg of an
+ AND has unmatched context, if the other leg has
+ matched context and is true then the predicate
+ succeeds. It's only when all the legs have unmatched
+ context that this one can skip evaluation of the
+ predicates.
+*/
+ if (p->expr == PRED_OR_LIST ||
+ p->expr == PRED_AND_LIST) {
+ for (q=p->down; q != NULL ; q=q->right) {
+ t=MR_compute_pred_tree_ctxXX(q);
+ result=tappend(result,t);
+ t=NULL;
+ };
+
+ result=tshrink(result);
+ result=tflatten( result );
+
+/* does NOT left factor: do not want to merge
+ (A B) with (A) to get (A B)
+ in fact the opposite: (A B) with (A) gives (A)
+*/
+
+/**** result=tleft_factor( result ); ****/
+ return result;
+ };
+
+#if 0
+** if (p->expr == PRED_AND_LIST) {
+**
+** Predicate *l;
+** Predicate *r;
+** Tree *l1;
+** Tree *r1;
+** Tree *prevl1;
+**
+** l=p->down;
+** require (l->right != NULL,"MR_compute_pred_tree - AND has only one child");
+**
+**/* l1 and r1 should already be in "canonical" format */
+**
+** l1=MR_compute_pred_tree(l);
+** for (r=l->right; r != NULL; r=r->right) {
+** r1=MR_compute_pred_tree(r);
+** prevl1=l1;
+** l1=MR_computeTreeAND(l1,r1);
+** Tfree(r1);
+** Tfree(prevl1);
+** };
+**
+**/* result from computeTreeAND should be in "canonical" format */
+**
+** result=l1;
+**
+**/* result of MR_computeTreeAND should be in "canonical" format */
+**
+** return result;
+** };
+#endif
+
+ if (p->k == 1) {
+ result=MR_make_tree_from_set(p->scontext[1]);
+ } else {
+ result=tdup(p->tcontext);
+ result=MR_remove_epsilon_from_tree(result);
+ result=tshrink(result);
+ result=tflatten(result);
+ result=tleft_factor(result);
+ };
+ return result;
+}
+
+#ifdef __USE_PROTOS
+void MR_pred_depth(Predicate *p,int *maxDepth)
+#else
+void MR_pred_depth(p,maxDepth)
+ Predicate *p;
+ int *maxDepth;
+#endif
+{
+ if (p == NULL) return;
+ if (p->expr != PRED_OR_LIST &&
+ p->expr != PRED_AND_LIST) {
+ if (p->k > *maxDepth) *maxDepth=p->k;
+ };
+ MR_pred_depth(p->down,maxDepth);
+ MR_pred_depth(p->right,maxDepth);
+}
+
+/* this computes the OR of all the contexts */
+
+#ifdef __USE_PROTOS
+set MR_compute_pred_set(Predicate *p)
+#else
+set MR_compute_pred_set(p)
+ Predicate *p;
+#endif
+{
+ set result;
+ Predicate *q;
+
+ result=empty;
+
+ if (p == NULL) return empty;
+
+ if (p->expr == PRED_OR_LIST ||
+ p->expr == PRED_AND_LIST) { /* yes, I do mean PRED_AND_LIST ! */
+ /* remember: r1: (A)? => <<p>>? r2; */
+ /* r2: (B)? => <<q>>? r3; */
+ set t;
+
+ t=empty;
+ result=empty;
+
+ for (q=p->down; q != NULL; q=q->right) {
+ t=MR_compute_pred_set(q);
+ set_orin(&result,t);
+ set_free(t);
+ };
+ return result;
+ } else if (p->k > 1) {
+ return empty;
+ } else {
+ return set_dup(p->scontext[1]);
+ };
+}
+
+#ifdef __USE_PROTOS
+set MR_First(int ck,Junction *j,set *incomplete)
+#else
+set MR_First(ck,j,incomplete)
+ int ck;
+ Junction *j;
+ set *incomplete;
+#endif
+{
+ Junction *p;
+ set tokensUsed;
+
+ tokensUsed=empty;
+
+ require(j->ntype==nJunction, "MR_First: non junction passed");
+
+ p = analysis_point((Junction *)j->p1);
+
+ REACH(p,ck,incomplete,tokensUsed);
+
+ return tokensUsed;
+}
+
+#ifdef __USE_PROTOS
+void MR_cleanup_pred_trees(Predicate *p)
+#else
+void MR_cleanup_pred_trees(p)
+ Predicate *p;
+#endif
+{
+ Tree *t;
+
+ if (p == NULL) return;
+ if (p->expr != PRED_OR_LIST &&
+ p->expr != PRED_AND_LIST) {
+ t=p->tcontext;
+ t=tshrink(t);
+ t=tflatten(t);
+ t=tleft_factor(t);
+ p->tcontext=t;
+ };
+ MR_cleanup_pred_trees(p->down);
+ MR_cleanup_pred_trees(p->right);
+}
+
+/* does NOT return canonical tree */
+
+#ifdef __USE_PROTOS
+Tree * MR_remove_epsilon_from_tree(Tree *t)
+#else
+Tree * MR_remove_epsilon_from_tree(t)
+ Tree *t;
+#endif
+{
+ if (t == NULL) return NULL;
+
+ /* I think ALT can be ignored as a special case */
+
+ if (t->token != EpToken) {
+ t->down=MR_remove_epsilon_from_tree(t->down);
+ t->right=MR_remove_epsilon_from_tree(t->right);
+ return t;
+ } else {
+ Tree *u;
+ u=MR_remove_epsilon_from_tree(t->right);
+ t->right=NULL;
+ Tfree(t);
+ return u;
+ };
+}
+
+#ifdef __USE_PROTOS
+void MR_complete_set(int predDepth,set *tokensUsed,set *incomplete)
+#else
+void MR_complete_set(predDepth,tokensUsed,incomplete)
+ int predDepth;
+ set *tokensUsed;
+ set *incomplete;
+#endif
+{
+ int i;
+ RuleRefNode *ruleRef;
+ set rk2;
+ set b;
+ int k2;
+ Junction *save_MR_RuleBlkWithHalt;
+
+ if (set_int(*incomplete) > (unsigned) predDepth) {
+ return;
+ };
+
+ require(MR_PredRuleRefStack.count == MR_RuleBlkWithHaltStack.count,
+ "RuleRefStack and RuleBlkWithHaltStack not same size");
+
+ require(MR_RuleBlkWithHalt == NULL ||
+ (MR_RuleBlkWithHalt->jtype == RuleBlk && MR_RuleBlkWithHalt->end->halt == TRUE),
+ "RuleBlkWithHalt has no halt set");
+
+ save_MR_RuleBlkWithHalt=MR_RuleBlkWithHalt;
+
+ if (MR_RuleBlkWithHalt != NULL) {
+ MR_RuleBlkWithHalt->end->halt=FALSE;
+ };
+
+ for (i=MR_PredRuleRefStack.count-1; i >= 0 ; i--) {
+ ruleRef=(RuleRefNode *)MR_PredRuleRefStack.data[i];
+ if (ruleRef == NULL) continue;
+
+ MR_RuleBlkWithHalt=(Junction *)MR_RuleBlkWithHaltStack.data[i];
+ if (MR_RuleBlkWithHalt != NULL) MR_RuleBlkWithHalt->end->halt=TRUE;
+
+ rk2=empty;
+ b=empty;
+
+ while ( !set_nil(*incomplete) ) {
+ k2=set_int(*incomplete);
+ if (k2 > predDepth) break; /* <=== another exit from loop */
+ set_rm(k2,*incomplete);
+ REACH(ruleRef->next,k2,&rk2,b);
+ set_orin(tokensUsed,b);
+ set_free(b);
+ };
+
+ if (MR_RuleBlkWithHalt != NULL) MR_RuleBlkWithHalt->end->halt=FALSE;
+
+ set_orin(incomplete,rk2); /* remember what we couldn't do */
+ set_free(rk2);
+ if (set_int(*incomplete) > (unsigned) predDepth) break; /* <=== another exit from loop */
+ };
+
+ MR_RuleBlkWithHalt=save_MR_RuleBlkWithHalt;
+ if (MR_RuleBlkWithHalt != NULL) {
+ MR_RuleBlkWithHalt->end->halt=TRUE;
+ };
+}
+
+#ifdef __USE_PROTOS
+void MR_complete_tree(int predDepth,Tree **t,set *incomplete)
+#else
+void MR_complete_tree(predDepth,t,incomplete)
+ int predDepth;
+ Tree **t;
+ set *incomplete;
+#endif
+{
+ int i;
+ RuleRefNode *ruleRef;
+ set rk2;
+ Tree *u;
+ unsigned k2;
+ Junction *save_MR_RuleBlkWithHalt;
+ int saveConstrainSearch;
+
+ if (set_int(*incomplete) > (unsigned) predDepth) {
+ return;
+ };
+
+ require(MR_PredRuleRefStack.count == MR_RuleBlkWithHaltStack.count,
+ "RuleRefStack and RuleBlkWithHaltStack not same size");
+
+ require(MR_RuleBlkWithHalt == NULL ||
+ (MR_RuleBlkWithHalt->jtype == RuleBlk && MR_RuleBlkWithHalt->end->halt == TRUE),
+ "RuleBlkWithHalt has no halt set");
+
+ save_MR_RuleBlkWithHalt=MR_RuleBlkWithHalt;
+ saveConstrainSearch=ConstrainSearch;
+ ConstrainSearch=0;
+
+ if (MR_RuleBlkWithHalt != NULL) {
+ MR_RuleBlkWithHalt->end->halt=FALSE;
+ };
+
+ for (i=MR_PredRuleRefStack.count-1; i >= 0 ; i--) {
+ ruleRef=(RuleRefNode *)MR_PredRuleRefStack.data[i];
+ if (ruleRef == NULL) continue;
+
+ MR_RuleBlkWithHalt=(Junction *)MR_RuleBlkWithHaltStack.data[i];
+
+ if (MR_RuleBlkWithHalt != NULL) MR_RuleBlkWithHalt->end->halt=TRUE;
+
+ rk2=empty;
+
+ while ( !set_nil(*incomplete) ) {
+ k2 = set_int(*incomplete);
+ if (k2 > (unsigned) predDepth) break; /* <=== another exit from loop */
+ set_rm(k2,*incomplete);
+ u = NULL;
+
+ TRAV(ruleRef->next,k2,&rk2,u);
+
+ /* any subtrees missing k2 tokens, add u onto end */
+
+ *t=tlink(*t,u,k2);
+ Tfree(u);
+ }
+
+ set_orin(incomplete,rk2); /* remember what we couldn't do */
+ set_free(rk2);
+
+ if (MR_RuleBlkWithHalt != NULL) MR_RuleBlkWithHalt->end->halt=FALSE;
+
+ if (set_int(*incomplete) > (unsigned) predDepth) break; /* <=== another exit from loop */
+ };
+
+ MR_RuleBlkWithHalt=save_MR_RuleBlkWithHalt;
+
+ if (MR_RuleBlkWithHalt != NULL) {
+ MR_RuleBlkWithHalt->end->halt=TRUE;
+ };
+ ConstrainSearch=saveConstrainSearch;
+}
+
+#ifdef __USE_PROTOS
+void MR_complete_predicates(int predDepth,Predicate *pred)
+#else
+void MR_complete_predicates(predDepth,pred)
+ int predDepth;
+ Predicate *pred;
+#endif
+{
+ if (pred == NULL) return;
+ if (pred->expr != PRED_AND_LIST &&
+ pred->expr != PRED_OR_LIST) {
+ MR_complete_set(predDepth,&(pred->scontext[1]),&(pred->completionSet));
+ MR_complete_tree(predDepth,&(pred->tcontext),&(pred->completionTree));
+ };
+ MR_complete_predicates(predDepth,pred->down);
+ MR_complete_predicates(predDepth,pred->right);
+}
+
+#ifdef __USE_PROTOS
+Junction * MR_junctionWithoutP2(Junction *j)
+#else
+Junction * MR_junctionWithoutP2(j)
+ Junction *j;
+#endif
+{
+ Junction *thisAlt;
+
+/* don't want to follow p2 to the next alternative of this rule */
+/* insert a generic node with null p2 if necessary */
+/* however FIRST requires a junction */
+
+ thisAlt=j;
+ if (thisAlt->p2 != NULL) {
+ if (thisAlt->p1->ntype == nJunction) {
+ thisAlt=(Junction *) thisAlt->p1;
+ } else {
+ thisAlt=newJunction();
+ thisAlt->p1=j->p1;
+ thisAlt->rname=j->rname;
+ thisAlt->file=j->file;
+ thisAlt->line=j->line;
+ j->p1=(Node *)thisAlt;
+ };
+ };
+ return thisAlt;
+}
+
+#ifdef __USE_PROTOS
+int MR_tree_equ(Tree *big, Tree *small) {
+#else
+int MR_tree_equ(big,small)
+ Tree *big;
+ Tree *small;
+{
+#endif
+
+ Tree *b;
+ Tree *s;
+ int bcount=0;
+ int scount=0;
+
+ if (small == NULL && big == NULL) return 1;
+ if (small == NULL) return 0;
+ if (big == NULL) return 0;
+
+ if (small->token == ALT) {
+ require(small->right == NULL,
+ "MR_tree_equ: small: ALT node has siblings");
+ return MR_tree_equ(big,small->down);
+ };
+ if (big->token == ALT) {
+ require(big->right == NULL,
+ "MR_tree_equ: big: ALT node has siblings");
+ return MR_tree_equ(big->down,small);
+ };
+ for (s=small; s != NULL; s=s->right) {
+ scount++;
+ require(s->token != EpToken,"MR_tree_equ: s->EpToken unexpected\n");
+ };
+ for (b=big; b != NULL; b=b->right) {
+ bcount++;
+ require(b->token != EpToken,"MR_tree_equ: b->EpToken unexpected\n");
+ };
+
+ if (bcount != scount) return 0;
+
+ for (s=small; s != NULL; s=s->right) {
+ for (b=big; b!= NULL; b=b->right) {
+ if (s->token == b->token) {
+ if (MR_tree_equ(b->down,s->down)) goto next_s;
+ };
+ };
+ return 0;
+next_s:
+ continue;
+ };
+ return 1;
+}
+
+/* this does not compare sources - only contexts ! */
+
+#ifdef __USE_PROTOS
+int MR_identicalContext(Predicate *p,Predicate *q)
+#else
+int MR_identicalContext(p,q)
+ Predicate *p;
+ Predicate *q;
+#endif
+{
+ if (p->k != q->k) return 0;
+ require ( (p->tcontext == NULL) == (q->tcontext == NULL),
+ "tcontext inconsistent");
+ if (p->k == 1) {
+ return set_equ(p->scontext[1],q->scontext[1]);
+ } else {
+ return MR_tree_equ(p->tcontext,q->tcontext);
+ };
+}
+
+#ifdef __USE_PROTOS
+void MR_reportSetSuppression(int predDepth,
+ set predSet,set plainSet,Junction *jPred,Junction *jPlain,Predicate *p)
+#else
+void MR_reportSetSuppression(predDepth,predSet,plainSet,jPred,jPlain,p)
+ int predDepth;
+ set predSet;
+ set plainSet;
+ Junction *jPred;
+ Junction *jPlain;
+ Predicate *p;
+#endif
+{
+ if (InfoP) {
+ fprintf(output,"\n#if 0\n\n");
+ fprintf(output,"Hoisting of predicate suppressed by alternative without predicate.\n");
+ fprintf(output,"The alt without the predicate includes all cases where the predicate is false.\n\n");
+ fprintf(output," WITH predicate: line %d %s\n",jPred->line,FileStr[jPred->file]);
+ if (jPlain != NULL) {
+ fprintf(output," WITHOUT predicate: line %d %s\n",jPlain->line,FileStr[jPlain->file]);
+ } else {
+ fprintf(output," WITHOUT predicate: all alternatives without predicates (combined)\n");
+ };
+ if (predDepth == 1) {
+ fprintf(output,"\nThe context set for the predicate:\n");
+ MR_dumpTokenSet(output,1,predSet);
+ };
+ fprintf(output,"\nThe lookahead set for the alt WITHOUT the semantic predicate:\n");
+ MR_dumpTokenSet(output,1,plainSet);
+ fprintf(output,"\nThe predicate:\n\n");
+ MR_dumpPred1(1,p,1);
+ fprintf(output,"Chain of referenced rules:\n\n");
+ MR_dumpPredRuleRefStack(output,4);
+ fprintf(output,"\n#endif\n");
+ };
+}
+
+#ifdef __USE_PROTOS
+void MR_reportSetRestriction(int predDepth,set predSet,set plainSet,
+ Junction *jPred,Junction *jPlain,Predicate *origPred,Predicate *newPred)
+#else
+void MR_reportSetRestriction(predDepth,predSet,plainSet,jPred,jPlain,origPred,newPred)
+ int predDepth;
+ set predSet;
+ set plainSet;
+ Junction *jPred;
+ Junction *jPlain;
+ Predicate *origPred;
+ Predicate *newPred;
+#endif
+{
+ set intersect;
+
+ intersect=empty;
+
+ if (! InfoP) return;
+ fprintf(output,"\n#if 0\n\n");
+ fprintf(output,"Restricting the context of a predicate because of overlap in the lookahead set\n");
+ fprintf(output," between the alternative with the semantic predicate and one without\n");
+ fprintf(output,"Without this restriction the alternative without the predicate could not\n");
+ fprintf(output," be reached when input matched the context of the predicate and the predicate\n");
+ fprintf(output," was false.\n\n");
+
+ fprintf(output," WITH predicate: line %d %s\n",jPred->line,FileStr[jPred->file]);
+ if (jPlain != NULL) {
+ fprintf(output," WITHOUT predicate: line %d %s\n",jPlain->line,FileStr[jPlain->file]);
+ } else {
+ fprintf(output," WITHOUT predicate: all alternatives without predicates (combined)\n");
+ };
+ if (predDepth == 1) {
+ fprintf(output,"\nThe original context set for the predicate:\n");
+ MR_dumpTokenSet(output,1,predSet);
+ };
+ fprintf(output,"\nThe lookahead set for the alt WITHOUT the semantic predicate:\n");
+ MR_dumpTokenSet(output,1,plainSet);
+ if (predDepth == 1) {
+ fprintf(output,"\nThe intersection of the two sets\n");
+ intersect=set_and(predSet,plainSet);
+ MR_dumpTokenSet(output,1,intersect);
+ set_free(intersect);
+ };
+ fprintf(output,"\nThe original predicate:\n\n");
+ MR_dumpPred1(1,origPred,1);
+ fprintf(output,"The new (modified) form of the predicate:\n\n");
+ MR_dumpPred1(1,newPred,1);
+ fprintf(output,"#endif\n");
+}
+
+/* don't use Pass3 by itself unless you know that inverted is not important */
+
+#ifdef __USE_PROTOS
+Predicate * MR_removeRedundantPredPass3(Predicate *p)
+#else
+Predicate * MR_removeRedundantPredPass3(p)
+ Predicate *p;
+#endif
+{
+ Predicate *q;
+
+ if (p == NULL) return NULL;
+ p->right=MR_removeRedundantPredPass3(p->right);
+ p->down=MR_removeRedundantPredPass3(p->down);
+ if (p->redundant) {
+ q=p->right;
+ p->right=NULL;
+ predicate_free(p);
+ return q;
+ };
+ if (p->expr == PRED_AND_LIST ||
+ p->expr == PRED_OR_LIST) {
+ if (p->down == NULL) {
+ q=p->right;
+ p->right=NULL;
+ predicate_free(p);
+ return q;
+ };
+ if (p->down != NULL && p->down->right == NULL) {
+ q=p->down;
+ q->right=p->right;
+ p->right=NULL;
+ p->down=NULL;
+ return q;
+ };
+ };
+ return p;
+}
+
+#ifdef __USE_PROTOS
+void MR_removeRedundantPredPass2(Predicate *p)
+#else
+void MR_removeRedundantPredPass2(p)
+ Predicate *p;
+#endif
+{
+ Predicate *q;
+
+ if (p == NULL) return;
+
+ if (p->expr == PRED_AND_LIST) {
+ for (q=p->down ; q != NULL ; q=q->right) {
+ MR_removeRedundantPredPass2(q);
+ if (q->isConst) {
+ if (q->constValue == 0) {
+ p->isConst=1;
+ p->constValue=0;
+ return;
+ } else {
+ q->redundant=1;
+ };
+ };
+ };
+ };
+
+ if (p->expr == PRED_OR_LIST) {
+ for (q=p->down ; q != NULL ; q=q->right) {
+ MR_removeRedundantPredPass2(q);
+ if (q->isConst) {
+ if (q->constValue == 0) {
+ q->redundant=1;
+ } else {
+ p->isConst=1;
+ p->constValue=1;
+ return;
+ };
+ };
+ };
+ };
+
+ return;
+}
+
+#if 0
+ this totally ignores the implications of guarded predicates
+ in which the part after the guard could possibly cover a predicate.
+ that would be much harder:
+
+ rule : (A)? => <<p>>? sub1; /* 1 */
+ | (B)? => <<r>>? sub2 /* 2 */
+ sub1 : (A)? => <<q>>? A B /* 3 */
+ | B /* 4 - suppresses line 2 */
+ ;
+#endif
+
+#ifdef __USE_PROTOS
+void MR_apply_restriction1(Predicate *pred,set *plainSet,int *changed)
+#else
+void MR_apply_restriction1(pred,plainSet,changed)
+ Predicate *pred;
+ set *plainSet;
+ int *changed;
+#endif
+{
+ if (pred == NULL) return;
+ MR_apply_restriction1(pred->right,plainSet,changed);
+ if (pred->down != NULL) {
+ MR_apply_restriction1(pred->down,plainSet,changed);
+ } else {
+ set t;
+ if (pred->k == 1) {
+ t=set_dif(pred->scontext[1],*plainSet);
+ if (*changed == 0 &&
+ !set_equ(t,pred->scontext[1])) {
+ *changed=1;
+ };
+ if (set_nil(t)) {
+ pred->redundant=1;
+ };
+ set_free(pred->scontext[1]);
+ pred->scontext[1]=t;
+ };
+ };
+}
+
+#ifdef __USE_PROTOS
+void MR_orin_plainSet(Predicate *p,set plainSet)
+#else
+void MR_orin_plainSet(p,plainSet)
+ Predicate *p;
+ set plainSet;
+#endif
+{
+ if (p == NULL) return;
+ MR_orin_plainSet(p->down,plainSet);
+ MR_orin_plainSet(p->right,plainSet);
+ set_orin(&p->plainSet,plainSet);
+}
+
+Predicate *PRED_SUPPRESS;
+
+#ifdef __USE_PROTOS
+Predicate * MR_find_in_aSubBlk(Junction *alt)
+#else
+Predicate * MR_find_in_aSubBlk(alt)
+ Junction *alt;
+#endif
+{
+ Predicate *root=NULL;
+ Predicate **tail=NULL;
+
+ Junction *p;
+
+ int nAlts=0;
+ Junction **jList;
+ Predicate **predList;
+ int *matchList;
+ set predSet;
+ int i;
+ int j;
+ int m;
+ int predDepth;
+ set incomplete;
+ set union_plainSet;
+ set setChange;
+ int changed;
+ Predicate *newPred;
+ set setDif;
+ Predicate *origPred;
+ int depth1=1; /* const int */
+ set *plainContext;
+ set plainSet;
+
+ predSet=empty;
+ incomplete=empty;
+ union_plainSet=empty;
+ setChange=empty;
+ setDif=empty;
+ plainSet=empty;
+
+ if (PRED_SUPPRESS == NULL) {
+ PRED_SUPPRESS=new_pred();
+ PRED_SUPPRESS->expr="Predicate Suppressed";
+ };
+
+ /* this section just counts the number of "interesting" alternatives */
+ /* in order to allocate arrays */
+
+ for (p=alt; p!=NULL; p=(Junction *)p->p2) {
+ /* ignore empty alts */
+ if ( p->p1->ntype != nJunction ||
+ ((Junction *)p->p1)->jtype != EndBlk ) {
+ nAlts++;
+ };
+ };
+
+ /* if this is a (...)+ block then don't count the last alt because
+ it can't be taken until at least one time through the block.
+ In other words it isn't a real choice until the (...)+ is entered
+ at which point the hoisting issue is moot.
+ Maybe look at "ignore" instead ?
+ */
+
+ if (alt->jtype == aPlusBlk) {
+ nAlts--;
+ };
+
+ jList=(Junction **)calloc(nAlts,sizeof(Junction *));
+ require(jList!=NULL,"cannot allocate MR_find_in_aSubBlk jList");
+
+ plainContext=(set *)calloc(nAlts,sizeof(set));
+ require(plainContext!=NULL,"cannot allocate MR_find_in_aSubBlk plainContext");
+ for (m=0; m < nAlts; m++) plainContext[m]=empty;
+
+ predList=(Predicate **)calloc(nAlts,sizeof(Predicate *));
+ require(predList!=NULL,"cannot allocate MR_find_in_aSubBlk predList");
+
+ matchList=(int *)calloc(nAlts,sizeof(int));
+ require(matchList!=NULL,"cannot allocate MR_find_in_aSubBlk matchList");
+
+ /* this section just fills in the arrays previously allocated */
+ /* the most interesting one is matchList[] */
+ /* */
+ /* bit 0 => this alt has a semantic pred which is "covered" */
+ /* by an alt without a semantic pred. Don't hoist. */
+
+ for (i=0,p=alt;
+ p!=NULL && i<nAlts;
+ i++,p=(Junction *)p->p2) {
+
+ /* ignore empty alts */
+
+ if ( p->p1->ntype != nJunction ||
+ ((Junction *)p->p1)->jtype != EndBlk ) {
+ jList[i]=MR_junctionWithoutP2(p);
+ predList[i]=find_predicates(p->p1); /* should be jList ????? */
+ if (predList[i] != NULL) {
+ MR_cleanup_pred_trees(predList[i]); /* flatten & left factor */
+ plainContext[i]=MR_union_plain_sets(predList[i]);
+ } else {
+ MR_set_reuse(&plainSet);
+ MR_set_reuse(&incomplete);
+ plainSet=MR_First(depth1,jList[i],&incomplete);
+ MR_complete_set(depth1,&plainSet,&incomplete);
+ require(set_nil(incomplete),"couldn't complete k=1");
+ plainContext[i]=plainSet;
+ plainSet=empty;
+ };
+ set_orin(&union_plainSet,plainContext[i]);
+ };
+ };
+
+ if (nAlts == 1) {
+ goto EXIT_SIMPLE;
+ };
+
+/*
+ * Looking for cases where alt i has a semantic pred and alt j does not.
+ * Don't care about cases where lookahead for semantic predicates overlap
+ * because normal predicate hoisting does the correct thing automatically.
+ * Don't care about cases where lookahead for alts without semantic predicates
+ * overlap because normal prediction does the correct thing automatically.
+ *
+ * When we find such a case check for one of three subcases:
+ *
+ * 1. if lookahead for alt i is contained in the lookahead for any
+ * alt j then ignore semantic predicate of alt i
+ * 2. if lookahead for alt i is not contained in the lookahead for
+ * any alt j then add add predicate i to the OR list to be hoisted
+ * 3. if lookahead for alt i overlaps the lookahead for some alt j then
+ * add a dummy semantic predicate for alt j
+ *
+ * There is an implicit assumption that the context of all alternatives following
+ * the rule being processed here are identical (but may vary from hoist to
+ * hoist depending on the place where the rule was invoked that led to hoisting
+ * these predicates. In othere words in the fragment:
+ *
+ * ( <<a>>? a1 a2 a3 | <<b>>? b1 b2 b3 )
+ *
+ * both a3 and b3 have the same follow sets because they are both at the end of
+ * alternatives in the same block.
+ */
+
+ for (i=0; i < nAlts; i++) {
+ if (jList[i] == NULL) continue;
+ if (predList[i] == NULL) continue;
+
+ /* if the predicate depth turns out to be one token only */
+ /* then it is can be easily represented as a set and */
+ /* compared to the junction set create by MR_First() */
+
+ predDepth=0;
+ MR_pred_depth(predList[i],&predDepth);
+ require (predDepth >= 1,"MR_find_in_aSubBlk: pred depth < 1");
+ require (predDepth <= CLL_k,"MR_find_in_aSubBlk: predDepth > CLL_k");
+
+ /* complete predicates to predDepth
+ If completed to depth=1 then the context would be incomplete.
+ The context would be truncated and the predicate simplify routine
+ would have incomplete information. It would lead to
+ either false matches of failure to find true matches.
+ */
+
+ MR_complete_predicates(predDepth,predList[i]);
+
+ if (predList[i] != NULL) {
+ MR_cleanup_pred_trees(predList[i]); /* flatten & left factor */
+ };
+
+ /* If the predicate depth is 1 then it is possible to suppress
+ a predicate completely using a single plain alt. Check for suppression
+ by a single plain alt first because it gives better messages. If that
+ fails try the union of all the plain alts.
+ */
+
+ if (predDepth == 1) {
+
+ MR_set_reuse(&predSet);
+ predSet=MR_compute_pred_set(predList[i]); /* ignores k>1 predicates */
+
+ for (j=0; j < nAlts; j++) {
+ if (jList[j] == NULL) continue;
+ if (j == i) continue;
+
+ MR_set_reuse(&setDif);
+ setDif=set_dif(predSet,plainContext[j]);
+ if (set_nil(setDif)) {
+ matchList[i] |= 1;
+ MR_reportSetSuppression(predDepth,predSet,plainContext[j],jList[i],jList[j],predList[i]);
+ predicate_free(predList[i]);
+ predList[i]=PRED_SUPPRESS;
+ goto next_i;
+ };
+
+ }; /* end loop on j */
+
+ changed=0;
+
+ /* predicate_dup is only to give good error messages */
+ /* remember to do a predicate_free() */
+
+ origPred=predicate_dup(predList[i]);
+ MR_apply_restriction1(predList[i],&union_plainSet,&changed);
+ if (changed) {
+
+ /* don't use Pass3 by itself unless you know that inverted is not important */
+
+ newPred=MR_removeRedundantPredPass3(predList[i]);
+ newPred=MR_predSimplifyALL(newPred);
+ if (newPred == NULL) {
+ matchList[i] |= 1;
+ MR_reportSetSuppression(predDepth,predSet,union_plainSet,jList[i],
+ NULL,origPred);
+ predList[i]=PRED_SUPPRESS;
+ } else {
+ MR_reportSetRestriction(predDepth,predSet,union_plainSet,jList[i],
+ NULL,origPred,newPred);
+ predList[i]=newPred;
+ };
+ };
+ predicate_free(origPred);
+ origPred=NULL;
+ };
+
+ /*
+ If the predicate depth is > 1 then it can't be suppressed completely
+ because the code doesn't support inspection of such things. They're
+ much messier than k=1 sets.
+ */
+
+ if (predDepth > 1 ) {
+
+ changed=0;
+
+ /* predicate_dup is only to give good error messages */
+ /* remember to do a predicate_free() */
+
+ origPred=predicate_dup(predList[i]);
+ MR_apply_restriction1(predList[i],&union_plainSet,&changed);
+ if (changed) {
+ newPred=MR_removeRedundantPredPass3(predList[i]);
+ newPred=MR_predSimplifyALL(newPred);
+ if (newPred == NULL) {
+ matchList[i] |= 1;
+ MR_reportSetSuppression(predDepth,predSet,union_plainSet,jList[i],
+ NULL,origPred);
+ predList[i]=PRED_SUPPRESS;
+ } else {
+ MR_reportSetRestriction(predDepth,predSet,union_plainSet,jList[i],
+ NULL,origPred,newPred);
+ predList[i]=newPred;
+ };
+ };
+ predicate_free(origPred);
+ origPred=NULL;
+ };
+next_i:
+ continue;
+ };
+
+EXIT_SIMPLE:
+
+ root = new_pred();
+ root->expr=PRED_OR_LIST;
+ tail = &(root->down);
+
+ for (i=0 ; i< nAlts ; i++) {
+ if (jList[i] == NULL) continue;
+
+ if (predList[i] == NULL) {
+ continue;
+ } else if ( (matchList[i] & 1) != 0) {
+ if (predList[i] != PRED_SUPPRESS) {
+ predicate_free(predList[i]);
+ };
+ continue;
+ };
+
+ /* make an OR list of predicates */
+
+ *tail=predList[i];
+ tail=&(predList[i]->right);
+ };
+
+ /* if just one pred, remove OR root */
+
+ if (root->down == NULL) {
+ predicate_free(root);
+ root=NULL;
+ } else if (root->down->right == NULL) {
+ Predicate *p=root->down;
+ root->down=NULL;
+ predicate_free(root);
+ root=p;
+ }
+
+ root=MR_predSimplifyALL(root);
+
+ MR_orin_plainSet(root,union_plainSet);
+
+ set_free(predSet);
+ set_free(union_plainSet);
+ set_free(incomplete);
+ set_free(setChange);
+ set_free(setDif);
+
+ for (m=0; m < nAlts; m++) set_free(plainContext[m]);
+
+ free ( (char *) jList);
+ free ( (char *) predList);
+ free ( (char *) matchList);
+ free ( (char *) plainContext);
+
+ return root;
+}
+
+#ifdef __USE_PROTOS
+void MR_predContextPresent(Predicate *p,int *allHaveContext,int *noneHaveContext)
+#else
+void MR_predContextPresent(p,allHaveContext,noneHaveContext)
+ Predicate *p;
+ int *allHaveContext;
+ int *noneHaveContext;
+#endif
+{
+ if (p == NULL) return;
+ MR_predContextPresent(p->right,allHaveContext,noneHaveContext);
+ if (p->expr != PRED_AND_LIST &&
+ p->expr != PRED_OR_LIST) {
+ if (set_nil(p->scontext[1]) == 0 ||
+ (p->tcontext != NULL)) {
+ *noneHaveContext=0;
+ } else {
+ *allHaveContext=0;
+ };
+ };
+ MR_predContextPresent(p->down,allHaveContext,noneHaveContext);
+}
+
+#ifdef __USE_PROTOS
+int MR_pointerStackPush(PointerStack *ps,void *dataPointer)
+#else
+int MR_pointerStackPush(ps,dataPointer)
+ PointerStack *ps;
+ void *dataPointer;
+#endif
+{
+ void **newStack;
+ int newSize;
+ int i;
+
+ if (ps->count == ps->size) {
+ newSize=20+ps->size*2;
+ newStack=(void **)calloc(newSize,sizeof(void *));
+ require (newStack != NULL,"cannot allocate PointerStack");
+ for (i=0; i < ps->size; i++) {
+ newStack[i]=ps->data[i];
+ };
+ if (ps->data != NULL) free( (char *) ps->data);
+ ps->data=newStack;
+ ps->size=newSize;
+ };
+ ps->data[ps->count]=dataPointer;
+ ps->count++;
+ return ps->count-1;
+}
+
+#ifdef __USE_PROTOS
+void * MR_pointerStackPop(PointerStack *ps)
+#else
+void * MR_pointerStackPop(ps)
+ PointerStack *ps;
+#endif
+{
+ void *dataPointer;
+
+ require(ps->count > 0,"MR_pointerStackPop underflow");
+
+ dataPointer=ps->data[ps->count-1];
+ ps->data[ps->count-1]=NULL;
+ (ps->count)--;
+ return dataPointer;
+}
+
+#ifdef __USE_PROTOS
+void * MR_pointerStackTop(PointerStack *ps)
+#else
+void * MR_pointerStackTop(ps)
+ PointerStack *ps;
+#endif
+{
+ require(ps->count > 0,"MR_pointerStackTop underflow");
+ return ps->data[ps->count-1];
+}
+
+#ifdef __USE_PROTOS
+void MR_pointerStackReset(PointerStack *ps)
+#else
+void MR_pointerStackReset(ps)
+ PointerStack *ps;
+#endif
+{
+ int i;
+ if (ps->data != NULL) {
+ for (i=0; i < ps->count ; i++) {
+ ps->data[i]=NULL;
+ };
+ };
+ ps->count=0;
+}
+
+#ifdef __USE_PROTOS
+Junction *MR_nameToRuleBlk(char *name)
+#else
+Junction *MR_nameToRuleBlk(name)
+ char *name;
+#endif
+{
+ RuleEntry *q;
+
+ require (RulePtr != NULL,"MR_nameToRule: RulePtr not initialized");
+
+ if (name == NULL) return NULL;
+
+ q = (RuleEntry *) hash_get(Rname,name);
+
+ if ( q == NULL ) {
+ return NULL;
+ } else {
+ return RulePtr[q->rulenum];
+ };
+}
+
+#ifdef __USE_PROTOS
+Junction * MR_ruleReferenced(RuleRefNode *rrn)
+#else
+Junction * MR_ruleReferenced(rrn)
+ RuleRefNode *rrn;
+#endif
+{
+ return MR_nameToRuleBlk(rrn->text);
+}
+
+#ifdef __USE_PROTOS
+void MR_comparePredLeaves(Predicate *me,Predicate *myParent,Predicate *him,Predicate *hisParent)
+#else
+void MR_comparePredLeaves(me,myParent,him,hisParent)
+ Predicate *me;
+ Predicate *myParent;
+ Predicate *him;
+ Predicate *hisParent;
+#endif
+{
+ if (me == NULL) return;
+ if (me == him) {
+ MR_comparePredLeaves(me->right,myParent,him,hisParent);
+ return;
+ } else if (me->expr == PRED_AND_LIST ||
+ me->expr == PRED_OR_LIST) {
+ MR_comparePredLeaves(me->down,me,him,hisParent);
+ MR_comparePredLeaves(me->right,myParent,him,hisParent);
+ return;
+ } else {
+ if (me->source != NULL) {
+
+ /* predicate->invert can be set only in the predEntry predicates */
+ /* thus they are only visible after the predEntry predicates have been "unfolded" */
+
+ int sameSource=(me->source == him->source);
+ int sameInvert=1 &
+ (1 + me->inverted + him->inverted + me->source->inverted + him->source->inverted);
+ int samePredEntry=(me->source->predEntry != NULL
+ && him->source->predEntry != NULL
+ && me->source->predEntry == him->source->predEntry);
+ if (sameInvert && (sameSource || samePredEntry)) {
+ if (MR_identicalContext(me,him)) {
+
+ /* identical predicates */
+
+ if (hisParent->expr == PRED_OR_LIST &&
+ myParent->expr == PRED_OR_LIST) {
+ me->redundant=1;
+ } else if (hisParent->expr == PRED_AND_LIST &&
+ myParent->expr == PRED_AND_LIST) {
+ me->redundant=1;
+ } else if ( (hisParent->expr == PRED_OR_LIST &&
+ myParent->expr == PRED_AND_LIST)
+ ||
+ (hisParent->expr == PRED_AND_LIST &&
+ myParent->expr == PRED_OR_LIST)
+ ) {
+ myParent->redundant=1;
+ } else {
+ require (0,"MR_comparePredLeaves: not both PRED_LIST");
+ };
+ };
+ }; /* end same source or same predEntrr with same invert sense */
+
+ /* same predEntry but opposite invert sense */
+
+ if (!sameInvert && (sameSource || samePredEntry)) {
+ if (MR_identicalContext(me,him)) {
+ if (hisParent->expr == PRED_OR_LIST &&
+ myParent->expr == PRED_OR_LIST) {
+ myParent->isConst=1;
+ myParent->constValue=1;
+ } else if (hisParent->expr == PRED_AND_LIST &&
+ myParent->expr == PRED_AND_LIST) {
+ myParent->isConst=1;
+ myParent->constValue=0;
+ } else if ( (hisParent->expr == PRED_OR_LIST &&
+ myParent->expr == PRED_AND_LIST)
+ ||
+ (hisParent->expr == PRED_AND_LIST &&
+ myParent->expr == PRED_OR_LIST)
+ ) {
+ me->redundant=1;
+ } else {
+ require (0,"MR_comparePredLeaves: not both PRED_LIST");
+ };
+ };
+ }; /* end same predEntry with opposite invert sense */
+ };
+
+ MR_comparePredLeaves(me->right,myParent,him,hisParent);
+ return;
+ };
+}
+
+#ifdef __USE_PROTOS
+void MR_removeRedundantPredPass1(Predicate *me,Predicate *myParent)
+#else
+void MR_removeRedundantPredPass1(me,myParent)
+ Predicate *me;
+ Predicate *myParent;
+#endif
+{
+ if (me == NULL) return;
+ if (me->redundant) {
+ MR_removeRedundantPredPass1(me->right,myParent);
+ return;
+ };
+ if (me->expr == PRED_AND_LIST ||
+ me->expr == PRED_OR_LIST) {
+ MR_removeRedundantPredPass1(me->down,me);
+ MR_removeRedundantPredPass1(me->right,myParent);
+ } else {
+ require (me->source != NULL,"me->source == NULL");
+ if (myParent != NULL) {
+ MR_comparePredLeaves(myParent->down,myParent,me,myParent);
+ };
+ MR_removeRedundantPredPass1(me->right,myParent);
+ };
+}
+
+/* pretty much ignores things with the inverted bit set */
+
+#ifdef __USE_PROTOS
+Predicate *MR_predFlatten(Predicate *p)
+#else
+Predicate *MR_predFlatten(p)
+ Predicate *p;
+#endif
+{
+ if (p == NULL) return NULL;
+ if (p->expr == PRED_OR_LIST
+ || p->expr == PRED_AND_LIST) {
+
+ Predicate *child;
+ Predicate *gchild;
+ Predicate **tail;
+ Predicate *next;
+ char *PRED_XXX_LIST=p->expr;
+
+ require (p->down != NULL,"MR_predFlatten AND/OR no child");
+
+
+ p->down=MR_predFlatten(p->down);
+ p->right=MR_predFlatten(p->right);
+ child=p->down;
+ if (child->right == NULL) {
+ child->right=p->right;
+ p->right=NULL;
+ p->down=NULL;
+ if (p->inverted) child->inverted=!child->inverted;
+ predicate_free(p);
+ return child;
+ };
+
+ /* make a single list of all children and grandchildren */
+
+ tail=&(p->down);
+ for (child=p->down; child != NULL; child=next) {
+ if (child->expr != PRED_XXX_LIST
+ || child->inverted
+ || child->predEntry != NULL) {
+ *tail=child;
+ tail=&(child->right);
+ next=child->right;
+ } else {
+ for (gchild=child->down;
+ gchild != NULL;
+ gchild=gchild->right) {
+ *tail=gchild;
+ tail=&(gchild->right);
+ };
+ next=child->right;
+ child->right=NULL;
+ child->down=NULL;
+ predicate_free(child);
+ };
+ };
+ *tail=NULL;
+ return p;
+ } else {
+ p->right=MR_predFlatten(p->right);
+ return p;
+ };
+}
+
+static char *alwaysFalseWarning=NULL;
+
+#ifdef __USE_PROTOS
+Predicate *checkPredicateConflict(Predicate *p)
+#else
+Predicate *checkPredicateConflict(p)
+ Predicate *p;
+#endif
+{
+ if (p->isConst) {
+ if (p->constValue == 1) {
+ predicate_free(p);
+ return NULL;
+ } else {
+ if (InfoP && !p->conflictReported) {
+ p->conflictReported=1;
+ fprintf(output,"\n#if 0\n\n");
+ fprintf(output,"The following predicate expression will always be false:\n\n");
+ MR_dumpPred1(1,p,1);
+ fprintf(output,"\n#endif\n");
+ };
+
+ if (alwaysFalseWarning != CurRule) {
+ alwaysFalseWarning=CurRule;
+ if (InfoP) {
+ warnNoFL(eMsg1("one (or more) predicate expression hoisted into rule \"%s\" are always false \
+- see output file for more information",CurRule));
+ } else {
+ warnNoFL(eMsg1("one (or more) predicate expressions hoisted into rule \"%s\" are always false \
+- use \"-info p\" for more information",CurRule));
+ };
+ };
+ };
+ };
+ return p;
+}
+
+
+#ifdef __USE_PROTOS
+int MR_countPredNodes(Predicate *p)
+#else
+int MR_countPredNodes(p)
+ Predicate *p;
+#endif
+{
+ if (p == NULL) return 0;
+ return 1 + MR_countPredNodes(p->down) + MR_countPredNodes(p->right);
+}
+
+#ifdef __USE_PROTOS
+Predicate *MR_predSimplifyALLX(Predicate *p,int skipPass3)
+#else
+Predicate *MR_predSimplifyALLX(p,skipPass3)
+ Predicate *p;
+ int skipPass3;
+#endif
+{
+ int countBefore;
+ int countAfter;
+
+ countAfter=MR_countPredNodes(p);
+
+ do {
+ if (p == NULL) return NULL;
+ if (p->right == NULL && p->down == NULL) return p;
+ countBefore=countAfter;
+ MR_simplifyInverted(p,0);
+ p=MR_predFlatten(p);
+ MR_removeRedundantPredPass1(p,NULL);
+ MR_removeRedundantPredPass2(p);
+ if (! skipPass3) {
+ p=checkPredicateConflict(p);
+ p=MR_removeRedundantPredPass3(p);
+ };
+ countAfter=MR_countPredNodes(p);
+ } while (countBefore != countAfter);
+
+ return p;
+}
+
+#ifdef __USE_PROTOS
+Predicate *MR_predSimplifyALL(Predicate *p)
+#else
+Predicate *MR_predSimplifyALL(p)
+ Predicate *p;
+#endif
+{
+ return MR_predSimplifyALLX(p,0);
+}
+
+#ifdef __USE_PROTOS
+void MR_releaseResourcesUsedInRule(Node *n)
+#else
+void MR_releaseResourcesUsedInRule(n)
+ Node *n;
+#endif
+{
+ Node *next;
+ Junction *j;
+ int i;
+
+ if (n == NULL) return;
+ if (n->ntype == nJunction) {
+ j=(Junction *) n;
+
+ if (j->predicate != NULL) {
+ predicate_free(j->predicate);
+ j->predicate=NULL;
+ };
+ for (i=0; i< CLL_k; i++) {
+ set_free(j->fset[i]);
+ j->fset[i]=empty;
+ };
+ if (j->ftree != NULL) {
+ Tfree(j->ftree);
+ j->ftree=NULL;
+ };
+ if (j->jtype == EndRule) return;
+ if (j->jtype != RuleBlk && j->jtype != EndBlk) {
+ if (j->p2 != NULL && !j->ignore) { /* MR11 */
+ MR_releaseResourcesUsedInRule(j->p2);
+ };
+ };
+ };
+ next=MR_advance(n);
+ MR_releaseResourcesUsedInRule(next);
+}
+
+#ifdef __USE_PROTOS
+int MR_allPredLeaves(Predicate *p)
+#else
+int MR_allPredLeaves(p)
+ Predicate *p;
+#endif
+{
+ Predicate *q;
+
+ if (p == NULL) return 1;
+
+ for (q=p; q != NULL; q=q->right) {
+ if (q->down != NULL) return 0;
+ };
+ return 1;
+}
+
+/* make sure it works for the last rule in a file */
+
+#ifdef __USE_PROTOS
+int MR_offsetFromRule(Node *n)
+#else
+int MR_offsetFromRule(n)
+ Node *n;
+#endif
+{
+ Junction *j;
+ int offset=(-1);
+
+ for (j=SynDiag; j != NULL; j=(Junction *)j->p2) {
+
+ require (j->ntype == nJunction && j->jtype == RuleBlk,"Not a rule block");
+
+ if (n->file < j->file) {
+ return offset;
+ };
+ if (n->file == j->file) {
+ if (n->line < j->line) {
+ return (offset < 0) ? 0 : offset;
+ } else {
+ offset=n->line - j->line;
+ if (offset == 0) return 0;
+ };
+ };
+ };
+ return offset;
+}
+
+#define ruleNameMax 50
+
+static char ruleNameStatic1[ruleNameMax];
+static char ruleNameStatic2[ruleNameMax+10];
+
+#ifdef __USE_PROTOS
+char * MR_ruleNamePlusOffset(Node *n)
+#else
+char * MR_ruleNamePlusOffset(n)
+ Node *n;
+#endif
+{
+ int offset=MR_offsetFromRule(n);
+
+ strncpy(ruleNameStatic1,n->rname,ruleNameMax);
+ if (offset < 0) {
+ sprintf(ruleNameStatic2,"%s/?",ruleNameStatic1);
+ } else {
+ sprintf(ruleNameStatic2,"%s/%d",ruleNameStatic1,offset+1);
+ };
+ return ruleNameStatic2;
+}
+
+#ifdef __USE_PROTOS
+int MR_max_height_of_tree(Tree *t)
+#else
+int MR_max_height_of_tree(t)
+ Tree *t;
+#endif
+{
+ int h;
+ int height=0;
+ Tree *u;
+
+ if (t == NULL) return 0;
+
+ require (t->token != ALT && t->token != EpToken,"MR_max_height_of_tree ALT or EpToken");
+
+ for (u=t; u != NULL; u=u->right) {
+ h=MR_max_height_of_tree(u->down)+1;
+ if (h > height) height=h;
+ };
+ return height;
+}
+
+#ifdef __USE_PROTOS
+int MR_all_leaves_same_height(Tree *t,int depth)
+#else
+int MR_all_leaves_same_height(t,depth)
+ Tree *t;
+ int depth;
+#endif
+{
+ if (t == NULL) {
+ return (depth==0);
+ };
+
+ require (t->token != ALT && t->token != EpToken,"MR_all_leaves_same_height ALT or EpToken");
+
+ if (depth == 0) {
+ return 0;
+ } else {
+ if ( ! MR_all_leaves_same_height(t->down,depth-1)) {
+ return 0;
+ };
+ if (t->right == NULL) {
+ return 1;
+ } else {
+ return MR_all_leaves_same_height(t->right,depth);
+ };
+ };
+}
+
+#ifdef __USE_PROTOS
+void MR_projectTreeOntoSet(Tree *tree,int ck,set *ckset)
+#else
+void MR_projectTreeOntoSet(tree,ck,ckset)
+ Tree *tree;
+ int ck;
+ set *ckset;
+#endif
+{
+ if (tree == NULL) return;
+
+ require(tree->token != EpToken,"MR_projectTreeOntoSet: EpToken unexpected\n");
+
+ MR_projectTreeOntoSet(tree->right,ck,ckset);
+ if (tree->token == ALT) {
+ MR_projectTreeOntoSet(tree->down,ck,ckset);
+ } else {
+ if (ck > 1) {
+ MR_projectTreeOntoSet(tree->down,ck-1,ckset);
+ } else {
+ set_orel(tree->token,ckset);
+ };
+ };
+}
+
+#ifdef __USE_PROTOS
+int MR_comparePredicates(Predicate *a,Predicate *b)
+#else
+int MR_comparePredicates(a,b)
+ Predicate *a;
+ Predicate *b;
+#endif
+{
+ Predicate *p;
+ Predicate *q;
+
+ if (a == b) return 1;
+ if (a == NULL || b == NULL ) return 0;
+ if (a->down == NULL && b->down == NULL) {
+
+ /* predicate->invert can be set only in the predEntry predicates */
+ /* thus they are only visible after the predEntry predicates have been "unfolded" */
+
+ int sameSource=(a->source == b->source);
+ int sameInvert= 1 & (1 +a->inverted + b->inverted +
+ a->source->inverted + b->source->inverted);
+ int samePredEntry=(a->source->predEntry != NULL
+ && b->source->predEntry != NULL
+ && a->source->predEntry == b->source->predEntry);
+ if (sameInvert && (sameSource || samePredEntry)) {
+ if (MR_identicalContext(a,b)) {
+ return 1;
+ };
+ };
+ return 0;
+ };
+ if (a->down == NULL || b->down == NULL) return 0;
+ if (a->expr != b->expr) return 0;
+
+ for (p=a->down; p != NULL; p=p->right) {
+ for (q=b->down; q != NULL; q=q->right) {
+ if (MR_comparePredicates(p,q)) goto NEXT_P;
+ };
+ return 0;
+NEXT_P:
+ continue;
+ };
+ return 1;
+}
+
+/*
+ * action->inverted can be set only when a predicate symbol appears in
+ * a rule: "rule : <<!XXX>>? X". It cannot be set under any
+ * other circumstances. In particular it cannot be set by
+ * "#pred NotA !A" or by "#pred Nota <<!A>>?". The first case
+ * creates a predEntry and the predicate expression of that predEntry
+ * has inverted set. In the second case, the code for handling "!"
+ * is only present in buildAction, which is not called by the #pred
+ * semantic routines, only when a <<...>>? is recognized as part of
+ * a rule definition.
+ *
+ * predicate->inverted can only be set by a predicate created by a #pred
+ * expression, such as "#pred NotA !A" or "#pred NotXY ! (X && Y) or
+ * "#pred XbarY !(X && Y)". In particular, it cannot be set by any
+ * predicate expression occurring under any other circumstances.
+ * The #pred predicate expresssions are stored with in predEntry->pred
+ * and do not normally appear anywhere else until the predicates are
+ * "unfolded" in order to recognize redundancies, conflicts, and
+ * tautologies.
+ *
+ * The unfold routine expands all references to #pred expressions.
+ *
+ * The simplifyInvert goes through and propagates the invert bit so that
+ * all OR and AND nodes are un-inverted.
+ *
+ * Note that !(A and B) => (!A or !B)
+ * !(A or B) => (!A and !B)
+ *
+ * MR_unfold() is called to expand predicate symbols by replacing predicates
+ * that reference predicate entries with the copies of the predicate entries.
+ * Each reference receives a duplicate of the original. This is necessary
+ * because the next phase involves simplification and removal of redundant
+ * predicate nodes. Anyway, the point I'm making is that predicate->invert
+ * should not be set in any predicate until it has been expanded.
+ *
+ * This is a recursive structure, but there is no need for "recursive expansion"
+ * by which I mean a predicate symbol refers to other predicate symbols which
+ * must also be expanded.
+ *
+ * Recursive expansion is *not* performed by this routine because it is not
+ * necessary. Expansion of references is performed by predPrimary when
+ * a new predicate symbol is created by referring to others in the pred expr.
+ */
+
+#ifdef __USE_PROTOS
+Predicate *MR_unfold(Predicate *pred)
+#else
+Predicate *MR_unfold(pred)
+ Predicate *pred;
+#endif
+{
+ Predicate *result;
+
+ if (pred == NULL) return NULL;
+
+ pred->right=MR_unfold(pred->right);
+
+ if (pred->down == NULL) {
+ if (pred->source->predEntry != NULL) {
+ if (pred->source->predEntry->pred == NULL) {
+ ; /* do nothing */ /* a reference to a literal #pred (perhaps with "!" */
+ } else {
+ result=predicate_dup_without_context(pred->source->predEntry->pred);
+ if (pred->inverted) {
+ result->inverted=!result->inverted;
+ };
+ if (pred->source->inverted) {
+ result->inverted=!result->inverted;
+ };
+ result->right=pred->right;
+ pred->right=NULL;
+ predicate_free(pred);
+/*** result=MR_unfold(result); *** not necessary */ /* recursive expansion */
+ return result;
+ };
+ } else {
+ ; /* do nothing */ /* an inline literal predicate */
+ };
+ } else {
+ pred->down=MR_unfold(pred->down);
+ };
+ return pred;
+}
+
+/* this should be called immediately after MR_unfold() and
+ at no other times
+*/
+
+#ifdef __USE_PROTOS
+void MR_simplifyInverted(Predicate *pred,int inverted)
+#else
+void MR_simplifyInverted(pred,inverted)
+ Predicate *pred;
+ int inverted;
+#endif
+{
+ int newInverted;
+
+ if (pred == NULL) return;
+
+ MR_simplifyInverted(pred->right,inverted);
+
+ newInverted= 1 & (inverted + pred->inverted);
+
+ if (pred->down == NULL) {
+ pred->inverted=newInverted;
+ } else {
+ if (newInverted != 0) {
+ if (pred->expr == PRED_AND_LIST) {
+ pred->expr=PRED_OR_LIST;
+ } else {
+ pred->expr=PRED_AND_LIST;
+ };
+ };
+ pred->inverted=0;
+ MR_simplifyInverted(pred->down,newInverted);
+ };
+}
+
+/* only remove it from AND and OR nodes, not leaves */
+
+#ifdef __USE_PROTOS
+void MR_clearPredEntry(Predicate *p)
+#else
+void MR_clearPredEntry(p)
+ Predicate *p;
+#endif
+{
+ if (p == NULL) return;
+ MR_clearPredEntry(p->down);
+ MR_clearPredEntry(p->right);
+ if (p->down != NULL) p->predEntry=NULL;
+}
+
+
+#ifdef __USE_PROTOS
+void MR_orphanRules(FILE *f)
+#else
+void MR_orphanRules(f)
+ FILE *f;
+#endif
+{
+ set a;
+ Junction *p;
+ unsigned e;
+ RuleEntry *re;
+
+ a=empty;
+
+ if (! InfoO) return;
+
+ for (p=SynDiag; p!=NULL; p = (Junction *)p->p2) {
+ if ( (Junction *) (p->end)->p1 == NULL) {
+ re=(RuleEntry *) hash_get(Rname,p->rname);
+ require (re != NULL,"RuleEntry == NULL");
+ set_orel(re->rulenum, &a);
+ }
+ }
+
+ if (set_deg(a) > 1) {
+ fprintf(f,"note: Start rules: {");
+ for (; !set_nil(a); set_rm(e,a)) {
+ e=set_int(a);
+ fprintf(f," %s",RulePtr[e]->rname);
+ };
+ fprintf(f," }\n");
+ };
+ set_free( a );
+}
+
+/* merge (X Y) and (X) to create (X) */
+
+static int *mergeChain;
+static Tree *mergeTree;
+
+#ifdef __USE_PROTOS
+Tree *MR_merge_tree_contexts_client(Tree *t,int chain[])
+#else
+Tree *MR_merge_tree_contexts_client(t,chain)
+ Tree *t;
+ int chain[];
+#endif
+{
+ if (t == NULL) return NULL;
+ if (chain[0] == 0) {
+ Tree *u=t->right;
+ t->right=NULL;
+ Tfree(t);
+ return MR_merge_tree_contexts_client(u,&chain[0]);
+ }
+ if (chain[0] == t->token) {
+ t->down=MR_merge_tree_contexts_client(t->down,&chain[1]);
+ };
+ t->right=MR_merge_tree_contexts_client(t->right,&chain[0]);
+ return t;
+}
+
+#ifdef __USE_PROTOS
+void MR_iterateOverTreeContexts(Tree *t,int chain[])
+#else
+void MR_iterateOverTreeContexts(t,chain)
+ Tree *t;
+ int chain[];
+#endif
+{
+ if (t == NULL) return;
+ chain[0]=t->token;
+ if (t->down != NULL) {
+ MR_iterateOverTreeContexts(t->down,&chain[1]);
+ } else {
+ MR_merge_tree_contexts_client(mergeTree,mergeChain);
+ };
+ MR_iterateOverTreeContexts(t->right,&chain[0]);
+ chain[0]=0;
+}
+
+#ifdef __USE_PROTOS
+Tree *MR_merge_tree_contexts(Tree *t)
+#else
+Tree *MR_merge_tree_contexts(t)
+ Tree *t;
+#endif
+{
+ int h=MR_max_height_of_tree(t);
+
+ mergeTree=t;
+ mergeChain=(int *) calloc(h+1,sizeof(int));
+ require (mergeChain != NULL,"MR_merge_tree_contexts: can't alloc chain");
+ MR_iterateOverTreeContexts(t,mergeChain);
+ t=tshrink(t);
+ t=tflatten(t);
+ t=tleft_factor(t);
+ free ( (char *) mergeChain);
+ mergeChain=NULL;
+ return t;
+}
+
+#ifdef __USE_PROTOS
+Tree *MR_compute_pred_tree_context(Predicate *p)
+#else
+Tree *MR_compute_pred_tree_context(p)
+ Predicate *p;
+#endif
+{
+ Tree *t;
+
+ t=MR_compute_pred_tree_ctxXX(p);
+ MR_merge_tree_contexts(t);
+ return t;
+}
+
+#ifdef __USE_PROTOS
+void MR_guardPred_plainSet(ActionNode *anode,Predicate *pred)
+#else
+void MR_guardPred_plainSet(anode,pred)
+ ActionNode *anode;
+ Predicate *pred;
+#endif
+{
+ Junction *j;
+ Predicate *workPred;
+ set maskSet;
+
+ maskSet=empty;
+
+ if (!MRhoisting) return;
+
+ /* it doesn't really matter whether the predicate has
+ depth k=1 or k>1 because we're not really looking
+ at the predicate itself, just the stuff "behind"
+ the predicate.
+ */
+
+ /* shouldn't have to worry about REACHing off the end
+ of the rule containing the predicate because the
+ Rule->end->halt should have been set already by the
+ the code which handles RuleRef nodes.
+
+ We don't want to REACH off the end of the rule because
+ this would give the "global" follow context rather than
+ the "local" context.
+
+ r1a : (A)? => <<p>>? r2 (A|B)
+ r1b : (A)? => <<p>>? r2 (A|C)
+ r2 : ();
+
+ For r1a we want follow of predicate = {A B}
+ we want plainSet = {B}
+ For r1b we want follow of predicate = {A C}
+ we want plainSet = {C}
+ */
+
+ require (anode->next->ntype == nJunction,"MR_guardpred_plainSet not Junction");
+ j=(Junction *)(anode->next);
+
+ workPred=predicate_dup_without_context(pred);
+ workPred->k=1;
+ workPred->scontext[1]=MR_First(1,j, &(workPred->completionSet) );
+ MR_complete_predicates(1,workPred);
+ if (pred->k == 1) {
+ maskSet=pred->scontext[1];
+ } else {
+ MR_projectTreeOntoSet(pred->tcontext,1,&maskSet);
+ }
+ pred->plainSet=set_dif(workPred->scontext[1],maskSet);
+ predicate_free(workPred);
+}
+
+/*******************************************************************************/
+
+static Tree * suppressTree;
+static int * suppressChain; /* element 0 not used */
+static set * suppressSets;
+static Node * suppressNode;
+static int suppressChainLength;
+int MR_SuppressSearch=0;
+static int suppressSucceeded;
+static Predicate * suppressPredicate;
+
+#ifdef __USE_PROTOS
+int MR_isChain(Tree *t)
+#else
+int MR_isChain(t)
+ Tree *t;
+#endif
+{
+ Tree *u;
+
+ for (u=t; u != NULL; u=u->down) {
+ if (u->right != NULL) return 0;
+ }
+ return 1;
+}
+
+#ifdef __USE_PROTOS
+int MR_suppressK_client(Tree *tree,int tokensInChain[])
+#else
+int MR_suppressK_client(tree,tokensInChain)
+ Tree *tree;
+ int tokensInChain[];
+#endif
+{
+ int i;
+ set *save_fset;
+ int save_ConstrainSearch;
+ set incomplete;
+ Tree *t;
+
+ suppressSucceeded=0; /* volatile */
+
+ if (suppressSets == NULL) {
+ suppressSets=(set *) calloc (CLL_k+1,sizeof(set));
+ require (suppressSets != NULL,"MR_suppressK_client: suppressSets alloc");
+ };
+
+ for (suppressChainLength=1;
+ tokensInChain[suppressChainLength+1] != 0;
+ suppressChainLength++) {};
+
+ require (suppressChainLength != 0,"MR_suppressK_client: chain empty");
+
+ for (i=1 ; i <= suppressChainLength ; i++) {
+ set_clr(suppressSets[i]);
+ set_orel( (unsigned) tokensInChain[i],
+ &suppressSets[i]);
+ };
+
+ save_fset=fset;
+ save_ConstrainSearch=ConstrainSearch;
+
+ fset=suppressSets;
+
+ MR_SuppressSearch=1;
+ MR_AmbSourceSearch=1;
+ MR_MaintainBackTrace=1;
+ ConstrainSearch=1;
+
+ maxk = suppressChainLength;
+
+ incomplete=empty;
+ t=NULL;
+
+/*** constrain = &(fset[1]); ***/
+
+ MR_setConstrainPointer(&(fset[1])); /* MR18 */
+
+ MR_pointerStackReset(&MR_BackTraceStack);
+
+ TRAV(suppressNode,maxk,&incomplete,t);
+
+ Tfree(t);
+
+ require (set_nil(incomplete),"MR_suppressK_client TRAV incomplete");
+ require (MR_BackTraceStack.count == 0,
+ "MR_suppressK_client: MR_BackTraceStack.count != 0");
+ set_free(incomplete);
+
+ ConstrainSearch=save_ConstrainSearch;
+ fset=save_fset;
+
+ MR_AmbSourceSearch=0;
+ MR_MaintainBackTrace=0;
+ MR_SuppressSearch=0;
+ return suppressSucceeded;
+}
+
+#ifdef __USE_PROTOS
+Tree * MR_iterateOverTreeSuppressK(Tree *t,int chain[])
+#else
+Tree * MR_iterateOverTreeSuppressK(t,chain)
+ Tree *t;
+ int chain[];
+#endif
+{
+ if (t == NULL) return NULL;
+ t->right=MR_iterateOverTreeSuppressK(t->right,&chain[0]);
+ chain[0]=t->token;
+ if (t->down != NULL) {
+ t->down=MR_iterateOverTreeSuppressK(t->down,&chain[1]);
+ if (t->down == NULL) {
+ Tree *u=t->right;
+ t->right=NULL;
+ Tfree(t);
+ chain[0]=0;
+ return u;
+ };
+ } else {
+ MR_suppressK_client(suppressTree,suppressChain);
+ if (suppressSucceeded) {
+ Tree *u=t->right;
+ t->right=NULL;
+ Tfree(t);
+ chain[0]=0;
+ return u;
+ };
+ };
+ chain[0]=0;
+ return t;
+}
+
+/* @@@ */
+
+#ifdef __USE_PROTOS
+Predicate * MR_suppressK(Node *j,Predicate *p)
+#else
+Predicate * MR_suppressK(j,p)
+ Node *j;
+ Predicate *p;
+#endif
+{
+ Predicate *result;
+ int guardPred=0;
+ int ampersandPred=0;
+ Node *nodePrime;
+
+ if (! MRhoistingk) {
+ return p;
+ }
+
+ if (! MRhoisting) return p;
+ if (CLL_k == 1) return p;
+
+ if (suppressChain == NULL) {
+ suppressChain=(int *) calloc(CLL_k+2,sizeof(int));
+ require (suppressChain != NULL,"MR_suppressK: can't allocate chain");
+ }
+
+ if (p == NULL) return NULL;
+
+ if (j->ntype == nJunction) {
+ nodePrime=(Node *) MR_junctionWithoutP2( (Junction *) j);
+ } else {
+ nodePrime=j;
+ };
+
+ p->down=MR_suppressK(j,p->down);
+ p->right=MR_suppressK(j,p->right);
+ if (p->down != NULL) {
+ result=p;
+ goto EXIT;
+ };
+ if (p->k == 1) {
+ result=p;
+ goto EXIT;
+ };
+
+ if (p->source != NULL) {
+ if (p->source->guardpred != NULL) guardPred=1;
+ if (p->source->ampersandPred != NULL) ampersandPred=1;
+ }
+
+ suppressPredicate=p;
+ suppressNode=nodePrime; /* was j*/
+
+ suppressTree=p->tcontext;
+
+ if (guardPred || ampersandPred) {
+ p->tcontext=MR_iterateOverTreeSuppressK(suppressTree,&suppressChain[1]);
+ if (p->tcontext == NULL) {
+ predicate_free(p);
+ result=NULL;
+ goto EXIT;
+ };
+ } else {
+ if (MR_isChain(p->tcontext)) {
+ p->tcontext=MR_iterateOverTreeSuppressK(suppressTree,&suppressChain[1]);
+ if (p->tcontext == NULL) {
+ predicate_free(p);
+ result=NULL;
+ goto EXIT;
+ };
+ }
+ }
+ result=p;
+EXIT:
+ return result;
+}
+
+#ifdef __USE_PROTOS
+void MR_suppressSearchReport(void)
+#else
+void MR_suppressSearchReport()
+#endif
+{
+ int i;
+ Node *p;
+ TokNode *tn;
+ int depth;
+ set setAnd;
+
+ /* number of tokens in back trace stack matches length of chain */
+
+ depth=0;
+ for (i=0; i < MR_BackTraceStack.count ; i++) {
+ p=(Node *) MR_BackTraceStack.data[i];
+ if (p->ntype == nToken) depth++;
+ };
+
+ require (depth == suppressChainLength,"depth > suppressChainLength");
+
+ /* token codes match chain */
+
+ depth=0;
+ for (i=0; i < MR_BackTraceStack.count ; i++) {
+ p=(Node *) MR_BackTraceStack.data[i];
+ if (p->ntype != nToken) continue;
+ tn=(TokNode *) p;
+ depth++;
+ if (set_nil(tn->tset)) {
+ require(set_el( (unsigned) tn->token,fset[depth]),
+ "MR_suppressSearchReport: no match to #token in chain");
+ } else {
+ setAnd=set_and(fset[depth],tn->tset);
+ require(!set_nil(setAnd),
+ "MR_suppressSearchReport: no match to #token set in chain");
+ set_free(setAnd);
+ };
+ };
+
+ /* have a match - now remove it from the predicate */
+
+ suppressSucceeded=1;
+
+ if (suppressSucceeded) {
+ fprintf(output,"\n");
+ fprintf(output,"#if 0\n");
+ fprintf(output,"\n");
+ fprintf(output,"Part (or all) of predicate with depth > 1 suppressed by ");
+ fprintf(output,"alternative without predicate\n\n");
+ MR_dumpPred(suppressPredicate,1);
+ fprintf(output,"The token sequence which is suppressed:");
+ fprintf(output," (");
+ for (i=1; i <= suppressChainLength; i++) {
+ fprintf(output," %s",TerminalString(suppressChain[i]));
+ };
+ fprintf(output," )\n");
+ fprintf(output,"The sequence of references which generate that sequence of tokens:\n\n");
+
+ MR_backTraceDumpItemReset();
+
+ for (i=0; i < MR_BackTraceStack.count ; i++) {
+ MR_backTraceDumpItem(output,0,(Node *) MR_BackTraceStack.data[i]);
+ };
+ fprintf(output,"\n");
+ fprintf(output,"#endif\n");
+ }
+}
+
+#ifdef __USE_PROTOS
+void MR_markCompromisedRule(Node *n)
+#else
+void MR_markCompromisedRule(n)
+ Node *n;
+#endif
+{
+ RuleEntry *q;
+ Node *mark=NULL;
+ Junction *j;
+
+ if (n->ntype == nRuleRef) {
+ mark=(Node *) MR_ruleReferenced( (RuleRefNode *) n);
+ } else if (n->ntype == nToken) {
+ mark=n;
+ } else if (n->ntype == nJunction) {
+ j=(Junction *)n;
+ switch (j->jtype) {
+ case aOptBlk:
+ case aLoopBlk:
+ case RuleBlk:
+ case EndRule:
+ case aPlusBlk:
+ case aLoopBegin:
+ mark=n;
+ break;
+ default:
+ break;
+ };
+ }
+
+ if (mark == NULL) return;
+
+ require (RulePtr != NULL,"RulePtr not initialized");
+
+ q = (RuleEntry *) hash_get(Rname,mark->rname);
+ require (q != NULL,"RuleEntry not found");
+ set_orel(q->rulenum,&MR_CompromisedRules);
+}
+
+#ifdef __USE_PROTOS
+void MR_alphaBetaTraceReport(void)
+#else
+void MR_alphaBetaTraceReport()
+#endif
+{
+ int i;
+
+ if (! AlphaBetaTrace) return;
+
+ MR_AlphaBetaMessageCount++;
+
+ fprintf(output,"\n");
+ fprintf(output,"#if 0\n");
+ fprintf(output,"\n");
+ fprintf(output,"Trace of references leading to attempt to compute the follow set of\n");
+ fprintf(output,"alpha in an \"(alpha)? beta\" block. It is not possible for antlr to\n");
+ fprintf(output,"compute this follow set because it is not known what part of beta has\n");
+ fprintf(output,"already been matched by alpha and what part remains to be matched.\n");
+ fprintf(output,"\n");
+ fprintf(output,"Rules which make use of the incorrect follow set will also be incorrect\n");
+ fprintf(output,"\n");
+
+ MR_backTraceDumpItemReset();
+
+ for (i=0; i < MR_BackTraceStack.count ; i++) {
+ MR_backTraceDumpItem(output,0,(Node *) MR_BackTraceStack.data[i]);
+ if (i < MR_BackTraceStack.count-1) {
+ MR_markCompromisedRule( (Node *) MR_BackTraceStack.data[i]);
+ };
+ };
+ fprintf(output,"\n");
+ fprintf(output,"#endif\n");
+}
+
+#ifdef __USE_PROTOS
+void MR_dumpRuleSet(set s)
+#else
+void MR_dumpRuleSet(s)
+ set s;
+#endif
+{
+ unsigned *cursor;
+ unsigned *origin=set_pdq(s);
+
+ require(origin != NULL,"set_pdq failed");
+
+ if (RulePtr == NULL) {
+ fprintf(stderr,"RulePtr[] not yet initialized");
+ } else {
+ for (cursor=origin; *cursor != nil ; cursor++) {
+/**** if (cursor != origin) fprintf(stderr,","); ****/
+ fprintf(stderr," %s",RulePtr[*cursor]->rname);
+ fprintf(stderr,"\n");
+ };
+ free( (char *) origin);
+ };
+}
diff --git a/Source/Pccts/antlr/parser.dlg b/Source/Pccts/antlr/parser.dlg
new file mode 100644
index 0000000..8c43dff
--- /dev/null
+++ b/Source/Pccts/antlr/parser.dlg
@@ -0,0 +1,1387 @@
+<<
+/* parser.dlg -- DLG Description of scanner
+ *
+ * Generated from: antlr.g
+ *
+ * Terence Parr, Will Cohen, and Hank Dietz: 1989-2001
+ * Purdue University Electrical Engineering
+ * With AHPCRC, University of Minnesota
+ * ANTLR Version 1.33MR33
+ */
+
+#define ANTLR_VERSION 13333
+#include "pcctscfg.h"
+#include "pccts_stdio.h"
+
+#include "pcctscfg.h"
+#include "set.h"
+#include <ctype.h>
+#include "syn.h"
+#include "hash.h"
+#include "generic.h"
+#define zzcr_attr(attr,tok,t)
+#include "antlr.h"
+#include "tokens.h"
+#include "dlgdef.h"
+LOOKAHEAD
+
+void
+#ifdef __USE_PROTOS
+zzerraction(void)
+#else
+zzerraction()
+#endif
+{
+ (*zzerr)("invalid token");
+ zzadvance();
+ zzskip();
+}
+>>
+
+<<%%lexaction
+
+/* maintained, but not used for now */
+set AST_nodes_refd_in_actions = set_init;
+int inAlt = 0;
+set attribsRefdFromAction = set_init; /* MR20 */
+int UsedOldStyleAttrib = 0;
+int UsedNewStyleLabel = 0;
+#ifdef __USE_PROTOS
+char *inline_set(char *);
+#else
+char *inline_set();
+#endif
+
+/* MR1 10-Apr-97 MR1 Previously unable to put right shift operator */
+/* MR1 in DLG action */
+
+int tokenActionActive=0; /* MR1 */
+
+
+>>
+
+<<%%lexaction
+
+
+static char *
+#ifdef __USE_PROTOS
+getFileNameFromTheLineInfo(char *toStr, char *fromStr)
+#else
+getFileNameFromTheLineInfo(toStr, fromStr)
+char *toStr, *fromStr;
+#endif
+{
+ int i, j, k;
+
+ if (!fromStr || !toStr) return toStr;
+
+ /* find the first " */
+
+ for (i=0;
+ (i<MaxFileName) &&
+ (fromStr[i] != '\n') &&
+ (fromStr[i] != '\r') &&
+ (fromStr[i] != '\"');
+ i++) /* nothing */ ;
+
+ if ( (i == MaxFileName) ||
+ (fromStr[i] == '\n') ||
+ (fromStr[i] == '\r') ) {
+ return toStr;
+}
+
+ /* find the second " */
+
+ for (j=i+1;
+(j<MaxFileName) &&
+(fromStr[j] != '\n') &&
+(fromStr[j] != '\r') &&
+(fromStr[j] != '\"');
+j++) /* nothing */ ;
+
+ if ((j == MaxFileName) ||
+(fromStr[j] == '\n') ||
+(fromStr[j] == '\r') ) {
+ return toStr;
+}
+
+ /* go back until the last / or \ */
+
+ for (k=j-1;
+(fromStr[k] != '\"') &&
+(fromStr[k] != '/') &&
+(fromStr[k] != '\\');
+k--) /* nothing */ ;
+
+ /* copy the string after " / or \ into toStr */
+
+ for (i=k+1; fromStr[i] != '\"'; i++) {
+toStr[i-k-1] = fromStr[i];
+}
+
+ toStr[i-k-1] = '\0';
+
+ return toStr;
+}
+
+/* MR14 end of a block to support #line in antlr source code */
+
+
+>>
+
+<<%%lexaction
+
+#ifdef __USE_PROTOS
+void mark_label_used_in_sem_pred(LabelEntry *le) /* MR10 */
+#else
+void mark_label_used_in_sem_pred(le) /* MR10 */
+LabelEntry *le;
+#endif
+{
+ TokNode *tn;
+ require (le->elem->ntype == nToken,"mark_label_used... ntype != nToken");
+ tn=(TokNode *)le->elem;
+ require (tn->label != 0,"mark_label_used... TokNode has no label");
+ tn->label_used_in_semantic_pred=1;
+}
+>>
+
+
+%%START
+
+@
+ <<
+ NLA = Eof;
+ /* L o o k F o r A n o t h e r F i l e */
+ {
+ FILE *new_input;
+ new_input = NextFile();
+ if ( new_input == NULL ) { NLA=Eof; return; }
+ fclose( input );
+ input = new_input;
+ zzrdstream( input );
+ zzskip(); /* Skip the Eof (@) char i.e continue */
+ }
+ >>
+
+[\t\ ]+
+ <<
+ NLA = 76;
+ zzskip();
+ >>
+
+\n|\r|\r\n
+ <<
+ NLA = 77;
+ zzline++; zzskip();
+ >>
+
+\[
+ <<
+ NLA = 78;
+ zzmode(ACTIONS); zzmore();
+ istackreset();
+ pushint(']');
+ >>
+
+\<\<
+ <<
+ NLA = 79;
+ action_file=CurFile; action_line=zzline;
+ zzmode(ACTIONS); zzmore();
+ list_free(&CurActionLabels,0); /* MR10 */
+ numericActionLabel=0; /* MR10 */
+ istackreset();
+ pushint('>');
+ >>
+
+\"
+ <<
+ NLA = 80;
+ zzmode(STRINGS); zzmore();
+ >>
+
+/\*
+ <<
+ NLA = 81;
+ zzmode(COMMENTS); zzskip();
+ >>
+
+\*/
+ <<
+ NLA = 82;
+ warn("Missing /*; found dangling */"); zzskip();
+ >>
+
+//
+ <<
+ NLA = 83;
+ zzmode(CPP_COMMENTS); zzskip();
+ >>
+
+#line[\ \t]* [0-9]+ {[\ \t]* \"~[\"]+\" ([\ \t]* [0-9]*)* } (\n|\r|\r\n)
+ <<
+ NLA = 84;
+
+ zzline = atoi(zzbegexpr+5) - 1; zzline++; zzmore();
+ getFileNameFromTheLineInfo(FileStr[CurFile], zzbegexpr);
+ >>
+
+#line ~[\n\r]* (\n|\r|\r\n)
+ <<
+ NLA = 85;
+
+ zzline++; zzmore();
+ >>
+
+\>\>
+ <<
+ NLA = 86;
+ warn("Missing <<; found dangling \>\>"); zzskip();
+ >>
+
+.
+ <<
+ NLA = WildCard;
+ >>
+
+\@
+ <<
+ NLA = 88;
+ FoundException = 1; /* MR6 */
+ FoundAtOperator = 1;
+ >>
+
+{\\}#pragma
+ <<
+ NLA = Pragma;
+ >>
+
+{\\}#FirstSetSymbol
+ <<
+ NLA = FirstSetSymbol;
+ >>
+
+{\\}#header
+ <<
+ NLA = 94;
+ >>
+
+{\\}#first
+ <<
+ NLA = 95;
+ >>
+
+{\\}#parser
+ <<
+ NLA = 96;
+ >>
+
+{\\}#tokdefs
+ <<
+ NLA = 97;
+ >>
+
+\}
+ <<
+ NLA = 98;
+ >>
+
+class
+ <<
+ NLA = 99;
+ >>
+
+\{
+ <<
+ NLA = 102;
+ >>
+
+!
+ <<
+ NLA = 103;
+ >>
+
+\<
+ <<
+ NLA = 104;
+ >>
+
+\>
+ <<
+ NLA = 105;
+ >>
+
+:
+ <<
+ NLA = 106;
+ >>
+
+;
+ <<
+ NLA = 107;
+ >>
+
+{\\}#lexaction
+ <<
+ NLA = 108;
+ >>
+
+{\\}#lexmember
+ <<
+ NLA = 109;
+ >>
+
+{\\}#lexprefix
+ <<
+ NLA = 110;
+ >>
+
+{\\}#pred
+ <<
+ NLA = 111;
+ >>
+
+\|\|
+ <<
+ NLA = 112;
+ >>
+
+&&
+ <<
+ NLA = 113;
+ >>
+
+\(
+ <<
+ NLA = 114;
+ >>
+
+\)
+ <<
+ NLA = 115;
+ >>
+
+{\\}#lexclass
+ <<
+ NLA = 116;
+ >>
+
+{\\}#errclass
+ <<
+ NLA = 117;
+ >>
+
+{\\}#tokclass
+ <<
+ NLA = 118;
+ >>
+
+..
+ <<
+ NLA = 119;
+ >>
+
+{\\}#token
+ <<
+ NLA = 120;
+ >>
+
+=
+ <<
+ NLA = 121;
+ >>
+
+[0-9]+
+ <<
+ NLA = 122;
+ >>
+
+\|
+ <<
+ NLA = 123;
+ >>
+
+\~
+ <<
+ NLA = 124;
+ >>
+
+^
+ <<
+ NLA = 125;
+ >>
+
+approx
+ <<
+ NLA = 126;
+ >>
+
+LL\(1\)
+ <<
+ NLA = 127;
+ >>
+
+LL\(2\)
+ <<
+ NLA = 128;
+ >>
+
+\*
+ <<
+ NLA = 129;
+ >>
+
+\+
+ <<
+ NLA = 130;
+ >>
+
+?
+ <<
+ NLA = 131;
+ >>
+
+=>
+ <<
+ NLA = 132;
+ >>
+
+exception
+ <<
+ NLA = 133;
+ >>
+
+default
+ <<
+ NLA = 134;
+ >>
+
+catch
+ <<
+ NLA = 135;
+ >>
+
+[a-z] [A-Za-z0-9_]*
+ <<
+ NLA = NonTerminal;
+
+ while ( zzchar==' ' || zzchar=='\t' ) {
+ zzadvance();
+ }
+ if ( zzchar == ':' && inAlt ) NLA = LABEL;
+ >>
+
+[A-Z] [A-Za-z0-9_]*
+ <<
+ NLA = TokenTerm;
+
+ while ( zzchar==' ' || zzchar=='\t' ) {
+ zzadvance();
+ }
+ if ( zzchar == ':' && inAlt ) NLA = LABEL;
+ >>
+
+{\\}#[A-Za-z0-9_]*
+ <<
+ NLA = 136;
+ warn(eMsg1("unknown meta-op: %s",LATEXT(1))); zzskip();
+ >>
+
+
+%%STRINGS
+
+@
+ <<
+ NLA = Eof;
+ >>
+
+\"
+ <<
+ NLA = QuotedTerm;
+ zzmode(START);
+ >>
+
+\n|\r|\r\n
+ <<
+ NLA = 3;
+
+ zzline++;
+ warn("eoln found in string");
+ zzskip();
+ >>
+
+\\(\n|\r|\r\n)
+ <<
+ NLA = 4;
+ zzline++; zzmore();
+ >>
+
+\\~[]
+ <<
+ NLA = 5;
+ zzmore();
+ >>
+
+~[\n\r\"\\]+
+ <<
+ NLA = 6;
+ zzmore();
+ >>
+
+
+%%ACTION_STRINGS
+
+@
+ <<
+ NLA = Eof;
+ >>
+
+\"
+ <<
+ NLA = 7;
+ zzmode(ACTIONS); zzmore();
+ >>
+
+\n|\r|\r\n
+ <<
+ NLA = 8;
+
+ zzline++;
+ warn("eoln found in string (in user action)");
+ zzskip();
+ >>
+
+\\(\n|\r|\r\n)
+ <<
+ NLA = 9;
+ zzline++; zzmore();
+ >>
+
+\\~[]
+ <<
+ NLA = 10;
+ zzmore();
+ >>
+
+~[\n\r\"\\]+
+ <<
+ NLA = 11;
+ zzmore();
+ >>
+
+
+%%ACTION_CHARS
+
+@
+ <<
+ NLA = Eof;
+ >>
+
+'
+ <<
+ NLA = 12;
+ zzmode(ACTIONS); zzmore();
+ >>
+
+\n|\r|\r\n
+ <<
+ NLA = 13;
+
+ zzline++;
+ warn("eoln found in char literal (in user action)");
+ zzskip();
+ >>
+
+\\~[]
+ <<
+ NLA = 14;
+ zzmore();
+ >>
+
+~[\n\r'\\]+
+ <<
+ NLA = 15;
+ zzmore();
+ >>
+
+
+%%ACTION_COMMENTS
+
+@
+ <<
+ NLA = Eof;
+ >>
+
+\*/
+ <<
+ NLA = 16;
+ zzmode(ACTIONS); zzmore();
+ >>
+
+\*
+ <<
+ NLA = 17;
+ zzmore();
+ >>
+
+\n|\r|\r\n
+ <<
+ NLA = 18;
+ zzline++; zzmore(); DAWDLE;
+ >>
+
+~[\n\r\*]+
+ <<
+ NLA = 19;
+ zzmore();
+ >>
+
+
+%%TOK_DEF_COMMENTS
+
+@
+ <<
+ NLA = Eof;
+ >>
+
+\*/
+ <<
+ NLA = 20;
+ zzmode(PARSE_ENUM_FILE);
+ zzmore();
+ >>
+
+\*
+ <<
+ NLA = 21;
+ zzmore();
+ >>
+
+\n|\r|\r\n
+ <<
+ NLA = 22;
+ zzline++; zzmore(); DAWDLE;
+ >>
+
+~[\n\r\*]+
+ <<
+ NLA = 23;
+ zzmore();
+ >>
+
+
+%%TOK_DEF_CPP_COMMENTS
+
+@
+ <<
+ NLA = Eof;
+ >>
+
+\n|\r|\r\n
+ <<
+ NLA = 24;
+ zzline++; zzmode(PARSE_ENUM_FILE); zzskip(); DAWDLE;
+ >>
+
+~[\n\r]+
+ <<
+ NLA = 25;
+ zzskip();
+ >>
+
+
+%%ACTION_CPP_COMMENTS
+
+@
+ <<
+ NLA = Eof;
+ >>
+
+\n|\r|\r\n
+ <<
+ NLA = 26;
+ zzline++; zzmode(ACTIONS); zzmore(); DAWDLE;
+ >>
+
+~[\n\r]+
+ <<
+ NLA = 27;
+ zzmore();
+ >>
+
+
+%%CPP_COMMENTS
+
+@
+ <<
+ NLA = Eof;
+ >>
+
+\n|\r|\r\n
+ <<
+ NLA = 28;
+ zzline++; zzmode(START); zzskip(); DAWDLE;
+ >>
+
+~[\n\r]+
+ <<
+ NLA = 29;
+ zzskip();
+ >>
+
+
+%%COMMENTS
+
+@
+ <<
+ NLA = Eof;
+ >>
+
+\*/
+ <<
+ NLA = 30;
+ zzmode(START); zzskip();
+ >>
+
+\*
+ <<
+ NLA = 31;
+ zzskip();
+ >>
+
+\n|\r|\r\n
+ <<
+ NLA = 32;
+ zzline++; zzskip(); DAWDLE;
+ >>
+
+~[\n\r\*]+
+ <<
+ NLA = 33;
+ zzskip();
+ >>
+
+
+%%ACTIONS
+
+@
+ <<
+ NLA = Eof;
+ >>
+
+\>\>
+ <<
+ NLA = Action;
+ /* these do not nest */
+ zzmode(START);
+ NLATEXT[0] = ' ';
+ NLATEXT[1] = ' ';
+ zzbegexpr[0] = ' ';
+ zzbegexpr[1] = ' ';
+ if ( zzbufovf ) {
+ err( eMsgd("action buffer overflow; size %d",ZZLEXBUFSIZE));
+ }
+
+/* MR1 10-Apr-97 MR1 Previously unable to put right shift operator */
+ /* MR1 in DLG action */
+ /* MR1 Doesn't matter what kind of action it is - reset*/
+
+ tokenActionActive=0; /* MR1 */
+ >>
+
+\>\>?
+ <<
+ NLA = Pred;
+ /* these do not nest */
+ zzmode(START);
+ NLATEXT[0] = ' ';
+ NLATEXT[1] = ' ';
+ zzbegexpr[0] = '\0';
+ if ( zzbufovf ) {
+ err( eMsgd("predicate buffer overflow; size %d",ZZLEXBUFSIZE));
+ };
+#ifdef __cplusplus__
+ /* MR10 */ list_apply(CurActionLabels, (void (*)(void *))mark_label_used_in_sem_pred);
+#else
+#ifdef __STDC__
+ /* MR10 */ list_apply(CurActionLabels, (void (*)(void *))mark_label_used_in_sem_pred);
+#else
+#ifdef __USE_PROTOS
+ /* MRxx */ list_apply(CurActionLabels, (void (*)(void *))mark_label_used_in_sem_pred);
+#else
+ /* MR10 */ list_apply(CurActionLabels,mark_label_used_in_sem_pred);
+#endif
+#endif
+#endif
+ >>
+
+\]
+ <<
+ NLA = PassAction;
+ if ( topint() == ']' ) {
+ popint();
+ if ( istackempty() ) /* terminate action */
+ {
+ zzmode(START);
+ NLATEXT[0] = ' ';
+ zzbegexpr[0] = ' ';
+ if ( zzbufovf ) {
+ err( eMsgd("parameter buffer overflow; size %d",ZZLEXBUFSIZE));
+ }
+ }
+ else {
+ /* terminate $[..] and #[..] */
+ if ( GenCC ) zzreplstr("))");
+ else zzreplstr(")");
+ zzmore();
+ }
+ }
+ else if ( topint() == '|' ) { /* end of simple [...] */
+ popint();
+ zzmore();
+ }
+ else zzmore();
+ >>
+
+consumeUntil\( [\ \t]* \{~[\}]+\} [\ \t]* \)
+ <<
+ NLA = 37;
+
+ zzmore();
+ zzreplstr(inline_set(zzbegexpr+
+ strlen("consumeUntil(")));
+ >>
+
+consumeUntil\( ~[\)]+ \)
+ <<
+ NLA = 38;
+ zzmore();
+ >>
+
+\n|\r|\r\n
+ <<
+ NLA = 39;
+ zzline++; zzmore(); DAWDLE;
+ >>
+
+\>
+ <<
+ NLA = 40;
+ zzmore();
+ >>
+
+$
+ <<
+ NLA = 41;
+ zzmore();
+ >>
+
+$$
+ <<
+ NLA = 42;
+ if ( !GenCC ) {zzreplstr("zzaRet"); zzmore();}
+ else err("$$ use invalid in C++ mode");
+ >>
+
+$\[\]
+ <<
+ NLA = 43;
+ if ( !GenCC ) {zzreplstr("zzempty_attr"); zzmore();}
+ else err("$[] use invalid in C++ mode");
+ >>
+
+$\[
+ <<
+ NLA = 44;
+
+ pushint(']');
+ if ( !GenCC ) zzreplstr("zzconstr_attr(");
+ else err("$[..] use invalid in C++ mode");
+ zzmore();
+ >>
+
+$[0-9]+
+ <<
+ NLA = 45;
+ {
+ static char buf[100];
+ numericActionLabel=1; /* MR10 */
+ if ( strlen(zzbegexpr)>(size_t)85 )
+ fatal("$i attrib ref too big");
+ set_orel(atoi(zzbegexpr+1), &attribsRefdFromAction);
+ if ( !GenCC ) sprintf(buf,"zzaArg(zztasp%d,%s)",
+ BlkLevel-1,zzbegexpr+1);
+ else sprintf(buf,"_t%d%s",
+ BlkLevel-1,zzbegexpr+1);
+ zzreplstr(buf);
+ zzmore();
+ UsedOldStyleAttrib = 1;
+ if ( UsedNewStyleLabel )
+ err("cannot mix old-style $i with new-style labels");
+ }
+ >>
+
+$[0-9]+.
+ <<
+ NLA = 46;
+ {
+ static char buf[100];
+ numericActionLabel=1; /* MR10 */
+ if ( strlen(zzbegexpr)>(size_t)85 )
+ fatal("$i.field attrib ref too big");
+ zzbegexpr[strlen(zzbegexpr)-1] = ' ';
+ set_orel(atoi(zzbegexpr+1), &attribsRefdFromAction);
+ if ( !GenCC ) sprintf(buf,"zzaArg(zztasp%d,%s).",
+ BlkLevel-1,zzbegexpr+1);
+ else sprintf(buf,"_t%d%s.",
+ BlkLevel-1,zzbegexpr+1);
+ zzreplstr(buf);
+ zzmore();
+ UsedOldStyleAttrib = 1;
+ if ( UsedNewStyleLabel )
+ err("cannot mix old-style $i with new-style labels");
+ }
+ >>
+
+$[0-9]+.[0-9]+
+ <<
+ NLA = 47;
+ {
+ static char buf[100];
+ static char i[20], j[20];
+ char *p,*q;
+ numericActionLabel=1; /* MR10 */
+ if (strlen(zzbegexpr)>(size_t)85) fatal("$i.j attrib ref too big");
+ for (p=zzbegexpr+1,q= &i[0]; *p!='.'; p++) {
+ if ( q == &i[20] )
+ fatalFL("i of $i.j attrib ref too big",
+ FileStr[CurFile], zzline );
+ *q++ = *p;
+ }
+ *q = '\0';
+ for (p++, q= &j[0]; *p!='\0'; p++) {
+ if ( q == &j[20] )
+ fatalFL("j of $i.j attrib ref too big",
+ FileStr[CurFile], zzline );
+ *q++ = *p;
+ }
+ *q = '\0';
+ if ( !GenCC ) sprintf(buf,"zzaArg(zztasp%s,%s)",i,j);
+ else sprintf(buf,"_t%s%s",i,j);
+ zzreplstr(buf);
+ zzmore();
+ UsedOldStyleAttrib = 1;
+ if ( UsedNewStyleLabel )
+ err("cannot mix old-style $i with new-style labels");
+ }
+ >>
+
+$[_a-zA-Z][_a-zA-Z0-9]*
+ <<
+ NLA = 48;
+ { static char buf[300]; LabelEntry *el;
+ zzbegexpr[0] = ' ';
+ if ( CurRule != NULL &&
+ strcmp(CurRule, &zzbegexpr[1])==0 ) {
+ if ( !GenCC ) zzreplstr("zzaRet");
+ }
+ else if ( CurRetDef != NULL &&
+ strmember(CurRetDef, &zzbegexpr[1])) {
+ if ( hasMultipleOperands( CurRetDef ) ) {
+ require (strlen(zzbegexpr)<=(size_t)285,
+ "$retval attrib ref too big");
+ sprintf(buf,"_retv.%s",&zzbegexpr[1]);
+ zzreplstr(buf);
+ }
+ else zzreplstr("_retv");
+ }
+ else if ( CurParmDef != NULL &&
+ strmember(CurParmDef, &zzbegexpr[1])) {
+ ;
+ }
+ else if ( Elabel==NULL ) {
+ { err("$-variables in actions outside of rules are not allowed"); }
+ } else if ( (el=(LabelEntry *)hash_get(Elabel, &zzbegexpr[1]))!=NULL ) {
+ /* MR10 */
+ /* MR10 */ /* element labels might exist without an elem when */
+ /* MR10 */ /* it is a forward reference (to a rule) */
+ /* MR10 */
+ /* MR10 */ if ( GenCC && (el->elem == NULL || el->elem->ntype==nRuleRef) )
+ /* MR10 */ { err(eMsg1("There are no token ptrs for rule references: '$%s'",&zzbegexpr[1])); }
+ /* MR10 */
+ /* MR10 */ if ( !GenCC && (el->elem == NULL || el->elem->ntype==nRuleRef) && GenAST) {
+ /* MR10 */ err("You can no longer use attributes returned by rules when also using ASTs");
+ /* MR10 */ err(" Use upward inheritance (\"rule >[Attrib a] : ... <<$a=...\>\>\")");
+ /* MR10 */ };
+ /* MR10 */
+ /* MR10 */ /* keep track of <<... $label ...>> for semantic predicates in guess mode */
+ /* MR10 */ /* element labels contain pointer to the owners node */
+ /* MR10 */
+ /* MR10 */ if (el->elem != NULL && el->elem->ntype == nToken) {
+ /* MR10 */ list_add(&CurActionLabels,el);
+ /* MR10 */ };
+}
+else
+warn(eMsg1("$%s not parameter, return value, (defined) element label",&zzbegexpr[1]));
+}
+zzmore();
+ >>
+
+#0
+ <<
+ NLA = 49;
+ zzreplstr("(*_root)"); zzmore(); chkGTFlag();
+ >>
+
+#\[\]
+ <<
+ NLA = 50;
+ if ( GenCC ) {
+ if (NewAST) zzreplstr("(newAST)");
+ else zzreplstr("(new AST)");}
+ else {zzreplstr("zzastnew()");} zzmore();
+ chkGTFlag();
+ >>
+
+#\(\)
+ <<
+ NLA = 51;
+ zzreplstr("NULL"); zzmore(); chkGTFlag();
+ >>
+
+#[0-9]+
+ <<
+ NLA = 52;
+ {
+ static char buf[100];
+ if ( strlen(zzbegexpr)>(size_t)85 )
+ fatal("#i AST ref too big");
+ if ( GenCC ) sprintf(buf,"_ast%d%s",BlkLevel-1,zzbegexpr+1);
+ else sprintf(buf,"zzastArg(%s)",zzbegexpr+1);
+ zzreplstr(buf);
+ zzmore();
+ set_orel(atoi(zzbegexpr+1), &AST_nodes_refd_in_actions);
+ chkGTFlag();
+ }
+ >>
+
+#line[\ \t]* [0-9]+ {[\ \t]* \"~[\"]+\" ([\ \t]* [0-9]*)* } (\n|\r|\r\n)
+ <<
+ NLA = 53;
+
+ zzline = atoi(zzbegexpr+5) - 1; zzline++; zzmore();
+ getFileNameFromTheLineInfo(FileStr[CurFile], zzbegexpr);
+ >>
+
+#line ~[\n\r]* (\n|\r|\r\n)
+ <<
+ NLA = 54;
+
+ zzline++; zzmore();
+ >>
+
+#[_a-zA-Z][_a-zA-Z0-9]*
+ <<
+ NLA = 55;
+
+ if ( !(strcmp(zzbegexpr, "#ifdef")==0 ||
+ strcmp(zzbegexpr, "#if")==0 ||
+ strcmp(zzbegexpr, "#else")==0 ||
+ strcmp(zzbegexpr, "#endif")==0 ||
+ strcmp(zzbegexpr, "#ifndef")==0 ||
+ strcmp(zzbegexpr, "#define")==0 ||
+ strcmp(zzbegexpr, "#pragma")==0 ||
+ strcmp(zzbegexpr, "#undef")==0 ||
+ strcmp(zzbegexpr, "#import")==0 ||
+ strcmp(zzbegexpr, "#line")==0 ||
+ strcmp(zzbegexpr, "#include")==0 ||
+ strcmp(zzbegexpr, "#error")==0) )
+ {
+ static char buf[100];
+ sprintf(buf, "%s_ast", zzbegexpr+1);
+ /* MR27 */ list_add(&CurAstLabelsInActions, mystrdup(zzbegexpr+1));
+ zzreplstr(buf);
+ chkGTFlag();
+ }
+ zzmore();
+ >>
+
+#\[
+ <<
+ NLA = 56;
+
+ pushint(']');
+ if ( GenCC ) {
+ if (NewAST) zzreplstr("(newAST(");
+ else zzreplstr("(new AST("); }
+ else zzreplstr("zzmk_ast(zzastnew(),");
+ zzmore();
+ chkGTFlag();
+ >>
+
+#\(
+ <<
+ NLA = 57;
+
+ pushint('}');
+ if ( GenCC ) {
+ if (tmakeInParser) {
+ zzreplstr("tmake(");
+ }
+ else {
+ zzreplstr("ASTBase::tmake(");
+ }
+ }
+ else {
+ zzreplstr("zztmake(");
+ }
+ zzmore();
+ chkGTFlag();
+ >>
+
+#
+ <<
+ NLA = 58;
+ zzmore();
+ >>
+
+\)
+ <<
+ NLA = 59;
+
+ if ( istackempty() )
+ zzmore();
+ else if ( topint()==')' ) {
+ popint();
+ }
+ else if ( topint()=='}' ) {
+ popint();
+ /* terminate #(..) */
+ zzreplstr(", NULL)");
+ }
+ zzmore();
+ >>
+
+\[
+ <<
+ NLA = 60;
+
+ pushint('|'); /* look for '|' to terminate simple [...] */
+ zzmore();
+ >>
+
+\(
+ <<
+ NLA = 61;
+
+ pushint(')');
+ zzmore();
+ >>
+
+\\\]
+ <<
+ NLA = 62;
+ zzreplstr("]"); zzmore();
+ >>
+
+\\\)
+ <<
+ NLA = 63;
+ zzreplstr(")"); zzmore();
+ >>
+
+\\>
+ <<
+ NLA = 64;
+ if (! tokenActionActive) zzreplstr(">"); /* MR1 */
+ zzmore(); /* MR1 */
+ >>
+
+'
+ <<
+ NLA = 65;
+ zzmode(ACTION_CHARS); zzmore();
+ >>
+
+\"
+ <<
+ NLA = 66;
+ zzmode(ACTION_STRINGS); zzmore();
+ >>
+
+\\$
+ <<
+ NLA = 67;
+ zzreplstr("$"); zzmore();
+ >>
+
+\\#
+ <<
+ NLA = 68;
+ zzreplstr("#"); zzmore();
+ >>
+
+\\(\n|\r|\r\n)
+ <<
+ NLA = 69;
+ zzline++; zzmore();
+ >>
+
+\\~[\]\)>$#]
+ <<
+ NLA = 70;
+ zzmore();
+ >>
+
+/
+ <<
+ NLA = 71;
+ zzmore();
+ >>
+
+/\*
+ <<
+ NLA = 72;
+ zzmode(ACTION_COMMENTS); zzmore();
+ >>
+
+\*/
+ <<
+ NLA = 73;
+ warn("Missing /*; found dangling */ in action"); zzmore();
+ >>
+
+//
+ <<
+ NLA = 74;
+ zzmode(ACTION_CPP_COMMENTS); zzmore();
+ >>
+
+~[\n\r\)\(\\$#\>\]\[\"'/]+
+ <<
+ NLA = 75;
+ zzmore();
+ >>
+
+
+%%PARSE_ENUM_FILE
+
+@
+ <<
+ NLA = Eof;
+ ;
+ >>
+
+[\t\ ]+
+ <<
+ NLA = 137;
+ zzskip();
+ >>
+
+\n|\r|\r\n
+ <<
+ NLA = 138;
+ zzline++; zzskip();
+ >>
+
+//
+ <<
+ NLA = 139;
+ zzmode(TOK_DEF_CPP_COMMENTS); zzmore();
+ >>
+
+/\*
+ <<
+ NLA = 140;
+ zzmode(TOK_DEF_COMMENTS); zzskip();
+ >>
+
+#ifdef
+ <<
+ NLA = 141;
+ zzmode(TOK_DEF_CPP_COMMENTS); zzskip();
+ >>
+
+#if
+ <<
+ NLA = 142;
+ zzmode(TOK_DEF_CPP_COMMENTS); zzskip();
+ >>
+
+#ifndef
+ <<
+ NLA = 143;
+ ;
+ >>
+
+#else
+ <<
+ NLA = 144;
+ zzmode(TOK_DEF_CPP_COMMENTS); zzskip();
+ >>
+
+#endif
+ <<
+ NLA = 145;
+ zzmode(TOK_DEF_CPP_COMMENTS); zzskip();
+ >>
+
+#undef
+ <<
+ NLA = 146;
+ zzmode(TOK_DEF_CPP_COMMENTS); zzskip();
+ >>
+
+#import
+ <<
+ NLA = 147;
+ zzmode(TOK_DEF_CPP_COMMENTS); zzskip();
+ >>
+
+#define
+ <<
+ NLA = 149;
+ >>
+
+enum
+ <<
+ NLA = 151;
+ >>
+
+\{
+ <<
+ NLA = 152;
+ >>
+
+=
+ <<
+ NLA = 153;
+ >>
+
+,
+ <<
+ NLA = 154;
+ >>
+
+\}
+ <<
+ NLA = 155;
+ >>
+
+;
+ <<
+ NLA = 156;
+ >>
+
+[0-9]+
+ <<
+ NLA = INT;
+ >>
+
+[a-zA-Z_][_a-zA-Z0-9]*
+ <<
+ NLA = ID;
+ >>
+
+%%
diff --git a/Source/Pccts/antlr/pred.c b/Source/Pccts/antlr/pred.c
new file mode 100644
index 0000000..eb11c4d
--- /dev/null
+++ b/Source/Pccts/antlr/pred.c
@@ -0,0 +1,821 @@
+/*
+ * pred.c -- source for predicate detection, manipulation
+ *
+ * SOFTWARE RIGHTS
+ *
+ * We reserve no LEGAL rights to the Purdue Compiler Construction Tool
+ * Set (PCCTS) -- PCCTS is in the public domain. An individual or
+ * company may do whatever they wish with source code distributed with
+ * PCCTS or the code generated by PCCTS, including the incorporation of
+ * PCCTS, or its output, into commerical software.
+ *
+ * We encourage users to develop software with PCCTS. However, we do ask
+ * that credit is given to us for developing PCCTS. By "credit",
+ * we mean that if you incorporate our source code into one of your
+ * programs (commercial product, research project, or otherwise) that you
+ * acknowledge this fact somewhere in the documentation, research report,
+ * etc... If you like PCCTS and have developed a nice tool with the
+ * output, please mention that you developed it using PCCTS. In
+ * addition, we ask that this header remain intact in our source code.
+ * As long as these guidelines are kept, we expect to continue enhancing
+ * this system and expect to make other tools available as they are
+ * completed.
+ *
+ * ANTLR 1.33
+ * Terence Parr
+ * Parr Research Corporation
+ * with Purdue University and AHPCRC, University of Minnesota
+ * 1989-2001
+ */
+
+#include <stdio.h>
+#include "pcctscfg.h"
+#include "set.h"
+#include "syn.h"
+#include "hash.h"
+#include "generic.h"
+#include "dlgdef.h"
+#include <ctype.h>
+
+#ifdef __USE_PROTOS
+static void complete_context_sets(RuleRefNode *, Predicate *);
+static void complete_context_trees(RuleRefNode *, Predicate *);
+#else
+static void complete_context_sets();
+static void complete_context_trees();
+#endif
+
+char *PRED_AND_LIST = "AND";
+char *PRED_OR_LIST = "OR";
+
+/*
+ * In C mode, return the largest constant integer found as the
+ * sole argument to LATEXT(i).
+ *
+ * In C++ mode, return the largest constant integer found as the
+ * sole argument to LT(i) given that the char before is nonalpha.
+ */
+
+int
+#ifdef __USE_PROTOS
+predicateLookaheadDepth(ActionNode *a)
+#else
+predicateLookaheadDepth(a)
+ActionNode *a;
+#endif
+{
+ int max_k=0;
+
+ if (a->predEntry != NULL) {
+ MR_pred_depth(a->predEntry->pred,&max_k);
+ goto PREDENTRY_EXIT;
+ }
+
+ if ( GenCC )
+ {
+ /* scan for LT(i) */
+ int k = 0;
+ char *p = a->action;
+ while ( p!=NULL )
+ {
+ p = strstr(p, "LT(");
+ if ( p!=NULL )
+ {
+ if ( p>=a->action && !isalpha(*(p-1)) )
+ {
+ k = atoi(p+strlen("LT("));
+ if ( k>max_k ) max_k=k;
+ }
+ p += strlen("LT(");
+ }
+ }
+ }
+ else {
+ /* scan for LATEXT(i) */
+ int k = 0;
+ char *p = a->action;
+ while ( p!=NULL )
+ {
+ p = strstr(p, "LATEXT(");
+ if ( p!=NULL )
+ {
+ p += strlen("LATEXT(");
+ k = atoi(p);
+ if ( k>max_k ) max_k=k;
+ }
+ }
+ }
+
+ if (max_k==0) {
+ max_k = 1; /* MR33 Badly designed if didn't set max_k when CLL_k = 1 */
+ if (CLL_k > 1) /* MR27 Don't warn if max(k,ck) == 1 */
+ {
+ if ( !a->frmwarned )
+ {
+ a->frmwarned = 1;
+ warnFL(eMsg1("predicate: %s missing, bad, or with i=0; assuming i=1",
+ GenCC?"LT(i)":"LATEXT(i)"),
+ FileStr[a->file], a->line);
+ }
+ }
+ }
+
+/* MR10 */ if ( max_k > CLL_k) {
+/* MR10 */ if ( !a->frmwarned )
+/* MR10 */ {
+/* MR10 */ a->frmwarned = 1;
+/* MR11 */ errFL(eMsgd2("predicate refers to lookahead token %d. Semantic lookahead is limited to max(k,ck)==%d",
+/* MR10 */ max_k,CLL_k),
+/* MR10 */ FileStr[a->file],a->line);
+/* MR10 */ if (max_k >= OutputLL_k) {
+/* MR10 */ if (!GenCC) {
+/* MR10 */ errFL(eMsgd(" the lookahead buffer size in C mode is %d token(s) (including the one just recognized)",
+/* MR10 */ OutputLL_k),
+/* MR10 */ FileStr[a->file],a->line);
+/* MR10 */ };
+/* MR10 */ };
+/* MR10 */ };
+/* MR10 */ max_k= CLL_k;
+/* MR10 */ };
+
+PREDENTRY_EXIT:
+ return max_k;
+}
+
+/* Find all predicates in a block of alternatives. DO NOT find predicates
+ * behind the block because that predicate could depend on things set in
+ * one of the nonoptional blocks
+ */
+
+Predicate *
+#ifdef __USE_PROTOS
+find_in_aSubBlk( Junction *alt )
+#else
+find_in_aSubBlk( alt )
+Junction *alt;
+#endif
+{
+ Predicate *a, *head=NULL, *tail=NULL, *root=NULL;
+ Junction *p = alt;
+
+ if (MRhoisting) {
+ return MR_find_in_aSubBlk(alt);
+ };
+ for (; p!=NULL; p=(Junction *)p->p2)
+ {
+ /* ignore empty alts */
+ if ( p->p1->ntype != nJunction ||
+ ((Junction *)p->p1)->jtype != EndBlk )
+ {
+ a = find_predicates(p->p1); /* get preds for this alt */
+ if ( a==NULL ) continue;
+
+ /* make an OR list of predicates */
+ if ( head==NULL )
+ {
+ root = new_pred();
+ root->expr = PRED_OR_LIST;
+ head = tail = a;
+ root->down = head;
+ }
+ else {
+ tail->right = a;
+ a->left = tail;
+ a->up = tail->up;
+ tail = a;
+ }
+ }
+ }
+
+ /* if just one pred, remove OR root */
+ if ( root!=NULL && root->down->right == NULL )
+ {
+ Predicate *d = root->down;
+ free( (char *) root);
+ return d;
+ }
+
+ return root;
+}
+
+Predicate *
+#ifdef __USE_PROTOS
+find_in_aOptBlk( Junction *alt )
+#else
+find_in_aOptBlk( alt )
+Junction *alt;
+#endif
+{
+ return find_in_aSubBlk( alt );
+}
+
+Predicate *
+#ifdef __USE_PROTOS
+find_in_aLoopBegin( Junction *alt )
+#else
+find_in_aLoopBegin( alt )
+Junction *alt;
+#endif
+{
+ return find_in_aSubBlk( (Junction *) alt->p1 ); /* get preds in alts */
+}
+
+Predicate *
+#ifdef __USE_PROTOS
+find_in_aPlusBlk( Junction *alt )
+#else
+find_in_aPlusBlk( alt )
+Junction *alt;
+#endif
+{
+ require(alt!=NULL&&alt->p2!=NULL, "invalid aPlusBlk");
+ return find_in_aSubBlk( alt );
+}
+
+/* Look for a predicate;
+ *
+ * Do not pass anything but Junction nodes; no Actions, Tokens, RuleRefs.
+ * This means that a "hoisting distance" of zero is the only distance
+ * allowable. Init actions are ignored.
+ *
+ * WARNING:
+ * Assumes no (..)? block after predicate for the moment.
+ * Does not check to see if pred is in production that can generate
+ * a sequence contained in the set of ambiguous tuples.
+ *
+ * Return the predicate found if any.
+ */
+
+
+Predicate *
+#ifdef __USE_PROTOS
+find_predicates( Node *alt )
+#else
+find_predicates( alt )
+Node *alt;
+#endif
+{
+#ifdef DBG_PRED
+ Junction *j;
+ RuleRefNode *r;
+ TokNode *t;
+#endif
+ Predicate *pred;
+
+ if ( alt==NULL ) return NULL;
+
+#ifdef DBG_PRED
+ switch ( alt->ntype )
+ {
+ case nJunction :
+ j = (Junction *) alt;
+ fprintf(stderr, "Junction(in %s)", j->rname);
+ switch ( j->jtype )
+ {
+ case aSubBlk :
+ fprintf(stderr,"aSubBlk\n");
+ break;
+ case aOptBlk :
+ fprintf(stderr,"aOptBlk\n");
+ break;
+ case aLoopBegin :
+ fprintf(stderr,"aLoopBeginBlk\n");
+ break;
+ case aLoopBlk :
+ fprintf(stderr,"aLoopBlk\n");
+ break;
+ case aPlusBlk :
+ fprintf(stderr,"aPlusBlk\n");
+ break;
+ case EndBlk :
+ fprintf(stderr,"EndBlk\n");
+ break;
+ case RuleBlk :
+ fprintf(stderr,"RuleBlk\n");
+ break;
+ case Generic :
+ fprintf(stderr,"Generic\n");
+ break;
+ case EndRule :
+ fprintf(stderr,"EndRule\n");
+ break;
+ }
+ break;
+ case nRuleRef :
+ r = (RuleRefNode *) alt;
+ fprintf(stderr, "RuleRef(in %s)\n", r->rname);
+ break;
+ case nToken :
+ t = (TokNode *) alt;
+ fprintf(stderr, "TokenNode(in %s)%s\n", t->rname, TokenString(t->token));
+ break;
+ case nAction :
+ fprintf(stderr, "Action\n");
+ break;
+ }
+#endif
+
+ switch ( alt->ntype )
+ {
+ case nJunction :
+ {
+ Predicate *a, *b;
+ Junction *p = (Junction *) alt;
+
+ /* lock nodes */
+ if ( p->jtype==aLoopBlk || p->jtype==RuleBlk ||
+ p->jtype==aPlusBlk || p->jtype==EndRule )
+ {
+ require(p->pred_lock!=NULL, "rJunc: lock array is NULL");
+ if ( p->pred_lock[1] )
+ {
+ return NULL;
+ }
+ p->pred_lock[1] = TRUE;
+ }
+
+ switch ( p->jtype )
+ {
+ case aSubBlk :
+ a = find_in_aSubBlk(p);
+ return a; /* nothing is visible past this guy */
+ case aOptBlk :
+ a = find_in_aOptBlk(p);
+ return a;
+ case aLoopBegin :
+ a = find_in_aLoopBegin(p);
+ return a;
+ case aLoopBlk :
+ a = find_in_aSubBlk(p);
+ p->pred_lock[1] = FALSE;
+ return a;
+ case aPlusBlk :
+ a = find_in_aPlusBlk(p);
+ p->pred_lock[1] = FALSE;
+ return a; /* nothing is visible past this guy */
+ case RuleBlk :
+ a = find_predicates(p->p1);
+ p->pred_lock[1] = FALSE;
+ return a;
+ case Generic :
+ a = find_predicates(p->p1);
+ b = find_predicates(p->p2);
+ if ( p->pred_lock!=NULL ) p->pred_lock[1] = FALSE;
+ if ( a==NULL ) return b;
+ if ( b==NULL ) return a;
+ /* otherwise OR the two preds together */
+ {
+ fatal_internal("hit unknown situation during predicate hoisting");
+ }
+ case EndBlk :
+ case EndRule : /* Find no predicates after a rule ref */
+ return NULL;
+ default:
+ fatal_internal("this cannot be printed\n");
+ break;
+ }
+ }
+ case nAction :
+ {
+ ActionNode *p = (ActionNode *) alt;
+ if ( p->noHoist) return NULL; /* MR12c */
+ if ( p->init_action ) return find_predicates(p->next);
+ if ( p->is_predicate )
+ {
+ Tree *t=NULL;
+#ifdef DBG_PRED
+ fprintf(stderr, "predicate: <<%s>>?\n", p->action);
+#endif
+ if ( p->guardpred!=NULL )
+ {
+ pred = predicate_dup(p->guardpred);
+ MR_guardPred_plainSet(p,pred); /* MR12c */
+ }
+ else
+ {
+ pred = new_pred();
+ pred->k = predicateLookaheadDepth(p);
+ pred->source = p;
+ pred->expr = p->action;
+ if ( HoistPredicateContext && pred->k > 1 )
+ {
+ /* MR30 No need to use first_item_is_guess_block_extra
+ since we know this is an action, not a (...)* or
+ (...)+ block.
+ */
+
+ if ( first_item_is_guess_block((Junction *)p->next) )
+ {
+ warnFL("cannot compute context of predicate in front of (..)? block",
+ FileStr[p->file], p->line);
+ }
+ else
+ {
+ ConstrainSearch = 0;
+/* MR11 */ if (p->ampersandPred != NULL) {
+/* MR11 */ TRAV(p,
+/* MR11 */ pred->k,
+/* MR11 */ &(pred->completionTree), t);
+/* MR11 */ } else {
+ TRAV(p->next,
+ pred->k,
+ &(pred->completionTree), t);
+ };
+ pred->tcontext = t;
+ MR_check_pred_too_long(pred,pred->completionTree);
+#ifdef DBG_PRED
+ fprintf(stderr, "LL(%d) context:", pred->k);
+ preorder(t);
+ fprintf(stderr, "\n");
+#endif
+ }
+ }
+ else if ( HoistPredicateContext && pred->k == 1 )
+ {
+ pred->scontext[1] = empty;
+ /* MR30 No need to use first_item_is_guess_block_extra
+ since we know this is an action.
+ */
+ if ( first_item_is_guess_block((Junction *)p->next) )
+ {
+ warnFL("cannot compute context of predicate in front of (..)? block",
+ FileStr[p->file], p->line);
+ }
+ else
+ {
+ REACH((Junction *)p->next,
+ 1,
+ &(pred->completionSet),
+ pred->scontext[1]);
+ MR_check_pred_too_long(pred,pred->completionSet);
+#ifdef DBG_PRED
+ fprintf(stderr, "LL(1) context:");
+ s_fprT(stderr, pred->scontext[1]);
+ fprintf(stderr, "\n");
+#endif
+ }
+ }
+ }
+ {
+ Predicate *d = find_predicates(p->next);
+ Predicate *root;
+
+/* Warning: Doesn't seem like the up pointers will all be set correctly;
+ * TJP: that's ok, we're not using them now.
+ */
+ if ( d!=NULL )
+ {
+ root = new_pred();
+ root->expr = PRED_AND_LIST;
+ root->down = pred;
+ pred->right = d;
+ pred->up = root;
+ d->left = pred;
+ d->up = pred->up;
+ return root;
+ }
+ }
+ return pred;
+ }
+ return NULL;
+ }
+ case nRuleRef :
+ {
+ Predicate *a;
+ RuleRefNode *p = (RuleRefNode *) alt;
+ Junction *r;
+ Junction *save_MR_RuleBlkWithHalt;
+
+ RuleEntry *q = (RuleEntry *) hash_get(Rname, p->text);
+ if ( q == NULL )
+ {
+ warnFL( eMsg1("rule %s not defined",p->text), FileStr[p->file], p->line );
+ return NULL;
+ }
+ r = RulePtr[q->rulenum];
+ if ( r->pred_lock[1] )
+ {
+ /* infinite left-recursion; ignore 'cause LL sup 1 (k) analysis
+ * must have seen it earlier.
+ */
+ return NULL;
+ }
+
+ /* MR10 There should only be one halt set at a time. */
+ /* MR10 Life would have been easier with a global variable */
+ /* MR10 (at least for this particular need) */
+ /* MR10 Unset the old one and set the new one, later undo. */
+
+ require(r->end->halt == FALSE,"should only have one halt at a time");
+
+/* MR10 */ require(MR_RuleBlkWithHalt == NULL ||
+/* MR10 */ (MR_RuleBlkWithHalt->jtype == RuleBlk && MR_RuleBlkWithHalt->end->halt == TRUE),
+/* MR10 */ "RuleBlkWithHalt->end not RuleBlk or does not have halt set");
+/* MR10 */ if (MR_RuleBlkWithHalt != NULL) {
+/* MR10 */ MR_RuleBlkWithHalt->end->halt=FALSE;
+/* MR10 */ };
+
+/*** fprintf(stderr,"\nSetting halt on junction #%d\n",r->end->seq); ***/
+
+ require(r->end->halt == FALSE,"rule->end->halt already set");
+
+ save_MR_RuleBlkWithHalt=MR_RuleBlkWithHalt;
+
+/* MR10 */ MR_pointerStackPush(&MR_RuleBlkWithHaltStack,MR_RuleBlkWithHalt);
+/* MR10 */ MR_pointerStackPush(&MR_PredRuleRefStack,p);
+
+ r->end->halt = TRUE;
+/* MR10 */ MR_RuleBlkWithHalt=r;
+
+ a = find_predicates((Node *)r);
+
+ require(r->end->halt == TRUE,"rule->end->halt not set");
+ r->end->halt = FALSE;
+
+/* MR10 */ MR_pointerStackPop(&MR_PredRuleRefStack);
+/* MR10 */ MR_RuleBlkWithHalt=(Junction *) MR_pointerStackPop(&MR_RuleBlkWithHaltStack);
+
+ require (MR_RuleBlkWithHalt==save_MR_RuleBlkWithHalt,
+ "RuleBlkWithHaltStack not consistent");
+
+/* MR10 */ require(MR_RuleBlkWithHalt == NULL ||
+/* MR10 */ (MR_RuleBlkWithHalt->jtype == RuleBlk && MR_RuleBlkWithHalt->end->halt == FALSE),
+/* MR10 */ "RuleBlkWithHalt->end not RuleBlk or has no halt set");
+/* MR10 */ if (MR_RuleBlkWithHalt != NULL) {
+/* MR10 */ MR_RuleBlkWithHalt->end->halt=TRUE;
+/* MR10 */ };
+
+/*** fprintf(stderr,"\nRestoring halt on junction #%d\n",r->end->seq); ***/
+
+ if ( a==NULL ) return NULL;
+
+ /* attempt to compute the "local" FOLLOW just like in normal lookahead
+ * computation if needed
+ */
+
+ complete_context_sets(p,a);
+ complete_context_trees(p,a);
+
+/* MR10 */ MR_cleanup_pred_trees(a);
+
+ return a;
+ }
+ case nToken :
+ break;
+ }
+
+ return NULL;
+}
+
+#ifdef __USE_PROTOS
+Predicate *MR_find_predicates_and_supp(Node *alt)
+#else
+Predicate *MR_find_predicates_and_supp(alt)
+ Node *alt;
+#endif
+{
+ Predicate *p;
+
+ p=find_predicates(alt);
+ p=MR_suppressK(alt,p);
+ return p;
+}
+
+Predicate *
+#ifdef __USE_PROTOS
+new_pred( void )
+#else
+new_pred( )
+#endif
+{
+ Predicate *p = (Predicate *) calloc(1,sizeof(Predicate)); /* MR10 */
+ require(p!=NULL, "new_pred: cannot alloc predicate");
+ p->scontext[0]=empty;
+ p->scontext[1]=empty;
+ p->completionTree=empty;
+ p->completionSet=empty;
+ p->plainSet=empty;
+ return p;
+}
+
+static void
+#ifdef __USE_PROTOS
+complete_context_sets( RuleRefNode *p, Predicate *a )
+#else
+complete_context_sets( p, a )
+RuleRefNode *p;
+Predicate *a;
+#endif
+{
+ set rk2, b;
+ int k2;
+
+#ifdef DBG_PRED
+ fprintf(stderr, "enter complete_context_sets\n");
+#endif
+ for (; a!=NULL; a=a->right)
+ {
+ if ( a->expr == PRED_AND_LIST || a->expr == PRED_OR_LIST )
+ {
+ complete_context_sets(p,a->down);
+ continue;
+ }
+ rk2 = b = empty;
+ while ( !set_nil(a->completionSet) )
+ {
+ k2 = set_int(a->completionSet);
+ set_rm(k2, a->completionSet);
+
+ REACH(p->next, k2, &rk2, b);
+ set_orin(&(a->scontext[1]), b);
+ set_free(b);
+ }
+
+ set_orin(&(a->completionSet), rk2);/* remember what we couldn't do */
+ set_free(rk2);
+#ifdef DBG_PRED
+ fprintf(stderr, "LL(1) context for %s(addr 0x%x) after ruleref:", a->expr, a);
+ s_fprT(stderr, a->scontext[1]);
+ fprintf(stderr, "\n");
+#endif
+/* complete_context_sets(p, a->down);*/
+ }
+#ifdef DBG_PRED
+ fprintf(stderr, "exit complete_context_sets\n");
+#endif
+}
+
+static void
+#ifdef __USE_PROTOS
+complete_context_trees( RuleRefNode *p, Predicate *a )
+#else
+complete_context_trees( p, a )
+RuleRefNode *p;
+Predicate *a;
+#endif
+{
+ set rk2;
+ int k2;
+ Tree *u;
+
+#ifdef DBG_PRED
+ fprintf(stderr, "enter complete_context_trees\n");
+#endif
+ for (; a!=NULL; a=a->right)
+ {
+ if ( a->expr == PRED_AND_LIST || a->expr == PRED_OR_LIST )
+ {
+ complete_context_trees(p, a->down);
+ continue;
+ }
+ rk2 = empty;
+
+ /* any k left to do? if so, link onto tree */
+ while ( !set_nil(a->completionTree) )
+ {
+ k2 = set_int(a->completionTree);
+ set_rm(k2, a->completionTree);
+ u = NULL;
+
+ TRAV(p->next, k2, &rk2, u);
+
+ /* any subtrees missing k2 tokens, add u onto end */
+ a->tcontext = tlink(a->tcontext, u, k2);
+ Tfree(u); /* MR10 */
+ }
+ set_orin(&(a->completionTree), rk2);/* remember what we couldn't do */
+ set_free(rk2);
+#ifdef DBG_PRED
+ fprintf(stderr, "LL(i<%d) context after ruleref:", LL_k);
+ preorder(a->tcontext);
+ fprintf(stderr, "\n");
+#endif
+/* complete_context_trees(p, a->down);*/
+ }
+#ifdef DBG_PRED
+ fprintf(stderr, "exit complete_context_trees\n");
+#endif
+}
+
+/* Walk a list of predicates and return the set of all tokens in scontext[1]'s */
+set
+#ifdef __USE_PROTOS
+covered_set( Predicate *p )
+#else
+covered_set( p )
+Predicate *p;
+#endif
+{
+ set a;
+
+ a = empty;
+ for (; p!=NULL; p=p->right)
+ {
+ if ( p->expr == PRED_AND_LIST || p->expr == PRED_OR_LIST )
+ {
+ set_orin(&a, covered_set(p->down));
+ continue;
+ }
+ set_orin(&a, p->scontext[1]);
+ set_orin(&a, covered_set(p->down));
+ }
+ return a;
+}
+
+/* MR10 predicate_free()
+ MR10 Don't free the leaf nodes since they are part of the action node
+*/
+
+#ifdef __USE_PROTOS
+void predicate_free(Predicate *p)
+#else
+void predicate_free(p)
+ Predicate *p;
+#endif
+{
+ if (p == NULL) return;
+ predicate_free(p->right);
+ predicate_free(p->down);
+ if (p->cloned ||
+ p->source == NULL ||
+ p->source->guardpred == NULL ||
+ p->expr == PRED_AND_LIST ||
+ p->expr == PRED_OR_LIST) {
+ set_free(p->scontext[1]);
+ set_free(p->completionSet);
+ set_free(p->completionTree);
+ set_free(p->plainSet);
+ Tfree(p->tcontext);
+ free( (char *) p);
+ } else {
+ p->right=NULL;
+ p->down=NULL; /* MR13 *** debug */
+ };
+}
+
+/* MR10 predicate_dup() */
+
+#ifdef __USE_PROTOS
+Predicate * predicate_dup_xxx(Predicate *p,int contextToo)
+#else
+Predicate * predicate_dup_xxx(p,contextToo)
+ Predicate *p;
+ int contextToo;
+#endif
+{
+ Predicate *q;
+
+ if (p == NULL) return NULL;
+ q=new_pred();
+ q->down=predicate_dup(p->down);
+ q->right=predicate_dup(p->right);
+
+ /*
+ don't replicate expr - it is read-only
+ and address comparison is used to look
+ for identical predicates.
+ */
+
+ q->expr=p->expr;
+ q->k=p->k;
+ q->source=p->source;
+ q->cloned=1;
+ q->ampersandStyle=p->ampersandStyle;
+ q->inverted=p->inverted;
+ q->predEntry=p->predEntry;
+ q->plainSet=set_dup(p->plainSet);
+
+ if (contextToo) {
+ q->tcontext=tdup(p->tcontext);
+ q->scontext[0]=set_dup(p->scontext[0]);
+ q->scontext[1]=set_dup(p->scontext[1]);
+ q->completionTree=set_dup(p->completionTree);
+ q->completionSet=set_dup(p->completionSet);
+ };
+
+ /* don't need to dup "redundant" */
+
+ return q;
+
+}
+
+#ifdef __USE_PROTOS
+Predicate * predicate_dup_without_context(Predicate *p)
+#else
+Predicate * predicate_dup_without_context(p)
+ Predicate *p;
+#endif
+{
+ return predicate_dup_xxx(p,0);
+}
+
+#ifdef __USE_PROTOS
+Predicate * predicate_dup(Predicate *p)
+#else
+Predicate * predicate_dup(p)
+ Predicate *p;
+#endif
+{
+ return predicate_dup_xxx(p,1);
+}
+
diff --git a/Source/Pccts/antlr/proto.h b/Source/Pccts/antlr/proto.h
new file mode 100644
index 0000000..53035e7
--- /dev/null
+++ b/Source/Pccts/antlr/proto.h
@@ -0,0 +1,852 @@
+/*
+ * proto.h -- function prototypes
+ *
+ * SOFTWARE RIGHTS
+ *
+ * We reserve no LEGAL rights to the Purdue Compiler Construction Tool
+ * Set (PCCTS) -- PCCTS is in the public domain. An individual or
+ * company may do whatever they wish with source code distributed with
+ * PCCTS or the code generated by PCCTS, including the incorporation of
+ * PCCTS, or its output, into commerical software.
+ *
+ * We encourage users to develop software with PCCTS. However, we do ask
+ * that credit is given to us for developing PCCTS. By "credit",
+ * we mean that if you incorporate our source code into one of your
+ * programs (commercial product, research project, or otherwise) that you
+ * acknowledge this fact somewhere in the documentation, research report,
+ * etc... If you like PCCTS and have developed a nice tool with the
+ * output, please mention that you developed it using PCCTS. In
+ * addition, we ask that this header remain intact in our source code.
+ * As long as these guidelines are kept, we expect to continue enhancing
+ * this system and expect to make other tools available as they are
+ * completed.
+ *
+ * ANTLR 1.33
+ * Terence Parr
+ * Parr Research Corporation
+ * with Purdue University and AHPCRC, University of Minnesota
+ * 1989-2001
+ */
+
+ /* V a r i a b l e s */
+
+extern int tp;
+extern Junction *SynDiag;
+extern char Version[];
+extern char VersionDef[];
+#ifdef __cplusplus
+extern void (*fpPrint[])(...);
+#else
+extern void (*fpPrint[])();
+#endif
+#ifdef __cplusplus
+extern struct _set (*fpReach[])(...);
+#else
+extern struct _set (*fpReach[])();
+#endif
+#ifdef __cplusplus
+extern struct _tree *(*fpTraverse[])(...);
+#else
+extern struct _tree *(*fpTraverse[])();
+#endif
+#ifdef __cplusplus
+extern void (**fpTrans)(...);
+#else
+extern void (**fpTrans)();
+#endif
+#ifdef __cplusplus
+extern void (**fpJTrans)(...);
+#else
+extern void (**fpJTrans)();
+#endif
+#ifdef __cplusplus
+extern void (*C_Trans[NumNodeTypes+1])(...);
+#else
+extern void (*C_Trans[])();
+#endif
+#ifdef __cplusplus
+extern void (*C_JTrans[NumJuncTypes+1])(...);
+#else
+extern void (*C_JTrans[])();
+#endif
+extern int BlkLevel;
+extern int CurFile;
+extern char *CurPredName;
+extern char *CurRule;
+extern int CurRuleDebug; /* MR13 */
+extern Junction *CurRuleBlk;
+extern RuleEntry *CurRuleNode;
+extern ListNode *CurElementLabels;
+extern ListNode *CurAstLabelsInActions; /* MR27 */
+extern ListNode *ContextGuardPredicateList; /* MR13 */
+extern ListNode *CurActionLabels;
+extern int numericActionLabel; /* MR10 << ... $1 ... >> or << ... $1 ... >>? */
+extern ListNode *NumericPredLabels; /* MR10 << ... $1 ... >>? ONLY */
+extern char *FileStr[];
+extern int NumFiles;
+extern int EpToken;
+extern int WildCardToken;
+extern Entry **Tname,
+ **Texpr,
+ **Rname,
+ **Fcache,
+ **Tcache,
+ **Elabel,
+ **Sname,
+ **Pname; /* MR11 */
+extern ListNode *ExprOrder;
+extern ListNode **Cycles;
+extern int TokenNum;
+extern int LastTokenCounted;
+extern ListNode *BeforeActions, *AfterActions, *LexActions;
+
+/* MR1 */
+/* MR1 11-Apr-97 Provide mechanism for inserting code into DLG class */
+/* MR1 via #lexmember <<....>> & #lexprefix <<...>> */
+/* MR1 */
+
+extern ListNode *LexMemberActions; /* MR1 */
+extern ListNode *LexPrefixActions; /* MR1 */
+
+extern set *fset; /* for constrained search */ /* MR11 */
+extern int maxk; /* for constrained search */ /* MR11 */
+extern int Save_argc; /* MR10 */
+extern char **Save_argv; /* MR10 */
+extern ListNode *eclasses, *tclasses;
+extern char *HdrAction;
+extern char *FirstAction; /* MR11 */
+extern FILE *ErrFile;
+extern char *RemapFileName;
+extern char *ErrFileName;
+extern char *DlgFileName;
+extern char *DefFileName;
+extern char *ModeFileName;
+extern char *StdMsgName;
+extern int NumRules;
+extern Junction **RulePtr;
+extern int LL_k;
+extern int CLL_k;
+extern char *decodeJType[];
+extern int PrintOut;
+extern int PrintAnnotate;
+extern int CodeGen;
+extern int LexGen;
+extern int esetnum;
+extern int setnum;
+extern int wordnum;
+extern int GenAST;
+extern int GenANSI;
+extern int **FoStack;
+extern int **FoTOS;
+extern int GenExprSetsOpt;
+extern FILE *DefFile;
+extern int CannotContinue;
+extern int GenCR;
+extern int GenLineInfo;
+extern int GenLineInfoMS;
+extern int action_file, action_line;
+extern int TraceGen;
+extern int CurAmbigAlt1, CurAmbigAlt2, CurAmbigline, CurAmbigfile;
+extern char *CurAmbigbtype;
+extern int elevel;
+extern int GenEClasseForRules;
+extern FILE *input, *output;
+extern char **TokenStr, **ExprStr;
+extern int CurrentLexClass, NumLexClasses;
+extern LClass lclass[];
+extern char LexStartSymbol[];
+extern char *CurRetDef;
+extern char *CurParmDef;
+extern int OutputLL_k;
+extern int TreeResourceLimit;
+extern int DemandLookahead;
+extern char *RulePrefix;
+extern int GenStdPccts;
+extern char *stdpccts;
+extern int ParseWithPredicates;
+extern int ConstrainSearch;
+extern int PURIFY; /* MR23 */
+
+extern set MR_CompromisedRules; /* MR14 */
+extern int MR_AmbSourceSearch; /* MR11 */
+extern int MR_SuppressSearch; /* MR13 */
+extern int MR_AmbSourceSearchGroup; /* MR11 */
+extern int MR_AmbSourceSearchChoice; /* MR11 */
+extern int MR_AmbSourceSearchLimit; /* MR11 */
+extern int MR_usingPredNames; /* MR11 */
+extern int MR_ErrorSetComputationActive; /* MR14 */
+extern char *MR_AmbAidRule; /* MR11 */
+extern int MR_AmbAidLine; /* MR11 */
+extern int MR_AmbAidMultiple; /* MR11 */
+extern int MR_AmbAidDepth; /* MR11 */
+extern int MR_skipped_e3_report; /* MR11 */
+extern int MR_matched_AmbAidRule; /* MR11 */
+extern int MR_Inhibit_Tokens_h_Gen; /* MR13 */
+extern int NewAST; /* MR13 */
+extern int tmakeInParser; /* MR23 */
+extern int AlphaBetaTrace; /* MR14 */
+extern int MR_BlkErr; /* MR21 */
+extern int MR_AlphaBetaWarning; /* MR14 */
+extern int MR_AlphaBetaMessageCount; /* MR14 */
+extern int MR_MaintainBackTrace; /* MR14 */
+extern int MR_BadExprSets; /* MR13 */
+extern int FoundGuessBlk;
+extern int FoundException;
+extern int FoundAtOperator; /* MR6 */
+extern int FoundExceptionGroup; /* MR6 */
+extern int WarningLevel;
+extern int UseStdout; /* MR6 */
+extern int TabWidth; /* MR6 */
+extern int pLevel;
+extern int pAlt1;
+extern int pAlt2;
+extern int AImode;
+extern int HoistPredicateContext;
+extern int MRhoisting; /* MR9 */
+extern int MRhoistingk; /* MR13 */
+extern int MR_debugGenRule; /* MR11 */
+extern int GenCC;
+extern char *ParserName;
+extern char *StandardSymbols[];
+extern char *ASTSymbols[];
+extern set reserved_positions;
+extern set all_tokens;
+extern set imag_tokens;
+extern set tokclasses;
+extern ListNode *ForcedTokens;
+extern int *TokenInd;
+extern FILE *Parser_h, *Parser_c;
+extern char CurrentClassName[];
+extern int no_classes_found;
+extern char Parser_h_Name[];
+extern char Parser_c_Name[];
+extern char MRinfoFile_Name[]; /* MR10 */
+extern FILE *MRinfoFile; /* MR10 */
+extern int MRinfo; /* MR10 */
+extern int MRinfoSeq; /* MR10 */
+extern int InfoP; /* MR10 */
+extern int InfoT; /* MR10 */
+extern int InfoF; /* MR10 */
+extern int InfoM; /* MR10 */
+extern int InfoO; /* MR12 */
+extern int PotentialSuppression; /* MR10 */
+extern int PotentialDummy; /* MR10 */
+extern int TnodesInUse; /* MR10 */
+extern int TnodesPeak; /* MR10 */
+extern int TnodesReportThreshold; /* MR11 */
+extern int TnodesAllocated; /* MR10 */
+extern char *ClassDeclStuff; /* MR10 */
+extern char *BaseClassName; /* MR22 */
+extern ListNode *class_before_actions, *class_after_actions;
+extern char *UserTokenDefsFile;
+extern int UserDefdTokens;
+extern ListNode *MetaTokenNodes;
+extern char *OutputDirectory;
+extern int DontCopyTokens;
+extern int LTinTokenAction; /* MR23 */
+extern set AST_nodes_refd_in_actions;
+extern ListNode *CurExGroups;
+extern int CurBlockID;
+extern int CurAltNum;
+extern Junction *CurAltStart;
+extern Junction *OuterAltStart; /* chain exception groups MR7 */
+extern ExceptionGroup *DefaultExGroup;
+extern int NumSignals;
+extern int ContextGuardTRAV;
+extern Junction *MR_RuleBlkWithHalt; /* MR10 */
+extern PointerStack MR_BackTraceStack; /* MR10 */
+extern PointerStack MR_PredRuleRefStack; /* MR10 */
+extern PointerStack MR_RuleBlkWithHaltStack; /* MR10 */
+
+/* */
+/* MR1 10-Apr-97 MR1 Previously unable to put right shift operator */
+/* MR1 in DLG action */
+/* */
+extern int tokenActionActive; /* MR1 */
+
+extern char *PRED_OR_LIST; /* MR10 */
+extern char *PRED_AND_LIST; /* MR10 */
+
+#ifdef __VMS
+#define STRICMP strcasecmp /* MR21 */
+#else
+#define STRICMP stricmp /* MR21 */
+#endif
+
+/* MR26 */
+#ifdef PCCTS_USE_STDARG
+extern Tree *tmake(Tree *root, ...);
+#else
+extern Tree *tmake();
+#endif
+
+#ifdef __USE_PROTOS
+extern int STRICMP(const char*, const char*);
+extern void istackreset(void);
+extern int istacksize(void);
+extern void pushint(int);
+extern int popint( void );
+extern int istackempty( void );
+extern int topint( void );
+extern void NewSetWd( void );
+extern void DumpSetWd( void );
+extern void DumpSetWdForC( void );
+extern void DumpSetWdForCC( void );
+extern void NewSet( void );
+extern void FillSet( set );
+extern void ComputeErrorSets( void );
+extern void ComputeTokSets( void );
+extern void SubstErrorClass( set * );
+extern int DefErrSet( set *, int, char * );
+extern int DefErrSetForC( set *, int, char * );
+extern int DefErrSetForCC( set *, int, char * );
+extern int DefErrSet1(int, set *, int, char *); /* MR21 */
+extern int DefErrSetForC1(int, set *, int, char *, const char* ); /* MR21 */
+extern int DefErrSetForCC1(int, set *, int, char *, const char* ); /* MR21 */
+extern int DefErrSetWithSuffix(int, set *, int, char *, const char *); /* MR21 */
+extern void GenErrHdr( void );
+extern void dumpExpr( FILE *, char * );
+extern void addParm( Node *, char * );
+extern Graph buildAction( char *, int, int, int );
+extern Graph buildToken( char * );
+extern Graph buildWildCard( char * );
+extern Graph buildRuleRef( char * );
+extern Graph Or( Graph, Graph );
+extern Graph Cat( Graph, Graph );
+extern Graph makeOpt( Graph, int, char *);
+extern Graph makeBlk( Graph, int, char *);
+extern Graph makeLoop( Graph, int, char *);
+extern Graph makePlus( Graph, int, char *);
+extern Graph emptyAlt( void );
+extern Graph emptyAlt3( void );
+extern TokNode * newTokNode( void );
+extern RuleRefNode * newRNode( void );
+extern Junction * newJunction( void );
+extern ActionNode * newActionNode( void );
+extern char * makelocks( void );
+extern void preorder( Tree * );
+extern Tree * tnode( int );
+extern void _Tfree( Tree * );
+extern Tree * tdup( Tree * );
+extern int is_single_tuple( Tree * );
+extern Tree * tappend( Tree *, Tree * );
+extern void Tfree( Tree * );
+extern Tree * tlink( Tree *, Tree *, int );
+extern Tree * tshrink( Tree * );
+extern Tree * tflatten( Tree * );
+extern Tree * tJunc( Junction *, int, set * );
+extern Tree * tRuleRef( RuleRefNode *, int, set * );
+extern Tree * tToken( TokNode *, int, set * );
+extern Tree * tAction( ActionNode *, int, set * );
+extern int tmember( Tree *, Tree * );
+extern int tmember_constrained( Tree *, Tree * );
+extern Tree * tleft_factor( Tree * );
+extern Tree * trm_perm( Tree *, Tree * );
+extern void tcvt( set *, Tree * );
+extern Tree * permute( int, int );
+extern Tree * VerifyAmbig( Junction *, Junction *, unsigned **, set *, Tree **, Tree **, int * );
+extern set rJunc( Junction *, int, set * );
+extern set rRuleRef( RuleRefNode *, int, set * );
+extern set rToken( TokNode *, int, set * );
+extern set rAction( ActionNode *, int, set * );
+extern void HandleAmbiguity( Junction *, Junction *, Junction *, int );
+extern set First( Junction *, int, int, int * );
+extern void freeBlkFsets( Junction * );
+extern void genAction( ActionNode * );
+extern void genRuleRef( RuleRefNode * );
+extern void genToken( TokNode * );
+extern void genOptBlk( Junction * );
+extern void genLoopBlk( Junction *, Junction *, Junction *, int );
+extern void genLoopBegin( Junction * );
+extern void genPlusBlk( Junction * );
+extern void genSubBlk( Junction * );
+extern void genRule( Junction * );
+extern void genJunction( Junction * );
+extern void genEndBlk( Junction * );
+extern void genEndRule( Junction * );
+extern void genHdr( int );
+extern void genHdr1( int );
+extern void dumpAction( char *, FILE *, int, int, int, int );
+extern void dumpActionPlus(ActionNode*, char *, FILE *, int, int, int, int ); /* MR21 */
+extern Entry ** newHashTable( void );
+extern Entry * hash_add( Entry **, char *, Entry * );
+extern Entry * hash_get( Entry **, char * );
+extern void hashStat( Entry ** );
+extern char * mystrdup( char * );
+extern void genLexDescr( void );
+extern void dumpLexClasses( FILE * );
+extern void genDefFile( void );
+extern void DumpListOfParmNames( char *, FILE *, int ); /* MR5 janm 26-May-97 */
+extern int DumpNextNameInDef( char **, FILE * );
+extern void DumpOldStyleParms( char *, FILE * );
+extern void DumpType( char *, FILE * );
+extern int strmember( char *, char * );
+/* extern int HasComma( char * ); MR23 Replaced by hasMultipleOperands() */
+extern void DumpRetValStruct( FILE *, char *, int );
+extern char * StripQuotes( char * );
+extern int main( int, char *[] );
+extern void readDescr( void );
+extern FILE * NextFile( void );
+extern char * outnameX( char *, char *);
+extern char * outname( char * );
+extern void fatalFL( char *, char *, int );
+extern void fatal_intern( char *, char *, int );
+extern void cleanUp( void );
+extern char * eMsg3( char *, char *, char *, char * );
+extern char * eMsgd( char *, int );
+extern char * eMsgd2( char *, int, int );
+extern void s_fprT( FILE *, set );
+extern char * TerminalString( int );
+extern void lexclass( char * );
+extern void lexmode( int );
+extern int LexClassIndex( char * );
+extern int hasAction( char * );
+extern void setHasAction( char *, char * );
+extern int addTname( char * );
+extern int addTexpr( char * );
+extern int Tnum( char * );
+extern void Tklink( char *, char * );
+extern Entry * newEntry( char *, int );
+extern void list_add( ListNode **, void * );
+extern void list_free( ListNode **, int freeData ); /* MR10 */
+extern void list_apply( ListNode *, void (*)(void *) );
+extern int list_search_cstring (ListNode *, char *); /* MR27 */
+extern char * Fkey( char *, int, int );
+extern void FoPush( char *, int );
+extern void FoPop( int );
+extern void RegisterCycle( char *, int );
+extern void ResolveFoCycles( int );
+extern void pJunc( Junction * );
+extern void pRuleRef( RuleRefNode * );
+extern void pToken( TokNode * );
+extern void pAction( ActionNode * );
+extern void FoLink( Node * );
+extern void addFoLink( Node *, char *, Junction * );
+extern void GenCrossRef( Junction * );
+extern void defErr( char *, long, long, long, long, long, long );
+extern void genStdPCCTSIncludeFile(FILE *,char *); /* MR10 */
+extern char * pcctsBaseName(char *); /* MR32 */
+extern Predicate *find_predicates(Node *); /* MR10 */
+extern Predicate *MR_find_predicates_and_supp(Node *); /* MR13 */
+extern int predicateLookaheadDepth(ActionNode *); /* MR10 */
+extern void predicate_free(Predicate *); /* MR10 */
+extern Predicate * predicate_dup(Predicate *); /* MR10 */
+extern Predicate * predicate_dup_without_context(Predicate *); /* MR11 */
+extern void GenRulePrototypes(FILE *, Junction *);
+extern Junction *first_item_is_guess_block(Junction *);
+extern Junction *first_item_is_guess_block_extra(Junction * q); /* MR30 */
+extern Junction *analysis_point(Junction *);
+extern Tree *make_tree_from_sets(set *, set *);
+extern Tree *tdup_chain(Tree *);
+extern Tree *tdif(Tree *, Predicate *, set *, set *);
+extern set covered_set(Predicate *);
+extern void AmbiguityDialog(Junction *, int, Junction *, Junction *, int *, int *);
+extern void dumpAmbigMsg(set *, FILE *, int);
+extern void GenRuleFuncRedefs(FILE *, Junction *);
+extern void GenPredefinedSymbolRedefs(FILE *);
+extern void GenASTSymbolRedefs(FILE *);
+extern void GenRemapFile(void);
+extern void GenSetRedefs(FILE *);
+extern ForcedToken *newForcedToken(char *, int);
+extern void RemapForcedTokens(void);
+extern char *TokenOrExpr(int);
+extern void setUpperRange(TokNode *, char *);
+extern void GenParser_c_Hdr(void);
+extern void GenParser_h_Hdr(void);
+extern void GenRuleMemberDeclarationsForCC(FILE *, Junction *);
+extern int addForcedTname( char *, int );
+extern char *OutMetaName(char *);
+extern void OutFirstSetSymbol(Junction *q, char *); /* MR21 */
+extern void warnNoFL(char *err);
+extern void warnFL(char *err,char *f,int l);
+extern void warn(char *err);
+extern void warnNoCR( char *err );
+extern void errNoFL(char *err);
+extern void errFL(char *err,char *f,int l);
+extern void err(char *err);
+extern void errNoCR( char *err );
+extern void genPredTree( Predicate *p, Node *j, int ,int);
+extern UserAction *newUserAction(char *);
+extern char *gate_symbol(char *name);
+extern char *makeAltID(int blockid, int altnum);
+extern void DumpRemainingTokSets(void);
+extern void DumpANSIFunctionArgDef(FILE *f, Junction *q, int bInit); /* MR23 */
+extern void DumpFormals(FILE *, char *, int bInit); /* MR23 */
+extern char* hideDefaultArgs(const char* pdecl); /* MR22 VHS */
+extern Predicate *computePredFromContextGuard(Graph,int *msgDone); /* MR21 */
+extern void recomputeContextGuard(Predicate *); /* MR13 */
+extern Predicate *new_pred(void);
+extern void chkGTFlag(void);
+extern void leAdd(LabelEntry *); /* MR7 */
+extern void leFixup(void); /* MR7 */
+extern void egAdd(ExceptionGroup *); /* MR7 */
+extern void egFixup(void); /* MR7 */
+extern void altAdd(Junction *); /* MR7 */
+extern void altFixup(void); /* MR7 */
+extern Predicate * MR_find_in_aSubBlk(Junction *alt); /* MR10 */
+extern Predicate * MR_predFlatten(Predicate *p); /* MR10 */
+extern Predicate * MR_predSimplifyALL(Predicate *p); /* MR10 */
+extern Predicate * MR_predSimplifyALLX(Predicate *p,int skipPass3); /* MR10 */
+extern int MR_allPredLeaves(Predicate *p); /* MR10 */
+extern void MR_cleanup_pred_trees(Predicate *p); /* MR10 */
+extern int MR_predicate_context_completed(Predicate *p); /* MR10 */
+extern void MR_check_pred_too_long(Predicate *p,set completion); /* MR10 */
+extern Tree * MR_remove_epsilon_from_tree(Tree *t); /* MR10 */
+extern Tree * MR_computeTreeAND(Tree *l,Tree *r); /* MR10 */
+extern int MR_tree_equ(Tree *big, Tree *small); /* MR10 */
+extern set MR_First(int ck,Junction *j,set *incomplete); /* MR10 */
+extern set MR_compute_pred_set(Predicate *p); /* MR10 */
+extern Tree * MR_compute_pred_tree_context(Predicate *p); /* MR10 */
+extern int MR_pointerStackPush(PointerStack *,void *); /* MR10 */
+extern void * MR_pointerStackPop(PointerStack *); /* MR10 */
+extern void * MR_pointerStackTop(PointerStack *); /* MR10 */
+extern void MR_pointerStackReset(PointerStack *); /* MR10 */
+extern void MR_backTraceReport(void); /* MR10 */
+extern void MR_alphaBetaTraceReport(void); /* MR14 */
+extern void MR_dumpRuleSet(set); /* MR14 */
+extern void MR_predContextPresent(Predicate *p,int *,int *); /* MR10 */
+extern void MR_dumpPred(Predicate *p,int withContext); /* MR10 */
+extern void MR_dumpPred1(int,Predicate *p,int withContext); /* MR10 */
+extern void MR_xxxIndent(FILE *f,int depth); /* MR11 */
+extern void MR_outputIndent(int depth); /* MR11 */
+extern void MR_stderrIndent(int depth); /* MR11 */
+extern Junction * MR_ruleReferenced(RuleRefNode *rrn); /* MR10 */
+extern Junction * MR_nameToRuleBlk(char *); /* MR10 */
+extern void MR_releaseResourcesUsedInRule(Node *); /* MR10 */
+extern void MR_dumpTreeX(int depth,Tree *t,int across); /* MR10 */
+extern void MR_dumpTreeF(FILE *f,int depth,Tree *t,int across); /* MR10 */
+extern void DumpFcache(void); /* MR10 */
+extern void MR_dumpTokenSet(FILE *f,int depth,set s); /* MR10 */
+extern void MR_traceAmbSource(set *,Junction *,Junction *); /* MR11 */
+extern void MR_traceAmbSourceK(Tree *,Junction *a1,Junction *a2); /* MR11 */
+extern void MR_traceAmbSourceKclient(void); /* MR20 */
+extern Node *MR_advance(Node *); /* MR11 */
+extern int MR_offsetFromRule(Node *); /* MR11 */
+extern char *MR_ruleNamePlusOffset(Node *); /* MR11 */
+extern int MR_max_height_of_tree(Tree *); /* MR11 */
+extern int MR_all_leaves_same_height(Tree *,int); /* MR11 */
+extern void MR_projectTreeOntoSet(Tree *t,int k,set *); /* MR11 */
+extern Tree *MR_make_tree_from_set(set); /* MR11 */
+extern Predicate *MR_removeRedundantPredPass3(Predicate *); /* MR11 */
+extern void MR_pred_depth(Predicate *,int *); /* MR11 */
+extern int MR_comparePredicates(Predicate *,Predicate *); /* MR11 */
+extern Predicate * MR_unfold(Predicate *); /* MR11 */
+extern void MR_simplifyInverted(Predicate *,int); /* MR11 */
+extern int MR_secondPredicateUnreachable /* MR11 */
+ (Predicate *first,Predicate *second); /* MR11 */
+extern void MR_clearPredEntry(Predicate *); /* MR11 */
+extern void MR_orphanRules(FILE *); /* MR12 */
+extern void MR_merge_contexts(Tree *); /* MR12 */
+extern int ci_strequ(char *,char *); /* MR12 */
+extern void MR_guardPred_plainSet(ActionNode *anode,Predicate *); /* MR12c */
+extern void MR_suppressSearchReport(void); /* MR12c */
+extern Predicate * MR_suppressK(Node *,Predicate *); /* MR13 */
+extern void MR_backTraceDumpItem(FILE *,int skip,Node *n); /* MR13 */
+extern void MR_backTraceDumpItemReset(void); /* MR13 */
+extern Junction * MR_junctionWithoutP2(Junction *); /* MR13 */
+extern void MR_setConstrainPointer(set *); /* MR18 */
+extern void BlockPreambleOption(Junction *q, char * pSymbol); /* MR23 */
+extern char* getInitializer(char *); /* MR23 */
+extern char *endFormal(char *pStart, /* MR23 */
+ char **ppDataType, /* MR23 */
+ char **ppSymbol, /* MR23 */
+ char **ppEqualSign, /* MR23 */
+ char **ppValue, /* MR23 */
+ char **ppSeparator, /* MR23 */
+ int *pNext); /* MR23 */
+extern char *strBetween(char *pStart, /* MR23 */
+ char *pNext, /* MR23 */
+ char *pStop); /* MR23 */
+extern int hasMultipleOperands(char *); /* MR23 */
+extern void DumpInitializers(FILE*, RuleEntry*, char*); /* MR23 */
+extern int isTermEntryTokClass(TermEntry *); /* MR23 */
+extern int isEmptyAlt(Node *, Node *); /* MR23 */
+#else
+extern int STRICMP();
+extern void istackreset();
+extern int istacksize();
+extern void pushint();
+extern int popint();
+extern int istackempty();
+extern int topint();
+extern void NewSetWd();
+extern void DumpSetWd();
+extern void DumpSetWdForC();
+extern void DumpSetWdForCC();
+extern void NewSet();
+extern void FillSet();
+extern void ComputeErrorSets();
+extern void ComputeTokSets();
+extern void SubstErrorClass();
+extern int DefErrSet();
+extern int DefErrSetForC();
+extern int DefErrSetForCC();
+extern int DefErrSet1();
+extern int DefErrSetForC1();
+extern int DefErrSetForCC1();
+extern int DefErrSetWithSuffix(); /* MR21 */
+extern void GenErrHdr();
+extern void dumpExpr();
+extern void addParm();
+extern Graph buildAction();
+extern Graph buildToken();
+extern Graph buildWildCard();
+extern Graph buildRuleRef();
+extern Graph Or();
+extern Graph Cat();
+extern Graph makeOpt();
+extern Graph makeBlk();
+extern Graph makeLoop();
+extern Graph makePlus();
+extern Graph emptyAlt();
+extern Graph emptyAlt3();
+extern TokNode * newTokNode();
+extern RuleRefNode * newRNode();
+extern Junction * newJunction();
+extern ActionNode * newActionNode();
+extern char * makelocks();
+extern void preorder();
+extern Tree * tnode();
+extern void _Tfree();
+extern Tree * tdup();
+extern int is_single_tuple();
+extern Tree * tappend();
+extern void Tfree();
+extern Tree * tlink();
+extern Tree * tshrink();
+extern Tree * tflatten();
+extern Tree * tJunc();
+extern Tree * tRuleRef();
+extern Tree * tToken();
+extern Tree * tAction();
+extern int tmember();
+extern int tmember_constrained();
+extern Tree * tleft_factor();
+extern Tree * trm_perm();
+extern void tcvt();
+extern Tree * permute();
+extern Tree * VerifyAmbig();
+extern set rJunc();
+extern set rRuleRef();
+extern set rToken();
+extern set rAction();
+extern void HandleAmbiguity();
+extern set First();
+extern void freeBlkFsets();
+extern void genAction();
+extern void genRuleRef();
+extern void genToken();
+extern void genOptBlk();
+extern void genLoopBlk();
+extern void genLoopBegin();
+extern void genPlusBlk();
+extern void genSubBlk();
+extern void genRule();
+extern void genJunction();
+extern void genEndBlk();
+extern void genEndRule();
+extern void genHdr();
+extern void genHdr1();
+extern void dumpAction();
+extern void dumpActionPlus(); /* MR21 */
+extern Entry ** newHashTable();
+extern Entry * hash_add();
+extern Entry * hash_get();
+extern void hashStat();
+extern char * mystrdup();
+extern void genLexDescr();
+extern void dumpLexClasses();
+extern void genDefFile();
+extern void DumpListOfParmNames(); /* MR5 janm 26-May-97 */
+extern int DumpNextNameInDef();
+extern void DumpOldStyleParms();
+extern void DumpType();
+extern int strmember();
+/* extern int HasComma(); MR23 Replaced by hasMultipleOperands() */
+extern void DumpRetValStruct();
+extern char * StripQuotes();
+extern int main();
+extern void readDescr();
+extern FILE * NextFile();
+extern char * outnameX();
+extern char * outname();
+extern void fatalFL();
+extern void fatal_intern();
+extern void cleanUp();
+extern char * eMsg3();
+extern char * eMsgd();
+extern char * eMsgd2();
+extern void s_fprT();
+extern char * TerminalString();
+extern void lexclass();
+extern void lexmode();
+extern int LexClassIndex();
+extern int hasAction();
+extern void setHasAction();
+extern int addTname();
+extern int addTexpr();
+extern int Tnum();
+extern void Tklink();
+extern Entry * newEntry();
+extern void list_add();
+extern void list_free(); /* MR10 */
+extern void list_apply();
+extern int list_search_cstring (); /* MR27 */
+extern char * Fkey();
+extern void FoPush();
+extern void FoPop();
+extern void RegisterCycle();
+extern void ResolveFoCycles();
+extern void pJunc();
+extern void pRuleRef();
+extern void pToken();
+extern void pAction();
+extern void FoLink();
+extern void addFoLink();
+extern void GenCrossRef();
+extern void defErr();
+extern void genStdPCCTSIncludeFile();
+extern char * pcctsBaseName(); /* MR32 */
+extern Predicate *find_predicates();
+extern Predicate *MR_find_predicates_and_supp(); /* MR13 */
+extern int predicateLookaheadDepth(); /* MR10 */
+extern void predicate_free(); /* MR10 */
+extern Predicate * predicate_dup(); /* MR10 */
+extern Predicate * predicate_dup_without_context(); /* MR11 */
+extern void GenRulePrototypes();
+extern Junction *first_item_is_guess_block();
+extern Junction *first_item_is_guess_block_extra(); /* MR30 */
+extern Junction *analysis_point();
+extern Tree *make_tree_from_sets();
+extern Tree *tdup_chain();
+extern Tree *tdif();
+extern set covered_set();
+extern void AmbiguityDialog();
+extern void dumpAmbigMsg();
+extern void GenRuleFuncRedefs();
+extern void GenPredefinedSymbolRedefs();
+extern void GenASTSymbolRedefs();
+extern void GenRemapFile();
+extern void GenSetRedefs();
+extern ForcedToken *newForcedToken();
+extern void RemapForcedTokens();
+extern char *TokenOrExpr();
+extern void setUpperRange();
+extern void GenParser_c_Hdr();
+extern void GenParser_h_Hdr();
+extern void GenRuleMemberDeclarationsForCC();
+extern int addForcedTname();
+extern char *OutMetaName();
+extern void OutFirstSetSymbol(); /* MR21 */
+extern void warnNoFL();
+extern void warnFL();
+extern void warn();
+extern void warnNoCR();
+extern void errNoFL();
+extern void errFL();
+extern void err();
+extern void errNoCR();
+extern void genPredTree();
+extern UserAction *newUserAction();
+extern char *gate_symbol();
+extern char *makeAltID();
+extern void DumpRemainingTokSets();
+extern void DumpANSIFunctionArgDef();
+extern void DumpFormals(); /* MR23 */
+extern char* hideDefaultArgs(); /* MR22 VHS */
+extern Predicate *computePredFromContextGuard();
+extern void recomputeContextGuard(); /* MR13 */
+extern Predicate *new_pred();
+extern void chkGTFlag();
+extern void leAdd(); /* MR7 */
+extern void leFixup(); /* MR7 */
+extern void egAdd(); /* MR7 */
+extern void egFixup(); /* MR7 */
+extern void altAdd(); /* MR7 */
+extern void altFixup(); /* MR7 */
+extern Predicate * MR_find_in_aSubBlk(); /* MR10 */
+extern Predicate * MR_predFlatten(); /* MR10 */
+extern Predicate * MR_predSimplifyALL(); /* MR10 */
+extern Predicate * MR_predSimplifyALLX(); /* MR10 */
+extern void MR_cleanup_pred_trees(); /* MR10 */
+extern int MR_allPredLeaves(); /* MR10 */
+extern int MR_predicate_context_completed(); /* MR10 */
+extern void MR_check_pred_too_long(); /* MR10 */
+extern Tree * MR_remove_epsilon_from_tree(); /* MR10 */
+extern Tree * MR_computeTreeAND(); /* MR10 */
+extern int MR_tree_equ(); /* MR10 */
+extern set MR_First(); /* MR10 */
+extern set MR_compute_pred_set(); /* MR10 */
+extern Tree * MR_compute_pred_tree_context(); /* MR10 */
+extern int MR_pointerStackPush(); /* MR10 */
+extern void * MR_pointerStackPop(); /* MR10 */
+extern void * MR_pointerStackTop(); /* MR10 */
+extern void MR_pointerStackReset(); /* MR10 */
+extern void MR_backTraceReport(); /* MR10 */
+extern void MR_alphaBetaTraceReport(); /* MR14 */
+extern void MR_dumpRuleSet(); /* MR14 */
+extern void MR_predContextPresent(); /* MR10 */
+extern void MR_dumpPred(); /* MR10 */
+extern void MR_dumpPred1(); /* MR10 */
+extern void MR_xxxIndent(); /* MR11 */
+extern void MR_stderrIndent(); /* MR11 */
+extern void MR_outputIndent(); /* MR11 */
+extern Junction * MR_ruleReferenced(); /* MR10 */
+extern void MR_releaseResourcesUsedInRule(); /* MR10 */
+extern void MR_dumpTreeX(); /* MR10 */
+extern void MR_dumpTreeF(); /* MR10 */
+extern void DumpFcache(); /* MR10 */
+extern void MR_dumpTokenSet(); /* MR10 */
+extern void MR_traceAmbSource(); /* MR11 */
+extern Node *MR_advance(); /* MR11 */
+extern int MR_offsetFromRule(); /* MR11 */
+extern char *MR_ruleNamePlusOffset(); /* MR11 */
+extern void MR_traceAmbSourceK(); /* MR11 */
+extern void MR_traceAmbSourceKclient(); /* [i_a] added */
+extern int MR_max_height_of_tree(); /* MR11 */
+extern int MR_all_leaves_same_height(); /* MR11 */
+extern void MR_projectTreeOntoSet(); /* MR11 */
+extern Tree *MR_make_tree_from_set(); /* MR11 */
+extern Predicate *MR_removeRedundantPredPass3(); /* MR11 */
+extern void MR_pred_depth(); /* MR11 */
+extern int MR_comparePredicates(); /* MR11 */
+extern Predicate * MR_unfold(); /* MR11 */
+extern void MR_simplifyInverted(); /* MR11 */
+extern int MR_secondPredicateUnreachable(); /* MR11 */
+extern Junction * MR_nameToRuleBlk(); /* MR10 */
+extern void MR_clearPredEntry(); /* MR11 */
+extern void MR_orphanRules(); /* MR12 */
+extern void MR_merge_contexts(); /* MR12 */
+extern int ci_strequ(); /* MR12 */
+extern void MR_guardPred_plainSet(); /* MR12c */
+extern void MR_suppressSearchReport(); /* MR12c */
+extern Predicate * MR_suppressK(); /* MR13 */
+extern void MR_backTraceDumpItem(); /* MR13 */
+extern void MR_backTraceDumpItemReset(); /* MR13 */
+extern Junction * MR_junctionWithoutP2(); /* MR13 */
+extern void MR_setConstrainPointer(); /* MR18 */
+extern void BlockPreambleOption(); /* MR23 */
+extern char* getInitializer(); /* MR23 */
+extern int hasMultipleOperands(); /* MR23 */
+extern char *endFormal(); /* MR23 */
+extern char *strBetween(); /* MR23 */
+extern void DumpInitializers(); /* MR23 */
+extern int isTermEntryTokClass(); /* MR23 */
+extern int isEmptyAlt();
+
+#endif
+
+#ifdef __USE_PROTOS
+#include <stdlib.h>
+#endif
+
+/* MR20 G. Hobbelt Create proper externs for dlg variables */
+
+extern set attribsRefdFromAction;
+extern int inAlt;
+extern int UsedOldStyleAttrib;
+extern int UsedNewStyleLabel;
+
+#define MAX_BLK_LEVEL 100 /* MR23 */
+extern int CurBlockID_array[MAX_BLK_LEVEL]; /* MR23 */
+extern int CurAltNum_array[MAX_BLK_LEVEL]; /* MR23 */
diff --git a/Source/Pccts/antlr/scan.c b/Source/Pccts/antlr/scan.c
new file mode 100644
index 0000000..9b4bde0
--- /dev/null
+++ b/Source/Pccts/antlr/scan.c
@@ -0,0 +1,5735 @@
+
+/* parser.dlg -- DLG Description of scanner
+ *
+ * Generated from: antlr.g
+ *
+ * Terence Parr, Will Cohen, and Hank Dietz: 1989-2001
+ * Purdue University Electrical Engineering
+ * With AHPCRC, University of Minnesota
+ * ANTLR Version 1.33MR33
+ */
+
+#define ANTLR_VERSION 13333
+#include "pcctscfg.h"
+#include "pccts_stdio.h"
+
+#include "pcctscfg.h"
+#include "set.h"
+#include <ctype.h>
+#include "syn.h"
+#include "hash.h"
+#include "generic.h"
+#define zzcr_attr(attr,tok,t)
+#include "antlr.h"
+#include "tokens.h"
+#include "dlgdef.h"
+LOOKAHEAD
+
+void
+#ifdef __USE_PROTOS
+zzerraction(void)
+#else
+zzerraction()
+#endif
+{
+ (*zzerr)("invalid token");
+ zzadvance();
+ zzskip();
+}
+/*
+ * D L G tables
+ *
+ * Generated from: parser.dlg
+ *
+ * 1989-2001 by Will Cohen, Terence Parr, and Hank Dietz
+ * Purdue University Electrical Engineering
+ * DLG Version 1.33MR33
+ */
+
+#include "mode.h"
+
+
+
+
+/* maintained, but not used for now */
+set AST_nodes_refd_in_actions = set_init;
+int inAlt = 0;
+set attribsRefdFromAction = set_init; /* MR20 */
+int UsedOldStyleAttrib = 0;
+int UsedNewStyleLabel = 0;
+#ifdef __USE_PROTOS
+char *inline_set(char *);
+#else
+char *inline_set();
+#endif
+
+/* MR1 10-Apr-97 MR1 Previously unable to put right shift operator */
+/* MR1 in DLG action */
+
+int tokenActionActive=0; /* MR1 */
+
+
+
+
+
+static char *
+#ifdef __USE_PROTOS
+getFileNameFromTheLineInfo(char *toStr, char *fromStr)
+#else
+getFileNameFromTheLineInfo(toStr, fromStr)
+char *toStr, *fromStr;
+#endif
+{
+ int i, j, k;
+
+ if (!fromStr || !toStr) return toStr;
+
+ /* find the first " */
+
+ for (i=0;
+ (i<MaxFileName) &&
+ (fromStr[i] != '\n') &&
+ (fromStr[i] != '\r') &&
+ (fromStr[i] != '\"');
+ i++) /* nothing */ ;
+
+ if ( (i == MaxFileName) ||
+ (fromStr[i] == '\n') ||
+ (fromStr[i] == '\r') ) {
+ return toStr;
+}
+
+ /* find the second " */
+
+ for (j=i+1;
+(j<MaxFileName) &&
+(fromStr[j] != '\n') &&
+(fromStr[j] != '\r') &&
+(fromStr[j] != '\"');
+j++) /* nothing */ ;
+
+ if ((j == MaxFileName) ||
+(fromStr[j] == '\n') ||
+(fromStr[j] == '\r') ) {
+ return toStr;
+}
+
+ /* go back until the last / or \ */
+
+ for (k=j-1;
+(fromStr[k] != '\"') &&
+(fromStr[k] != '/') &&
+(fromStr[k] != '\\');
+k--) /* nothing */ ;
+
+ /* copy the string after " / or \ into toStr */
+
+ for (i=k+1; fromStr[i] != '\"'; i++) {
+toStr[i-k-1] = fromStr[i];
+}
+
+ toStr[i-k-1] = '\0';
+
+ return toStr;
+}
+
+/* MR14 end of a block to support #line in antlr source code */
+
+
+
+
+#ifdef __USE_PROTOS
+void mark_label_used_in_sem_pred(LabelEntry *le) /* MR10 */
+#else
+void mark_label_used_in_sem_pred(le) /* MR10 */
+LabelEntry *le;
+#endif
+{
+ TokNode *tn;
+ require (le->elem->ntype == nToken,"mark_label_used... ntype != nToken");
+ tn=(TokNode *)le->elem;
+ require (tn->label != 0,"mark_label_used... TokNode has no label");
+ tn->label_used_in_semantic_pred=1;
+}
+
+static void act1()
+{
+ NLA = Eof;
+ /* L o o k F o r A n o t h e r F i l e */
+ {
+ FILE *new_input;
+ new_input = NextFile();
+ if ( new_input == NULL ) { NLA=Eof; return; }
+ fclose( input );
+ input = new_input;
+ zzrdstream( input );
+ zzskip(); /* Skip the Eof (@) char i.e continue */
+ }
+ }
+
+
+static void act2()
+{
+ NLA = 76;
+ zzskip();
+ }
+
+
+static void act3()
+{
+ NLA = 77;
+ zzline++; zzskip();
+ }
+
+
+static void act4()
+{
+ NLA = 78;
+ zzmode(ACTIONS); zzmore();
+ istackreset();
+ pushint(']');
+ }
+
+
+static void act5()
+{
+ NLA = 79;
+ action_file=CurFile; action_line=zzline;
+ zzmode(ACTIONS); zzmore();
+ list_free(&CurActionLabels,0); /* MR10 */
+ numericActionLabel=0; /* MR10 */
+ istackreset();
+ pushint('>');
+ }
+
+
+static void act6()
+{
+ NLA = 80;
+ zzmode(STRINGS); zzmore();
+ }
+
+
+static void act7()
+{
+ NLA = 81;
+ zzmode(COMMENTS); zzskip();
+ }
+
+
+static void act8()
+{
+ NLA = 82;
+ warn("Missing /*; found dangling */"); zzskip();
+ }
+
+
+static void act9()
+{
+ NLA = 83;
+ zzmode(CPP_COMMENTS); zzskip();
+ }
+
+
+static void act10()
+{
+ NLA = 84;
+
+ zzline = atoi(zzbegexpr+5) - 1; zzline++; zzmore();
+ getFileNameFromTheLineInfo(FileStr[CurFile], zzbegexpr);
+ }
+
+
+static void act11()
+{
+ NLA = 85;
+
+ zzline++; zzmore();
+ }
+
+
+static void act12()
+{
+ NLA = 86;
+ warn("Missing <<; found dangling >>"); zzskip();
+ }
+
+
+static void act13()
+{
+ NLA = WildCard;
+ }
+
+
+static void act14()
+{
+ NLA = 88;
+ FoundException = 1; /* MR6 */
+ FoundAtOperator = 1;
+ }
+
+
+static void act15()
+{
+ NLA = Pragma;
+ }
+
+
+static void act16()
+{
+ NLA = FirstSetSymbol;
+ }
+
+
+static void act17()
+{
+ NLA = 94;
+ }
+
+
+static void act18()
+{
+ NLA = 95;
+ }
+
+
+static void act19()
+{
+ NLA = 96;
+ }
+
+
+static void act20()
+{
+ NLA = 97;
+ }
+
+
+static void act21()
+{
+ NLA = 98;
+ }
+
+
+static void act22()
+{
+ NLA = 99;
+ }
+
+
+static void act23()
+{
+ NLA = 102;
+ }
+
+
+static void act24()
+{
+ NLA = 103;
+ }
+
+
+static void act25()
+{
+ NLA = 104;
+ }
+
+
+static void act26()
+{
+ NLA = 105;
+ }
+
+
+static void act27()
+{
+ NLA = 106;
+ }
+
+
+static void act28()
+{
+ NLA = 107;
+ }
+
+
+static void act29()
+{
+ NLA = 108;
+ }
+
+
+static void act30()
+{
+ NLA = 109;
+ }
+
+
+static void act31()
+{
+ NLA = 110;
+ }
+
+
+static void act32()
+{
+ NLA = 111;
+ }
+
+
+static void act33()
+{
+ NLA = 112;
+ }
+
+
+static void act34()
+{
+ NLA = 113;
+ }
+
+
+static void act35()
+{
+ NLA = 114;
+ }
+
+
+static void act36()
+{
+ NLA = 115;
+ }
+
+
+static void act37()
+{
+ NLA = 116;
+ }
+
+
+static void act38()
+{
+ NLA = 117;
+ }
+
+
+static void act39()
+{
+ NLA = 118;
+ }
+
+
+static void act40()
+{
+ NLA = 119;
+ }
+
+
+static void act41()
+{
+ NLA = 120;
+ }
+
+
+static void act42()
+{
+ NLA = 121;
+ }
+
+
+static void act43()
+{
+ NLA = 122;
+ }
+
+
+static void act44()
+{
+ NLA = 123;
+ }
+
+
+static void act45()
+{
+ NLA = 124;
+ }
+
+
+static void act46()
+{
+ NLA = 125;
+ }
+
+
+static void act47()
+{
+ NLA = 126;
+ }
+
+
+static void act48()
+{
+ NLA = 127;
+ }
+
+
+static void act49()
+{
+ NLA = 128;
+ }
+
+
+static void act50()
+{
+ NLA = 129;
+ }
+
+
+static void act51()
+{
+ NLA = 130;
+ }
+
+
+static void act52()
+{
+ NLA = 131;
+ }
+
+
+static void act53()
+{
+ NLA = 132;
+ }
+
+
+static void act54()
+{
+ NLA = 133;
+ }
+
+
+static void act55()
+{
+ NLA = 134;
+ }
+
+
+static void act56()
+{
+ NLA = 135;
+ }
+
+
+static void act57()
+{
+ NLA = NonTerminal;
+
+ while ( zzchar==' ' || zzchar=='\t' ) {
+ zzadvance();
+ }
+ if ( zzchar == ':' && inAlt ) NLA = LABEL;
+ }
+
+
+static void act58()
+{
+ NLA = TokenTerm;
+
+ while ( zzchar==' ' || zzchar=='\t' ) {
+ zzadvance();
+ }
+ if ( zzchar == ':' && inAlt ) NLA = LABEL;
+ }
+
+
+static void act59()
+{
+ NLA = 136;
+ warn(eMsg1("unknown meta-op: %s",LATEXT(1))); zzskip();
+ }
+
+static unsigned char shift0[257] = {
+ 0, 58, 58, 58, 58, 58, 58, 58, 58, 58,
+ 1, 2, 58, 58, 3, 58, 58, 58, 58, 58,
+ 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
+ 58, 58, 58, 1, 40, 6, 9, 58, 58, 45,
+ 58, 46, 47, 8, 52, 58, 58, 18, 7, 16,
+ 14, 15, 16, 16, 16, 16, 16, 16, 16, 41,
+ 42, 5, 48, 17, 53, 19, 56, 56, 56, 56,
+ 56, 26, 56, 56, 56, 56, 56, 51, 56, 56,
+ 56, 56, 56, 56, 29, 56, 56, 56, 56, 56,
+ 56, 56, 4, 20, 58, 50, 57, 58, 23, 31,
+ 38, 34, 13, 35, 24, 33, 11, 55, 36, 10,
+ 25, 12, 32, 21, 55, 22, 27, 28, 54, 55,
+ 55, 43, 30, 55, 39, 44, 37, 49, 58, 58,
+ 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
+ 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
+ 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
+ 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
+ 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
+ 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
+ 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
+ 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
+ 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
+ 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
+ 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
+ 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
+ 58, 58, 58, 58, 58, 58, 58
+};
+
+
+static void act60()
+{
+ NLA = Eof;
+ }
+
+
+static void act61()
+{
+ NLA = QuotedTerm;
+ zzmode(START);
+ }
+
+
+static void act62()
+{
+ NLA = 3;
+
+ zzline++;
+ warn("eoln found in string");
+ zzskip();
+ }
+
+
+static void act63()
+{
+ NLA = 4;
+ zzline++; zzmore();
+ }
+
+
+static void act64()
+{
+ NLA = 5;
+ zzmore();
+ }
+
+
+static void act65()
+{
+ NLA = 6;
+ zzmore();
+ }
+
+static unsigned char shift1[257] = {
+ 0, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 2, 5, 5, 3, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 1, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 4, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5
+};
+
+
+static void act66()
+{
+ NLA = Eof;
+ }
+
+
+static void act67()
+{
+ NLA = 7;
+ zzmode(ACTIONS); zzmore();
+ }
+
+
+static void act68()
+{
+ NLA = 8;
+
+ zzline++;
+ warn("eoln found in string (in user action)");
+ zzskip();
+ }
+
+
+static void act69()
+{
+ NLA = 9;
+ zzline++; zzmore();
+ }
+
+
+static void act70()
+{
+ NLA = 10;
+ zzmore();
+ }
+
+
+static void act71()
+{
+ NLA = 11;
+ zzmore();
+ }
+
+static unsigned char shift2[257] = {
+ 0, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 2, 5, 5, 3, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 1, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 4, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5
+};
+
+
+static void act72()
+{
+ NLA = Eof;
+ }
+
+
+static void act73()
+{
+ NLA = 12;
+ zzmode(ACTIONS); zzmore();
+ }
+
+
+static void act74()
+{
+ NLA = 13;
+
+ zzline++;
+ warn("eoln found in char literal (in user action)");
+ zzskip();
+ }
+
+
+static void act75()
+{
+ NLA = 14;
+ zzmore();
+ }
+
+
+static void act76()
+{
+ NLA = 15;
+ zzmore();
+ }
+
+static unsigned char shift3[257] = {
+ 0, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 2, 5, 5, 3, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 1, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 4, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5
+};
+
+
+static void act77()
+{
+ NLA = Eof;
+ }
+
+
+static void act78()
+{
+ NLA = 16;
+ zzmode(ACTIONS); zzmore();
+ }
+
+
+static void act79()
+{
+ NLA = 17;
+ zzmore();
+ }
+
+
+static void act80()
+{
+ NLA = 18;
+ zzline++; zzmore(); DAWDLE;
+ }
+
+
+static void act81()
+{
+ NLA = 19;
+ zzmore();
+ }
+
+static unsigned char shift4[257] = {
+ 0, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 3, 5, 5, 4, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 1, 5, 5, 5, 5, 2, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5
+};
+
+
+static void act82()
+{
+ NLA = Eof;
+ }
+
+
+static void act83()
+{
+ NLA = 20;
+ zzmode(PARSE_ENUM_FILE);
+ zzmore();
+ }
+
+
+static void act84()
+{
+ NLA = 21;
+ zzmore();
+ }
+
+
+static void act85()
+{
+ NLA = 22;
+ zzline++; zzmore(); DAWDLE;
+ }
+
+
+static void act86()
+{
+ NLA = 23;
+ zzmore();
+ }
+
+static unsigned char shift5[257] = {
+ 0, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 3, 5, 5, 4, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 1, 5, 5, 5, 5, 2, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5
+};
+
+
+static void act87()
+{
+ NLA = Eof;
+ }
+
+
+static void act88()
+{
+ NLA = 24;
+ zzline++; zzmode(PARSE_ENUM_FILE); zzskip(); DAWDLE;
+ }
+
+
+static void act89()
+{
+ NLA = 25;
+ zzskip();
+ }
+
+static unsigned char shift6[257] = {
+ 0, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 1, 3, 3, 2, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3
+};
+
+
+static void act90()
+{
+ NLA = Eof;
+ }
+
+
+static void act91()
+{
+ NLA = 26;
+ zzline++; zzmode(ACTIONS); zzmore(); DAWDLE;
+ }
+
+
+static void act92()
+{
+ NLA = 27;
+ zzmore();
+ }
+
+static unsigned char shift7[257] = {
+ 0, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 1, 3, 3, 2, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3
+};
+
+
+static void act93()
+{
+ NLA = Eof;
+ }
+
+
+static void act94()
+{
+ NLA = 28;
+ zzline++; zzmode(START); zzskip(); DAWDLE;
+ }
+
+
+static void act95()
+{
+ NLA = 29;
+ zzskip();
+ }
+
+static unsigned char shift8[257] = {
+ 0, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 1, 3, 3, 2, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3
+};
+
+
+static void act96()
+{
+ NLA = Eof;
+ }
+
+
+static void act97()
+{
+ NLA = 30;
+ zzmode(START); zzskip();
+ }
+
+
+static void act98()
+{
+ NLA = 31;
+ zzskip();
+ }
+
+
+static void act99()
+{
+ NLA = 32;
+ zzline++; zzskip(); DAWDLE;
+ }
+
+
+static void act100()
+{
+ NLA = 33;
+ zzskip();
+ }
+
+static unsigned char shift9[257] = {
+ 0, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 3, 5, 5, 4, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 1, 5, 5, 5, 5, 2, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5
+};
+
+
+static void act101()
+{
+ NLA = Eof;
+ }
+
+
+static void act102()
+{
+ NLA = Action;
+ /* these do not nest */
+ zzmode(START);
+ NLATEXT[0] = ' ';
+ NLATEXT[1] = ' ';
+ zzbegexpr[0] = ' ';
+ zzbegexpr[1] = ' ';
+ if ( zzbufovf ) {
+ err( eMsgd("action buffer overflow; size %d",ZZLEXBUFSIZE));
+ }
+
+/* MR1 10-Apr-97 MR1 Previously unable to put right shift operator */
+ /* MR1 in DLG action */
+ /* MR1 Doesn't matter what kind of action it is - reset*/
+
+ tokenActionActive=0; /* MR1 */
+ }
+
+
+static void act103()
+{
+ NLA = Pred;
+ /* these do not nest */
+ zzmode(START);
+ NLATEXT[0] = ' ';
+ NLATEXT[1] = ' ';
+ zzbegexpr[0] = '\0';
+ if ( zzbufovf ) {
+ err( eMsgd("predicate buffer overflow; size %d",ZZLEXBUFSIZE));
+ };
+#ifdef __cplusplus__
+ /* MR10 */ list_apply(CurActionLabels, (void (*)(void *))mark_label_used_in_sem_pred);
+#else
+#ifdef __STDC__
+ /* MR10 */ list_apply(CurActionLabels, (void (*)(void *))mark_label_used_in_sem_pred);
+#else
+#ifdef __USE_PROTOS
+ /* MRxx */ list_apply(CurActionLabels, (void (*)(void *))mark_label_used_in_sem_pred);
+#else
+ /* MR10 */ list_apply(CurActionLabels,mark_label_used_in_sem_pred);
+#endif
+#endif
+#endif
+ }
+
+
+static void act104()
+{
+ NLA = PassAction;
+ if ( topint() == ']' ) {
+ popint();
+ if ( istackempty() ) /* terminate action */
+ {
+ zzmode(START);
+ NLATEXT[0] = ' ';
+ zzbegexpr[0] = ' ';
+ if ( zzbufovf ) {
+ err( eMsgd("parameter buffer overflow; size %d",ZZLEXBUFSIZE));
+ }
+ }
+ else {
+ /* terminate $[..] and #[..] */
+ if ( GenCC ) zzreplstr("))");
+ else zzreplstr(")");
+ zzmore();
+ }
+ }
+ else if ( topint() == '|' ) { /* end of simple [...] */
+ popint();
+ zzmore();
+ }
+ else zzmore();
+ }
+
+
+static void act105()
+{
+ NLA = 37;
+
+ zzmore();
+ zzreplstr(inline_set(zzbegexpr+
+ strlen("consumeUntil(")));
+ }
+
+
+static void act106()
+{
+ NLA = 38;
+ zzmore();
+ }
+
+
+static void act107()
+{
+ NLA = 39;
+ zzline++; zzmore(); DAWDLE;
+ }
+
+
+static void act108()
+{
+ NLA = 40;
+ zzmore();
+ }
+
+
+static void act109()
+{
+ NLA = 41;
+ zzmore();
+ }
+
+
+static void act110()
+{
+ NLA = 42;
+ if ( !GenCC ) {zzreplstr("zzaRet"); zzmore();}
+ else err("$$ use invalid in C++ mode");
+ }
+
+
+static void act111()
+{
+ NLA = 43;
+ if ( !GenCC ) {zzreplstr("zzempty_attr"); zzmore();}
+ else err("$[] use invalid in C++ mode");
+ }
+
+
+static void act112()
+{
+ NLA = 44;
+
+ pushint(']');
+ if ( !GenCC ) zzreplstr("zzconstr_attr(");
+ else err("$[..] use invalid in C++ mode");
+ zzmore();
+ }
+
+
+static void act113()
+{
+ NLA = 45;
+ {
+ static char buf[100];
+ numericActionLabel=1; /* MR10 */
+ if ( strlen(zzbegexpr)>(size_t)85 )
+ fatal("$i attrib ref too big");
+ set_orel(atoi(zzbegexpr+1), &attribsRefdFromAction);
+ if ( !GenCC ) sprintf(buf,"zzaArg(zztasp%d,%s)",
+ BlkLevel-1,zzbegexpr+1);
+ else sprintf(buf,"_t%d%s",
+ BlkLevel-1,zzbegexpr+1);
+ zzreplstr(buf);
+ zzmore();
+ UsedOldStyleAttrib = 1;
+ if ( UsedNewStyleLabel )
+ err("cannot mix old-style $i with new-style labels");
+ }
+ }
+
+
+static void act114()
+{
+ NLA = 46;
+ {
+ static char buf[100];
+ numericActionLabel=1; /* MR10 */
+ if ( strlen(zzbegexpr)>(size_t)85 )
+ fatal("$i.field attrib ref too big");
+ zzbegexpr[strlen(zzbegexpr)-1] = ' ';
+ set_orel(atoi(zzbegexpr+1), &attribsRefdFromAction);
+ if ( !GenCC ) sprintf(buf,"zzaArg(zztasp%d,%s).",
+ BlkLevel-1,zzbegexpr+1);
+ else sprintf(buf,"_t%d%s.",
+ BlkLevel-1,zzbegexpr+1);
+ zzreplstr(buf);
+ zzmore();
+ UsedOldStyleAttrib = 1;
+ if ( UsedNewStyleLabel )
+ err("cannot mix old-style $i with new-style labels");
+ }
+ }
+
+
+static void act115()
+{
+ NLA = 47;
+ {
+ static char buf[100];
+ static char i[20], j[20];
+ char *p,*q;
+ numericActionLabel=1; /* MR10 */
+ if (strlen(zzbegexpr)>(size_t)85) fatal("$i.j attrib ref too big");
+ for (p=zzbegexpr+1,q= &i[0]; *p!='.'; p++) {
+ if ( q == &i[20] )
+ fatalFL("i of $i.j attrib ref too big",
+ FileStr[CurFile], zzline );
+ *q++ = *p;
+ }
+ *q = '\0';
+ for (p++, q= &j[0]; *p!='\0'; p++) {
+ if ( q == &j[20] )
+ fatalFL("j of $i.j attrib ref too big",
+ FileStr[CurFile], zzline );
+ *q++ = *p;
+ }
+ *q = '\0';
+ if ( !GenCC ) sprintf(buf,"zzaArg(zztasp%s,%s)",i,j);
+ else sprintf(buf,"_t%s%s",i,j);
+ zzreplstr(buf);
+ zzmore();
+ UsedOldStyleAttrib = 1;
+ if ( UsedNewStyleLabel )
+ err("cannot mix old-style $i with new-style labels");
+ }
+ }
+
+
+static void act116()
+{
+ NLA = 48;
+ { static char buf[300]; LabelEntry *el;
+ zzbegexpr[0] = ' ';
+ if ( CurRule != NULL &&
+ strcmp(CurRule, &zzbegexpr[1])==0 ) {
+ if ( !GenCC ) zzreplstr("zzaRet");
+ }
+ else if ( CurRetDef != NULL &&
+ strmember(CurRetDef, &zzbegexpr[1])) {
+ if ( hasMultipleOperands( CurRetDef ) ) {
+ require (strlen(zzbegexpr)<=(size_t)285,
+ "$retval attrib ref too big");
+ sprintf(buf,"_retv.%s",&zzbegexpr[1]);
+ zzreplstr(buf);
+ }
+ else zzreplstr("_retv");
+ }
+ else if ( CurParmDef != NULL &&
+ strmember(CurParmDef, &zzbegexpr[1])) {
+ ;
+ }
+ else if ( Elabel==NULL ) {
+ { err("$-variables in actions outside of rules are not allowed"); }
+ } else if ( (el=(LabelEntry *)hash_get(Elabel, &zzbegexpr[1]))!=NULL ) {
+ /* MR10 */
+ /* MR10 */ /* element labels might exist without an elem when */
+ /* MR10 */ /* it is a forward reference (to a rule) */
+ /* MR10 */
+ /* MR10 */ if ( GenCC && (el->elem == NULL || el->elem->ntype==nRuleRef) )
+ /* MR10 */ { err(eMsg1("There are no token ptrs for rule references: '$%s'",&zzbegexpr[1])); }
+ /* MR10 */
+ /* MR10 */ if ( !GenCC && (el->elem == NULL || el->elem->ntype==nRuleRef) && GenAST) {
+ /* MR10 */ err("You can no longer use attributes returned by rules when also using ASTs");
+ /* MR10 */ err(" Use upward inheritance (\"rule >[Attrib a] : ... <<$a=...>>\")");
+ /* MR10 */ };
+ /* MR10 */
+ /* MR10 */ /* keep track of <<... $label ...>> for semantic predicates in guess mode */
+ /* MR10 */ /* element labels contain pointer to the owners node */
+ /* MR10 */
+ /* MR10 */ if (el->elem != NULL && el->elem->ntype == nToken) {
+ /* MR10 */ list_add(&CurActionLabels,el);
+ /* MR10 */ };
+}
+else
+warn(eMsg1("$%s not parameter, return value, (defined) element label",&zzbegexpr[1]));
+}
+zzmore();
+ }
+
+
+static void act117()
+{
+ NLA = 49;
+ zzreplstr("(*_root)"); zzmore(); chkGTFlag();
+ }
+
+
+static void act118()
+{
+ NLA = 50;
+ if ( GenCC ) {
+ if (NewAST) zzreplstr("(newAST)");
+ else zzreplstr("(new AST)");}
+ else {zzreplstr("zzastnew()");} zzmore();
+ chkGTFlag();
+ }
+
+
+static void act119()
+{
+ NLA = 51;
+ zzreplstr("NULL"); zzmore(); chkGTFlag();
+ }
+
+
+static void act120()
+{
+ NLA = 52;
+ {
+ static char buf[100];
+ if ( strlen(zzbegexpr)>(size_t)85 )
+ fatal("#i AST ref too big");
+ if ( GenCC ) sprintf(buf,"_ast%d%s",BlkLevel-1,zzbegexpr+1);
+ else sprintf(buf,"zzastArg(%s)",zzbegexpr+1);
+ zzreplstr(buf);
+ zzmore();
+ set_orel(atoi(zzbegexpr+1), &AST_nodes_refd_in_actions);
+ chkGTFlag();
+ }
+ }
+
+
+static void act121()
+{
+ NLA = 53;
+
+ zzline = atoi(zzbegexpr+5) - 1; zzline++; zzmore();
+ getFileNameFromTheLineInfo(FileStr[CurFile], zzbegexpr);
+ }
+
+
+static void act122()
+{
+ NLA = 54;
+
+ zzline++; zzmore();
+ }
+
+
+static void act123()
+{
+ NLA = 55;
+
+ if ( !(strcmp(zzbegexpr, "#ifdef")==0 ||
+ strcmp(zzbegexpr, "#if")==0 ||
+ strcmp(zzbegexpr, "#else")==0 ||
+ strcmp(zzbegexpr, "#endif")==0 ||
+ strcmp(zzbegexpr, "#ifndef")==0 ||
+ strcmp(zzbegexpr, "#define")==0 ||
+ strcmp(zzbegexpr, "#pragma")==0 ||
+ strcmp(zzbegexpr, "#undef")==0 ||
+ strcmp(zzbegexpr, "#import")==0 ||
+ strcmp(zzbegexpr, "#line")==0 ||
+ strcmp(zzbegexpr, "#include")==0 ||
+ strcmp(zzbegexpr, "#error")==0) )
+ {
+ static char buf[100];
+ sprintf(buf, "%s_ast", zzbegexpr+1);
+ /* MR27 */ list_add(&CurAstLabelsInActions, mystrdup(zzbegexpr+1));
+ zzreplstr(buf);
+ chkGTFlag();
+ }
+ zzmore();
+ }
+
+
+static void act124()
+{
+ NLA = 56;
+
+ pushint(']');
+ if ( GenCC ) {
+ if (NewAST) zzreplstr("(newAST(");
+ else zzreplstr("(new AST("); }
+ else zzreplstr("zzmk_ast(zzastnew(),");
+ zzmore();
+ chkGTFlag();
+ }
+
+
+static void act125()
+{
+ NLA = 57;
+
+ pushint('}');
+ if ( GenCC ) {
+ if (tmakeInParser) {
+ zzreplstr("tmake(");
+ }
+ else {
+ zzreplstr("ASTBase::tmake(");
+ }
+ }
+ else {
+ zzreplstr("zztmake(");
+ }
+ zzmore();
+ chkGTFlag();
+ }
+
+
+static void act126()
+{
+ NLA = 58;
+ zzmore();
+ }
+
+
+static void act127()
+{
+ NLA = 59;
+
+ if ( istackempty() )
+ zzmore();
+ else if ( topint()==')' ) {
+ popint();
+ }
+ else if ( topint()=='}' ) {
+ popint();
+ /* terminate #(..) */
+ zzreplstr(", NULL)");
+ }
+ zzmore();
+ }
+
+
+static void act128()
+{
+ NLA = 60;
+
+ pushint('|'); /* look for '|' to terminate simple [...] */
+ zzmore();
+ }
+
+
+static void act129()
+{
+ NLA = 61;
+
+ pushint(')');
+ zzmore();
+ }
+
+
+static void act130()
+{
+ NLA = 62;
+ zzreplstr("]"); zzmore();
+ }
+
+
+static void act131()
+{
+ NLA = 63;
+ zzreplstr(")"); zzmore();
+ }
+
+
+static void act132()
+{
+ NLA = 64;
+ if (! tokenActionActive) zzreplstr(">"); /* MR1 */
+ zzmore(); /* MR1 */
+ }
+
+
+static void act133()
+{
+ NLA = 65;
+ zzmode(ACTION_CHARS); zzmore();
+ }
+
+
+static void act134()
+{
+ NLA = 66;
+ zzmode(ACTION_STRINGS); zzmore();
+ }
+
+
+static void act135()
+{
+ NLA = 67;
+ zzreplstr("$"); zzmore();
+ }
+
+
+static void act136()
+{
+ NLA = 68;
+ zzreplstr("#"); zzmore();
+ }
+
+
+static void act137()
+{
+ NLA = 69;
+ zzline++; zzmore();
+ }
+
+
+static void act138()
+{
+ NLA = 70;
+ zzmore();
+ }
+
+
+static void act139()
+{
+ NLA = 71;
+ zzmore();
+ }
+
+
+static void act140()
+{
+ NLA = 72;
+ zzmode(ACTION_COMMENTS); zzmore();
+ }
+
+
+static void act141()
+{
+ NLA = 73;
+ warn("Missing /*; found dangling */ in action"); zzmore();
+ }
+
+
+static void act142()
+{
+ NLA = 74;
+ zzmode(ACTION_CPP_COMMENTS); zzmore();
+ }
+
+
+static void act143()
+{
+ NLA = 75;
+ zzmore();
+ }
+
+static unsigned char shift10[257] = {
+ 0, 33, 33, 33, 33, 33, 33, 33, 33, 33,
+ 16, 19, 33, 33, 20, 33, 33, 33, 33, 33,
+ 33, 33, 33, 33, 33, 33, 33, 33, 33, 33,
+ 33, 33, 33, 16, 33, 28, 27, 21, 33, 33,
+ 30, 15, 18, 32, 33, 33, 33, 25, 31, 23,
+ 24, 24, 24, 24, 24, 24, 24, 24, 24, 33,
+ 33, 33, 33, 1, 2, 33, 26, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 11, 26, 26, 26,
+ 26, 26, 22, 29, 3, 33, 26, 33, 26, 26,
+ 4, 26, 10, 26, 26, 26, 13, 26, 26, 14,
+ 9, 6, 5, 26, 26, 26, 7, 12, 8, 26,
+ 26, 26, 26, 26, 17, 33, 34, 33, 33, 33,
+ 33, 33, 33, 33, 33, 33, 33, 33, 33, 33,
+ 33, 33, 33, 33, 33, 33, 33, 33, 33, 33,
+ 33, 33, 33, 33, 33, 33, 33, 33, 33, 33,
+ 33, 33, 33, 33, 33, 33, 33, 33, 33, 33,
+ 33, 33, 33, 33, 33, 33, 33, 33, 33, 33,
+ 33, 33, 33, 33, 33, 33, 33, 33, 33, 33,
+ 33, 33, 33, 33, 33, 33, 33, 33, 33, 33,
+ 33, 33, 33, 33, 33, 33, 33, 33, 33, 33,
+ 33, 33, 33, 33, 33, 33, 33, 33, 33, 33,
+ 33, 33, 33, 33, 33, 33, 33, 33, 33, 33,
+ 33, 33, 33, 33, 33, 33, 33, 33, 33, 33,
+ 33, 33, 33, 33, 33, 33, 33, 33, 33, 33,
+ 33, 33, 33, 33, 33, 33, 33
+};
+
+
+static void act144()
+{
+ NLA = Eof;
+ ;
+ }
+
+
+static void act145()
+{
+ NLA = 137;
+ zzskip();
+ }
+
+
+static void act146()
+{
+ NLA = 138;
+ zzline++; zzskip();
+ }
+
+
+static void act147()
+{
+ NLA = 139;
+ zzmode(TOK_DEF_CPP_COMMENTS); zzmore();
+ }
+
+
+static void act148()
+{
+ NLA = 140;
+ zzmode(TOK_DEF_COMMENTS); zzskip();
+ }
+
+
+static void act149()
+{
+ NLA = 141;
+ zzmode(TOK_DEF_CPP_COMMENTS); zzskip();
+ }
+
+
+static void act150()
+{
+ NLA = 142;
+ zzmode(TOK_DEF_CPP_COMMENTS); zzskip();
+ }
+
+
+static void act151()
+{
+ NLA = 143;
+ ;
+ }
+
+
+static void act152()
+{
+ NLA = 144;
+ zzmode(TOK_DEF_CPP_COMMENTS); zzskip();
+ }
+
+
+static void act153()
+{
+ NLA = 145;
+ zzmode(TOK_DEF_CPP_COMMENTS); zzskip();
+ }
+
+
+static void act154()
+{
+ NLA = 146;
+ zzmode(TOK_DEF_CPP_COMMENTS); zzskip();
+ }
+
+
+static void act155()
+{
+ NLA = 147;
+ zzmode(TOK_DEF_CPP_COMMENTS); zzskip();
+ }
+
+
+static void act156()
+{
+ NLA = 149;
+ }
+
+
+static void act157()
+{
+ NLA = 151;
+ }
+
+
+static void act158()
+{
+ NLA = 152;
+ }
+
+
+static void act159()
+{
+ NLA = 153;
+ }
+
+
+static void act160()
+{
+ NLA = 154;
+ }
+
+
+static void act161()
+{
+ NLA = 155;
+ }
+
+
+static void act162()
+{
+ NLA = 156;
+ }
+
+
+static void act163()
+{
+ NLA = INT;
+ }
+
+
+static void act164()
+{
+ NLA = ID;
+ }
+
+static unsigned char shift11[257] = {
+ 0, 27, 27, 27, 27, 27, 27, 27, 27, 27,
+ 1, 2, 27, 27, 3, 27, 27, 27, 27, 27,
+ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
+ 27, 27, 27, 1, 27, 27, 6, 27, 27, 27,
+ 27, 27, 27, 5, 27, 22, 27, 27, 4, 25,
+ 25, 25, 25, 25, 25, 25, 25, 25, 25, 27,
+ 24, 27, 21, 27, 27, 27, 26, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 27, 27, 27, 27, 26, 27, 26, 26,
+ 26, 9, 10, 8, 26, 26, 7, 26, 26, 12,
+ 15, 11, 17, 16, 26, 18, 13, 19, 14, 26,
+ 26, 26, 26, 26, 20, 27, 23, 27, 27, 27,
+ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
+ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
+ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
+ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
+ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
+ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
+ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
+ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
+ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
+ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
+ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
+ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
+ 27, 27, 27, 27, 27, 27, 27
+};
+
+#define DfaStates 436
+typedef unsigned short DfaState;
+
+static DfaState st0[60] = {
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
+ 11, 11, 11, 12, 13, 13, 13, 14, 15, 16,
+ 17, 11, 11, 18, 11, 11, 19, 11, 11, 19,
+ 11, 11, 11, 11, 20, 11, 11, 21, 22, 23,
+ 24, 25, 26, 11, 27, 28, 29, 30, 31, 32,
+ 33, 34, 35, 36, 11, 11, 19, 436, 436, 436
+};
+
+static DfaState st1[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st2[60] = {
+ 436, 2, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st3[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st4[60] = {
+ 436, 436, 37, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st5[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st6[60] = {
+ 436, 436, 436, 436, 436, 38, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st7[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st8[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 39, 40, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st9[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 41, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st10[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 42, 43, 43, 44, 43, 43, 43, 436, 436, 436,
+ 436, 45, 43, 43, 43, 43, 46, 43, 47, 43,
+ 43, 43, 43, 48, 43, 49, 43, 436, 43, 436,
+ 436, 436, 436, 43, 436, 436, 436, 436, 436, 436,
+ 436, 43, 436, 436, 43, 43, 43, 43, 436, 436
+};
+
+static DfaState st11[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 50, 50, 50, 50, 50, 50, 50, 436, 436, 436,
+ 436, 50, 50, 50, 50, 50, 50, 50, 50, 50,
+ 50, 50, 50, 50, 50, 50, 50, 436, 50, 436,
+ 436, 436, 436, 50, 436, 436, 436, 436, 436, 436,
+ 436, 50, 436, 436, 50, 50, 50, 50, 436, 436
+};
+
+static DfaState st12[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 50, 50, 50, 50, 50, 50, 50, 436, 436, 436,
+ 436, 50, 50, 50, 50, 50, 50, 50, 50, 50,
+ 50, 50, 50, 50, 50, 50, 50, 436, 50, 436,
+ 436, 436, 436, 51, 436, 436, 436, 436, 436, 436,
+ 436, 50, 436, 436, 50, 50, 50, 50, 436, 436
+};
+
+static DfaState st13[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 13, 13, 13, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st14[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 52, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st15[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 53, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st16[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st17[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 54,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st18[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 50, 50, 50, 50, 50, 50, 50, 436, 436, 436,
+ 436, 55, 50, 50, 50, 50, 50, 50, 50, 50,
+ 50, 50, 50, 50, 50, 50, 50, 436, 50, 436,
+ 436, 436, 436, 50, 436, 436, 436, 436, 436, 436,
+ 436, 50, 436, 436, 50, 50, 50, 50, 436, 436
+};
+
+static DfaState st19[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 56, 56, 56, 56, 56, 56, 56, 436, 436, 436,
+ 436, 56, 56, 56, 56, 56, 56, 56, 56, 56,
+ 56, 56, 56, 56, 56, 56, 56, 436, 56, 436,
+ 436, 436, 436, 56, 436, 436, 436, 436, 436, 436,
+ 436, 56, 436, 436, 56, 56, 56, 56, 436, 436
+};
+
+static DfaState st20[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 50, 50, 50, 57, 50, 50, 50, 436, 436, 436,
+ 436, 50, 50, 50, 50, 50, 50, 50, 50, 50,
+ 50, 50, 50, 50, 50, 50, 50, 436, 50, 436,
+ 436, 436, 436, 50, 436, 436, 436, 436, 436, 436,
+ 436, 50, 436, 436, 50, 50, 50, 50, 436, 436
+};
+
+static DfaState st21[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st22[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 58, 50, 50, 50, 50, 50, 50, 436, 436, 436,
+ 436, 50, 50, 59, 50, 50, 50, 50, 50, 50,
+ 50, 50, 50, 50, 50, 50, 50, 436, 50, 436,
+ 436, 436, 436, 50, 436, 436, 436, 436, 436, 436,
+ 436, 50, 436, 436, 50, 50, 50, 50, 436, 436
+};
+
+static DfaState st23[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st24[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st25[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st26[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st27[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 60, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st28[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 61, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st29[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st30[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st31[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 62, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st32[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st33[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st34[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 56, 56, 56, 56, 56, 56, 56, 436, 436, 436,
+ 436, 56, 56, 56, 56, 56, 56, 56, 56, 56,
+ 56, 56, 56, 56, 56, 56, 56, 436, 56, 436,
+ 436, 436, 436, 56, 436, 436, 436, 436, 436, 436,
+ 436, 63, 436, 436, 56, 56, 56, 56, 436, 436
+};
+
+static DfaState st35[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st36[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st37[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st38[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st39[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st40[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st41[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st42[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 43, 64, 43, 65, 43, 43, 43, 436, 436, 436,
+ 436, 43, 43, 43, 43, 43, 43, 43, 43, 43,
+ 43, 43, 43, 43, 43, 43, 43, 436, 43, 436,
+ 436, 436, 436, 43, 436, 436, 436, 436, 436, 436,
+ 436, 43, 436, 436, 43, 43, 43, 43, 436, 436
+};
+
+static DfaState st43[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 43, 43, 43, 43, 43, 43, 43, 436, 436, 436,
+ 436, 43, 43, 43, 43, 43, 43, 43, 43, 43,
+ 43, 43, 43, 43, 43, 43, 43, 436, 43, 436,
+ 436, 436, 436, 43, 436, 436, 436, 436, 436, 436,
+ 436, 43, 436, 436, 43, 43, 43, 43, 436, 436
+};
+
+static DfaState st44[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 43, 43, 43, 43, 43, 43, 43, 436, 436, 436,
+ 436, 43, 66, 43, 43, 43, 43, 43, 43, 43,
+ 43, 43, 43, 43, 43, 43, 43, 436, 43, 436,
+ 436, 436, 436, 43, 436, 436, 436, 436, 436, 436,
+ 436, 43, 436, 436, 43, 43, 43, 43, 436, 436
+};
+
+static DfaState st45[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 43, 43, 43, 43, 43, 43, 43, 436, 436, 436,
+ 436, 43, 67, 68, 43, 43, 43, 43, 43, 43,
+ 43, 43, 43, 43, 43, 43, 43, 436, 43, 436,
+ 436, 436, 436, 43, 436, 436, 436, 436, 436, 436,
+ 436, 43, 436, 436, 43, 43, 43, 43, 436, 436
+};
+
+static DfaState st46[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 43, 69, 43, 43, 43, 43, 43, 436, 436, 436,
+ 436, 43, 43, 43, 43, 43, 43, 43, 43, 43,
+ 43, 43, 43, 43, 43, 43, 43, 436, 43, 436,
+ 436, 436, 436, 43, 436, 436, 436, 436, 436, 436,
+ 436, 43, 436, 436, 43, 43, 43, 43, 436, 436
+};
+
+static DfaState st47[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 43, 43, 43, 43, 43, 43, 43, 436, 436, 436,
+ 436, 43, 43, 43, 43, 43, 43, 43, 43, 43,
+ 43, 43, 70, 43, 43, 43, 43, 436, 43, 436,
+ 436, 436, 436, 43, 436, 436, 436, 436, 436, 436,
+ 436, 43, 436, 436, 43, 43, 43, 43, 436, 436
+};
+
+static DfaState st48[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 43, 43, 43, 71, 43, 43, 43, 436, 436, 436,
+ 436, 43, 43, 43, 43, 43, 43, 43, 43, 43,
+ 43, 43, 43, 43, 43, 43, 43, 436, 43, 436,
+ 436, 436, 436, 43, 436, 436, 436, 436, 436, 436,
+ 436, 43, 436, 436, 43, 43, 43, 43, 436, 436
+};
+
+static DfaState st49[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 43, 72, 43, 43, 43, 43, 43, 436, 436, 436,
+ 436, 43, 43, 43, 43, 43, 43, 43, 43, 43,
+ 43, 43, 43, 43, 43, 43, 43, 436, 43, 436,
+ 436, 436, 436, 43, 436, 436, 436, 436, 436, 436,
+ 436, 43, 436, 436, 43, 43, 43, 43, 436, 436
+};
+
+static DfaState st50[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 50, 50, 50, 50, 50, 50, 50, 436, 436, 436,
+ 436, 50, 50, 50, 50, 50, 50, 50, 50, 50,
+ 50, 50, 50, 50, 50, 50, 50, 436, 50, 436,
+ 436, 436, 436, 50, 436, 436, 436, 436, 436, 436,
+ 436, 50, 436, 436, 50, 50, 50, 50, 436, 436
+};
+
+static DfaState st51[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 50, 50, 50, 50, 50, 50, 50, 436, 436, 436,
+ 436, 50, 50, 50, 50, 50, 50, 50, 50, 50,
+ 50, 50, 50, 50, 50, 50, 50, 436, 73, 436,
+ 436, 436, 436, 50, 436, 436, 436, 436, 436, 436,
+ 436, 50, 436, 436, 50, 50, 50, 50, 436, 436
+};
+
+static DfaState st52[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st53[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st54[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 74, 43, 43, 44, 43, 43, 43, 436, 436, 436,
+ 436, 45, 43, 43, 43, 43, 46, 43, 47, 43,
+ 43, 43, 43, 48, 43, 49, 43, 436, 43, 436,
+ 436, 436, 436, 43, 436, 436, 436, 436, 436, 436,
+ 436, 43, 436, 436, 43, 43, 43, 43, 436, 436
+};
+
+static DfaState st55[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 50, 50, 50, 50, 50, 50, 50, 436, 436, 436,
+ 436, 75, 50, 50, 50, 50, 50, 50, 50, 50,
+ 50, 50, 50, 50, 50, 50, 50, 436, 50, 436,
+ 436, 436, 436, 50, 436, 436, 436, 436, 436, 436,
+ 436, 50, 436, 436, 50, 50, 50, 50, 436, 436
+};
+
+static DfaState st56[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 56, 56, 56, 56, 56, 56, 56, 436, 436, 436,
+ 436, 56, 56, 56, 56, 56, 56, 56, 56, 56,
+ 56, 56, 56, 56, 56, 56, 56, 436, 56, 436,
+ 436, 436, 436, 56, 436, 436, 436, 436, 436, 436,
+ 436, 56, 436, 436, 56, 56, 56, 56, 436, 436
+};
+
+static DfaState st57[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 50, 50, 50, 50, 50, 50, 50, 436, 436, 436,
+ 436, 50, 50, 50, 50, 50, 50, 50, 50, 50,
+ 50, 50, 50, 50, 50, 76, 50, 436, 50, 436,
+ 436, 436, 436, 50, 436, 436, 436, 436, 436, 436,
+ 436, 50, 436, 436, 50, 50, 50, 50, 436, 436
+};
+
+static DfaState st58[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 50, 50, 50, 50, 50, 50, 50, 436, 436, 436,
+ 436, 50, 50, 77, 50, 50, 50, 50, 50, 50,
+ 50, 50, 50, 50, 50, 50, 50, 436, 50, 436,
+ 436, 436, 436, 50, 436, 436, 436, 436, 436, 436,
+ 436, 50, 436, 436, 50, 50, 50, 50, 436, 436
+};
+
+static DfaState st59[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 50, 50, 50, 50, 50, 50, 50, 436, 436, 436,
+ 436, 50, 50, 50, 50, 50, 50, 50, 78, 50,
+ 50, 50, 50, 50, 50, 50, 50, 436, 50, 436,
+ 436, 436, 436, 50, 436, 436, 436, 436, 436, 436,
+ 436, 50, 436, 436, 50, 50, 50, 50, 436, 436
+};
+
+static DfaState st60[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st61[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st62[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st63[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 56, 56, 56, 56, 56, 56, 56, 436, 436, 436,
+ 436, 56, 56, 56, 56, 56, 56, 56, 56, 56,
+ 56, 56, 56, 56, 56, 56, 56, 436, 56, 436,
+ 436, 436, 436, 56, 436, 436, 79, 436, 436, 436,
+ 436, 56, 436, 436, 56, 56, 56, 56, 436, 436
+};
+
+static DfaState st64[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 43, 43, 80, 43, 43, 43, 43, 436, 436, 436,
+ 436, 43, 43, 43, 43, 43, 43, 43, 43, 43,
+ 43, 43, 43, 43, 43, 43, 43, 436, 43, 436,
+ 436, 436, 436, 43, 436, 436, 436, 436, 436, 436,
+ 436, 43, 436, 436, 43, 43, 43, 43, 436, 436
+};
+
+static DfaState st65[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 43, 43, 43, 43, 43, 43, 43, 436, 436, 436,
+ 436, 43, 43, 43, 43, 43, 43, 43, 43, 43,
+ 43, 43, 43, 43, 43, 43, 43, 436, 43, 436,
+ 436, 436, 436, 81, 436, 436, 436, 436, 436, 436,
+ 436, 43, 436, 436, 43, 43, 43, 43, 436, 436
+};
+
+static DfaState st66[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 43, 43, 43, 43, 43, 43, 43, 436, 436, 436,
+ 436, 43, 82, 43, 43, 43, 43, 43, 43, 43,
+ 43, 43, 43, 43, 43, 43, 43, 436, 43, 436,
+ 436, 436, 436, 43, 436, 436, 436, 436, 436, 436,
+ 436, 43, 436, 436, 43, 43, 43, 43, 436, 436
+};
+
+static DfaState st67[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 43, 43, 43, 83, 43, 43, 43, 436, 436, 436,
+ 436, 43, 43, 84, 43, 43, 43, 43, 43, 43,
+ 43, 43, 43, 43, 43, 43, 43, 436, 43, 436,
+ 436, 436, 436, 43, 436, 436, 436, 436, 436, 436,
+ 436, 43, 436, 436, 43, 43, 43, 43, 436, 436
+};
+
+static DfaState st68[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 43, 43, 43, 43, 43, 43, 43, 436, 436, 436,
+ 436, 43, 85, 43, 43, 43, 43, 43, 43, 43,
+ 43, 43, 43, 43, 43, 43, 43, 436, 43, 436,
+ 436, 436, 436, 43, 436, 436, 436, 436, 436, 436,
+ 436, 43, 436, 436, 43, 43, 43, 43, 436, 436
+};
+
+static DfaState st69[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 43, 43, 43, 43, 43, 43, 43, 436, 436, 436,
+ 436, 43, 86, 43, 43, 43, 43, 43, 43, 43,
+ 43, 43, 43, 43, 43, 43, 43, 436, 43, 436,
+ 436, 436, 436, 43, 436, 436, 436, 436, 436, 436,
+ 436, 43, 436, 436, 43, 43, 43, 43, 436, 436
+};
+
+static DfaState st70[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 43, 43, 43, 43, 43, 43, 43, 436, 436, 436,
+ 436, 43, 43, 43, 43, 43, 43, 43, 43, 43,
+ 43, 43, 43, 43, 43, 43, 87, 436, 43, 436,
+ 436, 436, 436, 43, 436, 436, 436, 436, 436, 436,
+ 436, 43, 436, 436, 43, 43, 43, 43, 436, 436
+};
+
+static DfaState st71[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 43, 43, 43, 43, 43, 43, 43, 436, 436, 436,
+ 436, 43, 43, 88, 43, 43, 43, 43, 43, 43,
+ 43, 43, 43, 43, 43, 43, 43, 436, 43, 436,
+ 436, 436, 436, 43, 436, 436, 436, 436, 436, 436,
+ 436, 43, 436, 436, 43, 43, 43, 43, 436, 436
+};
+
+static DfaState st72[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 43, 43, 43, 43, 43, 43, 43, 436, 436, 436,
+ 436, 43, 89, 43, 43, 43, 43, 43, 43, 43,
+ 43, 43, 43, 43, 43, 43, 43, 436, 43, 436,
+ 436, 436, 436, 43, 436, 436, 436, 436, 436, 436,
+ 436, 43, 436, 436, 43, 43, 43, 43, 436, 436
+};
+
+static DfaState st73[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 50, 50, 50, 90, 50, 50, 50, 436, 436, 436,
+ 436, 50, 50, 50, 50, 50, 50, 50, 50, 50,
+ 50, 50, 50, 50, 50, 50, 50, 436, 50, 436,
+ 436, 436, 436, 50, 436, 436, 436, 436, 436, 436,
+ 436, 50, 436, 436, 50, 50, 50, 50, 436, 436
+};
+
+static DfaState st74[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 43, 43, 43, 65, 43, 43, 43, 436, 436, 436,
+ 436, 43, 43, 43, 43, 43, 43, 43, 43, 43,
+ 43, 43, 43, 43, 43, 43, 43, 436, 43, 436,
+ 436, 436, 436, 43, 436, 436, 436, 436, 436, 436,
+ 436, 43, 436, 436, 43, 43, 43, 43, 436, 436
+};
+
+static DfaState st75[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 50, 50, 50, 50, 50, 50, 50, 436, 436, 436,
+ 436, 50, 91, 50, 50, 50, 50, 50, 50, 50,
+ 50, 50, 50, 50, 50, 50, 50, 436, 50, 436,
+ 436, 436, 436, 50, 436, 436, 436, 436, 436, 436,
+ 436, 50, 436, 436, 50, 50, 50, 50, 436, 436
+};
+
+static DfaState st76[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 50, 50, 50, 50, 50, 50, 50, 436, 436, 436,
+ 436, 50, 50, 92, 50, 50, 50, 50, 50, 50,
+ 50, 50, 50, 50, 50, 50, 50, 436, 50, 436,
+ 436, 436, 436, 50, 436, 436, 436, 436, 436, 436,
+ 436, 50, 436, 436, 50, 50, 50, 50, 436, 436
+};
+
+static DfaState st77[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 50, 50, 50, 50, 50, 50, 50, 436, 436, 436,
+ 436, 50, 50, 50, 50, 50, 50, 93, 50, 50,
+ 50, 50, 50, 50, 50, 50, 50, 436, 50, 436,
+ 436, 436, 436, 50, 436, 436, 436, 436, 436, 436,
+ 436, 50, 436, 436, 50, 50, 50, 50, 436, 436
+};
+
+static DfaState st78[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 50, 50, 50, 50, 50, 50, 50, 436, 436, 436,
+ 436, 50, 50, 50, 50, 50, 50, 50, 50, 50,
+ 50, 50, 50, 50, 50, 50, 50, 436, 94, 436,
+ 436, 436, 436, 50, 436, 436, 436, 436, 436, 436,
+ 436, 50, 436, 436, 50, 50, 50, 50, 436, 436
+};
+
+static DfaState st79[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 95, 96, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st80[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 43, 43, 43, 97, 43, 43, 43, 436, 436, 436,
+ 436, 43, 43, 43, 43, 43, 43, 43, 43, 43,
+ 43, 43, 43, 43, 43, 43, 43, 436, 43, 436,
+ 436, 436, 436, 43, 436, 436, 436, 436, 436, 436,
+ 436, 43, 436, 436, 43, 43, 43, 43, 436, 436
+};
+
+static DfaState st81[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 43, 43, 43, 43, 43, 43, 43, 436, 436, 436,
+ 436, 98, 43, 99, 43, 100, 43, 43, 43, 43,
+ 43, 43, 43, 43, 43, 43, 43, 436, 101, 436,
+ 436, 436, 436, 43, 436, 436, 436, 436, 436, 436,
+ 436, 43, 436, 436, 43, 43, 43, 43, 436, 436
+};
+
+static DfaState st82[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 43, 43, 43, 43, 43, 43, 43, 436, 436, 436,
+ 436, 43, 43, 43, 43, 43, 43, 43, 43, 43,
+ 43, 43, 43, 43, 43, 43, 43, 436, 102, 436,
+ 436, 436, 436, 43, 436, 436, 436, 436, 436, 436,
+ 436, 43, 436, 436, 43, 43, 43, 43, 436, 436
+};
+
+static DfaState st83[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 43, 43, 43, 43, 43, 43, 43, 436, 436, 436,
+ 436, 43, 43, 43, 43, 43, 43, 43, 43, 43,
+ 43, 43, 43, 43, 103, 43, 43, 436, 43, 436,
+ 436, 436, 436, 43, 436, 436, 436, 436, 436, 436,
+ 436, 43, 436, 436, 43, 43, 43, 43, 436, 436
+};
+
+static DfaState st84[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 43, 43, 43, 43, 43, 43, 43, 436, 436, 436,
+ 436, 43, 43, 43, 104, 43, 43, 43, 43, 43,
+ 43, 43, 43, 43, 43, 43, 43, 436, 43, 436,
+ 436, 436, 436, 43, 436, 436, 436, 436, 436, 436,
+ 436, 43, 436, 436, 43, 43, 43, 43, 436, 436
+};
+
+static DfaState st85[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 43, 43, 43, 43, 43, 43, 43, 436, 436, 436,
+ 436, 43, 43, 43, 43, 43, 43, 105, 43, 43,
+ 43, 43, 43, 43, 43, 43, 43, 436, 43, 436,
+ 436, 436, 436, 43, 436, 436, 436, 436, 436, 436,
+ 436, 43, 436, 436, 43, 43, 43, 43, 436, 436
+};
+
+static DfaState st86[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 43, 43, 43, 43, 43, 43, 43, 436, 436, 436,
+ 436, 43, 43, 43, 43, 43, 43, 106, 43, 43,
+ 43, 43, 43, 43, 43, 43, 43, 436, 43, 436,
+ 436, 436, 436, 43, 436, 436, 436, 436, 436, 436,
+ 436, 43, 436, 436, 43, 43, 43, 43, 436, 436
+};
+
+static DfaState st87[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 43, 43, 43, 107, 43, 43, 43, 436, 436, 436,
+ 436, 43, 43, 43, 43, 43, 43, 43, 43, 43,
+ 43, 43, 43, 43, 108, 43, 43, 436, 109, 436,
+ 436, 436, 436, 43, 436, 436, 436, 436, 436, 436,
+ 436, 43, 436, 436, 43, 43, 43, 43, 436, 436
+};
+
+static DfaState st88[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 43, 43, 43, 43, 43, 43, 43, 436, 436, 436,
+ 436, 43, 43, 43, 43, 43, 43, 43, 43, 43,
+ 43, 43, 43, 43, 110, 43, 43, 436, 43, 436,
+ 436, 436, 436, 43, 436, 436, 436, 436, 436, 436,
+ 436, 43, 436, 436, 43, 43, 43, 43, 436, 436
+};
+
+static DfaState st89[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 43, 43, 43, 43, 43, 43, 43, 436, 436, 436,
+ 436, 43, 43, 43, 43, 43, 43, 111, 43, 43,
+ 43, 43, 43, 43, 43, 43, 43, 436, 43, 436,
+ 436, 436, 436, 43, 436, 436, 436, 436, 436, 436,
+ 436, 43, 436, 436, 43, 43, 43, 43, 436, 436
+};
+
+static DfaState st90[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 50, 50, 50, 50, 50, 50, 50, 436, 436, 436,
+ 436, 112, 50, 50, 50, 50, 50, 50, 50, 50,
+ 50, 50, 50, 50, 50, 50, 50, 436, 50, 436,
+ 436, 436, 436, 50, 436, 436, 436, 436, 436, 436,
+ 436, 50, 436, 436, 50, 50, 50, 50, 436, 436
+};
+
+static DfaState st91[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 50, 50, 50, 50, 50, 50, 50, 436, 436, 436,
+ 436, 50, 50, 50, 50, 50, 50, 50, 50, 50,
+ 50, 50, 113, 50, 50, 50, 50, 436, 50, 436,
+ 436, 436, 436, 50, 436, 436, 436, 436, 436, 436,
+ 436, 50, 436, 436, 50, 50, 50, 50, 436, 436
+};
+
+static DfaState st92[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 50, 50, 50, 50, 50, 50, 50, 436, 436, 436,
+ 436, 50, 50, 50, 50, 50, 50, 50, 50, 50,
+ 50, 50, 50, 50, 50, 50, 50, 436, 50, 436,
+ 436, 436, 436, 50, 436, 436, 436, 436, 436, 436,
+ 436, 50, 436, 436, 114, 50, 50, 50, 436, 436
+};
+
+static DfaState st93[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 50, 50, 50, 50, 50, 50, 50, 436, 436, 436,
+ 436, 50, 50, 50, 50, 50, 50, 115, 50, 50,
+ 50, 50, 50, 50, 50, 50, 50, 436, 50, 436,
+ 436, 436, 436, 50, 436, 436, 436, 436, 436, 436,
+ 436, 50, 436, 436, 50, 50, 50, 50, 436, 436
+};
+
+static DfaState st94[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 50, 50, 50, 50, 50, 50, 50, 436, 436, 436,
+ 436, 50, 50, 50, 50, 50, 50, 50, 50, 50,
+ 50, 50, 50, 116, 50, 50, 50, 436, 50, 436,
+ 436, 436, 436, 50, 436, 436, 436, 436, 436, 436,
+ 436, 50, 436, 436, 50, 50, 50, 50, 436, 436
+};
+
+static DfaState st95[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 117, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st96[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 118, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st97[60] = {
+ 436, 119, 120, 121, 122, 122, 122, 122, 122, 122,
+ 123, 123, 123, 123, 124, 124, 124, 122, 122, 122,
+ 122, 123, 123, 123, 123, 123, 123, 123, 123, 123,
+ 123, 123, 123, 123, 123, 123, 123, 122, 123, 122,
+ 122, 122, 122, 123, 122, 122, 122, 122, 122, 122,
+ 122, 123, 122, 122, 123, 123, 123, 123, 122, 436
+};
+
+static DfaState st98[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 43, 43, 43, 43, 43, 43, 43, 436, 436, 436,
+ 436, 43, 125, 43, 43, 43, 43, 43, 43, 43,
+ 43, 43, 43, 43, 43, 43, 43, 436, 43, 436,
+ 436, 436, 436, 43, 436, 436, 436, 436, 436, 436,
+ 436, 43, 436, 436, 43, 43, 43, 43, 436, 436
+};
+
+static DfaState st99[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 43, 43, 43, 43, 43, 43, 43, 436, 436, 436,
+ 436, 43, 43, 43, 43, 43, 43, 43, 43, 43,
+ 43, 43, 43, 43, 43, 43, 43, 436, 126, 436,
+ 436, 436, 436, 43, 436, 436, 436, 436, 436, 436,
+ 436, 43, 436, 436, 43, 43, 43, 43, 436, 436
+};
+
+static DfaState st100[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 43, 43, 43, 127, 43, 43, 43, 436, 436, 436,
+ 436, 43, 43, 43, 43, 43, 43, 43, 43, 43,
+ 43, 43, 43, 43, 43, 43, 43, 436, 43, 436,
+ 436, 436, 436, 43, 436, 436, 436, 436, 436, 436,
+ 436, 43, 436, 436, 43, 43, 43, 43, 436, 436
+};
+
+static DfaState st101[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 128, 43, 43, 43, 43, 43, 43, 436, 436, 436,
+ 436, 43, 43, 43, 43, 43, 43, 43, 43, 43,
+ 43, 43, 43, 43, 43, 43, 43, 436, 43, 436,
+ 436, 436, 436, 43, 436, 436, 436, 436, 436, 436,
+ 436, 43, 436, 436, 43, 43, 43, 43, 436, 436
+};
+
+static DfaState st102[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 129, 43, 43, 43, 43, 43, 43, 436, 436, 436,
+ 436, 43, 43, 43, 43, 43, 43, 43, 43, 43,
+ 43, 43, 43, 43, 43, 43, 43, 436, 43, 436,
+ 436, 436, 436, 43, 436, 436, 436, 436, 436, 436,
+ 436, 43, 436, 436, 43, 43, 43, 43, 436, 436
+};
+
+static DfaState st103[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 43, 43, 43, 43, 43, 43, 43, 436, 436, 436,
+ 436, 43, 43, 43, 43, 43, 43, 43, 43, 43,
+ 43, 43, 43, 43, 43, 43, 43, 436, 43, 436,
+ 436, 436, 436, 43, 436, 436, 436, 436, 436, 436,
+ 436, 43, 436, 436, 43, 43, 43, 43, 436, 436
+};
+
+static DfaState st104[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 43, 43, 43, 43, 43, 43, 43, 436, 436, 436,
+ 436, 43, 43, 43, 43, 130, 43, 43, 43, 43,
+ 43, 43, 43, 43, 43, 43, 43, 436, 43, 436,
+ 436, 436, 436, 43, 436, 436, 436, 436, 436, 436,
+ 436, 43, 436, 436, 43, 43, 43, 43, 436, 436
+};
+
+static DfaState st105[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 43, 43, 43, 131, 43, 43, 43, 436, 436, 436,
+ 436, 43, 43, 43, 43, 43, 43, 43, 43, 43,
+ 43, 43, 43, 43, 43, 43, 43, 436, 43, 436,
+ 436, 436, 436, 43, 436, 436, 436, 436, 436, 436,
+ 436, 43, 436, 436, 43, 43, 43, 43, 436, 436
+};
+
+static DfaState st106[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 43, 43, 43, 43, 43, 43, 43, 436, 436, 436,
+ 436, 43, 43, 43, 43, 43, 43, 43, 132, 43,
+ 43, 43, 43, 43, 43, 43, 43, 436, 43, 436,
+ 436, 436, 436, 43, 436, 436, 436, 436, 436, 436,
+ 436, 43, 436, 436, 43, 43, 43, 43, 436, 436
+};
+
+static DfaState st107[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 43, 43, 133, 43, 43, 43, 43, 436, 436, 436,
+ 436, 43, 43, 43, 43, 43, 43, 43, 43, 43,
+ 43, 43, 43, 43, 43, 43, 43, 436, 43, 436,
+ 436, 436, 436, 43, 436, 436, 436, 436, 436, 436,
+ 436, 43, 436, 436, 43, 43, 43, 43, 436, 436
+};
+
+static DfaState st108[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 43, 43, 43, 134, 43, 43, 43, 436, 436, 436,
+ 436, 43, 43, 43, 43, 43, 43, 43, 43, 43,
+ 43, 43, 43, 43, 43, 43, 43, 436, 43, 436,
+ 436, 436, 436, 43, 436, 436, 436, 436, 436, 436,
+ 436, 43, 436, 436, 43, 43, 43, 43, 436, 436
+};
+
+static DfaState st109[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 135, 43, 43, 43, 43, 43, 43, 436, 436, 436,
+ 436, 43, 43, 43, 43, 43, 43, 43, 43, 43,
+ 43, 43, 43, 43, 43, 43, 43, 436, 43, 436,
+ 436, 436, 436, 43, 436, 436, 436, 436, 436, 436,
+ 436, 43, 436, 436, 43, 43, 43, 43, 436, 436
+};
+
+static DfaState st110[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 43, 43, 43, 136, 43, 43, 43, 436, 436, 436,
+ 436, 43, 43, 43, 43, 43, 43, 43, 43, 43,
+ 43, 43, 43, 43, 43, 43, 43, 436, 43, 436,
+ 436, 436, 436, 43, 436, 436, 436, 436, 436, 436,
+ 436, 43, 436, 436, 43, 43, 43, 43, 436, 436
+};
+
+static DfaState st111[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 43, 43, 43, 43, 43, 43, 43, 436, 436, 436,
+ 436, 43, 43, 43, 43, 43, 43, 43, 137, 43,
+ 43, 43, 43, 43, 43, 43, 43, 436, 43, 436,
+ 436, 436, 436, 43, 436, 436, 436, 436, 436, 436,
+ 436, 43, 436, 436, 43, 43, 43, 43, 436, 436
+};
+
+static DfaState st112[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 50, 50, 50, 50, 50, 50, 50, 436, 436, 436,
+ 436, 50, 50, 50, 50, 50, 50, 50, 138, 50,
+ 50, 50, 50, 50, 50, 50, 50, 436, 50, 436,
+ 436, 436, 436, 50, 436, 436, 436, 436, 436, 436,
+ 436, 50, 436, 436, 50, 50, 50, 50, 436, 436
+};
+
+static DfaState st113[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 50, 50, 50, 50, 50, 50, 50, 436, 436, 436,
+ 436, 50, 50, 50, 50, 50, 50, 50, 50, 50,
+ 50, 50, 50, 50, 50, 50, 50, 436, 50, 436,
+ 436, 436, 436, 139, 436, 436, 436, 436, 436, 436,
+ 436, 50, 436, 436, 50, 50, 50, 50, 436, 436
+};
+
+static DfaState st114[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 140, 50, 50, 50, 50, 50, 50, 436, 436, 436,
+ 436, 50, 50, 50, 50, 50, 50, 50, 50, 50,
+ 50, 50, 50, 50, 50, 50, 50, 436, 50, 436,
+ 436, 436, 436, 50, 436, 436, 436, 436, 436, 436,
+ 436, 50, 436, 436, 50, 50, 50, 50, 436, 436
+};
+
+static DfaState st115[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 50, 50, 50, 50, 50, 50, 50, 436, 436, 436,
+ 436, 50, 50, 50, 50, 50, 50, 50, 50, 50,
+ 50, 50, 50, 50, 50, 50, 50, 436, 50, 436,
+ 436, 436, 436, 50, 436, 436, 436, 436, 436, 436,
+ 436, 50, 436, 436, 50, 50, 50, 50, 436, 436
+};
+
+static DfaState st116[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 50, 50, 50, 50, 50, 50, 50, 436, 436, 436,
+ 436, 50, 50, 50, 50, 50, 50, 50, 50, 50,
+ 50, 50, 50, 50, 50, 50, 50, 436, 50, 436,
+ 436, 436, 436, 50, 436, 436, 436, 436, 436, 436,
+ 436, 50, 436, 436, 50, 50, 50, 50, 436, 436
+};
+
+static DfaState st117[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st118[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st119[60] = {
+ 436, 119, 120, 121, 122, 122, 122, 122, 122, 122,
+ 122, 122, 122, 122, 141, 141, 141, 122, 122, 122,
+ 122, 122, 122, 122, 122, 122, 122, 122, 122, 122,
+ 122, 122, 122, 122, 122, 122, 122, 122, 122, 122,
+ 122, 122, 122, 122, 122, 122, 122, 122, 122, 122,
+ 122, 122, 122, 122, 122, 122, 122, 122, 122, 436
+};
+
+static DfaState st120[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st121[60] = {
+ 436, 436, 142, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st122[60] = {
+ 436, 122, 120, 121, 122, 122, 122, 122, 122, 122,
+ 122, 122, 122, 122, 122, 122, 122, 122, 122, 122,
+ 122, 122, 122, 122, 122, 122, 122, 122, 122, 122,
+ 122, 122, 122, 122, 122, 122, 122, 122, 122, 122,
+ 122, 122, 122, 122, 122, 122, 122, 122, 122, 122,
+ 122, 122, 122, 122, 122, 122, 122, 122, 122, 436
+};
+
+static DfaState st123[60] = {
+ 436, 122, 120, 121, 122, 122, 122, 122, 122, 122,
+ 123, 123, 123, 123, 123, 123, 123, 122, 122, 122,
+ 122, 123, 123, 123, 123, 123, 123, 123, 123, 123,
+ 123, 123, 123, 123, 123, 123, 123, 122, 123, 122,
+ 122, 122, 122, 123, 122, 122, 122, 122, 122, 122,
+ 122, 123, 122, 122, 123, 123, 123, 123, 122, 436
+};
+
+static DfaState st124[60] = {
+ 436, 143, 144, 145, 122, 122, 146, 122, 122, 122,
+ 123, 123, 123, 123, 124, 124, 124, 122, 122, 122,
+ 122, 123, 123, 123, 123, 123, 123, 123, 123, 123,
+ 123, 123, 123, 123, 123, 123, 123, 122, 123, 122,
+ 122, 122, 122, 123, 122, 122, 122, 122, 122, 122,
+ 122, 123, 122, 122, 123, 123, 123, 123, 122, 436
+};
+
+static DfaState st125[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 43, 43, 43, 147, 43, 43, 43, 436, 436, 436,
+ 436, 43, 43, 43, 43, 43, 43, 43, 43, 43,
+ 43, 43, 43, 43, 43, 43, 43, 436, 43, 436,
+ 436, 436, 436, 43, 436, 436, 436, 436, 436, 436,
+ 436, 43, 436, 436, 43, 43, 43, 43, 436, 436
+};
+
+static DfaState st126[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 43, 43, 43, 43, 43, 43, 43, 436, 436, 436,
+ 436, 43, 43, 43, 43, 43, 43, 43, 148, 43,
+ 43, 43, 43, 43, 43, 43, 43, 436, 43, 436,
+ 436, 436, 436, 43, 436, 436, 436, 436, 436, 436,
+ 436, 43, 436, 436, 43, 43, 43, 43, 436, 436
+};
+
+static DfaState st127[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 43, 43, 43, 43, 43, 43, 43, 436, 436, 436,
+ 436, 43, 43, 43, 43, 149, 43, 43, 43, 43,
+ 43, 43, 43, 43, 43, 43, 43, 436, 43, 436,
+ 436, 436, 436, 43, 436, 436, 436, 436, 436, 436,
+ 436, 43, 436, 436, 43, 43, 43, 43, 436, 436
+};
+
+static DfaState st128[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 43, 43, 43, 43, 43, 43, 43, 436, 436, 436,
+ 436, 43, 43, 150, 43, 43, 43, 43, 43, 43,
+ 43, 43, 43, 43, 43, 43, 43, 436, 43, 436,
+ 436, 436, 436, 43, 436, 436, 436, 436, 436, 436,
+ 436, 43, 436, 436, 43, 43, 43, 43, 436, 436
+};
+
+static DfaState st129[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 43, 43, 43, 43, 43, 43, 43, 436, 436, 436,
+ 436, 43, 43, 151, 43, 43, 43, 43, 43, 43,
+ 43, 43, 43, 43, 43, 43, 43, 436, 43, 436,
+ 436, 436, 436, 43, 436, 436, 436, 436, 436, 436,
+ 436, 43, 436, 436, 43, 43, 43, 43, 436, 436
+};
+
+static DfaState st130[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 43, 43, 43, 43, 43, 43, 43, 436, 436, 436,
+ 436, 43, 43, 152, 43, 43, 43, 43, 43, 43,
+ 43, 43, 43, 43, 43, 43, 43, 436, 43, 436,
+ 436, 436, 436, 43, 436, 436, 436, 436, 436, 436,
+ 436, 43, 436, 436, 43, 43, 43, 43, 436, 436
+};
+
+static DfaState st131[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 43, 43, 43, 43, 43, 43, 43, 436, 436, 436,
+ 436, 43, 153, 43, 43, 43, 43, 43, 43, 43,
+ 43, 43, 43, 43, 43, 43, 43, 436, 43, 436,
+ 436, 436, 436, 43, 436, 436, 436, 436, 436, 436,
+ 436, 43, 436, 436, 43, 43, 43, 43, 436, 436
+};
+
+static DfaState st132[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 43, 43, 43, 43, 43, 43, 43, 436, 436, 436,
+ 436, 43, 43, 43, 43, 43, 43, 43, 43, 154,
+ 43, 43, 43, 43, 43, 43, 43, 436, 43, 436,
+ 436, 436, 436, 43, 436, 436, 436, 436, 436, 436,
+ 436, 43, 436, 436, 43, 43, 43, 43, 436, 436
+};
+
+static DfaState st133[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 43, 43, 43, 43, 43, 43, 43, 436, 436, 436,
+ 436, 43, 43, 43, 43, 43, 43, 43, 43, 43,
+ 43, 43, 43, 43, 43, 43, 43, 436, 43, 436,
+ 436, 436, 436, 43, 436, 436, 436, 436, 436, 436,
+ 436, 43, 436, 436, 43, 43, 43, 43, 436, 436
+};
+
+static DfaState st134[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 43, 43, 43, 43, 43, 43, 43, 436, 436, 436,
+ 436, 43, 43, 43, 43, 43, 43, 43, 43, 43,
+ 43, 43, 43, 43, 43, 155, 43, 436, 43, 436,
+ 436, 436, 436, 43, 436, 436, 436, 436, 436, 436,
+ 436, 43, 436, 436, 43, 43, 43, 43, 436, 436
+};
+
+static DfaState st135[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 43, 43, 43, 43, 43, 43, 43, 436, 436, 436,
+ 436, 43, 43, 156, 43, 43, 43, 43, 43, 43,
+ 43, 43, 43, 43, 43, 43, 43, 436, 43, 436,
+ 436, 436, 436, 43, 436, 436, 436, 436, 436, 436,
+ 436, 43, 436, 436, 43, 43, 43, 43, 436, 436
+};
+
+static DfaState st136[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 43, 43, 43, 43, 43, 43, 43, 436, 436, 436,
+ 436, 43, 157, 43, 43, 43, 43, 43, 43, 43,
+ 43, 43, 43, 43, 43, 43, 43, 436, 43, 436,
+ 436, 436, 436, 43, 436, 436, 436, 436, 436, 436,
+ 436, 43, 436, 436, 43, 43, 43, 43, 436, 436
+};
+
+static DfaState st137[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 43, 43, 43, 43, 43, 43, 43, 436, 436, 436,
+ 436, 43, 43, 43, 43, 43, 43, 43, 43, 43,
+ 43, 43, 43, 43, 43, 43, 43, 436, 43, 436,
+ 436, 436, 436, 43, 436, 436, 436, 436, 436, 436,
+ 436, 43, 436, 436, 43, 43, 43, 43, 436, 436
+};
+
+static DfaState st138[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 50, 158, 50, 50, 50, 50, 50, 436, 436, 436,
+ 436, 50, 50, 50, 50, 50, 50, 50, 50, 50,
+ 50, 50, 50, 50, 50, 50, 50, 436, 50, 436,
+ 436, 436, 436, 50, 436, 436, 436, 436, 436, 436,
+ 436, 50, 436, 436, 50, 50, 50, 50, 436, 436
+};
+
+static DfaState st139[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 50, 50, 50, 50, 50, 50, 50, 436, 436, 436,
+ 436, 50, 50, 50, 50, 50, 50, 50, 50, 50,
+ 50, 50, 50, 50, 50, 50, 50, 436, 50, 436,
+ 436, 436, 436, 50, 436, 436, 436, 436, 436, 436,
+ 436, 50, 436, 436, 50, 50, 50, 50, 436, 436
+};
+
+static DfaState st140[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 50, 50, 50, 50, 50, 50, 50, 436, 436, 436,
+ 436, 50, 50, 50, 50, 50, 50, 50, 159, 50,
+ 50, 50, 50, 50, 50, 50, 50, 436, 50, 436,
+ 436, 436, 436, 50, 436, 436, 436, 436, 436, 436,
+ 436, 50, 436, 436, 50, 50, 50, 50, 436, 436
+};
+
+static DfaState st141[60] = {
+ 436, 143, 144, 145, 122, 122, 146, 122, 122, 122,
+ 122, 122, 122, 122, 141, 141, 141, 122, 122, 122,
+ 122, 122, 122, 122, 122, 122, 122, 122, 122, 122,
+ 122, 122, 122, 122, 122, 122, 122, 122, 122, 122,
+ 122, 122, 122, 122, 122, 122, 122, 122, 122, 122,
+ 122, 122, 122, 122, 122, 122, 122, 122, 122, 436
+};
+
+static DfaState st142[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st143[60] = {
+ 436, 143, 120, 121, 122, 122, 146, 122, 122, 122,
+ 122, 122, 122, 122, 122, 122, 122, 122, 122, 122,
+ 122, 122, 122, 122, 122, 122, 122, 122, 122, 122,
+ 122, 122, 122, 122, 122, 122, 122, 122, 122, 122,
+ 122, 122, 122, 122, 122, 122, 122, 122, 122, 122,
+ 122, 122, 122, 122, 122, 122, 122, 122, 122, 436
+};
+
+static DfaState st144[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st145[60] = {
+ 436, 436, 160, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st146[60] = {
+ 436, 161, 162, 163, 161, 161, 122, 161, 161, 161,
+ 161, 161, 161, 161, 161, 161, 161, 161, 161, 161,
+ 161, 161, 161, 161, 161, 161, 161, 161, 161, 161,
+ 161, 161, 161, 161, 161, 161, 161, 161, 161, 161,
+ 161, 161, 161, 161, 161, 161, 161, 161, 161, 161,
+ 161, 161, 161, 161, 161, 161, 161, 161, 161, 436
+};
+
+static DfaState st147[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 43, 43, 43, 43, 43, 43, 43, 436, 436, 436,
+ 436, 43, 43, 43, 43, 43, 43, 43, 43, 43,
+ 43, 43, 43, 43, 43, 164, 43, 436, 43, 436,
+ 436, 436, 436, 43, 436, 436, 436, 436, 436, 436,
+ 436, 43, 436, 436, 43, 43, 43, 43, 436, 436
+};
+
+static DfaState st148[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 43, 165, 43, 43, 43, 43, 43, 436, 436, 436,
+ 436, 43, 43, 43, 43, 43, 43, 43, 43, 43,
+ 43, 43, 43, 43, 43, 43, 43, 436, 43, 436,
+ 436, 436, 436, 43, 436, 436, 436, 436, 436, 436,
+ 436, 43, 436, 436, 43, 43, 43, 43, 436, 436
+};
+
+static DfaState st149[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 43, 43, 43, 43, 43, 43, 43, 436, 436, 436,
+ 436, 43, 43, 43, 43, 43, 43, 43, 43, 43,
+ 43, 166, 43, 43, 43, 43, 43, 436, 43, 436,
+ 436, 436, 436, 43, 436, 436, 436, 436, 436, 436,
+ 436, 43, 436, 436, 43, 43, 43, 43, 436, 436
+};
+
+static DfaState st150[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 43, 43, 43, 43, 43, 43, 43, 436, 436, 436,
+ 436, 43, 43, 43, 43, 43, 43, 167, 43, 43,
+ 43, 43, 43, 43, 43, 43, 43, 436, 43, 436,
+ 436, 436, 436, 43, 436, 436, 436, 436, 436, 436,
+ 436, 43, 436, 436, 43, 43, 43, 43, 436, 436
+};
+
+static DfaState st151[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 43, 43, 43, 43, 43, 43, 43, 436, 436, 436,
+ 436, 43, 43, 43, 43, 43, 43, 168, 43, 43,
+ 43, 43, 43, 43, 43, 43, 43, 436, 43, 436,
+ 436, 436, 436, 43, 436, 436, 436, 436, 436, 436,
+ 436, 43, 436, 436, 43, 43, 43, 43, 436, 436
+};
+
+static DfaState st152[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 43, 43, 43, 43, 43, 43, 43, 436, 436, 436,
+ 436, 43, 43, 43, 43, 43, 43, 43, 43, 43,
+ 43, 43, 43, 43, 43, 43, 43, 436, 43, 436,
+ 436, 436, 436, 43, 436, 436, 436, 436, 436, 436,
+ 436, 43, 436, 436, 43, 43, 43, 43, 436, 436
+};
+
+static DfaState st153[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 43, 43, 43, 43, 43, 43, 43, 436, 436, 436,
+ 436, 43, 43, 43, 43, 43, 43, 43, 43, 43,
+ 43, 43, 43, 43, 43, 43, 43, 436, 43, 436,
+ 436, 436, 436, 43, 436, 436, 436, 436, 436, 436,
+ 436, 43, 436, 436, 43, 43, 43, 43, 436, 436
+};
+
+static DfaState st154[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 43, 43, 43, 169, 43, 43, 43, 436, 436, 436,
+ 436, 43, 43, 43, 43, 43, 43, 43, 43, 43,
+ 43, 43, 43, 43, 43, 43, 43, 436, 43, 436,
+ 436, 436, 436, 43, 436, 436, 436, 436, 436, 436,
+ 436, 43, 436, 436, 43, 43, 43, 43, 436, 436
+};
+
+static DfaState st155[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 43, 43, 43, 43, 43, 43, 43, 436, 436, 436,
+ 436, 43, 43, 43, 43, 43, 43, 170, 43, 43,
+ 43, 43, 43, 43, 43, 43, 43, 436, 43, 436,
+ 436, 436, 436, 43, 436, 436, 436, 436, 436, 436,
+ 436, 43, 436, 436, 43, 43, 43, 43, 436, 436
+};
+
+static DfaState st156[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 43, 43, 43, 43, 43, 43, 43, 436, 436, 436,
+ 436, 43, 43, 43, 43, 43, 43, 171, 43, 43,
+ 43, 43, 43, 43, 43, 43, 43, 436, 43, 436,
+ 436, 436, 436, 43, 436, 436, 436, 436, 436, 436,
+ 436, 43, 436, 436, 43, 43, 43, 43, 436, 436
+};
+
+static DfaState st157[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 43, 43, 43, 43, 43, 43, 43, 436, 436, 436,
+ 436, 43, 43, 43, 43, 43, 43, 43, 43, 43,
+ 43, 43, 43, 43, 43, 43, 43, 436, 43, 436,
+ 436, 436, 436, 43, 436, 436, 436, 436, 436, 436,
+ 436, 43, 436, 436, 43, 43, 43, 43, 436, 436
+};
+
+static DfaState st158[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 50, 50, 50, 50, 50, 50, 50, 436, 436, 436,
+ 436, 50, 50, 50, 50, 50, 50, 50, 50, 50,
+ 50, 50, 172, 50, 50, 50, 50, 436, 50, 436,
+ 436, 436, 436, 50, 436, 436, 436, 436, 436, 436,
+ 436, 50, 436, 436, 50, 50, 50, 50, 436, 436
+};
+
+static DfaState st159[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 50, 50, 50, 50, 50, 50, 50, 436, 436, 436,
+ 436, 50, 50, 50, 50, 50, 50, 50, 50, 50,
+ 50, 50, 50, 50, 50, 50, 50, 436, 50, 436,
+ 436, 436, 436, 50, 436, 436, 436, 436, 436, 436,
+ 436, 50, 436, 436, 50, 50, 50, 50, 436, 436
+};
+
+static DfaState st160[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st161[60] = {
+ 436, 161, 162, 163, 161, 161, 173, 161, 161, 161,
+ 161, 161, 161, 161, 161, 161, 161, 161, 161, 161,
+ 161, 161, 161, 161, 161, 161, 161, 161, 161, 161,
+ 161, 161, 161, 161, 161, 161, 161, 161, 161, 161,
+ 161, 161, 161, 161, 161, 161, 161, 161, 161, 161,
+ 161, 161, 161, 161, 161, 161, 161, 161, 161, 436
+};
+
+static DfaState st162[60] = {
+ 436, 174, 174, 174, 174, 174, 175, 174, 174, 174,
+ 174, 174, 174, 174, 174, 174, 174, 174, 174, 174,
+ 174, 174, 174, 174, 174, 174, 174, 174, 174, 174,
+ 174, 174, 174, 174, 174, 174, 174, 174, 174, 174,
+ 174, 174, 174, 174, 174, 174, 174, 174, 174, 174,
+ 174, 174, 174, 174, 174, 174, 174, 174, 174, 436
+};
+
+static DfaState st163[60] = {
+ 436, 174, 176, 174, 174, 174, 175, 174, 174, 174,
+ 174, 174, 174, 174, 174, 174, 174, 174, 174, 174,
+ 174, 174, 174, 174, 174, 174, 174, 174, 174, 174,
+ 174, 174, 174, 174, 174, 174, 174, 174, 174, 174,
+ 174, 174, 174, 174, 174, 174, 174, 174, 174, 174,
+ 174, 174, 174, 174, 174, 174, 174, 174, 174, 436
+};
+
+static DfaState st164[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 43, 177, 43, 43, 43, 43, 43, 436, 436, 436,
+ 436, 43, 43, 43, 43, 43, 43, 43, 43, 43,
+ 43, 43, 43, 43, 43, 43, 43, 436, 43, 436,
+ 436, 436, 436, 43, 436, 436, 436, 436, 436, 436,
+ 436, 43, 436, 436, 43, 43, 43, 43, 436, 436
+};
+
+static DfaState st165[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 43, 43, 43, 43, 43, 43, 43, 436, 436, 436,
+ 436, 43, 43, 43, 43, 43, 43, 43, 43, 43,
+ 43, 43, 178, 43, 43, 43, 43, 436, 43, 436,
+ 436, 436, 436, 43, 436, 436, 436, 436, 436, 436,
+ 436, 43, 436, 436, 43, 43, 43, 43, 436, 436
+};
+
+static DfaState st166[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 43, 43, 43, 179, 43, 43, 43, 436, 436, 436,
+ 436, 43, 43, 43, 43, 43, 43, 43, 43, 43,
+ 43, 43, 43, 43, 43, 43, 43, 436, 43, 436,
+ 436, 436, 436, 43, 436, 436, 436, 436, 436, 436,
+ 436, 43, 436, 436, 43, 43, 43, 43, 436, 436
+};
+
+static DfaState st167[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 43, 43, 43, 43, 43, 43, 43, 436, 436, 436,
+ 436, 43, 43, 43, 43, 43, 43, 180, 43, 43,
+ 43, 43, 43, 43, 43, 43, 43, 436, 43, 436,
+ 436, 436, 436, 43, 436, 436, 436, 436, 436, 436,
+ 436, 43, 436, 436, 43, 43, 43, 43, 436, 436
+};
+
+static DfaState st168[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 43, 43, 43, 43, 43, 43, 43, 436, 436, 436,
+ 436, 43, 43, 43, 43, 43, 43, 181, 43, 43,
+ 43, 43, 43, 43, 43, 43, 43, 436, 43, 436,
+ 436, 436, 436, 43, 436, 436, 436, 436, 436, 436,
+ 436, 43, 436, 436, 43, 43, 43, 43, 436, 436
+};
+
+static DfaState st169[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 43, 43, 43, 43, 43, 43, 43, 436, 436, 436,
+ 436, 43, 43, 43, 43, 43, 43, 43, 182, 43,
+ 43, 43, 43, 43, 43, 43, 43, 436, 43, 436,
+ 436, 436, 436, 43, 436, 436, 436, 436, 436, 436,
+ 436, 43, 436, 436, 43, 43, 43, 43, 436, 436
+};
+
+static DfaState st170[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 43, 43, 43, 43, 43, 43, 43, 436, 436, 436,
+ 436, 43, 43, 43, 43, 43, 43, 43, 43, 43,
+ 43, 43, 43, 43, 43, 43, 43, 436, 43, 436,
+ 436, 436, 436, 43, 436, 436, 436, 436, 436, 436,
+ 436, 43, 436, 436, 43, 43, 43, 43, 436, 436
+};
+
+static DfaState st171[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 43, 43, 43, 43, 43, 43, 43, 436, 436, 436,
+ 436, 43, 43, 43, 43, 43, 43, 183, 43, 43,
+ 43, 43, 43, 43, 43, 43, 43, 436, 43, 436,
+ 436, 436, 436, 43, 436, 436, 436, 436, 436, 436,
+ 436, 43, 436, 436, 43, 43, 43, 43, 436, 436
+};
+
+static DfaState st172[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 50, 50, 184, 50, 50, 50, 50, 436, 436, 436,
+ 436, 50, 50, 50, 50, 50, 50, 50, 50, 50,
+ 50, 50, 50, 50, 50, 50, 50, 436, 50, 436,
+ 436, 436, 436, 50, 436, 436, 436, 436, 436, 436,
+ 436, 50, 436, 436, 50, 50, 50, 50, 436, 436
+};
+
+static DfaState st173[60] = {
+ 436, 185, 144, 145, 122, 122, 122, 122, 122, 122,
+ 122, 122, 122, 122, 186, 186, 186, 122, 122, 122,
+ 122, 122, 122, 122, 122, 122, 122, 122, 122, 122,
+ 122, 122, 122, 122, 122, 122, 122, 122, 122, 122,
+ 122, 122, 122, 122, 122, 122, 122, 122, 122, 122,
+ 122, 122, 122, 122, 122, 122, 122, 122, 122, 436
+};
+
+static DfaState st174[60] = {
+ 436, 174, 174, 174, 174, 174, 175, 174, 174, 174,
+ 174, 174, 174, 174, 174, 174, 174, 174, 174, 174,
+ 174, 174, 174, 174, 174, 174, 174, 174, 174, 174,
+ 174, 174, 174, 174, 174, 174, 174, 174, 174, 174,
+ 174, 174, 174, 174, 174, 174, 174, 174, 174, 174,
+ 174, 174, 174, 174, 174, 174, 174, 174, 174, 436
+};
+
+static DfaState st175[60] = {
+ 436, 187, 188, 189, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 190, 190, 190, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st176[60] = {
+ 436, 174, 174, 174, 174, 174, 175, 174, 174, 174,
+ 174, 174, 174, 174, 174, 174, 174, 174, 174, 174,
+ 174, 174, 174, 174, 174, 174, 174, 174, 174, 174,
+ 174, 174, 174, 174, 174, 174, 174, 174, 174, 174,
+ 174, 174, 174, 174, 174, 174, 174, 174, 174, 174,
+ 174, 174, 174, 174, 174, 174, 174, 174, 174, 436
+};
+
+static DfaState st177[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 43, 43, 43, 43, 43, 43, 43, 436, 436, 436,
+ 436, 43, 43, 43, 43, 43, 43, 43, 43, 43,
+ 43, 43, 43, 43, 43, 43, 43, 436, 43, 436,
+ 436, 436, 436, 191, 436, 436, 436, 436, 436, 436,
+ 436, 43, 436, 436, 43, 43, 43, 43, 436, 436
+};
+
+static DfaState st178[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 43, 43, 192, 43, 43, 43, 43, 436, 436, 436,
+ 436, 43, 43, 43, 43, 43, 43, 43, 43, 43,
+ 43, 43, 43, 43, 43, 43, 43, 436, 43, 436,
+ 436, 436, 436, 43, 436, 436, 436, 436, 436, 436,
+ 436, 43, 436, 436, 43, 43, 43, 43, 436, 436
+};
+
+static DfaState st179[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 43, 43, 43, 43, 43, 43, 43, 436, 436, 436,
+ 436, 43, 193, 43, 43, 43, 43, 43, 43, 43,
+ 43, 43, 43, 43, 43, 43, 43, 436, 43, 436,
+ 436, 436, 436, 43, 436, 436, 436, 436, 436, 436,
+ 436, 43, 436, 436, 43, 43, 43, 43, 436, 436
+};
+
+static DfaState st180[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 43, 43, 43, 43, 43, 43, 43, 436, 436, 436,
+ 436, 43, 43, 43, 43, 43, 43, 43, 43, 43,
+ 43, 43, 43, 43, 43, 43, 43, 436, 43, 436,
+ 436, 436, 436, 43, 436, 436, 436, 436, 436, 436,
+ 436, 43, 436, 436, 43, 43, 43, 43, 436, 436
+};
+
+static DfaState st181[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 43, 43, 43, 43, 43, 43, 43, 436, 436, 436,
+ 436, 43, 43, 43, 43, 43, 43, 43, 43, 43,
+ 43, 43, 43, 43, 43, 43, 43, 436, 43, 436,
+ 436, 436, 436, 43, 436, 436, 436, 436, 436, 436,
+ 436, 43, 436, 436, 43, 43, 43, 43, 436, 436
+};
+
+static DfaState st182[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 43, 43, 43, 43, 43, 43, 43, 436, 436, 436,
+ 436, 43, 43, 43, 43, 43, 43, 43, 43, 194,
+ 43, 43, 43, 43, 43, 43, 43, 436, 43, 436,
+ 436, 436, 436, 43, 436, 436, 436, 436, 436, 436,
+ 436, 43, 436, 436, 43, 43, 43, 43, 436, 436
+};
+
+static DfaState st183[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 43, 43, 43, 43, 43, 43, 43, 436, 436, 436,
+ 436, 43, 43, 43, 43, 43, 43, 43, 43, 43,
+ 43, 43, 43, 43, 43, 43, 43, 436, 43, 436,
+ 436, 436, 436, 43, 436, 436, 436, 436, 436, 436,
+ 436, 43, 436, 436, 43, 43, 43, 43, 436, 436
+};
+
+static DfaState st184[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 50, 50, 50, 50, 50, 50, 50, 436, 436, 436,
+ 436, 50, 50, 50, 50, 50, 50, 50, 50, 50,
+ 50, 50, 50, 50, 50, 50, 50, 436, 50, 436,
+ 436, 436, 436, 50, 436, 436, 436, 436, 436, 436,
+ 436, 50, 436, 436, 50, 50, 50, 50, 436, 436
+};
+
+static DfaState st185[60] = {
+ 436, 185, 144, 145, 122, 122, 122, 122, 122, 122,
+ 122, 122, 122, 122, 186, 186, 186, 122, 122, 122,
+ 122, 122, 122, 122, 122, 122, 122, 122, 122, 122,
+ 122, 122, 122, 122, 122, 122, 122, 122, 122, 122,
+ 122, 122, 122, 122, 122, 122, 122, 122, 122, 122,
+ 122, 122, 122, 122, 122, 122, 122, 122, 122, 436
+};
+
+static DfaState st186[60] = {
+ 436, 185, 144, 145, 122, 122, 122, 122, 122, 122,
+ 122, 122, 122, 122, 186, 186, 186, 122, 122, 122,
+ 122, 122, 122, 122, 122, 122, 122, 122, 122, 122,
+ 122, 122, 122, 122, 122, 122, 122, 122, 122, 122,
+ 122, 122, 122, 122, 122, 122, 122, 122, 122, 122,
+ 122, 122, 122, 122, 122, 122, 122, 122, 122, 436
+};
+
+static DfaState st187[60] = {
+ 436, 187, 188, 189, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 190, 190, 190, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st188[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st189[60] = {
+ 436, 436, 195, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st190[60] = {
+ 436, 187, 188, 189, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 190, 190, 190, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st191[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 43, 43, 43, 43, 43, 43, 43, 436, 436, 436,
+ 436, 43, 43, 43, 43, 43, 43, 43, 43, 43,
+ 43, 43, 43, 43, 43, 43, 43, 436, 43, 436,
+ 436, 436, 436, 43, 436, 436, 436, 436, 436, 436,
+ 436, 43, 436, 436, 43, 43, 43, 43, 436, 436
+};
+
+static DfaState st192[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 43, 43, 43, 43, 43, 43, 43, 436, 436, 436,
+ 436, 43, 43, 43, 43, 43, 43, 43, 43, 43,
+ 43, 43, 43, 43, 43, 43, 43, 436, 43, 436,
+ 436, 436, 436, 43, 436, 436, 436, 436, 436, 436,
+ 436, 43, 436, 436, 43, 43, 43, 43, 436, 436
+};
+
+static DfaState st193[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 43, 43, 43, 43, 43, 43, 43, 436, 436, 436,
+ 436, 43, 43, 43, 43, 43, 43, 43, 43, 43,
+ 43, 43, 43, 43, 43, 43, 43, 436, 43, 436,
+ 436, 436, 436, 43, 436, 436, 436, 436, 436, 436,
+ 436, 43, 436, 436, 43, 43, 43, 43, 436, 436
+};
+
+static DfaState st194[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 43, 43, 43, 43, 43, 43, 43, 436, 436, 436,
+ 436, 43, 43, 43, 43, 43, 43, 43, 43, 43,
+ 196, 43, 43, 43, 43, 43, 43, 436, 43, 436,
+ 436, 436, 436, 43, 436, 436, 436, 436, 436, 436,
+ 436, 43, 436, 436, 43, 43, 43, 43, 436, 436
+};
+
+static DfaState st195[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st196[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 43, 43, 43, 43, 43, 43, 43, 436, 436, 436,
+ 436, 43, 43, 43, 43, 197, 43, 43, 43, 43,
+ 43, 43, 43, 43, 43, 43, 43, 436, 43, 436,
+ 436, 436, 436, 43, 436, 436, 436, 436, 436, 436,
+ 436, 43, 436, 436, 43, 43, 43, 43, 436, 436
+};
+
+static DfaState st197[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 43, 43, 43, 43, 43, 43, 43, 436, 436, 436,
+ 436, 43, 43, 43, 43, 43, 43, 43, 43, 43,
+ 43, 198, 43, 43, 43, 43, 43, 436, 43, 436,
+ 436, 436, 436, 43, 436, 436, 436, 436, 436, 436,
+ 436, 43, 436, 436, 43, 43, 43, 43, 436, 436
+};
+
+static DfaState st198[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 43, 43, 43, 43, 43, 43, 43, 436, 436, 436,
+ 436, 43, 43, 43, 43, 43, 43, 43, 43, 43,
+ 43, 43, 199, 43, 43, 43, 43, 436, 43, 436,
+ 436, 436, 436, 43, 436, 436, 436, 436, 436, 436,
+ 436, 43, 436, 436, 43, 43, 43, 43, 436, 436
+};
+
+static DfaState st199[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 200, 43, 43, 43, 43, 43, 43, 436, 436, 436,
+ 436, 43, 43, 43, 43, 43, 43, 43, 43, 43,
+ 43, 43, 43, 43, 43, 43, 43, 436, 43, 436,
+ 436, 436, 436, 43, 436, 436, 436, 436, 436, 436,
+ 436, 43, 436, 436, 43, 43, 43, 43, 436, 436
+};
+
+static DfaState st200[60] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 43, 43, 43, 43, 43, 43, 43, 436, 436, 436,
+ 436, 43, 43, 43, 43, 43, 43, 43, 43, 43,
+ 43, 43, 43, 43, 43, 43, 43, 436, 43, 436,
+ 436, 436, 436, 43, 436, 436, 436, 436, 436, 436,
+ 436, 43, 436, 436, 43, 43, 43, 43, 436, 436
+};
+
+static DfaState st201[7] = {
+ 202, 203, 204, 205, 206, 207, 436
+};
+
+static DfaState st202[7] = {
+ 436, 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st203[7] = {
+ 436, 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st204[7] = {
+ 436, 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st205[7] = {
+ 436, 436, 208, 436, 436, 436, 436
+};
+
+static DfaState st206[7] = {
+ 436, 209, 210, 211, 209, 209, 436
+};
+
+static DfaState st207[7] = {
+ 436, 436, 436, 436, 436, 207, 436
+};
+
+static DfaState st208[7] = {
+ 436, 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st209[7] = {
+ 436, 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st210[7] = {
+ 436, 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st211[7] = {
+ 436, 436, 212, 436, 436, 436, 436
+};
+
+static DfaState st212[7] = {
+ 436, 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st213[7] = {
+ 214, 215, 216, 217, 218, 219, 436
+};
+
+static DfaState st214[7] = {
+ 436, 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st215[7] = {
+ 436, 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st216[7] = {
+ 436, 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st217[7] = {
+ 436, 436, 220, 436, 436, 436, 436
+};
+
+static DfaState st218[7] = {
+ 436, 221, 222, 223, 221, 221, 436
+};
+
+static DfaState st219[7] = {
+ 436, 436, 436, 436, 436, 219, 436
+};
+
+static DfaState st220[7] = {
+ 436, 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st221[7] = {
+ 436, 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st222[7] = {
+ 436, 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st223[7] = {
+ 436, 436, 224, 436, 436, 436, 436
+};
+
+static DfaState st224[7] = {
+ 436, 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st225[7] = {
+ 226, 227, 228, 229, 230, 231, 436
+};
+
+static DfaState st226[7] = {
+ 436, 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st227[7] = {
+ 436, 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st228[7] = {
+ 436, 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st229[7] = {
+ 436, 436, 232, 436, 436, 436, 436
+};
+
+static DfaState st230[7] = {
+ 436, 233, 233, 233, 233, 233, 436
+};
+
+static DfaState st231[7] = {
+ 436, 436, 436, 436, 436, 231, 436
+};
+
+static DfaState st232[7] = {
+ 436, 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st233[7] = {
+ 436, 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st234[7] = {
+ 235, 236, 237, 238, 239, 237, 436
+};
+
+static DfaState st235[7] = {
+ 436, 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st236[7] = {
+ 436, 436, 240, 436, 436, 436, 436
+};
+
+static DfaState st237[7] = {
+ 436, 436, 237, 436, 436, 237, 436
+};
+
+static DfaState st238[7] = {
+ 436, 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st239[7] = {
+ 436, 436, 436, 241, 436, 436, 436
+};
+
+static DfaState st240[7] = {
+ 436, 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st241[7] = {
+ 436, 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st242[7] = {
+ 243, 244, 245, 246, 247, 245, 436
+};
+
+static DfaState st243[7] = {
+ 436, 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st244[7] = {
+ 436, 436, 248, 436, 436, 436, 436
+};
+
+static DfaState st245[7] = {
+ 436, 436, 245, 436, 436, 245, 436
+};
+
+static DfaState st246[7] = {
+ 436, 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st247[7] = {
+ 436, 436, 436, 249, 436, 436, 436
+};
+
+static DfaState st248[7] = {
+ 436, 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st249[7] = {
+ 436, 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st250[5] = {
+ 251, 252, 253, 254, 436
+};
+
+static DfaState st251[5] = {
+ 436, 436, 436, 436, 436
+};
+
+static DfaState st252[5] = {
+ 436, 436, 436, 436, 436
+};
+
+static DfaState st253[5] = {
+ 436, 255, 436, 436, 436
+};
+
+static DfaState st254[5] = {
+ 436, 436, 436, 254, 436
+};
+
+static DfaState st255[5] = {
+ 436, 436, 436, 436, 436
+};
+
+static DfaState st256[5] = {
+ 257, 258, 259, 260, 436
+};
+
+static DfaState st257[5] = {
+ 436, 436, 436, 436, 436
+};
+
+static DfaState st258[5] = {
+ 436, 436, 436, 436, 436
+};
+
+static DfaState st259[5] = {
+ 436, 261, 436, 436, 436
+};
+
+static DfaState st260[5] = {
+ 436, 436, 436, 260, 436
+};
+
+static DfaState st261[5] = {
+ 436, 436, 436, 436, 436
+};
+
+static DfaState st262[5] = {
+ 263, 264, 265, 266, 436
+};
+
+static DfaState st263[5] = {
+ 436, 436, 436, 436, 436
+};
+
+static DfaState st264[5] = {
+ 436, 436, 436, 436, 436
+};
+
+static DfaState st265[5] = {
+ 436, 267, 436, 436, 436
+};
+
+static DfaState st266[5] = {
+ 436, 436, 436, 266, 436
+};
+
+static DfaState st267[5] = {
+ 436, 436, 436, 436, 436
+};
+
+static DfaState st268[7] = {
+ 269, 270, 271, 272, 273, 271, 436
+};
+
+static DfaState st269[7] = {
+ 436, 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st270[7] = {
+ 436, 436, 274, 436, 436, 436, 436
+};
+
+static DfaState st271[7] = {
+ 436, 436, 271, 436, 436, 271, 436
+};
+
+static DfaState st272[7] = {
+ 436, 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st273[7] = {
+ 436, 436, 436, 275, 436, 436, 436
+};
+
+static DfaState st274[7] = {
+ 436, 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st275[7] = {
+ 436, 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st276[36] = {
+ 277, 278, 279, 280, 281, 279, 279, 279, 279, 279,
+ 279, 279, 279, 279, 279, 282, 279, 279, 283, 284,
+ 285, 286, 287, 279, 279, 279, 279, 288, 289, 290,
+ 291, 292, 293, 279, 279, 436
+};
+
+static DfaState st277[36] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st278[36] = {
+ 436, 294, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st279[36] = {
+ 436, 436, 279, 436, 279, 279, 279, 279, 279, 279,
+ 279, 279, 279, 279, 279, 436, 279, 279, 436, 436,
+ 436, 436, 436, 279, 279, 279, 279, 436, 436, 436,
+ 436, 436, 279, 279, 279, 436
+};
+
+static DfaState st280[36] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st281[36] = {
+ 436, 436, 279, 436, 279, 295, 279, 279, 279, 279,
+ 279, 279, 279, 279, 279, 436, 279, 279, 436, 436,
+ 436, 436, 436, 279, 279, 279, 279, 436, 436, 436,
+ 436, 436, 279, 279, 279, 436
+};
+
+static DfaState st282[36] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st283[36] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st284[36] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st285[36] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 296,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st286[36] = {
+ 436, 436, 436, 436, 297, 297, 297, 297, 297, 297,
+ 297, 297, 297, 297, 297, 436, 436, 436, 436, 436,
+ 436, 298, 299, 300, 300, 436, 297, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st287[36] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st288[36] = {
+ 436, 436, 436, 436, 301, 301, 301, 301, 301, 301,
+ 301, 301, 301, 301, 302, 303, 436, 436, 436, 436,
+ 436, 436, 304, 305, 306, 436, 301, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st289[36] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st290[36] = {
+ 436, 307, 308, 309, 308, 308, 308, 308, 308, 308,
+ 308, 308, 308, 308, 308, 308, 308, 308, 310, 311,
+ 312, 313, 308, 308, 308, 308, 308, 314, 308, 308,
+ 308, 308, 308, 308, 308, 436
+};
+
+static DfaState st291[36] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st292[36] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 315, 316, 436, 436, 436
+};
+
+static DfaState st293[36] = {
+ 436, 436, 279, 436, 279, 279, 279, 279, 279, 279,
+ 279, 279, 279, 279, 279, 436, 279, 279, 436, 436,
+ 436, 436, 436, 279, 279, 279, 279, 436, 436, 436,
+ 436, 317, 279, 279, 279, 436
+};
+
+static DfaState st294[36] = {
+ 436, 436, 318, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st295[36] = {
+ 436, 436, 279, 436, 279, 279, 319, 279, 279, 279,
+ 279, 279, 279, 279, 279, 436, 279, 279, 436, 436,
+ 436, 436, 436, 279, 279, 279, 279, 436, 436, 436,
+ 436, 436, 279, 279, 279, 436
+};
+
+static DfaState st296[36] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st297[36] = {
+ 436, 436, 436, 436, 320, 320, 320, 320, 320, 320,
+ 320, 320, 320, 320, 320, 436, 436, 436, 436, 436,
+ 436, 436, 436, 320, 320, 436, 320, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st298[36] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st299[36] = {
+ 436, 436, 436, 321, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st300[36] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 300, 300, 322, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st301[36] = {
+ 436, 436, 436, 436, 323, 323, 323, 323, 323, 323,
+ 323, 323, 323, 323, 323, 436, 436, 436, 436, 436,
+ 436, 436, 436, 323, 323, 436, 323, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st302[36] = {
+ 436, 436, 436, 436, 323, 323, 323, 323, 323, 323,
+ 323, 323, 323, 324, 323, 436, 436, 436, 436, 436,
+ 436, 436, 436, 323, 323, 436, 323, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st303[36] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 325, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st304[36] = {
+ 436, 436, 436, 326, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st305[36] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 306, 306, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st306[36] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 306, 306, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st307[36] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st308[36] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st309[36] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st310[36] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st311[36] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st312[36] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 327,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st313[36] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st314[36] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st315[36] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st316[36] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st317[36] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st318[36] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st319[36] = {
+ 436, 436, 279, 436, 279, 279, 279, 328, 279, 279,
+ 279, 279, 279, 279, 279, 436, 279, 279, 436, 436,
+ 436, 436, 436, 279, 279, 279, 279, 436, 436, 436,
+ 436, 436, 279, 279, 279, 436
+};
+
+static DfaState st320[36] = {
+ 436, 436, 436, 436, 320, 320, 320, 320, 320, 320,
+ 320, 320, 320, 320, 320, 436, 436, 436, 436, 436,
+ 436, 436, 436, 320, 320, 436, 320, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st321[36] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st322[36] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 329, 329, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st323[36] = {
+ 436, 436, 436, 436, 323, 323, 323, 323, 323, 323,
+ 323, 323, 323, 323, 323, 436, 436, 436, 436, 436,
+ 436, 436, 436, 323, 323, 436, 323, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st324[36] = {
+ 436, 436, 436, 436, 323, 323, 330, 323, 323, 323,
+ 323, 323, 323, 323, 323, 436, 436, 436, 436, 436,
+ 436, 436, 436, 323, 323, 436, 323, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st325[36] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st326[36] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st327[36] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st328[36] = {
+ 436, 436, 279, 436, 279, 279, 279, 279, 331, 279,
+ 279, 279, 279, 279, 279, 436, 279, 279, 436, 436,
+ 436, 436, 436, 279, 279, 279, 279, 436, 436, 436,
+ 436, 436, 279, 279, 279, 436
+};
+
+static DfaState st329[36] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 329, 329, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st330[36] = {
+ 436, 436, 436, 436, 323, 323, 323, 323, 323, 323,
+ 332, 323, 323, 323, 323, 436, 436, 436, 436, 436,
+ 436, 436, 436, 323, 323, 436, 323, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st331[36] = {
+ 436, 436, 279, 436, 279, 279, 279, 279, 279, 333,
+ 279, 279, 279, 279, 279, 436, 279, 279, 436, 436,
+ 436, 436, 436, 279, 279, 279, 279, 436, 436, 436,
+ 436, 436, 279, 279, 279, 436
+};
+
+static DfaState st332[36] = {
+ 436, 334, 334, 334, 335, 335, 335, 335, 335, 335,
+ 335, 335, 335, 335, 335, 334, 336, 334, 334, 337,
+ 338, 334, 334, 339, 339, 334, 335, 334, 334, 334,
+ 334, 334, 334, 334, 334, 436
+};
+
+static DfaState st333[36] = {
+ 436, 436, 279, 436, 279, 279, 279, 279, 279, 279,
+ 340, 279, 279, 279, 279, 436, 279, 279, 436, 436,
+ 436, 436, 436, 279, 279, 279, 279, 436, 436, 436,
+ 436, 436, 279, 279, 279, 436
+};
+
+static DfaState st334[36] = {
+ 436, 334, 334, 334, 334, 334, 334, 334, 334, 334,
+ 334, 334, 334, 334, 334, 334, 334, 334, 334, 337,
+ 338, 334, 334, 334, 334, 334, 334, 334, 334, 334,
+ 334, 334, 334, 334, 334, 436
+};
+
+static DfaState st335[36] = {
+ 436, 334, 334, 334, 335, 335, 335, 335, 335, 335,
+ 335, 335, 335, 335, 335, 334, 334, 334, 334, 337,
+ 338, 334, 334, 335, 335, 334, 335, 334, 334, 334,
+ 334, 334, 334, 334, 334, 436
+};
+
+static DfaState st336[36] = {
+ 436, 334, 334, 334, 334, 334, 334, 334, 334, 334,
+ 334, 334, 334, 334, 334, 334, 336, 334, 334, 337,
+ 338, 334, 334, 341, 341, 334, 334, 334, 334, 334,
+ 334, 334, 334, 334, 334, 436
+};
+
+static DfaState st337[36] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st338[36] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 342,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st339[36] = {
+ 436, 334, 334, 334, 335, 335, 335, 335, 335, 335,
+ 335, 335, 335, 335, 335, 334, 343, 334, 334, 344,
+ 345, 334, 334, 339, 339, 334, 335, 334, 346, 334,
+ 334, 334, 334, 334, 334, 436
+};
+
+static DfaState st340[36] = {
+ 436, 436, 279, 436, 279, 279, 279, 279, 279, 279,
+ 279, 347, 279, 279, 279, 436, 279, 279, 436, 436,
+ 436, 436, 436, 279, 279, 279, 279, 436, 436, 436,
+ 436, 436, 279, 279, 279, 436
+};
+
+static DfaState st341[36] = {
+ 436, 334, 334, 334, 334, 334, 334, 334, 334, 334,
+ 334, 334, 334, 334, 334, 334, 343, 334, 334, 344,
+ 345, 334, 334, 341, 341, 334, 334, 334, 346, 334,
+ 334, 334, 334, 334, 334, 436
+};
+
+static DfaState st342[36] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st343[36] = {
+ 436, 334, 334, 334, 334, 334, 334, 334, 334, 334,
+ 334, 334, 334, 334, 334, 334, 343, 334, 334, 337,
+ 338, 334, 334, 334, 334, 334, 334, 334, 346, 334,
+ 334, 334, 334, 334, 334, 436
+};
+
+static DfaState st344[36] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st345[36] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 348,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st346[36] = {
+ 436, 349, 349, 349, 349, 349, 349, 349, 349, 349,
+ 349, 349, 349, 349, 349, 349, 349, 349, 349, 350,
+ 351, 349, 349, 349, 349, 349, 349, 349, 334, 349,
+ 349, 349, 349, 349, 349, 436
+};
+
+static DfaState st347[36] = {
+ 436, 436, 279, 436, 279, 279, 352, 279, 279, 279,
+ 279, 279, 279, 279, 279, 436, 279, 279, 436, 436,
+ 436, 436, 436, 279, 279, 279, 279, 436, 436, 436,
+ 436, 436, 279, 279, 279, 436
+};
+
+static DfaState st348[36] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st349[36] = {
+ 436, 349, 349, 349, 349, 349, 349, 349, 349, 349,
+ 349, 349, 349, 349, 349, 349, 349, 349, 349, 350,
+ 351, 349, 349, 349, 349, 349, 349, 349, 353, 349,
+ 349, 349, 349, 349, 349, 436
+};
+
+static DfaState st350[36] = {
+ 436, 354, 354, 354, 354, 354, 354, 354, 354, 354,
+ 354, 354, 354, 354, 354, 354, 354, 354, 354, 354,
+ 354, 354, 354, 354, 354, 354, 354, 354, 355, 354,
+ 354, 354, 354, 354, 354, 436
+};
+
+static DfaState st351[36] = {
+ 436, 354, 354, 354, 354, 354, 354, 354, 354, 354,
+ 354, 354, 354, 354, 354, 354, 354, 354, 354, 356,
+ 354, 354, 354, 354, 354, 354, 354, 354, 355, 354,
+ 354, 354, 354, 354, 354, 436
+};
+
+static DfaState st352[36] = {
+ 436, 436, 279, 436, 279, 279, 279, 279, 279, 279,
+ 279, 279, 357, 279, 279, 436, 279, 279, 436, 436,
+ 436, 436, 436, 279, 279, 279, 279, 436, 436, 436,
+ 436, 436, 279, 279, 279, 436
+};
+
+static DfaState st353[36] = {
+ 436, 334, 334, 334, 334, 334, 334, 334, 334, 334,
+ 334, 334, 334, 334, 334, 334, 358, 334, 334, 344,
+ 345, 334, 334, 359, 359, 334, 334, 334, 334, 334,
+ 334, 334, 334, 334, 334, 436
+};
+
+static DfaState st354[36] = {
+ 436, 354, 354, 354, 354, 354, 354, 354, 354, 354,
+ 354, 354, 354, 354, 354, 354, 354, 354, 354, 354,
+ 354, 354, 354, 354, 354, 354, 354, 354, 355, 354,
+ 354, 354, 354, 354, 354, 436
+};
+
+static DfaState st355[36] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 360, 436, 436, 361,
+ 362, 436, 436, 363, 363, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st356[36] = {
+ 436, 354, 354, 354, 354, 354, 354, 354, 354, 354,
+ 354, 354, 354, 354, 354, 354, 354, 354, 354, 354,
+ 354, 354, 354, 354, 354, 354, 354, 354, 355, 354,
+ 354, 354, 354, 354, 354, 436
+};
+
+static DfaState st357[36] = {
+ 436, 436, 279, 436, 279, 279, 279, 279, 279, 279,
+ 279, 279, 279, 364, 279, 436, 279, 279, 436, 436,
+ 436, 436, 436, 279, 279, 279, 279, 436, 436, 436,
+ 436, 436, 279, 279, 279, 436
+};
+
+static DfaState st358[36] = {
+ 436, 334, 334, 334, 334, 334, 334, 334, 334, 334,
+ 334, 334, 334, 334, 334, 334, 358, 334, 334, 344,
+ 345, 334, 334, 359, 359, 334, 334, 334, 334, 334,
+ 334, 334, 334, 334, 334, 436
+};
+
+static DfaState st359[36] = {
+ 436, 334, 334, 334, 334, 334, 334, 334, 334, 334,
+ 334, 334, 334, 334, 334, 334, 358, 334, 334, 344,
+ 345, 334, 334, 359, 359, 334, 334, 334, 334, 334,
+ 334, 334, 334, 334, 334, 436
+};
+
+static DfaState st360[36] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 360, 436, 436, 361,
+ 362, 436, 436, 363, 363, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st361[36] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st362[36] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 365,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st363[36] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 360, 436, 436, 361,
+ 362, 436, 436, 363, 363, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st364[36] = {
+ 436, 436, 279, 436, 279, 279, 279, 279, 279, 279,
+ 279, 279, 279, 279, 366, 436, 279, 279, 436, 436,
+ 436, 436, 436, 279, 279, 279, 279, 436, 436, 436,
+ 436, 436, 279, 279, 279, 436
+};
+
+static DfaState st365[36] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st366[36] = {
+ 436, 436, 279, 436, 279, 279, 279, 279, 279, 279,
+ 279, 279, 279, 279, 279, 367, 279, 279, 436, 436,
+ 436, 436, 436, 279, 279, 279, 279, 436, 436, 436,
+ 436, 436, 279, 279, 279, 436
+};
+
+static DfaState st367[36] = {
+ 436, 368, 368, 368, 368, 368, 368, 368, 368, 368,
+ 368, 368, 368, 368, 368, 368, 369, 370, 436, 368,
+ 368, 368, 368, 368, 368, 368, 368, 368, 368, 368,
+ 368, 368, 368, 368, 368, 436
+};
+
+static DfaState st368[36] = {
+ 436, 368, 368, 368, 368, 368, 368, 368, 368, 368,
+ 368, 368, 368, 368, 368, 368, 368, 368, 371, 368,
+ 368, 368, 368, 368, 368, 368, 368, 368, 368, 368,
+ 368, 368, 368, 368, 368, 436
+};
+
+static DfaState st369[36] = {
+ 436, 368, 368, 368, 368, 368, 368, 368, 368, 368,
+ 368, 368, 368, 368, 368, 368, 369, 370, 371, 368,
+ 368, 368, 368, 368, 368, 368, 368, 368, 368, 368,
+ 368, 368, 368, 368, 368, 436
+};
+
+static DfaState st370[36] = {
+ 436, 372, 372, 372, 372, 372, 372, 372, 372, 372,
+ 372, 372, 372, 372, 372, 372, 372, 372, 373, 372,
+ 372, 372, 372, 372, 372, 372, 372, 372, 372, 372,
+ 372, 372, 372, 372, 368, 436
+};
+
+static DfaState st371[36] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st372[36] = {
+ 436, 372, 372, 372, 372, 372, 372, 372, 372, 372,
+ 372, 372, 372, 372, 372, 372, 372, 372, 373, 372,
+ 372, 372, 372, 372, 372, 372, 372, 372, 372, 372,
+ 372, 372, 372, 372, 374, 436
+};
+
+static DfaState st373[36] = {
+ 436, 375, 375, 375, 375, 375, 375, 375, 375, 375,
+ 375, 375, 375, 375, 375, 375, 375, 375, 375, 375,
+ 375, 375, 375, 375, 375, 375, 375, 375, 375, 375,
+ 375, 375, 375, 375, 376, 436
+};
+
+static DfaState st374[36] = {
+ 436, 368, 368, 368, 368, 368, 368, 368, 368, 368,
+ 368, 368, 368, 368, 368, 368, 377, 368, 378, 368,
+ 368, 368, 368, 368, 368, 368, 368, 368, 368, 368,
+ 368, 368, 368, 368, 368, 436
+};
+
+static DfaState st375[36] = {
+ 436, 375, 375, 375, 375, 375, 375, 375, 375, 375,
+ 375, 375, 375, 375, 375, 375, 375, 375, 375, 375,
+ 375, 375, 375, 375, 375, 375, 375, 375, 375, 375,
+ 375, 375, 375, 375, 376, 436
+};
+
+static DfaState st376[36] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 379, 436, 380, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st377[36] = {
+ 436, 368, 368, 368, 368, 368, 368, 368, 368, 368,
+ 368, 368, 368, 368, 368, 368, 377, 368, 378, 368,
+ 368, 368, 368, 368, 368, 368, 368, 368, 368, 368,
+ 368, 368, 368, 368, 368, 436
+};
+
+static DfaState st378[36] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st379[36] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 379, 436, 380, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st380[36] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st381[28] = {
+ 382, 383, 384, 385, 386, 436, 387, 388, 388, 388,
+ 389, 388, 388, 388, 388, 388, 388, 388, 388, 388,
+ 390, 391, 392, 393, 394, 395, 388, 436
+};
+
+static DfaState st382[28] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st383[28] = {
+ 436, 383, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st384[28] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st385[28] = {
+ 436, 436, 396, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st386[28] = {
+ 436, 436, 436, 436, 397, 398, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st387[28] = {
+ 436, 436, 436, 436, 436, 436, 436, 399, 436, 400,
+ 401, 436, 436, 436, 402, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st388[28] = {
+ 436, 436, 436, 436, 436, 436, 436, 403, 403, 403,
+ 403, 403, 403, 403, 403, 403, 403, 403, 403, 403,
+ 436, 436, 436, 436, 436, 403, 403, 436
+};
+
+static DfaState st389[28] = {
+ 436, 436, 436, 436, 436, 436, 436, 403, 403, 403,
+ 403, 404, 403, 403, 403, 403, 403, 403, 403, 403,
+ 436, 436, 436, 436, 436, 403, 403, 436
+};
+
+static DfaState st390[28] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st391[28] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st392[28] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st393[28] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st394[28] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st395[28] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 395, 436, 436
+};
+
+static DfaState st396[28] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st397[28] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st398[28] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st399[28] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 405, 436,
+ 436, 436, 436, 436, 436, 406, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st400[28] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 407, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st401[28] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 408, 409, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st402[28] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 410, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st403[28] = {
+ 436, 436, 436, 436, 436, 436, 436, 403, 403, 403,
+ 403, 403, 403, 403, 403, 403, 403, 403, 403, 403,
+ 436, 436, 436, 436, 436, 403, 403, 436
+};
+
+static DfaState st404[28] = {
+ 436, 436, 436, 436, 436, 436, 436, 403, 403, 403,
+ 403, 403, 403, 403, 411, 403, 403, 403, 403, 403,
+ 436, 436, 436, 436, 436, 403, 403, 436
+};
+
+static DfaState st405[28] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 412,
+ 436, 413, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st406[28] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 414, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st407[28] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 415, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st408[28] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 416,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st409[28] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 417, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st410[28] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 418,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st411[28] = {
+ 436, 436, 436, 436, 436, 436, 436, 403, 403, 403,
+ 403, 403, 403, 403, 403, 419, 403, 403, 403, 403,
+ 436, 436, 436, 436, 436, 403, 403, 436
+};
+
+static DfaState st412[28] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 420, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st413[28] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 421,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st414[28] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 422, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st415[28] = {
+ 436, 436, 436, 436, 436, 436, 436, 423, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st416[28] = {
+ 436, 436, 436, 436, 436, 436, 436, 424, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st417[28] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 425, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st418[28] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 426, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st419[28] = {
+ 436, 436, 436, 436, 436, 436, 436, 403, 403, 403,
+ 403, 403, 403, 403, 403, 403, 403, 403, 403, 403,
+ 436, 436, 436, 436, 436, 403, 403, 436
+};
+
+static DfaState st420[28] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 427, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st421[28] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 428, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st422[28] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 429, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st423[28] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 430, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st424[28] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 431, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st425[28] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st426[28] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 432, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st427[28] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st428[28] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 433, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st429[28] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 434,
+ 436, 436, 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st430[28] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 435, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st431[28] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st432[28] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st433[28] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st434[28] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436
+};
+
+static DfaState st435[28] = {
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
+ 436, 436, 436, 436, 436, 436, 436, 436
+};
+
+
+DfaState *dfa[436] = {
+ st0,
+ st1,
+ st2,
+ st3,
+ st4,
+ st5,
+ st6,
+ st7,
+ st8,
+ st9,
+ st10,
+ st11,
+ st12,
+ st13,
+ st14,
+ st15,
+ st16,
+ st17,
+ st18,
+ st19,
+ st20,
+ st21,
+ st22,
+ st23,
+ st24,
+ st25,
+ st26,
+ st27,
+ st28,
+ st29,
+ st30,
+ st31,
+ st32,
+ st33,
+ st34,
+ st35,
+ st36,
+ st37,
+ st38,
+ st39,
+ st40,
+ st41,
+ st42,
+ st43,
+ st44,
+ st45,
+ st46,
+ st47,
+ st48,
+ st49,
+ st50,
+ st51,
+ st52,
+ st53,
+ st54,
+ st55,
+ st56,
+ st57,
+ st58,
+ st59,
+ st60,
+ st61,
+ st62,
+ st63,
+ st64,
+ st65,
+ st66,
+ st67,
+ st68,
+ st69,
+ st70,
+ st71,
+ st72,
+ st73,
+ st74,
+ st75,
+ st76,
+ st77,
+ st78,
+ st79,
+ st80,
+ st81,
+ st82,
+ st83,
+ st84,
+ st85,
+ st86,
+ st87,
+ st88,
+ st89,
+ st90,
+ st91,
+ st92,
+ st93,
+ st94,
+ st95,
+ st96,
+ st97,
+ st98,
+ st99,
+ st100,
+ st101,
+ st102,
+ st103,
+ st104,
+ st105,
+ st106,
+ st107,
+ st108,
+ st109,
+ st110,
+ st111,
+ st112,
+ st113,
+ st114,
+ st115,
+ st116,
+ st117,
+ st118,
+ st119,
+ st120,
+ st121,
+ st122,
+ st123,
+ st124,
+ st125,
+ st126,
+ st127,
+ st128,
+ st129,
+ st130,
+ st131,
+ st132,
+ st133,
+ st134,
+ st135,
+ st136,
+ st137,
+ st138,
+ st139,
+ st140,
+ st141,
+ st142,
+ st143,
+ st144,
+ st145,
+ st146,
+ st147,
+ st148,
+ st149,
+ st150,
+ st151,
+ st152,
+ st153,
+ st154,
+ st155,
+ st156,
+ st157,
+ st158,
+ st159,
+ st160,
+ st161,
+ st162,
+ st163,
+ st164,
+ st165,
+ st166,
+ st167,
+ st168,
+ st169,
+ st170,
+ st171,
+ st172,
+ st173,
+ st174,
+ st175,
+ st176,
+ st177,
+ st178,
+ st179,
+ st180,
+ st181,
+ st182,
+ st183,
+ st184,
+ st185,
+ st186,
+ st187,
+ st188,
+ st189,
+ st190,
+ st191,
+ st192,
+ st193,
+ st194,
+ st195,
+ st196,
+ st197,
+ st198,
+ st199,
+ st200,
+ st201,
+ st202,
+ st203,
+ st204,
+ st205,
+ st206,
+ st207,
+ st208,
+ st209,
+ st210,
+ st211,
+ st212,
+ st213,
+ st214,
+ st215,
+ st216,
+ st217,
+ st218,
+ st219,
+ st220,
+ st221,
+ st222,
+ st223,
+ st224,
+ st225,
+ st226,
+ st227,
+ st228,
+ st229,
+ st230,
+ st231,
+ st232,
+ st233,
+ st234,
+ st235,
+ st236,
+ st237,
+ st238,
+ st239,
+ st240,
+ st241,
+ st242,
+ st243,
+ st244,
+ st245,
+ st246,
+ st247,
+ st248,
+ st249,
+ st250,
+ st251,
+ st252,
+ st253,
+ st254,
+ st255,
+ st256,
+ st257,
+ st258,
+ st259,
+ st260,
+ st261,
+ st262,
+ st263,
+ st264,
+ st265,
+ st266,
+ st267,
+ st268,
+ st269,
+ st270,
+ st271,
+ st272,
+ st273,
+ st274,
+ st275,
+ st276,
+ st277,
+ st278,
+ st279,
+ st280,
+ st281,
+ st282,
+ st283,
+ st284,
+ st285,
+ st286,
+ st287,
+ st288,
+ st289,
+ st290,
+ st291,
+ st292,
+ st293,
+ st294,
+ st295,
+ st296,
+ st297,
+ st298,
+ st299,
+ st300,
+ st301,
+ st302,
+ st303,
+ st304,
+ st305,
+ st306,
+ st307,
+ st308,
+ st309,
+ st310,
+ st311,
+ st312,
+ st313,
+ st314,
+ st315,
+ st316,
+ st317,
+ st318,
+ st319,
+ st320,
+ st321,
+ st322,
+ st323,
+ st324,
+ st325,
+ st326,
+ st327,
+ st328,
+ st329,
+ st330,
+ st331,
+ st332,
+ st333,
+ st334,
+ st335,
+ st336,
+ st337,
+ st338,
+ st339,
+ st340,
+ st341,
+ st342,
+ st343,
+ st344,
+ st345,
+ st346,
+ st347,
+ st348,
+ st349,
+ st350,
+ st351,
+ st352,
+ st353,
+ st354,
+ st355,
+ st356,
+ st357,
+ st358,
+ st359,
+ st360,
+ st361,
+ st362,
+ st363,
+ st364,
+ st365,
+ st366,
+ st367,
+ st368,
+ st369,
+ st370,
+ st371,
+ st372,
+ st373,
+ st374,
+ st375,
+ st376,
+ st377,
+ st378,
+ st379,
+ st380,
+ st381,
+ st382,
+ st383,
+ st384,
+ st385,
+ st386,
+ st387,
+ st388,
+ st389,
+ st390,
+ st391,
+ st392,
+ st393,
+ st394,
+ st395,
+ st396,
+ st397,
+ st398,
+ st399,
+ st400,
+ st401,
+ st402,
+ st403,
+ st404,
+ st405,
+ st406,
+ st407,
+ st408,
+ st409,
+ st410,
+ st411,
+ st412,
+ st413,
+ st414,
+ st415,
+ st416,
+ st417,
+ st418,
+ st419,
+ st420,
+ st421,
+ st422,
+ st423,
+ st424,
+ st425,
+ st426,
+ st427,
+ st428,
+ st429,
+ st430,
+ st431,
+ st432,
+ st433,
+ st434,
+ st435
+};
+
+
+DfaState accepts[437] = {
+ 0, 1, 2, 3, 3, 4, 25, 6, 0, 50,
+ 59, 57, 57, 43, 26, 13, 14, 0, 57, 58,
+ 57, 21, 57, 23, 24, 27, 28, 44, 0, 35,
+ 36, 42, 45, 46, 58, 51, 52, 3, 5, 9,
+ 7, 8, 59, 59, 59, 59, 59, 59, 59, 59,
+ 57, 57, 12, 40, 59, 57, 58, 57, 57, 57,
+ 33, 34, 53, 58, 59, 59, 59, 59, 59, 59,
+ 59, 59, 59, 57, 59, 57, 57, 57, 57, 0,
+ 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
+ 57, 57, 57, 57, 57, 0, 0, 59, 59, 59,
+ 59, 59, 59, 32, 59, 59, 59, 59, 59, 59,
+ 59, 59, 57, 57, 57, 22, 56, 48, 49, 0,
+ 11, 11, 0, 59, 59, 59, 59, 59, 59, 59,
+ 59, 59, 59, 41, 59, 59, 59, 18, 57, 47,
+ 57, 0, 11, 0, 10, 10, 0, 59, 59, 59,
+ 59, 59, 15, 19, 59, 59, 59, 17, 57, 55,
+ 10, 0, 11, 11, 59, 59, 59, 59, 59, 59,
+ 20, 59, 57, 0, 0, 0, 11, 59, 59, 59,
+ 37, 38, 59, 39, 54, 0, 0, 0, 10, 10,
+ 0, 31, 29, 30, 59, 10, 59, 59, 59, 59,
+ 16, 0, 60, 61, 62, 62, 0, 65, 62, 64,
+ 63, 63, 63, 0, 66, 67, 68, 68, 0, 71,
+ 68, 70, 69, 69, 69, 0, 72, 73, 74, 74,
+ 0, 76, 74, 75, 0, 77, 79, 81, 80, 80,
+ 78, 80, 0, 82, 84, 86, 85, 85, 83, 85,
+ 0, 87, 88, 88, 89, 88, 0, 90, 91, 91,
+ 92, 91, 0, 93, 94, 94, 95, 94, 0, 96,
+ 98, 100, 99, 99, 97, 99, 0, 101, 108, 143,
+ 104, 143, 129, 127, 107, 107, 109, 128, 126, 134,
+ 0, 133, 139, 143, 102, 143, 107, 116, 110, 112,
+ 113, 123, 123, 125, 124, 117, 120, 132, 138, 130,
+ 131, 137, 137, 135, 136, 142, 140, 141, 103, 143,
+ 116, 111, 114, 123, 123, 119, 118, 137, 143, 115,
+ 123, 143, 123, 143, 0, 123, 0, 122, 122, 123,
+ 143, 0, 122, 0, 121, 121, 0, 143, 121, 0,
+ 122, 122, 143, 0, 0, 0, 122, 143, 0, 0,
+ 0, 121, 121, 0, 143, 121, 143, 0, 0, 0,
+ 0, 106, 0, 106, 0, 0, 0, 0, 105, 0,
+ 105, 0, 144, 145, 146, 146, 0, 0, 164, 164,
+ 158, 159, 160, 161, 162, 163, 146, 147, 148, 0,
+ 0, 0, 0, 164, 164, 150, 0, 0, 0, 0,
+ 0, 164, 0, 0, 0, 0, 0, 0, 0, 157,
+ 0, 0, 0, 0, 0, 152, 0, 149, 0, 0,
+ 0, 153, 154, 151, 155, 156, 0
+};
+
+void (*actions[165])() = {
+ zzerraction,
+ act1,
+ act2,
+ act3,
+ act4,
+ act5,
+ act6,
+ act7,
+ act8,
+ act9,
+ act10,
+ act11,
+ act12,
+ act13,
+ act14,
+ act15,
+ act16,
+ act17,
+ act18,
+ act19,
+ act20,
+ act21,
+ act22,
+ act23,
+ act24,
+ act25,
+ act26,
+ act27,
+ act28,
+ act29,
+ act30,
+ act31,
+ act32,
+ act33,
+ act34,
+ act35,
+ act36,
+ act37,
+ act38,
+ act39,
+ act40,
+ act41,
+ act42,
+ act43,
+ act44,
+ act45,
+ act46,
+ act47,
+ act48,
+ act49,
+ act50,
+ act51,
+ act52,
+ act53,
+ act54,
+ act55,
+ act56,
+ act57,
+ act58,
+ act59,
+ act60,
+ act61,
+ act62,
+ act63,
+ act64,
+ act65,
+ act66,
+ act67,
+ act68,
+ act69,
+ act70,
+ act71,
+ act72,
+ act73,
+ act74,
+ act75,
+ act76,
+ act77,
+ act78,
+ act79,
+ act80,
+ act81,
+ act82,
+ act83,
+ act84,
+ act85,
+ act86,
+ act87,
+ act88,
+ act89,
+ act90,
+ act91,
+ act92,
+ act93,
+ act94,
+ act95,
+ act96,
+ act97,
+ act98,
+ act99,
+ act100,
+ act101,
+ act102,
+ act103,
+ act104,
+ act105,
+ act106,
+ act107,
+ act108,
+ act109,
+ act110,
+ act111,
+ act112,
+ act113,
+ act114,
+ act115,
+ act116,
+ act117,
+ act118,
+ act119,
+ act120,
+ act121,
+ act122,
+ act123,
+ act124,
+ act125,
+ act126,
+ act127,
+ act128,
+ act129,
+ act130,
+ act131,
+ act132,
+ act133,
+ act134,
+ act135,
+ act136,
+ act137,
+ act138,
+ act139,
+ act140,
+ act141,
+ act142,
+ act143,
+ act144,
+ act145,
+ act146,
+ act147,
+ act148,
+ act149,
+ act150,
+ act151,
+ act152,
+ act153,
+ act154,
+ act155,
+ act156,
+ act157,
+ act158,
+ act159,
+ act160,
+ act161,
+ act162,
+ act163,
+ act164
+};
+
+static DfaState dfa_base[] = {
+ 0,
+ 201,
+ 213,
+ 225,
+ 234,
+ 242,
+ 250,
+ 256,
+ 262,
+ 268,
+ 276,
+ 381
+};
+
+static unsigned char *b_class_no[] = {
+ shift0,
+ shift1,
+ shift2,
+ shift3,
+ shift4,
+ shift5,
+ shift6,
+ shift7,
+ shift8,
+ shift9,
+ shift10,
+ shift11
+};
+
+
+
+#define ZZSHIFT(c) (b_class_no[zzauto][1+c])
+#define MAX_MODE 12
+#include "dlgauto.h"
diff --git a/Source/Pccts/antlr/stdpccts.h b/Source/Pccts/antlr/stdpccts.h
new file mode 100644
index 0000000..ccdc21c
--- /dev/null
+++ b/Source/Pccts/antlr/stdpccts.h
@@ -0,0 +1,31 @@
+#ifndef STDPCCTS_H
+#define STDPCCTS_H
+/*
+ * stdpccts.h -- P C C T S I n c l u d e
+ *
+ * Terence Parr, Will Cohen, and Hank Dietz: 1989-2001
+ * Purdue University Electrical Engineering
+ * With AHPCRC, University of Minnesota
+ * ANTLR Version 1.33MR33
+ */
+
+#ifndef ANTLR_VERSION
+#define ANTLR_VERSION 13333
+#endif
+
+#include "pcctscfg.h"
+#include "pccts_stdio.h"
+
+#include "pcctscfg.h"
+#include "set.h"
+#include <ctype.h>
+#include "syn.h"
+#include "hash.h"
+#include "generic.h"
+#define zzcr_attr(attr,tok,t)
+#define zzSET_SIZE 20
+#include "antlr.h"
+#include "tokens.h"
+#include "dlgdef.h"
+#include "mode.h"
+#endif
diff --git a/Source/Pccts/antlr/syn.h b/Source/Pccts/antlr/syn.h
new file mode 100644
index 0000000..a23d196
--- /dev/null
+++ b/Source/Pccts/antlr/syn.h
@@ -0,0 +1,390 @@
+/*
+ * syn.h
+ *
+ * This file includes definitions and macros associated with syntax diagrams
+ *
+ * SOFTWARE RIGHTS
+ *
+ * We reserve no LEGAL rights to the Purdue Compiler Construction Tool
+ * Set (PCCTS) -- PCCTS is in the public domain. An individual or
+ * company may do whatever they wish with source code distributed with
+ * PCCTS or the code generated by PCCTS, including the incorporation of
+ * PCCTS, or its output, into commerical software.
+ *
+ * We encourage users to develop software with PCCTS. However, we do ask
+ * that credit is given to us for developing PCCTS. By "credit",
+ * we mean that if you incorporate our source code into one of your
+ * programs (commercial product, research project, or otherwise) that you
+ * acknowledge this fact somewhere in the documentation, research report,
+ * etc... If you like PCCTS and have developed a nice tool with the
+ * output, please mention that you developed it using PCCTS. In
+ * addition, we ask that this header remain intact in our source code.
+ * As long as these guidelines are kept, we expect to continue enhancing
+ * this system and expect to make other tools available as they are
+ * completed.
+ *
+ * ANTLR 1.33
+ * Terence Parr
+ * Parr Research Corporation
+ * with Purdue University and AHPCRC, University of Minnesota
+ * 1989-2001
+ */
+
+#include "set.h"
+
+#define NumNodeTypes 4
+#define NumJuncTypes 9
+
+/* List the different node types */
+#define nJunction 1
+#define nRuleRef 2
+#define nToken 3
+#define nAction 4
+
+/* Different types of junctions */
+#define aSubBlk 1
+#define aOptBlk 2
+#define aLoopBlk 3
+#define EndBlk 4
+#define RuleBlk 5
+#define Generic 6 /* just a junction--no unusual characteristics */
+#define EndRule 7
+#define aPlusBlk 8
+#define aLoopBegin 9
+
+typedef int NodeType;
+
+#define TreeBlockAllocSize 500
+#define JunctionBlockAllocSize 200
+#define ActionBlockAllocSize 50
+#define RRefBlockAllocSize 100
+#define TokenBlockAllocSize 100
+
+#ifdef __cplusplus
+class ActionNode;
+class Junction;
+#endif
+
+/* note that 'right' is used by the tree node allocator as a ptr for linked list */
+typedef struct _tree {
+ struct _tree *down, *right;
+ int token;
+ union {
+ int rk; /* if token==EpToken, => how many more tokens req'd */
+ struct _tree *tref; /* if token==TREE_REF */
+ set sref; /* if token==SET */
+ } v;
+#ifdef TREE_DEBUG
+ int in_use;
+ int seq;
+#endif
+ } Tree;
+
+
+/* a predicate is defined to be a predicate action and a token tree with
+ * context info (if used); later, this struct may include the
+ * "hoisting distance" when we hoist past tokens.
+ *
+ * A tree is used to indicate && vs ||
+ *
+ * p
+ * |
+ * q--r
+ *
+ * indicates p && (q||r).
+ *
+ * If expr is PRED_AND_LIST or PRED_OR_LIST, then it's an operation node
+ * and indicates the start of an && or || list.
+ */
+
+typedef struct _Predicate {
+ struct _Predicate *down, *right; /* these have to be first */
+ struct _Predicate *up, *left; /* doubly-link me */
+ char *expr;
+ Tree *tcontext; /* used if lookahead depth of > one is needed (tree) */
+ int k; /* lookahead depth for this tcontext */
+ set scontext[2];/* used if lookahead depth of one is needed (set) */
+ /* scontext[0] is not used; only needed so genExprSets()
+ routine works (it expects an array)
+ */
+ set completionTree; /* which lookahead depths are required to complete tcontext? */
+ set completionSet; /* MR10 separate completion set for sets and trees */
+ struct _PredEntry *predEntry; /* MR11 */
+
+#ifdef __cplusplus
+ ActionNode *source; /* where did this predicate come from? */
+#else
+ struct _anode *source; /* where did this predicate come from? */
+#endif
+
+ char cloned; /* MR10 don't want to free original guard pred */
+ char redundant; /* MR10 predicate tree simplification */
+ char ampersandStyle; /* MR10 (g)? && <<p>>? */
+ char inverted; /* MR11 ! predName */
+ char isConst; /* MR11 */
+ char constValue; /* MR11 */
+ char conflictReported; /* MR11 */
+
+ set plainSet; /* MR12b */
+
+ /*** remember to change new_predicate() and predicate_dup() when changing this ***/
+
+} Predicate;
+
+typedef struct _ExceptionHandler {
+ char *signalname;
+ char *action;
+ } ExceptionHandler;
+
+typedef struct _ExceptionGroup {
+ struct _ListNode *handlers; /* list of ExceptionHandler's */
+ char *label; /* label==""; implies not attached to any
+ * particular rule ref.
+ */
+ char *altID; /* which alt did it come from (blk#:alt#) */
+
+ struct _ExceptionGroup *pendingLink; /* for alternative EG MR7 */
+ struct _ExceptionGroup *outerEG; /* for alternative EG MR7 */
+ struct _LabelEntry *labelEntry; /* for alternative EG MR7 */
+ int forRule; /* MR7 */
+ int used; /* MR7 */
+ } ExceptionGroup ;
+
+
+#define TokenString(_i) ((TokenInd!=NULL)?TokenStr[TokenInd[_i]]:TokenStr[_i])
+#define ExprString(_i) ((TokenInd!=NULL)?ExprStr[TokenInd[_i]]:ExprStr[_i])
+
+
+ /* M e s s a g e P a s s i n g T o N o d e s */
+
+/*
+ * assumes a 'Junction *r' exists. This macro calls a function with
+ * the pointer to the node to operate on and a pointer to the rule
+ * in which it is enclosed.
+ */
+#define TRANS(p) {if ( (p)==NULL ) fatal("TRANS: NULL object"); \
+ if ( (p)->ntype == nJunction ) (*(fpJTrans[((Junction *)(p))->jtype]))( p );\
+ else (*(fpTrans[(p)->ntype]))( p );}
+
+#define PRINT(p) {if ( (p)==NULL ) fatal("PRINT: NULL object");\
+ (*(fpPrint[(p)->ntype]))( p );}
+
+#define REACH(p,k,rk,a) {if ( (p)==NULL ) fatal("REACH: NULL object");\
+ (a) = (*(fpReach[(p)->ntype]))( p, k, rk );}
+
+#define TRAV(p,k,rk,a) {if ( (p)==NULL ) {\
+ if ( ContextGuardTRAV ) (a)=NULL; \
+ else fatal("TRAV: NULL object");\
+ } \
+ else (a) = (*(fpTraverse[(p)->ntype]))( p, k, rk );}
+
+/**
+*** #define TRAV(p,k,rk,a) {if ( (p)==NULL ) fatal("TRAV: NULL object");\
+*** (a) = (*(fpTraverse[(p)->ntype]))( p, k, rk );}
+**/
+
+/* All syntax diagram nodes derive from Node -- superclass
+ */
+#ifdef __cplusplus
+class Node {
+public:
+ NodeType ntype;
+ char *rname; /* what rule does this element live in? */
+ int file; /* index in FileStr */
+ int line; /* line number that element occurs on */
+ };
+#else
+typedef struct _node {
+ NodeType ntype;
+ char *rname; /* what rule does this element live in? */
+ int file; /* index in FileStr */
+ int line; /* line number that element occurs on */
+ } Node;
+#endif
+
+#ifdef __cplusplus
+class ActionNode : public Node {
+public:
+#else
+typedef struct _anode {
+ NodeType ntype;
+ char *rname; /* what rule does this action live in? */
+ int file; /* index in FileStr (name of file with action) */
+ int line; /* line number that action occurs on */
+#endif
+ Node *next;
+ char *action;
+ int is_predicate; /* true if action is a <<...>>? predicate action */
+ int done; /* don't dump if action dumped (used for predicates) */
+ int init_action; /* is this the 1st action of 1st prod of block? */
+ char *pred_fail; /* what to do/print when predicate fails */
+ Predicate *guardpred; /* if '(context)? =>' was present, already done */
+ unsigned char frmwarned;/* have we dumped a warning for pred yet? */
+ unsigned char ctxwarned;/* have we dumped a warning for pred yet? */
+ unsigned char predTooLong; /* MR10 have we dumped warning for pred yet */
+ unsigned char noHoist; /* MR12 literally "noHoist" */
+ Predicate *ampersandPred; /* MR10 (g)? && <<p>>? expr */
+#ifdef __cplusplus
+ Junction *guardNodes; /* MR11 */
+#else
+ struct _junct *guardNodes; /* MR11 */
+#endif
+ struct _PredEntry *predEntry; /* MR11 */
+ int inverted; /* MR11 <<!predSymbol>>? */
+#ifdef __cplusplus
+ };
+#else
+ } ActionNode;
+#endif
+
+#ifdef __cplusplus
+class TokNode : public Node {
+public:
+#else
+typedef struct _toknode {
+ NodeType ntype;
+ char *rname; /* name of rule it's in */
+ int file; /* index in FileStr (name of file with rule) */
+ int line; /* line number that token occurs on */
+#endif
+ Node *next;
+ int token;
+ int astnode; /* leaf/root/excluded (used to build AST's) */
+ unsigned char label;/* token label or expression ? */
+ unsigned char remapped;
+ /* used if token id's are forced to certain positions;
+ * a function walks the tree reassigning token numbers */
+ int upper_range; /* MR13 - was char */
+ /* used only if Token is of type T1..T2; in this case,
+ * use token..upper_range as the range; else
+ * upper_range must be 0 */
+ unsigned char wild_card;
+ /* indicates that the token is the "." wild-card;
+ * field token is ignored if wild_card is set
+ */
+ unsigned int elnum; /* element number within the alternative */
+#ifdef __cplusplus
+ Junction *altstart; /* pointer to node that starts alt */
+#else
+ struct _junct *altstart; /* pointer to node that starts alt */
+#endif
+ struct _TCnode *tclass; /* token class if tokclass ref */
+ set tset; /* set of tokens represented by meta token */
+ char *el_label; /* el_label:toknode */
+ unsigned char complement; /* complement the set? */
+ ExceptionGroup *ex_group; /* any exception[el_label] attached? */
+ unsigned char use_def_MT_handler;
+ unsigned char label_used_in_semantic_pred; /* MR10 */
+#ifdef __cplusplus
+ };
+#else
+ } TokNode;
+#endif
+
+#ifdef __cplusplus
+class RuleRefNode : public Node {
+public:
+#else
+typedef struct _rrnode {
+ NodeType ntype;
+ char *rname; /* name of rule it's in */
+ int file; /* index in FileStr (name of file with rule)
+ it's in */
+ int line; /* line number that rule ref occurs on */
+#endif
+ Node *next;
+ char *text; /* reference to which rule */
+ char *parms; /* point to parameters of rule invocation
+ (if present) */
+ char *assign; /* point to left-hand-side of assignment
+ (if any) */
+ int linked; /* Has a FoLink already been established? */
+ int astnode; /* excluded? (used to build AST's) */
+ unsigned int elnum; /* element number within the alternative */
+#ifdef __cplusplus
+ Junction *altstart;
+#else
+ struct _junct *altstart;
+#endif
+ char *el_label; /* el_label:rrnode */
+ ExceptionGroup *ex_group; /* any exception[el_label] attached? */
+#ifdef __cplusplus
+ };
+#else
+ } RuleRefNode;
+#endif
+
+#ifdef __cplusplus
+class Junction : public Node {
+public:
+#else
+typedef struct _junct {
+ NodeType ntype;
+ char *rname; /* name of rule junction is in */
+ int file; /* index in FileStr (name of file with rule)
+ if blk == RuleBlk */
+ int line; /* line number that rule occurs on */
+#endif
+ int seq; /* MR10 sequence number */
+ char ignore; /* used by FIRST computation to ignore
+ empty alt added for the (...)+ blks */
+ char visited; /* used by recursive routines to avoid
+ infinite recursion */
+ char pvisited; /* used by print routines to avoid
+ infinite recursion */
+ char fvisited; /* used by FoLink() to avoid
+ infinite recursion */
+ char *lock; /* used by REACH to track infinite recursion */
+ char *pred_lock; /* used by find_predicates to track infinite recursion */
+ int altnum; /* used in subblocks. altnum==0 means not an
+ alt of subrule */
+ int jtype; /* annotation for code-gen/FIRST/FOLLOW.
+ Junction type */
+#ifdef __cplusplus
+ Junction *end; /* pointer to node with EndBlk in it
+ if blk == a block type */
+#else
+ struct _junct *end; /* pointer to node with EndBlk in it
+ if blk == a block type */
+#endif
+ Node *p1, *p2;
+ char halt; /* never move past a junction with halt==TRUE */ /* MR10 was int */
+ char *pdecl; /* point to declaration of parameters on rule
+ (if present) */
+ char *parm; /* point to parameter of block invocation
+ (if present) */
+ char predparm; /* indicates that the 'parm' is a predicate
+ * to be used in the while loop generated
+ * for blocks */ /* MR10 was int */
+ char *ret; /* point to return type of rule (if present) */
+ char *erraction; /* point to error action (if present) */
+ int blockid; /* this is a unique ID */
+ char *exception_label; /* goto label for this alt */
+ set *fset; /* used for code generation */
+ Tree *ftree; /* used for code generation */
+ Predicate *predicate;/* predicate that can be used to disambiguate */
+ char guess; /* true if (...)? block */
+ char alpha_beta_guess_end; /* MR14 1 => end block of guess sub block */
+ Node *guess_analysis_point; /* MR14 */
+ char approx; /* limit block to use linear approx lookahead? */
+ set tokrefs; /* if ith element of alt is tokref then i is member */
+ set rulerefs; /* if ith element of alt is rule ref then i is member */
+ struct _ListNode *exceptions; /* list of exceptions groups for rule */
+ struct _ListNode *el_labels; /* list of element labels for rule */
+ ExceptionGroup *outerEG; /* MR7 */
+ int curAltNum; /* MR7 */
+ char* pFirstSetSymbol; /* #pragma FirstSetSymbol(Foo) MR21 */
+#ifdef __cplusplus
+ Junction *pendingLink; /* MR7 */
+#else
+ struct _junct *pendingLink; /* MR7 */
+#endif
+ char overlap_warning; /* MR10 */
+#ifdef __cplusplus
+ };
+#else
+ } Junction;
+#endif
+
+typedef struct { Node *left, *right;} Graph;
+
diff --git a/Source/Pccts/antlr/tokens.h b/Source/Pccts/antlr/tokens.h
new file mode 100644
index 0000000..91a53a8
--- /dev/null
+++ b/Source/Pccts/antlr/tokens.h
@@ -0,0 +1,246 @@
+#ifndef tokens_h
+#define tokens_h
+/* tokens.h -- List of labelled tokens and stuff
+ *
+ * Generated from: antlr.g
+ *
+ * Terence Parr, Will Cohen, and Hank Dietz: 1989-2001
+ * Purdue University Electrical Engineering
+ * ANTLR Version 1.33MR33
+ */
+#define zzEOF_TOKEN 1
+#define Eof 1
+#define QuotedTerm 2
+#define Action 34
+#define Pred 35
+#define PassAction 36
+#define WildCard 87
+#define LABEL 89
+#define Pragma 92
+#define FirstSetSymbol 93
+#define NonTerminal 100
+#define TokenTerm 101
+#define ID 148
+#define INT 150
+
+#ifdef __USE_PROTOS
+void grammar(void);
+#else
+extern void grammar();
+#endif
+
+#ifdef __USE_PROTOS
+void class_def(void);
+#else
+extern void class_def();
+#endif
+
+#ifdef __USE_PROTOS
+void rule(void);
+#else
+extern void rule();
+#endif
+
+#ifdef __USE_PROTOS
+void laction(void);
+#else
+extern void laction();
+#endif
+
+#ifdef __USE_PROTOS
+void lmember(void);
+#else
+extern void lmember();
+#endif
+
+#ifdef __USE_PROTOS
+void lprefix(void);
+#else
+extern void lprefix();
+#endif
+
+#ifdef __USE_PROTOS
+void aPred(void);
+#else
+extern void aPred();
+#endif
+
+#ifdef __USE_PROTOS
+extern Predicate * predOrExpr(void);
+#else
+extern Predicate * predOrExpr();
+#endif
+
+#ifdef __USE_PROTOS
+extern Predicate * predAndExpr(void);
+#else
+extern Predicate * predAndExpr();
+#endif
+
+#ifdef __USE_PROTOS
+extern Predicate * predPrimary(void);
+#else
+extern Predicate * predPrimary();
+#endif
+
+#ifdef __USE_PROTOS
+void aLexclass(void);
+#else
+extern void aLexclass();
+#endif
+
+#ifdef __USE_PROTOS
+void error(void);
+#else
+extern void error();
+#endif
+
+#ifdef __USE_PROTOS
+void tclass(void);
+#else
+extern void tclass();
+#endif
+
+#ifdef __USE_PROTOS
+void token(void);
+#else
+extern void token();
+#endif
+
+#ifdef __USE_PROTOS
+void block(set * toksrefd,set * rulesrefd);
+#else
+extern void block();
+#endif
+
+#ifdef __USE_PROTOS
+void alt(set * toksrefd,set * rulesrefd);
+#else
+extern void alt();
+#endif
+
+#ifdef __USE_PROTOS
+extern LabelEntry * element_label(void);
+#else
+extern LabelEntry * element_label();
+#endif
+
+#ifdef __USE_PROTOS
+extern Node * element(int old_not,int first_on_line,int use_def_MT_handler);
+#else
+extern Node * element();
+#endif
+
+#ifdef __USE_PROTOS
+void default_exception_handler(void);
+#else
+extern void default_exception_handler();
+#endif
+
+#ifdef __USE_PROTOS
+extern ExceptionGroup * exception_group(void);
+#else
+extern ExceptionGroup * exception_group();
+#endif
+
+#ifdef __USE_PROTOS
+extern ExceptionHandler * exception_handler(void);
+#else
+extern ExceptionHandler * exception_handler();
+#endif
+
+#ifdef __USE_PROTOS
+void enum_file(char * fname);
+#else
+extern void enum_file();
+#endif
+
+#ifdef __USE_PROTOS
+void defines(char * fname);
+#else
+extern void defines();
+#endif
+
+#ifdef __USE_PROTOS
+void enum_def(char * fname);
+#else
+extern void enum_def();
+#endif
+
+#endif
+extern SetWordType zzerr1[];
+extern SetWordType zzerr2[];
+extern SetWordType zzerr3[];
+extern SetWordType zzerr4[];
+extern SetWordType setwd1[];
+extern SetWordType zzerr5[];
+extern SetWordType zzerr6[];
+extern SetWordType zzerr7[];
+extern SetWordType zzerr8[];
+extern SetWordType zzerr9[];
+extern SetWordType setwd2[];
+extern SetWordType zzerr10[];
+extern SetWordType zzerr11[];
+extern SetWordType zzerr12[];
+extern SetWordType zzerr13[];
+extern SetWordType setwd3[];
+extern SetWordType zzerr14[];
+extern SetWordType zzerr15[];
+extern SetWordType zzerr16[];
+extern SetWordType zzerr17[];
+extern SetWordType zzerr18[];
+extern SetWordType zzerr19[];
+extern SetWordType zzerr20[];
+extern SetWordType zzerr21[];
+extern SetWordType setwd4[];
+extern SetWordType zzerr22[];
+extern SetWordType zzerr23[];
+extern SetWordType zzerr24[];
+extern SetWordType zzerr25[];
+extern SetWordType zzerr26[];
+extern SetWordType setwd5[];
+extern SetWordType zzerr27[];
+extern SetWordType zzerr28[];
+extern SetWordType zzerr29[];
+extern SetWordType zzerr30[];
+extern SetWordType zzerr31[];
+extern SetWordType zzerr32[];
+extern SetWordType zzerr33[];
+extern SetWordType setwd6[];
+extern SetWordType zzerr34[];
+extern SetWordType zzerr35[];
+extern SetWordType zzerr36[];
+extern SetWordType zzerr37[];
+extern SetWordType zzerr38[];
+extern SetWordType zzerr39[];
+extern SetWordType zzerr40[];
+extern SetWordType zzerr41[];
+extern SetWordType zzerr42[];
+extern SetWordType setwd7[];
+extern SetWordType zzerr43[];
+extern SetWordType zzerr44[];
+extern SetWordType zzerr45[];
+extern SetWordType zzerr46[];
+extern SetWordType zzerr47[];
+extern SetWordType zzerr48[];
+extern SetWordType zzerr49[];
+extern SetWordType zzerr50[];
+extern SetWordType zzerr51[];
+extern SetWordType zzerr52[];
+extern SetWordType zzerr53[];
+extern SetWordType setwd8[];
+extern SetWordType zzerr54[];
+extern SetWordType zzerr55[];
+extern SetWordType zzerr56[];
+extern SetWordType zzerr57[];
+extern SetWordType setwd9[];
+extern SetWordType zzerr58[];
+extern SetWordType zzerr59[];
+extern SetWordType zzerr60[];
+extern SetWordType zzerr61[];
+extern SetWordType zzerr62[];
+extern SetWordType zzerr63[];
+extern SetWordType zzerr64[];
+extern SetWordType zzerr65[];
+extern SetWordType setwd10[];
+extern SetWordType setwd11[];
diff --git a/Source/Pccts/build.xml b/Source/Pccts/build.xml
new file mode 100644
index 0000000..58a82f4
--- /dev/null
+++ b/Source/Pccts/build.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" ?>
+<!--
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+-->
+<project default="GenTool" basedir=".">
+<!--
+ EDK Pccts Tool
+ Copyright (c) 2006, Intel Corporation
+ <property name="ToolName" value="Pccts"/>
+-->
+
+ <taskdef resource="net/sf/antcontrib/antlib.xml"/>
+
+ <target name="init">
+ <echo message="Building the EDK Pccts Tools"/>
+ </target>
+
+ <target name="GenTool" depends="init, Pccts">
+ <echo message="The EDK Pccts Tools build has completed!"/>
+ </target>
+
+ <target name="Pccts" depends="init">
+ <subant target="" inheritall="true">
+ <fileset dir="${PACKAGE_DIR}/Pccts/antlr" includes="build.xml"/>
+ </subant>
+ <subant target="" inheritall="true">
+ <fileset dir="${PACKAGE_DIR}/Pccts/dlg" includes="build.xml"/>
+ </subant>
+ </target>
+
+ <target name="clean">
+ <ant dir="${PACKAGE_DIR}/Pccts/antlr" target="clean" inheritAll="true"/>
+ <ant dir="${PACKAGE_DIR}/Pccts/dlg" target="clean" inheritAll="true"/>
+ </target>
+
+ <target name="cleanall">
+ <echo message="Removing Object Files and the Executables from the package: Pccts"/>
+ <ant dir="${PACKAGE_DIR}/Pccts/antlr" target="cleanall" inheritAll="true"/>
+ <ant dir="${PACKAGE_DIR}/Pccts/dlg" target="cleanall" inheritAll="true"/>
+ </target>
+
+</project>
diff --git a/Source/Pccts/dlg/DlgMS.mak b/Source/Pccts/dlg/DlgMS.mak
new file mode 100644
index 0000000..086af95
--- /dev/null
+++ b/Source/Pccts/dlg/DlgMS.mak
@@ -0,0 +1,121 @@
+# PCCTS directory
+
+# You will need to set the LIB variable similar to this.
+# LIB="C:/Program Files/Microsoft Visual Studio .NET 2003/Vc7/lib;c:/Microsoft Visual Studio .NET 2003/Vc7/PlatformSDK/Lib"
+
+# PCCTS_HOME=<your PCCTS_HOME>
+PCCTS_HOME=$(WORKSPACE)\Tools\CCode\Source\Pccts
+DLG_SRC=$(PCCTS_HOME)\dlg
+PCCTS_H=$(PCCTS_HOME)\h
+
+
+# Support directories
+SET=$(PCCTS_HOME)\support\set
+
+
+# Compiler stuff
+CC = cl
+CFLAGS = /nologo -I "." -I "$(PCCTS_H)" -I "$(SET)" -D "USER_ZZSYN" -D "PC" \
+ -D "ZZLEXBUFSIZE=65536" /D "LONGFILENAMES" /W3 /Zi
+
+DLG_OBJS = dlg_p.obj dlg_a.obj main.obj err.obj support.obj \
+ output.obj relabel.obj automata.obj
+
+SUPPORT_OBJS = set.obj
+
+# Dependencies
+
+dlg.exe: $(DLG_OBJS) $(SUPPORT_OBJS)
+ $(CC) $(CFLAGS) -o dlg.exe $(DLG_OBJS) $(SUPPORT_OBJS)
+ del *.obj
+ del *.ilk
+ del *.pdb
+ move dlg.exe $(WORKSPACE)\Tools\bin\.
+
+dlg_p.obj: $(DLG_SRC)\dlg_p.c \
+ $(PCCTS_H)\antlr.h \
+ $(PCCTS_H)\config.h \
+ $(PCCTS_H)\dlgdef.h \
+ $(SET)\set.h \
+ $(DLG_SRC)\dlg.h \
+ $(DLG_SRC)\mode.h \
+ $(DLG_SRC)\tokens.h \
+
+ $(CC) -c $(CFLAGS) $(DLG_SRC)\dlg_p.c
+
+dlg_a.obj: $(DLG_SRC)\dlg_a.c \
+ $(PCCTS_H)\antlr.h \
+ $(PCCTS_H)\config.h \
+ $(PCCTS_H)\dlgauto.h \
+ $(PCCTS_H)\dlgdef.h \
+ $(SET)\set.h \
+ $(DLG_SRC)\dlg.h \
+ $(DLG_SRC)\mode.h \
+ $(DLG_SRC)\tokens.h \
+
+ $(CC) -c $(CFLAGS) $(DLG_SRC)\dlg_a.c
+
+main.obj: $(DLG_SRC)\main.c \
+ $(PCCTS_H)\antlr.h \
+ $(PCCTS_H)\config.h \
+ $(PCCTS_H)\dlgdef.h \
+ $(SET)\set.h \
+ $(DLG_SRC)\dlg.h \
+ $(DLG_SRC)\mode.h \
+ $(DLG_SRC)\stdpccts.h \
+ $(DLG_SRC)\tokens.h \
+
+ $(CC) -c $(CFLAGS) $(DLG_SRC)\main.c
+
+err.obj: $(DLG_SRC)\err.c \
+ $(PCCTS_H)\antlr.h \
+ $(PCCTS_H)\config.h \
+ $(PCCTS_H)\dlgdef.h \
+ $(PCCTS_H)\err.h \
+ $(SET)\set.h \
+ $(DLG_SRC)\dlg.h \
+ $(DLG_SRC)\tokens.h \
+
+ $(CC) -c $(CFLAGS) $(DLG_SRC)\err.c
+
+support.obj: $(DLG_SRC)\support.c \
+ $(PCCTS_H)\config.h \
+ $(SET)\set.h \
+ $(DLG_SRC)\dlg.h \
+
+ $(CC) -c $(CFLAGS) $(DLG_SRC)\support.c
+
+output.obj: $(DLG_SRC)\output.c \
+ $(PCCTS_H)\config.h \
+ $(SET)\set.h \
+ $(DLG_SRC)\dlg.h \
+
+ $(CC) -c $(CFLAGS) $(DLG_SRC)\output.c
+
+relabel.obj: $(DLG_SRC)\relabel.c \
+ $(PCCTS_H)\config.h \
+ $(SET)\set.h \
+ $(DLG_SRC)\dlg.h \
+
+ $(CC) -c $(CFLAGS) $(DLG_SRC)\relabel.c
+
+automata.obj: $(DLG_SRC)\automata.c \
+ $(PCCTS_H)\config.h \
+ $(SET)\set.h \
+ $(DLG_SRC)\dlg.h \
+
+ $(CC) -c $(CFLAGS) $(DLG_SRC)\automata.c
+
+
+set.obj: $(SET)\set.c \
+ $(PCCTS_H)\config.h \
+ $(SET)\set.h \
+
+ $(CC) -c $(CFLAGS) $(SET)\set.c
+
+clean:
+ del *.obj
+
+distclean:
+ del *.obj
+ del $(WORKSPACE)\Tools\bin\dlg.exe
diff --git a/Source/Pccts/dlg/DlgPPC.mak b/Source/Pccts/dlg/DlgPPC.mak
new file mode 100644
index 0000000..55b643a
--- /dev/null
+++ b/Source/Pccts/dlg/DlgPPC.mak
@@ -0,0 +1,84 @@
+# File: dlgPPC.make
+# Target: dlgPPC
+# Sources: automata.c
+# dlg_a.c
+# dlg_p.c
+# err.c
+# main.c
+# output.c
+# relabel.c
+# support.c
+# ::support:set:set.c
+# Created: Sunday, May 17, 1998 11:34:20 PM
+# Author: Kenji Tanaka
+
+
+MAKEFILE = dlgPPC.make
+¥MondoBuild¥ = {MAKEFILE} # Make blank to avoid rebuilds when makefile is modified
+Includes = ¶
+ -i "::h:" ¶
+ -i "::support:set:"
+Sym¥PPC =
+ObjDir¥PPC = ":Obj:"
+
+PPCCOptions = {Includes} {Sym¥PPC} -w off -d MPW -d __STDC__=1 -d USER_ZZSYN
+
+Objects¥PPC = ¶
+ "{ObjDir¥PPC}automata.c.x" ¶
+ "{ObjDir¥PPC}dlg_a.c.x" ¶
+ "{ObjDir¥PPC}dlg_p.c.x" ¶
+ "{ObjDir¥PPC}err.c.x" ¶
+ "{ObjDir¥PPC}main.c.x" ¶
+ "{ObjDir¥PPC}output.c.x" ¶
+ "{ObjDir¥PPC}relabel.c.x" ¶
+ "{ObjDir¥PPC}support.c.x" ¶
+ "{ObjDir¥PPC}set.c.x"
+
+
+dlgPPC ÄÄ {¥MondoBuild¥} {Objects¥PPC}
+ PPCLink ¶
+ -o {Targ} {Sym¥PPC} ¶
+ {Objects¥PPC} ¶
+ -t 'MPST' ¶
+ -c 'MPS ' ¶
+ "{SharedLibraries}InterfaceLib" ¶
+ "{SharedLibraries}StdCLib" ¶
+ "{SharedLibraries}MathLib" ¶
+ "{PPCLibraries}StdCRuntime.o" ¶
+ "{PPCLibraries}PPCCRuntime.o" ¶
+ "{PPCLibraries}PPCToolLibs.o"
+
+
+"{ObjDir¥PPC}automata.c.x" Ä {¥MondoBuild¥} automata.c
+ {PPCC} automata.c -o {Targ} {PPCCOptions}
+
+"{ObjDir¥PPC}dlg_a.c.x" Ä {¥MondoBuild¥} dlg_a.c
+ {PPCC} dlg_a.c -o {Targ} {PPCCOptions}
+
+"{ObjDir¥PPC}dlg_p.c.x" Ä {¥MondoBuild¥} dlg_p.c
+ {PPCC} dlg_p.c -o {Targ} {PPCCOptions}
+
+"{ObjDir¥PPC}err.c.x" Ä {¥MondoBuild¥} err.c
+ {PPCC} err.c -o {Targ} {PPCCOptions}
+
+"{ObjDir¥PPC}main.c.x" Ä {¥MondoBuild¥} main.c
+ {PPCC} main.c -o {Targ} {PPCCOptions}
+
+"{ObjDir¥PPC}output.c.x" Ä {¥MondoBuild¥} output.c
+ {PPCC} output.c -o {Targ} {PPCCOptions}
+
+"{ObjDir¥PPC}relabel.c.x" Ä {¥MondoBuild¥} relabel.c
+ {PPCC} relabel.c -o {Targ} {PPCCOptions}
+
+"{ObjDir¥PPC}support.c.x" Ä {¥MondoBuild¥} support.c
+ {PPCC} support.c -o {Targ} {PPCCOptions}
+
+"{ObjDir¥PPC}set.c.x" Ä {¥MondoBuild¥} "::support:set:set.c"
+ {PPCC} "::support:set:set.c" -o {Targ} {PPCCOptions}
+
+
+dlgPPC ÄÄ dlg.r
+ Rez dlg.r -o dlgPPC -a
+
+Install Ä dlgPPC
+ Duplicate -y dlgPPC "{MPW}"Tools:dlg
diff --git a/Source/Pccts/dlg/automata.c b/Source/Pccts/dlg/automata.c
new file mode 100644
index 0000000..d6d5d78
--- /dev/null
+++ b/Source/Pccts/dlg/automata.c
@@ -0,0 +1,353 @@
+/* Automata conversion functions for DLG
+ *
+ * SOFTWARE RIGHTS
+ *
+ * We reserve no LEGAL rights to the Purdue Compiler Construction Tool
+ * Set (PCCTS) -- PCCTS is in the public domain. An individual or
+ * company may do whatever they wish with source code distributed with
+ * PCCTS or the code generated by PCCTS, including the incorporation of
+ * PCCTS, or its output, into commerical software.
+ *
+ * We encourage users to develop software with PCCTS. However, we do ask
+ * that credit is given to us for developing PCCTS. By "credit",
+ * we mean that if you incorporate our source code into one of your
+ * programs (commercial product, research project, or otherwise) that you
+ * acknowledge this fact somewhere in the documentation, research report,
+ * etc... If you like PCCTS and have developed a nice tool with the
+ * output, please mention that you developed it using PCCTS. In
+ * addition, we ask that this header remain intact in our source code.
+ * As long as these guidelines are kept, we expect to continue enhancing
+ * this system and expect to make other tools available as they are
+ * completed.
+ *
+ * DLG 1.33
+ * Will Cohen
+ * With mods by Terence Parr; AHPCRC, University of Minnesota
+ * 1989-2001
+ */
+
+#include <stdio.h>
+#include "pcctscfg.h"
+#include "dlg.h"
+#ifdef MEMCHK
+#include "trax.h"
+#else
+#ifdef __STDC__
+#include <stdlib.h>
+#else
+#include <malloc.h>
+#endif /* __STDC__ */
+#endif
+
+#define hash_list struct _hash_list_
+hash_list{
+ hash_list *next; /* next thing in list */
+ dfa_node *node;
+ };
+
+int dfa_allocated = 0; /* keeps track of number of dfa nodes */
+dfa_node **dfa_array; /* root of binary tree that stores dfa array */
+dfa_node *dfa_model_node;
+hash_list *dfa_hash[HASH_SIZE]; /* used to quickly find */
+ /* desired dfa node */
+
+void
+#ifdef __USE_PROTOS
+make_dfa_model_node(int width)
+#else
+make_dfa_model_node(width)
+int width;
+#endif
+{
+ register int i;
+ dfa_model_node = (dfa_node*) malloc(sizeof(dfa_node)
+ + sizeof(int)*width);
+ dfa_model_node->node_no = -1; /* impossible value for real dfa node */
+ dfa_model_node->dfa_set = 0;
+ dfa_model_node->alternatives = FALSE;
+ dfa_model_node->done = FALSE;
+ dfa_model_node->nfa_states = empty;
+ for(i = 0; i<width; i++){
+ dfa_model_node->trans[i] = NIL_INDEX;
+ }
+}
+
+
+/* adds a new nfa to the binary tree and returns a pointer to it */
+dfa_node *
+#ifdef __USE_PROTOS
+new_dfa_node(set nfa_states)
+#else
+new_dfa_node(nfa_states)
+set nfa_states;
+#endif
+{
+ register int j;
+ register dfa_node *t;
+ static int dfa_size=0; /* elements dfa_array[] can hold */
+
+ ++dfa_allocated;
+ if (dfa_size<=dfa_allocated){
+ /* need to redo array */
+ if (!dfa_array){
+ /* need some to do inital allocation */
+ dfa_size=dfa_allocated+DFA_MIN;
+ dfa_array=(dfa_node **) malloc(sizeof(dfa_node*)*
+ dfa_size);
+ }else{
+ /* need more space */
+ dfa_size=2*(dfa_allocated+1);
+ dfa_array=(dfa_node **) realloc(dfa_array,
+ sizeof(dfa_node*)*dfa_size);
+ }
+ }
+ /* fill out entry in array */
+ t = (dfa_node*) malloc(sizeof(nfa_node)+sizeof(int)*class_no);
+ *t = *dfa_model_node;
+ for (j=0; j<class_no; ++j)
+ t->trans[j] = NIL_INDEX;
+ t->node_no = dfa_allocated;
+ t->nfa_states = set_dup(nfa_states);
+ dfa_array[dfa_allocated] = t;
+ return t;
+}
+
+
+/* past a pointer to the start start of the nfa graph
+ * nfa_to_dfa convers this graph to dfa. The function returns
+ * a pointer to the first dfa state.
+ * NOTE: The function that prints out the table will have to figure out how
+ * to find the other dfa states given the first dfa_state and the number of dfa
+ * nodes allocated
+ */
+dfa_node **
+#ifdef __USE_PROTOS
+nfa_to_dfa(nfa_node *start)
+#else
+nfa_to_dfa(start)
+nfa_node *start;
+#endif
+{
+ register dfa_node *d_state, *trans_d_state;
+ register int a;
+ set t;
+ int last_done;
+ unsigned *nfa_list;
+ unsigned *reach_list;
+
+ reach_list = (unsigned *) malloc((2+nfa_allocated)*sizeof(unsigned));
+ if (!start) return NULL;
+ t = set_of(NFA_NO(start));
+ _set_pdq(t,reach_list);
+ closure(&t,reach_list);
+ /* Make t a dfa state */
+ d_state = dfastate(t);
+ last_done = DFA_NO(d_state);
+
+ do {
+ /* Mark dfa state x as "done" */
+ d_state->done = TRUE;
+ nfa_list = set_pdq(d_state->nfa_states);
+ for (a = 0; a<class_no; ++a) {
+ /* Add NFA states reached by a from d_state */
+ reach(nfa_list,a,reach_list);
+ /* Were any states found? */
+ if ((*reach_list)!=nil) {
+ /* was t=empty; */
+ set_free(t);
+ /* yes, compute closure */
+ closure(&t,reach_list);
+ /* Make DFA state of it ... */
+ trans_d_state = dfastate(t);
+ /* And make transition x->t, labeled with a */
+ d_state->trans[a] = DFA_NO(trans_d_state);
+ d_state->alternatives = TRUE;
+ }
+ }
+ free(nfa_list);
+ ++last_done; /* move forward in queue */
+ /* And so forth until nothing isn't done */
+ d_state = DFA(last_done);
+ } while (last_done<=dfa_allocated);
+
+ free(reach_list);
+ set_free(t);
+
+ /* returns pointer to the array that holds the automaton */
+ return dfa_array;
+}
+
+void
+#ifdef __USE_PROTOS
+clear_hash(void)
+#else
+clear_hash()
+#endif
+{
+ register int i;
+
+ for(i=0; i<HASH_SIZE; ++i)
+ dfa_hash[i] = 0;
+}
+
+#if HASH_STAT
+void
+#ifdef __USE_PROTOS
+fprint_hash_stats(FILE *f)
+#else
+fprint_hash_stats(f)
+FILE *f;
+#endif
+{
+ register hash_list *p;
+ register int i,j;
+ register total;
+
+ total=0;
+ for(i=0; i<HASH_SIZE; ++i){
+ j=0;
+ p = dfa_hash[i];
+ while(p){
+ ++j;
+ p = p->next;
+ }
+ total+=j;
+ fprintf(f,"bin[%d] has %d\n",i,j);
+ }
+ fprintf(f,"total = %d\n",total);
+}
+#endif
+
+/* Returns a pointer to a dfa node that has the same nfa nodes in it.
+ * This may or maynot be a newly created node.
+ */
+dfa_node *
+#ifdef __USE_PROTOS
+dfastate(set nfa_states)
+#else
+dfastate(nfa_states)
+set nfa_states;
+#endif
+{
+ register hash_list *p;
+ int bin;
+
+ /* hash using set and see if it exists */
+ bin = set_hash(nfa_states,HASH_SIZE);
+ p = dfa_hash[bin];
+ while(p && !set_equ(nfa_states,(p->node)->nfa_states)){
+ p = p->next;
+ }
+ if(!p){
+ /* next state to add to hash table */
+ p = (hash_list*)malloc(sizeof(hash_list));
+ p->node = new_dfa_node(nfa_states);
+ p->next = dfa_hash[bin];
+ dfa_hash[bin] = p;
+ }
+ return (p->node);
+}
+
+
+/* this reach assumes the closure has been done already on set */
+int
+#ifdef __USE_PROTOS
+reach(unsigned *nfa_list, register int a, unsigned *reach_list)
+#else
+reach(nfa_list, a, reach_list)
+unsigned *nfa_list;
+register int a;
+unsigned *reach_list;
+#endif
+{
+ register unsigned *e;
+ register nfa_node *node;
+ int t=0;
+
+ e = nfa_list;
+ if (e){
+ while (*e != nil){
+ node = NFA(*e);
+ if (set_el(a,node->label)){
+ t=1;
+ *reach_list=NFA_NO(node->trans[0]);
+ ++reach_list;
+ }
+ ++e;
+ }
+ }
+ *reach_list=nil;
+ return t;
+}
+
+/* finds all the nodes that can be reached by epsilon transitions
+ from the set of a nodes and returns puts them back in set b */
+set
+#ifdef __USE_PROTOS
+closure(set *b, unsigned *reach_list)
+#else
+closure(b, reach_list)
+set *b;
+unsigned *reach_list;
+#endif
+{
+ register nfa_node *node,*n; /* current node being examined */
+ register unsigned *e;
+
+ ++operation_no;
+#if 0
+ t = e = set_pdq(*b);
+#else
+ e=reach_list;
+#endif
+ while (*e != nil){
+ node = NFA(*e);
+ set_orel(NFA_NO(node),b);
+ /* mark it done */
+ node->nfa_set = operation_no;
+ if ((n=node->trans[0]) != NIL_INDEX && set_nil(node->label) &&
+ (n->nfa_set != operation_no)){
+ /* put in b */
+ set_orel(NFA_NO(n),b);
+ close1(n,operation_no,b);
+ }
+ if ((n=node->trans[1]) != NIL_INDEX &&
+ (n->nfa_set != operation_no)){
+ /* put in b */
+ set_orel(NFA_NO(node->trans[1]),b);
+ close1(n,operation_no,b);
+ }
+ ++e;
+ }
+#if 0
+ free(t);
+#endif
+ return *b;
+}
+
+#ifdef __USE_PROTOS
+void close1(nfa_node *node, int o, set *b)
+#else
+void close1(node,o,b)
+nfa_node *node;
+int o; /* marker to avoid cycles */
+set *b;
+#endif
+{
+ register nfa_node *n; /* current node being examined */
+
+ /* mark it done */
+ node->nfa_set = o;
+ if ((n=node->trans[0]) != NIL_INDEX && set_nil(node->label) &&
+ (n->nfa_set != o)){
+ /* put in b */
+ set_orel(NFA_NO(n),b);
+ close1(n,o,b);
+ }
+ if ((n=node->trans[1]) != NIL_INDEX &&
+ (n->nfa_set != o)){
+ /* put in b */
+ set_orel(NFA_NO(node->trans[1]),b);
+ close1(n,o,b);
+ }
+}
diff --git a/Source/Pccts/dlg/build.xml b/Source/Pccts/dlg/build.xml
new file mode 100644
index 0000000..da5dbd0
--- /dev/null
+++ b/Source/Pccts/dlg/build.xml
@@ -0,0 +1,127 @@
+<?xml version="1.0" ?>
+<!--
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+-->
+<project default="GenTool" basedir=".">
+<!--
+ EDK Pccts Tool: dlg
+ Copyright (c) 2006, Intel Corporation
+-->
+ <property name="ToolName" value="dlg"/>
+
+ <taskdef resource="net/sf/antcontrib/antlib.xml"/>
+
+ <property name="PACKAGE_DIR" value="${WORKSPACE}/Tools"/>
+
+ <target name="init">
+ <condition property="CheckDepends">
+ <uptodate targetfile="${WORKSPACE}/Tools/bin/dlg.exe">
+ <srcfiles dir="." includes="*.c *.h *.g"/>
+ </uptodate>
+ </condition>
+ <if>
+ <equals arg1="${CheckDepends}" arg2="true"/>
+ <then>
+ <echo message="Executable, dlg.exe, is up to date."/>
+ </then>
+ <else>
+ <echo message="Building the EDK Pccts Tool: ${ToolName}"/>
+ </else>
+ </if>
+ </target>
+
+ <target name="GenTool" depends="init" unless="CheckDepends">
+ <if>
+ <equals arg1="${ToolChain}" arg2="msvc"/>
+ <then>
+ <exec dir="${PACKAGE_DIR}/Pccts/dlg" executable="nmake" failonerror="TRUE">
+ <arg line="/NOLOGO"/>
+ <arg line="-f DlgMS.mak"/>
+ </exec>
+ </then>
+ <elseif>
+ <istrue value="${cygwin}"/>
+ <then>
+ <exec dir="${PACKAGE_DIR}/Pccts/dlg" executable="make" failonerror="TRUE">
+ <arg line="-f makefile.cygwin"/>
+ </exec>
+ </then>
+ </elseif>
+ <elseif>
+ <equals arg1="${ToolChain}" arg2="gcc"/>
+ <then>
+ <exec dir="${PACKAGE_DIR}/Pccts/dlg" executable="make" failonerror="TRUE">
+ <arg line="-s"/>
+ <arg line="-f makefile BIN_DIR=${BIN_DIR}"/>
+ </exec>
+ </then>
+ </elseif>
+ </if>
+ <echo message="The EDK Tool: ${ToolName} build has completed!"/>
+ </target>
+
+ <target name="clean">
+ <echo message="Removing Intermediate Files Only"/>
+ <if>
+ <equals arg1="${ToolChain}" arg2="msvc"/>
+ <then>
+ <exec dir="${PACKAGE_DIR}/Pccts/dlg" executable="nmake" failonerror="TRUE">
+ <arg line="/C"/>
+ <arg line="/NOLOGO"/>
+ <arg line="-f DlgMS.mak clean"/>
+ </exec>
+ </then>
+ <elseif>
+ <istrue value="${cygwin}"/>
+ <then>
+ <exec dir="${PACKAGE_DIR}/Pccts/dlg" executable="make" failonerror="TRUE">
+ <arg line="-f makefile.cygwin clean"/>
+ </exec>
+ </then>
+ </elseif>
+ <elseif>
+ <equals arg1="${ToolChain}" arg2="gcc"/>
+ <then>
+ <exec dir="${PACKAGE_DIR}/Pccts/dlg" executable="make" failonerror="TRUE">
+ <arg line="-s"/>
+ <arg line="-f makefile clean"/>
+ </exec>
+ </then>
+ </elseif>
+ </if>
+ </target>
+
+ <target name="cleanall">
+ <echo message="Removing Object Files and the Executable: ${ToolName}${ext_exe}"/>
+ <if>
+ <equals arg1="${ToolChain}" arg2="msvc"/>
+ <then>
+ <exec dir="${PACKAGE_DIR}/Pccts/dlg" executable="nmake" failonerror="FALSE">
+ <arg line="/C"/>
+ <arg line="/NOLOGO"/>
+ <arg line="-f DlgMS.mak clean"/>
+ </exec>
+ </then>
+ <elseif>
+ <equals arg1="${ToolChain}" arg2="gcc"/>
+ <then>
+ <exec dir="${PACKAGE_DIR}/Pccts/dlg" executable="make" failonerror="FALSE">
+ <arg line="-s"/>
+ <arg line="-f makefile clean"/>
+ </exec>
+ </then>
+ </elseif>
+ </if>
+ <delete failonerror="false" quiet="true" includeEmptyDirs="true">
+ <fileset file="${BIN_DIR}/${ToolName}${ext_exe}"/>
+ </delete>
+ </target>
+
+</project>
diff --git a/Source/Pccts/dlg/dlg.1 b/Source/Pccts/dlg/dlg.1
new file mode 100644
index 0000000..f68e3ae
--- /dev/null
+++ b/Source/Pccts/dlg/dlg.1
@@ -0,0 +1,79 @@
+.TH dlg 1 "April 1994" "DLG" "PCCTS Manual Pages"
+.SH NAME
+dlg \- DFA Lexical Analyzer Generator
+.SH SYNTAX
+.LP
+\fBdlg\fR [\fIoptions\fR] \fIlexical_spec\fR [\fIoutput_file\fR]
+.SH DESCRIPTION
+.B dlg
+is a tool that produces fast deterministic finite automata for recognizing
+regular expressions in input.
+.SH OPTIONS
+.IP "\fB-CC\fR"
+Generate C++ output. The \fIoutput_file\fP is not specified in this
+case.
+.IP "\fB-C\fR[\fP level\fR]
+Where \fPlevel\fR is the compression level used. 0 indications no
+compression, 1 removes all unused characters from the transition from table,
+and 2 maps equivalent characters into the same character classes. It is
+suggested that level -C2 is used, since it will significantly reduce the size
+of the dfa produced for lexical analyzer.
+.IP "\fB-m\fP
+Produces the header file for the lexical mode with a name other than
+the default name of "mode.h".
+.IP \fB-i\fP
+An interactive, or as interactive as possible, parser is produced. A character
+is only obtained when required to decide which state to go to. Some care
+must be taken to obtain accept states that do not require look ahead at the
+next character to determine if that is the stop state. Any regular expression
+with a Kleene closure at the end is guaranteed to require another character
+of look ahead.
+.IP "\fB-cl\fP class
+Specify a class name for DLG to generate. The default is DLGLexer.
+'class' will be a subclass of DLGLexerBase; only used for -CC.
+.IP \fB-ci\fP
+The automaton will treat upper and lower case characters identically.
+This is accomplished in the automaton; the characters in the lexical
+buffer are unmodified.
+.IP \fB-cs\fP
+Upper and lower case characters are treated as distinct. This is the
+default.
+.IP "\fB-o\fP dir
+Directory where output files should go (default="."). This is very
+nice for keeping the source directory clear of ANTLR and DLG spawn.
+.IP \fB-Wambiguity\fP
+Warns if more than one regular expression could match the same character
+sequence. The warnings give the numbers of the expressions in the dlg
+lexical specification file. The numbering of the expressions starts at one.
+Multiple warnings may be print for the same expressions.
+.IP \-
+Used in place of file names to get input from standard in or send output
+to standard out.
+.SH "SPECIAL CONSIDERATIONS"
+.PP
+\fIDlg\fP works... we think. There is no implicit guarantee of
+anything. We reserve no \fBlegal\fP rights to the software known as
+the Purdue Compiler Construction Tool Set (PCCTS) \(em PCCTS is in the
+public domain. An individual or company may do whatever they wish
+with source code distributed with PCCTS or the code generated by
+PCCTS, including the incorporation of PCCTS, or its output, into
+commercial software. We encourage users to develop software with
+PCCTS. However, we do ask that credit is given to us for developing
+PCCTS. By "credit", we mean that if you incorporate our source code
+into one of your programs (commercial product, research project, or
+otherwise) that you acknowledge this fact somewhere in the
+documentation, research report, etc... If you like PCCTS and have
+developed a nice tool with the output, please mention that you
+developed it using PCCTS. As long as these guidelines are followed, we
+expect to continue enhancing this system and expect to make other
+tools available as they are completed.
+.SH FILES
+.B mode.h
+,
+.B dlgauto.h
+,
+.B dlgdef.h
+.SH SEE ALSO
+.BR antlr (1),
+.BR pccts (1)
+.SH BUGS
diff --git a/Source/Pccts/dlg/dlg.h b/Source/Pccts/dlg/dlg.h
new file mode 100644
index 0000000..9f387c0
--- /dev/null
+++ b/Source/Pccts/dlg/dlg.h
@@ -0,0 +1,250 @@
+/* dlg header file
+ *
+ * SOFTWARE RIGHTS
+ *
+ * We reserve no LEGAL rights to the Purdue Compiler Construction Tool
+ * Set (PCCTS) -- PCCTS is in the public domain. An individual or
+ * company may do whatever they wish with source code distributed with
+ * PCCTS or the code generated by PCCTS, including the incorporation of
+ * PCCTS, or its output, into commerical software.
+ *
+ * We encourage users to develop software with PCCTS. However, we do ask
+ * that credit is given to us for developing PCCTS. By "credit",
+ * we mean that if you incorporate our source code into one of your
+ * programs (commercial product, research project, or otherwise) that you
+ * acknowledge this fact somewhere in the documentation, research report,
+ * etc... If you like PCCTS and have developed a nice tool with the
+ * output, please mention that you developed it using PCCTS. In
+ * addition, we ask that this header remain intact in our source code.
+ * As long as these guidelines are kept, we expect to continue enhancing
+ * this system and expect to make other tools available as they are
+ * completed.
+ *
+ * DLG 1.33
+ * Will Cohen
+ * With mods by Terence Parr; AHPCRC, University of Minnesota
+ * 1989-2001
+ */
+
+/* MR1 Move pcctscfg.h to top of file */
+
+#include "pcctscfg.h"
+
+/* turn off warnings for unreferenced labels */
+
+#ifdef _MSC_VER
+#pragma warning(disable:4102)
+#endif
+
+#include "set.h"
+
+#define TRUE 1
+#define FALSE 0
+
+/***** output related stuff *******************/
+#define IN input_stream
+#define OUT output_stream
+
+#define MAX_MODES 50 /* number of %%names allowed */
+#define MAX_ON_LINE 10
+
+#define NFA_MIN 64 /* minimum nfa_array size */
+#define DFA_MIN 64 /* minimum dfa_array size */
+
+#define DEFAULT_CLASSNAME "DLGLexer"
+
+/* these macros allow the size of the character set to be easily changed */
+/* NOTE: do NOT change MIN_CHAR since EOF is the lowest char, -1 */
+#define MIN_CHAR (-1) /* lowest possible character possible on input */
+#define MAX_CHAR 255 /* highest possible character possible on input */
+#define CHAR_RANGE (1+(MAX_CHAR) - (MIN_CHAR))
+
+/* indicates that the not an "array" reference */
+#define NIL_INDEX 0
+
+/* size of hash table used to find dfa_states quickly */
+#define HASH_SIZE 211
+
+#define nfa_node struct _nfa_node
+nfa_node {
+ int node_no;
+ int nfa_set;
+ int accept; /* what case to use */
+ nfa_node *trans[2];
+ set label; /* one arc always labelled with epsilon */
+};
+
+#define dfa_node struct _dfa_node
+dfa_node {
+ int node_no;
+ int dfa_set;
+ int alternatives; /* used for interactive mode */
+ /* are more characters needed */
+ int done;
+ set nfa_states;
+ int trans[1];/* size of transition table depends on
+ * number of classes required for automata.
+ */
+
+
+};
+
+/******** macros for accessing the NFA and DFA nodes ****/
+#define NFA(x) (nfa_array[x])
+#define DFA(x) (dfa_array[x])
+#define DFA_NO(x) ( (x) ? (x)->node_no : NIL_INDEX)
+#define NFA_NO(x) ( (x) ? (x)->node_no : NIL_INDEX)
+
+/******** wrapper for memory checking ***/
+/*#define malloc(x) dlg_malloc((x),__FILE__,__LINE__)*/
+
+/*#define calloc(x,y) dlg_calloc((x),(y),__FILE__,__LINE__)*/
+
+/******** antlr attributes *************/
+typedef struct {
+ unsigned char letter;
+ nfa_node *l,*r;
+ set label;
+ } Attrib;
+
+#define zzcr_attr(attr, token, text) { \
+ (attr)->letter = text[0]; (attr)->l = NULL; \
+ (attr)->r = NULL; (attr)->label = empty; \
+}
+#define zzd_attr(a) set_free((a)->label);
+
+/******************** Variable ******************************/
+extern char program[]; /* tells what program this is */
+extern char version[]; /* tells what version this is */
+extern char *file_str[]; /* file names being used */
+extern int err_found; /* flag to indicate error occured */
+extern int action_no; /* last action function printed */
+extern int func_action; /* should actions be turned into functions?*/
+extern set used_chars; /* used to label trans. arcs */
+extern set used_classes; /* classes or chars used to label trans. arcs */
+extern int class_no; /* number of classes used */
+extern set class_sets[]; /* shows char. in each class */
+extern set normal_chars; /* mask off unused portion of set */
+extern int comp_level; /* what compression level to use */
+extern int interactive; /* interactive scanner (avoid lookahead)*/
+extern int mode_counter; /* keeps track of the number of %%name */
+extern int dfa_basep[]; /* start of each group of dfa */
+extern int dfa_class_nop[];/* number of transistion arcs in */
+ /* each dfa in each mode */
+extern int nfa_allocated;
+extern int dfa_allocated;
+extern nfa_node **nfa_array; /* start of nfa "array" */
+extern dfa_node **dfa_array; /* start of dfa "array" */
+extern int operation_no; /* unique number for each operation */
+extern FILE *input_stream; /* where description read from */
+extern FILE *output_stream; /* where to put the output */
+extern FILE *mode_stream; /* where to put the mode output */
+extern FILE *class_stream;
+extern char *mode_file; /* name of file for mode output */
+extern int gen_ansi; /* produce ansi compatible code */
+extern int case_insensitive;/* ignore case of input spec. */
+extern int warn_ambig; /* show if regular expressions ambiguous */
+extern int gen_cpp;
+extern char *cl_file_str;
+extern int firstLexMember; /* MR1 */
+extern char *OutputDirectory;
+extern char *class_name;
+
+/******************** Functions ******************************/
+#ifdef __USE_PROTOS
+extern char *dlg_malloc(int, char *, int); /* wrapper malloc */
+extern char *dlg_calloc(int, int, char *, int); /* wrapper calloc */
+extern int reach(unsigned *, register int, unsigned *);
+extern set closure(set *, unsigned *);
+extern dfa_node *new_dfa_node(set);
+extern nfa_node *new_nfa_node(void);
+extern dfa_node *dfastate(set);
+extern dfa_node **nfa_to_dfa(nfa_node *);
+extern void internal_error(char *, char *, int); /* MR9 23-Sep-97 */
+extern FILE *read_stream(char *); /* opens file for reading */
+extern FILE *write_stream(char *); /* opens file for writing */
+extern void make_nfa_model_node(void);
+extern void make_dfa_model_node(int);
+extern char *ClassName(char *);
+extern char *OutMetaName(char *);
+extern void error(char*, int);
+extern void warning(char*, int);
+extern void p_head(void);
+extern void p_class_hdr(void);
+extern void p_includes(void);
+extern void p_tables(void);
+extern void p_tail(void); /* MR1 */
+extern void p_class_def1(void); /* MR1 */
+extern void new_automaton_mode(void); /* MR1 */
+extern int relabel(nfa_node *,int); /* MR1 */
+extern void p_shift_table(int); /* MR1 */
+extern void p_bshift_table(void); /* MR1 */
+extern void p_class_table(void); /* MR1 */
+extern void p_mode_def(char *,int); /* MR1 */
+extern void init(void); /* MR1 */
+extern void p_class_def2(void); /* MR1 */
+extern void clear_hash(void); /* MR1 */
+extern void p_alternative_table(void); /* MR1 */
+extern void p_node_table(void); /* MR1 */
+extern void p_dfa_table(void); /* MR1 */
+extern void p_accept_table(void); /* MR1 */
+extern void p_action_table(void); /* MR1 */
+extern void p_base_table(void); /* MR1 */
+extern void p_single_node(int,int); /* MR1 */
+extern char * minsize(int); /* MR1 */
+extern void close1(nfa_node *,int,set *); /* MR1 */
+extern void partition(nfa_node *,int); /* MR1 */
+extern void intersect_nfa_labels(nfa_node *,set *); /* MR1 */
+extern void r_intersect(nfa_node *,set *); /* MR1 */
+extern void label_node(nfa_node *); /* MR1 */
+extern void label_with_classes(nfa_node *); /* MR1 */
+
+#else
+extern char *dlg_malloc(); /* wrapper malloc */
+extern char *dlg_calloc(); /* wrapper calloc */
+extern int reach();
+extern set closure();
+extern dfa_node *new_dfa_node();
+extern nfa_node *new_nfa_node();
+extern dfa_node *dfastate();
+extern dfa_node **nfa_to_dfa();
+extern void internal_error(); /* MR9 23-Sep-97 */
+extern FILE *read_stream(); /* opens file for reading */
+extern FILE *write_stream(); /* opens file for writing */
+extern void make_nfa_model_node();
+extern void make_dfa_model_node();
+extern char *ClassName();
+extern char *OutMetaName();
+extern void error();
+extern void warning();
+extern void p_head(); /* MR9 */
+extern void p_class_hdr(); /* MR9 */
+extern void p_includes(); /* MR9 */
+extern void p_tables(); /* MR9 */
+extern void p_tail(); /* MR1 */
+extern void p_class_def1(); /* MR1 */
+extern void new_automaton_mode(); /* MR1 */
+extern int relabel(); /* MR1 */
+extern void p_shift_table(); /* MR1 */
+extern void p_bshift_table(); /* MR1 */
+extern void p_class_table(); /* MR1 */
+extern void p_mode_def(); /* MR1 */
+extern void init(); /* MR1 */
+extern void p_class_def2(); /* MR1 */
+extern void clear_hash(); /* MR1 */
+extern void p_alternative_table(); /* MR1 */
+extern void p_node_table(); /* MR1 */
+extern void p_dfa_table(); /* MR1 */
+extern void p_accept_table(); /* MR1 */
+extern void p_action_table(); /* MR1 */
+extern void p_base_table(); /* MR1 */
+extern void p_single_node(); /* MR1 */
+extern char * minsize(); /* MR1 */
+extern void close1(); /* MR1 */
+extern void partition(); /* MR1 */
+extern void intersect_nfa_labels(); /* MR1 */
+extern void r_intersect(); /* MR1 */
+extern void label_node(); /* MR1 */
+extern void label_with_classes(); /* MR1 */
+
+#endif
diff --git a/Source/Pccts/dlg/dlg.r b/Source/Pccts/dlg/dlg.r
new file mode 100644
index 0000000..c5311fa
--- /dev/null
+++ b/Source/Pccts/dlg/dlg.r
@@ -0,0 +1,275 @@
+/*
+ File: dlgMPW.r
+ Target: dlg 133MR
+ Created: Monday, June 15, 1998 4:44:11 AM
+ Author: Kenji Tanaka (kentar@osa.att.ne.jp)
+*/
+
+#include "cmdo.r"
+
+resource 'cmdo' (128, "Dlg") {
+ { /* array dialogs: 1 elements */
+ /* [1] */
+ 295,
+ "DLG -- Purdue Compiler Construction Tool"
+ " Set (PCCTS) lexical analyzer generator.",
+ { /* array itemArray: 18 elements */
+ /* [1] */
+ NotDependent {
+
+ },
+ CheckOption {
+ NotSet,
+ {35, 175, 50, 225},
+ "On",
+ "-CC",
+ "When this control is checked, DLG genera"
+ "tes a scanner using C++ classes rather t"
+ "han C functions."
+ },
+ /* [2] */
+ Or {
+ { /* array OrArray: 1 elements */
+ /* [1] */
+ 1
+ }
+ },
+ RegularEntry {
+ "Lexer Class Name:",
+ {35, 225, 50, 355},
+ {35, 355, 51, 450},
+ "DLGLexer",
+ keepCase,
+ "-cl",
+ "This entry specifies the name DLG uses f"
+ "or the C++ lexer class."
+ },
+ /* [3] */
+ NotDependent {
+
+ },
+ TextBox {
+ gray,
+ {25, 165, 60, 460},
+ "C++ Code Generation"
+ },
+ /* [4] */
+ NotDependent {
+
+ },
+ Files {
+ InputFile,
+ RequiredFile {
+ {37, 25, 56, 135},
+ "Input File",
+ "",
+ "Choose the lexical description file for "
+ "DLG to process."
+ },
+ Additional {
+ "",
+ "",
+ "",
+ "",
+ { /* array TypesArray: 1 elements */
+ /* [1] */
+ text
+ }
+ }
+ },
+ /* [5] */
+ Or {
+ { /* array OrArray: 1 elements */
+ /* [1] */
+ -1
+ }
+ },
+ Files {
+ OutputFile,
+ RequiredFile {
+ {66, 25, 85, 135},
+ "Output File",
+ "",
+ "Choose the name of the file that will ho"
+ "ld the DLG-produced scanner."
+ },
+ NoMore {
+
+ }
+ },
+ /* [6] */
+ Or {
+ { /* array OrArray: 2 elements */
+ /* [1] */
+ 1,
+ /* [2] */
+ 5
+ }
+ },
+ Dummy {
+
+ },
+ /* [7] */
+ NotDependent {
+
+ },
+ Redirection {
+ DiagnosticOutput,
+ {90, 25}
+ },
+ /* [8] */
+ NotDependent {
+
+ },
+ TextBox {
+ gray,
+ {25, 20, 132, 145},
+ "Files"
+ },
+ /* [9] */
+ NotDependent {
+
+ },
+ Files {
+ DirOnly,
+ OptionalFile {
+ {68, 175, 84, 305},
+ {88, 175, 107, 305},
+ "Output Directory",
+ ":",
+ "-o",
+ "",
+ "Choose the directory where DLG will put "
+ "its output.",
+ dim,
+ "Output DirectoryI",
+ "",
+ ""
+ },
+ NoMore {
+
+ }
+ },
+ /* [10] */
+ NotDependent {
+
+ },
+ RegularEntry {
+ "Mode File Name:",
+ {68, 315, 83, 450},
+ {88, 315, 104, 450},
+ "mode.h",
+ keepCase,
+ "-m",
+ "This entry specifies the name DLG uses f"
+ "or its lexical mode output file."
+ },
+ /* [11] */
+ NotDependent {
+
+ },
+ RadioButtons {
+ { /* array radioArray: 3 elements */
+ /* [1] */
+ {134, 175, 149, 255}, "None", "", Set, "When this option is selected, DLG will n"
+ "ot compress its tables.",
+ /* [2] */
+ {134, 265, 149, 345}, "Level 1", "-C1", NotSet, "When this option is selected, DLG will r"
+ "emove all unused characters from the tra"
+ "nsition-from table.",
+ /* [3] */
+ {134, 360, 149, 450}, "Level 2", "-C2", NotSet, "When this option is selected, DLG will p"
+ "erform level 1 compression plus it will "
+ "map equivalent characters into the same "
+ "character classes."
+ }
+ },
+ /* [12] */
+ NotDependent {
+
+ },
+ TextBox {
+ gray,
+ {124, 165, 156, 460},
+ "Table Compression"
+ },
+ /* [13] */
+ NotDependent {
+
+ },
+ CheckOption {
+ Set,
+ {165, 20, 180, 145},
+ "Case Sensitive",
+ "-ci",
+ "When this control is checked, the DLG au"
+ "tomaton will treat upper and lower case "
+ "characters identically."
+ },
+ /* [14] */
+ NotDependent {
+
+ },
+ CheckOption {
+ NotSet,
+ {165, 150, 180, 300},
+ "Interactive Scanner",
+ "-i",
+ "When this control is checked, DLG will g"
+ "enerate as interactive a scanner as poss"
+ "ible."
+ },
+ /* [15] */
+ NotDependent {
+
+ },
+ CheckOption {
+ NotSet,
+ {165, 310, 180, 460},
+ "Ambiguity Warnings",
+ "-Wambiguity",
+ "When this control is checked, DLG warns "
+ "if more than one regular expression coul"
+ "d match the same character sequence."
+ },
+ /* [16] */
+ NotDependent {
+
+ },
+ VersionDialog {
+ VersionString {
+ "1.33MR"
+ },
+ "PCCTS was written by Terence Parr, Russe"
+ "ll Quong, Will Cohen, and Hank Dietz: 19"
+ "89-1998. MPW port by Scott Haney.",
+ noDialog
+ },
+ /* [17] */
+ And {
+ { /* array AndArray: 2 elements */
+ /* [1] */
+ 4,
+ /* [2] */
+ 6
+ }
+ },
+ DoItButton {
+
+ },
+ /* [18] */
+ NotDependent {
+
+ },
+ CheckOption {
+ NotSet,
+ {142, 20, 157, 148},
+ "Generate ANSI C",
+ "-ga",
+ "When this control is checked, DLG genera"
+ "tes ANSI C compatible code."
+ }
+ }
+ }
+};
+
diff --git a/Source/Pccts/dlg/dlg1.txt b/Source/Pccts/dlg/dlg1.txt
new file mode 100644
index 0000000..06b320d
--- /dev/null
+++ b/Source/Pccts/dlg/dlg1.txt
@@ -0,0 +1,132 @@
+
+
+
+dlg(1) PCCTS Manual Pages dlg(1)
+
+
+
+NAME
+ dlg - DFA Lexical Analyzer Generator
+
+SYNTAX
+ dlg [_o_p_t_i_o_n_s] _l_e_x_i_c_a_l__s_p_e_c [_o_u_t_p_u_t__f_i_l_e]
+
+DESCRIPTION
+ dlg is a tool that produces fast deterministic finite auto-
+ mata for recognizing regular expressions in input.
+
+OPTIONS
+ -CC Generate C++ output. The _o_u_t_p_u_t__f_i_l_e is not specified
+ in this case.
+
+ -C[ level]
+ Where level is the compression level used. 0 indica-
+ tions no compression, 1 removes all unused characters
+ from the transition from table, and 2 maps equivalent
+ characters into the same character classes. It is sug-
+ gested that level -C2 is used, since it will signifi-
+ cantly reduce the size of the dfa produced for lexical
+ analyzer.
+
+ -m Produces the header file for the lexical mode with a
+ name other than the default name of "mode.h".
+
+ -i An interactive, or as interactive as possible, parser
+ is produced. A character is only obtained when
+ required to decide which state to go to. Some care
+ must be taken to obtain accept states that do not
+ require look ahead at the next character to determine
+ if that is the stop state. Any regular expression with
+ a Kleene closure at the end is guaranteed to require
+ another character of look ahead.
+
+ -cl class
+ Specify a class name for DLG to generate. The default
+ is DLGLexer.
+
+ -ci The automaton will treat upper and lower case charac-
+ ters identically. This is accomplished in the automa-
+ ton; the characters in the lexical buffer are unmodi-
+ fied.
+
+ -cs Upper and lower case characters are treated as dis-
+ tinct. This is the default.
+
+ -o dir
+ Directory where output files should go (default=".").
+ This is very nice for keeping the source directory
+ clear of ANTLR and DLG spawn.
+
+ -Wambiguity
+ Warns if more than one regular expression could match
+ the same character sequence. The warnings give the
+ numbers of the expressions in the dlg lexical specifi-
+ cation file. The numbering of the expressions starts
+ at one. Multiple warnings may be print for the same
+ expressions.
+
+ - Used in place of file names to get input from standard
+ in or send output to standard out.
+
+SPECIAL CONSIDERATIONS
+ _D_l_g works... we think. There is no implicit guarantee of
+ anything. We reserve no legal rights to the software known
+ as the Purdue Compiler Construction Tool Set (PCCTS) - PCCTS
+ is in the public domain. An individual or company may do
+ whatever they wish with source code distributed with PCCTS
+ or the code generated by PCCTS, including the incorporation
+ of PCCTS, or its output, into commercial software. We
+ encourage users to develop software with PCCTS. However, we
+ do ask that credit is given to us for developing PCCTS. By
+ "credit", we mean that if you incorporate our source code
+ into one of your programs (commercial product, research pro-
+ ject, or otherwise) that you acknowledge this fact somewhere
+ in the documentation, research report, etc... If you like
+ PCCTS and have developed a nice tool with the output, please
+ mention that you developed it using PCCTS. As long as these
+ guidelines are followed, we expect to continue enhancing
+ this system and expect to make other tools available as they
+ are completed.
+
+FILES
+ mode.h , dlgauto.h , dlgdef.h
+
+SEE ALSO
+ antlr(1), pccts(1)
+
+BUGS
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Source/Pccts/dlg/dlg_a.c b/Source/Pccts/dlg/dlg_a.c
new file mode 100644
index 0000000..0b8982c
--- /dev/null
+++ b/Source/Pccts/dlg/dlg_a.c
@@ -0,0 +1,1414 @@
+
+/* parser.dlg -- DLG Description of scanner
+ *
+ * Generated from: dlg_p.g
+ *
+ * Terence Parr, Will Cohen, and Hank Dietz: 1989-2001
+ * Purdue University Electrical Engineering
+ * With AHPCRC, University of Minnesota
+ * ANTLR Version 1.33MR33
+ */
+
+#define ANTLR_VERSION 13333
+#include "pcctscfg.h"
+#include "pccts_stdio.h"
+
+#include <ctype.h>
+#include "dlg.h"
+#include "antlr.h"
+#include "tokens.h"
+#include "dlgdef.h"
+LOOKAHEAD
+
+void
+#ifdef __USE_PROTOS
+zzerraction(void)
+#else
+zzerraction()
+#endif
+{
+ (*zzerr)("invalid token");
+ zzadvance();
+ zzskip();
+}
+/*
+ * D L G tables
+ *
+ * Generated from: parser.dlg
+ *
+ * 1989-2001 by Will Cohen, Terence Parr, and Hank Dietz
+ * Purdue University Electrical Engineering
+ * DLG Version 1.33MR33
+ */
+
+#include "mode.h"
+
+
+
+
+int func_action; /* should actions be turned into functions?*/
+int lex_mode_counter = 0; /* keeps track of the number of %%names */
+/* MR1 */
+/* MR1 11-Apr-97 Provide mechanism for inserting code into DLG class */
+/* MR1 via <<%%lexmember...>> */
+/* MR1 */
+int lexMember = 0; /* <<%%lexmemeber ...>> MR1 */
+int lexAction = 0; /* <<%%lexaction ...>> MR1 */
+int parserClass = 0; /* <<%%parserclass ...>> MR1 */
+int lexPrefix = 0; /* <<%%lexprefix ...>> MR1 */
+char theClassName[100]; /* MR11 */
+char *pClassName=theClassName; /* MR11 */
+int firstLexMember=1; /* MR1 */
+
+#ifdef __USE_PROTOS
+void xxputc(int c) { /* MR1 */
+#else
+ void xxputc(c) /* MR1 */
+ int c; /* MR1 */
+ { /* MR1 */
+#endif
+ if (parserClass) { /* MR1 */
+ *pClassName++=c; /* MR1 */
+ *pClassName=0; /* MR1 */
+ } else if (lexMember || lexPrefix) { /* MR1 */
+ if (class_stream != NULL) fputc(c,class_stream); /* MR1 */
+ } else { /* MR1 */
+ fputc(c,OUT); /* MR1 */
+ }; /* MR1 */
+ } /* MR1 */
+
+#ifdef __USE_PROTOS
+ void xxprintf(char *format,char *string) { /* MR1 */
+#else
+ void xxprintf(format,string) /* MR1 */
+ char *format; /* MR1 */
+ char *string; /* MR1 */
+ { /* MR1 */
+#endif
+ if (lexMember || lexPrefix || parserClass) { /* MR1 */
+ if (class_stream != NULL) /* MR1 */
+ fprintf(class_stream,format,string); /* MR1 */
+ } else { /* MR1 */
+ fprintf(OUT,format,string); /* MR1 */
+ }; /* MR1 */
+ } /* MR1 */
+
+static void act1()
+{
+ NLA = 1;
+ }
+
+
+static void act2()
+{
+ NLA = 2;
+ zzskip();
+ }
+
+
+static void act3()
+{
+ NLA = 3;
+ zzline++; zzskip(); DAWDLE;
+ }
+
+
+static void act4()
+{
+ NLA = L_EOF;
+ }
+
+
+static void act5()
+{
+ NLA = PER_PER;
+ }
+
+
+static void act6()
+{
+ NLA = NAME_PER_PER;
+ p_mode_def(&zzlextext[2],lex_mode_counter++);
+ }
+
+
+static void act7()
+{
+ NLA = LEXMEMBER;
+ lexMember=1; /* MR1 */
+ if (firstLexMember != 0) { /* MR1 */
+ firstLexMember=0; /* MR1 */
+ p_class_def1(); /* MR1 */
+ }; /* MR1 */
+ zzmode(ACT); /* MR1 */
+ }
+
+
+static void act8()
+{
+ NLA = LEXACTION;
+ lexAction=1;zzmode(ACT);
+ }
+
+
+static void act9()
+{
+ NLA = PARSERCLASS;
+ parserClass=1; /* MR1 */
+ zzmode(ACT); /* MR1 */
+ }
+
+
+static void act10()
+{
+ NLA = LEXPREFIX;
+ lexPrefix=1;zzmode(ACT);
+ }
+
+
+static void act11()
+{
+ NLA = ACTION;
+ if (func_action)
+ fprintf(OUT,"\n%s %sact%d()\n{ ",
+ gen_cpp?"ANTLRTokenType":"static void",
+ gen_cpp?ClassName("::"):"", ++action_no);
+ zzmode(ACT); zzskip();
+ }
+
+
+static void act12()
+{
+ NLA = GREAT_GREAT;
+ }
+
+
+static void act13()
+{
+ NLA = L_BRACE;
+ }
+
+
+static void act14()
+{
+ NLA = R_BRACE;
+ }
+
+
+static void act15()
+{
+ NLA = L_PAR;
+ }
+
+
+static void act16()
+{
+ NLA = R_PAR;
+ }
+
+
+static void act17()
+{
+ NLA = L_BRACK;
+ }
+
+
+static void act18()
+{
+ NLA = R_BRACK;
+ }
+
+
+static void act19()
+{
+ NLA = ZERO_MORE;
+ }
+
+
+static void act20()
+{
+ NLA = ONE_MORE;
+ }
+
+
+static void act21()
+{
+ NLA = OR;
+ }
+
+
+static void act22()
+{
+ NLA = RANGE;
+ }
+
+
+static void act23()
+{
+ NLA = NOT;
+ }
+
+
+static void act24()
+{
+ NLA = OCTAL_VALUE;
+ {int t; sscanf(&zzlextext[1],"%o",&t); zzlextext[0] = t;}
+ }
+
+
+static void act25()
+{
+ NLA = HEX_VALUE;
+ {int t; sscanf(&zzlextext[3],"%x",&t); zzlextext[0] = t;}
+ }
+
+
+static void act26()
+{
+ NLA = DEC_VALUE;
+ {int t; sscanf(&zzlextext[1],"%d",&t); zzlextext[0] = t;}
+ }
+
+
+static void act27()
+{
+ NLA = TAB;
+ zzlextext[0] = '\t';
+ }
+
+
+static void act28()
+{
+ NLA = NL;
+ zzlextext[0] = '\n';
+ }
+
+
+static void act29()
+{
+ NLA = CR;
+ zzlextext[0] = '\r';
+ }
+
+
+static void act30()
+{
+ NLA = BS;
+ zzlextext[0] = '\b';
+ }
+
+
+static void act31()
+{
+ NLA = CONTINUATION;
+ zzline++; zzskip();
+ }
+
+
+static void act32()
+{
+ NLA = LIT;
+ zzlextext[0] = zzlextext[1];
+ }
+
+
+static void act33()
+{
+ NLA = REGCHAR;
+ }
+
+static unsigned char shift0[257] = {
+ 0, 40, 40, 40, 40, 40, 40, 40, 40, 40,
+ 1, 2, 40, 40, 1, 40, 40, 40, 40, 40,
+ 40, 40, 40, 40, 40, 40, 40, 40, 40, 40,
+ 40, 40, 40, 1, 40, 40, 40, 40, 4, 40,
+ 40, 30, 31, 34, 35, 40, 37, 40, 40, 23,
+ 24, 24, 24, 24, 24, 24, 24, 25, 25, 40,
+ 40, 26, 40, 27, 40, 3, 21, 21, 21, 21,
+ 21, 21, 22, 22, 22, 22, 22, 22, 22, 22,
+ 22, 22, 22, 22, 22, 22, 22, 22, 22, 20,
+ 22, 22, 32, 39, 33, 40, 22, 40, 11, 9,
+ 12, 21, 6, 19, 22, 22, 14, 22, 22, 5,
+ 8, 16, 15, 17, 22, 10, 18, 13, 22, 22,
+ 22, 7, 22, 22, 28, 36, 29, 38, 40, 40,
+ 40, 40, 40, 40, 40, 40, 40, 40, 40, 40,
+ 40, 40, 40, 40, 40, 40, 40, 40, 40, 40,
+ 40, 40, 40, 40, 40, 40, 40, 40, 40, 40,
+ 40, 40, 40, 40, 40, 40, 40, 40, 40, 40,
+ 40, 40, 40, 40, 40, 40, 40, 40, 40, 40,
+ 40, 40, 40, 40, 40, 40, 40, 40, 40, 40,
+ 40, 40, 40, 40, 40, 40, 40, 40, 40, 40,
+ 40, 40, 40, 40, 40, 40, 40, 40, 40, 40,
+ 40, 40, 40, 40, 40, 40, 40, 40, 40, 40,
+ 40, 40, 40, 40, 40, 40, 40, 40, 40, 40,
+ 40, 40, 40, 40, 40, 40, 40, 40, 40, 40,
+ 40, 40, 40, 40, 40, 40, 40, 40, 40, 40,
+ 40, 40, 40, 40, 40, 40, 40
+};
+
+
+static void act34()
+{
+ NLA = 1;
+ error("unterminated action", zzline); zzmode(START);
+ }
+
+
+static void act35()
+{
+ NLA = ACTION;
+ if (func_action) fprintf(OUT,"}\n\n");
+ zzmode(START);
+ /* MR1 */
+ /* MR1 11-Apr-97 Provide mechanism for inserting code into DLG class */
+ /* MR1 via <<%%lexmember ...>> */
+ /* MR1 This is a consequence of not saving actions */
+ /* MR1 */
+ /* MR1 */ parserClass=0;
+ /* MR1 */ lexPrefix=0;
+ /* MR1 */ lexAction=0;
+ /* MR1 */ lexMember=0;
+ }
+
+
+static void act36()
+{
+ NLA = 34;
+ xxputc(zzlextext[0]); zzskip();
+ }
+
+
+static void act37()
+{
+ NLA = 35;
+ xxputc('>'); zzskip();
+ }
+
+
+static void act38()
+{
+ NLA = 36;
+ xxputc('\\'); zzskip();
+ }
+
+
+static void act39()
+{
+ NLA = 37;
+ xxputc(zzlextext[0]); ++zzline; zzskip();
+ }
+
+
+static void act40()
+{
+ NLA = 38;
+ zzmode(ACTION_COMMENTS); /* MR1 */
+ xxprintf("%s", &(zzlextext[0])); zzskip(); /* MR1 */
+ }
+
+
+static void act41()
+{
+ NLA = 39;
+ zzmode(ACTION_CPP_COMMENTS); /* MR1 */
+ xxprintf("%s", &(zzlextext[0])); zzskip(); /* MR1 */
+ }
+
+
+static void act42()
+{
+ NLA = 40;
+ xxputc(zzlextext[0]); zzskip();
+ }
+
+static unsigned char shift1[257] = {
+ 0, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 6, 3, 6, 6, 6, 6, 6, 6, 6, 6,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 6, 6, 6, 5, 6, 6, 6, 6, 4, 6,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 6, 6, 6, 1, 6, 6, 6, 6, 6, 6,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 6, 6, 6, 2, 6, 6, 6, 6, 6, 6,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 6, 6, 6, 6, 6, 6, 6
+};
+
+
+static void act43()
+{
+ NLA = 1;
+ }
+
+
+static void act44()
+{
+ NLA = 41;
+ zzmode(ACT); /* MR1 */
+ xxprintf("%s", &(zzlextext[0])); zzskip(); /* MR1 */
+ }
+
+
+static void act45()
+{
+ NLA = 42;
+ zzline++; xxputc(zzlextext[0]); zzskip();
+ }
+
+
+static void act46()
+{
+ NLA = 43;
+ xxputc(zzlextext[0]); zzskip();
+ }
+
+static unsigned char shift2[257] = {
+ 0, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 3, 4, 4, 3, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 1, 4, 4, 4, 4, 2, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4
+};
+
+
+static void act47()
+{
+ NLA = 1;
+ }
+
+
+static void act48()
+{
+ NLA = 44;
+ zzmode(ACT); zzline++; /* MR1 */
+ xxprintf("%s", &(zzlextext[0])); zzskip(); /* MR1 */
+ }
+
+
+static void act49()
+{
+ NLA = 45;
+ xxputc(zzlextext[0]); zzskip();
+ }
+
+static unsigned char shift3[257] = {
+ 0, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 1, 2, 2, 1, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2
+};
+
+#define DfaStates 94
+typedef unsigned char DfaState;
+
+static DfaState st0[42] = {
+ 1, 2, 3, 4, 5, 6, 6, 6, 6, 6,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 6, 6, 6, 6, 6, 6, 7, 8, 9, 10,
+ 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
+ 6, 94
+};
+
+static DfaState st1[42] = {
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94
+};
+
+static DfaState st2[42] = {
+ 94, 21, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94
+};
+
+static DfaState st3[42] = {
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94
+};
+
+static DfaState st4[42] = {
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94
+};
+
+static DfaState st5[42] = {
+ 94, 94, 94, 94, 22, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94
+};
+
+static DfaState st6[42] = {
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94
+};
+
+static DfaState st7[42] = {
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 23, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94
+};
+
+static DfaState st8[42] = {
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 24, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94
+};
+
+static DfaState st9[42] = {
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94
+};
+
+static DfaState st10[42] = {
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94
+};
+
+static DfaState st11[42] = {
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94
+};
+
+static DfaState st12[42] = {
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94
+};
+
+static DfaState st13[42] = {
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94
+};
+
+static DfaState st14[42] = {
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94
+};
+
+static DfaState st15[42] = {
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94
+};
+
+static DfaState st16[42] = {
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94
+};
+
+static DfaState st17[42] = {
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94
+};
+
+static DfaState st18[42] = {
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94
+};
+
+static DfaState st19[42] = {
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94
+};
+
+static DfaState st20[42] = {
+ 94, 25, 26, 25, 25, 25, 25, 25, 25, 27,
+ 28, 25, 25, 29, 25, 25, 30, 25, 25, 25,
+ 25, 25, 25, 31, 32, 32, 25, 25, 25, 25,
+ 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+ 25, 94
+};
+
+static DfaState st21[42] = {
+ 94, 21, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94
+};
+
+static DfaState st22[42] = {
+ 94, 94, 94, 94, 94, 33, 33, 33, 33, 33,
+ 33, 33, 33, 33, 33, 33, 33, 33, 33, 33,
+ 33, 33, 33, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94
+};
+
+static DfaState st23[42] = {
+ 94, 94, 94, 94, 34, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94
+};
+
+static DfaState st24[42] = {
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94
+};
+
+static DfaState st25[42] = {
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94
+};
+
+static DfaState st26[42] = {
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94
+};
+
+static DfaState st27[42] = {
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94
+};
+
+static DfaState st28[42] = {
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94
+};
+
+static DfaState st29[42] = {
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94
+};
+
+static DfaState st30[42] = {
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94
+};
+
+static DfaState st31[42] = {
+ 94, 94, 94, 94, 94, 94, 94, 35, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 35, 94, 94, 36, 36, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94
+};
+
+static DfaState st32[42] = {
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 37, 37, 37, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94
+};
+
+static DfaState st33[42] = {
+ 94, 94, 94, 94, 94, 38, 38, 38, 38, 38,
+ 38, 38, 38, 38, 38, 38, 38, 38, 38, 38,
+ 38, 38, 38, 38, 38, 38, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94
+};
+
+static DfaState st34[42] = {
+ 94, 94, 94, 94, 39, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94
+};
+
+static DfaState st35[42] = {
+ 94, 94, 94, 94, 94, 94, 40, 94, 94, 40,
+ 94, 40, 40, 94, 94, 94, 94, 94, 94, 40,
+ 94, 40, 94, 40, 40, 40, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94
+};
+
+static DfaState st36[42] = {
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 36, 36, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94
+};
+
+static DfaState st37[42] = {
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 37, 37, 37, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94
+};
+
+static DfaState st38[42] = {
+ 94, 94, 94, 94, 94, 38, 38, 38, 38, 38,
+ 38, 38, 38, 38, 38, 38, 38, 38, 38, 38,
+ 38, 38, 38, 38, 38, 38, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94
+};
+
+static DfaState st39[42] = {
+ 94, 94, 94, 94, 94, 41, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 42, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94
+};
+
+static DfaState st40[42] = {
+ 94, 94, 94, 94, 94, 94, 40, 94, 94, 40,
+ 94, 40, 40, 94, 94, 94, 94, 94, 94, 40,
+ 94, 40, 94, 40, 40, 40, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94
+};
+
+static DfaState st41[42] = {
+ 94, 94, 94, 94, 94, 94, 43, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94
+};
+
+static DfaState st42[42] = {
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 44, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94
+};
+
+static DfaState st43[42] = {
+ 94, 94, 94, 94, 94, 94, 94, 45, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94
+};
+
+static DfaState st44[42] = {
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 46, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94
+};
+
+static DfaState st45[42] = {
+ 94, 94, 94, 94, 94, 94, 94, 94, 47, 94,
+ 94, 48, 94, 94, 94, 94, 94, 49, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94
+};
+
+static DfaState st46[42] = {
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 50, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94
+};
+
+static DfaState st47[42] = {
+ 94, 94, 94, 94, 94, 94, 51, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94
+};
+
+static DfaState st48[42] = {
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 52, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94
+};
+
+static DfaState st49[42] = {
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 53, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94
+};
+
+static DfaState st50[42] = {
+ 94, 94, 94, 94, 94, 94, 54, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94
+};
+
+static DfaState st51[42] = {
+ 94, 94, 94, 94, 94, 94, 94, 94, 55, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94
+};
+
+static DfaState st52[42] = {
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 56, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94
+};
+
+static DfaState st53[42] = {
+ 94, 94, 94, 94, 94, 94, 57, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94
+};
+
+static DfaState st54[42] = {
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 58, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94
+};
+
+static DfaState st55[42] = {
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 59,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94
+};
+
+static DfaState st56[42] = {
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 60, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94
+};
+
+static DfaState st57[42] = {
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 61,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94
+};
+
+static DfaState st58[42] = {
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 62, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94
+};
+
+static DfaState st59[42] = {
+ 94, 94, 94, 94, 94, 94, 63, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94
+};
+
+static DfaState st60[42] = {
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 64, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94
+};
+
+static DfaState st61[42] = {
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 65, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94
+};
+
+static DfaState st62[42] = {
+ 94, 94, 94, 94, 94, 66, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94
+};
+
+static DfaState st63[42] = {
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 67, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94
+};
+
+static DfaState st64[42] = {
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 68, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94
+};
+
+static DfaState st65[42] = {
+ 94, 94, 94, 94, 94, 94, 94, 69, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94
+};
+
+static DfaState st66[42] = {
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 70, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94
+};
+
+static DfaState st67[42] = {
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94
+};
+
+static DfaState st68[42] = {
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94
+};
+
+static DfaState st69[42] = {
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94
+};
+
+static DfaState st70[42] = {
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 71, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94
+};
+
+static DfaState st71[42] = {
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 72, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94
+};
+
+static DfaState st72[42] = {
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94
+};
+
+static DfaState st73[8] = {
+ 74, 75, 76, 77, 78, 79, 79, 94
+};
+
+static DfaState st74[8] = {
+ 94, 94, 94, 94, 94, 94, 94, 94
+};
+
+static DfaState st75[8] = {
+ 94, 80, 94, 94, 94, 94, 94, 94
+};
+
+static DfaState st76[8] = {
+ 94, 81, 94, 94, 94, 94, 94, 94
+};
+
+static DfaState st77[8] = {
+ 94, 94, 94, 94, 94, 94, 94, 94
+};
+
+static DfaState st78[8] = {
+ 94, 94, 94, 94, 82, 83, 94, 94
+};
+
+static DfaState st79[8] = {
+ 94, 94, 94, 94, 94, 94, 94, 94
+};
+
+static DfaState st80[8] = {
+ 94, 94, 94, 94, 94, 94, 94, 94
+};
+
+static DfaState st81[8] = {
+ 94, 94, 94, 94, 94, 94, 94, 94
+};
+
+static DfaState st82[8] = {
+ 94, 94, 94, 94, 94, 94, 94, 94
+};
+
+static DfaState st83[8] = {
+ 94, 94, 94, 94, 94, 94, 94, 94
+};
+
+static DfaState st84[6] = {
+ 85, 86, 87, 88, 87, 94
+};
+
+static DfaState st85[6] = {
+ 94, 94, 94, 94, 94, 94
+};
+
+static DfaState st86[6] = {
+ 94, 94, 89, 94, 94, 94
+};
+
+static DfaState st87[6] = {
+ 94, 94, 94, 94, 94, 94
+};
+
+static DfaState st88[6] = {
+ 94, 94, 94, 94, 94, 94
+};
+
+static DfaState st89[6] = {
+ 94, 94, 94, 94, 94, 94
+};
+
+static DfaState st90[4] = {
+ 91, 92, 93, 94
+};
+
+static DfaState st91[4] = {
+ 94, 94, 94, 94
+};
+
+static DfaState st92[4] = {
+ 94, 94, 94, 94
+};
+
+static DfaState st93[4] = {
+ 94, 94, 94, 94
+};
+
+
+DfaState *dfa[94] = {
+ st0,
+ st1,
+ st2,
+ st3,
+ st4,
+ st5,
+ st6,
+ st7,
+ st8,
+ st9,
+ st10,
+ st11,
+ st12,
+ st13,
+ st14,
+ st15,
+ st16,
+ st17,
+ st18,
+ st19,
+ st20,
+ st21,
+ st22,
+ st23,
+ st24,
+ st25,
+ st26,
+ st27,
+ st28,
+ st29,
+ st30,
+ st31,
+ st32,
+ st33,
+ st34,
+ st35,
+ st36,
+ st37,
+ st38,
+ st39,
+ st40,
+ st41,
+ st42,
+ st43,
+ st44,
+ st45,
+ st46,
+ st47,
+ st48,
+ st49,
+ st50,
+ st51,
+ st52,
+ st53,
+ st54,
+ st55,
+ st56,
+ st57,
+ st58,
+ st59,
+ st60,
+ st61,
+ st62,
+ st63,
+ st64,
+ st65,
+ st66,
+ st67,
+ st68,
+ st69,
+ st70,
+ st71,
+ st72,
+ st73,
+ st74,
+ st75,
+ st76,
+ st77,
+ st78,
+ st79,
+ st80,
+ st81,
+ st82,
+ st83,
+ st84,
+ st85,
+ st86,
+ st87,
+ st88,
+ st89,
+ st90,
+ st91,
+ st92,
+ st93
+};
+
+
+DfaState accepts[95] = {
+ 0, 1, 2, 3, 4, 33, 33, 33, 33, 13,
+ 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
+ 0, 2, 5, 11, 12, 32, 31, 30, 29, 27,
+ 28, 24, 26, 6, 0, 0, 24, 26, 6, 0,
+ 25, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 7, 8, 10,
+ 0, 0, 9, 0, 34, 36, 38, 39, 42, 42,
+ 35, 37, 41, 40, 0, 43, 46, 46, 45, 44,
+ 0, 47, 48, 49, 0
+};
+
+void (*actions[50])() = {
+ zzerraction,
+ act1,
+ act2,
+ act3,
+ act4,
+ act5,
+ act6,
+ act7,
+ act8,
+ act9,
+ act10,
+ act11,
+ act12,
+ act13,
+ act14,
+ act15,
+ act16,
+ act17,
+ act18,
+ act19,
+ act20,
+ act21,
+ act22,
+ act23,
+ act24,
+ act25,
+ act26,
+ act27,
+ act28,
+ act29,
+ act30,
+ act31,
+ act32,
+ act33,
+ act34,
+ act35,
+ act36,
+ act37,
+ act38,
+ act39,
+ act40,
+ act41,
+ act42,
+ act43,
+ act44,
+ act45,
+ act46,
+ act47,
+ act48,
+ act49
+};
+
+static DfaState dfa_base[] = {
+ 0,
+ 73,
+ 84,
+ 90
+};
+
+static unsigned char *b_class_no[] = {
+ shift0,
+ shift1,
+ shift2,
+ shift3
+};
+
+
+
+#define ZZSHIFT(c) (b_class_no[zzauto][1+c])
+#define MAX_MODE 4
+#include "dlgauto.h"
diff --git a/Source/Pccts/dlg/dlg_p.c b/Source/Pccts/dlg/dlg_p.c
new file mode 100644
index 0000000..e726ae3
--- /dev/null
+++ b/Source/Pccts/dlg/dlg_p.c
@@ -0,0 +1,959 @@
+/*
+ * A n t l r T r a n s l a t i o n H e a d e r
+ *
+ * Terence Parr, Will Cohen, and Hank Dietz: 1989-2001
+ * Purdue University Electrical Engineering
+ * With AHPCRC, University of Minnesota
+ * ANTLR Version 1.33MR33
+ *
+ * ..\bin\antlr dlg_p.g -gh
+ *
+ */
+
+#define ANTLR_VERSION 13333
+#include "pcctscfg.h"
+#include "pccts_stdio.h"
+
+#include <ctype.h>
+#include "dlg.h"
+#define zzSET_SIZE 8
+#include "antlr.h"
+#include "tokens.h"
+#include "dlgdef.h"
+#include "mode.h"
+
+/* MR23 In order to remove calls to PURIFY use the antlr -nopurify option */
+
+#ifndef PCCTS_PURIFY
+#define PCCTS_PURIFY(r,s) memset((char *) &(r),'\0',(s));
+#endif
+
+ANTLR_INFO
+
+
+/* MR20 G. Hobbelt
+Fix for Borland C++ 4.x & 5.x compiling with ALL warnings enabled
+*/
+
+#ifdef __TURBOC__
+#pragma warn -aus /* unused assignment of 'xxx' */
+#endif
+
+int action_no = 0; /* keep track of actions outputed */
+int nfa_allocated = 0; /* keeps track of number of nfa nodes */
+nfa_node **nfa_array = NULL;/* root of binary tree that stores nfa array */
+nfa_node nfa_model_node; /* model to initialize new nodes */
+set used_chars; /* used to label trans. arcs */
+set used_classes; /* classes or chars used to label trans. arcs */
+set normal_chars; /* mask to get rid elements that aren't used
+in set */
+int flag_paren = FALSE;
+int flag_brace = FALSE;
+int mode_counter = 0; /* keep track of number of %%names */
+
+
+
+void
+#ifdef __USE_PROTOS
+grammar(void)
+#else
+grammar()
+#endif
+{
+ zzRULE;
+ zzBLOCK(zztasp1);
+ zzMake0;
+ {
+ p_head(); p_class_hdr(); func_action = FALSE;
+ {
+ zzBLOCK(zztasp2);
+ zzMake0;
+ {
+ while ( (setwd1[LA(1)]&0x1) ) {
+ {
+ zzBLOCK(zztasp3);
+ zzMake0;
+ {
+ if ( (LA(1)==LEXACTION) ) {
+ zzmatch(LEXACTION); zzCONSUME;
+ }
+ else {
+ if ( (LA(1)==LEXMEMBER) ) {
+ zzmatch(LEXMEMBER); zzCONSUME;
+ }
+ else {
+ if ( (LA(1)==LEXPREFIX) ) {
+ zzmatch(LEXPREFIX); zzCONSUME;
+ }
+ else {
+ if ( (LA(1)==PARSERCLASS) ) {
+ zzmatch(PARSERCLASS); zzCONSUME;
+ }
+ else {
+ if ( (LA(1)==ACTION) ) {
+ }
+ else {zzFAIL(1,zzerr1,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}
+ }
+ }
+ }
+ }
+ zzEXIT(zztasp3);
+ }
+ }
+ zzmatch(ACTION); zzCONSUME;
+ zzLOOP(zztasp2);
+ }
+ zzEXIT(zztasp2);
+ }
+ }
+ if ( gen_cpp ) p_includes();
+ start_states();
+ func_action = FALSE; p_tables(); p_tail();
+ {
+ zzBLOCK(zztasp2);
+ zzMake0;
+ {
+ while ( (LA(1)==ACTION) ) {
+ zzmatch(ACTION); zzCONSUME;
+ zzLOOP(zztasp2);
+ }
+ zzEXIT(zztasp2);
+ }
+ }
+ zzmatch(1);
+ if (firstLexMember != 0) p_class_def1();
+ zzCONSUME;
+
+ zzEXIT(zztasp1);
+ return;
+fail:
+ zzEXIT(zztasp1);
+ zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText);
+ zzresynch(setwd1, 0x2);
+ }
+}
+
+void
+#ifdef __USE_PROTOS
+start_states(void)
+#else
+start_states()
+#endif
+{
+ zzRULE;
+ zzBLOCK(zztasp1);
+ zzMake0;
+ {
+ {
+ zzBLOCK(zztasp2);
+ zzMake0;
+ {
+ if ( (LA(1)==PER_PER) ) {
+ zzmatch(PER_PER); zzCONSUME;
+ do_conversion();
+ }
+ else {
+ if ( (LA(1)==NAME_PER_PER) ) {
+ zzmatch(NAME_PER_PER); zzCONSUME;
+ do_conversion();
+ {
+ zzBLOCK(zztasp3);
+ zzMake0;
+ {
+ while ( (LA(1)==NAME_PER_PER) ) {
+ zzmatch(NAME_PER_PER); zzCONSUME;
+ do_conversion();
+ zzLOOP(zztasp3);
+ }
+ zzEXIT(zztasp3);
+ }
+ }
+ }
+ else {zzFAIL(1,zzerr2,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}
+ }
+ zzEXIT(zztasp2);
+ }
+ }
+ zzmatch(PER_PER); zzCONSUME;
+ zzEXIT(zztasp1);
+ return;
+fail:
+ zzEXIT(zztasp1);
+ zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText);
+ zzresynch(setwd1, 0x4);
+ }
+}
+
+void
+#ifdef __USE_PROTOS
+do_conversion(void)
+#else
+do_conversion()
+#endif
+{
+ zzRULE;
+ zzBLOCK(zztasp1);
+ zzMake0;
+ {
+ new_automaton_mode(); func_action = TRUE;
+ rule_list();
+
+ dfa_class_nop[mode_counter] =
+ relabel(zzaArg(zztasp1,1 ).l,comp_level);
+ if (comp_level)
+ p_shift_table(mode_counter);
+ dfa_basep[mode_counter] = dfa_allocated+1;
+ make_dfa_model_node(dfa_class_nop[mode_counter]);
+ nfa_to_dfa(zzaArg(zztasp1,1 ).l);
+ ++mode_counter;
+ func_action = FALSE;
+#ifdef HASH_STAT
+ fprint_hash_stats(stderr);
+#endif
+ zzEXIT(zztasp1);
+ return;
+fail:
+ zzEXIT(zztasp1);
+ zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText);
+ zzresynch(setwd1, 0x8);
+ }
+}
+
+void
+#ifdef __USE_PROTOS
+rule_list(void)
+#else
+rule_list()
+#endif
+{
+ zzRULE;
+ zzBLOCK(zztasp1);
+ zzMake0;
+ {
+ if ( (setwd1[LA(1)]&0x10) ) {
+ rule();
+ zzaRet.l=zzaArg(zztasp1,1 ).l; zzaRet.r=zzaArg(zztasp1,1 ).r;
+ {
+ zzBLOCK(zztasp2);
+ zzMake0;
+ {
+ while ( (setwd1[LA(1)]&0x20) ) {
+ rule();
+ {nfa_node *t1;
+ t1 = new_nfa_node();
+ (t1)->trans[0]=zzaRet.l;
+ (t1)->trans[1]=zzaArg(zztasp2,1 ).l;
+ /* all accept nodes "dead ends" */
+ zzaRet.l=t1; zzaRet.r=NULL;
+ }
+ zzLOOP(zztasp2);
+ }
+ zzEXIT(zztasp2);
+ }
+ }
+ }
+ else {
+ if ( (setwd1[LA(1)]&0x40) ) {
+ zzaRet.l = new_nfa_node(); zzaRet.r = NULL;
+ warning("no regular expressions", zzline);
+ }
+ else {zzFAIL(1,zzerr3,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}
+ }
+ zzEXIT(zztasp1);
+ return;
+fail:
+ zzEXIT(zztasp1);
+ zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText);
+ zzresynch(setwd1, 0x80);
+ }
+}
+
+void
+#ifdef __USE_PROTOS
+rule(void)
+#else
+rule()
+#endif
+{
+ zzRULE;
+ zzBLOCK(zztasp1);
+ zzMake0;
+ {
+ if ( (setwd2[LA(1)]&0x1) ) {
+ reg_expr();
+ zzmatch(ACTION);
+ if (zzaArg(zztasp1,1 ).r != NULL) {
+ zzaRet.l=zzaArg(zztasp1,1 ).l; zzaRet.r=zzaArg(zztasp1,1 ).r; (zzaArg(zztasp1,1 ).r)->accept=action_no;
+ }
+ zzCONSUME;
+
+ }
+ else {
+ if ( (LA(1)==ACTION) ) {
+ zzmatch(ACTION);
+ zzaRet.l = NULL; zzaRet.r = NULL;
+ error("no expression for action ", zzline);
+ zzCONSUME;
+
+ }
+ else {zzFAIL(1,zzerr4,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}
+ }
+ zzEXIT(zztasp1);
+ return;
+fail:
+ zzEXIT(zztasp1);
+ zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText);
+ zzresynch(setwd2, 0x2);
+ }
+}
+
+void
+#ifdef __USE_PROTOS
+reg_expr(void)
+#else
+reg_expr()
+#endif
+{
+ zzRULE;
+ zzBLOCK(zztasp1);
+ zzMake0;
+ {
+ and_expr();
+ zzaRet.l=zzaArg(zztasp1,1 ).l; zzaRet.r=zzaArg(zztasp1,1 ).r;
+ {
+ zzBLOCK(zztasp2);
+ zzMake0;
+ {
+ while ( (LA(1)==OR) ) {
+ zzmatch(OR); zzCONSUME;
+ and_expr();
+ {nfa_node *t1, *t2;
+ t1 = new_nfa_node(); t2 = new_nfa_node();
+ (t1)->trans[0]=zzaRet.l;
+ (t1)->trans[1]=zzaArg(zztasp2,2 ).l;
+ /* MR23 */ if (zzaRet.r != NULL) (zzaRet.r)->trans[1]=t2;
+ if (zzaArg(zztasp2,2 ).r) {
+ (zzaArg(zztasp2,2 ).r)->trans[1]=t2; /* MR20 */
+ }
+ zzaRet.l=t1; zzaRet.r=t2;
+ }
+ zzLOOP(zztasp2);
+ }
+ zzEXIT(zztasp2);
+ }
+ }
+ zzEXIT(zztasp1);
+ return;
+fail:
+ zzEXIT(zztasp1);
+ zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText);
+ zzresynch(setwd2, 0x4);
+ }
+}
+
+void
+#ifdef __USE_PROTOS
+and_expr(void)
+#else
+and_expr()
+#endif
+{
+ zzRULE;
+ zzBLOCK(zztasp1);
+ zzMake0;
+ {
+ repeat_expr();
+
+ zzaRet.l=zzaArg(zztasp1,1 ).l; zzaRet.r=zzaArg(zztasp1,1 ).r;
+ {
+ zzBLOCK(zztasp2);
+ zzMake0;
+ {
+ while ( (setwd2[LA(1)]&0x8) ) {
+ repeat_expr();
+ if (zzaRet.r != NULL) {
+ (zzaRet.r)->trans[1]=zzaArg(zztasp2,1 ).l;
+ zzaRet.r=zzaArg(zztasp2,1 ).r;
+ }
+ zzLOOP(zztasp2);
+ }
+ zzEXIT(zztasp2);
+ }
+ }
+ zzEXIT(zztasp1);
+ return;
+fail:
+ zzEXIT(zztasp1);
+ zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText);
+ zzresynch(setwd2, 0x10);
+ }
+}
+
+void
+#ifdef __USE_PROTOS
+repeat_expr(void)
+#else
+repeat_expr()
+#endif
+{
+ zzRULE;
+ zzBLOCK(zztasp1);
+ zzMake0;
+ {
+ if ( (setwd2[LA(1)]&0x20) ) {
+ expr();
+ zzaRet.l=zzaArg(zztasp1,1 ).l; zzaRet.r=zzaArg(zztasp1,1 ).r;
+ {
+ zzBLOCK(zztasp2);
+ zzMake0;
+ {
+ if ( (LA(1)==ZERO_MORE) ) {
+ zzmatch(ZERO_MORE);
+ { nfa_node *t1,*t2;
+ /* MR23 */ if (zzaRet.r != NULL) (zzaRet.r)->trans[0] = zzaRet.l;
+ t1 = new_nfa_node(); t2 = new_nfa_node();
+ t1->trans[0]=zzaRet.l;
+ t1->trans[1]=t2;
+ /* MR23 */ if (zzaRet.r != NULL) (zzaRet.r)->trans[1]=t2;
+ zzaRet.l=t1;zzaRet.r=t2;
+ }
+ zzCONSUME;
+
+ }
+ else {
+ if ( (LA(1)==ONE_MORE) ) {
+ zzmatch(ONE_MORE);
+ if (zzaRet.r != NULL) (zzaRet.r)->trans[0] = zzaRet.l;
+ zzCONSUME;
+
+ }
+ else {
+ if ( (setwd2[LA(1)]&0x40) ) {
+ }
+ else {zzFAIL(1,zzerr5,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}
+ }
+ }
+ zzEXIT(zztasp2);
+ }
+ }
+ }
+ else {
+ if ( (LA(1)==ZERO_MORE) ) {
+ zzmatch(ZERO_MORE);
+ error("no expression for *", zzline);
+ zzCONSUME;
+
+ }
+ else {
+ if ( (LA(1)==ONE_MORE) ) {
+ zzmatch(ONE_MORE);
+ error("no expression for +", zzline);
+ zzCONSUME;
+
+ }
+ else {zzFAIL(1,zzerr6,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}
+ }
+ }
+ zzEXIT(zztasp1);
+ return;
+fail:
+ zzEXIT(zztasp1);
+ zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText);
+ zzresynch(setwd2, 0x80);
+ }
+}
+
+void
+#ifdef __USE_PROTOS
+expr(void)
+#else
+expr()
+#endif
+{
+ zzRULE;
+ zzBLOCK(zztasp1);
+ zzMake0;
+ {
+ zzaRet.l = new_nfa_node();
+ zzaRet.r = new_nfa_node();
+ if ( (LA(1)==L_BRACK) ) {
+ zzmatch(L_BRACK); zzCONSUME;
+ atom_list();
+ zzmatch(R_BRACK);
+
+ /* MR23 */ if (zzaRet.l != NULL) {
+ (zzaRet.l)->trans[0] = zzaRet.r;
+ (zzaRet.l)->label = set_dup(zzaArg(zztasp1,2 ).label);
+ set_orin(&used_chars,(zzaRet.l)->label);
+ }
+ zzCONSUME;
+
+ }
+ else {
+ if ( (LA(1)==NOT) ) {
+ zzmatch(NOT); zzCONSUME;
+ zzmatch(L_BRACK); zzCONSUME;
+ atom_list();
+ zzmatch(R_BRACK);
+
+ /* MR23 */ if (zzaRet.l != NULL) {
+ (zzaRet.l)->trans[0] = zzaRet.r;
+ (zzaRet.l)->label = set_dif(normal_chars,zzaArg(zztasp1,3 ).label);
+ set_orin(&used_chars,(zzaRet.l)->label);
+ }
+ zzCONSUME;
+
+ }
+ else {
+ if ( (LA(1)==L_PAR) ) {
+ zzmatch(L_PAR); zzCONSUME;
+ reg_expr();
+ zzmatch(R_PAR);
+
+ /* MR23 */ if (zzaRet.l != NULL) {
+ (zzaRet.l)->trans[0] = zzaArg(zztasp1,2 ).l;
+ if (zzaArg(zztasp1,2 ).r) {
+ (zzaArg(zztasp1,2 ).r)->trans[1] = zzaRet.r; /* MR20 */
+ }
+ }
+ zzCONSUME;
+
+ }
+ else {
+ if ( (LA(1)==L_BRACE) ) {
+ zzmatch(L_BRACE); zzCONSUME;
+ reg_expr();
+ zzmatch(R_BRACE);
+
+ /* MR23 */ if (zzaRet.l != NULL) {
+ (zzaRet.l)->trans[0] = zzaArg(zztasp1,2 ).l;
+ (zzaRet.l)->trans[1] = zzaRet.r;
+ if (zzaArg(zztasp1,2 ).r) {
+ (zzaArg(zztasp1,2 ).r)->trans[1] = zzaRet.r; /* MR20 */
+ }
+ }
+ zzCONSUME;
+
+ }
+ else {
+ if ( (setwd3[LA(1)]&0x1) ) {
+ atom();
+
+ /* MR23 */ if (zzaRet.l != NULL) {
+ (zzaRet.l)->trans[0] = zzaRet.r;
+ (zzaRet.l)->label = set_dup(zzaArg(zztasp1,1 ).label);
+ set_orin(&used_chars,(zzaRet.l)->label);
+ }
+ }
+ else {zzFAIL(1,zzerr7,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}
+ }
+ }
+ }
+ }
+ zzEXIT(zztasp1);
+ return;
+fail:
+ zzEXIT(zztasp1);
+ zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText);
+ zzresynch(setwd3, 0x2);
+ }
+}
+
+void
+#ifdef __USE_PROTOS
+atom_list(void)
+#else
+atom_list()
+#endif
+{
+ zzRULE;
+ zzBLOCK(zztasp1);
+ zzMake0;
+ {
+ set_free(zzaRet.label);
+ {
+ zzBLOCK(zztasp2);
+ zzMake0;
+ {
+ while ( (setwd3[LA(1)]&0x4) ) {
+ near_atom();
+ set_orin(&(zzaRet.label),zzaArg(zztasp2,1 ).label);
+ zzLOOP(zztasp2);
+ }
+ zzEXIT(zztasp2);
+ }
+ }
+ zzEXIT(zztasp1);
+ return;
+fail:
+ zzEXIT(zztasp1);
+ zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText);
+ zzresynch(setwd3, 0x8);
+ }
+}
+
+void
+#ifdef __USE_PROTOS
+near_atom(void)
+#else
+near_atom()
+#endif
+{
+ zzRULE;
+ zzBLOCK(zztasp1);
+ zzMake0;
+ {
+ register int i;
+ register int i_prime;
+ anychar();
+ zzaRet.letter=zzaArg(zztasp1,1 ).letter; zzaRet.label=set_of(zzaArg(zztasp1,1 ).letter);
+ i_prime = zzaArg(zztasp1,1 ).letter + MIN_CHAR;
+ if (case_insensitive && islower(i_prime))
+ set_orel(toupper(i_prime)-MIN_CHAR,
+ &(zzaRet.label));
+ if (case_insensitive && isupper(i_prime))
+ set_orel(tolower(i_prime)-MIN_CHAR,
+ &(zzaRet.label));
+ {
+ zzBLOCK(zztasp2);
+ zzMake0;
+ {
+ if ( (LA(1)==RANGE) ) {
+ zzmatch(RANGE); zzCONSUME;
+ anychar();
+ if (case_insensitive){
+ i_prime = zzaRet.letter+MIN_CHAR;
+ zzaRet.letter = (islower(i_prime) ?
+ toupper(i_prime) : i_prime)-MIN_CHAR;
+ i_prime = zzaArg(zztasp2,2 ).letter+MIN_CHAR;
+ zzaArg(zztasp2,2 ).letter = (islower(i_prime) ?
+ toupper(i_prime) : i_prime)-MIN_CHAR;
+ }
+ /* check to see if range okay */
+ {
+ int debugLetter1 = zzaRet.letter;
+ int debugLetter2 = zzaArg(zztasp2,2 ).letter;
+ }
+ if (zzaRet.letter > zzaArg(zztasp2,2 ).letter
+ && zzaArg(zztasp2,2 ).letter != 0xff){ /* MR16 */
+ error("invalid range ", zzline);
+ }
+ for (i=zzaRet.letter; i<= (int)zzaArg(zztasp2,2 ).letter; ++i){
+ set_orel(i,&(zzaRet.label));
+ i_prime = i+MIN_CHAR;
+ if (case_insensitive && islower(i_prime))
+ set_orel(toupper(i_prime)-MIN_CHAR,
+ &(zzaRet.label));
+ if (case_insensitive && isupper(i_prime))
+ set_orel(tolower(i_prime)-MIN_CHAR,
+ &(zzaRet.label));
+ }
+ }
+ else {
+ if ( (setwd3[LA(1)]&0x10) ) {
+ }
+ else {zzFAIL(1,zzerr8,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}
+ }
+ zzEXIT(zztasp2);
+ }
+ }
+ zzEXIT(zztasp1);
+ return;
+fail:
+ zzEXIT(zztasp1);
+ zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText);
+ zzresynch(setwd3, 0x20);
+ }
+}
+
+void
+#ifdef __USE_PROTOS
+atom(void)
+#else
+atom()
+#endif
+{
+ zzRULE;
+ zzBLOCK(zztasp1);
+ zzMake0;
+ {
+ register int i_prime;
+ anychar();
+ zzaRet.label = set_of(zzaArg(zztasp1,1 ).letter);
+ i_prime = zzaArg(zztasp1,1 ).letter + MIN_CHAR;
+ if (case_insensitive && islower(i_prime))
+ set_orel(toupper(i_prime)-MIN_CHAR,
+ &(zzaRet.label));
+ if (case_insensitive && isupper(i_prime))
+ set_orel(tolower(i_prime)-MIN_CHAR,
+ &(zzaRet.label));
+ zzEXIT(zztasp1);
+ return;
+fail:
+ zzEXIT(zztasp1);
+ zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText);
+ zzresynch(setwd3, 0x40);
+ }
+}
+
+void
+#ifdef __USE_PROTOS
+anychar(void)
+#else
+anychar()
+#endif
+{
+ zzRULE;
+ zzBLOCK(zztasp1);
+ zzMake0;
+ {
+ if ( (LA(1)==REGCHAR) ) {
+ zzmatch(REGCHAR);
+ zzaRet.letter = zzaArg(zztasp1,1 ).letter - MIN_CHAR;
+ zzCONSUME;
+
+ }
+ else {
+ if ( (LA(1)==OCTAL_VALUE) ) {
+ zzmatch(OCTAL_VALUE);
+ zzaRet.letter = zzaArg(zztasp1,1 ).letter - MIN_CHAR;
+ zzCONSUME;
+
+ }
+ else {
+ if ( (LA(1)==HEX_VALUE) ) {
+ zzmatch(HEX_VALUE);
+ zzaRet.letter = zzaArg(zztasp1,1 ).letter - MIN_CHAR;
+ zzCONSUME;
+
+ }
+ else {
+ if ( (LA(1)==DEC_VALUE) ) {
+ zzmatch(DEC_VALUE);
+ zzaRet.letter = zzaArg(zztasp1,1 ).letter - MIN_CHAR;
+ zzCONSUME;
+
+ }
+ else {
+ if ( (LA(1)==TAB) ) {
+ zzmatch(TAB);
+ zzaRet.letter = zzaArg(zztasp1,1 ).letter - MIN_CHAR;
+ zzCONSUME;
+
+ }
+ else {
+ if ( (LA(1)==NL) ) {
+ zzmatch(NL);
+ zzaRet.letter = zzaArg(zztasp1,1 ).letter - MIN_CHAR;
+ zzCONSUME;
+
+ }
+ else {
+ if ( (LA(1)==CR) ) {
+ zzmatch(CR);
+ zzaRet.letter = zzaArg(zztasp1,1 ).letter - MIN_CHAR;
+ zzCONSUME;
+
+ }
+ else {
+ if ( (LA(1)==BS) ) {
+ zzmatch(BS);
+ zzaRet.letter = zzaArg(zztasp1,1 ).letter - MIN_CHAR;
+ zzCONSUME;
+
+ }
+ else {
+ if ( (LA(1)==LIT) ) {
+ zzmatch(LIT);
+ zzaRet.letter = zzaArg(zztasp1,1 ).letter - MIN_CHAR;
+ zzCONSUME;
+
+ }
+ else {
+ if ( (LA(1)==L_EOF) ) {
+ zzmatch(L_EOF);
+ zzaRet.letter = 0;
+ zzCONSUME;
+
+ }
+ else {zzFAIL(1,zzerr9,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ zzEXIT(zztasp1);
+ return;
+fail:
+ zzEXIT(zztasp1);
+ /* empty action */
+ zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText);
+ zzresynch(setwd3, 0x80);
+ }
+}
+
+/* adds a new nfa to the binary tree and returns a pointer to it */
+nfa_node *
+#ifdef __USE_PROTOS
+new_nfa_node(void)
+#else
+new_nfa_node()
+#endif
+{
+ register nfa_node *t;
+ static int nfa_size=0; /* elements nfa_array[] can hold */
+
+ ++nfa_allocated;
+ if (nfa_size<=nfa_allocated){
+ /* need to redo array */
+ if (!nfa_array){
+ /* need some to do inital allocation */
+ nfa_size=nfa_allocated+NFA_MIN;
+ nfa_array=(nfa_node **) malloc(sizeof(nfa_node*)*
+ nfa_size);
+ }else{
+ /* need more space */
+ nfa_size=2*(nfa_allocated+1);
+ nfa_array=(nfa_node **) realloc(nfa_array,
+ sizeof(nfa_node*)*nfa_size);
+ }
+ }
+ /* fill out entry in array */
+ t = (nfa_node*) malloc(sizeof(nfa_node));
+ nfa_array[nfa_allocated] = t;
+ *t = nfa_model_node;
+ t->node_no = nfa_allocated;
+ return t;
+}
+
+
+/* initialize the model node used to fill in newly made nfa_nodes */
+void
+#ifdef __USE_PROTOS
+make_nfa_model_node(void)
+#else
+make_nfa_model_node()
+#endif
+{
+ nfa_model_node.node_no = -1; /* impossible value for real nfa node */
+ nfa_model_node.nfa_set = 0;
+ nfa_model_node.accept = 0; /* error state default*/
+ nfa_model_node.trans[0] = NULL;
+ nfa_model_node.trans[1] = NULL;
+ nfa_model_node.label = empty;
+}
+
+#if defined(DEBUG) || defined(_DEBUG)
+
+/* print out the pointer value and the node_number */
+void
+#ifdef __USE_PROTOS
+fprint_dfa_pair(FILE *f, nfa_node *p)
+#else
+fprint_dfa_pair(f, p)
+FILE *f;
+nfa_node *p;
+#endif
+{
+ if (p){
+ fprintf(f, "%x (%d)", p, p->node_no);
+ }else{
+ fprintf(f, "(nil)");
+ }
+}
+
+/* print out interest information on a set */
+void
+#ifdef __USE_PROTOS
+fprint_set(FILE *f, set s)
+#else
+fprint_set(f,s)
+FILE *f;
+set s;
+#endif
+{
+ unsigned int *x;
+
+ fprintf(f, "n = %d,", s.n);
+ if (s.setword){
+ fprintf(f, "setword = %x, ", s.setword);
+ /* print out all the elements in the set */
+ x = set_pdq(s);
+ while (*x!=nil){
+ fprintf(f, "%d ", *x);
+ ++x;
+ }
+ }else{
+ fprintf(f, "setword = (nil)");
+ }
+}
+
+/* code to be able to dump out the nfas
+return 0 if okay dump
+return 1 if screwed up
+*/
+int
+#ifdef __USE_PROTOS
+dump_nfas(int first_node, int last_node)
+#else
+dump_nfas(first_node, last_node)
+int first_node;
+int last_node;
+#endif
+{
+ register int i;
+ nfa_node *t;
+
+ for (i=first_node; i<=last_node; ++i){
+ t = NFA(i);
+ if (!t) break;
+ fprintf(stderr, "nfa_node %d {\n", t->node_no);
+ fprintf(stderr, "\n\tnfa_set = %d\n", t->nfa_set);
+ fprintf(stderr, "\taccept\t=\t%d\n", t->accept);
+ fprintf(stderr, "\ttrans\t=\t(");
+ fprint_dfa_pair(stderr, t->trans[0]);
+ fprintf(stderr, ",");
+ fprint_dfa_pair(stderr, t->trans[1]);
+ fprintf(stderr, ")\n");
+ fprintf(stderr, "\tlabel\t=\t{ ");
+ fprint_set(stderr, t->label);
+ fprintf(stderr, "\t}\n");
+ fprintf(stderr, "}\n\n");
+ }
+ return 0;
+}
+#endif
+
+/* DLG-specific syntax error message generator
+* (define USER_ZZSYN when compiling so don't get 2 definitions)
+*/
+void
+#ifdef __USE_PROTOS
+zzsyn(char *text, int tok, char *egroup, SetWordType *eset, int etok, int k, char *bad_text)
+#else
+zzsyn(text, tok, egroup, eset, etok, k, bad_text)
+char *text, *egroup, *bad_text;
+int tok;
+int etok;
+int k;
+SetWordType *eset;
+#endif
+{
+fprintf(stderr, ErrHdr, file_str[0]!=NULL?file_str[0]:"stdin", zzline);
+fprintf(stderr, " syntax error at \"%s\"", (tok==zzEOF_TOKEN)?"EOF":text);
+if ( !etok && !eset ) {fprintf(stderr, "\n"); return;}
+if ( k==1 ) fprintf(stderr, " missing");
+else
+{
+fprintf(stderr, "; \"%s\" not", bad_text);
+if ( zzset_deg(eset)>1 ) fprintf(stderr, " in");
+}
+if ( zzset_deg(eset)>0 ) zzedecode(eset);
+else fprintf(stderr, " %s", zztokens[etok]);
+if ( strlen(egroup) > (size_t)0 ) fprintf(stderr, " in %s", egroup);
+fprintf(stderr, "\n");
+}
diff --git a/Source/Pccts/dlg/dlg_p.g b/Source/Pccts/dlg/dlg_p.g
new file mode 100644
index 0000000..58ca110
--- /dev/null
+++ b/Source/Pccts/dlg/dlg_p.g
@@ -0,0 +1,614 @@
+/* This is the parser for the dlg
+ * This is a part of the Purdue Compiler Construction Tool Set
+ *
+ * SOFTWARE RIGHTS
+ *
+ * We reserve no LEGAL rights to the Purdue Compiler Construction Tool
+ * Set (PCCTS) -- PCCTS is in the public domain. An individual or
+ * company may do whatever they wish with source code distributed with
+ * PCCTS or the code generated by PCCTS, including the incorporation of
+ * PCCTS, or its output, into commerical software.
+ *
+ * We encourage users to develop software with PCCTS. However, we do ask
+ * that credit is given to us for developing PCCTS. By "credit",
+ * we mean that if you incorporate our source code into one of your
+ * programs (commercial product, research project, or otherwise) that you
+ * acknowledge this fact somewhere in the documentation, research report,
+ * etc... If you like PCCTS and have developed a nice tool with the
+ * output, please mention that you developed it using PCCTS. In
+ * addition, we ask that this header remain intact in our source code.
+ * As long as these guidelines are kept, we expect to continue enhancing
+ * this system and expect to make other tools available as they are
+ * completed.
+ *
+ * DLG 1.33
+ * Will Cohen
+ * With mods by Terence Parr; AHPCRC, University of Minnesota
+ * 1989-1995
+ */
+
+#header <<
+#include <ctype.h>
+#include "dlg.h"
+>>
+
+<<
+
+/* MR20 G. Hobbelt
+ Fix for Borland C++ 4.x & 5.x compiling with ALL warnings enabled
+*/
+
+#ifdef __TURBOC__
+#pragma warn -aus /* unused assignment of 'xxx' */
+#endif
+
+int action_no = 0; /* keep track of actions outputed */
+int nfa_allocated = 0; /* keeps track of number of nfa nodes */
+nfa_node **nfa_array = NULL;/* root of binary tree that stores nfa array */
+nfa_node nfa_model_node; /* model to initialize new nodes */
+set used_chars; /* used to label trans. arcs */
+set used_classes; /* classes or chars used to label trans. arcs */
+set normal_chars; /* mask to get rid elements that aren't used
+ in set */
+int flag_paren = FALSE;
+int flag_brace = FALSE;
+int mode_counter = 0; /* keep track of number of %%names */
+
+>>
+
+#lexaction <<
+int func_action; /* should actions be turned into functions?*/
+int lex_mode_counter = 0; /* keeps track of the number of %%names */
+/* MR1 */
+/* MR1 11-Apr-97 Provide mechanism for inserting code into DLG class */
+/* MR1 via <<%%lexmember...>> */
+/* MR1 */
+int lexMember = 0; /* <<%%lexmemeber ...>> MR1 */
+int lexAction = 0; /* <<%%lexaction ...>> MR1 */
+int parserClass = 0; /* <<%%parserclass ...>> MR1 */
+int lexPrefix = 0; /* <<%%lexprefix ...>> MR1 */
+char theClassName[100]; /* MR11 */
+char *pClassName=theClassName; /* MR11 */
+int firstLexMember=1; /* MR1 */
+
+#ifdef __USE_PROTOS
+void xxputc(int c) { /* MR1 */
+#else
+void xxputc(c) /* MR1 */
+ int c; /* MR1 */
+{ /* MR1 */
+#endif
+ if (parserClass) { /* MR1 */
+ *pClassName++=c; /* MR1 */
+ *pClassName=0; /* MR1 */
+ } else if (lexMember || lexPrefix) { /* MR1 */
+ if (class_stream != NULL) fputc(c,class_stream); /* MR1 */
+ } else { /* MR1 */
+ fputc(c,OUT); /* MR1 */
+ }; /* MR1 */
+} /* MR1 */
+
+#ifdef __USE_PROTOS
+void xxprintf(char *format,char *string) { /* MR1 */
+#else
+void xxprintf(format,string) /* MR1 */
+ char *format; /* MR1 */
+ char *string; /* MR1 */
+{ /* MR1 */
+#endif
+ if (lexMember || lexPrefix || parserClass) { /* MR1 */
+ if (class_stream != NULL) /* MR1 */
+ fprintf(class_stream,format,string); /* MR1 */
+ } else { /* MR1 */
+ fprintf(OUT,format,string); /* MR1 */
+ }; /* MR1 */
+} /* MR1 */
+>>
+
+#token "[\r\t\ ]+" << zzskip(); >> /* Ignore white */
+#token "\n" << zzline++; zzskip(); DAWDLE; >> /* Track Line # */
+#token L_EOF "\@"
+#token PER_PER "\%\%"
+#token NAME_PER_PER "\%\%[a-zA-Z_][a-zA-Z0-9_]*"
+ << p_mode_def(&zzlextext[2],lex_mode_counter++); >>
+
+#token LEXMEMBER "\<\<\%\%lexmember" /* MR1 */
+ <<lexMember=1; /* MR1 */
+ if (firstLexMember != 0) { /* MR1 */
+ firstLexMember=0; /* MR1 */
+ p_class_def1(); /* MR1 */
+ }; /* MR1 */
+ zzmode(ACT); /* MR1 */
+ >> /* MR1 */
+#token LEXACTION "\<\<\%\%lexaction" /* MR1 */
+ <<lexAction=1;zzmode(ACT);>> /* MR1 */
+#token PARSERCLASS "\<\<\%\%parserclass" /* MR1 */
+ <<parserClass=1; /* MR1 */
+ zzmode(ACT); /* MR1 */
+ >> /* MR1 */
+#token LEXPREFIX "\<\<\%\%lexprefix" /* MR1 */
+ <<lexPrefix=1;zzmode(ACT);>> /* MR1 */
+
+#token ACTION "\<\<"
+ << if (func_action)
+ fprintf(OUT,"\n%s %sact%d()\n{ ",
+ gen_cpp?"ANTLRTokenType":"static void",
+ gen_cpp?ClassName("::"):"", ++action_no);
+ zzmode(ACT); zzskip();
+ >>
+#token GREAT_GREAT "\>\>"
+#token L_BRACE "\{"
+#token R_BRACE "\}"
+#token L_PAR "\("
+#token R_PAR "\)"
+#token L_BRACK "\["
+#token R_BRACK "\]"
+#token ZERO_MORE "\*"
+#token ONE_MORE "\+"
+#token OR "\|"
+#token RANGE "\-"
+#token NOT "\~"
+#token OCTAL_VALUE "\\0[0-7]*"
+ << {int t; sscanf(&zzlextext[1],"%o",&t); zzlextext[0] = t;}>>
+#token HEX_VALUE "\\0[Xx][0-9a-fA-F]+"
+ << {int t; sscanf(&zzlextext[3],"%x",&t); zzlextext[0] = t;}>>
+#token DEC_VALUE "\\[1-9][0-9]*"
+ << {int t; sscanf(&zzlextext[1],"%d",&t); zzlextext[0] = t;}>>
+#token TAB "\\t" << zzlextext[0] = '\t';>>
+#token NL "\\n" << zzlextext[0] = '\n';>>
+#token CR "\\r" << zzlextext[0] = '\r';>>
+#token BS "\\b" << zzlextext[0] = '\b';>>
+
+/* MR1 */
+/* MR1 10-Apr-97 MR1 Allow #token regular expressions to cross lines */
+/* MR1 */
+#token CONTINUATION "\\ \n" << zzline++; zzskip();>> /* MR1 */
+
+/* NOTE: this takes ANYTHING after the \ */
+#token LIT "\\~[tnrb]" << zzlextext[0] = zzlextext[1];>>
+
+/* NOTE: this takes ANYTHING that doesn't match the other tokens */
+#token REGCHAR "~[\\]"
+
+
+grammar : << p_head(); p_class_hdr(); func_action = FALSE;>>
+ ( {LEXACTION | LEXMEMBER | LEXPREFIX | PARSERCLASS } ACTION)* /* MR1 */
+ <<if ( gen_cpp ) p_includes();>>
+ start_states
+ << func_action = FALSE; p_tables(); p_tail(); >>
+ (ACTION)* "@"
+ << if (firstLexMember != 0) p_class_def1(); >> /* MR1 */
+ ;
+
+start_states : ( PER_PER do_conversion
+ | NAME_PER_PER do_conversion (NAME_PER_PER do_conversion)*)
+ PER_PER
+ ;
+
+do_conversion : <<new_automaton_mode(); func_action = TRUE;>>
+ rule_list
+ <<
+ dfa_class_nop[mode_counter] =
+ relabel($1.l,comp_level);
+ if (comp_level)
+ p_shift_table(mode_counter);
+ dfa_basep[mode_counter] = dfa_allocated+1;
+ make_dfa_model_node(dfa_class_nop[mode_counter]);
+ nfa_to_dfa($1.l);
+ ++mode_counter;
+ func_action = FALSE;
+#ifdef HASH_STAT
+ fprint_hash_stats(stderr);
+#endif
+ >>
+ ;
+
+rule_list : rule <<$$.l=$1.l; $$.r=$1.r;>>
+ (rule
+ <<{nfa_node *t1;
+ t1 = new_nfa_node();
+ (t1)->trans[0]=$$.l;
+ (t1)->trans[1]=$1.l;
+ /* all accept nodes "dead ends" */
+ $$.l=t1; $$.r=NULL;
+ }
+ >>
+ )*
+ | /* empty */
+ <<$$.l = new_nfa_node(); $$.r = NULL;
+ warning("no regular expressions", zzline);
+ >>
+ ;
+
+rule : reg_expr ACTION
+/* MR23 */ << if ($1.r != NULL) {
+ $$.l=$1.l; $$.r=$1.r; ($1.r)->accept=action_no;
+ }
+ >>
+ | ACTION
+ <<$$.l = NULL; $$.r = NULL;
+ error("no expression for action ", zzline);
+ >>
+ ;
+
+reg_expr : and_expr <<$$.l=$1.l; $$.r=$1.r;>>
+ (OR and_expr
+ <<{nfa_node *t1, *t2;
+ t1 = new_nfa_node(); t2 = new_nfa_node();
+ (t1)->trans[0]=$$.l;
+ (t1)->trans[1]=$2.l;
+/* MR23 */ if ($$.r != NULL) ($$.r)->trans[1]=t2;
+ if ($2.r) {
+ ($2.r)->trans[1]=t2; /* MR20 */
+ }
+ $$.l=t1; $$.r=t2;
+ }
+ >>
+ )*
+ ;
+
+and_expr : repeat_expr
+ <<
+ $$.l=$1.l; $$.r=$1.r;
+ >>
+ (repeat_expr
+/* MR23 */ << if ($$.r != NULL) {
+ ($$.r)->trans[1]=$1.l;
+ $$.r=$1.r;
+ }
+ >>
+ )*
+ ;
+
+repeat_expr : expr <<$$.l=$1.l; $$.r=$1.r;>>
+ { ZERO_MORE
+ <<{ nfa_node *t1,*t2;
+/* MR23 */ if ($$.r != NULL) ($$.r)->trans[0] = $$.l;
+ t1 = new_nfa_node(); t2 = new_nfa_node();
+ t1->trans[0]=$$.l;
+ t1->trans[1]=t2;
+/* MR23 */ if ($$.r != NULL) ($$.r)->trans[1]=t2;
+ $$.l=t1;$$.r=t2;
+ }
+ >>
+ | ONE_MORE
+/* MR23 */ <<if ($$.r != NULL) ($$.r)->trans[0] = $$.l;>>
+ }
+ | ZERO_MORE
+ << error("no expression for *", zzline);>>
+ | ONE_MORE
+ << error("no expression for +", zzline);>>
+ ;
+
+expr : << $$.l = new_nfa_node();
+ $$.r = new_nfa_node();
+ >>
+ L_BRACK atom_list R_BRACK
+ <<
+/* MR23 */ if ($$.l != NULL) {
+ ($$.l)->trans[0] = $$.r;
+ ($$.l)->label = set_dup($2.label);
+ set_orin(&used_chars,($$.l)->label);
+ }
+ >>
+ | NOT L_BRACK atom_list R_BRACK
+ <<
+/* MR23 */ if ($$.l != NULL) {
+ ($$.l)->trans[0] = $$.r;
+ ($$.l)->label = set_dif(normal_chars,$3.label);
+ set_orin(&used_chars,($$.l)->label);
+ }
+ >>
+ | L_PAR reg_expr R_PAR
+ <<
+/* MR23 */ if ($$.l != NULL) {
+ ($$.l)->trans[0] = $2.l;
+ if ($2.r) {
+ ($2.r)->trans[1] = $$.r; /* MR20 */
+ }
+ }
+ >>
+ | L_BRACE reg_expr R_BRACE
+ <<
+/* MR23 */ if ($$.l != NULL) {
+ ($$.l)->trans[0] = $2.l;
+ ($$.l)->trans[1] = $$.r;
+ if ($2.r) {
+ ($2.r)->trans[1] = $$.r; /* MR20 */
+ }
+ }
+ >>
+ | atom
+ <<
+/* MR23 */ if ($$.l != NULL) {
+ ($$.l)->trans[0] = $$.r;
+ ($$.l)->label = set_dup($1.label);
+ set_orin(&used_chars,($$.l)->label);
+ }
+ >>
+ ;
+
+atom_list : << set_free($$.label); >>
+ (near_atom <<set_orin(&($$.label),$1.label);>>)*
+ ;
+
+near_atom : << register int i;
+ register int i_prime;
+ >>
+ anychar
+ <<$$.letter=$1.letter; $$.label=set_of($1.letter);
+ i_prime = $1.letter + MIN_CHAR;
+ if (case_insensitive && islower(i_prime))
+ set_orel(toupper(i_prime)-MIN_CHAR,
+ &($$.label));
+ if (case_insensitive && isupper(i_prime))
+ set_orel(tolower(i_prime)-MIN_CHAR,
+ &($$.label));
+ >>
+ { RANGE anychar
+ << if (case_insensitive){
+ i_prime = $$.letter+MIN_CHAR;
+ $$.letter = (islower(i_prime) ?
+ toupper(i_prime) : i_prime)-MIN_CHAR;
+ i_prime = $2.letter+MIN_CHAR;
+ $2.letter = (islower(i_prime) ?
+ toupper(i_prime) : i_prime)-MIN_CHAR;
+ }
+ /* check to see if range okay */
+ {
+ int debugLetter1 = $$.letter;
+ int debugLetter2 = $2.letter;
+ }
+ if ($$.letter > $2.letter
+ && $2.letter != 0xff){ /* MR16 */
+ error("invalid range ", zzline);
+ }
+ for (i=$$.letter; i<= (int)$2.letter; ++i){
+ set_orel(i,&($$.label));
+ i_prime = i+MIN_CHAR;
+ if (case_insensitive && islower(i_prime))
+ set_orel(toupper(i_prime)-MIN_CHAR,
+ &($$.label));
+ if (case_insensitive && isupper(i_prime))
+ set_orel(tolower(i_prime)-MIN_CHAR,
+ &($$.label));
+ }
+ >>
+ }
+ ;
+
+atom : << register int i_prime;>>
+ anychar
+ <<$$.label = set_of($1.letter);
+ i_prime = $1.letter + MIN_CHAR;
+ if (case_insensitive && islower(i_prime))
+ set_orel(toupper(i_prime)-MIN_CHAR,
+ &($$.label));
+ if (case_insensitive && isupper(i_prime))
+ set_orel(tolower(i_prime)-MIN_CHAR,
+ &($$.label));
+ >>
+ ;
+
+anychar : REGCHAR <<$$.letter = $1.letter - MIN_CHAR;>>
+ | OCTAL_VALUE <<$$.letter = $1.letter - MIN_CHAR;>>
+ | HEX_VALUE <<$$.letter = $1.letter - MIN_CHAR;>>
+ | DEC_VALUE <<$$.letter = $1.letter - MIN_CHAR;>>
+ | TAB <<$$.letter = $1.letter - MIN_CHAR;>>
+ | NL <<$$.letter = $1.letter - MIN_CHAR;>>
+ | CR <<$$.letter = $1.letter - MIN_CHAR;>>
+ | BS <<$$.letter = $1.letter - MIN_CHAR;>>
+ | LIT <<$$.letter = $1.letter - MIN_CHAR;>>
+ /* NOTE: LEX_EOF is ALWAYS shifted to 0 = MIN_CHAR - MIN_CHAR*/
+ | L_EOF <<$$.letter = 0;>>
+ ;
+
+<</* empty action */>>
+
+#lexclass ACT
+#token "@" << error("unterminated action", zzline); zzmode(START); >>
+#token ACTION "\>\>"
+ << if (func_action) fprintf(OUT,"}\n\n");
+ zzmode(START);
+/* MR1 */
+/* MR1 11-Apr-97 Provide mechanism for inserting code into DLG class */
+/* MR1 via <<%%lexmember ...>> */
+/* MR1 This is a consequence of not saving actions */
+/* MR1 */
+/* MR1 */ parserClass=0;
+/* MR1 */ lexPrefix=0;
+/* MR1 */ lexAction=0;
+/* MR1 */ lexMember=0;
+ >>
+#token "\>" << xxputc(zzlextext[0]); zzskip(); >> /* MR1 */
+#token "\\\>" << xxputc('>'); zzskip(); >> /* MR1 */
+#token "\\" << xxputc('\\'); zzskip(); >> /* MR1 */
+#token "\n" << xxputc(zzlextext[0]); ++zzline; zzskip(); >> /* MR1 */
+#token "/\*" << zzmode(ACTION_COMMENTS); /* MR1 */
+ xxprintf("%s", &(zzlextext[0])); zzskip(); /* MR1 */
+ >> /* MR1 */
+#token "//" << zzmode(ACTION_CPP_COMMENTS); /* MR1 */
+ xxprintf("%s", &(zzlextext[0])); zzskip(); /* MR1 */
+ >> /* MR1 */
+#token "~[]" << xxputc(zzlextext[0]); zzskip(); >> /* MR1 */
+ /* MR1 */
+#lexclass ACTION_COMMENTS /* MR1 */
+#token "\*/" << zzmode(ACT); /* MR1 */
+ xxprintf("%s", &(zzlextext[0])); zzskip(); /* MR1 */
+ >> /* MR1 */
+#token "[\n\r]" << zzline++; xxputc(zzlextext[0]); zzskip();>> /* MR1 */
+#token "~[]" << xxputc(zzlextext[0]); zzskip();>> /* MR1 */
+ /* MR1 */
+#lexclass ACTION_CPP_COMMENTS /* MR1 */
+#token "[\n\r]" << zzmode(ACT); zzline++; /* MR1 */
+ xxprintf("%s", &(zzlextext[0])); zzskip(); /* MR1 */
+ >> /* MR1 */
+#token "~[]" << xxputc(zzlextext[0]); zzskip();>> /* MR1 */
+
+<<
+/* adds a new nfa to the binary tree and returns a pointer to it */
+nfa_node *
+#ifdef __USE_PROTOS
+new_nfa_node(void)
+#else
+new_nfa_node()
+#endif
+{
+ register nfa_node *t;
+ static int nfa_size=0; /* elements nfa_array[] can hold */
+
+ ++nfa_allocated;
+ if (nfa_size<=nfa_allocated){
+ /* need to redo array */
+ if (!nfa_array){
+ /* need some to do inital allocation */
+ nfa_size=nfa_allocated+NFA_MIN;
+ nfa_array=(nfa_node **) malloc(sizeof(nfa_node*)*
+ nfa_size);
+ }else{
+ /* need more space */
+ nfa_size=2*(nfa_allocated+1);
+ nfa_array=(nfa_node **) realloc(nfa_array,
+ sizeof(nfa_node*)*nfa_size);
+ }
+ }
+ /* fill out entry in array */
+ t = (nfa_node*) malloc(sizeof(nfa_node));
+ nfa_array[nfa_allocated] = t;
+ *t = nfa_model_node;
+ t->node_no = nfa_allocated;
+ return t;
+}
+
+
+/* initialize the model node used to fill in newly made nfa_nodes */
+void
+#ifdef __USE_PROTOS
+make_nfa_model_node(void)
+#else
+make_nfa_model_node()
+#endif
+{
+ nfa_model_node.node_no = -1; /* impossible value for real nfa node */
+ nfa_model_node.nfa_set = 0;
+ nfa_model_node.accept = 0; /* error state default*/
+ nfa_model_node.trans[0] = NULL;
+ nfa_model_node.trans[1] = NULL;
+ nfa_model_node.label = empty;
+}
+>>
+
+<<
+#if defined(DEBUG) || defined(_DEBUG)
+
+/* print out the pointer value and the node_number */
+void
+#ifdef __USE_PROTOS
+fprint_dfa_pair(FILE *f, nfa_node *p)
+#else
+fprint_dfa_pair(f, p)
+FILE *f;
+nfa_node *p;
+#endif
+{
+ if (p){
+ fprintf(f, "%x (%d)", p, p->node_no);
+ }else{
+ fprintf(f, "(nil)");
+ }
+}
+
+/* print out interest information on a set */
+void
+#ifdef __USE_PROTOS
+fprint_set(FILE *f, set s)
+#else
+fprint_set(f,s)
+FILE *f;
+set s;
+#endif
+{
+ unsigned int *x;
+
+ fprintf(f, "n = %d,", s.n);
+ if (s.setword){
+ fprintf(f, "setword = %x, ", s.setword);
+ /* print out all the elements in the set */
+ x = set_pdq(s);
+ while (*x!=nil){
+ fprintf(f, "%d ", *x);
+ ++x;
+ }
+ }else{
+ fprintf(f, "setword = (nil)");
+ }
+}
+
+/* code to be able to dump out the nfas
+ return 0 if okay dump
+ return 1 if screwed up
+ */
+int
+#ifdef __USE_PROTOS
+dump_nfas(int first_node, int last_node)
+#else
+dump_nfas(first_node, last_node)
+int first_node;
+int last_node;
+#endif
+{
+ register int i;
+ nfa_node *t;
+
+ for (i=first_node; i<=last_node; ++i){
+ t = NFA(i);
+ if (!t) break;
+ fprintf(stderr, "nfa_node %d {\n", t->node_no);
+ fprintf(stderr, "\n\tnfa_set = %d\n", t->nfa_set);
+ fprintf(stderr, "\taccept\t=\t%d\n", t->accept);
+ fprintf(stderr, "\ttrans\t=\t(");
+ fprint_dfa_pair(stderr, t->trans[0]);
+ fprintf(stderr, ",");
+ fprint_dfa_pair(stderr, t->trans[1]);
+ fprintf(stderr, ")\n");
+ fprintf(stderr, "\tlabel\t=\t{ ");
+ fprint_set(stderr, t->label);
+ fprintf(stderr, "\t}\n");
+ fprintf(stderr, "}\n\n");
+ }
+ return 0;
+}
+#endif
+>>
+
+<<
+/* DLG-specific syntax error message generator
+ * (define USER_ZZSYN when compiling so don't get 2 definitions)
+ */
+void
+#ifdef __USE_PROTOS
+zzsyn(char *text, int tok, char *egroup, SetWordType *eset, int etok, int k, char *bad_text)
+#else
+zzsyn(text, tok, egroup, eset, etok, k, bad_text)
+char *text, *egroup, *bad_text;
+int tok;
+int etok;
+int k;
+SetWordType *eset;
+#endif
+{
+ fprintf(stderr, ErrHdr, file_str[0]!=NULL?file_str[0]:"stdin", zzline);
+ fprintf(stderr, " syntax error at \"%s\"", (tok==zzEOF_TOKEN)?"EOF":text);
+ if ( !etok && !eset ) {fprintf(stderr, "\n"); return;}
+ if ( k==1 ) fprintf(stderr, " missing");
+ else
+ {
+ fprintf(stderr, "; \"%s\" not", bad_text);
+ if ( zzset_deg(eset)>1 ) fprintf(stderr, " in");
+ }
+ if ( zzset_deg(eset)>0 ) zzedecode(eset);
+ else fprintf(stderr, " %s", zztokens[etok]);
+ if ( strlen(egroup) > (size_t)0 ) fprintf(stderr, " in %s", egroup);
+ fprintf(stderr, "\n");
+}
+>>
diff --git a/Source/Pccts/dlg/err.c b/Source/Pccts/dlg/err.c
new file mode 100644
index 0000000..c3eaeae
--- /dev/null
+++ b/Source/Pccts/dlg/err.c
@@ -0,0 +1,99 @@
+/*
+ * A n t l r S e t s / E r r o r F i l e H e a d e r
+ *
+ * Generated from: dlg_p.g
+ *
+ * Terence Parr, Russell Quong, Will Cohen, and Hank Dietz: 1989-2001
+ * Parr Research Corporation
+ * with Purdue University Electrical Engineering
+ * With AHPCRC, University of Minnesota
+ * ANTLR Version 1.33MR33
+ */
+
+#define ANTLR_VERSION 13333
+#include "pcctscfg.h"
+#include "pccts_stdio.h"
+
+#include <ctype.h>
+#include "dlg.h"
+#define zzSET_SIZE 8
+#include "antlr.h"
+#include "tokens.h"
+#include "dlgdef.h"
+#include "err.h"
+
+ANTLRChar *zztokens[46]={
+ /* 00 */ "Invalid",
+ /* 01 */ "@",
+ /* 02 */ "[\\r\\t\\ ]+",
+ /* 03 */ "\\n",
+ /* 04 */ "L_EOF",
+ /* 05 */ "PER_PER",
+ /* 06 */ "NAME_PER_PER",
+ /* 07 */ "LEXMEMBER",
+ /* 08 */ "LEXACTION",
+ /* 09 */ "PARSERCLASS",
+ /* 10 */ "LEXPREFIX",
+ /* 11 */ "ACTION",
+ /* 12 */ "GREAT_GREAT",
+ /* 13 */ "L_BRACE",
+ /* 14 */ "R_BRACE",
+ /* 15 */ "L_PAR",
+ /* 16 */ "R_PAR",
+ /* 17 */ "L_BRACK",
+ /* 18 */ "R_BRACK",
+ /* 19 */ "ZERO_MORE",
+ /* 20 */ "ONE_MORE",
+ /* 21 */ "OR",
+ /* 22 */ "RANGE",
+ /* 23 */ "NOT",
+ /* 24 */ "OCTAL_VALUE",
+ /* 25 */ "HEX_VALUE",
+ /* 26 */ "DEC_VALUE",
+ /* 27 */ "TAB",
+ /* 28 */ "NL",
+ /* 29 */ "CR",
+ /* 30 */ "BS",
+ /* 31 */ "CONTINUATION",
+ /* 32 */ "LIT",
+ /* 33 */ "REGCHAR",
+ /* 34 */ "\\>",
+ /* 35 */ "\\\\>",
+ /* 36 */ "\\",
+ /* 37 */ "\\n",
+ /* 38 */ "/\\*",
+ /* 39 */ "//",
+ /* 40 */ "~[]",
+ /* 41 */ "\\*/",
+ /* 42 */ "[\\n\\r]",
+ /* 43 */ "~[]",
+ /* 44 */ "[\\n\\r]",
+ /* 45 */ "~[]"
+};
+SetWordType zzerr1[8] = {0x80,0xf,0x0,0x0, 0x0,0x0,0x0,0x0};
+SetWordType zzerr2[8] = {0x60,0x0,0x0,0x0, 0x0,0x0,0x0,0x0};
+SetWordType zzerr3[8] = {0x70,0xa8,0x9a,0x7f, 0x3,0x0,0x0,0x0};
+SetWordType setwd1[46] = {0x0,0x6,0x0,0x0,0x30,0xc8,0xc8,
+ 0x1,0x1,0x1,0x1,0x35,0x0,0x30,0x0,
+ 0x30,0x0,0x30,0x0,0x30,0x30,0x0,0x0,
+ 0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,
+ 0x0,0x30,0x30,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+SetWordType zzerr4[8] = {0x10,0xa8,0x9a,0x7f, 0x3,0x0,0x0,0x0};
+SetWordType zzerr5[8] = {0x10,0xe8,0xbb,0x7f, 0x3,0x0,0x0,0x0};
+SetWordType zzerr6[8] = {0x10,0xa0,0x9a,0x7f, 0x3,0x0,0x0,0x0};
+SetWordType setwd2[46] = {0x0,0x0,0x0,0x0,0xeb,0x2,0x2,
+ 0x0,0x0,0x0,0x0,0xd6,0x0,0xeb,0xd4,
+ 0xeb,0xd4,0xeb,0x0,0xcb,0xcb,0xd0,0x0,
+ 0xeb,0xeb,0xeb,0xeb,0xeb,0xeb,0xeb,0xeb,
+ 0x0,0xeb,0xeb,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+SetWordType zzerr7[8] = {0x10,0xa0,0x82,0x7f, 0x3,0x0,0x0,0x0};
+SetWordType zzerr8[8] = {0x10,0x0,0x44,0x7f, 0x3,0x0,0x0,0x0};
+SetWordType zzerr9[8] = {0x10,0x0,0x0,0x7f, 0x3,0x0,0x0,0x0};
+SetWordType setwd3[46] = {0x0,0x0,0x0,0x0,0xf7,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0xc2,0x0,0xc2,0xc2,
+ 0xc2,0xc2,0xc2,0xb8,0xc2,0xc2,0xc2,0x80,
+ 0xc2,0xf7,0xf7,0xf7,0xf7,0xf7,0xf7,0xf7,
+ 0x0,0xf7,0xf7,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0};
diff --git a/Source/Pccts/dlg/main.c b/Source/Pccts/dlg/main.c
new file mode 100644
index 0000000..35bd827
--- /dev/null
+++ b/Source/Pccts/dlg/main.c
@@ -0,0 +1,281 @@
+/* Main function for dlg version
+ *
+ * SOFTWARE RIGHTS
+ *
+ * We reserve no LEGAL rights to the Purdue Compiler Construction Tool
+ * Set (PCCTS) -- PCCTS is in the public domain. An individual or
+ * company may do whatever they wish with source code distributed with
+ * PCCTS or the code generated by PCCTS, including the incorporation of
+ * PCCTS, or its output, into commerical software.
+ *
+ * We encourage users to develop software with PCCTS. However, we do ask
+ * that credit is given to us for developing PCCTS. By "credit",
+ * we mean that if you incorporate our source code into one of your
+ * programs (commercial product, research project, or otherwise) that you
+ * acknowledge this fact somewhere in the documentation, research report,
+ * etc... If you like PCCTS and have developed a nice tool with the
+ * output, please mention that you developed it using PCCTS. In
+ * addition, we ask that this header remain intact in our source code.
+ * As long as these guidelines are kept, we expect to continue enhancing
+ * this system and expect to make other tools available as they are
+ * completed.
+ *
+ * DLG 1.33
+ * Will Cohen
+ * With mods by Terence Parr; AHPCRC, University of Minnesota
+ * 1989-2001
+ */
+
+#include <stdio.h>
+#include "stdpccts.h"
+
+char program[] = "dlg";
+char version[] = "1.33MR33"; /* MRXXX */
+int numfiles = 0;
+char *file_str[2] = {NULL, NULL};
+char *mode_file = "mode.h";
+char *class_name = DEFAULT_CLASSNAME;
+char *OutputDirectory = TopDirectory;
+
+/* Option variables */
+int comp_level = 0;
+int interactive = FALSE;
+int case_insensitive = FALSE;
+int warn_ambig = FALSE;
+int gen_cpp = FALSE;
+
+#ifdef __USE_PROTOS
+static int ci_strequ(char *a,char *b)
+#else
+static int ci_strequ(a,b)
+ char *a;
+ char *b;
+#endif
+{
+ for ( ;*a != 0 && *b != 0; a++, b++) {
+ if (toupper(*a) != toupper(*b)) return 0;
+ }
+ return (*a == *b);
+}
+
+/* Option List Stuff */
+#ifdef __USE_PROTOS
+void p_comp0(void) {comp_level = 0;}
+void p_comp1(void) {comp_level = 1;}
+void p_comp2(void) {comp_level = 2;}
+void p_stdio(void) { file_str[numfiles++] = NULL;}
+void p_file(char *s) { file_str[numfiles++] = s;}
+void p_cl_name(char *s, char *t)
+ {
+ if ( gen_cpp ) {
+ class_name = t;
+ }
+ else {
+ warning("-cl only valid in C++ mode; -cl ignored...",0);
+ }
+ }
+void p_mode_file(char *s, char *t){mode_file=t;}
+void p_outdir(char *s,char *t) {OutputDirectory=t;}
+void p_ansi(void) {gen_ansi = TRUE;}
+void p_interactive(void) {interactive = TRUE;}
+void p_case_s(void) { case_insensitive = FALSE; }
+void p_case_i(void) { case_insensitive = TRUE; }
+void p_warn_ambig(void) { warn_ambig = TRUE; }
+void p_cpp(void) { gen_cpp = TRUE; }
+#else
+void p_comp0() {comp_level = 0;}
+void p_comp1() {comp_level = 1;}
+void p_comp2() {comp_level = 2;}
+void p_stdio() { file_str[numfiles++] = NULL;}
+void p_file(s) char *s; { file_str[numfiles++] = s;}
+void p_cl_name(s,t)
+ char *s, *t;
+ {
+ if ( gen_cpp ) {
+ class_name = t;
+ }
+ else {
+ warning("-cl only valid in C++ mode; -cl ignored...",0);
+ }
+ }
+void p_mode_file(s,t) char *s,*t;{mode_file=t;}
+void p_outdir(s,t) char *s,*t;{OutputDirectory=t;}
+void p_ansi() {gen_ansi = TRUE;}
+void p_interactive() {interactive = TRUE;}
+void p_case_s() { case_insensitive = FALSE; }
+void p_case_i() { case_insensitive = TRUE; }
+void p_warn_ambig() { warn_ambig = TRUE; }
+void p_cpp() { gen_cpp = TRUE; }
+#endif
+
+#ifdef __cplusplus
+typedef void (*WildFunc)(...);
+#else
+typedef void (*WildFunc)();
+#endif
+
+typedef struct {
+ char *option;
+ int arg;
+ WildFunc process;
+ char *descr;
+ } Opt;
+
+Opt options[] = {
+ { "-CC", 0, (WildFunc)p_cpp, "Generate C++ output" },
+ { "-C0", 0, (WildFunc)p_comp0, "No compression (default)" },
+ { "-C1", 0, (WildFunc)p_comp1, "Compression level 1" },
+ { "-C2", 0, (WildFunc)p_comp2, "Compression level 2" },
+ { "-ga", 0, (WildFunc)p_ansi, "Generate ansi C"},
+ { "-Wambiguity", 0, (WildFunc)p_warn_ambig, "Warn if expressions ambiguous"},
+ { "-m", 1, (WildFunc)p_mode_file, "Rename lexical mode output file"},
+ { "-i", 0, (WildFunc)p_interactive, "Build interactive scanner (not valid for C++ mode)"},
+ { "-ci", 0, (WildFunc)p_case_i, "Make lexical analyzer case insensitive"},
+ { "-cl", 1, (WildFunc)p_cl_name, "Rename lexer class (DLGLexer); only used for -CC"},
+ { "-cs", 0, (WildFunc)p_case_s, "Make lexical analyzer case sensitive (default)"},
+ { "-o", 1, (WildFunc)p_outdir, OutputDirectoryOption},
+ { "-", 0, (WildFunc)p_stdio, "Use standard i/o rather than file"},
+ { "*", 0, (WildFunc)p_file, ""}, /* anything else is a file */
+ { NULL, 0, NULL }
+ };
+
+#ifdef __USE_PROTOS
+void ProcessArgs(int argc, char **argv, Opt *options)
+#else
+void ProcessArgs(argc, argv, options)
+int argc;
+char **argv;
+Opt *options;
+#endif
+{
+ Opt *p;
+
+ while ( argc-- > 0 )
+ {
+ p = options;
+ while ( p->option != NULL )
+ {
+ if ( strcmp(p->option, "*") == 0 ||
+ ci_strequ(p->option,*argv) )
+ {
+ if ( p->arg )
+ {
+ (*p->process)( *argv, *(argv+1) );
+ argv++;
+ argc--;
+ }
+ else
+ (*p->process)( *argv );
+ break;
+ }
+ p++;
+ }
+ argv++;
+ }
+}
+
+#ifdef __USE_PROTOS
+int main(int argc, char *argv[])
+#else
+int main(argc, argv)
+int argc;
+char *argv[];
+#endif
+{
+ init();
+ fprintf(stderr, "%s Version %s 1989-2001\n", &(program[0]),
+ &(version[0]));
+ if ( argc == 1 )
+ {
+ Opt *p = options;
+ fprintf(stderr, "%s [options] f1 f2 ... fn\n",argv[0]);
+ while ( *(p->option) != '*' )
+ {
+ fprintf(stderr, "\t%s %s\t%s\n",
+ p->option,
+ (p->arg)?"___":" ",
+ p->descr);
+ p++;
+ }
+ }else{
+ ProcessArgs(argc-1, &(argv[1]), options);
+ if (interactive && gen_cpp) {
+ fprintf(stderr,"\n");
+/*** MR21a This statement is wrong ! ***/
+#if 0
+*** fprintf(stderr,"Interactive lexer option (\"-i\") has no effect when in C++ mode\n");
+*** fprintf(stderr,"because of extra buffering provided by ANTLRTokenBuffer class.\n");
+*** fprintf(stderr,"\n");
+#endif
+ }
+ input_stream = read_stream(file_str[0]);
+ if (input_stream) {
+ /* don't overwrite unless input okay */
+ if ( gen_cpp ) {
+ output_stream = write_stream(ClassName(CPP_FILE_SUFFIX));
+ if ( file_str[1]!=NULL ) {
+ warning("output file implicit in C++ mode; ignored...",0);
+ }
+ class_stream = write_stream(ClassName(".h"));
+ mode_stream = class_stream;
+ }
+ else {
+ output_stream = write_stream(file_str[1]);
+ mode_stream = write_stream(mode_file);
+ }
+ }
+ /* make sure that error reporting routines in grammar
+ know what the file really is */
+ /* make sure that reading and writing somewhere */
+ if (input_stream && output_stream && mode_stream){
+ ANTLR(grammar(), input_stream);
+ }
+ p_class_def2(); /* MR1 */
+ }
+ if ( output_stream!=NULL ) fclose(output_stream);
+ if ( !gen_cpp && mode_stream!=NULL ) fclose(mode_stream);
+ if ( class_stream!=NULL ) fclose(class_stream);
+ exit(PCCTS_EXIT_SUCCESS);
+ return 0; /* get rid of warning message MR1 */
+}
+
+/* initialize all the variables */
+void
+#ifdef __USE_PROTOS
+init(void)
+#else
+init()
+#endif
+{
+ register int i;
+
+#ifdef SPECIAL_INITS
+ special_inits(); /* MR1 */
+#endif
+ used_chars = empty;
+ used_classes = empty;
+ /* make the valid character set */
+ normal_chars = empty;
+ /* NOTE: MIN_CHAR is EOF */
+ /* NOTE: EOF is not quite a valid char, it is special. Skip it*/
+ for (i = 1; i<CHAR_RANGE; ++i){
+ set_orel(i,&normal_chars);
+ }
+ make_nfa_model_node();
+ clear_hash();
+ /* NOTE: need to set this flag before the lexer starts getting */
+ /* tokens */
+ func_action = FALSE;
+}
+
+/* stuff that needs to be reset when a new automaton is being built */
+void
+#ifdef __USE_PROTOS
+new_automaton_mode(void) /* MR1 */
+#else
+new_automaton_mode() /* MR1 */
+#endif
+{
+ set_free(used_chars);
+ clear_hash();
+}
diff --git a/Source/Pccts/dlg/makefile b/Source/Pccts/dlg/makefile
new file mode 100644
index 0000000..d5cceb8
--- /dev/null
+++ b/Source/Pccts/dlg/makefile
@@ -0,0 +1,156 @@
+#
+# Makefile for DLG 1.33
+# Terence Parr
+# Purdue University, U of MN, Parr Research Corporation
+# 1989-1994
+#
+# Ported to IBM C-Set/2 and Microsoft 6.0 by
+# Ed Harfmann
+# Micro Data Base Systems
+# Lafayette, Indiana
+#
+SET=../support/set
+PCCTS_H=../h
+
+##
+## Uncomment the appropriate section to build
+##
+
+#
+# OS/2 & DOS 16 bit using MSC 6.0
+#
+#CC=cl
+#ANTLR=..\bin\antlr
+#DLG=..\bin\dlg
+#CFLAGS= -I. -I$(SET) -I$(PCCTS_H) /AL /Za /W3 -DPC -DUSER_ZZSYN
+#OUT_OBJ = -Fo
+#LIBS=/NOD:LLIBCE LLIBCEP
+#OBJ_EXT = obj
+#
+#dlg.exe : dlg_p.obj dlg_a.obj main.obj err.obj set.obj support.obj \
+# output.obj relabel.obj automata.obj
+# link @<<
+#$** /NOI
+#$@ /STACK:16384
+#
+#$(LIBS: = +^
+#)
+#$(DEF_FILE) $(LFLAGS) ;
+#<<
+# bind $@ c:\os2\doscalls.lib
+# copy *.exe ..\bin
+#
+
+#
+# Borland C++ for DOS
+#
+#CC=bcc
+#ANTLR=..\bin\antlr
+#DLG=..\bin\dlg
+#CFLAGS= -I. -I$(SET) -I$(PCCTS_H) -ml -ff- -w- -DPC -DUSER_ZZSYN
+#OUT_OBJ = -o
+#LIBS= emu mathl cl
+#OBJ_EXT = obj
+#
+#dlg.exe : dlg_p.obj dlg_a.obj main.obj err.obj set.obj support.obj \
+# output.obj relabel.obj automata.obj
+# tlink @&&|
+#C0L $**
+#$@ /Tde /c
+#
+#$(LIBS)
+#$(DEF_FILE) $(LFLAGS) ;
+#|
+# copy *.exe ..\bin
+#
+
+#
+# C-Set/2 for OS/2
+#
+#CC=icc
+#CFLAGS= -I. -I$(SET) -I$(PCCTS_H) /Sa /W3 /DUSER_ZZSYN
+#OUT_OBJ = -Fo
+#LIBS=
+#ANTLR=..\bin\antlr
+#DLG=..\bin\dlg
+#OBJ_EXT=obj
+#
+#dlg.exe : dlg_p.obj dlg_a.obj main.obj err.obj set.obj support.obj \
+# output.obj relabel.obj automata.obj
+# link386 @<<
+#$** /NOI
+#$@ /STACK:32768
+#
+#$(LIBS: = +^
+#)
+#$(DEF_FILE) $(LFLAGS) ;
+#<<
+# copy *.exe ..\bin
+#
+
+#
+# Borland C++ for OS/2
+#
+#CC=bcc
+#CFLAGS= -I. -I$(SET) -I$(PCCTS_H) -w- -DUSER_ZZSYN
+#OUT_OBJ = -o
+#LIBS= c2 os2
+#
+#ANTLR=..\bin\antlr
+#DLG=..\bin\dlg
+#OBJ_EXT = obj
+#dlg.exe : dlg_p.obj dlg_a.obj main.obj err.obj set.obj support.obj \
+# output.obj relabel.obj automata.obj
+# tlink @&&|
+#c02 $** -c
+#dlg.exe
+#
+#C2 os2
+#
+#|
+# copy *.exe ..\bin
+#
+
+#
+# UNIX
+#
+CC=cc
+COPT=-O
+ANTLR=${BIN_DIR}/antlr
+DLG=${BIN_DIR}/dlg
+CFLAGS= $(COPT) -I. -I$(SET) -I$(PCCTS_H) -DUSER_ZZSYN -DZZLEXBUFSIZE=65536
+OBJ_EXT=o
+OUT_OBJ = -o
+OBJ = dlg_p.o dlg_a.o main.o err.o set.o support.o output.o \
+ relabel.o automata.o
+
+dlg : $(OBJ) $(SRC)
+ $(CC) $(CFLAGS) -o ${BIN_DIR}/dlg $(OBJ)
+
+SRC = dlg_p.c dlg_a.c main.c err.c $(SET)/set.c support.c output.c \
+ relabel.c automata.c
+
+#dlg_p.c parser.dlg err.c tokens.h : dlg_p.g
+# $(ANTLR) dlg_p.g
+
+#dlg_a.c mode.h : parser.dlg
+# $(DLG) -C2 parser.dlg dlg_a.c
+
+dlg_p.$(OBJ_EXT) : dlg_p.c dlg.h tokens.h mode.h
+ $(CC) $(CFLAGS) -c dlg_p.c
+
+dlg_a.$(OBJ_EXT) : dlg_a.c dlg.h tokens.h mode.h
+ $(CC) $(CFLAGS) -c dlg_a.c
+
+main.$(OBJ_EXT) : main.c dlg.h
+ $(CC) $(CFLAGS) -c main.c
+
+set.$(OBJ_EXT) : $(SET)/set.c
+ $(CC) -c $(CFLAGS) $(SET)/set.c
+
+lint:
+ lint *.c
+
+#clean up all the intermediate files
+clean:
+ rm -f *.$(OBJ_EXT) core
diff --git a/Source/Pccts/dlg/makefile.cygwin b/Source/Pccts/dlg/makefile.cygwin
new file mode 100644
index 0000000..bbba820
--- /dev/null
+++ b/Source/Pccts/dlg/makefile.cygwin
@@ -0,0 +1,157 @@
+#
+# Makefile for DLG 1.33
+# Terence Parr
+# Purdue University, U of MN, Parr Research Corporation
+# 1989-1994
+#
+# Ported to IBM C-Set/2 and Microsoft 6.0 by
+# Ed Harfmann
+# Micro Data Base Systems
+# Lafayette, Indiana
+#
+SET=../support/set
+PCCTS_H=../h
+
+##
+## Uncomment the appropriate section to build
+##
+
+#
+# OS/2 & DOS 16 bit using MSC 6.0
+#
+#CC=cl
+#ANTLR=..\bin\antlr
+#DLG=..\bin\dlg
+#CFLAGS= -I. -I$(SET) -I$(PCCTS_H) /AL /Za /W3 -DPC -DUSER_ZZSYN
+#OUT_OBJ = -Fo
+#LIBS=/NOD:LLIBCE LLIBCEP
+#OBJ_EXT = obj
+#
+#dlg.exe : dlg_p.obj dlg_a.obj main.obj err.obj set.obj support.obj \
+# output.obj relabel.obj automata.obj
+# link @<<
+#$** /NOI
+#$@ /STACK:16384
+#
+#$(LIBS: = +^
+#)
+#$(DEF_FILE) $(LFLAGS) ;
+#<<
+# bind $@ c:\os2\doscalls.lib
+# copy *.exe ..\bin
+#
+
+#
+# Borland C++ for DOS
+#
+#CC=bcc
+#ANTLR=..\bin\antlr
+#DLG=..\bin\dlg
+#CFLAGS= -I. -I$(SET) -I$(PCCTS_H) -ml -ff- -w- -DPC -DUSER_ZZSYN
+#OUT_OBJ = -o
+#LIBS= emu mathl cl
+#OBJ_EXT = obj
+#
+#dlg.exe : dlg_p.obj dlg_a.obj main.obj err.obj set.obj support.obj \
+# output.obj relabel.obj automata.obj
+# tlink @&&|
+#C0L $**
+#$@ /Tde /c
+#
+#$(LIBS)
+#$(DEF_FILE) $(LFLAGS) ;
+#|
+# copy *.exe ..\bin
+#
+
+#
+# C-Set/2 for OS/2
+#
+#CC=icc
+#CFLAGS= -I. -I$(SET) -I$(PCCTS_H) /Sa /W3 /DUSER_ZZSYN
+#OUT_OBJ = -Fo
+#LIBS=
+#ANTLR=..\bin\antlr
+#DLG=..\bin\dlg
+#OBJ_EXT=obj
+#
+#dlg.exe : dlg_p.obj dlg_a.obj main.obj err.obj set.obj support.obj \
+# output.obj relabel.obj automata.obj
+# link386 @<<
+#$** /NOI
+#$@ /STACK:32768
+#
+#$(LIBS: = +^
+#)
+#$(DEF_FILE) $(LFLAGS) ;
+#<<
+# copy *.exe ..\bin
+#
+
+#
+# Borland C++ for OS/2
+#
+#CC=bcc
+#CFLAGS= -I. -I$(SET) -I$(PCCTS_H) -w- -DUSER_ZZSYN
+#OUT_OBJ = -o
+#LIBS= c2 os2
+#
+#ANTLR=..\bin\antlr
+#DLG=..\bin\dlg
+#OBJ_EXT = obj
+#dlg.exe : dlg_p.obj dlg_a.obj main.obj err.obj set.obj support.obj \
+# output.obj relabel.obj automata.obj
+# tlink @&&|
+#c02 $** -c
+#dlg.exe
+#
+#C2 os2
+#
+#|
+# copy *.exe ..\bin
+#
+
+#
+# UNIX
+#
+BIN_DIR=../../../../bin
+CC=cc
+COPT=-O
+ANTLR=$(BIN_DIR)/antlr.exe
+DLG=${BIN_DIR}/dlg.exe
+CFLAGS= $(COPT) -I. -I$(SET) -I$(PCCTS_H) -DUSER_ZZSYN -DZZLEXBUFSIZE=65536
+OBJ_EXT=o
+OUT_OBJ = -o
+OBJ = dlg_p.o dlg_a.o main.o err.o set.o support.o output.o \
+ relabel.o automata.o
+
+dlg : $(OBJ) $(SRC)
+ $(CC) $(CFLAGS) -o $(BIN_DIR)/dlg.exe $(OBJ)
+
+SRC = dlg_p.c dlg_a.c main.c err.c $(SET)/set.c support.c output.c \
+ relabel.c automata.c
+
+#dlg_p.c parser.dlg err.c tokens.h : dlg_p.g
+# $(ANTLR) dlg_p.g
+
+#dlg_a.c mode.h : parser.dlg
+# $(DLG) -C2 parser.dlg dlg_a.c
+
+dlg_p.$(OBJ_EXT) : dlg_p.c dlg.h tokens.h mode.h
+ $(CC) $(CFLAGS) -c dlg_p.c
+
+dlg_a.$(OBJ_EXT) : dlg_a.c dlg.h tokens.h mode.h
+ $(CC) $(CFLAGS) -c dlg_a.c
+
+main.$(OBJ_EXT) : main.c dlg.h
+ $(CC) $(CFLAGS) -c main.c
+
+set.$(OBJ_EXT) : $(SET)/set.c
+ $(CC) -c $(CFLAGS) $(SET)/set.c
+
+lint:
+ lint *.c
+
+#clean up all the intermediate files
+clean:
+ rm -f *.$(OBJ_EXT) core
diff --git a/Source/Pccts/dlg/makefile1 b/Source/Pccts/dlg/makefile1
new file mode 100644
index 0000000..4d00f79
--- /dev/null
+++ b/Source/Pccts/dlg/makefile1
@@ -0,0 +1,63 @@
+#
+# Makefile for DLG 1.33
+# Terence Parr
+# Purdue University, U of MN, Parr Research Corporation
+# 1989-1994
+#
+# Ported to IBM C-Set/2 and Microsoft 6.0 by
+# Ed Harfmann
+# Micro Data Base Systems
+# Lafayette, Indiana
+#
+SET=../support/set
+PCCTS_H=../h
+
+##
+## Uncomment the appropriate section to build
+##
+
+
+#
+# UNIX
+#
+CC=cc
+ANTLR=../bin/antlr
+DLG=../bin/dlg
+ANSI=-ansi
+CFLAGS= -O -I. -I$(SET) -I$(PCCTS_H) -DUSER_ZZSYN $(COTHER) $(ANSI) -DZZLEXBUFSIZE=32000
+OBJ_EXT=o
+OUT_OBJ = -o
+OBJ = dlg_p.o dlg_a.o main.o err.o set.o support.o output.o \
+ relabel.o automata.o
+
+dlg : $(OBJ) $(SRC)
+ $(CC) $(CFLAGS) -o dlg $(OBJ)
+ mv dlg ../bin
+
+SRC = dlg_p.c dlg_a.c main.c err.c $(SET)/set.c support.c output.c \
+ relabel.c automata.c
+
+dlg_p.c parser.dlg err.c tokens.h : dlg_p.g
+ $(ANTLR) dlg_p.g
+
+dlg_a.c mode.h : parser.dlg
+ $(DLG) -C2 parser.dlg dlg_a.c
+
+dlg_p.$(OBJ_EXT) : dlg_p.c dlg.h tokens.h mode.h
+ $(CC) $(CFLAGS) -c dlg_p.c
+
+dlg_a.$(OBJ_EXT) : dlg_a.c dlg.h tokens.h mode.h
+ $(CC) $(CFLAGS) -c dlg_a.c
+
+main.$(OBJ_EXT) : main.c dlg.h
+ $(CC) $(CFLAGS) -c main.c
+
+set.$(OBJ_EXT) : $(SET)/set.c
+ $(CC) -c $(CFLAGS) $(SET)/set.c
+
+lint:
+ lint *.c
+
+#clean up all the intermediate files
+clean:
+ rm -f *.$(OBJ_EXT) core
diff --git a/Source/Pccts/dlg/mode.h b/Source/Pccts/dlg/mode.h
new file mode 100644
index 0000000..3f3279e
--- /dev/null
+++ b/Source/Pccts/dlg/mode.h
@@ -0,0 +1,4 @@
+#define START 0
+#define ACT 1
+#define ACTION_COMMENTS 2
+#define ACTION_CPP_COMMENTS 3
diff --git a/Source/Pccts/dlg/output.c b/Source/Pccts/dlg/output.c
new file mode 100644
index 0000000..2e56a6d
--- /dev/null
+++ b/Source/Pccts/dlg/output.c
@@ -0,0 +1,850 @@
+/* output.c, output generator for dlg
+ *
+ * Output Notes:
+ *
+ * DfaStates == number of dfa nodes in automaton (just a #define)
+ * DfaState == type large enough to index every node in automaton
+ * <256 unsigned char, <65536 unsigned short, etc.
+ *
+ * Thus, the elements in each of the automaton states (st%d) are type DfaState
+ * and are size appropriately, since they must be able to index the next
+ * automaton state.
+ *
+ * dfa[] == a linear array that points to all the automaton states (st%d)
+ * (dfa_base[] should be the same, but isn't right now)
+ *
+ * accepts[] == Taking a closer look at this one, it probably shouldn't be type
+ * DfaState because there is no real requirement that the number of
+ * accepts states is less than the number of dfa state. However, if
+ * the number of accept states was more than the number of DFA states
+ * then the lexical specification would be really ambiguous.
+ *
+ * Another note. Is that is should be possible to fold accepts[] and
+ * actions[] together. If this is done, I would suggest get rid of
+ * accept[] and make actions[] have an entry for each state (st%d) in
+ * the automaton.
+ *
+ * dfa_base[] == starting location for each lexical mode. This should be
+ * Dfastate type (but isn't right now), since it points to the states
+ * in the automaton.
+ *
+ * dfa_class_no[] == indicates the number of columns each lexical mode has.
+ *
+ * b_class_no[] == pointer to the start of the translation array used to
+ * convert from input character to character class. This could cause
+ * problems if there are more than 256 classes
+ *
+ * shift%d[] == the actual translation arrays that convert the input character
+ * into the character class. These will have to change if there are
+ * more than 256 character classes.
+ *
+ * SOFTWARE RIGHTS
+ *
+ * We reserve no LEGAL rights to the Purdue Compiler Construction Tool
+ * Set (PCCTS) -- PCCTS is in the public domain. An individual or
+ * company may do whatever they wish with source code distributed with
+ * PCCTS or the code generated by PCCTS, including the incorporation of
+ * PCCTS, or its output, into commerical software.
+ *
+ * We encourage users to develop software with PCCTS. However, we do ask
+ * that credit is given to us for developing PCCTS. By "credit",
+ * we mean that if you incorporate our source code into one of your
+ * programs (commercial product, research project, or otherwise) that you
+ * acknowledge this fact somewhere in the documentation, research report,
+ * etc... If you like PCCTS and have developed a nice tool with the
+ * output, please mention that you developed it using PCCTS. In
+ * addition, we ask that this header remain intact in our source code.
+ * As long as these guidelines are kept, we expect to continue enhancing
+ * this system and expect to make other tools available as they are
+ * completed.
+ *
+ * DLG 1.33
+ * Will Cohen
+ * With mods by Terence Parr; AHPCRC, University of Minnesota
+ * 1989-2001
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include "dlg.h"
+#ifdef MEMCHK
+#include "trax.h"
+#else
+#ifdef __STDC__
+#include <stdlib.h>
+#else
+#include <malloc.h>
+#endif /* __STDC__ */
+#endif
+
+static char *mode_name[MAX_MODES];
+static int mode_number[MAX_MODES];
+static int cur_mode=0;
+
+int operation_no = 0; /* used to mark nodes so that infinite loops avoided */
+int dfa_basep[MAX_MODES]; /* start of each group of states */
+int dfa_class_nop[MAX_MODES]; /* number of elements in each group of states*/
+
+int gen_ansi = FALSE; /* allows ansi code to be generated */
+
+FILE *input_stream; /* where to read description from */
+FILE *output_stream; /* where to put the output */
+FILE *mode_stream; /* where to put the mode.h stuff */
+FILE *class_stream; /* where to put the scan.h stuff (if gen_cpp) */
+
+/* NOTE: This section is MACHINE DEPENDENT */
+#define DIF_SIZE 4
+#if defined(PC) && !defined(PC32)
+unsigned long typesize[DIF_SIZE] = { 0x7f, 0x7fff, 0x7ffful, 0x7ffffffful }; /* MR20 */
+char t0[] = "unsigned char";
+char t1[] = "unsigned short";
+char t2[] = "unsigned int";
+char t3[] = "unsigned long";
+char *typevar[DIF_SIZE] = { t0, t1, t2, t3};
+#else
+unsigned long typesize[DIF_SIZE] = { 0x7f, 0x7fff, 0x7ffffffful, 0x7ffffffful }; /* MR20 */
+char t0[] = "unsigned char";
+char t1[] = "unsigned short";
+char t2[] = "unsigned int";
+char t3[] = "unsigned long";
+char *typevar[DIF_SIZE] = { t0, t1, t2, t3};
+#endif
+
+/* Added by TJP August 1994 */
+/* Take in MyLexer and return MyLexer_h */
+
+static char *
+#ifdef __USE_PROTOS
+gate_symbol(char *name)
+#else
+gate_symbol(name)
+char *name;
+#endif
+{
+ static char buf[100];
+ sprintf(buf, "%s_h", name);
+ return buf;
+}
+
+/* Added by TJP August 1994 */
+static char *
+#ifdef __USE_PROTOS
+mystrdup(char *s)
+#else
+mystrdup(s)
+char *s;
+#endif
+{
+ char *p = (char *)malloc(strlen(s)+1);
+ strcpy(p, s);
+ return p;
+}
+
+#ifdef __USE_PROTOS
+void p_class_hdr(void)
+#else
+void p_class_hdr()
+#endif
+{
+ if ( class_stream == NULL ) return;
+ fprintf(class_stream, "#ifndef %s\n", gate_symbol(ClassName("")));
+ fprintf(class_stream, "#define %s\n", gate_symbol(ClassName("")));
+ fprintf(class_stream, "/*\n");
+ fprintf(class_stream, " * D L G L e x e r C l a s s D e f i n i t i o n\n");
+ fprintf(class_stream, " *\n");
+ fprintf(class_stream, " * Generated from:");
+ fprintf(class_stream, " %s", file_str[0]);
+ fprintf(class_stream, "\n");
+ fprintf(class_stream, " *\n");
+ fprintf(class_stream, " * 1989-2001 by Will Cohen, Terence Parr, and Hank Dietz\n");
+ fprintf(class_stream, " * Purdue University Electrical Engineering\n");
+ fprintf(class_stream, " * DLG Version %s\n", version);
+ fprintf(class_stream, " */\n\n");
+ fprintf(class_stream, "\n");
+ fprintf(class_stream, "#include \"%s\"\n", DLEXERBASE_H);
+}
+
+/* MR1 */
+/* MR1 16-Apr-97 Split printing of class header up into several parts */
+/* MR1 so that #lexprefix <<...>>and #lexmember <<...>> */
+/* MR1 can be inserted in the appropriate spots */
+/* MR1 */
+
+#ifdef __USE_PROTOS
+void p_class_def1(void)
+#else
+void p_class_def1()
+#endif
+{
+ if ( class_stream == NULL ) return;
+ fprintf(class_stream, "\nclass %s : public DLGLexerBase {\n", ClassName(""));
+ fprintf(class_stream, "public:\n");
+}
+
+#ifdef __USE_PROTOS
+void p_class_def2(void)
+#else
+void p_class_def2()
+#endif
+{
+ int i, m;
+ if ( class_stream == NULL ) return;
+ fprintf(class_stream, "public:\n");
+ fprintf(class_stream, "\tstatic const int MAX_MODE;\n");
+ fprintf(class_stream, "\tstatic const int DfaStates;\n");
+ for (i=0; i<cur_mode; i++) {
+ fprintf(class_stream, "\tstatic const int %s;\n", mode_name[i]);
+ }
+
+ fprintf(class_stream, "\ttypedef %s DfaState;\n\n", minsize(dfa_allocated));
+ fprintf(class_stream, "\t%s(DLGInputStream *in,\n",ClassName(""));
+ fprintf(class_stream, "\t\tunsigned bufsize=2000)\n");
+ fprintf(class_stream, "\t\t: DLGLexerBase(in, bufsize, %d)\n", interactive);
+ fprintf(class_stream, "\t{\n");
+ fprintf(class_stream, "\t;\n");
+ fprintf(class_stream, "\t}\n");
+ fprintf(class_stream, "\tvoid mode(int);\n");
+ fprintf(class_stream, "\tANTLRTokenType nextTokenType(void);\n");
+ fprintf(class_stream, "\tvoid advance(void);\n");
+ fprintf(class_stream, "protected:\n");
+ for (i=1; i<=action_no; ++i) {
+ fprintf(class_stream, "\tANTLRTokenType act%d();\n", i);
+ }
+
+ for(m=0; m<(mode_counter-1); ++m){
+ for(i=dfa_basep[m]; i<dfa_basep[m+1]; ++i)
+ fprintf(class_stream, "\tstatic DfaState st%d[%d];\n", i-1, dfa_class_nop[m]+1);
+ }
+ for(i=dfa_basep[m]; i<=dfa_allocated; ++i)
+ fprintf(class_stream, "\tstatic DfaState st%d[%d];\n", i-1, dfa_class_nop[m]+1);
+
+ fprintf(class_stream, "\tstatic DfaState *dfa[%d];\n", dfa_allocated);
+ fprintf(class_stream, "\tstatic DfaState dfa_base[];\n");
+/* fprintf(class_stream, "\tstatic int dfa_base_no[];\n"); */
+ fprintf(class_stream, "\tstatic unsigned char *b_class_no[];\n");
+ fprintf(class_stream, "\tstatic DfaState accepts[%d];\n",dfa_allocated+1);
+ fprintf(class_stream, "\tstatic DLGChar alternatives[%d];\n",dfa_allocated+1);
+ /* WARNING: should be ANTLRTokenType for action table, but g++ 2.5.6 is hosed */
+ fprintf(class_stream, "\tstatic ANTLRTokenType (%s::*actions[%d])();\n", ClassName(""), action_no+1);
+ for(m=0; m<mode_counter; ++m) {
+ fprintf(class_stream, "\tstatic unsigned char shift%d[%d];\n",
+ m, CHAR_RANGE);
+ }
+ if (comp_level)
+ fprintf(class_stream, "\tint ZZSHIFT(int c) { return b_class_no[automaton][1+c]; }\n");
+ else
+ fprintf(class_stream, "\tint ZZSHIFT(int c) { return 1+c; }\n");
+
+/* MR1 */
+/* MR1 11-APr-97 Kludge to allow inclusion of user-defined code in */
+/* MR1 DLGLexer class header */
+/* MR1 Deprecated in favor of 133MR1 addition #lexmember <<>> */
+/* MR1 */
+/* MR1 */ fprintf(class_stream,"//\n");
+/* MR1 */ fprintf(class_stream,
+/* MR1 */ "// 133MR1 Deprecated feature to allow inclusion of ");
+/* MR1 */ fprintf(class_stream,
+/* MR1 */ "user-defined code in DLG class header\n");
+/* MR1 */ fprintf(class_stream,"//\n");
+/* MR1 */
+/* MR1 */ fprintf(class_stream,"#ifdef DLGLexerIncludeFile\n");
+/* MR1 */ fprintf(class_stream,"#include DLGLexerIncludeFile\n");
+/* MR1 */ fprintf(class_stream,"#endif\n");
+
+ fprintf(class_stream, "};\n");
+
+ fprintf(class_stream, "typedef ANTLRTokenType (%s::*Ptr%sMemberFunc)();\n",
+ ClassName(""), ClassName(""));
+
+ fprintf(class_stream, "#endif\n");
+}
+
+/* generate required header on output */
+
+#ifdef __USE_PROTOS
+void p_head(void)
+#else
+void p_head()
+#endif
+{
+ fprintf(OUT, "/*\n");
+ fprintf(OUT, " * D L G tables\n");
+ fprintf(OUT, " *\n");
+ fprintf(OUT, " * Generated from:");
+ fprintf(OUT, " %s", file_str[0]);
+ fprintf(OUT, "\n");
+ fprintf(OUT, " *\n");
+ fprintf(OUT, " * 1989-2001 by Will Cohen, Terence Parr, and Hank Dietz\n");
+ fprintf(OUT, " * Purdue University Electrical Engineering\n");
+ fprintf(OUT, " * DLG Version %s\n", version);
+ fprintf(OUT, " */\n\n");
+ if ( gen_cpp) fprintf(OUT, "#include \"pcctscfg.h\"\n");
+ if ( gen_cpp ) fprintf(OUT, "#include \"pccts_stdio.h\"\n");
+ if ( !gen_cpp ) fprintf(OUT, "#include \"%s\"\n\n", mode_file);
+ fprintf(OUT,"\n");
+}
+
+#ifdef __USE_PROTOS
+void p_includes(void)
+#else
+void p_includes()
+#endif
+{
+ fprintf(OUT, "#include \"%s\"\n", APARSER_H);
+ fprintf(OUT, "#include \"%s\"\n", DLEXERBASE_H);
+ fprintf(OUT, "#include \"%s\"\n", ClassName(".h"));
+}
+
+/* generate code to tie up any loose ends */
+
+#ifdef __USE_PROTOS
+void p_tail(void) /* MR1 */
+#else
+void p_tail() /* MR1 */
+#endif
+{
+ if ( gen_cpp ) {
+ if ( strcmp(ClassName(""), DEFAULT_CLASSNAME)!=0 )
+ fprintf(OUT, "#define DLGLexer %s\n", ClassName(""));
+ fprintf(OUT, "#include \"%s\"\n", DLEXER_H); /* MR23 Rename DLexer.cpp to DLexer.h */
+ return;
+ }
+ fprintf(OUT, "\n");
+ fprintf(OUT, "\n");
+ if (comp_level)
+ fprintf(OUT, "#define ZZSHIFT(c) (b_class_no[zzauto][1+c])\n");
+ else
+ fprintf(OUT, "#define ZZSHIFT(c) (1+c)\n");
+ if ( !gen_cpp ) fprintf(OUT, "#define MAX_MODE %d\n",mode_counter);
+ fprintf(OUT, "#include \"dlgauto.h\"\n");
+}
+
+
+/* output the table of DFA for general use */
+
+#ifdef __USE_PROTOS
+void p_tables()
+#else
+void p_tables()
+#endif
+{
+ if ( !gen_cpp ) {
+ fprintf(OUT, "#define DfaStates\t%d\n", dfa_allocated);
+ fprintf(OUT, "typedef %s DfaState;\n\n", minsize(dfa_allocated));
+ }
+
+ if ( gen_cpp ) {
+ int i;
+ fprintf(OUT, "\n");
+ fprintf(OUT, "const int %s::MAX_MODE=%d;\n",
+ ClassName(""),
+ mode_counter);
+ fprintf(OUT, "const int %s::DfaStates=%d;\n",
+ ClassName(""),
+ dfa_allocated);
+ for (i=0; i<cur_mode; i++) {
+ fprintf(OUT, "const int %s::%s=%d;\n",
+ ClassName(""), mode_name[i], mode_number[i]);
+ }
+ fprintf(OUT, "\n");
+ }
+
+ p_node_table();
+ p_dfa_table();
+ p_accept_table();
+ p_action_table();
+ p_base_table();
+ p_class_table();
+ if (comp_level)
+ p_bshift_table();
+ if (interactive || gen_cpp )
+ p_alternative_table();
+}
+
+
+/* figures out the smallest variable type that will hold the transitions
+ */
+
+#ifdef __USE_PROTOS
+char *minsize(int elements)
+#else
+char *minsize(elements)
+int elements;
+#endif
+{
+ int i = 0;
+
+ while ((unsigned long) elements > typesize[i]) /* MR20 */
+ ++i;
+ return typevar[i];
+}
+
+
+#ifdef __USE_PROTOS
+void p_node_table(void)
+#else
+void p_node_table()
+#endif
+{
+ register int i;
+ register int m = 0;
+
+ for(m=0; m<(mode_counter-1); ++m){
+ for(i=dfa_basep[m]; i<dfa_basep[m+1]; ++i)
+ p_single_node(i,dfa_class_nop[m]);
+ }
+ for(i=dfa_basep[m]; i<=dfa_allocated; ++i)
+ p_single_node(i,dfa_class_nop[m]);
+}
+
+
+#ifdef __USE_PROTOS
+void p_single_node(int i,int classes)
+#else
+void p_single_node(i,classes)
+int i,classes;
+#endif
+{
+ register int j;
+ register int trans, items_on_line;
+
+#if 1
+ /* extra state (classes+1) for invalid characters */
+ fprintf(OUT, "%sDfaState %sst%d[%d] = {\n ",
+ gen_cpp?ClassName("::"):"static ",
+ gen_cpp?ClassName("::"):"",(i-1), (classes+1));
+#else
+ fprintf(OUT, "static DfaState st%d[%d] = {\n ", (i-1), classes);
+#endif
+ items_on_line = MAX_ON_LINE;
+ for(j=0; j<classes; ++j){
+ DAWDLE;
+ trans = DFA(i)->trans[j];
+ if (trans == NIL_INDEX)
+ trans = dfa_allocated+1;
+ /* all of DFA moved down one in array */
+ fprintf(OUT, "%d", trans-1);
+ fprintf(OUT, ", ");
+ if (!(--items_on_line)){
+ fprintf(OUT, "\n ");
+ items_on_line = MAX_ON_LINE;
+ }
+ }
+#if 1
+ /* put in jump to error state */
+ fprintf(OUT, "%d\n};\n\n", dfa_allocated);
+#else
+ fprintf(OUT, "\n};\n\n");
+#endif
+}
+
+
+#ifdef __USE_PROTOS
+void p_dfa_table(void)
+#else
+void p_dfa_table()
+#endif
+{
+ register int i;
+
+ fprintf(OUT, "\n%sDfaState *%sdfa[%d] = {\n",
+ gen_cpp?ClassName("::"):"",gen_cpp?ClassName("::"):"", dfa_allocated);
+ for (i=0; i<(dfa_allocated-1); ++i){
+ fprintf(OUT, "\tst%d,\n", i);
+ }
+ fprintf(OUT, "\tst%d\n", i);
+ fprintf(OUT, "};\n\n");
+}
+
+
+#ifdef __USE_PROTOS
+void p_accept_table(void)
+#else
+void p_accept_table()
+#endif
+{
+ register int i = 1;
+ register int items_on_line = 0;
+ int true_interactive = TRUE;
+
+ /* make sure element for one past (zzerraction) -WEC 12/16/92 */
+ fprintf(OUT,"\n%sDfaState %saccepts[%d] = {\n ",
+ gen_cpp?ClassName("::"):"",
+ gen_cpp?ClassName("::"):"",
+ dfa_allocated+1);
+ /* don't do anything if no dfa nodes */
+ if (i>dfa_allocated) goto skip_accepts;
+ for (;;) {
+ int accept=0; /* MR14a - Manuel Kessler (mlkessle@cip.physik.uni-wuerzburg.de) */
+ set accept_set;
+ set nfa_states;
+ unsigned int *t, *nfa_i;
+ unsigned int *q, *regular_expr;
+
+ accept_set = empty;
+ nfa_states = DFA(i)->nfa_states;
+ t = nfa_i = set_pdq(nfa_states);
+ /* NOTE: picks lowest accept because accepts monotonic */
+ /* with respect to nfa node numbers and set_pdq */
+ /* returns in that order */
+ while((*nfa_i != nil) && (!(accept = NFA(*nfa_i)->accept))){
+ nfa_i++;
+ }
+
+ /* figure out if more than one accept state there */
+ if (warn_ambig ){
+ set_orel(accept, &accept_set);
+ while(*nfa_i != nil){
+ set_orel(NFA(*nfa_i)->accept, &accept_set);
+ nfa_i++;
+ }
+ /* remove error action from consideration */
+ set_rm(0, accept_set);
+
+ if( set_deg(accept_set)>1){
+ fprintf(stderr, "dlg warning: ambiguous regular expression ");
+ q = regular_expr = set_pdq(accept_set);
+ while(*regular_expr != nil){
+ fprintf(stderr," %d ", *regular_expr);
+ ++regular_expr;
+ }
+ fprintf(stderr, "\n");
+ free(q);
+ }
+ }
+
+ if ((DFA(i)->alternatives) && (accept != 0)){
+ true_interactive = FALSE;
+ }
+ fprintf(OUT, "%d, ", accept);
+
+ /* free up memory before we "break" below -ATG 4/6/95 */
+ free(t);
+ set_free(accept_set);
+
+ if ((++i)>dfa_allocated)
+ break;
+ if ((++items_on_line)>=MAX_ON_LINE){
+ fprintf(OUT,"\n ");
+ items_on_line = 0;
+ }
+/*
+ free(t);
+ set_free(accept_set);
+*/
+ }
+ /* make sure element for one past (zzerraction) -WEC 12/16/92 */
+skip_accepts:
+ fprintf(OUT, "0\n};\n\n");
+}
+
+
+#ifdef __USE_PROTOS
+void p_action_table(void)
+#else
+void p_action_table()
+#endif
+{
+ register int i;
+ char* theClassName = ClassName("");
+
+ if ( gen_cpp )
+ fprintf(OUT, "Ptr%sMemberFunc %s::actions[%d] = {\n", theClassName,
+ theClassName, action_no+1);
+ else
+ fprintf(OUT, "void (*actions[%d])() = {\n", action_no+1);
+ if ( gen_cpp )
+/* fprintf(OUT, "\t(Ptr%sMemberFunc)&%s::erraction,\n", theClassName, theClassName);*/
+ fprintf(OUT, "\t&%s::erraction,\n", theClassName);
+ else
+ fprintf(OUT, "\tzzerraction,\n");
+ for (i=1; i<action_no; ++i) {
+ if ( gen_cpp )
+/* fprintf(OUT,"\t(Ptr%sMemberFunc)&%s::act%d,\n", theClassName, theClassName, i);*/
+ fprintf(OUT,"\t&%s::act%d,\n", theClassName, i);
+ else
+ fprintf(OUT,"\tact%d,\n", i);
+ DAWDLE;
+ }
+ if ( gen_cpp )
+/* fprintf(OUT,"\t(Ptr%sMemberFunc)&%s::act%d\n", theClassName, theClassName, i);*/
+ fprintf(OUT,"\t&%s::act%d\n", theClassName, i);
+ else
+ fprintf(OUT,"\tact%d\n", i);
+ fprintf(OUT, "};\n\n");
+}
+
+
+#ifdef __USE_PROTOS
+void p_shift_table(int m) /* MR1 */
+#else
+void p_shift_table(m) /* MR1 */
+int m;
+#endif
+{
+ register int i = 0, j;
+ register int items_on_line = 0;
+
+ fprintf(OUT, "%s unsigned char %sshift%d[%d] = {\n ",
+ gen_cpp?"":"static",
+ gen_cpp?ClassName("::"):"", m, CHAR_RANGE);
+ for (;;) {
+ /* find which partition character i is in */
+ for (j=0; j<dfa_class_nop[mode_counter]; ++j){
+ if (set_el(i,class_sets[j]))
+ break;
+ }
+ fprintf(OUT,"%d",j);
+ if ((++i)>=CHAR_RANGE)
+ break;
+ fprintf(OUT,", ");
+ if ((++items_on_line)>=MAX_ON_LINE){
+ fprintf(OUT,"\n ");
+ items_on_line = 0;
+ }
+ }
+ fprintf(OUT, "\n};\n\n");
+}
+
+
+#ifdef __USE_PROTOS
+void p_base_table(void)
+#else
+void p_base_table()
+#endif
+{
+ register int m;
+
+ fprintf(OUT, "%sDfaState %sdfa_base[] = {\n",
+ gen_cpp?ClassName("::"):"static ",
+ gen_cpp?ClassName("::"):"");
+ for(m=0; m<(mode_counter-1); ++m)
+ fprintf(OUT, "\t%d,\n", dfa_basep[m]-1);
+ fprintf(OUT, "\t%d\n};\n\n", dfa_basep[m]-1);
+}
+
+
+#ifdef __USE_PROTOS
+void p_class_table(void) /* MR1 */
+#else
+void p_class_table() /* MR1 */
+#endif
+{
+#if 0
+ register int m;
+
+ fprintf(OUT,"%s int %sdfa_class_no[] = {\n",
+ gen_cpp?"":"static",
+ gen_cpp?ClassName("::"):"");
+ for(m=0; m<(mode_counter-1); ++m)
+ fprintf(OUT,"\t%d,\n", dfa_class_nop[m]);
+ fprintf(OUT,"\t%d\n};\n\n", dfa_class_nop[m]);
+#endif
+}
+
+
+#ifdef __USE_PROTOS
+void p_bshift_table(void) /* MR1 */
+#else
+void p_bshift_table() /* MR1 */
+#endif
+{
+ register int m;
+
+ fprintf(OUT,"%s unsigned char *%sb_class_no[] = {\n",
+ gen_cpp?"":"static",
+ gen_cpp?ClassName("::"):"");
+ for(m=0; m<(mode_counter-1); ++m)
+ fprintf(OUT, "\tshift%d,\n", m);
+ fprintf(OUT, "\tshift%d\n};\n\n", m);
+}
+
+
+#ifdef __USE_PROTOS
+void p_alternative_table(void) /* MR1 */
+#else
+void p_alternative_table() /* MR1 */
+#endif
+{
+ register int i;
+
+ if ( !gen_cpp ) fprintf(OUT, "#define ZZINTERACTIVE\n\n");
+ if ( gen_cpp )
+ fprintf(OUT, "DLGChar %salternatives[%d] = {\n", /* mr23 vhs %sDfaStates+1 */
+ ClassName("::"),
+ dfa_allocated+1); /* vhs ClassName("::")); */
+ else
+ fprintf(OUT, "static %s zzalternatives[DfaStates+1] = {\n",
+ minsize(dfa_allocated));
+
+ for(i=1; i<=dfa_allocated; ++i)
+ fprintf(OUT, "\t%d,\n", DFA(i)->alternatives);
+ fprintf(OUT, "/* must have 0 for zzalternatives[DfaStates] */\n");
+ fprintf(OUT, "\t0\n};\n\n");
+}
+
+
+#ifdef __USE_PROTOS
+void p_mode_def(char *s,int m) /* MR1 */
+#else
+void p_mode_def(s,m) /* MR1 */
+char *s;
+int m;
+#endif
+{
+ if ( gen_cpp )
+ {
+ mode_name[cur_mode] = mystrdup(s);
+ mode_number[cur_mode] = m;
+ cur_mode++;
+ }
+ else
+ fprintf(mode_stream, "#define %s %d\n", s, m);
+}
+
+#ifdef __USE_PROTOS
+char * ClassName(char *suffix)
+#else
+char * ClassName(suffix)
+char *suffix;
+#endif
+{
+ static char buf[200];
+ extern char *class_name;
+
+ sprintf(buf, "%s%s", class_name, suffix);
+ return buf;
+}
+
+#ifdef DEBUG
+
+/* print out a particular nfa node that is pointed to by p */
+
+#ifdef __USE_PROTOS
+void p_nfa_node(nfa_node *p)
+#else
+void p_nfa_node(p)
+nfa_node *p;
+#endif
+{
+ register nfa_node *t;
+
+ if (p != NIL_INDEX){
+ printf("NFA state : %d\naccept state : %d\n",
+ NFA_NO(p),p->accept);
+ if (p->trans[0] != NIL_INDEX){
+ printf("trans[0] => %d on ", NFA_NO(p->trans[0]));
+ p_set(p->label);
+ printf("\n");
+ }
+ else
+ printf("trans[0] => nil\n");
+ if (p->trans[1] != NIL_INDEX)
+ printf("trans[1] => %d on epsilon\n",
+ NFA_NO(p->trans[1]));
+ else
+ printf("trans[1] => nil\n");
+ printf("\n");
+ }
+}
+#endif
+
+#ifdef DEBUG
+
+/* code to print out special structures when using a debugger */
+
+#ifdef __USE_PROTOS
+void p_nfa(p)
+#else
+void p_nfa(nfa_node *p)
+nfa_node *p; /* state number also index into array */
+#endif
+{
+/* each node has a marker on it so it only gets printed once */
+
+ operation_no++; /* get new number */
+ s_p_nfa(p);
+}
+
+#ifdef __USE_PROTOS
+void s_p_nfa(nfa_node *p)
+#else
+void s_p_nfa(p)
+nfa_node *p; /* state number also index into array */
+#endif
+{
+ if ((p != NIL_INDEX) && (p->nfa_set != operation_no)){
+ /* so it is only printed once */
+ p->nfa_set = operation_no;
+ p_nfa_node(p);
+ s_p_nfa(p->trans[0]);
+ s_p_nfa(p->trans[1]);
+ }
+}
+
+#ifdef __USE_PROTOS
+void p_dfa_node(dfa_node *p)
+#else
+void p_dfa_node(p)
+dfa_node *p;
+#endif
+{
+ int i;
+
+ if (p != NIL_INDEX){
+ printf("DFA state :%d\n",NFA_NO(p));
+ if (p->done)
+ printf("done\n");
+ else
+ printf("undone\n");
+ printf("from nfa states : ");
+ p_set(p->nfa_states);
+ printf("\n");
+ /* NOTE: trans arcs stored as ints rather than pointer*/
+ for (i=0; i<class_no; i++){
+ printf("%d ",p->trans[i]);
+ }
+ printf("\n\n");
+ }
+}
+
+#ifdef __USE_PROTOS
+void p_dfa(void)
+#else
+void p_dfa()
+#endif
+{
+/* prints out all the dfa nodes actually allocated */
+
+ int i;
+
+ for (i = 1; i<=dfa_allocated; i++)
+ p_dfa_node(NFA(i));
+}
+
+
+/* print out numbers in the set label */
+
+#ifdef __USE_PROTOS
+void p_set(set label)
+#else
+void p_set(label)
+set label;
+#endif
+{
+ unsigned *t, *e;
+
+ if (set_nil(label)){
+ printf("epsilon\n");
+ }else{
+ t = e = set_pdq(label);
+ while(*e != nil){
+ printf("%d ", (*e+MIN_CHAR));
+ e++;
+ }
+ printf("\n");
+ free(t);
+ }
+
+}
+#endif
diff --git a/Source/Pccts/dlg/parser.dlg b/Source/Pccts/dlg/parser.dlg
new file mode 100644
index 0000000..df9a637
--- /dev/null
+++ b/Source/Pccts/dlg/parser.dlg
@@ -0,0 +1,398 @@
+<<
+/* parser.dlg -- DLG Description of scanner
+ *
+ * Generated from: dlg_p.g
+ *
+ * Terence Parr, Will Cohen, and Hank Dietz: 1989-2001
+ * Purdue University Electrical Engineering
+ * With AHPCRC, University of Minnesota
+ * ANTLR Version 1.33MR33
+ */
+
+#define ANTLR_VERSION 13333
+#include "pcctscfg.h"
+#include "pccts_stdio.h"
+
+#include <ctype.h>
+#include "dlg.h"
+#include "antlr.h"
+#include "tokens.h"
+#include "dlgdef.h"
+LOOKAHEAD
+
+void
+#ifdef __USE_PROTOS
+zzerraction(void)
+#else
+zzerraction()
+#endif
+{
+ (*zzerr)("invalid token");
+ zzadvance();
+ zzskip();
+}
+>>
+
+<<%%lexaction
+
+int func_action; /* should actions be turned into functions?*/
+int lex_mode_counter = 0; /* keeps track of the number of %%names */
+/* MR1 */
+/* MR1 11-Apr-97 Provide mechanism for inserting code into DLG class */
+/* MR1 via <<%%lexmember...>> */
+/* MR1 */
+int lexMember = 0; /* <<%%lexmemeber ...>> MR1 */
+int lexAction = 0; /* <<%%lexaction ...>> MR1 */
+int parserClass = 0; /* <<%%parserclass ...>> MR1 */
+int lexPrefix = 0; /* <<%%lexprefix ...>> MR1 */
+char theClassName[100]; /* MR11 */
+char *pClassName=theClassName; /* MR11 */
+int firstLexMember=1; /* MR1 */
+
+#ifdef __USE_PROTOS
+void xxputc(int c) { /* MR1 */
+#else
+ void xxputc(c) /* MR1 */
+ int c; /* MR1 */
+ { /* MR1 */
+#endif
+ if (parserClass) { /* MR1 */
+ *pClassName++=c; /* MR1 */
+ *pClassName=0; /* MR1 */
+ } else if (lexMember || lexPrefix) { /* MR1 */
+ if (class_stream != NULL) fputc(c,class_stream); /* MR1 */
+ } else { /* MR1 */
+ fputc(c,OUT); /* MR1 */
+ }; /* MR1 */
+ } /* MR1 */
+
+#ifdef __USE_PROTOS
+ void xxprintf(char *format,char *string) { /* MR1 */
+#else
+ void xxprintf(format,string) /* MR1 */
+ char *format; /* MR1 */
+ char *string; /* MR1 */
+ { /* MR1 */
+#endif
+ if (lexMember || lexPrefix || parserClass) { /* MR1 */
+ if (class_stream != NULL) /* MR1 */
+ fprintf(class_stream,format,string); /* MR1 */
+ } else { /* MR1 */
+ fprintf(OUT,format,string); /* MR1 */
+ }; /* MR1 */
+ } /* MR1 */
+>>
+
+
+%%START
+
+@
+ <<
+ NLA = 1;
+ >>
+
+[\r\t\ ]+
+ <<
+ NLA = 2;
+ zzskip();
+ >>
+
+\n
+ <<
+ NLA = 3;
+ zzline++; zzskip(); DAWDLE;
+ >>
+
+\@
+ <<
+ NLA = L_EOF;
+ >>
+
+\%\%
+ <<
+ NLA = PER_PER;
+ >>
+
+\%\%[a-zA-Z_][a-zA-Z0-9_]*
+ <<
+ NLA = NAME_PER_PER;
+ p_mode_def(&zzlextext[2],lex_mode_counter++);
+ >>
+
+\<\<\%\%lexmember
+ <<
+ NLA = LEXMEMBER;
+ lexMember=1; /* MR1 */
+ if (firstLexMember != 0) { /* MR1 */
+ firstLexMember=0; /* MR1 */
+ p_class_def1(); /* MR1 */
+ }; /* MR1 */
+ zzmode(ACT); /* MR1 */
+ >>
+
+\<\<\%\%lexaction
+ <<
+ NLA = LEXACTION;
+ lexAction=1;zzmode(ACT);
+ >>
+
+\<\<\%\%parserclass
+ <<
+ NLA = PARSERCLASS;
+ parserClass=1; /* MR1 */
+ zzmode(ACT); /* MR1 */
+ >>
+
+\<\<\%\%lexprefix
+ <<
+ NLA = LEXPREFIX;
+ lexPrefix=1;zzmode(ACT);
+ >>
+
+\<\<
+ <<
+ NLA = ACTION;
+ if (func_action)
+ fprintf(OUT,"\n%s %sact%d()\n{ ",
+ gen_cpp?"ANTLRTokenType":"static void",
+ gen_cpp?ClassName("::"):"", ++action_no);
+ zzmode(ACT); zzskip();
+ >>
+
+\>\>
+ <<
+ NLA = GREAT_GREAT;
+ >>
+
+\{
+ <<
+ NLA = L_BRACE;
+ >>
+
+\}
+ <<
+ NLA = R_BRACE;
+ >>
+
+\(
+ <<
+ NLA = L_PAR;
+ >>
+
+\)
+ <<
+ NLA = R_PAR;
+ >>
+
+\[
+ <<
+ NLA = L_BRACK;
+ >>
+
+\]
+ <<
+ NLA = R_BRACK;
+ >>
+
+\*
+ <<
+ NLA = ZERO_MORE;
+ >>
+
+\+
+ <<
+ NLA = ONE_MORE;
+ >>
+
+\|
+ <<
+ NLA = OR;
+ >>
+
+\-
+ <<
+ NLA = RANGE;
+ >>
+
+\~
+ <<
+ NLA = NOT;
+ >>
+
+\\0[0-7]*
+ <<
+ NLA = OCTAL_VALUE;
+ {int t; sscanf(&zzlextext[1],"%o",&t); zzlextext[0] = t;}
+ >>
+
+\\0[Xx][0-9a-fA-F]+
+ <<
+ NLA = HEX_VALUE;
+ {int t; sscanf(&zzlextext[3],"%x",&t); zzlextext[0] = t;}
+ >>
+
+\\[1-9][0-9]*
+ <<
+ NLA = DEC_VALUE;
+ {int t; sscanf(&zzlextext[1],"%d",&t); zzlextext[0] = t;}
+ >>
+
+\\t
+ <<
+ NLA = TAB;
+ zzlextext[0] = '\t';
+ >>
+
+\\n
+ <<
+ NLA = NL;
+ zzlextext[0] = '\n';
+ >>
+
+\\r
+ <<
+ NLA = CR;
+ zzlextext[0] = '\r';
+ >>
+
+\\b
+ <<
+ NLA = BS;
+ zzlextext[0] = '\b';
+ >>
+
+\\ \n
+ <<
+ NLA = CONTINUATION;
+ zzline++; zzskip();
+ >>
+
+\\~[tnrb]
+ <<
+ NLA = LIT;
+ zzlextext[0] = zzlextext[1];
+ >>
+
+~[\\]
+ <<
+ NLA = REGCHAR;
+ >>
+
+
+%%ACT
+
+@
+ <<
+ NLA = 1;
+ error("unterminated action", zzline); zzmode(START);
+ >>
+
+\>\>
+ <<
+ NLA = ACTION;
+ if (func_action) fprintf(OUT,"}\n\n");
+ zzmode(START);
+ /* MR1 */
+ /* MR1 11-Apr-97 Provide mechanism for inserting code into DLG class */
+ /* MR1 via <<%%lexmember ...>> */
+ /* MR1 This is a consequence of not saving actions */
+ /* MR1 */
+ /* MR1 */ parserClass=0;
+ /* MR1 */ lexPrefix=0;
+ /* MR1 */ lexAction=0;
+ /* MR1 */ lexMember=0;
+ >>
+
+\>
+ <<
+ NLA = 34;
+ xxputc(zzlextext[0]); zzskip();
+ >>
+
+\\\>
+ <<
+ NLA = 35;
+ xxputc('>'); zzskip();
+ >>
+
+\\
+ <<
+ NLA = 36;
+ xxputc('\\'); zzskip();
+ >>
+
+\n
+ <<
+ NLA = 37;
+ xxputc(zzlextext[0]); ++zzline; zzskip();
+ >>
+
+/\*
+ <<
+ NLA = 38;
+ zzmode(ACTION_COMMENTS); /* MR1 */
+ xxprintf("%s", &(zzlextext[0])); zzskip(); /* MR1 */
+ >>
+
+//
+ <<
+ NLA = 39;
+ zzmode(ACTION_CPP_COMMENTS); /* MR1 */
+ xxprintf("%s", &(zzlextext[0])); zzskip(); /* MR1 */
+ >>
+
+~[]
+ <<
+ NLA = 40;
+ xxputc(zzlextext[0]); zzskip();
+ >>
+
+
+%%ACTION_COMMENTS
+
+@
+ <<
+ NLA = 1;
+ >>
+
+\*/
+ <<
+ NLA = 41;
+ zzmode(ACT); /* MR1 */
+ xxprintf("%s", &(zzlextext[0])); zzskip(); /* MR1 */
+ >>
+
+[\n\r]
+ <<
+ NLA = 42;
+ zzline++; xxputc(zzlextext[0]); zzskip();
+ >>
+
+~[]
+ <<
+ NLA = 43;
+ xxputc(zzlextext[0]); zzskip();
+ >>
+
+
+%%ACTION_CPP_COMMENTS
+
+@
+ <<
+ NLA = 1;
+ >>
+
+[\n\r]
+ <<
+ NLA = 44;
+ zzmode(ACT); zzline++; /* MR1 */
+ xxprintf("%s", &(zzlextext[0])); zzskip(); /* MR1 */
+ >>
+
+~[]
+ <<
+ NLA = 45;
+ xxputc(zzlextext[0]); zzskip();
+ >>
+
+%%
diff --git a/Source/Pccts/dlg/relabel.c b/Source/Pccts/dlg/relabel.c
new file mode 100644
index 0000000..0b8bc16
--- /dev/null
+++ b/Source/Pccts/dlg/relabel.c
@@ -0,0 +1,217 @@
+/* This group of functions does the character class compression.
+ It goes over the dfa and relabels the arcs with the partitions
+ of characters in the NFA. The partitions are stored in the
+ array class.
+
+ *
+ * SOFTWARE RIGHTS
+ *
+ * We reserve no LEGAL rights to the Purdue Compiler Construction Tool
+ * Set (PCCTS) -- PCCTS is in the public domain. An individual or
+ * company may do whatever they wish with source code distributed with
+ * PCCTS or the code generated by PCCTS, including the incorporation of
+ * PCCTS, or its output, into commerical software.
+ *
+ * We encourage users to develop software with PCCTS. However, we do ask
+ * that credit is given to us for developing PCCTS. By "credit",
+ * we mean that if you incorporate our source code into one of your
+ * programs (commercial product, research project, or otherwise) that you
+ * acknowledge this fact somewhere in the documentation, research report,
+ * etc... If you like PCCTS and have developed a nice tool with the
+ * output, please mention that you developed it using PCCTS. In
+ * addition, we ask that this header remain intact in our source code.
+ * As long as these guidelines are kept, we expect to continue enhancing
+ * this system and expect to make other tools available as they are
+ * completed.
+ *
+ * DLG 1.33
+ * Will Cohen
+ * With mods by Terence Parr; AHPCRC, University of Minnesota
+ * 1989-2001
+ */
+
+#include <stdio.h>
+#include "dlg.h"
+#ifdef MEMCHK
+#include "trax.h"
+#else
+#ifdef __STDC__
+#include <stdlib.h>
+#else
+#include <malloc.h>
+#endif /* __STDC__ */
+#endif
+
+int class_no = CHAR_RANGE; /* number of classes for labels */
+int first_el[CHAR_RANGE]; /* first element in each class partition */
+set class_sets[CHAR_RANGE]; /* array holds partitions from class */
+ /* compression */
+
+/* goes through labels on NFA graph and partitions the characters into
+ * character classes. This reduces the amount of space required for each
+ * dfa node, since only one arc is required each class instead of one arc
+ * for each character
+ * level:
+ * 0 no compression done
+ * 1 remove unused characters from classes
+ * 2 compress equivalent characters into same class
+ *
+ * returns the number of character classes required
+ */
+#ifdef __USE_PROTOS
+int relabel(nfa_node* start,int level)
+#else
+int relabel(start,level)
+int level;
+nfa_node *start;
+#endif
+{
+ if (level){
+ set_free(used_classes);
+ partition(start,level);
+ label_with_classes(start);
+ }else{
+ /* classes equivalent to all characters in alphabet */
+ class_no = CHAR_RANGE;
+ }
+ return class_no;
+}
+
+/* makes character class sets for new labels */
+#ifdef __USE_PROTOS
+void partition(nfa_node* start,int level)
+#else
+void partition(start,level)
+nfa_node *start; /* beginning of nfa graph */
+int level; /* compression level to uses */
+#endif
+{
+ set current_class;
+ set unpart_chars;
+ set temp;
+
+ unpart_chars = set_dup(used_chars);
+#if 0
+ /* EOF (-1+1) alway in class 0 */
+ class_sets[0] = set_of(0);
+ first_el[0] = 0;
+ used_classes = set_of(0);
+ temp = set_dif(unpart_chars, class_sets[0]);
+ set_free(unpart_chars);
+ unpart_chars = temp;
+ class_no = 1;
+#else
+ class_no = 0;
+#endif
+ while (!set_nil(unpart_chars)){
+ /* don't look for equivalent labels if c <= 1 */
+ if (level <= 1){
+ current_class = set_of(set_int(unpart_chars));
+ }else{
+ current_class = set_dup(unpart_chars);
+ intersect_nfa_labels(start,&current_class);
+ }
+ set_orel(class_no,&used_classes);
+ first_el[class_no] = set_int(current_class);
+ class_sets[class_no] = current_class;
+ temp = set_dif(unpart_chars,current_class);
+ set_free(unpart_chars);
+ unpart_chars = temp;
+ ++class_no;
+ }
+
+ /* free unpart_chars -ATG 5/6/95 */
+ set_free(unpart_chars);
+
+#if 0
+ /* group all the other unused characters into a class */
+ set_orel(class_no,&used_classes);
+ first_el[class_no] = set_int(current_class);
+ class_sets[class_no] = set_dif(normal_chars,used_chars);
+ ++class_no;
+#endif
+}
+
+
+/* given pointer to beginning of graph and recursively walks it trying
+ * to find a maximal partition. This partion in returned in maximal_class
+ */
+#ifdef __USE_PROTOS
+void intersect_nfa_labels(nfa_node* start,set* maximal_class)
+#else
+void intersect_nfa_labels(start,maximal_class)
+nfa_node *start;
+set *maximal_class;
+#endif
+{
+ /* pick a new operation number */
+ ++operation_no;
+ r_intersect(start,maximal_class);
+}
+
+#ifdef __USE_PROTOS
+void r_intersect(nfa_node* start,set* maximal_class)
+#else
+void r_intersect(start,maximal_class)
+nfa_node *start;
+set * maximal_class;
+#endif
+{
+ set temp;
+
+ if(start && start->nfa_set != operation_no)
+ {
+ start->nfa_set = operation_no;
+ temp = set_and(*maximal_class,start->label);
+ if (!set_nil(temp))
+ {
+ set_free(*maximal_class);
+ *maximal_class = temp;
+ }else{
+ set_free(temp);
+ }
+ r_intersect(start->trans[0],maximal_class);
+ r_intersect(start->trans[1],maximal_class);
+ }
+}
+
+
+/* puts class labels in place of old character labels */
+#ifdef __USE_PROTOS
+void label_with_classes(nfa_node* start)
+#else
+void label_with_classes(start)
+nfa_node *start;
+#endif
+{
+ ++operation_no;
+ label_node(start);
+}
+
+#ifdef __USE_PROTOS
+void label_node(nfa_node *start)
+#else
+void label_node(start)
+nfa_node *start;
+#endif
+{
+ set new_label;
+ register int i;
+
+ /* only do node if it hasn't been done before */
+ if (start && start->nfa_set != operation_no){
+ start->nfa_set = operation_no;
+ new_label = empty;
+ for (i = 0; i<class_no; ++i){
+ /* if one element of class in old_label,
+ all elements are. */
+ if (set_el(first_el[i],start->label))
+ set_orel(i,&new_label);
+ }
+ set_free(start->label);
+ start->label = new_label;
+ /* do any nodes that can be reached from this one */
+ label_node(start->trans[0]);
+ label_node(start->trans[1]);
+ }
+}
diff --git a/Source/Pccts/dlg/stdpccts.h b/Source/Pccts/dlg/stdpccts.h
new file mode 100644
index 0000000..06ec67e
--- /dev/null
+++ b/Source/Pccts/dlg/stdpccts.h
@@ -0,0 +1,26 @@
+#ifndef STDPCCTS_H
+#define STDPCCTS_H
+/*
+ * stdpccts.h -- P C C T S I n c l u d e
+ *
+ * Terence Parr, Will Cohen, and Hank Dietz: 1989-2001
+ * Purdue University Electrical Engineering
+ * With AHPCRC, University of Minnesota
+ * ANTLR Version 1.33MR33
+ */
+
+#ifndef ANTLR_VERSION
+#define ANTLR_VERSION 13333
+#endif
+
+#include "pcctscfg.h"
+#include "pccts_stdio.h"
+
+#include <ctype.h>
+#include "dlg.h"
+#define zzSET_SIZE 8
+#include "antlr.h"
+#include "tokens.h"
+#include "dlgdef.h"
+#include "mode.h"
+#endif
diff --git a/Source/Pccts/dlg/support.c b/Source/Pccts/dlg/support.c
new file mode 100644
index 0000000..84fe99d
--- /dev/null
+++ b/Source/Pccts/dlg/support.c
@@ -0,0 +1,240 @@
+/*
+ * SOFTWARE RIGHTS
+ *
+ * We reserve no LEGAL rights to the Purdue Compiler Construction Tool
+ * Set (PCCTS) -- PCCTS is in the public domain. An individual or
+ * company may do whatever they wish with source code distributed with
+ * PCCTS or the code generated by PCCTS, including the incorporation of
+ * PCCTS, or its output, into commerical software.
+ *
+ * We encourage users to develop software with PCCTS. However, we do ask
+ * that credit is given to us for developing PCCTS. By "credit",
+ * we mean that if you incorporate our source code into one of your
+ * programs (commercial product, research project, or otherwise) that you
+ * acknowledge this fact somewhere in the documentation, research report,
+ * etc... If you like PCCTS and have developed a nice tool with the
+ * output, please mention that you developed it using PCCTS. In
+ * addition, we ask that this header remain intact in our source code.
+ * As long as these guidelines are kept, we expect to continue enhancing
+ * this system and expect to make other tools available as they are
+ * completed.
+ *
+ * DLG 1.33
+ * Will Cohen
+ * With mods by Terence Parr; AHPCRC, University of Minnesota
+ * 1989-2001
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include "dlg.h"
+#ifdef MEMCHK
+#include "trax.h"
+#else
+#ifdef __STDC__
+#include <stdlib.h>
+#else
+#include <malloc.h>
+#endif /* __STDC__ */
+#endif
+
+int err_found = 0; /* indicates whether problem found */
+
+#ifdef __USE_PROTOS
+void internal_error(char *s, char *file,int line) /* MR9 23-Sep-97 */
+#else
+void internal_error(s,file,line) /* MR9 23-Sep-97 */
+char *s,*file;
+int line;
+#endif
+{
+ fprintf(stderr,s,file,line);
+ exit(PCCTS_EXIT_FAILURE);
+}
+
+#ifdef __USE_PROTOS
+char *dlg_malloc(int bytes,char *file,int line)
+#else
+char *dlg_malloc(bytes,file,line)
+int bytes;
+char *file;
+int line;
+#endif
+{
+ char *t;
+
+ t = (char *) malloc(bytes);
+ if (!t){
+ /* error */
+ internal_error("%s(%d): unable to allocate memory\n",
+ file,line);
+ }
+ return t;
+}
+
+
+#ifdef __USE_PROTOS
+char *dlg_calloc(int n,int bytes,char *file,int line)
+#else
+char *dlg_calloc(n,bytes,file,line)
+int n,bytes;
+char *file;
+int line;
+#endif
+{
+ char *t;
+
+ t = (char *) calloc(n,bytes);
+ if (!t){
+ /* error */
+ internal_error("%s(%d): unable to allocate memory\n",
+ file,line);
+ }
+ return t;
+}
+
+
+#ifdef __USE_PROTOS
+FILE *read_stream(char *name)
+#else
+FILE *read_stream(name)
+char *name;
+#endif
+{
+ FILE *f;
+
+ if (name){
+ if (name[0] == '-') {
+ fprintf(stderr, "dlg: invalid option: '%s'\n", name);
+ f = NULL;
+ }else{
+ f = fopen(name, "r");
+ if (f == NULL){
+ /* couldn't open file */
+ fprintf(stderr,
+ "dlg: Warning: Can't read file %s.\n",
+ name);
+ }
+ }
+ }else{
+ /* open stdin if nothing there */
+ f = stdin;
+ }
+ return f;
+}
+
+#ifdef __USE_PROTOS
+FILE *write_stream(char *name)
+#else
+FILE *write_stream(name)
+char *name;
+#endif
+{
+ FILE *f;
+
+ if (name){
+ if (name[0] == '-') {
+ fprintf(stderr, "dlg: invalid option: '%s'\n", name);
+ f = NULL;
+ }else{
+ f = fopen(OutMetaName(name), "w");
+ if (f == NULL){
+ /* couldn't open file */
+ fprintf(stderr,
+ "dlg: Warning: Can't write to file %s.\n",
+ name);
+ }
+ else
+#ifdef SPECIAL_FOPEN
+ special_fopen_actions(OutMetaName(name)); /* MR1 */
+#else
+ ; /* MR1 */
+#endif
+ }
+ }else{
+ /* open stdout if nothing there */
+ f = stdout;
+ }
+ return f;
+}
+
+
+#ifdef __USE_PROTOS
+void fatal(char *message,int line_no)
+#else
+void fatal(message,line_no)
+char *message;
+int line_no;
+#endif
+{
+ fprintf(stderr,ErrHdr,
+ (file_str[0] ? file_str[0] : "stdin"), line_no);
+ fprintf(stderr, " Fatal: %s\n", message);
+ exit(PCCTS_EXIT_FAILURE);
+}
+
+#ifdef __USE_PROTOS
+void error(char *message,int line_no)
+#else
+void error(message,line_no)
+char *message;
+int line_no;
+#endif
+{
+ fprintf(stderr,ErrHdr,
+ (file_str[0] ? file_str[0] : "stdin"), line_no);
+ fprintf(stderr, " Error: %s\n", message);
+ err_found = 1;
+}
+
+#ifdef __USE_PROTOS
+void warning(char *message,int line_no)
+#else
+void warning(message,line_no)
+char *message;
+int line_no;
+#endif
+{
+ fprintf(stderr,ErrHdr,
+ (file_str[0] ? file_str[0] : "stdin"), line_no);
+ fprintf(stderr, " Warning: %s\n", message);
+}
+
+/* MR10: Jeff Vincent
+ MR10: Changed to remove directory information from n only if
+ MR10: if OutputDirectory was changed by user (-o option)
+*/
+
+#ifdef __USE_PROTOS
+char *OutMetaName(char *n)
+#else
+char *OutMetaName(n)
+char *n;
+#endif
+{
+ static char *dir_sym = DirectorySymbol;
+ static char newname[MaxFileName+1];
+ char *p;
+
+ /* If OutputDirectory is same as TopDirectory (platform default) then leave n alone. */
+ if (strcmp(OutputDirectory, TopDirectory) == 0)
+ return n;
+
+ /* p will point to filename without path information */
+ if ((p = strrchr(n, *dir_sym)) != NULL)
+ p++;
+ else
+ p = n;
+
+ /* Copy new output directory into newname[] */
+ strcpy(newname, OutputDirectory);
+
+ /* if new output directory does not have trailing dir_sym, add it! */
+ if (newname[strlen(newname)-1] != *dir_sym)
+ strcat(newname, dir_sym);
+
+ /* contatenate FILE NAME ONLY to new output directory */
+ strcat(newname, p);
+
+ return newname;
+}
diff --git a/Source/Pccts/dlg/tokens.h b/Source/Pccts/dlg/tokens.h
new file mode 100644
index 0000000..73e502b
--- /dev/null
+++ b/Source/Pccts/dlg/tokens.h
@@ -0,0 +1,133 @@
+#ifndef tokens_h
+#define tokens_h
+/* tokens.h -- List of labelled tokens and stuff
+ *
+ * Generated from: dlg_p.g
+ *
+ * Terence Parr, Will Cohen, and Hank Dietz: 1989-2001
+ * Purdue University Electrical Engineering
+ * ANTLR Version 1.33MR33
+ */
+#define zzEOF_TOKEN 1
+#define L_EOF 4
+#define PER_PER 5
+#define NAME_PER_PER 6
+#define LEXMEMBER 7
+#define LEXACTION 8
+#define PARSERCLASS 9
+#define LEXPREFIX 10
+#define ACTION 11
+#define GREAT_GREAT 12
+#define L_BRACE 13
+#define R_BRACE 14
+#define L_PAR 15
+#define R_PAR 16
+#define L_BRACK 17
+#define R_BRACK 18
+#define ZERO_MORE 19
+#define ONE_MORE 20
+#define OR 21
+#define RANGE 22
+#define NOT 23
+#define OCTAL_VALUE 24
+#define HEX_VALUE 25
+#define DEC_VALUE 26
+#define TAB 27
+#define NL 28
+#define CR 29
+#define BS 30
+#define CONTINUATION 31
+#define LIT 32
+#define REGCHAR 33
+
+#ifdef __USE_PROTOS
+void grammar(void);
+#else
+extern void grammar();
+#endif
+
+#ifdef __USE_PROTOS
+void start_states(void);
+#else
+extern void start_states();
+#endif
+
+#ifdef __USE_PROTOS
+void do_conversion(void);
+#else
+extern void do_conversion();
+#endif
+
+#ifdef __USE_PROTOS
+void rule_list(void);
+#else
+extern void rule_list();
+#endif
+
+#ifdef __USE_PROTOS
+void rule(void);
+#else
+extern void rule();
+#endif
+
+#ifdef __USE_PROTOS
+void reg_expr(void);
+#else
+extern void reg_expr();
+#endif
+
+#ifdef __USE_PROTOS
+void and_expr(void);
+#else
+extern void and_expr();
+#endif
+
+#ifdef __USE_PROTOS
+void repeat_expr(void);
+#else
+extern void repeat_expr();
+#endif
+
+#ifdef __USE_PROTOS
+void expr(void);
+#else
+extern void expr();
+#endif
+
+#ifdef __USE_PROTOS
+void atom_list(void);
+#else
+extern void atom_list();
+#endif
+
+#ifdef __USE_PROTOS
+void near_atom(void);
+#else
+extern void near_atom();
+#endif
+
+#ifdef __USE_PROTOS
+void atom(void);
+#else
+extern void atom();
+#endif
+
+#ifdef __USE_PROTOS
+void anychar(void);
+#else
+extern void anychar();
+#endif
+
+#endif
+extern SetWordType zzerr1[];
+extern SetWordType zzerr2[];
+extern SetWordType zzerr3[];
+extern SetWordType setwd1[];
+extern SetWordType zzerr4[];
+extern SetWordType zzerr5[];
+extern SetWordType zzerr6[];
+extern SetWordType setwd2[];
+extern SetWordType zzerr7[];
+extern SetWordType zzerr8[];
+extern SetWordType zzerr9[];
+extern SetWordType setwd3[];
diff --git a/Source/Pccts/h/AParser.cpp b/Source/Pccts/h/AParser.cpp
new file mode 100644
index 0000000..720fe75
--- /dev/null
+++ b/Source/Pccts/h/AParser.cpp
@@ -0,0 +1,871 @@
+/* ANTLRParser.C
+ *
+ * SOFTWARE RIGHTS
+ *
+ * We reserve no LEGAL rights to the Purdue Compiler Construction Tool
+ * Set (PCCTS) -- PCCTS is in the public domain. An individual or
+ * company may do whatever they wish with source code distributed with
+ * PCCTS or the code generated by PCCTS, including the incorporation of
+ * PCCTS, or its output, into commerical software.
+ *
+ * We encourage users to develop software with PCCTS. However, we do ask
+ * that credit is given to us for developing PCCTS. By "credit",
+ * we mean that if you incorporate our source code into one of your
+ * programs (commercial product, research project, or otherwise) that you
+ * acknowledge this fact somewhere in the documentation, research report,
+ * etc... If you like PCCTS and have developed a nice tool with the
+ * output, please mention that you developed it using PCCTS. In
+ * addition, we ask that this header remain intact in our source code.
+ * As long as these guidelines are kept, we expect to continue enhancing
+ * this system and expect to make other tools available as they are
+ * completed.
+ *
+ * ANTLR 1.33
+ * Terence Parr
+ * Parr Research Corporation
+ * with Purdue University and AHPCRC, University of Minnesota
+ * 1989-2000
+ */
+
+#include "pcctscfg.h"
+
+#include "pccts_stdlib.h"
+#include "pccts_stdarg.h"
+#include "pccts_string.h"
+#include "pccts_stdio.h"
+
+PCCTS_NAMESPACE_STD
+
+/* I have to put this here due to C++ limitation
+ * that you can't have a 'forward' decl for enums.
+ * I hate C++!!!!!!!!!!!!!!!
+ * Of course, if I could use real templates, this would go away.
+ */
+// MR1
+// MR1 10-Apr-97 133MR1 Prevent use of varying sizes for the
+// MR1 ANTLRTokenType enum
+// MR1
+
+enum ANTLRTokenType { TER_HATES_CPP=0, ITS_TOO_COMPLICATED=9999}; // MR1
+
+#define ANTLR_SUPPORT_CODE
+
+#include ATOKEN_H
+#include ATOKENBUFFER_H
+#include APARSER_H
+
+static const int zzINF_DEF_TOKEN_BUFFER_SIZE = 2000; /* MR14 */
+static const int zzINF_BUFFER_TOKEN_CHUNK_SIZE = 1000; /* MR14 */
+
+ /* L o o k a h e a d M a c r o s */
+
+/* maximum of 32 bits/unsigned int and must be 8 bits/byte;
+ * we only use 8 bits of it.
+ */
+SetWordType ANTLRParser::bitmask[sizeof(SetWordType)*8] = {
+ 0x00000001, 0x00000002, 0x00000004, 0x00000008,
+ 0x00000010, 0x00000020, 0x00000040, 0x00000080
+};
+
+char ANTLRParser::eMsgBuffer[500] = "";
+
+ANTLRParser::
+~ANTLRParser()
+{
+ delete [] token_type;
+ delete [] zzFAILtext; // MR16 Manfred Kogler
+}
+
+ANTLRParser::
+ANTLRParser(ANTLRTokenBuffer *_inputTokens,
+ int k,
+ int use_inf_look,
+ int dlook,
+ int ssize)
+{
+ LLk = k;
+ can_use_inf_look = use_inf_look;
+/* MR14 */ if (dlook != 0) {
+/* MR14 */ panic("ANTLRParser::ANTLRParser - Demand lookahead not supported in C++ mode");
+/* MR14 */
+/* MR14 */ };
+ demand_look = 0; /* demand_look = dlook; */
+ bsetsize = ssize;
+ guessing = 0;
+ token_tbl = NULL;
+ eofToken = (ANTLRTokenType)1;
+
+ // allocate lookahead buffer
+ token_type = new ANTLRTokenType[LLk];
+ lap = 0;
+ labase = 0;
+#ifdef ZZDEFER_FETCH
+ stillToFetch = 0; // MR19
+#endif
+ dirty = 0;
+ inf_labase = 0; // MR7
+ inf_last = 0; // MR7
+ /* prime lookahead buffer, point to inputTokens */
+ this->inputTokens = _inputTokens;
+ this->inputTokens->setMinTokens(k);
+ _inputTokens->setParser(this); // MR1
+ resynchConsumed=1; // MR8
+ zzFAILtext=NULL; // MR9
+ traceOptionValueDefault=0; // MR10
+ traceReset(); // MR10
+ zzGuessSeq=0; // MR10
+ syntaxErrCount=0; // MR11
+}
+
+void ANTLRParser::init()
+{
+ prime_lookahead();
+ resynchConsumed=1; // MR8
+ traceReset(); // MR10
+}
+
+void ANTLRParser::traceReset()
+{
+ traceOptionValue=traceOptionValueDefault;
+ traceGuessOptionValue=1;
+ traceCurrentRuleName=NULL;
+ traceDepth=0;
+}
+
+
+#ifdef _MSC_VER // MR23
+//Turn off warning:
+//interaction between '_setjmp' and C++ object destruction is non-portable
+#pragma warning(disable : 4611)
+#endif
+int ANTLRParser::
+guess(ANTLRParserState *st)
+{
+ saveState(st);
+ guessing = 1;
+ return setjmp(guess_start.state);
+}
+#ifdef _MSC_VER // MR23
+#pragma warning(default: 4611)
+#endif
+
+void ANTLRParser::
+saveState(ANTLRParserState *buf)
+{
+ buf->guess_start = guess_start;
+ buf->guessing = guessing;
+ buf->inf_labase = inf_labase;
+ buf->inf_last = inf_last;
+ buf->dirty = dirty;
+ buf->traceOptionValue=traceOptionValue; /* MR10 */
+ buf->traceGuessOptionValue=traceGuessOptionValue; /* MR10 */
+ buf->traceCurrentRuleName=traceCurrentRuleName; /* MR10 */
+ buf->traceDepth=traceDepth; /* MR10 */
+}
+
+void ANTLRParser::
+restoreState(ANTLRParserState *buf)
+{
+ int i;
+ int prevTraceOptionValue;
+
+ guess_start = buf->guess_start;
+ guessing = buf->guessing;
+ inf_labase = buf->inf_labase;
+ inf_last = buf->inf_last;
+ dirty = buf->dirty;
+
+ // restore lookahead buffer from k tokens before restored TokenBuffer position
+ // if demand_look, then I guess we don't look backwards for these tokens.
+ for (i=1; i<=LLk; i++) token_type[i-1] =
+ inputTokens->bufferedToken(i-LLk)->getType();
+ lap = 0;
+ labase = 0;
+
+ /* MR10 */
+
+ prevTraceOptionValue=traceOptionValue;
+ traceOptionValue=buf->traceOptionValue;
+ if ( (prevTraceOptionValue > 0) !=
+ (traceOptionValue > 0)) {
+ if (traceCurrentRuleName != NULL) { /* MR21 */
+ if (traceOptionValue > 0) {
+ /* MR23 */ printMessage(stderr,
+ "trace enable restored in rule %s depth %d\n",
+ traceCurrentRuleName,
+ traceDepth);
+ };
+ if (traceOptionValue <= 0) {
+ /* MR23 */ printMessage(stderr,
+ "trace disable restored in rule %s depth %d\n",
+ traceCurrentRuleName, /* MR21 */
+ traceDepth);
+ };
+ }
+ };
+ traceGuessOptionValue=buf->traceGuessOptionValue;
+ traceCurrentRuleName=buf->traceCurrentRuleName;
+ traceDepth=buf->traceDepth;
+ traceGuessDone(buf);
+}
+
+/* Get the next symbol from the input stream; put it into lookahead buffer;
+ * fill token_type[] fast reference cache also. NLA is the next place where
+ * a lookahead ANTLRAbstractToken should go.
+ */
+void ANTLRParser::
+consume()
+{
+
+#ifdef ZZDEBUG_CONSUME_ACTION
+ zzdebug_consume_action();
+#endif
+
+// MR19 V.H. Simonis
+// Defer Fetch feature
+// Moves action of consume() into LA() function
+
+#ifdef ZZDEFER_FETCH
+ stillToFetch++;
+#else
+ NLA = inputTokens->getToken()->getType();
+ dirty--;
+ lap = (lap+1)&(LLk-1);
+#endif
+
+}
+
+_ANTLRTokenPtr ANTLRParser::
+LT(int i)
+{
+
+// MR19 V.H. Simonis
+// Defer Fetch feature
+// Moves action of consume() into LA() function
+
+#ifdef ZZDEFER_FETCH
+ undeferFetch();
+#endif
+
+#ifdef DEBUG_TOKENBUFFER
+ if ( i >= inputTokens->bufferSize() || inputTokens->minTokens() < LLk ) /* MR20 Was "<=" */
+ {
+ char buf[2000]; /* MR20 Was "static" */
+ sprintf(buf, "The minimum number of tokens you requested that the\nANTLRTokenBuffer buffer is not enough to satisfy your\nLT(%d) request; increase 'k' argument to constructor for ANTLRTokenBuffer\n", i);
+ panic(buf);
+ }
+#endif
+ return inputTokens->bufferedToken(i-LLk);
+}
+
+void
+ANTLRParser::
+look(int k)
+{
+ int i, c = k - (LLk-dirty);
+ for (i=1; i<=c; i++) consume();
+}
+
+/* fill the lookahead buffer up with k symbols (even if DEMAND_LOOK);
+ */
+void
+ANTLRParser::
+prime_lookahead()
+{
+ int i;
+ for(i=1;i<=LLk; i++) consume();
+ dirty=0;
+ // lap = 0; // MR14 Sinan Karasu (sinan.karasu@boeing.com)
+ // labase = 0; // MR14
+ labase=lap; // MR14
+}
+
+/* check to see if the current input symbol matches '_t'.
+ * During NON demand lookahead mode, dirty will always be 0 and
+ * hence the extra code for consuming tokens in _match is never
+ * executed; the same routine can be used for both modes.
+ */
+int ANTLRParser::
+_match(ANTLRTokenType _t, ANTLRChar **MissText,
+ ANTLRTokenType *MissTok, _ANTLRTokenPtr *BadTok,
+ SetWordType **MissSet)
+{
+ if ( dirty==LLk ) {
+ consume();
+ }
+ if ( LA(1)!=_t ) {
+ *MissText=NULL;
+ *MissTok= _t;
+ *BadTok = LT(1);
+ *MissSet=NULL;
+ return 0;
+ }
+ dirty++;
+ labase = (labase+1)&(LLk-1); // labase maintained even if !demand look
+ return 1;
+}
+
+/* check to see if the current input symbol matches '_t'.
+ * Used during exception handling.
+ */
+int ANTLRParser::
+_match_wsig(ANTLRTokenType _t)
+{
+ if ( dirty==LLk ) {
+ consume();
+ }
+ if ( LA(1)!=_t ) return 0;
+ dirty++;
+ labase = (labase+1)&(LLk-1); // labase maintained even if !demand look
+ return 1;
+}
+
+/* check to see if the current input symbol matches any token in a set.
+ * During NON demand lookahead mode, dirty will always be 0 and
+ * hence the extra code for consuming tokens in _match is never
+ * executed; the same routine can be used for both modes.
+ */
+int ANTLRParser::
+_setmatch(SetWordType *tset, ANTLRChar **MissText,
+ ANTLRTokenType *MissTok, _ANTLRTokenPtr *BadTok,
+ SetWordType **MissSet, SetWordType *tokclassErrset)
+{
+ if ( dirty==LLk ) {
+ consume();
+ }
+ if ( !set_el(LA(1), tset) ) {
+ *MissText=NULL; /* MR23 */
+ *MissTok=(ANTLRTokenType) 0; /* MR23 */
+ *BadTok=LT(1); /* MR23 */
+ *MissSet=tokclassErrset; /* MR23 */
+ return 0;
+ }
+ dirty++;
+ labase = (labase+1)&(LLk-1); // labase maintained even if !demand look
+ return 1;
+}
+
+int ANTLRParser::
+_setmatch_wsig(SetWordType *tset)
+{
+ if ( dirty==LLk ) {
+ consume();
+ }
+ if ( !set_el(LA(1), tset) ) return 0;
+ dirty++;
+ labase = (labase+1)&(LLk-1); // labase maintained even if !demand look
+ return 1;
+}
+
+ /* Exception handling routines */
+//
+// 7-Apr-97 133MR1
+// Change suggested by Eli Sternheim (eli@interhdl.com)
+//
+void ANTLRParser::
+consumeUntil(SetWordType *st)
+{
+ ANTLRTokenType tmp; // MR1
+ const int Eof=1; // MR1
+ while ( !set_el( (tmp=LA(1)), st) && tmp!=Eof) { consume(); } // MR1
+}
+
+//
+// 7-Apr-97 133MR1
+// Change suggested by Eli Sternheim (eli@interhdl.com)
+//
+void ANTLRParser::
+consumeUntilToken(int t)
+{
+ int tmp; // MR1
+ const int Eof=1; // MR1
+ while ( (tmp=LA(1)) !=t && tmp!=Eof) { consume(); } // MR1
+}
+
+
+ /* Old error stuff */
+
+void ANTLRParser::
+resynch(SetWordType *wd,SetWordType mask)
+{
+
+/* MR8 S.Bochnak@microtool.com.pl */
+/* MR8 Change file scope static "consumed" to instance var */
+
+ /* if you enter here without having consumed a token from last resynch
+ * force a token consumption.
+ */
+/* MR8 */ if ( !resynchConsumed ) {consume(); resynchConsumed=1; return;}
+
+ /* if current token is in resynch set, we've got what we wanted */
+
+/* MR8 */ if ( wd[LA(1)]&mask || LA(1) == eofToken ) {resynchConsumed=0; return;}
+
+ /* scan until we find something in the resynch set */
+
+ while ( !(wd[LA(1)]&mask) && LA(1) != eofToken ) {consume();}
+
+/* MR8 */ resynchConsumed=1;
+}
+
+/* standard error reporting function that assumes DLG-based scanners;
+ * you should redefine in subclass to change it or if you use your
+ * own scanner.
+ */
+
+/* MR23 THM There appears to be a parameter "badText" passed to syn()
+ which is not present in the parameter list. This may be
+ because in C mode there is no attribute function which
+ returns the text, so the text representation of the token
+ must be passed explicitly. I think.
+*/
+
+void ANTLRParser::
+syn(_ANTLRTokenPtr /*tok MR23*/, ANTLRChar *egroup, SetWordType *eset,
+ ANTLRTokenType etok, int k)
+{
+ int line;
+
+ line = LT(1)->getLine();
+
+ syntaxErrCount++; /* MR11 */
+
+ /* MR23 If the token is not an EOF token, then use the ->getText() value.
+
+ If the token is the EOF token the text returned by ->getText()
+ may be garbage. If the text from the token table is "@" use
+ "<eof>" instead, because end-users don't know what "@" means.
+ If the text is not "@" then use that text, which must have been
+ supplied by the grammar writer.
+ */
+ const char * errorAt = LT(1)->getText();
+ if (LA(1) == eofToken) {
+ errorAt = parserTokenName(LA(1));
+ if (errorAt[0] == '@') errorAt = "<eof>";
+ }
+ /* MR23 */ printMessage(stderr, "line %d: syntax error at \"%s\"",
+ line, errorAt);
+ if ( !etok && !eset ) {/* MR23 */ printMessage(stderr, "\n"); return;}
+ if ( k==1 ) /* MR23 */ printMessage(stderr, " missing");
+ else
+ {
+ /* MR23 */ printMessage(stderr, "; \"%s\" not", LT(k)->getText()); // MR23 use LT(k) since k>1
+ if ( set_deg(eset)>1 ) /* MR23 */ printMessage(stderr, " in");
+ }
+ if ( set_deg(eset)>0 ) edecode(eset);
+ else /* MR23 */ printMessage(stderr, " %s", token_tbl[etok]);
+ if ( strlen(egroup) > 0 ) /* MR23 */ printMessage(stderr, " in %s", egroup);
+ /* MR23 */ printMessage(stderr, "\n");
+}
+
+/* is b an element of set p? */
+int ANTLRParser::
+set_el(ANTLRTokenType b, SetWordType *p)
+{
+ return( p[DIVWORD(b)] & bitmask[MODWORD(b)] );
+}
+
+int ANTLRParser::
+set_deg(SetWordType *a)
+{
+ /* Fast compute degree of a set... the number
+ of elements present in the set. Assumes
+ that all word bits are used in the set
+ */
+ register SetWordType *p = a;
+ register SetWordType *endp = &(a[bsetsize]);
+ register int degree = 0;
+
+ if ( a == NULL ) return 0;
+ while ( p < endp )
+ {
+ register SetWordType t = *p;
+ register SetWordType *b = &(bitmask[0]);
+ do {
+ if (t & *b) ++degree;
+ } while (++b < &(bitmask[sizeof(SetWordType)*8]));
+ p++;
+ }
+
+ return(degree);
+}
+
+void ANTLRParser::
+edecode(SetWordType *a)
+{
+ register SetWordType *p = a;
+ register SetWordType *endp = &(p[bsetsize]);
+ register unsigned e = 0;
+
+ if ( set_deg(a)>1 ) /* MR23 */ printMessage(stderr, " {");
+ do {
+ register SetWordType t = *p;
+ register SetWordType *b = &(bitmask[0]);
+ do {
+ if ( t & *b ) /* MR23 */ printMessage(stderr, " %s", token_tbl[e]);
+ e++;
+ } while (++b < &(bitmask[sizeof(SetWordType)*8]));
+ } while (++p < endp);
+ if ( set_deg(a)>1 ) /* MR23 */ printMessage(stderr, " }");
+}
+
+/* input looks like:
+ * zzFAIL(k, e1, e2, ...,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk)
+ * where the zzMiss stuff is set here to the token that did not match
+ * (and which set wasn't it a member of).
+ */
+
+// MR9 29-Sep-97 Stan Bochnak (S.Bochnak@microTool.com.pl)
+// MR9 Original fix to static allocated text didn't
+// MR9 work because a pointer to it was passed back
+// MR9 to caller. Replace with instance variable.
+
+const int SETWORDCOUNT=20;
+
+void
+ANTLRParser::FAIL(int k, ...)
+{
+//
+// MR1 10-Apr-97
+//
+
+ if (zzFAILtext == NULL) zzFAILtext=new char [1000]; // MR9
+ SetWordType **f=new SetWordType *[SETWORDCOUNT]; // MR1 // MR9
+ SetWordType **miss_set;
+ ANTLRChar **miss_text;
+ _ANTLRTokenPtr *bad_tok;
+ ANTLRChar **bad_text;
+//
+// 7-Apr-97 133MR1
+// err_k is passed as a "int *", not "unsigned *"
+//
+ int *err_k; // MR1
+ int i;
+ va_list ap;
+
+ va_start(ap, k);
+
+ zzFAILtext[0] = '\0';
+ if ( k > SETWORDCOUNT ) panic("FAIL: overflowed buffer");
+ for (i=1; i<=k; i++) /* collect all lookahead sets */
+ {
+ f[i-1] = va_arg(ap, SetWordType *);
+ }
+ for (i=1; i<=k; i++) /* look for offending token */
+ {
+ if ( i>1 ) strcat(zzFAILtext, " ");
+ strcat(zzFAILtext, LT(i)->getText());
+ if ( !set_el(LA(i), f[i-1]) ) break;
+ }
+ miss_set = va_arg(ap, SetWordType **);
+ miss_text = va_arg(ap, ANTLRChar **);
+ bad_tok = va_arg(ap, _ANTLRTokenPtr *);
+ bad_text = va_arg(ap, ANTLRChar **);
+ err_k = va_arg(ap, int *); // MR1
+ if ( i>k )
+ {
+ /* bad; lookahead is permutation that cannot be matched,
+ * but, the ith token of lookahead is valid at the ith position
+ * (The old LL sub 1 (k) versus LL(k) parsing technique)
+ */
+ *miss_set = NULL;
+ *miss_text = LT(1)->getText();
+ *bad_tok = LT(1);
+ *bad_text = (*bad_tok)->getText();
+ *err_k = k;
+//
+// MR4 20-May-97 erroneously deleted contents of f[]
+// MR4 reported by Bruce Guenter (bruceg@qcc.sk.ca)
+// MR1 10-Apr-97 release temporary storage
+//
+ delete [] f; // MR1
+ return; // MR1
+ }
+/* MR23 printMessage(stderr, "%s not in %dth set\n", zztokens[LA(i)], i);*/
+ *miss_set = f[i-1];
+ *miss_text = zzFAILtext;
+ *bad_tok = LT(i);
+ *bad_text = (*bad_tok)->getText();
+ if ( i==1 ) *err_k = 1;
+ else *err_k = k;
+//
+// MR4 20-May-97 erroneously deleted contents of f[]
+// MR4 reported by Bruce Guenter (bruceg@qcc.sk.ca)
+// MR1 10-Apr-97 release temporary storage
+//
+ delete [] f; // MR1
+ return; // MR1
+}
+
+int ANTLRParser::
+_match_wdfltsig(ANTLRTokenType tokenWanted, SetWordType *whatFollows)
+{
+ if ( dirty==LLk ) consume();
+
+ if ( LA(1)!=tokenWanted )
+ {
+ syntaxErrCount++; /* MR11 */
+ /* MR23 */ printMessage(stderr,
+ "line %d: syntax error at \"%s\" missing %s\n",
+ LT(1)->getLine(),
+ (LA(1)==eofToken && LT(1)->getText()[0] == '@')?"<eof>":LT(1)->getText(), /* MR21a */
+ token_tbl[tokenWanted]);
+ consumeUntil( whatFollows );
+ return 0;
+ }
+ else {
+ dirty++;
+ labase = (labase+1)&(LLk-1); // labase maintained even if !demand look
+/* if ( !demand_look ) consume(); */
+ return 1;
+ }
+}
+
+
+int ANTLRParser::
+_setmatch_wdfltsig(SetWordType *tokensWanted,
+ ANTLRTokenType tokenTypeOfSet,
+ SetWordType *whatFollows)
+{
+ if ( dirty==LLk ) consume();
+ if ( !set_el(LA(1), tokensWanted) )
+ {
+ syntaxErrCount++; /* MR11 */
+ /* MR23 */ printMessage(stderr,
+ "line %d: syntax error at \"%s\" missing %s\n",
+ LT(1)->getLine(),
+ (LA(1)==eofToken && LT(1)->getText()[0] == '@')?"<eof>":LT(1)->getText(), /* MR21a */
+ token_tbl[tokenTypeOfSet]);
+ consumeUntil( whatFollows );
+ return 0;
+ }
+ else {
+ dirty++;
+ labase = (labase+1)&(LLk-1); // labase maintained even if !demand look
+/* if ( !demand_look ) consume(); */
+ return 1;
+ }
+}
+
+char *ANTLRParser::
+eMsgd(char *err,int d)
+{
+ sprintf(eMsgBuffer, err, d); // dangerous, but I don't care
+ return eMsgBuffer;
+}
+
+char *ANTLRParser::
+eMsg(char *err, char *s)
+{
+ sprintf(eMsgBuffer, err, s);
+ return eMsgBuffer;
+}
+
+char *ANTLRParser::
+eMsg2(char *err,char *s, char *t)
+{
+ sprintf(eMsgBuffer, err, s, t);
+ return eMsgBuffer;
+}
+
+void ANTLRParser::
+panic(const char *msg) // MR20 const
+{
+ /* MR23 */ printMessage(stderr, "ANTLR panic: %s\n", msg);
+ exit(PCCTS_EXIT_FAILURE); // MR1
+}
+
+const ANTLRChar *ANTLRParser:: // MR1
+parserTokenName(int tok) { // MR1
+ return token_tbl[tok]; // MR1
+} // MR1
+
+void ANTLRParser::traceGuessDone(const ANTLRParserState *state) {
+
+ int doIt=0;
+
+ if (traceCurrentRuleName == NULL) return;
+
+ if (traceOptionValue <= 0) {
+ doIt=0;
+ } else if (traceGuessOptionValue <= 0) {
+ doIt=0;
+ } else {
+ doIt=1;
+ };
+
+ if (doIt) {
+ /* MR23 */ printMessage(stderr,"guess done - returning to rule %s {\"%s\"} at depth %d",
+ state->traceCurrentRuleName,
+ LT(1)->getType() == eofToken ? "@" : LT(1)->getText(),
+ state->traceDepth);
+ if (state->guessing != 0) {
+ /* MR23 */ printMessage(stderr," (guess mode continues - an enclosing guess is still active)");
+ } else {
+ /* MR23 */ printMessage(stderr," (guess mode ends)");
+ };
+ /* MR23 */ printMessage(stderr,"\n");
+ };
+}
+
+void ANTLRParser::traceGuessFail() {
+
+ int doIt=0;
+
+ if (traceCurrentRuleName == NULL) return; /* MR21 */
+
+ if (traceOptionValue <= 0) {
+ doIt=0;
+ } else if (guessing && traceGuessOptionValue <= 0) {
+ doIt=0;
+ } else {
+ doIt=1;
+ };
+
+ if (doIt) {
+ /* MR23 */ printMessage(stderr,"guess failed in %s\n",traceCurrentRuleName);
+ };
+}
+
+/* traceOption:
+ zero value turns off trace
+*/
+
+void ANTLRParser::tracein(const ANTLRChar * rule) {
+
+ int doIt=0;
+
+ traceDepth++;
+ traceCurrentRuleName=rule;
+
+ if (traceOptionValue <= 0) {
+ doIt=0;
+ } else if (guessing && traceGuessOptionValue <= 0) {
+ doIt=0;
+ } else {
+ doIt=1;
+ };
+
+ if (doIt) {
+ /* MR23 */ printMessage(stderr,"enter rule %s {\"%s\"} depth %d",
+ rule,
+ LT(1)->getType() == eofToken ? "@" : LT(1)->getText(),
+ traceDepth);
+ if (guessing) /* MR23 */ printMessage(stderr," guessing");
+ /* MR23 */ printMessage(stderr,"\n");
+ };
+ return;
+}
+
+void ANTLRParser::traceout(const ANTLRChar * rule) {
+
+ int doIt=0;
+
+ traceDepth--;
+
+ if (traceOptionValue <= 0) {
+ doIt=0;
+ } else if (guessing && traceGuessOptionValue <= 0) {
+ doIt=0;
+ } else {
+ doIt=1;
+ };
+
+ if (doIt) {
+ /* MR23 */ printMessage(stderr,"exit rule %s {\"%s\"} depth %d",
+ rule,
+ LT(1)->getType() == eofToken ? "@" : LT(1)->getText(),
+ traceDepth+1);
+ if (guessing) /* MR23 */ printMessage(stderr," guessing");
+ /* MR23 */ printMessage(stderr,"\n");
+ };
+}
+
+int ANTLRParser::traceOption(int delta) {
+
+ int prevValue=traceOptionValue;
+
+ traceOptionValue=traceOptionValue+delta;
+
+ if (traceCurrentRuleName != NULL) {
+ if (prevValue <= 0 && traceOptionValue > 0) {
+ /* MR23 */ printMessage(stderr,"trace enabled in rule %s depth %d\n",traceCurrentRuleName,traceDepth);
+ };
+ if (prevValue > 0 && traceOptionValue <= 0) {
+ /* MR23 */ printMessage(stderr,"trace disabled in rule %s depth %d\n",traceCurrentRuleName,traceDepth);
+ };
+ };
+
+ return prevValue;
+}
+
+int ANTLRParser::traceGuessOption(int delta) {
+
+ int prevValue=traceGuessOptionValue;
+
+ traceGuessOptionValue=traceGuessOptionValue+delta;
+
+ if (traceCurrentRuleName != NULL) {
+ if (prevValue <= 0 && traceGuessOptionValue > 0) {
+ /* MR23 */ printMessage(stderr,"guess trace enabled in rule %s depth %d\n",traceCurrentRuleName,traceDepth);
+ };
+ if (prevValue > 0 && traceGuessOptionValue <= 0) {
+ /* MR23 */ printMessage(stderr,"guess trace disabled in rule %s depth %d\n",traceCurrentRuleName,traceDepth);
+ };
+ };
+ return prevValue;
+}
+
+// MR19 V.H. Simonis Defer Fetch feature
+
+void ANTLRParser::undeferFetch()
+{
+
+#ifdef ZZDEFER_FETCH
+ if (stillToFetch) {
+ for (int stillToFetch_x = 0; stillToFetch_x < stillToFetch; ++stillToFetch_x) {
+ NLA = inputTokens->getToken()->getType();
+ dirty--;
+ lap = (lap+1)&(LLk-1);
+ }
+ stillToFetch = 0;
+ }
+#else
+ return;
+#endif
+
+}
+
+int ANTLRParser::isDeferFetchEnabled()
+{
+#ifdef ZZDEFER_FETCH
+ return 1;
+#else
+ return 0;
+#endif
+}
+
+//MR23
+int ANTLRParser::printMessage(FILE* pFile, const char* pFormat, ...)
+{
+ va_list marker;
+ va_start( marker, pFormat );
+ int iRet = printMessageV(pFile, pFormat, marker);
+ va_end( marker );
+ return iRet;
+}
+
+int ANTLRParser::printMessageV(FILE* pFile, const char* pFormat, va_list arglist) // MR23
+{
+ return vfprintf(pFile, pFormat, arglist);
+}
+
+// MR23 Move semantic predicate error handling from macro to virtual function
+//
+// Called by the zzfailed_pred
+
+void ANTLRParser::failedSemanticPredicate(const char* predicate)
+{
+ printMessage(stdout,"line %d: semantic error; failed predicate: '%s'\n",
+ LT(1)->getLine(), predicate);
+}
diff --git a/Source/Pccts/h/AParser.h b/Source/Pccts/h/AParser.h
new file mode 100644
index 0000000..fe405f4
--- /dev/null
+++ b/Source/Pccts/h/AParser.h
@@ -0,0 +1,376 @@
+/* ANTLRParser.h
+ *
+ * Define the generic ANTLRParser superclass, which is subclassed to
+ * define an actual parser.
+ *
+ * Before entry into this file: ANTLRTokenType must be set.
+ *
+ * SOFTWARE RIGHTS
+ *
+ * We reserve no LEGAL rights to the Purdue Compiler Construction Tool
+ * Set (PCCTS) -- PCCTS is in the public domain. An individual or
+ * company may do whatever they wish with source code distributed with
+ * PCCTS or the code generated by PCCTS, including the incorporation of
+ * PCCTS, or its output, into commerical software.
+ *
+ * We encourage users to develop software with PCCTS. However, we do ask
+ * that credit is given to us for developing PCCTS. By "credit",
+ * we mean that if you incorporate our source code into one of your
+ * programs (commercial product, research project, or otherwise) that you
+ * acknowledge this fact somewhere in the documentation, research report,
+ * etc... If you like PCCTS and have developed a nice tool with the
+ * output, please mention that you developed it using PCCTS. In
+ * addition, we ask that this header remain intact in our source code.
+ * As long as these guidelines are kept, we expect to continue enhancing
+ * this system and expect to make other tools available as they are
+ * completed.
+ *
+ * ANTLR 1.33
+ * Terence Parr
+ * Parr Research Corporation
+ * with Purdue University and AHPCRC, University of Minnesota
+ * 1989-2000
+ */
+
+#ifndef APARSER_H_GATE
+#define APARSER_H_GATE
+
+#include "pcctscfg.h"
+
+#include "pccts_stdio.h"
+#include "pccts_setjmp.h"
+
+PCCTS_NAMESPACE_STD
+
+#include ATOKEN_H
+#include ATOKENBUFFER_H
+
+#ifdef ZZCAN_GUESS
+#ifndef ZZINF_LOOK
+#define ZZINF_LOOK
+#endif
+#endif
+
+
+#define NLA (token_type[lap&(LLk-1)])/* --> next LA */
+
+typedef unsigned char SetWordType;
+
+/* Define external bit set stuff (for SetWordType) */
+#define EXT_WORDSIZE (sizeof(char)*8)
+#define EXT_LOGWORDSIZE 3
+
+ /* s y n t a c t i c p r e d i c a t e s t u f f */
+
+#ifndef zzUSER_GUESS_HOOK
+#define zzUSER_GUESS_HOOK(seqFrozen,zzrv)
+#endif
+
+#ifndef zzUSER_GUESS_DONE_HOOK
+#define zzUSER_GUESS_DONE_HOOK(seqFrozen)
+#endif
+
+/* MR14 Add zzUSER_GUESS_FAIL_HOOK and related code */
+
+#define zzUSER_GUESS_FAIL_HOOK_INTERNAL zzUSER_GUESS_FAIL_HOOK(SeqFrozen)
+#ifndef zzUSER_GUESS_FAIL_HOOK
+#define zzUSER_GUESS_FAIL_HOOK(zzGuessSeq)
+#endif
+
+
+typedef struct _zzjmp_buf {
+ jmp_buf state;
+ } zzjmp_buf;
+
+/* these need to be macros not member functions */
+#define zzGUESS_BLOCK ANTLRParserState zzst; int zzrv; int _marker; int zzGuessSeqFrozen;
+#define zzNON_GUESS_MODE if ( !guessing )
+#define zzGUESS_FAIL guess_fail();
+
+/* Note: zzGUESS_DONE does not execute longjmp() */
+
+#define zzGUESS_DONE {zzrv=1; inputTokens->rewind(_marker); guess_done(&zzst);zzUSER_GUESS_DONE_HOOK(zzGuessSeqFrozen) }
+#define zzGUESS saveState(&zzst); \
+ guessing = 1; \
+ zzGuessSeqFrozen = ++zzGuessSeq; \
+ _marker = inputTokens->mark(); \
+ zzrv = setjmp(guess_start.state); \
+ zzUSER_GUESS_HOOK(zzGuessSeqFrozen,zzrv) \
+ if ( zzrv ) zzGUESS_DONE
+
+#define zzTRACEdata const ANTLRChar *zzTracePrevRuleName = NULL;
+
+#ifndef zzTRACEIN
+#define zzTRACEIN(r) zzTracePrevRuleName=traceCurrentRuleName;tracein(r);
+#endif
+#ifndef zzTRACEOUT
+#define zzTRACEOUT(r) traceout(r);traceCurrentRuleName=zzTracePrevRuleName;
+#endif
+
+ /* a n t l r p a r s e r d e f */
+
+struct ANTLRParserState {
+ /* class variables */
+ zzjmp_buf guess_start;
+ int guessing;
+
+ int inf_labase;
+ int inf_last;
+
+ int dirty;
+
+ int traceOptionValue; // MR10
+ int traceGuessOptionValue; // MR10
+ const ANTLRChar *traceCurrentRuleName; // MR10
+ int traceDepth; // MR10
+
+};
+
+/* notes:
+ *
+ * multiple inheritance is a cool way to include what stuff is needed
+ * in this structure (like guess stuff). however, i'm not convinced that
+ * multiple inheritance works correctly on all platforms. not that
+ * much space is used--just include all possibly useful members.
+ *
+ * the class should also be a template with arguments for the lookahead
+ * depth and so on. that way, more than one parser can be defined (as
+ * each will probably have different lookahead requirements). however,
+ * am i sure that templates work? no, i'm not sure.
+ *
+ * no attributes are maintained and, hence, the 'asp' variable is not
+ * needed. $i can still be referenced, but it refers to the token
+ * associated with that rule element. question: where are the token's
+ * stored if not on the software stack? in local variables created
+ * and assigned to by antlr.
+ */
+class ANTLRParser {
+protected:
+ /* class variables */
+ static SetWordType bitmask[sizeof(SetWordType)*8];
+ static char eMsgBuffer[500];
+
+protected:
+ int LLk; // number of lookahead symbols (old LL_K)
+ int demand_look;
+ ANTLRTokenType eofToken; // when do I stop during resynch()s
+ int bsetsize; // size of bitsets created by ANTLR in
+ // units of SetWordType
+
+ ANTLRTokenBuffer *inputTokens; //place to get input tokens
+
+ zzjmp_buf guess_start; // where to jump back to upon failure
+ int guessing; // if guessing (using (...)? predicate)
+
+ // infinite lookahead stuff
+ int can_use_inf_look; // set by subclass (generated by ANTLR)
+ int inf_lap;
+ int inf_labase;
+ int inf_last;
+ int *_inf_line;
+
+ const ANTLRChar **token_tbl; // pointer to table of token type strings MR20 const
+
+ int dirty; // used during demand lookahead
+
+ ANTLRTokenType *token_type; // fast reference cache of token.getType()
+// ANTLRLightweightToken **token; // the token with all its attributes
+ int lap;
+ int labase;
+#ifdef ZZDEFER_FETCH
+ int stillToFetch; // MR19 V.H. Simonis
+#endif
+
+private:
+ void fill_inf_look();
+
+protected:
+ virtual void guess_fail() { // MR9 27-Sep-97 make virtual
+ traceGuessFail(); // MR10
+ longjmp(guess_start.state, 1); } // MR9
+ virtual void guess_done(ANTLRParserState *st) { // MR9 27-Sep-97 make virtual
+ restoreState(st); } // MR9
+ virtual int guess(ANTLRParserState *); // MR9 27-Sep-97 make virtual
+ void look(int);
+ int _match(ANTLRTokenType, ANTLRChar **, ANTLRTokenType *,
+ _ANTLRTokenPtr *, SetWordType **);
+ int _setmatch(SetWordType *, ANTLRChar **, ANTLRTokenType *,
+ _ANTLRTokenPtr *, SetWordType **,
+ SetWordType * tokclassErrset /* MR23 */);
+ int _match_wsig(ANTLRTokenType);
+ int _setmatch_wsig(SetWordType *);
+ virtual void consume();
+ virtual void resynch(SetWordType *wd,SetWordType mask); // MR21
+ void prime_lookahead();
+ virtual void tracein(const ANTLRChar *r); // MR10
+ virtual void traceout(const ANTLRChar *r); // MR10
+ static unsigned MODWORD(unsigned x) {return x & (EXT_WORDSIZE-1);} // x % EXT_WORDSIZE // MR9
+ static unsigned DIVWORD(unsigned x) {return x >> EXT_LOGWORDSIZE;} // x / EXT_WORDSIZE // MR9
+ int set_deg(SetWordType *);
+ int set_el(ANTLRTokenType, SetWordType *);
+ virtual void edecode(SetWordType *); // MR1
+ virtual void FAIL(int k, ...); // MR1
+ int traceOptionValue; // MR10
+ int traceGuessOptionValue; // MR10
+ const ANTLRChar *traceCurrentRuleName; // MR10
+ int traceDepth; // MR10
+ void traceReset(); // MR10
+ virtual void traceGuessFail(); // MR10
+ virtual void traceGuessDone(const ANTLRParserState *); // MR10
+ int zzGuessSeq; // MR10
+
+public:
+ ANTLRParser(ANTLRTokenBuffer *,
+ int k=1,
+ int use_inf_look=0,
+ int demand_look=0,
+ int bsetsize=1);
+ virtual ~ANTLRParser();
+
+ virtual void init();
+
+ ANTLRTokenType LA(int i)
+ {
+//
+// MR14 demand look will always be 0 for C++ mode
+//
+//// return demand_look ? token_type[(labase+(i)-1)&(LLk-1)] :
+//// token_type[(lap+(i)-1)&(LLk-1)];
+
+// MR19 V.H. Simonis Defer fetch feature
+
+#ifdef ZZDEFER_FETCH
+ undeferFetch();
+#endif
+ return token_type[(lap+(i)-1)&(LLk-1)];
+ }
+ _ANTLRTokenPtr LT(int i);
+
+ void setEofToken(ANTLRTokenType t) { eofToken = t; }
+ ANTLRTokenType getEofToken() const { return eofToken; } // MR14
+
+ void noGarbageCollectTokens() { inputTokens->noGarbageCollectTokens(); }
+ void garbageCollectTokens() { inputTokens->garbageCollectTokens(); }
+
+ virtual void syn(_ANTLRTokenPtr tok, ANTLRChar *egroup,
+ SetWordType *eset, ANTLRTokenType etok, int k);
+ virtual void saveState(ANTLRParserState *); // MR9 27-Sep-97 make virtual
+ virtual void restoreState(ANTLRParserState *); // MR9 27-Sep-97 make virtual
+
+ virtual void panic(const char *msg); // MR20 const
+
+ static char *eMsgd(char *,int);
+ static char *eMsg(char *,char *);
+ static char *eMsg2(char *,char *,char *);
+
+ virtual int printMessage(FILE* pFile, const char* pFormat, ...); // MR23
+ virtual int printMessageV(FILE* pFile, const char* pFormat, va_list arglist); // MR23
+
+ void consumeUntil(SetWordType *st);
+ void consumeUntilToken(int t);
+
+ virtual int _setmatch_wdfltsig(SetWordType *tokensWanted,
+ ANTLRTokenType tokenTypeOfSet,
+ SetWordType *whatFollows);
+ virtual int _match_wdfltsig(ANTLRTokenType tokenWanted,
+ SetWordType *whatFollows);
+
+ const ANTLRChar * parserTokenName(int tok); // MR1
+
+ int traceOptionValueDefault; // MR11
+ int traceOption(int delta); // MR11
+ int traceGuessOption(int delta); // MR11
+
+// MR8 5-Aug-97 S.Bochnak@microtool.com.pl
+// MR8 Move resynch static local variable
+// MR8 to class instance
+
+ int syntaxErrCount; // MR12
+ ANTLRTokenStream *getLexer() const { // MR12
+ return inputTokens ? inputTokens->getLexer() : 0; } // MR12
+protected: // MR8
+ int resynchConsumed; // MR8
+ char *zzFAILtext; // workarea required by zzFAIL // MR9
+ void undeferFetch(); // MR19 V.H. Simonis
+ int isDeferFetchEnabled(); // MR19 V.H. Simonis
+ virtual void failedSemanticPredicate(const char* predicate); /* MR23 */
+};
+
+#define zzmatch(_t) \
+ if ( !_match((ANTLRTokenType)_t, &zzMissText, &zzMissTok, \
+ (_ANTLRTokenPtr *) &zzBadTok, &zzMissSet) ) goto fail;
+
+#define zzmatch_wsig(_t,handler) \
+ if ( !_match_wsig((ANTLRTokenType)_t) ) if ( guessing ) zzGUESS_FAIL else {_signal=MismatchedToken; goto handler;}
+
+#define zzsetmatch(_ts,_tokclassErrset) \
+ if ( !_setmatch(_ts, &zzMissText, &zzMissTok, \
+ (_ANTLRTokenPtr *) &zzBadTok, &zzMissSet, _tokclassErrset) ) goto fail;
+
+#define zzsetmatch_wsig(_ts, handler) \
+ if ( !_setmatch_wsig(_ts) ) if ( guessing ) zzGUESS_FAIL else {_signal=MismatchedToken; goto handler;}
+
+/* For the dflt signal matchers, a FALSE indicates that an error occurred
+ * just like the other matchers, but in this case, the routine has already
+ * recovered--we do NOT want to consume another token. However, when
+ * the match was successful, we do want to consume hence _signal=0 so that
+ * a token is consumed by the "if (!_signal) consume(); _signal=NoSignal;"
+ * preamble.
+ */
+#define zzsetmatch_wdfltsig(tokensWanted, tokenTypeOfSet, whatFollows) \
+ if ( !_setmatch_wdfltsig(tokensWanted, tokenTypeOfSet, whatFollows) ) \
+ _signal = MismatchedToken;
+
+#define zzmatch_wdfltsig(tokenWanted, whatFollows) \
+ if ( !_match_wdfltsig(tokenWanted, whatFollows) ) _signal = MismatchedToken;
+
+
+// MR1 10-Apr-97 zzfailed_pred() macro does not backtrack in guess mode.
+// MR1 Identification and correction due to J. Lilley
+//
+// MR23 Call virtual method to report error.
+// MR23 Provide more control over failed predicate action
+// without any need for user to worry about guessing internals.
+
+#ifndef zzfailed_pred
+#define zzfailed_pred(_p,_hasuseraction,_useraction) \
+ if (guessing) { \
+ zzGUESS_FAIL; \
+ } else { \
+ zzfailed_pred_action(_p,_hasuseraction,_useraction) \
+ }
+#endif
+
+// MR23 Provide more control over failed predicate action
+// without any need for user to worry about guessing internals.
+// _hasuseraction == 0 => no user specified error action
+// _hasuseraction == 1 => user specified error action
+
+#ifndef zzfailed_pred_action
+#define zzfailed_pred_action(_p,_hasuseraction,_useraction) \
+ if (_hasuseraction) { _useraction } else { failedSemanticPredicate(_p); }
+#endif
+
+#define zzRULE \
+ SetWordType *zzMissSet=NULL; ANTLRTokenType zzMissTok=(ANTLRTokenType)0; \
+ _ANTLRTokenPtr zzBadTok=NULL; ANTLRChar *zzBadText=(ANTLRChar *)""; \
+ int zzErrk=1,zzpf=0; \
+ zzTRACEdata \
+ ANTLRChar *zzMissText=(ANTLRChar *)"";
+
+#endif
+
+ /* S t a n d a r d E x c e p t i o n S i g n a l s */
+
+#define NoSignal 0
+#define MismatchedToken 1
+#define NoViableAlt 2
+#define NoSemViableAlt 3
+
+/* MR7 Allow more control over signalling */
+/* by adding "Unwind" and "SetSignal" */
+
+#define Unwind 4
+#define setSignal(newValue) *_retsignal=_signal=(newValue)
+#define suppressSignal *_retsignal=_signal=0
+#define exportSignal *_retsignal=_signal
diff --git a/Source/Pccts/h/ASTBase.cpp b/Source/Pccts/h/ASTBase.cpp
new file mode 100644
index 0000000..a94f080
--- /dev/null
+++ b/Source/Pccts/h/ASTBase.cpp
@@ -0,0 +1,256 @@
+/* Abstract syntax tree manipulation functions
+ *
+ * SOFTWARE RIGHTS
+ *
+ * We reserve no LEGAL rights to the Purdue Compiler Construction Tool
+ * Set (PCCTS) -- PCCTS is in the public domain. An individual or
+ * company may do whatever they wish with source code distributed with
+ * PCCTS or the code generated by PCCTS, including the incorporation of
+ * PCCTS, or its output, into commerical software.
+ *
+ * We encourage users to develop software with PCCTS. However, we do ask
+ * that credit is given to us for developing PCCTS. By "credit",
+ * we mean that if you incorporate our source code into one of your
+ * programs (commercial product, research project, or otherwise) that you
+ * acknowledge this fact somewhere in the documentation, research report,
+ * etc... If you like PCCTS and have developed a nice tool with the
+ * output, please mention that you developed it using PCCTS. In
+ * addition, we ask that this header remain intact in our source code.
+ * As long as these guidelines are kept, we expect to continue enhancing
+ * this system and expect to make other tools available as they are
+ * completed.
+ *
+ * ANTLR 1.33
+ * Terence Parr
+ * Parr Research Corporation
+ * with Purdue University and AHPCRC, University of Minnesota
+ * 1989-2000
+ */
+
+#include "pcctscfg.h"
+
+#include "pccts_stdio.h"
+#include "pccts_stdarg.h"
+
+PCCTS_NAMESPACE_STD
+
+#define ANTLR_SUPPORT_CODE
+
+#include "ASTBase.h"
+
+/* ensure that tree manipulation variables are current after a rule
+ * reference
+ */
+void
+ASTBase::link(ASTBase **_root, ASTBase **_sibling, ASTBase **_tail)
+{
+ if ( *_sibling == NULL ) return;
+ if ( *_root == NULL ) *_root = *_sibling;
+ else if ( *_root != *_sibling ) (*_root)->_down = *_sibling;
+ if ( *_tail==NULL ) *_tail = *_sibling;
+ while ( (*_tail)->_right != NULL ) *_tail = (*_tail)->_right;
+}
+
+/* add a child node to the current sibling list */
+void
+ASTBase::subchild(ASTBase **_root, ASTBase **_sibling, ASTBase **_tail)
+{
+ if ( *_tail != NULL ) (*_tail)->_right = this;
+ else {
+ *_sibling = this;
+ if ( *_root != NULL ) (*_root)->_down = *_sibling;
+ }
+ *_tail = this;
+ if ( *_root == NULL ) *_root = *_sibling;
+}
+
+/* make a new AST node. Make the newly-created
+ * node the root for the current sibling list. If a root node already
+ * exists, make the newly-created node the root of the current root.
+ */
+void
+ASTBase::subroot(ASTBase **_root, ASTBase **_sibling, ASTBase **_tail)
+{
+ if ( *_root != NULL )
+ if ( (*_root)->_down == *_sibling ) *_sibling = *_tail = *_root;
+ *_root = this;
+ (*_root)->_down = *_sibling;
+}
+
+/* Apply preorder_action(), etc.. to root then each sibling */
+//
+// 7-Apr-97 133MR1
+// Fix suggested by Ron House (house@helios.usq.edu.au)
+//
+void
+ASTBase::preorder(void* pData /*= NULL*/ /* MR23 */)
+{
+ ASTBase *tree = this;
+
+ while ( tree!= NULL )
+ {
+ if ( tree->_down != NULL ) {
+ tree->preorder_before_action(pData); // MR1
+ };
+ tree->preorder_action(pData);
+ if ( tree->_down!=NULL )
+ {
+ tree->_down->preorder(pData);
+ tree->preorder_after_action(pData); // MR1
+ }
+ tree = tree->_right;
+ }
+}
+
+/* free all AST nodes in tree; apply func to each before freeing */
+void
+ASTBase::destroy()
+{
+ ASTBase* tree = this;
+ while (tree) {
+ if (tree->_down) tree->_down->destroy();
+
+ ASTBase* cur = tree;
+ tree = tree->_right;
+ delete cur;
+ }
+}
+
+/* build a tree (root child1 child2 ... NULL)
+ * If root is NULL, simply make the children siblings and return ptr
+ * to 1st sibling (child1). If root is not single node, return NULL.
+ *
+ * Siblings that are actually siblins lists themselves are handled
+ * correctly. For example #( NULL, #( NULL, A, B, C), D) results
+ * in the tree ( NULL A B C D ).
+ *
+ * Requires at least two parameters with the last one being NULL. If
+ * both are NULL, return NULL.
+ */
+ASTBase *
+ASTBase::tmake(ASTBase *root, ...)
+{
+ va_list ap;
+ register ASTBase *child, *sibling=NULL, *tail=NULL /*MR23*/, *w;
+
+ va_start(ap, root);
+
+ if ( root != NULL )
+ if ( root->_down != NULL ) {
+ root->reportOverwriteOfDownPointer(); /* MR21 Report problem which almost always an error */
+ return NULL;
+ }
+ child = va_arg(ap, ASTBase *);
+ while ( child != NULL )
+ {
+ for (w=child; w->_right!=NULL; w=w->_right) {;} /* find end of child */
+ if ( sibling == NULL ) {sibling = child; tail = w;}
+ else {tail->_right = child; tail = w;}
+ child = va_arg(ap, ASTBase *);
+ }
+ if ( root==NULL ) root = sibling;
+ else root->_down = sibling;
+ va_end(ap);
+ return root;
+}
+
+#ifndef PCCTS_NOT_USING_SOR
+
+/* tree duplicate */
+// forgot to check for NULL this (TJP July 23,1995)
+ASTBase *
+ASTBase::dup()
+{
+ ASTBase *u, *t=this;
+
+ if ( t == NULL ) return NULL;
+/*
+ u = new ASTBase;
+ *u = *t;
+*/
+ u = (ASTBase *)this->shallowCopy();
+ if ( t->_right!=NULL ) u->_right = t->_right->dup();
+ else u->_right = NULL;
+ if ( t->_down!=NULL ) u->_down = t->_down->dup();
+ else u->_down = NULL;
+ return u;
+}
+#endif
+
+//
+// 7-Apr-97 133MR1
+// Fix suggested by Asgeir Olafsson (olafsson@cstar.ac.com)
+//
+/* tree duplicate */
+
+#ifndef PCCTS_NOT_USING_SOR
+
+ASTBase *
+ASTDoublyLinkedBase::dup()
+{
+ ASTDoublyLinkedBase *u, *t=this;
+
+ if ( t == NULL ) return NULL;
+ u = (ASTDoublyLinkedBase *)this->shallowCopy();
+ u->_up = NULL; /* set by calling invocation */
+ u->_left = NULL;
+ if (t->_right!=NULL) { // MR1
+ u->_right=t->_right->dup(); // MR1
+ ((ASTDoublyLinkedBase *)u->_right)->_left = u; // MR1
+ } else { // MR1
+ u->_right = NULL; // MR1
+ }; // MR1
+ if (t->_down!=NULL) { // MR1
+ u->_down = t->_down->dup(); // MR1
+ ((ASTDoublyLinkedBase *)u->_down)->_up = u; // MR1
+ } else { // MR1
+ u->_down = NULL; // MR1
+ }; // MR1
+ return u;
+}
+
+#endif
+
+/*
+ * Set the 'up', and 'left' pointers of all nodes in 't'.
+ * Initial call is double_link(your_tree, NULL, NULL).
+ */
+void
+ASTDoublyLinkedBase::double_link(ASTBase *left, ASTBase *up)
+{
+ ASTDoublyLinkedBase *t = this;
+
+ t->_left = (ASTDoublyLinkedBase *) left;
+ t->_up = (ASTDoublyLinkedBase *) up;
+ if (t->_down != NULL)
+ ((ASTDoublyLinkedBase *)t->_down)->double_link(NULL, t);
+ if (t->_right != NULL)
+ ((ASTDoublyLinkedBase *)t->_right)->double_link(t, up);
+}
+
+// MR21 ASTBase::reportOverwriteOfDownPointer
+
+void ASTBase::reportOverwriteOfDownPointer()
+{
+ panic("Attempt to overwrite down pointer in ASTBase::tmake");
+}
+
+// MR21 ASTBase::panic
+
+void ASTBase::panic(const char *msg)
+{
+ /* MR23 */ printMessage(stderr,"ASTBase panic: %s\n", msg);
+ exit(PCCTS_EXIT_FAILURE);
+}
+
+#ifdef PCCTS_NOT_USING_SOR
+//MR23
+int ASTBase::printMessage(FILE* pFile, const char* pFormat, ...)
+{
+ va_list marker;
+ va_start( marker, pFormat );
+ int iRet = vfprintf(pFile, pFormat, marker);
+ va_end( marker );
+ return iRet;
+}
+#endif
diff --git a/Source/Pccts/h/ASTBase.h b/Source/Pccts/h/ASTBase.h
new file mode 100644
index 0000000..912f4b8
--- /dev/null
+++ b/Source/Pccts/h/ASTBase.h
@@ -0,0 +1,122 @@
+/* Abstract syntax tree
+ *
+ * SOFTWARE RIGHTS
+ *
+ * We reserve no LEGAL rights to the Purdue Compiler Construction Tool
+ * Set (PCCTS) -- PCCTS is in the public domain. An individual or
+ * company may do whatever they wish with source code distributed with
+ * PCCTS or the code generated by PCCTS, including the incorporation of
+ * PCCTS, or its output, into commerical software.
+ *
+ * We encourage users to develop software with PCCTS. However, we do ask
+ * that credit is given to us for developing PCCTS. By "credit",
+ * we mean that if you incorporate our source code into one of your
+ * programs (commercial product, research project, or otherwise) that you
+ * acknowledge this fact somewhere in the documentation, research report,
+ * etc... If you like PCCTS and have developed a nice tool with the
+ * output, please mention that you developed it using PCCTS. In
+ * addition, we ask that this header remain intact in our source code.
+ * As long as these guidelines are kept, we expect to continue enhancing
+ * this system and expect to make other tools available as they are
+ * completed.
+ *
+ * ANTLR 1.33
+ * Terence Parr
+ * Parr Research Corporation
+ * with Purdue University and AHPCRC, University of Minnesota
+ * 1989-2000
+ */
+
+#ifndef ASTBase_H
+#define ASTBase_H
+
+#include "pcctscfg.h"
+
+#include "pccts_stdio.h"
+#include "pccts_stdlib.h"
+
+PCCTS_NAMESPACE_STD
+
+#ifndef PCCTS_NOT_USING_SOR
+#include "PCCTSAST.h"
+#endif
+
+/*
+ * Notes:
+ *
+ * To specify a copy constructor, subclass one of these classes and
+ * give the copy constructor. To use dup(), you must define shallowCopy().
+ * shallowCopy() can use either a copy constructor or just copy the node
+ * itself.
+ */
+
+#ifdef PCCTS_NOT_USING_SOR
+class DllExportPCCTS ASTBase {
+#else
+class DllExportPCCTS ASTBase : public PCCTS_AST {
+#endif
+
+protected:
+ ASTBase *_right, *_down;
+
+public:
+
+#ifdef PCCTS_NOT_USING_SOR
+ ASTBase *right() { return _right; }
+ ASTBase *down() { return _down; }
+ void setRight(ASTBase *t) { _right = (ASTBase *)t; }
+ void setDown(ASTBase *t) { _down = (ASTBase *)t; }
+#else
+ PCCTS_AST *right() { return _right; } // define the SORCERER interface
+ PCCTS_AST *down() { return _down; }
+ void setRight(PCCTS_AST *t) { _right = (ASTBase *)t; }
+ void setDown(PCCTS_AST *t) { _down = (ASTBase *)t; }
+#endif
+ ASTBase() { _right = _down = NULL; }
+ virtual ~ASTBase() { ; }
+#ifndef PCCTS_NOT_USING_SOR
+ virtual ASTBase *dup();
+#endif
+ void destroy();
+ void preorder(void* pData = NULL /* MR23 */);
+ static ASTBase *tmake(ASTBase *, ...);
+ static void link(ASTBase **, ASTBase **, ASTBase **);
+ void subchild(ASTBase **, ASTBase **, ASTBase **);
+ void subroot(ASTBase **, ASTBase **, ASTBase **);
+ virtual void preorder_action(void* /*pData*/ = NULL /* MR23 */) { ; }
+ virtual void preorder_before_action(void* /*pData*/ = NULL /* MR23 */) { /* MR23 */ printMessage(stdout, " ("); }
+ virtual void preorder_after_action(void* /*pData*/ = NULL /* MR23 */) { /* MR23 */ printMessage(stdout, " )"); }
+ virtual void panic(const char *msg); /* MR21 */
+ virtual void reportOverwriteOfDownPointer(); /* MR21 */
+#ifdef PCCTS_NOT_USING_SOR
+ virtual int printMessage(FILE* pFile, const char* pFormat, ...); // MR23
+#endif
+};
+
+class DllExportPCCTS ASTDoublyLinkedBase : public ASTBase {
+protected:
+ ASTDoublyLinkedBase *_left, *_up;
+
+public:
+ void double_link(ASTBase *left, ASTBase *up);
+
+#ifndef PCCTS_NOT_USING_SOR
+ virtual ASTBase *dup();
+#endif
+
+#ifdef PCCTS_NOT_USING_SOR
+ ASTBase *left() { return _left; }
+ ASTBase *up() { return _up; }
+ void setLeft(ASTBase *t) { _left = (ASTDoublyLinkedBase *)t; } // MR6
+ void setUp(ASTBase *t) { _up = (ASTDoublyLinkedBase *)t; } // MR6
+#else
+ PCCTS_AST *left() { return _left; }
+ PCCTS_AST *up() { return _up; }
+ void setLeft(PCCTS_AST *t) { _left = (ASTDoublyLinkedBase *)t; } // MR6
+ void setUp(PCCTS_AST *t) { _up = (ASTDoublyLinkedBase *)t; } // MR6
+#endif
+
+};
+
+class AST; // announce that this class will be coming along shortly
+#endif
diff --git a/Source/Pccts/h/ATokPtr.h b/Source/Pccts/h/ATokPtr.h
new file mode 100644
index 0000000..75b4c86
--- /dev/null
+++ b/Source/Pccts/h/ATokPtr.h
@@ -0,0 +1,88 @@
+/* ATokPtr.h
+ *
+ * SOFTWARE RIGHTS
+ *
+ * We reserve no LEGAL rights to the Purdue Compiler Construction Tool
+ * Set (PCCTS) -- PCCTS is in the public domain. An individual or
+ * company may do whatever they wish with source code distributed with
+ * PCCTS or the code generated by PCCTS, including the incorporation of
+ * PCCTS, or its output, into commerical software.
+ *
+ * We encourage users to develop software with PCCTS. However, we do ask
+ * that credit is given to us for developing PCCTS. By "credit",
+ * we mean that if you incorporate our source code into one of your
+ * programs (commercial product, research project, or otherwise) that you
+ * acknowledge this fact somewhere in the documentation, research report,
+ * etc... If you like PCCTS and have developed a nice tool with the
+ * output, please mention that you developed it using PCCTS. In
+ * addition, we ask that this header remain intact in our source code.
+ * As long as these guidelines are kept, we expect to continue enhancing
+ * this system and expect to make other tools available as they are
+ * completed.
+ *
+ * ANTLR 1.33
+ * Written by Russell Quong June 30, 1995
+ * Adapted by Terence Parr to ANTLR stuff
+ * Parr Research Corporation
+ * with Purdue University and AHPCRC, University of Minnesota
+ * 1989-2000
+ */
+
+#ifndef ATokPtr_h
+#define ATokPtr_h
+
+#include "pcctscfg.h"
+
+#include "pccts_stdio.h"
+
+PCCTS_NAMESPACE_STD
+
+// pointer to a reference counted object
+// robust in that an unused ANTLRTokenPtr can point to NULL.
+
+class ANTLRAbstractToken;
+
+class DllExportPCCTS ANTLRTokenPtr {
+public:
+ ANTLRTokenPtr(ANTLRAbstractToken *addr=NULL){ptr_ = addr; ref();}
+ ANTLRTokenPtr(const ANTLRTokenPtr &lhs) {ptr_ = lhs.ptr_; lhs.ref();}
+ ~ANTLRTokenPtr();
+
+ // use ANTLRTokenPtr as a pointer to ANTLRToken
+//
+// 8-Apr-97 MR1 Make operator -> a const member function
+// as well as some other member functions
+//
+ ANTLRAbstractToken *operator-> () const { return ptr_; } // MR1
+//
+// 7-Apr-97 133MR1
+// Fix suggested by Andreas Magnusson
+// (Andreas.Magnusson@mailbox.swipnet.se)
+ void operator = (const ANTLRTokenPtr & lhs); // MR1
+ void operator = (ANTLRAbstractToken *addr);
+ int operator != (const ANTLRTokenPtr &q) const // MR1 // MR11 unsigned -> int
+ { return this->ptr_ != q.ptr_; }
+ int operator == (const ANTLRTokenPtr &q) const // MR1 // MR11 unsigned -> int
+ { return this->ptr_ == q.ptr_; }
+ int operator == (const ANTLRAbstractToken *addr) const // MR11
+ { return this->ptr_ == addr; }
+ int operator != (const ANTLRAbstractToken *addr) const // MR11
+ { return this->ptr_ != addr; }
+
+ void ref() const;
+ void deref();
+
+protected:
+ ANTLRAbstractToken *ptr_;
+};
+
+//typedef ANTLRTokenPtr _ANTLRTokenPtr;
+
+/*
+ * Since you cannot redefine operator->() to return one of the user's
+ * token object types, we must down cast. This is a drag. Here's
+ * a macro that helps. template: "mytoken(a-smart-ptr)->myfield".
+ */
+#define mytoken(tk) ((ANTLRToken *)(tk.operator->()))
+
+#endif
diff --git a/Source/Pccts/h/ATokPtrImpl.h b/Source/Pccts/h/ATokPtrImpl.h
new file mode 100644
index 0000000..9c07cf5
--- /dev/null
+++ b/Source/Pccts/h/ATokPtrImpl.h
@@ -0,0 +1,88 @@
+/*
+ * ATokPtrImpl.h (formerly ATokPtr.cpp)
+ *
+ * This is #included in ATokBuffer.cpp for historical reasons.
+ * It has been renamed because of problems with the .cpp extension
+ * when used with IDE.
+ *
+ *
+ * ANTLRToken MUST be defined before entry to this file.
+ *
+ * SOFTWARE RIGHTS
+ *
+ * We reserve no LEGAL rights to the Purdue Compiler Construction Tool
+ * Set (PCCTS) -- PCCTS is in the public domain. An individual or
+ * company may do whatever they wish with source code distributed with
+ * PCCTS or the code generated by PCCTS, including the incorporation of
+ * PCCTS, or its output, into commerical software.
+ *
+ * We encourage users to develop software with PCCTS. However, we do ask
+ * that credit is given to us for developing PCCTS. By "credit",
+ * we mean that if you incorporate our source code into one of your
+ * programs (commercial product, research project, or otherwise) that you
+ * acknowledge this fact somewhere in the documentation, research report,
+ * etc... If you like PCCTS and have developed a nice tool with the
+ * output, please mention that you developed it using PCCTS. In
+ * addition, we ask that this header remain intact in our source code.
+ * As long as these guidelines are kept, we expect to continue enhancing
+ * this system and expect to make other tools available as they are
+ * completed.
+ *
+ * ANTLR 1.33
+ * Written by Russell Quong June 30, 1995
+ * Adapted by Terence Parr to ANTLR stuff
+ * Parr Research Corporation
+ * with Purdue University and AHPCRC, University of Minnesota
+ * 1989-2000
+ */
+
+#include "pcctscfg.h"
+
+PCCTS_NAMESPACE_STD
+
+#include "ATokPtr.h"
+
+void ANTLRTokenPtr::ref() const
+{
+ if (ptr_ != NULL) {
+ ptr_->ref();
+ }
+}
+
+void ANTLRTokenPtr::deref()
+{
+ if (ptr_ != NULL)
+ {
+ ptr_->deref();
+ if ( ptr_->nref()==0 )
+ {
+ delete ptr_;
+ ptr_ = NULL;
+ }
+ }
+}
+
+ANTLRTokenPtr::~ANTLRTokenPtr()
+{
+ deref();
+}
+
+//
+// 8-Apr-97 MR1 Make operator -> a const member function
+// as weall as some other member functions
+//
+void ANTLRTokenPtr::operator = (const ANTLRTokenPtr & lhs) // MR1
+{
+ lhs.ref(); // protect against "xp = xp"; ie same underlying object
+ deref();
+ ptr_ = lhs.ptr_;
+}
+
+void ANTLRTokenPtr::operator = (ANTLRAbstractToken *addr)
+{
+ if (addr != NULL) {
+ addr->ref();
+ }
+ deref();
+ ptr_ = addr;
+}
diff --git a/Source/Pccts/h/AToken.h b/Source/Pccts/h/AToken.h
new file mode 100644
index 0000000..6167c21
--- /dev/null
+++ b/Source/Pccts/h/AToken.h
@@ -0,0 +1,325 @@
+/* ANTLRToken.h
+ *
+ * SOFTWARE RIGHTS
+ *
+ * We reserve no LEGAL rights to the Purdue Compiler Construction Tool
+ * Set (PCCTS) -- PCCTS is in the public domain. An individual or
+ * company may do whatever they wish with source code distributed with
+ * PCCTS or the code generated by PCCTS, including the incorporation of
+ * PCCTS, or its output, into commerical software.
+ *
+ * We encourage users to develop software with PCCTS. However, we do ask
+ * that credit is given to us for developing PCCTS. By "credit",
+ * we mean that if you incorporate our source code into one of your
+ * programs (commercial product, research project, or otherwise) that you
+ * acknowledge this fact somewhere in the documentation, research report,
+ * etc... If you like PCCTS and have developed a nice tool with the
+ * output, please mention that you developed it using PCCTS. In
+ * addition, we ask that this header remain intact in our source code.
+ * As long as these guidelines are kept, we expect to continue enhancing
+ * this system and expect to make other tools available as they are
+ * completed.
+ *
+ * ANTLR 1.33
+ * Terence Parr
+ * Parr Research Corporation
+ * with Purdue University and AHPCRC, University of Minnesota
+ * 1989-2000
+ */
+
+#ifndef ATOKEN_H_GATE
+#define ATOKEN_H_GATE
+
+#include "pcctscfg.h"
+
+#include "pccts_string.h"
+#include "pccts_stdio.h"
+#include "pccts_stdlib.h"
+#include "pccts_stdarg.h" // MR23
+
+PCCTS_NAMESPACE_STD
+
+// MR9 RJV (JVincent@novell.com) Not needed for variable length strings
+
+//// MR9 #ifndef ANTLRCommonTokenTEXTSIZE
+//// MR9 #define ANTLRCommonTokenTEXTSIZE 100
+//// MR9 #endif
+
+
+/* must define what a char looks like; can make this a class too */
+typedef char ANTLRChar;
+
+/* D E F I N E S M A R T P O I N T E R S */
+
+//#include ATOKPTR_H not tested yet, leave out
+class ANTLRAbstractToken;
+typedef ANTLRAbstractToken *_ANTLRTokenPtr;
+
+class ANTLRAbstractToken {
+public:
+ virtual ~ANTLRAbstractToken() {;}
+ virtual ANTLRTokenType getType() const = 0;
+ virtual void setType(ANTLRTokenType t) = 0;
+ virtual int getLine() const = 0;
+ virtual void setLine(int line) = 0;
+ virtual ANTLRChar *getText() const = 0;
+ virtual void setText(const ANTLRChar *) = 0;
+
+ /* This function will disappear when I can use templates */
+ virtual ANTLRAbstractToken *makeToken(ANTLRTokenType tt,
+ ANTLRChar *text,
+ int line) = 0;
+
+ /* define to satisfy ANTLRTokenBuffer's need to determine whether or
+ not a token object can be destroyed. If nref()==0, no one has
+ a reference, and the object may be destroyed. This function defaults
+ to 1, hence, if you use deleteTokens() message with a token object
+ not derived from ANTLRCommonRefCountToken, the parser will compile
+ but will not delete objects after they leave the token buffer.
+ */
+
+ virtual unsigned nref() const { return 1; } // MR11
+ virtual void ref() {;}
+ virtual void deref() {;}
+
+ virtual void panic(const char *msg) // MR20 const
+ {
+ /* MR23 */ printMessage(stderr, "ANTLRAbstractToken panic: %s\n", msg);
+ exit(PCCTS_EXIT_FAILURE);
+ }
+
+ virtual int printMessage(FILE* pFile, const char* pFormat, ...) // MR23
+ {
+ va_list marker;
+ va_start( marker, pFormat );
+ int iRet = vfprintf(pFile, pFormat, marker);
+ va_end( marker );
+ return iRet;
+ }
+};
+
+/* This class should be subclassed. It cannot store token type or text */
+
+class ANTLRRefCountToken : public ANTLRAbstractToken {
+public:
+#ifdef DBG_REFCOUNTTOKEN
+ static int ctor;
+ static int dtor;
+#endif
+protected:
+ unsigned refcnt_;
+#ifdef DBG_REFCOUNTTOKEN
+ char object[200];
+#endif
+
+public:
+
+ // MR23 - No matter what you do, you're hammered.
+ // Don't give names to formals something breaks.
+ // Give names to formals and don't use them it breaks.
+
+#ifndef DBG_REFCOUNTTOKEN
+ ANTLRRefCountToken(ANTLRTokenType /* t MR23 */, const ANTLRChar * /* s MR23 */)
+#else
+ ANTLRRefCountToken(ANTLRTokenType t, const ANTLRChar * s)
+#endif
+
+#ifndef DBG_REFCOUNTTOKEN
+ {
+ refcnt_ = 0;
+ }
+#else
+ {
+ ctor++;
+ refcnt_ = 0;
+ if ( t==1 ) sprintf(object,"tok_EOF");
+ else sprintf(object,"tok_%s",s);
+ /* MR23 */ printMessage(stderr, "ctor %s #%d\n",object,ctor);
+ }
+#endif
+ ANTLRRefCountToken()
+#ifndef DBG_REFCOUNTTOKEN
+ { refcnt_ = 0; }
+#else
+ {
+ ctor++;
+ refcnt_ = 0;
+ sprintf(object,"tok_blank");
+ /* MR23 */ printMessage(stderr, "ctor %s #%d\n",object,ctor);
+ }
+ virtual ~ANTLRRefCountToken()
+ {
+ dtor++;
+ if ( dtor>ctor ) /* MR23 */ printMessage(stderr, "WARNING: dtor>ctor\n");
+ /* MR23 */ printMessage(stderr, "dtor %s #%d\n", object, dtor);
+ object[0]='\0';
+ }
+#endif
+
+ // reference counting stuff needed by ANTLRTokenPtr.
+ // User should not access these; for C++ language reasons, we had
+ // to make these public. Yuck.
+
+ void ref() { refcnt_++; }
+ void deref() { refcnt_--; }
+ unsigned nref() const { return refcnt_; } // MR11
+
+ virtual ANTLRAbstractToken *makeToken(ANTLRTokenType /*tt MR23*/,
+ ANTLRChar * /*txt MR23*/,
+ int /*line MR23*/)
+ {
+ panic("call to ANTLRRefCountToken::makeToken()\n");
+ return NULL;
+ }
+};
+
+class ANTLRCommonNoRefCountToken : public ANTLRAbstractToken {
+protected:
+ ANTLRTokenType _type;
+ int _line;
+ ANTLRChar *_text; // MR9 RJV
+
+public:
+ ANTLRCommonNoRefCountToken(ANTLRTokenType t, const ANTLRChar *s)
+ { setType(t); _line = 0; _text = NULL; setText(s); }
+ ANTLRCommonNoRefCountToken()
+ { setType((ANTLRTokenType)0); _line = 0; _text = NULL; setText(""); }
+
+ ~ANTLRCommonNoRefCountToken() { if (_text) delete [] _text; } // MR9 RJV: Added Destructor to remove string
+
+ ANTLRTokenType getType() const { return _type; }
+ void setType(ANTLRTokenType t) { _type = t; }
+ virtual int getLine() const { return _line; }
+ void setLine(int line) { _line = line; }
+ ANTLRChar *getText() const { return _text; }
+ int getLength() const { return strlen(getText()); } // MR11
+
+// MR9 RJV: Added code for variable length strings to setText()
+
+ void setText(const ANTLRChar *s)
+ { if (s != _text) {
+ if (_text) delete [] _text;
+ if (s != NULL) {
+ _text = new ANTLRChar[strlen(s)+1];
+ if (_text == NULL) panic("ANTLRCommonNoRefCountToken::setText new failed");
+ strcpy(_text,s);
+ } else {
+ _text = new ANTLRChar[1];
+ if (_text == NULL) panic("ANTLRCommonNoRefCountToken::setText new failed");
+ strcpy(_text,"");
+ };
+ };
+ }
+
+ virtual ANTLRAbstractToken *makeToken(ANTLRTokenType tt,
+ ANTLRChar *txt,
+ int line)
+ {
+ ANTLRAbstractToken *t = new ANTLRCommonNoRefCountToken;
+ t->setType(tt); t->setText(txt); t->setLine(line);
+ return t;
+ }
+
+// MR9 THM Copy constructor required when heap allocated string is used with copy semantics
+
+ ANTLRCommonNoRefCountToken (const ANTLRCommonNoRefCountToken& from) :
+ ANTLRAbstractToken(from) {
+ setType(from._type);
+ setLine(from._line);
+ _text=NULL;
+ setText(from._text);
+ };
+
+// MR9 THM operator =() required when heap allocated string is used with copy semantics
+
+ virtual ANTLRCommonNoRefCountToken& operator =(const ANTLRCommonNoRefCountToken& rhs) {
+
+////// MR15 WatCom can't hack use of operator =()
+////// Use this: *( (ANTRLAbstractToken *) this)=rhs;
+
+ *( (ANTLRAbstractToken *) this ) = rhs;
+
+ setType(rhs._type);
+ setLine(rhs._line);
+ setText(rhs._text);
+ return *this;
+ };
+};
+
+class ANTLRCommonToken : public ANTLRRefCountToken {
+protected:
+ ANTLRTokenType _type;
+ int _line;
+ ANTLRChar *_text; // MR9 RJV:Added
+
+public:
+ ANTLRCommonToken(ANTLRTokenType t, const ANTLRChar *s) : ANTLRRefCountToken(t,s)
+ { setType(t); _line = 0; _text = NULL; setText(s); } // MR9
+ ANTLRCommonToken()
+ { setType((ANTLRTokenType)0); _line = 0; _text = NULL; setText(""); } // MR9
+
+ virtual ~ANTLRCommonToken() { if (_text) delete [] _text; } // MR9 RJV: Added Destructor to remove string
+
+ ANTLRTokenType getType() const { return _type; }
+ void setType(ANTLRTokenType t) { _type = t; }
+ virtual int getLine() const { return _line; }
+ void setLine(int line) { _line = line; }
+ ANTLRChar *getText() const { return _text; }
+ int getLength() const { return strlen(getText()); } // MR11
+
+// MR9 RJV: Added code for variable length strings to setText()
+
+ void setText(const ANTLRChar *s)
+ { if (s != _text) {
+ if (_text) delete [] _text;
+ if (s != NULL) {
+ _text = new ANTLRChar[strlen(s)+1];
+ if (_text == NULL) panic("ANTLRCommonToken::setText new failed");
+ strcpy(_text,s);
+ } else {
+ _text = new ANTLRChar[1];
+ if (_text == NULL) panic("ANTLRCommonToken::setText new failed");
+ strcpy(_text,"");
+ };
+ };
+ }
+
+ virtual ANTLRAbstractToken *makeToken(ANTLRTokenType tt,
+ ANTLRChar *txt,
+ int line)
+ {
+ ANTLRAbstractToken *t = new ANTLRCommonToken(tt,txt);
+ t->setLine(line);
+ return t;
+ }
+
+// MR9 THM Copy constructor required when heap allocated string is used with copy semantics
+
+ ANTLRCommonToken (const ANTLRCommonToken& from) :
+ ANTLRRefCountToken(from) {
+ setType(from._type);
+ setLine(from._line);
+ _text=NULL;
+ setText(from._text);
+ };
+
+// MR9 THM operator =() required when heap allocated string is used with copy semantics
+
+ virtual ANTLRCommonToken& operator =(const ANTLRCommonToken& rhs) {
+
+////// MR15 WatCom can't hack use of operator =()
+////// Use this instead: *( (ANTRLRRefCountToken *) this)=rhs;
+
+ *( (ANTLRRefCountToken *) this) = rhs;
+
+ setType(rhs._type);
+ setLine(rhs._line);
+ setText(rhs._text);
+ return *this;
+ };
+};
+
+// used for backward compatibility
+typedef ANTLRCommonToken ANTLRCommonBacktrackingToken;
+
+#endif
diff --git a/Source/Pccts/h/ATokenBuffer.cpp b/Source/Pccts/h/ATokenBuffer.cpp
new file mode 100644
index 0000000..9a2f2fc
--- /dev/null
+++ b/Source/Pccts/h/ATokenBuffer.cpp
@@ -0,0 +1,374 @@
+/* ANTLRTokenBuffer.cpp
+ *
+ * SOFTWARE RIGHTS
+ *
+ * We reserve no LEGAL rights to the Purdue Compiler Construction Tool
+ * Set (PCCTS) -- PCCTS is in the public domain. An individual or
+ * company may do whatever they wish with source code distributed with
+ * PCCTS or the code generated by PCCTS, including the incorporation of
+ * PCCTS, or its output, into commerical software.
+ *
+ * We encourage users to develop software with PCCTS. However, we do ask
+ * that credit is given to us for developing PCCTS. By "credit",
+ * we mean that if you incorporate our source code into one of your
+ * programs (commercial product, research project, or otherwise) that you
+ * acknowledge this fact somewhere in the documentation, research report,
+ * etc... If you like PCCTS and have developed a nice tool with the
+ * output, please mention that you developed it using PCCTS. In
+ * addition, we ask that this header remain intact in our source code.
+ * As long as these guidelines are kept, we expect to continue enhancing
+ * this system and expect to make other tools available as they are
+ * completed.
+ *
+ * ANTLR 1.33
+ * Terence Parr
+ * Parr Research Corporation
+ * with Purdue University and AHPCRC, University of Minnesota
+ * 1989-2000
+ */
+
+typedef int ANTLRTokenType; // fool AToken.h into compiling
+
+class ANTLRParser; /* MR1 */
+
+#define ANTLR_SUPPORT_CODE
+
+#include "pcctscfg.h"
+
+#include ATOKENBUFFER_H
+#include APARSER_H // MR23
+
+typedef ANTLRAbstractToken *_ANTLRTokenPtr;
+
+#if defined(DBG_TBUF)||defined(DBG_TBUF_MARK_REW)
+static unsigned char test[1000];
+#endif
+
+#ifdef DBG_REFCOUNTTOKEN
+int ANTLRRefCountToken::ctor = 0; /* MR23 */
+int ANTLRRefCountToken::dtor = 0; /* MR23 */
+#endif
+
+ANTLRTokenBuffer::
+ANTLRTokenBuffer(ANTLRTokenStream *_input, int _k, int _chunk_size_formal) /* MR14 */
+{
+ this->input = _input;
+ this->k = _k;
+ buffer_size = chunk_size = _chunk_size_formal;
+ buffer = (_ANTLRTokenPtr *)
+ calloc(chunk_size+1,sizeof(_ANTLRTokenPtr ));
+ if ( buffer == NULL ) {
+ panic("cannot alloc token buffer");
+ }
+ buffer++; // leave the first elem empty so tp-1 is valid ptr
+
+ tp = &buffer[0];
+ last = tp-1;
+ next = &buffer[0];
+ num_markers = 0;
+ end_of_buffer = &buffer[buffer_size-1];
+ threshold = &buffer[(int)(buffer_size/2)]; // MR23 - Used to be 1.0/2.0 !
+ _deleteTokens = 1; // assume we delete tokens
+ parser=NULL; // MR5 - uninitialized reference
+}
+
+static void f() {;}
+ANTLRTokenBuffer::
+~ANTLRTokenBuffer()
+{
+ f();
+ // Delete all remaining tokens (from 0..last inclusive)
+ if ( _deleteTokens )
+ {
+ _ANTLRTokenPtr *z;
+ for (z=buffer; z<=last; z++)
+ {
+ (*z)->deref();
+// z->deref();
+#ifdef DBG_REFCOUNTTOKEN
+ /* MR23 */ printMessage(stderr, "##########dtor: deleting token '%s' (ref %d)\n",
+ ((ANTLRCommonToken *)*z)->getText(), (*z)->nref());
+#endif
+ if ( (*z)->nref()==0 )
+ {
+ delete (*z);
+ }
+ }
+ }
+
+ if ( buffer!=NULL ) free((char *)(buffer-1));
+}
+
+#if defined(DBG_TBUF)||defined(DBG_TBUF_MARK_REW)
+#include "pccts_stdio.h"
+PCCTS_NAMESPACE_STD
+#endif
+
+_ANTLRTokenPtr ANTLRTokenBuffer::
+getToken()
+{
+ if ( tp <= last ) // is there any buffered lookahead still to be read?
+ {
+ return *tp++; // read buffered lookahead
+ }
+ // out of buffered lookahead, get some more "real"
+ // input from getANTLRToken()
+ if ( num_markers==0 )
+ {
+ if( next > threshold )
+ {
+#ifdef DBG_TBUF
+/* MR23 */ printMessage(stderr,"getToken: next > threshold (high water is %d)\n", threshold-buffer);
+#endif
+ makeRoom();
+ }
+ }
+ else {
+ if ( next > end_of_buffer )
+ {
+#ifdef DBG_TBUF
+/* MR23 */ printMessage(stderr,"getToken: next > end_of_buffer (size is %d)\n", buffer_size);
+#endif
+ extendBuffer();
+ }
+ }
+ *next = getANTLRToken();
+ (*next)->ref(); // say we have a copy of this pointer in buffer
+ last = next;
+ next++;
+ tp = last;
+ return *tp++;
+}
+
+void ANTLRTokenBuffer::
+rewind(int pos)
+{
+#if defined(DBG_TBUF)||defined(DBG_TBUF_MARK_REW)
+ /* MR23 */ printMessage(stderr, "rewind(%d)[nm=%d,from=%d,%d.n=%d]\n", pos, num_markers, tp-buffer,pos,test[pos]);
+ test[pos]--;
+#endif
+ tp = &buffer[pos];
+ num_markers--;
+}
+
+/*
+ * This function is used to specify that the token pointers read
+ * by the ANTLRTokenBuffer should be buffered up (to be reused later).
+ */
+int ANTLRTokenBuffer::
+mark()
+{
+#if defined(DBG_TBUF)||defined(DBG_TBUF_MARK_REW)
+ test[tp-buffer]++;
+ /* MR23 */ printMessage(stderr,"mark(%d)[nm=%d,%d.n=%d]\n",tp-buffer,num_markers+1,tp-buffer,test[tp-buffer]);
+#endif
+ num_markers++;
+ return tp - buffer;
+}
+
+/*
+ * returns the token pointer n positions ahead.
+ * This implies that bufferedToken(1) gets the NEXT symbol of lookahead.
+ * This is used in conjunction with the ANTLRParser lookahead buffer.
+ *
+ * No markers are set or anything. A bunch of input is buffered--that's all.
+ * The tp pointer is left alone as the lookahead has not been advanced
+ * with getToken(). The next call to getToken() will find a token
+ * in the buffer and won't have to call getANTLRToken().
+ *
+ * If this is called before a consume() is done, how_many_more_i_need is
+ * set to 'n'.
+ */
+_ANTLRTokenPtr ANTLRTokenBuffer::
+bufferedToken(int n)
+{
+// int how_many_more_i_need = (last-tp < 0) ? n : n-(last-tp)-1;
+ int how_many_more_i_need = (tp > last) ? n : n-(last-tp)-1;
+ // Make sure that at least n tokens are available in the buffer
+#ifdef DBG_TBUF
+ /* MR23 */ printMessage(stderr, "bufferedToken(%d)\n", n);
+#endif
+ for (int i=1; i<=how_many_more_i_need; i++)
+ {
+ if ( next > end_of_buffer ) // buffer overflow?
+ {
+ extendBuffer();
+ }
+ *next = getANTLRToken();
+ (*next)->ref(); // say we have a copy of this pointer in buffer
+ last = next;
+ next++;
+ }
+ return tp[n - 1];
+}
+
+/* If no markers are set, the none of the input needs to be saved (except
+ * for the lookahead Token pointers). We save only k-1 token pointers as
+ * we are guaranteed to do a getANTLRToken() right after this because otherwise
+ * we wouldn't have needed to extend the buffer.
+ *
+ * If there are markers in the buffer, we need to save things and so
+ * extendBuffer() is called.
+ */
+void ANTLRTokenBuffer::
+makeRoom()
+{
+#ifdef DBG_TBUF
+ /* MR23 */ printMessage(stderr, "in makeRoom.................\n");
+ /* MR23 */ printMessage(stderr, "num_markers==%d\n", num_markers);
+#endif
+/*
+ if ( num_markers == 0 )
+ {
+*/
+#ifdef DBG_TBUF
+ /* MR23 */ printMessage(stderr, "moving lookahead and resetting next\n");
+
+ _ANTLRTokenPtr *r;
+ /* MR23 */ printMessage(stderr, "tbuf = [");
+ for (r=buffer; r<=last; r++)
+ {
+ if ( *r==NULL ) /* MR23 */ printMessage(stderr, " xxx");
+ else /* MR23 */ printMessage(stderr, " '%s'", ((ANTLRCommonToken *)*r)->getText());
+ }
+ /* MR23 */ printMessage(stderr, " ]\n");
+
+ /* MR23 */ printMessage(stderr,
+ "before: tp=%d, last=%d, next=%d, threshold=%d\n",tp-buffer,last-buffer,next-buffer,threshold-buffer);
+#endif
+
+ // Delete all tokens from 0..last-(k-1) inclusive
+ if ( _deleteTokens )
+ {
+ _ANTLRTokenPtr *z;
+ for (z=buffer; z<=last-(k-1); z++)
+ {
+ (*z)->deref();
+// z->deref();
+#ifdef DBG_REFCOUNTTOKEN
+ /* MR23 */ printMessage(stderr, "##########makeRoom: deleting token '%s' (ref %d)\n",
+ ((ANTLRCommonToken *)*z)->getText(), (*z)->nref());
+#endif
+ if ( (*z)->nref()==0 )
+ {
+ delete (*z);
+ }
+ }
+ }
+
+ // reset the buffer to initial conditions, but move k-1 symbols
+ // to the beginning of buffer and put new input symbol at k
+ _ANTLRTokenPtr *p = buffer, *q = last-(k-1)+1;
+// ANTLRAbstractToken **p = buffer, **q = end_of_buffer-(k-1)+1;
+#ifdef DBG_TBUF
+ /* MR23 */ printMessage(stderr, "lookahead buffer = [");
+#endif
+ for (int i=1; i<=(k-1); i++)
+ {
+ *p++ = *q++;
+#ifdef DBG_TBUF
+ /* MR23 */ printMessage(stderr,
+ " '%s'", ((ANTLRCommonToken *)buffer[i-1])->getText());
+#endif
+ }
+#ifdef DBG_TBUF
+ /* MR23 */ printMessage(stderr, " ]\n");
+#endif
+ next = &buffer[k-1];
+ tp = &buffer[k-1]; // tp points to what will be filled in next
+ last = tp-1;
+#ifdef DBG_TBUF
+ /* MR23 */ printMessage(stderr,
+ "after: tp=%d, last=%d, next=%d\n",
+ tp-buffer, last-buffer, next-buffer);
+#endif
+/*
+ }
+ else {
+ extendBuffer();
+ }
+*/
+}
+
+/* This function extends 'buffer' by chunk_size and returns with all
+ * pointers at the same relative positions in the buffer (the buffer base
+ * address could have changed in realloc()) except that 'next' comes
+ * back set to where the next token should be stored. All other pointers
+ * are untouched.
+ */
+void
+ANTLRTokenBuffer::
+extendBuffer()
+{
+ int save_last = last-buffer, save_tp = tp-buffer, save_next = next-buffer;
+#ifdef DBG_TBUF
+ /* MR23 */ printMessage(stderr, "extending physical buffer\n");
+#endif
+ buffer_size += chunk_size;
+ buffer = (_ANTLRTokenPtr *)
+ realloc((char *)(buffer-1),
+ (buffer_size+1)*sizeof(_ANTLRTokenPtr ));
+ if ( buffer == NULL ) {
+ panic("cannot alloc token buffer");
+ }
+ buffer++; // leave the first elem empty so tp-1 is valid ptr
+
+ tp = buffer + save_tp; // put the pointers back to same relative position
+ last = buffer + save_last;
+ next = buffer + save_next;
+ end_of_buffer = &buffer[buffer_size-1];
+ threshold = &buffer[(int)(buffer_size*(1.0/2.0))];
+
+/*
+ // zero out new token ptrs so we'll know if something to delete in buffer
+ ANTLRAbstractToken **p = end_of_buffer-chunk_size+1;
+ for (; p<=end_of_buffer; p++) *p = NULL;
+*/
+}
+
+ANTLRParser * ANTLRTokenBuffer:: // MR1
+setParser(ANTLRParser *p) { // MR1
+ ANTLRParser *old=parser; // MR1
+ parser=p; // MR1
+ input->setParser(p); // MR1
+ return old; // MR1
+} // MR1
+ // MR1
+ANTLRParser * ANTLRTokenBuffer:: // MR1
+getParser() { // MR1
+ return parser; // MR1
+} // MR1
+
+void ANTLRTokenBuffer::panic(const char *msg) // MR23
+{
+ if (parser) //MR23
+ parser->panic(msg); //MR23
+ else //MR23
+ exit(PCCTS_EXIT_FAILURE);
+}
+
+//MR23
+int ANTLRTokenBuffer::printMessage(FILE* pFile, const char* pFormat, ...)
+{
+ va_list marker;
+ va_start( marker, pFormat );
+
+ int iRet = 0;
+ if (parser)
+ parser->printMessageV(pFile, pFormat, marker);
+ else
+ iRet = vfprintf(pFile, pFormat, marker);
+
+ va_end( marker );
+ return iRet;
+}
+
+/* to avoid having to link in another file just for the smart token ptr
+ * stuff, we include it here. Ugh.
+ *
+ * MR23 This causes nothing but problems for IDEs.
+ * Change from .cpp to .h
+ *
+ */
+
+#include ATOKPTR_IMPL_H
diff --git a/Source/Pccts/h/ATokenBuffer.h b/Source/Pccts/h/ATokenBuffer.h
new file mode 100644
index 0000000..1c008fd
--- /dev/null
+++ b/Source/Pccts/h/ATokenBuffer.h
@@ -0,0 +1,109 @@
+/* ANTLRTokenBuffer.h
+ *
+ * SOFTWARE RIGHTS
+ *
+ * We reserve no LEGAL rights to the Purdue Compiler Construction Tool
+ * Set (PCCTS) -- PCCTS is in the public domain. An individual or
+ * company may do whatever they wish with source code distributed with
+ * PCCTS or the code generated by PCCTS, including the incorporation of
+ * PCCTS, or its output, into commerical software.
+ *
+ * We encourage users to develop software with PCCTS. However, we do ask
+ * that credit is given to us for developing PCCTS. By "credit",
+ * we mean that if you incorporate our source code into one of your
+ * programs (commercial product, research project, or otherwise) that you
+ * acknowledge this fact somewhere in the documentation, research report,
+ * etc... If you like PCCTS and have developed a nice tool with the
+ * output, please mention that you developed it using PCCTS. In
+ * addition, we ask that this header remain intact in our source code.
+ * As long as these guidelines are kept, we expect to continue enhancing
+ * this system and expect to make other tools available as they are
+ * completed.
+ *
+ * ANTLR 1.33
+ * Terence Parr
+ * Parr Research Corporation
+ * with Purdue University and AHPCRC, University of Minnesota
+ * 1989-2000
+ */
+
+#ifndef ATOKENBUFFER_H_GATE
+#define ATOKENBUFFER_H_GATE
+
+#include "pcctscfg.h"
+
+#include "pccts_stdlib.h"
+
+PCCTS_NAMESPACE_STD
+
+#include ATOKEN_H
+#include ATOKENSTREAM_H
+
+/*
+ * The parser is "attached" to an ANTLRTokenBuffer via interface
+ * functions: getToken() and bufferedToken(). The object that actually
+ * consumes characters and constructs tokens is connected to the
+ * ANTLRTokenBuffer via interface function ANTLRTokenStream::getToken();
+ * where ANTLRTokenStream is really just a behavior (class with no data).
+ * C++ does not have this abstraction and hence we simply have come up
+ * with a fancy name for "void *". See the note in ANTLRTokenStream.h on
+ * the "behavior" of ANTLRTokenStream.
+ */
+
+class ANTLRParser; // MR1
+
+class DllExportPCCTS ANTLRTokenBuffer {
+protected:
+ ANTLRTokenStream *input; // where do I get tokens
+ int buffer_size;
+ int chunk_size;
+ int num_markers;
+ int k; // Need at least this many tokens in buffer
+ _ANTLRTokenPtr *buffer; // buffer used for arbitrary lookahead
+ _ANTLRTokenPtr *tp; // pts into buffer; current token ptr
+ _ANTLRTokenPtr *last; // pts to last valid token in buffer
+ _ANTLRTokenPtr *next; // place to put token from getANTLRToken()
+ _ANTLRTokenPtr *end_of_buffer;
+ /* when you try to write a token past this and there are no markers
+ set, then move k-1 tokens back to the beginning of the buffer.
+ We want to stay away from the end of the buffer because we have
+ to extend it if a marker is set and we reach the end (we cannot
+ move tokens to the beginning of the buffer in this case).
+ */
+ _ANTLRTokenPtr *threshold;
+ unsigned char _deleteTokens;
+
+ // This function is filled in by the subclass; it initiates fetch of input
+ virtual _ANTLRTokenPtr getANTLRToken() { return input->getToken(); }
+ void makeRoom();
+ void extendBuffer();
+
+public:
+ ANTLRTokenBuffer(ANTLRTokenStream *in, int k=1, int chksz=50);
+ virtual ~ANTLRTokenBuffer();
+ virtual _ANTLRTokenPtr getToken();
+ virtual void rewind(int pos);
+ virtual int mark();
+ virtual _ANTLRTokenPtr bufferedToken(int i);
+
+ void noGarbageCollectTokens() { _deleteTokens=0; }
+ void garbageCollectTokens() { _deleteTokens=1; }
+
+ virtual int bufferSize() { return buffer_size; }
+ virtual int minTokens() { return k; }
+ virtual void setMinTokens(int k_new) { k = k_new; }
+
+ virtual void panic(const char *msg); /* MR20 const */
+
+ virtual int printMessage(FILE* pFile, const char* pFormat, ...); // MR23
+
+protected: // MR1
+ ANTLRParser *parser; // MR1
+public: // MR1
+ ANTLRParser *setParser(ANTLRParser *p); // MR1
+ ANTLRParser *getParser(); // MR1
+ ANTLRTokenStream *getLexer() const { // MR12
+ return input;} // MR12
+};
+
+#endif
diff --git a/Source/Pccts/h/ATokenStream.h b/Source/Pccts/h/ATokenStream.h
new file mode 100644
index 0000000..3dfea6e
--- /dev/null
+++ b/Source/Pccts/h/ATokenStream.h
@@ -0,0 +1,51 @@
+/* ANTLRTokenStream.h
+ *
+ * SOFTWARE RIGHTS
+ *
+ * We reserve no LEGAL rights to the Purdue Compiler Construction Tool
+ * Set (PCCTS) -- PCCTS is in the public domain. An individual or
+ * company may do whatever they wish with source code distributed with
+ * PCCTS or the code generated by PCCTS, including the incorporation of
+ * PCCTS, or its output, into commerical software.
+ *
+ * We encourage users to develop software with PCCTS. However, we do ask
+ * that credit is given to us for developing PCCTS. By "credit",
+ * we mean that if you incorporate our source code into one of your
+ * programs (commercial product, research project, or otherwise) that you
+ * acknowledge this fact somewhere in the documentation, research report,
+ * etc... If you like PCCTS and have developed a nice tool with the
+ * output, please mention that you developed it using PCCTS. In
+ * addition, we ask that this header remain intact in our source code.
+ * As long as these guidelines are kept, we expect to continue enhancing
+ * this system and expect to make other tools available as they are
+ * completed.
+ *
+ * ANTLR 1.33
+ * Terence Parr
+ * Parr Research Corporation
+ * with Purdue University and AHPCRC, University of Minnesota
+ * 1989-2000
+ */
+
+#ifndef ATOKENSTREAM_H_GATE
+#define ATOKENSTREAM_H_GATE
+
+#include "pcctscfg.h"
+
+/* This is really a behavior or protocol; it merely indicates the behavior
+ * required of the input and output of an ANTLRTokenBuffer. You could
+ * subclass it, but you can also just pass any old pointer to ANTLRTokenBuffer
+ * with a type cast (in which case, your getANTLRToken() would have to
+ * explicitly cast the input pointer to your REAL type (typically your lexer)).
+ */
+
+class ANTLRParser; // MR1
+
+class DllExportPCCTS ANTLRTokenStream {
+public:
+ virtual _ANTLRTokenPtr getToken() = 0;
+ virtual ANTLRParser * setParser(ANTLRParser * /*p MR23*/) {return 0; }; // MR12
+ virtual ANTLRParser * getParser() { return 0; }; // MR12
+};
+
+#endif
diff --git a/Source/Pccts/h/BufFileInput.cpp b/Source/Pccts/h/BufFileInput.cpp
new file mode 100644
index 0000000..99d08a4
--- /dev/null
+++ b/Source/Pccts/h/BufFileInput.cpp
@@ -0,0 +1,100 @@
+// FILE: BufFileInput.cpp
+// AUTHOR: Alexey Demakov (AVD) demakov@kazbek.ispras.ru
+// CREATION: 26-JAN-1998
+// DESCRIPTION: File Input Stream with lookahead for Scanner.
+// See file BufFileInput.h for details
+
+// Change History:
+//
+// 22-Jun-1998 assert.h -> PCCTS_ASSERT_H
+// string.h -> PCCTS_STRING_H
+//
+// 28-May-1998 Add virtual destructor to release buffer.
+//
+// Add dummy definition for ANTLRTokenType
+// to allow compilation without knowing
+// token type codes.
+//
+// Manfred Kogler (km@cast.uni-linz.ac.at)
+// (1.33MR14)
+//
+// 20-Jul-1998 MR14a - Reorder initialization list for ctor.
+//
+
+enum ANTLRTokenType {TER_HATES_CPP=0, SO_DO_OTHERS=9999 };
+
+#include "pcctscfg.h"
+#include "pccts_assert.h"
+#include "pccts_string.h"
+
+PCCTS_NAMESPACE_STD
+
+#include "BufFileInput.h"
+
+BufFileInput::BufFileInput( FILE *f, int buf_size )
+: input( f ),
+ buf( new int[buf_size] ),
+ size( buf_size ),
+ start( 0 ),
+ len( 0 )
+{
+}
+
+BufFileInput::~BufFileInput()
+{
+ delete [] buf;
+}
+
+int BufFileInput::nextChar( void )
+{
+ if( len > 0 )
+ {
+ // get char from buffer
+ int c = buf[start];
+
+ if( c != EOF )
+ {
+ start++; start %= size;
+ len--;
+ }
+ return c;
+ } else {
+ // get char from file
+ int c = getc( input );
+
+ if( c == EOF )
+ {
+ // if EOF - put it in the buffer as indicator
+ buf[start] = EOF;
+ len++;
+ }
+ return c;
+ }
+}
+
+int BufFileInput::lookahead( char* s )
+{
+ int l = strlen( s );
+
+ assert( 0 < l && l <= size );
+
+ while( len < l )
+ {
+ int c = getc( input );
+
+ buf[ (start+len) % size ] = c;
+
+ len++;
+
+ if( c == EOF ) return 0;
+ }
+
+ for( int i = 0; i < l; i++ )
+ {
+ if( s[i] != buf[ (start+i) % size ] ) return 0;
+ }
+ return 1;
+}
+
+// End of file BufFileInput.cpp
+
diff --git a/Source/Pccts/h/BufFileInput.h b/Source/Pccts/h/BufFileInput.h
new file mode 100644
index 0000000..ea54c0e
--- /dev/null
+++ b/Source/Pccts/h/BufFileInput.h
@@ -0,0 +1,53 @@
+// FILE: BufFileInput.h
+// AUTHOR: Alexey Demakov (AVD) demakov@kazbek.ispras.ru
+// CREATION: 26-JAN-1998
+// DESCRIPTION: File Input Stream with lookahead for Scanner
+// Tested under Win32 with ANTLR 1.33 MR10 and MSVC 5.0
+
+// Change History:
+//
+// 28-May-1998 Add virtual destructor to release buffer
+// Manfred Kogler (km@cast.uni-linz.ac.at)
+// (1.33MR14)
+
+#ifndef BufFileInput_h
+#define BufFileInput_h
+
+#include "pcctscfg.h"
+
+#include "pccts_stdio.h"
+
+PCCTS_NAMESPACE_STD
+
+#include "DLexerBase.h"
+
+class DllExportPCCTS BufFileInput : public DLGInputStream
+{
+public:
+ // constructor
+ // f - input stream
+ // buf_size - size of buffer (maximal length for string in is_in)
+
+ BufFileInput(FILE *f, int buf_size = 8 );
+
+ virtual ~BufFileInput();
+
+ // gets next char from stream
+
+ virtual int nextChar( void );
+
+ // looks in stream and compares next l characters with s
+ // returns the result of comparision
+
+ int lookahead( char* s );
+
+private:
+ FILE *input; // input stream;
+ int* buf; // buffer
+ int size; // size of buffer
+ int start; // position of the first symbol in buffer
+ int len; // count of characters in buffers
+};
+
+#endif
+// end of file BufFileInput.h
diff --git a/Source/Pccts/h/DLG_stream_input.h b/Source/Pccts/h/DLG_stream_input.h
new file mode 100644
index 0000000..d2147f5
--- /dev/null
+++ b/Source/Pccts/h/DLG_stream_input.h
@@ -0,0 +1,98 @@
+
+/************************************************************/
+/* */
+/* Predefined char stream: Input from (c++) stream. */
+/* */
+/* By Hubert Holin (Hubert.Holin@Bigfoot.com), 1998. */
+/* */
+/* This is completely free stuff, do whatever you want with */
+/* it (but then, I will take no responsability for whatever */
+/* may happen if you do either... caveat emptor!). */
+/* */
+/************************************************************/
+
+#ifndef _DLG_STREAM_INPUT_H
+#define _DLG_STREAM_INPUT_H
+
+#include "pccts_istream.h"
+
+PCCTS_NAMESPACE_STD
+
+#ifndef DLGX_H
+#include "DLexerBase.h"
+#endif
+
+
+// NOTES: The semantics of the copy constructor
+// and the affectation operator may be unwaranted...
+// and the stream may not be reset.
+//
+// It would have been so much nicer for nextChar()
+// to throw (of for the DLGInputStream to change status)
+// upon hiting EOF than to return an "int"...
+
+template <
+ class E,
+ class T = ::std::char_traits<E>
+ >
+class DLG_stream_input : public DLGInputStream
+{
+public:
+
+ DLG_stream_input(::std::basic_istream<E,T> * p_input_stream)
+ : input(p_input_stream)
+ {
+ // nothing to do!
+ };
+
+ DLG_stream_input(const DLG_stream_input & a_recopier)
+ : input(a_recopier.input)
+ {
+ // nothing to do!
+ };
+
+ virtual ~DLG_stream_input()
+ {
+ this->purge(); // bloody templarized lookup...
+ };
+
+ DLG_stream_input operator = (const DLG_stream_input & a_affecter)
+ {
+ if (this != &a_affecter)
+ {
+ input = a_affecter.input;
+ }
+
+ return(*this);
+ };
+
+ virtual int nextChar()
+ {
+ E extracted_stuff;
+
+ input->get(extracted_stuff);
+
+ if (*input)
+ {
+ return(int(extracted_stuff));
+ }
+ else
+ {
+ return(EOF);
+ }
+ };
+
+protected:
+
+ ::std::basic_istream<E,T> * input;
+
+private:
+
+ void purge()
+ {
+ // nothing to do!
+ };
+};
+
+#endif /* _DLG_STREAM_INPUT_H */
+
diff --git a/Source/Pccts/h/DLexer.h b/Source/Pccts/h/DLexer.h
new file mode 100644
index 0000000..37cac24
--- /dev/null
+++ b/Source/Pccts/h/DLexer.h
@@ -0,0 +1,191 @@
+/* DLexer.h (formerly DLexer.cpp)
+ *
+ * This was renamed because the use of the .cpp extension caused problems
+ * with IDEs.
+ *
+ * SOFTWARE RIGHTS
+ *
+ * We reserve no LEGAL rights to the Purdue Compiler Construction Tool
+ * Set (PCCTS) -- PCCTS is in the public domain. An individual or
+ * company may do whatever they wish with source code distributed with
+ * PCCTS or the code generated by PCCTS, including the incorporation of
+ * PCCTS, or its output, into commerical software.
+ *
+ * We encourage users to develop software with PCCTS. However, we do ask
+ * that credit is given to us for developing PCCTS. By "credit",
+ * we mean that if you incorporate our source code into one of your
+ * programs (commercial product, research project, or otherwise) that you
+ * acknowledge this fact somewhere in the documentation, research report,
+ * etc... If you like PCCTS and have developed a nice tool with the
+ * output, please mention that you developed it using PCCTS. In
+ * addition, we ask that this header remain intact in our source code.
+ * As long as these guidelines are kept, we expect to continue enhancing
+ * this system and expect to make other tools available as they are
+ * completed.
+ *
+ * ANTLR 1.33
+ * Terence Parr
+ * Parr Research Corporation
+ * with Purdue University and AHPCRC, University of Minnesota
+ * 1989-2000
+ */
+
+#define ZZINC {if ( track_columns ) (++_endcol);}
+
+#define ZZGETC {ch = input->nextChar(); cl = ZZSHIFT(ch);}
+
+#define ZZNEWSTATE (newstate = dfa[state][cl])
+
+#ifndef ZZCOPY
+#define ZZCOPY \
+ /* Truncate matching buffer to size (not an error) */ \
+ if (nextpos < lastpos){ \
+ *(nextpos++) = ch; \
+ }else{ \
+ bufovf = 1; \
+ }
+#endif
+
+void DLGLexer::
+mode( int m )
+{
+ /* points to base of dfa table */
+ if (m<MAX_MODE){
+ automaton = m;
+ /* have to redo class since using different compression */
+ cl = ZZSHIFT(ch);
+ }else{
+ sprintf((char *)ebuf,"Invalid automaton mode = %d ",m);
+ errstd(ebuf);
+ }
+}
+
+ANTLRTokenType DLGLexer::
+nextTokenType(void)
+{
+ register int state, newstate;
+ /* last space reserved for the null char */
+ register DLGChar *lastpos;
+ ANTLRTokenType tk;
+
+skip:
+ bufovf = 0;
+ lastpos = &_lextext[_bufsize-1];
+ nextpos = _lextext;
+ _begcol = _endcol+1;
+more:
+ _begexpr = nextpos;
+ if ( interactive ) {
+ /* interactive version of automaton */
+ /* if there is something in ch, process it */
+ state = newstate = dfa_base[automaton];
+ if (charfull){
+ ZZINC;
+ ZZCOPY;
+ ZZNEWSTATE;
+ }
+ while (alternatives[newstate]){
+ state = newstate;
+ ZZGETC;
+ ZZINC;
+ ZZCOPY;
+ ZZNEWSTATE;
+ }
+ /* figure out if last character really part of token */
+ if ((state != dfa_base[automaton]) && (newstate == DfaStates)){
+ charfull = 1;
+ --nextpos;
+ }else{
+ charfull = 0;
+ state = newstate;
+ }
+ *(nextpos) = '\0';
+ /* Able to transition out of start state to some non err state?*/
+ if ( state == dfa_base[automaton] ){
+ /* make sure doesn't get stuck */
+ advance();
+ }
+ }
+ else { /* non-interactive version of automaton */
+ if (!charfull)
+ advance();
+ else
+ ZZINC;
+ state = dfa_base[automaton];
+ while (ZZNEWSTATE != DfaStates) {
+ state = newstate;
+ ZZCOPY;
+ ZZGETC;
+ ZZINC;
+ }
+ charfull = 1;
+ if ( state == dfa_base[automaton] ){
+ if (nextpos < lastpos){
+ *(nextpos++) = ch;
+ }else{
+ bufovf = 1;
+ }
+ *nextpos = '\0';
+ /* make sure doesn't get stuck */
+ advance();
+ }else{
+ *nextpos = '\0';
+ }
+ }
+ if ( track_columns ) _endcol -= charfull;
+ _endexpr = nextpos -1;
+ add_erase = 0;
+#ifdef OLD
+ tk = (ANTLRTokenType)
+ (*actions[accepts[state]])(this); // must pass this manually
+ // actions is not a [] of pointers
+ // to member functions.
+#endif
+ tk = (this->*actions[accepts[state]])();
+
+// MR1
+// MR1 11-Apr-97 Help for tracking DLG results
+// MR1
+
+#ifdef DEBUG_LEXER
+
+/* MR1 */ if (debugLexerFlag) {
+/* MR1 */ if (parser != NULL) {
+/* MR1 */ /* MR23 */ printMessage(stdout, "\ntoken name=%s",parser->parserTokenName(tk));
+/* MR1 */ } else {
+/* MR1 */ /* MR23 */ printMessage(stdout, "\ntoken nnumber=%d",tk);
+/* MR1 */ };
+/* MR1 */ /* MR23 */ printMessage(stdout, " lextext=(%s) mode=%d",
+/* MR1 */ (_lextext[0]=='\n' && _lextext[1]==0) ?
+/* MR1 */ "newline" : _lextext,
+/* MR1 */ automaton);
+/* MR1 */ if (interactive && !charfull) {
+/* MR1 */ /* MR23 */ printMessage(stdout, " char=empty");
+/* MR1 */ } else {
+/* MR1 */ if (ch=='\n') {
+/* MR1 */ /* MR23 */ printMessage(stdout, " char=newline");
+/* MR1 */ } else {
+/* MR1 */ /* MR23 */ printMessage(stdout, " char=(%c)",ch);
+/* MR1 */ };
+/* MR1 */ };
+/* MR1 */ /* MR23 */ printMessage(stdout, " %s\n",
+/* MR1 */ (add_erase==1 ? "skip()" :
+/* MR1 */ add_erase==2 ? "more()" :
+/* MR1 */ ""));
+/* MR1 */ };
+
+#endif
+
+ switch (add_erase) {
+ case 1: goto skip;
+ case 2: goto more;
+ }
+ return tk;
+}
+
+void DLGLexer::
+advance()
+{
+ if ( input==NULL ) err_in();
+ ZZGETC; charfull = 1; ZZINC;
+}
diff --git a/Source/Pccts/h/DLexerBase.cpp b/Source/Pccts/h/DLexerBase.cpp
new file mode 100644
index 0000000..b218afc
--- /dev/null
+++ b/Source/Pccts/h/DLexerBase.cpp
@@ -0,0 +1,302 @@
+/* DLGLexerBase.c
+ *
+ * SOFTWARE RIGHTS
+ *
+ * We reserve no LEGAL rights to the Purdue Compiler Construction Tool
+ * Set (PCCTS) -- PCCTS is in the public domain. An individual or
+ * company may do whatever they wish with source code distributed with
+ * PCCTS or the code generated by PCCTS, including the incorporation of
+ * PCCTS, or its output, into commerical software.
+ *
+ * We encourage users to develop software with PCCTS. However, we do ask
+ * that credit is given to us for developing PCCTS. By "credit",
+ * we mean that if you incorporate our source code into one of your
+ * programs (commercial product, research project, or otherwise) that you
+ * acknowledge this fact somewhere in the documentation, research report,
+ * etc... If you like PCCTS and have developed a nice tool with the
+ * output, please mention that you developed it using PCCTS. In
+ * addition, we ask that this header remain intact in our source code.
+ * As long as these guidelines are kept, we expect to continue enhancing
+ * this system and expect to make other tools available as they are
+ * completed.
+ *
+ * ANTLR 1.33
+ * Terence Parr
+ * Parr Research Corporation
+ * with Purdue University and AHPCRC, University of Minnesota
+ * 1989-2000
+ */
+
+#include "pcctscfg.h"
+
+#include "pccts_stdio.h"
+#include "pccts_stdlib.h"
+
+PCCTS_NAMESPACE_STD
+
+/* I have to put this here due to C++ limitation
+ * that you can't have a 'forward' decl for enums.
+ * I hate C++!!!!!!!!!!!!!!!
+ */
+
+// MR1
+// MR1 10-Apr-97 133MR1 Prevent use of varying sizes for the
+// MR1 ANTLRTokenType enum
+// MR1
+
+enum ANTLRTokenType { TER_HATES_CPP=0, ITS_UTTER_GARBAGE, // MR1
+ WITH_SOME_GOOD_IDEAS=9999}; // MR1
+
+#define ANTLR_SUPPORT_CODE
+
+#include "pcctscfg.h"
+#include DLEXERBASE_H
+#include APARSER_H // MR23
+
+DLGLexerBase::
+DLGLexerBase(DLGInputStream *in,
+ unsigned bufsize,
+ int _interactive,
+ int _track_columns)
+{
+ this->_bufsize = bufsize;
+ this->_lextext = new DLGChar[_bufsize];
+ if ( this->_lextext==NULL ) {
+ panic("text buffer is NULL");
+ }
+ this->_begexpr = this->_endexpr = NULL;
+ this->ch = this->bufovf = 0;
+ this->nextpos = NULL;
+ this->cl = 0;
+ this->add_erase = 0;
+ this->input = in;
+ this->_begcol = 0;
+ this->_endcol = 0;
+ this->_line = 1;
+ this->charfull = 0;
+ this->automaton = 0;
+ this->token_to_fill = NULL;
+ this->interactive = _interactive;
+ this->track_columns = _track_columns;
+ this->debugLexerFlag = 0; // MR1
+ this->parser = NULL; // MR1
+ this->lexErrCount=0; // MR11
+}
+
+// MR19 THM
+
+void DLGLexerBase::reset()
+{
+ this->charfull = 0;
+ this->_begcol = 0;
+ this->_endcol = 0;
+ this->automaton = 0;
+ this->_line=1;
+ this->lexErrCount=0;
+}
+
+void DLGLexerBase::
+setInputStream( DLGInputStream *in )
+{
+ this->input = in;
+ _line = 1;
+ charfull = 0;
+}
+
+/* saves dlg state, but not what feeds dlg (such as file position) */
+void DLGLexerBase::
+saveState(DLGState *state)
+{
+ state->input = input;
+ state->interactive = interactive;
+ state->track_columns = track_columns;
+ state->auto_num = automaton;
+ state->add_erase = add_erase;
+ state->lookc = ch;
+ state->char_full = charfull;
+ state->begcol = _begcol;
+ state->endcol = _endcol;
+ state->line = _line;
+ state->lextext = _lextext;
+ state->begexpr = _begexpr;
+ state->endexpr = _endexpr;
+ state->bufsize = _bufsize;
+ state->bufovf = bufovf;
+ state->nextpos = nextpos;
+ state->class_num = cl;
+ state->debugLexerFlag = debugLexerFlag; // MR1
+ state->parser = parser; // MR1
+}
+
+void DLGLexerBase::
+restoreState(DLGState *state)
+{
+ input = state->input;
+ interactive = state->interactive;
+ track_columns = state->track_columns;
+ automaton = state->auto_num;
+ add_erase = state->add_erase;
+ ch = state->lookc;
+ charfull = state->char_full;
+ _begcol = state->begcol;
+ _endcol = state->endcol;
+ _line = state->line;
+ _lextext = state->lextext;
+ _begexpr = state->begexpr;
+ _endexpr = state->endexpr;
+ _bufsize = state->bufsize;
+ bufovf = state->bufovf;
+ nextpos = state->nextpos;
+ cl = state->class_num;
+ debugLexerFlag = state->debugLexerFlag; // MR1
+ parser = state->parser; // MR1
+}
+
+/* erase what is currently in the buffer, and get a new reg. expr */
+void DLGLexerBase::
+skip()
+{
+ add_erase = 1;
+}
+
+/* don't erase what is in the lextext buffer, add on to it */
+void DLGLexerBase::
+more()
+{
+ add_erase = 2;
+}
+
+/* substitute c for the reg. expr last matched and is in the buffer */
+void DLGLexerBase::
+replchar(DLGChar c)
+{
+ /* can't allow overwriting null at end of string */
+ if (_begexpr < &_lextext[_bufsize-1]){
+ *_begexpr = c;
+ *(_begexpr+1) = '\0';
+ }
+ _endexpr = _begexpr;
+ if (c != '\0') {
+ nextpos = _begexpr + 1;
+ }
+ else {
+ nextpos = _begexpr; /* MR30 Zero terminates string. */
+ }
+}
+
+/* replace the string s for the reg. expr last matched and in the buffer */
+
+#ifdef _MSC_VER // MR23
+//Turn off "assignment within conditional expression" warning
+#pragma warning(disable : 4706)
+#endif
+void DLGLexerBase::
+replstr(const DLGChar *s) /* MR20 const */
+{
+ register DLGChar *l= &_lextext[_bufsize -1];
+
+ nextpos = _begexpr;
+ if (s){
+ while ((nextpos <= l) && (*(nextpos++) = *(s++))){
+ /* empty */
+ }
+ /* correct for NULL at end of string */
+ nextpos--;
+ }
+ if ((nextpos <= l) && (*(--s) == 0)){
+ bufovf = 0;
+ }else{
+ bufovf = 1;
+ }
+ *(nextpos) = '\0';
+ _endexpr = nextpos - 1;
+}
+#ifdef _MSC_VER // MR23
+#pragma warning(default: 4706)
+#endif
+
+void DLGLexerBase::
+errstd(const char *s) /* MR20 const */
+{
+ lexErrCount++; /* MR11 */
+ /* MR23 */ printMessage(stderr,
+ "%s near line %d (text was '%s')\n",
+ ((s == NULL) ? "Lexical error" : s),
+ _line,_lextext);
+}
+
+int DLGLexerBase::
+err_in()
+{
+ /* MR23 */ printMessage(stderr,"No input stream, function, or string\n");
+ /* return eof to get out gracefully */
+ return EOF;
+}
+
+ANTLRTokenType DLGLexerBase::
+erraction()
+{
+ errstd("invalid token");
+ advance();
+ skip();
+ return (ANTLRTokenType) 0; // bogus, but satisfies compiler
+}
+
+_ANTLRTokenPtr DLGLexerBase::
+getToken()
+{
+ if ( token_to_fill==NULL ) panic("NULL token_to_fill");
+ ANTLRTokenType tt = nextTokenType();
+ _ANTLRTokenPtr tk = token_to_fill->makeToken(tt, _lextext,_line);
+ return tk;
+}
+
+void DLGLexerBase::
+panic(const char *msg) /* MR20 const */
+{
+ if (parser) //MR23
+ parser->panic(msg); //MR23
+ else //MR23
+ {
+ /* MR23 */ printMessage(stderr, "DLG panic: %s\n", msg);
+ //
+ // 7-Apr-97 133MR1
+ //
+ exit(PCCTS_EXIT_FAILURE); // MR1
+ }
+}
+
+ANTLRParser * DLGLexerBase:: // MR1
+setParser(ANTLRParser *p) { // MR1
+ ANTLRParser *oldValue=parser; // MR1
+ parser=p; // MR1
+ return oldValue; // MR1
+} // MR1
+ // MR1
+ANTLRParser * DLGLexerBase:: // MR1
+getParser() { // MR1
+ return parser; // MR1
+} // MR1
+ // MR1
+int DLGLexerBase:: // MR1
+debugLexer(int newValue) { // MR1
+ int oldValue=debugLexerFlag; // MR1
+ debugLexerFlag=newValue; // MR1
+ return oldValue; // MR1
+} // MR1
+
+//MR23
+int DLGLexerBase::printMessage(FILE* pFile, const char* pFormat, ...)
+{
+ va_list marker;
+ va_start( marker, pFormat );
+
+ int iRet = 0;
+ if (parser)
+ parser->printMessageV(pFile, pFormat, marker);
+ else
+ iRet = vfprintf(pFile, pFormat, marker);
+
+ va_end( marker );
+ return iRet;
+}
diff --git a/Source/Pccts/h/DLexerBase.h b/Source/Pccts/h/DLexerBase.h
new file mode 100644
index 0000000..db6cc18
--- /dev/null
+++ b/Source/Pccts/h/DLexerBase.h
@@ -0,0 +1,198 @@
+/* DLGLexerBase.h
+ *
+ * SOFTWARE RIGHTS
+ *
+ * We reserve no LEGAL rights to the Purdue Compiler Construction Tool
+ * Set (PCCTS) -- PCCTS is in the public domain. An individual or
+ * company may do whatever they wish with source code distributed with
+ * PCCTS or the code generated by PCCTS, including the incorporation of
+ * PCCTS, or its output, into commerical software.
+ *
+ * We encourage users to develop software with PCCTS. However, we do ask
+ * that credit is given to us for developing PCCTS. By "credit",
+ * we mean that if you incorporate our source code into one of your
+ * programs (commercial product, research project, or otherwise) that you
+ * acknowledge this fact somewhere in the documentation, research report,
+ * etc... If you like PCCTS and have developed a nice tool with the
+ * output, please mention that you developed it using PCCTS. In
+ * addition, we ask that this header remain intact in our source code.
+ * As long as these guidelines are kept, we expect to continue enhancing
+ * this system and expect to make other tools available as they are
+ * completed.
+ *
+ * ANTLR 1.33
+ * Terence Parr
+ * Parr Research Corporation
+ * with Purdue University and AHPCRC, University of Minnesota
+ * 1989-2000
+ */
+
+#ifndef DLGX_H
+#define DLGX_H
+
+#include "pcctscfg.h"
+#include "pccts_stdio.h"
+
+PCCTS_NAMESPACE_STD
+
+#include ATOKEN_H
+#include ATOKENSTREAM_H
+
+class ANTLRParser; // MR1
+
+/* must define what a char looks like; can make this a class too */
+typedef char DLGChar;
+
+/* Can have it as a class too: (ack this looks weird; is it right?)
+class DllExportPCCTS DLGChar {
+private:
+ int c;
+public:
+ DLGChar(int ch) { c = ch; }
+ int atom() { return c; }
+};
+*/
+
+/* user must subclass this */
+class DllExportPCCTS DLGInputStream {
+public:
+ virtual int nextChar() = 0;
+};
+
+/* Predefined char stream: Input from FILE */
+class DllExportPCCTS DLGFileInput : public DLGInputStream {
+private:
+ int found_eof;
+ FILE *input;
+public:
+ DLGFileInput(FILE *f) { input = f; found_eof = 0; }
+ int nextChar() {
+ int c;
+ if ( found_eof ) return EOF;
+ else {
+ c=getc(input);
+ if ( c==EOF ) found_eof = 1;
+ return c;
+ }
+ }
+ void DLGFileReset(FILE *f) {input=f; found_eof = 0; }; // MR11
+};
+
+// MR9 Suggested by Bruce Guenter (bruceg@qcc.sk.ca)
+// MR9 Make DLGStringInput const correct
+
+/* Predefined char stream: Input from string */
+class DllExportPCCTS DLGStringInput : public DLGInputStream {
+private:
+ const DLGChar *input; // MR9
+ const DLGChar *p; // MR9
+public:
+ DLGStringInput(const DLGChar *s) { input = s; p = &input[0];} // MR9
+ int nextChar()
+ {
+ if (*p) return (int) (unsigned char) *p++; // MR14
+ else return EOF;
+ }
+
+ void DLGStringReset(const DLGChar *s) {input=s; p= &input[0]; }; // MR11 // MR16
+};
+
+class DllExportPCCTS DLGState {
+public:
+ DLGInputStream *input;
+ int interactive;
+ int track_columns;
+ int auto_num;
+ int add_erase;
+ int lookc;
+ int char_full;
+ int begcol, endcol;
+ int line;
+ DLGChar *lextext, *begexpr, *endexpr;
+ int bufsize;
+ int bufovf;
+ DLGChar *nextpos;
+ int class_num;
+ int debugLexerFlag; // MR1
+ ANTLRParser *parser; // MR1
+};
+
+/* user must subclass this */
+class DllExportPCCTS DLGLexerBase : public ANTLRTokenStream {
+public:
+ virtual ANTLRTokenType erraction();
+
+protected:
+ DLGInputStream *input;
+ int interactive;
+ int track_columns;
+ DLGChar *_lextext; /* text of most recently matched token */
+ DLGChar *_begexpr; /* beginning of last reg expr recogn. */
+ DLGChar *_endexpr; /* beginning of last reg expr recogn. */
+ int _bufsize; /* number of characters in lextext */
+ int _begcol; /* column that first character of token is in*/
+ int _endcol; /* column that last character of token is in */
+ int _line; /* line current token is on */
+ int ch; /* character to determine next state */
+ int bufovf; /* indicates that buffer too small for text */
+ int charfull;
+ DLGChar *nextpos; /* points to next available position in lextext*/
+ int cl;
+ int automaton;
+ int add_erase;
+ DLGChar ebuf[70];
+ _ANTLRTokenPtr token_to_fill;
+
+ int debugLexerFlag; // MR1
+ ANTLRParser *parser; // MR1
+public:
+ virtual _ANTLRTokenPtr getToken(); // MR12 public
+ virtual void advance(void) = 0;
+ void skip(void); /* erase lextext, look for antoher token */
+ void more(void); /* keep lextext, look for another token */
+ void mode(int k); /* switch to automaton 'k' */
+ void saveState(DLGState *);
+ void restoreState(DLGState *);
+ virtual ANTLRTokenType nextTokenType(void)=0;/* get next token */
+ void replchar(DLGChar c); /* replace last recognized reg. expr. with
+ a character */
+ void replstr(const DLGChar *s); /* replace last recognized reg. expr. with
+ a string */ /* MR20 const */
+ virtual int err_in(); // MR1
+ virtual void errstd(const char *); // MR1 MR20 const
+ int line() { return _line; }
+ void set_line(int newValue) { _line=newValue; }; // MR1
+ virtual void newline() { _line++; }
+ DLGChar *lextext() { return _lextext; }
+
+ int begcol() { return _begcol; }
+ int endcol() { return _endcol; }
+ void set_begcol(int a) { _begcol=a; }
+ void set_endcol(int a) { _endcol=a; }
+ DLGChar *begexpr() { return _begexpr; }
+ DLGChar *endexpr() { return _endexpr; }
+ int bufsize() { return _bufsize; }
+
+ void setToken(ANTLRAbstractToken *t) { token_to_fill = t; }
+
+ void setInputStream(DLGInputStream *);
+ DLGLexerBase(DLGInputStream *in,
+ unsigned bufsize=2000,
+ int interactive=0,
+ int track_columns=0);
+ void reset(); // MR19
+ virtual ~DLGLexerBase() { delete [] _lextext; }
+ virtual void panic(const char *msg); // MR1 MR20 const
+ void trackColumns() {
+ track_columns = 1;
+ this->_begcol = 0;
+ this->_endcol = 0;
+ };
+ virtual ANTLRParser *setParser(ANTLRParser *p); // MR1
+ virtual ANTLRParser *getParser(); // MR1
+ virtual int debugLexer(int value); // MR1
+ int lexErrCount; // MR12
+ virtual int printMessage(FILE* pFile, const char* pFormat, ...); // MR23
+};
+
+#endif
diff --git a/Source/Pccts/h/PBlackBox.h b/Source/Pccts/h/PBlackBox.h
new file mode 100644
index 0000000..d25b8d6
--- /dev/null
+++ b/Source/Pccts/h/PBlackBox.h
@@ -0,0 +1,134 @@
+#ifndef PBLACKBOX_H
+#define PBLACKBOX_H
+
+/*
+ * SOFTWARE RIGHTS
+ *
+ * We reserve no LEGAL rights to the Purdue Compiler Construction Tool
+ * Set (PCCTS) -- PCCTS is in the public domain. An individual or
+ * company may do whatever they wish with source code distributed with
+ * PCCTS or the code generated by PCCTS, including the incorporation of
+ * PCCTS, or its output, into commerical software.
+ *
+ * We encourage users to develop software with PCCTS. However, we do ask
+ * that credit is given to us for developing PCCTS. By "credit",
+ * we mean that if you incorporate our source code into one of your
+ * programs (commercial product, research project, or otherwise) that you
+ * acknowledge this fact somewhere in the documentation, research report,
+ * etc... If you like PCCTS and have developed a nice tool with the
+ * output, please mention that you developed it using PCCTS. In
+ * addition, we ask that this header remain intact in our source code.
+ * As long as these guidelines are kept, we expect to continue enhancing
+ * this system and expect to make other tools available as they are
+ * completed.
+ *
+ * ANTLR 1.33
+ * Terence Parr
+ * Parr Research Corporation
+ * with Purdue University and AHPCRC, University of Minnesota
+ * 1989-2000
+ */
+
+/* Completely rewritten by Chris Uzdavinis (chris@atdesk.com) for MR23 */
+
+#include "pcctscfg.h"
+
+#include "pccts_iostream.h"
+
+PCCTS_NAMESPACE_STD
+
+// MR20 Added #include for "DLexerBase.h"
+
+#include "DLexerBase.h"
+
+//
+// The default buffer size of the lexer is given by the
+// second argument of the lexer's ctor. It is optional
+// and defaults to 2000
+//
+
+template<class Lexer, class Parser, class Token>
+class DllExportPCCTS ParserBlackBox {
+private:
+ // no copy construction allowed
+ ParserBlackBox(ParserBlackBox const &);
+
+ // no copy assignment allowed
+ ParserBlackBox & operator=(ParserBlackBox const &);
+
+protected:
+ DLGFileInput *in;
+ Lexer *scan;
+ _ANTLRTokenPtr tok;
+ ANTLRTokenBuffer *pipe;
+ Parser *_parser;
+ FILE *file;
+ int openByBlackBox; /* MR21 Don't close what we haven't opened */
+public:
+
+ ParserBlackBox(FILE *f)
+ : in(0)
+ , scan(0)
+ , tok(0)
+ , pipe(0)
+ , _parser(0)
+ , file(0)
+ , openByBlackBox(0)
+ {
+ if (f == NULL)
+ {
+ cerr << "invalid file pointer\n";
+ }
+ else
+ {
+ openByBlackBox = 0; /* MR21a */
+ file = f;
+ in = new DLGFileInput(f);
+ scan = new Lexer(in);
+ pipe = new ANTLRTokenBuffer(scan);
+ tok = new Token;
+ scan->setToken(tok);
+ _parser = new Parser(pipe);
+ _parser->init();
+ }
+ }
+ ParserBlackBox(char *fname)
+ : in(0)
+ , scan(0)
+ , tok(0)
+ , pipe(0)
+ , _parser(0)
+ , file(0)
+ , openByBlackBox(0)
+ {
+ FILE *f = fopen(fname, "r");
+ if ( f==NULL ) {
+ openByBlackBox = 0;
+ cerr << "cannot open " << fname << "\n"; return;
+ }
+ else {
+ openByBlackBox = 1;
+ file = f;
+ in = new DLGFileInput(f);
+ scan = new Lexer(in);
+ pipe = new ANTLRTokenBuffer(scan);
+ tok = new Token;
+ scan->setToken(tok);
+ _parser = new Parser(pipe);
+ _parser->init();
+ }
+ }
+
+ ~ParserBlackBox()
+ {
+ delete in; delete scan; delete pipe; delete _parser; delete tok;
+ if (1 == openByBlackBox) {
+ fclose(file);
+ }
+ }
+
+ Parser *parser() { return _parser; }
+ Lexer *getLexer() { return scan; }
+};
+
+#endif
diff --git a/Source/Pccts/h/PCCTSAST.cpp b/Source/Pccts/h/PCCTSAST.cpp
new file mode 100644
index 0000000..a8249cd
--- /dev/null
+++ b/Source/Pccts/h/PCCTSAST.cpp
@@ -0,0 +1,684 @@
+/*
+ * PCCTSAST.C
+ *
+ * SOFTWARE RIGHTS
+ *
+ * We reserve no LEGAL rights to SORCERER -- SORCERER is in the public
+ * domain. An individual or company may do whatever they wish with
+ * source code distributed with SORCERER or the code generated by
+ * SORCERER, including the incorporation of SORCERER, or its output, into
+ * commerical software.
+ *
+ * We encourage users to develop software with SORCERER. However, we do
+ * ask that credit is given to us for developing SORCERER. By "credit",
+ * we mean that if you incorporate our source code into one of your
+ * programs (commercial product, research project, or otherwise) that you
+ * acknowledge this fact somewhere in the documentation, research report,
+ * etc... If you like SORCERER and have developed a nice tool with the
+ * output, please mention that you developed it using SORCERER. In
+ * addition, we ask that this header remain intact in our source code.
+ * As long as these guidelines are kept, we expect to continue enhancing
+ * this system and expect to make other tools available as they are
+ * completed.
+ *
+ * SORCERER 1.00B14 and ANTLR 1.33
+ * Terence Parr
+ * Parr Research Corporation
+ * AHPCRC, University of Minnesota
+ * 1992-2000
+ */
+
+#define ANTLR_SUPPORT_CODE
+
+#include "pcctscfg.h"
+
+#include "PCCTSAST.h"
+#include "pccts_stdarg.h"
+
+PCCTS_NAMESPACE_STD
+
+#include <ctype.h>
+
+//#include "SList.h"
+
+ /* String Scanning/Parsing Stuff */
+
+const char *PCCTS_AST::scan_token_tbl[] = { /* MR20 const */
+ "invalid", /* 0 */
+ "LPAREN", /* 1 */
+ "RPAREN", /* 2 */
+ "PERCENT", /* 3 */
+ "INT", /* 4 */
+ "COLON", /* 5 */
+ "POUND", /* 6 */
+ "PERIOD", /* 7 */
+};
+
+void PCCTS_AST::
+addChild(PCCTS_AST *t)
+{
+ if ( t==NULL ) return;
+ PCCTS_AST *s = down();
+ if ( s!=NULL )
+ {
+ while ( s->right()!=NULL ) s = s->right();
+ s->setRight(t);
+ }
+ else
+ this->setDown(t);
+}
+
+void PCCTS_AST::
+lisp(FILE *f)
+{
+ if ( down() != NULL ) /* MR23 */ printMessage(f," (");
+ lisp_action(f);
+ if ( down()!=NULL ) down()->lisp(f);
+ if ( down() != NULL ) /* MR23 */ printMessage(f," )");
+ if ( right()!=NULL ) right()->lisp(f);
+}
+
+/* build a tree (root child1 child2 ... NULL)
+ * If root is NULL, simply make the children siblings and return ptr
+ * to 1st sibling (child1). If root is not single node, return NULL.
+ *
+ * Siblings that are actually sibling lists themselves are handled
+ * correctly. For example #( NULL, #( NULL, A, B, C), D) results
+ * in the tree ( NULL A B C D ).
+ *
+ * Requires at least two parameters with the last one being NULL. If
+ * both are NULL, return NULL.
+ *
+ * The down() and right() down/right pointers are used to make the tree.
+ */
+PCCTS_AST *PCCTS_AST::
+make(PCCTS_AST *rt, ...)
+{
+ va_list ap;
+ register PCCTS_AST *child, *sibling=NULL, *tail=NULL /*MR23*/, *w;
+ PCCTS_AST *root;
+
+ va_start(ap, rt);
+ root = rt;
+
+ if ( root != NULL )
+ if ( root->down() != NULL ) return NULL;
+ child = va_arg(ap, PCCTS_AST *);
+ while ( child != NULL )
+ {
+ /* find end of child */
+ for (w=child; w->right()!=NULL; w=w->right()) {;}
+ if ( sibling == NULL ) {sibling = child; tail = w;}
+ else {tail->setRight(child); tail = w;}
+ child = va_arg(ap, PCCTS_AST *);
+ }
+ if ( root==NULL ) root = sibling;
+ else root->setDown(sibling);
+ va_end(ap);
+ return root;
+}
+
+/* The following push and pop routines are only used by ast_find_all() */
+
+void PCCTS_AST::
+_push(PCCTS_AST **st, int *sp, PCCTS_AST *e)
+{
+ (*sp)--;
+ require((*sp)>=0, "stack overflow");
+ st[(*sp)] = e;
+}
+
+PCCTS_AST *PCCTS_AST::
+_pop(PCCTS_AST **st, int *sp)
+{
+ PCCTS_AST *e = st[*sp];
+ (*sp)++;
+ require((*sp)<=MaxTreeStackDepth, "stack underflow");
+ return e;
+}
+
+/* Find all occurrences of u in t.
+ * 'cursor' must be initialized to 't'. It eventually
+ * returns NULL when no more occurrences of 'u' are found.
+ */
+PCCTS_AST *PCCTS_AST::
+ast_find_all(PCCTS_AST *u, PCCTS_AST **cursor)
+{
+ PCCTS_AST *sib;
+ /*** static ***/ PCCTS_AST *template_stack[MaxTreeStackDepth]; /* MR23 Remove "static" */
+ /*** static ***/ int tsp = MaxTreeStackDepth; /* MR23 Remove "static" */
+
+////static int nesting = 0; /* MR23 Not referenced */
+
+ if ( *cursor == NULL ) return NULL;
+ if ( *cursor!=this ) sib = *cursor;
+ else {
+ /* else, first time--start at top of template 't' */
+ tsp = MaxTreeStackDepth;
+ sib = this;
+ /* bottom of stack is always a NULL--"cookie" indicates "done" */
+ _push(template_stack, &tsp, NULL);
+ }
+
+keep_looking:
+ if ( sib==NULL ) /* hit end of sibling list */
+ {
+ sib = _pop(template_stack, &tsp);
+ if ( sib == NULL ) { *cursor = NULL; return NULL; }
+ }
+
+ if ( sib->type() != u->type() )
+ {
+ /* look for another match */
+ if ( sib->down()!=NULL )
+ {
+ if ( sib->right()!=NULL ) _push(template_stack, &tsp, sib->right());
+ sib=sib->down();
+ goto keep_looking;
+ }
+ /* nothing below to try, try next sibling */
+ sib=sib->right();
+ goto keep_looking;
+ }
+
+ /* found a matching root node, try to match what's below */
+ if ( match_partial(sib, u) )
+ {
+ /* record sibling cursor so we can pick up next from there */
+ if ( sib->down()!=NULL )
+ {
+ if ( sib->right()!=NULL ) _push(template_stack, &tsp, sib->right());
+ *cursor = sib->down();
+ }
+ else if ( sib->right()!=NULL ) *cursor = sib->right();
+ else *cursor = _pop(template_stack, &tsp);
+ return sib;
+ }
+
+ /* no match, keep searching */
+ if ( sib->down()!=NULL )
+ {
+ if ( sib->right()!=NULL ) _push(template_stack, &tsp, sib->right());
+ sib=sib->down();
+ }
+ else sib = sib->right(); /* else, try to right if zip below */
+ goto keep_looking;
+}
+
+/* are two trees exactly alike? */
+int PCCTS_AST::
+match(PCCTS_AST *u)
+{
+ PCCTS_AST *t = this;
+ PCCTS_AST *sib;
+
+ if ( u==NULL ) return 0;
+
+ for (sib=t; sib!=NULL&&u!=NULL; sib=sib->right(), u=u->right())
+ {
+ if ( sib->type() != u->type() ) return 0;
+ if ( sib->down()!=NULL )
+ if ( !sib->down()->match(u->down()) ) return 0;
+ }
+ return 1;
+}
+
+/* Is 'u' a subtree of 't' beginning at the root? */
+int PCCTS_AST::
+match_partial(PCCTS_AST *t, PCCTS_AST *u)
+{
+ PCCTS_AST *sib;
+
+ if ( u==NULL ) return 1;
+ if ( t==NULL ) return 0; /* MR23 removed unreachable code */
+
+ for (sib=t; sib!=NULL&&u!=NULL; sib=sib->right(), u=u->right())
+ {
+ if ( sib->type() != u->type() ) return 0;
+ if ( sib->down()!=NULL )
+ if ( !match_partial(sib->down(), u->down()) ) return 0;
+ }
+ return 1;
+}
+
+#ifdef _MSC_VER // MR23
+//Turn off "unreachable code" warning
+#pragma warning(disable : 4702)
+#endif
+/* Walk the template tree 't' (matching against 'this'), filling in the
+ * 'labels' array, and setting 'n' according to how many labels were matched.
+ */
+int PCCTS_AST::
+scanmatch(ScanAST *t, PCCTS_AST **labels[], int *n)
+{
+ ScanAST *sib;
+ PCCTS_AST *u = this;
+
+ if ( u==NULL ) return 0;
+
+ for (sib=t; sib!=NULL&&u!=NULL; sib=sib->right(), u=u->right())
+ {
+ /* make sure tokens match; token of '0' means wildcard match */
+ if ( sib->type() != u->type() && sib->type()!=0 ) return 0;
+ /* we have a matched token here; set label pointers if exists */
+ if ( sib->label_num>0 )
+ {
+ require(labels!=NULL, "label found in template, but no array of labels");
+ (*n)++;
+ *(labels[sib->label_num-1]) = u;
+ }
+ /* match what's below if something there and current node is not wildcard */
+ if ( sib->down()!=NULL && sib->type()!=0 )
+ {
+ if ( sib->down()==NULL )
+ {
+ if ( u->down()!=NULL )
+ return 0;
+ else
+ return 1;
+ }
+ if ( !u->down()->scanmatch(sib->down(), labels, n) ) return 0;
+ }
+ }
+ return 1;
+}
+#ifdef _MSC_VER // MR23
+#pragma warning(default : 4702)
+#endif
+
+void PCCTS_AST::
+insert_after(PCCTS_AST *b)
+{
+ PCCTS_AST *end;
+ if ( b==NULL ) return;
+ /* find end of b's child list */
+ for (end=b; end->right()!=NULL; end=end->right()) {;}
+ end->setRight(this->right());
+ this->setRight(b);
+}
+
+void PCCTS_AST::
+append(PCCTS_AST *b)
+{
+ PCCTS_AST *end;
+ require(b!=NULL, "append: NULL input tree");
+ /* find end of child list */
+ for (end=this; end->right()!=NULL; end=end->right()) {;}
+ end->setRight(b);
+}
+
+PCCTS_AST *PCCTS_AST::
+tail()
+{
+ PCCTS_AST *end;
+ /* find end of child list */
+ for (end=this; end->right()!=NULL; end=end->right()) {;}
+ return end;
+}
+
+PCCTS_AST *PCCTS_AST::
+bottom()
+{
+ PCCTS_AST *end;
+ /* find end of child list */
+ for (end=this; end->down()!=NULL; end=end->down()) {;}
+ return end;
+}
+
+PCCTS_AST *PCCTS_AST::
+cut_between(PCCTS_AST *a, PCCTS_AST *b)
+{
+ PCCTS_AST *end, *ret;
+ if (a==NULL||b==NULL) return NULL;
+ /* find node pointing to b */
+ for (end=a; end->right()!=NULL&&end->right()!=b; end=end->right())
+ {;}
+ if (end->right()==NULL) return NULL; //ast_cut_between: a,b not connected
+ end->setRight(NULL); /* don't want it point to 'b' anymore */
+ ret = a->right();
+ a->setRight(b);
+ return ret;
+}
+
+#ifdef NOT_YET
+SList *PCCTS_AST::
+to_slist()
+{
+ SList *list = new SList;
+ PCCTS_AST *p;
+
+ for (p=this; p!=NULL; p=p->right())
+ {
+ list->add(p);
+ }
+ return list;
+}
+#endif
+
+void PCCTS_AST::
+tfree()
+{
+ PCCTS_AST *t = this;
+ if ( t->down()!=NULL ) t->down()->tfree();
+ if ( t->right()!=NULL ) t->right()->tfree();
+ delete t;
+}
+
+int PCCTS_AST::
+nsiblings()
+{
+ PCCTS_AST *t = this;
+ int n=0;
+
+ while ( t!=NULL )
+ {
+ n++;
+ t = t->right();
+ }
+ return n;
+}
+
+PCCTS_AST *PCCTS_AST::
+sibling_index(int i)
+{
+ PCCTS_AST *t = this;
+ int j=1;
+ require(i>0, "sibling_index: i<=0");
+
+ while ( t!=NULL )
+ {
+ if ( j==i ) return t;
+ j++;
+ t = t->right();
+ }
+ return NULL;
+}
+
+/* Assume this is a root node of a tree--
+ * duplicate that node and what's below; ignore siblings of root node.
+ */
+
+// MR9 23-Sep-97 RJV
+// MR9
+// MR9 RJV: Original version only duplicated the node and down elements.
+// MR9 Made copies of the pointers to sibling.
+// MR9 Changed call "down()->deepCopy()" to "down()->deepCopyBushy()"
+// MR9
+
+PCCTS_AST *PCCTS_AST::
+deepCopy()
+{
+ PCCTS_AST *u = this->shallowCopy();
+ if ( down()!=NULL ) u->setDown(down()->deepCopyBushy());
+ u->setRight(NULL);
+ return u;
+}
+
+/* Copy all nodes including siblings of root. */
+PCCTS_AST *PCCTS_AST::
+deepCopyBushy()
+{
+ PCCTS_AST *u = this->shallowCopy();
+ /* copy the rest of the tree */
+ if ( down()!=NULL ) u->setDown(down()->deepCopyBushy());
+ if ( right()!=NULL ) u->setRight(right()->deepCopyBushy());
+ return u;
+}
+
+void PCCTS_AST::
+scanast_free(ScanAST *t)
+{
+ if ( t == NULL ) return;
+ scanast_free( t->down() );
+ scanast_free( t->right() );
+ free( (char *) t ); // MR1
+}
+
+/*
+ * scan
+ *
+ * This function is like scanf(): it attempts to match a template
+ * against an input tree. A variable number of tree pointers
+ * may be set according to the '%i' labels in the template string.
+ * For example:
+ *
+ * t->ast_scan("#( 6 #(5 %1:4 %2:3) #(1 %3:3 %4:3) )",
+ * &w, &x, &y, &z);
+ *
+ * Naturally, you'd want this converted from
+ *
+ * t->ast_scan("#( RangeOp #(Minus %1:IConst %2:Var) #(Plus %3:Var %4Var) )",
+ * &w, &x, &y, &z);
+ *
+ * by SORCERER.
+ *
+ * This function call must be done withing a SORCERER file because SORCERER
+ * must convert the token references to the associated token number.
+ *
+ * This functions parses the template and creates trees which are then
+ * matched against the input tree. The labels are set as they are
+ * encountered; hence, partial matches may leave some pointers set
+ * and some NULL. This routines initializes all argument pointers to NULL
+ * at the beginning.
+ *
+ * This function returns the number of labels matched.
+ */
+int PCCTS_AST::
+ast_scan(char *templ, ...)
+{
+ va_list ap;
+ ScanAST *tmpl;
+ int n, i, found=0;
+ PCCTS_AST ***label_ptrs=NULL;
+
+ va_start(ap, templ);
+
+ /* make a ScanAST tree out of the template */
+ tmpl = stringparser_parse_scanast(templ, &n);
+
+ /* make an array out of the labels */
+ if ( n>0 )
+ {
+ label_ptrs = (PCCTS_AST ***) calloc(n, sizeof(PCCTS_AST **));
+ require(label_ptrs!=NULL, "scan: out of memory");
+ for (i=1; i<=n; i++)
+ {
+ label_ptrs[i-1] = va_arg(ap, PCCTS_AST **);
+ *(label_ptrs[i-1]) = NULL;
+ }
+ }
+
+ /* match the input tree against the template */
+ scanmatch(tmpl, label_ptrs, &found);
+
+ scanast_free(tmpl);
+ free( (char *) label_ptrs); // MR1
+
+ return found;
+}
+
+ScanAST *PCCTS_AST::
+new_scanast(int tok)
+{
+ ScanAST *p = (ScanAST *) calloc(1, sizeof(ScanAST));
+//
+// 7-Apr-97 133MR1
+//
+ if ( p == NULL )
+ panic("out of memory\n"); // MR23
+ p->_token = tok;
+ return p;
+}
+
+ScanAST *PCCTS_AST::
+stringparser_parse_scanast(char *templ, int *num_labels)
+{
+ StringLexer lex;
+ StringParser parser;
+ ScanAST *t;
+
+ stringlexer_init(&lex, templ);
+ stringparser_init(&parser, &lex);
+ t = stringparser_parse_tree(&parser);
+ *num_labels = parser.num_labels;
+ return t;
+}
+
+void PCCTS_AST::
+stringparser_match(StringParser *parser, int token)
+{
+ if ( parser->token != token ) panic("bad tree in scan()");
+}
+
+/*
+ * Match a tree of the form:
+ * (root child1 child2 ... childn)
+ * or,
+ * node
+ *
+ * where the elements are integers or labeled integers.
+ */
+ScanAST *PCCTS_AST::
+stringparser_parse_tree(StringParser *parser)
+{
+ ScanAST *t=NULL, *root, *child, *last=NULL /*MR23*/;
+
+ if ( parser->token != __POUND )
+ {
+ return stringparser_parse_element(parser);
+ }
+ stringparser_match(parser,__POUND);
+ parser->token = stringscan_gettok(parser->lexer);
+ stringparser_match(parser,__LPAREN);
+ parser->token = stringscan_gettok(parser->lexer);
+ root = stringparser_parse_element(parser);
+ while ( parser->token != __RPAREN )
+ {
+ child = stringparser_parse_element(parser);
+ if ( t==NULL ) { t = child; last = t; }
+ else { last->_right = child; last = child; }
+ }
+ stringparser_match(parser,__RPAREN);
+ parser->token = stringscan_gettok(parser->lexer);
+ root->_down = t;
+ return root;
+}
+
+ScanAST *PCCTS_AST::
+stringparser_parse_element(StringParser *parser)
+{
+ char ebuf[100];
+ int label = 0;
+
+ if ( parser->token == __POUND )
+ {
+ return stringparser_parse_tree(parser);
+ }
+ if ( parser->token == __PERCENT )
+ {
+ parser->token = stringscan_gettok(parser->lexer);
+ stringparser_match(parser,__INT);
+ label = atoi(parser->lexer->text);
+ parser->num_labels++;
+ if ( label==0 ) panic("%%0 is an invalid label");
+ parser->token = stringscan_gettok(parser->lexer);
+ stringparser_match(parser,__COLON);
+ parser->token = stringscan_gettok(parser->lexer);
+ /* can label tokens and wildcards */
+ if ( parser->token != __INT && parser->token != __PERIOD )
+ panic("can only label tokens");
+ }
+ if ( parser->token == __INT )
+ {
+ ScanAST *p = new_scanast(atoi(parser->lexer->text));
+ parser->token = stringscan_gettok(parser->lexer);
+ p->label_num = label;
+ return p;
+ }
+ if ( parser->token == __PERIOD )
+ {
+ ScanAST *p = new_scanast(0); /* token of 0 is wildcard */
+ parser->token = stringscan_gettok(parser->lexer);
+ p->label_num = label;
+ return p;
+ }
+ sprintf(ebuf, "mismatch token in scan(): %s", scan_token_str(parser->token));
+ panic(ebuf);
+ return NULL;
+}
+
+void PCCTS_AST::
+stringparser_init(StringParser *parser, StringLexer *input)
+{
+ parser->lexer = input;
+ parser->token = stringscan_gettok(parser->lexer);
+ parser->num_labels = 0;
+}
+
+void PCCTS_AST::
+stringlexer_init(StringLexer *scanner, char *input)
+{
+ scanner->text[0]='\0';
+ scanner->input = input;
+ scanner->p = input;
+ stringscan_advance(scanner);
+}
+
+void PCCTS_AST::
+stringscan_advance(StringLexer *scanner)
+{
+ if ( *(scanner->p) == '\0' ) scanner->c = __StringScanEOF;
+ scanner->c = *(scanner->p)++;
+}
+
+int PCCTS_AST::
+stringscan_gettok(StringLexer *scanner)
+{
+ char *index = &scanner->text[0];
+ char ebuf[100]; /* MR23 Remove static */
+
+ while ( isspace(scanner->c) ) { stringscan_advance(scanner); }
+ if ( isdigit(scanner->c) )
+ {
+ int tok = __INT;
+ while ( isdigit(scanner->c) ) {
+ *index++ = (char) /* static_cast<char> */ (scanner->c); // MR23
+ stringscan_advance(scanner);
+ }
+ *index = '\0';
+ return tok;
+ }
+ switch ( scanner->c )
+ {
+ case '#' : stringscan_advance(scanner); return __POUND;
+ case '(' : stringscan_advance(scanner); return __LPAREN;
+ case ')' : stringscan_advance(scanner); return __RPAREN;
+ case '%' : stringscan_advance(scanner); return __PERCENT;
+ case ':' : stringscan_advance(scanner); return __COLON;
+ case '.' : stringscan_advance(scanner); return __PERIOD;
+ case '\0' : return __StringScanEOF;
+ case __StringScanEOF : return __StringScanEOF;
+ default :
+ sprintf(ebuf, "invalid char in scan: '%c'", scanner->c);
+ panic(ebuf);
+ }
+ return __StringScanEOF; // never reached
+}
+
+const char *PCCTS_AST:: /* MR20 const */
+scan_token_str(int t)
+{
+ if ( VALID_SCAN_TOKEN(t) ) return scan_token_tbl[t];
+ else if ( t==__StringScanEOF ) return "<end-of-string>";
+ else return "<invalid-token>";
+}
+
+//MR23
+int PCCTS_AST::printMessage(FILE* pFile, const char* pFormat, ...)
+{
+ va_list marker;
+ va_start( marker, pFormat );
+ int iRet = vfprintf(pFile, pFormat, marker);
+ va_end( marker );
+ return iRet;
+}
diff --git a/Source/Pccts/h/PCCTSAST.h b/Source/Pccts/h/PCCTSAST.h
new file mode 100644
index 0000000..3485da7
--- /dev/null
+++ b/Source/Pccts/h/PCCTSAST.h
@@ -0,0 +1,143 @@
+/* Abstract syntax tree
+ *
+ * SOFTWARE RIGHTS
+ *
+ * We reserve no LEGAL rights to the Purdue Compiler Construction Tool
+ * Set (PCCTS) -- PCCTS is in the public domain. An individual or
+ * company may do whatever they wish with source code distributed with
+ * PCCTS or the code generated by PCCTS, including the incorporation of
+ * PCCTS, or its output, into commerical software.
+ *
+ * We encourage users to develop software with PCCTS. However, we do ask
+ * that credit is given to us for developing PCCTS. By "credit",
+ * we mean that if you incorporate our source code into one of your
+ * programs (commercial product, research project, or otherwise) that you
+ * acknowledge this fact somewhere in the documentation, research report,
+ * etc... If you like PCCTS and have developed a nice tool with the
+ * output, please mention that you developed it using PCCTS. In
+ * addition, we ask that this header remain intact in our source code.
+ * As long as these guidelines are kept, we expect to continue enhancing
+ * this system and expect to make other tools available as they are
+ * completed.
+ *
+ * ANTLR 1.33
+ * Terence Parr
+ * Parr Research Corporation
+ * with Purdue University and AHPCRC, University of Minnesota
+ * 1989-2000
+ */
+
+#ifndef PCCTSAST_H
+#define PCCTSAST_H
+
+#include "pcctscfg.h"
+
+#include "pccts_stdio.h"
+#include "pccts_stdlib.h"
+
+PCCTS_NAMESPACE_STD
+
+//class SList;
+
+#define StringScanMaxText 50
+#define MaxTreeStackDepth 400
+
+//
+// 7-Apr-97 133MR1 signed int not accepted by AT&T cfront
+//
+typedef struct stringlexer {
+ int c; // MR1
+ char *input;
+ char *p;
+ char text[StringScanMaxText];
+ } StringLexer;
+
+/* Define the structures needed for ast_scan() */
+typedef struct stringparser {
+ int token;
+ StringLexer *lexer;
+ int num_labels;
+ } StringParser;
+
+typedef struct _scanast {
+ struct _scanast *_right, *_down;
+ int _token;
+ int label_num;
+ int type() { return _token; }
+ struct _scanast *right() { return _right; }
+ struct _scanast *down() { return _down; }
+ } ScanAST;
+
+#define VALID_SCAN_TOKEN(t) (t>=__LPAREN && t<=__PERIOD)
+
+class DllExportPCCTS PCCTS_AST {
+protected:
+ static const char *scan_token_tbl[]; /* MR20 const */
+ enum {
+ __LPAREN=1,
+ __RPAREN=2,
+ __PERCENT=3,
+ __INT=4,
+ __COLON=5,
+ __POUND=6,
+ __PERIOD=7,
+ __StringScanEOF=-1};
+
+protected:
+ const char *scan_token_str(int t); /* MR20 const */
+ void stringlexer_init(StringLexer *scanner, char *input);
+ void stringparser_init(StringParser *, StringLexer *);
+ ScanAST *stringparser_parse_scanast(char *templ, int *n);
+ ScanAST *stringparser_parse_tree(StringParser *parser);
+ ScanAST *stringparser_parse_element(StringParser *parser);
+ void stringscan_advance(StringLexer *scanner);
+ int stringscan_gettok(StringLexer *scanner);
+ void _push(PCCTS_AST **st, int *sp, PCCTS_AST *e);
+ PCCTS_AST *_pop(PCCTS_AST **st, int *sp);
+ int match_partial(PCCTS_AST *t, PCCTS_AST *u);
+ int scanmatch(ScanAST *t, PCCTS_AST **labels[], int *n);
+ void scanast_free(ScanAST *t);
+ ScanAST *new_scanast(int tok);
+ void stringparser_match(StringParser *parser, int type);
+ virtual PCCTS_AST *deepCopyBushy();
+
+public:
+ PCCTS_AST() {;}
+ virtual ~PCCTS_AST() {;}
+
+ /* This group must be defined for SORCERER to work correctly */
+ virtual PCCTS_AST *right() = 0;
+ virtual PCCTS_AST *down() = 0;
+ virtual void setRight(PCCTS_AST *t) = 0;
+ virtual void setDown(PCCTS_AST *t) = 0;
+// we define these so ANTLR doesn't have to
+ virtual int type() { return 0; }
+ virtual void setType(int /*t MR23 */) {;}
+ virtual PCCTS_AST *shallowCopy() {panic("no shallowCopy() defined"); return NULL;}
+
+ /* These are not needed by ANTLR, but are support functions */
+ virtual PCCTS_AST *deepCopy(); // used by SORCERER in transform mode
+ virtual void addChild(PCCTS_AST *t);
+ virtual void lisp_action(FILE * /*f MR23 */) {;}
+ virtual void lisp(FILE *f);
+ static PCCTS_AST *make(PCCTS_AST *rt, ...);
+ virtual PCCTS_AST *ast_find_all(PCCTS_AST *u, PCCTS_AST **cursor);
+ virtual int match(PCCTS_AST *u);
+ virtual void insert_after(PCCTS_AST *b);
+ virtual void append(PCCTS_AST *b);
+ virtual PCCTS_AST *tail();
+ virtual PCCTS_AST *bottom();
+ static PCCTS_AST *cut_between(PCCTS_AST *a, PCCTS_AST *b);
+// virtual SList *to_slist();
+ virtual void tfree();
+ int ast_scan(char *templ, ...);
+ virtual int nsiblings();
+ virtual PCCTS_AST *sibling_index(int i);
+
+ void require(int e,const char *err){ if ( !e ) panic(err); } /* MR20 const */
+ virtual void panic(const char *err) // MR20 const
+ { /* MR23 */ printMessage(stderr, "PCCTS_AST: %s\n", err); exit(PCCTS_EXIT_FAILURE); }
+ virtual int printMessage(FILE* pFile, const char* pFormat, ...); // MR23
+};
+
+#endif /* PCCTSAST_H */
diff --git a/Source/Pccts/h/SList.h b/Source/Pccts/h/SList.h
new file mode 100644
index 0000000..5b8bf97
--- /dev/null
+++ b/Source/Pccts/h/SList.h
@@ -0,0 +1,72 @@
+#ifndef SList_h
+#define SList_h
+
+/*
+ * SList.h
+ *
+ * SOFTWARE RIGHTS
+ *
+ * We reserve no LEGAL rights to SORCERER -- SORCERER is in the public
+ * domain. An individual or company may do whatever they wish with
+ * source code distributed with SORCERER or the code generated by
+ * SORCERER, including the incorporation of SORCERER, or its output, into
+ * commerical software.
+ *
+ * We encourage users to develop software with SORCERER. However, we do
+ * ask that credit is given to us for developing SORCERER. By "credit",
+ * we mean that if you incorporate our source code into one of your
+ * programs (commercial product, research project, or otherwise) that you
+ * acknowledge this fact somewhere in the documentation, research report,
+ * etc... If you like SORCERER and have developed a nice tool with the
+ * output, please mention that you developed it using SORCERER. In
+ * addition, we ask that this header remain intact in our source code.
+ * As long as these guidelines are kept, we expect to continue enhancing
+ * this system and expect to make other tools available as they are
+ * completed.
+ *
+ * PCCTS 1.33
+ * Terence Parr
+ * Parr Research Corporation
+ * with Purdue University and AHPCRC, University of Minnesota
+ * 1992-2000
+ */
+
+#include "pcctscfg.h"
+
+#include "pccts_stdio.h"
+#include "pccts_stdlib.h"
+
+PCCTS_NAMESPACE_STD
+
+#include "PCCTSAST.h"
+
+class PCCTS_AST;
+
+class SListNode {
+protected:
+ void *_elem; /* pointer to any kind of element */
+ SListNode *_next;
+public:
+ SListNode() {_elem=_next=NULL;}
+ virtual ~SListNode() {_elem=_next=NULL;}
+ void *elem() { return _elem; }
+ void setElem(void *e) { _elem = e; }
+ void setNext(SListNode *t) { _next = t; }
+ SListNode *next() { return _next; }
+};
+
+class SList {
+ SListNode *head, *tail;
+public:
+ SList() {head=tail=NULL;}
+ virtual ~SList() {head=tail=NULL;}
+ virtual void *iterate(SListNode **);
+ virtual void add(void *e);
+ virtual void lfree();
+ virtual PCCTS_AST *to_ast(SList list);
+ virtual void require(int e,char *err){ if ( !e ) panic(err); }
+ virtual void panic(char *err){ /* MR23 */ printMessage(stderr, "SList panic: %s\n", err); exit(PCCTS_EXIT_FAILURE); }
+ virtual int printMessage(FILE* pFile, const char* pFormat, ...); // MR23
+};
+
+#endif
diff --git a/Source/Pccts/h/antlr.h b/Source/Pccts/h/antlr.h
new file mode 100644
index 0000000..8066453
--- /dev/null
+++ b/Source/Pccts/h/antlr.h
@@ -0,0 +1,807 @@
+/* antlr.h
+ *
+ * SOFTWARE RIGHTS
+ *
+ * We reserve no LEGAL rights to the Purdue Compiler Construction Tool
+ * Set (PCCTS) -- PCCTS is in the public domain. An individual or
+ * company may do whatever they wish with source code distributed with
+ * PCCTS or the code generated by PCCTS, including the incorporation of
+ * PCCTS, or its output, into commerical software.
+ *
+ * We encourage users to develop software with PCCTS. However, we do ask
+ * that credit is given to us for developing PCCTS. By "credit",
+ * we mean that if you incorporate our source code into one of your
+ * programs (commercial product, research project, or otherwise) that you
+ * acknowledge this fact somewhere in the documentation, research report,
+ * etc... If you like PCCTS and have developed a nice tool with the
+ * output, please mention that you developed it using PCCTS. In
+ * addition, we ask that this header remain intact in our source code.
+ * As long as these guidelines are kept, we expect to continue enhancing
+ * this system and expect to make other tools available as they are
+ * completed.
+ *
+ * ANTLR 1.33
+ * Terence Parr
+ * Parr Research Corporation
+ * with Purdue University and AHPCRC, University of Minnesota
+ * 1989-2000
+ */
+
+#ifndef ANTLR_H
+#define ANTLR_H
+
+#include "pcctscfg.h"
+
+#include "pccts_stdio.h"
+
+/* turn off warnings for unreferenced labels */
+
+#ifdef _MSC_VER
+#pragma warning(disable:4102)
+#endif
+
+/*
+ * Define all of the stack setup and manipulation of $i, #i variables.
+ *
+ * Notes:
+ * The type 'Attrib' must be defined before entry into this .h file.
+ */
+
+
+#ifdef __USE_PROTOS
+#include "pccts_stdlib.h"
+#else
+#ifdef VAXC
+#include <stdlib.h>
+#else
+#include <malloc.h>
+#endif
+#endif
+#include "pccts_string.h"
+
+#if 0
+#include "set.h"
+#endif
+
+
+typedef int ANTLRTokenType;
+typedef unsigned char SetWordType;
+
+typedef char ANTLRChar;
+
+ /* G u e s s S t u f f */
+
+#ifdef ZZCAN_GUESS
+#ifndef ZZINF_LOOK
+#define ZZINF_LOOK
+#endif
+#endif
+
+#ifdef ZZCAN_GUESS
+typedef struct _zzjmp_buf {
+ jmp_buf state;
+ } zzjmp_buf;
+#endif
+
+
+/* can make this a power of 2 for more efficient lookup */
+
+#ifndef ZZLEXBUFSIZE
+#define ZZLEXBUFSIZE 8000 /* MR22 raise from 2k to 8k */
+#endif
+
+#define zzOvfChk \
+ if ( zzasp <= 0 ) \
+ { \
+ fprintf(stderr, zzStackOvfMsg, __FILE__, __LINE__); \
+ exit(PCCTS_EXIT_FAILURE); \
+ }
+
+#ifndef ZZA_STACKSIZE
+#define ZZA_STACKSIZE 400
+#endif
+#ifndef ZZAST_STACKSIZE
+#define ZZAST_STACKSIZE 400
+#endif
+
+#ifndef zzfailed_pred
+#ifdef ZZCAN_GUESS
+#define zzfailed_pred(_p,_hasuseraction,_useraction) \
+ if (zzguessing) { \
+ zzGUESS_FAIL; \
+ } else { \
+ zzfailed_pred_action(_p,_hasuseraction,_useraction); \
+ }
+#else
+#define zzfailed_pred(_p,_hasuseraction,_useraction) \
+ zzfailed_pred_action(_p,_hasuseraction,_useraction);
+#endif
+#endif
+
+/* MR23 Provide more control over failed predicate action
+ without any need for user to worry about guessing internals.
+ _hasuseraction == 0 => no user specified error action
+ _hasuseraction == 1 => user specified error action
+*/
+
+#ifndef zzfailed_pred_action
+#define zzfailed_pred_action(_p,_hasuseraction,_useraction) \
+ if (_hasuseraction) { _useraction } \
+ else { fprintf(stderr, "semantic error; failed predicate: '%s'\n",_p); }
+#endif
+
+/* MR19 zzchar_t additions */
+
+#ifdef LL_K
+#define LOOKAHEAD \
+ int zztokenLA[LL_K]; \
+ zzchar_t zztextLA[LL_K][ZZLEXBUFSIZE]; \
+ int zzlap = 0, zzlabase=0; /* labase only used for DEMAND_LOOK */
+#else
+#define LOOKAHEAD \
+ int zztoken;
+#endif
+
+#ifndef zzcr_ast
+#define zzcr_ast(ast,attr,tok,text)
+#endif
+
+#ifdef DEMAND_LOOK
+#define DemandLookData int zzdirty=1;
+#else
+#define DemandLookData
+#endif
+
+#ifndef zzUSER_GUESS_HOOK
+#define zzUSER_GUESS_HOOK(seqFrozen,zzrv)
+#endif
+
+#ifndef zzUSER_GUESS_DONE_HOOK
+#define zzUSER_GUESS_DONE_HOOK(seqFrozen)
+#endif
+
+ /* S t a t e S t u f f */
+
+#ifdef ZZCAN_GUESS
+#define zzGUESS_BLOCK zzantlr_state zzst; int zzrv; int zzGuessSeqFrozen;
+
+/* MR10 change zzGUESS: do zzGUESS_DONE when zzrv==1 after longjmp as in C++ mode */
+
+#define zzGUESS zzsave_antlr_state(&zzst); \
+ zzguessing = 1; \
+ zzGuessSeqFrozen=++zzGuessSeq; \
+ zzrv = setjmp(zzguess_start.state); \
+ zzUSER_GUESS_HOOK(zzGuessSeqFrozen,zzrv) \
+ if (zzrv) zzGUESS_DONE;
+#ifdef zzTRACE_RULES
+#define zzGUESS_FAIL { zzTraceGuessFail(); longjmp(zzguess_start.state, 1); }
+#else
+#define zzGUESS_FAIL longjmp(zzguess_start.state, 1)
+#endif
+
+/* MR10 change zzGUESS_DONE: zzrv=1 to simulate longjmp() return value as in C++ mode */
+
+#define zzGUESS_DONE { zzrestore_antlr_state(&zzst); zzrv=1; zzUSER_GUESS_DONE_HOOK(zzGuessSeqFrozen) }
+#define zzNON_GUESS_MODE if ( !zzguessing )
+#define zzGuessData \
+ zzjmp_buf zzguess_start; \
+ int zzguessing;
+#else
+#define zzGUESS_BLOCK
+#define zzGUESS
+#define zzGUESS_FAIL
+#define zzGUESS_DONE
+#define zzNON_GUESS_MODE
+#define zzGuessData
+#endif
+
+typedef struct _zzantlr_state {
+#ifdef ZZCAN_GUESS
+ zzjmp_buf guess_start;
+ int guessing;
+#endif
+ int asp;
+ int ast_sp;
+#ifdef ZZINF_LOOK
+ int inf_lap; /* not sure we need to save this one */
+ int inf_labase;
+ int inf_last;
+
+/* MR6 Gunnar Rxnning (gunnar@candleweb.no) */
+/* MR6 Additional state needs to be saved/restored */
+/* MR6 Matching changes in err.h */
+
+ int *inf_tokens; /* MR6 */
+ char **inf_text; /* MR6 */
+ char *inf_text_buffer; /* MR6 */
+ int *inf_line; /* MR6 */
+#endif
+#ifdef DEMAND_LOOK
+ int dirty;
+#endif
+
+#ifdef LL_K
+ int tokenLA[LL_K];
+ char textLA[LL_K][ZZLEXBUFSIZE];
+ int lap;
+ int labase;
+#else
+ int token;
+ char text[ZZLEXBUFSIZE];
+#endif
+#ifdef zzTRACE_RULES
+ int traceOptionValue; /* MR10 */
+ int traceGuessOptionValue; /* MR10 */
+ char *traceCurrentRuleName; /* MR10 */
+ int traceDepth; /* MR10 */
+#endif
+
+ } zzantlr_state;
+
+#ifdef zzTRACE_RULES
+extern int zzTraceOptionValueDefault;
+extern int zzTraceOptionValue;
+extern int zzTraceGuessOptionValue;
+extern char *zzTraceCurrentRuleName;
+extern int zzTraceDepth;
+#endif
+
+extern int zzGuessSeq; /* MR10 */
+extern int zzSyntaxErrCount; /* MR11 */
+extern int zzLexErrCount; /* MR11 */
+
+ /* I n f i n i t e L o o k a h e a d */
+
+
+#ifdef ZZINF_LOOK
+#define InfLookData \
+ int *zzinf_tokens; \
+ char **zzinf_text; \
+ char *zzinf_text_buffer; \
+ int *zzinf_line; \
+ int zzinf_labase; \
+ int zzinf_last;
+#else
+#define InfLookData
+#endif
+
+#ifdef ZZINF_LOOK
+
+#ifndef ZZINF_DEF_TEXT_BUFFER_SIZE
+#define ZZINF_DEF_TEXT_BUFFER_SIZE 20000
+#endif
+#ifndef ZZINF_DEF_TOKEN_BUFFER_SIZE
+#define ZZINF_DEF_TOKEN_BUFFER_SIZE 2000
+#endif
+/* WARNING!!!!!!
+ * ZZINF_BUFFER_TEXT_CHUNK_SIZE must be > sizeof(text) largest possible token.
+ */
+#ifndef ZZINF_BUFFER_TEXT_CHUNK_SIZE
+#define ZZINF_BUFFER_TEXT_CHUNK_SIZE 5000
+#endif
+#ifndef ZZINF_BUFFER_TOKEN_CHUNK_SIZE
+#define ZZINF_BUFFER_TOKEN_CHUNK_SIZE 1000
+#endif
+
+#if ZZLEXBUFSIZE > ZZINF_BUFFER_TEXT_CHUNK_SIZE
+#define ZZINF_BUFFER_TEXT_CHUNK_SIZE ZZLEXBUFSIZE+5
+#endif
+
+/* make inf_look user-access macros */
+#ifdef LL_K
+#define ZZINF_LA_VALID(i) (((zzinf_labase+i-1)-LL_K+1) <= zzinf_last)
+#define ZZINF_LA(i) zzinf_tokens[(zzinf_labase+i-1)-LL_K+1]
+#define ZZINF_LATEXT(i) zzinf_text[(zzinf_labase+i-1)-LL_K+1]
+/* MR6 In 1.33 vanilla the #define ZZINF_LINE(i) is was commented out */
+#define ZZINF_LINE(i) zzinf_line[(zzinf_labase+i-1)-LL_K+1]
+#else
+#define ZZINF_LA_VALID(i) (((zzinf_labase+i-1)) <= zzinf_last)
+#define ZZINF_LA(i) zzinf_tokens[(zzinf_labase+i-1)]
+#define ZZINF_LATEXT(i) zzinf_text[(zzinf_labase+i-1)]
+#endif
+
+#define inf_zzgettok _inf_zzgettok()
+extern void _inf_zzgettok();
+
+#endif /* ZZINF_LOOK */
+
+
+#ifdef LL_K
+
+#ifdef __USE_PROTOS
+#define ANTLR_INFO \
+ Attrib zzempty_attr(void) {static Attrib a; return a;} \
+ Attrib zzconstr_attr(int _tok, char *_text) \
+ {Attrib a; zzcr_attr((&a),_tok,_text); return a;} \
+ int zzasp=ZZA_STACKSIZE; \
+ char zzStackOvfMsg[]="fatal: attrib/AST stack overflow %s(%d)!\n"; \
+ Attrib zzaStack[ZZA_STACKSIZE]; DemandLookData \
+ InfLookData \
+ zzGuessData
+#else
+#define ANTLR_INFO \
+ Attrib zzempty_attr() {static Attrib a; return a;} \
+ Attrib zzconstr_attr(_tok, _text) int _tok; char *_text; \
+ {Attrib a; zzcr_attr((&a),_tok,_text); return a;} \
+ int zzasp=ZZA_STACKSIZE; \
+ char zzStackOvfMsg[]="fatal: attrib/AST stack overflow %s(%d)!\n"; \
+ Attrib zzaStack[ZZA_STACKSIZE]; DemandLookData \
+ InfLookData \
+ zzGuessData
+#endif
+
+#else
+
+#ifdef __USE_PROTOS
+#define ANTLR_INFO \
+ Attrib zzempty_attr(void) {static Attrib a; return a;} \
+ Attrib zzconstr_attr(int _tok, char *_text) \
+ {Attrib a; zzcr_attr((&a),_tok,_text); return a;} \
+ int zzasp=ZZA_STACKSIZE; \
+ char zzStackOvfMsg[]="fatal: attrib/AST stack overflow %s(%d)!\n"; \
+ Attrib zzaStack[ZZA_STACKSIZE]; DemandLookData \
+ InfLookData \
+ zzGuessData
+#else
+#define ANTLR_INFO \
+ Attrib zzempty_attr() {static Attrib a; return a;} \
+ Attrib zzconstr_attr(_tok, _text) int _tok; char *_text; \
+ {Attrib a; zzcr_attr((&a),_tok,_text); return a;} \
+ int zzasp=ZZA_STACKSIZE; \
+ char zzStackOvfMsg[]="fatal: attrib/AST stack overflow %s(%d)!\n"; \
+ Attrib zzaStack[ZZA_STACKSIZE]; DemandLookData \
+ InfLookData \
+ zzGuessData
+#endif
+
+#endif /* LL_k */
+
+
+#ifdef ZZINF_LOOK
+
+#ifdef LL_K
+#ifdef DEMAND_LOOK
+#define zzPrimeLookAhead {zzdirty=LL_K; zzlap = zzlabase = 0;}
+#else
+#define zzPrimeLookAhead {zzlap = zzlabase = 0; zzfill_inf_look();\
+ {int _i; for(_i=1;_i<=LL_K; _i++) \
+ {zzCONSUME;} zzlap = zzlabase = 0;}}
+#endif
+
+#else /* LL_K */
+
+#ifdef DEMAND_LOOK
+#define zzPrimeLookAhead zzfill_inf_look(); zzdirty=1
+#else
+#define zzPrimeLookAhead zzfill_inf_look(); inf_zzgettok
+
+#endif
+#endif /* LL_K */
+
+#else /* ZZINF_LOOK */
+
+#ifdef LL_K
+#ifdef DEMAND_LOOK
+#define zzPrimeLookAhead {zzdirty=LL_K; zzlap = zzlabase = 0;}
+#else
+#define zzPrimeLookAhead {int _i; zzlap = 0; for(_i=1;_i<=LL_K; _i++) \
+ {zzCONSUME;} zzlap = 0;}
+#endif
+
+#else
+
+#ifdef DEMAND_LOOK
+#define zzPrimeLookAhead zzdirty=1
+#else
+#define zzPrimeLookAhead zzgettok()
+#endif
+#endif /* LL_K */
+
+#endif /* ZZINF_LOOK */
+
+
+#ifdef LL_K
+#define zzenterANTLRs(s) \
+ zzlextext = &(zztextLA[0][0]); zzrdstr( s ); zzPrimeLookAhead;
+#define zzenterANTLRf(f) \
+ zzlextext = &(zztextLA[0][0]); zzrdfunc( f ); zzPrimeLookAhead;
+#define zzenterANTLR(f) \
+ zzlextext = &(zztextLA[0][0]); zzrdstream( f ); zzPrimeLookAhead;
+#ifdef ZZINF_LOOK
+#define zzleaveANTLR(f) free(zzinf_text_buffer); free(zzinf_text); free(zzinf_tokens); free(zzinf_line);
+#define zzleaveANTLRf(f) free(zzinf_text_buffer); free(zzinf_text); free(zzinf_tokens); free(zzinf_line);
+#define zzleaveANTLRs(f) free(zzinf_text_buffer); free(zzinf_text); free(zzinf_tokens); free(zzinf_line);
+#else
+#define zzleaveANTLR(f)
+#define zzleaveANTLRf(f)
+#define zzleaveANTLRs(f)
+#endif
+
+#else
+
+#define zzenterANTLRs(s) \
+ {static char zztoktext[ZZLEXBUFSIZE]; \
+ zzlextext = zztoktext; zzrdstr( s ); zzPrimeLookAhead;}
+#define zzenterANTLRf(f) \
+ {static char zztoktext[ZZLEXBUFSIZE]; \
+ zzlextext = zztoktext; zzrdfunc( f ); zzPrimeLookAhead;}
+#define zzenterANTLR(f) \
+ {static char zztoktext[ZZLEXBUFSIZE]; \
+ zzlextext = zztoktext; zzrdstream( f ); zzPrimeLookAhead;}
+#ifdef ZZINF_LOOK
+#define zzleaveANTLR(f) free(zzinf_text_buffer); free(zzinf_text); free(zzinf_tokens); free(zzinf_line);
+#define zzleaveANTLRf(f) free(zzinf_text_buffer); free(zzinf_text); free(zzinf_tokens); free(zzinf_line);
+#define zzleaveANTLRs(f) free(zzinf_text_buffer); free(zzinf_text); free(zzinf_tokens); free(zzinf_line);
+#else
+#define zzleaveANTLR(f)
+#define zzleaveANTLRf(f)
+#define zzleaveANTLRs(f)
+#endif
+
+#endif
+
+/* MR19 Paul D. Smith (psmith@baynetworks.com)
+ Need to adjust AST stack pointer at exit.
+ Referenced in ANTLRx macros.
+*/
+
+#ifdef GENAST
+#define ZZAST_ADJUST ++zzast_sp;
+#else
+#define ZZAST_ADJUST
+#endif
+
+#define ANTLR(st, f) zzbufsize = ZZLEXBUFSIZE; \
+ zzenterANTLR(f); \
+ { \
+ zzBLOCK(zztasp1); \
+ st; /* ++zzasp; Removed MR20 G. Hobbelt */ \
+ /* ZZAST_ADJUST Removed MR20 G. Hobbelt */ \
+ /* MR20 G. Hobbelt. Kill the top' attribute (+AST stack corr.) */ \
+ zzEXIT_ANTLR(zztasp1 + 1); \
+ } \
+ zzleaveANTLR(f);
+
+#define ANTLRm(st, f, _m) zzbufsize = ZZLEXBUFSIZE; \
+ zzmode(_m); \
+ zzenterANTLR(f); \
+ { \
+ zzBLOCK(zztasp1); \
+ st; /* ++zzasp; Removed MR20 G. Hobbelt */ \
+ /* ZZAST_ADJUST Removed MR20 G. Hobbelt */ \
+ /* MR20 G. Hobbelt. Kill the top' attribute (+AST stack corr.) */ \
+ zzEXIT_ANTLR(zztasp1 + 1); \
+ } \
+ zzleaveANTLR(f);
+
+#define ANTLRf(st, f) zzbufsize = ZZLEXBUFSIZE; \
+ zzenterANTLRf(f); \
+ { \
+ zzBLOCK(zztasp1); \
+ st; /* ++zzasp; Removed MR20 G. Hobbelt */ \
+ /* ZZAST_ADJUST Removed MR20 G. Hobbelt */ \
+ /* MR20 G. Hobbelt. Kill the top' attribute (+AST stack corr.) */ \
+ zzEXIT_ANTLR(zztasp1 + 1); \
+ } \
+ zzleaveANTLRf(f);
+
+#define ANTLRs(st, s) zzbufsize = ZZLEXBUFSIZE; \
+ zzenterANTLRs(s); \
+ { \
+ zzBLOCK(zztasp1); \
+ st; /* ++zzasp; Removed MR20 G. Hobbelt */ \
+ /* ZZAST_ADJUST Removed MR20 G. Hobbelt */ \
+ /* MR20 G. Hobbelt. Kill the top' attribute (+AST stack corr.) */ \
+ zzEXIT_ANTLR(zztasp1 + 1); \
+ } \
+ zzleaveANTLRs(s);
+
+#ifdef LL_K
+#define zztext (&(zztextLA[zzlap][0]))
+#else
+#define zztext zzlextext
+#endif
+
+
+ /* A r g u m e n t A c c e s s */
+
+#define zzaCur (zzaStack[zzasp])
+#define zzaRet (*zzaRetPtr)
+#define zzaArg(v,n) zzaStack[v-n]
+#define zzMakeAttr { zzNON_GUESS_MODE {zzOvfChk; --zzasp; zzcr_attr(&(zzaStack[zzasp]),LA(1),LATEXT(1));}}
+#ifdef zzdef0
+#define zzMake0 { zzOvfChk; --zzasp; zzdef0(&(zzaStack[zzasp]));}
+#else
+#define zzMake0 { zzOvfChk; --zzasp;}
+#endif
+#define zzaPush(_v) { zzOvfChk; zzaStack[--zzasp] = _v;}
+#ifndef zzd_attr
+#define zzREL(t) zzasp=(t); /* Restore state of stack */
+#else
+#define zzREL(t) for (; zzasp<(t); zzasp++) \
+ { zzd_attr(&(zzaStack[zzasp])); }
+#endif
+
+
+#define zzsetmatch(_es,_tokclassErrset) \
+ if ( !_zzsetmatch(_es, &zzBadText, &zzMissText, &zzMissTok, &zzBadTok, &zzMissSet, _tokclassErrset) ) goto fail; /* MR23 */
+
+#ifdef ZZCAN_GUESS
+#define zzsetmatch_wsig(_es, handler) \
+ if ( !_zzsetmatch_wsig(_es) ) if (zzguessing) { zzGUESS_FAIL; } else {_signal=MismatchedToken; goto handler;}
+#else
+#define zzsetmatch_wsig(_es, handler) \
+ if ( !_zzsetmatch_wsig(_es) ) {_signal=MismatchedToken; goto handler;}
+#endif
+
+#ifdef __USE_PROTOS
+extern int _zzsetmatch(SetWordType *, char **, char **, int *, int *, SetWordType **, SetWordType * /* MR23 */);
+extern int _zzsetmatch_wsig(SetWordType *);
+#else
+extern int _zzsetmatch();
+extern int _zzsetmatch_wsig();
+#endif
+
+#define zzmatch(_t) \
+ if ( !_zzmatch(_t, &zzBadText, &zzMissText, &zzMissTok, &zzBadTok, &zzMissSet) ) goto fail;
+
+#ifdef ZZCAN_GUESS
+#define zzmatch_wsig(_t,handler) \
+ if ( !_zzmatch_wsig(_t) ) if (zzguessing) { zzGUESS_FAIL; } else {_signal=MismatchedToken; goto handler;}
+#else
+#define zzmatch_wsig(_t,handler) \
+ if ( !_zzmatch_wsig(_t) ) {_signal=MismatchedToken; goto handler;}
+#endif
+
+#ifdef __USE_PROTOS
+extern int _zzmatch(int, char **, char **, int *, int *, SetWordType **);
+extern int _zzmatch_wsig(int);
+#else
+extern int _zzmatch();
+extern int _zzmatch_wsig();
+#endif
+
+#define zzmatch_wdfltsig(_t,_f) \
+ if ( !_zzmatch_wdfltsig(_t,_f) ) _signal=MismatchedToken;
+#define zzsetmatch_wdfltsig(tw,tt,wf) \
+ if ( !_zzsetmatch_wdfltsig(tw,tt,wf) ) _signal=MismatchedToken;
+
+#ifdef __USE_PROTOS
+extern int _zzmatch_wdfltsig(int, SetWordType *);
+extern int _zzsetmatch_wdfltsig(SetWordType *tokensWanted,
+ int tokenTypeOfSet,
+ SetWordType *whatFollows);
+#else
+extern int _zzmatch_wdfltsig();
+extern int _zzsetmatch_wdfltsig();
+#endif
+
+#ifdef GENAST
+#define zzRULE Attrib *zzaRetPtr = &(zzaStack[zzasp-1]); \
+ SetWordType *zzMissSet=NULL; int zzMissTok=0; \
+ int zzBadTok=0; char *zzBadText=""; \
+ int zzErrk=1,zzpf=0; \
+ zzTRACEdata \
+ char *zzMissText=""; zzASTVars
+#else
+#define zzRULE Attrib *zzaRetPtr = &(zzaStack[zzasp-1]); \
+ int zzBadTok=0; char *zzBadText=""; \
+ int zzErrk=1,zzpf=0; \
+ zzTRACEdata \
+ SetWordType *zzMissSet=NULL; int zzMissTok=0; char *zzMissText=""
+#endif
+
+#ifdef GENAST
+#define zzBLOCK(i) int i = zzasp - 1; int zztsp = zzast_sp
+#define zzEXIT(i) zzREL(i); zzastREL; zzNON_GUESS_MODE { zzastPush(*_root); }
+#define zzEXIT_ANTLR(i) zzREL(i); zzastREL /* [i_a] added as we want this for the ANTLRx() macros */
+#define zzLOOP(i) zzREL(i); zzastREL
+#else
+#define zzBLOCK(i) int i = zzasp - 1
+#define zzEXIT(i) zzREL(i)
+#define zzEXIT_ANTLR(i) zzREL(i) /* [i_a] added as we want this for the ANTLRx() macros */
+#define zzLOOP(i) zzREL(i)
+#endif
+
+#ifdef LL_K
+
+#ifdef DEMAND_LOOK
+#define LOOK(_k) {int i,stop=_k-(LL_K-zzdirty); for (i=1; i<=stop; i++) \
+ zzCONSUME;}
+#define zzCONSUME {zzgettok(); zzdirty--; \
+ zzlap = (zzlap+1)&(LL_K-1); \
+ zzlextext = &(zztextLA[zzlap][0]);}
+#else
+#ifdef ZZINF_LOOK
+#define zzCONSUME {inf_zzgettok; \
+ zzlap = (zzlap+1)&(LL_K-1); \
+ zzlextext = &(zztextLA[zzlap][0]); \
+ }
+#else
+#define zzCONSUME {zzgettok(); \
+ zzlap = (zzlap+1)&(LL_K-1); \
+ zzlextext = &(zztextLA[zzlap][0]);}
+#endif /* ZZINF_LOOK */
+#endif /* DEMAND_LOOK */
+
+#else /* LL_K */
+
+#ifdef DEMAND_LOOK
+#define LOOK(_k) if ( zzdirty) zzCONSUME;
+#ifdef ZZINF_LOOK
+#define zzCONSUME inf_zzgettok; zzdirty=0;
+#else
+#define zzCONSUME zzgettok(); zzdirty=0;
+#endif /* ZZINF_LOOK */
+
+#else /* DEMAND_LOOK */
+
+#ifdef ZZINF_LOOK
+#define zzCONSUME inf_zzgettok
+#else
+#define zzCONSUME zzgettok();
+#endif
+
+#endif /* DEMAND_LOOK */
+
+#endif /* LL_K */
+
+#ifdef LL_K
+#define NLA zztokenLA[zzlap&(LL_K-1)] /* --> next LA */
+#define NLATEXT zztextLA[zzlap&(LL_K-1)] /* --> next text of LA */
+#ifdef DEMAND_LOOK
+#define LA(i) zztokenLA[(zzlabase+(i)-1)&(LL_K-1)]
+#define LATEXT(i) (&(zztextLA[(zzlabase+(i)-1)&(LL_K-1)][0]))
+#else
+#define LA(i) zztokenLA[(zzlap+(i)-1)&(LL_K-1)]
+#define LATEXT(i) (&(zztextLA[(zzlap+(i)-1)&(LL_K-1)][0]))
+#endif
+#else
+#define NLA zztoken
+#define NLATEXT zztext
+#define LA(i) zztoken
+#define LATEXT(i) zztext
+#endif
+
+
+ /* S t a n d a r d S i g n a l s */
+
+#define NoSignal 0
+#define MismatchedToken 1
+#define NoViableAlt 2
+#define NoSemViableAlt 3
+
+/* MR7 Allow more control over signalling */
+/* by adding "Unwind" and "zzsetSignal" */
+
+#define Unwind 4
+#define zzsetSignal(newValue) *_retsignal=_signal=(newValue)
+#define zzsuppressSignal *_retsignal=_signal=0
+#define zzexportSignal *_retsignal=_signal
+
+ /* F u n c t i o n T r a c i n g */
+
+#ifndef zzTRACE_RULES
+#define zzTRACEdata
+#else
+#ifndef zzTRACEdata
+#define zzTRACEdata ANTLRChar *zzTracePrevRuleName = NULL;
+#endif
+#endif
+
+#ifndef zzTRACEIN
+#define zzTRACEIN(r) zzTracePrevRuleName=zzTraceCurrentRuleName;zzTraceIn(r);
+#endif
+#ifndef zzTRACEOUT
+#define zzTRACEOUT(r) zzTraceOut(r);zzTraceCurrentRuleName=zzTracePrevRuleName;
+#endif
+
+/* MR19 zzchar_t additions */
+
+#ifndef zzchar_t
+#ifdef ZZWCHAR_T
+#define zzchar_t wchar_t
+#else
+#define zzchar_t char
+#endif
+#endif
+
+
+/* MR26 */
+
+#ifdef PCCTS_USE_STDARG
+extern void zzFAIL(int k, ...);
+#else
+extern void zzFAIL();
+#endif
+ /* E x t e r n D e f s */
+
+#ifdef __USE_PROTOS
+extern Attrib zzempty_attr(void);
+extern Attrib zzconstr_attr(int, char *);
+extern void zzsyn(char *, int, char *, SetWordType *, int, int, char *);
+extern int zzset_el(unsigned, SetWordType *);
+extern int zzset_deg(SetWordType *);
+extern void zzedecode(SetWordType *);
+
+extern void zzresynch(SetWordType *, SetWordType);
+extern void zzsave_antlr_state(zzantlr_state *);
+extern void zzrestore_antlr_state(zzantlr_state *);
+extern void zzfill_inf_look(void);
+extern void zzconsumeUntil(SetWordType *st); /* MR7 */
+extern void zzconsumeUntilToken(int t); /* MR7 */
+extern void zzTraceIn(char * ruleName); /* MR10 */
+extern void zzTraceOut(char * ruleName); /* MR10 */
+extern int zzTraceOption(int delta); /* MR10 */
+extern int zzTraceGuessOption(int delta); /* MR10 */
+extern void zzTraceReset(void); /* MR10 */
+extern void zzTraceGuessFail(void); /* MR10 */
+#ifdef EXCEPTION_HANDLING
+extern void zzdflthandlers(int, int *);
+#endif
+#else
+extern Attrib zzempty_attr();
+extern Attrib zzconstr_attr();
+extern void zzsyn();
+extern int zzset_el();
+extern int zzset_deg();
+extern void zzedecode();
+extern void zzresynch();
+extern void zzsave_antlr_state();
+extern void zzrestore_antlr_state();
+extern void zzfill_inf_look();
+extern void zzconsumeUntil(); /* MR7 */
+extern void zzconsumeUntilToken(); /* MR7 */
+extern void zzTraceIn(); /* MR10 */
+extern void zzTraceOut(); /* MR10 */
+extern int zzTraceOption(); /* MR10 */
+extern int zzTraceGuessOption(); /* MR10 */
+extern void zzTraceReset(); /* MR10 */
+extern void zzTraceGuessFail(); /* MR10 */
+#ifdef EXCEPTION_HANDLING
+extern void zzdflthandlers();
+#endif
+#endif
+
+ /* G l o b a l V a r i a b l e s */
+
+/* Define a parser; user should do a "#parser myname" in their grammar file */
+/*extern struct pccts_parser zzparser;*/
+
+extern char *zztokens[];
+#ifdef LL_K
+extern int zztokenLA[];
+extern zzchar_t zztextLA[][ZZLEXBUFSIZE];
+extern int zzlap;
+extern int zzlabase;
+#else
+extern int zztoken;
+#endif
+
+extern char zzStackOvfMsg[];
+extern int zzasp;
+extern Attrib zzaStack[];
+#ifdef ZZINF_LOOK
+extern int *zzinf_tokens;
+extern char **zzinf_text;
+extern char *zzinf_text_buffer;
+extern int *zzinf_line;
+extern int zzinf_labase;
+extern int zzinf_last;
+#endif
+#ifdef DEMAND_LOOK
+extern int zzdirty;
+#endif
+#ifdef ZZCAN_GUESS
+extern int zzguessing;
+extern zzjmp_buf zzguess_start;
+#endif
+
+/* Define global veriables that refer to values exported by the scanner.
+ * These declarations duplicate those in dlgdef.h, but are needed
+ * if ANTLR is not to generate a .dlg file (-gx); PS, this is a hack.
+ */
+extern zzchar_t *zzlextext; /* text of most recently matched token */
+extern int zzbufsize; /* how long zzlextext is */
+
+#endif
diff --git a/Source/Pccts/h/ast.c b/Source/Pccts/h/ast.c
new file mode 100644
index 0000000..9326ae1
--- /dev/null
+++ b/Source/Pccts/h/ast.c
@@ -0,0 +1,345 @@
+/* Abstract syntax tree manipulation functions
+ *
+ * SOFTWARE RIGHTS
+ *
+ * We reserve no LEGAL rights to the Purdue Compiler Construction Tool
+ * Set (PCCTS) -- PCCTS is in the public domain. An individual or
+ * company may do whatever they wish with source code distributed with
+ * PCCTS or the code generated by PCCTS, including the incorporation of
+ * PCCTS, or its output, into commerical software.
+ *
+ * We encourage users to develop software with PCCTS. However, we do ask
+ * that credit is given to us for developing PCCTS. By "credit",
+ * we mean that if you incorporate our source code into one of your
+ * programs (commercial product, research project, or otherwise) that you
+ * acknowledge this fact somewhere in the documentation, research report,
+ * etc... If you like PCCTS and have developed a nice tool with the
+ * output, please mention that you developed it using PCCTS. In
+ * addition, we ask that this header remain intact in our source code.
+ * As long as these guidelines are kept, we expect to continue enhancing
+ * this system and expect to make other tools available as they are
+ * completed.
+ *
+ * ANTLR 1.33
+ * Terence Parr
+ * Parr Research Corporation
+ * with Purdue University and AHPCRC, University of Minnesota
+ * 1989-2000
+ */
+
+#include "pcctscfg.h"
+
+#ifdef PCCTS_USE_STDARG
+#include "pccts_stdarg.h"
+#else
+#include <varargs.h>
+#endif
+
+/* ensure that tree manipulation variables are current after a rule
+ * reference
+ */
+
+void
+#ifdef __USE_PROTOS
+zzlink(AST **_root, AST **_sibling, AST **_tail)
+#else
+zzlink(_root, _sibling, _tail)
+AST **_root, **_sibling, **_tail;
+#endif
+{
+ if ( *_sibling == NULL ) return;
+ if ( *_root == NULL ) *_root = *_sibling;
+ else if ( *_root != *_sibling ) (*_root)->down = *_sibling;
+ if ( *_tail==NULL ) *_tail = *_sibling;
+ while ( (*_tail)->right != NULL ) *_tail = (*_tail)->right;
+}
+
+AST *
+#ifdef __USE_PROTOS
+zzastnew(void)
+#else
+zzastnew()
+#endif
+{
+ AST *p = (AST *) calloc(1, sizeof(AST));
+ if ( p == NULL ) fprintf(stderr,"%s(%d): cannot allocate AST node\n",__FILE__,__LINE__);
+ return p;
+}
+
+/* add a child node to the current sibling list */
+void
+#ifdef __USE_PROTOS
+zzsubchild(AST **_root, AST **_sibling, AST **_tail)
+#else
+zzsubchild(_root, _sibling, _tail)
+AST **_root, **_sibling, **_tail;
+#endif
+{
+ AST *n;
+ zzNON_GUESS_MODE {
+ n = zzastnew();
+#ifdef DEMAND_LOOK
+ zzcr_ast(n, &(zzaCur), LA(0), LATEXT(0));
+#else
+ zzcr_ast(n, &(zzaCur), LA(1), LATEXT(1));
+#endif
+ zzastPush( n );
+ if ( *_tail != NULL ) (*_tail)->right = n;
+ else {
+ *_sibling = n;
+ if ( *_root != NULL ) (*_root)->down = *_sibling;
+ }
+ *_tail = n;
+ if ( *_root == NULL ) *_root = *_sibling;
+ }
+}
+
+/* make a new AST node. Make the newly-created
+ * node the root for the current sibling list. If a root node already
+ * exists, make the newly-created node the root of the current root.
+ */
+void
+#ifdef __USE_PROTOS
+zzsubroot(AST **_root, AST **_sibling, AST **_tail)
+#else
+zzsubroot(_root, _sibling, _tail)
+AST **_root, **_sibling, **_tail;
+#endif
+{
+ AST *n;
+ zzNON_GUESS_MODE {
+ n = zzastnew();
+#ifdef DEMAND_LOOK
+ zzcr_ast(n, &(zzaCur), LA(0), LATEXT(0));
+#else
+ zzcr_ast(n, &(zzaCur), LA(1), LATEXT(1));
+#endif
+ zzastPush( n );
+ if ( *_root != NULL )
+ if ( (*_root)->down == *_sibling ) *_sibling = *_tail = *_root;
+ *_root = n;
+ (*_root)->down = *_sibling;
+ }
+}
+
+/* Apply function to root then each sibling
+ * example: print tree in child-sibling LISP-format (AST has token field)
+ *
+ * void show(tree)
+ * AST *tree;
+ * {
+ * if ( tree == NULL ) return;
+ * printf(" %s", zztokens[tree->token]);
+ * }
+ *
+ * void before() { printf(" ("); }
+ * void after() { printf(" )"); }
+ *
+ * LISPdump() { zzpre_ast(tree, show, before, after); }
+ *
+ */
+void
+#ifdef __USE_PROTOS
+zzpre_ast(
+ AST *tree,
+ void (*func)(AST *), /* apply this to each tree node */
+ void (*before)(AST *), /* apply this to root of subtree before preordering it */
+ void (*after)(AST *)) /* apply this to root of subtree after preordering it */
+#else
+zzpre_ast(tree, func, before, after)
+AST *tree;
+void (*func)(), /* apply this to each tree node */
+ (*before)(), /* apply this to root of subtree before preordering it */
+ (*after)(); /* apply this to root of subtree after preordering it */
+#endif
+{
+ while ( tree!= NULL )
+ {
+ if ( tree->down != NULL ) (*before)(tree);
+ (*func)(tree);
+ zzpre_ast(tree->down, func, before, after);
+ if ( tree->down != NULL ) (*after)(tree);
+ tree = tree->right;
+ }
+}
+
+/* free all AST nodes in tree; apply func to each before freeing */
+
+#if 0
+////void
+////#ifdef __USE_PROTOS
+////zzfree_ast(AST *tree)
+////#else
+////zzfree_ast(tree)
+////AST *tree;
+////#endif
+////{
+//// if ( tree == NULL ) return;
+//// zzfree_ast( tree->down );
+//// zzfree_ast( tree->right );
+//// zztfree( tree );
+////}
+#endif
+
+/*
+ MR19 Optimize freeing of the following structure to limit recursion
+ SAKAI Kiyotaka (ksakai@isr.co.jp)
+*/
+
+/*
+ NULL o
+ / \
+ NULL o
+ / \
+ NULL NULL
+*/
+
+/*
+ MR21 Another refinement to replace recursion with iteration
+ NAKAJIMA Mutsuki (muc@isr.co.jp).
+*/
+
+void
+#ifdef __USE_PROTOS
+zzfree_ast(AST *tree)
+#else
+zzfree_ast(tree)
+AST *tree;
+#endif
+{
+
+ AST *otree;
+
+ if (tree == NULL) return;
+
+ while (tree->down == NULL || tree->right == NULL) {
+
+ if (tree->down == NULL && tree->right == NULL) {
+ zztfree(tree);
+ return;
+ }
+
+ otree = tree;
+ if (tree->down == NULL) {
+ tree = tree->right;
+ } else {
+ tree = tree->down;
+ }
+ zztfree( otree );
+ }
+
+ while (tree != NULL) {
+ zzfree_ast(tree->down);
+ otree = tree;
+ tree = otree->right;
+ zztfree(otree);
+ }
+}
+
+/* build a tree (root child1 child2 ... NULL)
+ * If root is NULL, simply make the children siblings and return ptr
+ * to 1st sibling (child1). If root is not single node, return NULL.
+ *
+ * Siblings that are actually siblins lists themselves are handled
+ * correctly. For example #( NULL, #( NULL, A, B, C), D) results
+ * in the tree ( NULL A B C D ).
+ *
+ * Requires at least two parameters with the last one being NULL. If
+ * both are NULL, return NULL.
+ */
+#ifdef PCCTS_USE_STDARG
+AST *zztmake(AST *rt, ...)
+#else
+AST *zztmake(va_alist)
+va_dcl
+#endif
+{
+ va_list ap;
+ register AST *child, *sibling=NULL, *tail=NULL /* MR20 */, *w;
+ AST *root;
+
+#ifdef PCCTS_USE_STDARG
+ va_start(ap, rt);
+ root = rt;
+#else
+ va_start(ap);
+ root = va_arg(ap, AST *);
+#endif
+
+ if ( root != NULL )
+ if ( root->down != NULL ) return NULL;
+ child = va_arg(ap, AST *);
+ while ( child != NULL )
+ {
+ for (w=child; w->right!=NULL; w=w->right) {;} /* find end of child */
+ if ( sibling == NULL ) {sibling = child; tail = w;}
+ else {tail->right = child; tail = w;}
+ child = va_arg(ap, AST *);
+ }
+ if ( root==NULL ) root = sibling;
+ else root->down = sibling;
+ va_end(ap);
+ return root;
+}
+
+/* tree duplicate */
+AST *
+#ifdef __USE_PROTOS
+zzdup_ast(AST *t)
+#else
+zzdup_ast(t)
+AST *t;
+#endif
+{
+ AST *u;
+
+ if ( t == NULL ) return NULL;
+ u = zzastnew();
+ *u = *t;
+#ifdef zzAST_DOUBLE
+ u->up = NULL; /* set by calling invocation */
+ u->left = NULL;
+#endif
+ u->right = zzdup_ast(t->right);
+ u->down = zzdup_ast(t->down);
+#ifdef zzAST_DOUBLE
+ if ( u->right!=NULL ) u->right->left = u;
+ if ( u->down!=NULL ) u->down->up = u;
+#endif
+ return u;
+}
+
+void
+#ifdef __USE_PROTOS
+zztfree(AST *t)
+#else
+zztfree(t)
+AST *t;
+#endif
+{
+#ifdef zzd_ast
+ zzd_ast( t );
+#endif
+ free( t );
+}
+
+#ifdef zzAST_DOUBLE
+/*
+ * Set the 'up', and 'left' pointers of all nodes in 't'.
+ * Initial call is double_link(your_tree, NULL, NULL).
+ */
+void
+#ifdef __USE_PROTOS
+zzdouble_link(AST *t, AST *left, AST *up)
+#else
+zzdouble_link(t, left, up)
+AST *t, *left, *up;
+#endif
+{
+ if ( t==NULL ) return;
+ t->left = left;
+ t->up = up;
+ zzdouble_link(t->down, NULL, t);
+ zzdouble_link(t->right, t, up);
+}
+#endif
diff --git a/Source/Pccts/h/ast.h b/Source/Pccts/h/ast.h
new file mode 100644
index 0000000..5ff84bd
--- /dev/null
+++ b/Source/Pccts/h/ast.h
@@ -0,0 +1,121 @@
+/* Abstract syntax tree
+ *
+ * Macros, definitions
+ *
+ * SOFTWARE RIGHTS
+ *
+ * We reserve no LEGAL rights to the Purdue Compiler Construction Tool
+ * Set (PCCTS) -- PCCTS is in the public domain. An individual or
+ * company may do whatever they wish with source code distributed with
+ * PCCTS or the code generated by PCCTS, including the incorporation of
+ * PCCTS, or its output, into commerical software.
+ *
+ * We encourage users to develop software with PCCTS. However, we do ask
+ * that credit is given to us for developing PCCTS. By "credit",
+ * we mean that if you incorporate our source code into one of your
+ * programs (commercial product, research project, or otherwise) that you
+ * acknowledge this fact somewhere in the documentation, research report,
+ * etc... If you like PCCTS and have developed a nice tool with the
+ * output, please mention that you developed it using PCCTS. In
+ * addition, we ask that this header remain intact in our source code.
+ * As long as these guidelines are kept, we expect to continue enhancing
+ * this system and expect to make other tools available as they are
+ * completed.
+ *
+ * ANTLR 1.33
+ * Terence Parr
+ * Parr Research Corporation
+ * with Purdue University and AHPCRC, University of Minnesota
+ * 1989-2000
+ */
+
+#ifndef ZZAST_H
+#define ZZAST_H
+
+#define zzastOvfChk \
+ if ( zzast_sp <= 0 ) \
+ { \
+ fprintf(stderr, zzStackOvfMsg, __FILE__, __LINE__); \
+ exit(PCCTS_EXIT_FAILURE); \
+ }
+
+#ifndef USER_DEFINED_AST
+#ifndef AST_FIELDS
+#define AST_FIELDS
+#endif
+
+typedef struct _ast {
+ struct _ast *right, *down;
+#ifdef zzAST_DOUBLE
+ struct _ast *left, *up;
+#endif
+ AST_FIELDS
+} AST;
+
+#else
+
+#ifdef zzAST_DOUBLE
+#define AST_REQUIRED_FIELDS struct _ast *right, *down, *left, *up;
+#else
+#define AST_REQUIRED_FIELDS struct _ast *right, *down;
+#endif
+
+#endif
+
+
+/* N o d e a c c e s s m a c r o s */
+#define zzchild(t) (((t)==NULL)? (AST *) NULL:(t->down)) /* MR19 */
+#define zzsibling(t) (((t)==NULL)? (AST *) NULL:(t->right)) /* MR19 */
+
+
+/* define global variables needed by #i stack */
+#define zzASTgvars \
+ AST *zzastStack[ZZAST_STACKSIZE]; \
+ int zzast_sp = ZZAST_STACKSIZE;
+
+#define zzASTVars AST *_ast = NULL, *_sibling = NULL, *_tail = NULL
+#define zzSTR ( (_tail==NULL)?(&_sibling):(&(_tail->right)) )
+#define zzastCur (zzastStack[zzast_sp])
+#define zzastArg(i) (zzastStack[zztsp-i])
+#define zzastPush(p) zzastOvfChk; zzastStack[--zzast_sp] = p;
+#define zzastDPush --zzast_sp
+#define zzastMARK zztsp=zzast_sp; /* Save state of stack */
+#define zzastREL zzast_sp=zztsp; /* Return state of stack */
+#define zzrm_ast {zzfree_ast(*_root); _tail = _sibling = (*_root)=NULL;}
+
+extern int zzast_sp;
+extern AST *zzastStack[];
+
+/* MR26 */
+
+#ifdef PCCTS_USE_STDARG
+AST *zztmake(AST *, ...);
+#else
+AST *zztmake();
+#endif
+
+#ifdef __USE_PROTOS
+void zzlink(AST **, AST **, AST **);
+void zzsubchild(AST **, AST **, AST **);
+void zzsubroot(AST **, AST **, AST **);
+void zzpre_ast(AST *, void (*)(AST *), void (*)(AST *), void (*)(AST *));
+void zzfree_ast(AST *);
+AST *zzdup_ast(AST *);
+void zztfree(AST *);
+void zzdouble_link(AST *, AST *, AST *);
+AST *zzastnew(void);
+
+#else
+
+void zzlink();
+AST *zzastnew();
+void zzsubchild();
+void zzsubroot();
+void zzpre_ast();
+void zzfree_ast();
+AST *zzdup_ast();
+void zztfree();
+void zzdouble_link();
+#endif
+
+#endif
diff --git a/Source/Pccts/h/charbuf.h b/Source/Pccts/h/charbuf.h
new file mode 100644
index 0000000..5f01c8b
--- /dev/null
+++ b/Source/Pccts/h/charbuf.h
@@ -0,0 +1,46 @@
+/* ANTLR attribute definition -- constant width text
+ *
+ * SOFTWARE RIGHTS
+ *
+ * We reserve no LEGAL rights to the Purdue Compiler Construction Tool
+ * Set (PCCTS) -- PCCTS is in the public domain. An individual or
+ * company may do whatever they wish with source code distributed with
+ * PCCTS or the code generated by PCCTS, including the incorporation of
+ * PCCTS, or its output, into commerical software.
+ *
+ * We encourage users to develop software with PCCTS. However, we do ask
+ * that credit is given to us for developing PCCTS. By "credit",
+ * we mean that if you incorporate our source code into one of your
+ * programs (commercial product, research project, or otherwise) that you
+ * acknowledge this fact somewhere in the documentation, research report,
+ * etc... If you like PCCTS and have developed a nice tool with the
+ * output, please mention that you developed it using PCCTS. In
+ * addition, we ask that this header remain intact in our source code.
+ * As long as these guidelines are kept, we expect to continue enhancing
+ * this system and expect to make other tools available as they are
+ * completed.
+ *
+ * ANTLR 1.33
+ * Terence Parr
+ * Parr Research Corporation
+ * with Purdue University and AHPCRC, University of Minnesota
+ * 1989-2000
+ */
+
+#ifndef ZZCHARBUF_H
+#define ZZCHARBUF_H
+
+#include "pcctscfg.h"
+
+#include "pccts_string.h"
+
+#ifndef D_TextSize
+#define D_TextSize 30
+#endif
+
+typedef struct { char text[D_TextSize]; } Attrib;
+
+#define zzcr_attr(a,tok,t) strncpy((a)->text, t, D_TextSize-1); \
+ (a)->text[D_TextSize-1] = '\0';
+
+#endif
diff --git a/Source/Pccts/h/charptr.c b/Source/Pccts/h/charptr.c
new file mode 100644
index 0000000..d3f80e6
--- /dev/null
+++ b/Source/Pccts/h/charptr.c
@@ -0,0 +1,58 @@
+/*
+ * SOFTWARE RIGHTS
+ *
+ * We reserve no LEGAL rights to the Purdue Compiler Construction Tool
+ * Set (PCCTS) -- PCCTS is in the public domain. An individual or
+ * company may do whatever they wish with source code distributed with
+ * PCCTS or the code generated by PCCTS, including the incorporation of
+ * PCCTS, or its output, into commerical software.
+ *
+ * We encourage users to develop software with PCCTS. However, we do ask
+ * that credit is given to us for developing PCCTS. By "credit",
+ * we mean that if you incorporate our source code into one of your
+ * programs (commercial product, research project, or otherwise) that you
+ * acknowledge this fact somewhere in the documentation, research report,
+ * etc... If you like PCCTS and have developed a nice tool with the
+ * output, please mention that you developed it using PCCTS. In
+ * addition, we ask that this header remain intact in our source code.
+ * As long as these guidelines are kept, we expect to continue enhancing
+ * this system and expect to make other tools available as they are
+ * completed.
+ *
+ * ANTLR 1.33
+ * Terence Parr
+ * Parr Research Corporation
+ * with Purdue University and AHPCRC, University of Minnesota
+ * 1989-2000
+ */
+
+#include "pcctscfg.h"
+
+#ifdef __STDC__
+#include "pccts_stdlib.h"
+#else
+#include <malloc.h>
+#endif
+#include "pccts_string.h"
+
+/* 133MR1 include stdio.h for fprintf in charptr.c */
+
+#include "pccts_stdio.h"
+
+/* 133MR1 include charptr.h for Attrib in charptr.c */
+
+#include "charptr.h"
+
+#ifdef __USE_PROTOS
+zzcr_attr(Attrib *a,int token,char *text)
+#else
+zzcr_attr(a,token,text)
+Attrib *a;
+int token;
+char *text;
+#endif
+{
+ *a = (char *) malloc(strlen(text)+1); /* MR6 */
+ if ( *a == NULL ) {fprintf(stderr, "zzcr_attr: out of memory!\n"); exit(-1);}
+ strcpy(*a, text);
+}
diff --git a/Source/Pccts/h/charptr.h b/Source/Pccts/h/charptr.h
new file mode 100644
index 0000000..e73da68
--- /dev/null
+++ b/Source/Pccts/h/charptr.h
@@ -0,0 +1,48 @@
+/*
+ *
+ * SOFTWARE RIGHTS
+ *
+ * We reserve no LEGAL rights to the Purdue Compiler Construction Tool
+ * Set (PCCTS) -- PCCTS is in the public domain. An individual or
+ * company may do whatever they wish with source code distributed with
+ * PCCTS or the code generated by PCCTS, including the incorporation of
+ * PCCTS, or its output, into commerical software.
+ *
+ * We encourage users to develop software with PCCTS. However, we do ask
+ * that credit is given to us for developing PCCTS. By "credit",
+ * we mean that if you incorporate our source code into one of your
+ * programs (commercial product, research project, or otherwise) that you
+ * acknowledge this fact somewhere in the documentation, research report,
+ * etc... If you like PCCTS and have developed a nice tool with the
+ * output, please mention that you developed it using PCCTS. In
+ * addition, we ask that this header remain intact in our source code.
+ * As long as these guidelines are kept, we expect to continue enhancing
+ * this system and expect to make other tools available as they are
+ * completed.
+ *
+ * ANTLR 1.33
+ * Terence Parr
+ * Parr Research Corporation
+ * with Purdue University and AHPCRC, University of Minnesota
+ * 1989-2000
+ */
+
+/*
+ * WARNING!!!!: charptr.h does NOT make copies and the
+ * memory is freed after the attribute scope exits.
+ */
+
+#ifndef ZZCHARPTR_H
+#define ZZCHARPTR_H
+
+typedef char *Attrib;
+#define zzdef0(a) {*(a)=NULL;}
+/* MR8 Jens Tingleff (jensting@imaginet.fr) */
+/* Set memory pointer to null after free() */
+#define zzd_attr(a) {if ( *(a)!=NULL ) {free(*(a)); *(a)=NULL; }; }
+
+#ifdef __STDC__
+extern zzcr_attr(Attrib *,int,char *);
+#endif
+
+#endif
diff --git a/Source/Pccts/h/config.h b/Source/Pccts/h/config.h
new file mode 100644
index 0000000..8aa50ad
--- /dev/null
+++ b/Source/Pccts/h/config.h
@@ -0,0 +1 @@
+#include "pcctscfg.h"
diff --git a/Source/Pccts/h/dlgauto.h b/Source/Pccts/h/dlgauto.h
new file mode 100644
index 0000000..db94cef
--- /dev/null
+++ b/Source/Pccts/h/dlgauto.h
@@ -0,0 +1,504 @@
+/* dlgauto.h automaton
+ *
+ * SOFTWARE RIGHTS
+ *
+ * We reserve no LEGAL rights to the Purdue Compiler Construction Tool
+ * Set (PCCTS) -- PCCTS is in the public domain. An individual or
+ * company may do whatever they wish with source code distributed with
+ * PCCTS or the code generated by PCCTS, including the incorporation of
+ * PCCTS, or its output, into commerical software.
+ *
+ * We encourage users to develop software with PCCTS. However, we do ask
+ * that credit is given to us for developing PCCTS. By "credit",
+ * we mean that if you incorporate our source code into one of your
+ * programs (commercial product, research project, or otherwise) that you
+ * acknowledge this fact somewhere in the documentation, research report,
+ * etc... If you like PCCTS and have developed a nice tool with the
+ * output, please mention that you developed it using PCCTS. In
+ * addition, we ask that this header remain intact in our source code.
+ * As long as these guidelines are kept, we expect to continue enhancing
+ * this system and expect to make other tools available as they are
+ * completed.
+ *
+ * ANTLR 1.33
+ * Will Cohen and Terence Parr
+ * Parr Research Corporation
+ * with Purdue University and AHPCRC, University of Minnesota
+ * 1989-2000
+ */
+
+#ifndef ZZDEFAUTO_H
+#define ZZDEFAUTO_H
+
+/* 10-Apr-97 133MR1 Uses __USE_PROTOS show should #include pcctscfg.h */
+
+#include "pcctscfg.h"
+
+zzchar_t *zzlextext; /* text of most recently matched token */
+zzchar_t *zzbegexpr; /* beginning of last reg expr recogn. */
+zzchar_t *zzendexpr; /* beginning of last reg expr recogn. */
+int zzbufsize = 0; /* number of characters in zzlextext */ /* MR7 */
+int zzbegcol = 0; /* column that first character of token is in*/
+int zzendcol = 0; /* column that last character of token is in */
+int zzline = 1; /* line current token is on */
+int zzreal_line=1; /* line of 1st portion of token that is not skipped */
+int zzchar; /* character to determine next state */
+int zzbufovf; /* indicates that buffer too small for text */
+int zzcharfull = 0;
+static zzchar_t *zznextpos;/* points to next available position in zzlextext*/
+static int zzclass;
+
+#ifdef __USE_PROTOS
+void zzerrstd(const char *);
+void (*zzerr)(const char *)=zzerrstd;/* pointer to error reporting function */
+extern int zzerr_in(void);
+static int (*zzfunc_in)(void) = zzerr_in; /* MR20 */
+#else
+void zzerrstd();
+void (*zzerr)()=zzerrstd; /* pointer to error reporting function */
+extern int zzerr_in();
+static int (*zzfunc_in)() = zzerr_in; /* MR20 */
+#endif
+
+static FILE *zzstream_in=0;
+static zzchar_t *zzstr_in=0;
+
+#ifdef USER_ZZMODE_STACK
+int zzauto = 0;
+#else
+static int zzauto = 0;
+#endif
+static int zzadd_erase;
+static char zzebuf[70];
+
+#ifdef ZZCOL
+#define ZZINC (++zzendcol)
+#else
+#define ZZINC
+#endif
+
+
+#define ZZGETC_STREAM {zzchar = getc(zzstream_in); zzclass = ZZSHIFT(zzchar);}
+#define ZZGETC_FUNC {zzchar = (*zzfunc_in)(); zzclass = ZZSHIFT(zzchar);}
+#define ZZGETC_STR { \
+ if (*zzstr_in){ \
+ zzchar = *zzstr_in; \
+ ++zzstr_in; \
+ }else{ \
+ zzchar = EOF; \
+ } \
+ zzclass = ZZSHIFT(zzchar); \
+}
+
+#define ZZNEWSTATE (newstate = dfa[state][zzclass])
+
+#ifndef ZZCOPY
+#define ZZCOPY \
+ /* Truncate matching buffer to size (not an error) */ \
+ if (zznextpos < lastpos){ \
+ *(zznextpos++) = zzchar; \
+ }else{ \
+ zzbufovf = 1; \
+ }
+#endif
+
+void
+#ifdef __USE_PROTOS
+zzrdstream( FILE *f )
+#else
+zzrdstream( f )
+FILE *f;
+#endif
+{
+ /* make sure that it is really set to something, otherwise just
+ leave it be.
+ */
+ if (f){
+ /* make sure that there is always someplace to get input
+ before closing zzstream_in
+ */
+#if 0
+ if (zzstream_in && zzstream_in!=stdin) fclose( zzstream_in );
+#endif
+ zzline = 1;
+ zzstream_in = f;
+ zzfunc_in = NULL;
+ zzstr_in = 0;
+ zzcharfull = 0;
+ }
+}
+
+void
+#ifdef __USE_PROTOS
+zzrdfunc( int (*f)(void) )
+#else
+zzrdfunc( f )
+int (*f)();
+#endif
+{
+ /* make sure that it is really set to something, otherwise just
+ leave it be.
+ */
+ if (f){
+ /* make sure that there is always someplace to get input
+ before closing zzstream_in
+ */
+#if 0
+ if (zzstream_in && zzstream_in!=stdin) fclose( zzstream_in );
+#endif
+ zzline = 1;
+ zzstream_in = NULL;
+ zzfunc_in = f;
+ zzstr_in = 0;
+ zzcharfull = 0;
+ }
+}
+
+
+void
+#ifdef __USE_PROTOS
+zzrdstr( zzchar_t *s )
+#else
+zzrdstr( s )
+zzchar_t *s;
+#endif
+{
+ /* make sure that it is really set to something, otherwise just
+ leave it be.
+ */
+ if (s){
+ /* make sure that there is always someplace to get input
+ before closing zzstream_in
+ */
+#if 0
+ if (zzstream_in && zzstream_in!=stdin) fclose( zzstream_in );
+#endif
+ zzline = 1;
+ zzstream_in = NULL;
+ zzfunc_in = 0;
+ zzstr_in = s;
+ zzcharfull = 0;
+ }
+}
+
+
+#ifdef __USE_PROTOS
+void zzclose_stream(void)
+#else
+void zzclose_stream()
+#endif
+{
+#if 0
+ fclose( zzstream_in );
+ zzstream_in = NULL;
+ zzfunc_in = NULL;
+#endif
+}
+
+/* saves dlg state, but not what feeds dlg (such as file position) */
+void
+#ifdef __USE_PROTOS
+zzsave_dlg_state(struct zzdlg_state *state)
+#else
+zzsave_dlg_state(state)
+struct zzdlg_state *state;
+#endif
+{
+ state->stream = zzstream_in;
+ state->func_ptr = zzfunc_in;
+ state->str = zzstr_in;
+ state->auto_num = zzauto;
+ state->add_erase = zzadd_erase;
+ state->lookc = zzchar;
+ state->char_full = zzcharfull;
+ state->begcol = zzbegcol;
+ state->endcol = zzendcol;
+ state->line = zzline;
+ state->lextext = zzlextext;
+ state->begexpr = zzbegexpr;
+ state->endexpr = zzendexpr;
+ state->bufsize = zzbufsize;
+ state->bufovf = zzbufovf;
+ state->nextpos = zznextpos;
+ state->class_num = zzclass;
+}
+
+void
+#ifdef __USE_PROTOS
+zzrestore_dlg_state(struct zzdlg_state *state)
+#else
+zzrestore_dlg_state(state)
+struct zzdlg_state *state;
+#endif
+{
+ zzstream_in = state->stream;
+ zzfunc_in = state->func_ptr;
+ zzstr_in = state->str;
+ zzauto = state->auto_num;
+ zzadd_erase = state->add_erase;
+ zzchar = state->lookc;
+ zzcharfull = state->char_full;
+ zzbegcol = state->begcol;
+ zzendcol = state->endcol;
+ zzline = state->line;
+ zzlextext = state->lextext;
+ zzbegexpr = state->begexpr;
+ zzendexpr = state->endexpr;
+ zzbufsize = state->bufsize;
+ zzbufovf = state->bufovf;
+ zznextpos = state->nextpos;
+ zzclass = state->class_num;
+}
+
+void
+#ifdef __USE_PROTOS
+zzmode( int m )
+#else
+zzmode( m )
+int m;
+#endif
+{
+ /* points to base of dfa table */
+ if (m<MAX_MODE){
+ zzauto = m;
+ /* have to redo class since using different compression */
+ zzclass = ZZSHIFT(zzchar);
+ }else{
+ sprintf(zzebuf,"Invalid automaton mode = %d ",m);
+ zzerr(zzebuf);
+ }
+}
+
+/* erase what is currently in the buffer, and get a new reg. expr */
+
+#ifdef __USE_PROTOS
+void zzskip(void)
+#else
+void zzskip()
+#endif
+{
+ zzadd_erase = 1;
+}
+
+/* don't erase what is in the zzlextext buffer, add on to it */
+#ifdef __USE_PROTOS
+void zzmore()
+#else
+void zzmore()
+#endif
+{
+ zzadd_erase = 2;
+}
+
+/* substitute c for the reg. expr last matched and is in the buffer */
+#ifdef __USE_PROTOS
+void
+zzreplchar(zzchar_t c)
+#else
+void
+zzreplchar(c)
+zzchar_t c;
+#endif
+{
+ /* can't allow overwriting null at end of string */
+ if (zzbegexpr < &zzlextext[zzbufsize-1]){
+ *zzbegexpr = c;
+ *(zzbegexpr+1) = '\0';
+ }
+ zzendexpr = zzbegexpr;
+ if (c != '\0') {
+ zznextpos = zzbegexpr + 1;
+ }
+ else {
+ zznextpos = zzbegexpr; /* MR30 Zero terminates string. */
+ }
+}
+
+/* replace the string s for the reg. expr last matched and in the buffer */
+void
+#ifdef __USE_PROTOS
+zzreplstr(register zzchar_t *s)
+#else
+zzreplstr(s)
+register zzchar_t *s;
+#endif
+{
+ register zzchar_t *l= &zzlextext[zzbufsize -1];
+
+ zznextpos = zzbegexpr;
+ if (s){
+ while ((zznextpos <= l) && (*(zznextpos++) = *(s++))!=0){
+ /* empty */
+ }
+ /* correct for NULL at end of string */
+ zznextpos--;
+ }
+ if ((zznextpos <= l) && (*(--s) == 0)){
+ zzbufovf = 0;
+ }else{
+ zzbufovf = 1;
+ }
+ *(zznextpos) = '\0';
+ zzendexpr = zznextpos - 1;
+}
+
+#ifdef __USE_PROTOS
+void zzgettok(void)
+#else
+void zzgettok()
+#endif
+{
+ register int state, newstate;
+ /* last space reserved for the null char */
+ zzchar_t *lastpos; /* MR27 Remove register since address operator used. */
+
+skip:
+ zzreal_line = zzline;
+ zzbufovf = 0;
+ lastpos = &zzlextext[zzbufsize-1];
+ zznextpos = zzlextext;
+ zzbegcol = zzendcol+1;
+more:
+ zzbegexpr = zznextpos;
+#ifdef ZZINTERACTIVE
+ /* interactive version of automaton */
+ /* if there is something in zzchar, process it */
+ state = newstate = dfa_base[zzauto];
+ if (zzcharfull){
+ ZZINC;
+ ZZCOPY;
+ ZZNEWSTATE;
+ }
+ if (zzstr_in)
+ while (zzalternatives[newstate]){
+ state = newstate;
+ ZZGETC_STR;
+ ZZINC;
+ ZZCOPY;
+ ZZNEWSTATE;
+ }
+ else if (zzstream_in)
+ while (zzalternatives[newstate]){
+ state = newstate;
+ ZZGETC_STREAM;
+ ZZINC;
+ ZZCOPY;
+ ZZNEWSTATE;
+ }
+ else if (zzfunc_in)
+ while (zzalternatives[newstate]){
+ state = newstate;
+ ZZGETC_FUNC;
+ ZZINC;
+ ZZCOPY;
+ ZZNEWSTATE;
+ }
+ /* figure out if last character really part of token */
+ if ((state != dfa_base[zzauto]) && (newstate == DfaStates)){
+ zzcharfull = 1;
+ --zznextpos;
+ }else{
+ zzcharfull = 0;
+ state = newstate;
+ }
+ *(zznextpos) = '\0';
+ /* Able to transition out of start state to some non err state?*/
+ if ( state == dfa_base[zzauto] ){
+ /* make sure doesn't get stuck */
+ zzadvance();
+ }
+#else
+ /* non-interactive version of automaton */
+ if (!zzcharfull)
+ zzadvance();
+ else
+ ZZINC;
+ state = dfa_base[zzauto];
+ if (zzstr_in)
+ while (ZZNEWSTATE != DfaStates){
+ state = newstate;
+ ZZCOPY;
+ ZZGETC_STR;
+ ZZINC;
+ }
+ else if (zzstream_in)
+ while (ZZNEWSTATE != DfaStates){
+ state = newstate;
+ ZZCOPY;
+ ZZGETC_STREAM;
+ ZZINC;
+ }
+ else if (zzfunc_in)
+ while (ZZNEWSTATE != DfaStates){
+ state = newstate;
+ ZZCOPY;
+ ZZGETC_FUNC;
+ ZZINC;
+ }
+ zzcharfull = 1;
+ if ( state == dfa_base[zzauto] ){
+ if (zznextpos < lastpos){
+ *(zznextpos++) = zzchar;
+ }else{
+ zzbufovf = 1;
+ }
+ *zznextpos = '\0';
+ /* make sure doesn't get stuck */
+ zzadvance();
+ }else{
+ *zznextpos = '\0';
+ }
+#endif
+#ifdef ZZCOL
+ zzendcol -= zzcharfull;
+#endif
+ zzendexpr = zznextpos -1;
+ zzadd_erase = 0;
+ (*actions[accepts[state]])();
+ switch (zzadd_erase) {
+ case 1: goto skip;
+ case 2: goto more;
+ }
+}
+
+#ifdef __USE_PROTOS
+void zzadvance(void)
+#else
+void zzadvance()
+#endif
+{
+ if (zzstream_in) { ZZGETC_STREAM; zzcharfull = 1; ZZINC;}
+ if (zzfunc_in) { ZZGETC_FUNC; zzcharfull = 1; ZZINC;}
+ if (zzstr_in) { ZZGETC_STR; zzcharfull = 1; ZZINC;}
+ if (!(zzstream_in || zzfunc_in || zzstr_in)){
+ zzerr_in();
+ }
+}
+
+void
+#ifdef __USE_PROTOS
+zzerrstd(const char *s)
+#else
+zzerrstd(s)
+char *s;
+#endif
+{
+ zzLexErrCount++; /* MR11 */
+ fprintf(stderr,
+ "%s near line %d (text was '%s')\n",
+ ((s == NULL) ? "Lexical error" : s),
+ zzline,zzlextext);
+}
+
+#ifdef __USE_PROTOS
+int zzerr_in(void)
+#else
+int zzerr_in()
+#endif
+{
+ fprintf(stderr,"No input stream, function, or string\n");
+ /* return eof to get out gracefully */
+ return EOF;
+}
+
+#endif
diff --git a/Source/Pccts/h/dlgdef.h b/Source/Pccts/h/dlgdef.h
new file mode 100644
index 0000000..733d256
--- /dev/null
+++ b/Source/Pccts/h/dlgdef.h
@@ -0,0 +1,128 @@
+/* dlgdef.h
+ * Things in scanner produced by dlg that should be visible to the outside
+ * world
+ *
+ * SOFTWARE RIGHTS
+ *
+ * We reserve no LEGAL rights to the Purdue Compiler Construction Tool
+ * Set (PCCTS) -- PCCTS is in the public domain. An individual or
+ * company may do whatever they wish with source code distributed with
+ * PCCTS or the code generated by PCCTS, including the incorporation of
+ * PCCTS, or its output, into commerical software.
+ *
+ * We encourage users to develop software with PCCTS. However, we do ask
+ * that credit is given to us for developing PCCTS. By "credit",
+ * we mean that if you incorporate our source code into one of your
+ * programs (commercial product, research project, or otherwise) that you
+ * acknowledge this fact somewhere in the documentation, research report,
+ * etc... If you like PCCTS and have developed a nice tool with the
+ * output, please mention that you developed it using PCCTS. In
+ * addition, we ask that this header remain intact in our source code.
+ * As long as these guidelines are kept, we expect to continue enhancing
+ * this system and expect to make other tools available as they are
+ * completed.
+ *
+ * ANTLR 1.33
+ * Terence Parr
+ * Parr Research Corporation
+ * with Purdue University and AHPCRC, University of Minnesota
+ * 1989-2000
+ */
+
+#ifndef ZZDLGDEF_H
+#define ZZDLGDEF_H
+
+#include "pcctscfg.h"
+
+#ifndef zzchar_t
+#ifdef ZZWCHAR_T
+#define zzchar_t wchar_t
+#else
+#define zzchar_t char
+#endif
+#endif
+
+struct zzdlg_state {
+ FILE *stream;
+#ifdef __USE_PROTOS
+ int (*func_ptr)(void);
+#else
+ int (*func_ptr)();
+#endif
+ zzchar_t *str;
+ int auto_num;
+ int add_erase;
+ int lookc;
+ int char_full;
+ int begcol, endcol;
+ int line;
+ zzchar_t *lextext, *begexpr, *endexpr;
+ int bufsize;
+ int bufovf;
+ zzchar_t *nextpos;
+ int class_num;
+};
+
+extern zzchar_t *zzlextext; /* text of most recently matched token */
+extern zzchar_t *zzbegexpr; /* beginning of last reg expr recogn. */
+extern zzchar_t *zzendexpr; /* beginning of last reg expr recogn. */
+extern int zzbufsize; /* how long zzlextext is */
+extern int zzbegcol; /* column that first character of token is in*/
+extern int zzendcol; /* column that last character of token is in */
+extern int zzline; /* line current token is on */
+extern int zzreal_line; /* line of 1st portion of token that is not skipped */
+extern int zzchar; /* character to determine next state */
+extern int zzbufovf; /* indicates that buffer too small for text */
+#ifdef __USE_PROTOS
+extern void (*zzerr)(const char *);/* pointer to error reporting function */
+#else
+extern void (*zzerr)();
+#endif
+
+#ifdef USER_ZZMODE_STACK
+extern int zzauto;
+#endif
+
+#ifdef __USE_PROTOS
+extern void zzadvance(void);
+extern void zzskip(void); /* erase zzlextext, look for antoher token */
+extern void zzmore(void); /* keep zzlextext, look for another token */
+extern void zzmode(int k); /* switch to automaton 'k' */
+extern void zzrdstream(FILE *);/* what stream to read from */
+extern void zzclose_stream(void);/* close the current input stream */
+extern void zzrdfunc(int (*)(void));/* what function to get char from */
+extern void zzrdstr( zzchar_t * );
+extern void zzgettok(void); /* get next token */
+extern void zzreplchar(zzchar_t c);/* replace last recognized reg. expr. with
+ a character */
+extern void zzreplstr(zzchar_t *s);/* replace last recognized reg. expr. with
+ a string */
+extern void zzsave_dlg_state(struct zzdlg_state *);
+extern void zzrestore_dlg_state(struct zzdlg_state *);
+extern int zzerr_in(void);
+extern void zzerrstd(const char *);
+extern void zzerraction(void);
+
+#else
+
+extern void zzadvance();
+extern void zzskip(); /* erase zzlextext, look for antoher token */
+extern void zzmore(); /* keep zzlextext, look for another token */
+extern void zzmode(/*k*/); /* switch to automaton 'k' */
+extern void zzrdstream(); /* what stream to read from */
+extern void zzclose_stream();/* close the current input stream */
+extern void zzrdfunc(); /* what function to get char from */
+extern void zzrdstr();
+extern void zzgettok(); /* get next token */
+extern void zzreplchar(); /* replace last recognized reg. expr. with
+ a character */
+extern void zzreplstr(); /* replace last recognized reg. expr. with
+ a string */
+extern void zzsave_dlg_state();
+extern void zzrestore_dlg_state();
+extern int zzerr_in();
+extern void zzerrstd();
+extern void zzerraction();
+#endif
+
+#endif
diff --git a/Source/Pccts/h/err.h b/Source/Pccts/h/err.h
new file mode 100644
index 0000000..b2b196b
--- /dev/null
+++ b/Source/Pccts/h/err.h
@@ -0,0 +1,1170 @@
+/*
+ * err.h
+ *
+ * Standard error handling mechanism
+ *
+ * SOFTWARE RIGHTS
+ *
+ * We reserve no LEGAL rights to the Purdue Compiler Construction Tool
+ * Set (PCCTS) -- PCCTS is in the public domain. An individual or
+ * company may do whatever they wish with source code distributed with
+ * PCCTS or the code generated by PCCTS, including the incorporation of
+ * PCCTS, or its output, into commerical software.
+ *
+ * We encourage users to develop software with PCCTS. However, we do ask
+ * that credit is given to us for developing PCCTS. By "credit",
+ * we mean that if you incorporate our source code into one of your
+ * programs (commercial product, research project, or otherwise) that you
+ * acknowledge this fact somewhere in the documentation, research report,
+ * etc... If you like PCCTS and have developed a nice tool with the
+ * output, please mention that you developed it using PCCTS. In
+ * addition, we ask that this header remain intact in our source code.
+ * As long as these guidelines are kept, we expect to continue enhancing
+ * this system and expect to make other tools available as they are
+ * completed.
+ *
+ * Has grown to hold all kinds of stuff (err.h is increasingly misnamed)
+ *
+ * ANTLR 1.33
+ * Terence Parr
+ * Parr Research Corporation
+ * with Purdue University and AHPCRC, University of Minnesota
+ * 1989-2000
+ */
+
+#ifndef ERR_H
+#define ERR_H
+
+#include "pcctscfg.h"
+#include <stdlib.h>
+#include <assert.h>
+
+/* */
+/* 7-Apr-97 133MR1 */
+/* Proper choice of STDC and cplusplus pre-processor symbols (?) */
+/* */
+#include "pccts_string.h"
+
+#ifdef PCCTS_USE_STDARG
+#include "pccts_stdarg.h"
+#else
+#include <varargs.h>
+#endif
+
+#ifdef DUM
+/* Define usable bits per unsigned int word (used for set stuff) */
+#ifdef PC
+#define BSETWORDSIZE 16
+#define BSETLOGWORDSIZE 4
+#else
+#define BSETWORDSIZE 32
+#define BSETLOGWORDSIZE 5
+#endif
+#endif
+
+#define BSETWORDSIZE 8
+#define BSETLOGWORDSIZE 3 /* SetWordType is 8bits */
+
+#define BSETMODWORD(x) ((x) & (BSETWORDSIZE-1)) /* x % BSETWORDSIZE */
+#define BSETDIVWORD(x) ((x) >> BSETLOGWORDSIZE) /* x / BSETWORDSIZE */
+
+/* This is not put into the global pccts_parser structure because it is
+ * hidden and does not need to be saved during a "save state" operation
+ */
+/* maximum of 32 bits/unsigned int and must be 8 bits/byte */
+static SetWordType bitmask[] = {
+ 0x00000001, 0x00000002, 0x00000004, 0x00000008,
+ 0x00000010, 0x00000020, 0x00000040, 0x00000080
+};
+
+#ifdef zzTRACE_RULES
+int zzTraceOptionValueDefault=1;
+int zzTraceOptionValue=1;
+int zzTraceGuessOptionValue=1;
+char *zzTraceCurrentRuleName=NULL;
+int zzTraceDepth=0;
+#endif
+
+int zzGuessSeq=0; /* MR10 */
+int zzSyntaxErrCount=0; /* MR11 */
+int zzLexErrCount=0; /* MR11 */
+
+void
+#ifdef __USE_PROTOS
+zzresynch(SetWordType *wd,SetWordType mask)
+#else
+zzresynch(wd,mask)
+SetWordType *wd, mask;
+#endif
+{
+ static int consumed = 1;
+
+ /* if you enter here without having consumed a token from last resynch
+ * force a token consumption.
+ */
+ if ( !consumed ) {zzCONSUME; consumed=1; return;} /* MR10 */
+
+ /* if current token is in resynch set, we've got what we wanted */
+ if ( wd[LA(1)]&mask || LA(1) == zzEOF_TOKEN ) {consumed=0; return;}
+
+ /* scan until we find something in the resynch set */
+ while ( !(wd[LA(1)]&mask) && LA(1) != zzEOF_TOKEN ) {zzCONSUME;}
+ consumed=1;
+}
+
+/* */
+/* 7-Apr-97 133MR1 for C++ and MR7 for C */
+/* Change suggested by Eli Sternheim (eli@interhdl.com) */
+/* */
+
+void
+#ifdef __USE_PROTOS
+zzconsumeUntil(SetWordType *st)
+#else
+zzconsumeUntil(st)
+SetWordType *st;
+#endif
+{
+ int tmp; /* MR7 */
+ while ( !zzset_el( (tmp=LA(1)), st) && tmp!=1 /* Eof */) { /* MR7 */
+ zzCONSUME; } /* MR7 */
+}
+
+/* */
+/* 7-Apr-97 133MR1 for C++ and MR7 for C */
+/* Change suggested by Eli Sternheim (eli@interhdl.com) */
+/* */
+
+void
+#ifdef __USE_PROTOS
+zzconsumeUntilToken(int t)
+#else
+zzconsumeUntilToken(t)
+int t;
+#endif
+{
+ int tmp; /* MR7 */
+ while ( (tmp=LA(1)) !=t && tmp!=1 /* Eof */) { zzCONSUME; } /* MR7 */
+}
+
+/* input looks like:
+ * zzFAIL(k, e1, e2, ...,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText)
+ * where the zzMiss stuff is set here to the token that did not match
+ * (and which set wasn't it a member of).
+ */
+
+#ifdef PCCTS_USE_STDARG
+void zzFAIL(int k, ...)
+#else
+void zzFAIL(va_alist)
+va_dcl
+#endif
+{
+#ifdef LL_K
+ static char text[LL_K*ZZLEXBUFSIZE+1];
+ SetWordType *f[LL_K];
+#else
+ static char text[ZZLEXBUFSIZE+1];
+ SetWordType *f[1];
+#endif
+ SetWordType **miss_set;
+ char **miss_text;
+ int *bad_tok;
+ char **bad_text;
+ int *err_k;
+ int i;
+ va_list ap;
+#ifndef PCCTS_USE_STDARG /* MR20 */
+ int k;
+#endif
+#ifdef PCCTS_USE_STDARG /* MR20 */
+ va_start(ap, k);
+#else
+ va_start(ap);
+ k = va_arg(ap, int); /* how many lookahead sets? */
+#endif
+ assert(k <= sizeof(f)/sizeof(f[0])); /* MR20 G. Hobbelt */
+ text[0] = '\0';
+ for (i=1; i<=k; i++) /* collect all lookahead sets */
+ {
+ f[i-1] = va_arg(ap, SetWordType *);
+ }
+ for (i=1; i<=k; i++) /* look for offending token */
+ {
+ if ( i>1 ) strcat(text, " ");
+ strcat(text, LATEXT(i));
+ if ( !zzset_el((unsigned)LA(i), f[i-1]) ) break;
+ }
+ miss_set = va_arg(ap, SetWordType **);
+ miss_text = va_arg(ap, char **);
+ bad_tok = va_arg(ap, int *);
+ bad_text = va_arg(ap, char **);
+ err_k = va_arg(ap, int *);
+ if ( i>k )
+ {
+ /* bad; lookahead is permutation that cannot be matched,
+ * but, the ith token of lookahead is valid at the ith position
+ * (The old LL sub 1 (k) versus LL(k) parsing technique)
+ */
+ *miss_set = NULL;
+ *miss_text = zzlextext;
+ *bad_tok = LA(1);
+ *bad_text = LATEXT(1);
+ *err_k = k;
+ return;
+ }
+/* fprintf(stderr, "%s not in %dth set\n", zztokens[LA(i)], i);*/
+ *miss_set = f[i-1];
+ *miss_text = text;
+ *bad_tok = LA(i);
+ *bad_text = LATEXT(i);
+ if ( i==1 ) *err_k = 1;
+ else *err_k = k;
+}
+
+#ifdef __USE_PROTOS
+void zzTraceGuessDone(zzantlr_state *state)
+#else
+void zzTraceGuessDone(state)
+ zzantlr_state *state;
+#endif
+{
+#ifdef zzTRACE_RULES
+#ifdef ZZCAN_GUESS
+
+ int doIt=0;
+
+ if (zzTraceCurrentRuleName == NULL) return;
+
+ if (zzTraceOptionValue <= 0) {
+ doIt=0;
+ } else if (zzTraceGuessOptionValue <= 0) {
+ doIt=0;
+ } else {
+ doIt=1;
+ };
+
+ if (doIt) {
+ fprintf(stderr,"guess done - returning to rule %s {\"%s\"} at depth %d",
+ state->traceCurrentRuleName,
+ LATEXT(1),
+ state->traceDepth);
+ if (state->guessing != 0) {
+ fprintf(stderr," (guess mode continues - an enclosing guess is still active)");
+ } else {
+ fprintf(stderr," (guess mode ends)");
+ };
+ fprintf(stderr,"\n");
+ };
+#endif
+#endif
+}
+
+void
+#ifdef __USE_PROTOS
+zzsave_antlr_state(zzantlr_state *buf)
+#else
+zzsave_antlr_state(buf)
+zzantlr_state *buf;
+#endif
+{
+#ifdef LL_K
+ int i;
+#endif
+
+#ifdef ZZCAN_GUESS
+ buf->guess_start = zzguess_start;
+ buf->guessing = zzguessing;
+#endif
+ buf->asp = zzasp;
+#ifdef GENAST
+ buf->ast_sp = zzast_sp;
+#endif
+#ifdef ZZINF_LOOK
+ buf->inf_labase = zzinf_labase;
+ buf->inf_last = zzinf_last;
+
+/* MR6 Gunnar Rxnning (gunnar@candleweb.no) */
+/* MR6 Additional state needs to be saved/restored */
+
+ buf->inf_tokens = zzinf_tokens; /* MR6 */
+ buf->inf_text = zzinf_text; /* MR6 */
+ buf->inf_text_buffer = zzinf_text_buffer; /* MR6 */
+ buf->inf_line = zzinf_line; /* MR6 */
+
+#endif
+#ifdef DEMAND_LOOK
+ buf->dirty = zzdirty;
+#endif
+#ifdef LL_K
+ for (i=0; i<LL_K; i++) buf->tokenLA[i] = zztokenLA[i];
+ for (i=0; i<LL_K; i++) strcpy(buf->textLA[i], zztextLA[i]);
+ buf->lap = zzlap;
+ buf->labase = zzlabase;
+#else
+ buf->token = zztoken;
+ strcpy(buf->text, zzlextext);
+#endif
+#ifdef zzTRACE_RULES
+
+ /* MR10 */
+
+ buf->traceOptionValue=zzTraceOptionValue;
+ buf->traceGuessOptionValue=zzTraceGuessOptionValue;
+ buf->traceCurrentRuleName=zzTraceCurrentRuleName;
+ buf->traceDepth=zzTraceDepth;
+#endif
+}
+
+void
+#ifdef __USE_PROTOS
+zzrestore_antlr_state(zzantlr_state *buf)
+#else
+zzrestore_antlr_state(buf)
+zzantlr_state *buf;
+#endif
+{
+
+#ifdef zzTRACE_RULES
+ int prevTraceOptionValue;
+#endif
+
+#ifdef LL_K
+ int i;
+#endif
+
+#ifdef ZZCAN_GUESS
+ zzguess_start = buf->guess_start;
+ zzguessing = buf->guessing;
+#endif
+ zzasp = buf->asp;
+#ifdef GENAST
+ zzast_sp = buf->ast_sp;
+#endif
+#ifdef ZZINF_LOOK
+ zzinf_labase = buf->inf_labase;
+ zzinf_last = buf->inf_last;
+
+/* MR6 Gunnar Rxnning (gunnar@candleweb.no) */
+/* MR6 Additional state needs to be saved/restored */
+
+ zzinf_tokens = buf->inf_tokens; /* MR6 */
+ zzinf_text = buf->inf_text; /* MR6 */
+ zzinf_text_buffer = buf->inf_text_buffer; /* MR6 */
+ zzinf_line = buf->inf_line; /* MR6 */
+#endif
+#ifdef DEMAND_LOOK
+ zzdirty = buf->dirty;
+#endif
+#ifdef LL_K
+ for (i=0; i<LL_K; i++) zztokenLA[i] = buf->tokenLA[i];
+ for (i=0; i<LL_K; i++) strcpy(zztextLA[i], buf->textLA[i]);
+ zzlap = buf->lap;
+ zzlabase = buf->labase;
+#else
+ zztoken = buf->token;
+ strcpy(zzlextext, buf->text);
+#endif
+#ifdef zzTRACE_RULES
+
+ prevTraceOptionValue=zzTraceOptionValue;
+ zzTraceOptionValue=buf->traceOptionValue;
+ if ( (prevTraceOptionValue > 0) !=
+ (zzTraceOptionValue > 0)) {
+ if (zzTraceOptionValue > 0) {
+ fprintf(stderr,"trace enable restored in rule %s depth %d\n",
+ zzTraceCurrentRuleName,zzTraceDepth);
+ };
+ if (zzTraceOptionValue <= 0) {
+ fprintf(stderr,"trace disable restored in rule %s depth %d\n",
+ zzTraceCurrentRuleName,zzTraceDepth);
+ };
+ };
+
+ zzTraceOptionValue=buf->traceOptionValue; /* MR10 */
+ zzTraceGuessOptionValue=buf->traceGuessOptionValue; /* MR10 */
+ zzTraceCurrentRuleName=buf->traceCurrentRuleName; /* MR10 */
+ zzTraceDepth=buf->traceDepth; /* MR10 */
+ zzTraceGuessDone(buf); /* MR10 */
+#endif
+}
+
+void
+#ifdef __USE_PROTOS
+zzedecode(SetWordType *a)
+#else
+zzedecode(a)
+SetWordType *a;
+#endif
+{
+ register SetWordType *p = a;
+ register SetWordType *endp = &(p[zzSET_SIZE]);
+ register unsigned e = 0;
+
+ if ( zzset_deg(a)>1 ) fprintf(stderr, " {");
+ do {
+ register SetWordType t = *p;
+ register SetWordType *b = &(bitmask[0]);
+ do {
+ if ( t & *b ) fprintf(stderr, " %s", zztokens[e]);
+ e++;
+ } while (++b < &(bitmask[sizeof(SetWordType)*8]));
+ } while (++p < endp);
+ if ( zzset_deg(a)>1 ) fprintf(stderr, " }");
+}
+
+#ifndef USER_ZZSYN
+/* standard error reporting function */
+void
+#ifdef __USE_PROTOS
+zzsyn(char *text, int tok, char *egroup, SetWordType *eset, int etok, int k, char *bad_text)
+#else
+zzsyn(text, tok, egroup, eset, etok, k, bad_text)
+char *text, *egroup, *bad_text;
+int tok;
+int etok;
+int k;
+SetWordType *eset;
+#endif
+{
+
+ zzSyntaxErrCount++; /* MR11 */
+ fprintf(stderr, "line %d: syntax error at \"%s\"", zzline, (tok==zzEOF_TOKEN)?"EOF":bad_text);
+ if ( !etok && !eset ) {fprintf(stderr, "\n"); return;}
+ if ( k==1 ) fprintf(stderr, " missing");
+ else
+ {
+ fprintf(stderr, "; \"%s\" not", bad_text);
+ if ( zzset_deg(eset)>1 ) fprintf(stderr, " in");
+ }
+ if ( zzset_deg(eset)>0 ) zzedecode(eset);
+ else fprintf(stderr, " %s", zztokens[etok]);
+ if ( strlen(egroup) > 0 ) fprintf(stderr, " in %s", egroup);
+ fprintf(stderr, "\n");
+}
+#endif
+
+/* is b an element of set p? */
+int
+#ifdef __USE_PROTOS
+zzset_el(unsigned b, SetWordType *p)
+#else
+zzset_el(b,p)
+unsigned b;
+SetWordType *p;
+#endif
+{
+ return( p[BSETDIVWORD(b)] & bitmask[BSETMODWORD(b)] );
+}
+
+int
+#ifdef __USE_PROTOS
+zzset_deg(SetWordType *a)
+#else
+zzset_deg(a)
+SetWordType *a;
+#endif
+{
+ /* Fast compute degree of a set... the number
+ of elements present in the set. Assumes
+ that all word bits are used in the set
+ */
+ register SetWordType *p = a;
+ register SetWordType *endp = &(a[zzSET_SIZE]);
+ register int degree = 0;
+
+ if ( a == NULL ) return 0;
+ while ( p < endp )
+ {
+ register SetWordType t = *p;
+ register SetWordType *b = &(bitmask[0]);
+ do {
+ if (t & *b) ++degree;
+ } while (++b < &(bitmask[sizeof(SetWordType)*8]));
+ p++;
+ }
+
+ return(degree);
+}
+
+#ifdef DEMAND_LOOK
+
+#ifdef LL_K
+int
+#ifdef __USE_PROTOS
+_zzmatch(int _t, char **zzBadText, char **zzMissText,
+ int *zzMissTok, int *zzBadTok,
+ SetWordType **zzMissSet)
+#else
+_zzmatch(_t, zzBadText, zzMissText, zzMissTok, zzBadTok, zzMissSet)
+int _t;
+char **zzBadText;
+char **zzMissText;
+int *zzMissTok, *zzBadTok;
+SetWordType **zzMissSet;
+#endif
+{
+ if ( zzdirty==LL_K ) {
+ zzCONSUME;
+ }
+ if ( LA(1)!=_t ) {
+ *zzBadText = *zzMissText=LATEXT(1);
+ *zzMissTok= _t; *zzBadTok=LA(1);
+ *zzMissSet=NULL;
+ return 0;
+ }
+ zzMakeAttr
+ zzdirty++;
+ zzlabase++;
+ return 1;
+}
+
+int
+#ifdef __USE_PROTOS
+_zzmatch_wsig(int _t)
+#else
+_zzmatch_wsig(_t)
+int _t;
+#endif
+{
+ if ( zzdirty==LL_K ) {
+ zzCONSUME;
+ }
+ if ( LA(1)!=_t ) {
+ return 0;
+ }
+ zzMakeAttr
+ zzdirty++;
+ zzlabase++;
+ return 1;
+}
+
+#else
+
+int
+#ifdef __USE_PROTOS
+_zzmatch(int _t, char **zzBadText, char **zzMissText,
+ int *zzMissTok, int *zzBadTok, SetWordType **zzMissSet)
+#else
+_zzmatch(_t, zzBadText, zzMissText, zzMissTok, zzBadTok, zzMissSet)
+int _t;
+char **zzBadText;
+char **zzMissText;
+int *zzMissTok, *zzBadTok;
+SetWordType **zzMissSet;
+#endif
+{
+ if ( zzdirty ) {zzCONSUME;}
+ if ( LA(1)!=_t ) {
+ *zzBadText = *zzMissText=LATEXT(1);
+ *zzMissTok= _t; *zzBadTok=LA(1);
+ *zzMissSet=NULL;
+ return 0;
+ }
+ zzdirty = 1;
+ zzMakeAttr
+ return 1;
+}
+
+int
+#ifdef __USE_PROTOS
+_zzmatch_wsig(int _t)
+#else
+_zzmatch_wsig(_t)
+int _t;
+#endif
+{
+ if ( zzdirty ) {zzCONSUME;}
+ if ( LA(1)!=_t ) {
+ return 0;
+ }
+ zzdirty = 1;
+ zzMakeAttr
+ return 1;
+}
+
+#endif /*LL_K*/
+
+#else
+
+int
+#ifdef __USE_PROTOS
+_zzmatch(int _t, char **zzBadText, char **zzMissText,
+ int *zzMissTok, int *zzBadTok,
+ SetWordType **zzMissSet)
+#else
+_zzmatch(_t, zzBadText, zzMissText, zzMissTok, zzBadTok, zzMissSet)
+int _t;
+char **zzBadText;
+char **zzMissText;
+int *zzMissTok, *zzBadTok;
+SetWordType **zzMissSet;
+#endif
+{
+ if ( LA(1)!=_t ) {
+ *zzBadText = *zzMissText=LATEXT(1);
+ *zzMissTok= _t; *zzBadTok=LA(1);
+ *zzMissSet=NULL;
+ return 0;
+ }
+ zzMakeAttr
+ return 1;
+}
+
+int
+#ifdef __USE_PROTOS
+_zzmatch_wsig(int _t)
+#else
+_zzmatch_wsig(_t)
+int _t;
+#endif
+{
+ if ( LA(1)!=_t ) return 0;
+ zzMakeAttr
+ return 1;
+}
+
+#endif /*DEMAND_LOOK*/
+
+#ifdef ZZINF_LOOK
+void
+#ifdef __USE_PROTOS
+_inf_zzgettok(void)
+#else
+_inf_zzgettok()
+#endif
+{
+ if ( zzinf_labase >= zzinf_last )
+ {NLA = zzEOF_TOKEN; strcpy(NLATEXT, "");}
+ else {
+ NLA = zzinf_tokens[zzinf_labase];
+ zzline = zzinf_line[zzinf_labase]; /* wrong in 1.21 */
+ strcpy(NLATEXT, zzinf_text[zzinf_labase]);
+ zzinf_labase++;
+ }
+}
+#endif
+
+#ifdef ZZINF_LOOK
+/* allocate default size text,token and line arrays;
+ * then, read all of the input reallocing the arrays as needed.
+ * Once the number of total tokens is known, the LATEXT(i) array (zzinf_text)
+ * is allocated and it's pointers are set to the tokens in zzinf_text_buffer.
+ */
+void
+#ifdef __USE_PROTOS
+zzfill_inf_look(void)
+#else
+zzfill_inf_look()
+#endif
+{
+ int tok, line;
+ int zzinf_token_buffer_size = ZZINF_DEF_TOKEN_BUFFER_SIZE;
+ int zzinf_text_buffer_size = ZZINF_DEF_TEXT_BUFFER_SIZE;
+ int zzinf_text_buffer_index = 0;
+ int zzinf_lap = 0;
+
+ /* allocate text/token buffers */
+ zzinf_text_buffer = (char *) malloc(zzinf_text_buffer_size);
+ if ( zzinf_text_buffer == NULL )
+ {
+ fprintf(stderr, "cannot allocate lookahead text buffer (%d bytes)\n",
+ zzinf_text_buffer_size);
+ exit(PCCTS_EXIT_FAILURE);
+ }
+ zzinf_tokens = (int *) calloc(zzinf_token_buffer_size,sizeof(int));
+ if ( zzinf_tokens == NULL )
+ {
+ fprintf(stderr, "cannot allocate token buffer (%d tokens)\n",
+ zzinf_token_buffer_size);
+ exit(PCCTS_EXIT_FAILURE);
+ }
+ zzinf_line = (int *) calloc(zzinf_token_buffer_size,sizeof(int));
+ if ( zzinf_line == NULL )
+ {
+ fprintf(stderr, "cannot allocate line buffer (%d ints)\n",
+ zzinf_token_buffer_size);
+ exit(PCCTS_EXIT_FAILURE);
+ }
+
+ /* get tokens, copying text to text buffer */
+ zzinf_text_buffer_index = 0;
+ do {
+ zzgettok();
+ line = zzreal_line;
+ while ( zzinf_lap>=zzinf_token_buffer_size )
+ {
+ zzinf_token_buffer_size += ZZINF_BUFFER_TOKEN_CHUNK_SIZE;
+ zzinf_tokens = (int *) realloc(zzinf_tokens,
+ zzinf_token_buffer_size*sizeof(int));
+ if ( zzinf_tokens == NULL )
+ {
+ fprintf(stderr, "cannot allocate lookahead token buffer (%d tokens)\n",
+ zzinf_token_buffer_size);
+ exit(PCCTS_EXIT_FAILURE);
+ }
+ zzinf_line = (int *) realloc(zzinf_line,
+ zzinf_token_buffer_size*sizeof(int));
+ if ( zzinf_line == NULL )
+ {
+ fprintf(stderr, "cannot allocate lookahead line buffer (%d ints)\n",
+ zzinf_token_buffer_size);
+ exit(PCCTS_EXIT_FAILURE);
+ }
+
+ }
+ while ( (zzinf_text_buffer_index+strlen(NLATEXT)+1) >= zzinf_text_buffer_size )
+ {
+ zzinf_text_buffer_size += ZZINF_BUFFER_TEXT_CHUNK_SIZE;
+ zzinf_text_buffer = (char *) realloc(zzinf_text_buffer,
+ zzinf_text_buffer_size);
+ if ( zzinf_text_buffer == NULL )
+ {
+ fprintf(stderr, "cannot allocate lookahead text buffer (%d bytes)\n",
+ zzinf_text_buffer_size);
+ exit(PCCTS_EXIT_FAILURE);
+ }
+ }
+ /* record token and text and line of input symbol */
+ tok = zzinf_tokens[zzinf_lap] = NLA;
+ strcpy(&zzinf_text_buffer[zzinf_text_buffer_index], NLATEXT);
+ zzinf_text_buffer_index += strlen(NLATEXT)+1;
+ zzinf_line[zzinf_lap] = line;
+ zzinf_lap++;
+ } while (tok!=zzEOF_TOKEN);
+ zzinf_labase = 0;
+ zzinf_last = zzinf_lap-1;
+
+ /* allocate ptrs to text of ith token */
+ zzinf_text = (char **) calloc(zzinf_last+1,sizeof(char *));
+ if ( zzinf_text == NULL )
+ {
+ fprintf(stderr, "cannot allocate lookahead text buffer (%d)\n",
+ zzinf_text_buffer_size);
+ exit(PCCTS_EXIT_FAILURE);
+ }
+ zzinf_text_buffer_index = 0;
+ zzinf_lap = 0;
+ /* set ptrs so that zzinf_text[i] is the text of the ith token found on input */
+ while (zzinf_lap<=zzinf_last)
+ {
+ zzinf_text[zzinf_lap++] = &zzinf_text_buffer[zzinf_text_buffer_index];
+ zzinf_text_buffer_index += strlen(&zzinf_text_buffer[zzinf_text_buffer_index])+1;
+ }
+}
+#endif
+
+int
+#ifdef __USE_PROTOS
+_zzsetmatch(SetWordType *e, char **zzBadText, char **zzMissText,
+ int *zzMissTok, int *zzBadTok,
+ SetWordType **zzMissSet,
+ SetWordType *zzTokclassErrset /* MR23 */)
+#else
+_zzsetmatch(e, zzBadText, zzMissText, zzMissTok, zzBadTok, zzMissSet, zzTokclassErrset /* MR23 */)
+SetWordType *e;
+char **zzBadText;
+char **zzMissText;
+int *zzMissTok, *zzBadTok;
+SetWordType **zzMissSet;
+SetWordType *zzTokclassErrset;
+#endif
+{
+#ifdef DEMAND_LOOK
+#ifdef LL_K
+ if ( zzdirty==LL_K ) {zzCONSUME;}
+#else
+ if ( zzdirty ) {zzCONSUME;}
+#endif
+#endif
+ if ( !zzset_el((unsigned)LA(1), e) ) {
+ *zzBadText = LATEXT(1); *zzMissText=NULL;
+ *zzMissTok= 0; *zzBadTok=LA(1);
+ *zzMissSet=zzTokclassErrset; /* MR23 */
+ return 0;
+ }
+ zzMakeAttr /* MR14 Ger Hobbelt (hobbelt@axa.nl) */
+#ifdef DEMAND_LOOK
+#ifdef LL_K
+ zzdirty++;
+ zzlabase++; /* MR14 Ger Hobbelt (hobbelt@axa.nl) */
+#else
+ zzdirty = 1;
+#endif
+#endif
+ return 1;
+}
+
+int
+#ifdef __USE_PROTOS
+_zzmatch_wdfltsig(int tokenWanted, SetWordType *whatFollows)
+#else
+_zzmatch_wdfltsig(tokenWanted, whatFollows)
+int tokenWanted;
+SetWordType *whatFollows;
+#endif
+{
+#ifdef DEMAND_LOOK
+#ifdef LL_K
+ if ( zzdirty==LL_K ) {
+ zzCONSUME;
+ }
+#else
+ if ( zzdirty ) {zzCONSUME;}
+#endif
+#endif
+
+ if ( LA(1)!=tokenWanted )
+ {
+ zzSyntaxErrCount++; /* MR11 */
+ fprintf(stderr,
+ "line %d: syntax error at \"%s\" missing %s\n",
+ zzline,
+ (LA(1)==zzEOF_TOKEN)?"<eof>":(char *)LATEXT(1),
+ zztokens[tokenWanted]);
+ zzconsumeUntil( whatFollows );
+ return 0;
+ }
+ else {
+ zzMakeAttr
+#ifdef DEMAND_LOOK
+#ifdef LL_K
+ zzdirty++;
+ zzlabase++;
+#else
+ zzdirty = 1;
+#endif
+#else
+/* zzCONSUME; consume if not demand lookahead */
+#endif
+ return 1;
+ }
+}
+
+int
+#ifdef __USE_PROTOS
+_zzsetmatch_wdfltsig(SetWordType *tokensWanted,
+ int tokenTypeOfSet,
+ SetWordType *whatFollows)
+#else
+_zzsetmatch_wdfltsig(tokensWanted, tokenTypeOfSet, whatFollows)
+SetWordType *tokensWanted;
+int tokenTypeOfSet;
+SetWordType *whatFollows;
+#endif
+{
+#ifdef DEMAND_LOOK
+#ifdef LL_K
+ if ( zzdirty==LL_K ) {zzCONSUME;}
+#else
+ if ( zzdirty ) {zzCONSUME;}
+#endif
+#endif
+ if ( !zzset_el((unsigned)LA(1), tokensWanted) )
+ {
+ zzSyntaxErrCount++; /* MR11 */
+ fprintf(stderr,
+ "line %d: syntax error at \"%s\" missing %s\n",
+ zzline,
+ (LA(1)==zzEOF_TOKEN)?"<eof>":(char *)LATEXT(1),
+ zztokens[tokenTypeOfSet]);
+ zzconsumeUntil( whatFollows );
+ return 0;
+ }
+ else {
+ zzMakeAttr
+#ifdef DEMAND_LOOK
+#ifdef LL_K
+ zzdirty++;
+ zzlabase++;
+#else
+ zzdirty = 1;
+#endif
+#else
+/* zzCONSUME; consume if not demand lookahead */
+#endif
+ return 1;
+ }
+}
+
+int
+#ifdef __USE_PROTOS
+_zzsetmatch_wsig(SetWordType *e)
+#else
+_zzsetmatch_wsig(e)
+SetWordType *e;
+#endif
+{
+#ifdef DEMAND_LOOK
+#ifdef LL_K
+ if ( zzdirty==LL_K ) {zzCONSUME;}
+#else
+ if ( zzdirty ) {zzCONSUME;}
+#endif
+#endif
+ if ( !zzset_el((unsigned)LA(1), e) ) return 0;
+ zzMakeAttr /* MR14 Ger Hobbelt (hobbelt@axa.nl) */
+#ifdef DEMAND_LOOK
+#ifdef LL_K
+ zzdirty++;
+ zzlabase++; /* MR14 Ger Hobbelt (hobbelt@axa.nl) */
+#else
+ zzdirty = 1;
+#endif
+#endif
+ return 1;
+}
+
+#ifdef USER_ZZMODE_STACK
+static int zzmstk[ZZMAXSTK] = { -1 };
+static int zzmdep = 0;
+static char zzmbuf[70];
+
+void
+#ifdef __USE_PROTOS
+zzmpush( int m )
+#else
+zzmpush( m )
+int m;
+#endif
+{
+ if(zzmdep == ZZMAXSTK - 1) {
+ sprintf(zzmbuf, "Mode stack overflow ");
+ zzerr(zzmbuf);
+ } else {
+ zzmstk[zzmdep++] = zzauto;
+ zzmode(m);
+ }
+}
+
+void
+#ifdef __USE_PROTOS
+zzmpop( void )
+#else
+zzmpop( )
+#endif
+{
+ if(zzmdep == 0)
+ { sprintf(zzmbuf, "Mode stack underflow ");
+ zzerr(zzmbuf);
+ }
+ else
+ { zzmdep--;
+ zzmode(zzmstk[zzmdep]);
+ }
+}
+
+void
+#ifdef __USE_PROTOS
+zzsave_mode_stack( int modeStack[], int *modeLevel )
+#else
+zzsave_mode_stack( modeStack, modeLevel )
+int modeStack[];
+int *modeLevel;
+#endif
+{
+ int i;
+ memcpy(modeStack, zzmstk, sizeof(zzmstk));
+ *modeLevel = zzmdep;
+ zzmdep = 0;
+
+ return;
+}
+
+void
+#ifdef __USE_PROTOS
+zzrestore_mode_stack( int modeStack[], int *modeLevel )
+#else
+zzrestore_mode_stack( modeStack, modeLevel )
+int modeStack[];
+int *modeLevel;
+#endif
+{
+ int i;
+
+ memcpy(zzmstk, modeStack, sizeof(zzmstk));
+ zzmdep = *modeLevel;
+
+ return;
+}
+#endif /* USER_ZZMODE_STACK */
+
+#ifdef __USE_PROTOS
+void zzTraceReset(void)
+#else
+void zzTraceReset()
+#endif
+{
+#ifdef zzTRACE_RULES
+ zzTraceOptionValue=zzTraceOptionValueDefault;
+ zzTraceGuessOptionValue=1;
+ zzTraceCurrentRuleName=NULL;
+ zzTraceDepth=0;
+#endif
+}
+
+#ifdef __USE_PROTOS
+void zzTraceGuessFail(void)
+#else
+void zzTraceGuessFail()
+#endif
+{
+
+#ifdef zzTRACE_RULES
+#ifdef ZZCAN_GUESS
+
+ int doIt=0;
+
+ if (zzTraceOptionValue <= 0) {
+ doIt=0;
+ } else if (zzguessing && zzTraceGuessOptionValue <= 0) {
+ doIt=0;
+ } else {
+ doIt=1;
+ };
+
+ if (doIt) {
+ fprintf(stderr,"guess failed\n");
+ };
+#endif
+#endif
+}
+
+/* zzTraceOption:
+ zero value turns off trace
+*/
+
+#ifdef __USE_PROTOS
+void zzTraceIn(char * rule)
+#else
+void zzTraceIn(rule)
+ char *rule;
+#endif
+{
+#ifdef zzTRACE_RULES
+
+ int doIt=0;
+
+ zzTraceDepth++;
+ zzTraceCurrentRuleName=rule;
+
+ if (zzTraceOptionValue <= 0) {
+ doIt=0;
+#ifdef ZZCAN_GUESS
+ } else if (zzguessing && zzTraceGuessOptionValue <= 0) {
+ doIt=0;
+#endif
+ } else {
+ doIt=1;
+ };
+
+ if (doIt) {
+ fprintf(stderr,"enter rule %s {\"%s\"} depth %d",
+ rule,
+ LA(1)==1 ? "@" : (char *) LATEXT(1), /* MR19 */
+ zzTraceDepth);
+#ifdef ZZCAN_GUESS
+ if (zzguessing) fprintf(stderr," guessing");
+#endif
+ fprintf(stderr,"\n");
+ };
+#endif
+ return;
+}
+
+#ifdef __USE_PROTOS
+void zzTraceOut(char * rule)
+#else
+void zzTraceOut(rule)
+ char *rule;
+#endif
+{
+#ifdef zzTRACE_RULES
+ int doIt=0;
+
+ zzTraceDepth--;
+
+ if (zzTraceOptionValue <= 0) {
+ doIt=0;
+#ifdef ZZCAN_GUESS
+ } else if (zzguessing && zzTraceGuessOptionValue <= 0) {
+ doIt=0;
+#endif
+ } else {
+ doIt=1;
+ };
+
+ if (doIt) {
+ fprintf(stderr,"exit rule %s {\"%s\"} depth %d",
+ rule,
+ LA(1)==1 ? "@" : (char *) LATEXT(1), /* MR19 */
+ zzTraceDepth+1);
+#ifdef ZZCAN_GUESS
+ if (zzguessing) fprintf(stderr," guessing");
+#endif
+ fprintf(stderr,"\n");
+ };
+#endif
+}
+
+#ifdef __USE_PROTOS
+int zzTraceOption(int delta)
+#else
+int zzTraceOption(delta)
+ int delta;
+#endif
+{
+#ifdef zzTRACE_RULES
+ int prevValue=zzTraceOptionValue;
+
+ zzTraceOptionValue=zzTraceOptionValue+delta;
+
+ if (zzTraceCurrentRuleName != NULL) {
+ if (prevValue <= 0 && zzTraceOptionValue > 0) {
+ fprintf(stderr,"trace enabled in rule %s depth %d\n",
+ zzTraceCurrentRuleName,zzTraceDepth);
+ };
+ if (prevValue > 0 && zzTraceOptionValue <= 0) {
+ fprintf(stderr,"trace disabled in rule %s depth %d\n",
+ zzTraceCurrentRuleName,zzTraceDepth);
+ };
+ };
+ return prevValue;
+#else
+ return 0;
+#endif
+}
+
+#ifdef __USE_PROTOS
+int zzTraceGuessOption(int delta)
+#else
+int zzTraceGuessOption(delta)
+ int delta;
+#endif
+{
+#ifdef zzTRACE_RULES
+#ifdef ZZCAN_GUESS
+ int prevValue=zzTraceGuessOptionValue;
+
+ zzTraceGuessOptionValue=zzTraceGuessOptionValue+delta;
+
+ if (zzTraceCurrentRuleName != NULL) {
+ if (prevValue <= 0 && zzTraceGuessOptionValue > 0) {
+ fprintf(stderr,"guess trace enabled in rule %s depth %d\n",
+ zzTraceCurrentRuleName,zzTraceDepth);
+ };
+ if (prevValue > 0 && zzTraceGuessOptionValue <= 0) {
+ fprintf(stderr,"guess trace disabled in rule %s depth %d\n",
+ zzTraceCurrentRuleName,zzTraceDepth);
+ };
+ };
+ return prevValue;
+#else
+ return 0;
+#endif
+#else
+ return 0;
+#endif
+}
+
+#endif /* ERR_H */
diff --git a/Source/Pccts/h/int.h b/Source/Pccts/h/int.h
new file mode 100644
index 0000000..cdcaa92
--- /dev/null
+++ b/Source/Pccts/h/int.h
@@ -0,0 +1,37 @@
+/* ANTLR attribute definition -- long integers
+ *
+ * SOFTWARE RIGHTS
+ *
+ * We reserve no LEGAL rights to the Purdue Compiler Construction Tool
+ * Set (PCCTS) -- PCCTS is in the public domain. An individual or
+ * company may do whatever they wish with source code distributed with
+ * PCCTS or the code generated by PCCTS, including the incorporation of
+ * PCCTS, or its output, into commerical software.
+ *
+ * We encourage users to develop software with PCCTS. However, we do ask
+ * that credit is given to us for developing PCCTS. By "credit",
+ * we mean that if you incorporate our source code into one of your
+ * programs (commercial product, research project, or otherwise) that you
+ * acknowledge this fact somewhere in the documentation, research report,
+ * etc... If you like PCCTS and have developed a nice tool with the
+ * output, please mention that you developed it using PCCTS. In
+ * addition, we ask that this header remain intact in our source code.
+ * As long as these guidelines are kept, we expect to continue enhancing
+ * this system and expect to make other tools available as they are
+ * completed.
+ *
+ * ANTLR 1.33
+ * Terence Parr
+ * Parr Research Corporation
+ * with Purdue University and AHPCRC, University of Minnesota
+ * 1989-2000
+ */
+
+#ifndef ZZINT_H
+#define ZZINT_H
+
+typedef long Attrib;
+
+#define zzcr_attr(a,tok,t) *(a) = atol(t);
+
+#endif
diff --git a/Source/Pccts/h/pccts_assert.h b/Source/Pccts/h/pccts_assert.h
new file mode 100644
index 0000000..ff0dfb5
--- /dev/null
+++ b/Source/Pccts/h/pccts_assert.h
@@ -0,0 +1,10 @@
+#ifndef __PCCTS_ASSERT_H__
+#define __PCCTS_ASSERT_H__
+
+#ifdef PCCTS_USE_NAMESPACE_STD
+#include <cassert>
+#else
+#include <assert.h>
+#endif
+
+#endif
diff --git a/Source/Pccts/h/pccts_iostream.h b/Source/Pccts/h/pccts_iostream.h
new file mode 100644
index 0000000..972b32c
--- /dev/null
+++ b/Source/Pccts/h/pccts_iostream.h
@@ -0,0 +1,10 @@
+#ifndef __PCCTS_IOSTREAM_H__
+#define __PCCTS_IOSTREAM_H__
+
+#ifdef PCCTS_USE_NAMESPACE_STD
+#include <iostream>
+#else
+#include <iostream.h>
+#endif
+
+#endif
diff --git a/Source/Pccts/h/pccts_istream.h b/Source/Pccts/h/pccts_istream.h
new file mode 100644
index 0000000..e25cb8c
--- /dev/null
+++ b/Source/Pccts/h/pccts_istream.h
@@ -0,0 +1,10 @@
+#ifndef __PCCTS_ISTREAM_H__
+#define __PCCTS_ISTREAM_H__
+
+#ifdef PCCTS_USE_NAMESPACE_STD
+#include <istream>
+#else
+#include <istream.h>
+#endif
+
+#endif
diff --git a/Source/Pccts/h/pccts_setjmp.h b/Source/Pccts/h/pccts_setjmp.h
new file mode 100644
index 0000000..9ea185c
--- /dev/null
+++ b/Source/Pccts/h/pccts_setjmp.h
@@ -0,0 +1,10 @@
+#ifndef __PCCTS_SETJMP_H__
+#define __PCCTS_SETJMP_H__
+
+#ifdef PCCTS_USE_NAMESPACE_STD
+#include <csetjmp>
+#else
+#include <setjmp.h>
+#endif
+
+#endif
diff --git a/Source/Pccts/h/pccts_stdarg.h b/Source/Pccts/h/pccts_stdarg.h
new file mode 100644
index 0000000..e957430
--- /dev/null
+++ b/Source/Pccts/h/pccts_stdarg.h
@@ -0,0 +1,10 @@
+#ifndef __PCCTS_STDARG_H__
+#define __PCCTS_STDARG_H__
+
+#ifdef PCCTS_USE_NAMESPACE_STD
+#include <cstdarg>
+#else
+#include <stdarg.h>
+#endif
+
+#endif
diff --git a/Source/Pccts/h/pccts_stdio.h b/Source/Pccts/h/pccts_stdio.h
new file mode 100644
index 0000000..ac34d10
--- /dev/null
+++ b/Source/Pccts/h/pccts_stdio.h
@@ -0,0 +1,10 @@
+#ifndef __PCCTS_STDIO_H__
+#define __PCCTS_STDIO_H__
+
+#ifdef PCCTS_USE_NAMESPACE_STD
+#include <cstdio>
+#else
+#include <stdio.h>
+#endif
+
+#endif
diff --git a/Source/Pccts/h/pccts_stdlib.h b/Source/Pccts/h/pccts_stdlib.h
new file mode 100644
index 0000000..f0b344e
--- /dev/null
+++ b/Source/Pccts/h/pccts_stdlib.h
@@ -0,0 +1,10 @@
+#ifndef __PCCTS_STDLIB_H__
+#define __PCCTS_STDLIB_H__
+
+#ifdef PCCTS_USE_NAMESPACE_STD
+#include <cstdlib>
+#else
+#include <stdlib.h>
+#endif
+
+#endif
diff --git a/Source/Pccts/h/pccts_string.h b/Source/Pccts/h/pccts_string.h
new file mode 100644
index 0000000..458a08a
--- /dev/null
+++ b/Source/Pccts/h/pccts_string.h
@@ -0,0 +1,10 @@
+#ifndef __PCCTS_STRING_H__
+#define __PCCTS_STRING_H__
+
+#ifdef PCCTS_USE_NAMESPACE_STD
+#include <cstring>
+#else
+#include <string.h>
+#endif
+
+#endif
diff --git a/Source/Pccts/h/pcctscfg.h b/Source/Pccts/h/pcctscfg.h
new file mode 100644
index 0000000..0c3c5ba
--- /dev/null
+++ b/Source/Pccts/h/pcctscfg.h
@@ -0,0 +1,359 @@
+#ifndef PCCTS_CONFIG_H
+#define PCCTS_CONFIG_H
+/*
+ * pcctscfg.h (formerly config.h) (for ANTLR, DLG, and SORCERER)
+ *
+ * This is a simple configuration file that doesn't have config stuff
+ * in it, but it's a start.
+ *
+ * SOFTWARE RIGHTS
+ *
+ * We reserve no LEGAL rights to the Purdue Compiler Construction Tool
+ * Set (PCCTS) -- PCCTS is in the public domain. An individual or
+ * company may do whatever they wish with source code distributed with
+ * PCCTS or the code generated by PCCTS, including the incorporation of
+ * PCCTS, or its output, into commerical software.
+ *
+ * We encourage users to develop software with PCCTS. However, we do ask
+ * that credit is given to us for developing PCCTS. By "credit",
+ * we mean that if you incorporate our source code into one of your
+ * programs (commercial product, research project, or otherwise) that you
+ * acknowledge this fact somewhere in the documentation, research report,
+ * etc... If you like PCCTS and have developed a nice tool with the
+ * output, please mention that you developed it using PCCTS. In
+ * addition, we ask that this header remain intact in our source code.
+ * As long as these guidelines are kept, we expect to continue enhancing
+ * this system and expect to make other tools available as they are
+ * completed.
+ *
+ * Used by PCCTS 1.33 (SORCERER 1.00B11 and up)
+ * Terence Parr
+ * Parr Research Corporation
+ * with Purdue University and AHPCRC, University of Minnesota
+ * 1989-2000
+ */
+
+/* This file knows about the following ``environments''
+ UNIX (default)
+ DOS (use #define PC)
+ MAC (use #define MPW; has a few things for THINK C, Metrowerks)
+ MS/C++ (MR14 Microsoft Visual C++ environment uses symbol _MSC_VER)
+
+ */
+
+/* should test __STDC__ for 1, but some compilers don't set value, just def */
+
+#ifndef __USE_PROTOS
+#ifdef __STDC__
+#define __USE_PROTOS
+#endif
+#ifdef __cplusplus
+#define __USE_PROTOS
+#endif
+#endif
+
+#ifdef PCCTS_USE_NAMESPACE_STD
+#define PCCTS_NAMESPACE_STD namespace std {}; using namespace std;
+#else
+#define PCCTS_NAMESPACE_STD
+#endif
+
+#include "pccts_stdio.h"
+#include "pccts_stdlib.h"
+
+/* largest file name size */
+
+#ifdef _MAX_PATH
+#define MaxFileName _MAX_PATH /* MR9 RJV: MAX_PATH defined in stdlib.h (MSVC++ 5.0) */
+#else
+#define MaxFileName 300
+#endif
+
+/*
+* Define PC32 if in a 32-bit PC environment (e.g. extended DOS or Win32).
+* The macros tested here are defined by Watcom, Microsoft, Borland,
+* and djgpp, respectively, when they are used as 32-bit compilers.
+* Users of these compilers *must* be sure to define PC in their
+* makefiles for this to work correctly.
+*/
+#ifdef PC
+# if (defined(__WATCOMC__) || defined(_WIN32) || defined(__WIN32__) || \
+ defined(__GNUC__) || defined(__GNUG__))
+# ifndef PC32
+# define PC32
+# endif
+# endif
+#endif
+
+/* MR1 10-Apr-97 Default for PC is short file names */
+/* MR1 Default for non-PC is long file names */
+/* MR1 Can override via command line option LONGFILENAMES */
+
+#ifndef LONGFILENAMES
+#ifndef PC
+#define LONGFILENAMES
+#endif
+#endif
+
+#ifndef LONGFILENAMES
+#define ATOKEN_H "AToken.h"
+#define ATOKPTR_H "ATokPtr.h"
+#define ATOKPTR_IMPL_H "ATokPtrIm.h"
+#define ATOKENBUFFER_H "ATokBuf.h"
+#define ATOKENBUFFER_C "ATokBuf.cpp"
+#define ATOKENSTREAM_H "ATokStr.h"
+#define APARSER_H "AParser.h"
+#define APARSER_C "AParser.cpp"
+#define ASTBASE_H "ASTBase.h"
+#define ASTBASE_C "ASTBase.cpp"
+#define PCCTSAST_C "PCCTSAST.cpp"
+#define LIST_C "List.cpp"
+#define DLEXERBASE_H "DLexBase.h"
+#define DLEXERBASE_C "DLexBase.cpp"
+#define DLEXER_H "DLexer.h"
+#define STREESUPPORT_C "STreeSup.C"
+#else
+#define ATOKEN_H "AToken.h"
+#define ATOKPTR_H "ATokPtr.h"
+#define ATOKPTR_IMPL_H "ATokPtrImpl.h"
+#define ATOKENBUFFER_H "ATokenBuffer.h"
+#define ATOKENBUFFER_C "ATokenBuffer.cpp"
+#define ATOKENSTREAM_H "ATokenStream.h"
+#define APARSER_H "AParser.h"
+#define APARSER_C "AParser.cpp"
+#define ASTBASE_H "ASTBase.h"
+#define ASTBASE_C "ASTBase.cpp"
+#define PCCTSAST_C "PCCTSAST.cpp"
+#define LIST_C "List.cpp"
+#define DLEXERBASE_H "DLexerBase.h"
+#define DLEXERBASE_C "DLexerBase.cpp"
+#define DLEXER_H "DLexer.h"
+#define STREESUPPORT_C "STreeSupport.cpp"
+#endif
+
+/* SORCERER Stuff */
+
+/* MR8 6-Aug-97 Change from ifdef PC to ifndef LONGFILENAMES */
+
+#ifndef LONGFILENAMES
+#define STPARSER_H "STreePar.h"
+#define STPARSER_C "STreePar.C"
+#else
+#define STPARSER_H "STreeParser.h"
+#define STPARSER_C "STreeParser.cpp"
+#endif
+
+#ifdef MPW
+#define CPP_FILE_SUFFIX ".cp"
+#define CPP_FILE_SUFFIX_NO_DOT "cp"
+#define OBJ_FILE_SUFFIX ".o"
+#else
+#ifdef PC
+#define CPP_FILE_SUFFIX ".cpp"
+#define CPP_FILE_SUFFIX_NO_DOT "cpp"
+#define OBJ_FILE_SUFFIX ".obj"
+#else
+#ifdef __VMS
+#define CPP_FILE_SUFFIX ".cpp"
+#define CPP_FILE_SUFFIX_NO_DOT "cpp"
+#define OBJ_FILE_SUFFIX ".obj"
+#else
+#define CPP_FILE_SUFFIX ".cpp"
+#define CPP_FILE_SUFFIX_NO_DOT "cpp"
+#define OBJ_FILE_SUFFIX ".o"
+#endif
+#endif
+#endif
+
+/* User may redefine how line information looks */ /* make it #line MR7 */
+/* MR21 Use #ifndef */
+
+#ifndef LineInfoFormatStr
+#define LineInfoFormatStr "#line %d \"%s\"\n"
+#endif
+
+#ifdef MPW /* Macintosh Programmer's Workshop */
+#define ErrHdr "File \"%s\"; Line %d #"
+#else
+#ifdef _MSC_VER /* MR14 Microsoft Visual C++ environment */
+#define ErrHdr "%s(%d) :"
+#else
+#define ErrHdr "%s, line %d:" /* default */
+#endif
+#endif
+
+/* must assume old K&R cpp here, can't use #if defined(..)... */
+
+#ifdef MPW
+#define TopDirectory ":"
+#define DirectorySymbol ":"
+#define OutputDirectoryOption "Directory where all output files should go (default=\":\")"
+#else
+#ifdef PC
+#define TopDirectory "."
+#define DirectorySymbol "\\"
+#define OutputDirectoryOption "Directory where all output files should go (default=\".\")"
+#else
+#ifdef __VMS
+#define TopDirectory "[000000]"
+#define DirectorySymbol "]"
+#define OutputDirectoryOption "Directory where all output files should go (default=\"[]\")"
+#else
+#define TopDirectory "."
+#define DirectorySymbol "/"
+#define OutputDirectoryOption "Directory where all output files should go (default=\".\")"
+#endif
+#endif
+#endif
+
+#ifdef MPW
+
+/* Make sure we have prototypes for all functions under MPW */
+
+#include "pccts_string.h"
+#include "pccts_stdlib.h"
+
+/* MR6 2-Jun-97 Fixes false dependency caused by VC++ #include scanner */
+/* MR6 Reported by Brad Schick (schick@interaccess.com) */
+#define MPW_CursorCtl_Header <CursorCtl.h>
+#include MPW_CursorCtl_Header
+#ifdef __cplusplus
+extern "C" {
+#endif
+extern void fsetfileinfo (const char *filename, unsigned long newcreator, unsigned long newtype);
+#ifdef __cplusplus
+}
+#endif
+
+/* File creators for various popular development environments */
+
+#define MAC_FILE_CREATOR 'MPS ' /* MPW Text files */
+#if 0
+#define MAC_FILE_CREATOR 'KAHL' /* THINK C/Symantec C++ Text files */
+#endif
+#if 0
+#define MAC_FILE_CREATOR 'CWIE' /* Metrowerks C/C++ Text files */
+#endif
+
+#endif
+
+#ifdef MPW
+#define DAWDLE SpinCursor(1)
+#else
+#define DAWDLE
+#endif
+
+#ifdef MPW
+#define SPECIAL_INITS
+#define SPECIAL_FOPEN
+#endif
+
+#ifdef MPW
+#ifdef __cplusplus
+inline
+#else
+static
+#endif
+void special_inits()
+{
+ InitCursorCtl((acurHandle) 0);
+}
+#endif
+
+#ifdef MPW
+#ifdef __cplusplus
+inline
+#else
+static
+#endif
+void special_fopen_actions(char * s)
+{
+ fsetfileinfo (s, MAC_FILE_CREATOR, 'TEXT');
+}
+#endif
+
+/* Define usable bits for set.c stuff */
+#define BytesPerWord sizeof(unsigned)
+#define WORDSIZE (sizeof(unsigned)*8)
+#define LogWordSize (WORDSIZE==16?4:5)
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+#if defined(VAXC) || defined(__VMS)
+#include <ssdef.h>
+#define PCCTS_EXIT_SUCCESS 1
+#define PCCTS_EXIT_FAILURE SS$_ABORT
+#define zzDIE return SS$_ABORT;
+#define zzDONE return 1;
+
+#else /* !VAXC and !__VMS */
+
+#define PCCTS_EXIT_SUCCESS 0
+#define PCCTS_EXIT_FAILURE 1
+#define zzDIE return 1;
+#define zzDONE return 0;
+
+#endif
+
+#ifdef USER_ZZMODE_STACK
+# ifndef ZZSTACK_MAX_MODE
+# define ZZSTACK_MAX_MODE 32
+# endif
+# define ZZMAXSTK (ZZSTACK_MAX_MODE * 2)
+#endif
+
+#ifndef DllExportPCCTS
+#define DllExportPCCTS
+#endif
+
+#ifdef PC
+#ifndef PCCTS_CASE_INSENSITIVE_FILE_NAME
+#define PCCTS_CASE_INSENSITIVE_FILE_NAME
+#endif
+#endif
+
+#ifdef PC32
+#ifndef PCCTS_CASE_INSENSITIVE_FILE_NAME
+#define PCCTS_CASE_INSENSITIVE_FILE_NAME
+#endif
+#endif
+
+#ifdef __VMS
+#ifndef PCCTS_CASE_INSENSITIVE_FILE_NAME
+#define PCCTS_CASE_INSENSITIVE_FILE_NAME
+#endif
+#endif
+
+#ifdef __USE_PROTOS
+#ifndef PCCTS_USE_STDARG
+#define PCCTS_USE_STDARG
+#endif
+#endif
+
+#ifdef __STDC__
+#ifndef PCCTS_USE_STDARG
+#define PCCTS_USE_STDARG
+#endif
+#endif
+
+#ifdef __cplusplus
+#ifndef PCCTS_USE_STDARG
+#define PCCTS_USE_STDARG
+#endif
+#endif
+
+#ifdef _MSC_VER
+/*Turn off the warnings for:
+ unreferenced inline/local function has been removed
+*/
+#pragma warning(disable : 4514)
+/* function not expanded */
+#pragma warning(disable : 4710)
+#endif
+
+#endif
diff --git a/Source/Pccts/h/pcnames.bat b/Source/Pccts/h/pcnames.bat
new file mode 100644
index 0000000..8784aee
--- /dev/null
+++ b/Source/Pccts/h/pcnames.bat
@@ -0,0 +1,11 @@
+ren aparser.c aparser.cpp
+ren astbase.c astbase.cpp
+ren atokenbu.c atokbuf.cpp
+ren atokenbu.h atokbuf.h
+ren atokenst.h atokstr.h
+ren dlexerba.c dlexbase.cpp
+ren dlexerba.h dlexbase.h
+ren dlexer.c dlexer.cpp
+ren list.c list.cpp
+ren pblackbo.h pblckbox.h
+ren pcctsast.c pcctsast.cpp
diff --git a/Source/Pccts/h/slist.cpp b/Source/Pccts/h/slist.cpp
new file mode 100644
index 0000000..faf2fe4
--- /dev/null
+++ b/Source/Pccts/h/slist.cpp
@@ -0,0 +1,116 @@
+/*
+ * SList.C
+ *
+ * SOFTWARE RIGHTS
+ *
+ * We reserve no LEGAL rights to SORCERER -- SORCERER is in the public
+ * domain. An individual or company may do whatever they wish with
+ * source code distributed with SORCERER or the code generated by
+ * SORCERER, including the incorporation of SORCERER, or its output, into
+ * commerical software.
+ *
+ * We encourage users to develop software with SORCERER. However, we do
+ * ask that credit is given to us for developing SORCERER. By "credit",
+ * we mean that if you incorporate our source code into one of your
+ * programs (commercial product, research project, or otherwise) that you
+ * acknowledge this fact somewhere in the documentation, research report,
+ * etc... If you like SORCERER and have developed a nice tool with the
+ * output, please mention that you developed it using SORCERER. In
+ * addition, we ask that this header remain intact in our source code.
+ * As long as these guidelines are kept, we expect to continue enhancing
+ * this system and expect to make other tools available as they are
+ * completed.
+ *
+ * PCCTS 1.33
+ * Terence Parr
+ * Parr Research Corporation
+ * with Purdue University and AHPCRC, University of Minnesota
+ * 1992-2000
+ */
+
+#define ANTLR_SUPPORT_CODE
+
+#include "SList.h"
+#include "pccts_stdarg.h" // MR23
+
+/* Iterate over a list of elements; returns ptr to a new element
+ * in list upon every call and NULL when no more are left.
+ * Very useful like this:
+ *
+ * cursor = mylist;
+ * while ( (p=mylist->iterate(&cursor)) ) {
+ * // place with element p
+ * }
+ *
+ * The cursor must be initialized to point to the list to iterate over.
+ */
+void *SList::
+iterate(SListNode **cursor)
+{
+ void *e;
+
+ if ( cursor == NULL || *cursor==NULL ) return NULL;
+ if ( head == *cursor ) { *cursor = (*cursor)->next(); }
+ e = (*cursor)->elem();
+ (*cursor) = (*cursor)->next();
+ return e;
+}
+
+/* add an element to end of list. */
+void SList::
+add(void *e)
+{
+ SListNode *p, *tail=NULL;
+ require(e!=NULL, "slist_add: attempting to add NULL list element");
+
+ p = new SListNode;
+ require(p!=NULL, "add: cannot alloc new list node");
+ p->setElem(e);
+ if ( head == NULL )
+ {
+ head = tail = p;
+ }
+ else /* find end of list */
+ {
+ tail->setNext(p);
+ tail = p;
+ }
+}
+
+void SList::
+lfree()
+{
+ SListNode *p,*q;
+
+ if ( head==NULL ) return; /* empty list */
+ for (p = head; p!=NULL; p=q)
+ {
+ q = p->next();
+ free(p);
+ }
+}
+
+PCCTS_AST *SList::
+to_ast(SList list)
+{
+ PCCTS_AST *t=NULL, *last=NULL;
+ SListNode *p;
+
+ for (p = head; p!=NULL; p=p->next())
+ {
+ PCCTS_AST *u = (PCCTS_AST *)p->elem();
+ if ( last==NULL ) last = t = u;
+ else { last->setRight(u); last = u; }
+ }
+ return t;
+}
+
+// MR23
+int SList::printMessage(FILE* pFile, const char* pFormat, ...)
+{
+ va_list marker;
+ va_start( marker, pFormat );
+ int iRet = vfprintf(pFile, pFormat, marker);
+ va_end( marker );
+ return iRet;
+}
diff --git a/Source/Pccts/history.ps b/Source/Pccts/history.ps
new file mode 100644
index 0000000..e2600d5
--- /dev/null
+++ b/Source/Pccts/history.ps
@@ -0,0 +1,473 @@
+%!PS-Adobe-3.0
+%%Creator: groff version 1.06
+%%DocumentNeededResources: font Times-Roman
+%%+ font Times-Italic
+%%+ font Courier
+%%DocumentSuppliedResources: procset grops 1.06 0
+%%Pages: 3
+%%PageOrder: Ascend
+%%Orientation: Portrait
+%%EndComments
+%%BeginProlog
+%%BeginResource: procset grops 1.06 0
+
+/setpacking where {
+ pop
+ currentpacking
+ true setpacking
+} if
+
+/grops 120 dict dup begin
+
+% The ASCII code of the space character.
+/SC 32 def
+
+/A /show load def
+/B { 0 SC 3 -1 roll widthshow } bind def
+/C { 0 exch ashow } bind def
+/D { 0 exch 0 SC 5 2 roll awidthshow } bind def
+/E { 0 rmoveto show } bind def
+/F { 0 rmoveto 0 SC 3 -1 roll widthshow } bind def
+/G { 0 rmoveto 0 exch ashow } bind def
+/H { 0 rmoveto 0 exch 0 SC 5 2 roll awidthshow } bind def
+/I { 0 exch rmoveto show } bind def
+/J { 0 exch rmoveto 0 SC 3 -1 roll widthshow } bind def
+/K { 0 exch rmoveto 0 exch ashow } bind def
+/L { 0 exch rmoveto 0 exch 0 SC 5 2 roll awidthshow } bind def
+/M { rmoveto show } bind def
+/N { rmoveto 0 SC 3 -1 roll widthshow } bind def
+/O { rmoveto 0 exch ashow } bind def
+/P { rmoveto 0 exch 0 SC 5 2 roll awidthshow } bind def
+/Q { moveto show } bind def
+/R { moveto 0 SC 3 -1 roll widthshow } bind def
+/S { moveto 0 exch ashow } bind def
+/T { moveto 0 exch 0 SC 5 2 roll awidthshow } bind def
+
+% name size font SF -
+
+/SF {
+ findfont exch
+ [ exch dup 0 exch 0 exch neg 0 0 ] makefont
+ dup setfont
+ [ exch /setfont cvx ] cvx bind def
+} bind def
+
+% name a c d font MF -
+
+/MF {
+ findfont
+ [ 5 2 roll
+ 0 3 1 roll % b
+ neg 0 0 ] makefont
+ dup setfont
+ [ exch /setfont cvx ] cvx bind def
+} bind def
+
+/level0 0 def
+/RES 0 def
+/PL 0 def
+/LS 0 def
+
+% Guess the page length.
+% This assumes that the imageable area is vertically centered on the page.
+% PLG - length
+
+/PLG {
+ gsave newpath clippath pathbbox grestore
+ exch pop add exch pop
+} bind def
+
+% BP -
+
+/BP {
+ /level0 save def
+ 1 setlinecap
+ 1 setlinejoin
+ 72 RES div dup scale
+ LS {
+ 90 rotate
+ } {
+ 0 PL translate
+ } ifelse
+ 1 -1 scale
+} bind def
+
+/EP {
+ level0 restore
+ showpage
+} bind def
+
+
+% centerx centery radius startangle endangle DA -
+
+/DA {
+ newpath arcn stroke
+} bind def
+
+% x y SN - x' y'
+% round a position to nearest (pixel + (.25,.25))
+
+/SN {
+ transform
+ .25 sub exch .25 sub exch
+ round .25 add exch round .25 add exch
+ itransform
+} bind def
+
+% endx endy startx starty DL -
+% we round the endpoints of the line, so that parallel horizontal
+% and vertical lines will appear even
+
+/DL {
+ SN
+ moveto
+ SN
+ lineto stroke
+} bind def
+
+% centerx centery radius DC -
+
+/DC {
+ newpath 0 360 arc closepath
+} bind def
+
+
+/TM matrix def
+
+% width height centerx centery DE -
+
+/DE {
+ TM currentmatrix pop
+ translate scale newpath 0 0 .5 0 360 arc closepath
+ TM setmatrix
+} bind def
+
+% these are for splines
+
+/RC /rcurveto load def
+/RL /rlineto load def
+/ST /stroke load def
+/MT /moveto load def
+/CL /closepath load def
+
+% fill the last path
+
+% amount FL -
+
+/FL {
+ currentgray exch setgray fill setgray
+} bind def
+
+% fill with the ``current color''
+
+/BL /fill load def
+
+/LW /setlinewidth load def
+% new_font_name encoding_vector old_font_name RE -
+
+/RE {
+ findfont
+ dup maxlength dict begin
+ {
+ 1 index /FID ne { def } { pop pop } ifelse
+ } forall
+ /Encoding exch def
+ dup /FontName exch def
+ currentdict end definefont pop
+} bind def
+
+/DEFS 0 def
+
+% hpos vpos EBEGIN -
+
+/EBEGIN {
+ moveto
+ DEFS begin
+} bind def
+
+/EEND /end load def
+
+/CNT 0 def
+/level1 0 def
+
+% llx lly newwid wid newht ht newllx newlly PBEGIN -
+
+/PBEGIN {
+ /level1 save def
+ translate
+ div 3 1 roll div exch scale
+ neg exch neg exch translate
+ % set the graphics state to default values
+ 0 setgray
+ 0 setlinecap
+ 1 setlinewidth
+ 0 setlinejoin
+ 10 setmiterlimit
+ [] 0 setdash
+ /setstrokeadjust where {
+ pop
+ false setstrokeadjust
+ } if
+ /setoverprint where {
+ pop
+ false setoverprint
+ } if
+ newpath
+ /CNT countdictstack def
+ userdict begin
+ /showpage {} def
+} bind def
+
+/PEND {
+ clear
+ countdictstack CNT sub { end } repeat
+ level1 restore
+} bind def
+
+end def
+
+/setpacking where {
+ pop
+ setpacking
+} if
+%%EndResource
+%%IncludeResource: font Times-Roman
+%%IncludeResource: font Times-Italic
+%%IncludeResource: font Courier
+grops begin/DEFS 1 dict def DEFS begin/u{.001 mul}bind def end/RES 72 def/PL
+792 def/LS false def/ENC0[/asciicircum/asciitilde/Scaron/Zcaron/scaron/zcaron
+/Ydieresis/trademark/quotesingle/.notdef/.notdef/.notdef/.notdef/.notdef
+/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef
+/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/space
+/exclam/quotedbl/numbersign/dollar/percent/ampersand/quoteright/parenleft
+/parenright/asterisk/plus/comma/hyphen/period/slash/zero/one/two/three/four
+/five/six/seven/eight/nine/colon/semicolon/less/equal/greater/question/at/A/B/C
+/D/E/F/G/H/I/J/K/L/M/N/O/P/Q/R/S/T/U/V/W/X/Y/Z/bracketleft/backslash
+/bracketright/circumflex/underscore/quoteleft/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q
+/r/s/t/u/v/w/x/y/z/braceleft/bar/braceright/tilde/.notdef/quotesinglbase
+/guillemotleft/guillemotright/bullet/florin/fraction/perthousand/dagger
+/daggerdbl/endash/emdash/ff/fi/fl/ffi/ffl/dotlessi/dotlessj/grave/hungarumlaut
+/dotaccent/breve/caron/ring/ogonek/quotedblleft/quotedblright/oe/lslash
+/quotedblbase/OE/Lslash/.notdef/exclamdown/cent/sterling/currency/yen/brokenbar
+/section/dieresis/copyright/ordfeminine/guilsinglleft/logicalnot/minus
+/registered/macron/degree/plusminus/twosuperior/threesuperior/acute/mu
+/paragraph/periodcentered/cedilla/onesuperior/ordmasculine/guilsinglright
+/onequarter/onehalf/threequarters/questiondown/Agrave/Aacute/Acircumflex/Atilde
+/Adieresis/Aring/AE/Ccedilla/Egrave/Eacute/Ecircumflex/Edieresis/Igrave/Iacute
+/Icircumflex/Idieresis/Eth/Ntilde/Ograve/Oacute/Ocircumflex/Otilde/Odieresis
+/multiply/Oslash/Ugrave/Uacute/Ucircumflex/Udieresis/Yacute/Thorn/germandbls
+/agrave/aacute/acircumflex/atilde/adieresis/aring/ae/ccedilla/egrave/eacute
+/ecircumflex/edieresis/igrave/iacute/icircumflex/idieresis/eth/ntilde/ograve
+/oacute/ocircumflex/otilde/odieresis/divide/oslash/ugrave/uacute/ucircumflex
+/udieresis/yacute/thorn/ydieresis]def/Courier@0 ENC0/Courier RE/Times-Italic@0
+ENC0/Times-Italic RE/Times-Roman@0 ENC0/Times-Roman RE
+%%EndProlog
+%%Page: 1 1
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 13/Times-Roman@0 SF(The History of PCCTS)228.232 84 Q/F1 11/Times-Roman@0
+SF(The Purdue Compiler)190.468 108 Q(-Construction T)-.22 E(ool Set)-.88 E/F2
+10/Times-Italic@0 SF -.92(Te)262.245 144 S -.37(re).92 G(nce P).37 E(arr)-.8 E
+/F3 10/Times-Roman@0 SF -.15(Pa)234.755 156 S(rr Research Corporation).15 E
+(Minneapolis, Minnesota)239.39 168 Q(and)280.78 180 Q(Uni)239.315 192 Q -.15
+(ve)-.25 G(rsity of Minnesota).15 E
+(Army High Performance Computing Research Center)180.38 204 Q F2
+([Updated 8-7-94])252.31 228 Q F1 .084(The PCCTS project be)97 259.6 R -.055
+(ga)-.165 G 2.834(na).055 G 2.833(sap)220.547 259.6 S(arser)240.876 259.6 Q
+.083(-generator project for a graduate course at Purdue Uni-)-.22 F -.165(ve)72
+275.6 S 1.085(rsity in the F).165 F 1.086
+(all of 1988 taught by Hank Dietz\212 translator)-.165 F 1.086
+(-writing systems.)-.22 F 1.086(Under the guid-)6.586 F .627
+(ance of Professor Dietz, the parser generator)72 291.6 R 3.377(,A)-.44 G .626
+(NTLR \(originally called YUCC\), continued after)285.18 291.6 R .253
+(the termination of the course and e)72 307.6 R -.165(ve)-.275 G .254
+(ntually became the subject of T).165 F .254(erence P)-.77 F(arr')-.165 E 3.004
+(sM)-.605 G(aster')445.083 307.6 Q 3.004(st)-.605 G(hesis.)479.25 307.6 Q
+(Originally)72 323.6 Q 4.092(,l)-.715 G -.165(ex)126.406 323.6 S 1.342
+(ical analysis w).165 F 1.342(as performed via ALX which w)-.11 F 1.342
+(as soon replaced by W)-.11 F 1.341(ill Cohen')-.44 F(s)-.605 E .594
+(DLG in the F)72 339.6 R .594(all of 1989 \(DF)-.165 F .595(A-based le)-.814 F
+.595(xical-analyzer generator)-.165 F 3.345(,a)-.44 G .595(lso an of)367.188
+339.6 R .595(fshoot of the graduate)-.275 F(translation course\).)72 355.6 Q
+.877(The alpha v)97 375.2 R .877(ersion of ANTLR w)-.165 F .877(as totally re)
+-.11 F .876(written resulting in 1.00B.)-.275 F -1.221(Ve)6.376 G .876
+(rsion 1.00B w)1.221 F(as)-.11 E 1.577(released via an internet ne)72 391.2 R
+1.577(wsgroup \(comp.compilers\) posting in February of 1990 and quickly)-.275
+F -.055(ga)72 407.2 S .356(thered a lar).055 F .356(ge follo)-.198 F 3.106
+(wing. 1.00B)-.275 F .356(generated only LL\(1\) parsers, b)3.106 F .356
+(ut allo)-.22 F .356(wed the mer)-.275 F .356(ged descrip-)-.198 F 1.859
+(tion of le)72 423.2 R 1.859(xical and syntactic analysis.)-.165 F 1.86
+(It had rudimentary attrib)7.359 F 1.86(ute handling similar to that of)-.22 F
+-.55 -1.32(YA C)72 439.2 T 3.549(Ca)1.32 G .799
+(nd did not incorporate rule parameters or return v)109.231 439.2 R .798
+(alues; do)-.275 F(wnw)-.275 E .798(ard inheritance w)-.11 F .798(as v)-.11 F
+(ery)-.165 E -.165(aw)72 455.2 S(kw).165 E 6.433(ard. 1.00B-generated)-.11 F
+3.684(parsers terminated upon the \214rst syntax error)6.433 F 9.184(.L)-.605 G
+-.165(ex)440.916 455.2 S 3.684(ical classes).165 F(\(modes\) were not allo)72
+471.2 Q(wed and DLG did not ha)-.275 E .33 -.165(ve a)-.22 H 2.75(ni).165 G
+(nteracti)305.959 471.2 Q .33 -.165(ve m)-.275 H(ode.).165 E .831
+(Upon starting his Ph.D. at Purdue in the F)97 490.8 R .83(all of 1990, T)-.165
+F .83(erence P)-.77 F .83(arr be)-.165 F -.055(ga)-.165 G 3.58(nt).055 G .83
+(he second total)436.351 490.8 R(re)72 506.8 Q 1.646(write of ANTLR.)-.275 F
+1.646(The method by which grammars may be practically analyzed to generate)
+7.146 F/F4 11/Times-Italic@0 SF(LL)72.638 522.8 Q F1(\().583 E F4(k).396 E F1
+3.849(\)l).737 G 1.099(ookahead information w)105.703 522.8 R 1.099(as disco)
+-.11 F -.165(ve)-.165 G 1.099(red in August of 1990 just before his return.)
+.165 F -1.221(Ve)6.598 G(rsion)1.221 E .626
+(1.00 incorporated this algorithm and included the AST mechanism, le)72 538.8 R
+.626(xical classes, error classes,)-.165 F .354(and automatic error reco)72
+554.8 R -.165(ve)-.165 G .353(ry; code quality and portability were higher).165
+F 5.853(.I)-.605 G 3.103(nF)395.965 554.8 S .353(ebruary of 1992 1.00)410.684
+554.8 R -.11(wa)72 570.8 S 2.76(sr).11 G .01
+(eleased via an article in SIGPLAN Notices.)95.418 570.8 R .01
+(Peter Dahl, Ph.D. candidate, and Professor Matt)5.51 F(O'K)72 586.8 Q 2.074
+(eefe \(both at the Uni)-.275 F -.165(ve)-.275 G 2.073
+(rsity of Minnesota\) tested this v).165 F 2.073(ersion e)-.165 F(xtensi)-.165
+E -.165(ve)-.275 G(ly).165 E 7.573(.D)-.715 G 2.073(ana Hogg)448.522 586.8 R
+(att)-.055 E .078(\(Micro Data Base Systems, Inc.\) came up with the idea of e\
+rror grouping \(strings attached to non-)72 602.8 R
+(terminals\) and tested 1.00 hea)72 618.8 Q(vily)-.22 E(.)-.715 E -1.221(Ve)97
+638.4 S .878(rsion 1.06 w)1.221 F .877
+(as released in December 1992 and represented a lar)-.11 F .877
+(ge feature enhancement)-.198 F -.165(ove)72 654.4 S 3.648(r1).165 G 3.648
+(.00. F)100.365 654.4 R .898(or e)-.165 F .899
+(xample, rudimentary semantic predicates were introduced, error messages were)
+-.165 F 2.281(signi\214cantly impro)72 670.4 R -.165(ve)-.165 G 5.031(df).165 G
+(or)181.953 670.4 Q F4(k)5.427 E F1 2.281
+(>1 lookahead and ANTLR parsers could indicate that lookahead).737 F 1.381
+(fetches were to occur only when necessary for the parse \(normally)72 686.4 R
+4.131(,t)-.715 G 1.381(he lookahead `)387.051 686.4 R(`pipe')-.814 E 4.132('w)
+-.814 G(as)494.837 686.4 Q 1.182(constantly full\).)72 702.4 R 1.182
+(Russell Quong joined the project in the Spring of 1992 to aid in the semantic)
+6.682 F .681(predicate design.)72 718.4 R(Be)6.181 E .681(ginning and adv)-.165
+F .682(anced tutorials were created and released as well.)-.275 F 3.432(Am)
+6.182 G(ak)485.179 718.4 Q(e-)-.11 E .993(\214le generator w)72 734.4 R .993
+(as included that sets up dependencies and such correctly for ANTLR and DLG.)
+-.11 F EP
+%%Page: 2 2
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 11/Times-Roman@0 SF 2.75(-2-)278.837 52 S -1.221(Ve)72 88 S 1.414(ry fe)
+1.221 F 4.164(w1)-.275 G 1.414(.00 incompatibilities were introduced \(1.00 w)
+122.81 88 R 1.415(as quite dif)-.11 F 1.415(ferent from 1.00B in some)-.275 F
+(areas\).)72 104 Q 1.089(1.10 w)97 123.6 R 1.088
+(as released on August 31, 1993 and incorporated b)-.11 F 1.088(ug \214x)-.22 F
+1.088(es, a fe)-.165 F 3.838(wf)-.275 G 1.088(eature enhance-)433.59 123.6 R
+3.112(ments and a major ne)72 139.6 R 5.863(wc)-.275 G(apability \212)196.957
+139.6 Q 3.113(an arbitrary lookahead operator \(syntactic predicate\),)5.863 F
+/F1 11/Courier@0 SF(\(alpha\)?beta)72 155.6 Q F0 6.754(.T)C 1.254
+(his feature w)167.425 155.6 R 1.254
+(as co-designed with Professor Russell Quong also at Purdue.)-.11 F 3.297 -.88
+(To s)72 171.6 T 1.537
+(upport in\214nite lookahead, a preprocessor \215ag, ZZINF_LOOK, w).88 F 1.537
+(as created that forced the)-.11 F .21(ANTLR\(\) macro to tok)72 187.6 R .21
+(enize all input prior to parsing.)-.11 F .209(Hence, at an)5.709 F 2.959(ym)
+-.165 G .209(oment, an action or predi-)389.215 187.6 R .936
+(cate can see the entire input sentence.)72 203.6 R .936
+(The predicate mechanism of 1.06 w)6.436 F .937(as e)-.11 F .937
+(xtended to allo)-.165 F(w)-.275 E .55
+(multiple predicates to be hoisted; the syntactic conte)72 219.6 R .55
+(xt of a predicate w)-.165 F .55(as also mo)-.11 F -.165(ve)-.165 G 3.299(da)
+.165 G .549(long with)461.585 219.6 R(the predicate.)72 235.6 Q .754
+(In February of 1994, SORCERER \(a simple tree-parser generator\) w)97 255.2 R
+.755(as released.)-.11 F .755(This tool)6.255 F(allo)72 271.2 Q .6(ws the user\
+ to parse child-sibling trees by specifying a grammar rather than b)-.275 F
+.599(uilding a recur)-.22 F(-)-.22 E(si)72 287.2 Q -.165(ve)-.275 G 1.39
+(-descent tree w).165 F(alk)-.11 E 1.391(er by hand.)-.11 F -.88(Wo)6.891 G
+1.391(rk to).88 F -.11(wa)-.275 G 1.391
+(rds a library of tree transformations is underw).11 F(ay)-.11 E(.)-.715 E .581
+(Aaron Sa)72 303.2 R(wde)-.165 E 3.331(ya)-.165 G 3.331(tT)145.531 303.2 S .581
+(he Uni)158.641 303.2 R -.165(ve)-.275 G .58
+(rsity of Minnesota became a second author of SORCERER after the).165 F
+(initial release.)72 319.2 Q .627(On April 1, 1994, PCCTS 1.20 w)97 338.8 R
+.627(as released.)-.11 F .627(This w)6.127 F .627(as the \214rst v)-.11 F .627
+(ersion to acti)-.165 F -.165(ve)-.275 G .627(ly support).165 F 1.664
+(C++ output.)72 354.8 R 1.664(It also included important \214x)7.164 F 1.663
+(es re)-.165 F -.055(ga)-.165 G 1.663
+(rding semantic predicates and \(..\)+ subrules.).055 F(This v)72 370.8 Q
+(ersion also introduced tok)-.165 E(en classes, the `)-.11 E(`)-.814 E/F2 11
+/Times-Italic@0 SF(not)A F0 1.628 -.814('' o)D(perator).814 E 2.75(,a)-.44 G
+(nd tok)355.294 370.8 Q(en ranges.)-.11 E .764
+(On June 19, 1994, SORCERER 1.00B9 w)97 390.4 R .765(as released.)-.11 F .765
+(Gary Funck of Intrepid T)6.265 F(echnology)-.77 E .807
+(joined the SORCERER team and pro)72 406.4 R .807(vided v)-.165 F .807(ery v)
+-.165 F .807(aluable suggestions re)-.275 F -.055(ga)-.165 G .806(rding the `)
+.055 F(`transform')-.814 E(')-.814 E(mode of SORCERER.)72 422.4 Q 1.137
+(On August 8, 1994, PCCTS 1.21 w)97 442 R 1.137(as released.)-.11 F 1.138
+(It mainly cleaned up the C++ output and)6.637 F(included a number of b)72 458
+Q(ug \214x)-.22 E(es.)-.165 E .316(From the 1.21 release forw)97 477.6 R .316
+(ard, the maintenance and support of all PCCTS tools will be pri-)-.11 F 1.557
+(marily pro)72 493.6 R 1.557(vided by P)-.165 F 1.557
+(arr Research Corporation, Minneapolis MN---an or)-.165 F -.055(ga)-.198 G
+1.558(nization founded on).055 F 1.616(the principles of e)72 509.6 R 1.616
+(xcellence in research and inte)-.165 F 1.616(grity in b)-.165 F 1.616
+(usiness; we are de)-.22 F -.22(vo)-.275 G 1.616(ted to pro).22 F(viding)-.165
+E 1.202(really cool softw)72 525.6 R 1.202(are tools.)-.11 F 1.202
+(Please see \214le PCCTS.FUTURE for more information.)6.702 F 1.203(All PCCTS)
+6.703 F(tools currently in the public domain will continue to be in the public\
+ domain.)72 541.6 Q 1.198(Looking to)97 561.2 R -.11(wa)-.275 G 1.198
+(rds the future, a graphical user).11 F(-interf)-.22 E 1.197
+(ace is in the design phase.)-.11 F 1.197(This w)6.697 F(ould)-.11 E(allo)72
+577.2 Q 2.753(wu)-.275 G .003(sers to vie)104.42 577.2 R 2.753(wt)-.275 G .004
+(he syntax diagram representation of their grammars and w)162.509 577.2 R .004
+(ould highlight non-)-.11 F 1.181(deterministic productions.)72 593.2 R -.165
+(Pa)6.681 G 1.18(rsing can be traced graphically as well.).165 F 1.18
+(This system will be b)6.68 F(uilt)-.22 E .167(using a multiplatform windo)72
+609.2 R 2.917(wl)-.275 G(ibrary)211.73 609.2 Q 5.667(.W)-.715 G 2.917(ea)
+255.204 609.2 S .168(lso anticipate the introduction of a sophisticated error)
+267.889 609.2 R(handling mechanism called `)72 625.2 Q(`parser e)-.814 E
+(xception handling')-.165 E 2.75('i)-.814 G 2.75(nan)327.431 625.2 S
+(ear future release.)348.815 625.2 Q(Currently)97 644.8 Q 3.019(,P)-.715 G .269
+(CCTS is used at o)150.333 644.8 R -.165(ve)-.165 G 3.019(r1).165 G .269
+(000 kno)253.098 644.8 R .268(wn academic, go)-.275 F -.165(ve)-.165 G .268
+(rnment, and commercial sites).165 F .859(in 37 countries.)72 660.8 R .859
+(Of course, the true number of users is unkno)6.359 F .859(wn due to the lar)
+-.275 F .859(ge number of ftp)-.198 F(sites.)72 676.8 Q EP
+%%Page: 3 3
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 11/Times-Roman@0 SF 2.75(-3-)278.837 52 S(Credits)272.11 88 Q .44 LW
+472.162 103.75 103.838 103.75 DL(Idea/T)134.236 117 Q 52.987(ool Coder)-.88 F
+(Co-designer\(s\))345.436 117 Q 281.334 103.75 281.334 124.75 DL 209.273 103.75
+209.273 124.75 DL 209.273 124.75 103.838 124.75 DL 103.838 126.75 209.273
+126.75 DL 281.334 124.75 209.273 124.75 DL 209.273 126.75 281.334 126.75 DL
+472.162 124.75 281.334 124.75 DL 281.334 126.75 472.162 126.75 DL(ANTLR 1.00A)
+109.338 140 Q -.77(Te)217.523 140 S(rence P).77 E 13.75(arr Hank)-.165 F(Dietz)
+2.75 E 82.83(ALX T)109.338 156 R(erence P)-.77 E 13.75(arr Hank)-.165 F(Dietz)
+2.75 E(ANTLR 1.00B)109.338 172 Q -.77(Te)217.523 172 S(rence P).77 E 13.75
+(arr Hank)-.165 F(Dietz, W)2.75 E(ill Cohen)-.44 E(DLG 1.00B)109.338 188 Q -.44
+(Wi)217.523 188 S(ll Cohen).44 E -.77(Te)289.584 188 S(rence P).77 E(arr)-.165
+E 2.75(,H)-.44 G(ank Dietz)358.147 188 Q(NF)109.338 204 Q 2.75(AR)-.814 G
+30.778(elabelling W)140.611 204 R(ill Cohen)-.44 E/F1 11/Times-Italic@0 SF(LL)
+109.976 220 Q F0(\().583 E F1(k).396 E F0 2.75(\)a).737 G 40.447(nalysis T)
+143.768 220 R(erence P)-.77 E 13.75(arr Hank)-.165 F(Dietz)2.75 E(ANTLR 1.00)
+109.338 236 Q -.77(Te)217.523 236 S(rence P).77 E 13.75(arr Hank)-.165 F
+(Dietz, W)2.75 E(ill Cohen)-.44 E(DLG 1.00)109.338 252 Q -.44(Wi)217.523 252 S
+(ll Cohen).44 E -.77(Te)289.584 252 S(rence P).77 E(arr)-.165 E 2.75(,H)-.44 G
+(ank Dietz)358.147 252 Q(ANTLR 1.06)109.338 268 Q -.77(Te)217.523 268 S
+(rence P).77 E 13.75(arr W)-.165 F(ill Cohen, Russell Quong, Hank Dietz)-.44 E
+(DLG 1.06)109.338 284 Q -.44(Wi)217.523 284 S(ll Cohen).44 E -.77(Te)289.584
+284 S(rence P).77 E(arr)-.165 E 2.75(,H)-.44 G(ank Dietz)358.147 284 Q
+(ANTLR 1.10)109.338 300 Q -.77(Te)217.523 300 S(rence P).77 E 13.75(arr W)-.165
+F(ill Cohen, Russell Quong)-.44 E(ANTLR 1.20)109.338 316 Q -.77(Te)217.523 316
+S(rence P).77 E 13.75(arr W)-.165 F(ill Cohen, Russell Quong)-.44 E(ANTLR 1.21)
+109.338 332 Q -.77(Te)217.523 332 S(rence P).77 E 13.75(arr Russell)-.165 F
+(Quong)2.75 E(DLG 1.10)109.338 348 Q -.44(Wi)217.523 348 S(ll Cohen).44 E -.77
+(Te)289.584 348 S(rence P).77 E(arr)-.165 E(DLG 1.20)109.338 364 Q -.44(Wi)
+217.523 364 S(ll Cohen).44 E -.77(Te)289.584 364 S(rence P).77 E(arr)-.165 E
+(DLG 1.21)109.338 380 Q -.77(Te)217.523 380 S(rence P).77 E(arr)-.165 E
+(Semantic predicates)109.338 396 Q -.77(Te)217.523 396 S(rence P).77 E 13.75
+(arr Russell)-.165 F(Quonq)2.75 E(Syntactic predicates)109.338 412 Q -.77(Te)
+217.523 412 S(rence P).77 E 13.75(arr Russell)-.165 F(Quonq)2.75 E
+(SORCERER 1.00A)109.338 428 Q -.77(Te)217.523 428 S(rence P).77 E(arr)-.165 E
+(SORCERER 1.00B)109.338 444 Q -.77(Te)217.523 444 S(rence P).77 E 13.75
+(arr Aaron)-.165 F(Sa)2.75 E(wde)-.165 E(y)-.165 E(SORCERER 1.00B9)109.338 460
+Q -.77(Te)217.523 460 S(rence P).77 E 13.75(arr Aaron)-.165 F(Sa)2.75 E(wde)
+-.165 E 1.43 -.715(y, G)-.165 H(ary Funck).715 E 472.162 467.75 103.838 467.75
+DL 472.162 103.75 472.162 467.75 DL 103.838 103.75 103.838 467.75 DL EP
+%%Trailer
+end
+%%EOF
diff --git a/Source/Pccts/history.txt b/Source/Pccts/history.txt
new file mode 100644
index 0000000..89ad840
--- /dev/null
+++ b/Source/Pccts/history.txt
@@ -0,0 +1,186 @@
+
+
+
+ The History of PCCTS
+
+ The Purdue Compiler-Construction Tool Set
+
+
+ Terence Parr
+ Parr Research Corporation
+ Minneapolis, Minnesota
+ and
+ University of Minnesota
+ Army High Performance Computing Research Center
+
+ [Updated 8-7-94]
+
+
+ The PCCTS project began as a parser-generator project for a gra-
+duate course at Purdue University in the Fall of 1988 taught by Hank
+Dietz- translator-writing systems. Under the guidance of Professor
+Dietz, the parser generator, ANTLR (originally called YUCC), continued
+after the termination of the course and eventually became the subject
+of Terence Parr's Master's thesis. Originally, lexical analysis was
+performed via ALX which was soon replaced by Will Cohen's DLG in the
+Fall of 1989 (DFA-based lexical-analyzer generator, also an offshoot
+of the graduate translation course).
+
+ The alpha version of ANTLR was totally rewritten resulting in
+1.00B. Version 1.00B was released via an internet newsgroup
+(comp.compilers) posting in February of 1990 and quickly gathered a
+large following. 1.00B generated only LL(1) parsers, but allowed the
+merged description of lexical and syntactic analysis. It had rudimen-
+tary attribute handling similar to that of YACC and did not incor-
+porate rule parameters or return values; downward inheritance was very
+awkward. 1.00B-generated parsers terminated upon the first syntax
+error. Lexical classes (modes) were not allowed and DLG did not have
+an interactive mode.
+
+ Upon starting his Ph.D. at Purdue in the Fall of 1990, Terence
+Parr began the second total rewrite of ANTLR. The method by which
+grammars may be practically analyzed to generate LL(k) lookahead
+information was discovered in August of 1990 just before his return.
+Version 1.00 incorporated this algorithm and included the AST mechan-
+ism, lexical classes, error classes, and automatic error recovery;
+code quality and portability were higher. In February of 1992 1.00
+was released via an article in SIGPLAN Notices. Peter Dahl, Ph.D.
+candidate, and Professor Matt O'Keefe (both at the University of Min-
+nesota) tested this version extensively. Dana Hoggatt (Micro Data
+Base Systems, Inc.) came up with the idea of error grouping (strings
+attached to non-terminals) and tested 1.00 heavily.
+
+ Version 1.06 was released in December 1992 and represented a
+large feature enhancement over 1.00. For example, rudimentary seman-
+tic predicates were introduced, error messages were significantly
+improved for k>1 lookahead and ANTLR parsers could indicate that loo-
+kahead fetches were to occur only when necessary for the parse
+
+
+
+ Page 1
+
+ PCCTS
+
+
+(normally, the lookahead "pipe" was constantly full). Russell Quong
+joined the project in the Spring of 1992 to aid in the semantic predi-
+cate design. Beginning and advanced tutorials were created and
+released as well. A makefile generator was included that sets up
+dependencies and such correctly for ANTLR and DLG. Very few 1.00
+incompatibilities were introduced (1.00 was quite different from 1.00B
+in some areas).
+
+ 1.10 was released on August 31, 1993 and incorporated bug fixes,
+a few feature enhancements and a major new capability - an arbitrary
+lookahead operator (syntactic predicate), (alpha)?beta. This feature
+was co-designed with Professor Russell Quong also at Purdue. To sup-
+port infinite lookahead, a preprocessor flag, ZZINF_LOOK, was created
+that forced the ANTLR() macro to tokenize all input prior to parsing.
+Hence, at any moment, an action or predicate can see the entire input
+sentence. The predicate mechanism of 1.06 was extended to allow mul-
+tiple predicates to be hoisted; the syntactic context of a predicate
+was also moved along with the predicate.
+
+ In February of 1994, SORCERER (a simple tree-parser generator)
+was released. This tool allows the user to parse child-sibling trees
+by specifying a grammar rather than building a recursive-descent tree
+walker by hand. Work towards a library of tree transformations is
+underway. Aaron Sawdey at The University of Minnesota became a second
+author of SORCERER after the initial release.
+
+ On April 1, 1994, PCCTS 1.20 was released. This was the first
+version to actively support C++ output. It also included important
+fixes regarding semantic predicates and (..)+ subrules. This version
+also introduced token classes, the "not" operator, and token ranges.
+
+ On June 19, 1994, SORCERER 1.00B9 was released. Gary Funck of
+Intrepid Technology joined the SORCERER team and provided very valu-
+able suggestions regarding the "transform" mode of SORCERER.
+
+ On August 8, 1994, PCCTS 1.21 was released. It mainly cleaned up
+the C++ output and included a number of bug fixes.
+
+ From the 1.21 release forward, the maintenance and support of all
+PCCTS tools will be primarily provided by Parr Research Corporation,
+Minneapolis MN---an organization founded on the principles of excel-
+lence in research and integrity in business; we are devoted to provid-
+ing really cool software tools. Please see file PCCTS.FUTURE for more
+information. All PCCTS tools currently in the public domain will con-
+tinue to be in the public domain.
+
+ Looking towards the future, a graphical user-interface is in the
+design phase. This would allow users to view the syntax diagram
+representation of their grammars and would highlight nondeterministic
+productions. Parsing can be traced graphically as well. This system
+will be built using a multiplatform window library. We also antici-
+pate the introduction of a sophisticated error handling mechanism
+called "parser exception handling" in a near future release.
+
+
+
+
+ Page 2
+
+ PCCTS
+
+
+ Currently, PCCTS is used at over 1000 known academic, government,
+and commercial sites in 37 countries. Of course, the true number of
+users is unknown due to the large number of ftp sites.
+ Credits
+
+_____________________________________________________________________________
+_____________________________________________________________________________
+|ANTLR 1.00A Terence Parr Hank Dietz |
+|ALX Terence Parr Hank Dietz |
+|ANTLR 1.00B Terence Parr Hank Dietz, Will Cohen |
+|DLG 1.00B Will Cohen Terence Parr, Hank Dietz |
+|NFA Relabelling Will Cohen |
+|LL(k) analysis Terence Parr Hank Dietz |
+|ANTLR 1.00 Terence Parr Hank Dietz, Will Cohen |
+|DLG 1.00 Will Cohen Terence Parr, Hank Dietz |
+|ANTLR 1.06 Terence Parr Will Cohen, Russell Quong, Hank Dietz|
+|DLG 1.06 Will Cohen Terence Parr, Hank Dietz |
+|ANTLR 1.10 Terence Parr Will Cohen, Russell Quong |
+|ANTLR 1.20 Terence Parr Will Cohen, Russell Quong |
+|ANTLR 1.21 Terence Parr Russell Quong |
+|DLG 1.10 Will Cohen Terence Parr |
+|DLG 1.20 Will Cohen Terence Parr |
+|DLG 1.21 Terence Parr |
+|Semantic predicates Terence Parr Russell Quonq |
+|Syntactic predicates Terence Parr Russell Quonq |
+|SORCERER 1.00A Terence Parr |
+|SORCERER 1.00B Terence Parr Aaron Sawdey |
+|SORCERER 1.00B9 Terence Parr Aaron Sawdey, Gary Funck |
+|___________________________________________________________________________|
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Page 3
+
diff --git a/Source/Pccts/makefile b/Source/Pccts/makefile
new file mode 100644
index 0000000..f9b2dd2
--- /dev/null
+++ b/Source/Pccts/makefile
@@ -0,0 +1,66 @@
+#
+# Main makefile for PCCTS 1.33MR33 /* MRXXX */
+#
+# Terence Parr
+# Parr Research Corporation
+#
+# verbosity versus silence...
+PSss=
+#
+# this can be set to /user/local/bin etc...
+BINDIR=bin
+# This part added by Thomas Herter, M"unchen, Germany. See also manpages
+# target.
+MANDIR=$(HOME)/man
+MANEXT=1
+MANFILES=dlg/dlg.1 antlr/antlr.1
+
+#CC=cc
+#CC=gcc
+#COPT=-O2
+
+pccts:
+ @echo " "
+ @echo " Welcome to PCCTS 1.33MR33 installation"
+ @echo " "
+ @echo " (Version 1.33 Maintenance Release #33)" # mrxxx
+ @echo " "
+ @echo " Released 19 April 2002"
+ @echo " "
+ @echo " Featuring"
+ @echo " ANTLR -- ANother Tool for Language Recognition"
+ @echo " DLG -- DFA-based Lexical Analyzer Generator"
+ @echo " SORCERER -- Source-to-source translator (tree walker)"
+ @echo " "
+ @echo " http://www.antlr.org"
+ @echo " "
+ @echo " Trouble reports to tmoog@polhode.com"
+ @echo " Additional PCCTS 1.33 information at"
+ @echo " http://www.polhode.com"
+ @echo
+ @echo
+ @echo "To substitute gcc for CC to invoke compiler: make CC=gcc"
+ @echo "If there are problems with cr and lf try: unzip -a ..."
+ @echo
+#
+ @if [ ! -d $(BINDIR) ] ; then mkdir $(BINDIR) ; fi
+ @echo Making executables...
+ (cd ./antlr; $(MAKE) CC="$(CC)" COPT="$(COPT)")
+ @echo antlr executable now in $(BINDIR)
+ (cd ./dlg; $(MAKE) CC="$(CC)" COPT="$(COPT)")
+ @echo dlg executable now in $(BINDIR)
+ @echo
+ @echo " PCCTS 1.33MR33 installation complete" # MRXXX
+
+clean:
+ (cd ./antlr; $(MAKE) -s clean)
+ (cd ./dlg; $(MAKE) -s clean)
+
+
+manpages:
+ # mkdir -p $(MANDIR)/man$(MANEXT)
+ if [ ! -d $(MANDIR) ] ; then \
+ mkdir $(MANDIR) ; fi
+ if [ ! -d $(MANDIR)/man$(MANEXT) ] ; then \
+ mkdir $(MANDIR)/man$(MANEXT); fi
+ cp -p $(MANFILES) $(MANDIR)/man$(MANEXT)
diff --git a/Source/Pccts/support/genmk/genmk.c b/Source/Pccts/support/genmk/genmk.c
new file mode 100644
index 0000000..4952a30
--- /dev/null
+++ b/Source/Pccts/support/genmk/genmk.c
@@ -0,0 +1,1063 @@
+/*
+ * genmk -- a program to make makefiles for PCCTS
+ *
+ * ANTLR 1.33MR23
+ * Terence John Parr 1989 - 2000
+ * Purdue University
+ * U of MN
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include "pcctscfg.h" /* be sensitive to what ANTLR/DLG call the files */
+
+#ifdef VAXC
+#define DIE return 0;
+#define DONE return 1;
+#else
+#define DIE return 1;
+#define DONE return 0;
+#endif
+
+#ifndef require
+#define require(expr, err) {if ( !(expr) ) fatal(err);}
+#endif
+
+#define MAX_FILES 50
+#define MAX_CFILES 1600
+#define MAX_SFILES 50
+#define MAX_SORS 50
+#define MAX_CLASSES 50
+
+char *RENAME_OBJ_FLAG="-o",
+ *RENAME_EXE_FLAG="-o";
+
+char *dlg = "parser.dlg";
+char *err = "err.c";
+char *hdr = "stdpccts.h";
+char *tok = "tokens.h";
+char *mode = "mode.h";
+char *scan = "scan";
+
+char ATOKENBUFFER_O[100];
+char APARSER_O[100];
+char ASTBASE_O[100];
+char PCCTSAST_O[100];
+char LIST_O[100];
+char DLEXERBASE_O[100];
+
+/* Option flags */
+static char *project="t", *files[MAX_FILES], *classes[MAX_CLASSES];
+static char *cfiles[MAX_CFILES];
+static char *sfiles[MAX_SORS][MAX_SFILES],*sclasses[MAX_SORS];
+static int num_sfiles[MAX_SORS]; /*sorcerer files in group */
+static int num_sors = 0; /*sorcerer groups */
+static int num_files = 0; /* grammar files */
+static int num_cfiles = 0; /* additional C/C++ files */
+static int num_classes = 0; /* ANTLR classes */
+static int user_lexer = 0;
+static char *user_token_types = NULL;
+static int gen_CPP = 0;
+static char *outdir=".";
+static char *dlg_class = "DLGLexer";
+static int gen_trees = 0;
+static int gen_hoist = 0;
+static int nondef_comp = 0; /* 1=compiler is non default */
+static char *compilerCCC="CC";
+static char *compilerCC="cc";
+static char *pccts_path="/usr/local/pccts";
+
+#ifdef __STDC__
+void help(void);
+void mk(char *project, char **files, int n, int argc, char **argv);
+void pfiles(char **files, int n, char *suffix);
+void fatal(char *msg);
+void warn(char *msg);
+#else
+void help();
+void mk();
+void pfiles();
+void fatal();
+void warn();
+#endif
+
+typedef struct _Opt {
+ char *option;
+ int arg;
+#ifdef __cplusplus
+ void (*process)(...);
+#else
+ void (*process)();
+#endif
+ char *descr;
+ } Opt;
+
+#ifdef __STDC__
+static void ProcessArgs(int, char **, Opt *);
+#else
+static void ProcessArgs();
+#endif
+
+static void
+#ifdef __STDC__
+pProj(char *s, char *t )
+#else
+pProj( s, t )
+char *s;
+char *t;
+#endif
+{
+ project = t;
+}
+
+static void
+#ifdef __STDC__
+pUL( char *s )
+#else
+pUL( s )
+char *s;
+#endif
+{
+ user_lexer = 1;
+}
+
+static void
+#ifdef __STDC__
+pCPP( char *s )
+#else
+pCPP( s )
+char *s;
+#endif
+{
+ gen_CPP = 1;
+}
+
+static void
+#ifdef __STDC__
+pUT( char *s, char *t )
+#else
+pUT( s, t )
+char *s;
+char *t;
+#endif
+{
+ user_token_types = t;
+}
+
+static void
+#ifdef __STDC__
+pTrees( char *s )
+#else
+pTrees( s )
+char *s;
+#endif
+{
+ gen_trees = 1;
+}
+
+static void
+#ifdef __STDC__
+pHoist( char *s )
+#else
+pHoist( s )
+char *s;
+#endif
+{
+ gen_hoist = 1;
+}
+
+static void
+#ifdef __STDC__
+pSor( char *s )
+#else
+pSor( s )
+char *s;
+#endif
+{
+ require(num_sors<MAX_SORS, "exceeded max # of sorcerer groups");
+ num_sors++;
+ pTrees(NULL); /* silently turn on tree generation */
+}
+
+static void
+#ifdef __STDC__
+pSFiles( char *s, char *t )
+#else
+pSFiles( s, t )
+char *s;
+char *t;
+#endif
+{
+ if (num_sors==0)
+ {
+ pSor(NULL);
+ warn("sorcerer input file before any '-sor' option");
+ }
+
+ require(num_sfiles[num_sors-1]<MAX_SFILES,
+ "exceeded max # of sorcerer input files");
+ sfiles[num_sors-1][num_sfiles[num_sors-1]++] = t;
+}
+
+static void
+#ifdef __STDC__
+pCFiles( char *s, char *t )
+#else
+pCFiles( s, t )
+char *s;
+char *t;
+#endif
+{
+ require(num_cfiles<MAX_CFILES, "exceeded max # of C/C++ input files");
+ cfiles[num_cfiles++] = t;
+}
+
+int
+#ifdef __STDC__
+isKnownSuffix( char *s )
+#else
+isKnownSuffix( s )
+ char *s;
+#endif
+{
+ if(s==NULL) return 0;
+ if (strcasecmp(s,".c")==0) return 1;
+ if (strcasecmp(s,".cc")==0) return 1;
+ if (strcasecmp(s,".cpp")==0) return 1;
+ if (strcasecmp(s,".cxx")==0) return 1;
+ if (strcasecmp(s,CPP_FILE_SUFFIX)==0) return 1;
+ if (strcasecmp(s,".sor")==0) return 2;
+ return 0;
+}
+
+static void
+#ifdef __STDC__
+pFile( char *s )
+#else
+pFile( s )
+char *s;
+#endif
+{
+ if ( *s=='-' )
+ {
+ fprintf(stderr, "invalid option: '%s'; ignored...",s);
+ return;
+ }
+ switch(isKnownSuffix(strrchr(s,'.')))
+ {
+ case 1: /* c/c++ */
+ pCFiles("-cfiles",s);
+ return;
+ case 2: /* sorcerer */
+ pSFiles("",s);
+ return;
+ default: /* grammar (ANTLR) */
+ break;
+ }
+ require(num_files<MAX_FILES, "exceeded max # of input files");
+ files[num_files++] = s;
+}
+
+static void
+#ifdef __STDC__
+pClass( char *s, char *t )
+#else
+pClass( s, t )
+char *s;
+char *t;
+#endif
+{
+ if (num_sors==0)
+ {
+ require(num_classes<MAX_CLASSES, "exceeded max # of grammar classes");
+ classes[num_classes++] = t;
+ } else
+ {
+ sclasses[num_sors-1] = t; /* one class per sorcerer group (last valid) */
+ }
+}
+
+static void
+#ifdef __STDC__
+pDLGClass( char *s, char *t )
+#else
+pDLGClass( s, t )
+char *s;
+char *t;
+#endif
+{
+ if ( !gen_CPP ) {
+ fprintf(stderr, "-dlg-class makes no sense without C++ mode; ignored...");
+ }
+ else dlg_class = t;
+}
+
+static void
+#ifdef __STDC__
+pOdir( char *s, char *t )
+#else
+pOdir( s, t )
+char *s;
+char *t;
+#endif
+{
+ outdir = t;
+}
+
+static void
+#ifdef __STDC__
+pHdr( char *s, char *t )
+#else
+pHdr( s, t )
+char *s;
+char *t;
+#endif
+{
+ hdr = t;
+}
+
+static void
+#ifdef __STDC__
+pCompiler( char *s, char *t )
+#else
+pCompiler( s, t )
+char *s;
+char *t;
+#endif
+{
+ compilerCCC = t;
+ compilerCC = t;
+ nondef_comp = 1;
+}
+
+static void
+#ifdef __STDC__
+ppccts_path( char *s, char *t )
+#else
+ppccts_path( s, t )
+char *s;
+char *t;
+#endif
+{
+ pccts_path = t;
+}
+
+Opt options[] = {
+ { "-CC", 0, pCPP, "Generate C++ output"},
+ { "-class", 1, pClass, "Name of a grammar class defined in grammar (if C++)"},
+ { "-dlg-class", 1,pDLGClass,"Name of DLG lexer class (default=DLGLexer) (if C++)"},
+ { "-header", 1,pHdr, "Name of ANTLR standard header info (default=no file)"},
+ { "-o", 1, pOdir, "Directory where output files should go (default=\".\")"},
+ { "-project", 1, pProj, "Name of executable to create (default=t)"},
+ { "-token-types", 1, pUT, "Token types are in this file (don't use tokens.h)"},
+ { "-trees", 0, pTrees, "Generate ASTs"},
+ { "-user-lexer", 0, pUL, "Do not create a DLG-based scanner"},
+ { "-mrhoist",0,pHoist, "Maintenance release style hoisting"},
+ { "-cfiles",1,pCFiles, "Additional files in C or C++ to compile"},
+ { "-sor",0,pSor, "Start of sorcerer group"},
+ { "-pccts_path",1,ppccts_path,
+ "Path for $PCCTS directory (default is /usr/local/pccts)"},
+ { "-compiler",1,pCompiler,
+ "Default compiler (default is CC/cc)"},
+ { "*", 0,pFile, "" }, /* anything else is a file */
+ { NULL, 0, NULL, NULL }
+};
+
+#ifdef __STDC__
+extern char *DIR(void);
+#else
+extern char *DIR();
+#endif
+
+#ifdef __STDC__
+int main(int argc, char **argv)
+#else
+int main(argc, argv)
+int argc;
+char **argv;
+#endif
+{
+ int i;
+
+ if ( argc == 1 ) { help(); DIE; }
+ for(i=0;i<MAX_SORS;i++) num_sfiles[i]=0;
+
+ ProcessArgs(argc-1, &(argv[1]), options);
+
+ strcpy(ATOKENBUFFER_O, ATOKENBUFFER_C);
+ ATOKENBUFFER_O[strlen(ATOKENBUFFER_C)-strlen(CPP_FILE_SUFFIX)] = '\0';
+ strcat(ATOKENBUFFER_O, OBJ_FILE_SUFFIX);
+ strcpy(APARSER_O, APARSER_C);
+ APARSER_O[strlen(APARSER_O)-strlen(CPP_FILE_SUFFIX)] = '\0';
+ strcat(APARSER_O, OBJ_FILE_SUFFIX);
+
+ strcpy(ASTBASE_O, ASTBASE_C);
+ ASTBASE_O[strlen(ASTBASE_C)-strlen(CPP_FILE_SUFFIX)] = '\0';
+ strcat(ASTBASE_O, OBJ_FILE_SUFFIX);
+
+ strcpy(PCCTSAST_O, PCCTSAST_C);
+ PCCTSAST_O[strlen(PCCTSAST_C)-strlen(CPP_FILE_SUFFIX)] = '\0';
+ strcat(PCCTSAST_O, OBJ_FILE_SUFFIX);
+
+ strcpy(LIST_O, LIST_C);
+ LIST_O[strlen(LIST_C)-strlen(CPP_FILE_SUFFIX)] = '\0';
+ strcat(LIST_O, OBJ_FILE_SUFFIX);
+
+ strcpy(DLEXERBASE_O, DLEXERBASE_C);
+ DLEXERBASE_O[strlen(DLEXERBASE_C)-strlen(CPP_FILE_SUFFIX)] = '\0';
+ strcat(DLEXERBASE_O, OBJ_FILE_SUFFIX);
+
+ if ( num_files == 0 ) fatal("no grammar files specified; exiting...");
+ if ( !gen_CPP && num_classes>0 ) {
+ warn("can't define classes w/o C++ mode; turning on C++ mode...\n");
+ gen_CPP=1;
+ }
+ if (!gen_CPP && num_sors) {
+ warn("can't define sorcerer group in C mode (yet); turning on C++ mode...\n");
+ gen_CPP=1;
+ }
+ if ( gen_CPP && num_classes==0 ) {
+ fatal("must define classes >0 grammar classes in C++ mode\n");
+ }
+
+ mk(project, files, num_files, argc, argv);
+ DONE;
+}
+
+#ifdef __STDC__
+void help(void)
+#else
+void help()
+#endif
+{
+ Opt *p = options;
+ static char buf[1000+1];
+
+ fprintf(stderr, "genmk [options] f1.g ... fn.g\n");
+ while ( p->option!=NULL && *(p->option) != '*' )
+ {
+ buf[0]='\0';
+ if ( p->arg ) sprintf(buf, "%s ___", p->option);
+ else strcpy(buf, p->option);
+ fprintf(stderr, "\t%-16s %s\n", buf, p->descr);
+ p++;
+ }
+}
+
+#ifdef __STDC__
+void mk(char *project, char **files, int n, int argc, char **argv)
+#else
+void mk(project, files, n, argc, argv)
+char *project;
+char **files;
+int n;
+int argc;
+char **argv;
+#endif
+{
+ int i,j;
+
+ printf("#\n");
+ printf("# PCCTS makefile for: ");
+ pfiles(files, n, NULL);
+ printf("\n");
+ printf("#\n");
+ printf("# Created from:");
+ for (i=0; i<argc; i++) printf(" %s", argv[i]);
+ printf("\n");
+ printf("#\n");
+ printf("# PCCTS release 1.33MR23\n");
+ printf("# Project: %s\n", project);
+ if ( gen_CPP ) printf("# C++ output\n");
+ else printf("# C output\n");
+ if ( user_lexer ) printf("# User-defined scanner\n");
+ else printf("# DLG scanner\n");
+ if ( user_token_types!=NULL ) printf("# User-defined token types in '%s'\n", user_token_types);
+ else printf("# ANTLR-defined token types\n");
+ printf("#\n");
+/***********
+ printf(".SUFFIXES:\n.SUFFIXES:\t.o .cpp .c .h .g .i .dlg .sor\n");
+ ***********/
+ if ( user_token_types!=NULL ) {
+ printf("# Make sure #tokdefs directive in ANTLR grammar lists this file:\n");
+ printf("TOKENS = %s", user_token_types);
+ }
+ else printf("TOKENS = %stokens.h", DIR());
+ printf("\n");
+ printf("#\n");
+ printf("# The following filenames must be consistent with ANTLR/DLG flags\n");
+ printf("DLG_FILE = %s%s\n", DIR(), dlg);
+ printf("ERR = %serr\n", DIR());
+ if ( strcmp(hdr,"stdpccts.h")!=0 ) printf("HDR_FILE = %s%s\n", DIR(), hdr);
+ else printf("HDR_FILE =\n");
+ if ( !gen_CPP ) printf("MOD_FILE = %s%s\n", DIR(), mode);
+ if ( !gen_CPP ) printf("SCAN = %s\n", scan);
+ else printf("SCAN = %s%s\n", DIR(), dlg_class);
+
+ printf("PCCTS = %s\n",pccts_path);
+ printf("ANTLR_H = $(PCCTS)%sh\n", DirectorySymbol);
+ if (num_sors>0) {
+ printf("SOR_H = $(PCCTS)%ssorcerer%sh\n", DirectorySymbol, DirectorySymbol);
+ printf("SOR_LIB = $(PCCTS)%ssorcerer%slib\n",
+ DirectorySymbol, DirectorySymbol);
+ }
+ printf("BIN = $(PCCTS)%sbin\n", DirectorySymbol);
+ printf("ANTLR = $(BIN)%santlr\n", DirectorySymbol);
+ printf("DLG = $(BIN)%sdlg\n", DirectorySymbol);
+ if (num_sors>0) printf("SOR = $(BIN)%ssor\n", DirectorySymbol);
+ printf("CFLAGS = -I. -I$(ANTLR_H)");
+ if (num_sors>0) printf(" -I$(SOR_H)");
+ if ( strcmp(outdir, ".")!=0 ) printf(" -I%s", outdir);
+ printf(" $(COTHER)");
+ printf("\n");
+ printf("AFLAGS =");
+ if ( strcmp(outdir,".")!=0 ) printf(" -o %s", outdir);
+ if ( user_lexer ) printf(" -gx");
+ if ( gen_CPP ) printf(" -CC");
+ if ( strcmp(hdr,"stdpccts.h")!=0 ) printf(" -gh %s", hdr);
+ if ( gen_trees ) printf(" -gt");
+ if ( gen_hoist ) {
+ printf(" -mrhoist on") ;
+ } else {
+ printf(" -mrhoist off");
+ };
+ printf(" $(AOTHER)");
+ printf("\n");
+ printf("DFLAGS = -C2 -i");
+ if ( gen_CPP ) printf(" -CC");
+ if ( strcmp(dlg_class,"DLGLexer")!=0 ) printf(" -cl %s", dlg_class);
+ if ( strcmp(outdir,".")!=0 ) printf(" -o %s", outdir);
+ printf(" $(DOTHER)");
+ printf("\n");
+ if (num_sors>0)
+ {
+ printf("SFLAGS = -CPP");
+ if ( strcmp(outdir,".")!=0 ) printf(" -out-dir %s", outdir);
+ printf(" $(SOTHER)\n");
+ }
+ printf("GRM = ");
+ pfiles(files, n, NULL);
+ printf("\n");
+ printf("SRC = ");
+ if ( gen_CPP ) pfiles(files, n, CPP_FILE_SUFFIX_NO_DOT);
+ else pfiles(files, n, "c");
+ if ( gen_CPP ) {
+ printf(" \\\n\t");
+ pclasses(classes, num_classes, CPP_FILE_SUFFIX_NO_DOT);
+ printf(" \\\n\t");
+ printf("$(ANTLR_H)%s%s", DirectorySymbol, APARSER_C);
+ if ( !user_lexer ) printf(" $(ANTLR_H)%s%s", DirectorySymbol, DLEXERBASE_C);
+ if ( gen_trees ) {
+ printf(" \\\n\t");
+ printf("$(ANTLR_H)%s%s", DirectorySymbol, ASTBASE_C);
+ printf(" $(ANTLR_H)%s%s", DirectorySymbol, PCCTSAST_C);
+/* printf(" $(ANTLR_H)%s%s", DirectorySymbol, LIST_C); */
+ printf(" \\\n\t");
+ }
+ printf(" $(ANTLR_H)%s%s", DirectorySymbol, ATOKENBUFFER_C);
+ }
+ if ( !user_lexer ) {
+ if ( gen_CPP ) printf(" $(SCAN)%s", CPP_FILE_SUFFIX);
+ else printf(" %s$(SCAN).c", DIR());
+ }
+ if ( !gen_CPP ) printf(" $(ERR).c");
+ for (i=0;i<num_sors;i++)
+ {
+ printf(" \\\n\t");
+ pclasses(&sclasses[i],1,CPP_FILE_SUFFIX_NO_DOT);
+ printf(" ");
+ pfiles(&sfiles[i][0],num_sfiles[i],CPP_FILE_SUFFIX_NO_DOT);
+ }
+ if(num_sors>0)
+ printf(" \\\n\t$(SOR_LIB)%sSTreeParser.cpp", DirectorySymbol);
+ if (num_cfiles>0)
+ {
+ printf(" \\\n\t");
+ pfiles(cfiles,num_cfiles,NULL);
+ }
+ printf("\n\n");
+ printf("OBJ = ");
+ pfiles(files, n, "o");
+ if ( gen_CPP ) {
+ printf(" \\\n\t");
+ pclasses(classes, num_classes, "o");
+ printf(" \\\n\t");
+ printf("%s%s", DIR(), APARSER_O);
+ if ( !user_lexer ) {
+ printf(" %s%s", DIR(), DLEXERBASE_O);
+ }
+ if ( gen_trees ) {
+ printf(" \\\n\t");
+ printf("%s%s", DIR(), ASTBASE_O);
+ printf(" %s%s", DIR(), PCCTSAST_O);
+/* printf(" %s%s", DIR(), LIST_O); */
+ printf(" \\\n\t");
+ }
+ printf(" %s%s", DIR(), ATOKENBUFFER_O);
+ }
+ if ( !user_lexer ) {
+ if ( gen_CPP ) printf(" $(SCAN)%s", OBJ_FILE_SUFFIX);
+ else printf(" %s$(SCAN)%s", DIR(), OBJ_FILE_SUFFIX);
+ }
+ if ( !gen_CPP ) printf(" $(ERR)%s", OBJ_FILE_SUFFIX);
+ for (i=0;i<num_sors;i++)
+ {
+ printf(" \\\n\t");
+ pclasses(&sclasses[i],1,"o");
+ printf(" ");
+ pfiles(&sfiles[i][0],num_sfiles[i],"o");
+ }
+ if(num_sors>0) printf(" \\\n\tSTreeParser.o");
+ if (num_cfiles>0)
+ {
+ printf(" \\\n\t");
+ pfiles(cfiles,num_cfiles,"o");
+ }
+ printf("\n\n");
+
+ printf("ANTLR_SPAWN = ");
+ if ( gen_CPP ) pfiles(files, n, CPP_FILE_SUFFIX_NO_DOT);
+ else pfiles(files, n, "c");
+ if ( gen_CPP ) {
+ printf(" ");
+ pclasses(classes, num_classes, CPP_FILE_SUFFIX_NO_DOT);
+ printf(" \\\n\t\t");
+ pclasses(classes, num_classes, "h");
+ if ( strcmp(hdr,"stdpccts.h")!=0 ) {
+ printf(" \\\n\t\t");
+ printf("$(HDR_FILE) stdpccts.h");
+ }
+ }
+ if ( user_lexer ) {
+ if ( !user_token_types ) printf(" $(TOKENS)");
+ }
+ else {
+ printf(" $(DLG_FILE)");
+ if ( !user_token_types ) printf(" $(TOKENS)");
+ }
+ if ( !gen_CPP ) printf(" $(ERR).c");
+ printf("\n");
+
+ if ( !user_lexer ) {
+ if ( gen_CPP ) printf("DLG_SPAWN = $(SCAN)%s", CPP_FILE_SUFFIX);
+ else printf("DLG_SPAWN = %s$(SCAN).c", DIR());
+ if ( gen_CPP ) printf(" $(SCAN).h");
+ if ( !gen_CPP ) printf(" $(MOD_FILE)");
+ printf("\n");
+ }
+
+ if ( gen_CPP ) {
+ if ( !nondef_comp )
+ printf("ifdef CXX\nCCC = $(CXX)\nendif\n\nifndef CCC\n");
+ printf("CCC = %s\n",compilerCCC);
+ if ( !nondef_comp ) printf("endif\n\n");
+ }
+ else
+ {
+ if ( !nondef_comp ) printf("ifndef CC\n");
+ printf("CC = %s\n",compilerCC);
+ if ( !nondef_comp ) printf("endif\n\n");
+ }
+
+ /* set up dependencies */
+ printf("\n%s : $(SRC) $(OBJ)\n", project);
+ printf("\t%s %s %s $(CFLAGS) $(OBJ)\n",
+ gen_CPP?"$(CCC)":"$(CC)",
+ RENAME_EXE_FLAG,
+ project);
+ printf("\n");
+
+ /* implicit rules */
+
+/* if(gen_CPP)
+ printf("%%.o : %%.cpp\n\t$(CCC) -c $(CFLAGS) $<\n\n");
+
+ printf("%%.o : %%.c\n\t%s -c $(CFLAGS) $<\n\n",
+ gen_CPP?"$(CCC)":"$(CC)");
+*/
+ /* how to compile parser files */
+
+ for (i=0; i<num_files; i++)
+ {
+ pfiles(&files[i], 1, "o");
+ if ( user_lexer ) {
+ printf(" : $(TOKENS)");
+ }
+ else {
+ if ( gen_CPP ) printf(" : $(TOKENS) $(SCAN).h");
+ else printf(" : $(MOD_FILE) $(TOKENS)");
+ }
+ printf(" ");
+ if ( gen_CPP ) pfiles(&files[i], 1, CPP_FILE_SUFFIX_NO_DOT);
+ else pfiles(&files[i], 1, "c");
+ if ( gen_CPP && strcmp(hdr,"stdpccts.h")!=0 ) printf(" $(HDR_FILE)");
+ printf("\n");
+ printf("\t%s -c $(CFLAGS) %s ",
+ gen_CPP?"$(CCC)":"$(CC)",RENAME_OBJ_FLAG);
+ pfiles(&files[i], 1, "o");
+ printf(" ");
+ if ( gen_CPP ) pfiles(&files[i], 1, CPP_FILE_SUFFIX_NO_DOT);
+ else pfiles(&files[i], 1, "c");
+ printf("\n\n");
+ }
+
+ for (i=0; i<num_cfiles; i++)
+ {
+ pfiles(&cfiles[i], 1, "o");
+ printf(" : ");
+ pfiles(&cfiles[i], 1, NULL);
+ if ( gen_CPP && strcmp(hdr,"stdpccts.h")!=0 ) printf(" $(HDR_FILE)");
+/*** printf(" "); ***/
+/*** pfiles(&cfiles[i], 1, "h"); ***/
+ printf("\n");
+ printf("\t%s -c $(CFLAGS) %s ",
+ gen_CPP?"$(CCC)":"$(CC)",RENAME_OBJ_FLAG);
+ pfiles(&cfiles[i], 1, "o");
+ printf(" ");
+ pfiles(&cfiles[i], 1, NULL);
+ printf("\n\n");
+
+/*
+ * pfiles(&cfiles[i], 1, "h");
+ * printf(" :\ntouch ");
+ * pfiles(&cfiles[i], 1, "h");
+ * printf("\n\n");
+ */
+ }
+
+ /* how to compile err.c */
+ if ( !gen_CPP ) {
+ printf("$(ERR)%s : $(ERR).c", OBJ_FILE_SUFFIX);
+ if ( !user_lexer ) printf(" $(TOKENS)");
+ printf("\n");
+ printf("\t%s -c $(CFLAGS) %s $(ERR)%s $(ERR).c",
+ gen_CPP?"$(CCC)":"$(CC)",
+ RENAME_OBJ_FLAG,
+ OBJ_FILE_SUFFIX);
+ printf("\n\n");
+ }
+
+ /* how to compile Class.c */
+ for (i=0; i<num_classes; i++)
+ {
+ pclasses(&classes[i], 1, "o");
+ if ( user_lexer ) {
+ printf(" : $(TOKENS)");
+ }
+ else {
+ printf(" : $(TOKENS) $(SCAN).h");
+ }
+ printf(" ");
+ pclasses(&classes[i], 1, CPP_FILE_SUFFIX_NO_DOT);
+ printf(" ");
+ pclasses(&classes[i], 1, "h");
+ if ( gen_CPP && strcmp(hdr,"stdpccts.h")!=0 ) printf(" $(HDR_FILE)");
+ printf("\n");
+ printf("\t%s -c $(CFLAGS) %s ",
+ gen_CPP?"$(CCC)":"$(CC)",
+ RENAME_OBJ_FLAG);
+ pclasses(&classes[i], 1, "o");
+ printf(" ");
+ pclasses(&classes[i], 1, CPP_FILE_SUFFIX_NO_DOT);
+ printf("\n\n");
+ }
+
+ /* how to compile scan.c */
+ if ( !user_lexer ) {
+ if ( gen_CPP ) printf("$(SCAN)%s : $(SCAN)%s", OBJ_FILE_SUFFIX, CPP_FILE_SUFFIX);
+ else printf("%s$(SCAN)%s : %s$(SCAN).c", DIR(), OBJ_FILE_SUFFIX, DIR());
+ if ( !user_lexer ) printf(" $(TOKENS)");
+ printf("\n");
+ if ( gen_CPP ) printf("\t$(CCC) -c $(CFLAGS) %s $(SCAN)%s $(SCAN)%s",
+ RENAME_OBJ_FLAG,
+ OBJ_FILE_SUFFIX,
+ CPP_FILE_SUFFIX);
+ else printf("\t$(CC) -c $(CFLAGS) %s %s$(SCAN)%s %s$(SCAN).c",
+ RENAME_OBJ_FLAG,
+ DIR(),
+ OBJ_FILE_SUFFIX,
+ DIR());
+ printf("\n\n");
+ }
+/* how to compile sorcerer classes */
+ for (i=0;i<num_sors;i++)
+ {
+ pclasses(&sclasses[i], 1, "o");
+ printf(" : ");
+ pclasses(&sclasses[i], 1, CPP_FILE_SUFFIX_NO_DOT);
+ printf(" ");
+ pclasses(&sclasses[i], 1, "h");
+ if ( gen_CPP && strcmp(hdr,"stdpccts.h")!=0 ) printf(" $(HDR_FILE)");
+ printf("\n");
+ printf("\t%s -c $(CFLAGS) %s ",
+ gen_CPP?"$(CCC)":"$(CC)",
+ RENAME_OBJ_FLAG);
+ pclasses(&sclasses[i], 1, "o");
+ printf(" ");
+ pclasses(&sclasses[i], 1, CPP_FILE_SUFFIX_NO_DOT);
+ printf("\n\n");
+/* how to compile i-th sorcerer's files*/
+ for (j=0; j<num_sfiles[i]; j++)
+ {
+ pfiles(&sfiles[i][j], 1, "o");
+ printf(" : ");
+ if ( gen_CPP ) pfiles(&sfiles[i][j], 1, CPP_FILE_SUFFIX_NO_DOT);
+ else pfiles(&sfiles[i][j], 1, "c");
+ if ( gen_CPP && strcmp(hdr,"stdpccts.h")!=0 ) printf(" $(HDR_FILE)");
+ printf("\n");
+ printf("\t%s -c $(CFLAGS) %s ",
+ gen_CPP?"$(CCC)":"$(CC)",RENAME_OBJ_FLAG);
+ pfiles(&sfiles[i][j], 1, "o");
+ printf(" ");
+ if ( gen_CPP ) pfiles(&sfiles[i][j], 1, CPP_FILE_SUFFIX_NO_DOT);
+ else pfiles(&sfiles[i][j], 1, "c");
+ printf("\n\n");
+ }
+ if ( gen_CPP ) pfiles(&sfiles[i][0], num_sfiles[i], CPP_FILE_SUFFIX_NO_DOT);
+ else pfiles(&sfiles[i][0], num_sfiles[i], "c");
+ if ( gen_CPP )
+ {
+ printf(" ");
+ pclasses(&sclasses[i], 1, CPP_FILE_SUFFIX_NO_DOT);
+ printf(" ");
+ pclasses(&sclasses[i], 1, "h");
+ if ( strcmp(hdr,"stdpccts.h")!=0 )
+ {
+ printf(" ");
+ printf("$(HDR_FILE) stdpccts.h");
+ }
+ }
+ printf(" : ");
+ pfiles(&sfiles[i][0],num_sfiles[i],NULL);
+ printf("\n\t$(SOR) $(SFLAGS) ");
+ pfiles(&sfiles[i][0],num_sfiles[i],NULL);
+ printf("\n\n");
+ }
+ if(num_sors>0)
+ {
+ printf("STreeParser%s : $(SOR_LIB)%sSTreeParser.cpp\n",
+ OBJ_FILE_SUFFIX,DirectorySymbol);
+ printf("\t%s -c $(CFLAGS) %s ",
+ gen_CPP?"$(CCC)":"$(CC)",RENAME_OBJ_FLAG);
+ printf("STreeParser%s ",OBJ_FILE_SUFFIX);
+ printf("$(SOR_LIB)%sSTreeParser.cpp\n\n",DirectorySymbol);
+ }
+
+ printf("$(ANTLR_SPAWN) : $(GRM)\n");
+ printf("\t$(ANTLR) $(AFLAGS) $(GRM)\n");
+
+ if ( !user_lexer )
+ {
+ printf("\n");
+ printf("$(DLG_SPAWN) : $(DLG_FILE)\n");
+ if ( gen_CPP ) printf("\t$(DLG) $(DFLAGS) $(DLG_FILE)\n");
+ else printf("\t$(DLG) $(DFLAGS) $(DLG_FILE) $(SCAN).c\n");
+ }
+
+ /* do the makes for ANTLR/DLG support */
+ if ( gen_CPP ) {
+ printf("\n");
+ printf("%s%s : $(ANTLR_H)%s%s\n", DIR(), APARSER_O, DirectorySymbol, APARSER_C);
+ printf("\t%s -c $(CFLAGS) %s ",
+ gen_CPP?"$(CCC)":"$(CC)",
+ RENAME_OBJ_FLAG);
+ printf("%s%s $(ANTLR_H)%s%s\n", DIR(), APARSER_O, DirectorySymbol, APARSER_C);
+ printf("\n");
+ printf("%s%s : $(ANTLR_H)%s%s\n", DIR(), ATOKENBUFFER_O, DirectorySymbol, ATOKENBUFFER_C);
+ printf("\t%s -c $(CFLAGS) %s ",
+ gen_CPP?"$(CCC)":"$(CC)",
+ RENAME_OBJ_FLAG);
+ printf("%s%s $(ANTLR_H)%s%s\n", DIR(), ATOKENBUFFER_O, DirectorySymbol, ATOKENBUFFER_C);
+ if ( !user_lexer ) {
+ printf("\n");
+ printf("%s%s : $(ANTLR_H)%s%s\n", DIR(), DLEXERBASE_O, DirectorySymbol, DLEXERBASE_C);
+ printf("\t%s -c $(CFLAGS) %s ",
+ gen_CPP?"$(CCC)":"$(CC)",
+ RENAME_OBJ_FLAG);
+ printf("%s%s $(ANTLR_H)%s%s\n", DIR(), DLEXERBASE_O, DirectorySymbol, DLEXERBASE_C);
+ }
+ if ( gen_trees ) {
+ printf("\n");
+ printf("%s%s : $(ANTLR_H)%s%s\n", DIR(), ASTBASE_O, DirectorySymbol, ASTBASE_C);
+ printf("\t%s -c $(CFLAGS) %s ",
+ gen_CPP?"$(CCC)":"$(CC)",
+ RENAME_OBJ_FLAG);
+ printf("%s%s $(ANTLR_H)%s%s\n", DIR(), ASTBASE_O, DirectorySymbol, ASTBASE_C);
+ printf("\n");
+ printf("%s%s : $(ANTLR_H)%s%s\n", DIR(), PCCTSAST_O, DirectorySymbol, PCCTSAST_C);
+ printf("\t%s -c $(CFLAGS) %s ",
+ gen_CPP?"$(CCC)":"$(CC)",
+ RENAME_OBJ_FLAG);
+ printf("%s%s $(ANTLR_H)%s%s\n", DIR(), PCCTSAST_O, DirectorySymbol, PCCTSAST_C);
+ printf("\n");
+/*
+ printf("%s%s : $(ANTLR_H)%s%s\n", DIR(), LIST_O, DirectorySymbol, LIST_C);
+ printf("\t%s -c $(CFLAGS) %s ",
+ gen_CPP?"$(CCC)":"$(CC)",RENAME_OBJ_FLAG);
+ printf("%s%s $(ANTLR_H)%s%s\n", DIR(), LIST_O, DirectorySymbol, LIST_C);
+*/
+ }
+ }
+
+ /* clean and scrub targets */
+
+ printf("\nclean:\n");
+ printf("\trm -f *%s core %s", OBJ_FILE_SUFFIX, project);
+ if ( strcmp(outdir, ".")!=0 ) printf(" %s*%s", DIR(), OBJ_FILE_SUFFIX);
+ printf("\n");
+
+ printf("\nscrub: clean\n");
+/* printf("\trm -f *%s core %s", OBJ_FILE_SUFFIX, project); */
+/* if ( strcmp(outdir, ".")!=0 ) printf(" %s*%s", DIR(), OBJ_FILE_SUFFIX); */
+ printf("\trm -f $(ANTLR_SPAWN)");
+ if ( !user_lexer ) printf(" $(DLG_SPAWN)");
+ for (i=0;i<num_sors;i++)
+ {
+ printf(" ");
+ if ( gen_CPP ) pfiles(&sfiles[i][0], num_sfiles[i], CPP_FILE_SUFFIX_NO_DOT);
+ else pfiles(&sfiles[i][0], num_sfiles[i], "c");
+ if ( gen_CPP )
+ {
+ printf(" ");
+ pclasses(&sclasses[i], 1, CPP_FILE_SUFFIX_NO_DOT);
+ printf(" ");
+ pclasses(&sclasses[i], 1, "h");
+ }
+ }
+ printf("\n\n");
+}
+
+#ifdef __STDC__
+void pfiles(char **files, int n, char *suffix)
+#else
+void pfiles(files, n, suffix)
+char **files;
+int n;
+char *suffix;
+#endif
+{
+ int first=1;
+
+ while ( n>0 )
+ {
+ char *p = &(*files)[strlen(*files)-1];
+ if ( !first ) putchar(' ');
+ first=0;
+ while ( p > *files && *p != '.' ) --p;
+ if ( p == *files )
+ {
+ fprintf(stderr,
+ "genmk: filenames must be file.suffix format: %s\n",
+ *files);
+ exit(-1);
+ }
+ if ( suffix == NULL ) printf("%s", *files);
+ else
+ {
+ *p = '\0';
+ printf("%s", DIR());
+ if ( strcmp(suffix, "o")==0 ) printf("%s%s", *files, OBJ_FILE_SUFFIX);
+ else printf("%s.%s", *files, suffix);
+ *p = '.';
+ }
+ files++;
+ --n;
+ }
+}
+
+#ifdef __STDC__
+pclasses(char **classes, int n, char *suffix)
+#else
+pclasses(classes, n, suffix)
+char **classes;
+int n;
+char *suffix;
+#endif
+{
+ int first=1;
+
+ while ( n>0 )
+ {
+ if ( !first ) putchar(' ');
+ first=0;
+ if ( suffix == NULL ) printf("%s", *classes);
+ else {
+ printf("%s", DIR());
+ if ( strcmp(suffix, "o")==0 ) printf("%s%s", *classes, OBJ_FILE_SUFFIX);
+ else printf("%s.%s", *classes, suffix);
+ }
+ classes++;
+ --n;
+ }
+}
+
+static void
+#ifdef __STDC__
+ProcessArgs( int argc, char **argv, Opt *options )
+#else
+ProcessArgs( argc, argv, options )
+int argc;
+char **argv;
+Opt *options;
+#endif
+{
+ Opt *p;
+ require(argv!=NULL, "ProcessArgs: command line NULL");
+
+ while ( argc-- > 0 )
+ {
+ p = options;
+ while ( p->option != NULL )
+ {
+ if ( strcmp(p->option, "*") == 0 ||
+ strcmp(p->option, *argv) == 0 )
+ {
+ if ( p->arg )
+ {
+ (*p->process)( *argv, *(argv+1) );
+ argv++;
+ argc--;
+ }
+ else
+ (*p->process)( *argv );
+ break;
+ }
+ p++;
+ }
+ argv++;
+ }
+}
+
+#ifdef __STDC__
+void fatal( char *err_)
+#else
+void fatal( err_)
+char *err_;
+#endif
+{
+ fprintf(stderr, "genmk: %s\n", err_);
+ exit(1);
+}
+
+#ifdef __STDC__
+void warn( char *err_)
+#else
+void warn( err_)
+char *err_;
+#endif
+{
+ fprintf(stderr, "genmk: %s\n", err_);
+}
+
+#ifdef __STDC__
+char *DIR(void)
+#else
+char *DIR()
+#endif
+{
+ static char buf[200+1];
+
+ if ( strcmp(outdir,TopDirectory)==0 ) return "";
+ sprintf(buf, "%s%s", outdir, DirectorySymbol);
+ return buf;
+}
diff --git a/Source/Pccts/support/genmk/genmk_old.c b/Source/Pccts/support/genmk/genmk_old.c
new file mode 100644
index 0000000..2cf9fad
--- /dev/null
+++ b/Source/Pccts/support/genmk/genmk_old.c
@@ -0,0 +1,762 @@
+/*
+ * genmk -- a program to make makefiles for PCCTS
+ *
+ * ANTLR 1.33MR10
+ * Terence John Parr 1989 - 1998
+ * Purdue University
+ * U of MN
+ */
+
+#include <stdio.h>
+#include "pcctscfg.h" /* be sensitive to what ANTLR/DLG call the files */
+
+#ifdef VAXC
+#define DIE return 0;
+#define DONE return 1;
+#else
+#define DIE return 1;
+#define DONE return 0;
+#endif
+
+#ifndef require
+#define require(expr, err) {if ( !(expr) ) fatal(err);}
+#endif
+
+#define MAX_FILES 50
+#define MAX_CLASSES 50
+
+char *RENAME_OBJ_FLAG="-o",
+ *RENAME_EXE_FLAG="-o";
+
+char *dlg = "parser.dlg";
+char *err = "err.c";
+char *hdr = "stdpccts.h";
+char *tok = "tokens.h";
+char *mode = "mode.h";
+char *scan = "scan";
+
+char ATOKENBUFFER_O[100];
+char APARSER_O[100];
+char ASTBASE_O[100];
+char PCCTSAST_O[100];
+char LIST_O[100];
+char DLEXERBASE_O[100];
+
+/* Option flags */
+static char *project="t", *files[MAX_FILES], *classes[MAX_CLASSES];
+static int num_files = 0;
+static int num_classes = 0;
+static int user_lexer = 0;
+static char *user_token_types = NULL;
+static int gen_CPP = 0;
+static char *outdir=".";
+static char *dlg_class = "DLGLexer";
+static int gen_trees = 0;
+static int gen_hoist = 0;
+static char cfiles[1600]="";
+static char *compilerCCC="CC";
+static char *compilerCC="cc";
+static char *pccts_path="/usr/local/pccts";
+
+void help();
+void mk();
+void pfiles();
+void pclasses();
+void fatal();
+void warn();
+
+typedef struct _Opt {
+ char *option;
+ int arg;
+#ifdef __cplusplus
+ void (*process)(...);
+#else
+ void (*process)();
+#endif
+ char *descr;
+ } Opt;
+
+#ifdef __STDC__
+static void ProcessArgs(int, char **, Opt *);
+#else
+static void ProcessArgs();
+#endif
+
+static void
+pProj( s, t )
+char *s;
+char *t;
+{
+ project = t;
+}
+
+static void
+pUL( s )
+char *s;
+{
+ user_lexer = 1;
+}
+
+static void
+pCPP( s )
+char *s;
+{
+ gen_CPP = 1;
+}
+
+static void
+pUT( s, t )
+char *s;
+char *t;
+{
+ user_token_types = t;
+}
+
+static void
+pTrees( s )
+char *s;
+{
+ gen_trees = 1;
+}
+
+static void
+pHoist( s )
+char *s;
+{
+ gen_hoist = 1;
+}
+
+static void
+#ifdef __STDC__
+pFile( char *s )
+#else
+pFile( s )
+char *s;
+#endif
+{
+ if ( *s=='-' )
+ {
+ fprintf(stderr, "invalid option: '%s'; ignored...",s);
+ return;
+ }
+
+ require(num_files<MAX_FILES, "exceeded max # of input files");
+ files[num_files++] = s;
+}
+
+static void
+#ifdef __STDC__
+pClass( char *s, char *t )
+#else
+pClass( s, t )
+char *s;
+char *t;
+#endif
+{
+ require(num_classes<MAX_CLASSES, "exceeded max # of grammar classes");
+ classes[num_classes++] = t;
+}
+
+static void
+#ifdef __STDC__
+pDLGClass( char *s, char *t )
+#else
+pDLGClass( s, t )
+char *s;
+char *t;
+#endif
+{
+ if ( !gen_CPP ) {
+ fprintf(stderr, "-dlg-class makes no sense without C++ mode; ignored...");
+ }
+ else dlg_class = t;
+}
+
+static void
+#ifdef __STDC__
+pOdir( char *s, char *t )
+#else
+pOdir( s, t )
+char *s;
+char *t;
+#endif
+{
+ outdir = t;
+}
+
+static void
+#ifdef __STDC__
+pHdr( char *s, char *t )
+#else
+pHdr( s, t )
+char *s;
+char *t;
+#endif
+{
+ hdr = t;
+}
+
+static void
+#ifdef __STDC__
+pCFiles( char *s, char *t )
+#else
+pCFiles( s, t )
+char *s;
+char *t;
+#endif
+{
+ strcat(strcat(cfiles," "), t);
+}
+
+static void
+#ifdef __STDC__
+pCompiler( char *s, char *t )
+#else
+pCompiler( s, t )
+char *s;
+char *t;
+#endif
+{
+ compilerCCC = t;
+ compilerCC = t;
+}
+
+static void
+#ifdef __STDC__
+ppccts_path( char *s, char *t )
+#else
+ppccts_path( s, t )
+char *s;
+char *t;
+#endif
+{
+ pccts_path = t;
+}
+
+Opt options[] = {
+ { "-CC", 0, pCPP, "Generate C++ output"},
+ { "-class", 1, pClass, "Name of a grammar class defined in grammar (if C++)"},
+ { "-dlg-class", 1,pDLGClass,"Name of DLG lexer class (default=DLGLexer) (if C++)"},
+ { "-header", 1,pHdr, "Name of ANTLR standard header info (default=no file)"},
+ { "-o", 1, pOdir, "Directory where output files should go (default=\".\")"},
+ { "-project", 1, pProj, "Name of executable to create (default=t)"},
+ { "-token-types", 1, pUT, "Token types are in this file (don't use tokens.h)"},
+ { "-trees", 0, pTrees, "Generate ASTs"},
+ { "-user-lexer", 0, pUL, "Do not create a DLG-based scanner"},
+ { "-mrhoist",0,pHoist, "Maintenance release style hoisting"},
+ { "-cfiles",1,pCFiles, "Additional files in C or C++ to compile"},
+ { "-pccts_path",1,ppccts_path,
+ "Path for $PCCTS directory (default is /usr/local/pccts)"},
+ { "-compiler",1,pCompiler,
+ "Default compiler (default is CC/cc)"},
+ { "*", 0,pFile, "" }, /* anything else is a file */
+ { NULL, 0, NULL, NULL }
+};
+
+extern char *DIR();
+
+int main(argc, argv)
+int argc;
+char **argv;
+{
+ if ( argc == 1 ) { help(); DIE; }
+ ProcessArgs(argc-1, &(argv[1]), options);
+
+ strcpy(ATOKENBUFFER_O, ATOKENBUFFER_C);
+ ATOKENBUFFER_O[strlen(ATOKENBUFFER_C)-strlen(CPP_FILE_SUFFIX)] = '\0';
+ strcat(ATOKENBUFFER_O, OBJ_FILE_SUFFIX);
+ strcpy(APARSER_O, APARSER_C);
+ APARSER_O[strlen(APARSER_O)-strlen(CPP_FILE_SUFFIX)] = '\0';
+ strcat(APARSER_O, OBJ_FILE_SUFFIX);
+
+ strcpy(ASTBASE_O, ASTBASE_C);
+ ASTBASE_O[strlen(ASTBASE_C)-strlen(CPP_FILE_SUFFIX)] = '\0';
+ strcat(ASTBASE_O, OBJ_FILE_SUFFIX);
+
+ strcpy(PCCTSAST_O, PCCTSAST_C);
+ PCCTSAST_O[strlen(PCCTSAST_C)-strlen(CPP_FILE_SUFFIX)] = '\0';
+ strcat(PCCTSAST_O, OBJ_FILE_SUFFIX);
+
+ strcpy(LIST_O, LIST_C);
+ LIST_O[strlen(LIST_C)-strlen(CPP_FILE_SUFFIX)] = '\0';
+ strcat(LIST_O, OBJ_FILE_SUFFIX);
+
+ strcpy(DLEXERBASE_O, DLEXERBASE_C);
+ DLEXERBASE_O[strlen(DLEXERBASE_C)-strlen(CPP_FILE_SUFFIX)] = '\0';
+ strcat(DLEXERBASE_O, OBJ_FILE_SUFFIX);
+
+ if ( num_files == 0 ) fatal("no grammar files specified; exiting...");
+ if ( !gen_CPP && num_classes>0 ) {
+ warn("can't define classes w/o C++ mode; turning on C++ mode...\n");
+ gen_CPP=1;
+ }
+ if ( gen_CPP && num_classes==0 ) {
+ fatal("must define classes >0 grammar classes in C++ mode\n");
+ }
+
+ mk(project, files, num_files, argc, argv);
+ DONE;
+}
+
+void help()
+{
+ Opt *p = options;
+ static char buf[1000+1];
+
+ fprintf(stderr, "genmk [options] f1.g ... fn.g\n");
+ while ( p->option!=NULL && *(p->option) != '*' )
+ {
+ buf[0]='\0';
+ if ( p->arg ) sprintf(buf, "%s ___", p->option);
+ else strcpy(buf, p->option);
+ fprintf(stderr, "\t%-16s %s\n", buf, p->descr);
+ p++;
+ }
+}
+
+void mk(project, files, n, argc, argv)
+char *project;
+char **files;
+int n;
+int argc;
+char **argv;
+{
+ int i;
+
+ printf("#\n");
+ printf("# PCCTS makefile for: ");
+ pfiles(files, n, NULL);
+ printf("\n");
+ printf("#\n");
+ printf("# Created from:");
+ for (i=0; i<argc; i++) printf(" %s", argv[i]);
+ printf("\n");
+ printf("#\n");
+ printf("# PCCTS release 1.33MR21\n");
+ printf("# Project: %s\n", project);
+ if ( gen_CPP ) printf("# C++ output\n");
+ else printf("# C output\n");
+ if ( user_lexer ) printf("# User-defined scanner\n");
+ else printf("# DLG scanner\n");
+ if ( user_token_types!=NULL ) printf("# User-defined token types in '%s'\n", user_token_types);
+ else printf("# ANTLR-defined token types\n");
+ printf("#\n");
+ printf(".SUFFIXES:\n.SUFFIXES: .o .cpp .c .h .g .i .dlg\n");
+ if ( user_token_types!=NULL ) {
+ printf("# Make sure #tokdefs directive in ANTLR grammar lists this file:\n");
+ printf("TOKENS = %s", user_token_types);
+ }
+ else printf("TOKENS = %stokens.h", DIR());
+ printf("\n");
+ printf("#\n");
+ printf("# The following filenames must be consistent with ANTLR/DLG flags\n");
+ printf("DLG_FILE = %s%s\n", DIR(), dlg);
+ printf("ERR = %serr\n", DIR());
+ if ( strcmp(hdr,"stdpccts.h")!=0 ) printf("HDR_FILE = %s%s\n", DIR(), hdr);
+ else printf("HDR_FILE =\n");
+ if ( !gen_CPP ) printf("MOD_FILE = %s%s\n", DIR(), mode);
+ if ( !gen_CPP ) printf("SCAN = %s\n", scan);
+ else printf("SCAN = %s%s\n", DIR(), dlg_class);
+
+ printf("PCCTS = %s\n",pccts_path);
+ printf("ANTLR_H = $(PCCTS)%sh\n", DirectorySymbol);
+ printf("BIN = $(PCCTS)%sbin\n", DirectorySymbol);
+ printf("ANTLR = $(BIN)%santlr\n", DirectorySymbol);
+ printf("DLG = $(BIN)%sdlg\n", DirectorySymbol);
+ printf("CFLAGS = -I. -I$(ANTLR_H)");
+ if ( strcmp(outdir, ".")!=0 ) printf(" -I%s", outdir);
+ printf(" $(COTHER)");
+ printf("\n");
+ printf("AFLAGS =");
+ if ( strcmp(outdir,".")!=0 ) printf(" -o %s", outdir);
+ if ( user_lexer ) printf(" -gx");
+ if ( gen_CPP ) printf(" -CC");
+ if ( strcmp(hdr,"stdpccts.h")!=0 ) printf(" -gh %s", hdr);
+ if ( gen_trees ) printf(" -gt");
+ if ( gen_hoist ) {
+ printf(" -mrhoist on") ;
+ } else {
+ printf(" -mrhoist off");
+ };
+ printf(" $(AOTHER)");
+ printf("\n");
+ printf("DFLAGS = -C2 -i");
+ if ( gen_CPP ) printf(" -CC");
+ if ( strcmp(dlg_class,"DLGLexer")!=0 ) printf(" -cl %s", dlg_class);
+ if ( strcmp(outdir,".")!=0 ) printf(" -o %s", outdir);
+ printf(" $(DOTHER)");
+ printf("\n");
+ printf("GRM = ");
+ pfiles(files, n, NULL);
+ printf("\n");
+ printf("MYFILES = %s\n",cfiles);
+ printf("SRC = ");
+ if ( gen_CPP ) pfiles(files, n, CPP_FILE_SUFFIX_NO_DOT);
+ else pfiles(files, n, "c");
+ if ( gen_CPP ) {
+ printf(" \\\n ");
+ printf(" ");
+ pclasses(classes, num_classes, CPP_FILE_SUFFIX_NO_DOT);
+ printf(" \\\n ");
+ printf("$(ANTLR_H)%s%s", DirectorySymbol, APARSER_C);
+ if ( !user_lexer ) printf(" $(ANTLR_H)%s%s", DirectorySymbol, DLEXERBASE_C);
+ if ( gen_trees ) {
+ printf(" \\\n ");
+ printf("$(ANTLR_H)%s%s", DirectorySymbol, ASTBASE_C);
+ printf(" $(ANTLR_H)%s%s", DirectorySymbol, PCCTSAST_C);
+/* printf(" $(ANTLR_H)%s%s", DirectorySymbol, LIST_C); */
+ printf(" \\\n ");
+ }
+ printf(" $(ANTLR_H)%s%s", DirectorySymbol, ATOKENBUFFER_C);
+ }
+ if ( !user_lexer ) {
+ if ( gen_CPP ) printf(" $(SCAN)%s", CPP_FILE_SUFFIX);
+ else printf(" %s$(SCAN).c", DIR());
+ }
+ if ( !gen_CPP ) printf(" $(ERR).c");
+ printf("\\\n $(MYFILES)\n");
+ printf("OBJ = ");
+ pfiles(files, n, "o");
+ if ( gen_CPP ) {
+ printf(" \\\n ");
+ printf(" ");
+ pclasses(classes, num_classes, "o");
+ printf(" \\\n ");
+ printf(" %s%s", DIR(), APARSER_O);
+ if ( !user_lexer ) {
+ printf(" %s%s", DIR(), DLEXERBASE_O);
+ }
+ if ( gen_trees ) {
+ printf(" \\\n ");
+ printf("%s%s", DIR(), ASTBASE_O);
+ printf(" %s%s", DIR(), PCCTSAST_O);
+/* printf(" %s%s", DIR(), LIST_O); */
+ printf(" \\\n ");
+ }
+ printf(" %s%s", DIR(), ATOKENBUFFER_O);
+ }
+ if ( !user_lexer ) {
+ if ( gen_CPP ) printf(" $(SCAN)%s", OBJ_FILE_SUFFIX);
+ else printf(" %s$(SCAN)%s", DIR(), OBJ_FILE_SUFFIX);
+ }
+ if ( !gen_CPP ) printf(" $(ERR)%s", OBJ_FILE_SUFFIX);
+ printf("\\\n $(MYFILES:.cpp=.o)\n");
+
+ printf("ANTLR_SPAWN = ");
+ if ( gen_CPP ) pfiles(files, n, CPP_FILE_SUFFIX_NO_DOT);
+ else pfiles(files, n, "c");
+ if ( gen_CPP ) {
+ printf(" ");
+ pclasses(classes, num_classes, CPP_FILE_SUFFIX_NO_DOT);
+ printf(" \\\n ");
+ pclasses(classes, num_classes, "h");
+ if ( strcmp(hdr,"stdpccts.h")!=0 ) {
+ printf(" \\\n ");
+ printf("$(HDR_FILE) stdpccts.h");
+ }
+ }
+ if ( user_lexer ) {
+ if ( !user_token_types ) printf(" $(TOKENS)");
+ }
+ else {
+ printf(" $(DLG_FILE)");
+ if ( !user_token_types ) printf(" $(TOKENS)");
+ }
+ if ( !gen_CPP ) printf(" $(ERR).c");
+ printf("\n");
+
+ if ( !user_lexer ) {
+ if ( gen_CPP ) printf("DLG_SPAWN = $(SCAN)%s", CPP_FILE_SUFFIX);
+ else printf("DLG_SPAWN = %s$(SCAN).c", DIR());
+ if ( gen_CPP ) printf(" $(SCAN).h");
+ if ( !gen_CPP ) printf(" $(MOD_FILE)");
+ printf("\n");
+ }
+
+ if ( gen_CPP ) {
+ printf("CCC = %s\n",compilerCCC);
+ }
+ else printf("CC = %s\n",compilerCC);
+
+ /* set up dependencies */
+ printf("\n%s : $(OBJ) $(SRC)\n", project);
+ printf(" %s %s %s $(CFLAGS) $(OBJ)\n",
+ gen_CPP?"$(CCC)":"$(CC)",
+ RENAME_EXE_FLAG,
+ project);
+ printf("\n");
+
+ /* implicit rules */
+
+ if(gen_CPP)
+ printf("%%.o : %%.cpp\n\t$(CCC) -c $(CFLAGS) $<\n\n");
+
+ printf("%%.o : %%.c\n\t%s -c $(CFLAGS) $<\n\n",
+ gen_CPP?"$(CCC)":"$(CC)");
+
+ /* how to compile parser files */
+
+ for (i=0; i<num_files; i++)
+ {
+ pfiles(&files[i], 1, "o");
+ if ( user_lexer ) {
+ printf(" : $(TOKENS)");
+ }
+ else {
+ if ( gen_CPP ) printf(" : $(TOKENS) $(SCAN).h");
+ else printf(" : $(MOD_FILE) $(TOKENS)");
+ }
+ printf(" ");
+ if ( gen_CPP ) pfiles(&files[i], 1, CPP_FILE_SUFFIX_NO_DOT);
+ else pfiles(&files[i], 1, "c");
+ if ( gen_CPP && strcmp(hdr,"stdpccts.h")!=0 ) printf(" $(HDR_FILE)");
+ printf("\n");
+ printf(" %s -c $(CFLAGS) %s ",
+ gen_CPP?"$(CCC)":"$(CC)",RENAME_OBJ_FLAG);
+ pfiles(&files[i], 1, "o");
+ printf(" ");
+ if ( gen_CPP ) pfiles(&files[i], 1, CPP_FILE_SUFFIX_NO_DOT);
+ else pfiles(&files[i], 1, "c");
+ printf("\n\n");
+ }
+
+ /* how to compile err.c */
+ if ( !gen_CPP ) {
+ printf("$(ERR)%s : $(ERR).c", OBJ_FILE_SUFFIX);
+ if ( !user_lexer ) printf(" $(TOKENS)");
+ printf("\n");
+ printf(" %s -c $(CFLAGS) %s $(ERR)%s $(ERR).c",
+ gen_CPP?"$(CCC)":"$(CC)",
+ RENAME_OBJ_FLAG,
+ OBJ_FILE_SUFFIX);
+ printf("\n\n");
+ }
+
+ /* how to compile Class.c */
+ for (i=0; i<num_classes; i++)
+ {
+ pclasses(&classes[i], 1, "o");
+ if ( user_lexer ) {
+ printf(" : $(TOKENS)");
+ }
+ else {
+ printf(" : $(TOKENS) $(SCAN).h");
+ }
+ printf(" ");
+ pclasses(&classes[i], 1, CPP_FILE_SUFFIX_NO_DOT);
+ printf(" ");
+ pclasses(&classes[i], 1, "h");
+ if ( gen_CPP && strcmp(hdr,"stdpccts.h")!=0 ) printf(" $(HDR_FILE)");
+ printf("\n");
+ printf(" %s -c $(CFLAGS) %s ",
+ gen_CPP?"$(CCC)":"$(CC)",
+ RENAME_OBJ_FLAG);
+ pclasses(&classes[i], 1, "o");
+ printf(" ");
+ pclasses(&classes[i], 1, CPP_FILE_SUFFIX_NO_DOT);
+ printf("\n\n");
+ }
+
+ /* how to compile scan.c */
+ if ( !user_lexer ) {
+ if ( gen_CPP ) printf("$(SCAN)%s : $(SCAN)%s", OBJ_FILE_SUFFIX, CPP_FILE_SUFFIX);
+ else printf("%s$(SCAN)%s : %s$(SCAN).c", DIR(), OBJ_FILE_SUFFIX, DIR());
+ if ( !user_lexer ) printf(" $(TOKENS)");
+ printf("\n");
+ if ( gen_CPP ) printf(" $(CCC) -c $(CFLAGS) %s $(SCAN)%s $(SCAN)%s",
+ RENAME_OBJ_FLAG,
+ OBJ_FILE_SUFFIX,
+ CPP_FILE_SUFFIX);
+ else printf(" $(CC) -c $(CFLAGS) %s %s$(SCAN)%s %s$(SCAN).c",
+ RENAME_OBJ_FLAG,
+ DIR(),
+ OBJ_FILE_SUFFIX,
+ DIR());
+ printf("\n\n");
+ }
+
+ printf("$(ANTLR_SPAWN) : $(GRM)\n");
+ printf(" $(ANTLR) $(AFLAGS) $(GRM)\n");
+
+ if ( !user_lexer )
+ {
+ printf("\n");
+ printf("$(DLG_SPAWN) : $(DLG_FILE)\n");
+ if ( gen_CPP ) printf(" $(DLG) $(DFLAGS) $(DLG_FILE)\n");
+ else printf(" $(DLG) $(DFLAGS) $(DLG_FILE) $(SCAN).c\n");
+ }
+
+ /* do the makes for ANTLR/DLG support */
+ if ( gen_CPP ) {
+ printf("\n");
+ printf("%s%s : $(ANTLR_H)%s%s\n", DIR(), APARSER_O, DirectorySymbol, APARSER_C);
+ printf(" %s -c $(CFLAGS) %s ",
+ gen_CPP?"$(CCC)":"$(CC)",
+ RENAME_OBJ_FLAG);
+ printf("%s%s $(ANTLR_H)%s%s\n", DIR(), APARSER_O, DirectorySymbol, APARSER_C);
+ printf("\n");
+ printf("%s%s : $(ANTLR_H)%s%s\n", DIR(), ATOKENBUFFER_O, DirectorySymbol, ATOKENBUFFER_C);
+ printf(" %s -c $(CFLAGS) %s ",
+ gen_CPP?"$(CCC)":"$(CC)",
+ RENAME_OBJ_FLAG);
+ printf("%s%s $(ANTLR_H)%s%s\n", DIR(), ATOKENBUFFER_O, DirectorySymbol, ATOKENBUFFER_C);
+ if ( !user_lexer ) {
+ printf("\n");
+ printf("%s%s : $(ANTLR_H)%s%s\n", DIR(), DLEXERBASE_O, DirectorySymbol, DLEXERBASE_C);
+ printf(" %s -c $(CFLAGS) %s ",
+ gen_CPP?"$(CCC)":"$(CC)",
+ RENAME_OBJ_FLAG);
+ printf("%s%s $(ANTLR_H)%s%s\n", DIR(), DLEXERBASE_O, DirectorySymbol, DLEXERBASE_C);
+ }
+ if ( gen_trees ) {
+ printf("\n");
+ printf("%s%s : $(ANTLR_H)%s%s\n", DIR(), ASTBASE_O, DirectorySymbol, ASTBASE_C);
+ printf(" %s -c $(CFLAGS) %s ",
+ gen_CPP?"$(CCC)":"$(CC)",
+ RENAME_OBJ_FLAG);
+ printf("%s%s $(ANTLR_H)%s%s\n", DIR(), ASTBASE_O, DirectorySymbol, ASTBASE_C);
+ printf("\n");
+ printf("%s%s : $(ANTLR_H)%s%s\n", DIR(), PCCTSAST_O, DirectorySymbol, PCCTSAST_C);
+ printf(" %s -c $(CFLAGS) %s ",
+ gen_CPP?"$(CCC)":"$(CC)",
+ RENAME_OBJ_FLAG);
+ printf("%s%s $(ANTLR_H)%s%s\n", DIR(), PCCTSAST_O, DirectorySymbol, PCCTSAST_C);
+ printf("\n");
+/*
+ printf("%s%s : $(ANTLR_H)%s%s\n", DIR(), LIST_O, DirectorySymbol, LIST_C);
+ printf(" %s -c $(CFLAGS) %s ",
+ gen_CPP?"$(CCC)":"$(CC)",RENAME_OBJ_FLAG);
+ printf("%s%s $(ANTLR_H)%s%s\n", DIR(), LIST_O, DirectorySymbol, LIST_C);
+*/
+ }
+ }
+
+ /* clean and scrub targets */
+
+ printf("\nclean:\n");
+ printf(" rm -f *%s core %s", OBJ_FILE_SUFFIX, project);
+ if ( strcmp(outdir, ".")!=0 ) printf(" %s*%s", DIR(), OBJ_FILE_SUFFIX);
+ printf("\n");
+
+ printf("\nscrub:\n");
+ printf(" rm -f *%s core %s", OBJ_FILE_SUFFIX, project);
+ if ( strcmp(outdir, ".")!=0 ) printf(" %s*%s", DIR(), OBJ_FILE_SUFFIX);
+ printf(" $(ANTLR_SPAWN)");
+ if ( !user_lexer ) printf(" $(DLG_SPAWN)");
+ printf("\n");
+}
+
+void pfiles(files, n, suffix)
+char **files;
+int n;
+char *suffix;
+{
+ int first=1;
+
+ while ( n>0 )
+ {
+ char *p = &(*files)[strlen(*files)-1];
+ if ( !first ) putchar(' ');
+ first=0;
+ while ( p > *files && *p != '.' ) --p;
+ if ( p == *files )
+ {
+ fprintf(stderr,
+ "genmk: filenames must be file.suffix format: %s\n",
+ *files);
+ exit(-1);
+ }
+ if ( suffix == NULL ) printf("%s", *files);
+ else
+ {
+ *p = '\0';
+ printf("%s", DIR());
+ if ( strcmp(suffix, "o")==0 ) printf("%s%s", *files, OBJ_FILE_SUFFIX);
+ else printf("%s.%s", *files, suffix);
+ *p = '.';
+ }
+ files++;
+ --n;
+ }
+}
+
+void pclasses(classes, n, suffix)
+char **classes;
+int n;
+char *suffix;
+{
+ int first=1;
+
+ while ( n>0 )
+ {
+ if ( !first ) putchar(' ');
+ first=0;
+ if ( suffix == NULL ) printf("%s", *classes);
+ else {
+ printf("%s", DIR());
+ if ( strcmp(suffix, "o")==0 ) printf("%s%s", *classes, OBJ_FILE_SUFFIX);
+ else printf("%s.%s", *classes, suffix);
+ }
+ classes++;
+ --n;
+ }
+}
+
+static void
+#ifdef __STDC__
+ProcessArgs( int argc, char **argv, Opt *options )
+#else
+ProcessArgs( argc, argv, options )
+int argc;
+char **argv;
+Opt *options;
+#endif
+{
+ Opt *p;
+ require(argv!=NULL, "ProcessArgs: command line NULL");
+
+ while ( argc-- > 0 )
+ {
+ p = options;
+ while ( p->option != NULL )
+ {
+ if ( strcmp(p->option, "*") == 0 ||
+ strcmp(p->option, *argv) == 0 )
+ {
+ if ( p->arg )
+ {
+ (*p->process)( *argv, *(argv+1) );
+ argv++;
+ argc--;
+ }
+ else
+ (*p->process)( *argv );
+ break;
+ }
+ p++;
+ }
+ argv++;
+ }
+}
+
+void fatal( err_)
+char *err_;
+{
+ fprintf(stderr, "genmk: %s\n", err_);
+ exit(1);
+}
+
+void warn( err_)
+char *err_;
+{
+ fprintf(stderr, "genmk: %s\n", err_);
+}
+
+char *DIR()
+{
+ static char buf[200+1];
+
+ if ( strcmp(outdir,TopDirectory)==0 ) return "";
+ sprintf(buf, "%s%s", outdir, DirectorySymbol);
+ return buf;
+}
diff --git a/Source/Pccts/support/genmk/makefile b/Source/Pccts/support/genmk/makefile
new file mode 100644
index 0000000..a003c2f
--- /dev/null
+++ b/Source/Pccts/support/genmk/makefile
@@ -0,0 +1,29 @@
+##
+## 7-Apr-97
+## added support/genmk/makefile to pccts 1.33MR1 distribution kit
+## (support/genmk/makefile" omitted from 1.33 distribution kit)
+##
+SRC=genmk.c
+OBJ=genmk.o
+# Define PC if you use a PC OS (changes directory symbol and object file extension)
+# see pccts/h/pcctscfg.h
+CC=cc
+COPT=-O
+#CFLAGS=-I../../h -DPC
+CFLAGS=$(COPT) -I../../h
+BAG=../../bin/bag
+
+genmk: $(OBJ) $(SRC) ../../h/pcctscfg.h
+ $(CC) -o genmk $(OBJ)
+
+clean:
+ rm -rf core *.o
+
+scrub:
+ rm -rf genmk core *.o
+
+shar:
+ shar genmk.c makefile > genmk.shar
+
+archive:
+ $(BAG) genmk.c makefile > genmk.bag
diff --git a/Source/Pccts/support/rexpr/makefile b/Source/Pccts/support/rexpr/makefile
new file mode 100644
index 0000000..44caef1
--- /dev/null
+++ b/Source/Pccts/support/rexpr/makefile
@@ -0,0 +1,19 @@
+BAG=../../bin/bag
+SRC=test.c rexpr.c
+OBJ=test.o rexpr.o
+CFLAGS = -g
+
+test: $(OBJ) $(SRC)
+ cc -g -o texpr $(OBJ)
+
+shar:
+ shar makefile test.c rexpr.c rexpr.h > rexpr.shar
+
+archive:
+ $(BAG) makefile test.c rexpr.c rexpr.h > rexpr.bag
+
+clean:
+ rm -rf *.o core texpr
+
+scrub:
+ rm -rf *.o core texpr
diff --git a/Source/Pccts/support/rexpr/rexpr.c b/Source/Pccts/support/rexpr/rexpr.c
new file mode 100644
index 0000000..805bf65
--- /dev/null
+++ b/Source/Pccts/support/rexpr/rexpr.c
@@ -0,0 +1,586 @@
+/*
+ * This file contains code for
+ *
+ * int rexpr(char *expr, char *s);
+ *
+ * which answers
+ *
+ * 1 if 's' is in the language described by the regular expression 'expr'
+ * 0 if it is not
+ * -1 if the regular expression is invalid
+ *
+ * Language membership is determined by constructing a non-deterministic
+ * finite automata (NFA) from the regular expression. A depth-
+ * first-search is performed on the NFA (graph) to check for a match of 's'.
+ * Each non-epsilon arc consumes one character from 's'. Backtracking is
+ * performed to check all possible paths through the NFA.
+ *
+ * Regular expressions follow the meta-language:
+ *
+ * <regExpr> ::= <andExpr> ( '|' <andExpr> )*
+ *
+ * <andExpr> ::= <expr> ( <expr> )*
+ *
+ * <expr> ::= {'~'} '[' <atomList> ']' <repeatSymbol>
+ * | '(' <regExpr> ')' <repeatSymbol>
+ * | '{' <regExpr> '}' <repeatSymbol>
+ * | <atom> <repeatSymbol>
+ *
+ * <repeatSymbol> ::= { '*' | '+' }
+ *
+ * <atomList> ::= <atom> ( <atom> )*
+ * | { <atomList> } <atom> '-' <atom> { <atomList> }
+ *
+ * <atom> ::= Token[Atom]
+ *
+ * Notes:
+ * ~ means complement the set in [..]. i.e. all characters not listed
+ * * means match 0 or more times (can be on expression or atom)
+ * + means match 1 or more times (can be on expression or atom)
+ * {} optional
+ * () grouping
+ * [] set of atoms
+ * x-y all characters from x to y (found only in [..])
+ * \xx the character with value xx
+ *
+ * Examples:
+ * [a-z]+
+ * match 1 or more lower-case letters (e.g. variable)
+ *
+ * 0x[0-9A-Fa-f]+
+ * match a hex number with 0x on front (e.g. 0xA1FF)
+ *
+ * [0-9]+.[0-9]+{e[0-9]+}
+ * match a floating point number (e.g. 3.14e21)
+ *
+ * Code example:
+ * if ( rexpr("[a-zA-Z][a-zA-Z0-9]+", str) ) then str is keyword
+ *
+ * Terence Parr
+ * Purdue University
+ * April 1991
+ */
+
+#include <stdio.h>
+#include <ctype.h>
+#ifdef __STDC__
+#include <stdlib.h>
+#else
+#include <malloc.h>
+#endif
+#include "rexpr.h"
+
+#ifdef __USE_PROTOS
+static int regExpr( GraphPtr g );
+static int andExpr( GraphPtr g );
+static int expr( GraphPtr g );
+static int repeatSymbol( GraphPtr g );
+static int atomList( char *p, int complement );
+static void next( void );
+static ArcPtr newGraphArc( void );
+static NodePtr newNode( void );
+static int ArcBetweenGraphNode( NodePtr i, NodePtr j, int label );
+static Graph BuildNFA_atom( int label );
+static Graph BuildNFA_AB( Graph A, Graph B );
+static Graph BuildNFA_AorB( Graph A, Graph B );
+static Graph BuildNFA_set( char *s );
+static Graph BuildNFA_Astar( Graph A );
+static Graph BuildNFA_Aplus( Graph A );
+static Graph BuildNFA_Aoptional( Graph A );
+#else
+static int regExpr();
+static int andExpr();
+static int expr();
+static int repeatSymbol();
+static int atomList();
+static void next();
+static ArcPtr newGraphArc();
+static NodePtr newNode();
+static int ArcBetweenGraphNode();
+static Graph BuildNFA_atom();
+static Graph BuildNFA_AB();
+static Graph BuildNFA_AorB();
+static Graph BuildNFA_set();
+static Graph BuildNFA_Astar();
+static Graph BuildNFA_Aplus();
+static Graph BuildNFA_Aoptional();
+#endif
+
+static char *_c;
+static int token, tokchar;
+static NodePtr accept;
+static NodePtr freelist = NULL;
+
+/*
+ * return 1 if s in language described by expr
+ * 0 if s is not
+ * -1 if expr is an invalid regular expression
+ */
+#ifdef __USE_PROTOS
+static int rexpr(char *expr,char *s)
+#else
+static int rexpr(expr, s)
+char *expr, *s;
+#endif
+{
+ NodePtr p,q;
+ Graph nfa;
+ int result;
+
+ fprintf(stderr, "rexpr(%s,%s);\n", expr,s);
+ freelist = NULL;
+ _c = expr;
+ next();
+ if ( regExpr(&nfa) == -1 ) return -1;
+ accept = nfa.right;
+ result = match(nfa.left, s);
+ /* free all your memory */
+ p = q = freelist;
+ while ( p!=NULL ) { q = p->track; free(p); p = q; }
+ return result;
+}
+
+/*
+ * do a depth-first-search on the NFA looking for a path from start to
+ * accept state labelled with the characters of 's'.
+ */
+
+#ifdef __USE_PROTOS
+static int match(NodePtr automaton,char *s)
+#else
+static int match(automaton, s)
+NodePtr automaton;
+char *s;
+#endif
+{
+ ArcPtr p;
+
+ if ( automaton == accept && *s == '\0' ) return 1; /* match */
+
+ for (p=automaton->arcs; p!=NULL; p=p->next) /* try all arcs */
+ {
+ if ( p->label == Epsilon )
+ {
+ if ( match(p->target, s) ) return 1;
+ }
+ else if ( p->label == *s )
+ if ( match(p->target, s+1) ) return 1;
+ }
+ return 0;
+}
+
+/*
+ * <regExpr> ::= <andExpr> ( '|' {<andExpr>} )*
+ *
+ * Return -1 if syntax error
+ * Return 0 if none found
+ * Return 1 if a regExrp was found
+ */
+
+#ifdef __USE_PROTOS
+static int regExpr(GraphPtr g)
+#else
+static int regExpr(g)
+GraphPtr g;
+#endif
+{
+ Graph g1, g2;
+
+ if ( andExpr(&g1) == -1 )
+ {
+ return -1;
+ }
+
+ while ( token == '|' )
+ {
+ int a;
+ next();
+ a = andExpr(&g2);
+ if ( a == -1 ) return -1; /* syntax error below */
+ else if ( !a ) return 1; /* empty alternative */
+ g1 = BuildNFA_AorB(g1, g2);
+ }
+
+ if ( token!='\0' ) return -1;
+
+ *g = g1;
+ return 1;
+}
+
+/*
+ * <andExpr> ::= <expr> ( <expr> )*
+ */
+
+#ifdef __USE_PROTOS
+static int andExpr(GraphPtr g)
+#else
+static int andExpr(g)
+GraphPtr g;
+#endif
+{
+ Graph g1, g2;
+
+ if ( expr(&g1) == -1 )
+ {
+ return -1;
+ }
+
+ while ( token==Atom || token=='{' || token=='(' || token=='~' || token=='[' )
+ {
+ if (expr(&g2) == -1) return -1;
+ g1 = BuildNFA_AB(g1, g2);
+ }
+
+ *g = g1;
+ return 1;
+}
+
+/*
+ * <expr> ::= {'~'} '[' <atomList> ']' <repeatSymbol>
+ * | '(' <regExpr> ')' <repeatSymbol>
+ * | '{' <regExpr> '}' <repeatSymbol>
+ * | <atom> <repeatSymbol>
+ */
+
+#ifdef __USE_PROTOS
+static int expr(GraphPtr g)
+#else
+static int expr(g)
+GraphPtr g;
+#endif
+{
+ int complement = 0;
+ char s[257]; /* alloc space for string of char in [] */
+
+ if ( token == '~' || token == '[' )
+ {
+ if ( token == '~' ) {complement = 1; next();}
+ if ( token != '[' ) return -1;
+ next();
+ if ( atomList( s, complement ) == -1 ) return -1;
+ *g = BuildNFA_set( s );
+ if ( token != ']' ) return -1;
+ next();
+ repeatSymbol( g );
+ return 1;
+ }
+ if ( token == '(' )
+ {
+ next();
+ if ( regExpr( g ) == -1 ) return -1;
+ if ( token != ')' ) return -1;
+ next();
+ repeatSymbol( g );
+ return 1;
+ }
+ if ( token == '{' )
+ {
+ next();
+ if ( regExpr( g ) == -1 ) return -1;
+ if ( token != '}' ) return -1;
+ next();
+ /* S p e c i a l C a s e O p t i o n a l { } */
+ if ( token != '*' && token != '+' )
+ {
+ *g = BuildNFA_Aoptional( *g );
+ }
+ repeatSymbol( g );
+ return 1;
+ }
+ if ( token == Atom )
+ {
+ *g = BuildNFA_atom( tokchar );
+ next();
+ repeatSymbol( g );
+ return 1;
+ }
+
+ return -1;
+}
+
+/*
+ * <repeatSymbol> ::= { '*' | '+' }
+ */
+#ifdef __USE_PROTOS
+static int repeatSymbol(GraphPtr g)
+#else
+static int repeatSymbol(g)
+GraphPtr g;
+#endif
+{
+ switch ( token )
+ {
+ case '*' : *g = BuildNFA_Astar( *g ); next(); break;
+ case '+' : *g = BuildNFA_Aplus( *g ); next(); break;
+ }
+ return 1;
+}
+
+/*
+ * <atomList> ::= <atom> { <atom> }*
+ * { <atomList> } <atom> '-' <atom> { <atomList> }
+ *
+ * a-b is same as ab
+ * q-a is same as q
+ */
+
+#ifdef __USE_PROTOS
+static int atomList(char *p, int complement)
+#else
+static int atomList(p, complement)
+char *p;
+int complement;
+#endif
+{
+ static unsigned char set[256]; /* no duplicates */
+ int first, last, i;
+ char *s = p;
+
+ if ( token != Atom ) return -1;
+
+ for (i=0; i<256; i++) set[i] = 0;
+ while ( token == Atom )
+ {
+ if ( !set[tokchar] ) *s++ = tokchar;
+ set[tokchar] = 1; /* Add atom to set */
+ next();
+ if ( token == '-' ) /* have we found '-' */
+ {
+ first = *(s-1); /* Get last char */
+ next();
+ if ( token != Atom ) return -1;
+ else
+ {
+ last = tokchar;
+ }
+ for (i = first+1; i <= last; i++)
+ {
+ if ( !set[tokchar] ) *s++ = i;
+ set[i] = 1; /* Add atom to set */
+ }
+ next();
+ }
+ }
+ *s = '\0';
+ if ( complement )
+ {
+ for (i=0; i<256; i++) set[i] = !set[i];
+ for (i=1,s=p; i<256; i++) if ( set[i] ) *s++ = i;
+ *s = '\0';
+ }
+ return 1;
+}
+
+/* a somewhat stupid lexical analyzer */
+
+#ifdef __USE_PROTOS
+static void next(void)
+#else
+static void next()
+#endif
+{
+ while ( *_c==' ' || *_c=='\t' || *_c=='\n' ) _c++;
+ if ( *_c=='\\' )
+ {
+ _c++;
+ if ( isdigit(*_c) )
+ {
+ int n=0;
+ while ( isdigit(*_c) )
+ {
+ n = n*10 + (*_c++ - '0');
+ }
+ if ( n>255 ) n=255;
+ tokchar = n;
+ }
+ else
+ {
+ switch (*_c)
+ {
+ case 'n' : tokchar = '\n'; break;
+ case 't' : tokchar = '\t'; break;
+ case 'r' : tokchar = '\r'; break;
+ default : tokchar = *_c;
+ }
+ _c++;
+ }
+ token = Atom;
+ }
+ else if ( isgraph(*_c) && *_c!='[' && *_c!='(' && *_c!='{' &&
+ *_c!='-' && *_c!='}' && *_c!=')' && *_c!=']' &&
+ *_c!='+' && *_c!='*' && *_c!='~' && *_c!='|' )
+ {
+ token = Atom;
+ tokchar = *_c++;
+ }
+ else
+ {
+ token = tokchar = *_c++;
+ }
+}
+
+/* N F A B u i l d i n g R o u t i n e s */
+
+#ifdef __USE_PROTOS
+static ArcPtr newGraphArc(void)
+#else
+static ArcPtr newGraphArc()
+#endif
+{
+ ArcPtr p;
+ p = (ArcPtr) calloc(1, sizeof(Arc));
+ if ( p==NULL ) {fprintf(stderr,"rexpr: out of memory\n"); exit(-1);}
+ if ( freelist != NULL ) p->track = (ArcPtr) freelist;
+ freelist = (NodePtr) p;
+ return p;
+}
+
+#ifdef __USE_PROTOS
+static NodePtr newNode(void)
+#else
+static NodePtr newNode()
+#endif
+{
+ NodePtr p;
+ p = (NodePtr) calloc(1, sizeof(Node));
+ if ( p==NULL ) {fprintf(stderr,"rexpr: out of memory\n"); exit(-1);}
+ if ( freelist != NULL ) p->track = freelist;
+ freelist = p;
+ return p;
+}
+
+#ifdef __USE_PROTOS
+static void ArcBetweenGraphNodes(NodePtr i,NodePtr j,int label)
+#else
+static void ArcBetweenGraphNodes(i, j, label)
+NodePtr i, j;
+int label;
+#endif
+{
+ ArcPtr a;
+
+ a = newGraphArc();
+ if ( i->arcs == NULL ) i->arctail = i->arcs = a;
+ else {(i->arctail)->next = a; i->arctail = a;}
+ a->label = label;
+ a->target = j;
+}
+
+#ifdef __USE_PROTOS
+static Graph BuildNFA_atom(int label)
+#else
+static Graph BuildNFA_atom(label)
+int label;
+#endif
+{
+ Graph g;
+
+ g.left = newNode();
+ g.right = newNode();
+ ArcBetweenGraphNodes(g.left, g.right, label);
+ return( g );
+}
+
+#ifdef __USE_PROTOS
+static Graph BuildNFA_AB(Graph A,Graph B)
+#else
+static Graph BuildNFA_AB(A, B)
+Graph A, B;
+#endif
+{
+ Graph g;
+
+ ArcBetweenGraphNodes(A.right, B.left, Epsilon);
+ g.left = A.left;
+ g.right = B.right;
+ return( g );
+}
+
+#ifdef __USE_PROTOS
+static Graph BuildNFA_AorB(Graph A,Graph B)
+#else
+static Graph BuildNFA_AorB(A, B)
+Graph A, B;
+#endif
+{
+ Graph g;
+
+ g.left = newNode();
+ ArcBetweenGraphNodes(g.left, A.left, Epsilon);
+ ArcBetweenGraphNodes(g.left, B.left, Epsilon);
+ g.right = newNode();
+ ArcBetweenGraphNodes(A.right, g.right, Epsilon);
+ ArcBetweenGraphNodes(B.right, g.right, Epsilon);
+ return( g );
+}
+
+#ifdef __USE_PROTOS
+static Graph BuildNFA_set(char *s)
+#else
+static Graph BuildNFA_set( s )
+char *s;
+#endif
+{
+ Graph g;
+
+ if ( s == NULL ) return g;
+
+ g.left = newNode();
+ g.right = newNode();
+ while ( *s != '\0' )
+ {
+ ArcBetweenGraphNodes(g.left, g.right, *s++);
+ }
+ return g;
+}
+
+#ifdef __USE_PROTOS
+static Graph BuildNFA_Astar(Graph A)
+#else
+static Graph BuildNFA_Astar( A )
+Graph A;
+#endif
+{
+ Graph g;
+
+ g.left = newNode();
+ g.right = newNode();
+
+ ArcBetweenGraphNodes(g.left, A.left, Epsilon);
+ ArcBetweenGraphNodes(g.left, g.right, Epsilon);
+ ArcBetweenGraphNodes(A.right, g.right, Epsilon);
+ ArcBetweenGraphNodes(A.right, A.left, Epsilon);
+
+ return( g );
+}
+
+#ifdef __USE_PROTOS
+static Graph BuildNFA_Aplus(Graph A)
+#else
+static Graph BuildNFA_Aplus( A )
+Graph A;
+#endif
+{
+ ArcBetweenGraphNodes(A.right, A.left, Epsilon);
+
+ return( A );
+}
+
+#ifdef __USE_PROTOS
+static Graph BuildNFA_Aoptional(Graph A)
+#else
+static Graph BuildNFA_Aoptional( A )
+Graph A;
+#endif
+{
+ Graph g;
+
+ g.left = newNode();
+ g.right = newNode();
+
+ ArcBetweenGraphNodes(g.left, A.left, Epsilon);
+ ArcBetweenGraphNodes(g.left, g.right, Epsilon);
+ ArcBetweenGraphNodes(A.right, g.right, Epsilon);
+
+ return( g );
+}
diff --git a/Source/Pccts/support/rexpr/rexpr.h b/Source/Pccts/support/rexpr/rexpr.h
new file mode 100644
index 0000000..e67a965
--- /dev/null
+++ b/Source/Pccts/support/rexpr/rexpr.h
@@ -0,0 +1,30 @@
+#define Atom 256 /* token Atom (an impossible char value) */
+#define Epsilon 257 /* epsilon arc (an impossible char value) */
+
+/* track field must be same for all node types */
+typedef struct _a {
+ struct _a *track; /* track mem allocation */
+ int label;
+ struct _a *next;
+ struct _n *target;
+ } Arc, *ArcPtr;
+
+typedef struct _n {
+ struct _n *track;
+ ArcPtr arcs, arctail;
+ } Node, *NodePtr;
+
+typedef struct {
+ NodePtr left,
+ right;
+ } Graph, *GraphPtr;
+
+#ifdef __USE_PROTOS
+int rexpr( char *expr, char *s );
+int match( NodePtr automaton, char *s );
+#else
+int rexpr();
+int match();
+#endif
+
+
diff --git a/Source/Pccts/support/rexpr/test.c b/Source/Pccts/support/rexpr/test.c
new file mode 100644
index 0000000..2619539
--- /dev/null
+++ b/Source/Pccts/support/rexpr/test.c
@@ -0,0 +1,19 @@
+#include <stdio.h>
+#include "rexpr.h"
+
+/*
+ * test for rexpr().
+ * To make this test:
+ * cc -o rexpr test.c rexpr.c
+ * Then from command line type:
+ * rexpr r string
+ * where r is the regular expression that decribes a language
+ * and string is the string to verify.
+ */
+main(argc,argv)
+int argc;
+char *argv[];
+{
+ if ( argc!=3 ) fprintf(stderr,"rexpr: expr s\n");
+ else printf("%d\n", rexpr(argv[1], argv[2]));
+}
diff --git a/Source/Pccts/support/set/set.c b/Source/Pccts/support/set/set.c
new file mode 100644
index 0000000..eb6fba7
--- /dev/null
+++ b/Source/Pccts/support/set/set.c
@@ -0,0 +1,816 @@
+/* set.c
+
+ The following is a general-purpose set library originally developed
+ by Hank Dietz and enhanced by Terence Parr to allow dynamic sets.
+
+ Sets are now structs containing the #words in the set and
+ a pointer to the actual set words.
+
+ Generally, sets need not be explicitly allocated. They are
+ created/extended/shrunk when appropriate (e.g. in set_of()).
+ HOWEVER, sets need to be destroyed (free()ed) when they go out of scope
+ or are otherwise no longer needed. A routine is provided to
+ free a set.
+
+ Sets can be explicitly created with set_new(s, max_elem).
+
+ Sets can be declared to have minimum size to reduce realloc traffic.
+ Default minimum size = 1.
+
+ Sets can be explicitly initialized to have no elements (set.n == 0)
+ by using the 'empty' initializer:
+
+ Examples:
+ set a = empty; -- set_deg(a) == 0
+
+ return( empty );
+
+ Example set creation and destruction:
+
+ set
+ set_of2(e,g)
+ unsigned e,g;
+ {
+ set a,b,c;
+
+ b = set_of(e); -- Creates space for b and sticks in e
+ set_new(c, g); -- set_new(); set_orel() ==> set_of()
+ set_orel(g, &c);
+ a = set_or(b, c);
+ .
+ .
+ .
+ set_free(b);
+ set_free(c);
+ return( a );
+ }
+
+ 1987 by Hank Dietz
+
+ Modified by:
+ Terence Parr
+ Purdue University
+ October 1989
+
+ Made it smell less bad to C++ 7/31/93 -- TJP
+*/
+
+#include <stdio.h>
+#include "pcctscfg.h"
+#ifdef __STDC__
+#include <stdlib.h>
+#else
+#include <malloc.h>
+#endif
+#include <string.h>
+
+#include "set.h"
+
+#define MIN(i,j) ( (i) > (j) ? (j) : (i))
+#define MAX(i,j) ( (i) < (j) ? (j) : (i))
+
+/* elems can be a maximum of 32 bits */
+static unsigned bitmask[] = {
+ 0x00000001, 0x00000002, 0x00000004, 0x00000008,
+ 0x00000010, 0x00000020, 0x00000040, 0x00000080,
+ 0x00000100, 0x00000200, 0x00000400, 0x00000800,
+ 0x00001000, 0x00002000, 0x00004000, 0x00008000,
+#if !defined(PC) || defined(PC32)
+ 0x00010000, 0x00020000, 0x00040000, 0x00080000,
+ 0x00100000, 0x00200000, 0x00400000, 0x00800000,
+ 0x01000000, 0x02000000, 0x04000000, 0x08000000,
+ 0x10000000, 0x20000000, 0x40000000, 0x80000000
+#endif
+};
+
+set empty = set_init;
+static unsigned min=1;
+
+#define StrSize 200
+
+#ifdef MEMCHK
+#define CHK(a) \
+ if ( a.setword != NULL ) \
+ if ( !valid(a.setword) ) \
+ {fprintf(stderr, "%s(%d): invalid set\n",__FILE__,__LINE__); exit(-1);}
+#else
+#define CHK(a)
+#endif
+
+/*
+ * Set the minimum size (in words) of a set to reduce realloc calls
+ */
+void
+#ifdef __USE_PROTOS
+set_size( unsigned n )
+#else
+set_size( n )
+unsigned n;
+#endif
+{
+ min = n;
+}
+
+unsigned int
+#ifdef __USE_PROTOS
+set_deg( set a )
+#else
+set_deg( a )
+set a;
+#endif
+{
+ /* Fast compute degree of a set... the number
+ of elements present in the set. Assumes
+ that all word bits are used in the set
+ and that SETSIZE(a) is a multiple of WORDSIZE.
+ */
+ register unsigned *p = &(a.setword[0]);
+ register unsigned *endp = NULL; /* MR27 Avoid false memory check report */
+ register unsigned degree = 0;
+
+ CHK(a);
+ if ( a.n == 0 ) return(0);
+ endp = &(a.setword[a.n]);
+ while ( p < endp )
+ {
+ register unsigned t = *p;
+ register unsigned *b = &(bitmask[0]);
+ do {
+ if (t & *b) ++degree;
+ } while (++b < &(bitmask[WORDSIZE]));
+ p++;
+ }
+
+ return(degree);
+}
+
+set
+#ifdef __USE_PROTOS
+set_or( set b, set c )
+#else
+set_or( b, c )
+set b;
+set c;
+#endif
+{
+ /* Fast set union operation */
+ /* resultant set size is max(b, c); */
+ set *big;
+ set t;
+ unsigned int m,n;
+ register unsigned *r, *p, *q, *endp;
+
+ CHK(b); CHK(c);
+ t = empty;
+ if (b.n > c.n) {big= &b; m=b.n; n=c.n;} else {big= &c; m=c.n; n=b.n;}
+ set_ext(&t, m);
+ r = t.setword;
+
+ /* Or b,c until max of smaller set */
+ q = c.setword;
+ p = b.setword;
+ endp = &(b.setword[n]);
+ while ( p < endp ) *r++ = *p++ | *q++;
+
+ /* Copy rest of bigger set into result */
+ p = &(big->setword[n]);
+ endp = &(big->setword[m]);
+ while ( p < endp ) *r++ = *p++;
+
+ return(t);
+}
+
+set
+#ifdef __USE_PROTOS
+set_and( set b, set c )
+#else
+set_and( b, c )
+set b;
+set c;
+#endif
+{
+ /* Fast set intersection operation */
+ /* resultant set size is min(b, c); */
+ set t;
+ unsigned int n;
+ register unsigned *r, *p, *q, *endp;
+
+ CHK(b); CHK(c);
+ t = empty;
+ n = (b.n > c.n) ? c.n : b.n;
+ if ( n == 0 ) return t; /* TJP 4-27-92 fixed for empty set */
+ set_ext(&t, n);
+ r = t.setword;
+
+ /* & b,c until max of smaller set */
+ q = c.setword;
+ p = b.setword;
+ endp = &(b.setword[n]);
+ while ( p < endp ) *r++ = *p++ & *q++;
+
+ return(t);
+}
+
+set
+#ifdef __USE_PROTOS
+set_dif( set b, set c )
+#else
+set_dif( b, c )
+set b;
+set c;
+#endif
+{
+ /* Fast set difference operation b - c */
+ /* resultant set size is size(b) */
+ set t;
+ unsigned int n;
+ register unsigned *r, *p, *q, *endp;
+
+ CHK(b); CHK(c);
+ t = empty;
+ n = (b.n <= c.n) ? b.n : c.n ;
+ if ( b.n == 0 ) return t; /* TJP 4-27-92 fixed for empty set */
+ /* WEC 12-1-92 fixed for c.n = 0 */
+ set_ext(&t, b.n);
+ r = t.setword;
+
+ /* Dif b,c until smaller set size */
+ q = c.setword;
+ p = b.setword;
+ endp = &(b.setword[n]);
+ while ( p < endp ) *r++ = *p++ & (~ *q++);
+
+ /* Copy rest of b into result if size(b) > c */
+ if ( b.n > n )
+ {
+ p = &(b.setword[n]);
+ endp = &(b.setword[b.n]);
+ while ( p < endp ) *r++ = *p++;
+ }
+
+ return(t);
+}
+
+set
+#ifdef __USE_PROTOS
+set_of( unsigned b )
+#else
+set_of( b )
+unsigned b;
+#endif
+{
+ /* Fast singleton set constructor operation */
+ static set a;
+
+ if ( b == nil ) return( empty );
+ set_new(a, b);
+ a.setword[DIVWORD(b)] = bitmask[MODWORD(b)];
+
+ return(a);
+}
+
+/*
+ * Extend (or shrink) the set passed in to have n words.
+ *
+ * if n is smaller than the minimum, boost n to have the minimum.
+ * if the new set size is the same as the old one, do nothing.
+ *
+ * TJP 4-27-92 Fixed so won't try to alloc 0 bytes
+ */
+void
+#ifdef __USE_PROTOS
+set_ext( set *a, unsigned int n )
+#else
+set_ext( a, n )
+set *a;
+unsigned int n;
+#endif
+{
+ register unsigned *p;
+ register unsigned *endp;
+ unsigned int size;
+
+ CHK((*a));
+ if ( a->n == 0 )
+ {
+ if ( n == 0 ) return;
+ if (a->setword != NULL) {
+ free (a->setword); /* MR20 */
+ }
+ a->setword = (unsigned *) calloc(n, BytesPerWord);
+ if ( a->setword == NULL )
+ {
+ fprintf(stderr, "set_ext(%d words): cannot allocate set\n", n);
+ exit(-1);
+ }
+ a->n = n;
+ return;
+ }
+ if ( n < min ) n = min;
+ if ( a->n == n || n == 0 ) return;
+ size = a->n;
+ a->n = n;
+ a->setword = (unsigned *) realloc( (char *)a->setword, (n*BytesPerWord) );
+ if ( a->setword == NULL )
+ {
+ fprintf(stderr, "set_ext(%d words): cannot allocate set\n", n);
+ exit(-1);
+ }
+
+ p = &(a->setword[size]); /* clear from old size to new size */
+ endp = &(a->setword[a->n]);
+ do {
+ *p++ = 0;
+ } while ( p < endp );
+}
+
+set
+#ifdef __USE_PROTOS
+set_not( set a )
+#else
+set_not( a )
+set a;
+#endif
+{
+ /* Fast not of set a (assumes all bits used) */
+ /* size of resultant set is size(a) */
+ /* ~empty = empty cause we don't know how bit to make set */
+ set t;
+ register unsigned *r;
+ register unsigned *p = a.setword;
+ register unsigned *endp = &(a.setword[a.n]);
+
+ CHK(a);
+ t = empty;
+ if ( a.n == 0 ) return( empty );
+ set_ext(&t, a.n);
+ r = t.setword;
+
+ do {
+ *r++ = (~ *p++);
+ } while ( p < endp );
+
+ return(t);
+}
+
+int
+#ifdef __USE_PROTOS
+set_equ( set a, set b )
+#else
+set_equ( a, b )
+set a;
+set b;
+#endif
+{
+/* 8-Nov-97 Make it work with sets of different sizes */
+/* Easy to understand, too. Probably faster. */
+/* Check for a equal to b */
+
+ unsigned int count; /* MR11 */
+ unsigned int i; /* MR11 */
+
+ CHK(a); CHK(b);
+
+ count=MIN(a.n,b.n);
+ if (count == 0) return 1;
+ for (i=0; i < count; i++) {
+ if (a.setword[i] != b.setword[i]) return 0;
+ };
+ if (a.n < b.n) {
+ for (i=count; i < b.n; i++) {
+ if (b.setword[i] != 0) return 0;
+ }
+ return 1;
+ } else if (a.n > b.n) {
+ for (i=count; i < a.n; i++) {
+ if (a.setword[i] != 0) return 0;
+ }
+ return 1;
+ } else {
+ return 1;
+ };
+}
+
+int
+#ifdef __USE_PROTOS
+set_sub( set a, set b )
+#else
+set_sub( a, b )
+set a;
+set b;
+#endif
+{
+
+/* 8-Nov-97 Make it work with sets of different sizes */
+/* Easy to understand, too. Probably faster. */
+/* Check for a is a PROPER subset of b */
+
+ unsigned int count;
+ unsigned int i;
+
+ CHK(a); CHK(b);
+
+ if (a.n == 0) return 1;
+ count=MIN(a.n,b.n);
+ for (i=0; i < count; i++) {
+ if (a.setword[i] & ~b.setword[i]) return 0;
+ };
+ if (a.n <= b.n) {
+ return 1;
+ } else {
+ for (i=count; i<a.n ; i++) {
+ if (a.setword[i]) return 0;
+ };
+ };
+ return 1;
+}
+
+unsigned
+#ifdef __USE_PROTOS
+set_int( set b )
+#else
+set_int( b )
+set b;
+#endif
+{
+ /* Fast pick any element of the set b */
+ register unsigned *p = b.setword;
+ register unsigned *endp = &(b.setword[b.n]);
+
+ CHK(b);
+ if ( b.n == 0 ) return( nil );
+
+ do {
+ if (*p) {
+ /* Found a non-empty word of the set */
+ register unsigned i = ((p - b.setword) << LogWordSize);
+ register unsigned t = *p;
+ p = &(bitmask[0]);
+ while (!(*p & t)) {
+ ++i; ++p;
+ }
+ return(i);
+ }
+ } while (++p < endp);
+
+ /* Empty -- only element it contains is nil */
+ return(nil);
+}
+
+int
+#ifdef __USE_PROTOS
+set_el( unsigned b, set a )
+#else
+set_el( b, a )
+unsigned b;
+set a;
+#endif
+{
+ CHK(a);
+ /* nil is an element of every set */
+ if (b == nil) return(1);
+ if ( a.n == 0 || NumWords(b) > a.n ) return(0);
+
+ /* Otherwise, we have to check */
+ return( a.setword[DIVWORD(b)] & bitmask[MODWORD(b)] );
+}
+
+int
+#ifdef __USE_PROTOS
+set_nil( set a )
+#else
+set_nil( a )
+set a;
+#endif
+{
+ /* Fast check for nil set */
+ register unsigned *p = a.setword;
+ register unsigned *endp;
+
+ CHK(a);
+ if ( a.n == 0 ) return(1);
+ endp = &(a.setword[a.n]);
+
+ /* The set is not empty if any word used to store
+ the set is non-zero. This means one must be a
+ bit careful about doing things like negation.
+ */
+ do {
+ if (*p) return(0);
+ } while (++p < endp);
+
+ return(1);
+}
+
+char *
+#ifdef __USE_PROTOS
+set_str( set a )
+#else
+set_str( a )
+set a;
+#endif
+{
+ /* Fast convert set a into ASCII char string...
+ assumes that all word bits are used in the set
+ and that SETSIZE is a multiple of WORDSIZE.
+ Trailing 0 bits are removed from the string.
+ if no bits are on or set is empty, "" is returned.
+ */
+ register unsigned *p = a.setword;
+ register unsigned *endp = &(a.setword[a.n]);
+ static char str_tmp[StrSize+1];
+ register char *q = &(str_tmp[0]);
+
+ CHK(a);
+ if ( a.n==0 ) {*q=0; return( &(str_tmp[0]) );}
+ do {
+ register unsigned t = *p;
+ register unsigned *b = &(bitmask[0]);
+ do {
+ *(q++) = (char) ((t & *b) ? '1' : '0');
+ } while (++b < &(bitmask[WORDSIZE]));
+ } while (++p < endp);
+
+ /* Trim trailing 0s & NULL terminate the string */
+ while ((q > &(str_tmp[0])) && (*(q-1) != '1')) --q;
+ *q = 0;
+
+ return(&(str_tmp[0]));
+}
+
+set
+#ifdef __USE_PROTOS
+set_val( register char *s )
+#else
+set_val( s )
+register char *s;
+#endif
+{
+ /* Fast convert set ASCII char string into a set.
+ If the string ends early, the remaining set bits
+ are all made zero.
+ The resulting set size is just big enough to hold all elements.
+ */
+ static set a;
+ register unsigned *p, *endp;
+
+ set_new(a, strlen(s));
+ p = a.setword;
+ endp = &(a.setword[a.n]);
+ do {
+ register unsigned *b = &(bitmask[0]);
+ /* Start with a word with no bits on */
+ *p = 0;
+ do {
+ if (*s) {
+ if (*s == '1') {
+ /* Turn-on this bit */
+ *p |= *b;
+ }
+ ++s;
+ }
+ } while (++b < &(bitmask[WORDSIZE]));
+ } while (++p < endp);
+
+ return(a);
+}
+
+/*
+ * Or element e into set a. a can be empty.
+ */
+void
+#ifdef __USE_PROTOS
+set_orel( unsigned e, set *a )
+#else
+set_orel( e, a )
+unsigned e;
+set *a;
+#endif
+{
+ CHK((*a));
+ if ( e == nil ) return;
+ if ( NumWords(e) > a->n ) set_ext(a, NumWords(e));
+ a->setword[DIVWORD(e)] |= bitmask[MODWORD(e)];
+}
+
+/*
+ * Or set b into set a. a can be empty. does nothing if b empty.
+ */
+void
+#ifdef __USE_PROTOS
+set_orin( set *a, set b )
+#else
+set_orin( a, b )
+set *a;
+set b;
+#endif
+{
+ /* Fast set union operation */
+ /* size(a) is max(a, b); */
+ unsigned int m;
+ register unsigned *p,
+ *q = b.setword,
+ *endq; /* MR20 */
+
+ CHK((*a)); CHK(b);
+ if ( b.n == 0 ) return;
+ endq = &(b.setword[b.n]); /* MR20 */
+ m = (a->n > b.n) ? a->n : b.n;
+ set_ext(a, m);
+ p = a->setword;
+ do {
+ *p++ |= *q++;
+ } while ( q < endq );
+}
+
+/*
+ * And set b into set a. a can be empty. does nothing if b empty.
+ */
+void
+#ifdef __USE_PROTOS
+set_andin( set *a, set b )
+#else
+set_andin( a, b )
+set *a;
+set b;
+#endif
+{
+ /* Fast set intersection operation */
+ /* size(a) is max(a, b); */
+ unsigned int m;
+ register unsigned *p,
+ *q = b.setword,
+ *endq = &(b.setword[b.n]);
+
+ CHK((*a)); CHK(b);
+ if ( b.n == 0 ) return;
+ m = (a->n > b.n) ? a->n : b.n;
+ set_ext(a, m);
+ p = a->setword;
+ do {
+ *p++ &= *q++;
+ } while ( q < endq );
+}
+
+void
+#ifdef __USE_PROTOS
+set_rm( unsigned e, set a )
+#else
+set_rm( e, a )
+unsigned e;
+set a;
+#endif
+{
+ /* Does not effect size of set */
+ CHK(a);
+ if ( (e == nil) || (NumWords(e) > a.n) ) return;
+ a.setword[DIVWORD(e)] ^= (a.setword[DIVWORD(e)]&bitmask[MODWORD(e)]);
+}
+
+void
+#ifdef __USE_PROTOS
+set_clr( set a )
+#else
+set_clr( a )
+set a;
+#endif
+{
+ /* Does not effect size of set */
+ register unsigned *p = a.setword;
+ register unsigned *endp;
+
+ CHK(a);
+ if ( a.n == 0 ) return;
+ endp = &(a.setword[a.n]);
+ do {
+ *p++ = 0;
+ } while ( p < endp );
+}
+
+set
+#ifdef __USE_PROTOS
+set_dup( set a )
+#else
+set_dup( a )
+set a;
+#endif
+{
+ set b;
+ register unsigned *p,
+ *q = a.setword,
+ *endq; /* MR20 */
+
+ CHK(a);
+ b = empty;
+ if ( a.n == 0 ) return( empty );
+ endq = &(a.setword[a.n]); /* MR20 */
+ set_ext(&b, a.n);
+ p = b.setword;
+ do {
+ *p++ = *q++;
+ } while ( q < endq );
+
+ return(b);
+}
+
+/*
+ * Return a nil terminated list of unsigned ints that represents all
+ * "on" bits in the bit set.
+ *
+ * e.g. {011011} --> {1, 2, 4, 5, nil}
+ *
+ * _set_pdq and set_pdq are useful when an operation is required on each element
+ * of a set. Normally, the sequence is:
+ *
+ * while ( set_deg(a) > 0 ) {
+ * e = set_int(a);
+ * set_rm(e, a);
+ * ...process e...
+ * }
+ * Now,
+ *
+ * t = e = set_pdq(a);
+ * while ( *e != nil ) {
+ * ...process *e...
+ * e++;
+ * }
+ * free( t );
+ *
+ * We have saved many set calls and have not destroyed set a.
+ */
+void
+#ifdef __USE_PROTOS
+_set_pdq( set a, register unsigned *q )
+#else
+_set_pdq( a, q )
+set a;
+register unsigned *q;
+#endif
+{
+ register unsigned *p = a.setword,
+ *endp = &(a.setword[a.n]);
+ register unsigned e=0;
+
+ CHK(a);
+ /* are there any space (possibility of elements)? */
+ if ( a.n == 0 ) return;
+ do {
+ register unsigned t = *p;
+ register unsigned *b = &(bitmask[0]);
+ do {
+ if ( t & *b ) *q++ = e;
+ ++e;
+ } while (++b < &(bitmask[WORDSIZE]));
+ } while (++p < endp);
+ *q = nil;
+}
+
+/*
+ * Same as _set_pdq except allocate memory. set_pdq is the natural function
+ * to use.
+ */
+unsigned *
+#ifdef __USE_PROTOS
+set_pdq( set a )
+#else
+set_pdq( a )
+set a;
+#endif
+{
+ unsigned *q;
+ int max_deg;
+
+ CHK(a);
+ max_deg = WORDSIZE*a.n;
+ /* assume a.n!=0 & no elements is rare, but still ok */
+ if ( a.n == 0 ) return(NULL);
+ q = (unsigned *) malloc((max_deg+1)*BytesPerWord);
+ if ( q == NULL ) return( NULL );
+ _set_pdq(a, q);
+ return( q );
+}
+
+/* a function that produces a hash number for the set
+ */
+unsigned int
+#ifdef __USE_PROTOS
+set_hash( set a, register unsigned int mod )
+#else
+set_hash( a, mod )
+set a;
+register unsigned int mod;
+#endif
+{
+ /* Fast hash of set a (assumes all bits used) */
+ register unsigned *p = &(a.setword[0]);
+ register unsigned *endp = &(a.setword[a.n]);
+ register unsigned i = 0;
+
+ CHK(a);
+ while (p<endp){
+ i += (*p);
+ ++p;
+ }
+
+ return(i % mod);
+}
diff --git a/Source/Pccts/support/set/set.h b/Source/Pccts/support/set/set.h
new file mode 100644
index 0000000..5d68152
--- /dev/null
+++ b/Source/Pccts/support/set/set.h
@@ -0,0 +1,121 @@
+#ifndef __GATE_SET_H
+#define __GATE_SET_H
+
+/* set.h
+
+ The following is a general-purpose set library originally developed
+ by Hank Dietz and enhanced by Terence Parr to allow dynamic sets.
+
+ Sets are now structs containing the #words in the set and
+ a pointer to the actual set words.
+
+ 1987 by Hank Dietz
+
+ Modified by:
+ Terence Parr
+ Purdue University
+ October 1989
+
+ Added ANSI prototyping Dec. 1992 -- TJP
+*/
+
+#include "pcctscfg.h"
+
+#ifdef NOT_USED /* SEE config.h */
+/* Define usable bits per unsigned int word */
+#ifdef PC
+#define WORDSIZE 16
+#define LogWordSize 4
+#else
+#define WORDSIZE 32
+#define LogWordSize 5
+#endif
+#define BytesPerWord sizeof(unsigned)
+#endif
+
+#define SETSIZE(a) ((a).n<<LogWordSize) /* Maximum items per set */
+#define MODWORD(x) ((x) & (WORDSIZE-1)) /* x % WORDSIZE */
+#define DIVWORD(x) ((x) >> LogWordSize) /* x / WORDSIZE */
+#define nil (~((unsigned) 0)) /* An impossible set member all bits on (big!) */
+
+typedef struct _set {
+ unsigned int n; /* Number of words in set */
+ unsigned *setword;
+ } set;
+
+#define set_init {0, NULL}
+#define set_null(a) ((a).setword==NULL)
+
+#define NumBytes(x) (((x)>>3)+1) /* Num bytes to hold x */
+#define NumWords(x) ((((unsigned)(x))>>LogWordSize)+1) /* Num words to hold x */
+
+
+/* M a c r o s */
+
+/* make arg1 a set big enough to hold max elem # of arg2 */
+#define set_new(a,_max) \
+if (((a).setword=(unsigned *)calloc(NumWords(_max),BytesPerWord))==NULL) \
+ fprintf(stderr, "set_new: Cannot allocate set with max of %d\n", _max); \
+ (a).n = NumWords(_max);
+
+#define set_free(a) \
+ {if ( (a).setword != NULL ) free((char *)((a).setword)); \
+ (a) = empty;}
+
+#ifdef __USE_PROTOS
+extern void set_size( unsigned );
+extern unsigned int set_deg( set );
+extern set set_or( set, set );
+extern set set_and( set, set );
+extern set set_dif( set, set );
+extern set set_of( unsigned );
+extern void set_ext( set *, unsigned int );
+extern set set_not( set );
+extern int set_equ( set, set );
+extern int set_sub( set, set );
+extern unsigned set_int( set );
+extern int set_el( unsigned, set );
+extern int set_nil( set );
+extern char * set_str( set );
+extern set set_val( register char * );
+extern void set_orel( unsigned, set * );
+extern void set_orin( set *, set );
+extern void set_andin( set *, set );
+extern void set_rm( unsigned, set );
+extern void set_clr( set );
+extern set set_dup( set );
+extern void set_PDQ( set, register unsigned * );
+extern unsigned *set_pdq( set );
+extern void _set_pdq( set a, register unsigned *q );
+extern unsigned int set_hash( set, register unsigned int );
+#else
+extern void set_size();
+extern unsigned int set_deg();
+extern set set_or();
+extern set set_and();
+extern set set_dif();
+extern set set_of();
+extern void set_ext();
+extern set set_not();
+extern int set_equ();
+extern int set_sub();
+extern unsigned set_int();
+extern int set_el();
+extern int set_nil();
+extern char * set_str();
+extern set set_val();
+extern void set_orel();
+extern void set_orin();
+extern void set_andin();
+extern void set_rm();
+extern void set_clr();
+extern set set_dup();
+extern void set_PDQ();
+extern unsigned *set_pdq();
+extern void _set_pdq();
+extern unsigned int set_hash();
+#endif
+
+extern set empty;
+
+#endif
diff --git a/Source/Pccts/support/sym/sym.c b/Source/Pccts/support/sym/sym.c
new file mode 100644
index 0000000..eccce05
--- /dev/null
+++ b/Source/Pccts/support/sym/sym.c
@@ -0,0 +1,402 @@
+/*
+ * Simple symbol table manager using coalesced chaining to resolve collisions
+ *
+ * Doubly-linked lists are used for fast removal of entries.
+ *
+ * 'sym.h' must have a definition for typedef "Sym". Sym must include at
+ * minimum the following fields:
+ *
+ * ...
+ * char *symbol;
+ * struct ... *next, *prev, **head, *scope;
+ * unsigned int hash;
+ * ...
+ *
+ * 'template.h' can be used as a template to create a 'sym.h'.
+ *
+ * 'head' is &(table[hash(itself)]).
+ * The hash table is not resizable at run-time.
+ * The scope field is used to link all symbols of a current scope together.
+ * Scope() sets the current scope (linked list) to add symbols to.
+ * Any number of scopes can be handled. The user passes the address of
+ * a pointer to a symbol table
+ * entry (INITIALIZED TO NULL first time).
+ *
+ * Available Functions:
+ *
+ * zzs_init(s1,s2) -- Create hash table with size s1, string table size s2.
+ * zzs_done() -- Free hash and string table created with zzs_init().
+ * zzs_add(key,rec)-- Add 'rec' with key 'key' to the symbol table.
+ * zzs_newadd(key) -- create entry; add using 'key' to the symbol table.
+ * zzs_get(key) -- Return pointer to last record entered under 'key'
+ * Else return NULL
+ * zzs_del(p) -- Unlink the entry associated with p. This does
+ * NOT free 'p' and DOES NOT remove it from a scope
+ * list. If it was a part of your intermediate code
+ * tree or another structure. It will still be there.
+ * It is only removed from further consideration
+ * by the symbol table.
+ * zzs_keydel(s) -- Unlink the entry associated with key s.
+ * Calls zzs_del(p) to unlink.
+ * zzs_scope(sc) -- Specifies that everything added to the symbol
+ * table with zzs_add() is added to the list (scope)
+ * 'sc'. 'sc' is of 'Sym **sc' type and must be
+ * initialized to NULL before trying to add anything
+ * to it (passing it to zzs_scope()). Scopes can be
+ * switched at any time and merely links a set of
+ * symbol table entries. If a NULL pointer is
+ * passed, the current scope is returned.
+ * zzs_rmscope(sc) -- Remove (zzs_del()) all elements of scope 'sc'
+ * from the symbol table. The entries are NOT
+ * free()'d. A pointer to the first
+ * element in the "scope" is returned. The user
+ * can then manipulate the list as he/she chooses
+ * (such as freeing them all). NOTE that this
+ * function sets your scope pointer to NULL,
+ * but returns a pointer to the list for you to use.
+ * zzs_stat() -- Print out the symbol table and some relevant stats.
+ * zzs_new(key) -- Create a new record with calloc() of type Sym.
+ * Add 'key' to the string table and make the new
+ * records 'symbol' pointer point to it.
+ * zzs_strdup(s) -- Add s to the string table and return a pointer
+ * to it. Very fast allocation routine
+ * and does not require strlen() nor calloc().
+ *
+ * Example:
+ *
+ * #include <stdio.h>
+ * #include "sym.h"
+ *
+ * main()
+ * {
+ * Sym *scope1=NULL, *scope2=NULL, *a, *p;
+ *
+ * zzs_init(101, 100);
+ *
+ * a = zzs_new("Apple"); zzs_add(a->symbol, a); -- No scope
+ * zzs_scope( &scope1 ); -- enter scope 1
+ * a = zzs_new("Plum"); zzs_add(a->symbol, a);
+ * zzs_scope( &scope2 ); -- enter scope 2
+ * a = zzs_new("Truck"); zzs_add(a->symbol, a);
+ *
+ * p = zzs_get("Plum");
+ * if ( p == NULL ) fprintf(stderr, "Hmmm...Can't find 'Plum'\n");
+ *
+ * p = zzs_rmscope(&scope1)
+ * for (; p!=NULL; p=p->scope) {printf("Scope1: %s\n", p->symbol);}
+ * p = zzs_rmscope(&scope2)
+ * for (; p!=NULL; p=p->scope) {printf("Scope2: %s\n", p->symbol);}
+ * }
+ *
+ * Terence Parr
+ * Purdue University
+ * February 1990
+ *
+ * CHANGES
+ *
+ * Terence Parr
+ * May 1991
+ * Renamed functions to be consistent with ANTLR
+ * Made HASH macro
+ * Added zzs_keydel()
+ * Added zzs_newadd()
+ * Fixed up zzs_stat()
+ *
+ * July 1991
+ * Made symbol table entry save its hash code for fast comparison
+ * during searching etc...
+ */
+
+#include <stdio.h>
+#if defined(__STDC__) || defined(__USE_PROTOS)
+#include <string.h>
+#include <stdlib.h>
+#else
+#include <malloc.h>
+#endif
+#include "sym.h"
+
+#define StrSame 0
+
+static Sym **CurScope = NULL;
+static unsigned size = 0;
+static Sym **table=NULL;
+static char *strings;
+static char *strp;
+static int strsize = 0;
+
+#ifdef __USE_PROTOS
+void zzs_init(int sz,int strs)
+#else
+void zzs_init(sz, strs)
+int sz, strs;
+#endif
+{
+ if ( sz <= 0 || strs <= 0 ) return;
+ table = (Sym **) calloc(sz, sizeof(Sym *));
+ if ( table == NULL )
+ {
+ fprintf(stderr, "Cannot allocate table of size %d\n", sz);
+ exit(1);
+ }
+ strings = (char *) calloc(strs, sizeof(char));
+ if ( strings == NULL )
+ {
+ fprintf(stderr, "Cannot allocate string table of size %d\n", strs);
+ exit(1);
+ }
+ size = sz;
+ strsize = strs;
+ strp = strings;
+}
+
+#ifdef __USE_PROTOS
+void zzs_done(void)
+#else
+void zzs_done()
+#endif
+{
+ if ( table != NULL ) free( table );
+ if ( strings != NULL ) free( strings );
+}
+
+#ifdef __USE_PROTOS
+void zzs_add(char *key,Sym rec)
+#else
+void zzs_add(key, rec)
+char *key;
+register Sym *rec;
+#endif
+{
+ register unsigned int h=0;
+ register char *p=key;
+
+ HASH(p, h);
+ rec->hash = h; /* save hash code for fast comp later */
+ h %= size;
+
+ if ( CurScope != NULL ) {rec->scope = *CurScope; *CurScope = rec;}
+ rec->next = table[h]; /* Add to doubly-linked list */
+ rec->prev = NULL;
+ if ( rec->next != NULL ) (rec->next)->prev = rec;
+ table[h] = rec;
+ rec->head = &(table[h]);
+}
+
+#ifdef __USE_PROTOS
+Sym * zzs_get(char *key)
+#else
+Sym * zzs_get(key)
+char *key;
+#endif
+{
+ register unsigned int h=0;
+ register char *p=key;
+ register Sym *q;
+
+ HASH(p, h);
+
+ for (q = table[h%size]; q != NULL; q = q->next)
+ {
+ if ( q->hash == h ) /* do we even have a chance of matching? */
+ if ( strcmp(key, q->symbol) == StrSame ) return( q );
+ }
+ return( NULL );
+}
+
+/*
+ * Unlink p from the symbol table. Hopefully, it's actually in the
+ * symbol table.
+ *
+ * If p is not part of a bucket chain of the symbol table, bad things
+ * will happen.
+ *
+ * Will do nothing if all list pointers are NULL
+ */
+#ifdef __USE_PROTOS
+void zzs_del(Sym *p)
+#else
+void zzs_del(p)
+register Sym *p;
+#endif
+{
+ if ( p == NULL ) {fprintf(stderr, "zzs_del(NULL)\n"); exit(1);}
+ if ( p->prev == NULL ) /* Head of list */
+ {
+ register Sym **t = p->head;
+
+ if ( t == NULL ) return; /* not part of symbol table */
+ (*t) = p->next;
+ if ( (*t) != NULL ) (*t)->prev = NULL;
+ }
+ else
+ {
+ (p->prev)->next = p->next;
+ if ( p->next != NULL ) (p->next)->prev = p->prev;
+ }
+ p->next = p->prev = NULL; /* not part of symbol table anymore */
+ p->head = NULL;
+}
+
+#ifdef __USE_PROTOS
+void zzs_keydel(char *key)
+#else
+void zzs_keydel(key)
+char *key;
+#endif
+{
+ Sym *p = zzs_get(key);
+
+ if ( p != NULL ) zzs_del( p );
+}
+
+/* S c o p e S t u f f */
+
+/* Set current scope to 'scope'; return current scope if 'scope' == NULL */
+
+#ifdef __USE_PROTOS
+Sym ** zzs_scope(Sym **scope)
+#else
+Sym ** zzs_scope(scope)
+Sym **scope;
+#endif
+{
+ if ( scope == NULL ) return( CurScope );
+ CurScope = scope;
+ return( scope );
+}
+
+/* Remove a scope described by 'scope'. Return pointer to 1st element in scope */
+
+#ifdef __USE_PROTOS
+Sym * zzs_rmscope(Sym **scope)
+#else
+Sym * zzs_rmscope(scope)
+register Sym **scope;
+#endif
+{
+ register Sym *p;
+ Sym *start;
+
+ if ( scope == NULL ) return(NULL);
+ start = p = *scope;
+ for (; p != NULL; p=p->scope) { zzs_del( p ); }
+ *scope = NULL;
+ return( start );
+}
+
+#ifdef __USE_PROTOS
+void zzs_stat(void)
+#else
+void zzs_stat()
+#endif
+{
+ static unsigned short count[20];
+ unsigned int i,n=0,low=0, hi=0;
+ register Sym **p;
+ float avg=0.0;
+
+ for (i=0; i<20; i++) count[i] = 0;
+ for (p=table; p<&(table[size]); p++)
+ {
+ register Sym *q = *p;
+ unsigned int len;
+
+ if ( q != NULL && low==0 ) low = p-table;
+ len = 0;
+ if ( q != NULL ) printf("[%d]", p-table);
+ while ( q != NULL )
+ {
+ len++;
+ n++;
+ printf(" %s", q->symbol);
+ q = q->next;
+ if ( q == NULL ) printf("\n");
+ }
+ if ( len>=20 ) printf("zzs_stat: count table too small\n");
+ else count[len]++;
+ if ( *p != NULL ) hi = p-table;
+ }
+
+ printf("Storing %d recs used %d hash positions out of %d\n",
+ n, size-count[0], size);
+ printf("%f %% utilization\n",
+ ((float)(size-count[0]))/((float)size));
+ for (i=0; i<20; i++)
+ {
+ if ( count[i] != 0 )
+ {
+ avg += (((float)(i*count[i]))/((float)n)) * i;
+ printf("Buckets of len %d == %d (%f %% of recs)\n",
+ i, count[i], 100.0*((float)(i*count[i]))/((float)n));
+ }
+ }
+ printf("Avg bucket length %f\n", avg);
+ printf("Range of hash function: %d..%d\n", low, hi);
+}
+
+/*
+ * Given a string, this function allocates and returns a pointer to a
+ * symbol table record whose "symbol" pointer is reset to a position
+ * in the string table.
+ */
+
+#ifdef __USE_PROTOS
+Sym * zzs_new(char *text)
+#else
+Sym * zzs_new(text)
+char *text;
+#endif
+{
+ Sym *p;
+
+ if ( (p = (Sym *) calloc(1,sizeof(Sym))) == 0 )
+ {
+ fprintf(stderr,"Out of memory\n");
+ exit(1);
+ }
+ p->symbol = zzs_strdup(text);
+
+ return p;
+}
+
+/* create a new symbol table entry and add it to the symbol table */
+
+#ifdef __USE_PROTOS
+Sym * zzs_newadd(char *text)
+#else
+Sym * zzs_newadd(text)
+char *text;
+#endif
+{
+ Sym *p = zzs_new(text);
+ if ( p != NULL ) zzs_add(text, p);
+ return p;
+}
+
+/* Add a string to the string table and return a pointer to it.
+ * Bump the pointer into the string table to next avail position.
+ */
+
+#ifdef __USE_PROTOS
+char * zzs_strdup(char *s)
+#else
+char * zzs_strdup(s)
+register char *s;
+#endif
+{
+ register char *start=strp;
+
+ while ( *s != '\0' )
+ {
+ if ( strp >= &(strings[strsize-2]) )
+ {
+ fprintf(stderr, "sym: string table overflow (%d chars)\n", strsize);
+ exit(-1);
+ }
+ *strp++ = *s++;
+ }
+ *strp++ = '\0';
+
+ return( start );
+}
diff --git a/Source/Pccts/support/sym/template.h b/Source/Pccts/support/sym/template.h
new file mode 100644
index 0000000..ee6e665
--- /dev/null
+++ b/Source/Pccts/support/sym/template.h
@@ -0,0 +1,41 @@
+/* T e m p l a t e F o r S y m b o l T a b l e M a n a g e r */
+
+/* define some hash function */
+#ifndef HASH
+#define HASH(p, h) while ( *p != '\0' ) h = (h<<1) + *p++;
+#endif
+
+/* minimum symbol table record */
+typedef struct _sym {
+ char *symbol;
+ struct _sym *next, *prev, **head, *scope;
+ unsigned int hash;
+ } Sym, *SymPtr;
+
+#ifdef __USE_PROTOS
+void zzs_init(int, int);
+void zzs_done(void);
+void zzs_add(char *, Sym *);
+Sym *zzs_get(char *);
+void zzs_del(Sym *);
+void zzs_keydel(char *);
+Sym **zzs_scope(Sym **);
+Sym *zzs_rmscope(Sym **);
+void zzs_stat(void);
+Sym *zzs_new(char *);
+Sym *zzs_newadd(char *);
+char *zzs_strdup(char *);
+#else
+void zzs_init();
+void zzs_done();
+void zzs_add();
+Sym *zzs_get();
+void zzs_del();
+void zzs_keydel();
+Sym **zzs_scope();
+Sym *zzs_rmscope();
+void zzs_stat();
+Sym *zzs_new();
+Sym *zzs_newadd();
+char *zzs_strdup();
+#endif
diff --git a/Source/PeCoffLoader/BasePeCoff.c b/Source/PeCoffLoader/BasePeCoff.c
new file mode 100644
index 0000000..9c25e1f
--- /dev/null
+++ b/Source/PeCoffLoader/BasePeCoff.c
@@ -0,0 +1,1060 @@
+/*++
+
+Copyright (c) 2004 - 2005, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ PeCoffLoader.c
+
+Abstract:
+
+ Tiano PE/COFF loader
+
+Revision History
+
+--*/
+
+
+#include <Common/UefiBaseTypes.h>
+#include <Common/EfiImage.h>
+#include <Library/PeCoffLib.h>
+
+STATIC
+RETURN_STATUS
+PeCoffLoaderGetPeHeader (
+ IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext,
+ OUT EFI_IMAGE_NT_HEADERS *PeHdr,
+ OUT EFI_TE_IMAGE_HEADER *TeHdr
+ );
+
+STATIC
+RETURN_STATUS
+PeCoffLoaderCheckImageType (
+ IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext,
+ IN EFI_IMAGE_NT_HEADERS *PeHdr,
+ IN EFI_TE_IMAGE_HEADER *TeHdr
+ );
+
+STATIC
+VOID *
+PeCoffLoaderImageAddress (
+ IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext,
+ IN UINTN Address
+ );
+
+
+STATIC
+RETURN_STATUS
+PeCoffLoaderGetPeHeader (
+ IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext,
+ OUT EFI_IMAGE_NT_HEADERS *PeHdr,
+ OUT EFI_TE_IMAGE_HEADER *TeHdr
+ )
+/*++
+
+Routine Description:
+
+ Retrieves the PE or TE Header from a PE/COFF or TE image
+
+Arguments:
+
+ ImageContext - The context of the image being loaded
+
+ PeHdr - The buffer in which to return the PE header
+
+ TeHdr - The buffer in which to return the TE header
+
+Returns:
+
+ RETURN_SUCCESS if the PE or TE Header is read,
+ Otherwise, the error status from reading the PE/COFF or TE image using the ImageRead function.
+
+--*/
+{
+ RETURN_STATUS Status;
+ EFI_IMAGE_DOS_HEADER DosHdr;
+ UINTN Size;
+
+ ImageContext->IsTeImage = FALSE;
+ //
+ // Read the DOS image headers
+ //
+ Size = sizeof (EFI_IMAGE_DOS_HEADER);
+ Status = ImageContext->ImageRead (
+ ImageContext->Handle,
+ 0,
+ &Size,
+ &DosHdr
+ );
+ if (RETURN_ERROR (Status)) {
+ ImageContext->ImageError = IMAGE_ERROR_IMAGE_READ;
+ return Status;
+ }
+
+ ImageContext->PeCoffHeaderOffset = 0;
+ if (DosHdr.e_magic == EFI_IMAGE_DOS_SIGNATURE) {
+ //
+ // DOS image header is present, so read the PE header after the DOS image header
+ //
+ ImageContext->PeCoffHeaderOffset = DosHdr.e_lfanew;
+ }
+ //
+ // Read the PE/COFF Header
+ //
+ Size = sizeof (EFI_IMAGE_NT_HEADERS);
+ Status = ImageContext->ImageRead (
+ ImageContext->Handle,
+ ImageContext->PeCoffHeaderOffset,
+ &Size,
+ PeHdr
+ );
+ if (RETURN_ERROR (Status)) {
+ ImageContext->ImageError = IMAGE_ERROR_IMAGE_READ;
+ return Status;
+ }
+ //
+ // Check the PE/COFF Header Signature. If not, then try to read a TE header
+ //
+ if (PeHdr->Signature != EFI_IMAGE_NT_SIGNATURE) {
+ Size = sizeof (EFI_TE_IMAGE_HEADER);
+ Status = ImageContext->ImageRead (
+ ImageContext->Handle,
+ 0,
+ &Size,
+ TeHdr
+ );
+ if (TeHdr->Signature != EFI_TE_IMAGE_HEADER_SIGNATURE) {
+ return RETURN_UNSUPPORTED;
+ }
+
+ ImageContext->IsTeImage = TRUE;
+ }
+
+ return RETURN_SUCCESS;
+}
+
+STATIC
+RETURN_STATUS
+PeCoffLoaderCheckImageType (
+ IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext,
+ IN EFI_IMAGE_NT_HEADERS *PeHdr,
+ IN EFI_TE_IMAGE_HEADER *TeHdr
+ )
+/*++
+
+Routine Description:
+
+ Checks the PE or TE header of a PE/COFF or TE image to determine if it supported
+
+Arguments:
+
+ ImageContext - The context of the image being loaded
+
+ PeHdr - The buffer in which to return the PE header
+
+ TeHdr - The buffer in which to return the TE header
+
+Returns:
+
+ RETURN_SUCCESS if the PE/COFF or TE image is supported
+ RETURN_UNSUPPORTED of the PE/COFF or TE image is not supported.
+
+--*/
+{
+ //
+ // See if the machine type is supported. We support a native machine type (IA-32/Itanium-based)
+ // and the machine type for the Virtual Machine.
+ //
+ if (ImageContext->IsTeImage == FALSE) {
+ ImageContext->Machine = PeHdr->FileHeader.Machine;
+ } else {
+ ImageContext->Machine = TeHdr->Machine;
+ }
+
+ if (!(EFI_IMAGE_MACHINE_TYPE_SUPPORTED (ImageContext->Machine))) {
+ ImageContext->ImageError = IMAGE_ERROR_INVALID_MACHINE_TYPE;
+ return RETURN_UNSUPPORTED;
+ }
+
+ //
+ // See if the image type is supported. We support EFI Applications,
+ // EFI Boot Service Drivers, and EFI Runtime Drivers.
+ //
+ if (ImageContext->IsTeImage == FALSE) {
+ ImageContext->ImageType = PeHdr->OptionalHeader.Subsystem;
+ } else {
+ ImageContext->ImageType = (UINT16) (TeHdr->Subsystem);
+ }
+
+
+ return RETURN_SUCCESS;
+}
+
+RETURN_STATUS
+EFIAPI
+PeCoffLoaderGetImageInfo (
+ IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext
+ )
+/*++
+
+Routine Description:
+
+ Retrieves information on a PE/COFF image
+
+Arguments:
+
+ This - Calling context
+ ImageContext - The context of the image being loaded
+
+Returns:
+
+ RETURN_SUCCESS - The information on the PE/COFF image was collected.
+ RETURN_INVALID_PARAMETER - ImageContext is NULL.
+ RETURN_UNSUPPORTED - The PE/COFF image is not supported.
+ Otherwise - The error status from reading the PE/COFF image using the
+ ImageContext->ImageRead() function
+
+--*/
+{
+ RETURN_STATUS Status;
+ EFI_IMAGE_NT_HEADERS PeHdr;
+ EFI_TE_IMAGE_HEADER TeHdr;
+ EFI_IMAGE_DATA_DIRECTORY *DebugDirectoryEntry;
+ UINTN Size;
+ UINTN Index;
+ UINTN DebugDirectoryEntryRva;
+ UINTN DebugDirectoryEntryFileOffset;
+ UINTN SectionHeaderOffset;
+ EFI_IMAGE_SECTION_HEADER SectionHeader;
+ EFI_IMAGE_DEBUG_DIRECTORY_ENTRY DebugEntry;
+
+ if (NULL == ImageContext) {
+ return RETURN_INVALID_PARAMETER;
+ }
+ //
+ // Assume success
+ //
+ ImageContext->ImageError = IMAGE_ERROR_SUCCESS;
+
+ Status = PeCoffLoaderGetPeHeader (ImageContext, &PeHdr, &TeHdr);
+ if (RETURN_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // Verify machine type
+ //
+ Status = PeCoffLoaderCheckImageType (ImageContext, &PeHdr, &TeHdr);
+ if (RETURN_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // Retrieve the base address of the image
+ //
+ if (!(ImageContext->IsTeImage)) {
+ ImageContext->ImageAddress = PeHdr.OptionalHeader.ImageBase;
+ } else {
+ ImageContext->ImageAddress = (PHYSICAL_ADDRESS) (TeHdr.ImageBase);
+ }
+ //
+ // Initialize the alternate destination address to 0 indicating that it
+ // should not be used.
+ //
+ ImageContext->DestinationAddress = 0;
+
+ //
+ // Initialize the codeview pointer.
+ //
+ ImageContext->CodeView = NULL;
+ ImageContext->PdbPointer = NULL;
+
+ //
+ // Three cases with regards to relocations:
+ // - Image has base relocs, RELOCS_STRIPPED==0 => image is relocatable
+ // - Image has no base relocs, RELOCS_STRIPPED==1 => Image is not relocatable
+ // - Image has no base relocs, RELOCS_STRIPPED==0 => Image is relocatable but
+ // has no base relocs to apply
+ // Obviously having base relocations with RELOCS_STRIPPED==1 is invalid.
+ //
+ // Look at the file header to determine if relocations have been stripped, and
+ // save this info in the image context for later use.
+ //
+ if ((!(ImageContext->IsTeImage)) && ((PeHdr.FileHeader.Characteristics & EFI_IMAGE_FILE_RELOCS_STRIPPED) != 0)) {
+ ImageContext->RelocationsStripped = TRUE;
+ } else {
+ ImageContext->RelocationsStripped = FALSE;
+ }
+
+ if (!(ImageContext->IsTeImage)) {
+ ImageContext->ImageSize = (UINT64) PeHdr.OptionalHeader.SizeOfImage;
+ ImageContext->SectionAlignment = PeHdr.OptionalHeader.SectionAlignment;
+ ImageContext->SizeOfHeaders = PeHdr.OptionalHeader.SizeOfHeaders;
+
+ //
+ // Modify ImageSize to contain .PDB file name if required and initialize
+ // PdbRVA field...
+ //
+ if (PeHdr.OptionalHeader.NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG) {
+ DebugDirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *) &(PeHdr.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG]);
+
+ DebugDirectoryEntryRva = DebugDirectoryEntry->VirtualAddress;
+
+ //
+ // Determine the file offset of the debug directory... This means we walk
+ // the sections to find which section contains the RVA of the debug
+ // directory
+ //
+ DebugDirectoryEntryFileOffset = 0;
+
+ SectionHeaderOffset = (UINTN)(
+ ImageContext->PeCoffHeaderOffset +
+ sizeof (UINT32) +
+ sizeof (EFI_IMAGE_FILE_HEADER) +
+ PeHdr.FileHeader.SizeOfOptionalHeader
+ );
+
+ for (Index = 0; Index < PeHdr.FileHeader.NumberOfSections; Index++) {
+ //
+ // Read section header from file
+ //
+ Size = sizeof (EFI_IMAGE_SECTION_HEADER);
+ Status = ImageContext->ImageRead (
+ ImageContext->Handle,
+ SectionHeaderOffset,
+ &Size,
+ &SectionHeader
+ );
+ if (RETURN_ERROR (Status)) {
+ ImageContext->ImageError = IMAGE_ERROR_IMAGE_READ;
+ return Status;
+ }
+
+ if (DebugDirectoryEntryRva >= SectionHeader.VirtualAddress &&
+ DebugDirectoryEntryRva < SectionHeader.VirtualAddress + SectionHeader.Misc.VirtualSize) {
+ DebugDirectoryEntryFileOffset =
+ DebugDirectoryEntryRva - SectionHeader.VirtualAddress + SectionHeader.PointerToRawData;
+ break;
+ }
+
+ SectionHeaderOffset += sizeof (EFI_IMAGE_SECTION_HEADER);
+ }
+
+ if (DebugDirectoryEntryFileOffset != 0) {
+ for (Index = 0; Index < DebugDirectoryEntry->Size; Index++) {
+ //
+ // Read next debug directory entry
+ //
+ Size = sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY);
+ Status = ImageContext->ImageRead (
+ ImageContext->Handle,
+ DebugDirectoryEntryFileOffset,
+ &Size,
+ &DebugEntry
+ );
+ if (RETURN_ERROR (Status)) {
+ ImageContext->ImageError = IMAGE_ERROR_IMAGE_READ;
+ return Status;
+ }
+
+ if (DebugEntry.Type == EFI_IMAGE_DEBUG_TYPE_CODEVIEW) {
+ ImageContext->DebugDirectoryEntryRva = (UINT32) (DebugDirectoryEntryRva + Index * sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY));
+ if (DebugEntry.RVA == 0 && DebugEntry.FileOffset != 0) {
+ ImageContext->ImageSize += DebugEntry.SizeOfData;
+ }
+
+ return RETURN_SUCCESS;
+ }
+ }
+ }
+ }
+ } else {
+ ImageContext->ImageSize = 0;
+ ImageContext->SectionAlignment = 4096;
+ ImageContext->SizeOfHeaders = sizeof (EFI_TE_IMAGE_HEADER) + (UINTN) TeHdr.BaseOfCode - (UINTN) TeHdr.StrippedSize;
+
+ DebugDirectoryEntry = &TeHdr.DataDirectory[1];
+ DebugDirectoryEntryRva = DebugDirectoryEntry->VirtualAddress;
+ SectionHeaderOffset = (UINTN) (sizeof (EFI_TE_IMAGE_HEADER));
+
+ DebugDirectoryEntryFileOffset = 0;
+
+ for (Index = 0; Index < TeHdr.NumberOfSections;) {
+ //
+ // Read section header from file
+ //
+ Size = sizeof (EFI_IMAGE_SECTION_HEADER);
+ Status = ImageContext->ImageRead (
+ ImageContext->Handle,
+ SectionHeaderOffset,
+ &Size,
+ &SectionHeader
+ );
+ if (RETURN_ERROR (Status)) {
+ ImageContext->ImageError = IMAGE_ERROR_IMAGE_READ;
+ return Status;
+ }
+
+ if (DebugDirectoryEntryRva >= SectionHeader.VirtualAddress &&
+ DebugDirectoryEntryRva < SectionHeader.VirtualAddress + SectionHeader.Misc.VirtualSize) {
+ DebugDirectoryEntryFileOffset = DebugDirectoryEntryRva -
+ SectionHeader.VirtualAddress +
+ SectionHeader.PointerToRawData +
+ sizeof (EFI_TE_IMAGE_HEADER) -
+ TeHdr.StrippedSize;
+
+ //
+ // File offset of the debug directory was found, if this is not the last
+ // section, then skip to the last section for calculating the image size.
+ //
+ if (Index < (UINTN) TeHdr.NumberOfSections - 1) {
+ SectionHeaderOffset += (TeHdr.NumberOfSections - 1 - Index) * sizeof (EFI_IMAGE_SECTION_HEADER);
+ Index = TeHdr.NumberOfSections - 1;
+ continue;
+ }
+ }
+
+ //
+ // In Te image header there is not a field to describe the ImageSize.
+ // Actually, the ImageSize equals the RVA plus the VirtualSize of
+ // the last section mapped into memory (Must be rounded up to
+ // a mulitple of Section Alignment). Per the PE/COFF specification, the
+ // section headers in the Section Table must appear in order of the RVA
+ // values for the corresponding sections. So the ImageSize can be determined
+ // by the RVA and the VirtualSize of the last section header in the
+ // Section Table.
+ //
+ if ((++Index) == (UINTN) TeHdr.NumberOfSections) {
+ ImageContext->ImageSize = (SectionHeader.VirtualAddress + SectionHeader.Misc.VirtualSize +
+ ImageContext->SectionAlignment - 1) & ~(ImageContext->SectionAlignment - 1);
+ }
+
+ SectionHeaderOffset += sizeof (EFI_IMAGE_SECTION_HEADER);
+ }
+
+ if (DebugDirectoryEntryFileOffset != 0) {
+ for (Index = 0; Index < DebugDirectoryEntry->Size; Index++) {
+ //
+ // Read next debug directory entry
+ //
+ Size = sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY);
+ Status = ImageContext->ImageRead (
+ ImageContext->Handle,
+ DebugDirectoryEntryFileOffset,
+ &Size,
+ &DebugEntry
+ );
+ if (RETURN_ERROR (Status)) {
+ ImageContext->ImageError = IMAGE_ERROR_IMAGE_READ;
+ return Status;
+ }
+
+ if (DebugEntry.Type == EFI_IMAGE_DEBUG_TYPE_CODEVIEW) {
+ ImageContext->DebugDirectoryEntryRva = (UINT32) (DebugDirectoryEntryRva + Index * sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY));
+ return RETURN_SUCCESS;
+ }
+ }
+ }
+ }
+
+ return RETURN_SUCCESS;
+}
+
+STATIC
+VOID *
+PeCoffLoaderImageAddress (
+ IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext,
+ IN UINTN Address
+ )
+/*++
+
+Routine Description:
+
+ Converts an image address to the loaded address
+
+Arguments:
+
+ ImageContext - The context of the image being loaded
+
+ Address - The address to be converted to the loaded address
+
+Returns:
+
+ NULL if the address can not be converted, otherwise, the converted address
+
+--*/
+{
+ if (Address >= ImageContext->ImageSize) {
+ ImageContext->ImageError = IMAGE_ERROR_INVALID_IMAGE_ADDRESS;
+ return NULL;
+ }
+
+ return (CHAR8 *) ((UINTN) ImageContext->ImageAddress + Address);
+}
+
+RETURN_STATUS
+EFIAPI
+PeCoffLoaderRelocateImage (
+ IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext
+ )
+/*++
+
+Routine Description:
+
+ Relocates a PE/COFF image in memory
+
+Arguments:
+
+ This - Calling context
+
+ ImageContext - Contains information on the loaded image to relocate
+
+Returns:
+
+ RETURN_SUCCESS if the PE/COFF image was relocated
+ RETURN_LOAD_ERROR if the image is not a valid PE/COFF image
+ RETURN_UNSUPPORTED not support
+
+--*/
+{
+ RETURN_STATUS Status;
+ EFI_IMAGE_NT_HEADERS *PeHdr;
+ EFI_TE_IMAGE_HEADER *TeHdr;
+ EFI_IMAGE_DATA_DIRECTORY *RelocDir;
+ UINT64 Adjust;
+ EFI_IMAGE_BASE_RELOCATION *RelocBase;
+ EFI_IMAGE_BASE_RELOCATION *RelocBaseEnd;
+ UINT16 *Reloc;
+ UINT16 *RelocEnd;
+ CHAR8 *Fixup;
+ CHAR8 *FixupBase;
+ UINT16 *F16;
+ UINT32 *F32;
+ CHAR8 *FixupData;
+ PHYSICAL_ADDRESS BaseAddress;
+
+ PeHdr = NULL;
+ TeHdr = NULL;
+ //
+ // Assume success
+ //
+ ImageContext->ImageError = IMAGE_ERROR_SUCCESS;
+
+ //
+ // If there are no relocation entries, then we are done
+ //
+ if (ImageContext->RelocationsStripped) {
+ return RETURN_SUCCESS;
+ }
+
+ //
+ // If the destination address is not 0, use that rather than the
+ // image address as the relocation target.
+ //
+ if (ImageContext->DestinationAddress) {
+ BaseAddress = ImageContext->DestinationAddress;
+ } else {
+ BaseAddress = ImageContext->ImageAddress;
+ }
+
+ if (!(ImageContext->IsTeImage)) {
+ PeHdr = (EFI_IMAGE_NT_HEADERS *)((UINTN)ImageContext->ImageAddress +
+ ImageContext->PeCoffHeaderOffset);
+ Adjust = (UINT64) BaseAddress - PeHdr->OptionalHeader.ImageBase;
+ PeHdr->OptionalHeader.ImageBase = (UINTN) BaseAddress;
+
+ //
+ // Find the relocation block
+ //
+ // Per the PE/COFF spec, you can't assume that a given data directory
+ // is present in the image. You have to check the NumberOfRvaAndSizes in
+ // the optional header to verify a desired directory entry is there.
+ //
+ if (PeHdr->OptionalHeader.NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) {
+ RelocDir = &PeHdr->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC];
+ RelocBase = PeCoffLoaderImageAddress (ImageContext, RelocDir->VirtualAddress);
+ RelocBaseEnd = PeCoffLoaderImageAddress (
+ ImageContext,
+ RelocDir->VirtualAddress + RelocDir->Size - 1
+ );
+ } else {
+ //
+ // Set base and end to bypass processing below.
+ //
+ RelocBase = RelocBaseEnd = 0;
+ }
+ } else {
+ TeHdr = (EFI_TE_IMAGE_HEADER *) (UINTN) (ImageContext->ImageAddress);
+ Adjust = (UINT64) (BaseAddress - TeHdr->ImageBase);
+ TeHdr->ImageBase = (UINT64) (BaseAddress);
+
+ //
+ // Find the relocation block
+ //
+ RelocDir = &TeHdr->DataDirectory[0];
+ RelocBase = (EFI_IMAGE_BASE_RELOCATION *)(UINTN)(
+ ImageContext->ImageAddress +
+ RelocDir->VirtualAddress +
+ sizeof(EFI_TE_IMAGE_HEADER) -
+ TeHdr->StrippedSize
+ );
+ RelocBaseEnd = (EFI_IMAGE_BASE_RELOCATION *) ((UINTN) RelocBase + (UINTN) RelocDir->Size - 1);
+ }
+
+ //
+ // Run the relocation information and apply the fixups
+ //
+ FixupData = ImageContext->FixupData;
+ while (RelocBase < RelocBaseEnd) {
+
+ Reloc = (UINT16 *) ((CHAR8 *) RelocBase + sizeof (EFI_IMAGE_BASE_RELOCATION));
+ RelocEnd = (UINT16 *) ((CHAR8 *) RelocBase + RelocBase->SizeOfBlock);
+ if (!(ImageContext->IsTeImage)) {
+ FixupBase = PeCoffLoaderImageAddress (ImageContext, RelocBase->VirtualAddress);
+ } else {
+ FixupBase = (CHAR8 *)(UINTN)(ImageContext->ImageAddress +
+ RelocBase->VirtualAddress +
+ sizeof(EFI_TE_IMAGE_HEADER) -
+ TeHdr->StrippedSize
+ );
+ }
+
+ if ((CHAR8 *) RelocEnd < (CHAR8 *) ((UINTN) ImageContext->ImageAddress) ||
+ (CHAR8 *) RelocEnd > (CHAR8 *)((UINTN)ImageContext->ImageAddress +
+ (UINTN)ImageContext->ImageSize)) {
+ ImageContext->ImageError = IMAGE_ERROR_FAILED_RELOCATION;
+ return RETURN_LOAD_ERROR;
+ }
+
+ //
+ // Run this relocation record
+ //
+ while (Reloc < RelocEnd) {
+
+ Fixup = FixupBase + (*Reloc & 0xFFF);
+ switch ((*Reloc) >> 12) {
+ case EFI_IMAGE_REL_BASED_ABSOLUTE:
+ break;
+
+ case EFI_IMAGE_REL_BASED_HIGH:
+ F16 = (UINT16 *) Fixup;
+ *F16 = (UINT16) (*F16 + ((UINT16) ((UINT32) Adjust >> 16)));
+ if (FixupData != NULL) {
+ *(UINT16 *) FixupData = *F16;
+ FixupData = FixupData + sizeof (UINT16);
+ }
+ break;
+
+ case EFI_IMAGE_REL_BASED_LOW:
+ F16 = (UINT16 *) Fixup;
+ *F16 = (UINT16) (*F16 + (UINT16) Adjust);
+ if (FixupData != NULL) {
+ *(UINT16 *) FixupData = *F16;
+ FixupData = FixupData + sizeof (UINT16);
+ }
+ break;
+
+ case EFI_IMAGE_REL_BASED_HIGHLOW:
+ F32 = (UINT32 *) Fixup;
+ *F32 = *F32 + (UINT32) Adjust;
+ if (FixupData != NULL) {
+ FixupData = ALIGN_POINTER (FixupData, sizeof (UINT32));
+ *(UINT32 *) FixupData = *F32;
+ FixupData = FixupData + sizeof (UINT32);
+ }
+ break;
+
+ case EFI_IMAGE_REL_BASED_HIGHADJ:
+ //
+ // Return the same EFI_UNSUPPORTED return code as
+ // PeCoffLoaderRelocateImageEx() returns if it does not recognize
+ // the relocation type.
+ //
+ ImageContext->ImageError = IMAGE_ERROR_FAILED_RELOCATION;
+ return RETURN_UNSUPPORTED;
+
+ default:
+ Status = PeCoffLoaderRelocateImageEx (Reloc, Fixup, &FixupData, Adjust);
+ if (RETURN_ERROR (Status)) {
+ ImageContext->ImageError = IMAGE_ERROR_FAILED_RELOCATION;
+ return Status;
+ }
+ }
+
+ //
+ // Next relocation record
+ //
+ Reloc += 1;
+ }
+
+ //
+ // Next reloc block
+ //
+ RelocBase = (EFI_IMAGE_BASE_RELOCATION *) RelocEnd;
+ }
+
+ return RETURN_SUCCESS;
+}
+
+RETURN_STATUS
+EFIAPI
+PeCoffLoaderLoadImage (
+ IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext
+ )
+/*++
+
+Routine Description:
+
+ Loads a PE/COFF image into memory
+
+Arguments:
+
+ This - Calling context
+
+ ImageContext - Contains information on image to load into memory
+
+Returns:
+
+ RETURN_SUCCESS if the PE/COFF image was loaded
+ RETURN_BUFFER_TOO_SMALL if the caller did not provide a large enough buffer
+ RETURN_LOAD_ERROR if the image is a runtime driver with no relocations
+ RETURN_INVALID_PARAMETER if the image address is invalid
+
+--*/
+{
+ RETURN_STATUS Status;
+ EFI_IMAGE_NT_HEADERS *PeHdr;
+ EFI_TE_IMAGE_HEADER *TeHdr;
+ PE_COFF_LOADER_IMAGE_CONTEXT CheckContext;
+ EFI_IMAGE_SECTION_HEADER *FirstSection;
+ EFI_IMAGE_SECTION_HEADER *Section;
+ UINTN NumberOfSections;
+ UINTN Index;
+ CHAR8 *Base;
+ CHAR8 *End;
+ CHAR8 *MaxEnd;
+ EFI_IMAGE_DATA_DIRECTORY *DirectoryEntry;
+ EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *DebugEntry;
+ UINTN Size;
+ UINT32 TempDebugEntryRva;
+
+ PeHdr = NULL;
+ TeHdr = NULL;
+ //
+ // Assume success
+ //
+ ImageContext->ImageError = IMAGE_ERROR_SUCCESS;
+
+ //
+ // Copy the provided context info into our local version, get what we
+ // can from the original image, and then use that to make sure everything
+ // is legit.
+ //
+ CopyMem (&CheckContext, ImageContext, sizeof (PE_COFF_LOADER_IMAGE_CONTEXT));
+
+ Status = PeCoffLoaderGetImageInfo (&CheckContext);
+ if (RETURN_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Make sure there is enough allocated space for the image being loaded
+ //
+ if (ImageContext->ImageSize < CheckContext.ImageSize) {
+ ImageContext->ImageError = IMAGE_ERROR_INVALID_IMAGE_SIZE;
+ return RETURN_BUFFER_TOO_SMALL;
+ }
+
+ //
+ // If there's no relocations, then make sure it's not a runtime driver,
+ // and that it's being loaded at the linked address.
+ //
+ if (CheckContext.RelocationsStripped) {
+ //
+ // If the image does not contain relocations and it is a runtime driver
+ // then return an error.
+ //
+ if (CheckContext.ImageType == EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER) {
+ ImageContext->ImageError = IMAGE_ERROR_INVALID_SUBSYSTEM;
+ return RETURN_LOAD_ERROR;
+ }
+ //
+ // If the image does not contain relocations, and the requested load address
+ // is not the linked address, then return an error.
+ //
+ if (CheckContext.ImageAddress != ImageContext->ImageAddress) {
+ ImageContext->ImageError = IMAGE_ERROR_INVALID_IMAGE_ADDRESS;
+ return RETURN_INVALID_PARAMETER;
+ }
+ }
+ //
+ // Make sure the allocated space has the proper section alignment
+ //
+ if (!(ImageContext->IsTeImage)) {
+ if ((ImageContext->ImageAddress & (CheckContext.SectionAlignment - 1)) != 0) {
+ ImageContext->ImageError = IMAGE_ERROR_INVALID_SECTION_ALIGNMENT;
+ return RETURN_INVALID_PARAMETER;
+ }
+ }
+ //
+ // Read the entire PE/COFF or TE header into memory
+ //
+ if (!(ImageContext->IsTeImage)) {
+ Status = ImageContext->ImageRead (
+ ImageContext->Handle,
+ 0,
+ &ImageContext->SizeOfHeaders,
+ (VOID *) (UINTN) ImageContext->ImageAddress
+ );
+
+ PeHdr = (EFI_IMAGE_NT_HEADERS *)
+ ((UINTN)ImageContext->ImageAddress + ImageContext->PeCoffHeaderOffset);
+
+ FirstSection = (EFI_IMAGE_SECTION_HEADER *) (
+ (UINTN)ImageContext->ImageAddress +
+ ImageContext->PeCoffHeaderOffset +
+ sizeof(UINT32) +
+ sizeof(EFI_IMAGE_FILE_HEADER) +
+ PeHdr->FileHeader.SizeOfOptionalHeader
+ );
+ NumberOfSections = (UINTN) (PeHdr->FileHeader.NumberOfSections);
+ } else {
+ Status = ImageContext->ImageRead (
+ ImageContext->Handle,
+ 0,
+ &ImageContext->SizeOfHeaders,
+ (void *) (UINTN) ImageContext->ImageAddress
+ );
+
+ TeHdr = (EFI_TE_IMAGE_HEADER *) (UINTN) (ImageContext->ImageAddress);
+
+ FirstSection = (EFI_IMAGE_SECTION_HEADER *) (
+ (UINTN)ImageContext->ImageAddress +
+ sizeof(EFI_TE_IMAGE_HEADER)
+ );
+ NumberOfSections = (UINTN) (TeHdr->NumberOfSections);
+
+ }
+
+ if (RETURN_ERROR (Status)) {
+ ImageContext->ImageError = IMAGE_ERROR_IMAGE_READ;
+ return RETURN_LOAD_ERROR;
+ }
+
+ //
+ // Load each section of the image
+ //
+ Section = FirstSection;
+ for (Index = 0, MaxEnd = NULL; Index < NumberOfSections; Index++) {
+
+ //
+ // Compute sections address
+ //
+ Base = PeCoffLoaderImageAddress (ImageContext, Section->VirtualAddress);
+ End = PeCoffLoaderImageAddress (
+ ImageContext,
+ Section->VirtualAddress + Section->Misc.VirtualSize - 1
+ );
+ if (ImageContext->IsTeImage) {
+ Base = (CHAR8 *) ((UINTN) Base + sizeof (EFI_TE_IMAGE_HEADER) - (UINTN) TeHdr->StrippedSize);
+ End = (CHAR8 *) ((UINTN) End + sizeof (EFI_TE_IMAGE_HEADER) - (UINTN) TeHdr->StrippedSize);
+ }
+
+ if (End > MaxEnd) {
+ MaxEnd = End;
+ }
+ //
+ // If the base start or end address resolved to 0, then fail.
+ //
+ if ((Base == NULL) || (End == NULL)) {
+ ImageContext->ImageError = IMAGE_ERROR_SECTION_NOT_LOADED;
+ return RETURN_LOAD_ERROR;
+ }
+
+ //
+ // Read the section
+ //
+ Size = (UINTN) Section->Misc.VirtualSize;
+ if ((Size == 0) || (Size > Section->SizeOfRawData)) {
+ Size = (UINTN) Section->SizeOfRawData;
+ }
+
+ if (Section->SizeOfRawData) {
+ if (!(ImageContext->IsTeImage)) {
+ Status = ImageContext->ImageRead (
+ ImageContext->Handle,
+ Section->PointerToRawData,
+ &Size,
+ Base
+ );
+ } else {
+ Status = ImageContext->ImageRead (
+ ImageContext->Handle,
+ Section->PointerToRawData + sizeof (EFI_TE_IMAGE_HEADER) - (UINTN) TeHdr->StrippedSize,
+ &Size,
+ Base
+ );
+ }
+
+ if (RETURN_ERROR (Status)) {
+ ImageContext->ImageError = IMAGE_ERROR_IMAGE_READ;
+ return Status;
+ }
+ }
+
+ //
+ // If raw size is less then virt size, zero fill the remaining
+ //
+
+ if (Size < Section->Misc.VirtualSize) {
+ ZeroMem (Base + Size, Section->Misc.VirtualSize - Size);
+ }
+
+ //
+ // Next Section
+ //
+ Section += 1;
+ }
+
+ //
+ // Get image's entry point
+ //
+ if (!(ImageContext->IsTeImage)) {
+ ImageContext->EntryPoint = (PHYSICAL_ADDRESS) (UINTN) PeCoffLoaderImageAddress (
+ ImageContext,
+ PeHdr->OptionalHeader.AddressOfEntryPoint
+ );
+ } else {
+ ImageContext->EntryPoint = (PHYSICAL_ADDRESS) (
+ (UINTN)ImageContext->ImageAddress +
+ (UINTN)TeHdr->AddressOfEntryPoint +
+ (UINTN)sizeof(EFI_TE_IMAGE_HEADER) -
+ (UINTN) TeHdr->StrippedSize
+ );
+ }
+
+ //
+ // Determine the size of the fixup data
+ //
+ // Per the PE/COFF spec, you can't assume that a given data directory
+ // is present in the image. You have to check the NumberOfRvaAndSizes in
+ // the optional header to verify a desired directory entry is there.
+ //
+ if (!(ImageContext->IsTeImage)) {
+ if (PeHdr->OptionalHeader.NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) {
+ DirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *)
+ &PeHdr->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC];
+ ImageContext->FixupDataSize = DirectoryEntry->Size / sizeof (UINT16) * sizeof (UINTN);
+ } else {
+ ImageContext->FixupDataSize = 0;
+ }
+ } else {
+ DirectoryEntry = &TeHdr->DataDirectory[0];
+ ImageContext->FixupDataSize = DirectoryEntry->Size / sizeof (UINT16) * sizeof (UINTN);
+ }
+ //
+ // Consumer must allocate a buffer for the relocation fixup log.
+ // Only used for runtime drivers.
+ //
+ ImageContext->FixupData = NULL;
+
+ //
+ // Load the Codeview info if present
+ //
+ if (ImageContext->DebugDirectoryEntryRva != 0) {
+ if (!(ImageContext->IsTeImage)) {
+ DebugEntry = PeCoffLoaderImageAddress (
+ ImageContext,
+ ImageContext->DebugDirectoryEntryRva
+ );
+ } else {
+ DebugEntry = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *)(UINTN)(
+ ImageContext->ImageAddress +
+ ImageContext->DebugDirectoryEntryRva +
+ sizeof(EFI_TE_IMAGE_HEADER) -
+ TeHdr->StrippedSize
+ );
+ }
+
+ if (DebugEntry != NULL) {
+ TempDebugEntryRva = DebugEntry->RVA;
+ if (DebugEntry->RVA == 0 && DebugEntry->FileOffset != 0) {
+ Section--;
+ if ((UINTN) Section->SizeOfRawData < Section->Misc.VirtualSize) {
+ TempDebugEntryRva = Section->VirtualAddress + Section->Misc.VirtualSize;
+ } else {
+ TempDebugEntryRva = Section->VirtualAddress + Section->SizeOfRawData;
+ }
+ }
+
+ if (TempDebugEntryRva != 0) {
+ if (!(ImageContext->IsTeImage)) {
+ ImageContext->CodeView = PeCoffLoaderImageAddress (ImageContext, TempDebugEntryRva);
+ } else {
+ ImageContext->CodeView = (VOID *)(
+ (UINTN)ImageContext->ImageAddress +
+ (UINTN)TempDebugEntryRva +
+ (UINTN)sizeof(EFI_TE_IMAGE_HEADER) -
+ (UINTN) TeHdr->StrippedSize
+ );
+ }
+
+ if (ImageContext->CodeView == NULL) {
+ ImageContext->ImageError = IMAGE_ERROR_IMAGE_READ;
+ return RETURN_LOAD_ERROR;
+ }
+
+ if (DebugEntry->RVA == 0) {
+ Size = DebugEntry->SizeOfData;
+ if (!(ImageContext->IsTeImage)) {
+ Status = ImageContext->ImageRead (
+ ImageContext->Handle,
+ DebugEntry->FileOffset,
+ &Size,
+ ImageContext->CodeView
+ );
+ } else {
+ Status = ImageContext->ImageRead (
+ ImageContext->Handle,
+ DebugEntry->FileOffset + sizeof (EFI_TE_IMAGE_HEADER) - TeHdr->StrippedSize,
+ &Size,
+ ImageContext->CodeView
+ );
+ //
+ // Should we apply fix up to this field according to the size difference between PE and TE?
+ // Because now we maintain TE header fields unfixed, this field will also remain as they are
+ // in original PE image.
+ //
+ }
+
+ if (RETURN_ERROR (Status)) {
+ ImageContext->ImageError = IMAGE_ERROR_IMAGE_READ;
+ return RETURN_LOAD_ERROR;
+ }
+
+ DebugEntry->RVA = TempDebugEntryRva;
+ }
+
+ switch (*(UINT32 *) ImageContext->CodeView) {
+ case CODEVIEW_SIGNATURE_NB10:
+ ImageContext->PdbPointer = (CHAR8 *) ImageContext->CodeView + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY);
+ break;
+
+ case CODEVIEW_SIGNATURE_RSDS:
+ ImageContext->PdbPointer = (CHAR8 *) ImageContext->CodeView + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY);
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+ }
+
+ return Status;
+}
diff --git a/Source/PeCoffLoader/Common/EfiImage.h b/Source/PeCoffLoader/Common/EfiImage.h
new file mode 100644
index 0000000..9528e6b
--- /dev/null
+++ b/Source/PeCoffLoader/Common/EfiImage.h
@@ -0,0 +1,701 @@
+/** @file
+ EFI image format for PE32+. Please note some data structures are different
+ for IA-32 and Itanium-based images, look for UINTN and the #ifdef EFI_IA64
+
+ @bug Fix text - doc as defined in MSFT EFI specification.
+
+ Copyright (c) 2006, Intel Corporation
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+ Module Name: EfiImage.h
+
+**/
+
+#ifndef __EFI_IMAGE_H__
+#define __EFI_IMAGE_H__
+
+//
+// PE32+ Subsystem type for EFI images
+//
+#define EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION 10
+#define EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER 11
+#define EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER 12
+#define EFI_IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER 13
+
+//
+// BugBug: Need to get a real answer for this problem. This is not in the
+// PE specification.
+//
+// A SAL runtime driver does not get fixed up when a transition to
+// virtual mode is made. In all other cases it should be treated
+// like a EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER image
+//
+#define EFI_IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER 13
+
+//
+// PE32+ Machine type for EFI images
+//
+#define IMAGE_FILE_MACHINE_I386 0x014c
+#define IMAGE_FILE_MACHINE_IA64 0x0200
+#define IMAGE_FILE_MACHINE_EBC 0x0EBC
+#define IMAGE_FILE_MACHINE_X64 0x8664
+//
+// Support old names for backward compatible
+//
+#define EFI_IMAGE_MACHINE_IA32 IMAGE_FILE_MACHINE_I386
+#define EFI_IMAGE_MACHINE_IA64 IMAGE_FILE_MACHINE_IA64
+#define EFI_IMAGE_MACHINE_IPF IMAGE_FILE_MACHINE_IA64
+#define EFI_IMAGE_MACHINE_EBC IMAGE_FILE_MACHINE_EBC
+#define EFI_IMAGE_MACHINE_X64 IMAGE_FILE_MACHINE_X64
+
+#define EFI_IMAGE_DOS_SIGNATURE 0x5A4D // MZ
+#define EFI_IMAGE_OS2_SIGNATURE 0x454E // NE
+#define EFI_IMAGE_OS2_SIGNATURE_LE 0x454C // LE
+#define EFI_IMAGE_NT_SIGNATURE 0x00004550 // PE00
+#define EFI_IMAGE_EDOS_SIGNATURE 0x44454550 // PEED
+
+///
+/// PE images can start with an optional DOS header, so if an image is run
+/// under DOS it can print an error message.
+///
+typedef struct {
+ UINT16 e_magic; // Magic number
+ UINT16 e_cblp; // Bytes on last page of file
+ UINT16 e_cp; // Pages in file
+ UINT16 e_crlc; // Relocations
+ UINT16 e_cparhdr; // Size of header in paragraphs
+ UINT16 e_minalloc; // Minimum extra paragraphs needed
+ UINT16 e_maxalloc; // Maximum extra paragraphs needed
+ UINT16 e_ss; // Initial (relative) SS value
+ UINT16 e_sp; // Initial SP value
+ UINT16 e_csum; // Checksum
+ UINT16 e_ip; // Initial IP value
+ UINT16 e_cs; // Initial (relative) CS value
+ UINT16 e_lfarlc; // File address of relocation table
+ UINT16 e_ovno; // Overlay number
+ UINT16 e_res[4]; // Reserved words
+ UINT16 e_oemid; // OEM identifier (for e_oeminfo)
+ UINT16 e_oeminfo; // OEM information; e_oemid specific
+ UINT16 e_res2[10]; // Reserved words
+ UINT32 e_lfanew; // File address of new exe header
+} EFI_IMAGE_DOS_HEADER;
+
+///
+/// File header format.
+///
+typedef struct {
+ UINT16 Machine;
+ UINT16 NumberOfSections;
+ UINT32 TimeDateStamp;
+ UINT32 PointerToSymbolTable;
+ UINT32 NumberOfSymbols;
+ UINT16 SizeOfOptionalHeader;
+ UINT16 Characteristics;
+} EFI_IMAGE_FILE_HEADER;
+
+#define EFI_IMAGE_SIZEOF_FILE_HEADER 20
+
+#define EFI_IMAGE_FILE_RELOCS_STRIPPED 0x0001 // Relocation info stripped from file.
+#define EFI_IMAGE_FILE_EXECUTABLE_IMAGE 0x0002 // File is executable (i.e. no unresolved externel references).
+#define EFI_IMAGE_FILE_LINE_NUMS_STRIPPED 0x0004 // Line nunbers stripped from file.
+#define EFI_IMAGE_FILE_LOCAL_SYMS_STRIPPED 0x0008 // Local symbols stripped from file.
+#define EFI_IMAGE_FILE_BYTES_REVERSED_LO 0x0080 // Bytes of machine word are reversed.
+#define EFI_IMAGE_FILE_32BIT_MACHINE 0x0100 // 32 bit word machine.
+#define EFI_IMAGE_FILE_DEBUG_STRIPPED 0x0200 // Debugging info stripped from file in .DBG file
+#define EFI_IMAGE_FILE_SYSTEM 0x1000 // System File.
+#define EFI_IMAGE_FILE_DLL 0x2000 // File is a DLL.
+#define EFI_IMAGE_FILE_BYTES_REVERSED_HI 0x8000 // Bytes of machine word are reversed.
+#define EFI_IMAGE_FILE_MACHINE_UNKNOWN 0
+#define EFI_IMAGE_FILE_MACHINE_I386 0x14c // Intel 386.
+#define EFI_IMAGE_FILE_MACHINE_R3000 0x162 // MIPS* little-endian, 0540 big-endian
+#define EFI_IMAGE_FILE_MACHINE_R4000 0x166 // MIPS* little-endian
+#define EFI_IMAGE_FILE_MACHINE_ALPHA 0x184 // Alpha_AXP*
+#define EFI_IMAGE_FILE_MACHINE_POWERPC 0x1F0 // IBM* PowerPC Little-Endian
+#define EFI_IMAGE_FILE_MACHINE_TAHOE 0x7cc // Intel EM machine
+//
+// * Other names and brands may be claimed as the property of others.
+//
+
+///
+/// Directory format.
+///
+typedef struct {
+ UINT32 VirtualAddress;
+ UINT32 Size;
+} EFI_IMAGE_DATA_DIRECTORY;
+
+#define EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES 16
+
+typedef struct {
+ UINT16 Magic;
+ UINT8 MajorLinkerVersion;
+ UINT8 MinorLinkerVersion;
+ UINT32 SizeOfCode;
+ UINT32 SizeOfInitializedData;
+ UINT32 SizeOfUninitializedData;
+ UINT32 AddressOfEntryPoint;
+ UINT32 BaseOfCode;
+ UINT32 BaseOfData;
+ UINT32 BaseOfBss;
+ UINT32 GprMask;
+ UINT32 CprMask[4];
+ UINT32 GpValue;
+} EFI_IMAGE_ROM_OPTIONAL_HEADER;
+
+#define EFI_IMAGE_ROM_OPTIONAL_HDR_MAGIC 0x107
+#define EFI_IMAGE_SIZEOF_ROM_OPTIONAL_HEADER sizeof (EFI_IMAGE_ROM_OPTIONAL_HEADER)
+
+typedef struct {
+ EFI_IMAGE_FILE_HEADER FileHeader;
+ EFI_IMAGE_ROM_OPTIONAL_HEADER OptionalHeader;
+} EFI_IMAGE_ROM_HEADERS;
+
+///
+/// @attention
+/// EFI_IMAGE_OPTIONAL_HEADER32 and EFI_IMAGE_OPTIONAL_HEADER64
+/// are for use ONLY by tools. All proper EFI code MUST use
+/// EFI_IMAGE_OPTIONAL_HEADER ONLY!!!
+///
+#define EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC 0x10b
+
+typedef struct {
+ //
+ // Standard fields.
+ //
+ UINT16 Magic;
+ UINT8 MajorLinkerVersion;
+ UINT8 MinorLinkerVersion;
+ UINT32 SizeOfCode;
+ UINT32 SizeOfInitializedData;
+ UINT32 SizeOfUninitializedData;
+ UINT32 AddressOfEntryPoint;
+ UINT32 BaseOfCode;
+ UINT32 BaseOfData;
+ //
+ // NT additional fields.
+ //
+ UINT32 ImageBase;
+ UINT32 SectionAlignment;
+ UINT32 FileAlignment;
+ UINT16 MajorOperatingSystemVersion;
+ UINT16 MinorOperatingSystemVersion;
+ UINT16 MajorImageVersion;
+ UINT16 MinorImageVersion;
+ UINT16 MajorSubsystemVersion;
+ UINT16 MinorSubsystemVersion;
+ UINT32 Win32VersionValue;
+ UINT32 SizeOfImage;
+ UINT32 SizeOfHeaders;
+ UINT32 CheckSum;
+ UINT16 Subsystem;
+ UINT16 DllCharacteristics;
+ UINT32 SizeOfStackReserve;
+ UINT32 SizeOfStackCommit;
+ UINT32 SizeOfHeapReserve;
+ UINT32 SizeOfHeapCommit;
+ UINT32 LoaderFlags;
+ UINT32 NumberOfRvaAndSizes;
+ EFI_IMAGE_DATA_DIRECTORY DataDirectory[EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES];
+} EFI_IMAGE_OPTIONAL_HEADER32;
+
+///
+/// @attention
+/// EFI_IMAGE_OPTIONAL_HEADER32 and EFI_IMAGE_OPTIONAL_HEADER64
+/// are for use ONLY by tools. All proper EFI code MUST use
+/// EFI_IMAGE_OPTIONAL_HEADER ONLY!!!
+///
+#define EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC 0x20b
+
+typedef struct {
+ //
+ // Standard fields.
+ //
+ UINT16 Magic;
+ UINT8 MajorLinkerVersion;
+ UINT8 MinorLinkerVersion;
+ UINT32 SizeOfCode;
+ UINT32 SizeOfInitializedData;
+ UINT32 SizeOfUninitializedData;
+ UINT32 AddressOfEntryPoint;
+ UINT32 BaseOfCode;
+ //
+ // NT additional fields.
+ //
+ UINT64 ImageBase;
+ UINT32 SectionAlignment;
+ UINT32 FileAlignment;
+ UINT16 MajorOperatingSystemVersion;
+ UINT16 MinorOperatingSystemVersion;
+ UINT16 MajorImageVersion;
+ UINT16 MinorImageVersion;
+ UINT16 MajorSubsystemVersion;
+ UINT16 MinorSubsystemVersion;
+ UINT32 Win32VersionValue;
+ UINT32 SizeOfImage;
+ UINT32 SizeOfHeaders;
+ UINT32 CheckSum;
+ UINT16 Subsystem;
+ UINT16 DllCharacteristics;
+ UINT64 SizeOfStackReserve;
+ UINT64 SizeOfStackCommit;
+ UINT64 SizeOfHeapReserve;
+ UINT64 SizeOfHeapCommit;
+ UINT32 LoaderFlags;
+ UINT32 NumberOfRvaAndSizes;
+ EFI_IMAGE_DATA_DIRECTORY DataDirectory[EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES];
+} EFI_IMAGE_OPTIONAL_HEADER64;
+
+///
+/// @attention
+/// EFI_IMAGE_NT_HEADERS32 and EFI_IMAGE_HEADERS64 are for use ONLY
+/// by tools. All proper EFI code MUST use EFI_IMAGE_NT_HEADERS ONLY!!!
+///
+typedef struct {
+ UINT32 Signature;
+ EFI_IMAGE_FILE_HEADER FileHeader;
+ EFI_IMAGE_OPTIONAL_HEADER32 OptionalHeader;
+} EFI_IMAGE_NT_HEADERS32;
+
+#define EFI_IMAGE_SIZEOF_NT_OPTIONAL32_HEADER sizeof (EFI_IMAGE_NT_HEADERS32)
+
+typedef struct {
+ UINT32 Signature;
+ EFI_IMAGE_FILE_HEADER FileHeader;
+ EFI_IMAGE_OPTIONAL_HEADER64 OptionalHeader;
+} EFI_IMAGE_NT_HEADERS64;
+
+#define EFI_IMAGE_SIZEOF_NT_OPTIONAL64_HEADER sizeof (EFI_IMAGE_NT_HEADERS64)
+
+//
+// Processor specific definition of EFI_IMAGE_OPTIONAL_HEADER so the
+// type name EFI_IMAGE_OPTIONAL_HEADER is appropriate to the build. Same for
+// EFI_IMAGE_NT_HEADERS. These definitions MUST be used by ALL EFI code.
+//
+#if defined (MDE_CPU_IA32) && !defined (BUILDING_TOOLS) || \
+ defined (BUILDING_TOOLS) && defined (TOOL_BUILD_IA32_TARGET)
+
+// typedef EFI_IMAGE_OPTIONAL_HEADER32 EFI_IMAGE_OPTIONAL_HEADER;
+typedef EFI_IMAGE_NT_HEADERS32 EFI_IMAGE_NT_HEADERS;
+
+#define EFI_IMAGE_NT_OPTIONAL_HDR_MAGIC EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
+#define EFI_IMAGE_MACHINE_TYPE_SUPPORTED(Machine) \
+ (((Machine) == EFI_IMAGE_MACHINE_IA32) || ((Machine) == EFI_IMAGE_MACHINE_EBC))
+
+#elif defined (MDE_CPU_IPF) && !defined (BUILDING_TOOLS) || \
+ defined (BUILDING_TOOLS) && defined (TOOL_BUILD_IPF_TARGET)
+
+typedef EFI_IMAGE_OPTIONAL_HEADER64 EFI_IMAGE_OPTIONAL_HEADER;
+typedef EFI_IMAGE_NT_HEADERS64 EFI_IMAGE_NT_HEADERS;
+
+#define EFI_IMAGE_NT_OPTIONAL_HDR_MAGIC EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
+#define EFI_IMAGE_MACHINE_TYPE_SUPPORTED(Machine) \
+ (((Machine) == EFI_IMAGE_MACHINE_IPF) || ((Machine) == EFI_IMAGE_MACHINE_EBC))
+
+#elif defined (MDE_CPU_X64) && !defined (BUILDING_TOOLS) || \
+ defined (BUILDING_TOOLS) && defined (TOOL_BUILD_X64_TARGET)
+
+typedef EFI_IMAGE_OPTIONAL_HEADER64 EFI_IMAGE_OPTIONAL_HEADER;
+typedef EFI_IMAGE_NT_HEADERS64 EFI_IMAGE_NT_HEADERS;
+
+#define EFI_IMAGE_NT_OPTIONAL_HDR_MAGIC EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
+#define EFI_IMAGE_MACHINE_TYPE_SUPPORTED(Machine) \
+ (((Machine) == EFI_IMAGE_MACHINE_X64) || ((Machine) == EFI_IMAGE_MACHINE_EBC))
+
+#elif defined (MDE_CPU_EBC)
+
+//
+// This is just to make sure you can cross compile with the EBC compiiler.
+// It does not make sense to have a PE loader coded in EBC. You need to
+// understand the basic
+//
+typedef EFI_IMAGE_OPTIONAL_HEADER64 EFI_IMAGE_OPTIONAL_HEADER;
+typedef EFI_IMAGE_NT_HEADERS64 EFI_IMAGE_NT_HEADERS;
+
+#define EFI_IMAGE_NT_OPTIONAL_HDR_MAGIC EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
+#define EFI_IMAGE_MACHINE_TYPE_SUPPORTED(Machine) ((Machine) == EFI_IMAGE_MACHINE_EBC)
+
+#else
+#error Unknown Processor Type
+#endif
+
+
+#define EFI_IMAGE_FIRST_SECTION(ntheader) \
+ ( \
+ (EFI_IMAGE_SECTION_HEADER *) \
+ ( \
+ (UINT32) ntheader + \
+ FIELD_OFFSET (EFI_IMAGE_NT_HEADERS, OptionalHeader) + \
+ ((EFI_IMAGE_NT_HEADERS *) (ntheader))->FileHeader.SizeOfOptionalHeader \
+ ) \
+ )
+
+//
+// Subsystem Values
+//
+#define EFI_IMAGE_SUBSYSTEM_UNKNOWN 0
+#define EFI_IMAGE_SUBSYSTEM_NATIVE 1
+#define EFI_IMAGE_SUBSYSTEM_WINDOWS_GUI 2
+#define EFI_IMAGE_SUBSYSTEM_WINDOWS_CUI 3.
+#define EFI_IMAGE_SUBSYSTEM_OS2_CUI 5
+#define EFI_IMAGE_SUBSYSTEM_POSIX_CUI 7
+
+//
+// Directory Entries
+//
+#define EFI_IMAGE_DIRECTORY_ENTRY_EXPORT 0
+#define EFI_IMAGE_DIRECTORY_ENTRY_IMPORT 1
+#define EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE 2
+#define EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION 3
+#define EFI_IMAGE_DIRECTORY_ENTRY_SECURITY 4
+#define EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC 5
+#define EFI_IMAGE_DIRECTORY_ENTRY_DEBUG 6
+#define EFI_IMAGE_DIRECTORY_ENTRY_COPYRIGHT 7
+#define EFI_IMAGE_DIRECTORY_ENTRY_GLOBALPTR 8
+#define EFI_IMAGE_DIRECTORY_ENTRY_TLS 9
+#define EFI_IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG 10
+
+//
+// Section header format.
+//
+#define EFI_IMAGE_SIZEOF_SHORT_NAME 8
+
+typedef struct {
+ UINT8 Name[EFI_IMAGE_SIZEOF_SHORT_NAME];
+ union {
+ UINT32 PhysicalAddress;
+ UINT32 VirtualSize;
+ } Misc;
+ UINT32 VirtualAddress;
+ UINT32 SizeOfRawData;
+ UINT32 PointerToRawData;
+ UINT32 PointerToRelocations;
+ UINT32 PointerToLinenumbers;
+ UINT16 NumberOfRelocations;
+ UINT16 NumberOfLinenumbers;
+ UINT32 Characteristics;
+} EFI_IMAGE_SECTION_HEADER;
+
+#define EFI_IMAGE_SIZEOF_SECTION_HEADER 40
+
+#define EFI_IMAGE_SCN_TYPE_NO_PAD 0x00000008 // Reserved.
+#define EFI_IMAGE_SCN_CNT_CODE 0x00000020
+#define EFI_IMAGE_SCN_CNT_INITIALIZED_DATA 0x00000040
+#define EFI_IMAGE_SCN_CNT_UNINITIALIZED_DATA 0x00000080
+
+#define EFI_IMAGE_SCN_LNK_OTHER 0x00000100 // Reserved.
+#define EFI_IMAGE_SCN_LNK_INFO 0x00000200 // Section contains comments or some other type of information.
+#define EFI_IMAGE_SCN_LNK_REMOVE 0x00000800 // Section contents will not become part of image.
+#define EFI_IMAGE_SCN_LNK_COMDAT 0x00001000
+
+#define EFI_IMAGE_SCN_ALIGN_1BYTES 0x00100000
+#define EFI_IMAGE_SCN_ALIGN_2BYTES 0x00200000
+#define EFI_IMAGE_SCN_ALIGN_4BYTES 0x00300000
+#define EFI_IMAGE_SCN_ALIGN_8BYTES 0x00400000
+#define EFI_IMAGE_SCN_ALIGN_16BYTES 0x00500000
+#define EFI_IMAGE_SCN_ALIGN_32BYTES 0x00600000
+#define EFI_IMAGE_SCN_ALIGN_64BYTES 0x00700000
+
+#define EFI_IMAGE_SCN_MEM_DISCARDABLE 0x02000000
+#define EFI_IMAGE_SCN_MEM_NOT_CACHED 0x04000000
+#define EFI_IMAGE_SCN_MEM_NOT_PAGED 0x08000000
+#define EFI_IMAGE_SCN_MEM_SHARED 0x10000000
+#define EFI_IMAGE_SCN_MEM_EXECUTE 0x20000000
+#define EFI_IMAGE_SCN_MEM_READ 0x40000000
+#define EFI_IMAGE_SCN_MEM_WRITE 0x80000000
+
+///
+/// Symbol format.
+///
+#define EFI_IMAGE_SIZEOF_SYMBOL 18
+
+//
+// Section values.
+//
+// Symbols have a section number of the section in which they are
+// defined. Otherwise, section numbers have the following meanings:
+//
+#define EFI_IMAGE_SYM_UNDEFINED (UINT16) 0 // Symbol is undefined or is common.
+#define EFI_IMAGE_SYM_ABSOLUTE (UINT16) -1 // Symbol is an absolute value.
+#define EFI_IMAGE_SYM_DEBUG (UINT16) -2 // Symbol is a special debug item.
+//
+// Type (fundamental) values.
+//
+#define EFI_IMAGE_SYM_TYPE_NULL 0 // no type.
+#define EFI_IMAGE_SYM_TYPE_VOID 1 //
+#define EFI_IMAGE_SYM_TYPE_CHAR 2 // type character.
+#define EFI_IMAGE_SYM_TYPE_SHORT 3 // type short integer.
+#define EFI_IMAGE_SYM_TYPE_INT 4
+#define EFI_IMAGE_SYM_TYPE_LONG 5
+#define EFI_IMAGE_SYM_TYPE_FLOAT 6
+#define EFI_IMAGE_SYM_TYPE_DOUBLE 7
+#define EFI_IMAGE_SYM_TYPE_STRUCT 8
+#define EFI_IMAGE_SYM_TYPE_UNION 9
+#define EFI_IMAGE_SYM_TYPE_ENUM 10 // enumeration.
+#define EFI_IMAGE_SYM_TYPE_MOE 11 // member of enumeration.
+#define EFI_IMAGE_SYM_TYPE_BYTE 12
+#define EFI_IMAGE_SYM_TYPE_WORD 13
+#define EFI_IMAGE_SYM_TYPE_UINT 14
+#define EFI_IMAGE_SYM_TYPE_DWORD 15
+
+//
+// Type (derived) values.
+//
+#define EFI_IMAGE_SYM_DTYPE_NULL 0 // no derived type.
+#define EFI_IMAGE_SYM_DTYPE_POINTER 1
+#define EFI_IMAGE_SYM_DTYPE_FUNCTION 2
+#define EFI_IMAGE_SYM_DTYPE_ARRAY 3
+
+//
+// Storage classes.
+//
+#define EFI_IMAGE_SYM_CLASS_END_OF_FUNCTION (UINT8) -1
+#define EFI_IMAGE_SYM_CLASS_NULL 0
+#define EFI_IMAGE_SYM_CLASS_AUTOMATIC 1
+#define EFI_IMAGE_SYM_CLASS_EXTERNAL 2
+#define EFI_IMAGE_SYM_CLASS_STATIC 3
+#define EFI_IMAGE_SYM_CLASS_REGISTER 4
+#define EFI_IMAGE_SYM_CLASS_EXTERNAL_DEF 5
+#define EFI_IMAGE_SYM_CLASS_LABEL 6
+#define EFI_IMAGE_SYM_CLASS_UNDEFINED_LABEL 7
+#define EFI_IMAGE_SYM_CLASS_MEMBER_OF_STRUCT 8
+#define EFI_IMAGE_SYM_CLASS_ARGUMENT 9
+#define EFI_IMAGE_SYM_CLASS_STRUCT_TAG 10
+#define EFI_IMAGE_SYM_CLASS_MEMBER_OF_UNION 11
+#define EFI_IMAGE_SYM_CLASS_UNION_TAG 12
+#define EFI_IMAGE_SYM_CLASS_TYPE_DEFINITION 13
+#define EFI_IMAGE_SYM_CLASS_UNDEFINED_STATIC 14
+#define EFI_IMAGE_SYM_CLASS_ENUM_TAG 15
+#define EFI_IMAGE_SYM_CLASS_MEMBER_OF_ENUM 16
+#define EFI_IMAGE_SYM_CLASS_REGISTER_PARAM 17
+#define EFI_IMAGE_SYM_CLASS_BIT_FIELD 18
+#define EFI_IMAGE_SYM_CLASS_BLOCK 100
+#define EFI_IMAGE_SYM_CLASS_FUNCTION 101
+#define EFI_IMAGE_SYM_CLASS_END_OF_STRUCT 102
+#define EFI_IMAGE_SYM_CLASS_FILE 103
+#define EFI_IMAGE_SYM_CLASS_SECTION 104
+#define EFI_IMAGE_SYM_CLASS_WEAK_EXTERNAL 105
+
+//
+// type packing constants
+//
+#define EFI_IMAGE_N_BTMASK 017
+#define EFI_IMAGE_N_TMASK 060
+#define EFI_IMAGE_N_TMASK1 0300
+#define EFI_IMAGE_N_TMASK2 0360
+#define EFI_IMAGE_N_BTSHFT 4
+#define EFI_IMAGE_N_TSHIFT 2
+
+//
+// Communal selection types.
+//
+#define EFI_IMAGE_COMDAT_SELECT_NODUPLICATES 1
+#define EFI_IMAGE_COMDAT_SELECT_ANY 2
+#define EFI_IMAGE_COMDAT_SELECT_SAME_SIZE 3
+#define EFI_IMAGE_COMDAT_SELECT_EXACT_MATCH 4
+#define EFI_IMAGE_COMDAT_SELECT_ASSOCIATIVE 5
+
+#define EFI_IMAGE_WEAK_EXTERN_SEARCH_NOLIBRARY 1
+#define EFI_IMAGE_WEAK_EXTERN_SEARCH_LIBRARY 2
+#define EFI_IMAGE_WEAK_EXTERN_SEARCH_ALIAS 3
+
+///
+/// Relocation format.
+///
+typedef struct {
+ UINT32 VirtualAddress;
+ UINT32 SymbolTableIndex;
+ UINT16 Type;
+} EFI_IMAGE_RELOCATION;
+
+#define EFI_IMAGE_SIZEOF_RELOCATION 10
+
+//
+// I386 relocation types.
+//
+#define EFI_IMAGE_REL_I386_ABSOLUTE 0 // Reference is absolute, no relocation is necessary
+#define EFI_IMAGE_REL_I386_DIR16 01 // Direct 16-bit reference to the symbols virtual address
+#define EFI_IMAGE_REL_I386_REL16 02 // PC-relative 16-bit reference to the symbols virtual address
+#define EFI_IMAGE_REL_I386_DIR32 06 // Direct 32-bit reference to the symbols virtual address
+#define EFI_IMAGE_REL_I386_DIR32NB 07 // Direct 32-bit reference to the symbols virtual address, base not included
+#define EFI_IMAGE_REL_I386_SEG12 011 // Direct 16-bit reference to the segment-selector bits of a 32-bit virtual address
+#define EFI_IMAGE_REL_I386_SECTION 012
+#define EFI_IMAGE_REL_I386_SECREL 013
+#define EFI_IMAGE_REL_I386_REL32 024 // PC-relative 32-bit reference to the symbols virtual address
+
+///
+/// Based relocation format.
+///
+typedef struct {
+ UINT32 VirtualAddress;
+ UINT32 SizeOfBlock;
+} EFI_IMAGE_BASE_RELOCATION;
+
+#define EFI_IMAGE_SIZEOF_BASE_RELOCATION 8
+
+//
+// Based relocation types.
+//
+#define EFI_IMAGE_REL_BASED_ABSOLUTE 0
+#define EFI_IMAGE_REL_BASED_HIGH 1
+#define EFI_IMAGE_REL_BASED_LOW 2
+#define EFI_IMAGE_REL_BASED_HIGHLOW 3
+#define EFI_IMAGE_REL_BASED_HIGHADJ 4
+#define EFI_IMAGE_REL_BASED_MIPS_JMPADDR 5
+#define EFI_IMAGE_REL_BASED_IA64_IMM64 9
+#define EFI_IMAGE_REL_BASED_DIR64 10
+
+///
+/// Line number format.
+///
+typedef struct {
+ union {
+ UINT32 SymbolTableIndex; // Symbol table index of function name if Linenumber is 0.
+ UINT32 VirtualAddress; // Virtual address of line number.
+ } Type;
+ UINT16 Linenumber; // Line number.
+} EFI_IMAGE_LINENUMBER;
+
+#define EFI_IMAGE_SIZEOF_LINENUMBER 6
+
+//
+// Archive format.
+//
+#define EFI_IMAGE_ARCHIVE_START_SIZE 8
+#define EFI_IMAGE_ARCHIVE_START "!<arch>\n"
+#define EFI_IMAGE_ARCHIVE_END "`\n"
+#define EFI_IMAGE_ARCHIVE_PAD "\n"
+#define EFI_IMAGE_ARCHIVE_LINKER_MEMBER "/ "
+#define EFI_IMAGE_ARCHIVE_LONGNAMES_MEMBER "// "
+
+typedef struct {
+ UINT8 Name[16]; // File member name - `/' terminated.
+ UINT8 Date[12]; // File member date - decimal.
+ UINT8 UserID[6]; // File member user id - decimal.
+ UINT8 GroupID[6]; // File member group id - decimal.
+ UINT8 Mode[8]; // File member mode - octal.
+ UINT8 Size[10]; // File member size - decimal.
+ UINT8 EndHeader[2]; // String to end header.
+} EFI_IMAGE_ARCHIVE_MEMBER_HEADER;
+
+#define EFI_IMAGE_SIZEOF_ARCHIVE_MEMBER_HDR 60
+
+//
+// DLL support.
+//
+
+///
+/// DLL Export Format
+///
+typedef struct {
+ UINT32 Characteristics;
+ UINT32 TimeDateStamp;
+ UINT16 MajorVersion;
+ UINT16 MinorVersion;
+ UINT32 Name;
+ UINT32 Base;
+ UINT32 NumberOfFunctions;
+ UINT32 NumberOfNames;
+ UINT32 AddressOfFunctions;
+ UINT32 AddressOfNames;
+ UINT32 AddressOfNameOrdinals;
+} EFI_IMAGE_EXPORT_DIRECTORY;
+
+///
+/// DLL support.
+/// Import Format
+///
+typedef struct {
+ UINT16 Hint;
+ UINT8 Name[1];
+} EFI_IMAGE_IMPORT_BY_NAME;
+
+typedef struct {
+ union {
+ UINT32 Function;
+ UINT32 Ordinal;
+ EFI_IMAGE_IMPORT_BY_NAME *AddressOfData;
+ } u1;
+} EFI_IMAGE_THUNK_DATA;
+
+#define EFI_IMAGE_ORDINAL_FLAG 0x80000000
+#define EFI_IMAGE_SNAP_BY_ORDINAL(Ordinal) ((Ordinal & EFI_IMAGE_ORDINAL_FLAG) != 0)
+#define EFI_IMAGE_ORDINAL(Ordinal) (Ordinal & 0xffff)
+
+typedef struct {
+ UINT32 Characteristics;
+ UINT32 TimeDateStamp;
+ UINT32 ForwarderChain;
+ UINT32 Name;
+ EFI_IMAGE_THUNK_DATA *FirstThunk;
+} EFI_IMAGE_IMPORT_DESCRIPTOR;
+
+///
+/// Debug Format
+///
+#define EFI_IMAGE_DEBUG_TYPE_CODEVIEW 2
+
+typedef struct {
+ UINT32 Characteristics;
+ UINT32 TimeDateStamp;
+ UINT16 MajorVersion;
+ UINT16 MinorVersion;
+ UINT32 Type;
+ UINT32 SizeOfData;
+ UINT32 RVA;
+ UINT32 FileOffset;
+} EFI_IMAGE_DEBUG_DIRECTORY_ENTRY;
+
+#define CODEVIEW_SIGNATURE_NB10 0x3031424E // "NB10"
+typedef struct {
+ UINT32 Signature; // "NB10"
+ UINT32 Unknown;
+ UINT32 Unknown2;
+ UINT32 Unknown3;
+ //
+ // Filename of .PDB goes here
+ //
+} EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY;
+
+#define CODEVIEW_SIGNATURE_RSDS 0x53445352 // "RSDS"
+typedef struct {
+ UINT32 Signature; // "RSDS"
+ UINT32 Unknown;
+ UINT32 Unknown2;
+ UINT32 Unknown3;
+ UINT32 Unknown4;
+ UINT32 Unknown5;
+ //
+ // Filename of .PDB goes here
+ //
+} EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY;
+
+///
+/// Header format for TE images
+///
+typedef struct {
+ UINT16 Signature; // signature for TE format = "VZ"
+ UINT16 Machine; // from the original file header
+ UINT8 NumberOfSections; // from the original file header
+ UINT8 Subsystem; // from original optional header
+ UINT16 StrippedSize; // how many bytes we removed from the header
+ UINT32 AddressOfEntryPoint; // offset to entry point -- from original optional header
+ UINT32 BaseOfCode; // from original image -- required for ITP debug
+ UINT64 ImageBase; // from original file header
+ EFI_IMAGE_DATA_DIRECTORY DataDirectory[2]; // only base relocation and debug directory
+} EFI_TE_IMAGE_HEADER;
+
+#define EFI_TE_IMAGE_HEADER_SIGNATURE 0x5A56 // "VZ"
+
+//
+// Data directory indexes in our TE image header
+//
+#define EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC 0
+#define EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG 1
+
+#endif
diff --git a/Source/PeCoffLoader/Ia32/PeCoffLoaderEx.c b/Source/PeCoffLoader/Ia32/PeCoffLoaderEx.c
new file mode 100644
index 0000000..f58e8d0
--- /dev/null
+++ b/Source/PeCoffLoader/Ia32/PeCoffLoaderEx.c
@@ -0,0 +1,56 @@
+/*++
+
+Copyright (c) 2004, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ PeCoffLoaderEx.c
+
+Abstract:
+
+ IA-32 Specific relocation fixups
+
+Revision History
+
+--*/
+
+#include <Common/UefiBaseTypes.h>
+
+RETURN_STATUS
+PeCoffLoaderRelocateImageEx (
+ IN UINT16 *Reloc,
+ IN OUT CHAR8 *Fixup,
+ IN OUT CHAR8 **FixupData,
+ IN UINT64 Adjust
+ )
+/*++
+
+Routine Description:
+
+ Performs an IA-32 specific relocation fixup
+
+Arguments:
+
+ Reloc - Pointer to the relocation record
+
+ Fixup - Pointer to the address to fix up
+
+ FixupData - Pointer to a buffer to log the fixups
+
+ Adjust - The offset to adjust the fixup
+
+Returns:
+
+ EFI_UNSUPPORTED - Unsupported now
+
+--*/
+{
+ return RETURN_UNSUPPORTED;
+}
diff --git a/Source/PeCoffLoader/Ipf/PeCoffLoaderEx.c b/Source/PeCoffLoader/Ipf/PeCoffLoaderEx.c
new file mode 100644
index 0000000..3f39899
--- /dev/null
+++ b/Source/PeCoffLoader/Ipf/PeCoffLoaderEx.c
@@ -0,0 +1,249 @@
+/*++
+
+Copyright (c) 2004, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ PeCoffLoaderEx.c
+
+Abstract:
+
+ Fixes Intel Itanium(TM) specific relocation types
+
+
+Revision History
+
+--*/
+
+#include <Common/UefiBaseTypes.h>
+#include <Common/EfiImage.h>
+#include <Library/PeCoffLib.h>
+
+
+
+
+
+#define EXT_IMM64(Value, Address, Size, InstPos, ValPos) \
+ Value |= (((UINT64)((*(Address) >> InstPos) & (((UINT64)1 << Size) - 1))) << ValPos)
+
+#define INS_IMM64(Value, Address, Size, InstPos, ValPos) \
+ *(UINT32*)Address = (*(UINT32*)Address & ~(((1 << Size) - 1) << InstPos)) | \
+ ((UINT32)((((UINT64)Value >> ValPos) & (((UINT64)1 << Size) - 1))) << InstPos)
+
+#define IMM64_IMM7B_INST_WORD_X 3
+#define IMM64_IMM7B_SIZE_X 7
+#define IMM64_IMM7B_INST_WORD_POS_X 4
+#define IMM64_IMM7B_VAL_POS_X 0
+
+#define IMM64_IMM9D_INST_WORD_X 3
+#define IMM64_IMM9D_SIZE_X 9
+#define IMM64_IMM9D_INST_WORD_POS_X 18
+#define IMM64_IMM9D_VAL_POS_X 7
+
+#define IMM64_IMM5C_INST_WORD_X 3
+#define IMM64_IMM5C_SIZE_X 5
+#define IMM64_IMM5C_INST_WORD_POS_X 13
+#define IMM64_IMM5C_VAL_POS_X 16
+
+#define IMM64_IC_INST_WORD_X 3
+#define IMM64_IC_SIZE_X 1
+#define IMM64_IC_INST_WORD_POS_X 12
+#define IMM64_IC_VAL_POS_X 21
+
+#define IMM64_IMM41a_INST_WORD_X 1
+#define IMM64_IMM41a_SIZE_X 10
+#define IMM64_IMM41a_INST_WORD_POS_X 14
+#define IMM64_IMM41a_VAL_POS_X 22
+
+#define IMM64_IMM41b_INST_WORD_X 1
+#define IMM64_IMM41b_SIZE_X 8
+#define IMM64_IMM41b_INST_WORD_POS_X 24
+#define IMM64_IMM41b_VAL_POS_X 32
+
+#define IMM64_IMM41c_INST_WORD_X 2
+#define IMM64_IMM41c_SIZE_X 23
+#define IMM64_IMM41c_INST_WORD_POS_X 0
+#define IMM64_IMM41c_VAL_POS_X 40
+
+#define IMM64_SIGN_INST_WORD_X 3
+#define IMM64_SIGN_SIZE_X 1
+#define IMM64_SIGN_INST_WORD_POS_X 27
+#define IMM64_SIGN_VAL_POS_X 63
+
+RETURN_STATUS
+PeCoffLoaderRelocateImageEx (
+ IN UINT16 *Reloc,
+ IN OUT CHAR8 *Fixup,
+ IN OUT CHAR8 **FixupData,
+ IN UINT64 Adjust
+ )
+/*++
+
+Routine Description:
+
+ Performs an Itanium-based specific relocation fixup
+
+Arguments:
+
+ Reloc - Pointer to the relocation record
+
+ Fixup - Pointer to the address to fix up
+
+ FixupData - Pointer to a buffer to log the fixups
+
+ Adjust - The offset to adjust the fixup
+
+Returns:
+
+ Status code
+
+--*/
+{
+ UINT64 *F64;
+ UINT64 FixupVal;
+
+ switch ((*Reloc) >> 12) {
+
+ case EFI_IMAGE_REL_BASED_DIR64:
+ F64 = (UINT64 *) Fixup;
+ *F64 = *F64 + (UINT64) Adjust;
+ if (*FixupData != NULL) {
+ *FixupData = ALIGN_POINTER(*FixupData, sizeof(UINT64));
+ *(UINT64 *)(*FixupData) = *F64;
+ *FixupData = *FixupData + sizeof(UINT64);
+ }
+ break;
+
+ case EFI_IMAGE_REL_BASED_IA64_IMM64:
+
+ //
+ // Align it to bundle address before fixing up the
+ // 64-bit immediate value of the movl instruction.
+ //
+
+ Fixup = (CHAR8 *)((UINTN) Fixup & (UINTN) ~(15));
+ FixupVal = (UINT64)0;
+
+ //
+ // Extract the lower 32 bits of IMM64 from bundle
+ //
+ EXT_IMM64(FixupVal,
+ (UINT32 *)Fixup + IMM64_IMM7B_INST_WORD_X,
+ IMM64_IMM7B_SIZE_X,
+ IMM64_IMM7B_INST_WORD_POS_X,
+ IMM64_IMM7B_VAL_POS_X
+ );
+
+ EXT_IMM64(FixupVal,
+ (UINT32 *)Fixup + IMM64_IMM9D_INST_WORD_X,
+ IMM64_IMM9D_SIZE_X,
+ IMM64_IMM9D_INST_WORD_POS_X,
+ IMM64_IMM9D_VAL_POS_X
+ );
+
+ EXT_IMM64(FixupVal,
+ (UINT32 *)Fixup + IMM64_IMM5C_INST_WORD_X,
+ IMM64_IMM5C_SIZE_X,
+ IMM64_IMM5C_INST_WORD_POS_X,
+ IMM64_IMM5C_VAL_POS_X
+ );
+
+ EXT_IMM64(FixupVal,
+ (UINT32 *)Fixup + IMM64_IC_INST_WORD_X,
+ IMM64_IC_SIZE_X,
+ IMM64_IC_INST_WORD_POS_X,
+ IMM64_IC_VAL_POS_X
+ );
+
+ EXT_IMM64(FixupVal,
+ (UINT32 *)Fixup + IMM64_IMM41a_INST_WORD_X,
+ IMM64_IMM41a_SIZE_X,
+ IMM64_IMM41a_INST_WORD_POS_X,
+ IMM64_IMM41a_VAL_POS_X
+ );
+
+ //
+ // Update 64-bit address
+ //
+ FixupVal += Adjust;
+
+ //
+ // Insert IMM64 into bundle
+ //
+ INS_IMM64(FixupVal,
+ ((UINT32 *)Fixup + IMM64_IMM7B_INST_WORD_X),
+ IMM64_IMM7B_SIZE_X,
+ IMM64_IMM7B_INST_WORD_POS_X,
+ IMM64_IMM7B_VAL_POS_X
+ );
+
+ INS_IMM64(FixupVal,
+ ((UINT32 *)Fixup + IMM64_IMM9D_INST_WORD_X),
+ IMM64_IMM9D_SIZE_X,
+ IMM64_IMM9D_INST_WORD_POS_X,
+ IMM64_IMM9D_VAL_POS_X
+ );
+
+ INS_IMM64(FixupVal,
+ ((UINT32 *)Fixup + IMM64_IMM5C_INST_WORD_X),
+ IMM64_IMM5C_SIZE_X,
+ IMM64_IMM5C_INST_WORD_POS_X,
+ IMM64_IMM5C_VAL_POS_X
+ );
+
+ INS_IMM64(FixupVal,
+ ((UINT32 *)Fixup + IMM64_IC_INST_WORD_X),
+ IMM64_IC_SIZE_X,
+ IMM64_IC_INST_WORD_POS_X,
+ IMM64_IC_VAL_POS_X
+ );
+
+ INS_IMM64(FixupVal,
+ ((UINT32 *)Fixup + IMM64_IMM41a_INST_WORD_X),
+ IMM64_IMM41a_SIZE_X,
+ IMM64_IMM41a_INST_WORD_POS_X,
+ IMM64_IMM41a_VAL_POS_X
+ );
+
+ INS_IMM64(FixupVal,
+ ((UINT32 *)Fixup + IMM64_IMM41b_INST_WORD_X),
+ IMM64_IMM41b_SIZE_X,
+ IMM64_IMM41b_INST_WORD_POS_X,
+ IMM64_IMM41b_VAL_POS_X
+ );
+
+ INS_IMM64(FixupVal,
+ ((UINT32 *)Fixup + IMM64_IMM41c_INST_WORD_X),
+ IMM64_IMM41c_SIZE_X,
+ IMM64_IMM41c_INST_WORD_POS_X,
+ IMM64_IMM41c_VAL_POS_X
+ );
+
+ INS_IMM64(FixupVal,
+ ((UINT32 *)Fixup + IMM64_SIGN_INST_WORD_X),
+ IMM64_SIGN_SIZE_X,
+ IMM64_SIGN_INST_WORD_POS_X,
+ IMM64_SIGN_VAL_POS_X
+ );
+
+ F64 = (UINT64 *) Fixup;
+ if (*FixupData != NULL) {
+ *FixupData = ALIGN_POINTER(*FixupData, sizeof(UINT64));
+ *(UINT64 *)(*FixupData) = *F64;
+ *FixupData = *FixupData + sizeof(UINT64);
+ }
+ break;
+
+ default:
+ return RETURN_UNSUPPORTED;
+ }
+
+ return RETURN_SUCCESS;
+}
diff --git a/Source/PeCoffLoader/X64/PeCoffLoaderEx.c b/Source/PeCoffLoader/X64/PeCoffLoaderEx.c
new file mode 100644
index 0000000..1e6cc34
--- /dev/null
+++ b/Source/PeCoffLoader/X64/PeCoffLoaderEx.c
@@ -0,0 +1,74 @@
+/*++
+
+Copyright 2005, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+
+Module Name:
+
+ PeCoffLoaderEx.c
+
+Abstract:
+
+ x64 Specific relocation fixups
+
+Revision History
+
+--*/
+
+#include <Common/UefiBaseTypes.h>
+#include <Common/EfiImage.h>
+#include <Library/PeCoffLib.h>
+
+
+
+
+RETURN_STATUS
+PeCoffLoaderRelocateImageEx (
+ IN UINT16 *Reloc,
+ IN OUT CHAR8 *Fixup,
+ IN OUT CHAR8 **FixupData,
+ IN UINT64 Adjust
+ )
+/*++
+
+Routine Description:
+ Performs an x64 specific relocation fixup
+
+Arguments:
+ Reloc - Pointer to the relocation record
+ Fixup - Pointer to the address to fix up
+ FixupData - Pointer to a buffer to log the fixups
+ Adjust - The offset to adjust the fixup
+
+Returns:
+ None
+
+--*/
+{
+ UINT64 *F64;
+
+ switch ((*Reloc) >> 12) {
+
+ case EFI_IMAGE_REL_BASED_DIR64:
+ F64 = (UINT64 *) Fixup;
+ *F64 = *F64 + (UINT64) Adjust;
+ if (*FixupData != NULL) {
+ *FixupData = ALIGN_POINTER(*FixupData, sizeof(UINT64));
+ *(UINT64 *)(*FixupData) = *F64;
+ *FixupData = *FixupData + sizeof(UINT64);
+ }
+ break;
+
+ default:
+ return RETURN_UNSUPPORTED;
+ }
+
+ return RETURN_SUCCESS;
+}
diff --git a/Source/PeCoffLoader/build.xml b/Source/PeCoffLoader/build.xml
new file mode 100644
index 0000000..c6137bd
--- /dev/null
+++ b/Source/PeCoffLoader/build.xml
@@ -0,0 +1,153 @@
+<?xml version="1.0" ?>
+<!--
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+-->
+<project default="GenTool" basedir=".">
+<!--
+ EDK PeCoffLoader
+ Copyright (c) 2006, Intel Corporation
+-->
+ <taskdef resource="net/sf/antcontrib/antlib.xml"/>
+
+ <property name="LibName" value="PeCoffLoader"/>
+ <property name="LINK_OUTPUT_TYPE" value="static"/>
+ <property name="BUILD_DIR_IA32" value="${PACKAGE_DIR}/${LibName}/tmp/Ia32"/>
+ <property name="BUILD_DIR_X64" value="${PACKAGE_DIR}/${LibName}/tmp/X64"/>
+ <property name="BUILD_DIR_IPF" value="${PACKAGE_DIR}/${LibName}/tmp/Ipf"/>
+
+ <target name="GenTool" depends="init, PeCoffLoaderLib">
+ <echo message="The EDK Library: ${LibName} build has completed!"/>
+ </target>
+
+ <target name="init">
+ <echo message="Building the EDK Library: ${LibName}"/>
+ <mkdir dir="${BUILD_DIR_IA32}"/>
+ <mkdir dir="${BUILD_DIR_X64}"/>
+ <mkdir dir="${BUILD_DIR_IPF}"/>
+
+ <condition property="syslibdirs" value="">
+ <os family="mac"/>
+ </condition>
+
+ <condition property="syslibs" value="">
+ <os family="mac"/>
+ </condition>
+
+ <condition property="syslibdirs" value="${env.CYGWIN_HOME}/lib/e2fsprogs">
+ <os family="windows"/>
+ </condition>
+
+ <condition property="syslibs" value="uuid">
+ <os family="windows"/>
+ </condition>
+
+ <condition property="syslibdirs" value="/usr/lib">
+ <os name="Linux"/>
+ </condition>
+
+ <condition property="syslibs" value="uuid">
+ <os name="Linux"/>
+ </condition>
+
+ </target>
+
+ <target name="PeCoffLoaderLib" depends="init, PeCoffLoader_Ia32, PeCoffLoader_Ipf, PeCoffLoader_X64"/>
+
+ <target name="PeCoffLoader_Ia32" >
+ <cc name="${ToolChain}" objdir="${BUILD_DIR_IA32}"
+ outfile="${LIB_DIR}/${LibName}_Ia32"
+ outtype="static"
+ debug="true"
+ optimize="speed">
+
+ <defineset>
+ <define name="BUILDING_TOOLS"/>
+ <define name="TOOL_BUILD_IA32_TARGET"/>
+ </defineset>
+
+ <fileset dir="${basedir}/${LibName}"
+ includes="BasePeCoff.c Ia32/PeCoffLoaderEx.c" />
+
+ <includepath path="${PACKAGE_DIR}/${LibName}"/>
+ <includepath path="${PACKAGE_DIR}/Include"/>
+ <includepath path="${PACKAGE_DIR}/Include/Ia32"/>
+ <includepath path="${PACKAGE_DIR}/Common"/>
+ </cc>
+ </target>
+
+ <target name="PeCoffLoader_Ipf" >
+ <cc name="${ToolChain}" objdir="${BUILD_DIR_IPF}"
+ outfile="${LIB_DIR}/${LibName}_Ipf"
+ outtype="static"
+ debug="true"
+ optimize="speed">
+
+ <defineset>
+ <define name="BUILDING_TOOLS"/>
+ <define name="TOOL_BUILD_IPF_TARGET"/>
+ </defineset>
+
+ <fileset dir="${basedir}/${LibName}"
+ includes="BasePeCoff.c Ipf/PeCoffLoaderEx.c" />
+
+ <includepath path="${PACKAGE_DIR}/${LibName}"/>
+ <includepath path="${PACKAGE_DIR}/Include"/>
+ <includepath path="${PACKAGE_DIR}/Include/Ia32"/>
+ <includepath path="${PACKAGE_DIR}/Common"/>
+ </cc>
+ </target>
+
+ <target name="PeCoffLoader_X64" >
+ <cc name="${ToolChain}" objdir="${BUILD_DIR_X64}"
+ outfile="${LIB_DIR}/${LibName}_X64"
+ outtype="static"
+ debug="true"
+ optimize="speed">
+
+ <defineset>
+ <define name="BUILDING_TOOLS"/>
+ <define name="TOOL_BUILD_X64_TARGET"/>
+ </defineset>
+
+ <fileset dir="${basedir}/${LibName}"
+ includes="BasePeCoff.c X64/PeCoffLoaderEx.c" />
+
+ <includepath path="${PACKAGE_DIR}/${LibName}"/>
+ <includepath path="${PACKAGE_DIR}/Include"/>
+ <includepath path="${PACKAGE_DIR}/Include/Ia32"/>
+ <includepath path="${PACKAGE_DIR}/Common"/>
+ </cc>
+ </target>
+
+
+ <target name="clean">
+ <echo message="Removing Intermediate Files Only"/>
+ <delete>
+ <fileset dir="${BUILD_DIR_IA32}" includes="*.obj"/>
+ <fileset dir="${BUILD_DIR_X64}" includes="*.obj"/>
+ <fileset dir="${BUILD_DIR_IPF}" includes="*.obj"/>
+ </delete>
+ </target>
+
+ <target name="cleanall">
+ <echo message="Removing Object Files and the Executable: ${LibName}${ext_exe}"/>
+ <delete dir="${PACKAGE_DIR}/${LibName}/tmp">
+ </delete>
+ <delete failonerror="false" quiet="true" includeEmptyDirs="true">
+ <fileset dir="${BUILD_DIR_IA32}"/>
+ <fileset dir="${BUILD_DIR_X64}"/>
+ <fileset dir="${BUILD_DIR_IPF}"/>
+ <fileset file="${LIB_DIR}/${LibName}_Ia32${ext_static}"/>
+ <fileset file="${BIN_DIR}/${LibName}_X64${ext_static}"/>
+ <fileset file="${BIN_DIR}/${LibName}_IPF${ext_static}"/>
+ </delete>
+ </target>
+
+</project>
diff --git a/Source/PeiRebase/PeiRebaseExe.c b/Source/PeiRebase/PeiRebaseExe.c
new file mode 100644
index 0000000..27c646e
--- /dev/null
+++ b/Source/PeiRebase/PeiRebaseExe.c
@@ -0,0 +1,1059 @@
+/*++
+
+Copyright (c) 1999-2006 Intel Corporation. All rights reserved
+This program and the accompanying materials are licensed and made available
+under the terms and conditions of the BSD License which accompanies this
+distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+
+Module Name:
+
+ PeiRebaseExe.c
+
+Abstract:
+
+ This contains all code necessary to build the PeiRebase.exe utility.
+ This utility relies heavily on the PeiRebase DLL. Definitions for both
+ can be found in the PEI Rebase Utility Specification, review draft.
+
+--*/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <Common/UefiBaseTypes.h>
+#include <Common/FirmwareVolumeImageFormat.h>
+#include <Common/FirmwareFileSystem.h>
+#include <Library/PeCoffLib.h>
+
+#include "CommonLib.h"
+#include "ParseInf.h"
+#include "FvLib.h"
+#include "EfiUtilityMsgs.h"
+#include "PeiRebaseExe.h"
+
+EFI_STATUS
+ReadHeader (
+ IN FILE *InputFile,
+ OUT UINT32 *FvSize,
+ OUT BOOLEAN *ErasePolarity
+ );
+
+int
+main (
+ int argc,
+ char **argv
+ )
+/*++
+
+Routine Description:
+
+ This utility relocates PEI XIP PE32s in a FV.
+
+Arguments:
+
+ argc - Number of command line arguments
+ argv[]:
+ BaseAddress The base address to use for rebasing the FV. The correct
+ format is a hex number preceded by 0x.
+ InputFileName The name of the input FV file.
+ OutputFileName The name of the output FV file.
+ MapFileName The name of the map file of relocation info.
+
+ Arguments come in pair in any order.
+ -I InputFileName
+ -O OutputFileName
+ -B BaseAddress
+ -M MapFileName
+
+Returns:
+
+ 0 No error conditions detected.
+ 1 One or more of the input parameters is invalid.
+ 2 A resource required by the utility was unavailable.
+ Most commonly this will be memory allocation or file creation.
+ 3 PeiRebase.dll could not be loaded.
+ 4 Error executing the PEI rebase.
+
+--*/
+{
+ UINT8 Index;
+ CHAR8 InputFileName[_MAX_PATH];
+ CHAR8 OutputFileName[_MAX_PATH];
+ CHAR8 MapFileName[_MAX_PATH];
+ EFI_PHYSICAL_ADDRESS BaseAddress;
+ BOOLEAN BaseAddressSet;
+ EFI_STATUS Status;
+ FILE *InputFile;
+ FILE *OutputFile;
+ FILE *MapFile;
+ UINT64 FvOffset;
+ UINT32 FileCount;
+ int BytesRead;
+ EFI_FIRMWARE_VOLUME_HEADER *FvImage;
+ UINT32 FvSize;
+ EFI_FFS_FILE_HEADER *CurrentFile;
+ BOOLEAN ErasePolarity;
+ EFI_PHYSICAL_ADDRESS CurrentFileBaseAddress;
+
+ ErasePolarity = FALSE;
+ //
+ // Set utility name for error/warning reporting purposes.
+ //
+ SetUtilityName (UTILITY_NAME);
+ //
+ // Verify the correct number of arguments
+ //
+ if (argc != MAX_ARGS) {
+ PrintUsage ();
+ return STATUS_ERROR;
+ }
+
+ //
+ // Initialize variables
+ //
+ InputFileName[0] = 0;
+ OutputFileName[0] = 0;
+ MapFileName[0] = 0;
+ BaseAddress = 0;
+ BaseAddressSet = FALSE;
+ FvOffset = 0;
+ FileCount = 0;
+ ErasePolarity = FALSE;
+ InputFile = NULL;
+ OutputFile = NULL;
+ MapFile = NULL;
+ FvImage = NULL;
+
+ //
+ // Parse the command line arguments
+ //
+ for (Index = 1; Index < MAX_ARGS; Index += 2) {
+ //
+ // Make sure argument pair begin with - or /
+ //
+ if (argv[Index][0] != '-' && argv[Index][0] != '/') {
+ PrintUsage ();
+ Error (NULL, 0, 0, argv[Index], "unrecognized option");
+ return STATUS_ERROR;
+ }
+ //
+ // Make sure argument specifier is only one letter
+ //
+ if (argv[Index][2] != 0) {
+ PrintUsage ();
+ Error (NULL, 0, 0, argv[Index], "unrecognized option");
+ return STATUS_ERROR;
+ }
+ //
+ // Determine argument to read
+ //
+ switch (argv[Index][1]) {
+ case 'I':
+ case 'i':
+ if (strlen (InputFileName) == 0) {
+ strcpy (InputFileName, argv[Index + 1]);
+ } else {
+ PrintUsage ();
+ Error (NULL, 0, 0, argv[Index + 1], "only one -i InputFileName may be specified");
+ return STATUS_ERROR;
+ }
+ break;
+
+ case 'O':
+ case 'o':
+ if (strlen (OutputFileName) == 0) {
+ strcpy (OutputFileName, argv[Index + 1]);
+ } else {
+ PrintUsage ();
+ Error (NULL, 0, 0, argv[Index + 1], "only one -o OutputFileName may be specified");
+ return STATUS_ERROR;
+ }
+ break;
+
+ case 'B':
+ case 'b':
+ if (!BaseAddressSet) {
+ Status = AsciiStringToUint64 (argv[Index + 1], FALSE, &BaseAddress);
+ if (EFI_ERROR (Status)) {
+ PrintUsage ();
+ Error (NULL, 0, 0, argv[Index + 1], "invalid hex digit given for the base address");
+ return STATUS_ERROR;
+ }
+
+ BaseAddressSet = TRUE;
+ } else {
+ PrintUsage ();
+ Error (NULL, 0, 0, argv[Index + 1], "-b BaseAddress may only be specified once");
+ return STATUS_ERROR;
+ }
+ break;
+
+ case 'M':
+ case 'm':
+ if (strlen (MapFileName) == 0) {
+ strcpy (MapFileName, argv[Index + 1]);
+ } else {
+ PrintUsage ();
+ Error (NULL, 0, 0, argv[Index + 1], "only one -m MapFileName may be specified");
+ return STATUS_ERROR;
+ }
+ break;
+
+ default:
+ PrintUsage ();
+ Error (NULL, 0, 0, argv[Index], "unrecognized argument");
+ return STATUS_ERROR;
+ break;
+ }
+ }
+
+ //
+ // Create the Map file if we need it
+ //
+ if (strlen (MapFileName) != 0) {
+ MapFile = fopen (MapFileName, "w");
+ if (MapFile == NULL) {
+ Error (NULL, 0, 0, MapFileName, "failed to open map file");
+ goto Finish;
+ }
+ }
+
+ //
+ // Open the file containing the FV
+ //
+ InputFile = fopen (InputFileName, "rb");
+ if (InputFile == NULL) {
+ Error (NULL, 0, 0, InputFileName, "could not open input file for reading");
+ return STATUS_ERROR;
+ }
+ //
+ // Determine size of FV
+ //
+ Status = ReadHeader (InputFile, &FvSize, &ErasePolarity);
+ if (EFI_ERROR (Status)) {
+ Error (NULL, 0, 0, "could not parse the FV header", NULL);
+ goto Finish;
+ }
+ //
+ // Allocate a buffer for the FV image
+ //
+ FvImage = malloc (FvSize);
+ if (FvImage == NULL) {
+ Error (NULL, 0, 0, "application error", "memory allocation failed");
+ goto Finish;
+ }
+ //
+ // Read the entire FV to the buffer
+ //
+ BytesRead = fread (FvImage, 1, FvSize, InputFile);
+ fclose (InputFile);
+ InputFile = NULL;
+ if ((unsigned int) BytesRead != FvSize) {
+ Error (NULL, 0, 0, InputFileName, "failed to read from file");
+ goto Finish;
+ }
+ //
+ // Prepare to walk the FV image
+ //
+ InitializeFvLib (FvImage, FvSize);
+ //
+ // Get the first file
+ //
+ Status = GetNextFile (NULL, &CurrentFile);
+ if (EFI_ERROR (Status)) {
+ Error (NULL, 0, 0, "cannot find the first file in the FV image", NULL);
+ goto Finish;
+ }
+ //
+ // Check if each file should be rebased
+ //
+ while (CurrentFile != NULL) {
+ //
+ // Rebase this file
+ //
+ CurrentFileBaseAddress = BaseAddress + ((UINTN) CurrentFile - (UINTN) FvImage);
+ Status = FfsRebase (CurrentFile, CurrentFileBaseAddress, MapFile);
+
+ if (EFI_ERROR (Status)) {
+ switch (Status) {
+
+ case EFI_INVALID_PARAMETER:
+ Error (NULL, 0, 0, "invalid parameter passed to FfsRebase", NULL);
+ break;
+
+ case EFI_ABORTED:
+ Error (NULL, 0, 0, "error detected while rebasing -- aborted", NULL);
+ break;
+
+ case EFI_OUT_OF_RESOURCES:
+ Error (NULL, 0, 0, "FfsRebase could not allocate required resources", NULL);
+ break;
+
+ case EFI_NOT_FOUND:
+ Error (NULL, 0, 0, "FfsRebase could not locate a PE32 section", NULL);
+ break;
+
+ default:
+ Error (NULL, 0, 0, "FfsRebase returned unknown status", "status=0x%08X", Status);
+ break;
+ }
+
+ goto Finish;
+ }
+
+ //
+ // Get the next file
+ //
+ Status = GetNextFile (CurrentFile, &CurrentFile);
+ if (EFI_ERROR (Status)) {
+ Error (NULL, 0, 0, "cannot find the next file in the FV image", NULL);
+ goto Finish;
+ }
+ }
+ //
+ // Open the output file
+ //
+ OutputFile = fopen (OutputFileName, "wb");
+ if (OutputFile == NULL) {
+ Error (NULL, 0, 0, OutputFileName, "failed to open output file");
+ goto Finish;
+ }
+
+ if (fwrite (FvImage, 1, FvSize, OutputFile) != FvSize) {
+ Error (NULL, 0, 0, "failed to write to output file", 0);
+ goto Finish;
+ }
+
+Finish:
+ if (InputFile != NULL) {
+ fclose (InputFile);
+ }
+ //
+ // If we created an output file, and there was an error, remove it so
+ // subsequent builds will rebuild it.
+ //
+ if (OutputFile != NULL) {
+ if (GetUtilityStatus () == STATUS_ERROR) {
+ remove (OutputFileName);
+ }
+
+ fclose (OutputFile);
+ }
+
+ if (MapFile != NULL) {
+ fclose (MapFile);
+ }
+
+ if (FvImage != NULL) {
+ free (FvImage);
+ }
+
+ return GetUtilityStatus ();
+}
+
+EFI_STATUS
+ReadHeader (
+ IN FILE *InputFile,
+ OUT UINT32 *FvSize,
+ OUT BOOLEAN *ErasePolarity
+ )
+/*++
+
+Routine Description:
+
+ This function determines the size of the FV and the erase polarity. The
+ erase polarity is the FALSE value for file state.
+
+Arguments:
+
+ InputFile The file that contains the FV image.
+ FvSize The size of the FV.
+ ErasePolarity The FV erase polarity.
+
+Returns:
+
+ EFI_SUCCESS Function completed successfully.
+ EFI_INVALID_PARAMETER A required parameter was NULL or is out of range.
+ EFI_ABORTED The function encountered an error.
+
+--*/
+{
+ EFI_FIRMWARE_VOLUME_HEADER VolumeHeader;
+ EFI_FV_BLOCK_MAP_ENTRY BlockMap;
+ UINTN Signature[2];
+ UINTN BytesRead;
+ UINT32 Size;
+
+ BytesRead = 0;
+ Size = 0;
+ //
+ // Check input parameters
+ //
+ if ((InputFile == NULL) || (FvSize == NULL) || (ErasePolarity == NULL)) {
+ Error (NULL, 0, 0, "ReadHeader()", "invalid input parameter");
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // Read the header
+ //
+ fread (&VolumeHeader, sizeof (EFI_FIRMWARE_VOLUME_HEADER) - sizeof (EFI_FV_BLOCK_MAP_ENTRY), 1, InputFile);
+ BytesRead = sizeof (EFI_FIRMWARE_VOLUME_HEADER) - sizeof (EFI_FV_BLOCK_MAP_ENTRY);
+ Signature[0] = VolumeHeader.Signature;
+ Signature[1] = 0;
+
+ //
+ // Get erase polarity
+ //
+ if (VolumeHeader.Attributes & EFI_FVB_ERASE_POLARITY) {
+ *ErasePolarity = TRUE;
+ }
+
+ do {
+ fread (&BlockMap, sizeof (EFI_FV_BLOCK_MAP_ENTRY), 1, InputFile);
+ BytesRead += sizeof (EFI_FV_BLOCK_MAP_ENTRY);
+
+ if (BlockMap.NumBlocks != 0) {
+ Size += BlockMap.NumBlocks * BlockMap.BlockLength;
+ }
+
+ } while (!(BlockMap.NumBlocks == 0 && BlockMap.BlockLength == 0));
+
+ if (VolumeHeader.FvLength != Size) {
+ Error (NULL, 0, 0, "volume size not consistant with block maps", NULL);
+ return EFI_ABORTED;
+ }
+
+ *FvSize = Size;
+
+ rewind (InputFile);
+
+ return EFI_SUCCESS;
+}
+
+VOID
+PrintUtilityInfo (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Displays the standard utility information to SDTOUT
+
+Arguments:
+
+ None
+
+Returns:
+
+ None
+
+--*/
+{
+ printf (
+ "%s, PEI Rebase Utility. Version %i.%i, %s.\n\n",
+ UTILITY_NAME,
+ UTILITY_MAJOR_VERSION,
+ UTILITY_MINOR_VERSION,
+ UTILITY_DATE
+ );
+}
+
+VOID
+PrintUsage (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Displays the utility usage syntax to STDOUT
+
+Arguments:
+
+ None
+
+Returns:
+
+ None
+
+--*/
+{
+ printf (
+ "Usage: %s -I InputFileName -O OutputFileName -B BaseAddress [-M MapFile]\n",
+ UTILITY_NAME
+ );
+ printf (" Where:\n");
+ printf (" InputFileName is the name of the EFI FV file to rebase.\n");
+ printf (" OutputFileName is the desired output file name.\n");
+ printf (" BaseAddress is the FV base address to rebase agains.\n");
+ printf (" MapFileName is an optional map file of the relocations\n");
+ printf (" Argument pair may be in any order.\n\n");
+}
+
+EFI_STATUS
+FfsRebase (
+ IN OUT EFI_FFS_FILE_HEADER *FfsFile,
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,
+ IN FILE *MapFile OPTIONAL
+ )
+/*++
+
+Routine Description:
+
+ This function determines if a file is XIP and should be rebased. It will
+ rebase any PE32 sections found in the file using the base address.
+
+Arguments:
+
+ FfsFile A pointer to Ffs file image.
+ BaseAddress The base address to use for rebasing the file image.
+ MapFile Optional file to dump relocation information into
+
+Returns:
+
+ EFI_SUCCESS The image was properly rebased.
+ EFI_INVALID_PARAMETER An input parameter is invalid.
+ EFI_ABORTED An error occurred while rebasing the input file image.
+ EFI_OUT_OF_RESOURCES Could not allocate a required resource.
+ EFI_NOT_FOUND No compressed sections could be found.
+
+--*/
+{
+ EFI_STATUS Status;
+ PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;
+ UINTN MemoryImagePointer;
+ UINTN MemoryImagePointerAligned;
+ EFI_PHYSICAL_ADDRESS ImageAddress;
+ UINT64 ImageSize;
+ EFI_PHYSICAL_ADDRESS EntryPoint;
+ UINT32 Pe32ImageSize;
+ UINT32 NewPe32BaseAddress;
+ UINTN Index;
+ EFI_FILE_SECTION_POINTER CurrentPe32Section;
+ EFI_FFS_FILE_STATE SavedState;
+ EFI_IMAGE_NT_HEADERS *PeHdr;
+ UINT32 *PeHdrSizeOfImage;
+ UINT32 *PeHdrChecksum;
+ UINT32 FoundCount;
+ EFI_TE_IMAGE_HEADER *TEImageHeader;
+ UINT8 *TEBuffer;
+ EFI_IMAGE_DOS_HEADER *DosHeader;
+ UINT8 FileGuidString[80];
+ UINT32 TailSize;
+ EFI_FFS_FILE_TAIL TailValue;
+
+ //
+ // Verify input parameters
+ //
+ if (FfsFile == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Convert the GUID to a string so we can at least report which file
+ // if we find an error.
+ //
+ PrintGuidToBuffer (&FfsFile->Name, FileGuidString, sizeof (FileGuidString), TRUE);
+ if (FfsFile->Attributes & FFS_ATTRIB_TAIL_PRESENT) {
+ TailSize = sizeof (EFI_FFS_FILE_TAIL);
+ } else {
+ TailSize = 0;
+ }
+
+ //
+ // Do some cursory checks on the FFS file contents
+ //
+ Status = VerifyFfsFile (FfsFile);
+ if (EFI_ERROR (Status)) {
+ Error (NULL, 0, 0, "file does not appear to be a valid FFS file, cannot be rebased", FileGuidString);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ memset (&ImageContext, 0, sizeof (ImageContext));
+
+ //
+ // Check if XIP file type. If not XIP, don't rebase.
+ //
+ if (FfsFile->Type != EFI_FV_FILETYPE_PEI_CORE &&
+ FfsFile->Type != EFI_FV_FILETYPE_PEIM &&
+ FfsFile->Type != EFI_FV_FILETYPE_SECURITY_CORE &&
+ FfsFile->Type != EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER
+ ) {
+ return EFI_SUCCESS;
+ }
+
+ //
+ // Rebase each PE32 section
+ //
+ Status = EFI_SUCCESS;
+ FoundCount = 0;
+ for (Index = 1;; Index++) {
+ Status = GetSectionByType (FfsFile, EFI_SECTION_PE32, Index, &CurrentPe32Section);
+ if (EFI_ERROR (Status)) {
+ break;
+ }
+
+ FoundCount++;
+
+ //
+ // Calculate the PE32 base address, the FFS file base plus the offset of the PE32 section
+ //
+ NewPe32BaseAddress = ((UINT32) BaseAddress) + ((UINTN) CurrentPe32Section.Pe32Section + sizeof (EFI_COMMON_SECTION_HEADER) - (UINTN) FfsFile);
+
+ //
+ // Initialize context
+ //
+ memset (&ImageContext, 0, sizeof (ImageContext));
+ ImageContext.Handle = (VOID *) ((UINTN) CurrentPe32Section.Pe32Section + sizeof (EFI_PE32_SECTION));
+ ImageContext.ImageRead = (PE_COFF_LOADER_READ_FILE) FfsRebaseImageRead;
+
+ Status = PeCoffLoaderGetImageInfo (&ImageContext);
+
+ if (EFI_ERROR (Status)) {
+ Error (NULL, 0, 0, "GetImageInfo() call failed on rebase", FileGuidString);
+ return Status;
+ }
+ //
+ // Allocate a buffer for the image to be loaded into.
+ //
+ Pe32ImageSize = GetLength (CurrentPe32Section.Pe32Section->CommonHeader.Size) - sizeof (EFI_PE32_SECTION);
+ MemoryImagePointer = (UINTN) (malloc (Pe32ImageSize + 0x1000));
+ if (MemoryImagePointer == 0) {
+ Error (NULL, 0, 0, "memory allocation failure", NULL);
+ return EFI_OUT_OF_RESOURCES;
+ }
+ memset ((void *) MemoryImagePointer, 0, Pe32ImageSize + 0x1000);
+ MemoryImagePointerAligned = (MemoryImagePointer + 0x0FFF) & (-1 << 12);
+
+
+ ImageContext.ImageAddress = MemoryImagePointerAligned;
+
+ Status = PeCoffLoaderLoadImage (&ImageContext);
+ if (EFI_ERROR (Status)) {
+ Error (NULL, 0, 0, "LoadImage() call failed on rebase", FileGuidString);
+ free ((VOID *) MemoryImagePointer);
+ return Status;
+ }
+
+ ImageContext.DestinationAddress = NewPe32BaseAddress;
+ Status = PeCoffLoaderRelocateImage (&ImageContext);
+ if (EFI_ERROR (Status)) {
+ Error (NULL, 0, 0, "RelocateImage() call failed on rebase", FileGuidString);
+ free ((VOID *) MemoryImagePointer);
+ return Status;
+ }
+
+ ImageAddress = ImageContext.ImageAddress;
+ ImageSize = ImageContext.ImageSize;
+ EntryPoint = ImageContext.EntryPoint;
+
+ if (ImageSize > Pe32ImageSize) {
+ Error (
+ NULL,
+ 0,
+ 0,
+ "rebased image is larger than original PE32 image",
+ "0x%X > 0x%X, file %s",
+ ImageSize,
+ Pe32ImageSize,
+ FileGuidString
+ );
+ free ((VOID *) MemoryImagePointer);
+ return EFI_ABORTED;
+ }
+ //
+ // Since we may have updated the Codeview RVA, we need to insure the PE
+ // header indicates the image is large enough to contain the Codeview data
+ // so it will be loaded properly later if the PEIM is reloaded into memory...
+ //
+ PeHdr = (VOID *) ((UINTN) ImageAddress + ImageContext.PeCoffHeaderOffset);
+ if (PeHdr->FileHeader.Machine == EFI_IMAGE_MACHINE_IA32) {
+ PeHdrSizeOfImage = (UINT32 *) (&(*(EFI_IMAGE_OPTIONAL_HEADER32 *) &PeHdr->OptionalHeader).SizeOfImage);
+ PeHdrChecksum = (UINT32 *) (&(*(EFI_IMAGE_OPTIONAL_HEADER32 *) &PeHdr->OptionalHeader).CheckSum);
+ } else if (PeHdr->FileHeader.Machine == EFI_IMAGE_MACHINE_IA64) {
+ PeHdrSizeOfImage = (UINT32 *) (&(*(EFI_IMAGE_OPTIONAL_HEADER64 *) &PeHdr->OptionalHeader).SizeOfImage);
+ PeHdrChecksum = (UINT32 *) (&(*(EFI_IMAGE_OPTIONAL_HEADER64 *) &PeHdr->OptionalHeader).CheckSum);
+ } else if (PeHdr->FileHeader.Machine == EFI_IMAGE_MACHINE_X64) {
+ PeHdrSizeOfImage = (UINT32 *) (&(*(EFI_IMAGE_OPTIONAL_HEADER64 *) &PeHdr->OptionalHeader).SizeOfImage);
+ PeHdrChecksum = (UINT32 *) (&(*(EFI_IMAGE_OPTIONAL_HEADER64 *) &PeHdr->OptionalHeader).CheckSum);
+ } else {
+ Error (
+ NULL,
+ 0,
+ 0,
+ "unknown machine type in PE32 image",
+ "machine type=0x%X, file=%s",
+ (UINT32) PeHdr->FileHeader.Machine,
+ FileGuidString
+ );
+ free ((VOID *) MemoryImagePointer);
+ return EFI_ABORTED;
+ }
+
+ if (*PeHdrSizeOfImage != ImageContext.ImageSize) {
+ *PeHdrSizeOfImage = (UINT32) ImageContext.ImageSize;
+ if (*PeHdrChecksum) {
+ *PeHdrChecksum = 0;
+ }
+ }
+
+ memcpy (CurrentPe32Section.Pe32Section + 1, (VOID *) MemoryImagePointerAligned, (UINT32) ImageSize);
+
+ //
+ // Get EntryPoint in Flash Region.
+ //
+ EntryPoint = NewPe32BaseAddress + EntryPoint - ImageAddress;
+
+ //
+ // If a map file was selected output mapping information for any file that
+ // was rebased.
+ //
+ if (MapFile != NULL) {
+ fprintf (MapFile, "PE32 File: %s Base:%08lx", FileGuidString, BaseAddress);
+ fprintf (MapFile, " EntryPoint:%08lx", EntryPoint);
+ if (ImageContext.PdbPointer != NULL) {
+ fprintf (MapFile, " FileName: %s", ImageContext.PdbPointer);
+ }
+ fprintf (MapFile, "\n");
+ }
+
+ free ((VOID *) MemoryImagePointer);
+
+ //
+ // Now update file checksum
+ //
+ if (FfsFile->Attributes & FFS_ATTRIB_TAIL_PRESENT) {
+ TailSize = sizeof (EFI_FFS_FILE_TAIL);
+ } else {
+ TailSize = 0;
+ }
+
+ if (FfsFile->Attributes & FFS_ATTRIB_CHECKSUM) {
+ SavedState = FfsFile->State;
+ FfsFile->IntegrityCheck.Checksum.File = 0;
+ FfsFile->State = 0;
+ if (FfsFile->Attributes & FFS_ATTRIB_CHECKSUM) {
+ FfsFile->IntegrityCheck.Checksum.File = CalculateChecksum8 (
+ (UINT8 *) FfsFile,
+ GetLength (FfsFile->Size) - TailSize
+ );
+ } else {
+ FfsFile->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM;
+ }
+
+ FfsFile->State = SavedState;
+ }
+ //
+ // Update tail if present
+ //
+ if (FfsFile->Attributes & FFS_ATTRIB_TAIL_PRESENT) {
+ TailValue = (EFI_FFS_FILE_TAIL) (~(FfsFile->IntegrityCheck.TailReference));
+ *(EFI_FFS_FILE_TAIL *) (((UINTN) FfsFile + GetLength (FfsFile->Size) - sizeof (EFI_FFS_FILE_TAIL))) = TailValue;
+ }
+ }
+ //
+ // Now process TE sections
+ //
+ for (Index = 1;; Index++) {
+ Status = GetSectionByType (FfsFile, EFI_SECTION_TE, Index, &CurrentPe32Section);
+ if (EFI_ERROR (Status)) {
+ break;
+ }
+
+ FoundCount++;
+
+ //
+ // Calculate the TE base address, the FFS file base plus the offset of the TE section less the size stripped off
+ // by GenTEImage
+ //
+ TEImageHeader = (EFI_TE_IMAGE_HEADER *) ((UINT8 *) CurrentPe32Section.Pe32Section + sizeof (EFI_COMMON_SECTION_HEADER));
+
+ NewPe32BaseAddress = ((UINT32) BaseAddress) +
+ (
+ (UINTN) CurrentPe32Section.Pe32Section +
+ sizeof (EFI_COMMON_SECTION_HEADER) +
+ sizeof (EFI_TE_IMAGE_HEADER) -
+ TEImageHeader->StrippedSize -
+ (UINTN) FfsFile
+ );
+
+ //
+ // Allocate a buffer to unshrink the image into.
+ //
+ Pe32ImageSize = GetLength (CurrentPe32Section.Pe32Section->CommonHeader.Size) - sizeof (EFI_PE32_SECTION) -
+ sizeof (EFI_TE_IMAGE_HEADER);
+ Pe32ImageSize += TEImageHeader->StrippedSize;
+ TEBuffer = (UINT8 *) malloc (Pe32ImageSize);
+ if (TEBuffer == NULL) {
+ Error (NULL, 0, 0, "failed to allocate memory", NULL);
+ return EFI_OUT_OF_RESOURCES;
+ }
+ //
+ // Expand the image into our buffer and fill in critical fields in the DOS header
+ // Fill in fields required by the loader.
+ // At offset 0x3C is the offset to the PE signature. We'll put it immediately following the offset value
+ // itself.
+ //
+ memset (TEBuffer, 0, Pe32ImageSize);
+ DosHeader = (EFI_IMAGE_DOS_HEADER *) TEBuffer;
+ DosHeader->e_magic = EFI_IMAGE_DOS_SIGNATURE;
+ *(UINT32 *) (TEBuffer + 0x3C) = 0x40;
+ PeHdr = (EFI_IMAGE_NT_HEADERS *) (TEBuffer + 0x40);
+ PeHdr->Signature = EFI_IMAGE_NT_SIGNATURE;
+ PeHdr->FileHeader.Machine = TEImageHeader->Machine;
+ PeHdr->FileHeader.NumberOfSections = TEImageHeader->NumberOfSections;
+
+ //
+ // Say the size of the optional header is the total we stripped off less the size of a PE file header and PE signature and
+ // the 0x40 bytes for our DOS header.
+ //
+ PeHdr->FileHeader.SizeOfOptionalHeader = (UINT16) (TEImageHeader->StrippedSize - 0x40 - sizeof (UINT32) - sizeof (EFI_IMAGE_FILE_HEADER));
+ PeHdr->OptionalHeader.ImageBase = (UINTN) (TEImageHeader->ImageBase - TEImageHeader->StrippedSize + sizeof (EFI_TE_IMAGE_HEADER));
+ PeHdr->OptionalHeader.AddressOfEntryPoint = TEImageHeader->AddressOfEntryPoint;
+ PeHdr->OptionalHeader.BaseOfCode = TEImageHeader->BaseOfCode;
+ PeHdr->OptionalHeader.SizeOfImage = Pe32ImageSize;
+ PeHdr->OptionalHeader.Subsystem = TEImageHeader->Subsystem;
+ PeHdr->OptionalHeader.SizeOfImage = Pe32ImageSize;
+ PeHdr->OptionalHeader.SizeOfHeaders = TEImageHeader->StrippedSize + TEImageHeader->NumberOfSections *
+ sizeof (EFI_IMAGE_SECTION_HEADER) - 12;
+
+ //
+ // Set NumberOfRvaAndSizes in the optional header to what we had available in the original image
+ //
+ if ((TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress != 0) ||
+ (TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size != 0)
+ ) {
+ PeHdr->OptionalHeader.NumberOfRvaAndSizes = EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC + 1;
+ PeHdr->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress;
+ PeHdr->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size = TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size;
+ }
+
+ if ((TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress != 0) ||
+ (TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].Size != 0)
+ ) {
+ PeHdr->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress = TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress;
+ PeHdr->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size = TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].Size;
+ if (PeHdr->OptionalHeader.NumberOfRvaAndSizes < EFI_IMAGE_DIRECTORY_ENTRY_DEBUG + 1) {
+ PeHdr->OptionalHeader.NumberOfRvaAndSizes = EFI_IMAGE_DIRECTORY_ENTRY_DEBUG + 1;
+ }
+ }
+ //
+ // NOTE: These values are defaults, and should be verified to be correct in the GenTE utility
+ //
+ PeHdr->OptionalHeader.SectionAlignment = 0x10;
+
+ //
+ // Copy the rest of the image to its original offset
+ //
+ memcpy (
+ TEBuffer + TEImageHeader->StrippedSize,
+ (UINT8 *) CurrentPe32Section.Pe32Section + sizeof (EFI_PE32_SECTION) + sizeof (EFI_TE_IMAGE_HEADER),
+ GetLength (CurrentPe32Section.Pe32Section->CommonHeader.Size) - sizeof (EFI_PE32_SECTION) -
+ sizeof (EFI_TE_IMAGE_HEADER)
+ );
+
+ //
+ // Initialize context
+ //
+ memset (&ImageContext, 0, sizeof (ImageContext));
+ ImageContext.Handle = (VOID *) TEBuffer;
+ ImageContext.ImageRead = (PE_COFF_LOADER_READ_FILE) FfsRebaseImageRead;
+
+ Status = PeCoffLoaderGetImageInfo (&ImageContext);
+
+ if (EFI_ERROR (Status)) {
+ Error (NULL, 0, 0, "GetImageInfo() call failed on rebase of TE image", FileGuidString);
+ free (TEBuffer);
+ return Status;
+ }
+ //
+ // Allocate a buffer for the image to be loaded into.
+ //
+ MemoryImagePointer = (UINTN) (malloc (Pe32ImageSize + 0x1000));
+ if (MemoryImagePointer == 0) {
+ Error (NULL, 0, 0, "memory allocation error on rebase of TE image", FileGuidString);
+ free (TEBuffer);
+ return EFI_OUT_OF_RESOURCES;
+ }
+ memset ((void *) MemoryImagePointer, 0, Pe32ImageSize + 0x1000);
+ MemoryImagePointerAligned = (MemoryImagePointer + 0x0FFF) & (-1 << 12);
+
+
+ ImageContext.ImageAddress = MemoryImagePointerAligned;
+ Status = PeCoffLoaderLoadImage (&ImageContext);
+ if (EFI_ERROR (Status)) {
+ Error (NULL, 0, 0, "LoadImage() call failed on rebase of TE image", FileGuidString);
+ free (TEBuffer);
+ free ((VOID *) MemoryImagePointer);
+ return Status;
+ }
+
+ ImageContext.DestinationAddress = NewPe32BaseAddress;
+ Status = PeCoffLoaderRelocateImage (&ImageContext);
+ if (EFI_ERROR (Status)) {
+ Error (NULL, 0, 0, "RelocateImage() call failed on rebase of TE image", FileGuidString);
+ free ((VOID *) MemoryImagePointer);
+ free (TEBuffer);
+ return Status;
+ }
+
+ ImageAddress = ImageContext.ImageAddress;
+ ImageSize = ImageContext.ImageSize;
+ EntryPoint = ImageContext.EntryPoint;
+
+ //
+ // Since we may have updated the Codeview RVA, we need to insure the PE
+ // header indicates the image is large enough to contain the Codeview data
+ // so it will be loaded properly later if the PEIM is reloaded into memory...
+ //
+ PeHdr = (VOID *) ((UINTN) ImageAddress + ImageContext.PeCoffHeaderOffset);
+ if (PeHdr->FileHeader.Machine == EFI_IMAGE_MACHINE_IA32) {
+ PeHdrSizeOfImage = (UINT32 *) (&(*(EFI_IMAGE_OPTIONAL_HEADER32 *) &PeHdr->OptionalHeader).SizeOfImage);
+ PeHdrChecksum = (UINT32 *) (&(*(EFI_IMAGE_OPTIONAL_HEADER32 *) &PeHdr->OptionalHeader).CheckSum);
+ } else if (PeHdr->FileHeader.Machine == EFI_IMAGE_MACHINE_IA64) {
+ PeHdrSizeOfImage = (UINT32 *) (&(*(EFI_IMAGE_OPTIONAL_HEADER64 *) &PeHdr->OptionalHeader).SizeOfImage);
+ PeHdrChecksum = (UINT32 *) (&(*(EFI_IMAGE_OPTIONAL_HEADER64 *) &PeHdr->OptionalHeader).CheckSum);
+ } else {
+ Error (
+ NULL,
+ 0,
+ 0,
+ "unknown machine type in TE image",
+ "machine type=0x%X, file=%s",
+ (UINT32) PeHdr->FileHeader.Machine,
+ FileGuidString
+ );
+ free ((VOID *) MemoryImagePointer);
+ free (TEBuffer);
+ return EFI_ABORTED;
+ }
+
+ if (*PeHdrSizeOfImage != ImageContext.ImageSize) {
+ *PeHdrSizeOfImage = (UINT32) ImageContext.ImageSize;
+ if (*PeHdrChecksum) {
+ *PeHdrChecksum = 0;
+ }
+ }
+
+ TEImageHeader->ImageBase = (UINT64) (NewPe32BaseAddress + TEImageHeader->StrippedSize - sizeof (EFI_TE_IMAGE_HEADER));
+ memcpy (
+ (UINT8 *) (CurrentPe32Section.Pe32Section + 1) + sizeof (EFI_TE_IMAGE_HEADER),
+ (VOID *) ((UINT8 *) MemoryImagePointerAligned + TEImageHeader->StrippedSize),
+ GetLength (CurrentPe32Section.Pe32Section->CommonHeader.Size) - sizeof (EFI_PE32_SECTION) -
+ sizeof (EFI_TE_IMAGE_HEADER)
+ );
+
+ //
+ // Get EntryPoint in Flash Region.
+ //
+ EntryPoint = NewPe32BaseAddress + EntryPoint - ImageAddress;
+
+ //
+ // If a map file was selected output mapping information for any file that
+ // was rebased.
+ //
+ if (MapFile != NULL) {
+ fprintf (MapFile, "TE File: %s Base:%08lx", FileGuidString, BaseAddress);
+ fprintf (MapFile, " EntryPoint:%08lx", EntryPoint);
+ if (ImageContext.PdbPointer != NULL) {
+ fprintf (MapFile, " FileName: %s", ImageContext.PdbPointer);
+ }
+ fprintf (MapFile, "\n");
+ }
+
+ free ((VOID *) MemoryImagePointer);
+ free (TEBuffer);
+ if (FfsFile->Attributes & FFS_ATTRIB_TAIL_PRESENT) {
+ TailSize = sizeof (EFI_FFS_FILE_TAIL);
+ } else {
+ TailSize = 0;
+ }
+ //
+ // Now update file checksum
+ //
+ if (FfsFile->Attributes & FFS_ATTRIB_CHECKSUM) {
+ SavedState = FfsFile->State;
+ FfsFile->IntegrityCheck.Checksum.File = 0;
+ FfsFile->State = 0;
+ if (FfsFile->Attributes & FFS_ATTRIB_CHECKSUM) {
+ FfsFile->IntegrityCheck.Checksum.File = CalculateChecksum8 (
+ (UINT8 *) FfsFile,
+ GetLength (FfsFile->Size) - TailSize
+ );
+ } else {
+ FfsFile->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM;
+ }
+
+ FfsFile->State = SavedState;
+ }
+ //
+ // Update tail if present
+ //
+ if (FfsFile->Attributes & FFS_ATTRIB_TAIL_PRESENT) {
+ TailValue = (EFI_FFS_FILE_TAIL) (~(FfsFile->IntegrityCheck.TailReference));
+ *(EFI_FFS_FILE_TAIL *) (((UINTN) FfsFile + GetLength (FfsFile->Size) - sizeof (EFI_FFS_FILE_TAIL))) = TailValue;
+ }
+ }
+ //
+ // If we found no files, then emit an error if no compressed sections either
+ //
+ if (FoundCount == 0) {
+ Status = GetSectionByType (FfsFile, EFI_SECTION_COMPRESSION, Index, &CurrentPe32Section);
+ if (EFI_ERROR (Status)) {
+ Error (NULL, 0, 0, "no PE32, TE, nor compressed section found in FV file", FileGuidString);
+ return EFI_NOT_FOUND;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+FfsRebaseImageRead (
+ IN VOID *FileHandle,
+ IN UINTN FileOffset,
+ IN OUT UINT32 *ReadSize,
+ OUT VOID *Buffer
+ )
+/*++
+
+Routine Description:
+
+ Support routine for the PE/COFF Loader that reads a buffer from a PE/COFF file
+
+Arguments:
+
+ FileHandle - The handle to the PE/COFF file
+
+ FileOffset - The offset, in bytes, into the file to read
+
+ ReadSize - The number of bytes to read from the file starting at FileOffset
+
+ Buffer - A pointer to the buffer to read the data into.
+
+Returns:
+
+ EFI_SUCCESS - ReadSize bytes of data were read into Buffer from the PE/COFF file starting at FileOffset
+
+--*/
+{
+ CHAR8 *Destination8;
+ CHAR8 *Source8;
+ UINT32 Length;
+
+ Destination8 = Buffer;
+ Source8 = (CHAR8 *) ((UINTN) FileHandle + FileOffset);
+ Length = *ReadSize;
+ while (Length--) {
+ *(Destination8++) = *(Source8++);
+ }
+
+ return EFI_SUCCESS;
+}
diff --git a/Source/PeiRebase/PeiRebaseExe.h b/Source/PeiRebase/PeiRebaseExe.h
new file mode 100644
index 0000000..b05baef
--- /dev/null
+++ b/Source/PeiRebase/PeiRebaseExe.h
@@ -0,0 +1,155 @@
+/*++
+
+Copyright (c) 1999-2006 Intel Corporation. All rights reserved
+This program and the accompanying materials are licensed and made available
+under the terms and conditions of the BSD License which accompanies this
+distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+
+Module Name:
+
+ PeiRebaseExe.h
+
+Abstract:
+
+ Definitions for the PeiRebase exe utility.
+
+--*/
+
+#ifndef _EFI_PEIM_FIXUP_EXE_H
+#define _EFI_PEIM_FIXUP_EXE_H
+
+#include <Common/FirmwareVolumeImageFormat.h>
+#include <Common/FirmwareFileSystem.h>
+#include <Common/FirmwareVolumeHeader.h>
+#include <Common/MultiPhase.h>
+
+//
+// Utility Name
+//
+#define UTILITY_NAME "PeiRebase"
+
+//
+// Utility version information
+//
+#define UTILITY_MAJOR_VERSION 0
+#define UTILITY_MINOR_VERSION 1
+#define UTILITY_DATE __DATE__
+
+//
+// The maximum number of arguments accepted from the command line.
+//
+#define MAX_ARGS 9
+
+//
+// The file copy buffer size
+//
+#define FILE_COPY_BUFFER_SIZE 512
+
+//
+// The function that displays general utility information
+//
+VOID
+PrintUtilityInfo (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ None
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+//
+// The function that displays the utility usage message.
+//
+VOID
+PrintUsage (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ None
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+//
+// Internal function declarations
+//
+EFI_STATUS
+FfsRebaseImageRead (
+ IN VOID *FileHandle,
+ IN UINTN FileOffset,
+ IN OUT UINT32 *ReadSize,
+ OUT VOID *Buffer
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ FileHandle - GC_TODO: add argument description
+ FileOffset - GC_TODO: add argument description
+ ReadSize - GC_TODO: add argument description
+ Buffer - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+FfsRebase (
+ IN OUT EFI_FFS_FILE_HEADER *FfsFile,
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,
+ IN FILE *MapFile OPTIONAL
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ FfsFile - GC_TODO: add argument description
+ BaseAddress - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+#endif
diff --git a/Source/PeiRebase/build.xml b/Source/PeiRebase/build.xml
new file mode 100644
index 0000000..7c719b7
--- /dev/null
+++ b/Source/PeiRebase/build.xml
@@ -0,0 +1,108 @@
+<?xml version="1.0" ?>
+<!--
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+-->
+<project default="GenTool" basedir=".">
+<!--
+ EDK PeiRebase Tool
+ Copyright (c) 2006, Intel Corporation
+-->
+ <property name="ToolName" value="PeiRebase"/>
+ <property name="FileSet" value="*.c"/>
+
+ <taskdef resource="net/sf/antcontrib/antlib.xml"/>
+
+ <property name="LINK_OUTPUT_TYPE" value="static"/>
+ <property name="BUILD_DIR" value="${PACKAGE_DIR}/${ToolName}/tmp"/>
+
+ <target name="GenTool" depends="init, Tool">
+ <echo message="The EDK Tool: ${ToolName} build has completed"/>
+ </target>
+
+ <target name="Tool" depends="init, PeiRebase_Ia32, PeiRebase_Ipf, PeiRebase_X64"/>
+
+ <target name="init">
+ <echo message="Building the EDK Tool: ${ToolName}"/>
+ <mkdir dir="${BUILD_DIR}"/>
+ </target>
+
+ <target name="PeiRebase_Ia32" depends="init">
+ <cc name="${ToolChain}" objdir="${BUILD_DIR}"
+ outfile="${BIN_DIR}/${ToolName}_Ia32"
+ outtype="executable"
+ debug="true"
+ optimize="speed">
+ <compilerarg value="${ExtraArgus}" if="ExtraArgus" />
+
+ <fileset dir="${basedir}/${ToolName}"
+ includes="${FileSet}"/>
+
+ <includepath path="${PACKAGE_DIR}/Include"/>
+ <includepath path="${PACKAGE_DIR}/Include/Ia32"/>
+ <includepath path="${PACKAGE_DIR}/Common"/>
+ <libset dir="${LIB_DIR}" libs="CommonTools PeCoffLoader_Ia32"/>
+ </cc>
+ </target>
+
+ <target name="PeiRebase_Ipf" depends="init">
+ <cc name="${ToolChain}" objdir="${BUILD_DIR}"
+ outfile="${BIN_DIR}/${ToolName}_Ipf"
+ outtype="executable"
+ debug="true"
+ optimize="speed">
+ <compilerarg value="${ExtraArgus}" if="ExtraArgus" />
+ <fileset dir="${basedir}/${ToolName}"
+ includes="${FileSet}"/>
+
+ <includepath path="${PACKAGE_DIR}/Include"/>
+ <includepath path="${PACKAGE_DIR}/Include/Ia32"/>
+ <includepath path="${PACKAGE_DIR}/Common"/>
+ <libset dir="${LIB_DIR}" libs="CommonTools PeCoffLoader_Ipf"/>
+ </cc>
+ </target>
+
+ <target name="PeiRebase_X64" depends="init">
+ <cc name="${ToolChain}" objdir="${BUILD_DIR}"
+ outfile="${BIN_DIR}/${ToolName}_X64"
+ outtype="executable"
+ debug="true"
+ optimize="speed">
+ <compilerarg value="${ExtraArgus}" if="ExtraArgus" />
+ <fileset dir="${basedir}/${ToolName}"
+ includes="${FileSet}" />
+
+ <includepath path="${PACKAGE_DIR}/Include"/>
+ <includepath path="${PACKAGE_DIR}/Include/Ia32"/>
+ <includepath path="${PACKAGE_DIR}/Common"/>
+ <libset dir="${LIB_DIR}" libs="CommonTools PeCoffLoader_X64"/>
+ </cc>
+ </target>
+
+ <target name="clean">
+ <echo message="Removing Intermediate Files Only"/>
+ <delete>
+ <fileset dir="${BUILD_DIR}" includes="*.obj"/>
+ </delete>
+ </target>
+
+ <target name="cleanall">
+ <echo message="Removing Object Files and the Executable: ${ToolName}_*${ext_exe}"/>
+ <delete failonerror="false" quiet="true" includeEmptyDirs="true">
+ <fileset dir="${BUILD_DIR}"/>
+ <fileset file="${BIN_DIR}/${ToolName}_Ia32${ext_exe}"/>
+ <fileset file="${BIN_DIR}/${ToolName}_Ipf${ext_exe}"/>
+ <fileset file="${BIN_DIR}/${ToolName}_X64${ext_exe}"/>
+ <fileset file="${BIN_DIR}/${ToolName}_Ia32.pdb"/>
+ <fileset file="${BIN_DIR}/${ToolName}_Ipf.pdb"/>
+ <fileset file="${BIN_DIR}/${ToolName}_X64.pdb"/>
+ </delete>
+ </target>
+
+</project>
diff --git a/Source/SecApResetVectorFixup/SecApResetVectorFixup.c b/Source/SecApResetVectorFixup/SecApResetVectorFixup.c
new file mode 100644
index 0000000..4426457
--- /dev/null
+++ b/Source/SecApResetVectorFixup/SecApResetVectorFixup.c
@@ -0,0 +1,363 @@
+/*++
+
+Copyright (c) 2004-2006 Intel Corporation. All rights reserved
+This program and the accompanying materials are licensed and made available
+under the terms and conditions of the BSD License which accompanies this
+distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+
+Module Name:
+
+ SecApResetVectorFixup.c
+
+Abstract:
+
+ This utility is part of build process for IA32 Fvrecovery.fv whose total size
+ is larger than 128kB so that we cannot use GenFvImage utility to put Ap reset
+ vector at the zero vector of Fv header.
+
+ PEI FV after using the tool
+
+ -------------------------
+ |zzz |
+ | |
+ | |
+ | FFS |
+ | |
+ | |
+ | |
+ |---------------------- |
+ | PAD |
+ | |
+ |.......................| ---
+ | | |
+ |xxx | | 128K
+ |---------------------- | |
+ | VTF (SEC) | |
+ ------------------------- ---
+
+ 1. zzz --> Zero vector, which is beyond the 128K limited address space
+ 2. xxx --> AP reset vector at 4K alignment below 128K and it is in the PAD
+ file area.
+ 3. After the build process ,the PAD guid is changed to a new GUID to avoid
+ the PAD definition confusing. If there is some problem, try to disable
+ UpdatePadFileGuid
+
+
+
+--*/
+
+#include "SecApResetVectorFixup.h"
+
+
+EFI_GUID DefaultFvPadFileNameGuid = { 0x78f54d4, 0xcc22, 0x4048, 0x9e, 0x94, 0x87, 0x9c, 0x21, 0x4d, 0x56, 0x2f };
+EFI_GUID NewFvPadFileNameGuid = { 0x145372bc, 0x66b9, 0x476d, 0x81, 0xbc, 0x21, 0x27, 0xc3, 0x76, 0xbb, 0x66 };
+
+//
+// jmp 0xf000:0xffd0 (0xFFFFFFD0)
+//
+UINT8 ApResetVector[5] = {0xEA, 0xD0, 0xFF, 0x00, 0xF0};
+
+VOID
+PrintUtilityInfo (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Displays the standard utility information to SDTOUT
+
+Arguments:
+
+ None
+
+Returns:
+
+ None
+
+--*/
+{
+ printf (
+ "%s - Tiano IA32 SEC Ap Reset Vector Fixup Utility."" Version %i.%i\n\n",
+ UTILITY_NAME,
+ UTILITY_MAJOR_VERSION,
+ UTILITY_MINOR_VERSION
+ );
+}
+
+VOID
+PrintUsage (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Displays the utility usage syntax to STDOUT
+
+Arguments:
+
+ None
+
+Returns:
+
+ None
+
+--*/
+{
+ printf ("Usage: %s InputFvrecoveryFile OutputFvrecoveryFile\n", UTILITY_NAME);
+ printf (" Where:\n");
+ printf ("\tInputFvrecoveryFile - Name of the IA32 input Fvrecovery.fv file.\n");
+ printf ("\tOutputFvrecoveryFile - Name of the IA32 output Fvrecovery.fv file.\n");
+}
+
+
+VOID
+UpdatePadFileGuid (
+ IN EFI_FIRMWARE_VOLUME_HEADER *FvHeader,
+ IN EFI_FFS_FILE_HEADER *FileHeader,
+ IN UINT32 FileLength,
+ IN OUT EFI_GUID *Guid
+ )
+/*++
+
+Routine Description:
+
+ Update the Pad File Guid to change it to other guid and update
+ the checksum
+
+Arguments:
+ FvHeader - EFI_FIRMWARE_VOLUME_HEADER
+ FileHeader - The FFS PAD file header.
+ FileLength - The FFS PAD file length.
+ Guid - The Guid to compare and if it is PAD Guid, update it to new Guid
+Returns:
+ VOID
+--*/
+
+{
+ if ((CompareGuid (Guid, (EFI_GUID *)&DefaultFvPadFileNameGuid)) == 0) {
+ //
+ // Set new Pad file guid
+ //
+ memcpy (Guid, &NewFvPadFileNameGuid, sizeof (EFI_GUID));
+
+
+
+ FileHeader->Type = EFI_FV_FILETYPE_FFS_PAD;
+ FileHeader->Attributes = 0;
+ //
+ // Fill in checksums and state, must be zero during checksum calculation.
+ //
+ FileHeader->IntegrityCheck.Checksum.Header = 0;
+ FileHeader->IntegrityCheck.Checksum.File = 0;
+ FileHeader->State = 0;
+ FileHeader->IntegrityCheck.Checksum.Header = CalculateChecksum8 ((UINT8 *) FileHeader, sizeof (EFI_FFS_FILE_HEADER));
+ if (FileHeader->Attributes & FFS_ATTRIB_CHECKSUM) {
+ FileHeader->IntegrityCheck.Checksum.File = CalculateChecksum8 ((UINT8 *) FileHeader, FileLength);
+ } else {
+ FileHeader->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM;
+ }
+
+ FileHeader->State = EFI_FILE_HEADER_CONSTRUCTION | EFI_FILE_HEADER_VALID | EFI_FILE_DATA_VALID;
+
+ if (FvHeader->Attributes & EFI_FVB_ERASE_POLARITY) {
+ FileHeader->State = (UINT8)~(FileHeader->State);
+ }
+ }
+
+}
+
+
+STATUS
+main (
+ IN INTN argc,
+ IN CHAR8 **argv
+ )
+/*++
+
+Routine Description:
+
+ Main function.
+
+Arguments:
+
+ argc - Number of command line parameters.
+ argv - Array of pointers to parameter strings.
+
+Returns:
+ STATUS_SUCCESS - Utility exits successfully.
+ STATUS_ERROR - Some error occurred during execution.
+
+--*/
+{
+ FILE *FpIn;
+ FILE *FpOut;
+ UINT32 FvrecoveryFileSize;
+ UINT8 *FileBuffer;
+ UINT8 *FileBufferRaw;
+ UINT64 FvLength;
+ UINT32 Offset;
+ UINT32 FileLength;
+ UINT32 FileOccupiedSize;
+ EFI_FIRMWARE_VOLUME_HEADER *FvHeader;
+ EFI_FFS_FILE_HEADER *FileHeader;
+ EFI_GUID *TempGuid;
+ UINT8 *FixPoint;
+ UINT32 TempResult;
+ UINT32 Index;
+ UINT32 IpiVector;
+
+ TempGuid = NULL;
+ SetUtilityName (UTILITY_NAME);
+
+ //
+ // Display utility information
+ //
+ PrintUtilityInfo ();
+
+ //
+ // Verify the correct number of arguments
+ //
+ if (argc != MAX_ARGS) {
+ Error (NULL, 0, 0, "invalid number of input parameters specified", NULL);
+ PrintUsage ();
+ return STATUS_ERROR;
+ }
+ //
+ // Open the Input Fvrecovery.fv file
+ //
+ if ((FpIn = fopen (argv[1], "rb")) == NULL) {
+ Error (NULL, 0, 0, "Unable to open file", argv[1]);
+ return STATUS_ERROR;
+ }
+ //
+ // Get the Input Fvrecovery.fv file size
+ //
+ fseek (FpIn, 0, SEEK_END);
+ FvrecoveryFileSize = ftell (FpIn);
+ //
+ // Read the contents of input file to memory buffer
+ //
+ FileBuffer = NULL;
+ FileBufferRaw = NULL;
+ FileBufferRaw = (UINT8 *) malloc (FvrecoveryFileSize + 0x10000);
+ if (NULL == FileBufferRaw) {
+ Error (NULL, 0, 0, "No sufficient memory to allocate!", NULL);
+ fclose (FpIn);
+ return STATUS_ERROR;
+ }
+ TempResult = 0x10000 - ((UINT32)FileBufferRaw & 0x0FFFF);
+ FileBuffer = (UINT8 *)((UINT32)FileBufferRaw + TempResult);
+ fseek (FpIn, 0, SEEK_SET);
+ TempResult = fread (FileBuffer, 1, FvrecoveryFileSize, FpIn);
+ if (TempResult != FvrecoveryFileSize) {
+ Error (NULL, 0, 0, "Read input file error!", NULL);
+ free ((VOID *)FileBufferRaw);
+ fclose (FpIn);
+ return STATUS_ERROR;
+ }
+ //
+ // Close the input Fvrecovery.fv file
+ //
+ fclose (FpIn);
+ //
+ // Find the pad FFS file
+ //
+ FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *)FileBuffer;
+ FvLength = FvHeader->FvLength;
+ FileHeader = (EFI_FFS_FILE_HEADER *)(FileBuffer + FvHeader->HeaderLength);
+ FileLength = (*(UINT32 *)(FileHeader->Size)) & 0x00FFFFFF;
+ FileOccupiedSize = GETOCCUPIEDSIZE(FileLength, 8);
+ Offset = (UINT32)FileHeader - (UINT32)FileBuffer;
+
+ while (Offset < FvLength) {
+ TempGuid = (EFI_GUID *)&(FileHeader->Name);
+ FileLength = (*(UINT32 *)(FileHeader->Size)) & 0x00FFFFFF;
+ FileOccupiedSize = GETOCCUPIEDSIZE(FileLength, 8);
+ if ((CompareGuid (TempGuid, (EFI_GUID *)&DefaultFvPadFileNameGuid)) == 0) {
+ break;
+ }
+ FileHeader = (EFI_FFS_FILE_HEADER *)((UINT32)FileHeader + FileOccupiedSize);
+ Offset = (UINT32)FileHeader - (UINT32)FileBuffer;
+ }
+
+ if (Offset >= FvLength) {
+ Error (NULL, 0, 0, "No pad file found!", NULL);
+ free ((VOID *)FileBufferRaw);
+ return STATUS_ERROR;
+ }
+ //
+ // Find the position to place Ap reset vector, the offset
+ // between the position and the end of Fvrecovery.fv file
+ // should not exceed 128kB to prevent Ap reset vector from
+ // outside legacy E and F segment
+ //
+ FixPoint = (UINT8 *)(FileHeader + sizeof(EFI_FFS_FILE_HEADER));
+ TempResult = 0x1000 - ((UINT32)FixPoint & 0x0FFF);
+ FixPoint +=TempResult;
+ if (((UINT32)FixPoint - (UINT32)FileHeader + 5) > FileOccupiedSize) {
+ Error (NULL, 0, 0, "No appropriate space in pad file to add Ap reset vector!", NULL);
+ free ((VOID *)FileBufferRaw);
+ return STATUS_ERROR;
+ }
+ while (((UINT32)FixPoint - (UINT32)FileHeader + 5) <= FileOccupiedSize) {
+ FixPoint += 0x1000;
+ }
+ FixPoint -= 0x1000;
+ if ((UINT32)FvHeader + FvLength - (UINT32)FixPoint > 0x20000) {
+ Error (NULL, 0, 0, "The position to place Ap reset vector is not in E and F segment!", NULL);
+ free ((VOID *)FileBufferRaw);
+ return STATUS_ERROR;
+ }
+ //
+ // Fix up Ap reset vector and calculate the IPI vector
+ //
+ for (Index = 0; Index < 5; Index++) {
+ FixPoint[Index] = ApResetVector[Index];
+ }
+ TempResult = 0x0FFFFFFFF - ((UINT32)FvHeader + (UINT32)FvLength - 1 - (UINT32)FixPoint);
+ TempResult >>= 12;
+ IpiVector = TempResult & 0x0FF;
+
+
+ UpdatePadFileGuid (FvHeader, FileHeader, FileLength, TempGuid);
+
+ //
+ // Open the output Fvrecovery.fv file
+ //
+ if ((FpOut = fopen (argv[2], "w+b")) == NULL) {
+ Error (NULL, 0, 0, "Unable to open file", argv[2]);
+ free ((VOID *)FileBufferRaw);
+ return STATUS_ERROR;
+ }
+ //
+ // Write the output Fvrecovery.fv file
+ //
+ if ((fwrite (FileBuffer, 1, FvrecoveryFileSize, FpOut)) != FvrecoveryFileSize) {
+ Error (NULL, 0, 0, "Write output file error!", NULL);
+ free ((VOID *)FileBufferRaw);
+ return STATUS_ERROR;
+ }
+ //
+ //
+ //
+ fseek (FpOut, -8, SEEK_END);
+ if ((fwrite (&IpiVector, 1, sizeof(UINT32), FpOut)) != sizeof(UINT32)) {
+ Error (NULL, 0, 0, "Write output file error!", NULL);
+ free ((VOID *)FileBufferRaw);
+ return STATUS_ERROR;
+ }
+ //
+ // Close the output Fvrecovery.fv file
+ //
+ fclose (FpOut);
+ free ((VOID *)FileBufferRaw);
+ return STATUS_SUCCESS;
+}
+
diff --git a/Source/SecApResetVectorFixup/SecApResetVectorFixup.h b/Source/SecApResetVectorFixup/SecApResetVectorFixup.h
new file mode 100644
index 0000000..6d234e3
--- /dev/null
+++ b/Source/SecApResetVectorFixup/SecApResetVectorFixup.h
@@ -0,0 +1,104 @@
+/*++
+
+Copyright (c) 1999-2006 Intel Corporation. All rights reserved
+This program and the accompanying materials are licensed and made available
+under the terms and conditions of the BSD License which accompanies this
+distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+
+Module Name:
+
+ SecApResetVectorFixup.h
+
+Abstract:
+
+ Definitions for the SecApResetVectorFixup utility.
+
+--*/
+
+#ifndef _SEC_AP_RESET_VECTOR_FIXUP_H
+#define _SEC_AP_RESET_VECTOR_FIXUP_H
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <Common/UefiBaseTypes.h>
+#include <Common/EfiImage.h>
+#include <Common/FirmwareVolumeImageFormat.h>
+#include <Common/FirmwareFileSystem.h>
+#include <Common/FirmwareVolumeHeader.h>
+
+#include "EfiUtilityMsgs.c"
+#include "CommonLib.h"
+
+
+//
+// Utility Name
+//
+#define UTILITY_NAME "SecApResetVectorFixup"
+
+//
+// Utility version information
+//
+#define UTILITY_MAJOR_VERSION 0
+#define UTILITY_MINOR_VERSION 1
+#define UTILITY_DATE __DATE__
+
+//
+// The maximum number of arguments accepted from the command line.
+//
+#define MAX_ARGS 3
+#define BUF_SIZE (8 * 1024)
+
+#define GETOCCUPIEDSIZE(ActualSize, Alignment) \
+ (ActualSize) + (((Alignment) - ((ActualSize) & ((Alignment) - 1))) & ((Alignment) - 1))
+
+
+VOID
+PrintUtilityInfo (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Displays the standard utility information to SDTOUT
+
+Arguments:
+
+ None
+
+Returns:
+
+ None
+
+--*/
+;
+
+VOID
+PrintUsage (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Displays the utility usage syntax to STDOUT
+
+Arguments:
+
+ None
+
+Returns:
+
+ None
+
+--*/
+;
+
+
+#endif
diff --git a/Source/SecApResetVectorFixup/build.xml b/Source/SecApResetVectorFixup/build.xml
new file mode 100644
index 0000000..5148d9d
--- /dev/null
+++ b/Source/SecApResetVectorFixup/build.xml
@@ -0,0 +1,69 @@
+<?xml version="1.0" ?>
+<!--
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+-->
+<project default="GenTool" basedir=".">
+<!--
+ EDK SecApResetVectorFixup Tool
+ Copyright (c) 2006, Intel Corporation
+-->
+ <property name="ToolName" value="SecApResetVectorFixup"/>
+ <property name="FileSet" value="*.c"/>
+
+ <taskdef resource="net/sf/antcontrib/antlib.xml"/>
+
+ <property name="LINK_OUTPUT_TYPE" value="static"/>
+ <property name="BUILD_DIR" value="${PACKAGE_DIR}/${ToolName}/tmp"/>
+
+ <target name="GenTool" depends="init, Tool">
+ <echo message="The EDK Tool: ${ToolName} build has completed"/>
+ </target>
+
+ <target name="init">
+ <echo message="Building the EDK Tool: ${ToolName}"/>
+ <mkdir dir="${BUILD_DIR}"/>
+ </target>
+
+ <target name="Tool" depends="init">
+ <cc name="${ToolChain}" objdir="${BUILD_DIR}"
+ outfile="${BIN_DIR}/${ToolName}"
+ outtype="executable"
+ optimize="speed"
+ debug="true">
+
+ <fileset dir="${basedir}/${ToolName}"
+ includes="${FileSet}"
+ defaultexcludes="TRUE"
+ excludes="*.xml *.inf"/>
+
+ <includepath path="${PACKAGE_DIR}/Include"/>
+ <includepath path="${PACKAGE_DIR}/Include/${HostArch}"/>
+ <includepath path="${PACKAGE_DIR}/Common"/>
+ <libset dir="${LIB_DIR}" libs="CommonTools"/>
+ </cc>
+ </target>
+
+ <target name="clean">
+ <echo message="Removing Intermediate Files Only"/>
+ <delete>
+ <fileset dir="${BUILD_DIR}" includes="*.obj"/>
+ </delete>
+ </target>
+
+ <target name="cleanall">
+ <echo message="Removing Object Files and the Executable: ${ToolName}${ext_exe}"/>
+ <delete failonerror="false" quiet="true" includeEmptyDirs="true">
+ <fileset dir="${BUILD_DIR}"/>
+ <fileset file="${BIN_DIR}/${ToolName}${ext_exe}"/>
+ <fileset file="${BIN_DIR}/${ToolName}.pdb"/>
+ </delete>
+ </target>
+
+</project>
diff --git a/Source/SecFixup/SecFixup.c b/Source/SecFixup/SecFixup.c
new file mode 100644
index 0000000..c2d46a1
--- /dev/null
+++ b/Source/SecFixup/SecFixup.c
@@ -0,0 +1,362 @@
+/*++
+
+Copyright (c) 1999-2006 Intel Corporation. All rights reserved
+This program and the accompanying materials are licensed and made available
+under the terms and conditions of the BSD License which accompanies this
+distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+
+Module Name:
+
+ SecFixup.c
+
+Abstract:
+
+ This utility is part of build process for IA32 SEC FFS file.
+
+ It fixup the reset vector data. The reset vector data binary file
+ will be wrapped as a RAW section and be located immediately after
+ the PE/TE section.
+
+ The SEC EXE file can be either PE or TE file.
+
+--*/
+
+#include <stdio.h>
+
+#include <Common/UefiBaseTypes.h>
+#include <Common/EfiImage.h>
+#include <Common/FirmwareVolumeImageFormat.h>
+
+#include "EfiUtilityMsgs.c"
+#include "SecFixup.h"
+
+VOID
+PrintUtilityInfo (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Displays the standard utility information to SDTOUT
+
+Arguments:
+
+ None
+
+Returns:
+
+ None
+
+--*/
+{
+ printf (
+ "%s - Tiano IA32 SEC Fixup Utility."" Version %i.%i\n\n",
+ UTILITY_NAME,
+ UTILITY_MAJOR_VERSION,
+ UTILITY_MINOR_VERSION
+ );
+}
+
+VOID
+PrintUsage (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Displays the utility usage syntax to STDOUT
+
+Arguments:
+
+ None
+
+Returns:
+
+ None
+
+--*/
+{
+ printf ("Usage: %s SecExeFile ResetVectorDataFile OutputFile\n", UTILITY_NAME);
+ printf (" Where:\n");
+ printf ("\tSecExeFile - Name of the IA32 SEC EXE file.\n");
+ printf ("\tResetVectorDataFile - Name of the reset vector data binary file.\n");
+ printf ("\tOutputFileName - Name of the output file.\n\n");
+}
+
+STATUS
+main (
+ IN INTN argc,
+ IN CHAR8 **argv
+ )
+/*++
+
+Routine Description:
+
+ Main function.
+
+Arguments:
+
+ argc - Number of command line parameters.
+ argv - Array of pointers to parameter strings.
+
+Returns:
+ STATUS_SUCCESS - Utility exits successfully.
+ STATUS_ERROR - Some error occurred during execution.
+
+--*/
+{
+ FILE *FpIn;
+
+ FILE *FpOut;
+ UINT32 AddressOfEntryPoint;
+ INT32 DestRel;
+ STATUS Status;
+ UINT32 SecFileSize;
+
+ SetUtilityName (UTILITY_NAME);
+
+ //
+ // Display utility information
+ //
+ PrintUtilityInfo ();
+
+ //
+ // Verify the correct number of arguments
+ //
+ if (argc != MAX_ARGS) {
+ Error (NULL, 0, 0, "invalid number of input parameters specified", NULL);
+ PrintUsage ();
+ return STATUS_ERROR;
+ }
+ //
+ // Open the SEC exe file
+ //
+ if ((FpIn = fopen (argv[1], "rb")) == NULL) {
+ Error (NULL, 0, 0, "Unable to open file", argv[1]);
+ return STATUS_ERROR;
+ }
+ //
+ // Get the entry point of the EXE file
+ //
+ Status = GetEntryPoint (FpIn, &AddressOfEntryPoint);
+ if (Status != STATUS_SUCCESS) {
+ fclose (FpIn);
+ return STATUS_ERROR;
+ }
+ //
+ // Get the SEC file size
+ //
+ fseek (FpIn, 0, SEEK_END);
+ SecFileSize = ftell (FpIn);
+
+ //
+ // Close the SEC file
+ //
+ fclose (FpIn);
+
+ //
+ // Open the reset vector data file
+ //
+ if ((FpIn = fopen (argv[2], "rb")) == NULL) {
+ Error (NULL, 0, 0, "Unable to open file", argv[2]);
+ return STATUS_ERROR;
+ }
+ //
+ // Open the output file
+ //
+ if ((FpOut = fopen (argv[3], "w+b")) == NULL) {
+ Error (NULL, 0, 0, "Unable to open file", argv[3]);
+ fclose (FpIn);
+ return STATUS_ERROR;
+ }
+ //
+ // Copy the input file to the output file
+ //
+ if (CopyFile (FpIn, FpOut) != STATUS_SUCCESS) {
+ fclose (FpIn);
+ fclose (FpOut);
+ return STATUS_ERROR;
+ }
+ //
+ // Close the reset vector data file
+ //
+ fclose (FpIn);
+
+ //
+ // Fix the destination relative in the jmp instruction
+ // in the reset vector data structure
+ //
+ fseek (FpOut, -DEST_REL_OFFSET, SEEK_END);
+ DestRel = AddressOfEntryPoint - (SecFileSize + sizeof (EFI_COMMON_SECTION_HEADER) + (UINT32) (ftell (FpOut)) + 2);
+ if (DestRel <= -65536) {
+ Error (NULL, 0, 0, "The SEC EXE file size is too big", NULL);
+ fclose (FpOut);
+ return STATUS_ERROR;
+ }
+
+ if (fwrite (&DestRel, sizeof (UINT16), 1, FpOut) != 1) {
+ Error (NULL, 0, 0, "Failed to write to the output file", NULL);
+ fclose (FpOut);
+ return STATUS_ERROR;
+ }
+ //
+ // Close the output file
+ //
+ fclose (FpOut);
+
+ return STATUS_SUCCESS;
+}
+
+STATUS
+GetEntryPoint (
+ IN FILE *ExeFile,
+ OUT UINT32 *EntryPoint
+ )
+/*++
+
+Routine Description:
+
+ Get the address of the entry point of a PE/TE file.
+
+Arguments:
+
+ PeFile - File pointer to the specified PE/TE file.
+ EntryPoint - Buffer for the address of the entry point to be returned.
+
+Returns:
+ STATUS_SUCCESS - Function completed successfully.
+ STATUS_ERROR - Error occured.
+
+--*/
+// GC_TODO: ExeFile - add argument and description to function comment
+{
+ EFI_IMAGE_DOS_HEADER DosHeader;
+ EFI_IMAGE_NT_HEADERS32 NtHeader;
+ EFI_TE_IMAGE_HEADER TeHeader;
+
+ //
+ // Check if it is a TE file
+ //
+ fseek (ExeFile, 0, SEEK_SET);
+ //
+ // Attempt to read the TE header
+ //
+ if (fread (&TeHeader, sizeof (TeHeader), 1, ExeFile) == 1) {
+ if (TeHeader.Signature == EFI_TE_IMAGE_HEADER_SIGNATURE) {
+ if (TeHeader.Machine != EFI_IMAGE_MACHINE_IA32) {
+ Error (NULL, 0, 0, "The SEC file is PE but is not PE32 for IA32", NULL);
+ return STATUS_ERROR;
+ }
+
+ *EntryPoint = TeHeader.AddressOfEntryPoint + sizeof (EFI_TE_IMAGE_HEADER) - TeHeader.StrippedSize;
+ return STATUS_SUCCESS;
+ }
+ }
+ //
+ // Check if it is a PE file
+ //
+ fseek (ExeFile, 0, SEEK_SET);
+ //
+ // Attempt to read the DOS header
+ //
+ if (fread (&DosHeader, sizeof (DosHeader), 1, ExeFile) != 1) {
+ goto InvalidFile;
+ }
+ //
+ // Check the magic number
+ //
+ if (DosHeader.e_magic != EFI_IMAGE_DOS_SIGNATURE) {
+ goto InvalidFile;
+ }
+ //
+ // Position into the file and read the NT PE header
+ //
+ fseek (ExeFile, (long) DosHeader.e_lfanew, SEEK_SET);
+ if (fread (&NtHeader, sizeof (NtHeader), 1, ExeFile) != 1) {
+ goto InvalidFile;
+ }
+ //
+ // Check the PE signature in the header
+ //
+ if (NtHeader.Signature != EFI_IMAGE_NT_SIGNATURE) {
+ goto InvalidFile;
+ }
+ //
+ // Make sure the PE file is PE32 for IA32
+ //
+ if (NtHeader.FileHeader.Machine != EFI_IMAGE_MACHINE_IA32 ||
+ NtHeader.OptionalHeader.Magic != EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
+ ) {
+ Error (NULL, 0, 0, "The SEC file is PE but is not PE32 for IA32", NULL);
+ return STATUS_ERROR;
+ }
+ //
+ // Get the entry point from the optional header
+ //
+ *EntryPoint = NtHeader.OptionalHeader.AddressOfEntryPoint;
+ return STATUS_SUCCESS;
+
+InvalidFile:
+ Error (NULL, 0, 0, "The SEC file is neither PE nor TE file", NULL);
+ return STATUS_ERROR;
+}
+
+STATUS
+CopyFile (
+ FILE *FpIn,
+ FILE *FpOut
+ )
+/*++
+
+Routine Description:
+
+ Copy file.
+
+Arguments:
+
+ FpIn - File pointer to the source file.
+ FpOut - File pointer to the destination file.
+
+Returns:
+ STATUS_SUCCESS - Function completed successfully.
+ STATUS_ERROR - Error occured.
+
+--*/
+{
+ INTN FileSize;
+
+ INTN Offset;
+
+ INTN Length;
+ UINT8 Buffer[BUF_SIZE];
+
+ fseek (FpIn, 0, SEEK_END);
+ FileSize = ftell (FpIn);
+
+ fseek (FpIn, 0, SEEK_SET);
+ fseek (FpOut, 0, SEEK_SET);
+
+ Offset = 0;
+ while (Offset < FileSize) {
+ Length = sizeof (Buffer);
+ if (FileSize - Offset < Length) {
+ Length = FileSize - Offset;
+ }
+
+ if (fread (Buffer, Length, 1, FpIn) != 1 || fwrite (Buffer, Length, 1, FpOut) != 1) {
+ Error (NULL, 0, 0, "Copy file error", NULL);
+ return STATUS_ERROR;
+ }
+
+ Offset += Length;
+ }
+
+ return STATUS_SUCCESS;
+}
diff --git a/Source/SecFixup/SecFixup.h b/Source/SecFixup/SecFixup.h
new file mode 100644
index 0000000..3694b15
--- /dev/null
+++ b/Source/SecFixup/SecFixup.h
@@ -0,0 +1,146 @@
+/*++
+
+Copyright (c) 1999-2006 Intel Corporation. All rights reserved
+This program and the accompanying materials are licensed and made available
+under the terms and conditions of the BSD License which accompanies this
+distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+
+Module Name:
+
+ SecFixup.h
+
+Abstract:
+
+ Definitions for the SecFixup utility.
+
+--*/
+
+#ifndef _SEC_FIXUP_H
+#define _SEC_FIXUP_H
+
+//
+// Utility Name
+//
+#define UTILITY_NAME "SecFixup"
+
+//
+// Utility version information
+//
+#define UTILITY_MAJOR_VERSION 0
+#define UTILITY_MINOR_VERSION 1
+#define UTILITY_DATE __DATE__
+
+//
+// The maximum number of arguments accepted from the command line.
+//
+#define MAX_ARGS 4
+
+#define DEST_REL_OFFSET 13
+#define BUF_SIZE (8 * 1024)
+
+//
+// The function that displays general utility information
+//
+VOID
+PrintUtilityInfo (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ None
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+//
+// The function that displays the utility usage message.
+//
+VOID
+PrintUsage (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ None
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+//
+// The function that gets the entry point of a PE/TE file.
+//
+STATUS
+GetEntryPoint (
+ IN FILE *ExeFile,
+ OUT UINT32 *EntryPoint
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ ExeFile - GC_TODO: add argument description
+ EntryPoint - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+//
+// The function that copies a file.
+//
+STATUS
+CopyFile (
+ FILE *FpIn,
+ FILE *FpOut
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ FpIn - GC_TODO: add argument description
+ FpOut - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+#endif
diff --git a/Source/SecFixup/build.xml b/Source/SecFixup/build.xml
new file mode 100644
index 0000000..2abb1da
--- /dev/null
+++ b/Source/SecFixup/build.xml
@@ -0,0 +1,69 @@
+<?xml version="1.0" ?>
+<!--
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+-->
+<project default="GenTool" basedir=".">
+<!--
+ EDK SecFixup Tool
+ Copyright (c) 2006, Intel Corporation
+-->
+ <property name="ToolName" value="SecFixup"/>
+ <property name="FileSet" value="*.c"/>
+
+ <taskdef resource="net/sf/antcontrib/antlib.xml"/>
+
+ <property name="LINK_OUTPUT_TYPE" value="static"/>
+ <property name="BUILD_DIR" value="${PACKAGE_DIR}/${ToolName}/tmp"/>
+
+ <target name="GenTool" depends="init, Tool">
+ <echo message="The EDK Tool: ${ToolName} build has completed!"/>
+ </target>
+
+ <target name="init">
+ <echo message="Building the EDK Tool: ${ToolName}"/>
+ <mkdir dir="${BUILD_DIR}"/>
+ </target>
+
+ <target name="Tool" depends="init">
+ <cc name="${ToolChain}" objdir="${BUILD_DIR}"
+ outfile="${BIN_DIR}/${ToolName}"
+ outtype="executable"
+ optimize="speed"
+ debug="true">
+
+ <fileset dir="${basedir}/${ToolName}"
+ includes="${FileSet}"
+ defaultexcludes="TRUE"
+ excludes="*.xml *.inf"/>
+
+ <includepath path="${PACKAGE_DIR}/Include"/>
+ <includepath path="${PACKAGE_DIR}/Include/${HostArch}"/>
+ <includepath path="${PACKAGE_DIR}/Common"/>
+ <libset dir="${LIB_DIR}" libs="CommonTools"/>
+ </cc>
+ </target>
+
+ <target name="clean">
+ <echo message="Removing Intermediate Files Only"/>
+ <delete>
+ <fileset dir="${BUILD_DIR}" includes="*.obj"/>
+ </delete>
+ </target>
+
+ <target name="cleanall">
+ <echo message="Removing Object Files and the Executable: ${ToolName}${ext_exe}"/>
+ <delete failonerror="false" quiet="true" includeEmptyDirs="true">
+ <fileset dir="${BUILD_DIR}"/>
+ <fileset file="${BIN_DIR}/${ToolName}${ext_exe}"/>
+ <fileset file="${BIN_DIR}/${ToolName}.pdb"/>
+ </delete>
+ </target>
+
+</project>
diff --git a/Source/SetStamp/SetStamp.c b/Source/SetStamp/SetStamp.c
new file mode 100644
index 0000000..539aced
--- /dev/null
+++ b/Source/SetStamp/SetStamp.c
@@ -0,0 +1,475 @@
+/*++
+
+Copyright (c) 2004, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+ SetStamp.c
+
+Abstract:
+ Set Date/Time Stamp of Portable Executable (PE) format file
+
+--*/
+
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+
+#define LINE_MAXLEN 80
+
+void
+PrintUsage (
+ void
+ )
+/*++
+Routine Description:
+ print usage of setstamp command
+
+Arguments:
+ void
+
+Returns:
+ None
+--*/
+{
+ //
+ // print usage of command
+ //
+ printf ("Usage: SetStamp <PE-File> <TIME-File>\n");
+}
+
+int
+GetDateTime (
+ FILE *fp,
+ time_t *ltime
+ )
+/*++
+Routine Description:
+ Read the date and time from TIME file. If the date/time string is
+"NOW NOW", write the current date and time to TIME file and set it to
+ltime. Else, set the date and time of TIME file to ltime.
+
+Arguments:
+ fp - The pointer of TIME file
+ ltime - Date and time
+
+Returns:
+ = 0 - Success
+ = -1 - Failed
+--*/
+{
+ char buffer[LINE_MAXLEN];
+ struct tm stime;
+ struct tm *now;
+
+ if (fgets (buffer, LINE_MAXLEN, fp) == NULL) {
+ printf ("Error: Cannot read TIME file.\n");
+ return -1;
+ }
+ //
+ // compare the value with "NOW NOW", write TIME file if equal
+ //
+ if (strncmp (buffer, "NOW NOW", 7) == 0) {
+ //
+ // get system current time and date
+ //
+ time (ltime);
+
+ now = localtime (ltime);
+ if (now == NULL) {
+ printf ("Error: Cannot get local time.\n");
+ return -1;
+ }
+
+ if (strftime (buffer, LINE_MAXLEN, "%Y-%m-%d %H:%M:%S", now) == 0) {
+ printf ("Error: Cannot format time string.\n");
+ return -1;
+ }
+ //
+ // write TIME file
+ //
+ if (fseek (fp, 0, SEEK_SET) != 0) {
+ printf ("Error: Cannot move location of TIME file.\n");
+ return -1;
+ }
+
+ if (fputs (buffer, fp) == EOF) {
+ printf ("Error: Cannot write time string to TIME file.\n");
+ return -1;
+ }
+ //
+ // ltime has been set as current time and date, return
+ //
+ return 0;
+ }
+ //
+ // get the date and time from buffer
+ //
+ if (6 != sscanf (
+ buffer,
+ "%d-%d-%d %d:%d:%d",
+ &stime.tm_year,
+ &stime.tm_mon,
+ &stime.tm_mday,
+ &stime.tm_hour,
+ &stime.tm_min,
+ &stime.tm_sec
+ )) {
+ printf ("Error: Invaild date or time!\n");
+ return -1;
+ }
+ //
+ // in struct, Month (0 - 11; Jan = 0). So decrease 1 from it
+ //
+ stime.tm_mon -= 1;
+
+ //
+ // in struct, Year (current year minus 1900)
+ // and only the dates can be handled from Jan 1, 1970 to Jan 18, 2038
+ //
+ //
+ // convert 0 -> 100 (2000), 1 -> 101 (2001), ..., 38 -> 138 (2038)
+ //
+ if (stime.tm_year <= 38) {
+ stime.tm_year += 100;
+ }
+ //
+ // convert 1970 -> 70, 2000 -> 100, ...
+ //
+ else if (stime.tm_year >= 1970) {
+ stime.tm_year -= 1900;
+ }
+ //
+ // convert the date and time to time_t format
+ //
+ *ltime = mktime (&stime);
+ if (*ltime == (time_t) - 1) {
+ printf ("Error: Invalid date or time!\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+int
+ReadFromFile (
+ FILE *fp,
+ long offset,
+ void *buffer,
+ int size
+ )
+/*++
+Routine Description:
+ read data from a specified location of file
+
+Arguments:
+ fp - file pointer
+ offset - number of bytes from beginning of file
+ buffer - buffer used to store data
+ size - size of buffer
+
+Returns:
+ = 0 - Success
+ = -1 - Failed
+--*/
+{
+ //
+ // set file pointer to the specified location of file
+ //
+ if (fseek (fp, offset, SEEK_SET) != 0) {
+ printf ("Error: Cannot move the current location of the file.\n");
+ return -1;
+ }
+ //
+ // read data from the file
+ //
+ if (fread (buffer, size, 1, fp) != 1) {
+ printf ("Error: Cannot read data from the file.\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+int
+WriteToFile (
+ FILE *fp,
+ long offset,
+ void *buffer,
+ int size
+ )
+/*++
+Routine Description:
+ write data to a specified location of file
+
+Arguments:
+ fp - file pointer
+ offset - number of bytes from beginning of file
+ buffer - buffer used to store data
+ size - size of buffer
+
+Returns:
+ = 0 - Success
+ = -1 - Failed
+--*/
+{
+ //
+ // set file pointer to the specified location of file
+ //
+ if (fseek (fp, offset, SEEK_SET) != 0) {
+ printf ("Error: Cannot move the current location of the file.\n");
+ return -1;
+ }
+ //
+ // write data to the file
+ //
+ if (fwrite (buffer, size, 1, fp) != 1) {
+ perror ("Error: Cannot write data to the file.\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+int
+SetStamp (
+ FILE *fp,
+ time_t ltime
+ )
+/*++
+Routine Description:
+ set Date/Time Stamp of the file
+
+Arguments:
+ fp - file pointer
+ ltime - time and date
+
+Returns:
+ = 0 - Success
+ = -1 - Failed
+--*/
+{
+ unsigned char header[4];
+ unsigned long offset;
+ unsigned long NumberOfRvaAndSizes;
+ unsigned int nvalue;
+ unsigned long lvalue;
+
+ //
+ // read the header of file
+ //
+ if (ReadFromFile (fp, 0, header, 2) != 0) {
+ return -1;
+ }
+ //
+ // "MZ" -- the header of image file (PE)
+ //
+ if (strncmp ((char *) header, "MZ", 2) != 0) {
+ printf ("Error: Invalid Image file.\n");
+ return -1;
+ }
+ //
+ // At location 0x3C, the stub has the file offset to the
+ // PE signature.
+ //
+ if (ReadFromFile (fp, 0x3C, &offset, 4) != 0) {
+ return -1;
+ }
+ //
+ // read the header of optional
+ //
+ if (ReadFromFile (fp, offset, header, 4) != 0) {
+ return -1;
+ }
+ //
+ // "PE\0\0" -- the signature of optional header
+ //
+ if (strncmp ((char *) header, "PE\0\0", 4) != 0) {
+ printf ("Error: Invalid PE format file.\n");
+ return -1;
+ }
+ //
+ // Add 8 to skip PE signature (4-byte), Machine (2-byte) and
+ // NumberOfSection (2-byte)
+ //
+ offset += 8;
+
+ if (WriteToFile (fp, offset, &ltime, 4) != 0) {
+ return -1;
+ }
+ //
+ // Add 16 to skip COFF file header, and get to optional header.
+ //
+ offset += 16;
+
+ //
+ // Check the magic field, 0x10B for PE32 and 0x20B for PE32+
+ //
+ if (ReadFromFile (fp, offset, &nvalue, 2) != 0) {
+ return -1;
+ }
+ //
+ // If this is PE32 image file, offset of NumberOfRvaAndSizes is 92.
+ // Else it is 108.
+ //
+ switch (nvalue & 0xFFFF) {
+ case 0x10B:
+ offset += 92;
+ break;
+
+ case 0x20B:
+ offset += 108;
+ break;
+
+ default:
+ printf ("Error: Sorry! The Magic value is unknown.\n");
+ return -1;
+ }
+ //
+ // get the value of NumberOfRvaAndSizes
+ //
+ if (ReadFromFile (fp, offset, &NumberOfRvaAndSizes, 4) != 0) {
+ return -1;
+ }
+ //
+ // Date/time stamp exists in Export Table, Import Table, Resource Table,
+ // Debug Table and Delay Import Table. And in Import Table and Delay Import
+ // Table, it will be set when bound. So here only set the date/time stamp
+ // of Export Table, Resource Table and Debug Table.
+ //
+ //
+ // change date/time stamp of Export Table, the offset of Export Table
+ // is 4 + 0 * 8 = 4. And the offset of stamp is 4.
+ //
+ if (NumberOfRvaAndSizes >= 1) {
+ if (ReadFromFile (fp, offset + 4, &lvalue, 4) != 0) {
+ return -1;
+ }
+
+ if (lvalue != 0) {
+ if (WriteToFile (fp, lvalue + 4, &ltime, 4) != 0) {
+ return -1;
+ }
+ }
+ }
+ //
+ // change date/time stamp of Resource Table, the offset of Resource Table
+ // is 4 + 2 * 8 = 20. And the offset of stamp is 4.
+ //
+ if (NumberOfRvaAndSizes >= 3) {
+ if (ReadFromFile (fp, offset + 20, &lvalue, 4) != 0) {
+ return -1;
+ }
+
+ if (lvalue != 0) {
+ if (WriteToFile (fp, lvalue + 4, &ltime, 4) != 0) {
+ return -1;
+ }
+ }
+ }
+ //
+ // change date/time stamp of Debug Table, offset of Debug Table
+ // is 4 + 6 * 8 = 52. And the offset of stamp is 4.
+ //
+ if (NumberOfRvaAndSizes >= 7) {
+ if (ReadFromFile (fp, offset + 52, &lvalue, 4) != 0) {
+ return -1;
+ }
+
+ if (lvalue != 0) {
+ if (WriteToFile (fp, lvalue + 4, &ltime, 4) != 0) {
+ return -1;
+ }
+ }
+ //
+ // change the date/time stamp of Debug Data
+ //
+ if (ReadFromFile (fp, lvalue + 24, &lvalue, 4) != 0) {
+ return -1;
+ }
+ //
+ // get the signature of debug data
+ //
+ if (ReadFromFile (fp, lvalue, header, 2) != 0) {
+ return -1;
+ }
+ //
+ // "NB" - the signature of Debug Data
+ // Need Review: (From Spec. is "NB05", From .dll is "NB10")
+ //
+ if (strncmp ((char *) header, "NB", 2) == 0) {
+ if (WriteToFile (fp, lvalue + 8, &ltime, 4) != 0) {
+ return -1;
+ }
+ }
+ }
+
+ return 0;
+}
+
+int
+main (
+ int argc,
+ char *argv[]
+ )
+{
+ FILE *fp;
+ time_t ltime;
+
+ //
+ // check the number of parameters
+ //
+ if (argc != 3) {
+ PrintUsage ();
+ return -1;
+ }
+ //
+ // open the TIME file, if not exists, return
+ //
+ fp = fopen (argv[2], "r+");
+ if (fp == NULL) {
+ return 0;
+ }
+ //
+ // get time and date from file
+ //
+ if (GetDateTime (fp, &ltime) != 0) {
+ fclose (fp);
+ return -1;
+ }
+ //
+ // close the TIME file
+ //
+ fclose (fp);
+
+ //
+ // open the PE file
+ //
+ fp = fopen (argv[1], "r+b");
+ if (fp == NULL) {
+ printf ("Error: Cannot open the PE file!\n");
+ return -1;
+ }
+ //
+ // set time and date stamp to the PE file
+ //
+ if (SetStamp (fp, ltime) != 0) {
+ fclose (fp);
+ return -1;
+ }
+
+ printf ("Set Date/Time Stamp to %s", ctime (&ltime));
+
+ //
+ // close the PE file
+ //
+ fclose (fp);
+
+ return 0;
+}
diff --git a/Source/SetStamp/build.xml b/Source/SetStamp/build.xml
new file mode 100644
index 0000000..ff8d6ed
--- /dev/null
+++ b/Source/SetStamp/build.xml
@@ -0,0 +1,69 @@
+<?xml version="1.0" ?>
+<!--
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+-->
+<project default="GenTool" basedir=".">
+<!--
+ EDK SetStamp Tool
+ Copyright (c) 2006, Intel Corporation
+-->
+ <property name="ToolName" value="SetStamp"/>
+ <property name="FileSet" value="SetStamp.c"/>
+
+ <taskdef resource="net/sf/antcontrib/antlib.xml"/>
+
+ <property name="LINK_OUTPUT_TYPE" value="static"/>
+ <property name="BUILD_DIR" value="${PACKAGE_DIR}/${ToolName}/tmp"/>
+
+ <target name="GenTool" depends="init, Tool">
+ <echo message="The EDK Tool: ${ToolName} build has completed!"/>
+ </target>
+
+ <target name="init">
+ <echo message="Building the EDK Tool: ${ToolName}"/>
+ <mkdir dir="${BUILD_DIR}"/>
+ </target>
+
+ <target name="Tool" depends="init">
+ <cc name="${ToolChain}" objdir="${BUILD_DIR}"
+ outfile="${BIN_DIR}/${ToolName}"
+ outtype="executable"
+ debug="true"
+ optimize="speed">
+
+ <fileset dir="${basedir}/${ToolName}"
+ includes="${FileSet}"
+ defaultexcludes="TRUE"
+ excludes="*.xml *.inf"/>
+
+ <includepath path="${PACKAGE_DIR}/Include"/>
+ <includepath path="${PACKAGE_DIR}/Include/Ia32"/>
+ <includepath path="${PACKAGE_DIR}/Common"/>
+
+ </cc>
+ </target>
+
+ <target name="clean">
+ <echo message="Removing Intermediate Files Only"/>
+ <delete>
+ <fileset dir="${BUILD_DIR}" includes="*.obj"/>
+ </delete>
+ </target>
+
+ <target name="cleanall">
+ <echo message="Removing Object Files and the Executable: ${ToolName}${ext_exe}"/>
+ <delete failonerror="false" quiet="true" includeEmptyDirs="true">
+ <fileset dir="${BUILD_DIR}"/>
+ <fileset file="${BIN_DIR}/${ToolName}${ext_exe}"/>
+ <fileset file="${BIN_DIR}/${ToolName}.pdb"/>
+ </delete>
+ </target>
+
+</project>
diff --git a/Source/SplitFile/SplitFile.c b/Source/SplitFile/SplitFile.c
new file mode 100644
index 0000000..a1bda7d
--- /dev/null
+++ b/Source/SplitFile/SplitFile.c
@@ -0,0 +1,131 @@
+/*
+
+Copyright (c) 1999-2006 Intel Corporation. All rights reserved
+This program and the accompanying materials are licensed and made available
+under the terms and conditions of the BSD License which accompanies this
+distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+*/
+
+// GC_TODO: fix comment to start with /*++
+#include "stdio.h"
+#include "string.h"
+#include "stdlib.h"
+
+void
+helpmsg (
+ void
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+{
+ printf (
+ "SplitFile Filename Offset\n"" Filename = Input file to split\n"" Offset = offset at which to split file\n"
+ "\n\n""SplitFile will break a file in two pieces at the requested offset\n"
+ " outputting Filename1 and Filename2\n"
+ );
+}
+
+int
+main (
+ int argc,
+ char*argv[]
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ argc - GC_TODO: add argument description
+ ] - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+{
+ FILE *In;
+
+ FILE *Out1;
+
+ FILE *Out2;
+ char OutName1[512];
+ char OutName2[512];
+ unsigned long Index;
+ unsigned long splitpoint;
+ char CharC;
+
+ if (argc != 3) {
+ helpmsg ();
+ return -1;
+ }
+
+ In = fopen (argv[1], "rb");
+ if (In == NULL) {
+ printf ("Unable to open file \"%s\"\n", argv[1]);
+ return -1;
+ }
+
+ strncpy (OutName1, argv[1], 510);
+ strncpy (OutName2, argv[1], 510);
+ strcat (OutName1, "1");
+ strcat (OutName2, "2");
+
+ Out1 = fopen (OutName1, "wb");
+ if (Out1 == NULL) {
+ printf ("Unable to open file \"%s\"\n", OutName1);
+ return -1;
+ }
+
+ Out2 = fopen (OutName2, "wb");
+ if (Out2 == NULL) {
+ printf ("Unable to open file \"%s\"\n", OutName2);
+ return -1;
+ }
+
+ splitpoint = atoi (argv[2]);
+
+ for (Index = 0; Index < splitpoint; Index++) {
+ CharC = (char) fgetc (In);
+ if (feof (In)) {
+ break;
+ }
+
+ fputc (CharC, Out1);
+ }
+
+ for (;;) {
+ CharC = (char) fgetc (In);
+ if (feof (In)) {
+ break;
+ }
+
+ fputc (CharC, Out2);
+ }
+
+ fclose (In);
+ fclose (Out1);
+ fclose (Out2);
+
+ return 0;
+}
diff --git a/Source/SplitFile/build.xml b/Source/SplitFile/build.xml
new file mode 100644
index 0000000..71e307b
--- /dev/null
+++ b/Source/SplitFile/build.xml
@@ -0,0 +1,68 @@
+<?xml version="1.0" ?>
+<!--
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+-->
+<project default="GenTool" basedir=".">
+<!--
+ EDK SplitFile Tool
+ Copyright (c) 2006, Intel Corporation
+-->
+ <property name="ToolName" value="SplitFile"/>
+ <property name="FileSet" value="*.c"/>
+
+ <taskdef resource="net/sf/antcontrib/antlib.xml"/>
+
+ <property name="LINK_OUTPUT_TYPE" value="static"/>
+ <property name="BUILD_DIR" value="${PACKAGE_DIR}/${ToolName}/tmp"/>
+
+ <target name="GenTool" depends="init, Tool">
+ <echo message="The EDK Tool: ${ToolName} build has completed!"/>
+ </target>
+
+ <target name="init">
+ <echo message="Building the EDK Tool: ${ToolName}"/>
+ <mkdir dir="${BUILD_DIR}"/>
+ </target>
+
+ <target name="Tool" depends="init">
+ <cc name="${ToolChain}" objdir="${BUILD_DIR}"
+ outfile="${BIN_DIR}/${ToolName}"
+ outtype="executable"
+ optimize="speed"
+ debug="true">
+
+ <fileset dir="${basedir}/${ToolName}"
+ includes="${FileSet}"
+ defaultexcludes="TRUE"
+ excludes="*.xml *.inf"/>
+
+ <includepath path="${PACKAGE_DIR}/Include"/>
+ <includepath path="${PACKAGE_DIR}/Include/Ia32"/>
+ <includepath path="${PACKAGE_DIR}/Common"/>
+ </cc>
+ </target>
+
+ <target name="clean">
+ <echo message="Removing Intermediate Files Only"/>
+ <delete>
+ <fileset dir="${BUILD_DIR}" includes="*.obj"/>
+ </delete>
+ </target>
+
+ <target name="cleanall">
+ <echo message="Removing Object Files and the Executable: ${ToolName}${ext_exe}"/>
+ <delete failonerror="false" quiet="true" includeEmptyDirs="true">
+ <fileset dir="${BUILD_DIR}"/>
+ <fileset file="${BIN_DIR}/${ToolName}${ext_exe}"/>
+ <fileset file="${BIN_DIR}/${ToolName}.pdb"/>
+ </delete>
+ </target>
+
+</project>
diff --git a/Source/StrGather/StrGather.c b/Source/StrGather/StrGather.c
new file mode 100644
index 0000000..9eb5c5a
--- /dev/null
+++ b/Source/StrGather/StrGather.c
@@ -0,0 +1,2531 @@
+/*++
+
+Copyright (c) 2004, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ StrGather.c
+
+Abstract:
+
+ Parse a strings file and create or add to a string database file.
+
+--*/
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+
+#include <Common/UefiBaseTypes.h>
+
+#include "CommonLib.h"
+#include "EfiUtilityMsgs.h"
+#include "StrGather.h"
+#include "StringDB.h"
+
+#define TOOL_VERSION "0.31"
+
+#ifndef MAX_PATH
+#define MAX_PATH 255
+#endif
+#define MAX_NEST_DEPTH 20 // just in case we get in an endless loop.
+#define MAX_STRING_IDENTIFIER_NAME 100 // number of wchars
+#define MAX_LINE_LEN 200
+#define STRING_TOKEN "STRING_TOKEN"
+#define DEFAULT_BASE_NAME "BaseName"
+//
+// Operational modes for this utility
+//
+#define MODE_UNKNOWN 0
+#define MODE_PARSE 1
+#define MODE_SCAN 2
+#define MODE_DUMP 3
+
+//
+// We keep a linked list of these for the source files we process
+//
+typedef struct _SOURCE_FILE {
+ FILE *Fptr;
+ WCHAR *FileBuffer;
+ WCHAR *FileBufferPtr;
+ UINT32 FileSize;
+ CHAR8 FileName[MAX_PATH];
+ UINT32 LineNum;
+ BOOLEAN EndOfFile;
+ BOOLEAN SkipToHash;
+ struct _SOURCE_FILE *Previous;
+ struct _SOURCE_FILE *Next;
+ WCHAR ControlCharacter;
+} SOURCE_FILE;
+
+#define DEFAULT_CONTROL_CHARACTER UNICODE_SLASH
+
+//
+// Here's all our globals. We need a linked list of include paths, a linked
+// list of source files, a linked list of subdirectories (appended to each
+// include path when searching), and a couple other fields.
+//
+static struct {
+ SOURCE_FILE SourceFiles;
+ TEXT_STRING_LIST *IncludePaths; // all include paths to search
+ TEXT_STRING_LIST *LastIncludePath;
+ TEXT_STRING_LIST *ScanFileName;
+ TEXT_STRING_LIST *LastScanFileName;
+ TEXT_STRING_LIST *SkipExt; // if -skipext .uni
+ TEXT_STRING_LIST *LastSkipExt;
+ TEXT_STRING_LIST *IndirectionFileName;
+ TEXT_STRING_LIST *LastIndirectionFileName;
+ TEXT_STRING_LIST *DatabaseFileName;
+ TEXT_STRING_LIST *LastDatabaseFileName;
+ WCHAR_STRING_LIST *Language;
+ WCHAR_STRING_LIST *LastLanguage;
+ WCHAR_MATCHING_STRING_LIST *IndirectionList; // from indirection file(s)
+ WCHAR_MATCHING_STRING_LIST *LastIndirectionList;
+ BOOLEAN Verbose; // for more detailed output
+ BOOLEAN VerboseDatabaseWrite; // for more detailed output when writing database
+ BOOLEAN VerboseDatabaseRead; // for more detailed output when reading database
+ BOOLEAN NewDatabase; // to start from scratch
+ BOOLEAN IgnoreNotFound; // when scanning
+ BOOLEAN VerboseScan;
+ BOOLEAN UnquotedStrings; // -uqs option
+ CHAR8 OutputDatabaseFileName[MAX_PATH];
+ CHAR8 StringHFileName[MAX_PATH];
+ CHAR8 StringCFileName[MAX_PATH]; // output .C filename
+ CHAR8 DumpUFileName[MAX_PATH]; // output unicode dump file name
+ CHAR8 HiiExportPackFileName[MAX_PATH]; // HII export pack file name
+ CHAR8 BaseName[MAX_PATH]; // base filename of the strings file
+ UINT32 Mode;
+} mGlobals;
+
+static
+BOOLEAN
+IsValidIdentifierChar (
+ CHAR8 Char,
+ BOOLEAN FirstChar
+ );
+
+static
+void
+RewindFile (
+ SOURCE_FILE *SourceFile
+ );
+
+static
+BOOLEAN
+SkipTo (
+ SOURCE_FILE *SourceFile,
+ WCHAR WChar,
+ BOOLEAN StopAfterNewline
+ );
+
+static
+UINT32
+SkipWhiteSpace (
+ SOURCE_FILE *SourceFile
+ );
+
+static
+BOOLEAN
+IsWhiteSpace (
+ SOURCE_FILE *SourceFile
+ );
+
+static
+BOOLEAN
+EndOfFile (
+ SOURCE_FILE *SourceFile
+ );
+
+static
+void
+PreprocessFile (
+ SOURCE_FILE *SourceFile
+ );
+
+static
+UINT32
+GetStringIdentifierName (
+ IN SOURCE_FILE *SourceFile,
+ IN OUT WCHAR *StringIdentifierName,
+ IN UINT32 StringIdentifierNameLen
+ );
+
+static
+UINT32
+GetLanguageIdentifierName (
+ IN SOURCE_FILE *SourceFile,
+ IN OUT WCHAR *LanguageIdentifierName,
+ IN UINT32 LanguageIdentifierNameLen,
+ IN BOOLEAN Optional
+ );
+
+static
+WCHAR *
+GetPrintableLanguageName (
+ IN SOURCE_FILE *SourceFile
+ );
+
+static
+STATUS
+AddCommandLineLanguage (
+ IN CHAR8 *Language
+ );
+
+static
+WCHAR *
+GetQuotedString (
+ SOURCE_FILE *SourceFile,
+ BOOLEAN Optional
+ );
+
+static
+STATUS
+ProcessIncludeFile (
+ SOURCE_FILE *SourceFile,
+ SOURCE_FILE *ParentSourceFile
+ );
+
+static
+STATUS
+ParseFile (
+ SOURCE_FILE *SourceFile
+ );
+
+static
+FILE *
+FindFile (
+ IN CHAR8 *FileName,
+ OUT CHAR8 *FoundFileName,
+ IN UINT32 FoundFileNameLen
+ );
+
+static
+STATUS
+ProcessArgs (
+ int Argc,
+ char *Argv[]
+ );
+
+static
+STATUS
+ProcessFile (
+ SOURCE_FILE *SourceFile
+ );
+
+static
+UINT32
+wstrcmp (
+ WCHAR *Buffer,
+ WCHAR *Str
+ );
+
+static
+void
+Usage (
+ VOID
+ );
+
+static
+void
+FreeLists (
+ VOID
+ );
+
+static
+void
+ProcessTokenString (
+ SOURCE_FILE *SourceFile
+ );
+
+static
+void
+ProcessTokenInclude (
+ SOURCE_FILE *SourceFile
+ );
+
+static
+void
+ProcessTokenScope (
+ SOURCE_FILE *SourceFile
+ );
+
+static
+void
+ProcessTokenLanguage (
+ SOURCE_FILE *SourceFile
+ );
+
+static
+void
+ProcessTokenLangDef (
+ SOURCE_FILE *SourceFile
+ );
+
+static
+STATUS
+ScanFiles (
+ TEXT_STRING_LIST *ScanFiles
+ );
+
+static
+STATUS
+ParseIndirectionFiles (
+ TEXT_STRING_LIST *Files
+ );
+
+STATUS
+StringDBCreateHiiExportPack (
+ CHAR8 *OutputFileName
+ );
+
+int
+main (
+ int Argc,
+ char *Argv[]
+ )
+/*++
+
+Routine Description:
+
+ Call the routine to parse the command-line options, then process the file.
+
+Arguments:
+
+ Argc - Standard C main() argc and argv.
+ Argv - Standard C main() argc and argv.
+
+Returns:
+
+ 0 if successful
+ nonzero otherwise
+
+--*/
+{
+ STATUS Status;
+
+ SetUtilityName (PROGRAM_NAME);
+ //
+ // Process the command-line arguments
+ //
+ Status = ProcessArgs (Argc, Argv);
+ if (Status != STATUS_SUCCESS) {
+ return Status;
+ }
+ //
+ // Initialize the database manager
+ //
+ StringDBConstructor ();
+ //
+ // We always try to read in an existing database file. It may not
+ // exist, which is ok usually.
+ //
+ if (mGlobals.NewDatabase == 0) {
+ //
+ // Read all databases specified.
+ //
+ for (mGlobals.LastDatabaseFileName = mGlobals.DatabaseFileName;
+ mGlobals.LastDatabaseFileName != NULL;
+ mGlobals.LastDatabaseFileName = mGlobals.LastDatabaseFileName->Next
+ ) {
+ Status = StringDBReadDatabase (mGlobals.LastDatabaseFileName->Str, TRUE, mGlobals.VerboseDatabaseRead);
+ if (Status != STATUS_SUCCESS) {
+ return Status;
+ }
+ }
+ }
+ //
+ // Read indirection file(s) if specified
+ //
+ if (ParseIndirectionFiles (mGlobals.IndirectionFileName) != STATUS_SUCCESS) {
+ goto Finish;
+ }
+ //
+ // If scanning source files, do that now
+ //
+ if (mGlobals.Mode == MODE_SCAN) {
+ ScanFiles (mGlobals.ScanFileName);
+ } else if (mGlobals.Mode == MODE_PARSE) {
+ //
+ // Parsing a unicode strings file
+ //
+ mGlobals.SourceFiles.ControlCharacter = DEFAULT_CONTROL_CHARACTER;
+ Status = ProcessIncludeFile (&mGlobals.SourceFiles, NULL);
+ if (Status != STATUS_SUCCESS) {
+ goto Finish;
+ }
+ }
+ //
+ // Create the string defines header file if there have been no errors.
+ //
+ ParserSetPosition (NULL, 0);
+ if ((mGlobals.StringHFileName[0] != 0) && (GetUtilityStatus () < STATUS_ERROR)) {
+ Status = StringDBDumpStringDefines (mGlobals.StringHFileName, mGlobals.BaseName);
+ if (Status != EFI_SUCCESS) {
+ goto Finish;
+ }
+ }
+ //
+ // Dump the strings to a .c file if there have still been no errors.
+ //
+ if ((mGlobals.StringCFileName[0] != 0) && (GetUtilityStatus () < STATUS_ERROR)) {
+ Status = StringDBDumpCStrings (
+ mGlobals.StringCFileName,
+ mGlobals.BaseName,
+ mGlobals.Language,
+ mGlobals.IndirectionList
+ );
+ if (Status != EFI_SUCCESS) {
+ goto Finish;
+ }
+ }
+ //
+ // Dump the database if requested
+ //
+ if ((mGlobals.DumpUFileName[0] != 0) && (GetUtilityStatus () < STATUS_ERROR)) {
+ StringDBDumpDatabase (NULL, mGlobals.DumpUFileName, FALSE);
+ }
+ //
+ // Dump the string data as HII binary string pack if requested
+ //
+ if ((mGlobals.HiiExportPackFileName[0] != 0) && (GetUtilityStatus () < STATUS_ERROR)) {
+ StringDBCreateHiiExportPack (mGlobals.HiiExportPackFileName);
+ }
+ //
+ // Always update the database if no errors and not in dump mode. If they specified -od
+ // for an output database file name, then use that name. Otherwise use the name of
+ // the first database file specified with -db
+ //
+ if ((mGlobals.Mode != MODE_DUMP) && (GetUtilityStatus () < STATUS_ERROR)) {
+ if (mGlobals.OutputDatabaseFileName[0]) {
+ Status = StringDBWriteDatabase (mGlobals.OutputDatabaseFileName, mGlobals.VerboseDatabaseWrite);
+ } else {
+ Status = StringDBWriteDatabase (mGlobals.DatabaseFileName->Str, mGlobals.VerboseDatabaseWrite);
+ }
+
+ if (Status != EFI_SUCCESS) {
+ goto Finish;
+ }
+ }
+
+Finish:
+ //
+ // Free up memory
+ //
+ FreeLists ();
+ StringDBDestructor ();
+ return GetUtilityStatus ();
+}
+
+static
+STATUS
+ProcessIncludeFile (
+ SOURCE_FILE *SourceFile,
+ SOURCE_FILE *ParentSourceFile
+ )
+/*++
+
+Routine Description:
+
+ Given a source file, open the file and parse it
+
+Arguments:
+
+ SourceFile - name of file to parse
+ ParentSourceFile - for error reporting purposes, the file that #included SourceFile.
+
+Returns:
+
+ Standard status.
+
+--*/
+{
+ static UINT32 NestDepth = 0;
+ CHAR8 FoundFileName[MAX_PATH];
+ STATUS Status;
+
+ Status = STATUS_SUCCESS;
+ NestDepth++;
+ //
+ // Print the file being processed. Indent so you can tell the include nesting
+ // depth.
+ //
+ if (mGlobals.Verbose) {
+ fprintf (stdout, "%*cProcessing file '%s'\n", NestDepth * 2, ' ', SourceFile->FileName);
+ }
+
+ //
+ // Make sure we didn't exceed our maximum nesting depth
+ //
+ if (NestDepth > MAX_NEST_DEPTH) {
+ Error (NULL, 0, 0, SourceFile->FileName, "max nesting depth (%d) exceeded", NestDepth);
+ Status = STATUS_ERROR;
+ goto Finish;
+ }
+ //
+ // Try to open the file locally, and if that fails try along our include paths.
+ //
+ strcpy (FoundFileName, SourceFile->FileName);
+ if ((SourceFile->Fptr = fopen (FoundFileName, "rb")) == NULL) {
+ //
+ // Try to find it among the paths if it has a parent (that is, it is included
+ // by someone else).
+ //
+ if (ParentSourceFile == NULL) {
+ Error (NULL, 0, 0, SourceFile->FileName, "file not found");
+ return STATUS_ERROR;
+ }
+
+ SourceFile->Fptr = FindFile (SourceFile->FileName, FoundFileName, sizeof (FoundFileName));
+ if (SourceFile->Fptr == NULL) {
+ Error (ParentSourceFile->FileName, ParentSourceFile->LineNum, 0, SourceFile->FileName, "include file not found");
+ return STATUS_ERROR;
+ }
+ }
+ //
+ // Process the file found
+ //
+ ProcessFile (SourceFile);
+Finish:
+ //
+ // Close open files and return status
+ //
+ if (SourceFile->Fptr != NULL) {
+ fclose (SourceFile->Fptr);
+ }
+
+ return Status;
+}
+
+static
+STATUS
+ProcessFile (
+ SOURCE_FILE *SourceFile
+ )
+{
+ //
+ // Get the file size, and then read the entire thing into memory.
+ // Allocate space for a terminator character.
+ //
+ fseek (SourceFile->Fptr, 0, SEEK_END);
+ SourceFile->FileSize = ftell (SourceFile->Fptr);
+ fseek (SourceFile->Fptr, 0, SEEK_SET);
+ SourceFile->FileBuffer = (WCHAR *) malloc (SourceFile->FileSize + sizeof (WCHAR));
+ if (SourceFile->FileBuffer == NULL) {
+ Error (NULL, 0, 0, "memory allocation failure", NULL);
+ return STATUS_ERROR;
+ }
+
+ fread ((VOID *) SourceFile->FileBuffer, SourceFile->FileSize, 1, SourceFile->Fptr);
+ SourceFile->FileBuffer[(SourceFile->FileSize / sizeof (WCHAR))] = UNICODE_NULL;
+ //
+ // Pre-process the file to replace comments with spaces
+ //
+ PreprocessFile (SourceFile);
+ //
+ // Parse the file
+ //
+ ParseFile (SourceFile);
+ free (SourceFile->FileBuffer);
+ return STATUS_SUCCESS;
+}
+
+static
+STATUS
+ParseFile (
+ SOURCE_FILE *SourceFile
+ )
+{
+ BOOLEAN InComment;
+ UINT32 Len;
+
+ //
+ // First character of a unicode file is special. Make sure
+ //
+ if (SourceFile->FileBufferPtr[0] != UNICODE_FILE_START) {
+ Error (SourceFile->FileName, 1, 0, SourceFile->FileName, "file does not appear to be a unicode file");
+ return STATUS_ERROR;
+ }
+
+ SourceFile->FileBufferPtr++;
+ InComment = FALSE;
+ //
+ // Print the first line if in verbose mode
+ //
+ if (mGlobals.Verbose) {
+ printf ("%d: %S\n", SourceFile->LineNum, SourceFile->FileBufferPtr);
+ }
+ //
+ // Since the syntax is relatively straightforward, just switch on the next char
+ //
+ while (!EndOfFile (SourceFile)) {
+ //
+ // Check for whitespace
+ //
+ if (SourceFile->FileBufferPtr[0] == UNICODE_SPACE) {
+ SourceFile->FileBufferPtr++;
+ } else if (SourceFile->FileBufferPtr[0] == UNICODE_TAB) {
+ SourceFile->FileBufferPtr++;
+ } else if (SourceFile->FileBufferPtr[0] == UNICODE_CR) {
+ SourceFile->FileBufferPtr++;
+ } else if (SourceFile->FileBufferPtr[0] == UNICODE_LF) {
+ SourceFile->FileBufferPtr++;
+ SourceFile->LineNum++;
+ if (mGlobals.Verbose) {
+ printf ("%d: %S\n", SourceFile->LineNum, SourceFile->FileBufferPtr);
+ }
+
+ InComment = FALSE;
+ } else if (SourceFile->FileBufferPtr[0] == 0) {
+ SourceFile->FileBufferPtr++;
+ } else if (InComment) {
+ SourceFile->FileBufferPtr++;
+ } else if ((SourceFile->FileBufferPtr[0] == UNICODE_SLASH) && (SourceFile->FileBufferPtr[1] == UNICODE_SLASH)) {
+ SourceFile->FileBufferPtr += 2;
+ InComment = TRUE;
+ } else if (SourceFile->SkipToHash && (SourceFile->FileBufferPtr[0] != SourceFile->ControlCharacter)) {
+ SourceFile->FileBufferPtr++;
+ } else {
+ SourceFile->SkipToHash = FALSE;
+ if ((SourceFile->FileBufferPtr[0] == SourceFile->ControlCharacter) &&
+ ((Len = wstrcmp (SourceFile->FileBufferPtr + 1, L"include")) > 0)
+ ) {
+ SourceFile->FileBufferPtr += Len + 1;
+ ProcessTokenInclude (SourceFile);
+ } else if ((SourceFile->FileBufferPtr[0] == SourceFile->ControlCharacter) &&
+ (Len = wstrcmp (SourceFile->FileBufferPtr + 1, L"scope")) > 0
+ ) {
+ SourceFile->FileBufferPtr += Len + 1;
+ ProcessTokenScope (SourceFile);
+ } else if ((SourceFile->FileBufferPtr[0] == SourceFile->ControlCharacter) &&
+ (Len = wstrcmp (SourceFile->FileBufferPtr + 1, L"language")) > 0
+ ) {
+ SourceFile->FileBufferPtr += Len + 1;
+ ProcessTokenLanguage (SourceFile);
+ } else if ((SourceFile->FileBufferPtr[0] == SourceFile->ControlCharacter) &&
+ (Len = wstrcmp (SourceFile->FileBufferPtr + 1, L"langdef")) > 0
+ ) {
+ SourceFile->FileBufferPtr += Len + 1;
+ ProcessTokenLangDef (SourceFile);
+ } else if ((SourceFile->FileBufferPtr[0] == SourceFile->ControlCharacter) &&
+ (Len = wstrcmp (SourceFile->FileBufferPtr + 1, L"string")) > 0
+ ) {
+ SourceFile->FileBufferPtr += Len + 1;
+ ProcessTokenString (SourceFile);
+ } else if ((SourceFile->FileBufferPtr[0] == SourceFile->ControlCharacter) &&
+ (Len = wstrcmp (SourceFile->FileBufferPtr + 1, L"EFI_BREAKPOINT()")) > 0
+ ) {
+ SourceFile->FileBufferPtr += Len;
+ //
+ // BUGBUG: Caling EFI_BREAKOINT() is breaking the link. What is the proper action for this tool
+ // in this condition?
+ //
+// EFI_BREAKPOINT ();
+ } else if ((SourceFile->FileBufferPtr[0] == SourceFile->ControlCharacter) &&
+ (SourceFile->FileBufferPtr[1] == UNICODE_EQUAL_SIGN)
+ ) {
+ SourceFile->ControlCharacter = SourceFile->FileBufferPtr[2];
+ SourceFile->FileBufferPtr += 3;
+ } else {
+ Error (SourceFile->FileName, SourceFile->LineNum, 0, "unrecognized token", "%S", SourceFile->FileBufferPtr);
+ //
+ // Treat rest of line as a comment.
+ //
+ InComment = TRUE;
+ }
+ }
+ }
+
+ return STATUS_SUCCESS;
+}
+
+static
+void
+PreprocessFile (
+ SOURCE_FILE *SourceFile
+ )
+/*++
+
+Routine Description:
+ Preprocess a file to replace all carriage returns with NULLs so
+ we can print lines from the file to the screen.
+
+Arguments:
+ SourceFile - structure that we use to keep track of an input file.
+
+Returns:
+ Nothing.
+
+--*/
+{
+ BOOLEAN InComment;
+
+ RewindFile (SourceFile);
+ InComment = FALSE;
+ while (!EndOfFile (SourceFile)) {
+ //
+ // If a line-feed, then no longer in a comment
+ //
+ if (SourceFile->FileBufferPtr[0] == UNICODE_LF) {
+ SourceFile->FileBufferPtr++;
+ SourceFile->LineNum++;
+ InComment = 0;
+ } else if (SourceFile->FileBufferPtr[0] == UNICODE_CR) {
+ //
+ // Replace all carriage returns with a NULL so we can print stuff
+ //
+ SourceFile->FileBufferPtr[0] = 0;
+ SourceFile->FileBufferPtr++;
+ } else if (InComment) {
+ SourceFile->FileBufferPtr[0] = UNICODE_SPACE;
+ SourceFile->FileBufferPtr++;
+ } else if ((SourceFile->FileBufferPtr[0] == UNICODE_SLASH) && (SourceFile->FileBufferPtr[1] == UNICODE_SLASH)) {
+ SourceFile->FileBufferPtr += 2;
+ InComment = TRUE;
+ } else {
+ SourceFile->FileBufferPtr++;
+ }
+ }
+ //
+ // Could check for end-of-file and still in a comment, but
+ // should not be necessary. So just restore the file pointers.
+ //
+ RewindFile (SourceFile);
+}
+
+static
+WCHAR *
+GetPrintableLanguageName (
+ IN SOURCE_FILE *SourceFile
+ )
+{
+ WCHAR *String;
+ WCHAR *Start;
+ WCHAR *Ptr;
+ UINT32 Len;
+
+ SkipWhiteSpace (SourceFile);
+ if (SourceFile->FileBufferPtr[0] != UNICODE_DOUBLE_QUOTE) {
+ Error (
+ SourceFile->FileName,
+ SourceFile->LineNum,
+ 0,
+ "expected quoted printable language name",
+ "%S",
+ SourceFile->FileBufferPtr
+ );
+ SourceFile->SkipToHash = TRUE;
+ return NULL;
+ }
+
+ Len = 0;
+ SourceFile->FileBufferPtr++;
+ Start = Ptr = SourceFile->FileBufferPtr;
+ while (!EndOfFile (SourceFile)) {
+ if (SourceFile->FileBufferPtr[0] == UNICODE_CR) {
+ Warning (SourceFile->FileName, SourceFile->LineNum, 0, "carriage return found in quoted string", "%S", Start);
+ break;
+ } else if (SourceFile->FileBufferPtr[0] == UNICODE_DOUBLE_QUOTE) {
+ break;
+ }
+
+ SourceFile->FileBufferPtr++;
+ Len++;
+ }
+
+ if (SourceFile->FileBufferPtr[0] != UNICODE_DOUBLE_QUOTE) {
+ Warning (
+ SourceFile->FileName,
+ SourceFile->LineNum,
+ 0,
+ "missing closing quote on printable language name string",
+ "%S",
+ Start
+ );
+ } else {
+ SourceFile->FileBufferPtr++;
+ }
+ //
+ // Now allocate memory for the string and save it off
+ //
+ String = (WCHAR *) malloc ((Len + 1) * sizeof (WCHAR));
+ if (String == NULL) {
+ Error (NULL, 0, 0, "memory allocation failed", NULL);
+ return NULL;
+ }
+ //
+ // Copy the string from the file buffer to the local copy.
+ // We do no reformatting of it whatsoever at this point.
+ //
+ Ptr = String;
+ while (Len > 0) {
+ *Ptr = *Start;
+ Start++;
+ Ptr++;
+ Len--;
+ }
+
+ *Ptr = 0;
+ //
+ // Now format the string to convert \wide and \narrow controls
+ //
+ StringDBFormatString (String);
+ return String;
+}
+
+static
+WCHAR *
+GetQuotedString (
+ SOURCE_FILE *SourceFile,
+ BOOLEAN Optional
+ )
+{
+ WCHAR *String;
+ WCHAR *Start;
+ WCHAR *Ptr;
+ UINT32 Len;
+ BOOLEAN PreviousBackslash;
+
+ if (SourceFile->FileBufferPtr[0] != UNICODE_DOUBLE_QUOTE) {
+ if (!Optional) {
+ Error (SourceFile->FileName, SourceFile->LineNum, 0, "expected quoted string", "%S", SourceFile->FileBufferPtr);
+ }
+
+ return NULL;
+ }
+
+ Len = 0;
+ SourceFile->FileBufferPtr++;
+ Start = Ptr = SourceFile->FileBufferPtr;
+ PreviousBackslash = FALSE;
+ while (!EndOfFile (SourceFile)) {
+ if ((SourceFile->FileBufferPtr[0] == UNICODE_DOUBLE_QUOTE) && (!PreviousBackslash)) {
+ break;
+ } else if (SourceFile->FileBufferPtr[0] == UNICODE_CR) {
+ Warning (SourceFile->FileName, SourceFile->LineNum, 0, "carriage return found in quoted string", "%S", Start);
+ PreviousBackslash = FALSE;
+ } else if (SourceFile->FileBufferPtr[0] == UNICODE_BACKSLASH) {
+ PreviousBackslash = TRUE;
+ } else {
+ PreviousBackslash = FALSE;
+ }
+
+ SourceFile->FileBufferPtr++;
+ Len++;
+ }
+
+ if (SourceFile->FileBufferPtr[0] != UNICODE_DOUBLE_QUOTE) {
+ Warning (SourceFile->FileName, SourceFile->LineNum, 0, "missing closing quote on string", "%S", Start);
+ } else {
+ SourceFile->FileBufferPtr++;
+ }
+ //
+ // Now allocate memory for the string and save it off
+ //
+ String = (WCHAR *) malloc ((Len + 1) * sizeof (WCHAR));
+ if (String == NULL) {
+ Error (NULL, 0, 0, "memory allocation failed", NULL);
+ return NULL;
+ }
+ //
+ // Copy the string from the file buffer to the local copy.
+ // We do no reformatting of it whatsoever at this point.
+ //
+ Ptr = String;
+ while (Len > 0) {
+ *Ptr = *Start;
+ Start++;
+ Ptr++;
+ Len--;
+ }
+
+ *Ptr = 0;
+ return String;
+}
+//
+// Parse:
+// #string STR_ID_NAME
+//
+// All we can do is call the string database to add the string identifier. Unfortunately
+// he'll have to keep track of the last identifier we added.
+//
+static
+void
+ProcessTokenString (
+ SOURCE_FILE *SourceFile
+ )
+{
+ WCHAR StringIdentifier[MAX_STRING_IDENTIFIER_NAME];
+ UINT16 StringId;
+ //
+ // Extract the string identifier name and add it to the database.
+ //
+ if (GetStringIdentifierName (SourceFile, StringIdentifier, sizeof (StringIdentifier)) > 0) {
+ StringId = STRING_ID_INVALID;
+ StringDBAddStringIdentifier (StringIdentifier, &StringId, 0);
+ } else {
+ //
+ // Error recovery -- skip to the next #
+ //
+ SourceFile->SkipToHash = TRUE;
+ }
+}
+
+static
+BOOLEAN
+EndOfFile (
+ SOURCE_FILE *SourceFile
+ )
+{
+ //
+ // The file buffer pointer will typically get updated before the End-of-file flag in the
+ // source file structure, so check it first.
+ //
+ if (SourceFile->FileBufferPtr >= SourceFile->FileBuffer + SourceFile->FileSize / sizeof (WCHAR)) {
+ SourceFile->EndOfFile = TRUE;
+ return TRUE;
+ }
+
+ if (SourceFile->EndOfFile) {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static
+UINT32
+GetStringIdentifierName (
+ IN SOURCE_FILE *SourceFile,
+ IN OUT WCHAR *StringIdentifierName,
+ IN UINT32 StringIdentifierNameLen
+ )
+{
+ UINT32 Len;
+ WCHAR *From;
+ WCHAR *Start;
+
+ //
+ // Skip whitespace
+ //
+ SkipWhiteSpace (SourceFile);
+ if (SourceFile->EndOfFile) {
+ Error (SourceFile->FileName, SourceFile->LineNum, 0, "end-of-file encountered", "expected string identifier");
+ return 0;
+ }
+ //
+ // Verify first character of name is [A-Za-z]
+ //
+ Len = 0;
+ StringIdentifierNameLen /= 2;
+ From = SourceFile->FileBufferPtr;
+ Start = SourceFile->FileBufferPtr;
+ if (((SourceFile->FileBufferPtr[0] >= UNICODE_A) && (SourceFile->FileBufferPtr[0] <= UNICODE_Z)) ||
+ ((SourceFile->FileBufferPtr[0] >= UNICODE_z) && (SourceFile->FileBufferPtr[0] <= UNICODE_z))
+ ) {
+ //
+ // Do nothing
+ //
+ } else {
+ Error (SourceFile->FileName, SourceFile->LineNum, 0, "invalid character in string identifier name", "%S", Start);
+ return 0;
+ }
+
+ while (!EndOfFile (SourceFile)) {
+ if (((SourceFile->FileBufferPtr[0] >= UNICODE_A) && (SourceFile->FileBufferPtr[0] <= UNICODE_Z)) ||
+ ((SourceFile->FileBufferPtr[0] >= UNICODE_z) && (SourceFile->FileBufferPtr[0] <= UNICODE_z)) ||
+ ((SourceFile->FileBufferPtr[0] >= UNICODE_0) && (SourceFile->FileBufferPtr[0] <= UNICODE_9)) ||
+ (SourceFile->FileBufferPtr[0] == UNICODE_UNDERSCORE)
+ ) {
+ Len++;
+ if (Len >= StringIdentifierNameLen) {
+ Error (SourceFile->FileName, SourceFile->LineNum, 0, "string identifier name too long", "%S", Start);
+ return 0;
+ }
+
+ *StringIdentifierName = SourceFile->FileBufferPtr[0];
+ StringIdentifierName++;
+ SourceFile->FileBufferPtr++;
+ } else if (SkipWhiteSpace (SourceFile) == 0) {
+ Error (SourceFile->FileName, SourceFile->LineNum, 0, "invalid string identifier name", "%S", Start);
+ return 0;
+ } else {
+ break;
+ }
+ }
+ //
+ // Terminate the copy of the string.
+ //
+ *StringIdentifierName = 0;
+ return Len;
+}
+
+static
+UINT32
+GetLanguageIdentifierName (
+ IN SOURCE_FILE *SourceFile,
+ IN OUT WCHAR *LanguageIdentifierName,
+ IN UINT32 LanguageIdentifierNameLen,
+ IN BOOLEAN Optional
+ )
+{
+ UINT32 Len;
+ WCHAR *From;
+ WCHAR *Start;
+ //
+ // Skip whitespace
+ //
+ SkipWhiteSpace (SourceFile);
+ if (SourceFile->EndOfFile) {
+ if (!Optional) {
+ Error (
+ SourceFile->FileName,
+ SourceFile->LineNum,
+ 0,
+ "end-of-file encountered",
+ "expected language identifier"
+ );
+ }
+
+ return 0;
+ }
+ //
+ // This function is called to optionally get a language identifier name in:
+ // #string STR_ID eng "the string"
+ // If it's optional, and we find a double-quote, then return now.
+ //
+ if (Optional) {
+ if (*SourceFile->FileBufferPtr == UNICODE_DOUBLE_QUOTE) {
+ return 0;
+ }
+ }
+
+ Len = 0;
+ LanguageIdentifierNameLen /= 2;
+ //
+ // Internal error if we weren't given at least 4 WCHAR's to work with.
+ //
+ if (LanguageIdentifierNameLen < LANGUAGE_IDENTIFIER_NAME_LEN + 1) {
+ Error (
+ SourceFile->FileName,
+ SourceFile->LineNum,
+ 0,
+ "app error -- language identifier name length is invalid",
+ NULL
+ );
+ }
+
+ From = SourceFile->FileBufferPtr;
+ Start = SourceFile->FileBufferPtr;
+ while (!EndOfFile (SourceFile)) {
+ if (((SourceFile->FileBufferPtr[0] >= UNICODE_a) && (SourceFile->FileBufferPtr[0] <= UNICODE_z))) {
+ Len++;
+ if (Len > LANGUAGE_IDENTIFIER_NAME_LEN) {
+ Error (SourceFile->FileName, SourceFile->LineNum, 0, "language identifier name too long", "%S", Start);
+ return 0;
+ }
+
+ *LanguageIdentifierName = SourceFile->FileBufferPtr[0];
+ SourceFile->FileBufferPtr++;
+ LanguageIdentifierName++;
+ } else if (!IsWhiteSpace (SourceFile)) {
+ Error (SourceFile->FileName, SourceFile->LineNum, 0, "invalid language identifier name", "%S", Start);
+ return 0;
+ } else {
+ break;
+ }
+ }
+ //
+ // Terminate the copy of the string.
+ //
+ *LanguageIdentifierName = 0;
+ return Len;
+}
+
+static
+void
+ProcessTokenInclude (
+ SOURCE_FILE *SourceFile
+ )
+{
+ CHAR8 IncludeFileName[MAX_PATH];
+ CHAR8 *To;
+ UINT32 Len;
+ BOOLEAN ReportedError;
+ SOURCE_FILE IncludedSourceFile;
+
+ ReportedError = FALSE;
+ if (SkipWhiteSpace (SourceFile) == 0) {
+ Warning (SourceFile->FileName, SourceFile->LineNum, 0, "expected whitespace following #include keyword", NULL);
+ }
+ //
+ // Should be quoted file name
+ //
+ if (SourceFile->FileBufferPtr[0] != UNICODE_DOUBLE_QUOTE) {
+ Error (SourceFile->FileName, SourceFile->LineNum, 0, "expected quoted include file name", NULL);
+ goto FailDone;
+ }
+
+ SourceFile->FileBufferPtr++;
+ //
+ // Copy the filename as ascii to our local string
+ //
+ To = IncludeFileName;
+ Len = 0;
+ while (!EndOfFile (SourceFile)) {
+ if ((SourceFile->FileBufferPtr[0] == UNICODE_CR) || (SourceFile->FileBufferPtr[0] == UNICODE_LF)) {
+ Error (SourceFile->FileName, SourceFile->LineNum, 0, "end-of-line found in quoted include file name", NULL);
+ goto FailDone;
+ }
+
+ if (SourceFile->FileBufferPtr[0] == UNICODE_DOUBLE_QUOTE) {
+ SourceFile->FileBufferPtr++;
+ break;
+ }
+ //
+ // If too long, then report the error once and process until the closing quote
+ //
+ Len++;
+ if (!ReportedError && (Len >= sizeof (IncludeFileName))) {
+ Error (SourceFile->FileName, SourceFile->LineNum, 0, "length of include file name exceeds limit", NULL);
+ ReportedError = TRUE;
+ }
+
+ if (!ReportedError) {
+ *To = UNICODE_TO_ASCII (SourceFile->FileBufferPtr[0]);
+ To++;
+ }
+
+ SourceFile->FileBufferPtr++;
+ }
+
+ if (!ReportedError) {
+ *To = 0;
+ memset ((char *) &IncludedSourceFile, 0, sizeof (SOURCE_FILE));
+ strcpy (IncludedSourceFile.FileName, IncludeFileName);
+ IncludedSourceFile.ControlCharacter = DEFAULT_CONTROL_CHARACTER;
+ ProcessIncludeFile (&IncludedSourceFile, SourceFile);
+ //
+ // printf ("including file '%s'\n", IncludeFileName);
+ //
+ }
+
+ return ;
+FailDone:
+ //
+ // Error recovery -- skip to next #
+ //
+ SourceFile->SkipToHash = TRUE;
+}
+
+static
+void
+ProcessTokenScope (
+ SOURCE_FILE *SourceFile
+ )
+{
+ WCHAR StringIdentifier[MAX_STRING_IDENTIFIER_NAME];
+ //
+ // Extract the scope name
+ //
+ if (GetStringIdentifierName (SourceFile, StringIdentifier, sizeof (StringIdentifier)) > 0) {
+ StringDBSetScope (StringIdentifier);
+ }
+}
+//
+// Parse: #langdef eng "English"
+// #langdef chn "\wideChinese"
+//
+static
+void
+ProcessTokenLangDef (
+ SOURCE_FILE *SourceFile
+ )
+{
+ WCHAR LanguageIdentifier[MAX_STRING_IDENTIFIER_NAME];
+ UINT32 Len;
+ WCHAR *PrintableName;
+ //
+ // Extract the 3-character language identifier
+ //
+ Len = GetLanguageIdentifierName (SourceFile, LanguageIdentifier, sizeof (LanguageIdentifier), FALSE);
+ if (Len != LANGUAGE_IDENTIFIER_NAME_LEN) {
+ Error (SourceFile->FileName, SourceFile->LineNum, 0, "invalid or missing language identifier", NULL);
+ } else {
+ //
+ // Extract the printable name
+ //
+ PrintableName = GetPrintableLanguageName (SourceFile);
+ if (PrintableName != NULL) {
+ ParserSetPosition (SourceFile->FileName, SourceFile->LineNum);
+ StringDBAddLanguage (LanguageIdentifier, PrintableName);
+ free (PrintableName);
+ return ;
+ }
+ }
+ //
+ // Error recovery -- skip to next #
+ //
+ SourceFile->SkipToHash = TRUE;
+}
+
+static
+BOOLEAN
+ApparentQuotedString (
+ SOURCE_FILE *SourceFile
+ )
+{
+ WCHAR *Ptr;
+ //
+ // See if the first and last nonblank characters on the line are double quotes
+ //
+ for (Ptr = SourceFile->FileBufferPtr; *Ptr && (*Ptr == UNICODE_SPACE); Ptr++)
+ ;
+ if (*Ptr != UNICODE_DOUBLE_QUOTE) {
+ return FALSE;
+ }
+
+ while (*Ptr) {
+ Ptr++;
+ }
+
+ Ptr--;
+ for (; *Ptr && (*Ptr == UNICODE_SPACE); Ptr--)
+ ;
+ if (*Ptr != UNICODE_DOUBLE_QUOTE) {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+//
+// Parse:
+// #language eng "some string " "more string"
+//
+static
+void
+ProcessTokenLanguage (
+ SOURCE_FILE *SourceFile
+ )
+{
+ WCHAR *String;
+ WCHAR *SecondString;
+ WCHAR *TempString;
+ WCHAR *From;
+ WCHAR *To;
+ WCHAR Language[LANGUAGE_IDENTIFIER_NAME_LEN + 1];
+ UINT32 Len;
+ BOOLEAN PreviousNewline;
+ //
+ // Get the language identifier
+ //
+ Language[0] = 0;
+ Len = GetLanguageIdentifierName (SourceFile, Language, sizeof (Language), TRUE);
+ if (Len != LANGUAGE_IDENTIFIER_NAME_LEN) {
+ Error (SourceFile->FileName, SourceFile->LineNum, 0, "invalid or missing language identifier", "%S", Language);
+ SourceFile->SkipToHash = TRUE;
+ return ;
+ }
+ //
+ // Extract the string value. It's either a quoted string that starts on the current line, or
+ // an unquoted string that starts on the following line and continues until the next control
+ // character in column 1.
+ // Look ahead to find a quote or a newline
+ //
+ if (SkipTo (SourceFile, UNICODE_DOUBLE_QUOTE, TRUE)) {
+ String = GetQuotedString (SourceFile, FALSE);
+ if (String != NULL) {
+ //
+ // Set the position in the file of where we are parsing for error
+ // reporting purposes. Then start looking ahead for additional
+ // quoted strings, and concatenate them until we get a failure
+ // back from the string parser.
+ //
+ Len = StrLen (String) + 1;
+ ParserSetPosition (SourceFile->FileName, SourceFile->LineNum);
+ do {
+ SkipWhiteSpace (SourceFile);
+ SecondString = GetQuotedString (SourceFile, TRUE);
+ if (SecondString != NULL) {
+ Len += StrLen (SecondString);
+ TempString = (WCHAR *) malloc (Len * sizeof (WCHAR));
+ if (TempString == NULL) {
+ Error (NULL, 0, 0, "application error", "failed to allocate memory");
+ return ;
+ }
+
+ StrCpy (TempString, String);
+ StrCat (TempString, SecondString);
+ free (String);
+ free (SecondString);
+ String = TempString;
+ }
+ } while (SecondString != NULL);
+ StringDBAddString (Language, NULL, NULL, String, TRUE, 0);
+ free (String);
+ } else {
+ //
+ // Error was reported at lower level. Error recovery mode.
+ //
+ SourceFile->SkipToHash = TRUE;
+ }
+ } else {
+ if (!mGlobals.UnquotedStrings) {
+ //
+ // They're using unquoted strings. If the next non-blank character is a double quote, and the
+ // last non-blank character on the line is a double quote, then more than likely they're using
+ // quotes, so they need to put the quoted string on the end of the previous line
+ //
+ if (ApparentQuotedString (SourceFile)) {
+ Warning (
+ SourceFile->FileName,
+ SourceFile->LineNum,
+ 0,
+ "unexpected quoted string on line",
+ "specify -uqs option if necessary"
+ );
+ }
+ }
+ //
+ // Found end-of-line (hopefully). Skip over it and start taking in characters
+ // until we find a control character at the start of a line.
+ //
+ Len = 0;
+ From = SourceFile->FileBufferPtr;
+ PreviousNewline = FALSE;
+ while (!EndOfFile (SourceFile)) {
+ if (SourceFile->FileBufferPtr[0] == UNICODE_LF) {
+ PreviousNewline = TRUE;
+ SourceFile->LineNum++;
+ } else {
+ Len++;
+ if (PreviousNewline && (SourceFile->FileBufferPtr[0] == SourceFile->ControlCharacter)) {
+ break;
+ }
+
+ PreviousNewline = FALSE;
+ }
+
+ SourceFile->FileBufferPtr++;
+ }
+
+ if ((Len == 0) && EndOfFile (SourceFile)) {
+ Error (SourceFile->FileName, SourceFile->LineNum, 0, "unexpected end of file", NULL);
+ SourceFile->SkipToHash = TRUE;
+ return ;
+ }
+ //
+ // Now allocate a buffer, copy the characters, and add the string.
+ //
+ String = (WCHAR *) malloc ((Len + 1) * sizeof (WCHAR));
+ if (String == NULL) {
+ Error (NULL, 0, 0, "application error", "failed to allocate memory");
+ return ;
+ }
+
+ To = String;
+ while (From < SourceFile->FileBufferPtr) {
+ switch (*From) {
+ case UNICODE_LF:
+ case 0:
+ break;
+
+ default:
+ *To = *From;
+ To++;
+ break;
+ }
+
+ From++;
+ }
+
+ //
+ // String[Len] = 0;
+ //
+ *To = 0;
+ StringDBAddString (Language, NULL, NULL, String, TRUE, 0);
+ }
+}
+
+static
+BOOLEAN
+IsWhiteSpace (
+ SOURCE_FILE *SourceFile
+ )
+{
+ switch (SourceFile->FileBufferPtr[0]) {
+ case UNICODE_NULL:
+ case UNICODE_CR:
+ case UNICODE_SPACE:
+ case UNICODE_TAB:
+ case UNICODE_LF:
+ return TRUE;
+
+ default:
+ return FALSE;
+ }
+}
+
+static
+UINT32
+SkipWhiteSpace (
+ SOURCE_FILE *SourceFile
+ )
+{
+ UINT32 Count;
+
+ Count = 0;
+ while (!EndOfFile (SourceFile)) {
+ Count++;
+ switch (*SourceFile->FileBufferPtr) {
+ case UNICODE_NULL:
+ case UNICODE_CR:
+ case UNICODE_SPACE:
+ case UNICODE_TAB:
+ SourceFile->FileBufferPtr++;
+ break;
+
+ case UNICODE_LF:
+ SourceFile->FileBufferPtr++;
+ SourceFile->LineNum++;
+ if (mGlobals.Verbose) {
+ printf ("%d: %S\n", SourceFile->LineNum, SourceFile->FileBufferPtr);
+ }
+ break;
+
+ default:
+ return Count - 1;
+ }
+ }
+ //
+ // Some tokens require trailing whitespace. If we're at the end of the
+ // file, then we count that as well.
+ //
+ if ((Count == 0) && (EndOfFile (SourceFile))) {
+ Count++;
+ }
+
+ return Count;
+}
+
+static
+UINT32
+wstrcmp (
+ WCHAR *Buffer,
+ WCHAR *Str
+ )
+{
+ UINT32 Len;
+
+ Len = 0;
+ while (*Str == *Buffer) {
+ Buffer++;
+ Str++;
+ Len++;
+ }
+
+ if (*Str) {
+ return 0;
+ }
+
+ return Len;
+}
+//
+// Given a filename, try to find it along the include paths.
+//
+static
+FILE *
+FindFile (
+ IN CHAR8 *FileName,
+ OUT CHAR8 *FoundFileName,
+ IN UINT32 FoundFileNameLen
+ )
+{
+ FILE *Fptr;
+ TEXT_STRING_LIST *List;
+
+ //
+ // Traverse the list of paths and try to find the file
+ //
+ List = mGlobals.IncludePaths;
+ while (List != NULL) {
+ //
+ // Put the path and filename together
+ //
+ if (strlen (List->Str) + strlen (FileName) + 1 > FoundFileNameLen) {
+ Error (PROGRAM_NAME, 0, 0, NULL, "internal error - cannot concatenate path+filename");
+ return NULL;
+ }
+ //
+ // Append the filename to this include path and try to open the file.
+ //
+ strcpy (FoundFileName, List->Str);
+ strcat (FoundFileName, FileName);
+ if ((Fptr = fopen (FoundFileName, "rb")) != NULL) {
+ //
+ // Return the file pointer
+ //
+ return Fptr;
+ }
+
+ List = List->Next;
+ }
+ //
+ // Not found
+ //
+ FoundFileName[0] = 0;
+ return NULL;
+}
+//
+// Process the command-line arguments
+//
+static
+STATUS
+ProcessArgs (
+ int Argc,
+ char *Argv[]
+ )
+{
+ TEXT_STRING_LIST *NewList;
+ //
+ // Clear our globals
+ //
+ memset ((char *) &mGlobals, 0, sizeof (mGlobals));
+ strcpy (mGlobals.BaseName, DEFAULT_BASE_NAME);
+ //
+ // Skip program name
+ //
+ Argc--;
+ Argv++;
+
+ if (Argc == 0) {
+ Usage ();
+ return STATUS_ERROR;
+ }
+
+ mGlobals.Mode = MODE_UNKNOWN;
+ //
+ // Process until no more -args.
+ //
+ while ((Argc > 0) && (Argv[0][0] == '-')) {
+ //
+ // -parse option
+ //
+ if (stricmp (Argv[0], "-parse") == 0) {
+ if (mGlobals.Mode != MODE_UNKNOWN) {
+ Error (NULL, 0, 0, "only one of -parse/-scan/-dump allowed", NULL);
+ return STATUS_ERROR;
+ }
+
+ mGlobals.Mode = MODE_PARSE;
+ //
+ // -scan option
+ //
+ } else if (stricmp (Argv[0], "-scan") == 0) {
+ if (mGlobals.Mode != MODE_UNKNOWN) {
+ Error (NULL, 0, 0, "only one of -parse/-scan/-dump allowed", NULL);
+ return STATUS_ERROR;
+ }
+
+ mGlobals.Mode = MODE_SCAN;
+ //
+ // -vscan verbose scanning option
+ //
+ } else if (stricmp (Argv[0], "-vscan") == 0) {
+ mGlobals.VerboseScan = TRUE;
+ //
+ // -dump option
+ //
+ } else if (stricmp (Argv[0], "-dump") == 0) {
+ if (mGlobals.Mode != MODE_UNKNOWN) {
+ Error (NULL, 0, 0, "only one of -parse/-scan/-dump allowed", NULL);
+ return STATUS_ERROR;
+ }
+
+ mGlobals.Mode = MODE_DUMP;
+ } else if (stricmp (Argv[0], "-uqs") == 0) {
+ mGlobals.UnquotedStrings = TRUE;
+ //
+ // -i path add include search path when parsing
+ //
+ } else if (stricmp (Argv[0], "-i") == 0) {
+ //
+ // check for one more arg
+ //
+ if ((Argc <= 1) || (Argv[1][0] == '-')) {
+ Error (PROGRAM_NAME, 0, 0, Argv[0], "missing include path");
+ return STATUS_ERROR;
+ }
+ //
+ // Allocate memory for a new list element, fill it in, and
+ // add it to our list of include paths. Always make sure it
+ // has a "\" on the end of it.
+ //
+ NewList = malloc (sizeof (TEXT_STRING_LIST));
+ if (NewList == NULL) {
+ Error (PROGRAM_NAME, 0, 0, NULL, "memory allocation failure");
+ return STATUS_ERROR;
+ }
+
+ memset ((char *) NewList, 0, sizeof (TEXT_STRING_LIST));
+ NewList->Str = malloc (strlen (Argv[1]) + 2);
+ if (NewList->Str == NULL) {
+ free (NewList);
+ Error (PROGRAM_NAME, 0, 0, NULL, "memory allocation failure");
+ return STATUS_ERROR;
+ }
+
+ strcpy (NewList->Str, Argv[1]);
+ if (NewList->Str[strlen (NewList->Str) - 1] != '\\') {
+ strcat (NewList->Str, "\\");
+ }
+ //
+ // Add it to our linked list
+ //
+ if (mGlobals.IncludePaths == NULL) {
+ mGlobals.IncludePaths = NewList;
+ } else {
+ mGlobals.LastIncludePath->Next = NewList;
+ }
+
+ mGlobals.LastIncludePath = NewList;
+ Argc--;
+ Argv++;
+ } else if (stricmp (Argv[0], "-if") == 0) {
+ //
+ // Indirection file -- check for one more arg
+ //
+ if ((Argc <= 1) || (Argv[1][0] == '-')) {
+ Error (PROGRAM_NAME, 0, 0, Argv[0], "missing indirection file name");
+ return STATUS_ERROR;
+ }
+ //
+ // Allocate memory for a new list element, fill it in, and
+ // add it to our list of include paths. Always make sure it
+ // has a "\" on the end of it.
+ //
+ NewList = malloc (sizeof (TEXT_STRING_LIST));
+ if (NewList == NULL) {
+ Error (PROGRAM_NAME, 0, 0, NULL, "memory allocation failure");
+ return STATUS_ERROR;
+ }
+
+ memset ((char *) NewList, 0, sizeof (TEXT_STRING_LIST));
+ NewList->Str = malloc (strlen (Argv[1]) + 1);
+ if (NewList->Str == NULL) {
+ free (NewList);
+ Error (PROGRAM_NAME, 0, 0, NULL, "memory allocation failure");
+ return STATUS_ERROR;
+ }
+
+ strcpy (NewList->Str, Argv[1]);
+ //
+ // Add it to our linked list
+ //
+ if (mGlobals.IndirectionFileName == NULL) {
+ mGlobals.IndirectionFileName = NewList;
+ } else {
+ mGlobals.LastIndirectionFileName->Next = NewList;
+ }
+
+ mGlobals.LastIndirectionFileName = NewList;
+ Argc--;
+ Argv++;
+ } else if (stricmp (Argv[0], "-db") == 0) {
+ //
+ // -db option to specify a database file.
+ // Check for one more arg (the database file name)
+ //
+ if ((Argc <= 1) || (Argv[1][0] == '-')) {
+ Error (PROGRAM_NAME, 0, 0, Argv[0], "missing database file name");
+ return STATUS_ERROR;
+ }
+
+ NewList = malloc (sizeof (TEXT_STRING_LIST));
+ if (NewList == NULL) {
+ Error (PROGRAM_NAME, 0, 0, NULL, "memory allocation failure");
+ return STATUS_ERROR;
+ }
+
+ memset ((char *) NewList, 0, sizeof (TEXT_STRING_LIST));
+ NewList->Str = malloc (strlen (Argv[1]) + 1);
+ if (NewList->Str == NULL) {
+ free (NewList);
+ Error (PROGRAM_NAME, 0, 0, NULL, "memory allocation failure");
+ return STATUS_ERROR;
+ }
+
+ strcpy (NewList->Str, Argv[1]);
+ //
+ // Add it to our linked list
+ //
+ if (mGlobals.DatabaseFileName == NULL) {
+ mGlobals.DatabaseFileName = NewList;
+ } else {
+ mGlobals.LastDatabaseFileName->Next = NewList;
+ }
+
+ mGlobals.LastDatabaseFileName = NewList;
+ Argc--;
+ Argv++;
+ } else if (stricmp (Argv[0], "-ou") == 0) {
+ //
+ // -ou option to specify an output unicode file to
+ // which we can dump our database.
+ //
+ if ((Argc <= 1) || (Argv[1][0] == '-')) {
+ Error (PROGRAM_NAME, 0, 0, Argv[0], "missing database dump output file name");
+ return STATUS_ERROR;
+ }
+
+ if (mGlobals.DumpUFileName[0] == 0) {
+ strcpy (mGlobals.DumpUFileName, Argv[1]);
+ } else {
+ Error (PROGRAM_NAME, 0, 0, Argv[1], "-ou option already specified with '%s'", mGlobals.DumpUFileName);
+ return STATUS_ERROR;
+ }
+
+ Argc--;
+ Argv++;
+ } else if (stricmp (Argv[0], "-hpk") == 0) {
+ //
+ // -hpk option to create an HII export pack of the input database file
+ //
+ if ((Argc <= 1) || (Argv[1][0] == '-')) {
+ Error (PROGRAM_NAME, 0, 0, Argv[0], "missing raw string data dump output file name");
+ return STATUS_ERROR;
+ }
+
+ if (mGlobals.HiiExportPackFileName[0] == 0) {
+ strcpy (mGlobals.HiiExportPackFileName, Argv[1]);
+ } else {
+ Error (PROGRAM_NAME, 0, 0, Argv[1], "-or option already specified with '%s'", mGlobals.HiiExportPackFileName);
+ return STATUS_ERROR;
+ }
+
+ Argc--;
+ Argv++;
+ } else if ((stricmp (Argv[0], "-?") == 0) || (stricmp (Argv[0], "-h") == 0)) {
+ Usage ();
+ return STATUS_ERROR;
+ } else if (stricmp (Argv[0], "-v") == 0) {
+ mGlobals.Verbose = 1;
+ } else if (stricmp (Argv[0], "-vdbw") == 0) {
+ mGlobals.VerboseDatabaseWrite = 1;
+ } else if (stricmp (Argv[0], "-vdbr") == 0) {
+ mGlobals.VerboseDatabaseRead = 1;
+ } else if (stricmp (Argv[0], "-newdb") == 0) {
+ mGlobals.NewDatabase = 1;
+ } else if (stricmp (Argv[0], "-ignorenotfound") == 0) {
+ mGlobals.IgnoreNotFound = 1;
+ } else if (stricmp (Argv[0], "-oc") == 0) {
+ //
+ // check for one more arg
+ //
+ if ((Argc <= 1) || (Argv[1][0] == '-')) {
+ Error (PROGRAM_NAME, 0, 0, Argv[0], "missing output C filename");
+ return STATUS_ERROR;
+ }
+
+ strcpy (mGlobals.StringCFileName, Argv[1]);
+ Argc--;
+ Argv++;
+ } else if (stricmp (Argv[0], "-bn") == 0) {
+ //
+ // check for one more arg
+ //
+ if ((Argc <= 1) || (Argv[1][0] == '-')) {
+ Error (PROGRAM_NAME, 0, 0, Argv[0], "missing base name");
+ Usage ();
+ return STATUS_ERROR;
+ }
+
+ strcpy (mGlobals.BaseName, Argv[1]);
+ Argc--;
+ Argv++;
+ } else if (stricmp (Argv[0], "-oh") == 0) {
+ //
+ // -oh to specify output .h defines file name
+ //
+ if ((Argc <= 1) || (Argv[1][0] == '-')) {
+ Error (PROGRAM_NAME, 0, 0, Argv[0], "missing output .h filename");
+ return STATUS_ERROR;
+ }
+
+ strcpy (mGlobals.StringHFileName, Argv[1]);
+ Argc--;
+ Argv++;
+ } else if (stricmp (Argv[0], "-skipext") == 0) {
+ //
+ // -skipext to skip scanning of files with certain filename extensions
+ //
+ if ((Argc <= 1) || (Argv[1][0] == '-')) {
+ Error (PROGRAM_NAME, 0, 0, Argv[0], "missing filename extension");
+ return STATUS_ERROR;
+ }
+ //
+ // Allocate memory for a new list element, fill it in, and
+ // add it to our list of excluded extensions. Always make sure it
+ // has a "." as the first character.
+ //
+ NewList = malloc (sizeof (TEXT_STRING_LIST));
+ if (NewList == NULL) {
+ Error (PROGRAM_NAME, 0, 0, NULL, "memory allocation failure");
+ return STATUS_ERROR;
+ }
+
+ memset ((char *) NewList, 0, sizeof (TEXT_STRING_LIST));
+ NewList->Str = malloc (strlen (Argv[1]) + 2);
+ if (NewList->Str == NULL) {
+ free (NewList);
+ Error (PROGRAM_NAME, 0, 0, NULL, "memory allocation failure");
+ return STATUS_ERROR;
+ }
+
+ if (Argv[1][0] == '.') {
+ strcpy (NewList->Str, Argv[1]);
+ } else {
+ NewList->Str[0] = '.';
+ strcpy (NewList->Str + 1, Argv[1]);
+ }
+ //
+ // Add it to our linked list
+ //
+ if (mGlobals.SkipExt == NULL) {
+ mGlobals.SkipExt = NewList;
+ } else {
+ mGlobals.LastSkipExt->Next = NewList;
+ }
+
+ mGlobals.LastSkipExt = NewList;
+ Argc--;
+ Argv++;
+ } else if (stricmp (Argv[0], "-lang") == 0) {
+ //
+ // "-lang eng" or "-lang spa+cat" to only output certain languages
+ //
+ if ((Argc <= 1) || (Argv[1][0] == '-')) {
+ Error (PROGRAM_NAME, 0, 0, Argv[0], "missing language name");
+ Usage ();
+ return STATUS_ERROR;
+ }
+
+ if (AddCommandLineLanguage (Argv[1]) != STATUS_SUCCESS) {
+ return STATUS_ERROR;
+ }
+
+ Argc--;
+ Argv++;
+ } else if (stricmp (Argv[0], "-od") == 0) {
+ //
+ // Output database file name -- check for another arg
+ //
+ if ((Argc <= 1) || (Argv[1][0] == '-')) {
+ Error (PROGRAM_NAME, 0, 0, Argv[0], "missing output database file name");
+ return STATUS_ERROR;
+ }
+
+ strcpy (mGlobals.OutputDatabaseFileName, Argv[1]);
+ Argv++;
+ Argc--;
+ } else {
+ //
+ // Unrecognized arg
+ //
+ Error (PROGRAM_NAME, 0, 0, Argv[0], "unrecognized option");
+ Usage ();
+ return STATUS_ERROR;
+ }
+
+ Argv++;
+ Argc--;
+ }
+ //
+ // Make sure they specified the mode parse/scan/dump
+ //
+ if (mGlobals.Mode == MODE_UNKNOWN) {
+ Error (NULL, 0, 0, "must specify one of -parse/-scan/-dump", NULL);
+ return STATUS_ERROR;
+ }
+ //
+ // All modes require a database filename
+ //
+ if (mGlobals.DatabaseFileName == 0) {
+ Error (NULL, 0, 0, "must specify a database filename using -db DbFileName", NULL);
+ Usage ();
+ return STATUS_ERROR;
+ }
+ //
+ // If dumping the database file, then return immediately if all
+ // parameters check out.
+ //
+ if (mGlobals.Mode == MODE_DUMP) {
+ //
+ // Not much use if they didn't specify -oh or -oc or -ou or -hpk
+ //
+ if ((mGlobals.DumpUFileName[0] == 0) &&
+ (mGlobals.StringHFileName[0] == 0) &&
+ (mGlobals.StringCFileName[0] == 0) &&
+ (mGlobals.HiiExportPackFileName[0] == 0)
+ ) {
+ Error (NULL, 0, 0, "-dump without -oc/-oh/-ou/-hpk is a NOP", NULL);
+ return STATUS_ERROR;
+ }
+
+ return STATUS_SUCCESS;
+ }
+ //
+ // Had to specify source string file and output string defines header filename.
+ //
+ if (mGlobals.Mode == MODE_SCAN) {
+ if (Argc < 1) {
+ Error (PROGRAM_NAME, 0, 0, NULL, "must specify at least one source file to scan with -scan");
+ Usage ();
+ return STATUS_ERROR;
+ }
+ //
+ // Get the list of filenames
+ //
+ while (Argc > 0) {
+ NewList = malloc (sizeof (TEXT_STRING_LIST));
+ if (NewList == NULL) {
+ Error (PROGRAM_NAME, 0, 0, "memory allocation failure", NULL);
+ return STATUS_ERROR;
+ }
+
+ memset (NewList, 0, sizeof (TEXT_STRING_LIST));
+ NewList->Str = (CHAR8 *) malloc (strlen (Argv[0]) + 1);
+ if (NewList->Str == NULL) {
+ Error (PROGRAM_NAME, 0, 0, "memory allocation failure", NULL);
+ return STATUS_ERROR;
+ }
+
+ strcpy (NewList->Str, Argv[0]);
+ if (mGlobals.ScanFileName == NULL) {
+ mGlobals.ScanFileName = NewList;
+ } else {
+ mGlobals.LastScanFileName->Next = NewList;
+ }
+
+ mGlobals.LastScanFileName = NewList;
+ Argc--;
+ Argv++;
+ }
+ } else {
+ //
+ // Parse mode -- must specify an input unicode file name
+ //
+ if (Argc < 1) {
+ Error (PROGRAM_NAME, 0, 0, NULL, "must specify input unicode string file name with -parse");
+ Usage ();
+ return STATUS_ERROR;
+ }
+
+ strcpy (mGlobals.SourceFiles.FileName, Argv[0]);
+ }
+
+ return STATUS_SUCCESS;
+}
+//
+// Found "-lang eng,spa+cat" on the command line. Parse the
+// language list and save the setting for later processing.
+//
+static
+STATUS
+AddCommandLineLanguage (
+ IN CHAR8 *Language
+ )
+{
+ WCHAR_STRING_LIST *WNewList;
+ WCHAR *From;
+ WCHAR *To;
+ //
+ // Keep processing the input string until we find the end.
+ //
+ while (*Language) {
+ //
+ // Allocate memory for a new list element, fill it in, and
+ // add it to our list.
+ //
+ WNewList = MALLOC (sizeof (WCHAR_STRING_LIST));
+ if (WNewList == NULL) {
+ Error (PROGRAM_NAME, 0, 0, NULL, "memory allocation failure");
+ return STATUS_ERROR;
+ }
+
+ memset ((char *) WNewList, 0, sizeof (WCHAR_STRING_LIST));
+ WNewList->Str = malloc ((strlen (Language) + 1) * sizeof (WCHAR));
+ if (WNewList->Str == NULL) {
+ free (WNewList);
+ Error (PROGRAM_NAME, 0, 0, NULL, "memory allocation failure");
+ return STATUS_ERROR;
+ }
+ //
+ // Copy it as unicode to our new structure. Then remove the
+ // plus signs in it, and verify each language name is 3 characters
+ // long. If we find a comma, then we're done with this group, so
+ // break out.
+ //
+ UnicodeSPrint (WNewList->Str, (strlen (Language) + 1) * sizeof (WCHAR), L"%a", Language);
+ From = To = WNewList->Str;
+ while (*From) {
+ if (*From == L',') {
+ break;
+ }
+
+ if ((StrLen (From) < LANGUAGE_IDENTIFIER_NAME_LEN) ||
+ (
+ (From[LANGUAGE_IDENTIFIER_NAME_LEN] != 0) &&
+ (From[LANGUAGE_IDENTIFIER_NAME_LEN] != UNICODE_PLUS_SIGN) &&
+ (From[LANGUAGE_IDENTIFIER_NAME_LEN] != L',')
+ )
+ ) {
+ Error (PROGRAM_NAME, 0, 0, Language, "invalid format for language name on command line");
+ FREE (WNewList->Str);
+ FREE (WNewList);
+ return STATUS_ERROR;
+ }
+
+ StrnCpy (To, From, LANGUAGE_IDENTIFIER_NAME_LEN);
+ To += LANGUAGE_IDENTIFIER_NAME_LEN;
+ From += LANGUAGE_IDENTIFIER_NAME_LEN;
+ if (*From == L'+') {
+ From++;
+ }
+ }
+
+ *To = 0;
+ //
+ // Add it to our linked list
+ //
+ if (mGlobals.Language == NULL) {
+ mGlobals.Language = WNewList;
+ } else {
+ mGlobals.LastLanguage->Next = WNewList;
+ }
+
+ mGlobals.LastLanguage = WNewList;
+ //
+ // Skip to next entry (comma-separated list)
+ //
+ while (*Language) {
+ if (*Language == L',') {
+ Language++;
+ break;
+ }
+
+ Language++;
+ }
+ }
+
+ return STATUS_SUCCESS;
+}
+//
+// The contents of the text file are expected to be (one per line)
+// STRING_IDENTIFIER_NAME ScopeName
+// For example:
+// STR_ID_MY_FAVORITE_STRING IBM
+//
+static
+STATUS
+ParseIndirectionFiles (
+ TEXT_STRING_LIST *Files
+ )
+{
+ FILE *Fptr;
+ CHAR8 Line[200];
+ CHAR8 *StringName;
+ CHAR8 *ScopeName;
+ CHAR8 *End;
+ UINT32 LineCount;
+ WCHAR_MATCHING_STRING_LIST *NewList;
+
+ Line[sizeof (Line) - 1] = 0;
+ Fptr = NULL;
+ while (Files != NULL) {
+ Fptr = fopen (Files->Str, "r");
+ LineCount = 0;
+ if (Fptr == NULL) {
+ Error (NULL, 0, 0, Files->Str, "failed to open input indirection file for reading");
+ return STATUS_ERROR;
+ }
+
+ while (fgets (Line, sizeof (Line), Fptr) != NULL) {
+ //
+ // remove terminating newline for error printing purposes.
+ //
+ if (Line[strlen (Line) - 1] == '\n') {
+ Line[strlen (Line) - 1] = 0;
+ }
+
+ LineCount++;
+ if (Line[sizeof (Line) - 1] != 0) {
+ Error (Files->Str, LineCount, 0, "line length exceeds maximum supported", NULL);
+ goto Done;
+ }
+
+ StringName = Line;
+ while (*StringName && (isspace (*StringName))) {
+ StringName++;
+ }
+
+ if (*StringName) {
+ if ((*StringName == '_') || isalpha (*StringName)) {
+ End = StringName;
+ while ((*End) && (*End == '_') || (isalnum (*End))) {
+ End++;
+ }
+
+ if (isspace (*End)) {
+ *End = 0;
+ End++;
+ while (isspace (*End)) {
+ End++;
+ }
+
+ if (*End) {
+ ScopeName = End;
+ while (*End && !isspace (*End)) {
+ End++;
+ }
+
+ *End = 0;
+ //
+ // Add the string name/scope pair
+ //
+ NewList = malloc (sizeof (WCHAR_MATCHING_STRING_LIST));
+ if (NewList == NULL) {
+ Error (NULL, 0, 0, "memory allocation error", NULL);
+ goto Done;
+ }
+
+ memset (NewList, 0, sizeof (WCHAR_MATCHING_STRING_LIST));
+ NewList->Str1 = (WCHAR *) malloc ((strlen (StringName) + 1) * sizeof (WCHAR));
+ NewList->Str2 = (WCHAR *) malloc ((strlen (ScopeName) + 1) * sizeof (WCHAR));
+ if ((NewList->Str1 == NULL) || (NewList->Str2 == NULL)) {
+ Error (NULL, 0, 0, "memory allocation error", NULL);
+ goto Done;
+ }
+
+ UnicodeSPrint (NewList->Str1, strlen (StringName) + 1, L"%a", StringName);
+ UnicodeSPrint (NewList->Str2, strlen (ScopeName) + 1, L"%a", ScopeName);
+ if (mGlobals.IndirectionList == NULL) {
+ mGlobals.IndirectionList = NewList;
+ } else {
+ mGlobals.LastIndirectionList->Next = NewList;
+ }
+
+ mGlobals.LastIndirectionList = NewList;
+ } else {
+ Error (Files->Str, LineCount, 0, StringName, "invalid line : expected 'StringIdentifier Scope'");
+ goto Done;
+ }
+ } else {
+ Error (Files->Str, LineCount, 0, StringName, "invalid line : expected 'StringIdentifier Scope'");
+ goto Done;
+ }
+ } else {
+ Error (Files->Str, LineCount, 0, StringName, "invalid string identifier");
+ goto Done;
+ }
+ }
+ }
+
+ fclose (Fptr);
+ Fptr = NULL;
+ Files = Files->Next;
+ }
+
+Done:
+ if (Fptr != NULL) {
+ fclose (Fptr);
+ return STATUS_ERROR;
+ }
+
+ return STATUS_SUCCESS;
+}
+
+static
+STATUS
+ScanFiles (
+ TEXT_STRING_LIST *ScanFiles
+ )
+{
+ char Line[MAX_LINE_LEN];
+ FILE *Fptr;
+ UINT32 LineNum;
+ char *Cptr;
+ char *SavePtr;
+ char *TermPtr;
+ char *StringTokenPos;
+ TEXT_STRING_LIST *SList;
+ BOOLEAN SkipIt;
+
+ //
+ // Put a null-terminator at the end of the line. If we read in
+ // a line longer than we support, then we can catch it.
+ //
+ Line[MAX_LINE_LEN - 1] = 0;
+ //
+ // Process each file. If they gave us a skip extension list, then
+ // skip it if the extension matches.
+ //
+ while (ScanFiles != NULL) {
+ SkipIt = FALSE;
+ for (SList = mGlobals.SkipExt; SList != NULL; SList = SList->Next) {
+ if ((strlen (ScanFiles->Str) > strlen (SList->Str)) &&
+ (strcmp (ScanFiles->Str + strlen (ScanFiles->Str) - strlen (SList->Str), SList->Str) == 0)
+ ) {
+ SkipIt = TRUE;
+ //
+ // printf ("Match: %s : %s\n", ScanFiles->Str, SList->Str);
+ //
+ break;
+ }
+ }
+
+ if (!SkipIt) {
+ if (mGlobals.VerboseScan) {
+ printf ("Scanning %s\n", ScanFiles->Str);
+ }
+
+ Fptr = fopen (ScanFiles->Str, "r");
+ if (Fptr == NULL) {
+ Error (NULL, 0, 0, ScanFiles->Str, "failed to open input file for scanning");
+ return STATUS_ERROR;
+ }
+
+ LineNum = 0;
+ while (fgets (Line, sizeof (Line), Fptr) != NULL) {
+ LineNum++;
+ if (Line[MAX_LINE_LEN - 1] != 0) {
+ Error (ScanFiles->Str, LineNum, 0, "line length exceeds maximum supported by tool", NULL);
+ fclose (Fptr);
+ return STATUS_ERROR;
+ }
+ //
+ // Remove the newline from the input line so we can print a warning message
+ //
+ if (Line[strlen (Line) - 1] == '\n') {
+ Line[strlen (Line) - 1] = 0;
+ }
+ //
+ // Terminate the line at // comments
+ //
+ Cptr = strstr (Line, "//");
+ if (Cptr != NULL) {
+ *Cptr = 0;
+ }
+
+ Cptr = Line;
+ while ((Cptr = strstr (Cptr, STRING_TOKEN)) != NULL) {
+ //
+ // Found "STRING_TOKEN". Make sure we don't have NUM_STRING_TOKENS or
+ // something like that. Then make sure it's followed by
+ // an open parenthesis, a string identifier, and then a closing
+ // parenthesis.
+ //
+ if (mGlobals.VerboseScan) {
+ printf (" %d: %s", LineNum, Cptr);
+ }
+
+ if (((Cptr == Line) || (!IsValidIdentifierChar (*(Cptr - 1), FALSE))) &&
+ (!IsValidIdentifierChar (*(Cptr + sizeof (STRING_TOKEN) - 1), FALSE))
+ ) {
+ StringTokenPos = Cptr;
+ SavePtr = Cptr;
+ Cptr += strlen (STRING_TOKEN);
+ while (*Cptr && isspace (*Cptr) && (*Cptr != '(')) {
+ Cptr++;
+ }
+
+ if (*Cptr != '(') {
+ Warning (ScanFiles->Str, LineNum, 0, StringTokenPos, "expected "STRING_TOKEN "(identifier)");
+ } else {
+ //
+ // Skip over the open-parenthesis and find the next non-blank character
+ //
+ Cptr++;
+ while (isspace (*Cptr)) {
+ Cptr++;
+ }
+
+ SavePtr = Cptr;
+ if ((*Cptr == '_') || isalpha (*Cptr)) {
+ while ((*Cptr == '_') || (isalnum (*Cptr))) {
+ Cptr++;
+ }
+
+ TermPtr = Cptr;
+ while (*Cptr && isspace (*Cptr)) {
+ Cptr++;
+ }
+
+ if (*Cptr != ')') {
+ Warning (ScanFiles->Str, LineNum, 0, StringTokenPos, "expected "STRING_TOKEN "(identifier)");
+ }
+
+ if (*TermPtr) {
+ *TermPtr = 0;
+ Cptr = TermPtr + 1;
+ } else {
+ Cptr = TermPtr;
+ }
+ //
+ // Add the string identifier to the list of used strings
+ //
+ ParserSetPosition (ScanFiles->Str, LineNum);
+ StringDBSetStringReferenced (SavePtr, mGlobals.IgnoreNotFound);
+ if (mGlobals.VerboseScan) {
+ printf ("...referenced %s", SavePtr);
+ }
+ } else {
+ Warning (ScanFiles->Str, LineNum, 0, StringTokenPos, "expected valid string identifier name");
+ }
+ }
+ } else {
+ //
+ // Found it, but it's a substring of something else. Advance our pointer.
+ //
+ Cptr++;
+ }
+
+ if (mGlobals.VerboseScan) {
+ printf ("\n");
+ }
+ }
+ }
+
+ fclose (Fptr);
+ } else {
+ //
+ // Skipping this file type
+ //
+ if (mGlobals.VerboseScan) {
+ printf ("Skip scanning of %s\n", ScanFiles->Str);
+ }
+ }
+
+ ScanFiles = ScanFiles->Next;
+ }
+
+ return STATUS_SUCCESS;
+}
+//
+// Free the global string lists we allocated memory for
+//
+static
+void
+FreeLists (
+ VOID
+ )
+{
+ TEXT_STRING_LIST *Temp;
+ WCHAR_STRING_LIST *WTemp;
+
+ //
+ // Traverse the include paths, freeing each
+ //
+ while (mGlobals.IncludePaths != NULL) {
+ Temp = mGlobals.IncludePaths->Next;
+ free (mGlobals.IncludePaths->Str);
+ free (mGlobals.IncludePaths);
+ mGlobals.IncludePaths = Temp;
+ }
+ //
+ // If we did a scan, then free up our
+ // list of files to scan.
+ //
+ while (mGlobals.ScanFileName != NULL) {
+ Temp = mGlobals.ScanFileName->Next;
+ free (mGlobals.ScanFileName->Str);
+ free (mGlobals.ScanFileName);
+ mGlobals.ScanFileName = Temp;
+ }
+ //
+ // If they gave us a list of filename extensions to
+ // skip on scan, then free them up.
+ //
+ while (mGlobals.SkipExt != NULL) {
+ Temp = mGlobals.SkipExt->Next;
+ free (mGlobals.SkipExt->Str);
+ free (mGlobals.SkipExt);
+ mGlobals.SkipExt = Temp;
+ }
+ //
+ // Free up any languages specified
+ //
+ while (mGlobals.Language != NULL) {
+ WTemp = mGlobals.Language->Next;
+ free (mGlobals.Language->Str);
+ free (mGlobals.Language);
+ mGlobals.Language = WTemp;
+ }
+ //
+ // Free up our indirection list
+ //
+ while (mGlobals.IndirectionList != NULL) {
+ mGlobals.LastIndirectionList = mGlobals.IndirectionList->Next;
+ free (mGlobals.IndirectionList->Str1);
+ free (mGlobals.IndirectionList->Str2);
+ free (mGlobals.IndirectionList);
+ mGlobals.IndirectionList = mGlobals.LastIndirectionList;
+ }
+
+ while (mGlobals.IndirectionFileName != NULL) {
+ mGlobals.LastIndirectionFileName = mGlobals.IndirectionFileName->Next;
+ free (mGlobals.IndirectionFileName->Str);
+ free (mGlobals.IndirectionFileName);
+ mGlobals.IndirectionFileName = mGlobals.LastIndirectionFileName;
+ }
+}
+
+static
+BOOLEAN
+IsValidIdentifierChar (
+ CHAR8 Char,
+ BOOLEAN FirstChar
+ )
+{
+ //
+ // If it's the first character of an identifier, then
+ // it must be one of [A-Za-z_].
+ //
+ if (FirstChar) {
+ if (isalpha (Char) || (Char == '_')) {
+ return TRUE;
+ }
+ } else {
+ //
+ // If it's not the first character, then it can
+ // be one of [A-Za-z_0-9]
+ //
+ if (isalnum (Char) || (Char == '_')) {
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+static
+void
+RewindFile (
+ SOURCE_FILE *SourceFile
+ )
+{
+ SourceFile->LineNum = 1;
+ SourceFile->FileBufferPtr = SourceFile->FileBuffer;
+ SourceFile->EndOfFile = 0;
+}
+
+static
+BOOLEAN
+SkipTo (
+ SOURCE_FILE *SourceFile,
+ WCHAR WChar,
+ BOOLEAN StopAfterNewline
+ )
+{
+ while (!EndOfFile (SourceFile)) {
+ //
+ // Check for the character of interest
+ //
+ if (SourceFile->FileBufferPtr[0] == WChar) {
+ return TRUE;
+ } else {
+ if (SourceFile->FileBufferPtr[0] == UNICODE_LF) {
+ SourceFile->LineNum++;
+ if (StopAfterNewline) {
+ SourceFile->FileBufferPtr++;
+ if (SourceFile->FileBufferPtr[0] == 0) {
+ SourceFile->FileBufferPtr++;
+ }
+
+ return FALSE;
+ }
+ }
+
+ SourceFile->FileBufferPtr++;
+ }
+ }
+
+ return FALSE;
+}
+
+static
+void
+Usage (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Print usage information for this utility.
+
+Arguments:
+
+ None.
+
+Returns:
+
+ Nothing.
+
+--*/
+{
+ int Index;
+ static const char *Str[] = {
+ "",
+ PROGRAM_NAME " version "TOOL_VERSION " -- process unicode strings file",
+ " Usage: "PROGRAM_NAME " -parse {parse options} [FileNames]",
+ " "PROGRAM_NAME " -scan {scan options} [FileName]",
+ " "PROGRAM_NAME " -dump {dump options}",
+ " Common options include:",
+ " -h or -? for this help information",
+ " -db Database required name of output/input database file",
+ " -bn BaseName for use in the .h and .c output files",
+ " Default = "DEFAULT_BASE_NAME,
+ " -v for verbose output",
+ " -vdbw for verbose output when writing database",
+ " -vdbr for verbose output when reading database",
+ " -od FileName to specify an output database file name",
+ " Parse options include:",
+ " -i IncludePath add IncludePath to list of search paths",
+ " -newdb to not read in existing database file",
+ " -uqs to indicate that unquoted strings are used",
+ " FileNames name of one or more unicode files to parse",
+ " Scan options include:",
+ " -scan scan text file(s) for STRING_TOKEN() usage",
+ " -skipext .ext to skip scan of files with .ext filename extension",
+ " -ignorenotfound ignore if a given STRING_TOKEN(STR) is not ",
+ " found in the database",
+ " FileNames one or more files to scan",
+ " Dump options include:",
+ " -oc FileName write string data to FileName",
+ " -oh FileName write string defines to FileName",
+ " -ou FileName dump database to unicode file FileName",
+ " -lang Lang only dump for the language 'Lang'",
+ " -if FileName to specify an indirection file",
+ " -hpk FileName to create an HII export pack of the strings",
+ "",
+ " The expected process is to parse a unicode string file to create an initial",
+ " database of string identifier names and string definitions. Then text files",
+ " should be scanned for STRING_TOKEN() usages, and the referenced",
+ " strings will be tagged as used in the database. After all files have been",
+ " scanned, then the database should be dumped to create the necessary output",
+ " files.",
+ "",
+ NULL
+ };
+ for (Index = 0; Str[Index] != NULL; Index++) {
+ fprintf (stdout, "%s\n", Str[Index]);
+ }
+}
diff --git a/Source/StrGather/StrGather.h b/Source/StrGather/StrGather.h
new file mode 100644
index 0000000..65dc15c
--- /dev/null
+++ b/Source/StrGather/StrGather.h
@@ -0,0 +1,84 @@
+/*++
+
+Copyright (c) 2004, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ StrGather.h
+
+Abstract:
+
+ Common defines and prototypes for StrGather.
+
+--*/
+
+#ifndef _STR_GATHER_H_
+#define _STR_GATHER_H_
+
+#define MALLOC(size) malloc (size)
+#define FREE(ptr) free (ptr)
+
+#define PROGRAM_NAME "StrGather"
+
+typedef CHAR16 WCHAR;
+
+#define UNICODE_TO_ASCII(w) (INT8) ((w) & 0xFF)
+#define ASCII_TO_UNICODE(a) (WCHAR) ((UINT8) (a))
+
+#define UNICODE_HASH L'#'
+#define UNICODE_BACKSLASH L'\\'
+#define UNICODE_SLASH L'/'
+#define UNICODE_EQUAL_SIGN L'='
+#define UNICODE_PLUS_SIGN L'+'
+
+#define UNICODE_FILE_START 0xFEFF
+#define UNICODE_CR 0x000D
+#define UNICODE_LF 0x000A
+#define UNICODE_NULL 0x0000
+#define UNICODE_SPACE L' '
+#define UNICODE_SLASH L'/'
+#define UNICODE_DOUBLE_QUOTE L'"'
+#define UNICODE_Z L'Z'
+#define UNICODE_z L'z'
+#define UNICODE_A L'A'
+#define UNICODE_a L'a'
+#define UNICODE_F L'F'
+#define UNICODE_f L'f'
+#define UNICODE_UNDERSCORE L'_'
+#define UNICODE_0 L'0'
+#define UNICODE_9 L'9'
+#define UNICODE_TAB L'\t'
+#define UNICODE_NBR_STRING L"\\nbr"
+#define UNICODE_BR_STRING L"\\br"
+#define UNICODE_WIDE_STRING L"\\wide"
+#define UNICODE_NARROW_STRING L"\\narrow"
+
+//
+// This is the length of a valid string identifier
+//
+#define LANGUAGE_IDENTIFIER_NAME_LEN 3
+
+typedef struct _TEXT_STRING_LIST {
+ struct _TEXT_STRING_LIST *Next;
+ CHAR8 *Str;
+} TEXT_STRING_LIST;
+
+typedef struct _WCHAR_STRING_LIST {
+ struct _WCHAR_STRING_LIST *Next;
+ WCHAR *Str;
+} WCHAR_STRING_LIST;
+
+typedef struct _WCHAR_MATCHING_STRING_LIST {
+ struct _WCHAR_MATCHING_STRING_LIST *Next;
+ WCHAR *Str1;
+ WCHAR *Str2;
+} WCHAR_MATCHING_STRING_LIST;
+
+#endif // #ifndef _STR_GATHER_H_
diff --git a/Source/StrGather/StringDB.c b/Source/StrGather/StringDB.c
new file mode 100644
index 0000000..16ef052
--- /dev/null
+++ b/Source/StrGather/StringDB.c
@@ -0,0 +1,2759 @@
+/*++
+
+Copyright (c) 2004, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ StringDB.c
+
+Abstract:
+
+ String database implementation
+
+--*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h> // for tolower()
+
+#include <Common/UefiBaseTypes.h>
+#include <Common/MultiPhase.h>
+#include <Common/InternalFormRepresentation.h>
+#include <Protocol/UgaDraw.h> // for EFI_UGA_PIXEL definition
+#include <Protocol/Hii.h>
+
+#include "EfiUtilityMsgs.h"
+#include "StrGather.h"
+#include "StringDB.h"
+
+
+#define STRING_OFFSET RELOFST
+
+#define STRING_DB_KEY (('S' << 24) | ('D' << 16) | ('B' << 8) | 'K')
+//
+// Version supported by this tool
+//
+#define STRING_DB_VERSION 0x00010000
+
+#define STRING_DB_MAJOR_VERSION_MASK 0xFFFF0000
+#define STRING_DB_MINOR_VERSION_MASK 0x0000FFFF
+
+#define DEFINE_STR L"// #define"
+
+#define LANGUAGE_CODE_WIDTH 4
+//
+// This is the header that gets written to the top of the
+// output binary database file.
+//
+typedef struct {
+ UINT32 Key;
+ UINT32 HeaderSize;
+ UINT32 Version;
+ UINT32 NumStringIdenfiers;
+ UINT32 StringIdentifiersSize;
+ UINT32 NumLanguages;
+} STRING_DB_HEADER;
+
+//
+// When we write out data to the database, we have a UINT16 identifier, which
+// indicates what follows, followed by the data. Here's the structure.
+//
+typedef struct {
+ UINT16 DataType;
+ UINT16 Reserved;
+} DB_DATA_ITEM_HEADER;
+
+#define DB_DATA_TYPE_INVALID 0x0000
+#define DB_DATA_TYPE_STRING_IDENTIFIER 0x0001
+#define DB_DATA_TYPE_LANGUAGE_DEFINITION 0x0002
+#define DB_DATA_TYPE_STRING_DEFINITION 0x0003
+#define DB_DATA_TYPE_LAST DB_DATA_TYPE_STRING_DEFINITION
+
+//
+// We have to keep track of a list of languages, each of which has its own
+// list of strings. Define a structure to keep track of all languages and
+// their list of strings.
+//
+typedef struct _STRING_LIST {
+ struct _STRING_LIST *Next;
+ UINT32 Size; // number of bytes in string, including null terminator
+ WCHAR *LanguageName;
+ WCHAR *StringName; // for example STR_ID_TEXT1
+ WCHAR *Scope; //
+ WCHAR *Str; // the actual string
+ UINT16 Flags; // properties of this string (used, undefined)
+} STRING_LIST;
+
+typedef struct _LANGUAGE_LIST {
+ struct _LANGUAGE_LIST *Next;
+ WCHAR LanguageName[4];
+ WCHAR *PrintableLanguageName;
+ STRING_LIST *String;
+ STRING_LIST *LastString;
+} LANGUAGE_LIST;
+
+//
+// We also keep track of all the string identifier names, which we assign unique
+// values to. Create a structure to keep track of them all.
+//
+typedef struct _STRING_IDENTIFIER {
+ struct _STRING_IDENTIFIER *Next;
+ UINT32 Index; // only need 16 bits, but makes it easier with UINT32
+ WCHAR *StringName;
+ UINT16 Flags; // if someone referenced it via STRING_TOKEN()
+} STRING_IDENTIFIER;
+//
+// Keep our globals in this structure to be as modular as possible.
+//
+typedef struct {
+ FILE *StringDBFptr;
+ LANGUAGE_LIST *LanguageList;
+ LANGUAGE_LIST *LastLanguageList;
+ LANGUAGE_LIST *CurrentLanguage; // keep track of the last language they used
+ STRING_IDENTIFIER *StringIdentifier;
+ STRING_IDENTIFIER *LastStringIdentifier;
+ UINT8 *StringDBFileName;
+ UINT32 NumStringIdentifiers;
+ UINT32 NumStringIdentifiersReferenced;
+ STRING_IDENTIFIER *CurrentStringIdentifier; // keep track of the last string identifier they added
+ WCHAR *CurrentScope;
+} STRING_DB_DATA;
+
+static STRING_DB_DATA mDBData;
+
+static const char *mSourceFileHeader[] = {
+ "//",
+ "// DO NOT EDIT -- auto-generated file",
+ "//",
+ "// This file is generated by the string gather utility",
+ "//",
+ NULL
+};
+
+static
+STRING_LIST *
+StringDBFindString (
+ WCHAR *LanguageName,
+ WCHAR *StringName,
+ WCHAR *Scope,
+ WCHAR_STRING_LIST *LanguagesOfInterest,
+ WCHAR_MATCHING_STRING_LIST *IndirectionList
+ );
+
+static
+STRING_IDENTIFIER *
+StringDBFindStringIdentifierByName (
+ WCHAR *Name
+ );
+
+static
+STRING_IDENTIFIER *
+StringDBFindStringIdentifierByIndex (
+ UINT32 Index
+ );
+
+static
+LANGUAGE_LIST *
+StringDBFindLanguageList (
+ WCHAR *LanguageName
+ );
+
+static
+void
+StringDBWriteStandardFileHeader (
+ FILE *OutFptr
+ );
+
+static
+WCHAR *
+AsciiToWchar (
+ CHAR8 *Str
+ );
+
+static
+WCHAR *
+DuplicateString (
+ WCHAR *Str
+ );
+
+static
+STATUS
+StringDBWriteStringIdentifier (
+ FILE *DBFptr,
+ UINT16 StringId,
+ UINT16 Flags,
+ WCHAR *IdentifierName
+ );
+
+static
+STATUS
+StringDBReadStringIdentifier (
+ FILE *DBFptr
+ );
+
+static
+STATUS
+StringDBWriteLanguageDefinition (
+ FILE *DBFptr,
+ WCHAR *LanguageName,
+ WCHAR *PrintableLanguageName
+ );
+
+static
+STATUS
+StringDBReadLanguageDefinition (
+ FILE *DBFptr
+ );
+
+static
+STATUS
+StringDBWriteString (
+ FILE *DBFptr,
+ UINT16 Flags,
+ WCHAR *Language,
+ WCHAR *StringName,
+ WCHAR *Scope,
+ WCHAR *Str
+ );
+
+static
+STATUS
+StringDBReadString (
+ FILE *DBFptr
+ );
+
+static
+STATUS
+StringDBReadGenericString (
+ FILE *DBFptr,
+ UINT16 *Size,
+ WCHAR **Str
+ );
+
+static
+STATUS
+StringDBWriteGenericString (
+ FILE *DBFptr,
+ WCHAR *Str
+ );
+
+static
+void
+StringDBAssignStringIndexes (
+ VOID
+ );
+
+/*****************************************************************************/
+
+/*++
+
+Routine Description:
+ Constructor function for the string database handler.
+
+Arguments:
+ None.
+
+Returns:
+ None.
+
+--*/
+void
+StringDBConstructor (
+ VOID
+ )
+{
+ memset ((char *) &mDBData, 0, sizeof (STRING_DB_DATA));
+ mDBData.CurrentScope = DuplicateString (L"NULL");
+}
+
+/*****************************************************************************/
+
+/*++
+
+Routine Description:
+ Destructor function for the string database handler.
+
+Arguments:
+ None.
+
+Returns:
+ None.
+
+--*/
+void
+StringDBDestructor (
+ VOID
+ )
+{
+ LANGUAGE_LIST *NextLang;
+ STRING_LIST *NextStr;
+ STRING_IDENTIFIER *NextIdentifier;
+ //
+ // Close the database file if it's open
+ //
+ if (mDBData.StringDBFptr != NULL) {
+ fclose (mDBData.StringDBFptr);
+ mDBData.StringDBFptr = NULL;
+ }
+ //
+ // If we've allocated any strings/languages, free them up
+ //
+ while (mDBData.LanguageList != NULL) {
+ NextLang = mDBData.LanguageList->Next;
+ //
+ // Free up all strings for this language
+ //
+ while (mDBData.LanguageList->String != NULL) {
+ NextStr = mDBData.LanguageList->String->Next;
+ FREE (mDBData.LanguageList->String->Str);
+ FREE (mDBData.LanguageList->String);
+ mDBData.LanguageList->String = NextStr;
+ }
+
+ FREE (mDBData.LanguageList->PrintableLanguageName);
+ FREE (mDBData.LanguageList);
+ mDBData.LanguageList = NextLang;
+ }
+ //
+ // Free up string identifiers
+ //
+ while (mDBData.StringIdentifier != NULL) {
+ NextIdentifier = mDBData.StringIdentifier->Next;
+ FREE (mDBData.StringIdentifier->StringName);
+ FREE (mDBData.StringIdentifier);
+ mDBData.StringIdentifier = NextIdentifier;
+ }
+ //
+ // Free the filename
+ //
+ if (mDBData.StringDBFileName != NULL) {
+ FREE (mDBData.StringDBFileName);
+ mDBData.StringDBFileName = NULL;
+ }
+ //
+ // We save a copy of the scope, so free it up if we
+ // have one.
+ //
+ if (mDBData.CurrentScope != NULL) {
+ FREE (mDBData.CurrentScope);
+ mDBData.CurrentScope = NULL;
+ }
+}
+
+/*****************************************************************************/
+
+/*++
+
+Routine Description:
+
+ Dump the contents of a database to an output C file.
+
+Arguments:
+
+ FileName - name of the output file to write
+ BaseName - used for the name of the C array defined
+ Languages - list of languages of interest
+
+Returns:
+
+ STATUS
+
+Notes:
+
+ Languages is a pointer to a linked list of languages specified on
+ the command line. Format is "eng" and "spa+cat". For this, print
+ the strings for eng. Print the strings for spa too, but if one is
+ missing look for a cat string and print if it it exists.
+
+--*/
+STATUS
+StringDBDumpCStrings (
+ CHAR8 *FileName,
+ CHAR8 *BaseName,
+ WCHAR_STRING_LIST *LanguagesOfInterest,
+ WCHAR_MATCHING_STRING_LIST *IndirectionList
+ )
+{
+ FILE *Fptr;
+ LANGUAGE_LIST *Lang;
+ STRING_LIST *CurrString;
+ STRING_LIST EmptyString;
+ UINT32 Offset;
+ UINT32 StringIndex;
+ UINT32 TempIndex;
+ UINT32 BytesThisLine;
+ EFI_HII_STRING_PACK StringPack;
+ UINT8 *Ptr;
+ UINT32 Len;
+ WCHAR ZeroString[1];
+ WCHAR_STRING_LIST *LOIPtr;
+ BOOLEAN LanguageOk;
+ WCHAR *TempStringPtr;
+ WCHAR *LangName;
+ STRING_IDENTIFIER *StringIdentifier;
+ WCHAR Line[200];
+
+ if ((Fptr = fopen (FileName, "w")) == NULL) {
+ Error (NULL, 0, 0, FileName, "failed to open output C string file");
+ return STATUS_ERROR;
+ }
+ //
+ // Assign index values to the string identifiers
+ //
+ StringDBAssignStringIndexes ();
+ //
+ // Write the standard header to the output file, then the structure
+ // definition header.
+ //
+ StringDBWriteStandardFileHeader (Fptr);
+ fprintf (Fptr, "\nunsigned char %s[] = {\n", BaseName);
+ //
+ // If a given string is not defined, then we'll use this one.
+ //
+ memset (&EmptyString, 0, sizeof (EmptyString));
+ EmptyString.Size = sizeof (ZeroString);
+ EmptyString.Str = ZeroString;
+ //
+ // Process each language, then each string for each langage
+ //
+ ZeroString[0] = 0;
+ for (Lang = mDBData.LanguageList; Lang != NULL; Lang = Lang->Next) {
+ //
+ // If we have a language list, then make sure this language is in that
+ // list.
+ //
+ LanguageOk = TRUE;
+ LangName = Lang->LanguageName;
+ if (LanguagesOfInterest != NULL) {
+ LanguageOk = FALSE;
+ for (LOIPtr = LanguagesOfInterest; LOIPtr != NULL; LOIPtr = LOIPtr->Next) {
+ if (StrnCmp (LOIPtr->Str, Lang->LanguageName, LANGUAGE_IDENTIFIER_NAME_LEN) == 0) {
+ LangName = LOIPtr->Str;
+ LanguageOk = TRUE;
+ break;
+ }
+ }
+ }
+
+ if (!LanguageOk) {
+ continue;
+ }
+ //
+ // Process each string for this language. We have to make 3 passes on the strings:
+ // Pass1: computes sizes and fill in the string pack header
+ // Pass2: write the array of offsets
+ // Pass3: write the strings
+ //
+ //
+ // PASS 1: Fill in and print the HII string pack header
+ //
+ // Compute the size for this language package and write
+ // the header out. Each string package contains:
+ // Header
+ // Offset[] -- an array of offsets to strings, of type RELOFST each
+ // String[] -- the actual strings themselves
+ //
+ AsciiSPrint ( Line, sizeof(Line),
+ "\n//******************************************************************************"
+ "\n// Start of string definitions for %s/%s",
+ Lang->LanguageName,
+ Lang->PrintableLanguageName
+ );
+ fprintf (Fptr, "%s", Line);
+ memset ((char *) &StringPack, 0, sizeof (EFI_HII_STRING_PACK));
+ StringPack.Header.Type = EFI_HII_STRING;
+ StringPack.NumStringPointers = (UINT16) mDBData.NumStringIdentifiersReferenced;
+ //
+ // First string is the language name. If we're printing all languages, then
+ // it's just the "spa". If we were given a list of languages to print, then it's
+ // the "spacat" string. Compute its offset and fill in
+ // the info in the header. Since we know the language name string's length,
+ // and the printable language name follows it, use that info to fill in the
+ // entry for the printable language name as well.
+ //
+ StringPack.LanguageNameString = (STRING_OFFSET) (sizeof (EFI_HII_STRING_PACK) + (mDBData.NumStringIdentifiersReferenced * sizeof (STRING_OFFSET)));
+ StringPack.PrintableLanguageName = (STRING_OFFSET) (StringPack.LanguageNameString + (StrLen (LangName) + 1) * sizeof (WCHAR));
+ //
+ // Add up the size of all strings so we can fill in our header.
+ //
+ Len = 0;
+ for (StringIndex = 0; StringIndex < mDBData.NumStringIdentifiersReferenced; StringIndex++) {
+ //
+ // For the first string (language name), we print out the "spacat" if they
+ // requested it. We set LangName to point to the proper language name string above.
+ //
+ if (StringIndex == STRING_ID_LANGUAGE_NAME) {
+ Len += (StrLen (LangName) + 1) * sizeof (WCHAR);
+ } else {
+ //
+ // Find a string with this language.stringname
+ //
+ StringIdentifier = StringDBFindStringIdentifierByIndex (StringIndex);
+ if (StringIdentifier == NULL) {
+ Error (NULL, 0, 0, "internal error", "invalid string index 0x%X", StringIndex);
+ return STATUS_ERROR;
+ }
+ //
+ // Find a matching string if this string identifier was referenced
+ //
+ EmptyString.Flags = STRING_FLAGS_UNDEFINED;
+ CurrString = NULL;
+ if (StringIdentifier->Flags & STRING_FLAGS_REFERENCED) {
+ CurrString = StringDBFindString (
+ Lang->LanguageName,
+ StringIdentifier->StringName,
+ NULL,
+ LanguagesOfInterest,
+ IndirectionList
+ );
+ if (NULL == CurrString) {
+ //
+ // If string for Lang->LanguageName is not found, try to get an English version
+ //
+ CurrString = StringDBFindString (
+ L"eng",
+ StringIdentifier->StringName,
+ NULL,
+ LanguagesOfInterest,
+ IndirectionList
+ );
+ }
+ }
+
+ if (CurrString == NULL) {
+ CurrString = &EmptyString;
+ EmptyString.Flags |= StringIdentifier->Flags;
+ }
+
+ Len += CurrString->Size;
+ }
+ }
+ StringPack.Header.Length = sizeof (EFI_HII_STRING_PACK)
+ + mDBData.NumStringIdentifiersReferenced * sizeof (STRING_OFFSET)
+ + Len;
+ //
+ // Write out the header one byte at a time
+ //
+ Ptr = (UINT8 *) &StringPack;
+ for (TempIndex = 0; TempIndex < sizeof (EFI_HII_STRING_PACK); TempIndex++, Ptr++) {
+ if ((TempIndex & 0x07) == 0) {
+ fprintf (Fptr, "\n ");
+ }
+
+ fprintf (Fptr, "0x%02X, ", (UINT32) *Ptr);
+ }
+
+ fprintf (Fptr, "\n // offset 0x%X\n", sizeof (StringPack));
+ //
+ // PASS2 : write the offsets
+ //
+ // Traverse the list of strings again and write the array of offsets. The
+ // offset to the first string is the size of the string pack header
+ // plus the size of the offsets array. The other strings follow it.
+ //
+ StringIndex = 0;
+ Offset = sizeof (StringPack) + mDBData.NumStringIdentifiersReferenced * sizeof (STRING_OFFSET);
+ for (StringIndex = 0; StringIndex < mDBData.NumStringIdentifiersReferenced; StringIndex++) {
+ //
+ // Write the offset, followed by a useful comment
+ //
+ fprintf (Fptr, " ");
+ Ptr = (UINT8 *) &Offset;
+ for (TempIndex = 0; TempIndex < sizeof (STRING_OFFSET); TempIndex++) {
+ fprintf (Fptr, "0x%02X, ", (UINT32) Ptr[TempIndex]);
+ }
+ //
+ // Find the string name
+ //
+ StringIdentifier = StringDBFindStringIdentifierByIndex (StringIndex);
+ if (StringIdentifier == NULL) {
+ Error (NULL, 0, 0, "internal error", "invalid string index 0x%X", StringIndex);
+ return STATUS_ERROR;
+ }
+
+ AsciiSPrint (Line, sizeof(Line) , " // offset to string %s (0x%04X)", StringIdentifier->StringName, StringIndex);
+ fprintf (Fptr, "%s", Line);
+ //
+ // For the first string (language name), we print out the "spacat" if they
+ // requested it. We set LangName to point to the proper language name string above.
+ //
+ if (StringIndex == STRING_ID_LANGUAGE_NAME) {
+ Offset += (StrLen (LangName) + 1) * sizeof (WCHAR);
+ CurrString = StringDBFindString (
+ Lang->LanguageName,
+ StringIdentifier->StringName,
+ NULL, // scope
+ NULL,
+ NULL
+ );
+ } else {
+ //
+ // Find a matching string
+ //
+ CurrString = StringDBFindString (
+ Lang->LanguageName,
+ StringIdentifier->StringName,
+ NULL, // scope
+ LanguagesOfInterest,
+ IndirectionList
+ );
+
+ if (NULL == CurrString) {
+ CurrString = StringDBFindString (
+ L"eng",
+ StringIdentifier->StringName,
+ NULL, // scope
+ LanguagesOfInterest,
+ IndirectionList
+ );
+ }
+
+ EmptyString.LanguageName = Lang->LanguageName;
+ if (CurrString == NULL) {
+ CurrString = &EmptyString;
+ EmptyString.Flags = STRING_FLAGS_UNDEFINED;
+ } else if ((StringIdentifier->Flags & STRING_FLAGS_REFERENCED) == 0) {
+ CurrString = &EmptyString;
+ EmptyString.Flags = 0;
+ }
+
+ Offset += CurrString->Size;
+ }
+ //
+ // Print useful info about this string
+ //
+ if ((StringIdentifier->Flags & STRING_FLAGS_REFERENCED) == 0) {
+ fprintf (Fptr, " - not referenced");
+ }
+
+ if (CurrString->Flags & STRING_FLAGS_UNDEFINED) {
+ fprintf (Fptr, " - not defined for this language");
+ } else if (StrCmp (CurrString->LanguageName, Lang->LanguageName) != 0) {
+ AsciiSPrint (
+ Line, sizeof(Line),
+ " - not defined for this language -- using secondary language %s definition",
+ CurrString->LanguageName
+ );
+ fprintf ( Fptr, "%s", Line);
+ }
+
+ fprintf (Fptr, "\n");
+ }
+ //
+ // For unreferenced string identifiers, print a message that they are not referenced anywhere
+ //
+ while (StringIndex < mDBData.NumStringIdentifiers) {
+ StringIdentifier = StringDBFindStringIdentifierByIndex (StringIndex);
+ if (StringIdentifier != NULL) {
+ AsciiSPrint (Line, sizeof(Line), " // %s not referenced\n", StringIdentifier->StringName);
+ fprintf (Fptr, "%s", Line);
+ }
+
+ StringIndex++;
+ }
+
+ //
+ // PASS 3: write the strings themselves.
+ // Keep track of how many bytes we write per line because some editors
+ // (Visual Studio for instance) can't handle too long of lines.
+ //
+ Offset = sizeof (StringPack) + mDBData.NumStringIdentifiersReferenced * sizeof (STRING_OFFSET);
+ for (StringIndex = 0; StringIndex < mDBData.NumStringIdentifiersReferenced; StringIndex++) {
+ StringIdentifier = StringDBFindStringIdentifierByIndex (StringIndex);
+ if (StringIdentifier == NULL) {
+ Error (NULL, 0, 0, "internal error", "invalid string index 0x%X", StringIndex);
+ return STATUS_ERROR;
+ }
+
+ AsciiSPrint (Line, sizeof(Line), " // string %s offset 0x%08X\n ", StringIdentifier->StringName, Offset);
+ fprintf (Fptr, "%s", Line);
+ //
+ // For the first string (language name), we print out the "spacat" if they
+ // requested it. We set LangName to point to the proper language name string above.
+ //
+ if (StringIndex == STRING_ID_LANGUAGE_NAME) {
+ TempStringPtr = LangName;
+ } else {
+ //
+ // Find a matching string if this string identifier was referenced
+ //
+ CurrString = NULL;
+ if (StringIdentifier->Flags & STRING_FLAGS_REFERENCED) {
+ CurrString = StringDBFindString (
+ Lang->LanguageName,
+ StringIdentifier->StringName,
+ NULL, // scope
+ LanguagesOfInterest,
+ IndirectionList
+ );
+ if (NULL == CurrString) {
+ CurrString = StringDBFindString (
+ L"eng",
+ StringIdentifier->StringName,
+ NULL, // scope
+ LanguagesOfInterest,
+ IndirectionList
+ );
+ }
+ }
+
+ if (CurrString == NULL) {
+ CurrString = &EmptyString;
+ }
+
+ TempStringPtr = CurrString->Str;
+ }
+
+ BytesThisLine = 0;
+ for (TempIndex = 0; TempStringPtr[TempIndex] != 0; TempIndex++) {
+ fprintf (
+ Fptr,
+ "0x%02X, 0x%02X, ",
+ (UINT32) TempStringPtr[TempIndex] & 0xFF,
+ (UINT32) ((TempStringPtr[TempIndex] >> 8) & 0xFF)
+ );
+ BytesThisLine += 2;
+ Offset += 2;
+ //
+ // Let's say we only allow 14 per line
+ //
+ if (BytesThisLine > 14) {
+ fprintf (Fptr, "\n ");
+ BytesThisLine = 0;
+ }
+ }
+ //
+ // Print NULL WCHAR at the end of this string.
+ //
+ fprintf (Fptr, "0x00, 0x00,\n");
+ Offset += 2;
+ }
+ //
+ // Sanity check the offset. Make sure our running offset is what we put in the
+ // string pack header.
+ //
+ if (StringPack.Header.Length != Offset) {
+ Error (
+ __FILE__,
+ __LINE__,
+ 0,
+ "application error",
+ "stringpack size 0x%X does not match final size 0x%X",
+ StringPack.Header.Length,
+ Offset
+ );
+ }
+ }
+ //
+ // Print terminator string pack, closing brace and close the file.
+ // The size of 0 triggers to the consumer that this is the end.
+ //
+ memset ((char *) &StringPack, 0, sizeof (EFI_HII_STRING_PACK));
+ StringPack.Header.Type = EFI_HII_STRING;
+ Ptr = (UINT8 *) &StringPack;
+ fprintf (Fptr, "\n // strings terminator pack");
+ for (TempIndex = 0; TempIndex < sizeof (StringPack); TempIndex++, Ptr++) {
+ if ((TempIndex & 0x0F) == 0) {
+ fprintf (Fptr, "\n ");
+ }
+
+ fprintf (Fptr, "0x%02X, ", (UINT32) *Ptr);
+ }
+
+ fprintf (Fptr, "\n};\n");
+ fclose (Fptr);
+ return STATUS_SUCCESS;
+}
+
+/*****************************************************************************/
+
+/*++
+
+Routine Description:
+
+ Dump the #define string names
+
+Arguments:
+
+ FileName - name of the output file to write
+ BaseName - used for the protection #ifndef/#endif
+
+Returns:
+
+ STATUS
+
+--*/
+STATUS
+StringDBDumpStringDefines (
+ CHAR8 *FileName,
+ CHAR8 *BaseName
+ )
+{
+ FILE *Fptr;
+ STRING_IDENTIFIER *Identifier;
+ CHAR8 CopyBaseName[100];
+ WCHAR Line[200];
+ UINT32 Index;
+ const CHAR8 *StrDefHeader[] = {
+ "#ifndef _%s_STRINGS_DEFINE_H_\n",
+ "#define _%s_STRINGS_DEFINE_H_\n\n",
+ NULL
+ };
+
+ if ((Fptr = fopen (FileName, "w")) == NULL) {
+ Error (NULL, 0, 0, FileName, "failed to open output string defines file");
+ return STATUS_ERROR;
+ }
+ //
+ // Get the base source filename and convert to uppercase.
+ //
+ if (sizeof (CopyBaseName) <= strlen (BaseName) + 1) {
+ Error (NULL, 0, 0, "application error", "StringDBDumpStringDefines() string length insufficient");
+ return STATUS_ERROR;
+ }
+
+ strcpy (CopyBaseName, BaseName);
+ for (Index = 0; CopyBaseName[Index] != 0; Index++) {
+ if (islower (CopyBaseName[Index])) {
+ CopyBaseName[Index] = (INT8) toupper (CopyBaseName[Index]);
+ }
+ }
+ //
+ // Assign index values to the string identifiers
+ //
+ StringDBAssignStringIndexes ();
+ //
+ // Write the standard header to the output file, and then the
+ // protective #ifndef.
+ //
+ StringDBWriteStandardFileHeader (Fptr);
+ for (Index = 0; StrDefHeader[Index] != NULL; Index++) {
+ fprintf (Fptr, StrDefHeader[Index], CopyBaseName);
+ }
+ //
+ // Print all the #defines for the string identifiers. Print identifiers
+ // whose names start with '$' as comments. Add comments for string
+ // identifiers not used as well.
+ //
+ Identifier = mDBData.StringIdentifier;
+ while (Identifier != NULL) {
+ if (Identifier->StringName[0] == L'$') {
+ fprintf (Fptr, "// ");
+ }
+
+ if (Identifier->Flags & STRING_FLAGS_REFERENCED) {
+ AsciiSPrint (Line, sizeof(Line), "#define %-40s 0x%04X\n", Identifier->StringName, Identifier->Index);
+ fprintf (Fptr, "%s", Line);
+ } else {
+ AsciiSPrint (Line, sizeof(Line), "//#define %-40s 0x%04X // not referenced\n", Identifier->StringName, Identifier->Index);
+ fprintf (Fptr, "%s", Line);
+ }
+
+ Identifier = Identifier->Next;
+ }
+
+ fprintf (Fptr, "\n#endif\n");
+ fclose (Fptr);
+ return STATUS_SUCCESS;
+}
+
+/*****************************************************************************/
+
+/*++
+
+Routine Description:
+
+ Add a string identifier to the database.
+
+Arguments:
+
+ StringName - name of the string identifier. For example "STR_MY_STRING"
+ NewId - if an ID has been assigned
+ Flags - characteristics for the identifier
+
+Returns:
+
+ STATUS
+
+--*/
+STATUS
+StringDBAddStringIdentifier (
+ WCHAR *StringName,
+ UINT16 *NewId,
+ UINT16 Flags
+ )
+{
+ STRING_IDENTIFIER *StringIdentifier;
+ STATUS Status;
+ //
+ // If it was already used for some other language, then we don't
+ // need to add it. But set it to the current string identifier.
+ // The referenced bit is sticky.
+ //
+ Status = STATUS_SUCCESS;
+ StringIdentifier = StringDBFindStringIdentifierByName (StringName);
+ if (StringIdentifier != NULL) {
+ if (Flags & STRING_FLAGS_REFERENCED) {
+ StringIdentifier->Flags |= STRING_FLAGS_REFERENCED;
+ }
+
+ mDBData.CurrentStringIdentifier = StringIdentifier;
+ *NewId = (UINT16) StringIdentifier->Index;
+ return Status;
+ }
+
+ StringIdentifier = (STRING_IDENTIFIER *) MALLOC (sizeof (STRING_IDENTIFIER));
+ if (StringIdentifier == NULL) {
+ Error (NULL, 0, 0, NULL, "memory allocation error");
+ return STATUS_ERROR;
+ }
+
+ memset ((char *) StringIdentifier, 0, sizeof (STRING_IDENTIFIER));
+ StringIdentifier->StringName = (WCHAR *) malloc ((StrLen (StringName) + 1) * sizeof (WCHAR));
+ if (StringIdentifier->StringName == NULL) {
+ Error (NULL, 0, 0, NULL, "memory allocation error");
+ return STATUS_ERROR;
+ }
+
+ StrCpy (StringIdentifier->StringName, StringName);
+ if (*NewId != STRING_ID_INVALID) {
+ StringIdentifier->Index = *NewId;
+ StringIdentifier->Flags |= STRING_FLAGS_INDEX_ASSIGNED;
+ if (mDBData.NumStringIdentifiers <= StringIdentifier->Index) {
+ mDBData.NumStringIdentifiers = StringIdentifier->Index + 1;
+ }
+ } else {
+ StringIdentifier->Index = mDBData.NumStringIdentifiers++;
+ }
+
+ StringIdentifier->Flags |= Flags;
+ //
+ // Add it to our list of string identifiers
+ //
+ if (mDBData.StringIdentifier == NULL) {
+ mDBData.StringIdentifier = StringIdentifier;
+ } else {
+ mDBData.LastStringIdentifier->Next = StringIdentifier;
+ }
+
+ mDBData.LastStringIdentifier = StringIdentifier;
+ mDBData.CurrentStringIdentifier = StringIdentifier;
+ *NewId = (UINT16) StringIdentifier->Index;
+ return Status;
+}
+
+/*****************************************************************************/
+
+/*++
+
+Routine Description:
+
+ Add a new string to the database.
+
+Arguments:
+
+ LanguageName - "eng" or "spa" language name
+ StringName - "STR_MY_TEXT" string name
+ Scope - from the #scope statements in the string file
+ Format - if we should format the string
+ Flags - characteristic flags for the string
+
+Returns:
+
+ STATUS
+
+Notes:
+
+ Several of the fields can be "inherited" from the previous calls to
+ our database functions. For example, if scope is NULL here, then
+ we'll use the previous setting.
+
+--*/
+STATUS
+StringDBAddString (
+ WCHAR *LanguageName,
+ WCHAR *StringName,
+ WCHAR *Scope,
+ WCHAR *String,
+ BOOLEAN Format,
+ UINT16 Flags
+ )
+{
+ LANGUAGE_LIST *Lang;
+ UINT32 Size;
+ STRING_LIST *Str;
+ UINT16 StringIndex;
+ WCHAR TempLangName[4];
+ STRING_IDENTIFIER *StringIdentifier;
+
+ //
+ // Check that language name is exactly 3 characters, or emit an error.
+ // Truncate at 3 if it's longer, or make it 3 if it's shorter.
+ //
+ if (LanguageName != NULL) {
+ Size = StrLen (LanguageName);
+ if (Size != 3) {
+ ParserError (0, "invalid length for language name", "%S", LanguageName);
+ if (Size > 3) {
+ LanguageName[3] = 0;
+ } else {
+ //
+ // Make a local copy of the language name string, and extend to
+ // 3 characters since we make assumptions elsewhere in this program
+ // on the length.
+ //
+ StrCpy (TempLangName, LanguageName);
+ for (; Size < 3; Size++) {
+ TempLangName[Size] = L'?';
+ }
+
+ TempLangName[4] = 0;
+ LanguageName = TempLangName;
+ }
+ }
+ }
+ //
+ // If they specified a language, make sure they've defined it already
+ // via a #langdef statement. Otherwise use the current default language.
+ //
+ if (LanguageName != NULL) {
+ Lang = StringDBFindLanguageList (LanguageName);
+ if (Lang == NULL) {
+ ParserError (0, "language not defined", "%S", LanguageName);
+ return STATUS_ERROR;
+ } else {
+ StringDBSetCurrentLanguage (LanguageName);
+ }
+ } else {
+ Lang = mDBData.CurrentLanguage;
+ if (Lang == NULL) {
+ //
+ // Have to call SetLanguage() first
+ //
+ ParserError (0, "no language defined", "%S", StringName);
+ return STATUS_ERROR;
+ }
+ }
+ //
+ // If they didn't define a string identifier, use the last string identifier
+ // added.
+ //
+ if (StringName == NULL) {
+ StringName = mDBData.CurrentStringIdentifier->StringName;
+ if (StringName == NULL) {
+ ParserError (0, "no string identifier previously specified", NULL);
+ return STATUS_ERROR;
+ }
+ }
+ //
+ // If scope was not specified, use the default setting
+ //
+ if (Scope != NULL) {
+ Scope = DuplicateString (Scope);
+ } else {
+ Scope = DuplicateString (mDBData.CurrentScope);
+ }
+ //
+ // printf ("Adding string: %S.%S.%S\n", Lang->LanguageName, StringName, Scope);
+ //
+ // Check for duplicates for this Language.StringName.Scope. Allow multiple
+ // definitions of the language name and printable language name, since the
+ // user does not specifically define them.
+ //
+ if (StringDBFindString (Lang->LanguageName, StringName, Scope, NULL, NULL) != NULL) {
+ if ((StrCmp (StringName, LANGUAGE_NAME_STRING_NAME) == 0) &&
+ (StrCmp (StringName, PRINTABLE_LANGUAGE_NAME_STRING_NAME) == 0)
+ ) {
+ ParserError (
+ 0,
+ "string multiply defined",
+ "Language.Name.Scope = %S.%S.%S",
+ Lang->LanguageName,
+ StringName,
+ Scope
+ );
+ return STATUS_ERROR;
+ }
+ }
+
+ StringIndex = STRING_ID_INVALID;
+ if (StringDBAddStringIdentifier (StringName, &StringIndex, Flags) != STATUS_SUCCESS) {
+ return STATUS_ERROR;
+ }
+
+ StringIdentifier = StringDBFindStringIdentifierByName (StringName);
+ //
+ // Add this string to the end of the strings for this language.
+ //
+ Str = (STRING_LIST *) malloc (sizeof (STRING_LIST));
+ if (Str == NULL) {
+ Error (NULL, 0, 0, NULL, "memory allocation error");
+ return STATUS_ERROR;
+ }
+
+ memset ((char *) Str, 0, sizeof (STRING_LIST));
+ Size = (StrLen (String) + 1) * sizeof (WCHAR);
+ Str->Flags = Flags;
+ Str->Scope = Scope;
+ Str->StringName = StringIdentifier->StringName;
+ Str->LanguageName = DuplicateString (LanguageName);
+ Str->Str = (WCHAR *) MALLOC (Size);
+ if (Str->Str == NULL) {
+ Error (NULL, 0, 0, NULL, "memory allocation error");
+ return STATUS_ERROR;
+ }
+ //
+ // If not formatting, just copy the string.
+ //
+ StrCpy (Str->Str, String);
+ if (Format) {
+ StringDBFormatString (Str->Str);
+ }
+ //
+ // Size may change after formatting. We set the size to
+ // the actual size of the string, including the null for
+ // easier processing later.
+ //
+ Str->Size = (StrLen (Str->Str) + 1) * sizeof (WCHAR);
+ if (Lang->String == NULL) {
+ Lang->String = Str;
+ } else {
+ Lang->LastString->Next = Str;
+ }
+
+ Lang->LastString = Str;
+ return STATUS_SUCCESS;
+}
+
+/*****************************************************************************/
+
+/*++
+
+Routine Description:
+
+ Given a language name, see if a language list for it has been defined
+
+Arguments:
+
+ LanguageName - like "eng"
+
+Returns:
+
+ A pointer to the language list
+
+--*/
+static
+LANGUAGE_LIST *
+StringDBFindLanguageList (
+ WCHAR *LanguageName
+ )
+{
+ LANGUAGE_LIST *Lang;
+
+ Lang = mDBData.LanguageList;
+ while (Lang != NULL) {
+ if (StrCmp (LanguageName, Lang->LanguageName) == 0) {
+ break;
+ }
+
+ Lang = Lang->Next;
+ }
+
+ return Lang;
+}
+
+/*****************************************************************************/
+STATUS
+StringDBSetCurrentLanguage (
+ WCHAR *LanguageName
+ )
+{
+ LANGUAGE_LIST *Lang;
+
+ Lang = StringDBFindLanguageList (LanguageName);
+ if (Lang == NULL) {
+ ParserError (0, "language not previously defined", "%S", LanguageName);
+ return STATUS_ERROR;
+ }
+
+ mDBData.CurrentLanguage = Lang;
+ return STATUS_SUCCESS;
+}
+
+/*****************************************************************************/
+STATUS
+StringDBAddLanguage (
+ WCHAR *LanguageName,
+ WCHAR *PrintableLanguageName
+ )
+{
+ LANGUAGE_LIST *Lang;
+ //
+ // Check for redefinitions
+ //
+ Lang = StringDBFindLanguageList (LanguageName);
+ if (Lang != NULL) {
+ //
+ // Better be the same printable name
+ //
+ if (StrCmp (PrintableLanguageName, Lang->PrintableLanguageName) != 0) {
+ ParserError (
+ 0,
+ "language redefinition",
+ "%S:%S != %S:%S",
+ Lang->LanguageName,
+ Lang->PrintableLanguageName,
+ LanguageName,
+ PrintableLanguageName
+ );
+ return STATUS_ERROR;
+ //
+ // } else {
+ // ParserWarning (0, "benign language redefinition", "%S", PrintableLanguageName);
+ // return STATUS_WARNING;
+ //
+ }
+ } else {
+ //
+ // Allocate memory to keep track of this new language
+ //
+ Lang = (LANGUAGE_LIST *) malloc (sizeof (LANGUAGE_LIST));
+ if (Lang == NULL) {
+ Error (NULL, 0, 0, NULL, "memory allocation error");
+ return STATUS_ERROR;
+ }
+
+ memset ((char *) Lang, 0, sizeof (LANGUAGE_LIST));
+ //
+ // Save the language name, then allocate memory to save the
+ // printable language name
+ //
+ StrCpy (Lang->LanguageName, LanguageName);
+ Lang->PrintableLanguageName = (WCHAR *) malloc ((StrLen (PrintableLanguageName) + 1) * sizeof (WCHAR));
+ if (Lang->PrintableLanguageName == NULL) {
+ Error (NULL, 0, 0, NULL, "memory allocation error");
+ return STATUS_ERROR;
+ }
+
+ StrCpy (Lang->PrintableLanguageName, PrintableLanguageName);
+
+ if (mDBData.LanguageList == NULL) {
+ mDBData.LanguageList = Lang;
+ } else {
+ mDBData.LastLanguageList->Next = Lang;
+ }
+
+ mDBData.LastLanguageList = Lang;
+ }
+ //
+ // Default is to make our active language this new one
+ //
+ StringDBSetCurrentLanguage (LanguageName);
+ //
+ // The first two strings for any language are the language name,
+ // followed by the printable language name. Add them and set them
+ // to referenced so they never get stripped out.
+ //
+ StringDBAddString (
+ LanguageName,
+ LANGUAGE_NAME_STRING_NAME,
+ NULL,
+ LanguageName,
+ FALSE,
+ STRING_FLAGS_REFERENCED
+ );
+ StringDBAddString (
+ LanguageName,
+ PRINTABLE_LANGUAGE_NAME_STRING_NAME,
+ NULL,
+ PrintableLanguageName,
+ FALSE,
+ STRING_FLAGS_REFERENCED
+ );
+ return STATUS_SUCCESS;
+}
+
+/*****************************************************************************/
+static
+STRING_IDENTIFIER *
+StringDBFindStringIdentifierByName (
+ WCHAR *StringName
+ )
+{
+ STRING_IDENTIFIER *Identifier;
+
+ Identifier = mDBData.StringIdentifier;
+ while (Identifier != NULL) {
+ if (StrCmp (StringName, Identifier->StringName) == 0) {
+ return Identifier;
+ }
+
+ Identifier = Identifier->Next;
+ }
+
+ return NULL;
+}
+
+static
+STRING_IDENTIFIER *
+StringDBFindStringIdentifierByIndex (
+ UINT32 StringIndex
+ )
+{
+ STRING_IDENTIFIER *Identifier;
+
+ Identifier = mDBData.StringIdentifier;
+ while (Identifier != NULL) {
+ if (Identifier->Index == StringIndex) {
+ return Identifier;
+ }
+
+ Identifier = Identifier->Next;
+ }
+
+ return NULL;
+}
+
+/*****************************************************************************/
+static
+void
+StringDBWriteStandardFileHeader (
+ FILE *OutFptr
+ )
+{
+ UINT32 TempIndex;
+ for (TempIndex = 0; mSourceFileHeader[TempIndex] != NULL; TempIndex++) {
+ fprintf (OutFptr, "%s\n", mSourceFileHeader[TempIndex]);
+ }
+}
+
+/*****************************************************************************/
+
+/*++
+
+Routine Description:
+
+ Given a Unicode string from an input file, reformat the string to replace
+ backslash control sequences with the appropriate encoding.
+
+Arguments:
+
+ String - pointer to string to reformat
+
+Returns:
+
+ Nothing
+
+--*/
+void
+StringDBFormatString (
+ WCHAR *String
+ )
+{
+ WCHAR *From;
+ WCHAR *To;
+ int HexNibbles;
+ WCHAR HexValue;
+ //
+ // Go through the string and process any formatting characters
+ //
+ From = String;
+ To = String;
+ while (*From) {
+ if (*From == UNICODE_BACKSLASH) {
+ //
+ // First look for \wide and replace with the appropriate control character. Note that
+ // when you have "define STR L"ABC"", then sizeof(ABC) is 8 because the null char is
+ // counted. Make adjustments for this. We advance From below, so subtract 2 each time.
+ //
+ if (StrnCmp (From, UNICODE_WIDE_STRING, sizeof (UNICODE_WIDE_STRING) / sizeof (WCHAR) - 1) == 0) {
+ *To = WIDE_CHAR;
+ From += sizeof (UNICODE_WIDE_STRING) / sizeof (WCHAR) - 2;
+ } else if (StrnCmp (From, UNICODE_NARROW_STRING, sizeof (UNICODE_NARROW_STRING) / sizeof (WCHAR) - 1) == 0) {
+ //
+ // Found: \narrow
+ //
+ *To = NARROW_CHAR;
+ From += sizeof (UNICODE_NARROW_STRING) / sizeof (WCHAR) - 2;
+ } else if (StrnCmp (From, UNICODE_NBR_STRING, sizeof (UNICODE_NBR_STRING) / sizeof (WCHAR) - 1) == 0) {
+ //
+ // Found: \nbr
+ //
+ *To = NON_BREAKING_CHAR;
+ From += sizeof (UNICODE_NBR_STRING) / sizeof (WCHAR) - 2;
+ } else if (StrnCmp (From, UNICODE_BR_STRING, sizeof (UNICODE_BR_STRING) / sizeof (WCHAR) - 1) == 0) {
+ //
+ // Found: \br -- pass through untouched
+ //
+ *To = *From;
+ } else {
+ //
+ // Standard one-character control sequences such as \n, \r, \\, or \x
+ //
+ From++;
+ switch (*From) {
+ case ASCII_TO_UNICODE ('n'):
+ *To = UNICODE_CR;
+ To++;
+ *To = UNICODE_LF;
+ break;
+
+ //
+ // carriage return
+ //
+ case ASCII_TO_UNICODE ('r'):
+ *To = UNICODE_CR;
+ break;
+
+ //
+ // backslash
+ //
+ case UNICODE_BACKSLASH:
+ *To = UNICODE_BACKSLASH;
+ break;
+
+ //
+ // Tab
+ //
+ case ASCII_TO_UNICODE ('t'):
+ *To = UNICODE_TAB;
+ break;
+
+ //
+ // embedded double-quote
+ //
+ case UNICODE_DOUBLE_QUOTE:
+ *To = UNICODE_DOUBLE_QUOTE;
+ break;
+
+ //
+ // Hex Unicode character \x1234. We'll process up to 4 hex characters
+ //
+ case ASCII_TO_UNICODE ('x'):
+ HexValue = 0;
+ for (HexNibbles = 0; HexNibbles < 4; HexNibbles++) {
+ if ((From[1] >= UNICODE_0) && (From[1] <= UNICODE_9)) {
+ HexValue = (HexValue << 4) | (From[1] - UNICODE_0);
+ } else if ((From[1] >= UNICODE_a) && (From[1] <= UNICODE_f)) {
+ HexValue = (HexValue << 4) | (10 + From[1] - UNICODE_a);
+ } else if ((From[1] >= UNICODE_A) && (From[1] <= UNICODE_F)) {
+ HexValue = (HexValue << 4) | (10 + From[1] - UNICODE_A);
+ } else {
+ break;
+ }
+
+ From++;
+ }
+
+ if (HexNibbles == 0) {
+ ParserWarning (
+ 0,
+ "expected at least one valid hex digit with \\x escaped character in string",
+ "\\%C",
+ *From
+ );
+ } else {
+ *To = HexValue;
+ }
+ break;
+
+ default:
+ *To = UNICODE_SPACE;
+ ParserWarning (0, "invalid escaped character in string", "\\%C", *From);
+ break;
+ }
+ }
+ } else {
+ *To = *From;
+ }
+
+ From++;
+ To++;
+ }
+
+ *To = 0;
+}
+
+/*****************************************************************************/
+STATUS
+StringDBReadDatabase (
+ CHAR8 *DBFileName,
+ BOOLEAN IgnoreIfNotExist,
+ BOOLEAN Verbose
+ )
+{
+ STRING_DB_HEADER DbHeader;
+ STATUS Status;
+ FILE *DBFptr;
+ DB_DATA_ITEM_HEADER DataItemHeader;
+
+ Status = STATUS_SUCCESS;
+ DBFptr = NULL;
+ //
+ // if (Verbose) {
+ // fprintf (stdout, "Reading database file %s\n", DBFileName);
+ // }
+ //
+ // Try to open the input file
+ //
+ if ((DBFptr = fopen (DBFileName, "rb")) == NULL) {
+ if (IgnoreIfNotExist) {
+ return STATUS_SUCCESS;
+ }
+
+ Error (NULL, 0, 0, DBFileName, "failed to open input database file for reading");
+ return STATUS_ERROR;
+ }
+ //
+ // Read and verify the database header
+ //
+ if (fread ((void *) &DbHeader, sizeof (STRING_DB_HEADER), 1, DBFptr) != 1) {
+ Error (NULL, 0, 0, DBFileName, "failed to read header from database file");
+ Status = STATUS_ERROR;
+ goto Finish;
+ }
+
+ if (DbHeader.Key != STRING_DB_KEY) {
+ Error (NULL, 0, 0, DBFileName, "invalid header in database file");
+ Status = STATUS_ERROR;
+ goto Finish;
+ }
+
+ if ((DbHeader.Version & STRING_DB_MAJOR_VERSION_MASK) != (STRING_DB_VERSION & STRING_DB_MAJOR_VERSION_MASK)) {
+ Error (NULL, 0, 0, DBFileName, "incompatible database file version -- rebuild clean");
+ Status = STATUS_ERROR;
+ goto Finish;
+ }
+ //
+ // Read remaining items
+ //
+ while (fread (&DataItemHeader, sizeof (DataItemHeader), 1, DBFptr) == 1) {
+ switch (DataItemHeader.DataType) {
+ case DB_DATA_TYPE_STRING_IDENTIFIER:
+ StringDBReadStringIdentifier (DBFptr);
+ break;
+
+ case DB_DATA_TYPE_LANGUAGE_DEFINITION:
+ StringDBReadLanguageDefinition (DBFptr);
+ break;
+
+ case DB_DATA_TYPE_STRING_DEFINITION:
+ StringDBReadString (DBFptr);
+ break;
+
+ default:
+ Error (
+ NULL,
+ 0,
+ 0,
+ "database corrupted",
+ "invalid data item type 0x%X at offset 0x%X",
+ (UINT32) DataItemHeader.DataType,
+ ftell (DBFptr) - sizeof (DataItemHeader)
+ );
+ Status = STATUS_ERROR;
+ goto Finish;
+ }
+ }
+
+Finish:
+ if (DBFptr != NULL) {
+ fclose (DBFptr);
+ }
+
+ return Status;
+}
+
+/*****************************************************************************/
+
+/*++
+
+Routine Description:
+
+ Write everything we know to the output database file. Write:
+
+ Database header
+ String identifiers[]
+ StringPacks[]
+
+Arguments:
+
+ DBFileName - name of the file to write to
+ Verbose - for debug purposes, print info messages along the way.
+
+Returns:
+
+ STATUS
+
+--*/
+STATUS
+StringDBWriteDatabase (
+ CHAR8 *DBFileName,
+ BOOLEAN Verbose
+ )
+{
+ STRING_DB_HEADER DbHeader;
+ UINT32 Counter;
+ UINT32 StrLength;
+ LANGUAGE_LIST *Lang;
+ STRING_IDENTIFIER *StringIdentifier;
+ STRING_LIST *StrList;
+ FILE *DBFptr;
+
+ if (Verbose) {
+ fprintf (stdout, "Writing database %s\n", DBFileName);
+ }
+
+ if ((DBFptr = fopen (DBFileName, "wb")) == NULL) {
+ Error (NULL, 0, 0, DBFileName, "failed to open output database file for writing");
+ return STATUS_ERROR;
+ }
+ //
+ // Fill in and write the database header
+ //
+ memset (&DbHeader, 0, sizeof (STRING_DB_HEADER));
+ DbHeader.HeaderSize = sizeof (STRING_DB_HEADER);
+ DbHeader.Key = STRING_DB_KEY;
+ DbHeader.Version = STRING_DB_VERSION;
+ //
+ // Count the number of languages we have
+ //
+ for (Lang = mDBData.LanguageList; Lang != NULL; Lang = Lang->Next) {
+ DbHeader.NumLanguages++;
+ }
+ //
+ // Count up how many string identifiers we have, and total up the
+ // size of the names plus the size of the flags field we will
+ // write out too.
+ //
+ DbHeader.NumStringIdenfiers = mDBData.NumStringIdentifiers;
+ StringIdentifier = mDBData.StringIdentifier;
+ for (Counter = 0; Counter < mDBData.NumStringIdentifiers; Counter++) {
+ StrLength = StrLen (StringIdentifier->StringName) + 1;
+ DbHeader.StringIdentifiersSize += StrLength * sizeof (WCHAR) + sizeof (StringIdentifier->Flags);
+ StringIdentifier = StringIdentifier->Next;
+ }
+
+ //
+ // Write the header
+ //
+ fwrite (&DbHeader, sizeof (STRING_DB_HEADER), 1, DBFptr);
+ if (Verbose) {
+ fprintf (stdout, " Number of string identifiers 0x%04X\n", DbHeader.NumStringIdenfiers);
+ fprintf (stdout, " Number of languages %d\n", DbHeader.NumLanguages);
+ }
+ //
+ // Write the string identifiers
+ //
+ for (StringIdentifier = mDBData.StringIdentifier; StringIdentifier != NULL; StringIdentifier = StringIdentifier->Next) {
+ StringDBWriteStringIdentifier (
+ DBFptr,
+ (UINT16) StringIdentifier->Index,
+ StringIdentifier->Flags,
+ StringIdentifier->StringName
+ );
+ }
+ //
+ // Now write all the strings for each language
+ //
+ for (Lang = mDBData.LanguageList; Lang != NULL; Lang = Lang->Next) {
+ StringDBWriteLanguageDefinition (DBFptr, Lang->LanguageName, Lang->PrintableLanguageName);
+ for (StrList = Lang->String; StrList != NULL; StrList = StrList->Next) {
+ StringDBWriteString (
+ DBFptr,
+ StrList->Flags,
+ Lang->LanguageName,
+ StrList->StringName,
+ StrList->Scope,
+ StrList->Str
+ );
+ }
+ }
+
+ fclose (DBFptr);
+ return STATUS_SUCCESS;
+}
+
+STATUS
+StringDBSetStringReferenced (
+ CHAR8 *StringIdentifierName,
+ BOOLEAN IgnoreNotFound
+ )
+{
+ STRING_IDENTIFIER *Id;
+ WCHAR *WName;
+ STATUS Status;
+ //
+ // See if it's already been defined.
+ //
+ Status = STATUS_SUCCESS;
+ WName = (WCHAR *) malloc ((strlen (StringIdentifierName) + 1) * sizeof (WCHAR));
+ UnicodeSPrint (WName, (strlen (StringIdentifierName) + 1) * sizeof (WCHAR), L"%a", StringIdentifierName);
+ Id = StringDBFindStringIdentifierByName (WName);
+ if (Id != NULL) {
+ Id->Flags |= STRING_FLAGS_REFERENCED;
+ } else {
+ if (IgnoreNotFound == 0) {
+ ParserWarning (0, StringIdentifierName, "string identifier not found in database");
+ Status = STATUS_WARNING;
+ }
+ }
+
+ free (WName);
+ return Status;
+}
+
+/*****************************************************************************/
+
+/*++
+
+Routine Description:
+
+ Dump the contents of a database to an output unicode file.
+
+Arguments:
+
+ DBFileName - name of the pre-existing database file to read
+ OutputFileName - name of the file to dump the database contents to
+ Verbose - for printing of additional info useful for debugging
+
+Returns:
+
+ STATUS
+
+Notes:
+
+ There's some issue with the unicode printing routines. Therefore to
+ write to the output file properly, open it as binary and use fwrite.
+ Ideally we could open it with just L"w" and use fwprintf().
+
+--*/
+STATUS
+StringDBDumpDatabase (
+ CHAR8 *DBFileName,
+ CHAR8 *OutputFileName,
+ BOOLEAN Verbose
+ )
+{
+ LANGUAGE_LIST *Lang;
+ STRING_IDENTIFIER *StringIdentifier;
+ STRING_LIST *StrList;
+ FILE *OutFptr;
+ WCHAR WChar;
+ WCHAR CrLf[2];
+ WCHAR Line[200];
+ WCHAR *Scope;
+ //
+ // This function assumes the database has already been read, and
+ // we're just dumping our internal data structures to a unicode file.
+ //
+ if (Verbose) {
+ fprintf (stdout, "Dumping database file %s\n", DBFileName);
+ }
+
+ OutFptr = fopen (OutputFileName, "wb");
+ if (OutFptr == NULL) {
+ Error (NULL, 0, 0, OutputFileName, "failed to open output file for writing");
+ return STATUS_ERROR;
+ }
+
+ WChar = UNICODE_FILE_START;
+ fwrite (&WChar, sizeof (WCHAR), 1, OutFptr);
+ CrLf[1] = UNICODE_LF;
+ CrLf[0] = UNICODE_CR;
+ //
+ // The default control character is '/'. Make it '#' by writing
+ // "/=#" to the output file.
+ //
+ UnicodeSPrint (Line, sizeof(Line), L"/=#");
+ fwrite (Line, StrLen (Line) * sizeof (WCHAR), 1, OutFptr);
+ fwrite (&CrLf, sizeof (CrLf), 1, OutFptr);
+ fwrite (&CrLf, sizeof (CrLf), 1, OutFptr);
+ //
+ // Dump all the string identifiers and their values
+ //
+ StringDBAssignStringIndexes ();
+ for (StringIdentifier = mDBData.StringIdentifier; StringIdentifier != NULL; StringIdentifier = StringIdentifier->Next) {
+ //
+ // Write the "#define " string
+ //
+ if (StringIdentifier->Flags & STRING_FLAGS_REFERENCED) {
+ UnicodeSPrint (
+ Line,
+ sizeof(Line), L"%s %-60.60s 0x%04X",
+ DEFINE_STR,
+ StringIdentifier->StringName,
+ StringIdentifier->Index
+ );
+ } else {
+ UnicodeSPrint (
+ Line,
+ sizeof(Line), L"%s %-60.60s 0x%04X // NOT REFERENCED",
+ DEFINE_STR,
+ StringIdentifier->StringName,
+ StringIdentifier->Index
+ );
+ }
+
+ fwrite (Line, StrLen (Line) * sizeof (WCHAR), 1, OutFptr);
+ fwrite (&CrLf, sizeof (CrLf), 1, OutFptr);
+ }
+
+ fwrite (&CrLf, sizeof (CrLf), 1, OutFptr);
+ //
+ // Now write all the strings for each language.
+ //
+ WChar = UNICODE_DOUBLE_QUOTE;
+ Scope = NULL;
+ for (Lang = mDBData.LanguageList; Lang != NULL; Lang = Lang->Next) {
+ fwrite (&CrLf, sizeof (CrLf), 1, OutFptr);
+ UnicodeSPrint (Line, sizeof(Line), L"#langdef %s \"%s\"", Lang->LanguageName, Lang->PrintableLanguageName);
+ fwrite (Line, StrLen (Line) * sizeof (WCHAR), 1, OutFptr);
+ fwrite (&CrLf, sizeof (CrLf), 1, OutFptr);
+ fwrite (&CrLf, sizeof (CrLf), 1, OutFptr);
+ //
+ // Now the strings (in double-quotes) for this language. Write
+ // #string STR_NAME #language eng "string"
+ //
+ for (StrList = Lang->String; StrList != NULL; StrList = StrList->Next) {
+ //
+ // Print the internal flags for debug
+ //
+ UnicodeSPrint (Line, sizeof(Line), L"// flags=0x%02X", (UINT32) StrList->Flags);
+ fwrite (Line, StrLen (Line) * sizeof (WCHAR), 1, OutFptr);
+ fwrite (&CrLf, sizeof (CrLf), 1, OutFptr);
+ //
+ // Print the scope if changed
+ //
+ if ((Scope == NULL) || (StrCmp (Scope, StrList->Scope) != 0)) {
+ UnicodeSPrint (Line, sizeof(Line), L"#scope %s", StrList->Scope);
+ fwrite (Line, StrLen (Line) * sizeof (WCHAR), 1, OutFptr);
+ fwrite (&CrLf, sizeof (CrLf), 1, OutFptr);
+ Scope = StrList->Scope;
+ }
+
+ UnicodeSPrint (
+ Line,
+ sizeof(Line), L"#string %-50.50s #language %s \"",
+ StrList->StringName,
+ Lang->LanguageName
+ );
+ fwrite (Line, StrLen (Line) * sizeof (WCHAR), 1, OutFptr);
+ fwrite (StrList->Str, StrList->Size - sizeof (WCHAR), 1, OutFptr);
+ UnicodeSPrint (Line, sizeof(Line), L"\"");
+ fwrite (Line, StrLen (Line) * sizeof (WCHAR), 1, OutFptr);
+ fwrite (&CrLf, sizeof (CrLf), 1, OutFptr);
+ }
+ }
+
+ fclose (OutFptr);
+ return STATUS_SUCCESS;
+}
+
+/*****************************************************************************/
+
+/*++
+
+Routine Description:
+
+ Given a primary language, a string identifier number, and a list of
+ languages, find a secondary string.
+
+Arguments:
+
+ LanguageName - primary language, like "spa"
+ StringId - string index value
+ LanguageList - linked list of "eng", "spa+cat",...
+
+Returns:
+
+ Pointer to a secondary string if found. NULL otherwise.
+
+Notes:
+
+ Given: LanguageName "spa" and LanguageList "spa+cat", match the
+ "spa" and extract the "cat" and see if there is a string defined
+ for "cat".StringId.
+
+--*/
+static
+STATUS
+StringDBWriteStringIdentifier (
+ FILE *DBFptr,
+ UINT16 StringId,
+ UINT16 Flags,
+ WCHAR *IdentifierName
+ )
+{
+ DB_DATA_ITEM_HEADER Hdr;
+ memset (&Hdr, 0, sizeof (DB_DATA_ITEM_HEADER));
+ Hdr.DataType = DB_DATA_TYPE_STRING_IDENTIFIER;
+ if (fwrite (&Hdr, sizeof (DB_DATA_ITEM_HEADER), 1, DBFptr) != 1) {
+ Error (NULL, 0, 0, "failed to write string to output database file", NULL);
+ return STATUS_ERROR;
+ }
+
+ if (fwrite (&StringId, sizeof (StringId), 1, DBFptr) != 1) {
+ Error (NULL, 0, 0, "failed to write StringId to output database", NULL);
+ return STATUS_ERROR;
+ }
+
+ if (fwrite (&Flags, sizeof (Flags), 1, DBFptr) != 1) {
+ Error (NULL, 0, 0, "failed to write StringId flags to output database", NULL);
+ return STATUS_ERROR;
+ }
+
+ if (StringDBWriteGenericString (DBFptr, IdentifierName) != STATUS_SUCCESS) {
+ return STATUS_ERROR;
+ }
+
+ return STATUS_SUCCESS;
+}
+
+static
+STATUS
+StringDBReadStringIdentifier (
+ FILE *DBFptr
+ )
+{
+ WCHAR *IdentifierName;
+ UINT16 Flags;
+ UINT16 StringId;
+ UINT16 Size;
+
+ if (fread (&StringId, sizeof (StringId), 1, DBFptr) != 1) {
+ Error (NULL, 0, 0, "failed to read StringId from database", NULL);
+ return STATUS_ERROR;
+ }
+
+ if (fread (&Flags, sizeof (Flags), 1, DBFptr) != 1) {
+ Error (NULL, 0, 0, "failed to read StringId flags from database", NULL);
+ return STATUS_ERROR;
+ }
+
+ if (StringDBReadGenericString (DBFptr, &Size, &IdentifierName) != STATUS_SUCCESS) {
+ return STATUS_ERROR;
+ }
+
+ StringDBAddStringIdentifier (IdentifierName, &StringId, Flags);
+ //
+ // printf ("STRID: 0x%04X %S\n", (UINT32)StringId, IdentifierName);
+ //
+ FREE (IdentifierName);
+ return STATUS_SUCCESS;
+}
+
+static
+STATUS
+StringDBWriteString (
+ FILE *DBFptr,
+ UINT16 Flags,
+ WCHAR *Language,
+ WCHAR *StringName,
+ WCHAR *Scope,
+ WCHAR *Str
+ )
+{
+ DB_DATA_ITEM_HEADER Hdr;
+ memset (&Hdr, 0, sizeof (DB_DATA_ITEM_HEADER));
+ Hdr.DataType = DB_DATA_TYPE_STRING_DEFINITION;
+ if (fwrite (&Hdr, sizeof (DB_DATA_ITEM_HEADER), 1, DBFptr) != 1) {
+ Error (NULL, 0, 0, "failed to write string header to output database file", NULL);
+ return STATUS_ERROR;
+ }
+
+ if (fwrite (&Flags, sizeof (Flags), 1, DBFptr) != 1) {
+ Error (NULL, 0, 0, "failed to write string flags to output database", NULL);
+ return STATUS_ERROR;
+ }
+
+ if (StringDBWriteGenericString (DBFptr, Language) != STATUS_SUCCESS) {
+ return STATUS_ERROR;
+ }
+
+ if (StringDBWriteGenericString (DBFptr, StringName) != STATUS_SUCCESS) {
+ return STATUS_ERROR;
+ }
+
+ if (StringDBWriteGenericString (DBFptr, Scope) != STATUS_SUCCESS) {
+ return STATUS_ERROR;
+ }
+
+ if (StringDBWriteGenericString (DBFptr, Str) != STATUS_SUCCESS) {
+ return STATUS_ERROR;
+ }
+ //
+ // printf ("DBWriteString: %S.%S.%S\n", Language, StringName, Scope);
+ //
+ return STATUS_SUCCESS;
+}
+
+static
+STATUS
+StringDBReadString (
+ FILE *DBFptr
+ )
+{
+ UINT16 Flags;
+ UINT16 Size;
+ WCHAR *Language;
+ WCHAR *StringName;
+ WCHAR *Scope;
+ WCHAR *Str;
+
+ if (fread (&Flags, sizeof (Flags), 1, DBFptr) != 1) {
+ Error (NULL, 0, 0, "failed to read string flags from database", NULL);
+ return STATUS_ERROR;
+ }
+
+ if (StringDBReadGenericString (DBFptr, &Size, &Language) != STATUS_SUCCESS) {
+ return STATUS_ERROR;
+ }
+
+ if (StringDBReadGenericString (DBFptr, &Size, &StringName) != STATUS_SUCCESS) {
+ return STATUS_ERROR;
+ }
+
+ if (StringDBReadGenericString (DBFptr, &Size, &Scope) != STATUS_SUCCESS) {
+ return STATUS_ERROR;
+ }
+
+ if (StringDBReadGenericString (DBFptr, &Size, &Str) != STATUS_SUCCESS) {
+ return STATUS_ERROR;
+ }
+ //
+ // If the first or second string (language name and printable language name),
+ // then skip them. They're added via language definitions data items in
+ // the database.
+ //
+ if (StringName[0] != L'$') {
+ StringDBAddString (Language, StringName, Scope, Str, FALSE, Flags);
+ }
+ //
+ // printf ("DBReadString: %S.%S.%S\n", Language, StringName, Scope);
+ //
+ FREE (Language);
+ FREE (StringName);
+ if (Str != NULL) {
+ FREE (Str);
+ }
+
+ if (Scope != NULL) {
+ FREE (Scope);
+ }
+
+ return STATUS_SUCCESS;
+}
+
+static
+STATUS
+StringDBWriteLanguageDefinition (
+ FILE *DBFptr,
+ WCHAR *LanguageName,
+ WCHAR *PrintableLanguageName
+ )
+{
+ DB_DATA_ITEM_HEADER Hdr;
+ memset (&Hdr, 0, sizeof (DB_DATA_ITEM_HEADER));
+ Hdr.DataType = DB_DATA_TYPE_LANGUAGE_DEFINITION;
+ if (fwrite (&Hdr, sizeof (DB_DATA_ITEM_HEADER), 1, DBFptr) != 1) {
+ Error (NULL, 0, 0, "failed to write string to output database file", NULL);
+ return STATUS_ERROR;
+ }
+
+ if (StringDBWriteGenericString (DBFptr, LanguageName) != STATUS_SUCCESS) {
+ return STATUS_ERROR;
+ }
+
+ if (StringDBWriteGenericString (DBFptr, PrintableLanguageName) != STATUS_SUCCESS) {
+ return STATUS_ERROR;
+ }
+
+ return STATUS_SUCCESS;
+}
+
+static
+STATUS
+StringDBReadLanguageDefinition (
+ FILE *DBFptr
+ )
+{
+ WCHAR *LanguageName;
+ WCHAR *PrintableLanguageName;
+ UINT16 Size;
+ STATUS Status;
+
+ if (StringDBReadGenericString (DBFptr, &Size, &LanguageName) != STATUS_SUCCESS) {
+ return STATUS_ERROR;
+ }
+
+ if (StringDBReadGenericString (DBFptr, &Size, &PrintableLanguageName) != STATUS_SUCCESS) {
+ return STATUS_ERROR;
+ }
+ //
+ // printf("LANG: %S %S\n", LanguageName, PrintableLanguageName);
+ //
+ Status = StringDBAddLanguage (LanguageName, PrintableLanguageName);
+ FREE (LanguageName);
+ FREE (PrintableLanguageName);
+ return Status;
+}
+//
+// All unicode strings in the database consist of a UINT16 length
+// field, followed by the string itself. This routine reads one
+// of those and returns the info.
+//
+static
+STATUS
+StringDBReadGenericString (
+ FILE *DBFptr,
+ UINT16 *Size,
+ WCHAR **Str
+ )
+{
+ UINT16 LSize;
+ UINT16 Flags;
+ WCHAR *LStr;
+
+ if (fread (&LSize, sizeof (UINT16), 1, DBFptr) != 1) {
+ Error (NULL, 0, 0, "failed to read a string length field from the database", NULL);
+ return STATUS_ERROR;
+ }
+
+ if (fread (&Flags, sizeof (UINT16), 1, DBFptr) != 1) {
+ Error (NULL, 0, 0, "failed to read a string flags field from the database", NULL);
+ return STATUS_ERROR;
+ }
+
+ LStr = MALLOC (LSize);
+ if (LStr == NULL) {
+ Error (__FILE__, __LINE__, 0, "memory allocation failed reading the database", NULL);
+ return STATUS_ERROR;
+ }
+
+ if (fread (LStr, sizeof (WCHAR), (UINT32) LSize / sizeof (WCHAR), DBFptr) != (UINT32) LSize / sizeof (WCHAR)) {
+ Error (NULL, 0, 0, "failed to read string from database", NULL);
+ Error (NULL, 0, 0, "database read failure", "offset 0x%X", ftell (DBFptr));
+ free (LStr);
+ return STATUS_ERROR;
+ }
+ //
+ // printf ("DBR: %S\n", LStr);
+ //
+ // If the flags field indicated we were asked to write a NULL string, then
+ // return them a NULL pointer.
+ //
+ if (Flags & STRING_FLAGS_UNDEFINED) {
+ *Size = 0;
+ *Str = NULL;
+ } else {
+ *Size = LSize;
+ *Str = LStr;
+ }
+
+ return STATUS_SUCCESS;
+}
+
+static
+STATUS
+StringDBWriteGenericString (
+ FILE *DBFptr,
+ WCHAR *Str
+ )
+{
+ UINT16 Size;
+ UINT16 Flags;
+ WCHAR ZeroString[1];
+ //
+ // Strings in the database consist of a size UINT16 followed
+ // by the string itself.
+ //
+ if (Str == NULL) {
+ ZeroString[0] = 0;
+ Str = ZeroString;
+ Size = sizeof (ZeroString);
+ Flags = STRING_FLAGS_UNDEFINED;
+ } else {
+ Flags = 0;
+ Size = (UINT16) ((StrLen (Str) + 1) * sizeof (WCHAR));
+ }
+
+ if (fwrite (&Size, sizeof (UINT16), 1, DBFptr) != 1) {
+ Error (NULL, 0, 0, "failed to write string size to database", NULL);
+ return STATUS_ERROR;
+ }
+
+ if (fwrite (&Flags, sizeof (UINT16), 1, DBFptr) != 1) {
+ Error (NULL, 0, 0, "failed to write string flags to database", NULL);
+ return STATUS_ERROR;
+ }
+
+ if (fwrite (Str, sizeof (WCHAR), Size / sizeof (WCHAR), DBFptr) != Size / sizeof (WCHAR)) {
+ Error (NULL, 0, 0, "failed to write string to database", NULL);
+ return STATUS_ERROR;
+ }
+
+ return STATUS_SUCCESS;
+}
+
+static
+STRING_LIST *
+StringDBFindString (
+ WCHAR *LanguageName,
+ WCHAR *StringName,
+ WCHAR *Scope,
+ WCHAR_STRING_LIST *LanguagesOfInterest,
+ WCHAR_MATCHING_STRING_LIST *IndirectionList
+ )
+{
+ LANGUAGE_LIST *Lang;
+ STRING_LIST *CurrString;
+ WCHAR_MATCHING_STRING_LIST *IndListPtr;
+ WCHAR TempLangName[LANGUAGE_IDENTIFIER_NAME_LEN + 1];
+ WCHAR *WCharPtr;
+
+ //
+ // If we were given an indirection list, then see if one was specified for this
+ // string identifier. That is to say, if the indirection says "STR_ID_MY_FAVORITE MyScope",
+ // then if this string name matches one in the list, then do a lookup with the
+ // specified scope and return that value.
+ //
+ if (IndirectionList != NULL) {
+ for (IndListPtr = IndirectionList; IndListPtr != NULL; IndListPtr = IndListPtr->Next) {
+ if (StrCmp (StringName, IndListPtr->Str1) == 0) {
+ CurrString = StringDBFindString (LanguageName, StringName, IndListPtr->Str2, LanguagesOfInterest, NULL);
+ if (CurrString != NULL) {
+ return CurrString;
+ }
+ }
+ }
+ }
+ //
+ // First look for exact match language.stringname
+ //
+ for (Lang = mDBData.LanguageList; Lang != NULL; Lang = Lang->Next) {
+ if (StrCmp (LanguageName, Lang->LanguageName) == 0) {
+ //
+ // Found language match. Try to find string name match
+ //
+ for (CurrString = Lang->String; CurrString != NULL; CurrString = CurrString->Next) {
+ if (StrCmp (StringName, CurrString->StringName) == 0) {
+ //
+ // Found a string name match. See if we're supposed to find
+ // a scope match.
+ //
+ if (Scope != NULL) {
+ if (StrCmp (CurrString->Scope, Scope) == 0) {
+ return CurrString;
+ }
+ } else {
+ return CurrString;
+ }
+ }
+ }
+ }
+ }
+ //
+ // If we got here, then we didn't find a match. Look for secondary string
+ // matches. That is to say, if we're processing "spa", and they requested
+ // "spa+cat", then recursively call with "cat"
+ //
+ while (LanguagesOfInterest != NULL) {
+ //
+ // If this is the language we're looking for, then process the
+ // languages of interest list for it.
+ //
+ if (StrnCmp (LanguageName, LanguagesOfInterest->Str, LANGUAGE_IDENTIFIER_NAME_LEN) == 0) {
+ WCharPtr = LanguagesOfInterest->Str + LANGUAGE_IDENTIFIER_NAME_LEN;
+ while (*WCharPtr) {
+ //
+ // Double-check the length, though it should have been checked on the
+ // command line.
+ //
+ if (StrLen (WCharPtr) < LANGUAGE_IDENTIFIER_NAME_LEN) {
+ Error (NULL, 0, 0, "malformed alternate language list", "%S", LanguagesOfInterest->Str);
+ return NULL;
+ }
+
+ StrnCpy (TempLangName, WCharPtr, LANGUAGE_IDENTIFIER_NAME_LEN);
+ TempLangName[LANGUAGE_IDENTIFIER_NAME_LEN] = 0;
+ CurrString = StringDBFindString (TempLangName, StringName, NULL, NULL, IndirectionList);
+ if (CurrString != NULL) {
+ return CurrString;
+ }
+
+ WCharPtr += LANGUAGE_IDENTIFIER_NAME_LEN;
+ }
+ }
+
+ LanguagesOfInterest = LanguagesOfInterest->Next;
+ }
+
+ return NULL;
+}
+
+STATUS
+StringDBSetScope (
+ WCHAR *Scope
+ )
+{
+ //
+ // Free up existing scope memory.
+ //
+ if (mDBData.CurrentScope != NULL) {
+ FREE (mDBData.CurrentScope);
+ }
+
+ mDBData.CurrentScope = DuplicateString (Scope);
+ return STATUS_SUCCESS;
+}
+//
+// We typically don't assign index values to string identifiers
+// until we're ready to write out files. To reduce the size of
+// the output file, re-order the string identifiers to move any
+// unreferenced ones to the end. Then we'll walk the list
+// again to assign string indexes, keeping track of the last
+// one referenced.
+//
+static
+void
+StringDBAssignStringIndexes (
+ VOID
+ )
+{
+ STRING_IDENTIFIER *StrId;
+ STRING_IDENTIFIER *FirstUsed;
+ STRING_IDENTIFIER *LastUsed;
+ STRING_IDENTIFIER *FirstUnused;
+ STRING_IDENTIFIER *LastUnused;
+ UINT32 Index;
+ UINT32 MaxReferenced;
+
+ //
+ // Create two lists -- used and unused. Then put them together with
+ // the unused ones on the end.
+ //
+ FirstUsed = NULL;
+ LastUsed = NULL;
+ FirstUnused = NULL;
+ LastUnused = NULL;
+ StrId = mDBData.StringIdentifier;
+ while (StrId != NULL) {
+ if ((StrId->Flags & STRING_FLAGS_REFERENCED) == 0) {
+ //
+ // Put it on the unused list
+ //
+ if (FirstUnused == NULL) {
+ FirstUnused = StrId;
+ } else {
+ LastUnused->Next = StrId;
+ }
+
+ LastUnused = StrId;
+ StrId = StrId->Next;
+ LastUnused->Next = NULL;
+ } else {
+ //
+ // Put it on the used list
+ //
+ if (FirstUsed == NULL) {
+ FirstUsed = StrId;
+ } else {
+ LastUsed->Next = StrId;
+ }
+
+ LastUsed = StrId;
+ StrId = StrId->Next;
+ LastUsed->Next = NULL;
+ }
+ }
+ //
+ // Join the lists
+ //
+ if (FirstUsed != NULL) {
+ mDBData.StringIdentifier = FirstUsed;
+ LastUsed->Next = FirstUnused;
+ } else {
+ mDBData.StringIdentifier = FirstUnused;
+ }
+
+ MaxReferenced = 0;
+ Index = 0;
+ for (StrId = mDBData.StringIdentifier; StrId != NULL; StrId = StrId->Next) {
+ StrId->Index = Index;
+ Index++;
+ if (StrId->Flags & STRING_FLAGS_REFERENCED) {
+ mDBData.NumStringIdentifiersReferenced = Index;
+ }
+ }
+
+ mDBData.NumStringIdentifiers = Index;
+}
+
+static
+WCHAR *
+DuplicateString (
+ WCHAR *Str
+ )
+{
+ WCHAR *NewStr;
+ if (Str == NULL) {
+ return NULL;
+ }
+
+ NewStr = MALLOC ((StrLen (Str) + 1) * sizeof (WCHAR));
+ if (NewStr == NULL) {
+ Error (NULL, 0, 0, "memory allocation failure", NULL);
+ return NULL;
+ }
+
+ StrCpy (NewStr, Str);
+ return NewStr;
+}
+
+static
+WCHAR *
+AsciiToWchar (
+ CHAR8 *Str
+ )
+{
+ UINT32 Len;
+ WCHAR *NewStr;
+ WCHAR *Ptr;
+
+ Len = strlen (Str) + 1;
+ NewStr = (WCHAR *) malloc (Len * sizeof (WCHAR));
+ for (Ptr = NewStr; *Str != 0; Str++, Ptr++) {
+ *Ptr = (UINT16) (UINT8) *Str;
+ }
+
+ *Ptr = 0;
+ return NewStr;
+}
+
+/*****************************************************************************/
+
+/*++
+
+Routine Description:
+
+ Create an HII export string pack for the strings in our database.
+
+Arguments:
+
+ FileName - name of the output file to write
+
+Returns:
+
+ STATUS
+
+
+--*/
+STATUS
+StringDBCreateHiiExportPack (
+ CHAR8 *FileName
+ )
+{
+ FILE *Fptr;
+ LANGUAGE_LIST *Lang;
+ STRING_LIST *CurrString;
+ STRING_LIST EmptyString;
+ UINT32 Offset;
+ UINT32 StringIndex;
+ UINT32 TempIndex;
+ EFI_HII_STRING_PACK StringPack;
+ UINT32 Len;
+ WCHAR ZeroString[1];
+ WCHAR *TempStringPtr;
+ WCHAR *LangName;
+ STRING_IDENTIFIER *StringIdentifier;
+
+ if ((Fptr = fopen (FileName, "wb")) == NULL) {
+ Error (NULL, 0, 0, FileName, "failed to open output HII export file");
+ return STATUS_ERROR;
+ }
+ //
+ // Assign index values to the string identifiers
+ //
+ StringDBAssignStringIndexes ();
+ //
+ // If a given string is not defined, then we'll use this one.
+ //
+ memset (&EmptyString, 0, sizeof (EmptyString));
+ EmptyString.Size = sizeof (ZeroString);
+ EmptyString.Str = ZeroString;
+ //
+ // Process each language, then each string for each langage
+ //
+ ZeroString[0] = 0;
+ for (Lang = mDBData.LanguageList; Lang != NULL; Lang = Lang->Next) {
+ //
+ // Process each string for this language. We have to make 3 passes on the strings:
+ // Pass1: computes sizes and fill in the string pack header
+ // Pass2: write the array of offsets
+ // Pass3: write the strings
+ //
+ //
+ // PASS 1: Fill in and print the HII string pack header
+ //
+ // Compute the size for this language package and write
+ // the header out. Each string package contains:
+ // Header
+ // Offset[] -- an array of offsets to strings, of type RELOFST each
+ // String[] -- the actual strings themselves
+ //
+ memset ((char *) &StringPack, 0, sizeof (EFI_HII_STRING_PACK));
+ StringPack.Header.Type = EFI_HII_STRING;
+ StringPack.NumStringPointers = (UINT16) mDBData.NumStringIdentifiersReferenced;
+ LangName = Lang->LanguageName;
+ //
+ // First string is the language name. If we're printing all languages, then
+ // it's just the "spa". If we were given a list of languages to print, then it's
+ // the "spacat" string. Compute its offset and fill in
+ // the info in the header. Since we know the language name string's length,
+ // and the printable language name follows it, use that info to fill in the
+ // entry for the printable language name as well.
+ //
+ StringPack.LanguageNameString = (STRING_OFFSET) (sizeof (EFI_HII_STRING_PACK) + (mDBData.NumStringIdentifiersReferenced * sizeof (STRING_OFFSET)));
+ StringPack.PrintableLanguageName = (STRING_OFFSET) (StringPack.LanguageNameString + (StrLen (LangName) + 1) * sizeof (WCHAR));
+ //
+ // Add up the size of all strings so we can fill in our header.
+ //
+ Len = 0;
+ for (StringIndex = 0; StringIndex < mDBData.NumStringIdentifiersReferenced; StringIndex++) {
+ //
+ // For the first string (language name), we print out the "spacat" if they
+ // requested it. We set LangName to point to the proper language name string above.
+ //
+ if (StringIndex == STRING_ID_LANGUAGE_NAME) {
+ Len += (StrLen (LangName) + 1) * sizeof (WCHAR);
+ } else {
+ //
+ // Find a string with this language.stringname
+ //
+ StringIdentifier = StringDBFindStringIdentifierByIndex (StringIndex);
+ if (StringIdentifier == NULL) {
+ Error (NULL, 0, 0, "internal error", "invalid string index 0x%X", StringIndex);
+ return STATUS_ERROR;
+ }
+ //
+ // Find a matching string if this string identifier was referenced
+ //
+ EmptyString.Flags = STRING_FLAGS_UNDEFINED;
+ CurrString = NULL;
+ if (StringIdentifier->Flags & STRING_FLAGS_REFERENCED) {
+ CurrString = StringDBFindString (
+ Lang->LanguageName,
+ StringIdentifier->StringName,
+ NULL,
+ NULL, // LanguagesOfInterest,
+ NULL
+ );
+ //
+ // IndirectionList);
+ //
+ if (NULL == CurrString) {
+ //
+ // If string for Lang->LanguageName is not found, try to get an English version
+ //
+ CurrString = StringDBFindString (
+ L"eng",
+ StringIdentifier->StringName,
+ NULL,
+ NULL, // LanguagesOfInterest,
+ NULL
+ );
+ //
+ // IndirectionList);
+ //
+ }
+ }
+
+ if (CurrString == NULL) {
+ CurrString = &EmptyString;
+ EmptyString.Flags |= StringIdentifier->Flags;
+ }
+
+ Len += CurrString->Size;
+ }
+ }
+ StringPack.Header.Length = sizeof (EFI_HII_STRING_PACK)
+ + mDBData.NumStringIdentifiersReferenced * sizeof (STRING_OFFSET)
+ + Len;
+ //
+ // Write out the string pack header
+ //
+ fwrite ((void *) &StringPack, sizeof (StringPack), 1, Fptr);
+ //
+ // PASS2 : write the offsets
+ //
+ // Traverse the list of strings again and write the array of offsets. The
+ // offset to the first string is the size of the string pack header
+ // plus the size of the offsets array. The other strings follow it.
+ //
+ StringIndex = 0;
+ Offset = sizeof (StringPack) + mDBData.NumStringIdentifiersReferenced * sizeof (STRING_OFFSET);
+ for (StringIndex = 0; StringIndex < mDBData.NumStringIdentifiersReferenced; StringIndex++) {
+ //
+ // Write the offset
+ //
+ fwrite (&Offset, sizeof (STRING_OFFSET), 1, Fptr);
+ //
+ // Find the string name
+ //
+ StringIdentifier = StringDBFindStringIdentifierByIndex (StringIndex);
+ if (StringIdentifier == NULL) {
+ Error (NULL, 0, 0, "internal error", "invalid string index 0x%X", StringIndex);
+ return STATUS_ERROR;
+ }
+ //
+ // For the first string (language name), we print out the "spacat" if they
+ // requested it. We set LangName to point to the proper language name string above.
+ //
+ if (StringIndex == STRING_ID_LANGUAGE_NAME) {
+ Offset += (StrLen (LangName) + 1) * sizeof (WCHAR);
+ CurrString = StringDBFindString (
+ Lang->LanguageName,
+ StringIdentifier->StringName,
+ NULL, // scope
+ NULL,
+ NULL
+ );
+ } else {
+ //
+ // Find a matching string
+ //
+ CurrString = StringDBFindString (
+ Lang->LanguageName,
+ StringIdentifier->StringName,
+ NULL, // scope
+ NULL, // LanguagesOfInterest,
+ NULL
+ );
+ //
+ // IndirectionList);
+ //
+ if (NULL == CurrString) {
+ CurrString = StringDBFindString (
+ L"eng",
+ StringIdentifier->StringName,
+ NULL, // scope
+ NULL, // LanguagesOfInterest,
+ NULL
+ );
+ //
+ // IndirectionList);
+ //
+ }
+
+ EmptyString.LanguageName = Lang->LanguageName;
+ if (CurrString == NULL) {
+ CurrString = &EmptyString;
+ EmptyString.Flags = STRING_FLAGS_UNDEFINED;
+ } else if ((StringIdentifier->Flags & STRING_FLAGS_REFERENCED) == 0) {
+ CurrString = &EmptyString;
+ EmptyString.Flags = 0;
+ }
+
+ Offset += CurrString->Size;
+ }
+ }
+
+ //
+ // PASS 3: write the strings themselves.
+ //
+ Offset = sizeof (StringPack) + mDBData.NumStringIdentifiersReferenced * sizeof (STRING_OFFSET);
+ for (StringIndex = 0; StringIndex < mDBData.NumStringIdentifiersReferenced; StringIndex++) {
+ StringIdentifier = StringDBFindStringIdentifierByIndex (StringIndex);
+ if (StringIdentifier == NULL) {
+ Error (NULL, 0, 0, "internal error", "invalid string index 0x%X", StringIndex);
+ return STATUS_ERROR;
+ }
+ //
+ // For the first string (language name), we print out the "spacat" if they
+ // requested it. We set LangName to point to the proper language name string above.
+ //
+ if (StringIndex == STRING_ID_LANGUAGE_NAME) {
+ TempStringPtr = LangName;
+ } else {
+ //
+ // Find a matching string if this string identifier was referenced
+ //
+ CurrString = NULL;
+ if (StringIdentifier->Flags & STRING_FLAGS_REFERENCED) {
+ CurrString = StringDBFindString (
+ Lang->LanguageName,
+ StringIdentifier->StringName,
+ NULL, // scope
+ NULL, // LanguagesOfInterest,
+ NULL
+ );
+ //
+ // IndirectionList);
+ //
+ if (NULL == CurrString) {
+ CurrString = StringDBFindString (
+ L"eng",
+ StringIdentifier->StringName,
+ NULL, // scope
+ NULL, // LanguagesOfInterest,
+ NULL
+ );
+ //
+ // IndirectionList);
+ //
+ }
+ }
+
+ if (CurrString == NULL) {
+ CurrString = &EmptyString;
+ }
+
+ TempStringPtr = CurrString->Str;
+ }
+
+ for (TempIndex = 0; TempStringPtr[TempIndex] != 0; TempIndex++) {
+ fwrite (&TempStringPtr[TempIndex], sizeof (CHAR16), 1, Fptr);
+ Offset += 2;
+ }
+ //
+ // Print NULL WCHAR at the end of this string.
+ //
+ TempIndex = 0;
+ fwrite (&TempIndex, sizeof (CHAR16), 1, Fptr);
+ Offset += 2;
+ }
+ //
+ // Sanity check the offset. Make sure our running offset is what we put in the
+ // string pack header.
+ //
+ if (StringPack.Header.Length != Offset) {
+ Error (
+ __FILE__,
+ __LINE__,
+ 0,
+ "application error",
+ "stringpack size 0x%X does not match final size 0x%X",
+ StringPack.Header.Length,
+ Offset
+ );
+ }
+ }
+ //
+ // Print terminator string pack, closing brace and close the file.
+ // The size of 0 triggers to the consumer that this is the end.
+ //
+ memset ((char *) &StringPack, 0, sizeof (EFI_HII_STRING_PACK));
+ StringPack.Header.Type = EFI_HII_STRING;
+ fwrite ((void *) &StringPack, sizeof (StringPack), 1, Fptr);
+ fclose (Fptr);
+ return STATUS_SUCCESS;
+}
diff --git a/Source/StrGather/StringDB.h b/Source/StrGather/StringDB.h
new file mode 100644
index 0000000..c525731
--- /dev/null
+++ b/Source/StrGather/StringDB.h
@@ -0,0 +1,136 @@
+/*++
+
+Copyright (c) 2004, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ StringDB.h
+
+Abstract:
+
+ Common defines and prototypes for string database management
+
+--*/
+
+#ifndef _STRING_DB_H_
+#define _STRING_DB_H_
+
+#define LANGUAGE_NAME_STRING_NAME L"$LANGUAGE_NAME"
+#define PRINTABLE_LANGUAGE_NAME_STRING_NAME L"$PRINTABLE_LANGUAGE_NAME"
+
+void
+StringDBConstructor (
+ void
+ )
+;
+void
+StringDBDestructor (
+ void
+ )
+;
+
+STATUS
+StringDBAddString (
+ WCHAR *LanguageName,
+ WCHAR *StringIdentifier,
+ WCHAR *Scope,
+ WCHAR *String,
+ BOOLEAN Format,
+ UINT16 Flags
+ )
+;
+
+STATUS
+StringDBSetScope (
+ WCHAR *Scope
+ )
+;
+
+#define STRING_FLAGS_REFERENCED 0x0001 // if referenced somewhere
+#define STRING_FLAGS_UNDEFINED 0x0002 // if we added it for padding purposes
+#define STRING_FLAGS_INDEX_ASSIGNED 0x0004 // so don't change the index value
+#define STRING_ID_INVALID 0xFFFF
+#define STRING_ID_LANGUAGE_NAME 0x0000
+#define STRING_ID_PRINTABLE_LANGUAGE_NAME 0x0001
+
+STATUS
+StringDBAddStringIdentifier (
+ WCHAR *StringIdentifier,
+ UINT16 *NewId,
+ UINT16 Flags
+ )
+;
+
+STATUS
+StringDBReadDatabase (
+ CHAR8 *DBFileName,
+ BOOLEAN IgnoreIfNotExist,
+ BOOLEAN Verbose
+ )
+;
+
+STATUS
+StringDBWriteDatabase (
+ CHAR8 *DBFileName,
+ BOOLEAN Verbose
+ )
+;
+
+STATUS
+StringDBDumpDatabase (
+ CHAR8 *DBFileName,
+ CHAR8 *OutputFileName,
+ BOOLEAN Verbose
+ )
+;
+
+STATUS
+StringDBAddLanguage (
+ WCHAR *LanguageName,
+ WCHAR *PrintableLanguageName
+ )
+;
+
+STATUS
+StringDBDumpCStrings (
+ CHAR8 *FileName,
+ CHAR8 *BaseName,
+ WCHAR_STRING_LIST *LanguagesOfInterest,
+ WCHAR_MATCHING_STRING_LIST *IndirectionList
+ )
+;
+
+STATUS
+StringDBDumpStringDefines (
+ CHAR8 *FileName,
+ CHAR8 *BaseName
+ )
+;
+
+STATUS
+StringDBSetCurrentLanguage (
+ WCHAR *LanguageName
+ )
+;
+
+STATUS
+StringDBSetStringReferenced (
+ CHAR8 *StringIdentifierName,
+ BOOLEAN IgnoreNotFound
+ )
+;
+
+void
+StringDBFormatString (
+ WCHAR *String
+ )
+;
+
+#endif // #ifndef _STRING_DB_H_
diff --git a/Source/StrGather/build.xml b/Source/StrGather/build.xml
new file mode 100644
index 0000000..901b4a8
--- /dev/null
+++ b/Source/StrGather/build.xml
@@ -0,0 +1,71 @@
+<?xml version="1.0" ?>
+<!--
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+-->
+<project default="GenTool" basedir=".">
+<!--
+ EDK StrGather Tool
+ Copyright (c) 2006, Intel Corporation
+-->
+ <property name="ToolName" value="StrGather"/>
+ <property name="FileSet" value="*.c *.h"/>
+
+ <taskdef resource="net/sf/antcontrib/antlib.xml"/>
+
+ <property name="LINK_OUTPUT_TYPE" value="static"/>
+ <property name="BUILD_DIR" value="${PACKAGE_DIR}/${ToolName}/tmp"/>
+
+ <target name="GenTool" depends="init, Tool">
+ <echo message="The EDK Tool: ${ToolName} build has completed!"/>
+ </target>
+
+ <target name="init">
+ <echo message="Building the EDK Tool: ${ToolName}"/>
+ <mkdir dir="${BUILD_DIR}"/>
+ </target>
+
+ <target name="Tool" depends="init">
+ <cc name="${ToolChain}" objdir="${BUILD_DIR}"
+ outfile="${BIN_DIR}/${ToolName}"
+ outtype="executable"
+ optimize="speed"
+ debug="true">
+
+ <compilerarg value="-fshort-wchar" if="gcc"/>
+
+ <fileset dir="${basedir}/${ToolName}"
+ includes="${FileSet}"
+ defaultexcludes="TRUE"
+ excludes="*.xml *.inf"/>
+
+ <includepath path="${PACKAGE_DIR}/Include"/>
+ <includepath path="${PACKAGE_DIR}/Include/${HostArch}"/>
+ <includepath path="${PACKAGE_DIR}/Common"/>
+ <libset dir="${LIB_DIR}" libs="CommonTools String"/>
+ </cc>
+ </target>
+
+ <target name="clean">
+ <echo message="Removing Intermediate Files Only"/>
+ <delete>
+ <fileset dir="${BUILD_DIR}" includes="*.obj"/>
+ </delete>
+ </target>
+
+ <target name="cleanall">
+ <echo message="Removing Object Files and the Executable: ${ToolName}${ext_exe}"/>
+ <delete failonerror="false" quiet="true" includeEmptyDirs="true">
+ <fileset dir="${BUILD_DIR}"/>
+ <fileset file="${BIN_DIR}/${ToolName}${ext_exe}"/>
+ <fileset file="${BIN_DIR}/${ToolName}.pdb"/>
+ </delete>
+ </target>
+
+</project>
diff --git a/Source/String/PrintLib.c b/Source/String/PrintLib.c
new file mode 100644
index 0000000..eef3f4d
--- /dev/null
+++ b/Source/String/PrintLib.c
@@ -0,0 +1,674 @@
+/*++
+
+Copyright (c) 2004-2006 Intel Corporation. All rights reserved
+This program and the accompanying materials are licensed and made available
+under the terms and conditions of the BSD License which accompanies this
+distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+
+Module Name:
+
+ PrintLib.c
+
+Abstract:
+
+ Print Library.
+
+--*/
+
+#include <Common/UefiBaseTypes.h>
+#include <Library/PrintLib.h>
+
+#include "CommonLib.h"
+#include "PrintLibInternal.h"
+
+typedef struct {
+ RETURN_STATUS Status;
+ CHAR8 *String;
+} STATUS_LOOKUP_TABLE_ENTRY;
+
+static CONST STATUS_LOOKUP_TABLE_ENTRY StatusString[] = {
+ { RETURN_SUCCESS, "Success" },
+ { RETURN_LOAD_ERROR, "Load Error" },
+ { RETURN_INVALID_PARAMETER, "Invalid Parameter" },
+ { RETURN_UNSUPPORTED, "Unsupported" },
+ { RETURN_BAD_BUFFER_SIZE, "Bad Buffer Size" },
+ { RETURN_BUFFER_TOO_SMALL, "Buffer Too Small" },
+ { RETURN_NOT_READY, "Not Ready" },
+ { RETURN_DEVICE_ERROR, "Device Error" },
+ { RETURN_WRITE_PROTECTED, "Write Protected" },
+ { RETURN_OUT_OF_RESOURCES, "Out of Resources" },
+ { RETURN_VOLUME_CORRUPTED, "Volume Corrupt" },
+ { RETURN_VOLUME_FULL, "Volume Full" },
+ { RETURN_NO_MEDIA, "No Media" },
+ { RETURN_MEDIA_CHANGED, "Media changed" },
+ { RETURN_NOT_FOUND, "Not Found" },
+ { RETURN_ACCESS_DENIED, "Access Denied" },
+ { RETURN_NO_RESPONSE, "No Response" },
+ { RETURN_NO_MAPPING, "No mapping" },
+ { RETURN_TIMEOUT, "Time out" },
+ { RETURN_NOT_STARTED, "Not started" },
+ { RETURN_ALREADY_STARTED, "Already started" },
+ { RETURN_ABORTED, "Aborted" },
+ { RETURN_ICMP_ERROR, "ICMP Error" },
+ { RETURN_TFTP_ERROR, "TFTP Error" },
+ { RETURN_PROTOCOL_ERROR, "Protocol Error" },
+ { RETURN_WARN_UNKNOWN_GLYPH, "Warning Unknown Glyph" },
+ { RETURN_WARN_DELETE_FAILURE, "Warning Delete Failure" },
+ { RETURN_WARN_WRITE_FAILURE, "Warning Write Failure" },
+ { RETURN_WARN_BUFFER_TOO_SMALL, "Warning Buffer Too Small" },
+ { 0, NULL }
+};
+
+
+/**
+ VSPrint function to process format and place the results in Buffer. Since a
+ VA_LIST is used this rountine allows the nesting of Vararg routines. Thus
+ this is the main print working routine
+
+ @param StartOfBuffer Unicode buffer to print the results of the parsing of Format into.
+
+ @param BufferSize Maximum number of characters to put into buffer. Zero means
+ no limit.
+
+ @param Flags Intial flags value. Can only have FORMAT_UNICODE and OUTPUT_UNICODE set
+
+ @param FormatString Unicode format string see file header for more details.
+
+ @param Marker Vararg list consumed by processing Format.
+
+ @return Number of characters printed.
+
+**/
+UINTN
+BasePrintLibVSPrint (
+ OUT CHAR8 *Buffer,
+ IN UINTN BufferSize,
+ IN UINTN Flags,
+ IN CONST CHAR8 *Format,
+ IN VA_LIST Marker
+ )
+{
+ CHAR8 *OriginalBuffer;
+ CHAR8 ValueBuffer[MAXIMUM_VALUE_CHARACTERS];
+ UINTN BytesPerOutputCharacter;
+ UINTN BytesPerFormatCharacter;
+ UINTN FormatMask;
+ UINTN FormatCharacter;
+ UINTN Width;
+ UINTN Precision;
+ INT64 Value;
+ CHAR8 *ArgumentString;
+ UINTN Character;
+ GUID *TmpGuid;
+ TIME *TmpTime;
+ UINTN Count;
+ UINTN ArgumentMask;
+ INTN BytesPerArgumentCharacter;
+ UINTN ArgumentCharacter;
+ BOOLEAN Done;
+ UINTN Index;
+ CHAR8 Prefix;
+ BOOLEAN ZeroPad;
+ BOOLEAN Comma;
+ UINTN Digits;
+ UINTN Radix;
+ RETURN_STATUS Status;
+
+ OriginalBuffer = Buffer;
+
+ if ((Flags & OUTPUT_UNICODE) != 0) {
+ BytesPerOutputCharacter = 2;
+ } else {
+ BytesPerOutputCharacter = 1;
+ }
+ if ((Flags & FORMAT_UNICODE) != 0) {
+ BytesPerFormatCharacter = 2;
+ FormatMask = 0xffff;
+ } else {
+ BytesPerFormatCharacter = 1;
+ FormatMask = 0xff;
+ }
+
+ //
+ // Reserve space for the Null terminator.
+ // If BufferSize is 0, this will set BufferSize to the max unsigned value
+ //
+ BufferSize--;
+
+ //
+ // Get the first character from the format string
+ //
+ FormatCharacter = (*Format | (*(Format + 1) << 8)) & FormatMask;
+
+ //
+ // Loop until the end of the format string is reached or the output buffer is full
+ //
+ while (FormatCharacter != 0 && BufferSize > 0) {
+ //
+ // Clear all the flag bits except those that may have been passed in
+ //
+ Flags &= (OUTPUT_UNICODE | FORMAT_UNICODE);
+
+ //
+ // Set the default width to zero, and the default precision to 1
+ //
+ Width = 0;
+ Precision = 1;
+ Prefix = 0;
+ Comma = FALSE;
+ ZeroPad = FALSE;
+ Count = 0;
+ Digits = 0;
+
+ switch (FormatCharacter) {
+ case '%':
+ //
+ // Parse Flags and Width
+ //
+ for (Done = FALSE; !Done; ) {
+ Format += BytesPerFormatCharacter;
+ FormatCharacter = (*Format | (*(Format + 1) << 8)) & FormatMask;
+ switch (FormatCharacter) {
+ case '.':
+ Flags |= PRECISION;
+ break;
+ case '-':
+ Flags |= LEFT_JUSTIFY;
+ break;
+ case '+':
+ Flags |= PREFIX_SIGN;
+ break;
+ case ' ':
+ Flags |= PREFIX_BLANK;
+ break;
+ case ',':
+ Flags |= COMMA_TYPE;
+ break;
+ case 'L':
+ case 'l':
+ Flags |= LONG_TYPE;
+ break;
+ case '*':
+ if ((Flags & PRECISION) == 0) {
+ Flags |= PAD_TO_WIDTH;
+ Width = VA_ARG (Marker, UINTN);
+ } else {
+ Precision = VA_ARG (Marker, UINTN);
+ }
+ break;
+ case '0':
+ if ((Flags & PRECISION) == 0) {
+ Flags |= PREFIX_ZERO;
+ }
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ for (Count = 0; ((FormatCharacter >= '0') && (FormatCharacter <= '9')); ){
+ Count = (Count * 10) + FormatCharacter - '0';
+ Format += BytesPerFormatCharacter;
+ FormatCharacter = (*Format | (*(Format + 1) << 8)) & FormatMask;
+ }
+ Format -= BytesPerFormatCharacter;
+ if ((Flags & PRECISION) == 0) {
+ Flags |= PAD_TO_WIDTH;
+ Width = Count;
+ } else {
+ Precision = Count;
+ }
+ break;
+ default:
+ Done = TRUE;
+ break;
+ }
+ }
+
+ //
+ // Limit the maximum field width to the remaining characters in the output buffer
+ //
+ if (Width > BufferSize) {
+ Width = BufferSize;
+ }
+
+ //
+ // Handle each argument type
+ //
+ switch (FormatCharacter) {
+ case 'X':
+ Flags |= PREFIX_ZERO;
+ //
+ // break skiped on purpose
+ //
+ case 'x':
+ Flags |= RADIX_HEX;
+ //
+ // break skiped on purpose
+ //
+ case 'd':
+ if ((Flags & LONG_TYPE) == 0) {
+ Value = (VA_ARG (Marker, INTN));
+ } else {
+ Value = VA_ARG (Marker, INT64);
+ }
+ if ((Flags & PREFIX_BLANK) != 0) {
+ Prefix = ' ';
+ }
+ if ((Flags & PREFIX_SIGN) != 0) {
+ Prefix = '+';
+ }
+ if ((Flags & COMMA_TYPE) != 0) {
+ Comma = TRUE;
+ }
+ if ((Flags & RADIX_HEX) == 0) {
+ Radix = 10;
+ if (Comma) {
+ Flags &= (~PREFIX_ZERO);
+ Precision = 1;
+ }
+ if (Value < 0) {
+ Flags |= PREFIX_SIGN;
+ Prefix = '-';
+ Value = -Value;
+ }
+ } else {
+ Radix = 16;
+ Comma = FALSE;
+ if ((Flags & LONG_TYPE) == 0 && Value < 0) {
+ Value = (UINTN)Value;
+ }
+ }
+ //
+ // Convert Value to a reversed string
+ //
+ Count = BasePrintLibValueToString (ValueBuffer, Value, Radix);
+ if (Value == 0 && Precision == 0) {
+ Count = 0;
+ }
+ ArgumentString = (CHAR8 *)ValueBuffer + Count;
+ Digits = 3 - (Count % 3);
+ if (Comma && Count != 0) {
+ Count += ((Count - 1) / 3);
+ }
+ if (Prefix != 0) {
+ Count++;
+ }
+ Flags |= ARGUMENT_REVERSED;
+ ZeroPad = TRUE;
+ if ((Flags & PREFIX_ZERO) != 0) {
+ if ((Flags & PAD_TO_WIDTH) != 0) {
+ if ((Flags & PRECISION) == 0) {
+ Precision = Width;
+ }
+ }
+ }
+ break;
+
+ case 's':
+ case 'S':
+ Flags |= ARGUMENT_UNICODE;
+ //
+ // break skipped on purpose
+ //
+ case 'a':
+ ArgumentString = (CHAR8 *)VA_ARG (Marker, CHAR8 *);
+ if (ArgumentString == NULL) {
+ Flags &= (~ARGUMENT_UNICODE);
+ ArgumentString = "<null string>";
+ }
+ break;
+
+ case 'c':
+ Character = VA_ARG (Marker, UINTN) & 0xffff;
+ ArgumentString = (CHAR8 *)&Character;
+ Flags |= ARGUMENT_UNICODE;
+ break;
+
+ case 'g':
+ TmpGuid = VA_ARG (Marker, GUID *);
+ if (TmpGuid == NULL) {
+ ArgumentString = "<null guid>";
+ } else {
+ BasePrintLibSPrint (
+ ValueBuffer,
+ 0,
+ 0,
+ "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
+ TmpGuid->Data1,
+ TmpGuid->Data2,
+ TmpGuid->Data3,
+ TmpGuid->Data4[0],
+ TmpGuid->Data4[1],
+ TmpGuid->Data4[2],
+ TmpGuid->Data4[3],
+ TmpGuid->Data4[4],
+ TmpGuid->Data4[5],
+ TmpGuid->Data4[6],
+ TmpGuid->Data4[7]
+ );
+ ArgumentString = ValueBuffer;
+ }
+ break;
+
+ case 't':
+ TmpTime = VA_ARG (Marker, TIME *);
+ if (TmpTime == NULL) {
+ ArgumentString = "<null time>";
+ } else {
+ BasePrintLibSPrint (
+ ValueBuffer,
+ 0,
+ 0,
+ "%02d/%02d/%04d %02d:%02d",
+ TmpTime->Month,
+ TmpTime->Day,
+ TmpTime->Year,
+ TmpTime->Hour,
+ TmpTime->Minute
+ );
+ ArgumentString = ValueBuffer;
+ }
+ break;
+
+ case 'r':
+ Status = VA_ARG (Marker, RETURN_STATUS);
+ ArgumentString = ValueBuffer;
+ for (Index = 0; StatusString[Index].String != NULL; Index++) {
+ if (Status == StatusString[Index].Status) {
+ ArgumentString = StatusString[Index].String;
+ }
+ }
+ if (ArgumentString == ValueBuffer) {
+ BasePrintLibSPrint ((CHAR8 *) ValueBuffer, 0, 0, "%08X", Status);
+ }
+ break;
+
+ case '%':
+ default:
+ //
+ // if the type is '%' or unknown, then print it to the screen
+ //
+ ArgumentString = (CHAR8 *)&FormatCharacter;
+ Flags |= ARGUMENT_UNICODE;
+ break;
+ }
+ break;
+ case '\n':
+ ArgumentString = "\n";
+
+ break;
+ default:
+ ArgumentString = (CHAR8 *)&FormatCharacter;
+ Flags |= ARGUMENT_UNICODE;
+ break;
+ }
+
+ //
+ // Retrieve the ArgumentString attriubutes
+ //
+ if ((Flags & ARGUMENT_UNICODE) != 0) {
+ ArgumentMask = 0xffff;
+ BytesPerArgumentCharacter = 2;
+ } else {
+ ArgumentMask = 0xff;
+ BytesPerArgumentCharacter = 1;
+ }
+ if ((Flags & ARGUMENT_REVERSED) != 0) {
+ BytesPerArgumentCharacter = -BytesPerArgumentCharacter;
+ } else {
+ //
+ // Compute the number of characters in ArgumentString and store it in Count
+ // ArgumentString is either null-terminated, or it contains Precision characters
+ //
+ for (Count = 0; Count < Precision || ((Flags & PRECISION) == 0); Count++) {
+ ArgumentCharacter = ((ArgumentString[Count * BytesPerArgumentCharacter] & 0xff) | ((ArgumentString[Count * BytesPerArgumentCharacter + 1]) << 8)) & ArgumentMask;
+ if (ArgumentCharacter == 0) {
+ break;
+ }
+ }
+ }
+
+ //
+ // Limit the length of the string to append to the remaining characters in the output buffer
+ //
+ if (Count > BufferSize) {
+ Count = BufferSize;
+ }
+ if (Precision < Count) {
+ Precision = Count;
+ }
+
+ //
+ // Pad before the string
+ //
+ if ((Flags & (PAD_TO_WIDTH | LEFT_JUSTIFY)) == (PAD_TO_WIDTH)) {
+ Buffer = BasePrintLibFillBuffer (Buffer, Width - Precision, ' ', BytesPerOutputCharacter);
+ }
+
+ if (ZeroPad) {
+ if (Prefix != 0) {
+ Buffer = BasePrintLibFillBuffer (Buffer, 1, Prefix, BytesPerOutputCharacter);
+ }
+ Buffer = BasePrintLibFillBuffer (Buffer, Precision - Count, '0', BytesPerOutputCharacter);
+ } else {
+ Buffer = BasePrintLibFillBuffer (Buffer, Precision - Count, ' ', BytesPerOutputCharacter);
+ if (Prefix != 0) {
+ Buffer = BasePrintLibFillBuffer (Buffer, 1, Prefix, BytesPerOutputCharacter);
+ }
+ }
+
+ //
+ // Output the Prefix character if it is present
+ //
+ Index = 0;
+ if (Prefix) {
+ Index++;
+ }
+
+ //
+ // Copy the string into the output buffer performing the required type conversions
+ //
+ while (Index < Count) {
+ ArgumentCharacter = ((*ArgumentString & 0xff) | (*(ArgumentString + 1) << 8)) & ArgumentMask;
+
+ Buffer = BasePrintLibFillBuffer (Buffer, 1, ArgumentCharacter, BytesPerOutputCharacter);
+ ArgumentString += BytesPerArgumentCharacter;
+ Index++;
+ if (Comma) {
+ Digits++;
+ if (Digits == 3) {
+ Digits = 0;
+ Index++;
+ if (Index < Count) {
+ Buffer = BasePrintLibFillBuffer (Buffer, 1, ',', BytesPerOutputCharacter);
+ }
+ }
+ }
+ }
+
+ //
+ // Pad after the string
+ //
+ if ((Flags & (PAD_TO_WIDTH | LEFT_JUSTIFY)) == (PAD_TO_WIDTH | LEFT_JUSTIFY)) {
+ Buffer = BasePrintLibFillBuffer (Buffer, Width - Precision, ' ', BytesPerOutputCharacter);
+ }
+
+ //
+ // Reduce the number of characters
+ //
+ BufferSize -= Count;
+
+ //
+ // Get the next character from the format string
+ //
+ Format += BytesPerFormatCharacter;
+
+ //
+ // Get the next character from the format string
+ //
+ FormatCharacter = (*Format | (*(Format + 1) << 8)) & FormatMask;
+ }
+
+ //
+ // Null terminate the Unicode or ASCII string
+ //
+ Buffer = BasePrintLibFillBuffer (Buffer, 1, 0, BytesPerOutputCharacter);
+
+ return ((Buffer - OriginalBuffer) / BytesPerOutputCharacter);
+}
+
+UINTN
+BasePrintLibSPrint (
+ OUT CHAR8 *StartOfBuffer,
+ IN UINTN BufferSize,
+ IN UINTN Flags,
+ IN CONST CHAR8 *FormatString,
+ ...
+ )
+{
+ VA_LIST Marker;
+
+ VA_START (Marker, FormatString);
+ return BasePrintLibVSPrint (StartOfBuffer, BufferSize, Flags, FormatString, Marker);
+}
+
+UINTN
+EFIAPI
+UnicodeVSPrint (
+ OUT CHAR16 *StartOfBuffer,
+ IN UINTN BufferSize,
+ IN CONST CHAR16 *FormatString,
+ IN VA_LIST Marker
+ )
+{
+ return BasePrintLibVSPrint ((CHAR8 *)StartOfBuffer, BufferSize >> 1, FORMAT_UNICODE | OUTPUT_UNICODE, (CHAR8 *)FormatString, Marker);
+}
+
+UINTN
+EFIAPI
+UnicodeSPrint (
+ OUT CHAR16 *StartOfBuffer,
+ IN UINTN BufferSize,
+ IN CONST CHAR16 *FormatString,
+ ...
+ )
+{
+ VA_LIST Marker;
+
+ VA_START (Marker, FormatString);
+ return UnicodeVSPrint (StartOfBuffer, BufferSize, FormatString, Marker);
+}
+
+UINTN
+EFIAPI
+UnicodeVSPrintAsciiFormat (
+ OUT CHAR16 *StartOfBuffer,
+ IN UINTN BufferSize,
+ IN CONST CHAR8 *FormatString,
+ IN VA_LIST Marker
+ )
+{
+ return BasePrintLibVSPrint ((CHAR8 *)StartOfBuffer, BufferSize >> 1, OUTPUT_UNICODE,FormatString, Marker);
+}
+
+UINTN
+EFIAPI
+UnicodeSPrintAsciiFormat (
+ OUT CHAR16 *StartOfBuffer,
+ IN UINTN BufferSize,
+ IN CONST CHAR8 *FormatString,
+ ...
+ )
+{
+ VA_LIST Marker;
+
+ VA_START (Marker, FormatString);
+ return UnicodeVSPrintAsciiFormat (StartOfBuffer, BufferSize >> 1, FormatString, Marker);
+}
+
+UINTN
+EFIAPI
+AsciiVSPrint (
+ OUT CHAR8 *StartOfBuffer,
+ IN UINTN BufferSize,
+ IN CONST CHAR8 *FormatString,
+ IN VA_LIST Marker
+ )
+{
+ return BasePrintLibVSPrint (StartOfBuffer, BufferSize, 0, FormatString, Marker);
+}
+
+UINTN
+EFIAPI
+AsciiSPrint (
+ OUT CHAR8 *StartOfBuffer,
+ IN UINTN BufferSize,
+ IN CONST CHAR8 *FormatString,
+ ...
+ )
+{
+ VA_LIST Marker;
+
+ VA_START (Marker, FormatString);
+ return AsciiVSPrint (StartOfBuffer, BufferSize, FormatString, Marker);
+}
+
+UINTN
+EFIAPI
+AsciiVSPrintUnicodeFormat (
+ OUT CHAR8 *StartOfBuffer,
+ IN UINTN BufferSize,
+ IN CONST CHAR16 *FormatString,
+ IN VA_LIST Marker
+ )
+{
+ return BasePrintLibVSPrint (StartOfBuffer, BufferSize, FORMAT_UNICODE, (CHAR8 *)FormatString, Marker);
+}
+
+UINTN
+EFIAPI
+AsciiSPrintUnicodeFormat (
+ OUT CHAR8 *StartOfBuffer,
+ IN UINTN BufferSize,
+ IN CONST CHAR16 *FormatString,
+ ...
+ )
+{
+ VA_LIST Marker;
+
+ VA_START (Marker, FormatString);
+ return AsciiVSPrintUnicodeFormat (StartOfBuffer, BufferSize, FormatString, Marker);
+}
+
+UINTN
+EFIAPI
+UnicodeValueToString (
+ IN OUT CHAR16 *Buffer,
+ IN UINTN Flags,
+ IN INT64 Value,
+ IN UINTN Width
+ )
+{
+ return BasePrintLibConvertValueToString ((CHAR8 *)Buffer, Flags, Value, Width, 2);
+}
+
+UINTN
+EFIAPI
+AsciiValueToString (
+ IN OUT CHAR8 *Buffer,
+ IN UINTN Flags,
+ IN INT64 Value,
+ IN UINTN Width
+ )
+{
+ return BasePrintLibConvertValueToString ((CHAR8 *)Buffer, Flags, Value, Width, 1);
+}
diff --git a/Source/String/PrintLibInternal.c b/Source/String/PrintLibInternal.c
new file mode 100644
index 0000000..63d0c71
--- /dev/null
+++ b/Source/String/PrintLibInternal.c
@@ -0,0 +1,142 @@
+/*++
+
+Copyright (c) 2004-2006 Intel Corporation. All rights reserved
+This program and the accompanying materials are licensed and made available
+under the terms and conditions of the BSD License which accompanies this
+distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+
+Module Name:
+
+ PrintLibInternal.c
+
+Abstract:
+
+ Print Library worker functions.
+
+--*/
+
+#include <Common/UefiBaseTypes.h>
+#include <Library/PrintLib.h>
+
+#include "CommonLib.h"
+#include "PrintLibInternal.h"
+
+static CONST CHAR8 mHexStr[] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
+
+CHAR8 *
+BasePrintLibFillBuffer (
+ CHAR8 *Buffer,
+ INTN Length,
+ UINTN Character,
+ INTN Increment
+ )
+{
+ INTN Index;
+
+ for (Index = 0; Index < Length; Index++) {
+ *Buffer = (CHAR8) Character;
+ *(Buffer + 1) = (CHAR8) (Character >> 8);
+ Buffer += Increment;
+ }
+ return Buffer;
+}
+
+/**
+ Print worker function that prints a Value as a decimal number in Buffer.
+
+ @param Buffer Location to place the Unicode or ASCII string of Value.
+
+ @param Value Value to convert to a Decimal or Hexidecimal string in Buffer.
+
+ @param Flags Flags to use in printing string, see file header for details.
+
+ @param Precision Minimum number of digits to return in the ASCII string
+
+ @return Number of characters printed.
+
+**/
+UINTN
+EFIAPI
+BasePrintLibValueToString (
+ IN OUT CHAR8 *Buffer,
+ IN INT64 Value,
+ IN UINTN Radix
+ )
+{
+ UINTN Digits;
+ UINT32 Remainder;
+
+ //
+ // Loop to convert one digit at a time in reverse order
+ //
+ *(Buffer++) = 0;
+ Digits = 0;
+ do {
+ // Value = (INT64)DivU64x32Remainder ((UINT64)Value, (UINT32)Radix, &Remainder);
+ Remainder = (UINT64)Value % (UINT32)Radix;
+ Value = (UINT64)Value / (UINT32)Radix;
+ *(Buffer++) = mHexStr[Remainder];
+ Digits++;
+ } while (Value != 0);
+ return Digits;
+}
+
+UINTN
+BasePrintLibConvertValueToString (
+ IN OUT CHAR8 *Buffer,
+ IN UINTN Flags,
+ IN INT64 Value,
+ IN UINTN Width,
+ IN UINTN Increment
+ )
+{
+ CHAR8 *OriginalBuffer;
+ CHAR8 ValueBuffer[MAXIMUM_VALUE_CHARACTERS];
+ UINTN Count;
+ UINTN Digits;
+ UINTN Index;
+
+ OriginalBuffer = Buffer;
+
+ if (Width == 0 || (Flags & COMMA_TYPE) != 0) {
+ Flags &= (~PREFIX_ZERO);
+ }
+
+ if (Width == 0 || Width > (MAXIMUM_VALUE_CHARACTERS - 1)) {
+ Width = MAXIMUM_VALUE_CHARACTERS - 1;
+ }
+
+ if (Value < 0) {
+ Value = -Value;
+ Buffer = BasePrintLibFillBuffer (Buffer, 1, '-', Increment);
+ }
+
+ Count = BasePrintLibValueToString (ValueBuffer, Value, 10);
+
+ if ((Flags & PREFIX_ZERO) != 0) {
+ Buffer = BasePrintLibFillBuffer (Buffer, Width - Count, '0', Increment);
+ }
+
+ Digits = 3 - (Count % 3);
+ for (Index = 0; Index < Count; Index++) {
+ Buffer = BasePrintLibFillBuffer (Buffer, 1, ValueBuffer[Count - Index], Increment);
+ if ((Flags & COMMA_TYPE) != 0) {
+ Digits++;
+ if (Digits == 3) {
+ Digits = 0;
+ if ((Index + 1) < Count) {
+ Buffer = BasePrintLibFillBuffer (Buffer, 1, ',', Increment);
+ }
+ }
+ }
+ }
+
+ Buffer = BasePrintLibFillBuffer (Buffer, 1, 0, Increment);
+
+ return ((Buffer - OriginalBuffer) / Increment);
+}
diff --git a/Source/String/PrintLibInternal.h b/Source/String/PrintLibInternal.h
new file mode 100644
index 0000000..87f0955e
--- /dev/null
+++ b/Source/String/PrintLibInternal.h
@@ -0,0 +1,101 @@
+/*++
+
+Copyright (c) 2004-2006 Intel Corporation. All rights reserved
+This program and the accompanying materials are licensed and made available
+under the terms and conditions of the BSD License which accompanies this
+distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+
+Module Name:
+
+ PrintLibInternal.h
+
+Abstract:
+
+ Print Library.
+
+--*/
+
+
+
+//
+// Print primitives
+//
+//#define LEFT_JUSTIFY 0x01
+#define PREFIX_SIGN 0x02
+#define PREFIX_BLANK 0x04
+//#define COMMA_TYPE 0x08
+#define LONG_TYPE 0x10
+//#define PREFIX_ZERO 0x20
+#define OUTPUT_UNICODE 0x40
+#define RADIX_HEX 0x80
+#define FORMAT_UNICODE 0x100
+#define PAD_TO_WIDTH 0x200
+#define ARGUMENT_UNICODE 0x400
+#define PRECISION 0x800
+#define ARGUMENT_REVERSED 0x1000
+
+///
+/// Define the maximum number of characters that are required to encode
+/// a decimal, hexidecimal, GUID, or TIME value with a Nll terminator.
+/// Maximum Length Decimal String = 28 "-9,223,372,036,854,775,808"
+/// Maximum Length Hexidecimal String = 17 "FFFFFFFFFFFFFFFF"
+/// Maximum Length GUID = 37 "00000000-0000-0000-0000-000000000000"
+/// Maximum Length TIME = 18 "12/12/2006 12:12"
+///
+#define MAXIMUM_VALUE_CHARACTERS 38
+
+//
+//
+//
+typedef struct {
+ UINT16 Year;
+ UINT8 Month;
+ UINT8 Day;
+ UINT8 Hour;
+ UINT8 Minute;
+ UINT8 Second;
+ UINT8 Pad1;
+ UINT32 Nanosecond;
+ INT16 TimeZone;
+ UINT8 Daylight;
+ UINT8 Pad2;
+} TIME;
+
+UINTN
+BasePrintLibSPrint (
+ OUT CHAR8 *Buffer,
+ IN UINTN BufferSize,
+ IN UINTN Flags,
+ IN CONST CHAR8 *FormatString,
+ ...
+ );
+
+CHAR8 *
+BasePrintLibFillBuffer (
+ CHAR8 *Buffer,
+ INTN Length,
+ UINTN Character,
+ INTN Increment
+ );
+
+UINTN
+EFIAPI
+BasePrintLibValueToString (
+ IN OUT CHAR8 *Buffer,
+ IN INT64 Value,
+ IN UINTN Radix
+ );
+
+UINTN
+BasePrintLibConvertValueToString (
+ IN OUT CHAR8 *Buffer,
+ IN UINTN Flags,
+ IN INT64 Value,
+ IN UINTN Width,
+ IN UINTN Increment
+ );
diff --git a/Source/String/String.c b/Source/String/String.c
new file mode 100644
index 0000000..78d0a59
--- /dev/null
+++ b/Source/String/String.c
@@ -0,0 +1,732 @@
+/*++
+
+Copyright (c) 2004-2006 Intel Corporation. All rights reserved
+This program and the accompanying materials are licensed and made available
+under the terms and conditions of the BSD License which accompanies this
+distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+
+Module Name:
+
+ String.c
+
+Abstract:
+
+ Unicode and ASCII string primatives.
+
+--*/
+
+#include <assert.h>
+
+#include <Common/UefiBaseTypes.h>
+
+#include <string.h>
+
+#include "CommonLib.h"
+
+/**
+ Returns the length of a Null-terminated Unicode string.
+
+ This function returns the number of Unicode characters in the Null-terminated
+ Unicode string specified by String.
+
+ If String is NULL, then ASSERT().
+
+ @param String Pointer to a Null-terminated Unicode string.
+
+ @return The length of String.
+
+**/
+UINTN
+EFIAPI
+StrLen (
+ IN CONST CHAR16 *String
+ )
+{
+ UINTN Length;
+
+ ASSERT (String != NULL);
+
+ for (Length = 0; *String != L'\0'; String++, Length++) {
+ ;
+ }
+ return Length;
+}
+
+/**
+ Returns the length of a Null-terminated ASCII string.
+
+ This function returns the number of ASCII characters in the Null-terminated
+ ASCII string specified by String.
+
+ If String is NULL, then ASSERT().
+
+ @param String Pointer to a Null-terminated ASCII string.
+
+ @return The length of String.
+
+**/
+UINTN
+EFIAPI
+AsciiStrLen (
+ IN CONST CHAR8 *String
+ )
+{
+ UINTN Length;
+
+ ASSERT (String != NULL);
+
+ for (Length = 0; *String != '\0'; String++, Length++) {
+ ;
+ }
+ return Length;
+}
+
+/**
+ Copies one Null-terminated Unicode string to another Null-terminated Unicode
+ string and returns the new Unicode string.
+
+ This function copies the contents of the Unicode string Source to the Unicode
+ string Destination, and returns Destination. If Source and Destination
+ overlap, then the results are undefined.
+
+ If Destination is NULL, then ASSERT().
+ If Source is NULL, then ASSERT().
+ If Source and Destination overlap, then ASSERT().
+
+ @param Destination Pointer to a Null-terminated Unicode string.
+ @param Source Pointer to a Null-terminated Unicode string.
+
+ @return Destiantion
+
+**/
+CHAR16 *
+EFIAPI
+StrCpy (
+ OUT CHAR16 *Destination,
+ IN CONST CHAR16 *Source
+ )
+{
+ CHAR16 *ReturnValue;
+
+ //
+ // Destination cannot be NULL
+ //
+ ASSERT (Destination != NULL);
+
+ //
+ // Destination and source cannot overlap
+ //
+ ASSERT ((UINTN)(Destination - Source) > StrLen (Source));
+ ASSERT ((UINTN)(Source - Destination) > StrLen (Source));
+
+ ReturnValue = Destination;
+ while (*Source) {
+ *(Destination++) = *(Source++);
+ }
+ *Destination = 0;
+ return ReturnValue;
+}
+
+/**
+ Copies one Null-terminated Unicode string with a maximum length to another
+ Null-terminated Unicode string with a maximum length and returns the new
+ Unicode string.
+
+ This function copies the contents of the Unicode string Source to the Unicode
+ string Destination, and returns Destination. At most, Length Unicode
+ characters are copied from Source to Destination. If Length is 0, then
+ Destination is returned unmodified. If Length is greater that the number of
+ Unicode characters in Source, then Destination is padded with Null Unicode
+ characters. If Source and Destination overlap, then the results are
+ undefined.
+
+ If Destination is NULL, then ASSERT().
+ If Source is NULL, then ASSERT().
+ If Source and Destination overlap, then ASSERT().
+
+ @param Destination Pointer to a Null-terminated Unicode string.
+ @param Source Pointer to a Null-terminated Unicode string.
+ @param Length Maximum number of Unicode characters to copy.
+
+ @return Destination
+
+**/
+CHAR16 *
+EFIAPI
+StrnCpy (
+ OUT CHAR16 *Destination,
+ IN CONST CHAR16 *Source,
+ IN UINTN Length
+ )
+{
+ CHAR16 *ReturnValue;
+
+ if (Length == 0) {
+ return Destination;
+ }
+
+ //
+ // Destination cannot be NULL if Length is not zero
+ //
+ ASSERT (Destination != NULL);
+
+ //
+ // Destination and source cannot overlap
+ // Q: Does Source have to be NULL-terminated?
+ //
+ ASSERT ((UINTN)(Destination - Source) > StrLen (Source));
+ ASSERT ((UINTN)(Source - Destination) >= Length);
+
+ ReturnValue = Destination;
+
+ while ((*Source != L'\0') && (Length > 0)) {
+ *(Destination++) = *(Source++);
+ Length--;
+ }
+
+ memset (Destination, 0, Length * sizeof (*Destination));
+ return ReturnValue;
+}
+
+/**
+ Returns the size of a Null-terminated Unicode string in bytes, including the
+ Null terminator.
+
+ This function returns the size, in bytes, of the Null-terminated Unicode
+ string specified by String.
+
+ If String is NULL, then ASSERT().
+
+ @param String Pointer to a Null-terminated Unicode string.
+
+ @return The size of String.
+
+**/
+UINTN
+EFIAPI
+StrSize (
+ IN CONST CHAR16 *String
+ )
+{
+ return (StrLen (String) + 1) * sizeof (*String);
+}
+
+/**
+ Compares two Null-terminated Unicode strings, and returns the difference
+ between the first mismatched Unicode characters.
+
+ This function compares the Null-terminated Unicode string FirstString to the
+ Null-terminated Unicode string SecondString. If FirstString is identical to
+ SecondString, then 0 is returned. Otherwise, the value returned is the first
+ mismatched Unicode character in SecondString subtracted from the first
+ mismatched Unicode character in FirstString.
+
+ If FirstString is NULL, then ASSERT().
+ If SecondString is NULL, then ASSERT().
+
+ @param FirstString Pointer to a Null-terminated Unicode string.
+ @param SecondString Pointer to a Null-terminated Unicode string.
+
+ @retval 0 FirstString is identical to SecondString.
+ @retval !=0 FirstString is not identical to SecondString.
+
+**/
+INTN
+EFIAPI
+StrCmp (
+ IN CONST CHAR16 *FirstString,
+ IN CONST CHAR16 *SecondString
+ )
+{
+ //
+ // ASSERT both strings should never be zero
+ //
+ ASSERT (StrSize (FirstString) != 0);
+ ASSERT (StrSize (SecondString) != 0);
+
+ while ((*FirstString != L'\0') && (*FirstString == *SecondString)) {
+ FirstString++;
+ SecondString++;
+ }
+ return *FirstString - *SecondString;
+}
+
+/**
+ Compares two Null-terminated Unicode strings with maximum lengths, and
+ returns the difference between the first mismatched Unicode characters.
+
+ This function compares the Null-terminated Unicode string FirstString to the
+ Null-terminated Unicode string SecondString. At most, Length Unicode
+ characters will be compared. If Length is 0, then 0 is returned. If
+ FirstString is identical to SecondString, then 0 is returned. Otherwise, the
+ value returned is the first mismatched Unicode character in SecondString
+ subtracted from the first mismatched Unicode character in FirstString.
+
+ If FirstString is NULL, then ASSERT().
+ If SecondString is NULL, then ASSERT().
+
+ @param FirstString Pointer to a Null-terminated Unicode string.
+ @param SecondString Pointer to a Null-terminated Unicode string.
+ @param Length Maximum number of Unicode characters to compare.
+
+ @retval 0 FirstString is identical to SecondString.
+ @retval !=0 FirstString is not identical to SecondString.
+
+**/
+INTN
+EFIAPI
+StrnCmp (
+ IN CONST CHAR16 *FirstString,
+ IN CONST CHAR16 *SecondString,
+ IN UINTN Length
+ )
+{
+ if (Length == 0) {
+ return 0;
+ }
+
+ //
+ // ASSERT both strings should never be zero
+ //
+ ASSERT (StrSize (FirstString) != 0);
+ ASSERT (StrSize (SecondString) != 0);
+
+ while ((*FirstString != L'\0') &&
+ (*FirstString == *SecondString) &&
+ (Length > 1)) {
+ FirstString++;
+ SecondString++;
+ Length--;
+ }
+
+ return *FirstString - *SecondString;
+}
+
+/**
+ Concatenates one Null-terminated Unicode string to another Null-terminated
+ Unicode string, and returns the concatenated Unicode string.
+
+ This function concatenates two Null-terminated Unicode strings. The contents
+ of Null-terminated Unicode string Source are concatenated to the end of
+ Null-terminated Unicode string Destination. The Null-terminated concatenated
+ Unicode String is returned. If Source and Destination overlap, then the
+ results are undefined.
+
+ If Destination is NULL, then ASSERT().
+ If Source is NULL, then ASSERT().
+ If Source and Destination overlap, then ASSERT().
+
+ @param Destination Pointer to a Null-terminated Unicode string.
+ @param Source Pointer to a Null-terminated Unicode string.
+
+ @return Destination
+
+**/
+CHAR16 *
+EFIAPI
+StrCat (
+ IN OUT CHAR16 *Destination,
+ IN CONST CHAR16 *Source
+ )
+{
+ StrCpy (Destination + StrLen (Destination), Source);
+
+ //
+ // Size of the resulting string should never be zero.
+ //
+ ASSERT (StrSize (Destination) != 0);
+ return Destination;
+}
+
+/**
+ Concatenates one Null-terminated Unicode string with a maximum length to the
+ end of another Null-terminated Unicode string, and returns the concatenated
+ Unicode string.
+
+ This function concatenates two Null-terminated Unicode strings. The contents
+ of Null-terminated Unicode string Source are concatenated to the end of
+ Null-terminated Unicode string Destination, and Destination is returned. At
+ most, Length Unicode characters are concatenated from Source to the end of
+ Destination, and Destination is always Null-terminated. If Length is 0, then
+ Destination is returned unmodified. If Source and Destination overlap, then
+ the results are undefined.
+
+ If Destination is NULL, then ASSERT().
+ If Source is NULL, then ASSERT().
+ If Source and Destination overlap, then ASSERT().
+
+ @param Destination Pointer to a Null-terminated Unicode string.
+ @param Source Pointer to a Null-terminated Unicode string.
+ @param Length Maximum number of Unicode characters to concatenate from
+ Source.
+
+ @return Destination
+
+**/
+CHAR16 *
+EFIAPI
+StrnCat (
+ IN OUT CHAR16 *Destination,
+ IN CONST CHAR16 *Source,
+ IN UINTN Length
+ )
+{
+ StrnCpy (Destination + StrLen (Destination), Source, Length);
+
+ //
+ // Size of the resulting string should never be zero.
+ //
+ ASSERT (StrSize (Destination) != 0);
+ return Destination;
+}
+
+/**
+ Copies one Null-terminated ASCII string to another Null-terminated ASCII
+ string and returns the new ASCII string.
+
+ This function copies the contents of the ASCII string Source to the ASCII
+ string Destination, and returns Destination. If Source and Destination
+ overlap, then the results are undefined.
+
+ If Destination is NULL, then ASSERT().
+ If Source is NULL, then ASSERT().
+ If Source and Destination overlap, then ASSERT().
+
+ @param Destination Pointer to a Null-terminated ASCII string.
+ @param Source Pointer to a Null-terminated ASCII string.
+
+ @return Destination
+
+**/
+CHAR8 *
+EFIAPI
+AsciiStrCpy (
+ OUT CHAR8 *Destination,
+ IN CONST CHAR8 *Source
+ )
+{
+ CHAR8 *ReturnValue;
+
+ //
+ // Destination cannot be NULL
+ //
+ ASSERT (Destination != NULL);
+
+ //
+ // Destination and source cannot overlap
+ //
+ ASSERT ((UINTN)(Destination - Source) > AsciiStrLen (Source));
+ ASSERT ((UINTN)(Source - Destination) > AsciiStrLen (Source));
+
+ ReturnValue = Destination;
+ while (*Source) {
+ *(Destination++) = *(Source++);
+ }
+ *Destination = 0;
+ return ReturnValue;
+}
+
+/**
+ Copies one Null-terminated ASCII string with a maximum length to another
+ Null-terminated ASCII string with a maximum length and returns the new ASCII
+ string.
+
+ This function copies the contents of the ASCII string Source to the ASCII
+ string Destination, and returns Destination. At most, Length ASCII characters
+ are copied from Source to Destination. If Length is 0, then Destination is
+ returned unmodified. If Length is greater that the number of ASCII characters
+ in Source, then Destination is padded with Null ASCII characters. If Source
+ and Destination overlap, then the results are undefined.
+
+ If Destination is NULL, then ASSERT().
+ If Source is NULL, then ASSERT().
+ If Source and Destination overlap, then ASSERT().
+
+ @param Destination Pointer to a Null-terminated ASCII string.
+ @param Source Pointer to a Null-terminated ASCII string.
+ @param Length Maximum number of ASCII characters to copy.
+
+ @return Destination
+
+**/
+CHAR8 *
+EFIAPI
+AsciiStrnCpy (
+ OUT CHAR8 *Destination,
+ IN CONST CHAR8 *Source,
+ IN UINTN Length
+ )
+{
+ CHAR8 *ReturnValue;
+
+ if (Length == 0) {
+ return Destination;
+ }
+
+ //
+ // Destination cannot be NULL
+ //
+ ASSERT (Destination != NULL);
+
+ //
+ // Destination and source cannot overlap
+ //
+ ASSERT ((UINTN)(Destination - Source) > AsciiStrLen (Source));
+ ASSERT ((UINTN)(Source - Destination) >= Length);
+
+ ReturnValue = Destination;
+
+ while (*Source && Length > 0) {
+ *(Destination++) = *(Source++);
+ Length--;
+ }
+
+ // ZeroMem (Destination, Length * sizeof (*Destination));
+ memset (Destination, 0, Length * sizeof (*Destination));
+ return ReturnValue;
+}
+
+/**
+ Returns the size of a Null-terminated ASCII string in bytes, including the
+ Null terminator.
+
+ This function returns the size, in bytes, of the Null-terminated ASCII string
+ specified by String.
+
+ If String is NULL, then ASSERT().
+
+ @param String Pointer to a Null-terminated ASCII string.
+
+ @return The size of String.
+
+**/
+UINTN
+EFIAPI
+AsciiStrSize (
+ IN CONST CHAR8 *String
+ )
+{
+ return (AsciiStrLen (String) + 1) * sizeof (*String);
+}
+
+/**
+ Compares two Null-terminated ASCII strings, and returns the difference
+ between the first mismatched ASCII characters.
+
+ This function compares the Null-terminated ASCII string FirstString to the
+ Null-terminated ASCII string SecondString. If FirstString is identical to
+ SecondString, then 0 is returned. Otherwise, the value returned is the first
+ mismatched ASCII character in SecondString subtracted from the first
+ mismatched ASCII character in FirstString.
+
+ If FirstString is NULL, then ASSERT().
+ If SecondString is NULL, then ASSERT().
+
+ @param FirstString Pointer to a Null-terminated ASCII string.
+ @param SecondString Pointer to a Null-terminated ASCII string.
+
+ @retval 0 FirstString is identical to SecondString.
+ @retval !=0 FirstString is not identical to SecondString.
+
+**/
+INTN
+EFIAPI
+AsciiStrCmp (
+ IN CONST CHAR8 *FirstString,
+ IN CONST CHAR8 *SecondString
+ )
+{
+ //
+ // ASSERT both strings should never be zero
+ //
+ ASSERT (AsciiStrSize (FirstString));
+ ASSERT (AsciiStrSize (SecondString));
+
+ while ((*FirstString != '\0') && (*FirstString == *SecondString)) {
+ FirstString++;
+ SecondString++;
+ }
+
+ return *FirstString - *SecondString;
+}
+
+STATIC
+CHAR8
+EFIAPI
+AsciiToUpper (
+ IN CHAR8 Chr
+ )
+{
+ return (Chr >= 'a' && Chr <= 'z') ? Chr - ('a' - 'A') : Chr;
+}
+
+/**
+ Performs a case insensitive comparison of two Null-terminated ASCII strings,
+ and returns the difference between the first mismatched ASCII characters.
+
+ This function performs a case insensitive comparison of the Null-terminated
+ ASCII string FirstString to the Null-terminated ASCII string SecondString. If
+ FirstString is identical to SecondString, then 0 is returned. Otherwise, the
+ value returned is the first mismatched lower case ASCII character in
+ SecondString subtracted from the first mismatched lower case ASCII character
+ in FirstString.
+
+ If FirstString is NULL, then ASSERT().
+ If SecondString is NULL, then ASSERT().
+
+ @param FirstString Pointer to a Null-terminated ASCII string.
+ @param SecondString Pointer to a Null-terminated ASCII string.
+
+ @retval 0 FirstString is identical to SecondString using case insensitive
+ comparisons.
+ @retval !=0 FirstString is not identical to SecondString using case
+ insensitive comparisons.
+
+**/
+INTN
+EFIAPI
+AsciiStriCmp (
+ IN CONST CHAR8 *FirstString,
+ IN CONST CHAR8 *SecondString
+ )
+{
+ //
+ // ASSERT both strings should never be zero
+ //
+ ASSERT (AsciiStrSize (FirstString));
+ ASSERT (AsciiStrSize (SecondString));
+
+ while ((*FirstString != '\0') &&
+ (AsciiToUpper (*FirstString) == AsciiToUpper (*SecondString))) {
+ FirstString++;
+ SecondString++;
+ }
+
+ return AsciiToUpper (*FirstString) - AsciiToUpper (*SecondString);
+}
+
+/**
+ Compares two Null-terminated ASCII strings with maximum lengths, and returns
+ the difference between the first mismatched ASCII characters.
+
+ This function compares the Null-terminated ASCII string FirstString to the
+ Null-terminated ASCII string SecondString. At most, Length ASCII characters
+ will be compared. If Length is 0, then 0 is returned. If FirstString is
+ identical to SecondString, then 0 is returned. Otherwise, the value returned
+ is the first mismatched ASCII character in SecondString subtracted from the
+ first mismatched ASCII character in FirstString.
+
+ If FirstString is NULL, then ASSERT().
+ If SecondString is NULL, then ASSERT().
+
+ @param FirstString Pointer to a Null-terminated ASCII string.
+ @param SecondString Pointer to a Null-terminated ASCII string.
+
+ @retval 0 FirstString is identical to SecondString.
+ @retval !=0 FirstString is not identical to SecondString.
+
+**/
+INTN
+EFIAPI
+AsciiStrnCmp (
+ IN CONST CHAR8 *FirstString,
+ IN CONST CHAR8 *SecondString,
+ IN UINTN Length
+ )
+{
+ //
+ // ASSERT both strings should never be zero
+ //
+ ASSERT (AsciiStrSize (FirstString));
+ ASSERT (AsciiStrSize (SecondString));
+
+ while ((*FirstString != '\0') &&
+ (*FirstString == *SecondString) &&
+ (Length > 1)) {
+ FirstString++;
+ SecondString++;
+ Length--;
+ }
+ return *FirstString - *SecondString;
+}
+
+/**
+ Concatenates one Null-terminated ASCII string to another Null-terminated
+ ASCII string, and returns the concatenated ASCII string.
+
+ This function concatenates two Null-terminated ASCII strings. The contents of
+ Null-terminated ASCII string Source are concatenated to the end of Null-
+ terminated ASCII string Destination. The Null-terminated concatenated ASCII
+ String is returned.
+
+ If Destination is NULL, then ASSERT().
+ If Source is NULL, then ASSERT().
+
+ @param Destination Pointer to a Null-terminated ASCII string.
+ @param Source Pointer to a Null-terminated ASCII string.
+
+ @return Destination
+
+**/
+CHAR8 *
+EFIAPI
+AsciiStrCat (
+ IN OUT CHAR8 *Destination,
+ IN CONST CHAR8 *Source
+ )
+{
+ AsciiStrCpy (Destination + AsciiStrLen (Destination), Source);
+
+ //
+ // Size of the resulting string should never be zero.
+ //
+ ASSERT (AsciiStrSize (Destination) != 0);
+ return Destination;
+}
+
+/**
+ Concatenates one Null-terminated ASCII string with a maximum length to the
+ end of another Null-terminated ASCII string, and returns the concatenated
+ ASCII string.
+
+ This function concatenates two Null-terminated ASCII strings. The contents
+ of Null-terminated ASCII string Source are concatenated to the end of Null-
+ terminated ASCII string Destination, and Destination is returned. At most,
+ Length ASCII characters are concatenated from Source to the end of
+ Destination, and Destination is always Null-terminated. If Length is 0, then
+ Destination is returned unmodified. If Source and Destination overlap, then
+ the results are undefined.
+
+ If Destination is NULL, then ASSERT().
+ If Source is NULL, then ASSERT().
+ If Source and Destination overlap, then ASSERT().
+
+ @param Destination Pointer to a Null-terminated ASCII string.
+ @param Source Pointer to a Null-terminated ASCII string.
+ @param Length Maximum number of ASCII characters to concatenate from
+ Source.
+
+ @return Destination
+
+**/
+CHAR8 *
+EFIAPI
+AsciiStrnCat (
+ IN OUT CHAR8 *Destination,
+ IN CONST CHAR8 *Source,
+ IN UINTN Length
+ )
+{
+ AsciiStrnCpy (Destination + AsciiStrLen (Destination), Source, Length);
+
+ //
+ // Size of the resulting string should never be zero.
+ //
+ ASSERT (AsciiStrSize (Destination) != 0);
+ return Destination;
+}
diff --git a/Source/String/build.xml b/Source/String/build.xml
new file mode 100644
index 0000000..b42504e
--- /dev/null
+++ b/Source/String/build.xml
@@ -0,0 +1,94 @@
+<?xml version="1.0" ?>
+<!--
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+-->
+<project default="GenTool" basedir=".">
+<!--
+ EDK String
+ Copyright (c) 2006, Intel Corporation
+-->
+ <taskdef resource="net/sf/antcontrib/antlib.xml"/>
+
+ <property name="LibName" value="String"/>
+ <property name="LINK_OUTPUT_TYPE" value="static"/>
+ <property name="BUILD_DIR" value="${PACKAGE_DIR}/${LibName}/tmp"/>
+
+ <target name="GenTool" depends="init, String">
+ <echo message="The EDK Library: ${LibName} build has completed!"/>
+ </target>
+
+ <target name="init">
+ <echo message="Building the EDK Library: ${LibName}"/>
+ <mkdir dir="${BUILD_DIR}"/>
+
+ <condition property="syslibdirs" value="">
+ <os family="mac"/>
+ </condition>
+
+ <condition property="syslibs" value="">
+ <os family="mac"/>
+ </condition>
+
+ <condition property="syslibdirs" value="${env.CYGWIN_HOME}/lib/e2fsprogs">
+ <os family="windows"/>
+ </condition>
+
+ <condition property="syslibs" value="uuid">
+ <os family="windows"/>
+ </condition>
+
+ <condition property="syslibdirs" value="/usr/lib">
+ <os name="Linux"/>
+ </condition>
+
+ <condition property="syslibs" value="uuid">
+ <os name="Linux"/>
+ </condition>
+
+ </target>
+
+ <target name="String" depends="init">
+ <cc name="${ToolChain}" objdir="${BUILD_DIR}"
+ outfile="${LIB_DIR}/${LibName}"
+ outtype="static"
+ debug="true"
+ optimize="speed">
+ <compilerarg value="${ExtraArgus}" if="ExtraArgus" />
+ <compilerarg value="-fshort-wchar" if="gcc"/>
+
+ <fileset dir="${basedir}/${LibName}"
+ includes="*.c" />
+
+ <includepath path="${PACKAGE_DIR}/${LibName}"/>
+ <includepath path="${PACKAGE_DIR}/Include"/>
+ <includepath path="${PACKAGE_DIR}/Include/${HostArch}"/>
+ <includepath path="${PACKAGE_DIR}/Common"/>
+ </cc>
+ </target>
+
+
+ <target name="clean">
+ <echo message="Removing Intermediate Files Only"/>
+ <delete>
+ <fileset dir="${BUILD_DIR}" includes="*.obj"/>
+ </delete>
+ </target>
+
+ <target name="cleanall">
+ <echo message="Removing Object Files and the Library: ${LibName}${ext_static}"/>
+ <delete dir="${PACKAGE_DIR}/${LibName}/tmp">
+ </delete>
+ <delete failonerror="false" quiet="true" includeEmptyDirs="true">
+ <fileset dir="${BUILD_DIR}"/>
+ <fileset file="${LIB_DIR}/${LibName}${ext_static}"/>
+ </delete>
+ </target>
+
+</project>
diff --git a/Source/Strip/Strip.c b/Source/Strip/Strip.c
new file mode 100644
index 0000000..bccdffb
--- /dev/null
+++ b/Source/Strip/Strip.c
@@ -0,0 +1,105 @@
+/*++
+
+Copyright (c) 2004-2006 Intel Corporation. All rights reserved
+This program and the accompanying materials are licensed and made available
+under the terms and conditions of the BSD License which accompanies this
+distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+
+Module Name:
+
+ Strip.c
+
+Abstract:
+
+ Quick Exe2Bin equivalent.
+
+--*/
+
+#include <stdio.h>
+#include <memory.h>
+#include <string.h>
+#include <stdlib.h>
+
+int
+main (
+ int argc,
+ char *argv[]
+ )
+/*++
+
+Routine Description:
+
+ Converts executable files to binary files.
+
+Arguments:
+
+ argc - Number of command line arguments
+ argv[] - Array of pointers to the command line arguments
+
+Returns:
+
+ Zero - Function completed successfully.
+ Non-zero - Function exited with errors.
+
+--*/
+{
+ FILE *InFile;
+ FILE *OutFile;
+ int Index;
+ int FileSize;
+ char *Buffer;
+ char *Ptrx;
+
+ if (argc < 3) {
+ printf ("Need more args, such as file name to convert and output name\n");
+ return -1;
+ }
+
+ InFile = fopen (argv[1], "rb");
+ OutFile = fopen (argv[2], "wb");
+
+ if (!InFile) {
+ printf ("no file, exit\n");
+ return -1;
+ }
+
+ if (OutFile == NULL) {
+ printf ("Unable to open output file.\n");
+ return -1;
+ }
+
+ fseek (InFile, 0, SEEK_END);
+ FileSize = ftell (InFile);
+
+ if (FileSize < 0x200) {
+ printf ("%d is not a legal size, exit\n", FileSize);
+ return -1;
+ }
+
+ fseek (InFile, 0, SEEK_SET);
+
+ Buffer = (char *) malloc (FileSize);
+ if (Buffer == NULL) {
+ printf ("Error: Out of resources.\n");
+ return -1;
+ }
+
+ fread (Buffer, 1, FileSize, InFile);
+
+ Ptrx = Buffer + 0x200;
+
+ Index = FileSize - 0x200;
+
+ fwrite (Ptrx, Index, 1, OutFile);
+
+ fclose (InFile);
+ fclose (OutFile);
+ free (Buffer);
+
+ return 0;
+}
diff --git a/Source/Strip/build.xml b/Source/Strip/build.xml
new file mode 100644
index 0000000..e079c7e
--- /dev/null
+++ b/Source/Strip/build.xml
@@ -0,0 +1,68 @@
+<?xml version="1.0" ?>
+<!--
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+-->
+<project default="GenTool" basedir=".">
+<!--
+ EDK Strip Tool
+ Copyright (c) 2006, Intel Corporation
+-->
+ <property name="ToolName" value="Strip"/>
+ <property name="FileSet" value="*.c"/>
+
+ <taskdef resource="net/sf/antcontrib/antlib.xml"/>
+
+ <property name="LINK_OUTPUT_TYPE" value="static"/>
+ <property name="BUILD_DIR" value="${PACKAGE_DIR}/${ToolName}/tmp"/>
+
+ <target name="GenTool" depends="init, Tool">
+ <echo message="The EDK Tool: ${ToolName} build has completed!"/>
+ </target>
+
+ <target name="init">
+ <echo message="Building the EDK Tool: ${ToolName}"/>
+ <mkdir dir="${BUILD_DIR}"/>
+ </target>
+
+ <target name="Tool" depends="init">
+ <cc name="${ToolChain}" objdir="${BUILD_DIR}"
+ outfile="${BIN_DIR}/${ToolName}"
+ outtype="executable"
+ optimize="speed"
+ debug="true">
+
+ <fileset dir="${basedir}/${ToolName}"
+ includes="${FileSet}"
+ defaultexcludes="TRUE"
+ excludes="*.xml *.inf"/>
+
+ <includepath path="${PACKAGE_DIR}/Include"/>
+ <includepath path="${PACKAGE_DIR}/Include/Ia32"/>
+ <includepath path="${PACKAGE_DIR}/Common"/>
+ </cc>
+ </target>
+
+ <target name="clean">
+ <echo message="Removing Intermediate Files Only"/>
+ <delete>
+ <fileset dir="${BUILD_DIR}" includes="*.obj"/>
+ </delete>
+ </target>
+
+ <target name="cleanall">
+ <echo message="Removing Object Files and the Executable: ${ToolName}${ext_exe}"/>
+ <delete failonerror="false" quiet="true" includeEmptyDirs="true">
+ <fileset dir="${BUILD_DIR}"/>
+ <fileset file="${BIN_DIR}/${ToolName}${ext_exe}"/>
+ <fileset file="${BIN_DIR}/${ToolName}.pdb"/>
+ </delete>
+ </target>
+
+</project>
diff --git a/Source/TianoTools.msa b/Source/TianoTools.msa
new file mode 100644
index 0000000..2e4b27c
--- /dev/null
+++ b/Source/TianoTools.msa
@@ -0,0 +1,316 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ModuleSurfaceArea xmlns="http://www.TianoCore.org/2006/Edk2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+ <MsaHeader>
+ <ModuleName>Tiano C Tools</ModuleName>
+ <ModuleType>TOOL</ModuleType>
+ <GuidValue>A169C678-3F55-4b6a-80BF-FD8B8DCAB883</GuidValue>
+ <Version>2.0</Version>
+ <Abstract>This is the TianoTools Module</Abstract>
+ <Description>This Module provides the EFI/Tiano Tools that are used to create EFI/Tiano
+ Modules and Platform Binary Files (PBF)
+ These tools require compilation only once if the Developer Workstation and
+ the Developer's choice of HOST tool chain are stable. If the developer
+ updates either the OS or the HOST tool chain, these tools should be rebuilt.</Description>
+ <Copyright>Copyright 2006, Intel Corporation</Copyright>
+ <License URL="http://opensource.org/licenses/bsd-license.php">All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the
+BSD License which accompanies this distribution. The full text of the
+license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.</License>
+ <Specification>FRAMEWORK_BUILD_PACKAGING_SPECIFICATION 0x00000052</Specification>
+ </MsaHeader>
+ <ModuleDefinitions>
+ <SupportedArchitectures>EBC IA32 X64 IPF</SupportedArchitectures>
+ <BinaryModule>false</BinaryModule>
+ <OutputFileBasename>NULL</OutputFileBasename>
+ </ModuleDefinitions>
+ <SourceFiles>
+ <Filename>build.xml</Filename>
+ <Filename>Common/build.xml</Filename>
+ <Filename>Common/CommonLib.c</Filename>
+ <Filename>Common/CommonLib.h</Filename>
+ <Filename>Common/Crc32.c</Filename>
+ <Filename>Common/Crc32.h</Filename>
+ <Filename>Common/EfiCompress.c</Filename>
+ <Filename>Common/EfiCompress.h</Filename>
+ <Filename>Common/EfiCustomizedCompress.h</Filename>
+ <Filename>Common/EfiDecompress.c</Filename>
+ <Filename>Common/EfiDecompress.h</Filename>
+ <Filename>Common/EfiUtilityMsgs.c</Filename>
+ <Filename>Common/EfiUtilityMsgs.h</Filename>
+ <Filename>Common/FvLib.c</Filename>
+ <Filename>Common/FvLib.h</Filename>
+ <Filename>Common/MyAlloc.c</Filename>
+ <Filename>Common/MyAlloc.h</Filename>
+ <Filename>Common/ParseInf.c</Filename>
+ <Filename>Common/ParseInf.h</Filename>
+ <Filename>Common/SimpleFileParsing.c</Filename>
+ <Filename>Common/SimpleFileParsing.h</Filename>
+ <Filename>Common/WinNtInclude.h</Filename>
+ <Filename>CompressDll/build.xml</Filename>
+ <Filename>CompressDll/CompressDll.c</Filename>
+ <Filename>CompressDll/CompressDll.h</Filename>
+ <Filename>CreateMtFile/build.xml</Filename>
+ <Filename>CreateMtFile/CreateMtFile.c</Filename>
+ <Filename>CustomizedCompress/build.xml</Filename>
+ <Filename>CustomizedCompress/CustomizedCompress.c</Filename>
+ <Filename>EfiCompress/build.xml</Filename>
+ <Filename>EfiCompress/EfiCompressMain.c</Filename>
+ <Filename>EfiCompress/makefile</Filename>
+ <Filename>EfiRom/build.xml</Filename>
+ <Filename>EfiRom/EfiRom.c</Filename>
+ <Filename>FlashMap/build.xml</Filename>
+ <Filename>FlashMap/FlashDefFile.c</Filename>
+ <Filename>FlashMap/FlashDefFile.h</Filename>
+ <Filename>FlashMap/FlashMap.c</Filename>
+ <Filename>FlashMap/Microcode.c</Filename>
+ <Filename>FlashMap/Microcode.h</Filename>
+ <Filename>FlashMap/Symbols.c</Filename>
+ <Filename>FlashMap/Symbols.h</Filename>
+ <Filename>FwImage/build.xml</Filename>
+ <Filename>FwImage/fwimage.c</Filename>
+ <Filename>GenAcpiTable/build.xml</Filename>
+ <Filename>GenAcpiTable/GenAcpiTable.c</Filename>
+ <Filename>GenCapsuleHdr/build.xml</Filename>
+ <Filename>GenCapsuleHdr/CreateGuid.c</Filename>
+ <Filename>GenCapsuleHdr/GenCapsuleHdr.c</Filename>
+ <Filename>GenCRC32Section/build.xml</Filename>
+ <Filename>GenCRC32Section/GenCRC32Section.c</Filename>
+ <Filename>GenCRC32Section/GenCRC32Section.h</Filename>
+ <Filename>GenDepex/build.xml</Filename>
+ <Filename>GenDepex/DepexParser.c</Filename>
+ <Filename>GenDepex/DepexParser.h</Filename>
+ <Filename>GenDepex/GenDepex.c</Filename>
+ <Filename>GenDepex/GenDepex.h</Filename>
+ <Filename>GenFfsFile/build.xml</Filename>
+ <Filename>GenFfsFile/GenFfsFile.c</Filename>
+ <Filename>GenFfsFile/GenFfsFile.h</Filename>
+ <Filename>GenFfsFile/SimpleFileParsing.c</Filename>
+ <Filename>GenFvImage/build.xml</Filename>
+ <Filename>GenFvImage/Ebc/PeCoffLoaderEx.c</Filename>
+ <Filename>GenFvImage/GenFvImageExe.c</Filename>
+ <Filename>GenFvImage/GenFvImageExe.h</Filename>
+ <Filename>GenFvImage/GenFvImageLib.c</Filename>
+ <Filename>GenFvImage/GenFvImageLib.h</Filename>
+ <Filename>GenFvImage/GenFvImageLibInternal.h</Filename>
+ <Filename>GenSection/build.xml</Filename>
+ <Filename>GenSection/GenSection.c</Filename>
+ <Filename>GenSection/GenSection.h</Filename>
+ <Filename>GenTEImage/build.xml</Filename>
+ <Filename>GenTEImage/GenTEImage.c</Filename>
+ <Filename>GuidChk/build.xml</Filename>
+ <Filename>GuidChk/CommonUtils.h</Filename>
+ <Filename>GuidChk/FileSearch.c</Filename>
+ <Filename>GuidChk/FileSearch.h</Filename>
+ <Filename>GuidChk/GuidChk.c</Filename>
+ <Filename>GuidChk/GuidList.c</Filename>
+ <Filename>GuidChk/UtilsMsgs.c</Filename>
+ <Filename>GuidChk/UtilsMsgs.h</Filename>
+ <Filename>Include/Common/BaseTypes.h</Filename>
+ <Filename>Include/Common/Capsule.h</Filename>
+ <Filename>Include/Common/Dependency.h</Filename>
+ <Filename>Include/Common/EfiImage.h</Filename>
+ <Filename>Include/Common/FirmwareFileSystem.h</Filename>
+ <Filename>Include/Common/FirmwareVolumeHeader.h</Filename>
+ <Filename>Include/Common/FirmwareVolumeImageFormat.h</Filename>
+ <Filename>Include/Common/InternalFormRepresentation.h</Filename>
+ <Filename>Include/Common/MultiPhase.h</Filename>
+ <Filename>Include/Common/UefiBaseTypes.h</Filename>
+ <Filename>Include/Common/Variable.h</Filename>
+ <Filename>Include/Common/WorkingBlockHeader.h</Filename>
+ <Filename>Include/Guid/AcpiTableStorage.h</Filename>
+ <Filename>Include/Guid/Apriori.h</Filename>
+ <Filename>Include/Guid/Capsule.h</Filename>
+ <Filename>Include/Guid/FirmwareFileSystem.h</Filename>
+ <Filename>Include/Ia32/ProcessorBind.h</Filename>
+ <Filename>Include/IndustryStandard/pci22.h</Filename>
+ <Filename>Include/Library/PeCoffLib.h</Filename>
+ <Filename>Include/Library/PrintLib.h</Filename>
+ <Filename>Include/Protocol/DevicePath.h</Filename>
+ <Filename>Include/Protocol/GuidedSectionExtraction.h</Filename>
+ <Filename>Include/Protocol/Hii.h</Filename>
+ <Filename>Include/Protocol/UgaDraw.h</Filename>
+ <Filename>MakeDeps/build.xml</Filename>
+ <Filename>MakeDeps/MakeDeps.c</Filename>
+ <Filename>ModifyInf/build.xml</Filename>
+ <Filename>ModifyInf/ModifyInf.c</Filename>
+ <Filename>Pccts/antlr/antlr.1</Filename>
+ <Filename>Pccts/antlr/antlr.c</Filename>
+ <Filename>Pccts/antlr/antlr.g</Filename>
+ <Filename>Pccts/antlr/antlr.ilk</Filename>
+ <Filename>Pccts/antlr/antlr.pdb</Filename>
+ <Filename>Pccts/antlr/antlr.r</Filename>
+ <Filename>Pccts/antlr/antlr1.txt</Filename>
+ <Filename>Pccts/antlr/AntlrMS.mak</Filename>
+ <Filename>Pccts/antlr/AntlrPPC.mak</Filename>
+ <Filename>Pccts/antlr/bits.c</Filename>
+ <Filename>Pccts/antlr/build.c</Filename>
+ <Filename>Pccts/antlr/build.xml</Filename>
+ <Filename>Pccts/antlr/dumpcycles.c</Filename>
+ <Filename>Pccts/antlr/dumpnode.c</Filename>
+ <Filename>Pccts/antlr/egman.c</Filename>
+ <Filename>Pccts/antlr/err.c</Filename>
+ <Filename>Pccts/antlr/fcache.c</Filename>
+ <Filename>Pccts/antlr/fset.c</Filename>
+ <Filename>Pccts/antlr/fset2.c</Filename>
+ <Filename>Pccts/antlr/gen.c</Filename>
+ <Filename>Pccts/antlr/generic.h</Filename>
+ <Filename>Pccts/antlr/globals.c</Filename>
+ <Filename>Pccts/antlr/hash.c</Filename>
+ <Filename>Pccts/antlr/hash.h</Filename>
+ <Filename>Pccts/antlr/lex.c</Filename>
+ <Filename>Pccts/antlr/main.c</Filename>
+ <Filename>Pccts/antlr/makefile</Filename>
+ <Filename>Pccts/antlr/makefile1</Filename>
+ <Filename>Pccts/antlr/misc.c</Filename>
+ <Filename>Pccts/antlr/mode.h</Filename>
+ <Filename>Pccts/antlr/mrhoist.c</Filename>
+ <Filename>Pccts/antlr/parser.dlg</Filename>
+ <Filename>Pccts/antlr/pred.c</Filename>
+ <Filename>Pccts/antlr/proto.h</Filename>
+ <Filename>Pccts/antlr/README</Filename>
+ <Filename>Pccts/antlr/scan.c</Filename>
+ <Filename>Pccts/antlr/stdpccts.h</Filename>
+ <Filename>Pccts/antlr/syn.h</Filename>
+ <Filename>Pccts/antlr/tokens.h</Filename>
+ <Filename>Pccts/antlr/vc70.pdb</Filename>
+ <Filename>Pccts/build.xml</Filename>
+ <Filename>Pccts/CHANGES_FROM_131.txt</Filename>
+ <Filename>Pccts/CHANGES_FROM_133.txt</Filename>
+ <Filename>Pccts/CHANGES_FROM_133_BEFORE_MR13.txt</Filename>
+ <Filename>Pccts/CHANGES_SUMMARY.txt</Filename>
+ <Filename>Pccts/dlg/automata.c</Filename>
+ <Filename>Pccts/dlg/build.xml</Filename>
+ <Filename>Pccts/dlg/dlg.1</Filename>
+ <Filename>Pccts/dlg/dlg.h</Filename>
+ <Filename>Pccts/dlg/dlg.r</Filename>
+ <Filename>Pccts/dlg/dlg1.txt</Filename>
+ <Filename>Pccts/dlg/dlg_a.c</Filename>
+ <Filename>Pccts/dlg/dlg_p.c</Filename>
+ <Filename>Pccts/dlg/dlg_p.g</Filename>
+ <Filename>Pccts/dlg/DlgMS.mak</Filename>
+ <Filename>Pccts/dlg/DlgPPC.mak</Filename>
+ <Filename>Pccts/dlg/err.c</Filename>
+ <Filename>Pccts/dlg/main.c</Filename>
+ <Filename>Pccts/dlg/makefile</Filename>
+ <Filename>Pccts/dlg/makefile1</Filename>
+ <Filename>Pccts/dlg/mode.h</Filename>
+ <Filename>Pccts/dlg/output.c</Filename>
+ <Filename>Pccts/dlg/parser.dlg</Filename>
+ <Filename>Pccts/dlg/relabel.c</Filename>
+ <Filename>Pccts/dlg/stdpccts.h</Filename>
+ <Filename>Pccts/dlg/support.c</Filename>
+ <Filename>Pccts/dlg/tokens.h</Filename>
+ <Filename>Pccts/h/antlr.h</Filename>
+ <Filename>Pccts/h/AParser.cpp</Filename>
+ <Filename>Pccts/h/AParser.h</Filename>
+ <Filename>Pccts/h/ast.c</Filename>
+ <Filename>Pccts/h/ast.h</Filename>
+ <Filename>Pccts/h/ASTBase.cpp</Filename>
+ <Filename>Pccts/h/ASTBase.h</Filename>
+ <Filename>Pccts/h/AToken.h</Filename>
+ <Filename>Pccts/h/ATokenBuffer.cpp</Filename>
+ <Filename>Pccts/h/ATokenBuffer.h</Filename>
+ <Filename>Pccts/h/ATokenStream.h</Filename>
+ <Filename>Pccts/h/ATokPtr.h</Filename>
+ <Filename>Pccts/h/ATokPtrImpl.h</Filename>
+ <Filename>Pccts/h/BufFileInput.cpp</Filename>
+ <Filename>Pccts/h/BufFileInput.h</Filename>
+ <Filename>Pccts/h/charbuf.h</Filename>
+ <Filename>Pccts/h/charptr.c</Filename>
+ <Filename>Pccts/h/charptr.h</Filename>
+ <Filename>Pccts/h/config.h</Filename>
+ <Filename>Pccts/h/DLexer.h</Filename>
+ <Filename>Pccts/h/DLexerBase.cpp</Filename>
+ <Filename>Pccts/h/DLexerBase.h</Filename>
+ <Filename>Pccts/h/DLG_stream_input.h</Filename>
+ <Filename>Pccts/h/dlgauto.h</Filename>
+ <Filename>Pccts/h/dlgdef.h</Filename>
+ <Filename>Pccts/h/err.h</Filename>
+ <Filename>Pccts/h/int.h</Filename>
+ <Filename>Pccts/h/PBlackBox.h</Filename>
+ <Filename>Pccts/h/pccts_assert.h</Filename>
+ <Filename>Pccts/h/pccts_iostream.h</Filename>
+ <Filename>Pccts/h/pccts_istream.h</Filename>
+ <Filename>Pccts/h/pccts_setjmp.h</Filename>
+ <Filename>Pccts/h/pccts_stdarg.h</Filename>
+ <Filename>Pccts/h/pccts_stdio.h</Filename>
+ <Filename>Pccts/h/pccts_stdlib.h</Filename>
+ <Filename>Pccts/h/pccts_string.h</Filename>
+ <Filename>Pccts/h/PCCTSAST.cpp</Filename>
+ <Filename>Pccts/h/PCCTSAST.h</Filename>
+ <Filename>Pccts/h/pcctscfg.h</Filename>
+ <Filename>Pccts/h/pcnames.bat</Filename>
+ <Filename>Pccts/h/slist.cpp</Filename>
+ <Filename>Pccts/h/SList.h</Filename>
+ <Filename>Pccts/history.ps</Filename>
+ <Filename>Pccts/history.txt</Filename>
+ <Filename>Pccts/KNOWN_PROBLEMS.txt</Filename>
+ <Filename>Pccts/makefile</Filename>
+ <Filename>Pccts/MPW_Read_Me</Filename>
+ <Filename>Pccts/NOTES.bcc</Filename>
+ <Filename>Pccts/NOTES.msvc</Filename>
+ <Filename>Pccts/README</Filename>
+ <Filename>Pccts/RIGHTS</Filename>
+ <Filename>Pccts/support/genmk/genmk.c</Filename>
+ <Filename>Pccts/support/genmk/genmk_old.c</Filename>
+ <Filename>Pccts/support/genmk/makefile</Filename>
+ <Filename>Pccts/support/rexpr/makefile</Filename>
+ <Filename>Pccts/support/rexpr/rexpr.c</Filename>
+ <Filename>Pccts/support/rexpr/rexpr.h</Filename>
+ <Filename>Pccts/support/rexpr/test.c</Filename>
+ <Filename>Pccts/support/set/set.c</Filename>
+ <Filename>Pccts/support/set/set.h</Filename>
+ <Filename>Pccts/support/sym/sym.c</Filename>
+ <Filename>Pccts/support/sym/template.h</Filename>
+ <Filename>PeCoffLoader/BasePeCoff.c</Filename>
+ <Filename>PeCoffLoader/build.xml</Filename>
+ <Filename>PeCoffLoader/Common/EfiImage.h</Filename>
+ <Filename>PeCoffLoader/Ia32/PeCoffLoaderEx.c</Filename>
+ <Filename>PeCoffLoader/Ipf/PeCoffLoaderEx.c</Filename>
+ <Filename>PeCoffLoader/X64/PeCoffLoaderEx.c</Filename>
+ <Filename>PeiRebase/build.xml</Filename>
+ <Filename>PeiRebase/makefile</Filename>
+ <Filename>PeiRebase/PeiRebaseExe.c</Filename>
+ <Filename>PeiRebase/PeiRebaseExe.h</Filename>
+ <Filename>SecApResetVectorFixup/build.xml</Filename>
+ <Filename>SecApResetVectorFixup/SecApResetVectorFixup.c</Filename>
+ <Filename>SecApResetVectorFixup/SecApResetVectorFixup.h</Filename>
+ <Filename>SecFixup/build.xml</Filename>
+ <Filename>SecFixup/SecFixup.c</Filename>
+ <Filename>SecFixup/SecFixup.h</Filename>
+ <Filename>SetStamp/build.xml</Filename>
+ <Filename>SetStamp/SetStamp.c</Filename>
+ <Filename>SplitFile/build.xml</Filename>
+ <Filename>SplitFile/SplitFile.c</Filename>
+ <Filename>StrGather/build.xml</Filename>
+ <Filename>StrGather/StrGather.c</Filename>
+ <Filename>StrGather/StrGather.h</Filename>
+ <Filename>StrGather/StringDB.c</Filename>
+ <Filename>StrGather/StringDB.h</Filename>
+ <Filename>String/build.xml</Filename>
+ <Filename>String/PrintLib.c</Filename>
+ <Filename>String/PrintLibInternal.c</Filename>
+ <Filename>String/PrintLibInternal.h</Filename>
+ <Filename>String/String.c</Filename>
+ <Filename>Strip/build.xml</Filename>
+ <Filename>Strip/Strip.c</Filename>
+ <Filename>VfrCompile/build.xml</Filename>
+ <Filename>VfrCompile/DLGLexer.cpp</Filename>
+ <Filename>VfrCompile/DLGLexer.h</Filename>
+ <Filename>VfrCompile/EfiVfr.h</Filename>
+ <Filename>VfrCompile/EfiVfrParser.cpp</Filename>
+ <Filename>VfrCompile/EfiVfrParser.h</Filename>
+ <Filename>VfrCompile/parser.dlg</Filename>
+ <Filename>VfrCompile/tokens.h</Filename>
+ <Filename>VfrCompile/VfrCompile.cpp</Filename>
+ <Filename>VfrCompile/VfrCompile.g</Filename>
+ <Filename>VfrCompile/VfrServices.cpp</Filename>
+ <Filename>VfrCompile/VfrServices.h</Filename>
+ <Filename>ZeroDebugData/build.xml</Filename>
+ <Filename>ZeroDebugData/ZeroDebugData.c</Filename>
+ </SourceFiles>
+</ModuleSurfaceArea> \ No newline at end of file
diff --git a/Source/VfrCompile/EfiVfr.h b/Source/VfrCompile/EfiVfr.h
new file mode 100644
index 0000000..6419ad7
--- /dev/null
+++ b/Source/VfrCompile/EfiVfr.h
@@ -0,0 +1,181 @@
+/*++
+
+Copyright (c) 2004 - 2005, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ EfiVfr.h
+
+Abstract:
+
+ Defines and prototypes for the EFI internal forms representation
+ setup protocol and drivers
+
+--*/
+
+#ifndef _EFI_VFR_H_
+#define _EFI_VFR_H_
+
+#include <string.h>
+
+#include <Common/UefiBaseTypes.h>
+#include <Common/InternalFormRepresentation.h>
+
+//
+// This number should be incremented with each change to the VFR compiler.
+// We write the version to the output list file for debug purposes.
+//
+#define VFR_COMPILER_VERSION "1.88"
+
+//
+// Maximum file path for filenames
+//
+#ifndef MAX_PATH
+#define MAX_PATH 255
+#endif
+#define MAX_QUEUE_COUNT 255
+#define MAX_LINE_LEN 1024
+#define PROGRAM_NAME "VfrCompile"
+
+//
+// We parse C-style structure definitions which can then be referenced
+// in VFR statements.
+// We need to define an internal structure that can be used to
+// track the fields in a structure definition, and another structure
+// to keep track of the structure name and subfields.
+//
+typedef struct _STRUCT_FIELD_DEFINITION {
+ struct _STRUCT_FIELD_DEFINITION *Next;
+ int DataSize;
+ int Offset; // from the start of the structure
+ int ArrayLength;
+ char IsArray;
+ char *Name;
+} STRUCT_FIELD_DEFINITION;
+
+typedef struct _STRUCT_DEFINITION {
+ struct _STRUCT_DEFINITION *Next;
+ int Size;
+ int LineNum; // line number where the structure was defined
+ int IsNonNV; // if this is the non-NV data structure definition
+ int Referenced; // if it's referenced anywhere in the VFR
+ int VarStoreIdValid; // found a 'varstore' statement for it in the VFR
+ unsigned short VarStoreId; // key from a varstore IFR statement
+ int VarStoreLineNum; // line number where VARSTORE was defined
+ char *Name;
+ STRUCT_FIELD_DEFINITION *Field;
+ STRUCT_FIELD_DEFINITION *LastField;
+} STRUCT_DEFINITION;
+
+//
+// For the IdEqValList variable list of UINT16's, keep track of them using
+// a linked list until we know how many there are.
+// We also use a linked list of these to keep track of labels used in
+// the VFR script so we can catch duplicates.
+// We'll also use it to keep track of defined varstore id's so we can
+// detect duplicate definitions.
+//
+typedef struct _UINT16_LIST {
+ struct _UINT16_LIST *Next;
+ UINT16 Value;
+ UINT32 LineNum;
+} UINT16_LIST;
+
+typedef struct _GOTO_REFERENCE {
+ struct _GOTO_REFERENCE *Next;
+ UINT32 RefLineNum; // line number of source file where referenced
+ UINT16 Value;
+} GOTO_REFERENCE;
+
+typedef struct _FORM_ID_VALUE {
+ struct _FORM_ID_VALUE *Next;
+ UINT32 LineNum;
+ UINT16 Value;
+} FORM_ID_VALUE;
+
+//
+// We keep track in the parser of all "#line 4 "x.y"" strings so we
+// can cross-reference the line numbers in the preprocessor output .i file
+// to the original input files.
+//
+typedef struct _PARSER_LINE_DEFINITION {
+ struct _PARSER_LINE_DEFINITION *Next;
+ UINT32 HashLineNum; // from the #line stmt
+ UINT32 TokenLineNum; // line number in the .i file
+ CHAR8 *FileName; // from the #line stmt
+} PARSER_LINE_DEFINITION;
+
+extern PARSER_LINE_DEFINITION *gLineDefinition;
+extern PARSER_LINE_DEFINITION *gLastLineDefinition;
+
+extern
+char *
+ConvertLineNumber (
+ UINT32 *LineNum
+ )
+/*++
+
+Routine Description:
+ Given the line number in the preprocessor-output file, use the line number
+ information we've saved to determine the source file name and line number
+ where the code originally came from. This is required for error reporting.
+
+Arguments:
+ LineNum - the line number in the preprocessor-output file.
+
+Returns:
+ Returns a pointer to the source file name. Also returns the line number
+ in the provided LineNum argument
+
+--*/
+;
+
+typedef struct _IFR_BYTE {
+ struct _IFR_BYTE *Next;
+ UINT32 LineNum;
+ UINT8 OpcodeByte;
+ UINT8 KeyByte;
+} IFR_BYTE;
+
+typedef struct {
+ CHAR8 VfrFileName[MAX_PATH];
+ CHAR8 VfrListFileName[MAX_PATH];
+ INT8 CreateListFile;
+ INT8 CreateIfrBinFile;
+ CHAR8 IfrOutputFileName[MAX_PATH];
+ CHAR8 OutputDirectory[MAX_PATH];
+ CHAR8 PreprocessorOutputFileName[MAX_PATH];
+ CHAR8 VfrBaseFileName[MAX_PATH]; // name of input VFR file with no path or extension
+ CHAR8 *IncludePaths;
+ CHAR8 *CPreprocessorOptions;
+} OPTIONS;
+
+extern OPTIONS gOptions;
+
+VOID
+WriteStandardFileHeader (
+ FILE *OutFptr
+ )
+/*++
+
+Routine Description:
+ This function is invoked to emit a standard header to an
+ output text file.
+
+Arguments:
+ OutFptr - file to write the header to
+
+Returns:
+ None
+
+--*/
+;
+
+#endif // #ifndef _EFI_VFR_H_
diff --git a/Source/VfrCompile/VfrCompile.g b/Source/VfrCompile/VfrCompile.g
new file mode 100644
index 0000000..44820bc
--- /dev/null
+++ b/Source/VfrCompile/VfrCompile.g
@@ -0,0 +1,3529 @@
+/*++
+
+Copyright (c) 2004 - 2005, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ VfrCompile.g
+
+Abstract:
+
+ PCCTS parser and lexer definitions for the EFI VFR forms compiler
+
+--*/
+
+#header<<
+
+#include <Common/UefiBaseTypes.h>
+#include <Common/MultiPhase.h>
+#include <Common/InternalFormRepresentation.h>
+#include <Protocol/UgaDraw.h>
+#include <Protocol/Hii.h>
+
+#include "CommonLib.h"
+#include "EfiUtilityMsgs.h"
+#include "EfiVfr.h"
+#include "VfrServices.h"
+
+#include <ctype.h>
+#ifndef __GNUC__
+#include <direct.h>
+#include <process.h> // for spawn functions
+#else
+#include <unistd.h>
+#endif
+
+>>
+
+<<
+
+//
+// Base info for DLG-generated scanner
+//
+#include "DLexerBase.h"
+
+//
+// Include the scanner file generated by DLG
+//
+#include "DLGLexer.h"
+
+class DLGLexerVfr : public DLGLexer
+{
+public:
+ DLGLexerVfr (DLGFileInput *F) : DLGLexer (F) {};
+ INT32 errstd (char *Text)
+ {
+ printf ("unrecognized input '%s'\n", Text);
+ }
+
+};
+
+//
+// Base token definitions for ANTLR
+//
+#include "AToken.h"
+
+//
+// This is how we invoke the C preprocessor on the VFR source file
+// to resolve #defines, #includes, etc. To make C source files
+// shareable between VFR and drivers, define VFRCOMPILE so that
+// #ifdefs can be used in shared .h files.
+//
+#ifdef __GNUC__
+#define PREPROCESSOR_COMMAND "gcc "
+#define PREPROCESSOR_OPTIONS "-x c -E -P -DVFRCOMPILE "
+#define FILE_SEP_CHAR '/'
+#define FILE_SEP_STRING "/"
+#else
+#define PREPROCESSOR_COMMAND "cl.exe "
+#define PREPROCESSOR_OPTIONS "/nologo /P /TC /DVFRCOMPILE "
+#define FILE_SEP_CHAR '/'
+#define FILE_SEP_STRING "/"
+#endif
+
+typedef ANTLRCommonToken ANTLRToken;
+
+//
+// Specify the filename extensions for the files we generate.
+//
+#define VFR_BINARY_FILENAME_EXTENSION ".c"
+#define VFR_LIST_FILENAME_EXTENSION ".lst"
+
+static
+VOID
+Usage ();
+
+static
+STATUS
+ProcessArgs (
+ int Argc,
+ char *Argv[]
+ );
+
+static
+VOID
+Cleanup ();
+
+//
+// Globals
+//
+OPTIONS gOptions;
+
+int
+main (
+ int argc,
+ char **argv
+ )
+/*++
+
+Routine Description:
+ Application entry point function. Parse command-line arguments,
+ invoke the parser, clean up, and return.
+
+Arguments:
+ argc - standard argc passed to main() per C conventions
+ argv - standard argv passed to main() per C conventions
+
+Returns:
+ STATUS_SUCCESS - program executed with no errors or warnings
+ STATUS_WARNING - program executed with warnings
+ STATUS_ERROR - non-recoverable errors encountered while processing
+
+--*/
+{
+ FILE *VfrFptr;
+ char *Cmd;
+ char *Cptr;
+ int Len;
+ STATUS Status;
+
+ //
+ // Set our program name for the error printing routines.
+ // Then set printing limits.
+ //
+ SetUtilityName (PROGRAM_NAME);
+ SetPrintLimits (20, 20, 30);
+ //
+ // Process the command-line arguments
+ //
+ if (ProcessArgs (argc, argv) != STATUS_SUCCESS) {
+ Usage ();
+ Cleanup();
+ return STATUS_ERROR;
+ }
+ VfrFptr = NULL;
+ //
+ // Verify the VFR script file exists
+ //
+ if ((VfrFptr = fopen (gOptions.VfrFileName, "r")) == NULL) {
+ Error (PROGRAM_NAME, 0, 0, gOptions.VfrFileName, "could not open input VFR file");
+ Cleanup();
+ return STATUS_ERROR;
+ }
+ //
+ // Now close the file and make a system call to run the preprocessor
+ // on it.
+ //
+ fclose (VfrFptr);
+ Len = strlen (PREPROCESSOR_OPTIONS) + strlen (gOptions.VfrFileName) + 10;
+ if (gOptions.CPreprocessorOptions != NULL) {
+ Len += strlen (gOptions.CPreprocessorOptions) + 1;
+ }
+ if (gOptions.IncludePaths != NULL) {
+ Len += strlen (gOptions.IncludePaths) + 1;
+ }
+ Cmd = (char *)malloc (Len);
+ if (Cmd == NULL) {
+ Error (PROGRAM_NAME, 0, 0, NULL, "could not allocate memory");
+ Cleanup();
+ return STATUS_ERROR;
+ }
+ strcpy (Cmd, PREPROCESSOR_OPTIONS);
+ if (gOptions.IncludePaths != NULL) {
+ strcat (Cmd, gOptions.IncludePaths);
+ strcat (Cmd, " ");
+ }
+ if (gOptions.CPreprocessorOptions != NULL) {
+ strcat (Cmd, gOptions.CPreprocessorOptions);
+ strcat (Cmd, " ");
+ }
+ strcat (Cmd, gOptions.VfrFileName);
+#ifndef __GNUC__
+ Status = _spawnlp (_P_WAIT, PREPROCESSOR_COMMAND, Cmd, NULL);
+#else
+ {
+ char CommandLine[1000];
+ char *p;
+
+ //
+ // Lean the slashes forward.
+ //
+ for (p = gOptions.PreprocessorOutputFileName; *p; p++) {
+ if (*p=='\\') {
+ *p=FILE_SEP_CHAR;
+ }
+ }
+
+ //
+ // Lean the slashes forward.
+ //
+ for (p = Cmd; *p; p++) {
+ if (*p=='\\') {
+ *p=FILE_SEP_CHAR;
+ }
+ }
+
+ sprintf(CommandLine, "%s %s > %s", PREPROCESSOR_COMMAND, Cmd, gOptions.PreprocessorOutputFileName);
+ Status = system (CommandLine);
+ }
+#endif
+ if (Status != 0) {
+ Error (PROGRAM_NAME, 0, 0, gOptions.VfrFileName, "failed to spawn C preprocessor on VFR file");
+ printf ("Command: '%s %s'\n", PREPROCESSOR_COMMAND, Cmd);
+ Cleanup();
+ return STATUS_ERROR;
+ }
+ free (Cmd);
+ //
+ // Open the preprocessor output file
+ //
+ if ((VfrFptr = fopen (gOptions.PreprocessorOutputFileName, "r")) == NULL) {
+ Error (PROGRAM_NAME, 0, 0, "failed to open input VFR preprocessor output file",
+ gOptions.PreprocessorOutputFileName);
+ Cleanup();
+ return STATUS_ERROR;
+ }
+ //
+ // Define input VFR file
+ //
+ DLGFileInput InputFile (VfrFptr);
+ //
+ // Define an instance of the scanner
+ //
+ DLGLexerVfr Scanner (&InputFile);
+ //
+ // Define token buffer between scanner and parser
+ //
+ ANTLRTokenBuffer Pipe (&Scanner);
+ //
+ // Create a token to use as a model
+ //
+ ANTLRToken Tok;
+ //
+ // Tell the scanner what type the token is
+ //
+ Scanner.setToken (&Tok);
+ //
+ // Create an instance of our parser
+ //
+ EfiVfrParser Parser (&Pipe);
+ //
+ // Initialize the parser
+ //
+ Parser.init ();
+ Status = GetUtilityStatus ();
+ if (Status != STATUS_SUCCESS) {
+ Cleanup();
+ return Status;
+ }
+ //
+ // Start the first rule
+ //
+ Parser.program ();
+ //
+ // Close the input script file
+ //
+ fclose (VfrFptr);
+ Parser.WriteIfrBytes ();
+ //
+ // Call cleanup, which does some extra checking of the script
+ //
+ Parser.Cleanup ();
+ Cleanup();
+ //
+ // If we had an error somewhere, delete our output files so that
+ // a subsequent build will rebuild them.
+ //
+ Status = GetUtilityStatus ();
+ if (Status == STATUS_ERROR) {
+ remove (gOptions.IfrOutputFileName);
+ }
+ return Status;
+}
+static
+VOID
+Cleanup ()
+/*++
+
+Routine Description:
+ Free up memory allocated during parsing.
+
+Arguments:
+ None
+
+Returns:
+ None
+
+--*/
+{
+ //
+ // Free up our string we allocated to track the include paths
+ //
+ if (gOptions.IncludePaths != NULL) {
+ free (gOptions.IncludePaths);
+ gOptions.IncludePaths = NULL;
+ }
+ //
+ // Free up our string we allocated to track preprocessor options
+ //
+ if (gOptions.CPreprocessorOptions != NULL) {
+ free (gOptions.CPreprocessorOptions);
+ gOptions.CPreprocessorOptions = NULL;
+ }
+}
+
+static
+STATUS
+ProcessArgs (
+ int Argc,
+ char *Argv[]
+ )
+/*++
+
+Routine Description:
+ Process the command-line arguments.
+
+Arguments:
+ Argc - standard argc passed to main()
+ Argv - standard argv passed to main()
+
+Returns:
+ STATUS_SUCCESS - program should continue (all args ok)
+
+--*/
+{
+ char *IncludePaths;
+ char *CPreprocessorOptions;
+ int Len;
+ char CopyStr[MAX_PATH];
+ char *Cptr;
+
+ //
+ // Put options in known state.
+ //
+ memset ((char *)&gOptions, 0, sizeof (OPTIONS));
+ //
+ // Go through all the arguments that start with '-'
+ //
+ Argc--;
+ Argv++;
+ while ((Argc > 0) && (Argv[0][0] == '-')) {
+ //
+ // -? or -h help option -- return an error for printing usage
+ //
+ if ((stricmp (Argv[0], "-?") == 0) || (stricmp (Argv[0], "-h") == 0)) {
+ return STATUS_ERROR;
+ break;
+ //
+ // -l to create a listing output file
+ //
+ } else if (stricmp (Argv[0], "-l") == 0) {
+ gOptions.CreateListFile = 1;
+ //
+ // -I include_path option for finding include files. We'll pass this
+ // to the preprocessor. Turn them all into a single include string.
+ //
+ } else if (stricmp (Argv[0], "-i") == 0) {
+ if ((Argc < 2) || (Argv[1][0] == '-')) {
+ Error (PROGRAM_NAME, 0, 0, Argv[0], "missing path argument");
+ return STATUS_ERROR;
+ }
+ Argc--;
+ Argv++;
+ Len = strlen (" -I ");
+ Len += strlen (Argv[0]) + 2;
+ if (gOptions.IncludePaths != NULL) {
+ Len += strlen (gOptions.IncludePaths);
+ }
+ IncludePaths = (CHAR8 *)malloc (Len);
+ if (IncludePaths == NULL) {
+ Error (PROGRAM_NAME, 0, 0, NULL, "memory allocation failure");
+ return STATUS_ERROR;
+ }
+ IncludePaths[0] = 0;
+ if (gOptions.IncludePaths != NULL) {
+ strcpy (IncludePaths, gOptions.IncludePaths);
+ free (gOptions.IncludePaths);
+ }
+ strcat (IncludePaths, " -I ");
+ strcat (IncludePaths, Argv[0]);
+ gOptions.IncludePaths = IncludePaths;
+ //
+ // -od OutputDirectory to define a common directory for output files
+ //
+ } else if (stricmp (Argv[0], "-od") == 0) {
+ if ((Argc < 2) || (Argv[1][0] == '-')) {
+ Error (PROGRAM_NAME, 0, 0, Argv[0], "missing output directory name");
+ return STATUS_ERROR;
+ }
+ Argc--;
+ Argv++;
+ strcpy (gOptions.OutputDirectory, Argv[0]);
+ } else if (stricmp (Argv[0], "-ibin") == 0) {
+ gOptions.CreateIfrBinFile = 1;
+ } else if (stricmp (Argv[0], "-nostrings") == 0) {
+ // deprecated option
+ //
+ // -ppflag C-preprocessor-flag option for passing options to the C preprocessor.
+ // Turn them all into a single string.
+ //
+ } else if (stricmp (Argv[0], "-ppflag") == 0) {
+ if (Argc < 2) {
+ Error (PROGRAM_NAME, 0, 0, Argv[0], "missing C-preprocessor argument");
+ return STATUS_ERROR;
+ }
+ Argc--;
+ Argv++;
+ Len = strlen (Argv[0]) + 2;
+ if (gOptions.CPreprocessorOptions != NULL) {
+ Len += strlen (gOptions.CPreprocessorOptions);
+ }
+ CPreprocessorOptions = (CHAR8 *)malloc (Len);
+ if (CPreprocessorOptions == NULL) {
+ Error (PROGRAM_NAME, 0, 0, NULL, "memory allocation failure");
+ return STATUS_ERROR;
+ }
+ CPreprocessorOptions[0] = 0;
+ if (gOptions.CPreprocessorOptions != NULL) {
+ strcpy (CPreprocessorOptions, gOptions.CPreprocessorOptions);
+ free (gOptions.CPreprocessorOptions);
+ }
+ strcat (CPreprocessorOptions, " ");
+ strcat (CPreprocessorOptions, Argv[0]);
+ gOptions.CPreprocessorOptions = CPreprocessorOptions;
+ } else {
+ Error (PROGRAM_NAME, 0, 0, Argv[0], "unrecognized option");
+ return STATUS_ERROR;
+ }
+ Argc--;
+ Argv++;
+ }
+ //
+ // Must specify at least the vfr file name
+ //
+ if (Argc > 1) {
+ Error (PROGRAM_NAME, 0, 0, Argv[1], "unrecognized argument after VFR file name");
+ return STATUS_ERROR;
+ } else if (Argc < 1) {
+ Error (PROGRAM_NAME, 0, 0, NULL, "must specify VFR file name");
+ return STATUS_ERROR;
+ }
+ strcpy (gOptions.VfrFileName, Argv[0]);
+ //
+ // We run the preprocessor on the VFR file to manage #include statements.
+ // Unfortunately the preprocessor does not allow you to specify the
+ // output name or path of the resultant .i file, so we have to do
+ // some work. Here we'll extract the basename of the VFR file, then
+ // append .i on the end.
+ //
+ strcpy (CopyStr, gOptions.VfrFileName);
+ Cptr = CopyStr + strlen (CopyStr) - 1;
+ for (;(Cptr > CopyStr) && (*Cptr != '\\') && (*Cptr != ':') && (*Cptr != '/'); Cptr--);
+ if (Cptr == CopyStr) {
+ strcpy (gOptions.PreprocessorOutputFileName, Cptr);
+ strcpy (gOptions.VfrBaseFileName, Cptr);
+ } else {
+ strcpy (gOptions.PreprocessorOutputFileName, Cptr+1);
+ strcpy (gOptions.VfrBaseFileName, Cptr+1);
+ }
+ for (Cptr = gOptions.PreprocessorOutputFileName; *Cptr && (*Cptr != '.'); Cptr++);
+ strcpy (Cptr, ".i");
+ //
+ // Terminate the vfr file basename at the extension
+ //
+ for (Cptr = gOptions.VfrBaseFileName; *Cptr && (*Cptr != '.'); Cptr++) {
+ }
+ *Cptr = 0;
+ //
+ // If they defined an output directory, prepend all output files
+ // with the working directory. Output files of interest:
+ // VfrListFileName -- list file
+ // IfrOutputFileName -- IFR bytes
+ // StringOutputFileName -- string bytes
+ // StringListFileName -- not used
+ // StringDefineFileName -- #defines of string identifiers
+ //
+ // We have two cases:
+ // 1. Output directory (-od) not specified, in which case output files
+ // go to the current working directory.
+ // 2. Output directory specified, in which case the output files
+ // go directly to the specified directory.
+ //
+ if (gOptions.OutputDirectory[0] == 0) {
+ CopyStr[0] = 0;
+#ifndef __GNUC__
+ _getcwd (CopyStr, sizeof (CopyStr));
+#else
+ getcwd (CopyStr, sizeof (CopyStr));
+#endif
+ strcpy (gOptions.OutputDirectory, CopyStr);
+ }
+ //
+ // Make sure output directory has a trailing backslash
+ //
+ if (gOptions.OutputDirectory[strlen (gOptions.OutputDirectory) - 1] != '\\' ||
+ gOptions.OutputDirectory[strlen (gOptions.OutputDirectory) - 1] != '/') {
+ strcat (gOptions.OutputDirectory, FILE_SEP_STRING);
+ }
+ //
+ // Create the base output file name as: path\base, copy it to all the output
+ // filenames, and then add the appropriate extension to each.
+ //
+ strcpy (gOptions.VfrListFileName, gOptions.OutputDirectory);
+ strcat (gOptions.VfrListFileName, gOptions.VfrBaseFileName);
+ strcpy (gOptions.IfrOutputFileName, gOptions.VfrListFileName);
+ strcat (gOptions.VfrListFileName, VFR_LIST_FILENAME_EXTENSION);
+ strcat (gOptions.IfrOutputFileName, VFR_BINARY_FILENAME_EXTENSION);
+ //
+ // We set a default list file name, so if they do not
+ // want a list file, null out the name now.
+ //
+ if (gOptions.CreateListFile == 0) {
+ gOptions.VfrListFileName[0] = 0;
+ }
+ return STATUS_SUCCESS;
+}
+static
+VOID
+Usage ()
+/*++
+
+Routine Description:
+ Print utility usage instructions
+
+Arguments:
+ None
+
+Returns:
+ None
+
+--*/
+{
+ int Index;
+ const char *Help[] = {
+ " ",
+ "VfrCompile version " VFR_COMPILER_VERSION,
+ " ",
+ " Usage: VfrCompile {options} [VfrFile]",
+ " ",
+ " where options include:",
+ " -? or -h prints this help",
+ " -l create an output IFR listing file",
+ " -i IncPath add IncPath to the search path for VFR included files",
+ " -od OutputDir deposit all output files to directory OutputDir (default=cwd)",
+ " -ibin create an IFR HII pack file",
+ " where parameters include:",
+ " VfrFile name of the input VFR script file",
+ " ",
+ NULL
+ };
+ for (Index = 0; Help[Index] != NULL; Index++) {
+ fprintf (stdout, "%s\n", Help[Index]);
+ }
+}
+
+>>
+
+
+#lexaction
+<<
+
+#include "EfiVfr.h"
+
+PARSER_LINE_DEFINITION *gLineDefinition = NULL;
+PARSER_LINE_DEFINITION *gLastLineDefinition = NULL;
+
+VOID
+AddFileLine (
+ char *TokenString,
+ UINT32 TokenLine
+ )
+/*++
+
+Routine Description:
+ During the lexer phase, if we encounter a #line statement output by
+ the preprocessor, this function gets called. We'll save off the info
+ for error reporting purposes. The preprocessor line information has the
+ form:
+
+ #line 3 "FileName.c"
+
+Arguments:
+ TokenString - the parsed string as shown above
+ TokenLine - the line number in the preprocessed output file
+
+Returns:
+ NA
+
+--*/
+{
+ PARSER_LINE_DEFINITION *LineDef;
+ CHAR8 *Cptr;
+
+ //
+ // Allocate a structure in which we can keep track of this line information.
+ //
+ LineDef = (PARSER_LINE_DEFINITION *)malloc (sizeof (PARSER_LINE_DEFINITION));
+ memset ((char *)LineDef, 0, sizeof (PARSER_LINE_DEFINITION));
+ LineDef->TokenLineNum = TokenLine;
+ LineDef->HashLineNum = atoi (TokenString + 6);
+ //
+ // Find the quotes in the filename, then allocate space in the line
+ // def structure for a copy of the filename. Finally, copy it without
+ // quotes to the line def.
+ //
+ for (Cptr = TokenString + 7; *Cptr && (*Cptr != '"'); Cptr++);
+ if (*Cptr == '"') {
+ LineDef->FileName = (CHAR8 *)malloc (strlen (Cptr));
+ Cptr++;
+ strcpy (LineDef->FileName, Cptr);
+ for (Cptr = LineDef->FileName; *Cptr && (*Cptr != '"'); Cptr++);
+ *Cptr = 0;
+ //
+ // Now add this new one to the list
+ //
+ if (gLineDefinition == NULL) {
+ gLineDefinition = LineDef;
+ } else {
+ gLastLineDefinition->Next = LineDef;
+ }
+ gLastLineDefinition = LineDef;
+ } else {
+ Error (PROGRAM_NAME, 0, 0, "invalid line definition in preprocessor output file", TokenString);
+ free (LineDef);
+ return;
+ }
+}
+char *
+ConvertLineNumber (
+ UINT32 *LineNum
+ )
+/*++
+
+Routine Description:
+ Given the line number in the preprocessor-output file, use the line number
+ information we've saved to determine the source file name and line number
+ where the code originally came from. This is required for error reporting.
+
+Arguments:
+ LineNum - the line number in the preprocessor-output file.
+
+Returns:
+ Returns a pointer to the source file name. Also returns the line number
+ in the provided LineNum argument
+
+--*/
+{
+ PARSER_LINE_DEFINITION *LineDef;
+ //
+ // Step through our linked list of #line information we saved off.
+ // For each one, look at its line number, and the line number of the
+ // next record, and see if the passed-in line number is in the range.
+ // If it is, then convert the line number to the appropriate line number
+ // of the original source file.
+ //
+ for (LineDef = gLineDefinition; LineDef != NULL; LineDef = LineDef->Next) {
+ //
+ // The given LineNum is the line number from the .i file.
+ // Find a line definition whose range includes this line number,
+ // convert the line number, and return the filename.
+ //
+ if (LineDef->TokenLineNum <= *LineNum) {
+ if (LineDef->Next != NULL) {
+ if (LineDef->Next->TokenLineNum > *LineNum) {
+ *LineNum = *LineNum - LineDef->TokenLineNum + LineDef->HashLineNum;
+ return LineDef->FileName;
+ }
+ } else {
+ //
+ // Last one in the list of line definitions, so has to be right
+ //
+ *LineNum = *LineNum - LineDef->TokenLineNum + LineDef->HashLineNum;
+ return LineDef->FileName;
+ }
+ }
+ }
+ return NULL;
+}
+
+>>
+
+//
+// Define a lexical class for parsing quoted strings. Basically
+// starts with a double quote, and ends with a double quote that
+// is not preceeded with a backslash.
+//
+#lexclass QUOTED_STRING
+#token TheString "~[\"]*\"" << mode (START); >>
+
+//
+// Define a lexical class for parsing "#pragma pack" statements.
+// We do this just for convenience (since we skip them here) so
+// that users can include some minimal .h files.
+//
+#lexclass PRAGMA_PACK
+#token "pack" << skip (); >>
+#token "[\ \t]" << skip (); >>
+#token "\(" << skip (); >>
+#token "[0-9]*" << skip (); >>
+#token "\)" << skip (); mode (START); >>
+
+//
+// Define a lexclass for skipping over C++ style comments
+//
+#lexclass CPP_COMMENT
+#token "~[\n]*" << skip (); >>
+#token "\n" << skip (); mode (START); newline (); >>
+
+//
+// Standard lexclass is START
+//
+#lexclass START
+
+//
+// Find start of C++ style comments
+//
+#token "//" << skip (); mode (CPP_COMMENT); >>
+
+//
+// Skip whitespace
+//
+#token "[\ \t]" << skip (); >>
+
+//
+// Skip over newlines, but count them
+//
+#token "\n" << skip (); newline (); >>
+
+//
+// Skip pragma pack statements
+//
+#token "\#pragma" << skip (); mode(PRAGMA_PACK); >>
+
+//
+// Skip over 'extern' in any included .H file
+//
+#token "extern" << skip (); >>
+
+//
+// Tokens for the different keywords. Syntax is:
+// TokenName("ErrorMessageText") "TokenString"
+// where:
+// TokenName is the token name (must be capitalized) that is used in the rules
+// ErrorMessageText is the string the compiler emits when it detects a syntax error
+// TokenString is the actual matching string used in the user script
+//
+#token LineDefinition "#line\ [0-9]+\ \"~[\"]+\"[\ \t]*\n" << AddFileLine (begexpr (), line ()); skip (); >>
+#token FormSet("formset") "formset"
+#token EndFormSet("endformset") "endformset"
+#token Title("title") "title"
+#token FormId("formid") "formid"
+#token OneOf("oneof") "oneof"
+#token Prompt("prompt") "prompt"
+#token OrderedList("orderedlist") "orderedlist"
+#token EndList("endlist") "endlist"
+#token EndForm("endform") "endform"
+#token EndOneOf("endoneof") "endoneof"
+#token Form("form") "form"
+#token Subtitle("subtitle") "subtitle"
+#token Help("help") "help"
+#token VarId("varid") "varid"
+#token Text("text") "text"
+#token Option("option") "option"
+#token Value("value") "value"
+#token Flags("flags") "flags"
+#token Date("date") "date"
+#token EndDate("enddate") "enddate"
+#token Year("year") "year"
+#token Month("month") "month"
+#token Day("day") "day"
+#token Time("time") "time"
+#token EndTime("endtime") "endtime"
+#token Hour("hour") "hour"
+#token Minute("minute") "minute"
+#token Second("second") "second"
+#token AND("AND") "AND"
+#token OR("OR") "OR"
+#token GrayOutIf("grayoutif") "grayoutif"
+#token NOT("NOT") "NOT"
+#token Label("label") "label"
+#token Timeout("timeout") "timeout"
+#token Inventory("inventory") "inventory"
+#token StringToken("STRING_TOKEN") "STRING_TOKEN"
+#token NonNvDataMap("_NON_NV_DATA_MAP") "_NON_NV_DATA_MAP"
+#token Struct("struct") "struct"
+#token Uint64("UINT64") "UINT64"
+#token Uint32("UINT32") "UINT32"
+#token Uint16("UINT16") "UINT16"
+#token Char16("CHAR16") "CHAR16"
+#token Uint8("UINT8") "UINT8"
+#token Guid("guid") "guid"
+#token CheckBox("checkbox") "checkbox"
+#token EndCheckBox("endcheckbox") "endcheckbox"
+#token Numeric("numeric") "numeric"
+#token EndNumeric("endnumeric") "endnumeric"
+#token Minimum("minimum") "minimum"
+#token Maximum("maximum") "maximum"
+#token Step("step") "step"
+#token Default("default") "default"
+#token Password("password") "password"
+#token EndPassword("endpassword") "endpassword"
+#token String("string") "string"
+#token EndString("endstring") "endstring"
+#token MinSize("minsize") "minsize"
+#token MaxSize("maxsize") "maxsize"
+#token Encoding("encoding") "encoding"
+#token SuppressIf("suppressif") "suppressif"
+#token Hidden("hidden") "hidden"
+#token Goto("goto") "goto"
+#token InconsistentIf "inconsistentif"
+#token EndIf("endif") "endif"
+#token IdEqId("ideqid") "ideqid"
+#token IdEqVal("ideqval") "ideqval"
+#token VarEqVal("vareqval") "vareqval"
+#token Var("var") "var"
+#token IdEqValList("ideqvallist") "ideqvallist"
+#token Length("length") "length"
+#token Values("values") "values"
+#token Key("key") "key"
+#token DefaultFlag("DEFAULT") "DEFAULT"
+#token ManufacturingFlag("MANUFACTURING") "MANUFACTURING"
+#token InteractiveFlag("INTERACTIVE") "INTERACTIVE"
+#token NVAccessFlag("NV_ACCESS") "NV_ACCESS"
+#token ResetRequiredFlag("RESET_REQUIRED") "RESET_REQUIRED"
+#token LateCheckFlag("LATE_CHECK") "LATE_CHECK"
+#token Class("class") "class"
+#token Subclass("subclass") "subclass"
+#token TypeDef("typedef") "typedef"
+#token Restore("restore") "restore"
+#token Save("save") "save"
+#token Defaults("defaults") "defaults"
+#token Banner("banner") "banner"
+#token Align("align") "align"
+#token Left("left") "left"
+#token Right("right") "right"
+#token Center("center") "center"
+#token Line("line") "line"
+#token VarStore("varstore") "varstore"
+#token Name("name") "name"
+#token Oem("oem") "oem"
+#token True("TRUE") "TRUE"
+#token False("FALSE") "FALSE"
+#token GreaterThan(">") ">"
+#token GreaterEqual(">=") ">="
+#token LessThan("<") "<"
+#token LessEqual("<=") "<="
+
+//
+// Define the class and subclass tokens
+//
+#token ClassNonDevice("NONDEVICE") "NON_DEVICE"
+#token ClassDiskDevice("DISK_DEVICE") "DISK_DEVICE"
+#token ClassVideoDevice("VIDEO_DEVICE") "VIDEO_DEVICE"
+#token ClassNetworkDevice("NETWORK_DEVICE") "NETWORK_DEVICE"
+#token ClassInputDevice("INPUT_DEVICE") "INPUT_DEVICE"
+#token ClassOnBoardDevice("ONBOARD_DEVICE") "ONBOARD_DEVICE"
+#token ClassOtherDevice("OTHER_DEVICE") "OTHER_DEVICE"
+
+#token SubclassSetupApplication("SETUP_APPLICATION") "SETUP_APPLICATION"
+#token SubclassGeneralApplication("GENERAL_APPLICATION") "GENERAL_APPLICATION"
+#token SubclassFrontPage("FRONT_PAGE") "FRONT_PAGE"
+#token SubclassSingleUse("SINGLE_USE") "SINGLE_USE"
+
+#token LanguageIdentifier("language identifier") "[a-z][a-z][a-z]" // 3 lowercase characters
+#token StringIdentifier("string identifier") "[A-Za-z_][A-Za-z_0-9]*"
+#token Number("numeric value") "(0x[0-9A-Fa-f]+) | [0-9]+"
+#token OpenBrace("{") "\{"
+#token CloseBrace("}") "\}"
+#token OpenParen("(") "\("
+#token CloseParen(")") "\)"
+#token OpenBracket("[") "\["
+#token CloseBracket("]") "\]"
+
+//
+// Define all other invalid characters so that they get through the lexical phase
+// and we can catch them during the parse phase. We get much better error
+// messages then.
+//
+#token InvalidCharacters("invalid characters") "~[;:=,\.\|]"
+
+//
+// This is the overall definition of a VFR form definition script.
+//
+program :
+ ( dataStructDefinition )*
+ formSetStatement
+ ( vfrStatementVarStore )*
+ ( formDefinition )*
+ EFS:EndFormSet ";" << WriteOpByte (EFS->getLine(), EFI_IFR_END_FORM_SET_OP); >>
+ "@" // end of file
+ ;
+
+formSetStatement :
+ FS:FormSet << WriteOpByte (FS->getLine(), EFI_IFR_FORM_SET_OP); >>
+ Guid "="
+ OpenBrace
+ G1:Number ","
+ G2:Number ","
+ G3:Number ","
+ OpenBrace
+ G4:Number ","
+ G5:Number ","
+ G6:Number ","
+ G7:Number ","
+ G8:Number ","
+ G9:Number ","
+ G10:Number ","
+ G11:Number
+ CloseBrace
+ CloseBrace << WriteGuidValue (G1->getLine (), G1->getText (), G2->getText (), G3->getText (),
+ G4->getText (), G5->getText (), G6->getText (), G7->getText (),
+ G8->getText (), G9->getText (), G10->getText (), G11->getText ()
+ );
+ >>
+ ","
+ Title "=" getStringId ","
+ Help "=" getStringId ","
+ //
+ // insert padding for an EFI_PHYSICAL_ADDRESS (UINT64)
+ //
+ << WriteDWord (0, 0); WriteDWord (0, 0); >>
+ Class "=" CVAL:classDefinition "," << WriteClass (); >>
+ Subclass "=" SVAL:subclassDefinition "," << WriteSubclass (); >>
+ << WriteWord (mNvDataStructSize); >>
+ ;
+
+//
+// A form can be of multiple classes, thus allow CLASS_A | CLASS_B | CLASS_C
+//
+classDefinition :
+ validClassNames ( "\|" validClassNames )*
+ ;
+
+validClassNames :
+ CND:ClassNonDevice << SetClass (CND->getLine(), EFI_NON_DEVICE_CLASS); >>
+ | CDD:ClassDiskDevice << SetClass (CDD->getLine(), EFI_DISK_DEVICE_CLASS); >>
+ | CVD:ClassVideoDevice << SetClass (CVD->getLine(), EFI_VIDEO_DEVICE_CLASS); >>
+ | CNW:ClassNetworkDevice << SetClass (CNW->getLine(), EFI_NETWORK_DEVICE_CLASS); >>
+ | CID:ClassInputDevice << SetClass (CID->getLine(), EFI_INPUT_DEVICE_CLASS); >>
+ | COB:ClassOnBoardDevice << SetClass (COB->getLine(), EFI_ON_BOARD_DEVICE_CLASS); >>
+ | COD:ClassOtherDevice << SetClass (COD->getLine(), EFI_OTHER_DEVICE_CLASS); >>
+ | CNUM:Number << SetClass (CNUM->getLine(), GetNumber (CNUM->getText(), CNUM->getLine(), 4)); >>
+ ; << PrintErrorMessage (LT(1)->getLine(), LT(1)->getText(), "invalid class"); >>
+
+//
+// A form can only be of one subclass type.
+//
+subclassDefinition :
+ SSA:SubclassSetupApplication << SetSubclass (SSA->getLine(), EFI_SETUP_APPLICATION_SUBCLASS); >>
+ | SGA:SubclassGeneralApplication << SetSubclass (SGA->getLine(), EFI_GENERAL_APPLICATION_SUBCLASS); >>
+ | SFP:SubclassFrontPage << SetSubclass (SFP->getLine(), EFI_FRONT_PAGE_SUBCLASS); >>
+ | SSU:SubclassSingleUse << SetSubclass (SSU->getLine(), EFI_SINGLE_USE_SUBCLASS); >>
+ | SNUM:Number << SetSubclass (SNUM->getLine(), GetNumber (SNUM->getText(), SNUM->getLine(), 4)); >>
+ ; << PrintErrorMessage (LT(1)->getLine(), LT(1)->getText(), "invalid subclass"); >>
+
+//
+// Parse a C type data structure for storing VFR setup data. Allow:
+// typedef struct _XXX_ {
+// (fields)
+// } MY_NV_DATA;
+//
+dataStructDefinition :
+ << int IsNonNV = 0; >>
+ { TypeDef }
+ S:Struct
+ (
+ NonNvDataMap << IsNonNV = 1; >>
+ |
+ { StringIdentifier }
+ ) << StartStructDefinition (IsNonNV, S->getLine()); >>
+ OpenBrace
+ dataStructFields
+ CloseBrace NAME:StringIdentifier << EndStructDefinition (NAME->getText(), NAME->getLine()); >>
+ ";"
+ ;
+
+//
+// Parse a C type data structure for defining data that is not stored in NV.
+// typedef struct _NON_NV_DATA_MAP {
+// (fields)
+// } NON_NV_DATA_MAP;
+//
+nonNvDataStructDefinition :
+ { TypeDef }
+ Struct NonNvDataMap
+ { StringIdentifier }
+ OpenBrace
+ dataStructFields
+ CloseBrace NAME:StringIdentifier << AddStructField (NAME->getText(), NAME->getLine(), 0, 0, 0); >>
+ ";"
+ ;
+
+dataStructFields :
+ ( dataStructField64 | dataStructField32 | dataStructField16 | dataStructField8 ) *
+ ;
+
+//*****************************************************************************
+//
+// PARSE:
+// UINT64 Name[4];
+// UINT64 Name;
+//
+// Used while parsing the NV data map structures.
+//
+dataStructField64 :
+ << int ArrayLength = 1; char IsArray = 0; >>
+ "UINT64"
+ NAME:StringIdentifier
+ ( ";" | OpenBracket IVal:Number CloseBracket ";" << ArrayLength = GetNumber (IVal->getText(), IVal->getLine(), 4); IsArray = 1; >> )
+ << AddStructField (NAME->getText(), NAME->getLine(), 8, ArrayLength, IsArray); >>
+ ;
+
+//*****************************************************************************
+//
+// PARSE:
+// UINT32 Name[4];
+// UINT32 Name;
+//
+// Used while parsing the NV data map structures.
+//
+dataStructField32 :
+ << int ArrayLength = 1; char IsArray = 0; >>
+ "UINT32"
+ NAME:StringIdentifier
+ ( ";" | OpenBracket IVal:Number CloseBracket ";" << ArrayLength = GetNumber (IVal->getText(), IVal->getLine(), 4); IsArray = 1; >> )
+ << AddStructField (NAME->getText(), NAME->getLine(), 4, ArrayLength, IsArray); >>
+ ;
+
+//*****************************************************************************
+//
+// PARSE:
+// UINT16 Name[4];
+// UINT16 Name;
+//
+// Used while parsing the NV data map structures.
+//
+dataStructField16 :
+ << int ArrayLength = 1; char IsArray = 0; >>
+ ( "UINT16" | "CHAR16" )
+ NAME:StringIdentifier
+ ( ";" | OpenBracket IVal:Number CloseBracket ";" << ArrayLength = GetNumber (IVal->getText(), IVal->getLine(), 4); IsArray = 1; >> )
+ << AddStructField (NAME->getText(), NAME->getLine(), 2, ArrayLength, IsArray); >>
+ ;
+
+//*****************************************************************************
+//
+// PARSE:
+// UINT8 Name[4];
+// UINT8 Name;
+//
+// Used while parsing the NV data map structures.
+//
+dataStructField8 :
+ << int ArrayLength = 1; char IsArray = 0; >>
+ "UINT8"
+ NAME:StringIdentifier
+ ( ";" | OpenBracket IVal:Number CloseBracket ";" << ArrayLength = GetNumber (IVal->getText(), IVal->getLine(), 4); IsArray = 1; >> )
+ << AddStructField (NAME->getText(), NAME->getLine(), 1, ArrayLength, IsArray); >>
+ ;
+
+//*****************************************************************************
+//
+// PARSE:
+// form formid = 1,
+// title = STRING_TOKEN(STR_FORM_TITLE);
+// -- form statements --
+// endform;
+//
+// The Form ID cannot be 0
+//
+formDefinition :
+ FRM:Form FormId << WriteOpByte (FRM->getLine(), EFI_IFR_FORM_OP); >>
+ "="
+ VAL:Number << WriteWord (GetNumber (VAL->getText(), VAL->getLine(), 2)); AddFormId (GetNumber (VAL->getText(), VAL->getLine(), 2), VAL->getLine()); >>
+ ","
+ Title "=" getStringId ";" // writes string identifier
+ ( vfrStatements )*
+ ENDF:EndForm ";" << WriteOpByte (ENDF->getLine(), EFI_IFR_END_FORM_OP); >>
+ ;
+
+//
+// VFR statements in a formset
+//
+vfrStatements :
+ vfrStatementSubTitle |
+ vfrStatementOneOf |
+ vfrStatementTextText |
+ vfrStatementCheckBox |
+ vfrStatementNumeric |
+ vfrStatementDate |
+ vfrStatementTime |
+ vfrStatementPassword |
+ vfrStatementString |
+ vfrStatementSuppressIf |
+ vfrStatementHidden |
+ vfrStatementGoto |
+ vfrStatementGrayOutIf |
+ vfrStatementInconsistentIf |
+ vfrStatementLabel |
+ vfrStatementBanner |
+ vfrStatementInventory |
+ vfrStatementOrderedList |
+ vfrStatementOem |
+ vfrStatementSaveRestoreDefaults
+ ;
+
+//*****************************************************************************
+//
+// PARSE:
+// label 100;
+//
+vfrStatementLabel :
+ OPID:Label << WriteOpByte (OPID->getLine(), EFI_IFR_LABEL_OP); >>
+ VAL:Number <<
+ WriteWord (GetNumber (VAL->getText(), VAL->getLine(), 2));
+ AddLabel (GetNumber (VAL->getText(), VAL->getLine(), 2), VAL->getLine());
+ >>
+ ";"
+ ;
+
+//*****************************************************************************
+//
+// PARSE:
+// oem 0x12, 0x34, 0x56;
+//
+vfrStatementOem :
+ OPID:Oem << WriteOpByte (OPID->getLine(), EFI_IFR_OEM_DEFINED_OP); >>
+ ( VAL1:Number << WriteByte (GetNumber (VAL1->getText(), VAL1->getLine(), 1), 0); >> )
+ ( "," VAL2:Number << WriteByte (GetNumber (VAL2->getText(), VAL2->getLine(), 1), 0); >> )*
+ ";"
+ ;
+
+//*****************************************************************************
+//
+// PARSE:
+// inconsistentif NOT .... AND NOT .... OR ... endif;
+//
+vfrStatementInconsistentIf :
+ << ResetFlags (); >>
+ IIFOP:InconsistentIf << WriteOpByte (IIFOP->getLine(), EFI_IFR_INCONSISTENT_IF_OP); >>
+ Prompt "=" getStringId ","
+ {
+ FF:Flags "=" flagsField ( "\|" flagsField )* ","
+ }
+ << WriteFlags (); >> // write the flags field
+ vfrBooleanExpression
+ EOP:EndIf ";" << WriteOpByte (EOP->getLine(), EFI_IFR_END_IF_OP); >>
+ ;
+
+//*****************************************************************************
+//
+// PARSE:
+// TRUE AND (ideqval SomeStruct.SomeMember >= 0x10 OR
+// ideqid SomeStruct.SomeMember < SomeStruct.SomeOtherMember) AND
+// (ideqlist SomeStruct.SomeOtherMember == 0x10, 0x20, 0x30 OR
+// vareqval var(VAR_EQ_TEST_NAME) == 0x1)
+//
+// For supporting complex express, divide the vfrBooleanExpression to two parts
+// so that pred-LL(k) parser can parse incrementally.
+//
+vfrBooleanExpression :
+ leftPartVfrBooleanExp { rightPartVfrBooleanExp }
+ ;
+
+leftPartVfrBooleanExp :
+ OpenParen vfrBooleanExpression CloseParen |
+ (ideqval | ideqid | ideqvallist | vareqval | truefalse) |
+ NOPID:NOT leftPartVfrBooleanExp << WriteOpByte (NOPID->getLine(), EFI_IFR_NOT_OP); >>
+ ;
+
+rightPartVfrBooleanExp :
+ AOPID:AND vfrBooleanExpression << WriteOpByte (AOPID->getLine(), EFI_IFR_AND_OP); >> |
+ OOPID:OR vfrBooleanExpression << WriteOpByte (OOPID->getLine(), EFI_IFR_OR_OP); >>
+ ;
+
+//*****************************************************************************
+//
+// PARSE:
+// TRUE
+//
+truefalse :
+ TOPID:True << WriteOpByte (TOPID->getLine(), EFI_IFR_TRUE_OP); >> |
+ FOPID:False << WriteOpByte (FOPID->getLine(), EFI_IFR_FALSE_OP); >>
+ ;
+
+//*****************************************************************************
+//
+// PARSE:
+// varstore MY_STRUCT_NAME, key = 0x1234, name = "MyVariableName", guid = {...};
+//
+vfrStatementVarStore :
+ OP:VarStore << WriteOpByte (OP->getLine(), EFI_IFR_VARSTORE_OP); >>
+ STRUCT_NAME:StringIdentifier ","
+ Key "=" KNUM:Number ","
+ Name "=" VAR_NAME:StringIdentifier ","
+ Guid "="
+ OpenBrace
+ G1:Number ","
+ G2:Number ","
+ G3:Number ","
+ OpenBrace
+ G4:Number ","
+ G5:Number ","
+ G6:Number ","
+ G7:Number ","
+ G8:Number ","
+ G9:Number ","
+ G10:Number ","
+ G11:Number
+ CloseBrace
+ CloseBrace << WriteGuidValue (G1->getLine (), G1->getText (), G2->getText (), G3->getText (),
+ G4->getText (), G5->getText (), G6->getText (), G7->getText (),
+ G8->getText (), G9->getText (), G10->getText (), G11->getText ()
+ );
+ WriteWord (GetNumber (KNUM->getText(), KNUM->getLine(), 2));
+ AddVarStore (STRUCT_NAME->getText(), VAR_NAME->getText(), GetNumber (KNUM->getText(), KNUM->getLine(), 2), STRUCT_NAME->getLine());
+ >>
+
+ ";"
+ ;
+
+//*****************************************************************************
+//
+// PARSE:
+// vareqval var(0x100) == 0x20
+//
+vareqval :
+ OPID:VarEqVal << WriteOpByte (OPID->getLine(), EFI_IFR_EQ_VAR_VAL_OP); >>
+ Var OpenParen
+ VAR:Number << WriteWord (GetNumber (VAR->getText(), VAR->getLine(), 2)); >>
+ CloseParen
+ compareNumber
+ ;
+
+ideqval :
+ OPID:IdEqVal << WriteOpByte (OPID->getLine(), EFI_IFR_EQ_ID_VAL_OP); >>
+ vfrStructFieldName[0]
+ compareNumber
+ ;
+
+//*****************************************************************************
+//
+// PARSE:
+// ideqid MyNVData3.Field16A == MyNVData3.Field16B
+//
+// NOTE: Before processing the second variable store in the ideqid statement, set a global flag
+// so that when we parse the second variable we set the secondary variable store id.
+//
+ideqid :
+ OPID:IdEqId << WriteOpByte (OPID->getLine(), EFI_IFR_EQ_ID_ID_OP); >>
+ vfrStructFieldName[0]
+ compareVfrStructFieldNameNL0
+ ;
+
+//*****************************************************************************
+//
+// compareNumber is the combination of compare operation and Number
+//
+compareNumber :
+ (
+ "=="
+ VAL1:Number << WriteWord (GetNumber (VAL1->getText(), VAL1->getLine(), 2)); >>
+ ) |
+ (
+ GTOPID:GreaterThan
+ VAL2:Number << WriteWord (GetNumber (VAL2->getText(), VAL2->getLine(), 2));
+ WriteOpByte (GTOPID->getLine(), EFI_IFR_GT_OP); >>
+ ) |
+ (
+ GEOPID:GreaterEqual
+ VAL3:Number << WriteWord (GetNumber (VAL3->getText(), VAL3->getLine(), 2));
+ WriteOpByte (GEOPID->getLine(), EFI_IFR_GE_OP); >>
+ ) |
+ (
+ LTOPID:LessThan
+ VAL4:Number << WriteWord (GetNumber (VAL4->getText(), VAL4->getLine(), 2));
+ WriteOpByte (LTOPID->getLine(), EFI_IFR_GE_OP);
+ WriteOpByte (LTOPID->getLine(), EFI_IFR_NOT_OP); >>
+ ) |
+ (
+ LEOPID:LessEqual
+ VAL5:Number << WriteWord (GetNumber (VAL5->getText(), VAL5->getLine(), 2));
+ WriteOpByte (LEOPID->getLine(), EFI_IFR_GT_OP);
+ WriteOpByte (LEOPID->getLine(), EFI_IFR_NOT_OP); >>
+ )
+ ;
+
+//*****************************************************************************
+//
+// compareVfrStructFieldNameNL0 is the combination of compare operation and vfrStructFieldNameNL[0]
+//
+compareVfrStructFieldNameNL0 :
+ (
+ "==" << mIdEqIdStmt = 1; >>
+ vfrStructFieldNameNL[0] << mIdEqIdStmt = 0; >>
+ ) |
+ (
+ GTOPID:GreaterThan << mIdEqIdStmt = 1; >>
+ vfrStructFieldNameNL[0] << mIdEqIdStmt = 0;
+ WriteOpByte (GTOPID->getLine(), EFI_IFR_GT_OP); >>
+ ) |
+ (
+ GEOPID:GreaterEqual << mIdEqIdStmt = 1; >>
+ vfrStructFieldNameNL[0] << mIdEqIdStmt = 0;
+ WriteOpByte (GEOPID->getLine(), EFI_IFR_GE_OP); >>
+ ) |
+ (
+ LTOPID:LessThan << mIdEqIdStmt = 1; >>
+ vfrStructFieldNameNL[0] << mIdEqIdStmt = 0;
+ WriteOpByte (LTOPID->getLine(), EFI_IFR_GE_OP);
+ WriteOpByte (LTOPID->getLine(), EFI_IFR_NOT_OP); >>
+ ) |
+ (
+ LEOPID:LessEqual << mIdEqIdStmt = 1; >>
+ vfrStructFieldNameNL[0] << mIdEqIdStmt = 0;
+ WriteOpByte (LEOPID->getLine(), EFI_IFR_GT_OP);
+ WriteOpByte (LEOPID->getLine(), EFI_IFR_NOT_OP); >>
+ )
+ ;
+
+
+ideqvallist :
+ OPID:IdEqValList << WriteOpByte (OPID->getLine(), EFI_IFR_EQ_ID_LIST_OP); >>
+ vfrStructFieldName[0]
+ "=="
+ ( VAL:Number << QueueIdEqValList (GetNumber (VAL->getText(), VAL->getLine(), 2)); >> ) +
+ << FlushQueueIdEqValList(); >>
+ ;
+
+vfrStatementGoto :
+ << UINT32 LineNum, KeyValue = 0; ResetFlags (); >>
+ IDG:Goto << WriteOpByte (IDG->getLine(), EFI_IFR_REF_OP); >>
+ VAL:Number "," << WriteWord (GetNumber (VAL->getText(), VAL->getLine(), 2));
+ AddGotoReference (GetNumber (VAL->getText(), VAL->getLine(), 2), VAL->getLine());
+ >>
+ KP:Prompt "=" getStringId "," << LineNum = KP->getLine(); >>
+ Help "=" getStringId
+ {
+ ","
+ FF:Flags "=" flagsField ( "\|" flagsField )* << LineNum = FF->getLine(); >>
+ }
+ {
+ "," Key "=" KNUM:Number << LineNum = KNUM->getLine(); KeyValue = GetNumber(KNUM->getText(), LineNum, 2); >>
+ }
+ << WriteFlagsKey (KeyValue, LineNum); >>
+ ";"
+ ;
+
+vfrStatementHidden :
+ IDH:Hidden << WriteOpByte (IDH->getLine(), EFI_IFR_HIDDEN_OP); >>
+ Value "="
+ VAL:Number "," << WriteWord (GetNumber (VAL->getText(), VAL->getLine(), 2)); >>
+ Key "="
+ KVAL:Number << WriteWord (GetNumber (KVAL->getText(), KVAL->getLine(), 2)); >>
+ ";"
+ ;
+
+//*****************************************************************************
+//
+// PARSE:
+// suppressif <boolean_expression> { grayoutif } <statements>+ endif;
+// Note:
+// You can have: suppressif:grayoutif:statements:endif
+// suppressif:grayoutif:endif -- serves no purpose
+// suppressif:statements:endif
+// suppressif:endif -- serves no purpose
+//
+vfrStatementSuppressIf :
+ << ResetFlags (); >>
+ OPID:SuppressIf << WriteOpByte (OPID->getLine(), EFI_IFR_SUPPRESS_IF_OP); SetIfStart (OPID->getLine()); >>
+ {
+ FF:Flags "=" flagsField ( "\|" flagsField )* ","
+ }
+ << WriteFlags (); >> // write the flags field
+ vfrBooleanExpression
+ ";"
+ { suppressIfGrayOutIf } ( suppressIfAndGrayoutIfSubstatements )+
+ ENDOP:EndIf ";" << WriteOpByte (ENDOP->getLine(), EFI_IFR_END_IF_OP); SetIfStart (0); >>
+ ;
+
+//
+// This is the form for a grayoutif nested in a suppressif statement
+//
+suppressIfGrayOutIf :
+ << ResetFlags (); >>
+ OPID:GrayOutIf << WriteOpByte (OPID->getLine(), EFI_IFR_GRAYOUT_IF_OP); >>
+ {
+ FF:Flags "=" flagsField ( "\|" flagsField )* ","
+ }
+ << WriteFlags (); >> // write the flags field
+ vfrBooleanExpression
+ ";"
+ ;
+
+//*****************************************************************************
+//
+// PARSE:
+// grayoutif { flags = n, } <boolean_expression> endif;
+// Note:
+// You can have: grayoutif:suppressif:statements:endif
+// grayoutif:statements:endif
+//
+//
+vfrStatementGrayOutIf :
+ << ResetFlags (); >>
+ OPID:GrayOutIf << WriteOpByte (OPID->getLine(), EFI_IFR_GRAYOUT_IF_OP); SetIfStart (OPID->getLine()); >>
+ {
+ FF:Flags "=" flagsField ( "\|" flagsField )* ","
+ }
+ << WriteFlags (); >> // write the flags field
+ vfrBooleanExpression
+ ";"
+ { grayoutIfSuppressIf } ( suppressIfAndGrayoutIfSubstatements )+
+ ENDOP:EndIf ";" << WriteOpByte (ENDOP->getLine(), EFI_IFR_END_IF_OP); SetIfStart (0); >>
+ ;
+
+//
+// This is the format for a suppressif nested in a grayoutif
+//
+grayoutIfSuppressIf :
+ << ResetFlags (); >>
+ OPID:SuppressIf << WriteOpByte (OPID->getLine(), EFI_IFR_SUPPRESS_IF_OP); >>
+ {
+ FF:Flags "=" flagsField ( "\|" flagsField )* ","
+ }
+ << WriteFlags (); >> // write the flags field
+ vfrBooleanExpression
+ ";"
+ ;
+
+//
+// These are the VFR statements that are valid inside a suppressif or grayoutif statement.
+//
+suppressIfAndGrayoutIfSubstatements :
+ vfrStatementOneOf |
+ vfrStatementTextText |
+ vfrStatementCheckBox |
+ vfrStatementNumeric |
+ vfrStatementDate |
+ vfrStatementTime |
+ vfrStatementPassword |
+ vfrStatementString |
+ vfrStatementHidden |
+ vfrStatementGoto |
+ vfrStatementLabel |
+ vfrStatementInventory |
+ vfrStatementOrderedList |
+ vfrStatementSaveRestoreDefaults
+ ;
+
+//*****************************************************************************
+//
+// PARSE:
+//
+// password varid = MyNvData.Password,
+// prompt = STRING_TOKEN(STR_PASSWORD_PROMPT),
+// help = STRING_TOKEN(STR_PASSWORD_HELP),
+// minsize = 6,
+// maxsize = 20,
+// encoding = 1,
+// endpassword;
+
+vfrStatementPassword :
+ << UINT32 KeyValue = 0; UINT32 LineNum; ResetFlags (); >>
+ IDPW:Password << WriteOpByte (IDPW->getLine(), EFI_IFR_PASSWORD_OP); >>
+ VarId "=" vfrStructFieldNameArray[0] ","
+ Prompt "=" getStringId ","
+ KH:Help "=" getStringId "," << LineNum = KH->getLine(); >>
+ {
+ FF:Flags "=" flagsField ( "\|" flagsField )* "," << LineNum = FF->getLine(); >>
+ }
+ {
+ Key "=" KNUM:Number "," << LineNum = KNUM->getLine(); KeyValue = GetNumber(KNUM->getText(), LineNum, 2); >>
+ }
+ << WriteFlagsKey (KeyValue, LineNum); >>
+ MinSize "=" MIN:Number "," << WriteByte (GetNumber (MIN->getText(), MIN->getLine(), 1), 0); >>
+ MaxSize "=" MAX:Number "," << WriteByte (GetNumber (MAX->getText(), MAX->getLine(), 1), 0); >>
+ Encoding "=" ENC:Number "," << WriteWord (GetNumber (ENC->getText(), ENC->getLine(), 2)); >>
+ EndPassword ";"
+ ;
+
+//*****************************************************************************
+//
+// PARSE:
+//
+// string varid = MyNv.String,
+// prompt = STRING_TOKEN(STR_STRING_PROMPT),
+// help = STRING_TOKEN(STR_STRING_HELP),
+// flags = INTERACTIVE,
+// key = 0x1234,
+// minsize = 6,
+// maxsize = 0x14,
+// endstring;
+//
+// Since flags and key are optional, we can't use Flags->getLine(). Therefore for error
+// reporting we save the line number of the "help" keyword.
+//
+vfrStatementString :
+ << unsigned int KeyValue = 0; UINT32 LineNum; ResetFlags (); >>
+ IDS:String << WriteOpByte (IDS->getLine(), EFI_IFR_STRING_OP); >>
+ VarId "=" vfrStructFieldNameArray[0] ","
+ Prompt "=" getStringId ","
+ KH:Help "=" getStringId "," << LineNum = KH->getLine(); >>
+ {
+ FF:Flags "="
+ flagsField ( "\|" flagsField )* << LineNum = FF->getLine(); >>
+ ","
+ }
+ {
+ Key "=" KNUM:Number "," << LineNum = KNUM->getLine(); KeyValue = GetNumber(KNUM->getText(), LineNum, 2); >>
+ }
+ << WriteFlagsKey (KeyValue, LineNum); >>
+ MinSize "=" MIN:Number "," << WriteByte (GetNumber (MIN->getText(), MIN->getLine(), 1), 0); >>
+ MaxSize "=" MAX:Number "," << WriteByte (GetNumber (MAX->getText(), MAX->getLine(), 1), 0); >>
+ EndString ";"
+ ;
+
+//*****************************************************************************
+//
+// PARSE:
+// numeric varid = MyIfrNVData.HowOldAreYouInYears,
+// prompt = STRING_TOKEN(STR_NUMERIC_PROMPT),
+// help = STRING_TOKEN(STR_NUMERIC_HELP),
+// flags = INTERACTIVE, // flags is optional
+// key = 0x1234, // key is optional if (flags & INTERACTIVE = 0)
+// minimum = 0x0,
+// maximum = 0xf0,
+// step = 1, // step is option, and step=1 if not specified
+// default = 0; // default is optional, and default=minimum if not specified
+// endnumeric;
+//
+// Make flags and key optional. However if flags includes INTERACTIVE, then a key is required.
+// That check is done in WriteFlagsKey() function.
+//
+vfrStatementNumeric :
+ << UINT32 LineNum, KeyValue = 0; ResetFlags (); >>
+ IDN:Numeric << WriteOpByte (IDN->getLine(), EFI_IFR_NUMERIC_OP); >>
+ VarId "=" vfrStructFieldName[2] ","
+ Prompt "=" getStringId ","
+ KH:Help "=" getStringId "," << LineNum = KH->getLine(); >>
+ {
+ FF:Flags "=" flagsField ( "\|" flagsField )* "," << LineNum = FF->getLine (); >>
+ }
+ {
+ Key "=" KNUM:Number "," << LineNum = KNUM->getLine(); KeyValue = GetNumber(KNUM->getText(), LineNum, 2); >>
+ }
+ << WriteFlagsKey (KeyValue, LineNum); >>
+ minMaxStepDefault
+ EndNumeric ";" << WriteMinMaxStepDefault (); >>
+ ;
+
+//
+// Parse minimum/maximum/step/default statements. Special cases:
+// - if step not specified, then the value is 1
+// - if default not specified, then the value is the min value specified
+// - if max < min, print a warning and swap the values (changes default too)
+//
+minMaxStepDefault :
+ << InitMinMaxStepDefault (); >>
+ Minimum "=" MIN:Number "," << SetMinMaxStepDefault (GetNumber (MIN->getText(), MIN->getLine(), 2), 0, MIN->getLine()); >>
+ Maximum "=" MAX:Number "," << SetMinMaxStepDefault (GetNumber (MAX->getText(), MAX->getLine(), 2), 1, MAX->getLine()); >>
+ { Step "=" STEP:Number "," << SetMinMaxStepDefault (GetNumber (STEP->getText(), STEP->getLine(), 2), 2, STEP->getLine()); >> }
+ { Default "=" DEF:Number "," << SetMinMaxStepDefault (GetNumber (DEF->getText(), DEF->getLine(), 2), 3, DEF->getLine()); >> }
+ ;
+
+
+//*****************************************************************************
+//
+// PARSE:
+//
+// date year varid = Date.Year, // "Date.Year" is a special case we recognize
+// prompt = STRING_TOKEN(STR_DATE_PROMPT),
+// help = STRING_TOKEN(STR_DATE_YEAR_HELP),
+// minimum = 1939,
+// maximum = 2101,
+// step = 1,
+// default = 1964,
+//
+// month varid = Date.Month,
+// prompt = STRING_TOKEN(STR_DATE_PROMPT),
+// help = STRING_TOKEN(STR_DATE_MONTH_HELP),
+// minimum = 1,
+// maximum = 12,
+// step = 1,
+// default = 1,
+//
+// day varid = Date.Day,
+// prompt = STRING_TOKEN(STR_DATE_PROMPT),
+// help = STRING_TOKEN(STR_DATE_DAY_HELP),
+// minimum = 1,
+// maximum = 31,
+// step = 0x1,
+// default = 1,
+//
+// enddate;
+//
+vfrStatementDate :
+ Date
+ IDY:Year VarId "=" << WriteOpByte (IDY->getLine(), EFI_IFR_DATE_OP); >>
+ vfrStructFieldName[2] ","
+ dateTimeSubStatement
+ IDM:Month VarId "=" << WriteOpByte (IDM->getLine(), EFI_IFR_DATE_OP); >>
+ vfrStructFieldName[2] ","
+ dateTimeSubStatement
+ IDD:Day VarId "=" << WriteOpByte (IDD->getLine(), EFI_IFR_DATE_OP); >>
+ vfrStructFieldName[2] ","
+ dateTimeSubStatement
+ EndDate ";"
+ ;
+
+vfrStatementTime :
+ Time
+ IDH:Hour VarId "=" << WriteOpByte (IDH->getLine(), EFI_IFR_TIME_OP); >>
+ vfrStructFieldName[2] ","
+ dateTimeSubStatement
+ IDM:Minute VarId "=" << WriteOpByte (IDM->getLine(), EFI_IFR_TIME_OP); >>
+ vfrStructFieldName[2] ","
+ dateTimeSubStatement
+ IDS:Second VarId "=" << WriteOpByte (IDS->getLine(), EFI_IFR_TIME_OP); >>
+ vfrStructFieldName[2] ","
+ dateTimeSubStatement
+ EndTime ";"
+ ;
+
+//*****************************************************************************
+//
+// PARSE:
+//
+// text text = STRING_ID;
+// text text = STRING_ID, text = STRING_ID;
+// text text = STRING_ID, text = STRING_ID, flags = x, key = y;
+//
+vfrStatementTextText :
+ << ResetFlags (); >>
+ IDT:Text << WriteOpByte (IDT->getLine(), EFI_IFR_TEXT_OP); >>
+ Help "=" getStringId ","
+ Text "="
+ getStringId // writes string identifier
+ { "," Text "=" getStringId
+ "," Flags "=" flagsField ( "\|" flagsField )* << WriteFlags (); >>
+ ","
+ Key "=" KNUM:Number << WriteWord (GetNumber(KNUM->getText(), KNUM->getLine(), 2)); >>
+ }
+ ";"
+ ;
+
+//*****************************************************************************
+//
+// PARSE:
+//
+// inventory help = ID, text = ID;
+// inventory help = ID, text = id, text = ID;
+//
+vfrStatementInventory :
+ IDI:Inventory << WriteOpByte (IDI->getLine(), EFI_IFR_INVENTORY_OP); >>
+ Help "=" getStringId ","
+ Text "=" getStringId // writes string identifier
+ { "," Text "=" getStringId
+ }
+ ";"
+ ;
+
+//*****************************************************************************
+//
+// PARSE:
+//
+// restore defaults,
+// formid = 4,
+// prompt = STRING_TOKEN(STR_RESTORE_DEFAULTS_PROMPT),
+// help = STRING_TOKEN(STR_RESTORE_DEFAULTS_HELP),
+// flags = 0,
+// key = 0;
+//
+// save defaults,
+// formid = 4,
+// prompt = STRING_TOKEN(STR_SAVE_DEFAULTS_PROMPT),
+// help = STRING_TOKEN(STR_SAVE_DEFAULTS_HELP),
+// flags = 0,
+// key = 0;
+//
+vfrStatementSaveRestoreDefaults :
+ << unsigned int KeyValue = 0; UINT32 LineNum; ResetFlags (); >>
+ ( IDS:Save << WriteOpByte (IDS->getLine(), EFI_IFR_SAVE_DEFAULTS_OP); >>
+ | IDR:Restore << WriteOpByte (IDR->getLine(), EFI_IFR_RESTORE_DEFAULTS_OP); >>
+ )
+ Defaults ","
+ FormId "=" FRMID:Number "," << WriteWord (GetNumber (FRMID->getText(), FRMID->getLine(), 2));
+ AddGotoReference (GetNumber (FRMID->getText(), FRMID->getLine(), 2), FRMID->getLine());
+ >>
+ Prompt "=" getStringId ","
+ KH:Help "=" getStringId << LineNum = KH->getLine(); >>
+ {
+ "," FF:Flags "=" flagsField ( "\|" flagsField )* << LineNum = FF->getLine(); >>
+ }
+ {
+ "," Key "=" KNUM:Number << LineNum = KNUM->getLine(); KeyValue = GetNumber(KNUM->getText(), LineNum, 2); >>
+ }
+ << WriteFlagsKey (KeyValue, LineNum); >>
+ ";"
+ ;
+
+//*****************************************************************************
+//
+// PARSE:
+//
+// flags = 0x10 | DEFAULT | MANUFACTURING | INTERACTIVE | NV_ACCESS | RESET_REQUIRED | LATE_CHECK
+//
+//
+flagsField :
+ VAL:Number << SetFlags (GetNumber(VAL->getText(), VAL->getLine(), 4), VAL->getLine()); >>
+ | IF:InteractiveFlag << SetFlags (EFI_IFR_FLAG_INTERACTIVE, IF->getLine()); >>
+ | MF:ManufacturingFlag << SetFlags (EFI_IFR_FLAG_MANUFACTURING, MF->getLine()); >>
+ | DF:DefaultFlag << SetFlags (EFI_IFR_FLAG_DEFAULT, DF->getLine()); >>
+ | NV:NVAccessFlag << SetFlags (EFI_IFR_FLAG_NV_ACCESS, NV->getLine()); >>
+ | RR:ResetRequiredFlag << SetFlags (EFI_IFR_FLAG_RESET_REQUIRED, RR->getLine()); >>
+ | LC:LateCheckFlag << SetFlags (EFI_IFR_FLAG_LATE_CHECK, LC->getLine()); >>
+ ;
+
+dateTimeSubStatement :
+ Prompt "=" getStringId ","
+ Help "=" getStringId ","
+ << WriteByte (0, 0); WriteWord (0); >> // bogus flags and key
+ minMaxStepDefault << WriteMinMaxStepDefault (); >>
+ ;
+
+vfrStatementCheckBox :
+ << UINT32 LineNum, KeyValue = 0; ResetFlags (); >>
+ IDCB:CheckBox << WriteOpByte (IDCB->getLine(), EFI_IFR_CHECKBOX_OP); >>
+ VarId "=" vfrStructFieldName[1] ","
+ Prompt "=" getStringId ","
+ Help "=" getStringId ","
+ FF:Flags "=" flagsField ( "\|" flagsField )* "," << LineNum = FF->getLine(); >>
+ {
+ Key "=" KV:Number "," << LineNum = KV->getLine(); KeyValue = GetNumber(KV->getText(), LineNum, 2); >>
+ }
+ << WriteFlagsKey (KeyValue, LineNum); >>
+ EndCheckBox ";"
+ ;
+
+vfrStatementSubTitle :
+ IDS:Subtitle Text "=" << WriteOpByte (IDS->getLine(), EFI_IFR_SUBTITLE_OP); >>
+ getStringId // writes string indentifier
+ ";"
+ ;
+
+//*****************************************************************************
+//
+// PARSE:
+// banner
+// title = STRING_TOKEN(STR_BANNER_TITLE),
+// line 1,
+// align center; // or left or right
+//
+// banner,
+// title = STRING_TOKEN(STR_BANNER_TITLE), timeout = 100;
+//
+vfrStatementBanner :
+ IDB:Banner { "," } << WriteOpByte (IDB->getLine(), EFI_IFR_BANNER_OP); >>
+ Title "=" getStringId ","
+ (
+ Line VAL:Number "," << WriteWord (GetNumber(VAL->getText(), VAL->getLine(), 2)); >>
+ Align
+ ( Left << WriteByte (EFI_IFR_BANNER_ALIGN_LEFT, 0); >>
+ | Center << WriteByte (EFI_IFR_BANNER_ALIGN_CENTER, 0); >>
+ | Right << WriteByte (EFI_IFR_BANNER_ALIGN_RIGHT, 0); >>
+ ) ";"
+ |
+ Timeout "=" TO:Number ";" << WriteWord (GetNumber(TO->getText(), TO->getLine(), 2)); >>
+ << WriteByte (EFI_IFR_BANNER_TIMEOUT, 0); >>
+ )
+ ;
+
+//*****************************************************************************
+//
+// PARSE:
+// oneof varid = MyNv.OneOfData,
+// prompt = STRING_TOKEN(STR_ONE_OF_PROMPT),
+// help = STRING_TOKEN(STR_ONE_OF_HELP),
+// option text = STRING_TOKEN(STR_ONE_OF_TEXT),
+// value = 0,
+// flags = DEFAULT | INTERACTIVE;
+//
+// supressif/grayoutif are supported inside oneof stmt.
+// We do not restrict the number of oneOfOptionText to >=2, but >=1.
+// The situation that all oneOfOptionText are suppressed is also possiable.
+//
+vfrStatementOneOf :
+ << ResetFlags (); >>
+ IDOO:OneOf << WriteOpByte (IDOO->getLine(), EFI_IFR_ONE_OF_OP); >>
+ VarId "=" vfrStructFieldName[2] ","
+ Prompt "=" getStringId "," // writes string identifier
+ Help "=" getStringId "," // writes string identifier
+ ( oneOfOptionText )+ // there must be at least 1 option to be choosed, not 2.
+ IDEOO:EndOneOf ";" << TestOneOfFlags (IDEOO->getLine()); WriteOpByte (IDEOO->getLine(), EFI_IFR_END_ONE_OF_OP); >>
+ ;
+
+//*****************************************************************************
+//
+// PARSE:
+//
+// orderedlist varid = MyNv.OrderedListData,
+// prompt = STRING_TOKEN(STR_ORDERED_LIST_PROMPT),
+// help = STRING_TOKEN(STR_ORDERED_LIST_HELP),
+// option text = STRING_TOKEN(STR_ORDERED_LIST_TEXT), value = 0, flags = INTERACTIVE;
+// -- additional option text --
+// endlist;
+//
+vfrStatementOrderedList :
+ << ResetFlags (); InitOrderedList(); >>
+ IDOL:OrderedList << WriteOpByte (IDOL->getLine(), EFI_IFR_ORDERED_LIST_OP); >>
+ VarId "=" vfrStructFieldNameArray[1] ","
+ Prompt "=" getStringId "," // writes string identifier
+ Help "=" getStringId "," // writes string identifier
+ orderedListOptionText ( orderedListOptionText )+
+ IDEOL:EndList ";" << WriteOpByte (IDEOL->getLine(), EFI_IFR_END_OP); EndOrderedList(IDEOL->getLine()); >>
+ ;
+
+//*****************************************************************************
+//
+// PARSE:
+//
+// option text = STRING_TOKEN(STRING_ID), value = 0 flags = 99;
+//
+// Differs from the oneOfOptionText in that we don't allow the DEFAULT flag to
+// be set, and value cannot be 0.
+//
+orderedListOptionText :
+ << UINT32 KeyValue = 0; >>
+ IDO:Option << WriteOpByte (IDO->getLine(), EFI_IFR_ONE_OF_OPTION_OP); >>
+ Text "=" getStringId "," // writes string identifier
+ Value "=" WVAL:Number "," <<
+ if (GetNumber(WVAL->getText(), WVAL->getLine(), 2) == 0) {
+ PrintErrorMessage (WVAL->getLine(), "value=0 is invalid for ordered lists", NULL);
+ } else {
+ WriteWord (GetNumber(WVAL->getText(), WVAL->getLine(), 2));
+ }
+ >>
+ FF:Flags "=" orderedListFlagsField
+ ("\|" orderedListFlagsField )*
+ {
+ "," Key "=" KV:Number << KeyValue = GetNumber (KV->getText(), KV->getLine(), 2); >>
+ }
+ << WriteFlagsKey (KeyValue, FF->getLine()); >>
+ ";" << mOptionCount++; >>
+ ;
+
+//*****************************************************************************
+//
+// PARSE:
+//
+// flags = 0x10 | DEFAULT | MANUFACTURING | INTERACTIVE | NV_ACCESS | RESET_REQUIRED | LATE_CHECK
+//
+// The ordered list flags field cannot have a default.
+//
+orderedListFlagsField :
+ VAL:Number << SetFlags (GetNumber(VAL->getText(), VAL->getLine(), 4), VAL->getLine()); >>
+ | IF:InteractiveFlag << SetFlags (EFI_IFR_FLAG_INTERACTIVE, IF->getLine()); >>
+ | MF:ManufacturingFlag << SetFlags (EFI_IFR_FLAG_MANUFACTURING, MF->getLine()); >>
+ | NV:NVAccessFlag << SetFlags (EFI_IFR_FLAG_NV_ACCESS, NV->getLine()); >>
+ | RR:ResetRequiredFlag << SetFlags (EFI_IFR_FLAG_RESET_REQUIRED, RR->getLine()); >>
+ | LC:LateCheckFlag << SetFlags (EFI_IFR_FLAG_LATE_CHECK, LC->getLine()); >>
+ | DF:DefaultFlag << PrintWarningMessage (DF->getLine(), "DEFAULT flag not valid for ordered lists", NULL); >>
+ ;
+
+//
+// Parse references to VFR structure field names of form "MyNvStructure.Field".
+// This implementation is specific to strings, passwords, and references in an
+// ordered list statement because we want to specify the size of the entire
+// field, rather than just one element. Then call a function to write out its
+// offset and length.
+//
+vfrStructFieldNameArray[int FieldWidth] :
+ << int ArrayIndex = 1; char IsArrayIndex = 0; >>
+ SName:StringIdentifier
+ "."
+ SFieldName:StringIdentifier
+ { OpenBracket AIndex:Number CloseBracket << ArrayIndex = GetNumber(AIndex->getText(), AIndex->getLine(), 4); IsArrayIndex = 1; >> }
+ <<
+ WriteFieldOffset (1,
+ SName->getText(),
+ SName->getLine(),
+ SFieldName->getText(),
+ SFieldName->getLine(),
+ ArrayIndex,
+ IsArrayIndex,
+ FieldWidth,
+ 1
+ );
+ >>
+ ;
+
+//
+// Parse references to VFR structure field names of form "MyNvStructure.Field",
+// then call a function to write out its offset and length.
+//
+vfrStructFieldName[int FieldWidth] :
+ << int ArrayIndex = 1; char IsArrayIndex = 0; >>
+ SName:StringIdentifier
+ "."
+ SFieldName:StringIdentifier
+ { OpenBracket AIndex:Number CloseBracket << ArrayIndex = GetNumber(AIndex->getText(), AIndex->getLine(), 4); IsArrayIndex = 1; >> }
+ <<
+ WriteFieldOffset (1,
+ SName->getText(),
+ SName->getLine(),
+ SFieldName->getText(),
+ SFieldName->getLine(),
+ ArrayIndex,
+ IsArrayIndex,
+ FieldWidth,
+ 0
+ );
+ >>
+ ;
+
+//*****************************************************************************
+//
+// PARSE:
+//
+// MyNvStructure.FieldName[4]
+//
+// Parse references to VFR structure field names of form "MyNvStructure.Field",
+// then call a function to write out the offset with no length.
+//
+vfrStructFieldNameNL[int FieldWidth] :
+ << int ArrayIndex = 1; char IsArrayIndex = 0; >>
+ SName:StringIdentifier
+ "."
+ SFieldName:StringIdentifier
+ { OpenBracket AIndex:Number CloseBracket << ArrayIndex = GetNumber(AIndex->getText(), AIndex->getLine(), 4); IsArrayIndex = 1; >> }
+ <<
+ WriteFieldOffset (0,
+ SName->getText(),
+ SName->getLine(),
+ SFieldName->getText(),
+ SFieldName->getLine(),
+ ArrayIndex,
+ IsArrayIndex,
+ FieldWidth,
+ 0
+ );
+ >>
+ ;
+
+//*****************************************************************************
+//
+// PARSE:
+// suppressif TRUE OR FALSE;
+// grayoutif FALSE OR TRUE;
+// option text = STRING_TOKEN(STRING_ID), value = 0 flags = 99;
+// option text = STRING_TOKEN(STRING_ID2), value = 1 flags = 98;
+// endif;
+//
+oneOfOptionText :
+ suppressIfOptionText |
+ grayOutIfOptionText |
+ commonOptionText
+ ;
+
+suppressIfOptionText :
+ << ResetFlags (); >>
+ OPID:SuppressIf << WriteOpByte (OPID->getLine(), EFI_IFR_SUPPRESS_IF_OP); SetIfStart (OPID->getLine()); >>
+ {
+ FF:Flags "=" flagsField ( "\|" flagsField )* ","
+ }
+ << WriteFlags (); >> // write the flags field
+ vfrBooleanExpression
+ ";"
+ { suppressIfGrayOutIf } ( commonOptionText )+
+ ENDOP:EndIf ";" << WriteOpByte (ENDOP->getLine(), EFI_IFR_END_IF_OP); SetIfStart (0); >>
+ ;
+
+grayOutIfOptionText :
+ << ResetFlags (); >>
+ OPID:GrayOutIf << WriteOpByte (OPID->getLine(), EFI_IFR_GRAYOUT_IF_OP); SetIfStart (OPID->getLine()); >>
+ {
+ FF:Flags "=" flagsField ( "\|" flagsField )* ","
+ }
+ << WriteFlags (); >> // write the flags field
+ vfrBooleanExpression
+ ";"
+ { grayoutIfSuppressIf } ( commonOptionText )+
+ ENDOP:EndIf ";" << WriteOpByte (ENDOP->getLine(), EFI_IFR_END_IF_OP); SetIfStart (0); >>
+ ;
+
+commonOptionText :
+ << UINT32 KeyValue = 0; >>
+ IDO:Option << WriteOpByte (IDO->getLine(), EFI_IFR_ONE_OF_OPTION_OP); >>
+ Text "=" getStringId "," // writes string identifier
+ Value "=" WVal:Number "," << WriteWord (GetNumber(WVal->getText(), WVal->getLine(), 2)); >>
+ FF:Flags "=" flagsField ("\|" flagsField )*
+ {
+ "," Key "=" KV:Number << KeyValue = GetNumber (KV->getText(), KV->getLine(), 2); >>
+ }
+ << WriteFlagsKey (KeyValue, FF->getLine()); >>
+ ";" << mOptionCount++; >>
+ ;
+
+//
+// Gets a string identifier. It must be a numeric value of form:
+//
+// STRING_TOKEN(100)
+//
+getStringId :
+ << unsigned short StrId; >>
+ StringToken OpenParen
+ IdVal:Number << StrId = GetNumber (IdVal->getText(), IdVal->getLine(), 2); WriteStringIdWord (StrId); >>
+ CloseParen
+ ;
+
+//******************************************************************************
+//
+// Parser class definition.
+//
+class EfiVfrParser {
+<<
+//
+// Parser definitions go here
+//
+private:
+ STRUCT_DEFINITION *mFirstStructDefinition;
+ STRUCT_DEFINITION *mLastStructDefinition;
+ INT32 mNvDataStructSize;
+ INT32 mNonNvDataStructSize;
+ //
+ // Flag to indicate that we're processing a ideqid VFR statement so that
+ // we can do late checks on the statement.
+ //
+ INT32 mIdEqIdStmt;
+ INT32 mLastNVVariableDataSize;
+ GOTO_REFERENCE *mGotoReferences;
+ FORM_ID_VALUE *mFormIdValues;
+ VfrOpcodeHandler mOpcodeHandler;
+ UINT16_LIST *mUint16List;
+ UINT16_LIST *mLastUint16;
+ UINT16_LIST *mDefinedLabels;
+ UINT16_LIST *mDefinedVarStoreId;
+ UINT16_LIST *mLastDefinedVarStoreId;
+ UINT32 mMinimumValue, mMaximumValue, mStepValue, mDefaultValue;
+ UINT32 mStmtFlags;
+ UINT32 mSubStmtFlags;
+ UINT32 mSubStmtFlagsLineNum;
+ EFI_GUID mFormSetGuid;
+ UINT8 mNvDataStructDefined;
+ UINT16 mClass, mSubclass;
+ UINT32 mIfStart;
+ UINT32 mOptionCount; // how many "option" fields in a given statement
+ UINT32 mLastVarIdSize;
+ UINT8 mOutput;
+public:
+
+VOID
+EfiVfrParser::SetIfStart (
+ UINT32 LineNum
+ )
+/*++
+
+Routine Description:
+ Invoked during VFR parsing when an "if" is encountered. Save the
+ source line number so we can point to it if we don't find a
+ corresponding endif later.
+
+Arguments:
+ LineNum - source line number where the "if" was parsed.
+
+Returns:
+ None
+
+--*/
+{
+ mIfStart = LineNum;
+}
+VOID
+EfiVfrParser::SetClass (
+ UINT32 LineNum,
+ UINT32 Value
+ )
+/*++
+
+Routine Description:
+ Invoked during VFR parsing when a "class" statement is found. Check the
+ range on the class value and save it for later.
+
+Arguments:
+ LineNum - source line number where the class statement was parsed.
+ Value - the class value
+
+Returns:
+ None
+
+--*/
+{
+ if (Value & 0xFFFF0000) {
+ PrintWarningMessage (LineNum, NULL, "class value exceeds maximum allowed");
+ }
+ mClass |= (UINT16)Value;
+}
+VOID
+EfiVfrParser::SetSubclass (
+ UINT32 LineNum,
+ UINT32 Value
+ )
+/*++
+
+Routine Description:
+ Invoked during VFR parsing when a subclass statement is found. Check the
+ range on the value and save it for later.
+
+Arguments:
+ LineNum - source line number where the class statement was parsed.
+ Value - the subclass value from the VFR statement
+
+Returns:
+ None
+
+--*/
+{
+ if (Value & 0xFFFF0000) {
+ PrintWarningMessage (LineNum, NULL, "subclass value exceeds maximum allowed");
+ }
+ mSubclass |= (UINT16)Value;
+}
+VOID EfiVfrParser::WriteClass ()
+{
+ WriteWord (mClass);
+ mClass = 0;
+}
+VOID EfiVfrParser::WriteSubclass ()
+{
+ WriteWord (mSubclass);
+ mSubclass = 0;
+}
+VOID EfiVfrParser::WriteIfrBytes ()
+{
+ mOpcodeHandler.WriteIfrBytes ();
+}
+VOID
+EfiVfrParser::WriteFlagsKey (
+ UINT32 KeyValue,
+ UINT32 LineNum
+ )
+/*++
+
+Routine Description:
+ Write out the flags and key values from the previous VFR statement.
+ Many statements take a flags/key pair. If not specified, then 0
+ values are written out. However do not allow an interactive flags field
+ to be specified if no key value is specified. Also, if NV_ACCESS flag
+ is set but INTERACTIVE is not, then set interactive and issue a warning.
+
+Arguments:
+ KeyValue - the key value from the VFR statement
+ LineNum - source line number where the statement was parsed
+
+Returns:
+ None
+
+--*/
+{
+ if ((mSubStmtFlags & EFI_IFR_FLAG_INTERACTIVE) && (KeyValue == 0)) {
+ PrintErrorMessage (LineNum, NULL, "invalid or missing key value - required with INTERACTIVE");
+ }
+ if ((mSubStmtFlags & EFI_IFR_FLAG_NV_ACCESS) && !(mSubStmtFlags & EFI_IFR_FLAG_INTERACTIVE)) {
+ PrintWarningMessage (LineNum, NULL, "NV_ACCESS without INTERACTIVE has no effect -- setting INTERACTIVE");
+ mSubStmtFlags |= EFI_IFR_FLAG_INTERACTIVE;
+ }
+ WriteFlags ();
+ WriteWord (KeyValue);
+}
+VOID
+EfiVfrParser::InitOrderedList ()
+{
+ mOptionCount = 0;
+}
+VOID
+EfiVfrParser::EndOrderedList (
+ UINT32 LineNum
+ )
+{
+ if (mLastVarIdSize < mOptionCount) {
+ PrintErrorMessage (LineNum, NULL, "number of options exceeds the variable store size");
+ }
+}
+VOID
+EfiVfrParser::ResetFlags ()
+/*++
+
+Routine Description:
+
+ Flags are set for each substatement in a given one-of statement.
+ To make sure there are no conflicts, for example setting DEFAULT on
+ more than one substatement, we keep track of the flags at a statement
+ level and a substatement level. This function resets the flags so
+ we get a fresh start.
+
+Arguments:
+ None
+
+Returns:
+ None
+
+--*/
+{
+ mStmtFlags = 0;
+ mSubStmtFlagsLineNum = 0;
+ mSubStmtFlags = 0;
+}
+//
+// Test validity of flags value for a one-of statement.
+//
+VOID
+EfiVfrParser::TestOneOfFlags (
+ UINT32 LineNum
+ )
+{
+ //
+ // One of the fields must have had the default bit set
+ //
+ if ((mStmtFlags & EFI_IFR_FLAG_DEFAULT) == 0) {
+ PrintWarningMessage (LineNum, "default value must be specified", NULL);
+ }
+}
+VOID
+EfiVfrParser::SetFlags (
+ UINT32 Flags,
+ UINT32 LineNum
+ )
+{
+ //
+ // Check for redefinitions and invalid combinations
+ //
+ if (mStmtFlags & Flags & EFI_IFR_FLAG_MANUFACTURING) {
+ PrintErrorMessage (LineNum, "MANUFACTURING", "a field with this flag already defined");
+ }
+ if (mStmtFlags & Flags & EFI_IFR_FLAG_DEFAULT) {
+ PrintErrorMessage (LineNum, "DEFAULT", "a field with this flag already defined");
+ }
+ mSubStmtFlags |= Flags;
+ mSubStmtFlagsLineNum = LineNum;
+}
+VOID
+EfiVfrParser::WriteFlags ()
+{
+ //
+ // Check value for validity
+ //
+ if (mSubStmtFlags & ~(EFI_IFR_FLAG_DEFAULT |
+ EFI_IFR_FLAG_MANUFACTURING |
+ EFI_IFR_FLAG_INTERACTIVE |
+ EFI_IFR_FLAG_NV_ACCESS |
+ EFI_IFR_FLAG_RESET_REQUIRED |
+ EFI_IFR_FLAG_LATE_CHECK )) {
+ PrintWarningMessage (mSubStmtFlagsLineNum, "invalid bits defined in flag", NULL);
+ }
+ WriteByte ((UINT8)mSubStmtFlags, 'F');
+ //
+ // We can now clear the substatement flags
+ //
+ mStmtFlags |= mSubStmtFlags;
+ mSubStmtFlags = 0;
+}
+//
+// When we parse a min/max/step/default sequence, save off the values for
+// later use. Call this first to init the values.
+//
+VOID
+EfiVfrParser::InitMinMaxStepDefault ()
+{
+ mMinimumValue = 0;
+ mMaximumValue = 0;
+ mStepValue = 1;
+ mDefaultValue = 0;
+}
+VOID
+EfiVfrParser::WriteMinMaxStepDefault ()
+{
+ WriteWord (mMinimumValue);
+ WriteWord (mMaximumValue);
+ WriteWord (mStepValue);
+ WriteWord (mDefaultValue);
+}
+VOID
+EfiVfrParser::SetMinMaxStepDefault (
+ UINT16 Value,
+ INT32 MMSD,
+ INT32 LineNum
+ )
+{
+ UINT16 TempValue;
+ //
+ // Min specified
+ //
+ if (MMSD == 0) {
+ mMinimumValue = Value;
+ mDefaultValue = Value;
+ //
+ // Max specified
+ //
+ } else if (MMSD == 1) {
+ mMaximumValue = Value;
+ //
+ // If min > max, then swap the values. That includes resetting the default
+ // value as well.
+ //
+ if (mMinimumValue > mMaximumValue) {
+ PrintWarningMessage (LineNum, NULL, "maximum < minimum");
+ TempValue = Value;
+ mMaximumValue = mMinimumValue;
+ mMinimumValue = TempValue;
+ mDefaultValue = mMinimumValue;
+ }
+ //
+ // Step specified
+ //
+ } else if (MMSD == 2) {
+ mStepValue = Value;
+ //
+ // Default specified. Make sure min <= default <= max.
+ //
+ } else if (MMSD == 3) {
+ mDefaultValue = Value;
+ if (mMinimumValue > Value) {
+ PrintErrorMessage (LineNum, NULL, "default value < minimum value");
+ } else if (Value > mMaximumValue) {
+ PrintErrorMessage (LineNum, NULL, "default value > maximum value");
+ }
+ } else {
+ PrintErrorMessage (LineNum, "application error", "internal MMSD error");
+ }
+}
+VOID
+EfiVfrParser::AddLabel (
+ UINT32 LabelNumber,
+ UINT32 LineNum
+ )
+{
+ UINT16_LIST *Label;
+
+ //
+ // Added a label from the user VFR script. Make sure they haven't already
+ // defined the same label elsewhere
+ //
+ for (Label = mDefinedLabels; Label != NULL; Label = Label->Next) {
+ if (Label->Value == LabelNumber) {
+ PrintErrorMessage (LineNum, NULL, "label already defined");
+ PrintErrorMessage (Label->LineNum, NULL, "previous definition of redefined label");
+ break;
+ }
+ }
+ Label = (UINT16_LIST *)malloc (sizeof (UINT16_LIST));
+ if (Label == NULL) {
+ PrintErrorMessage (0, NULL, "memory allocation error");
+ return;
+ }
+ memset ((char *)Label, 0, sizeof (UINT16_LIST));
+ Label->Value = LabelNumber;
+ Label->LineNum = LineNum;
+ Label->Next = mDefinedLabels;
+ mDefinedLabels = Label;
+}
+VOID
+EfiVfrParser::QueueIdEqValList (
+ UINT16 Value
+ )
+{
+ UINT16_LIST *U16;
+
+ U16 = (UINT16_LIST *)malloc (sizeof (UINT16_LIST));
+ if (U16 == NULL) {
+ Error (PROGRAM_NAME, 0, 0, NULL, "memory allocation failed");
+ } else {
+ memset ((char *)U16, 0, sizeof (UINT16_LIST));
+ U16->Value = Value;
+ if (mUint16List == NULL) {
+ mUint16List = U16;
+ } else {
+ mLastUint16->Next = U16;
+ }
+ mLastUint16 = U16;
+ }
+}
+VOID
+EfiVfrParser::FlushQueueIdEqValList ()
+{
+ UINT32 Count;
+
+ //
+ // We queued up a list of IdEqValList items. The IFR requires a count
+ // followed by the actual values. Do it.
+ //
+ Count = 0;
+ mLastUint16 = mUint16List;
+ while (mLastUint16 != NULL) {
+ Count++;
+ mLastUint16 = mLastUint16->Next;
+ }
+ // BUGBUG -- check for more than 16K items?
+ WriteWord (Count);
+ //
+ // Now write the values.
+ //
+ mLastUint16 = mUint16List;
+ while (mLastUint16 != NULL) {
+ WriteWord ((UINT32)mLastUint16->Value);
+ mLastUint16 = mLastUint16->Next;
+ }
+ //
+ // Free up the list
+ //
+ mLastUint16 = mUint16List;
+ while (mUint16List != NULL) {
+ mLastUint16 = mUint16List->Next;
+ free (mUint16List);
+ mUint16List = mLastUint16;
+ }
+}
+VOID
+EfiVfrParser::PrintErrorMessage (
+ UINT32 LineNum,
+ CHAR8 *Msg1,
+ CHAR8 *Msg2
+ )
+{
+ char *FileName;
+
+ if (LineNum != 0) {
+ FileName = ConvertLineNumber ((UINT32 *)&LineNum);
+ Error (FileName, LineNum, 0, Msg1, Msg2);
+ } else {
+ Error (PROGRAM_NAME, 0, 0, Msg1, Msg2);
+ }
+}
+VOID
+EfiVfrParser::PrintWarningMessage (
+ UINT32 LineNum,
+ CHAR8 *Msg1,
+ CHAR8 *Msg2
+ )
+{
+ char *FileName;
+
+ if (LineNum != 0) {
+ FileName = ConvertLineNumber ((UINT32 *)&LineNum);
+ Warning (FileName, LineNum, 0, Msg1, Msg2);
+ } else {
+ Warning (PROGRAM_NAME, 0, 0, Msg1, Msg2);
+ }
+}
+VOID
+EfiVfrParser::syn (
+ ANTLRAbstractToken *Tok,
+ ANTLRChar *Egroup,
+ SetWordType *Eset,
+ ANTLRTokenType ETok,
+ INT32 Huh
+ )
+/*++
+
+Routine Description:
+ Called by the parser base class as a result of parse syntax errors.
+
+Arguments:
+ Tok - token that caused the error
+ Egroup - not sure
+ Eset - index in token table of the expected token
+ Huh - not sure
+
+Returns:
+ NA
+
+--*/
+{
+ char *FileName;
+ UINT32 LineNum;
+
+ LineNum = Tok->getLine ();
+ FileName = ConvertLineNumber ((UINT32 *)&LineNum);
+ //
+ // Sometimes the token number is 0, in which case I don't know what to
+ // print.
+ //
+ if (ETok == 0) {
+ Error (FileName, LineNum, 0, Tok->getText (), "unexpected token");
+ } else {
+ //
+ // If we were expecting an endif, then report the line where the corresponding
+ // IF began.
+ //
+ if ((strcmp (_token_tbl[ETok], "endif") == 0) && (mIfStart != 0)) {
+ LineNum = mIfStart;
+ FileName = ConvertLineNumber (&LineNum);
+ Error (FileName, LineNum, 0, "statement missing corresponding endif", NULL);
+ } else {
+ Error (FileName, LineNum, 0, Tok->getText (), "expected %s", _token_tbl[ETok]);
+ }
+ }
+}
+
+VOID
+EfiVfrParser::init()
+/*++
+
+Routine Description:
+ Initializations function for our parser.
+
+Arguments:
+ None.
+
+Returns:
+ None.
+
+--*/
+{
+ ANTLRParser::init();
+
+ //
+ // Used for queuing a variable list of UINT16's
+ //
+ mUint16List = NULL;
+ mLastUint16 = NULL;
+ mFirstStructDefinition = NULL;
+ mLastStructDefinition = NULL;
+ mNvDataStructSize = 0;
+ mNonNvDataStructSize = 0;
+ mNvDataStructDefined = 0;
+ mGotoReferences = NULL;
+ mFormIdValues = NULL;
+ mDefinedLabels = NULL;
+ mClass = 0;
+ mSubclass = 0;
+ mIfStart = 0;
+ mDefinedVarStoreId = NULL;
+ mLastDefinedVarStoreId = NULL;
+ mIdEqIdStmt = 0;
+ mLastNVVariableDataSize = 0;
+
+ memset ((char *)&mFormSetGuid, 0, sizeof (EFI_GUID));
+}
+//
+// Destructor for the parser.
+//
+EfiVfrParser::~EfiVfrParser(VOID)
+{
+ Cleanup();
+}
+VOID
+EfiVfrParser::Cleanup (VOID)
+/*++
+
+Routine Description:
+ Free memory allocated during parsing
+
+Arguments:
+ None.
+
+Returns:
+ None.
+
+--*/
+{
+ STRUCT_DEFINITION *NextStruct;
+ STRUCT_FIELD_DEFINITION *NextField;
+ UINT8 Buff[6];
+ UINT16_LIST *NextU16List;
+
+ //
+ // Free up the structure definitions if any
+ //
+ while (mFirstStructDefinition != NULL) {
+ //
+ // Free up all the fields for this struct
+ //
+ while (mFirstStructDefinition->Field != NULL) {
+ NextField = mFirstStructDefinition->Field->Next;
+ free (mFirstStructDefinition->Field->Name);
+ free (mFirstStructDefinition->Field);
+ mFirstStructDefinition->Field = NextField;
+ }
+ NextStruct = mFirstStructDefinition->Next;
+ free (mFirstStructDefinition->Name);
+ free (mFirstStructDefinition);
+ mFirstStructDefinition = NextStruct;
+ }
+ //
+ // Free up the goto references and form id defines
+ //
+ FreeGotoReferences ();
+ //
+ // Free up label list
+ //
+ while (mDefinedLabels != NULL) {
+ NextU16List = mDefinedLabels->Next;
+ delete (mDefinedLabels);
+ mDefinedLabels = NextU16List;
+ }
+ //
+ // Free up the list of defined variable storage IDs
+ //
+ while (mDefinedVarStoreId != NULL) {
+ NextU16List = mDefinedVarStoreId->Next;
+ delete (mDefinedVarStoreId);
+ mDefinedVarStoreId = NextU16List;
+ }
+}
+
+INT32
+EfiVfrParser::AtoX (
+ CHAR8 *HexString,
+ INT32 NumBytes,
+ UINT32 *HexValue
+ )
+/*++
+
+Routine Description:
+ Given a pointer to a ascii hex string, convert to a number with the given
+ number of bytes.
+
+Arguments:
+ HexString - pointer to a string of format 30BCA
+ Size - number of bytes to convert
+ HexValue - return result
+
+Returns:
+ The number of bytes converted.
+
+--*/
+{
+ INT32 Count;
+ INT32 Value;
+
+ *HexValue = 0;
+ Count = 0;
+ while (Count < NumBytes) {
+ if ((*HexString >= '0') && (*HexString <= '9')) {
+ Value = *HexString - '0';
+ } else if ((*HexString >= 'a') && (*HexString <= 'f')) {
+ Value = *HexString - 'a' + 10;
+ } else if ((*HexString >= 'A') && (*HexString <= 'F')) {
+ Value = *HexString - 'A' + 10;
+ } else {
+ return Count;
+ }
+ HexString++;
+ *HexValue = (*HexValue << 4) | Value;
+ if ((*HexString >= '0') && (*HexString <= '9')) {
+ Value = *HexString - '0';
+ } else if ((*HexString >= 'a') && (*HexString <= 'f')) {
+ Value = *HexString - 'a' + 10;
+ } else if ((*HexString >= 'A') && (*HexString <= 'F')) {
+ Value = *HexString - 'A' + 10;
+ } else {
+ return Count;
+ }
+ *HexValue = (*HexValue << 4) | Value;
+ HexString++;
+ Count++;
+ }
+ return Count;
+}
+VOID
+EfiVfrParser::WriteGuidValue (
+ UINT32 TokenLineNum,
+ CHAR8 *G1,
+ CHAR8 *G2,
+ CHAR8 *G3,
+ CHAR8 *G4,
+ CHAR8 *G5,
+ CHAR8 *G6,
+ CHAR8 *G7,
+ CHAR8 *G8,
+ CHAR8 *G9,
+ CHAR8 *G10,
+ CHAR8 *G11
+ )
+/*++
+
+Routine Description:
+ A Guid was parsed, likely of format:
+ #define MY_GUID { 0x12345678, 0xAABB, 0xCCDD, 0xEE, 0xFF, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66 }
+
+ Write out the value.
+
+Arguments:
+ TokenLineNum - line number where the guid was used
+ G1-G11 - the 11 fields of the guid value
+
+Returns:
+ None.
+
+--*/
+{
+ UINT32 Value;
+ INT32 Loop;
+
+ mFormSetGuid.Data1 = GetNumber (G1, TokenLineNum, 4);
+ mFormSetGuid.Data2 = (UINT16)GetNumber (G2, TokenLineNum, 2);
+ mFormSetGuid.Data3 = (UINT16)GetNumber (G3, TokenLineNum, 2);
+ mFormSetGuid.Data4[0] = (UINT8)GetNumber (G4, TokenLineNum, 1);
+ mFormSetGuid.Data4[1] = (UINT8)GetNumber (G5, TokenLineNum, 1);
+ mFormSetGuid.Data4[2] = (UINT8)GetNumber (G6, TokenLineNum, 1);
+ mFormSetGuid.Data4[3] = (UINT8)GetNumber (G7, TokenLineNum, 1);
+ mFormSetGuid.Data4[4] = (UINT8)GetNumber (G8, TokenLineNum, 1);
+ mFormSetGuid.Data4[5] = (UINT8)GetNumber (G9, TokenLineNum, 1);
+ mFormSetGuid.Data4[6] = (UINT8)GetNumber (G10, TokenLineNum, 1);
+ mFormSetGuid.Data4[7] = (UINT8)GetNumber (G11, TokenLineNum, 1);
+
+ WriteDWord (mFormSetGuid.Data1, 'G');
+ WriteWord (mFormSetGuid.Data2);
+ WriteWord (mFormSetGuid.Data3);
+ WriteByte (mFormSetGuid.Data4[0], 0);
+ WriteByte (mFormSetGuid.Data4[1], 0);
+ WriteByte (mFormSetGuid.Data4[2], 0);
+ WriteByte (mFormSetGuid.Data4[3], 0);
+ WriteByte (mFormSetGuid.Data4[4], 0);
+ WriteByte (mFormSetGuid.Data4[5], 0);
+ WriteByte (mFormSetGuid.Data4[6], 0);
+ WriteByte (mFormSetGuid.Data4[7], 0);
+}
+VOID
+EfiVfrParser::WriteFieldOffset (
+ INT8 WriteLength,
+ CHAR8 *StructName,
+ INT32 LineNum1,
+ CHAR8 *FieldName,
+ INT32 LineNum2,
+ INT32 ArrayIndex,
+ INT8 IsArrayIndex,
+ INT32 FieldWidth,
+ INT8 WriteArraySize
+ )
+/*++
+
+Routine Description:
+ A VFR script referenced the NV store structure. Given the structure's name
+ and the field's name, write the offset of the field to the output file.
+
+Arguments:
+ WriteLength - write the field length byte out
+ StructName - name of the NV store structure
+ LineNum1 - line number in the VFR where we are (for error printing)
+ FieldName - the name of the field within the NV store structure
+ LineNum2 - line number in the VFR where FieldName is referenced
+ ArrayIndex - the index specified, for example NV_DATA.Field[ArrayIndex]
+ IsArrayIndex - non-zero if an array index was specified
+ FieldWidth - expected size for the Field (1 byte? 2 bytes?)
+ WriteArraySize - write the size of the entire field, not the size of a single element
+
+Returns:
+ None.
+
+--*/
+{
+ STRUCT_DEFINITION *StructDef;
+ STRUCT_FIELD_DEFINITION *FieldDef;
+ UINT32 Offset;
+ UINT32 VarSize;
+ CHAR8 Msg[100];
+ //
+ // If we're writing an array size, then they better have referenced the field without an
+ // index.
+ //
+ if (WriteArraySize && IsArrayIndex) {
+ sprintf (Msg, "array index specified where an array is required");
+ PrintErrorMessage (LineNum2, FieldName, Msg);
+ return;
+ }
+ //
+ // Look through our list of known structures for a match
+ //
+ for (StructDef = mFirstStructDefinition; StructDef != NULL; StructDef = StructDef->Next) {
+ //
+ // Check for matching structure name
+ //
+ if (strcmp (StructDef->Name, StructName) == 0) {
+ //
+ // Mark it as referenced (for debug purposes only). Check the
+ // flag that indicates that we have already found a varstore VFR
+ // statement for it.
+ //
+ StructDef->Referenced++;
+ if (StructDef->VarStoreIdValid == 0) {
+ //
+ // Set it valid so we don't flag it multiple times, then emit the error
+ //
+ StructDef->VarStoreIdValid = 1;
+ PrintErrorMessage (LineNum1, StructName, "varstore statement missing for this variable store");
+ }
+ //
+ // Let the opcode-handler know which variable storage we're now using
+ //
+ if (mIdEqIdStmt) {
+ mOpcodeHandler.SetSecondaryVarStoreId (StructDef->VarStoreId);
+ } else {
+ mOpcodeHandler.SetVarStoreId (StructDef->VarStoreId);
+ }
+ //
+ // Found matching structure name. Now find the matching field name
+ //
+ for (FieldDef = StructDef->Field; FieldDef != NULL; FieldDef = FieldDef->Next) {
+ if (strcmp (FieldDef->Name, FieldName) == 0) {
+ //
+ // Make sure the variable size is valid
+ //
+ if ((FieldWidth != 0) && (FieldDef->DataSize > FieldWidth)) {
+ sprintf (Msg, "field width exceeds %d byte%c", FieldWidth, FieldWidth == 1 ? ' ' : 's');
+ PrintErrorMessage (LineNum2, FieldName, Msg);
+ }
+ //
+ // If they specified an index (MyVfrData.FieldX[10]), then make sure that the
+ // data structure was declared as an array, and that the index is in bounds.
+ // If they did not specify an index, then we'll assume 0. This is required for
+ // strings.
+ //
+ if (IsArrayIndex) {
+ VarSize = FieldDef->DataSize;
+ if (FieldDef->IsArray == 0) {
+ PrintErrorMessage (LineNum2, FieldName, "field is not declared as an array");
+ return;
+ }
+ if (FieldDef->ArrayLength < ArrayIndex) {
+ PrintErrorMessage (LineNum2, FieldName, "array index exceeds declared size of field");
+ return;
+ }
+ } else {
+ if (FieldDef->IsArray) {
+ VarSize = FieldDef->DataSize * FieldDef->ArrayLength;
+ } else {
+ VarSize = FieldDef->DataSize;
+ }
+ }
+ //
+ // If we're in the middle of a ideqid VFR statement, then this is the second
+ // variable ID that we're now processing. Make sure that its size is the same
+ // as the first variable.
+ //
+ if (mIdEqIdStmt) {
+ if (mLastVarIdSize != VarSize) {
+ PrintErrorMessage (LineNum2, FieldName, "variables must have the same size");
+ return;
+ }
+ }
+ mLastVarIdSize = VarSize;
+ //
+ // If we're supposed to write an array size, then require it to be an array
+ //
+ if (WriteArraySize && !FieldDef->IsArray) {
+ PrintErrorMessage (LineNum2, FieldName, "array required");
+ return;
+ }
+ //
+ // Write the variable offset and size. If we're in the non-NV structure, then
+ // set the offset beyond the NV data structure size.
+ //
+ Offset = FieldDef->Offset + FieldDef->DataSize * (ArrayIndex - 1);
+ if (StructDef->IsNonNV) Offset += mNvDataStructSize;
+ WriteWord (Offset);
+ if (WriteLength) {
+ if (WriteArraySize) {
+ if (FieldDef->DataSize * FieldDef->ArrayLength > 255) {
+ PrintErrorMessage (LineNum2, FieldName, "array size exceeds 255 maximum encoding limit");
+ return;
+ }
+ WriteByte (FieldDef->DataSize * FieldDef->ArrayLength, 0);
+ } else {
+ WriteByte (FieldDef->DataSize, 0);
+ }
+ }
+ return;
+ }
+ }
+ sprintf (Msg, "structure %s does not have a field named '%s'", StructName, FieldName);
+ PrintErrorMessage (LineNum2, Msg, NULL);
+ PrintErrorMessage (StructDef->LineNum, "see structure definition", NULL);
+ return;
+ }
+ }
+ //
+ // The structure was not found in the defined list. See if it's the "Date" structure
+ //
+ if (strcmp (StructName, "Date") == 0) {
+ //
+ // BUGBUG -- remove support for Date and Time as valid structure
+ // names. They should use the NON_NV_DATA_MAP structure for this.
+ //
+ // Someone specified Date.Years|Months|Days
+ // BUGBUG -- define some constants for the IDs used here
+ // Length == 0 implies that this is not user NV data storage.
+ //
+ if (strcmp (FieldName, "Year") == 0) {
+ //
+ // Write ID (offset), ID, and size
+ //
+ WriteWord (mNvDataStructSize + mNonNvDataStructSize + 0);
+ if (WriteLength) {
+ WriteByte (0, 0);
+ }
+ } else if (strcmp (FieldName, "Month") == 0) {
+ //
+ // Write ID (offset), ID, and size
+ //
+ WriteWord (mNvDataStructSize + mNonNvDataStructSize + 2);
+ if (WriteLength) {
+ WriteByte (0, 0);
+ }
+ } else if (strcmp (FieldName, "Day") == 0) {
+ //
+ // Write ID (offset), ID, and size
+ //
+ WriteWord (mNvDataStructSize + mNonNvDataStructSize + 4);
+ if (WriteLength) {
+ WriteByte (0, 0);
+ }
+ } else {
+ PrintErrorMessage (LineNum1, FieldName, "expected valid field name TheYear/TheMonth/TheDay");
+ }
+ return;
+ } else if (strcmp (StructName, "Time") == 0) {
+ //
+ // Someone specified Time.Hours|Minutes|Seconds
+ // BUGBUG -- define some constants for the IDs used here
+ //
+ if (strcmp (FieldName, "Hours") == 0) {
+ //
+ // Write ID (offset), ID, and size
+ //
+ WriteWord (mNvDataStructSize + mNonNvDataStructSize + 6);
+ if (WriteLength) {
+ WriteByte (0, 0);
+ }
+ } else if (strcmp (FieldName, "Minutes") == 0) {
+ //
+ // Write ID (offset), ID, and size
+ //
+ WriteWord (mNvDataStructSize + mNonNvDataStructSize + 8);
+ if (WriteLength) {
+ WriteByte (0, 0);
+ }
+ } else if (strcmp (FieldName, "Seconds") == 0) {
+ //
+ // Write ID (offset), ID, and size
+ //
+ WriteWord (mNvDataStructSize + mNonNvDataStructSize + 10);
+ if (WriteLength) {
+ WriteByte (0, 0);
+ }
+ } else {
+ PrintErrorMessage (LineNum1, FieldName, "expected valid field name Hours/Minutes/Seconds");
+ }
+ return;
+ } else {
+ PrintErrorMessage (LineNum1, StructName, "undefined structure");
+ return;
+ }
+}
+VOID
+EfiVfrParser::StartStructDefinition (
+ INT32 IsNonNV,
+ INT32 LineNum
+ )
+/*++
+
+Routine Description:
+ Called when we encounter a new "struct _MY_STRUCT..." statement while parsing.
+ Initialize internal data and structures for parsing the fields of the structure.
+
+Arguments:
+ LineNum - line number in the source file (for error reporting purposes)
+ IsNonNv - flag indicating (if nonzero) that the variable referred to is not in
+ the standard NV store.
+Returns:
+ None
+
+--*/
+{
+ STRUCT_DEFINITION *StructDef;
+ //
+ // Allocate memory for the structure record
+ //
+ StructDef = (STRUCT_DEFINITION *)malloc (sizeof (STRUCT_DEFINITION));
+ memset (StructDef, 0, sizeof (STRUCT_DEFINITION));
+ StructDef->LineNum = LineNum;
+ //
+ // Set flag indicating non-NV data structure or not
+ //
+ StructDef->IsNonNV = IsNonNV;
+ //
+ // Add it to the end of our linked list. If it's the first one
+ // defined, then it's the default varstore ID, so set it valid.
+ //
+ if (mFirstStructDefinition == NULL) {
+ mFirstStructDefinition = StructDef;
+ StructDef->VarStoreIdValid = 1;
+ } else {
+ mLastStructDefinition->Next = StructDef;
+ }
+ mLastStructDefinition = StructDef;
+}
+VOID
+EfiVfrParser::EndStructDefinition (
+ CHAR8 *StructName,
+ INT32 LineNum
+ )
+{
+ STRUCT_DEFINITION *StructDef;
+ STRUCT_FIELD_DEFINITION *FieldDef;
+ UINT32 Offset;
+ //
+ // Make sure they have not already defined a structure with this name
+ //
+ for (StructDef = mFirstStructDefinition; StructDef != NULL; StructDef = StructDef->Next) {
+ if ((StructDef->Name != NULL) && (strcmp (StructDef->Name, StructName) == 0)) {
+ PrintErrorMessage (LineNum, StructName, "structure with this name already defined");
+ //
+ // Fall through and fill in the rest of the structure information. We do
+ // this because the structure has already been added to our global list,
+ // so will be used elsewhere, so we want it to contain valid fields.
+ //
+ }
+ }
+ //
+ // Allocate memory for the structure name
+ //
+ mLastStructDefinition->Name = (char *)malloc (strlen (StructName) + 1);
+ strcpy (mLastStructDefinition->Name, StructName);
+ //
+ // Compute the structure size, and the offsets to each field
+ //
+ Offset = 0;
+ for (FieldDef = mLastStructDefinition->Field; FieldDef != NULL; FieldDef = FieldDef->Next) {
+ FieldDef->Offset = Offset;
+ Offset += FieldDef->ArrayLength * FieldDef->DataSize;
+ }
+ mLastStructDefinition->Size = Offset;
+ //
+ // Go through all the structure we have so far and figure out (if we can)
+ // the size of the non-NV storage. We also assume that the first structure
+ // definition is the primary/default storage for the VFR form.
+ //
+ if (mNonNvDataStructSize == 0) {
+ for (StructDef = mFirstStructDefinition; StructDef != NULL; StructDef = StructDef->Next) {
+ if (StructDef->IsNonNV) {
+ mNonNvDataStructSize = StructDef->Size;
+ break;
+ }
+ }
+ }
+ if (mNvDataStructSize == 0) {
+ for (StructDef = mFirstStructDefinition; StructDef != NULL; StructDef = StructDef->Next) {
+ if (StructDef->IsNonNV == 0) {
+ mNvDataStructSize = StructDef->Size;
+ break;
+ }
+ }
+ }
+}
+VOID
+EfiVfrParser::AddStructField (
+ CHAR8 *FieldName,
+ INT32 LineNum,
+ INT32 DataSize,
+ INT32 ArrayLength,
+ INT8 IsArray
+ )
+/*++
+
+Routine Description:
+ We're parsing the VFR structure definition. Add another defined field to
+ our definition.
+
+Arguments:
+ FieldName - name of the field in the structure.
+ LineNum - the line number from the input (preprocessor output) file
+ DataSize - the size of the field (1, 2, or 4 bytes)
+ ArrayLength - the number of elements (for array)
+ IsArray - non-zero if the field is an array
+
+Returns:
+ None.
+
+--*/
+{
+ STRUCT_FIELD_DEFINITION *FieldDef;
+ STRUCT_FIELD_DEFINITION *Temp;
+ //
+ // Make sure we don't already have a field of this name in our structure
+ //
+ for (FieldDef = mLastStructDefinition->Field; FieldDef != NULL; FieldDef = FieldDef->Next) {
+ if (strcmp (FieldDef->Name, FieldName) == 0) {
+ PrintErrorMessage (LineNum, FieldName, "field with this name already defined");
+ return;
+ }
+ }
+ //
+ // If it's an array, then they better not have a size of 0. For example:
+ // UINT8 MyBytes[0];
+ //
+ if (IsArray && (ArrayLength <= 0)) {
+ PrintErrorMessage (LineNum, FieldName, "invalid array size");
+ return;
+ }
+ //
+ // Allocate memory for a new structure field definition
+ //
+ FieldDef = (STRUCT_FIELD_DEFINITION *)malloc (sizeof (STRUCT_FIELD_DEFINITION));
+ memset ((char *)FieldDef, 0, sizeof (STRUCT_FIELD_DEFINITION));
+ FieldDef->ArrayLength = ArrayLength;
+ FieldDef->DataSize = DataSize;
+ FieldDef->IsArray = IsArray;
+ FieldDef->Name = (char *)malloc (strlen (FieldName) + 1);
+ strcpy (FieldDef->Name, FieldName);
+ //
+ // Add it to the end of the field list for the currently active structure
+ //
+ if (mLastStructDefinition->Field == NULL) {
+ mLastStructDefinition->Field = FieldDef;
+ } else {
+ mLastStructDefinition->LastField->Next = FieldDef;
+ }
+ mLastStructDefinition->LastField = FieldDef;
+}
+VOID
+EfiVfrParser::AddVarStore (
+ CHAR8 *StructName, // actual name of the structure
+ CHAR8 *VarName, // actual NV variable name
+ UINT16 VarStoreId, // key value
+ INT32 LineNum // parse line number (for error reporting)
+ )
+/*++
+
+Routine Description:
+ Called while parsing a varstore statement. Add the variable store
+ to our linked list.
+
+Arguments:
+ StructName - the name of the typedef'ed structure to use
+ VarName - the NV variable name as specified in the varstore statement
+ VarStoreId - the variable store ID as specified in the varstore statememt
+ LineNum - the line number from the input (preprocessor output) file
+
+Returns:
+ None.
+
+--*/
+{
+ STRUCT_DEFINITION *StructDef;
+ UINT16_LIST *L16Ptr;
+ //
+ // Go through our list of previously-defined variable store IDs and
+ // make sure this one is not a duplicate in name or key value.
+ //
+ for (L16Ptr = mDefinedVarStoreId; L16Ptr != NULL; L16Ptr = L16Ptr->Next) {
+ if (L16Ptr->Value == VarStoreId) {
+ PrintErrorMessage (LineNum, "variable storage key already used", NULL);
+ PrintErrorMessage (L16Ptr->LineNum, "previous usage of storage key", NULL);
+ }
+ }
+ //
+ // Key value of 0 is invalid since that's assigned by default to the default
+ // variable store (the first structure parsed).
+ //
+ if (VarStoreId == 0) {
+ PrintErrorMessage (LineNum, "variable storage key of 0 is invalid", NULL);
+ }
+ //
+ // Create a new element to add to the list
+ //
+ L16Ptr = (UINT16_LIST *)malloc(sizeof (UINT16_LIST));
+ memset (L16Ptr, 0, sizeof (UINT16_LIST));
+ L16Ptr->LineNum = LineNum;
+ L16Ptr->Value = VarStoreId;
+ if (mDefinedVarStoreId == NULL) {
+ mDefinedVarStoreId = L16Ptr;
+ } else {
+ mLastDefinedVarStoreId->Next = L16Ptr;
+ }
+ mLastDefinedVarStoreId = L16Ptr;
+ //
+ // Find the structure definition with this name
+ //
+ for (StructDef = mFirstStructDefinition; StructDef != NULL; StructDef = StructDef->Next) {
+ if (strcmp (StructDef->Name, StructName) == 0) {
+ //
+ // Make sure they did not already define a variable storage ID
+ // for this structure.
+ //
+ if (StructDef->VarStoreId != 0) {
+ PrintErrorMessage (LineNum, StructName, "variable storage already defined for this structure");
+ PrintErrorMessage (StructDef->VarStoreLineNum, StructName, "previous definition for variable storage");
+ }
+ StructDef->VarStoreId = VarStoreId;
+ StructDef->VarStoreIdValid = 1;
+ StructDef->VarStoreLineNum = LineNum;
+ WriteWord (StructDef->Size);
+ while (*VarName) {
+ WriteByte(*VarName, 0);
+ VarName++;
+ }
+ WriteByte(0,0);
+ return;
+ }
+ }
+ PrintErrorMessage (LineNum, StructName, "structure with this name not defined");
+}
+VOID
+EfiVfrParser::WriteDWord (
+ UINT32 Value,
+ UINT8 KeyByte
+ )
+/*++
+
+Routine Description:
+ During parsing, we came upon some code that requires a 32-bit value be
+ written to the VFR binary file. Queue up the 4 bytes.
+
+Arguments:
+ Value - the 32-bit value to write
+ KeyByte - a single character which gets written out beside the first byte.
+ This is used to tag the data in the output file so that during
+ debug you have an idea what the value is.
+
+Returns:
+ None.
+
+--*/
+{
+ //
+ // Write 4 bytes, little endian. Specify a key byte only on the first one
+ //
+ mOpcodeHandler.AddByte ((UINT8)Value, KeyByte);
+ Value \>>= 8;
+ mOpcodeHandler.AddByte ((UINT8)Value, 0);
+ Value \>>= 8;
+ mOpcodeHandler.AddByte ((UINT8)Value, 0);
+ Value \>>= 8;
+ mOpcodeHandler.AddByte ((UINT8)Value, 0);
+}
+VOID
+EfiVfrParser::WriteOpByte (
+ UINT32 LineNum,
+ UINT8 ByteValue
+ )
+/*++
+
+Routine Description:
+
+ During parsing, we came upon a new VFR opcode. At this point we flush
+ the output queue and then queue up this byte (with 'O' for opcode tag).
+
+Arguments:
+
+ ByteValue - opcode value
+
+Returns:
+
+ None.
+
+--*/
+{
+ mOpcodeHandler.AddOpcodeByte (ByteValue, LineNum);
+}
+VOID
+EfiVfrParser::WriteByte (
+ UINT8 ByteValue,
+ UINT8 Key
+ )
+/*++
+
+Routine Description:
+
+ During parsing of the VFR we spoonfeed this function with bytes to write to
+ the output VFR binary file. This function simply queues up the bytes, and
+ the queue gets flushed each time a new VFR opcode is encountered.
+
+Arguments:
+
+ ByteValue - raw byte to write
+ Key - character to tag the byte with when we write ByteValue to the
+ output file.
+
+Returns:
+
+ None.
+
+--*/
+{
+ mOpcodeHandler.AddByte (ByteValue, Key);
+}
+VOID
+EfiVfrParser::WriteWord (
+ UINT32 Value
+ )
+/*++
+
+Routine Description:
+ During VFR parsing we came upon a case where we need to write out a
+ 16-bit value. Queue it up.
+
+Arguments:
+ Value - value to write.
+
+Returns:
+ None.
+
+--*/
+{
+ mOpcodeHandler.AddByte ((UINT8)Value, 0);
+ mOpcodeHandler.AddByte ((UINT8)((Value \>> 8) & 0xFF), 0);
+}
+VOID
+EfiVfrParser::WriteStringIdWord (
+ UINT16 WordValue
+ )
+{
+ mOpcodeHandler.AddByte ((UINT8)WordValue, 'S');
+ mOpcodeHandler.AddByte ((UINT8)((WordValue \>> 8) & 0xFF), 0);
+}
+VOID
+EfiVfrParser::FreeGotoReferences ()
+/*++
+
+Routine Description:
+ Called during cleanup to free up the memory we allocated when
+ keeping track of VFR goto statements.
+
+Arguments:
+ None
+
+Returns:
+ None
+
+--*/
+{
+ GOTO_REFERENCE *CurrRef;
+ GOTO_REFERENCE *NextRef;
+ FORM_ID_VALUE *CurrFormId;
+ FORM_ID_VALUE *NextFormId;
+ UINT8 Found;
+ CHAR8 Name[20];
+
+ //
+ // Go through all the "goto" references and make sure there was a
+ // form ID of that value defined.
+ //
+ for (CurrRef = mGotoReferences; CurrRef != NULL; CurrRef = CurrRef->Next) {
+ Found = 0;
+ for (CurrFormId = mFormIdValues; CurrFormId != NULL; CurrFormId = CurrFormId->Next) {
+ if (CurrRef->Value == CurrFormId->Value) {
+ Found = 1;
+ break;
+ }
+ }
+ if (!Found) {
+ sprintf (Name, "%d", (UINT32)CurrRef->Value);
+ PrintErrorMessage (CurrRef->RefLineNum, Name, "undefined form ID");
+ }
+ }
+ //
+ // Now free up the form id and goto references
+ //
+ CurrFormId = mFormIdValues;
+ while (CurrFormId != NULL) {
+ NextFormId = CurrFormId->Next;
+ free (CurrFormId);
+ CurrFormId = NextFormId;
+ }
+ mFormIdValues = NULL;
+ CurrRef = mGotoReferences;
+ while (CurrRef != NULL) {
+ NextRef = CurrRef->Next;
+ free (CurrRef);
+ CurrRef = NextRef;
+ }
+ mGotoReferences = NULL;
+}
+VOID
+EfiVfrParser::AddGotoReference (
+ UINT32 GotoNumber,
+ UINT32 LineNum
+ )
+/*++
+
+Routine Description:
+ During VFR parsing we came upon a goto statement. Since we support
+ forward references, save the referenced label and at the end of parsing
+ we'll check that the label was actually defined somewhere.
+
+Arguments:
+ GotoNumber - the label number referenced
+ LineNum - the line number where the reference was made (used for
+ error reporting)
+
+Returns:
+ None
+
+--*/
+{
+ GOTO_REFERENCE *NewRef;
+
+ NewRef = (GOTO_REFERENCE *)malloc (sizeof (GOTO_REFERENCE));
+ if (NewRef == NULL) {
+ Error (PROGRAM_NAME, 0, 0, NULL, "memory allocation failure");
+ return;
+ }
+ memset ((char *)NewRef, 0, sizeof (GOTO_REFERENCE));
+ NewRef->Value = (UINT16)GotoNumber;
+ NewRef->RefLineNum = LineNum;
+ NewRef->Next = mGotoReferences;
+ mGotoReferences = NewRef;
+}
+VOID
+EfiVfrParser::AddFormId (
+ INT32 FormIdValue,
+ UINT32 LineNum
+ )
+/*++
+
+Routine Description:
+ This function is called when we parse "form formid = 3" statements.
+ We save the form ID valud so we can verify that duplicates are not
+ defined. Also, these are the targets of goto statements, so when we're
+ done parsing the script we also go through all the goto statements to
+ check that there was a target FormId defined as referenced by each
+ goto statement.
+
+ Note that formid = 0 is invalid.
+
+Arguments:
+ FormIdValue - the parsed value for the Form ID
+ LineNum - line number of the source file we're parsing
+
+Returns:
+ NA
+
+--*/
+{
+ FORM_ID_VALUE *NewFormId;
+ char *FileName;
+ char *FileName2;
+ UINT32 LineNum2;
+ //
+ // Verify that FormId != 0
+ //
+ if (FormIdValue == 0) {
+ FileName = ConvertLineNumber (&LineNum);
+ Error (FileName, LineNum, 0, "form ID cannot be 0", NULL);
+ return;
+ }
+ //
+ // First go through all previously defined form IDs and make sure they have not defined
+ // duplicates.
+ //
+ for (NewFormId = mFormIdValues; NewFormId != NULL; NewFormId = NewFormId->Next) {
+ if ((UINT16)FormIdValue == NewFormId->Value) {
+ FileName = ConvertLineNumber (&LineNum);
+ LineNum2 = NewFormId->LineNum;
+ FileName2 = ConvertLineNumber (&LineNum2);
+ Error (FileName, LineNum, 0, NULL, "form ID %d already defined", FormIdValue);
+ Error (FileName2, LineNum2, 0, NULL, "form ID %d previous definition", FormIdValue);
+ return;
+ }
+ }
+ //
+ // Allocate memory for a new one
+ //
+ NewFormId = (FORM_ID_VALUE *)malloc (sizeof (FORM_ID_VALUE));
+ if (NewFormId == NULL) {
+ Error (PROGRAM_NAME, 0, 0, NULL, "memory allocation failure");
+ return;
+ }
+ memset ((char *)NewFormId, 0, sizeof (FORM_ID_VALUE));
+ NewFormId->LineNum = LineNum;
+ NewFormId->Next = mFormIdValues;
+ NewFormId->Value = (UINT16)FormIdValue;
+ mFormIdValues = NewFormId;
+}
+UINT32
+EfiVfrParser::GetNumber (
+ CHAR8 *NumStr,
+ UINT32 LineNum,
+ UINT32 NumBytes
+ )
+{
+ UINT32 Value;
+
+ if ((NumStr[0] == '0') && (NumStr[1] == 'x')) {
+ AtoX (NumStr + 2, 4, &Value);
+ } else {
+ Value = (UINT32)atoi (NumStr);
+ }
+ //
+ // Check range
+ //
+ if ((NumBytes < 4) && (Value & ((UINT32)0xFFFFFFFF << (NumBytes * 8)))) {
+ PrintErrorMessage (LineNum, NumStr, "value out of range");
+ return 0;
+ }
+ return Value;
+}
+
+>>
+
+} // end grammar class
+
diff --git a/Source/VfrCompile/VfrServices.cpp b/Source/VfrCompile/VfrServices.cpp
new file mode 100644
index 0000000..359256a
--- /dev/null
+++ b/Source/VfrCompile/VfrServices.cpp
@@ -0,0 +1,758 @@
+/*++
+
+Copyright (c) 2004 - 2005, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ VfrServices.cpp
+
+Abstract:
+
+ Support routines for the VFR compiler
+
+--*/
+
+#include <stdio.h> // for FILE routines
+#include <stdlib.h> // for malloc() and free()
+
+#include <Common/UefiBaseTypes.h>
+#include <Common/MultiPhase.h>
+#include <Common/InternalFormRepresentation.h>
+#include <Protocol/UgaDraw.h> // for EFI_UGA_PIXEL definition
+#include <Protocol/Hii.h>
+
+#include "EfiUtilityMsgs.h"
+#include "EfiVfr.h"
+#include "VfrServices.h"
+
+
+static const char *mSourceFileHeader[] = {
+ "//",
+ "// DO NOT EDIT -- auto-generated file",
+ "//",
+ "// This file is generated by the VFR compiler.",
+ "//",
+ NULL
+};
+
+typedef struct {
+ CHAR8 *Name;
+ INT32 Size;
+} IFR_OPCODE_SIZES;
+
+//
+// Create a table that can be used to do internal checking on the IFR
+// bytes we emit.
+//
+static const IFR_OPCODE_SIZES mOpcodeSizes[] = {
+ { 0, 0 }, // invalid
+ { "EFI_IFR_FORM", sizeof (EFI_IFR_FORM) },
+ { "EFI_IFR_SUBTITLE", sizeof (EFI_IFR_SUBTITLE) },
+ { "EFI_IFR_TEXT", -6 }, //sizeof (EFI_IFR_TEXT) },
+ { "unused 0x04 opcode", 0 }, // EFI_IFR_GRAPHIC_OP
+ { "EFI_IFR_ONE_OF", sizeof (EFI_IFR_ONE_OF) },
+ { "EFI_IFR_CHECKBOX", sizeof (EFI_IFR_CHECKBOX) },
+ { "EFI_IFR_NUMERIC", sizeof (EFI_IFR_NUMERIC) },
+ { "EFI_IFR_PASSWORD", sizeof (EFI_IFR_PASSWORD) },
+ { "EFI_IFR_ONE_OF_OPTION", sizeof (EFI_IFR_ONE_OF_OPTION) },
+ { "EFI_IFR_SUPPRESS", sizeof (EFI_IFR_SUPPRESS) },
+ { "EFI_IFR_END_FORM", sizeof (EFI_IFR_END_FORM) },
+ { "EFI_IFR_HIDDEN", sizeof (EFI_IFR_HIDDEN) },
+ { "EFI_IFR_END_FORM_SET", sizeof (EFI_IFR_END_FORM_SET) },
+ { "EFI_IFR_FORM_SET", sizeof (EFI_IFR_FORM_SET) },
+ { "EFI_IFR_REF", sizeof (EFI_IFR_REF) },
+ { "EFI_IFR_END_ONE_OF", sizeof (EFI_IFR_END_ONE_OF) },
+ { "EFI_IFR_INCONSISTENT", sizeof (EFI_IFR_INCONSISTENT) },
+ { "EFI_IFR_EQ_ID_VAL", sizeof (EFI_IFR_EQ_ID_VAL) },
+ { "EFI_IFR_EQ_ID_ID", sizeof (EFI_IFR_EQ_ID_ID) },
+ { "EFI_IFR_EQ_ID_LIST", -sizeof (EFI_IFR_EQ_ID_LIST) },
+ { "EFI_IFR_AND", sizeof (EFI_IFR_AND) },
+ { "EFI_IFR_OR", sizeof (EFI_IFR_OR) },
+ { "EFI_IFR_NOT", sizeof (EFI_IFR_NOT) },
+ { "EFI_IFR_END_EXPR", sizeof (EFI_IFR_END_EXPR) },
+ { "EFI_IFR_GRAY_OUT", sizeof (EFI_IFR_GRAY_OUT) },
+ { "EFI_IFR_DATE", sizeof (EFI_IFR_DATE) / 3 },
+ { "EFI_IFR_TIME", sizeof (EFI_IFR_TIME) / 3 },
+ { "EFI_IFR_STRING", sizeof (EFI_IFR_STRING) },
+ { "EFI_IFR_LABEL", sizeof (EFI_IFR_LABEL) },
+ { "EFI_IFR_SAVE_DEFAULTS", sizeof (EFI_IFR_SAVE_DEFAULTS) },
+ { "EFI_IFR_RESTORE_DEFAULTS", sizeof (EFI_IFR_RESTORE_DEFAULTS) },
+ { "EFI_IFR_BANNER", sizeof (EFI_IFR_BANNER) },
+ { "EFI_IFR_INVENTORY", sizeof (EFI_IFR_INVENTORY) },
+ { "EFI_IFR_EQ_VAR_VAL_OP", sizeof (EFI_IFR_EQ_VAR_VAL) },
+ { "EFI_IFR_ORDERED_LIST_OP", sizeof (EFI_IFR_ORDERED_LIST) },
+ { "EFI_IFR_VARSTORE_OP", -sizeof (EFI_IFR_VARSTORE) },
+ { "EFI_IFR_VARSTORE_SELECT_OP", sizeof (EFI_IFR_VARSTORE_SELECT) },
+ { "EFI_IFR_VARSTORE_SELECT_PAIR_OP", sizeof (EFI_IFR_VARSTORE_SELECT_PAIR) },
+ { "EFI_IFR_TRUE", sizeof (EFI_IFR_TRUE)},
+ { "EFI_IFR_FALSE", sizeof (EFI_IFR_FALSE)},
+ { "EFI_IFR_GT", sizeof (EFI_IFR_GT)},
+ { "EFI_IFR_GE", sizeof (EFI_IFR_GE)},
+ { "EFI_IFR_OEM_DEFINED_OP", -2 },
+};
+
+
+VfrOpcodeHandler::VfrOpcodeHandler (
+ )
+/*++
+
+Routine Description:
+ Constructor for the VFR opcode handling class.
+
+Arguments:
+ None
+
+Returns:
+ None
+
+--*/
+{
+ mIfrBytes = NULL;
+ mLastIfrByte = NULL;
+ mBytesWritten = 0;
+ mQueuedByteCount = 0;
+ mQueuedOpcodeByteValid = 0;
+ mPrimaryVarStoreId = 0;
+ mSecondaryVarStoreId = 0;
+ mSecondaryVarStoreIdSet = 0;
+ mPrimaryVarStoreIdSet = 0;
+ mDefaultVarStoreId = 0;
+}
+
+VOID
+VfrOpcodeHandler::SetVarStoreId (
+ UINT16 VarStoreId
+ )
+/*++
+
+Routine Description:
+ This function is invoked by the parser when a variable is referenced in the
+ VFR. Save the variable store (and set a flag) so that we can later determine
+ if we need to emit a varstore-select or varstore-select-pair opcode.
+
+Arguments:
+ VarStoreId - ID of the variable store referenced in the VFR
+
+Returns:
+ None
+
+--*/
+{
+ mPrimaryVarStoreId = VarStoreId;
+ mPrimaryVarStoreIdSet = 1;
+}
+
+VOID
+VfrOpcodeHandler::SetSecondaryVarStoreId (
+ UINT16 VarStoreId
+ )
+/*++
+
+Routine Description:
+ This function is invoked by the parser when a secondary variable is
+ referenced in the VFR. Save the variable store (and set a flag) so
+ that we can later determine if we need to emit a varstore-select or
+ varstore-pair opcode.
+
+Arguments:
+ VarStoreId - ID of the variable store referenced in the VFR
+
+Returns:
+ None
+
+--*/
+{
+ mSecondaryVarStoreId = VarStoreId;
+ mSecondaryVarStoreIdSet = 1;
+}
+
+VOID
+VfrOpcodeHandler::WriteIfrBytes (
+ )
+/*++
+
+Routine Description:
+ This function is invoked at the end of parsing. Its purpose
+ is to write out all the IFR bytes that were queued up while
+ parsing.
+
+Arguments:
+ None
+
+Returns:
+ None
+
+--*/
+{
+ IFR_BYTE *Curr;
+ IFR_BYTE *Next;
+ UINT32 Count;
+ UINT32 LineCount;
+ UINT32 PoundLines;
+ UINT32 ByteCount;
+ CHAR8 Line[MAX_LINE_LEN];
+ CHAR8 *Cptr;
+ FILE *InFptr;
+ FILE *OutFptr;
+ UINT32 ListFile;
+ EFI_HII_IFR_PACK_HEADER IfrHeader;
+ UINT8 *Ptr;
+ FILE *IfrBinFptr;
+ UINT32 BytesLeftThisOpcode;
+ //
+ // If someone added a new opcode and didn't update our opcode sizes structure, error out.
+ //
+ if (sizeof(mOpcodeSizes) / sizeof (mOpcodeSizes[0]) != EFI_IFR_LAST_OPCODE + 1) {
+ Error (__FILE__, __LINE__, 0, "application error", "internal IFR binary table size is incorrect");
+ return;
+ }
+ //
+ // Flush the queue
+ //
+ FlushQueue ();
+ //
+ // If there have been any errors to this point, then skip dumping the IFR
+ // binary data. This way doing an nmake again will try to build it again, and
+ // the build will fail if they did not fix the problem.
+ //
+ if (GetUtilityStatus () != STATUS_ERROR) {
+ if ((IfrBinFptr = fopen (gOptions.IfrOutputFileName, "w")) == NULL) {
+ Error (PROGRAM_NAME, 0, 0, gOptions.IfrOutputFileName, "could not open file for writing");
+ return;
+ }
+ //
+ // Write the standard file header to the output file
+ //
+ WriteStandardFileHeader (IfrBinFptr);
+ //
+ // Write the structure header
+ //
+ fprintf (IfrBinFptr, "\nunsigned char %sBin[] = {", gOptions.VfrBaseFileName);
+ //
+ // Write the header
+ //
+ memset ((char *)&IfrHeader, 0, sizeof (IfrHeader));
+ IfrHeader.Header.Type = EFI_HII_IFR;
+ IfrHeader.Header.Length = mBytesWritten + sizeof (IfrHeader);
+ Ptr = (UINT8 *)&IfrHeader;
+ for (Count = 0; Count < sizeof (IfrHeader); Count++, Ptr++) {
+ if ((Count & 0x03) == 0) {
+ fprintf (IfrBinFptr, "\n ");
+ }
+ fprintf (IfrBinFptr, "0x%02X, ", *Ptr);
+ }
+ //
+ //
+ // Write all the IFR bytes
+ //
+ fprintf (IfrBinFptr, "\n // start of IFR data");
+ Curr = mIfrBytes;
+ Count = 0;
+ while (Curr != NULL) {
+ if ((Count & 0x0F) == 0) {
+ fprintf (IfrBinFptr, "\n ");
+ }
+ if (Curr->KeyByte != 0) {
+ fprintf (IfrBinFptr, "/*%c*/ ", Curr->KeyByte);
+ }
+ fprintf (IfrBinFptr, "0x%02X, ", Curr->OpcodeByte);
+ Count++;
+ Curr = Curr->Next;
+ }
+ fprintf (IfrBinFptr, "\n};\n\n");
+ //
+ //
+ // Close the file
+ //
+ fclose (IfrBinFptr);
+ IfrBinFptr = NULL;
+ }
+ //
+ // Write the bytes as binary data if the user specified to do so
+ //
+ if ((GetUtilityStatus () != STATUS_ERROR) && (gOptions.CreateIfrBinFile != 0)) {
+ //
+ // Use the Ifr output file name with a ".hpk" extension.
+ //
+ for (Cptr = gOptions.IfrOutputFileName + strlen (gOptions.IfrOutputFileName) - 1;
+ (*Cptr != '.') && (Cptr > gOptions.IfrOutputFileName) && (*Cptr != '\\');
+ Cptr--) {
+ //
+ // do nothing
+ //
+ }
+ if (*Cptr == '.') {
+ strcpy (Cptr, ".hpk");
+ } else {
+ strcat (gOptions.IfrOutputFileName, ".hpk");
+ }
+ if ((IfrBinFptr = fopen (gOptions.IfrOutputFileName, "wb")) == NULL) {
+ Error (PROGRAM_NAME, 0, 0, gOptions.IfrOutputFileName, "could not open file for writing");
+ return;
+ }
+ //
+ // Write the structure header
+ //
+ memset ((char *)&IfrHeader, 0, sizeof (IfrHeader));
+ IfrHeader.Header.Type = EFI_HII_IFR;
+ IfrHeader.Header.Length = mBytesWritten + sizeof (IfrHeader);
+ Ptr = (UINT8 *)&IfrHeader;
+ for (Count = 0; Count < sizeof (IfrHeader); Count++, Ptr++) {
+ fwrite (Ptr, 1, 1, IfrBinFptr);
+ }
+ //
+ //
+ // Write all the IFR bytes
+ //
+ Curr = mIfrBytes;
+ Count = 0;
+ while (Curr != NULL) {
+ fwrite (&Curr->OpcodeByte, 1, 1, IfrBinFptr);
+ Curr = Curr->Next;
+ }
+ //
+ //
+ // Close the file
+ //
+ fclose (IfrBinFptr);
+ IfrBinFptr = NULL;
+ }
+ //
+ // If creating a listing file, then open the input and output files
+ //
+ ListFile = 0;
+ if (gOptions.CreateListFile) {
+ //
+ // Open the input VFR file and the output list file
+ //
+ if ((InFptr = fopen (gOptions.PreprocessorOutputFileName, "r")) == NULL) {
+ Warning (PROGRAM_NAME, 0, 0, gOptions.PreprocessorOutputFileName, "could not open file for creating a list file");
+ } else {
+ if ((OutFptr = fopen (gOptions.VfrListFileName, "w")) == NULL) {
+ Warning (PROGRAM_NAME, 0, 0, gOptions.VfrListFileName, "could not open output list file for writing");
+ fclose (InFptr);
+ InFptr = NULL;
+ } else {
+ LineCount = 0;
+ ListFile = 1;
+ PoundLines = 0;
+ ByteCount = 0;
+ }
+ }
+ }
+ //
+ // Write the list file
+ //
+ if (ListFile) {
+ //
+ // Write out the VFR compiler version
+ //
+ fprintf (OutFptr, "//\n// VFR compiler version " VFR_COMPILER_VERSION "\n//\n");
+ Curr = mIfrBytes;
+ while (Curr != NULL) {
+ //
+ // Print lines until we reach the line of the current opcode
+ //
+ while (LineCount < PoundLines + Curr->LineNum) {
+ if (fgets (Line, sizeof (Line), InFptr) != NULL) {
+ //
+ // We should check for line length exceeded on the fgets(). Otherwise it
+ // throws the listing file output off. Future enhancement perhaps.
+ //
+ fprintf (OutFptr, "%s", Line);
+ if (strncmp (Line, "#line", 5) == 0) {
+ PoundLines++;
+ }
+ }
+ LineCount++;
+ }
+ //
+ // Print all opcodes with line numbers less than where we are now
+ //
+ BytesLeftThisOpcode = 0;
+ while ((Curr != NULL) && ((Curr->LineNum == 0) || (LineCount >= PoundLines + Curr->LineNum))) {
+ if (BytesLeftThisOpcode == 0) {
+ fprintf (OutFptr, ">%08X: ", ByteCount);
+ if (Curr->Next != NULL) {
+ BytesLeftThisOpcode = (UINT32)Curr->Next->OpcodeByte;
+ }
+ }
+ fprintf (OutFptr, "%02X ", (UINT32)Curr->OpcodeByte);
+ ByteCount++;
+ BytesLeftThisOpcode--;
+ if (BytesLeftThisOpcode == 0) {
+ fprintf (OutFptr, "\n");
+ }
+ Curr = Curr->Next;
+ }
+ }
+ //
+ // Dump any remaining lines from the input file
+ //
+ while (fgets (Line, sizeof (Line), InFptr) != NULL) {
+ fprintf (OutFptr, "%s", Line);
+ }
+ fclose (InFptr);
+ fclose (OutFptr);
+ }
+ //
+ // Debug code to make sure that each opcode we write out has as many
+ // bytes as the IFR structure requires. If there were errors, then
+ // don't do this step.
+ //
+ if (GetUtilityStatus () != STATUS_ERROR) {
+ Curr = mIfrBytes;
+ ByteCount = 0;
+ while (Curr != NULL) {
+ //
+ // First byte is the opcode, second byte is the length
+ //
+ if (Curr->Next == NULL) {
+ Error (__FILE__, __LINE__, 0, "application error", "last opcode written does not contain a length byte");
+ break;
+ }
+ Count = (UINT32)Curr->Next->OpcodeByte;
+ if (Count == 0) {
+ Error (
+ __FILE__,
+ __LINE__,
+ 0,
+ "application error",
+ "opcode with 0 length specified in output at offset 0x%X",
+ ByteCount
+ );
+ break;
+ }
+ //
+ // Check the length
+ //
+ if ((Curr->OpcodeByte > EFI_IFR_LAST_OPCODE) || (Curr->OpcodeByte == 0)) {
+ Error (
+ __FILE__,
+ __LINE__,
+ 0,
+ "application error",
+ "invalid opcode 0x%X in output at offset 0x%X",
+ (UINT32) Curr->OpcodeByte, ByteCount
+ );
+ } else if (mOpcodeSizes[Curr->OpcodeByte].Size < 0) {
+ //
+ // For those cases where the length is variable, the size is negative, and indicates
+ // the miniumum size.
+ //
+ if ((mOpcodeSizes[Curr->OpcodeByte].Size * -1) > Count) {
+ Error (
+ __FILE__,
+ __LINE__,
+ 0,
+ "application error",
+ "insufficient number of bytes written for %s at offset 0x%X",
+ mOpcodeSizes[Curr->OpcodeByte].Name,
+ ByteCount
+ );
+ }
+ } else {
+ //
+ // Check for gaps
+ //
+ if (mOpcodeSizes[Curr->OpcodeByte].Size == 0) {
+ Error (
+ __FILE__,
+ __LINE__,
+ 0,
+ "application error",
+ "invalid opcode 0x%X in output at offset 0x%X",
+ (UINT32)Curr->OpcodeByte,
+ ByteCount
+ );
+ } else {
+ //
+ // Check size
+ //
+ if (mOpcodeSizes[Curr->OpcodeByte].Size != Count) {
+ Error (
+ __FILE__,
+ __LINE__,
+ 0,
+ "application error",
+ "invalid number of bytes (%d written s/b %d) written for %s at offset 0x%X",
+ Count,
+ mOpcodeSizes[Curr->OpcodeByte].Size,
+ mOpcodeSizes[Curr->OpcodeByte].Name,
+ ByteCount
+ );
+ }
+ }
+ }
+ //
+ // Skip to next opcode
+ //
+ while (Count > 0) {
+ ByteCount++;
+ if (Curr == NULL) {
+ Error (__FILE__, __LINE__, 0, "application error", "last opcode written has invalid length");
+ break;
+ }
+ Curr = Curr->Next;
+ Count--;
+ }
+ }
+ }
+}
+
+VfrOpcodeHandler::~VfrOpcodeHandler(
+ )
+/*++
+
+Routine Description:
+ Destructor for the VFR opcode handler. Free up memory allocated
+ while parsing the VFR script.
+
+Arguments:
+ None
+
+Returns:
+ None
+
+--*/
+{
+ IFR_BYTE *Curr;
+ IFR_BYTE *Next;
+ //
+ // Free up the IFR bytes
+ //
+ Curr = mIfrBytes;
+ while (Curr != NULL) {
+ Next = Curr->Next;
+ free (Curr);
+ Curr = Next;
+ }
+}
+
+int
+VfrOpcodeHandler::AddOpcodeByte (
+ UINT8 OpcodeByte,
+ UINT32 LineNum
+ )
+/*++
+
+Routine Description:
+ This function is invoked by the parser when a new IFR
+ opcode should be emitted.
+
+Arguments:
+ OpcodeByte - the IFR opcode
+ LineNum - the line number from the source file that resulted
+ in the opcode being emitted.
+
+Returns:
+ 0 always
+
+--*/
+{
+ UINT32 Count;
+
+ FlushQueue();
+ //
+ // Now add this new byte
+ //
+ mQueuedOpcodeByte = OpcodeByte;
+ mQueuedLineNum = LineNum;
+ mQueuedOpcodeByteValid = 1;
+ return 0;
+}
+
+VOID
+VfrOpcodeHandler::AddByte (
+ UINT8 ByteVal,
+ UINT8 KeyByte
+ )
+/*++
+
+Routine Description:
+ This function is invoked by the parser when it determines
+ that more raw IFR bytes should be emitted to the output stream.
+ Here we just queue them up into an output buffer.
+
+Arguments:
+ ByteVal - the raw byte to emit to the output IFR stream
+ KeyByte - a value that can be used for debug.
+
+Returns:
+ None
+
+--*/
+{
+ //
+ // Check for buffer overflow
+ //
+ if (mQueuedByteCount > MAX_QUEUE_COUNT) {
+ Error (PROGRAM_NAME, 0, 0, NULL, "opcode queue overflow");
+ } else {
+ mQueuedBytes[mQueuedByteCount] = ByteVal;
+ mQueuedKeyBytes[mQueuedByteCount] = KeyByte;
+ mQueuedByteCount++;
+ }
+}
+
+int
+VfrOpcodeHandler::FlushQueue (
+ )
+/*++
+
+Routine Description:
+ This function is invoked to flush the internal IFR buffer.
+
+Arguments:
+ None
+
+Returns:
+ 0 always
+
+--*/
+{
+ UINT32 Count;
+ UINT32 EmitNoneOnePair;
+
+ EmitNoneOnePair = 0;
+ //
+ // If the secondary varstore was specified, then we have to emit
+ // a varstore-select-pair opcode, which only applies to the following
+ // statement.
+ //
+ if (mSecondaryVarStoreIdSet) {
+ mSecondaryVarStoreIdSet = 0;
+ //
+ // If primary and secondary are the same as the current default
+ // varstore, then we don't have to do anything.
+ // Note that the varstore-select-pair only applies to the following
+ // opcode.
+ //
+ if ((mPrimaryVarStoreId != mSecondaryVarStoreId) || (mPrimaryVarStoreId != mDefaultVarStoreId)) {
+ IAddByte (EFI_IFR_VARSTORE_SELECT_PAIR_OP, 'O', mQueuedLineNum);
+ IAddByte ((UINT8)sizeof (EFI_IFR_VARSTORE_SELECT_PAIR), 'L', 0);
+ IAddByte ((UINT8)mPrimaryVarStoreId, 0, 0);
+ IAddByte ((UINT8)(mPrimaryVarStoreId >> 8), 0, 0);
+ IAddByte ((UINT8)mSecondaryVarStoreId, 0, 0);
+ IAddByte ((UINT8)(mSecondaryVarStoreId >> 8), 0, 0);
+ }
+ } else if (mPrimaryVarStoreIdSet != 0) {
+ mPrimaryVarStoreIdSet = 0;
+ if (mDefaultVarStoreId != mPrimaryVarStoreId) {
+ //
+ // The VFR statement referenced a different variable store
+ // than the last one we reported. Insert a new varstore select
+ // statement.
+ //
+ IAddByte (EFI_IFR_VARSTORE_SELECT_OP, 'O', mQueuedLineNum);
+ IAddByte ((UINT8)sizeof (EFI_IFR_VARSTORE_SELECT), 'L', 0);
+ IAddByte ((UINT8)mPrimaryVarStoreId, 0, 0);
+ IAddByte ((UINT8)(mPrimaryVarStoreId >> 8), 0, 0);
+ mDefaultVarStoreId = mPrimaryVarStoreId;
+ }
+ }
+ //
+ // Likely a new opcode is being added. Since each opcode item in the IFR has
+ // a header that specifies the size of the opcode item (which we don't
+ // know until we find the next opcode in the VFR), we queue up bytes
+ // until we know the size. Then we write them out. So flush the queue
+ // now.
+ //
+ if (mQueuedOpcodeByteValid != 0) {
+ //
+ // Add the previous opcode byte, the length byte, and the binary
+ // data.
+ //
+ IAddByte (mQueuedOpcodeByte, 'O', mQueuedLineNum);
+ IAddByte ((UINT8)(mQueuedByteCount + 2), 'L', 0);
+ for (Count = 0; Count < mQueuedByteCount; Count++) {
+ IAddByte (mQueuedBytes[Count], mQueuedKeyBytes[Count], 0);
+ }
+ mQueuedByteCount = 0;
+ mQueuedOpcodeByteValid = 0;
+ }
+ return 0;
+}
+
+int
+VfrOpcodeHandler::IAddByte (
+ UINT8 ByteVal,
+ UINT8 KeyByte,
+ UINT32 LineNum
+ )
+/*++
+
+Routine Description:
+ This internal function is used to add actual IFR bytes to
+ the output stream. Most other functions queue up the bytes
+ in an internal buffer. Once they come here, there's no
+ going back.
+
+
+Arguments:
+ ByteVal - value to write to output
+ KeyByte - key value tied to the byte -- useful for debug
+ LineNum - line number from source file the byte resulted from
+
+Returns:
+ 0 - if successful
+ 1 - failed due to memory allocation failure
+
+--*/
+{
+ IFR_BYTE *NewByte;
+ NewByte = (IFR_BYTE *)malloc (sizeof (IFR_BYTE));
+ if (NewByte == NULL) {
+ return 1;
+ }
+ memset ((char *)NewByte, 0, sizeof (IFR_BYTE));
+ NewByte->OpcodeByte = ByteVal;
+ NewByte->KeyByte = KeyByte;
+ NewByte->LineNum = LineNum;
+ //
+ // Add to the list
+ //
+ if (mIfrBytes == NULL) {
+ mIfrBytes = NewByte;
+ } else {
+ mLastIfrByte->Next = NewByte;
+ }
+ mLastIfrByte = NewByte;
+ mBytesWritten++;
+ return 0;
+}
+
+VOID
+WriteStandardFileHeader (
+ FILE *OutFptr
+ )
+/*++
+
+Routine Description:
+ This function is invoked to emit a standard header to an
+ output text file.
+
+Arguments:
+ OutFptr - file to write the header to
+
+Returns:
+ None
+
+--*/
+{
+ UINT32 TempIndex;
+ for (TempIndex = 0; mSourceFileHeader[TempIndex] != NULL; TempIndex++) {
+ fprintf (OutFptr, "%s\n", mSourceFileHeader[TempIndex]);
+ }
+ //
+ // Write out the VFR compiler version
+ //
+ fprintf (OutFptr, "// VFR compiler version " VFR_COMPILER_VERSION "\n//\n");
+}
diff --git a/Source/VfrCompile/VfrServices.h b/Source/VfrCompile/VfrServices.h
new file mode 100644
index 0000000..6b8c560
--- /dev/null
+++ b/Source/VfrCompile/VfrServices.h
@@ -0,0 +1,227 @@
+/*++
+
+Copyright (c) 2004, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ VfrServices.h
+
+Abstract:
+
+ Prototypes and defines for routines and classes used by the
+ EFI VFR compiler.
+
+--*/
+
+#ifndef _VFR_SERVICES_H_
+#define _VFR_SERVICES_H_
+
+class VfrOpcodeHandler
+{
+public:
+ VfrOpcodeHandler (
+ VOID
+ )
+ /*++
+
+Routine Description:
+ Constructor for the VFR opcode handling class.
+
+Arguments:
+ None
+
+Returns:
+ None
+
+--*/
+ ;
+ ~VfrOpcodeHandler (
+ VOID
+ )
+ /*++
+
+Routine Description:
+ Destructor for the VFR opcode handler. Free up memory allocated
+ while parsing the VFR script.
+
+Arguments:
+ None
+
+Returns:
+ None
+
+--*/
+ ;
+ void
+ WriteIfrBytes (
+ VOID
+ )
+ /*++
+
+Routine Description:
+ This function is invoked at the end of parsing. Its purpose
+ is to write out all the IFR bytes that were queued up while
+ parsing.
+
+Arguments:
+ None
+
+Returns:
+ None
+
+--*/
+ ;
+ int
+ AddOpcodeByte (
+ UINT8 OpcodeByte,
+ UINT32 LineNum
+ )
+ /*++
+
+Routine Description:
+ This function is invoked by the parser when a new IFR
+ opcode should be emitted.
+
+Arguments:
+ OpcodeByte - the IFR opcode
+ LineNum - the line number from the source file that resulted
+ in the opcode being emitted.
+
+Returns:
+ 0 always
+
+--*/
+ ;
+ void
+ AddByte (
+ UINT8 ByteVal,
+ UINT8 KeyByte
+ )
+ /*++
+
+Routine Description:
+ This function is invoked by the parser when it determines
+ that more raw IFR bytes should be emitted to the output stream.
+ Here we just queue them up into an output buffer.
+
+Arguments:
+ ByteVal - the raw byte to emit to the output IFR stream
+ KeyByte - a value that can be used for debug.
+
+Returns:
+ None
+
+--*/
+ ;
+ void
+ SetVarStoreId (
+ UINT16 VarStoreId
+ )
+ /*++
+
+Routine Description:
+ This function is invoked by the parser when a variable is referenced in the
+ VFR. Save the variable store (and set a flag) so that we can later determine
+ if we need to emit a varstore-select or varstore-select-pair opcode.
+
+Arguments:
+ VarStoreId - ID of the variable store referenced in the VFR
+
+Returns:
+ None
+
+--*/
+ ;
+ void
+ SetSecondaryVarStoreId (
+ UINT16 VarStoreId
+ )
+ /*++
+
+Routine Description:
+ This function is invoked by the parser when a secondary variable is
+ referenced in the VFR. Save the variable store (and set a flag) so
+ that we can later determine if we need to emit a varstore-select or
+ varstore-pair opcode.
+
+Arguments:
+ VarStoreId - ID of the variable store referenced in the VFR
+
+Returns:
+ None
+
+--*/
+ ;
+
+/* */
+private:
+ int
+ FlushQueue (
+ VOID
+ )
+ /*++
+
+Routine Description:
+ This function is invoked to flush the internal IFR buffer.
+
+Arguments:
+ None
+
+Returns:
+ 0 always
+
+--*/
+ ;
+ int
+ IAddByte (
+ UINT8 ByteVal,
+ UINT8 KeyByte,
+ UINT32 LineNum
+ )
+ /*++
+
+Routine Description:
+ This internal function is used to add actual IFR bytes to
+ the output stream. Most other functions queue up the bytes
+ in an internal buffer. Once they come here, there's no
+ going back.
+
+
+Arguments:
+ ByteVal - value to write to output
+ KeyByte - key value tied to the byte -- useful for debug
+ LineNum - line number from source file the byte resulted from
+
+Returns:
+ 0 - if successful
+ 1 - failed due to memory allocation failure
+
+--*/
+ ;
+
+/* */
+private:
+ IFR_BYTE *mIfrBytes;
+ IFR_BYTE *mLastIfrByte;
+ UINT32 mQueuedByteCount;
+ UINT32 mBytesWritten;
+ UINT32 mQueuedLineNum;
+ UINT8 mQueuedBytes[MAX_QUEUE_COUNT];
+ UINT8 mQueuedKeyBytes[MAX_QUEUE_COUNT];
+ UINT8 mQueuedOpcodeByte;
+ UINT32 mQueuedOpcodeByteValid;
+ UINT16 mPrimaryVarStoreId;
+ UINT8 mPrimaryVarStoreIdSet;
+ UINT16 mSecondaryVarStoreId;
+ UINT8 mSecondaryVarStoreIdSet;
+ UINT16 mDefaultVarStoreId;
+};
+
+#endif // #ifndef _VFR_SERVICES_H_
diff --git a/Source/VfrCompile/build.xml b/Source/VfrCompile/build.xml
new file mode 100644
index 0000000..51770d8
--- /dev/null
+++ b/Source/VfrCompile/build.xml
@@ -0,0 +1,122 @@
+<?xml version="1.0" ?>
+<!--
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+-->
+<project default="GenTool" basedir="." name="VfrCompile">
+<!--
+ EDK VfrCompile Tool
+ Copyright (c) 2006, Intel Corporation
+-->
+ <property name="ToolName" value="VfrCompile"/>
+ <property name="FileSet" value="*.cpp"/>
+ <property name="FileSetPccts" value="ATokenBuffer.cpp DLexerBase.cpp AParser.cpp"/>
+ <taskdef resource="net/sf/antcontrib/antlib.xml"/>
+
+ <property name="LINK_OUTPUT_TYPE" value="static"/>
+ <property name="BUILD_DIR" value="${PACKAGE_DIR}/${ToolName}/tmp"/>
+
+ <target name="GenTool" depends="init, Antlr, Dlg, Tool">
+ <echo message="The EDK Tool: ${ToolName} build has completed"/>
+ </target>
+
+ <target name="init">
+
+ <echo message="Building the EDK Tool: ${ToolName}"/>
+ <mkdir dir="${BUILD_DIR}"/>
+
+ <condition property="AntlrDepends">
+ <uptodate targetfile="${PACKAGE_DIR}/VfrCompile/parser.dlg" srcfile="${PACKAGE_DIR}/VfrCompile/VfrCompile.g" value="true"/>
+ </condition>
+
+ <condition property="DlgDepends">
+ <uptodate targetfile="${PACKAGE_DIR}/VfrCompile/DLGLexer.cpp" srcfile="${PACKAGE_DIR}/VfrCompile/parser.dlg" value="true"/>
+ </condition>
+
+ <condition property="CheckDepends">
+ <or>
+ <isset property="AntlrDepends"/>
+ <isset property="DlgDepends"/>
+ </or>
+ </condition>
+
+ <condition property="gxx_extra_libs" value="stdc++ System gcc_s.10.4 gcc">
+ <os family="mac"/>
+ </condition>
+
+ <condition property="gxx_extra_libs" value="stdc++">
+ <os name="linux"/>
+ </condition>
+
+ <condition property="gxx_extra_libs" value="stdc++">
+ <os family="windows"/>
+ </condition>
+
+ </target>
+
+ <target name="Antlr" depends="init" unless="AntlrDepends">
+ <echo message="Executing ANTLR"/>
+ <exec dir="${basedir}/${ToolName}" executable="${env.FRAMEWORK_TOOLS_PATH}/antlr" failonerror="TRUE">
+ <arg line="-CC -e3 -ck 3 -o . VfrCompile.g"/>
+ </exec>
+ </target>
+
+ <target name="Dlg" depends="Antlr" unless="DlgDepends">
+ <echo message="Executing DLG"/>
+ <exec dir="${basedir}/${ToolName}" executable="${env.FRAMEWORK_TOOLS_PATH}/dlg" failonerror="TRUE">
+ <arg line="-C2 -i -CC -o . parser.dlg"/>
+ </exec>
+ </target>
+
+ <target name="Tool" depends="init">
+ <cc name="${ToolChain}" objdir="${BUILD_DIR}"
+ outfile="${BIN_DIR}/${ToolName}"
+ outtype="executable"
+ debug="true"
+ optimize="speed">
+
+ <fileset dir="${basedir}/${ToolName}"
+ includes="${FileSet}" />
+
+ <fileset dir="${basedir}/Pccts/h"
+ includes="${FileSetPccts}" />
+
+ <includepath path="${PACKAGE_DIR}/Pccts/h"/>
+ <includepath path="${PACKAGE_DIR}/Include"/>
+ <includepath path="${PACKAGE_DIR}/Include/${HostArch}"/>
+ <includepath path="${PACKAGE_DIR}/Common"/>
+ <libset dir="${LIB_DIR}" libs="CommonTools"/>
+ <syslibset libs="${gxx_extra_libs}" if="gcc"/>
+ </cc>
+ </target>
+
+ <target name="clean">
+ <echo message="Removing Intermediate Files Only"/>
+ <delete>
+ <fileset dir="${BUILD_DIR}" includes="*.obj"/>
+ </delete>
+ </target>
+
+ <target name="cleanall">
+ <echo message="Removing Object Files and the Executable: ${ToolName}${ext_exe}"/>
+ <delete failonerror="false" quiet="true" includeEmptyDirs="true">
+ <fileset dir="${BUILD_DIR}"/>
+ <fileset file="${basedir}/${ToolName}/DLGLexer.cpp"/>
+ <fileset file="${basedir}/${ToolName}/DLGLexer.h"/>
+ <fileset file="${basedir}/${ToolName}/EfiVfrParser.cpp"/>
+ <fileset file="${basedir}/${ToolName}/EfiVfrParser.h"/>
+ <fileset file="${basedir}/${ToolName}/parser.dlg"/>
+ <fileset file="${basedir}/${ToolName}/tokens.h"/>
+ <fileset file="${basedir}/${ToolName}/VfrCompile.cpp"/>
+ <fileset file="${BIN_DIR}/${ToolName}${ext_exe}"/>
+ <fileset file="${BIN_DIR}/${ToolName}.pdb"/>
+ </delete>
+ </target>
+
+</project>
diff --git a/Source/ZeroDebugData/ZeroDebugData.c b/Source/ZeroDebugData/ZeroDebugData.c
new file mode 100644
index 0000000..caf129b
--- /dev/null
+++ b/Source/ZeroDebugData/ZeroDebugData.c
@@ -0,0 +1,391 @@
+/*++
+
+Copyright (c) 2004-2006 Intel Corporation. All rights reserved
+This program and the accompanying materials are licensed and made available
+under the terms and conditions of the BSD License which accompanies this
+distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+
+Module Name:
+
+ ZeroDebugData.c
+
+Abstract:
+
+ Zero the Debug Data Fields of Portable Executable (PE) format file.
+
+--*/
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+void
+PrintUsage (
+ void
+ )
+/*++
+Routine Description:
+ print usage of ZeroDebugData command
+
+Arguments:
+ None
+
+Returns:
+ None
+--*/
+// GC_TODO: void - add argument and description to function comment
+{
+ //
+ // print usage of command
+ //
+ printf ("\nUsage: ZeroDebugData <PE-File> [DebugData-File]\n");
+}
+
+int
+ReadFromFile (
+ FILE *fp,
+ long offset,
+ void *buffer,
+ int size
+ )
+/*++
+Routine Description:
+ read data from a specified location of file
+
+Arguments:
+ fp - file pointer
+ offset - number of bytes from beginning of file
+ buffer - buffer used to store data
+ size - size of buffer
+
+Returns:
+ = 0 - Success
+ = -1 - Failed
+--*/
+{
+ //
+ // set file pointer to the specified location of file
+ //
+ if (fseek (fp, offset, SEEK_SET) != 0) {
+ printf ("Error: Cannot move the current location of the file.\n");
+ return -1;
+ }
+ //
+ // read data from the file
+ //
+ if (fread (buffer, size, 1, fp) != 1) {
+ printf ("Error: Cannot read data from the file.\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+int
+ZeroDebugData (
+ FILE *fp,
+ FILE *fpData
+ )
+/*++
+
+Routine Description:
+
+ Zero the debug data fields of the file
+
+Arguments:
+
+ fp - file pointer
+ fpData - pointer to output file that ZeroDebugData progress is written to
+
+Returns:
+
+ = 0 - Success
+ = -1 - Failed
+
+--*/
+{
+ unsigned char header[4];
+ unsigned long offset;
+ unsigned long NumberOfRvaAndSizes;
+ unsigned int nvalue;
+ unsigned long lvalue;
+ unsigned long Size;
+ unsigned long Pointer;
+ unsigned char *Buffer;
+ unsigned long Index;
+
+ //
+ // read the header of file
+ //
+ if (ReadFromFile (fp, 0, header, 2) != 0) {
+ printf ("Error: open image file\n");
+ return -1;
+ }
+ //
+ // "MZ" -- the header of image file (PE)
+ //
+ if (strncmp ((char *) header, "MZ", 2) != 0) {
+ printf ("Error: Invalid Image file.\n");
+ return -1;
+ }
+ //
+ // At location 0x3C, the stub has the file offset to the
+ // PE signature.
+ //
+ if (ReadFromFile (fp, 0x3C, &offset, 4) != 0) {
+ return -1;
+ }
+ //
+ // read the header of optional
+ //
+ if (ReadFromFile (fp, offset, header, 4) != 0) {
+ return -1;
+ }
+ //
+ // "PE\0\0" -- the signature of optional header
+ //
+ if (strncmp ((char *) header, "PE\0\0", 4) != 0) {
+ printf ("Error: Invalid PE format file.\n");
+ return -1;
+ }
+ //
+ // Add 16 to skip COFF file header, and get to optional header.
+ //
+ offset += 24;
+
+ //
+ // Check the magic field, 0x10B for PE32 and 0x20B for PE32+
+ //
+ if (ReadFromFile (fp, offset, &nvalue, 2) != 0) {
+ return -1;
+ }
+ //
+ // If this is PE32 image file, offset of NumberOfRvaAndSizes is 92.
+ // Else it is 108.
+ //
+ switch (nvalue & 0xFFFF) {
+ case 0x10B:
+ offset += 92;
+ printf ("Info: Image is PE32. ");
+ break;
+
+ case 0x20B:
+ offset += 108;
+ printf ("Info: Image is PE32+. ");
+ break;
+
+ default:
+ printf ("Error: Magic value is unknown.\n");
+ return -1;
+ }
+ //
+ // get the value of NumberOfRvaAndSizes
+ //
+ if (ReadFromFile (fp, offset, &NumberOfRvaAndSizes, 4) != 0) {
+ printf ("Error: read NumberOfRvaAndSizes error.\n");
+ return -1;
+ }
+ //
+ // printf ("Info: NumberOfRvaAndSizes = %d\n", NumberOfRvaAndSizes);
+ //
+ //
+ // Finding Debug Table, offset of Debug Table
+ // is 4 + 6 * 8 = 52.
+ //
+ if (NumberOfRvaAndSizes >= 7) {
+ if (ReadFromFile (fp, offset + 52, &lvalue, 4) != 0) {
+ return -1;
+ }
+ //
+ // Read the SizeOfData(16) and PointerToRawData(24)
+ //
+ if (ReadFromFile (fp, lvalue + 16, &Size, 4) != 0) {
+ printf ("error: Size = %d\n", Size);
+ return -1;
+ }
+
+ printf ("Debug data: size = %xh, ", Size);
+ fprintf (fpData, "Debug data: size = %xh, ", Size);
+
+ if (ReadFromFile (fp, lvalue + 20, &Pointer, 4) != 0) {
+ printf ("error: LoadOffset = %xh\n", Pointer);
+ return -1;
+ }
+ //
+ // printf ("LoadOffset = %xh, ", Pointer);
+ //
+ fprintf (fpData, "LoadOffset = %xh, ", Pointer);
+
+ if (ReadFromFile (fp, lvalue + 24, &Pointer, 4) != 0) {
+ printf ("error: FileOffset = %xh\n", Pointer);
+ return -1;
+ }
+
+ printf ("FileOffset = %xh, ", Pointer);
+ fprintf (fpData, "FileOffset = %xh, \n", Pointer);
+
+ if ((lvalue != 0) && (Pointer != 0)) {
+ //
+ // prepare buffer
+ //
+ Buffer = malloc (Size + 1);
+ if (Buffer == NULL) {
+ printf ("Error: Cannot allocate memory.\n");
+ return -1;
+ }
+ //
+ // set file pointer to the specified location of file
+ //
+ if (fseek (fp, Pointer, SEEK_SET) != 0) {
+ printf ("Error: Cannot move the current location of the file.\n");
+ free (Buffer);
+ return -1;
+ }
+ //
+ // read data from PE file
+ //
+ if (fread (Buffer, Size, 1, fp) != 1) {
+ printf ("Error: Cannot read data from the file.\n");
+ free (Buffer);
+ return -1;
+ }
+ //
+ // write to data file
+ //
+ for (Index = 0; Index < Size;) {
+ fprintf (fpData, "%02x ", Buffer[Index]);
+
+ Index++;
+ if (Index % 8 == 0) {
+ fprintf (fpData, "\n");
+ }
+ }
+
+ fprintf (fpData, "\n");
+
+ //
+ // zero buffer and write back to PE file
+ //
+ if (fseek (fp, Pointer, SEEK_SET) != 0) {
+ printf ("Error: Cannot move the current location of the file.\n");
+ free (Buffer);
+ return -1;
+ }
+
+ memset (Buffer, 0, Size);
+ if (fwrite (Buffer, Size, 1, fp) != 1) {
+ perror ("Error: Cannot write zero to the file.\n");
+ free (Buffer);
+ return -1;
+ }
+ //
+ // set file pointer to the specified location of file
+ //
+ if (fseek (fp, lvalue + 4, SEEK_SET) != 0) {
+ printf ("Error: Cannot move the current location of the file.\n");
+ free (Buffer);
+ return -1;
+ }
+
+ if (fwrite (Buffer, 4, 1, fp) != 1) {
+ perror ("Error: Cannot write zero to the file.\n");
+ free (Buffer);
+ return -1;
+ }
+
+ free (Buffer);
+ }
+ }
+
+ return 0;
+}
+
+int
+main (
+ int argc,
+ char *argv[]
+ )
+/*++
+
+Routine Description:
+
+ Prints the zero debug data of the PE file to the DebugData file.
+ Executes the ZeroDebugData function.
+
+Arguments:
+
+ argc - Standard C argument, number of command line arguments.
+ argv[] - Standard C argument, array of pointers to the input files,
+ such as the PE and DebugData files.
+
+Returns:
+
+ zero - success
+ nonzero - failure
+
+--*/
+{
+ FILE *fp;
+ FILE *fpData;
+ char DataFile[1024] = "";
+
+ //
+ // check the number of parameters
+ //
+ if (argc < 2) {
+ printf ("\nUsage: ZeroDebugData <PE-File> [DebugData-File]\n");
+ return -1;
+ }
+ //
+ // open the DebugData file, if not exists, return
+ //
+ if (argc >= 3) {
+ strcpy (DataFile, argv[2]);
+ } else {
+ strcpy (DataFile, "DebugData.dat");
+ }
+
+ fpData = fopen (DataFile, "a+");
+ if (fpData == NULL) {
+ fpData = fopen (DataFile, "w");
+ if (fpData == NULL) {
+ printf ("Error: Cannot open the data file!\n");
+ return -1;
+ }
+ }
+ //
+ // open the PE file
+ //
+ fp = fopen (argv[1], "r+b");
+ if (fp == NULL) {
+ printf ("Error: Cannot open the PE file!\n");
+ return -1;
+ }
+ //
+ // Zero the Debug Data to the PE file
+ //
+ printf ("Zero Debug Data to file %s:\n", argv[1]);
+ fprintf (fpData, "\nZero Debug Data to file %s:\n", argv[1]);
+ if ((int *) ZeroDebugData (fp, fpData) != 0) {
+ printf ("Error: Zero Debug Data PE file\n");
+ fclose (fp);
+ return -1;
+ }
+
+ printf (" success\n");
+
+ //
+ // close the PE file
+ //
+ fflush (fpData);
+ fflush (fp);
+ fclose (fpData);
+ fclose (fp);
+
+ return 0;
+}
diff --git a/Source/ZeroDebugData/build.xml b/Source/ZeroDebugData/build.xml
new file mode 100644
index 0000000..194afc8
--- /dev/null
+++ b/Source/ZeroDebugData/build.xml
@@ -0,0 +1,68 @@
+<?xml version="1.0" ?>
+<!--
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+-->
+<project default="GenTool" basedir=".">
+<!--
+ EDK ZeroDebugData Tool
+ Copyright (c) 2006, Intel Corporation
+-->
+ <property name="ToolName" value="ZeroDebugData"/>
+ <property name="FileSet" value="*.c"/>
+
+ <taskdef resource="net/sf/antcontrib/antlib.xml"/>
+
+ <property name="LINK_OUTPUT_TYPE" value="static"/>
+ <property name="BUILD_DIR" value="${PACKAGE_DIR}/${ToolName}/tmp"/>
+
+ <target name="GenTool" depends="init, Tool">
+ <echo message="The EDK Tool: ${ToolName} build has completed"/>
+ </target>
+
+ <target name="init">
+ <echo message="Building the EDK Tool: ${ToolName}"/>
+ <mkdir dir="${BUILD_DIR}"/>
+ </target>
+
+ <target name="Tool" depends="init">
+ <cc name="${ToolChain}" objdir="${BUILD_DIR}"
+ outfile="${BIN_DIR}/${ToolName}"
+ outtype="executable"
+ optimize="speed"
+ debug="true">
+
+ <fileset dir="${basedir}/${ToolName}"
+ includes="${FileSet}"
+ defaultexcludes="TRUE"
+ excludes="*.xml *.inf"/>
+
+ <includepath path="${PACKAGE_DIR}/Include"/>
+ <includepath path="${PACKAGE_DIR}/Include/${HostArch}"/>
+ <includepath path="${PACKAGE_DIR}/Common"/>
+ </cc>
+ </target>
+
+ <target name="clean">
+ <echo message="Removing Intermediate Files Only"/>
+ <delete failonerror="false" quiet="true" includeEmptyDirs="true">
+ <fileset dir="${BUILD_DIR}"/>
+ </delete>
+ </target>
+
+ <target name="cleanall">
+ <echo message="Removing Object Files and the Executable: ${ToolName}${ext_exe}"/>
+ <delete failonerror="false" quiet="true" includeEmptyDirs="true">
+ <fileset dir="${BUILD_DIR}"/>
+ <fileset file="${BIN_DIR}/${ToolName}${ext_exe}"/>
+ <fileset file="${BIN_DIR}/${ToolName}.pdb"/>
+ </delete>
+ </target>
+
+</project>
diff --git a/Source/build.xml b/Source/build.xml
new file mode 100644
index 0000000..f222b4a
--- /dev/null
+++ b/Source/build.xml
@@ -0,0 +1,272 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!--
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+-->
+<project default="all" basedir="." name="C_Code">
+<!-- Copyright (c) 2006, Intel Corporation -->
+<!-- Filename: Tools/Source/build.xml -->
+
+ <taskdef resource="net/sf/antcontrib/antlib.xml"/>
+
+ <property name="ReallyVerbose" value="false"/>
+ <property environment="env" />
+
+ <property name="WORKSPACE" value="${env.WORKSPACE}" />
+ <property name="WORKSPACE_DIR" value="${WORKSPACE}" />
+ <property name="PACKAGE" value="Tools" />
+ <property name="PACKAGE_DIR" value="${WORKSPACE}/Tools/CCode/Source" />
+ <property name="LIB_DIR" value="${PACKAGE_DIR}/Library" />
+ <property name="BIN_DIR" value="${WORKSPACE}/Tools/bin" />
+ <property name="BUILD_MODE" value="PACKAGE" />
+ <property name="Libs"
+ value="Common/build.xml CustomizedCompress/build.xml PeCoffLoader/build.xml String/build.xml"/>
+
+ <import file="${WORKSPACE_DIR}/Tools/Conf/BuildMacro.xml" />
+
+ <path id="classpath">
+ <fileset dir="${WORKSPACE}/Tools/Jars" includes="*.jar"/>
+ <fileset dir="${env.XMLBEANS_HOME}/lib" includes="*.jar"/>
+ </path>
+
+ <taskdef classpathref="classpath" resource="net/sf/antcontrib/antlib.xml" />
+
+
+ <target name="all" depends="initArch, init, Tools">
+ <echo message="The EDK II C Tools build complete!"/>
+ </target>
+
+ <target name="init">
+ <echo message="EDK C Code Tools, build initialization"/>
+ <taskdef classpathref="classpath" resource="GenBuild.tasks" />
+ <taskdef classpathref="classpath" resource="cpptasks.tasks"/>
+ <typedef classpathref="classpath" resource="cpptasks.types"/>
+ <mkdir dir="${BIN_DIR}" />
+ <mkdir dir="${LIB_DIR}" />
+
+ </target>
+
+ <target name="initArch">
+ <condition property="HostArch" value="X64">
+ <os arch="amd64"/>
+ </condition>
+ <condition property="HostArch" value="Ia32">
+ <or>
+ <os arch="x86"/>
+ <os arch="i386"/>
+ </or>
+ </condition>
+ <condition property="HostArch" value="Ia32">
+ <os arch="i386"/>
+ </condition>
+
+ <if>
+ <os family="unix" />
+ <then>
+ <echo message="OS Family UNIX, ${HostArch}" />
+ </then>
+ <elseif>
+ <os family="dos" />
+ <then>
+ <echo message="OS Family DOS, ${HostArch}" />
+ </then>
+ </elseif>
+ <elseif>
+ <os family="mac" />
+ <then>
+ <echo message="OS Family OS X, ${HostArch}" />
+ </then>
+ </elseif>
+ <else>
+ <fail message="OS Family Unsupported, ${HostArch}" />
+ </else>
+ </if>
+
+ <if>
+ <not>
+ <isset property="ToolChain" />
+ </not>
+ <then>
+ <if>
+ <isset property="env.TOOL_CHAIN" />
+ <then>
+ <property name="ToolChain" value="${env.TOOL_CHAIN}"/>
+ </then>
+ <else>
+ <!-- Default Tool Chain is Microsoft Visual Studio -->
+ <property name="ToolChain" value="msvc"/>
+ </else>
+ </if>
+ </then>
+ </if>
+
+ <if>
+ <equals arg1="${ToolChain}" arg2="gcc" />
+ <then>
+ <exec executable="gcc" outputproperty="host.gcc.ver">
+ <arg line="-E" />
+ <arg line="-P" />
+ <arg line="-x c" />
+ <arg line="gcc.ver" />
+ </exec>
+ <if>
+ <contains string="${host.gcc.ver}" substring="4" />
+ <then>
+ <property name="ExtraArgus" value="-Wno-pointer-sign" />
+ </then>
+ </if>
+ </then>
+ </if>
+
+ <condition property="linux" value="true">
+ <os name="Linux"/>
+ </condition>
+
+ <condition property="intel_win">
+ <and>
+ <os family="dos"/>
+ <equals arg1="${ToolChain}" arg2="intel"/>
+ </and>
+ </condition>
+
+ <condition property="intel_linux">
+ <and>
+ <os name="Linux"/>
+ <equals arg1="${ToolChain}" arg2="intel"/>
+ </and>
+ </condition>
+
+ <condition property="intel_mac">
+ <and>
+ <os family="mac"/>
+ <equals arg1="${ToolChain}" arg2="intel"/>
+ </and>
+ </condition>
+
+ <condition property="gcc">
+ <and>
+ <equals arg1="${ToolChain}" arg2="gcc"/>
+ </and>
+ </condition>
+
+ <condition property="cygwin">
+ <and>
+ <os family="dos"/>
+ <equals arg1="${ToolChain}" arg2="gcc"/>
+ </and>
+ </condition>
+
+ <condition property="x86_64_linux">
+ <and>
+ <os name="Linux"/>
+ <equals arg1="${HostArch}" arg2="X64"/>
+ </and>
+ </condition>
+
+ <condition property="windows" value="true">
+ <os family="Windows"/>
+ </condition>
+
+ <condition property="OSX" value="true">
+ <os family="Mac"/>
+ </condition>
+
+ <condition property="cyglinux">
+ <or>
+ <istrue value="${linux}"/>
+ <istrue value="${cygwin}"/>
+ </or>
+ </condition>
+
+ <!-- msft is a family, used by both Microsoft and Intel Windows compiler tool chains -->
+ <condition property="msft">
+ <isfalse value="${gcc}"/>
+ </condition>
+
+ <if>
+ <istrue value="${ReallyVerbose}"/>
+ <then>
+ <echo message="Test property msvc: ${msvc}"/>
+ <echo message="Test property gcc: ${gcc}"/>
+ <echo message="Test property intel_win: ${intel_win}"/>
+ <echo message="Test property intel_linux: ${intel_linux}"/>
+ <echo message="Test property intel_mac: ${intel_mac}"/>
+ <echo message="Test property msft: ${msft}"/>
+ <echo message="Test property cygwin: ${cygwin}"/>
+ <echo message="Test property cyglinux: ${cyglinux}"/>
+ <echo message="Test property windows: ${windows}"/>
+ <echo message="Test property linux: ${linux}"/>
+ <echo message="Test property OSX: ${OSX}"/>
+ <echo message="Test property x86_64_linux: ${x86_64_linux}"/>
+ </then>
+ </if>
+
+ <property name="haveLibtool" value="false"/>
+ <if>
+ <and>
+ <not>
+ <isset property="env.CYGWIN_HOME"/>
+ </not>
+ <isset property="cygwin"/>
+ </and>
+ <then>
+ <fail message="You must set the environment variable: CYGWIN_HOME"/>
+ </then>
+ </if>
+
+ <if>
+ <istrue value="${gcc}"/>
+ <then>
+ <property name="ext_static" value=".a"/>
+ <property name="ext_dynamic" value=".so"/>
+ <if>
+ <istrue value="${cygwin}"/>
+ <then>
+ <property name="ext_exe" value=".exe"/>
+ </then>
+ <else>
+ <property name="ext_exe" value=""/>
+ </else>
+ </if>
+ </then>
+ <else>
+ <property name="ext_static" value=".lib"/>
+ <property name="ext_dynamic" value=".dll"/>
+ <property name="ext_exe" value=".exe"/>
+ </else>
+ </if>
+ </target>
+
+ <target name="Libraries" depends="initArch, init">
+ <subant target="" inheritall="true">
+ <fileset dir="${PACKAGE_DIR}"
+ includes="${Libs}"/>
+ </subant>
+ </target>
+
+ <target name="Tools" depends="Libraries">
+ <subant target="" inheritall="true">
+ <fileset dir="${PACKAGE_DIR}" includes="*/build.xml"
+ excludes="${Libs}"/>
+ </subant>
+ </target>
+
+ <target name="clean" depends="initArch">
+ <subant target="clean" inheritall="true">
+ <fileset dir="${PACKAGE_DIR}" includes="*/build.xml"/>
+ </subant>
+ </target>
+
+ <target name="cleanall" depends="initArch">
+ <subant target="cleanall" inheritall="true">
+ <fileset dir="${PACKAGE_DIR}" includes="*/build.xml"/>
+ </subant>
+ <delete dir="${LIB_DIR}"/>
+ </target>
+</project>