From 30fdf1140b8d1ce93f3821d986fa165552023440 Mon Sep 17 00:00:00 2001 From: lgao4 Date: Fri, 17 Jul 2009 09:10:31 +0000 Subject: Check In tool source code based on Build tool project revision r1655. git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@8964 6f19259b-4bc3-4df7-8a09-765794883524 --- BaseTools/Source/C/BootSectImage/GNUmakefile | 10 + BaseTools/Source/C/BootSectImage/Makefile | 10 + BaseTools/Source/C/BootSectImage/bootsectimage.c | 930 + BaseTools/Source/C/BootSectImage/fat.h | 152 + BaseTools/Source/C/BootSectImage/mbr.h | 58 + BaseTools/Source/C/Common/BasePeCoff.c | 1386 ++ BaseTools/Source/C/Common/BinderFuncs.c | 87 + BaseTools/Source/C/Common/BinderFuncs.h | 75 + BaseTools/Source/C/Common/CommonLib.c | 584 + BaseTools/Source/C/Common/CommonLib.h | 172 + BaseTools/Source/C/Common/Compress.h | 95 + BaseTools/Source/C/Common/Crc32.c | 326 + BaseTools/Source/C/Common/Crc32.h | 54 + BaseTools/Source/C/Common/Decompress.c | 982 + BaseTools/Source/C/Common/Decompress.h | 172 + BaseTools/Source/C/Common/EfiCompress.c | 1598 ++ BaseTools/Source/C/Common/EfiUtilityMsgs.c | 929 + BaseTools/Source/C/Common/EfiUtilityMsgs.h | 166 + BaseTools/Source/C/Common/FirmwareVolumeBuffer.c | 1667 ++ .../Source/C/Common/FirmwareVolumeBufferLib.h | 166 + BaseTools/Source/C/Common/FvLib.c | 850 + BaseTools/Source/C/Common/FvLib.h | 178 + BaseTools/Source/C/Common/GNUmakefile | 28 + BaseTools/Source/C/Common/Makefile | 30 + BaseTools/Source/C/Common/MemoryFile.c | 260 + BaseTools/Source/C/Common/MemoryFile.h | 122 + BaseTools/Source/C/Common/MyAlloc.c | 516 + BaseTools/Source/C/Common/MyAlloc.h | 222 + BaseTools/Source/C/Common/OsPath.c | 307 + BaseTools/Source/C/Common/OsPath.h | 146 + .../Source/C/Common/ParseGuidedSectionTools.c | 210 + .../Source/C/Common/ParseGuidedSectionTools.h | 133 + BaseTools/Source/C/Common/ParseInf.c | 665 + BaseTools/Source/C/Common/ParseInf.h | 230 + BaseTools/Source/C/Common/PeCoffLib.h | 137 + BaseTools/Source/C/Common/PeCoffLoaderEx.c | 317 + BaseTools/Source/C/Common/SimpleFileParsing.c | 1443 ++ BaseTools/Source/C/Common/SimpleFileParsing.h | 117 + BaseTools/Source/C/Common/StringFuncs.c | 426 + BaseTools/Source/C/Common/StringFuncs.h | 257 + BaseTools/Source/C/Common/TianoCompress.c | 1753 ++ BaseTools/Source/C/Common/WinNtInclude.h | 73 + BaseTools/Source/C/EfiLdrImage/EfiLdrImage.c | 329 + BaseTools/Source/C/EfiLdrImage/GNUmakefile | 10 + BaseTools/Source/C/EfiLdrImage/Makefile | 10 + BaseTools/Source/C/EfiRom/EfiRom.c | 1546 ++ BaseTools/Source/C/EfiRom/EfiRom.h | 366 + BaseTools/Source/C/EfiRom/GNUmakefile | 10 + BaseTools/Source/C/EfiRom/Makefile | 10 + BaseTools/Source/C/GNUmakefile | 90 + BaseTools/Source/C/GenBootSector/FatFormat.h | 152 + BaseTools/Source/C/GenBootSector/GenBootSector.c | 795 + BaseTools/Source/C/GenBootSector/GetDrvNumOffset.c | 73 + BaseTools/Source/C/GenBootSector/Makefile | 10 + BaseTools/Source/C/GenCrc32/GNUmakefile | 10 + BaseTools/Source/C/GenCrc32/GenCrc32.c | 362 + BaseTools/Source/C/GenCrc32/Makefile | 10 + BaseTools/Source/C/GenFfs/GNUmakefile | 11 + BaseTools/Source/C/GenFfs/GenFfs.c | 897 + BaseTools/Source/C/GenFfs/Makefile | 10 + BaseTools/Source/C/GenFv/GNUmakefile | 18 + BaseTools/Source/C/GenFv/GenFv.c | 713 + BaseTools/Source/C/GenFv/GenFvInternalLib.c | 3574 ++++ BaseTools/Source/C/GenFv/GenFvInternalLib.h | 421 + BaseTools/Source/C/GenFv/Makefile | 10 + BaseTools/Source/C/GenFw/GNUmakefile | 18 + BaseTools/Source/C/GenFw/GenFw.c | 3073 +++ BaseTools/Source/C/GenFw/Makefile | 12 + BaseTools/Source/C/GenFw/elf32.h | 244 + BaseTools/Source/C/GenFw/elf64.h | 247 + BaseTools/Source/C/GenFw/elf_common.h | 872 + BaseTools/Source/C/GenFw/elf_generic.h | 88 + BaseTools/Source/C/GenPage/GNUmakefile | 10 + BaseTools/Source/C/GenPage/GenPage.c | 424 + BaseTools/Source/C/GenPage/Makefile | 10 + BaseTools/Source/C/GenPage/VirtualMemory.h | 127 + BaseTools/Source/C/GenSec/GNUmakefile | 18 + BaseTools/Source/C/GenSec/GenSec.c | 1307 ++ BaseTools/Source/C/GenSec/Makefile | 12 + BaseTools/Source/C/GenVtf/GNUmakefile | 10 + BaseTools/Source/C/GenVtf/GenVtf.c | 2721 +++ BaseTools/Source/C/GenVtf/GenVtf.h | 330 + BaseTools/Source/C/GenVtf/Makefile | 10 + BaseTools/Source/C/GnuGenBootSector/FatFormat.h | 152 + BaseTools/Source/C/GnuGenBootSector/GNUmakefile | 10 + .../Source/C/GnuGenBootSector/GnuGenBootSector.c | 457 + BaseTools/Source/C/Include/Common/BaseTypes.h | 223 + BaseTools/Source/C/Include/Common/MdeModuleHii.h | 154 + BaseTools/Source/C/Include/Common/PiFirmwareFile.h | 270 + .../Source/C/Include/Common/PiFirmwareVolume.h | 146 + BaseTools/Source/C/Include/Common/UefiBaseTypes.h | 177 + BaseTools/Source/C/Include/Common/UefiCapsule.h | 34 + .../Common/UefiInternalFormRepresentation.h | 1509 ++ BaseTools/Source/C/Include/Common/UefiMultiPhase.h | 231 + BaseTools/Source/C/Include/Common/VariableFormat.h | 54 + .../Source/C/Include/Common/WorkingBlockHeader.h | 43 + BaseTools/Source/C/Include/Guid/PcAnsi.h | 61 + .../Source/C/Include/Guid/PiFirmwareFileSystem.h | 41 + BaseTools/Source/C/Include/Ia32/ProcessorBind.h | 168 + BaseTools/Source/C/Include/IndustryStandard/Acpi.h | 125 + .../Source/C/Include/IndustryStandard/Acpi1_0.h | 292 + .../Source/C/Include/IndustryStandard/Acpi2_0.h | 528 + .../Source/C/Include/IndustryStandard/Acpi3_0.h | 676 + .../Source/C/Include/IndustryStandard/EfiPci.h | 59 + .../MemoryMappedConfigurationSpaceAccessTable.h | 47 + .../Source/C/Include/IndustryStandard/PeImage.h | 699 + .../Source/C/Include/IndustryStandard/pci22.h | 544 + .../Source/C/Include/IndustryStandard/pci23.h | 26 + .../Source/C/Include/IndustryStandard/pci30.h | 46 + BaseTools/Source/C/Include/Protocol/DevicePath.h | 548 + .../Source/C/Include/Protocol/GraphicsOutput.h | 195 + .../C/Include/Protocol/GuidedSectionExtraction.h | 153 + BaseTools/Source/C/Include/Protocol/HiiFramework.h | 952 + BaseTools/Source/C/Include/Protocol/UgaDraw.h | 169 + BaseTools/Source/C/Include/X64/ProcessorBind.h | 194 + BaseTools/Source/C/LzmaCompress/GNUmakefile | 18 + .../Source/C/LzmaCompress/LZMA-SDK-README.txt | 3 + BaseTools/Source/C/LzmaCompress/LzmaCompress.c | 337 + BaseTools/Source/C/LzmaCompress/Makefile | 19 + BaseTools/Source/C/LzmaCompress/Sdk/C/7zFile.c | 263 + BaseTools/Source/C/LzmaCompress/Sdk/C/7zFile.h | 74 + BaseTools/Source/C/LzmaCompress/Sdk/C/7zStream.c | 169 + BaseTools/Source/C/LzmaCompress/Sdk/C/7zVersion.h | 7 + BaseTools/Source/C/LzmaCompress/Sdk/C/Alloc.c | 127 + BaseTools/Source/C/LzmaCompress/Sdk/C/Alloc.h | 32 + BaseTools/Source/C/LzmaCompress/Sdk/C/CpuArch.h | 69 + BaseTools/Source/C/LzmaCompress/Sdk/C/LzFind.c | 751 + BaseTools/Source/C/LzmaCompress/Sdk/C/LzFind.h | 107 + BaseTools/Source/C/LzmaCompress/Sdk/C/LzFindMt.c | 793 + BaseTools/Source/C/LzmaCompress/Sdk/C/LzFindMt.h | 97 + BaseTools/Source/C/LzmaCompress/Sdk/C/LzHash.h | 54 + BaseTools/Source/C/LzmaCompress/Sdk/C/LzmaDec.c | 1007 + BaseTools/Source/C/LzmaCompress/Sdk/C/LzmaDec.h | 223 + BaseTools/Source/C/LzmaCompress/Sdk/C/LzmaEnc.c | 2281 +++ BaseTools/Source/C/LzmaCompress/Sdk/C/LzmaEnc.h | 72 + BaseTools/Source/C/LzmaCompress/Sdk/C/Threads.c | 109 + BaseTools/Source/C/LzmaCompress/Sdk/C/Threads.h | 68 + BaseTools/Source/C/LzmaCompress/Sdk/C/Types.h | 208 + BaseTools/Source/C/LzmaCompress/Sdk/history.txt | 236 + BaseTools/Source/C/LzmaCompress/Sdk/lzma.txt | 594 + BaseTools/Source/C/Makefile | 61 + BaseTools/Source/C/Makefiles/NmakeSubdirs.bat | 28 + BaseTools/Source/C/Makefiles/app.makefile | 13 + BaseTools/Source/C/Makefiles/footer.makefile | 23 + BaseTools/Source/C/Makefiles/header.makefile | 40 + BaseTools/Source/C/Makefiles/lib.makefile | 7 + BaseTools/Source/C/Makefiles/ms.app | 21 + BaseTools/Source/C/Makefiles/ms.common | 49 + BaseTools/Source/C/Makefiles/ms.lib | 20 + BaseTools/Source/C/Makefiles/ms.rule | 13 + BaseTools/Source/C/PyEfiCompressor/EfiCompressor.c | 198 + BaseTools/Source/C/PyEfiCompressor/Makefile | 12 + BaseTools/Source/C/PyEfiCompressor/setup.py | 43 + BaseTools/Source/C/PyUtility/Makefile | 12 + BaseTools/Source/C/PyUtility/PyUtility.c | 92 + BaseTools/Source/C/PyUtility/setup.py | 42 + BaseTools/Source/C/Split/GNUmakefile | 12 + BaseTools/Source/C/Split/Makefile | 10 + BaseTools/Source/C/Split/Split.c | 446 + BaseTools/Source/C/TianoCompress/GNUmakefile | 10 + BaseTools/Source/C/TianoCompress/Makefile | 10 + BaseTools/Source/C/TianoCompress/TianoCompress.c | 2719 +++ BaseTools/Source/C/TianoCompress/TianoCompress.h | 439 + BaseTools/Source/C/VfrCompile/EfiVfr.h | 55 + BaseTools/Source/C/VfrCompile/GNUmakefile | 53 + BaseTools/Source/C/VfrCompile/Makefile | 44 + .../Source/C/VfrCompile/Pccts/CHANGES_FROM_131.txt | 522 + .../Source/C/VfrCompile/Pccts/CHANGES_FROM_133.txt | 2448 +++ .../Pccts/CHANGES_FROM_133_BEFORE_MR13.txt | 3666 ++++ .../Source/C/VfrCompile/Pccts/CHANGES_SUMMARY.txt | 2049 ++ .../Source/C/VfrCompile/Pccts/KNOWN_PROBLEMS.txt | 241 + BaseTools/Source/C/VfrCompile/Pccts/MPW_Read_Me | 21 + BaseTools/Source/C/VfrCompile/Pccts/Makefile | 15 + BaseTools/Source/C/VfrCompile/Pccts/NOTES.bcc | 184 + BaseTools/Source/C/VfrCompile/Pccts/NOTES.msvc | 189 + BaseTools/Source/C/VfrCompile/Pccts/README | 159 + BaseTools/Source/C/VfrCompile/Pccts/RIGHTS | 26 + .../Source/C/VfrCompile/Pccts/antlr/AntlrDDK.mak | 233 + .../Source/C/VfrCompile/Pccts/antlr/AntlrMS.mak | 238 + .../Source/C/VfrCompile/Pccts/antlr/AntlrPPC.mak | 101 + BaseTools/Source/C/VfrCompile/Pccts/antlr/README | 19 + BaseTools/Source/C/VfrCompile/Pccts/antlr/antlr.1 | 209 + BaseTools/Source/C/VfrCompile/Pccts/antlr/antlr.c | 3564 ++++ BaseTools/Source/C/VfrCompile/Pccts/antlr/antlr.g | 2586 +++ BaseTools/Source/C/VfrCompile/Pccts/antlr/antlr.r | 787 + .../Source/C/VfrCompile/Pccts/antlr/antlr1.txt | 264 + BaseTools/Source/C/VfrCompile/Pccts/antlr/bits.c | 1025 + BaseTools/Source/C/VfrCompile/Pccts/antlr/build.c | 813 + .../Source/C/VfrCompile/Pccts/antlr/dumpcycles.c | 67 + .../Source/C/VfrCompile/Pccts/antlr/dumpnode.c | 423 + BaseTools/Source/C/VfrCompile/Pccts/antlr/egman.c | 328 + BaseTools/Source/C/VfrCompile/Pccts/antlr/err.c | 538 + BaseTools/Source/C/VfrCompile/Pccts/antlr/fcache.c | 123 + BaseTools/Source/C/VfrCompile/Pccts/antlr/fset.c | 1555 ++ BaseTools/Source/C/VfrCompile/Pccts/antlr/fset2.c | 2250 +++ BaseTools/Source/C/VfrCompile/Pccts/antlr/gen.c | 4797 +++++ .../Source/C/VfrCompile/Pccts/antlr/generic.h | 286 + .../Source/C/VfrCompile/Pccts/antlr/globals.c | 484 + BaseTools/Source/C/VfrCompile/Pccts/antlr/hash.c | 221 + BaseTools/Source/C/VfrCompile/Pccts/antlr/hash.h | 73 + BaseTools/Source/C/VfrCompile/Pccts/antlr/lex.c | 878 + BaseTools/Source/C/VfrCompile/Pccts/antlr/main.c | 1747 ++ BaseTools/Source/C/VfrCompile/Pccts/antlr/makefile | 218 + .../C/VfrCompile/Pccts/antlr/makefile.cygwin | 219 + .../Source/C/VfrCompile/Pccts/antlr/makefile1 | 96 + BaseTools/Source/C/VfrCompile/Pccts/antlr/misc.c | 1864 ++ BaseTools/Source/C/VfrCompile/Pccts/antlr/mode.h | 12 + .../Source/C/VfrCompile/Pccts/antlr/mrhoist.c | 3030 +++ .../Source/C/VfrCompile/Pccts/antlr/parser.dlg | 1387 ++ BaseTools/Source/C/VfrCompile/Pccts/antlr/pred.c | 821 + BaseTools/Source/C/VfrCompile/Pccts/antlr/proto.h | 852 + BaseTools/Source/C/VfrCompile/Pccts/antlr/scan.c | 5735 ++++++ .../Source/C/VfrCompile/Pccts/antlr/stdpccts.h | 31 + BaseTools/Source/C/VfrCompile/Pccts/antlr/syn.h | 390 + BaseTools/Source/C/VfrCompile/Pccts/antlr/tokens.h | 246 + BaseTools/Source/C/VfrCompile/Pccts/dlg/DlgDDK.mak | 121 + BaseTools/Source/C/VfrCompile/Pccts/dlg/DlgMS.mak | 125 + BaseTools/Source/C/VfrCompile/Pccts/dlg/DlgPPC.mak | 84 + BaseTools/Source/C/VfrCompile/Pccts/dlg/automata.c | 353 + BaseTools/Source/C/VfrCompile/Pccts/dlg/dlg.1 | 79 + BaseTools/Source/C/VfrCompile/Pccts/dlg/dlg.h | 250 + BaseTools/Source/C/VfrCompile/Pccts/dlg/dlg.r | 275 + BaseTools/Source/C/VfrCompile/Pccts/dlg/dlg1.txt | 132 + BaseTools/Source/C/VfrCompile/Pccts/dlg/dlg_a.c | 1414 ++ BaseTools/Source/C/VfrCompile/Pccts/dlg/dlg_p.c | 959 + BaseTools/Source/C/VfrCompile/Pccts/dlg/dlg_p.g | 614 + BaseTools/Source/C/VfrCompile/Pccts/dlg/err.c | 99 + BaseTools/Source/C/VfrCompile/Pccts/dlg/main.c | 281 + BaseTools/Source/C/VfrCompile/Pccts/dlg/makefile | 156 + .../Source/C/VfrCompile/Pccts/dlg/makefile.cygwin | 157 + BaseTools/Source/C/VfrCompile/Pccts/dlg/makefile1 | 63 + BaseTools/Source/C/VfrCompile/Pccts/dlg/mode.h | 4 + BaseTools/Source/C/VfrCompile/Pccts/dlg/output.c | 850 + BaseTools/Source/C/VfrCompile/Pccts/dlg/parser.dlg | 398 + BaseTools/Source/C/VfrCompile/Pccts/dlg/relabel.c | 217 + BaseTools/Source/C/VfrCompile/Pccts/dlg/stdpccts.h | 26 + BaseTools/Source/C/VfrCompile/Pccts/dlg/support.c | 240 + BaseTools/Source/C/VfrCompile/Pccts/dlg/tokens.h | 133 + BaseTools/Source/C/VfrCompile/Pccts/h/AParser.cpp | 871 + BaseTools/Source/C/VfrCompile/Pccts/h/AParser.h | 376 + BaseTools/Source/C/VfrCompile/Pccts/h/ASTBase.cpp | 256 + BaseTools/Source/C/VfrCompile/Pccts/h/ASTBase.h | 122 + BaseTools/Source/C/VfrCompile/Pccts/h/ATokPtr.h | 88 + .../Source/C/VfrCompile/Pccts/h/ATokPtrImpl.h | 88 + BaseTools/Source/C/VfrCompile/Pccts/h/AToken.h | 325 + .../Source/C/VfrCompile/Pccts/h/ATokenBuffer.cpp | 374 + .../Source/C/VfrCompile/Pccts/h/ATokenBuffer.h | 109 + .../Source/C/VfrCompile/Pccts/h/ATokenStream.h | 51 + .../Source/C/VfrCompile/Pccts/h/BufFileInput.cpp | 100 + .../Source/C/VfrCompile/Pccts/h/BufFileInput.h | 53 + .../Source/C/VfrCompile/Pccts/h/DLG_stream_input.h | 98 + BaseTools/Source/C/VfrCompile/Pccts/h/DLexer.h | 191 + .../Source/C/VfrCompile/Pccts/h/DLexerBase.cpp | 302 + BaseTools/Source/C/VfrCompile/Pccts/h/DLexerBase.h | 198 + BaseTools/Source/C/VfrCompile/Pccts/h/PBlackBox.h | 134 + BaseTools/Source/C/VfrCompile/Pccts/h/PCCTSAST.cpp | 684 + BaseTools/Source/C/VfrCompile/Pccts/h/PCCTSAST.h | 143 + BaseTools/Source/C/VfrCompile/Pccts/h/SList.h | 72 + BaseTools/Source/C/VfrCompile/Pccts/h/antlr.h | 807 + BaseTools/Source/C/VfrCompile/Pccts/h/ast.c | 345 + BaseTools/Source/C/VfrCompile/Pccts/h/ast.h | 121 + BaseTools/Source/C/VfrCompile/Pccts/h/charbuf.h | 46 + BaseTools/Source/C/VfrCompile/Pccts/h/charptr.c | 58 + BaseTools/Source/C/VfrCompile/Pccts/h/charptr.h | 48 + BaseTools/Source/C/VfrCompile/Pccts/h/config.h | 1 + BaseTools/Source/C/VfrCompile/Pccts/h/dlgauto.h | 504 + BaseTools/Source/C/VfrCompile/Pccts/h/dlgdef.h | 128 + BaseTools/Source/C/VfrCompile/Pccts/h/err.h | 1170 ++ BaseTools/Source/C/VfrCompile/Pccts/h/int.h | 37 + .../Source/C/VfrCompile/Pccts/h/pccts_assert.h | 10 + .../Source/C/VfrCompile/Pccts/h/pccts_iostream.h | 10 + .../Source/C/VfrCompile/Pccts/h/pccts_istream.h | 10 + .../Source/C/VfrCompile/Pccts/h/pccts_setjmp.h | 10 + .../Source/C/VfrCompile/Pccts/h/pccts_stdarg.h | 10 + .../Source/C/VfrCompile/Pccts/h/pccts_stdio.h | 10 + .../Source/C/VfrCompile/Pccts/h/pccts_stdlib.h | 10 + .../Source/C/VfrCompile/Pccts/h/pccts_string.h | 10 + BaseTools/Source/C/VfrCompile/Pccts/h/pcctscfg.h | 359 + BaseTools/Source/C/VfrCompile/Pccts/h/pcnames.bat | 11 + BaseTools/Source/C/VfrCompile/Pccts/h/slist.cpp | 116 + BaseTools/Source/C/VfrCompile/Pccts/history.ps | 473 + BaseTools/Source/C/VfrCompile/Pccts/history.txt | 186 + BaseTools/Source/C/VfrCompile/Pccts/makefile.old | 66 + .../C/VfrCompile/Pccts/support/genmk/genmk.c | 1063 ++ .../C/VfrCompile/Pccts/support/genmk/genmk_old.c | 762 + .../C/VfrCompile/Pccts/support/genmk/makefile | 29 + .../C/VfrCompile/Pccts/support/rexpr/makefile | 19 + .../C/VfrCompile/Pccts/support/rexpr/rexpr.c | 586 + .../C/VfrCompile/Pccts/support/rexpr/rexpr.h | 30 + .../Source/C/VfrCompile/Pccts/support/rexpr/test.c | 19 + .../Source/C/VfrCompile/Pccts/support/set/set.c | 816 + .../Source/C/VfrCompile/Pccts/support/set/set.h | 121 + .../Source/C/VfrCompile/Pccts/support/sym/sym.c | 402 + .../C/VfrCompile/Pccts/support/sym/template.h | 41 + BaseTools/Source/C/VfrCompile/VfrCompiler.cpp | 741 + BaseTools/Source/C/VfrCompile/VfrCompiler.h | 108 + BaseTools/Source/C/VfrCompile/VfrError.cpp | 241 + BaseTools/Source/C/VfrCompile/VfrError.h | 85 + BaseTools/Source/C/VfrCompile/VfrFormPkg.cpp | 1386 ++ BaseTools/Source/C/VfrCompile/VfrFormPkg.h | 2358 +++ BaseTools/Source/C/VfrCompile/VfrSyntax.g | 3893 ++++ BaseTools/Source/C/VfrCompile/VfrUtilityLib.cpp | 2879 +++ BaseTools/Source/C/VfrCompile/VfrUtilityLib.h | 427 + BaseTools/Source/C/VolInfo/GNUmakefile | 12 + BaseTools/Source/C/VolInfo/Makefile | 10 + BaseTools/Source/C/VolInfo/VolInfo.c | 1798 ++ BaseTools/Source/C/VolInfo/VolInfo.h | 41 + BaseTools/Source/Python/AutoGen/AutoGen.py | 1919 ++ BaseTools/Source/Python/AutoGen/BuildEngine.py | 622 + BaseTools/Source/Python/AutoGen/GenC.py | 1931 ++ BaseTools/Source/Python/AutoGen/GenDepex.py | 441 + BaseTools/Source/Python/AutoGen/GenMake.py | 1389 ++ BaseTools/Source/Python/AutoGen/StrGather.py | 532 + BaseTools/Source/Python/AutoGen/UniClassObject.py | 530 + BaseTools/Source/Python/AutoGen/__init__.py | 10 + BaseTools/Source/Python/Common/BuildToolError.py | 152 + BaseTools/Source/Python/Common/DataType.py | 401 + BaseTools/Source/Python/Common/Database.py | 120 + BaseTools/Source/Python/Common/DecClassObject.py | 563 + .../Source/Python/Common/DecClassObjectLight.py | 580 + BaseTools/Source/Python/Common/Dictionary.py | 75 + BaseTools/Source/Python/Common/DscClassObject.py | 1434 ++ BaseTools/Source/Python/Common/EdkIIWorkspace.py | 318 + .../Source/Python/Common/EdkIIWorkspaceBuild.py | 1669 ++ BaseTools/Source/Python/Common/EdkLogger.py | 269 + BaseTools/Source/Python/Common/FdfClassObject.py | 116 + BaseTools/Source/Python/Common/FdfParserLite.py | 3603 ++++ BaseTools/Source/Python/Common/GlobalData.py | 37 + BaseTools/Source/Python/Common/Identification.py | 58 + BaseTools/Source/Python/Common/InfClassObject.py | 1116 ++ .../Source/Python/Common/InfClassObjectLight.py | 876 + .../Source/Python/Common/MigrationUtilities.py | 567 + BaseTools/Source/Python/Common/Misc.py | 1327 ++ BaseTools/Source/Python/Common/Parsing.py | 935 + BaseTools/Source/Python/Common/PyUtility.pyd | Bin 0 -> 4608 bytes BaseTools/Source/Python/Common/String.py | 703 + .../Source/Python/Common/TargetTxtClassObject.py | 174 + .../Source/Python/Common/ToolDefClassObject.py | 217 + BaseTools/Source/Python/Common/XmlParser.py | 1754 ++ BaseTools/Source/Python/Common/XmlRoutines.py | 228 + BaseTools/Source/Python/Common/__init__.py | 0 .../Source/Python/CommonDataClass/CommonClass.py | 473 + .../Source/Python/CommonDataClass/DataClass.py | 351 + .../CommonDataClass/DistributionPackageClass.py | 159 + .../Source/Python/CommonDataClass/FdfClass.py | 402 + .../Source/Python/CommonDataClass/ModuleClass.py | 486 + .../Source/Python/CommonDataClass/PackageClass.py | 127 + .../Source/Python/CommonDataClass/PlatformClass.py | 432 + .../Source/Python/CommonDataClass/__init__.py | 0 BaseTools/Source/Python/Ecc/C.g | 626 + BaseTools/Source/Python/Ecc/CLexer.py | 4887 +++++ BaseTools/Source/Python/Ecc/CParser.py | 18825 +++++++++++++++++++ BaseTools/Source/Python/Ecc/Check.py | 865 + BaseTools/Source/Python/Ecc/CodeFragment.py | 165 + .../Source/Python/Ecc/CodeFragmentCollector.py | 624 + BaseTools/Source/Python/Ecc/Configuration.py | 264 + BaseTools/Source/Python/Ecc/Database.py | 344 + BaseTools/Source/Python/Ecc/Ecc.py | 329 + BaseTools/Source/Python/Ecc/EccGlobalData.py | 24 + BaseTools/Source/Python/Ecc/EccToolError.py | 179 + BaseTools/Source/Python/Ecc/Exception.py | 87 + BaseTools/Source/Python/Ecc/FileProfile.py | 57 + BaseTools/Source/Python/Ecc/MetaDataParser.py | 65 + BaseTools/Source/Python/Ecc/ParserWarning.py | 17 + BaseTools/Source/Python/Ecc/__init__.py | 0 BaseTools/Source/Python/Ecc/c.py | 2503 +++ BaseTools/Source/Python/Ecc/config.ini | 242 + BaseTools/Source/Python/Ecc/exception.xml | 310 + BaseTools/Source/Python/Fdb/__init__.py | 0 BaseTools/Source/Python/FixFlash/__init__.py | 0 BaseTools/Source/Python/GNUmakefile | 6 + BaseTools/Source/Python/GenFds/AprioriSection.py | 118 + BaseTools/Source/Python/GenFds/Attribute.py | 28 + BaseTools/Source/Python/GenFds/Capsule.py | 89 + BaseTools/Source/Python/GenFds/CapsuleData.py | 84 + .../Source/Python/GenFds/ComponentStatement.py | 29 + BaseTools/Source/Python/GenFds/CompressSection.py | 87 + BaseTools/Source/Python/GenFds/DataSection.py | 109 + BaseTools/Source/Python/GenFds/DepexSection.py | 102 + BaseTools/Source/Python/GenFds/EfiSection.py | 262 + BaseTools/Source/Python/GenFds/Fd.py | 169 + BaseTools/Source/Python/GenFds/FdfParser.py | 3778 ++++ BaseTools/Source/Python/GenFds/Ffs.py | 81 + BaseTools/Source/Python/GenFds/FfsFileStatement.py | 118 + BaseTools/Source/Python/GenFds/FfsInfStatement.py | 582 + BaseTools/Source/Python/GenFds/Fv.py | 215 + BaseTools/Source/Python/GenFds/FvImageSection.py | 90 + BaseTools/Source/Python/GenFds/GenFds.py | 486 + .../Source/Python/GenFds/GenFdsGlobalVariable.py | 472 + BaseTools/Source/Python/GenFds/GuidSection.py | 190 + .../Source/Python/GenFds/OptRomFileStatement.py | 50 + .../Source/Python/GenFds/OptRomInfStatement.py | 147 + BaseTools/Source/Python/GenFds/OptionRom.py | 140 + BaseTools/Source/Python/GenFds/Region.py | 240 + BaseTools/Source/Python/GenFds/Rule.py | 29 + BaseTools/Source/Python/GenFds/RuleComplexFile.py | 30 + BaseTools/Source/Python/GenFds/RuleSimpleFile.py | 30 + BaseTools/Source/Python/GenFds/Section.py | 153 + BaseTools/Source/Python/GenFds/UiSection.py | 77 + BaseTools/Source/Python/GenFds/VerSection.py | 82 + BaseTools/Source/Python/GenFds/Vtf.py | 188 + BaseTools/Source/Python/GenFds/__init__.py | 0 BaseTools/Source/Python/Makefile | 89 + .../Python/MigrationMsa2Inf/AutoGenExterns.py | 369 + .../Python/MigrationMsa2Inf/MigrationMsa2Inf.py | 2477 +++ .../Source/Python/MigrationMsa2Inf/__init__.py | 0 BaseTools/Source/Python/MkBOM/__init__.py | 0 .../Source/Python/PackagingTool/DependencyRules.py | 185 + .../Source/Python/PackagingTool/InstallPkg.py | 309 + BaseTools/Source/Python/PackagingTool/IpiDb.py | 629 + BaseTools/Source/Python/PackagingTool/MkPkg.py | 294 + .../Source/Python/PackagingTool/PackageFile.py | 160 + BaseTools/Source/Python/PackagingTool/RmPkg.py | 218 + BaseTools/Source/Python/Table/Table.py | 120 + BaseTools/Source/Python/Table/TableDataModel.py | 95 + BaseTools/Source/Python/Table/TableDec.py | 108 + BaseTools/Source/Python/Table/TableDsc.py | 108 + BaseTools/Source/Python/Table/TableEotReport.py | 76 + BaseTools/Source/Python/Table/TableFdf.py | 108 + BaseTools/Source/Python/Table/TableFile.py | 91 + BaseTools/Source/Python/Table/TableFunction.py | 95 + BaseTools/Source/Python/Table/TableIdentifier.py | 90 + BaseTools/Source/Python/Table/TableInf.py | 114 + BaseTools/Source/Python/Table/TablePcd.py | 90 + BaseTools/Source/Python/Table/TableQuery.py | 66 + BaseTools/Source/Python/Table/TableReport.py | 123 + BaseTools/Source/Python/Table/__init__.py | 0 BaseTools/Source/Python/TargetTool/TargetTool.py | 261 + BaseTools/Source/Python/TargetTool/__init__.py | 0 BaseTools/Source/Python/Trim/Trim.py | 520 + .../Source/Python/Workspace/BuildClassObject.py | 364 + BaseTools/Source/Python/Workspace/MetaDataTable.py | 335 + .../Source/Python/Workspace/MetaFileParser.py | 1131 ++ BaseTools/Source/Python/Workspace/MetaFileTable.py | 275 + .../Source/Python/Workspace/WorkspaceDatabase.py | 2274 +++ BaseTools/Source/Python/Workspace/__init__.py | 0 BaseTools/Source/Python/build/__init__.py | 0 BaseTools/Source/Python/build/build.py | 1436 ++ .../Python/fpd2dsc/EdkIIWorkspaceGuidsInfo.py | 327 + BaseTools/Source/Python/fpd2dsc/LoadFpd.py | 1039 + .../Source/Python/fpd2dsc/MigrationUtilities.py | 563 + BaseTools/Source/Python/fpd2dsc/StoreDsc.py | 765 + BaseTools/Source/Python/fpd2dsc/__init__.py | 0 BaseTools/Source/Python/fpd2dsc/fpd2dsc.py | 116 + BaseTools/Source/Python/msa2inf/ConvertModule.py | 112 + .../Python/msa2inf/EdkIIWorkspaceGuidsInfo.py | 325 + BaseTools/Source/Python/msa2inf/LoadMsa.py | 747 + BaseTools/Source/Python/msa2inf/Msa2Inf.py | 44 + BaseTools/Source/Python/msa2inf/StoreInf.py | 442 + BaseTools/Source/Python/msa2inf/__init__.py | 0 BaseTools/Source/Python/spd2dec/ConvertPackage.py | 66 + BaseTools/Source/Python/spd2dec/LoadSpd.py | 273 + BaseTools/Source/Python/spd2dec/Spd2Dec.py | 46 + BaseTools/Source/Python/spd2dec/StoreDec.py | 247 + BaseTools/Source/Python/spd2dec/__init__.py | 0 455 files changed, 223792 insertions(+) create mode 100644 BaseTools/Source/C/BootSectImage/GNUmakefile create mode 100644 BaseTools/Source/C/BootSectImage/Makefile create mode 100644 BaseTools/Source/C/BootSectImage/bootsectimage.c create mode 100644 BaseTools/Source/C/BootSectImage/fat.h create mode 100644 BaseTools/Source/C/BootSectImage/mbr.h create mode 100644 BaseTools/Source/C/Common/BasePeCoff.c create mode 100644 BaseTools/Source/C/Common/BinderFuncs.c create mode 100644 BaseTools/Source/C/Common/BinderFuncs.h create mode 100644 BaseTools/Source/C/Common/CommonLib.c create mode 100644 BaseTools/Source/C/Common/CommonLib.h create mode 100644 BaseTools/Source/C/Common/Compress.h create mode 100644 BaseTools/Source/C/Common/Crc32.c create mode 100644 BaseTools/Source/C/Common/Crc32.h create mode 100644 BaseTools/Source/C/Common/Decompress.c create mode 100644 BaseTools/Source/C/Common/Decompress.h create mode 100644 BaseTools/Source/C/Common/EfiCompress.c create mode 100644 BaseTools/Source/C/Common/EfiUtilityMsgs.c create mode 100644 BaseTools/Source/C/Common/EfiUtilityMsgs.h create mode 100644 BaseTools/Source/C/Common/FirmwareVolumeBuffer.c create mode 100644 BaseTools/Source/C/Common/FirmwareVolumeBufferLib.h create mode 100644 BaseTools/Source/C/Common/FvLib.c create mode 100644 BaseTools/Source/C/Common/FvLib.h create mode 100644 BaseTools/Source/C/Common/GNUmakefile create mode 100644 BaseTools/Source/C/Common/Makefile create mode 100644 BaseTools/Source/C/Common/MemoryFile.c create mode 100644 BaseTools/Source/C/Common/MemoryFile.h create mode 100644 BaseTools/Source/C/Common/MyAlloc.c create mode 100644 BaseTools/Source/C/Common/MyAlloc.h create mode 100644 BaseTools/Source/C/Common/OsPath.c create mode 100644 BaseTools/Source/C/Common/OsPath.h create mode 100644 BaseTools/Source/C/Common/ParseGuidedSectionTools.c create mode 100644 BaseTools/Source/C/Common/ParseGuidedSectionTools.h create mode 100644 BaseTools/Source/C/Common/ParseInf.c create mode 100644 BaseTools/Source/C/Common/ParseInf.h create mode 100644 BaseTools/Source/C/Common/PeCoffLib.h create mode 100644 BaseTools/Source/C/Common/PeCoffLoaderEx.c create mode 100644 BaseTools/Source/C/Common/SimpleFileParsing.c create mode 100644 BaseTools/Source/C/Common/SimpleFileParsing.h create mode 100644 BaseTools/Source/C/Common/StringFuncs.c create mode 100644 BaseTools/Source/C/Common/StringFuncs.h create mode 100644 BaseTools/Source/C/Common/TianoCompress.c create mode 100644 BaseTools/Source/C/Common/WinNtInclude.h create mode 100644 BaseTools/Source/C/EfiLdrImage/EfiLdrImage.c create mode 100644 BaseTools/Source/C/EfiLdrImage/GNUmakefile create mode 100644 BaseTools/Source/C/EfiLdrImage/Makefile create mode 100644 BaseTools/Source/C/EfiRom/EfiRom.c create mode 100644 BaseTools/Source/C/EfiRom/EfiRom.h create mode 100644 BaseTools/Source/C/EfiRom/GNUmakefile create mode 100644 BaseTools/Source/C/EfiRom/Makefile create mode 100644 BaseTools/Source/C/GNUmakefile create mode 100644 BaseTools/Source/C/GenBootSector/FatFormat.h create mode 100644 BaseTools/Source/C/GenBootSector/GenBootSector.c create mode 100644 BaseTools/Source/C/GenBootSector/GetDrvNumOffset.c create mode 100644 BaseTools/Source/C/GenBootSector/Makefile create mode 100644 BaseTools/Source/C/GenCrc32/GNUmakefile create mode 100644 BaseTools/Source/C/GenCrc32/GenCrc32.c create mode 100644 BaseTools/Source/C/GenCrc32/Makefile create mode 100644 BaseTools/Source/C/GenFfs/GNUmakefile create mode 100644 BaseTools/Source/C/GenFfs/GenFfs.c create mode 100644 BaseTools/Source/C/GenFfs/Makefile create mode 100644 BaseTools/Source/C/GenFv/GNUmakefile create mode 100644 BaseTools/Source/C/GenFv/GenFv.c create mode 100644 BaseTools/Source/C/GenFv/GenFvInternalLib.c create mode 100644 BaseTools/Source/C/GenFv/GenFvInternalLib.h create mode 100644 BaseTools/Source/C/GenFv/Makefile create mode 100644 BaseTools/Source/C/GenFw/GNUmakefile create mode 100644 BaseTools/Source/C/GenFw/GenFw.c create mode 100644 BaseTools/Source/C/GenFw/Makefile create mode 100644 BaseTools/Source/C/GenFw/elf32.h create mode 100644 BaseTools/Source/C/GenFw/elf64.h create mode 100644 BaseTools/Source/C/GenFw/elf_common.h create mode 100644 BaseTools/Source/C/GenFw/elf_generic.h create mode 100644 BaseTools/Source/C/GenPage/GNUmakefile create mode 100644 BaseTools/Source/C/GenPage/GenPage.c create mode 100644 BaseTools/Source/C/GenPage/Makefile create mode 100644 BaseTools/Source/C/GenPage/VirtualMemory.h create mode 100644 BaseTools/Source/C/GenSec/GNUmakefile create mode 100644 BaseTools/Source/C/GenSec/GenSec.c create mode 100644 BaseTools/Source/C/GenSec/Makefile create mode 100644 BaseTools/Source/C/GenVtf/GNUmakefile create mode 100644 BaseTools/Source/C/GenVtf/GenVtf.c create mode 100644 BaseTools/Source/C/GenVtf/GenVtf.h create mode 100644 BaseTools/Source/C/GenVtf/Makefile create mode 100644 BaseTools/Source/C/GnuGenBootSector/FatFormat.h create mode 100644 BaseTools/Source/C/GnuGenBootSector/GNUmakefile create mode 100644 BaseTools/Source/C/GnuGenBootSector/GnuGenBootSector.c create mode 100644 BaseTools/Source/C/Include/Common/BaseTypes.h create mode 100644 BaseTools/Source/C/Include/Common/MdeModuleHii.h create mode 100644 BaseTools/Source/C/Include/Common/PiFirmwareFile.h create mode 100644 BaseTools/Source/C/Include/Common/PiFirmwareVolume.h create mode 100644 BaseTools/Source/C/Include/Common/UefiBaseTypes.h create mode 100644 BaseTools/Source/C/Include/Common/UefiCapsule.h create mode 100644 BaseTools/Source/C/Include/Common/UefiInternalFormRepresentation.h create mode 100644 BaseTools/Source/C/Include/Common/UefiMultiPhase.h create mode 100644 BaseTools/Source/C/Include/Common/VariableFormat.h create mode 100644 BaseTools/Source/C/Include/Common/WorkingBlockHeader.h create mode 100644 BaseTools/Source/C/Include/Guid/PcAnsi.h create mode 100644 BaseTools/Source/C/Include/Guid/PiFirmwareFileSystem.h create mode 100644 BaseTools/Source/C/Include/Ia32/ProcessorBind.h create mode 100644 BaseTools/Source/C/Include/IndustryStandard/Acpi.h create mode 100644 BaseTools/Source/C/Include/IndustryStandard/Acpi1_0.h create mode 100644 BaseTools/Source/C/Include/IndustryStandard/Acpi2_0.h create mode 100644 BaseTools/Source/C/Include/IndustryStandard/Acpi3_0.h create mode 100644 BaseTools/Source/C/Include/IndustryStandard/EfiPci.h create mode 100644 BaseTools/Source/C/Include/IndustryStandard/MemoryMappedConfigurationSpaceAccessTable.h create mode 100644 BaseTools/Source/C/Include/IndustryStandard/PeImage.h create mode 100644 BaseTools/Source/C/Include/IndustryStandard/pci22.h create mode 100644 BaseTools/Source/C/Include/IndustryStandard/pci23.h create mode 100644 BaseTools/Source/C/Include/IndustryStandard/pci30.h create mode 100644 BaseTools/Source/C/Include/Protocol/DevicePath.h create mode 100644 BaseTools/Source/C/Include/Protocol/GraphicsOutput.h create mode 100644 BaseTools/Source/C/Include/Protocol/GuidedSectionExtraction.h create mode 100644 BaseTools/Source/C/Include/Protocol/HiiFramework.h create mode 100644 BaseTools/Source/C/Include/Protocol/UgaDraw.h create mode 100644 BaseTools/Source/C/Include/X64/ProcessorBind.h create mode 100644 BaseTools/Source/C/LzmaCompress/GNUmakefile create mode 100644 BaseTools/Source/C/LzmaCompress/LZMA-SDK-README.txt create mode 100644 BaseTools/Source/C/LzmaCompress/LzmaCompress.c create mode 100644 BaseTools/Source/C/LzmaCompress/Makefile create mode 100644 BaseTools/Source/C/LzmaCompress/Sdk/C/7zFile.c create mode 100644 BaseTools/Source/C/LzmaCompress/Sdk/C/7zFile.h create mode 100644 BaseTools/Source/C/LzmaCompress/Sdk/C/7zStream.c create mode 100644 BaseTools/Source/C/LzmaCompress/Sdk/C/7zVersion.h create mode 100644 BaseTools/Source/C/LzmaCompress/Sdk/C/Alloc.c create mode 100644 BaseTools/Source/C/LzmaCompress/Sdk/C/Alloc.h create mode 100644 BaseTools/Source/C/LzmaCompress/Sdk/C/CpuArch.h create mode 100644 BaseTools/Source/C/LzmaCompress/Sdk/C/LzFind.c create mode 100644 BaseTools/Source/C/LzmaCompress/Sdk/C/LzFind.h create mode 100644 BaseTools/Source/C/LzmaCompress/Sdk/C/LzFindMt.c create mode 100644 BaseTools/Source/C/LzmaCompress/Sdk/C/LzFindMt.h create mode 100644 BaseTools/Source/C/LzmaCompress/Sdk/C/LzHash.h create mode 100644 BaseTools/Source/C/LzmaCompress/Sdk/C/LzmaDec.c create mode 100644 BaseTools/Source/C/LzmaCompress/Sdk/C/LzmaDec.h create mode 100644 BaseTools/Source/C/LzmaCompress/Sdk/C/LzmaEnc.c create mode 100644 BaseTools/Source/C/LzmaCompress/Sdk/C/LzmaEnc.h create mode 100644 BaseTools/Source/C/LzmaCompress/Sdk/C/Threads.c create mode 100644 BaseTools/Source/C/LzmaCompress/Sdk/C/Threads.h create mode 100644 BaseTools/Source/C/LzmaCompress/Sdk/C/Types.h create mode 100644 BaseTools/Source/C/LzmaCompress/Sdk/history.txt create mode 100644 BaseTools/Source/C/LzmaCompress/Sdk/lzma.txt create mode 100644 BaseTools/Source/C/Makefile create mode 100644 BaseTools/Source/C/Makefiles/NmakeSubdirs.bat create mode 100644 BaseTools/Source/C/Makefiles/app.makefile create mode 100644 BaseTools/Source/C/Makefiles/footer.makefile create mode 100644 BaseTools/Source/C/Makefiles/header.makefile create mode 100644 BaseTools/Source/C/Makefiles/lib.makefile create mode 100644 BaseTools/Source/C/Makefiles/ms.app create mode 100644 BaseTools/Source/C/Makefiles/ms.common create mode 100644 BaseTools/Source/C/Makefiles/ms.lib create mode 100644 BaseTools/Source/C/Makefiles/ms.rule create mode 100644 BaseTools/Source/C/PyEfiCompressor/EfiCompressor.c create mode 100644 BaseTools/Source/C/PyEfiCompressor/Makefile create mode 100644 BaseTools/Source/C/PyEfiCompressor/setup.py create mode 100644 BaseTools/Source/C/PyUtility/Makefile create mode 100644 BaseTools/Source/C/PyUtility/PyUtility.c create mode 100644 BaseTools/Source/C/PyUtility/setup.py create mode 100644 BaseTools/Source/C/Split/GNUmakefile create mode 100644 BaseTools/Source/C/Split/Makefile create mode 100644 BaseTools/Source/C/Split/Split.c create mode 100644 BaseTools/Source/C/TianoCompress/GNUmakefile create mode 100644 BaseTools/Source/C/TianoCompress/Makefile create mode 100644 BaseTools/Source/C/TianoCompress/TianoCompress.c create mode 100644 BaseTools/Source/C/TianoCompress/TianoCompress.h create mode 100644 BaseTools/Source/C/VfrCompile/EfiVfr.h create mode 100644 BaseTools/Source/C/VfrCompile/GNUmakefile create mode 100644 BaseTools/Source/C/VfrCompile/Makefile create mode 100644 BaseTools/Source/C/VfrCompile/Pccts/CHANGES_FROM_131.txt create mode 100644 BaseTools/Source/C/VfrCompile/Pccts/CHANGES_FROM_133.txt create mode 100644 BaseTools/Source/C/VfrCompile/Pccts/CHANGES_FROM_133_BEFORE_MR13.txt create mode 100644 BaseTools/Source/C/VfrCompile/Pccts/CHANGES_SUMMARY.txt create mode 100644 BaseTools/Source/C/VfrCompile/Pccts/KNOWN_PROBLEMS.txt create mode 100644 BaseTools/Source/C/VfrCompile/Pccts/MPW_Read_Me create mode 100644 BaseTools/Source/C/VfrCompile/Pccts/Makefile create mode 100644 BaseTools/Source/C/VfrCompile/Pccts/NOTES.bcc create mode 100644 BaseTools/Source/C/VfrCompile/Pccts/NOTES.msvc create mode 100644 BaseTools/Source/C/VfrCompile/Pccts/README create mode 100644 BaseTools/Source/C/VfrCompile/Pccts/RIGHTS create mode 100644 BaseTools/Source/C/VfrCompile/Pccts/antlr/AntlrDDK.mak create mode 100644 BaseTools/Source/C/VfrCompile/Pccts/antlr/AntlrMS.mak create mode 100644 BaseTools/Source/C/VfrCompile/Pccts/antlr/AntlrPPC.mak create mode 100644 BaseTools/Source/C/VfrCompile/Pccts/antlr/README create mode 100644 BaseTools/Source/C/VfrCompile/Pccts/antlr/antlr.1 create mode 100644 BaseTools/Source/C/VfrCompile/Pccts/antlr/antlr.c create mode 100644 BaseTools/Source/C/VfrCompile/Pccts/antlr/antlr.g create mode 100644 BaseTools/Source/C/VfrCompile/Pccts/antlr/antlr.r create mode 100644 BaseTools/Source/C/VfrCompile/Pccts/antlr/antlr1.txt create mode 100644 BaseTools/Source/C/VfrCompile/Pccts/antlr/bits.c create mode 100644 BaseTools/Source/C/VfrCompile/Pccts/antlr/build.c create mode 100644 BaseTools/Source/C/VfrCompile/Pccts/antlr/dumpcycles.c create mode 100644 BaseTools/Source/C/VfrCompile/Pccts/antlr/dumpnode.c create mode 100644 BaseTools/Source/C/VfrCompile/Pccts/antlr/egman.c create mode 100644 BaseTools/Source/C/VfrCompile/Pccts/antlr/err.c create mode 100644 BaseTools/Source/C/VfrCompile/Pccts/antlr/fcache.c create mode 100644 BaseTools/Source/C/VfrCompile/Pccts/antlr/fset.c create mode 100644 BaseTools/Source/C/VfrCompile/Pccts/antlr/fset2.c create mode 100644 BaseTools/Source/C/VfrCompile/Pccts/antlr/gen.c create mode 100644 BaseTools/Source/C/VfrCompile/Pccts/antlr/generic.h create mode 100644 BaseTools/Source/C/VfrCompile/Pccts/antlr/globals.c create mode 100644 BaseTools/Source/C/VfrCompile/Pccts/antlr/hash.c create mode 100644 BaseTools/Source/C/VfrCompile/Pccts/antlr/hash.h create mode 100644 BaseTools/Source/C/VfrCompile/Pccts/antlr/lex.c create mode 100644 BaseTools/Source/C/VfrCompile/Pccts/antlr/main.c create mode 100644 BaseTools/Source/C/VfrCompile/Pccts/antlr/makefile create mode 100644 BaseTools/Source/C/VfrCompile/Pccts/antlr/makefile.cygwin create mode 100644 BaseTools/Source/C/VfrCompile/Pccts/antlr/makefile1 create mode 100644 BaseTools/Source/C/VfrCompile/Pccts/antlr/misc.c create mode 100644 BaseTools/Source/C/VfrCompile/Pccts/antlr/mode.h create mode 100644 BaseTools/Source/C/VfrCompile/Pccts/antlr/mrhoist.c create mode 100644 BaseTools/Source/C/VfrCompile/Pccts/antlr/parser.dlg create mode 100644 BaseTools/Source/C/VfrCompile/Pccts/antlr/pred.c create mode 100644 BaseTools/Source/C/VfrCompile/Pccts/antlr/proto.h create mode 100644 BaseTools/Source/C/VfrCompile/Pccts/antlr/scan.c create mode 100644 BaseTools/Source/C/VfrCompile/Pccts/antlr/stdpccts.h create mode 100644 BaseTools/Source/C/VfrCompile/Pccts/antlr/syn.h create mode 100644 BaseTools/Source/C/VfrCompile/Pccts/antlr/tokens.h create mode 100644 BaseTools/Source/C/VfrCompile/Pccts/dlg/DlgDDK.mak create mode 100644 BaseTools/Source/C/VfrCompile/Pccts/dlg/DlgMS.mak create mode 100644 BaseTools/Source/C/VfrCompile/Pccts/dlg/DlgPPC.mak create mode 100644 BaseTools/Source/C/VfrCompile/Pccts/dlg/automata.c create mode 100644 BaseTools/Source/C/VfrCompile/Pccts/dlg/dlg.1 create mode 100644 BaseTools/Source/C/VfrCompile/Pccts/dlg/dlg.h create mode 100644 BaseTools/Source/C/VfrCompile/Pccts/dlg/dlg.r create mode 100644 BaseTools/Source/C/VfrCompile/Pccts/dlg/dlg1.txt create mode 100644 BaseTools/Source/C/VfrCompile/Pccts/dlg/dlg_a.c create mode 100644 BaseTools/Source/C/VfrCompile/Pccts/dlg/dlg_p.c create mode 100644 BaseTools/Source/C/VfrCompile/Pccts/dlg/dlg_p.g create mode 100644 BaseTools/Source/C/VfrCompile/Pccts/dlg/err.c create mode 100644 BaseTools/Source/C/VfrCompile/Pccts/dlg/main.c create mode 100644 BaseTools/Source/C/VfrCompile/Pccts/dlg/makefile create mode 100644 BaseTools/Source/C/VfrCompile/Pccts/dlg/makefile.cygwin create mode 100644 BaseTools/Source/C/VfrCompile/Pccts/dlg/makefile1 create mode 100644 BaseTools/Source/C/VfrCompile/Pccts/dlg/mode.h create mode 100644 BaseTools/Source/C/VfrCompile/Pccts/dlg/output.c create mode 100644 BaseTools/Source/C/VfrCompile/Pccts/dlg/parser.dlg create mode 100644 BaseTools/Source/C/VfrCompile/Pccts/dlg/relabel.c create mode 100644 BaseTools/Source/C/VfrCompile/Pccts/dlg/stdpccts.h create mode 100644 BaseTools/Source/C/VfrCompile/Pccts/dlg/support.c create mode 100644 BaseTools/Source/C/VfrCompile/Pccts/dlg/tokens.h create mode 100644 BaseTools/Source/C/VfrCompile/Pccts/h/AParser.cpp create mode 100644 BaseTools/Source/C/VfrCompile/Pccts/h/AParser.h create mode 100644 BaseTools/Source/C/VfrCompile/Pccts/h/ASTBase.cpp create mode 100644 BaseTools/Source/C/VfrCompile/Pccts/h/ASTBase.h create mode 100644 BaseTools/Source/C/VfrCompile/Pccts/h/ATokPtr.h create mode 100644 BaseTools/Source/C/VfrCompile/Pccts/h/ATokPtrImpl.h create mode 100644 BaseTools/Source/C/VfrCompile/Pccts/h/AToken.h create mode 100644 BaseTools/Source/C/VfrCompile/Pccts/h/ATokenBuffer.cpp create mode 100644 BaseTools/Source/C/VfrCompile/Pccts/h/ATokenBuffer.h create mode 100644 BaseTools/Source/C/VfrCompile/Pccts/h/ATokenStream.h create mode 100644 BaseTools/Source/C/VfrCompile/Pccts/h/BufFileInput.cpp create mode 100644 BaseTools/Source/C/VfrCompile/Pccts/h/BufFileInput.h create mode 100644 BaseTools/Source/C/VfrCompile/Pccts/h/DLG_stream_input.h create mode 100644 BaseTools/Source/C/VfrCompile/Pccts/h/DLexer.h create mode 100644 BaseTools/Source/C/VfrCompile/Pccts/h/DLexerBase.cpp create mode 100644 BaseTools/Source/C/VfrCompile/Pccts/h/DLexerBase.h create mode 100644 BaseTools/Source/C/VfrCompile/Pccts/h/PBlackBox.h create mode 100644 BaseTools/Source/C/VfrCompile/Pccts/h/PCCTSAST.cpp create mode 100644 BaseTools/Source/C/VfrCompile/Pccts/h/PCCTSAST.h create mode 100644 BaseTools/Source/C/VfrCompile/Pccts/h/SList.h create mode 100644 BaseTools/Source/C/VfrCompile/Pccts/h/antlr.h create mode 100644 BaseTools/Source/C/VfrCompile/Pccts/h/ast.c create mode 100644 BaseTools/Source/C/VfrCompile/Pccts/h/ast.h create mode 100644 BaseTools/Source/C/VfrCompile/Pccts/h/charbuf.h create mode 100644 BaseTools/Source/C/VfrCompile/Pccts/h/charptr.c create mode 100644 BaseTools/Source/C/VfrCompile/Pccts/h/charptr.h create mode 100644 BaseTools/Source/C/VfrCompile/Pccts/h/config.h create mode 100644 BaseTools/Source/C/VfrCompile/Pccts/h/dlgauto.h create mode 100644 BaseTools/Source/C/VfrCompile/Pccts/h/dlgdef.h create mode 100644 BaseTools/Source/C/VfrCompile/Pccts/h/err.h create mode 100644 BaseTools/Source/C/VfrCompile/Pccts/h/int.h create mode 100644 BaseTools/Source/C/VfrCompile/Pccts/h/pccts_assert.h create mode 100644 BaseTools/Source/C/VfrCompile/Pccts/h/pccts_iostream.h create mode 100644 BaseTools/Source/C/VfrCompile/Pccts/h/pccts_istream.h create mode 100644 BaseTools/Source/C/VfrCompile/Pccts/h/pccts_setjmp.h create mode 100644 BaseTools/Source/C/VfrCompile/Pccts/h/pccts_stdarg.h create mode 100644 BaseTools/Source/C/VfrCompile/Pccts/h/pccts_stdio.h create mode 100644 BaseTools/Source/C/VfrCompile/Pccts/h/pccts_stdlib.h create mode 100644 BaseTools/Source/C/VfrCompile/Pccts/h/pccts_string.h create mode 100644 BaseTools/Source/C/VfrCompile/Pccts/h/pcctscfg.h create mode 100644 BaseTools/Source/C/VfrCompile/Pccts/h/pcnames.bat create mode 100644 BaseTools/Source/C/VfrCompile/Pccts/h/slist.cpp create mode 100644 BaseTools/Source/C/VfrCompile/Pccts/history.ps create mode 100644 BaseTools/Source/C/VfrCompile/Pccts/history.txt create mode 100644 BaseTools/Source/C/VfrCompile/Pccts/makefile.old create mode 100644 BaseTools/Source/C/VfrCompile/Pccts/support/genmk/genmk.c create mode 100644 BaseTools/Source/C/VfrCompile/Pccts/support/genmk/genmk_old.c create mode 100644 BaseTools/Source/C/VfrCompile/Pccts/support/genmk/makefile create mode 100644 BaseTools/Source/C/VfrCompile/Pccts/support/rexpr/makefile create mode 100644 BaseTools/Source/C/VfrCompile/Pccts/support/rexpr/rexpr.c create mode 100644 BaseTools/Source/C/VfrCompile/Pccts/support/rexpr/rexpr.h create mode 100644 BaseTools/Source/C/VfrCompile/Pccts/support/rexpr/test.c create mode 100644 BaseTools/Source/C/VfrCompile/Pccts/support/set/set.c create mode 100644 BaseTools/Source/C/VfrCompile/Pccts/support/set/set.h create mode 100644 BaseTools/Source/C/VfrCompile/Pccts/support/sym/sym.c create mode 100644 BaseTools/Source/C/VfrCompile/Pccts/support/sym/template.h create mode 100644 BaseTools/Source/C/VfrCompile/VfrCompiler.cpp create mode 100644 BaseTools/Source/C/VfrCompile/VfrCompiler.h create mode 100644 BaseTools/Source/C/VfrCompile/VfrError.cpp create mode 100644 BaseTools/Source/C/VfrCompile/VfrError.h create mode 100644 BaseTools/Source/C/VfrCompile/VfrFormPkg.cpp create mode 100644 BaseTools/Source/C/VfrCompile/VfrFormPkg.h create mode 100644 BaseTools/Source/C/VfrCompile/VfrSyntax.g create mode 100644 BaseTools/Source/C/VfrCompile/VfrUtilityLib.cpp create mode 100644 BaseTools/Source/C/VfrCompile/VfrUtilityLib.h create mode 100644 BaseTools/Source/C/VolInfo/GNUmakefile create mode 100644 BaseTools/Source/C/VolInfo/Makefile create mode 100644 BaseTools/Source/C/VolInfo/VolInfo.c create mode 100644 BaseTools/Source/C/VolInfo/VolInfo.h create mode 100644 BaseTools/Source/Python/AutoGen/AutoGen.py create mode 100644 BaseTools/Source/Python/AutoGen/BuildEngine.py create mode 100644 BaseTools/Source/Python/AutoGen/GenC.py create mode 100644 BaseTools/Source/Python/AutoGen/GenDepex.py create mode 100644 BaseTools/Source/Python/AutoGen/GenMake.py create mode 100644 BaseTools/Source/Python/AutoGen/StrGather.py create mode 100644 BaseTools/Source/Python/AutoGen/UniClassObject.py create mode 100644 BaseTools/Source/Python/AutoGen/__init__.py create mode 100644 BaseTools/Source/Python/Common/BuildToolError.py create mode 100644 BaseTools/Source/Python/Common/DataType.py create mode 100644 BaseTools/Source/Python/Common/Database.py create mode 100644 BaseTools/Source/Python/Common/DecClassObject.py create mode 100644 BaseTools/Source/Python/Common/DecClassObjectLight.py create mode 100644 BaseTools/Source/Python/Common/Dictionary.py create mode 100644 BaseTools/Source/Python/Common/DscClassObject.py create mode 100644 BaseTools/Source/Python/Common/EdkIIWorkspace.py create mode 100644 BaseTools/Source/Python/Common/EdkIIWorkspaceBuild.py create mode 100644 BaseTools/Source/Python/Common/EdkLogger.py create mode 100644 BaseTools/Source/Python/Common/FdfClassObject.py create mode 100644 BaseTools/Source/Python/Common/FdfParserLite.py create mode 100644 BaseTools/Source/Python/Common/GlobalData.py create mode 100644 BaseTools/Source/Python/Common/Identification.py create mode 100644 BaseTools/Source/Python/Common/InfClassObject.py create mode 100644 BaseTools/Source/Python/Common/InfClassObjectLight.py create mode 100644 BaseTools/Source/Python/Common/MigrationUtilities.py create mode 100644 BaseTools/Source/Python/Common/Misc.py create mode 100644 BaseTools/Source/Python/Common/Parsing.py create mode 100644 BaseTools/Source/Python/Common/PyUtility.pyd create mode 100644 BaseTools/Source/Python/Common/String.py create mode 100644 BaseTools/Source/Python/Common/TargetTxtClassObject.py create mode 100644 BaseTools/Source/Python/Common/ToolDefClassObject.py create mode 100644 BaseTools/Source/Python/Common/XmlParser.py create mode 100644 BaseTools/Source/Python/Common/XmlRoutines.py create mode 100644 BaseTools/Source/Python/Common/__init__.py create mode 100644 BaseTools/Source/Python/CommonDataClass/CommonClass.py create mode 100644 BaseTools/Source/Python/CommonDataClass/DataClass.py create mode 100644 BaseTools/Source/Python/CommonDataClass/DistributionPackageClass.py create mode 100644 BaseTools/Source/Python/CommonDataClass/FdfClass.py create mode 100644 BaseTools/Source/Python/CommonDataClass/ModuleClass.py create mode 100644 BaseTools/Source/Python/CommonDataClass/PackageClass.py create mode 100644 BaseTools/Source/Python/CommonDataClass/PlatformClass.py create mode 100644 BaseTools/Source/Python/CommonDataClass/__init__.py create mode 100644 BaseTools/Source/Python/Ecc/C.g create mode 100644 BaseTools/Source/Python/Ecc/CLexer.py create mode 100644 BaseTools/Source/Python/Ecc/CParser.py create mode 100644 BaseTools/Source/Python/Ecc/Check.py create mode 100644 BaseTools/Source/Python/Ecc/CodeFragment.py create mode 100644 BaseTools/Source/Python/Ecc/CodeFragmentCollector.py create mode 100644 BaseTools/Source/Python/Ecc/Configuration.py create mode 100644 BaseTools/Source/Python/Ecc/Database.py create mode 100644 BaseTools/Source/Python/Ecc/Ecc.py create mode 100644 BaseTools/Source/Python/Ecc/EccGlobalData.py create mode 100644 BaseTools/Source/Python/Ecc/EccToolError.py create mode 100644 BaseTools/Source/Python/Ecc/Exception.py create mode 100644 BaseTools/Source/Python/Ecc/FileProfile.py create mode 100644 BaseTools/Source/Python/Ecc/MetaDataParser.py create mode 100644 BaseTools/Source/Python/Ecc/ParserWarning.py create mode 100644 BaseTools/Source/Python/Ecc/__init__.py create mode 100644 BaseTools/Source/Python/Ecc/c.py create mode 100644 BaseTools/Source/Python/Ecc/config.ini create mode 100644 BaseTools/Source/Python/Ecc/exception.xml create mode 100644 BaseTools/Source/Python/Fdb/__init__.py create mode 100644 BaseTools/Source/Python/FixFlash/__init__.py create mode 100644 BaseTools/Source/Python/GNUmakefile create mode 100644 BaseTools/Source/Python/GenFds/AprioriSection.py create mode 100644 BaseTools/Source/Python/GenFds/Attribute.py create mode 100644 BaseTools/Source/Python/GenFds/Capsule.py create mode 100644 BaseTools/Source/Python/GenFds/CapsuleData.py create mode 100644 BaseTools/Source/Python/GenFds/ComponentStatement.py create mode 100644 BaseTools/Source/Python/GenFds/CompressSection.py create mode 100644 BaseTools/Source/Python/GenFds/DataSection.py create mode 100644 BaseTools/Source/Python/GenFds/DepexSection.py create mode 100644 BaseTools/Source/Python/GenFds/EfiSection.py create mode 100644 BaseTools/Source/Python/GenFds/Fd.py create mode 100644 BaseTools/Source/Python/GenFds/FdfParser.py create mode 100644 BaseTools/Source/Python/GenFds/Ffs.py create mode 100644 BaseTools/Source/Python/GenFds/FfsFileStatement.py create mode 100644 BaseTools/Source/Python/GenFds/FfsInfStatement.py create mode 100644 BaseTools/Source/Python/GenFds/Fv.py create mode 100644 BaseTools/Source/Python/GenFds/FvImageSection.py create mode 100644 BaseTools/Source/Python/GenFds/GenFds.py create mode 100644 BaseTools/Source/Python/GenFds/GenFdsGlobalVariable.py create mode 100644 BaseTools/Source/Python/GenFds/GuidSection.py create mode 100644 BaseTools/Source/Python/GenFds/OptRomFileStatement.py create mode 100644 BaseTools/Source/Python/GenFds/OptRomInfStatement.py create mode 100644 BaseTools/Source/Python/GenFds/OptionRom.py create mode 100644 BaseTools/Source/Python/GenFds/Region.py create mode 100644 BaseTools/Source/Python/GenFds/Rule.py create mode 100644 BaseTools/Source/Python/GenFds/RuleComplexFile.py create mode 100644 BaseTools/Source/Python/GenFds/RuleSimpleFile.py create mode 100644 BaseTools/Source/Python/GenFds/Section.py create mode 100644 BaseTools/Source/Python/GenFds/UiSection.py create mode 100644 BaseTools/Source/Python/GenFds/VerSection.py create mode 100644 BaseTools/Source/Python/GenFds/Vtf.py create mode 100644 BaseTools/Source/Python/GenFds/__init__.py create mode 100644 BaseTools/Source/Python/Makefile create mode 100644 BaseTools/Source/Python/MigrationMsa2Inf/AutoGenExterns.py create mode 100644 BaseTools/Source/Python/MigrationMsa2Inf/MigrationMsa2Inf.py create mode 100644 BaseTools/Source/Python/MigrationMsa2Inf/__init__.py create mode 100644 BaseTools/Source/Python/MkBOM/__init__.py create mode 100644 BaseTools/Source/Python/PackagingTool/DependencyRules.py create mode 100644 BaseTools/Source/Python/PackagingTool/InstallPkg.py create mode 100644 BaseTools/Source/Python/PackagingTool/IpiDb.py create mode 100644 BaseTools/Source/Python/PackagingTool/MkPkg.py create mode 100644 BaseTools/Source/Python/PackagingTool/PackageFile.py create mode 100644 BaseTools/Source/Python/PackagingTool/RmPkg.py create mode 100644 BaseTools/Source/Python/Table/Table.py create mode 100644 BaseTools/Source/Python/Table/TableDataModel.py create mode 100644 BaseTools/Source/Python/Table/TableDec.py create mode 100644 BaseTools/Source/Python/Table/TableDsc.py create mode 100644 BaseTools/Source/Python/Table/TableEotReport.py create mode 100644 BaseTools/Source/Python/Table/TableFdf.py create mode 100644 BaseTools/Source/Python/Table/TableFile.py create mode 100644 BaseTools/Source/Python/Table/TableFunction.py create mode 100644 BaseTools/Source/Python/Table/TableIdentifier.py create mode 100644 BaseTools/Source/Python/Table/TableInf.py create mode 100644 BaseTools/Source/Python/Table/TablePcd.py create mode 100644 BaseTools/Source/Python/Table/TableQuery.py create mode 100644 BaseTools/Source/Python/Table/TableReport.py create mode 100644 BaseTools/Source/Python/Table/__init__.py create mode 100644 BaseTools/Source/Python/TargetTool/TargetTool.py create mode 100644 BaseTools/Source/Python/TargetTool/__init__.py create mode 100644 BaseTools/Source/Python/Trim/Trim.py create mode 100644 BaseTools/Source/Python/Workspace/BuildClassObject.py create mode 100644 BaseTools/Source/Python/Workspace/MetaDataTable.py create mode 100644 BaseTools/Source/Python/Workspace/MetaFileParser.py create mode 100644 BaseTools/Source/Python/Workspace/MetaFileTable.py create mode 100644 BaseTools/Source/Python/Workspace/WorkspaceDatabase.py create mode 100644 BaseTools/Source/Python/Workspace/__init__.py create mode 100644 BaseTools/Source/Python/build/__init__.py create mode 100644 BaseTools/Source/Python/build/build.py create mode 100644 BaseTools/Source/Python/fpd2dsc/EdkIIWorkspaceGuidsInfo.py create mode 100644 BaseTools/Source/Python/fpd2dsc/LoadFpd.py create mode 100644 BaseTools/Source/Python/fpd2dsc/MigrationUtilities.py create mode 100644 BaseTools/Source/Python/fpd2dsc/StoreDsc.py create mode 100644 BaseTools/Source/Python/fpd2dsc/__init__.py create mode 100644 BaseTools/Source/Python/fpd2dsc/fpd2dsc.py create mode 100644 BaseTools/Source/Python/msa2inf/ConvertModule.py create mode 100644 BaseTools/Source/Python/msa2inf/EdkIIWorkspaceGuidsInfo.py create mode 100644 BaseTools/Source/Python/msa2inf/LoadMsa.py create mode 100644 BaseTools/Source/Python/msa2inf/Msa2Inf.py create mode 100644 BaseTools/Source/Python/msa2inf/StoreInf.py create mode 100644 BaseTools/Source/Python/msa2inf/__init__.py create mode 100644 BaseTools/Source/Python/spd2dec/ConvertPackage.py create mode 100644 BaseTools/Source/Python/spd2dec/LoadSpd.py create mode 100644 BaseTools/Source/Python/spd2dec/Spd2Dec.py create mode 100644 BaseTools/Source/Python/spd2dec/StoreDec.py create mode 100644 BaseTools/Source/Python/spd2dec/__init__.py (limited to 'BaseTools/Source') diff --git a/BaseTools/Source/C/BootSectImage/GNUmakefile b/BaseTools/Source/C/BootSectImage/GNUmakefile new file mode 100644 index 0000000000..0891060988 --- /dev/null +++ b/BaseTools/Source/C/BootSectImage/GNUmakefile @@ -0,0 +1,10 @@ +ARCH ?= IA32 +MAKEROOT ?= .. + +APPNAME = BootSectImage + +LIBS = -lCommon + +OBJECTS = bootsectimage.o + +include $(MAKEROOT)/Makefiles/app.makefile diff --git a/BaseTools/Source/C/BootSectImage/Makefile b/BaseTools/Source/C/BootSectImage/Makefile new file mode 100644 index 0000000000..ce0c83c7b9 --- /dev/null +++ b/BaseTools/Source/C/BootSectImage/Makefile @@ -0,0 +1,10 @@ +!INCLUDE ..\Makefiles\ms.common + +APPNAME = BootSectImage + +LIBS = $(LIB_PATH)\Common.lib + +OBJECTS = BootSectImage.obj + +!INCLUDE ..\Makefiles\ms.app + diff --git a/BaseTools/Source/C/BootSectImage/bootsectimage.c b/BaseTools/Source/C/BootSectImage/bootsectimage.c new file mode 100644 index 0000000000..10a545292b --- /dev/null +++ b/BaseTools/Source/C/BootSectImage/bootsectimage.c @@ -0,0 +1,930 @@ +/** @file + +Abstract: + Patch the BPB information in boot sector image file. + Patch the MBR code in MBR image file. + +Copyright 2006 - 2008, 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. + +**/ + +#include +#include +#include "fat.h" +#include "mbr.h" +#include "EfiUtilityMsgs.h" + +#define DEBUG_WARN 0x1 +#define DEBUG_ERROR 0x2 + +// +// Utility Name +// +#define UTILITY_NAME "BootSectImage" + +// +// Utility version information +// +#define UTILITY_MAJOR_VERSION 0 +#define UTILITY_MINOR_VERSION 1 + +void +Version ( + void + ) +/*++ + +Routine Description: + + Displays the standard utility information to SDTOUT + +Arguments: + + None + +Returns: + + None + +--*/ +{ + printf ("%s v%d.%d - Utility to break a file into two pieces at the specified offset.\n", UTILITY_NAME, UTILITY_MAJOR_VERSION, UTILITY_MINOR_VERSION); + printf ("Copyright (c) 1999-2007 Intel Corporation. All rights reserved.\n"); +} + +void +Usage ( + void + ) +/*++ + +Routine Description: + + GC_TODO: Add function description + +Arguments: + + +Returns: + + GC_TODO: add return values + +--*/ +{ + Version(); + printf ("\nUsage: \n\ + BootSectImage\n\ + [-f, --force force patch even if the FAT type of SrcImage and DstImage mismatch]\n\ + [-m, --mbr process MBR instead of boot sector]\n\ + [-p, --parse parse SrcImageFile]\n\ + [-o, --output DstImage]\n\ + [-g, --patch patch DstImage using data from SrcImageFile]\n\ + [-v, --verbose]\n\ + [--version]\n\ + [-q, --quiet disable all messages except fatal errors]\n\ + [-d, --debug[#]\n\ + [-h, --help]\n\ + [SrcImageFile]\n"); +} + +int WriteToFile ( + void *BootSector, + char *FileName + ) +/*++ +Routine Description: + Write 512 bytes boot sector to file. + +Arguments: + BootSector - point to a buffer containing 512 bytes boot sector to write + FileName - file to write to + +Return: + int - number of bytes wrote, + 512 indicates write successful + 0 indicates write failure +--*/ +{ + FILE *FileHandle; + int result; + + FileHandle = fopen (FileName, "r+b"); + if (FileHandle == NULL) { + DebugMsg (NULL, 0, DEBUG_ERROR, NULL, "Open file: %s", FileName); + return 0; + } + fseek (FileHandle, 0, SEEK_SET); + + result = fwrite (BootSector, 1, 512, FileHandle); + if (result != 512) { + DebugMsg (NULL, 0, DEBUG_ERROR, NULL, "Write file: %s", FileName); + result = 0; + } + + fclose (FileHandle); + return result; +} + +int ReadFromFile ( + void *BootSector, + char *FileName + ) +/*++ +Routine Description: + Read first 512 bytes from file. + +Arguments: + BootSector - point to a buffer receiving the first 512 bytes data from file + FileName - file to read from + +Return: + int - number of bytes read, + 512 indicates read successful + 0 indicates read failure +--*/ +{ + FILE *FileHandle; + int result; + + FileHandle = fopen (FileName, "rb"); + if (FileHandle == NULL) { + DebugMsg (NULL, 0, DEBUG_ERROR, NULL, "ERROR: E0001: Error opening file: %s", FileName); + return 0; + } + + result = fread (BootSector, 1, 512, FileHandle); + if (result != 512) { + DebugMsg (NULL, 0, DEBUG_ERROR, NULL, "ERROR: E0004: Error reading file: %s", FileName); + result = 0; + } + + fclose (FileHandle); + return result; +} + +char * +FatTypeToString ( + IN FAT_TYPE FatType + ) +/*++ +Routine Description: + Convert enum type of FatType to string +--*/ +{ + switch (FatType) { + case FatTypeFat12: + return "FAT12"; + case FatTypeFat16: + return "FAT16"; + case FatTypeFat32: + return "FAT32"; + default: + break; + } + return "FAT Unknown"; +} + +FAT_TYPE +GetFatType ( + IN FAT_BPB_STRUCT *FatBpb + ) +/*++ +Routine Description: + Determine the FAT type according to BIOS Paramater Block (BPB) data + +Arguments: + FatBpb - BIOS Parameter Block (BPB) data, 512 Bytes + +Return: + FatTypeUnknown - Cannot determine the FAT type + FatTypeFat12 - FAT12 + FatTypeFat16 - FAT16 + FatTypeFat32 - FAT32 +--*/ +{ + FAT_TYPE FatType; + UINTN RootDirSectors; + UINTN FATSz; + UINTN TotSec; + UINTN DataSec; + UINTN CountOfClusters; + CHAR8 FilSysType[9]; + + FatType = FatTypeUnknown; + + // + // Simple check + // + if (FatBpb->Fat12_16.Signature != FAT_BS_SIGNATURE) { + DebugMsg (NULL, 0, DEBUG_ERROR, NULL, "ERROR: E3003: FAT - Signature Invalid - %04x, expected: %04x", + FatBpb->Fat12_16.Signature, FAT_BS_SIGNATURE); + return FatTypeUnknown; + } + + // + // Check according to FAT spec + // + if ((FatBpb->Fat12_16.BS_jmpBoot[0] != FAT_BS_JMP1) && + (FatBpb->Fat12_16.BS_jmpBoot[0] != FAT_BS_JMP2)) { + DebugMsg (NULL, 0, DEBUG_ERROR, NULL, "ERROR: E3003: FAT - BS_jmpBoot - %02x, expected: %02x or %02x", + FatBpb->Fat12_16.BS_jmpBoot[0], FAT_BS_JMP1, FAT_BS_JMP2); + return FatTypeUnknown; + } + + if ((FatBpb->Fat12_16.BPB_BytsPerSec != 512) && + (FatBpb->Fat12_16.BPB_BytsPerSec != 1024) && + (FatBpb->Fat12_16.BPB_BytsPerSec != 2048) && + (FatBpb->Fat12_16.BPB_BytsPerSec != 4096)) { + DebugMsg (NULL, 0, DEBUG_ERROR, NULL, "ERROR: E3003: FAT - BPB_BytsPerSec - %04x, expected: %04x, %04x, %04x, or %04x", + FatBpb->Fat12_16.BPB_BytsPerSec, 512, 1024, 2048, 4096); + return FatTypeUnknown; + } + if (FatBpb->Fat12_16.BPB_BytsPerSec != 512) { + DebugMsg (NULL, 0, DEBUG_WARN, NULL, "ERROR: E3003: FAT - BPB_BytsPerSec - %04x, expected: %04x", + FatBpb->Fat12_16.BPB_BytsPerSec, 512); + } + if ((FatBpb->Fat12_16.BPB_SecPerClus != 1) && + (FatBpb->Fat12_16.BPB_SecPerClus != 2) && + (FatBpb->Fat12_16.BPB_SecPerClus != 4) && + (FatBpb->Fat12_16.BPB_SecPerClus != 8) && + (FatBpb->Fat12_16.BPB_SecPerClus != 16) && + (FatBpb->Fat12_16.BPB_SecPerClus != 32) && + (FatBpb->Fat12_16.BPB_SecPerClus != 64) && + (FatBpb->Fat12_16.BPB_SecPerClus != 128)) { + DebugMsg (NULL, 0, DEBUG_ERROR, NULL, "ERROR: E3003: FAT - BPB_SecPerClus - %02x, expected: %02x, %02x, %02x, %02x, %02x, %02x, %02x, or %02x", + FatBpb->Fat12_16.BPB_BytsPerSec, 1, 2, 4, 8, 16, 32, 64, 128); + return FatTypeUnknown; + } + if (FatBpb->Fat12_16.BPB_BytsPerSec * FatBpb->Fat12_16.BPB_SecPerClus > 32 * 1024) { + DebugMsg (NULL, 0, DEBUG_ERROR, NULL, "ERROR: E3003: FAT - BPB_BytsPerSec * BPB_SecPerClus - %08x, expected: <= %08x", + FatBpb->Fat12_16.BPB_BytsPerSec * FatBpb->Fat12_16.BPB_SecPerClus, 32 * 1024); + return FatTypeUnknown; + } + if (FatBpb->Fat12_16.BPB_RsvdSecCnt == 0) { + DebugMsg (NULL, 0, DEBUG_ERROR, NULL, "ERROR: E3003: FAT - BPB_RsvdSecCnt - %04x, expected: Non-Zero Value", + FatBpb->Fat12_16.BPB_RsvdSecCnt); + return FatTypeUnknown; + } + if (FatBpb->Fat12_16.BPB_NumFATs != 2) { + DebugMsg (NULL, 0, DEBUG_WARN, NULL, "ERROR: E3003: FAT - BPB_NumFATs - %02x, expected: %02x", + FatBpb->Fat12_16.BPB_NumFATs, 2); + } + if ((FatBpb->Fat12_16.BPB_Media != 0xF0) && + (FatBpb->Fat12_16.BPB_Media != 0xF8) && + (FatBpb->Fat12_16.BPB_Media != 0xF9) && + (FatBpb->Fat12_16.BPB_Media != 0xFA) && + (FatBpb->Fat12_16.BPB_Media != 0xFB) && + (FatBpb->Fat12_16.BPB_Media != 0xFC) && + (FatBpb->Fat12_16.BPB_Media != 0xFD) && + (FatBpb->Fat12_16.BPB_Media != 0xFE) && + (FatBpb->Fat12_16.BPB_Media != 0xFF)) { + DebugMsg (NULL, 0, DEBUG_ERROR, NULL, "ERROR: E3003: FAT - BPB_Media - %02x, expected: %02x, %02x, %02x, %02x, %02x, %02x, %02x, %02x, or %02x", + FatBpb->Fat12_16.BPB_Media, 0xF0, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF); + return FatTypeUnknown; + } + + // + // Algo in FAT spec + // + RootDirSectors = ((FatBpb->Fat12_16.BPB_RootEntCnt * sizeof(FAT_DIRECTORY_ENTRY)) + + (FatBpb->Fat12_16.BPB_BytsPerSec - 1)) / + FatBpb->Fat12_16.BPB_BytsPerSec; + + if (FatBpb->Fat12_16.BPB_FATSz16 != 0) { + FATSz = FatBpb->Fat12_16.BPB_FATSz16; + } else { + FATSz = FatBpb->Fat32.BPB_FATSz32; + } + if (FATSz == 0) { + DebugMsg (NULL, 0, DEBUG_ERROR, NULL, "ERROR: E3003: FAT - BPB_FATSz16, BPB_FATSz32 - 0, expected: Non-Zero Value"); + return FatTypeUnknown; + } + + if (FatBpb->Fat12_16.BPB_TotSec16 != 0) { + TotSec = FatBpb->Fat12_16.BPB_TotSec16; + } else { + TotSec = FatBpb->Fat12_16.BPB_TotSec32; + } + if (TotSec == 0) { + DebugMsg (NULL, 0, DEBUG_ERROR, NULL, "ERROR: E3003: FAT - BPB_TotSec16, BPB_TotSec32 - 0, expected: Non-Zero Value"); + return FatTypeUnknown; + } + + DataSec = TotSec - ( + FatBpb->Fat12_16.BPB_RsvdSecCnt + + FatBpb->Fat12_16.BPB_NumFATs * FATSz + + RootDirSectors + ); + + CountOfClusters = DataSec / FatBpb->Fat12_16.BPB_SecPerClus; + + if (CountOfClusters < FAT_MAX_FAT12_CLUSTER) { + FatType = FatTypeFat12; + } else if (CountOfClusters < FAT_MAX_FAT16_CLUSTER) { + FatType = FatTypeFat16; + } else { + FatType = FatTypeFat32; + } + // + // Check according to FAT spec + // + if (((FatType == FatTypeFat12) || (FatType == FatTypeFat16)) && + (FatBpb->Fat12_16.BPB_RsvdSecCnt != 1)) { + DebugMsg (NULL, 0, DEBUG_WARN, NULL, "ERROR: E3003: FAT12_16 - BPB_RsvdSecCnt - %04x, expected: %04x", + FatBpb->Fat12_16.BPB_RsvdSecCnt, 1); + } + if ((FatType == FatTypeFat32) && + (FatBpb->Fat12_16.BPB_RsvdSecCnt != 32)) { + DebugMsg (NULL, 0, DEBUG_WARN, NULL, "ERROR: E3003: FAT32 - BPB_RsvdSecCnt - %04x, expected: %04x", + FatBpb->Fat12_16.BPB_RsvdSecCnt, 32); + } + if ((FatType == FatTypeFat16) && + (FatBpb->Fat12_16.BPB_RootEntCnt != 512)) { + printf ("WARNING: FAT16: BPB_RootEntCnt - %04x, expected - %04x\n", + FatBpb->Fat12_16.BPB_RootEntCnt, 512); + } + if ((FatType == FatTypeFat32) && + (FatBpb->Fat12_16.BPB_RootEntCnt != 0)) { + DebugMsg (NULL, 0, DEBUG_ERROR, NULL, "ERROR: E3003: FAT32 - BPB_RootEntCnt - %04x, expected: %04x", + FatBpb->Fat12_16.BPB_RootEntCnt, 0); + return FatTypeUnknown; + } + if ((FatType == FatTypeFat32) && + (FatBpb->Fat12_16.BPB_TotSec16 != 0)) { + DebugMsg (NULL, 0, DEBUG_ERROR, NULL, "ERROR: E3003: FAT32 - BPB_TotSec16 - %04x, expected: %04x", + FatBpb->Fat12_16.BPB_TotSec16, 0); + return FatTypeUnknown; + } + if ((FatType == FatTypeFat32) && + (FatBpb->Fat12_16.BPB_FATSz16 != 0)) { + DebugMsg (NULL, 0, DEBUG_ERROR, NULL, "ERROR: E3003: FAT32 - BPB_FATSz16 - %04x, expected: %04x", + FatBpb->Fat12_16.BPB_FATSz16, 0); + return FatTypeUnknown; + } + if ((FatType == FatTypeFat32) && + (FatBpb->Fat12_16.BPB_TotSec32 == 0)) { + DebugMsg (NULL, 0, DEBUG_ERROR, NULL, "ERROR: E3003: FAT32 - BPB_TotSec32 - %04x, expected: Non-Zero", + FatBpb->Fat12_16.BPB_TotSec32); + return FatTypeUnknown; + } + if ((FatType == FatTypeFat32) && + (FatBpb->Fat32.BPB_FATSz32 == 0)) { + DebugMsg (NULL, 0, DEBUG_ERROR, NULL, "ERROR: E3003: FAT32 - BPB_FATSz32 - %08x, expected: Non-Zero", + FatBpb->Fat32.BPB_FATSz32); + return FatTypeUnknown; + } + if ((FatType == FatTypeFat32) && + (FatBpb->Fat32.BPB_FSVer != 0)) { + DebugMsg (NULL, 0, DEBUG_WARN, NULL, "ERROR: E3003: FAT32 - BPB_FSVer - %08x, expected: %04x", + FatBpb->Fat32.BPB_FSVer, 0); + } + if ((FatType == FatTypeFat32) && + (FatBpb->Fat32.BPB_RootClus != 2)) { + DebugMsg (NULL, 0, DEBUG_WARN, NULL, "ERROR: E3003: FAT32 - BPB_RootClus - %08x, expected: %04x", + FatBpb->Fat32.BPB_RootClus, 2); + } + if ((FatType == FatTypeFat32) && + (FatBpb->Fat32.BPB_FSInfo != 1)) { + DebugMsg (NULL, 0, DEBUG_WARN, NULL, "ERROR: E3003: FAT32 - BPB_FSInfo - %08x, expected: %04x", + FatBpb->Fat32.BPB_FSInfo, 1); + } + if ((FatType == FatTypeFat32) && + (FatBpb->Fat32.BPB_BkBootSec != 6)) { + DebugMsg (NULL, 0, DEBUG_WARN, NULL, "ERROR: E3003: FAT32 - BPB_BkBootSec - %08x, expected: %04x", + FatBpb->Fat32.BPB_BkBootSec, 6); + } + if ((FatType == FatTypeFat32) && + ((*(UINT32 *)FatBpb->Fat32.BPB_Reserved != 0) || + (*((UINT32 *)FatBpb->Fat32.BPB_Reserved + 1) != 0) || + (*((UINT32 *)FatBpb->Fat32.BPB_Reserved + 2) != 0))) { + DebugMsg (NULL, 0, DEBUG_ERROR, NULL, "ERROR: E3003: FAT32 - BPB_Reserved - %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x, expected: 0", + FatBpb->Fat32.BPB_Reserved[0], + FatBpb->Fat32.BPB_Reserved[1], + FatBpb->Fat32.BPB_Reserved[2], + FatBpb->Fat32.BPB_Reserved[3], + FatBpb->Fat32.BPB_Reserved[4], + FatBpb->Fat32.BPB_Reserved[5], + FatBpb->Fat32.BPB_Reserved[6], + FatBpb->Fat32.BPB_Reserved[7], + FatBpb->Fat32.BPB_Reserved[8], + FatBpb->Fat32.BPB_Reserved[9], + FatBpb->Fat32.BPB_Reserved[10], + FatBpb->Fat32.BPB_Reserved[11]); + return FatTypeUnknown; + } + if (((FatType == FatTypeFat12) || (FatType == FatTypeFat16)) && + (FatBpb->Fat12_16.BS_Reserved1 != 0)) { + DebugMsg (NULL, 0, DEBUG_ERROR, NULL, "ERROR: E3003: FAT12_16 - BS_Reserved1 - %02x, expected: 0\n", + FatBpb->Fat12_16.BS_Reserved1); + return FatTypeUnknown; + } + if ((FatType == FatTypeFat32) && + (FatBpb->Fat32.BS_Reserved1 != 0)) { + DebugMsg (NULL, 0, DEBUG_ERROR, NULL, "ERROR: E3003: FAT32 - BS_Reserved1 - %02x, expected: 0\n", + FatBpb->Fat32.BS_Reserved1); + return FatTypeUnknown; + } + if (((FatType == FatTypeFat12) || (FatType == FatTypeFat16)) && + (FatBpb->Fat12_16.BS_BootSig != FAT_BS_BOOTSIG)) { + DebugMsg (NULL, 0, DEBUG_ERROR, NULL, "ERROR: E3003: FAT12_16 - BS_BootSig - %02x, expected: %02x\n", + FatBpb->Fat12_16.BS_BootSig, FAT_BS_BOOTSIG); + return FatTypeUnknown; + } + if ((FatType == FatTypeFat32) && + (FatBpb->Fat32.BS_BootSig != FAT_BS_BOOTSIG)) { + DebugMsg (NULL, 0, DEBUG_ERROR, NULL, "ERROR: E3003: FAT32 - BS_BootSig - %02x, expected: %02x\n", + FatBpb->Fat32.BS_BootSig, FAT_BS_BOOTSIG); + return FatTypeUnknown; + } + + if ((FatType == FatTypeFat12) || (FatType == FatTypeFat16)) { + memcpy (FilSysType, FatBpb->Fat12_16.BS_FilSysType, 8); + FilSysType[8] = 0; + if ((FatType == FatTypeFat12) && + (strcmp (FilSysType, FAT12_FILSYSTYPE) != 0) && + (strcmp (FilSysType, FAT_FILSYSTYPE) != 0)) { + DebugMsg (NULL, 0, DEBUG_WARN, NULL, "ERROR: E3003: FAT12 - BS_FilSysType - %s, expected: %s, or %s\n", + FilSysType, FAT12_FILSYSTYPE, FAT_FILSYSTYPE); + } + if ((FatType == FatTypeFat16) && + (strcmp (FilSysType, FAT16_FILSYSTYPE) != 0) && + (strcmp (FilSysType, FAT_FILSYSTYPE) != 0)) { + DebugMsg (NULL, 0, DEBUG_WARN, NULL, "ERROR: E3003: FAT16 - BS_FilSysType - %s, expected: %s, or %s\n", + FilSysType, FAT16_FILSYSTYPE, FAT_FILSYSTYPE); + } + } + if (FatType == FatTypeFat32) { + memcpy (FilSysType, FatBpb->Fat32.BS_FilSysType, 8); + FilSysType[8] = 0; + if (strcmp (FilSysType, FAT32_FILSYSTYPE) != 0) { + DebugMsg (NULL, 0, DEBUG_WARN, NULL, "ERROR: E3003: FAT32 - BS_FilSysType - %s, expected: %s\n", + FilSysType, FAT32_FILSYSTYPE); + } + } + + // + // pass all check, get FAT type + // + return FatType; +} + + +void +ParseBootSector ( + char *FileName + ) +{ + FAT_BPB_STRUCT FatBpb; + FAT_TYPE FatType; + + if (ReadFromFile ((void *)&FatBpb, FileName) == 0) { + return ; + } + + FatType = GetFatType (&FatBpb); + if (FatType <= FatTypeUnknown || FatType >= FatTypeMax) { + printf ("ERROR: E3002: Unknown FAT Type!\n"); + return; + } + + printf ("\nBoot Sector %s:\n", FatTypeToString (FatType)); + printf ("\n"); + printf (" Offset Title Data\n"); + printf ("==================================================================\n"); + printf (" 0 JMP instruction %02x %02x %02x\n", + FatBpb.Fat12_16.BS_jmpBoot[0], + FatBpb.Fat12_16.BS_jmpBoot[1], + FatBpb.Fat12_16.BS_jmpBoot[2]); + printf (" 3 OEM %c%c%c%c%c%c%c%c\n", + FatBpb.Fat12_16.BS_OEMName[0], + FatBpb.Fat12_16.BS_OEMName[1], + FatBpb.Fat12_16.BS_OEMName[2], + FatBpb.Fat12_16.BS_OEMName[3], + FatBpb.Fat12_16.BS_OEMName[4], + FatBpb.Fat12_16.BS_OEMName[5], + FatBpb.Fat12_16.BS_OEMName[6], + FatBpb.Fat12_16.BS_OEMName[7]); + printf ("\n"); + printf ("BIOS Parameter Block\n"); + printf (" B Bytes per sector %04x\n", FatBpb.Fat12_16.BPB_BytsPerSec); + printf (" D Sectors per cluster %02x\n", FatBpb.Fat12_16.BPB_SecPerClus); + printf (" E Reserved sectors %04x\n", FatBpb.Fat12_16.BPB_RsvdSecCnt); + printf (" 10 Number of FATs %02x\n", FatBpb.Fat12_16.BPB_NumFATs); + printf (" 11 Root entries %04x\n", FatBpb.Fat12_16.BPB_RootEntCnt); + printf (" 13 Sectors (under 32MB) %04x\n", FatBpb.Fat12_16.BPB_TotSec16); + printf (" 15 Media descriptor %02x\n", FatBpb.Fat12_16.BPB_Media); + printf (" 16 Sectors per FAT (small vol.) %04x\n", FatBpb.Fat12_16.BPB_FATSz16); + printf (" 18 Sectors per track %04x\n", FatBpb.Fat12_16.BPB_SecPerTrk); + printf (" 1A Heads %04x\n", FatBpb.Fat12_16.BPB_NumHeads); + printf (" 1C Hidden sectors %08x\n", FatBpb.Fat12_16.BPB_HiddSec); + printf (" 20 Sectors (over 32MB) %08x\n", FatBpb.Fat12_16.BPB_TotSec32); + printf ("\n"); + if (FatType != FatTypeFat32) { + printf (" 24 BIOS drive %02x\n", FatBpb.Fat12_16.BS_DrvNum); + printf (" 25 (Unused) %02x\n", FatBpb.Fat12_16.BS_Reserved1); + printf (" 26 Ext. boot signature %02x\n", FatBpb.Fat12_16.BS_BootSig); + printf (" 27 Volume serial number %08x\n", FatBpb.Fat12_16.BS_VolID); + printf (" 2B Volume lable %c%c%c%c%c%c%c%c%c%c%c\n", + FatBpb.Fat12_16.BS_VolLab[0], + FatBpb.Fat12_16.BS_VolLab[1], + FatBpb.Fat12_16.BS_VolLab[2], + FatBpb.Fat12_16.BS_VolLab[3], + FatBpb.Fat12_16.BS_VolLab[4], + FatBpb.Fat12_16.BS_VolLab[5], + FatBpb.Fat12_16.BS_VolLab[6], + FatBpb.Fat12_16.BS_VolLab[7], + FatBpb.Fat12_16.BS_VolLab[8], + FatBpb.Fat12_16.BS_VolLab[9], + FatBpb.Fat12_16.BS_VolLab[10]); + printf (" 36 File system %c%c%c%c%c%c%c%c\n", + FatBpb.Fat12_16.BS_FilSysType[0], + FatBpb.Fat12_16.BS_FilSysType[1], + FatBpb.Fat12_16.BS_FilSysType[2], + FatBpb.Fat12_16.BS_FilSysType[3], + FatBpb.Fat12_16.BS_FilSysType[4], + FatBpb.Fat12_16.BS_FilSysType[5], + FatBpb.Fat12_16.BS_FilSysType[6], + FatBpb.Fat12_16.BS_FilSysType[7]); + printf ("\n"); + } else { + printf ("FAT32 Section\n"); + printf (" 24 Sectors per FAT (large vol.) %08x\n", FatBpb.Fat32.BPB_FATSz32); + printf (" 28 Flags %04x\n", FatBpb.Fat32.BPB_ExtFlags); + printf (" 2A Version %04x\n", FatBpb.Fat32.BPB_FSVer); + printf (" 2C Root dir 1st cluster %08x\n", FatBpb.Fat32.BPB_RootClus); + printf (" 30 FSInfo sector %04x\n", FatBpb.Fat32.BPB_FSInfo); + printf (" 32 Backup boot sector %04x\n", FatBpb.Fat32.BPB_BkBootSec); + printf (" 34 (Reserved) %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n", + FatBpb.Fat32.BPB_Reserved[0], + FatBpb.Fat32.BPB_Reserved[1], + FatBpb.Fat32.BPB_Reserved[2], + FatBpb.Fat32.BPB_Reserved[3], + FatBpb.Fat32.BPB_Reserved[4], + FatBpb.Fat32.BPB_Reserved[5], + FatBpb.Fat32.BPB_Reserved[6], + FatBpb.Fat32.BPB_Reserved[7], + FatBpb.Fat32.BPB_Reserved[8], + FatBpb.Fat32.BPB_Reserved[9], + FatBpb.Fat32.BPB_Reserved[10], + FatBpb.Fat32.BPB_Reserved[11]); + printf ("\n"); + printf (" 40 BIOS drive %02x\n", FatBpb.Fat32.BS_DrvNum); + printf (" 41 (Unused) %02x\n", FatBpb.Fat32.BS_Reserved1); + printf (" 42 Ext. boot signature %02x\n", FatBpb.Fat32.BS_BootSig); + printf (" 43 Volume serial number %08x\n", FatBpb.Fat32.BS_VolID); + printf (" 47 Volume lable %c%c%c%c%c%c%c%c%c%c%c\n", + FatBpb.Fat32.BS_VolLab[0], + FatBpb.Fat32.BS_VolLab[1], + FatBpb.Fat32.BS_VolLab[2], + FatBpb.Fat32.BS_VolLab[3], + FatBpb.Fat32.BS_VolLab[4], + FatBpb.Fat32.BS_VolLab[5], + FatBpb.Fat32.BS_VolLab[6], + FatBpb.Fat32.BS_VolLab[7], + FatBpb.Fat32.BS_VolLab[8], + FatBpb.Fat32.BS_VolLab[9], + FatBpb.Fat32.BS_VolLab[10]); + printf (" 52 File system %c%c%c%c%c%c%c%c\n", + FatBpb.Fat32.BS_FilSysType[0], + FatBpb.Fat32.BS_FilSysType[1], + FatBpb.Fat32.BS_FilSysType[2], + FatBpb.Fat32.BS_FilSysType[3], + FatBpb.Fat32.BS_FilSysType[4], + FatBpb.Fat32.BS_FilSysType[5], + FatBpb.Fat32.BS_FilSysType[6], + FatBpb.Fat32.BS_FilSysType[7]); + printf ("\n"); + } + printf (" 1FE Signature %04x\n", FatBpb.Fat12_16.Signature); + printf ("\n"); + + + return ; +} + +void +PatchBootSector ( + char *DestFileName, + char *SourceFileName, + BOOLEAN ForcePatch + ) +/*++ +Routine Description: + Patch destination file according to the information from source file. + Only patch BPB data but leave boot code un-touched. + +Arguments: + DestFileName - Destination file to patch + SourceFileName - Source file where patch from +--*/ +{ + FAT_BPB_STRUCT DestFatBpb; + FAT_BPB_STRUCT SourceFatBpb; + FAT_TYPE DestFatType; + FAT_TYPE SourceFatType; + CHAR8 VolLab[11]; + CHAR8 FilSysType[8]; + + if (ReadFromFile ((void *)&DestFatBpb, DestFileName) == 0) { + return ; + } + if (ReadFromFile ((void *)&SourceFatBpb, SourceFileName) == 0) { + return ; + } + + DestFatType = GetFatType (&DestFatBpb); + SourceFatType = GetFatType (&SourceFatBpb); + + if (DestFatType != SourceFatType) { + // + // FAT type mismatch + // + if (ForcePatch) { + DebugMsg (NULL, 0, DEBUG_WARN, NULL, "ERROR: E3004: FAT type mismatch: Source - %s, Dest - %s", + FatTypeToString(SourceFatType), FatTypeToString(DestFatType)); + } else { + DebugMsg (NULL, 0, DEBUG_ERROR, NULL, "ERROR: E3004: FAT type mismatch: Source - %s, Dest - %s", + FatTypeToString(SourceFatType), FatTypeToString(DestFatType)); + return ; + } + } + + if (SourceFatType <= FatTypeUnknown || SourceFatType >= FatTypeMax) { + DebugMsg (NULL, 0, DEBUG_ERROR, NULL, "ERROR: E3002: Unknown FAT Type!\n"); + return; + } + + // + // Copy BPB/boot data (excluding BS_jmpBoot, BS_OEMName, BootCode and Signature) from SourceFatBpb to DestFatBpb + // + printf ("Patching %s BPB: ", FatTypeToString (SourceFatType)); + if (SourceFatType != FatTypeFat32) { + memcpy ( + &DestFatBpb.Fat12_16.BPB_BytsPerSec, + &SourceFatBpb.Fat12_16.BPB_BytsPerSec, + ((UINTN)&DestFatBpb.Fat12_16.Reserved - (UINTN)&DestFatBpb.Fat12_16.BPB_BytsPerSec) + ); + } else { + memcpy ( + &DestFatBpb.Fat32.BPB_BytsPerSec, + &SourceFatBpb.Fat32.BPB_BytsPerSec, + ((UINTN)&DestFatBpb.Fat32.Reserved - (UINTN)&DestFatBpb.Fat32.BPB_BytsPerSec) + ); + } + + // + // Set BS_VolLab and BS_FilSysType of DestFatBpb + // + // BS_VolLab BS_FilSysType + // FAT12: EFI FAT12 FAT12 + // FAT16: EFI FAT16 FAT16 + // FAT32: EFI FAT32 FAT32 + // + if (SourceFatType == FatTypeFat32) { + memcpy (VolLab, "EFI FAT32 ", sizeof(VolLab)); + memcpy (FilSysType, FAT32_FILSYSTYPE, sizeof(FilSysType)); + } else if (SourceFatType == FatTypeFat16) { + memcpy (VolLab, "EFI FAT16 ", sizeof(VolLab)); + memcpy (FilSysType, FAT16_FILSYSTYPE, sizeof(FilSysType)); + } else { + memcpy (VolLab, "EFI FAT12 ", sizeof(VolLab)); + memcpy (FilSysType, FAT12_FILSYSTYPE, sizeof(FilSysType)); + } + if (SourceFatType != FatTypeFat32) { + memcpy (DestFatBpb.Fat12_16.BS_VolLab, VolLab, sizeof(VolLab)); + memcpy (DestFatBpb.Fat12_16.BS_FilSysType, FilSysType, sizeof(FilSysType)); + } else { + memcpy (DestFatBpb.Fat32.BS_VolLab, VolLab, sizeof(VolLab)); + memcpy (DestFatBpb.Fat32.BS_FilSysType, FilSysType, sizeof(FilSysType)); + } + + // + // Set Signature of DestFatBpb to 55AA + // + DestFatBpb.Fat12_16.Signature = FAT_BS_SIGNATURE; + + // + // Write DestFatBpb + // + if (WriteToFile ((void *)&DestFatBpb, DestFileName)) { + printf ("successful!\n"); + } else { + printf ("failed!\n"); + } + + return ; +} + +void +ParseMbr ( + char *FileName + ) +{ + MASTER_BOOT_RECORD Mbr; + + if (ReadFromFile ((void *)&Mbr, FileName) == 0) { + return ; + } + + printf ("\nMaster Boot Record:\n"); + printf ("\n"); + printf (" Offset Title Value\n"); + printf ("==================================================================\n"); + printf (" 0 Master bootstrap loader code (not list)\n"); + printf (" 1B8 Windows disk signature %08x\n", Mbr.UniqueMbrSignature); + printf ("\n"); + printf ("Partition Table Entry #1\n"); + printf (" 1BE 80 = active partition %02x\n", Mbr.PartitionRecord[0].BootIndicator); + printf (" 1BF Start head %02x\n", Mbr.PartitionRecord[0].StartHead); + printf (" 1C0 Start sector %02x\n", Mbr.PartitionRecord[0].StartSector); + printf (" 1C1 Start cylinder %02x\n", Mbr.PartitionRecord[0].StartTrack); + printf (" 1C2 Partition type indicator %02x\n", Mbr.PartitionRecord[0].OSType); + printf (" 1C3 End head %02x\n", Mbr.PartitionRecord[0].EndHead); + printf (" 1C4 End sector %02x\n", Mbr.PartitionRecord[0].EndSector); + printf (" 1C5 End cylinder %02x\n", Mbr.PartitionRecord[0].EndTrack); + printf (" 1C6 Sectors preceding partition %08x\n", Mbr.PartitionRecord[0].StartingLBA); + printf (" 1CA Sectors in partition %08x\n", Mbr.PartitionRecord[0].SizeInLBA); + printf ("\n"); + printf ("Partition Table Entry #2\n"); + printf (" 1CE 80 = active partition %02x\n", Mbr.PartitionRecord[1].BootIndicator); + printf (" 1CF Start head %02x\n", Mbr.PartitionRecord[1].StartHead); + printf (" 1D0 Start sector %02x\n", Mbr.PartitionRecord[1].StartSector); + printf (" 1D1 Start cylinder %02x\n", Mbr.PartitionRecord[1].StartTrack); + printf (" 1D2 Partition type indicator %02x\n", Mbr.PartitionRecord[1].OSType); + printf (" 1D3 End head %02x\n", Mbr.PartitionRecord[1].EndHead); + printf (" 1D4 End sector %02x\n", Mbr.PartitionRecord[1].EndSector); + printf (" 1D5 End cylinder %02x\n", Mbr.PartitionRecord[1].EndTrack); + printf (" 1D6 Sectors preceding partition %08x\n", Mbr.PartitionRecord[1].StartingLBA); + printf (" 1DA Sectors in partition %08x\n", Mbr.PartitionRecord[1].SizeInLBA); + printf ("\n"); + printf ("Partition Table Entry #3\n"); + printf (" 1DE 80 = active partition %02x\n", Mbr.PartitionRecord[2].BootIndicator); + printf (" 1DF Start head %02x\n", Mbr.PartitionRecord[2].StartHead); + printf (" 1E0 Start sector %02x\n", Mbr.PartitionRecord[2].StartSector); + printf (" 1E1 Start cylinder %02x\n", Mbr.PartitionRecord[2].StartTrack); + printf (" 1E2 Partition type indicator %02x\n", Mbr.PartitionRecord[2].OSType); + printf (" 1E3 End head %02x\n", Mbr.PartitionRecord[2].EndHead); + printf (" 1E4 End sector %02x\n", Mbr.PartitionRecord[2].EndSector); + printf (" 1E5 End cylinder %02x\n", Mbr.PartitionRecord[2].EndTrack); + printf (" 1E6 Sectors preceding partition %08x\n", Mbr.PartitionRecord[2].StartingLBA); + printf (" 1EA Sectors in partition %08x\n", Mbr.PartitionRecord[2].SizeInLBA); + printf ("\n"); + printf ("Partition Table Entry #4\n"); + printf (" 1EE 80 = active partition %02x\n", Mbr.PartitionRecord[3].BootIndicator); + printf (" 1EF Start head %02x\n", Mbr.PartitionRecord[3].StartHead); + printf (" 1F0 Start sector %02x\n", Mbr.PartitionRecord[3].StartSector); + printf (" 1F1 Start cylinder %02x\n", Mbr.PartitionRecord[3].StartTrack); + printf (" 1F2 Partition type indicator %02x\n", Mbr.PartitionRecord[3].OSType); + printf (" 1F3 End head %02x\n", Mbr.PartitionRecord[3].EndHead); + printf (" 1F4 End sector %02x\n", Mbr.PartitionRecord[3].EndSector); + printf (" 1F5 End cylinder %02x\n", Mbr.PartitionRecord[3].EndTrack); + printf (" 1F6 Sectors preceding partition %08x\n", Mbr.PartitionRecord[3].StartingLBA); + printf (" 1FA Sectors in partition %08x\n", Mbr.PartitionRecord[3].SizeInLBA); + printf ("\n"); + printf (" 1FE Signature %04x\n", Mbr.Signature); + printf ("\n"); + + return ; +} + +void +PatchMbr ( + char *DestFileName, + char *SourceFileName + ) +{ + MASTER_BOOT_RECORD DestMbr; + MASTER_BOOT_RECORD SourceMbr; + + if (ReadFromFile ((void *)&DestMbr, DestFileName) == 0) { + return ; + } + if (ReadFromFile ((void *)&SourceMbr, SourceFileName) == 0) { + return ; + } + + if (SourceMbr.Signature != MBR_SIGNATURE) { + printf ("ERROR: E3000: Invalid MBR!\n"); + return; + } + + printf ("Patching MBR:\n"); + memcpy ( + &DestMbr.PartitionRecord[0], + &SourceMbr.PartitionRecord[0], + sizeof(DestMbr.PartitionRecord) + ); + + DestMbr.Signature = MBR_SIGNATURE; + + + if (WriteToFile ((void *)&DestMbr, DestFileName)) { + printf ("\tsuccessful!\n"); + } + + return ; +} + + +int +main ( + int argc, + char *argv[] + ) +{ + char *SrcImage; + char *DstImage; + BOOLEAN ForcePatch; // -f + BOOLEAN ProcessMbr; // -m + BOOLEAN DoParse; // -p SrcImage or -g SrcImage DstImage + BOOLEAN Verbose; // -v + + SrcImage = DstImage = NULL; + ForcePatch = FALSE; + ProcessMbr = FALSE; + DoParse = TRUE; + Verbose = FALSE; + + SetUtilityName ("bootsectimage"); + + argc--; argv++; + + if (argc == 0) { + Usage (); + return -1; + } + + while (argc != 0) { + if (strcmp (*argv, "-f") == 0 || strcmp (*argv, "--force") == 0) { + ForcePatch = TRUE; + } else if (strcmp (*argv, "-p") == 0 || strcmp (*argv, "--parse") == 0) { + DoParse = TRUE; + argc--; argv++; + if (argc < 1) { + Usage (); + return -1; + } + SrcImage = *argv; + } else if (strcmp (*argv, "-g") == 0 || strcmp (*argv, "--patch") == 0) { + DoParse = FALSE; + argc--; argv++; + if (argc < 2) { + Usage (); + return -1; + } + SrcImage = *argv; + argc--; argv++; + DstImage = *argv; + } else if (strcmp (*argv, "-m") == 0 || strcmp (*argv, "--mbr") == 0) { + ProcessMbr = TRUE; + } else if (strcmp (*argv, "-v") == 0 || strcmp (*argv, "--verbose") == 0) { + Verbose = TRUE; + } else { + Usage (); + return -1; + } + + argc--; argv++; + } + + if (ForcePatch && DoParse) { + printf ("ERROR: E1002: Conflicting options: -f, -p. Cannot apply force(-f) to parse(-p)!\n"); + Usage (); + return -1; + } + if (ForcePatch && !DoParse && ProcessMbr) { + printf ("ERROR: E1002: Conflicting options: -f, -g -m. Cannot apply force(-f) to processing MBR (-g -m)!\n"); + Usage (); + return -1; + } + + if (Verbose) { + SetPrintLevel (VERBOSE_LOG_LEVEL); + } else { + SetPrintLevel (KEY_LOG_LEVEL); + } + + if (DoParse) { + if (ProcessMbr) { + ParseMbr (SrcImage); + } else { + ParseBootSector (SrcImage); + } + } else { + if (ProcessMbr) { + PatchMbr (DstImage, SrcImage); + } else { + PatchBootSector (DstImage, SrcImage, ForcePatch); + } + } + + return 0; +} + diff --git a/BaseTools/Source/C/BootSectImage/fat.h b/BaseTools/Source/C/BootSectImage/fat.h new file mode 100644 index 0000000000..fac03e683b --- /dev/null +++ b/BaseTools/Source/C/BootSectImage/fat.h @@ -0,0 +1,152 @@ +/** @file + + Fat file system structure and definition. + +Copyright 2006 - 2008, 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. + +**/ + +#ifndef _FAT_BPB_H_ +#define _FAT_BPB_H_ + +#include "CommonLib.h" + +#pragma pack(1) + +typedef struct { + // + // Fat common field + // + UINT8 BS_jmpBoot[3]; + CHAR8 BS_OEMName[8]; + UINT16 BPB_BytsPerSec; + UINT8 BPB_SecPerClus; + UINT16 BPB_RsvdSecCnt; + UINT8 BPB_NumFATs; + UINT16 BPB_RootEntCnt; + UINT16 BPB_TotSec16; + UINT8 BPB_Media; + UINT16 BPB_FATSz16; + UINT16 BPB_SecPerTrk; + UINT16 BPB_NumHeads; + UINT32 BPB_HiddSec; + UINT32 BPB_TotSec32; + + // + // Fat12/16 specific field + // + UINT8 BS_DrvNum; + UINT8 BS_Reserved1; + UINT8 BS_BootSig; + UINT32 BS_VolID; + CHAR8 BS_VolLab[11]; + CHAR8 BS_FilSysType[8]; + + // + // Boot Code and Data + // + UINT8 Reserved[448]; + + // + // Fat common signature - 0xAA55 + // + UINT16 Signature; +} FAT12_16_BPB_STRUCT; + +typedef struct { + // + // Fat common field + // + UINT8 BS_jmpBoot[3]; + CHAR8 BS_OEMName[8]; + UINT16 BPB_BytsPerSec; + UINT8 BPB_SecPerClus; + UINT16 BPB_RsvdSecCnt; + UINT8 BPB_NumFATs; + UINT16 BPB_RootEntCnt; + UINT16 BPB_TotSec16; + UINT8 BPB_Media; + UINT16 BPB_FATSz16; + UINT16 BPB_SecPerTrk; + UINT16 BPB_NumHeads; + UINT32 BPB_HiddSec; + UINT32 BPB_TotSec32; + + // + // Fat32 specific field + // + UINT32 BPB_FATSz32; + UINT16 BPB_ExtFlags; + UINT16 BPB_FSVer; + UINT32 BPB_RootClus; + UINT16 BPB_FSInfo; + UINT16 BPB_BkBootSec; + UINT8 BPB_Reserved[12]; + UINT8 BS_DrvNum; + UINT8 BS_Reserved1; + UINT8 BS_BootSig; + UINT32 BS_VolID; + CHAR8 BS_VolLab[11]; + CHAR8 BS_FilSysType[8]; + + // + // Boot Code and Data + // + UINT8 Reserved[420]; + + // + // Fat common signature - 0xAA55 + // + UINT16 Signature; +} FAT32_BPB_STRUCT; + +typedef union { + FAT12_16_BPB_STRUCT Fat12_16; + FAT32_BPB_STRUCT Fat32; +} FAT_BPB_STRUCT; + +typedef enum { + FatTypeUnknown, + FatTypeFat12, + FatTypeFat16, + FatTypeFat32, + FatTypeMax +} FAT_TYPE; + +typedef struct { + CHAR8 DIR_Name[11]; + UINT8 DIR_Attr; + UINT8 DIR_NTRes; + UINT8 DIR_CrtTimeTenth; + UINT16 DIR_CrtTime; + UINT16 DIR_CrtDate; + UINT16 DIR_LstAccDate; + UINT16 DIR_FstClusHI; + UINT16 DIR_WrtTime; + UINT16 DIR_WrtDate; + UINT16 DIR_FstClusLO; + UINT32 DIR_FileSize; +} FAT_DIRECTORY_ENTRY; + +#pragma pack() + +#define FAT_MAX_FAT12_CLUSTER 0xFF5 +#define FAT_MAX_FAT16_CLUSTER 0xFFF5 + +#define FAT_BS_SIGNATURE 0xAA55 +#define FAT_BS_BOOTSIG 0x29 +#define FAT_BS_JMP1 0xEB +#define FAT_BS_JMP2 0xE9 +#define FAT_FILSYSTYPE "FAT " +#define FAT12_FILSYSTYPE "FAT12 " +#define FAT16_FILSYSTYPE "FAT16 " +#define FAT32_FILSYSTYPE "FAT32 " + +#endif diff --git a/BaseTools/Source/C/BootSectImage/mbr.h b/BaseTools/Source/C/BootSectImage/mbr.h new file mode 100644 index 0000000000..9103585cdd --- /dev/null +++ b/BaseTools/Source/C/BootSectImage/mbr.h @@ -0,0 +1,58 @@ +/** @file + + MBR Partition Entry and Table structure defintions. + +Copyright 2006 - 2008, 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. + +**/ + +#ifndef _MBR_H_ +#define _MBR_H_ + +#include "CommonLib.h" + +#pragma pack(1) + +#define MAX_MBR_PARTITIONS 4 + +// +// MBR Partition Entry +// +typedef struct { + UINT8 BootIndicator; + UINT8 StartHead; + UINT8 StartSector; + UINT8 StartTrack; + UINT8 OSType; + UINT8 EndHead; + UINT8 EndSector; + UINT8 EndTrack; + UINT32 StartingLBA; + UINT32 SizeInLBA; +} MBR_PARTITION_RECORD; + +// +// MBR Partition table +// +typedef struct { + UINT8 BootCode[440]; + UINT32 UniqueMbrSignature; + UINT16 Unknown; + MBR_PARTITION_RECORD PartitionRecord[MAX_MBR_PARTITIONS]; + UINT16 Signature; +} MASTER_BOOT_RECORD; + +#pragma pack() + +#define MBR_SIGNATURE 0xAA55 +#define EXTENDED_DOS_PARTITION 0x05 +#define EXTENDED_WINDOWS_PARTITION 0x0F + +#endif diff --git a/BaseTools/Source/C/Common/BasePeCoff.c b/BaseTools/Source/C/Common/BasePeCoff.c new file mode 100644 index 0000000000..72b6a52f89 --- /dev/null +++ b/BaseTools/Source/C/Common/BasePeCoff.c @@ -0,0 +1,1386 @@ +/** @file + + Functions to get info and load PE/COFF image. + +Copyright (c) 2004 - 2008, 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. + +**/ + +#include +#include +#include +#include "PeCoffLib.h" + +typedef union { + VOID *Header; + EFI_IMAGE_OPTIONAL_HEADER32 *Optional32; + EFI_IMAGE_OPTIONAL_HEADER64 *Optional64; +} EFI_IMAGE_OPTIONAL_HEADER_POINTER; + +STATIC +RETURN_STATUS +PeCoffLoaderGetPeHeader ( + IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext, + OUT EFI_IMAGE_OPTIONAL_HEADER_UNION **PeHdr, + OUT EFI_TE_IMAGE_HEADER **TeHdr + ); + +STATIC +RETURN_STATUS +PeCoffLoaderCheckImageType ( + IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext, + IN EFI_IMAGE_OPTIONAL_HEADER_UNION *PeHdr, + IN EFI_TE_IMAGE_HEADER *TeHdr + ); + +STATIC +VOID * +PeCoffLoaderImageAddress ( + IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext, + IN UINTN Address + ); + +RETURN_STATUS +PeCoffLoaderRelocateIa32Image ( + IN UINT16 *Reloc, + IN OUT CHAR8 *Fixup, + IN OUT CHAR8 **FixupData, + IN UINT64 Adjust + ); + +RETURN_STATUS +PeCoffLoaderRelocateX64Image ( + IN UINT16 *Reloc, + IN OUT CHAR8 *Fixup, + IN OUT CHAR8 **FixupData, + IN UINT64 Adjust + ); + +RETURN_STATUS +PeCoffLoaderRelocateIpfImage ( + IN UINT16 *Reloc, + IN OUT CHAR8 *Fixup, + IN OUT CHAR8 **FixupData, + IN UINT64 Adjust + ); + +STATIC +RETURN_STATUS +PeCoffLoaderGetPeHeader ( + IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext, + OUT EFI_IMAGE_OPTIONAL_HEADER_UNION **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; + } + // + // Get the PE/COFF Header pointer + // + *PeHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *) ((UINTN)ImageContext->Handle + ImageContext->PeCoffHeaderOffset); + if ((*PeHdr)->Pe32.Signature != EFI_IMAGE_NT_SIGNATURE) { + // + // Check the PE/COFF Header Signature. If not, then try to get a TE header + // + *TeHdr = (EFI_TE_IMAGE_HEADER *)*PeHdr; + 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_OPTIONAL_HEADER_UNION *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) + // + if (ImageContext->IsTeImage == FALSE) { + ImageContext->Machine = PeHdr->Pe32.FileHeader.Machine; + } else { + ImageContext->Machine = TeHdr->Machine; + } + + if (ImageContext->Machine != EFI_IMAGE_MACHINE_IA32 && \ + ImageContext->Machine != EFI_IMAGE_MACHINE_IA64 && \ + ImageContext->Machine != EFI_IMAGE_MACHINE_X64 && \ + ImageContext->Machine != EFI_IMAGE_MACHINE_ARMT && \ + ImageContext->Machine != EFI_IMAGE_MACHINE_EBC) { + if (ImageContext->Machine == IMAGE_FILE_MACHINE_ARM) { + // + // There are two types of ARM images. Pure ARM and ARM/Thumb. + // If we see the ARM say it is the ARM/Thumb so there is only + // a single machine type we need to check for ARM. + // + ImageContext->Machine = EFI_IMAGE_MACHINE_ARMT; + if (ImageContext->IsTeImage == FALSE) { + PeHdr->Pe32.FileHeader.Machine = ImageContext->Machine; + } else { + TeHdr->Machine = ImageContext->Machine; + } + + } else { + // + // unsupported PeImage machine type + // + return RETURN_UNSUPPORTED; + } + } + + // + // See if the image type is supported. We support EFI Applications, + // EFI Boot Service Drivers, EFI Runtime Drivers and EFI SAL Drivers. + // + if (ImageContext->IsTeImage == FALSE) { + ImageContext->ImageType = PeHdr->Pe32.OptionalHeader.Subsystem; + } else { + ImageContext->ImageType = (UINT16) (TeHdr->Subsystem); + } + + if (ImageContext->ImageType != EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION && \ + ImageContext->ImageType != EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER && \ + ImageContext->ImageType != EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER && \ + ImageContext->ImageType != EFI_IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER) { + // + // upsupported PeImage subsystem type + // + return RETURN_UNSUPPORTED; + } + + 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_OPTIONAL_HEADER_UNION *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; + EFI_IMAGE_OPTIONAL_HEADER_POINTER OptionHeader; + + PeHdr = NULL; + TeHdr = NULL; + DebugDirectoryEntry = NULL; + DebugDirectoryEntryRva = 0; + + 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; + } + OptionHeader.Header = (VOID *) &(PeHdr->Pe32.OptionalHeader); + + // + // Retrieve the base address of the image + // + if (!(ImageContext->IsTeImage)) { + if (PeHdr->Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) { + ImageContext->ImageAddress = (PHYSICAL_ADDRESS) OptionHeader.Optional32->ImageBase; + } else { + ImageContext->ImageAddress = (PHYSICAL_ADDRESS) OptionHeader.Optional64->ImageBase; + } + } else { + ImageContext->ImageAddress = (PHYSICAL_ADDRESS) (TeHdr->ImageBase + TeHdr->StrippedSize - sizeof (EFI_TE_IMAGE_HEADER)); + } + // + // 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->Pe32.FileHeader.Characteristics & EFI_IMAGE_FILE_RELOCS_STRIPPED) != 0)) { + ImageContext->RelocationsStripped = TRUE; + } else if ((ImageContext->IsTeImage) && (TeHdr->DataDirectory[0].Size == 0)) { + ImageContext->RelocationsStripped = TRUE; + } else { + ImageContext->RelocationsStripped = FALSE; + } + + if (!(ImageContext->IsTeImage)) { + + if (PeHdr->Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) { + ImageContext->ImageSize = (UINT64) OptionHeader.Optional32->SizeOfImage; + ImageContext->SectionAlignment = OptionHeader.Optional32->SectionAlignment; + ImageContext->SizeOfHeaders = OptionHeader.Optional32->SizeOfHeaders; + + // + // Modify ImageSize to contain .PDB file name if required and initialize + // PdbRVA field... + // + if (OptionHeader.Optional32->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG) { + DebugDirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *) &(OptionHeader.Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG]); + DebugDirectoryEntryRva = DebugDirectoryEntry->VirtualAddress; + } + } else { + ImageContext->ImageSize = (UINT64) OptionHeader.Optional64->SizeOfImage; + ImageContext->SectionAlignment = OptionHeader.Optional64->SectionAlignment; + ImageContext->SizeOfHeaders = OptionHeader.Optional64->SizeOfHeaders; + + // + // Modify ImageSize to contain .PDB file name if required and initialize + // PdbRVA field... + // + if (OptionHeader.Optional64->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG) { + DebugDirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *) &(OptionHeader.Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG]); + DebugDirectoryEntryRva = DebugDirectoryEntry->VirtualAddress; + } + } + + if (DebugDirectoryEntryRva != 0) { + // + // 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->Pe32.FileHeader.SizeOfOptionalHeader + ); + + for (Index = 0; Index < PeHdr->Pe32.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 += sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY)) { + // + // Read next debug directory entry + // + Size = sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY); + Status = ImageContext->ImageRead ( + ImageContext->Handle, + DebugDirectoryEntryFileOffset + Index, + &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); + 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 += sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY)) { + // + // 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); + 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 (UINT8 *) ((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_OPTIONAL_HEADER_UNION *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; + UINT16 MachineType; + EFI_IMAGE_OPTIONAL_HEADER_POINTER OptionHeader; + + 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_OPTIONAL_HEADER_UNION *)((UINTN)ImageContext->ImageAddress + + ImageContext->PeCoffHeaderOffset); + OptionHeader.Header = (VOID *) &(PeHdr->Pe32.OptionalHeader); + if (PeHdr->Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) { + Adjust = (UINT64) BaseAddress - OptionHeader.Optional32->ImageBase; + OptionHeader.Optional32->ImageBase = (UINT32) BaseAddress; + MachineType = ImageContext->Machine; + // + // 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 (OptionHeader.Optional32->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) { + RelocDir = &OptionHeader.Optional32->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 { + Adjust = (UINT64) BaseAddress - OptionHeader.Optional64->ImageBase; + OptionHeader.Optional64->ImageBase = BaseAddress; + MachineType = ImageContext->Machine; + // + // 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 (OptionHeader.Optional64->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) { + RelocDir = &OptionHeader.Optional64->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); + MachineType = TeHdr->Machine; + + // + // 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: + switch (MachineType) { + case EFI_IMAGE_MACHINE_IA32: + case EFI_IMAGE_MACHINE_ARMT: + Status = PeCoffLoaderRelocateIa32Image (Reloc, Fixup, &FixupData, Adjust); + break; + case EFI_IMAGE_MACHINE_X64: + Status = PeCoffLoaderRelocateX64Image (Reloc, Fixup, &FixupData, Adjust); + break; + case EFI_IMAGE_MACHINE_IA64: + Status = PeCoffLoaderRelocateIpfImage (Reloc, Fixup, &FixupData, Adjust); + break; + default: + Status = RETURN_UNSUPPORTED; + break; + } + 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_OPTIONAL_HEADER_UNION *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; + EFI_IMAGE_OPTIONAL_HEADER_POINTER OptionHeader; + + 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_OPTIONAL_HEADER_UNION *) + ((UINTN)ImageContext->ImageAddress + ImageContext->PeCoffHeaderOffset); + + OptionHeader.Header = (VOID *) &(PeHdr->Pe32.OptionalHeader); + + FirstSection = (EFI_IMAGE_SECTION_HEADER *) ( + (UINTN)ImageContext->ImageAddress + + ImageContext->PeCoffHeaderOffset + + sizeof(UINT32) + + sizeof(EFI_IMAGE_FILE_HEADER) + + PeHdr->Pe32.FileHeader.SizeOfOptionalHeader + ); + NumberOfSections = (UINTN) (PeHdr->Pe32.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->Pe32.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->Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) { + if (OptionHeader.Optional32->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) { + DirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *) + &OptionHeader.Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC]; + ImageContext->FixupDataSize = DirectoryEntry->Size / sizeof (UINT16) * sizeof (UINTN); + } else { + ImageContext->FixupDataSize = 0; + } + } else { + if (OptionHeader.Optional64->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) { + DirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *) + &OptionHeader.Optional64->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; +} + +/** + Returns a pointer to the PDB file name for a raw PE/COFF image that is not + loaded into system memory with the PE/COFF Loader Library functions. + + Returns the PDB file name for the PE/COFF image specified by Pe32Data. If + the PE/COFF image specified by Pe32Data is not a valid, then NULL is + returned. If the PE/COFF image specified by Pe32Data does not contain a + debug directory entry, then NULL is returned. If the debug directory entry + in the PE/COFF image specified by Pe32Data does not contain a PDB file name, + then NULL is returned. + If Pe32Data is NULL, then return NULL. + + @param Pe32Data Pointer to the PE/COFF image that is loaded in system + memory. + + @return The PDB file name for the PE/COFF image specified by Pe32Data or NULL + if it cannot be retrieved. + +**/ +VOID * +EFIAPI +PeCoffLoaderGetPdbPointer ( + IN VOID *Pe32Data + ) +{ + EFI_IMAGE_DOS_HEADER *DosHdr; + EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr; + EFI_IMAGE_DATA_DIRECTORY *DirectoryEntry; + EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *DebugEntry; + UINTN DirCount; + VOID *CodeViewEntryPointer; + INTN TEImageAdjust; + UINT32 NumberOfRvaAndSizes; + UINT16 Magic; + EFI_IMAGE_SECTION_HEADER *SectionHeader; + UINT32 Index, Index1; + + if (Pe32Data == NULL) { + return NULL; + } + + TEImageAdjust = 0; + DirectoryEntry = NULL; + DebugEntry = NULL; + NumberOfRvaAndSizes = 0; + Index = 0; + Index1 = 0; + SectionHeader = NULL; + + DosHdr = (EFI_IMAGE_DOS_HEADER *)Pe32Data; + if (EFI_IMAGE_DOS_SIGNATURE == DosHdr->e_magic) { + // + // DOS image header is present, so read the PE header after the DOS image header. + // + Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)((UINTN) Pe32Data + (UINTN) ((DosHdr->e_lfanew) & 0x0ffff)); + } else { + // + // DOS image header is not present, so PE header is at the image base. + // + Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)Pe32Data; + } + + if (EFI_TE_IMAGE_HEADER_SIGNATURE == Hdr.Te->Signature) { + if (Hdr.Te->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress != 0) { + DirectoryEntry = &Hdr.Te->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG]; + TEImageAdjust = sizeof (EFI_TE_IMAGE_HEADER) - Hdr.Te->StrippedSize; + + // + // Get the DebugEntry offset in the raw data image. + // + SectionHeader = (EFI_IMAGE_SECTION_HEADER *) (Hdr.Te + 1); + Index = Hdr.Te->NumberOfSections; + for (Index1 = 0; Index1 < Index; Index1 ++) { + if ((DirectoryEntry->VirtualAddress >= SectionHeader[Index1].VirtualAddress) && + (DirectoryEntry->VirtualAddress < (SectionHeader[Index1].VirtualAddress + SectionHeader[Index1].Misc.VirtualSize))) { + DebugEntry = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *)((UINTN) Hdr.Te + + DirectoryEntry->VirtualAddress - + SectionHeader [Index1].VirtualAddress + + SectionHeader [Index1].PointerToRawData + + TEImageAdjust); + break; + } + } + } + } else if (EFI_IMAGE_NT_SIGNATURE == Hdr.Pe32->Signature) { + // + // NOTE: We use Machine field to identify PE32/PE32+, instead of Magic. + // It is due to backward-compatibility, for some system might + // generate PE32+ image with PE32 Magic. + // + switch (Hdr.Pe32->FileHeader.Machine) { + case EFI_IMAGE_MACHINE_IA32: + case EFI_IMAGE_MACHINE_ARMT: + // + // Assume PE32 image with IA32 Machine field. + // + Magic = EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC; + break; + case EFI_IMAGE_MACHINE_X64: + case EFI_IMAGE_MACHINE_IPF: + // + // Assume PE32+ image with X64 or IPF Machine field + // + Magic = EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC; + break; + default: + // + // For unknow Machine field, use Magic in optional Header + // + Magic = Hdr.Pe32->OptionalHeader.Magic; + } + + SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ( + (UINT8 *) Hdr.Pe32 + + sizeof (UINT32) + + sizeof (EFI_IMAGE_FILE_HEADER) + + Hdr.Pe32->FileHeader.SizeOfOptionalHeader + ); + Index = Hdr.Pe32->FileHeader.NumberOfSections; + + if (EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC == Magic) { + // + // Use PE32 offset get Debug Directory Entry + // + NumberOfRvaAndSizes = Hdr.Pe32->OptionalHeader.NumberOfRvaAndSizes; + DirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *)&(Hdr.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG]); + } else if (Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) { + // + // Use PE32+ offset get Debug Directory Entry + // + NumberOfRvaAndSizes = Hdr.Pe32Plus->OptionalHeader.NumberOfRvaAndSizes; + DirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *)&(Hdr.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG]); + } + + if (NumberOfRvaAndSizes <= EFI_IMAGE_DIRECTORY_ENTRY_DEBUG || DirectoryEntry->VirtualAddress == 0) { + DirectoryEntry = NULL; + DebugEntry = NULL; + } else { + // + // Get the DebugEntry offset in the raw data image. + // + for (Index1 = 0; Index1 < Index; Index1 ++) { + if ((DirectoryEntry->VirtualAddress >= SectionHeader[Index1].VirtualAddress) && + (DirectoryEntry->VirtualAddress < (SectionHeader[Index1].VirtualAddress + SectionHeader[Index1].Misc.VirtualSize))) { + DebugEntry = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *) ( + (UINTN) Pe32Data + + DirectoryEntry->VirtualAddress - + SectionHeader[Index1].VirtualAddress + + SectionHeader[Index1].PointerToRawData); + break; + } + } + } + } else { + return NULL; + } + + if (NULL == DebugEntry || NULL == DirectoryEntry) { + return NULL; + } + + // + // Scan the directory to find the debug entry. + // + for (DirCount = 0; DirCount < DirectoryEntry->Size; DirCount += sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY), DebugEntry++) { + if (EFI_IMAGE_DEBUG_TYPE_CODEVIEW == DebugEntry->Type) { + if (DebugEntry->SizeOfData > 0) { + // + // Get the DebugEntry offset in the raw data image. + // + for (Index1 = 0; Index1 < Index; Index1 ++) { + if ((DebugEntry->RVA >= SectionHeader[Index1].VirtualAddress) && + (DebugEntry->RVA < (SectionHeader[Index1].VirtualAddress + SectionHeader[Index1].Misc.VirtualSize))) { + CodeViewEntryPointer = (VOID *) ( + ((UINTN)Pe32Data) + + (UINTN) DebugEntry->RVA - + SectionHeader[Index1].VirtualAddress + + SectionHeader[Index1].PointerToRawData + + (UINTN)TEImageAdjust); + break; + } + } + if (Index1 >= Index) { + // + // Can't find CodeViewEntryPointer in raw PE/COFF image. + // + continue; + } + switch (* (UINT32 *) CodeViewEntryPointer) { + case CODEVIEW_SIGNATURE_NB10: + return (VOID *) ((CHAR8 *)CodeViewEntryPointer + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY)); + case CODEVIEW_SIGNATURE_RSDS: + return (VOID *) ((CHAR8 *)CodeViewEntryPointer + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY)); + default: + break; + } + } + } + } + + return NULL; +} diff --git a/BaseTools/Source/C/Common/BinderFuncs.c b/BaseTools/Source/C/Common/BinderFuncs.c new file mode 100644 index 0000000000..89e75efa3d --- /dev/null +++ b/BaseTools/Source/C/Common/BinderFuncs.c @@ -0,0 +1,87 @@ +/** @file + +Copyright (c) 1999 - 2008, 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: + + BinderFuncs.c + +Abstract: + + Binder function implementations for ANSI C libraries. + +**/ + +#include "BinderFuncs.h" +#include "CommonLib.h" +#include +#include + +// +// Binder Function Implementations +// + +VOID * +CommonLibBinderAllocate ( + IN UINTN Size + ) +{ + return (VOID *) malloc (Size); +} + +VOID +CommonLibBinderFree ( + IN VOID *Pointer + ) +{ + free (Pointer); +} + +VOID +CommonLibBinderCopyMem ( + IN VOID *Destination, + IN VOID *Source, + IN UINTN Length + ) +{ + memmove (Destination, Source, Length); +} + +VOID +CommonLibBinderSetMem ( + IN VOID *Destination, + IN UINTN Length, + IN UINT8 Value + ) +{ + memset (Destination, Value, Length); +} + +INTN +CommonLibBinderCompareMem ( + IN VOID *MemOne, + IN VOID *MemTwo, + IN UINTN Length + ) +{ + return memcmp (MemOne, MemTwo, Length); +} + +BOOLEAN +CommonLibBinderCompareGuid ( + IN EFI_GUID *Guid1, + IN EFI_GUID *Guid2 + ) +{ + return CompareGuid (Guid1, Guid2) ? FALSE : TRUE; +} + + + diff --git a/BaseTools/Source/C/Common/BinderFuncs.h b/BaseTools/Source/C/Common/BinderFuncs.h new file mode 100644 index 0000000000..779c5a2e06 --- /dev/null +++ b/BaseTools/Source/C/Common/BinderFuncs.h @@ -0,0 +1,75 @@ +/** @file + +Copyright (c) 1999 - 2008, 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: + + BinderFuncs.h + +Abstract: + + Prototypes for binder functions that allow common code to be + written which then links to implementation of these functions + which is appropriate for the specific environment that they + are running under. + +**/ + +#ifndef BinderFuncs_h_INCLUDED +#define BinderFuncs_h_INCLUDED + +#include "Common/UefiBaseTypes.h" + +// +// Binder Function Prototypes +// +// These binding functions must be implemented externally as appropriate for +// the environment that the code will be running under. +// + +VOID * +CommonLibBinderAllocate ( + IN UINTN Size + ); + +VOID +CommonLibBinderFree ( + IN VOID *Pointer + ); + +VOID +CommonLibBinderCopyMem ( + IN VOID *Destination, + IN VOID *Source, + IN UINTN Length + ); + +VOID +CommonLibBinderSetMem ( + IN VOID *Destination, + IN UINTN Length, + IN UINT8 Value + ); + +INTN +CommonLibBinderCompareMem ( + IN VOID *MemOne, + IN VOID *MemTwo, + IN UINTN Length + ); + +BOOLEAN +CommonLibBinderCompareGuid ( + IN EFI_GUID *Guid1, + IN EFI_GUID *Guid2 + ); + +#endif // #ifndef CommonLibs_h_INCLUDED + diff --git a/BaseTools/Source/C/Common/CommonLib.c b/BaseTools/Source/C/Common/CommonLib.c new file mode 100644 index 0000000000..970b2af27b --- /dev/null +++ b/BaseTools/Source/C/Common/CommonLib.c @@ -0,0 +1,584 @@ +/** @file + +Copyright (c) 2004 - 2008, 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 basic Library Functions + +**/ + +#include +#include +#include +#include +#include "CommonLib.h" +#include "EfiUtilityMsgs.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) { + Error (NULL, 0, 0001, "Error opening the input file", InputFileName); + return EFI_ABORTED; + } + // + // Go to the end so that we can determine the file size + // + if (fseek (InputFile, 0, SEEK_END)) { + Error (NULL, 0, 0004, "Error reading the input file", InputFileName); + fclose (InputFile); + return EFI_ABORTED; + } + // + // Get the file size + // + FileSize = ftell (InputFile); + if (FileSize == -1) { + Error (NULL, 0, 0003, "Error parsing the input file", 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)) { + Error (NULL, 0, 0004, "Error reading the input file", 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) { + Error (NULL, 0, 0004, "Error reading the input file", InputFileName); + fclose (InputFile); + free (*InputFileImage); + *InputFileImage = NULL; + return EFI_ABORTED; + } + // + // Close the file + // + fclose (InputFile); + + return EFI_SUCCESS; +} + +EFI_STATUS +PutFileImage ( + IN CHAR8 *OutputFileName, + IN CHAR8 *OutputFileImage, + IN UINT32 BytesToWrite + ) +/*++ + +Routine Description: + + This function opens a file and writes OutputFileImage into the file. + +Arguments: + + OutputFileName The name of the file to write. + OutputFileImage A pointer to the memory buffer. + BytesToWrite 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 *OutputFile; + UINT32 BytesWrote; + + // + // Verify input parameters. + // + if (OutputFileName == NULL || strlen (OutputFileName) == 0 || OutputFileImage == NULL) { + return EFI_INVALID_PARAMETER; + } + // + // Open the file and copy contents into a memory buffer. + // + // + // Open the file + // + OutputFile = fopen (OutputFileName, "wb"); + if (OutputFile == NULL) { + Error (NULL, 0, 0001, "Error opening the output file", OutputFileName); + return EFI_ABORTED; + } + + // + // Write all of the file contents. + // + BytesWrote = fwrite (OutputFileImage, sizeof (UINT8), BytesToWrite, OutputFile); + if (BytesWrote != sizeof (UINT8) * BytesToWrite) { + Error (NULL, 0, 0002, "Error writing the output file", OutputFileName); + fclose (OutputFile); + return EFI_ABORTED; + } + // + // Close the file + // + fclose (OutputFile); + + 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) { + Error (NULL, 0, 2000, "Invalid parameter", "PrintGuidToBuffer() called with a NULL value"); + 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) { + Error (NULL, 0, 2000, "Invalid parameter", "PrintGuidToBuffer() called with a NULL value"); + return EFI_INVALID_PARAMETER; + } + + if (BufferLen < PRINTED_GUID_BUFFER_SIZE) { + Error (NULL, 0, 2000, "Invalid parameter", "PrintGuidToBuffer() called with invalid buffer size"); + return EFI_BUFFER_TOO_SMALL; + } + + if (Uppercase) { + sprintf ( + (CHAR8 *)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 ( + (CHAR8 *)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(int fd) +{ + struct stat stat_buf; + fstat(fd, &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/BaseTools/Source/C/Common/CommonLib.h b/BaseTools/Source/C/Common/CommonLib.h new file mode 100644 index 0000000000..7e4af036e5 --- /dev/null +++ b/BaseTools/Source/C/Common/CommonLib.h @@ -0,0 +1,172 @@ +/** @file + +Copyright (c) 2004 - 2008, 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 +#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 + ) +; + +EFI_STATUS +PutFileImage ( + IN CHAR8 *OutputFileName, + IN CHAR8 *OutputFileImage, + IN UINT32 BytesToWrite + ) +; +/*++ + +Routine Description: + + This function opens a file and writes OutputFileImage into the file. + +Arguments: + + OutputFileName The name of the file to write. + OutputFileImage A pointer to the memory buffer. + BytesToWrite 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. + +**/ + +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 +#include +#define stricmp strcasecmp +#define _stricmp strcasecmp +#define strnicmp strncasecmp +#define strcmpi strcasecmp +size_t _filelength(int fd); +#ifndef __CYGWIN__ +char *strlwr(char *s); +#endif +#endif + +// +// On windows, mkdir only has one parameter. +// On unix, it has two parameters +// +#if defined(__GNUC__) +#define mkdir(dir, perm) mkdir(dir, perm) +#else +#define mkdir(dir, perm) mkdir(dir) +#endif + +#endif diff --git a/BaseTools/Source/C/Common/Compress.h b/BaseTools/Source/C/Common/Compress.h new file mode 100644 index 0000000000..10d0c72a16 --- /dev/null +++ b/BaseTools/Source/C/Common/Compress.h @@ -0,0 +1,95 @@ +/** @file + +Copyright (c) 2004 - 2008, 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: + + Compress.h + +Abstract: + + Header file for compression routine. + Providing both EFI and Tiano Compress algorithms. + +**/ + +#ifndef _COMPRESS_H_ +#define _COMPRESS_H_ + +#include +#include + +#include "CommonLib.h" +#include +/*++ + +Routine Description: + + Tiano compression routine. + +--*/ +EFI_STATUS +TianoCompress ( + IN UINT8 *SrcBuffer, + IN UINT32 SrcSize, + IN UINT8 *DstBuffer, + IN OUT UINT32 *DstSize + ) +; + +/*++ + +Routine Description: + + Efi compression routine. + +--*/ +EFI_STATUS +EfiCompress ( + 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. + EFI_OUT_OF_RESOURCES - No resource to complete function. + EFI_INVALID_PARAMETER - Parameter supplied is wrong. + +--*/ +typedef +EFI_STATUS +(*COMPRESS_FUNCTION) ( + IN UINT8 *SrcBuffer, + IN UINT32 SrcSize, + IN UINT8 *DstBuffer, + IN OUT UINT32 *DstSize + ); + +#endif diff --git a/BaseTools/Source/C/Common/Crc32.c b/BaseTools/Source/C/Common/Crc32.c new file mode 100644 index 0000000000..f52b51453a --- /dev/null +++ b/BaseTools/Source/C/Common/Crc32.c @@ -0,0 +1,326 @@ +/** @file + +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 +#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/BaseTools/Source/C/Common/Crc32.h b/BaseTools/Source/C/Common/Crc32.h new file mode 100644 index 0000000000..e598a916a0 --- /dev/null +++ b/BaseTools/Source/C/Common/Crc32.h @@ -0,0 +1,54 @@ +/** @file + +Copyright (c) 2004 - 2008, 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 + +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/BaseTools/Source/C/Common/Decompress.c b/BaseTools/Source/C/Common/Decompress.c new file mode 100644 index 0000000000..8ccb21f211 --- /dev/null +++ b/BaseTools/Source/C/Common/Decompress.c @@ -0,0 +1,982 @@ +/** @file + +Copyright (c) 2004 - 2008, 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: + + Decompress.c + +Abstract: + + Decompressor. Algorithm Ported from OPSD code (Decomp.asm) + for Efi and Tiano compress algorithm. + +--*/ + +#include +#include +#include "Decompress.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 EFIPBIT 4 +#define MAXPBIT 5 +#define TBIT 5 +#define MAXNP ((1U << MAXPBIT) - 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 UINT16 mPbit = EFIPBIT; + +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++; + } + + 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, mPbit, (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 Efi and Tiano Decompress(). + +Arguments: + + 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; +} + +EFI_STATUS +EfiGetInfo ( + IN VOID *Source, + IN UINT32 SrcSize, + OUT UINT32 *DstSize, + OUT UINT32 *ScratchSize + ) +/*++ + +Routine Description: + + The implementation Efi Decompress 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 + +--*/ +{ + return GetInfo (Source, SrcSize, DstSize, ScratchSize); +} + +EFI_STATUS +TianoGetInfo ( + IN VOID *Source, + IN UINT32 SrcSize, + OUT UINT32 *DstSize, + OUT UINT32 *ScratchSize + ) +/*++ + +Routine Description: + + The implementation Tiano Decompress 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 + +--*/ +{ + return GetInfo (Source, SrcSize, DstSize, ScratchSize); +} + +EFI_STATUS +EfiDecompress ( + 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(). + +Arguments: + + 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 + +--*/ +{ + mPbit = EFIPBIT; + return Decompress (Source, SrcSize, Destination, DstSize, Scratch, ScratchSize); +} + +EFI_STATUS +TianoDecompress ( + 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 Tiano Decompress(). + +Arguments: + + 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 + +--*/ +{ + mPbit = MAXPBIT; + return Decompress (Source, SrcSize, Destination, DstSize, Scratch, ScratchSize); +} + +EFI_STATUS +Extract ( + IN VOID *Source, + IN UINT32 SrcSize, + OUT VOID **Destination, + OUT UINT32 *DstSize, + IN UINTN Algorithm + ) +{ + VOID *Scratch; + UINT32 ScratchSize; + EFI_STATUS Status; + + Status = EFI_SUCCESS; + switch (Algorithm) { + case 0: + *Destination = (VOID *)malloc(SrcSize); + if (*Destination != NULL) { + memcpy(*Destination, Source, SrcSize); + } else { + Status = EFI_OUT_OF_RESOURCES; + } + break; + case 1: + Status = EfiGetInfo(Source, SrcSize, DstSize, &ScratchSize); + if (Status == EFI_SUCCESS) { + Scratch = (VOID *)malloc(ScratchSize); + *Destination = (VOID *)malloc(*DstSize); + if (Scratch != NULL && *Destination != NULL) { + Status = EfiDecompress(Source, SrcSize, *Destination, *DstSize, Scratch, ScratchSize); + } else { + Status = EFI_OUT_OF_RESOURCES; + } + } + break; + case 2: + Status = TianoGetInfo(Source, SrcSize, DstSize, &ScratchSize); + if (Status == EFI_SUCCESS) { + Scratch = (VOID *)malloc(ScratchSize); + *Destination = (VOID *)malloc(*DstSize); + if (Scratch != NULL && *Destination != NULL) { + Status = TianoDecompress(Source, SrcSize, *Destination, *DstSize, Scratch, ScratchSize); + } else { + Status = EFI_OUT_OF_RESOURCES; + } + } + break; + default: + Status = EFI_INVALID_PARAMETER; + } + + return Status; +} + + diff --git a/BaseTools/Source/C/Common/Decompress.h b/BaseTools/Source/C/Common/Decompress.h new file mode 100644 index 0000000000..3d5c0cd54d --- /dev/null +++ b/BaseTools/Source/C/Common/Decompress.h @@ -0,0 +1,172 @@ +/** @file + +Copyright (c) 2006 - 2008, 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: + + Decompress.h + +Abstract: + + Header file for compression routine + +**/ + +#ifndef _EFI_DECOMPRESS_H +#define _EFI_DECOMPRESS_H + +#include + +EFI_STATUS +EfiGetInfo ( + IN VOID *Source, + IN UINT32 SrcSize, + OUT UINT32 *DstSize, + OUT UINT32 *ScratchSize + ); +/** + +Routine Description: + + The implementation Efi Decompress 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 +EfiDecompress ( + 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(). + +Arguments: + + 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 +TianoGetInfo ( + IN VOID *Source, + IN UINT32 SrcSize, + OUT UINT32 *DstSize, + OUT UINT32 *ScratchSize + ); +/** + +Routine Description: + + The implementation Tiano Decompress 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 +TianoDecompress ( + 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 Tiano Decompress(). + +Arguments: + + 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 + ); + +EFI_STATUS +Extract ( + IN VOID *Source, + IN UINT32 SrcSize, + OUT VOID **Destination, + OUT UINT32 *DstSize, + IN UINTN Algorithm + ); + +#endif diff --git a/BaseTools/Source/C/Common/EfiCompress.c b/BaseTools/Source/C/Common/EfiCompress.c new file mode 100644 index 0000000000..aafa9c6e24 --- /dev/null +++ b/BaseTools/Source/C/Common/EfiCompress.c @@ -0,0 +1,1598 @@ +/** @file + +Copyright (c) 2006 - 2008, 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 "Compress.h" + + +// +// Macro Definitions +// + +#undef UINT8_MAX +typedef INT16 NODE; +#define UINT8_MAX 0xff +#define UINT8_BIT 8 +#define THRESHOLD 3 +#define INIT_CRC 0 +#define WNDBIT 13 +#define WNDSIZ (1U << WNDBIT) +#define MAXMATCH 256 +#define PERC_FLAG 0x8000U +#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 4 +#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 ( + ); + +STATIC +VOID +FreeMemory ( + ); + +STATIC +VOID +InitSlide ( + ); + +STATIC +NODE +Child ( + IN NODE q, + IN UINT8 c + ); + +STATIC +VOID +MakeChild ( + IN NODE q, + IN UINT8 c, + IN NODE r + ); + +STATIC +VOID +Split ( + IN NODE Old + ); + +STATIC +VOID +InsertNode ( + ); + +STATIC +VOID +DeleteNode ( + ); + +STATIC +VOID +GetNextMatch ( + ); + +STATIC +EFI_STATUS +Encode ( + ); + +STATIC +VOID +CountTFreq ( + ); + +STATIC +VOID +WritePTLen ( + IN INT32 n, + IN INT32 nbit, + IN INT32 Special + ); + +STATIC +VOID +WriteCLen ( + ); + +STATIC +VOID +EncodeC ( + IN INT32 c + ); + +STATIC +VOID +EncodeP ( + IN UINT32 p + ); + +STATIC +VOID +SendBlock ( + ); + +STATIC +VOID +Output ( + IN UINT32 c, + IN UINT32 p + ); + +STATIC +VOID +HufEncodeStart ( + ); + +STATIC +VOID +HufEncodeEnd ( + ); + +STATIC +VOID +MakeCrcTable ( + ); + +STATIC +VOID +PutBits ( + IN INT32 n, + IN UINT32 x + ); + +STATIC +INT32 +FreadCrc ( + OUT UINT8 *p, + IN INT32 n + ); + +STATIC +VOID +InitPutBits ( + ); + +STATIC +VOID +CountLen ( + IN INT32 i + ); + +STATIC +VOID +MakeLen ( + IN INT32 Root + ); + +STATIC +VOID +DownHeap ( + IN INT32 i + ); + +STATIC +VOID +MakeCode ( + IN INT32 n, + 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],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 +EfiCompress ( + 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_STATUS Status = EFI_SUCCESS; + + // + // 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 () +/*++ + +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 i; + + mText = malloc (WNDSIZ * 2 + MAXMATCH); + for (i = 0 ; i < WNDSIZ * 2 + MAXMATCH; i ++) { + mText[i] = 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 = 16 * 1024U; + while ((mBuf = malloc(mBufSiz)) == NULL) { + mBufSiz = (mBufSiz / 10U) * 9U; + if (mBufSiz < 4 * 1024U) { + return EFI_OUT_OF_RESOURCES; + } + } + mBuf[0] = 0; + + return EFI_SUCCESS; +} + +VOID +FreeMemory () +/*++ + +Routine Description: + + Called when compression is completed to free memory previously allocated. + +Arguments: (VOID) + +Returns: (VOID) + +--*/ +{ + if (mText) { + free (mText); + } + + if (mLevel) { + free (mLevel); + } + + if (mChildCount) { + free (mChildCount); + } + + if (mPosition) { + free (mPosition); + } + + if (mParent) { + free (mParent); + } + + if (mPrev) { + free (mPrev); + } + + if (mNext) { + free (mNext); + } + + if (mBuf) { + free (mBuf); + } + + return; +} + + +STATIC +VOID +InitSlide () +/*++ + +Routine Description: + + Initialize String Info Log data structures + +Arguments: (VOID) + +Returns: (VOID) + +--*/ +{ + NODE i; + + for (i = WNDSIZ; i <= WNDSIZ + UINT8_MAX; i++) { + mLevel[i] = 1; + mPosition[i] = NIL; /* sentinel */ + } + for (i = WNDSIZ; i < WNDSIZ * 2; i++) { + mParent[i] = NIL; + } + mAvail = 1; + for (i = 1; i < WNDSIZ - 1; i++) { + mNext[i] = (NODE)(i + 1); + } + + mNext[WNDSIZ - 1] = NIL; + for (i = WNDSIZ * 2; i <= MAX_HASH_VAL; i++) { + mNext[i] = NIL; + } +} + + +STATIC +NODE +Child ( + IN NODE q, + IN UINT8 c + ) +/*++ + +Routine Description: + + Find child node given the parent node and the edge character + +Arguments: + + q - the parent node + c - the edge character + +Returns: + + The child node (NIL if not found) + +--*/ +{ + NODE r; + + r = mNext[HASH(q, c)]; + mParent[NIL] = q; /* sentinel */ + while (mParent[r] != q) { + r = mNext[r]; + } + + return r; +} + +STATIC +VOID +MakeChild ( + IN NODE q, + IN UINT8 c, + IN NODE r + ) +/*++ + +Routine Description: + + Create a new child for a given parent node. + +Arguments: + + q - the parent node + c - the edge character + r - the child node + +Returns: (VOID) + +--*/ +{ + NODE h, t; + + h = (NODE)HASH(q, c); + t = mNext[h]; + mNext[h] = r; + mNext[r] = t; + mPrev[t] = r; + mPrev[r] = h; + mParent[r] = q; + mChildCount[q]++; +} + +STATIC +VOID +Split ( + NODE Old + ) +/*++ + +Routine Description: + + Split a node. + +Arguments: + + Old - the node to split + +Returns: (VOID) + +--*/ +{ + NODE New, t; + + New = mAvail; + mAvail = mNext[New]; + mChildCount[New] = 0; + t = mPrev[Old]; + mPrev[New] = t; + mNext[t] = New; + t = mNext[Old]; + mNext[New] = t; + mPrev[t] = 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 () +/*++ + +Routine Description: + + Insert string info for current position into the String Info Log + +Arguments: (VOID) + +Returns: (VOID) + +--*/ +{ + NODE q, r, j, t; + UINT8 c, *t1, *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--; + r = (INT16)((mMatchPos + 1) | WNDSIZ); + while ((q = mParent[r]) == NIL) { + r = mNext[r]; + } + while (mLevel[q] >= mMatchLen) { + r = q; q = mParent[q]; + } + t = q; + while (mPosition[t] < 0) { + mPosition[t] = mPos; + t = mParent[t]; + } + if (t < WNDSIZ) { + mPosition[t] = (NODE)(mPos | PERC_FLAG); + } + } else { + + // + // Locate the target tree + // + + q = (INT16)(mText[mPos] + WNDSIZ); + c = mText[mPos + 1]; + if ((r = Child(q, c)) == NIL) { + MakeChild(q, c, 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 (r >= WNDSIZ) { + j = MAXMATCH; + mMatchPos = r; + } else { + j = mLevel[r]; + mMatchPos = (NODE)(mPosition[r] & ~PERC_FLAG); + } + if (mMatchPos >= mPos) { + mMatchPos -= WNDSIZ; + } + t1 = &mText[mPos + mMatchLen]; + t2 = &mText[mMatchPos + mMatchLen]; + while (mMatchLen < j) { + if (*t1 != *t2) { + Split(r); + return; + } + mMatchLen++; + t1++; + t2++; + } + if (mMatchLen >= MAXMATCH) { + break; + } + mPosition[r] = mPos; + q = r; + if ((r = Child(q, *t1)) == NIL) { + MakeChild(q, *t1, mPos); + return; + } + mMatchLen++; + } + t = mPrev[r]; + mPrev[mPos] = t; + mNext[t] = mPos; + t = mNext[r]; + mNext[mPos] = t; + mPrev[t] = mPos; + mParent[mPos] = q; + mParent[r] = NIL; + + // + // Special usage of 'next' + // + mNext[r] = mPos; + +} + +STATIC +VOID +DeleteNode () +/*++ + +Routine Description: + + Delete outdated string info. (The Usage of PERC_FLAG + ensures a clean deletion) + +Arguments: (VOID) + +Returns: (VOID) + +--*/ +{ + NODE q, r, s, t, u; + + if (mParent[mPos] == NIL) { + return; + } + + r = mPrev[mPos]; + s = mNext[mPos]; + mNext[r] = s; + mPrev[s] = r; + r = mParent[mPos]; + mParent[mPos] = NIL; + if (r >= WNDSIZ || --mChildCount[r] > 1) { + return; + } + t = (NODE)(mPosition[r] & ~PERC_FLAG); + if (t >= mPos) { + t -= WNDSIZ; + } + s = t; + q = mParent[r]; + while ((u = mPosition[q]) & PERC_FLAG) { + u &= ~PERC_FLAG; + if (u >= mPos) { + u -= WNDSIZ; + } + if (u > s) { + s = u; + } + mPosition[q] = (INT16)(s | WNDSIZ); + q = mParent[q]; + } + if (q < WNDSIZ) { + if (u >= mPos) { + u -= WNDSIZ; + } + if (u > s) { + s = u; + } + mPosition[q] = (INT16)(s | WNDSIZ | PERC_FLAG); + } + s = Child(r, mText[t + mLevel[r]]); + t = mPrev[s]; + u = mNext[s]; + mNext[t] = u; + mPrev[u] = t; + t = mPrev[r]; + mNext[t] = s; + mPrev[s] = t; + t = mNext[r]; + mPrev[t] = s; + mNext[s] = t; + mParent[s] = mParent[r]; + mParent[r] = NIL; + mNext[r] = mAvail; + mAvail = r; +} + +STATIC +VOID +GetNextMatch () +/*++ + +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 n; + + mRemainder--; + if (++mPos == WNDSIZ * 2) { + memmove(&mText[0], &mText[WNDSIZ], WNDSIZ + MAXMATCH); + n = FreadCrc(&mText[WNDSIZ + MAXMATCH], WNDSIZ); + mRemainder += n; + mPos = WNDSIZ; + } + DeleteNode(); + InsertNode(); +} + +STATIC +EFI_STATUS +Encode () +/*++ + +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 { + + // + // Outputting a pointer is beneficial enough, do it. + // + + Output(LastMatchLen + (UINT8_MAX + 1 - THRESHOLD), + (mPos - LastMatchPos - 2) & (WNDSIZ - 1)); + while (--LastMatchLen > 0) { + GetNextMatch(); + } + if (mMatchLen > mRemainder) { + mMatchLen = mRemainder; + } + } + } + + HufEncodeEnd(); + FreeMemory(); + return EFI_SUCCESS; +} + +STATIC +VOID +CountTFreq () +/*++ + +Routine Description: + + Count the frequencies for the Extra Set + +Arguments: (VOID) + +Returns: (VOID) + +--*/ +{ + INT32 i, k, n, Count; + + for (i = 0; i < NT; i++) { + mTFreq[i] = 0; + } + n = NC; + while (n > 0 && mCLen[n - 1] == 0) { + n--; + } + i = 0; + while (i < n) { + k = mCLen[i++]; + if (k == 0) { + Count = 1; + while (i < n && mCLen[i] == 0) { + i++; + 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[k + 2]++; + } + } +} + +STATIC +VOID +WritePTLen ( + IN INT32 n, + IN INT32 nbit, + IN INT32 Special + ) +/*++ + +Routine Description: + + Outputs the code length array for the Extra Set or the Position Set. + +Arguments: + + n - 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 i, k; + + while (n > 0 && mPTLen[n - 1] == 0) { + n--; + } + PutBits(nbit, n); + i = 0; + while (i < n) { + k = mPTLen[i++]; + if (k <= 6) { + PutBits(3, k); + } else { + PutBits(k - 3, (1U << (k - 3)) - 2); + } + if (i == Special) { + while (i < 6 && mPTLen[i] == 0) { + i++; + } + PutBits(2, (i - 3) & 3); + } + } +} + +STATIC +VOID +WriteCLen () +/*++ + +Routine Description: + + Outputs the code length array for Char&Length Set + +Arguments: (VOID) + +Returns: (VOID) + +--*/ +{ + INT32 i, k, n, Count; + + n = NC; + while (n > 0 && mCLen[n - 1] == 0) { + n--; + } + PutBits(CBIT, n); + i = 0; + while (i < n) { + k = mCLen[i++]; + if (k == 0) { + Count = 1; + while (i < n && mCLen[i] == 0) { + i++; + Count++; + } + if (Count <= 2) { + for (k = 0; k < Count; k++) { + 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[k + 2], mPTCode[k + 2]); + } + } +} + +STATIC +VOID +EncodeC ( + IN INT32 c + ) +{ + PutBits(mCLen[c], mCCode[c]); +} + +STATIC +VOID +EncodeP ( + IN UINT32 p + ) +{ + UINT32 c, q; + + c = 0; + q = p; + while (q) { + q >>= 1; + c++; + } + PutBits(mPTLen[c], mPTCode[c]); + if (c > 1) { + PutBits(c - 1, p & (0xFFFFU >> (17 - c))); + } +} + +STATIC +VOID +SendBlock () +/*++ + +Routine Description: + + Huffman code the block and output it. + +Argument: (VOID) + +Returns: (VOID) + +--*/ +{ + UINT32 i, k, Flags, Root, Pos, 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 (i = 0; i < Size; i++) { + if (i % UINT8_BIT == 0) { + Flags = mBuf[Pos++]; + } else { + Flags <<= 1; + } + if (Flags & (1U << (UINT8_BIT - 1))) { + EncodeC(mBuf[Pos++] + (1U << UINT8_BIT)); + k = mBuf[Pos++] << UINT8_BIT; + k += mBuf[Pos++]; + EncodeP(k); + } else { + EncodeC(mBuf[Pos++]); + } + } + for (i = 0; i < NC; i++) { + mCFreq[i] = 0; + } + for (i = 0; i < NP; i++) { + mPFreq[i] = 0; + } +} + + +STATIC +VOID +Output ( + IN UINT32 c, + IN UINT32 p + ) +/*++ + +Routine Description: + + Outputs an Original Character or a Pointer + +Arguments: + + c - The original character or the 'String Length' element of a Pointer + p - The 'Position' field of a Pointer + +Returns: (VOID) + +--*/ +{ + STATIC UINT32 CPos; + + if ((mOutputMask >>= 1) == 0) { + mOutputMask = 1U << (UINT8_BIT - 1); + if (mOutputPos >= mBufSiz - 3 * UINT8_BIT) { + SendBlock(); + mOutputPos = 0; + } + CPos = mOutputPos++; + mBuf[CPos] = 0; + } + mBuf[mOutputPos++] = (UINT8) c; + mCFreq[c]++; + if (c >= (1U << UINT8_BIT)) { + mBuf[CPos] |= mOutputMask; + mBuf[mOutputPos++] = (UINT8)(p >> UINT8_BIT); + mBuf[mOutputPos++] = (UINT8) p; + c = 0; + while (p) { + p >>= 1; + c++; + } + mPFreq[c]++; + } +} + +STATIC +VOID +HufEncodeStart () +{ + INT32 i; + + for (i = 0; i < NC; i++) { + mCFreq[i] = 0; + } + for (i = 0; i < NP; i++) { + mPFreq[i] = 0; + } + mOutputPos = mOutputMask = 0; + InitPutBits(); + return; +} + +STATIC +VOID +HufEncodeEnd () +{ + SendBlock(); + + // + // Flush remaining bits + // + PutBits(UINT8_BIT - 1, 0); + + return; +} + + +STATIC +VOID +MakeCrcTable () +{ + UINT32 i, j, r; + + for (i = 0; i <= UINT8_MAX; i++) { + r = i; + for (j = 0; j < UINT8_BIT; j++) { + if (r & 1) { + r = (r >> 1) ^ CRCPOLY; + } else { + r >>= 1; + } + } + mCrcTable[i] = (UINT16)r; + } +} + +STATIC +VOID +PutBits ( + IN INT32 n, + IN UINT32 x + ) +/*++ + +Routine Description: + + Outputs rightmost n bits of x + +Argments: + + n - the rightmost n bits of the data is used + x - the data + +Returns: (VOID) + +--*/ +{ + UINT8 Temp; + + if (n < mBitCount) { + mSubBitBuf |= x << (mBitCount -= n); + } else { + + Temp = (UINT8)(mSubBitBuf | (x >> (n -= mBitCount))); + if (mDst < mDstUpperLimit) { + *mDst++ = Temp; + } + mCompSize++; + + if (n < UINT8_BIT) { + mSubBitBuf = x << (mBitCount = UINT8_BIT - n); + } else { + + Temp = (UINT8)(x >> (n - UINT8_BIT)); + if (mDst < mDstUpperLimit) { + *mDst++ = Temp; + } + mCompSize++; + + mSubBitBuf = x << (mBitCount = 2 * UINT8_BIT - n); + } + } +} + +STATIC +INT32 +FreadCrc ( + OUT UINT8 *p, + IN INT32 n + ) +/*++ + +Routine Description: + + Read in source data + +Arguments: + + p - the buffer to hold the data + n - number of bytes to read + +Returns: + + number of bytes actually read + +--*/ +{ + INT32 i; + + for (i = 0; mSrc < mSrcUpperLimit && i < n; i++) { + *p++ = *mSrc++; + } + n = i; + + p -= n; + mOrigSize += n; + while (--i >= 0) { + UPDATE_CRC(*p++); + } + return n; +} + + +STATIC +VOID +InitPutBits () +{ + mBitCount = UINT8_BIT; + mSubBitBuf = 0; +} + +STATIC +VOID +CountLen ( + IN INT32 i + ) +/*++ + +Routine Description: + + Count the number of each code length for a Huffman tree. + +Arguments: + + i - the top node + +Returns: (VOID) + +--*/ +{ + STATIC INT32 Depth = 0; + + if (i < mN) { + mLenCnt[(Depth < 16) ? Depth : 16]++; + } else { + Depth++; + CountLen(mLeft [i]); + CountLen(mRight[i]); + Depth--; + } +} + +STATIC +VOID +MakeLen ( + IN INT32 Root + ) +/*++ + +Routine Description: + + Create code length array for a Huffman tree + +Arguments: + + Root - the root of the tree + +--*/ +{ + INT32 i, k; + UINT32 Cum; + + for (i = 0; i <= 16; i++) { + mLenCnt[i] = 0; + } + CountLen(Root); + + // + // Adjust the length count array so that + // no code will be generated longer than its designated length + // + + Cum = 0; + for (i = 16; i > 0; i--) { + Cum += mLenCnt[i] << (16 - i); + } + while (Cum != (1U << 16)) { + mLenCnt[16]--; + for (i = 15; i > 0; i--) { + if (mLenCnt[i] != 0) { + mLenCnt[i]--; + mLenCnt[i+1] += 2; + break; + } + } + Cum--; + } + for (i = 16; i > 0; i--) { + k = mLenCnt[i]; + while (--k >= 0) { + mLen[*mSortPtr++] = (UINT8)i; + } + } +} + +STATIC +VOID +DownHeap ( + IN INT32 i + ) +{ + INT32 j, k; + + // + // priority queue: send i-th entry down heap + // + + k = mHeap[i]; + while ((j = 2 * i) <= mHeapSize) { + if (j < mHeapSize && mFreq[mHeap[j]] > mFreq[mHeap[j + 1]]) { + j++; + } + if (mFreq[k] <= mFreq[mHeap[j]]) { + break; + } + mHeap[i] = mHeap[j]; + i = j; + } + mHeap[i] = (INT16)k; +} + +STATIC +VOID +MakeCode ( + IN INT32 n, + IN UINT8 Len[], + OUT UINT16 Code[] + ) +/*++ + +Routine Description: + + Assign code to each symbol based on the code length array + +Arguments: + + n - number of symbols + Len - the code length array + Code - stores codes for each symbol + +Returns: (VOID) + +--*/ +{ + INT32 i; + UINT16 Start[18]; + + Start[1] = 0; + for (i = 1; i <= 16; i++) { + Start[i + 1] = (UINT16)((Start[i] + mLenCnt[i]) << 1); + } + for (i = 0; i < n; i++) { + Code[i] = Start[Len[i]]++; + } +} + +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 i, j, k, Avail; + + // + // make tree, calculate len[], return root + // + + mN = NParm; + mFreq = FreqParm; + mLen = LenParm; + Avail = mN; + mHeapSize = 0; + mHeap[1] = 0; + for (i = 0; i < mN; i++) { + mLen[i] = 0; + if (mFreq[i]) { + mHeap[++mHeapSize] = (INT16)i; + } + } + if (mHeapSize < 2) { + CodeParm[mHeap[1]] = 0; + return mHeap[1]; + } + for (i = mHeapSize / 2; i >= 1; i--) { + + // + // make priority queue + // + DownHeap(i); + } + mSortPtr = CodeParm; + do { + i = mHeap[1]; + if (i < mN) { + *mSortPtr++ = (UINT16)i; + } + mHeap[1] = mHeap[mHeapSize--]; + DownHeap(1); + j = mHeap[1]; + if (j < mN) { + *mSortPtr++ = (UINT16)j; + } + k = Avail++; + mFreq[k] = (UINT16)(mFreq[i] + mFreq[j]); + mHeap[1] = (INT16)k; + DownHeap(1); + mLeft[k] = (UINT16)i; + mRight[k] = (UINT16)j; + } while (mHeapSize > 1); + + mSortPtr = CodeParm; + MakeLen(k); + MakeCode(NParm, LenParm, CodeParm); + + // + // return root + // + return k; +} + diff --git a/BaseTools/Source/C/Common/EfiUtilityMsgs.c b/BaseTools/Source/C/Common/EfiUtilityMsgs.c new file mode 100644 index 0000000000..9d697da82d --- /dev/null +++ b/BaseTools/Source/C/Common/EfiUtilityMsgs.c @@ -0,0 +1,929 @@ +/** @file + +Copyright (c) 2004 - 2008, 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 +#include +#include +#include +#include + +#include "EfiUtilityMsgs.h" + +// +// 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 mPrintLogLevel = INFO_LOG_LEVEL; +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); + // + // Don't set warning 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; + + // + // Current Print Level not output warning information. + // + if (WARNING_LOG_LEVEL < mPrintLogLevel) { + return; + } + // + // 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); +} + +VOID +DebugMsg ( + CHAR8 *FileName, + UINT32 LineNumber, + UINT32 MsgLevel, + CHAR8 *Text, + CHAR8 *MsgFmt, + ... + ) +/*++ + +Routine Description: + Print a Debug 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) + + MsgLevel - Debug message print level (0~9) + + 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 level is less than current print level, then do nothing. + // + if (MsgLevel < mPrintLogLevel) { + 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: + () : : : + + 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; + struct tm *NewTime; + time_t CurrentTime; + + // + // init local variable + // + Line[0] = '\0'; + Line2[0] = '\0'; + + // + // 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 { + Cptr = NULL; + } + + if (strcmp (Type, "DEBUG") == 0) { + // + // Debug Message requires current time. + // + time (&CurrentTime); + NewTime = localtime (&CurrentTime); + fprintf (stdout, "%04d-%02d-%02d %02d:%02d:%02d", + NewTime->tm_year + 1900, + NewTime->tm_mon + 1, + NewTime->tm_mday, + NewTime->tm_hour, + NewTime->tm_min, + NewTime->tm_sec + ); + if (Cptr != NULL) { + sprintf (Line, ": %s", Cptr); + if (LineNumber != 0) { + sprintf (Line2, "(%d)", LineNumber); + strcat (Line, Line2); + } + } + } else { + // + // Error and Warning Information. + // + if (Cptr != NULL) { + if (mUtilityName[0] != '\0') { + fprintf (stdout, "%s...\n", mUtilityName); + } + sprintf (Line, "%s", Cptr); + if (LineNumber != 0) { + sprintf (Line2, "(%d)", LineNumber); + strcat (Line, Line2); + } + } else { + if (mUtilityName[0] != '\0') { + sprintf (Line, "%s", mUtilityName); + } + } + } + + // + // Have to print an error code or Visual Studio won't find the + // message for you. It has to be decimal digits too. + // + if (MessageCode != 0) { + sprintf (Line2, ": %s %04d", Type, MessageCode); + } else { + sprintf (Line2, ": %s", Type); + } + strcat (Line, Line2); + fprintf (stdout, "%s", Line); + // + // If offending text was provided, then print it + // + if (Text != NULL) { + fprintf (stdout, ": %s", Text); + } + fprintf (stdout, "\n"); + + // + // Print formatted message if provided + // + if (MsgFmt != NULL) { + vsprintf (Line2, MsgFmt, List); + fprintf (stdout, " %s\n", Line2); + } +} + +STATIC +VOID +PrintSimpleMessage ( + CHAR8 *MsgFmt, + va_list List + ) +/*++ +Routine Description: + Print message into stdout. + +Arguments: + MsgFmt - the format string for the message. Can contain formatting + controls for use with varargs. + List - the variable list. + +Returns: + None. +--*/ +{ + CHAR8 Line[MAX_LINE_LEN]; + // + // Print formatted message if provided + // + if (MsgFmt != NULL) { + vsprintf (Line, MsgFmt, List); + fprintf (stdout, "%s\n", Line); + } +} + +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 +SetPrintLevel ( + UINT32 LogLevel + ) +/*++ + +Routine Description: + Set the printing message Level. This is used by the PrintMsg() function + to determine when/if a message should be printed. + +Arguments: + LogLevel - 0~50 to specify the different level message. + +Returns: + NA + +--*/ +{ + mPrintLogLevel = LogLevel; +} + +VOID +VerboseMsg ( + CHAR8 *MsgFmt, + ... + ) +/*++ + +Routine Description: + Print a verbose level message. + +Arguments: + MsgFmt - the format string for the message. Can contain formatting + controls for use with varargs. + List - the variable list. + +Returns: + NA + +--*/ +{ + va_list List; + // + // If the debug level is less than current print level, then do nothing. + // + if (VERBOSE_LOG_LEVEL < mPrintLogLevel) { + return ; + } + + va_start (List, MsgFmt); + PrintSimpleMessage (MsgFmt, List); + va_end (List); +} + +VOID +NormalMsg ( + CHAR8 *MsgFmt, + ... + ) +/*++ + +Routine Description: + Print a default level message. + +Arguments: + MsgFmt - the format string for the message. Can contain formatting + controls for use with varargs. + List - the variable list. + +Returns: + NA + +--*/ +{ + va_list List; + // + // If the debug level is less than current print level, then do nothing. + // + if (INFO_LOG_LEVEL < mPrintLogLevel) { + return ; + } + + va_start (List, MsgFmt); + PrintSimpleMessage (MsgFmt, List); + va_end (List); +} + +VOID +KeyMsg ( + CHAR8 *MsgFmt, + ... + ) +/*++ + +Routine Description: + Print a key level message. + +Arguments: + MsgFmt - the format string for the message. Can contain formatting + controls for use with varargs. + List - the variable list. + +Returns: + NA + +--*/ +{ + va_list List; + // + // If the debug level is less than current print level, then do nothing. + // + if (KEY_LOG_LEVEL < mPrintLogLevel) { + return ; + } + + va_start (List, MsgFmt); + PrintSimpleMessage (MsgFmt, List); + va_end (List); +} + +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 + ) +{ + CHAR8 *ArgStr = "ArgString"; + INTN 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/BaseTools/Source/C/Common/EfiUtilityMsgs.h b/BaseTools/Source/C/Common/EfiUtilityMsgs.h new file mode 100644 index 0000000000..6c2f9d2989 --- /dev/null +++ b/BaseTools/Source/C/Common/EfiUtilityMsgs.h @@ -0,0 +1,166 @@ +/** @file + +Copyright (c) 2004 - 2008, 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 + +// +// Log message print Level +// +#define VERBOSE_LOG_LEVEL 15 +#define WARNING_LOG_LEVEL 15 +#define INFO_LOG_LEVEL 20 +#define KEY_LOG_LEVEL 40 +#define ERROR_LOG_LEVLE 50 + +// +// 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; + +#define MAX_LINE_LEN 0x200 +#define MAXIMUM_INPUT_FILE_NUM 10 + +#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 WarningCode, + CHAR8 *OffendingText, + CHAR8 *MsgFmt, + ... + ) +; + +VOID +DebugMsg ( + CHAR8 *FileName, + UINT32 LineNumber, + UINT32 MsgLevel, + CHAR8 *OffendingText, + CHAR8 *MsgFmt, + ... + ) +; + +VOID +VerboseMsg ( + CHAR8 *MsgFmt, + ... + ); + +VOID +NormalMsg ( + CHAR8 *MsgFmt, + ... + ); + +VOID +KeyMsg ( + CHAR8 *MsgFmt, + ... + ); + +VOID +SetPrintLevel ( + UINT32 LogLevel + ); + +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/BaseTools/Source/C/Common/FirmwareVolumeBuffer.c b/BaseTools/Source/C/Common/FirmwareVolumeBuffer.c new file mode 100644 index 0000000000..d51e359043 --- /dev/null +++ b/BaseTools/Source/C/Common/FirmwareVolumeBuffer.c @@ -0,0 +1,1667 @@ +/** @file + +Copyright (c) 1999 - 2008, 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: + + FirmwareVolumeBuffer.c + +Abstract: + + EFI Firmware Volume routines which work on a Fv image in buffers. + +**/ + +#include "FirmwareVolumeBufferLib.h" +#include "BinderFuncs.h" + +// +// Local macros +// +#define EFI_TEST_FFS_ATTRIBUTES_BIT(FvbAttributes, TestAttributes, Bit) \ + ( \ + (BOOLEAN) ( \ + (FvbAttributes & EFI_FVB2_ERASE_POLARITY) ? (((~TestAttributes) & Bit) == Bit) : ((TestAttributes & Bit) == Bit) \ + ) \ + ) + + +// +// Local prototypes +// + +STATIC +UINT16 +FvBufCalculateChecksum16 ( + IN UINT16 *Buffer, + IN UINTN Size + ); + +STATIC +UINT8 +FvBufCalculateChecksum8 ( + IN UINT8 *Buffer, + IN UINTN Size + ); + +// +// Procedures start +// + +EFI_STATUS +FvBufRemoveFileNew ( + IN OUT VOID *Fv, + IN EFI_GUID *Name + ) +/*++ + +Routine Description: + + Clears out all files from the Fv buffer in memory + +Arguments: + + SourceFv - Address of the Fv in memory, this firmware volume volume will + be modified, if SourceFfsFile exists + SourceFfsFile - Input FFS file to replace + +Returns: + + EFI_SUCCESS + EFI_NOT_FOUND + +--*/ +{ + EFI_STATUS Status; + EFI_FFS_FILE_HEADER* FileToRm; + UINTN FileToRmLength; + + Status = FvBufFindFileByName( + Fv, + Name, + (VOID **)&FileToRm + ); + if (EFI_ERROR (Status)) { + return Status; + } + + FileToRmLength = FvBufExpand3ByteSize (FileToRm->Size); + + CommonLibBinderSetMem ( + FileToRm, + FileToRmLength, + (((EFI_FIRMWARE_VOLUME_HEADER*)Fv)->Attributes & EFI_FVB2_ERASE_POLARITY) + ? 0xFF : 0 + ); + + return EFI_SUCCESS; +} + + +EFI_STATUS +FvBufRemoveFile ( + IN OUT VOID *Fv, + IN EFI_GUID *Name + ) +/*++ + +Routine Description: + + Clears out all files from the Fv buffer in memory + +Arguments: + + SourceFv - Address of the Fv in memory, this firmware volume volume will + be modified, if SourceFfsFile exists + SourceFfsFile - Input FFS file to replace + +Returns: + + EFI_SUCCESS + EFI_NOT_FOUND + +--*/ +{ + EFI_STATUS Status; + EFI_FFS_FILE_HEADER *NextFile; + EFI_FIRMWARE_VOLUME_HEADER *TempFv; + UINTN FileKey; + UINTN FvLength; + + Status = FvBufFindFileByName( + Fv, + Name, + NULL + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = FvBufGetSize (Fv, &FvLength); + if (EFI_ERROR (Status)) { + return Status; + } + + TempFv = NULL; + Status = FvBufDuplicate (Fv, (VOID **)&TempFv); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = FvBufClearAllFiles (TempFv); + if (EFI_ERROR (Status)) { + return Status; + } + + // TempFv has been allocated. It must now be freed + // before returning. + + FileKey = 0; + while (TRUE) { + + Status = FvBufFindNextFile (Fv, &FileKey, (VOID **)&NextFile); + if (Status == EFI_NOT_FOUND) { + break; + } else if (EFI_ERROR (Status)) { + CommonLibBinderFree (TempFv); + return Status; + } + + if (CommonLibBinderCompareGuid (Name, &NextFile->Name)) { + continue; + } + else { + Status = FvBufAddFile (TempFv, NextFile); + if (EFI_ERROR (Status)) { + CommonLibBinderFree (TempFv); + return Status; + } + } + } + + CommonLibBinderCopyMem (Fv, TempFv, FvLength); + CommonLibBinderFree (TempFv); + + return EFI_SUCCESS; +} + + +EFI_STATUS +FvBufChecksumFile ( + IN OUT VOID *FfsFile + ) +/*++ + +Routine Description: + + Clears out all files from the Fv buffer in memory + +Arguments: + + SourceFfsFile - Input FFS file to update the checksum for + +Returns: + + EFI_SUCCESS + EFI_NOT_FOUND + +--*/ +{ + EFI_FFS_FILE_HEADER* File = (EFI_FFS_FILE_HEADER*)FfsFile; + EFI_FFS_FILE_STATE StateBackup; + UINT32 FileSize; + + FileSize = FvBufExpand3ByteSize (File->Size); + + // + // Fill in checksums and state, they must be 0 for checksumming. + // + File->IntegrityCheck.Checksum.Header = 0; + File->IntegrityCheck.Checksum.File = 0; + StateBackup = File->State; + File->State = 0; + + File->IntegrityCheck.Checksum.Header = + FvBufCalculateChecksum8 ( + (UINT8 *) File, + sizeof (EFI_FFS_FILE_HEADER) + ); + + if (File->Attributes & FFS_ATTRIB_CHECKSUM) { + File->IntegrityCheck.Checksum.File = FvBufCalculateChecksum8 ( + (VOID*)File, + FileSize + ); + } else { + File->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM; + } + + File->State = StateBackup; + + return EFI_SUCCESS; +} + + +EFI_STATUS +FvBufChecksumHeader ( + IN OUT VOID *Fv + ) +/*++ + +Routine Description: + + Clears out all files from the Fv buffer in memory + +Arguments: + + SourceFv - Address of the Fv in memory, this firmware volume volume will + be modified, if SourceFfsFile exists + SourceFfsFile - Input FFS file to replace + +Returns: + + EFI_SUCCESS + EFI_NOT_FOUND + +--*/ +{ + EFI_FIRMWARE_VOLUME_HEADER* FvHeader = (EFI_FIRMWARE_VOLUME_HEADER*)Fv; + + FvHeader->Checksum = 0; + FvHeader->Checksum = + FvBufCalculateChecksum16 ( + (UINT16*) FvHeader, + FvHeader->HeaderLength / sizeof (UINT16) + ); + + return EFI_SUCCESS; +} + + +EFI_STATUS +FvBufDuplicate ( + IN VOID *SourceFv, + IN OUT VOID **DestinationFv + ) +/*++ + +Routine Description: + + Clears out all files from the Fv buffer in memory + +Arguments: + + SourceFv - Address of the Fv in memory + DestinationFv - Output for destination Fv + DestinationFv == NULL - invalid parameter + *DestinationFv == NULL - memory will be allocated + *DestinationFv != NULL - this address will be the destination + +Returns: + + EFI_SUCCESS + +--*/ +{ + EFI_STATUS Status; + UINTN size; + + if (DestinationFv == NULL) { + return EFI_INVALID_PARAMETER; + } + + Status = FvBufGetSize (SourceFv, &size); + if (EFI_ERROR (Status)) { + return Status; + } + + if (*DestinationFv == NULL) { + *DestinationFv = CommonLibBinderAllocate (size); + } + + CommonLibBinderCopyMem (*DestinationFv, SourceFv, size); + + return EFI_SUCCESS; +} + + +EFI_STATUS +FvBufExtend ( + IN VOID **Fv, + IN UINTN Size + ) +/*++ + +Routine Description: + + Extends a firmware volume by the given number of bytes. + + BUGBUG: Does not handle the case where the firmware volume has a + VTF (Volume Top File). The VTF will not be moved to the + end of the extended FV. + +Arguments: + + Fv - Source and destination firmware volume. + Note: The original firmware volume buffer is freed! + + Size - The minimum size that the firmware volume is to be extended by. + The FV may be extended more than this size. + +Returns: + + EFI_SUCCESS + +--*/ +{ + EFI_STATUS Status; + UINTN OldSize; + UINTN NewSize; + UINTN BlockCount; + VOID* NewFv; + + EFI_FIRMWARE_VOLUME_HEADER* hdr; + EFI_FV_BLOCK_MAP_ENTRY* blk; + + Status = FvBufGetSize (*Fv, &OldSize); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Locate the block map in the fv header + // + hdr = (EFI_FIRMWARE_VOLUME_HEADER*)*Fv; + blk = hdr->BlockMap; + + // + // Calculate the number of blocks needed to achieve the requested + // size extension + // + BlockCount = ((Size + (blk->Length - 1)) / blk->Length); + + // + // Calculate the new size from the number of blocks that will be added + // + NewSize = OldSize + (BlockCount * blk->Length); + + NewFv = CommonLibBinderAllocate (NewSize); + if (NewFv == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + // + // Copy the old data + // + CommonLibBinderCopyMem (NewFv, *Fv, OldSize); + + // + // Free the old fv buffer + // + CommonLibBinderFree (*Fv); + + // + // Locate the block map in the new fv header + // + hdr = (EFI_FIRMWARE_VOLUME_HEADER*)NewFv; + hdr->FvLength = NewSize; + blk = hdr->BlockMap; + + // + // Update the block map for the new fv + // + blk->NumBlocks += (UINT32)BlockCount; + + // + // Update the FV header checksum + // + FvBufChecksumHeader (NewFv); + + // + // Clear out the new area of the FV + // + CommonLibBinderSetMem ( + (UINT8*)NewFv + OldSize, + (NewSize - OldSize), + (hdr->Attributes & EFI_FVB2_ERASE_POLARITY) ? 0xFF : 0 + ); + + // + // Set output with new fv that was created + // + *Fv = NewFv; + + return EFI_SUCCESS; + +} + + +EFI_STATUS +FvBufClearAllFiles ( + IN OUT VOID *Fv + ) +/*++ + +Routine Description: + + Clears out all files from the Fv buffer in memory + +Arguments: + + Fv - Address of the Fv in memory + +Returns: + + EFI_SUCCESS + +--*/ + +{ + EFI_FIRMWARE_VOLUME_HEADER *hdr = (EFI_FIRMWARE_VOLUME_HEADER*)Fv; + EFI_STATUS Status; + UINTN size = 0; + + Status = FvBufGetSize (Fv, &size); + if (EFI_ERROR (Status)) { + return Status; + } + + CommonLibBinderSetMem( + (UINT8*)hdr + hdr->HeaderLength, + size - hdr->HeaderLength, + (hdr->Attributes & EFI_FVB2_ERASE_POLARITY) ? 0xFF : 0 + ); + + return EFI_SUCCESS; +} + + +EFI_STATUS +FvBufGetSize ( + IN VOID *Fv, + OUT UINTN *Size + ) +/*++ + +Routine Description: + + Clears out all files from the Fv buffer in memory + +Arguments: + + Fv - Address of the Fv in memory + +Returns: + + EFI_SUCCESS + +--*/ + +{ + EFI_FIRMWARE_VOLUME_HEADER *hdr = (EFI_FIRMWARE_VOLUME_HEADER*)Fv; + EFI_FV_BLOCK_MAP_ENTRY *blk = hdr->BlockMap; + + *Size = 0; + + while (blk->Length != 0 || blk->NumBlocks != 0) { + *Size = *Size + (blk->Length * blk->NumBlocks); + if (*Size >= 0x40000000) { + // If size is greater than 1GB, then assume it is corrupted + return EFI_VOLUME_CORRUPTED; + } + blk++; + } + + if (*Size == 0) { + // If size is 0, then assume the volume is corrupted + return EFI_VOLUME_CORRUPTED; + } + + return EFI_SUCCESS; +} + + +EFI_STATUS +FvBufAddFile ( + IN OUT VOID *Fv, + IN VOID *File + ) +/*++ + +Routine Description: + + Adds a new FFS file + +Arguments: + + Fv - Address of the Fv in memory + File - FFS file to add to Fv + +Returns: + + EFI_SUCCESS + +--*/ +{ + EFI_FIRMWARE_VOLUME_HEADER *hdr = (EFI_FIRMWARE_VOLUME_HEADER*)Fv; + + EFI_FFS_FILE_HEADER *fhdr = NULL; + EFI_FVB_ATTRIBUTES FvbAttributes; + UINTN offset; + UINTN fsize; + UINTN newSize; + UINTN clearLoop; + + EFI_STATUS Status; + UINTN fvSize; + + Status = FvBufGetSize (Fv, &fvSize); + if (EFI_ERROR (Status)) { + return Status; + } + + FvbAttributes = hdr->Attributes; + newSize = FvBufExpand3ByteSize (((EFI_FFS_FILE_HEADER*)File)->Size); + + for( + offset = (UINTN)ALIGN_POINTER (hdr->HeaderLength, 8); + offset + newSize <= fvSize; + offset = (UINTN)ALIGN_POINTER (offset, 8) + ) { + + fhdr = (EFI_FFS_FILE_HEADER*) ((UINT8*)hdr + offset); + + if (EFI_TEST_FFS_ATTRIBUTES_BIT( + FvbAttributes, + fhdr->State, + EFI_FILE_HEADER_VALID + ) + ) { + // BUGBUG: Need to make sure that the new file does not already + // exist. + + fsize = FvBufExpand3ByteSize (fhdr->Size); + if (fsize == 0 || (offset + fsize > fvSize)) { + return EFI_VOLUME_CORRUPTED; + } + + offset = offset + fsize; + continue; + } + + clearLoop = 0; + while ((clearLoop < newSize) && + (((UINT8*)fhdr)[clearLoop] == + (UINT8)((hdr->Attributes & EFI_FVB2_ERASE_POLARITY) ? 0xFF : 0) + ) + ) { + clearLoop++; + } + + // + // We found a place in the FV which is empty and big enough for + // the new file + // + if (clearLoop >= newSize) { + break; + } + + offset = offset + 1; // Make some forward progress + } + + if (offset + newSize > fvSize) { + return EFI_OUT_OF_RESOURCES; + } + + CommonLibBinderCopyMem (fhdr, File, newSize); + + return EFI_SUCCESS; +} + + +EFI_STATUS +FvBufAddFileWithExtend ( + IN OUT VOID **Fv, + IN VOID *File + ) +/*++ + +Routine Description: + + Adds a new FFS file. Extends the firmware volume if needed. + +Arguments: + + Fv - Source and destination firmware volume. + Note: If the FV is extended, then the original firmware volume + buffer is freed! + + Size - The minimum size that the firmware volume is to be extended by. + The FV may be extended more than this size. + +Returns: + + EFI_SUCCESS + +--*/ +{ + EFI_STATUS Status; + EFI_FFS_FILE_HEADER* NewFile; + + NewFile = (EFI_FFS_FILE_HEADER*)File; + + // + // Try to add to the capsule volume + // + Status = FvBufAddFile (*Fv, NewFile); + if (Status == EFI_OUT_OF_RESOURCES) { + // + // Try to extend the capsule volume by the size of the file + // + Status = FvBufExtend (Fv, FvBufExpand3ByteSize (NewFile->Size)); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Now, try to add the file again + // + Status = FvBufAddFile (*Fv, NewFile); + } + + return Status; +} + + +EFI_STATUS +FvBufAddVtfFile ( + IN OUT VOID *Fv, + IN VOID *File + ) +/*++ + +Routine Description: + + Adds a new FFS VFT (Volume Top File) file. In other words, adds the + file to the end of the firmware volume. + +Arguments: + + Fv - Address of the Fv in memory + File - FFS file to add to Fv + +Returns: + + EFI_SUCCESS + +--*/ +{ + EFI_STATUS Status; + + EFI_FIRMWARE_VOLUME_HEADER *hdr = (EFI_FIRMWARE_VOLUME_HEADER*)Fv; + + EFI_FFS_FILE_HEADER* NewFile; + UINTN NewFileSize; + + UINT8 erasedUint8; + UINTN clearLoop; + + EFI_FFS_FILE_HEADER *LastFile; + UINTN LastFileSize; + + UINTN fvSize; + UINTN Key; + + Status = FvBufGetSize (Fv, &fvSize); + if (EFI_ERROR (Status)) { + return Status; + } + + erasedUint8 = (UINT8)((hdr->Attributes & EFI_FVB2_ERASE_POLARITY) ? 0xFF : 0); + NewFileSize = FvBufExpand3ByteSize (((EFI_FFS_FILE_HEADER*)File)->Size); + + if (NewFileSize != (UINTN)ALIGN_POINTER (NewFileSize, 8)) { + return EFI_INVALID_PARAMETER; + } + + // + // Find the last file in the FV + // + Key = 0; + LastFile = NULL; + LastFileSize = 0; + do { + Status = FvBufFindNextFile (Fv, &Key, (VOID **)&LastFile); + LastFileSize = FvBufExpand3ByteSize (((EFI_FFS_FILE_HEADER*)File)->Size); + } while (!EFI_ERROR (Status)); + + // + // If no files were found, then we start at the beginning of the FV + // + if (LastFile == NULL) { + LastFile = (EFI_FFS_FILE_HEADER*)((UINT8*)hdr + hdr->HeaderLength); + } + + // + // We want to put the new file (VTF) at the end of the FV + // + NewFile = (EFI_FFS_FILE_HEADER*)((UINT8*)hdr + (fvSize - NewFileSize)); + + // + // Check to see if there is enough room for the VTF after the last file + // found in the FV + // + if ((UINT8*)NewFile < ((UINT8*)LastFile + LastFileSize)) { + return EFI_OUT_OF_RESOURCES; + } + + // + // Loop to determine if the end of the FV is empty + // + clearLoop = 0; + while ((clearLoop < NewFileSize) && + (((UINT8*)NewFile)[clearLoop] == erasedUint8) + ) { + clearLoop++; + } + + // + // Check to see if there was not enough room for the file + // + if (clearLoop < NewFileSize) { + return EFI_OUT_OF_RESOURCES; + } + + CommonLibBinderCopyMem (NewFile, File, NewFileSize); + + return EFI_SUCCESS; +} + + +VOID +FvBufCompact3ByteSize ( + OUT VOID* SizeDest, + IN UINT32 Size + ) +/*++ + +Routine Description: + + Expands the 3 byte size commonly used in Firmware Volume data structures + +Arguments: + + Size - Address of the 3 byte array representing the size + +Returns: + + UINT32 + +--*/ +{ + ((UINT8*)SizeDest)[0] = (UINT8)Size; + ((UINT8*)SizeDest)[1] = (UINT8)(Size >> 8); + ((UINT8*)SizeDest)[2] = (UINT8)(Size >> 16); +} + +UINT32 +FvBufExpand3ByteSize ( + IN VOID* Size + ) +/*++ + +Routine Description: + + Expands the 3 byte size commonly used in Firmware Volume data structures + +Arguments: + + Size - Address of the 3 byte array representing the size + +Returns: + + UINT32 + +--*/ +{ + return (((UINT8*)Size)[2] << 16) + + (((UINT8*)Size)[1] << 8) + + ((UINT8*)Size)[0]; +} + +EFI_STATUS +FvBufFindNextFile ( + IN VOID *Fv, + IN OUT UINTN *Key, + OUT VOID **File + ) +/*++ + +Routine Description: + + Iterates through the files contained within the firmware volume + +Arguments: + + Fv - Address of the Fv in memory + Key - Should be 0 to get the first file. After that, it should be + passed back in without modifying it's contents to retrieve + subsequent files. + File - Output file pointer + File == NULL - invalid parameter + otherwise - *File will be update to the location of the file + +Returns: + + EFI_SUCCESS + EFI_NOT_FOUND + EFI_VOLUME_CORRUPTED + +--*/ +{ + EFI_FIRMWARE_VOLUME_HEADER *hdr = (EFI_FIRMWARE_VOLUME_HEADER*)Fv; + + EFI_FFS_FILE_HEADER *fhdr = NULL; + EFI_FVB_ATTRIBUTES FvbAttributes; + UINTN fsize; + + EFI_STATUS Status; + UINTN fvSize; + + if (Fv == NULL) { + return EFI_INVALID_PARAMETER; + } + + Status = FvBufGetSize (Fv, &fvSize); + if (EFI_ERROR (Status)) { + return Status; + } + + if (*Key == 0) { + *Key = hdr->HeaderLength; + } + + FvbAttributes = hdr->Attributes; + + for( + *Key = (UINTN)ALIGN_POINTER (*Key, 8); + (*Key + sizeof (*fhdr)) < fvSize; + *Key = (UINTN)ALIGN_POINTER (*Key, 8) + ) { + + fhdr = (EFI_FFS_FILE_HEADER*) ((UINT8*)hdr + *Key); + fsize = FvBufExpand3ByteSize (fhdr->Size); + + if (!EFI_TEST_FFS_ATTRIBUTES_BIT( + FvbAttributes, + fhdr->State, + EFI_FILE_HEADER_VALID + ) || + EFI_TEST_FFS_ATTRIBUTES_BIT( + FvbAttributes, + fhdr->State, + EFI_FILE_HEADER_INVALID + ) + ) { + *Key = *Key + 1; // Make some forward progress + continue; + } else if( + EFI_TEST_FFS_ATTRIBUTES_BIT( + FvbAttributes, + fhdr->State, + EFI_FILE_MARKED_FOR_UPDATE + ) || + EFI_TEST_FFS_ATTRIBUTES_BIT( + FvbAttributes, + fhdr->State, + EFI_FILE_DELETED + ) + ) { + *Key = *Key + fsize; + continue; + } else if (EFI_TEST_FFS_ATTRIBUTES_BIT( + FvbAttributes, + fhdr->State, + EFI_FILE_DATA_VALID + ) + ) { + *File = (UINT8*)hdr + *Key; + *Key = *Key + fsize; + return EFI_SUCCESS; + } + + *Key = *Key + 1; // Make some forward progress + } + + return EFI_NOT_FOUND; +} + + +EFI_STATUS +FvBufFindFileByName ( + IN VOID *Fv, + IN EFI_GUID *Name, + OUT VOID **File + ) +/*++ + +Routine Description: + + Searches the Fv for a file by its name + +Arguments: + + Fv - Address of the Fv in memory + Name - Guid filename to search for in the firmware volume + File - Output file pointer + File == NULL - Only determine if the file exists, based on return + value from the function call. + otherwise - *File will be update to the location of the file + +Returns: + + EFI_SUCCESS + EFI_NOT_FOUND + EFI_VOLUME_CORRUPTED + +--*/ +{ + EFI_STATUS Status; + UINTN Key; + EFI_FFS_FILE_HEADER *NextFile; + + Key = 0; + while (TRUE) { + Status = FvBufFindNextFile (Fv, &Key, (VOID **)&NextFile); + if (EFI_ERROR (Status)) { + return Status; + } + + if (CommonLibBinderCompareGuid (Name, &NextFile->Name)) { + if (File != NULL) { + *File = NextFile; + } + return EFI_SUCCESS; + } + } + + return EFI_NOT_FOUND; +} + + +EFI_STATUS +FvBufFindFileByType ( + IN VOID *Fv, + IN EFI_FV_FILETYPE Type, + OUT VOID **File + ) +/*++ + +Routine Description: + + Searches the Fv for a file by its type + +Arguments: + + Fv - Address of the Fv in memory + Type - FFS FILE type to search for + File - Output file pointer + (File == NULL) -> Only determine if the file exists, based on return + value from the function call. + otherwise -> *File will be update to the location of the file + +Returns: + + EFI_SUCCESS + EFI_NOT_FOUND + EFI_VOLUME_CORRUPTED + +--*/ +{ + EFI_STATUS Status; + UINTN Key; + EFI_FFS_FILE_HEADER *NextFile; + + Key = 0; + while (TRUE) { + Status = FvBufFindNextFile (Fv, &Key, (VOID **)&NextFile); + if (EFI_ERROR (Status)) { + return Status; + } + + if (Type == NextFile->Type) { + if (File != NULL) { + *File = NextFile; + } + return EFI_SUCCESS; + } + } + + return EFI_NOT_FOUND; +} + + +EFI_STATUS +FvBufGetFileRawData ( + IN VOID* FfsFile, + OUT VOID** RawData, + OUT UINTN* RawDataSize + ) +/*++ + +Routine Description: + + Searches the requested file for raw data. + + This routine either returns all the payload of a EFI_FV_FILETYPE_RAW file, + or finds the EFI_SECTION_RAW section within the file and returns its data. + +Arguments: + + FfsFile - Address of the FFS file in memory + RawData - Pointer to the raw data within the file + (This is NOT allocated. It is within the file.) + RawDataSize - Size of the raw data within the file + +Returns: + + EFI_STATUS + +--*/ +{ + EFI_STATUS Status; + EFI_FFS_FILE_HEADER* File; + EFI_RAW_SECTION* Section; + + File = (EFI_FFS_FILE_HEADER*)FfsFile; + + // + // Is the file type == EFI_FV_FILETYPE_RAW? + // + if (File->Type == EFI_FV_FILETYPE_RAW) { + // + // Raw filetypes don't have sections, so we just return the raw data + // + *RawData = (VOID*)(File + 1); + *RawDataSize = FvBufExpand3ByteSize (File->Size) - sizeof (*File); + return EFI_SUCCESS; + } + + // + // Within the file, we now need to find the EFI_SECTION_RAW section. + // + Status = FvBufFindSectionByType (File, EFI_SECTION_RAW, (VOID **)&Section); + if (EFI_ERROR (Status)) { + return Status; + } + + *RawData = (VOID*)(Section + 1); + *RawDataSize = + FvBufExpand3ByteSize (Section->Size) - sizeof (*Section); + + return EFI_SUCCESS; + +} + + +EFI_STATUS +FvBufPackageFreeformRawFile ( + IN EFI_GUID* Filename, + IN VOID* RawData, + IN UINTN RawDataSize, + OUT VOID** FfsFile + ) +/*++ + +Routine Description: + + Packages up a FFS file containing the input raw data. + + The file created will have a type of EFI_FV_FILETYPE_FREEFORM, and will + contain one EFI_FV_FILETYPE_RAW section. + +Arguments: + + RawData - Pointer to the raw data to be packed + RawDataSize - Size of the raw data to be packed + FfsFile - Address of the packaged FFS file. + Note: The called must deallocate this memory! + +Returns: + + EFI_STATUS + +--*/ +{ + EFI_FFS_FILE_HEADER* NewFile; + UINT32 NewFileSize; + EFI_RAW_SECTION* NewSection; + UINT32 NewSectionSize; + + // + // The section size is the DataSize + the size of the section header + // + NewSectionSize = (UINT32)sizeof (EFI_RAW_SECTION) + (UINT32)RawDataSize; + + // + // The file size is the size of the file header + the section size + // + NewFileSize = sizeof (EFI_FFS_FILE_HEADER) + NewSectionSize; + + // + // Try to allocate a buffer to build the new FFS file in + // + NewFile = CommonLibBinderAllocate (NewFileSize); + if (NewFile == NULL) { + return EFI_OUT_OF_RESOURCES; + } + CommonLibBinderSetMem (NewFile, NewFileSize, 0); + + // + // The NewSection follow right after the FFS file header + // + NewSection = (EFI_RAW_SECTION*)(NewFile + 1); + FvBufCompact3ByteSize (NewSection->Size, NewSectionSize); + NewSection->Type = EFI_SECTION_RAW; + + // + // Copy the actual file data into the buffer + // + CommonLibBinderCopyMem (NewSection + 1, RawData, RawDataSize); + + // + // Initialize the FFS file header + // + CommonLibBinderCopyMem (&NewFile->Name, Filename, sizeof (EFI_GUID)); + FvBufCompact3ByteSize (NewFile->Size, NewFileSize); + NewFile->Type = EFI_FV_FILETYPE_FREEFORM; + NewFile->Attributes = 0; + NewFile->IntegrityCheck.Checksum.Header = + FvBufCalculateChecksum8 ((UINT8*)NewFile, sizeof (*NewFile)); + NewFile->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM; + NewFile->State = (UINT8)~( EFI_FILE_HEADER_CONSTRUCTION | + EFI_FILE_HEADER_VALID | + EFI_FILE_DATA_VALID + ); + + *FfsFile = NewFile; + + return EFI_SUCCESS; +} + + +EFI_STATUS +FvBufFindNextSection ( + IN VOID *SectionsStart, + IN UINTN TotalSectionsSize, + IN OUT UINTN *Key, + OUT VOID **Section + ) +/*++ + +Routine Description: + + Iterates through the sections contained within a given array of sections + +Arguments: + + SectionsStart - Address of the start of the FFS sections array + TotalSectionsSize - Total size of all the sections + Key - Should be 0 to get the first section. After that, it should be + passed back in without modifying it's contents to retrieve + subsequent files. + Section - Output section pointer + (Section == NULL) -> invalid parameter + otherwise -> *Section will be update to the location of the file + +Returns: + + EFI_SUCCESS + EFI_NOT_FOUND + EFI_VOLUME_CORRUPTED + +--*/ +{ + EFI_COMMON_SECTION_HEADER *sectionHdr; + UINTN sectionSize; + + *Key = (UINTN)ALIGN_POINTER (*Key, 4); // Sections are DWORD aligned + + if ((*Key + sizeof (*sectionHdr)) > TotalSectionsSize) { + return EFI_NOT_FOUND; + } + + sectionHdr = (EFI_COMMON_SECTION_HEADER*)((UINT8*)SectionsStart + *Key); + sectionSize = FvBufExpand3ByteSize (sectionHdr->Size); + + if (sectionSize < sizeof (EFI_COMMON_SECTION_HEADER)) { + return EFI_NOT_FOUND; + } + + if ((*Key + sectionSize) > TotalSectionsSize) { + return EFI_NOT_FOUND; + } + + *Section = (UINT8*)sectionHdr; + *Key = *Key + sectionSize; + return EFI_SUCCESS; + +} + + +EFI_STATUS +FvBufCountSections ( + IN VOID* FfsFile, + IN UINTN* Count + ) +/*++ + +Routine Description: + + Searches the FFS file and counts the number of sections found. + The sections are NOT recursed. + +Arguments: + + FfsFile - Address of the FFS file in memory + Count - The location to store the section count in + +Returns: + + EFI_SUCCESS + EFI_NOT_FOUND + EFI_VOLUME_CORRUPTED + +--*/ +{ + EFI_STATUS Status; + UINTN Key; + VOID* SectionStart; + UINTN TotalSectionsSize; + EFI_COMMON_SECTION_HEADER* NextSection; + + SectionStart = (VOID*)((UINTN)FfsFile + sizeof (EFI_FFS_FILE_HEADER)); + TotalSectionsSize = + FvBufExpand3ByteSize (((EFI_FFS_FILE_HEADER*)FfsFile)->Size) - + sizeof (EFI_FFS_FILE_HEADER); + Key = 0; + *Count = 0; + while (TRUE) { + Status = FvBufFindNextSection ( + SectionStart, + TotalSectionsSize, + &Key, + (VOID **)&NextSection + ); + if (Status == EFI_NOT_FOUND) { + return EFI_SUCCESS; + } else if (EFI_ERROR (Status)) { + return Status; + } + + // + // Increment the section counter + // + *Count += 1; + + } + + return EFI_NOT_FOUND; +} + + +EFI_STATUS +FvBufFindSectionByType ( + IN VOID *FfsFile, + IN UINT8 Type, + OUT VOID **Section + ) +/*++ + +Routine Description: + + Searches the FFS file for a section by its type + +Arguments: + + FfsFile - Address of the FFS file in memory + Type - FFS FILE section type to search for + Section - Output section pointer + (Section == NULL) -> Only determine if the section exists, based on return + value from the function call. + otherwise -> *Section will be update to the location of the file + +Returns: + + EFI_SUCCESS + EFI_NOT_FOUND + EFI_VOLUME_CORRUPTED + +--*/ +{ + EFI_STATUS Status; + UINTN Key; + VOID* SectionStart; + UINTN TotalSectionsSize; + EFI_COMMON_SECTION_HEADER* NextSection; + + SectionStart = (VOID*)((UINTN)FfsFile + sizeof (EFI_FFS_FILE_HEADER)); + TotalSectionsSize = + FvBufExpand3ByteSize (((EFI_FFS_FILE_HEADER*)FfsFile)->Size) - + sizeof (EFI_FFS_FILE_HEADER); + Key = 0; + while (TRUE) { + Status = FvBufFindNextSection ( + SectionStart, + TotalSectionsSize, + &Key, + (VOID **)&NextSection + ); + if (EFI_ERROR (Status)) { + return Status; + } + + if (Type == NextSection->Type) { + if (Section != NULL) { + *Section = NextSection; + } + return EFI_SUCCESS; + } + } + + return EFI_NOT_FOUND; +} + + +EFI_STATUS +FvBufShrinkWrap ( + IN VOID *Fv + ) +/*++ + +Routine Description: + + Shrinks a firmware volume (in place) to provide a minimal FV. + + BUGBUG: Does not handle the case where the firmware volume has a + VTF (Volume Top File). The VTF will not be moved to the + end of the extended FV. + +Arguments: + + Fv - Firmware volume. + +Returns: + + EFI_SUCCESS + +--*/ +{ + EFI_STATUS Status; + UINTN OldSize; + UINT32 BlockCount; + UINT32 NewBlockSize = 128; + UINTN Key; + EFI_FFS_FILE_HEADER* FileIt; + VOID* EndOfLastFile; + + EFI_FIRMWARE_VOLUME_HEADER* FvHdr; + + Status = FvBufGetSize (Fv, &OldSize); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = FvBufUnifyBlockSizes (Fv, NewBlockSize); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Locate the block map in the fv header + // + FvHdr = (EFI_FIRMWARE_VOLUME_HEADER*)Fv; + + // + // Find the end of the last file + // + Key = 0; + EndOfLastFile = (UINT8*)FvHdr + FvHdr->FvLength; + while (!EFI_ERROR (FvBufFindNextFile (Fv, &Key, (VOID **)&FileIt))) { + EndOfLastFile = + (VOID*)((UINT8*)FileIt + FvBufExpand3ByteSize (FileIt->Size)); + } + + // + // Set the BlockCount to have the minimal number of blocks for the Fv. + // + BlockCount = (UINT32)((UINTN)EndOfLastFile - (UINTN)Fv); + BlockCount = BlockCount + NewBlockSize - 1; + BlockCount = BlockCount / NewBlockSize; + + // + // Adjust the block count to shrink the Fv in place. + // + FvHdr->BlockMap[0].NumBlocks = BlockCount; + FvHdr->FvLength = BlockCount * NewBlockSize; + + // + // Update the FV header checksum + // + FvBufChecksumHeader (Fv); + + return EFI_SUCCESS; + +} + + +EFI_STATUS +FvBufUnifyBlockSizes ( + IN OUT VOID *Fv, + IN UINTN BlockSize + ) +/*++ + +Routine Description: + + Searches the FFS file for a section by its type + +Arguments: + + Fv - Address of the Fv in memory + BlockSize - The size of the blocks to convert the Fv to. If the total size + of the Fv is not evenly divisible by this size, then + EFI_INVALID_PARAMETER will be returned. + +Returns: + + EFI_SUCCESS + EFI_NOT_FOUND + EFI_VOLUME_CORRUPTED + +--*/ +{ + EFI_FIRMWARE_VOLUME_HEADER *hdr = (EFI_FIRMWARE_VOLUME_HEADER*)Fv; + EFI_FV_BLOCK_MAP_ENTRY *blk = hdr->BlockMap; + UINT32 Size; + + Size = 0; + + // + // Scan through the block map list, performing error checking, and adding + // up the total Fv size. + // + while( blk->Length != 0 || + blk->NumBlocks != 0 + ) { + Size = Size + (blk->Length * blk->NumBlocks); + blk++; + if ((UINT8*)blk > ((UINT8*)hdr + hdr->HeaderLength)) { + return EFI_VOLUME_CORRUPTED; + } + } + + // + // Make sure that the Fv size is a multiple of the new block size. + // + if ((Size % BlockSize) != 0) { + return EFI_INVALID_PARAMETER; + } + + // + // Zero out the entire block map. + // + CommonLibBinderSetMem ( + &hdr->BlockMap, + (UINTN)blk - (UINTN)&hdr->BlockMap, + 0 + ); + + // + // Write out the single block map entry. + // + hdr->BlockMap[0].Length = (UINT32)BlockSize; + hdr->BlockMap[0].NumBlocks = Size / (UINT32)BlockSize; + + return EFI_SUCCESS; +} + +STATIC +UINT16 +FvBufCalculateSum16 ( + 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; +} + + +STATIC +UINT16 +FvBufCalculateChecksum16 ( + 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 - FvBufCalculateSum16 (Buffer, Size)); +} + + +STATIC +UINT8 +FvBufCalculateSum8 ( + IN UINT8 *Buffer, + IN UINTN Size + ) +/*++ + +Description: + + This function calculates the UINT8 sum for the requested region. + +Input: + + Buffer Pointer to buffer containing byte data of component. + Size Size of the buffer + +Return: + + 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; +} + + +STATIC +UINT8 +FvBufCalculateChecksum8 ( + IN UINT8 *Buffer, + IN UINTN Size + ) +/*++ + +Description: + + This function calculates the value needed for a valid UINT8 checksum + +Input: + + Buffer Pointer to buffer containing byte data of component. + Size Size of the buffer + +Return: + + The 8 bit checksum value needed. + +--*/ +{ + return (UINT8)(0x100 - FvBufCalculateSum8 (Buffer, Size)); +} + + diff --git a/BaseTools/Source/C/Common/FirmwareVolumeBufferLib.h b/BaseTools/Source/C/Common/FirmwareVolumeBufferLib.h new file mode 100644 index 0000000000..5a52695a7f --- /dev/null +++ b/BaseTools/Source/C/Common/FirmwareVolumeBufferLib.h @@ -0,0 +1,166 @@ +/** @file + +Copyright (c) 1999 - 2008, 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: + + FirmwareVolumeBufferLib.h + +Abstract: + + EFI Firmware Volume routines which work on a Fv image in buffers. + +**/ + +#ifndef FirmwareVolumeBuffer_h_INCLUDED +#define FirmwareVolumeBuffer_h_INCLUDED + +#include "Common/UefiBaseTypes.h" +#include "Common/PiFirmwareFile.h" +#include "Common/PiFirmwareVolume.h" + +EFI_STATUS +FvBufAddFile ( + IN OUT VOID *Fv, + IN VOID *File + ); + +EFI_STATUS +FvBufAddFileWithExtend ( + IN OUT VOID **Fv, + IN VOID *File + ); + +EFI_STATUS +FvBufAddVtfFile ( + IN OUT VOID *Fv, + IN VOID *File + ); + +EFI_STATUS +FvBufChecksumFile ( + IN OUT VOID *FfsFile + ); + +EFI_STATUS +FvBufChecksumHeader ( + IN OUT VOID *Fv + ); + +EFI_STATUS +FvBufClearAllFiles ( + IN OUT VOID *Fv + ); + +VOID +FvBufCompact3ByteSize ( + OUT VOID* SizeDest, + IN UINT32 Size + ); + +EFI_STATUS +FvBufCountSections ( + IN VOID* FfsFile, + IN UINTN* Count + ); + +EFI_STATUS +FvBufDuplicate ( + IN VOID *SourceFv, + IN OUT VOID **DestinationFv + ); + +UINT32 +FvBufExpand3ByteSize ( + IN VOID* Size + ); + +EFI_STATUS +FvBufExtend ( + IN VOID **Fv, + IN UINTN Size + ); + +EFI_STATUS +FvBufFindFileByName ( + IN VOID *Fv, + IN EFI_GUID *Name, + OUT VOID **File + ); + +EFI_STATUS +FvBufFindFileByType ( + IN VOID *Fv, + IN EFI_FV_FILETYPE Type, + OUT VOID **File + ); + +EFI_STATUS +FvBufFindNextFile ( + IN VOID *Fv, + IN OUT UINTN *Key, + OUT VOID **File + ); + +EFI_STATUS +FvBufFindNextSection ( + IN VOID *SectionsStart, + IN UINTN TotalSectionsSize, + IN OUT UINTN *Key, + OUT VOID **Section + ); + +EFI_STATUS +FvBufFindSectionByType ( + IN VOID *FfsFile, + IN UINT8 Type, + OUT VOID **Section + ); + +EFI_STATUS +FvBufGetFileRawData ( + IN VOID* FfsFile, + OUT VOID** RawData, + OUT UINTN* RawDataSize + ); + +EFI_STATUS +FvBufGetSize ( + IN VOID *Fv, + OUT UINTN *Size + ); + +EFI_STATUS +FvBufPackageFreeformRawFile ( + IN EFI_GUID* Filename, + IN VOID* RawData, + IN UINTN RawDataSize, + OUT VOID** FfsFile + ); + +EFI_STATUS +FvBufRemoveFile ( + IN OUT VOID *Fv, + IN EFI_GUID *Name + ); + +EFI_STATUS +FvBufUnifyBlockSizes ( + IN OUT VOID *Fv, + IN UINTN BlockSize + ); + +EFI_STATUS +FvBufShrinkWrap ( + IN VOID *Fv + ); + +#endif // #ifndef FirmwareVolumeBuffer_h_INCLUDED + diff --git a/BaseTools/Source/C/Common/FvLib.c b/BaseTools/Source/C/Common/FvLib.c new file mode 100644 index 0000000000..292b077f34 --- /dev/null +++ b/BaseTools/Source/C/Common/FvLib.c @@ -0,0 +1,850 @@ +/** @file + +Copyright (c) 2004 - 2008, 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 + GetLength (CurrentFile->Size) > (UINTN) mFvHeader + mFvLength) { + *NextFile = NULL; + return EFI_SUCCESS; + } + + *NextFile = CurrentFile; + return EFI_SUCCESS; + } + } + // + // Verify current file is in range + // + if (((UINTN) CurrentFile < (UINTN) mFvHeader + mFvHeader->HeaderLength) || + ((UINTN) CurrentFile + GetLength (CurrentFile->Size) > (UINTN) mFvHeader + mFvLength) + ) { + 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 + sizeof (EFI_FFS_FILE_HEADER) >= (UINTN) mFvHeader + mFvLength) || + ((UINTN) *NextFile + GetLength ((*NextFile)->Size) > (UINTN) mFvHeader + mFvLength) + ) { + *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; + CHAR8 FileGuidString[80]; + + // + // 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; + } + // + // File Guid String Name + // + PrintGuidToBuffer (FileName, (UINT8 *)FileGuidString, sizeof (FileGuidString), TRUE); + // + // 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, 0003, "error parsing FV image", "FFS file with Guid %s can't be found", FileGuidString); + 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, 0003, "error parsing FV image", "FFS file with Guid %s can't be found", FileGuidString); + 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, 0003, "error parsing FV image", "FFS file with FileType 0x%x can't be found", FileType); + 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, 0003, "error parsing FV image", "FFS file with FileType 0x%x can't be found", FileType); + return EFI_ABORTED; + } + } + + *File = NULL; + return EFI_SUCCESS; +} + +EFI_STATUS +SearchSectionByType ( + IN EFI_FILE_SECTION_POINTER FirstSection, + IN UINT8 *SearchEnd, + IN EFI_SECTION_TYPE SectionType, + IN OUT UINTN *StartIndex, + IN UINTN Instance, + OUT EFI_FILE_SECTION_POINTER *Section + ) +/*++ + +Routine Description: + + Helper function to search a sequence of sections from the section pointed + by FirstSection to SearchEnd for the Instance-th section of type SectionType. + The current counter is saved in StartIndex and when the section is found, it's + saved in Section. GUID-defined sections, if special processing is not required, + are searched recursively in a depth-first manner. + +Arguments: + + FirstSection The first section to start searching from. + SearchEnd The end address to stop search. + SectionType The type of section to search. + StartIndex The current counter is saved. + Instance The requested n-th section number. + Section The found section returned. + +Returns: + + EFI_SUCCESS The function completed successfully. + EFI_NOT_FOUND The section is not found. +--*/ +{ + EFI_FILE_SECTION_POINTER CurrentSection; + EFI_FILE_SECTION_POINTER InnerSection; + EFI_STATUS Status; + UINTN SectionSize; + + CurrentSection = FirstSection; + + while ((UINTN) CurrentSection.CommonHeader < (UINTN) SearchEnd) { + if (CurrentSection.CommonHeader->Type == SectionType) { + (*StartIndex)++; + } + + if (*StartIndex == Instance) { + *Section = CurrentSection; + return EFI_SUCCESS; + } + // + // If the requesting section is not GUID-defined and + // we find a GUID-defined section that doesn't need + // special processing, go ahead to search the requesting + // section inside the GUID-defined section. + // + if (SectionType != EFI_SECTION_GUID_DEFINED && + CurrentSection.CommonHeader->Type == EFI_SECTION_GUID_DEFINED && + !(CurrentSection.GuidDefinedSection->Attributes & EFI_GUIDED_SECTION_PROCESSING_REQUIRED)) { + InnerSection.CommonHeader = (EFI_COMMON_SECTION_HEADER *) + ((UINTN) CurrentSection.CommonHeader + CurrentSection.GuidDefinedSection->DataOffset); + SectionSize = CurrentSection.CommonHeader->Size[0] + + (CurrentSection.CommonHeader->Size[1] << 8) + + (CurrentSection.CommonHeader->Size[2] << 16); + Status = SearchSectionByType ( + InnerSection, + (UINT8 *) ((UINTN) CurrentSection.CommonHeader + SectionSize), + SectionType, + StartIndex, + Instance, + Section + ); + if (!EFI_ERROR (Status)) { + 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)); + } + + return EFI_NOT_FOUND; +} + +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. + GUID-defined sections, if special processing is not needed, are handled in a + depth-first manner. + +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, 0006, "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)); + + // + // Depth-first manner to find section file. + // + Status = SearchSectionByType ( + CurrentSection, + (UINT8 *) ((UINTN) File + GetLength (File->Size)), + SectionType, + &SectionCount, + Instance, + Section + ); + + if (!EFI_ERROR (Status)) { + return EFI_SUCCESS; + } else { + // + // 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, 0006, "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, 0006, "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; + UINT8 SavedChecksum; + UINT8 SavedState; + UINT8 FileGuidString[80]; + // + // 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); + // + // 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, 0006, "invalid FFS file header checksum", "Ffs file with Guid %s", FileGuidString); + return EFI_ABORTED; + } + // + // Verify file checksum + // + if (FfsHeader->Attributes & FFS_ATTRIB_CHECKSUM) { + // + // Verify file data checksum + // + FileLength = GetLength (FfsHeader->Size); + Checksum = CalculateSum8 ((UINT8 *) FfsHeader, FileLength); + Checksum = (UINT8) (Checksum - FfsHeader->State); + if (Checksum != 0) { + Error (NULL, 0, 0006, "invalid FFS file checksum", "Ffs file with Guid %s", FileGuidString); + 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, 0006, "invalid fixed FFS file header checksum", "Ffs file with Guid %s", FileGuidString); + 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_FVB2_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/BaseTools/Source/C/Common/FvLib.h b/BaseTools/Source/C/Common/FvLib.h new file mode 100644 index 0000000000..43d3737f68 --- /dev/null +++ b/BaseTools/Source/C/Common/FvLib.h @@ -0,0 +1,178 @@ +/** @file + +Copyright (c) 2004 - 2008, 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 + +#include +#include +#include + +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/BaseTools/Source/C/Common/GNUmakefile b/BaseTools/Source/C/Common/GNUmakefile new file mode 100644 index 0000000000..df3108d923 --- /dev/null +++ b/BaseTools/Source/C/Common/GNUmakefile @@ -0,0 +1,28 @@ +ARCH ?= IA32 +MAKEROOT ?= .. + +# VPATH = .. + +LIBNAME = Common + +OBJECTS = \ + BasePeCoff.o \ + BinderFuncs.o \ + CommonLib.o \ + Crc32.o \ + Decompress.o \ + EfiCompress.o \ + EfiUtilityMsgs.o \ + FirmwareVolumeBuffer.o \ + FvLib.o \ + MemoryFile.o \ + MyAlloc.o \ + OsPath.o \ + ParseGuidedSectionTools.o \ + ParseInf.o \ + PeCoffLoaderEx.o \ + SimpleFileParsing.o \ + StringFuncs.o \ + TianoCompress.o + +include $(MAKEROOT)/Makefiles/lib.makefile diff --git a/BaseTools/Source/C/Common/Makefile b/BaseTools/Source/C/Common/Makefile new file mode 100644 index 0000000000..cdaa0065f3 --- /dev/null +++ b/BaseTools/Source/C/Common/Makefile @@ -0,0 +1,30 @@ +!INCLUDE ..\Makefiles\ms.common + +# VPATH = .. + +LIBNAME = Common + +OBJECTS = \ + BasePeCoff.obj \ + BinderFuncs.obj \ + CommonLib.obj \ + Crc32.obj \ + Decompress.obj \ + EfiCompress.obj \ + EfiUtilityMsgs.obj \ + FirmwareVolumeBuffer.obj \ + FvLib.obj \ + MemoryFile.obj \ + MyAlloc.obj \ + OsPath.obj \ + ParseGuidedSectionTools.obj \ + ParseInf.obj \ + PeCoffLoaderEx.obj \ + SimpleFileParsing.obj \ + StringFuncs.obj \ + TianoCompress.obj + +!INCLUDE ..\Makefiles\ms.lib + + + diff --git a/BaseTools/Source/C/Common/MemoryFile.c b/BaseTools/Source/C/Common/MemoryFile.c new file mode 100644 index 0000000000..cace6282ac --- /dev/null +++ b/BaseTools/Source/C/Common/MemoryFile.c @@ -0,0 +1,260 @@ +/** @file + +Copyright (c) 2004 - 2008, 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: + + MemoryFile.c + +Abstract: + + This contains some useful functions for accessing files. + +**/ + +#include +#include +#include +#include +#include "CommonLib.h" +#include "MemoryFile.h" + + +// +// Local (static) function prototypes +// +STATIC +VOID +CheckMemoryFileState ( + IN EFI_HANDLE InputMemoryFile + ); + +// +// Function implementations +// + +EFI_STATUS +GetMemoryFile ( + IN CHAR8 *InputFileName, + OUT EFI_HANDLE *OutputMemoryFile + ) +/*++ + +Routine Description: + + This opens a file, reads it into memory and returns a memory file + object. + +Arguments: + + InputFile Memory file image. + OutputMemoryFile Handle to memory file + +Returns: + + EFI_STATUS + OutputMemoryFile is valid if !EFI_ERROR + +--*/ +{ + EFI_STATUS Status; + CHAR8 *InputFileImage; + UINT32 BytesRead; + MEMORY_FILE *NewMemoryFile; + + Status = GetFileImage (InputFileName, &InputFileImage, &BytesRead); + if (EFI_ERROR (Status)) { + return Status; + } + + NewMemoryFile = malloc (sizeof (*NewMemoryFile)); + if (NewMemoryFile == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + NewMemoryFile->FileImage = InputFileImage; + NewMemoryFile->CurrentFilePointer = InputFileImage; + NewMemoryFile->Eof = InputFileImage + BytesRead; + + *OutputMemoryFile = (EFI_HANDLE)NewMemoryFile; + + CheckMemoryFileState (*OutputMemoryFile); + + return EFI_SUCCESS; +} + + +EFI_STATUS +FreeMemoryFile ( + IN EFI_HANDLE InputMemoryFile + ) +/*++ + +Routine Description: + + Frees all memory associated with the input memory file. + +Arguments: + + InputMemoryFile Handle to memory file + +Returns: + + EFI_STATUS + +--*/ +{ + MEMORY_FILE *MemoryFile; + + CheckMemoryFileState (InputMemoryFile); + + MemoryFile = (MEMORY_FILE*)InputMemoryFile; + + free (MemoryFile->FileImage); + + // + // Invalidate state of MEMORY_FILE structure to catch invalid usage. + // + memset (MemoryFile, 0xcc, sizeof (*MemoryFile)); + MemoryFile->Eof -= 1; + + free (MemoryFile); + + return EFI_SUCCESS; +} + + +CHAR8 * +ReadMemoryFileLine ( + IN EFI_HANDLE InputMemoryFile + ) +/*++ + +Routine Description: + + This function reads a line from the memory file. The newline characters + are stripped and a null terminated string is returned. + + If the string pointer returned is non-NULL, then the caller must free the + memory associated with this string. + +Arguments: + + InputMemoryFile Handle to memory file + +Returns: + + NULL if error or EOF + NULL character termincated string otherwise (MUST BE FREED BY CALLER) + +--*/ +{ + CHAR8 *EndOfLine; + UINTN CharsToCopy; + MEMORY_FILE *InputFile; + UINTN BytesToEof; + CHAR8 *OutputString; + + // + // Verify input parameters are not null + // + CheckMemoryFileState (InputMemoryFile); + + InputFile = (MEMORY_FILE*)InputMemoryFile; + + // + // Check for end of file condition + // + if (InputFile->CurrentFilePointer >= InputFile->Eof) { + return NULL; + } + + // + // Determine the number of bytes remaining until the EOF + // + BytesToEof = InputFile->Eof - InputFile->CurrentFilePointer; + + // + // Find the next newline char + // + EndOfLine = memchr (InputFile->CurrentFilePointer, '\n', BytesToEof); + + // + // 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 { + // + // Newline found in the file. + // + CharsToCopy = EndOfLine - InputFile->CurrentFilePointer; + } + + OutputString = malloc (CharsToCopy); + if (OutputString == NULL) { + return NULL; + } + + // + // Copy the line. + // + memcpy (OutputString, InputFile->CurrentFilePointer, CharsToCopy); + + // + // Add the null termination over the 0x0D + // + if (OutputString[CharsToCopy - 1] == '\r') { + + OutputString[CharsToCopy - 1] = '\0'; + + } else { + + OutputString[CharsToCopy] = '\0'; + + } + + // + // Increment the current file pointer (include the 0x0A) + // + InputFile->CurrentFilePointer += CharsToCopy + 1; + CheckMemoryFileState (InputMemoryFile); + + // + // Return the string + // + return OutputString; +} + + +STATIC +VOID +CheckMemoryFileState ( + IN EFI_HANDLE InputMemoryFile + ) +{ + MEMORY_FILE *MemoryFile; + + assert (InputMemoryFile != NULL); + + MemoryFile = (MEMORY_FILE*)InputMemoryFile; + + assert (MemoryFile->FileImage != NULL); + assert (MemoryFile->CurrentFilePointer != NULL); + assert (MemoryFile->Eof != NULL); + assert (MemoryFile->Eof >= MemoryFile->FileImage); + assert (MemoryFile->CurrentFilePointer >= MemoryFile->FileImage); + assert (MemoryFile->CurrentFilePointer <= MemoryFile->Eof); +} + + diff --git a/BaseTools/Source/C/Common/MemoryFile.h b/BaseTools/Source/C/Common/MemoryFile.h new file mode 100644 index 0000000000..9148d9d06c --- /dev/null +++ b/BaseTools/Source/C/Common/MemoryFile.h @@ -0,0 +1,122 @@ +/** @file + +Copyright (c) 2004 - 2008, 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: + + MemoryFile.h + +Abstract: + + Header file for helper functions useful for accessing files. + +**/ + +#ifndef _EFI_MEMORY_FILE_H +#define _EFI_MEMORY_FILE_H + +#include +#include +#include + +#ifndef _MAX_PATH +#define _MAX_PATH 500 +#endif + +// +// Common data structures +// +typedef struct { + CHAR8 *FileImage; + CHAR8 *Eof; + CHAR8 *CurrentFilePointer; +} MEMORY_FILE; + + +// +// Functions declarations +// + +EFI_STATUS +GetMemoryFile ( + IN CHAR8 *InputFileName, + OUT EFI_HANDLE *OutputMemoryFile + ) +; +/** + +Routine Description: + + This opens a file, reads it into memory and returns a memory file + object. + +Arguments: + + InputFile Memory file image. + OutputMemoryFile Handle to memory file + +Returns: + + EFI_STATUS + OutputMemoryFile is valid if !EFI_ERROR + +**/ + + +EFI_STATUS +FreeMemoryFile ( + IN EFI_HANDLE InputMemoryFile + ) +; +/** + +Routine Description: + + Frees all memory associated with the input memory file. + +Arguments: + + InputMemoryFile Handle to memory file + +Returns: + + EFI_STATUS + +**/ + + +CHAR8 * +ReadMemoryFileLine ( + IN EFI_HANDLE InputMemoryFile + ) +; +/** + +Routine Description: + + This function reads a line from the memory file. The newline characters + are stripped and a null terminated string is returned. + + If the string pointer returned is non-NULL, then the caller must free the + memory associated with this string. + +Arguments: + + InputMemoryFile Handle to memory file + +Returns: + + NULL if error or EOF + NULL character termincated string otherwise (MUST BE FREED BY CALLER) + +**/ + + +#endif diff --git a/BaseTools/Source/C/Common/MyAlloc.c b/BaseTools/Source/C/Common/MyAlloc.c new file mode 100644 index 0000000000..b53713941c --- /dev/null +++ b/BaseTools/Source/C/Common/MyAlloc.c @@ -0,0 +1,516 @@ +/** @file + +Copyright (c) 2004 - 2008, 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=%s, Line=%u)" + "Invalid parameter(s).\n", + Final, + File, + (UINT32)Line + ); + + exit (1); + } + + if (strlen ((CHAR8 *)File) == 0) { + printf ( + "\nMyCheck(Final=%u, File=%s, Line=%u)" + "Invalid parameter.\n", + Final, + File, + (UINT32)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, + (UINT32)Line, + Tmp->File, + (UINT32)Tmp->Line, + (UINT32)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, + (UINT32)Line + ); + + for (Tmp = MyAllocData; Tmp != NULL; Tmp = Tmp->Next) { + printf ( + "File=%s, Line=%u, nSize=%u, Head=%xh, Tail=%xh\n", + Tmp->File, + (UINT32)Tmp->Line, + (UINT32)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=%s, Line=%u)" + "\nInvalid parameter(s).\n", + (UINT32)Size, + File, + (UINT32)Line + ); + + exit (1); + } + + Len = strlen ((CHAR8 *)File); + if (Len == 0) { + printf ( + "\nMyAlloc(Size=%u, File=%s, Line=%u)" + "\nInvalid parameter.\n", + (UINT32)Size, + File, + (UINT32)Line + ); + + exit (1); + } + // + // Check the allocation list for corruption. + // + MyCheck (0, (UINT8 *)__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", + (UINT32)Size, + File, + (UINT32)Line + ); + + exit (1); + } + // + // Fill in the new entry. + // + Tmp->File = ((UINT8 *) Tmp) + sizeof (MY_ALLOC_STRUCT); + strcpy ((CHAR8 *)Tmp->File, (CHAR8 *)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=%p, Size=%u, File=%s, Line=%u)" + "\nInvalid parameter(s).\n", + Ptr, + (UINT32)Size, + File, + (UINT32)Line + ); + + exit (1); + } + + if (strlen ((CHAR8 *)File) == 0) { + printf ( + "\nMyRealloc(Ptr=%p, Size=%u, File=%s, Line=%u)" + "\nInvalid parameter.\n", + Ptr, + (UINT32)Size, + File, + (UINT32)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=%p, Size=%u, File=%s, Line=%u)" + "\nCould not find buffer.\n", + Ptr, + (UINT32)Size, + File, + (UINT32)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, (UINT8 *)__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=%p, File=%s, Line=%u)" + "\nInvalid parameter(s).\n", + Ptr, + File, + (UINT32)Line + ); + + exit (1); + } + + if (strlen ((CHAR8 *)File) == 0) { + printf ( + "\nMyFree(Ptr=%p, File=%s, Line=%u)" + "\nInvalid parameter.\n", + Ptr, + File, + (UINT32)Line + ); + + exit (1); + } + // + // Freeing NULL is always valid. + // + if (Ptr == NULL) { + return ; + } + // + // Fail if nothing is allocated. + // + if (MyAllocData == NULL) { + printf ( + "\nMyFree(Ptr=%p, File=%s, Line=%u)" + "\nCalled before memory allocated.\n", + Ptr, + File, + (UINT32)Line + ); + + exit (1); + } + // + // Check for corrupted allocation list. + // + MyCheck (0, (UINT8 *)__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=%p, File=%s, Line=%u)\n" + "\nNot found.\n", + Ptr, + File, + (UINT32)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/BaseTools/Source/C/Common/MyAlloc.h b/BaseTools/Source/C/Common/MyAlloc.h new file mode 100644 index 0000000000..9dbe91cd41 --- /dev/null +++ b/BaseTools/Source/C/Common/MyAlloc.h @@ -0,0 +1,222 @@ +/** @file + +Copyright (c) 2004 - 2008, 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 +#include +#include + +#include + +// +// 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/BaseTools/Source/C/Common/OsPath.c b/BaseTools/Source/C/Common/OsPath.c new file mode 100644 index 0000000000..088730689d --- /dev/null +++ b/BaseTools/Source/C/Common/OsPath.c @@ -0,0 +1,307 @@ +/** @file + +Copyright (c) 2007 - 2008, 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: + + StringFuncs.c + +Abstract: + + Functions useful to operate file directories by parsing file path. + +**/ + +#include +#include +#include +#include "OsPath.h" + +// +// Functions implementations +// + +#if 0 + // + // BUGBUG: Not fully implemented yet. + // +CHAR8* +OsPathDirName ( + IN CHAR8 *FilePath + ) +/*++ + +Routine Description: + + This function returns the directory path which contains the particular path. + Some examples: + "a/b/c" -> "a/b" + "a/b/c/" -> "a/b" + "a" -> "." + "." -> ".." + "/" -> NULL + + This function does not check for the existence of the file. + + The caller must free the string returned. + +Arguments: + + FilePath Path name of file to get the parent directory for. + +Returns: + + NULL if error + +--*/ +{ + CHAR8 *Return; + CHAR8 *Pos; + CHAR8 Char; + UINTN Length; + INTN Offset; + + Length = strlen (FilePath); + + if (Length == 0) { + return NULL; + } + + // + // Check for the root directory case + // + if ( + (Length == 3 && isalpha (FilePath[0]) && (strcmp(FilePath + 1, ":\\") == 0)) || + (strcmp(FilePath, "/") == 0) + ) { + return NULL; + } + + // + // If the path ends with a path separator, then just append ".." + // + Char = FilePath[Length - 1]; + if (Char == '/' || Char == '\\') { + return OsPathJoin (FilePath, ".."); + } + + // + // + // + for (Offset = Length; Offset > 0; Offset--) { + if ((Return[Offset] == '/') || (Return[Offset] == '\\')) { + Return[Offset] = '\0'; + return Return; + } + } +} +#endif + + +#if 0 + // + // BUGBUG: Not fully implemented yet. + // +VOID +OsPathNormPathInPlace ( + IN CHAR8 *Path + ) +/*++ + +Routine Description: + + This function returns the directory path which contains the particular path. + Some examples: + "a/b/../c" -> "a/c" + "a/b//c" -> "a/b/c" + "a/./b" -> "a/b" + + This function does not check for the existence of the file. + +Arguments: + + Path Path name of file to normalize + +Returns: + + The string is altered in place. + +--*/ +{ + CHAR8 *Pos; + INTN Offset; + BOOLEAN TryAgain; + UINTN Length; + UINTN Remaining; + UINTN SubLength; + + do { + TryAgain = FALSE; + Length = strlen (Path); + + for (Offset = 0; Offset < Length; Offset++) { + Remaining = Length - Offset; + + // + // Collapse '//' -> '/' + // + if ( + (Remaining >= 2) && + ((Offset > 0) || (Path[0] != '\\')) && + IsDirSep (Path[Offset]) && IsDirSep (Path[Offset + 1]) + ) { + memmove (&Path[Offset], &Path[Offset + 1], Remaining); + TryAgain = TRUE; + break; + } + + // + // Collapse '/./' -> '/' + // + if ((Remaining >= 3) && IsDirSep (Path[Offset]) && + (Path[Offset + 1] == '.') && IsDirSep (Path[Offset + 2]) + ) { + memmove (&Path[Offset], &Path[Offset + 1], Remaining); + TryAgain = TRUE; + break; + } + + // + // Collapse 'a/../b' -> 'b' + // + // BUGBUG: Not implemented yet + + } + + } while (TryAgain); + + Return = CloneString (FilePath); + if (Return == NULL) { + return NULL; + } + + Length = strlen (Return); + + // + // Check for the root directory case + // + if ( + (Length == 3 && isalpha (Return[0]) && (strcmp(Return + 1, ":\\") == 0)) || + (strcmp(Return, "/") == 0) + ) { + free (Return); + return NULL; + } + + // + // + // + for (Offset = Length; Offset > 0; Offset--) { + if ((Return[Offset] == '/') || (Return[Offset] == '\\')) { + Return[Offset] = '\0'; + return Return; + } + } +} +#endif + + +CHAR8* +OsPathPeerFilePath ( + IN CHAR8 *OldPath, + IN CHAR8 *Peer + ) +/*++ + +Routine Description: + + This function replaces the final portion of a path with an alternative + 'peer' filename. For example: + "a/b/../c", "peer" -> "a/b/../peer" + "a/b/", "peer" -> "a/b/peer" + "/a", "peer" -> "/peer" + "a", "peer" -> "peer" + + This function does not check for the existence of the file. + +Arguments: + + OldPath Path name of replace the final segment + Peer The new path name to concatinate to become the peer path + +Returns: + + A CHAR8* string, which must be freed by the caller + +--*/ +{ + CHAR8 *Result; + INTN Offset; + + Result = (CHAR8 *) malloc (strlen (OldPath) + strlen (Peer) + 1); + if (Result == NULL) { + return NULL; + } + + strcpy (Result, OldPath); + + // + // Search for the last '/' or '\' in the string. If found, replace + // everything following it with Peer + // + for (Offset = strlen (Result); Offset >= 0; Offset--) { + if ((Result[Offset] == '/') || (Result[Offset] == '\\')) { + Result[Offset + 1] = '\0'; + strcat (Result, Peer); + return Result; + } + } + + // + // Neither a '/' nor a '\' was found. Therefore, we simply return Peer. + // + strcpy (Result, Peer); + return Result; +} + + +BOOLEAN +OsPathExists ( + IN CHAR8 *InputFileName + ) +/*++ + +Routine Description: + + Checks if a file exists + +Arguments: + + InputFileName The name of the file to check for existence + +Returns: + + TRUE The file exists + FALSE The file does not exist + +--*/ +{ + FILE *InputFile; + InputFile = fopen (InputFileName, "rb"); + if (InputFile == NULL) { + return FALSE; + } else { + fclose (InputFile); + return TRUE; + } +} + + + diff --git a/BaseTools/Source/C/Common/OsPath.h b/BaseTools/Source/C/Common/OsPath.h new file mode 100644 index 0000000000..0386dfa50d --- /dev/null +++ b/BaseTools/Source/C/Common/OsPath.h @@ -0,0 +1,146 @@ +/** @file + +Copyright (c) 2007 - 2008, 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: + + OsPath.h + +Abstract: + + Header file for helper functions useful to operate file directories + by parsing file path. + +**/ + +#ifndef _EFI_OS_PATH_H +#define _EFI_OS_PATH_H + +#include + +// +// Functions declarations +// + +CHAR8* +OsPathDirName ( + IN CHAR8 *FilePath + ) +; +/** + +Routine Description: + + This function returns the directory path which contains the particular path. + Some examples: + "a/b/c" -> "a/b" + "a/b/c/" -> "a/b" + "a" -> "." + "." -> ".." + "/" -> NULL + + This function does not check for the existence of the file. + + The caller must free the string returned. + +Arguments: + + FilePath Path name of file to get the parent directory for. + +Returns: + + NULL if error + +**/ + + +VOID +OsPathNormPathInPlace ( + IN CHAR8 *Path + ) +; +/** + +Routine Description: + + This function returns the directory path which contains the particular path. + Some examples: + "a/b/../c" -> "a/c" + "a/b//c" -> "a/b/c" + "a/./b" -> "a/b" + + This function does not check for the existence of the file. + +Arguments: + + Path Path name of file to normalize + +Returns: + + The string is altered in place. + +**/ + + +CHAR8* +OsPathPeerFilePath ( + IN CHAR8 *OldPath, + IN CHAR8 *Peer + ) +; +/** + +Routine Description: + + This function replaces the final portion of a path with an alternative + 'peer' filename. For example: + "a/b/../c", "peer" -> "a/b/../peer" + "a/b/", "peer" -> "a/b/peer" + "/a", "peer" -> "/peer" + "a", "peer" -> "peer" + + This function does not check for the existence of the file. + +Arguments: + + OldPath Path name of replace the final segment + Peer The new path name to concatinate to become the peer path + +Returns: + + A CHAR8* string, which must be freed by the caller + +**/ + + +BOOLEAN +OsPathExists ( + IN CHAR8 *InputFileName + ) +; +/** + +Routine Description: + + Checks if a file exists + +Arguments: + + InputFileName The name of the file to check for existence + +Returns: + + TRUE The file exists + FALSE The file does not exist + +**/ + + +#endif diff --git a/BaseTools/Source/C/Common/ParseGuidedSectionTools.c b/BaseTools/Source/C/Common/ParseGuidedSectionTools.c new file mode 100644 index 0000000000..02d0b11f0d --- /dev/null +++ b/BaseTools/Source/C/Common/ParseGuidedSectionTools.c @@ -0,0 +1,210 @@ +/** @file + +Copyright (c) 2007 - 2008, 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: + + ParseGuidedSectionTools.c + +Abstract: + + Helper functions for parsing GuidedSectionTools.txt + +**/ + +#include +#include +#include +#include +#include "MemoryFile.h" +#include "CommonLib.h" +#include "EfiUtilityMsgs.h" +#include "ParseInf.h" +#include "ParseGuidedSectionTools.h" +#include "StringFuncs.h" + + +// +// Local types / structures +// + +typedef struct _GUID_SEC_TOOL_ENTRY { + EFI_GUID Guid; + CHAR8* Name; + CHAR8* Path; + struct _GUID_SEC_TOOL_ENTRY *Next; +} GUID_SEC_TOOL_ENTRY; + +// +// Functin Implementation +// + +EFI_HANDLE +ParseGuidedSectionToolsFile ( + IN CHAR8 *InputFile + ) +/*++ + +Routine Description: + + This function parses the tools_def.txt file. It returns a + EFI_HANDLE object which can be used for the other library + functions and should be passed to FreeParsedGuidedSectionToolsHandle + to free resources when the tools_def.txt information is no + longer needed. + +Arguments: + + InputFile Path name of file to read + +Returns: + + NULL if error parsing + A non-NULL EFI_HANDLE otherwise + +--*/ +{ + EFI_STATUS Status; + EFI_HANDLE MemoryFile; + EFI_HANDLE ParsedGuidedSectionTools; + + Status = GetMemoryFile (InputFile, &MemoryFile); + if (EFI_ERROR (Status)) { + return NULL; + } + + ParsedGuidedSectionTools = ParseGuidedSectionToolsMemoryFile (MemoryFile); + + FreeMemoryFile (MemoryFile); + + return ParsedGuidedSectionTools; +} + + +EFI_HANDLE +ParseGuidedSectionToolsMemoryFile ( + IN EFI_HANDLE InputFile + ) +/*++ + +Routine Description: + + This function parses the tools_def.txt file. It returns a + EFI_HANDLE object which can be used for the other library + functions and should be passed to FreeParsedGuidedSectionToolsHandle + to free resources when the tools_def.txt information is no + longer needed. + +Arguments: + + InputFile Memory file image. + +Returns: + + NULL if error or EOF + InputBuffer otherwise + +--*/ +{ + EFI_STATUS Status; + CHAR8 *NextLine; + STRING_LIST *Tool; + EFI_GUID Guid; + GUID_SEC_TOOL_ENTRY *FirstGuidTool; + GUID_SEC_TOOL_ENTRY *LastGuidTool; + GUID_SEC_TOOL_ENTRY *NewGuidTool; + + FirstGuidTool = NULL; + + while (TRUE) { + NextLine = ReadMemoryFileLine (InputFile); + if (NextLine == NULL) { + break; + } + + Status = StripInfDscStringInPlace (NextLine); + if (EFI_ERROR (Status)) { + break; + } + + if (NextLine[0] == '\0') { + continue; + } + + Tool = SplitStringByWhitespace (NextLine); + if ((Tool != NULL) && + (Tool->Count == 3) + ) { + Status = StringToGuid (Tool->Strings[0], &Guid); + if (!EFI_ERROR (Status)) { + NewGuidTool = malloc (sizeof (GUID_SEC_TOOL_ENTRY)); + if (NewGuidTool != NULL) { + memcpy (&(NewGuidTool->Guid), &Guid, sizeof (Guid)); + NewGuidTool->Name = CloneString(Tool->Strings[1]); + NewGuidTool->Path = CloneString(Tool->Strings[2]); + NewGuidTool->Next = NULL; + } + if (FirstGuidTool == NULL) { + FirstGuidTool = NewGuidTool; + } else { + LastGuidTool->Next = NewGuidTool; + } + LastGuidTool = NewGuidTool; + } + FreeStringList (Tool); + } + } + + return FirstGuidTool; +} + + +CHAR8* +LookupGuidedSectionToolPath ( + IN EFI_HANDLE ParsedGuidedSectionToolsHandle, + IN EFI_GUID *SectionGuid + ) +/*++ + +Routine Description: + + This function looks up the appropriate tool to use for extracting + a GUID defined FV section. + +Arguments: + + ParsedGuidedSectionToolsHandle A parsed GUID section tools handle. + SectionGuid The GUID for the section. + +Returns: + + NULL - if no tool is found or there is another error + Non-NULL - The tool to use to access the section contents. (The caller + must free the memory associated with this string.) + +--*/ +{ + GUID_SEC_TOOL_ENTRY *GuidTool; + + GuidTool = (GUID_SEC_TOOL_ENTRY*)ParsedGuidedSectionToolsHandle; + if (GuidTool == NULL) { + return NULL; + } + + for ( ; GuidTool != NULL; GuidTool = GuidTool->Next) { + if (CompareGuid (&(GuidTool->Guid), SectionGuid) == 0) { + return CloneString (GuidTool->Path); + } + } + + return NULL; +} + + diff --git a/BaseTools/Source/C/Common/ParseGuidedSectionTools.h b/BaseTools/Source/C/Common/ParseGuidedSectionTools.h new file mode 100644 index 0000000000..d30afff1cc --- /dev/null +++ b/BaseTools/Source/C/Common/ParseGuidedSectionTools.h @@ -0,0 +1,133 @@ +/** @file + +Copyright (c) 2007 - 2008, 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: + + ParseGuidedSectionTools.h + +Abstract: + + Header file for helper functions for parsing GuidedSectionTools.txt + +**/ + +#ifndef _EFI_PARSE_GUIDED_SECTION_TOOLS_H +#define _EFI_PARSE_GUIDED_SECTION_TOOLS_H + +#include + +// +// Functions declarations +// + +EFI_HANDLE +ParseGuidedSectionToolsFile ( + IN CHAR8 *InputFile + ) +; +/** + +Routine Description: + + This function parses the tools_def.txt file. It returns a + EFI_HANDLE object which can be used for the other library + functions and should be passed to FreeParsedToolsDefHandle + to free resources when the tools_def.txt information is no + longer needed. + +Arguments: + + InputFile Path name of file to read + +Returns: + + NULL if error parsing + A non-NULL EFI_HANDLE otherwise + +**/ + + +EFI_HANDLE +ParseGuidedSectionToolsMemoryFile ( + IN EFI_HANDLE InputFile + ) +; +/** + +Routine Description: + + This function parses the tools_def.txt file. It returns a + EFI_HANDLE object which can be used for the other library + functions and should be passed to FreeParsedToolsDefHandle + to free resources when the tools_def.txt information is no + longer needed. + +Arguments: + + InputFile Memory file image. + +Returns: + + NULL if error parsing + A non-NULL EFI_HANDLE otherwise + +**/ + +CHAR8* +LookupGuidedSectionToolPath ( + IN EFI_HANDLE ParsedGuidedSectionToolsHandle, + IN EFI_GUID *SectionGuid + ) +; +/** + +Routine Description: + + This function looks up the appropriate tool to use for extracting + a GUID defined FV section. + +Arguments: + + ParsedGuidedSectionToolsHandle A parsed GUID section tools handle. + SectionGuid The GUID for the section. + +Returns: + + NULL - if no tool is found or there is another error + Non-NULL - The tool to use to access the section contents. (The caller + must free the memory associated with this string.) + +**/ + +EFI_STATUS +FreeParsedGuidedSectionToolsHandle ( + IN EFI_HANDLE ParsedGuidedSectionToolsHandle + ) +; +/** + +Routine Description: + + Frees resources that were allocated by ParseGuidedSectionToolsFile. + After freeing these resources, the information that was parsed + is no longer accessible. + +Arguments: + + ParsedToolDefHandle Handle returned from ParseGuidedSectionToolsFile + +Returns: + + EFI_STATUS + +**/ + +#endif diff --git a/BaseTools/Source/C/Common/ParseInf.c b/BaseTools/Source/C/Common/ParseInf.c new file mode 100644 index 0000000000..8305f14aef --- /dev/null +++ b/BaseTools/Source/C/Common/ParseInf.c @@ -0,0 +1,665 @@ +/** @file + +Copyright (c) 2004 - 2008, 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 +#include +#include +#include +#include "EfiUtilityMsgs.h" +#include "ParseInf.h" + +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 + // + if (InputBuffer[CharsToCopy - 1] == '\r') { + + InputBuffer[CharsToCopy - 1] = '\0'; + + } else { + + InputBuffer[CharsToCopy] = '\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; + UINT32 Data1; + UINT32 Data2; + UINT32 Data3; + UINT16 Data4[8]; + + if (AsciiGuidBuffer == NULL || GuidBuffer == NULL) { + return EFI_INVALID_PARAMETER; + } + // + // Check Guid Format strictly xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + // + for (Index = 0; AsciiGuidBuffer[Index] != '\0' && Index < 37; Index ++) { + if (Index == 8 || Index == 13 || Index == 18 || Index == 23) { + if (AsciiGuidBuffer[Index] != '-') { + break; + } + } else { + if (((AsciiGuidBuffer[Index] >= '0') && (AsciiGuidBuffer[Index] <= '9')) || + ((AsciiGuidBuffer[Index] >= 'a') && (AsciiGuidBuffer[Index] <= 'f')) || + ((AsciiGuidBuffer[Index] >= 'A') && (AsciiGuidBuffer[Index] <= 'F'))) { + continue; + } else { + break; + } + } + } + + if (Index < 36 || AsciiGuidBuffer[36] != '\0') { + Error (NULL, 0, 1003, "Invalid option value", "Incorrect GUID \"%s\"\n Correct Format \"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\"", AsciiGuidBuffer); + return EFI_ABORTED; + } + + // + // Scan the guid string into the buffer + // + Index = sscanf ( + AsciiGuidBuffer, + "%08x-%04x-%04x-%02hx%02hx-%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) { + Error (NULL, 0, 1003, "Invalid option value", "Incorrect GUID \"%s\"\n Correct Format \"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\"", 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; + + // + // Check input paramter + // + if (AsciiString == NULL || ReturnValue == NULL) { + return EFI_INVALID_PARAMETER; + } + // + // 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/BaseTools/Source/C/Common/ParseInf.h b/BaseTools/Source/C/Common/ParseInf.h new file mode 100644 index 0000000000..af532b8a18 --- /dev/null +++ b/BaseTools/Source/C/Common/ParseInf.h @@ -0,0 +1,230 @@ +/** @file + +Copyright (c) 2004 - 2008, 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 +#include +#include +#include + +#ifndef _MAX_PATH +#define _MAX_PATH 500 +#endif + + +// +// 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/BaseTools/Source/C/Common/PeCoffLib.h b/BaseTools/Source/C/Common/PeCoffLib.h new file mode 100644 index 0000000000..fc2e4cafc9 --- /dev/null +++ b/BaseTools/Source/C/Common/PeCoffLib.h @@ -0,0 +1,137 @@ +/** @file + Function prototypes and defines on 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 + ) +; + +VOID * +EFIAPI +PeCoffLoaderGetPdbPointer ( + IN VOID *Pe32Data + ) +; +#endif diff --git a/BaseTools/Source/C/Common/PeCoffLoaderEx.c b/BaseTools/Source/C/Common/PeCoffLoaderEx.c new file mode 100644 index 0000000000..fedc0941cb --- /dev/null +++ b/BaseTools/Source/C/Common/PeCoffLoaderEx.c @@ -0,0 +1,317 @@ +/** @file + +Copyright (c) 2004 - 2008, 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: + + IA32, X64 and IPF Specific relocation fixups + +Revision History + +--*/ + +#include +#include +#include "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 +PeCoffLoaderRelocateIa32Image ( + 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; +} + +RETURN_STATUS +PeCoffLoaderRelocateIpfImage ( + 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; +} + +RETURN_STATUS +PeCoffLoaderRelocateX64Image ( + IN UINT16 *Reloc, + IN OUT CHAR8 *Fixup, + IN OUT CHAR8 **FixupData, + IN UINT64 Adjust + ) +/** + Performs an x64 specific relocation fixup + + @param Reloc Pointer to the relocation record + @param Fixup Pointer to the address to fix up + @param FixupData Pointer to a buffer to log the fixups + @param Adjust The offset to adjust the fixup + + @retval RETURN_SUCCESS Success to perform relocation + @retval RETURN_UNSUPPORTED Unsupported. +**/ +{ + 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/BaseTools/Source/C/Common/SimpleFileParsing.c b/BaseTools/Source/C/Common/SimpleFileParsing.c new file mode 100644 index 0000000000..52ec129193 --- /dev/null +++ b/BaseTools/Source/C/Common/SimpleFileParsing.c @@ -0,0 +1,1443 @@ +/** @file + +Copyright (c) 2004 - 2008, 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 +#include +#include +#include + +#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 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; + CHAR8 *FileBuffer; + CHAR8 *FileBufferPtr; + UINTN FileSize; + CHAR8 FileName[MAX_PATH]; + UINTN LineNum; + BOOLEAN EndOfFile; + BOOLEAN SkipToHash; + struct _SOURCE_FILE *Previous; + struct _SOURCE_FILE *Next; + CHAR8 ControlCharacter; +} SOURCE_FILE; + +typedef struct { + CHAR8 *FileBufferPtr; +} FILE_POSITION; + +// +// Keep all our module globals in this structure +// +STATIC struct { + SOURCE_FILE SourceFile; + BOOLEAN VerboseFile; + BOOLEAN VerboseToken; +} mGlobals; + +STATIC +UINTN +t_strcmp ( + CHAR8 *Buffer, + CHAR8 *Str + ); + +STATIC +UINTN +t_strncmp ( + CHAR8 *Str1, + CHAR8 *Str2, + INTN Len + ); + +STATIC +UINTN +t_strlen ( + CHAR8 *Str + ); + +STATIC +VOID +RewindFile ( + SOURCE_FILE *SourceFile + ); + +STATIC +BOOLEAN +IsWhiteSpace ( + SOURCE_FILE *SourceFile + ); + +STATIC +UINTN +SkipWhiteSpace ( + SOURCE_FILE *SourceFile + ); + +STATIC +BOOLEAN +EndOfFile ( + SOURCE_FILE *SourceFile + ); + +STATIC +VOID +PreprocessFile ( + SOURCE_FILE *SourceFile + ); + +STATIC +CHAR8 * +t_strcpy ( + CHAR8 *Dest, + CHAR8 *Src + ); + +STATIC +STATUS +ProcessIncludeFile ( + SOURCE_FILE *SourceFile, + SOURCE_FILE *ParentSourceFile + ); + +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; +} + +UINTN +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; +} + +CHAR8 * +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 ( + CHAR8 *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 ( + CHAR8 *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. + +--*/ +{ + UINTN 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 ( + CHAR8 *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. + +--*/ +{ + UINTN 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 ( + CHAR8 *Str, + UINTN 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. + +--*/ +{ + UINTN Index; + CHAR8 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 ( + CHAR8 *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 ( + CHAR8 *Str + ) +{ + UINTN Len; + CHAR8 *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 ( + UINTN *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 Val; + + 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", &Val); + *Value = Val; + 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 UINTN 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.VerboseFile) { + fprintf (stdout, "%*cProcessing file '%s'\n", (INT32)NestDepth * 2, ' ', SourceFile->FileName); + fprintf (stdout, "Parent source file = '%s'\n", ParentSourceFile->FileName); + } + + // + // Make sure we didn't exceed our maximum nesting depth + // + if (NestDepth > MAX_NEST_DEPTH) { + Error (NULL, 0, 3001, "Not Supported", "%s exceeeds max nesting depth (%d)", SourceFile->FileName, 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", (INT32)SourceFile->FileSize, (UINT32)SourceFile->FileSize); + } + + fseek (SourceFile->Fptr, 0, SEEK_SET); + SourceFile->FileBuffer = (CHAR8 *) malloc (SourceFile->FileSize + sizeof (CHAR8 )); + if (SourceFile->FileBuffer == NULL) { + Error (NULL, 0, 4001, "Resource: memory cannot be allocated", NULL); + return STATUS_ERROR; + } + + fread ((VOID *) SourceFile->FileBuffer, SourceFile->FileSize, 1, SourceFile->Fptr); + SourceFile->FileBuffer[(SourceFile->FileSize / sizeof (CHAR8 ))] = 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", (INT32)SourceFile->FileSize, (UINT32)SourceFile->FileSize); + RewindFile (SourceFile); + } +} + +BOOLEAN +SFPGetQuotedString ( + CHAR8 *Str, + INTN 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 +CHAR8 * +GetQuotedString ( + SOURCE_FILE *SourceFile, + BOOLEAN Optional + ) +{ + CHAR8 *String; + CHAR8 *Start; + CHAR8 *Ptr; + UINTN 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 = (CHAR8 *) malloc ((Len + 1) * sizeof (CHAR8 )); + if (String == NULL) { + Error (NULL, 0, 4001, "Resource: memory cannot be allocated", 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 (CHAR8 )) { + SourceFile->EndOfFile = TRUE; + return TRUE; + } + + if (SourceFile->EndOfFile) { + return TRUE; + } + + return FALSE; +} + +#if 0 +STATIC +VOID +ProcessTokenInclude ( + SOURCE_FILE *SourceFile + ) +{ + CHAR8 IncludeFileName[MAX_PATH]; + CHAR8 *To; + UINTN 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 = (CHAR8 ) SourceFile->FileBufferPtr[0]; + To++; + } + + SourceFile->FileBufferPtr++; + } + + if (!ReportedError) { + *To = 0; + memset ((CHAR8 *) &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; + } +} + +UINTN +SkipWhiteSpace ( + SOURCE_FILE *SourceFile + ) +{ + UINTN 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 +UINTN +t_strcmp ( + CHAR8 *Buffer, + CHAR8 *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 + +--*/ +{ + UINTN Len; + + Len = 0; + while (*Str && (*Str == *Buffer)) { + Buffer++; + Str++; + Len++; + } + + if (*Str) { + return 0; + } + + return Len; +} + +STATIC +UINTN +t_strlen ( + CHAR8 *Str + ) +{ + UINTN Len; + Len = 0; + while (*Str) { + Len++; + Str++; + } + + return Len; +} + +STATIC +UINTN +t_strncmp ( + CHAR8 *Str1, + CHAR8 *Str2, + INTN Len + ) +{ + while (Len > 0) { + if (*Str1 != *Str2) { + return Len; + } + + Len--; + Str1++; + Str2++; + } + + return 0; +} + +STATIC +CHAR8 * +t_strcpy ( + CHAR8 *Dest, + CHAR8 *Src + ) +{ + CHAR8 *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 ( + CHAR8 *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 ( + INTN 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; + CHAR8 TempString[20]; + CHAR8 TempString2[3]; + CHAR8 *From; + CHAR8 *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/BaseTools/Source/C/Common/SimpleFileParsing.h b/BaseTools/Source/C/Common/SimpleFileParsing.h new file mode 100644 index 0000000000..7b33727d68 --- /dev/null +++ b/BaseTools/Source/C/Common/SimpleFileParsing.h @@ -0,0 +1,117 @@ +/** @file + +Copyright (c) 2004 - 2008, 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 + +STATUS +SFPInit ( + VOID + ) +; + +STATUS +SFPOpenFile ( + CHAR8 *FileName + ) +; + +BOOLEAN +SFPIsKeyword ( + CHAR8 *Str + ) +; + +BOOLEAN +SFPIsToken ( + CHAR8 *Str + ) +; + +BOOLEAN +SFPGetNextToken ( + CHAR8 *Str, + UINTN Len + ) +; + +BOOLEAN +SFPGetGuidToken ( + CHAR8 *Str, + UINT32 Len + ) +; + +#define PARSE_GUID_STYLE_5_FIELDS 0 + +BOOLEAN +SFPGetGuid ( + INTN GuidStyle, + EFI_GUID *Value + ) +; + +BOOLEAN +SFPSkipToToken ( + CHAR8 *Str + ) +; + +BOOLEAN +SFPGetNumber ( + UINTN *Value + ) +; + +BOOLEAN +SFPGetQuotedString ( + CHAR8 *Str, + INTN Length + ) +; + +BOOLEAN +SFPIsEOF ( + VOID + ) +; + +STATUS +SFPCloseFile ( + VOID + ) +; + +UINTN +SFPGetLineNumber ( + VOID + ) +; + +CHAR8 * +SFPGetFileName ( + VOID + ) +; + +#endif // #ifndef _SIMPLE_FILE_PARSING_H_ diff --git a/BaseTools/Source/C/Common/StringFuncs.c b/BaseTools/Source/C/Common/StringFuncs.c new file mode 100644 index 0000000000..b0ad2d165e --- /dev/null +++ b/BaseTools/Source/C/Common/StringFuncs.c @@ -0,0 +1,426 @@ +/** @file + +Copyright (c) 2007 - 2008, 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: + + StringFuncs.c + +Abstract: + + Function prototypes and defines for string routines. + +**/ + +#include +#include +#include "StringFuncs.h" + +// +// Functions implementations +// + +CHAR8* +CloneString ( + IN CHAR8 *String + ) +/*++ + +Routine Description: + + Allocates a new string and copies 'String' to clone it + +Arguments: + + String The string to clone + +Returns: + + CHAR8* - NULL if there are not enough resources + +--*/ +{ + CHAR8* NewString; + + NewString = malloc (strlen (String) + 1); + if (NewString != NULL) { + strcpy (NewString, String); + } + + return NewString; +} + + +EFI_STATUS +StripInfDscStringInPlace ( + IN CHAR8 *String + ) +/*++ + +Routine Description: + + Remove all comments, leading and trailing whitespace from the string. + +Arguments: + + String The string to 'strip' + +Returns: + + EFI_STATUS + +--*/ +{ + CHAR8 *Pos; + + if (String == NULL) { + return EFI_INVALID_PARAMETER; + } + + // + // Remove leading whitespace + // + for (Pos = String; isspace (*Pos); Pos++) { + } + if (Pos != String) { + memmove (String, Pos, strlen (Pos) + 1); + } + + // + // Comment BUGBUGs! + // + // What about strings? Comment characters are okay in strings. + // What about multiline comments? + // + + Pos = (CHAR8 *) strstr (String, "//"); + if (Pos != NULL) { + *Pos = '\0'; + } + + Pos = (CHAR8 *) strchr (String, '#'); + if (Pos != NULL) { + *Pos = '\0'; + } + + // + // Remove trailing whitespace + // + for (Pos = String + strlen (String); + ((Pos - 1) >= String) && (isspace (*(Pos - 1))); + Pos-- + ) { + } + *Pos = '\0'; + + return EFI_SUCCESS; +} + + +STRING_LIST* +SplitStringByWhitespace ( + IN CHAR8 *String + ) +/*++ + +Routine Description: + + Creates and returns a 'split' STRING_LIST by splitting the string + on whitespace boundaries. + +Arguments: + + String The string to 'split' + +Returns: + + EFI_STATUS + +--*/ +{ + CHAR8 *Pos; + CHAR8 *EndOfSubString; + CHAR8 *EndOfString; + STRING_LIST *Output; + UINTN Item; + + String = CloneString (String); + if (String == NULL) { + return NULL; + } + EndOfString = String + strlen (String); + + Output = NewStringList (); + + for (Pos = String, Item = 0; Pos < EndOfString; Item++) { + while (isspace (*Pos)) { + Pos++; + } + + for (EndOfSubString=Pos; + (*EndOfSubString != '\0') && !isspace (*EndOfSubString); + EndOfSubString++ + ) { + } + + if (EndOfSubString == Pos) { + break; + } + + *EndOfSubString = '\0'; + + AppendCopyOfStringToList (&Output, Pos); + + Pos = EndOfSubString + 1; + } + + free (String); + return Output; +} + + +STRING_LIST* +NewStringList ( + ) +/*++ + +Routine Description: + + Creates a new STRING_LIST with 0 strings. + +Returns: + + STRING_LIST* - Null if there is not enough resources to create the object. + +--*/ +{ + STRING_LIST *NewList; + NewList = AllocateStringListStruct (0); + if (NewList != NULL) { + NewList->Count = 0; + } + return NewList; +} + + +EFI_STATUS +AppendCopyOfStringToList ( + IN OUT STRING_LIST **StringList, + IN CHAR8 *String + ) +/*++ + +Routine Description: + + Adds String to StringList. A new copy of String is made before it is + added to StringList. + +Returns: + + EFI_STATUS + +--*/ +{ + STRING_LIST *OldList; + STRING_LIST *NewList; + CHAR8 *NewString; + + OldList = *StringList; + NewList = AllocateStringListStruct (OldList->Count + 1); + if (NewList == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + NewString = CloneString (String); + if (NewString == NULL) { + free (NewList); + return EFI_OUT_OF_RESOURCES; + } + + memcpy ( + NewList->Strings, + OldList->Strings, + sizeof (OldList->Strings[0]) * OldList->Count + ); + NewList->Count = OldList->Count + 1; + NewList->Strings[OldList->Count] = NewString; + + *StringList = NewList; + free (OldList); + + return EFI_SUCCESS; +} + + +EFI_STATUS +RemoveLastStringFromList ( + IN STRING_LIST *StringList + ) +/*++ + +Routine Description: + + Removes the last string from StringList and frees the memory associated + with it. + +Arguments: + + StringList The string list to remove the string from + +Returns: + + EFI_STATUS + +--*/ +{ + if (StringList->Count == 0) { + return EFI_INVALID_PARAMETER; + } + + free (StringList->Strings[StringList->Count - 1]); + StringList->Count--; + return EFI_SUCCESS; +} + + +STRING_LIST* +AllocateStringListStruct ( + IN UINTN StringCount + ) +/*++ + +Routine Description: + + Allocates a STRING_LIST structure that can store StringCount strings. + +Arguments: + + StringCount The number of strings that need to be stored + +Returns: + + EFI_STATUS + +--*/ +{ + return malloc (OFFSET_OF(STRING_LIST, Strings[StringCount + 1])); +} + + +VOID +FreeStringList ( + IN STRING_LIST *StringList + ) +/*++ + +Routine Description: + + Frees all memory associated with StringList. + +Arguments: + + StringList The string list to free + +Returns: + + VOID +--*/ +{ + while (StringList->Count > 0) { + RemoveLastStringFromList (StringList); + } + + free (StringList); +} + + +CHAR8* +StringListToString ( + IN STRING_LIST *StringList + ) +/*++ + +Routine Description: + + Generates a string that represents the STRING_LIST + +Arguments: + + StringList The string list to convert to a string + +Returns: + + CHAR8* - The string list represented with a single string. The returned + string must be freed by the caller. + +--*/ +{ + UINTN Count; + UINTN Length; + CHAR8 *NewString; + + Length = 2; + for (Count = 0; Count < StringList->Count; Count++) { + if (Count > 0) { + Length += 2; + } + Length += strlen (StringList->Strings[Count]) + 2; + } + + NewString = malloc (Length + 1); + if (NewString == NULL) { + return NewString; + } + NewString[0] = '\0'; + + strcat (NewString, "["); + for (Count = 0; Count < StringList->Count; Count++) { + if (Count > 0) { + strcat (NewString, ", "); + } + strcat (NewString, "\""); + strcat (NewString, StringList->Strings[Count]); + strcat (NewString, "\""); + } + strcat (NewString, "]"); + + return NewString; +} + + +VOID +PrintStringList ( + IN STRING_LIST *StringList + ) +/*++ + +Routine Description: + + Prints out the string list + +Arguments: + + StringList The string list to print + +Returns: + + EFI_STATUS + +--*/ +{ + CHAR8* String; + String = StringListToString (StringList); + if (String != NULL) { + printf ("%s", String); + free (String); + } +} + + diff --git a/BaseTools/Source/C/Common/StringFuncs.h b/BaseTools/Source/C/Common/StringFuncs.h new file mode 100644 index 0000000000..cf18460c4c --- /dev/null +++ b/BaseTools/Source/C/Common/StringFuncs.h @@ -0,0 +1,257 @@ +/** + +Copyright (c) 2007 - 2008, 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: + + StringFuncs.h + +Abstract: + + String routines implementation. + +**/ + +#ifndef _EFI_STRING_FUNCS_H +#define _EFI_STRING_FUNCS_H + +#include +#include +#include + +// +// Common data structures +// +typedef struct { + UINTN Count; + // + // Actually this array can be 0 or more items (based on Count) + // + CHAR8* Strings[1]; +} STRING_LIST; + + +// +// Functions declarations +// + +CHAR8* +CloneString ( + IN CHAR8 *String + ) +; +/** + +Routine Description: + + Allocates a new string and copies 'String' to clone it + +Arguments: + + String The string to clone + +Returns: + + CHAR8* - NULL if there are not enough resources + +**/ + + +EFI_STATUS +StripInfDscStringInPlace ( + IN CHAR8 *String + ) +; +/** + +Routine Description: + + Remove all comments, leading and trailing whitespace from the string. + +Arguments: + + Strin The string to 'strip' + +Returns: + + EFI_STATUS + +**/ + + +STRING_LIST* +SplitStringByWhitespace ( + IN CHAR8 *String + ) +; +/** + +Routine Description: + + Creates and returns a 'split' STRING_LIST by splitting the string + on whitespace boundaries. + +Arguments: + + String The string to 'split' + +Returns: + + EFI_STATUS + +**/ + + +STRING_LIST* +NewStringList ( + ) +; +/** + +Routine Description: + + Creates a new STRING_LIST with 0 strings. + +Returns: + + STRING_LIST* - Null if there is not enough resources to create the object. + +**/ + + +EFI_STATUS +AppendCopyOfStringToList ( + IN OUT STRING_LIST **StringList, + IN CHAR8 *String + ) +; +/** + +Routine Description: + + Adds String to StringList. A new copy of String is made before it is + added to StringList. + +Returns: + + EFI_STATUS + +**/ + + +EFI_STATUS +RemoveLastStringFromList ( + IN STRING_LIST *StringList + ) +; +/** + +Routine Description: + + Removes the last string from StringList and frees the memory associated + with it. + +Arguments: + + StringList The string list to remove the string from + +Returns: + + EFI_STATUS + +**/ + + +STRING_LIST* +AllocateStringListStruct ( + IN UINTN StringCount + ) +; +/** + +Routine Description: + + Allocates a STRING_LIST structure that can store StringCount strings. + +Arguments: + + StringCount The number of strings that need to be stored + +Returns: + + EFI_STATUS + +**/ + + +VOID +FreeStringList ( + IN STRING_LIST *StringList + ) +; +/** + +Routine Description: + + Frees all memory associated with StringList. + +Arguments: + + StringList The string list to free + +Returns: + + EFI_STATUS + +**/ + + +CHAR8* +StringListToString ( + IN STRING_LIST *StringList + ) +; +/** + +Routine Description: + + Generates a string that represents the STRING_LIST + +Arguments: + + StringList The string list to convert to a string + +Returns: + + CHAR8* - The string list represented with a single string. The returned + string must be freed by the caller. + +**/ + + +VOID +PrintStringList ( + IN STRING_LIST *StringList + ) +; +/** + +Routine Description: + + Prints out the string list + +Arguments: + + StringList The string list to print + +**/ + + +#endif diff --git a/BaseTools/Source/C/Common/TianoCompress.c b/BaseTools/Source/C/Common/TianoCompress.c new file mode 100644 index 0000000000..625f99eaca --- /dev/null +++ b/BaseTools/Source/C/Common/TianoCompress.c @@ -0,0 +1,1753 @@ +/** @file + +Copyright (c) 2006 - 2008, 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: + + TianoCompress.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 "Compress.h" + +// +// Macro Definitions +// +#undef UINT8_MAX +typedef INT32 NODE; +#define UINT8_MAX 0xff +#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], 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 +TianoCompress ( + IN UINT8 *SrcBuffer, + IN UINT32 SrcSize, + IN UINT8 *DstBuffer, + IN OUT UINT32 *DstSize + ) +/*++ + +Routine Description: + + The internal implementation of [Efi/Tiano]Compress(). + +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. + Version - The version of de/compression algorithm. + Version 1 for UEFI 2.0 de/compression algorithm. + Version 2 for Tiano de/compression algorithm. + +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_INVALID_PARAMETER - Parameter supplied is wrong. + +--*/ +{ + 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/BaseTools/Source/C/Common/WinNtInclude.h b/BaseTools/Source/C/Common/WinNtInclude.h new file mode 100644 index 0000000000..96c17993a1 --- /dev/null +++ b/BaseTools/Source/C/Common/WinNtInclude.h @@ -0,0 +1,73 @@ +/** @file + +Copyright (c) 2006 - 2008, 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__ + +#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" + +// +// 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) + +// +// 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 + +#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 + +#endif diff --git a/BaseTools/Source/C/EfiLdrImage/EfiLdrImage.c b/BaseTools/Source/C/EfiLdrImage/EfiLdrImage.c new file mode 100644 index 0000000000..3591a4d71b --- /dev/null +++ b/BaseTools/Source/C/EfiLdrImage/EfiLdrImage.c @@ -0,0 +1,329 @@ +/** @file + +Copyright 2006 - 2008, 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: + + efildrimage.c + +Abstract: + + Creates and EFILDR image. + This tool combines several PE Image files together using following format denoted as EBNF: + FILE := EFILDR_HEADER + EFILDR_IMAGE + + + + The order of EFILDR_IMAGE is same as the order of placing PeImageFileContent. + +Revision History + +**/ + + +#include +#include +#include +#include "ParseInf.h" +#include "CommonLib.h" +#include "EfiUtilityMsgs.h" + +#define MAX_PE_IMAGES 63 +#define FILE_TYPE_FIXED_LOADER 0 +#define FILE_TYPE_RELOCATABLE_PE_IMAGE 1 + +typedef struct { + UINT32 CheckSum; + UINT32 Offset; + UINT32 Length; + UINT8 FileName[52]; +} EFILDR_IMAGE; + +typedef struct { + UINT32 Signature; + UINT32 HeaderCheckSum; + UINT32 FileLength; + UINT32 NumberOfImages; +} EFILDR_HEADER; + +// +// Utility Name +// +#define UTILITY_NAME "EfiLdrImage" + +// +// Utility version information +// +#define UTILITY_MAJOR_VERSION 0 +#define UTILITY_MINOR_VERSION 1 + +void +Version ( + void + ) +/*++ + +Routine Description: + + Displays the standard utility information to SDTOUT + +Arguments: + + None + +Returns: + + None + +--*/ +{ + printf ("%s v%d.%d -Utility to break a file into two pieces at the request offset.\n", UTILITY_NAME, UTILITY_MAJOR_VERSION, UTILITY_MINOR_VERSION); + printf ("Copyright (c) 1999-2007 Intel Corporation. All rights reserved.\n"); +} + +VOID +Usage ( + VOID + ) +{ + printf ("Usage: EfiLdrImage -o OutImage LoaderImage PeImage1 PeImage2 ... PeImageN\n"); + exit (1); +} + +EFI_STATUS +CountVerboseLevel ( + IN CONST CHAR8* VerboseLevelString, + IN CONST UINT64 Length, + OUT UINT64 *ReturnValue +) +{ + UINT64 i = 0; + for (;i < Length; ++i) { + if (VerboseLevelString[i] != 'v' && VerboseLevelString[i] != 'V') { + return EFI_ABORTED; + } + ++(*ReturnValue); + } + + return EFI_SUCCESS; +} + +UINT64 +FCopyFile ( + FILE *in, + FILE *out + ) +/*++ +Routine Description: + Write all the content of input file to output file. + +Arguments: + in - input file pointer + out - output file pointer + +Return: + UINT64 : file size of input file +--*/ +{ + UINT64 filesize, offset, length; + CHAR8 Buffer[8*1024]; + + fseek (in, 0, SEEK_END); + filesize = ftell(in); + + fseek (in, 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; + } + + return filesize; +} + + +int +main ( + int argc, + char *argv[] + ) +/*++ + +Routine Description: + + +Arguments: + + +Returns: + + +--*/ +{ + UINT64 i; + UINT64 filesize; + FILE *fpIn, *fpOut; + EFILDR_HEADER EfiLdrHeader; + EFILDR_IMAGE EfiLdrImage[MAX_PE_IMAGES]; + CHAR8* OutputFileName = NULL; + CHAR8* InputFileNames[MAX_PE_IMAGES + 1]; + UINT8 InputFileCount = 0; + BOOLEAN QuietFlag = FALSE; + UINT64 DebugLevel = 0; + UINT64 VerboseLevel = 0; + EFI_STATUS Status = EFI_SUCCESS; + + SetUtilityName (UTILITY_NAME); + + if (argc == 1) { + Usage(); + return STATUS_ERROR; + } + + argc --; + argv ++; + + if ((stricmp (argv[0], "-h") == 0) || (stricmp (argv[0], "--help") == 0)) { + Usage(); + return STATUS_SUCCESS; + } + + if (stricmp (argv[0], "--version") == 0) { + Version(); + return STATUS_SUCCESS; + } + + while (argc > 0) { + + if ((stricmp (argv[0], "-o") == 0) || (stricmp (argv[0], "--output") == 0)) { + OutputFileName = argv[1]; + if (OutputFileName == NULL) { + Error (NULL, 0, 1003, "Invalid option value", "Output file can't be null"); + return STATUS_ERROR; + } + argc -= 2; + argv += 2; + continue; + } + + if ((stricmp (argv[0], "-q") == 0) || (stricmp (argv[0], "--quiet") == 0)) { + QuietFlag = TRUE; + argc --; + argv ++; + continue; + } + + if ((strlen(argv[0]) >= 2 && argv[0][0] == '-' && (argv[0][1] == 'v' || argv[0][1] == 'V')) || (stricmp (argv[0], "--verbose") == 0)) { + VerboseLevel = 1; + if (strlen(argv[0]) > 2) { + Status = CountVerboseLevel (&argv[0][2], strlen(argv[0]) - 2, &VerboseLevel); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 1003, "Invalid option value", argv[0]); + return STATUS_ERROR; + } + } + + argc --; + argv ++; + continue; + } + + if ((stricmp (argv[0], "-d") == 0) || (stricmp (argv[0], "--debug") == 0)) { + Status = AsciiStringToUint64 (argv[1], FALSE, &DebugLevel); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]); + return STATUS_ERROR; + } + argc -= 2; + argv += 2; + continue; + } + // + // Don't recognize the paramter, should be regarded as the input file name. + // + InputFileNames[InputFileCount] = argv[0]; + InputFileCount++; + argc--; + argv++; + } + + if (InputFileCount == 0) { + Error (NULL, 0, 1001, "Missing option", "No input file"); + return STATUS_ERROR; + } + // + // Open output file for write + // + if (OutputFileName == NULL) { + Error (NULL, 0, 1001, "Missing option", "No output file"); + return STATUS_ERROR; + } + + fpOut = fopen(OutputFileName, "w+b"); + if (!fpOut) { + Error (NULL, 0, 0001, "Could not open output file", OutputFileName); + return STATUS_ERROR; + } + + memset (&EfiLdrHeader, 0, sizeof (EfiLdrHeader)); + memset (&EfiLdrImage, 0, sizeof (EFILDR_IMAGE) * (InputFileCount)); + + memcpy (&EfiLdrHeader.Signature, "EFIL", 4); + EfiLdrHeader.FileLength = sizeof(EFILDR_HEADER) + sizeof(EFILDR_IMAGE)*(InputFileCount); + + // + // Skip the file header first + // + fseek (fpOut, EfiLdrHeader.FileLength, SEEK_SET); + + // + // copy all the input files to the output file + // + for(i=0;iNext) { + if ((Ptr0 = strstr ((CONST CHAR8 *)FList->FileName, DEFAULT_OUTPUT_EXTENSION)) != NULL) { + DumpImage (mOptions.FileList); + goto BailOut; + } else { + Error (NULL, 0, 1002, "No PciRom input file", "No *.rom input file"); + 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; + Error (NULL, 0, 1002, "Invalid input paramter", "Input and output file names must be different - %s = %s.", FList->FileName, mOptions.OutFileName); + goto BailOut; + } + } + // + // Now open our output file + // + if ((FptrOut = fopen (mOptions.OutFileName, "wb")) == NULL) { + Error (NULL, 0, 0001, "Error opening file", "Error opening file %s", 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) != 0) { + if (mOptions.Verbose) { + VerboseMsg("Processing EFI file %s\n", FList->FileName); + } + + Status = ProcessEfiFile (FptrOut, FList, mOptions.VendId, mOptions.DevId, &Size); + } else if ((FList->FileFlags & FILE_FLAG_BINARY) !=0 ) { + if (mOptions.Verbose) { + VerboseMsg("Processing binary file %s\n", FList->FileName); + } + + Status = ProcessBinFile (FptrOut, FList, &Size); + } else { + Error (NULL, 0, 2000, "Invalid parameter", "File type not specified, it must be either an EFI or binary file: %s.", FList->FileName); + Status = STATUS_ERROR; + } + + if (mOptions.Verbose) { + VerboseMsg(" Output size = 0x%X\n", Size); + } + + if (Status != STATUS_SUCCESS) { + break; + } + + TotalSize += Size; + } + // + // Check total size + // + if (TotalSize > MAX_OPTION_ROM_SIZE) { + Error (NULL, 0, 2000, "Invalid paramter", "Option ROM image size exceeds limit of 0x%X bytes.", MAX_OPTION_ROM_SIZE); + Status = STATUS_ERROR; + } + +BailOut: + if (Status == STATUS_SUCCESS) { + if (FptrOut != NULL) { + fclose (FptrOut); + } + // + // Clean up our file list + // + while (mOptions.FileList != NULL) { + FList = mOptions.FileList->Next; + free (mOptions.FileList); + mOptions.FileList = FList; + } + } + + if (mOptions.Verbose) { + VerboseMsg("%s tool done with return code is 0x%x.\n", UTILITY_NAME, GetUtilityStatus ()); + } + + return GetUtilityStatus (); +} + +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 *PciDs23; + PCI_3_0_DATA_STRUCTURE *PciDs30; + UINT32 Index; + UINT8 ByteCheckSum; + + + Status = STATUS_SUCCESS; + + // + // Try to open the input file + // + if ((InFptr = fopen (InFile->FileName, "rb")) == NULL) { + Error (NULL, 0, 0001, "Error opening file", 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) { + VerboseMsg(" File size = 0x%X\n", FileSize); + } + + fseek (InFptr, 0, SEEK_SET); + Buffer = (UINT8 *) malloc (FileSize); + if (Buffer == NULL) { + Error (NULL, 0, 4003, "Resource", "memory cannot be allocated!"); + Status = STATUS_ERROR; + goto BailOut; + } + + if (fread (Buffer, FileSize, 1, InFptr) != 1) { + Error (NULL, 0, 2000, "Invalid", "Failed to read all bytes from input file."); + 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) { + Error (NULL, 0, 3001, "Invalid", "Option ROM image %s size exceeds limit of 0x%X bytes.", 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) { + Error (NULL, 0, 2000, "Invalid parameter", "ROM image file has an invalid ROM signature."); + 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)) { + Error (NULL, 0, 2000, "Invalid parameter", "Invalid PCI data structure offset."); + Status = STATUS_ERROR; + goto BailOut; + } + + // + // Check the header is conform to PCI2.3 or PCI3.0 + // + if (mOptions.Pci23 == 1) { + PciDs23 = (PCI_DATA_STRUCTURE *) (Buffer + RomHdr->PcirOffset); + if (PciDs23->Signature != PCI_DATA_STRUCTURE_SIGNATURE) { + Error (NULL, 0, 2000, "Invalid parameter", "PCI data structure has an invalid signature."); + Status = STATUS_ERROR; + goto BailOut; + } + } else { + // + // Default setting is PCI3.0 header + // + PciDs30 = (PCI_3_0_DATA_STRUCTURE *)(Buffer + RomHdr->PcirOffset); + if (PciDs30->Signature != PCI_DATA_STRUCTURE_SIGNATURE) { + Error (NULL, 0, 2000, "Invalid parameter", "PCI data structure has an invalid signature."); + Status = STATUS_ERROR; + goto BailOut; + } + } + + // + // ReSet Option Rom size + // + if (mOptions.Pci23 == 1) { + PciDs23->ImageLength = (UINT16) (TotalSize / 512); + } else { + PciDs30->ImageLength = (UINT16) (TotalSize / 512); + } + + // + // If this is the last image, then set the LAST bit unless requested not + // to via the command-line -n argument. Otherwise, make sure you clear it. + // + if ((InFile->Next == NULL) && (mOptions.NoLast == 0)) { + if (mOptions.Pci23 == 1) { + PciDs23->Indicator = INDICATOR_LAST; + } else { + PciDs30->Indicator = INDICATOR_LAST; + } + } else { + if (mOptions.Pci23 == 1) { + PciDs23->Indicator = 0; + } else { + PciDs30->Indicator = 0; + } + } + + ByteCheckSum = 0; + for (Index = 0; Index < FileSize - 1; Index++) { + ByteCheckSum = (UINT8) (ByteCheckSum + Buffer[Index]); + } + + Buffer[FileSize - 1] = (UINT8) ((~ByteCheckSum) + 1); + if (mOptions.Verbose) { + VerboseMsg(" Checksum = %02x\n\n", (UINT32) Buffer[FileSize - 1]); + } + + // + // Now copy the input file contents out to the output file + // + if (fwrite (Buffer, FileSize, 1, OutFptr) != 1) { + Error (NULL, 0, 0005, "Failed to write all file bytes to output file.", NULL); + 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) { + Error (NULL, 0, 0003, "Error", "Error parsing file: %s", 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 PciDs23; + PCI_3_0_DATA_STRUCTURE PciDs30; + 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) { + Error (NULL, 0, 0001, "Open file error", "Error opening file: %s", 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; + } + + // + // For Pci3.0 to use the different data structure. + // + if (mOptions.Pci23 == 1) { + HeaderSize = sizeof (PCI_DATA_STRUCTURE) + HeaderPadBytes + sizeof (EFI_PCI_EXPANSION_ROM_HEADER); + } else { + HeaderSize = sizeof (PCI_3_0_DATA_STRUCTURE) + HeaderPadBytes + sizeof (EFI_PCI_EXPANSION_ROM_HEADER); + } + + if (mOptions.Verbose) { + VerboseMsg(" 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 = (UINT8 *) malloc (FileSize); + if (Buffer == NULL) { + Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!"); + Status = STATUS_ERROR; + goto BailOut; + } + + fseek (InFptr, 0, SEEK_SET); + if (fread (Buffer, FileSize, 1, InFptr) != 1) { + Error (NULL, 0, 0004, "Error reading file", "File %s", InFile->FileName); + 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) != 0) { + // + // Allocate a buffer into which we can compress the image, compress it, + // and use that size as the new size. + // + CompressedBuffer = (UINT8 *) malloc (FileSize); + if (CompressedBuffer == NULL) { + Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!"); + Status = STATUS_ERROR; + goto BailOut; + } + + CompressedFileSize = FileSize; + Status = EfiCompress (Buffer, FileSize, CompressedBuffer, &CompressedFileSize); + if (Status != STATUS_SUCCESS) { + Error (NULL, 0, 0007, "Error compressing file!", NULL); + goto BailOut; + } + // + // Now compute the size, then swap buffer pointers. + // + if (mOptions.Verbose) { + VerboseMsg(" 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) { + Error (NULL, 0, 2000, "Invalid", "Option ROM image %s size exceeds limit of 0x%X bytes.", 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 + // + if (mOptions.Pci23 == 1) { + memset (&PciDs23, 0, sizeof (PCI_DATA_STRUCTURE)); + } else { + memset (&PciDs30, 0, sizeof (PCI_3_0_DATA_STRUCTURE)); + } + + if (mOptions.Pci23 == 1) { + PciDs23.Signature = PCI_DATA_STRUCTURE_SIGNATURE; + PciDs23.VendorId = VendId; + PciDs23.DeviceId = DevId; + PciDs23.Length = (UINT16) sizeof (PCI_DATA_STRUCTURE); + PciDs23.Revision = 0; + // + // Class code and code revision from the command line (optional) + // + PciDs23.ClassCode[0] = (UINT8) InFile->ClassCode; + PciDs23.ClassCode[1] = (UINT8) (InFile->ClassCode >> 8); + PciDs23.ClassCode[2] = (UINT8) (InFile->ClassCode >> 16); + PciDs23.ImageLength = RomHdr.InitializationSize; + PciDs23.CodeRevision = InFile->CodeRevision; + PciDs23.CodeType = PCI_CODE_TYPE_EFI_IMAGE; + } else { + PciDs30.Signature = PCI_DATA_STRUCTURE_SIGNATURE; + PciDs30.VendorId = VendId; + PciDs30.DeviceId = DevId; + PciDs30.DeviceListOffset = 0; // to be fixed + PciDs30.Length = (UINT16) sizeof (PCI_3_0_DATA_STRUCTURE); + PciDs30.Revision = 0x3; + // + // Class code and code revision from the command line (optional) + // + PciDs30.ClassCode[0] = (UINT8) InFile->ClassCode; + PciDs30.ClassCode[1] = (UINT8) (InFile->ClassCode >> 8); + PciDs30.ClassCode[2] = (UINT8) (InFile->ClassCode >> 16); + PciDs30.ImageLength = RomHdr.InitializationSize; + PciDs30.CodeRevision = InFile->CodeRevision; + PciDs30.CodeType = PCI_CODE_TYPE_EFI_IMAGE; + PciDs30.MaxRuntimeImageLength = 0; // to be fixed + PciDs30.ConfigUtilityCodeHeaderOffset = 0; // to be fixed + PciDs30.DMTFCLPEntryPointOffset = 0; // to be fixed + } + // + // If this is the last image, then set the LAST bit unless requested not + // to via the command-line -n argument. + // + if ((InFile->Next == NULL) && (mOptions.NoLast == 0)) { + if (mOptions.Pci23 == 1) { + PciDs23.Indicator = INDICATOR_LAST; + } else { + PciDs30.Indicator = INDICATOR_LAST;} + } else { + if (mOptions.Pci23 == 1) { + PciDs23.Indicator = 0; + } else { + PciDs30.Indicator = 0; + } + } + // + // Write the ROM header to the output file + // + if (fwrite (&RomHdr, sizeof (RomHdr), 1, OutFptr) != 1) { + Error (NULL, 0, 0002, "Failed to write ROM header to output file!", NULL); + Status = STATUS_ERROR; + goto BailOut; + } + + // + // Write pad bytes to align the PciDs + // + while (HeaderPadBytes > 0) { + if (putc (0, OutFptr) == EOF) { + Error (NULL, 0, 0002, "Failed to write ROM header pad bytes to output file!", NULL); + Status = STATUS_ERROR; + goto BailOut; + } + + HeaderPadBytes--; + } + // + // Write the PCI data structure header to the output file + // + if (mOptions.Pci23 == 1) { + if (fwrite (&PciDs23, sizeof (PciDs23), 1, OutFptr) != 1) { + Error (NULL, 0, 0002, "Failed to write PCI ROM header to output file!", NULL); + Status = STATUS_ERROR; + goto BailOut; + } + } else { + if (fwrite (&PciDs30, sizeof (PciDs30), 1, OutFptr) != 1) { + Error (NULL, 0, 0002, "Failed to write PCI ROM header to output file!", NULL); + 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) { + Error (NULL, 0, 0002, "Failed to write all file bytes to output file!", NULL); + 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) { + Error (NULL, 0, 2000, "Failed to write trailing pad bytes output file!", NULL); + 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) { + Error (NULL, 0, 0003, "Error parsing", "Error parsing file: %s", InFile->FileName); + } + + return Status; +} + +static +int +CheckPE32File ( + FILE *Fptr, + UINT16 *MachineType, + UINT16 *SubSystem + ) +/*++ + +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_OPTIONAL_HEADER_UNION PeHdr; + + // + // 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, 0004, "Failed to read the DOS stub from the input file!", NULL); + return STATUS_ERROR; + } + // + // Check the magic number (0x5A4D) + // + if (DosHeader.e_magic != EFI_IMAGE_DOS_SIGNATURE) { + Error (NULL, 0, 2000, "Invalid parameter", "Input file does not appear to be a PE32 image (magic number)!"); + return STATUS_ERROR; + } + // + // Position into the file and check the PE signature + // + fseek (Fptr, (long) DosHeader.e_lfanew, SEEK_SET); + + // + // Read PE headers + // + if (fread (&PeHdr, sizeof (PeHdr), 1, Fptr) != 1) { + Error (NULL, 0, 0004, "Failed to read PE/COFF headers from input file!", NULL); + return STATUS_ERROR; + } + + + // + // Check the PE signature in the header "PE\0\0" + // + if (PeHdr.Pe32.Signature != EFI_IMAGE_NT_SIGNATURE) { + Error (NULL, 0, 2000, "Invalid parameter", "Input file does not appear to be a PE32 image (signature)!"); + return STATUS_ERROR; + } + + memcpy ((char *) MachineType, &PeHdr.Pe32.FileHeader.Machine, 2); + + if (PeHdr.Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) { + *SubSystem = PeHdr.Pe32.OptionalHeader.Subsystem; + } else if (PeHdr.Pe32Plus.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) { + *SubSystem = PeHdr.Pe32Plus.OptionalHeader.Subsystem; + } else { + Error (NULL, 0, 2000, "Invalid parameter", "Unable to find subsystem type!"); + return STATUS_ERROR; + } + + if (mOptions.Verbose) { + VerboseMsg(" Got subsystem = 0x%X from image\n", (int) *SubSystem); + } + + // + // File was successfully identified as a PE32 + // + 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; + EFI_STATUS Status; + BOOLEAN EfiRomFlag; + UINT64 TempValue; + + FileFlags = 0; + EfiRomFlag = FALSE; + + // + // 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; + } + + if ((stricmp(Argv[0], "-h") == 0) || (stricmp(Argv[0], "--help") == 0)) { + Usage(); + return STATUS_ERROR; + } + + if ((stricmp(Argv[0], "--version") == 0)) { + Version(); + return STATUS_ERROR; + } + + // + // Process until no more arguments + // + while (Argc > 0) { + if (Argv[0][0] == '-') { + // + // Vendor ID specified with -f + // + if (stricmp (Argv[0], "-f") == 0) { + // + // Make sure there's another parameter + // + Status = AsciiStringToUint64(Argv[1], FALSE, &TempValue); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 2000, "Invalid option value", "%s = %s", Argv[0], Argv[1]); + return 1; + } + if (TempValue >= 0x10000) { + Error (NULL, 0, 2000, "Invalid option value", "Vendor Id %s out of range!", Argv[1]); + return 1; + } + Options->VendId = (UINT16) TempValue; + Options->VendIdValid = 1; + + Argv++; + Argc--; + } else if (stricmp (Argv[0], "-i") == 0) { + // + // Device ID specified with -i + // Make sure there's another parameter + // + Status = AsciiStringToUint64(Argv[1], FALSE, &TempValue); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 2000, "Invalid option value", "%s = %s", Argv[0], Argv[1]); + return 1; + } + if (TempValue >= 0x10000) { + Error (NULL, 0, 2000, "Invalid option value", "Device Id %s out of range!", Argv[1]); + return 1; + } + Options->DevId = (UINT16) TempValue; + Options->DevIdValid = 1; + + Argv++; + Argc--; + } else if ((stricmp (Argv[0], "-o") == 0) || (stricmp (Argv[0], "--output") == 0)) { + // + // Output filename specified with -o + // Make sure there's another parameter + // + if (Argv[1] == NULL || Argv[1][0] == '-') { + Error (NULL, 0, 2000, "Invalid parameter", "Missing output file name with %s option!", Argv[0]); + return STATUS_ERROR; + } + strcpy (Options->OutFileName, Argv[1]); + + Argv++; + Argc--; + } else if ((stricmp (Argv[0], "-h") == 0) || (stricmp (Argv[0], "--help") == 0)) { + // + // Help option + // + Usage (); + return STATUS_ERROR; + } else if (stricmp (Argv[0], "-b") == 0) { + // + // Specify binary files with -b + // + FileFlags = FILE_FLAG_BINARY; + } else if ((stricmp (Argv[0], "-e") == 0) || (stricmp (Argv[0], "-ec") == 0)) { + // + // Specify EFI files with -e. Specify EFI-compressed with -c. + // + FileFlags = 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 -n + // + } else if (stricmp (Argv[0], "-n") == 0) { + Options->NoLast = 1; + } else if (((stricmp (Argv[0], "-v") == 0)) || ((stricmp (Argv[0], "--verbose") == 0))) { + // + // -v for verbose + // + Options->Verbose = 1; + } else if (stricmp (Argv[0], "--debug") == 0) { + Status = AsciiStringToUint64(Argv[1], FALSE, &DebugLevel); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 2000, "Invalid option value", "%s = %s", Argv[0], Argv[1]); + return 1; + } + if (DebugLevel > 9) { + Error (NULL, 0, 2000, "Invalid option value", "Debug Level range is 0-9, currnt input level is %d", Argv[1]); + return 1; + } + if (DebugLevel>=5 && DebugLevel<=9) { + Options->Debug = TRUE; + } else { + Options->Debug = FALSE; + } + Argv++; + Argc--; + } else if ((stricmp (Argv[0], "--quiet") == 0) || (stricmp (Argv[0], "-q") == 0)) { + Options->Quiet = TRUE; + } else if ((stricmp (Argv[0], "--dump") == 0) || (stricmp (Argv[0], "-d") == 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], "-l") == 0) || (stricmp (Argv[0], "--class-code") == 0)) { + // + // Class code value for the next file in the list. + // Make sure there's another parameter + // + Status = AsciiStringToUint64(Argv[1], FALSE, &TempValue); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 2000, "Invalid option value", "%s = %s", Argv[0], Argv[1]); + return 1; + } + ClassCode = (UINT32) TempValue; + if (ClassCode & 0xFF000000) { + Error (NULL, 0, 2000, "Invalid parameter", "Class code %s out of range!", Argv[1]); + return STATUS_ERROR; + } + if (FileList != NULL && FileList->ClassCode == 0) { + FileList->ClassCode = ClassCode; + } + Argv++; + Argc--; + } else if ((stricmp (Argv[0], "-r") == 0) || (stricmp (Argv[0], "--Revision") == 0)) { + // + // Code revision in the PCI data structure. The value is for the next + // file in the list. + // Make sure there's another parameter + // + Status = AsciiStringToUint64(Argv[1], FALSE, &TempValue); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 2000, "Invalid option value", "%s = %s", Argv[0], Argv[1]); + return 1; + } + CodeRevision = (UINT32) TempValue; + if (CodeRevision & 0xFFFF0000) { + Error (NULL, 0, 2000, "Invalid parameter", "Code revision %s out of range!", Argv[1]); + return STATUS_ERROR; + } + if (FileList != NULL && FileList->CodeRevision == 0) { + FileList->CodeRevision = (UINT16) CodeRevision; + } + Argv++; + Argc--; + } else if ((stricmp (Argv[0], "-p") == 0) || (stricmp (Argv[0], "--pci23") == 0)) { + // + // Default layout meets PCI 3.0 specifications, specifying this flag will for a PCI 2.3 layout. + // + mOptions.Pci23 = 1; + } else { + Error (NULL, 0, 2000, "Invalid parameter", "Invalid option specified: %s", Argv[0]); + 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) { + Error (NULL, 0, 2000, "Invalid parameter", "Missing -e or -b with input file %s!", Argv[0]); + return STATUS_ERROR; + } + // + // Check Efi Option RomImage + // + if ((FileFlags & FILE_FLAG_EFI) == FILE_FLAG_EFI) { + EfiRomFlag = TRUE; + } + // + // Create a new file structure + // + FileList = (FILE_LIST *) malloc (sizeof (FILE_LIST)); + if (FileList == NULL) { + Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!", NULL); + return STATUS_ERROR; + } + + // + // set flag and class code for this image. + // + memset ((char *) FileList, 0, sizeof (FILE_LIST)); + FileList->FileName = Argv[0]; + FileList->FileFlags = FileFlags; + FileList->ClassCode = ClassCode; + FileList->CodeRevision = (UINT16) CodeRevision; + ClassCode = 0; + CodeRevision = 0; + + if (Options->FileList == NULL) { + Options->FileList = FileList; + } else { + if (PrevFileList == NULL) { + PrevFileList = FileList; + } else { + PrevFileList->Next = FileList; + } + } + + PrevFileList = FileList; + } + // + // Next argument + // + Argv++; + Argc--; + } + + // + // Must have specified some files + // + if (Options->FileList == NULL) { + Error (NULL, 0, 2000, "Invalid parameter", "Missing input file name!"); + return STATUS_ERROR; + } + + // + // For EFI OptionRom image, Make sure a device ID and vendor ID are both specified. + // + if (EfiRomFlag) { + if (!Options->VendIdValid) { + Error (NULL, 0, 2000, "Missing Vendor ID in command line", NULL); + return STATUS_ERROR; + } + + if (!Options->DevIdValid) { + Error (NULL, 0, 2000, "Missing Device ID in command line", NULL); + return STATUS_ERROR; + } + } + + return 0; +} + +static +void +Version ( + VOID + ) +/*++ + +Routine Description: + + Print version information for this utility. + +Arguments: + + None. + +Returns: + + Nothing. +--*/ +{ + fprintf (stdout, "%s Version %d.%d\n", UTILITY_NAME, UTILITY_MAJOR_VERSION, UTILITY_MINOR_VERSION); +} + +static +void +Usage ( + VOID + ) +/*++ + +Routine Description: + + Print usage information for this utility. + +Arguments: + + None. + +Returns: + + Nothing. + +--*/ +{ + // + // Summary usage + // + fprintf (stdout, "Usage: %s [options] [file name] \n\n", UTILITY_NAME); + + // + // Copyright declaration + // + fprintf (stdout, "Copyright (c) 2007 - 2009, Intel Corporation. All rights reserved.\n\n"); + + // + // Details Option + // + fprintf (stdout, "Options:\n"); + fprintf (stdout, " -o FileName, --output FileName\n\ + File will be created to store the ouput content.\n"); + fprintf (stdout, " -e EfiFileName\n\ + EFI PE32 image files.\n"); + fprintf (stdout, " -ec EfiFileName\n\ + EFI PE32 image files and will be compressed.\n"); + fprintf (stdout, " -b BinFileName\n\ + Legacy binary files.\n"); + fprintf (stdout, " -l ClassCode\n\ + Hex ClassCode in the PCI data structure header.\n"); + fprintf (stdout, " -r Rev Hex Revision in the PCI data structure header.\n"); + fprintf (stdout, " -n Not to automatically set the LAST bit in the last file.\n"); + fprintf (stdout, " -f VendorId\n\ + Hex PCI Vendor ID for the device OpROM.\n"); + fprintf (stdout, " -i DeviceId\n\ + Hex PCI Device ID for the device OpROM.\n"); + fprintf (stdout, " -p, --pci23\n\ + Default layout meets PCI 3.0 specifications\n\ + specifying this flag will for a PCI 2.3 layout.\n"); + fprintf (stdout, " -d, --dump\n\ + Dump the headers of an existing option ROM image.\n"); + fprintf (stdout, " -v, --verbose\n\ + Turn on verbose output with informational messages.\n"); + fprintf (stdout, " --version Show program's version number and exit.\n"); + fprintf (stdout, " -h, --help\n\ + Show this help message and exit.\n"); + fprintf (stdout, " -q, --quiet\n\ + Disable all messages except FATAL ERRORS.\n"); + fprintf (stdout, " --debug [#,0-9]\n\ + Enable debug messages at level #.\n"); +} + +static +void +DumpImage ( + FILE_LIST *InFile + ) +/*++ + +Routine Description: + + Dump the headers of an existing option ROM image + +Arguments: + + InFile - the file name of an existing option ROM image + +Returns: + + none + +--*/ +{ + PCI_EXPANSION_ROM_HEADER PciRomHdr; + FILE *InFptr; + UINT32 ImageStart; + UINT32 ImageCount; + EFI_PCI_EXPANSION_ROM_HEADER EfiRomHdr; + PCI_DATA_STRUCTURE PciDs23; + PCI_3_0_DATA_STRUCTURE PciDs30; + + // + // Open the input file + // + if ((InFptr = fopen (InFile->FileName, "rb")) == NULL) { + Error (NULL, 0, 0001, "Error opening file", 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) { + Error (NULL, 0, 3001, "Not supported", "Failed to read PCI ROM header from file!"); + 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)) { + Error (NULL, 0, 3001, "Not supported", "Failed to seek to PCI data structure!"); + goto BailOut; + } + // + // Read and dump the PCI data structure + // + memset (&PciDs23, 0, sizeof (PciDs23)); + memset (&PciDs30, 0, sizeof (PciDs30)); + if (mOptions.Pci23 == 1) { + if (fread (&PciDs23, sizeof (PciDs23), 1, InFptr) != 1) { + Error (NULL, 0, 3001, "Not supported", "Failed to read PCI data structure from file %s!", InFile->FileName); + goto BailOut; + } + } else { + if (fread (&PciDs30, sizeof (PciDs30), 1, InFptr) != 1) { + Error (NULL, 0, 3001, "Not supported", "Failed to read PCI data structure from file %s!", InFile->FileName); + goto BailOut; + } + } + if (mOptions.Verbose) { + VerboseMsg("Read PCI data structure from file %s", InFile->FileName); + } + + //fprintf (stdout, " PCI Data Structure\n"); + if (mOptions.Pci23 == 1) { + fprintf ( + stdout, + " Signature %c%c%c%c\n", + (char) PciDs23.Signature, + (char) (PciDs23.Signature >> 8), + (char) (PciDs23.Signature >> 16), + (char) (PciDs23.Signature >> 24) + ); + fprintf (stdout, " Vendor ID 0x%04X\n", PciDs23.VendorId); + fprintf (stdout, " Device ID 0x%04X\n", PciDs23.DeviceId); + fprintf (stdout, " Length 0x%04X\n", PciDs23.Length); + fprintf (stdout, " Revision 0x%04X\n", PciDs23.Revision); + fprintf ( + stdout, + " Class Code 0x%06X\n", + (UINT32) (PciDs23.ClassCode[0] | (PciDs23.ClassCode[1] << 8) | (PciDs23.ClassCode[2] << 16)) + ); + fprintf (stdout, " Image size 0x%X\n", PciDs23.ImageLength * 512); + fprintf (stdout, " Code revision: 0x%04X\n", PciDs23.CodeRevision); + fprintf (stdout, " Indicator 0x%02X", (UINT32) PciDs23.Indicator); + } else { + fprintf ( + stdout, + " Signature %c%c%c%c\n", + (char) PciDs30.Signature, + (char) (PciDs30.Signature >> 8), + (char) (PciDs30.Signature >> 16), + (char) (PciDs30.Signature >> 24) + ); + fprintf (stdout, " Vendor ID 0x%04X\n", PciDs30.VendorId); + fprintf (stdout, " Device ID 0x%04X\n", PciDs30.DeviceId); + fprintf (stdout, " Length 0x%04X\n", PciDs30.Length); + fprintf (stdout, " Revision 0x%04X\n", PciDs30.Revision); + fprintf (stdout, " DeviceListOffset 0x%02X\n", (UINT32) PciDs30.DeviceListOffset); + fprintf ( + stdout, + " Class Code 0x%06X\n", + (UINT32) (PciDs30.ClassCode[0] | (PciDs30.ClassCode[1] << 8) | (PciDs30.ClassCode[2] << 16)) + ); + fprintf (stdout, " Image size 0x%X\n", PciDs30.ImageLength * 512); + fprintf (stdout, " Code revision: 0x%04X\n", PciDs30.CodeRevision); + fprintf (stdout, " MaxRuntimeImageLength 0x%02X\n", (UINT32) PciDs30.MaxRuntimeImageLength); + fprintf (stdout, " ConfigUtilityCodeHeaderOffset 0x%02X\n", (UINT32) PciDs30.ConfigUtilityCodeHeaderOffset); + fprintf (stdout, " DMTFCLPEntryPointOffset 0x%02X\n", (UINT32) PciDs30.DMTFCLPEntryPointOffset); + fprintf (stdout, " Indicator 0x%02X", (UINT32) PciDs30.Indicator); + } + // + // Print the indicator, used to flag the last image + // + if (PciDs23.Indicator == INDICATOR_LAST || PciDs30.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. + // + if (mOptions.Pci23 == 1) { + fprintf (stdout, " Code type 0x%02X", (UINT32) PciDs23.CodeType); + } else { + fprintf (stdout, " Code type 0x%02X", (UINT32) PciDs30.CodeType); + } + if (PciDs23.CodeType == PCI_CODE_TYPE_EFI_IMAGE || PciDs30.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)) { + Error (NULL, 0, 5001, "Failed to re-seek to ROM header structure!", NULL); + goto BailOut; + } + + if (fread (&EfiRomHdr, sizeof (EfiRomHdr), 1, InFptr) != 1) { + Error (NULL, 0, 5001, "Failed to read EFI PCI ROM header from file!", NULL); + 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 (PciDs23.Indicator == INDICATOR_LAST || PciDs30.Indicator == INDICATOR_LAST) { + goto BailOut; + } + // + // Seek to the start of the next image + // + if (mOptions.Pci23 == 1) { + if (fseek (InFptr, ImageStart + (PciDs23.ImageLength * 512), SEEK_SET)) { + Error (NULL, 0, 3001, "Not supported", "Failed to seek to next image!"); + goto BailOut; + } + } else { + if (fseek (InFptr, ImageStart + (PciDs30.ImageLength * 512), SEEK_SET)) { + Error (NULL, 0, 3001, "Not supported", "Failed to seek to next image!"); + 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/BaseTools/Source/C/EfiRom/EfiRom.h b/BaseTools/Source/C/EfiRom/EfiRom.h new file mode 100644 index 0000000000..2689c2293c --- /dev/null +++ b/BaseTools/Source/C/EfiRom/EfiRom.h @@ -0,0 +1,366 @@ +/** @file + +Copyright (c) 1999 - 2008 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: + + EfiRom.h + +Abstract: + + This file contains the relevant declarations required + to generate Option Rom File + +**/ + +#ifndef __EFI_ROM_H__ +#define __EFI_ROM_H__ + +#include +#include +#include + +#include +#include // for PE32 structure definitions + +#include // for option ROM header structures +#include + +#include "Compress.h" +#include "CommonLib.h" + +// +// Version of this utility +// +#define UTILITY_NAME "EfiRom" +#define UTILITY_MAJOR_VERSION 0 +#define UTILITY_MINOR_VERSION 1 + +// +// Define the max length of a filename +// +#define MAX_PATH 200 + +// +// Define the default file extension name +// +#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; + CHAR8 *FileName; + UINT32 FileFlags; + UINT32 ClassCode; + UINT16 CodeRevision; +} FILE_LIST; + +// +// Use this to track our command-line options +// +typedef struct { + CHAR8 OutFileName[MAX_PATH]; + INT8 NoLast; + UINT16 ClassCode; + UINT16 PciRevision; + UINT16 VendId; + UINT16 DevId; + UINT8 VendIdValid; + UINT8 DevIdValid; + INT8 Verbose; + INT8 Quiet; + INT8 Debug; + INT8 Pci23; + INT8 Pci30; + INT8 DumpOption; +// INT8 Help; +// INT8 Version; + 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; + CHAR8 *Name; +} STRING_LOOKUP; + +// +// Machine Types +// +static STRING_LOOKUP mMachineTypes[] = { + { EFI_IMAGE_MACHINE_IA32, "IA32" }, + { EFI_IMAGE_MACHINE_IA64, "IA64" }, + { EFI_IMAGE_MACHINE_EBC, "EBC" }, + { 0, NULL } +}; + +// +// Subsystem Types +// +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 +Version ( + VOID + ) +/*++ + +Routine Description: + + Displays the utility version to STDOUT + +Arguments: + + None + +Returns: + + None + +--*/ +; + +static +void +Usage ( + VOID + ) +/*++ + +Routine Description: + + Displays the utility usage syntax to STDOUT + +Arguments: + + None + +Returns: + + None + +--*/ +; + +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 + +--*/ +; + +static +int +CheckPE32File ( + FILE *Fptr, + UINT16 *MachineType, + UINT16 *SubSystem + ) +/*++ + +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 + +--*/ +; + +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 + +--*/ +; + +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 + +--*/ +; + +static +void +DumpImage ( + FILE_LIST *InFile + ) +/*++ + +Routine Description: + + Dump the headers of an existing option ROM image + +Arguments: + + InFile - the file name of an existing option ROM image + +Returns: + + none + +--*/ +; + +char * +GetMachineTypeStr ( + UINT16 MachineType + ) +/*++ + +Routine Description: + + GC_TODO: Add function description + +Arguments: + + MachineType - GC_TODO: add argument description + +Returns: + + GC_TODO: add return values + +--*/ +; + +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 + +--*/ +; + +#endif diff --git a/BaseTools/Source/C/EfiRom/GNUmakefile b/BaseTools/Source/C/EfiRom/GNUmakefile new file mode 100644 index 0000000000..9392a6f6df --- /dev/null +++ b/BaseTools/Source/C/EfiRom/GNUmakefile @@ -0,0 +1,10 @@ +ARCH ?= IA32 +MAKEROOT ?= .. + +APPNAME = EfiRom + +LIBS = -lCommon + +OBJECTS = EfiRom.o + +include $(MAKEROOT)/Makefiles/app.makefile diff --git a/BaseTools/Source/C/EfiRom/Makefile b/BaseTools/Source/C/EfiRom/Makefile new file mode 100644 index 0000000000..9bf8e8aad5 --- /dev/null +++ b/BaseTools/Source/C/EfiRom/Makefile @@ -0,0 +1,10 @@ +!INCLUDE ..\Makefiles\ms.common + +APPNAME = EfiRom + +LIBS = $(LIB_PATH)\Common.lib + +OBJECTS = EfiRom.obj + +!INCLUDE ..\Makefiles\ms.app + diff --git a/BaseTools/Source/C/GNUmakefile b/BaseTools/Source/C/GNUmakefile new file mode 100644 index 0000000000..3b370eb4ce --- /dev/null +++ b/BaseTools/Source/C/GNUmakefile @@ -0,0 +1,90 @@ +## @file +# GNU Make makefile for BaseTools/Source/C. +# +# Copyright (c) 2007 - 2009, 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. +# + +ifndef ARCH + # + # If ARCH is not defined, then we use 'uname -m' to attempt + # try to figure out the appropriate ARCH. + # + uname_m = $(shell uname -m) + $(info Attempting to detect ARCH from 'uname -m': $(uname_m)) + ifeq ($(uname_m),x86_64) + ARCH=X64 + endif + ifeq ($(uname_m),i386) + ARCH=IA32 + endif + ifeq ($(uname_m),i686) + ARCH=IA32 + endif + ifndef ARCH + $(info Could not detected ARCH from uname results) + $(error ARCH is not defined!) + endif + $(info Detected ARCH of $(ARCH) using uname.) +endif + +export ARCH + +MAKEROOT = . + +include Makefiles/header.makefile + +all: makerootdir subdirs $(MAKEROOT)/libs + @echo Finished building BaseTools C Tools with ARCH=$(ARCH) + +LIBRARIES = Common +# NON_BUILDABLE_APPLICATIONS = GenBootSector BootSectImage +APPLICATIONS = \ + GnuGenBootSector \ + BootSectImage \ + EfiLdrImage \ + EfiRom \ + GenFfs \ + GenFv \ + GenFw \ + GenPage \ + GenSec \ + GenCrc32 \ + GenVtf \ + LzmaCompress \ + Split \ + TianoCompress \ + VolInfo \ + VfrCompile + +SUBDIRS := $(LIBRARIES) $(APPLICATIONS) + +.PHONY: outputdirs +makerootdir: + -mkdir $(MAKEROOT) + +.PHONY: subdirs $(SUBDIRS) +subdirs: $(SUBDIRS) +$(SUBDIRS): + $(MAKE) -C $@ + +.PHONY: $(patsubst %,%-clean,$(sort $(SUBDIRS))) +$(patsubst %,%-clean,$(sort $(SUBDIRS))): + -$(MAKE) -C $(@:-clean=) clean + +clean: $(patsubst %,%-clean,$(sort $(SUBDIRS))) + +clean: localClean + +localClean: + rm -f $(MAKEROOT)/bin/* + -rmdir $(MAKEROOT)/libs $(MAKEROOT)/bin + +include Makefiles/footer.makefile diff --git a/BaseTools/Source/C/GenBootSector/FatFormat.h b/BaseTools/Source/C/GenBootSector/FatFormat.h new file mode 100644 index 0000000000..f24b4ee9ac --- /dev/null +++ b/BaseTools/Source/C/GenBootSector/FatFormat.h @@ -0,0 +1,152 @@ +/** @file + + Fat file system structure and definition. + +Copyright 2006 - 2008, 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. + +--*/ + +#ifndef _FAT_BPB_H_ +#define _FAT_BPB_H_ + +#include "CommonLib.h" + +#pragma pack(1) + +typedef struct { + // + // Fat common field + // + UINT8 BS_jmpBoot[3]; + CHAR8 BS_OEMName[8]; + UINT16 BPB_BytsPerSec; + UINT8 BPB_SecPerClus; + UINT16 BPB_RsvdSecCnt; + UINT8 BPB_NumFATs; + UINT16 BPB_RootEntCnt; + UINT16 BPB_TotSec16; + UINT8 BPB_Media; + UINT16 BPB_FATSz16; + UINT16 BPB_SecPerTrk; + UINT16 BPB_NumHeads; + UINT32 BPB_HiddSec; + UINT32 BPB_TotSec32; + + // + // Fat12/16 specific field + // + UINT8 BS_DrvNum; + UINT8 BS_Reserved1; + UINT8 BS_BootSig; + UINT32 BS_VolID; + CHAR8 BS_VolLab[11]; + CHAR8 BS_FilSysType[8]; + + // + // Boot Code and Data + // + UINT8 Reserved[448]; + + // + // Fat common signature - 0xAA55 + // + UINT16 Signature; +} FAT12_16_BPB_STRUCT; + +typedef struct { + // + // Fat common field + // + UINT8 BS_jmpBoot[3]; + CHAR8 BS_OEMName[8]; + UINT16 BPB_BytsPerSec; + UINT8 BPB_SecPerClus; + UINT16 BPB_RsvdSecCnt; + UINT8 BPB_NumFATs; + UINT16 BPB_RootEntCnt; + UINT16 BPB_TotSec16; + UINT8 BPB_Media; + UINT16 BPB_FATSz16; + UINT16 BPB_SecPerTrk; + UINT16 BPB_NumHeads; + UINT32 BPB_HiddSec; + UINT32 BPB_TotSec32; + + // + // Fat32 specific field + // + UINT32 BPB_FATSz32; + UINT16 BPB_ExtFlags; + UINT16 BPB_FSVer; + UINT32 BPB_RootClus; + UINT16 BPB_FSInfo; + UINT16 BPB_BkBootSec; + UINT8 BPB_Reserved[12]; + UINT8 BS_DrvNum; + UINT8 BS_Reserved1; + UINT8 BS_BootSig; + UINT32 BS_VolID; + CHAR8 BS_VolLab[11]; + CHAR8 BS_FilSysType[8]; + + // + // Boot Code and Data + // + UINT8 Reserved[420]; + + // + // Fat common signature - 0xAA55 + // + UINT16 Signature; +} FAT32_BPB_STRUCT; + +typedef union { + FAT12_16_BPB_STRUCT Fat12_16; + FAT32_BPB_STRUCT Fat32; +} FAT_BPB_STRUCT; + +typedef enum { + FatTypeUnknown, + FatTypeFat12, + FatTypeFat16, + FatTypeFat32, + FatTypeMax +} FAT_TYPE; + +typedef struct { + CHAR8 DIR_Name[11]; + UINT8 DIR_Attr; + UINT8 DIR_NTRes; + UINT8 DIR_CrtTimeTenth; + UINT16 DIR_CrtTime; + UINT16 DIR_CrtDate; + UINT16 DIR_LstAccDate; + UINT16 DIR_FstClusHI; + UINT16 DIR_WrtTime; + UINT16 DIR_WrtDate; + UINT16 DIR_FstClusLO; + UINT32 DIR_FileSize; +} FAT_DIRECTORY_ENTRY; + +#pragma pack() + +#define FAT_MAX_FAT12_CLUSTER 0xFF5 +#define FAT_MAX_FAT16_CLUSTER 0xFFF5 + +#define FAT_BS_SIGNATURE 0xAA55 +#define FAT_BS_BOOTSIG 0x29 +#define FAT_BS_JMP1 0xEB +#define FAT_BS_JMP2 0xE9 +#define FAT_FILSYSTYPE "FAT " +#define FAT12_FILSYSTYPE "FAT12 " +#define FAT16_FILSYSTYPE "FAT16 " +#define FAT32_FILSYSTYPE "FAT32 " + +#endif diff --git a/BaseTools/Source/C/GenBootSector/GenBootSector.c b/BaseTools/Source/C/GenBootSector/GenBootSector.c new file mode 100644 index 0000000000..47b5c5c67a --- /dev/null +++ b/BaseTools/Source/C/GenBootSector/GenBootSector.c @@ -0,0 +1,795 @@ +/** @file + +Copyright 2006 - 2008, 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: + + genbootsector.c + +Abstract: + Reading/writing MBR/DBR. + NOTE: + If we write MBR to disk, we just update the MBR code and the partition table wouldn't be over written. + If we process DBR, we will patch MBR to set first partition active if no active partition exists. + +**/ + +#include +#include +#include +#include + +// +// Utility Name +// +#define UTILITY_NAME "GenBootSector" + +// +// Utility version information +// +#define UTILITY_MAJOR_VERSION 0 +#define UTILITY_MINOR_VERSION 1 + +#define MAX_DRIVE 26 +#define PARTITION_TABLE_OFFSET 0x1BE + +#define SIZE_OF_PARTITION_ENTRY 0x10 + +#define PARTITION_ENTRY_STARTLBA_OFFSET 8 + +#define PARTITION_ENTRY_NUM 4 + +INT +GetDrvNumOffset ( + IN VOID *BootSector + ); + +typedef enum { + PatchTypeUnknown, + PatchTypeFloppy, + PatchTypeIde, + PatchTypeUsb, + PatchTypeFileImage // input and output are all file image, patching action is same as PatchTypeFloppy +} PATCH_TYPE; + +typedef enum { + PathUnknown, + PathFile, + PathFloppy, + PathUsb, + PathIde +} PATH_TYPE; + +typedef enum { + ErrorSuccess, + ErrorFileCreate, + ErrorFileReadWrite, + ErrorNoMbr, + ErrorFatType, + ErrorPath, +} ERROR_STATUS; + +CHAR *ErrorStatusDesc[] = { + "Success", + "Failed to create files", + "Failed to read/write files", + "No MBR exists", + "Failed to detect Fat type", + "Inavlid path" +}; + +typedef struct _DRIVE_TYPE_DESC { + UINT Type; + CHAR *Description; +} DRIVE_TYPE_DESC; + +#define DRIVE_TYPE_ITEM(x) {x, #x} +DRIVE_TYPE_DESC DriveTypeDesc[] = { + DRIVE_TYPE_ITEM (DRIVE_UNKNOWN), + DRIVE_TYPE_ITEM (DRIVE_NO_ROOT_DIR), + DRIVE_TYPE_ITEM (DRIVE_REMOVABLE), + DRIVE_TYPE_ITEM (DRIVE_FIXED), + DRIVE_TYPE_ITEM (DRIVE_REMOTE), + DRIVE_TYPE_ITEM (DRIVE_CDROM), + DRIVE_TYPE_ITEM (DRIVE_RAMDISK), + (UINT) -1, NULL +}; + +typedef struct _DRIVE_INFO { + CHAR VolumeLetter; + DRIVE_TYPE_DESC *DriveType; + UINT DiskNumber; +} DRIVE_INFO; + +typedef struct _PATH_INFO { + CHAR *Path; + CHAR PhysicalPath[260]; + PATH_TYPE Type; + BOOL Input; +} PATH_INFO; + +#define BOOT_SECTOR_LBA_OFFSET 0x1FA + +#define IsLetter(x) (((x) >= 'a' && (x) <= 'z') || ((x) >= 'A' && (x) <= 'Z')) + +BOOL +GetDriveInfo ( + CHAR VolumeLetter, + DRIVE_INFO *DriveInfo + ) +/*++ +Routine Description: + Get drive information including disk number and drive type, + where disknumber is useful for reading/writing disk raw data. + NOTE: Floppy disk doesn't have disk number but it doesn't matter because + we can reading/writing floppy disk without disk number. + +Arguments: + VolumeLetter : volume letter, e.g.: C for C:, A for A: + DriveInfo : pointer to DRIVE_INFO structure receiving drive information. + +Return: + TRUE : successful + FALSE : failed +--*/ +{ + HANDLE VolumeHandle; + STORAGE_DEVICE_NUMBER StorageDeviceNumber; + DWORD BytesReturned; + BOOL Success; + UINT DriveType; + UINT Index; + + CHAR RootPath[] = "X:\\"; // "X:\" -> for GetDriveType + CHAR VolumeAccessPath[] = "\\\\.\\X:"; // "\\.\X:" -> to open the volume + + RootPath[0] = VolumeAccessPath[4] = VolumeLetter; + DriveType = GetDriveType(RootPath); + if (DriveType != DRIVE_REMOVABLE && DriveType != DRIVE_FIXED) { + return FALSE; + } + + DriveInfo->VolumeLetter = VolumeLetter; + VolumeHandle = CreateFile ( + VolumeAccessPath, + 0, + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, + OPEN_EXISTING, + 0, + NULL + ); + if (VolumeHandle == INVALID_HANDLE_VALUE) { + fprintf ( + stderr, + "error E0005: CreateFile failed: Volume = %s, LastError = 0x%x\n", + VolumeAccessPath, + GetLastError () + ); + return FALSE; + } + + // + // Get Disk Number. It should fail when operating on floppy. That's ok + // because Disk Number is only needed when operating on Hard or USB disk. + // + // To direct write to disk: + // for USB and HD: use path = \\.\PHYSICALDRIVEx, where x is Disk Number + // for floppy: use path = \\.\X:, where X can be A or B + // + Success = DeviceIoControl( + VolumeHandle, + IOCTL_STORAGE_GET_DEVICE_NUMBER, + NULL, + 0, + &StorageDeviceNumber, + sizeof(StorageDeviceNumber), + &BytesReturned, + NULL + ); + // + // DeviceIoControl should fail if Volume is floppy or network drive. + // + if (!Success) { + DriveInfo->DiskNumber = (UINT) -1; + } else if (StorageDeviceNumber.DeviceType != FILE_DEVICE_DISK) { + // + // Only care about the disk. + // + return FALSE; + } else{ + DriveInfo->DiskNumber = StorageDeviceNumber.DeviceNumber; + } + CloseHandle(VolumeHandle); + + // + // Fill in the type string + // + DriveInfo->DriveType = NULL; + for (Index = 0; DriveTypeDesc[Index].Description != NULL; Index ++) { + if (DriveType == DriveTypeDesc[Index].Type) { + DriveInfo->DriveType = &DriveTypeDesc[Index]; + break; + } + } + + if (DriveInfo->DriveType == NULL) { + // + // Should have a type. + // + fprintf (stderr, "error E3005: Fatal Error!!!\n"); + return FALSE; + } + return TRUE; +} + +VOID +ListDrive ( + VOID + ) +/*++ +Routine Description: + List every drive in current system and their information. + +--*/ +{ + UINT Index; + DRIVE_INFO DriveInfo; + + UINT Mask = GetLogicalDrives(); + + for (Index = 0; Index < MAX_DRIVE; Index++) { + if (((Mask >> Index) & 0x1) == 1) { + if (GetDriveInfo ('A' + (CHAR) Index, &DriveInfo)) { + if (Index < 2) { + // Floppy will occupy 'A' and 'B' + fprintf ( + stdout, + "%c: - Type: %s\n", + DriveInfo.VolumeLetter, + DriveInfo.DriveType->Description + ); + } else { + fprintf ( + stdout, + "%c: - DiskNum: %d, Type: %s\n", + DriveInfo.VolumeLetter, + DriveInfo.DiskNumber, + DriveInfo.DriveType->Description + ); + } + } + } + } + +} + +INT +GetBootSectorOffset ( + HANDLE DiskHandle, + PATH_INFO *PathInfo + ) +/*++ +Description: + Get the offset of boot sector. + For non-MBR disk, offset is just 0 + for disk with MBR, offset needs to be caculated by parsing MBR + + NOTE: if no one is active, we will patch MBR to select first partition as active. + +Arguments: + DiskHandle : HANDLE of disk + PathInfo : PATH_INFO structure. + WriteToDisk : TRUE indicates writing + +Return: + -1 : failed + o.w. : Offset to boot sector +--*/ +{ + BYTE DiskPartition[0x200]; + DWORD BytesReturn; + DWORD DbrOffset; + DWORD Index; + BOOL HasMbr; + + DbrOffset = 0; + HasMbr = FALSE; + + SetFilePointer(DiskHandle, 0, NULL, FILE_BEGIN); + if (!ReadFile (DiskHandle, DiskPartition, 0x200, &BytesReturn, NULL)) { + return -1; + } + + // + // Check Signature, Jmp, and Boot Indicator. + // if all pass, we assume MBR found. + // + + // Check Signature: 55AA + if ((DiskPartition[0x1FE] == 0x55) && (DiskPartition[0x1FF] == 0xAA)) { + // Check Jmp: (EB ?? 90) or (E9 ?? ??) + if (((DiskPartition[0] != 0xEB) || (DiskPartition[2] != 0x90)) && + (DiskPartition[0] != 0xE9)) { + // Check Boot Indicator: 0x00 or 0x80 + // Boot Indicator is the first byte of Partition Entry + HasMbr = TRUE; + for (Index = 0; Index < PARTITION_ENTRY_NUM; ++Index) { + if ((DiskPartition[PARTITION_TABLE_OFFSET + Index * SIZE_OF_PARTITION_ENTRY] & 0x7F) != 0) { + HasMbr = FALSE; + break; + } + } + } + } + + if (HasMbr) { + // + // Skip MBR + // + for (Index = 0; Index < PARTITION_ENTRY_NUM; Index++) { + // + // Found Boot Indicator. + // + if (DiskPartition[PARTITION_TABLE_OFFSET + (Index * SIZE_OF_PARTITION_ENTRY)] == 0x80) { + DbrOffset = *(DWORD *)&DiskPartition[PARTITION_TABLE_OFFSET + (Index * SIZE_OF_PARTITION_ENTRY) + PARTITION_ENTRY_STARTLBA_OFFSET]; + break; + } + } + // + // If no boot indicator, we manually select 1st partition, and patch MBR. + // + if (Index == PARTITION_ENTRY_NUM) { + DbrOffset = *(DWORD *)&DiskPartition[PARTITION_TABLE_OFFSET + PARTITION_ENTRY_STARTLBA_OFFSET]; + if (!PathInfo->Input && (PathInfo->Type == PathUsb)) { + SetFilePointer(DiskHandle, 0, NULL, FILE_BEGIN); + DiskPartition[PARTITION_TABLE_OFFSET] = 0x80; + WriteFile (DiskHandle, DiskPartition, 0x200, &BytesReturn, NULL); + } + } + } + + return DbrOffset; +} + +/** + * Get window file handle for input/ouput disk/file. + * + * @param PathInfo + * @param ProcessMbr + * @param FileHandle + * + * @return ERROR_STATUS + */ +ERROR_STATUS +GetFileHandle ( + PATH_INFO *PathInfo, + BOOL ProcessMbr, + HANDLE *FileHandle, + DWORD *DbrOffset + ) +{ + DWORD OpenFlag; + + OpenFlag = OPEN_ALWAYS; + if (PathInfo->Input || PathInfo->Type != PathFile) { + OpenFlag = OPEN_EXISTING; + } + + *FileHandle = CreateFile( + PathInfo->PhysicalPath, + GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ, + NULL, + OpenFlag, + FILE_ATTRIBUTE_NORMAL, + NULL + ); + if (*FileHandle == INVALID_HANDLE_VALUE) { + return ErrorFileCreate; + } + + if ((PathInfo->Type == PathIde) || (PathInfo->Type == PathUsb)){ + *DbrOffset = GetBootSectorOffset (*FileHandle, PathInfo); + if (!ProcessMbr) { + // + // 1. Process boot sector, set file pointer to the beginning of boot sector + // + SetFilePointer (*FileHandle, *DbrOffset * 0x200, NULL, FILE_BEGIN); + } else if(*DbrOffset == 0) { + // + // If user want to process Mbr, but no Mbr exists, simply return FALSE + // + return ErrorNoMbr; + } else { + // + // 2. Process MBR, set file pointer to 0 + // + SetFilePointer (*FileHandle, 0, NULL, FILE_BEGIN); + } + } + + return ErrorSuccess; +} + +/** + Writing or reading boot sector or MBR according to the argument. + + @param InputInfo PATH_INFO instance for input path + @param OutputInfo PATH_INFO instance for output path + @param ProcessMbr TRUE is to process MBR, otherwise, processing boot sector + + @return ERROR_STATUS + **/ +ERROR_STATUS +ProcessBsOrMbr ( + PATH_INFO *InputInfo, + PATH_INFO *OutputInfo, + BOOL ProcessMbr + ) +{ + BYTE DiskPartition[0x200] = {0}; + BYTE DiskPartitionBackup[0x200] = {0}; + DWORD BytesReturn; + DWORD DbrOffset; + INT DrvNumOffset; + HANDLE InputHandle; + HANDLE OutputHandle; + BOOL WriteToDisk; + ERROR_STATUS Status; + DWORD InputDbrOffset; + DWORD OutputDbrOffset; + + // + // Create file Handle and move file Pointer is pointed to beginning of Mbr or Dbr + // + Status = GetFileHandle(InputInfo, ProcessMbr, &InputHandle, &InputDbrOffset); + if (Status != ErrorSuccess) { + return Status; + } + + // + // Create file Handle and move file Pointer is pointed to beginning of Mbr or Dbr + // + Status = GetFileHandle(OutputInfo, ProcessMbr, &OutputHandle, &OutputDbrOffset); + if (Status != ErrorSuccess) { + return Status; + } + + // + // Read boot sector from source disk/file + // + if (!ReadFile (InputHandle, DiskPartition, 0x200, &BytesReturn, NULL)) { + return ErrorFileReadWrite; + } + + if (InputInfo->Type == PathUsb) { + // Manually set BS_DrvNum to 0x80 as window's format.exe has a bug which will clear this field discarding USB disk's MBR. + // offset of BS_DrvNum is 0x24 for FAT12/16 + // 0x40 for FAT32 + // + DrvNumOffset = GetDrvNumOffset (DiskPartition); + if (DrvNumOffset == -1) { + return ErrorFatType; + } + // + // Some legacy BIOS require 0x80 discarding MBR. + // Question left here: is it needed to check Mbr before set 0x80? + // + DiskPartition[DrvNumOffset] = ((InputDbrOffset > 0) ? 0x80 : 0); + } + + if (InputInfo->Type == PathIde) { + // + // Patch LBAOffsetForBootSector + // + *(DWORD *)&DiskPartition [BOOT_SECTOR_LBA_OFFSET] = InputDbrOffset; + } + + if (OutputInfo->Type != PathFile) { + if (ProcessMbr) { + // + // Use original partition table + // + if (!ReadFile (OutputHandle, DiskPartitionBackup, 0x200, &BytesReturn, NULL)) { + return ErrorFileReadWrite; + } + memcpy (DiskPartition + 0x1BE, DiskPartitionBackup + 0x1BE, 0x40); + SetFilePointer (OutputHandle, 0, NULL, FILE_BEGIN); + + } + } + + // + // Write boot sector to taget disk/file + // + if (!WriteFile (OutputHandle, DiskPartition, 0x200, &BytesReturn, NULL)) { + return ErrorFileReadWrite; + } + + CloseHandle (InputHandle); + CloseHandle (OutputHandle); + + return ErrorSuccess; +} + +void +Version ( + void + ) +/*++ + +Routine Description: + + Displays the standard utility information to SDTOUT + +Arguments: + + None + +Returns: + + None + +--*/ +{ + printf ("%s v%d.%d -Utility to retrieve and update the boot sector or MBR.\n", UTILITY_NAME, UTILITY_MAJOR_VERSION, UTILITY_MINOR_VERSION); + printf ("Copyright (c) 2009 Intel Corporation. All rights reserved.\n"); +} + +VOID +PrintUsage ( + void + ) +{ + Version(); + printf ("\nUsage: \n\ + GenBootSector\n\ + [-l, --list list disks]\n\ + [-i, --input Filename]\n\ + [-o, --output Filename]\n\ + [-m, --mbr process the MBR also]\n\ + [-v, --verbose]\n\ + [--version]\n\ + [-q, --quiet disable all messages except fatal errors]\n\ + [-d, --debug[#]\n\ + [-h, --help]\n"); + +} + +/** + Get path information, including physical path for windows platform. + + @param PathInfo Point to PATH_INFO structure. + + @return whether path is valid. +**/ +ERROR_STATUS +GetPathInfo ( + PATH_INFO *PathInfo + ) +{ + DRIVE_INFO DriveInfo; + CHAR VolumeLetter; + CHAR DiskPathTemplate[] = "\\\\.\\PHYSICALDRIVE%u"; + CHAR FloppyPathTemplate[] = "\\\\.\\%c:"; + FILE *f; + + // + // If path is disk path + // + if (IsLetter(PathInfo->Path[0]) && (PathInfo->Path[1] == ':') && (PathInfo->Path[2] == '\0')) { + VolumeLetter = PathInfo->Path[0]; + if ((VolumeLetter == 'A') || (VolumeLetter == 'a') || + (VolumeLetter == 'B') || (VolumeLetter == 'b')) { + PathInfo->Type = PathFloppy; + sprintf (PathInfo->PhysicalPath, FloppyPathTemplate, VolumeLetter); + return ErrorSuccess; + } + + if (!GetDriveInfo(VolumeLetter, &DriveInfo)) { + fprintf (stderr, "ERROR: GetDriveInfo - 0x%x\n", GetLastError ()); + return ErrorPath; + } + + if (!PathInfo->Input && (DriveInfo.DriveType->Type == DRIVE_FIXED)) { + fprintf (stderr, "ERROR: Could patch own IDE disk!\n"); + return ErrorPath; + } + + sprintf(PathInfo->PhysicalPath, DiskPathTemplate, DriveInfo.DiskNumber); + if (DriveInfo.DriveType->Type == DRIVE_REMOVABLE) { + PathInfo->Type = PathUsb; + } else if (DriveInfo.DriveType->Type == DRIVE_FIXED) { + PathInfo->Type = PathIde; + } else { + fprintf (stderr, "ERROR, Invalid disk path - %s", PathInfo->Path); + return ErrorPath; + } + + return ErrorSuccess; + } + + PathInfo->Type = PathFile; + if (PathInfo->Input) { + // + // If path is file path, check whether file is valid. + // + f = fopen (PathInfo->Path, "r"); + if (f == NULL) { + fprintf (stderr, "error E2003: File was not provided!\n"); + return ErrorPath; + } + } + PathInfo->Type = PathFile; + strcpy(PathInfo->PhysicalPath, PathInfo->Path); + + return ErrorSuccess; +} + +INT +main ( + INT argc, + CHAR *argv[] + ) +{ + CHAR8 *AppName; + INTN Index; + BOOLEAN ProcessMbr; + ERROR_STATUS Status; + EFI_STATUS EfiStatus; + PATH_INFO InputPathInfo = {0}; + PATH_INFO OutputPathInfo = {0}; + UINT64 LogLevel; + + SetUtilityName (UTILITY_NAME); + + AppName = *argv; + argv ++; + argc --; + + ProcessMbr = FALSE; + + if (argc == 0) { + PrintUsage(); + return 0; + } + + // + // Parse command line + // + for (Index = 0; Index < argc; Index ++) { + if ((stricmp (argv[Index], "-l") == 0) || (stricmp (argv[Index], "--list") == 0)) { + ListDrive (); + return 0; + } + + if ((stricmp (argv[Index], "-m") == 0) || (stricmp (argv[Index], "--mbr") == 0)) { + ProcessMbr = TRUE; + continue; + } + + if ((stricmp (argv[Index], "-i") == 0) || (stricmp (argv[Index], "--input") == 0)) { + InputPathInfo.Path = argv[Index + 1]; + InputPathInfo.Input = TRUE; + if (InputPathInfo.Path == NULL) { + Error (NULL, 0, 1003, "Invalid option value", "Input file name can't be NULL"); + return 1; + } + if (InputPathInfo.Path[0] == '-') { + Error (NULL, 0, 1003, "Invalid option value", "Input file is missing"); + return 1; + } + ++Index; + continue; + } + + if ((stricmp (argv[Index], "-o") == 0) || (stricmp (argv[Index], "--output") == 0)) { + OutputPathInfo.Path = argv[Index + 1]; + OutputPathInfo.Input = FALSE; + if (OutputPathInfo.Path == NULL) { + Error (NULL, 0, 1003, "Invalid option value", "Output file name can't be NULL"); + return 1; + } + if (OutputPathInfo.Path[0] == '-') { + Error (NULL, 0, 1003, "Invalid option value", "Output file is missing"); + return 1; + } + ++Index; + continue; + } + + if ((stricmp (argv[Index], "-h") == 0) || (stricmp (argv[Index], "--help") == 0)) { + PrintUsage (); + return 0; + } + + if (stricmp (argv[Index], "--version") == 0) { + Version (); + return 0; + } + + if ((stricmp (argv[Index], "-v") == 0) || (stricmp (argv[Index], "--verbose") == 0)) { + continue; + } + + if ((stricmp (argv[Index], "-q") == 0) || (stricmp (argv[Index], "--quiet") == 0)) { + continue; + } + + if ((stricmp (argv[Index], "-d") == 0) || (stricmp (argv[Index], "--debug") == 0)) { + EfiStatus = AsciiStringToUint64 (argv[Index + 1], FALSE, &LogLevel); + if (EFI_ERROR (EfiStatus)) { + Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[Index], argv[Index + 1]); + return 1; + } + if (LogLevel > 9) { + Error (NULL, 0, 1003, "Invalid option value", "Debug Level range is 0-9, currnt input level is %d", LogLevel); + return 1; + } + SetPrintLevel (LogLevel); + DebugMsg (NULL, 0, 9, "Debug Mode Set", "Debug Output Mode Level %s is set!", argv[Index + 1]); + ++Index; + continue; + } + + // + // Don't recognize the parameter. + // + Error (NULL, 0, 1000, "Unknown option", "%s", argv[Index]); + return 1; + } + + if (InputPathInfo.Path == NULL) { + Error (NULL, 0, 1001, "Missing options", "Input file is missing"); + return 1; + } + + if (OutputPathInfo.Path == NULL) { + Error (NULL, 0, 1001, "Missing options", "Output file is missing"); + return 1; + } + + if (GetPathInfo(&InputPathInfo) != ErrorSuccess) { + Error (NULL, 0, 1003, "Invalid option value", "Input file can't be found."); + return 1; + } + + if (GetPathInfo(&OutputPathInfo) != ErrorSuccess) { + Error (NULL, 0, 1003, "Invalid option value", "Output file can't be found."); + return 1; + } + + // + // Process DBR (Patch or Read) + // + Status = ProcessBsOrMbr (&InputPathInfo, &OutputPathInfo, ProcessMbr); + + if (Status == ErrorSuccess) { + fprintf ( + stdout, + "%s %s: successful!\n", + (OutputPathInfo.Type != PathFile) ? "Write" : "Read", + ProcessMbr ? "MBR" : "DBR" + ); + return 0; + } else { + fprintf ( + stderr, + "%s: %s %s: failed - %s (LastError: 0x%x)!\n", + (Status == ErrorNoMbr) ? "WARNING" : "ERROR", + (OutputPathInfo.Type != PathFile) ? "Write" : "Read", + ProcessMbr ? "MBR" : "DBR", + ErrorStatusDesc[Status], + GetLastError () + ); + return 1; + } +} diff --git a/BaseTools/Source/C/GenBootSector/GetDrvNumOffset.c b/BaseTools/Source/C/GenBootSector/GetDrvNumOffset.c new file mode 100644 index 0000000000..a55137b557 --- /dev/null +++ b/BaseTools/Source/C/GenBootSector/GetDrvNumOffset.c @@ -0,0 +1,73 @@ +/** @file + + Get Drv Num offset from Fat file system. + +Copyright 2006 - 2008, 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. + +**/ + +#include +#include "FatFormat.h" + +INTN +GetDrvNumOffset ( + IN VOID *BootSector + ) +{ + FAT_BPB_STRUCT *FatBpb; + UINTN RootDirSectors; + UINTN FATSz; + UINTN TotSec; + UINTN DataSec; + UINTN CountOfClusters; + + FatBpb = (FAT_BPB_STRUCT *) BootSector; + + // + // Check FAT type algorithm from FAT spec + // + RootDirSectors = ((FatBpb->Fat12_16.BPB_RootEntCnt * sizeof(FAT_DIRECTORY_ENTRY)) + + (FatBpb->Fat12_16.BPB_BytsPerSec - 1)) / FatBpb->Fat12_16.BPB_BytsPerSec; + + if (FatBpb->Fat12_16.BPB_FATSz16 != 0) { + FATSz = FatBpb->Fat12_16.BPB_FATSz16; + } else { + FATSz = FatBpb->Fat32.BPB_FATSz32; + } + if (FATSz == 0) { + fprintf (stderr, "error E3003: FAT - BPB_FATSz16, BPB_FATSz32 - 0, expected: Non-Zero number\n"); + return -1; + } + + if (FatBpb->Fat12_16.BPB_TotSec16 != 0) { + TotSec = FatBpb->Fat12_16.BPB_TotSec16; + } else { + TotSec = FatBpb->Fat12_16.BPB_TotSec32; + } + if (TotSec == 0) { + fprintf (stderr, "error E3003: FAT - BPB_TotSec16, BPB_TotSec32 - 0, expected: Non-Zero number\n"); + return -1; + } + + DataSec = TotSec - ( + FatBpb->Fat12_16.BPB_RsvdSecCnt + + FatBpb->Fat12_16.BPB_NumFATs * FATSz + + RootDirSectors + ); + + CountOfClusters = DataSec / FatBpb->Fat12_16.BPB_SecPerClus; + + if (CountOfClusters < FAT_MAX_FAT16_CLUSTER) { + return (INTN) ((UINTN) &FatBpb->Fat12_16.BS_DrvNum - (UINTN) FatBpb); + } else { + return (INTN) ((UINTN) &FatBpb->Fat32.BS_DrvNum - (UINTN) FatBpb); + } +} + diff --git a/BaseTools/Source/C/GenBootSector/Makefile b/BaseTools/Source/C/GenBootSector/Makefile new file mode 100644 index 0000000000..90fc2fe4ad --- /dev/null +++ b/BaseTools/Source/C/GenBootSector/Makefile @@ -0,0 +1,10 @@ +!INCLUDE ..\Makefiles\ms.common + +APPNAME = GenBootSector + +LIBS = $(LIB_PATH)\Common.lib + +OBJECTS = GenBootSector.obj GetDrvNumOffset.obj + +!INCLUDE ..\Makefiles\ms.app + diff --git a/BaseTools/Source/C/GenCrc32/GNUmakefile b/BaseTools/Source/C/GenCrc32/GNUmakefile new file mode 100644 index 0000000000..73f525c82a --- /dev/null +++ b/BaseTools/Source/C/GenCrc32/GNUmakefile @@ -0,0 +1,10 @@ +ARCH ?= IA32 +MAKEROOT ?= .. + +APPNAME = GenCrc32 + +LIBS = -lCommon + +OBJECTS = GenCrc32.o + +include $(MAKEROOT)/Makefiles/app.makefile diff --git a/BaseTools/Source/C/GenCrc32/GenCrc32.c b/BaseTools/Source/C/GenCrc32/GenCrc32.c new file mode 100644 index 0000000000..63900b6461 --- /dev/null +++ b/BaseTools/Source/C/GenCrc32/GenCrc32.c @@ -0,0 +1,362 @@ +/** @file + +Copyright (c) 2007 - 2008, 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: + + GenCrc32.c + +Abstract: + Calculate Crc32 value and Verify Crc32 value for input data. + +**/ + +#include +#include +#include + +#include "EfiUtilityMsgs.h" +#include "CommonLib.h" +#include "Crc32.h" + +#define UTILITY_NAME "GenCrc32" +#define UTILITY_MAJOR_VERSION 0 +#define UTILITY_MINOR_VERSION 1 + +#define CRC32_NULL 0 +#define CRC32_ENCODE 1 +#define CRC32_DECODE 2 + +VOID +Version ( + VOID + ) +/*++ + +Routine Description: + + Displays the standard utility information to SDTOUT + +Arguments: + + None + +Returns: + + None + +--*/ +{ + fprintf (stdout, "%s Version %d.%d\n", UTILITY_NAME, UTILITY_MAJOR_VERSION, UTILITY_MINOR_VERSION); +} + +VOID +Usage ( + VOID + ) +/*++ + +Routine Description: + + Displays the utility usage syntax to STDOUT + +Arguments: + + None + +Returns: + + None + +--*/ +{ + // + // Summary usage + // + fprintf (stdout, "\nUsage: %s -e|-d [options] \n\n", UTILITY_NAME); + + // + // Copyright declaration + // + fprintf (stdout, "Copyright (c) 2007 - 2009, Intel Corporation. All rights reserved.\n\n"); + + // + // Details Option + // + fprintf (stdout, "Options:\n"); + fprintf (stdout, " -o FileName, --output FileName\n\ + File will be created to store the ouput content.\n"); + fprintf (stdout, " -e, --encode Calculate CRC32 value for the input file.\n"); + fprintf (stdout, " -d, --decode Verify CRC32 value for the input file.\n"); + fprintf (stdout, " -v, --verbose Turn on verbose output with informational messages.\n"); + fprintf (stdout, " -q, --quiet Disable all messages except key message and fatal error\n"); + fprintf (stdout, " --debug level Enable debug messages, at input debug level.\n"); + fprintf (stdout, " --version Show program's version number and exit.\n"); + fprintf (stdout, " -h, --help Show this help message and exit.\n"); +} + +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. + +--*/ +{ + EFI_STATUS Status; + CHAR8 *OutputFileName; + CHAR8 *InputFileName; + UINT8 *FileBuffer; + UINT32 FileSize; + UINT64 LogLevel; + UINT8 FileAction; + UINT32 Crc32Value; + FILE *InFile; + FILE *OutFile; + + // + // Init local variables + // + LogLevel = 0; + Status = EFI_SUCCESS; + InputFileName = NULL; + OutputFileName = NULL; + FileAction = CRC32_NULL; + InFile = NULL; + OutFile = NULL; + Crc32Value = 0; + FileBuffer = NULL; + + SetUtilityName (UTILITY_NAME); + + if (argc == 1) { + Error (NULL, 0, 1001, "Missing options", "no options input"); + Usage (); + return STATUS_ERROR; + } + + // + // Parse command line + // + argc --; + argv ++; + + if ((stricmp (argv[0], "-h") == 0) || (stricmp (argv[0], "--help") == 0)) { + Version (); + Usage (); + return STATUS_SUCCESS; + } + + if (stricmp (argv[0], "--version") == 0) { + Version (); + return STATUS_SUCCESS; + } + + while (argc > 0) { + if ((stricmp (argv[0], "-o") == 0) || (stricmp (argv[0], "--output") == 0)) { + if (argv[1] == NULL || argv[1][0] == '-') { + Error (NULL, 0, 1003, "Invalid option value", "Output File name is missing for -o option"); + goto Finish; + } + OutputFileName = argv[1]; + argc -= 2; + argv += 2; + continue; + } + + if ((stricmp (argv[0], "-e") == 0) || (stricmp (argv[0], "--encode") == 0)) { + FileAction = CRC32_ENCODE; + argc --; + argv ++; + continue; + } + + if ((stricmp (argv[0], "-d") == 0) || (stricmp (argv[0], "--decode") == 0)) { + FileAction = CRC32_DECODE; + argc --; + argv ++; + continue; + } + + if ((stricmp (argv[0], "-v") == 0) || (stricmp (argv[0], "--verbose") == 0)) { + SetPrintLevel (VERBOSE_LOG_LEVEL); + VerboseMsg ("Verbose output Mode Set!"); + argc --; + argv ++; + continue; + } + + if ((stricmp (argv[0], "-q") == 0) || (stricmp (argv[0], "--quiet") == 0)) { + SetPrintLevel (KEY_LOG_LEVEL); + KeyMsg ("Quiet output Mode Set!"); + argc --; + argv ++; + continue; + } + + if (stricmp (argv[0], "--debug") == 0) { + Status = AsciiStringToUint64 (argv[1], FALSE, &LogLevel); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]); + goto Finish; + } + if (LogLevel > 9) { + Error (NULL, 0, 1003, "Invalid option value", "Debug Level range is 0-9, current input level is %d", LogLevel); + goto Finish; + } + SetPrintLevel (LogLevel); + DebugMsg (NULL, 0, 9, "Debug Mode Set", "Debug Output Mode Level %s is set!", argv[1]); + argc -= 2; + argv += 2; + continue; + } + + if (argv[0][0] == '-') { + Error (NULL, 0, 1000, "Unknown option", argv[0]); + goto Finish; + } + + // + // Get Input file file name. + // + InputFileName = argv[0]; + argc --; + argv ++; + } + + VerboseMsg ("%s tool start.", UTILITY_NAME); + + // + // Check Input paramters + // + if (FileAction == CRC32_NULL) { + Error (NULL, 0, 1001, "Missing option", "either the encode or the decode option must be specified!"); + return STATUS_ERROR; + } else if (FileAction == CRC32_ENCODE) { + VerboseMsg ("File will be encoded by Crc32"); + } else if (FileAction == CRC32_DECODE) { + VerboseMsg ("File will be decoded by Crc32"); + } + + if (InputFileName == NULL) { + Error (NULL, 0, 1001, "Missing option", "Input files are not specified"); + goto Finish; + } else { + VerboseMsg ("Input file name is %s", InputFileName); + } + + if (OutputFileName == NULL) { + Error (NULL, 0, 1001, "Missing option", "Output file are not specified"); + goto Finish; + } else { + VerboseMsg ("Output file name is %s", OutputFileName); + } + + // + // Open Input file and read file data. + // + InFile = fopen (InputFileName, "rb"); + if (InFile == NULL) { + Error (NULL, 0, 0001, "Error opening file", InputFileName); + return STATUS_ERROR; + } + + fseek (InFile, 0, SEEK_END); + FileSize = ftell (InFile); + fseek (InFile, 0, SEEK_SET); + + FileBuffer = (UINT8 *) malloc (FileSize); + if (FileBuffer == NULL) { + Error (NULL, 0, 4001, "Resource", "memory cannot be allcoated!"); + goto Finish; + } + + fread (FileBuffer, 1, FileSize, InFile); + fclose (InFile); + VerboseMsg ("the size of the input file is %d bytes", FileSize); + + // + // Open output file + // + OutFile = fopen (OutputFileName, "wb"); + if (OutFile == NULL) { + Error (NULL, 0, 0001, "Error opening file", OutputFileName); + goto Finish; + } + + // + // Calculate Crc32 value + // + if (FileAction == CRC32_ENCODE) { + Status = CalculateCrc32 (FileBuffer, FileSize, &Crc32Value); + if (Status != EFI_SUCCESS) { + Error (NULL, 0, 3000, "Invalid", "Calculate CRC32 value failed!"); + goto Finish; + } + // + // Done, write output file. + // + fwrite (&Crc32Value, 1, sizeof (Crc32Value), OutFile); + VerboseMsg ("The calculated CRC32 value is 0x%08x", Crc32Value); + fwrite (FileBuffer, 1, FileSize, OutFile); + VerboseMsg ("the size of the encoded file is %d bytes", FileSize + sizeof (UINT32)); + } else { + // + // Verify Crc32 Value + // + Status = CalculateCrc32 (FileBuffer + sizeof (UINT32), FileSize - sizeof (UINT32), &Crc32Value); + if (Status != EFI_SUCCESS) { + Error (NULL, 0, 3000, "Invalid", "Calculate CRC32 value failed!"); + goto Finish; + } + VerboseMsg ("The calculated CRC32 value is 0x%08x and File Crc32 value is 0x%08x", Crc32Value, *(UINT32 *)FileBuffer); + if (Crc32Value != *(UINT32 *)FileBuffer) { + Error (NULL, 0, 3000, "Invalid", "CRC32 value of input file is not correct!"); + Status = STATUS_ERROR; + goto Finish; + } + // + // Done, write output file. + // + fwrite (FileBuffer + sizeof (UINT32), 1, FileSize - sizeof (UINT32), OutFile); + VerboseMsg ("the size of the decoded file is %d bytes", FileSize - sizeof (UINT32)); + } + +Finish: + if (FileBuffer != NULL) { + free (FileBuffer); + } + + if (OutFile != NULL) { + fclose (OutFile); + } + + VerboseMsg ("%s tool done with return code is 0x%x.", UTILITY_NAME, GetUtilityStatus ()); + + return GetUtilityStatus (); +} + + + + diff --git a/BaseTools/Source/C/GenCrc32/Makefile b/BaseTools/Source/C/GenCrc32/Makefile new file mode 100644 index 0000000000..46397673a5 --- /dev/null +++ b/BaseTools/Source/C/GenCrc32/Makefile @@ -0,0 +1,10 @@ +!INCLUDE ..\Makefiles\ms.common + +APPNAME = GenCrc32 + +LIBS = $(LIB_PATH)\Common.lib + +OBJECTS = GenCrc32.obj + +!INCLUDE ..\Makefiles\ms.app + diff --git a/BaseTools/Source/C/GenFfs/GNUmakefile b/BaseTools/Source/C/GenFfs/GNUmakefile new file mode 100644 index 0000000000..df431b49e8 --- /dev/null +++ b/BaseTools/Source/C/GenFfs/GNUmakefile @@ -0,0 +1,11 @@ +ARCH ?= IA32 +MAKEROOT ?= .. + +APPNAME = GenFfs + +OBJECTS = GenFfs.o + +include $(MAKEROOT)/Makefiles/app.makefile + +LIBS = -lCommon + diff --git a/BaseTools/Source/C/GenFfs/GenFfs.c b/BaseTools/Source/C/GenFfs/GenFfs.c new file mode 100644 index 0000000000..e8cd09e947 --- /dev/null +++ b/BaseTools/Source/C/GenFfs/GenFfs.c @@ -0,0 +1,897 @@ +/** + +Copyright (c) 2004-2008, 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: + + GenFfs.c + +Abstract: + + This file contains functions required to generate a Firmware File System + file. + +**/ + +#include +#include +#include + +#include +#include +#include + +#include "CommonLib.h" +#include "ParseInf.h" +#include "EfiUtilityMsgs.h" + +#define UTILITY_NAME "GenFfs" +#define UTILITY_MAJOR_VERSION 0 +#define UTILITY_MINOR_VERSION 1 + +STATIC CHAR8 *mFfsFileType[] = { + NULL, // 0x00 + "EFI_FV_FILETYPE_RAW", // 0x01 + "EFI_FV_FILETYPE_FREEFORM", // 0x02 + "EFI_FV_FILETYPE_SECURITY_CORE", // 0x03 + "EFI_FV_FILETYPE_PEI_CORE", // 0x04 + "EFI_FV_FILETYPE_DXE_CORE", // 0x05 + "EFI_FV_FILETYPE_PEIM", // 0x06 + "EFI_FV_FILETYPE_DRIVER", // 0x07 + "EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER", // 0x08 + "EFI_FV_FILETYPE_APPLICATION", // 0x09 + "EFI_FV_FILETYPE_SMM", // 0x0A + "EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE",// 0x0B + "EFI_FV_FILETYPE_COMBINED_SMM_DXE", // 0x0C + "EFI_FV_FILETYPE_SMM_CORE" // 0x0D + }; + +STATIC CHAR8 *mAlignName[] = { + "1", "2", "4", "8", "16", "32", "64", "128", "256", "512", + "1K", "2K", "4K", "8K", "16K", "32K", "64K" + }; + +STATIC CHAR8 *mFfsValidAlignName[] = { + "8", "16", "128", "512", "1K", "4K", "32K", "64K" + }; + +STATIC UINT32 mFfsValidAlign[] = {0, 8, 16, 128, 512, 1024, 4096, 32768, 65536}; + +STATIC EFI_GUID mZeroGuid = {0}; + +STATIC +VOID +Version ( + VOID + ) +/*++ + +Routine Description: + + Print out version information for this utility. + +Arguments: + + None + +Returns: + + None + +--*/ +{ + fprintf (stdout, "%s Version %d.%d\n", UTILITY_NAME, UTILITY_MAJOR_VERSION, UTILITY_MINOR_VERSION); +} + +STATIC +VOID +Usage ( + VOID + ) +/*++ + +Routine Description: + + Print Error / Help message. + +Arguments: + + VOID + +Returns: + + None + +--*/ +{ + // + // Summary usage + // + fprintf (stdout, "\nUsage: %s [options]\n\n", UTILITY_NAME); + + // + // Copyright declaration + // + fprintf (stdout, "Copyright (c) 2007, Intel Corporation. All rights reserved.\n\n"); + + // + // Details Option + // + fprintf (stdout, "Options:\n"); + fprintf (stdout, " -o FileName, --outputfile FileName\n\ + File is FFS file to be created.\n"); + fprintf (stdout, " -t Type, --filetype Type\n\ + Type is one FV file type defined in PI spec, which is\n\ + EFI_FV_FILETYPE_RAW, EFI_FV_FILETYPE_FREEFORM,\n\ + EFI_FV_FILETYPE_SECURITY_CORE, EFI_FV_FILETYPE_PEIM,\n\ + EFI_FV_FILETYPE_PEI_CORE, EFI_FV_FILETYPE_DXE_CORE,\n\ + EFI_FV_FILETYPE_DRIVER, EFI_FV_FILETYPE_APPLICATION,\n\ + EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER,\n\ + EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE.\n"); + fprintf (stdout, " -g FileGuid, --fileguid FileGuid\n\ + FileGuid is one module guid.\n\ + Its format is xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\n"); + fprintf (stdout, " -x, --fixed Indicates that the file may not be moved\n\ + from its present location.\n"); + fprintf (stdout, " -s, --checksum Indicates to calculate file checksum.\n"); + fprintf (stdout, " -a FileAlign, --align FileAlign\n\ + FileAlign points to file alignment, which only support\n\ + the following align: 1,2,4,8,16,128,512,1K,4K,32K,64K\n"); + fprintf (stdout, " -i SectionFile, --sectionfile SectionFile\n\ + Section file will be contained in this FFS file.\n"); + fprintf (stdout, " -n SectionAlign, --sectionalign SectionAlign\n\ + SectionAlign points to section alignment, which support\n\ + the alignment scope 1~64K. It is specified together\n\ + with sectionfile to point its alignment in FFS file.\n"); + fprintf (stdout, " -v, --verbose Turn on verbose output with informational messages.\n"); + fprintf (stdout, " -q, --quiet Disable all messages except key message and fatal error\n"); + fprintf (stdout, " -d, --debug level Enable debug messages, at input debug level.\n"); + fprintf (stdout, " --version Show program's version number and exit.\n"); + fprintf (stdout, " -h, --help Show this help message and exit.\n"); +} + +STATIC +EFI_STATUS +StringtoAlignment ( + IN CHAR8 *AlignBuffer, + OUT UINT32 *AlignNumber + ) +/*++ + +Routine Description: + + Converts Align String to align value (1~64K). + +Arguments: + + AlignBuffer - Pointer to Align string. + AlignNumber - Pointer to Align value. + +Returns: + + EFI_SUCCESS Successfully convert align string to align value. + EFI_INVALID_PARAMETER Align string is invalid or align value is not in scope. + +--*/ +{ + UINT32 Index = 0; + // + // Check AlignBuffer + // + if (AlignBuffer == NULL) { + return EFI_INVALID_PARAMETER; + } + for (Index = 0; Index < sizeof (mAlignName) / sizeof (CHAR8 *); Index ++) { + if (stricmp (AlignBuffer, mAlignName [Index]) == 0) { + *AlignNumber = 1 << Index; + return EFI_SUCCESS; + } + } + return EFI_INVALID_PARAMETER; +} + +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 + +--*/ +{ + UINT8 Index = 0; + + if (String == NULL) { + return EFI_FV_FILETYPE_ALL; + } + + for (Index = 0; Index < sizeof (mFfsFileType) / sizeof (CHAR8 *); Index ++) { + if (mFfsFileType [Index] != NULL && (stricmp (String, mFfsFileType [Index]) == 0)) { + return Index; + } + } + return EFI_FV_FILETYPE_ALL; +} + +STATIC +EFI_STATUS +GetSectionContents ( + IN CHAR8 **InputFileName, + IN UINT32 *InputFileAlign, + IN UINT32 InputFileNum, + OUT UINT8 *FileBuffer, + OUT UINT32 *BufferLength, + OUT UINT32 *MaxAlignment, + OUT UINT8 *PESectionNum + ) +/*++ + +Routine Description: + + Get the contents of all section files specified in InputFileName + into FileBuffer. + +Arguments: + + InputFileName - Name of the input file. + + InputFileAlign - Alignment required by the input file data. + + InputFileNum - Number of input files. Should be at least 1. + + FileBuffer - Output buffer to contain data + + BufferLength - On input, this is size of the FileBuffer. + On output, this is the actual length of the data. + + MaxAlignment - The max alignment required by all the input file datas. + + PeSectionNum - Calculate the number of Pe/Te Section in this FFS file. + +Returns: + + EFI_SUCCESS on successful return + EFI_INVALID_PARAMETER if InputFileNum is less than 1 or BufferLength point is NULL. + EFI_ABORTED if unable to open input file. + EFI_BUFFER_TOO_SMALL FileBuffer is not enough to contain all file data. +--*/ +{ + UINT32 Size; + UINT32 Offset; + UINT32 FileSize; + UINT32 Index; + FILE *InFile; + EFI_COMMON_SECTION_HEADER *SectHeader; + EFI_COMMON_SECTION_HEADER TempSectHeader; + EFI_TE_IMAGE_HEADER TeHeader; + UINT32 TeOffset; + + Size = 0; + Offset = 0; + TeOffset = 0; + + // + // Go through our array of file names and copy their contents + // to the output buffer. + // + for (Index = 0; Index < InputFileNum; Index++) { + // + // make sure section ends on a DWORD boundary + // + while ((Size & 0x03) != 0) { + Size++; + } + + // + // Get the Max alignment of all input file datas + // + if (*MaxAlignment < InputFileAlign [Index]) { + *MaxAlignment = InputFileAlign [Index]; + } + + // + // Open file and read contents + // + InFile = fopen (InputFileName[Index], "rb"); + if (InFile == NULL) { + Error (NULL, 0, 0001, "Error opening file", InputFileName[Index]); + return EFI_ABORTED; + } + + fseek (InFile, 0, SEEK_END); + FileSize = ftell (InFile); + fseek (InFile, 0, SEEK_SET); + DebugMsg (NULL, 0, 9, "Input section files", + "the input section name is %s and the size is %d bytes", InputFileName[Index], FileSize); + + // + // Check this section is Te/Pe section, and Calculate the numbers of Te/Pe section. + // + TeOffset = 0; + fread (&TempSectHeader, 1, sizeof (TempSectHeader), InFile); + if (TempSectHeader.Type == EFI_SECTION_TE) { + (*PESectionNum) ++; + fread (&TeHeader, 1, sizeof (TeHeader), InFile); + if (TeHeader.Signature == EFI_TE_IMAGE_HEADER_SIGNATURE) { + TeOffset = TeHeader.StrippedSize - sizeof (TeHeader); + } + } else if (TempSectHeader.Type == EFI_SECTION_PE32) { + (*PESectionNum) ++; + } else if (TempSectHeader.Type == EFI_SECTION_COMPRESSION || + TempSectHeader.Type == EFI_SECTION_GUID_DEFINED || + TempSectHeader.Type == EFI_SECTION_FIRMWARE_VOLUME_IMAGE) { + // + // for the encapsulated section, assume it contains Pe/Te section + // + (*PESectionNum) ++; + } + + fseek (InFile, 0, SEEK_SET); + + // + // Revert TeOffset to the converse value relative to Alignment + // This is to assure the original PeImage Header at Alignment. + // + if ((TeOffset != 0) && (InputFileAlign [Index] != 0)) { + TeOffset = InputFileAlign [Index] - (TeOffset % InputFileAlign [Index]); + TeOffset = TeOffset % InputFileAlign [Index]; + } + + // + // make sure section data meet its alignment requirement by adding one raw pad section. + // But the different sections have the different section header. Necessary or not? + // Based on section type to adjust offset? Todo + // + if ((InputFileAlign [Index] != 0) && (((Size + sizeof (EFI_COMMON_SECTION_HEADER) + TeOffset) % InputFileAlign [Index]) != 0)) { + Offset = (Size + 2 * sizeof (EFI_COMMON_SECTION_HEADER) + TeOffset + InputFileAlign [Index] - 1) & ~(InputFileAlign [Index] - 1); + Offset = Offset - Size - sizeof (EFI_COMMON_SECTION_HEADER) - TeOffset; + + if (FileBuffer != NULL && ((Size + Offset) < *BufferLength)) { + SectHeader = (EFI_COMMON_SECTION_HEADER *) (FileBuffer + Size); + SectHeader->Type = EFI_SECTION_RAW; + SectHeader->Size[0] = (UINT8) (Offset & 0xff); + SectHeader->Size[1] = (UINT8) ((Offset & 0xff00) >> 8); + SectHeader->Size[2] = (UINT8) ((Offset & 0xff0000) >> 16); + } + DebugMsg (NULL, 0, 9, "Pad raw section for section data alignment", + "Pad Raw section size is %d", Offset); + + Size = Size + Offset; + } + + // + // Now read the contents of the file into the buffer + // Buffer must be enough to contain the file content. + // + if ((FileSize > 0) && (FileBuffer != NULL) && ((Size + FileSize) <= *BufferLength)) { + if (fread (FileBuffer + Size, (size_t) FileSize, 1, InFile) != 1) { + Error (NULL, 0, 0004, "Error reading file", InputFileName[Index]); + fclose (InFile); + return EFI_ABORTED; + } + } + + fclose (InFile); + Size += FileSize; + } + + // + // Set the actual length of the data. + // + if (Size > *BufferLength) { + *BufferLength = Size; + return EFI_BUFFER_TOO_SMALL; + } else { + *BufferLength = Size; + return EFI_SUCCESS; + } +} + +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. + +--*/ +{ + EFI_STATUS Status; + EFI_FFS_FILE_ATTRIBUTES FfsAttrib; + UINT32 FfsAlign; + EFI_FV_FILETYPE FfsFiletype; + CHAR8 *OutputFileName; + EFI_GUID FileGuid = {0}; + UINT32 InputFileNum; + UINT32 *InputFileAlign; + CHAR8 **InputFileName; + UINT8 *FileBuffer; + UINT32 FileSize; + UINT32 MaxAlignment; + EFI_FFS_FILE_HEADER FfsFileHeader; + FILE *FfsFile; + UINT32 Index; + UINT64 LogLevel; + UINT8 PeSectionNum; + + // + // Init local variables + // + LogLevel = 0; + Index = 0; + FfsAttrib = 0; + FfsAlign = 0; + FfsFiletype = EFI_FV_FILETYPE_ALL; + OutputFileName = NULL; + InputFileNum = 0; + InputFileName = NULL; + InputFileAlign = NULL; + FileBuffer = NULL; + FileSize = 0; + MaxAlignment = 1; + FfsFile = NULL; + Status = EFI_SUCCESS; + PeSectionNum = 0; + + SetUtilityName (UTILITY_NAME); + + if (argc == 1) { + Error (NULL, 0, 1001, "Missing options", "no options input"); + Usage (); + return STATUS_ERROR; + } + + // + // Parse command line + // + argc --; + argv ++; + + if ((stricmp (argv[0], "-h") == 0) || (stricmp (argv[0], "--help") == 0)) { + Version (); + Usage (); + return STATUS_SUCCESS; + } + + if (stricmp (argv[0], "--version") == 0) { + Version (); + return STATUS_SUCCESS; + } + + while (argc > 0) { + if ((stricmp (argv[0], "-t") == 0) || (stricmp (argv[0], "--filetype") == 0)) { + if (argv[1] == NULL || argv[1][0] == '-') { + Error (NULL, 0, 1003, "Invalid option value", "file type is missing for -t option"); + goto Finish; + } + FfsFiletype = StringToType (argv[1]); + if (FfsFiletype == EFI_FV_FILETYPE_ALL) { + Error (NULL, 0, 1003, "Invalid option value", "%s is not a valid file type", argv[1]); + goto Finish; + } + argc -= 2; + argv += 2; + continue; + } + + if ((stricmp (argv[0], "-o") == 0) || (stricmp (argv[0], "--outputfile") == 0)) { + if (argv[1] == NULL || argv[1][0] == '-') { + Error (NULL, 0, 1003, "Invalid option value", "Output file is missing for -o option"); + goto Finish; + } + OutputFileName = argv[1]; + argc -= 2; + argv += 2; + continue; + } + + if ((stricmp (argv[0], "-g") == 0) || (stricmp (argv[0], "--fileguid") == 0)) { + Status = StringToGuid (argv[1], &FileGuid); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]); + goto Finish; + } + argc -= 2; + argv += 2; + continue; + } + + if ((stricmp (argv[0], "-x") == 0) || (stricmp (argv[0], "--fixed") == 0)) { + FfsAttrib |= FFS_ATTRIB_FIXED; + argc -= 1; + argv += 1; + continue; + } + + if ((stricmp (argv[0], "-s") == 0) || (stricmp (argv[0], "--checksum") == 0)) { + FfsAttrib |= FFS_ATTRIB_CHECKSUM; + argc -= 1; + argv += 1; + continue; + } + + if ((stricmp (argv[0], "-a") == 0) || (stricmp (argv[0], "--align") == 0)) { + if (argv[1] == NULL || argv[1][0] == '-') { + Error (NULL, 0, 1003, "Invalid option value", "Align value is missing for -a option"); + goto Finish; + } + for (Index = 0; Index < sizeof (mFfsValidAlignName) / sizeof (CHAR8 *); Index ++) { + if (stricmp (argv[1], mFfsValidAlignName[Index]) == 0) { + break; + } + } + if (Index == sizeof (mFfsValidAlignName) / sizeof (CHAR8 *)) { + if ((stricmp (argv[1], "1") == 0) || (stricmp (argv[1], "2") == 0) || (stricmp (argv[1], "4") == 0)) { + // + // 1, 2, 4 byte alignment same to 8 byte alignment + // + Index = 0; + } else { + Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]); + goto Finish; + } + } + FfsAlign = Index; + argc -= 2; + argv += 2; + continue; + } + + if ((stricmp (argv[0], "-i") == 0) || (stricmp (argv[0], "--sectionfile") == 0)) { + // + // Get Input file name and its alignment + // + if (argv[1] == NULL || argv[1][0] == '-') { + Error (NULL, 0, 1003, "Invalid option value", "input section file is missing for -i option"); + goto Finish; + } + + // + // Allocate Input file name buffer and its alignment buffer. + // + if ((InputFileNum == 0) && (InputFileName == NULL)) { + InputFileName = (CHAR8 **) malloc (MAXIMUM_INPUT_FILE_NUM * sizeof (CHAR8 *)); + if (InputFileName == NULL) { + Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!"); + return STATUS_ERROR; + } + memset (InputFileName, 0, (MAXIMUM_INPUT_FILE_NUM * sizeof (CHAR8 *))); + + InputFileAlign = (UINT32 *) malloc (MAXIMUM_INPUT_FILE_NUM * sizeof (UINT32)); + if (InputFileAlign == NULL) { + Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!"); + free (InputFileName); + return STATUS_ERROR; + } + memset (InputFileAlign, 0, MAXIMUM_INPUT_FILE_NUM * sizeof (UINT32)); + } else if (InputFileNum % MAXIMUM_INPUT_FILE_NUM == 0) { + // + // InputFileName and alignment buffer too small, need to realloc + // + InputFileName = (CHAR8 **) realloc ( + InputFileName, + (InputFileNum + MAXIMUM_INPUT_FILE_NUM) * sizeof (CHAR8 *) + ); + + if (InputFileName == NULL) { + Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!"); + free (InputFileAlign); + return STATUS_ERROR; + } + memset (&(InputFileName[InputFileNum]), 0, (MAXIMUM_INPUT_FILE_NUM * sizeof (CHAR8 *))); + + InputFileAlign = (UINT32 *) realloc ( + InputFileAlign, + (InputFileNum + MAXIMUM_INPUT_FILE_NUM) * sizeof (UINT32) + ); + + if (InputFileAlign == NULL) { + Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!"); + free (InputFileName); + return STATUS_ERROR; + } + memset (&(InputFileAlign[InputFileNum]), 0, (MAXIMUM_INPUT_FILE_NUM * sizeof (UINT32))); + } + + InputFileName[InputFileNum] = argv[1]; + argc -= 2; + argv += 2; + + if (argc <= 0) { + InputFileNum ++; + break; + } + + // + // Section File alignment requirement + // + if ((stricmp (argv[0], "-n") == 0) || (stricmp (argv[0], "--sectionalign") == 0)) { + Status = StringtoAlignment (argv[1], &(InputFileAlign[InputFileNum])); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]); + goto Finish; + } + argc -= 2; + argv += 2; + } + InputFileNum ++; + continue; + } + + if ((stricmp (argv[0], "-n") == 0) || (stricmp (argv[0], "--sectionalign") == 0)) { + Error (NULL, 0, 1000, "Unknown option", "SectionAlign option must be specified with section file."); + goto Finish; + } + + if ((stricmp (argv[0], "-v") == 0) || (stricmp (argv[0], "--verbose") == 0)) { + SetPrintLevel (VERBOSE_LOG_LEVEL); + VerboseMsg ("Verbose output Mode Set!"); + argc --; + argv ++; + continue; + } + + if ((stricmp (argv[0], "-q") == 0) || (stricmp (argv[0], "--quiet") == 0)) { + SetPrintLevel (KEY_LOG_LEVEL); + KeyMsg ("Quiet output Mode Set!"); + argc --; + argv ++; + continue; + } + + if ((stricmp (argv[0], "-d") == 0) || (stricmp (argv[0], "--debug") == 0)) { + Status = AsciiStringToUint64 (argv[1], FALSE, &LogLevel); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]); + goto Finish; + } + if (LogLevel > 9) { + Error (NULL, 0, 1003, "Invalid option value", "Debug Level range is 0-9, current input level is %d", LogLevel); + goto Finish; + } + SetPrintLevel (LogLevel); + DebugMsg (NULL, 0, 9, "Debug Mode Set", "Debug Output Mode Level %s is set!", argv[1]); + argc -= 2; + argv += 2; + continue; + } + + Error (NULL, 0, 1000, "Unknown option", argv[0]); + goto Finish; + } + + VerboseMsg ("%s tool start.", UTILITY_NAME); + + // + // Check the complete input paramters. + // + if (FfsFiletype == EFI_FV_FILETYPE_ALL) { + Error (NULL, 0, 1001, "Missing option", "filetype"); + goto Finish; + } + + if (CompareGuid (&FileGuid, &mZeroGuid) == 0) { + Error (NULL, 0, 1001, "Missing option", "fileguid"); + goto Finish; + } + + if (InputFileNum == 0) { + Error (NULL, 0, 1001, "Missing option", "Input files"); + goto Finish; + } + + // + // Output input parameter information + // + VerboseMsg ("Fv File type is %s", mFfsFileType [FfsFiletype]); + VerboseMsg ("Output file name is %s", OutputFileName); + VerboseMsg ("FFS File Guid is %08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X", + FileGuid.Data1, + FileGuid.Data2, + FileGuid.Data3, + FileGuid.Data4[0], + FileGuid.Data4[1], + FileGuid.Data4[2], + FileGuid.Data4[3], + FileGuid.Data4[4], + FileGuid.Data4[5], + FileGuid.Data4[6], + FileGuid.Data4[7]); + if ((FfsAttrib & FFS_ATTRIB_FIXED) != 0) { + VerboseMsg ("FFS File has the fixed file attribute"); + } + if ((FfsAttrib & FFS_ATTRIB_CHECKSUM) != 0) { + VerboseMsg ("FFS File requires the checksum of the whole file"); + } + VerboseMsg ("FFS file alignment is %s", mFfsValidAlignName[FfsAlign]); + for (Index = 0; Index < InputFileNum; Index ++) { + if (InputFileAlign[Index] == 0) { + // + // Minimum alignment is 1 byte. + // + InputFileAlign[Index] = 1; + } + VerboseMsg ("the %dth input section name is %s and section alignment is %d", Index, InputFileName[Index], InputFileAlign[Index]); + } + + // + // Calculate the size of all input section files. + // + Status = GetSectionContents ( + InputFileName, + InputFileAlign, + InputFileNum, + FileBuffer, + &FileSize, + &MaxAlignment, + &PeSectionNum + ); + + if ((FfsFiletype == EFI_FV_FILETYPE_SECURITY_CORE || + FfsFiletype == EFI_FV_FILETYPE_PEI_CORE || + FfsFiletype == EFI_FV_FILETYPE_DXE_CORE) && (PeSectionNum != 1)) { + Error (NULL, 0, 2000, "Invalid parameter", "Fv File type %s must have one and only one Pe or Te section, but %d Pe/Te section are input", mFfsFileType [FfsFiletype], PeSectionNum); + goto Finish; + } + + if ((FfsFiletype == EFI_FV_FILETYPE_PEIM || + FfsFiletype == EFI_FV_FILETYPE_DRIVER || + FfsFiletype == EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER || + FfsFiletype == EFI_FV_FILETYPE_APPLICATION) && (PeSectionNum < 1)) { + Error (NULL, 0, 2000, "Invalid parameter", "Fv File type %s must have at least one Pe or Te section, but no Pe/Te section is input", mFfsFileType [FfsFiletype]); + goto Finish; + } + + if (Status == EFI_BUFFER_TOO_SMALL) { + FileBuffer = (UINT8 *) malloc (FileSize); + if (FileBuffer == NULL) { + Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!"); + goto Finish; + } + memset (FileBuffer, 0, FileSize); + + // + // read all input file contents into a buffer + // + Status = GetSectionContents ( + InputFileName, + InputFileAlign, + InputFileNum, + FileBuffer, + &FileSize, + &MaxAlignment, + &PeSectionNum + ); + } + + if (EFI_ERROR (Status)) { + goto Finish; + } + + // + // Create Ffs file header. + // + memset (&FfsFileHeader, 0, sizeof (EFI_FFS_FILE_HEADER)); + memcpy (&FfsFileHeader.Name, &FileGuid, sizeof (EFI_GUID)); + FfsFileHeader.Type = FfsFiletype; + // + // Update FFS Alignment based on the max alignment required by input section files + // + VerboseMsg ("the max alignment of all input sections is %d", MaxAlignment); + for (Index = 0; Index < sizeof (mFfsValidAlign) / sizeof (UINT32) - 1; Index ++) { + if ((MaxAlignment > mFfsValidAlign [Index]) && (MaxAlignment <= mFfsValidAlign [Index + 1])) { + break; + } + } + if (FfsAlign < Index) { + FfsAlign = Index; + } + VerboseMsg ("the alignment of the genreated FFS file is %d", mFfsValidAlign [FfsAlign + 1]); + FfsFileHeader.Attributes = FfsAttrib | (FfsAlign << 3); + + // + // Now FileSize includes the EFI_FFS_FILE_HEADER + // + FileSize += sizeof (EFI_FFS_FILE_HEADER); + VerboseMsg ("the size of the genreated FFS file is %d bytes", FileSize); + FfsFileHeader.Size[0] = (UINT8) (FileSize & 0xFF); + FfsFileHeader.Size[1] = (UINT8) ((FileSize & 0xFF00) >> 8); + FfsFileHeader.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; + // + FfsFileHeader.IntegrityCheck.Checksum.Header = CalculateChecksum8 ( + (UINT8 *) &FfsFileHeader, + sizeof (EFI_FFS_FILE_HEADER) + ); + + if (FfsFileHeader.Attributes & FFS_ATTRIB_CHECKSUM) { + // + // Ffs header checksum = zero, so only need to calculate ffs body. + // + FfsFileHeader.IntegrityCheck.Checksum.File = CalculateChecksum8 ( + FileBuffer, + FileSize - sizeof (EFI_FFS_FILE_HEADER) + ); + } else { + FfsFileHeader.IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM; + } + + FfsFileHeader.State = EFI_FILE_HEADER_CONSTRUCTION | EFI_FILE_HEADER_VALID | EFI_FILE_DATA_VALID; + + // + // Open output file to write ffs data. + // + remove(OutputFileName); + FfsFile = fopen (OutputFileName, "wb"); + if (FfsFile == NULL) { + Error (NULL, 0, 0001, "Error opening file", OutputFileName); + goto Finish; + } + // + // write header + // + fwrite (&FfsFileHeader, 1, sizeof (FfsFileHeader), FfsFile); + // + // write data + // + fwrite (FileBuffer, 1, FileSize - sizeof (EFI_FFS_FILE_HEADER), FfsFile); + + fclose (FfsFile); + +Finish: + if (InputFileName != NULL) { + free (InputFileName); + } + if (InputFileAlign != NULL) { + free (InputFileAlign); + } + if (FileBuffer != NULL) { + free (FileBuffer); + } + // + // 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. + // + VerboseMsg ("%s tool done with return code is 0x%x.", UTILITY_NAME, GetUtilityStatus ()); + + return GetUtilityStatus (); +} diff --git a/BaseTools/Source/C/GenFfs/Makefile b/BaseTools/Source/C/GenFfs/Makefile new file mode 100644 index 0000000000..060cd03209 --- /dev/null +++ b/BaseTools/Source/C/GenFfs/Makefile @@ -0,0 +1,10 @@ +!INCLUDE ..\Makefiles\ms.common + +APPNAME = GenFfs + +LIBS = $(LIB_PATH)\Common.lib + +OBJECTS = GenFfs.obj + +!INCLUDE ..\Makefiles\ms.app + diff --git a/BaseTools/Source/C/GenFv/GNUmakefile b/BaseTools/Source/C/GenFv/GNUmakefile new file mode 100644 index 0000000000..7cb1664350 --- /dev/null +++ b/BaseTools/Source/C/GenFv/GNUmakefile @@ -0,0 +1,18 @@ +ARCH ?= IA32 +MAKEROOT ?= .. + +APPNAME = GenFv + +OBJECTS = GenFv.o GenFvInternalLib.o + +include $(MAKEROOT)/Makefiles/app.makefile + +LIBS = -lCommon +ifeq ($(CYGWIN), CYGWIN) + LIBS += -L/lib/e2fsprogs -luuid +endif + +ifeq ($(LINUX), Linux) + LIBS += -luuid +endif + diff --git a/BaseTools/Source/C/GenFv/GenFv.c b/BaseTools/Source/C/GenFv/GenFv.c new file mode 100644 index 0000000000..e080422e54 --- /dev/null +++ b/BaseTools/Source/C/GenFv/GenFv.c @@ -0,0 +1,713 @@ +/** @file + +Copyright (c) 2007 - 2008, 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: + + GenFv.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 +#include +#include +#include "GenFvInternalLib.h" + +// +// Utility Name +// +#define UTILITY_NAME "GenFv" + +// +// Utility version information +// +#define UTILITY_MAJOR_VERSION 0 +#define UTILITY_MINOR_VERSION 1 +#define GENFV_UPDATE_TIME " updated on 2008/11/21" + +EFI_GUID mEfiFirmwareFileSystem2Guid = EFI_FIRMWARE_FILE_SYSTEM2_GUID; + +STATIC +VOID +Version ( + VOID +) +/*++ + +Routine Description: + + Displays the standard utility information to SDTOUT + +Arguments: + + None + +Returns: + + None + +--*/ +{ + fprintf (stdout, "%s Version %d.%d %s\n", UTILITY_NAME, UTILITY_MAJOR_VERSION, UTILITY_MINOR_VERSION, GENFV_UPDATE_TIME); +} + +STATIC +VOID +Usage ( + VOID + ) +/*++ + +Routine Description: + + Displays the utility usage syntax to STDOUT + +Arguments: + + None + +Returns: + + None + +--*/ +{ + // + // Summary usage + // + fprintf (stdout, "\nUsage: %s [options]\n\n", UTILITY_NAME); + + // + // Copyright declaration + // + fprintf (stdout, "Copyright (c) 2007, Intel Corporation. All rights reserved.\n\n"); + + // + // Details Option + // + fprintf (stdout, "Options:\n"); + fprintf (stdout, " -o FileName, --outputfile FileName\n\ + File is the FvImage or CapImage to be created.\n"); + fprintf (stdout, " -i FileName, --inputfile FileName\n\ + File is the input FV.inf or Cap.inf to specify\n\ + how to construct FvImage or CapImage.\n"); + fprintf (stdout, " -b BlockSize, --blocksize BlockSize\n\ + BlockSize is one HEX or DEC format value\n\ + BlockSize is required by Fv Image.\n"); + fprintf (stdout, " -n NumberBlock, --numberblock NumberBlock\n\ + NumberBlock is one HEX or DEC format value\n\ + NumberBlock is one optional parameter.\n"); + fprintf (stdout, " -f FfsFile, --ffsfile FfsFile\n\ + FfsFile is placed into Fv Image\n\ + multi files can input one by one\n"); + fprintf (stdout, " -s FileTakenSize, --filetakensize FileTakenSize\n\ + FileTakenSize specifies the size of the required\n\ + space that the input file is placed in Fvimage.\n\ + It is specified together with the input file.\n"); + fprintf (stdout, " -r Address, --baseaddr Address\n\ + Address is the rebase start address for drivers that\n\ + run in Flash. It supports DEC or HEX digital format.\n\ + If it is set to zero, no rebase action will be taken\n"); + fprintf (stdout, " -a AddressFile, --addrfile AddressFile\n\ + AddressFile is one file used to record boot driver base\n\ + address and runtime driver base address. And this tool\n\ + will update these two addresses after it relocates all\n\ + boot drivers and runtime drivers in this fv iamge to\n\ + the preferred loaded memory address.\n"); + fprintf (stdout, " -m logfile, --map logfile\n\ + Logfile is the output fv map file name. if it is not\n\ + given, the FvName.map will be the default map file name\n"); + fprintf (stdout, " -g Guid, --guid GuidValue\n\ + GuidValue is one specific capsule guid value\n\ + or fv file system guid value.\n\ + Its format is xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\n"); + fprintf (stdout, " --FvNameGuid GuidValue is the Fv Name Guid value.\n\ + Its format is xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\n"); + fprintf (stdout, " --capflag CapFlag Capsule Reset Flag can be PersistAcrossReset,\n\ + or PopulateSystemTable or not set.\n"); + fprintf (stdout, " --capheadsize HeadSize\n\ + HeadSize is one HEX or DEC format value\n\ + HeadSize is required by Capsule Image.\n"); + fprintf (stdout, " -c, --capsule Create Capsule Image.\n"); + fprintf (stdout, " -p, --dump Dump Capsule Image header.\n"); + fprintf (stdout, " -v, --verbose Turn on verbose output with informational messages.\n"); + fprintf (stdout, " -q, --quiet Disable all messages except key message and fatal error\n"); + fprintf (stdout, " -d, --debug level Enable debug messages, at input debug level.\n"); + fprintf (stdout, " --version Show program's version number and exit.\n"); + fprintf (stdout, " -h, --help Show this help message and exit.\n"); +} + +UINT32 mFvTotalSize; +UINT32 mFvTakenSize; + +int +main ( + IN int argc, + IN char **argv + ) +/*++ + +Routine Description: + + This utility uses GenFvImage.Lib to build a firmware volume image. + +Arguments: + + FvInfFileName The name of an FV image description file or Capsule Image. + + 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; + CHAR8 *AddrFileName; + CHAR8 *MapFileName; + CHAR8 *InfFileImage; + UINT32 InfFileSize; + CHAR8 *OutFileName; + CHAR8 ValueString[_MAX_PATH]; + BOOLEAN CapsuleFlag; + BOOLEAN DumpCapsule; + MEMORY_FILE AddrMemoryFile; + FILE *FpFile; + EFI_CAPSULE_HEADER *CapsuleHeader; + UINT64 LogLevel, TempNumber; + UINT32 Index; + + InfFileName = NULL; + AddrFileName = NULL; + InfFileImage = NULL; + OutFileName = NULL; + MapFileName = NULL; + InfFileSize = 0; + CapsuleFlag = FALSE; + DumpCapsule = FALSE; + FpFile = NULL; + CapsuleHeader = NULL; + LogLevel = 0; + TempNumber = 0; + Index = 0; + mFvTotalSize = 0; + mFvTakenSize = 0; + + SetUtilityName (UTILITY_NAME); + + if (argc == 1) { + Error (NULL, 0, 1001, "Missing options", "No input options specified."); + Usage (); + return STATUS_ERROR; + } + + // + // Init global data to Zero + // + memset (&mFvDataInfo, 0, sizeof (FV_INFO)); + memset (&mCapDataInfo, 0, sizeof (CAP_INFO)); + // + // Set the default FvGuid + // + memcpy (&mFvDataInfo.FvFileSystemGuid, &mEfiFirmwareFileSystem2Guid, sizeof (EFI_GUID)); + + // + // Parse command line + // + argc --; + argv ++; + + if ((stricmp (argv[0], "-h") == 0) || (stricmp (argv[0], "--help") == 0)) { + Version (); + Usage (); + return STATUS_SUCCESS; + } + + if (stricmp (argv[0], "--version") == 0) { + Version (); + return STATUS_SUCCESS; + } + + while (argc > 0) { + if ((stricmp (argv[0], "-i") == 0) || (stricmp (argv[0], "--inputfile") == 0)) { + InfFileName = argv[1]; + if (InfFileName == NULL) { + Error (NULL, 0, 1003, "Invalid option value", "Input file can't be null"); + return STATUS_ERROR; + } + argc -= 2; + argv += 2; + continue; + } + + if ((stricmp (argv[0], "-a") == 0) || (stricmp (argv[0], "--addrfile") == 0)) { + AddrFileName = argv[1]; + if (AddrFileName == NULL) { + Error (NULL, 0, 1003, "Invalid option value", "Address file can't be null"); + return STATUS_ERROR; + } + argc -= 2; + argv += 2; + continue; + } + + if ((stricmp (argv[0], "-o") == 0) || (stricmp (argv[0], "--outputfile") == 0)) { + OutFileName = argv[1]; + if (OutFileName == NULL) { + Error (NULL, 0, 1003, "Invalid option value", "Output file can't be null"); + return STATUS_ERROR; + } + argc -= 2; + argv += 2; + continue; + } + + if ((stricmp (argv[0], "-r") == 0) || (stricmp (argv[0], "--baseaddr") == 0)) { + Status = AsciiStringToUint64 (argv[1], FALSE, &TempNumber); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]); + return STATUS_ERROR; + } + mFvDataInfo.BaseAddress = TempNumber; + mFvDataInfo.BaseAddressSet = TRUE; + argc -= 2; + argv += 2; + continue; + } + + if ((stricmp (argv[0], "-b") == 0) || (stricmp (argv[0], "--blocksize") == 0)) { + Status = AsciiStringToUint64 (argv[1], FALSE, &TempNumber); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]); + return STATUS_ERROR; + } + if (TempNumber == 0) { + Error (NULL, 0, 1003, "Invalid option value", "Fv block size can't be be set to zero"); + return STATUS_ERROR; + } + mFvDataInfo.FvBlocks[0].Length = (UINT32) TempNumber; + DebugMsg (NULL, 0, 9, "FV Block Size", "%s = 0x%x", EFI_BLOCK_SIZE_STRING, TempNumber); + argc -= 2; + argv += 2; + continue; + } + + if ((stricmp (argv[0], "-n") == 0) || (stricmp (argv[0], "--numberblock") == 0)) { + Status = AsciiStringToUint64 (argv[1], FALSE, &TempNumber); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]); + return STATUS_ERROR; + } + if (TempNumber == 0) { + Error (NULL, 0, 1003, "Invalid option value", "Fv block number can't be set to zero"); + return STATUS_ERROR; + } + mFvDataInfo.FvBlocks[0].NumBlocks = (UINT32) TempNumber; + DebugMsg (NULL, 0, 9, "FV Number Block", "%s = 0x%x", EFI_NUM_BLOCKS_STRING, TempNumber); + argc -= 2; + argv += 2; + continue; + } + + if ((stricmp (argv[0], "-f") == 0) || (stricmp (argv[0], "--ffsfile") == 0)) { + if (argv[1] == NULL) { + Error (NULL, 0, 1003, "Invalid option value", "Input Ffsfile can't be null"); + return STATUS_ERROR; + } + strcpy (mFvDataInfo.FvFiles[Index], argv[1]); + DebugMsg (NULL, 0, 9, "FV component file", "the %dth name is %s", Index + 1, argv[1]); + argc -= 2; + argv += 2; + + if (argc > 0) { + if ((stricmp (argv[0], "-s") == 0) || (stricmp (argv[0], "--filetakensize") == 0)) { + if (argv[1] == NULL) { + Error (NULL, 0, 1003, "Invalid option value", "Ffsfile Size can't be null"); + return STATUS_ERROR; + } + Status = AsciiStringToUint64 (argv[1], FALSE, &TempNumber); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]); + return STATUS_ERROR; + } + mFvDataInfo.SizeofFvFiles[Index] = TempNumber; + DebugMsg (NULL, 0, 9, "FV component file size", "the %dth size is %s", Index + 1, argv[1]); + argc -= 2; + argv += 2; + } + } + Index ++; + continue; + } + + if ((stricmp (argv[0], "-s") == 0) || (stricmp (argv[0], "--filetakensize") == 0)) { + Error (NULL, 0, 1003, "Invalid option", "It must be specified together with -f option to specify the file size."); + return STATUS_ERROR; + } + + if ((stricmp (argv[0], "-c") == 0) || (stricmp (argv[0], "--capsule") == 0)) { + CapsuleFlag = TRUE; + argc --; + argv ++; + continue; + } + + if (stricmp (argv[0], "--capheadsize") == 0) { + // + // Get Capsule Image Header Size + // + Status = AsciiStringToUint64 (argv[1], FALSE, &TempNumber); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]); + return STATUS_ERROR; + } + mCapDataInfo.HeaderSize = (UINT32) TempNumber; + DebugMsg (NULL, 0, 9, "Capsule Header size", "%s = 0x%x", EFI_CAPSULE_HEADER_SIZE_STRING, TempNumber); + argc -= 2; + argv += 2; + continue; + } + + if (stricmp (argv[0], "--capflag") == 0) { + // + // Get Capsule Header + // + if (argv[1] == NULL) { + Error (NULL, 0, 1003, "Option value is not set", "%s = %s", argv[0], argv[1]); + return STATUS_ERROR; + } + if (strcmp (argv[1], "PopulateSystemTable") == 0) { + mCapDataInfo.Flags |= CAPSULE_FLAGS_PERSIST_ACROSS_RESET | CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE; + } else if (strcmp (argv[1], "PersistAcrossReset") == 0) { + mCapDataInfo.Flags |= CAPSULE_FLAGS_PERSIST_ACROSS_RESET; + } else { + Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]); + return STATUS_ERROR; + } + DebugMsg (NULL, 0, 9, "Capsule Flag", argv[1]); + argc -= 2; + argv += 2; + continue; + } + + if (stricmp (argv[0], "--capguid") == 0) { + // + // Get the Capsule Guid + // + Status = StringToGuid (argv[1], &mCapDataInfo.CapGuid); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 1003, "Invalid option value", "%s = %s", EFI_CAPSULE_GUID_STRING, argv[1]); + return STATUS_ERROR; + } + DebugMsg (NULL, 0, 9, "Capsule Guid", "%s = %s", EFI_CAPSULE_GUID_STRING, argv[1]); + argc -= 2; + argv += 2; + continue; + } + + if ((stricmp (argv[0], "-g") == 0) || (stricmp (argv[0], "--guid") == 0)) { + // + // Get the Capsule or Fv Guid + // + Status = StringToGuid (argv[1], &mCapDataInfo.CapGuid); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 1003, "Invalid option value", "%s = %s", EFI_GUID_STRING, argv[1]); + return STATUS_ERROR; + } + memcpy (&mFvDataInfo.FvFileSystemGuid, &mCapDataInfo.CapGuid, sizeof (EFI_GUID)); + mFvDataInfo.FvFileSystemGuidSet = TRUE; + DebugMsg (NULL, 0, 9, "Capsule Guid", "%s = %s", EFI_CAPSULE_GUID_STRING, argv[1]); + DebugMsg (NULL, 0, 9, "FV Guid", "%s = %s", EFI_FV_FILESYSTEMGUID_STRING, argv[1]); + argc -= 2; + argv += 2; + continue; + } + + if (stricmp (argv[0], "--FvNameGuid") == 0) { + // + // Get Fv Name Guid + // + Status = StringToGuid (argv[1], &mFvDataInfo.FvNameGuid); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 1003, "Invalid option value", "%s = %s", EFI_GUID_STRING, argv[1]); + return STATUS_ERROR; + } + mFvDataInfo.FvNameGuidSet = TRUE; + DebugMsg (NULL, 0, 9, "FV Name Guid", "%s = %s", EFI_FV_NAMEGUID_STRING, argv[1]); + argc -= 2; + argv += 2; + continue; + } + + if ((stricmp (argv[0], "-p") == 0) || (stricmp (argv[0], "--dump") == 0)) { + DumpCapsule = TRUE; + argc --; + argv ++; + continue; + } + + if ((stricmp (argv[0], "-m") == 0) || (stricmp (argv[0], "--map") == 0)) { + MapFileName = argv[1]; + if (MapFileName == NULL) { + Error (NULL, 0, 1003, "Invalid option value", "Map file can't be null"); + return STATUS_ERROR; + } + argc -= 2; + argv += 2; + continue; + } + + if ((stricmp (argv[0], "-v") == 0) || (stricmp (argv[0], "--verbose") == 0)) { + SetPrintLevel (VERBOSE_LOG_LEVEL); + VerboseMsg ("Verbose output Mode Set!"); + argc --; + argv ++; + continue; + } + + if ((stricmp (argv[0], "-q") == 0) || (stricmp (argv[0], "--quiet") == 0)) { + SetPrintLevel (KEY_LOG_LEVEL); + KeyMsg ("Quiet output Mode Set!"); + argc --; + argv ++; + continue; + } + + if ((stricmp (argv[0], "-d") == 0) || (stricmp (argv[0], "--debug") == 0)) { + Status = AsciiStringToUint64 (argv[1], FALSE, &LogLevel); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]); + return STATUS_ERROR; + } + if (LogLevel > 9) { + Error (NULL, 0, 1003, "Invalid option value", "Debug Level range is 0-9, current input level is %d", LogLevel); + return STATUS_ERROR; + } + SetPrintLevel (LogLevel); + DebugMsg (NULL, 0, 9, "Debug Mode Set", "Debug Output Mode Level %s is set!", argv[1]); + argc -= 2; + argv += 2; + continue; + } + + // + // Don't recognize the parameter. + // + Error (NULL, 0, 1000, "Unknown option", "%s", argv[0]); + return STATUS_ERROR; + } + + VerboseMsg ("%s tool start.", UTILITY_NAME); + + // + // check input parameter, InfFileName can be NULL + // + if (InfFileName == NULL && DumpCapsule) { + Error (NULL, 0, 1001, "Missing option", "Input Capsule Image"); + return STATUS_ERROR; + } + VerboseMsg ("the input FvInf or CapInf file name is %s", InfFileName); + + if (!DumpCapsule && OutFileName == NULL) { + Error (NULL, 0, 1001, "Missing option", "Output File"); + return STATUS_ERROR; + } + if (OutFileName != NULL) { + VerboseMsg ("the output file name is %s", OutFileName); + } + + // + // Read boot and runtime address from address file + // + if (AddrFileName != NULL) { + VerboseMsg ("the input address file name is %s", AddrFileName); + Status = GetFileImage (AddrFileName, &InfFileImage, &InfFileSize); + if (EFI_ERROR (Status)) { + return STATUS_ERROR; + } + + AddrMemoryFile.FileImage = InfFileImage; + AddrMemoryFile.CurrentFilePointer = InfFileImage; + AddrMemoryFile.Eof = InfFileImage + InfFileSize; + + // + // Read the boot driver base address for this FV image + // + Status = FindToken (&AddrMemoryFile, OPTIONS_SECTION_STRING, EFI_FV_BOOT_DRIVER_BASE_ADDRESS_STRING, 0, ValueString); + if (Status == EFI_SUCCESS) { + // + // Get the base address + // + Status = AsciiStringToUint64 (ValueString, FALSE, &TempNumber); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 2000, "Invalid parameter", "%s = %s", EFI_FV_BOOT_DRIVER_BASE_ADDRESS_STRING, ValueString); + return STATUS_ERROR; + } + mFvDataInfo.BootBaseAddress = TempNumber; + DebugMsg (NULL, 0, 9, "Boot driver base address", "%s = %s", EFI_FV_BOOT_DRIVER_BASE_ADDRESS_STRING, ValueString); + } + + // + // Read the FV runtime driver base address + // + Status = FindToken (&AddrMemoryFile, OPTIONS_SECTION_STRING, EFI_FV_RUNTIME_DRIVER_BASE_ADDRESS_STRING, 0, ValueString); + if (Status == EFI_SUCCESS) { + // + // Get the base address + // + Status = AsciiStringToUint64 (ValueString, FALSE, &TempNumber); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 2000, "Invalid parameter", "%s = %s", EFI_FV_RUNTIME_DRIVER_BASE_ADDRESS_STRING, ValueString); + return STATUS_ERROR; + } + mFvDataInfo.RuntimeBaseAddress = TempNumber; + DebugMsg (NULL, 0, 9, "Runtime driver base address", "%s = %s", EFI_FV_RUNTIME_DRIVER_BASE_ADDRESS_STRING, ValueString); + } + + // + // free the allocated memory space for addr file. + // + free (InfFileImage); + InfFileImage = NULL; + InfFileSize = 0; + } + + // + // Read the INF file image + // + if (InfFileName != NULL) { + Status = GetFileImage (InfFileName, &InfFileImage, &InfFileSize); + if (EFI_ERROR (Status)) { + return STATUS_ERROR; + } + } + + if (DumpCapsule) { + VerboseMsg ("Dump the capsule header information for the input capsule image %s", InfFileName); + // + // Dump Capsule Image Header Information + // + CapsuleHeader = (EFI_CAPSULE_HEADER *) InfFileImage; + if (OutFileName == NULL) { + FpFile = stdout; + } else { + FpFile = fopen (OutFileName, "w"); + if (FpFile == NULL) { + Error (NULL, 0, 0001, "Error opening file", OutFileName); + return STATUS_ERROR; + } + } + fprintf (FpFile, "Capsule %s Image Header Information\n", InfFileName); + fprintf (FpFile, " GUID %08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X\n", + 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]); + fprintf (FpFile, " Header size 0x%08X\n", CapsuleHeader->HeaderSize); + fprintf (FpFile, " Flags 0x%08X\n", CapsuleHeader->Flags); + fprintf (FpFile, " Capsule image size 0x%08X\n", CapsuleHeader->CapsuleImageSize); + fclose (FpFile); + } else if (CapsuleFlag) { + VerboseMsg ("Create capsule image"); + // + // Call the GenerateCapImage to generate Capsule Image + // + for (Index = 0; mFvDataInfo.FvFiles[Index][0] != '\0'; Index ++) { + strcpy (mCapDataInfo.CapFiles[Index], mFvDataInfo.FvFiles[Index]); + } + + Status = GenerateCapImage ( + InfFileImage, + InfFileSize, + OutFileName + ); + } else { + VerboseMsg ("Create Fv image and its map file"); + if (mFvDataInfo.BaseAddress != 0) { + VerboseMsg ("FvImage Rebase Address is 0x%X", mFvDataInfo.BaseAddress); + } + // + // Call the GenerateFvImage to generate Fv Image + // + Status = GenerateFvImage ( + InfFileImage, + InfFileSize, + OutFileName, + MapFileName + ); + } + + // + // free InfFileImage memory + // + if (InfFileImage != NULL) { + free (InfFileImage); + } + + // + // update boot driver address and runtime driver address in address file + // + if (Status == EFI_SUCCESS && AddrFileName != NULL) { + FpFile = fopen (AddrFileName, "w"); + if (FpFile == NULL) { + Error (NULL, 0, 0001, "Error opening file", AddrFileName); + return STATUS_ERROR; + } + fprintf (FpFile, OPTIONS_SECTION_STRING); + fprintf (FpFile, "\n"); + if (mFvDataInfo.BootBaseAddress != 0) { + fprintf (FpFile, EFI_FV_BOOT_DRIVER_BASE_ADDRESS_STRING); + fprintf (FpFile, " = 0x%lx\n", mFvDataInfo.BootBaseAddress); + DebugMsg (NULL, 0, 9, "Updated boot driver base address", "%s = 0x%x", EFI_FV_RUNTIME_DRIVER_BASE_ADDRESS_STRING, mFvDataInfo.BootBaseAddress); + } + if (mFvDataInfo.RuntimeBaseAddress != 0) { + fprintf (FpFile, EFI_FV_RUNTIME_DRIVER_BASE_ADDRESS_STRING); + fprintf (FpFile, " = 0x%lx\n", mFvDataInfo.RuntimeBaseAddress); + DebugMsg (NULL, 0, 9, "Updated runtime driver base address", "%s = 0x%x", EFI_FV_RUNTIME_DRIVER_BASE_ADDRESS_STRING, mFvDataInfo.RuntimeBaseAddress); + } + fclose (FpFile); + } + + if (Status == EFI_SUCCESS) { + DebugMsg (NULL, 0, 9, "The Total Fv Size", "%s = 0x%x", EFI_FV_TOTAL_SIZE_STRING, mFvTotalSize); + DebugMsg (NULL, 0, 9, "The used Fv Size", "%s = 0x%x", EFI_FV_TAKEN_SIZE_STRING, mFvTakenSize); + DebugMsg (NULL, 0, 9, "The space Fv size", "%s = 0x%x", EFI_FV_SPACE_SIZE_STRING, mFvTotalSize - mFvTakenSize); + } + + VerboseMsg ("%s tool done with return code is 0x%x.", UTILITY_NAME, GetUtilityStatus ()); + + return GetUtilityStatus (); +} diff --git a/BaseTools/Source/C/GenFv/GenFvInternalLib.c b/BaseTools/Source/C/GenFv/GenFvInternalLib.c new file mode 100644 index 0000000000..ad3e7a6e08 --- /dev/null +++ b/BaseTools/Source/C/GenFv/GenFvInternalLib.c @@ -0,0 +1,3574 @@ +/** @file + +Copyright (c) 2004 - 2008, 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: + + GenFvInternalLib.c + +Abstract: + + This file contains the internal functions required to generate a Firmware Volume. + +**/ + +// +// Include files +// +#ifdef __GNUC__ +#include +#include +#endif +#include +#ifndef __GNUC__ +#include +#endif +#include + +#include "GenFvInternalLib.h" +#include "FvLib.h" +#include "PeCoffLib.h" +#include "WinNtInclude.h" + +BOOLEAN mArm = FALSE; +STATIC UINT32 MaxFfsAlignment = 0; + +EFI_GUID mEfiFirmwareVolumeTopFileGuid = EFI_FFS_VOLUME_TOP_FILE_GUID; +EFI_GUID mFileGuidArray [MAX_NUMBER_OF_FILES_IN_FV]; +EFI_GUID mZeroGuid = {0x0, 0x0, 0x0, {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}; +EFI_GUID mDefaultCapsuleGuid = {0x3B6686BD, 0x0D76, 0x4030, { 0xB7, 0x0E, 0xB5, 0x51, 0x9E, 0x2F, 0xC5, 0xA0 }}; + +CHAR8 *mFvbAttributeName[] = { + EFI_FVB2_READ_DISABLED_CAP_STRING, + EFI_FVB2_READ_ENABLED_CAP_STRING, + EFI_FVB2_READ_STATUS_STRING, + EFI_FVB2_WRITE_DISABLED_CAP_STRING, + EFI_FVB2_WRITE_ENABLED_CAP_STRING, + EFI_FVB2_WRITE_STATUS_STRING, + EFI_FVB2_LOCK_CAP_STRING, + EFI_FVB2_LOCK_STATUS_STRING, + NULL, + EFI_FVB2_STICKY_WRITE_STRING, + EFI_FVB2_MEMORY_MAPPED_STRING, + EFI_FVB2_ERASE_POLARITY_STRING, + EFI_FVB2_READ_LOCK_CAP_STRING, + EFI_FVB2_READ_LOCK_STATUS_STRING, + EFI_FVB2_WRITE_LOCK_CAP_STRING, + EFI_FVB2_WRITE_LOCK_STATUS_STRING +}; + +CHAR8 *mFvbAlignmentName[] = { + EFI_FVB2_ALIGNMENT_1_STRING, + EFI_FVB2_ALIGNMENT_2_STRING, + EFI_FVB2_ALIGNMENT_4_STRING, + EFI_FVB2_ALIGNMENT_8_STRING, + EFI_FVB2_ALIGNMENT_16_STRING, + EFI_FVB2_ALIGNMENT_32_STRING, + EFI_FVB2_ALIGNMENT_64_STRING, + EFI_FVB2_ALIGNMENT_128_STRING, + EFI_FVB2_ALIGNMENT_256_STRING, + EFI_FVB2_ALIGNMENT_512_STRING, + EFI_FVB2_ALIGNMENT_1K_STRING, + EFI_FVB2_ALIGNMENT_2K_STRING, + EFI_FVB2_ALIGNMENT_4K_STRING, + EFI_FVB2_ALIGNMENT_8K_STRING, + EFI_FVB2_ALIGNMENT_16K_STRING, + EFI_FVB2_ALIGNMENT_32K_STRING, + EFI_FVB2_ALIGNMENT_64K_STRING, + EFI_FVB2_ALIGNMENT_128K_STRING, + EFI_FVB2_ALIGNMENT_256K_STRING, + EFI_FVB2_ALIGNMNET_512K_STRING, + EFI_FVB2_ALIGNMENT_1M_STRING, + EFI_FVB2_ALIGNMENT_2M_STRING, + EFI_FVB2_ALIGNMENT_4M_STRING, + EFI_FVB2_ALIGNMENT_8M_STRING, + EFI_FVB2_ALIGNMENT_16M_STRING, + EFI_FVB2_ALIGNMENT_32M_STRING, + EFI_FVB2_ALIGNMENT_64M_STRING, + EFI_FVB2_ALIGNMENT_128M_STRING, + EFI_FVB2_ALIGNMENT_256M_STRING, + EFI_FVB2_ALIGNMENT_512M_STRING, + EFI_FVB2_ALIGNMENT_1G_STRING, + EFI_FVB2_ALIGNMENT_2G_STRING +}; + +// +// 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 +}; + +FV_INFO mFvDataInfo; +CAP_INFO mCapDataInfo; + +EFI_STATUS +ParseFvInf ( + IN MEMORY_FILE *InfFile, + OUT 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, Number, Index1; + EFI_STATUS Status; + EFI_GUID GuidValue; + + // + // Read the FV base address + // + if (!mFvDataInfo.BaseAddressSet) { + 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, 2000, "Invalid parameter", "%s = %s", EFI_FV_BASE_ADDRESS_STRING, Value); + return EFI_ABORTED; + } + DebugMsg (NULL, 0, 9, "rebase address", "%s = %s", EFI_FV_BASE_ADDRESS_STRING, Value); + + FvInfo->BaseAddress = Value64; + } + } + + // + // Read the FV File System Guid + // + if (!FvInfo->FvFileSystemGuidSet) { + Status = FindToken (InfFile, OPTIONS_SECTION_STRING, EFI_FV_FILESYSTEMGUID_STRING, 0, Value); + if (Status == EFI_SUCCESS) { + // + // Get the guid value + // + Status = StringToGuid (Value, &GuidValue); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 2000, "Invalid parameter", "%s = %s", EFI_FV_FILESYSTEMGUID_STRING, Value); + return EFI_ABORTED; + } + memcpy (&FvInfo->FvFileSystemGuid, &GuidValue, sizeof (EFI_GUID)); + FvInfo->FvFileSystemGuidSet = TRUE; + } + } + + // + // Read the FV Name Guid + // + if (!FvInfo->FvNameGuidSet) { + Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FV_NAMEGUID_STRING, 0, Value); + if (Status == EFI_SUCCESS) { + // + // Get the guid value + // + Status = StringToGuid (Value, &GuidValue); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 2000, "Invalid parameter", "%s = %s", EFI_FV_NAMEGUID_STRING, Value); + return EFI_ABORTED; + } + memcpy (&FvInfo->FvNameGuid, &GuidValue, sizeof (EFI_GUID)); + FvInfo->FvNameGuidSet = TRUE; + } + } + + // + // 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); + } + + // + // Read Fv Attribute + // + for (Index = 0; Index < sizeof (mFvbAttributeName)/sizeof (CHAR8 *); Index ++) { + if ((mFvbAttributeName [Index] != NULL) && \ + (FindToken (InfFile, ATTRIBUTES_SECTION_STRING, mFvbAttributeName [Index], 0, Value) == EFI_SUCCESS)) { + if ((strcmp (Value, TRUE_STRING) == 0) || (strcmp (Value, ONE_STRING) == 0)) { + FvInfo->FvAttributes |= 1 << Index; + } else if ((strcmp (Value, FALSE_STRING) != 0) && (strcmp (Value, ZERO_STRING) != 0)) { + Error (NULL, 0, 2000, "Invalid parameter", "%s expected %s | %s", mFvbAttributeName [Index], TRUE_STRING, FALSE_STRING); + return EFI_ABORTED; + } + } + } + + // + // Read Fv Alignment + // + for (Index = 0; Index < sizeof (mFvbAlignmentName)/sizeof (CHAR8 *); Index ++) { + if (FindToken (InfFile, ATTRIBUTES_SECTION_STRING, mFvbAlignmentName [Index], 0, Value) == EFI_SUCCESS) { + if (strcmp (Value, TRUE_STRING) == 0) { + FvInfo->FvAttributes |= Index << 16; + DebugMsg (NULL, 0, 9, "FV file alignment", "Align = %s", mFvbAlignmentName [Index]); + break; + } + } + } + + // + // Read block maps + // + for (Index = 0; Index < MAX_NUMBER_OF_FV_BLOCKS; Index++) { + if (FvInfo->FvBlocks[Index].Length == 0) { + // + // Read block size + // + Status = FindToken (InfFile, OPTIONS_SECTION_STRING, EFI_BLOCK_SIZE_STRING, Index, Value); + + if (Status == EFI_SUCCESS) { + // + // Update the size of block + // + Status = AsciiStringToUint64 (Value, FALSE, &Value64); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 2000, "Invalid parameter", "%s = %s", EFI_BLOCK_SIZE_STRING, Value); + return EFI_ABORTED; + } + + FvInfo->FvBlocks[Index].Length = (UINT32) Value64; + DebugMsg (NULL, 0, 9, "FV Block Size", "%s = %s", EFI_BLOCK_SIZE_STRING, Value); + } else { + // + // If there is no blocks size, but there is the number of block, then we have a mismatched pair + // and should return an error. + // + Status = FindToken (InfFile, OPTIONS_SECTION_STRING, EFI_NUM_BLOCKS_STRING, Index, Value); + if (!EFI_ERROR (Status)) { + Error (NULL, 0, 2000, "Invalid parameter", "both %s and %s must be specified.", EFI_NUM_BLOCKS_STRING, EFI_BLOCK_SIZE_STRING); + return EFI_ABORTED; + } else { + // + // We are done + // + break; + } + } + + // + // Read blocks number + // + 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, 2000, "Invalid parameter", "%s = %s", EFI_NUM_BLOCKS_STRING, Value); + return EFI_ABORTED; + } + + FvInfo->FvBlocks[Index].NumBlocks = (UINT32) Value64; + DebugMsg (NULL, 0, 9, "FV Block Number", "%s = %s", EFI_NUM_BLOCKS_STRING, Value); + } + } + } + + if (Index == 0) { + Error (NULL, 0, 2001, "Missing required argument", "block size."); + return EFI_ABORTED; + } + + // + // Read files + // + Number = 0; + for (Number = 0; Number < MAX_NUMBER_OF_FILES_IN_FV; Number ++) { + if (FvInfo->FvFiles[Number][0] == '\0') { + break; + } + } + + for (Index = 0; Index < MAX_NUMBER_OF_FILES_IN_FV; Index++) { + // + // Read the FFS file list + // + Status = FindToken (InfFile, FILES_SECTION_STRING, EFI_FILE_NAME_STRING, Index, Value); + + if (Status == EFI_SUCCESS) { + // + // Add the file + // + strcpy (FvInfo->FvFiles[Number + Index], Value); + DebugMsg (NULL, 0, 9, "FV component file", "the %dth name is %s", Index, Value); + } else { + break; + } + } + + if ((Index + Number) == 0) { + Warning (NULL, 0, 0, "FV components are not specified.", NULL); + } + + 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. Update the reserved bits of State to EFI_FVB2_ERASE_POLARITY. + +Arguments: + + FfsFile File header. + FvHeader FV header. + +Returns: + + None + +--*/ +{ + if (FvHeader->Attributes & EFI_FVB2_ERASE_POLARITY) { + FfsFile->State = (UINT8)~(FfsFile->State); + // FfsFile->State |= ~(UINT8) EFI_FILE_ALL_STATE_BITS; + } +} + +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 offset of the FFS file + +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: + // + // 8 byte alignment, mini alignment requirement for FFS file. + // + *Alignment = 3; + break; + + case 1: + // + // 16 byte alignment + // + *Alignment = 4; + break; + + case 2: + // + // 128 byte alignment + // + *Alignment = 7; + break; + + case 3: + // + // 512 byte alignment + // + *Alignment = 9; + break; + + case 4: + // + // 1K byte alignment + // + *Alignment = 10; + break; + + case 5: + // + // 4K byte alignment + // + *Alignment = 12; + break; + + case 6: + // + // 32K byte alignment + // + *Alignment = 15; + break; + + case 7: + // + // 64K byte alignment + // + *Alignment = 16; + break; + + default: + break; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +AddPadFile ( + IN OUT MEMORY_FILE *FvImage, + IN UINT32 DataAlignment, + IN EFI_FIRMWARE_VOLUME_EXT_HEADER *ExtHeader + ) +/*++ + +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. + ExtHeader PI FvExtHeader Optional + +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; + UINTN PadFileSize; + + // + // Verify input parameters. + // + if (FvImage == NULL) { + return EFI_INVALID_PARAMETER; + } + + // + // Check if a pad file is necessary + // + if ((ExtHeader == NULL) && (((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 (ExtHeader != NULL) { + if ((UINTN) (PadFile + sizeof (EFI_FFS_FILE_HEADER) + ExtHeader->ExtHeaderSize) >= (UINTN) FvImage->Eof) { + return EFI_OUT_OF_RESOURCES; + } + } else { + if ((UINTN) (PadFile + sizeof (EFI_FFS_FILE_HEADER)) >= (UINTN) FvImage->Eof) { + return EFI_OUT_OF_RESOURCES; + } + } + + // + // write PadFile FFS header with PadType, don't need to set PAD file guid in its header. + // + 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) + // + if (ExtHeader != NULL) { + PadFileSize = (UINTN) FvImage->CurrentFilePointer - (UINTN) FvImage->FileImage + (sizeof (EFI_FFS_FILE_HEADER) * 2) + ExtHeader->ExtHeaderSize; + } else { + 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)); + 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 + ); + + if (ExtHeader != NULL) { + // + // Copy Fv Extension Header and Set Fv Extension header offset + // + memcpy (PadFile + 1, ExtHeader, ExtHeader->ExtHeaderSize); + ((EFI_FIRMWARE_VOLUME_HEADER *) FvImage->FileImage)->ExtHeaderOffset = (UINT16) ((UINTN) (PadFile + 1) - (UINTN) FvImage->FileImage); + } + + // + // Verify that we have enough space (including the padding) + // + if (((UINTN)PadFile + PadFileSize) >= (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 + +--*/ +{ + if (!memcmp (&FileBuffer->Name, &mEfiFirmwareVolumeTopFileGuid, sizeof (EFI_GUID))) { + return TRUE; + } else { + return FALSE; + } +} + +EFI_STATUS +WriteMapFile ( + IN OUT FILE *FvMapFile, + IN CHAR8 *FileName, + IN EFI_GUID *FileGuidPtr, + IN EFI_PHYSICAL_ADDRESS ImageBaseAddress, + IN PE_COFF_LOADER_IMAGE_CONTEXT *pImageContext + ) +/*++ + +Routine Description: + + This function gets the basic debug information (entrypoint, baseaddress, .text, .data section base address) + from PE/COFF image and abstracts Pe Map file information and add them into FvMap file for Debug. + +Arguments: + + FvMapFile A pointer to FvMap File + FileName Ffs File PathName + FileGuidPtr Guid Value of Ffs file + ImageBaseAddress PeImage Base Address. + pImageContext Image Context Information. + +Returns: + + EFI_SUCCESS Added required map information. + +--*/ +{ + CHAR8 PeMapFileName [_MAX_PATH]; + CHAR8 *Cptr, *Cptr2; + CHAR8 FileGuidName [MAX_LINE_LEN]; + FILE *PeMapFile; + CHAR8 Line [MAX_LINE_LEN]; + CHAR8 KeyWord [MAX_LINE_LEN]; + CHAR8 FunctionName [MAX_LINE_LEN]; + EFI_PHYSICAL_ADDRESS FunctionAddress; + UINT32 FunctionType; + CHAR8 FunctionTypeName [MAX_LINE_LEN]; + UINT32 Index; + UINT32 AddressOfEntryPoint; + UINT32 Offset; + EFI_IMAGE_OPTIONAL_HEADER_UNION *ImgHdr; + EFI_TE_IMAGE_HEADER *TEImageHeader; + EFI_IMAGE_SECTION_HEADER *SectionHeader; + + // + // Init local variable + // + FunctionType = 0; + // + // Print FileGuid to string buffer. + // + PrintGuidToBuffer (FileGuidPtr, (UINT8 *)FileGuidName, MAX_LINE_LEN, TRUE); + + // + // Construct Map file Name + // + strcpy (PeMapFileName, FileName); + + // + // Change '\\' to '/', unified path format. + // + Cptr = PeMapFileName; + while (*Cptr != '\0') { + if (*Cptr == '\\') { + *Cptr = FILE_SEP_CHAR; + } + Cptr ++; + } + + // + // Get Map file + // + Cptr = PeMapFileName + strlen (PeMapFileName); + while ((*Cptr != '.') && (Cptr >= PeMapFileName)) { + Cptr --; + } + if (Cptr < PeMapFileName) { + return EFI_NOT_FOUND; + } else { + *(Cptr + 1) = 'm'; + *(Cptr + 2) = 'a'; + *(Cptr + 3) = 'p'; + *(Cptr + 4) = '\0'; + } + + // + // Get module Name + // + Cptr2 = Cptr; + while ((*Cptr != FILE_SEP_CHAR) && (Cptr >= PeMapFileName)) { + Cptr --; + } + *Cptr2 = '\0'; + strcpy (KeyWord, Cptr + 1); + *Cptr2 = '.'; + + // + // AddressOfEntryPoint and Offset in Image + // + if (!pImageContext->IsTeImage) { + ImgHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *) ((UINT8 *) pImageContext->Handle + pImageContext->PeCoffHeaderOffset); + AddressOfEntryPoint = ImgHdr->Pe32.OptionalHeader.AddressOfEntryPoint; + Offset = 0; + SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ( + (UINT8 *) ImgHdr + + sizeof (UINT32) + + sizeof (EFI_IMAGE_FILE_HEADER) + + ImgHdr->Pe32.FileHeader.SizeOfOptionalHeader + ); + Index = ImgHdr->Pe32.FileHeader.NumberOfSections; + } else { + TEImageHeader = (EFI_TE_IMAGE_HEADER *) pImageContext->Handle; + AddressOfEntryPoint = TEImageHeader->AddressOfEntryPoint; + Offset = TEImageHeader->StrippedSize - sizeof (EFI_TE_IMAGE_HEADER); + SectionHeader = (EFI_IMAGE_SECTION_HEADER *) (TEImageHeader + 1); + Index = TEImageHeader->NumberOfSections; + } + + // + // module information output + // + if (ImageBaseAddress == 0) { + fprintf (FvMapFile, "%s (dummy) (", KeyWord); + fprintf (FvMapFile, "BaseAddress=%08lx, ", ImageBaseAddress); + } else { + fprintf (FvMapFile, "%s (", KeyWord); + fprintf (FvMapFile, "BaseAddress=%08lx, ", ImageBaseAddress + Offset); + } + fprintf (FvMapFile, "EntryPoint=%08lx, ", ImageBaseAddress + AddressOfEntryPoint); + fprintf (FvMapFile, "GUID=%s", FileGuidName); + fprintf (FvMapFile, ")\n"); + + for (; Index > 0; Index --, SectionHeader ++) { + if (stricmp ((CHAR8 *)SectionHeader->Name, ".text") == 0) { + fprintf (FvMapFile, ".textbaseaddress=%08lx ",ImageBaseAddress + SectionHeader->VirtualAddress); + } else if (stricmp ((CHAR8 *)SectionHeader->Name, ".data") == 0) { + fprintf (FvMapFile, ".databaseaddress=%08lx ",ImageBaseAddress + SectionHeader->VirtualAddress); + } + } + fprintf (FvMapFile, "\n\n"); + + // + // Open PeMapFile + // + PeMapFile = fopen (PeMapFileName, "r"); + if (PeMapFile == NULL) { + // fprintf (stdout, "can't open %s file to reading\n", PeMapFileName); + return EFI_ABORTED; + } + VerboseMsg ("The map file is %s", PeMapFileName); + + // + // Output Functions information into Fv Map file + // + while (fgets (Line, MAX_LINE_LEN, PeMapFile) != NULL) { + // + // Skip blank line + // + if (Line[0] == 0x0a) { + FunctionType = 0; + continue; + } + // + // By Address and Static keyword + // + if (FunctionType == 0) { + sscanf (Line, "%s", KeyWord); + if (stricmp (KeyWord, "Address") == 0) { + // + // function list + // + FunctionType = 1; + fgets (Line, MAX_LINE_LEN, PeMapFile); + } else if (stricmp (KeyWord, "Static") == 0) { + // + // static function list + // + FunctionType = 2; + fgets (Line, MAX_LINE_LEN, PeMapFile); + } + continue; + } + // + // Printf Function Information + // + if (FunctionType == 1) { + sscanf (Line, "%s %s %lx %s", KeyWord, FunctionName, &FunctionAddress, FunctionTypeName); + if (FunctionTypeName [1] == '\0' && (FunctionTypeName [0] == 'f' || FunctionTypeName [0] == 'F')) { + fprintf (FvMapFile, " %016lx ", ImageBaseAddress + FunctionAddress); + fprintf (FvMapFile, "(%08lx) F ", FunctionAddress - Offset); + fprintf (FvMapFile, "%s\n", FunctionName); + } else { + fprintf (FvMapFile, " %016lx ", ImageBaseAddress + FunctionAddress); + fprintf (FvMapFile, "(%08lx) ", FunctionAddress - Offset); + fprintf (FvMapFile, "%s\n", FunctionName); + } + } else if (FunctionType == 2) { + sscanf (Line, "%s %s %lx %s", KeyWord, FunctionName, &FunctionAddress, FunctionTypeName); + if (FunctionTypeName [1] == '\0' && (FunctionTypeName [0] == 'f' || FunctionTypeName [0] == 'F')) { + fprintf (FvMapFile, " %016lx ", ImageBaseAddress + FunctionAddress); + fprintf (FvMapFile, "(%08lx) FS ", FunctionAddress - Offset); + fprintf (FvMapFile, "%s\n", FunctionName); + } else { + fprintf (FvMapFile, " %016lx ", ImageBaseAddress + FunctionAddress); + fprintf (FvMapFile, "(%08lx) ", FunctionAddress - Offset); + fprintf (FvMapFile, "%s\n", FunctionName); + } + } + } + // + // Close PeMap file + // + fprintf (FvMapFile, "\n\n"); + fclose (PeMapFile); + + 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 FILE *FvMapFile + ) +/*++ + +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. + FvMapFile Pointer to FvMap File + +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; + UINTN Index1; + + Index1 = 0; + // + // Verify input parameters. + // + if (FvImage == NULL || FvInfo == NULL || FvInfo->FvFiles[Index][0] == 0 || VtfFileImage == NULL) { + return EFI_INVALID_PARAMETER; + } + + // + // Read the file to add + // + NewFile = fopen (FvInfo->FvFiles[Index], "rb"); + + if (NewFile == NULL) { + Error (NULL, 0, 0001, "Error opening file", FvInfo->FvFiles[Index]); + 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, 4001, "Resouce", "memory cannot be allocated!"); + 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, 0004, "Error reading file", FvInfo->FvFiles[Index]); + return EFI_ABORTED; + } + + // + // For None PI Ffs file, directly add them into FvImage. + // + if (!FvInfo->IsPiFvImage) { + memcpy (FvImage->CurrentFilePointer, FileBuffer, FileSize); + if (FvInfo->SizeofFvFiles[Index] > FileSize) { + FvImage->CurrentFilePointer += FvInfo->SizeofFvFiles[Index]; + } else { + FvImage->CurrentFilePointer += FileSize; + } + goto Done; + } + + // + // Verify Ffs file + // + Status = VerifyFfsFile ((EFI_FFS_FILE_HEADER *)FileBuffer); + if (EFI_ERROR (Status)) { + free (FileBuffer); + Error (NULL, 0, 3000, "Invalid", "%s is a FFS file.", FvInfo->FvFiles[Index]); + return EFI_INVALID_PARAMETER; + } + + // + // Verify space exists to add the file + // + if (FileSize > (UINTN) ((UINTN) *VtfFileImage - (UINTN) FvImage->CurrentFilePointer)) { + free (FileBuffer); + Error (NULL, 0, 4002, "Resource", "FV space is full, not enough room to add file %s.", FvInfo->FvFiles[Index]); + return EFI_OUT_OF_RESOURCES; + } + + // + // Verify the input file is the duplicated file in this Fv image + // + for (Index1 = 0; Index1 < Index; Index1 ++) { + if (CompareGuid ((EFI_GUID *) FileBuffer, &mFileGuidArray [Index1]) == 0) { + Error (NULL, 0, 2000, "Invalid parameter", "the %dth file and %dth file have the same file GUID.", Index1 + 1, Index + 1); + PrintGuid ((EFI_GUID *) FileBuffer); + return EFI_INVALID_PARAMETER; + } + } + CopyMem (&mFileGuidArray [Index], FileBuffer, sizeof (EFI_GUID)); + + // + // Update the file state based on polarity of the FV. + // + UpdateFfsFileState ( + (EFI_FFS_FILE_HEADER *) FileBuffer, + (EFI_FIRMWARE_VOLUME_HEADER *) FvImage->FileImage + ); + + // + // Check if alignment is required + // + ReadFfsAlignment ((EFI_FFS_FILE_HEADER *) FileBuffer, &CurrentFileAlignment); + + // + // Find the largest alignment of all the FFS files in the FV + // + if (CurrentFileAlignment > MaxFfsAlignment) { + MaxFfsAlignment = CurrentFileAlignment; + } + // + // 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 + sizeof (EFI_FFS_FILE_HEADER) - (UINTN) FvImage->FileImage) % (1 << CurrentFileAlignment)) { + Error (NULL, 0, 3000, "Invalid", "VTF file cannot be aligned on a %d-byte boundary.", 1 << CurrentFileAlignment); + free (FileBuffer); + return EFI_ABORTED; + } + // + // Rebase the PE or TE image in FileBuffer of FFS file for XIP + // Rebase for the debug genfvmap tool + // + FfsRebase (FvInfo, FvInfo->FvFiles[Index], (EFI_FFS_FILE_HEADER *) FileBuffer, (UINTN) *VtfFileImage - (UINTN) FvImage->FileImage, FvMapFile); + // + // copy VTF File + // + memcpy (*VtfFileImage, FileBuffer, FileSize); + free (FileBuffer); + DebugMsg (NULL, 0, 9, "Add VTF FFS file in FV image", NULL); + return EFI_SUCCESS; + } else { + // + // Already found a VTF file. + // + Error (NULL, 0, 3000, "Invalid", "multiple VTF files are not permitted within a single FV."); + free (FileBuffer); + return EFI_ABORTED; + } + } + + // + // Add pad file if necessary + // + Status = AddPadFile (FvImage, 1 << CurrentFileAlignment, NULL); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 4002, "Resource", "FV space is full, could not add pad file for data alignment property."); + free (FileBuffer); + return EFI_ABORTED; + } + // + // Add file + // + if ((FvImage->CurrentFilePointer + FileSize) < FvImage->Eof) { + // + // Rebase the PE or TE image in FileBuffer of FFS file for XIP. + // Rebase Bs and Rt drivers for the debug genfvmap tool. + // + FfsRebase (FvInfo, FvInfo->FvFiles[Index], (EFI_FFS_FILE_HEADER *) FileBuffer, (UINTN) FvImage->CurrentFilePointer - (UINTN) FvImage->FileImage, FvMapFile); + // + // Copy the file + // + memcpy (FvImage->CurrentFilePointer, FileBuffer, FileSize); + FvImage->CurrentFilePointer += FileSize; + } else { + Error (NULL, 0, 4002, "Resource", "FV space is full, cannot add file %s.", FvInfo->FvFiles[Index]); + free (FileBuffer); + return EFI_ABORTED; + } + // + // Make next file start at QWord Boundry + // + while (((UINTN) FvImage->CurrentFilePointer & (EFI_FFS_FILE_HEADER_ALIGNMENT - 1)) != 0) { + FvImage->CurrentFilePointer++; + } + +Done: + // + // Free allocated memory. + // + free (FileBuffer); + + 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 || \ + ((UINTN) VtfFileImage == (UINTN) FvImage->CurrentFilePointer)) { + return EFI_SUCCESS; + } + + // + // Pad file starts at beginning of free space + // + PadFile = (EFI_FFS_FILE_HEADER *) FvImage->CurrentFilePointer; + + // + // write PadFile FFS header with PadType, don't need to set PAD file guid in its header. + // + 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)); + 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; + INT32 Ia32SecEntryOffset; + UINT32 *Ia32ResetAddressPtr; + UINT8 *BytePointer; + UINT8 *BytePointer2; + UINT16 *WordPointer; + UINT16 CheckSum; + UINTN Index; + EFI_FFS_FILE_STATE SavedState; + UINT64 FitAddress; + FIT_TABLE *FitTablePtr; + UINT32 IpiVector; + + // + // Verify input parameters + // + if (FvImage == NULL || FvInfo == NULL || VtfFile == NULL) { + return EFI_INVALID_PARAMETER; + } + // + // Initialize FV library + // + InitializeFvLib (FvImage->FileImage, FvInfo->Size); + + // + // Verify VTF file + // + Status = VerifyFfsFile (VtfFile); + if (EFI_ERROR (Status)) { + return EFI_INVALID_PARAMETER; + } + + // + // Find the Sec Core + // + Status = GetFileByType (EFI_FV_FILETYPE_SECURITY_CORE, 1, &SecCoreFile); + if (EFI_ERROR (Status) || SecCoreFile == NULL) { + Error (NULL, 0, 3000, "Invalid", "could not find the SEC core file in the FV."); + return EFI_ABORTED; + } + // + // Sec Core found, now find PE32 section + // + Status = GetSectionByType (SecCoreFile, EFI_SECTION_PE32, 1, &Pe32Section); + if (Status == EFI_NOT_FOUND) { + Status = GetSectionByType (SecCoreFile, EFI_SECTION_TE, 1, &Pe32Section); + } + + if (EFI_ERROR (Status)) { + Error (NULL, 0, 3000, "Invalid", "could not find a PE32 section in the SEC core file."); + return EFI_ABORTED; + } + + Status = GetPe32Info ( + (VOID *) ((UINTN) Pe32Section.Pe32Section + sizeof (EFI_SECTION_PE32)), + &EntryPoint, + &BaseOfCode, + &MachineType + ); + + if (EFI_ERROR (Status)) { + Error (NULL, 0, 3000, "Invalid", "could not get the PE32 entry point for the SEC core."); + 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; + DebugMsg (NULL, 0, 9, "SecCore physical entry point address", "Address = 0x%X", SecCorePhysicalAddress); + + // + // Find the PEI Core + // + Status = GetFileByType (EFI_FV_FILETYPE_PEI_CORE, 1, &PeiCoreFile); + if (EFI_ERROR (Status) || PeiCoreFile == NULL) { + Error (NULL, 0, 3000, "Invalid", "could not find the PEI core in the FV."); + 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, 3000, "Invalid", "could not find either a PE32 or a TE section in PEI core file."); + return EFI_ABORTED; + } + + Status = GetPe32Info ( + (VOID *) ((UINTN) Pe32Section.Pe32Section + sizeof (EFI_SECTION_PE32)), + &EntryPoint, + &BaseOfCode, + &MachineType + ); + + if (EFI_ERROR (Status)) { + Error (NULL, 0, 3000, "Invalid", "could not get the PE32 entry point for the PEI core."); + 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; + DebugMsg (NULL, 0, 9, "PeiCore physical entry point address", "Address = 0x%X", PeiCorePhysicalAddress); + + 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) { + Error (NULL, 0, 3000, "Invalid", + "PEI_CORE entry point is not aligned on a 16 byte boundary, address specified is %Xh.", + 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); + } + + // + // Update SEC_CORE address + // + // + // Set the uncached attribute bit in the physical address + // + SecCorePhysicalAddress |= 0x8000000000000000ULL; + // + // Check if address is aligned on a 16 byte boundary + // + if (SecCorePhysicalAddress & 0xF) { + Error (NULL, 0, 3000, "Invalid", + "SALE_ENTRY entry point is not aligned on a 16 byte boundary, address specified is %Xh.", + SecCorePhysicalAddress + ); + return EFI_ABORTED; + } + // + // Update the address + // + SecCoreEntryAddressPtr = (EFI_PHYSICAL_ADDRESS *) ((UINTN) FvImage->Eof - IPF_SALE_ENTRY_ADDRESS_OFFSET); + *SecCoreEntryAddressPtr = SecCorePhysicalAddress; + + } else if ( + (MachineType == EFI_IMAGE_MACHINE_IA32 || + MachineType == EFI_IMAGE_MACHINE_X64) && + (((UINTN)FvImage->Eof - (UINTN)FvImage->FileImage) >= IA32_X64_VTF_SIGNATURE_OFFSET) && + (*(UINT32 *)(VOID*)((UINTN) FvImage->Eof - IA32_X64_VTF_SIGNATURE_OFFSET) == + IA32_X64_VTF0_SIGNATURE) + ) { + // + // If VTF-0 signature is found, then no modifications are needed. + // + } else if (MachineType == EFI_IMAGE_MACHINE_IA32 || MachineType == EFI_IMAGE_MACHINE_X64) { + // + // Get the location to update + // + Ia32ResetAddressPtr = (UINT32 *) ((UINTN) FvImage->Eof - IA32_PEI_CORE_ENTRY_OFFSET); + + // + // Write lower 32 bits of physical address for Pei Core entry + // + *Ia32ResetAddressPtr = (UINT32) PeiCorePhysicalAddress; + + // + // Write SecCore Entry point relative address into the jmp instruction in reset vector. + // + Ia32ResetAddressPtr = (UINT32 *) ((UINTN) FvImage->Eof - IA32_SEC_CORE_ENTRY_OFFSET); + + Ia32SecEntryOffset = SecCorePhysicalAddress - (FV_IMAGES_TOP_ADDRESS - IA32_SEC_CORE_ENTRY_OFFSET + 2); + if (Ia32SecEntryOffset <= -65536) { + Error (NULL, 0, 3000, "Invalid", "The SEC EXE file size is too large, it must be less than 64K."); + return STATUS_ERROR; + } + + *(UINT16 *) Ia32ResetAddressPtr = (UINT16) Ia32SecEntryOffset; + + // + // Update the BFV base address + // + Ia32ResetAddressPtr = (UINT32 *) ((UINTN) FvImage->Eof - 4); + *Ia32ResetAddressPtr = (UINT32) (FvInfo->BaseAddress); + DebugMsg (NULL, 0, 9, "update BFV base address in the top FV image", "BFV base address = 0x%X.", FvInfo->BaseAddress); + + // + // Update the Startup AP in the FVH header block ZeroVector region. + // + BytePointer = (UINT8 *) ((UINTN) FvImage->FileImage); + if (FvInfo->Size <= 0x10000) { + BytePointer2 = m64kRecoveryStartupApDataArray; + } else if (FvInfo->Size <= 0x20000) { + BytePointer2 = m128kRecoveryStartupApDataArray; + } else { + BytePointer2 = m128kRecoveryStartupApDataArray; + // + // 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 + // + Status = FindApResetVectorPosition (FvImage, &BytePointer); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 3000, "Invalid", "Cannot find the appropriate location in FvImage to add Ap reset vector!"); + return EFI_ABORTED; + } + } + + for (Index = 0; Index < SIZEOF_STARTUP_DATA_ARRAY; Index++) { + BytePointer[Index] = BytePointer2[Index]; + } + // + // Calculate the checksum + // + CheckSum = 0x0000; + WordPointer = (UINT16 *) (BytePointer); + for (Index = 0; Index < SIZEOF_STARTUP_DATA_ARRAY / 2; Index++) { + CheckSum = (UINT16) (CheckSum + ((UINT16) *WordPointer)); + WordPointer++; + } + // + // Update the checksum field + // + WordPointer = (UINT16 *) (BytePointer + SIZEOF_STARTUP_DATA_ARRAY - 2); + *WordPointer = (UINT16) (0x10000 - (UINT32) CheckSum); + + // + // IpiVector at the 4k aligned address in the top 2 blocks in the PEI FV. + // + IpiVector = FV_IMAGES_TOP_ADDRESS - ((UINTN) FvImage->Eof - (UINTN) BytePointer); + DebugMsg (NULL, 0, 9, "Startup AP Vector address", "IpiVector at 0x%X", IpiVector); + if (IpiVector & 0xFFF != 0) { + Error (NULL, 0, 3000, "Invalid", "Startup AP Vector address are not 4K aligned, because the FV size is not 4K aligned"); + return EFI_ABORTED; + } + IpiVector = IpiVector >> 12; + IpiVector = IpiVector & 0xFF; + + // + // Write IPI Vector at Offset FvrecoveryFileSize - 8 + // + Ia32ResetAddressPtr = (UINT32 *) ((UINTN) FvImage->Eof - 8); + *Ia32ResetAddressPtr = IpiVector; + } else if (MachineType == EFI_IMAGE_MACHINE_ARMT) { + // + // Since the ARM reset vector is in the FV Header you really don't need a + // Volume Top File, but if you have one for some reason don't crash... + // + } else { + Error (NULL, 0, 3000, "Invalid", "machine type=0x%X in PEI core.", (UINT32) MachineType); + return EFI_ABORTED; + } + + // + // 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) + ); + } else { + VtfFile->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM; + } + + VtfFile->State = SavedState; + + return EFI_SUCCESS; +} + + +EFI_STATUS +UpdateArmResetVectorIfNeeded ( + IN MEMORY_FILE *FvImage, + IN FV_INFO *FvInfo + ) +/*++ + +Routine Description: + This parses the FV looking for SEC and patches that address into the + beginning of the FV header. + + For ARM the reset vector is at 0x00000000 or 0xFFFF0000. + This would commonly map to the first entry in the ROM. + ARM Exceptions: + Reset +0 + Undefined +4 + SWI +8 + Prefetch Abort +12 + Data Abort +16 + IRQ +20 + FIQ +24 + + We support two schemes on ARM. + 1) Begining of the FV is the reset vector + 2) Reset vector is data bytes FDF file and that code branches to reset vector + in the beginning of the FV (fixed size offset). + + + Need to have the jump for the reset vector at location zero. + We also need to store the address or PEI (if it exists). + We stub out a return from interrupt in case the debugger + is using SWI. + The optional entry to the common exception handler is + to support full featured exception handling from ROM and is currently + not support by this tool. + +Arguments: + FvImage Memory file for the FV memory image + FvInfo Information read from INF file. + +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; + INT32 ResetVector[4]; // 0 - is branch relative to SEC entry point + // 1 - PEI Entry Point + // 2 - movs pc,lr for a SWI handler + // 3 - Place holder for Common Exception Handler + + // + // Verify input parameters + // + if (FvImage == NULL || FvInfo == NULL) { + return EFI_INVALID_PARAMETER; + } + // + // Initialize FV library + // + InitializeFvLib (FvImage->FileImage, FvInfo->Size); + + // + // Find the Sec Core + // + Status = GetFileByType (EFI_FV_FILETYPE_SECURITY_CORE, 1, &SecCoreFile); + if (EFI_ERROR (Status) || SecCoreFile == NULL) { + // + // Maybe hardware does SEC job and we only have PEI Core? + // + + // + // Find the PEI Core. It may not exist if SEC loads DXE core directly + // + PeiCorePhysicalAddress = 0; + Status = GetFileByType (EFI_FV_FILETYPE_PEI_CORE, 1, &PeiCoreFile); + if (!EFI_ERROR (Status) && PeiCoreFile != NULL) { + // + // 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, 3000, "Invalid", "could not find either a PE32 or a TE section in PEI core file!"); + return EFI_ABORTED; + } + + Status = GetPe32Info ( + (VOID *) ((UINTN) Pe32Section.Pe32Section + sizeof (EFI_SECTION_PE32)), + &EntryPoint, + &BaseOfCode, + &MachineType + ); + + if (EFI_ERROR (Status)) { + Error (NULL, 0, 3000, "Invalid", "could not get the PE32 entry point for the PEI core!"); + 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; + DebugMsg (NULL, 0, 9, "PeiCore physical entry point address", "Address = 0x%X", PeiCorePhysicalAddress); + + if (MachineType == EFI_IMAGE_MACHINE_ARMT) { + memset (ResetVector, 0, sizeof (ResetVector)); + // Address of PEI Core, if we have one + ResetVector[1] = (UINT32)PeiCorePhysicalAddress; + } + + // + // Copy to the beginning of the FV + // + memcpy ((UINT8 *) ((UINTN) FvImage->FileImage), ResetVector, sizeof (ResetVector)); + + } + + return EFI_SUCCESS; + } + + // + // Sec Core found, now find PE32 section + // + Status = GetSectionByType (SecCoreFile, EFI_SECTION_PE32, 1, &Pe32Section); + if (Status == EFI_NOT_FOUND) { + Status = GetSectionByType (SecCoreFile, EFI_SECTION_TE, 1, &Pe32Section); + } + + if (EFI_ERROR (Status)) { + Error (NULL, 0, 3000, "Invalid", "could not find a PE32 section in the SEC core file."); + return EFI_ABORTED; + } + + Status = GetPe32Info ( + (VOID *) ((UINTN) Pe32Section.Pe32Section + sizeof (EFI_SECTION_PE32)), + &EntryPoint, + &BaseOfCode, + &MachineType + ); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 3000, "Invalid", "could not get the PE32 entry point for the SEC core."); + return EFI_ABORTED; + } + + if (MachineType != EFI_IMAGE_MACHINE_ARMT) { + // + // If SEC is not ARM we have nothing to do + // + return EFI_SUCCESS; + } + + // + // 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; + DebugMsg (NULL, 0, 9, "SecCore physical entry point address", "Address = 0x%X", SecCorePhysicalAddress); + + // + // Find the PEI Core. It may not exist if SEC loads DXE core directly + // + PeiCorePhysicalAddress = 0; + Status = GetFileByType (EFI_FV_FILETYPE_PEI_CORE, 1, &PeiCoreFile); + if (!EFI_ERROR (Status) && PeiCoreFile != NULL) { + // + // 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, 3000, "Invalid", "could not find either a PE32 or a TE section in PEI core file!"); + return EFI_ABORTED; + } + + Status = GetPe32Info ( + (VOID *) ((UINTN) Pe32Section.Pe32Section + sizeof (EFI_SECTION_PE32)), + &EntryPoint, + &BaseOfCode, + &MachineType + ); + + if (EFI_ERROR (Status)) { + Error (NULL, 0, 3000, "Invalid", "could not get the PE32 entry point for the PEI core!"); + 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; + DebugMsg (NULL, 0, 9, "PeiCore physical entry point address", "Address = 0x%X", PeiCorePhysicalAddress); + } + + + // B SecEntryPoint - signed_immed_24 part +/-32MB offset + // on ARM, the PC is always 8 ahead, so we're not really jumping from the base address, but from base address + 8 + ResetVector[0] = (INT32)(SecCorePhysicalAddress - FvInfo->BaseAddress - 8) >> 2; + + if (ResetVector[0] > 0x00FFFFFF) { + Error (NULL, 0, 3000, "Invalid", "SEC Entry point must be within 32MB of the start of the FV"); + return EFI_ABORTED; + } + + // Add opcode for an uncondional branch with no link. AKA B SecEntryPoint + ResetVector[0] |= 0xEA000000; + + + // Address of PEI Core, if we have one + ResetVector[1] = (UINT32)PeiCorePhysicalAddress; + + // SWI handler movs pc,lr. Just in case a debugger uses SWI + ResetVector[2] = 0xE1B0F07E; + + // Place holder to support a common interrupt handler from ROM. + // Currently not suppprted. For this to be used the reset vector would not be in this FV + // and the exception vectors would be hard coded in the ROM and just through this address + // to find a common handler in the a module in the FV. + ResetVector[3] = 0; + + // + // Copy to the beginning of the FV + // + memcpy ((UINT8 *) ((UINTN) FvImage->FileImage), ResetVector, sizeof (ResetVector)); + + DebugMsg (NULL, 0, 9, "Update Reset vector in FV Header", NULL); + + 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_OPTIONAL_HEADER_UNION *ImgHdr; + 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) { + Error (NULL, 0, 3000, "Invalid", "Unknown magic number in the DOS header, 0x%04X.", DosHeader->e_magic); + return EFI_UNSUPPORTED; + } + // + // Immediately following is the NT header. + // + ImgHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *) ((UINTN) Pe32 + DosHeader->e_lfanew); + + // + // Verify NT header is expected + // + if (ImgHdr->Pe32.Signature != EFI_IMAGE_NT_SIGNATURE) { + Error (NULL, 0, 3000, "Invalid", "Unrecognized image signature 0x%08X.", ImgHdr->Pe32.Signature); + return EFI_UNSUPPORTED; + } + // + // Get output + // + *EntryPoint = ImgHdr->Pe32.OptionalHeader.AddressOfEntryPoint; + *BaseOfCode = ImgHdr->Pe32.OptionalHeader.BaseOfCode; + *MachineType = ImgHdr->Pe32.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 && + *MachineType != EFI_IMAGE_MACHINE_ARMT) { + Error (NULL, 0, 3000, "Invalid", "Unrecognized machine type in the PE32 file."); + return EFI_UNSUPPORTED; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +GenerateFvImage ( + IN CHAR8 *InfFileImage, + IN UINTN InfFileSize, + IN CHAR8 *FvFileName, + IN CHAR8 *MapFileName + ) +/*++ + +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. + FvFileName Requested name for the FV file. + MapFileName Fv map file to log fv driver information. + +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; + UINTN Index; + EFI_FIRMWARE_VOLUME_HEADER *FvHeader; + EFI_FFS_FILE_HEADER *VtfFileImage; + UINT8 *FvBufferHeader; // to make sure fvimage header 8 type alignment. + UINT8 *FvImage; + UINTN FvImageSize; + FILE *FvFile; + CHAR8 FvMapName [_MAX_PATH]; + FILE *FvMapFile; + EFI_FIRMWARE_VOLUME_EXT_HEADER FvExtHeader; + + FvBufferHeader = NULL; + FvFile = NULL; + FvMapFile = NULL; + + if (InfFileImage != NULL) { + // + // Initialize file structures + // + InfMemoryFile.FileImage = InfFileImage; + InfMemoryFile.CurrentFilePointer = InfFileImage; + InfMemoryFile.Eof = InfFileImage + InfFileSize; + + // + // Parse the FV inf file for header information + // + Status = ParseFvInf (&InfMemoryFile, &mFvDataInfo); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 0003, "Error parsing file", "the input FV INF file."); + return Status; + } + } + + // + // Update the file name return values + // + if (FvFileName == NULL && mFvDataInfo.FvName[0] != '\0') { + FvFileName = mFvDataInfo.FvName; + } + + if (FvFileName == NULL) { + Error (NULL, 0, 1001, "Missing option", "Output file name"); + return EFI_ABORTED; + } + + if (mFvDataInfo.FvBlocks[0].Length == 0) { + Error (NULL, 0, 1001, "Missing required argument", "Block Size"); + return EFI_ABORTED; + } + + // + // Debug message Fv File System Guid + // + if (mFvDataInfo.FvFileSystemGuidSet) { + DebugMsg (NULL, 0, 9, "FV File System Guid", "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X", + mFvDataInfo.FvFileSystemGuid.Data1, + mFvDataInfo.FvFileSystemGuid.Data2, + mFvDataInfo.FvFileSystemGuid.Data3, + mFvDataInfo.FvFileSystemGuid.Data4[0], + mFvDataInfo.FvFileSystemGuid.Data4[1], + mFvDataInfo.FvFileSystemGuid.Data4[2], + mFvDataInfo.FvFileSystemGuid.Data4[3], + mFvDataInfo.FvFileSystemGuid.Data4[4], + mFvDataInfo.FvFileSystemGuid.Data4[5], + mFvDataInfo.FvFileSystemGuid.Data4[6], + mFvDataInfo.FvFileSystemGuid.Data4[7]); + } + // + // Debug message Fv Name Guid + // + if (mFvDataInfo.FvNameGuidSet) { + DebugMsg (NULL, 0, 9, "FV Name Guid", "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X", + mFvDataInfo.FvNameGuid.Data1, + mFvDataInfo.FvNameGuid.Data2, + mFvDataInfo.FvNameGuid.Data3, + mFvDataInfo.FvNameGuid.Data4[0], + mFvDataInfo.FvNameGuid.Data4[1], + mFvDataInfo.FvNameGuid.Data4[2], + mFvDataInfo.FvNameGuid.Data4[3], + mFvDataInfo.FvNameGuid.Data4[4], + mFvDataInfo.FvNameGuid.Data4[5], + mFvDataInfo.FvNameGuid.Data4[6], + mFvDataInfo.FvNameGuid.Data4[7]); + } + + if (CompareGuid (&mFvDataInfo.FvFileSystemGuid, &mEfiFirmwareFileSystem2Guid) == 0) { + mFvDataInfo.IsPiFvImage = TRUE; + } + + // + // FvMap file to log the function address of all modules in one Fvimage + // + if (MapFileName != NULL) { + strcpy (FvMapName, MapFileName); + } else { + strcpy (FvMapName, FvFileName); + strcat (FvMapName, ".map"); + } + VerboseMsg ("FV Map file name is %s", FvMapName); + + // + // Calculate the FV size and Update Fv Size based on the actual FFS files. + // And Update mFvDataInfo data. + // + Status = CalculateFvSize (&mFvDataInfo); + if (EFI_ERROR (Status)) { + return Status; + } + VerboseMsg ("the generated FV image size is %d bytes", mFvDataInfo.Size); + + // + // support fv image and empty fv image + // + FvImageSize = mFvDataInfo.Size; + + // + // Allocate the FV, assure FvImage Header 8 byte alignment + // + FvBufferHeader = malloc (FvImageSize + sizeof (UINT64)); + if (FvBufferHeader == NULL) { + return EFI_OUT_OF_RESOURCES; + } + FvImage = (UINT8 *) (((UINTN) FvBufferHeader + 7) & ~7); + + // + // Initialize the FV to the erase polarity + // + if (mFvDataInfo.FvAttributes == 0) { + // + // Set Default Fv Attribute + // + mFvDataInfo.FvAttributes = FV_DEFAULT_ATTRIBUTE; + } + if (mFvDataInfo.FvAttributes & EFI_FVB2_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 Fv file system GUID + // + memcpy (&FvHeader->FileSystemGuid, &mFvDataInfo.FvFileSystemGuid, sizeof (EFI_GUID)); + + FvHeader->FvLength = FvImageSize; + FvHeader->Signature = EFI_FVH_SIGNATURE; + FvHeader->Attributes = mFvDataInfo.FvAttributes; + FvHeader->Revision = EFI_FVH_REVISION; + FvHeader->ExtHeaderOffset = 0; + FvHeader->Reserved[0] = 0; + + // + // Copy firmware block map + // + for (Index = 0; mFvDataInfo.FvBlocks[Index].Length != 0; Index++) { + FvHeader->BlockMap[Index].NumBlocks = mFvDataInfo.FvBlocks[Index].NumBlocks; + FvHeader->BlockMap[Index].Length = mFvDataInfo.FvBlocks[Index].Length; + } + + // + // Add block map terminator + // + FvHeader->BlockMap[Index].NumBlocks = 0; + FvHeader->BlockMap[Index].Length = 0; + + // + // Complete the header + // + FvHeader->HeaderLength = (UINT16) (((UINTN) &(FvHeader->BlockMap[Index + 1])) - (UINTN) FvImage); + FvHeader->Checksum = 0; + FvHeader->Checksum = CalculateChecksum16 ((UINT16 *) FvHeader, FvHeader->HeaderLength / sizeof (UINT16)); + + // + // If there is no FFS file, generate one empty FV + // + if (mFvDataInfo.FvFiles[0][0] == 0) { + goto WriteFile; + } + + // + // Initialize our "file" view of the buffer + // + FvImageMemoryFile.FileImage = (CHAR8 *)FvImage; + FvImageMemoryFile.CurrentFilePointer = (CHAR8 *)FvImage + FvHeader->HeaderLength; + FvImageMemoryFile.Eof = (CHAR8 *)FvImage + FvImageSize; + + // + // Initialize the FV library. + // + InitializeFvLib (FvImageMemoryFile.FileImage, FvImageSize); + + // + // Initialize the VTF file address. + // + VtfFileImage = (EFI_FFS_FILE_HEADER *) FvImageMemoryFile.Eof; + + // + // Open FvMap file + // + FvMapFile = fopen (FvMapName, "w"); + if (FvMapFile == NULL) { + Error (NULL, 0, 0001, "Error opening file", FvMapName); + return EFI_ABORTED; + } + + // + // record FV size information into FvMap file. + // + if (mFvTotalSize != 0) { + fprintf (FvMapFile, EFI_FV_TOTAL_SIZE_STRING); + fprintf (FvMapFile, " = 0x%x\n", mFvTotalSize); + } + if (mFvTakenSize != 0) { + fprintf (FvMapFile, EFI_FV_TAKEN_SIZE_STRING); + fprintf (FvMapFile, " = 0x%x\n", mFvTakenSize); + } + if (mFvTotalSize != 0 && mFvTakenSize != 0) { + fprintf (FvMapFile, EFI_FV_SPACE_SIZE_STRING); + fprintf (FvMapFile, " = 0x%x\n\n", mFvTotalSize - mFvTakenSize); + } + + // + // Set PI FV extension header + // + if (mFvDataInfo.FvNameGuidSet) { + memcpy (&FvExtHeader.FvName, &mFvDataInfo.FvNameGuid, sizeof (EFI_GUID)); + FvExtHeader.ExtHeaderSize = sizeof (EFI_FIRMWARE_VOLUME_EXT_HEADER); + AddPadFile (&FvImageMemoryFile, 8, &FvExtHeader); + // + // Fv Extension header change update Fv Header Check sum + // + FvHeader->Checksum = 0; + FvHeader->Checksum = CalculateChecksum16 ((UINT16 *) FvHeader, FvHeader->HeaderLength / sizeof (UINT16)); + } + + // + // Add files to FV + // + for (Index = 0; mFvDataInfo.FvFiles[Index][0] != 0; Index++) { + // + // Add the file + // + Status = AddFile (&FvImageMemoryFile, &mFvDataInfo, Index, &VtfFileImage, FvMapFile); + + // + // Exit if error detected while adding the file + // + if (EFI_ERROR (Status)) { + goto Finish; + } + } + + // + // 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. + // If the left space is less than sizeof (EFI_FFS_FILE_HEADER)? + // + Status = PadFvImage (&FvImageMemoryFile, VtfFileImage); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 4002, "Resource", "FV space is full, cannot add pad file between the last file and the VTF file."); + goto Finish; + } + if (!mArm) { + // + // 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 ((mFvDataInfo.BaseAddress + mFvDataInfo.Size) == FV_IMAGES_TOP_ADDRESS) { + Status = UpdateResetVector (&FvImageMemoryFile, &mFvDataInfo, VtfFileImage); + if (EFI_ERROR(Status)) { + Error (NULL, 0, 3000, "Invalid", "Could not update the reset vector."); + goto Finish; + } + DebugMsg (NULL, 0, 9, "Update Reset vector in VTF file", NULL); + } + } + } + + if (mArm) { + Status = UpdateArmResetVectorIfNeeded (&FvImageMemoryFile, &mFvDataInfo); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 3000, "Invalid", "Could not update the reset vector."); + goto Finish; + } + + // + // Update Checksum for FvHeader + // + FvHeader->Checksum = 0; + FvHeader->Checksum = CalculateChecksum16 ((UINT16 *) FvHeader, FvHeader->HeaderLength / sizeof (UINT16)); + } + + // + // Update FV Alignment attribute to the largest alignment of all the FFS files in the FV + // + if ((((FvHeader->Attributes & EFI_FVB2_ALIGNMENT) >> 16)) < MaxFfsAlignment) { + FvHeader->Attributes = ((MaxFfsAlignment << 16) | (FvHeader->Attributes & 0xFFFF)); + // + // Update Checksum for FvHeader + // + FvHeader->Checksum = 0; + FvHeader->Checksum = CalculateChecksum16 ((UINT16 *) FvHeader, FvHeader->HeaderLength / sizeof (UINT16)); + } + +WriteFile: + // + // Write fv file + // + FvFile = fopen (FvFileName, "wb"); + if (FvFile == NULL) { + Error (NULL, 0, 0001, "Error opening file", FvFileName); + Status = EFI_ABORTED; + goto Finish; + } + + if (fwrite (FvImage, 1, FvImageSize, FvFile) != FvImageSize) { + Error (NULL, 0, 0002, "Error writing file", FvFileName); + Status = EFI_ABORTED; + goto Finish; + } + +Finish: + if (FvBufferHeader != NULL) { + free (FvBufferHeader); + } + + if (FvFile != NULL) { + fclose (FvFile); + } + + if (FvMapFile != NULL) { + fclose (FvMapFile); + } + + return Status; +} + +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); + } +} + +EFI_STATUS +CalculateFvSize ( + FV_INFO *FvInfoPtr + ) +/*++ +Routine Description: + Calculate the FV size and Update Fv Size based on the actual FFS files. + And Update FvInfo data. + +Arguments: + FvInfoPtr - The pointer to FV_INFO structure. + +Returns: + EFI_ABORTED - Ffs Image Error + EFI_SUCCESS - Successfully update FvSize +--*/ +{ + UINTN CurrentOffset; + UINTN Index; + FILE *fpin; + UINTN FfsFileSize; + UINT32 FfsAlignment; + EFI_FFS_FILE_HEADER FfsHeader; + BOOLEAN VtfFileFlag; + + VtfFileFlag = FALSE; + fpin = NULL; + Index = 0; + + // + // Compute size for easy access later + // + FvInfoPtr->Size = 0; + for (Index = 0; FvInfoPtr->FvBlocks[Index].NumBlocks > 0 && FvInfoPtr->FvBlocks[Index].Length > 0; Index++) { + FvInfoPtr->Size += FvInfoPtr->FvBlocks[Index].NumBlocks * FvInfoPtr->FvBlocks[Index].Length; + } + + // + // Caculate the required sizes for all FFS files. + // + CurrentOffset = sizeof (EFI_FIRMWARE_VOLUME_HEADER); + + for (Index = 1;; Index ++) { + CurrentOffset += sizeof (EFI_FV_BLOCK_MAP_ENTRY); + if (FvInfoPtr->FvBlocks[Index].NumBlocks == 0 || FvInfoPtr->FvBlocks[Index].Length == 0) { + break; + } + } + + // + // Calculate PI extension header + // + if (CompareGuid (&mFvDataInfo.FvNameGuid, &mZeroGuid) != 0) { + CurrentOffset += sizeof (EFI_FFS_FILE_HEADER) + sizeof (EFI_FIRMWARE_VOLUME_EXT_HEADER); + CurrentOffset = (CurrentOffset + 7) & (~7); + } + + // + // Accumlate every FFS file size. + // + for (Index = 0; FvInfoPtr->FvFiles[Index][0] != 0; Index++) { + // + // Open FFS file + // + fpin = NULL; + fpin = fopen (FvInfoPtr->FvFiles[Index], "rb"); + if (fpin == NULL) { + Error (NULL, 0, 0001, "Error opening file", FvInfoPtr->FvFiles[Index]); + return EFI_ABORTED; + } + // + // Get the file size + // + FfsFileSize = _filelength (fileno (fpin)); + // + // Read Ffs File header + // + fread (&FfsHeader, sizeof (UINT8), sizeof (EFI_FFS_FILE_HEADER), fpin); + // + // close file + // + fclose (fpin); + + if (FvInfoPtr->IsPiFvImage) { + // + // Check whether this ffs file is vtf file + // + if (IsVtfFile (&FfsHeader)) { + if (VtfFileFlag) { + // + // One Fv image can't have two vtf files. + // + return EFI_ABORTED; + } + VtfFileFlag = TRUE; + // + // The space between Vft File and the latest file must be able to contain + // one ffs file header in order to add one pad file. + // + CurrentOffset += sizeof (EFI_FFS_FILE_HEADER); + } + // + // Get the alignment of FFS file + // + ReadFfsAlignment (&FfsHeader, &FfsAlignment); + FfsAlignment = 1 << FfsAlignment; + // + // Add Pad file + // + if (((CurrentOffset + sizeof (EFI_FFS_FILE_HEADER)) % FfsAlignment) != 0) { + CurrentOffset = (CurrentOffset + sizeof (EFI_FFS_FILE_HEADER) * 2 + FfsAlignment - 1) & ~(FfsAlignment - 1); + CurrentOffset -= sizeof (EFI_FFS_FILE_HEADER); + } + } + + // + // Add ffs file size + // + if (FvInfoPtr->SizeofFvFiles[Index] > FfsFileSize) { + CurrentOffset += FvInfoPtr->SizeofFvFiles[Index]; + } else { + CurrentOffset += FfsFileSize; + } + + // + // Make next ffs file start at QWord Boundry + // + if (FvInfoPtr->IsPiFvImage) { + CurrentOffset = (CurrentOffset + EFI_FFS_FILE_HEADER_ALIGNMENT - 1) & ~(EFI_FFS_FILE_HEADER_ALIGNMENT - 1); + } + } + + DebugMsg (NULL, 0, 9, "FvImage size", "The caculated fv image size is 0x%x and the current set fv image size is 0x%x", CurrentOffset, FvInfoPtr->Size); + + if (FvInfoPtr->Size == 0) { + // + // Update FvInfo data + // + FvInfoPtr->FvBlocks[0].NumBlocks = CurrentOffset / FvInfoPtr->FvBlocks[0].Length + ((CurrentOffset % FvInfoPtr->FvBlocks[0].Length)?1:0); + FvInfoPtr->Size = FvInfoPtr->FvBlocks[0].NumBlocks * FvInfoPtr->FvBlocks[0].Length; + FvInfoPtr->FvBlocks[1].NumBlocks = 0; + FvInfoPtr->FvBlocks[1].Length = 0; + } else if (FvInfoPtr->Size < CurrentOffset) { + // + // Not invalid + // + Error (NULL, 0, 3000, "Invalid", "the required fv image size 0x%x exceeds the set fv image size 0x%x", CurrentOffset, FvInfoPtr->Size); + return EFI_INVALID_PARAMETER; + } + + // + // Set Fv Size Information + // + mFvTotalSize = FvInfoPtr->Size; + mFvTakenSize = CurrentOffset; + + 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; +} + +EFI_STATUS +FfsRebase ( + IN OUT FV_INFO *FvInfo, + IN CHAR8 *FileName, + IN OUT EFI_FFS_FILE_HEADER *FfsFile, + IN UINTN XipOffset, + IN FILE *FvMapFile + ) +/*++ + +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: + + FvInfo A pointer to FV_INFO struture. + FileName Ffs File PathName + FfsFile A pointer to Ffs file image. + XipOffset The offset address to use for rebasing the XIP file image. + FvMapFile FvMapFile to record the function address in one Fvimage + +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; + PE_COFF_LOADER_IMAGE_CONTEXT OrigImageContext; + EFI_PHYSICAL_ADDRESS XipBase; + EFI_PHYSICAL_ADDRESS NewPe32BaseAddress; + EFI_PHYSICAL_ADDRESS *BaseToUpdate; + UINTN Index; + EFI_FILE_SECTION_POINTER CurrentPe32Section; + EFI_FFS_FILE_STATE SavedState; + EFI_IMAGE_OPTIONAL_HEADER_UNION *ImgHdr; + EFI_TE_IMAGE_HEADER *TEImageHeader; + UINT8 Flags; + UINT8 *MemoryImagePointer; + EFI_IMAGE_SECTION_HEADER *SectionHeader; + CHAR8 PeFileName [_MAX_PATH]; + CHAR8 *Cptr; + FILE *PeFile; + UINT8 *PeFileBuffer; + UINT32 PeFileSize; + CHAR8 *PdbPointer; + + Index = 0; + MemoryImagePointer = NULL; + BaseToUpdate = NULL; + TEImageHeader = NULL; + ImgHdr = NULL; + SectionHeader = NULL; + Cptr = NULL; + PeFile = NULL; + PeFileBuffer = NULL; + + // + // Check XipAddress, BootAddress and RuntimeAddress + // + Flags = 0; + + if (FvInfo->BaseAddress != 0) { + Flags |= REBASE_XIP_FILE; + XipBase = FvInfo->BaseAddress + XipOffset; + } + if (FvInfo->BootBaseAddress != 0) { + Flags |= REBASE_BOOTTIME_FILE; + } + if (FvInfo->RuntimeBaseAddress != 0) { + Flags |= REBASE_RUNTIME_FILE; + } + + // + // Don't Rebase this FFS. + // Only copy the original map file into the FvMap file + // for the image that is not required to be relocated. + // + + // + // We only process files potentially containing PE32 sections. + // + switch (FfsFile->Type) { + case EFI_FV_FILETYPE_SECURITY_CORE: + case EFI_FV_FILETYPE_PEI_CORE: + case EFI_FV_FILETYPE_PEIM: + case EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER: + case EFI_FV_FILETYPE_DRIVER: + case EFI_FV_FILETYPE_DXE_CORE: + break; + default: + return EFI_SUCCESS; + } + // + // Rebase each PE32 section + // + Status = EFI_SUCCESS; + for (Index = 1;; Index++) { + // + // Init Value + // + NewPe32BaseAddress = 0; + + // + // Find Pe Image + // + Status = GetSectionByType (FfsFile, EFI_SECTION_PE32, Index, &CurrentPe32Section); + if (EFI_ERROR (Status)) { + break; + } + + // + // 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, 3000, "Invalid PeImage", "The input file is %s and the return status is %x", FileName, Status); + return Status; + } + + if (ImageContext.Machine == EFI_IMAGE_MACHINE_ARMT) { + mArm = TRUE; + } + + // + // Keep Image Context for PE image in FV + // + memcpy (&OrigImageContext, &ImageContext, sizeof (ImageContext)); + + // + // Get File PdbPointer + // + PdbPointer = PeCoffLoaderGetPdbPointer (ImageContext.Handle); + + // + // Get PeHeader pointer + // + ImgHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)((UINTN) CurrentPe32Section.Pe32Section + sizeof (EFI_PE32_SECTION) + ImageContext.PeCoffHeaderOffset); + + // + // Calculate the PE32 base address, based on file type + // + switch (FfsFile->Type) { + case EFI_FV_FILETYPE_SECURITY_CORE: + case EFI_FV_FILETYPE_PEI_CORE: + case EFI_FV_FILETYPE_PEIM: + case EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER: + if ((Flags & REBASE_XIP_FILE) == 0) { + // + // We aren't relocating XIP code, so skip it. + // + goto WritePeMap; + } + + // + // Check if section-alignment and file-alignment match or not + // + if ((ImgHdr->Pe32.OptionalHeader.SectionAlignment != ImgHdr->Pe32.OptionalHeader.FileAlignment)) { + // + // Xip module has the same section alignment and file alignment. + // + Error (NULL, 0, 3000, "Invalid", "Section-Alignment and File-Alignment do not match : %s.", FileName); + return EFI_ABORTED; + } + // + // PeImage has no reloc section. It will try to get reloc data from the original EFI image. + // + if (ImageContext.RelocationsStripped) { + // + // Construct the original efi file Name + // + strcpy (PeFileName, FileName); + Cptr = PeFileName + strlen (PeFileName); + while (*Cptr != '.') { + Cptr --; + } + if (*Cptr != '.') { + Error (NULL, 0, 3000, "Invalid", "The file %s has no .reloc section.", FileName); + return EFI_ABORTED; + } else { + *(Cptr + 1) = 'e'; + *(Cptr + 2) = 'f'; + *(Cptr + 3) = 'i'; + *(Cptr + 4) = '\0'; + } + PeFile = fopen (PeFileName, "rb"); + if (PeFile == NULL) { + Warning (NULL, 0, 0, "Invalid", "The file %s has no .reloc section.", FileName); + //Error (NULL, 0, 3000, "Invalid", "The file %s has no .reloc section.", FileName); + //return EFI_ABORTED; + break; + } + // + // Get the file size + // + PeFileSize = _filelength (fileno (PeFile)); + PeFileBuffer = (UINT8 *) malloc (PeFileSize); + if (PeFileBuffer == NULL) { + Error (NULL, 0, 4001, "Resource", "memory cannot be allocated on rebase of %s", FileName); + return EFI_OUT_OF_RESOURCES; + } + // + // Read Pe File + // + fread (PeFileBuffer, sizeof (UINT8), PeFileSize, PeFile); + // + // close file + // + fclose (PeFile); + // + // Handle pointer to the original efi image. + // + ImageContext.Handle = PeFileBuffer; + Status = PeCoffLoaderGetImageInfo (&ImageContext); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 3000, "Invalid PeImage", "The input file is %s and the return status is %x", FileName, Status); + return Status; + } + ImageContext.RelocationsStripped = FALSE; + } + + NewPe32BaseAddress = XipBase + (UINTN) CurrentPe32Section.Pe32Section + sizeof (EFI_PE32_SECTION) - (UINTN)FfsFile; + BaseToUpdate = &XipBase; + break; + + case EFI_FV_FILETYPE_DRIVER: + case EFI_FV_FILETYPE_DXE_CORE: + switch (ImgHdr->Pe32.OptionalHeader.Subsystem) { + case EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER: + if ((Flags & REBASE_XIP_FILE) == REBASE_XIP_FILE) { + // + // Check if section-alignment and file-alignment match or not + // + if ((ImgHdr->Pe32.OptionalHeader.SectionAlignment != ImgHdr->Pe32.OptionalHeader.FileAlignment)) { + // + // Xip module has the same section alignment and file alignment. + // + Error (NULL, 0, 3000, "Invalid", "Section-Alignment and File-Alignment do not match : %s.", FileName); + return EFI_ABORTED; + } + NewPe32BaseAddress = XipBase + (UINTN) CurrentPe32Section.Pe32Section + sizeof (EFI_PE32_SECTION) - (UINTN)FfsFile; + BaseToUpdate = &XipBase; + } else if ((Flags & REBASE_RUNTIME_FILE) == REBASE_RUNTIME_FILE) { + // + // make sure image base address at the section alignment + // + FvInfo->RuntimeBaseAddress = (FvInfo->RuntimeBaseAddress - ImageContext.ImageSize) & (~(ImageContext.SectionAlignment - 1)); + FvInfo->RuntimeBaseAddress = FvInfo->RuntimeBaseAddress & (~(EFI_PAGE_SIZE - 1)); + NewPe32BaseAddress = FvInfo->RuntimeBaseAddress; + BaseToUpdate = &(FvInfo->RuntimeBaseAddress); + } else { + // + // RT drivers aren't supposed to be relocated + // + goto WritePeMap; + } + break; + + default: + // + // We treat all other subsystems the same as BS_DRIVER + // + if ((Flags & REBASE_XIP_FILE) == REBASE_XIP_FILE) { + // + // Check if section-alignment and file-alignment match or not + // + if ((ImgHdr->Pe32.OptionalHeader.SectionAlignment != ImgHdr->Pe32.OptionalHeader.FileAlignment)) { + // + // Xip module has the same section alignment and file alignment. + // + Error (NULL, 0, 3000, "Invalid", "Section-Alignment and File-Alignment do not match : %s.", FileName); + return EFI_ABORTED; + } + NewPe32BaseAddress = XipBase + (UINTN) CurrentPe32Section.Pe32Section + sizeof (EFI_PE32_SECTION) - (UINTN)FfsFile; + BaseToUpdate = &XipBase; + } else if ((Flags & REBASE_BOOTTIME_FILE) == REBASE_BOOTTIME_FILE) { + // + // make sure image base address at the Section and Page alignment + // + FvInfo->BootBaseAddress = (FvInfo->BootBaseAddress - ImageContext.ImageSize) & (~(ImageContext.SectionAlignment - 1)); + FvInfo->BootBaseAddress = FvInfo->BootBaseAddress & (~(EFI_PAGE_SIZE - 1)); + NewPe32BaseAddress = FvInfo->BootBaseAddress; + BaseToUpdate = &(FvInfo->BootBaseAddress); + } else { + // + // Skip all BS_DRIVER's + // + goto WritePeMap; + } + break; + } + break; + + default: + // + // Not supported file type + // + return EFI_SUCCESS; + } + + // + // Relocation exist and rebase + // + if (!ImageContext.RelocationsStripped) { + // + // Load and Relocate Image Data + // + MemoryImagePointer = (UINT8 *) malloc ((UINTN) ImageContext.ImageSize + ImageContext.SectionAlignment); + if (MemoryImagePointer == NULL) { + Error (NULL, 0, 4001, "Resource", "memory cannot be allocated on rebase of %s", FileName); + return EFI_OUT_OF_RESOURCES; + } + memset ((VOID *) MemoryImagePointer, 0, (UINTN) ImageContext.ImageSize + ImageContext.SectionAlignment); + ImageContext.ImageAddress = ((UINTN) MemoryImagePointer + ImageContext.SectionAlignment - 1) & (~(ImageContext.SectionAlignment - 1)); + + Status = PeCoffLoaderLoadImage (&ImageContext); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 3000, "Invalid", "LocateImage() call failed on rebase of %s", FileName); + free ((VOID *) MemoryImagePointer); + return Status; + } + + ImageContext.DestinationAddress = NewPe32BaseAddress; + Status = PeCoffLoaderRelocateImage (&ImageContext); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 3000, "Invalid", "RelocateImage() call failed on rebase of %s", FileName); + free ((VOID *) MemoryImagePointer); + return Status; + } + + // + // Copy Relocated data to raw image file. + // + SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ( + (UINTN) ImgHdr + + sizeof (UINT32) + + sizeof (EFI_IMAGE_FILE_HEADER) + + ImgHdr->Pe32.FileHeader.SizeOfOptionalHeader + ); + + for (Index = 0; Index < ImgHdr->Pe32.FileHeader.NumberOfSections; Index ++, SectionHeader ++) { + CopyMem ( + (UINT8 *) CurrentPe32Section.Pe32Section + sizeof (EFI_COMMON_SECTION_HEADER) + SectionHeader->PointerToRawData, + (VOID*) (UINTN) (ImageContext.ImageAddress + SectionHeader->VirtualAddress), + SectionHeader->SizeOfRawData + ); + } + + free ((VOID *) MemoryImagePointer); + MemoryImagePointer = NULL; + if (PeFileBuffer != NULL) { + free (PeFileBuffer); + PeFileBuffer = NULL; + } + } + + // + // Update Image Base Address + // + if (ImgHdr->Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) { + ImgHdr->Pe32.OptionalHeader.ImageBase = (UINT32) NewPe32BaseAddress; + } else if (ImgHdr->Pe32Plus.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) { + ImgHdr->Pe32Plus.OptionalHeader.ImageBase = NewPe32BaseAddress; + } else { + Error (NULL, 0, 3000, "Invalid", "unknown PE magic signature %X in PE32 image %s", + (UINT32) ImgHdr->Pe32.OptionalHeader.Magic, + FileName + ); + return EFI_ABORTED; + } + + // + // Update BASE address by add one page size. + // + *BaseToUpdate -= EFI_PAGE_SIZE; + + // + // 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) + ); + } else { + FfsFile->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM; + } + + FfsFile->State = SavedState; + } + + // + // Get this module function address from ModulePeMapFile and add them into FvMap file + // +WritePeMap: + // + // Default use FileName as map file path + // + if (PdbPointer == NULL) { + PdbPointer = FileName; + } + + WriteMapFile (FvMapFile, PdbPointer, (EFI_GUID *) FfsFile, NewPe32BaseAddress, &OrigImageContext); + } + + if (FfsFile->Type != EFI_FV_FILETYPE_SECURITY_CORE && + FfsFile->Type != EFI_FV_FILETYPE_PEI_CORE && + FfsFile->Type != EFI_FV_FILETYPE_PEIM && + FfsFile->Type != EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER + ) { + // + // Only Peim code may have a TE section + // + return EFI_SUCCESS; + } + + // + // Now process TE sections + // + for (Index = 1;; Index++) { + NewPe32BaseAddress = 0; + + // + // Find Te Image + // + Status = GetSectionByType (FfsFile, EFI_SECTION_TE, Index, &CurrentPe32Section); + if (EFI_ERROR (Status)) { + break; + } + + // + // 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)); + + // + // Initialize context, load image info. + // + memset (&ImageContext, 0, sizeof (ImageContext)); + ImageContext.Handle = (VOID *) TEImageHeader; + ImageContext.ImageRead = (PE_COFF_LOADER_READ_FILE) FfsRebaseImageRead; + Status = PeCoffLoaderGetImageInfo (&ImageContext); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 3000, "Invalid TeImage", "The input file is %s and the return status is %x", FileName, Status); + return Status; + } + + if (ImageContext.Machine == EFI_IMAGE_MACHINE_ARMT) { + mArm = TRUE; + } + + // + // Keep Image Context for TE image in FV + // + memcpy (&OrigImageContext, &ImageContext, sizeof (ImageContext)); + + // + // Get File PdbPointer + // + PdbPointer = PeCoffLoaderGetPdbPointer (ImageContext.Handle); + + if ((Flags & REBASE_XIP_FILE) == 0) { + // + // For none XIP PEIM module, their map info also are collected. + // + goto WriteTeMap; + } + + // + // Set new rebased address. + // + NewPe32BaseAddress = XipBase + (UINTN) TEImageHeader + sizeof (EFI_TE_IMAGE_HEADER) \ + - TEImageHeader->StrippedSize - (UINTN) FfsFile; + + // + // if reloc is stripped, try to get the original efi image to get reloc info. + // + if (ImageContext.RelocationsStripped == TRUE) { + // + // Construct the original efi file name + // + strcpy (PeFileName, FileName); + Cptr = PeFileName + strlen (PeFileName); + while (*Cptr != '.') { + Cptr --; + } + + if (*Cptr != '.') { + Error (NULL, 0, 3000, "Invalid", "The file %s has no .reloc section.", FileName); + return EFI_ABORTED; + } else { + *(Cptr + 1) = 'e'; + *(Cptr + 2) = 'f'; + *(Cptr + 3) = 'i'; + *(Cptr + 4) = '\0'; + } + + PeFile = fopen (PeFileName, "rb"); + if (PeFile == NULL) { + Warning (NULL, 0, 0, "Invalid", "The file %s has no .reloc section.", FileName); + //Error (NULL, 0, 3000, "Invalid", "The file %s has no .reloc section.", FileName); + //return EFI_ABORTED; + } else { + // + // Get the file size + // + PeFileSize = _filelength (fileno (PeFile)); + PeFileBuffer = (UINT8 *) malloc (PeFileSize); + if (PeFileBuffer == NULL) { + Error (NULL, 0, 4001, "Resource", "memory cannot be allocated on rebase of %s", FileName); + return EFI_OUT_OF_RESOURCES; + } + // + // Read Pe File + // + fread (PeFileBuffer, sizeof (UINT8), PeFileSize, PeFile); + // + // close file + // + fclose (PeFile); + // + // Append reloc section into TeImage + // + ImageContext.Handle = PeFileBuffer; + Status = PeCoffLoaderGetImageInfo (&ImageContext); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 3000, "Invalid TeImage", "The input file is %s and the return status is %x", FileName, Status); + return Status; + } + ImageContext.RelocationsStripped = FALSE; + } + } + + // + // Relocation exist and rebase + // + if (!ImageContext.RelocationsStripped) { + // + // Load and Relocate Image Data + // + MemoryImagePointer = (UINT8 *) malloc ((UINTN) ImageContext.ImageSize + ImageContext.SectionAlignment); + if (MemoryImagePointer == NULL) { + Error (NULL, 0, 4001, "Resource", "memory cannot be allocated on rebase of %s", FileName); + return EFI_OUT_OF_RESOURCES; + } + memset ((VOID *) MemoryImagePointer, 0, (UINTN) ImageContext.ImageSize + ImageContext.SectionAlignment); + ImageContext.ImageAddress = ((UINTN) MemoryImagePointer + ImageContext.SectionAlignment - 1) & (~(ImageContext.SectionAlignment - 1)); + + Status = PeCoffLoaderLoadImage (&ImageContext); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 3000, "Invalid", "LocateImage() call failed on rebase of %s", FileName); + free ((VOID *) MemoryImagePointer); + return Status; + } + // + // Reloacate TeImage + // + ImageContext.DestinationAddress = NewPe32BaseAddress; + Status = PeCoffLoaderRelocateImage (&ImageContext); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 3000, "Invalid", "RelocateImage() call failed on rebase of TE image %s", FileName); + free ((VOID *) MemoryImagePointer); + return Status; + } + + // + // Copy the relocated image into raw image file. + // + SectionHeader = (EFI_IMAGE_SECTION_HEADER *) (TEImageHeader + 1); + for (Index = 0; Index < TEImageHeader->NumberOfSections; Index ++, SectionHeader ++) { + if (!ImageContext.IsTeImage) { + CopyMem ( + (UINT8 *) TEImageHeader + sizeof (EFI_TE_IMAGE_HEADER) - TEImageHeader->StrippedSize + SectionHeader->PointerToRawData, + (VOID*) (UINTN) (ImageContext.ImageAddress + SectionHeader->VirtualAddress), + SectionHeader->SizeOfRawData + ); + } else { + CopyMem ( + (UINT8 *) TEImageHeader + sizeof (EFI_TE_IMAGE_HEADER) - TEImageHeader->StrippedSize + SectionHeader->PointerToRawData, + (VOID*) (UINTN) (ImageContext.ImageAddress + sizeof (EFI_TE_IMAGE_HEADER) - TEImageHeader->StrippedSize + SectionHeader->VirtualAddress), + SectionHeader->SizeOfRawData + ); + } + } + + // + // Free the allocated memory resource + // + free ((VOID *) MemoryImagePointer); + MemoryImagePointer = NULL; + if (PeFileBuffer != NULL) { + free (PeFileBuffer); + PeFileBuffer = NULL; + } + } + + // + // Update Image Base Address + // + TEImageHeader->ImageBase = NewPe32BaseAddress; + + // + // 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) + ); + } else { + FfsFile->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM; + } + + FfsFile->State = SavedState; + } + // + // Get this module function address from ModulePeMapFile and add them into FvMap file + // +WriteTeMap: + // + // Default use FileName as map file path + // + if (PdbPointer == NULL) { + PdbPointer = FileName; + } + + WriteMapFile ( + FvMapFile, + PdbPointer, + (EFI_GUID *) FfsFile, + NewPe32BaseAddress, + &OrigImageContext + ); + } + + return EFI_SUCCESS; +} + +EFI_STATUS +FindApResetVectorPosition ( + IN MEMORY_FILE *FvImage, + OUT UINT8 **Pointer + ) +/*++ + +Routine Description: + + Find the position in this FvImage to place Ap reset vector. + +Arguments: + + FvImage Memory file for the FV memory image. + Pointer Pointer to pointer to position. + +Returns: + + EFI_NOT_FOUND - No satisfied position is found. + EFI_SUCCESS - The suitable position is return. + +--*/ +{ + EFI_FFS_FILE_HEADER *PadFile; + UINT32 Index; + EFI_STATUS Status; + UINT8 *FixPoint; + UINT32 FileLength; + + for (Index = 1; ;Index ++) { + // + // Find Pad File to add ApResetVector info + // + Status = GetFileByType (EFI_FV_FILETYPE_FFS_PAD, Index, &PadFile); + if (EFI_ERROR (Status) || (PadFile == NULL)) { + // + // No Pad file to be found. + // + break; + } + // + // Get Pad file size. + // + FileLength = (*(UINT32 *)(PadFile->Size)) & 0x00FFFFFF; + FileLength = (FileLength + EFI_FFS_FILE_HEADER_ALIGNMENT - 1) & ~(EFI_FFS_FILE_HEADER_ALIGNMENT - 1); + // + // FixPoint must be align on 0x1000 relative to FvImage Header + // + FixPoint = (UINT8*) PadFile + sizeof (EFI_FFS_FILE_HEADER); + FixPoint = FixPoint + 0x1000 - (((UINTN) FixPoint - (UINTN) FvImage->FileImage) & 0xFFF); + // + // FixPoint be larger at the last place of one fv image. + // + while (((UINTN) FixPoint + SIZEOF_STARTUP_DATA_ARRAY - (UINTN) PadFile) <= FileLength) { + FixPoint += 0x1000; + } + FixPoint -= 0x1000; + + if ((UINTN) FixPoint < ((UINTN) PadFile + sizeof (EFI_FFS_FILE_HEADER))) { + // + // No alignment FixPoint in this Pad File. + // + continue; + } + + if ((UINTN) FvImage->Eof - (UINTN)FixPoint <= 0x20000) { + // + // Find the position to place ApResetVector + // + *Pointer = FixPoint; + return EFI_SUCCESS; + } + } + + return EFI_NOT_FOUND; +} + +EFI_STATUS +ParseCapInf ( + IN MEMORY_FILE *InfFile, + OUT CAP_INFO *CapInfo + ) +/*++ + +Routine Description: + + This function parses a Cap.INF file and copies info into a CAP_INFO structure. + +Arguments: + + InfFile Memory file image. + CapInfo 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, Number; + EFI_STATUS Status; + + // + // Initialize Cap info + // + // memset (CapInfo, 0, sizeof (CAP_INFO)); + // + + // + // Read the Capsule Guid + // + Status = FindToken (InfFile, OPTIONS_SECTION_STRING, EFI_CAPSULE_GUID_STRING, 0, Value); + if (Status == EFI_SUCCESS) { + // + // Get the Capsule Guid + // + Status = StringToGuid (Value, &CapInfo->CapGuid); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 2000, "Invalid parameter", "%s = %s", EFI_CAPSULE_GUID_STRING, Value); + return EFI_ABORTED; + } + DebugMsg (NULL, 0, 9, "Capsule Guid", "%s = %s", EFI_CAPSULE_GUID_STRING, Value); + } + + // + // Read the Capsule Header Size + // + Status = FindToken (InfFile, OPTIONS_SECTION_STRING, EFI_CAPSULE_HEADER_SIZE_STRING, 0, Value); + if (Status == EFI_SUCCESS) { + Status = AsciiStringToUint64 (Value, FALSE, &Value64); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 2000, "Invalid parameter", "%s = %s", EFI_CAPSULE_HEADER_SIZE_STRING, Value); + return EFI_ABORTED; + } + CapInfo->HeaderSize = (UINT32) Value64; + DebugMsg (NULL, 0, 9, "Capsule Header size", "%s = %s", EFI_CAPSULE_HEADER_SIZE_STRING, Value); + } + + // + // Read the Capsule Flag + // + Status = FindToken (InfFile, OPTIONS_SECTION_STRING, EFI_CAPSULE_FLAGS_STRING, 0, Value); + if (Status == EFI_SUCCESS) { + if (strstr (Value, "PopulateSystemTable") != NULL) { + CapInfo->Flags |= CAPSULE_FLAGS_PERSIST_ACROSS_RESET | CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE; + } else if (strstr (Value, "PersistAcrossReset") != NULL) { + CapInfo->Flags |= CAPSULE_FLAGS_PERSIST_ACROSS_RESET; + } else { + Error (NULL, 0, 2000, "Invalid parameter", "invalid Flag setting for %s.", EFI_CAPSULE_FLAGS_STRING); + return EFI_ABORTED; + } + DebugMsg (NULL, 0, 9, "Capsule Flag", Value); + } + + // + // Read Capsule File name + // + Status = FindToken (InfFile, OPTIONS_SECTION_STRING, EFI_FILE_NAME_STRING, 0, Value); + if (Status == EFI_SUCCESS) { + // + // Get output file name + // + strcpy (CapInfo->CapName, Value); + } + + // + // Read the Capsule FileImage + // + Number = 0; + for (Index = 0; Index < MAX_NUMBER_OF_FILES_IN_CAP; Index++) { + if (CapInfo->CapFiles[Index][0] != '\0') { + continue; + } + // + // Read the capsule file name + // + Status = FindToken (InfFile, FILES_SECTION_STRING, EFI_FILE_NAME_STRING, Number++, Value); + + if (Status == EFI_SUCCESS) { + // + // Add the file + // + strcpy (CapInfo->CapFiles[Index], Value); + DebugMsg (NULL, 0, 9, "Capsule component file", "the %dth file name is %s", Index, CapInfo->CapFiles[Index]); + } else { + break; + } + } + + if (Index == 0) { + Warning (NULL, 0, 0, "Capsule components are not specified.", NULL); + } + + return EFI_SUCCESS; +} + +EFI_STATUS +GenerateCapImage ( + IN CHAR8 *InfFileImage, + IN UINTN InfFileSize, + IN CHAR8 *CapFileName + ) +/*++ + +Routine Description: + + This is the main function which will be called from application to create UEFI Capsule image. + +Arguments: + + InfFileImage Buffer containing the INF file contents. + InfFileSize Size of the contents of the InfFileImage buffer. + CapFileName Requested name for the Cap 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. + +--*/ +{ + UINT32 CapSize; + UINT8 *CapBuffer; + EFI_CAPSULE_HEADER *CapsuleHeader; + MEMORY_FILE InfMemoryFile; + UINT32 FileSize; + UINT32 Index; + FILE *fpin, *fpout; + EFI_STATUS Status; + + if (InfFileImage != NULL) { + // + // Initialize file structures + // + InfMemoryFile.FileImage = InfFileImage; + InfMemoryFile.CurrentFilePointer = InfFileImage; + InfMemoryFile.Eof = InfFileImage + InfFileSize; + + // + // Parse the Cap inf file for header information + // + Status = ParseCapInf (&InfMemoryFile, &mCapDataInfo); + if (Status != EFI_SUCCESS) { + return Status; + } + } + + if (mCapDataInfo.HeaderSize == 0) { + // + // make header size align 16 bytes. + // + mCapDataInfo.HeaderSize = sizeof (EFI_CAPSULE_HEADER); + mCapDataInfo.HeaderSize = (mCapDataInfo.HeaderSize + 0xF) & ~0xF; + } + + if (mCapDataInfo.HeaderSize < sizeof (EFI_CAPSULE_HEADER)) { + Error (NULL, 0, 2000, "Invalid parameter", "The specified HeaderSize cannot be less than the size of EFI_CAPSULE_HEADER."); + return EFI_INVALID_PARAMETER; + } + + if (CapFileName == NULL && mCapDataInfo.CapName[0] != '\0') { + CapFileName = mCapDataInfo.CapName; + } + + if (CapFileName == NULL) { + Error (NULL, 0, 2001, "Missing required argument", "Output Capsule file name"); + return EFI_INVALID_PARAMETER; + } + + // + // Set Default Capsule Guid value + // + if (CompareGuid (&mCapDataInfo.CapGuid, &mZeroGuid) == 0) { + memcpy (&mCapDataInfo.CapGuid, &mDefaultCapsuleGuid, sizeof (EFI_GUID)); + } + // + // Calculate the size of capsule image. + // + Index = 0; + FileSize = 0; + CapSize = mCapDataInfo.HeaderSize; + while (mCapDataInfo.CapFiles [Index][0] != '\0') { + fpin = fopen (mCapDataInfo.CapFiles[Index], "rb"); + if (fpin == NULL) { + Error (NULL, 0, 0001, "Error opening file", mCapDataInfo.CapFiles[Index]); + return EFI_ABORTED; + } + FileSize = _filelength (fileno (fpin)); + CapSize += FileSize; + fclose (fpin); + Index ++; + } + + // + // Allocate buffer for capsule image. + // + CapBuffer = (UINT8 *) malloc (CapSize); + if (CapBuffer == NULL) { + Error (NULL, 0, 4001, "Resource", "memory cannot be allocated for creating the capsule."); + return EFI_OUT_OF_RESOURCES; + } + + // + // Initialize the capsule header to zero + // + memset (CapBuffer, 0, mCapDataInfo.HeaderSize); + + // + // create capsule header and get capsule body + // + CapsuleHeader = (EFI_CAPSULE_HEADER *) CapBuffer; + memcpy (&CapsuleHeader->CapsuleGuid, &mCapDataInfo.CapGuid, sizeof (EFI_GUID)); + CapsuleHeader->HeaderSize = mCapDataInfo.HeaderSize; + CapsuleHeader->Flags = mCapDataInfo.Flags; + CapsuleHeader->CapsuleImageSize = CapSize; + + Index = 0; + FileSize = 0; + CapSize = CapsuleHeader->HeaderSize; + while (mCapDataInfo.CapFiles [Index][0] != '\0') { + fpin = fopen (mCapDataInfo.CapFiles[Index], "rb"); + if (fpin == NULL) { + Error (NULL, 0, 0001, "Error opening file", mCapDataInfo.CapFiles[Index]); + free (CapBuffer); + return EFI_ABORTED; + } + FileSize = _filelength (fileno (fpin)); + fread (CapBuffer + CapSize, 1, FileSize, fpin); + fclose (fpin); + Index ++; + CapSize += FileSize; + } + + // + // write capsule data into the output file + // + fpout = fopen (CapFileName, "wb"); + if (fpout == NULL) { + Error (NULL, 0, 0001, "Error opening file", CapFileName); + free (CapBuffer); + return EFI_ABORTED; + } + + fwrite (CapBuffer, 1, CapSize, fpout); + fclose (fpout); + + VerboseMsg ("The size of the generated capsule image is %d bytes", CapSize); + + return EFI_SUCCESS; +} diff --git a/BaseTools/Source/C/GenFv/GenFvInternalLib.h b/BaseTools/Source/C/GenFv/GenFvInternalLib.h new file mode 100644 index 0000000000..d6b3ad7fc1 --- /dev/null +++ b/BaseTools/Source/C/GenFv/GenFvInternalLib.h @@ -0,0 +1,421 @@ +/** @file + +Copyright (c) 2004 - 2008, 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: + + GenFvInternalLib.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_INTERNAL_LIB_H +#define _EFI_GEN_FV_INTERNAL_LIB_H + +// +// Include files +// +#include + +#include +#include + +#include +#include +#include +#include + +#include "CommonLib.h" +#include "ParseInf.h" +#include "EfiUtilityMsgs.h" + +// +// Different file separater for Linux and Windows +// +#define FILE_SEP_CHAR '/' + +// +// The maximum number of Pad file guid entries. +// +#define MAX_NUMBER_OF_PAD_FILE_GUIDS 1024 + +// +// 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_FILES_IN_CAP 1000 +#define EFI_FFS_FILE_HEADER_ALIGNMENT 8 + +// +// INF file strings +// +#define OPTIONS_SECTION_STRING "[options]" +#define ATTRIBUTES_SECTION_STRING "[attributes]" +#define FILES_SECTION_STRING "[files]" + +// +// Options section +// +#define EFI_FV_BASE_ADDRESS_STRING "EFI_BASE_ADDRESS" +#define EFI_FV_FILE_NAME_STRING "EFI_FILE_NAME" +#define EFI_NUM_BLOCKS_STRING "EFI_NUM_BLOCKS" +#define EFI_BLOCK_SIZE_STRING "EFI_BLOCK_SIZE" +#define EFI_GUID_STRING "EFI_GUID" +#define EFI_FV_FILESYSTEMGUID_STRING "EFI_FV_GUID" +#define EFI_FV_NAMEGUID_STRING "EFI_FVNAME_GUID" +#define EFI_CAPSULE_GUID_STRING "EFI_CAPSULE_GUID" +#define EFI_CAPSULE_HEADER_SIZE_STRING "EFI_CAPSULE_HEADER_SIZE" +#define EFI_CAPSULE_FLAGS_STRING "EFI_CAPSULE_FLAGS" +#define EFI_CAPSULE_VERSION_STRING "EFI_CAPSULE_VERSION" +#define EFI_FV_BOOT_DRIVER_BASE_ADDRESS_STRING "EFI_BOOT_DRIVER_BASE_ADDRESS" +#define EFI_FV_RUNTIME_DRIVER_BASE_ADDRESS_STRING "EFI_RUNTIME_DRIVER_BASE_ADDRESS" + +#define EFI_FV_TOTAL_SIZE_STRING "EFI_FV_TOTAL_SIZE" +#define EFI_FV_TAKEN_SIZE_STRING "EFI_FV_TAKEN_SIZE" +#define EFI_FV_SPACE_SIZE_STRING "EFI_FV_SPACE_SIZE" + +// +// Attributes section +// +#define EFI_FVB2_READ_DISABLED_CAP_STRING "EFI_READ_DISABLED_CAP" +#define EFI_FVB2_READ_ENABLED_CAP_STRING "EFI_READ_ENABLED_CAP" +#define EFI_FVB2_READ_STATUS_STRING "EFI_READ_STATUS" + +#define EFI_FVB2_WRITE_DISABLED_CAP_STRING "EFI_WRITE_DISABLED_CAP" +#define EFI_FVB2_WRITE_ENABLED_CAP_STRING "EFI_WRITE_ENABLED_CAP" +#define EFI_FVB2_WRITE_STATUS_STRING "EFI_WRITE_STATUS" + +#define EFI_FVB2_LOCK_CAP_STRING "EFI_LOCK_CAP" +#define EFI_FVB2_LOCK_STATUS_STRING "EFI_LOCK_STATUS" + +#define EFI_FVB2_STICKY_WRITE_STRING "EFI_STICKY_WRITE" +#define EFI_FVB2_MEMORY_MAPPED_STRING "EFI_MEMORY_MAPPED" +#define EFI_FVB2_ERASE_POLARITY_STRING "EFI_ERASE_POLARITY" + +#define EFI_FVB2_READ_LOCK_CAP_STRING "EFI_READ_LOCK_CAP" +#define EFI_FVB2_READ_LOCK_STATUS_STRING "EFI_READ_LOCK_STATUS" +#define EFI_FVB2_WRITE_LOCK_CAP_STRING "EFI_WRITE_LOCK_CAP" +#define EFI_FVB2_WRITE_LOCK_STATUS_STRING "EFI_WRITE_LOCK_STATUS" + +#define EFI_FVB2_ALIGNMENT_1_STRING "EFI_FVB2_ALIGNMENT_1" +#define EFI_FVB2_ALIGNMENT_2_STRING "EFI_FVB2_ALIGNMENT_2" +#define EFI_FVB2_ALIGNMENT_4_STRING "EFI_FVB2_ALIGNMENT_4" +#define EFI_FVB2_ALIGNMENT_8_STRING "EFI_FVB2_ALIGNMENT_8" +#define EFI_FVB2_ALIGNMENT_16_STRING "EFI_FVB2_ALIGNMENT_16" +#define EFI_FVB2_ALIGNMENT_32_STRING "EFI_FVB2_ALIGNMENT_32" +#define EFI_FVB2_ALIGNMENT_64_STRING "EFI_FVB2_ALIGNMENT_64" +#define EFI_FVB2_ALIGNMENT_128_STRING "EFI_FVB2_ALIGNMENT_128" +#define EFI_FVB2_ALIGNMENT_256_STRING "EFI_FVB2_ALIGNMENT_256" +#define EFI_FVB2_ALIGNMENT_512_STRING "EFI_FVB2_ALIGNMENT_512" +#define EFI_FVB2_ALIGNMENT_1K_STRING "EFI_FVB2_ALIGNMENT_1K" +#define EFI_FVB2_ALIGNMENT_2K_STRING "EFI_FVB2_ALIGNMENT_2K" +#define EFI_FVB2_ALIGNMENT_4K_STRING "EFI_FVB2_ALIGNMENT_4K" +#define EFI_FVB2_ALIGNMENT_8K_STRING "EFI_FVB2_ALIGNMENT_8K" +#define EFI_FVB2_ALIGNMENT_16K_STRING "EFI_FVB2_ALIGNMENT_16K" +#define EFI_FVB2_ALIGNMENT_32K_STRING "EFI_FVB2_ALIGNMENT_32K" +#define EFI_FVB2_ALIGNMENT_64K_STRING "EFI_FVB2_ALIGNMENT_64K" +#define EFI_FVB2_ALIGNMENT_128K_STRING "EFI_FVB2_ALIGNMENT_128K" +#define EFI_FVB2_ALIGNMENT_256K_STRING "EFI_FVB2_ALIGNMENT_256K" +#define EFI_FVB2_ALIGNMNET_512K_STRING "EFI_FVB2_ALIGNMENT_512K" +#define EFI_FVB2_ALIGNMENT_1M_STRING "EFI_FVB2_ALIGNMENT_1M" +#define EFI_FVB2_ALIGNMENT_2M_STRING "EFI_FVB2_ALIGNMENT_2M" +#define EFI_FVB2_ALIGNMENT_4M_STRING "EFI_FVB2_ALIGNMENT_4M" +#define EFI_FVB2_ALIGNMENT_8M_STRING "EFI_FVB2_ALIGNMENT_8M" +#define EFI_FVB2_ALIGNMENT_16M_STRING "EFI_FVB2_ALIGNMENT_16M" +#define EFI_FVB2_ALIGNMENT_32M_STRING "EFI_FVB2_ALIGNMENT_32M" +#define EFI_FVB2_ALIGNMENT_64M_STRING "EFI_FVB2_ALIGNMENT_64M" +#define EFI_FVB2_ALIGNMENT_128M_STRING "EFI_FVB2_ALIGNMENT_128M" +#define EFI_FVB2_ALIGNMENT_256M_STRING "EFI_FVB2_ALIGNMENT_256M" +#define EFI_FVB2_ALIGNMENT_512M_STRING "EFI_FVB2_ALIGNMENT_512M" +#define EFI_FVB2_ALIGNMENT_1G_STRING "EFI_FVB2_ALIGNMENT_1G" +#define EFI_FVB2_ALIGNMENT_2G_STRING "EFI_FVB2_ALIGNMENT_2G" + +// +// File sections +// +#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" + +// +// VTF (Firmware Volume Top File) signatures +// +#define IA32_X64_VTF_SIGNATURE_OFFSET 0x14 +#define IA32_X64_VTF0_SIGNATURE EFI_SIGNATURE_32('V','T','F',0) + +// +// Defines to calculate the offset for PEI CORE entry points +// +#define IA32_PEI_CORE_ENTRY_OFFSET 0x20 + +// +// Defines to calculate the offset for IA32 SEC CORE entry point +// +#define IA32_SEC_CORE_ENTRY_OFFSET 0xD + +// +// 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 + +// +// 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 + +// +// Rebase File type +// +#define REBASE_XIP_FILE 0x1 +#define REBASE_BOOTTIME_FILE 0x2 +#define REBASE_RUNTIME_FILE 0x4 + +// +// Private data types +// +// +// Component information +// +typedef struct { + UINTN Size; + CHAR8 ComponentName[_MAX_PATH]; +} COMPONENT_INFO; + +// +// FV and capsule information holder +// +typedef struct { + BOOLEAN BaseAddressSet; + EFI_PHYSICAL_ADDRESS BaseAddress; + EFI_PHYSICAL_ADDRESS BootBaseAddress; + EFI_PHYSICAL_ADDRESS RuntimeBaseAddress; + EFI_GUID FvFileSystemGuid; + BOOLEAN FvFileSystemGuidSet; + EFI_GUID FvNameGuid; + BOOLEAN FvNameGuidSet; + UINTN Size; + EFI_FVB_ATTRIBUTES FvAttributes; + CHAR8 FvName[_MAX_PATH]; + EFI_FV_BLOCK_MAP_ENTRY FvBlocks[MAX_NUMBER_OF_FV_BLOCKS]; + CHAR8 FvFiles[MAX_NUMBER_OF_FILES_IN_FV][_MAX_PATH]; + UINT32 SizeofFvFiles[MAX_NUMBER_OF_FILES_IN_FV]; + BOOLEAN IsPiFvImage; +} FV_INFO; + +typedef struct { + EFI_GUID CapGuid; + UINT32 HeaderSize; + UINT32 Flags; + CHAR8 CapName[_MAX_PATH]; + CHAR8 CapFiles[MAX_NUMBER_OF_FILES_IN_CAP][_MAX_PATH]; +} CAP_INFO; + +#pragma pack(1) + +typedef struct { + UINT64 CompAddress; + UINT32 CompSize; + UINT16 CompVersion; + UINT8 CvAndType; + UINT8 CheckSum; +} FIT_TABLE; + +#pragma pack() + +#define FV_DEFAULT_ATTRIBUTE 0x0004FEFF +extern FV_INFO mFvDataInfo; +extern CAP_INFO mCapDataInfo; +extern EFI_GUID mEfiFirmwareFileSystem2Guid; +extern UINT32 mFvTotalSize; +extern UINT32 mFvTakenSize; +// +// Local function prototypes +// +EFI_STATUS +ParseFvInf ( + IN MEMORY_FILE *InfFile, + OUT FV_INFO *FvInfo + ) +; + +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. + +--*/ +; + +EFI_STATUS +GetPe32Info ( + IN UINT8 *Pe32, + OUT UINT32 *EntryPoint, + OUT UINT32 *BaseOfCode, + OUT UINT16 *MachineType + ); + +EFI_STATUS +ParseCapInf ( + IN MEMORY_FILE *InfFile, + OUT CAP_INFO *CapInfo + ); + +EFI_STATUS +FindApResetVectorPosition ( + IN MEMORY_FILE *FvImage, + OUT UINT8 **Pointer + ); + +EFI_STATUS +CalculateFvSize ( + FV_INFO *FvInfoPtr + ); + +EFI_STATUS +FfsRebase ( + IN OUT FV_INFO *FvInfo, + IN CHAR8 *FileName, + IN OUT EFI_FFS_FILE_HEADER *FfsFile, + IN UINTN XipOffset, + IN FILE *FvMapFile + ); + +// +// Exported function prototypes +// +EFI_STATUS +GenerateCapImage ( + IN CHAR8 *InfFileImage, + IN UINTN InfFileSize, + IN CHAR8 *CapFileName + ) +/*++ + +Routine Description: + + This is the main function which will be called from application to + generate UEFI Capsule image. + +Arguments: + + InfFileImage Buffer containing the INF file contents. + InfFileSize Size of the contents of the InfFileImage buffer. + CapFileName Requested name for the Cap 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 +GenerateFvImage ( + IN CHAR8 *InfFileImage, + IN UINTN InfFileSize, + IN CHAR8 *FvFileName, + IN CHAR8 *MapFileName + ) +/*++ + +Routine Description: + + This is the main function which will be called from application to + generate Firmware Image conforms to PI spec. + +Arguments: + + InfFileImage Buffer containing the INF file contents. + InfFileSize Size of the contents of the InfFileImage buffer. + FvFileName Requested name for the FV file. + MapFileName Fv map file to log fv driver information. + +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. + +--*/ +; + +#endif diff --git a/BaseTools/Source/C/GenFv/Makefile b/BaseTools/Source/C/GenFv/Makefile new file mode 100644 index 0000000000..ee6ba4d437 --- /dev/null +++ b/BaseTools/Source/C/GenFv/Makefile @@ -0,0 +1,10 @@ +!INCLUDE ..\Makefiles\ms.common + +APPNAME = GenFv + +LIBS = $(LIB_PATH)\Common.lib RpcRT4.lib + +OBJECTS = GenFv.obj GenFvInternalLib.obj + +!INCLUDE ..\Makefiles\ms.app + diff --git a/BaseTools/Source/C/GenFw/GNUmakefile b/BaseTools/Source/C/GenFw/GNUmakefile new file mode 100644 index 0000000000..decae9e9ba --- /dev/null +++ b/BaseTools/Source/C/GenFw/GNUmakefile @@ -0,0 +1,18 @@ +ARCH ?= IA32 +MAKEROOT ?= .. + +APPNAME = GenFw + +OBJECTS = GenFw.o + +include $(MAKEROOT)/Makefiles/app.makefile + +LIBS = -lCommon +ifeq ($(CYGWIN), CYGWIN) + LIBS += -L/lib/e2fsprogs -luuid +endif + +ifeq ($(LINUX), Linux) + LIBS += -luuid +endif + diff --git a/BaseTools/Source/C/GenFw/GenFw.c b/BaseTools/Source/C/GenFw/GenFw.c new file mode 100644 index 0000000000..2278948b3d --- /dev/null +++ b/BaseTools/Source/C/GenFw/GenFw.c @@ -0,0 +1,3073 @@ +/** @file + +Copyright (c) 2004 - 2009, 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: + + GenFw.c + +Abstract: + + Converts a pe32+ image to an FW, Te image type, or other specific image. + +**/ + +#include "WinNtInclude.h" + +#ifndef __GNUC__ +#include +#endif +#include +#include +#include +#include +#include + +#include +#include + +// +// Acpi Table definition +// +#include +#include +#include +#include +#include + +#include "CommonLib.h" +#include "EfiUtilityMsgs.h" + +#include "elf_common.h" +#include "elf32.h" +#include "elf64.h" + + +// +// Version of this utility +// +#define UTILITY_NAME "GenFw" +#define UTILITY_MAJOR_VERSION 0 +#define UTILITY_MINOR_VERSION 2 + +// +// Action for this tool. +// +#define FW_DUMMY_IMAGE 0 +#define FW_EFI_IMAGE 1 +#define FW_TE_IMAGE 2 +#define FW_ACPI_IMAGE 3 +#define FW_BIN_IMAGE 4 +#define FW_ZERO_DEBUG_IMAGE 5 +#define FW_SET_STAMP_IMAGE 6 +#define FW_MCI_IMAGE 7 +#define FW_MERGE_IMAGE 8 +#define FW_RELOC_STRIPEED_IMAGE 9 + +#define DUMP_TE_HEADER 0x11 + +#define DEFAULT_MC_PAD_BYTE_VALUE 0xFF +#define DEFAULT_MC_ALIGNMENT 16 + +#ifndef _MAX_PATH +#define _MAX_PATH 500 +#endif + +#define STATUS_IGNORE 0xA +// +// Structure definition for a microcode header +// +typedef struct { + UINT32 HeaderVersion; + UINT32 PatchId; + UINT32 Date; + UINT32 CpuId; + UINT32 Checksum; + UINT32 LoaderVersion; + UINT32 PlatformId; + UINT32 DataSize; // if 0, then TotalSize = 2048, and TotalSize field is invalid + UINT32 TotalSize; // number of bytes + UINT32 Reserved[3]; +} MICROCODE_IMAGE_HEADER; + +STATIC CHAR8 *mInImageName; + +STATIC +EFI_STATUS +ZeroDebugData ( + IN OUT UINT8 *FileBuffer, + BOOLEAN ZeroDebug + ); + +STATIC +EFI_STATUS +SetStamp ( + IN OUT UINT8 *FileBuffer, + IN CHAR8 *TimeStamp + ); + +STATIC +STATUS +MicrocodeReadData ( + FILE *InFptr, + UINT32 *Data + ); + +STATIC +VOID +Version ( + VOID + ) +/*++ + +Routine Description: + + Print out version information for this utility. + +Arguments: + + None + +Returns: + + None + +--*/ +{ + fprintf (stdout, "%s Version %d.%d\n", UTILITY_NAME, UTILITY_MAJOR_VERSION, UTILITY_MINOR_VERSION); +} + +STATIC +VOID +Usage ( + VOID + ) +/*++ + +Routine Description: + + Print Help message. + +Arguments: + + VOID + +Returns: + + None + +--*/ +{ + // + // Summary usage + // + fprintf (stdout, "\nUsage: %s [options] \n\n", UTILITY_NAME); + + // + // Copyright declaration + // + fprintf (stdout, "Copyright (c) 2007, Intel Corporation. All rights reserved.\n\n"); + + // + // Details Option + // + fprintf (stdout, "Options:\n"); + fprintf (stdout, " -o FileName, --outputfile FileName\n\ + File will be created to store the ouput content.\n"); + fprintf (stdout, " -e EFI_FILETYPE, --efiImage EFI_FILETYPE\n\ + Create Efi Image. EFI_FILETYPE is one of BASE, SEC,\n\ + PEI_CORE, PEIM, DXE_CORE, DXE_DRIVER, UEFI_APPLICATION,\n\ + DXE_SAL_DRIVER, UEFI_DRIVER, DXE_RUNTIME_DRIVER, \n\ + DXE_SMM_DRIVER, SECURITY_CORE, COMBINED_PEIM_DRIVER, \n\ + PIC_PEIM, RELOCATABLE_PEIM, BS_DRIVER, RT_DRIVER,\n\ + APPLICATION, SAL_RT_DRIVER to support all module types\n\ + It can only be used together with --keepexceptiontable,\n\ + --keepzeropending, -r, -o option.It is a action option.\n\ + If it is combined with other action options, the later\n\ + input action option will override the previous one.\n"); + fprintf (stdout, " -c, --acpi Create Acpi table.\n\ + It can't be combined with other action options\n\ + except for -o, -r option. It is a action option.\n\ + If it is combined with other action options, the later\n\ + input action option will override the previous one.\n"); + fprintf (stdout, " -t, --terse Create Te Image.\n\ + It can only be used together with --keepexceptiontable,\n\ + --keepzeropending, -r, -o option.It is a action option.\n\ + If it is combined with other action options, the later\n\ + input action option will override the previous one.\n"); + fprintf (stdout, " -u, --dump Dump TeImage Header.\n\ + It can't be combined with other action options\n\ + except for -o, -r option. It is a action option.\n\ + If it is combined with other action options, the later\n\ + input action option will override the previous one.\n"); + fprintf (stdout, " -z, --zero Zero the Debug Data Fields in the PE input image file.\n\ + It also zeros the time stamp fields.\n\ + This option can be used to compare the binary efi image.\n\ + It can't be combined with other action options\n\ + except for -o, -r option. It is a action option.\n\ + If it is combined with other action options, the later\n\ + input action option will override the previous one.\n"); + fprintf (stdout, " -b, --exe2bin Convert the input EXE to the output BIN file.\n\ + It can't be combined with other action options\n\ + except for -o, -r option. It is a action option.\n\ + If it is combined with other action options, the later\n\ + input action option will override the previous one.\n");; + fprintf (stdout, " -l, --stripped Relocation info stripped from the input PE or TE image.\n\ + It can't be combined with other action options\n\ + except for -o, -r option. It is a action option.\n\ + If it is combined with other action options, the later\n\ + input action option will override the previous one.\n"); + fprintf (stdout, " -s timedate, --stamp timedate\n\ + timedate format is \"yyyy-mm-dd 00:00:00\". if timedata \n\ + is set to NOW, current system time is used. The support\n\ + date scope is 1970-1-1 8:0:0 ~ 2038-1-19 3:14:07\n\ + It can't be combined with other action options\n\ + except for -o, -r option. It is a action option.\n\ + If it is combined with other action options, the later\n\ + input action option will override the previous one.\n"); + fprintf (stdout, " -m, --mcifile Convert input microcode txt file to microcode bin file.\n\ + It can't be combined with other action options\n\ + except for -o option. It is a action option.\n\ + If it is combined with other action options, the later\n\ + input action option will override the previous one.\n"); + fprintf (stdout, " -j, --join Combine multi microcode bin files to one file.\n\ + It can be specified with -a, -p, -o option.\n\ + No other options can be combined with it.\n\ + If it is combined with other action options, the later\n\ + input action option will override the previous one.\n"); + fprintf (stdout, " -a NUM, --align NUM NUM is one HEX or DEC format alignment value.\n\ + This option is only used together with -j option.\n"); + fprintf (stdout, " -p NUM, --pad NUM NUM is one HEX or DEC format padding value.\n\ + This option is only used together with -j option.\n"); + fprintf (stdout, " --keepexceptiontable Don't clear exception table.\n\ + This option can be used together with -e or -t.\n\ + It doesn't work for other options.\n"); + fprintf (stdout, " --keepzeropending Don't strip zero pending of .reloc.\n\ + This option can be used together with -e or -t.\n\ + It doesn't work for other options.\n"); + fprintf (stdout, " -r, --replace Overwrite the input file with the output content.\n\ + If more input files are specified,\n\ + the last input file will be as the output file.\n"); + fprintf (stdout, " -v, --verbose Turn on verbose output with informational messages.\n"); + fprintf (stdout, " -q, --quiet Disable all messages except key message and fatal error\n"); + fprintf (stdout, " -d, --debug level Enable debug messages, at input debug level.\n"); + fprintf (stdout, " --version Show program's version number and exit\n"); + fprintf (stdout, " -h, --help Show this help message and exit\n"); +} + +STATIC +STATUS +CheckAcpiTable ( + VOID *AcpiTable, + UINT32 Length + ) +/*++ + +Routine Description: + + Check Acpi Table + +Arguments: + + AcpiTable Buffer for AcpiSection + Length AcpiSection Length + +Returns: + + 0 success + non-zero otherwise + +--*/ +{ + EFI_ACPI_DESCRIPTION_HEADER *AcpiHeader; + EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *Facs; + UINT32 ExpectedLength; + + AcpiHeader = (EFI_ACPI_DESCRIPTION_HEADER *)AcpiTable; + + // + // Generic check for AcpiTable length. + // + if (AcpiHeader->Length > Length) { + Error (NULL, 0, 3000, "Invalid", "AcpiTable length check failed.", NULL); + return STATUS_ERROR; + } + + // + // Currently, we only check must-have tables: FADT, FACS, DSDT, + // and some important tables: MADT, MCFG. + // + switch (AcpiHeader->Signature) { + + // + // "FACP" Fixed ACPI Description Table + // + case EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE: + switch (AcpiHeader->Revision) { + case EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION: + ExpectedLength = sizeof(EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE); + break; + case EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION: + ExpectedLength = sizeof(EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE); + break; + case EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION: + ExpectedLength = sizeof(EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE); + break; + default: + Error (NULL, 0, 3000, "Invalid", "FACP revision check failed."); + return STATUS_ERROR; + } + if (ExpectedLength != AcpiHeader->Length) { + Error (NULL, 0, 3000, "Invalid", "FACP length check failed."); + return STATUS_ERROR; + } + break; + + // + // "FACS" Firmware ACPI Control Structure + // + case EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE: + Facs = (EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *)AcpiTable; + if ((Facs->Version != 0) && + (Facs->Version != EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_VERSION) && + (Facs->Version != EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_VERSION)){ + Error (NULL, 0, 3000, "Invalid", "FACS version check failed."); + return STATUS_ERROR; + } + if ((Facs->Length != sizeof(EFI_ACPI_1_0_FIRMWARE_ACPI_CONTROL_STRUCTURE)) && + (Facs->Length != sizeof(EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE)) && + (Facs->Length != sizeof(EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE))) { + Error (NULL, 0, 3000, "Invalid", "FACS length check failed."); + return STATUS_ERROR; + } + break; + + // + // "DSDT" Differentiated System Description Table + // + case EFI_ACPI_3_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE: + if (AcpiHeader->Revision > EFI_ACPI_3_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_REVISION) { + Error (NULL, 0, 3000, "Invalid", "DSDT revision check failed."); + return STATUS_ERROR; + } + if (AcpiHeader->Length <= sizeof(EFI_ACPI_DESCRIPTION_HEADER)) { + Error (NULL, 0, 3000, "Invalid", "DSDT length check failed."); + return STATUS_ERROR; + } + break; + + // + // "APIC" Multiple APIC Description Table + // + case EFI_ACPI_3_0_MULTIPLE_APIC_DESCRIPTION_TABLE_SIGNATURE: + if ((AcpiHeader->Revision != EFI_ACPI_1_0_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION) && + (AcpiHeader->Revision != EFI_ACPI_2_0_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION) && + (AcpiHeader->Revision != EFI_ACPI_3_0_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION)) { + Error (NULL, 0, 3000, "Invalid", "APIC revision check failed."); + return STATUS_ERROR; + } + if (AcpiHeader->Length <= sizeof(EFI_ACPI_DESCRIPTION_HEADER) + sizeof(UINT32) + sizeof(UINT32)) { + Error (NULL, 0, 3000, "Invalid", "APIC length check failed."); + return STATUS_ERROR; + } + break; + + // + // "MCFG" PCI Express Memory Mapped Configuration Space Base Address Description Table + // + case EFI_ACPI_3_0_PCI_EXPRESS_MEMORY_MAPPED_CONFIGURATION_SPACE_BASE_ADDRESS_DESCRIPTION_TABLE_SIGNATURE: + if (AcpiHeader->Revision != EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_SPACE_ACCESS_TABLE_REVISION) { + Error (NULL, 0, 3000, "Invalid", "MCFG revision check failed."); + return STATUS_ERROR; + } + if (AcpiHeader->Length <= sizeof(EFI_ACPI_DESCRIPTION_HEADER) + sizeof(UINT64)) { + Error (NULL, 0, 3000, "Invalid", "MCFG length check failed."); + return STATUS_ERROR; + } + break; + + // + // Other table pass check + // + default: + break; + } + + return STATUS_SUCCESS; +} + + +INTN +IsElfHeader( + UINT8 *FileBuffer +) +{ + return (FileBuffer[EI_MAG0] == ELFMAG0 + && FileBuffer[EI_MAG1] == ELFMAG1 + && FileBuffer[EI_MAG2] == ELFMAG2 + && FileBuffer[EI_MAG3] == ELFMAG3); +} + +typedef Elf32_Shdr Elf_Shdr; +typedef Elf32_Ehdr Elf_Ehdr; +typedef Elf32_Rel Elf_Rel; +typedef Elf32_Sym Elf_Sym; +typedef Elf32_Phdr Elf_Phdr; +typedef Elf32_Dyn Elf_Dyn; + +#define ELFCLASS ELFCLASS32 +#define ELF_R_TYPE(r) ELF32_R_TYPE(r) +#define ELF_R_SYM(r) ELF32_R_SYM(r) + +// +// Well known ELF structures. +// +Elf_Ehdr *Ehdr; +Elf_Shdr *ShdrBase; +Elf_Phdr *gPhdrBase; + +// +// PE section alignment. +// +const UINT32 CoffAlignment = 0x20; +const UINT32 CoffNbrSections = 4; + +// +// Current offset in coff file. +// +UINT32 CoffOffset; + +// +// Result Coff file in memory. +// +UINT8 *CoffFile = NULL; +// +// ELF sections to offset in Coff file. +// +UINT32 *CoffSectionsOffset = NULL; + +// +// Offset in Coff file of headers and sections. +// +UINT32 NtHdrOffset; +UINT32 TableOffset; +UINT32 TextOffset; +UINT32 DataOffset; +UINT32 RelocOffset; + +EFI_IMAGE_BASE_RELOCATION *CoffBaseRel; +UINT16 *CoffEntryRel; + +UINT32 +CoffAlign( + UINT32 Offset + ) +{ + return (Offset + CoffAlignment - 1) & ~(CoffAlignment - 1); +} + +Elf_Shdr * +GetShdrByIndex( + UINT32 Num + ) +{ + if (Num >= Ehdr->e_shnum) + return NULL; + return (Elf_Shdr*)((UINT8*)ShdrBase + Num * Ehdr->e_shentsize); +} + +INTN +CheckElfHeader( + VOID + ) +{ + // + // Note: Magic has already been tested. + // + if (Ehdr->e_ident[EI_CLASS] != ELFCLASS) { + Error (NULL, 0, 3000, "Unsupported", "%s needs to be ported for 64-bit ELF.", mInImageName); + return 0; + } + if (Ehdr->e_ident[EI_DATA] != ELFDATA2LSB) { + Error (NULL, 0, 3000, "Unsupported", "ELF EI_DATA not ELFDATA2LSB"); + return 0; + } + if ((Ehdr->e_type != ET_EXEC) && (Ehdr->e_type != ET_DYN)) { + Error (NULL, 0, 3000, "Unsupported", "ELF e_type not ET_EXEC or ET_DYN"); + return 0; + } + if (!((Ehdr->e_machine == EM_386) || (Ehdr->e_machine == EM_ARM))) { + Error (NULL, 0, 3000, "Unsupported", "ELF e_machine not EM_386 or EM_ARM"); + return 0; + } + if (Ehdr->e_version != EV_CURRENT) { + Error (NULL, 0, 3000, "Unsupported", "ELF e_version (%d) not EV_CURRENT (%d)", Ehdr->e_version, EV_CURRENT); + return 0; + } + + // + // Find the section header table + // + ShdrBase = (Elf_Shdr *)((UINT8 *)Ehdr + Ehdr->e_shoff); + gPhdrBase = (Elf_Phdr *)((UINT8 *)Ehdr + Ehdr->e_phoff); + + CoffSectionsOffset = (UINT32 *)malloc(Ehdr->e_shnum * sizeof (UINT32)); + + memset(CoffSectionsOffset, 0, Ehdr->e_shnum * sizeof(UINT32)); + return 1; +} + +int +IsTextShdr( + Elf_Shdr *Shdr + ) +{ + return (Shdr->sh_flags & (SHF_WRITE | SHF_ALLOC)) == SHF_ALLOC; +} + +int +IsDataShdr( + Elf_Shdr *Shdr + ) +{ + return (Shdr->sh_flags & (SHF_WRITE | SHF_ALLOC)) == (SHF_ALLOC | SHF_WRITE); +} + +VOID +CreateSectionHeader( + const CHAR8 *Name, + UINT32 Offset, + UINT32 Size, + UINT32 Flags + ) +{ + EFI_IMAGE_SECTION_HEADER *Hdr; + Hdr = (EFI_IMAGE_SECTION_HEADER*)(CoffFile + TableOffset); + + strcpy((char *)Hdr->Name, Name); + Hdr->Misc.VirtualSize = Size; + Hdr->VirtualAddress = Offset; + Hdr->SizeOfRawData = Size; + Hdr->PointerToRawData = Offset; + Hdr->PointerToRelocations = 0; + Hdr->PointerToLinenumbers = 0; + Hdr->NumberOfRelocations = 0; + Hdr->NumberOfLinenumbers = 0; + Hdr->Characteristics = Flags; + + TableOffset += sizeof (EFI_IMAGE_SECTION_HEADER); +} + +VOID +ScanSections( + VOID + ) +{ + UINT32 i; + EFI_IMAGE_DOS_HEADER *DosHdr; + EFI_IMAGE_OPTIONAL_HEADER_UNION *NtHdr; + UINT32 CoffEntry; + + CoffEntry = 0; + CoffOffset = 0; + + // + // Coff file start with a DOS header. + // + CoffOffset = sizeof(EFI_IMAGE_DOS_HEADER) + 0x40; + NtHdrOffset = CoffOffset; + CoffOffset += sizeof(EFI_IMAGE_OPTIONAL_HEADER_UNION); + TableOffset = CoffOffset; + CoffOffset += CoffNbrSections * sizeof(EFI_IMAGE_SECTION_HEADER); + + // + // First text sections. + // + CoffOffset = CoffAlign(CoffOffset); + TextOffset = CoffOffset; + for (i = 0; i < Ehdr->e_shnum; i++) { + Elf_Shdr *shdr = GetShdrByIndex(i); + if (IsTextShdr(shdr)) { + if ((shdr->sh_addralign != 0) && (shdr->sh_addralign != 1)) { + // the alignment field is valid + if ((shdr->sh_addr & (shdr->sh_addralign - 1)) == 0) { + // if the section address is aligned we must align PE/COFF + CoffOffset = (CoffOffset + shdr->sh_addralign - 1) & ~(shdr->sh_addralign - 1); + } else if ((shdr->sh_addr % shdr->sh_addralign) != (CoffOffset % shdr->sh_addralign)) { + // ARM RVCT tools have behavior outside of the ELF specification to try + // and make images smaller. If sh_addr is not aligned to sh_addralign + // then the section needs to preserve sh_addr MOD sh_addralign. + // Normally doing nothing here works great. + Error (NULL, 0, 3000, "Invalid", "Unsupported section alignment."); + } + } + + /* Relocate entry. */ + if ((Ehdr->e_entry >= shdr->sh_addr) && + (Ehdr->e_entry < shdr->sh_addr + shdr->sh_size)) { + CoffEntry = CoffOffset + Ehdr->e_entry - shdr->sh_addr; + } + CoffSectionsOffset[i] = CoffOffset; + CoffOffset += shdr->sh_size; + } + } + + if (Ehdr->e_machine != EM_ARM) { + CoffOffset = CoffAlign(CoffOffset); + } + + // + // Then data sections. + // + DataOffset = CoffOffset; + for (i = 0; i < Ehdr->e_shnum; i++) { + Elf_Shdr *shdr = GetShdrByIndex(i); + if (IsDataShdr(shdr)) { + if ((shdr->sh_addralign != 0) && (shdr->sh_addralign != 1)) { + // the alignment field is valid + if ((shdr->sh_addr & (shdr->sh_addralign - 1)) == 0) { + // if the section address is aligned we must align PE/COFF + CoffOffset = (CoffOffset + shdr->sh_addralign - 1) & ~(shdr->sh_addralign - 1); + } else if ((shdr->sh_addr % shdr->sh_addralign) != (CoffOffset % shdr->sh_addralign)) { + // ARM RVCT tools have behavior outside of the ELF specification to try + // and make images smaller. If sh_addr is not aligned to sh_addralign + // then the section needs to preserve sh_addr MOD sh_addralign. + // Normally doing nothing here works great. + Error (NULL, 0, 3000, "Invalid", "Unsupported section alignment."); + } + } + + CoffSectionsOffset[i] = CoffOffset; + CoffOffset += shdr->sh_size; + } + } + CoffOffset = CoffAlign(CoffOffset); + + RelocOffset = CoffOffset; + + // + // Allocate base Coff file. Will be expanded later for relocations. + // + CoffFile = (UINT8 *)malloc(CoffOffset); + memset(CoffFile, 0, CoffOffset); + + // + // Fill headers. + // + DosHdr = (EFI_IMAGE_DOS_HEADER *)CoffFile; + DosHdr->e_magic = EFI_IMAGE_DOS_SIGNATURE; + DosHdr->e_lfanew = NtHdrOffset; + + NtHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION*)(CoffFile + NtHdrOffset); + + NtHdr->Pe32.Signature = EFI_IMAGE_NT_SIGNATURE; + + switch (Ehdr->e_machine) { + case EM_386: + NtHdr->Pe32.FileHeader.Machine = EFI_IMAGE_MACHINE_IA32; + NtHdr->Pe32.OptionalHeader.Magic = EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC; + break; + case EM_X86_64: + NtHdr->Pe32.FileHeader.Machine = EFI_IMAGE_MACHINE_X64; + NtHdr->Pe32.OptionalHeader.Magic = EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC; + break; + case EM_IA_64: + NtHdr->Pe32.FileHeader.Machine = EFI_IMAGE_MACHINE_IPF; + NtHdr->Pe32.OptionalHeader.Magic = EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC; + break; + case EM_ARM: + NtHdr->Pe32.FileHeader.Machine = EFI_IMAGE_MACHINE_ARMT; + NtHdr->Pe32.OptionalHeader.Magic = EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC; + break; + default: + VerboseMsg ("%s unknown e_machine type. Assume IA-32", (UINTN)Ehdr->e_machine); + NtHdr->Pe32.FileHeader.Machine = EFI_IMAGE_MACHINE_IA32; + NtHdr->Pe32.OptionalHeader.Magic = EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC; + } + + NtHdr->Pe32.FileHeader.NumberOfSections = CoffNbrSections; + NtHdr->Pe32.FileHeader.TimeDateStamp = time(NULL); + NtHdr->Pe32.FileHeader.PointerToSymbolTable = 0; + NtHdr->Pe32.FileHeader.NumberOfSymbols = 0; + NtHdr->Pe32.FileHeader.SizeOfOptionalHeader = sizeof(NtHdr->Pe32.OptionalHeader); + NtHdr->Pe32.FileHeader.Characteristics = EFI_IMAGE_FILE_EXECUTABLE_IMAGE + | EFI_IMAGE_FILE_LINE_NUMS_STRIPPED + | EFI_IMAGE_FILE_LOCAL_SYMS_STRIPPED + | EFI_IMAGE_FILE_32BIT_MACHINE; + + NtHdr->Pe32.OptionalHeader.SizeOfCode = DataOffset - TextOffset; + NtHdr->Pe32.OptionalHeader.SizeOfInitializedData = RelocOffset - DataOffset; + NtHdr->Pe32.OptionalHeader.SizeOfUninitializedData = 0; + NtHdr->Pe32.OptionalHeader.AddressOfEntryPoint = CoffEntry; + + NtHdr->Pe32.OptionalHeader.BaseOfCode = TextOffset; + + NtHdr->Pe32.OptionalHeader.BaseOfData = DataOffset; + NtHdr->Pe32.OptionalHeader.ImageBase = 0; + NtHdr->Pe32.OptionalHeader.SectionAlignment = CoffAlignment; + NtHdr->Pe32.OptionalHeader.FileAlignment = CoffAlignment; + NtHdr->Pe32.OptionalHeader.SizeOfImage = 0; + + NtHdr->Pe32.OptionalHeader.SizeOfHeaders = TextOffset; + NtHdr->Pe32.OptionalHeader.NumberOfRvaAndSizes = EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES; + + // + // Section headers. + // + if ((DataOffset - TextOffset) > 0) { + CreateSectionHeader (".text", TextOffset, DataOffset - TextOffset, + EFI_IMAGE_SCN_CNT_CODE + | EFI_IMAGE_SCN_MEM_EXECUTE + | EFI_IMAGE_SCN_MEM_READ); + } else { + // Don't make a section of size 0. + NtHdr->Pe32.FileHeader.NumberOfSections--; + } + + if ((RelocOffset - TextOffset) > 0) { + CreateSectionHeader (".data", DataOffset, RelocOffset - DataOffset, + EFI_IMAGE_SCN_CNT_INITIALIZED_DATA + | EFI_IMAGE_SCN_MEM_WRITE + | EFI_IMAGE_SCN_MEM_READ); + } else { + // Don't make a section of size 0. + NtHdr->Pe32.FileHeader.NumberOfSections--; + } +} + +VOID +WriteSections( + int (*Filter)(Elf_Shdr *) + ) +{ + UINT32 Idx; + Elf_Shdr *SecShdr; + UINT32 SecOffset; + + // + // First: copy sections. + // + for (Idx = 0; Idx < Ehdr->e_shnum; Idx++) { + Elf_Shdr *Shdr = GetShdrByIndex(Idx); + if ((*Filter)(Shdr)) { + switch (Shdr->sh_type) { + case SHT_PROGBITS: + /* Copy. */ + memcpy(CoffFile + CoffSectionsOffset[Idx], + (UINT8*)Ehdr + Shdr->sh_offset, + Shdr->sh_size); + break; + + case SHT_NOBITS: + memset(CoffFile + CoffSectionsOffset[Idx], 0, Shdr->sh_size); + break; + + default: + // + // Ignore for unkown section type. + // + VerboseMsg ("%s unknown section type %x. We directly copy this section into Coff file", mInImageName, (UINTN)Shdr->sh_type); + break; + } + } + } + + // + // Second: apply relocations. + // + for (Idx = 0; Idx < Ehdr->e_shnum; Idx++) { + Elf_Shdr *RelShdr = GetShdrByIndex(Idx); + if (RelShdr->sh_type != SHT_REL) + continue; + SecShdr = GetShdrByIndex(RelShdr->sh_info); + SecOffset = CoffSectionsOffset[RelShdr->sh_info]; + if (RelShdr->sh_type == SHT_REL && (*Filter)(SecShdr)) { + UINT32 RelIdx; + Elf_Shdr *SymtabShdr = GetShdrByIndex(RelShdr->sh_link); + UINT8 *Symtab = (UINT8*)Ehdr + SymtabShdr->sh_offset; + + for (RelIdx = 0; RelIdx < RelShdr->sh_size; RelIdx += RelShdr->sh_entsize) { + Elf_Rel *Rel = (Elf_Rel *)((UINT8*)Ehdr + RelShdr->sh_offset + RelIdx); + Elf_Sym *Sym = (Elf_Sym *)(Symtab + ELF_R_SYM(Rel->r_info) * SymtabShdr->sh_entsize); + Elf_Shdr *SymShdr; + UINT8 *Targ; + + if (Sym->st_shndx == SHN_UNDEF + || Sym->st_shndx == SHN_ABS + || Sym->st_shndx > Ehdr->e_shnum) { + Error (NULL, 0, 3000, "Invalid", "%s bad symbol definition.", mInImageName); + } + SymShdr = GetShdrByIndex(Sym->st_shndx); + + // + // Note: r_offset in a memory address. + // Convert it to a pointer in the coff file. + // + Targ = CoffFile + SecOffset + (Rel->r_offset - SecShdr->sh_addr); + + if (Ehdr->e_machine == EM_386) { + switch (ELF_R_TYPE(Rel->r_info)) { + case R_386_NONE: + break; + case R_386_32: + // + // Absolute relocation. + // + *(UINT32 *)Targ = *(UINT32 *)Targ - SymShdr->sh_addr + + CoffSectionsOffset[Sym->st_shndx]; + break; + case R_386_PC32: + // + // Relative relocation: Symbol - Ip + Addend + // + *(UINT32 *)Targ = *(UINT32 *)Targ + + (CoffSectionsOffset[Sym->st_shndx] - SymShdr->sh_addr) + - (SecOffset - SecShdr->sh_addr); + break; + default: + Error (NULL, 0, 3000, "Invalid", "%s unhandled section type %x.", mInImageName, ELF_R_TYPE(Rel->r_info)); + } + } else if (Ehdr->e_machine == EM_ARM) { + switch (ELF32_R_TYPE(Rel->r_info)) { + case R_ARM_RBASE: // No relocation - no action required + case R_ARM_PC24: // PC-relative relocations don't require modification + case R_ARM_XPC25: // PC-relative relocations don't require modification + break; + case R_ARM_ABS32: + case R_ARM_RABS32: + // + // Absolute relocation. + // + *(UINT32 *)Targ = *(UINT32 *)Targ - SymShdr->sh_addr + CoffSectionsOffset[Sym->st_shndx]; + break; + default: + Error (NULL, 0, 3000, "Invalid", "%s unhandled section type %x.", mInImageName, ELF32_R_TYPE(Rel->r_info)); + } + } + } + } + } +} + +VOID +CoffAddFixupEntry( + UINT16 Val + ) +{ + *CoffEntryRel = Val; + CoffEntryRel++; + CoffBaseRel->SizeOfBlock += 2; + CoffOffset += 2; +} + +VOID +CoffAddFixup( + UINT32 Offset, + UINT8 Type + ) +{ + if (CoffBaseRel == NULL + || CoffBaseRel->VirtualAddress != (Offset & ~0xfff)) { + if (CoffBaseRel != NULL) { + // + // Add a null entry (is it required ?) + // + CoffAddFixupEntry (0); + // + // Pad for alignment. + // + if (CoffOffset % 4 != 0) + CoffAddFixupEntry (0); + } + + CoffFile = realloc + (CoffFile, + CoffOffset + sizeof(EFI_IMAGE_BASE_RELOCATION) + 2*0x1000); + memset(CoffFile + CoffOffset, 0, + sizeof(EFI_IMAGE_BASE_RELOCATION) + 2*0x1000); + + CoffBaseRel = (EFI_IMAGE_BASE_RELOCATION*)(CoffFile + CoffOffset); + CoffBaseRel->VirtualAddress = Offset & ~0xfff; + CoffBaseRel->SizeOfBlock = sizeof(EFI_IMAGE_BASE_RELOCATION); + + CoffEntryRel = (UINT16 *)(CoffBaseRel + 1); + CoffOffset += sizeof(EFI_IMAGE_BASE_RELOCATION); + } + + // + // Fill the entry. + // + CoffAddFixupEntry((Type << 12) | (Offset & 0xfff)); +} + + +Elf_Phdr * +GetPhdrByIndex ( + UINT32 num + ) +{ + if (num >= Ehdr->e_phnum) { + return NULL; + } + + return (Elf32_Phdr *)((UINT8*)gPhdrBase + num * Ehdr->e_phentsize); +} + + +VOID +WriteRelocations( + VOID + ) +{ + UINT32 Index; + EFI_IMAGE_OPTIONAL_HEADER_UNION *NtHdr; + EFI_IMAGE_DATA_DIRECTORY *Dir; + BOOLEAN FoundRelocations; + Elf_Dyn *Dyn; + Elf_Rel *Rel; + UINTN RelElementSize; + UINTN RelSize; + UINTN RelOffset; + UINTN K; + UINT8 *Targ; + Elf32_Phdr *DynamicSegment; + Elf32_Phdr *TargetSegment; + + for (Index = 0, FoundRelocations = FALSE; Index < Ehdr->e_shnum; Index++) { + Elf_Shdr *RelShdr = GetShdrByIndex(Index); + if (RelShdr->sh_type == SHT_REL) { + Elf_Shdr *SecShdr = GetShdrByIndex(RelShdr->sh_info); + if (IsTextShdr(SecShdr) || IsDataShdr(SecShdr)) { + UINT32 RelIdx; + FoundRelocations = TRUE; + for (RelIdx = 0; RelIdx < RelShdr->sh_size; RelIdx += RelShdr->sh_entsize) { + Elf_Rel *Rel = (Elf_Rel *) + ((UINT8*)Ehdr + RelShdr->sh_offset + RelIdx); + + if (Ehdr->e_machine == EM_386) { + switch (ELF_R_TYPE(Rel->r_info)) { + case R_386_NONE: + case R_386_PC32: + break; + case R_386_32: + CoffAddFixup(CoffSectionsOffset[RelShdr->sh_info] + + (Rel->r_offset - SecShdr->sh_addr), + EFI_IMAGE_REL_BASED_HIGHLOW); + break; + default: + Error (NULL, 0, 3000, "Invalid", "%s unhandled section type %x.", mInImageName, ELF_R_TYPE(Rel->r_info)); + } + } else if (Ehdr->e_machine == EM_ARM) { + switch (ELF32_R_TYPE(Rel->r_info)) { + case R_ARM_RBASE: + case R_ARM_PC24: + case R_ARM_XPC25: + break; + case R_ARM_ABS32: + case R_ARM_RABS32: + CoffAddFixup ( + CoffSectionsOffset[RelShdr->sh_info] + + (Rel->r_offset - SecShdr->sh_addr), + EFI_IMAGE_REL_BASED_HIGHLOW + ); + break; + default: + Error (NULL, 0, 3000, "Invalid", "%s unhandled section type %x.", mInImageName, ELF32_R_TYPE(Rel->r_info)); + } + } else { + Error (NULL, 0, 3000, "Not Supported", "This tool does not support relocations for ELF with e_machine %d (processor type).", Ehdr->e_machine); + } + } + } + } + } + + if (!FoundRelocations && (Ehdr->e_machine == EM_ARM)) { + /* Try again, but look for PT_DYNAMIC instead of SHT_REL */ + + for (Index = 0; Index < Ehdr->e_phnum; Index++) { + RelElementSize = 0; + RelSize = 0; + RelOffset = 0; + + DynamicSegment = GetPhdrByIndex (Index); + + if (DynamicSegment->p_type == PT_DYNAMIC) { + Dyn = (Elf32_Dyn *) ((UINT8 *)Ehdr + DynamicSegment->p_offset); + + while (Dyn->d_tag != DT_NULL) { + switch (Dyn->d_tag) { + case DT_REL: + RelOffset = Dyn->d_un.d_val; + break; + + case DT_RELSZ: + RelSize = Dyn->d_un.d_val; + break; + + case DT_RELENT: + RelElementSize = Dyn->d_un.d_val; + break; + } + Dyn++; + } + if (( RelOffset == 0 ) || ( RelSize == 0 ) || ( RelElementSize == 0 )) { + Error (NULL, 0, 3000, "Invalid", "%s bad ARM dynamic relocations.", mInImageName); + } + + for (K = 0; K < RelSize; K += RelElementSize) { + + Rel = (Elf32_Rel *) ((UINT8 *) Ehdr + DynamicSegment->p_offset + RelOffset + K); + + switch (ELF32_R_TYPE (Rel->r_info)) { + case R_ARM_RBASE: + break; + case R_ARM_RABS32: + TargetSegment = GetPhdrByIndex (ELF32_R_SYM (Rel->r_info) - 1); + + // Note: r_offset in a memory address. Convert it to a pointer in the coff file. + Targ = CoffFile + CoffSectionsOffset[ ELF32_R_SYM( Rel->r_info ) ] + Rel->r_offset - TargetSegment->p_vaddr; + + *(UINT32 *)Targ = *(UINT32 *)Targ + CoffSectionsOffset [ELF32_R_SYM( Rel->r_info )]; + + CoffAddFixup (CoffSectionsOffset[ELF32_R_SYM (Rel->r_info)] + (Rel->r_offset - TargetSegment->p_vaddr), EFI_IMAGE_REL_BASED_HIGHLOW); + break; + default: + Error (NULL, 0, 3000, "Invalid", "%s bad ARM dynamic relocations, unkown type.", mInImageName); + } + } + break; + } + } + } + + // + // Pad by adding empty entries. + // + while (CoffOffset & (CoffAlignment - 1)) { + CoffAddFixupEntry(0); + } + + + NtHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(CoffFile + NtHdrOffset); + Dir = &NtHdr->Pe32.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC]; + Dir->Size = CoffOffset - RelocOffset; + if (Dir->Size == 0) { + // If no relocations, null out the directory entry and don't add the .reloc section + Dir->VirtualAddress = 0; + NtHdr->Pe32.FileHeader.NumberOfSections--; + } else { + Dir->VirtualAddress = RelocOffset; + CreateSectionHeader (".reloc", RelocOffset, CoffOffset - RelocOffset, + EFI_IMAGE_SCN_CNT_INITIALIZED_DATA + | EFI_IMAGE_SCN_MEM_DISCARDABLE + | EFI_IMAGE_SCN_MEM_READ); + } + +} + +VOID +WriteDebug( + VOID + ) +{ + UINT32 Len; + UINT32 DebugOffset; + EFI_IMAGE_OPTIONAL_HEADER_UNION *NtHdr; + EFI_IMAGE_DATA_DIRECTORY *DataDir; + EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *Dir; + EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY *Nb10; + + Len = strlen(mInImageName) + 1; + DebugOffset = CoffOffset; + + CoffOffset += sizeof(EFI_IMAGE_DEBUG_DIRECTORY_ENTRY) + + sizeof(EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY) + + Len; + CoffOffset = CoffAlign(CoffOffset); + + CoffFile = realloc(CoffFile, CoffOffset); + memset(CoffFile + DebugOffset, 0, CoffOffset - DebugOffset); + + Dir = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY*)(CoffFile + DebugOffset); + Dir->Type = EFI_IMAGE_DEBUG_TYPE_CODEVIEW; + Dir->SizeOfData = sizeof(EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY) + Len; + Dir->RVA = DebugOffset + sizeof(EFI_IMAGE_DEBUG_DIRECTORY_ENTRY); + Dir->FileOffset = DebugOffset + sizeof(EFI_IMAGE_DEBUG_DIRECTORY_ENTRY); + + Nb10 = (EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY*)(Dir + 1); + Nb10->Signature = CODEVIEW_SIGNATURE_NB10; + strcpy ((char *)(Nb10 + 1), mInImageName); + + + NtHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(CoffFile + NtHdrOffset); + DataDir = &NtHdr->Pe32.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG]; + DataDir->VirtualAddress = DebugOffset; + DataDir->Size = CoffOffset - DebugOffset; + if (DataDir->Size == 0) { + // If no debug, null out the directory entry and don't add the .debug section + DataDir->VirtualAddress = 0; + NtHdr->Pe32.FileHeader.NumberOfSections--; + } else { + DataDir->VirtualAddress = DebugOffset; + CreateSectionHeader (".debug", DebugOffset, CoffOffset - DebugOffset, + EFI_IMAGE_SCN_CNT_INITIALIZED_DATA + | EFI_IMAGE_SCN_MEM_DISCARDABLE + | EFI_IMAGE_SCN_MEM_READ); + + } +} + +VOID +ConvertElf ( + UINT8 **FileBuffer, + UINT32 *FileLength + ) +{ + EFI_IMAGE_OPTIONAL_HEADER_UNION *NtHdr; + + // + // Check header, read section table. + // + Ehdr = (Elf32_Ehdr*)*FileBuffer; + if (!CheckElfHeader()) + return; + + VerboseMsg ("Check Efl Image Header"); + // + // Compute sections new address. + // + ScanSections(); + + VerboseMsg ("Compute sections new address."); + + // + // Write and relocate sections. + // + WriteSections(IsTextShdr); + WriteSections(IsDataShdr); + VerboseMsg ("Write and relocate sections."); + + // + // Translate and write relocations. + // + WriteRelocations(); + VerboseMsg ("Translate and write relocations."); + + // + // Write debug info. + // + WriteDebug(); + VerboseMsg ("Write debug info."); + + NtHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(CoffFile + NtHdrOffset); + NtHdr->Pe32.OptionalHeader.SizeOfImage = CoffOffset; + + // + // Replace. + // + free(*FileBuffer); + *FileBuffer = CoffFile; + *FileLength = CoffOffset; + + // + // Free memory space + // + if (CoffSectionsOffset != NULL) { + free (CoffSectionsOffset); + } +} + +void +ZeroXdataSection ( + IN CHAR8 *ImageName, + IN OUT UINT8 *FileBuffer, + IN EFI_IMAGE_SECTION_HEADER *SectionHeader, + IN UINT32 SectionTotalNumber + ) +{ + FILE *fpMapFile; + CHAR8 MapFileName[_MAX_PATH]; + CHAR8 Line [MAX_LINE_LEN]; + CHAR8 KeyWord [MAX_LINE_LEN]; + CHAR8 SectionName [MAX_LINE_LEN]; + UINT32 FunctionType = 0; + UINT32 SectionOffset; + UINT32 SectionLength; + UINT32 SectionNumber; + CHAR8 *PdbPointer; + INT32 Index = 0; + + for (Index = 0; Index < SectionTotalNumber; Index ++) { + if (stricmp ((char *)SectionHeader[Index].Name, ".zdata") == 0) { + // + // try to zero the customized .zdata section, which is mapped to .xdata + // + memset (FileBuffer + SectionHeader[Index].PointerToRawData, 0, SectionHeader[Index].SizeOfRawData); + DebugMsg (NULL, 0, 9, NULL, "Zero the .xdata section for PE image at Offset 0x%x and Length 0x%x", SectionHeader[Index].PointerToRawData, SectionHeader[Index].SizeOfRawData); + return; + } + } + // + // Try to get PDB file name + // + PdbPointer = (CHAR8 *) PeCoffLoaderGetPdbPointer (FileBuffer); + if (PdbPointer != NULL) { + strcpy (MapFileName, PdbPointer); + } else { + strcpy (MapFileName, ImageName); + } + + // + // Construct map file name + // + Index = strlen (MapFileName) - 1; + while (Index >= 0 && MapFileName[Index] != '.') { + Index --; + } + if (Index < 0) { + // + // don't know how to costruct map file + // + return; + } + + // + // fill map file postfix + // + MapFileName[Index + 1] = 'm'; + MapFileName[Index + 2] = 'a'; + MapFileName[Index + 3] = 'p'; + MapFileName[Index + 4] = '\0'; + + // + // try opening Map File + // + fpMapFile = fopen (MapFileName, "r"); + if (fpMapFile == NULL) { + // + // Can't open Map file. Maybe it doesn't exist. + // + return; + } + + // + // Output Functions information into Fv Map file + // + while (fgets (Line, MAX_LINE_LEN, fpMapFile) != NULL) { + // + // Skip blank line + // + if (Line[0] == 0x0a) { + if (FunctionType != 0) { + // + // read all section table data + // + FunctionType = 0; + break; + } + FunctionType = 0; + continue; + } + + // + // By Start keyword + // + if (FunctionType == 0) { + sscanf (Line, "%s", KeyWord); + if (stricmp (KeyWord, "Start") == 0) { + // + // function list + // + FunctionType = 1; + } + continue; + } + // + // Printf Function Information + // + if (FunctionType == 1) { + sscanf (Line, "%x:%x %xH %s", &SectionNumber, &SectionOffset, &SectionLength, SectionName); + if (stricmp (SectionName, ".xdata") == 0) { + FunctionType = 2; + break; + } + } + } + + if (FunctionType != 2) { + // + // no .xdata section is found + // + fclose (fpMapFile); + return; + } + + // + // Zero .xdata Section data + // + memset (FileBuffer + SectionHeader[SectionNumber-1].PointerToRawData + SectionOffset, 0, SectionLength); + DebugMsg (NULL, 0, 9, NULL, "Zero the .xdata section for PE image at Offset 0x%x and Length 0x%x", SectionHeader[SectionNumber-1].PointerToRawData + SectionOffset, SectionLength); + fclose (fpMapFile); + return; +} + +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. + +--*/ +{ + UINT32 Type; + UINT32 InputFileNum; + CHAR8 **InputFileName; + char *OutImageName; + char *ModuleType; + CHAR8 *TimeStamp; + UINT32 OutImageType; + FILE *fpIn; + FILE *fpOut; + FILE *fpInOut; + UINT32 Data; + UINT32 *DataPointer; + UINT32 *OldDataPointer; + UINT32 CheckSum; + UINT32 Index; + UINT32 Index1; + UINT32 Index2; + UINT64 Temp64; + UINT32 MciAlignment; + UINT8 MciPadValue; + UINT32 AllignedRelocSize; + UINT8 *FileBuffer; + UINT32 FileLength; + UINT8 *OutputFileBuffer; + UINT32 OutputFileLength; + RUNTIME_FUNCTION *RuntimeFunction; + UNWIND_INFO *UnwindInfo; + STATUS Status; + BOOLEAN ReplaceFlag; + BOOLEAN KeepExceptionTableFlag; + BOOLEAN KeepZeroPendingFlag; + UINT64 LogLevel; + EFI_TE_IMAGE_HEADER TEImageHeader; + EFI_TE_IMAGE_HEADER *TeHdr; + EFI_IMAGE_SECTION_HEADER *SectionHeader; + EFI_IMAGE_DOS_HEADER *DosHdr; + EFI_IMAGE_OPTIONAL_HEADER_UNION *PeHdr; + EFI_IMAGE_OPTIONAL_HEADER32 *Optional32; + EFI_IMAGE_OPTIONAL_HEADER64 *Optional64; + EFI_IMAGE_DOS_HEADER BackupDosHdr; + MICROCODE_IMAGE_HEADER *MciHeader; + + SetUtilityName (UTILITY_NAME); + + // + // Assign to fix compile warning + // + InputFileNum = 0; + InputFileName = NULL; + mInImageName = NULL; + OutImageName = NULL; + ModuleType = NULL; + OutImageType = FW_DUMMY_IMAGE; + Type = 0; + Status = STATUS_SUCCESS; + FileBuffer = NULL; + fpIn = NULL; + fpOut = NULL; + fpInOut = NULL; + TimeStamp = NULL; + MciAlignment = DEFAULT_MC_ALIGNMENT; + MciPadValue = DEFAULT_MC_PAD_BYTE_VALUE; + FileLength = 0; + MciHeader = NULL; + CheckSum = 0; + ReplaceFlag = FALSE; + LogLevel = 0; + OutputFileBuffer = NULL; + OutputFileLength = 0; + Optional32 = NULL; + Optional64 = NULL; + KeepExceptionTableFlag = FALSE; + KeepZeroPendingFlag = FALSE; + + if (argc == 1) { + Error (NULL, 0, 1001, "Missing options", "No input options."); + Usage (); + return STATUS_ERROR; + } + + argc --; + argv ++; + + if ((stricmp (argv[0], "-h") == 0) || (stricmp (argv[0], "--help") == 0)) { + Version (); + Usage (); + return STATUS_SUCCESS; + } + + if (stricmp (argv[0], "--version") == 0) { + Version (); + return STATUS_SUCCESS; + } + + while (argc > 0) { + if ((stricmp (argv[0], "-o") == 0) || (stricmp (argv[0], "--outputfile") == 0)) { + if (argv[1] == NULL || argv[1][0] == '-') { + Error (NULL, 0, 1003, "Invalid option value", "Output file name is missing for -o option"); + goto Finish; + } + OutImageName = argv[1]; + argc -= 2; + argv += 2; + continue; + } + + if ((stricmp (argv[0], "-e") == 0) || (stricmp (argv[0], "--efiImage") == 0)) { + if (argv[1] == NULL || argv[1][0] == '-') { + Error (NULL, 0, 1003, "Invalid option value", "Module Type is missing for -o option"); + goto Finish; + } + ModuleType = argv[1]; + if (OutImageType != FW_TE_IMAGE) { + OutImageType = FW_EFI_IMAGE; + } + argc -= 2; + argv += 2; + continue; + } + + if ((stricmp (argv[0], "-l") == 0) || (stricmp (argv[0], "--stripped") == 0)) { + OutImageType = FW_RELOC_STRIPEED_IMAGE; + argc --; + argv ++; + continue; + } + + if ((stricmp (argv[0], "-c") == 0) || (stricmp (argv[0], "--acpi") == 0)) { + OutImageType = FW_ACPI_IMAGE; + argc --; + argv ++; + continue; + } + + if ((stricmp (argv[0], "-t") == 0) || (stricmp (argv[0], "--terse") == 0)) { + OutImageType = FW_TE_IMAGE; + argc --; + argv ++; + continue; + } + + if ((stricmp (argv[0], "-u") == 0) || (stricmp (argv[0], "--dump") == 0)) { + OutImageType = DUMP_TE_HEADER; + argc --; + argv ++; + continue; + } + + if ((stricmp (argv[0], "-b") == 0) || (stricmp (argv[0], "--exe2bin") == 0)) { + OutImageType = FW_BIN_IMAGE; + argc --; + argv ++; + continue; + } + + if ((stricmp (argv[0], "-z") == 0) || (stricmp (argv[0], "--zero") == 0)) { + OutImageType = FW_ZERO_DEBUG_IMAGE; + argc --; + argv ++; + continue; + } + + if ((stricmp (argv[0], "-s") == 0) || (stricmp (argv[0], "--stamp") == 0)) { + OutImageType = FW_SET_STAMP_IMAGE; + if (argv[1] == NULL || argv[1][0] == '-') { + Error (NULL, 0, 1003, "Invalid option value", "time stamp is missing for -s option"); + goto Finish; + } + TimeStamp = argv[1]; + argc -= 2; + argv += 2; + continue; + } + + if ((stricmp (argv[0], "-r") == 0) || (stricmp (argv[0], "--replace") == 0)) { + ReplaceFlag = TRUE; + argc --; + argv ++; + continue; + } + + if (stricmp (argv[0], "--keepexceptiontable") == 0) { + KeepExceptionTableFlag = TRUE; + argc --; + argv ++; + continue; + } + + if (stricmp (argv[0], "--keepzeropending") == 0) { + KeepZeroPendingFlag = TRUE; + argc --; + argv ++; + continue; + } + + if ((stricmp (argv[0], "-m") == 0) || (stricmp (argv[0], "--mcifile") == 0)) { + OutImageType = FW_MCI_IMAGE; + argc --; + argv ++; + continue; + } + + if ((stricmp (argv[0], "-j") == 0) || (stricmp (argv[0], "--join") == 0)) { + OutImageType = FW_MERGE_IMAGE; + argc --; + argv ++; + continue; + } + + if ((stricmp (argv[0], "-a") == 0) || (stricmp (argv[0], "--align") == 0)) { + if (AsciiStringToUint64 (argv[1], FALSE, &Temp64) != EFI_SUCCESS) { + Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]); + goto Finish; + } + MciAlignment = (UINT32) Temp64; + argc -= 2; + argv += 2; + continue; + } + + if ((stricmp (argv[0], "-p") == 0) || (stricmp (argv[0], "--pad") == 0)) { + if (AsciiStringToUint64 (argv[1], FALSE, &Temp64) != EFI_SUCCESS) { + Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]); + goto Finish; + } + MciPadValue = (UINT8) Temp64; + argc -= 2; + argv += 2; + continue; + } + + if ((stricmp (argv[0], "-v") == 0) || (stricmp (argv[0], "--verbose") == 0)) { + SetPrintLevel (VERBOSE_LOG_LEVEL); + VerboseMsg ("Verbose output Mode Set!"); + argc --; + argv ++; + continue; + } + + if ((stricmp (argv[0], "-q") == 0) || (stricmp (argv[0], "--quiet") == 0)) { + SetPrintLevel (KEY_LOG_LEVEL); + KeyMsg ("Quiet output Mode Set!"); + argc --; + argv ++; + continue; + } + + if ((stricmp (argv[0], "-d") == 0) || (stricmp (argv[0], "--debug") == 0)) { + Status = AsciiStringToUint64 (argv[1], FALSE, &LogLevel); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]); + goto Finish; + } + if (LogLevel > 9) { + Error (NULL, 0, 1003, "Invalid option value", "Debug Level range is 0-9, currnt input level is %d", LogLevel); + goto Finish; + } + SetPrintLevel (LogLevel); + DebugMsg (NULL, 0, 9, "Debug Mode Set", "Debug Output Mode Level %s is set!", argv[1]); + argc -= 2; + argv += 2; + continue; + } + + if (argv[0][0] == '-') { + Error (NULL, 0, 1000, "Unknown option", argv[0]); + goto Finish; + } + // + // Get Input file name + // + if ((InputFileNum == 0) && (InputFileName == NULL)) { + InputFileName = (CHAR8 **) malloc (MAXIMUM_INPUT_FILE_NUM * sizeof (CHAR8 *)); + if (InputFileName == NULL) { + Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!"); + return EFI_OUT_OF_RESOURCES; + } + + memset (InputFileName, 0, (MAXIMUM_INPUT_FILE_NUM * sizeof (CHAR8 *))); + } else if (InputFileNum % MAXIMUM_INPUT_FILE_NUM == 0) { + // + // InputFileName buffer too small, need to realloc + // + InputFileName = (CHAR8 **) realloc ( + InputFileName, + (InputFileNum + MAXIMUM_INPUT_FILE_NUM) * sizeof (CHAR8 *) + ); + + if (InputFileName == NULL) { + Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!"); + return EFI_OUT_OF_RESOURCES; + } + + memset (&(InputFileName[InputFileNum]), 0, (MAXIMUM_INPUT_FILE_NUM * sizeof (CHAR8 *))); + } + + InputFileName [InputFileNum ++] = argv[0]; + argc --; + argv ++; + } + + VerboseMsg ("%s tool start.", UTILITY_NAME); + + if (OutImageType == FW_DUMMY_IMAGE) { + Error (NULL, 0, 1001, "Missing option", "No create file action specified; pls specify -e, -c or -t option to create efi image, or acpi table or TeImage!"); + if (ReplaceFlag) { + Error (NULL, 0, 1001, "Missing option", "-r option is not supported as the independent option. It can be used together with other create file option specified at the above."); + } + goto Finish; + } + + // + // check input files + // + if (InputFileNum == 0) { + Error (NULL, 0, 1001, "Missing option", "Input files"); + goto Finish; + } + + // + // Combine MciBinary files to one file + // + if ((OutImageType == FW_MERGE_IMAGE) && ReplaceFlag) { + Error (NULL, 0, 1002, "Conflicting option", "-r replace option cannot be used with -j merge files option."); + goto Finish; + } + + // + // Input image file + // + mInImageName = InputFileName [InputFileNum - 1]; + VerboseMsg ("the input file name is %s", mInImageName); + + // + // Action will be taken for the input file. + // + switch (OutImageType) { + case FW_EFI_IMAGE: + VerboseMsg ("Create efi image on module type %s based on the input PE image.", ModuleType); + break; + case FW_TE_IMAGE: + VerboseMsg ("Create Te Image based on the input PE image."); + break; + case FW_ACPI_IMAGE: + VerboseMsg ("Get acpi table data from the input PE image."); + break; + case FW_RELOC_STRIPEED_IMAGE: + VerboseMsg ("Remove relocation section from Pe or Te image."); + break; + case FW_BIN_IMAGE: + VerboseMsg ("Convert the input EXE to the output BIN file."); + break; + case FW_ZERO_DEBUG_IMAGE: + VerboseMsg ("Zero the Debug Data Fields and Time Stamp in input PE image."); + break; + case FW_SET_STAMP_IMAGE: + VerboseMsg ("Set new time stamp %s in the input PE image.", TimeStamp); + break; + case DUMP_TE_HEADER: + VerboseMsg ("Dump the TE header information of the input TE image."); + break; + case FW_MCI_IMAGE: + VerboseMsg ("Conver input MicroCode.txt file to MicroCode.bin file."); + break; + case FW_MERGE_IMAGE: + VerboseMsg ("Combine the input multi microcode bin files to one bin file."); + break; + default: + break; + } + + if (ReplaceFlag) { + VerboseMsg ("Overwrite the input file with the output content."); + } + + // + // Open output file and Write image into the output file. + // + if (OutImageName != NULL) { + fpOut = fopen (OutImageName, "rb"); + if (fpOut != NULL) { + OutputFileLength = _filelength (fileno (fpOut)); + OutputFileBuffer = malloc (OutputFileLength); + if (OutputFileBuffer == NULL) { + Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!"); + fclose (fpOut); + fpOut = NULL; + goto Finish; + } + fread (OutputFileBuffer, 1, OutputFileLength, fpOut); + fclose (fpOut); + } + fpOut = fopen (OutImageName, "wb"); + if (!fpOut) { + Error (NULL, 0, 0001, "Error opening output file", OutImageName); + goto Finish; + } + VerboseMsg ("Output file name is %s", OutImageName); + } else if (!ReplaceFlag) { + if (OutImageType == DUMP_TE_HEADER) { + fpOut = stdout; + } else { + Error (NULL, 0, 1001, "Missing option", "output file"); + goto Finish; + } + } + + // + // Combine MciBinary files to one file + // + if (OutImageType == FW_MERGE_IMAGE) { + for (Index = 0; Index < InputFileNum; Index ++) { + fpIn = fopen (InputFileName [Index], "rb"); + if (!fpIn) { + Error (NULL, 0, 0001, "Error opening file", InputFileName [Index]); + goto Finish; + } + + FileLength = _filelength (fileno (fpIn)); + FileBuffer = malloc (FileLength); + if (FileBuffer == NULL) { + Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!"); + fclose (fpIn); + goto Finish; + } + + fread (FileBuffer, 1, FileLength, fpIn); + fclose (fpIn); + // + // write input file to out file + // + fwrite (FileBuffer, 1, FileLength, fpOut); + // + // write pad value to out file. + // + while (FileLength ++ % MciAlignment != 0) { + fwrite (&MciPadValue, 1, 1, fpOut); + } + // + // free allocated memory space + // + free (FileBuffer); + FileBuffer = NULL; + } + // + // Done successfully + // + goto Finish; + } + + // + // Convert MicroCode.txt file to MicroCode.bin file + // + if (OutImageType == FW_MCI_IMAGE) { + fpIn = fopen (mInImageName, "r"); + if (!fpIn) { + Error (NULL, 0, 0001, "Error opening file", mInImageName); + goto Finish; + } + + // + // The first pass is to determine + // how much data is in the file so we can allocate a working buffer. + // + FileLength = 0; + do { + Status = MicrocodeReadData (fpIn, &Data); + if (Status == STATUS_SUCCESS) { + FileLength += sizeof (Data); + } + if (Status == STATUS_IGNORE) { + Status = STATUS_SUCCESS; + } + } while (Status == STATUS_SUCCESS); + // + // Error if no data. + // + if (FileLength == 0) { + Error (NULL, 0, 3000, "Invalid", "no parseable data found in file %s", mInImageName); + goto Finish; + } + if (FileLength < sizeof (MICROCODE_IMAGE_HEADER)) { + Error (NULL, 0, 3000, "Invalid", "amount of parseable data in %s is insufficient to contain a microcode header", mInImageName); + goto Finish; + } + + // + // Allocate a buffer for the data + // + FileBuffer = malloc (FileLength); + if (FileBuffer == NULL) { + Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!"); + goto Finish; + } + // + // Re-read the file, storing the data into our buffer + // + fseek (fpIn, 0, SEEK_SET); + DataPointer = (UINT32 *) FileBuffer; + OldDataPointer = DataPointer; + do { + OldDataPointer = DataPointer; + Status = MicrocodeReadData (fpIn, DataPointer++); + if (Status == STATUS_IGNORE) { + DataPointer = OldDataPointer; + Status = STATUS_SUCCESS; + } + } while (Status == STATUS_SUCCESS); + // + // close input file after read data + // + fclose (fpIn); + + // + // 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. + // + MciHeader = (MICROCODE_IMAGE_HEADER *) FileBuffer; + if (MciHeader->DataSize == 0) { + Index = 2048; + } else { + Index = MciHeader->TotalSize; + } + + if (Index != FileLength) { + Error (NULL, 0, 3000, "Invalid", "file length of %s (0x%x) does not equal expected TotalSize: 0x%04X.", mInImageName, FileLength, Index); + goto Finish; + } + + // + // Checksum the contents + // + DataPointer = (UINT32 *) FileBuffer; + CheckSum = 0; + Index = 0; + while (Index < FileLength) { + CheckSum += *DataPointer; + DataPointer ++; + Index += sizeof (*DataPointer); + } + if (CheckSum != 0) { + Error (NULL, 0, 3000, "Invalid", "checksum (0x%x) failed on file %s.", CheckSum, mInImageName); + goto Finish; + } + // + // Open the output file and write the buffer contents + // + if (fpOut != NULL) { + if (fwrite (FileBuffer, FileLength, 1, fpOut) != 1) { + Error (NULL, 0, 0002, "Error writing file", OutImageName); + goto Finish; + } + } + + if (ReplaceFlag) { + fpInOut = fopen (mInImageName, "wb"); + if (fpInOut != NULL) { + Error (NULL, 0, 0001, "Error opening file", mInImageName); + goto Finish; + } + if (fwrite (FileBuffer, FileLength, 1, fpInOut) != 1) { + Error (NULL, 0, 0002, "Error writing file", mInImageName); + goto Finish; + } + } + VerboseMsg ("the size of output file is %d bytes", FileLength); + // + // Convert Mci.TXT to Mci.bin file successfully + // + goto Finish; + } + + // + // Open input file and read file data into file buffer. + // + fpIn = fopen (mInImageName, "rb"); + if (!fpIn) { + Error (NULL, 0, 0001, "Error opening file", mInImageName); + goto Finish; + } + + FileLength = _filelength (fileno (fpIn)); + FileBuffer = malloc (FileLength); + if (FileBuffer == NULL) { + Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!"); + fclose (fpIn); + goto Finish; + } + + fread (FileBuffer, 1, FileLength, fpIn); + fclose (fpIn); + + DebugMsg (NULL, 0, 9, "input file info", "the input file size is %d bytes", FileLength); + + // + // Replace file + // + if (ReplaceFlag) { + fpInOut = fopen (mInImageName, "wb"); + if (!fpInOut) { + Error (NULL, 0, 0001, "Error opening file", mInImageName); + goto Finish; + } + } + // + // Dump TeImage Header into output file. + // + if (OutImageType == DUMP_TE_HEADER) { + memcpy (&TEImageHeader, FileBuffer, sizeof (TEImageHeader)); + if (TEImageHeader.Signature != EFI_TE_IMAGE_HEADER_SIGNATURE) { + Error (NULL, 0, 3000, "Invalid", "TE header signature of file %s is not correct.", mInImageName); + goto Finish; + } + if (fpInOut != NULL) { + fprintf (fpInOut, "Dump of file %s\n\n", mInImageName); + fprintf (fpInOut, "TE IMAGE HEADER VALUES\n"); + fprintf (fpInOut, "%17X machine\n", TEImageHeader.Machine); + fprintf (fpInOut, "%17X number of sections\n", TEImageHeader.NumberOfSections); + fprintf (fpInOut, "%17X subsystems\n", TEImageHeader.Subsystem); + fprintf (fpInOut, "%17X stripped size\n", TEImageHeader.StrippedSize); + fprintf (fpInOut, "%17X entry point\n", TEImageHeader.AddressOfEntryPoint); + fprintf (fpInOut, "%17X base of code\n", TEImageHeader.BaseOfCode); + fprintf (fpInOut, "%17lX image base\n", (long unsigned int)TEImageHeader.ImageBase); + fprintf (fpInOut, "%17X [%8X] RVA [size] of Base Relocation Directory\n", TEImageHeader.DataDirectory[0].VirtualAddress, TEImageHeader.DataDirectory[0].Size); + fprintf (fpInOut, "%17X [%8X] RVA [size] of Debug Directory\n", TEImageHeader.DataDirectory[1].VirtualAddress, TEImageHeader.DataDirectory[1].Size); + } + + if (fpOut != NULL) { + fprintf (fpOut, "Dump of file %s\n\n", mInImageName); + fprintf (fpOut, "TE IMAGE HEADER VALUES\n"); + fprintf (fpOut, "%17X machine\n", TEImageHeader.Machine); + fprintf (fpOut, "%17X number of sections\n", TEImageHeader.NumberOfSections); + fprintf (fpOut, "%17X subsystems\n", TEImageHeader.Subsystem); + fprintf (fpOut, "%17X stripped size\n", TEImageHeader.StrippedSize); + fprintf (fpOut, "%17X entry point\n", TEImageHeader.AddressOfEntryPoint); + fprintf (fpOut, "%17X base of code\n", TEImageHeader.BaseOfCode); + fprintf (fpOut, "%17lX image base\n", (long unsigned int)TEImageHeader.ImageBase); + fprintf (fpOut, "%17X [%8X] RVA [size] of Base Relocation Directory\n", TEImageHeader.DataDirectory[0].VirtualAddress, TEImageHeader.DataDirectory[0].Size); + fprintf (fpOut, "%17X [%8X] RVA [size] of Debug Directory\n", TEImageHeader.DataDirectory[1].VirtualAddress, TEImageHeader.DataDirectory[1].Size); + } + goto Finish; + } + + // + // Following code to convert dll to efi image or te image. + // Get new image type + // + if ((OutImageType == FW_EFI_IMAGE) || (OutImageType == FW_TE_IMAGE)) { + if (ModuleType == NULL) { + if (OutImageType == FW_EFI_IMAGE) { + Error (NULL, 0, 1001, "Missing option", "EFI_FILETYPE"); + goto Finish; + } else if (OutImageType == FW_TE_IMAGE) { + // + // Default TE Image Type is Boot service driver + // + Type = EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER; + VerboseMsg ("Efi Image subsystem type is efi boot service driver."); + } + } else { + if (stricmp (ModuleType, "BASE") == 0 || + stricmp (ModuleType, "SEC") == 0 || + stricmp (ModuleType, "SECURITY_CORE") == 0 || + stricmp (ModuleType, "PEI_CORE") == 0 || + stricmp (ModuleType, "PEIM") == 0 || + stricmp (ModuleType, "COMBINED_PEIM_DRIVER") == 0 || + stricmp (ModuleType, "PIC_PEIM") == 0 || + stricmp (ModuleType, "RELOCATABLE_PEIM") == 0 || + stricmp (ModuleType, "DXE_CORE") == 0 || + stricmp (ModuleType, "BS_DRIVER") == 0 || + stricmp (ModuleType, "DXE_DRIVER") == 0 || + stricmp (ModuleType, "DXE_SMM_DRIVER") == 0 || + stricmp (ModuleType, "UEFI_DRIVER") == 0 || + stricmp (ModuleType, "SMM_DRIVER") == 0 || + stricmp (ModuleType, "SMM_CORE") == 0) { + Type = EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER; + VerboseMsg ("Efi Image subsystem type is efi boot service driver."); + + } else if (stricmp (ModuleType, "UEFI_APPLICATION") == 0 || + stricmp (ModuleType, "APPLICATION") == 0) { + Type = EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION; + VerboseMsg ("Efi Image subsystem type is efi application."); + + } else if (stricmp (ModuleType, "DXE_RUNTIME_DRIVER") == 0 || + stricmp (ModuleType, "RT_DRIVER") == 0) { + Type = EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER; + VerboseMsg ("Efi Image subsystem type is efi runtime driver."); + + } else if (stricmp (ModuleType, "DXE_SAL_DRIVER") == 0 || + stricmp (ModuleType, "SAL_RT_DRIVER") == 0) { + Type = EFI_IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER; + VerboseMsg ("Efi Image subsystem type is efi sal runtime driver."); + + } else { + Error (NULL, 0, 1003, "Invalid option value", "EFI_FILETYPE = %s", ModuleType); + goto Finish; + } + } + } + + // + // Convert EFL image to PeImage + // + if (IsElfHeader(FileBuffer)) { + VerboseMsg ("Convert the input ELF Image to Pe Image"); + ConvertElf(&FileBuffer, &FileLength); + } + + // + // Remove reloc section from PE or TE image + // + if (OutImageType == FW_RELOC_STRIPEED_IMAGE) { + // + // Check TeImage + // + TeHdr = (EFI_TE_IMAGE_HEADER *) FileBuffer; + if (TeHdr->Signature == EFI_TE_IMAGE_HEADER_SIGNATURE) { + SectionHeader = (EFI_IMAGE_SECTION_HEADER *) (TeHdr + 1); + for (Index = 0; Index < TeHdr->NumberOfSections; Index ++, SectionHeader ++) { + if (strcmp ((char *)SectionHeader->Name, ".reloc") == 0) { + // + // Check the reloc section is in the end of image. + // + if ((SectionHeader->PointerToRawData + SectionHeader->SizeOfRawData) == + (FileLength + TeHdr->StrippedSize - sizeof (EFI_TE_IMAGE_HEADER))) { + // + // Remove .reloc section and update TeImage Header + // + FileLength = FileLength - SectionHeader->SizeOfRawData; + SectionHeader->SizeOfRawData = 0; + SectionHeader->Misc.VirtualSize = 0; + TeHdr->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = 0; + TeHdr->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size = 0; + break; + } + } + } + } else { + // + // Check PE Image + // + DosHdr = (EFI_IMAGE_DOS_HEADER *) FileBuffer; + if (DosHdr->e_magic != EFI_IMAGE_DOS_SIGNATURE) { + PeHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(FileBuffer); + if (PeHdr->Pe32.Signature != EFI_IMAGE_NT_SIGNATURE) { + Error (NULL, 0, 3000, "Invalid", "TE and DOS header signatures were not found in %s image.", mInImageName); + goto Finish; + } + DosHdr = NULL; + } else { + PeHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(FileBuffer + DosHdr->e_lfanew); + if (PeHdr->Pe32.Signature != EFI_IMAGE_NT_SIGNATURE) { + Error (NULL, 0, 3000, "Invalid", "PE header signature was not found in %s image.", mInImageName); + goto Finish; + } + } + SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) &(PeHdr->Pe32.OptionalHeader) + PeHdr->Pe32.FileHeader.SizeOfOptionalHeader); + for (Index = 0; Index < PeHdr->Pe32.FileHeader.NumberOfSections; Index ++, SectionHeader ++) { + if (strcmp ((char *)SectionHeader->Name, ".reloc") == 0) { + // + // Check the reloc section is in the end of image. + // + if ((SectionHeader->PointerToRawData + SectionHeader->SizeOfRawData) == FileLength) { + // + // Remove .reloc section and update PeImage Header + // + FileLength = FileLength - SectionHeader->SizeOfRawData; + + PeHdr->Pe32.FileHeader.Characteristics |= EFI_IMAGE_FILE_RELOCS_STRIPPED; + if (PeHdr->Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) { + Optional32 = (EFI_IMAGE_OPTIONAL_HEADER32 *)&PeHdr->Pe32.OptionalHeader; + Optional32->SizeOfImage -= SectionHeader->SizeOfRawData; + Optional32->SizeOfInitializedData -= SectionHeader->SizeOfRawData; + if (Optional32->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) { + Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = 0; + Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size = 0; + } + } + if (PeHdr->Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) { + Optional64 = (EFI_IMAGE_OPTIONAL_HEADER64 *)&PeHdr->Pe32.OptionalHeader; + Optional64->SizeOfImage -= SectionHeader->SizeOfRawData; + Optional64->SizeOfInitializedData -= SectionHeader->SizeOfRawData; + if (Optional64->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) { + Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = 0; + Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size = 0; + } + } + SectionHeader->Misc.VirtualSize = 0; + SectionHeader->SizeOfRawData = 0; + break; + } + } + } + } + // + // Write file + // + goto WriteFile; + } + // + // Read the dos & pe hdrs of the image + // + DosHdr = (EFI_IMAGE_DOS_HEADER *)FileBuffer; + if (DosHdr->e_magic != EFI_IMAGE_DOS_SIGNATURE) { + // NO DOS header, check for PE/COFF header + PeHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(FileBuffer); + if (PeHdr->Pe32.Signature != EFI_IMAGE_NT_SIGNATURE) { + Error (NULL, 0, 3000, "Invalid", "DOS header signature was not found in %s image.", mInImageName); + goto Finish; + } + DosHdr = NULL; + } else { + + PeHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(FileBuffer + DosHdr->e_lfanew); + if (PeHdr->Pe32.Signature != EFI_IMAGE_NT_SIGNATURE) { + Error (NULL, 0, 3000, "Invalid", "PE header signature was not found in %s image.", mInImageName); + goto Finish; + } + } + + if (PeHdr->Pe32.FileHeader.Machine == IMAGE_FILE_MACHINE_ARM) { + // Some tools kick out IMAGE_FILE_MACHINE_ARM (0x1c0) vs IMAGE_FILE_MACHINE_ARMT (0x1c2) + // so patch back to the offical UEFI value. + PeHdr->Pe32.FileHeader.Machine = IMAGE_FILE_MACHINE_ARMT; + } + + // + // Extract bin data from Pe image. + // + if (OutImageType == FW_BIN_IMAGE) { + if (FileLength < PeHdr->Pe32.OptionalHeader.SizeOfHeaders) { + Error (NULL, 0, 3000, "Invalid", "FileSize of %s is not a legal size.", mInImageName); + goto Finish; + } + // + // Output bin data from exe file + // + if (fpOut != NULL) { + fwrite (FileBuffer + PeHdr->Pe32.OptionalHeader.SizeOfHeaders, 1, FileLength - PeHdr->Pe32.OptionalHeader.SizeOfHeaders, fpOut); + } + if (fpInOut != NULL) { + fwrite (FileBuffer + PeHdr->Pe32.OptionalHeader.SizeOfHeaders, 1, FileLength - PeHdr->Pe32.OptionalHeader.SizeOfHeaders, fpInOut); + } + VerboseMsg ("the size of output file is %d bytes", FileLength - PeHdr->Pe32.OptionalHeader.SizeOfHeaders); + goto Finish; + } + + // + // Zero Debug Information of Pe Image + // + if (OutImageType == FW_ZERO_DEBUG_IMAGE) { + Status = ZeroDebugData (FileBuffer, TRUE); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 3000, "Invalid", "Zero DebugData Error status is 0x%lx", (UINTN) Status); + goto Finish; + } + + if (fpOut != NULL) { + fwrite (FileBuffer, 1, FileLength, fpOut); + } + if (fpInOut != NULL) { + fwrite (FileBuffer, 1, FileLength, fpInOut); + } + VerboseMsg ("the size of output file is %d bytes", FileLength); + goto Finish; + } + + // + // Set Time Stamp of Pe Image + // + if (OutImageType == FW_SET_STAMP_IMAGE) { + Status = SetStamp (FileBuffer, TimeStamp); + if (EFI_ERROR (Status)) { + goto Finish; + } + + if (fpOut != NULL) { + fwrite (FileBuffer, 1, FileLength, fpOut); + } + if (fpInOut != NULL) { + fwrite (FileBuffer, 1, FileLength, fpInOut); + } + VerboseMsg ("the size of output file is %d bytes", FileLength); + goto Finish; + } + + // + // Extract acpi data from pe image. + // + if (OutImageType == FW_ACPI_IMAGE) { + SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) &(PeHdr->Pe32.OptionalHeader) + PeHdr->Pe32.FileHeader.SizeOfOptionalHeader); + for (Index = 0; Index < PeHdr->Pe32.FileHeader.NumberOfSections; Index ++, SectionHeader ++) { + if (strcmp ((char *)SectionHeader->Name, ".data") == 0 || strcmp ((char *)SectionHeader->Name, ".sdata") == 0) { + // + // Check Acpi Table + // + if (SectionHeader->Misc.VirtualSize < SectionHeader->SizeOfRawData) { + FileLength = SectionHeader->Misc.VirtualSize; + } else { + FileLength = SectionHeader->SizeOfRawData; + } + + if (CheckAcpiTable (FileBuffer + SectionHeader->PointerToRawData, FileLength) != STATUS_SUCCESS) { + Error (NULL, 0, 3000, "Invalid", "ACPI table check failed in %s.", mInImageName); + goto Finish; + } + + // + // Output Apci data to file + // + if (fpOut != NULL) { + fwrite (FileBuffer + SectionHeader->PointerToRawData, 1, FileLength, fpOut); + } + if (fpInOut != NULL) { + fwrite (FileBuffer + SectionHeader->PointerToRawData, 1, FileLength, fpInOut); + } + VerboseMsg ("the size of output file is %d bytes", FileLength); + goto Finish; + } + } + Error (NULL, 0, 3000, "Invalid", "failed to get ACPI table from %s.", mInImageName); + goto Finish; + } + // + // Zero all unused fields of the DOS header + // + if (DosHdr != NULL) { + 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 < (UINT32 ) DosHdr->e_lfanew; Index++) { + FileBuffer[Index] = DosHdr->e_cp; + } + } + + // + // Initialize TeImage Header + // + memset (&TEImageHeader, 0, sizeof (EFI_TE_IMAGE_HEADER)); + TEImageHeader.Signature = EFI_TE_IMAGE_HEADER_SIGNATURE; + TEImageHeader.Machine = PeHdr->Pe32.FileHeader.Machine; + TEImageHeader.NumberOfSections = (UINT8) PeHdr->Pe32.FileHeader.NumberOfSections; + TEImageHeader.StrippedSize = (UINT16) ((UINTN) ((UINT8 *) &(PeHdr->Pe32.OptionalHeader) + PeHdr->Pe32.FileHeader.SizeOfOptionalHeader) - (UINTN) FileBuffer); + TEImageHeader.Subsystem = (UINT8) Type; + + // + // Patch the PE header + // + PeHdr->Pe32.OptionalHeader.Subsystem = (UINT16) Type; + + if (PeHdr->Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) { + Optional32 = (EFI_IMAGE_OPTIONAL_HEADER32 *)&PeHdr->Pe32.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; + + TEImageHeader.AddressOfEntryPoint = Optional32->AddressOfEntryPoint; + TEImageHeader.BaseOfCode = Optional32->BaseOfCode; + TEImageHeader.ImageBase = (UINT64) (Optional32->ImageBase); + + if (Optional32->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) { + TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress; + TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size = Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size; + } + + if (Optional32->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG) { + TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress = Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress; + TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].Size = Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size; + } + + // + // Zero .pdata section data. + // + if (!KeepExceptionTableFlag && Optional32->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION && + Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress != 0 && + Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].Size != 0) { + SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) &(PeHdr->Pe32.OptionalHeader) + PeHdr->Pe32.FileHeader.SizeOfOptionalHeader); + for (Index = 0; Index < PeHdr->Pe32.FileHeader.NumberOfSections; Index++, SectionHeader++) { + if (SectionHeader->VirtualAddress == Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress) { + // + // Zero .pdata Section data + // + memset (FileBuffer + SectionHeader->PointerToRawData, 0, SectionHeader->SizeOfRawData); + // + // Zero .pdata Section header name + // + memset (SectionHeader->Name, 0, sizeof (SectionHeader->Name)); + // + // Zero Execption Table + // + Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress = 0; + Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].Size = 0; + DebugMsg (NULL, 0, 9, "Zero the .pdata section for PE image", NULL); + break; + } + } + } + + // + // Strip zero padding at the end of the .reloc section + // + if (!KeepZeroPendingFlag && Optional32->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) { + if (Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size != 0) { + SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) &(PeHdr->Pe32.OptionalHeader) + PeHdr->Pe32.FileHeader.SizeOfOptionalHeader); + for (Index = 0; Index < PeHdr->Pe32.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[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress) { + SectionHeader->Misc.VirtualSize = Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size; + AllignedRelocSize = (Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].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; + DebugMsg (NULL, 0, 9, "Remove the zero padding bytes at the end of the base relocations", "The size of padding bytes is %d", SectionHeader->SizeOfRawData - AllignedRelocSize); + } + } + } + } + } + } + } else if (PeHdr->Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) { + Optional64 = (EFI_IMAGE_OPTIONAL_HEADER64 *)&PeHdr->Pe32.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; + + TEImageHeader.AddressOfEntryPoint = Optional64->AddressOfEntryPoint; + TEImageHeader.BaseOfCode = Optional64->BaseOfCode; + TEImageHeader.ImageBase = (UINT64) (Optional64->ImageBase); + + if (Optional64->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) { + TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress; + TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size = Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size; + } + + if (Optional64->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG) { + TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress = Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress; + TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].Size = Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size; + } + + // + // Zero the .pdata section for X64 machine and don't check the Debug Directory is empty + // For Itaninum and X64 Image, remove .pdata section. + // + if ((!KeepExceptionTableFlag && PeHdr->Pe32.FileHeader.Machine == IMAGE_FILE_MACHINE_X64) || PeHdr->Pe32.FileHeader.Machine == IMAGE_FILE_MACHINE_IA64) { + if (Optional64->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION && + Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress != 0 && + Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].Size != 0) { + SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) &(PeHdr->Pe32.OptionalHeader) + PeHdr->Pe32.FileHeader.SizeOfOptionalHeader); + for (Index = 0; Index < PeHdr->Pe32.FileHeader.NumberOfSections; Index++, SectionHeader++) { + if (SectionHeader->VirtualAddress == Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress) { + // + // Zero .pdata Section header name + // + memset (SectionHeader->Name, 0, sizeof (SectionHeader->Name)); + + RuntimeFunction = (RUNTIME_FUNCTION *)(FileBuffer + SectionHeader->PointerToRawData); + for (Index1 = 0; Index1 < Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].Size / sizeof (RUNTIME_FUNCTION); Index1++, RuntimeFunction++) { + SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) &(PeHdr->Pe32.OptionalHeader) + PeHdr->Pe32.FileHeader.SizeOfOptionalHeader); + for (Index2 = 0; Index2 < PeHdr->Pe32.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)); + } + // + // Zero Execption Table + // + Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].Size = 0; + Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress = 0; + DebugMsg (NULL, 0, 9, "Zero the .pdata section if the machine type is X64 for PE32+ image", NULL); + break; + } + } + } + } + + // + // Strip zero padding at the end of the .reloc section + // + if (!KeepZeroPendingFlag && Optional64->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG) { + if (Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size != 0) { + SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) &(PeHdr->Pe32.OptionalHeader) + PeHdr->Pe32.FileHeader.SizeOfOptionalHeader); + for (Index = 0; Index < PeHdr->Pe32.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[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress) { + SectionHeader->Misc.VirtualSize = Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size; + AllignedRelocSize = (Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].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; + DebugMsg (NULL, 0, 9, "Remove the zero padding bytes at the end of the base relocations", "The size of padding bytes is %d", SectionHeader->SizeOfRawData - AllignedRelocSize); + } + } + } + } + } + } + } else { + Error (NULL, 0, 3000, "Invalid", "Magic 0x%x of PeImage %s is unknown.", PeHdr->Pe32.OptionalHeader.Magic, mInImageName); + goto Finish; + } + + if (((PeHdr->Pe32.FileHeader.Characteristics & EFI_IMAGE_FILE_RELOCS_STRIPPED) == 0) && \ + (TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress == 0) && \ + (TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size == 0)) { + // + // PeImage can be loaded into memory, but it has no relocation section. + // Fix TeImage Header to set VA of relocation data directory to not zero, the size is still zero. + // + if (Optional32 != NULL) { + TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = Optional32->SizeOfImage - sizeof (EFI_IMAGE_BASE_RELOCATION); + } else if (Optional64 != NULL) { + TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = Optional64->SizeOfImage - sizeof (EFI_IMAGE_BASE_RELOCATION); + } + } + + // + // Zero ExceptionTable Xdata + // + if (!KeepExceptionTableFlag) { + SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) &(PeHdr->Pe32.OptionalHeader) + PeHdr->Pe32.FileHeader.SizeOfOptionalHeader); + ZeroXdataSection(mInImageName, FileBuffer, SectionHeader, PeHdr->Pe32.FileHeader.NumberOfSections); + } + + // + // Zero Time/Data field + // + ZeroDebugData (FileBuffer, FALSE); + + if (OutImageType == FW_TE_IMAGE) { + if ((PeHdr->Pe32.FileHeader.NumberOfSections &~0xFF) || (Type &~0xFF)) { + // + // Pack the subsystem and NumberOfSections into 1 byte. Make sure they fit both. + // + Error (NULL, 0, 3000, "Invalid", "Image's subsystem or NumberOfSections of PeImage %s cannot be packed into 1 byte.", mInImageName); + goto Finish; + } + + if ((PeHdr->Pe32.OptionalHeader.SectionAlignment != PeHdr->Pe32.OptionalHeader.FileAlignment)) { + // + // TeImage has the same section alignment and file alignment. + // + Error (NULL, 0, 3000, "Invalid", "Section-Alignment and File-Alignment of PeImage %s do not match, they must be equal for a TeImage.", mInImageName); + goto Finish; + } + + DebugMsg (NULL, 0, 9, "TeImage Header Info", "Machine type is %X, Number of sections is %X, Stripped size is %X, EntryPoint is %X, BaseOfCode is %X, ImageBase is %X", + TEImageHeader.Machine, TEImageHeader.NumberOfSections, TEImageHeader.StrippedSize, TEImageHeader.AddressOfEntryPoint, TEImageHeader.BaseOfCode, TEImageHeader.ImageBase); + // + // Update Image to TeImage + // + if (fpOut != NULL) { + fwrite (&TEImageHeader, 1, sizeof (EFI_TE_IMAGE_HEADER), fpOut); + fwrite (FileBuffer + TEImageHeader.StrippedSize, 1, FileLength - TEImageHeader.StrippedSize, fpOut); + } + if (fpInOut != NULL) { + fwrite (&TEImageHeader, 1, sizeof (EFI_TE_IMAGE_HEADER), fpInOut); + fwrite (FileBuffer + TEImageHeader.StrippedSize, 1, FileLength - TEImageHeader.StrippedSize, fpInOut); + } + VerboseMsg ("the size of output file is %d bytes", FileLength - TEImageHeader.StrippedSize); + goto Finish; + } +WriteFile: + // + // Update Image to EfiImage + // + if (fpOut != NULL) { + fwrite (FileBuffer, 1, FileLength, fpOut); + } + if (fpInOut != NULL) { + fwrite (FileBuffer, 1, FileLength, fpInOut); + } + VerboseMsg ("the size of output file is %d bytes", FileLength); + +Finish: + if (fpInOut != NULL) { + if (GetUtilityStatus () != STATUS_SUCCESS) { + // + // when file updates failed, original file is still recoveried. + // + fwrite (FileBuffer, 1, FileLength, fpInOut); + } + // + // Write converted data into fpInOut file and close input file. + // + fclose (fpInOut); + } + + if (FileBuffer != NULL) { + free (FileBuffer); + } + + if (InputFileName != NULL) { + free (InputFileName); + } + + if (fpOut != NULL) { + // + // Write converted data into fpOut file and close output file. + // + fclose (fpOut); + if (GetUtilityStatus () != STATUS_SUCCESS) { + if (OutputFileBuffer == NULL) { + remove (OutImageName); + } else { + fpOut = fopen (OutImageName, "wb"); + fwrite (OutputFileBuffer, 1, OutputFileLength, fpOut); + fclose (fpOut); + free (OutputFileBuffer); + } + } + } + + VerboseMsg ("%s tool done with return code is 0x%x.", UTILITY_NAME, GetUtilityStatus ()); + + return GetUtilityStatus (); +} + +STATIC +EFI_STATUS +ZeroDebugData ( + IN OUT UINT8 *FileBuffer, + BOOLEAN ZeroDebugFlag + ) +/*++ + +Routine Description: + + Zero debug information in PeImage. + +Arguments: + + FileBuffer - Pointer to PeImage. + ZeroDebugFlag - TRUE to zero Debug information, FALSE to only zero time/stamp + +Returns: + + EFI_ABORTED - PeImage is invalid. + EFI_SUCCESS - Zero debug data successfully. + +--*/ +{ + UINT32 Index; + UINT32 DebugDirectoryEntryRva; + UINT32 DebugDirectoryEntryFileOffset; + UINT32 ExportDirectoryEntryRva; + UINT32 ExportDirectoryEntryFileOffset; + UINT32 ResourceDirectoryEntryRva; + UINT32 ResourceDirectoryEntryFileOffset; + EFI_IMAGE_DOS_HEADER *DosHdr; + EFI_IMAGE_FILE_HEADER *FileHdr; + EFI_IMAGE_OPTIONAL_HEADER32 *Optional32Hdr; + EFI_IMAGE_OPTIONAL_HEADER64 *Optional64Hdr; + EFI_IMAGE_SECTION_HEADER *SectionHeader; + EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *DebugEntry; + UINT32 *NewTimeStamp; + + // + // Init variable. + // + DebugDirectoryEntryRva = 0; + ExportDirectoryEntryRva = 0; + ResourceDirectoryEntryRva = 0; + DosHdr = (EFI_IMAGE_DOS_HEADER *) FileBuffer; + FileHdr = (EFI_IMAGE_FILE_HEADER *) (FileBuffer + DosHdr->e_lfanew + sizeof (UINT32)); + + + DosHdr = (EFI_IMAGE_DOS_HEADER *)FileBuffer; + if (DosHdr->e_magic != EFI_IMAGE_DOS_SIGNATURE) { + // NO DOS header, must start with PE/COFF header + FileHdr = (EFI_IMAGE_FILE_HEADER *)(FileBuffer + sizeof (UINT32)); + } else { + FileHdr = (EFI_IMAGE_FILE_HEADER *)(FileBuffer + DosHdr->e_lfanew + sizeof (UINT32)); + } + + // + // Get Debug, Export and Resource EntryTable RVA address. + // Resource Directory entry need to review. + // + if (FileHdr->Machine == EFI_IMAGE_MACHINE_IA32) { + Optional32Hdr = (EFI_IMAGE_OPTIONAL_HEADER32 *) ((UINT8*) FileHdr + sizeof (EFI_IMAGE_FILE_HEADER)); + SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) Optional32Hdr + FileHdr->SizeOfOptionalHeader); + if (Optional32Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_EXPORT && \ + Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT].Size != 0) { + ExportDirectoryEntryRva = Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress; + } + if (Optional32Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE && \ + Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].Size != 0) { + ResourceDirectoryEntryRva = Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress; + } + if (Optional32Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG && \ + Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size != 0) { + DebugDirectoryEntryRva = Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress; + if (ZeroDebugFlag) { + Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size = 0; + Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress = 0; + } + } + } else { + Optional64Hdr = (EFI_IMAGE_OPTIONAL_HEADER64 *) ((UINT8*) FileHdr + sizeof (EFI_IMAGE_FILE_HEADER)); + SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) Optional64Hdr + FileHdr->SizeOfOptionalHeader); + if (Optional64Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_EXPORT && \ + Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT].Size != 0) { + ExportDirectoryEntryRva = Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress; + } + if (Optional64Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE && \ + Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].Size != 0) { + ResourceDirectoryEntryRva = Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress; + } + if (Optional64Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG && \ + Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size != 0) { + DebugDirectoryEntryRva = Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress; + if (ZeroDebugFlag) { + Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size = 0; + Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress = 0; + } + } + } + + // + // Get DirectoryEntryTable file offset. + // + for (Index = 0; Index < FileHdr->NumberOfSections; Index ++, SectionHeader ++) { + if (DebugDirectoryEntryRva >= SectionHeader->VirtualAddress && + DebugDirectoryEntryRva < SectionHeader->VirtualAddress + SectionHeader->Misc.VirtualSize) { + DebugDirectoryEntryFileOffset = + DebugDirectoryEntryRva - SectionHeader->VirtualAddress + SectionHeader->PointerToRawData; + } + if (ExportDirectoryEntryRva >= SectionHeader->VirtualAddress && + ExportDirectoryEntryRva < SectionHeader->VirtualAddress + SectionHeader->Misc.VirtualSize) { + ExportDirectoryEntryFileOffset = + ExportDirectoryEntryRva - SectionHeader->VirtualAddress + SectionHeader->PointerToRawData; + } + if (ResourceDirectoryEntryRva >= SectionHeader->VirtualAddress && + ResourceDirectoryEntryRva < SectionHeader->VirtualAddress + SectionHeader->Misc.VirtualSize) { + ResourceDirectoryEntryFileOffset = + ResourceDirectoryEntryRva - SectionHeader->VirtualAddress + SectionHeader->PointerToRawData; + } + } + + // + //Zero Debug Data and TimeStamp + // + FileHdr->TimeDateStamp = 0; + + if (ExportDirectoryEntryRva != 0) { + NewTimeStamp = (UINT32 *) (FileBuffer + ExportDirectoryEntryFileOffset + sizeof (UINT32)); + *NewTimeStamp = 0; + } + + if (ResourceDirectoryEntryRva != 0) { + NewTimeStamp = (UINT32 *) (FileBuffer + ResourceDirectoryEntryFileOffset + sizeof (UINT32)); + *NewTimeStamp = 0; + } + + if (DebugDirectoryEntryRva != 0) { + DebugEntry = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *) (FileBuffer + DebugDirectoryEntryFileOffset); + DebugEntry->TimeDateStamp = 0; + if (ZeroDebugFlag) { + memset (FileBuffer + DebugEntry->FileOffset, 0, DebugEntry->SizeOfData); + memset (DebugEntry, 0, sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY)); + } + } + + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +SetStamp ( + IN OUT UINT8 *FileBuffer, + IN CHAR8 *TimeStamp + ) +/*++ + +Routine Description: + + Set new time stamp into PeImage FileHdr and Directory table: + Debug, Export and Resource. + +Arguments: + + FileBuffer - Pointer to PeImage. + TimeStamp - Time stamp string. + +Returns: + + EFI_INVALID_PARAMETER - TimeStamp format is not recognized. + EFI_SUCCESS - Set new time stamp in this image successfully. + +--*/ +{ + struct tm stime; + struct tm *ptime; + time_t newtime; + UINT32 Index; + UINT32 DebugDirectoryEntryRva; + UINT32 DebugDirectoryEntryFileOffset; + UINT32 ExportDirectoryEntryRva; + UINT32 ExportDirectoryEntryFileOffset; + UINT32 ResourceDirectoryEntryRva; + UINT32 ResourceDirectoryEntryFileOffset; + EFI_IMAGE_DOS_HEADER *DosHdr; + EFI_IMAGE_FILE_HEADER *FileHdr; + EFI_IMAGE_OPTIONAL_HEADER32 *Optional32Hdr; + EFI_IMAGE_OPTIONAL_HEADER64 *Optional64Hdr; + EFI_IMAGE_SECTION_HEADER *SectionHeader; + UINT32 *NewTimeStamp; + + // + // Init variable. + // + DebugDirectoryEntryRva = 0; + ExportDirectoryEntryRva = 0; + ResourceDirectoryEntryRva = 0; + // + // Get time and date that will be set. + // + if (TimeStamp == NULL) { + Error (NULL, 0, 3000, "Invalid", "TimeStamp cannot be NULL."); + return EFI_INVALID_PARAMETER; + } + // + // compare the value with "NOW", if yes, current system time is set. + // + if (stricmp (TimeStamp, "NOW") == 0) { + // + // get system current time and date + // + time (&newtime); + } else { + // + // Check Time Format strictly yyyy-mm-dd 00:00:00 + // + for (Index = 0; TimeStamp[Index] != '\0' && Index < 20; Index ++) { + if (Index == 4 || Index == 7) { + if (TimeStamp[Index] == '-') { + continue; + } + } else if (Index == 13 || Index == 16) { + if (TimeStamp[Index] == ':') { + continue; + } + } else if (Index == 10 && TimeStamp[Index] == ' ') { + continue; + } else if ((TimeStamp[Index] < '0') || (TimeStamp[Index] > '9')) { + break; + } + } + + if (Index < 19 || TimeStamp[19] != '\0') { + Error (NULL, 0, 1003, "Invalid option value", "Incorrect Time \"%s\"\n Correct Format \"yyyy-mm-dd 00:00:00\"", TimeStamp); + return EFI_INVALID_PARAMETER; + } + + // + // get the date and time from TimeStamp + // + if (sscanf (TimeStamp, "%d-%d-%d %d:%d:%d", + &stime.tm_year, + &stime.tm_mon, + &stime.tm_mday, + &stime.tm_hour, + &stime.tm_min, + &stime.tm_sec + ) != 6) { + Error (NULL, 0, 1003, "Invalid option value", "Incorrect Tiem \"%s\"\n Correct Format \"yyyy-mm-dd 00:00:00\"", TimeStamp); + return EFI_INVALID_PARAMETER; + } + + // + // in struct, Month (0 - 11; Jan = 0). So decrease 1 from it + // + if (stime.tm_mon <= 0 || stime.tm_mday <=0) { + Error (NULL, 0, 3000, "Invalid", "%s Invalid date!", TimeStamp); + return EFI_INVALID_PARAMETER; + } + 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 >= 1970 && stime.tm_year <= 2038) { + // + // convert 1970 -> 70, 2000 -> 100, ... + // + stime.tm_year -= 1900; + } else { + Error (NULL, 0, 3000, "Invalid", "%s Invalid or unsupported datetime!", TimeStamp); + return EFI_INVALID_PARAMETER; + } + + // + // convert the date and time to time_t format + // + newtime = mktime (&stime); + if (newtime == (time_t) - 1) { + Error (NULL, 0, 3000, "Invalid", "%s Invalid or unsupported datetime!", TimeStamp); + return EFI_INVALID_PARAMETER; + } + } + + ptime = localtime (&newtime); + DebugMsg (NULL, 0, 9, "New Image Time Stamp", "%04d-%02d-%02d %02d:%02d:%02d", + ptime->tm_year + 1900, ptime->tm_mon + 1, ptime->tm_mday, ptime->tm_hour, ptime->tm_min, ptime->tm_sec); + // + // Set new time and data into PeImage. + // + DosHdr = (EFI_IMAGE_DOS_HEADER *)FileBuffer; + if (DosHdr->e_magic != EFI_IMAGE_DOS_SIGNATURE) { + // NO DOS header, must start with PE/COFF header + FileHdr = (EFI_IMAGE_FILE_HEADER *)(FileBuffer + sizeof (UINT32)); + } else { + FileHdr = (EFI_IMAGE_FILE_HEADER *)(FileBuffer + DosHdr->e_lfanew + sizeof (UINT32)); + } + + // + // Get Debug, Export and Resource EntryTable RVA address. + // Resource Directory entry need to review. + // + if (FileHdr->Machine == EFI_IMAGE_MACHINE_IA32) { + Optional32Hdr = (EFI_IMAGE_OPTIONAL_HEADER32 *) ((UINT8*) FileHdr + sizeof (EFI_IMAGE_FILE_HEADER)); + SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) Optional32Hdr + FileHdr->SizeOfOptionalHeader); + if (Optional32Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_EXPORT && \ + Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT].Size != 0) { + ExportDirectoryEntryRva = Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress; + } + if (Optional32Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE && \ + Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].Size != 0) { + ResourceDirectoryEntryRva = Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress; + } + if (Optional32Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG && \ + Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size != 0) { + DebugDirectoryEntryRva = Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress; + } + } else { + Optional64Hdr = (EFI_IMAGE_OPTIONAL_HEADER64 *) ((UINT8*) FileHdr + sizeof (EFI_IMAGE_FILE_HEADER)); + SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) Optional64Hdr + FileHdr->SizeOfOptionalHeader); + if (Optional64Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_EXPORT && \ + Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT].Size != 0) { + ExportDirectoryEntryRva = Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress; + } + if (Optional64Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE && \ + Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].Size != 0) { + ResourceDirectoryEntryRva = Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress; + } + if (Optional64Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG && \ + Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size != 0) { + DebugDirectoryEntryRva = Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress; + } + } + + // + // Get DirectoryEntryTable file offset. + // + for (Index = 0; Index < FileHdr->NumberOfSections; Index ++, SectionHeader ++) { + if (DebugDirectoryEntryRva >= SectionHeader->VirtualAddress && + DebugDirectoryEntryRva < SectionHeader->VirtualAddress + SectionHeader->Misc.VirtualSize) { + DebugDirectoryEntryFileOffset = + DebugDirectoryEntryRva - SectionHeader->VirtualAddress + SectionHeader->PointerToRawData; + } + if (ExportDirectoryEntryRva >= SectionHeader->VirtualAddress && + ExportDirectoryEntryRva < SectionHeader->VirtualAddress + SectionHeader->Misc.VirtualSize) { + ExportDirectoryEntryFileOffset = + ExportDirectoryEntryRva - SectionHeader->VirtualAddress + SectionHeader->PointerToRawData; + } + if (ResourceDirectoryEntryRva >= SectionHeader->VirtualAddress && + ResourceDirectoryEntryRva < SectionHeader->VirtualAddress + SectionHeader->Misc.VirtualSize) { + ResourceDirectoryEntryFileOffset = + ResourceDirectoryEntryRva - SectionHeader->VirtualAddress + SectionHeader->PointerToRawData; + } + } + + // + // Set new stamp + // + FileHdr->TimeDateStamp = (UINT32) newtime; + + if (ExportDirectoryEntryRva != 0) { + NewTimeStamp = (UINT32 *) (FileBuffer + ExportDirectoryEntryFileOffset + sizeof (UINT32)); + *NewTimeStamp = (UINT32) newtime; + } + + if (ResourceDirectoryEntryRva != 0) { + NewTimeStamp = (UINT32 *) (FileBuffer + ResourceDirectoryEntryFileOffset + sizeof (UINT32)); + *NewTimeStamp = (UINT32) newtime; + } + + if (DebugDirectoryEntryRva != 0) { + NewTimeStamp = (UINT32 *) (FileBuffer + DebugDirectoryEntryFileOffset + sizeof (UINT32)); + *NewTimeStamp = (UINT32) newtime; + } + + return EFI_SUCCESS; +} + +STATIC +STATUS +MicrocodeReadData ( + FILE *InFptr, + UINT32 *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 + +--*/ +{ + CHAR8 Line[MAX_LINE_LEN]; + CHAR8 *cptr; + + Line[MAX_LINE_LEN - 1] = 0; + while (1) { + 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; + } + + // + // strip space + // + for (cptr = Line; *cptr && isspace(*cptr); cptr++) { + } + + // Skip Blank Lines and Comment Lines + if ((strlen(cptr) != 0) && (*cptr != ';')) { + break; + } + } + + // Look for + // dd 000000001h ; comment + // dd XXXXXXXX + // DD XXXXXXXXX + // DD XXXXXXXXX + // + 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; +} diff --git a/BaseTools/Source/C/GenFw/Makefile b/BaseTools/Source/C/GenFw/Makefile new file mode 100644 index 0000000000..35adfb1386 --- /dev/null +++ b/BaseTools/Source/C/GenFw/Makefile @@ -0,0 +1,12 @@ +!INCLUDE ..\Makefiles\ms.common + +APPNAME = GenFw + +LIBS = $(LIB_PATH)\Common.lib + +OBJECTS = GenFw.obj + +#CFLAGS = $(CFLAGS) /nodefaultlib:libc.lib + +!INCLUDE ..\Makefiles\ms.app + diff --git a/BaseTools/Source/C/GenFw/elf32.h b/BaseTools/Source/C/GenFw/elf32.h new file mode 100644 index 0000000000..9e47123533 --- /dev/null +++ b/BaseTools/Source/C/GenFw/elf32.h @@ -0,0 +1,244 @@ +/*- + * Copyright (c) 1996-1998 John D. Polstra. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/sys/sys/elf32.h,v 1.8.14.2 2007/12/03 21:30:36 marius Exp $ + */ + +#ifndef _SYS_ELF32_H_ +#define _SYS_ELF32_H_ 1 + + +/* + * ELF definitions common to all 32-bit architectures. + */ + +typedef UINT32 Elf32_Addr; +typedef UINT16 Elf32_Half; +typedef UINT32 Elf32_Off; +typedef INT32 Elf32_Sword; +typedef UINT32 Elf32_Word; +typedef UINT64 Elf32_Lword; + +typedef Elf32_Word Elf32_Hashelt; + +/* Non-standard class-dependent datatype used for abstraction. */ +typedef Elf32_Word Elf32_Size; +typedef Elf32_Sword Elf32_Ssize; + +/* + * ELF header. + */ + +typedef struct { + unsigned char e_ident[EI_NIDENT]; /* File identification. */ + Elf32_Half e_type; /* File type. */ + Elf32_Half e_machine; /* Machine architecture. */ + Elf32_Word e_version; /* ELF format version. */ + Elf32_Addr e_entry; /* Entry point. */ + Elf32_Off e_phoff; /* Program header file offset. */ + Elf32_Off e_shoff; /* Section header file offset. */ + Elf32_Word e_flags; /* Architecture-specific flags. */ + Elf32_Half e_ehsize; /* Size of ELF header in bytes. */ + Elf32_Half e_phentsize; /* Size of program header entry. */ + Elf32_Half e_phnum; /* Number of program header entries. */ + Elf32_Half e_shentsize; /* Size of section header entry. */ + Elf32_Half e_shnum; /* Number of section header entries. */ + Elf32_Half e_shstrndx; /* Section name strings section. */ +} Elf32_Ehdr; + +/* + * Section header. + */ + +typedef struct { + Elf32_Word sh_name; /* Section name (index into the + section header string table). */ + Elf32_Word sh_type; /* Section type. */ + Elf32_Word sh_flags; /* Section flags. */ + Elf32_Addr sh_addr; /* Address in memory image. */ + Elf32_Off sh_offset; /* Offset in file. */ + Elf32_Word sh_size; /* Size in bytes. */ + Elf32_Word sh_link; /* Index of a related section. */ + Elf32_Word sh_info; /* Depends on section type. */ + Elf32_Word sh_addralign; /* Alignment in bytes. */ + Elf32_Word sh_entsize; /* Size of each entry in section. */ +} Elf32_Shdr; + +/* + * Program header. + */ + +typedef struct { + Elf32_Word p_type; /* Entry type. */ + Elf32_Off p_offset; /* File offset of contents. */ + Elf32_Addr p_vaddr; /* Virtual address in memory image. */ + Elf32_Addr p_paddr; /* Physical address (not used). */ + Elf32_Word p_filesz; /* Size of contents in file. */ + Elf32_Word p_memsz; /* Size of contents in memory. */ + Elf32_Word p_flags; /* Access permission flags. */ + Elf32_Word p_align; /* Alignment in memory and file. */ +} Elf32_Phdr; + +/* + * Dynamic structure. The ".dynamic" section contains an array of them. + */ + +typedef struct { + Elf32_Sword d_tag; /* Entry type. */ + union { + Elf32_Word d_val; /* Integer value. */ + Elf32_Addr d_ptr; /* Address value. */ + } d_un; +} Elf32_Dyn; + +/* + * Relocation entries. + */ + +/* Relocations that don't need an addend field. */ +typedef struct { + Elf32_Addr r_offset; /* Location to be relocated. */ + Elf32_Word r_info; /* Relocation type and symbol index. */ +} Elf32_Rel; + +/* Relocations that need an addend field. */ +typedef struct { + Elf32_Addr r_offset; /* Location to be relocated. */ + Elf32_Word r_info; /* Relocation type and symbol index. */ + Elf32_Sword r_addend; /* Addend. */ +} Elf32_Rela; + +/* Macros for accessing the fields of r_info. */ +#define ELF32_R_SYM(info) ((info) >> 8) +#define ELF32_R_TYPE(info) ((unsigned char)(info)) + +/* Macro for constructing r_info from field values. */ +#define ELF32_R_INFO(sym, type) (((sym) << 8) + (unsigned char)(type)) + +/* + * Note entry header + */ +typedef Elf_Note Elf32_Nhdr; + +/* + * Move entry + */ +typedef struct { + Elf32_Lword m_value; /* symbol value */ + Elf32_Word m_info; /* size + index */ + Elf32_Word m_poffset; /* symbol offset */ + Elf32_Half m_repeat; /* repeat count */ + Elf32_Half m_stride; /* stride info */ +} Elf32_Move; + +/* + * The macros compose and decompose values for Move.r_info + * + * sym = ELF32_M_SYM(M.m_info) + * size = ELF32_M_SIZE(M.m_info) + * M.m_info = ELF32_M_INFO(sym, size) + */ +#define ELF32_M_SYM(info) ((info)>>8) +#define ELF32_M_SIZE(info) ((unsigned char)(info)) +#define ELF32_M_INFO(sym, size) (((sym)<<8)+(unsigned char)(size)) + +/* + * Hardware/Software capabilities entry + */ +typedef struct { + Elf32_Word c_tag; /* how to interpret value */ + union { + Elf32_Word c_val; + Elf32_Addr c_ptr; + } c_un; +} Elf32_Cap; + +/* + * Symbol table entries. + */ + +typedef struct { + Elf32_Word st_name; /* String table index of name. */ + Elf32_Addr st_value; /* Symbol value. */ + Elf32_Word st_size; /* Size of associated object. */ + unsigned char st_info; /* Type and binding information. */ + unsigned char st_other; /* Reserved (not used). */ + Elf32_Half st_shndx; /* Section index of symbol. */ +} Elf32_Sym; + +/* Macros for accessing the fields of st_info. */ +#define ELF32_ST_BIND(info) ((info) >> 4) +#define ELF32_ST_TYPE(info) ((info) & 0xf) + +/* Macro for constructing st_info from field values. */ +#define ELF32_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf)) + +/* Macro for accessing the fields of st_other. */ +#define ELF32_ST_VISIBILITY(oth) ((oth) & 0x3) + +/* Structures used by Sun & GNU symbol versioning. */ +typedef struct +{ + Elf32_Half vd_version; + Elf32_Half vd_flags; + Elf32_Half vd_ndx; + Elf32_Half vd_cnt; + Elf32_Word vd_hash; + Elf32_Word vd_aux; + Elf32_Word vd_next; +} Elf32_Verdef; + +typedef struct +{ + Elf32_Word vda_name; + Elf32_Word vda_next; +} Elf32_Verdaux; + +typedef struct +{ + Elf32_Half vn_version; + Elf32_Half vn_cnt; + Elf32_Word vn_file; + Elf32_Word vn_aux; + Elf32_Word vn_next; +} Elf32_Verneed; + +typedef struct +{ + Elf32_Word vna_hash; + Elf32_Half vna_flags; + Elf32_Half vna_other; + Elf32_Word vna_name; + Elf32_Word vna_next; +} Elf32_Vernaux; + +typedef Elf32_Half Elf32_Versym; + +typedef struct { + Elf32_Half si_boundto; /* direct bindings - symbol bound to */ + Elf32_Half si_flags; /* per symbol flags */ +} Elf32_Syminfo; + +#endif /* !_SYS_ELF32_H_ */ diff --git a/BaseTools/Source/C/GenFw/elf64.h b/BaseTools/Source/C/GenFw/elf64.h new file mode 100644 index 0000000000..9960888940 --- /dev/null +++ b/BaseTools/Source/C/GenFw/elf64.h @@ -0,0 +1,247 @@ +/*- + * Copyright (c) 1996-1998 John D. Polstra. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/sys/sys/elf64.h,v 1.10.14.2 2007/12/03 21:30:36 marius Exp $ + */ + +#ifndef _SYS_ELF64_H_ +#define _SYS_ELF64_H_ 1 + + +/* + * ELF definitions common to all 64-bit architectures. + */ + +typedef UINT64 Elf64_Addr; +typedef UINT16 Elf64_Half; +typedef UINT64 Elf64_Off; +typedef INT32 Elf64_Sword; +typedef INT64 Elf64_Sxword; +typedef UINT32 Elf64_Word; +typedef UINT64 Elf64_Lword; +typedef UINT64 Elf64_Xword; + +/* + * Types of dynamic symbol hash table bucket and chain elements. + * + * This is inconsistent among 64 bit architectures, so a machine dependent + * typedef is required. + */ + +typedef Elf64_Word Elf64_Hashelt; + +/* Non-standard class-dependent datatype used for abstraction. */ +typedef Elf64_Xword Elf64_Size; +typedef Elf64_Sxword Elf64_Ssize; + +/* + * ELF header. + */ + +typedef struct { + unsigned char e_ident[EI_NIDENT]; /* File identification. */ + Elf64_Half e_type; /* File type. */ + Elf64_Half e_machine; /* Machine architecture. */ + Elf64_Word e_version; /* ELF format version. */ + Elf64_Addr e_entry; /* Entry point. */ + Elf64_Off e_phoff; /* Program header file offset. */ + Elf64_Off e_shoff; /* Section header file offset. */ + Elf64_Word e_flags; /* Architecture-specific flags. */ + Elf64_Half e_ehsize; /* Size of ELF header in bytes. */ + Elf64_Half e_phentsize; /* Size of program header entry. */ + Elf64_Half e_phnum; /* Number of program header entries. */ + Elf64_Half e_shentsize; /* Size of section header entry. */ + Elf64_Half e_shnum; /* Number of section header entries. */ + Elf64_Half e_shstrndx; /* Section name strings section. */ +} Elf64_Ehdr; + +/* + * Section header. + */ + +typedef struct { + Elf64_Word sh_name; /* Section name (index into the + section header string table). */ + Elf64_Word sh_type; /* Section type. */ + Elf64_Xword sh_flags; /* Section flags. */ + Elf64_Addr sh_addr; /* Address in memory image. */ + Elf64_Off sh_offset; /* Offset in file. */ + Elf64_Xword sh_size; /* Size in bytes. */ + Elf64_Word sh_link; /* Index of a related section. */ + Elf64_Word sh_info; /* Depends on section type. */ + Elf64_Xword sh_addralign; /* Alignment in bytes. */ + Elf64_Xword sh_entsize; /* Size of each entry in section. */ +} Elf64_Shdr; + +/* + * Program header. + */ + +typedef struct { + Elf64_Word p_type; /* Entry type. */ + Elf64_Word p_flags; /* Access permission flags. */ + Elf64_Off p_offset; /* File offset of contents. */ + Elf64_Addr p_vaddr; /* Virtual address in memory image. */ + Elf64_Addr p_paddr; /* Physical address (not used). */ + Elf64_Xword p_filesz; /* Size of contents in file. */ + Elf64_Xword p_memsz; /* Size of contents in memory. */ + Elf64_Xword p_align; /* Alignment in memory and file. */ +} Elf64_Phdr; + +/* + * Dynamic structure. The ".dynamic" section contains an array of them. + */ + +typedef struct { + Elf64_Sxword d_tag; /* Entry type. */ + union { + Elf64_Xword d_val; /* Integer value. */ + Elf64_Addr d_ptr; /* Address value. */ + } d_un; +} Elf64_Dyn; + +/* + * Relocation entries. + */ + +/* Relocations that don't need an addend field. */ +typedef struct { + Elf64_Addr r_offset; /* Location to be relocated. */ + Elf64_Xword r_info; /* Relocation type and symbol index. */ +} Elf64_Rel; + +/* Relocations that need an addend field. */ +typedef struct { + Elf64_Addr r_offset; /* Location to be relocated. */ + Elf64_Xword r_info; /* Relocation type and symbol index. */ + Elf64_Sxword r_addend; /* Addend. */ +} Elf64_Rela; + +/* Macros for accessing the fields of r_info. */ +#define ELF64_R_SYM(info) ((info) >> 32) +#define ELF64_R_TYPE(info) ((info) & 0xffffffffL) + +/* Macro for constructing r_info from field values. */ +#define ELF64_R_INFO(sym, type) (((sym) << 32) + ((type) & 0xffffffffL)) + +#define ELF64_R_TYPE_DATA(info) (((Elf64_Xword)(info)<<32)>>40) +#define ELF64_R_TYPE_ID(info) (((Elf64_Xword)(info)<<56)>>56) +#define ELF64_R_TYPE_INFO(data, type) \ + (((Elf64_Xword)(data)<<8)+(Elf64_Xword)(type)) + +/* + * Note entry header + */ +typedef Elf_Note Elf64_Nhdr; + +/* + * Move entry + */ +typedef struct { + Elf64_Lword m_value; /* symbol value */ + Elf64_Xword m_info; /* size + index */ + Elf64_Xword m_poffset; /* symbol offset */ + Elf64_Half m_repeat; /* repeat count */ + Elf64_Half m_stride; /* stride info */ +} Elf64_Move; + +#define ELF64_M_SYM(info) ((info)>>8) +#define ELF64_M_SIZE(info) ((unsigned char)(info)) +#define ELF64_M_INFO(sym, size) (((sym)<<8)+(unsigned char)(size)) + +/* + * Hardware/Software capabilities entry + */ +typedef struct { + Elf64_Xword c_tag; /* how to interpret value */ + union { + Elf64_Xword c_val; + Elf64_Addr c_ptr; + } c_un; +} Elf64_Cap; + +/* + * Symbol table entries. + */ + +typedef struct { + Elf64_Word st_name; /* String table index of name. */ + unsigned char st_info; /* Type and binding information. */ + unsigned char st_other; /* Reserved (not used). */ + Elf64_Half st_shndx; /* Section index of symbol. */ + Elf64_Addr st_value; /* Symbol value. */ + Elf64_Xword st_size; /* Size of associated object. */ +} Elf64_Sym; + +/* Macros for accessing the fields of st_info. */ +#define ELF64_ST_BIND(info) ((info) >> 4) +#define ELF64_ST_TYPE(info) ((info) & 0xf) + +/* Macro for constructing st_info from field values. */ +#define ELF64_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf)) + +/* Macro for accessing the fields of st_other. */ +#define ELF64_ST_VISIBILITY(oth) ((oth) & 0x3) + +/* Structures used by Sun & GNU-style symbol versioning. */ +typedef struct { + Elf64_Half vd_version; + Elf64_Half vd_flags; + Elf64_Half vd_ndx; + Elf64_Half vd_cnt; + Elf64_Word vd_hash; + Elf64_Word vd_aux; + Elf64_Word vd_next; +} Elf64_Verdef; + +typedef struct { + Elf64_Word vda_name; + Elf64_Word vda_next; +} Elf64_Verdaux; + +typedef struct { + Elf64_Half vn_version; + Elf64_Half vn_cnt; + Elf64_Word vn_file; + Elf64_Word vn_aux; + Elf64_Word vn_next; +} Elf64_Verneed; + +typedef struct { + Elf64_Word vna_hash; + Elf64_Half vna_flags; + Elf64_Half vna_other; + Elf64_Word vna_name; + Elf64_Word vna_next; +} Elf64_Vernaux; + +typedef Elf64_Half Elf64_Versym; + +typedef struct { + Elf64_Half si_boundto; /* direct bindings - symbol bound to */ + Elf64_Half si_flags; /* per symbol flags */ +} Elf64_Syminfo; + +#endif /* !_SYS_ELF64_H_ */ diff --git a/BaseTools/Source/C/GenFw/elf_common.h b/BaseTools/Source/C/GenFw/elf_common.h new file mode 100644 index 0000000000..471c2650a1 --- /dev/null +++ b/BaseTools/Source/C/GenFw/elf_common.h @@ -0,0 +1,872 @@ +/*- + * Copyright (c) 1998 John D. Polstra. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/sys/sys/elf_common.h,v 1.15.8.2 2007/12/03 21:30:36 marius Exp $ + */ + +#ifndef _SYS_ELF_COMMON_H_ +#define _SYS_ELF_COMMON_H_ 1 + +/* + * ELF definitions that are independent of architecture or word size. + */ + +/* + * Note header. The ".note" section contains an array of notes. Each + * begins with this header, aligned to a word boundary. Immediately + * following the note header is n_namesz bytes of name, padded to the + * next word boundary. Then comes n_descsz bytes of descriptor, again + * padded to a word boundary. The values of n_namesz and n_descsz do + * not include the padding. + */ + +typedef struct { + UINT32 n_namesz; /* Length of name. */ + UINT32 n_descsz; /* Length of descriptor. */ + UINT32 n_type; /* Type of this note. */ +} Elf_Note; + +/* Indexes into the e_ident array. Keep synced with + http://www.sco.com/developers/gabi/latest/ch4.eheader.html */ +#define EI_MAG0 0 /* Magic number, byte 0. */ +#define EI_MAG1 1 /* Magic number, byte 1. */ +#define EI_MAG2 2 /* Magic number, byte 2. */ +#define EI_MAG3 3 /* Magic number, byte 3. */ +#define EI_CLASS 4 /* Class of machine. */ +#define EI_DATA 5 /* Data format. */ +#define EI_VERSION 6 /* ELF format version. */ +#define EI_OSABI 7 /* Operating system / ABI identification */ +#define EI_ABIVERSION 8 /* ABI version */ +#define OLD_EI_BRAND 8 /* Start of architecture identification. */ +#define EI_PAD 9 /* Start of padding (per SVR4 ABI). */ +#define EI_NIDENT 16 /* Size of e_ident array. */ + +/* Values for the magic number bytes. */ +#define ELFMAG0 0x7f +#define ELFMAG1 'E' +#define ELFMAG2 'L' +#define ELFMAG3 'F' +#define ELFMAG "\177ELF" /* magic string */ +#define SELFMAG 4 /* magic string size */ + +/* Values for e_ident[EI_VERSION] and e_version. */ +#define EV_NONE 0 +#define EV_CURRENT 1 + +/* Values for e_ident[EI_CLASS]. */ +#define ELFCLASSNONE 0 /* Unknown class. */ +#define ELFCLASS32 1 /* 32-bit architecture. */ +#define ELFCLASS64 2 /* 64-bit architecture. */ + +/* Values for e_ident[EI_DATA]. */ +#define ELFDATANONE 0 /* Unknown data format. */ +#define ELFDATA2LSB 1 /* 2's complement little-endian. */ +#define ELFDATA2MSB 2 /* 2's complement big-endian. */ + +/* Values for e_ident[EI_OSABI]. */ +#define ELFOSABI_NONE 0 /* UNIX System V ABI */ +#define ELFOSABI_HPUX 1 /* HP-UX operating system */ +#define ELFOSABI_NETBSD 2 /* NetBSD */ +#define ELFOSABI_LINUX 3 /* GNU/Linux */ +#define ELFOSABI_HURD 4 /* GNU/Hurd */ +#define ELFOSABI_86OPEN 5 /* 86Open common IA32 ABI */ +#define ELFOSABI_SOLARIS 6 /* Solaris */ +#define ELFOSABI_AIX 7 /* AIX */ +#define ELFOSABI_IRIX 8 /* IRIX */ +#define ELFOSABI_FREEBSD 9 /* FreeBSD */ +#define ELFOSABI_TRU64 10 /* TRU64 UNIX */ +#define ELFOSABI_MODESTO 11 /* Novell Modesto */ +#define ELFOSABI_OPENBSD 12 /* OpenBSD */ +#define ELFOSABI_OPENVMS 13 /* Open VMS */ +#define ELFOSABI_NSK 14 /* HP Non-Stop Kernel */ +#define ELFOSABI_ARM 97 /* ARM */ +#define ELFOSABI_STANDALONE 255 /* Standalone (embedded) application */ + +#define ELFOSABI_SYSV ELFOSABI_NONE /* symbol used in old spec */ +#define ELFOSABI_MONTEREY ELFOSABI_AIX /* Monterey */ + +/* e_ident */ +#define IS_ELF(ehdr) ((ehdr).e_ident[EI_MAG0] == ELFMAG0 && \ + (ehdr).e_ident[EI_MAG1] == ELFMAG1 && \ + (ehdr).e_ident[EI_MAG2] == ELFMAG2 && \ + (ehdr).e_ident[EI_MAG3] == ELFMAG3) + +/* Values for e_type. */ +#define ET_NONE 0 /* Unknown type. */ +#define ET_REL 1 /* Relocatable. */ +#define ET_EXEC 2 /* Executable. */ +#define ET_DYN 3 /* Shared object. */ +#define ET_CORE 4 /* Core file. */ +#define ET_LOOS 0xfe00 /* First operating system specific. */ +#define ET_HIOS 0xfeff /* Last operating system-specific. */ +#define ET_LOPROC 0xff00 /* First processor-specific. */ +#define ET_HIPROC 0xffff /* Last processor-specific. */ + +/* Values for e_machine. */ +#define EM_NONE 0 /* Unknown machine. */ +#define EM_M32 1 /* AT&T WE32100. */ +#define EM_SPARC 2 /* Sun SPARC. */ +#define EM_386 3 /* Intel i386. */ +#define EM_68K 4 /* Motorola 68000. */ +#define EM_88K 5 /* Motorola 88000. */ +#define EM_860 7 /* Intel i860. */ +#define EM_MIPS 8 /* MIPS R3000 Big-Endian only. */ +#define EM_S370 9 /* IBM System/370. */ +#define EM_MIPS_RS3_LE 10 /* MIPS R3000 Little-Endian. */ +#define EM_PARISC 15 /* HP PA-RISC. */ +#define EM_VPP500 17 /* Fujitsu VPP500. */ +#define EM_SPARC32PLUS 18 /* SPARC v8plus. */ +#define EM_960 19 /* Intel 80960. */ +#define EM_PPC 20 /* PowerPC 32-bit. */ +#define EM_PPC64 21 /* PowerPC 64-bit. */ +#define EM_S390 22 /* IBM System/390. */ +#define EM_V800 36 /* NEC V800. */ +#define EM_FR20 37 /* Fujitsu FR20. */ +#define EM_RH32 38 /* TRW RH-32. */ +#define EM_RCE 39 /* Motorola RCE. */ +#define EM_ARM 40 /* ARM. */ +#define EM_SH 42 /* Hitachi SH. */ +#define EM_SPARCV9 43 /* SPARC v9 64-bit. */ +#define EM_TRICORE 44 /* Siemens TriCore embedded processor. */ +#define EM_ARC 45 /* Argonaut RISC Core. */ +#define EM_H8_300 46 /* Hitachi H8/300. */ +#define EM_H8_300H 47 /* Hitachi H8/300H. */ +#define EM_H8S 48 /* Hitachi H8S. */ +#define EM_H8_500 49 /* Hitachi H8/500. */ +#define EM_IA_64 50 /* Intel IA-64 Processor. */ +#define EM_MIPS_X 51 /* Stanford MIPS-X. */ +#define EM_COLDFIRE 52 /* Motorola ColdFire. */ +#define EM_68HC12 53 /* Motorola M68HC12. */ +#define EM_MMA 54 /* Fujitsu MMA. */ +#define EM_PCP 55 /* Siemens PCP. */ +#define EM_NCPU 56 /* Sony nCPU. */ +#define EM_NDR1 57 /* Denso NDR1 microprocessor. */ +#define EM_STARCORE 58 /* Motorola Star*Core processor. */ +#define EM_ME16 59 /* Toyota ME16 processor. */ +#define EM_ST100 60 /* STMicroelectronics ST100 processor. */ +#define EM_TINYJ 61 /* Advanced Logic Corp. TinyJ processor. */ +#define EM_X86_64 62 /* Advanced Micro Devices x86-64 */ +#define EM_AMD64 EM_X86_64 /* Advanced Micro Devices x86-64 (compat) */ + +/* Non-standard or deprecated. */ +#define EM_486 6 /* Intel i486. */ +#define EM_MIPS_RS4_BE 10 /* MIPS R4000 Big-Endian */ +#define EM_ALPHA_STD 41 /* Digital Alpha (standard value). */ +#define EM_ALPHA 0x9026 /* Alpha (written in the absence of an ABI) */ + +/* Special section indexes. */ +#define SHN_UNDEF 0 /* Undefined, missing, irrelevant. */ +#define SHN_LORESERVE 0xff00 /* First of reserved range. */ +#define SHN_LOPROC 0xff00 /* First processor-specific. */ +#define SHN_HIPROC 0xff1f /* Last processor-specific. */ +#define SHN_LOOS 0xff20 /* First operating system-specific. */ +#define SHN_HIOS 0xff3f /* Last operating system-specific. */ +#define SHN_ABS 0xfff1 /* Absolute values. */ +#define SHN_COMMON 0xfff2 /* Common data. */ +#define SHN_XINDEX 0xffff /* Escape -- index stored elsewhere. */ +#define SHN_HIRESERVE 0xffff /* Last of reserved range. */ + +/* sh_type */ +#define SHT_NULL 0 /* inactive */ +#define SHT_PROGBITS 1 /* program defined information */ +#define SHT_SYMTAB 2 /* symbol table section */ +#define SHT_STRTAB 3 /* string table section */ +#define SHT_RELA 4 /* relocation section with addends */ +#define SHT_HASH 5 /* symbol hash table section */ +#define SHT_DYNAMIC 6 /* dynamic section */ +#define SHT_NOTE 7 /* note section */ +#define SHT_NOBITS 8 /* no space section */ +#define SHT_REL 9 /* relocation section - no addends */ +#define SHT_SHLIB 10 /* reserved - purpose unknown */ +#define SHT_DYNSYM 11 /* dynamic symbol table section */ +#define SHT_INIT_ARRAY 14 /* Initialization function pointers. */ +#define SHT_FINI_ARRAY 15 /* Termination function pointers. */ +#define SHT_PREINIT_ARRAY 16 /* Pre-initialization function ptrs. */ +#define SHT_GROUP 17 /* Section group. */ +#define SHT_SYMTAB_SHNDX 18 /* Section indexes (see SHN_XINDEX). */ +#define SHT_LOOS 0x60000000 /* First of OS specific semantics */ +#define SHT_LOSUNW 0x6ffffff4 +#define SHT_SUNW_dof 0x6ffffff4 +#define SHT_SUNW_cap 0x6ffffff5 +#define SHT_SUNW_SIGNATURE 0x6ffffff6 +#define SHT_SUNW_ANNOTATE 0x6ffffff7 +#define SHT_SUNW_DEBUGSTR 0x6ffffff8 +#define SHT_SUNW_DEBUG 0x6ffffff9 +#define SHT_SUNW_move 0x6ffffffa +#define SHT_SUNW_COMDAT 0x6ffffffb +#define SHT_SUNW_syminfo 0x6ffffffc +#define SHT_SUNW_verdef 0x6ffffffd +#define SHT_GNU_verdef 0x6ffffffd /* Symbol versions provided */ +#define SHT_SUNW_verneed 0x6ffffffe +#define SHT_GNU_verneed 0x6ffffffe /* Symbol versions required */ +#define SHT_SUNW_versym 0x6fffffff +#define SHT_GNU_versym 0x6fffffff /* Symbol version table */ +#define SHT_HISUNW 0x6fffffff +#define SHT_HIOS 0x6fffffff /* Last of OS specific semantics */ +#define SHT_LOPROC 0x70000000 /* reserved range for processor */ +#define SHT_AMD64_UNWIND 0x70000001 /* unwind information */ +#define SHT_HIPROC 0x7fffffff /* specific section header types */ +#define SHT_LOUSER 0x80000000 /* reserved range for application */ +#define SHT_HIUSER 0xffffffff /* specific indexes */ + +/* Flags for sh_flags. */ +#define SHF_WRITE 0x1 /* Section contains writable data. */ +#define SHF_ALLOC 0x2 /* Section occupies memory. */ +#define SHF_EXECINSTR 0x4 /* Section contains instructions. */ +#define SHF_MERGE 0x10 /* Section may be merged. */ +#define SHF_STRINGS 0x20 /* Section contains strings. */ +#define SHF_INFO_LINK 0x40 /* sh_info holds section index. */ +#define SHF_LINK_ORDER 0x80 /* Special ordering requirements. */ +#define SHF_OS_NONCONFORMING 0x100 /* OS-specific processing required. */ +#define SHF_GROUP 0x200 /* Member of section group. */ +#define SHF_TLS 0x400 /* Section contains TLS data. */ +#define SHF_MASKOS 0x0ff00000 /* OS-specific semantics. */ +#define SHF_MASKPROC 0xf0000000 /* Processor-specific semantics. */ + +/* Values for p_type. */ +#define PT_NULL 0 /* Unused entry. */ +#define PT_LOAD 1 /* Loadable segment. */ +#define PT_DYNAMIC 2 /* Dynamic linking information segment. */ +#define PT_INTERP 3 /* Pathname of interpreter. */ +#define PT_NOTE 4 /* Auxiliary information. */ +#define PT_SHLIB 5 /* Reserved (not used). */ +#define PT_PHDR 6 /* Location of program header itself. */ +#define PT_TLS 7 /* Thread local storage segment */ +#define PT_LOOS 0x60000000 /* First OS-specific. */ +#define PT_SUNW_UNWIND 0x6464e550 /* amd64 UNWIND program header */ +#define PT_GNU_EH_FRAME 0x6474e550 +#define PT_LOSUNW 0x6ffffffa +#define PT_SUNWBSS 0x6ffffffa /* Sun Specific segment */ +#define PT_SUNWSTACK 0x6ffffffb /* describes the stack segment */ +#define PT_SUNWDTRACE 0x6ffffffc /* private */ +#define PT_SUNWCAP 0x6ffffffd /* hard/soft capabilities segment */ +#define PT_HISUNW 0x6fffffff +#define PT_HIOS 0x6fffffff /* Last OS-specific. */ +#define PT_LOPROC 0x70000000 /* First processor-specific type. */ +#define PT_HIPROC 0x7fffffff /* Last processor-specific type. */ + +/* Values for p_flags. */ +#define PF_X 0x1 /* Executable. */ +#define PF_W 0x2 /* Writable. */ +#define PF_R 0x4 /* Readable. */ +#define PF_MASKOS 0x0ff00000 /* Operating system-specific. */ +#define PF_MASKPROC 0xf0000000 /* Processor-specific. */ + +/* Extended program header index. */ +#define PN_XNUM 0xffff + +/* Values for d_tag. */ +#define DT_NULL 0 /* Terminating entry. */ +#define DT_NEEDED 1 /* String table offset of a needed shared + library. */ +#define DT_PLTRELSZ 2 /* Total size in bytes of PLT relocations. */ +#define DT_PLTGOT 3 /* Processor-dependent address. */ +#define DT_HASH 4 /* Address of symbol hash table. */ +#define DT_STRTAB 5 /* Address of string table. */ +#define DT_SYMTAB 6 /* Address of symbol table. */ +#define DT_RELA 7 /* Address of ElfNN_Rela relocations. */ +#define DT_RELASZ 8 /* Total size of ElfNN_Rela relocations. */ +#define DT_RELAENT 9 /* Size of each ElfNN_Rela relocation entry. */ +#define DT_STRSZ 10 /* Size of string table. */ +#define DT_SYMENT 11 /* Size of each symbol table entry. */ +#define DT_INIT 12 /* Address of initialization function. */ +#define DT_FINI 13 /* Address of finalization function. */ +#define DT_SONAME 14 /* String table offset of shared object + name. */ +#define DT_RPATH 15 /* String table offset of library path. [sup] */ +#define DT_SYMBOLIC 16 /* Indicates "symbolic" linking. [sup] */ +#define DT_REL 17 /* Address of ElfNN_Rel relocations. */ +#define DT_RELSZ 18 /* Total size of ElfNN_Rel relocations. */ +#define DT_RELENT 19 /* Size of each ElfNN_Rel relocation. */ +#define DT_PLTREL 20 /* Type of relocation used for PLT. */ +#define DT_DEBUG 21 /* Reserved (not used). */ +#define DT_TEXTREL 22 /* Indicates there may be relocations in + non-writable segments. [sup] */ +#define DT_JMPREL 23 /* Address of PLT relocations. */ +#define DT_BIND_NOW 24 /* [sup] */ +#define DT_INIT_ARRAY 25 /* Address of the array of pointers to + initialization functions */ +#define DT_FINI_ARRAY 26 /* Address of the array of pointers to + termination functions */ +#define DT_INIT_ARRAYSZ 27 /* Size in bytes of the array of + initialization functions. */ +#define DT_FINI_ARRAYSZ 28 /* Size in bytes of the array of + terminationfunctions. */ +#define DT_RUNPATH 29 /* String table offset of a null-terminated + library search path string. */ +#define DT_FLAGS 30 /* Object specific flag values. */ +#define DT_ENCODING 32 /* Values greater than or equal to DT_ENCODING + and less than DT_LOOS follow the rules for + the interpretation of the d_un union + as follows: even == 'd_ptr', even == 'd_val' + or none */ +#define DT_PREINIT_ARRAY 32 /* Address of the array of pointers to + pre-initialization functions. */ +#define DT_PREINIT_ARRAYSZ 33 /* Size in bytes of the array of + pre-initialization functions. */ +#define DT_MAXPOSTAGS 34 /* number of positive tags */ +#define DT_LOOS 0x6000000d /* First OS-specific */ +#define DT_SUNW_AUXILIARY 0x6000000d /* symbol auxiliary name */ +#define DT_SUNW_RTLDINF 0x6000000e /* ld.so.1 info (private) */ +#define DT_SUNW_FILTER 0x6000000f /* symbol filter name */ +#define DT_SUNW_CAP 0x60000010 /* hardware/software */ +#define DT_HIOS 0x6ffff000 /* Last OS-specific */ + +/* + * DT_* entries which fall between DT_VALRNGHI & DT_VALRNGLO use the + * Dyn.d_un.d_val field of the Elf*_Dyn structure. + */ +#define DT_VALRNGLO 0x6ffffd00 +#define DT_CHECKSUM 0x6ffffdf8 /* elf checksum */ +#define DT_PLTPADSZ 0x6ffffdf9 /* pltpadding size */ +#define DT_MOVEENT 0x6ffffdfa /* move table entry size */ +#define DT_MOVESZ 0x6ffffdfb /* move table size */ +#define DT_FEATURE_1 0x6ffffdfc /* feature holder */ +#define DT_POSFLAG_1 0x6ffffdfd /* flags for DT_* entries, effecting */ + /* the following DT_* entry. */ + /* See DF_P1_* definitions */ +#define DT_SYMINSZ 0x6ffffdfe /* syminfo table size (in bytes) */ +#define DT_SYMINENT 0x6ffffdff /* syminfo entry size (in bytes) */ +#define DT_VALRNGHI 0x6ffffdff + +/* + * DT_* entries which fall between DT_ADDRRNGHI & DT_ADDRRNGLO use the + * Dyn.d_un.d_ptr field of the Elf*_Dyn structure. + * + * If any adjustment is made to the ELF object after it has been + * built, these entries will need to be adjusted. + */ +#define DT_ADDRRNGLO 0x6ffffe00 +#define DT_CONFIG 0x6ffffefa /* configuration information */ +#define DT_DEPAUDIT 0x6ffffefb /* dependency auditing */ +#define DT_AUDIT 0x6ffffefc /* object auditing */ +#define DT_PLTPAD 0x6ffffefd /* pltpadding (sparcv9) */ +#define DT_MOVETAB 0x6ffffefe /* move table */ +#define DT_SYMINFO 0x6ffffeff /* syminfo table */ +#define DT_ADDRRNGHI 0x6ffffeff + +#define DT_VERSYM 0x6ffffff0 /* Address of versym section. */ +#define DT_RELACOUNT 0x6ffffff9 /* number of RELATIVE relocations */ +#define DT_RELCOUNT 0x6ffffffa /* number of RELATIVE relocations */ +#define DT_FLAGS_1 0x6ffffffb /* state flags - see DF_1_* defs */ +#define DT_VERDEF 0x6ffffffc /* Address of verdef section. */ +#define DT_VERDEFNUM 0x6ffffffd /* Number of elems in verdef section */ +#define DT_VERNEED 0x6ffffffe /* Address of verneed section. */ +#define DT_VERNEEDNUM 0x6fffffff /* Number of elems in verneed section */ + +#define DT_LOPROC 0x70000000 /* First processor-specific type. */ +#define DT_DEPRECATED_SPARC_REGISTER 0x7000001 +#define DT_AUXILIARY 0x7ffffffd /* shared library auxiliary name */ +#define DT_USED 0x7ffffffe /* ignored - same as needed */ +#define DT_FILTER 0x7fffffff /* shared library filter name */ +#define DT_HIPROC 0x7fffffff /* Last processor-specific type. */ + +/* Values for DT_FLAGS */ +#define DF_ORIGIN 0x0001 /* Indicates that the object being loaded may + make reference to the $ORIGIN substitution + string */ +#define DF_SYMBOLIC 0x0002 /* Indicates "symbolic" linking. */ +#define DF_TEXTREL 0x0004 /* Indicates there may be relocations in + non-writable segments. */ +#define DF_BIND_NOW 0x0008 /* Indicates that the dynamic linker should + process all relocations for the object + containing this entry before transferring + control to the program. */ +#define DF_STATIC_TLS 0x0010 /* Indicates that the shared object or + executable contains code using a static + thread-local storage scheme. */ + +/* Values for n_type. Used in core files. */ +#define NT_PRSTATUS 1 /* Process status. */ +#define NT_FPREGSET 2 /* Floating point registers. */ +#define NT_PRPSINFO 3 /* Process state info. */ + +/* Symbol Binding - ELFNN_ST_BIND - st_info */ +#define STB_LOCAL 0 /* Local symbol */ +#define STB_GLOBAL 1 /* Global symbol */ +#define STB_WEAK 2 /* like global - lower precedence */ +#define STB_LOOS 10 /* Reserved range for operating system */ +#define STB_HIOS 12 /* specific semantics. */ +#define STB_LOPROC 13 /* reserved range for processor */ +#define STB_HIPROC 15 /* specific semantics. */ + +/* Symbol type - ELFNN_ST_TYPE - st_info */ +#define STT_NOTYPE 0 /* Unspecified type. */ +#define STT_OBJECT 1 /* Data object. */ +#define STT_FUNC 2 /* Function. */ +#define STT_SECTION 3 /* Section. */ +#define STT_FILE 4 /* Source file. */ +#define STT_COMMON 5 /* Uninitialized common block. */ +#define STT_TLS 6 /* TLS object. */ +#define STT_NUM 7 +#define STT_LOOS 10 /* Reserved range for operating system */ +#define STT_HIOS 12 /* specific semantics. */ +#define STT_LOPROC 13 /* reserved range for processor */ +#define STT_HIPROC 15 /* specific semantics. */ + +/* Symbol visibility - ELFNN_ST_VISIBILITY - st_other */ +#define STV_DEFAULT 0x0 /* Default visibility (see binding). */ +#define STV_INTERNAL 0x1 /* Special meaning in relocatable objects. */ +#define STV_HIDDEN 0x2 /* Not visible. */ +#define STV_PROTECTED 0x3 /* Visible but not preemptible. */ + +/* Special symbol table indexes. */ +#define STN_UNDEF 0 /* Undefined symbol index. */ + +/* Symbol versioning flags. */ +#define VER_DEF_CURRENT 1 +#define VER_DEF_IDX(x) VER_NDX(x) + +#define VER_FLG_BASE 0x01 +#define VER_FLG_WEAK 0x02 + +#define VER_NEED_CURRENT 1 +#define VER_NEED_WEAK (1u << 15) +#define VER_NEED_HIDDEN VER_NDX_HIDDEN +#define VER_NEED_IDX(x) VER_NDX(x) + +#define VER_NDX_LOCAL 0 +#define VER_NDX_GLOBAL 1 +#define VER_NDX_GIVEN 2 + +#define VER_NDX_HIDDEN (1u << 15) +#define VER_NDX(x) ((x) & ~(1u << 15)) + +#define CA_SUNW_NULL 0 +#define CA_SUNW_HW_1 1 /* first hardware capabilities entry */ +#define CA_SUNW_SF_1 2 /* first software capabilities entry */ + +/* + * Syminfo flag values + */ +#define SYMINFO_FLG_DIRECT 0x0001 /* symbol ref has direct association */ + /* to object containing defn. */ +#define SYMINFO_FLG_PASSTHRU 0x0002 /* ignored - see SYMINFO_FLG_FILTER */ +#define SYMINFO_FLG_COPY 0x0004 /* symbol is a copy-reloc */ +#define SYMINFO_FLG_LAZYLOAD 0x0008 /* object containing defn should be */ + /* lazily-loaded */ +#define SYMINFO_FLG_DIRECTBIND 0x0010 /* ref should be bound directly to */ + /* object containing defn. */ +#define SYMINFO_FLG_NOEXTDIRECT 0x0020 /* don't let an external reference */ + /* directly bind to this symbol */ +#define SYMINFO_FLG_FILTER 0x0002 /* symbol ref is associated to a */ +#define SYMINFO_FLG_AUXILIARY 0x0040 /* standard or auxiliary filter */ + +/* + * Syminfo.si_boundto values. + */ +#define SYMINFO_BT_SELF 0xffff /* symbol bound to self */ +#define SYMINFO_BT_PARENT 0xfffe /* symbol bound to parent */ +#define SYMINFO_BT_NONE 0xfffd /* no special symbol binding */ +#define SYMINFO_BT_EXTERN 0xfffc /* symbol defined as external */ +#define SYMINFO_BT_LOWRESERVE 0xff00 /* beginning of reserved entries */ + +/* + * Syminfo version values. + */ +#define SYMINFO_NONE 0 /* Syminfo version */ +#define SYMINFO_CURRENT 1 +#define SYMINFO_NUM 2 + +/* + * Relocation types. + * + * All machine architectures are defined here to allow tools on one to + * handle others. + */ + +#define R_386_NONE 0 /* No relocation. */ +#define R_386_32 1 /* Add symbol value. */ +#define R_386_PC32 2 /* Add PC-relative symbol value. */ +#define R_386_GOT32 3 /* Add PC-relative GOT offset. */ +#define R_386_PLT32 4 /* Add PC-relative PLT offset. */ +#define R_386_COPY 5 /* Copy data from shared object. */ +#define R_386_GLOB_DAT 6 /* Set GOT entry to data address. */ +#define R_386_JMP_SLOT 7 /* Set GOT entry to code address. */ +#define R_386_RELATIVE 8 /* Add load address of shared object. */ +#define R_386_GOTOFF 9 /* Add GOT-relative symbol address. */ +#define R_386_GOTPC 10 /* Add PC-relative GOT table address. */ +#define R_386_TLS_TPOFF 14 /* Negative offset in static TLS block */ +#define R_386_TLS_IE 15 /* Absolute address of GOT for -ve static TLS */ +#define R_386_TLS_GOTIE 16 /* GOT entry for negative static TLS block */ +#define R_386_TLS_LE 17 /* Negative offset relative to static TLS */ +#define R_386_TLS_GD 18 /* 32 bit offset to GOT (index,off) pair */ +#define R_386_TLS_LDM 19 /* 32 bit offset to GOT (index,zero) pair */ +#define R_386_TLS_GD_32 24 /* 32 bit offset to GOT (index,off) pair */ +#define R_386_TLS_GD_PUSH 25 /* pushl instruction for Sun ABI GD sequence */ +#define R_386_TLS_GD_CALL 26 /* call instruction for Sun ABI GD sequence */ +#define R_386_TLS_GD_POP 27 /* popl instruction for Sun ABI GD sequence */ +#define R_386_TLS_LDM_32 28 /* 32 bit offset to GOT (index,zero) pair */ +#define R_386_TLS_LDM_PUSH 29 /* pushl instruction for Sun ABI LD sequence */ +#define R_386_TLS_LDM_CALL 30 /* call instruction for Sun ABI LD sequence */ +#define R_386_TLS_LDM_POP 31 /* popl instruction for Sun ABI LD sequence */ +#define R_386_TLS_LDO_32 32 /* 32 bit offset from start of TLS block */ +#define R_386_TLS_IE_32 33 /* 32 bit offset to GOT static TLS offset entry */ +#define R_386_TLS_LE_32 34 /* 32 bit offset within static TLS block */ +#define R_386_TLS_DTPMOD32 35 /* GOT entry containing TLS index */ +#define R_386_TLS_DTPOFF32 36 /* GOT entry containing TLS offset */ +#define R_386_TLS_TPOFF32 37 /* GOT entry of -ve static TLS offset */ + +#define R_ALPHA_NONE 0 /* No reloc */ +#define R_ALPHA_REFLONG 1 /* Direct 32 bit */ +#define R_ALPHA_REFQUAD 2 /* Direct 64 bit */ +#define R_ALPHA_GPREL32 3 /* GP relative 32 bit */ +#define R_ALPHA_LITERAL 4 /* GP relative 16 bit w/optimization */ +#define R_ALPHA_LITUSE 5 /* Optimization hint for LITERAL */ +#define R_ALPHA_GPDISP 6 /* Add displacement to GP */ +#define R_ALPHA_BRADDR 7 /* PC+4 relative 23 bit shifted */ +#define R_ALPHA_HINT 8 /* PC+4 relative 16 bit shifted */ +#define R_ALPHA_SREL16 9 /* PC relative 16 bit */ +#define R_ALPHA_SREL32 10 /* PC relative 32 bit */ +#define R_ALPHA_SREL64 11 /* PC relative 64 bit */ +#define R_ALPHA_OP_PUSH 12 /* OP stack push */ +#define R_ALPHA_OP_STORE 13 /* OP stack pop and store */ +#define R_ALPHA_OP_PSUB 14 /* OP stack subtract */ +#define R_ALPHA_OP_PRSHIFT 15 /* OP stack right shift */ +#define R_ALPHA_GPVALUE 16 +#define R_ALPHA_GPRELHIGH 17 +#define R_ALPHA_GPRELLOW 18 +#define R_ALPHA_IMMED_GP_16 19 +#define R_ALPHA_IMMED_GP_HI32 20 +#define R_ALPHA_IMMED_SCN_HI32 21 +#define R_ALPHA_IMMED_BR_HI32 22 +#define R_ALPHA_IMMED_LO32 23 +#define R_ALPHA_COPY 24 /* Copy symbol at runtime */ +#define R_ALPHA_GLOB_DAT 25 /* Create GOT entry */ +#define R_ALPHA_JMP_SLOT 26 /* Create PLT entry */ +#define R_ALPHA_RELATIVE 27 /* Adjust by program base */ + +#define R_ARM_NONE 0 /* No relocation. */ +#define R_ARM_PC24 1 +#define R_ARM_ABS32 2 +#define R_ARM_REL32 3 +#define R_ARM_PC13 4 +#define R_ARM_ABS16 5 +#define R_ARM_ABS12 6 +#define R_ARM_THM_ABS5 7 +#define R_ARM_ABS8 8 +#define R_ARM_SBREL32 9 +#define R_ARM_THM_PC22 10 +#define R_ARM_THM_PC8 11 +#define R_ARM_AMP_VCALL9 12 +#define R_ARM_SWI24 13 +#define R_ARM_THM_SWI8 14 +#define R_ARM_XPC25 15 +#define R_ARM_THM_XPC22 16 +#define R_ARM_COPY 20 /* Copy data from shared object. */ +#define R_ARM_GLOB_DAT 21 /* Set GOT entry to data address. */ +#define R_ARM_JUMP_SLOT 22 /* Set GOT entry to code address. */ +#define R_ARM_RELATIVE 23 /* Add load address of shared object. */ +#define R_ARM_GOTOFF 24 /* Add GOT-relative symbol address. */ +#define R_ARM_GOTPC 25 /* Add PC-relative GOT table address. */ +#define R_ARM_GOT32 26 /* Add PC-relative GOT offset. */ +#define R_ARM_PLT32 27 /* Add PC-relative PLT offset. */ +#define R_ARM_GNU_VTENTRY 100 +#define R_ARM_GNU_VTINHERIT 101 +#define R_ARM_RSBREL32 250 +#define R_ARM_THM_RPC22 251 +#define R_ARM_RREL32 252 +#define R_ARM_RABS32 253 +#define R_ARM_RPC24 254 +#define R_ARM_RBASE 255 + +/* Name Value Field Calculation */ +#define R_IA_64_NONE 0 /* None */ +#define R_IA_64_IMM14 0x21 /* immediate14 S + A */ +#define R_IA_64_IMM22 0x22 /* immediate22 S + A */ +#define R_IA_64_IMM64 0x23 /* immediate64 S + A */ +#define R_IA_64_DIR32MSB 0x24 /* word32 MSB S + A */ +#define R_IA_64_DIR32LSB 0x25 /* word32 LSB S + A */ +#define R_IA_64_DIR64MSB 0x26 /* word64 MSB S + A */ +#define R_IA_64_DIR64LSB 0x27 /* word64 LSB S + A */ +#define R_IA_64_GPREL22 0x2a /* immediate22 @gprel(S + A) */ +#define R_IA_64_GPREL64I 0x2b /* immediate64 @gprel(S + A) */ +#define R_IA_64_GPREL32MSB 0x2c /* word32 MSB @gprel(S + A) */ +#define R_IA_64_GPREL32LSB 0x2d /* word32 LSB @gprel(S + A) */ +#define R_IA_64_GPREL64MSB 0x2e /* word64 MSB @gprel(S + A) */ +#define R_IA_64_GPREL64LSB 0x2f /* word64 LSB @gprel(S + A) */ +#define R_IA_64_LTOFF22 0x32 /* immediate22 @ltoff(S + A) */ +#define R_IA_64_LTOFF64I 0x33 /* immediate64 @ltoff(S + A) */ +#define R_IA_64_PLTOFF22 0x3a /* immediate22 @pltoff(S + A) */ +#define R_IA_64_PLTOFF64I 0x3b /* immediate64 @pltoff(S + A) */ +#define R_IA_64_PLTOFF64MSB 0x3e /* word64 MSB @pltoff(S + A) */ +#define R_IA_64_PLTOFF64LSB 0x3f /* word64 LSB @pltoff(S + A) */ +#define R_IA_64_FPTR64I 0x43 /* immediate64 @fptr(S + A) */ +#define R_IA_64_FPTR32MSB 0x44 /* word32 MSB @fptr(S + A) */ +#define R_IA_64_FPTR32LSB 0x45 /* word32 LSB @fptr(S + A) */ +#define R_IA_64_FPTR64MSB 0x46 /* word64 MSB @fptr(S + A) */ +#define R_IA_64_FPTR64LSB 0x47 /* word64 LSB @fptr(S + A) */ +#define R_IA_64_PCREL60B 0x48 /* immediate60 form1 S + A - P */ +#define R_IA_64_PCREL21B 0x49 /* immediate21 form1 S + A - P */ +#define R_IA_64_PCREL21M 0x4a /* immediate21 form2 S + A - P */ +#define R_IA_64_PCREL21F 0x4b /* immediate21 form3 S + A - P */ +#define R_IA_64_PCREL32MSB 0x4c /* word32 MSB S + A - P */ +#define R_IA_64_PCREL32LSB 0x4d /* word32 LSB S + A - P */ +#define R_IA_64_PCREL64MSB 0x4e /* word64 MSB S + A - P */ +#define R_IA_64_PCREL64LSB 0x4f /* word64 LSB S + A - P */ +#define R_IA_64_LTOFF_FPTR22 0x52 /* immediate22 @ltoff(@fptr(S + A)) */ +#define R_IA_64_LTOFF_FPTR64I 0x53 /* immediate64 @ltoff(@fptr(S + A)) */ +#define R_IA_64_LTOFF_FPTR32MSB 0x54 /* word32 MSB @ltoff(@fptr(S + A)) */ +#define R_IA_64_LTOFF_FPTR32LSB 0x55 /* word32 LSB @ltoff(@fptr(S + A)) */ +#define R_IA_64_LTOFF_FPTR64MSB 0x56 /* word64 MSB @ltoff(@fptr(S + A)) */ +#define R_IA_64_LTOFF_FPTR64LSB 0x57 /* word64 LSB @ltoff(@fptr(S + A)) */ +#define R_IA_64_SEGREL32MSB 0x5c /* word32 MSB @segrel(S + A) */ +#define R_IA_64_SEGREL32LSB 0x5d /* word32 LSB @segrel(S + A) */ +#define R_IA_64_SEGREL64MSB 0x5e /* word64 MSB @segrel(S + A) */ +#define R_IA_64_SEGREL64LSB 0x5f /* word64 LSB @segrel(S + A) */ +#define R_IA_64_SECREL32MSB 0x64 /* word32 MSB @secrel(S + A) */ +#define R_IA_64_SECREL32LSB 0x65 /* word32 LSB @secrel(S + A) */ +#define R_IA_64_SECREL64MSB 0x66 /* word64 MSB @secrel(S + A) */ +#define R_IA_64_SECREL64LSB 0x67 /* word64 LSB @secrel(S + A) */ +#define R_IA_64_REL32MSB 0x6c /* word32 MSB BD + A */ +#define R_IA_64_REL32LSB 0x6d /* word32 LSB BD + A */ +#define R_IA_64_REL64MSB 0x6e /* word64 MSB BD + A */ +#define R_IA_64_REL64LSB 0x6f /* word64 LSB BD + A */ +#define R_IA_64_LTV32MSB 0x74 /* word32 MSB S + A */ +#define R_IA_64_LTV32LSB 0x75 /* word32 LSB S + A */ +#define R_IA_64_LTV64MSB 0x76 /* word64 MSB S + A */ +#define R_IA_64_LTV64LSB 0x77 /* word64 LSB S + A */ +#define R_IA_64_PCREL21BI 0x79 /* immediate21 form1 S + A - P */ +#define R_IA_64_PCREL22 0x7a /* immediate22 S + A - P */ +#define R_IA_64_PCREL64I 0x7b /* immediate64 S + A - P */ +#define R_IA_64_IPLTMSB 0x80 /* function descriptor MSB special */ +#define R_IA_64_IPLTLSB 0x81 /* function descriptor LSB speciaal */ +#define R_IA_64_SUB 0x85 /* immediate64 A - S */ +#define R_IA_64_LTOFF22X 0x86 /* immediate22 special */ +#define R_IA_64_LDXMOV 0x87 /* immediate22 special */ +#define R_IA_64_TPREL14 0x91 /* imm14 @tprel(S + A) */ +#define R_IA_64_TPREL22 0x92 /* imm22 @tprel(S + A) */ +#define R_IA_64_TPREL64I 0x93 /* imm64 @tprel(S + A) */ +#define R_IA_64_TPREL64MSB 0x96 /* word64 MSB @tprel(S + A) */ +#define R_IA_64_TPREL64LSB 0x97 /* word64 LSB @tprel(S + A) */ +#define R_IA_64_LTOFF_TPREL22 0x9a /* imm22 @ltoff(@tprel(S+A)) */ +#define R_IA_64_DTPMOD64MSB 0xa6 /* word64 MSB @dtpmod(S + A) */ +#define R_IA_64_DTPMOD64LSB 0xa7 /* word64 LSB @dtpmod(S + A) */ +#define R_IA_64_LTOFF_DTPMOD22 0xaa /* imm22 @ltoff(@dtpmod(S+A)) */ +#define R_IA_64_DTPREL14 0xb1 /* imm14 @dtprel(S + A) */ +#define R_IA_64_DTPREL22 0xb2 /* imm22 @dtprel(S + A) */ +#define R_IA_64_DTPREL64I 0xb3 /* imm64 @dtprel(S + A) */ +#define R_IA_64_DTPREL32MSB 0xb4 /* word32 MSB @dtprel(S + A) */ +#define R_IA_64_DTPREL32LSB 0xb5 /* word32 LSB @dtprel(S + A) */ +#define R_IA_64_DTPREL64MSB 0xb6 /* word64 MSB @dtprel(S + A) */ +#define R_IA_64_DTPREL64LSB 0xb7 /* word64 LSB @dtprel(S + A) */ +#define R_IA_64_LTOFF_DTPREL22 0xba /* imm22 @ltoff(@dtprel(S+A)) */ + +#define R_PPC_NONE 0 /* No relocation. */ +#define R_PPC_ADDR32 1 +#define R_PPC_ADDR24 2 +#define R_PPC_ADDR16 3 +#define R_PPC_ADDR16_LO 4 +#define R_PPC_ADDR16_HI 5 +#define R_PPC_ADDR16_HA 6 +#define R_PPC_ADDR14 7 +#define R_PPC_ADDR14_BRTAKEN 8 +#define R_PPC_ADDR14_BRNTAKEN 9 +#define R_PPC_REL24 10 +#define R_PPC_REL14 11 +#define R_PPC_REL14_BRTAKEN 12 +#define R_PPC_REL14_BRNTAKEN 13 +#define R_PPC_GOT16 14 +#define R_PPC_GOT16_LO 15 +#define R_PPC_GOT16_HI 16 +#define R_PPC_GOT16_HA 17 +#define R_PPC_PLTREL24 18 +#define R_PPC_COPY 19 +#define R_PPC_GLOB_DAT 20 +#define R_PPC_JMP_SLOT 21 +#define R_PPC_RELATIVE 22 +#define R_PPC_LOCAL24PC 23 +#define R_PPC_UADDR32 24 +#define R_PPC_UADDR16 25 +#define R_PPC_REL32 26 +#define R_PPC_PLT32 27 +#define R_PPC_PLTREL32 28 +#define R_PPC_PLT16_LO 29 +#define R_PPC_PLT16_HI 30 +#define R_PPC_PLT16_HA 31 +#define R_PPC_SDAREL16 32 +#define R_PPC_SECTOFF 33 +#define R_PPC_SECTOFF_LO 34 +#define R_PPC_SECTOFF_HI 35 +#define R_PPC_SECTOFF_HA 36 + +/* + * TLS relocations + */ +#define R_PPC_TLS 67 +#define R_PPC_DTPMOD32 68 +#define R_PPC_TPREL16 69 +#define R_PPC_TPREL16_LO 70 +#define R_PPC_TPREL16_HI 71 +#define R_PPC_TPREL16_HA 72 +#define R_PPC_TPREL32 73 +#define R_PPC_DTPREL16 74 +#define R_PPC_DTPREL16_LO 75 +#define R_PPC_DTPREL16_HI 76 +#define R_PPC_DTPREL16_HA 77 +#define R_PPC_DTPREL32 78 +#define R_PPC_GOT_TLSGD16 79 +#define R_PPC_GOT_TLSGD16_LO 80 +#define R_PPC_GOT_TLSGD16_HI 81 +#define R_PPC_GOT_TLSGD16_HA 82 +#define R_PPC_GOT_TLSLD16 83 +#define R_PPC_GOT_TLSLD16_LO 84 +#define R_PPC_GOT_TLSLD16_HI 85 +#define R_PPC_GOT_TLSLD16_HA 86 +#define R_PPC_GOT_TPREL16 87 +#define R_PPC_GOT_TPREL16_LO 88 +#define R_PPC_GOT_TPREL16_HI 89 +#define R_PPC_GOT_TPREL16_HA 90 + +/* + * The remaining relocs are from the Embedded ELF ABI, and are not in the + * SVR4 ELF ABI. + */ + +#define R_PPC_EMB_NADDR32 101 +#define R_PPC_EMB_NADDR16 102 +#define R_PPC_EMB_NADDR16_LO 103 +#define R_PPC_EMB_NADDR16_HI 104 +#define R_PPC_EMB_NADDR16_HA 105 +#define R_PPC_EMB_SDAI16 106 +#define R_PPC_EMB_SDA2I16 107 +#define R_PPC_EMB_SDA2REL 108 +#define R_PPC_EMB_SDA21 109 +#define R_PPC_EMB_MRKREF 110 +#define R_PPC_EMB_RELSEC16 111 +#define R_PPC_EMB_RELST_LO 112 +#define R_PPC_EMB_RELST_HI 113 +#define R_PPC_EMB_RELST_HA 114 +#define R_PPC_EMB_BIT_FLD 115 +#define R_PPC_EMB_RELSDA 116 + +#define R_SPARC_NONE 0 +#define R_SPARC_8 1 +#define R_SPARC_16 2 +#define R_SPARC_32 3 +#define R_SPARC_DISP8 4 +#define R_SPARC_DISP16 5 +#define R_SPARC_DISP32 6 +#define R_SPARC_WDISP30 7 +#define R_SPARC_WDISP22 8 +#define R_SPARC_HI22 9 +#define R_SPARC_22 10 +#define R_SPARC_13 11 +#define R_SPARC_LO10 12 +#define R_SPARC_GOT10 13 +#define R_SPARC_GOT13 14 +#define R_SPARC_GOT22 15 +#define R_SPARC_PC10 16 +#define R_SPARC_PC22 17 +#define R_SPARC_WPLT30 18 +#define R_SPARC_COPY 19 +#define R_SPARC_GLOB_DAT 20 +#define R_SPARC_JMP_SLOT 21 +#define R_SPARC_RELATIVE 22 +#define R_SPARC_UA32 23 +#define R_SPARC_PLT32 24 +#define R_SPARC_HIPLT22 25 +#define R_SPARC_LOPLT10 26 +#define R_SPARC_PCPLT32 27 +#define R_SPARC_PCPLT22 28 +#define R_SPARC_PCPLT10 29 +#define R_SPARC_10 30 +#define R_SPARC_11 31 +#define R_SPARC_64 32 +#define R_SPARC_OLO10 33 +#define R_SPARC_HH22 34 +#define R_SPARC_HM10 35 +#define R_SPARC_LM22 36 +#define R_SPARC_PC_HH22 37 +#define R_SPARC_PC_HM10 38 +#define R_SPARC_PC_LM22 39 +#define R_SPARC_WDISP16 40 +#define R_SPARC_WDISP19 41 +#define R_SPARC_GLOB_JMP 42 +#define R_SPARC_7 43 +#define R_SPARC_5 44 +#define R_SPARC_6 45 +#define R_SPARC_DISP64 46 +#define R_SPARC_PLT64 47 +#define R_SPARC_HIX22 48 +#define R_SPARC_LOX10 49 +#define R_SPARC_H44 50 +#define R_SPARC_M44 51 +#define R_SPARC_L44 52 +#define R_SPARC_REGISTER 53 +#define R_SPARC_UA64 54 +#define R_SPARC_UA16 55 +#define R_SPARC_TLS_GD_HI22 56 +#define R_SPARC_TLS_GD_LO10 57 +#define R_SPARC_TLS_GD_ADD 58 +#define R_SPARC_TLS_GD_CALL 59 +#define R_SPARC_TLS_LDM_HI22 60 +#define R_SPARC_TLS_LDM_LO10 61 +#define R_SPARC_TLS_LDM_ADD 62 +#define R_SPARC_TLS_LDM_CALL 63 +#define R_SPARC_TLS_LDO_HIX22 64 +#define R_SPARC_TLS_LDO_LOX10 65 +#define R_SPARC_TLS_LDO_ADD 66 +#define R_SPARC_TLS_IE_HI22 67 +#define R_SPARC_TLS_IE_LO10 68 +#define R_SPARC_TLS_IE_LD 69 +#define R_SPARC_TLS_IE_LDX 70 +#define R_SPARC_TLS_IE_ADD 71 +#define R_SPARC_TLS_LE_HIX22 72 +#define R_SPARC_TLS_LE_LOX10 73 +#define R_SPARC_TLS_DTPMOD32 74 +#define R_SPARC_TLS_DTPMOD64 75 +#define R_SPARC_TLS_DTPOFF32 76 +#define R_SPARC_TLS_DTPOFF64 77 +#define R_SPARC_TLS_TPOFF32 78 +#define R_SPARC_TLS_TPOFF64 79 + +#define R_X86_64_NONE 0 /* No relocation. */ +#define R_X86_64_64 1 /* Add 64 bit symbol value. */ +#define R_X86_64_PC32 2 /* PC-relative 32 bit signed sym value. */ +#define R_X86_64_GOT32 3 /* PC-relative 32 bit GOT offset. */ +#define R_X86_64_PLT32 4 /* PC-relative 32 bit PLT offset. */ +#define R_X86_64_COPY 5 /* Copy data from shared object. */ +#define R_X86_64_GLOB_DAT 6 /* Set GOT entry to data address. */ +#define R_X86_64_JMP_SLOT 7 /* Set GOT entry to code address. */ +#define R_X86_64_RELATIVE 8 /* Add load address of shared object. */ +#define R_X86_64_GOTPCREL 9 /* Add 32 bit signed pcrel offset to GOT. */ +#define R_X86_64_32 10 /* Add 32 bit zero extended symbol value */ +#define R_X86_64_32S 11 /* Add 32 bit sign extended symbol value */ +#define R_X86_64_16 12 /* Add 16 bit zero extended symbol value */ +#define R_X86_64_PC16 13 /* Add 16 bit signed extended pc relative symbol value */ +#define R_X86_64_8 14 /* Add 8 bit zero extended symbol value */ +#define R_X86_64_PC8 15 /* Add 8 bit signed extended pc relative symbol value */ +#define R_X86_64_DTPMOD64 16 /* ID of module containing symbol */ +#define R_X86_64_DTPOFF64 17 /* Offset in TLS block */ +#define R_X86_64_TPOFF64 18 /* Offset in static TLS block */ +#define R_X86_64_TLSGD 19 /* PC relative offset to GD GOT entry */ +#define R_X86_64_TLSLD 20 /* PC relative offset to LD GOT entry */ +#define R_X86_64_DTPOFF32 21 /* Offset in TLS block */ +#define R_X86_64_GOTTPOFF 22 /* PC relative offset to IE GOT entry */ +#define R_X86_64_TPOFF32 23 /* Offset in static TLS block */ + + +#endif /* !_SYS_ELF_COMMON_H_ */ diff --git a/BaseTools/Source/C/GenFw/elf_generic.h b/BaseTools/Source/C/GenFw/elf_generic.h new file mode 100644 index 0000000000..dd4f8e14fd --- /dev/null +++ b/BaseTools/Source/C/GenFw/elf_generic.h @@ -0,0 +1,88 @@ +/*- + * Copyright (c) 1998 John D. Polstra. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/sys/sys/elf_generic.h,v 1.6.14.2 2007/12/03 21:30:36 marius Exp $ + */ + +#ifndef _SYS_ELF_GENERIC_H_ +#define _SYS_ELF_GENERIC_H_ 1 + +#include + +/* + * Definitions of generic ELF names which relieve applications from + * needing to know the word size. + */ + +#if __ELF_WORD_SIZE != 32 && __ELF_WORD_SIZE != 64 +#error "__ELF_WORD_SIZE must be defined as 32 or 64" +#endif + +#define ELF_CLASS __CONCAT(ELFCLASS,__ELF_WORD_SIZE) + +#if BYTE_ORDER == LITTLE_ENDIAN +#define ELF_DATA ELFDATA2LSB +#elif BYTE_ORDER == BIG_ENDIAN +#define ELF_DATA ELFDATA2MSB +#else +#error "Unknown byte order" +#endif + +#define __elfN(x) __CONCAT(__CONCAT(__CONCAT(elf,__ELF_WORD_SIZE),_),x) +#define __ElfN(x) __CONCAT(__CONCAT(__CONCAT(Elf,__ELF_WORD_SIZE),_),x) +#define __ELFN(x) __CONCAT(__CONCAT(__CONCAT(ELF,__ELF_WORD_SIZE),_),x) +#define __ElfType(x) typedef __ElfN(x) __CONCAT(Elf_,x) + +__ElfType(Addr); +__ElfType(Half); +__ElfType(Off); +__ElfType(Sword); +__ElfType(Word); +__ElfType(Ehdr); +__ElfType(Shdr); +__ElfType(Phdr); +__ElfType(Dyn); +__ElfType(Rel); +__ElfType(Rela); +__ElfType(Sym); +__ElfType(Verdef); +__ElfType(Verdaux); +__ElfType(Verneed); +__ElfType(Vernaux); +__ElfType(Versym); + +/* Non-standard ELF types. */ +__ElfType(Hashelt); +__ElfType(Size); +__ElfType(Ssize); + +#define ELF_R_SYM __ELFN(R_SYM) +#define ELF_R_TYPE __ELFN(R_TYPE) +#define ELF_R_INFO __ELFN(R_INFO) +#define ELF_ST_BIND __ELFN(ST_BIND) +#define ELF_ST_TYPE __ELFN(ST_TYPE) +#define ELF_ST_INFO __ELFN(ST_INFO) + +#endif /* !_SYS_ELF_GENERIC_H_ */ diff --git a/BaseTools/Source/C/GenPage/GNUmakefile b/BaseTools/Source/C/GenPage/GNUmakefile new file mode 100644 index 0000000000..a828168cd0 --- /dev/null +++ b/BaseTools/Source/C/GenPage/GNUmakefile @@ -0,0 +1,10 @@ +ARCH ?= IA32 +MAKEROOT ?= .. + +APPNAME = GenPage + +LIBS = -lCommon + +OBJECTS = GenPage.o + +include $(MAKEROOT)/Makefiles/app.makefile diff --git a/BaseTools/Source/C/GenPage/GenPage.c b/BaseTools/Source/C/GenPage/GenPage.c new file mode 100644 index 0000000000..99fbc1e472 --- /dev/null +++ b/BaseTools/Source/C/GenPage/GenPage.c @@ -0,0 +1,424 @@ +/** @file + +Copyright 2006 - 2008, 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: + GenPage.c + +Abstract: + Pre-Create a 4G page table (2M pages). + It's used in DUET x64 build needed to enter LongMode. + + Create 4G page table (2M pages) + + Linear Address + 63 48 47 39 38 30 29 21 20 0 + +--------+-------+---------------+-----------+-----------------------------+ + PML4 Directory-Ptr Directory Offset + + Paging-Structures := + PML4 + ( + Directory-Ptr Directory {512} + ) {4} +**/ + +#include +#include +#include +#include "VirtualMemory.h" +#include "EfiUtilityMsgs.h" + +#define EFI_PAGE_BASE_OFFSET_IN_LDR 0x70000 +#define EFI_PAGE_BASE_ADDRESS (EFI_PAGE_BASE_OFFSET_IN_LDR + 0x20000) + +UINT32 gPageTableBaseAddress = EFI_PAGE_BASE_ADDRESS; +UINT32 gPageTableOffsetInFile = EFI_PAGE_BASE_OFFSET_IN_LDR; + +#define EFI_MAX_ENTRY_NUM 512 + +#define EFI_PML4_ENTRY_NUM 1 +#define EFI_PDPTE_ENTRY_NUM 4 +#define EFI_PDE_ENTRY_NUM EFI_MAX_ENTRY_NUM + +#define EFI_PML4_PAGE_NUM 1 +#define EFI_PDPTE_PAGE_NUM EFI_PML4_ENTRY_NUM +#define EFI_PDE_PAGE_NUM (EFI_PML4_ENTRY_NUM * EFI_PDPTE_ENTRY_NUM) + +#define EFI_PAGE_NUMBER (EFI_PML4_PAGE_NUM + EFI_PDPTE_PAGE_NUM + EFI_PDE_PAGE_NUM) + +#define EFI_SIZE_OF_PAGE 0x1000 +#define EFI_PAGE_SIZE_2M 0x200000 + +#define CONVERT_BIN_PAGE_ADDRESS(a) ((UINT8 *) a - PageTable + gPageTableBaseAddress) + +// +// Utility Name +// +#define UTILITY_NAME "GenBootSector" + +// +// Utility version information +// +#define UTILITY_MAJOR_VERSION 0 +#define UTILITY_MINOR_VERSION 1 + +void +Version ( + void + ) +/*++ + +Routine Description: + + Displays the standard utility information to SDTOUT + +Arguments: + + None + +Returns: + + None + +--*/ +{ + printf ("%s v%d.%d -Utility to generate the EfiLoader image containing page table.\n", UTILITY_NAME, UTILITY_MAJOR_VERSION, UTILITY_MINOR_VERSION); + printf ("Copyright (c) 2008 - 2009 Intel Corporation. All rights reserved.\n"); +} + +VOID +Usage ( + void + ) +{ + Version(); + printf ("\nUsage: \n\ + GenPage\n\ + -o, --output Filename containing page table\n\ + [-b, --baseaddr baseaddress of page table]\n\ + [-f, --offset offset in the file that page table will reside]\n\ + [-v, --verbose]\n\ + [--version]\n\ + [-q, --quiet disable all messages except fatal errors]\n\ + [-d, --debug[#]\n\ + [-h, --help]\n\ + EfiLoaderImageName\n"); + +} + +void * +CreateIdentityMappingPageTables ( + void + ) +/*++ + +Routine Description: + To create 4G PAE 2M pagetable + +Return: + void * - buffer containing created pagetable + +--*/ +{ + UINT64 PageAddress; + UINT8 *PageTable; + UINT8 *PageTablePtr; + int PML4Index; + int PDPTEIndex; + int PDEIndex; + X64_PAGE_MAP_AND_DIRECTORY_POINTER_2MB_4K *PageMapLevel4Entry; + X64_PAGE_MAP_AND_DIRECTORY_POINTER_2MB_4K *PageDirectoryPointerEntry; + X64_PAGE_TABLE_ENTRY_2M *PageDirectoryEntry2MB; + + PageTable = (void *)malloc (EFI_PAGE_NUMBER * EFI_SIZE_OF_PAGE); + memset (PageTable, 0, (EFI_PAGE_NUMBER * EFI_SIZE_OF_PAGE)); + PageTablePtr = PageTable; + + PageAddress = 0; + + // + // Page Table structure 3 level 2MB. + // + // Page-Map-Level-4-Table : bits 47-39 + // Page-Directory-Pointer-Table : bits 38-30 + // + // Page Table 2MB : Page-Directory(2M) : bits 29-21 + // + // + + PageMapLevel4Entry = (X64_PAGE_MAP_AND_DIRECTORY_POINTER_2MB_4K *)PageTablePtr; + + for (PML4Index = 0; PML4Index < EFI_PML4_ENTRY_NUM; PML4Index++, PageMapLevel4Entry++) { + // + // Each Page-Map-Level-4-Table Entry points to the base address of a Page-Directory-Pointer-Table Entry + // + PageTablePtr += EFI_SIZE_OF_PAGE; + PageDirectoryPointerEntry = (X64_PAGE_MAP_AND_DIRECTORY_POINTER_2MB_4K *)PageTablePtr; + + // + // Make a Page-Map-Level-4-Table Entry + // + PageMapLevel4Entry->Uint64 = (UINT64)(UINT32)(CONVERT_BIN_PAGE_ADDRESS (PageDirectoryPointerEntry)); + PageMapLevel4Entry->Bits.ReadWrite = 1; + PageMapLevel4Entry->Bits.Present = 1; + + for (PDPTEIndex = 0; PDPTEIndex < EFI_PDPTE_ENTRY_NUM; PDPTEIndex++, PageDirectoryPointerEntry++) { + // + // Each Page-Directory-Pointer-Table Entry points to the base address of a Page-Directory Entry + // + PageTablePtr += EFI_SIZE_OF_PAGE; + PageDirectoryEntry2MB = (X64_PAGE_TABLE_ENTRY_2M *)PageTablePtr; + + // + // Make a Page-Directory-Pointer-Table Entry + // + PageDirectoryPointerEntry->Uint64 = (UINT64)(UINT32)(CONVERT_BIN_PAGE_ADDRESS (PageDirectoryEntry2MB)); + PageDirectoryPointerEntry->Bits.ReadWrite = 1; + PageDirectoryPointerEntry->Bits.Present = 1; + + for (PDEIndex = 0; PDEIndex < EFI_PDE_ENTRY_NUM; PDEIndex++, PageDirectoryEntry2MB++) { + // + // Make a Page-Directory Entry + // + PageDirectoryEntry2MB->Uint64 = (UINT64)PageAddress; + PageDirectoryEntry2MB->Bits.ReadWrite = 1; + PageDirectoryEntry2MB->Bits.Present = 1; + PageDirectoryEntry2MB->Bits.MustBe1 = 1; + + PageAddress += EFI_PAGE_SIZE_2M; + } + } + } + + return PageTable; +} + +INT32 +GenBinPage ( + void *BaseMemory, + char *NoPageFileName, + char *PageFileName + ) +/*++ + +Routine Description: + Write the buffer containing page table to file at a specified offset. + Here the offset is defined as EFI_PAGE_BASE_OFFSET_IN_LDR. + +Arguments: + BaseMemory - buffer containing page table + NoPageFileName - file to write page table + PageFileName - file save to after writing + +return: + 0 : successful + -1 : failed + +--*/ +{ + FILE *PageFile; + FILE *NoPageFile; + UINT8 Data; + unsigned long FileSize; + + // + // Open files + // + PageFile = fopen (PageFileName, "w+b"); + if (PageFile == NULL) { + Error (NoPageFileName, 0, 0x4002, "Invalid parameter option", "Output File %s open failure", PageFileName); + return -1; + } + + NoPageFile = fopen (NoPageFileName, "r+b"); + if (NoPageFile == NULL) { + Error (NoPageFileName, 0, 0x4002, "Invalid parameter option", "Input File %s open failure", NoPageFileName); + fclose (PageFile); + return -1; + } + + // + // Check size - should not be great than EFI_PAGE_BASE_OFFSET_IN_LDR + // + fseek (NoPageFile, 0, SEEK_END); + FileSize = ftell (NoPageFile); + fseek (NoPageFile, 0, SEEK_SET); + if (FileSize > gPageTableOffsetInFile) { + Error (NoPageFileName, 0, 0x4002, "Invalid parameter option", "Input file size (0x%x) exceeds the Page Table Offset (0x%x)", FileSize, gPageTableOffsetInFile); + fclose (PageFile); + fclose (NoPageFile); + return -1; + } + + // + // Write data + // + while (fread (&Data, sizeof(UINT8), 1, NoPageFile)) { + fwrite (&Data, sizeof(UINT8), 1, PageFile); + } + + // + // Write PageTable + // + fseek (PageFile, gPageTableOffsetInFile, SEEK_SET); + fwrite (BaseMemory, (EFI_PAGE_NUMBER * EFI_SIZE_OF_PAGE), 1, PageFile); + + // + // Close files + // + fclose (PageFile); + fclose (NoPageFile); + + return 0; +} + +int +main ( + int argc, + char **argv + ) +{ + VOID *BaseMemory; + INTN result; + CHAR8 *OutputFile = NULL; + CHAR8 *InputFile = NULL; + EFI_STATUS Status; + UINT64 TempValue; + + SetUtilityName("GenPage"); + + if (argc == 1) { + Usage(); + return STATUS_ERROR; + } + + argc --; + argv ++; + + if ((stricmp (argv[0], "-h") == 0) || (stricmp (argv[0], "--help") == 0)) { + Usage(); + return 0; + } + + if (stricmp (argv[0], "--version") == 0) { + Version(); + return 0; + } + + while (argc > 0) { + if ((stricmp (argv[0], "-o") == 0) || (stricmp (argv[0], "--output") == 0)) { + if (argv[1] == NULL || argv[1][0] == '-') { + Error (NULL, 0, 1003, "Invalid option value", "Output file is missing for -o option"); + return STATUS_ERROR; + } + OutputFile = argv[1]; + argc -= 2; + argv += 2; + continue; + } + + if ((stricmp (argv[0], "-b") == 0) || (stricmp (argv[0], "--baseaddr") == 0)) { + if (argv[1] == NULL || argv[1][0] == '-') { + Error (NULL, 0, 1003, "Invalid option value", "Base address is missing for -b option"); + return STATUS_ERROR; + } + Status = AsciiStringToUint64 (argv[1], FALSE, &TempValue); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 1003, "Invalid option value", "Base address is not valid intergrator"); + return STATUS_ERROR; + } + gPageTableBaseAddress = (UINT32) TempValue; + argc -= 2; + argv += 2; + continue; + } + + if ((stricmp (argv[0], "-f") == 0) || (stricmp (argv[0], "--offset") == 0)) { + if (argv[1] == NULL || argv[1][0] == '-') { + Error (NULL, 0, 1003, "Invalid option value", "Offset is missing for -f option"); + return STATUS_ERROR; + } + Status = AsciiStringToUint64 (argv[1], FALSE, &TempValue); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 1003, "Invalid option value", "Offset is not valid intergrator"); + return STATUS_ERROR; + } + gPageTableOffsetInFile = (UINT32) TempValue; + argc -= 2; + argv += 2; + continue; + } + + if ((stricmp (argv[0], "-q") == 0) || (stricmp (argv[0], "--quiet") == 0)) { + argc --; + argv ++; + continue; + } + + if ((stricmp (argv[0], "-v") ==0) || (stricmp (argv[0], "--verbose") == 0)) { + argc --; + argv ++; + continue; + } + + if ((stricmp (argv[0], "-d") == 0) || (stricmp (argv[0], "--debug") == 0)) { + if (argv[1] == NULL || argv[1][0] == '-') { + Error (NULL, 0, 1003, "Invalid option value", "Debug Level is not specified."); + return STATUS_ERROR; + } + Status = AsciiStringToUint64 (argv[1], FALSE, &TempValue); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 1003, "Invalid option value", "Debug Level is not valid intergrator."); + return STATUS_ERROR; + } + if (TempValue > 9) { + Error (NULL, 0, 1003, "Invalid option value", "Debug Level range is 0-9, currnt input level is %d", TempValue); + return STATUS_ERROR; + } + argc -= 2; + argv += 2; + continue; + } + + if (argv[0][0] == '-') { + Error (NULL, 0, 1000, "Unknown option", argv[0]); + return STATUS_ERROR; + } + + // + // Don't recognize the paramter. + // + InputFile = argv[0]; + argc--; + argv++; + } + + if (InputFile == NULL) { + Error (NULL, 0, 1003, "Invalid option value", "Input file is not specified"); + return STATUS_ERROR; + } + + // + // Create X64 page table + // + BaseMemory = CreateIdentityMappingPageTables (); + + // + // Add page table to binary file + // + result = GenBinPage (BaseMemory, InputFile, OutputFile); + if (result < 0) { + return STATUS_ERROR; + } + + return 0; +} + diff --git a/BaseTools/Source/C/GenPage/Makefile b/BaseTools/Source/C/GenPage/Makefile new file mode 100644 index 0000000000..5faf037f44 --- /dev/null +++ b/BaseTools/Source/C/GenPage/Makefile @@ -0,0 +1,10 @@ +!INCLUDE ..\Makefiles\ms.common + +APPNAME = GenPage + +LIBS = $(LIB_PATH)\Common.lib + +OBJECTS = GenPage.obj + +!INCLUDE ..\Makefiles\ms.app + diff --git a/BaseTools/Source/C/GenPage/VirtualMemory.h b/BaseTools/Source/C/GenPage/VirtualMemory.h new file mode 100644 index 0000000000..b4baec86b2 --- /dev/null +++ b/BaseTools/Source/C/GenPage/VirtualMemory.h @@ -0,0 +1,127 @@ +/** @file + +Copyright 2006 - 2008, 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: + VirtualMemory.h + +Abstract: + + x64 Long Mode Virtual Memory Management Definitions + + References: + 1) IA-32 Intel(R) Atchitecture Software Developer's Manual Volume 1:Basic Architecture, Intel + 2) IA-32 Intel(R) Atchitecture Software Developer's Manual Volume 2:Instruction Set Reference, Intel + 3) IA-32 Intel(R) Atchitecture Software Developer's Manual Volume 3:System Programmer's Guide, Intel + 4) AMD64 Architecture Programmer's Manual Volume 2: System Programming +**/ + +#ifndef _VIRTUAL_MEMORY_H_ +#define _VIRTUAL_MEMORY_H_ + +#include "CommonLib.h" + +#pragma pack(1) + +// +// Page-Map Level-4 Offset (PML4) and +// Page-Directory-Pointer Offset (PDPE) entries 4K & 2MB +// + +typedef union { + struct { + UINT64 Present:1; // 0 = Not present in memory, 1 = Present in memory + UINT64 ReadWrite:1; // 0 = Read-Only, 1= Read/Write + UINT64 UserSupervisor:1; // 0 = Supervisor, 1=User + UINT64 WriteThrough:1; // 0 = Write-Back caching, 1=Write-Through caching + UINT64 CacheDisabled:1; // 0 = Cached, 1=Non-Cached + UINT64 Accessed:1; // 0 = Not accessed, 1 = Accessed (set by CPU) + UINT64 Reserved:1; // Reserved + UINT64 MustBeZero:2; // Must Be Zero + UINT64 Available:3; // Available for use by system software + UINT64 PageTableBaseAddress:40; // Page Table Base Address + UINT64 AvabilableHigh:11; // Available for use by system software + UINT64 Nx:1; // No Execute bit + } Bits; + UINT64 Uint64; +} X64_PAGE_MAP_AND_DIRECTORY_POINTER_2MB_4K; + +// +// Page-Directory Offset 4K +// +typedef union { + struct { + UINT64 Present:1; // 0 = Not present in memory, 1 = Present in memory + UINT64 ReadWrite:1; // 0 = Read-Only, 1= Read/Write + UINT64 UserSupervisor:1; // 0 = Supervisor, 1=User + UINT64 WriteThrough:1; // 0 = Write-Back caching, 1=Write-Through caching + UINT64 CacheDisabled:1; // 0 = Cached, 1=Non-Cached + UINT64 Accessed:1; // 0 = Not accessed, 1 = Accessed (set by CPU) + UINT64 Reserved:1; // Reserved + UINT64 MustBeZero:1; // Must Be Zero + UINT64 Reserved2:1; // Reserved + UINT64 Available:3; // Available for use by system software + UINT64 PageTableBaseAddress:40; // Page Table Base Address + UINT64 AvabilableHigh:11; // Available for use by system software + UINT64 Nx:1; // No Execute bit + } Bits; + UINT64 Uint64; +} X64_PAGE_DIRECTORY_ENTRY_4K; + +// +// Page Table Entry 4K +// +typedef union { + struct { + UINT64 Present:1; // 0 = Not present in memory, 1 = Present in memory + UINT64 ReadWrite:1; // 0 = Read-Only, 1= Read/Write + UINT64 UserSupervisor:1; // 0 = Supervisor, 1=User + UINT64 WriteThrough:1; // 0 = Write-Back caching, 1=Write-Through caching + UINT64 CacheDisabled:1; // 0 = Cached, 1=Non-Cached + UINT64 Accessed:1; // 0 = Not accessed, 1 = Accessed (set by CPU) + UINT64 Dirty:1; // 0 = Not Dirty, 1 = written by processor on access to page + UINT64 PAT:1; // 0 = Ignore Page Attribute Table + UINT64 Global:1; // 0 = Not global page, 1 = global page TLB not cleared on CR3 write + UINT64 Available:3; // Available for use by system software + UINT64 PageTableBaseAddress:40; // Page Table Base Address + UINT64 AvabilableHigh:11; // Available for use by system software + UINT64 Nx:1; // 0 = Execute Code, 1 = No Code Execution + } Bits; + UINT64 Uint64; +} X64_PAGE_TABLE_ENTRY_4K; + + +// +// Page Table Entry 2MB +// +typedef union { + struct { + UINT64 Present:1; // 0 = Not present in memory, 1 = Present in memory + UINT64 ReadWrite:1; // 0 = Read-Only, 1= Read/Write + UINT64 UserSupervisor:1; // 0 = Supervisor, 1=User + UINT64 WriteThrough:1; // 0 = Write-Back caching, 1=Write-Through caching + UINT64 CacheDisabled:1; // 0 = Cached, 1=Non-Cached + UINT64 Accessed:1; // 0 = Not accessed, 1 = Accessed (set by CPU) + UINT64 Dirty:1; // 0 = Not Dirty, 1 = written by processor on access to page + UINT64 MustBe1:1; // Must be 1 + UINT64 Global:1; // 0 = Not global page, 1 = global page TLB not cleared on CR3 write + UINT64 Available:3; // Available for use by system software + UINT64 PAT:1; // + UINT64 MustBeZero:8; // Must be zero; + UINT64 PageTableBaseAddress:31; // Page Table Base Address + UINT64 AvabilableHigh:11; // Available for use by system software + UINT64 Nx:1; // 0 = Execute Code, 1 = No Code Execution + } Bits; + UINT64 Uint64; +} X64_PAGE_TABLE_ENTRY_2M; + +#pragma pack() + +#endif diff --git a/BaseTools/Source/C/GenSec/GNUmakefile b/BaseTools/Source/C/GenSec/GNUmakefile new file mode 100644 index 0000000000..a3bed5d325 --- /dev/null +++ b/BaseTools/Source/C/GenSec/GNUmakefile @@ -0,0 +1,18 @@ +ARCH ?= IA32 +MAKEROOT ?= .. + +APPNAME = GenSec + +OBJECTS = GenSec.o + +include $(MAKEROOT)/Makefiles/app.makefile + +LIBS = -lCommon +ifeq ($(CYGWIN), CYGWIN) + LIBS += -L/lib/e2fsprogs -luuid +endif + +ifeq ($(LINUX), Linux) + LIBS += -luuid +endif + diff --git a/BaseTools/Source/C/GenSec/GenSec.c b/BaseTools/Source/C/GenSec/GenSec.c new file mode 100644 index 0000000000..952034ad5f --- /dev/null +++ b/BaseTools/Source/C/GenSec/GenSec.c @@ -0,0 +1,1307 @@ +/** @file + +Copyright (c) 2004 - 2008, 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 PI spec. + +**/ + +#include +#include +#include +#include + +#include +#include +#include + +#include "CommonLib.h" +#include "Compress.h" +#include "Crc32.h" +#include "EfiUtilityMsgs.h" +#include "ParseInf.h" + +// +// GenSec Tool Information +// +#define UTILITY_NAME "GenSec" +#define UTILITY_MAJOR_VERSION 0 +#define UTILITY_MINOR_VERSION 1 + +#define MAX_SECTION_SIZE 0x1000000 + +STATIC CHAR8 *mSectionTypeName[] = { + 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 + "EFI_SECTION_SMM_DEPEX" // 0x1C +}; + +STATIC CHAR8 *mCompressionTypeName[] = { "PI_NONE", "PI_STD" }; + +#define EFI_GUIDED_SECTION_NONE 0x80 +STATIC CHAR8 *mGUIDedSectionAttribue[] = { "NONE", "PROCESSING_REQUIRED", "AUTH_STATUS_VALID"}; + +// +// Crc32 GUID section related definitions. +// +typedef struct { + EFI_GUID_DEFINED_SECTION GuidSectionHeader; + UINT32 CRC32Checksum; +} CRC32_SECTION_HEADER; + +STATIC EFI_GUID mZeroGuid = {0x0, 0x0, 0x0, {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}; +STATIC EFI_GUID mEfiCrc32SectionGuid = EFI_CRC32_GUIDED_SECTION_EXTRACTION_PROTOCOL_GUID; + +STATIC +VOID +Version ( + VOID + ) +/*++ + +Routine Description: + + Print out version information for this utility. + +Arguments: + + None + +Returns: + + None + +--*/ +{ + fprintf (stdout, "%s Version %d.%d\n", UTILITY_NAME, UTILITY_MAJOR_VERSION, UTILITY_MINOR_VERSION); +} + +STATIC +VOID +Usage ( + VOID + ) +/*++ + +Routine Description: + + Print Help message. + +Arguments: + + VOID + +Returns: + + None + +--*/ +{ + // + // Summary usage + // + fprintf (stdout, "\nUsage: %s [options] [input_file]\n\n", UTILITY_NAME); + + // + // Copyright declaration + // + fprintf (stdout, "Copyright (c) 2007, Intel Corporation. All rights reserved.\n\n"); + + // + // Details Option + // + fprintf (stdout, "Options:\n"); + fprintf (stdout, " -o FileName, --outputfile FileName\n\ + File is the SectionFile to be created.\n"); + fprintf (stdout, " -s [SectionType], --sectiontype [SectionType]\n\ + SectionType defined in PI spec is one type of\n\ + EFI_SECTION_COMPRESSION, EFI_SECTION_GUID_DEFINED,\n\ + EFI_SECTION_PE32, EFI_SECTION_PIC, EFI_SECTION_TE,\n\ + EFI_SECTION_DXE_DEPEX, EFI_SECTION_COMPATIBILITY16,\n\ + EFI_SECTION_USER_INTERFACE, EFI_SECTION_VERSION,\n\ + EFI_SECTION_FIRMWARE_VOLUME_IMAGE, EFI_SECTION_RAW,\n\ + EFI_SECTION_FREEFORM_SUBTYPE_GUID,\n\ + EFI_SECTION_PEI_DEPEX. if -s option is not given, \n\ + EFI_SECTION_ALL is default section type.\n"); + fprintf (stdout, " -c [Type], --compress [Type]\n\ + Compress method type can be PI_NONE or PI_STD.\n\ + if -c option is not given, PI_STD is default type.\n"); + fprintf (stdout, " -g GuidValue, --vendor GuidValue\n\ + GuidValue is one specific vendor guid value.\n\ + Its format is xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\n"); + fprintf (stdout, " -l GuidHeaderLength, --HeaderLength GuidHeaderLength\n\ + GuidHeaderLength is the size of header of guided data\n"); + fprintf (stdout, " -r GuidAttr, --attributes GuidAttr\n\ + GuidAttr is guid section atttributes, which may be\n\ + PROCESSING_REQUIRED, AUTH_STATUS_VALID and NONE. \n\ + if -r option is not given, default PROCESSING_REQUIRED\n"); + fprintf (stdout, " -n String, --name String\n\ + String is a NULL terminated string used in Ui section.\n"); + fprintf (stdout, " -j Number, --buildnumber Number\n\ + Number is an integer value between 0000 and 9999\n\ + used in Ver section.\n"); + fprintf (stdout, " -v, --verbose Turn on verbose output with informational messages.\n"); + fprintf (stdout, " -q, --quiet Disable all messages except key message and fatal error\n"); + fprintf (stdout, " -d, --debug level Enable debug messages, at input debug level.\n"); + fprintf (stdout, " --version Show program's version number and exit.\n"); + fprintf (stdout, " -h, --help Show this help message and exit.\n"); +} + +VOID +Ascii2UnicodeString ( + CHAR8 *String, + CHAR16 *UniString + ) +/*++ + +Routine Description: + + Write ascii string as unicode string format to FILE + +Arguments: + + String - Pointer to string that is written to FILE. + UniString - Pointer to unicode string + +Returns: + + NULL + +--*/ +{ + while (*String != '\0') { + *(UniString++) = (CHAR16) *(String++); + } + // + // End the UniString with a NULL. + // + *UniString = '\0'; +} + +STATUS +GenSectionCommonLeafSection ( + CHAR8 **InputFileName, + UINT32 InputFileNum, + UINT8 SectionType, + UINT8 **OutFileBuffer + ) +/*++ + +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 + + OutFileBuffer - Buffer pointer to Output file contents + +Returns: + + STATUS_ERROR - can't continue + STATUS_SUCCESS - successful return + +--*/ +{ + UINT32 InputFileLength; + FILE *InFile; + UINT8 *Buffer; + UINT32 TotalLength; + EFI_COMMON_SECTION_HEADER *CommonSect; + STATUS Status; + + if (InputFileNum > 1) { + Error (NULL, 0, 2000, "Invalid paramter", "more than one input file specified"); + return STATUS_ERROR; + } else if (InputFileNum < 1) { + Error (NULL, 0, 2000, "Invalid paramter", "no input file specified"); + return STATUS_ERROR; + } + // + // Open the input file + // + InFile = fopen (InputFileName[0], "rb"); + if (InFile == NULL) { + Error (NULL, 0, 0001, "Error opening file", InputFileName[0]); + 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); + InputFileLength = ftell (InFile); + fseek (InFile, 0, SEEK_SET); + DebugMsg (NULL, 0, 9, "Input file", "File name is %s and File size is %d bytes", InputFileName[0], InputFileLength); + TotalLength = sizeof (EFI_COMMON_SECTION_HEADER) + InputFileLength; + // + // Size must fit in 3 bytes + // + if (TotalLength >= MAX_SECTION_SIZE) { + Error (NULL, 0, 2000, "Invalid paramter", "%s file size (0x%X) exceeds section size limit(%dM).", InputFileName[0], TotalLength, MAX_SECTION_SIZE>>20); + goto Done; + } + VerboseMsg ("the size of the created section file is %d bytes", TotalLength); + // + // Fill in the fields in the local section header structure + // + Buffer = (UINT8 *) malloc ((size_t) TotalLength); + if (Buffer == NULL) { + Error (NULL, 0, 4001, "Resource", "memory cannot be allcoated"); + goto Done; + } + CommonSect = (EFI_COMMON_SECTION_HEADER *) Buffer; + CommonSect->Type = SectionType; + CommonSect->Size[0] = (UINT8) (TotalLength & 0xff); + CommonSect->Size[1] = (UINT8) ((TotalLength & 0xff00) >> 8); + CommonSect->Size[2] = (UINT8) ((TotalLength & 0xff0000) >> 16); + + // + // read data from the input file. + // + if (InputFileLength != 0) { + if (fread (Buffer + sizeof (EFI_COMMON_SECTION_HEADER), (size_t) InputFileLength, 1, InFile) != 1) { + Error (NULL, 0, 0004, "Error reading file", InputFileName[0]); + goto Done; + } + } + + // + // Set OutFileBuffer + // + *OutFileBuffer = Buffer; + Status = STATUS_SUCCESS; + +Done: + fclose (InFile); + + return Status; +} + +EFI_STATUS +GetSectionContents ( + CHAR8 **InputFileName, + UINT32 InputFileNum, + UINT8 *FileBuffer, + UINT32 *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 - On input, this is size of the FileBuffer. + On output, this is the actual length of the data. + +Returns: + + EFI_SUCCESS on successful return + EFI_INVALID_PARAMETER if InputFileNum is less than 1 or BufferLength point is NULL. + EFI_ABORTED if unable to open input file. + EFI_BUFFER_TOO_SMALL FileBuffer is not enough to contain all file data. +--*/ +{ + UINT32 Size; + UINT32 FileSize; + UINT32 Index; + FILE *InFile; + + if (InputFileNum < 1) { + Error (NULL, 0, 2000, "Invalid paramter", "must specify at least one input file"); + return EFI_INVALID_PARAMETER; + } + + if (BufferLength == NULL) { + Error (NULL, 0, 2000, "Invalid paramter", "BufferLength can't be 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++) { + // + // make sure section ends on a DWORD boundary + // + while ((Size & 0x03) != 0) { + if (FileBuffer != NULL && Size < *BufferLength) { + FileBuffer[Size] = 0; + } + Size++; + } + + // + // Open file and read contents + // + InFile = fopen (InputFileName[Index], "rb"); + if (InFile == NULL) { + Error (NULL, 0, 0001, "Error opening file", InputFileName[Index]); + return EFI_ABORTED; + } + + fseek (InFile, 0, SEEK_END); + FileSize = ftell (InFile); + fseek (InFile, 0, SEEK_SET); + DebugMsg (NULL, 0, 9, "Input files", "the input file name is %s and the size is %d bytes", InputFileName[Index], FileSize); + // + // Now read the contents of the file into the buffer + // Buffer must be enough to contain the file content. + // + if (FileSize > 0 && FileBuffer != NULL && (Size + FileSize) <= *BufferLength) { + if (fread (FileBuffer + Size, (size_t) FileSize, 1, InFile) != 1) { + Error (NULL, 0, 0004, "Error reading file", InputFileName[Index]); + fclose (InFile); + return EFI_ABORTED; + } + } + + fclose (InFile); + Size += FileSize; + } + + // + // Set the real required buffer size. + // + if (Size > *BufferLength) { + *BufferLength = Size; + return EFI_BUFFER_TOO_SMALL; + } else { + *BufferLength = Size; + return EFI_SUCCESS; + } +} + +EFI_STATUS +GenSectionCompressionSection ( + CHAR8 **InputFileName, + UINT32 InputFileNum, + UINT8 SectCompSubType, + UINT8 **OutFileBuffer + ) +/*++ + +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. + + SectCompSubType - Specify the compression algorithm requested. + + OutFileBuffer - Buffer pointer to Output file contents + +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. +--*/ +{ + UINT32 TotalLength; + UINT32 InputLength; + UINT32 CompressedLength; + UINT8 *FileBuffer; + UINT8 *OutputBuffer; + EFI_STATUS Status; + EFI_COMPRESSION_SECTION *CompressionSect; + COMPRESS_FUNCTION CompressFunction; + + InputLength = 0; + FileBuffer = NULL; + OutputBuffer = NULL; + CompressedLength = 0; + // + // read all input file contents into a buffer + // first get the size of all file contents + // + Status = GetSectionContents ( + InputFileName, + InputFileNum, + FileBuffer, + &InputLength + ); + + if (Status == EFI_BUFFER_TOO_SMALL) { + FileBuffer = (UINT8 *) malloc (InputLength); + if (FileBuffer == NULL) { + Error (NULL, 0, 4001, "Resource", "memory cannot be allcoated"); + return EFI_OUT_OF_RESOURCES; + } + // + // read all input file contents into a buffer + // + Status = GetSectionContents ( + InputFileName, + InputFileNum, + FileBuffer, + &InputLength + ); + } + + if (EFI_ERROR (Status)) { + if (FileBuffer != NULL) { + free (FileBuffer); + } + return Status; + } + + CompressFunction = NULL; + + // + // Now data is in FileBuffer, compress the data + // + switch (SectCompSubType) { + case EFI_NOT_COMPRESSED: + CompressedLength = InputLength; + break; + + case EFI_STANDARD_COMPRESSION: + CompressFunction = (COMPRESS_FUNCTION) EfiCompress; + break; + + default: + Error (NULL, 0, 2000, "Invalid paramter", "unknown compression type"); + free (FileBuffer); + return EFI_ABORTED; + } + + if (CompressFunction != NULL) { + + Status = CompressFunction (FileBuffer, InputLength, OutputBuffer, &CompressedLength); + if (Status == EFI_BUFFER_TOO_SMALL) { + OutputBuffer = malloc (CompressedLength + sizeof (EFI_COMPRESSION_SECTION)); + if (!OutputBuffer) { + free (FileBuffer); + return EFI_OUT_OF_RESOURCES; + } + + Status = CompressFunction (FileBuffer, InputLength, OutputBuffer + sizeof (EFI_COMPRESSION_SECTION), &CompressedLength); + } + + free (FileBuffer); + FileBuffer = OutputBuffer; + + if (EFI_ERROR (Status)) { + if (FileBuffer != NULL) { + free (FileBuffer); + } + + return Status; + } + } + + DebugMsg (NULL, 0, 9, "comprss file size", + "the original section size is %d bytes and the compressed section size is %d bytes", InputLength, CompressedLength); + TotalLength = CompressedLength + sizeof (EFI_COMPRESSION_SECTION); + if (TotalLength >= MAX_SECTION_SIZE) { + Error (NULL, 0, 2000, "Invalid paramter", "The size of all files exceeds section size limit(%dM).", MAX_SECTION_SIZE>>20); + if (FileBuffer != NULL) { + free (FileBuffer); + } + if (OutputBuffer != NULL) { + free (OutputBuffer); + } + return STATUS_ERROR; + } + VerboseMsg ("the size of the created section file is %d bytes", TotalLength); + + // + // Add the section header for the compressed data + // + CompressionSect = (EFI_COMPRESSION_SECTION *) FileBuffer; + + CompressionSect->CommonHeader.Type = EFI_SECTION_COMPRESSION; + 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 = SectCompSubType; + CompressionSect->UncompressedLength = InputLength; + + // + // Set OutFileBuffer + // + *OutFileBuffer = FileBuffer; + + return EFI_SUCCESS; +} + +EFI_STATUS +GenSectionGuidDefinedSection ( + CHAR8 **InputFileName, + UINT32 InputFileNum, + EFI_GUID *VendorGuid, + UINT16 DataAttribute, + UINT32 DataHeaderSize, + UINT8 **OutFileBuffer + ) +/*++ + +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. + + VendorGuid - Specify vendor guid value. + + DataAttribute - Specify attribute for the vendor guid data. + + DataHeaderSize- Guided Data Header Size + + OutFileBuffer - Buffer pointer to Output file contents + +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. + +--*/ +{ + UINT32 TotalLength; + UINT32 InputLength; + UINT32 Offset; + UINT8 *FileBuffer; + UINT32 Crc32Checksum; + EFI_STATUS Status; + CRC32_SECTION_HEADER *Crc32GuidSect; + EFI_GUID_DEFINED_SECTION *VendorGuidSect; + + InputLength = 0; + Offset = 0; + FileBuffer = NULL; + + if (CompareGuid (VendorGuid, &mEfiCrc32SectionGuid) == 0) { + Offset = sizeof (CRC32_SECTION_HEADER); + } else { + Offset = sizeof (EFI_GUID_DEFINED_SECTION); + } + + // + // read all input file contents into a buffer + // first get the size of all file contents + // + Status = GetSectionContents ( + InputFileName, + InputFileNum, + FileBuffer, + &InputLength + ); + + if (Status == EFI_BUFFER_TOO_SMALL) { + FileBuffer = (UINT8 *) malloc (InputLength + Offset); + if (FileBuffer == NULL) { + Error (NULL, 0, 4001, "Resource", "memory cannot be allcoated"); + return EFI_OUT_OF_RESOURCES; + } + // + // read all input file contents into a buffer + // + Status = GetSectionContents ( + InputFileName, + InputFileNum, + FileBuffer + Offset, + &InputLength + ); + } + + if (EFI_ERROR (Status)) { + if (FileBuffer != NULL) { + free (FileBuffer); + } + Error (NULL, 0, 0001, "Error opening file for reading", InputFileName[0]); + return Status; + } + + if (InputLength == 0) { + Error (NULL, 0, 2000, "Invalid parameter", "the size of input file %s can't be zero", InputFileName); + return EFI_NOT_FOUND; + } + + // + // Now data is in FileBuffer + Offset + // + if (CompareGuid (VendorGuid, &mEfiCrc32SectionGuid) == 0) { + // + // Default Guid section is CRC32. + // + Crc32Checksum = 0; + CalculateCrc32 (FileBuffer + Offset, InputLength, &Crc32Checksum); + + TotalLength = InputLength + sizeof (CRC32_SECTION_HEADER); + if (TotalLength >= MAX_SECTION_SIZE) { + Error (NULL, 0, 2000, "Invalid paramter", "The size of all files exceeds section size limit(%dM).", MAX_SECTION_SIZE>>20); + free (FileBuffer); + return STATUS_ERROR; + } + + Crc32GuidSect = (CRC32_SECTION_HEADER *) FileBuffer; + Crc32GuidSect->GuidSectionHeader.CommonHeader.Type = EFI_SECTION_GUID_DEFINED; + 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), &mEfiCrc32SectionGuid, sizeof (EFI_GUID)); + Crc32GuidSect->GuidSectionHeader.Attributes = EFI_GUIDED_SECTION_AUTH_STATUS_VALID; + Crc32GuidSect->GuidSectionHeader.DataOffset = sizeof (CRC32_SECTION_HEADER); + Crc32GuidSect->CRC32Checksum = Crc32Checksum; + DebugMsg (NULL, 0, 9, "Guided section", "Data offset is %d", Crc32GuidSect->GuidSectionHeader.DataOffset); + + } else { + TotalLength = InputLength + sizeof (EFI_GUID_DEFINED_SECTION); + if (TotalLength >= MAX_SECTION_SIZE) { + Error (NULL, 0, 2000, "Invalid paramter", "The size of all files exceeds section size limit(%dM).", MAX_SECTION_SIZE>>20); + free (FileBuffer); + return STATUS_ERROR; + } + + VendorGuidSect = (EFI_GUID_DEFINED_SECTION *) FileBuffer; + VendorGuidSect->CommonHeader.Type = EFI_SECTION_GUID_DEFINED; + VendorGuidSect->CommonHeader.Size[0] = (UINT8) (TotalLength & 0xff); + VendorGuidSect->CommonHeader.Size[1] = (UINT8) ((TotalLength & 0xff00) >> 8); + VendorGuidSect->CommonHeader.Size[2] = (UINT8) ((TotalLength & 0xff0000) >> 16); + memcpy (&(VendorGuidSect->SectionDefinitionGuid), VendorGuid, sizeof (EFI_GUID)); + VendorGuidSect->Attributes = DataAttribute; + VendorGuidSect->DataOffset = sizeof (EFI_GUID_DEFINED_SECTION) + DataHeaderSize; + DebugMsg (NULL, 0, 9, "Guided section", "Data offset is %d", VendorGuidSect->DataOffset); + } + VerboseMsg ("the size of the created section file is %d bytes", TotalLength); + + // + // Set OutFileBuffer + // + *OutFileBuffer = 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. + +--*/ +{ + UINT32 Index; + UINT32 InputFileNum; + FILE *InFile; + FILE *OutFile; + CHAR8 **InputFileName; + CHAR8 *OutputFileName; + CHAR8 *SectionName; + CHAR8 *CompressionName; + CHAR8 *StringBuffer; + EFI_GUID VendorGuid = mZeroGuid; + INT32 VersionNumber; + UINT8 SectType; + UINT8 SectCompSubType; + UINT16 SectGuidAttribute; + UINT64 SectGuidHeaderLength; + EFI_VERSION_SECTION *VersionSect; + EFI_USER_INTERFACE_SECTION *UiSect; + UINT32 InputLength; + UINT8 *OutFileBuffer; + EFI_STATUS Status; + UINT64 LogLevel; + + InputFileName = NULL; + OutputFileName = NULL; + SectionName = NULL; + CompressionName = NULL; + StringBuffer = ""; + InFile = NULL; + OutFile = NULL; + VersionNumber = 0; + InputFileNum = 0; + SectType = EFI_SECTION_ALL; + SectCompSubType = 0; + SectGuidAttribute = 0; + OutFileBuffer = NULL; + InputLength = 0; + Status = STATUS_SUCCESS; + LogLevel = 0; + SectGuidHeaderLength = 0; + VersionSect = NULL; + UiSect = NULL; + + SetUtilityName (UTILITY_NAME); + + if (argc == 1) { + Error (NULL, 0, 1001, "Missing options", "No options input"); + Usage (); + return STATUS_ERROR; + } + + // + // Parse command line + // + argc --; + argv ++; + + if ((stricmp (argv[0], "-h") == 0) || (stricmp (argv[0], "--help") == 0)) { + Version (); + Usage (); + return STATUS_SUCCESS; + } + + if (stricmp (argv[0], "--version") == 0) { + Version (); + return STATUS_SUCCESS; + } + + while (argc > 0) { + if ((stricmp (argv[0], "-s") == 0) || (stricmp (argv[0], "--SectionType") == 0)) { + SectionName = argv[1]; + if (SectionName == NULL) { + Error (NULL, 0, 1003, "Invalid option value", "Section Type can't be NULL"); + goto Finish; + } + argc -= 2; + argv += 2; + continue; + } + + if ((stricmp (argv[0], "-o") == 0) || (stricmp (argv[0], "--outputfile") == 0)) { + OutputFileName = argv[1]; + if (OutputFileName == NULL) { + Error (NULL, 0, 1003, "Invalid option value", "Output file can't be NULL"); + goto Finish; + } + argc -= 2; + argv += 2; + continue; + } + + if ((stricmp (argv[0], "-c") == 0) || (stricmp (argv[0], "--compress") == 0)) { + CompressionName = argv[1]; + if (CompressionName == NULL) { + Error (NULL, 0, 1003, "Invalid option value", "Compression Type can't be NULL"); + goto Finish; + } + argc -= 2; + argv += 2; + continue; + } + + if ((stricmp (argv[0], "-g") == 0) || (stricmp (argv[0], "--vendor") == 0)) { + Status = StringToGuid (argv[1], &VendorGuid); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]); + goto Finish; + } + argc -= 2; + argv += 2; + continue; + } + + if ((stricmp (argv[0], "-r") == 0) || (stricmp (argv[0], "--attributes") == 0)) { + if (stricmp (argv[1], mGUIDedSectionAttribue[EFI_GUIDED_SECTION_PROCESSING_REQUIRED]) == 0) { + SectGuidAttribute |= EFI_GUIDED_SECTION_PROCESSING_REQUIRED; + } else if (stricmp (argv[1], mGUIDedSectionAttribue[EFI_GUIDED_SECTION_AUTH_STATUS_VALID]) == 0) { + SectGuidAttribute |= EFI_GUIDED_SECTION_AUTH_STATUS_VALID; + } else if (stricmp (argv[1], mGUIDedSectionAttribue[0]) == 0) { + // + // NONE attribute + // + SectGuidAttribute |= EFI_GUIDED_SECTION_NONE; + } else { + Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]); + goto Finish; + } + argc -= 2; + argv += 2; + continue; + } + + if ((stricmp (argv[0], "-l") == 0) || (stricmp (argv[0], "--HeaderLength") == 0)) { + Status = AsciiStringToUint64 (argv[1], FALSE, &SectGuidHeaderLength); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 1003, "Invalid option value for GuidHeaderLength", "%s = %s", argv[0], argv[1]); + goto Finish; + } + argc -= 2; + argv += 2; + continue; + } + + if ((stricmp (argv[0], "-n") == 0) || (stricmp (argv[0], "--name") == 0)) { + StringBuffer = argv[1]; + if (StringBuffer == NULL) { + Error (NULL, 0, 1003, "Invalid option value", "Name can't be NULL"); + goto Finish; + } + argc -= 2; + argv += 2; + continue; + } + + if ((stricmp (argv[0], "-j") == 0) || (stricmp (argv[0], "--buildnumber") == 0)) { + if (argv[1] == NULL) { + Error (NULL, 0, 1003, "Invalid option value", "build number can't be NULL"); + goto Finish; + } + // + // Verify string is a integrator number + // + for (Index = 0; Index < strlen (argv[1]); Index++) { + if ((argv[1][Index] != '-') && (isdigit (argv[1][Index]) == 0)) { + Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]); + goto Finish; + } + } + + sscanf (argv[1], "%d", &VersionNumber); + argc -= 2; + argv += 2; + continue; + } + + if ((stricmp (argv[0], "-v") == 0) || (stricmp (argv[0], "--verbose") == 0)) { + SetPrintLevel (VERBOSE_LOG_LEVEL); + VerboseMsg ("Verbose output Mode Set!"); + argc --; + argv ++; + continue; + } + + if ((stricmp (argv[0], "-q") == 0) || (stricmp (argv[0], "--quiet") == 0)) { + SetPrintLevel (KEY_LOG_LEVEL); + KeyMsg ("Quiet output Mode Set!"); + argc --; + argv ++; + continue; + } + + if ((stricmp (argv[0], "-d") == 0) || (stricmp (argv[0], "--debug") == 0)) { + Status = AsciiStringToUint64 (argv[1], FALSE, &LogLevel); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]); + goto Finish; + } + if (LogLevel > 9) { + Error (NULL, 0, 1003, "Invalid option value", "Debug Level range is 0~9, currnt input level is %d", LogLevel); + goto Finish; + } + SetPrintLevel (LogLevel); + DebugMsg (NULL, 0, 9, "Debug Mode Set", "Debug Output Mode Level %s is set!", argv[1]); + argc -= 2; + argv += 2; + continue; + } + + // + // Get Input file name + // + if ((InputFileNum == 0) && (InputFileName == NULL)) { + InputFileName = (CHAR8 **) malloc (MAXIMUM_INPUT_FILE_NUM * sizeof (CHAR8 *)); + if (InputFileName == NULL) { + Error (NULL, 0, 4001, "Resource", "memory cannot be allcoated"); + return 1; + } + + memset (InputFileName, 0, (MAXIMUM_INPUT_FILE_NUM * sizeof (CHAR8 *))); + } else if (InputFileNum % MAXIMUM_INPUT_FILE_NUM == 0) { + // + // InputFileName buffer too small, need to realloc + // + InputFileName = (CHAR8 **) realloc ( + InputFileName, + (InputFileNum + MAXIMUM_INPUT_FILE_NUM) * sizeof (CHAR8 *) + ); + + if (InputFileName == NULL) { + Error (NULL, 0, 4001, "Resource", "memory cannot be allcoated"); + return 1; + } + + memset (&(InputFileName[InputFileNum]), 0, (MAXIMUM_INPUT_FILE_NUM * sizeof (CHAR8 *))); + } + + InputFileName[InputFileNum++] = argv[0]; + argc --; + argv ++; + } + + VerboseMsg ("%s tool start.", UTILITY_NAME); + + // + // Parse all command line parameters to get the corresponding section type. + // + VerboseMsg ("Section type is %s", SectionName); + if (SectionName == NULL) { + // + // No specified Section type, default is SECTION_ALL. + // + SectType = EFI_SECTION_ALL; + } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_COMPRESSION]) == 0) { + SectType = EFI_SECTION_COMPRESSION; + if (CompressionName == NULL) { + // + // Default is PI_STD compression algorithm. + // + SectCompSubType = EFI_STANDARD_COMPRESSION; + } else if (stricmp (CompressionName, mCompressionTypeName[EFI_NOT_COMPRESSED]) == 0) { + SectCompSubType = EFI_NOT_COMPRESSED; + } else if (stricmp (CompressionName, mCompressionTypeName[EFI_STANDARD_COMPRESSION]) == 0) { + SectCompSubType = EFI_STANDARD_COMPRESSION; + } else { + Error (NULL, 0, 1003, "Invalid option value", "--compress = %s", CompressionName); + goto Finish; + } + VerboseMsg ("Compress method is %s", mCompressionTypeName [SectCompSubType]); + } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_GUID_DEFINED]) == 0) { + SectType = EFI_SECTION_GUID_DEFINED; + + if (CompareGuid (&VendorGuid, &mZeroGuid) == 0) { + memcpy (&VendorGuid, &mEfiCrc32SectionGuid, sizeof (EFI_GUID)); + } + + if (SectGuidAttribute == 0) { + SectGuidAttribute = EFI_GUIDED_SECTION_PROCESSING_REQUIRED; + } + if ((SectGuidAttribute & EFI_GUIDED_SECTION_NONE) != 0) { + // + // NONE attribute, clear attribute value. + // + SectGuidAttribute = 0; + } + VerboseMsg ("Vendor Guid is %08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X", + VendorGuid.Data1, + VendorGuid.Data2, + VendorGuid.Data3, + VendorGuid.Data4[0], + VendorGuid.Data4[1], + VendorGuid.Data4[2], + VendorGuid.Data4[3], + VendorGuid.Data4[4], + VendorGuid.Data4[5], + VendorGuid.Data4[6], + VendorGuid.Data4[7]); + if ((SectGuidAttribute & EFI_GUIDED_SECTION_PROCESSING_REQUIRED) != 0) { + VerboseMsg ("Guid Attribute is %s", mGUIDedSectionAttribue[EFI_GUIDED_SECTION_PROCESSING_REQUIRED]); + } + if ((SectGuidAttribute & EFI_GUIDED_SECTION_AUTH_STATUS_VALID) != 0) { + VerboseMsg ("Guid Attribute is %s", mGUIDedSectionAttribue[EFI_GUIDED_SECTION_AUTH_STATUS_VALID]); + } + if (SectGuidHeaderLength != 0) { + VerboseMsg ("Guid Data Header size is 0x%x", SectGuidHeaderLength); + } + } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_PE32]) == 0) { + SectType = EFI_SECTION_PE32; + } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_PIC]) == 0) { + SectType = EFI_SECTION_PIC; + } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_TE]) == 0) { + SectType = EFI_SECTION_TE; + } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_DXE_DEPEX]) == 0) { + SectType = EFI_SECTION_DXE_DEPEX; + } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_VERSION]) == 0) { + SectType = EFI_SECTION_VERSION; + if (VersionNumber < 0 || VersionNumber > 9999) { + Error (NULL, 0, 1003, "Invalid option value", "%d is not in 0~9999", VersionNumber); + goto Finish; + } + VerboseMsg ("Version section number is %d", VersionNumber); + } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_USER_INTERFACE]) == 0) { + SectType = EFI_SECTION_USER_INTERFACE; + if (StringBuffer[0] == '\0') { + Error (NULL, 0, 1001, "Missing option", "user interface string"); + goto Finish; + } + VerboseMsg ("UI section string name is %s", StringBuffer); + } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_COMPATIBILITY16]) == 0) { + SectType = EFI_SECTION_COMPATIBILITY16; + } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_FIRMWARE_VOLUME_IMAGE]) == 0) { + SectType = EFI_SECTION_FIRMWARE_VOLUME_IMAGE; + } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_FREEFORM_SUBTYPE_GUID]) == 0) { + SectType = EFI_SECTION_FREEFORM_SUBTYPE_GUID; + } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_RAW]) == 0) { + SectType = EFI_SECTION_RAW; + } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_PEI_DEPEX]) == 0) { + SectType = EFI_SECTION_PEI_DEPEX; + } else { + Error (NULL, 0, 1003, "Invalid option value", "SectionType = %s", SectionName); + goto Finish; + } + + // + // GuidValue is only required by Guided section. + // + if ((SectType != EFI_SECTION_GUID_DEFINED) && (CompareGuid (&VendorGuid, &mZeroGuid) != 0)) { + fprintf (stdout, "Warning: the input guid value is not required for this section type %s\n", SectionName); + } + + // + // Check whether there is input file + // + if ((SectType != EFI_SECTION_VERSION) && (SectType != EFI_SECTION_USER_INTERFACE)) { + // + // The input file are required for other section type. + // + if (InputFileNum == 0) { + Error (NULL, 0, 1001, "Missing options", "Input files"); + goto Finish; + } + } + // + // Check whether there is output file + // + for (Index = 0; Index < InputFileNum; Index ++) { + VerboseMsg ("the %dth input file name is %s", Index, InputFileName[Index]); + } + if (OutputFileName == NULL) { + Error (NULL, 0, 1001, "Missing options", "Output file"); + goto Finish; + // OutFile = stdout; + } + VerboseMsg ("Output file name is %s", OutputFileName); + + // + // 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 (SectType) { + case EFI_SECTION_COMPRESSION: + Status = GenSectionCompressionSection ( + InputFileName, + InputFileNum, + SectCompSubType, + &OutFileBuffer + ); + break; + + case EFI_SECTION_GUID_DEFINED: + Status = GenSectionGuidDefinedSection ( + InputFileName, + InputFileNum, + &VendorGuid, + SectGuidAttribute, + (UINT32) SectGuidHeaderLength, + &OutFileBuffer + ); + break; + + case EFI_SECTION_VERSION: + Index = sizeof (EFI_COMMON_SECTION_HEADER); + // + // 2 bytes for the build number UINT16 + // + Index += 2; + // + // StringBuffer is ascii.. unicode is 2X + 2 bytes for terminating unicode null. + // + Index += (strlen (StringBuffer) * 2) + 2; + OutFileBuffer = (UINT8 *) malloc (Index); + if (OutFileBuffer == NULL) { + Error (NULL, 0, 4001, "Resource", "memory cannot be allcoated"); + goto Finish; + } + VersionSect = (EFI_VERSION_SECTION *) OutFileBuffer; + VersionSect->CommonHeader.Type = SectType; + VersionSect->CommonHeader.Size[0] = (UINT8) (Index & 0xff); + VersionSect->CommonHeader.Size[1] = (UINT8) ((Index & 0xff00) >> 8); + VersionSect->CommonHeader.Size[2] = (UINT8) ((Index & 0xff0000) >> 16); + VersionSect->BuildNumber = (UINT16) VersionNumber; + Ascii2UnicodeString (StringBuffer, VersionSect->VersionString); + VerboseMsg ("the size of the created section file is %d bytes", Index); + break; + + case EFI_SECTION_USER_INTERFACE: + Index = sizeof (EFI_COMMON_SECTION_HEADER); + // + // StringBuffer is ascii.. unicode is 2X + 2 bytes for terminating unicode null. + // + Index += (strlen (StringBuffer) * 2) + 2; + OutFileBuffer = (UINT8 *) malloc (Index); + if (OutFileBuffer == NULL) { + Error (NULL, 0, 4001, "Resource", "memory cannot be allcoated"); + goto Finish; + } + UiSect = (EFI_USER_INTERFACE_SECTION *) OutFileBuffer; + UiSect->CommonHeader.Type = SectType; + UiSect->CommonHeader.Size[0] = (UINT8) (Index & 0xff); + UiSect->CommonHeader.Size[1] = (UINT8) ((Index & 0xff00) >> 8); + UiSect->CommonHeader.Size[2] = (UINT8) ((Index & 0xff0000) >> 16); + Ascii2UnicodeString (StringBuffer, UiSect->FileNameString); + VerboseMsg ("the size of the created section file is %d bytes", Index); + break; + + case EFI_SECTION_ALL: + // + // read all input file contents into a buffer + // first get the size of all file contents + // + Status = GetSectionContents ( + InputFileName, + InputFileNum, + OutFileBuffer, + &InputLength + ); + + if (Status == EFI_BUFFER_TOO_SMALL) { + OutFileBuffer = (UINT8 *) malloc (InputLength); + if (OutFileBuffer == NULL) { + Error (NULL, 0, 4001, "Resource", "memory cannot be allcoated"); + goto Finish; + } + // + // read all input file contents into a buffer + // + Status = GetSectionContents ( + InputFileName, + InputFileNum, + OutFileBuffer, + &InputLength + ); + } + VerboseMsg ("the size of the created section file is %d bytes", InputLength); + break; + default: + // + // All other section types are caught by default (they're all the same) + // + Status = GenSectionCommonLeafSection ( + InputFileName, + InputFileNum, + SectType, + &OutFileBuffer + ); + break; + } + + if (Status != EFI_SUCCESS || OutFileBuffer == NULL) { + Error (NULL, 0, 2000, "Status is not successful", "Status value is 0x%X", (UINTN) Status); + goto Finish; + } + + // + // Get output file length + // + if (SectType != EFI_SECTION_ALL) { + InputLength = SECTION_SIZE (OutFileBuffer); + } + + // + // Write the output file + // + OutFile = fopen (OutputFileName, "wb"); + if (OutFile == NULL) { + Error (NULL, 0, 0001, "Error opening file for writing", OutputFileName); + goto Finish; + } + + fwrite (OutFileBuffer, InputLength, 1, OutFile); + +Finish: + if (InputFileName != NULL) { + free (InputFileName); + } + + if (OutFileBuffer != NULL) { + free (OutFileBuffer); + } + + if (OutFile != NULL) { + fclose (OutFile); + } + + VerboseMsg ("%s tool done with return code is 0x%x.", UTILITY_NAME, GetUtilityStatus ()); + + return GetUtilityStatus (); +} diff --git a/BaseTools/Source/C/GenSec/Makefile b/BaseTools/Source/C/GenSec/Makefile new file mode 100644 index 0000000000..502735bfea --- /dev/null +++ b/BaseTools/Source/C/GenSec/Makefile @@ -0,0 +1,12 @@ +!INCLUDE ..\Makefiles\ms.common + +APPNAME = GenSec + +LIBS = $(LIB_PATH)\Common.lib + +OBJECTS = GenSec.obj + +#CFLAGS = $(CFLAGS) /nodefaultlib:libc.lib + +!INCLUDE ..\Makefiles\ms.app + diff --git a/BaseTools/Source/C/GenVtf/GNUmakefile b/BaseTools/Source/C/GenVtf/GNUmakefile new file mode 100644 index 0000000000..2449bb8ed5 --- /dev/null +++ b/BaseTools/Source/C/GenVtf/GNUmakefile @@ -0,0 +1,10 @@ +ARCH ?= IA32 +MAKEROOT ?= .. + +APPNAME = GenVtf + +LIBS = -lCommon + +OBJECTS = GenVtf.o + +include $(MAKEROOT)/Makefiles/app.makefile diff --git a/BaseTools/Source/C/GenVtf/GenVtf.c b/BaseTools/Source/C/GenVtf/GenVtf.c new file mode 100644 index 0000000000..e633b7ccf8 --- /dev/null +++ b/BaseTools/Source/C/GenVtf/GenVtf.c @@ -0,0 +1,2721 @@ +/** + +Copyright (c) 1999 - 2008, 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: + + GenVtf.c + +Abstract: + + This file contains functions required to generate a boot strap file (BSF) + also known as the Volume Top File (VTF) + +**/ + +// +// +// +#include +#include +#include "GenVtf.h" +#include +#include "CommonLib.h" +#include "EfiUtilityMsgs.h" + +// +// Global variables +// +UINTN SectionOptionFlag = 0; +UINTN SectionCompFlag = 0; + +UINT64 DebugLevel; +BOOLEAN DebugMode; + +BOOLEAN QuietMode = FALSE; + +BOOLEAN VTF_OUTPUT = FALSE; +CHAR8 *OutFileName1; +CHAR8 *OutFileName2; +CHAR8 *SymFileName; + +CHAR8 **TokenStr; +CHAR8 **OrgStrTokPtr; + +PARSED_VTF_INFO *FileListPtr; +PARSED_VTF_INFO *FileListHeadPtr; + +VOID *Vtf1Buffer; +VOID *Vtf1EndBuffer; +VOID *Vtf2Buffer; +VOID *Vtf2EndBuffer; + +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 VTF Present, if yes then will be used +// to decide about adding FFS header to pad data +// +BOOLEAN VTFPresent = FALSE; +BOOLEAN SecondVTF = FALSE; + +// +// Address related information +// +UINT64 Fv1BaseAddress = 0; +UINT64 Fv2BaseAddress = 0; +UINT64 Fv1EndAddress = 0; +UINT64 Fv2EndAddress = 0; +UINT32 Vtf1TotalSize = SIZE_TO_OFFSET_PAL_A_END; +UINT64 Vtf1LastStartAddress = 0; +UINT32 Vtf2TotalSize = 0; +UINT64 Vtf2LastStartAddress = 0; + +UINT32 BufferToTop = 0; + +// +// IA32 Reset Vector Bin name +// +CHAR8 IA32BinFile[FILE_NAME_SIZE]; + +// +// Function Implementations +// +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; + UINT32 Major; + UINT32 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') && (Char != '\r')) { + 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++; + } +} + +EFI_STATUS +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 + 1]; + CHAR8 Delimit[] = "="; + + Buff [FILE_NAME_SIZE] = '\0'; + Token = NULL; + + while (fgets (Buff, FILE_NAME_SIZE, Fp) != NULL) { + TrimLine (Buff); + if (Buff[0] == 0) { + continue; + } + Token = strtok (Buff, Delimit); + while (Token != NULL) { + strcpy (*TokenStr, Token); + TokenStr ++; + Token = strtok (NULL, Delimit); + } + } + return EFI_SUCCESS; +} + +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 VTF symbol file. + +Arguments: + + None + +Returns: + + EFI_SUCCESS - The function completed successfully + EFI_OUT_OF_RESOURCES - Malloc failed. + +--*/ +{ + + FileListPtr = malloc (sizeof (PARSED_VTF_INFO)); + + if (FileListPtr == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + FileListHeadPtr = FileListPtr; + memset (FileListPtr, 0, sizeof (PARSED_VTF_INFO)); + FileListPtr->NextVtfInfo = NULL; + + remove (SymFileName); + return EFI_SUCCESS; +} + +VOID +ParseAndUpdateComponents ( + IN PARSED_VTF_INFO *VtfInfo + ) +/*++ + +Routine Description: + + This function intializes the relevant global variable which is being + used to store the information retrieved from INF file. + +Arguments: + + VtfInfo - A pointer to the VTF Info Structure + + +Returns: + + None + +--*/ +{ + UINT64 StringValue; + + while (*TokenStr != NULL && (strnicmp (*TokenStr, "COMP_NAME", 9) != 0)) { + + if (strnicmp (*TokenStr, "COMP_LOC", 8) == 0) { + TokenStr++; + if (strnicmp (*TokenStr, "F", 1) == 0) { + VtfInfo->LocationType = FIRST_VTF; + } else if (strnicmp (*TokenStr, "S", 1) == 0) { + VtfInfo->LocationType = SECOND_VTF; + } else { + VtfInfo->LocationType = NONE; + Warning(UTILITY_NAME, 0, 0001, "Unknown location for component.", VtfInfo->CompName); + } + } else if (strnicmp (*TokenStr, "COMP_TYPE", 9) == 0) { + TokenStr++; + if (AsciiStringToUint64 (*TokenStr, FALSE, &StringValue) != EFI_SUCCESS) { + Error (NULL, 0, 5001, "Cannot get: \"0x%x\".", *TokenStr); + return ; + } + + VtfInfo->CompType = (UINT8) StringValue; + } else if (strnicmp (*TokenStr, "COMP_VER", 8) == 0) { + TokenStr++; + if (strnicmp (*TokenStr, "-", 1) == 0) { + VtfInfo->VersionPresent = FALSE; + VtfInfo->MajorVer = 0; + VtfInfo->MinorVer = 0; + } else { + VtfInfo->VersionPresent = TRUE; + ConvertVersionInfo (*TokenStr, &VtfInfo->MajorVer, &VtfInfo->MinorVer); + } + } else if (strnicmp (*TokenStr, "COMP_BIN", 8) == 0) { + TokenStr++; + strcpy (VtfInfo->CompBinName, *TokenStr); + } else if (strnicmp (*TokenStr, "COMP_SYM", 8) == 0) { + TokenStr++; + strcpy (VtfInfo->CompSymName, *TokenStr); + } else if (strnicmp (*TokenStr, "COMP_SIZE", 9) == 0) { + TokenStr++; + if (strnicmp (*TokenStr, "-", 1) == 0) { + VtfInfo->PreferredSize = FALSE; + VtfInfo->CompSize = 0; + } else { + VtfInfo->PreferredSize = TRUE; + if (AsciiStringToUint64 (*TokenStr, FALSE, &StringValue) != EFI_SUCCESS) { + Error (NULL, 0, 5001, "Parse error", "Cannot get: %s.", TokenStr); + return ; + } + + VtfInfo->CompSize = (UINTN) StringValue; + } + + } else if (strnicmp (*TokenStr, "COMP_CS", 7) == 0) { + TokenStr++; + if (strnicmp (*TokenStr, "1", 1) == 0) { + VtfInfo->CheckSumRequired = 1; + } else if (strnicmp (*TokenStr, "0", 1) == 0) { + VtfInfo->CheckSumRequired = 0; + } else { + Error (NULL, 0, 3000, "Invaild", "Bad value in INF file required field: Checksum, the value must be '0' or '1'."); + } + } + + 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 + +--*/ +{ + + SectionOptionFlag = 0; + SectionCompFlag = 0; + TokenStr = OrgStrTokPtr; + + while (*TokenStr != NULL) { + if (strnicmp (*TokenStr, "[OPTIONS]", 9) == 0) { + SectionOptionFlag = 1; + SectionCompFlag = 0; + } + + if (strnicmp (*TokenStr, "[COMPONENTS]", 12) == 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->NextVtfInfo = malloc (sizeof (PARSED_VTF_INFO)); + if (FileListPtr->NextVtfInfo == NULL) { + Error (NULL, 0, 4003, "Resource", "Out of memory resources.", NULL); + break; + } + FileListPtr = FileListPtr->NextVtfInfo; + memset (FileListPtr, 0, sizeof (PARSED_VTF_INFO)); + FileListPtr->NextVtfInfo = NULL; + continue; + } else { + break; + } + } + + TokenStr++; + } +} + +EFI_STATUS +GetVtfRelatedInfoFromInfFile ( + IN FILE *FilePointer + ) +/*++ + +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 VTF + +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 information + EFI_OUT_OF_RESOURCES - Malloc Failed + EFI_SUCCESS - The function completed successfully + +--*/ +{ + FILE *Fp; + UINTN Index; + UINTN Index1; + EFI_STATUS Status; + + Status = EFI_SUCCESS; + Fp = FilePointer; + if (Fp == NULL) { + Error (NULL, 0, 2000, "Invalid parameter", "BSF INF file is invalid!"); + return EFI_ABORTED; + } + + ValidLineCount (Fp); + + if (ValidLineNum == 0) { + Error (NULL, 0, 2000, "Invalid parameter", "File does not contain any valid information!"); + 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) { + Status = EFI_OUT_OF_RESOURCES; + goto ParseFileError; + } + + memset (*TokenStr, 0, FILE_NAME_SIZE); + TokenStr++; + } + + TokenStr = OrgStrTokPtr; + fseek (Fp, 0L, SEEK_SET); + + Status = InitializeComps (); + + if (Status != EFI_SUCCESS) { + goto ParseFileError; + } + + Status = ParseInputFile (Fp); + if (Status != EFI_SUCCESS) { + goto ParseFileError; + } + + InitializeInFileInfo (); + +ParseFileError: + + for (Index1 = 0; Index1 < Index; Index1 ++) { + free (OrgStrTokPtr[Index1]); + } + + free (OrgStrTokPtr); + + return Status; +} + +VOID +GetRelativeAddressInVtfBuffer ( + 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 VTF + + +Returns: + + +--*/ +{ + UINT64 TempAddress; + UINT8 *LocalBuff; + + if (LocType == FIRST_VTF) { + LocalBuff = (UINT8 *) Vtf1EndBuffer; + TempAddress = Fv1EndAddress - Address; + *RelativeAddress = (UINTN) LocalBuff - (UINTN) TempAddress; + } else { + LocalBuff = (UINT8 *) Vtf2EndBuffer; + TempAddress = Fv2EndAddress - Address; + *RelativeAddress = (UINTN) LocalBuff - (UINTN) TempAddress; + } +} + +EFI_STATUS +GetComponentVersionInfo ( + IN OUT PARSED_VTF_INFO *VtfInfo, + IN UINT8 *Buffer + ) +/*++ +Routine Description: + + This function will extract the version information from File + +Arguments: + + VtfInfo - A Pointer to the VTF 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 (VtfInfo->CompType) { + + case COMP_TYPE_FIT_PAL_A: + case COMP_TYPE_FIT_PAL_B: + memcpy (&VersionInfo, (Buffer + 8), sizeof (UINT16)); + VtfInfo->MajorVer = (UINT8) ((VersionInfo & 0xFF00) >> 8); + VtfInfo->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 VTF 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 VTF buffer. + // + GetRelativeAddressInVtfBuffer (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 VTF + // Buffer. + // + GetRelativeAddressInVtfBuffer (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 VTF buffer. + // + GetRelativeAddressInVtfBuffer (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 VTF + // Buffer. + // + GetRelativeAddressInVtfBuffer (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; +} + +int +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 information 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 + // + Vtf1LastStartAddress -= 0x10; + Vtf1TotalSize += 0x10; + + GetRelativeAddressInVtfBuffer (Vtf1LastStartAddress, &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 VTF component will reside outside the VTF, we will not have its + // binary image while creating VTF, hence we will not perform checksum at + // this time. Once Firmware Volume is being created which will contain this + // VTF, it will fix the FIT table for all the non VTF component and hence + // checksum + // + CompFitPtr->CheckSum = 0; +} + +EFI_STATUS +UpdateFitEntryForNonVTFComp ( + IN PARSED_VTF_INFO *VtfInfo + ) +/*++ + +Routine Description: + + This function updates the information about non VTF component in FIT TABLE. + Since non VTF componets binaries are not part of VTF binary, we would still + be required to update its location information in Firmware Volume, inside + FIT table. + +Arguments: + + VtfInfo - Pointer to VTF 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) { + Error (NULL, 0, 5003, "Invalid", "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 = VtfInfo->CompSize; + CompFitPtr->CompVersion = MAKE_VERSION (VtfInfo->MajorVer, VtfInfo->MinorVer); + CompFitPtr->CvAndType = CV_N_TYPE (VtfInfo->CheckSumRequired, VtfInfo->CompType); + + // + // Since non VTF component will reside outside the VTF, we will not have its + // binary image while creating VTF, hence we will not perform checksum at + // this time. Once Firmware Volume is being created which will contain this + // VTF, it will fix the FIT table for all the non VTF 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 VTF 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_VTF_INFO *VtfInfo, + IN UINT64 *CompStartAddress + ) +/*++ + +Routine Description: + + This function updated the architectural entry point in IPF, SALE_ENTRY. + +Arguments: + + VtfInfo - Pointer to VTF 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 (VtfInfo->CompSymName, "rb"); + + if (Fp == NULL) { + Error (NULL, 0, 0001, "Error opening file", VtfInfo->CompSymName); + 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 (strnicmp (Token, "SALE_ENTRY", 10) == 0) { + break; + } + } + + Offset = strtoul (OffsetStr, NULL, 16); + + *CompStartAddress += Offset; + SalEntryAdd = Fv1EndAddress - (SIZE_IA32_RESET_VECT + SIZE_SALE_ENTRY_POINT); + + GetRelativeAddressInVtfBuffer (SalEntryAdd, &RelativeAddress, FIRST_VTF); + + memcpy ((VOID *) RelativeAddress, (VOID *) CompStartAddress, sizeof (UINT64)); + + if (Fp != NULL) { + fclose (Fp); + } + + return EFI_SUCCESS; +} + +EFI_STATUS +CreateAndUpdateComponent ( + IN PARSED_VTF_INFO *VtfInfo + ) +/*++ + +Routine Description: + + This function reads the binary file for each components and update them + in VTF Buffer as well as in FIT table. If the component is located in non + VTF area, only the FIT table address will be updated + +Arguments: + + VtfInfo - 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 (VtfInfo->LocationType == NONE) { + UpdateFitEntryForNonVTFComp (VtfInfo); + return EFI_SUCCESS; + } + + Fp = fopen (VtfInfo->CompBinName, "rb"); + + if (Fp == NULL) { + Error (NULL, 0, 0001, "Error opening file", VtfInfo->CompBinName); + return EFI_ABORTED; + } + + FileSize = _filelength (fileno (Fp)); + if ((VtfInfo->CompType == COMP_TYPE_FIT_PAL_B) || (VtfInfo->CompType == COMP_TYPE_FIT_PAL_A_SPECIFIC)) { + + // + // BUGBUG: Satish to correct + // + FileSize -= SIZE_OF_PAL_HEADER; + } + + if (VtfInfo->PreferredSize) { + if (FileSize > VtfInfo->CompSize) { + Error (NULL, 0, 2000, "Invalid parameter", "The component size is more than specified size."); + return EFI_ABORTED; + } + + FileSize = VtfInfo->CompSize; + } + + Buffer = malloc ((UINTN) FileSize); + if (Buffer == NULL) { + return EFI_OUT_OF_RESOURCES; + } + memset (Buffer, 0, (UINTN) FileSize); + + if ((VtfInfo->CompType == COMP_TYPE_FIT_PAL_B) || (VtfInfo->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 (!VtfInfo->VersionPresent) { + GetComponentVersionInfo (VtfInfo, 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 (VtfInfo->CompType != COMP_TYPE_FIT_PAL_B) { + if (!VtfInfo->VersionPresent) { + GetComponentVersionInfo (VtfInfo, Buffer); + } + } + + if (VtfInfo->LocationType == SECOND_VTF) { + + CompStartAddress = (Vtf2LastStartAddress - FileSize); + } else { + CompStartAddress = (Vtf1LastStartAddress - FileSize); + } + + if (VtfInfo->CompType == COMP_TYPE_FIT_PAL_B) { + Aligncheck = CheckAddressAlignment (CompStartAddress, 32 * 1024, &NumAdjustByte); + } else { + Aligncheck = CheckAddressAlignment (CompStartAddress, 8, &NumAdjustByte); + } + + if (!Aligncheck) { + CompStartAddress -= NumAdjustByte; + } + + if (VtfInfo->LocationType == SECOND_VTF && SecondVTF == TRUE) { + Vtf2LastStartAddress = CompStartAddress; + Vtf2TotalSize += (UINT32) (FileSize + NumAdjustByte); + Status = UpdateVtfBuffer (CompStartAddress, Buffer, FileSize, SECOND_VTF); + } else if (VtfInfo->LocationType == FIRST_VTF) { + Vtf1LastStartAddress = CompStartAddress; + Vtf1TotalSize += (UINT32) (FileSize + NumAdjustByte); + Status = UpdateVtfBuffer (CompStartAddress, Buffer, FileSize, FIRST_VTF); + } else { + Error (NULL, 0, 2000,"Invalid Parameter", "There's component in second VTF so second BaseAddress and Size must be specified!"); + return EFI_INVALID_PARAMETER; + } + + if (EFI_ERROR (Status)) { + return EFI_ABORTED; + } + + GetNextAvailableFitPtr (&CompFitPtr); + + CompFitPtr->CompAddress = CompStartAddress | IPF_CACHE_BIT; + if ((FileSize % 16) != 0) { + Error (NULL, 0, 2000, "Invalid parameter", "Binary FileSize must be a multiple of 16."); + return EFI_INVALID_PARAMETER; + } + //assert ((FileSize % 16) == 0); + CompFitPtr->CompSize = (UINT32) (FileSize / 16); + CompFitPtr->CompVersion = MAKE_VERSION (VtfInfo->MajorVer, VtfInfo->MinorVer); + CompFitPtr->CvAndType = CV_N_TYPE (VtfInfo->CheckSumRequired, VtfInfo->CompType); + if (VtfInfo->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, SymFileName, VtfInfo->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 + // VTF till we work out how to determine the SALE_ENTRY through it. We will need + // to clarify so many related questions + // !!!!!!!!!!!!!!!!!!!!!!! + + if (VtfInfo->CompType == COMP_TYPE_FIT_PEICORE) { + Status = UpdateEntryPoint (VtfInfo, &CompStartAddress); + } + + return Status; +} + +EFI_STATUS +CreateAndUpdatePAL_A ( + IN PARSED_VTF_INFO *VtfInfo + ) +/*++ + +Routine Description: + + This function reads the binary file for each components and update them + in VTF Buffer as well as FIT table + +Arguments: + + VtfInfo - 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 (VtfInfo->CompBinName, "rb"); + + if (Fp == NULL) { + Error (NULL, 0, 0001, "Error opening file", VtfInfo->CompBinName); + return EFI_ABORTED; + } + + FileSize = _filelength (fileno (Fp)); + if (FileSize < 64) { + Error (NULL, 0, 2000, "Invalid parameter", "PAL_A bin header is 64 bytes, so the Bin size must be larger than 64 bytes!"); + return EFI_INVALID_PARAMETER; + } + FileSize -= SIZE_OF_PAL_HEADER; + + + if (VtfInfo->PreferredSize) { + if (FileSize > VtfInfo->CompSize) { + Error (NULL, 0, 2000, "Invalid parameter", "The PAL_A Size is more than the specified size."); + return EFI_ABORTED; + } + + FileSize = VtfInfo->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 (!VtfInfo->VersionPresent) { + GetComponentVersionInfo (VtfInfo, 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); + Vtf1LastStartAddress = PalStartAddress; + Vtf1TotalSize += (UINT32) FileSize; + Status = UpdateVtfBuffer (PalStartAddress, Buffer, FileSize, FIRST_VTF); + + AbsAddress = Fv1EndAddress - SIZE_TO_PAL_A_FIT; + GetRelativeAddressInVtfBuffer (AbsAddress, &RelativeAddress, FIRST_VTF); + PalFitPtr = (FIT_TABLE *) RelativeAddress; + PalFitPtr->CompAddress = PalStartAddress | IPF_CACHE_BIT; + //assert ((FileSize % 16) == 0); + if ((FileSize % 16) != 0) { + Error (NULL, 0, 2000, "Invalid parameter", "Binary FileSize must be a multiple of 16."); + return EFI_INVALID_PARAMETER; + } + + PalFitPtr->CompSize = (UINT32) (FileSize / 16); + PalFitPtr->CompVersion = MAKE_VERSION (VtfInfo->MajorVer, VtfInfo->MinorVer); + PalFitPtr->CvAndType = CV_N_TYPE (VtfInfo->CheckSumRequired, VtfInfo->CompType); + if (VtfInfo->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, SymFileName, VtfInfo->CompSymName); + if (EFI_ERROR (Status)) { + + // + // At this time, SYM files are not required, so continue on error. + // + } + + return Status; +} + +EFI_STATUS +CreateFitTableAndInitialize ( + IN PARSED_VTF_INFO *VtfInfo + ) +/*++ + +Routine Description: + + This function creates and intializes FIT table which would be used to + add component info inside this + +Arguments: + + VtfInfo - 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 (!VtfInfo->PreferredSize) { + Error (NULL, 0, 2000, "Invalid parameter", "FIT could not be allocated because there is no size information."); + return EFI_ABORTED; + } + + if ((VtfInfo->CompSize % 16) != 0) { + Error (NULL, 0, 2000, "Invalid parameter", "Invalid FIT Table Size, it is not a multiple of 16 bytes. Please correct the size."); + } + + PalFitTableAdd = Fv1EndAddress - SIZE_TO_PAL_A_FIT; + GetRelativeAddressInVtfBuffer (PalFitTableAdd, &RelativeAddress, FIRST_VTF); + PalFitPtr = (FIT_TABLE *) RelativeAddress; + PalFitTableAdd = (PalFitPtr->CompAddress - VtfInfo->CompSize); + + FitTableAdd = (PalFitPtr->CompAddress - 0x10) - VtfInfo->CompSize; + FitTableAddressOffset = Fv1EndAddress - (SIZE_IA32_RESET_VECT + SIZE_SALE_ENTRY_POINT + SIZE_FIT_TABLE_ADD); + GetRelativeAddressInVtfBuffer (FitTableAddressOffset, &RelativeAddress, FIRST_VTF); + *(UINT64 *) RelativeAddress = FitTableAdd; + + GetRelativeAddressInVtfBuffer (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 (((VtfInfo->CompSize & 0x00FFFFFF) % 16) == 0); + FitStartPtr->CompSize = (VtfInfo->CompSize & 0x00FFFFFF) / 16; + FitStartPtr->CompVersion = MAKE_VERSION (VtfInfo->MajorVer, VtfInfo->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 (VtfInfo->CheckSumRequired, VtfInfo->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++; + } + + Vtf1TotalSize += VtfInfo->CompSize; + Vtf1LastStartAddress -= VtfInfo->CompSize; + + return EFI_SUCCESS; +} + +EFI_STATUS +WriteVtfBinary ( + IN CHAR8 *FileName, + IN UINT32 VtfSize, + IN LOC_TYPE LocType + ) +/*++ + +Routine Description: + + Write Firmware Volume from memory to a file. + +Arguments: + + FileName - Output File Name which needed to be created/ + VtfSize - FileSize + LocType - The type of the VTF + +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 *VtfBuffer; + UINTN RelativeAddress; + + if (LocType == FIRST_VTF) { + GetRelativeAddressInVtfBuffer (Vtf1LastStartAddress, &RelativeAddress, FIRST_VTF); + VtfBuffer = (VOID *) RelativeAddress; + } else { + GetRelativeAddressInVtfBuffer (Vtf2LastStartAddress, &RelativeAddress, SECOND_VTF); + VtfBuffer = (VOID *) RelativeAddress; + } + + Fp = fopen (FileName, "wb"); + if (Fp == NULL) { + Error (NULL, 0, 0001, "Error opening file", FileName); + return EFI_ABORTED; + } + + NumByte = fwrite (VtfBuffer, sizeof (UINT8), (UINTN) VtfSize, Fp); + + if (Fp) { + fclose (Fp); + } + + if (NumByte != (sizeof (UINT8) * VtfSize)) { + Error (NULL, 0, 0002, "Error writing file", FileName); + return EFI_ABORTED; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +UpdateVtfBuffer ( + 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 VTF: First or Second + +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) < (Vtf1LastStartAddress | IPF_CACHE_BIT)) { + Error (NULL, 0, 2000, "Invalid parameter", "Start Address is less than the VTF start address."); + return EFI_ABORTED; + } + + LocalBufferPtrToWrite = (UINT8 *) Vtf1EndBuffer; + + LocalBufferPtrToWrite -= (Fv1EndAddress - StartAddress); + + } else { + + if ((StartAddress | IPF_CACHE_BIT) < (Vtf2LastStartAddress | IPF_CACHE_BIT)) { + Error (NULL, 0, 2000, "Invalid parameter", "Error StartAddress"); + return EFI_ABORTED; + } + LocalBufferPtrToWrite = (UINT8 *) Vtf2EndBuffer; + LocalBufferPtrToWrite -= (Fv2EndAddress - StartAddress); + } + + memcpy (LocalBufferPtrToWrite, Buffer, (UINTN) DataSize); + + return EFI_SUCCESS; +} + +EFI_STATUS +UpdateFfsHeader ( + IN UINT32 TotalVtfSize, + IN LOC_TYPE LocType + ) +/*++ + +Routine Description: + + Update the Firmware Volume Buffer with requested buffer data + +Arguments: + + TotalVtfSize - Size of the VTF + Fileoffset - The start of the file relative to the start of the FV. + LocType - The type of the VTF + +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 VTF file header location + // + if (LocType == FIRST_VTF) { + GetRelativeAddressInVtfBuffer (Vtf1LastStartAddress, &RelativeAddress, FIRST_VTF); + FileHeader = (EFI_FFS_FILE_HEADER *) RelativeAddress; + } else { + GetRelativeAddressInVtfBuffer (Vtf2LastStartAddress, &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_RAW; + FileHeader->Attributes = FFS_ATTRIB_CHECKSUM; + + // + // Now FileSize includes the EFI_FFS_FILE_HEADER + // + FileHeader->Size[0] = (UINT8) (TotalVtfSize & 0x000000FF); + FileHeader->Size[1] = (UINT8) ((TotalVtfSize & 0x0000FF00) >> 8); + FileHeader->Size[2] = (UINT8) ((TotalVtfSize & 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, TotalVtfSize); + 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 VTF 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 VTF 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 *LocalVtfBuffer; + UINTN FileSize; + UINTN NumByteRead; + FILE *Fp; + + if (!strcmp (FileName, "")) { + return EFI_INVALID_PARAMETER; + } + + Fp = fopen (FileName, "rb"); + + if (Fp == NULL) { + Error (NULL, 0, 0001, "Error opening file", FileName); + return EFI_ABORTED; + } + + 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); + + LocalVtfBuffer = (UINT8 *) Vtf1EndBuffer - SIZE_IA32_RESET_VECT; + memcpy (LocalVtfBuffer, Buffer, FileSize); + + if (Buffer) { + free (Buffer); + } + + if (Fp != NULL) { + fclose (Fp); + } + return EFI_SUCCESS; +} + +VOID +CleanUpMemory ( + VOID + ) +/*++ + +Routine Description: + + This function cleans up any allocated buffer + +Arguments: + + NONE + +Returns: + + NONE + +--*/ +{ + PARSED_VTF_INFO *TempFileListPtr; + + if (Vtf1Buffer) { + free (Vtf1Buffer); + } + + if (Vtf2Buffer) { + free (Vtf2Buffer); + } + + // + // Cleanup the buffer which was allocated to read the file names from FV.INF + // + FileListPtr = FileListHeadPtr; + while (FileListPtr != NULL) { + TempFileListPtr = FileListPtr->NextVtfInfo; + free (FileListPtr); + FileListPtr = TempFileListPtr; + } +} + +EFI_STATUS +ProcessAndCreateVtf ( + IN UINT64 Size + ) +/*++ + +Routine Description: + + This function process the link list created during INF file parsing + and create component in VTF and updates its info in FIT table + +Arguments: + + Size - Size of the Firmware Volume of which, this VTF belongs to. + +Returns: + + EFI_UNSUPPORTED - Unknown FIT type + EFI_SUCCESS - The function completed successfully + +--*/ +{ + EFI_STATUS Status; + PARSED_VTF_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: + //COMP_TYPE_FIT_HEADER 0x00 + Status = CreateFitTableAndInitialize (ParsedInfoPtr); + break; + + // + // COMP_TYPE_FIT_PAL_A is a special case, hence handle it here + // + case COMP_TYPE_FIT_PAL_A: + //COMP_TYPE_FIT_PAL_A 0x0F + Status = CreateAndUpdatePAL_A (ParsedInfoPtr); + + // + // Based on VTF 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 VTF will be + // of part. + // + if (Status == EFI_SUCCESS) { + UpdateFitEntryForFwVolume (Size); + } + break; + + case COMP_TYPE_FIT_FV_BOOT: + //COMP_TYPE_FIT_FV_BOOT 0x7E + // + // 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 VTF and create appropriate entry about this + // component in FIT Entry. + // + Status = CreateAndUpdateComponent (ParsedInfoPtr); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 0002, "Error updating component", ParsedInfoPtr->CompName); + return EFI_ABORTED; + } else { + break;} + } + + ParsedInfoPtr = ParsedInfoPtr->NextVtfInfo; + } + return Status; +} + +EFI_STATUS +GenerateVtfImage ( + IN UINT64 StartAddress1, + IN UINT64 Size1, + IN UINT64 StartAddress2, + IN UINT64 Size2, + IN FILE *fp + ) +/*++ + +Routine Description: + + This is the main function which will be called from application. + +Arguments: + + StartAddress1 - The start address of the first VTF + Size1 - The size of the first VTF + StartAddress2 - The start address of the second VTF + Size2 - The size of the second VTF + fp - The pointer to BSF inf file + +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: + GetVtfRelatedInfoFromInfFile + ProcessAndCreateVtf + UpdateIA32ResetVector + UpdateFfsHeader + WriteVtfBinary + +--*/ +{ + EFI_STATUS Status; + FILE *VtfFP; + + Status = EFI_UNSUPPORTED; + VtfFP = fp; + + if (StartAddress2 == 0) { + SecondVTF = FALSE; + } else { + SecondVTF = TRUE; + } + + Fv1BaseAddress = StartAddress1; + Fv1EndAddress = Fv1BaseAddress + Size1; + if (Fv1EndAddress != 0x100000000 || Size1 < 0x100000) { + Error (NULL, 0, 2000, "Invalid parameter", "Error BaseAddress and Size parameters!"); + if (Size1 < 0x100000) { + Error (NULL, 0, 2000, "Invalid parameter", "The FwVolumeSize must be larger than 1M!"); + } else if (SecondVTF != TRUE) { + Error (NULL, 0, 2000, "Invalid parameter", "BaseAddress + FwVolumeSize must equal 0x100000000!"); + } + Usage(); + return EFI_INVALID_PARAMETER; + } + + // + // The image buffer for the First VTF + // + Vtf1Buffer = malloc ((UINTN) Size1); + if (Vtf1Buffer == NULL) { + Error (NULL, 0, 4001, "Resource", "Not enough resources available to create memory mapped file for the Boot Strap File!"); + return EFI_OUT_OF_RESOURCES; + } + memset (Vtf1Buffer, 0x00, (UINTN) Size1); + Vtf1EndBuffer = (UINT8 *) Vtf1Buffer + Size1; + Vtf1LastStartAddress = Fv1EndAddress | IPF_CACHE_BIT; + + if (SecondVTF) { + Fv2BaseAddress = StartAddress2; + Fv2EndAddress = Fv2BaseAddress + Size2; + if (Fv2EndAddress != StartAddress1) { + Error (NULL, 0, 2000, "Invalid parameter", "Error BaseAddress and Size parameters!"); + if (SecondVTF == TRUE) { + Error (NULL, 0, 2000, "Invalid parameter", "FirstBaseAddress + FirstFwVolumeSize must equal 0x100000000!"); + Error (NULL, 0, 2000, "Invalid parameter", "SecondBaseAddress + SecondFwVolumeSize must equal FirstBaseAddress!"); + } + Usage(); + return EFI_INVALID_PARAMETER; + } + + // + // The image buffer for the second VTF + // + Vtf2Buffer = malloc ((UINTN) Size2); + if (Vtf2Buffer == NULL) { + Error (NULL, 0, 4001, "Resource", "Not enough resources available to create memory mapped file for the Boot Strap File!"); + return EFI_OUT_OF_RESOURCES; + } + memset (Vtf2Buffer, 0x00, (UINTN) Size2); + Vtf2EndBuffer = (UINT8 *) Vtf2Buffer + Size2; + Vtf2LastStartAddress = Fv2EndAddress | IPF_CACHE_BIT; + } + + Status = GetVtfRelatedInfoFromInfFile (VtfFP); + + if (Status != EFI_SUCCESS) { + Error (NULL, 0, 0003, "Error parsing file", "the input file."); + CleanUpMemory (); + return Status; + } + + Status = ProcessAndCreateVtf (Size1); + if (Status != EFI_SUCCESS) { + CleanUpMemory (); + return Status; + } + + if (SectionOptionFlag) { + Status = UpdateIA32ResetVector (IA32BinFile, Vtf1TotalSize); + 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 + // + Vtf1TotalSize += sizeof (EFI_FFS_FILE_HEADER); + Vtf1LastStartAddress -= sizeof (EFI_FFS_FILE_HEADER); + + Status = UpdateFfsHeader (Vtf1TotalSize, FIRST_VTF); + if (Status != EFI_SUCCESS) { + CleanUpMemory (); + return Status; + } + // + // Update the VTF buffer into specified VTF binary file + // + Status = WriteVtfBinary (OutFileName1, Vtf1TotalSize, FIRST_VTF); + + if (SecondVTF) { + Vtf2TotalSize += sizeof (EFI_FFS_FILE_HEADER); + Vtf2LastStartAddress -= sizeof (EFI_FFS_FILE_HEADER); + Status = UpdateFfsHeader (Vtf2TotalSize, SECOND_VTF); + if (Status != EFI_SUCCESS) { + CleanUpMemory (); + return Status; + } + + // + // Update the VTF buffer into specified VTF binary file + // + Status = WriteVtfBinary (OutFileName2, Vtf2TotalSize, SECOND_VTF); + } + + CleanUpMemory (); + + 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; + + StartAddressPtr = malloc (sizeof (UINT64)); + if (StartAddressPtr == NULL) { + return EFI_OUT_OF_RESOURCES; + } + *StartAddressPtr = StartAddress; + + Fp = fopen (OutFileName1, "rb"); + + if (Fp == NULL) { + Error (NULL, 0, 0001, "Error opening file", OutFileName1); + 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); + } + + 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); + Error (NULL, 0, 0001, "Error opening file", DestFileName); + 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); + Error (NULL, 0, 2000, "Invalid parameter", "not at the beginning of the output file."); + return EFI_ABORTED; + } + + StartLocation = ftell (DestFile); + + if (StartLocation == 0) { + fprintf (DestFile, "TEXTSYM format | V1.0\n"); + } else if (StartLocation == -1) { + fclose (SourceFile); + fclose (DestFile); + Error (NULL, 0, 2000, "Invalid parameter", "StartLocation error"); + 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); + Error (NULL, 0, 2000, "Invalid parameter", "The symbol file does not match the expected TEXTSYM format (V1.0.)"); + 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; + +#ifdef __GNUC__ + fprintf (DestFile, "%s | %016lX | %s | %s%s\n", Type, TokenAddress, Section, BaseToken, Token); +#else + fprintf (DestFile, "%s | %016I64X | %s | %s%s\n", Type, TokenAddress, Section, BaseToken, Token); +#endif + } + } + + 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 + // + GetRelativeAddressInVtfBuffer (FitTableAddOffset, &RelativeAddress, FIRST_VTF); + FitTableAdd = *(UINTN *) RelativeAddress; + + GetRelativeAddressInVtfBuffer (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 +Version ( + VOID + ) +/*++ + +Routine Description: + + Displays the standard utility information to SDTOUT + +Arguments: + + None + +Returns: + + None + +--*/ +{ + fprintf (stdout, "%s Version %d.%d\n", UTILITY_NAME, UTILITY_MAJOR_VERSION, UTILITY_MINOR_VERSION); +} + +VOID +Usage ( + VOID + ) +/*++ + +Routine Description: + + Displays the utility usage syntax to STDOUT + +Arguments: + + None + +Returns: + + None + +--*/ +{ + // + // Summary usage + // + fprintf (stdout, "Usage: %s [options] <-f input_file> <-r BaseAddress> <-s FwVolumeSize>\n\n", UTILITY_NAME); + + // + // Copyright declaration + // + fprintf (stdout, "Copyright (c) 2007 - 2009, Intel Corporation. All rights reserved.\n\n"); + // + // Details Option + // + fprintf (stdout, "Options:\n"); + fprintf (stdout, " -f Input_file, --filename Input_file\n\ + Input_file is name of the BS Image INF file\n"); + fprintf (stdout, " -r BaseAddress, --baseaddr BaseAddress\n\ + BaseAddress is the starting address of Firmware Volume\n\ + where Boot Strapped Image will reside.\n"); + fprintf (stdout, " -s FwVolumeSize, --size FwVolumeSize\n\ + FwVolumeSize is the size of Firmware Volume.\n"); + fprintf (stdout, " -o FileName, --output FileName\n\ + File will be created to store the ouput content.\n"); + fprintf (stdout, " -v, --verbose Turn on verbose output with informational messages.\n"); + fprintf (stdout, " --version Show program's version number and exit.\n"); + fprintf (stdout, " -h, --help Show this help message and exit.\n"); + fprintf (stdout, " -q, --quiet Disable all messages except FATAL ERRORS.\n"); + fprintf (stdout, " -d, --debug [#, 0-9] Enable debug messages at level #.\n"); +} + +int +main ( + IN int argc, + IN char **argv + ) +/*++ + +Routine Description: + + This utility uses GenVtf.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 FirstRoundO; + BOOLEAN FirstRoundB; + BOOLEAN FirstRoundS; + EFI_STATUS Status; + FILE *VtfFP; + CHAR8 *VtfFileName; + + SetUtilityName (UTILITY_NAME); + + // + // Initialize variables + // + StartAddress1 = 0; + StartAddress2 = 0; + FwVolSize1 = 0; + FwVolSize2 = 0; + FirstRoundB = TRUE; + FirstRoundS = TRUE; + FirstRoundO = TRUE; + DebugMode = FALSE; + OutFileName1 = NULL; + OutFileName2 = NULL; + VtfFP = NULL; + DebugLevel = 0; + + // + // Verify the correct number of arguments + // + if (argc == 1) { + Usage(); + return 0; + } + + if ((strcmp(argv[1], "-h") == 0) || (strcmp(argv[1], "--help") == 0)) { + Usage(); + return 0; + } + + if ((strcmp(argv[1], "--version") == 0)) { + Version(); + return 0; + } + + // + // Parse the command line arguments + // + for (Index = 1; Index < argc; Index += 2) { + if ((stricmp (argv[Index], "-o") == 0) || (stricmp (argv[Index], "--output") == 0)) { + if (argv[Index + 1] == NULL || argv[Index + 1][0] == '-') { + Error (NULL, 0, 1003, "Invalid option value", "Output file is missing for -o option"); + goto ERROR; + } + // + // Get the output file name + // + VTF_OUTPUT = TRUE; + if (FirstRoundO) { + // + // It's the first output file name + // + OutFileName1 = (CHAR8 *)argv[Index+1]; + FirstRoundO = FALSE; + } else { + // + //It's the second output file name + // + OutFileName2 = (CHAR8 *)argv[Index+1]; + } + continue; + } + + if ((stricmp (argv[Index], "-f") == 0) || (stricmp (argv[Index], "--filename") == 0)) { + if (argv[Index + 1] == NULL || argv[Index + 1][0] == '-') { + Error (NULL, 0, 1003, "Invalid option value", "BS Image INF file is missing for -f option"); + goto ERROR; + } + // + // Get the input VTF file name + // + VtfFileName = argv[Index+1]; + VtfFP = fopen(VtfFileName, "rb"); + if (VtfFP == NULL) { + Error (NULL, 0, 0001, "Error opening file", VtfFileName); + goto ERROR; + } + continue; + } + + if ((stricmp (argv[Index], "-r") == 0) || (stricmp (argv[Index], "--baseaddr") == 0)) { + if (FirstRoundB) { + Status = AsciiStringToUint64 (argv[Index + 1], FALSE, &StartAddress1); + FirstRoundB = FALSE; + } else { + Status = AsciiStringToUint64 (argv[Index + 1], FALSE, &StartAddress2); + } + if (Status != EFI_SUCCESS) { + Error (NULL, 0, 2000, "Invalid option value", "%s is Bad FV start address.", argv[Index + 1]); + goto ERROR; + } + continue; + } + + if ((stricmp (argv[Index], "-s") == 0) || (stricmp (argv[Index], "--size") == 0)) { + if (FirstRoundS) { + Status = AsciiStringToUint64 (argv[Index + 1], FALSE, &FwVolSize1); + FirstRoundS = FALSE; + } else { + Status = AsciiStringToUint64 (argv[Index + 1], FALSE, &FwVolSize2); + SecondVTF = TRUE; + } + + if (Status != EFI_SUCCESS) { + Error (NULL, 0, 2000, "Invalid option value", "%s is Bad FV size.", argv[Index + 1]); + goto ERROR; + } + continue; + } + + if ((stricmp (argv[Index], "-v") == 0) || (stricmp (argv[Index], "--verbose") == 0)) { + VerboseMode = TRUE; + Index--; + continue; + } + + if ((stricmp (argv[Index], "-q") == 0) || (stricmp (argv[Index], "--quiet") == 0)) { + QuietMode = TRUE; + Index--; + continue; + } + + if ((stricmp (argv[Index], "-d") == 0) || (stricmp (argv[Index], "--debug") == 0)) { + // + // debug level specified + // + Status = AsciiStringToUint64(argv[Index + 1], FALSE, &DebugLevel); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[Index], argv[Index + 1]); + goto ERROR; + } + if (DebugLevel > 9) { + Error (NULL, 0, 2000, "Invalid option value", "Unrecognized argument %s.", argv[Index + 1]); + goto ERROR; + } + if((DebugLevel <= 9) &&(DebugLevel >= 5)) { + DebugMode = TRUE; + } else { + DebugMode = FALSE; + } + continue; + } + + Error (NULL, 0, 2000, "Invalid parameter", "Unrecognized argument %s.", argv[Index]); + goto ERROR; + } + + if (VtfFP == NULL) { + Error (NULL, 0, 2000, "Invalid parameter", "No BS Image INF file is specified"); + goto ERROR; + } + + if (FirstRoundB) { + Error (NULL, 0, 2000, "Invalid parameter", "No FV base address is specified"); + goto ERROR; + } + + if (FirstRoundS) { + Error (NULL, 0, 2000, "Invalid parameter", "No FV Size is specified"); + goto ERROR; + } + // + // All Parameters has been parsed, now set the message print level + // + if (QuietMode) { + SetPrintLevel(40); + } else if (VerboseMode) { + SetPrintLevel(15); + } else if (DebugMode) { + SetPrintLevel(DebugLevel); + } + + if (VerboseMode) { + VerboseMsg("%s tool start.\n", UTILITY_NAME); + } + + if (VTF_OUTPUT == FALSE) { + if (SecondVTF == TRUE) { + OutFileName1 = VTF_OUTPUT_FILE1; + OutFileName2 = VTF_OUTPUT_FILE2; + } else { + OutFileName1 = VTF_OUTPUT_FILE1; + } + SymFileName = VTF_SYM_FILE; + } else { + INTN OutFileNameLen = strlen(OutFileName1); + INTN Index; + + for (Index = OutFileNameLen; Index > 0; --Index) { + if (OutFileName1[Index] == '/' || OutFileName1[Index] == '\\') { + break; + } + } + if (Index == 0) { + SymFileName = VTF_SYM_FILE; + } else { + INTN SymFileNameLen = Index + 1 + strlen(VTF_SYM_FILE); + SymFileName = malloc(SymFileNameLen + 1); + memcpy(SymFileName, OutFileName1, Index + 1); + memcpy(SymFileName + Index + 1, VTF_SYM_FILE, strlen(VTF_SYM_FILE)); + SymFileName[SymFileNameLen] = '\0'; + } + if (DebugMode) { + DebugMsg(UTILITY_NAME, 0, DebugLevel, SymFileName, NULL); + } + } + + // + // Call the GenVtfImage + // + if (DebugMode) { + DebugMsg(UTILITY_NAME, 0, DebugLevel, "Start to generate the VTF image\n", NULL); + } + Status = GenerateVtfImage (StartAddress1, FwVolSize1, StartAddress2, FwVolSize2, VtfFP); + + if (EFI_ERROR (Status)) { + switch (Status) { + + case EFI_INVALID_PARAMETER: + Error (NULL, 0, 2000, "Invalid parameter", "Invalid parameter passed to GenVtf function."); + break; + + case EFI_ABORTED: + Error (NULL, 0, 3000, "Invaild", "Error detected while creating the file image."); + break; + + case EFI_OUT_OF_RESOURCES: + Error (NULL, 0, 4002, "Resource", "GenVtfImage function could not allocate required resources."); + break; + + case EFI_VOLUME_CORRUPTED: + Error (NULL, 0, 3000, "Invaild", "No base address was specified."); + break; + + default: + Error (NULL, 0, 3000, "Invaild", "GenVtfImage function returned unknown status %x.",Status ); + break; + } + } +ERROR: + if (VtfFP != NULL) { + fclose (VtfFP); + } + + if (DebugMode) { + DebugMsg(UTILITY_NAME, 0, DebugLevel, "VTF image generated successful\n", NULL); + } + + if (VerboseMode) { + VerboseMsg("%s tool done with return code is 0x%x.\n", UTILITY_NAME, GetUtilityStatus ()); + } + return GetUtilityStatus(); +} diff --git a/BaseTools/Source/C/GenVtf/GenVtf.h b/BaseTools/Source/C/GenVtf/GenVtf.h new file mode 100644 index 0000000000..25ce1141ba --- /dev/null +++ b/BaseTools/Source/C/GenVtf/GenVtf.h @@ -0,0 +1,330 @@ +/** @file + +Copyright (c) 1999 - 2008 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: + + GenVtf.h + +Abstract: + + This file contains the relevant declarations required + to generate Boot Strap File + +**/ + +// +// Module Coded to EFI 2.0 Coding Conventions +// +#ifndef __GEN_VTF_H__ +#define __GEN_VTF_H__ + +// +// External Files Referenced +// +#include +#include +#include +#include "assert.h" +#include +#include "ParseInf.h" + +// +// Internal Constants +// +#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 VTF_INPUT_FILE "VTF.INF" +#define VTF_OUTPUT_FILE1 "VTF1.RAW" +#define VTF_OUTPUT_FILE2 "VTF2.RAW" +#define VTF_SYM_FILE "Vtf.SYM" +#define FIT_SIGNATURE "_FIT_ " + +// +//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 0x8000000000000000ULL + +// +// 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 "GenVtf" + +// +// 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 ONE_VTF_ARGS 10 +#define TWO_VTF_ARGS 12 +#define THREE_VTF_ARGS 16 + +static BOOLEAN VerboseMode = FALSE; + +// +// Internal Data Structure +// +typedef enum _LOC_TYPE +{ + NONE, // In case there is - INF file + FIRST_VTF, // First VTF + SECOND_VTF, // Outside VTF +} LOC_TYPE; + +typedef struct _PARSED_VTF_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 _ParsedVtfInfo *' to 'struct _PARSED_VTF_INFO *' + // Fixed - warning C4133: '=' : incompatible types - from 'struct _ParsedVtfInfo *' to 'struct _PARSED_VTF_INFO *' + // Fixed - warning C4133: '=' : incompatible types - from 'struct _ParsedVtfInfo *' to 'struct _PARSED_VTF_INFO *' + // Fixed - warning C4133: '=' : incompatible types - from 'struct _ParsedVtfInfo *' to 'struct _PARSED_VTF_INFO *' + // + struct _PARSED_VTF_INFO *NextVtfInfo; +} PARSED_VTF_INFO; + +#pragma pack (1) +typedef struct { + UINT64 CompAddress; + UINT32 CompSize; + UINT16 CompVersion; + UINT8 CvAndType; + UINT8 CheckSum; +} FIT_TABLE; +#pragma pack () + +// +// Function Prototype Declarations +// + +EFI_STATUS +UpdateVtfBuffer( + 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 VTF + +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 +GenerateVtfImage ( + IN UINT64 StartAddress1, + IN UINT64 Size1, + IN UINT64 StartAddress2, + IN UINT64 Size2, + IN FILE *fp + ) +/*++ + +Routine Description: + + This is the main function which will be called from application. + +Arguments: + + StartAddress1 - The start address of the first VTF + Size1 - The size of the first VTF + StartAddress2 - The start address of the second VTF + Size2 - The size of the second VTF + +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: + GetVtfRelatedInfoFromInfFile + ProcessAndCreateVtf + UpdateIA32ResetVector + UpdateFfsHeader + WriteVtfBinary + +--*/ +; + +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 + +--*/ +; + +VOID +Usage ( + VOID + ) +/*++ + +Routine Description: + + Displays the utility usage syntax to STDOUT + +Arguments: + + None + +Returns: + + None + +--*/ +; +#endif diff --git a/BaseTools/Source/C/GenVtf/Makefile b/BaseTools/Source/C/GenVtf/Makefile new file mode 100644 index 0000000000..0d6a8d134b --- /dev/null +++ b/BaseTools/Source/C/GenVtf/Makefile @@ -0,0 +1,10 @@ +!INCLUDE ..\Makefiles\ms.common + +APPNAME = GenVtf + +LIBS = $(LIB_PATH)\Common.lib + +OBJECTS = GenVtf.obj + +!INCLUDE ..\Makefiles\ms.app + diff --git a/BaseTools/Source/C/GnuGenBootSector/FatFormat.h b/BaseTools/Source/C/GnuGenBootSector/FatFormat.h new file mode 100644 index 0000000000..f24b4ee9ac --- /dev/null +++ b/BaseTools/Source/C/GnuGenBootSector/FatFormat.h @@ -0,0 +1,152 @@ +/** @file + + Fat file system structure and definition. + +Copyright 2006 - 2008, 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. + +--*/ + +#ifndef _FAT_BPB_H_ +#define _FAT_BPB_H_ + +#include "CommonLib.h" + +#pragma pack(1) + +typedef struct { + // + // Fat common field + // + UINT8 BS_jmpBoot[3]; + CHAR8 BS_OEMName[8]; + UINT16 BPB_BytsPerSec; + UINT8 BPB_SecPerClus; + UINT16 BPB_RsvdSecCnt; + UINT8 BPB_NumFATs; + UINT16 BPB_RootEntCnt; + UINT16 BPB_TotSec16; + UINT8 BPB_Media; + UINT16 BPB_FATSz16; + UINT16 BPB_SecPerTrk; + UINT16 BPB_NumHeads; + UINT32 BPB_HiddSec; + UINT32 BPB_TotSec32; + + // + // Fat12/16 specific field + // + UINT8 BS_DrvNum; + UINT8 BS_Reserved1; + UINT8 BS_BootSig; + UINT32 BS_VolID; + CHAR8 BS_VolLab[11]; + CHAR8 BS_FilSysType[8]; + + // + // Boot Code and Data + // + UINT8 Reserved[448]; + + // + // Fat common signature - 0xAA55 + // + UINT16 Signature; +} FAT12_16_BPB_STRUCT; + +typedef struct { + // + // Fat common field + // + UINT8 BS_jmpBoot[3]; + CHAR8 BS_OEMName[8]; + UINT16 BPB_BytsPerSec; + UINT8 BPB_SecPerClus; + UINT16 BPB_RsvdSecCnt; + UINT8 BPB_NumFATs; + UINT16 BPB_RootEntCnt; + UINT16 BPB_TotSec16; + UINT8 BPB_Media; + UINT16 BPB_FATSz16; + UINT16 BPB_SecPerTrk; + UINT16 BPB_NumHeads; + UINT32 BPB_HiddSec; + UINT32 BPB_TotSec32; + + // + // Fat32 specific field + // + UINT32 BPB_FATSz32; + UINT16 BPB_ExtFlags; + UINT16 BPB_FSVer; + UINT32 BPB_RootClus; + UINT16 BPB_FSInfo; + UINT16 BPB_BkBootSec; + UINT8 BPB_Reserved[12]; + UINT8 BS_DrvNum; + UINT8 BS_Reserved1; + UINT8 BS_BootSig; + UINT32 BS_VolID; + CHAR8 BS_VolLab[11]; + CHAR8 BS_FilSysType[8]; + + // + // Boot Code and Data + // + UINT8 Reserved[420]; + + // + // Fat common signature - 0xAA55 + // + UINT16 Signature; +} FAT32_BPB_STRUCT; + +typedef union { + FAT12_16_BPB_STRUCT Fat12_16; + FAT32_BPB_STRUCT Fat32; +} FAT_BPB_STRUCT; + +typedef enum { + FatTypeUnknown, + FatTypeFat12, + FatTypeFat16, + FatTypeFat32, + FatTypeMax +} FAT_TYPE; + +typedef struct { + CHAR8 DIR_Name[11]; + UINT8 DIR_Attr; + UINT8 DIR_NTRes; + UINT8 DIR_CrtTimeTenth; + UINT16 DIR_CrtTime; + UINT16 DIR_CrtDate; + UINT16 DIR_LstAccDate; + UINT16 DIR_FstClusHI; + UINT16 DIR_WrtTime; + UINT16 DIR_WrtDate; + UINT16 DIR_FstClusLO; + UINT32 DIR_FileSize; +} FAT_DIRECTORY_ENTRY; + +#pragma pack() + +#define FAT_MAX_FAT12_CLUSTER 0xFF5 +#define FAT_MAX_FAT16_CLUSTER 0xFFF5 + +#define FAT_BS_SIGNATURE 0xAA55 +#define FAT_BS_BOOTSIG 0x29 +#define FAT_BS_JMP1 0xEB +#define FAT_BS_JMP2 0xE9 +#define FAT_FILSYSTYPE "FAT " +#define FAT12_FILSYSTYPE "FAT12 " +#define FAT16_FILSYSTYPE "FAT16 " +#define FAT32_FILSYSTYPE "FAT32 " + +#endif diff --git a/BaseTools/Source/C/GnuGenBootSector/GNUmakefile b/BaseTools/Source/C/GnuGenBootSector/GNUmakefile new file mode 100644 index 0000000000..c0261e9253 --- /dev/null +++ b/BaseTools/Source/C/GnuGenBootSector/GNUmakefile @@ -0,0 +1,10 @@ +ARCH ?= IA32 +MAKEROOT ?= .. + +APPNAME = GnuGenBootSector + +LIBS = -lCommon + +OBJECTS = GnuGenBootSector.o + +include $(MAKEROOT)/Makefiles/app.makefile diff --git a/BaseTools/Source/C/GnuGenBootSector/GnuGenBootSector.c b/BaseTools/Source/C/GnuGenBootSector/GnuGenBootSector.c new file mode 100644 index 0000000000..178bec2476 --- /dev/null +++ b/BaseTools/Source/C/GnuGenBootSector/GnuGenBootSector.c @@ -0,0 +1,457 @@ +/** @file + +Copyright 2006 - 2009, 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: + + GnuGenBootSector.c + +Abstract: + Reading/writing MBR/DBR. + NOTE: + If we write MBR to disk, we just update the MBR code and the partition table wouldn't be over written. + If we process DBR, we will patch MBR to set first partition active if no active partition exists. + +**/ + +#include "CommonLib.h" +#include +#include +#include +#include + +// +// Utility Name +// +#define UTILITY_NAME "GnuGenBootSector" + +// +// Utility version information +// +#define UTILITY_MAJOR_VERSION 0 +#define UTILITY_MINOR_VERSION 1 + +#define MAX_DRIVE 26 +#define PARTITION_TABLE_OFFSET 0x1BE + +#define SIZE_OF_PARTITION_ENTRY 0x10 + +#define PARTITION_ENTRY_STARTLBA_OFFSET 8 + +#define PARTITION_ENTRY_NUM 4 + +#define DRIVE_UNKNOWN 0 +#define DRIVE_NO_ROOT_DIR 1 +#define DRIVE_REMOVABLE 2 +#define DRIVE_FIXED 3 +#define DRIVE_REMOTE 4 +#define DRIVE_CDROM 5 +#define DRIVE_RAMDISK 6 + +typedef struct _DRIVE_TYPE_DESC { + UINTN Type; + CHAR8 *Description; +} DRIVE_TYPE_DESC; + +#define DRIVE_TYPE_ITEM(x) {x, #x} + +DRIVE_TYPE_DESC DriveTypeDesc[] = { + DRIVE_TYPE_ITEM (DRIVE_UNKNOWN), + DRIVE_TYPE_ITEM (DRIVE_NO_ROOT_DIR), + DRIVE_TYPE_ITEM (DRIVE_REMOVABLE), + DRIVE_TYPE_ITEM (DRIVE_FIXED), + DRIVE_TYPE_ITEM (DRIVE_REMOTE), + DRIVE_TYPE_ITEM (DRIVE_CDROM), + DRIVE_TYPE_ITEM (DRIVE_RAMDISK), + {(UINTN) -1, NULL} +}; + +typedef struct _DRIVE_INFO { + CHAR8 VolumeLetter; + DRIVE_TYPE_DESC *DriveType; + UINTN DiskNumber; +} DRIVE_INFO; + +typedef enum { + PathUnknown, + PathFile, + PathFloppy, + PathUsb, + PathIde +} PATH_TYPE; + +typedef struct _PATH_INFO { + CHAR8 *Path; + CHAR8 PhysicalPath[260]; + PATH_TYPE Type; + BOOLEAN Input; +} PATH_INFO; + +typedef enum { + ErrorSuccess, + ErrorFileCreate, + ErrorFileReadWrite, + ErrorNoMbr, + ErrorFatType, + ErrorPath, +} ERROR_STATUS; + +CHAR8 *ErrorStatusDesc[] = { + "Success", + "Failed to create files", + "Failed to read/write files", + "No MBR exists", + "Failed to detect Fat type", + "Inavlid path" +}; + + +//UnSupported Windows API functions. +UINTN GetLogicalDrives(void) { return 1; } + + + +/** + Get path information, including physical path for Linux platform. + + @param PathInfo Point to PATH_INFO structure. + + @return whether path is valid. +**/ +ERROR_STATUS +GetPathInfo ( + PATH_INFO *PathInfo + ) +{ + FILE *f; + + if (strncmp(PathInfo->Path, "/dev/", 5) == 0) { + // + // Process disk path here. + // + + // Process floppy disk + if (PathInfo->Path[5] == 'f' && PathInfo->Path[6] == 'd' && PathInfo->Path[8] == '\0') { + PathInfo->Type = PathFloppy; + strcpy (PathInfo->PhysicalPath, PathInfo->Path); + + return ErrorSuccess; + } else { + // Other disk types is not supported yet. + fprintf (stderr, "ERROR: It's not a floppy disk!\n"); + return ErrorPath; + } + + // Try to open the device. + f = fopen(PathInfo->Path,"r"); + if (f == NULL) { + printf ("error :open device failed!\n"); + return ErrorPath; + } + fclose (f); + return ErrorSuccess; + } + + // Process file path here. + PathInfo->Type = PathFile; + if (PathInfo->Input) { + // If path is file path, check whether file is valid. + printf("Path = %s\n",PathInfo->Path); + f = fopen (PathInfo->Path, "r"); + if (f == NULL) { + fprintf (stderr, "Test error E2003: File was not provided!\n"); + return ErrorPath; + } + fclose (f); + } + + strcpy(PathInfo->PhysicalPath, PathInfo->Path); + return ErrorSuccess; + +} + +VOID +ListDrive ( + VOID + ) +{ + printf("-l or -list not supported!\n"); +} + +/** + Writing or reading boot sector or MBR according to the argument. + + @param InputInfo PATH_INFO instance for input path + @param OutputInfo PATH_INFO instance for output path + @param ProcessMbr TRUE is to process MBR, otherwise, processing boot sector + + @return ERROR_STATUS + **/ +ERROR_STATUS +ProcessBsOrMbr ( + PATH_INFO *InputInfo, + PATH_INFO *OutputInfo, + BOOLEAN ProcessMbr + ) +{ + CHAR8 FirstSector[0x200] = {0}; + CHAR8 FirstSectorBackup[0x200] = {0}; + + FILE *InputFile; + FILE *OutputFile; + + + InputFile = fopen(InputInfo->PhysicalPath, "r"); + if (InputFile == NULL) { + return ErrorFileReadWrite; + } + + if (0x200 != fread(FirstSector, 1, 0x200, InputFile)) { + fclose(InputFile); + return ErrorFileReadWrite; + } + + fclose(InputFile); + + //Not support USB and IDE. + if (InputInfo->Type == PathUsb) { + printf("USB has not been supported yet!"); + return ErrorSuccess; + } + + if (InputInfo->Type == PathIde) { + printf("IDE has not been supported yet!"); + return ErrorSuccess; + } + + //Process Floppy Disk + OutputFile = fopen(OutputInfo->PhysicalPath, "w"); + if (OutputFile == NULL) { + return ErrorFileReadWrite; + } + + if (OutputInfo->Type != PathFile) { + if (ProcessMbr) { + // + // Use original partition table + // + if (0x200 != fread (FirstSectorBackup, 1, 0x200, OutputFile)) { + fclose(OutputFile); + return ErrorFileReadWrite; + } + memcpy (FirstSector + 0x1BE, FirstSectorBackup + 0x1BE, 0x40); + } + } + if(0x200 != fwrite(FirstSector, 1, 0x200, OutputFile)) { + fclose(OutputFile); + return ErrorFileReadWrite; + } + + fclose(OutputFile); + return ErrorSuccess; +} + + +/** + + Displays the standard utility information to SDTOUT + +**/ +VOID +Version ( + VOID + ) +{ + printf ("%s v%d.%d -Utility to retrieve and update the boot sector or MBR.\n", UTILITY_NAME, UTILITY_MAJOR_VERSION, UTILITY_MINOR_VERSION); + printf ("Copyright (c) 2007-2009 Intel Corporation. All rights reserved.\n"); +} + + +VOID +PrintUsage ( + VOID + ) +{ + Version(); + printf ("\nUsage: \n\ + GenBootSector\n\ + [-l, --list list disks]\n\ + [-i, --input Filename]\n\ + [-o, --output Filename]\n\ + [-m, --mbr process the MBR also]\n\ + [-v, --verbose]\n\ + [--version]\n\ + [-q, --quiet disable all messages except fatal errors]\n\ + [-d, --debug[#]\n\ + [-h, --help]\n"); +} + +INTN +main ( + INTN argc, + CHAR8 *argv[] + ) +{ + CHAR8 *AppName; + INTN Index; + BOOLEAN ProcessMbr; + ERROR_STATUS Status; + EFI_STATUS EfiStatus; + PATH_INFO InputPathInfo; + PATH_INFO OutputPathInfo; + UINT64 LogLevel; + + SetUtilityName (UTILITY_NAME); + + ZeroMem(&InputPathInfo, sizeof(PATH_INFO)); + ZeroMem(&OutputPathInfo, sizeof(PATH_INFO)); + + AppName = *argv; + argv ++; + argc --; + + ProcessMbr = FALSE; + + if (argc == 0) { + PrintUsage(); + return 0; + } + + // + // Parse command line + // + for (Index = 0; Index < argc; Index ++) { + if ((stricmp (argv[Index], "-l") == 0) || (stricmp (argv[Index], "--list") == 0)) { + ListDrive (); + return 0; + } + + if ((stricmp (argv[Index], "-m") == 0) || (stricmp (argv[Index], "--mbr") == 0)) { + ProcessMbr = TRUE; + continue; + } + + if ((stricmp (argv[Index], "-i") == 0) || (stricmp (argv[Index], "--input") == 0)) { + InputPathInfo.Path = argv[Index + 1]; + InputPathInfo.Input = TRUE; + if (InputPathInfo.Path == NULL) { + Error (NULL, 0, 1003, "Invalid option value", "Input file name can't be NULL"); + return 1; + } + if (InputPathInfo.Path[0] == '-') { + Error (NULL, 0, 1003, "Invalid option value", "Input file is missing"); + return 1; + } + ++Index; + continue; + } + + if ((stricmp (argv[Index], "-o") == 0) || (stricmp (argv[Index], "--output") == 0)) { + OutputPathInfo.Path = argv[Index + 1]; + OutputPathInfo.Input = FALSE; + if (OutputPathInfo.Path == NULL) { + Error (NULL, 0, 1003, "Invalid option value", "Output file name can't be NULL"); + return 1; + } + if (OutputPathInfo.Path[0] == '-') { + Error (NULL, 0, 1003, "Invalid option value", "Output file is missing"); + return 1; + } + ++Index; + continue; + } + + if ((stricmp (argv[Index], "-h") == 0) || (stricmp (argv[Index], "--help") == 0)) { + PrintUsage (); + return 0; + } + + if (stricmp (argv[Index], "--version") == 0) { + Version (); + return 0; + } + + if ((stricmp (argv[Index], "-v") == 0) || (stricmp (argv[Index], "--verbose") == 0)) { + continue; + } + + if ((stricmp (argv[Index], "-q") == 0) || (stricmp (argv[Index], "--quiet") == 0)) { + continue; + } + + if ((stricmp (argv[Index], "-d") == 0) || (stricmp (argv[Index], "--debug") == 0)) { + EfiStatus = AsciiStringToUint64 (argv[Index + 1], FALSE, &LogLevel); + if (EFI_ERROR (EfiStatus)) { + Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[Index], argv[Index + 1]); + return 1; + } + if (LogLevel > 9) { + Error (NULL, 0, 1003, "Invalid option value", "Debug Level range is 0-9, currnt input level is %d", LogLevel); + return 1; + } + SetPrintLevel (LogLevel); + DebugMsg (NULL, 0, 9, "Debug Mode Set", "Debug Output Mode Level %s is set!", argv[Index + 1]); + ++Index; + continue; + } + + // + // Don't recognize the parameter. + // + Error (NULL, 0, 1000, "Unknown option", "%s", argv[Index]); + return 1; + } + + if (InputPathInfo.Path == NULL) { + Error (NULL, 0, 1001, "Missing options", "Input file is missing"); + return 1; + } + + if (OutputPathInfo.Path == NULL) { + Error (NULL, 0, 1001, "Missing options", "Output file is missing"); + return 1; + } + + if (GetPathInfo(&InputPathInfo) != ErrorSuccess) { + Error (NULL, 0, 1003, "Invalid option value", "Input file can't be found."); + return 1; + } + + if (GetPathInfo(&OutputPathInfo) != ErrorSuccess) { + Error (NULL, 0, 1003, "Invalid option value", "Output file can't be found."); + return 1; + } + + // + // Process DBR (Patch or Read) + // + Status = ProcessBsOrMbr (&InputPathInfo, &OutputPathInfo, ProcessMbr); + + if (Status == ErrorSuccess) { + fprintf ( + stdout, + "%s %s: successful!\n", + (OutputPathInfo.Type != PathFile) ? "Write" : "Read", + ProcessMbr ? "MBR" : "DBR" + ); + return 0; + } else { + fprintf ( + stderr, + "%s: %s %s: failed - %s (LastError: 0x%x)!\n", + (Status == ErrorNoMbr) ? "WARNING" : "ERROR", + (OutputPathInfo.Type != PathFile) ? "Write" : "Read", + ProcessMbr ? "MBR" : "DBR", + ErrorStatusDesc[Status], + errno + ); + return 1; + } +} diff --git a/BaseTools/Source/C/Include/Common/BaseTypes.h b/BaseTools/Source/C/Include/Common/BaseTypes.h new file mode 100644 index 0000000000..438d949a6b --- /dev/null +++ b/BaseTools/Source/C/Include/Common/BaseTypes.h @@ -0,0 +1,223 @@ +/** @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. + + File Name: BaseTypes.h + +**/ + +#ifndef __BASE_TYPES_H__ +#define __BASE_TYPES_H__ + +// +// Include processor specific binding +// +#include +#include + +// +// 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 + +// +// Macro that returns the byte offset of a field in a data structure. +// +#define OFFSET_OF(TYPE, Field) ((UINTN) &(((TYPE *)0)->Field)) + +/// +/// _CR - 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 *) ((UINTN)(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)) + +// +// Return the maximum of two operands. +// This macro returns the maximum of two operand specified by a and b. +// Both a and b must be the same numerical types, signed or unsigned. +// +#define MAX(a, b) \ + (((a) > (b)) ? (a) : (b)) + + +// +// Return the minimum of two operands. +// This macro returns the minimal of two operand specified by a and b. +// Both a and b must be the same numerical types, signed or unsigned. +// +#define MIN(a, b) \ + (((a) < (b)) ? (a) : (b)) + + +// +// 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/BaseTools/Source/C/Include/Common/MdeModuleHii.h b/BaseTools/Source/C/Include/Common/MdeModuleHii.h new file mode 100644 index 0000000000..022a7492f2 --- /dev/null +++ b/BaseTools/Source/C/Include/Common/MdeModuleHii.h @@ -0,0 +1,154 @@ +/** @file + EDK II specific HII relative definition. + + Copyright (c) 2006 - 2007, 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. + + File Name: MdeModuleHii.h + +**/ + +#ifndef _MDEMODULE_HII_H +#define _MDEMODULE_HII_H + +#define NARROW_CHAR 0xFFF0 +#define WIDE_CHAR 0xFFF1 +#define NON_BREAKING_CHAR 0xFFF2 + +#define GLYPH_WIDTH EFI_GLYPH_WIDTH +#define GLYPH_HEIGHT EFI_GLYPH_HEIGHT + +// +// State defined for password statemachine +// +#define BROWSER_STATE_VALIDATE_PASSWORD 0 +#define BROWSER_STATE_SET_PASSWORD 1 + + +// +// Tiano Implementation specific Device Path definition. +// +#pragma pack(1) +typedef struct { + VENDOR_DEVICE_PATH VendorDevicePath; + UINT32 Reserved; + UINT64 UniqueId; +} HII_VENDOR_DEVICE_PATH_NODE; +#pragma pack() + +typedef struct { + HII_VENDOR_DEVICE_PATH_NODE Node; + EFI_DEVICE_PATH_PROTOCOL End; +} HII_VENDOR_DEVICE_PATH; + + +// +// GUIDed opcodes defined for Tiano +// +#define EFI_IFR_TIANO_GUID \ + { 0xf0b1735, 0x87a0, 0x4193, {0xb2, 0x66, 0x53, 0x8c, 0x38, 0xaf, 0x48, 0xce} } + +#pragma pack(1) + +#define EFI_IFR_EXTEND_OP_LABEL 0x0 +#define EFI_IFR_EXTEND_OP_BANNER 0x1 +#define EFI_IFR_EXTEND_OP_TIMEOUT 0x2 +#define EFI_IFR_EXTEND_OP_CLASS 0x3 +#define EFI_IFR_EXTEND_OP_SUBCLASS 0x4 + +typedef struct _EFI_IFR_GUID_LABEL { + EFI_IFR_OP_HEADER Header; + EFI_GUID Guid; + UINT8 ExtendOpCode; + UINT16 Number; +} EFI_IFR_GUID_LABEL; + +#define EFI_IFR_BANNER_ALIGN_LEFT 0 +#define EFI_IFR_BANNER_ALIGN_CENTER 1 +#define EFI_IFR_BANNER_ALIGN_RIGHT 2 + +typedef struct _EFI_IFR_GUID_BANNER { + EFI_IFR_OP_HEADER Header; + EFI_GUID Guid; + UINT8 ExtendOpCode; // Extended opcode is EFI_IFR_EXTEND_OP_BANNER + EFI_STRING_ID Title; // The string token for the banner title + UINT16 LineNumber; // 1-based line number + UINT8 Alignment; // left, center, or right-aligned +} EFI_IFR_GUID_BANNER; + +typedef struct _EFI_IFR_GUID_TIMEOUT { + EFI_IFR_OP_HEADER Header; + EFI_GUID Guid; + UINT8 ExtendOpCode; + UINT16 TimeOut; +} EFI_IFR_GUID_TIMEOUT; + +#define EFI_NON_DEVICE_CLASS 0x00 +#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 + +typedef struct _EFI_IFR_GUID_CLASS { + EFI_IFR_OP_HEADER Header; + EFI_GUID Guid; + UINT8 ExtendOpCode; + UINT16 Class; +} EFI_IFR_GUID_CLASS; + +#define EFI_SETUP_APPLICATION_SUBCLASS 0x00 +#define EFI_GENERAL_APPLICATION_SUBCLASS 0x01 +#define EFI_FRONT_PAGE_SUBCLASS 0x02 +#define EFI_SINGLE_USE_SUBCLASS 0x03 + +typedef struct _EFI_IFR_GUID_SUBCLASS { + EFI_IFR_OP_HEADER Header; + EFI_GUID Guid; + UINT8 ExtendOpCode; + UINT16 SubClass; +} EFI_IFR_GUID_SUBCLASS; + +// +// GUIDed opcodes defined for Tiano +// +#define EFI_IFR_FRAMEWORK_GUID \ + { 0x31ca5d1a, 0xd511, 0x4931, { 0xb7, 0x82, 0xae, 0x6b, 0x2b, 0x17, 0x8c, 0xd7 } } + +#define EFI_IFR_EXTEND_OP_OPTIONKEY 0x0 +#define EFI_IFR_EXTEND_OP_VAREQNAME 0x1 +// +// Store the framework vfr option key value +// +typedef struct _EFI_IFR_GUID_OPTIONKEY { + EFI_IFR_OP_HEADER Header; + EFI_GUID Guid; + UINT8 ExtendOpCode; + EFI_QUESTION_ID QuestionId; + EFI_IFR_TYPE_VALUE OptionValue; + EFI_QUESTION_ID KeyValue; +} EFI_IFR_GUID_OPTIONKEY; + +// +// Store the framework vfr vareqval name number +// +typedef struct _EFI_IFR_GUID_VAREQNAME { + EFI_IFR_OP_HEADER Header; + EFI_GUID Guid; + UINT8 ExtendOpCode; + EFI_QUESTION_ID QuestionId; + EFI_STRING_ID NameId; +} EFI_IFR_GUID_VAREQNAME; + +#pragma pack() + +#endif + diff --git a/BaseTools/Source/C/Include/Common/PiFirmwareFile.h b/BaseTools/Source/C/Include/Common/PiFirmwareFile.h new file mode 100644 index 0000000000..1e9f6028b4 --- /dev/null +++ b/BaseTools/Source/C/Include/Common/PiFirmwareFile.h @@ -0,0 +1,270 @@ +/** @file + The firmware file related definitions in PI. + + Copyright (c) 2006 - 2008, 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. + + File Name: PiFirmwareFile.h + + @par Revision Reference: + Version 1.0. + +**/ + +#ifndef __PI_FIRMWARE_FILE_H__ +#define __PI_FIRMWARE_FILE_H__ + +#pragma pack(1) +// +// Used to verify the integrity of the file. +// +typedef union { + struct { + UINT8 Header; + UINT8 File; + } Checksum; + UINT16 Checksum16; +} EFI_FFS_INTEGRITY_CHECK; + +typedef UINT8 EFI_FV_FILETYPE; +typedef UINT8 EFI_FFS_FILE_ATTRIBUTES; +typedef UINT8 EFI_FFS_FILE_STATE; + +// +// File Types Definitions +// +#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 +#define EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE 0x0B +#define EFI_FV_FILETYPE_OEM_MIN 0xc0 +#define EFI_FV_FILETYPE_OEM_MAX 0xdf +#define EFI_FV_FILETYPE_DEBUG_MIN 0xe0 +#define EFI_FV_FILETYPE_DEBUG_MAX 0xef +#define EFI_FV_FILETYPE_FFS_MIN 0xf0 +#define EFI_FV_FILETYPE_FFS_MAX 0xff +#define EFI_FV_FILETYPE_FFS_PAD 0xf0 +// +// FFS File Attributes. +// +#define FFS_ATTRIB_FIXED 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 + +// +// FFS File State Bits. +// +#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 \ + ) + +// +// Each file begins with the header that describe the +// contents and state of the files. +// +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; + + +typedef UINT8 EFI_SECTION_TYPE; + +// +// Pseudo type. It is +// used as a wild card 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_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 + +typedef struct { + UINT8 Size[3]; + EFI_SECTION_TYPE Type; +} EFI_COMMON_SECTION_HEADER; + +// +// Leaf section type that contains an +// IA-32 16-bit executable image. +// +typedef EFI_COMMON_SECTION_HEADER EFI_COMPATIBILITY16_SECTION; + +// +// CompressionType of EFI_COMPRESSION_SECTION. +// +#define EFI_NOT_COMPRESSED 0x00 +#define EFI_STANDARD_COMPRESSION 0x01 +// +// An encapsulation section type in which the +// section data is compressed. +// +typedef struct { + EFI_COMMON_SECTION_HEADER CommonHeader; + UINT32 UncompressedLength; + UINT8 CompressionType; +} EFI_COMPRESSION_SECTION; + +// +// Leaf section which could be used to determine the dispatch order of DXEs. +// +typedef EFI_COMMON_SECTION_HEADER EFI_DXE_DEPEX_SECTION; + +// +// Leaf section witch contains a PI FV. +// +typedef EFI_COMMON_SECTION_HEADER EFI_FIRMWARE_VOLUME_IMAGE_SECTION; + +// +// Leaf section which contains a single GUID. +// +typedef struct { + EFI_COMMON_SECTION_HEADER CommonHeader; + EFI_GUID SubTypeGuid; +} EFI_FREEFORM_SUBTYPE_GUID_SECTION; + +// +// Attributes of EFI_GUID_DEFINED_SECTION +// +#define EFI_GUIDED_SECTION_PROCESSING_REQUIRED 0x01 +#define EFI_GUIDED_SECTION_AUTH_STATUS_VALID 0x02 +// +// Leaf section which is encapsulation defined by specific GUID +// +typedef struct { + EFI_COMMON_SECTION_HEADER CommonHeader; + EFI_GUID SectionDefinitionGuid; + UINT16 DataOffset; + UINT16 Attributes; +} EFI_GUID_DEFINED_SECTION; + +// +// Leaf section which contains PE32+ image. +// +typedef EFI_COMMON_SECTION_HEADER EFI_PE32_SECTION; + +// +// Leaf section which contains PIC image. +// +typedef EFI_COMMON_SECTION_HEADER EFI_PIC_SECTION; + +// +// Leaf section which used to determine the dispatch order of PEIMs. +// +typedef EFI_COMMON_SECTION_HEADER EFI_PEI_DEPEX_SECTION; + +// +// Leaf section which constains the position-independent-code image. +// +typedef EFI_COMMON_SECTION_HEADER EFI_TE_SECTION; + +// +// Leaf section which contains an array of zero or more bytes. +// +typedef EFI_COMMON_SECTION_HEADER EFI_RAW_SECTION; + +// +// Leaf section which contains a unicode string that +// is human readable file name. +// +typedef struct { + EFI_COMMON_SECTION_HEADER CommonHeader; + + // + // Array of unicode string. + // + CHAR16 FileNameString[1]; +} EFI_USER_INTERFACE_SECTION; + + +// +// Leaf section which contains a numeric build number and +// an optional unicode string that represent the file revision. +// +typedef struct { + EFI_COMMON_SECTION_HEADER CommonHeader; + UINT16 BuildNumber; + CHAR16 VersionString[1]; +} EFI_VERSION_SECTION; + + +#define SECTION_SIZE(SectionHeaderPtr) \ + ((UINT32) (*((UINT32 *) ((EFI_COMMON_SECTION_HEADER *) SectionHeaderPtr)->Size) & 0x00ffffff)) + +#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_TE_SECTION *TeSection; + EFI_PEI_DEPEX_SECTION *PeimHeaderSection; + EFI_DXE_DEPEX_SECTION *DependencySection; + EFI_VERSION_SECTION *VersionSection; + EFI_USER_INTERFACE_SECTION *UISection; + EFI_COMPATIBILITY16_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/BaseTools/Source/C/Include/Common/PiFirmwareVolume.h b/BaseTools/Source/C/Include/Common/PiFirmwareVolume.h new file mode 100644 index 0000000000..07682a3fca --- /dev/null +++ b/BaseTools/Source/C/Include/Common/PiFirmwareVolume.h @@ -0,0 +1,146 @@ +/** @file + The firmware volume related definitions in PI. + + Copyright (c) 2006 - 2008, 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. + + File Name: PiFirmwareVolume.h + + @par Revision Reference: + Version 1.0. + +**/ + +#ifndef __PI_FIRMWAREVOLUME_H__ +#define __PI_FIRMWAREVOLUME_H__ + +// +// EFI_FV_FILE_ATTRIBUTES +// +typedef UINT32 EFI_FV_FILE_ATTRIBUTES; + +// +// Value of EFI_FV_FILE_ATTRIBUTES. +// +#define EFI_FV_FILE_ATTRIB_ALIGNMENT 0x0000001F +#define EFI_FV_FILE_ATTRIB_FIXED 0x00000100 +#define EFI_FV_FILE_ATTRIB_MEMORY_MAPPED 0x00000200 + +typedef UINT32 EFI_FVB_ATTRIBUTES; + +// +// Attributes bit definitions +// +#define EFI_FVB2_READ_DISABLED_CAP 0x00000001 +#define EFI_FVB2_READ_ENABLED_CAP 0x00000002 +#define EFI_FVB2_READ_STATUS 0x00000004 +#define EFI_FVB2_WRITE_DISABLED_CAP 0x00000008 +#define EFI_FVB2_WRITE_ENABLED_CAP 0x00000010 +#define EFI_FVB2_WRITE_STATUS 0x00000020 +#define EFI_FVB2_LOCK_CAP 0x00000040 +#define EFI_FVB2_LOCK_STATUS 0x00000080 +#define EFI_FVB2_STICKY_WRITE 0x00000200 +#define EFI_FVB2_MEMORY_MAPPED 0x00000400 +#define EFI_FVB2_ERASE_POLARITY 0x00000800 +#define EFI_FVB2_READ_LOCK_CAP 0x00001000 +#define EFI_FVB2_READ_LOCK_STATUS 0x00002000 +#define EFI_FVB2_WRITE_LOCK_CAP 0x00004000 +#define EFI_FVB2_WRITE_LOCK_STATUS 0x00008000 +#define EFI_FVB2_ALIGNMENT 0x001F0000 +#define EFI_FVB2_ALIGNMENT_1 0x00000000 +#define EFI_FVB2_ALIGNMENT_2 0x00010000 +#define EFI_FVB2_ALIGNMENT_4 0x00020000 +#define EFI_FVB2_ALIGNMENT_8 0x00030000 +#define EFI_FVB2_ALIGNMENT_16 0x00040000 +#define EFI_FVB2_ALIGNMENT_32 0x00050000 +#define EFI_FVB2_ALIGNMENT_64 0x00060000 +#define EFI_FVB2_ALIGNMENT_128 0x00070000 +#define EFI_FVB2_ALIGNMENT_256 0x00080000 +#define EFI_FVB2_ALIGNMENT_512 0x00090000 +#define EFI_FVB2_ALIGNMENT_1K 0x000A0000 +#define EFI_FVB2_ALIGNMENT_2K 0x000B0000 +#define EFI_FVB2_ALIGNMENT_4K 0x000C0000 +#define EFI_FVB2_ALIGNMENT_8K 0x000D0000 +#define EFI_FVB2_ALIGNMENT_16K 0x000E0000 +#define EFI_FVB2_ALIGNMENT_32K 0x000F0000 +#define EFI_FVB2_ALIGNMENT_64K 0x00100000 +#define EFI_FVB2_ALIGNMENT_128K 0x00110000 +#define EFI_FVB2_ALIGNMENT_256K 0x00120000 +#define EFI_FVB2_ALIGNMNET_512K 0x00130000 +#define EFI_FVB2_ALIGNMENT_1M 0x00140000 +#define EFI_FVB2_ALIGNMENT_2M 0x00150000 +#define EFI_FVB2_ALIGNMENT_4M 0x00160000 +#define EFI_FVB2_ALIGNMENT_8M 0x00170000 +#define EFI_FVB2_ALIGNMENT_16M 0x00180000 +#define EFI_FVB2_ALIGNMENT_32M 0x00190000 +#define EFI_FVB2_ALIGNMENT_64M 0x001A0000 +#define EFI_FVB2_ALIGNMENT_128M 0x001B0000 +#define EFI_FVB2_ALIGNMENT_256M 0x001C0000 +#define EFI_FVB2_ALIGNMENT_512M 0x001D0000 +#define EFI_FVB2_ALIGNMENT_1G 0x001E0000 +#define EFI_FVB2_ALIGNMENT_2G 0x001F0000 + + +typedef struct { + UINT32 NumBlocks; + UINT32 Length; +} EFI_FV_BLOCK_MAP_ENTRY; + +// +// Describes the features and layout of the firmware volume. +// +typedef struct { + UINT8 ZeroVector[16]; + EFI_GUID FileSystemGuid; + UINT64 FvLength; + UINT32 Signature; + EFI_FVB_ATTRIBUTES Attributes; + UINT16 HeaderLength; + UINT16 Checksum; + UINT16 ExtHeaderOffset; + UINT8 Reserved[1]; + UINT8 Revision; + EFI_FV_BLOCK_MAP_ENTRY BlockMap[1]; +} EFI_FIRMWARE_VOLUME_HEADER; + +#define EFI_FVH_SIGNATURE EFI_SIGNATURE_32 ('_', 'F', 'V', 'H') + +/// +/// Firmware Volume Header Revision definition +/// +#define EFI_FVH_REVISION 0x02 + +// +// Extension header pointed by ExtHeaderOffset of volume header. +// +typedef struct { + EFI_GUID FvName; + UINT32 ExtHeaderSize; +} EFI_FIRMWARE_VOLUME_EXT_HEADER; + +typedef struct { + UINT16 ExtEntrySize; + UINT16 ExtEntryType; +} EFI_FIRMWARE_VOLUME_EXT_ENTRY; + +#define EFI_FV_EXT_TYPE_OEM_TYPE 0x01 +typedef struct { + EFI_FIRMWARE_VOLUME_EXT_ENTRY Hdr; + UINT32 TypeMask; + + // + // Array of GUIDs. + // Each GUID represents an OEM file type. + // + EFI_GUID Types[1]; +} EFI_FIRMWARE_VOLUME_EXT_ENTRY_OEM_TYPE; + + +#endif diff --git a/BaseTools/Source/C/Include/Common/UefiBaseTypes.h b/BaseTools/Source/C/Include/Common/UefiBaseTypes.h new file mode 100644 index 0000000000..53f86bd52d --- /dev/null +++ b/BaseTools/Source/C/Include/Common/UefiBaseTypes.h @@ -0,0 +1,177 @@ +/** @file + Defines data types and constants introduced in UEFI. + + Copyright (c) 2006 - 2007, 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. + + File Name: UefiBaseTypes.h + +**/ + +#ifndef __UEFI_BASETYPE_H__ +#define __UEFI_BASETYPE_H__ + +#include + +// +// Basical data type definitions introduced in UEFI. +// +typedef struct { + UINT32 Data1; + UINT16 Data2; + UINT16 Data3; + UINT8 Data4[8]; +} EFI_GUID; + +typedef RETURN_STATUS EFI_STATUS; +typedef VOID *EFI_HANDLE; + +typedef VOID *EFI_EVENT; + +typedef UINTN EFI_TPL; + + +typedef UINT64 EFI_LBA; + + +typedef UINT16 STRING_REF; + +typedef UINT64 EFI_PHYSICAL_ADDRESS; +typedef UINT64 EFI_VIRTUAL_ADDRESS; + +// +// EFI Time Abstraction: +// Year: 2000 - 20XX +// Month: 1 - 12 +// Day: 1 - 31 +// Hour: 0 - 23 +// Minute: 0 - 59 +// Second: 0 - 59 +// Nanosecond: 0 - 999,999,999 +// TimeZone: -1440 to 1440 or 2047 +// +typedef struct { + UINT16 Year; + UINT8 Month; + UINT8 Day; + UINT8 Hour; + UINT8 Minute; + UINT8 Second; + UINT8 Pad1; + UINT32 Nanosecond; + INT16 TimeZone; + UINT8 Daylight; + UINT8 Pad2; +} EFI_TIME; + + +// +// Networking Definitions +// +typedef struct { + UINT8 Addr[4]; +} EFI_IPv4_ADDRESS; + +typedef struct { + UINT8 Addr[16]; +} EFI_IPv6_ADDRESS; + +typedef struct { + UINT8 Addr[32]; +} EFI_MAC_ADDRESS; + +typedef union { + UINT32 Addr[4]; + EFI_IPv4_ADDRESS v4; + EFI_IPv6_ADDRESS v6; +} EFI_IP_ADDRESS; + + +// +// Enumeration of 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 + + +#define NULL_HANDLE ((VOID *) 0) + +// +// Define macro to encode the status code. +// +#define EFIERR(_a) ENCODE_ERROR(_a) + +#define EFI_ERROR(A) RETURN_ERROR(A) + +// +// 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)) + + +// +// Returns the byte offset to a field within a structure +// +#define EFI_FIELD_OFFSET(TYPE,Field) ((UINTN)(&(((TYPE *) 0)->Field))) + +// +// 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_SIZE 0x1000 +#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) + + +#define EFI_MAX_BIT MAX_BIT +#define EFI_MAX_ADDRESS MAX_ADDRESS + +#endif diff --git a/BaseTools/Source/C/Include/Common/UefiCapsule.h b/BaseTools/Source/C/Include/Common/UefiCapsule.h new file mode 100644 index 0000000000..d50492662b --- /dev/null +++ b/BaseTools/Source/C/Include/Common/UefiCapsule.h @@ -0,0 +1,34 @@ +/** @file + Defines for the EFI Capsule functionality. + + Copyright (c) 2006 - 2008, 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. + + File Name: Capsule.h + + @par Revision Reference: + These definitions are from Uefi Spec. + +**/ + +#ifndef _EFI_CAPSULE_H_ +#define _EFI_CAPSULE_H_ + +typedef struct { + EFI_GUID CapsuleGuid; + UINT32 HeaderSize; + UINT32 Flags; + UINT32 CapsuleImageSize; +} EFI_CAPSULE_HEADER; + +#define CAPSULE_FLAGS_PERSIST_ACROSS_RESET 0x00010000 +#define CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE 0x00020000 + +#endif // #ifndef _EFI_CAPSULE_H_ diff --git a/BaseTools/Source/C/Include/Common/UefiInternalFormRepresentation.h b/BaseTools/Source/C/Include/Common/UefiInternalFormRepresentation.h new file mode 100644 index 0000000000..a127c952d4 --- /dev/null +++ b/BaseTools/Source/C/Include/Common/UefiInternalFormRepresentation.h @@ -0,0 +1,1509 @@ +/** @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 - 2008, 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. + + File Name: UefiInternalFormRepresentation.h + + @par Revision Reference: + These definitions are from UEFI2.1. + +**/ + +#ifndef __UEFI_INTERNAL_FORMREPRESENTATION_H__ +#define __UEFI_INTERNAL_FORMREPRESENTATION_H__ + + +#define EFI_HII_PLATFORM_SETUP_FORMSET_GUID \ + { 0x93039971, 0x8545, 0x4b04, { 0xb4, 0x5e, 0x32, 0xeb, 0x83, 0x26, 0x4, 0xe } } + +// +// The following types are currently defined: +// +typedef UINT32 RELOFST; + +typedef VOID* EFI_HII_HANDLE; +typedef CHAR16* EFI_STRING; +typedef UINT16 EFI_IMAGE_ID; +typedef UINT16 EFI_QUESTION_ID; +typedef UINT16 EFI_STRING_ID; +typedef UINT16 EFI_FORM_ID; +typedef UINT16 EFI_VARSTORE_ID; +typedef UINT16 EFI_DEFAULT_ID; +typedef UINT32 EFI_HII_FONT_STYLE; + + + +#pragma pack(1) + + +// +// HII package list +// +typedef struct { + EFI_GUID PackageListGuid; + UINT32 PackageLength; +} EFI_HII_PACKAGE_LIST_HEADER; + +/** + + Each package starts with a header, as defined above, which + indicates the size and type of the package. When added to a + pointer pointing to the start of the header, Length points at + the next package. The package lists form a package list when + concatenated together and terminated with an + EFI_HII_PACKAGE_HEADER with a Type of EFI_HII_PACKAGE_END. The + type EFI_HII_PACKAGE_TYPE_GUID is used for vendor-defined HII + packages, whose contents are determined by the Guid. The range + of package types starting with EFI_HII_PACKAGE_TYPE_SYSTEM_BEGIN + through EFI_HII_PACKAGE_TYPE_SYSTEM_END are reserved for system + firmware implementers. + + @param Length The size of the package in bytes. + + @param Type The package type. See EFI_HII_PACKAGE_TYPE_x, + below. + + @param Data The package data, the format of which is + determined by Type. + +**/ +typedef struct { + UINT32 Length:24; + UINT32 Type:8; + // UINT8 Data[...]; +} EFI_HII_PACKAGE_HEADER; + +// +// EFI_HII_PACKAGE_TYPE_x. +// +#define EFI_HII_PACKAGE_TYPE_ALL 0x00 +#define EFI_HII_PACKAGE_TYPE_GUID 0x01 +#define EFI_HII_PACKAGE_FORM 0x02 +#define EFI_HII_PACKAGE_KEYBOARD_LAYOUT 0x03 +#define EFI_HII_PACKAGE_STRINGS 0x04 +#define EFI_HII_PACKAGE_FONTS 0x05 +#define EFI_HII_PACKAGE_IMAGES 0x06 +#define EFI_HII_PACKAGE_SIMPLE_FONTS 0x07 +#define EFI_HII_PACKAGE_DEVICE_PATH 0x08 +#define EFI_HII_PACKAGE_END 0xDF +#define EFI_HII_PACKAGE_TYPE_SYSTEM_BEGIN 0xE0 +#define EFI_HII_PACKAGE_TYPE_SYSTEM_END 0xFF + +// +// Simplified Font Package +// + +#define EFI_GLYPH_HEIGHT 19 +#define EFI_GLYPH_WIDTH 8 +// +// Contents of EFI_NARROW_GLYPH.Attributes +// +#define EFI_GLYPH_NON_SPACING 0x01 +#define EFI_GLYPH_WIDE 0x02 + +typedef struct { + CHAR16 UnicodeWeight; + UINT8 Attributes; + UINT8 GlyphCol1[EFI_GLYPH_HEIGHT]; +} EFI_NARROW_GLYPH; + +typedef struct { + CHAR16 UnicodeWeight; + UINT8 Attributes; + UINT8 GlyphCol1[EFI_GLYPH_HEIGHT]; + UINT8 GlyphCol2[EFI_GLYPH_HEIGHT]; + UINT8 Pad[3]; +} EFI_WIDE_GLYPH; + + +typedef struct _EFI_HII_SIMPLE_FONT_PACKAGE_HDR { + EFI_HII_PACKAGE_HEADER Header; + UINT16 NumberOfNarrowGlyphs; + UINT16 NumberOfWideGlyphs; + // EFI_NARROW_GLYPH NarrowGlyphs[]; + // EFI_WIDE_GLYPH WideGlyphs[]; +} EFI_HII_SIMPLE_FONT_PACKAGE_HDR; + +// +// Font Package +// + +#define EFI_HII_FONT_STYLE_BOLD 0x00000001 +#define EFI_HII_FONT_STYLE_ITALIC 0x00000002 +#define EFI_HII_FONT_STYLE_EMBOSS 0x00010000 +#define EFI_HII_FONT_STYLE_OUTLINE 0x00020000 +#define EFI_HII_FONT_STYLE_SHADOW 0x00040000 +#define EFI_HII_FONT_STYLE_UNDERLINE 0x00080000 +#define EFI_HII_FONT_STYLE_DBL_UNDER 0x00100000 + +typedef struct _EFI_HII_GLYPH_INFO { + UINT16 Width; + UINT16 Height; + INT16 OffsetX; + INT16 OffsetY; + INT16 AdvanceX; +} EFI_HII_GLYPH_INFO; + +typedef struct _EFI_HII_FONT_PACKAGE_HDR { + EFI_HII_PACKAGE_HEADER Header; + UINT32 HdrSize; + UINT32 GlyphBlockOffset; + EFI_HII_GLYPH_INFO Cell; + EFI_HII_FONT_STYLE FontStyle; + CHAR16 FontFamily[1]; +} EFI_HII_FONT_PACKAGE_HDR; + +#define EFI_HII_GIBT_END 0x00 +#define EFI_HII_GIBT_GLYPH 0x10 +#define EFI_HII_GIBT_GLYPHS 0x11 +#define EFI_HII_GIBT_GLYPH_DEFAULT 0x12 +#define EFI_HII_GIBT_GLYPHS_DEFAULT 0x13 +#define EFI_HII_GIBT_DUPLICATE 0x20 +#define EFI_HII_GIBT_SKIP2 0x21 +#define EFI_HII_GIBT_SKIP1 0x22 +#define EFI_HII_GIBT_DEFAULTS 0x23 +#define EFI_HII_GIBT_EXT1 0x30 +#define EFI_HII_GIBT_EXT2 0x31 +#define EFI_HII_GIBT_EXT4 0x32 + +typedef struct _EFI_HII_GLYPH_BLOCK { + UINT8 BlockType; +} EFI_HII_GLYPH_BLOCK; + +typedef struct _EFI_HII_GIBT_DEFAULTS_BLOCK { + EFI_HII_GLYPH_BLOCK Header; + EFI_HII_GLYPH_INFO Cell; +} EFI_HII_GIBT_DEFAULTS_BLOCK; + +typedef struct _EFI_HII_GIBT_DUPLICATE_BLOCK { + EFI_HII_GLYPH_BLOCK Header; + CHAR16 CharValue; +} EFI_HII_GIBT_DUPLICATE_BLOCK; + +typedef struct _EFI_GLYPH_GIBT_END_BLOCK { + EFI_HII_GLYPH_BLOCK Header; +} EFI_GLYPH_GIBT_END_BLOCK; + +typedef struct _EFI_HII_GIBT_EXT1_BLOCK { + EFI_HII_GLYPH_BLOCK Header; + UINT8 BlockType2; + UINT8 Length; +} EFI_HII_GIBT_EXT1_BLOCK; + +typedef struct _EFI_HII_GIBT_EXT2_BLOCK { + EFI_HII_GLYPH_BLOCK Header; + UINT8 BlockType2; + UINT16 Length; +} EFI_HII_GIBT_EXT2_BLOCK; + +typedef struct _EFI_HII_GIBT_EXT4_BLOCK { + EFI_HII_GLYPH_BLOCK Header; + UINT8 BlockType2; + UINT32 Length; +} EFI_HII_GIBT_EXT4_BLOCK; + +typedef struct _EFI_HII_GIBT_GLYPH_BLOCK { + EFI_HII_GLYPH_BLOCK Header; + EFI_HII_GLYPH_INFO Cell; + UINT8 BitmapData[1]; // the number of bytes per bitmap can be calculated by ((Cell.Width+7)/8)*Cell.Height +} EFI_HII_GIBT_GLYPH_BLOCK; + +typedef struct _EFI_HII_GIBT_GLYPHS_BLOCK { + EFI_HII_GLYPH_BLOCK Header; + EFI_HII_GLYPH_INFO Cell; + UINT16 Count; + UINT8 BitmapData[1]; // the number of bytes per bitmap can be calculated by ((Cell.Width+7)/8)*Cell.Height +} EFI_HII_GIBT_GLYPHS_BLOCK; + +typedef struct _EFI_HII_GIBT_GLYPH_DEFAULT_BLOCK { + EFI_HII_GLYPH_BLOCK Header; + UINT8 BitmapData[1]; // the number of bytes per bitmap can be calculated by ((Global.Cell.Width+7)/8)*Global.Cell.Height +} EFI_HII_GIBT_GLYPH_DEFAULT_BLOCK; + +typedef struct _EFI_HII_GIBT_GLYPHS_DEFAULT_BLOCK { + EFI_HII_GLYPH_BLOCK Header; + UINT16 Count; + UINT8 BitmapData[1]; // the number of bytes per bitmap can be calculated by ((Global.Cell.Width+7)/8)*Global.Cell.Height +} EFI_HII_GIBT_GLYPHS_DEFAULT_BLOCK; + +typedef struct _EFI_HII_GIBT_SKIP1_BLOCK { + EFI_HII_GLYPH_BLOCK Header; + UINT8 SkipCount; +} EFI_HII_GIBT_SKIP1_BLOCK; + +typedef struct _EFI_HII_GIBT_SKIP2_BLOCK { + EFI_HII_GLYPH_BLOCK Header; + UINT16 SkipCount; +} EFI_HII_GIBT_SKIP2_BLOCK; + +// +// Device Path Package +// +typedef struct _EFI_HII_DEVICE_PATH_PACKAGE { + EFI_HII_PACKAGE_HEADER Header; + // EFI_DEVICE_PATH_PROTOCOL DevicePath[]; +} EFI_HII_DEVICE_PATH_PACKAGE; + +// +// GUID Package +// +typedef struct _EFI_HII_GUID_PACKAGE_HDR { + EFI_HII_PACKAGE_HEADER Header; + EFI_GUID Guid; + // Data per GUID definition may follow +} EFI_HII_GUID_PACKAGE_HDR; + +// +// String Package +// + +#define UEFI_CONFIG_LANG L"x-UEFI" +#define UEFI_CONFIG_LANG2 L"x-i-UEFI" // BUGBUG, spec need to be updated. + +typedef struct _EFI_HII_STRING_PACKAGE_HDR { + EFI_HII_PACKAGE_HEADER Header; + UINT32 HdrSize; + UINT32 StringInfoOffset; + CHAR16 LanguageWindow[16]; + EFI_STRING_ID LanguageName; + CHAR8 Language[1]; +} EFI_HII_STRING_PACKAGE_HDR; + +typedef struct { + UINT8 BlockType; +} EFI_HII_STRING_BLOCK; + +#define EFI_HII_SIBT_END 0x00 +#define EFI_HII_SIBT_STRING_SCSU 0x10 +#define EFI_HII_SIBT_STRING_SCSU_FONT 0x11 +#define EFI_HII_SIBT_STRINGS_SCSU 0x12 +#define EFI_HII_SIBT_STRINGS_SCSU_FONT 0x13 +#define EFI_HII_SIBT_STRING_UCS2 0x14 +#define EFI_HII_SIBT_STRING_UCS2_FONT 0x15 +#define EFI_HII_SIBT_STRINGS_UCS2 0x16 +#define EFI_HII_SIBT_STRINGS_UCS2_FONT 0x17 +#define EFI_HII_SIBT_DUPLICATE 0x20 +#define EFI_HII_SIBT_SKIP2 0x21 +#define EFI_HII_SIBT_SKIP1 0x22 +#define EFI_HII_SIBT_EXT1 0x30 +#define EFI_HII_SIBT_EXT2 0x31 +#define EFI_HII_SIBT_EXT4 0x32 +#define EFI_HII_SIBT_FONT 0x40 + +typedef struct _EFI_HII_SIBT_DUPLICATE_BLOCK { + EFI_HII_STRING_BLOCK Header; + EFI_STRING_ID StringId; +} EFI_HII_SIBT_DUPLICATE_BLOCK; + +typedef struct _EFI_HII_SIBT_END_BLOCK { + EFI_HII_STRING_BLOCK Header; +} EFI_HII_SIBT_END_BLOCK; + +typedef struct _EFI_HII_SIBT_EXT1_BLOCK { + EFI_HII_STRING_BLOCK Header; + UINT8 BlockType2; + UINT8 Length; +} EFI_HII_SIBT_EXT1_BLOCK; + +typedef struct _EFI_HII_SIBT_EXT2_BLOCK { + EFI_HII_STRING_BLOCK Header; + UINT8 BlockType2; + UINT16 Length; +} EFI_HII_SIBT_EXT2_BLOCK; + +typedef struct _EFI_HII_SIBT_EXT4_BLOCK { + EFI_HII_STRING_BLOCK Header; + UINT8 BlockType2; + UINT32 Length; +} EFI_HII_SIBT_EXT4_BLOCK; + +typedef struct _EFI_HII_SIBT_FONT_BLOCK { + EFI_HII_SIBT_EXT2_BLOCK Header; + UINT8 FontId; + UINT16 FontSize; + EFI_HII_FONT_STYLE FontStyle; + CHAR16 FontName[1]; +} EFI_HII_SIBT_FONT_BLOCK; + +typedef struct _EFI_HII_SIBT_SKIP1_BLOCK { + EFI_HII_STRING_BLOCK Header; + UINT8 SkipCount; +} EFI_HII_SIBT_SKIP1_BLOCK; + +typedef struct _EFI_HII_SIBT_SKIP2_BLOCK { + EFI_HII_STRING_BLOCK Header; + UINT16 SkipCount; +} EFI_HII_SIBT_SKIP2_BLOCK; + +typedef struct _EFI_HII_SIBT_STRING_SCSU_BLOCK { + EFI_HII_STRING_BLOCK Header; + UINT8 StringText[1]; +} EFI_HII_SIBT_STRING_SCSU_BLOCK; + +typedef struct _EFI_HII_SIBT_STRING_SCSU_FONT_BLOCK { + EFI_HII_STRING_BLOCK Header; + UINT8 FontIdentifier; + UINT8 StringText[1]; +} EFI_HII_SIBT_STRING_SCSU_FONT_BLOCK; + +typedef struct _EFI_HII_SIBT_STRINGS_SCSU_BLOCK { + EFI_HII_STRING_BLOCK Header; + UINT16 StringCount; + UINT8 StringText[1]; +} EFI_HII_SIBT_STRINGS_SCSU_BLOCK; + +typedef struct _EFI_HII_SIBT_STRINGS_SCSU_FONT_BLOCK { + EFI_HII_STRING_BLOCK Header; + UINT8 FontIdentifier; + UINT16 StringCount; + UINT8 StringText[1]; +} EFI_HII_SIBT_STRINGS_SCSU_FONT_BLOCK; + +typedef struct _EFI_HII_SIBT_STRING_UCS2_BLOCK { + EFI_HII_STRING_BLOCK Header; + CHAR16 StringText[1]; +} EFI_HII_SIBT_STRING_UCS2_BLOCK; + +typedef struct _EFI_HII_SIBT_STRING_UCS2_FONT_BLOCK { + EFI_HII_STRING_BLOCK Header; + UINT8 FontIdentifier; + CHAR16 StringText[1]; +} EFI_HII_SIBT_STRING_UCS2_FONT_BLOCK; + +typedef struct _EFI_HII_SIBT_STRINGS_UCS2_BLOCK { + EFI_HII_STRING_BLOCK Header; + UINT16 StringCount; + CHAR16 StringText[1]; +} EFI_HII_SIBT_STRINGS_UCS2_BLOCK; + +typedef struct _EFI_HII_SIBT_STRINGS_UCS2_FONT_BLOCK { + EFI_HII_STRING_BLOCK Header; + UINT8 FontIdentifier; + UINT16 StringCount; + CHAR16 StringText[1]; +} EFI_HII_SIBT_STRINGS_UCS2_FONT_BLOCK; + +// +// Image Packages +// + +typedef struct _EFI_HII_IMAGE_PACKAGE_HDR { + EFI_HII_PACKAGE_HEADER Header; + UINT32 ImageInfoOffset; + UINT32 PaletteInfoOffset; +} EFI_HII_IMAGE_PACKAGE_HDR; + +typedef struct _EFI_HII_IMAGE_BLOCK { + UINT8 BlockType; +} EFI_HII_IMAGE_BLOCK; + +#define EFI_HII_IIBT_END 0x00 +#define EFI_HII_IIBT_IMAGE_1BIT 0x10 +#define EFI_HII_IIBT_IMAGE_1BIT_TRANS 0x11 +#define EFI_HII_IIBT_IMAGE_4BIT 0x12 +#define EFI_HII_IIBT_IMAGE_4BIT_TRANS 0x13 +#define EFI_HII_IIBT_IMAGE_8BIT 0x14 +#define EFI_HII_IIBT_IMAGE_8BIT_TRANS 0x15 +#define EFI_HII_IIBT_IMAGE_24BIT 0x16 +#define EFI_HII_IIBT_IMAGE_24BIT_TRANS 0x17 +#define EFI_HII_IIBT_IMAGE_JPEG 0x18 +#define EFI_HII_IIBT_DUPLICATE 0x20 +#define EFI_HII_IIBT_SKIP2 0x21 +#define EFI_HII_IIBT_SKIP1 0x22 +#define EFI_HII_IIBT_EXT1 0x30 +#define EFI_HII_IIBT_EXT2 0x31 +#define EFI_HII_IIBT_EXT4 0x32 + +typedef struct _EFI_HII_IIBT_END_BLOCK { + EFI_HII_IMAGE_BLOCK Header; +} EFI_HII_IIBT_END_BLOCK; + +typedef struct _EFI_HII_IIBT_EXT1_BLOCK { + EFI_HII_IMAGE_BLOCK Header; + UINT8 BlockType2; + UINT8 Length; +} EFI_HII_IIBT_EXT1_BLOCK; + +typedef struct _EFI_HII_IIBT_EXT2_BLOCK { + EFI_HII_IMAGE_BLOCK Header; + UINT8 BlockType2; + UINT16 Length; +} EFI_HII_IIBT_EXT2_BLOCK; + +typedef struct _EFI_HII_IIBT_EXT4_BLOCK { + EFI_HII_IMAGE_BLOCK Header; + UINT8 BlockType2; + UINT32 Length; +} EFI_HII_IIBT_EXT4_BLOCK; + +typedef struct _EFI_HII_IIBT_IMAGE_1BIT_BASE { + UINT16 Width; + UINT16 Height; + UINT8 Data[1]; +} EFI_HII_IIBT_IMAGE_1BIT_BASE; + +typedef struct _EFI_HII_IIBT_IMAGE_1BIT_BLOCK { + EFI_HII_IMAGE_BLOCK Header; + UINT8 PaletteIndex; + EFI_HII_IIBT_IMAGE_1BIT_BASE Bitmap; +} EFI_HII_IIBT_IMAGE_1BIT_BLOCK; + +typedef struct _EFI_HII_IIBT_IMAGE_1BIT_TRANS_BLOCK { + EFI_HII_IMAGE_BLOCK Header; + UINT8 PaletteIndex; + EFI_HII_IIBT_IMAGE_1BIT_BASE Bitmap; +} EFI_HII_IIBT_IMAGE_1BIT_TRANS_BLOCK; + +typedef struct _EFI_HII_RGB_PIXEL { + UINT8 b; + UINT8 g; + UINT8 r; +} EFI_HII_RGB_PIXEL; + +typedef struct _EFI_HII_IIBT_IMAGE_24BIT_BASE { + UINT16 Width; + UINT16 Height; + EFI_HII_RGB_PIXEL Bitmap[1]; +} EFI_HII_IIBT_IMAGE_24BIT_BASE; + +typedef struct _EFI_HII_IIBT_IMAGE_24BIT_BLOCK { + EFI_HII_IMAGE_BLOCK Header; + EFI_HII_IIBT_IMAGE_24BIT_BASE Bitmap; +} EFI_HII_IIBT_IMAGE_24BIT_BLOCK; + +typedef struct _EFI_HII_IIBT_IMAGE_24BIT_TRANS_BLOCK { + EFI_HII_IMAGE_BLOCK Header; + EFI_HII_IIBT_IMAGE_24BIT_BASE Bitmap; +} EFI_HII_IIBT_IMAGE_24BIT_TRANS_BLOCK; + +typedef struct _EFI_HII_IIBT_IMAGE_4BIT_BASE { + UINT16 Width; + UINT16 Height; + UINT8 Data[1]; +} EFI_HII_IIBT_IMAGE_4BIT_BASE; + +typedef struct _EFI_HII_IIBT_IMAGE_4BIT_BLOCK { + EFI_HII_IMAGE_BLOCK Header; + UINT8 PaletteIndex; + EFI_HII_IIBT_IMAGE_4BIT_BASE Bitmap; +} EFI_HII_IIBT_IMAGE_4BIT_BLOCK; + +typedef struct _EFI_HII_IIBT_IMAGE_4BIT_TRANS_BLOCK { + EFI_HII_IMAGE_BLOCK Header; + UINT8 PaletteIndex; + EFI_HII_IIBT_IMAGE_4BIT_BASE Bitmap; +} EFI_HII_IIBT_IMAGE_4BIT_TRANS_BLOCK; + +typedef struct _EFI_HII_IIBT_IMAGE_8BIT_BASE { + UINT16 Width; + UINT16 Height; + UINT8 Data[1]; +} EFI_HII_IIBT_IMAGE_8BIT_BASE; + +typedef struct _EFI_HII_IIBT_IMAGE_8BIT_PALETTE_BLOCK { + EFI_HII_IMAGE_BLOCK Header; + UINT8 PaletteIndex; + EFI_HII_IIBT_IMAGE_8BIT_BASE Bitmap; +} EFI_HII_IIBT_IMAGE_8BIT_BLOCK; + +typedef struct _EFI_HII_IIBT_IMAGE_8BIT_TRANS_BLOCK { + EFI_HII_IMAGE_BLOCK Header; + UINT8 PaletteIndex; + EFI_HII_IIBT_IMAGE_8BIT_BASE Bitmap; +} EFI_HII_IIBT_IMAGE_8BIT_TRAN_BLOCK; + +typedef struct _EFI_HII_IIBT_DUPLICATE_BLOCK { + EFI_HII_IMAGE_BLOCK Header; + EFI_IMAGE_ID ImageId; +} EFI_HII_IIBT_DUPLICATE_BLOCK; + +typedef struct _EFI_HII_IIBT_JPEG_BLOCK { + EFI_HII_IMAGE_BLOCK Header; + UINT32 Size; + UINT8 Data[1]; +} EFI_HII_IIBT_JPEG_BLOCK; + +typedef struct _EFI_HII_IIBT_SKIP1_BLOCK { + EFI_HII_IMAGE_BLOCK Header; + UINT8 SkipCount; +} EFI_HII_IIBT_SKIP1_BLOCK; + +typedef struct _EFI_HII_IIBT_SKIP2_BLOCK { + EFI_HII_IMAGE_BLOCK Header; + UINT16 SkipCount; +} EFI_HII_IIBT_SKIP2_BLOCK; + +typedef struct _EFI_HII_IMAGE_PALETTE_INFO_HEADER { + UINT16 PaletteCount; +} EFI_HII_IMAGE_PALETTE_INFO_HEADER; + +typedef struct _EFI_HII_IMAGE_PALETTE_INFO { + UINT16 PaletteSize; + EFI_HII_RGB_PIXEL PaletteValue[1]; +} EFI_HII_IMAGE_PALETTE_INFO; + +// +// Forms Package +// + +typedef struct _EFI_HII_FORM_PACKAGE { + EFI_HII_PACKAGE_HEADER Header; + // EFI_IFR_OP_HEADER OpCodeHeader; + // More op-codes follow +} EFI_HII_FORM_PACKAGE; + +typedef struct { + UINT8 Hour; + UINT8 Minute; + UINT8 Second; +} EFI_HII_TIME; + +typedef struct { + UINT16 Year; + UINT8 Month; + UINT8 Day; +} EFI_HII_DATE; + +typedef union { + UINT8 u8; + UINT16 u16; + UINT32 u32; + UINT64 u64; + BOOLEAN b; + EFI_HII_TIME time; + EFI_HII_DATE date; + EFI_STRING_ID string; +} EFI_IFR_TYPE_VALUE; + +#define EFI_IFR_FORM_OP 0x01 +#define EFI_IFR_SUBTITLE_OP 0x02 +#define EFI_IFR_TEXT_OP 0x03 +#define EFI_IFR_IMAGE_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 +#define EFI_IFR_SUPPRESS_IF_OP 0x0A +#define EFI_IFR_LOCKED_OP 0x0B +#define EFI_IFR_ACTION_OP 0x0C +#define EFI_IFR_RESET_BUTTON_OP 0x0D +#define EFI_IFR_FORM_SET_OP 0x0E +#define EFI_IFR_REF_OP 0x0F +#define EFI_IFR_NO_SUBMIT_IF_OP 0x10 +#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_RULE_OP 0x18 +#define EFI_IFR_GRAY_OUT_IF_OP 0x19 +#define EFI_IFR_DATE_OP 0x1A +#define EFI_IFR_TIME_OP 0x1B +#define EFI_IFR_STRING_OP 0x1C +#define EFI_IFR_REFRESH_OP 0x1D +#define EFI_IFR_DISABLE_IF_OP 0x1E +#define EFI_IFR_TO_LOWER_OP 0x20 +#define EFI_IFR_TO_UPPER_OP 0x21 +#define EFI_IFR_ORDERED_LIST_OP 0x23 +#define EFI_IFR_VARSTORE_OP 0x24 +#define EFI_IFR_VARSTORE_NAME_VALUE_OP 0x25 +#define EFI_IFR_VARSTORE_EFI_OP 0x26 +#define EFI_IFR_VARSTORE_DEVICE_OP 0x27 +#define EFI_IFR_VERSION_OP 0x28 +#define EFI_IFR_END_OP 0x29 +#define EFI_IFR_MATCH_OP 0x2A +#define EFI_IFR_EQUAL_OP 0x2F +#define EFI_IFR_NOT_EQUAL_OP 0x30 +#define EFI_IFR_GREATER_THAN_OP 0x31 +#define EFI_IFR_GREATER_EQUAL_OP 0x32 +#define EFI_IFR_LESS_THAN_OP 0x33 +#define EFI_IFR_LESS_EQUAL_OP 0x34 +#define EFI_IFR_BITWISE_AND_OP 0x35 +#define EFI_IFR_BITWISE_OR_OP 0x36 +#define EFI_IFR_BITWISE_NOT_OP 0x37 +#define EFI_IFR_SHIFT_LEFT_OP 0x38 +#define EFI_IFR_SHIFT_RIGHT_OP 0x39 +#define EFI_IFR_ADD_OP 0x3A +#define EFI_IFR_SUBTRACT_OP 0x3B +#define EFI_IFR_MULTIPLY_OP 0x3C +#define EFI_IFR_DIVIDE_OP 0x3D +#define EFI_IFR_MODULO_OP 0x3E +#define EFI_IFR_RULE_REF_OP 0x3F +#define EFI_IFR_QUESTION_REF1_OP 0x40 +#define EFI_IFR_QUESTION_REF2_OP 0x41 +#define EFI_IFR_UINT8_OP 0x42 +#define EFI_IFR_UINT16_OP 0x43 +#define EFI_IFR_UINT32_OP 0x44 +#define EFI_IFR_UINT64_OP 0x45 +#define EFI_IFR_TRUE_OP 0x46 +#define EFI_IFR_FALSE_OP 0x47 +#define EFI_IFR_TO_UINT_OP 0x48 +#define EFI_IFR_TO_STRING_OP 0x49 +#define EFI_IFR_TO_BOOLEAN_OP 0x4A +#define EFI_IFR_MID_OP 0x4B +#define EFI_IFR_FIND_OP 0x4C +#define EFI_IFR_TOKEN_OP 0x4D +#define EFI_IFR_STRING_REF1_OP 0x4E +#define EFI_IFR_STRING_REF2_OP 0x4F +#define EFI_IFR_CONDITIONAL_OP 0x50 +#define EFI_IFR_QUESTION_REF3_OP 0x51 +#define EFI_IFR_ZERO_OP 0x52 +#define EFI_IFR_ONE_OP 0x53 +#define EFI_IFR_ONES_OP 0x54 +#define EFI_IFR_UNDEFINED_OP 0x55 +#define EFI_IFR_LENGTH_OP 0x56 +#define EFI_IFR_DUP_OP 0x57 +#define EFI_IFR_THIS_OP 0x58 +#define EFI_IFR_SPAN_OP 0x59 +#define EFI_IFR_VALUE_OP 0x5A +#define EFI_IFR_DEFAULT_OP 0x5B +#define EFI_IFR_DEFAULTSTORE_OP 0x5C +#define EFI_IFR_CATENATE_OP 0x5E +#define EFI_IFR_GUID_OP 0x5F + + +typedef struct _EFI_IFR_OP_HEADER { + UINT8 OpCode; + UINT8 Length:7; + UINT8 Scope:1; +} EFI_IFR_OP_HEADER; + +typedef struct _EFI_IFR_STATEMENT_HEADER { + EFI_STRING_ID Prompt; + EFI_STRING_ID Help; +} EFI_IFR_STATEMENT_HEADER; + +typedef struct _EFI_IFR_QUESTION_HEADER { + EFI_IFR_STATEMENT_HEADER Header; + EFI_QUESTION_ID QuestionId; + EFI_VARSTORE_ID VarStoreId; + union { + EFI_STRING_ID VarName; + UINT16 VarOffset; + } VarStoreInfo; + UINT8 Flags; +} EFI_IFR_QUESTION_HEADER; + +#define EFI_IFR_FLAG_READ_ONLY 0x01 +#define EFI_IFR_FLAG_CALLBACK 0x04 +#define EFI_IFR_FLAG_RESET_REQUIRED 0x10 +#define EFI_IFR_FLAG_OPTIONS_ONLY 0x80 + +typedef struct _EFI_IFR_DEFAULTSTORE { + EFI_IFR_OP_HEADER Header; + EFI_STRING_ID DefaultName; + UINT16 DefaultId; +} EFI_IFR_DEFAULTSTORE; + +#define EFI_HII_DEFAULT_CLASS_STANDARD 0x0000 +#define EFI_HII_DEFAULT_CLASS_MANUFACTURING 0x0001 +#define EFI_HII_DEFAULT_CLASS_SAFE 0x0002 +#define EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN 0x4000 +#define EFI_HII_DEFAULT_CLASS_PLATFORM_END 0x7fff +#define EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN 0x8000 +#define EFI_HII_DEFAULT_CLASS_HARDWARE_END 0xbfff +#define EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN 0xc000 +#define EFI_HII_DEFAULT_CLASS_FIRMWARE_END 0xffff + +typedef struct _EFI_IFR_VARSTORE { + EFI_IFR_OP_HEADER Header; + EFI_GUID Guid; + EFI_VARSTORE_ID VarStoreId; + UINT16 Size; + UINT8 Name[1]; +} EFI_IFR_VARSTORE; + +typedef struct _EFI_IFR_VARSTORE_EFI { + EFI_IFR_OP_HEADER Header; + UINT16 VarStoreId; + EFI_GUID Guid; + UINT32 Attributes; +} EFI_IFR_VARSTORE_EFI; + +typedef struct _EFI_IFR_VARSTORE_NAME_VALUE { + EFI_IFR_OP_HEADER Header; + UINT16 VarStoreId; + EFI_GUID Guid; +} EFI_IFR_VARSTORE_NAME_VALUE; + +typedef struct _EFI_IFR_FORM_SET { + EFI_IFR_OP_HEADER Header; + EFI_GUID Guid; + EFI_STRING_ID FormSetTitle; + EFI_STRING_ID Help; + UINT8 Flags; + EFI_GUID ClassGuid[1]; +} EFI_IFR_FORM_SET; + +typedef struct _EFI_IFR_END { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_END; + +typedef struct _EFI_IFR_FORM { + EFI_IFR_OP_HEADER Header; + UINT16 FormId; + EFI_STRING_ID FormTitle; +} EFI_IFR_FORM; + +typedef struct _EFI_IFR_IMAGE { + EFI_IFR_OP_HEADER Header; + EFI_IMAGE_ID Id; +} EFI_IFR_IMAGE; + +typedef struct _EFI_IFR_LOCKED { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_LOCKED; + +typedef struct _EFI_IFR_RULE { + EFI_IFR_OP_HEADER Header; + UINT8 RuleId; +} EFI_IFR_RULE; + +typedef struct _EFI_IFR_DEFAULT { + EFI_IFR_OP_HEADER Header; + UINT16 DefaultId; + UINT8 Type; + EFI_IFR_TYPE_VALUE Value; +} EFI_IFR_DEFAULT; + +typedef struct _EFI_IFR_VALUE { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_VALUE; + +typedef struct _EFI_IFR_SUBTITLE { + EFI_IFR_OP_HEADER Header; + EFI_IFR_STATEMENT_HEADER Statement; + UINT8 Flags; +} EFI_IFR_SUBTITLE; + +#define EFI_IFR_FLAGS_HORIZONTAL 0x01 + +typedef struct _EFI_IFR_CHECKBOX { + EFI_IFR_OP_HEADER Header; + EFI_IFR_QUESTION_HEADER Question; + UINT8 Flags; +} EFI_IFR_CHECKBOX; + +#define EFI_IFR_CHECKBOX_DEFAULT 0x01 +#define EFI_IFR_CHECKBOX_DEFAULT_MFG 0x02 + +typedef struct _EFI_IFR_TEXT { + EFI_IFR_OP_HEADER Header; + EFI_IFR_STATEMENT_HEADER Statement; + EFI_STRING_ID TextTwo; +} EFI_IFR_TEXT; + +typedef struct _EFI_IFR_REF { + EFI_IFR_OP_HEADER Header; + EFI_IFR_QUESTION_HEADER Question; + EFI_FORM_ID FormId; +} EFI_IFR_REF; + +typedef struct _EFI_IFR_REF2 { + EFI_IFR_OP_HEADER Header; + EFI_IFR_QUESTION_HEADER Question; + EFI_FORM_ID FormId; + EFI_QUESTION_ID QuestionId; +} EFI_IFR_REF2; + +typedef struct _EFI_IFR_REF3 { + EFI_IFR_OP_HEADER Header; + EFI_IFR_QUESTION_HEADER Question; + EFI_FORM_ID FormId; + EFI_QUESTION_ID QuestionId; + EFI_GUID FormSetId; +} EFI_IFR_REF3; + +typedef struct _EFI_IFR_REF4 { + EFI_IFR_OP_HEADER Header; + EFI_IFR_QUESTION_HEADER Question; + EFI_FORM_ID FormId; + EFI_QUESTION_ID QuestionId; + EFI_GUID FormSetId; + EFI_STRING_ID DevicePath; +} EFI_IFR_REF4; + +typedef struct _EFI_IFR_RESET_BUTTON { + EFI_IFR_OP_HEADER Header; + EFI_IFR_QUESTION_HEADER Question; + EFI_DEFAULT_ID DefaultId; +} EFI_IFR_RESET_BUTTON; + +typedef struct _EFI_IFR_ACTION { + EFI_IFR_OP_HEADER Header; + EFI_IFR_QUESTION_HEADER Question; + EFI_STRING_ID QuestionConfig; +} EFI_IFR_ACTION; + +typedef struct _EFI_IFR_ACTION_1 { + EFI_IFR_OP_HEADER Header; + EFI_IFR_QUESTION_HEADER Question; +} EFI_IFR_ACTION_1; + +typedef struct _EFI_IFR_DATE { + EFI_IFR_OP_HEADER Header; + EFI_IFR_QUESTION_HEADER Question; + UINT8 Flags; +} EFI_IFR_DATE; + +#define EFI_QF_DATE_YEAR_SUPPRESS 0x01 +#define EFI_QF_DATE_MONTH_SUPPRESS 0x02 +#define EFI_QF_DATE_DAY_SUPPRESS 0x04 + +#define EFI_QF_DATE_STORAGE 0x30 +#define QF_DATE_STORAGE_NORMAL 0x00 +#define QF_DATE_STORAGE_TIME 0x10 +#define QF_DATE_STORAGE_WAKEUP 0x20 + +typedef union { + struct { + UINT8 MinValue; + UINT8 MaxValue; + UINT8 Step; + } u8; + struct { + UINT16 MinValue; + UINT16 MaxValue; + UINT16 Step; + } u16; + struct { + UINT32 MinValue; + UINT32 MaxValue; + UINT32 Step; + } u32; + struct { + UINT64 MinValue; + UINT64 MaxValue; + UINT64 Step; + } u64; +} MINMAXSTEP_DATA; + +typedef struct _EFI_IFR_NUMERIC { + EFI_IFR_OP_HEADER Header; + EFI_IFR_QUESTION_HEADER Question; + UINT8 Flags; + MINMAXSTEP_DATA data; +} EFI_IFR_NUMERIC; + +#define EFI_IFR_NUMERIC_SIZE 0x03 +#define EFI_IFR_NUMERIC_SIZE_1 0x00 +#define EFI_IFR_NUMERIC_SIZE_2 0x01 +#define EFI_IFR_NUMERIC_SIZE_4 0x02 +#define EFI_IFR_NUMERIC_SIZE_8 0x03 + +#define EFI_IFR_DISPLAY 0x30 +#define EFI_IFR_DISPLAY_INT_DEC 0x00 +#define EFI_IFR_DISPLAY_UINT_DEC 0x10 +#define EFI_IFR_DISPLAY_UINT_HEX 0x20 + +typedef struct _EFI_IFR_ONE_OF { + EFI_IFR_OP_HEADER Header; + EFI_IFR_QUESTION_HEADER Question; + UINT8 Flags; + MINMAXSTEP_DATA data; +} EFI_IFR_ONE_OF; + +typedef struct _EFI_IFR_STRING { + EFI_IFR_OP_HEADER Header; + EFI_IFR_QUESTION_HEADER Question; + UINT8 MinSize; + UINT8 MaxSize; + UINT8 Flags; +} EFI_IFR_STRING; + +#define EFI_IFR_STRING_MULTI_LINE 0x01 + +typedef struct _EFI_IFR_PASSWORD { + EFI_IFR_OP_HEADER Header; + EFI_IFR_QUESTION_HEADER Question; + UINT16 MinSize; + UINT16 MaxSize; +} EFI_IFR_PASSWORD; + +typedef struct _EFI_IFR_ORDERED_LIST { + EFI_IFR_OP_HEADER Header; + EFI_IFR_QUESTION_HEADER Question; + UINT8 MaxContainers; + UINT8 Flags; +} EFI_IFR_ORDERED_LIST; + +#define EFI_IFR_UNIQUE_SET 0x01 +#define EFI_IFR_NO_EMPTY_SET 0x02 + +typedef struct _EFI_IFR_TIME { + EFI_IFR_OP_HEADER Header; + EFI_IFR_QUESTION_HEADER Question; + UINT8 Flags; +} EFI_IFR_TIME; + +#define QF_TIME_HOUR_SUPPRESS 0x01 +#define QF_TIME_MINUTE_SUPPRESS 0x02 +#define QF_TIME_SECOND_SUPPRESS 0x04 + +#define QF_TIME_STORAGE 0x30 +#define QF_TIME_STORAGE_NORMAL 0x00 +#define QF_TIME_STORAGE_TIME 0x10 +#define QF_TIME_STORAGE_WAKEUP 0x20 + +typedef struct _EFI_IFR_DISABLE_IF { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_DISABLE_IF; + +typedef struct _EFI_IFR_SUPPRESS_IF { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_SUPPRESS_IF; + +typedef struct _EFI_IFR_GRAY_OUT_IF { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_GRAY_OUT_IF; + +typedef struct _EFI_IFR_INCONSISTENT_IF { + EFI_IFR_OP_HEADER Header; + EFI_STRING_ID Error; +} EFI_IFR_INCONSISTENT_IF; + +typedef struct _EFI_IFR_NO_SUBMIT_IF { + EFI_IFR_OP_HEADER Header; + EFI_STRING_ID Error; +} EFI_IFR_NO_SUBMIT_IF; + +typedef struct _EFI_IFR_REFRESH { + EFI_IFR_OP_HEADER Header; + UINT8 RefreshInterval; +} EFI_IFR_REFRESH; + +typedef struct _EFI_IFR_VARSTORE_DEVICE { + EFI_IFR_OP_HEADER Header; + EFI_STRING_ID DevicePath; +} EFI_IFR_VARSTORE_DEVICE; + +typedef struct _EFI_IFR_ONE_OF_OPTION { + EFI_IFR_OP_HEADER Header; + EFI_STRING_ID Option; + UINT8 Flags; + UINT8 Type; + EFI_IFR_TYPE_VALUE Value; +} EFI_IFR_ONE_OF_OPTION; + +#define EFI_IFR_TYPE_NUM_SIZE_8 0x00 +#define EFI_IFR_TYPE_NUM_SIZE_16 0x01 +#define EFI_IFR_TYPE_NUM_SIZE_32 0x02 +#define EFI_IFR_TYPE_NUM_SIZE_64 0x03 +#define EFI_IFR_TYPE_BOOLEAN 0x04 +#define EFI_IFR_TYPE_TIME 0x05 +#define EFI_IFR_TYPE_DATE 0x06 +#define EFI_IFR_TYPE_STRING 0x07 +#define EFI_IFR_TYPE_OTHER 0x08 + +#define EFI_IFR_OPTION_DEFAULT 0x10 +#define EFI_IFR_OPTION_DEFAULT_MFG 0x20 + +typedef struct _EFI_IFR_GUID { + EFI_IFR_OP_HEADER Header; + EFI_GUID Guid; + //Optional Data Follows +} EFI_IFR_GUID; + +typedef struct _EFI_IFR_DUP { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_DUP; + +typedef struct _EFI_IFR_EQ_ID_ID { + EFI_IFR_OP_HEADER Header; + EFI_QUESTION_ID QuestionId1; + EFI_QUESTION_ID QuestionId2; +} EFI_IFR_EQ_ID_ID; + +typedef struct _EFI_IFR_EQ_ID_VAL { + EFI_IFR_OP_HEADER Header; + EFI_QUESTION_ID QuestionId; + UINT16 Value; +} EFI_IFR_EQ_ID_VAL; + +typedef struct _EFI_IFR_EQ_ID_LIST { + EFI_IFR_OP_HEADER Header; + EFI_QUESTION_ID QuestionId; + UINT16 ListLength; + UINT16 ValueList[1]; +} EFI_IFR_EQ_ID_LIST; + +typedef struct _EFI_IFR_QUESTION_REF1 { + EFI_IFR_OP_HEADER Header; + EFI_QUESTION_ID QuestionId; +} EFI_IFR_QUESTION_REF1; + +typedef struct _EFI_IFR_UINT8 { + EFI_IFR_OP_HEADER Header; + UINT8 Value; +} EFI_IFR_UINT8; + +typedef struct _EFI_IFR_UINT16 { + EFI_IFR_OP_HEADER Header; + UINT16 Value; +} EFI_IFR_UINT16; + +typedef struct _EFI_IFR_QUESTION_REF2 { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_QUESTION_REF2; + +typedef struct _EFI_IFR_UINT32 { + EFI_IFR_OP_HEADER Header; + UINT32 Value; +} EFI_IFR_UINT32; + +typedef struct _EFI_IFR_UINT64 { + EFI_IFR_OP_HEADER Header; + UINT64 Value; +} EFI_IFR_UINT64; + +typedef struct _EFI_IFR_QUESTION_REF3 { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_QUESTION_REF3; + +typedef struct _EFI_IFR_QUESTION_REF3_2 { + EFI_IFR_OP_HEADER Header; + EFI_STRING_ID DevicePath; +} EFI_IFR_QUESTION_REF3_2; + +typedef struct _EFI_IFR_QUESTION_REF3_3 { + EFI_IFR_OP_HEADER Header; + EFI_STRING_ID DevicePath; + EFI_GUID Guid; +} EFI_IFR_QUESTION_REF3_3; + +typedef struct _EFI_IFR_RULE_REF { + EFI_IFR_OP_HEADER Header; + UINT8 RuleId; +} EFI_IFR_RULE_REF; + +typedef struct _EFI_IFR_STRING_REF1 { + EFI_IFR_OP_HEADER Header; + EFI_STRING_ID StringId; +} EFI_IFR_STRING_REF1; + +typedef struct _EFI_IFR_STRING_REF2 { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_STRING_REF2; + +typedef struct _EFI_IFR_THIS { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_THIS; + +typedef struct _EFI_IFR_TRUE { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_TRUE; + +typedef struct _EFI_IFR_FALSE { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_FALSE; + +typedef struct _EFI_IFR_ONE { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_ONE; + +typedef struct _EFI_IFR_ONES { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_ONES; + +typedef struct _EFI_IFR_ZERO { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_ZERO; + +typedef struct _EFI_IFR_UNDEFINED { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_UNDEFINED; + +typedef struct _EFI_IFR_VERSION { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_VERSION; + +typedef struct _EFI_IFR_LENGTH { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_LENGTH; + +typedef struct _EFI_IFR_NOT { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_NOT; + +typedef struct _EFI_IFR_BITWISE_NOT { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_BITWISE_NOT; + +typedef struct _EFI_IFR_TO_BOOLEAN { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_TO_BOOLEAN; + +#define EFI_IFR_STRING_UNSIGNED_DEC 0 +#define EFI_IFR_STRING_SIGNED_DEC 1 +#define EFI_IFR_STRING_LOWERCASE_HEX 2 +#define EFI_IFR_STRING_UPPERCASE_HEX 3 + +#define EFI_IFR_STRING_ASCII 0 +#define EFI_IFR_STRING_UNICODE 8 + +typedef struct _EFI_IFR_TO_STRING { + EFI_IFR_OP_HEADER Header; + UINT8 Format; +} EFI_IFR_TO_STRING; + +typedef struct _EFI_IFR_TO_UINT { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_TO_UINT; + +typedef struct _EFI_IFR_TO_UPPER { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_TO_UPPER; + +typedef struct _EFI_IFR_TO_LOWER { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_TO_LOWER; + +typedef struct _EFI_IFR_ADD { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_ADD; + +typedef struct _EFI_IFR_AND { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_AND; + +typedef struct _EFI_IFR_BITWISE_AND { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_BITWISE_AND; + +typedef struct _EFI_IFR_BITWISE_OR { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_BITWISE_OR; + +typedef struct _EFI_IFR_CATENATE { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_CATENATE; + +typedef struct _EFI_IFR_DIVIDE { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_DIVIDE; + +typedef struct _EFI_IFR_EQUAL { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_EQUAL; + +typedef struct _EFI_IFR_GREATER_EQUAL { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_GREATER_EQUAL; + +typedef struct _EFI_IFR_GREATER_THAN { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_GREATER_THAN; + +typedef struct _EFI_IFR_LESS_EQUAL { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_LESS_EQUAL; + +typedef struct _EFI_IFR_LESS_THAN { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_LESS_THAN; + +typedef struct _EFI_IFR_MATCH { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_MATCH; + +typedef struct _EFI_IFR_MULTIPLY { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_MULTIPLY; + +typedef struct _EFI_IFR_MODULO { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_MODULO; + +typedef struct _EFI_IFR_NOT_EQUAL { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_NOT_EQUAL; + +typedef struct _EFI_IFR_OR { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_OR; + +typedef struct _EFI_IFR_SHIFT_LEFT { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_SHIFT_LEFT; + +typedef struct _EFI_IFR_SHIFT_RIGHT { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_SHIFT_RIGHT; + +typedef struct _EFI_IFR_SUBTRACT { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_SUBTRACT; + +typedef struct _EFI_IFR_CONDITIONAL { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_CONDITIONAL; + +#define EFI_IFR_FF_CASE_SENSITIVE 0x00 +#define EFI_IFR_FF_CASE_INSENSITIVE 0x01 + +typedef struct _EFI_IFR_FIND { + EFI_IFR_OP_HEADER Header; + UINT8 Format; +} EFI_IFR_FIND; + +typedef struct _EFI_IFR_MID { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_MID; + +typedef struct _EFI_IFR_TOKEN { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_TOKEN; + +#define EFI_IFR_FLAGS_FIRST_MATCHING 0x00 +#define EFI_IFR_FLAGS_FIRST_NON_MATCHING 0x01 + +typedef struct _EFI_IFR_SPAN { + EFI_IFR_OP_HEADER Header; + UINT8 Flags; +} EFI_IFR_SPAN; + +// +// Keyboard Package +// + +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; + UINT16 AffectedAttribute; +} EFI_KEY_DESCRIPTOR; + +// +// A key which is affected by all the standard shift modifiers. +// Most keys would be expected to have this bit active. +// +#define EFI_AFFECTED_BY_STANDARD_SHIFT 0x0001 +// +// This key is affected by the caps lock so that if a keyboard driver +// would need to disambiguate between a key which had a "1" defined +// versus a "a" character. Having this bit turned on would tell +// the keyboard driver to use the appropriate shifted state or not. +// +#define EFI_AFFECTED_BY_CAPS_LOCK 0x0002 +// +// Similar to the case of CAPS lock, if this bit is active, the key +// is affected by the num lock being turned on. +// +#define EFI_AFFECTED_BY_NUM_LOCK 0x0004 + +typedef struct { + UINT16 LayoutLength; + EFI_GUID Guid; + UINT32 LayoutDescriptorStringOffset; + UINT8 DescriptorCount; + // EFI_KEY_DESCRIPTOR Descriptors[]; +} EFI_HII_KEYBOARD_LAYOUT; + +typedef struct { + EFI_HII_PACKAGE_HEADER Header; + UINT16 LayoutCount; + // EFI_HII_KEYBOARD_LAYOUT Layout[]; +} EFI_HII_KEYBOARD_PACKAGE_HDR; + +typedef struct { + CHAR16 Language[3]; + CHAR16 Space; + CHAR16 DescriptionString[1]; +} EFI_DESCRIPTION_STRING; + +typedef struct { + UINT16 DescriptionCount; + EFI_DESCRIPTION_STRING DescriptionString[1]; +} EFI_DESCRIPTION_STRING_BUNDLE; + +// +// Modifier values +// +#define EFI_NULL_MODIFIER 0x0000 +#define EFI_LEFT_CONTROL_MODIFIER 0x0001 +#define EFI_RIGHT_CONTROL_MODIFIER 0x0002 +#define EFI_LEFT_ALT_MODIFIER 0x0003 +#define EFI_RIGHT_ALT_MODIFIER 0x0004 +#define EFI_ALT_GR_MODIFIER 0x0005 +#define EFI_INSERT_MODIFIER 0x0006 +#define EFI_DELETE_MODIFIER 0x0007 +#define EFI_PAGE_DOWN_MODIFIER 0x0008 +#define EFI_PAGE_UP_MODIFIER 0x0009 +#define EFI_HOME_MODIFIER 0x000A +#define EFI_END_MODIFIER 0x000B +#define EFI_LEFT_SHIFT_MODIFIER 0x000C +#define EFI_RIGHT_SHIFT_MODIFIER 0x000D +#define EFI_CAPS_LOCK_MODIFIER 0x000E +#define EFI_NUM_LOCK _MODIFIER 0x000F +#define EFI_LEFT_ARROW_MODIFIER 0x0010 +#define EFI_RIGHT_ARROW_MODIFIER 0x0011 +#define EFI_DOWN_ARROW_MODIFIER 0x0012 +#define EFI_UP_ARROW_MODIFIER 0x0013 +#define EFI_NS_KEY_MODIFIER 0x0014 +#define EFI_NS_KEY_DEPENDENCY_MODIFIER 0x0015 +#define EFI_FUNCTION_KEY_ONE_MODIFIER 0x0016 +#define EFI_FUNCTION_KEY_TWO_MODIFIER 0x0017 +#define EFI_FUNCTION_KEY_THREE_MODIFIER 0x0018 +#define EFI_FUNCTION_KEY_FOUR_MODIFIER 0x0019 +#define EFI_FUNCTION_KEY_FIVE_MODIFIER 0x001A +#define EFI_FUNCTION_KEY_SIX_MODIFIER 0x001B +#define EFI_FUNCTION_KEY_SEVEN_MODIFIER 0x001C +#define EFI_FUNCTION_KEY_EIGHT_MODIFIER 0x001D +#define EFI_FUNCTION_KEY_NINE_MODIFIER 0x001E +#define EFI_FUNCTION_KEY_TEN_MODIFIER 0x001F +#define EFI_FUNCTION_KEY_ELEVEN_MODIFIER 0x0020 +#define EFI_FUNCTION_KEY_TWELVE_MODIFIER 0x0021 + +// +// Keys that have multiple control functions based on modifier +// settings are handled in the keyboard driver implementation. +// For instance PRINT_KEY might have a modifier held down and +// is still a nonprinting character, but might have an alternate +// control function like SYSREQUEST +// +#define EFI_PRINT_MODIFIER 0x0022 +#define EFI_SYS_REQUEST_MODIFIER 0x0023 +#define EFI_SCROLL_LOCK_MODIFIER 0x0024 +#define EFI_PAUSE_MODIFIER 0x0025 +#define EFI_BREAK_MODIFIER 0x0026 + +#pragma pack() + + + +// +// References to string tokens must use this macro to enable scanning for +// token usages. +// +// +// STRING_TOKEN is not defined in UEFI specification. But it is placed +// here for the easy access by C files and VFR source files. +// +#define STRING_TOKEN(t) t + +#endif diff --git a/BaseTools/Source/C/Include/Common/UefiMultiPhase.h b/BaseTools/Source/C/Include/Common/UefiMultiPhase.h new file mode 100644 index 0000000000..59db59c5f5 --- /dev/null +++ b/BaseTools/Source/C/Include/Common/UefiMultiPhase.h @@ -0,0 +1,231 @@ +/** @file + This includes some definitions introduced in UEFI that will be used in both PEI and DXE phases. + + Copyright (c) 2006 - 2008, 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. + + File Name: UefiMultiPhase.h + +**/ + +#ifndef __UEFI_MULTIPHASE_H__ +#define __UEFI_MULTIPHASE_H__ + +// +// Enumeration of memory types introduced in UEFI. +// +typedef enum { + EfiReservedMemoryType, + EfiLoaderCode, + EfiLoaderData, + EfiBootServicesCode, + EfiBootServicesData, + EfiRuntimeServicesCode, + EfiRuntimeServicesData, + EfiConventionalMemory, + EfiUnusableMemory, + EfiACPIReclaimMemory, + EfiACPIMemoryNVS, + EfiMemoryMappedIO, + EfiMemoryMappedIOPortSpace, + EfiPalCode, + EfiMaxMemoryType +} EFI_MEMORY_TYPE; + + +// +// Data structure that precedes all of the standard EFI table types. +// +typedef struct { + UINT64 Signature; + UINT32 Revision; + UINT32 HeaderSize; + UINT32 CRC32; + UINT32 Reserved; +} EFI_TABLE_HEADER; + +// +// Attributes of variable. +// +#define EFI_VARIABLE_NON_VOLATILE 0x00000001 +#define EFI_VARIABLE_BOOTSERVICE_ACCESS 0x00000002 +#define EFI_VARIABLE_RUNTIME_ACCESS 0x00000004 +#define EFI_VARIABLE_HARDWARE_ERROR_RECORD 0x00000008 + +// +// This attribute is identified by the mnemonic 'HR' +// elsewhere in this specification. +// +#define EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS 0x00000010 + + + +// +// _WIN_CERTIFICATE.wCertificateType +// +#define WIN_CERT_TYPE_EFI_PKCS115 0x0EF0 +#define WIN_CERT_TYPE_EFI_GUID 0x0EF1 + +/** + + The WIN_CERTIFICATE structure is part of the PE/COFF + specification and has the following definition: + + @param dwLength The length of the entire certificate, + including the length of the header, in + bytes. + + @param wRevision The revision level of the WIN_CERTIFICATE + structure. The current revision level is + 0x0200. + + @param wCertificateType The certificate type. See + WIN_CERT_TYPE_xxx for the UEFI + certificate types. The UEFI + specification reserves the range of + certificate type values from 0x0EF0 + to 0x0EFF. + + @param bCertificate The actual certificate. The format of + the certificate depends on + wCertificateType. The format of the UEFI + certificates is defined below. + + +**/ +typedef struct _WIN_CERTIFICATE { + UINT32 dwLength; + UINT16 wRevision; + UINT16 wCertificateType; + //UINT8 bCertificate[ANYSIZE_ARRAY]; +} WIN_CERTIFICATE; + +// +// WIN_CERTIFICATE_UEFI_GUID.CertType +// +#define EFI_CERT_TYPE_RSA2048_SHA256_GUID \ + {0xa7717414, 0xc616, 0x4977, {0x94, 0x20, 0x84, 0x47, 0x12, 0xa7, 0x35, 0xbf } } + +// +// WIN_CERTIFICATE_UEFI_GUID.CertData +// +typedef struct _EFI_CERT_BLOCK_RSA_2048_SHA256 { + UINT32 HashType; + UINT8 PublicKey[256]; + UINT8 Signature[256]; +} EFI_CERT_BLOCK_RSA_2048_SHA256; + + +/** + + @param Hdr This is the standard WIN_CERTIFICATE header, where + wCertificateType is set to + WIN_CERT_TYPE_UEFI_GUID. + + @param CertType This is the unique id which determines the + format of the CertData. In this case, the + value is EFI_CERT_TYPE_RSA2048_SHA256_GUID. + + @param CertData This is the certificate data. The format of + the data is determined by the CertType. In + this case the value is + EFI_CERT_BLOCK_RSA_2048_SHA256. + + @param Information The WIN_CERTIFICATE_UEFI_GUID certificate + type allows new types of certificates to + be developed for driver authentication + without requiring a new certificate type. + The CertType defines the format of the + CertData, which length is defined by the + size of the certificate less the fixed + size of the WIN_CERTIFICATE_UEFI_GUID + structure. + +**/ +typedef struct _WIN_CERTIFICATE_UEFI_GUID { + WIN_CERTIFICATE Hdr; + EFI_GUID CertType; + // UINT8 CertData[ANYSIZE_ARRAY]; +} WIN_CERTIFICATE_UEFI_GUID; + + +/** + + Certificate which encapsulates the RSASSA_PKCS1-v1_5 digital + signature. + + The WIN_CERTIFICATE_UEFI_PKCS1_15 structure is derived from + WIN_CERTIFICATE and encapsulate the information needed to + implement the RSASSA-PKCS1-v1_5 digital signature algorithm as + specified in RFC2437. + + @param Hdr This is the standard WIN_CERTIFICATE header, where + wCertificateType is set to + WIN_CERT_TYPE_UEFI_PKCS1_15. + + @param HashAlgorithm This is the hashing algorithm which was + performed on the UEFI executable when + creating the digital signature. It is + one of the enumerated values pre-defined + in Section 26.4.1. See + EFI_HASH_ALGORITHM_x. + + @param Signature This is the actual digital signature. The + size of the signature is the same size as + the key (1024-bit key is 128 bytes) and can + be determined by subtracting the length of + the other parts of this header from the + total length of the certificate as found in + Hdr.dwLength. + +**/ +typedef struct _WIN_CERTIFICATE_EFI_PKCS1_15 { + WIN_CERTIFICATE Hdr; + EFI_GUID HashAlgorithm; + // UINT8 Signature[ANYSIZE_ARRAY]; +} WIN_CERTIFICATE_EFI_PKCS1_15; + + +/** + + AuthInfo is a WIN_CERTIFICATE using the wCertificateType + WIN_CERTIFICATE_UEFI_GUID and the CertType + EFI_CERT_TYPE_RSA2048_SHA256. If the attribute specifies + authenticated access, then the Data buffer should begin with an + authentication descriptor prior to the data payload and DataSize + should reflect the the data.and descriptor size. The caller + shall digest the Monotonic Count value and the associated data + for the variable update using the SHA-256 1-way hash algorithm. + The ensuing the 32-byte digest will be signed using the private + key associated w/ the public/private 2048-bit RSA key-pair. The + WIN_CERTIFICATE shall be used to describe the signature of the + Variable data *Data. In addition, the signature will also + include the MonotonicCount value to guard against replay attacks + + @param MonotonicCount Included in the signature of + AuthInfo.Used to ensure freshness/no + replay. Incremented during each + "Write" access. + + @param AuthInfo Provides the authorization for the variable + access. It is a signature across the + variable data and the Monotonic Count + value. Caller uses Private key that is + associated with a public key that has been + provisioned via the key exchange. + +**/ +typedef struct { + UINT64 MonotonicCount; + WIN_CERTIFICATE_UEFI_GUID AuthInfo; +} EFI_VARIABLE_AUTHENTICATION; + +#endif + diff --git a/BaseTools/Source/C/Include/Common/VariableFormat.h b/BaseTools/Source/C/Include/Common/VariableFormat.h new file mode 100644 index 0000000000..32d6b2570b --- /dev/null +++ b/BaseTools/Source/C/Include/Common/VariableFormat.h @@ -0,0 +1,54 @@ +/**@file + Header file for EFI Variable Services. + + Copyright (c) 2007 - 2008, 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. + + File Name: VariableFormat.h + +**/ + +#ifndef __VARIABLE_FORMAT_H__ +#define __VARIABLE_FORMAT_H__ + +#define VARIABLE_STORE_SIGNATURE EFI_SIGNATURE_32 ('$', 'V', 'S', 'S') + +#define VARIABLE_DATA 0x55AA + +// +// Variable Store Header flags +// +#define VARIABLE_STORE_FORMATTED 0x5a +#define VARIABLE_STORE_HEALTHY 0xfe + +#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; + UINT32 NameSize; + UINT32 DataSize; + EFI_GUID VendorGuid; +} VARIABLE_HEADER; + +#pragma pack() + +#endif // _EFI_VARIABLE_H_ diff --git a/BaseTools/Source/C/Include/Common/WorkingBlockHeader.h b/BaseTools/Source/C/Include/Common/WorkingBlockHeader.h new file mode 100644 index 0000000000..98f8527a7b --- /dev/null +++ b/BaseTools/Source/C/Include/Common/WorkingBlockHeader.h @@ -0,0 +1,43 @@ +/** @file + 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. + + Copyright (c) 2006 - 2008, 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. + + File Name: WorkingBlockHeader.h + +**/ + +#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; + UINT8 WorkingBlockValid : 1; + UINT8 WorkingBlockInvalid : 1; +#define WORKING_BLOCK_VALID 0x1 +#define WORKING_BLOCK_INVALID 0x2 + UINT8 Reserved : 6; + UINT8 Reserved3[3]; + UINT32 WriteQueueSize; + // + // UINT8 WriteQueue[WriteQueueSize]; + // +} EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER; + +#endif diff --git a/BaseTools/Source/C/Include/Guid/PcAnsi.h b/BaseTools/Source/C/Include/Guid/PcAnsi.h new file mode 100644 index 0000000000..9084d99f09 --- /dev/null +++ b/BaseTools/Source/C/Include/Guid/PcAnsi.h @@ -0,0 +1,61 @@ +/** @file + Terminal Device Path Vendor Guid. + + Copyright (c) 2006 - 2008, 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. + + File Name: PcAnsi.h + + @par Revision Reference: + GUIDs defined in UEFI 2.0 spec. + +**/ + +#ifndef __PC_ANSI_H__ +#define __PC_ANSI_H__ + +#define EFI_PC_ANSI_GUID \ + { \ + 0xe0c14753, 0xf9be, 0x11d2, {0x9a, 0x0c, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d } \ + } + +#define EFI_VT_100_GUID \ + { \ + 0xdfa66065, 0xb419, 0x11d3, {0x9a, 0x2d, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d } \ + } + +#define EFI_VT_100_PLUS_GUID \ + { \ + 0x7baec70b, 0x57e0, 0x4c76, {0x8e, 0x87, 0x2f, 0x9e, 0x28, 0x08, 0x83, 0x43 } \ + } + +#define EFI_VT_UTF8_GUID \ + { \ + 0xad15a0d6, 0x8bec, 0x4acf, {0xa0, 0x73, 0xd0, 0x1d, 0xe7, 0x7e, 0x2d, 0x88 } \ + } + +#define EFI_UART_DEVICE_PATH_GUID \ + { \ + 0x37499a9d, 0x542f, 0x4c89, {0xa0, 0x26, 0x35, 0xda, 0x14, 0x20, 0x94, 0xe4 } \ + } + +#define EFI_SAS_DEVICE_PATH_GUID \ + { \ + 0xd487ddb4, 0x008b, 0x11d9, {0xaf, 0xdc, 0x00, 0x10, 0x83, 0xff, 0xca, 0x4d } \ + } + +extern EFI_GUID gEfiPcAnsiGuid; +extern EFI_GUID gEfiVT100Guid; +extern EFI_GUID gEfiVT100PlusGuid; +extern EFI_GUID gEfiVTUTF8Guid; +extern EFI_GUID gEfiUartDevicePathGuid; +extern EFI_GUID gEfiSasDevicePathGuid; + +#endif diff --git a/BaseTools/Source/C/Include/Guid/PiFirmwareFileSystem.h b/BaseTools/Source/C/Include/Guid/PiFirmwareFileSystem.h new file mode 100644 index 0000000000..8ab4993584 --- /dev/null +++ b/BaseTools/Source/C/Include/Guid/PiFirmwareFileSystem.h @@ -0,0 +1,41 @@ +/** @file + Guid used to define the Firmware File System. See PI spec volume 3 for more + details. + + Copyright (c) 2006 - 2008, 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. + + File Name: PiFirmwareFileSystem.h + + @par Revision Reference: + Guids defined in PI Spec Volume 3 + +**/ + +#ifndef __FIRMWARE_FILE_SYSTEM2_GUID_H__ +#define __FIRMWARE_FILE_SYSTEM2_GUID_H__ + +// +// GUIDs defined by the PI specification. +// +#define EFI_FIRMWARE_FILE_SYSTEM2_GUID \ + { \ + 0x8c8ce578, 0x8a3d, 0x4f1c, {0x99, 0x35, 0x89, 0x61, 0x85, 0xc3, 0x2d, 0xd3 } \ + } + +#define EFI_FFS_VOLUME_TOP_FILE_GUID \ + { \ + 0x1BA0062E, 0xC779, 0x4582, {0x85, 0x66, 0x33, 0x6A, 0xE8, 0xF7, 0x8F, 0x09 } \ + } + +extern EFI_GUID gEfiFirmwareFileSystem2Guid; +extern EFI_GUID gEfiFirmwareVolumeTopFileGuid; + +#endif diff --git a/BaseTools/Source/C/Include/Ia32/ProcessorBind.h b/BaseTools/Source/C/Include/Ia32/ProcessorBind.h new file mode 100644 index 0000000000..122a0b1178 --- /dev/null +++ b/BaseTools/Source/C/Include/Ia32/ProcessorBind.h @@ -0,0 +1,168 @@ +/** @file + Processor or Compiler specific defines and types for x64. + + Copyright (c) 2006 - 2008, 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. + + File 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/BaseTools/Source/C/Include/IndustryStandard/Acpi.h b/BaseTools/Source/C/Include/IndustryStandard/Acpi.h new file mode 100644 index 0000000000..07c542ebfb --- /dev/null +++ b/BaseTools/Source/C/Include/IndustryStandard/Acpi.h @@ -0,0 +1,125 @@ +/** @file + This file contains some basic ACPI definitions that are consumed by drivers + that do not care about ACPI versions. + + 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. + + File Name: Acpi.h + +**/ + +#ifndef _ACPI_H_ +#define _ACPI_H_ + +// +// Common table header, this prefaces all ACPI tables, including FACS, but +// excluding the RSD PTR structure +// +typedef struct { + UINT32 Signature; + UINT32 Length; +} EFI_ACPI_COMMON_HEADER; + +// +// Common ACPI description table header. This structure prefaces most ACPI tables. +// +#pragma pack(1) + +typedef struct { + UINT32 Signature; + UINT32 Length; + UINT8 Revision; + UINT8 Checksum; + UINT8 OemId[6]; + UINT64 OemTableId; + UINT32 OemRevision; + UINT32 CreatorId; + UINT32 CreatorRevision; +} EFI_ACPI_DESCRIPTION_HEADER; + +#pragma pack() +// +// Define for Pci Host Bridge Resource Allocation +// +#define ACPI_ADDRESS_SPACE_DESCRIPTOR 0x8A +#define ACPI_END_TAG_DESCRIPTOR 0x79 + +#define ACPI_ADDRESS_SPACE_TYPE_MEM 0x00 +#define ACPI_ADDRESS_SPACE_TYPE_IO 0x01 +#define ACPI_ADDRESS_SPACE_TYPE_BUS 0x02 + +// +// Power Management Timer frequency is fixed at 3.579545MHz +// +#define ACPI_TIMER_FREQUENCY 3579545 + +// +// Make sure structures match spec +// +#pragma pack(1) + +typedef struct { + UINT8 Desc; + UINT16 Len; + UINT8 ResType; + UINT8 GenFlag; + UINT8 SpecificFlag; + UINT64 AddrSpaceGranularity; + UINT64 AddrRangeMin; + UINT64 AddrRangeMax; + UINT64 AddrTranslationOffset; + UINT64 AddrLen; +} EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR; + +typedef struct { + UINT8 Desc; + UINT8 Checksum; +} EFI_ACPI_END_TAG_DESCRIPTOR; + +// +// General use definitions +// +#define EFI_ACPI_RESERVED_BYTE 0x00 +#define EFI_ACPI_RESERVED_WORD 0x0000 +#define EFI_ACPI_RESERVED_DWORD 0x00000000 +#define EFI_ACPI_RESERVED_QWORD 0x0000000000000000 + +// +// Resource Type Specific Flags +// Ref ACPI specification 6.4.3.5.5 +// +// Bit [0] : Write Status, _RW +// +#define EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_READ_WRITE (1 << 0) +#define EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_READ_ONLY (0 << 0) +// +// Bit [2:1] : Memory Attributes, _MEM +// +#define EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_NON_CACHEABLE (0 << 1) +#define EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE (1 << 1) +#define EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_WRITE_COMBINING (2 << 1) +#define EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE (3 << 1) +// +// Bit [4:3] : Memory Attributes, _MTP +// +#define EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_ADDRESS_RANGE_MEMORY (0 << 3) +#define EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_ADDRESS_RANGE_RESERVED (1 << 3) +#define EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_ADDRESS_RANGE_ACPI (2 << 3) +#define EFI_APCI_MEMORY_RESOURCE_SPECIFIC_FLAG_ADDRESS_RANGE_NVS (3 << 3) +// +// Bit [5] : Memory to I/O Translation, _TTP +// +#define EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_TYPE_TRANSLATION (1 << 5) +#define EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_TYPE_STATIC (0 << 5) + +#pragma pack() + +#endif diff --git a/BaseTools/Source/C/Include/IndustryStandard/Acpi1_0.h b/BaseTools/Source/C/Include/IndustryStandard/Acpi1_0.h new file mode 100644 index 0000000000..946c524ddb --- /dev/null +++ b/BaseTools/Source/C/Include/IndustryStandard/Acpi1_0.h @@ -0,0 +1,292 @@ +/** @file + ACPI 1.0b definitions from the ACPI Specification, revision 1.0b + + Copyright (c) 2006 - 2007 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. + + File Name: Acpi1_0.h + +**/ + +#ifndef _ACPI_1_0_H_ +#define _ACPI_1_0_H_ + +#include "IndustryStandard/Acpi.h" + +// +// Ensure proper structure formats +// +#pragma pack(1) +// +// ACPI 1.0b table structures +// +// +// Root System Description Pointer Structure +// +typedef struct { + UINT64 Signature; + UINT8 Checksum; + UINT8 OemId[6]; + UINT8 Reserved; + UINT32 RsdtAddress; +} EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER; + +// +// Root System Description Table +// No definition needed as it is a common description table header followed by a +// variable number of UINT32 table pointers. +// +// +// RSDT Revision (as defined in ACPI 1.0b spec.) +// +#define EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_TABLE_REVISION 0x01 + +// +// Fixed ACPI Description Table Structure (FADT) +// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT32 FirmwareCtrl; + UINT32 Dsdt; + UINT8 IntModel; + UINT8 Reserved1; + UINT16 SciInt; + UINT32 SmiCmd; + UINT8 AcpiEnable; + UINT8 AcpiDisable; + UINT8 S4BiosReq; + UINT8 Reserved2; + UINT32 Pm1aEvtBlk; + UINT32 Pm1bEvtBlk; + UINT32 Pm1aCntBlk; + UINT32 Pm1bCntBlk; + UINT32 Pm2CntBlk; + UINT32 PmTmrBlk; + UINT32 Gpe0Blk; + UINT32 Gpe1Blk; + UINT8 Pm1EvtLen; + UINT8 Pm1CntLen; + UINT8 Pm2CntLen; + UINT8 PmTmLen; + UINT8 Gpe0BlkLen; + UINT8 Gpe1BlkLen; + UINT8 Gpe1Base; + UINT8 Reserved3; + UINT16 PLvl2Lat; + UINT16 PLvl3Lat; + UINT16 FlushSize; + UINT16 FlushStride; + UINT8 DutyOffset; + UINT8 DutyWidth; + UINT8 DayAlrm; + UINT8 MonAlrm; + UINT8 Century; + UINT8 Reserved4; + UINT8 Reserved5; + UINT8 Reserved6; + UINT32 Flags; +} EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE; + +// +// FADT Version (as defined in ACPI 1.0b spec.) +// +#define EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION 0x01 + +// +// Fixed ACPI Description Table Fixed Feature Flags +// All other bits are reserved and must be set to 0. +// +#define EFI_ACPI_1_0_WBINVD (1 << 0) +#define EFI_ACPI_1_0_WBINVD_FLUSH (1 << 1) +#define EFI_ACPI_1_0_PROC_C1 (1 << 2) +#define EFI_ACPI_1_0_P_LVL2_UP (1 << 3) +#define EFI_ACPI_1_0_PWR_BUTTON (1 << 4) +#define EFI_ACPI_1_0_SLP_BUTTON (1 << 5) +#define EFI_ACPI_1_0_FIX_RTC (1 << 6) +#define EFI_ACPI_1_0_RTC_S4 (1 << 7) +#define EFI_ACPI_1_0_TMR_VAL_EXT (1 << 8) +#define EFI_ACPI_1_0_DCK_CAP (1 << 9) + +// +// Firmware ACPI Control Structure +// +typedef struct { + UINT32 Signature; + UINT32 Length; + UINT32 HardwareSignature; + UINT32 FirmwareWakingVector; + UINT32 GlobalLock; + UINT32 Flags; + UINT8 Reserved[40]; +} EFI_ACPI_1_0_FIRMWARE_ACPI_CONTROL_STRUCTURE; + +// +// Firmware Control Structure Feature Flags +// All other bits are reserved and must be set to 0. +// +#define EFI_ACPI_1_0_S4BIOS_F (1 << 0) + +// +// Multiple APIC Description Table header definition. The rest of the table +// must be defined in a platform specific manner. +// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT32 LocalApicAddress; + UINT32 Flags; +} EFI_ACPI_1_0_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER; + +// +// MADT Revision (as defined in ACPI 1.0b spec.) +// +#define EFI_ACPI_1_0_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION 0x01 + +// +// Multiple APIC Flags +// All other bits are reserved and must be set to 0. +// +#define EFI_ACPI_1_0_PCAT_COMPAT (1 << 0) + +// +// Multiple APIC Description Table APIC structure types +// All other values between 0x09 an 0xFF are reserved and +// will be ignored by OSPM. +// +#define EFI_ACPI_1_0_PROCESSOR_LOCAL_APIC 0x00 +#define EFI_ACPI_1_0_IO_APIC 0x01 +#define EFI_ACPI_1_0_INTERRUPT_SOURCE_OVERRIDE 0x02 +#define EFI_ACPI_1_0_NON_MASKABLE_INTERRUPT_SOURCE 0x03 +#define EFI_ACPI_1_0_LOCAL_APIC_NMI 0x04 + +// +// APIC Structure Definitions +// +// +// Processor Local APIC Structure Definition +// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT8 AcpiProcessorId; + UINT8 ApicId; + UINT32 Flags; +} EFI_ACPI_1_0_PROCESSOR_LOCAL_APIC_STRUCTURE; + +// +// Local APIC Flags. All other bits are reserved and must be 0. +// +#define EFI_ACPI_1_0_LOCAL_APIC_ENABLED (1 << 0) + +// +// IO APIC Structure +// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT8 IoApicId; + UINT8 Reserved; + UINT32 IoApicAddress; + UINT32 SystemVectorBase; +} EFI_ACPI_1_0_IO_APIC_STRUCTURE; + +// +// Interrupt Source Override Structure +// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT8 Bus; + UINT8 Source; + UINT32 GlobalSystemInterruptVector; + UINT16 Flags; +} EFI_ACPI_1_0_INTERRUPT_SOURCE_OVERRIDE_STRUCTURE; + +// +// Non-Maskable Interrupt Source Structure +// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT16 Flags; + UINT32 GlobalSystemInterruptVector; +} EFI_ACPI_1_0_NON_MASKABLE_INTERRUPT_SOURCE_STRUCTURE; + +// +// Local APIC NMI Structure +// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT8 AcpiProcessorId; + UINT16 Flags; + UINT8 LocalApicInti; +} EFI_ACPI_1_0_LOCAL_APIC_NMI_STRUCTURE; + +// +// Smart Battery Description Table (SBST) +// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT32 WarningEnergyLevel; + UINT32 LowEnergyLevel; + UINT32 CriticalEnergyLevel; +} EFI_ACPI_1_0_SMART_BATTERY_DESCRIPTION_TABLE; + +// +// Known table signatures +// +// +// "RSD PTR " Root System Description Pointer +// +#define EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER_SIGNATURE 0x2052545020445352ULL + +// +// "APIC" Multiple APIC Description Table +// +#define EFI_ACPI_1_0_APIC_SIGNATURE 0x43495041 + +// +// "DSDT" Differentiated System Description Table +// +#define EFI_ACPI_1_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE 0x54445344 + +// +// "FACS" Firmware ACPI Control Structure +// +#define EFI_ACPI_1_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE 0x53434146 + +// +// "FACP" Fixed ACPI Description Table +// +#define EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE 0x50434146 + +// +// "PSDT" Persistent System Description Table +// +#define EFI_ACPI_1_0_PERSISTENT_SYSTEM_DESCRIPTION_TABLE_SIGNATURE 0x54445350 + +// +// "RSDT" Root System Description Table +// +#define EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_TABLE_SIGNATURE 0x54445352 + +// +// "SBST" Smart Battery Specification Table +// +#define EFI_ACPI_1_0_SMART_BATTERY_SPECIFICATION_TABLE_SIGNATURE 0x54534253 + +// +// "SSDT" Secondary System Description Table +// +#define EFI_ACPI_1_0_SECONDARY_SYSTEM_DESCRIPTION_TABLE_SIGNATURE 0x54445353 + +#pragma pack() + +#endif diff --git a/BaseTools/Source/C/Include/IndustryStandard/Acpi2_0.h b/BaseTools/Source/C/Include/IndustryStandard/Acpi2_0.h new file mode 100644 index 0000000000..a19e8822c3 --- /dev/null +++ b/BaseTools/Source/C/Include/IndustryStandard/Acpi2_0.h @@ -0,0 +1,528 @@ +/** @file + ACPI 2.0 definitions from the ACPI Specification, revision 2.0 + + Copyright (c) 2006 - 2007 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. + + File Name: Acpi2_0.h + +**/ + +#ifndef _ACPI_2_0_H_ +#define _ACPI_2_0_H_ + +#include "IndustryStandard/Acpi.h" + +// +// Ensure proper structure formats +// +#pragma pack(1) +// +// ACPI Specification Revision +// +#define EFI_ACPI_2_0_REVISION 0x02 + +// +// BUGBUG: OEM values need to be moved somewhere else, probably read from data hub +// and produced by a platform specific driver. +// +// +// ACPI OEM ID +// +#define EFI_ACPI_2_0_OEM_ID "INTEL " +#define EFI_ACPI_2_0_OEM_TABLE_ID 0x5034303738543245 // "E2T8704P" +// +// ACPI OEM Revision +// +#define EFI_ACPI_2_0_OEM_REVISION 0x00000002 + +// +// ACPI table creator ID +// +#define EFI_ACPI_2_0_CREATOR_ID 0x5446534D // TBD "MSFT" +// +// ACPI table creator revision +// +#define EFI_ACPI_2_0_CREATOR_REVISION 0x01000013 // TBD +// +// ACPI 2.0 Generic Address Space definition +// +typedef struct { + UINT8 AddressSpaceId; + UINT8 RegisterBitWidth; + UINT8 RegisterBitOffset; + UINT8 Reserved; + UINT64 Address; +} EFI_ACPI_2_0_GENERIC_ADDRESS_STRUCTURE; + +// +// Generic Address Space Address IDs +// +#define EFI_ACPI_2_0_SYSTEM_MEMORY 0 +#define EFI_ACPI_2_0_SYSTEM_IO 1 +#define EFI_ACPI_2_0_PCI_CONFIGURATION_SPACE 2 +#define EFI_ACPI_2_0_EMBEDDED_CONTROLLER 3 +#define EFI_ACPI_2_0_SMBUS 4 +#define EFI_ACPI_2_0_FUNCTIONAL_FIXED_HARDWARE 0x7F + +// +// ACPI 2.0 table structures +// +// +// Root System Description Pointer Structure +// +typedef struct { + UINT64 Signature; + UINT8 Checksum; + UINT8 OemId[6]; + UINT8 Revision; + UINT32 RsdtAddress; + UINT32 Length; + UINT64 XsdtAddress; + UINT8 ExtendedChecksum; + UINT8 Reserved[3]; +} EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER; + +// +// RSD_PTR Revision (as defined in ACPI 2.0 spec.) +// +#define EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER_REVISION 0x02 + +// +// Common table header, this prefaces all ACPI tables, including FACS, but +// excluding the RSD PTR structure +// +typedef struct { + UINT32 Signature; + UINT32 Length; +} EFI_ACPI_2_0_COMMON_HEADER; + +// +// Root System Description Table +// No definition needed as it is a common description table header followed by a +// variable number of UINT32 table pointers. +// +// +// RSDT Revision (as defined in ACPI 2.0 spec.) +// +#define EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_TABLE_REVISION 0x01 + +// +// Extended System Description Table +// No definition needed as it is a common description table header followed by a +// variable number of UINT64 table pointers. +// +// +// XSDT Revision (as defined in ACPI 2.0 spec.) +// +#define EFI_ACPI_2_0_EXTENDED_SYSTEM_DESCRIPTION_TABLE_REVISION 0x01 + +// +// Fixed ACPI Description Table Structure (FADT) +// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT32 FirmwareCtrl; + UINT32 Dsdt; + UINT8 Reserved0; + UINT8 PreferredPmProfile; + UINT16 SciInt; + UINT32 SmiCmd; + UINT8 AcpiEnable; + UINT8 AcpiDisable; + UINT8 S4BiosReq; + UINT8 PstateCnt; + UINT32 Pm1aEvtBlk; + UINT32 Pm1bEvtBlk; + UINT32 Pm1aCntBlk; + UINT32 Pm1bCntBlk; + UINT32 Pm2CntBlk; + UINT32 PmTmrBlk; + UINT32 Gpe0Blk; + UINT32 Gpe1Blk; + UINT8 Pm1EvtLen; + UINT8 Pm1CntLen; + UINT8 Pm2CntLen; + UINT8 PmTmrLen; + UINT8 Gpe0BlkLen; + UINT8 Gpe1BlkLen; + UINT8 Gpe1Base; + UINT8 CstCnt; + UINT16 PLvl2Lat; + UINT16 PLvl3Lat; + UINT16 FlushSize; + UINT16 FlushStride; + UINT8 DutyOffset; + UINT8 DutyWidth; + UINT8 DayAlrm; + UINT8 MonAlrm; + UINT8 Century; + UINT16 IaPcBootArch; + UINT8 Reserved1; + UINT32 Flags; + EFI_ACPI_2_0_GENERIC_ADDRESS_STRUCTURE ResetReg; + UINT8 ResetValue; + UINT8 Reserved2[3]; + UINT64 XFirmwareCtrl; + UINT64 XDsdt; + EFI_ACPI_2_0_GENERIC_ADDRESS_STRUCTURE XPm1aEvtBlk; + EFI_ACPI_2_0_GENERIC_ADDRESS_STRUCTURE XPm1bEvtBlk; + EFI_ACPI_2_0_GENERIC_ADDRESS_STRUCTURE XPm1aCntBlk; + EFI_ACPI_2_0_GENERIC_ADDRESS_STRUCTURE XPm1bCntBlk; + EFI_ACPI_2_0_GENERIC_ADDRESS_STRUCTURE XPm2CntBlk; + EFI_ACPI_2_0_GENERIC_ADDRESS_STRUCTURE XPmTmrBlk; + EFI_ACPI_2_0_GENERIC_ADDRESS_STRUCTURE XGpe0Blk; + EFI_ACPI_2_0_GENERIC_ADDRESS_STRUCTURE XGpe1Blk; +} EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE; + +// +// FADT Version (as defined in ACPI 2.0 spec.) +// +#define EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION 0x03 + +// +// Fixed ACPI Description Table Boot Architecture Flags +// All other bits are reserved and must be set to 0. +// +#define EFI_ACPI_2_0_LEGACY_DEVICES (1 << 0) +#define EFI_ACPI_2_0_8042 (1 << 1) + +// +// Fixed ACPI Description Table Fixed Feature Flags +// All other bits are reserved and must be set to 0. +// +#define EFI_ACPI_2_0_WBINVD (1 << 0) +#define EFI_ACPI_2_0_WBINVD_FLUSH (1 << 1) +#define EFI_ACPI_2_0_PROC_C1 (1 << 2) +#define EFI_ACPI_2_0_P_LVL2_UP (1 << 3) +#define EFI_ACPI_2_0_PWR_BUTTON (1 << 4) +#define EFI_ACPI_2_0_SLP_BUTTON (1 << 5) +#define EFI_ACPI_2_0_FIX_RTC (1 << 6) +#define EFI_ACPI_2_0_RTC_S4 (1 << 7) +#define EFI_ACPI_2_0_TMR_VAL_EXT (1 << 8) +#define EFI_ACPI_2_0_DCK_CAP (1 << 9) +#define EFI_ACPI_2_0_RESET_REG_SUP (1 << 10) +#define EFI_ACPI_2_0_SEALED_CASE (1 << 11) +#define EFI_ACPI_2_0_HEADLESS (1 << 12) +#define EFI_ACPI_2_0_CPU_SW_SLP (1 << 13) + +// +// Firmware ACPI Control Structure +// +typedef struct { + UINT32 Signature; + UINT32 Length; + UINT32 HardwareSignature; + UINT32 FirmwareWakingVector; + UINT32 GlobalLock; + UINT32 Flags; + UINT64 XFirmwareWakingVector; + UINT8 Version; + UINT8 Reserved[31]; +} EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE; + +// +// FACS Version (as defined in ACPI 2.0 spec.) +// +#define EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_VERSION 0x01 + +// +// Firmware Control Structure Feature Flags +// All other bits are reserved and must be set to 0. +// +#define EFI_ACPI_2_0_S4BIOS_F (1 << 0) + +// +// Multiple APIC Description Table header definition. The rest of the table +// must be defined in a platform specific manner. +// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT32 LocalApicAddress; + UINT32 Flags; +} EFI_ACPI_2_0_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER; + +// +// MADT Revision (as defined in ACPI 2.0 spec.) +// +#define EFI_ACPI_2_0_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION 0x01 + +// +// Multiple APIC Flags +// All other bits are reserved and must be set to 0. +// +#define EFI_ACPI_2_0_PCAT_COMPAT (1 << 0) + +// +// Multiple APIC Description Table APIC structure types +// All other values between 0x09 an 0xFF are reserved and +// will be ignored by OSPM. +// +#define EFI_ACPI_2_0_PROCESSOR_LOCAL_APIC 0x00 +#define EFI_ACPI_2_0_IO_APIC 0x01 +#define EFI_ACPI_2_0_INTERRUPT_SOURCE_OVERRIDE 0x02 +#define EFI_ACPI_2_0_NON_MASKABLE_INTERRUPT_SOURCE 0x03 +#define EFI_ACPI_2_0_LOCAL_APIC_NMI 0x04 +#define EFI_ACPI_2_0_LOCAL_APIC_ADDRESS_OVERRIDE 0x05 +#define EFI_ACPI_2_0_IO_SAPIC 0x06 +#define EFI_ACPI_2_0_PROCESSOR_LOCAL_SAPIC 0x07 +#define EFI_ACPI_2_0_PLATFORM_INTERRUPT_SOURCES 0x08 + +// +// APIC Structure Definitions +// +// +// Processor Local APIC Structure Definition +// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT8 AcpiProcessorId; + UINT8 ApicId; + UINT32 Flags; +} EFI_ACPI_2_0_PROCESSOR_LOCAL_APIC_STRUCTURE; + +// +// Local APIC Flags. All other bits are reserved and must be 0. +// +#define EFI_ACPI_2_0_LOCAL_APIC_ENABLED (1 << 0) + +// +// IO APIC Structure +// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT8 IoApicId; + UINT8 Reserved; + UINT32 IoApicAddress; + UINT32 GlobalSystemInterruptBase; +} EFI_ACPI_2_0_IO_APIC_STRUCTURE; + +// +// Interrupt Source Override Structure +// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT8 Bus; + UINT8 Source; + UINT32 GlobalSystemInterrupt; + UINT16 Flags; +} EFI_ACPI_2_0_INTERRUPT_SOURCE_OVERRIDE_STRUCTURE; + +// +// Non-Maskable Interrupt Source Structure +// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT16 Flags; + UINT32 GlobalSystemInterrupt; +} EFI_ACPI_2_0_NON_MASKABLE_INTERRUPT_SOURCE_STRUCTURE; + +// +// Local APIC NMI Structure +// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT8 AcpiProcessorId; + UINT16 Flags; + UINT8 LocalApicLint; +} EFI_ACPI_2_0_LOCAL_APIC_NMI_STRUCTURE; + +// +// Local APIC Address Override Structure +// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT16 Reserved; + UINT64 LocalApicAddress; +} EFI_ACPI_2_0_LOCAL_APIC_ADDRESS_OVERRIDE_STRUCTURE; + +// +// IO SAPIC Structure +// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT8 IoApicId; + UINT8 Reserved; + UINT32 GlobalSystemInterruptBase; + UINT64 IoSapicAddress; +} EFI_ACPI_2_0_IO_SAPIC_STRUCTURE; + +// +// Local SAPIC Structure +// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT8 AcpiProcessorId; + UINT8 LocalSapicId; + UINT8 LocalSapicEid; + UINT8 Reserved[3]; + UINT32 Flags; +} EFI_ACPI_2_0_PROCESSOR_LOCAL_SAPIC_STRUCTURE; + +// +// Platform Interrupt Sources Structure +// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT16 Flags; + UINT8 InterruptType; + UINT8 ProcessorId; + UINT8 ProcessorEid; + UINT8 IoSapicVector; + UINT32 GlobalSystemInterrupt; + UINT32 Reserved; +} EFI_ACPI_2_0_PLATFORM_INTERRUPT_SOURCES_STRUCTURE; + +// +// Smart Battery Description Table (SBST) +// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT32 WarningEnergyLevel; + UINT32 LowEnergyLevel; + UINT32 CriticalEnergyLevel; +} EFI_ACPI_2_0_SMART_BATTERY_DESCRIPTION_TABLE; + +// +// SBST Version (as defined in ACPI 2.0 spec.) +// +#define EFI_ACPI_2_0_SMART_BATTERY_DESCRIPTION_TABLE_REVISION 0x01 + +// +// Embedded Controller Boot Resources Table (ECDT) +// The table is followed by a null terminated ASCII string that contains +// a fully qualified reference to the name space object. +// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + EFI_ACPI_2_0_GENERIC_ADDRESS_STRUCTURE EcControl; + EFI_ACPI_2_0_GENERIC_ADDRESS_STRUCTURE EcData; + UINT32 Uid; + UINT8 GpeBit; +} EFI_ACPI_2_0_EMBEDDED_CONTROLLER_BOOT_RESOURCES_TABLE; + +// +// ECDT Version (as defined in ACPI 2.0 spec.) +// +#define EFI_ACPI_2_0_EMBEDDED_CONTROLLER_BOOT_RESOURCES_TABLE_REVISION 0x01 + +// +// Known table signatures +// +// +// "RSD PTR " Root System Description Pointer +// +#define EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER_SIGNATURE 0x2052545020445352 + +// +// "SPIC" Multiple SAPIC Description Table +// +// BUGBUG: Don't know where this came from except SR870BN4 uses it. +// #define EFI_ACPI_2_0_MULTIPLE_SAPIC_DESCRIPTION_TABLE_SIGNATURE 0x43495053 +// +#define EFI_ACPI_2_0_MULTIPLE_SAPIC_DESCRIPTION_TABLE_SIGNATURE 0x43495041 + +// +// "BOOT" MS Simple Boot Spec +// +#define EFI_ACPI_2_0_SIMPLE_BOOT_FLAG_TABLE_SIGNATURE 0x544F4F42 + +// +// "DBGP" MS Bebug Port Spec +// +#define EFI_ACPI_2_0_DEBUG_PORT_TABLE_SIGNATURE 0x50474244 + +// +// "DSDT" Differentiated System Description Table +// +#define EFI_ACPI_2_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE 0x54445344 + +// +// "ECDT" Embedded Controller Boot Resources Table +// +#define EFI_ACPI_2_0_EMBEDDED_CONTROLLER_BOOT_RESOURCES_TABLE_SIGNATURE 0x54444345 + +// +// "ETDT" Event Timer Description Table +// +#define EFI_ACPI_2_0_EVENT_TIMER_DESCRIPTION_TABLE_SIGNATURE 0x54445445 + +// +// "FACS" Firmware ACPI Control Structure +// +#define EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE 0x53434146 + +// +// "FACP" Fixed ACPI Description Table +// +#define EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE 0x50434146 + +// +// "APIC" Multiple APIC Description Table +// +#define EFI_ACPI_2_0_MULTIPLE_APIC_DESCRIPTION_TABLE_SIGNATURE 0x43495041 + +// +// "PSDT" Persistent System Description Table +// +#define EFI_ACPI_2_0_PERSISTENT_SYSTEM_DESCRIPTION_TABLE_SIGNATURE 0x54445350 + +// +// "RSDT" Root System Description Table +// +#define EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_TABLE_SIGNATURE 0x54445352 + +// +// "SBST" Smart Battery Specification Table +// +#define EFI_ACPI_2_0_SMART_BATTERY_SPECIFICATION_TABLE_SIGNATURE 0x54534253 + +// +// "SLIT" System Locality Information Table +// +#define EFI_ACPI_2_0_SYSTEM_LOCALITY_INFORMATION_TABLE_SIGNATURE 0x54494C53 + +// +// "SPCR" Serial Port Concole Redirection Table +// +#define EFI_ACPI_2_0_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_SIGNATURE 0x52435053 + +// +// "SRAT" Static Resource Affinity Table +// +#define EFI_ACPI_2_0_STATIC_RESOURCE_AFFINITY_TABLE_SIGNATURE 0x54415253 + +// +// "SSDT" Secondary System Description Table +// +#define EFI_ACPI_2_0_SECONDARY_SYSTEM_DESCRIPTION_TABLE_SIGNATURE 0x54445353 + +// +// "SPMI" Server Platform Management Interface Table +// +#define EFI_ACPI_2_0_SERVER_PLATFORM_MANAGEMENT_INTERFACE_SIGNATURE 0x494D5053 + +// +// "XSDT" Extended System Description Table +// +#define EFI_ACPI_2_0_EXTENDED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE 0x54445358 + +#pragma pack() + +#endif diff --git a/BaseTools/Source/C/Include/IndustryStandard/Acpi3_0.h b/BaseTools/Source/C/Include/IndustryStandard/Acpi3_0.h new file mode 100644 index 0000000000..4cd8b08df0 --- /dev/null +++ b/BaseTools/Source/C/Include/IndustryStandard/Acpi3_0.h @@ -0,0 +1,676 @@ +/** @file + ACPI 3.0 definitions from the ACPI Specification Revision 3.0 September 2, 2004 + + Copyright (c) 2006 - 2007 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. + + File Name: Acpi3_0.h + +**/ + +#ifndef _ACPI_3_0_H_ +#define _ACPI_3_0_H_ + +#include "IndustryStandard/Acpi.h" + +// +// Ensure proper structure formats +// +#pragma pack(1) +// +// ACPI Specification Revision +// +#define EFI_ACPI_3_0_REVISION 0x03 // BUGBUG: Not in spec yet. +// +// BUGBUG: OEM values need to be moved somewhere else, probably read from data hub +// and produced by a platform specific driver. +// +// +// ACPI 3.0 Generic Address Space definition +// +typedef struct { + UINT8 AddressSpaceId; + UINT8 RegisterBitWidth; + UINT8 RegisterBitOffset; + UINT8 AccessSize; + UINT64 Address; +} EFI_ACPI_3_0_GENERIC_ADDRESS_STRUCTURE; + +// +// Generic Address Space Address IDs +// +#define EFI_ACPI_3_0_SYSTEM_MEMORY 0 +#define EFI_ACPI_3_0_SYSTEM_IO 1 +#define EFI_ACPI_3_0_PCI_CONFIGURATION_SPACE 2 +#define EFI_ACPI_3_0_EMBEDDED_CONTROLLER 3 +#define EFI_ACPI_3_0_SMBUS 4 +#define EFI_ACPI_3_0_FUNCTIONAL_FIXED_HARDWARE 0x7F + +// +// Generic Address Space Access Sizes +// +#define EFI_ACPI_3_0_UNDEFINED 0 +#define EFI_ACPI_3_0_BYTE 1 +#define EFI_ACPI_3_0_WORD 2 +#define EFI_ACPI_3_0_DWORD 3 +#define EFI_ACPI_3_0_QWORD 4 + +// +// ACPI 3.0 table structures +// +// +// Root System Description Pointer Structure +// +typedef struct { + UINT64 Signature; + UINT8 Checksum; + UINT8 OemId[6]; + UINT8 Revision; + UINT32 RsdtAddress; + UINT32 Length; + UINT64 XsdtAddress; + UINT8 ExtendedChecksum; + UINT8 Reserved[3]; +} EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER; + +// +// RSD_PTR Revision (as defined in ACPI 3.0 spec.) +// +#define EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER_REVISION 0x02 // ACPISpec30 (Revision 3.0 September 2, 2004) says current value is 2 +// +// Common table header, this prefaces all ACPI tables, including FACS, but +// excluding the RSD PTR structure +// +typedef struct { + UINT32 Signature; + UINT32 Length; +} EFI_ACPI_3_0_COMMON_HEADER; + +// +// Root System Description Table +// No definition needed as it is a common description table header followed by a +// variable number of UINT32 table pointers. +// +// +// RSDT Revision (as defined in ACPI 3.0 spec.) +// +#define EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_TABLE_REVISION 0x01 + +// +// Extended System Description Table +// No definition needed as it is a common description table header followed by a +// variable number of UINT64 table pointers. +// +// +// XSDT Revision (as defined in ACPI 3.0 spec.) +// +#define EFI_ACPI_3_0_EXTENDED_SYSTEM_DESCRIPTION_TABLE_REVISION 0x01 + +// +// Fixed ACPI Description Table Structure (FADT) +// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT32 FirmwareCtrl; + UINT32 Dsdt; + UINT8 Reserved0; + UINT8 PreferredPmProfile; + UINT16 SciInt; + UINT32 SmiCmd; + UINT8 AcpiEnable; + UINT8 AcpiDisable; + UINT8 S4BiosReq; + UINT8 PstateCnt; + UINT32 Pm1aEvtBlk; + UINT32 Pm1bEvtBlk; + UINT32 Pm1aCntBlk; + UINT32 Pm1bCntBlk; + UINT32 Pm2CntBlk; + UINT32 PmTmrBlk; + UINT32 Gpe0Blk; + UINT32 Gpe1Blk; + UINT8 Pm1EvtLen; + UINT8 Pm1CntLen; + UINT8 Pm2CntLen; + UINT8 PmTmrLen; + UINT8 Gpe0BlkLen; + UINT8 Gpe1BlkLen; + UINT8 Gpe1Base; + UINT8 CstCnt; + UINT16 PLvl2Lat; + UINT16 PLvl3Lat; + UINT16 FlushSize; + UINT16 FlushStride; + UINT8 DutyOffset; + UINT8 DutyWidth; + UINT8 DayAlrm; + UINT8 MonAlrm; + UINT8 Century; + UINT16 IaPcBootArch; + UINT8 Reserved1; + UINT32 Flags; + EFI_ACPI_3_0_GENERIC_ADDRESS_STRUCTURE ResetReg; + UINT8 ResetValue; + UINT8 Reserved2[3]; + UINT64 XFirmwareCtrl; + UINT64 XDsdt; + EFI_ACPI_3_0_GENERIC_ADDRESS_STRUCTURE XPm1aEvtBlk; + EFI_ACPI_3_0_GENERIC_ADDRESS_STRUCTURE XPm1bEvtBlk; + EFI_ACPI_3_0_GENERIC_ADDRESS_STRUCTURE XPm1aCntBlk; + EFI_ACPI_3_0_GENERIC_ADDRESS_STRUCTURE XPm1bCntBlk; + EFI_ACPI_3_0_GENERIC_ADDRESS_STRUCTURE XPm2CntBlk; + EFI_ACPI_3_0_GENERIC_ADDRESS_STRUCTURE XPmTmrBlk; + EFI_ACPI_3_0_GENERIC_ADDRESS_STRUCTURE XGpe0Blk; + EFI_ACPI_3_0_GENERIC_ADDRESS_STRUCTURE XGpe1Blk; +} EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE; + +// +// FADT Version (as defined in ACPI 3.0 spec.) +// +#define EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION 0x04 + +// +// Fixed ACPI Description Table Preferred Power Management Profile +// +#define EFI_ACPI_3_0_PM_PROFILE_UNSPECIFIED 0 +#define EFI_ACPI_3_0_PM_PROFILE_DESKTOP 1 +#define EFI_ACPI_3_0_PM_PROFILE_MOBILE 2 +#define EFI_ACPI_3_0_PM_PROFILE_WORKSTATION 3 +#define EFI_ACPI_3_0_PM_PROFILE_ENTERPRISE_SERVER 4 +#define EFI_ACPI_3_0_PM_PROFILE_SOHO_SERVER 5 +#define EFI_ACPI_3_0_PM_PROFILE_APPLIANCE_PC 6 +#define EFI_ACPI_3_0_PM_PROFILE_PERFORMANCE_SERVER 7 + +// +// Fixed ACPI Description Table Boot Architecture Flags +// All other bits are reserved and must be set to 0. +// +#define EFI_ACPI_3_0_LEGACY_DEVICES (1 << 0) +#define EFI_ACPI_3_0_8042 (1 << 1) +#define EFI_ACPI_3_0_VGA_NOT_PRESENT (1 << 2) +#define EFI_ACPI_3_0_MSI_NOT_SUPPORTED (1 << 3) +// +// Fixed ACPI Description Table Fixed Feature Flags +// All other bits are reserved and must be set to 0. +// +#define EFI_ACPI_3_0_WBINVD (1 << 0) +#define EFI_ACPI_3_0_WBINVD_FLUSH (1 << 1) +#define EFI_ACPI_3_0_PROC_C1 (1 << 2) +#define EFI_ACPI_3_0_P_LVL2_UP (1 << 3) +#define EFI_ACPI_3_0_PWR_BUTTON (1 << 4) +#define EFI_ACPI_3_0_SLP_BUTTON (1 << 5) +#define EFI_ACPI_3_0_FIX_RTC (1 << 6) +#define EFI_ACPI_3_0_RTC_S4 (1 << 7) +#define EFI_ACPI_3_0_TMR_VAL_EXT (1 << 8) +#define EFI_ACPI_3_0_DCK_CAP (1 << 9) +#define EFI_ACPI_3_0_RESET_REG_SUP (1 << 10) +#define EFI_ACPI_3_0_SEALED_CASE (1 << 11) +#define EFI_ACPI_3_0_HEADLESS (1 << 12) +#define EFI_ACPI_3_0_CPU_SW_SLP (1 << 13) +#define EFI_ACPI_3_0_PCI_EXP_WAK (1 << 14) +#define EFI_ACPI_3_0_USE_PLATFORM_CLOCK (1 << 15) +#define EFI_ACPI_3_0_S4_RTC_STS_VALID (1 << 16) +#define EFI_ACPI_3_0_REMOTE_POWER_ON_CAPABLE (1 << 17) +#define EFI_ACPI_3_0_FORCE_APIC_CLUSTER_MODEL (1 << 18) +#define EFI_ACPI_3_0_FORCE_APIC_PHYSICAL_DESTINATION_MODE (1 << 19) + +// +// Firmware ACPI Control Structure +// +typedef struct { + UINT32 Signature; + UINT32 Length; + UINT32 HardwareSignature; + UINT32 FirmwareWakingVector; + UINT32 GlobalLock; + UINT32 Flags; + UINT64 XFirmwareWakingVector; + UINT8 Version; + UINT8 Reserved[31]; +} EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE; + +// +// FACS Version (as defined in ACPI 3.0 spec.) +// +#define EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_VERSION 0x01 + +// +// Firmware Control Structure Feature Flags +// All other bits are reserved and must be set to 0. +// +#define EFI_ACPI_3_0_S4BIOS_F (1 << 0) + +// +// Differentiated System Description Table, +// Secondary System Description Table +// and Persistent System Description Table, +// no definition needed as they are common description table header followed by a +// definition block. +// +#define EFI_ACPI_3_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_REVISION 0x02 +#define EFI_ACPI_3_0_SECONDARY_SYSTEM_DESCRIPTION_TABLE_REVISION 0x02 + +// +// Multiple APIC Description Table header definition. The rest of the table +// must be defined in a platform specific manner. +// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT32 LocalApicAddress; + UINT32 Flags; +} EFI_ACPI_3_0_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER; + +// +// MADT Revision (as defined in ACPI 3.0 spec.) +// +#define EFI_ACPI_3_0_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION 0x02 + +// +// Multiple APIC Flags +// All other bits are reserved and must be set to 0. +// +#define EFI_ACPI_3_0_PCAT_COMPAT (1 << 0) + +// +// Multiple APIC Description Table APIC structure types +// All other values between 0x09 an 0xFF are reserved and +// will be ignored by OSPM. +// +#define EFI_ACPI_3_0_PROCESSOR_LOCAL_APIC 0x00 +#define EFI_ACPI_3_0_IO_APIC 0x01 +#define EFI_ACPI_3_0_INTERRUPT_SOURCE_OVERRIDE 0x02 +#define EFI_ACPI_3_0_NON_MASKABLE_INTERRUPT_SOURCE 0x03 +#define EFI_ACPI_3_0_LOCAL_APIC_NMI 0x04 +#define EFI_ACPI_3_0_LOCAL_APIC_ADDRESS_OVERRIDE 0x05 +#define EFI_ACPI_3_0_IO_SAPIC 0x06 +#define EFI_ACPI_3_0_LOCAL_SAPIC 0x07 +#define EFI_ACPI_3_0_PLATFORM_INTERRUPT_SOURCES 0x08 + +// +// APIC Structure Definitions +// +// +// Processor Local APIC Structure Definition +// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT8 AcpiProcessorId; + UINT8 ApicId; + UINT32 Flags; +} EFI_ACPI_3_0_PROCESSOR_LOCAL_APIC_STRUCTURE; + +// +// Local APIC Flags. All other bits are reserved and must be 0. +// +#define EFI_ACPI_3_0_LOCAL_APIC_ENABLED (1 << 0) + +// +// IO APIC Structure +// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT8 IoApicId; + UINT8 Reserved; + UINT32 IoApicAddress; + UINT32 GlobalSystemInterruptBase; +} EFI_ACPI_3_0_IO_APIC_STRUCTURE; + +// +// Interrupt Source Override Structure +// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT8 Bus; + UINT8 Source; + UINT32 GlobalSystemInterrupt; + UINT16 Flags; +} EFI_ACPI_3_0_INTERRUPT_SOURCE_OVERRIDE_STRUCTURE; + +// +// Platform Interrupt Sources Structure Definition +// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT16 Flags; + UINT8 InterruptType; + UINT8 ProcessorId; + UINT8 ProcessorEid; + UINT8 IoSapicVector; + UINT32 GlobalSystemInterrupt; + UINT32 PlatformInterruptSourceFlags; + UINT8 CpeiProcessorOverride; + UINT8 Reserved[31]; +} EFI_ACPI_3_0_PLATFORM_INTERRUPT_APIC_STRUCTURE; + +// +// MPS INTI flags. +// All other bits are reserved and must be set to 0. +// +#define EFI_ACPI_3_0_POLARITY (3 << 0) +#define EFI_ACPI_3_0_TRIGGER_MODE (3 << 2) + +// +// Non-Maskable Interrupt Source Structure +// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT16 Flags; + UINT32 GlobalSystemInterrupt; +} EFI_ACPI_3_0_NON_MASKABLE_INTERRUPT_SOURCE_STRUCTURE; + +// +// Local APIC NMI Structure +// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT8 AcpiProcessorId; + UINT16 Flags; + UINT8 LocalApicLint; +} EFI_ACPI_3_0_LOCAL_APIC_NMI_STRUCTURE; + +// +// Local APIC Address Override Structure +// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT16 Reserved; + UINT64 LocalApicAddress; +} EFI_ACPI_3_0_LOCAL_APIC_ADDRESS_OVERRIDE_STRUCTURE; + +// +// IO SAPIC Structure +// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT8 IoApicId; + UINT8 Reserved; + UINT32 GlobalSystemInterruptBase; + UINT64 IoSapicAddress; +} EFI_ACPI_3_0_IO_SAPIC_STRUCTURE; + +// +// Local SAPIC Structure +// This struct followed by a null-terminated ASCII string - ACPI Processor UID String +// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT8 AcpiProcessorId; + UINT8 LocalSapicId; + UINT8 LocalSapicEid; + UINT8 Reserved[3]; + UINT32 Flags; + UINT32 ACPIProcessorUIDValue; +} EFI_ACPI_3_0_PROCESSOR_LOCAL_SAPIC_STRUCTURE; + +// +// Platform Interrupt Sources Structure +// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT16 Flags; + UINT8 InterruptType; + UINT8 ProcessorId; + UINT8 ProcessorEid; + UINT8 IoSapicVector; + UINT32 GlobalSystemInterrupt; + UINT32 PlatformInterruptSourceFlags; +} EFI_ACPI_3_0_PLATFORM_INTERRUPT_SOURCES_STRUCTURE; + +// +// Platform Interrupt Source Flags. +// All other bits are reserved and must be set to 0. +// +#define EFI_ACPI_3_0_CPEI_PROCESSOR_OVERRIDE (1 << 0) + +// +// Smart Battery Description Table (SBST) +// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT32 WarningEnergyLevel; + UINT32 LowEnergyLevel; + UINT32 CriticalEnergyLevel; +} EFI_ACPI_3_0_SMART_BATTERY_DESCRIPTION_TABLE; + +// +// SBST Version (as defined in ACPI 3.0 spec.) +// +#define EFI_ACPI_3_0_SMART_BATTERY_DESCRIPTION_TABLE_REVISION 0x01 + +// +// Embedded Controller Boot Resources Table (ECDT) +// The table is followed by a null terminated ASCII string that contains +// a fully qualified reference to the name space object. +// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + EFI_ACPI_3_0_GENERIC_ADDRESS_STRUCTURE EcControl; + EFI_ACPI_3_0_GENERIC_ADDRESS_STRUCTURE EcData; + UINT32 Uid; + UINT8 GpeBit; +} EFI_ACPI_3_0_EMBEDDED_CONTROLLER_BOOT_RESOURCES_TABLE; + +// +// ECDT Version (as defined in ACPI 3.0 spec.) +// +#define EFI_ACPI_3_0_EMBEDDED_CONTROLLER_BOOT_RESOURCES_TABLE_REVISION 0x01 + +// +// System Resource Affinity Table (SRAT. The rest of the table +// must be defined in a platform specific manner. +// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT32 Reserved1; // Must be set to 1 + UINT64 Reserved2; +} EFI_ACPI_3_0_SYSTEM_RESOURCE_AFFINITY_TABLE_HEADER; + +// +// SRAT Version (as defined in ACPI 3.0 spec.) +// +#define EFI_ACPI_3_0_SYSTEM_RESOURCE_AFFINITY_TABLE_REVISION 0x02 + +// +// SRAT structure types. +// All other values between 0x02 an 0xFF are reserved and +// will be ignored by OSPM. +// +#define EFI_ACPI_3_0_PROCESSOR_LOCAL_APIC_SAPIC_AFFINITY 0x00 +#define EFI_ACPI_3_0_MEMORY_AFFINITY 0x01 + +// +// Processor Local APIC/SAPIC Affinity Structure Definition +// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT8 ProximityDomain7To0; + UINT8 ApicId; + UINT32 Flags; + UINT8 LocalSapicEid; + UINT8 ProximityDomain31To8[3]; + UINT8 Reserved[4]; +} EFI_ACPI_3_0_PROCESSOR_LOCAL_APIC_SAPIC_AFFINITY_STRUCTURE; + +// +// Local APIC/SAPIC Flags. All other bits are reserved and must be 0. +// +#define EFI_ACPI_3_0_PROCESSOR_LOCAL_APIC_SAPIC_ENABLED (1 << 0) + +// +// Memory Affinity Structure Definition +// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT32 ProximityDomain; + UINT16 Reserved1; + UINT32 AddressBaseLow; + UINT32 AddressBaseHigh; + UINT32 LengthLow; + UINT32 LengthHigh; + UINT32 Reserved2; + UINT32 Flags; + UINT64 Reserved3; +} EFI_ACPI_3_0_MEMORY_AFFINITY_STRUCTURE; + +// +// Memory Flags. All other bits are reserved and must be 0. +// +#define EFI_ACPI_3_0_MEMORY_ENABLED (1 << 0) +#define EFI_ACPI_3_0_MEMORY_HOT_PLUGGABLE (1 << 1) +#define EFI_ACPI_3_0_MEMORY_NONVOLATILE (1 << 2) + +// +// System Locality Distance Information Table (SLIT). +// The rest of the table is a matrix. +// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT64 NumberOfSystemLocalities; +} EFI_ACPI_3_0_SYSTEM_LOCALITY_DISTANCE_INFORMATION_TABLE_HEADER; + +// +// SLIT Version (as defined in ACPI 3.0 spec.) +// +#define EFI_ACPI_3_0_SYSTEM_LOCALITY_DISTANCE_INFORMATION_TABLE_REVISION 0x01 + +// +// Known table signatures +// +// +// "RSD PTR " Root System Description Pointer +// +#define EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER_SIGNATURE 0x2052545020445352ULL + +// +// "APIC" Multiple APIC Description Table +// +#define EFI_ACPI_3_0_MULTIPLE_APIC_DESCRIPTION_TABLE_SIGNATURE 0x43495041 + +// +// "DSDT" Differentiated System Description Table +// +#define EFI_ACPI_3_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE 0x54445344 + +// +// "ECDT" Embedded Controller Boot Resources Table +// +#define EFI_ACPI_3_0_EMBEDDED_CONTROLLER_BOOT_RESOURCES_TABLE_SIGNATURE 0x54444345 + +// +// "FACP" Fixed ACPI Description Table +// +#define EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE 0x50434146 + +// +// "FACS" Firmware ACPI Control Structure +// +#define EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE 0x53434146 + +// +// "PSDT" Persistent System Description Table +// +#define EFI_ACPI_3_0_PERSISTENT_SYSTEM_DESCRIPTION_TABLE_SIGNATURE 0x54445350 + +// +// "RSDT" Root System Description Table +// +#define EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_TABLE_SIGNATURE 0x54445352 + +// +// "SBST" Smart Battery Specification Table +// +#define EFI_ACPI_3_0_SMART_BATTERY_SPECIFICATION_TABLE_SIGNATURE 0x54534253 + +// +// "SLIT" System Locality Information Table +// +#define EFI_ACPI_3_0_SYSTEM_LOCALITY_INFORMATION_TABLE_SIGNATURE 0x54494C53 + +// +// "SRAT" System Resource Affinity Table +// +#define EFI_ACPI_3_0_SYSTEM_RESOURCE_AFFINITY_TABLE_SIGNATURE 0x54415253 + +// +// "SSDT" Secondary System Description Table +// +#define EFI_ACPI_3_0_SECONDARY_SYSTEM_DESCRIPTION_TABLE_SIGNATURE 0x54445353 + +// +// "XSDT" Extended System Description Table +// +#define EFI_ACPI_3_0_EXTENDED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE 0x54445358 + +// +// "BOOT" MS Simple Boot Spec +// +#define EFI_ACPI_3_0_SIMPLE_BOOT_FLAG_TABLE_SIGNATURE 0x544F4F42 + +// +// "CPEP" Corrected Platform Error Polling Table +// See +// +#define EFI_ACPI_3_0_CORRECTED_PLATFORM_ERROR_POLLING_TABLE_SIGNATURE 0x50455043 + +// +// "DBGP" MS Debug Port Spec +// +#define EFI_ACPI_3_0_DEBUG_PORT_TABLE_SIGNATURE 0x50474244 + +// +// "ETDT" Event Timer Description Table +// +#define EFI_ACPI_3_0_EVENT_TIMER_DESCRIPTION_TABLE_SIGNATURE 0x54445445 + +// +// "HPET" IA-PC High Precision Event Timer Table +// +#define EFI_ACPI_3_0_HIGH_PRECISION_EVENT_TIMER_TABLE_SIGNATURE 0x54455048 + +// +// "MCFG" PCI Express Memory Mapped Configuration Space Base Address Description Table +// +#define EFI_ACPI_3_0_PCI_EXPRESS_MEMORY_MAPPED_CONFIGURATION_SPACE_BASE_ADDRESS_DESCRIPTION_TABLE_SIGNATURE 0x4746434D + +// +// "SPCR" Serial Port Concole Redirection Table +// +#define EFI_ACPI_3_0_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_SIGNATURE 0x52435053 + +// +// "SPMI" Server Platform Management Interface Table +// +#define EFI_ACPI_3_0_SERVER_PLATFORM_MANAGEMENT_INTERFACE_TABLE_SIGNATURE 0x494D5053 + +// +// "TCPA" Trusted Computing Platform Alliance Capabilities Table +// +#define EFI_ACPI_3_0_TRUSTED_COMPUTING_PLATFORM_ALLIANCE_CAPABILITIES_TABLE_SIGNATURE 0x41504354 + +// +// "WDRT" Watchdog Resource Table +// +#define EFI_ACPI_3_0_WATCHDOG_RESOURCE_TABLE_SIGNATURE 0x54524457 + +#pragma pack() + +#endif diff --git a/BaseTools/Source/C/Include/IndustryStandard/EfiPci.h b/BaseTools/Source/C/Include/IndustryStandard/EfiPci.h new file mode 100644 index 0000000000..24356b8b19 --- /dev/null +++ b/BaseTools/Source/C/Include/IndustryStandard/EfiPci.h @@ -0,0 +1,59 @@ +/** @file + Support for EFI PCI specification. + + Copyright (c) 2006 - 2008, 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. + + File Name: EfiPci.h + +**/ + +#ifndef _EFI_PCI_H_ +#define _EFI_PCI_H_ + +//#include "pci22.h" +//#include "pci23.h" +//#include "pci30.h" + +#pragma pack(push, 1) + +typedef struct { + UINT8 Register; + UINT8 Function; + UINT8 Device; + UINT8 Bus; + UINT8 Reserved[4]; +} DEFIO_PCI_ADDR; + +#define EFI_ROOT_BRIDGE_LIST 'eprb' +#define EFI_PCI_EXPANSION_ROM_HEADER_EFISIGNATURE 0x0EF1 + +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 union { + UINT8 *Raw; + PCI_EXPANSION_ROM_HEADER *Generic; + EFI_PCI_EXPANSION_ROM_HEADER *Efi; + EFI_LEGACY_EXPANSION_ROM_HEADER *PcAt; +} EFI_PCI_ROM_HEADER; + +#pragma pack(pop) + +#endif diff --git a/BaseTools/Source/C/Include/IndustryStandard/MemoryMappedConfigurationSpaceAccessTable.h b/BaseTools/Source/C/Include/IndustryStandard/MemoryMappedConfigurationSpaceAccessTable.h new file mode 100644 index 0000000000..69bd83e882 --- /dev/null +++ b/BaseTools/Source/C/Include/IndustryStandard/MemoryMappedConfigurationSpaceAccessTable.h @@ -0,0 +1,47 @@ +/** @file + ACPI memory mapped configuration space access table definition, defined at + in the PCI Firmware Specification, version 3.0 draft version 0.5. + Specification is available at http://www.pcisig.com. + + Copyright (c) 2006 - 2008, 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. + + File Name: MemoryMappedConfigurationSpaceAccessTable.h + +**/ + +#ifndef _MEMORY_MAPPED_CONFIGURATION_SPACE_ACCESS_TABLE_H_ +#define _MEMORY_MAPPED_CONFIGURATION_SPACE_ACCESS_TABLE_H_ + +// +// Ensure proper structure formats +// +#pragma pack(1) +// +// Memory Mapped Configuration Space Access Table (MCFG) +// This table is a basic description table header followed by +// a number of base address allocation structures. +// +typedef struct { + UINT64 BaseAddress; + UINT16 PciSegmentGroupNumber; + UINT8 StartBusNumber; + UINT8 EndBusNumber; + UINT32 Reserved; +} EFI_ACPI_MEMORY_MAPPED_ENHANCED_CONFIGURATION_SPACE_BASE_ADDRESS_ALLOCATION_STRUCTURE; + +// +// MCFG Revision (defined in spec) +// +#define EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_SPACE_ACCESS_TABLE_REVISION 0x01 + +#pragma pack() + +#endif diff --git a/BaseTools/Source/C/Include/IndustryStandard/PeImage.h b/BaseTools/Source/C/Include/IndustryStandard/PeImage.h new file mode 100644 index 0000000000..1595a987e1 --- /dev/null +++ b/BaseTools/Source/C/Include/IndustryStandard/PeImage.h @@ -0,0 +1,699 @@ +/** @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 - 2008, 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. + + File Name: PeImage.h + +**/ + +#ifndef __PE_IMAGE_H__ +#define __PE_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 +#define IMAGE_FILE_MACHINE_ARM 0x01c0 // Thumb only +#define IMAGE_FILE_MACHINE_ARMT 0x01c2 // 32bit Mixed ARM and Thumb/Thumb 2 Little Endian + +// +// 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_MACHINE_ARMT IMAGE_FILE_MACHINE_ARMT + +#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) + +// +// 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 09 // Direct 16-bit reference to the segment-selector bits of a 32-bit virtual address +#define EFI_IMAGE_REL_I386_SECTION 010 +#define EFI_IMAGE_REL_I386_SECREL 011 +#define EFI_IMAGE_REL_I386_REL32 020 // PC-relative 32-bit reference to the symbols virtual address + +// +// x64 processor relocation types. +// +#define IMAGE_REL_AMD64_ABSOLUTE 0x0000 +#define IMAGE_REL_AMD64_ADDR64 0x0001 +#define IMAGE_REL_AMD64_ADDR32 0x0002 +#define IMAGE_REL_AMD64_ADDR32NB 0x0003 +#define IMAGE_REL_AMD64_REL32 0x0004 +#define IMAGE_REL_AMD64_REL32_1 0x0005 +#define IMAGE_REL_AMD64_REL32_2 0x0006 +#define IMAGE_REL_AMD64_REL32_3 0x0007 +#define IMAGE_REL_AMD64_REL32_4 0x0008 +#define IMAGE_REL_AMD64_REL32_5 0x0009 +#define IMAGE_REL_AMD64_SECTION 0x000A +#define IMAGE_REL_AMD64_SECREL 0x000B +#define IMAGE_REL_AMD64_SECREL7 0x000C +#define IMAGE_REL_AMD64_TOKEN 0x000D +#define IMAGE_REL_AMD64_SREL32 0x000E +#define IMAGE_REL_AMD64_PAIR 0x000F +#define IMAGE_REL_AMD64_SSPAN32 0x0010 + +/// +/// 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 "!\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 + + +// +// Union of PE32, PE32+, and TE headers +// +typedef union { + EFI_IMAGE_NT_HEADERS32 Pe32; + EFI_IMAGE_NT_HEADERS64 Pe32Plus; + EFI_TE_IMAGE_HEADER Te; +} EFI_IMAGE_OPTIONAL_HEADER_UNION; + +typedef union { + EFI_IMAGE_NT_HEADERS32 *Pe32; + EFI_IMAGE_NT_HEADERS64 *Pe32Plus; + EFI_TE_IMAGE_HEADER *Te; + EFI_IMAGE_OPTIONAL_HEADER_UNION *Union; +} EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION; + +#endif diff --git a/BaseTools/Source/C/Include/IndustryStandard/pci22.h b/BaseTools/Source/C/Include/IndustryStandard/pci22.h new file mode 100644 index 0000000000..057b6d7494 --- /dev/null +++ b/BaseTools/Source/C/Include/IndustryStandard/pci22.h @@ -0,0 +1,544 @@ +/** @file + Support for PCI 2.2 standard. + + Copyright (c) 2006 - 2008, 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. + + File 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_SCC 0x07 // Simple communications controllers +#define PCI_SUBCLASS_SERIAL 0x00 +#define PCI_IF_GENERIC_XT 0x00 +#define PCI_IF_16450 0x01 +#define PCI_IF_16550 0x02 +#define PCI_IF_16650 0x03 +#define PCI_IF_16750 0x04 +#define PCI_IF_16850 0x05 +#define PCI_IF_16950 0x06 +#define PCI_SUBCLASS_PARALLEL 0x01 +#define PCI_IF_PARALLEL_PORT 0x00 +#define PCI_IF_BI_DIR_PARALLEL_PORT 0x01 +#define PCI_IF_ECP_PARALLEL_PORT 0x02 +#define PCI_IF_1284_CONTROLLER 0x03 +#define PCI_IF_1284_DEVICE 0xFE +#define PCI_SUBCLASS_MULTIPORT_SERIAL 0x02 +#define PCI_SUBCLASS_MODEM 0x03 +#define PCI_IF_GENERIC_MODEM 0x00 +#define PCI_IF_16450_MODEM 0x01 +#define PCI_IF_16550_MODEM 0x02 +#define PCI_IF_16650_MODEM 0x03 +#define PCI_IF_16750_MODEM 0x04 +#define PCI_SUBCLASS_OTHER 0x80 + +#define PCI_CLASS_SYSTEM_PERIPHERAL 0x08 +#define PCI_SUBCLASS_PIC 0x00 +#define PCI_IF_8259_PIC 0x00 +#define PCI_IF_ISA_PIC 0x01 +#define PCI_IF_EISA_PIC 0x02 +#define PCI_IF_APIC_CONTROLLER 0x10 // I/O APIC interrupt controller , 32 bye none-prefectable memory. +#define PCI_IF_APIC_CONTROLLER2 0x20 +#define PCI_SUBCLASS_TIMER 0x02 +#define PCI_IF_8254_TIMER 0x00 +#define PCI_IF_ISA_TIMER 0x01 +#define PCI_EISA_TIMER 0x02 +#define PCI_SUBCLASS_RTC 0x03 +#define PCI_IF_GENERIC_RTC 0x00 +#define PCI_IF_ISA_RTC 0x00 +#define PCI_SUBCLASS_PNP_CONTROLLER 0x04 // HotPlug Controller + +#define PCI_CLASS_INPUT_DEVICE 0x09 +#define PCI_SUBCLASS_KEYBOARD 0x00 +#define PCI_SUBCLASS_PEN 0x01 +#define PCI_SUBCLASS_MOUSE_CONTROLLER 0x02 +#define PCI_SUBCLASS_SCAN_CONTROLLER 0x03 +#define PCI_SUBCLASS_GAMEPORT 0x04 + +#define PCI_CLASS_DOCKING_STATION 0x0A + +#define PCI_CLASS_PROCESSOR 0x0B +#define PCI_SUBCLASS_PROC_386 0x00 +#define PCI_SUBCLASS_PROC_486 0x01 +#define PCI_SUBCLASS_PROC_PENTIUM 0x02 +#define PCI_SUBCLASS_PROC_ALPHA 0x10 +#define PCI_SUBCLASS_PROC_POWERPC 0x20 +#define PCI_SUBCLASS_PROC_MIPS 0x30 +#define PCI_SUBCLASS_PROC_CO_PORC 0x40 // Co-Processor + +#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 PCI_CLASS_WIRELESS 0x0D +#define PCI_SUBCLASS_IRDA 0x00 +#define PCI_SUBCLASS_IR 0x01 +#define PCI_SUBCLASS_RF 0x02 + +#define PCI_CLASS_INTELLIGENT_IO 0x0E + +#define PCI_CLASS_SATELLITE 0x0F +#define PCI_SUBCLASS_TV 0x01 +#define PCI_SUBCLASS_AUDIO 0x02 +#define PCI_SUBCLASS_VOICE 0x03 +#define PCI_SUBCLASS_DATA 0x04 + +#define PCI_SECURITY_CONTROLLER 0x10 // Encryption and decryption controller +#define PCI_SUBCLASS_NET_COMPUT 0x00 +#define PCI_SUBCLASS_ENTERTAINMENT 0x10 + +#define PCI_CLASS_DPIO 0x11 + +#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 0x0006 +#define PCI_MAX_CONFIG_OFFSET 0x0100 + +#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_BASE_ADDRESSREG_OFFSET 0x10 +#define PCI_CARDBUS_CIS_OFFSET 0x28 +#define PCI_SVID_OFFSET 0x2C // SubSystem Vendor id +#define PCI_SUBSYSTEM_VENDOR_ID_OFFSET 0x2C +#define PCI_SID_OFFSET 0x2E // SubSystem ID +#define PCI_SUBSYSTEM_ID_OFFSET 0x2E +#define PCI_EXPANSION_ROM_BASE 0x30 +#define PCI_CAPBILITY_POINTER_OFFSET 0x34 +#define PCI_INT_LINE_OFFSET 0x3C // Interrupt Line Register +#define PCI_INT_PIN_OFFSET 0x3D // Interrupt Pin Register +#define PCI_MAXGNT_OFFSET 0x3E // Max Grant Register +#define PCI_MAXLAT_OFFSET 0x3F // Max Latency Register + +#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 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 PCI_EXPANSION_ROM_HEADER_SIGNATURE 0xaa55 +#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 + UINT8 Size512; + UINT8 InitEntryPoint[3]; + UINT8 Reserved[0x12]; + UINT16 PcirOffset; +} EFI_LEGACY_EXPANSION_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 + +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) + +// +// NOTE: The following header files are included here for +// compatibility consideration. +// +#include "pci23.h" +#include "pci30.h" +#include "EfiPci.h" + +#endif diff --git a/BaseTools/Source/C/Include/IndustryStandard/pci23.h b/BaseTools/Source/C/Include/IndustryStandard/pci23.h new file mode 100644 index 0000000000..2cbf13d134 --- /dev/null +++ b/BaseTools/Source/C/Include/IndustryStandard/pci23.h @@ -0,0 +1,26 @@ +/** @file + Support for PCI 2.3 standard. + + Copyright (c) 2006 - 2008, 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. + + File Name: pci23.h + +**/ + +#ifndef _PCI23_H +#define _PCI23_H + +//#include "pci22.h" + +#define PCI_EXP_MAX_CONFIG_OFFSET 0x1000 +#define EFI_PCI_CAPABILITY_ID_PCIEXP 0x10 + +#endif diff --git a/BaseTools/Source/C/Include/IndustryStandard/pci30.h b/BaseTools/Source/C/Include/IndustryStandard/pci30.h new file mode 100644 index 0000000000..b2a9198dfb --- /dev/null +++ b/BaseTools/Source/C/Include/IndustryStandard/pci30.h @@ -0,0 +1,46 @@ +/** @file + Support for PCI 3.0 standard. + + Copyright (c) 2006 - 2008, 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. + + File Name: pci30.h + +**/ + +#ifndef _PCI30_H +#define _PCI30_H + +//#include "pci23.h" + +#define PCI_CLASS_MASS_STORAGE_SATADPA 0x06 + +#pragma pack(push, 1) + +typedef struct { + UINT32 Signature; // "PCIR" + UINT16 VendorId; + UINT16 DeviceId; + UINT16 DeviceListOffset; + UINT16 Length; + UINT8 Revision; + UINT8 ClassCode[3]; + UINT16 ImageLength; + UINT16 CodeRevision; + UINT8 CodeType; + UINT8 Indicator; + UINT16 MaxRuntimeImageLength; + UINT16 ConfigUtilityCodeHeaderOffset; + UINT16 DMTFCLPEntryPointOffset; +} PCI_3_0_DATA_STRUCTURE; + +#pragma pack(pop) + +#endif diff --git a/BaseTools/Source/C/Include/Protocol/DevicePath.h b/BaseTools/Source/C/Include/Protocol/DevicePath.h new file mode 100644 index 0000000000..1fdffe419f --- /dev/null +++ b/BaseTools/Source/C/Include/Protocol/DevicePath.h @@ -0,0 +1,548 @@ +/** @file + The device path protocol as defined in UEFI 2.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 - 2008, 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. + + File Name: DevicePath.h + +**/ + +#ifndef __EFI_DEVICE_PATH_PROTOCOL_H__ +#define __EFI_DEVICE_PATH_PROTOCOL_H__ + +#include + +// +// Device Path protocol +// +#define EFI_DEVICE_PATH_PROTOCOL_GUID \ + { \ + 0x9576e91, 0x6d3f, 0x11d2, {0x8e, 0x39, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b } \ + } + +// +// Protocol GUID defined in EFI1.1. +// + +// +// Device Path information +// +#define DEVICE_PATH_PROTOCOL EFI_DEVICE_PATH_PROTOCOL_GUID + +#pragma pack(1) + +typedef struct { + UINT8 Type; + UINT8 SubType; + UINT8 Length[2]; +} EFI_DEVICE_PATH_PROTOCOL; + +// +// For backward-compatible with EFI1.1. +// +typedef EFI_DEVICE_PATH_PROTOCOL EFI_DEVICE_PATH; + +// +// Hardware Device Paths +// +#define HARDWARE_DEVICE_PATH 0x01 + +#define HW_PCI_DP 0x01 +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + UINT8 Function; + UINT8 Device; +} PCI_DEVICE_PATH; + +#define HW_PCCARD_DP 0x02 +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + UINT8 FunctionNumber; +} PCCARD_DEVICE_PATH; + +#define HW_MEMMAP_DP 0x03 +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + UINT32 MemoryType; + EFI_PHYSICAL_ADDRESS StartingAddress; + EFI_PHYSICAL_ADDRESS EndingAddress; +} MEMMAP_DEVICE_PATH; + +#define HW_VENDOR_DP 0x04 +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + EFI_GUID Guid; +} VENDOR_DEVICE_PATH; + +#define HW_CONTROLLER_DP 0x05 +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + UINT32 ControllerNumber; +} CONTROLLER_DEVICE_PATH; + +// +// ACPI Device Paths +// +#define ACPI_DEVICE_PATH 0x02 + +#define ACPI_DP 0x01 +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + UINT32 HID; + UINT32 UID; +} ACPI_HID_DEVICE_PATH; + +#define ACPI_EXTENDED_DP 0x02 +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + UINT32 HID; + UINT32 UID; + UINT32 CID; + // + // Optional variable length _HIDSTR + // Optional variable length _UIDSTR + // +} ACPI_EXTENDED_HID_DEVICE_PATH; + +// +// EISA ID Macro +// EISA ID Definition 32-bits +// bits[15:0] - three character compressed ASCII EISA ID. +// bits[31:16] - binary number +// Compressed ASCII is 5 bits per character 0b00001 = 'A' 0b11010 = 'Z' +// +#define PNP_EISA_ID_CONST 0x41d0 +#define EISA_ID(_Name, _Num) ((UINT32) ((_Name) | (_Num) << 16)) +#define EISA_PNP_ID(_PNPId) (EISA_ID(PNP_EISA_ID_CONST, (_PNPId))) +#define EFI_PNP_ID(_PNPId) (EISA_ID(PNP_EISA_ID_CONST, (_PNPId))) + +#define PNP_EISA_ID_MASK 0xffff +#define EISA_ID_TO_NUM(_Id) ((_Id) >> 16) + + +#define ACPI_ADR_DP 0x03 +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + UINT32 ADR; +} ACPI_ADR_DEVICE_PATH; + + +// +// Messaging Device Paths +// +#define MESSAGING_DEVICE_PATH 0x03 + +#define MSG_ATAPI_DP 0x01 +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + UINT8 PrimarySecondary; + UINT8 SlaveMaster; + UINT16 Lun; +} ATAPI_DEVICE_PATH; + +#define MSG_SCSI_DP 0x02 +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + UINT16 Pun; + UINT16 Lun; +} SCSI_DEVICE_PATH; + +#define MSG_FIBRECHANNEL_DP 0x03 +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + UINT32 Reserved; + UINT64 WWN; + UINT64 Lun; +} FIBRECHANNEL_DEVICE_PATH; + +#define MSG_1394_DP 0x04 +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + UINT32 Reserved; + UINT64 Guid; +} F1394_DEVICE_PATH; + +#define MSG_USB_DP 0x05 +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + UINT8 ParentPortNumber; + UINT8 InterfaceNumber; +} USB_DEVICE_PATH; + +#define MSG_USB_CLASS_DP 0x0f +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + UINT16 VendorId; + UINT16 ProductId; + UINT8 DeviceClass; + UINT8 DeviceSubClass; + UINT8 DeviceProtocol; +} USB_CLASS_DEVICE_PATH; + +#define MSG_USB_WWID_DP 0x10 +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + UINT16 InterfaceNumber; + UINT16 VendorId; + UINT16 ProductId; + // CHAR16 SerialNumber[...]; +} USB_WWID_DEVICE_PATH; + + +#define MSG_DEVICE_LOGICAL_UNIT_DP 0x11 +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + UINT8 Lun; +} DEVICE_LOGICAL_UNIT_DEVICE_PATH; + +#define MSG_SATA_DP 0x12 +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + UINT16 HBAPortNumber; + UINT16 PortMultiplierPortNumber; + UINT16 Lun; +} SATA_DEVICE_PATH; + +#define MSG_I2O_DP 0x06 +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + UINT32 Tid; +} I2O_DEVICE_PATH; + +#define MSG_MAC_ADDR_DP 0x0b +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + EFI_MAC_ADDRESS MacAddress; + UINT8 IfType; +} MAC_ADDR_DEVICE_PATH; + +#define MSG_IPv4_DP 0x0c +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + EFI_IPv4_ADDRESS LocalIpAddress; + EFI_IPv4_ADDRESS RemoteIpAddress; + UINT16 LocalPort; + UINT16 RemotePort; + UINT16 Protocol; + BOOLEAN StaticIpAddress; +} IPv4_DEVICE_PATH; + +#define MSG_IPv6_DP 0x0d +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + EFI_IPv6_ADDRESS LocalIpAddress; + EFI_IPv6_ADDRESS RemoteIpAddress; + UINT16 LocalPort; + UINT16 RemotePort; + UINT16 Protocol; + BOOLEAN StaticIpAddress; +} IPv6_DEVICE_PATH; + +#define MSG_INFINIBAND_DP 0x09 +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + UINT32 ResourceFlags; + UINT8 PortGid[16]; + UINT64 ServiceId; + UINT64 TargetPortId; + UINT64 DeviceId; +} INFINIBAND_DEVICE_PATH; + +#define INFINIBAND_RESOURCE_FLAG_IOC_SERVICE 0x01 +#define INFINIBAND_RESOURCE_FLAG_EXTENDED_BOOT_ENVIRONMENT 0x02 +#define INFINIBAND_RESOURCE_FLAG_CONSOLE_PROTOCOL 0x04 +#define INFINIBAND_RESOURCE_FLAG_STORAGE_PROTOCOL 0x08 +#define INFINIBAND_RESOURCE_FLAG_NETWORK_PROTOCOL 0x10 + +#define MSG_UART_DP 0x0e +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + UINT32 Reserved; + UINT64 BaudRate; + UINT8 DataBits; + UINT8 Parity; + UINT8 StopBits; +} UART_DEVICE_PATH; + +// +// Use VENDOR_DEVICE_PATH struct +// +#define MSG_VENDOR_DP 0x0a +typedef VENDOR_DEVICE_PATH VENDOR_DEFINED_DEVICE_PATH; + +#define DEVICE_PATH_MESSAGING_PC_ANSI EFI_PC_ANSI_GUID +#define DEVICE_PATH_MESSAGING_VT_100 EFI_VT_100_GUID +#define DEVICE_PATH_MESSAGING_VT_100_PLUS EFI_VT_100_PLUS_GUID +#define DEVICE_PATH_MESSAGING_VT_UTF8 EFI_VT_UTF8_GUID + +#define DEVICE_PATH_MESSAGING_UART_FLOW_CONTROL EFI_UART_DEVICE_PATH_GUID + +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + EFI_GUID Guid; + UINT32 FlowControlMap; +} UART_FLOW_CONTROL_DEVICE_PATH; + +#define DEVICE_PATH_MESSAGING_SAS EFI_SAS_DEVICE_PATH_GUID + +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + EFI_GUID Guid; + UINT32 Reserved; + UINT64 SasAddress; + UINT64 Lun; + UINT16 DeviceTopology; + UINT16 RelativeTargetPort; +} SAS_DEVICE_PATH; + +#define MSG_ISCSI_DP 0x13 +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + UINT16 NetworkProtocol; + UINT16 LoginOption; + UINT64 Lun; + UINT16 TargetPortalGroupTag; + // CHAR8 iSCSI Target Name +} ISCSI_DEVICE_PATH; + +#define ISCSI_LOGIN_OPTION_NO_HEADER_DIGEST 0x0000 +#define ISCSI_LOGIN_OPTION_HEADER_DIGEST_USING_CRC32C 0x0002 +#define ISCSI_LOGIN_OPTION_NO_DATA_DIGEST 0x0000 +#define ISCSI_LOGIN_OPTION_DATA_DIGEST_USING_CRC32C 0x0008 +#define ISCSI_LOGIN_OPTION_AUTHMETHOD_CHAP 0x0000 +#define ISCSI_LOGIN_OPTION_AUTHMETHOD_NON 0x1000 +#define ISCSI_LOGIN_OPTION_CHAP_BI 0x0000 +#define ISCSI_LOGIN_OPTION_CHAP_UNI 0x2000 + +// +// Media Device Path +// +#define MEDIA_DEVICE_PATH 0x04 + +#define MEDIA_HARDDRIVE_DP 0x01 +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + UINT32 PartitionNumber; + UINT64 PartitionStart; + UINT64 PartitionSize; + UINT8 Signature[16]; + UINT8 MBRType; + UINT8 SignatureType; +} HARDDRIVE_DEVICE_PATH; + +#define MBR_TYPE_PCAT 0x01 +#define MBR_TYPE_EFI_PARTITION_TABLE_HEADER 0x02 + +#define SIGNATURE_TYPE_MBR 0x01 +#define SIGNATURE_TYPE_GUID 0x02 + +#define MEDIA_CDROM_DP 0x02 +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + UINT32 BootEntry; + UINT64 PartitionStart; + UINT64 PartitionSize; +} CDROM_DEVICE_PATH; + +// +// Use VENDOR_DEVICE_PATH struct +// +#define MEDIA_VENDOR_DP 0x03 + +#define MEDIA_FILEPATH_DP 0x04 +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + CHAR16 PathName[1]; +} FILEPATH_DEVICE_PATH; + +#define SIZE_OF_FILEPATH_DEVICE_PATH EFI_FIELD_OFFSET(FILEPATH_DEVICE_PATH,PathName) + +#define MEDIA_PROTOCOL_DP 0x05 +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + EFI_GUID Protocol; +} MEDIA_PROTOCOL_DEVICE_PATH; + + +#define MEDIA_PIWG_FW_VOL_DP 0x7 +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + EFI_GUID FvName; +} MEDIA_FW_VOL_DEVICE_PATH; + + +#define MEDIA_PIWG_FW_FILE_DP 0x6 +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + EFI_GUID FvFileName; +} MEDIA_FW_VOL_FILEPATH_DEVICE_PATH; + +// +// BBS Device Path +// +#define BBS_DEVICE_PATH 0x05 +#define BBS_BBS_DP 0x01 +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + UINT16 DeviceType; + UINT16 StatusFlag; + CHAR8 String[1]; +} BBS_BBS_DEVICE_PATH; + +// +// DeviceType definitions - from BBS specification +// +#define BBS_TYPE_FLOPPY 0x01 +#define BBS_TYPE_HARDDRIVE 0x02 +#define BBS_TYPE_CDROM 0x03 +#define BBS_TYPE_PCMCIA 0x04 +#define BBS_TYPE_USB 0x05 +#define BBS_TYPE_EMBEDDED_NETWORK 0x06 +#define BBS_TYPE_BEV 0x80 +#define BBS_TYPE_UNKNOWN 0xFF + + +// +// Union of all possible Device Paths and pointers to Device Paths +// + +typedef union { + EFI_DEVICE_PATH_PROTOCOL DevPath; + PCI_DEVICE_PATH Pci; + PCCARD_DEVICE_PATH PcCard; + MEMMAP_DEVICE_PATH MemMap; + VENDOR_DEVICE_PATH Vendor; + + CONTROLLER_DEVICE_PATH Controller; + ACPI_HID_DEVICE_PATH Acpi; + + ATAPI_DEVICE_PATH Atapi; + SCSI_DEVICE_PATH Scsi; + ISCSI_DEVICE_PATH Iscsi; + FIBRECHANNEL_DEVICE_PATH FibreChannel; + + F1394_DEVICE_PATH F1394; + USB_DEVICE_PATH Usb; + SATA_DEVICE_PATH Sata; + USB_CLASS_DEVICE_PATH UsbClass; + I2O_DEVICE_PATH I2O; + MAC_ADDR_DEVICE_PATH MacAddr; + IPv4_DEVICE_PATH Ipv4; + IPv6_DEVICE_PATH Ipv6; + INFINIBAND_DEVICE_PATH InfiniBand; + UART_DEVICE_PATH Uart; + + HARDDRIVE_DEVICE_PATH HardDrive; + CDROM_DEVICE_PATH CD; + + FILEPATH_DEVICE_PATH FilePath; + MEDIA_PROTOCOL_DEVICE_PATH MediaProtocol; + + BBS_BBS_DEVICE_PATH Bbs; +} EFI_DEV_PATH; + + + +typedef union { + EFI_DEVICE_PATH_PROTOCOL *DevPath; + PCI_DEVICE_PATH *Pci; + PCCARD_DEVICE_PATH *PcCard; + MEMMAP_DEVICE_PATH *MemMap; + VENDOR_DEVICE_PATH *Vendor; + + CONTROLLER_DEVICE_PATH *Controller; + ACPI_HID_DEVICE_PATH *Acpi; + ACPI_EXTENDED_HID_DEVICE_PATH *ExtendedAcpi; + + ATAPI_DEVICE_PATH *Atapi; + SCSI_DEVICE_PATH *Scsi; + FIBRECHANNEL_DEVICE_PATH *FibreChannel; + + F1394_DEVICE_PATH *F1394; + USB_DEVICE_PATH *Usb; + SATA_DEVICE_PATH *Sata; + USB_CLASS_DEVICE_PATH *UsbClass; + I2O_DEVICE_PATH *I2O; + MAC_ADDR_DEVICE_PATH *MacAddr; + IPv4_DEVICE_PATH *Ipv4; + IPv6_DEVICE_PATH *Ipv6; + INFINIBAND_DEVICE_PATH *InfiniBand; + UART_DEVICE_PATH *Uart; + + HARDDRIVE_DEVICE_PATH *HardDrive; + CDROM_DEVICE_PATH *CD; + + FILEPATH_DEVICE_PATH *FilePath; + MEDIA_PROTOCOL_DEVICE_PATH *MediaProtocol; + + BBS_BBS_DEVICE_PATH *Bbs; + UINT8 *Raw; +} EFI_DEV_PATH_PTR; + +#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/BaseTools/Source/C/Include/Protocol/GraphicsOutput.h b/BaseTools/Source/C/Include/Protocol/GraphicsOutput.h new file mode 100644 index 0000000000..35cf7a14a5 --- /dev/null +++ b/BaseTools/Source/C/Include/Protocol/GraphicsOutput.h @@ -0,0 +1,195 @@ +/** @file + Graphics Output Protocol from the UEFI 2.0 specification. + + Abstraction of a very simple graphics device. + + Copyright (c) 2006 - 2008, 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. + + File Name: GraphicsOutput.h + +**/ + +#ifndef __GRAPHICS_OUTPUT_H__ +#define __GRAPHICS_OUTPUT_H__ + +#define EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID \ + { \ + 0x9042a9de, 0x23dc, 0x4a38, {0x96, 0xfb, 0x7a, 0xde, 0xd0, 0x80, 0x51, 0x6a } \ + } + +typedef struct _EFI_GRAPHICS_OUTPUT_PROTOCOL EFI_GRAPHICS_OUTPUT_PROTOCOL; + +typedef struct { + UINT32 RedMask; + UINT32 GreenMask; + UINT32 BlueMask; + UINT32 ReservedMask; +} EFI_PIXEL_BITMASK; + +typedef enum { + PixelRedGreenBlueReserved8BitPerColor, + PixelBlueGreenRedReserved8BitPerColor, + PixelBitMask, + PixelBltOnly, + PixelFormatMax +} EFI_GRAPHICS_PIXEL_FORMAT; + +typedef struct { + UINT32 Version; + UINT32 HorizontalResolution; + UINT32 VerticalResolution; + EFI_GRAPHICS_PIXEL_FORMAT PixelFormat; + EFI_PIXEL_BITMASK PixelInformation; + UINT32 PixelsPerScanLine; +} EFI_GRAPHICS_OUTPUT_MODE_INFORMATION; + +/** + Return the current video mode information. + + @param This Protocol instance pointer. + @param ModeNumber The mode number to return information on. + @param SizeOfInfo A pointer to the size, in bytes, of the Info buffer. + @param Info A pointer to callee allocated buffer that returns information about ModeNumber. + + @retval EFI_SUCCESS Mode information returned. + @retval EFI_BUFFER_TOO_SMALL The Info buffer was too small. + @retval EFI_DEVICE_ERROR A hardware error occurred trying to retrieve the video mode. + @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_GRAPHICS_OUTPUT_PROTOCOL_QUERY_MODE) ( + IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This, + IN UINT32 ModeNumber, + OUT UINTN *SizeOfInfo, + OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION **Info + ) +; + +/** + Return the current video mode information. + + @param This Protocol instance pointer. + @param ModeNumber The mode number to be set. + + @retval EFI_SUCCESS Graphics mode was changed. + @retval EFI_DEVICE_ERROR The device had an error and could not complete the request. + @retval EFI_UNSUPPORTED ModeNumber is not supported by this device. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_GRAPHICS_OUTPUT_PROTOCOL_SET_MODE) ( + IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This, + IN UINT32 ModeNumber + ) +; + +typedef struct { + UINT8 Blue; + UINT8 Green; + UINT8 Red; + UINT8 Reserved; +} EFI_GRAPHICS_OUTPUT_BLT_PIXEL; + +typedef union { + EFI_GRAPHICS_OUTPUT_BLT_PIXEL Pixel; + UINT32 Raw; +} EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION; + +typedef enum { + EfiBltVideoFill, + EfiBltVideoToBltBuffer, + EfiBltBufferToVideo, + EfiBltVideoToVideo, + EfiGraphicsOutputBltOperationMax +} EFI_GRAPHICS_OUTPUT_BLT_OPERATION; + +/** + The following table defines actions for BltOperations: + + EfiBltVideoFill - 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. + + EfiBltVideoToBltBuffer - 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. + + EfiBltBufferToVideo - 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. + + EfiBltVideoToVideo - 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 This Protocol instance pointer. + @param BltBuffer Buffer containing data to blit into video buffer. This + buffer has a size of Width*Height*sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL) + @param BltOperation Operation to perform on BlitBuffer and video memory + @param SourceX X coordinate of source for the BltBuffer. + @param SourceY Y coordinate of source for the BltBuffer. + @param DestinationX X coordinate of destination for the BltBuffer. + @param DestinationY Y coordinate of destination for the BltBuffer. + @param Width Width of rectangle in BltBuffer in pixels. + @param Height Hight of rectangle in BltBuffer in pixels. + @param 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_GRAPHICS_OUTPUT_PROTOCOL_BLT) ( + IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This, + IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, OPTIONAL + IN EFI_GRAPHICS_OUTPUT_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 + ); + +typedef struct { + UINT32 MaxMode; + UINT32 Mode; + EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info; + UINTN SizeOfInfo; + EFI_PHYSICAL_ADDRESS FrameBufferBase; + UINTN FrameBufferSize; +} EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE; + +struct _EFI_GRAPHICS_OUTPUT_PROTOCOL { + EFI_GRAPHICS_OUTPUT_PROTOCOL_QUERY_MODE QueryMode; + EFI_GRAPHICS_OUTPUT_PROTOCOL_SET_MODE SetMode; + EFI_GRAPHICS_OUTPUT_PROTOCOL_BLT Blt; + EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE *Mode; +}; + +extern EFI_GUID gEfiGraphicsOutputProtocolGuid; + +#endif diff --git a/BaseTools/Source/C/Include/Protocol/GuidedSectionExtraction.h b/BaseTools/Source/C/Include/Protocol/GuidedSectionExtraction.h new file mode 100644 index 0000000000..3b5dadadfa --- /dev/null +++ b/BaseTools/Source/C/Include/Protocol/GuidedSectionExtraction.h @@ -0,0 +1,153 @@ +/** @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 - 2008, 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. + + File Name: EfiGuidedSectionExtraction.h + + @par Revision Reference: PI + Version 1.00. + +**/ + +#ifndef __EFI_GUIDED_SECTION_EXTRACTION_PROTOCOL_H__ +#define __EFI_GUIDED_SECTION_EXTRACTION_PROTOCOL_H__ + +// +// Forward reference for pure ANSI compatability + +typedef struct _EFI_GUIDED_SECTION_EXTRACTION_PROTOCOL EFI_GUIDED_SECTION_EXTRACTION_PROTOCOL; + + +/** + The ExtractSection() function processes the input section and + allocates a buffer from the pool in which it returns the section + contents. If the section being extracted contains + authentication information (the section's + GuidedSectionHeader.Attributes field has the + EFI_GUIDED_SECTION_AUTH_STATUS_VALID bit set), the values + returned in AuthenticationStatus must reflect the results of + the authentication operation. Depending on the algorithm and + size of the encapsulated data, the time that is required to do + a full authentication may be prohibitively long for some + classes of systems. To indicate this, use + EFI_SECURITY_POLICY_PROTOCOL_GUID, which may be published by + the security policy driver (see the Platform Initialization + Driver Execution Environment Core Interface Specification for + more details and the GUID definition). If the + EFI_SECURITY_POLICY_PROTOCOL_GUID exists in the handle + database, then, if possible, full authentication should be + skipped and the section contents simply returned in the + OutputBuffer. In this case, the + EFI_AUTH_STATUS_PLATFORM_OVERRIDE bit AuthenticationStatus + must be set on return. ExtractSection() is callable only from + TPL_NOTIFY and below. Behavior of ExtractSection() at any + EFI_TPL above TPL_NOTIFY is undefined. Type EFI_TPL is + defined in RaiseTPL() in the UEFI 2.0 specification. + + + @param This Indicates the + EFI_GUIDED_SECTION_EXTRACTION_PROTOCOL instance. + + @param InputSection Buffer containing the input GUIDed section + to be processed. OutputBuffer OutputBuffer + is allocated from boot services pool + memory and contains the new section + stream. The caller is responsible for + freeing this buffer. + + @param OutputSize A pointer to a caller-allocated UINTN in + which the size of OutputBuffer allocation + is stored. If the function returns + anything other than EFI_SUCCESS, the value + of OutputSize is undefined. + + @param AuthenticationStatus A pointer to a caller-allocated + UINT32 that indicates the + authentication status of the + output buffer. If the input + section's + GuidedSectionHeader.Attributes + field has the + EFI_GUIDED_SECTION_AUTH_STATUS_VAL + bit as clear, AuthenticationStatus + must return zero. Both local bits + (19:16) and aggregate bits (3:0) + in AuthenticationStatus are + returned by ExtractSection(). + These bits reflect the status of + the extraction operation. The bit + pattern in both regions must be + the same, as the local and + aggregate authentication statuses + have equivalent meaning at this + level. If the function returns + anything other than EFI_SUCCESS, + the value of AuthenticationStatus + is undefined. + + + @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 CONST EFI_GUIDED_SECTION_EXTRACTION_PROTOCOL *This, + IN CONST VOID *InputSection, + OUT VOID **OutputBuffer, + OUT UINTN *OutputSize, + OUT UINT32 *AuthenticationStatus +); + + +/** + + Takes the GUIDed section as input and produces the section + stream data. See the ExtractSection() function description. + +**/ +struct _EFI_GUIDED_SECTION_EXTRACTION_PROTOCOL { + EFI_EXTRACT_GUIDED_SECTION ExtractSection; +}; + +// +// 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 } \ + } + +// +// may add other GUID here +// +extern EFI_GUID gEfiCrc32GuidedSectionExtractionProtocolGuid; + +#endif diff --git a/BaseTools/Source/C/Include/Protocol/HiiFramework.h b/BaseTools/Source/C/Include/Protocol/HiiFramework.h new file mode 100644 index 0000000000..49a60b2afe --- /dev/null +++ b/BaseTools/Source/C/Include/Protocol/HiiFramework.h @@ -0,0 +1,952 @@ +/** @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) 2007, 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. + + File Name: HiiFramework.h + + @par Revision Reference: + This protocol is defined in HII spec 0.92. + +**/ + +#ifndef _FRAMEWORK_HII_H_ +#define _FRAMEWORK_HII_H_ + +//#include + +// +// To get EFI_GRAPHICS_OUTPUT_BLT_PIXEL, +// is defined in MdePkg/Protocol/GraphicsOutput.h +// +#include + +#define EFI_HII_PROTOCOL_GUID \ + { \ + 0xd7ad636e, 0xb997, 0x459b, {0xbf, 0x3f, 0x88, 0x46, 0x89, 0x79, 0x80, 0xe1} \ + } + +// 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: +// EFI_FROM_ID has been defined in UEFI spec. +// +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_GRAPHICS_OUTPUT_BLT_PIXEL Foreground, + IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background, + IN UINTN Count, + IN UINTN Width, + IN UINTN Height, + IN OUT EFI_GRAPHICS_OUTPUT_BLT_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 with and by removing special characters such + as the 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/BaseTools/Source/C/Include/Protocol/UgaDraw.h b/BaseTools/Source/C/Include/Protocol/UgaDraw.h new file mode 100644 index 0000000000..35de25c163 --- /dev/null +++ b/BaseTools/Source/C/Include/Protocol/UgaDraw.h @@ -0,0 +1,169 @@ +/** @file + UGA Draw protocol from the EFI 1.1 specification. + + Abstraction of a very simple graphics device. + + Copyright (c) 2006 - 2008, 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. + + File 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: + + EfiUgaVideoFill - 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. + + EfiUgaVideoToBltBuffer - 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. + + EfiUgaBltBufferToVideo - 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. + + EfiUgaVideoToVideo - 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/BaseTools/Source/C/Include/X64/ProcessorBind.h b/BaseTools/Source/C/Include/X64/ProcessorBind.h new file mode 100644 index 0000000000..5b2ad46637 --- /dev/null +++ b/BaseTools/Source/C/Include/X64/ProcessorBind.h @@ -0,0 +1,194 @@ +/** @file + Processor or Compiler specific defines and types x64 (Intel(r) EM64T, AMD64). + + Copyright (c) 2006 - 2008, 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. + + File 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 !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 + #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 + 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/BaseTools/Source/C/LzmaCompress/GNUmakefile b/BaseTools/Source/C/LzmaCompress/GNUmakefile new file mode 100644 index 0000000000..de38ea1047 --- /dev/null +++ b/BaseTools/Source/C/LzmaCompress/GNUmakefile @@ -0,0 +1,18 @@ +ARCH ?= IA32 +MAKEROOT ?= .. + +APPNAME = LzmaCompress + +SDK_C = Sdk/C + +OBJECTS = \ + LzmaCompress.o \ + $(SDK_C)/Alloc.o \ + $(SDK_C)/LzFind.o \ + $(SDK_C)/LzmaDec.o \ + $(SDK_C)/LzmaEnc.o \ + $(SDK_C)/7zFile.o \ + $(SDK_C)/7zStream.o + +include $(MAKEROOT)/Makefiles/app.makefile + diff --git a/BaseTools/Source/C/LzmaCompress/LZMA-SDK-README.txt b/BaseTools/Source/C/LzmaCompress/LZMA-SDK-README.txt new file mode 100644 index 0000000000..e0476ad994 --- /dev/null +++ b/BaseTools/Source/C/LzmaCompress/LZMA-SDK-README.txt @@ -0,0 +1,3 @@ +LzmaCompress is based on the LZMA SDK 4.65. LZMA SDK 4.65 +was placed in the public domain on 2009-02-03. It was +released on the http://www.7-zip.org/sdk.html website. \ No newline at end of file diff --git a/BaseTools/Source/C/LzmaCompress/LzmaCompress.c b/BaseTools/Source/C/LzmaCompress/LzmaCompress.c new file mode 100644 index 0000000000..7207a752a1 --- /dev/null +++ b/BaseTools/Source/C/LzmaCompress/LzmaCompress.c @@ -0,0 +1,337 @@ +/** @file + LZMA Compress/Decompress tool (LzmaCompress) + + Based on LZMA SDK 4.65: + LzmaUtil.c -- Test application for LZMA compression + 2008-11-23 : Igor Pavlov : Public domain + + Copyright (c) 2006 - 2009, 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. + +**/ + +#define _CRT_SECURE_NO_WARNINGS + +#include +#include +#include + +#include "Sdk/C/Alloc.h" +#include "Sdk/C/7zFile.h" +#include "Sdk/C/7zVersion.h" +#include "Sdk/C/LzmaDec.h" +#include "Sdk/C/LzmaEnc.h" + +const char *kCantReadMessage = "Can not read input file"; +const char *kCantWriteMessage = "Can not write output file"; +const char *kCantAllocateMessage = "Can not allocate memory"; +const char *kDataErrorMessage = "Data error"; + +static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); } +static void SzFree(void *p, void *address) { p = p; MyFree(address); } +static ISzAlloc g_Alloc = { SzAlloc, SzFree }; + +static Bool mQuietMode = False; + +#define UTILITY_NAME "LzmaCompress" +#define UTILITY_MAJOR_VERSION 0 +#define UTILITY_MINOR_VERSION 1 +#define INTEL_COPYRIGHT \ + "Copyright (c) 2009, Intel Corporation. All rights reserved." +void PrintHelp(char *buffer) +{ + strcat(buffer, + "\n" UTILITY_NAME " - " INTEL_COPYRIGHT "\n" + "Based on LZMA Utility " MY_VERSION_COPYRIGHT_DATE "\n" + "\nUsage: LzmaCompress -e|-d [options] \n" + " -e: encode file\n" + " -d: decode file\n" + " -o FileName, --output FileName: specify the output filename\n" + " -v, --verbose: increase output messages\n" + " -q, --quiet: reduce output messages\n" + " --debug [0-9]: set debug level\n" + " --version: display the program version and exit\n" + " -h, --help: display this help text\n" + ); +} + +int PrintError(char *buffer, const char *message) +{ + strcat(buffer, "\nError: "); + strcat(buffer, message); + strcat(buffer, "\n"); + return 1; +} + +int PrintErrorNumber(char *buffer, SRes val) +{ + sprintf(buffer + strlen(buffer), "\nError code: %x\n", (unsigned)val); + return 1; +} + +int PrintUserError(char *buffer) +{ + return PrintError(buffer, "Incorrect command"); +} + +void PrintVersion(char *buffer) +{ + sprintf (buffer, "%s Version %d.%d", UTILITY_NAME, UTILITY_MAJOR_VERSION, UTILITY_MINOR_VERSION); +} + +#define IN_BUF_SIZE (1 << 16) +#define OUT_BUF_SIZE (1 << 16) + +static SRes Decode2(CLzmaDec *state, ISeqOutStream *outStream, ISeqInStream *inStream, + UInt64 unpackSize) +{ + int thereIsSize = (unpackSize != (UInt64)(Int64)-1); + Byte inBuf[IN_BUF_SIZE]; + Byte outBuf[OUT_BUF_SIZE]; + size_t inPos = 0, inSize = 0, outPos = 0; + LzmaDec_Init(state); + for (;;) + { + if (inPos == inSize) + { + inSize = IN_BUF_SIZE; + RINOK(inStream->Read(inStream, inBuf, &inSize)); + inPos = 0; + } + { + SRes res; + SizeT inProcessed = inSize - inPos; + SizeT outProcessed = OUT_BUF_SIZE - outPos; + ELzmaFinishMode finishMode = LZMA_FINISH_ANY; + ELzmaStatus status; + if (thereIsSize && outProcessed > unpackSize) + { + outProcessed = (SizeT)unpackSize; + finishMode = LZMA_FINISH_END; + } + + res = LzmaDec_DecodeToBuf(state, outBuf + outPos, &outProcessed, + inBuf + inPos, &inProcessed, finishMode, &status); + inPos += inProcessed; + outPos += outProcessed; + unpackSize -= outProcessed; + + if (outStream) + if (outStream->Write(outStream, outBuf, outPos) != outPos) + return SZ_ERROR_WRITE; + + outPos = 0; + + if (res != SZ_OK || (thereIsSize && unpackSize == 0)) + return res; + + if (inProcessed == 0 && outProcessed == 0) + { + if (thereIsSize || status != LZMA_STATUS_FINISHED_WITH_MARK) + return SZ_ERROR_DATA; + return res; + } + } + } +} + +static SRes Decode(ISeqOutStream *outStream, ISeqInStream *inStream) +{ + UInt64 unpackSize; + int i; + SRes res = 0; + + CLzmaDec state; + + /* header: 5 bytes of LZMA properties and 8 bytes of uncompressed size */ + unsigned char header[LZMA_PROPS_SIZE + 8]; + + /* Read and parse header */ + + RINOK(SeqInStream_Read(inStream, header, sizeof(header))); + + unpackSize = 0; + for (i = 0; i < 8; i++) + unpackSize += (UInt64)header[LZMA_PROPS_SIZE + i] << (i * 8); + + LzmaDec_Construct(&state); + RINOK(LzmaDec_Allocate(&state, header, LZMA_PROPS_SIZE, &g_Alloc)); + res = Decode2(&state, outStream, inStream, unpackSize); + LzmaDec_Free(&state, &g_Alloc); + return res; +} + +static SRes Encode(ISeqOutStream *outStream, ISeqInStream *inStream, UInt64 fileSize, char *rs) +{ + CLzmaEncHandle enc; + SRes res; + CLzmaEncProps props; + + rs = rs; + + enc = LzmaEnc_Create(&g_Alloc); + if (enc == 0) + return SZ_ERROR_MEM; + + LzmaEncProps_Init(&props); + res = LzmaEnc_SetProps(enc, &props); + + if (res == SZ_OK) + { + Byte header[LZMA_PROPS_SIZE + 8]; + size_t headerSize = LZMA_PROPS_SIZE; + int i; + + res = LzmaEnc_WriteProperties(enc, header, &headerSize); + for (i = 0; i < 8; i++) + header[headerSize++] = (Byte)(fileSize >> (8 * i)); + if (outStream->Write(outStream, header, headerSize) != headerSize) + res = SZ_ERROR_WRITE; + else + { + if (res == SZ_OK) + res = LzmaEnc_Encode(enc, outStream, inStream, NULL, &g_Alloc, &g_Alloc); + } + } + LzmaEnc_Destroy(enc, &g_Alloc, &g_Alloc); + return res; +} + +int main2(int numArgs, const char *args[], char *rs) +{ + CFileSeqInStream inStream; + CFileOutStream outStream; + int res; + int encodeMode; + Bool modeWasSet = False; + const char *inputFile = NULL; + const char *outputFile = "file.tmp"; + int param; + + FileSeqInStream_CreateVTable(&inStream); + File_Construct(&inStream.file); + + FileOutStream_CreateVTable(&outStream); + File_Construct(&outStream.file); + + if (numArgs == 1) + { + PrintHelp(rs); + return 0; + } + + for (param = 1; param < numArgs; param++) { + if (strcmp(args[param], "-e") == 0 || strcmp(args[param], "-d") == 0) { + encodeMode = (args[param][1] == 'e'); + modeWasSet = True; + } else if (strcmp(args[param], "-o") == 0 || + strcmp(args[param], "--output") == 0) { + if (numArgs < (param + 2)) { + return PrintUserError(rs); + } + outputFile = args[++param]; + } else if (strcmp(args[param], "--debug") == 0) { + if (numArgs < (param + 2)) { + return PrintUserError(rs); + } + // + // For now we silently ignore this parameter to achieve command line + // parameter compatibility with other build tools. + // + param++; + } else if ( + strcmp(args[param], "-h") == 0 || + strcmp(args[param], "--help") == 0 + ) { + PrintHelp(rs); + return 0; + } else if ( + strcmp(args[param], "-v") == 0 || + strcmp(args[param], "--verbose") == 0 + ) { + // + // For now we silently ignore this parameter to achieve command line + // parameter compatibility with other build tools. + // + } else if ( + strcmp(args[param], "-q") == 0 || + strcmp(args[param], "--quiet") == 0 + ) { + mQuietMode = True; + } else if (strcmp(args[param], "--version") == 0) { + PrintVersion(rs); + return 0; + } else if (inputFile == NULL) { + inputFile = args[param]; + } else { + return PrintUserError(rs); + } + } + + if ((inputFile == NULL) || !modeWasSet) { + return PrintUserError(rs); + } + + { + size_t t4 = sizeof(UInt32); + size_t t8 = sizeof(UInt64); + if (t4 != 4 || t8 != 8) + return PrintError(rs, "Incorrect UInt32 or UInt64"); + } + + if (InFile_Open(&inStream.file, inputFile) != 0) + return PrintError(rs, "Can not open input file"); + + if (OutFile_Open(&outStream.file, outputFile) != 0) + return PrintError(rs, "Can not open output file"); + + if (encodeMode) + { + UInt64 fileSize; + File_GetLength(&inStream.file, &fileSize); + if (!mQuietMode) { + printf("Encoding\n"); + } + res = Encode(&outStream.s, &inStream.s, fileSize, rs); + } + else + { + if (!mQuietMode) { + printf("Decoding\n"); + } + res = Decode(&outStream.s, &inStream.s); + } + + File_Close(&outStream.file); + File_Close(&inStream.file); + + if (res != SZ_OK) + { + if (res == SZ_ERROR_MEM) + return PrintError(rs, kCantAllocateMessage); + else if (res == SZ_ERROR_DATA) + return PrintError(rs, kDataErrorMessage); + else if (res == SZ_ERROR_WRITE) + return PrintError(rs, kCantWriteMessage); + else if (res == SZ_ERROR_READ) + return PrintError(rs, kCantReadMessage); + return PrintErrorNumber(rs, res); + } + return 0; +} + +int MY_CDECL main(int numArgs, const char *args[]) +{ + char rs[2000] = { 0 }; + int res = main2(numArgs, args, rs); + if (strlen(rs) > 0) { + puts(rs); + } + return res; +} diff --git a/BaseTools/Source/C/LzmaCompress/Makefile b/BaseTools/Source/C/LzmaCompress/Makefile new file mode 100644 index 0000000000..b2fc9de75e --- /dev/null +++ b/BaseTools/Source/C/LzmaCompress/Makefile @@ -0,0 +1,19 @@ +!INCLUDE ..\Makefiles\ms.common + +APPNAME = LzmaCompress + +#LIBS = $(LIB_PATH)\Common.lib + +SDK_C = Sdk\C + +OBJECTS = \ + LzmaCompress.obj \ + $(SDK_C)\Alloc.obj \ + $(SDK_C)\LzFind.obj \ + $(SDK_C)\LzmaDec.obj \ + $(SDK_C)\LzmaEnc.obj \ + $(SDK_C)\7zFile.obj \ + $(SDK_C)\7zStream.obj + +!INCLUDE ..\Makefiles\ms.app + diff --git a/BaseTools/Source/C/LzmaCompress/Sdk/C/7zFile.c b/BaseTools/Source/C/LzmaCompress/Sdk/C/7zFile.c new file mode 100644 index 0000000000..2b605a5665 --- /dev/null +++ b/BaseTools/Source/C/LzmaCompress/Sdk/C/7zFile.c @@ -0,0 +1,263 @@ +/* 7zFile.c -- File IO +2008-11-22 : Igor Pavlov : Public domain */ + +#include "7zFile.h" + +#ifndef USE_WINDOWS_FILE + +#include + +#endif + +#ifdef USE_WINDOWS_FILE + +/* + ReadFile and WriteFile functions in Windows have BUG: + If you Read or Write 64MB or more (probably min_failure_size = 64MB - 32KB + 1) + from/to Network file, it returns ERROR_NO_SYSTEM_RESOURCES + (Insufficient system resources exist to complete the requested service). + Probably in some version of Windows there are problems with other sizes: + for 32 MB (maybe also for 16 MB). + And message can be "Network connection was lost" +*/ + +#define kChunkSizeMax (1 << 22) + +#endif + +void File_Construct(CSzFile *p) +{ + #ifdef USE_WINDOWS_FILE + p->handle = INVALID_HANDLE_VALUE; + #else + p->file = NULL; + #endif +} + +static WRes File_Open(CSzFile *p, const char *name, int writeMode) +{ + #ifdef USE_WINDOWS_FILE + p->handle = CreateFileA(name, + writeMode ? GENERIC_WRITE : GENERIC_READ, + FILE_SHARE_READ, NULL, + writeMode ? CREATE_ALWAYS : OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, NULL); + return (p->handle != INVALID_HANDLE_VALUE) ? 0 : GetLastError(); + #else + p->file = fopen(name, writeMode ? "wb+" : "rb"); + return (p->file != 0) ? 0 : errno; + #endif +} + +WRes InFile_Open(CSzFile *p, const char *name) { return File_Open(p, name, 0); } +WRes OutFile_Open(CSzFile *p, const char *name) { return File_Open(p, name, 1); } + +WRes File_Close(CSzFile *p) +{ + #ifdef USE_WINDOWS_FILE + if (p->handle != INVALID_HANDLE_VALUE) + { + if (!CloseHandle(p->handle)) + return GetLastError(); + p->handle = INVALID_HANDLE_VALUE; + } + #else + if (p->file != NULL) + { + int res = fclose(p->file); + if (res != 0) + return res; + p->file = NULL; + } + #endif + return 0; +} + +WRes File_Read(CSzFile *p, void *data, size_t *size) +{ + size_t originalSize = *size; + if (originalSize == 0) + return 0; + + #ifdef USE_WINDOWS_FILE + + *size = 0; + do + { + DWORD curSize = (originalSize > kChunkSizeMax) ? kChunkSizeMax : (DWORD)originalSize; + DWORD processed = 0; + BOOL res = ReadFile(p->handle, data, curSize, &processed, NULL); + data = (void *)((Byte *)data + processed); + originalSize -= processed; + *size += processed; + if (!res) + return GetLastError(); + if (processed == 0) + break; + } + while (originalSize > 0); + return 0; + + #else + + *size = fread(data, 1, originalSize, p->file); + if (*size == originalSize) + return 0; + return ferror(p->file); + + #endif +} + +WRes File_Write(CSzFile *p, const void *data, size_t *size) +{ + size_t originalSize = *size; + if (originalSize == 0) + return 0; + + #ifdef USE_WINDOWS_FILE + + *size = 0; + do + { + DWORD curSize = (originalSize > kChunkSizeMax) ? kChunkSizeMax : (DWORD)originalSize; + DWORD processed = 0; + BOOL res = WriteFile(p->handle, data, curSize, &processed, NULL); + data = (void *)((Byte *)data + processed); + originalSize -= processed; + *size += processed; + if (!res) + return GetLastError(); + if (processed == 0) + break; + } + while (originalSize > 0); + return 0; + + #else + + *size = fwrite(data, 1, originalSize, p->file); + if (*size == originalSize) + return 0; + return ferror(p->file); + + #endif +} + +WRes File_Seek(CSzFile *p, Int64 *pos, ESzSeek origin) +{ + #ifdef USE_WINDOWS_FILE + + LARGE_INTEGER value; + DWORD moveMethod; + value.LowPart = (DWORD)*pos; + value.HighPart = (LONG)((UInt64)*pos >> 16 >> 16); /* for case when UInt64 is 32-bit only */ + switch (origin) + { + case SZ_SEEK_SET: moveMethod = FILE_BEGIN; break; + case SZ_SEEK_CUR: moveMethod = FILE_CURRENT; break; + case SZ_SEEK_END: moveMethod = FILE_END; break; + default: return ERROR_INVALID_PARAMETER; + } + value.LowPart = SetFilePointer(p->handle, value.LowPart, &value.HighPart, moveMethod); + if (value.LowPart == 0xFFFFFFFF) + { + WRes res = GetLastError(); + if (res != NO_ERROR) + return res; + } + *pos = ((Int64)value.HighPart << 32) | value.LowPart; + return 0; + + #else + + int moveMethod; + int res; + switch (origin) + { + case SZ_SEEK_SET: moveMethod = SEEK_SET; break; + case SZ_SEEK_CUR: moveMethod = SEEK_CUR; break; + case SZ_SEEK_END: moveMethod = SEEK_END; break; + default: return 1; + } + res = fseek(p->file, (long)*pos, moveMethod); + *pos = ftell(p->file); + return res; + + #endif +} + +WRes File_GetLength(CSzFile *p, UInt64 *length) +{ + #ifdef USE_WINDOWS_FILE + + DWORD sizeHigh; + DWORD sizeLow = GetFileSize(p->handle, &sizeHigh); + if (sizeLow == 0xFFFFFFFF) + { + DWORD res = GetLastError(); + if (res != NO_ERROR) + return res; + } + *length = (((UInt64)sizeHigh) << 32) + sizeLow; + return 0; + + #else + + long pos = ftell(p->file); + int res = fseek(p->file, 0, SEEK_END); + *length = ftell(p->file); + fseek(p->file, pos, SEEK_SET); + return res; + + #endif +} + + +/* ---------- FileSeqInStream ---------- */ + +static SRes FileSeqInStream_Read(void *pp, void *buf, size_t *size) +{ + CFileSeqInStream *p = (CFileSeqInStream *)pp; + return File_Read(&p->file, buf, size) == 0 ? SZ_OK : SZ_ERROR_READ; +} + +void FileSeqInStream_CreateVTable(CFileSeqInStream *p) +{ + p->s.Read = FileSeqInStream_Read; +} + + +/* ---------- FileInStream ---------- */ + +static SRes FileInStream_Read(void *pp, void *buf, size_t *size) +{ + CFileInStream *p = (CFileInStream *)pp; + return (File_Read(&p->file, buf, size) == 0) ? SZ_OK : SZ_ERROR_READ; +} + +static SRes FileInStream_Seek(void *pp, Int64 *pos, ESzSeek origin) +{ + CFileInStream *p = (CFileInStream *)pp; + return File_Seek(&p->file, pos, origin); +} + +void FileInStream_CreateVTable(CFileInStream *p) +{ + p->s.Read = FileInStream_Read; + p->s.Seek = FileInStream_Seek; +} + + +/* ---------- FileOutStream ---------- */ + +static size_t FileOutStream_Write(void *pp, const void *data, size_t size) +{ + CFileOutStream *p = (CFileOutStream *)pp; + File_Write(&p->file, data, &size); + return size; +} + +void FileOutStream_CreateVTable(CFileOutStream *p) +{ + p->s.Write = FileOutStream_Write; +} diff --git a/BaseTools/Source/C/LzmaCompress/Sdk/C/7zFile.h b/BaseTools/Source/C/LzmaCompress/Sdk/C/7zFile.h new file mode 100644 index 0000000000..4fd2936cc3 --- /dev/null +++ b/BaseTools/Source/C/LzmaCompress/Sdk/C/7zFile.h @@ -0,0 +1,74 @@ +/* 7zFile.h -- File IO +2008-11-22 : Igor Pavlov : Public domain */ + +#ifndef __7Z_FILE_H +#define __7Z_FILE_H + +#ifdef _WIN32 +#define USE_WINDOWS_FILE +#endif + +#ifdef USE_WINDOWS_FILE +#include +#else +#include +#endif + +#include "Types.h" + + +/* ---------- File ---------- */ + +typedef struct +{ + #ifdef USE_WINDOWS_FILE + HANDLE handle; + #else + FILE *file; + #endif +} CSzFile; + +void File_Construct(CSzFile *p); +WRes InFile_Open(CSzFile *p, const char *name); +WRes OutFile_Open(CSzFile *p, const char *name); +WRes File_Close(CSzFile *p); + +/* reads max(*size, remain file's size) bytes */ +WRes File_Read(CSzFile *p, void *data, size_t *size); + +/* writes *size bytes */ +WRes File_Write(CSzFile *p, const void *data, size_t *size); + +WRes File_Seek(CSzFile *p, Int64 *pos, ESzSeek origin); +WRes File_GetLength(CSzFile *p, UInt64 *length); + + +/* ---------- FileInStream ---------- */ + +typedef struct +{ + ISeqInStream s; + CSzFile file; +} CFileSeqInStream; + +void FileSeqInStream_CreateVTable(CFileSeqInStream *p); + + +typedef struct +{ + ISeekInStream s; + CSzFile file; +} CFileInStream; + +void FileInStream_CreateVTable(CFileInStream *p); + + +typedef struct +{ + ISeqOutStream s; + CSzFile file; +} CFileOutStream; + +void FileOutStream_CreateVTable(CFileOutStream *p); + +#endif diff --git a/BaseTools/Source/C/LzmaCompress/Sdk/C/7zStream.c b/BaseTools/Source/C/LzmaCompress/Sdk/C/7zStream.c new file mode 100644 index 0000000000..a0a2405d01 --- /dev/null +++ b/BaseTools/Source/C/LzmaCompress/Sdk/C/7zStream.c @@ -0,0 +1,169 @@ +/* 7zStream.c -- 7z Stream functions +2008-11-23 : Igor Pavlov : Public domain */ + +#include + +#include "Types.h" + +SRes SeqInStream_Read2(ISeqInStream *stream, void *buf, size_t size, SRes errorType) +{ + while (size != 0) + { + size_t processed = size; + RINOK(stream->Read(stream, buf, &processed)); + if (processed == 0) + return errorType; + buf = (void *)((Byte *)buf + processed); + size -= processed; + } + return SZ_OK; +} + +SRes SeqInStream_Read(ISeqInStream *stream, void *buf, size_t size) +{ + return SeqInStream_Read2(stream, buf, size, SZ_ERROR_INPUT_EOF); +} + +SRes SeqInStream_ReadByte(ISeqInStream *stream, Byte *buf) +{ + size_t processed = 1; + RINOK(stream->Read(stream, buf, &processed)); + return (processed == 1) ? SZ_OK : SZ_ERROR_INPUT_EOF; +} + +SRes LookInStream_SeekTo(ILookInStream *stream, UInt64 offset) +{ + Int64 t = offset; + return stream->Seek(stream, &t, SZ_SEEK_SET); +} + +SRes LookInStream_LookRead(ILookInStream *stream, void *buf, size_t *size) +{ + void *lookBuf; + if (*size == 0) + return SZ_OK; + RINOK(stream->Look(stream, &lookBuf, size)); + memcpy(buf, lookBuf, *size); + return stream->Skip(stream, *size); +} + +SRes LookInStream_Read2(ILookInStream *stream, void *buf, size_t size, SRes errorType) +{ + while (size != 0) + { + size_t processed = size; + RINOK(stream->Read(stream, buf, &processed)); + if (processed == 0) + return errorType; + buf = (void *)((Byte *)buf + processed); + size -= processed; + } + return SZ_OK; +} + +SRes LookInStream_Read(ILookInStream *stream, void *buf, size_t size) +{ + return LookInStream_Read2(stream, buf, size, SZ_ERROR_INPUT_EOF); +} + +static SRes LookToRead_Look_Lookahead(void *pp, void **buf, size_t *size) +{ + SRes res = SZ_OK; + CLookToRead *p = (CLookToRead *)pp; + size_t size2 = p->size - p->pos; + if (size2 == 0 && *size > 0) + { + p->pos = 0; + size2 = LookToRead_BUF_SIZE; + res = p->realStream->Read(p->realStream, p->buf, &size2); + p->size = size2; + } + if (size2 < *size) + *size = size2; + *buf = p->buf + p->pos; + return res; +} + +static SRes LookToRead_Look_Exact(void *pp, void **buf, size_t *size) +{ + SRes res = SZ_OK; + CLookToRead *p = (CLookToRead *)pp; + size_t size2 = p->size - p->pos; + if (size2 == 0 && *size > 0) + { + p->pos = 0; + if (*size > LookToRead_BUF_SIZE) + *size = LookToRead_BUF_SIZE; + res = p->realStream->Read(p->realStream, p->buf, size); + size2 = p->size = *size; + } + if (size2 < *size) + *size = size2; + *buf = p->buf + p->pos; + return res; +} + +static SRes LookToRead_Skip(void *pp, size_t offset) +{ + CLookToRead *p = (CLookToRead *)pp; + p->pos += offset; + return SZ_OK; +} + +static SRes LookToRead_Read(void *pp, void *buf, size_t *size) +{ + CLookToRead *p = (CLookToRead *)pp; + size_t rem = p->size - p->pos; + if (rem == 0) + return p->realStream->Read(p->realStream, buf, size); + if (rem > *size) + rem = *size; + memcpy(buf, p->buf + p->pos, rem); + p->pos += rem; + *size = rem; + return SZ_OK; +} + +static SRes LookToRead_Seek(void *pp, Int64 *pos, ESzSeek origin) +{ + CLookToRead *p = (CLookToRead *)pp; + p->pos = p->size = 0; + return p->realStream->Seek(p->realStream, pos, origin); +} + +void LookToRead_CreateVTable(CLookToRead *p, int lookahead) +{ + p->s.Look = lookahead ? + LookToRead_Look_Lookahead : + LookToRead_Look_Exact; + p->s.Skip = LookToRead_Skip; + p->s.Read = LookToRead_Read; + p->s.Seek = LookToRead_Seek; +} + +void LookToRead_Init(CLookToRead *p) +{ + p->pos = p->size = 0; +} + +static SRes SecToLook_Read(void *pp, void *buf, size_t *size) +{ + CSecToLook *p = (CSecToLook *)pp; + return LookInStream_LookRead(p->realStream, buf, size); +} + +void SecToLook_CreateVTable(CSecToLook *p) +{ + p->s.Read = SecToLook_Read; +} + +static SRes SecToRead_Read(void *pp, void *buf, size_t *size) +{ + CSecToRead *p = (CSecToRead *)pp; + return p->realStream->Read(p->realStream, buf, size); +} + +void SecToRead_CreateVTable(CSecToRead *p) +{ + p->s.Read = SecToRead_Read; +} diff --git a/BaseTools/Source/C/LzmaCompress/Sdk/C/7zVersion.h b/BaseTools/Source/C/LzmaCompress/Sdk/C/7zVersion.h new file mode 100644 index 0000000000..5a6bcadac6 --- /dev/null +++ b/BaseTools/Source/C/LzmaCompress/Sdk/C/7zVersion.h @@ -0,0 +1,7 @@ +#define MY_VER_MAJOR 4 +#define MY_VER_MINOR 65 +#define MY_VER_BUILD 0 +#define MY_VERSION "4.65" +#define MY_DATE "2009-02-03" +#define MY_COPYRIGHT ": Igor Pavlov : Public domain" +#define MY_VERSION_COPYRIGHT_DATE MY_VERSION " " MY_COPYRIGHT " : " MY_DATE diff --git a/BaseTools/Source/C/LzmaCompress/Sdk/C/Alloc.c b/BaseTools/Source/C/LzmaCompress/Sdk/C/Alloc.c new file mode 100644 index 0000000000..bb24a772b3 --- /dev/null +++ b/BaseTools/Source/C/LzmaCompress/Sdk/C/Alloc.c @@ -0,0 +1,127 @@ +/* Alloc.c -- Memory allocation functions +2008-09-24 +Igor Pavlov +Public domain */ + +#ifdef _WIN32 +#include +#endif +#include + +#include "Alloc.h" + +/* #define _SZ_ALLOC_DEBUG */ + +/* use _SZ_ALLOC_DEBUG to debug alloc/free operations */ +#ifdef _SZ_ALLOC_DEBUG +#include +int g_allocCount = 0; +int g_allocCountMid = 0; +int g_allocCountBig = 0; +#endif + +void *MyAlloc(size_t size) +{ + if (size == 0) + return 0; + #ifdef _SZ_ALLOC_DEBUG + { + void *p = malloc(size); + fprintf(stderr, "\nAlloc %10d bytes, count = %10d, addr = %8X", size, g_allocCount++, (unsigned)p); + return p; + } + #else + return malloc(size); + #endif +} + +void MyFree(void *address) +{ + #ifdef _SZ_ALLOC_DEBUG + if (address != 0) + fprintf(stderr, "\nFree; count = %10d, addr = %8X", --g_allocCount, (unsigned)address); + #endif + free(address); +} + +#ifdef _WIN32 + +void *MidAlloc(size_t size) +{ + if (size == 0) + return 0; + #ifdef _SZ_ALLOC_DEBUG + fprintf(stderr, "\nAlloc_Mid %10d bytes; count = %10d", size, g_allocCountMid++); + #endif + return VirtualAlloc(0, size, MEM_COMMIT, PAGE_READWRITE); +} + +void MidFree(void *address) +{ + #ifdef _SZ_ALLOC_DEBUG + if (address != 0) + fprintf(stderr, "\nFree_Mid; count = %10d", --g_allocCountMid); + #endif + if (address == 0) + return; + VirtualFree(address, 0, MEM_RELEASE); +} + +#ifndef MEM_LARGE_PAGES +#undef _7ZIP_LARGE_PAGES +#endif + +#ifdef _7ZIP_LARGE_PAGES +SIZE_T g_LargePageSize = 0; +typedef SIZE_T (WINAPI *GetLargePageMinimumP)(); +#endif + +void SetLargePageSize() +{ + #ifdef _7ZIP_LARGE_PAGES + SIZE_T size = 0; + GetLargePageMinimumP largePageMinimum = (GetLargePageMinimumP) + GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "GetLargePageMinimum"); + if (largePageMinimum == 0) + return; + size = largePageMinimum(); + if (size == 0 || (size & (size - 1)) != 0) + return; + g_LargePageSize = size; + #endif +} + + +void *BigAlloc(size_t size) +{ + if (size == 0) + return 0; + #ifdef _SZ_ALLOC_DEBUG + fprintf(stderr, "\nAlloc_Big %10d bytes; count = %10d", size, g_allocCountBig++); + #endif + + #ifdef _7ZIP_LARGE_PAGES + if (g_LargePageSize != 0 && g_LargePageSize <= (1 << 30) && size >= (1 << 18)) + { + void *res = VirtualAlloc(0, (size + g_LargePageSize - 1) & (~(g_LargePageSize - 1)), + MEM_COMMIT | MEM_LARGE_PAGES, PAGE_READWRITE); + if (res != 0) + return res; + } + #endif + return VirtualAlloc(0, size, MEM_COMMIT, PAGE_READWRITE); +} + +void BigFree(void *address) +{ + #ifdef _SZ_ALLOC_DEBUG + if (address != 0) + fprintf(stderr, "\nFree_Big; count = %10d", --g_allocCountBig); + #endif + + if (address == 0) + return; + VirtualFree(address, 0, MEM_RELEASE); +} + +#endif diff --git a/BaseTools/Source/C/LzmaCompress/Sdk/C/Alloc.h b/BaseTools/Source/C/LzmaCompress/Sdk/C/Alloc.h new file mode 100644 index 0000000000..a396c6b9e1 --- /dev/null +++ b/BaseTools/Source/C/LzmaCompress/Sdk/C/Alloc.h @@ -0,0 +1,32 @@ +/* Alloc.h -- Memory allocation functions +2008-03-13 +Igor Pavlov +Public domain */ + +#ifndef __COMMON_ALLOC_H +#define __COMMON_ALLOC_H + +#include + +void *MyAlloc(size_t size); +void MyFree(void *address); + +#ifdef _WIN32 + +void SetLargePageSize(); + +void *MidAlloc(size_t size); +void MidFree(void *address); +void *BigAlloc(size_t size); +void BigFree(void *address); + +#else + +#define MidAlloc(size) MyAlloc(size) +#define MidFree(address) MyFree(address) +#define BigAlloc(size) MyAlloc(size) +#define BigFree(address) MyFree(address) + +#endif + +#endif diff --git a/BaseTools/Source/C/LzmaCompress/Sdk/C/CpuArch.h b/BaseTools/Source/C/LzmaCompress/Sdk/C/CpuArch.h new file mode 100644 index 0000000000..006361f2f2 --- /dev/null +++ b/BaseTools/Source/C/LzmaCompress/Sdk/C/CpuArch.h @@ -0,0 +1,69 @@ +/* CpuArch.h +2008-08-05 +Igor Pavlov +Public domain */ + +#ifndef __CPUARCH_H +#define __CPUARCH_H + +/* +LITTLE_ENDIAN_UNALIGN means: + 1) CPU is LITTLE_ENDIAN + 2) it's allowed to make unaligned memory accesses +if LITTLE_ENDIAN_UNALIGN is not defined, it means that we don't know +about these properties of platform. +*/ + +#if defined(_M_IX86) || defined(_M_X64) || defined(_M_AMD64) || defined(__i386__) || defined(__x86_64__) +#define LITTLE_ENDIAN_UNALIGN +#endif + +#ifdef LITTLE_ENDIAN_UNALIGN + +#define GetUi16(p) (*(const UInt16 *)(p)) +#define GetUi32(p) (*(const UInt32 *)(p)) +#define GetUi64(p) (*(const UInt64 *)(p)) +#define SetUi32(p, d) *(UInt32 *)(p) = (d); + +#else + +#define GetUi16(p) (((const Byte *)(p))[0] | ((UInt16)((const Byte *)(p))[1] << 8)) + +#define GetUi32(p) ( \ + ((const Byte *)(p))[0] | \ + ((UInt32)((const Byte *)(p))[1] << 8) | \ + ((UInt32)((const Byte *)(p))[2] << 16) | \ + ((UInt32)((const Byte *)(p))[3] << 24)) + +#define GetUi64(p) (GetUi32(p) | ((UInt64)GetUi32(((const Byte *)(p)) + 4) << 32)) + +#define SetUi32(p, d) { UInt32 _x_ = (d); \ + ((Byte *)(p))[0] = (Byte)_x_; \ + ((Byte *)(p))[1] = (Byte)(_x_ >> 8); \ + ((Byte *)(p))[2] = (Byte)(_x_ >> 16); \ + ((Byte *)(p))[3] = (Byte)(_x_ >> 24); } + +#endif + +#if defined(LITTLE_ENDIAN_UNALIGN) && defined(_WIN64) && (_MSC_VER >= 1300) + +#pragma intrinsic(_byteswap_ulong) +#pragma intrinsic(_byteswap_uint64) +#define GetBe32(p) _byteswap_ulong(*(const UInt32 *)(const Byte *)(p)) +#define GetBe64(p) _byteswap_uint64(*(const UInt64 *)(const Byte *)(p)) + +#else + +#define GetBe32(p) ( \ + ((UInt32)((const Byte *)(p))[0] << 24) | \ + ((UInt32)((const Byte *)(p))[1] << 16) | \ + ((UInt32)((const Byte *)(p))[2] << 8) | \ + ((const Byte *)(p))[3] ) + +#define GetBe64(p) (((UInt64)GetBe32(p) << 32) | GetBe32(((const Byte *)(p)) + 4)) + +#endif + +#define GetBe16(p) (((UInt16)((const Byte *)(p))[0] << 8) | ((const Byte *)(p))[1]) + +#endif diff --git a/BaseTools/Source/C/LzmaCompress/Sdk/C/LzFind.c b/BaseTools/Source/C/LzmaCompress/Sdk/C/LzFind.c new file mode 100644 index 0000000000..e0ebe62356 --- /dev/null +++ b/BaseTools/Source/C/LzmaCompress/Sdk/C/LzFind.c @@ -0,0 +1,751 @@ +/* LzFind.c -- Match finder for LZ algorithms +2008-10-04 : Igor Pavlov : Public domain */ + +#include + +#include "LzFind.h" +#include "LzHash.h" + +#define kEmptyHashValue 0 +#define kMaxValForNormalize ((UInt32)0xFFFFFFFF) +#define kNormalizeStepMin (1 << 10) /* it must be power of 2 */ +#define kNormalizeMask (~(kNormalizeStepMin - 1)) +#define kMaxHistorySize ((UInt32)3 << 30) + +#define kStartMaxLen 3 + +static void LzInWindow_Free(CMatchFinder *p, ISzAlloc *alloc) +{ + if (!p->directInput) + { + alloc->Free(alloc, p->bufferBase); + p->bufferBase = 0; + } +} + +/* keepSizeBefore + keepSizeAfter + keepSizeReserv must be < 4G) */ + +static int LzInWindow_Create(CMatchFinder *p, UInt32 keepSizeReserv, ISzAlloc *alloc) +{ + UInt32 blockSize = p->keepSizeBefore + p->keepSizeAfter + keepSizeReserv; + if (p->directInput) + { + p->blockSize = blockSize; + return 1; + } + if (p->bufferBase == 0 || p->blockSize != blockSize) + { + LzInWindow_Free(p, alloc); + p->blockSize = blockSize; + p->bufferBase = (Byte *)alloc->Alloc(alloc, (size_t)blockSize); + } + return (p->bufferBase != 0); +} + +Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p) { return p->buffer; } +Byte MatchFinder_GetIndexByte(CMatchFinder *p, Int32 index) { return p->buffer[index]; } + +UInt32 MatchFinder_GetNumAvailableBytes(CMatchFinder *p) { return p->streamPos - p->pos; } + +void MatchFinder_ReduceOffsets(CMatchFinder *p, UInt32 subValue) +{ + p->posLimit -= subValue; + p->pos -= subValue; + p->streamPos -= subValue; +} + +static void MatchFinder_ReadBlock(CMatchFinder *p) +{ + if (p->streamEndWasReached || p->result != SZ_OK) + return; + for (;;) + { + Byte *dest = p->buffer + (p->streamPos - p->pos); + size_t size = (p->bufferBase + p->blockSize - dest); + if (size == 0) + return; + p->result = p->stream->Read(p->stream, dest, &size); + if (p->result != SZ_OK) + return; + if (size == 0) + { + p->streamEndWasReached = 1; + return; + } + p->streamPos += (UInt32)size; + if (p->streamPos - p->pos > p->keepSizeAfter) + return; + } +} + +void MatchFinder_MoveBlock(CMatchFinder *p) +{ + memmove(p->bufferBase, + p->buffer - p->keepSizeBefore, + (size_t)(p->streamPos - p->pos + p->keepSizeBefore)); + p->buffer = p->bufferBase + p->keepSizeBefore; +} + +int MatchFinder_NeedMove(CMatchFinder *p) +{ + /* if (p->streamEndWasReached) return 0; */ + return ((size_t)(p->bufferBase + p->blockSize - p->buffer) <= p->keepSizeAfter); +} + +void MatchFinder_ReadIfRequired(CMatchFinder *p) +{ + if (p->streamEndWasReached) + return; + if (p->keepSizeAfter >= p->streamPos - p->pos) + MatchFinder_ReadBlock(p); +} + +static void MatchFinder_CheckAndMoveAndRead(CMatchFinder *p) +{ + if (MatchFinder_NeedMove(p)) + MatchFinder_MoveBlock(p); + MatchFinder_ReadBlock(p); +} + +static void MatchFinder_SetDefaultSettings(CMatchFinder *p) +{ + p->cutValue = 32; + p->btMode = 1; + p->numHashBytes = 4; + /* p->skipModeBits = 0; */ + p->directInput = 0; + p->bigHash = 0; +} + +#define kCrcPoly 0xEDB88320 + +void MatchFinder_Construct(CMatchFinder *p) +{ + UInt32 i; + p->bufferBase = 0; + p->directInput = 0; + p->hash = 0; + MatchFinder_SetDefaultSettings(p); + + for (i = 0; i < 256; i++) + { + UInt32 r = i; + int j; + for (j = 0; j < 8; j++) + r = (r >> 1) ^ (kCrcPoly & ~((r & 1) - 1)); + p->crc[i] = r; + } +} + +static void MatchFinder_FreeThisClassMemory(CMatchFinder *p, ISzAlloc *alloc) +{ + alloc->Free(alloc, p->hash); + p->hash = 0; +} + +void MatchFinder_Free(CMatchFinder *p, ISzAlloc *alloc) +{ + MatchFinder_FreeThisClassMemory(p, alloc); + LzInWindow_Free(p, alloc); +} + +static CLzRef* AllocRefs(UInt32 num, ISzAlloc *alloc) +{ + size_t sizeInBytes = (size_t)num * sizeof(CLzRef); + if (sizeInBytes / sizeof(CLzRef) != num) + return 0; + return (CLzRef *)alloc->Alloc(alloc, sizeInBytes); +} + +int MatchFinder_Create(CMatchFinder *p, UInt32 historySize, + UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter, + ISzAlloc *alloc) +{ + UInt32 sizeReserv; + if (historySize > kMaxHistorySize) + { + MatchFinder_Free(p, alloc); + return 0; + } + sizeReserv = historySize >> 1; + if (historySize > ((UInt32)2 << 30)) + sizeReserv = historySize >> 2; + sizeReserv += (keepAddBufferBefore + matchMaxLen + keepAddBufferAfter) / 2 + (1 << 19); + + p->keepSizeBefore = historySize + keepAddBufferBefore + 1; + p->keepSizeAfter = matchMaxLen + keepAddBufferAfter; + /* we need one additional byte, since we use MoveBlock after pos++ and before dictionary using */ + if (LzInWindow_Create(p, sizeReserv, alloc)) + { + UInt32 newCyclicBufferSize = (historySize /* >> p->skipModeBits */) + 1; + UInt32 hs; + p->matchMaxLen = matchMaxLen; + { + p->fixedHashSize = 0; + if (p->numHashBytes == 2) + hs = (1 << 16) - 1; + else + { + hs = historySize - 1; + hs |= (hs >> 1); + hs |= (hs >> 2); + hs |= (hs >> 4); + hs |= (hs >> 8); + hs >>= 1; + /* hs >>= p->skipModeBits; */ + hs |= 0xFFFF; /* don't change it! It's required for Deflate */ + if (hs > (1 << 24)) + { + if (p->numHashBytes == 3) + hs = (1 << 24) - 1; + else + hs >>= 1; + } + } + p->hashMask = hs; + hs++; + if (p->numHashBytes > 2) p->fixedHashSize += kHash2Size; + if (p->numHashBytes > 3) p->fixedHashSize += kHash3Size; + if (p->numHashBytes > 4) p->fixedHashSize += kHash4Size; + hs += p->fixedHashSize; + } + + { + UInt32 prevSize = p->hashSizeSum + p->numSons; + UInt32 newSize; + p->historySize = historySize; + p->hashSizeSum = hs; + p->cyclicBufferSize = newCyclicBufferSize; + p->numSons = (p->btMode ? newCyclicBufferSize * 2 : newCyclicBufferSize); + newSize = p->hashSizeSum + p->numSons; + if (p->hash != 0 && prevSize == newSize) + return 1; + MatchFinder_FreeThisClassMemory(p, alloc); + p->hash = AllocRefs(newSize, alloc); + if (p->hash != 0) + { + p->son = p->hash + p->hashSizeSum; + return 1; + } + } + } + MatchFinder_Free(p, alloc); + return 0; +} + +static void MatchFinder_SetLimits(CMatchFinder *p) +{ + UInt32 limit = kMaxValForNormalize - p->pos; + UInt32 limit2 = p->cyclicBufferSize - p->cyclicBufferPos; + if (limit2 < limit) + limit = limit2; + limit2 = p->streamPos - p->pos; + if (limit2 <= p->keepSizeAfter) + { + if (limit2 > 0) + limit2 = 1; + } + else + limit2 -= p->keepSizeAfter; + if (limit2 < limit) + limit = limit2; + { + UInt32 lenLimit = p->streamPos - p->pos; + if (lenLimit > p->matchMaxLen) + lenLimit = p->matchMaxLen; + p->lenLimit = lenLimit; + } + p->posLimit = p->pos + limit; +} + +void MatchFinder_Init(CMatchFinder *p) +{ + UInt32 i; + for (i = 0; i < p->hashSizeSum; i++) + p->hash[i] = kEmptyHashValue; + p->cyclicBufferPos = 0; + p->buffer = p->bufferBase; + p->pos = p->streamPos = p->cyclicBufferSize; + p->result = SZ_OK; + p->streamEndWasReached = 0; + MatchFinder_ReadBlock(p); + MatchFinder_SetLimits(p); +} + +static UInt32 MatchFinder_GetSubValue(CMatchFinder *p) +{ + return (p->pos - p->historySize - 1) & kNormalizeMask; +} + +void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, UInt32 numItems) +{ + UInt32 i; + for (i = 0; i < numItems; i++) + { + UInt32 value = items[i]; + if (value <= subValue) + value = kEmptyHashValue; + else + value -= subValue; + items[i] = value; + } +} + +static void MatchFinder_Normalize(CMatchFinder *p) +{ + UInt32 subValue = MatchFinder_GetSubValue(p); + MatchFinder_Normalize3(subValue, p->hash, p->hashSizeSum + p->numSons); + MatchFinder_ReduceOffsets(p, subValue); +} + +static void MatchFinder_CheckLimits(CMatchFinder *p) +{ + if (p->pos == kMaxValForNormalize) + MatchFinder_Normalize(p); + if (!p->streamEndWasReached && p->keepSizeAfter == p->streamPos - p->pos) + MatchFinder_CheckAndMoveAndRead(p); + if (p->cyclicBufferPos == p->cyclicBufferSize) + p->cyclicBufferPos = 0; + MatchFinder_SetLimits(p); +} + +static UInt32 * Hc_GetMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son, + UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue, + UInt32 *distances, UInt32 maxLen) +{ + son[_cyclicBufferPos] = curMatch; + for (;;) + { + UInt32 delta = pos - curMatch; + if (cutValue-- == 0 || delta >= _cyclicBufferSize) + return distances; + { + const Byte *pb = cur - delta; + curMatch = son[_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)]; + if (pb[maxLen] == cur[maxLen] && *pb == *cur) + { + UInt32 len = 0; + while (++len != lenLimit) + if (pb[len] != cur[len]) + break; + if (maxLen < len) + { + *distances++ = maxLen = len; + *distances++ = delta - 1; + if (len == lenLimit) + return distances; + } + } + } + } +} + +UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son, + UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue, + UInt32 *distances, UInt32 maxLen) +{ + CLzRef *ptr0 = son + (_cyclicBufferPos << 1) + 1; + CLzRef *ptr1 = son + (_cyclicBufferPos << 1); + UInt32 len0 = 0, len1 = 0; + for (;;) + { + UInt32 delta = pos - curMatch; + if (cutValue-- == 0 || delta >= _cyclicBufferSize) + { + *ptr0 = *ptr1 = kEmptyHashValue; + return distances; + } + { + CLzRef *pair = son + ((_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1); + const Byte *pb = cur - delta; + UInt32 len = (len0 < len1 ? len0 : len1); + if (pb[len] == cur[len]) + { + if (++len != lenLimit && pb[len] == cur[len]) + while (++len != lenLimit) + if (pb[len] != cur[len]) + break; + if (maxLen < len) + { + *distances++ = maxLen = len; + *distances++ = delta - 1; + if (len == lenLimit) + { + *ptr1 = pair[0]; + *ptr0 = pair[1]; + return distances; + } + } + } + if (pb[len] < cur[len]) + { + *ptr1 = curMatch; + ptr1 = pair + 1; + curMatch = *ptr1; + len1 = len; + } + else + { + *ptr0 = curMatch; + ptr0 = pair; + curMatch = *ptr0; + len0 = len; + } + } + } +} + +static void SkipMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son, + UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue) +{ + CLzRef *ptr0 = son + (_cyclicBufferPos << 1) + 1; + CLzRef *ptr1 = son + (_cyclicBufferPos << 1); + UInt32 len0 = 0, len1 = 0; + for (;;) + { + UInt32 delta = pos - curMatch; + if (cutValue-- == 0 || delta >= _cyclicBufferSize) + { + *ptr0 = *ptr1 = kEmptyHashValue; + return; + } + { + CLzRef *pair = son + ((_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1); + const Byte *pb = cur - delta; + UInt32 len = (len0 < len1 ? len0 : len1); + if (pb[len] == cur[len]) + { + while (++len != lenLimit) + if (pb[len] != cur[len]) + break; + { + if (len == lenLimit) + { + *ptr1 = pair[0]; + *ptr0 = pair[1]; + return; + } + } + } + if (pb[len] < cur[len]) + { + *ptr1 = curMatch; + ptr1 = pair + 1; + curMatch = *ptr1; + len1 = len; + } + else + { + *ptr0 = curMatch; + ptr0 = pair; + curMatch = *ptr0; + len0 = len; + } + } + } +} + +#define MOVE_POS \ + ++p->cyclicBufferPos; \ + p->buffer++; \ + if (++p->pos == p->posLimit) MatchFinder_CheckLimits(p); + +#define MOVE_POS_RET MOVE_POS return offset; + +static void MatchFinder_MovePos(CMatchFinder *p) { MOVE_POS; } + +#define GET_MATCHES_HEADER2(minLen, ret_op) \ + UInt32 lenLimit; UInt32 hashValue; const Byte *cur; UInt32 curMatch; \ + lenLimit = p->lenLimit; { if (lenLimit < minLen) { MatchFinder_MovePos(p); ret_op; }} \ + cur = p->buffer; + +#define GET_MATCHES_HEADER(minLen) GET_MATCHES_HEADER2(minLen, return 0) +#define SKIP_HEADER(minLen) GET_MATCHES_HEADER2(minLen, continue) + +#define MF_PARAMS(p) p->pos, p->buffer, p->son, p->cyclicBufferPos, p->cyclicBufferSize, p->cutValue + +#define GET_MATCHES_FOOTER(offset, maxLen) \ + offset = (UInt32)(GetMatchesSpec1(lenLimit, curMatch, MF_PARAMS(p), \ + distances + offset, maxLen) - distances); MOVE_POS_RET; + +#define SKIP_FOOTER \ + SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p)); MOVE_POS; + +static UInt32 Bt2_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) +{ + UInt32 offset; + GET_MATCHES_HEADER(2) + HASH2_CALC; + curMatch = p->hash[hashValue]; + p->hash[hashValue] = p->pos; + offset = 0; + GET_MATCHES_FOOTER(offset, 1) +} + +UInt32 Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) +{ + UInt32 offset; + GET_MATCHES_HEADER(3) + HASH_ZIP_CALC; + curMatch = p->hash[hashValue]; + p->hash[hashValue] = p->pos; + offset = 0; + GET_MATCHES_FOOTER(offset, 2) +} + +static UInt32 Bt3_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) +{ + UInt32 hash2Value, delta2, maxLen, offset; + GET_MATCHES_HEADER(3) + + HASH3_CALC; + + delta2 = p->pos - p->hash[hash2Value]; + curMatch = p->hash[kFix3HashSize + hashValue]; + + p->hash[hash2Value] = + p->hash[kFix3HashSize + hashValue] = p->pos; + + + maxLen = 2; + offset = 0; + if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur) + { + for (; maxLen != lenLimit; maxLen++) + if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen]) + break; + distances[0] = maxLen; + distances[1] = delta2 - 1; + offset = 2; + if (maxLen == lenLimit) + { + SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p)); + MOVE_POS_RET; + } + } + GET_MATCHES_FOOTER(offset, maxLen) +} + +static UInt32 Bt4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) +{ + UInt32 hash2Value, hash3Value, delta2, delta3, maxLen, offset; + GET_MATCHES_HEADER(4) + + HASH4_CALC; + + delta2 = p->pos - p->hash[ hash2Value]; + delta3 = p->pos - p->hash[kFix3HashSize + hash3Value]; + curMatch = p->hash[kFix4HashSize + hashValue]; + + p->hash[ hash2Value] = + p->hash[kFix3HashSize + hash3Value] = + p->hash[kFix4HashSize + hashValue] = p->pos; + + maxLen = 1; + offset = 0; + if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur) + { + distances[0] = maxLen = 2; + distances[1] = delta2 - 1; + offset = 2; + } + if (delta2 != delta3 && delta3 < p->cyclicBufferSize && *(cur - delta3) == *cur) + { + maxLen = 3; + distances[offset + 1] = delta3 - 1; + offset += 2; + delta2 = delta3; + } + if (offset != 0) + { + for (; maxLen != lenLimit; maxLen++) + if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen]) + break; + distances[offset - 2] = maxLen; + if (maxLen == lenLimit) + { + SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p)); + MOVE_POS_RET; + } + } + if (maxLen < 3) + maxLen = 3; + GET_MATCHES_FOOTER(offset, maxLen) +} + +static UInt32 Hc4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) +{ + UInt32 hash2Value, hash3Value, delta2, delta3, maxLen, offset; + GET_MATCHES_HEADER(4) + + HASH4_CALC; + + delta2 = p->pos - p->hash[ hash2Value]; + delta3 = p->pos - p->hash[kFix3HashSize + hash3Value]; + curMatch = p->hash[kFix4HashSize + hashValue]; + + p->hash[ hash2Value] = + p->hash[kFix3HashSize + hash3Value] = + p->hash[kFix4HashSize + hashValue] = p->pos; + + maxLen = 1; + offset = 0; + if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur) + { + distances[0] = maxLen = 2; + distances[1] = delta2 - 1; + offset = 2; + } + if (delta2 != delta3 && delta3 < p->cyclicBufferSize && *(cur - delta3) == *cur) + { + maxLen = 3; + distances[offset + 1] = delta3 - 1; + offset += 2; + delta2 = delta3; + } + if (offset != 0) + { + for (; maxLen != lenLimit; maxLen++) + if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen]) + break; + distances[offset - 2] = maxLen; + if (maxLen == lenLimit) + { + p->son[p->cyclicBufferPos] = curMatch; + MOVE_POS_RET; + } + } + if (maxLen < 3) + maxLen = 3; + offset = (UInt32)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p), + distances + offset, maxLen) - (distances)); + MOVE_POS_RET +} + +UInt32 Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) +{ + UInt32 offset; + GET_MATCHES_HEADER(3) + HASH_ZIP_CALC; + curMatch = p->hash[hashValue]; + p->hash[hashValue] = p->pos; + offset = (UInt32)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p), + distances, 2) - (distances)); + MOVE_POS_RET +} + +static void Bt2_MatchFinder_Skip(CMatchFinder *p, UInt32 num) +{ + do + { + SKIP_HEADER(2) + HASH2_CALC; + curMatch = p->hash[hashValue]; + p->hash[hashValue] = p->pos; + SKIP_FOOTER + } + while (--num != 0); +} + +void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num) +{ + do + { + SKIP_HEADER(3) + HASH_ZIP_CALC; + curMatch = p->hash[hashValue]; + p->hash[hashValue] = p->pos; + SKIP_FOOTER + } + while (--num != 0); +} + +static void Bt3_MatchFinder_Skip(CMatchFinder *p, UInt32 num) +{ + do + { + UInt32 hash2Value; + SKIP_HEADER(3) + HASH3_CALC; + curMatch = p->hash[kFix3HashSize + hashValue]; + p->hash[hash2Value] = + p->hash[kFix3HashSize + hashValue] = p->pos; + SKIP_FOOTER + } + while (--num != 0); +} + +static void Bt4_MatchFinder_Skip(CMatchFinder *p, UInt32 num) +{ + do + { + UInt32 hash2Value, hash3Value; + SKIP_HEADER(4) + HASH4_CALC; + curMatch = p->hash[kFix4HashSize + hashValue]; + p->hash[ hash2Value] = + p->hash[kFix3HashSize + hash3Value] = p->pos; + p->hash[kFix4HashSize + hashValue] = p->pos; + SKIP_FOOTER + } + while (--num != 0); +} + +static void Hc4_MatchFinder_Skip(CMatchFinder *p, UInt32 num) +{ + do + { + UInt32 hash2Value, hash3Value; + SKIP_HEADER(4) + HASH4_CALC; + curMatch = p->hash[kFix4HashSize + hashValue]; + p->hash[ hash2Value] = + p->hash[kFix3HashSize + hash3Value] = + p->hash[kFix4HashSize + hashValue] = p->pos; + p->son[p->cyclicBufferPos] = curMatch; + MOVE_POS + } + while (--num != 0); +} + +void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num) +{ + do + { + SKIP_HEADER(3) + HASH_ZIP_CALC; + curMatch = p->hash[hashValue]; + p->hash[hashValue] = p->pos; + p->son[p->cyclicBufferPos] = curMatch; + MOVE_POS + } + while (--num != 0); +} + +void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder *vTable) +{ + vTable->Init = (Mf_Init_Func)MatchFinder_Init; + vTable->GetIndexByte = (Mf_GetIndexByte_Func)MatchFinder_GetIndexByte; + vTable->GetNumAvailableBytes = (Mf_GetNumAvailableBytes_Func)MatchFinder_GetNumAvailableBytes; + vTable->GetPointerToCurrentPos = (Mf_GetPointerToCurrentPos_Func)MatchFinder_GetPointerToCurrentPos; + if (!p->btMode) + { + vTable->GetMatches = (Mf_GetMatches_Func)Hc4_MatchFinder_GetMatches; + vTable->Skip = (Mf_Skip_Func)Hc4_MatchFinder_Skip; + } + else if (p->numHashBytes == 2) + { + vTable->GetMatches = (Mf_GetMatches_Func)Bt2_MatchFinder_GetMatches; + vTable->Skip = (Mf_Skip_Func)Bt2_MatchFinder_Skip; + } + else if (p->numHashBytes == 3) + { + vTable->GetMatches = (Mf_GetMatches_Func)Bt3_MatchFinder_GetMatches; + vTable->Skip = (Mf_Skip_Func)Bt3_MatchFinder_Skip; + } + else + { + vTable->GetMatches = (Mf_GetMatches_Func)Bt4_MatchFinder_GetMatches; + vTable->Skip = (Mf_Skip_Func)Bt4_MatchFinder_Skip; + } +} diff --git a/BaseTools/Source/C/LzmaCompress/Sdk/C/LzFind.h b/BaseTools/Source/C/LzmaCompress/Sdk/C/LzFind.h new file mode 100644 index 0000000000..423d67e0c3 --- /dev/null +++ b/BaseTools/Source/C/LzmaCompress/Sdk/C/LzFind.h @@ -0,0 +1,107 @@ +/* LzFind.h -- Match finder for LZ algorithms +2008-10-04 : Igor Pavlov : Public domain */ + +#ifndef __LZFIND_H +#define __LZFIND_H + +#include "Types.h" + +typedef UInt32 CLzRef; + +typedef struct _CMatchFinder +{ + Byte *buffer; + UInt32 pos; + UInt32 posLimit; + UInt32 streamPos; + UInt32 lenLimit; + + UInt32 cyclicBufferPos; + UInt32 cyclicBufferSize; /* it must be = (historySize + 1) */ + + UInt32 matchMaxLen; + CLzRef *hash; + CLzRef *son; + UInt32 hashMask; + UInt32 cutValue; + + Byte *bufferBase; + ISeqInStream *stream; + int streamEndWasReached; + + UInt32 blockSize; + UInt32 keepSizeBefore; + UInt32 keepSizeAfter; + + UInt32 numHashBytes; + int directInput; + int btMode; + /* int skipModeBits; */ + int bigHash; + UInt32 historySize; + UInt32 fixedHashSize; + UInt32 hashSizeSum; + UInt32 numSons; + SRes result; + UInt32 crc[256]; +} CMatchFinder; + +#define Inline_MatchFinder_GetPointerToCurrentPos(p) ((p)->buffer) +#define Inline_MatchFinder_GetIndexByte(p, index) ((p)->buffer[(Int32)(index)]) + +#define Inline_MatchFinder_GetNumAvailableBytes(p) ((p)->streamPos - (p)->pos) + +int MatchFinder_NeedMove(CMatchFinder *p); +Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p); +void MatchFinder_MoveBlock(CMatchFinder *p); +void MatchFinder_ReadIfRequired(CMatchFinder *p); + +void MatchFinder_Construct(CMatchFinder *p); + +/* Conditions: + historySize <= 3 GB + keepAddBufferBefore + matchMaxLen + keepAddBufferAfter < 511MB +*/ +int MatchFinder_Create(CMatchFinder *p, UInt32 historySize, + UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter, + ISzAlloc *alloc); +void MatchFinder_Free(CMatchFinder *p, ISzAlloc *alloc); +void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, UInt32 numItems); +void MatchFinder_ReduceOffsets(CMatchFinder *p, UInt32 subValue); + +UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *buffer, CLzRef *son, + UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 _cutValue, + UInt32 *distances, UInt32 maxLen); + +/* +Conditions: + Mf_GetNumAvailableBytes_Func must be called before each Mf_GetMatchLen_Func. + Mf_GetPointerToCurrentPos_Func's result must be used only before any other function +*/ + +typedef void (*Mf_Init_Func)(void *object); +typedef Byte (*Mf_GetIndexByte_Func)(void *object, Int32 index); +typedef UInt32 (*Mf_GetNumAvailableBytes_Func)(void *object); +typedef const Byte * (*Mf_GetPointerToCurrentPos_Func)(void *object); +typedef UInt32 (*Mf_GetMatches_Func)(void *object, UInt32 *distances); +typedef void (*Mf_Skip_Func)(void *object, UInt32); + +typedef struct _IMatchFinder +{ + Mf_Init_Func Init; + Mf_GetIndexByte_Func GetIndexByte; + Mf_GetNumAvailableBytes_Func GetNumAvailableBytes; + Mf_GetPointerToCurrentPos_Func GetPointerToCurrentPos; + Mf_GetMatches_Func GetMatches; + Mf_Skip_Func Skip; +} IMatchFinder; + +void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder *vTable); + +void MatchFinder_Init(CMatchFinder *p); +UInt32 Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances); +UInt32 Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances); +void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num); +void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num); + +#endif diff --git a/BaseTools/Source/C/LzmaCompress/Sdk/C/LzFindMt.c b/BaseTools/Source/C/LzmaCompress/Sdk/C/LzFindMt.c new file mode 100644 index 0000000000..0ef134735d --- /dev/null +++ b/BaseTools/Source/C/LzmaCompress/Sdk/C/LzFindMt.c @@ -0,0 +1,793 @@ +/* LzFindMt.c -- multithreaded Match finder for LZ algorithms +2008-10-04 : Igor Pavlov : Public domain */ + +#include "LzHash.h" + +#include "LzFindMt.h" + +void MtSync_Construct(CMtSync *p) +{ + p->wasCreated = False; + p->csWasInitialized = False; + p->csWasEntered = False; + Thread_Construct(&p->thread); + Event_Construct(&p->canStart); + Event_Construct(&p->wasStarted); + Event_Construct(&p->wasStopped); + Semaphore_Construct(&p->freeSemaphore); + Semaphore_Construct(&p->filledSemaphore); +} + +void MtSync_GetNextBlock(CMtSync *p) +{ + if (p->needStart) + { + p->numProcessedBlocks = 1; + p->needStart = False; + p->stopWriting = False; + p->exit = False; + Event_Reset(&p->wasStarted); + Event_Reset(&p->wasStopped); + + Event_Set(&p->canStart); + Event_Wait(&p->wasStarted); + } + else + { + CriticalSection_Leave(&p->cs); + p->csWasEntered = False; + p->numProcessedBlocks++; + Semaphore_Release1(&p->freeSemaphore); + } + Semaphore_Wait(&p->filledSemaphore); + CriticalSection_Enter(&p->cs); + p->csWasEntered = True; +} + +/* MtSync_StopWriting must be called if Writing was started */ + +void MtSync_StopWriting(CMtSync *p) +{ + UInt32 myNumBlocks = p->numProcessedBlocks; + if (!Thread_WasCreated(&p->thread) || p->needStart) + return; + p->stopWriting = True; + if (p->csWasEntered) + { + CriticalSection_Leave(&p->cs); + p->csWasEntered = False; + } + Semaphore_Release1(&p->freeSemaphore); + + Event_Wait(&p->wasStopped); + + while (myNumBlocks++ != p->numProcessedBlocks) + { + Semaphore_Wait(&p->filledSemaphore); + Semaphore_Release1(&p->freeSemaphore); + } + p->needStart = True; +} + +void MtSync_Destruct(CMtSync *p) +{ + if (Thread_WasCreated(&p->thread)) + { + MtSync_StopWriting(p); + p->exit = True; + if (p->needStart) + Event_Set(&p->canStart); + Thread_Wait(&p->thread); + Thread_Close(&p->thread); + } + if (p->csWasInitialized) + { + CriticalSection_Delete(&p->cs); + p->csWasInitialized = False; + } + + Event_Close(&p->canStart); + Event_Close(&p->wasStarted); + Event_Close(&p->wasStopped); + Semaphore_Close(&p->freeSemaphore); + Semaphore_Close(&p->filledSemaphore); + + p->wasCreated = False; +} + +#define RINOK_THREAD(x) { if ((x) != 0) return SZ_ERROR_THREAD; } + +static SRes MtSync_Create2(CMtSync *p, unsigned (MY_STD_CALL *startAddress)(void *), void *obj, UInt32 numBlocks) +{ + if (p->wasCreated) + return SZ_OK; + + RINOK_THREAD(CriticalSection_Init(&p->cs)); + p->csWasInitialized = True; + + RINOK_THREAD(AutoResetEvent_CreateNotSignaled(&p->canStart)); + RINOK_THREAD(AutoResetEvent_CreateNotSignaled(&p->wasStarted)); + RINOK_THREAD(AutoResetEvent_CreateNotSignaled(&p->wasStopped)); + + RINOK_THREAD(Semaphore_Create(&p->freeSemaphore, numBlocks, numBlocks)); + RINOK_THREAD(Semaphore_Create(&p->filledSemaphore, 0, numBlocks)); + + p->needStart = True; + + RINOK_THREAD(Thread_Create(&p->thread, startAddress, obj)); + p->wasCreated = True; + return SZ_OK; +} + +static SRes MtSync_Create(CMtSync *p, unsigned (MY_STD_CALL *startAddress)(void *), void *obj, UInt32 numBlocks) +{ + SRes res = MtSync_Create2(p, startAddress, obj, numBlocks); + if (res != SZ_OK) + MtSync_Destruct(p); + return res; +} + +void MtSync_Init(CMtSync *p) { p->needStart = True; } + +#define kMtMaxValForNormalize 0xFFFFFFFF + +#define DEF_GetHeads2(name, v, action) \ +static void GetHeads ## name(const Byte *p, UInt32 pos, \ +UInt32 *hash, UInt32 hashMask, UInt32 *heads, UInt32 numHeads, const UInt32 *crc) \ +{ action; for (; numHeads != 0; numHeads--) { \ +const UInt32 value = (v); p++; *heads++ = pos - hash[value]; hash[value] = pos++; } } + +#define DEF_GetHeads(name, v) DEF_GetHeads2(name, v, ;) + +DEF_GetHeads2(2, (p[0] | ((UInt32)p[1] << 8)), hashMask = hashMask; crc = crc; ) +DEF_GetHeads(3, (crc[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8)) & hashMask) +DEF_GetHeads(4, (crc[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8) ^ (crc[p[3]] << 5)) & hashMask) +DEF_GetHeads(4b, (crc[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8) ^ ((UInt32)p[3] << 16)) & hashMask) +DEF_GetHeads(5, (crc[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8) ^ (crc[p[3]] << 5) ^ (crc[p[4]] << 3)) & hashMask) + +void HashThreadFunc(CMatchFinderMt *mt) +{ + CMtSync *p = &mt->hashSync; + for (;;) + { + UInt32 numProcessedBlocks = 0; + Event_Wait(&p->canStart); + Event_Set(&p->wasStarted); + for (;;) + { + if (p->exit) + return; + if (p->stopWriting) + { + p->numProcessedBlocks = numProcessedBlocks; + Event_Set(&p->wasStopped); + break; + } + + { + CMatchFinder *mf = mt->MatchFinder; + if (MatchFinder_NeedMove(mf)) + { + CriticalSection_Enter(&mt->btSync.cs); + CriticalSection_Enter(&mt->hashSync.cs); + { + const Byte *beforePtr = MatchFinder_GetPointerToCurrentPos(mf); + const Byte *afterPtr; + MatchFinder_MoveBlock(mf); + afterPtr = MatchFinder_GetPointerToCurrentPos(mf); + mt->pointerToCurPos -= beforePtr - afterPtr; + mt->buffer -= beforePtr - afterPtr; + } + CriticalSection_Leave(&mt->btSync.cs); + CriticalSection_Leave(&mt->hashSync.cs); + continue; + } + + Semaphore_Wait(&p->freeSemaphore); + + MatchFinder_ReadIfRequired(mf); + if (mf->pos > (kMtMaxValForNormalize - kMtHashBlockSize)) + { + UInt32 subValue = (mf->pos - mf->historySize - 1); + MatchFinder_ReduceOffsets(mf, subValue); + MatchFinder_Normalize3(subValue, mf->hash + mf->fixedHashSize, mf->hashMask + 1); + } + { + UInt32 *heads = mt->hashBuf + ((numProcessedBlocks++) & kMtHashNumBlocksMask) * kMtHashBlockSize; + UInt32 num = mf->streamPos - mf->pos; + heads[0] = 2; + heads[1] = num; + if (num >= mf->numHashBytes) + { + num = num - mf->numHashBytes + 1; + if (num > kMtHashBlockSize - 2) + num = kMtHashBlockSize - 2; + mt->GetHeadsFunc(mf->buffer, mf->pos, mf->hash + mf->fixedHashSize, mf->hashMask, heads + 2, num, mf->crc); + heads[0] += num; + } + mf->pos += num; + mf->buffer += num; + } + } + + Semaphore_Release1(&p->filledSemaphore); + } + } +} + +void MatchFinderMt_GetNextBlock_Hash(CMatchFinderMt *p) +{ + MtSync_GetNextBlock(&p->hashSync); + p->hashBufPosLimit = p->hashBufPos = ((p->hashSync.numProcessedBlocks - 1) & kMtHashNumBlocksMask) * kMtHashBlockSize; + p->hashBufPosLimit += p->hashBuf[p->hashBufPos++]; + p->hashNumAvail = p->hashBuf[p->hashBufPos++]; +} + +#define kEmptyHashValue 0 + +/* #define MFMT_GM_INLINE */ + +#ifdef MFMT_GM_INLINE + +#define NO_INLINE MY_FAST_CALL + +Int32 NO_INLINE GetMatchesSpecN(UInt32 lenLimit, UInt32 pos, const Byte *cur, CLzRef *son, + UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 _cutValue, + UInt32 *_distances, UInt32 _maxLen, const UInt32 *hash, Int32 limit, UInt32 size, UInt32 *posRes) +{ + do + { + UInt32 *distances = _distances + 1; + UInt32 curMatch = pos - *hash++; + + CLzRef *ptr0 = son + (_cyclicBufferPos << 1) + 1; + CLzRef *ptr1 = son + (_cyclicBufferPos << 1); + UInt32 len0 = 0, len1 = 0; + UInt32 cutValue = _cutValue; + UInt32 maxLen = _maxLen; + for (;;) + { + UInt32 delta = pos - curMatch; + if (cutValue-- == 0 || delta >= _cyclicBufferSize) + { + *ptr0 = *ptr1 = kEmptyHashValue; + break; + } + { + CLzRef *pair = son + ((_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1); + const Byte *pb = cur - delta; + UInt32 len = (len0 < len1 ? len0 : len1); + if (pb[len] == cur[len]) + { + if (++len != lenLimit && pb[len] == cur[len]) + while (++len != lenLimit) + if (pb[len] != cur[len]) + break; + if (maxLen < len) + { + *distances++ = maxLen = len; + *distances++ = delta - 1; + if (len == lenLimit) + { + *ptr1 = pair[0]; + *ptr0 = pair[1]; + break; + } + } + } + if (pb[len] < cur[len]) + { + *ptr1 = curMatch; + ptr1 = pair + 1; + curMatch = *ptr1; + len1 = len; + } + else + { + *ptr0 = curMatch; + ptr0 = pair; + curMatch = *ptr0; + len0 = len; + } + } + } + pos++; + _cyclicBufferPos++; + cur++; + { + UInt32 num = (UInt32)(distances - _distances); + *_distances = num - 1; + _distances += num; + limit -= num; + } + } + while (limit > 0 && --size != 0); + *posRes = pos; + return limit; +} + +#endif + +void BtGetMatches(CMatchFinderMt *p, UInt32 *distances) +{ + UInt32 numProcessed = 0; + UInt32 curPos = 2; + UInt32 limit = kMtBtBlockSize - (p->matchMaxLen * 2); + distances[1] = p->hashNumAvail; + while (curPos < limit) + { + if (p->hashBufPos == p->hashBufPosLimit) + { + MatchFinderMt_GetNextBlock_Hash(p); + distances[1] = numProcessed + p->hashNumAvail; + if (p->hashNumAvail >= p->numHashBytes) + continue; + for (; p->hashNumAvail != 0; p->hashNumAvail--) + distances[curPos++] = 0; + break; + } + { + UInt32 size = p->hashBufPosLimit - p->hashBufPos; + UInt32 lenLimit = p->matchMaxLen; + UInt32 pos = p->pos; + UInt32 cyclicBufferPos = p->cyclicBufferPos; + if (lenLimit >= p->hashNumAvail) + lenLimit = p->hashNumAvail; + { + UInt32 size2 = p->hashNumAvail - lenLimit + 1; + if (size2 < size) + size = size2; + size2 = p->cyclicBufferSize - cyclicBufferPos; + if (size2 < size) + size = size2; + } + #ifndef MFMT_GM_INLINE + while (curPos < limit && size-- != 0) + { + UInt32 *startDistances = distances + curPos; + UInt32 num = (UInt32)(GetMatchesSpec1(lenLimit, pos - p->hashBuf[p->hashBufPos++], + pos, p->buffer, p->son, cyclicBufferPos, p->cyclicBufferSize, p->cutValue, + startDistances + 1, p->numHashBytes - 1) - startDistances); + *startDistances = num - 1; + curPos += num; + cyclicBufferPos++; + pos++; + p->buffer++; + } + #else + { + UInt32 posRes; + curPos = limit - GetMatchesSpecN(lenLimit, pos, p->buffer, p->son, cyclicBufferPos, p->cyclicBufferSize, p->cutValue, + distances + curPos, p->numHashBytes - 1, p->hashBuf + p->hashBufPos, (Int32)(limit - curPos) , size, &posRes); + p->hashBufPos += posRes - pos; + cyclicBufferPos += posRes - pos; + p->buffer += posRes - pos; + pos = posRes; + } + #endif + + numProcessed += pos - p->pos; + p->hashNumAvail -= pos - p->pos; + p->pos = pos; + if (cyclicBufferPos == p->cyclicBufferSize) + cyclicBufferPos = 0; + p->cyclicBufferPos = cyclicBufferPos; + } + } + distances[0] = curPos; +} + +void BtFillBlock(CMatchFinderMt *p, UInt32 globalBlockIndex) +{ + CMtSync *sync = &p->hashSync; + if (!sync->needStart) + { + CriticalSection_Enter(&sync->cs); + sync->csWasEntered = True; + } + + BtGetMatches(p, p->btBuf + (globalBlockIndex & kMtBtNumBlocksMask) * kMtBtBlockSize); + + if (p->pos > kMtMaxValForNormalize - kMtBtBlockSize) + { + UInt32 subValue = p->pos - p->cyclicBufferSize; + MatchFinder_Normalize3(subValue, p->son, p->cyclicBufferSize * 2); + p->pos -= subValue; + } + + if (!sync->needStart) + { + CriticalSection_Leave(&sync->cs); + sync->csWasEntered = False; + } +} + +void BtThreadFunc(CMatchFinderMt *mt) +{ + CMtSync *p = &mt->btSync; + for (;;) + { + UInt32 blockIndex = 0; + Event_Wait(&p->canStart); + Event_Set(&p->wasStarted); + for (;;) + { + if (p->exit) + return; + if (p->stopWriting) + { + p->numProcessedBlocks = blockIndex; + MtSync_StopWriting(&mt->hashSync); + Event_Set(&p->wasStopped); + break; + } + Semaphore_Wait(&p->freeSemaphore); + BtFillBlock(mt, blockIndex++); + Semaphore_Release1(&p->filledSemaphore); + } + } +} + +void MatchFinderMt_Construct(CMatchFinderMt *p) +{ + p->hashBuf = 0; + MtSync_Construct(&p->hashSync); + MtSync_Construct(&p->btSync); +} + +void MatchFinderMt_FreeMem(CMatchFinderMt *p, ISzAlloc *alloc) +{ + alloc->Free(alloc, p->hashBuf); + p->hashBuf = 0; +} + +void MatchFinderMt_Destruct(CMatchFinderMt *p, ISzAlloc *alloc) +{ + MtSync_Destruct(&p->hashSync); + MtSync_Destruct(&p->btSync); + MatchFinderMt_FreeMem(p, alloc); +} + +#define kHashBufferSize (kMtHashBlockSize * kMtHashNumBlocks) +#define kBtBufferSize (kMtBtBlockSize * kMtBtNumBlocks) + +static unsigned MY_STD_CALL HashThreadFunc2(void *p) { HashThreadFunc((CMatchFinderMt *)p); return 0; } +static unsigned MY_STD_CALL BtThreadFunc2(void *p) +{ + Byte allocaDummy[0x180]; + int i = 0; + for (i = 0; i < 16; i++) + allocaDummy[i] = (Byte)i; + BtThreadFunc((CMatchFinderMt *)p); + return 0; +} + +SRes MatchFinderMt_Create(CMatchFinderMt *p, UInt32 historySize, UInt32 keepAddBufferBefore, + UInt32 matchMaxLen, UInt32 keepAddBufferAfter, ISzAlloc *alloc) +{ + CMatchFinder *mf = p->MatchFinder; + p->historySize = historySize; + if (kMtBtBlockSize <= matchMaxLen * 4) + return SZ_ERROR_PARAM; + if (p->hashBuf == 0) + { + p->hashBuf = (UInt32 *)alloc->Alloc(alloc, (kHashBufferSize + kBtBufferSize) * sizeof(UInt32)); + if (p->hashBuf == 0) + return SZ_ERROR_MEM; + p->btBuf = p->hashBuf + kHashBufferSize; + } + keepAddBufferBefore += (kHashBufferSize + kBtBufferSize); + keepAddBufferAfter += kMtHashBlockSize; + if (!MatchFinder_Create(mf, historySize, keepAddBufferBefore, matchMaxLen, keepAddBufferAfter, alloc)) + return SZ_ERROR_MEM; + + RINOK(MtSync_Create(&p->hashSync, HashThreadFunc2, p, kMtHashNumBlocks)); + RINOK(MtSync_Create(&p->btSync, BtThreadFunc2, p, kMtBtNumBlocks)); + return SZ_OK; +} + +/* Call it after ReleaseStream / SetStream */ +void MatchFinderMt_Init(CMatchFinderMt *p) +{ + CMatchFinder *mf = p->MatchFinder; + p->btBufPos = p->btBufPosLimit = 0; + p->hashBufPos = p->hashBufPosLimit = 0; + MatchFinder_Init(mf); + p->pointerToCurPos = MatchFinder_GetPointerToCurrentPos(mf); + p->btNumAvailBytes = 0; + p->lzPos = p->historySize + 1; + + p->hash = mf->hash; + p->fixedHashSize = mf->fixedHashSize; + p->crc = mf->crc; + + p->son = mf->son; + p->matchMaxLen = mf->matchMaxLen; + p->numHashBytes = mf->numHashBytes; + p->pos = mf->pos; + p->buffer = mf->buffer; + p->cyclicBufferPos = mf->cyclicBufferPos; + p->cyclicBufferSize = mf->cyclicBufferSize; + p->cutValue = mf->cutValue; +} + +/* ReleaseStream is required to finish multithreading */ +void MatchFinderMt_ReleaseStream(CMatchFinderMt *p) +{ + MtSync_StopWriting(&p->btSync); + /* p->MatchFinder->ReleaseStream(); */ +} + +void MatchFinderMt_Normalize(CMatchFinderMt *p) +{ + MatchFinder_Normalize3(p->lzPos - p->historySize - 1, p->hash, p->fixedHashSize); + p->lzPos = p->historySize + 1; +} + +void MatchFinderMt_GetNextBlock_Bt(CMatchFinderMt *p) +{ + UInt32 blockIndex; + MtSync_GetNextBlock(&p->btSync); + blockIndex = ((p->btSync.numProcessedBlocks - 1) & kMtBtNumBlocksMask); + p->btBufPosLimit = p->btBufPos = blockIndex * kMtBtBlockSize; + p->btBufPosLimit += p->btBuf[p->btBufPos++]; + p->btNumAvailBytes = p->btBuf[p->btBufPos++]; + if (p->lzPos >= kMtMaxValForNormalize - kMtBtBlockSize) + MatchFinderMt_Normalize(p); +} + +const Byte * MatchFinderMt_GetPointerToCurrentPos(CMatchFinderMt *p) +{ + return p->pointerToCurPos; +} + +#define GET_NEXT_BLOCK_IF_REQUIRED if (p->btBufPos == p->btBufPosLimit) MatchFinderMt_GetNextBlock_Bt(p); + +UInt32 MatchFinderMt_GetNumAvailableBytes(CMatchFinderMt *p) +{ + GET_NEXT_BLOCK_IF_REQUIRED; + return p->btNumAvailBytes; +} + +Byte MatchFinderMt_GetIndexByte(CMatchFinderMt *p, Int32 index) +{ + return p->pointerToCurPos[index]; +} + +UInt32 * MixMatches2(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *distances) +{ + UInt32 hash2Value, curMatch2; + UInt32 *hash = p->hash; + const Byte *cur = p->pointerToCurPos; + UInt32 lzPos = p->lzPos; + MT_HASH2_CALC + + curMatch2 = hash[hash2Value]; + hash[hash2Value] = lzPos; + + if (curMatch2 >= matchMinPos) + if (cur[(ptrdiff_t)curMatch2 - lzPos] == cur[0]) + { + *distances++ = 2; + *distances++ = lzPos - curMatch2 - 1; + } + return distances; +} + +UInt32 * MixMatches3(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *distances) +{ + UInt32 hash2Value, hash3Value, curMatch2, curMatch3; + UInt32 *hash = p->hash; + const Byte *cur = p->pointerToCurPos; + UInt32 lzPos = p->lzPos; + MT_HASH3_CALC + + curMatch2 = hash[ hash2Value]; + curMatch3 = hash[kFix3HashSize + hash3Value]; + + hash[ hash2Value] = + hash[kFix3HashSize + hash3Value] = + lzPos; + + if (curMatch2 >= matchMinPos && cur[(ptrdiff_t)curMatch2 - lzPos] == cur[0]) + { + distances[1] = lzPos - curMatch2 - 1; + if (cur[(ptrdiff_t)curMatch2 - lzPos + 2] == cur[2]) + { + distances[0] = 3; + return distances + 2; + } + distances[0] = 2; + distances += 2; + } + if (curMatch3 >= matchMinPos && cur[(ptrdiff_t)curMatch3 - lzPos] == cur[0]) + { + *distances++ = 3; + *distances++ = lzPos - curMatch3 - 1; + } + return distances; +} + +/* +UInt32 *MixMatches4(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *distances) +{ + UInt32 hash2Value, hash3Value, hash4Value, curMatch2, curMatch3, curMatch4; + UInt32 *hash = p->hash; + const Byte *cur = p->pointerToCurPos; + UInt32 lzPos = p->lzPos; + MT_HASH4_CALC + + curMatch2 = hash[ hash2Value]; + curMatch3 = hash[kFix3HashSize + hash3Value]; + curMatch4 = hash[kFix4HashSize + hash4Value]; + + hash[ hash2Value] = + hash[kFix3HashSize + hash3Value] = + hash[kFix4HashSize + hash4Value] = + lzPos; + + if (curMatch2 >= matchMinPos && cur[(ptrdiff_t)curMatch2 - lzPos] == cur[0]) + { + distances[1] = lzPos - curMatch2 - 1; + if (cur[(ptrdiff_t)curMatch2 - lzPos + 2] == cur[2]) + { + distances[0] = (cur[(ptrdiff_t)curMatch2 - lzPos + 3] == cur[3]) ? 4 : 3; + return distances + 2; + } + distances[0] = 2; + distances += 2; + } + if (curMatch3 >= matchMinPos && cur[(ptrdiff_t)curMatch3 - lzPos] == cur[0]) + { + distances[1] = lzPos - curMatch3 - 1; + if (cur[(ptrdiff_t)curMatch3 - lzPos + 3] == cur[3]) + { + distances[0] = 4; + return distances + 2; + } + distances[0] = 3; + distances += 2; + } + + if (curMatch4 >= matchMinPos) + if ( + cur[(ptrdiff_t)curMatch4 - lzPos] == cur[0] && + cur[(ptrdiff_t)curMatch4 - lzPos + 3] == cur[3] + ) + { + *distances++ = 4; + *distances++ = lzPos - curMatch4 - 1; + } + return distances; +} +*/ + +#define INCREASE_LZ_POS p->lzPos++; p->pointerToCurPos++; + +UInt32 MatchFinderMt2_GetMatches(CMatchFinderMt *p, UInt32 *distances) +{ + const UInt32 *btBuf = p->btBuf + p->btBufPos; + UInt32 len = *btBuf++; + p->btBufPos += 1 + len; + p->btNumAvailBytes--; + { + UInt32 i; + for (i = 0; i < len; i += 2) + { + *distances++ = *btBuf++; + *distances++ = *btBuf++; + } + } + INCREASE_LZ_POS + return len; +} + +UInt32 MatchFinderMt_GetMatches(CMatchFinderMt *p, UInt32 *distances) +{ + const UInt32 *btBuf = p->btBuf + p->btBufPos; + UInt32 len = *btBuf++; + p->btBufPos += 1 + len; + + if (len == 0) + { + if (p->btNumAvailBytes-- >= 4) + len = (UInt32)(p->MixMatchesFunc(p, p->lzPos - p->historySize, distances) - (distances)); + } + else + { + /* Condition: there are matches in btBuf with length < p->numHashBytes */ + UInt32 *distances2; + p->btNumAvailBytes--; + distances2 = p->MixMatchesFunc(p, p->lzPos - btBuf[1], distances); + do + { + *distances2++ = *btBuf++; + *distances2++ = *btBuf++; + } + while ((len -= 2) != 0); + len = (UInt32)(distances2 - (distances)); + } + INCREASE_LZ_POS + return len; +} + +#define SKIP_HEADER2 do { GET_NEXT_BLOCK_IF_REQUIRED +#define SKIP_HEADER(n) SKIP_HEADER2 if (p->btNumAvailBytes-- >= (n)) { const Byte *cur = p->pointerToCurPos; UInt32 *hash = p->hash; +#define SKIP_FOOTER } INCREASE_LZ_POS p->btBufPos += p->btBuf[p->btBufPos] + 1; } while (--num != 0); + +void MatchFinderMt0_Skip(CMatchFinderMt *p, UInt32 num) +{ + SKIP_HEADER2 { p->btNumAvailBytes--; + SKIP_FOOTER +} + +void MatchFinderMt2_Skip(CMatchFinderMt *p, UInt32 num) +{ + SKIP_HEADER(2) + UInt32 hash2Value; + MT_HASH2_CALC + hash[hash2Value] = p->lzPos; + SKIP_FOOTER +} + +void MatchFinderMt3_Skip(CMatchFinderMt *p, UInt32 num) +{ + SKIP_HEADER(3) + UInt32 hash2Value, hash3Value; + MT_HASH3_CALC + hash[kFix3HashSize + hash3Value] = + hash[ hash2Value] = + p->lzPos; + SKIP_FOOTER +} + +/* +void MatchFinderMt4_Skip(CMatchFinderMt *p, UInt32 num) +{ + SKIP_HEADER(4) + UInt32 hash2Value, hash3Value, hash4Value; + MT_HASH4_CALC + hash[kFix4HashSize + hash4Value] = + hash[kFix3HashSize + hash3Value] = + hash[ hash2Value] = + p->lzPos; + SKIP_FOOTER +} +*/ + +void MatchFinderMt_CreateVTable(CMatchFinderMt *p, IMatchFinder *vTable) +{ + vTable->Init = (Mf_Init_Func)MatchFinderMt_Init; + vTable->GetIndexByte = (Mf_GetIndexByte_Func)MatchFinderMt_GetIndexByte; + vTable->GetNumAvailableBytes = (Mf_GetNumAvailableBytes_Func)MatchFinderMt_GetNumAvailableBytes; + vTable->GetPointerToCurrentPos = (Mf_GetPointerToCurrentPos_Func)MatchFinderMt_GetPointerToCurrentPos; + vTable->GetMatches = (Mf_GetMatches_Func)MatchFinderMt_GetMatches; + switch(p->MatchFinder->numHashBytes) + { + case 2: + p->GetHeadsFunc = GetHeads2; + p->MixMatchesFunc = (Mf_Mix_Matches)0; + vTable->Skip = (Mf_Skip_Func)MatchFinderMt0_Skip; + vTable->GetMatches = (Mf_GetMatches_Func)MatchFinderMt2_GetMatches; + break; + case 3: + p->GetHeadsFunc = GetHeads3; + p->MixMatchesFunc = (Mf_Mix_Matches)MixMatches2; + vTable->Skip = (Mf_Skip_Func)MatchFinderMt2_Skip; + break; + default: + /* case 4: */ + p->GetHeadsFunc = p->MatchFinder->bigHash ? GetHeads4b : GetHeads4; + /* p->GetHeadsFunc = GetHeads4; */ + p->MixMatchesFunc = (Mf_Mix_Matches)MixMatches3; + vTable->Skip = (Mf_Skip_Func)MatchFinderMt3_Skip; + break; + /* + default: + p->GetHeadsFunc = GetHeads5; + p->MixMatchesFunc = (Mf_Mix_Matches)MixMatches4; + vTable->Skip = (Mf_Skip_Func)MatchFinderMt4_Skip; + break; + */ + } +} diff --git a/BaseTools/Source/C/LzmaCompress/Sdk/C/LzFindMt.h b/BaseTools/Source/C/LzmaCompress/Sdk/C/LzFindMt.h new file mode 100644 index 0000000000..b7ead2d472 --- /dev/null +++ b/BaseTools/Source/C/LzmaCompress/Sdk/C/LzFindMt.h @@ -0,0 +1,97 @@ +/* LzFindMt.h -- multithreaded Match finder for LZ algorithms +2008-10-04 : Igor Pavlov : Public domain */ + +#ifndef __LZFINDMT_H +#define __LZFINDMT_H + +#include "Threads.h" +#include "LzFind.h" + +#define kMtHashBlockSize (1 << 13) +#define kMtHashNumBlocks (1 << 3) +#define kMtHashNumBlocksMask (kMtHashNumBlocks - 1) + +#define kMtBtBlockSize (1 << 14) +#define kMtBtNumBlocks (1 << 6) +#define kMtBtNumBlocksMask (kMtBtNumBlocks - 1) + +typedef struct _CMtSync +{ + Bool wasCreated; + Bool needStart; + Bool exit; + Bool stopWriting; + + CThread thread; + CAutoResetEvent canStart; + CAutoResetEvent wasStarted; + CAutoResetEvent wasStopped; + CSemaphore freeSemaphore; + CSemaphore filledSemaphore; + Bool csWasInitialized; + Bool csWasEntered; + CCriticalSection cs; + UInt32 numProcessedBlocks; +} CMtSync; + +typedef UInt32 * (*Mf_Mix_Matches)(void *p, UInt32 matchMinPos, UInt32 *distances); + +/* kMtCacheLineDummy must be >= size_of_CPU_cache_line */ +#define kMtCacheLineDummy 128 + +typedef void (*Mf_GetHeads)(const Byte *buffer, UInt32 pos, + UInt32 *hash, UInt32 hashMask, UInt32 *heads, UInt32 numHeads, const UInt32 *crc); + +typedef struct _CMatchFinderMt +{ + /* LZ */ + const Byte *pointerToCurPos; + UInt32 *btBuf; + UInt32 btBufPos; + UInt32 btBufPosLimit; + UInt32 lzPos; + UInt32 btNumAvailBytes; + + UInt32 *hash; + UInt32 fixedHashSize; + UInt32 historySize; + const UInt32 *crc; + + Mf_Mix_Matches MixMatchesFunc; + + /* LZ + BT */ + CMtSync btSync; + Byte btDummy[kMtCacheLineDummy]; + + /* BT */ + UInt32 *hashBuf; + UInt32 hashBufPos; + UInt32 hashBufPosLimit; + UInt32 hashNumAvail; + + CLzRef *son; + UInt32 matchMaxLen; + UInt32 numHashBytes; + UInt32 pos; + Byte *buffer; + UInt32 cyclicBufferPos; + UInt32 cyclicBufferSize; /* it must be historySize + 1 */ + UInt32 cutValue; + + /* BT + Hash */ + CMtSync hashSync; + /* Byte hashDummy[kMtCacheLineDummy]; */ + + /* Hash */ + Mf_GetHeads GetHeadsFunc; + CMatchFinder *MatchFinder; +} CMatchFinderMt; + +void MatchFinderMt_Construct(CMatchFinderMt *p); +void MatchFinderMt_Destruct(CMatchFinderMt *p, ISzAlloc *alloc); +SRes MatchFinderMt_Create(CMatchFinderMt *p, UInt32 historySize, UInt32 keepAddBufferBefore, + UInt32 matchMaxLen, UInt32 keepAddBufferAfter, ISzAlloc *alloc); +void MatchFinderMt_CreateVTable(CMatchFinderMt *p, IMatchFinder *vTable); +void MatchFinderMt_ReleaseStream(CMatchFinderMt *p); + +#endif diff --git a/BaseTools/Source/C/LzmaCompress/Sdk/C/LzHash.h b/BaseTools/Source/C/LzmaCompress/Sdk/C/LzHash.h new file mode 100644 index 0000000000..c923417501 --- /dev/null +++ b/BaseTools/Source/C/LzmaCompress/Sdk/C/LzHash.h @@ -0,0 +1,54 @@ +/* LzHash.h -- HASH functions for LZ algorithms +2008-10-04 : Igor Pavlov : Public domain */ + +#ifndef __LZHASH_H +#define __LZHASH_H + +#define kHash2Size (1 << 10) +#define kHash3Size (1 << 16) +#define kHash4Size (1 << 20) + +#define kFix3HashSize (kHash2Size) +#define kFix4HashSize (kHash2Size + kHash3Size) +#define kFix5HashSize (kHash2Size + kHash3Size + kHash4Size) + +#define HASH2_CALC hashValue = cur[0] | ((UInt32)cur[1] << 8); + +#define HASH3_CALC { \ + UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ + hash2Value = temp & (kHash2Size - 1); \ + hashValue = (temp ^ ((UInt32)cur[2] << 8)) & p->hashMask; } + +#define HASH4_CALC { \ + UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ + hash2Value = temp & (kHash2Size - 1); \ + hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \ + hashValue = (temp ^ ((UInt32)cur[2] << 8) ^ (p->crc[cur[3]] << 5)) & p->hashMask; } + +#define HASH5_CALC { \ + UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ + hash2Value = temp & (kHash2Size - 1); \ + hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \ + hash4Value = (temp ^ ((UInt32)cur[2] << 8) ^ (p->crc[cur[3]] << 5)); \ + hashValue = (hash4Value ^ (p->crc[cur[4]] << 3)) & p->hashMask; \ + hash4Value &= (kHash4Size - 1); } + +/* #define HASH_ZIP_CALC hashValue = ((cur[0] | ((UInt32)cur[1] << 8)) ^ p->crc[cur[2]]) & 0xFFFF; */ +#define HASH_ZIP_CALC hashValue = ((cur[2] | ((UInt32)cur[0] << 8)) ^ p->crc[cur[1]]) & 0xFFFF; + + +#define MT_HASH2_CALC \ + hash2Value = (p->crc[cur[0]] ^ cur[1]) & (kHash2Size - 1); + +#define MT_HASH3_CALC { \ + UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ + hash2Value = temp & (kHash2Size - 1); \ + hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); } + +#define MT_HASH4_CALC { \ + UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ + hash2Value = temp & (kHash2Size - 1); \ + hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \ + hash4Value = (temp ^ ((UInt32)cur[2] << 8) ^ (p->crc[cur[3]] << 5)) & (kHash4Size - 1); } + +#endif diff --git a/BaseTools/Source/C/LzmaCompress/Sdk/C/LzmaDec.c b/BaseTools/Source/C/LzmaCompress/Sdk/C/LzmaDec.c new file mode 100644 index 0000000000..eb5250174b --- /dev/null +++ b/BaseTools/Source/C/LzmaCompress/Sdk/C/LzmaDec.c @@ -0,0 +1,1007 @@ +/* LzmaDec.c -- LZMA Decoder +2008-11-06 : Igor Pavlov : Public domain */ + +#include "LzmaDec.h" + +#include + +#define kNumTopBits 24 +#define kTopValue ((UInt32)1 << kNumTopBits) + +#define kNumBitModelTotalBits 11 +#define kBitModelTotal (1 << kNumBitModelTotalBits) +#define kNumMoveBits 5 + +#define RC_INIT_SIZE 5 + +#define NORMALIZE if (range < kTopValue) { range <<= 8; code = (code << 8) | (*buf++); } + +#define IF_BIT_0(p) ttt = *(p); NORMALIZE; bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound) +#define UPDATE_0(p) range = bound; *(p) = (CLzmaProb)(ttt + ((kBitModelTotal - ttt) >> kNumMoveBits)); +#define UPDATE_1(p) range -= bound; code -= bound; *(p) = (CLzmaProb)(ttt - (ttt >> kNumMoveBits)); +#define GET_BIT2(p, i, A0, A1) IF_BIT_0(p) \ + { UPDATE_0(p); i = (i + i); A0; } else \ + { UPDATE_1(p); i = (i + i) + 1; A1; } +#define GET_BIT(p, i) GET_BIT2(p, i, ; , ;) + +#define TREE_GET_BIT(probs, i) { GET_BIT((probs + i), i); } +#define TREE_DECODE(probs, limit, i) \ + { i = 1; do { TREE_GET_BIT(probs, i); } while (i < limit); i -= limit; } + +/* #define _LZMA_SIZE_OPT */ + +#ifdef _LZMA_SIZE_OPT +#define TREE_6_DECODE(probs, i) TREE_DECODE(probs, (1 << 6), i) +#else +#define TREE_6_DECODE(probs, i) \ + { i = 1; \ + TREE_GET_BIT(probs, i); \ + TREE_GET_BIT(probs, i); \ + TREE_GET_BIT(probs, i); \ + TREE_GET_BIT(probs, i); \ + TREE_GET_BIT(probs, i); \ + TREE_GET_BIT(probs, i); \ + i -= 0x40; } +#endif + +#define NORMALIZE_CHECK if (range < kTopValue) { if (buf >= bufLimit) return DUMMY_ERROR; range <<= 8; code = (code << 8) | (*buf++); } + +#define IF_BIT_0_CHECK(p) ttt = *(p); NORMALIZE_CHECK; bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound) +#define UPDATE_0_CHECK range = bound; +#define UPDATE_1_CHECK range -= bound; code -= bound; +#define GET_BIT2_CHECK(p, i, A0, A1) IF_BIT_0_CHECK(p) \ + { UPDATE_0_CHECK; i = (i + i); A0; } else \ + { UPDATE_1_CHECK; i = (i + i) + 1; A1; } +#define GET_BIT_CHECK(p, i) GET_BIT2_CHECK(p, i, ; , ;) +#define TREE_DECODE_CHECK(probs, limit, i) \ + { i = 1; do { GET_BIT_CHECK(probs + i, i) } while (i < limit); i -= limit; } + + +#define kNumPosBitsMax 4 +#define kNumPosStatesMax (1 << kNumPosBitsMax) + +#define kLenNumLowBits 3 +#define kLenNumLowSymbols (1 << kLenNumLowBits) +#define kLenNumMidBits 3 +#define kLenNumMidSymbols (1 << kLenNumMidBits) +#define kLenNumHighBits 8 +#define kLenNumHighSymbols (1 << kLenNumHighBits) + +#define LenChoice 0 +#define LenChoice2 (LenChoice + 1) +#define LenLow (LenChoice2 + 1) +#define LenMid (LenLow + (kNumPosStatesMax << kLenNumLowBits)) +#define LenHigh (LenMid + (kNumPosStatesMax << kLenNumMidBits)) +#define kNumLenProbs (LenHigh + kLenNumHighSymbols) + + +#define kNumStates 12 +#define kNumLitStates 7 + +#define kStartPosModelIndex 4 +#define kEndPosModelIndex 14 +#define kNumFullDistances (1 << (kEndPosModelIndex >> 1)) + +#define kNumPosSlotBits 6 +#define kNumLenToPosStates 4 + +#define kNumAlignBits 4 +#define kAlignTableSize (1 << kNumAlignBits) + +#define kMatchMinLen 2 +#define kMatchSpecLenStart (kMatchMinLen + kLenNumLowSymbols + kLenNumMidSymbols + kLenNumHighSymbols) + +#define IsMatch 0 +#define IsRep (IsMatch + (kNumStates << kNumPosBitsMax)) +#define IsRepG0 (IsRep + kNumStates) +#define IsRepG1 (IsRepG0 + kNumStates) +#define IsRepG2 (IsRepG1 + kNumStates) +#define IsRep0Long (IsRepG2 + kNumStates) +#define PosSlot (IsRep0Long + (kNumStates << kNumPosBitsMax)) +#define SpecPos (PosSlot + (kNumLenToPosStates << kNumPosSlotBits)) +#define Align (SpecPos + kNumFullDistances - kEndPosModelIndex) +#define LenCoder (Align + kAlignTableSize) +#define RepLenCoder (LenCoder + kNumLenProbs) +#define Literal (RepLenCoder + kNumLenProbs) + +#define LZMA_BASE_SIZE 1846 +#define LZMA_LIT_SIZE 768 + +#define LzmaProps_GetNumProbs(p) ((UInt32)LZMA_BASE_SIZE + (LZMA_LIT_SIZE << ((p)->lc + (p)->lp))) + +#if Literal != LZMA_BASE_SIZE +StopCompilingDueBUG +#endif + +static const Byte kLiteralNextStates[kNumStates * 2] = +{ + 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 4, 5, + 7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10 +}; + +#define LZMA_DIC_MIN (1 << 12) + +/* First LZMA-symbol is always decoded. +And it decodes new LZMA-symbols while (buf < bufLimit), but "buf" is without last normalization +Out: + Result: + SZ_OK - OK + SZ_ERROR_DATA - Error + p->remainLen: + < kMatchSpecLenStart : normal remain + = kMatchSpecLenStart : finished + = kMatchSpecLenStart + 1 : Flush marker + = kMatchSpecLenStart + 2 : State Init Marker +*/ + +static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte *bufLimit) +{ + CLzmaProb *probs = p->probs; + + unsigned state = p->state; + UInt32 rep0 = p->reps[0], rep1 = p->reps[1], rep2 = p->reps[2], rep3 = p->reps[3]; + unsigned pbMask = ((unsigned)1 << (p->prop.pb)) - 1; + unsigned lpMask = ((unsigned)1 << (p->prop.lp)) - 1; + unsigned lc = p->prop.lc; + + Byte *dic = p->dic; + SizeT dicBufSize = p->dicBufSize; + SizeT dicPos = p->dicPos; + + UInt32 processedPos = p->processedPos; + UInt32 checkDicSize = p->checkDicSize; + unsigned len = 0; + + const Byte *buf = p->buf; + UInt32 range = p->range; + UInt32 code = p->code; + + do + { + CLzmaProb *prob; + UInt32 bound; + unsigned ttt; + unsigned posState = processedPos & pbMask; + + prob = probs + IsMatch + (state << kNumPosBitsMax) + posState; + IF_BIT_0(prob) + { + unsigned symbol; + UPDATE_0(prob); + prob = probs + Literal; + if (checkDicSize != 0 || processedPos != 0) + prob += (LZMA_LIT_SIZE * (((processedPos & lpMask) << lc) + + (dic[(dicPos == 0 ? dicBufSize : dicPos) - 1] >> (8 - lc)))); + + if (state < kNumLitStates) + { + symbol = 1; + do { GET_BIT(prob + symbol, symbol) } while (symbol < 0x100); + } + else + { + unsigned matchByte = p->dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)]; + unsigned offs = 0x100; + symbol = 1; + do + { + unsigned bit; + CLzmaProb *probLit; + matchByte <<= 1; + bit = (matchByte & offs); + probLit = prob + offs + bit + symbol; + GET_BIT2(probLit, symbol, offs &= ~bit, offs &= bit) + } + while (symbol < 0x100); + } + dic[dicPos++] = (Byte)symbol; + processedPos++; + + state = kLiteralNextStates[state]; + /* if (state < 4) state = 0; else if (state < 10) state -= 3; else state -= 6; */ + continue; + } + else + { + UPDATE_1(prob); + prob = probs + IsRep + state; + IF_BIT_0(prob) + { + UPDATE_0(prob); + state += kNumStates; + prob = probs + LenCoder; + } + else + { + UPDATE_1(prob); + if (checkDicSize == 0 && processedPos == 0) + return SZ_ERROR_DATA; + prob = probs + IsRepG0 + state; + IF_BIT_0(prob) + { + UPDATE_0(prob); + prob = probs + IsRep0Long + (state << kNumPosBitsMax) + posState; + IF_BIT_0(prob) + { + UPDATE_0(prob); + dic[dicPos] = dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)]; + dicPos++; + processedPos++; + state = state < kNumLitStates ? 9 : 11; + continue; + } + UPDATE_1(prob); + } + else + { + UInt32 distance; + UPDATE_1(prob); + prob = probs + IsRepG1 + state; + IF_BIT_0(prob) + { + UPDATE_0(prob); + distance = rep1; + } + else + { + UPDATE_1(prob); + prob = probs + IsRepG2 + state; + IF_BIT_0(prob) + { + UPDATE_0(prob); + distance = rep2; + } + else + { + UPDATE_1(prob); + distance = rep3; + rep3 = rep2; + } + rep2 = rep1; + } + rep1 = rep0; + rep0 = distance; + } + state = state < kNumLitStates ? 8 : 11; + prob = probs + RepLenCoder; + } + { + unsigned limit, offset; + CLzmaProb *probLen = prob + LenChoice; + IF_BIT_0(probLen) + { + UPDATE_0(probLen); + probLen = prob + LenLow + (posState << kLenNumLowBits); + offset = 0; + limit = (1 << kLenNumLowBits); + } + else + { + UPDATE_1(probLen); + probLen = prob + LenChoice2; + IF_BIT_0(probLen) + { + UPDATE_0(probLen); + probLen = prob + LenMid + (posState << kLenNumMidBits); + offset = kLenNumLowSymbols; + limit = (1 << kLenNumMidBits); + } + else + { + UPDATE_1(probLen); + probLen = prob + LenHigh; + offset = kLenNumLowSymbols + kLenNumMidSymbols; + limit = (1 << kLenNumHighBits); + } + } + TREE_DECODE(probLen, limit, len); + len += offset; + } + + if (state >= kNumStates) + { + UInt32 distance; + prob = probs + PosSlot + + ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) << kNumPosSlotBits); + TREE_6_DECODE(prob, distance); + if (distance >= kStartPosModelIndex) + { + unsigned posSlot = (unsigned)distance; + int numDirectBits = (int)(((distance >> 1) - 1)); + distance = (2 | (distance & 1)); + if (posSlot < kEndPosModelIndex) + { + distance <<= numDirectBits; + prob = probs + SpecPos + distance - posSlot - 1; + { + UInt32 mask = 1; + unsigned i = 1; + do + { + GET_BIT2(prob + i, i, ; , distance |= mask); + mask <<= 1; + } + while (--numDirectBits != 0); + } + } + else + { + numDirectBits -= kNumAlignBits; + do + { + NORMALIZE + range >>= 1; + + { + UInt32 t; + code -= range; + t = (0 - ((UInt32)code >> 31)); /* (UInt32)((Int32)code >> 31) */ + distance = (distance << 1) + (t + 1); + code += range & t; + } + /* + distance <<= 1; + if (code >= range) + { + code -= range; + distance |= 1; + } + */ + } + while (--numDirectBits != 0); + prob = probs + Align; + distance <<= kNumAlignBits; + { + unsigned i = 1; + GET_BIT2(prob + i, i, ; , distance |= 1); + GET_BIT2(prob + i, i, ; , distance |= 2); + GET_BIT2(prob + i, i, ; , distance |= 4); + GET_BIT2(prob + i, i, ; , distance |= 8); + } + if (distance == (UInt32)0xFFFFFFFF) + { + len += kMatchSpecLenStart; + state -= kNumStates; + break; + } + } + } + rep3 = rep2; + rep2 = rep1; + rep1 = rep0; + rep0 = distance + 1; + if (checkDicSize == 0) + { + if (distance >= processedPos) + return SZ_ERROR_DATA; + } + else if (distance >= checkDicSize) + return SZ_ERROR_DATA; + state = (state < kNumStates + kNumLitStates) ? kNumLitStates : kNumLitStates + 3; + /* state = kLiteralNextStates[state]; */ + } + + len += kMatchMinLen; + + if (limit == dicPos) + return SZ_ERROR_DATA; + { + SizeT rem = limit - dicPos; + unsigned curLen = ((rem < len) ? (unsigned)rem : len); + SizeT pos = (dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0); + + processedPos += curLen; + + len -= curLen; + if (pos + curLen <= dicBufSize) + { + Byte *dest = dic + dicPos; + ptrdiff_t src = (ptrdiff_t)pos - (ptrdiff_t)dicPos; + const Byte *lim = dest + curLen; + dicPos += curLen; + do + *(dest) = (Byte)*(dest + src); + while (++dest != lim); + } + else + { + do + { + dic[dicPos++] = dic[pos]; + if (++pos == dicBufSize) + pos = 0; + } + while (--curLen != 0); + } + } + } + } + while (dicPos < limit && buf < bufLimit); + NORMALIZE; + p->buf = buf; + p->range = range; + p->code = code; + p->remainLen = len; + p->dicPos = dicPos; + p->processedPos = processedPos; + p->reps[0] = rep0; + p->reps[1] = rep1; + p->reps[2] = rep2; + p->reps[3] = rep3; + p->state = state; + + return SZ_OK; +} + +static void MY_FAST_CALL LzmaDec_WriteRem(CLzmaDec *p, SizeT limit) +{ + if (p->remainLen != 0 && p->remainLen < kMatchSpecLenStart) + { + Byte *dic = p->dic; + SizeT dicPos = p->dicPos; + SizeT dicBufSize = p->dicBufSize; + unsigned len = p->remainLen; + UInt32 rep0 = p->reps[0]; + if (limit - dicPos < len) + len = (unsigned)(limit - dicPos); + + if (p->checkDicSize == 0 && p->prop.dicSize - p->processedPos <= len) + p->checkDicSize = p->prop.dicSize; + + p->processedPos += len; + p->remainLen -= len; + while (len-- != 0) + { + dic[dicPos] = dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)]; + dicPos++; + } + p->dicPos = dicPos; + } +} + +static int MY_FAST_CALL LzmaDec_DecodeReal2(CLzmaDec *p, SizeT limit, const Byte *bufLimit) +{ + do + { + SizeT limit2 = limit; + if (p->checkDicSize == 0) + { + UInt32 rem = p->prop.dicSize - p->processedPos; + if (limit - p->dicPos > rem) + limit2 = p->dicPos + rem; + } + RINOK(LzmaDec_DecodeReal(p, limit2, bufLimit)); + if (p->processedPos >= p->prop.dicSize) + p->checkDicSize = p->prop.dicSize; + LzmaDec_WriteRem(p, limit); + } + while (p->dicPos < limit && p->buf < bufLimit && p->remainLen < kMatchSpecLenStart); + + if (p->remainLen > kMatchSpecLenStart) + { + p->remainLen = kMatchSpecLenStart; + } + return 0; +} + +typedef enum +{ + DUMMY_ERROR, /* unexpected end of input stream */ + DUMMY_LIT, + DUMMY_MATCH, + DUMMY_REP +} ELzmaDummy; + +static ELzmaDummy LzmaDec_TryDummy(const CLzmaDec *p, const Byte *buf, SizeT inSize) +{ + UInt32 range = p->range; + UInt32 code = p->code; + const Byte *bufLimit = buf + inSize; + CLzmaProb *probs = p->probs; + unsigned state = p->state; + ELzmaDummy res; + + { + CLzmaProb *prob; + UInt32 bound; + unsigned ttt; + unsigned posState = (p->processedPos) & ((1 << p->prop.pb) - 1); + + prob = probs + IsMatch + (state << kNumPosBitsMax) + posState; + IF_BIT_0_CHECK(prob) + { + UPDATE_0_CHECK + + /* if (bufLimit - buf >= 7) return DUMMY_LIT; */ + + prob = probs + Literal; + if (p->checkDicSize != 0 || p->processedPos != 0) + prob += (LZMA_LIT_SIZE * + ((((p->processedPos) & ((1 << (p->prop.lp)) - 1)) << p->prop.lc) + + (p->dic[(p->dicPos == 0 ? p->dicBufSize : p->dicPos) - 1] >> (8 - p->prop.lc)))); + + if (state < kNumLitStates) + { + unsigned symbol = 1; + do { GET_BIT_CHECK(prob + symbol, symbol) } while (symbol < 0x100); + } + else + { + unsigned matchByte = p->dic[p->dicPos - p->reps[0] + + ((p->dicPos < p->reps[0]) ? p->dicBufSize : 0)]; + unsigned offs = 0x100; + unsigned symbol = 1; + do + { + unsigned bit; + CLzmaProb *probLit; + matchByte <<= 1; + bit = (matchByte & offs); + probLit = prob + offs + bit + symbol; + GET_BIT2_CHECK(probLit, symbol, offs &= ~bit, offs &= bit) + } + while (symbol < 0x100); + } + res = DUMMY_LIT; + } + else + { + unsigned len; + UPDATE_1_CHECK; + + prob = probs + IsRep + state; + IF_BIT_0_CHECK(prob) + { + UPDATE_0_CHECK; + state = 0; + prob = probs + LenCoder; + res = DUMMY_MATCH; + } + else + { + UPDATE_1_CHECK; + res = DUMMY_REP; + prob = probs + IsRepG0 + state; + IF_BIT_0_CHECK(prob) + { + UPDATE_0_CHECK; + prob = probs + IsRep0Long + (state << kNumPosBitsMax) + posState; + IF_BIT_0_CHECK(prob) + { + UPDATE_0_CHECK; + NORMALIZE_CHECK; + return DUMMY_REP; + } + else + { + UPDATE_1_CHECK; + } + } + else + { + UPDATE_1_CHECK; + prob = probs + IsRepG1 + state; + IF_BIT_0_CHECK(prob) + { + UPDATE_0_CHECK; + } + else + { + UPDATE_1_CHECK; + prob = probs + IsRepG2 + state; + IF_BIT_0_CHECK(prob) + { + UPDATE_0_CHECK; + } + else + { + UPDATE_1_CHECK; + } + } + } + state = kNumStates; + prob = probs + RepLenCoder; + } + { + unsigned limit, offset; + CLzmaProb *probLen = prob + LenChoice; + IF_BIT_0_CHECK(probLen) + { + UPDATE_0_CHECK; + probLen = prob + LenLow + (posState << kLenNumLowBits); + offset = 0; + limit = 1 << kLenNumLowBits; + } + else + { + UPDATE_1_CHECK; + probLen = prob + LenChoice2; + IF_BIT_0_CHECK(probLen) + { + UPDATE_0_CHECK; + probLen = prob + LenMid + (posState << kLenNumMidBits); + offset = kLenNumLowSymbols; + limit = 1 << kLenNumMidBits; + } + else + { + UPDATE_1_CHECK; + probLen = prob + LenHigh; + offset = kLenNumLowSymbols + kLenNumMidSymbols; + limit = 1 << kLenNumHighBits; + } + } + TREE_DECODE_CHECK(probLen, limit, len); + len += offset; + } + + if (state < 4) + { + unsigned posSlot; + prob = probs + PosSlot + + ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) << + kNumPosSlotBits); + TREE_DECODE_CHECK(prob, 1 << kNumPosSlotBits, posSlot); + if (posSlot >= kStartPosModelIndex) + { + int numDirectBits = ((posSlot >> 1) - 1); + + /* if (bufLimit - buf >= 8) return DUMMY_MATCH; */ + + if (posSlot < kEndPosModelIndex) + { + prob = probs + SpecPos + ((2 | (posSlot & 1)) << numDirectBits) - posSlot - 1; + } + else + { + numDirectBits -= kNumAlignBits; + do + { + NORMALIZE_CHECK + range >>= 1; + code -= range & (((code - range) >> 31) - 1); + /* if (code >= range) code -= range; */ + } + while (--numDirectBits != 0); + prob = probs + Align; + numDirectBits = kNumAlignBits; + } + { + unsigned i = 1; + do + { + GET_BIT_CHECK(prob + i, i); + } + while (--numDirectBits != 0); + } + } + } + } + } + NORMALIZE_CHECK; + return res; +} + + +static void LzmaDec_InitRc(CLzmaDec *p, const Byte *data) +{ + p->code = ((UInt32)data[1] << 24) | ((UInt32)data[2] << 16) | ((UInt32)data[3] << 8) | ((UInt32)data[4]); + p->range = 0xFFFFFFFF; + p->needFlush = 0; +} + +void LzmaDec_InitDicAndState(CLzmaDec *p, Bool initDic, Bool initState) +{ + p->needFlush = 1; + p->remainLen = 0; + p->tempBufSize = 0; + + if (initDic) + { + p->processedPos = 0; + p->checkDicSize = 0; + p->needInitState = 1; + } + if (initState) + p->needInitState = 1; +} + +void LzmaDec_Init(CLzmaDec *p) +{ + p->dicPos = 0; + LzmaDec_InitDicAndState(p, True, True); +} + +static void LzmaDec_InitStateReal(CLzmaDec *p) +{ + UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (p->prop.lc + p->prop.lp)); + UInt32 i; + CLzmaProb *probs = p->probs; + for (i = 0; i < numProbs; i++) + probs[i] = kBitModelTotal >> 1; + p->reps[0] = p->reps[1] = p->reps[2] = p->reps[3] = 1; + p->state = 0; + p->needInitState = 0; +} + +SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, const Byte *src, SizeT *srcLen, + ELzmaFinishMode finishMode, ELzmaStatus *status) +{ + SizeT inSize = *srcLen; + (*srcLen) = 0; + LzmaDec_WriteRem(p, dicLimit); + + *status = LZMA_STATUS_NOT_SPECIFIED; + + while (p->remainLen != kMatchSpecLenStart) + { + int checkEndMarkNow; + + if (p->needFlush != 0) + { + for (; inSize > 0 && p->tempBufSize < RC_INIT_SIZE; (*srcLen)++, inSize--) + p->tempBuf[p->tempBufSize++] = *src++; + if (p->tempBufSize < RC_INIT_SIZE) + { + *status = LZMA_STATUS_NEEDS_MORE_INPUT; + return SZ_OK; + } + if (p->tempBuf[0] != 0) + return SZ_ERROR_DATA; + + LzmaDec_InitRc(p, p->tempBuf); + p->tempBufSize = 0; + } + + checkEndMarkNow = 0; + if (p->dicPos >= dicLimit) + { + if (p->remainLen == 0 && p->code == 0) + { + *status = LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK; + return SZ_OK; + } + if (finishMode == LZMA_FINISH_ANY) + { + *status = LZMA_STATUS_NOT_FINISHED; + return SZ_OK; + } + if (p->remainLen != 0) + { + *status = LZMA_STATUS_NOT_FINISHED; + return SZ_ERROR_DATA; + } + checkEndMarkNow = 1; + } + + if (p->needInitState) + LzmaDec_InitStateReal(p); + + if (p->tempBufSize == 0) + { + SizeT processed; + const Byte *bufLimit; + if (inSize < LZMA_REQUIRED_INPUT_MAX || checkEndMarkNow) + { + int dummyRes = LzmaDec_TryDummy(p, src, inSize); + if (dummyRes == DUMMY_ERROR) + { + memcpy(p->tempBuf, src, inSize); + p->tempBufSize = (unsigned)inSize; + (*srcLen) += inSize; + *status = LZMA_STATUS_NEEDS_MORE_INPUT; + return SZ_OK; + } + if (checkEndMarkNow && dummyRes != DUMMY_MATCH) + { + *status = LZMA_STATUS_NOT_FINISHED; + return SZ_ERROR_DATA; + } + bufLimit = src; + } + else + bufLimit = src + inSize - LZMA_REQUIRED_INPUT_MAX; + p->buf = src; + if (LzmaDec_DecodeReal2(p, dicLimit, bufLimit) != 0) + return SZ_ERROR_DATA; + processed = (SizeT)(p->buf - src); + (*srcLen) += processed; + src += processed; + inSize -= processed; + } + else + { + unsigned rem = p->tempBufSize, lookAhead = 0; + while (rem < LZMA_REQUIRED_INPUT_MAX && lookAhead < inSize) + p->tempBuf[rem++] = src[lookAhead++]; + p->tempBufSize = rem; + if (rem < LZMA_REQUIRED_INPUT_MAX || checkEndMarkNow) + { + int dummyRes = LzmaDec_TryDummy(p, p->tempBuf, rem); + if (dummyRes == DUMMY_ERROR) + { + (*srcLen) += lookAhead; + *status = LZMA_STATUS_NEEDS_MORE_INPUT; + return SZ_OK; + } + if (checkEndMarkNow && dummyRes != DUMMY_MATCH) + { + *status = LZMA_STATUS_NOT_FINISHED; + return SZ_ERROR_DATA; + } + } + p->buf = p->tempBuf; + if (LzmaDec_DecodeReal2(p, dicLimit, p->buf) != 0) + return SZ_ERROR_DATA; + lookAhead -= (rem - (unsigned)(p->buf - p->tempBuf)); + (*srcLen) += lookAhead; + src += lookAhead; + inSize -= lookAhead; + p->tempBufSize = 0; + } + } + if (p->code == 0) + *status = LZMA_STATUS_FINISHED_WITH_MARK; + return (p->code == 0) ? SZ_OK : SZ_ERROR_DATA; +} + +SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status) +{ + SizeT outSize = *destLen; + SizeT inSize = *srcLen; + *srcLen = *destLen = 0; + for (;;) + { + SizeT inSizeCur = inSize, outSizeCur, dicPos; + ELzmaFinishMode curFinishMode; + SRes res; + if (p->dicPos == p->dicBufSize) + p->dicPos = 0; + dicPos = p->dicPos; + if (outSize > p->dicBufSize - dicPos) + { + outSizeCur = p->dicBufSize; + curFinishMode = LZMA_FINISH_ANY; + } + else + { + outSizeCur = dicPos + outSize; + curFinishMode = finishMode; + } + + res = LzmaDec_DecodeToDic(p, outSizeCur, src, &inSizeCur, curFinishMode, status); + src += inSizeCur; + inSize -= inSizeCur; + *srcLen += inSizeCur; + outSizeCur = p->dicPos - dicPos; + memcpy(dest, p->dic + dicPos, outSizeCur); + dest += outSizeCur; + outSize -= outSizeCur; + *destLen += outSizeCur; + if (res != 0) + return res; + if (outSizeCur == 0 || outSize == 0) + return SZ_OK; + } +} + +void LzmaDec_FreeProbs(CLzmaDec *p, ISzAlloc *alloc) +{ + alloc->Free(alloc, p->probs); + p->probs = 0; +} + +static void LzmaDec_FreeDict(CLzmaDec *p, ISzAlloc *alloc) +{ + alloc->Free(alloc, p->dic); + p->dic = 0; +} + +void LzmaDec_Free(CLzmaDec *p, ISzAlloc *alloc) +{ + LzmaDec_FreeProbs(p, alloc); + LzmaDec_FreeDict(p, alloc); +} + +SRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size) +{ + UInt32 dicSize; + Byte d; + + if (size < LZMA_PROPS_SIZE) + return SZ_ERROR_UNSUPPORTED; + else + dicSize = data[1] | ((UInt32)data[2] << 8) | ((UInt32)data[3] << 16) | ((UInt32)data[4] << 24); + + if (dicSize < LZMA_DIC_MIN) + dicSize = LZMA_DIC_MIN; + p->dicSize = dicSize; + + d = data[0]; + if (d >= (9 * 5 * 5)) + return SZ_ERROR_UNSUPPORTED; + + p->lc = d % 9; + d /= 9; + p->pb = d / 5; + p->lp = d % 5; + + return SZ_OK; +} + +static SRes LzmaDec_AllocateProbs2(CLzmaDec *p, const CLzmaProps *propNew, ISzAlloc *alloc) +{ + UInt32 numProbs = LzmaProps_GetNumProbs(propNew); + if (p->probs == 0 || numProbs != p->numProbs) + { + LzmaDec_FreeProbs(p, alloc); + p->probs = (CLzmaProb *)alloc->Alloc(alloc, numProbs * sizeof(CLzmaProb)); + p->numProbs = numProbs; + if (p->probs == 0) + return SZ_ERROR_MEM; + } + return SZ_OK; +} + +SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc) +{ + CLzmaProps propNew; + RINOK(LzmaProps_Decode(&propNew, props, propsSize)); + RINOK(LzmaDec_AllocateProbs2(p, &propNew, alloc)); + p->prop = propNew; + return SZ_OK; +} + +SRes LzmaDec_Allocate(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc) +{ + CLzmaProps propNew; + SizeT dicBufSize; + RINOK(LzmaProps_Decode(&propNew, props, propsSize)); + RINOK(LzmaDec_AllocateProbs2(p, &propNew, alloc)); + dicBufSize = propNew.dicSize; + if (p->dic == 0 || dicBufSize != p->dicBufSize) + { + LzmaDec_FreeDict(p, alloc); + p->dic = (Byte *)alloc->Alloc(alloc, dicBufSize); + if (p->dic == 0) + { + LzmaDec_FreeProbs(p, alloc); + return SZ_ERROR_MEM; + } + } + p->dicBufSize = dicBufSize; + p->prop = propNew; + return SZ_OK; +} + +SRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, + const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode, + ELzmaStatus *status, ISzAlloc *alloc) +{ + CLzmaDec p; + SRes res; + SizeT inSize = *srcLen; + SizeT outSize = *destLen; + *srcLen = *destLen = 0; + if (inSize < RC_INIT_SIZE) + return SZ_ERROR_INPUT_EOF; + + LzmaDec_Construct(&p); + res = LzmaDec_AllocateProbs(&p, propData, propSize, alloc); + if (res != 0) + return res; + p.dic = dest; + p.dicBufSize = outSize; + + LzmaDec_Init(&p); + + *srcLen = inSize; + res = LzmaDec_DecodeToDic(&p, outSize, src, srcLen, finishMode, status); + + if (res == SZ_OK && *status == LZMA_STATUS_NEEDS_MORE_INPUT) + res = SZ_ERROR_INPUT_EOF; + + (*destLen) = p.dicPos; + LzmaDec_FreeProbs(&p, alloc); + return res; +} diff --git a/BaseTools/Source/C/LzmaCompress/Sdk/C/LzmaDec.h b/BaseTools/Source/C/LzmaCompress/Sdk/C/LzmaDec.h new file mode 100644 index 0000000000..ad7d7057a4 --- /dev/null +++ b/BaseTools/Source/C/LzmaCompress/Sdk/C/LzmaDec.h @@ -0,0 +1,223 @@ +/* LzmaDec.h -- LZMA Decoder +2008-10-04 : Igor Pavlov : Public domain */ + +#ifndef __LZMADEC_H +#define __LZMADEC_H + +#include "Types.h" + +/* #define _LZMA_PROB32 */ +/* _LZMA_PROB32 can increase the speed on some CPUs, + but memory usage for CLzmaDec::probs will be doubled in that case */ + +#ifdef _LZMA_PROB32 +#define CLzmaProb UInt32 +#else +#define CLzmaProb UInt16 +#endif + + +/* ---------- LZMA Properties ---------- */ + +#define LZMA_PROPS_SIZE 5 + +typedef struct _CLzmaProps +{ + unsigned lc, lp, pb; + UInt32 dicSize; +} CLzmaProps; + +/* LzmaProps_Decode - decodes properties +Returns: + SZ_OK + SZ_ERROR_UNSUPPORTED - Unsupported properties +*/ + +SRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size); + + +/* ---------- LZMA Decoder state ---------- */ + +/* LZMA_REQUIRED_INPUT_MAX = number of required input bytes for worst case. + Num bits = log2((2^11 / 31) ^ 22) + 26 < 134 + 26 = 160; */ + +#define LZMA_REQUIRED_INPUT_MAX 20 + +typedef struct +{ + CLzmaProps prop; + CLzmaProb *probs; + Byte *dic; + const Byte *buf; + UInt32 range, code; + SizeT dicPos; + SizeT dicBufSize; + UInt32 processedPos; + UInt32 checkDicSize; + unsigned state; + UInt32 reps[4]; + unsigned remainLen; + int needFlush; + int needInitState; + UInt32 numProbs; + unsigned tempBufSize; + Byte tempBuf[LZMA_REQUIRED_INPUT_MAX]; +} CLzmaDec; + +#define LzmaDec_Construct(p) { (p)->dic = 0; (p)->probs = 0; } + +void LzmaDec_Init(CLzmaDec *p); + +/* There are two types of LZMA streams: + 0) Stream with end mark. That end mark adds about 6 bytes to compressed size. + 1) Stream without end mark. You must know exact uncompressed size to decompress such stream. */ + +typedef enum +{ + LZMA_FINISH_ANY, /* finish at any point */ + LZMA_FINISH_END /* block must be finished at the end */ +} ELzmaFinishMode; + +/* ELzmaFinishMode has meaning only if the decoding reaches output limit !!! + + You must use LZMA_FINISH_END, when you know that current output buffer + covers last bytes of block. In other cases you must use LZMA_FINISH_ANY. + + If LZMA decoder sees end marker before reaching output limit, it returns SZ_OK, + and output value of destLen will be less than output buffer size limit. + You can check status result also. + + You can use multiple checks to test data integrity after full decompression: + 1) Check Result and "status" variable. + 2) Check that output(destLen) = uncompressedSize, if you know real uncompressedSize. + 3) Check that output(srcLen) = compressedSize, if you know real compressedSize. + You must use correct finish mode in that case. */ + +typedef enum +{ + LZMA_STATUS_NOT_SPECIFIED, /* use main error code instead */ + LZMA_STATUS_FINISHED_WITH_MARK, /* stream was finished with end mark. */ + LZMA_STATUS_NOT_FINISHED, /* stream was not finished */ + LZMA_STATUS_NEEDS_MORE_INPUT, /* you must provide more input bytes */ + LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK /* there is probability that stream was finished without end mark */ +} ELzmaStatus; + +/* ELzmaStatus is used only as output value for function call */ + + +/* ---------- Interfaces ---------- */ + +/* There are 3 levels of interfaces: + 1) Dictionary Interface + 2) Buffer Interface + 3) One Call Interface + You can select any of these interfaces, but don't mix functions from different + groups for same object. */ + + +/* There are two variants to allocate state for Dictionary Interface: + 1) LzmaDec_Allocate / LzmaDec_Free + 2) LzmaDec_AllocateProbs / LzmaDec_FreeProbs + You can use variant 2, if you set dictionary buffer manually. + For Buffer Interface you must always use variant 1. + +LzmaDec_Allocate* can return: + SZ_OK + SZ_ERROR_MEM - Memory allocation error + SZ_ERROR_UNSUPPORTED - Unsupported properties +*/ + +SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc); +void LzmaDec_FreeProbs(CLzmaDec *p, ISzAlloc *alloc); + +SRes LzmaDec_Allocate(CLzmaDec *state, const Byte *prop, unsigned propsSize, ISzAlloc *alloc); +void LzmaDec_Free(CLzmaDec *state, ISzAlloc *alloc); + +/* ---------- Dictionary Interface ---------- */ + +/* You can use it, if you want to eliminate the overhead for data copying from + dictionary to some other external buffer. + You must work with CLzmaDec variables directly in this interface. + + STEPS: + LzmaDec_Constr() + LzmaDec_Allocate() + for (each new stream) + { + LzmaDec_Init() + while (it needs more decompression) + { + LzmaDec_DecodeToDic() + use data from CLzmaDec::dic and update CLzmaDec::dicPos + } + } + LzmaDec_Free() +*/ + +/* LzmaDec_DecodeToDic + + The decoding to internal dictionary buffer (CLzmaDec::dic). + You must manually update CLzmaDec::dicPos, if it reaches CLzmaDec::dicBufSize !!! + +finishMode: + It has meaning only if the decoding reaches output limit (dicLimit). + LZMA_FINISH_ANY - Decode just dicLimit bytes. + LZMA_FINISH_END - Stream must be finished after dicLimit. + +Returns: + SZ_OK + status: + LZMA_STATUS_FINISHED_WITH_MARK + LZMA_STATUS_NOT_FINISHED + LZMA_STATUS_NEEDS_MORE_INPUT + LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK + SZ_ERROR_DATA - Data error +*/ + +SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, + const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status); + + +/* ---------- Buffer Interface ---------- */ + +/* It's zlib-like interface. + See LzmaDec_DecodeToDic description for information about STEPS and return results, + but you must use LzmaDec_DecodeToBuf instead of LzmaDec_DecodeToDic and you don't need + to work with CLzmaDec variables manually. + +finishMode: + It has meaning only if the decoding reaches output limit (*destLen). + LZMA_FINISH_ANY - Decode just destLen bytes. + LZMA_FINISH_END - Stream must be finished after (*destLen). +*/ + +SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen, + const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status); + + +/* ---------- One Call Interface ---------- */ + +/* LzmaDecode + +finishMode: + It has meaning only if the decoding reaches output limit (*destLen). + LZMA_FINISH_ANY - Decode just destLen bytes. + LZMA_FINISH_END - Stream must be finished after (*destLen). + +Returns: + SZ_OK + status: + LZMA_STATUS_FINISHED_WITH_MARK + LZMA_STATUS_NOT_FINISHED + LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK + SZ_ERROR_DATA - Data error + SZ_ERROR_MEM - Memory allocation error + SZ_ERROR_UNSUPPORTED - Unsupported properties + SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src). +*/ + +SRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, + const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode, + ELzmaStatus *status, ISzAlloc *alloc); + +#endif diff --git a/BaseTools/Source/C/LzmaCompress/Sdk/C/LzmaEnc.c b/BaseTools/Source/C/LzmaCompress/Sdk/C/LzmaEnc.c new file mode 100644 index 0000000000..529fd98f87 --- /dev/null +++ b/BaseTools/Source/C/LzmaCompress/Sdk/C/LzmaEnc.c @@ -0,0 +1,2281 @@ +/* LzmaEnc.c -- LZMA Encoder +2009-02-02 : Igor Pavlov : Public domain */ + +#include + +/* #define SHOW_STAT */ +/* #define SHOW_STAT2 */ + +#if defined(SHOW_STAT) || defined(SHOW_STAT2) +#include +#endif + +#include "LzmaEnc.h" + +#include "LzFind.h" +#ifdef COMPRESS_MF_MT +#include "LzFindMt.h" +#endif + +#ifdef SHOW_STAT +static int ttt = 0; +#endif + +#define kBlockSizeMax ((1 << LZMA_NUM_BLOCK_SIZE_BITS) - 1) + +#define kBlockSize (9 << 10) +#define kUnpackBlockSize (1 << 18) +#define kMatchArraySize (1 << 21) +#define kMatchRecordMaxSize ((LZMA_MATCH_LEN_MAX * 2 + 3) * LZMA_MATCH_LEN_MAX) + +#define kNumMaxDirectBits (31) + +#define kNumTopBits 24 +#define kTopValue ((UInt32)1 << kNumTopBits) + +#define kNumBitModelTotalBits 11 +#define kBitModelTotal (1 << kNumBitModelTotalBits) +#define kNumMoveBits 5 +#define kProbInitValue (kBitModelTotal >> 1) + +#define kNumMoveReducingBits 4 +#define kNumBitPriceShiftBits 4 +#define kBitPrice (1 << kNumBitPriceShiftBits) + +void LzmaEncProps_Init(CLzmaEncProps *p) +{ + p->level = 5; + p->dictSize = p->mc = 0; + p->lc = p->lp = p->pb = p->algo = p->fb = p->btMode = p->numHashBytes = p->numThreads = -1; + p->writeEndMark = 0; +} + +void LzmaEncProps_Normalize(CLzmaEncProps *p) +{ + int level = p->level; + if (level < 0) level = 5; + p->level = level; + if (p->dictSize == 0) p->dictSize = (level <= 5 ? (1 << (level * 2 + 14)) : (level == 6 ? (1 << 25) : (1 << 26))); + if (p->lc < 0) p->lc = 3; + if (p->lp < 0) p->lp = 0; + if (p->pb < 0) p->pb = 2; + if (p->algo < 0) p->algo = (level < 5 ? 0 : 1); + if (p->fb < 0) p->fb = (level < 7 ? 32 : 64); + if (p->btMode < 0) p->btMode = (p->algo == 0 ? 0 : 1); + if (p->numHashBytes < 0) p->numHashBytes = 4; + if (p->mc == 0) p->mc = (16 + (p->fb >> 1)) >> (p->btMode ? 0 : 1); + if (p->numThreads < 0) + p->numThreads = + #ifdef COMPRESS_MF_MT + ((p->btMode && p->algo) ? 2 : 1); + #else + 1; + #endif +} + +UInt32 LzmaEncProps_GetDictSize(const CLzmaEncProps *props2) +{ + CLzmaEncProps props = *props2; + LzmaEncProps_Normalize(&props); + return props.dictSize; +} + +/* #define LZMA_LOG_BSR */ +/* Define it for Intel's CPU */ + + +#ifdef LZMA_LOG_BSR + +#define kDicLogSizeMaxCompress 30 + +#define BSR2_RET(pos, res) { unsigned long i; _BitScanReverse(&i, (pos)); res = (i + i) + ((pos >> (i - 1)) & 1); } + +UInt32 GetPosSlot1(UInt32 pos) +{ + UInt32 res; + BSR2_RET(pos, res); + return res; +} +#define GetPosSlot2(pos, res) { BSR2_RET(pos, res); } +#define GetPosSlot(pos, res) { if (pos < 2) res = pos; else BSR2_RET(pos, res); } + +#else + +#define kNumLogBits (9 + (int)sizeof(size_t) / 2) +#define kDicLogSizeMaxCompress ((kNumLogBits - 1) * 2 + 7) + +void LzmaEnc_FastPosInit(Byte *g_FastPos) +{ + int c = 2, slotFast; + g_FastPos[0] = 0; + g_FastPos[1] = 1; + + for (slotFast = 2; slotFast < kNumLogBits * 2; slotFast++) + { + UInt32 k = (1 << ((slotFast >> 1) - 1)); + UInt32 j; + for (j = 0; j < k; j++, c++) + g_FastPos[c] = (Byte)slotFast; + } +} + +#define BSR2_RET(pos, res) { UInt32 i = 6 + ((kNumLogBits - 1) & \ + (0 - (((((UInt32)1 << (kNumLogBits + 6)) - 1) - pos) >> 31))); \ + res = p->g_FastPos[pos >> i] + (i * 2); } +/* +#define BSR2_RET(pos, res) { res = (pos < (1 << (kNumLogBits + 6))) ? \ + p->g_FastPos[pos >> 6] + 12 : \ + p->g_FastPos[pos >> (6 + kNumLogBits - 1)] + (6 + (kNumLogBits - 1)) * 2; } +*/ + +#define GetPosSlot1(pos) p->g_FastPos[pos] +#define GetPosSlot2(pos, res) { BSR2_RET(pos, res); } +#define GetPosSlot(pos, res) { if (pos < kNumFullDistances) res = p->g_FastPos[pos]; else BSR2_RET(pos, res); } + +#endif + + +#define LZMA_NUM_REPS 4 + +typedef unsigned CState; + +typedef struct _COptimal +{ + UInt32 price; + + CState state; + int prev1IsChar; + int prev2; + + UInt32 posPrev2; + UInt32 backPrev2; + + UInt32 posPrev; + UInt32 backPrev; + UInt32 backs[LZMA_NUM_REPS]; +} COptimal; + +#define kNumOpts (1 << 12) + +#define kNumLenToPosStates 4 +#define kNumPosSlotBits 6 +#define kDicLogSizeMin 0 +#define kDicLogSizeMax 32 +#define kDistTableSizeMax (kDicLogSizeMax * 2) + + +#define kNumAlignBits 4 +#define kAlignTableSize (1 << kNumAlignBits) +#define kAlignMask (kAlignTableSize - 1) + +#define kStartPosModelIndex 4 +#define kEndPosModelIndex 14 +#define kNumPosModels (kEndPosModelIndex - kStartPosModelIndex) + +#define kNumFullDistances (1 << (kEndPosModelIndex / 2)) + +#ifdef _LZMA_PROB32 +#define CLzmaProb UInt32 +#else +#define CLzmaProb UInt16 +#endif + +#define LZMA_PB_MAX 4 +#define LZMA_LC_MAX 8 +#define LZMA_LP_MAX 4 + +#define LZMA_NUM_PB_STATES_MAX (1 << LZMA_PB_MAX) + + +#define kLenNumLowBits 3 +#define kLenNumLowSymbols (1 << kLenNumLowBits) +#define kLenNumMidBits 3 +#define kLenNumMidSymbols (1 << kLenNumMidBits) +#define kLenNumHighBits 8 +#define kLenNumHighSymbols (1 << kLenNumHighBits) + +#define kLenNumSymbolsTotal (kLenNumLowSymbols + kLenNumMidSymbols + kLenNumHighSymbols) + +#define LZMA_MATCH_LEN_MIN 2 +#define LZMA_MATCH_LEN_MAX (LZMA_MATCH_LEN_MIN + kLenNumSymbolsTotal - 1) + +#define kNumStates 12 + +typedef struct +{ + CLzmaProb choice; + CLzmaProb choice2; + CLzmaProb low[LZMA_NUM_PB_STATES_MAX << kLenNumLowBits]; + CLzmaProb mid[LZMA_NUM_PB_STATES_MAX << kLenNumMidBits]; + CLzmaProb high[kLenNumHighSymbols]; +} CLenEnc; + +typedef struct +{ + CLenEnc p; + UInt32 prices[LZMA_NUM_PB_STATES_MAX][kLenNumSymbolsTotal]; + UInt32 tableSize; + UInt32 counters[LZMA_NUM_PB_STATES_MAX]; +} CLenPriceEnc; + +typedef struct _CRangeEnc +{ + UInt32 range; + Byte cache; + UInt64 low; + UInt64 cacheSize; + Byte *buf; + Byte *bufLim; + Byte *bufBase; + ISeqOutStream *outStream; + UInt64 processed; + SRes res; +} CRangeEnc; + +typedef struct _CSeqInStreamBuf +{ + ISeqInStream funcTable; + const Byte *data; + SizeT rem; +} CSeqInStreamBuf; + +static SRes MyRead(void *pp, void *data, size_t *size) +{ + size_t curSize = *size; + CSeqInStreamBuf *p = (CSeqInStreamBuf *)pp; + if (p->rem < curSize) + curSize = p->rem; + memcpy(data, p->data, curSize); + p->rem -= curSize; + p->data += curSize; + *size = curSize; + return SZ_OK; +} + +typedef struct +{ + CLzmaProb *litProbs; + + CLzmaProb isMatch[kNumStates][LZMA_NUM_PB_STATES_MAX]; + CLzmaProb isRep[kNumStates]; + CLzmaProb isRepG0[kNumStates]; + CLzmaProb isRepG1[kNumStates]; + CLzmaProb isRepG2[kNumStates]; + CLzmaProb isRep0Long[kNumStates][LZMA_NUM_PB_STATES_MAX]; + + CLzmaProb posSlotEncoder[kNumLenToPosStates][1 << kNumPosSlotBits]; + CLzmaProb posEncoders[kNumFullDistances - kEndPosModelIndex]; + CLzmaProb posAlignEncoder[1 << kNumAlignBits]; + + CLenPriceEnc lenEnc; + CLenPriceEnc repLenEnc; + + UInt32 reps[LZMA_NUM_REPS]; + UInt32 state; +} CSaveState; + +typedef struct _CLzmaEnc +{ + IMatchFinder matchFinder; + void *matchFinderObj; + + #ifdef COMPRESS_MF_MT + Bool mtMode; + CMatchFinderMt matchFinderMt; + #endif + + CMatchFinder matchFinderBase; + + #ifdef COMPRESS_MF_MT + Byte pad[128]; + #endif + + UInt32 optimumEndIndex; + UInt32 optimumCurrentIndex; + + UInt32 longestMatchLength; + UInt32 numPairs; + UInt32 numAvail; + COptimal opt[kNumOpts]; + + #ifndef LZMA_LOG_BSR + Byte g_FastPos[1 << kNumLogBits]; + #endif + + UInt32 ProbPrices[kBitModelTotal >> kNumMoveReducingBits]; + UInt32 matches[LZMA_MATCH_LEN_MAX * 2 + 2 + 1]; + UInt32 numFastBytes; + UInt32 additionalOffset; + UInt32 reps[LZMA_NUM_REPS]; + UInt32 state; + + UInt32 posSlotPrices[kNumLenToPosStates][kDistTableSizeMax]; + UInt32 distancesPrices[kNumLenToPosStates][kNumFullDistances]; + UInt32 alignPrices[kAlignTableSize]; + UInt32 alignPriceCount; + + UInt32 distTableSize; + + unsigned lc, lp, pb; + unsigned lpMask, pbMask; + + CLzmaProb *litProbs; + + CLzmaProb isMatch[kNumStates][LZMA_NUM_PB_STATES_MAX]; + CLzmaProb isRep[kNumStates]; + CLzmaProb isRepG0[kNumStates]; + CLzmaProb isRepG1[kNumStates]; + CLzmaProb isRepG2[kNumStates]; + CLzmaProb isRep0Long[kNumStates][LZMA_NUM_PB_STATES_MAX]; + + CLzmaProb posSlotEncoder[kNumLenToPosStates][1 << kNumPosSlotBits]; + CLzmaProb posEncoders[kNumFullDistances - kEndPosModelIndex]; + CLzmaProb posAlignEncoder[1 << kNumAlignBits]; + + CLenPriceEnc lenEnc; + CLenPriceEnc repLenEnc; + + unsigned lclp; + + Bool fastMode; + + CRangeEnc rc; + + Bool writeEndMark; + UInt64 nowPos64; + UInt32 matchPriceCount; + Bool finished; + Bool multiThread; + + SRes result; + UInt32 dictSize; + UInt32 matchFinderCycles; + + ISeqInStream *inStream; + CSeqInStreamBuf seqBufInStream; + + CSaveState saveState; +} CLzmaEnc; + +void LzmaEnc_SaveState(CLzmaEncHandle pp) +{ + CLzmaEnc *p = (CLzmaEnc *)pp; + CSaveState *dest = &p->saveState; + int i; + dest->lenEnc = p->lenEnc; + dest->repLenEnc = p->repLenEnc; + dest->state = p->state; + + for (i = 0; i < kNumStates; i++) + { + memcpy(dest->isMatch[i], p->isMatch[i], sizeof(p->isMatch[i])); + memcpy(dest->isRep0Long[i], p->isRep0Long[i], sizeof(p->isRep0Long[i])); + } + for (i = 0; i < kNumLenToPosStates; i++) + memcpy(dest->posSlotEncoder[i], p->posSlotEncoder[i], sizeof(p->posSlotEncoder[i])); + memcpy(dest->isRep, p->isRep, sizeof(p->isRep)); + memcpy(dest->isRepG0, p->isRepG0, sizeof(p->isRepG0)); + memcpy(dest->isRepG1, p->isRepG1, sizeof(p->isRepG1)); + memcpy(dest->isRepG2, p->isRepG2, sizeof(p->isRepG2)); + memcpy(dest->posEncoders, p->posEncoders, sizeof(p->posEncoders)); + memcpy(dest->posAlignEncoder, p->posAlignEncoder, sizeof(p->posAlignEncoder)); + memcpy(dest->reps, p->reps, sizeof(p->reps)); + memcpy(dest->litProbs, p->litProbs, (0x300 << p->lclp) * sizeof(CLzmaProb)); +} + +void LzmaEnc_RestoreState(CLzmaEncHandle pp) +{ + CLzmaEnc *dest = (CLzmaEnc *)pp; + const CSaveState *p = &dest->saveState; + int i; + dest->lenEnc = p->lenEnc; + dest->repLenEnc = p->repLenEnc; + dest->state = p->state; + + for (i = 0; i < kNumStates; i++) + { + memcpy(dest->isMatch[i], p->isMatch[i], sizeof(p->isMatch[i])); + memcpy(dest->isRep0Long[i], p->isRep0Long[i], sizeof(p->isRep0Long[i])); + } + for (i = 0; i < kNumLenToPosStates; i++) + memcpy(dest->posSlotEncoder[i], p->posSlotEncoder[i], sizeof(p->posSlotEncoder[i])); + memcpy(dest->isRep, p->isRep, sizeof(p->isRep)); + memcpy(dest->isRepG0, p->isRepG0, sizeof(p->isRepG0)); + memcpy(dest->isRepG1, p->isRepG1, sizeof(p->isRepG1)); + memcpy(dest->isRepG2, p->isRepG2, sizeof(p->isRepG2)); + memcpy(dest->posEncoders, p->posEncoders, sizeof(p->posEncoders)); + memcpy(dest->posAlignEncoder, p->posAlignEncoder, sizeof(p->posAlignEncoder)); + memcpy(dest->reps, p->reps, sizeof(p->reps)); + memcpy(dest->litProbs, p->litProbs, (0x300 << dest->lclp) * sizeof(CLzmaProb)); +} + +SRes LzmaEnc_SetProps(CLzmaEncHandle pp, const CLzmaEncProps *props2) +{ + CLzmaEnc *p = (CLzmaEnc *)pp; + CLzmaEncProps props = *props2; + LzmaEncProps_Normalize(&props); + + if (props.lc > LZMA_LC_MAX || props.lp > LZMA_LP_MAX || props.pb > LZMA_PB_MAX || + props.dictSize > (1 << kDicLogSizeMaxCompress) || props.dictSize > (1 << 30)) + return SZ_ERROR_PARAM; + p->dictSize = props.dictSize; + p->matchFinderCycles = props.mc; + { + unsigned fb = props.fb; + if (fb < 5) + fb = 5; + if (fb > LZMA_MATCH_LEN_MAX) + fb = LZMA_MATCH_LEN_MAX; + p->numFastBytes = fb; + } + p->lc = props.lc; + p->lp = props.lp; + p->pb = props.pb; + p->fastMode = (props.algo == 0); + p->matchFinderBase.btMode = props.btMode; + { + UInt32 numHashBytes = 4; + if (props.btMode) + { + if (props.numHashBytes < 2) + numHashBytes = 2; + else if (props.numHashBytes < 4) + numHashBytes = props.numHashBytes; + } + p->matchFinderBase.numHashBytes = numHashBytes; + } + + p->matchFinderBase.cutValue = props.mc; + + p->writeEndMark = props.writeEndMark; + + #ifdef COMPRESS_MF_MT + /* + if (newMultiThread != _multiThread) + { + ReleaseMatchFinder(); + _multiThread = newMultiThread; + } + */ + p->multiThread = (props.numThreads > 1); + #endif + + return SZ_OK; +} + +static const int kLiteralNextStates[kNumStates] = {0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 4, 5}; +static const int kMatchNextStates[kNumStates] = {7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10}; +static const int kRepNextStates[kNumStates] = {8, 8, 8, 8, 8, 8, 8, 11, 11, 11, 11, 11}; +static const int kShortRepNextStates[kNumStates]= {9, 9, 9, 9, 9, 9, 9, 11, 11, 11, 11, 11}; + +#define IsCharState(s) ((s) < 7) + +#define GetLenToPosState(len) (((len) < kNumLenToPosStates + 1) ? (len) - 2 : kNumLenToPosStates - 1) + +#define kInfinityPrice (1 << 30) + +static void RangeEnc_Construct(CRangeEnc *p) +{ + p->outStream = 0; + p->bufBase = 0; +} + +#define RangeEnc_GetProcessed(p) ((p)->processed + ((p)->buf - (p)->bufBase) + (p)->cacheSize) + +#define RC_BUF_SIZE (1 << 16) +static int RangeEnc_Alloc(CRangeEnc *p, ISzAlloc *alloc) +{ + if (p->bufBase == 0) + { + p->bufBase = (Byte *)alloc->Alloc(alloc, RC_BUF_SIZE); + if (p->bufBase == 0) + return 0; + p->bufLim = p->bufBase + RC_BUF_SIZE; + } + return 1; +} + +static void RangeEnc_Free(CRangeEnc *p, ISzAlloc *alloc) +{ + alloc->Free(alloc, p->bufBase); + p->bufBase = 0; +} + +static void RangeEnc_Init(CRangeEnc *p) +{ + /* Stream.Init(); */ + p->low = 0; + p->range = 0xFFFFFFFF; + p->cacheSize = 1; + p->cache = 0; + + p->buf = p->bufBase; + + p->processed = 0; + p->res = SZ_OK; +} + +static void RangeEnc_FlushStream(CRangeEnc *p) +{ + size_t num; + if (p->res != SZ_OK) + return; + num = p->buf - p->bufBase; + if (num != p->outStream->Write(p->outStream, p->bufBase, num)) + p->res = SZ_ERROR_WRITE; + p->processed += num; + p->buf = p->bufBase; +} + +static void MY_FAST_CALL RangeEnc_ShiftLow(CRangeEnc *p) +{ + if ((UInt32)p->low < (UInt32)0xFF000000 || (int)(p->low >> 32) != 0) + { + Byte temp = p->cache; + do + { + Byte *buf = p->buf; + *buf++ = (Byte)(temp + (Byte)(p->low >> 32)); + p->buf = buf; + if (buf == p->bufLim) + RangeEnc_FlushStream(p); + temp = 0xFF; + } + while (--p->cacheSize != 0); + p->cache = (Byte)((UInt32)p->low >> 24); + } + p->cacheSize++; + p->low = (UInt32)p->low << 8; +} + +static void RangeEnc_FlushData(CRangeEnc *p) +{ + int i; + for (i = 0; i < 5; i++) + RangeEnc_ShiftLow(p); +} + +static void RangeEnc_EncodeDirectBits(CRangeEnc *p, UInt32 value, int numBits) +{ + do + { + p->range >>= 1; + p->low += p->range & (0 - ((value >> --numBits) & 1)); + if (p->range < kTopValue) + { + p->range <<= 8; + RangeEnc_ShiftLow(p); + } + } + while (numBits != 0); +} + +static void RangeEnc_EncodeBit(CRangeEnc *p, CLzmaProb *prob, UInt32 symbol) +{ + UInt32 ttt = *prob; + UInt32 newBound = (p->range >> kNumBitModelTotalBits) * ttt; + if (symbol == 0) + { + p->range = newBound; + ttt += (kBitModelTotal - ttt) >> kNumMoveBits; + } + else + { + p->low += newBound; + p->range -= newBound; + ttt -= ttt >> kNumMoveBits; + } + *prob = (CLzmaProb)ttt; + if (p->range < kTopValue) + { + p->range <<= 8; + RangeEnc_ShiftLow(p); + } +} + +static void LitEnc_Encode(CRangeEnc *p, CLzmaProb *probs, UInt32 symbol) +{ + symbol |= 0x100; + do + { + RangeEnc_EncodeBit(p, probs + (symbol >> 8), (symbol >> 7) & 1); + symbol <<= 1; + } + while (symbol < 0x10000); +} + +static void LitEnc_EncodeMatched(CRangeEnc *p, CLzmaProb *probs, UInt32 symbol, UInt32 matchByte) +{ + UInt32 offs = 0x100; + symbol |= 0x100; + do + { + matchByte <<= 1; + RangeEnc_EncodeBit(p, probs + (offs + (matchByte & offs) + (symbol >> 8)), (symbol >> 7) & 1); + symbol <<= 1; + offs &= ~(matchByte ^ symbol); + } + while (symbol < 0x10000); +} + +void LzmaEnc_InitPriceTables(UInt32 *ProbPrices) +{ + UInt32 i; + for (i = (1 << kNumMoveReducingBits) / 2; i < kBitModelTotal; i += (1 << kNumMoveReducingBits)) + { + const int kCyclesBits = kNumBitPriceShiftBits; + UInt32 w = i; + UInt32 bitCount = 0; + int j; + for (j = 0; j < kCyclesBits; j++) + { + w = w * w; + bitCount <<= 1; + while (w >= ((UInt32)1 << 16)) + { + w >>= 1; + bitCount++; + } + } + ProbPrices[i >> kNumMoveReducingBits] = ((kNumBitModelTotalBits << kCyclesBits) - 15 - bitCount); + } +} + + +#define GET_PRICE(prob, symbol) \ + p->ProbPrices[((prob) ^ (((-(int)(symbol))) & (kBitModelTotal - 1))) >> kNumMoveReducingBits]; + +#define GET_PRICEa(prob, symbol) \ + ProbPrices[((prob) ^ ((-((int)(symbol))) & (kBitModelTotal - 1))) >> kNumMoveReducingBits]; + +#define GET_PRICE_0(prob) p->ProbPrices[(prob) >> kNumMoveReducingBits] +#define GET_PRICE_1(prob) p->ProbPrices[((prob) ^ (kBitModelTotal - 1)) >> kNumMoveReducingBits] + +#define GET_PRICE_0a(prob) ProbPrices[(prob) >> kNumMoveReducingBits] +#define GET_PRICE_1a(prob) ProbPrices[((prob) ^ (kBitModelTotal - 1)) >> kNumMoveReducingBits] + +static UInt32 LitEnc_GetPrice(const CLzmaProb *probs, UInt32 symbol, UInt32 *ProbPrices) +{ + UInt32 price = 0; + symbol |= 0x100; + do + { + price += GET_PRICEa(probs[symbol >> 8], (symbol >> 7) & 1); + symbol <<= 1; + } + while (symbol < 0x10000); + return price; +} + +static UInt32 LitEnc_GetPriceMatched(const CLzmaProb *probs, UInt32 symbol, UInt32 matchByte, UInt32 *ProbPrices) +{ + UInt32 price = 0; + UInt32 offs = 0x100; + symbol |= 0x100; + do + { + matchByte <<= 1; + price += GET_PRICEa(probs[offs + (matchByte & offs) + (symbol >> 8)], (symbol >> 7) & 1); + symbol <<= 1; + offs &= ~(matchByte ^ symbol); + } + while (symbol < 0x10000); + return price; +} + + +static void RcTree_Encode(CRangeEnc *rc, CLzmaProb *probs, int numBitLevels, UInt32 symbol) +{ + UInt32 m = 1; + int i; + for (i = numBitLevels; i != 0;) + { + UInt32 bit; + i--; + bit = (symbol >> i) & 1; + RangeEnc_EncodeBit(rc, probs + m, bit); + m = (m << 1) | bit; + } +} + +static void RcTree_ReverseEncode(CRangeEnc *rc, CLzmaProb *probs, int numBitLevels, UInt32 symbol) +{ + UInt32 m = 1; + int i; + for (i = 0; i < numBitLevels; i++) + { + UInt32 bit = symbol & 1; + RangeEnc_EncodeBit(rc, probs + m, bit); + m = (m << 1) | bit; + symbol >>= 1; + } +} + +static UInt32 RcTree_GetPrice(const CLzmaProb *probs, int numBitLevels, UInt32 symbol, UInt32 *ProbPrices) +{ + UInt32 price = 0; + symbol |= (1 << numBitLevels); + while (symbol != 1) + { + price += GET_PRICEa(probs[symbol >> 1], symbol & 1); + symbol >>= 1; + } + return price; +} + +static UInt32 RcTree_ReverseGetPrice(const CLzmaProb *probs, int numBitLevels, UInt32 symbol, UInt32 *ProbPrices) +{ + UInt32 price = 0; + UInt32 m = 1; + int i; + for (i = numBitLevels; i != 0; i--) + { + UInt32 bit = symbol & 1; + symbol >>= 1; + price += GET_PRICEa(probs[m], bit); + m = (m << 1) | bit; + } + return price; +} + + +static void LenEnc_Init(CLenEnc *p) +{ + unsigned i; + p->choice = p->choice2 = kProbInitValue; + for (i = 0; i < (LZMA_NUM_PB_STATES_MAX << kLenNumLowBits); i++) + p->low[i] = kProbInitValue; + for (i = 0; i < (LZMA_NUM_PB_STATES_MAX << kLenNumMidBits); i++) + p->mid[i] = kProbInitValue; + for (i = 0; i < kLenNumHighSymbols; i++) + p->high[i] = kProbInitValue; +} + +static void LenEnc_Encode(CLenEnc *p, CRangeEnc *rc, UInt32 symbol, UInt32 posState) +{ + if (symbol < kLenNumLowSymbols) + { + RangeEnc_EncodeBit(rc, &p->choice, 0); + RcTree_Encode(rc, p->low + (posState << kLenNumLowBits), kLenNumLowBits, symbol); + } + else + { + RangeEnc_EncodeBit(rc, &p->choice, 1); + if (symbol < kLenNumLowSymbols + kLenNumMidSymbols) + { + RangeEnc_EncodeBit(rc, &p->choice2, 0); + RcTree_Encode(rc, p->mid + (posState << kLenNumMidBits), kLenNumMidBits, symbol - kLenNumLowSymbols); + } + else + { + RangeEnc_EncodeBit(rc, &p->choice2, 1); + RcTree_Encode(rc, p->high, kLenNumHighBits, symbol - kLenNumLowSymbols - kLenNumMidSymbols); + } + } +} + +static void LenEnc_SetPrices(CLenEnc *p, UInt32 posState, UInt32 numSymbols, UInt32 *prices, UInt32 *ProbPrices) +{ + UInt32 a0 = GET_PRICE_0a(p->choice); + UInt32 a1 = GET_PRICE_1a(p->choice); + UInt32 b0 = a1 + GET_PRICE_0a(p->choice2); + UInt32 b1 = a1 + GET_PRICE_1a(p->choice2); + UInt32 i = 0; + for (i = 0; i < kLenNumLowSymbols; i++) + { + if (i >= numSymbols) + return; + prices[i] = a0 + RcTree_GetPrice(p->low + (posState << kLenNumLowBits), kLenNumLowBits, i, ProbPrices); + } + for (; i < kLenNumLowSymbols + kLenNumMidSymbols; i++) + { + if (i >= numSymbols) + return; + prices[i] = b0 + RcTree_GetPrice(p->mid + (posState << kLenNumMidBits), kLenNumMidBits, i - kLenNumLowSymbols, ProbPrices); + } + for (; i < numSymbols; i++) + prices[i] = b1 + RcTree_GetPrice(p->high, kLenNumHighBits, i - kLenNumLowSymbols - kLenNumMidSymbols, ProbPrices); +} + +static void MY_FAST_CALL LenPriceEnc_UpdateTable(CLenPriceEnc *p, UInt32 posState, UInt32 *ProbPrices) +{ + LenEnc_SetPrices(&p->p, posState, p->tableSize, p->prices[posState], ProbPrices); + p->counters[posState] = p->tableSize; +} + +static void LenPriceEnc_UpdateTables(CLenPriceEnc *p, UInt32 numPosStates, UInt32 *ProbPrices) +{ + UInt32 posState; + for (posState = 0; posState < numPosStates; posState++) + LenPriceEnc_UpdateTable(p, posState, ProbPrices); +} + +static void LenEnc_Encode2(CLenPriceEnc *p, CRangeEnc *rc, UInt32 symbol, UInt32 posState, Bool updatePrice, UInt32 *ProbPrices) +{ + LenEnc_Encode(&p->p, rc, symbol, posState); + if (updatePrice) + if (--p->counters[posState] == 0) + LenPriceEnc_UpdateTable(p, posState, ProbPrices); +} + + + + +static void MovePos(CLzmaEnc *p, UInt32 num) +{ + #ifdef SHOW_STAT + ttt += num; + printf("\n MovePos %d", num); + #endif + if (num != 0) + { + p->additionalOffset += num; + p->matchFinder.Skip(p->matchFinderObj, num); + } +} + +static UInt32 ReadMatchDistances(CLzmaEnc *p, UInt32 *numDistancePairsRes) +{ + UInt32 lenRes = 0, numPairs; + p->numAvail = p->matchFinder.GetNumAvailableBytes(p->matchFinderObj); + numPairs = p->matchFinder.GetMatches(p->matchFinderObj, p->matches); + #ifdef SHOW_STAT + printf("\n i = %d numPairs = %d ", ttt, numPairs / 2); + ttt++; + { + UInt32 i; + for (i = 0; i < numPairs; i += 2) + printf("%2d %6d | ", p->matches[i], p->matches[i + 1]); + } + #endif + if (numPairs > 0) + { + lenRes = p->matches[numPairs - 2]; + if (lenRes == p->numFastBytes) + { + const Byte *pby = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1; + UInt32 distance = p->matches[numPairs - 1] + 1; + UInt32 numAvail = p->numAvail; + if (numAvail > LZMA_MATCH_LEN_MAX) + numAvail = LZMA_MATCH_LEN_MAX; + { + const Byte *pby2 = pby - distance; + for (; lenRes < numAvail && pby[lenRes] == pby2[lenRes]; lenRes++); + } + } + } + p->additionalOffset++; + *numDistancePairsRes = numPairs; + return lenRes; +} + + +#define MakeAsChar(p) (p)->backPrev = (UInt32)(-1); (p)->prev1IsChar = False; +#define MakeAsShortRep(p) (p)->backPrev = 0; (p)->prev1IsChar = False; +#define IsShortRep(p) ((p)->backPrev == 0) + +static UInt32 GetRepLen1Price(CLzmaEnc *p, UInt32 state, UInt32 posState) +{ + return + GET_PRICE_0(p->isRepG0[state]) + + GET_PRICE_0(p->isRep0Long[state][posState]); +} + +static UInt32 GetPureRepPrice(CLzmaEnc *p, UInt32 repIndex, UInt32 state, UInt32 posState) +{ + UInt32 price; + if (repIndex == 0) + { + price = GET_PRICE_0(p->isRepG0[state]); + price += GET_PRICE_1(p->isRep0Long[state][posState]); + } + else + { + price = GET_PRICE_1(p->isRepG0[state]); + if (repIndex == 1) + price += GET_PRICE_0(p->isRepG1[state]); + else + { + price += GET_PRICE_1(p->isRepG1[state]); + price += GET_PRICE(p->isRepG2[state], repIndex - 2); + } + } + return price; +} + +static UInt32 GetRepPrice(CLzmaEnc *p, UInt32 repIndex, UInt32 len, UInt32 state, UInt32 posState) +{ + return p->repLenEnc.prices[posState][len - LZMA_MATCH_LEN_MIN] + + GetPureRepPrice(p, repIndex, state, posState); +} + +static UInt32 Backward(CLzmaEnc *p, UInt32 *backRes, UInt32 cur) +{ + UInt32 posMem = p->opt[cur].posPrev; + UInt32 backMem = p->opt[cur].backPrev; + p->optimumEndIndex = cur; + do + { + if (p->opt[cur].prev1IsChar) + { + MakeAsChar(&p->opt[posMem]) + p->opt[posMem].posPrev = posMem - 1; + if (p->opt[cur].prev2) + { + p->opt[posMem - 1].prev1IsChar = False; + p->opt[posMem - 1].posPrev = p->opt[cur].posPrev2; + p->opt[posMem - 1].backPrev = p->opt[cur].backPrev2; + } + } + { + UInt32 posPrev = posMem; + UInt32 backCur = backMem; + + backMem = p->opt[posPrev].backPrev; + posMem = p->opt[posPrev].posPrev; + + p->opt[posPrev].backPrev = backCur; + p->opt[posPrev].posPrev = cur; + cur = posPrev; + } + } + while (cur != 0); + *backRes = p->opt[0].backPrev; + p->optimumCurrentIndex = p->opt[0].posPrev; + return p->optimumCurrentIndex; +} + +#define LIT_PROBS(pos, prevByte) (p->litProbs + ((((pos) & p->lpMask) << p->lc) + ((prevByte) >> (8 - p->lc))) * 0x300) + +static UInt32 GetOptimum(CLzmaEnc *p, UInt32 position, UInt32 *backRes) +{ + UInt32 numAvail, mainLen, numPairs, repMaxIndex, i, posState, lenEnd, len, cur; + UInt32 matchPrice, repMatchPrice, normalMatchPrice; + UInt32 reps[LZMA_NUM_REPS], repLens[LZMA_NUM_REPS]; + UInt32 *matches; + const Byte *data; + Byte curByte, matchByte; + if (p->optimumEndIndex != p->optimumCurrentIndex) + { + const COptimal *opt = &p->opt[p->optimumCurrentIndex]; + UInt32 lenRes = opt->posPrev - p->optimumCurrentIndex; + *backRes = opt->backPrev; + p->optimumCurrentIndex = opt->posPrev; + return lenRes; + } + p->optimumCurrentIndex = p->optimumEndIndex = 0; + + if (p->additionalOffset == 0) + mainLen = ReadMatchDistances(p, &numPairs); + else + { + mainLen = p->longestMatchLength; + numPairs = p->numPairs; + } + + numAvail = p->numAvail; + if (numAvail < 2) + { + *backRes = (UInt32)(-1); + return 1; + } + if (numAvail > LZMA_MATCH_LEN_MAX) + numAvail = LZMA_MATCH_LEN_MAX; + + data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1; + repMaxIndex = 0; + for (i = 0; i < LZMA_NUM_REPS; i++) + { + UInt32 lenTest; + const Byte *data2; + reps[i] = p->reps[i]; + data2 = data - (reps[i] + 1); + if (data[0] != data2[0] || data[1] != data2[1]) + { + repLens[i] = 0; + continue; + } + for (lenTest = 2; lenTest < numAvail && data[lenTest] == data2[lenTest]; lenTest++); + repLens[i] = lenTest; + if (lenTest > repLens[repMaxIndex]) + repMaxIndex = i; + } + if (repLens[repMaxIndex] >= p->numFastBytes) + { + UInt32 lenRes; + *backRes = repMaxIndex; + lenRes = repLens[repMaxIndex]; + MovePos(p, lenRes - 1); + return lenRes; + } + + matches = p->matches; + if (mainLen >= p->numFastBytes) + { + *backRes = matches[numPairs - 1] + LZMA_NUM_REPS; + MovePos(p, mainLen - 1); + return mainLen; + } + curByte = *data; + matchByte = *(data - (reps[0] + 1)); + + if (mainLen < 2 && curByte != matchByte && repLens[repMaxIndex] < 2) + { + *backRes = (UInt32)-1; + return 1; + } + + p->opt[0].state = (CState)p->state; + + posState = (position & p->pbMask); + + { + const CLzmaProb *probs = LIT_PROBS(position, *(data - 1)); + p->opt[1].price = GET_PRICE_0(p->isMatch[p->state][posState]) + + (!IsCharState(p->state) ? + LitEnc_GetPriceMatched(probs, curByte, matchByte, p->ProbPrices) : + LitEnc_GetPrice(probs, curByte, p->ProbPrices)); + } + + MakeAsChar(&p->opt[1]); + + matchPrice = GET_PRICE_1(p->isMatch[p->state][posState]); + repMatchPrice = matchPrice + GET_PRICE_1(p->isRep[p->state]); + + if (matchByte == curByte) + { + UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(p, p->state, posState); + if (shortRepPrice < p->opt[1].price) + { + p->opt[1].price = shortRepPrice; + MakeAsShortRep(&p->opt[1]); + } + } + lenEnd = ((mainLen >= repLens[repMaxIndex]) ? mainLen : repLens[repMaxIndex]); + + if (lenEnd < 2) + { + *backRes = p->opt[1].backPrev; + return 1; + } + + p->opt[1].posPrev = 0; + for (i = 0; i < LZMA_NUM_REPS; i++) + p->opt[0].backs[i] = reps[i]; + + len = lenEnd; + do + p->opt[len--].price = kInfinityPrice; + while (len >= 2); + + for (i = 0; i < LZMA_NUM_REPS; i++) + { + UInt32 repLen = repLens[i]; + UInt32 price; + if (repLen < 2) + continue; + price = repMatchPrice + GetPureRepPrice(p, i, p->state, posState); + do + { + UInt32 curAndLenPrice = price + p->repLenEnc.prices[posState][repLen - 2]; + COptimal *opt = &p->opt[repLen]; + if (curAndLenPrice < opt->price) + { + opt->price = curAndLenPrice; + opt->posPrev = 0; + opt->backPrev = i; + opt->prev1IsChar = False; + } + } + while (--repLen >= 2); + } + + normalMatchPrice = matchPrice + GET_PRICE_0(p->isRep[p->state]); + + len = ((repLens[0] >= 2) ? repLens[0] + 1 : 2); + if (len <= mainLen) + { + UInt32 offs = 0; + while (len > matches[offs]) + offs += 2; + for (; ; len++) + { + COptimal *opt; + UInt32 distance = matches[offs + 1]; + + UInt32 curAndLenPrice = normalMatchPrice + p->lenEnc.prices[posState][len - LZMA_MATCH_LEN_MIN]; + UInt32 lenToPosState = GetLenToPosState(len); + if (distance < kNumFullDistances) + curAndLenPrice += p->distancesPrices[lenToPosState][distance]; + else + { + UInt32 slot; + GetPosSlot2(distance, slot); + curAndLenPrice += p->alignPrices[distance & kAlignMask] + p->posSlotPrices[lenToPosState][slot]; + } + opt = &p->opt[len]; + if (curAndLenPrice < opt->price) + { + opt->price = curAndLenPrice; + opt->posPrev = 0; + opt->backPrev = distance + LZMA_NUM_REPS; + opt->prev1IsChar = False; + } + if (len == matches[offs]) + { + offs += 2; + if (offs == numPairs) + break; + } + } + } + + cur = 0; + + #ifdef SHOW_STAT2 + if (position >= 0) + { + unsigned i; + printf("\n pos = %4X", position); + for (i = cur; i <= lenEnd; i++) + printf("\nprice[%4X] = %d", position - cur + i, p->opt[i].price); + } + #endif + + for (;;) + { + UInt32 numAvailFull, newLen, numPairs, posPrev, state, posState, startLen; + UInt32 curPrice, curAnd1Price, matchPrice, repMatchPrice; + Bool nextIsChar; + Byte curByte, matchByte; + const Byte *data; + COptimal *curOpt; + COptimal *nextOpt; + + cur++; + if (cur == lenEnd) + return Backward(p, backRes, cur); + + newLen = ReadMatchDistances(p, &numPairs); + if (newLen >= p->numFastBytes) + { + p->numPairs = numPairs; + p->longestMatchLength = newLen; + return Backward(p, backRes, cur); + } + position++; + curOpt = &p->opt[cur]; + posPrev = curOpt->posPrev; + if (curOpt->prev1IsChar) + { + posPrev--; + if (curOpt->prev2) + { + state = p->opt[curOpt->posPrev2].state; + if (curOpt->backPrev2 < LZMA_NUM_REPS) + state = kRepNextStates[state]; + else + state = kMatchNextStates[state]; + } + else + state = p->opt[posPrev].state; + state = kLiteralNextStates[state]; + } + else + state = p->opt[posPrev].state; + if (posPrev == cur - 1) + { + if (IsShortRep(curOpt)) + state = kShortRepNextStates[state]; + else + state = kLiteralNextStates[state]; + } + else + { + UInt32 pos; + const COptimal *prevOpt; + if (curOpt->prev1IsChar && curOpt->prev2) + { + posPrev = curOpt->posPrev2; + pos = curOpt->backPrev2; + state = kRepNextStates[state]; + } + else + { + pos = curOpt->backPrev; + if (pos < LZMA_NUM_REPS) + state = kRepNextStates[state]; + else + state = kMatchNextStates[state]; + } + prevOpt = &p->opt[posPrev]; + if (pos < LZMA_NUM_REPS) + { + UInt32 i; + reps[0] = prevOpt->backs[pos]; + for (i = 1; i <= pos; i++) + reps[i] = prevOpt->backs[i - 1]; + for (; i < LZMA_NUM_REPS; i++) + reps[i] = prevOpt->backs[i]; + } + else + { + UInt32 i; + reps[0] = (pos - LZMA_NUM_REPS); + for (i = 1; i < LZMA_NUM_REPS; i++) + reps[i] = prevOpt->backs[i - 1]; + } + } + curOpt->state = (CState)state; + + curOpt->backs[0] = reps[0]; + curOpt->backs[1] = reps[1]; + curOpt->backs[2] = reps[2]; + curOpt->backs[3] = reps[3]; + + curPrice = curOpt->price; + nextIsChar = False; + data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1; + curByte = *data; + matchByte = *(data - (reps[0] + 1)); + + posState = (position & p->pbMask); + + curAnd1Price = curPrice + GET_PRICE_0(p->isMatch[state][posState]); + { + const CLzmaProb *probs = LIT_PROBS(position, *(data - 1)); + curAnd1Price += + (!IsCharState(state) ? + LitEnc_GetPriceMatched(probs, curByte, matchByte, p->ProbPrices) : + LitEnc_GetPrice(probs, curByte, p->ProbPrices)); + } + + nextOpt = &p->opt[cur + 1]; + + if (curAnd1Price < nextOpt->price) + { + nextOpt->price = curAnd1Price; + nextOpt->posPrev = cur; + MakeAsChar(nextOpt); + nextIsChar = True; + } + + matchPrice = curPrice + GET_PRICE_1(p->isMatch[state][posState]); + repMatchPrice = matchPrice + GET_PRICE_1(p->isRep[state]); + + if (matchByte == curByte && !(nextOpt->posPrev < cur && nextOpt->backPrev == 0)) + { + UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(p, state, posState); + if (shortRepPrice <= nextOpt->price) + { + nextOpt->price = shortRepPrice; + nextOpt->posPrev = cur; + MakeAsShortRep(nextOpt); + nextIsChar = True; + } + } + numAvailFull = p->numAvail; + { + UInt32 temp = kNumOpts - 1 - cur; + if (temp < numAvailFull) + numAvailFull = temp; + } + + if (numAvailFull < 2) + continue; + numAvail = (numAvailFull <= p->numFastBytes ? numAvailFull : p->numFastBytes); + + if (!nextIsChar && matchByte != curByte) /* speed optimization */ + { + /* try Literal + rep0 */ + UInt32 temp; + UInt32 lenTest2; + const Byte *data2 = data - (reps[0] + 1); + UInt32 limit = p->numFastBytes + 1; + if (limit > numAvailFull) + limit = numAvailFull; + + for (temp = 1; temp < limit && data[temp] == data2[temp]; temp++); + lenTest2 = temp - 1; + if (lenTest2 >= 2) + { + UInt32 state2 = kLiteralNextStates[state]; + UInt32 posStateNext = (position + 1) & p->pbMask; + UInt32 nextRepMatchPrice = curAnd1Price + + GET_PRICE_1(p->isMatch[state2][posStateNext]) + + GET_PRICE_1(p->isRep[state2]); + /* for (; lenTest2 >= 2; lenTest2--) */ + { + UInt32 curAndLenPrice; + COptimal *opt; + UInt32 offset = cur + 1 + lenTest2; + while (lenEnd < offset) + p->opt[++lenEnd].price = kInfinityPrice; + curAndLenPrice = nextRepMatchPrice + GetRepPrice(p, 0, lenTest2, state2, posStateNext); + opt = &p->opt[offset]; + if (curAndLenPrice < opt->price) + { + opt->price = curAndLenPrice; + opt->posPrev = cur + 1; + opt->backPrev = 0; + opt->prev1IsChar = True; + opt->prev2 = False; + } + } + } + } + + startLen = 2; /* speed optimization */ + { + UInt32 repIndex; + for (repIndex = 0; repIndex < LZMA_NUM_REPS; repIndex++) + { + UInt32 lenTest; + UInt32 lenTestTemp; + UInt32 price; + const Byte *data2 = data - (reps[repIndex] + 1); + if (data[0] != data2[0] || data[1] != data2[1]) + continue; + for (lenTest = 2; lenTest < numAvail && data[lenTest] == data2[lenTest]; lenTest++); + while (lenEnd < cur + lenTest) + p->opt[++lenEnd].price = kInfinityPrice; + lenTestTemp = lenTest; + price = repMatchPrice + GetPureRepPrice(p, repIndex, state, posState); + do + { + UInt32 curAndLenPrice = price + p->repLenEnc.prices[posState][lenTest - 2]; + COptimal *opt = &p->opt[cur + lenTest]; + if (curAndLenPrice < opt->price) + { + opt->price = curAndLenPrice; + opt->posPrev = cur; + opt->backPrev = repIndex; + opt->prev1IsChar = False; + } + } + while (--lenTest >= 2); + lenTest = lenTestTemp; + + if (repIndex == 0) + startLen = lenTest + 1; + + /* if (_maxMode) */ + { + UInt32 lenTest2 = lenTest + 1; + UInt32 limit = lenTest2 + p->numFastBytes; + UInt32 nextRepMatchPrice; + if (limit > numAvailFull) + limit = numAvailFull; + for (; lenTest2 < limit && data[lenTest2] == data2[lenTest2]; lenTest2++); + lenTest2 -= lenTest + 1; + if (lenTest2 >= 2) + { + UInt32 state2 = kRepNextStates[state]; + UInt32 posStateNext = (position + lenTest) & p->pbMask; + UInt32 curAndLenCharPrice = + price + p->repLenEnc.prices[posState][lenTest - 2] + + GET_PRICE_0(p->isMatch[state2][posStateNext]) + + LitEnc_GetPriceMatched(LIT_PROBS(position + lenTest, data[lenTest - 1]), + data[lenTest], data2[lenTest], p->ProbPrices); + state2 = kLiteralNextStates[state2]; + posStateNext = (position + lenTest + 1) & p->pbMask; + nextRepMatchPrice = curAndLenCharPrice + + GET_PRICE_1(p->isMatch[state2][posStateNext]) + + GET_PRICE_1(p->isRep[state2]); + + /* for (; lenTest2 >= 2; lenTest2--) */ + { + UInt32 curAndLenPrice; + COptimal *opt; + UInt32 offset = cur + lenTest + 1 + lenTest2; + while (lenEnd < offset) + p->opt[++lenEnd].price = kInfinityPrice; + curAndLenPrice = nextRepMatchPrice + GetRepPrice(p, 0, lenTest2, state2, posStateNext); + opt = &p->opt[offset]; + if (curAndLenPrice < opt->price) + { + opt->price = curAndLenPrice; + opt->posPrev = cur + lenTest + 1; + opt->backPrev = 0; + opt->prev1IsChar = True; + opt->prev2 = True; + opt->posPrev2 = cur; + opt->backPrev2 = repIndex; + } + } + } + } + } + } + /* for (UInt32 lenTest = 2; lenTest <= newLen; lenTest++) */ + if (newLen > numAvail) + { + newLen = numAvail; + for (numPairs = 0; newLen > matches[numPairs]; numPairs += 2); + matches[numPairs] = newLen; + numPairs += 2; + } + if (newLen >= startLen) + { + UInt32 normalMatchPrice = matchPrice + GET_PRICE_0(p->isRep[state]); + UInt32 offs, curBack, posSlot; + UInt32 lenTest; + while (lenEnd < cur + newLen) + p->opt[++lenEnd].price = kInfinityPrice; + + offs = 0; + while (startLen > matches[offs]) + offs += 2; + curBack = matches[offs + 1]; + GetPosSlot2(curBack, posSlot); + for (lenTest = /*2*/ startLen; ; lenTest++) + { + UInt32 curAndLenPrice = normalMatchPrice + p->lenEnc.prices[posState][lenTest - LZMA_MATCH_LEN_MIN]; + UInt32 lenToPosState = GetLenToPosState(lenTest); + COptimal *opt; + if (curBack < kNumFullDistances) + curAndLenPrice += p->distancesPrices[lenToPosState][curBack]; + else + curAndLenPrice += p->posSlotPrices[lenToPosState][posSlot] + p->alignPrices[curBack & kAlignMask]; + + opt = &p->opt[cur + lenTest]; + if (curAndLenPrice < opt->price) + { + opt->price = curAndLenPrice; + opt->posPrev = cur; + opt->backPrev = curBack + LZMA_NUM_REPS; + opt->prev1IsChar = False; + } + + if (/*_maxMode && */lenTest == matches[offs]) + { + /* Try Match + Literal + Rep0 */ + const Byte *data2 = data - (curBack + 1); + UInt32 lenTest2 = lenTest + 1; + UInt32 limit = lenTest2 + p->numFastBytes; + UInt32 nextRepMatchPrice; + if (limit > numAvailFull) + limit = numAvailFull; + for (; lenTest2 < limit && data[lenTest2] == data2[lenTest2]; lenTest2++); + lenTest2 -= lenTest + 1; + if (lenTest2 >= 2) + { + UInt32 state2 = kMatchNextStates[state]; + UInt32 posStateNext = (position + lenTest) & p->pbMask; + UInt32 curAndLenCharPrice = curAndLenPrice + + GET_PRICE_0(p->isMatch[state2][posStateNext]) + + LitEnc_GetPriceMatched(LIT_PROBS(position + lenTest, data[lenTest - 1]), + data[lenTest], data2[lenTest], p->ProbPrices); + state2 = kLiteralNextStates[state2]; + posStateNext = (posStateNext + 1) & p->pbMask; + nextRepMatchPrice = curAndLenCharPrice + + GET_PRICE_1(p->isMatch[state2][posStateNext]) + + GET_PRICE_1(p->isRep[state2]); + + /* for (; lenTest2 >= 2; lenTest2--) */ + { + UInt32 offset = cur + lenTest + 1 + lenTest2; + UInt32 curAndLenPrice; + COptimal *opt; + while (lenEnd < offset) + p->opt[++lenEnd].price = kInfinityPrice; + curAndLenPrice = nextRepMatchPrice + GetRepPrice(p, 0, lenTest2, state2, posStateNext); + opt = &p->opt[offset]; + if (curAndLenPrice < opt->price) + { + opt->price = curAndLenPrice; + opt->posPrev = cur + lenTest + 1; + opt->backPrev = 0; + opt->prev1IsChar = True; + opt->prev2 = True; + opt->posPrev2 = cur; + opt->backPrev2 = curBack + LZMA_NUM_REPS; + } + } + } + offs += 2; + if (offs == numPairs) + break; + curBack = matches[offs + 1]; + if (curBack >= kNumFullDistances) + GetPosSlot2(curBack, posSlot); + } + } + } + } +} + +#define ChangePair(smallDist, bigDist) (((bigDist) >> 7) > (smallDist)) + +static UInt32 GetOptimumFast(CLzmaEnc *p, UInt32 *backRes) +{ + UInt32 numAvail, mainLen, mainDist, numPairs, repIndex, repLen, i; + const Byte *data; + const UInt32 *matches; + + if (p->additionalOffset == 0) + mainLen = ReadMatchDistances(p, &numPairs); + else + { + mainLen = p->longestMatchLength; + numPairs = p->numPairs; + } + + numAvail = p->numAvail; + *backRes = (UInt32)-1; + if (numAvail < 2) + return 1; + if (numAvail > LZMA_MATCH_LEN_MAX) + numAvail = LZMA_MATCH_LEN_MAX; + data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1; + + repLen = repIndex = 0; + for (i = 0; i < LZMA_NUM_REPS; i++) + { + UInt32 len; + const Byte *data2 = data - (p->reps[i] + 1); + if (data[0] != data2[0] || data[1] != data2[1]) + continue; + for (len = 2; len < numAvail && data[len] == data2[len]; len++); + if (len >= p->numFastBytes) + { + *backRes = i; + MovePos(p, len - 1); + return len; + } + if (len > repLen) + { + repIndex = i; + repLen = len; + } + } + + matches = p->matches; + if (mainLen >= p->numFastBytes) + { + *backRes = matches[numPairs - 1] + LZMA_NUM_REPS; + MovePos(p, mainLen - 1); + return mainLen; + } + + mainDist = 0; /* for GCC */ + if (mainLen >= 2) + { + mainDist = matches[numPairs - 1]; + while (numPairs > 2 && mainLen == matches[numPairs - 4] + 1) + { + if (!ChangePair(matches[numPairs - 3], mainDist)) + break; + numPairs -= 2; + mainLen = matches[numPairs - 2]; + mainDist = matches[numPairs - 1]; + } + if (mainLen == 2 && mainDist >= 0x80) + mainLen = 1; + } + + if (repLen >= 2 && ( + (repLen + 1 >= mainLen) || + (repLen + 2 >= mainLen && mainDist >= (1 << 9)) || + (repLen + 3 >= mainLen && mainDist >= (1 << 15)))) + { + *backRes = repIndex; + MovePos(p, repLen - 1); + return repLen; + } + + if (mainLen < 2 || numAvail <= 2) + return 1; + + p->longestMatchLength = ReadMatchDistances(p, &p->numPairs); + if (p->longestMatchLength >= 2) + { + UInt32 newDistance = matches[p->numPairs - 1]; + if ((p->longestMatchLength >= mainLen && newDistance < mainDist) || + (p->longestMatchLength == mainLen + 1 && !ChangePair(mainDist, newDistance)) || + (p->longestMatchLength > mainLen + 1) || + (p->longestMatchLength + 1 >= mainLen && mainLen >= 3 && ChangePair(newDistance, mainDist))) + return 1; + } + + data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1; + for (i = 0; i < LZMA_NUM_REPS; i++) + { + UInt32 len, limit; + const Byte *data2 = data - (p->reps[i] + 1); + if (data[0] != data2[0] || data[1] != data2[1]) + continue; + limit = mainLen - 1; + for (len = 2; len < limit && data[len] == data2[len]; len++); + if (len >= limit) + return 1; + } + *backRes = mainDist + LZMA_NUM_REPS; + MovePos(p, mainLen - 2); + return mainLen; +} + +static void WriteEndMarker(CLzmaEnc *p, UInt32 posState) +{ + UInt32 len; + RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][posState], 1); + RangeEnc_EncodeBit(&p->rc, &p->isRep[p->state], 0); + p->state = kMatchNextStates[p->state]; + len = LZMA_MATCH_LEN_MIN; + LenEnc_Encode2(&p->lenEnc, &p->rc, len - LZMA_MATCH_LEN_MIN, posState, !p->fastMode, p->ProbPrices); + RcTree_Encode(&p->rc, p->posSlotEncoder[GetLenToPosState(len)], kNumPosSlotBits, (1 << kNumPosSlotBits) - 1); + RangeEnc_EncodeDirectBits(&p->rc, (((UInt32)1 << 30) - 1) >> kNumAlignBits, 30 - kNumAlignBits); + RcTree_ReverseEncode(&p->rc, p->posAlignEncoder, kNumAlignBits, kAlignMask); +} + +static SRes CheckErrors(CLzmaEnc *p) +{ + if (p->result != SZ_OK) + return p->result; + if (p->rc.res != SZ_OK) + p->result = SZ_ERROR_WRITE; + if (p->matchFinderBase.result != SZ_OK) + p->result = SZ_ERROR_READ; + if (p->result != SZ_OK) + p->finished = True; + return p->result; +} + +static SRes Flush(CLzmaEnc *p, UInt32 nowPos) +{ + /* ReleaseMFStream(); */ + p->finished = True; + if (p->writeEndMark) + WriteEndMarker(p, nowPos & p->pbMask); + RangeEnc_FlushData(&p->rc); + RangeEnc_FlushStream(&p->rc); + return CheckErrors(p); +} + +static void FillAlignPrices(CLzmaEnc *p) +{ + UInt32 i; + for (i = 0; i < kAlignTableSize; i++) + p->alignPrices[i] = RcTree_ReverseGetPrice(p->posAlignEncoder, kNumAlignBits, i, p->ProbPrices); + p->alignPriceCount = 0; +} + +static void FillDistancesPrices(CLzmaEnc *p) +{ + UInt32 tempPrices[kNumFullDistances]; + UInt32 i, lenToPosState; + for (i = kStartPosModelIndex; i < kNumFullDistances; i++) + { + UInt32 posSlot = GetPosSlot1(i); + UInt32 footerBits = ((posSlot >> 1) - 1); + UInt32 base = ((2 | (posSlot & 1)) << footerBits); + tempPrices[i] = RcTree_ReverseGetPrice(p->posEncoders + base - posSlot - 1, footerBits, i - base, p->ProbPrices); + } + + for (lenToPosState = 0; lenToPosState < kNumLenToPosStates; lenToPosState++) + { + UInt32 posSlot; + const CLzmaProb *encoder = p->posSlotEncoder[lenToPosState]; + UInt32 *posSlotPrices = p->posSlotPrices[lenToPosState]; + for (posSlot = 0; posSlot < p->distTableSize; posSlot++) + posSlotPrices[posSlot] = RcTree_GetPrice(encoder, kNumPosSlotBits, posSlot, p->ProbPrices); + for (posSlot = kEndPosModelIndex; posSlot < p->distTableSize; posSlot++) + posSlotPrices[posSlot] += ((((posSlot >> 1) - 1) - kNumAlignBits) << kNumBitPriceShiftBits); + + { + UInt32 *distancesPrices = p->distancesPrices[lenToPosState]; + UInt32 i; + for (i = 0; i < kStartPosModelIndex; i++) + distancesPrices[i] = posSlotPrices[i]; + for (; i < kNumFullDistances; i++) + distancesPrices[i] = posSlotPrices[GetPosSlot1(i)] + tempPrices[i]; + } + } + p->matchPriceCount = 0; +} + +void LzmaEnc_Construct(CLzmaEnc *p) +{ + RangeEnc_Construct(&p->rc); + MatchFinder_Construct(&p->matchFinderBase); + #ifdef COMPRESS_MF_MT + MatchFinderMt_Construct(&p->matchFinderMt); + p->matchFinderMt.MatchFinder = &p->matchFinderBase; + #endif + + { + CLzmaEncProps props; + LzmaEncProps_Init(&props); + LzmaEnc_SetProps(p, &props); + } + + #ifndef LZMA_LOG_BSR + LzmaEnc_FastPosInit(p->g_FastPos); + #endif + + LzmaEnc_InitPriceTables(p->ProbPrices); + p->litProbs = 0; + p->saveState.litProbs = 0; +} + +CLzmaEncHandle LzmaEnc_Create(ISzAlloc *alloc) +{ + void *p; + p = alloc->Alloc(alloc, sizeof(CLzmaEnc)); + if (p != 0) + LzmaEnc_Construct((CLzmaEnc *)p); + return p; +} + +void LzmaEnc_FreeLits(CLzmaEnc *p, ISzAlloc *alloc) +{ + alloc->Free(alloc, p->litProbs); + alloc->Free(alloc, p->saveState.litProbs); + p->litProbs = 0; + p->saveState.litProbs = 0; +} + +void LzmaEnc_Destruct(CLzmaEnc *p, ISzAlloc *alloc, ISzAlloc *allocBig) +{ + #ifdef COMPRESS_MF_MT + MatchFinderMt_Destruct(&p->matchFinderMt, allocBig); + #endif + MatchFinder_Free(&p->matchFinderBase, allocBig); + LzmaEnc_FreeLits(p, alloc); + RangeEnc_Free(&p->rc, alloc); +} + +void LzmaEnc_Destroy(CLzmaEncHandle p, ISzAlloc *alloc, ISzAlloc *allocBig) +{ + LzmaEnc_Destruct((CLzmaEnc *)p, alloc, allocBig); + alloc->Free(alloc, p); +} + +static SRes LzmaEnc_CodeOneBlock(CLzmaEnc *p, Bool useLimits, UInt32 maxPackSize, UInt32 maxUnpackSize) +{ + UInt32 nowPos32, startPos32; + if (p->inStream != 0) + { + p->matchFinderBase.stream = p->inStream; + p->matchFinder.Init(p->matchFinderObj); + p->inStream = 0; + } + + if (p->finished) + return p->result; + RINOK(CheckErrors(p)); + + nowPos32 = (UInt32)p->nowPos64; + startPos32 = nowPos32; + + if (p->nowPos64 == 0) + { + UInt32 numPairs; + Byte curByte; + if (p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) == 0) + return Flush(p, nowPos32); + ReadMatchDistances(p, &numPairs); + RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][0], 0); + p->state = kLiteralNextStates[p->state]; + curByte = p->matchFinder.GetIndexByte(p->matchFinderObj, 0 - p->additionalOffset); + LitEnc_Encode(&p->rc, p->litProbs, curByte); + p->additionalOffset--; + nowPos32++; + } + + if (p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) != 0) + for (;;) + { + UInt32 pos, len, posState; + + if (p->fastMode) + len = GetOptimumFast(p, &pos); + else + len = GetOptimum(p, nowPos32, &pos); + + #ifdef SHOW_STAT2 + printf("\n pos = %4X, len = %d pos = %d", nowPos32, len, pos); + #endif + + posState = nowPos32 & p->pbMask; + if (len == 1 && pos == (UInt32)-1) + { + Byte curByte; + CLzmaProb *probs; + const Byte *data; + + RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][posState], 0); + data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - p->additionalOffset; + curByte = *data; + probs = LIT_PROBS(nowPos32, *(data - 1)); + if (IsCharState(p->state)) + LitEnc_Encode(&p->rc, probs, curByte); + else + LitEnc_EncodeMatched(&p->rc, probs, curByte, *(data - p->reps[0] - 1)); + p->state = kLiteralNextStates[p->state]; + } + else + { + RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][posState], 1); + if (pos < LZMA_NUM_REPS) + { + RangeEnc_EncodeBit(&p->rc, &p->isRep[p->state], 1); + if (pos == 0) + { + RangeEnc_EncodeBit(&p->rc, &p->isRepG0[p->state], 0); + RangeEnc_EncodeBit(&p->rc, &p->isRep0Long[p->state][posState], ((len == 1) ? 0 : 1)); + } + else + { + UInt32 distance = p->reps[pos]; + RangeEnc_EncodeBit(&p->rc, &p->isRepG0[p->state], 1); + if (pos == 1) + RangeEnc_EncodeBit(&p->rc, &p->isRepG1[p->state], 0); + else + { + RangeEnc_EncodeBit(&p->rc, &p->isRepG1[p->state], 1); + RangeEnc_EncodeBit(&p->rc, &p->isRepG2[p->state], pos - 2); + if (pos == 3) + p->reps[3] = p->reps[2]; + p->reps[2] = p->reps[1]; + } + p->reps[1] = p->reps[0]; + p->reps[0] = distance; + } + if (len == 1) + p->state = kShortRepNextStates[p->state]; + else + { + LenEnc_Encode2(&p->repLenEnc, &p->rc, len - LZMA_MATCH_LEN_MIN, posState, !p->fastMode, p->ProbPrices); + p->state = kRepNextStates[p->state]; + } + } + else + { + UInt32 posSlot; + RangeEnc_EncodeBit(&p->rc, &p->isRep[p->state], 0); + p->state = kMatchNextStates[p->state]; + LenEnc_Encode2(&p->lenEnc, &p->rc, len - LZMA_MATCH_LEN_MIN, posState, !p->fastMode, p->ProbPrices); + pos -= LZMA_NUM_REPS; + GetPosSlot(pos, posSlot); + RcTree_Encode(&p->rc, p->posSlotEncoder[GetLenToPosState(len)], kNumPosSlotBits, posSlot); + + if (posSlot >= kStartPosModelIndex) + { + UInt32 footerBits = ((posSlot >> 1) - 1); + UInt32 base = ((2 | (posSlot & 1)) << footerBits); + UInt32 posReduced = pos - base; + + if (posSlot < kEndPosModelIndex) + RcTree_ReverseEncode(&p->rc, p->posEncoders + base - posSlot - 1, footerBits, posReduced); + else + { + RangeEnc_EncodeDirectBits(&p->rc, posReduced >> kNumAlignBits, footerBits - kNumAlignBits); + RcTree_ReverseEncode(&p->rc, p->posAlignEncoder, kNumAlignBits, posReduced & kAlignMask); + p->alignPriceCount++; + } + } + p->reps[3] = p->reps[2]; + p->reps[2] = p->reps[1]; + p->reps[1] = p->reps[0]; + p->reps[0] = pos; + p->matchPriceCount++; + } + } + p->additionalOffset -= len; + nowPos32 += len; + if (p->additionalOffset == 0) + { + UInt32 processed; + if (!p->fastMode) + { + if (p->matchPriceCount >= (1 << 7)) + FillDistancesPrices(p); + if (p->alignPriceCount >= kAlignTableSize) + FillAlignPrices(p); + } + if (p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) == 0) + break; + processed = nowPos32 - startPos32; + if (useLimits) + { + if (processed + kNumOpts + 300 >= maxUnpackSize || + RangeEnc_GetProcessed(&p->rc) + kNumOpts * 2 >= maxPackSize) + break; + } + else if (processed >= (1 << 15)) + { + p->nowPos64 += nowPos32 - startPos32; + return CheckErrors(p); + } + } + } + p->nowPos64 += nowPos32 - startPos32; + return Flush(p, nowPos32); +} + +#define kBigHashDicLimit ((UInt32)1 << 24) + +static SRes LzmaEnc_Alloc(CLzmaEnc *p, UInt32 keepWindowSize, ISzAlloc *alloc, ISzAlloc *allocBig) +{ + UInt32 beforeSize = kNumOpts; + Bool btMode; + if (!RangeEnc_Alloc(&p->rc, alloc)) + return SZ_ERROR_MEM; + btMode = (p->matchFinderBase.btMode != 0); + #ifdef COMPRESS_MF_MT + p->mtMode = (p->multiThread && !p->fastMode && btMode); + #endif + + { + unsigned lclp = p->lc + p->lp; + if (p->litProbs == 0 || p->saveState.litProbs == 0 || p->lclp != lclp) + { + LzmaEnc_FreeLits(p, alloc); + p->litProbs = (CLzmaProb *)alloc->Alloc(alloc, (0x300 << lclp) * sizeof(CLzmaProb)); + p->saveState.litProbs = (CLzmaProb *)alloc->Alloc(alloc, (0x300 << lclp) * sizeof(CLzmaProb)); + if (p->litProbs == 0 || p->saveState.litProbs == 0) + { + LzmaEnc_FreeLits(p, alloc); + return SZ_ERROR_MEM; + } + p->lclp = lclp; + } + } + + p->matchFinderBase.bigHash = (p->dictSize > kBigHashDicLimit); + + if (beforeSize + p->dictSize < keepWindowSize) + beforeSize = keepWindowSize - p->dictSize; + + #ifdef COMPRESS_MF_MT + if (p->mtMode) + { + RINOK(MatchFinderMt_Create(&p->matchFinderMt, p->dictSize, beforeSize, p->numFastBytes, LZMA_MATCH_LEN_MAX, allocBig)); + p->matchFinderObj = &p->matchFinderMt; + MatchFinderMt_CreateVTable(&p->matchFinderMt, &p->matchFinder); + } + else + #endif + { + if (!MatchFinder_Create(&p->matchFinderBase, p->dictSize, beforeSize, p->numFastBytes, LZMA_MATCH_LEN_MAX, allocBig)) + return SZ_ERROR_MEM; + p->matchFinderObj = &p->matchFinderBase; + MatchFinder_CreateVTable(&p->matchFinderBase, &p->matchFinder); + } + return SZ_OK; +} + +void LzmaEnc_Init(CLzmaEnc *p) +{ + UInt32 i; + p->state = 0; + for (i = 0 ; i < LZMA_NUM_REPS; i++) + p->reps[i] = 0; + + RangeEnc_Init(&p->rc); + + + for (i = 0; i < kNumStates; i++) + { + UInt32 j; + for (j = 0; j < LZMA_NUM_PB_STATES_MAX; j++) + { + p->isMatch[i][j] = kProbInitValue; + p->isRep0Long[i][j] = kProbInitValue; + } + p->isRep[i] = kProbInitValue; + p->isRepG0[i] = kProbInitValue; + p->isRepG1[i] = kProbInitValue; + p->isRepG2[i] = kProbInitValue; + } + + { + UInt32 num = 0x300 << (p->lp + p->lc); + for (i = 0; i < num; i++) + p->litProbs[i] = kProbInitValue; + } + + { + for (i = 0; i < kNumLenToPosStates; i++) + { + CLzmaProb *probs = p->posSlotEncoder[i]; + UInt32 j; + for (j = 0; j < (1 << kNumPosSlotBits); j++) + probs[j] = kProbInitValue; + } + } + { + for (i = 0; i < kNumFullDistances - kEndPosModelIndex; i++) + p->posEncoders[i] = kProbInitValue; + } + + LenEnc_Init(&p->lenEnc.p); + LenEnc_Init(&p->repLenEnc.p); + + for (i = 0; i < (1 << kNumAlignBits); i++) + p->posAlignEncoder[i] = kProbInitValue; + + p->optimumEndIndex = 0; + p->optimumCurrentIndex = 0; + p->additionalOffset = 0; + + p->pbMask = (1 << p->pb) - 1; + p->lpMask = (1 << p->lp) - 1; +} + +void LzmaEnc_InitPrices(CLzmaEnc *p) +{ + if (!p->fastMode) + { + FillDistancesPrices(p); + FillAlignPrices(p); + } + + p->lenEnc.tableSize = + p->repLenEnc.tableSize = + p->numFastBytes + 1 - LZMA_MATCH_LEN_MIN; + LenPriceEnc_UpdateTables(&p->lenEnc, 1 << p->pb, p->ProbPrices); + LenPriceEnc_UpdateTables(&p->repLenEnc, 1 << p->pb, p->ProbPrices); +} + +static SRes LzmaEnc_AllocAndInit(CLzmaEnc *p, UInt32 keepWindowSize, ISzAlloc *alloc, ISzAlloc *allocBig) +{ + UInt32 i; + for (i = 0; i < (UInt32)kDicLogSizeMaxCompress; i++) + if (p->dictSize <= ((UInt32)1 << i)) + break; + p->distTableSize = i * 2; + + p->finished = False; + p->result = SZ_OK; + RINOK(LzmaEnc_Alloc(p, keepWindowSize, alloc, allocBig)); + LzmaEnc_Init(p); + LzmaEnc_InitPrices(p); + p->nowPos64 = 0; + return SZ_OK; +} + +static SRes LzmaEnc_Prepare(CLzmaEncHandle pp, ISeqInStream *inStream, ISeqOutStream *outStream, + ISzAlloc *alloc, ISzAlloc *allocBig) +{ + CLzmaEnc *p = (CLzmaEnc *)pp; + p->inStream = inStream; + p->rc.outStream = outStream; + return LzmaEnc_AllocAndInit(p, 0, alloc, allocBig); +} + +SRes LzmaEnc_PrepareForLzma2(CLzmaEncHandle pp, + ISeqInStream *inStream, UInt32 keepWindowSize, + ISzAlloc *alloc, ISzAlloc *allocBig) +{ + CLzmaEnc *p = (CLzmaEnc *)pp; + p->inStream = inStream; + return LzmaEnc_AllocAndInit(p, keepWindowSize, alloc, allocBig); +} + +static void LzmaEnc_SetInputBuf(CLzmaEnc *p, const Byte *src, SizeT srcLen) +{ + p->seqBufInStream.funcTable.Read = MyRead; + p->seqBufInStream.data = src; + p->seqBufInStream.rem = srcLen; +} + +SRes LzmaEnc_MemPrepare(CLzmaEncHandle pp, const Byte *src, SizeT srcLen, + UInt32 keepWindowSize, ISzAlloc *alloc, ISzAlloc *allocBig) +{ + CLzmaEnc *p = (CLzmaEnc *)pp; + LzmaEnc_SetInputBuf(p, src, srcLen); + p->inStream = &p->seqBufInStream.funcTable; + return LzmaEnc_AllocAndInit(p, keepWindowSize, alloc, allocBig); +} + +void LzmaEnc_Finish(CLzmaEncHandle pp) +{ + #ifdef COMPRESS_MF_MT + CLzmaEnc *p = (CLzmaEnc *)pp; + if (p->mtMode) + MatchFinderMt_ReleaseStream(&p->matchFinderMt); + #else + pp = pp; + #endif +} + +typedef struct _CSeqOutStreamBuf +{ + ISeqOutStream funcTable; + Byte *data; + SizeT rem; + Bool overflow; +} CSeqOutStreamBuf; + +static size_t MyWrite(void *pp, const void *data, size_t size) +{ + CSeqOutStreamBuf *p = (CSeqOutStreamBuf *)pp; + if (p->rem < size) + { + size = p->rem; + p->overflow = True; + } + memcpy(p->data, data, size); + p->rem -= size; + p->data += size; + return size; +} + + +UInt32 LzmaEnc_GetNumAvailableBytes(CLzmaEncHandle pp) +{ + const CLzmaEnc *p = (CLzmaEnc *)pp; + return p->matchFinder.GetNumAvailableBytes(p->matchFinderObj); +} + +const Byte *LzmaEnc_GetCurBuf(CLzmaEncHandle pp) +{ + const CLzmaEnc *p = (CLzmaEnc *)pp; + return p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - p->additionalOffset; +} + +SRes LzmaEnc_CodeOneMemBlock(CLzmaEncHandle pp, Bool reInit, + Byte *dest, size_t *destLen, UInt32 desiredPackSize, UInt32 *unpackSize) +{ + CLzmaEnc *p = (CLzmaEnc *)pp; + UInt64 nowPos64; + SRes res; + CSeqOutStreamBuf outStream; + + outStream.funcTable.Write = MyWrite; + outStream.data = dest; + outStream.rem = *destLen; + outStream.overflow = False; + + p->writeEndMark = False; + p->finished = False; + p->result = SZ_OK; + + if (reInit) + LzmaEnc_Init(p); + LzmaEnc_InitPrices(p); + nowPos64 = p->nowPos64; + RangeEnc_Init(&p->rc); + p->rc.outStream = &outStream.funcTable; + + res = LzmaEnc_CodeOneBlock(p, True, desiredPackSize, *unpackSize); + + *unpackSize = (UInt32)(p->nowPos64 - nowPos64); + *destLen -= outStream.rem; + if (outStream.overflow) + return SZ_ERROR_OUTPUT_EOF; + + return res; +} + +SRes LzmaEnc_Encode(CLzmaEncHandle pp, ISeqOutStream *outStream, ISeqInStream *inStream, ICompressProgress *progress, + ISzAlloc *alloc, ISzAlloc *allocBig) +{ + CLzmaEnc *p = (CLzmaEnc *)pp; + SRes res = SZ_OK; + + #ifdef COMPRESS_MF_MT + Byte allocaDummy[0x300]; + int i = 0; + for (i = 0; i < 16; i++) + allocaDummy[i] = (Byte)i; + #endif + + RINOK(LzmaEnc_Prepare(pp, inStream, outStream, alloc, allocBig)); + + for (;;) + { + res = LzmaEnc_CodeOneBlock(p, False, 0, 0); + if (res != SZ_OK || p->finished != 0) + break; + if (progress != 0) + { + res = progress->Progress(progress, p->nowPos64, RangeEnc_GetProcessed(&p->rc)); + if (res != SZ_OK) + { + res = SZ_ERROR_PROGRESS; + break; + } + } + } + LzmaEnc_Finish(pp); + return res; +} + +SRes LzmaEnc_WriteProperties(CLzmaEncHandle pp, Byte *props, SizeT *size) +{ + CLzmaEnc *p = (CLzmaEnc *)pp; + int i; + UInt32 dictSize = p->dictSize; + if (*size < LZMA_PROPS_SIZE) + return SZ_ERROR_PARAM; + *size = LZMA_PROPS_SIZE; + props[0] = (Byte)((p->pb * 5 + p->lp) * 9 + p->lc); + + for (i = 11; i <= 30; i++) + { + if (dictSize <= ((UInt32)2 << i)) + { + dictSize = (2 << i); + break; + } + if (dictSize <= ((UInt32)3 << i)) + { + dictSize = (3 << i); + break; + } + } + + for (i = 0; i < 4; i++) + props[1 + i] = (Byte)(dictSize >> (8 * i)); + return SZ_OK; +} + +SRes LzmaEnc_MemEncode(CLzmaEncHandle pp, Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen, + int writeEndMark, ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig) +{ + SRes res; + CLzmaEnc *p = (CLzmaEnc *)pp; + + CSeqOutStreamBuf outStream; + + LzmaEnc_SetInputBuf(p, src, srcLen); + + outStream.funcTable.Write = MyWrite; + outStream.data = dest; + outStream.rem = *destLen; + outStream.overflow = False; + + p->writeEndMark = writeEndMark; + res = LzmaEnc_Encode(pp, &outStream.funcTable, &p->seqBufInStream.funcTable, + progress, alloc, allocBig); + + *destLen -= outStream.rem; + if (outStream.overflow) + return SZ_ERROR_OUTPUT_EOF; + return res; +} + +SRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen, + const CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark, + ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig) +{ + CLzmaEnc *p = (CLzmaEnc *)LzmaEnc_Create(alloc); + SRes res; + if (p == 0) + return SZ_ERROR_MEM; + + res = LzmaEnc_SetProps(p, props); + if (res == SZ_OK) + { + res = LzmaEnc_WriteProperties(p, propsEncoded, propsSize); + if (res == SZ_OK) + res = LzmaEnc_MemEncode(p, dest, destLen, src, srcLen, + writeEndMark, progress, alloc, allocBig); + } + + LzmaEnc_Destroy(p, alloc, allocBig); + return res; +} diff --git a/BaseTools/Source/C/LzmaCompress/Sdk/C/LzmaEnc.h b/BaseTools/Source/C/LzmaCompress/Sdk/C/LzmaEnc.h new file mode 100644 index 0000000000..e3d84fa35e --- /dev/null +++ b/BaseTools/Source/C/LzmaCompress/Sdk/C/LzmaEnc.h @@ -0,0 +1,72 @@ +/* LzmaEnc.h -- LZMA Encoder +2008-10-04 : Igor Pavlov : Public domain */ + +#ifndef __LZMAENC_H +#define __LZMAENC_H + +#include "Types.h" + +#define LZMA_PROPS_SIZE 5 + +typedef struct _CLzmaEncProps +{ + int level; /* 0 <= level <= 9 */ + UInt32 dictSize; /* (1 << 12) <= dictSize <= (1 << 27) for 32-bit version + (1 << 12) <= dictSize <= (1 << 30) for 64-bit version + default = (1 << 24) */ + int lc; /* 0 <= lc <= 8, default = 3 */ + int lp; /* 0 <= lp <= 4, default = 0 */ + int pb; /* 0 <= pb <= 4, default = 2 */ + int algo; /* 0 - fast, 1 - normal, default = 1 */ + int fb; /* 5 <= fb <= 273, default = 32 */ + int btMode; /* 0 - hashChain Mode, 1 - binTree mode - normal, default = 1 */ + int numHashBytes; /* 2, 3 or 4, default = 4 */ + UInt32 mc; /* 1 <= mc <= (1 << 30), default = 32 */ + unsigned writeEndMark; /* 0 - do not write EOPM, 1 - write EOPM, default = 0 */ + int numThreads; /* 1 or 2, default = 2 */ +} CLzmaEncProps; + +void LzmaEncProps_Init(CLzmaEncProps *p); +void LzmaEncProps_Normalize(CLzmaEncProps *p); +UInt32 LzmaEncProps_GetDictSize(const CLzmaEncProps *props2); + + +/* ---------- CLzmaEncHandle Interface ---------- */ + +/* LzmaEnc_* functions can return the following exit codes: +Returns: + SZ_OK - OK + SZ_ERROR_MEM - Memory allocation error + SZ_ERROR_PARAM - Incorrect paramater in props + SZ_ERROR_WRITE - Write callback error. + SZ_ERROR_PROGRESS - some break from progress callback + SZ_ERROR_THREAD - errors in multithreading functions (only for Mt version) +*/ + +typedef void * CLzmaEncHandle; + +CLzmaEncHandle LzmaEnc_Create(ISzAlloc *alloc); +void LzmaEnc_Destroy(CLzmaEncHandle p, ISzAlloc *alloc, ISzAlloc *allocBig); +SRes LzmaEnc_SetProps(CLzmaEncHandle p, const CLzmaEncProps *props); +SRes LzmaEnc_WriteProperties(CLzmaEncHandle p, Byte *properties, SizeT *size); +SRes LzmaEnc_Encode(CLzmaEncHandle p, ISeqOutStream *outStream, ISeqInStream *inStream, + ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig); +SRes LzmaEnc_MemEncode(CLzmaEncHandle p, Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen, + int writeEndMark, ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig); + +/* ---------- One Call Interface ---------- */ + +/* LzmaEncode +Return code: + SZ_OK - OK + SZ_ERROR_MEM - Memory allocation error + SZ_ERROR_PARAM - Incorrect paramater + SZ_ERROR_OUTPUT_EOF - output buffer overflow + SZ_ERROR_THREAD - errors in multithreading functions (only for Mt version) +*/ + +SRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen, + const CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark, + ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig); + +#endif diff --git a/BaseTools/Source/C/LzmaCompress/Sdk/C/Threads.c b/BaseTools/Source/C/LzmaCompress/Sdk/C/Threads.c new file mode 100644 index 0000000000..c7d8b0a8ab --- /dev/null +++ b/BaseTools/Source/C/LzmaCompress/Sdk/C/Threads.c @@ -0,0 +1,109 @@ +/* Threads.c -- multithreading library +2008-08-05 +Igor Pavlov +Public domain */ + +#include "Threads.h" +#include + +static WRes GetError() +{ + DWORD res = GetLastError(); + return (res) ? (WRes)(res) : 1; +} + +WRes HandleToWRes(HANDLE h) { return (h != 0) ? 0 : GetError(); } +WRes BOOLToWRes(BOOL v) { return v ? 0 : GetError(); } + +static WRes MyCloseHandle(HANDLE *h) +{ + if (*h != NULL) + if (!CloseHandle(*h)) + return GetError(); + *h = NULL; + return 0; +} + +WRes Thread_Create(CThread *thread, THREAD_FUNC_RET_TYPE (THREAD_FUNC_CALL_TYPE *startAddress)(void *), LPVOID parameter) +{ + unsigned threadId; /* Windows Me/98/95: threadId parameter may not be NULL in _beginthreadex/CreateThread functions */ + thread->handle = + /* CreateThread(0, 0, startAddress, parameter, 0, &threadId); */ + (HANDLE)_beginthreadex(NULL, 0, startAddress, parameter, 0, &threadId); + /* maybe we must use errno here, but probably GetLastError() is also OK. */ + return HandleToWRes(thread->handle); +} + +WRes WaitObject(HANDLE h) +{ + return (WRes)WaitForSingleObject(h, INFINITE); +} + +WRes Thread_Wait(CThread *thread) +{ + if (thread->handle == NULL) + return 1; + return WaitObject(thread->handle); +} + +WRes Thread_Close(CThread *thread) +{ + return MyCloseHandle(&thread->handle); +} + +WRes Event_Create(CEvent *p, BOOL manualReset, int initialSignaled) +{ + p->handle = CreateEvent(NULL, manualReset, (initialSignaled ? TRUE : FALSE), NULL); + return HandleToWRes(p->handle); +} + +WRes ManualResetEvent_Create(CManualResetEvent *p, int initialSignaled) + { return Event_Create(p, TRUE, initialSignaled); } +WRes ManualResetEvent_CreateNotSignaled(CManualResetEvent *p) + { return ManualResetEvent_Create(p, 0); } + +WRes AutoResetEvent_Create(CAutoResetEvent *p, int initialSignaled) + { return Event_Create(p, FALSE, initialSignaled); } +WRes AutoResetEvent_CreateNotSignaled(CAutoResetEvent *p) + { return AutoResetEvent_Create(p, 0); } + +WRes Event_Set(CEvent *p) { return BOOLToWRes(SetEvent(p->handle)); } +WRes Event_Reset(CEvent *p) { return BOOLToWRes(ResetEvent(p->handle)); } +WRes Event_Wait(CEvent *p) { return WaitObject(p->handle); } +WRes Event_Close(CEvent *p) { return MyCloseHandle(&p->handle); } + + +WRes Semaphore_Create(CSemaphore *p, UInt32 initiallyCount, UInt32 maxCount) +{ + p->handle = CreateSemaphore(NULL, (LONG)initiallyCount, (LONG)maxCount, NULL); + return HandleToWRes(p->handle); +} + +WRes Semaphore_Release(CSemaphore *p, LONG releaseCount, LONG *previousCount) +{ + return BOOLToWRes(ReleaseSemaphore(p->handle, releaseCount, previousCount)); +} +WRes Semaphore_ReleaseN(CSemaphore *p, UInt32 releaseCount) +{ + return Semaphore_Release(p, (LONG)releaseCount, NULL); +} +WRes Semaphore_Release1(CSemaphore *p) +{ + return Semaphore_ReleaseN(p, 1); +} + +WRes Semaphore_Wait(CSemaphore *p) { return WaitObject(p->handle); } +WRes Semaphore_Close(CSemaphore *p) { return MyCloseHandle(&p->handle); } + +WRes CriticalSection_Init(CCriticalSection *p) +{ + /* InitializeCriticalSection can raise only STATUS_NO_MEMORY exception */ + __try + { + InitializeCriticalSection(p); + /* InitializeCriticalSectionAndSpinCount(p, 0); */ + } + __except (EXCEPTION_EXECUTE_HANDLER) { return 1; } + return 0; +} + diff --git a/BaseTools/Source/C/LzmaCompress/Sdk/C/Threads.h b/BaseTools/Source/C/LzmaCompress/Sdk/C/Threads.h new file mode 100644 index 0000000000..3d9072946e --- /dev/null +++ b/BaseTools/Source/C/LzmaCompress/Sdk/C/Threads.h @@ -0,0 +1,68 @@ +/* Threads.h -- multithreading library +2008-11-22 : Igor Pavlov : Public domain */ + +#ifndef __7Z_THRESDS_H +#define __7Z_THRESDS_H + +#include "Types.h" + +typedef struct _CThread +{ + HANDLE handle; +} CThread; + +#define Thread_Construct(thread) (thread)->handle = NULL +#define Thread_WasCreated(thread) ((thread)->handle != NULL) + +typedef unsigned THREAD_FUNC_RET_TYPE; +#define THREAD_FUNC_CALL_TYPE MY_STD_CALL +#define THREAD_FUNC_DECL THREAD_FUNC_RET_TYPE THREAD_FUNC_CALL_TYPE + +WRes Thread_Create(CThread *thread, THREAD_FUNC_RET_TYPE (THREAD_FUNC_CALL_TYPE *startAddress)(void *), LPVOID parameter); +WRes Thread_Wait(CThread *thread); +WRes Thread_Close(CThread *thread); + +typedef struct _CEvent +{ + HANDLE handle; +} CEvent; + +typedef CEvent CAutoResetEvent; +typedef CEvent CManualResetEvent; + +#define Event_Construct(event) (event)->handle = NULL +#define Event_IsCreated(event) ((event)->handle != NULL) + +WRes ManualResetEvent_Create(CManualResetEvent *event, int initialSignaled); +WRes ManualResetEvent_CreateNotSignaled(CManualResetEvent *event); +WRes AutoResetEvent_Create(CAutoResetEvent *event, int initialSignaled); +WRes AutoResetEvent_CreateNotSignaled(CAutoResetEvent *event); +WRes Event_Set(CEvent *event); +WRes Event_Reset(CEvent *event); +WRes Event_Wait(CEvent *event); +WRes Event_Close(CEvent *event); + + +typedef struct _CSemaphore +{ + HANDLE handle; +} CSemaphore; + +#define Semaphore_Construct(p) (p)->handle = NULL + +WRes Semaphore_Create(CSemaphore *p, UInt32 initiallyCount, UInt32 maxCount); +WRes Semaphore_ReleaseN(CSemaphore *p, UInt32 num); +WRes Semaphore_Release1(CSemaphore *p); +WRes Semaphore_Wait(CSemaphore *p); +WRes Semaphore_Close(CSemaphore *p); + + +typedef CRITICAL_SECTION CCriticalSection; + +WRes CriticalSection_Init(CCriticalSection *p); +#define CriticalSection_Delete(p) DeleteCriticalSection(p) +#define CriticalSection_Enter(p) EnterCriticalSection(p) +#define CriticalSection_Leave(p) LeaveCriticalSection(p) + +#endif + diff --git a/BaseTools/Source/C/LzmaCompress/Sdk/C/Types.h b/BaseTools/Source/C/LzmaCompress/Sdk/C/Types.h new file mode 100644 index 0000000000..2638196aac --- /dev/null +++ b/BaseTools/Source/C/LzmaCompress/Sdk/C/Types.h @@ -0,0 +1,208 @@ +/* Types.h -- Basic types +2008-11-23 : Igor Pavlov : Public domain */ + +#ifndef __7Z_TYPES_H +#define __7Z_TYPES_H + +#include + +#ifdef _WIN32 +#include +#endif + +#define SZ_OK 0 + +#define SZ_ERROR_DATA 1 +#define SZ_ERROR_MEM 2 +#define SZ_ERROR_CRC 3 +#define SZ_ERROR_UNSUPPORTED 4 +#define SZ_ERROR_PARAM 5 +#define SZ_ERROR_INPUT_EOF 6 +#define SZ_ERROR_OUTPUT_EOF 7 +#define SZ_ERROR_READ 8 +#define SZ_ERROR_WRITE 9 +#define SZ_ERROR_PROGRESS 10 +#define SZ_ERROR_FAIL 11 +#define SZ_ERROR_THREAD 12 + +#define SZ_ERROR_ARCHIVE 16 +#define SZ_ERROR_NO_ARCHIVE 17 + +typedef int SRes; + +#ifdef _WIN32 +typedef DWORD WRes; +#else +typedef int WRes; +#endif + +#ifndef RINOK +#define RINOK(x) { int __result__ = (x); if (__result__ != 0) return __result__; } +#endif + +typedef unsigned char Byte; +typedef short Int16; +typedef unsigned short UInt16; + +#ifdef _LZMA_UINT32_IS_ULONG +typedef long Int32; +typedef unsigned long UInt32; +#else +typedef int Int32; +typedef unsigned int UInt32; +#endif + +#ifdef _SZ_NO_INT_64 + +/* define _SZ_NO_INT_64, if your compiler doesn't support 64-bit integers. + NOTES: Some code will work incorrectly in that case! */ + +typedef long Int64; +typedef unsigned long UInt64; + +#else + +#if defined(_MSC_VER) || defined(__BORLANDC__) +typedef __int64 Int64; +typedef unsigned __int64 UInt64; +#else +typedef long long int Int64; +typedef unsigned long long int UInt64; +#endif + +#endif + +#ifdef _LZMA_NO_SYSTEM_SIZE_T +typedef UInt32 SizeT; +#else +typedef size_t SizeT; +#endif + +typedef int Bool; +#define True 1 +#define False 0 + + +#ifdef _MSC_VER + +#if _MSC_VER >= 1300 +#define MY_NO_INLINE __declspec(noinline) +#else +#define MY_NO_INLINE +#endif + +#define MY_CDECL __cdecl +#define MY_STD_CALL __stdcall +#define MY_FAST_CALL MY_NO_INLINE __fastcall + +#else + +#define MY_CDECL +#define MY_STD_CALL +#define MY_FAST_CALL + +#endif + + +/* The following interfaces use first parameter as pointer to structure */ + +typedef struct +{ + SRes (*Read)(void *p, void *buf, size_t *size); + /* if (input(*size) != 0 && output(*size) == 0) means end_of_stream. + (output(*size) < input(*size)) is allowed */ +} ISeqInStream; + +/* it can return SZ_ERROR_INPUT_EOF */ +SRes SeqInStream_Read(ISeqInStream *stream, void *buf, size_t size); +SRes SeqInStream_Read2(ISeqInStream *stream, void *buf, size_t size, SRes errorType); +SRes SeqInStream_ReadByte(ISeqInStream *stream, Byte *buf); + +typedef struct +{ + size_t (*Write)(void *p, const void *buf, size_t size); + /* Returns: result - the number of actually written bytes. + (result < size) means error */ +} ISeqOutStream; + +typedef enum +{ + SZ_SEEK_SET = 0, + SZ_SEEK_CUR = 1, + SZ_SEEK_END = 2 +} ESzSeek; + +typedef struct +{ + SRes (*Read)(void *p, void *buf, size_t *size); /* same as ISeqInStream::Read */ + SRes (*Seek)(void *p, Int64 *pos, ESzSeek origin); +} ISeekInStream; + +typedef struct +{ + SRes (*Look)(void *p, void **buf, size_t *size); + /* if (input(*size) != 0 && output(*size) == 0) means end_of_stream. + (output(*size) > input(*size)) is not allowed + (output(*size) < input(*size)) is allowed */ + SRes (*Skip)(void *p, size_t offset); + /* offset must be <= output(*size) of Look */ + + SRes (*Read)(void *p, void *buf, size_t *size); + /* reads directly (without buffer). It's same as ISeqInStream::Read */ + SRes (*Seek)(void *p, Int64 *pos, ESzSeek origin); +} ILookInStream; + +SRes LookInStream_LookRead(ILookInStream *stream, void *buf, size_t *size); +SRes LookInStream_SeekTo(ILookInStream *stream, UInt64 offset); + +/* reads via ILookInStream::Read */ +SRes LookInStream_Read2(ILookInStream *stream, void *buf, size_t size, SRes errorType); +SRes LookInStream_Read(ILookInStream *stream, void *buf, size_t size); + +#define LookToRead_BUF_SIZE (1 << 14) + +typedef struct +{ + ILookInStream s; + ISeekInStream *realStream; + size_t pos; + size_t size; + Byte buf[LookToRead_BUF_SIZE]; +} CLookToRead; + +void LookToRead_CreateVTable(CLookToRead *p, int lookahead); +void LookToRead_Init(CLookToRead *p); + +typedef struct +{ + ISeqInStream s; + ILookInStream *realStream; +} CSecToLook; + +void SecToLook_CreateVTable(CSecToLook *p); + +typedef struct +{ + ISeqInStream s; + ILookInStream *realStream; +} CSecToRead; + +void SecToRead_CreateVTable(CSecToRead *p); + +typedef struct +{ + SRes (*Progress)(void *p, UInt64 inSize, UInt64 outSize); + /* Returns: result. (result != SZ_OK) means break. + Value (UInt64)(Int64)-1 for size means unknown value. */ +} ICompressProgress; + +typedef struct +{ + void *(*Alloc)(void *p, size_t size); + void (*Free)(void *p, void *address); /* address can be 0 */ +} ISzAlloc; + +#define IAlloc_Alloc(p, size) (p)->Alloc((p), size) +#define IAlloc_Free(p, a) (p)->Free((p), a) + +#endif diff --git a/BaseTools/Source/C/LzmaCompress/Sdk/history.txt b/BaseTools/Source/C/LzmaCompress/Sdk/history.txt new file mode 100644 index 0000000000..9bed5ebbef --- /dev/null +++ b/BaseTools/Source/C/LzmaCompress/Sdk/history.txt @@ -0,0 +1,236 @@ +HISTORY of the LZMA SDK +----------------------- + +4.65 2009-02-03 +------------------------- +- Some minor fixes + + +4.63 2008-12-31 +------------------------- +- Some minor fixes + + +4.61 beta 2008-11-23 +------------------------- +- The bug in ANSI-C LZMA Decoder was fixed: + If encoded stream was corrupted, decoder could access memory + outside of allocated range. +- Some changes in ANSI-C 7z Decoder interfaces. +- LZMA SDK is placed in the public domain. + + +4.60 beta 2008-08-19 +------------------------- +- Some minor fixes. + + +4.59 beta 2008-08-13 +------------------------- +- The bug was fixed: + LZMA Encoder in fast compression mode could access memory outside of + allocated range in some rare cases. + + +4.58 beta 2008-05-05 +------------------------- +- ANSI-C LZMA Decoder was rewritten for speed optimizations. +- ANSI-C LZMA Encoder was included to LZMA SDK. +- C++ LZMA code now is just wrapper over ANSI-C code. + + +4.57 2007-12-12 +------------------------- +- Speed optimizations in Ñ++ LZMA Decoder. +- Small changes for more compatibility with some C/C++ compilers. + + +4.49 beta 2007-07-05 +------------------------- +- .7z ANSI-C Decoder: + - now it supports BCJ and BCJ2 filters + - now it supports files larger than 4 GB. + - now it supports "Last Write Time" field for files. +- C++ code for .7z archives compressing/decompressing from 7-zip + was included to LZMA SDK. + + +4.43 2006-06-04 +------------------------- +- Small changes for more compatibility with some C/C++ compilers. + + +4.42 2006-05-15 +------------------------- +- Small changes in .h files in ANSI-C version. + + +4.39 beta 2006-04-14 +------------------------- +- The bug in versions 4.33b:4.38b was fixed: + C++ version of LZMA encoder could not correctly compress + files larger than 2 GB with HC4 match finder (-mfhc4). + + +4.37 beta 2005-04-06 +------------------------- +- Fixes in C++ code: code could no be compiled if _NO_EXCEPTIONS was defined. + + +4.35 beta 2005-03-02 +------------------------- +- The bug was fixed in C++ version of LZMA Decoder: + If encoded stream was corrupted, decoder could access memory + outside of allocated range. + + +4.34 beta 2006-02-27 +------------------------- +- Compressing speed and memory requirements for compressing were increased +- LZMA now can use only these match finders: HC4, BT2, BT3, BT4 + + +4.32 2005-12-09 +------------------------- +- Java version of LZMA SDK was included + + +4.30 2005-11-20 +------------------------- +- Compression ratio was improved in -a2 mode +- Speed optimizations for compressing in -a2 mode +- -fb switch now supports values up to 273 +- The bug in 7z_C (7zIn.c) was fixed: + It used Alloc/Free functions from different memory pools. + So if program used two memory pools, it worked incorrectly. +- 7z_C: .7z format supporting was improved +- LZMA# SDK (C#.NET version) was included + + +4.27 (Updated) 2005-09-21 +------------------------- +- Some GUIDs/interfaces in C++ were changed. + IStream.h: + ISequentialInStream::Read now works as old ReadPart + ISequentialOutStream::Write now works as old WritePart + + +4.27 2005-08-07 +------------------------- +- The bug in LzmaDecodeSize.c was fixed: + if _LZMA_IN_CB and _LZMA_OUT_READ were defined, + decompressing worked incorrectly. + + +4.26 2005-08-05 +------------------------- +- Fixes in 7z_C code and LzmaTest.c: + previous versions could work incorrectly, + if malloc(0) returns 0 + + +4.23 2005-06-29 +------------------------- +- Small fixes in C++ code + + +4.22 2005-06-10 +------------------------- +- Small fixes + + +4.21 2005-06-08 +------------------------- +- Interfaces for ANSI-C LZMA Decoder (LzmaDecode.c) were changed +- New additional version of ANSI-C LZMA Decoder with zlib-like interface: + - LzmaStateDecode.h + - LzmaStateDecode.c + - LzmaStateTest.c +- ANSI-C LZMA Decoder now can decompress files larger than 4 GB + + +4.17 2005-04-18 +------------------------- +- New example for RAM->RAM compressing/decompressing: + LZMA + BCJ (filter for x86 code): + - LzmaRam.h + - LzmaRam.cpp + - LzmaRamDecode.h + - LzmaRamDecode.c + - -f86 switch for lzma.exe + + +4.16 2005-03-29 +------------------------- +- The bug was fixed in LzmaDecode.c (ANSI-C LZMA Decoder): + If _LZMA_OUT_READ was defined, and if encoded stream was corrupted, + decoder could access memory outside of allocated range. +- Speed optimization of ANSI-C LZMA Decoder (now it's about 20% faster). + Old version of LZMA Decoder now is in file LzmaDecodeSize.c. + LzmaDecodeSize.c can provide slightly smaller code than LzmaDecode.c +- Small speed optimization in LZMA C++ code +- filter for SPARC's code was added +- Simplified version of .7z ANSI-C Decoder was included + + +4.06 2004-09-05 +------------------------- +- The bug in v4.05 was fixed: + LZMA-Encoder didn't release output stream in some cases. + + +4.05 2004-08-25 +------------------------- +- Source code of filters for x86, IA-64, ARM, ARM-Thumb + and PowerPC code was included to SDK +- Some internal minor changes + + +4.04 2004-07-28 +------------------------- +- More compatibility with some C++ compilers + + +4.03 2004-06-18 +------------------------- +- "Benchmark" command was added. It measures compressing + and decompressing speed and shows rating values. + Also it checks hardware errors. + + +4.02 2004-06-10 +------------------------- +- C++ LZMA Encoder/Decoder code now is more portable + and it can be compiled by GCC on Linux. + + +4.01 2004-02-15 +------------------------- +- Some detection of data corruption was enabled. + LzmaDecode.c / RangeDecoderReadByte + ..... + { + rd->ExtraBytes = 1; + return 0xFF; + } + + +4.00 2004-02-13 +------------------------- +- Original version of LZMA SDK + + + +HISTORY of the LZMA +------------------- + 2001-2008: Improvements to LZMA compressing/decompressing code, + keeping compatibility with original LZMA format + 1996-2001: Development of LZMA compression format + + Some milestones: + + 2001-08-30: LZMA compression was added to 7-Zip + 1999-01-02: First version of 7-Zip was released + + +End of document diff --git a/BaseTools/Source/C/LzmaCompress/Sdk/lzma.txt b/BaseTools/Source/C/LzmaCompress/Sdk/lzma.txt new file mode 100644 index 0000000000..d4f4af929a --- /dev/null +++ b/BaseTools/Source/C/LzmaCompress/Sdk/lzma.txt @@ -0,0 +1,594 @@ +LZMA SDK 4.65 +------------- + +LZMA SDK provides the documentation, samples, header files, libraries, +and tools you need to develop applications that use LZMA compression. + +LZMA is default and general compression method of 7z format +in 7-Zip compression program (www.7-zip.org). LZMA provides high +compression ratio and very fast decompression. + +LZMA is an improved version of famous LZ77 compression algorithm. +It was improved in way of maximum increasing of compression ratio, +keeping high decompression speed and low memory requirements for +decompressing. + + + +LICENSE +------- + +LZMA SDK is written and placed in the public domain by Igor Pavlov. + + +LZMA SDK Contents +----------------- + +LZMA SDK includes: + + - ANSI-C/C++/C#/Java source code for LZMA compressing and decompressing + - Compiled file->file LZMA compressing/decompressing program for Windows system + + +UNIX/Linux version +------------------ +To compile C++ version of file->file LZMA encoding, go to directory +C++/7zip/Compress/LZMA_Alone +and call make to recompile it: + make -f makefile.gcc clean all + +In some UNIX/Linux versions you must compile LZMA with static libraries. +To compile with static libraries, you can use +LIB = -lm -static + + +Files +--------------------- +lzma.txt - LZMA SDK description (this file) +7zFormat.txt - 7z Format description +7zC.txt - 7z ANSI-C Decoder description +methods.txt - Compression method IDs for .7z +lzma.exe - Compiled file->file LZMA encoder/decoder for Windows +history.txt - history of the LZMA SDK + + +Source code structure +--------------------- + +C/ - C files + 7zCrc*.* - CRC code + Alloc.* - Memory allocation functions + Bra*.* - Filters for x86, IA-64, ARM, ARM-Thumb, PowerPC and SPARC code + LzFind.* - Match finder for LZ (LZMA) encoders + LzFindMt.* - Match finder for LZ (LZMA) encoders for multithreading encoding + LzHash.h - Additional file for LZ match finder + LzmaDec.* - LZMA decoding + LzmaEnc.* - LZMA encoding + LzmaLib.* - LZMA Library for DLL calling + Types.h - Basic types for another .c files + Threads.* - The code for multithreading. + + LzmaLib - LZMA Library (.DLL for Windows) + + LzmaUtil - LZMA Utility (file->file LZMA encoder/decoder). + + Archive - files related to archiving + 7z - 7z ANSI-C Decoder + +CPP/ -- CPP files + + Common - common files for C++ projects + Windows - common files for Windows related code + + 7zip - files related to 7-Zip Project + + Common - common files for 7-Zip + + Compress - files related to compression/decompression + + Copy - Copy coder + RangeCoder - Range Coder (special code of compression/decompression) + LZMA - LZMA compression/decompression on C++ + LZMA_Alone - file->file LZMA compression/decompression + Branch - Filters for x86, IA-64, ARM, ARM-Thumb, PowerPC and SPARC code + + Archive - files related to archiving + + Common - common files for archive handling + 7z - 7z C++ Encoder/Decoder + + Bundles - Modules that are bundles of other modules + + Alone7z - 7zr.exe: Standalone version of 7z.exe that supports only 7z/LZMA/BCJ/BCJ2 + Format7zR - 7zr.dll: Reduced version of 7za.dll: extracting/compressing to 7z/LZMA/BCJ/BCJ2 + Format7zExtractR - 7zxr.dll: Reduced version of 7zxa.dll: extracting from 7z/LZMA/BCJ/BCJ2. + + UI - User Interface files + + Client7z - Test application for 7za.dll, 7zr.dll, 7zxr.dll + Common - Common UI files + Console - Code for console archiver + + + +CS/ - C# files + 7zip + Common - some common files for 7-Zip + Compress - files related to compression/decompression + LZ - files related to LZ (Lempel-Ziv) compression algorithm + LZMA - LZMA compression/decompression + LzmaAlone - file->file LZMA compression/decompression + RangeCoder - Range Coder (special code of compression/decompression) + +Java/ - Java files + SevenZip + Compression - files related to compression/decompression + LZ - files related to LZ (Lempel-Ziv) compression algorithm + LZMA - LZMA compression/decompression + RangeCoder - Range Coder (special code of compression/decompression) + + +C/C++ source code of LZMA SDK is part of 7-Zip project. +7-Zip source code can be downloaded from 7-Zip's SourceForge page: + + http://sourceforge.net/projects/sevenzip/ + + + +LZMA features +------------- + - Variable dictionary size (up to 1 GB) + - Estimated compressing speed: about 2 MB/s on 2 GHz CPU + - Estimated decompressing speed: + - 20-30 MB/s on 2 GHz Core 2 or AMD Athlon 64 + - 1-2 MB/s on 200 MHz ARM, MIPS, PowerPC or other simple RISC + - Small memory requirements for decompressing (16 KB + DictionarySize) + - Small code size for decompressing: 5-8 KB + +LZMA decoder uses only integer operations and can be +implemented in any modern 32-bit CPU (or on 16-bit CPU with some conditions). + +Some critical operations that affect the speed of LZMA decompression: + 1) 32*16 bit integer multiply + 2) Misspredicted branches (penalty mostly depends from pipeline length) + 3) 32-bit shift and arithmetic operations + +The speed of LZMA decompressing mostly depends from CPU speed. +Memory speed has no big meaning. But if your CPU has small data cache, +overall weight of memory speed will slightly increase. + + +How To Use +---------- + +Using LZMA encoder/decoder executable +-------------------------------------- + +Usage: LZMA inputFile outputFile [...] + + e: encode file + + d: decode file + + b: Benchmark. There are two tests: compressing and decompressing + with LZMA method. Benchmark shows rating in MIPS (million + instructions per second). Rating value is calculated from + measured speed and it is normalized with Intel's Core 2 results. + Also Benchmark checks possible hardware errors (RAM + errors in most cases). Benchmark uses these settings: + (-a1, -d21, -fb32, -mfbt4). You can change only -d parameter. + Also you can change the number of iterations. Example for 30 iterations: + LZMA b 30 + Default number of iterations is 10. + + + + + -a{N}: set compression mode 0 = fast, 1 = normal + default: 1 (normal) + + d{N}: Sets Dictionary size - [0, 30], default: 23 (8MB) + The maximum value for dictionary size is 1 GB = 2^30 bytes. + Dictionary size is calculated as DictionarySize = 2^N bytes. + For decompressing file compressed by LZMA method with dictionary + size D = 2^N you need about D bytes of memory (RAM). + + -fb{N}: set number of fast bytes - [5, 273], default: 128 + Usually big number gives a little bit better compression ratio + and slower compression process. + + -lc{N}: set number of literal context bits - [0, 8], default: 3 + Sometimes lc=4 gives gain for big files. + + -lp{N}: set number of literal pos bits - [0, 4], default: 0 + lp switch is intended for periodical data when period is + equal 2^N. For example, for 32-bit (4 bytes) + periodical data you can use lp=2. Often it's better to set lc0, + if you change lp switch. + + -pb{N}: set number of pos bits - [0, 4], default: 2 + pb switch is intended for periodical data + when period is equal 2^N. + + -mf{MF_ID}: set Match Finder. Default: bt4. + Algorithms from hc* group doesn't provide good compression + ratio, but they often works pretty fast in combination with + fast mode (-a0). + + Memory requirements depend from dictionary size + (parameter "d" in table below). + + MF_ID Memory Description + + bt2 d * 9.5 + 4MB Binary Tree with 2 bytes hashing. + bt3 d * 11.5 + 4MB Binary Tree with 3 bytes hashing. + bt4 d * 11.5 + 4MB Binary Tree with 4 bytes hashing. + hc4 d * 7.5 + 4MB Hash Chain with 4 bytes hashing. + + -eos: write End Of Stream marker. By default LZMA doesn't write + eos marker, since LZMA decoder knows uncompressed size + stored in .lzma file header. + + -si: Read data from stdin (it will write End Of Stream marker). + -so: Write data to stdout + + +Examples: + +1) LZMA e file.bin file.lzma -d16 -lc0 + +compresses file.bin to file.lzma with 64 KB dictionary (2^16=64K) +and 0 literal context bits. -lc0 allows to reduce memory requirements +for decompression. + + +2) LZMA e file.bin file.lzma -lc0 -lp2 + +compresses file.bin to file.lzma with settings suitable +for 32-bit periodical data (for example, ARM or MIPS code). + +3) LZMA d file.lzma file.bin + +decompresses file.lzma to file.bin. + + +Compression ratio hints +----------------------- + +Recommendations +--------------- + +To increase the compression ratio for LZMA compressing it's desirable +to have aligned data (if it's possible) and also it's desirable to locate +data in such order, where code is grouped in one place and data is +grouped in other place (it's better than such mixing: code, data, code, +data, ...). + + +Filters +------- +You can increase the compression ratio for some data types, using +special filters before compressing. For example, it's possible to +increase the compression ratio on 5-10% for code for those CPU ISAs: +x86, IA-64, ARM, ARM-Thumb, PowerPC, SPARC. + +You can find C source code of such filters in C/Bra*.* files + +You can check the compression ratio gain of these filters with such +7-Zip commands (example for ARM code): +No filter: + 7z a a1.7z a.bin -m0=lzma + +With filter for little-endian ARM code: + 7z a a2.7z a.bin -m0=arm -m1=lzma + +It works in such manner: +Compressing = Filter_encoding + LZMA_encoding +Decompressing = LZMA_decoding + Filter_decoding + +Compressing and decompressing speed of such filters is very high, +so it will not increase decompressing time too much. +Moreover, it reduces decompression time for LZMA_decoding, +since compression ratio with filtering is higher. + +These filters convert CALL (calling procedure) instructions +from relative offsets to absolute addresses, so such data becomes more +compressible. + +For some ISAs (for example, for MIPS) it's impossible to get gain from such filter. + + +LZMA compressed file format +--------------------------- +Offset Size Description + 0 1 Special LZMA properties (lc,lp, pb in encoded form) + 1 4 Dictionary size (little endian) + 5 8 Uncompressed size (little endian). -1 means unknown size + 13 Compressed data + + +ANSI-C LZMA Decoder +~~~~~~~~~~~~~~~~~~~ + +Please note that interfaces for ANSI-C code were changed in LZMA SDK 4.58. +If you want to use old interfaces you can download previous version of LZMA SDK +from sourceforge.net site. + +To use ANSI-C LZMA Decoder you need the following files: +1) LzmaDec.h + LzmaDec.c + Types.h +LzmaUtil/LzmaUtil.c is example application that uses these files. + + +Memory requirements for LZMA decoding +------------------------------------- + +Stack usage of LZMA decoding function for local variables is not +larger than 200-400 bytes. + +LZMA Decoder uses dictionary buffer and internal state structure. +Internal state structure consumes + state_size = (4 + (1.5 << (lc + lp))) KB +by default (lc=3, lp=0), state_size = 16 KB. + + +How To decompress data +---------------------- + +LZMA Decoder (ANSI-C version) now supports 2 interfaces: +1) Single-call Decompressing +2) Multi-call State Decompressing (zlib-like interface) + +You must use external allocator: +Example: +void *SzAlloc(void *p, size_t size) { p = p; return malloc(size); } +void SzFree(void *p, void *address) { p = p; free(address); } +ISzAlloc alloc = { SzAlloc, SzFree }; + +You can use p = p; operator to disable compiler warnings. + + +Single-call Decompressing +------------------------- +When to use: RAM->RAM decompressing +Compile files: LzmaDec.h + LzmaDec.c + Types.h +Compile defines: no defines +Memory Requirements: + - Input buffer: compressed size + - Output buffer: uncompressed size + - LZMA Internal Structures: state_size (16 KB for default settings) + +Interface: + int LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, + const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode, + ELzmaStatus *status, ISzAlloc *alloc); + In: + dest - output data + destLen - output data size + src - input data + srcLen - input data size + propData - LZMA properties (5 bytes) + propSize - size of propData buffer (5 bytes) + finishMode - It has meaning only if the decoding reaches output limit (*destLen). + LZMA_FINISH_ANY - Decode just destLen bytes. + LZMA_FINISH_END - Stream must be finished after (*destLen). + You can use LZMA_FINISH_END, when you know that + current output buffer covers last bytes of stream. + alloc - Memory allocator. + + Out: + destLen - processed output size + srcLen - processed input size + + Output: + SZ_OK + status: + LZMA_STATUS_FINISHED_WITH_MARK + LZMA_STATUS_NOT_FINISHED + LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK + SZ_ERROR_DATA - Data error + SZ_ERROR_MEM - Memory allocation error + SZ_ERROR_UNSUPPORTED - Unsupported properties + SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src). + + If LZMA decoder sees end_marker before reaching output limit, it returns OK result, + and output value of destLen will be less than output buffer size limit. + + You can use multiple checks to test data integrity after full decompression: + 1) Check Result and "status" variable. + 2) Check that output(destLen) = uncompressedSize, if you know real uncompressedSize. + 3) Check that output(srcLen) = compressedSize, if you know real compressedSize. + You must use correct finish mode in that case. */ + + +Multi-call State Decompressing (zlib-like interface) +---------------------------------------------------- + +When to use: file->file decompressing +Compile files: LzmaDec.h + LzmaDec.c + Types.h + +Memory Requirements: + - Buffer for input stream: any size (for example, 16 KB) + - Buffer for output stream: any size (for example, 16 KB) + - LZMA Internal Structures: state_size (16 KB for default settings) + - LZMA dictionary (dictionary size is encoded in LZMA properties header) + +1) read LZMA properties (5 bytes) and uncompressed size (8 bytes, little-endian) to header: + unsigned char header[LZMA_PROPS_SIZE + 8]; + ReadFile(inFile, header, sizeof(header) + +2) Allocate CLzmaDec structures (state + dictionary) using LZMA properties + + CLzmaDec state; + LzmaDec_Constr(&state); + res = LzmaDec_Allocate(&state, header, LZMA_PROPS_SIZE, &g_Alloc); + if (res != SZ_OK) + return res; + +3) Init LzmaDec structure before any new LZMA stream. And call LzmaDec_DecodeToBuf in loop + + LzmaDec_Init(&state); + for (;;) + { + ... + int res = LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen, + const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode); + ... + } + + +4) Free all allocated structures + LzmaDec_Free(&state, &g_Alloc); + +For full code example, look at C/LzmaUtil/LzmaUtil.c code. + + +How To compress data +-------------------- + +Compile files: LzmaEnc.h + LzmaEnc.c + Types.h + +LzFind.c + LzFind.h + LzFindMt.c + LzFindMt.h + LzHash.h + +Memory Requirements: + - (dictSize * 11.5 + 6 MB) + state_size + +Lzma Encoder can use two memory allocators: +1) alloc - for small arrays. +2) allocBig - for big arrays. + +For example, you can use Large RAM Pages (2 MB) in allocBig allocator for +better compression speed. Note that Windows has bad implementation for +Large RAM Pages. +It's OK to use same allocator for alloc and allocBig. + + +Single-call Compression with callbacks +-------------------------------------- + +Check C/LzmaUtil/LzmaUtil.c as example, + +When to use: file->file decompressing + +1) you must implement callback structures for interfaces: +ISeqInStream +ISeqOutStream +ICompressProgress +ISzAlloc + +static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); } +static void SzFree(void *p, void *address) { p = p; MyFree(address); } +static ISzAlloc g_Alloc = { SzAlloc, SzFree }; + + CFileSeqInStream inStream; + CFileSeqOutStream outStream; + + inStream.funcTable.Read = MyRead; + inStream.file = inFile; + outStream.funcTable.Write = MyWrite; + outStream.file = outFile; + + +2) Create CLzmaEncHandle object; + + CLzmaEncHandle enc; + + enc = LzmaEnc_Create(&g_Alloc); + if (enc == 0) + return SZ_ERROR_MEM; + + +3) initialize CLzmaEncProps properties; + + LzmaEncProps_Init(&props); + + Then you can change some properties in that structure. + +4) Send LZMA properties to LZMA Encoder + + res = LzmaEnc_SetProps(enc, &props); + +5) Write encoded properties to header + + Byte header[LZMA_PROPS_SIZE + 8]; + size_t headerSize = LZMA_PROPS_SIZE; + UInt64 fileSize; + int i; + + res = LzmaEnc_WriteProperties(enc, header, &headerSize); + fileSize = MyGetFileLength(inFile); + for (i = 0; i < 8; i++) + header[headerSize++] = (Byte)(fileSize >> (8 * i)); + MyWriteFileAndCheck(outFile, header, headerSize) + +6) Call encoding function: + res = LzmaEnc_Encode(enc, &outStream.funcTable, &inStream.funcTable, + NULL, &g_Alloc, &g_Alloc); + +7) Destroy LZMA Encoder Object + LzmaEnc_Destroy(enc, &g_Alloc, &g_Alloc); + + +If callback function return some error code, LzmaEnc_Encode also returns that code. + + +Single-call RAM->RAM Compression +-------------------------------- + +Single-call RAM->RAM Compression is similar to Compression with callbacks, +but you provide pointers to buffers instead of pointers to stream callbacks: + +HRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen, + CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark, + ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig); + +Return code: + SZ_OK - OK + SZ_ERROR_MEM - Memory allocation error + SZ_ERROR_PARAM - Incorrect paramater + SZ_ERROR_OUTPUT_EOF - output buffer overflow + SZ_ERROR_THREAD - errors in multithreading functions (only for Mt version) + + + +LZMA Defines +------------ + +_LZMA_SIZE_OPT - Enable some optimizations in LZMA Decoder to get smaller executable code. + +_LZMA_PROB32 - It can increase the speed on some 32-bit CPUs, but memory usage for + some structures will be doubled in that case. + +_LZMA_UINT32_IS_ULONG - Define it if int is 16-bit on your compiler and long is 32-bit. + +_LZMA_NO_SYSTEM_SIZE_T - Define it if you don't want to use size_t type. + + +C++ LZMA Encoder/Decoder +~~~~~~~~~~~~~~~~~~~~~~~~ +C++ LZMA code use COM-like interfaces. So if you want to use it, +you can study basics of COM/OLE. +C++ LZMA code is just wrapper over ANSI-C code. + + +C++ Notes +~~~~~~~~~~~~~~~~~~~~~~~~ +If you use some C++ code folders in 7-Zip (for example, C++ code for .7z handling), +you must check that you correctly work with "new" operator. +7-Zip can be compiled with MSVC 6.0 that doesn't throw "exception" from "new" operator. +So 7-Zip uses "CPP\Common\NewHandler.cpp" that redefines "new" operator: +operator new(size_t size) +{ + void *p = ::malloc(size); + if (p == 0) + throw CNewException(); + return p; +} +If you use MSCV that throws exception for "new" operator, you can compile without +"NewHandler.cpp". So standard exception will be used. Actually some code of +7-Zip catches any exception in internal code and converts it to HRESULT code. +So you don't need to catch CNewException, if you call COM interfaces of 7-Zip. + +--- + +http://www.7-zip.org +http://www.7-zip.org/sdk.html +http://www.7-zip.org/support.html diff --git a/BaseTools/Source/C/Makefile b/BaseTools/Source/C/Makefile new file mode 100644 index 0000000000..b137da6498 --- /dev/null +++ b/BaseTools/Source/C/Makefile @@ -0,0 +1,61 @@ +ARCH = IA32 + +!INCLUDE Makefiles\ms.common + +LIBRARIES = Common +APPLICATIONS = \ + BootSectImage \ + EfiLdrImage \ + EfiRom \ + GenBootSector \ + GenCrc32 \ + GenFfs \ + GenFv \ + GenFw \ + GenPage \ + GenSec \ + GenVtf \ + LzmaCompress \ + Split \ + TianoCompress \ + VolInfo \ + VfrCompile + +all: libs apps install + +libs: $(LIBRARIES) + @echo. + @echo ###################### + @echo # Build libraries + @echo ###################### + @if not exist $(LIB_PATH) mkdir $(LIB_PATH) + @Makefiles\NmakeSubdirs.bat all $** + +apps: $(APPLICATIONS) + @echo. + @echo ###################### + @echo # Build executables + @echo ###################### + @if not exist $(BIN_PATH) mkdir $(BIN_PATH) + @Makefiles\NmakeSubdirs.bat all $** + +install: $(LIB_PATH) $(BIN_PATH) + @echo. + @echo ###################### + @echo # Install to $(SYS_LIB_PATH) + @echo # Install to $(SYS_BIN_PATH) + @echo ###################### + @-xcopy $(LIB_PATH)\*.lib $(SYS_LIB_PATH) /I /D /E /F /Y > NUL 2>&1 + @-xcopy $(BIN_PATH)\*.exe $(SYS_BIN_PATH) /I /D /E /F /Y > NUL 2>&1 + +.PHONY: clean +clean: + @Makefiles\NmakeSubdirs.bat clean $(LIBRARIES) $(APPLICATIONS) + +.PHONY: cleanall +cleanall: + @Makefiles\NmakeSubdirs.bat cleanall $(LIBRARIES) $(APPLICATIONS) + @del /f /q $(BIN_PATH)\*.pdb $(BIN_PATH)\*.ilk + +!INCLUDE Makefiles\ms.rule + diff --git a/BaseTools/Source/C/Makefiles/NmakeSubdirs.bat b/BaseTools/Source/C/Makefiles/NmakeSubdirs.bat new file mode 100644 index 0000000000..cacb50baa9 --- /dev/null +++ b/BaseTools/Source/C/Makefiles/NmakeSubdirs.bat @@ -0,0 +1,28 @@ +@echo off +setlocal +SET NMAKE_COMMAND=%1 +SHIFT + +:loop +if "%1"=="" goto success + +ECHO Building %1 +pushd %1 +nmake %NMAKE_COMMAND% +if ERRORLEVEL 1 goto error +ECHO %1 built successfully (%NMAKE_COMMAND%) +ECHO. +shift +popd +goto loop + +:success +goto exit + +:error +popd +ENDLOCAL +ECHO Error while making %1! +VERIFY OTHER 2>NUL + +:exit diff --git a/BaseTools/Source/C/Makefiles/app.makefile b/BaseTools/Source/C/Makefiles/app.makefile new file mode 100644 index 0000000000..7555556baa --- /dev/null +++ b/BaseTools/Source/C/Makefiles/app.makefile @@ -0,0 +1,13 @@ +MAKEROOT ?= ../.. + +include $(MAKEROOT)/Makefiles/header.makefile + +APPLICATION = $(MAKEROOT)/bin/$(APPNAME) + +.PHONY:all +all: $(MAKEROOT)/bin $(APPLICATION) + +$(APPLICATION): $(OBJECTS) + $(LINKER) -o $(APPLICATION) $(OBJECTS) -L$(MAKEROOT)/libs $(LIBS) + +include $(MAKEROOT)/Makefiles/footer.makefile diff --git a/BaseTools/Source/C/Makefiles/footer.makefile b/BaseTools/Source/C/Makefiles/footer.makefile new file mode 100644 index 0000000000..7bdf49c1af --- /dev/null +++ b/BaseTools/Source/C/Makefiles/footer.makefile @@ -0,0 +1,23 @@ +DEPFILES = $(OBJECTS:%.o=%.d) + +$(MAKEROOT)/libs-$(ARCH): + mkdir -p $(MAKEROOT)/libs-$(ARCH) + +.PHONY: install +install: $(MAKEROOT)/libs-$(ARCH) $(LIBRARY) + cp $(LIBRARY) $(MAKEROOT)/libs-$(ARCH) + +$(LIBRARY): $(OBJECTS) + $(AR) crs $@ $^ + +%.o : %.c + $(CC) -c $(CFLAGS) $(CPPFLAGS) $< -o $@ + +%.o : %.S + $(AS) -c $(ASFLAGS) $< -o $@ + +.PHONY: clean +clean: + @rm -f $(OBJECTS) $(LIBRARY) $(DEPFILES) + +-include $(DEPFILES) diff --git a/BaseTools/Source/C/Makefiles/header.makefile b/BaseTools/Source/C/Makefiles/header.makefile new file mode 100644 index 0000000000..271b141a81 --- /dev/null +++ b/BaseTools/Source/C/Makefiles/header.makefile @@ -0,0 +1,40 @@ +# The makefile can be invoked with +# ARCH = x86_64 or x64 for EM64T build +# ARCH = ia32 or IA32 for IA32 build +# ARCH = ia64 or IA64 for IA64 build +# +ARCH ?= IA32 + +CYGWIN:=$(findstring CYGWIN, $(shell uname -s)) +LINUX:=$(findstring Linux, $(shell uname -s)) +DARWIN:=$(findstring Darwin, $(shell uname -s)) + +CC = gcc +CXX = g++ +AS = gcc +AR = ar +LD = ld +LINKER ?= $(CC) +ifeq ($(ARCH), IA32) +ARCH_INCLUDE = -I $(MAKEROOT)/Include/Ia32/ +endif + +ifeq ($(ARCH), X64) +ARCH_INCLUDE = -I $(MAKEROOT)/Include/X64/ +endif + +INCLUDE = $(TOOL_INCLUDE) -I $(MAKEROOT) -I $(MAKEROOT)/Include/Common -I $(MAKEROOT)/Include/ -I $(MAKEROOT)/Include/IndustryStandard -I $(MAKEROOT)/Common/ -I .. -I . $(ARCH_INCLUDE) +CPPFLAGS = $(INCLUDE) +CFLAGS = -MD -fshort-wchar -fno-strict-aliasing -fno-merge-constants -nostdlib -Wall -c -g + +.PHONY: all +.PHONY: install +.PHONY: clean + +all: + +$(MAKEROOT)/libs: + mkdir $(MAKEROOT)/libs + +$(MAKEROOT)/bin: + mkdir $(MAKEROOT)/bin diff --git a/BaseTools/Source/C/Makefiles/lib.makefile b/BaseTools/Source/C/Makefiles/lib.makefile new file mode 100644 index 0000000000..2b1a9d4289 --- /dev/null +++ b/BaseTools/Source/C/Makefiles/lib.makefile @@ -0,0 +1,7 @@ +include $(MAKEROOT)/Makefiles/header.makefile + +LIBRARY = $(MAKEROOT)/libs/lib$(LIBNAME).a + +all: $(MAKEROOT)/libs $(LIBRARY) + +include $(MAKEROOT)/Makefiles/footer.makefile diff --git a/BaseTools/Source/C/Makefiles/ms.app b/BaseTools/Source/C/Makefiles/ms.app new file mode 100644 index 0000000000..fabc0bc656 --- /dev/null +++ b/BaseTools/Source/C/Makefiles/ms.app @@ -0,0 +1,21 @@ +!INCLUDE ..\Makefiles\ms.common + +APPLICATION = $(BIN_PATH)\$(APPNAME).exe + +all: $(APPLICATION) + +$(APPLICATION) : $(OBJECTS) + -@if not exist $(BIN_PATH) mkdir $(BIN_PATH) + $(LD) /nologo /debug /incremental:no /nodefaultlib:libc.lib /out:$@ $(LIBS) $** + +.PHONY:clean +.PHONY:cleanall + +clean: + del /f /q $(OBJECTS) *.pdb > nul + +cleanall: + del /f /q $(OBJECTS) $(APPLICATION) *.pdb $(BIN_PATH)\*.pdb > nul + +!INCLUDE ..\Makefiles\ms.rule + diff --git a/BaseTools/Source/C/Makefiles/ms.common b/BaseTools/Source/C/Makefiles/ms.common new file mode 100644 index 0000000000..2385518c1b --- /dev/null +++ b/BaseTools/Source/C/Makefiles/ms.common @@ -0,0 +1,49 @@ +!IFNDEF EDK_TOOLS_PATH +!ERROR "Please set your EDK_TOOLS_PATH!" +!ENDIF + +!IFNDEF BASE_TOOLS_PATH +!ERROR "BASE_TOOLS_PATH is not set! Please run build_tools.bat at first!" +!ENDIF + +!IFNDEF ARCH +ARCH = IA32 +!ENDIF + +MAKE = nmake -nologo + +SOURCE_PATH = $(BASE_TOOLS_PATH)\Source\C +BIN_PATH = $(BASE_TOOLS_PATH)\Bin +LIB_PATH = $(BASE_TOOLS_PATH)\Lib + +SYS_BIN_PATH=$(EDK_TOOLS_PATH)\Bin +SYS_LIB_PATH=$(EDK_TOOLS_PATH)\Lib + +!IF "$(ARCH)"=="IA32" +ARCH_INCLUDE = $(SOURCE_PATH)\Include\Ia32 +BIN_PATH = $(BASE_TOOLS_PATH)\Bin\Win32 +LIB_PATH = $(BASE_TOOLS_PATH)\Lib\Win32 +SYS_BIN_PATH = $(EDK_TOOLS_PATH)\Bin\Win32 +SYS_LIB_PATH = $(EDK_TOOLS_PATH)\Lib\Win32 +!ENDIF + +!IF "$(ARCH)"=="X64" +ARCH_INCLUDE = $(SOURCE_PATH)\Include\X64 +BIN_PATH = $(BASE_TOOLS_PATH)\Bin\Win64 +LIB_PATH = $(BASE_TOOLS_PATH)\Lib\Win64 +SYS_BIN_PATH = $(EDK_TOOLS_PATH)\Bin\Win64 +SYS_LIB_PATH = $(EDK_TOOLS_PATH)\Lib\Win64 +!ENDIF + +CC = cl.exe +CXX = cl.exe +AS = ml.exe +AR = lib.exe +LD = link.exe +LINKER = $(LD) + +INC = -I . -I $(SOURCE_PATH)\Include -I $(ARCH_INCLUDE) -I $(SOURCE_PATH)\Common $(INC) + +CFLAGS = $(CFLAGS) /nologo /c /Zi /Od /RTC1 /D _DEBUG /MTd /D _CRT_SECURE_NO_DEPRECATE /D _CRT_NONSTDC_NO_DEPRECATE +CPPFLAGS = $(CPPFLAGS) /EHsc /nologo /c /Zi /Od /RTC1 /D _DEBUG /MTd /D _CRT_SECURE_NO_DEPRECATE /D _CRT_NONSTDC_NO_DEPRECATE + diff --git a/BaseTools/Source/C/Makefiles/ms.lib b/BaseTools/Source/C/Makefiles/ms.lib new file mode 100644 index 0000000000..79fdf55e41 --- /dev/null +++ b/BaseTools/Source/C/Makefiles/ms.lib @@ -0,0 +1,20 @@ +!INCLUDE ..\Makefiles\ms.common + +LIBRARY = $(LIB_PATH)\$(LIBNAME).lib + +all: $(LIBRARY) + +$(LIBRARY) : $(OBJECTS) + -@if not exist $(LIB_PATH) mkdir $(LIB_PATH) + $(AR) /nologo /out:$@ $** + +.PHONY:clean +clean: + del /f /q $(OBJECTS) *.pdb > nul + +.PHONY:cleanall +cleanall: + del /f /q $(OBJECTS) $(LIBRARY) *.pdb > nul + +!INCLUDE ..\Makefiles\ms.rule + diff --git a/BaseTools/Source/C/Makefiles/ms.rule b/BaseTools/Source/C/Makefiles/ms.rule new file mode 100644 index 0000000000..94687a075d --- /dev/null +++ b/BaseTools/Source/C/Makefiles/ms.rule @@ -0,0 +1,13 @@ +#DEPFILES = $(OBJECTS:%.o=%.d) + +.c.obj : + $(CC) -c $(CFLAGS) $(INC) $< -Fo$@ + +.S.obj : + $(AS) -c $(ASFLAGS) $< -Fo$@ + +.cpp.obj : + $(CXX) -c $(CPPFLAGS) $(INC) $< -Fo$@ + +#-include $(DEPFILES) + diff --git a/BaseTools/Source/C/PyEfiCompressor/EfiCompressor.c b/BaseTools/Source/C/PyEfiCompressor/EfiCompressor.c new file mode 100644 index 0000000000..38a81c3c27 --- /dev/null +++ b/BaseTools/Source/C/PyEfiCompressor/EfiCompressor.c @@ -0,0 +1,198 @@ +#include +#include + +/* + UefiDecompress(data_buffer, size, original_size) +*/ +STATIC +PyObject* +UefiDecompress( + PyObject *Self, + PyObject *Args + ) +{ + PyObject *SrcData; + UINT32 SrcDataSize; + UINT32 DstDataSize; + UINTN Status; + UINT8 *SrcBuf; + UINT8 *DstBuf; + UINT8 *TmpBuf; + Py_ssize_t SegNum; + Py_ssize_t Index; + + Status = PyArg_ParseTuple( + Args, + "Oi", + &SrcData, + &SrcDataSize + ); + if (Status == 0) { + return NULL; + } + + if (SrcData->ob_type->tp_as_buffer == NULL + || SrcData->ob_type->tp_as_buffer->bf_getreadbuffer == NULL + || SrcData->ob_type->tp_as_buffer->bf_getsegcount == NULL) { + PyErr_SetString(PyExc_Exception, "First argument is not a buffer\n"); + return NULL; + } + + // Because some Python objects which support "buffer" protocol have more than one + // memory segment, we have to copy them into a contiguous memory. + SrcBuf = PyMem_Malloc(SrcDataSize); + if (SrcBuf == NULL) { + PyErr_SetString(PyExc_Exception, "Not enough memory\n"); + goto ERROR; + } + + SegNum = SrcData->ob_type->tp_as_buffer->bf_getsegcount((PyObject *)SrcData, NULL); + TmpBuf = SrcBuf; + for (Index = 0; Index < SegNum; ++Index) { + VOID *BufSeg; + Py_ssize_t Len; + + Len = SrcData->ob_type->tp_as_buffer->bf_getreadbuffer((PyObject *)SrcData, Index, &BufSeg); + if (Len < 0) { + PyErr_SetString(PyExc_Exception, "Buffer segment is not available\n"); + goto ERROR; + } + memcpy(TmpBuf, BufSeg, Len); + TmpBuf += Len; + } + + Status = Extract((VOID *)SrcBuf, SrcDataSize, (VOID **)&DstBuf, &DstDataSize, 1); + if (Status != EFI_SUCCESS) { + PyErr_SetString(PyExc_Exception, "Failed to decompress\n"); + goto ERROR; + } + + return PyBuffer_FromMemory(DstBuf, (Py_ssize_t)DstDataSize); + +ERROR: + if (SrcBuf != NULL) { + free(SrcBuf); + } + + if (DstBuf != NULL) { + free(DstBuf); + } + return NULL; +} + + +STATIC +PyObject* +FrameworkDecompress( + PyObject *Self, + PyObject *Args + ) +{ + PyObject *SrcData; + UINT32 SrcDataSize; + UINT32 DstDataSize; + UINTN Status; + UINT8 *SrcBuf; + UINT8 *DstBuf; + UINT8 *TmpBuf; + Py_ssize_t SegNum; + Py_ssize_t Index; + + Status = PyArg_ParseTuple( + Args, + "Oi", + &SrcData, + &SrcDataSize + ); + if (Status == 0) { + return NULL; + } + + if (SrcData->ob_type->tp_as_buffer == NULL + || SrcData->ob_type->tp_as_buffer->bf_getreadbuffer == NULL + || SrcData->ob_type->tp_as_buffer->bf_getsegcount == NULL) { + PyErr_SetString(PyExc_Exception, "First argument is not a buffer\n"); + return NULL; + } + + // Because some Python objects which support "buffer" protocol have more than one + // memory segment, we have to copy them into a contiguous memory. + SrcBuf = PyMem_Malloc(SrcDataSize); + if (SrcBuf == NULL) { + PyErr_SetString(PyExc_Exception, "Not enough memory\n"); + goto ERROR; + } + + SegNum = SrcData->ob_type->tp_as_buffer->bf_getsegcount((PyObject *)SrcData, NULL); + TmpBuf = SrcBuf; + for (Index = 0; Index < SegNum; ++Index) { + VOID *BufSeg; + Py_ssize_t Len; + + Len = SrcData->ob_type->tp_as_buffer->bf_getreadbuffer((PyObject *)SrcData, Index, &BufSeg); + if (Len < 0) { + PyErr_SetString(PyExc_Exception, "Buffer segment is not available\n"); + goto ERROR; + } + memcpy(TmpBuf, BufSeg, Len); + TmpBuf += Len; + } + + Status = Extract((VOID *)SrcBuf, SrcDataSize, (VOID **)&DstBuf, &DstDataSize, 2); + if (Status != EFI_SUCCESS) { + PyErr_SetString(PyExc_Exception, "Failed to decompress\n"); + goto ERROR; + } + + return PyString_FromStringAndSize((CONST INT8*)DstBuf, (Py_ssize_t)DstDataSize); + +ERROR: + if (SrcBuf != NULL) { + free(SrcBuf); + } + + if (DstBuf != NULL) { + free(DstBuf); + } + return NULL; +} + + +STATIC +PyObject* +UefiCompress( + PyObject *Self, + PyObject *Args + ) +{ + return NULL; +} + + +STATIC +PyObject* +FrameworkCompress( + PyObject *Self, + PyObject *Args + ) +{ + return NULL; +} + +STATIC INT8 DecompressDocs[] = "Decompress(): Decompress data using UEFI standard algorithm\n"; +STATIC INT8 CompressDocs[] = "Compress(): Compress data using UEFI standard algorithm\n"; + +STATIC PyMethodDef EfiCompressor_Funcs[] = { + {"UefiDecompress", (PyCFunction)UefiDecompress, METH_VARARGS, DecompressDocs}, + {"UefiCompress", (PyCFunction)UefiCompress, METH_VARARGS, DecompressDocs}, + {"FrameworkDecompress", (PyCFunction)FrameworkDecompress, METH_VARARGS, DecompressDocs}, + {"FrameworkCompress", (PyCFunction)FrameworkCompress, METH_VARARGS, DecompressDocs}, + {NULL, NULL, 0, NULL} +}; + +PyMODINIT_FUNC +initEfiCompressor(VOID) { + Py_InitModule3("EfiCompressor", EfiCompressor_Funcs, "EFI Compression Algorithm Extension Module"); +} + + diff --git a/BaseTools/Source/C/PyEfiCompressor/Makefile b/BaseTools/Source/C/PyEfiCompressor/Makefile new file mode 100644 index 0000000000..502735bfea --- /dev/null +++ b/BaseTools/Source/C/PyEfiCompressor/Makefile @@ -0,0 +1,12 @@ +!INCLUDE ..\Makefiles\ms.common + +APPNAME = GenSec + +LIBS = $(LIB_PATH)\Common.lib + +OBJECTS = GenSec.obj + +#CFLAGS = $(CFLAGS) /nodefaultlib:libc.lib + +!INCLUDE ..\Makefiles\ms.app + diff --git a/BaseTools/Source/C/PyEfiCompressor/setup.py b/BaseTools/Source/C/PyEfiCompressor/setup.py new file mode 100644 index 0000000000..508ac83516 --- /dev/null +++ b/BaseTools/Source/C/PyEfiCompressor/setup.py @@ -0,0 +1,43 @@ +## @file +# package and install PyEfiCompressor extension +# +# Copyright (c) 2008, 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. +# + +## +# Import Modules +# +from distutils.core import setup, Extension +import os + +if 'BASE_TOOLS_PATH' not in os.environ: + raise "Please define BASE_TOOLS_PATH to the root of base tools tree" + +BaseToolsDir = os.environ['BASE_TOOLS_PATH'] +setup( + name="EfiCompressor", + version="0.01", + ext_modules=[ + Extension( + 'EfiCompressor', + sources=[ + os.path.join(BaseToolsDir, 'Source', 'C', 'Common', 'Decompress.c'), + 'EfiCompressor.c' + ], + include_dirs=[ + os.path.join(BaseToolsDir, 'Source', 'C', 'Include'), + os.path.join(BaseToolsDir, 'Source', 'C', 'Include', 'Ia32'), + os.path.join(BaseToolsDir, 'Source', 'C', 'Common') + ], + ) + ], + ) + diff --git a/BaseTools/Source/C/PyUtility/Makefile b/BaseTools/Source/C/PyUtility/Makefile new file mode 100644 index 0000000000..8f50ae1aeb --- /dev/null +++ b/BaseTools/Source/C/PyUtility/Makefile @@ -0,0 +1,12 @@ +!INCLUDE ..\Makefiles\ms.common + +APPNAME = GenSec + +LIBS = $(LIB_PATH)\Common.lib + +OBJECTS = PyUtility.obj + +#CFLAGS = $(CFLAGS) /nodefaultlib:libc.lib + +!INCLUDE ..\Makefiles\ms.app + diff --git a/BaseTools/Source/C/PyUtility/PyUtility.c b/BaseTools/Source/C/PyUtility/PyUtility.c new file mode 100644 index 0000000000..f06cb9222d --- /dev/null +++ b/BaseTools/Source/C/PyUtility/PyUtility.c @@ -0,0 +1,92 @@ +#include +#include +#include + +/* + SaveFileToDisk(FilePath, Content) +*/ +STATIC +PyObject* +SaveFileToDisk ( + PyObject *Self, + PyObject *Args + ) +{ + CHAR8 *File; + UINT8 *Data; + UINTN DataLength; + UINTN WriteBytes; + UINTN Status; + HANDLE FileHandle; + PyObject *ReturnValue = Py_False; + + Status = PyArg_ParseTuple( + Args, + "ss#", + &File, + &Data, + &DataLength + ); + if (Status == 0) { + return NULL; + } + + FileHandle = CreateFile( + File, + GENERIC_WRITE, + FILE_SHARE_WRITE|FILE_SHARE_READ|FILE_SHARE_DELETE, + NULL, + CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, + NULL + ); + if (FileHandle == INVALID_HANDLE_VALUE) { + PyErr_SetString(PyExc_Exception, "File creation failure"); + return NULL; + } + + while (WriteFile(FileHandle, Data, DataLength, &WriteBytes, NULL)) { + if (DataLength <= WriteBytes) { + DataLength = 0; + break; + } + + Data += WriteBytes; + DataLength -= WriteBytes; + } + + if (DataLength != 0) { + // file saved unsuccessfully + PyErr_SetString(PyExc_Exception, "File write failure"); + goto Done; + } + + // + // Flush buffer may slow down the whole build performance (average 10s slower) + // + //if (!FlushFileBuffers(FileHandle)) { + // PyErr_SetString(PyExc_Exception, "File flush failure"); + // goto Done; + //} + + // success! + ReturnValue = Py_True; + +Done: + CloseHandle(FileHandle); + return ReturnValue; +} + +STATIC INT8 SaveFileToDiskDocs[] = "SaveFileToDisk(): Make sure the file is saved to disk\n"; + +STATIC PyMethodDef PyUtility_Funcs[] = { + {"SaveFileToDisk", (PyCFunction)SaveFileToDisk, METH_VARARGS, SaveFileToDiskDocs}, + {NULL, NULL, 0, NULL} +}; + +PyMODINIT_FUNC +initPyUtility(VOID) { + Py_InitModule3("PyUtility", PyUtility_Funcs, "Utilties Module Implemented C Language"); +} + + diff --git a/BaseTools/Source/C/PyUtility/setup.py b/BaseTools/Source/C/PyUtility/setup.py new file mode 100644 index 0000000000..ff78af3d58 --- /dev/null +++ b/BaseTools/Source/C/PyUtility/setup.py @@ -0,0 +1,42 @@ +## @file +# package and install PyEfiCompressor extension +# +# Copyright (c) 2008, 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. +# + +## +# Import Modules +# +from distutils.core import setup, Extension +import os + +if 'BASE_TOOLS_PATH' not in os.environ: + raise "Please define BASE_TOOLS_PATH to the root of base tools tree" + +BaseToolsDir = os.environ['BASE_TOOLS_PATH'] +setup( + name="PyUtility", + version="0.01", + ext_modules=[ + Extension( + 'PyUtility', + sources=[ + 'PyUtility.c' + ], + include_dirs=[ + os.path.join(BaseToolsDir, 'Source', 'C', 'Include'), + os.path.join(BaseToolsDir, 'Source', 'C', 'Include', 'Ia32'), + os.path.join(BaseToolsDir, 'Source', 'C', 'Common') + ], + ) + ], + ) + diff --git a/BaseTools/Source/C/Split/GNUmakefile b/BaseTools/Source/C/Split/GNUmakefile new file mode 100644 index 0000000000..45cf419145 --- /dev/null +++ b/BaseTools/Source/C/Split/GNUmakefile @@ -0,0 +1,12 @@ +ARCH ?= IA32 +MAKEROOT ?= .. + +APPNAME = Split + +OBJECTS = Split.o + +include $(MAKEROOT)/Makefiles/app.makefile + +LIBS = -lCommon + + diff --git a/BaseTools/Source/C/Split/Makefile b/BaseTools/Source/C/Split/Makefile new file mode 100644 index 0000000000..33e4b51082 --- /dev/null +++ b/BaseTools/Source/C/Split/Makefile @@ -0,0 +1,10 @@ +!INCLUDE ..\Makefiles\ms.common + +APPNAME = Split + +LIBS = $(LIB_PATH)\Common.lib + +OBJECTS = Split.obj + +!INCLUDE ..\Makefiles\ms.app + diff --git a/BaseTools/Source/C/Split/Split.c b/BaseTools/Source/C/Split/Split.c new file mode 100644 index 0000000000..5ebda0901b --- /dev/null +++ b/BaseTools/Source/C/Split/Split.c @@ -0,0 +1,446 @@ +/** @file + + Split a file into two pieces at the request offset. + +Copyright (c) 1999-2008 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 +#include +#include +#ifdef __GNUC__ +#include +#endif +#include +#include "ParseInf.h" +#include "CommonLib.h" +#include "EfiUtilityMsgs.h" +// +// Utility Name +// +#define UTILITY_NAME "Split" + +// +// Utility version information +// +#define UTILITY_MAJOR_VERSION 0 +#define UTILITY_MINOR_VERSION 1 + +void +Version ( + void + ) +/*++ + +Routine Description: + + Displays the standard utility information to SDTOUT + +Arguments: + + None + +Returns: + + None + +--*/ +{ + printf ("%s v%d.%d -Utility to break a file into two pieces at the request offset.\n", UTILITY_NAME, UTILITY_MAJOR_VERSION, UTILITY_MINOR_VERSION); + printf ("Copyright (c) 1999-2007 Intel Corporation. All rights reserved.\n"); +} + +void +Usage ( + void + ) +/*++ + +Routine Description: + + GC_TODO: Add function description + +Arguments: + + +Returns: + + GC_TODO: add return values + +--*/ +{ + Version(); + printf ("\nUsage: \n\ + Split\n\ + -f, --filename inputFile to split\n\ + -s, --split VALUE the number of bytes in the first file\n\ + [-p, --prefix OutputDir]\n\ + [-o, --firstfile Filename1]\n\ + [-t, --secondfile Filename2]\n\ + [-v, --verbose]\n\ + [--version]\n\ + [-q, --quiet disable all messages except fatal errors]\n\ + [-d, --debug[#]\n\ + [-h, --help]\n"); +} + +EFI_STATUS +GetSplitValue ( + IN CONST CHAR8* SplitValueString, + OUT UINT64 *ReturnValue +) +{ + UINT64 len = strlen(SplitValueString); + UINT64 base = 1; + UINT64 index = 0; + UINT64 number = 0; + CHAR8 lastCHAR = 0; + EFI_STATUS Status = EFI_SUCCESS; + + if (len == 0) { + return EFI_ABORTED; + } + + Status = AsciiStringToUint64 (SplitValueString, FALSE, ReturnValue); + if (!EFI_ERROR (Status)) { + return Status; + } + + if (SplitValueString[0] == '0' && (SplitValueString[1] == 'x' || SplitValueString[1] == 'X')) { + Status = AsciiStringToUint64 (SplitValueString, TRUE, ReturnValue); + if (!EFI_ERROR (Status)) { + return Status; + } + } + + lastCHAR = (CHAR8)toupper(SplitValueString[len - 1]); + + if (lastCHAR != 'K' && lastCHAR != 'M' && lastCHAR != 'G') { + return STATUS_ERROR; + } + + for (;index < len - 1; ++index) { + if (!isdigit(SplitValueString[index])) { + return EFI_ABORTED; + } + } + + number = atol (SplitValueString); + if (lastCHAR == 'K') + base = 1024; + else if (lastCHAR == 'M') + base = 1024*1024; + else + base = 1024*1024*1024; + + *ReturnValue = number*base; + + return EFI_SUCCESS; +} + +EFI_STATUS +CountVerboseLevel ( + IN CONST CHAR8* VerboseLevelString, + IN CONST UINT64 Length, + OUT UINT64 *ReturnValue +) +{ + UINT64 i = 0; + for (;i < Length; ++i) { + if (VerboseLevelString[i] != 'v' && VerboseLevelString[i] != 'V') { + return EFI_ABORTED; + } + ++(*ReturnValue); + } + + return EFI_SUCCESS; +} + +EFI_STATUS +CreateDir ( + IN OUT CHAR8** FullFileName +) +{ + CHAR8* temp = *FullFileName; + CHAR8* start = temp; + UINT64 index = 0; + + for (;index < strlen(temp); ++index) { + if (temp[index] == '\\' || temp[index] == '/') { + temp[index] = 0; + if (chdir(start)) { + if (mkdir(start, S_IRWXU | S_IRWXG | S_IRWXO) != 0) { + return EFI_ABORTED; + } + chdir(start); + } + start = temp + index + 1; + temp[index] = '/'; + } + } + + return EFI_SUCCESS; +} + +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 + +--*/ +{ + EFI_STATUS Status = EFI_SUCCESS; + FILE *In; + CHAR8 *InputFileName = NULL; + CHAR8 *OutputDir = NULL; + CHAR8 *OutFileName1 = NULL; + CHAR8 *OutFileName2 = NULL; + UINT64 SplitValue = -1; + FILE *Out1; + FILE *Out2; + CHAR8 *OutName1 = NULL; + CHAR8 *OutName2 = NULL; + CHAR8 *CurrentDir = NULL; + UINT64 Index; + CHAR8 CharC; + BOOLEAN QuietFlag = TRUE; + UINT64 DebugLevel = 0; + UINT64 VerboseLevel = 0; + + SetUtilityName(UTILITY_NAME); + if (argc == 1) { + Usage(); + return STATUS_ERROR; + } + + argc --; + argv ++; + + if ((stricmp (argv[0], "-h") == 0) || (stricmp (argv[0], "--help") == 0)) { + Usage(); + return STATUS_SUCCESS; + } + + if (stricmp (argv[0], "--version") == 0) { + Version(); + return STATUS_SUCCESS; + } + + while (argc > 0) { + if ((stricmp (argv[0], "-p") == 0) || (stricmp (argv[0], "--prefix") == 0)) { + OutputDir = argv[1]; + if (OutputDir == NULL) { + Warning (NULL, 0, 0, "NO output directory specified.", NULL); + return STATUS_ERROR; + } + argc -= 2; + argv += 2; + continue; + } + + if ((stricmp (argv[0], "-f") == 0) || (stricmp (argv[0], "--filename") == 0)) { + InputFileName = argv[1]; + if (InputFileName == NULL) { + Error (NULL, 0, 0x1001, "NO Input file specified.", NULL); + return STATUS_ERROR; + } + argc -= 2; + argv += 2; + continue; + } + + if ((stricmp (argv[0], "-s") == 0) || (stricmp (argv[0], "--split") == 0)) { + Status = GetSplitValue(argv[1], &SplitValue); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 0x1003, "Input split value is not one valid integer.", NULL); + return STATUS_ERROR; + } + argc -= 2; + argv += 2; + continue; + } + + if ((stricmp (argv[0], "-o") == 0) || (stricmp (argv[0], "--firstfile") == 0)) { + OutFileName1 = argv[1]; + if (OutFileName1 == NULL) { + Warning (NULL, 0, 0, NULL, "No output file1 specified."); + } + argc -= 2; + argv += 2; + continue; + } + + if ((stricmp (argv[0], "-t") == 0) || (stricmp (argv[0], "--secondfile") == 0)) { + OutFileName2 = argv[1]; + if (OutFileName2 == NULL) { + Warning (NULL, 0, 0, NULL, "No output file2 specified."); + } + argc -= 2; + argv += 2; + continue; + } + + if ((stricmp (argv[0], "-q") == 0) || (stricmp (argv[0], "--quiet") == 0)) { + QuietFlag = TRUE; + argc --; + argv ++; + continue; + } + + if ((strlen(argv[0]) >= 2 && argv[0][0] == '-' && (argv[0][1] == 'v' || argv[0][1] == 'V')) || (stricmp (argv[0], "--verbose") == 0)) { + VerboseLevel = 1; + if (strlen(argv[0]) > 2) { + Status = CountVerboseLevel (&argv[0][2], strlen(argv[0]) - 2, &VerboseLevel); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 0x1003, NULL, "%s is invaild paramter!", argv[0]); + return STATUS_ERROR; + } + } + + argc --; + argv ++; + continue; + } + + if ((stricmp (argv[0], "-d") == 0) || (stricmp (argv[0], "--debug") == 0)) { + Status = AsciiStringToUint64 (argv[1], FALSE, &DebugLevel); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 0x1003, "Input debug level is not one valid integrator.", NULL); + return STATUS_ERROR; + } + argc -= 2; + argv += 2; + continue; + } + // + // Don't recognize the paramter. + // + Error (NULL, 0, 0x1003, NULL, "%s is invaild paramter!", argv[0]); + return STATUS_ERROR; + } + + if (InputFileName == NULL) { + Error (NULL, 0, 0x1001, "NO Input file specified.", NULL); + return STATUS_ERROR; + } + + In = fopen (InputFileName, "rb"); + if (In == NULL) { + // ("Unable to open file \"%s\"\n", InputFileName); + Error (InputFileName, 0, 1, "File open failure", NULL); + return STATUS_ERROR; + } + + if (OutFileName1 == NULL) { + OutName1 = (CHAR8*)malloc(strlen(InputFileName) + 16); + if (OutName1 == NULL) { + Warning (NULL, 0, 0, NULL, "Memory Allocation Fail."); + return STATUS_ERROR; + } + strcpy (OutName1, InputFileName); + strcat (OutName1, "1"); + OutFileName1 = OutName1; + + } + if (OutFileName2 == NULL) { + OutName2 = (CHAR8*)malloc(strlen(InputFileName) + 16); + if (OutName2 == NULL) { + Warning (NULL, 0, 0, NULL, "Memory Allocation Fail."); + return STATUS_ERROR; + } + strcpy (OutName2, InputFileName); + strcat (OutName2, "2"); + OutFileName2 = OutName2; + + } + + if (OutputDir != NULL) { + //OutputDirSpecified = TRUE; + if (chdir(OutputDir) != 0) { + Warning (NULL, 0, 0, NULL, "Change dir to OutputDir Fail."); + return STATUS_ERROR; + } + } + + CurrentDir = (CHAR8*)getcwd((CHAR8*)0, 0); + if (EFI_ERROR(CreateDir(&OutFileName1))) { + Error (OutFileName1, 0, 5, "Create Dir for File1 Fail.", NULL); + return STATUS_ERROR; + } + chdir(CurrentDir); + + if (EFI_ERROR(CreateDir(&OutFileName2))) { + Error (OutFileName2, 0, 5, "Create Dir for File2 Fail.", NULL); + return STATUS_ERROR; + } + chdir(CurrentDir); + free(CurrentDir); + + Out1 = fopen (OutFileName1, "wb"); + if (Out1 == NULL) { + // ("Unable to open file \"%s\"\n", OutFileName1); + Error (OutFileName1, 0, 1, "File open failure", NULL); + return STATUS_ERROR; + } + + Out2 = fopen (OutFileName2, "wb"); + if (Out2 == NULL) { + // ("Unable to open file \"%s\"\n", OutFileName2); + Error (OutFileName2, 0, 1, "File open failure", NULL); + return STATUS_ERROR; + } + + for (Index = 0; Index < SplitValue; Index++) { + CharC = (CHAR8) fgetc (In); + if (feof (In)) { + break; + } + + fputc (CharC, Out1); + } + + for (;;) { + CharC = (CHAR8) fgetc (In); + if (feof (In)) { + break; + } + + fputc (CharC, Out2); + } + + if (OutName1 != NULL) { + free(OutName1); + } + if (OutName2 != NULL) { + free(OutName2); + } + fclose (In); + fclose (Out1); + fclose (Out2); + + return STATUS_SUCCESS; +} diff --git a/BaseTools/Source/C/TianoCompress/GNUmakefile b/BaseTools/Source/C/TianoCompress/GNUmakefile new file mode 100644 index 0000000000..151bbe2cc1 --- /dev/null +++ b/BaseTools/Source/C/TianoCompress/GNUmakefile @@ -0,0 +1,10 @@ +ARCH ?= IA32 +MAKEROOT ?= .. + +APPNAME = TianoCompress + +LIBS = -lCommon + +OBJECTS = TianoCompress.o + +include $(MAKEROOT)/Makefiles/app.makefile diff --git a/BaseTools/Source/C/TianoCompress/Makefile b/BaseTools/Source/C/TianoCompress/Makefile new file mode 100644 index 0000000000..c7e0bed2d8 --- /dev/null +++ b/BaseTools/Source/C/TianoCompress/Makefile @@ -0,0 +1,10 @@ +!INCLUDE ..\Makefiles\ms.common + +APPNAME = TianoCompress + +LIBS = $(LIB_PATH)\Common.lib + +OBJECTS = TianoCompress.obj + +!INCLUDE ..\Makefiles\ms.app + diff --git a/BaseTools/Source/C/TianoCompress/TianoCompress.c b/BaseTools/Source/C/TianoCompress/TianoCompress.c new file mode 100644 index 0000000000..b3ce640fde --- /dev/null +++ b/BaseTools/Source/C/TianoCompress/TianoCompress.c @@ -0,0 +1,2719 @@ +/** @file + +Copyright (c) 2007 - 2008, 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: + + TianoCompress.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 "Compress.h" +#include "TianoCompress.h" +#include "EfiUtilityMsgs.h" +#include "ParseInf.h" +#include +#include "assert.h" + +// +// Macro Definitions +// +static BOOLEAN VerboseMode = FALSE; +static BOOLEAN QuietMode = FALSE; +#undef UINT8_MAX +#define UINT8_MAX 0xff +#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 + +// +// Global Variables +// +STATIC BOOLEAN ENCODE = FALSE; +STATIC BOOLEAN DECODE = FALSE; +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], mCCode[NC], mPFreq[2 * NP - 1], mPTCode[NPT], mTFreq[2 * NT - 1]; + +STATIC NODE mPos, mMatchPos, mAvail, *mPosition, *mParent, *mPrev, *mNext = NULL; + +static UINTN DebugLevel; +static BOOLEAN DebugMode; +// +// functions +// +EFI_STATUS +TianoCompress ( + IN UINT8 *SrcBuffer, + IN UINT32 SrcSize, + IN UINT8 *DstBuffer, + IN OUT UINT32 *DstSize + ) +/*++ + +Routine Description: + + The internal implementation of [Efi/Tiano]Compress(). + +Arguments: + + SrcBuffer - The buffer storing the source data + SrcSize - The size of source data + DstBuffer - The buffer to store the compressed data + + Version - The version of de/compression algorithm. + Version 1 for EFI 1.1 de/compression algorithm. + Version 2 for Tiano de/compression algorithm. + +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_INVALID_PARAMETER - Parameter supplied is wrong. + +--*/ +{ + 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; + } + 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; +} + +EFI_STATUS +GetFileContents ( + IN char *InputFileName, + OUT UINT8 *FileBuffer, + OUT UINT32 *BufferLength + ) +/*++ + +Routine Description: + + Get the contents of file specified in InputFileName + into FileBuffer. + +Arguments: + + InputFileName - Name of the input file. + + FileBuffer - Output buffer to contain data + + BufferLength - Actual length of the data + +Returns: + + EFI_SUCCESS on successful return + EFI_ABORTED if unable to open input file. + +--*/ +{ + UINTN Size; + UINTN FileSize; + FILE *InputFile; + + Size = 0; + // + // Copy the file contents to the output buffer. + // + InputFile = fopen (InputFileName, "rb"); + if (InputFile == NULL) { + Error (NULL, 0, 0001, "Error opening file: %s", InputFileName); + return EFI_ABORTED; + } + + fseek (InputFile, 0, SEEK_END); + FileSize = ftell (InputFile); + fseek (InputFile, 0, SEEK_SET); + // + // Now read the contents of the file into the buffer + // + if (FileSize > 0 && FileBuffer != NULL) { + if (fread (FileBuffer, FileSize, 1, InputFile) != 1) { + Error (NULL, 0, 0004, "Error reading contents of input file: %s", InputFileName); + fclose (InputFile); + return EFI_ABORTED; + } + } + + fclose (InputFile); + Size += (UINTN) FileSize; + *BufferLength = Size; + + if (FileBuffer != NULL) { + return EFI_SUCCESS; + } else { + return EFI_BUFFER_TOO_SMALL; + } +} + +VOID +Version ( + VOID + ) +/*++ + +Routine Description: + + Displays the standard utility information to SDTOUT + +Arguments: + + None + +Returns: + + None + +--*/ +{ + fprintf (stdout, "%s Version %d.%d\n", UTILITY_NAME, UTILITY_MAJOR_VERSION, UTILITY_MINOR_VERSION); +} + +VOID +Usage ( + VOID + ) +/*++ + +Routine Description: + + Displays the utility usage syntax to STDOUT + +Arguments: + + None + +Returns: + + None + +--*/ +{ + // + // Summary usage + // + fprintf (stdout, "Usage: %s -e|-d [options] \n\n", UTILITY_NAME); + + // + // Copyright declaration + // + fprintf (stdout, "Copyright (c) 2007, Intel Corporation. All rights reserved.\n\n"); + + // + // Details Option + // + fprintf (stdout, "Options:\n"); + fprintf (stdout, " -o FileName, --output FileName\n\ + File will be created to store the ouput content.\n"); + fprintf (stdout, " -v, --verbose\n\ + Turn on verbose output with informational messages.\n"); + fprintf (stdout, " -q, --quiet\n\ + Disable all messages except key message and fatal error\n"); + fprintf (stdout, " --debug [0-9]\n\ + Enable debug messages, at input debug level.\n"); + fprintf (stdout, " --version\n\ + Show program's version number and exit.\n"); + fprintf (stdout, " -h, --help\n\ + Show this help message and exit.\n"); +} + + +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. + +--*/ +{ + FILE *OutputFile; + char *OutputFileName; + char *InputFileName; + FILE *InputFile; + EFI_STATUS Status; + UINT8 *FileBuffer; + UINT8 *OutBuffer; + UINT32 InputLength; + UINT32 DstSize; + SCRATCH_DATA *Scratch; + UINT8 *Src; + UINT32 OrigSize; + + SetUtilityName(UTILITY_NAME); + + FileBuffer = NULL; + Src = NULL; + OutBuffer = NULL; + Scratch = NULL; + OrigSize = 0; + InputLength = 0; + InputFileName = NULL; + OutputFileName = NULL; + DstSize=0; + DebugLevel = 0; + DebugMode = FALSE; + + // + // Verify the correct number of arguments + // + if (argc == 1) { + Error (NULL, 0, 1001, "Missing options", "No input options specified."); + Usage(); + return 0; + } + + if ((strcmp(argv[1], "-h") == 0) || (strcmp(argv[1], "--help") == 0)) { + Usage(); + return 0; + } + + if ((strcmp(argv[1], "--version") == 0)) { + Version(); + return 0; + } + + argc--; + argv++; + if (strcmp(argv[0],"-e") == 0) { + // + // encode the input file + // + ENCODE = TRUE; + argc--; + argv++; + } else if (strcmp(argv[0], "-d") == 0) { + // + // decode the input file + // + DECODE = TRUE; + argc--; + argv++; + } else { + // + // Error command line + // + Error (NULL, 0, 1003, "Invalid option value", "the options specified are not recognized."); + Usage(); + return 1; + } + + while (argc > 0) { + if ((strcmp(argv[0], "-v") == 0) || (stricmp(argv[0], "--verbose") == 0)) { + VerboseMode = TRUE; + argc--; + argv++; + continue; + } + + if (stricmp (argv[0], "--debug") == 0) { + argc-=2; + argv++; + Status = AsciiStringToUint64(argv[0], FALSE, &DebugLevel); + if (DebugLevel > 9) { + Error (NULL, 0 ,2000, "Invalid parameter", "Unrecognized argument %s", argv[0]); + goto ERROR; + } + if (DebugLevel>=5 && DebugLevel <=9){ + DebugMode = TRUE; + } else { + DebugMode = FALSE; + } + argv++; + continue; + } + + if ((strcmp(argv[0], "-q") == 0) || (stricmp (argv[0], "--quiet") == 0)) { + QuietMode = TRUE; + argc--; + argv++; + continue; + } + + if ((strcmp(argv[0], "-o") == 0) || (stricmp (argv[0], "--output") == 0)) { + if (argv[1] == NULL || argv[1][0] == '-') { + Error (NULL, 0, 1003, "Invalid option value", "Output File name is missing for -o option"); + goto ERROR; + } + OutputFileName = argv[1]; + argc -=2; + argv +=2; + continue; + } + + if (argv[0][0]!='-') { + InputFileName = argv[0]; + argc--; + argv++; + continue; + } + + Error (NULL, 0, 1000, "Unknown option", argv[0]); + goto ERROR; + } + + if (InputFileName == NULL) { + Error (NULL, 0, 1001, "Missing options", "No input files specified."); + goto ERROR; + } + +// +// All Parameters has been parsed, now set the message print level +// + if (QuietMode) { + SetPrintLevel(40); + } else if (VerboseMode) { + SetPrintLevel(15); + } else if (DebugMode) { + SetPrintLevel(DebugLevel); + } + + if (VerboseMode) { + VerboseMsg("%s tool start.\n", UTILITY_NAME); + } + Scratch = (SCRATCH_DATA *)malloc(sizeof(SCRATCH_DATA)); + if (Scratch == NULL) { + Error (NULL, 0, 4001, "Resource:", "Memory cannot be allocated!"); + goto ERROR; + } + + InputFile = fopen (InputFileName, "rb"); + if (InputFile == NULL) { + Error (NULL, 0, 0001, "Error opening input file", InputFileName); + goto ERROR; + } + + Status = GetFileContents( + InputFileName, + FileBuffer, + &InputLength); + + if (Status == EFI_BUFFER_TOO_SMALL) { + FileBuffer = (UINT8 *) malloc (InputLength); + if (FileBuffer == NULL) { + Error (NULL, 0, 4001, "Resource:", "Memory cannot be allocated!"); + return 1; + } + + Status = GetFileContents ( + InputFileName, + FileBuffer, + &InputLength + ); + } + + if (EFI_ERROR(Status)) { + free(FileBuffer); + return 1; + } + + if (OutputFileName != NULL) { + OutputFile = fopen (OutputFileName, "wb"); + if (OutputFile == NULL) { + Error (NULL, 0, 0001, "Error opening output file for writing", OutputFileName); + if (InputFile != NULL) { + fclose (InputFile); + } + goto ERROR; + } + } else { + OutputFileName = DEFAULT_OUTPUT_FILE; + OutputFile = fopen (OutputFileName, "wb"); + } + + if (ENCODE) { + // + // First call TianoCompress to get DstSize + // + if (DebugMode) { + DebugMsg(UTILITY_NAME, 0, DebugLevel, "Encoding", NULL); + } + Status = TianoCompress ((UINT8 *)FileBuffer, InputLength, OutBuffer, &DstSize); + + if (Status == EFI_BUFFER_TOO_SMALL) { + OutBuffer = (UINT8 *) malloc (DstSize); + if (OutBuffer == NULL) { + Error (NULL, 0, 4001, "Resource:", "Memory cannot be allocated!"); + goto ERROR; + } + } + Status = TianoCompress ((UINT8 *)FileBuffer, InputLength, OutBuffer, &DstSize); + if (Status != EFI_SUCCESS) { + Error (NULL, 0, 0007, "Error compressing file", NULL); + goto ERROR; + } + + fwrite(OutBuffer,(size_t)DstSize, 1, OutputFile); + free(Scratch); + free(FileBuffer); + free(OutBuffer); + + if (DebugMode) { + DebugMsg(UTILITY_NAME, 0, DebugLevel, "Encoding Successful!\n", NULL); + } + if (VerboseMode) { + VerboseMsg("Encoding successful\n"); + } + return 0; + } + else if (DECODE) { + if (DebugMode) { + DebugMsg(UTILITY_NAME, 0, DebugLevel, "Decoding\n", NULL); + } + // + // Get Compressed file original size + // + Src = (UINT8 *)FileBuffer; + OrigSize = Src[4] + (Src[5] << 8) + (Src[6] << 16) + (Src[7] << 24); + + // + // Allocate OutputBuffer + // + OutBuffer = (UINT8 *)malloc(OrigSize); + if (OutBuffer == NULL) { + Error (NULL, 0, 4001, "Resource:", "Memory cannot be allocated!"); + goto ERROR; + } + + Status = Decompress((VOID *)FileBuffer, (VOID *)OutBuffer, (VOID *)Scratch, 2); + if (Status != EFI_SUCCESS) { + goto ERROR; + } + + fwrite(OutBuffer, (size_t)(Scratch->mOrigSize), 1, OutputFile); + free(Scratch); + free(FileBuffer); + free(OutBuffer); + + if (DebugMode) { + DebugMsg(UTILITY_NAME, 0, DebugLevel, "Encoding successful!\n", NULL); + } + + if (VerboseMode) { + VerboseMsg("Decoding successful\n"); + } + return 0; + } + +ERROR: + if (DebugMode) { + if (ENCODE) { + DebugMsg(UTILITY_NAME, 0, DebugLevel, "Encoding Error\n", NULL); + } else if (DECODE) { + DebugMsg(UTILITY_NAME, 0, DebugLevel, "Decoding Error\n", NULL); + } + } + if (Scratch != NULL) { + free(Scratch); + } + if (FileBuffer != NULL) { + free(FileBuffer); + } + if (OutBuffer != NULL) { + free(OutBuffer); + } + + if (VerboseMode) { + VerboseMsg("%s tool done with return code is 0x%x.\n", UTILITY_NAME, GetUtilityStatus ()); + } + return GetUtilityStatus (); +} + +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 + NumOfBits - 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; +} + +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; +} + +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; + volatile UINT16 Index; + UINT16 Len; + UINT16 Char; + UINT16 JuBits; + UINT16 Avail; + UINT16 NextCode; + UINT16 Mask; + UINT16 WordOfStart; + UINT16 WordOfCount; + + 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++) { + WordOfStart = Start[Index]; + WordOfCount = Count[Index]; + Start[Index + 1] = (UINT16) (WordOfStart + (WordOfCount << (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++; + } + + 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; +} + +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; +} + +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; + volatile 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); + while ((INT16) (--CharC) >= 0) { + Sd->mPTLen[Index++] = 0; + } + } + } + + while (Index < nn) { + Sd->mPTLen[Index++] = 0; + } + + return MakeTable (Sd, nn, Sd->mPTLen, 8, Sd->mPTTable); +} + +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; + volatile 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); + } + + while ((INT16) (--CharC) >= 0) { + Sd->mCLen[Index++] = 0; + } + + } else { + + Sd->mCLen[Index++] = (UINT8) (CharC - 2); + + } + } + + while (Index < NC) { + Sd->mCLen[Index++] = 0; + } + + MakeTable (Sd, NC, Sd->mCLen, 12, Sd->mCTable); + + return ; +} + +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, Sd->mPBit, (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; +} + +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) { + goto Done ; + } + + if (CharC < 256) { + // + // Process an Original character + // + if (Sd->mOutBuf >= Sd->mOrigSize) { + goto Done ; + } else { + Sd->mDstBase[Sd->mOutBuf++] = (UINT8) CharC; + } + + } 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) { + goto Done ; + } + + BytesRemain--; + } + } + } + +Done: + return ; +} + +RETURN_STATUS +EFIAPI +Decompress ( + IN VOID *Source, + IN OUT VOID *Destination, + IN OUT VOID *Scratch, + IN UINT32 Version + ) +/*++ + +Routine Description: + + The internal implementation of Decompress(). + +Arguments: + + Source - The source buffer containing the compressed data. + Destination - The destination buffer to store the decompressed data + Scratch - The buffer used internally by the decompress routine. This buffer is needed to store intermediate data. + Version - 1 for EFI1.1 Decompress algoruthm, 2 for Tiano Decompress algorithm + +Returns: + + RETURN_SUCCESS - Decompression is successfull + RETURN_INVALID_PARAMETER - The source data is corrupted + +--*/ +{ + volatile UINT32 Index; + UINT32 CompSize; + UINT32 OrigSize; + SCRATCH_DATA *Sd; + CONST UINT8 *Src; + UINT8 *Dst; + + // + // Verify input is not NULL + // + assert(Source); +// assert(Destination); + assert(Scratch); + + Src = (UINT8 *)Source; + Dst = (UINT8 *)Destination; + + Sd = (SCRATCH_DATA *) Scratch; + 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 compressed file size is 0, return + // + if (OrigSize == 0) { + return RETURN_SUCCESS; + } + + Src = Src + 8; + + for (Index = 0; Index < sizeof (SCRATCH_DATA); Index++) { + ((UINT8 *) Sd)[Index] = 0; + } + // + // The length of the field 'Position Set Code Length Array Size' in Block Header. + // For EFI 1.1 de/compression algorithm(Version 1), mPBit = 4 + // For Tiano de/compression algorithm(Version 2), mPBit = 5 + // + switch (Version) { + case 1 : + Sd->mPBit = 4; + break; + case 2 : + Sd->mPBit = 5; + break; + default: + assert(FALSE); + } + Sd->mSrcBase = (UINT8 *)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 + // + return RETURN_INVALID_PARAMETER; + } + + return RETURN_SUCCESS; +} + + diff --git a/BaseTools/Source/C/TianoCompress/TianoCompress.h b/BaseTools/Source/C/TianoCompress/TianoCompress.h new file mode 100644 index 0000000000..4fc48c3ad4 --- /dev/null +++ b/BaseTools/Source/C/TianoCompress/TianoCompress.h @@ -0,0 +1,439 @@ +/** @file + Internal include file for Tiano Decompress Libary. + + 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: TianoDecompress.h + +**/ + +#ifndef __TIANO_DECOMPRESS_H__ +#define __TIANO_DECOMPRESS_H__ + +#include +#include +#include + + +// +// Decompression algorithm begins here +// +#define UTILITY_NAME "TianoCompress" +#define UTILITY_MAJOR_VERSION 0 +#define UTILITY_MINOR_VERSION 1 + +// +// Default output file name +// +#define DEFAULT_OUTPUT_FILE "file.tmp" + +#define BITBUFSIZ 32 +#define MAXMATCH 256 +#define THRESHOLD 3 +#define CODE_BIT 16 +#define BAD_TABLE - 1 + +typedef INT32 NODE; + +// +// C: Char&Len Set; P: Position Set; T: exTra Set +// +#define NC (0xff + MAXMATCH + 2 - THRESHOLD) +#define CBIT 9 +#define MAXPBIT 5 +#define TBIT 5 +#define MAXNP ((1U << MAXPBIT) - 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]; + + // + // The length of the field 'Position Set Code Length Array Size' in Block Header. + // For EFI 1.1 de/compression algorithm, mPBit = 4 + // For Tiano de/compression algorithm, mPBit = 5 + // + UINT8 mPBit; +} SCRATCH_DATA; + +// +// Function Prototypes +// + +EFI_STATUS +GetFileContents ( + IN char *InputFileName, + OUT UINT8 *FileBuffer, + OUT UINT32 *BufferLength + ); + +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[] + ); + +/** + Read NumOfBit of bits from source into mBitBuf + + Shift mBitBuf NumOfBits left. Read in NumOfBits of bits from source. + + @param Sd The global scratch data + @param NumOfBits The number of bits to shift and read. + +**/ +VOID +FillBuf ( + IN SCRATCH_DATA *Sd, + IN UINT16 NumOfBits + ); + +/** + Get NumOfBits of bits out from mBitBuf + + Get NumOfBits of bits out from mBitBuf. Fill mBitBuf with subsequent + NumOfBits of bits from source. Returns NumOfBits of bits that are + popped out. + + @param Sd The global scratch data. + @param NumOfBits The number of bits to pop and read. + + @return The bits that are popped out. + +**/ +UINT32 +GetBits ( + IN SCRATCH_DATA *Sd, + IN UINT16 NumOfBits + ); + +/** + Creates Huffman Code mapping table according to code length array. + + Creates Huffman Code mapping table for Extra Set, Char&Len Set + and Position Set according to code length array. + + @param Sd The global scratch data + @param NumOfChar Number of symbols in the symbol set + @param BitLen Code length array + @param TableBits The width of the mapping table + @param Table The table + + @retval 0 OK. + @retval BAD_TABLE The table is corrupted. + +**/ +UINT16 +MakeTable ( + IN SCRATCH_DATA *Sd, + IN UINT16 NumOfChar, + IN UINT8 *BitLen, + IN UINT16 TableBits, + OUT UINT16 *Table + ); + +/** + Decodes a position value. + + Get a position value according to Position Huffman Table. + + @param Sd the global scratch data + + @return The position value decoded. + +**/ +UINT32 +DecodeP ( + IN SCRATCH_DATA *Sd + ); + +/** + Reads code lengths for the Extra Set or the Position Set. + + Read in the Extra Set or Pointion Set Length Arrary, then + generate the Huffman code mapping for them. + + @param Sd The global scratch data. + @param nn Number of symbols. + @param nbit Number of bits needed to represent nn. + @param Special The special symbol that needs to be taken care of. + + @retval 0 OK. + @retval BAD_TABLE Table is corrupted. + +**/ +UINT16 +ReadPTLen ( + IN SCRATCH_DATA *Sd, + IN UINT16 nn, + IN UINT16 nbit, + IN UINT16 Special + ); + +/** + Reads code lengths for Char&Len Set. + + Read in and decode the Char&Len Set Code Length Array, then + generate the Huffman Code mapping table for the Char&Len Set. + + @param Sd the global scratch data + +**/ +VOID +ReadCLen ( + SCRATCH_DATA *Sd + ); + +/** + Decode a character/length value. + + Read one value from mBitBuf, Get one code from mBitBuf. If it is at block boundary, generates + Huffman code mapping table for Extra Set, Code&Len Set and + Position Set. + + @param Sd The global scratch data. + + @return The value decoded. + +**/ +UINT16 +DecodeC ( + SCRATCH_DATA *Sd + ); + +/** + Decode the source data and put the resulting data into the destination buffer. + + Decode the source data and put the resulting data into the destination buffer. + + @param Sd The global scratch data + +**/ +VOID +Decode ( + SCRATCH_DATA *Sd + ); + +RETURN_STATUS +EFIAPI +Decompress ( + IN VOID *Source, + IN OUT VOID *Destination, + IN OUT VOID *Scratch, + IN UINT32 Version + ); + +#endif diff --git a/BaseTools/Source/C/VfrCompile/EfiVfr.h b/BaseTools/Source/C/VfrCompile/EfiVfr.h new file mode 100644 index 0000000000..a88b101953 --- /dev/null +++ b/BaseTools/Source/C/VfrCompile/EfiVfr.h @@ -0,0 +1,55 @@ +/** @file + +Copyright (c) 2004 - 2008, 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 UEFI VFR compiler internal use. + +**/ + +#ifndef _EFIVFR_H_ +#define _EFIVFR_H_ + +#include "Common/UefiBaseTypes.h" +#include "Protocol/DevicePath.h" +#include "Common/UefiInternalFormRepresentation.h" +#include "Common/MdeModuleHii.h" + +#define MAX_PATH 255 +#define MAX_VFR_LINE_LEN 4096 + +#define EFI_IFR_MAX_LENGTH 0xFF + +#define EFI_VARSTORE_ID_INVALID 0 +#define EFI_VAROFFSET_INVALID 0xFFFF +#define EFI_VARSTORE_ID_START 0x20 +#define EFI_STRING_ID_INVALID 0x0 +#define EFI_IMAGE_ID_INVALID 0xFFFF + +typedef enum { + QUESTION_NORMAL, + QUESTION_DATE, + QUESTION_TIME, +} EFI_QUESION_TYPE; + +typedef enum { + EQUAL, + LESS_EQUAL, + LESS_THAN, + GREATER_THAN, + GREATER_EQUAL +} EFI_COMPARE_TYPE; + +#endif diff --git a/BaseTools/Source/C/VfrCompile/GNUmakefile b/BaseTools/Source/C/VfrCompile/GNUmakefile new file mode 100644 index 0000000000..6fe376ddbb --- /dev/null +++ b/BaseTools/Source/C/VfrCompile/GNUmakefile @@ -0,0 +1,53 @@ + +ARCH ?= IA32 +MAKEROOT ?= .. + +APPNAME = VfrCompile + +LIBS = -lCommon + +TOOL_INCLUDE = -I Pccts/h + +#OBJECTS = VfrSyntax.o VfrServices.o DLGLexer.o EfiVfrParser.o ATokenBuffer.o DLexerBase.o AParser.o +OBJECTS = AParser.o DLexerBase.o ATokenBuffer.o EfiVfrParser.o VfrLexer.o VfrSyntax.o \ + VfrFormPkg.o VfrError.o VfrUtilityLib.o VfrCompiler.o + +VFR_CPPFLAGS = -DPCCTS_USE_NAMESPACE_STD $(CPPFLAGS) + +LINKER = $(CXX) + +EXTRA_CLEAN_OBJECTS = EfiVfrParser.cpp EfiVfrParser.h VfrParser.dlg VfrTokens.h VfrLexer.cpp VfrLexer.h VfrSyntax.cpp tokens.h + +include $(MAKEROOT)/Makefiles/app.makefile + +VfrSyntax.cpp EfiVfrParser.cpp EfiVfrParser.h VfrParser.dlg VfrTokens.h: Pccts/antlr/antlr VfrSyntax.g + Pccts/antlr/antlr -CC -e3 -ck 3 -k 2 -fl VfrParser.dlg -ft VfrTokens.h -o . VfrSyntax.g + +VfrLexer.cpp VfrLexer.h: Pccts/dlg/dlg VfrParser.dlg + Pccts/dlg/dlg -C2 -i -CC -cl VfrLexer -o . VfrParser.dlg + +Pccts/antlr/antlr: + BIN_DIR='.' make -C Pccts/antlr + +Pccts/dlg/dlg: + BIN_DIR='.' make -C Pccts/dlg + +ATokenBuffer.o: Pccts/h/ATokenBuffer.cpp + $(CXX) -c $(VFR_CPPFLAGS) $(INC) $? -o $@ + +DLexerBase.o: Pccts/h/DLexerBase.cpp + $(CXX) -c $(VFR_CPPFLAGS) $(INC) $? -o $@ + +AParser.o: Pccts/h/AParser.cpp + $(CXX) -c $(VFR_CPPFLAGS) $(INC) $? -o $@ + +VfrSyntax.o: VfrSyntax.cpp + $(CXX) -c $(VFR_CPPFLAGS) $(INC) $? -o $@ + +clean: localClean + +localClean: + BIN_DIR='.' make -C Pccts/antlr clean + BIN_DIR='.' make -C Pccts/dlg clean + rm -f $(EXTRA_CLEAN_OBJECTS) + diff --git a/BaseTools/Source/C/VfrCompile/Makefile b/BaseTools/Source/C/VfrCompile/Makefile new file mode 100644 index 0000000000..e847b762f9 --- /dev/null +++ b/BaseTools/Source/C/VfrCompile/Makefile @@ -0,0 +1,44 @@ +!INCLUDE ..\Makefiles\ms.common + +CPPFLAGS = $(CPPFLAGS) /WX /D PCCTS_USE_NAMESPACE_STD /D VFREXP_DEBUG +APPNAME = VfrCompile + +LIBS = $(LIB_PATH)\Common.lib + +OBJECTS = AParser.obj DLexerBase.obj ATokenBuffer.obj \ + EfiVfrParser.obj VfrLexer.obj VfrSyntax.obj \ + VfrFormPkg.obj VfrError.obj VfrUtilityLib.obj VfrCompiler.obj + +INC = $(INC) -I $(BASE_TOOLS_PATH)\Source\C\VfrCompile\Pccts\h + +!INCLUDE ..\Makefiles\ms.app + +VfrSyntax.cpp EfiVfrParser.cpp EfiVfrParser.h VfrParser.dlg VfrTokens.h: VfrSyntax.g + pushd . & cd Pccts & $(MAKE) & popd + antlr -CC -e3 -ck 3 -k 2 -fl VfrParser.dlg -ft VfrTokens.h -o . VfrSyntax.g +# pushd . & cd Pccts & $(MAKE) clean + +VfrLexer.cpp VfrLexer.h: VfrParser.dlg + dlg -C2 -i -CC -cl VfrLexer -o . VfrParser.dlg + +ATokenBuffer.obj: Pccts\h\ATokenBuffer.cpp + $(CXX) -c $(CPPFLAGS) $(INC) $? -Fo$@ + +DLexerBase.obj: Pccts\h\DLexerBase.cpp + $(CXX) -c $(CPPFLAGS) $(INC) $? -Fo$@ + +AParser.obj: Pccts\h\AParser.cpp + $(CXX) -c $(CPPFLAGS) $(INC) $? -Fo$@ + +EXTRA_CLEAN_OBJECTS = VfrParser.dlg EfiVfrParser.cpp EfiVfrParser.h \ + VfrLexer.cpp VfrLexer.h \ + VfrSyntax.cpp VfrTokens.h + +clean: localClean +cleanall: localClean localCleanall + +localClean: + -DEL $(EXTRA_CLEAN_OBJECTS) + +localCleanall: + pushd . & cd Pccts & $(MAKE) cleanall & popd diff --git a/BaseTools/Source/C/VfrCompile/Pccts/CHANGES_FROM_131.txt b/BaseTools/Source/C/VfrCompile/Pccts/CHANGES_FROM_131.txt new file mode 100644 index 0000000000..500d84f2e8 --- /dev/null +++ b/BaseTools/Source/C/VfrCompile/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 instead of + +====================================================================== +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 : <>? 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 : <>? 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 : <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)? => <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 )? => <>? + +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 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 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 : <> + +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 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 +). + + +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." 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/BaseTools/Source/C/VfrCompile/Pccts/CHANGES_FROM_133.txt b/BaseTools/Source/C/VfrCompile/Pccts/CHANGES_FROM_133.txt new file mode 100644 index 0000000000..2128c4ff25 --- /dev/null +++ b/BaseTools/Source/C/VfrCompile/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 + <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 + "" 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_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 <> D <> 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 "" 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 (...) { + + } } + 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) { + match(A); + } else if (B) { + match(B); + } else { + if (cnt > 1) break; + FAIL(...{A,B,Z}...) FAIL(...{A,B}...); + } } + cnt++; + } } + + 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 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 + #else + #include + #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 + #define PCCTS_STDLIB_H + #define PCCTS_STDARG_H + #define PCCTS_SETJMP_H + #define PCCTS_STRING_H + #define PCCTS_ASSERT_H + #define PCCTS_ISTREAM_H + #define PCCTS_IOSTREAM_H + #define PCCTS_NAMESPACE_STD namespace std {}; using namespace std; + #else + #define PCCTS_STDIO_H + #define PCCTS_STDLIB_H + #define PCCTS_STDARG_H + #define PCCTS_SETJMP_H + #define PCCTS_STRING_H + #define PCCTS_ASSERT_H + #define PCCTS_ISTREAM_H + #define PCCTS_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 : + <> + (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)? => <>? 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)? => <>? (A B | D E) + ; + + b : <>? 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)? => <>? 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 + >> + +#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 : <

>? B ; + rq : (A)? => <>? (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 <> + + 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 : <<;>> <> rule2 + + The following will give an error message: + + rule1 : <> rule2 + + If the <> 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/BaseTools/Source/C/VfrCompile/Pccts/CHANGES_FROM_133_BEFORE_MR13.txt b/BaseTools/Source/C/VfrCompile/Pccts/CHANGES_FROM_133_BEFORE_MR13.txt new file mode 100644 index 0000000000..bba5ecdd64 --- /dev/null +++ b/BaseTools/Source/C/VfrCompile/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)? => <>? 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)? => <

>? r2 ; + r2 : (BBB)? => <>? Q + | (BBB)? => <>? 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" <> + +#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 : <>? A + | <>? 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 <>? + #pred IsLocalVar <>? + #pred IsGlobalVar <>? + #pred IsVar <>? IsLocalVar || IsGlobalVar + #pred IsScoped <>? 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 + ( + "<>?" + | "<>?" 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: <>? ID ; + rule3: <>? 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 <>? + + ... + + rule2: <>? ID ; + rule3: <>? 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 <>? + #pred NotX <>? + ... + rule2: <>? ID ; + rule3: <>? ID ; + + *Not* equivalent and is not simplified during hoisting: + + #pred IsX <>? + #pred NotX !IsX + ... + rule2: <>? ID ; + rule3: <>? 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: <>? X + | <>? 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 <>? + #pred Lower <>? + #pred Alpha <>? Upper || Lower + + rule0: rule1 + | <>? ID + ; + + rule1: + | rule2 + | rule3 + ... + ; + + rule2: <>? ID; + rule3: <>? 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: <>? ID + | <>? 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: <>? A + | rule2 + ; + + rule2: <>? A + | <>? 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 <>? + #pred B <>? + #pred A_or_B A || B + + r : s + | t + ; + s : <>? ID + ; + t : <>? 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 *) + + getType()==IDENTIFIER ? isTypeName(LT(1)->getText()) : 1>>? + ====> <getText())>>? + + <<(LT(1)->getType()==LPARENTHESIS && LT(2)->getType()==IDENTIFIER) ? \ + isTypeName(LT(2)->getText()) : 1>>? + ====> (LPARENTHESIS IDENTIFIER)? => <getText())>>? + + <<(LT(1)->getType()==LPARENTHESIS && LT(2)->getType()==IDENTIFIER) ? \ + isTypeName(LT(2)->getText()) : 1>>? + ====> (LPARENTHESIS IDENTIFIER)? => <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 : <>? 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: <>? A B + | <>? 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 .h + + The following code is now inserted into .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 (<>? ...)+ + + Prior to 1.33MR11, the following grammar would generate + redundant tests for the "while" condition. + + rule2 : (<>? 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)? && <

>? 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)? && <>? ab ; + b : (B)? && <>? 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 : <>? 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 : + <>? + 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)? => <>? + 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 : + <>? + LP typeName RP + | .... + ; + + typeName : <>? 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)? && <>? fun_call | + | | (ID)? && <>? 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>? 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 <>? 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 : <>? ( 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 : <>? + ( 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 : <>? 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 : <>? LP ID RP ; + + expr : LP ID RP ; + | <>? A + + Limitation (b) is illustrated by the following example of a + context guarded predicate: + + rule : (A)? <

>? // #1 + (A // #2 + |B // #3 + ) // #4 + | <> 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 : <>? 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)? && <

>? expr + + The existing context guarded predicate: + + rule : (guard)? => <

>? 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)? && <

>? expr + | next_alternative + ; + + The new style of context guarded predicate is equivalent to: + + rule : <>? 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)? && <>? 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 : <> + ( + rest-of-rule + ) + <> + ; /* fail clause */ <> + + 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]" <> + + class P { + + start : (top)+ + ; + + top : (which) ? <> + | other <> + ; <> + + which : which2 + ; + + which2 : which3 + ; + which3 + : (label)? <> + | (global)? <> + | (exclamation)? <> + ; + + label : <getText());>> A ":" ; + + global : <getText());>> A "::" ; + + exclamation : <getText());>> A "!" ; + + other : <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 : <>? + ; + + d : <>? B C + ; + + e : <>? 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 : <>? vowel; + vowel: : <>? 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 : <>? + | B + ; + + b : <>? 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 : <>? ( AAA | BBB ) + | <>? ( 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)? => <>? (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 : <>? ID X + | <>? 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 : <>? ID X + | <>? 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)? => <>? A ; + b : (B)? => <>? 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 ( + <>? 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. <>?). + 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 + #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 : <> + 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 + + 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 <> + exception[ex] + catch NoViableAlt: + <> + ; + + 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 <> + exception[ex] + catch NoViableAlt: + <> + ; + + 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 <> + exception[ex] + catch NoViableAlt: + <> + + 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: <> + + 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 + #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 + #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 + + 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 <> + + Adds source code to the DLGLexer.h file + after the #include "DLexerBase.h" but + before the start of the class definition. + + #lexmember <> + + 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 : <>?[ 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 : <>?[ 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 + 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 + + 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 + + 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 + + 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/BaseTools/Source/C/VfrCompile/Pccts/CHANGES_SUMMARY.txt b/BaseTools/Source/C/VfrCompile/Pccts/CHANGES_SUMMARY.txt new file mode 100644 index 0000000000..91defae169 --- /dev/null +++ b/BaseTools/Source/C/VfrCompile/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)? => <>? 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)? => <>? (A B | D E) + ; + + b : <>? 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 + >> + +#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 : <

>? B ; + rq : (A)? => <>? (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 <> + + 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 : <<;>> <> rule2 + + The following will give an error message: + + rule1 : <> rule2 + + If the <> 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" <> + +#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 : <>? A + | <>? 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 <>? + #pred IsLocalVar <>? + #pred IsGlobalVar <>? + #pred IsVar <>? IsLocalVar || IsGlobalVar + #pred IsScoped <>? 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 + ( + "<>?" + | "<>?" 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: <>? ID ; + rule3: <>? 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 <>? + + ... + + rule2: <>? ID ; + rule3: <>? 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 <>? + #pred NotX <>? + ... + rule2: <>? ID ; + rule3: <>? ID ; + + *Not* equivalent and is not simplified during hoisting: + + #pred IsX <>? + #pred NotX !IsX + ... + rule2: <>? ID ; + rule3: <>? 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: <>? X + | <>? 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 <>? + #pred Lower <>? + #pred Alpha <>? Upper || Lower + + rule0: rule1 + | <>? ID + ; + + rule1: + | rule2 + | rule3 + ... + ; + + rule2: <>? ID; + rule3: <>? 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: <>? ID + | <>? 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: <>? A + | rule2 + ; + + rule2: <>? A + | <>? 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 <>? + #pred B <>? + #pred A_or_B A || B + + r : s + | t + ; + s : <>? ID + ; + t : <>? 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 : <>? 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: <>? A B + | <>? 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 : <>? 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 : + <>? + 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)? => <>? + 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 : + <>? + LP typeName RP + | .... + ; + + typeName : <>? 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)? && <>? fun_call | + | | (ID)? && <>? 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>? 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 <>? 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 : <>? ( 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 : <>? + ( 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 : <>? 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 : <>? LP ID RP ; + + expr : LP ID RP ; + | <>? A + + Limitation (b) is illustrated by the following example of a + context guarded predicate: + + rule : (A)? <

>? // #1 + (A // #2 + |B // #3 + ) // #4 + | <> 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 : <>? 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)? && <

>? expr + + The existing context guarded predicate: + + rule : (guard)? => <

>? 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)? && <

>? expr + | next_alternative + ; + + The new style of context guarded predicate is equivalent to: + + rule : <>? 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)? && <>? 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 : <> + ( + rest-of-rule + ) + <> + ; /* fail clause */ <> + + 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]" <> + + class P { + + start : (top)+ + ; + + top : (which) ? <> + | other <> + ; <> + + which : which2 + ; + + which2 : which3 + ; + which3 + : (label)? <> + | (global)? <> + | (exclamation)? <> + ; + + label : <getText());>> A ":" ; + + global : <getText());>> A "::" ; + + exclamation : <getText());>> A "!" ; + + other : <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 : <>? + ; + + d : <>? B C + ; + + e : <>? 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 : <>? vowel; + vowel: : <>? 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 : <>? + | B + ; + + b : <>? 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 <> + exception[ex] + catch NoViableAlt: + <> + ; + + 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 <> + exception[ex] + catch NoViableAlt: + <> + ; + + 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 <> + + Adds source code to the DLGLexer.h file + after the #include "DLexerBase.h" but + before the start of the class definition. + + #lexmember <> + + 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/BaseTools/Source/C/VfrCompile/Pccts/KNOWN_PROBLEMS.txt b/BaseTools/Source/C/VfrCompile/Pccts/KNOWN_PROBLEMS.txt new file mode 100644 index 0000000000..5a9b22e1bd --- /dev/null +++ b/BaseTools/Source/C/VfrCompile/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)? => <

>? 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 <> D <> 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: + + /* + * ::= ( '|' {} )* + * + * 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/BaseTools/Source/C/VfrCompile/Pccts/MPW_Read_Me b/BaseTools/Source/C/VfrCompile/Pccts/MPW_Read_Me new file mode 100644 index 0000000000..70a9d1bcad --- /dev/null +++ b/BaseTools/Source/C/VfrCompile/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/BaseTools/Source/C/VfrCompile/Pccts/Makefile b/BaseTools/Source/C/VfrCompile/Pccts/Makefile new file mode 100644 index 0000000000..57eeda5934 --- /dev/null +++ b/BaseTools/Source/C/VfrCompile/Pccts/Makefile @@ -0,0 +1,15 @@ +# +# Main makefile for PCCTS 1.33MR33 /* MRXXX */ +# +pccts: + pushd . & cd antlr & $(MAKE) /nologo /f AntlrMS.mak & popd + pushd . & cd dlg & $(MAKE) /nologo /f DlgMS.mak & popd + +clean: + pushd . & cd antlr & $(MAKE) /nologo /f AntlrMS.mak clean & popd + pushd . & cd dlg & $(MAKE) /nologo /f DlgMS.mak clean & popd + +cleanall: + pushd . & cd antlr & $(MAKE) /nologo /f AntlrMS.mak cleanall & popd + pushd . & cd dlg & $(MAKE) /nologo /f DlgMS.mak cleanall & popd + diff --git a/BaseTools/Source/C/VfrCompile/Pccts/NOTES.bcc b/BaseTools/Source/C/VfrCompile/Pccts/NOTES.bcc new file mode 100644 index 0000000000..1ac05b17c5 --- /dev/null +++ b/BaseTools/Source/C/VfrCompile/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/BaseTools/Source/C/VfrCompile/Pccts/NOTES.msvc b/BaseTools/Source/C/VfrCompile/Pccts/NOTES.msvc new file mode 100644 index 0000000000..86f8ed66e0 --- /dev/null +++ b/BaseTools/Source/C/VfrCompile/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 + +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/BaseTools/Source/C/VfrCompile/Pccts/README b/BaseTools/Source/C/VfrCompile/Pccts/README new file mode 100644 index 0000000000..d089b638b4 --- /dev/null +++ b/BaseTools/Source/C/VfrCompile/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/BaseTools/Source/C/VfrCompile/Pccts/RIGHTS b/BaseTools/Source/C/VfrCompile/Pccts/RIGHTS new file mode 100644 index 0000000000..9db175ff40 --- /dev/null +++ b/BaseTools/Source/C/VfrCompile/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/BaseTools/Source/C/VfrCompile/Pccts/antlr/AntlrDDK.mak b/BaseTools/Source/C/VfrCompile/Pccts/antlr/AntlrDDK.mak new file mode 100644 index 0000000000..71b7c6b0b1 --- /dev/null +++ b/BaseTools/Source/C/VfrCompile/Pccts/antlr/AntlrDDK.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= +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 bufferoverflowu.lib $(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/BaseTools/Source/C/VfrCompile/Pccts/antlr/AntlrMS.mak b/BaseTools/Source/C/VfrCompile/Pccts/antlr/AntlrMS.mak new file mode 100644 index 0000000000..8d87547a50 --- /dev/null +++ b/BaseTools/Source/C/VfrCompile/Pccts/antlr/AntlrMS.mak @@ -0,0 +1,238 @@ +# 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= +PCCTS_HOME=$(BASE_TOOLS_PATH)\Source\C\VfrCompile\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 \ + /D _CRT_SECURE_NO_DEPRECATE /D _CRT_NONSTDC_NO_DEPRECATE + +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 + +$(EDK_TOOLS_PATH)\Bin\Win32\antlr.exe: $(ANTLR_OBJS) $(SUPPORT_OBJS) + $(CC) $(CFLAGS) -Feantlr.exe $(ANTLR_OBJS) $(SUPPORT_OBJS) + copy antlr.exe $(EDK_TOOLS_PATH)\Bin\Win32 + + +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 + -del *.ilk + -del *.pdb + +cleanall: + -del *.obj + -del *.ilk + -del *.pdb + -del *.exe + -del $(EDK_TOOLS_PATH)\Bin\Win32\antlr.exe diff --git a/BaseTools/Source/C/VfrCompile/Pccts/antlr/AntlrPPC.mak b/BaseTools/Source/C/VfrCompile/Pccts/antlr/AntlrPPC.mak new file mode 100644 index 0000000000..9ede60d64c --- /dev/null +++ b/BaseTools/Source/C/VfrCompile/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/BaseTools/Source/C/VfrCompile/Pccts/antlr/README b/BaseTools/Source/C/VfrCompile/Pccts/antlr/README new file mode 100644 index 0000000000..d7fc95916e --- /dev/null +++ b/BaseTools/Source/C/VfrCompile/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/BaseTools/Source/C/VfrCompile/Pccts/antlr/antlr.1 b/BaseTools/Source/C/VfrCompile/Pccts/antlr/antlr.1 new file mode 100644 index 0000000000..acfa85b066 --- /dev/null +++ b/BaseTools/Source/C/VfrCompile/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/BaseTools/Source/C/VfrCompile/Pccts/antlr/antlr.c b/BaseTools/Source/C/VfrCompile/Pccts/antlr/antlr.c new file mode 100644 index 0000000000..8aaef794e1 --- /dev/null +++ b/BaseTools/Source/C/VfrCompile/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 +#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("<> appears as init-action - use <<>> <>", + /* 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)? && <>? ... 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/BaseTools/Source/C/VfrCompile/Pccts/antlr/antlr.g b/BaseTools/Source/C/VfrCompile/Pccts/antlr/antlr.g new file mode 100644 index 0000000000..e6eda6010c --- /dev/null +++ b/BaseTools/Source/C/VfrCompile/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 + #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 "\@" <> /* 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 : <> + ( "{\\}#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 <> + ( rule + + <> + + | 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 + ; + <> + +/* rule class_def */ + +class_def + : <> + "class" + ( NonTerminal <> + | TokenTerm <> + ) + << + if ( CurrentClassName[0]!='\0' && strcmp(CurrentClassName,name)!=0 + && GenCC ) { + err("only one grammar class allowed in this release"); + go = 0; + } + else strcpy(CurrentClassName, name); + >> + <> + +/* MR10 */ (~ "\{" +/* MR10 */ <> +/* MR10 */ )* + + "\{" + << + no_classes_found = 0; + if ( class_nest_level>=1 ) {warn("cannot have nested classes");} + else class_nest_level++; + >> + ; + <> + +/* + * 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 + <str; + } + CurRuleNode = q; + f = CurFile; l = zzline; + NumRules++; + >> + { "!" <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 <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); + } + } + >> + <= MAX_BLK_LEVEL) fatal("Blocks nested too deeply"); +/* MR23 */ CurBlockID_array[BlkLevel] = CurBlockID; +/* MR23 */ CurAltNum_array[BlkLevel] = CurAltNum; + >> + + ":" <> + block[&toksrefd, &rulesrefd] + <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; + >> + <> /* MR7 */ + ";" <> + { 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] + <label == NULL || *eg->label=='\0' ) q->has_rule_exception = 1; + } + >> + )* + <> + <exceptions = CurExGroups;>> + <el_labels = CurElementLabels;>> + <ast_labels_in_actions = CurAstLabelsInActions;>> /* MR27 */ + <> /* MR27 Moved */ + ; + <> + +/* + * pragma : "{\\}#pragma" "dup\-labeled\-tokens" + * <> + * ; + */ + +/* rule laction */ + +laction : <> + + "{\\}#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); + >> + ; + <> + +/* MR1 */ +/* MR1 11-Apr-97 Provide mechanism for inserting code into DLG class */ +/* MR1 via #lexmember <<....>> & #lexprefix <<...>> */ +/* MR1 */ + +/* rule lmember */ + +lmember: <> /* 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 */ <> + +/* rule lprefix */ + +lprefix: <> /* 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 */ <> + +/* + * #pred upper <>? predicate literal + * #pred lower <>? predicate literal + * #pred up_or_low upper || lower predicate expression + * concealed interdependence + * #pred up_or_low_2 <>? A || B predicate literal equals predicate expr + * analyze using lower||upper + * generate using isLetter() + */ + +/* rule aPref */ + +aPred: <> + + "{\\}#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 <> + + << + /* 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 <> + + { + predOrExpr>[predExpr] <> + } + + <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); + >> + + | + <> + + predOrExpr>[predExpr] + + <file=CurFile; + predEntry->line=zzline; + predExpr=MR_predFlatten(predExpr); + predEntry->pred=predExpr; + hash_add(Pname,name,(Entry *)predEntry); + predExpr=NULL; + }; + predicate_free(predExpr); + >> + ) + {";"} +; + +/* fail */ + +<> + +/* rule predOrExpr */ + +predOrExpr>[Predicate *result] : + <> + 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 */ + +<> + +/* rule predAndExpr */ + +predAndExpr>[Predicate *result] : + <> + 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 */ + +<> + + +/* rule predPrimary */ + +predPrimary>[Predicate *result] : + << + char *name=NULL; + PredEntry *predEntry=NULL; + Predicate *predExpr=NULL; + >> + + TokenTerm <> + + << + 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 <> + ; + <> + +/* rule error */ + +error : <> + "{\\}#errclass" + (<<;>> TokenTerm <> + | QuotedTerm <> + ) + <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 <> + | TokenTerm <> + | QuotedTerm <> + ) + <elist), t);>> + ( + ( NonTerminal <> + | TokenTerm <> + | QuotedTerm <> + ) + <elist), t);>> + )* + "\}" + ; + <> + +/* rule tclass */ + +tclass : <> + <> + <> + "{\\}#tokclass" TokenTerm <> + <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 */ <> +/* 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 + <> + + { + ".." + TokenTerm + + <> + } + + | QuotedTerm + <> + ) + <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 "+") + "\}" + ; + <> + +/* rule token */ + +token : <> + <> /* MR11 */ + "{\\}#token" + +/* MR1 10-Apr-97 MR1 Allow shift right operator in DLG actions */ +/* MR1 Danger when parser feedback to lexer */ +/* MR1 */ + + <> /* MR1 */ + { TokenTerm <> + +/* MR11 */ { +/* MR11 */ "\(" +/* MR11 */ QuotedTerm +/* MR11 */ <> +/* MR11 */ "\)" +/* MR11 */ } + + { "=" "[0-9]+" /* define the token type number */ + <> + } + } + { QuotedTerm <> } + { Action + << + a = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char)); + require(a!=NULL, "rule token: cannot allocate action"); + strcpy(a, LATEXT(1)); + >> + } + + { ";" } /* MR11 */ + + <> + + <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; + }; + }; + }; + >> + ; + <> + +/* 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] <> + + << + 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("<> appears as init-action - use <<>> <>", +/* 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); + } + >> + )* + <> + + ( "\|" <> + alt[toksrefd,rulesrefd] <> + << + ((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); + } + >> + )* + + <> + + )* + <<$0 = b;>> + <> + ; + <> + +/* rule alt */ + +alt[set *toksrefd, set *rulesrefd] + : <> + { "\@" /* handle MismatchedToken signals with default handler */ + <> + } + + ( <<;>> /* MR9 Removed unreferenced variable "tok" */ + { <> "\~" <> } + element[old_not, first_on_line, use_def_MT_handler] > [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); + } + } + } + >> + )* + <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; + >> + ; + <> + +/* rule element_label */ + +element_label > [LabelEntry *label] + : <> + LABEL <> + << + 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 + <> + | TokenTerm + <> + ) + } + << + if ( p!=NULL && (p->upper_range!=0 || p->tclass || $old_not) ) + list_add(&MetaTokenNodes, (void *)p); + >> + ( "^" <astnode=ASTroot;>> + | <astnode=ASTchild;>> + | "!" <astnode=ASTexclude;>> + ) + { "\@" <> } + << + 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 + <> + | TokenTerm + <> + ) + } + ( "^" <astnode=ASTroot;>> + | <astnode=ASTchild;>> + | "!" <astnode=ASTexclude;>> + ) + { "\@" <> } + << + 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; + >> + + | <> + "." + <<$$ = buildWildCard(LATEXT(1)); p=((TokNode *)((Junction *)$$.left)->p1);>> + ( "^" <astnode=ASTroot;>> + | <astnode=ASTchild;>> + | "!" <astnode=ASTexclude;>> + ) + <> + << + 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; + >> + + | <> + NonTerminal + <<$$ = buildRuleRef(LATEXT(1));>> + { "!" <p1; + q->astnode=ASTexclude;>> + } + { {"\<"} + PassAction <p1, LATEXT(1));>> + } + <p1;>> + { <> + "\>" + 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; + >> + ) + + | <> + Action <<$0 = buildAction(LATEXT(1),action_file,action_line, 0);>> + <> /* MR7 */ + <<$node = (Node *) ((Junction *)$0.left)->p1;>> + + | <> + Pred <<$0 = buildAction(LATEXT(1),action_file,action_line, 1);>> + <p1;>> + <> + { <> + 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; + >> + } + <> /* MR7 */ + <<$node = (Node *)act;>> + + | <> + <= MAX_BLK_LEVEL) fatal("Blocks nested too deeply"); +/* MR23 */ CurBlockID_array[BlkLevel] = CurBlockID; +/* MR23 */ CurAltNum_array[BlkLevel] = CurAltNum; + >> + { Pragma + ( "approx" <> + | "LL\(1\)" <> /* MR20 */ + | "LL\(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] "\)" + <> + + ( "\*" <<$$ = makeLoop($$,approx,pFirstSetSymbol);>> + | "\+" <<$$ = makePlus($$,approx,pFirstSetSymbol);>> + | "?" + ( + ( "=>" <> + | "&&" <> /* MR10 (g)? && <

>? */ + ) + Pred /* generalized predicate */ + /* first make into a predicate */ + <<$$ = buildAction(LATEXT(1),action_file,action_line,1);>> + <p1;>> + <> /* MR10 */ + <> + { <> + 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; + >> + } + <> + <<$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)? && <>? ... 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; + >> + <p1); /* MR7 */ + altAdd(CurAltStart); /* MR7 */ + }; + >> + <<$node = (Node *) ((Junction *)$$.left)->p1;>> + + ) + +/* Error catching alternatives */ + | "\*" <> + | "\+" <> + | "\>" <' can only appear after a nonterminal"); CannotContinue=TRUE;>> + | PassAction < [...]'"); + CannotContinue=TRUE;>> + ; + <> + +/* rule default_exception_handler */ + +default_exception_handler + : exception_group > [DefaultExGroup] + ; + +/* rule exception_group */ + +exception_group > [ExceptionGroup *eg] + : <> /* MR6 */ + + "exception" <<$eg = (ExceptionGroup *)calloc(1, sizeof(ExceptionGroup));>> + { <> + 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] + <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 */ }; + + >> + ; + <> + +/* 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)); + >> + } + ; + <> + +#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_]*" <> + +#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] + : <> /* MR3 */ + ( + "#define" ID + <> + 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); + }; + }; + >> + )+ + <> + ; + +/* rule enum_def */ + +enum_def[char *fname] + : <> /* MR3 */ + "enum" ID + "\{" + ID + <> + ( "=" INT <> + | <> + ) + << +/* 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 */ + + { + <>? ID { "=" INT } /* MR2 */ + | ID /* MR2 */ + <> + ( "=" INT <> + | <> + ) + << +/* 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); + } + >> + } + )* + "\}" + ";" + <> /* 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> + +<< + +/* 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/BaseTools/Source/C/VfrCompile/Pccts/antlr/antlr.r b/BaseTools/Source/C/VfrCompile/Pccts/antlr/antlr.r new file mode 100644 index 0000000000..e3de38759f --- /dev/null +++ b/BaseTools/Source/C/VfrCompile/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/BaseTools/Source/C/VfrCompile/Pccts/antlr/antlr1.txt b/BaseTools/Source/C/VfrCompile/Pccts/antlr/antlr1.txt new file mode 100644 index 0000000000..4a7d22e7f2 --- /dev/null +++ b/BaseTools/Source/C/VfrCompile/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/BaseTools/Source/C/VfrCompile/Pccts/antlr/bits.c b/BaseTools/Source/C/VfrCompile/Pccts/antlr/bits.c new file mode 100644 index 0000000000..ddd9bd6053 --- /dev/null +++ b/BaseTools/Source/C/VfrCompile/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 +#include +#include +#include +#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>(i*BitsPerByte)); + if ( itok))); + 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=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 ) + { + 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 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=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 ) + { + 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/BaseTools/Source/C/VfrCompile/Pccts/antlr/build.c b/BaseTools/Source/C/VfrCompile/Pccts/antlr/build.c new file mode 100644 index 0000000000..4eb3b02af1 --- /dev/null +++ b/BaseTools/Source/C/VfrCompile/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 +#include +#include +#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 +#include + +#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/BaseTools/Source/C/VfrCompile/Pccts/antlr/dumpnode.c b/BaseTools/Source/C/VfrCompile/Pccts/antlr/dumpnode.c new file mode 100644 index 0000000000..2a34c6fcd5 --- /dev/null +++ b/BaseTools/Source/C/VfrCompile/Pccts/antlr/dumpnode.c @@ -0,0 +1,423 @@ +#include +#include + +#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; iexpr == 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; iscontext[1]); + for (i=0; itcontext); + 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/BaseTools/Source/C/VfrCompile/Pccts/antlr/egman.c b/BaseTools/Source/C/VfrCompile/Pccts/antlr/egman.c new file mode 100644 index 0000000000..c8a633fc06 --- /dev/null +++ b/BaseTools/Source/C/VfrCompile/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 +#include + +#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; ipendingLink; + 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/BaseTools/Source/C/VfrCompile/Pccts/antlr/err.c b/BaseTools/Source/C/VfrCompile/Pccts/antlr/err.c new file mode 100644 index 0000000000..ca239398cf --- /dev/null +++ b/BaseTools/Source/C/VfrCompile/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 +#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/BaseTools/Source/C/VfrCompile/Pccts/antlr/fcache.c b/BaseTools/Source/C/VfrCompile/Pccts/antlr/fcache.c new file mode 100644 index 0000000000..ff7dcdfdd5 --- /dev/null +++ b/BaseTools/Source/C/VfrCompile/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 +#include + +#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/BaseTools/Source/C/VfrCompile/Pccts/antlr/fset.c b/BaseTools/Source/C/VfrCompile/Pccts/antlr/fset.c new file mode 100644 index 0000000000..e1a76ec620 --- /dev/null +++ b/BaseTools/Source/C/VfrCompile/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 +#include + +#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 : <>? (A B|A C) + * | b + * ; + * b : <>? 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=1 permutation; + * don't bother doing full LL(k) analysis. + * (This "if" block handles the LL(1) case) + */ + + n2 = 0; + for (i=1; ifset[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 kp1)!=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 kaltnum; + 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/BaseTools/Source/C/VfrCompile/Pccts/antlr/fset2.c b/BaseTools/Source/C/VfrCompile/Pccts/antlr/fset2.c new file mode 100644 index 0000000000..7f686a53d5 --- /dev/null +++ b/BaseTools/Source/C/VfrCompile/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 +#include "pcctscfg.h" +#include + +#ifdef PCCTS_USE_STDARG +#include +#else +#include +#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: <

>? r2 + guarded: r1: (A)? => <

>? r2 + ampersand style: r1: (A)? && <

>? 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)? && <

>? 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 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 +#include +#include +#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; irname);} + 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<= 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<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<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/BaseTools/Source/C/VfrCompile/Pccts/antlr/generic.h b/BaseTools/Source/C/VfrCompile/Pccts/antlr/generic.h new file mode 100644 index 0000000000..8d736d5200 --- /dev/null +++ b/BaseTools/Source/C/VfrCompile/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 diff --git a/BaseTools/Source/C/VfrCompile/Pccts/antlr/globals.c b/BaseTools/Source/C/VfrCompile/Pccts/antlr/globals.c new file mode 100644 index 0000000000..59d00320a0 --- /dev/null +++ b/BaseTools/Source/C/VfrCompile/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 + +#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/BaseTools/Source/C/VfrCompile/Pccts/antlr/hash.c b/BaseTools/Source/C/VfrCompile/Pccts/antlr/hash.c new file mode 100644 index 0000000000..68fe8fd227 --- /dev/null +++ b/BaseTools/Source/C/VfrCompile/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 +#include "pcctscfg.h" +#include "hash.h" + +#ifdef __USE_PROTOS +#include +#else +#ifdef VAXC +#include +#else +#include +#endif +#endif +#include + +#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/BaseTools/Source/C/VfrCompile/Pccts/antlr/hash.h b/BaseTools/Source/C/VfrCompile/Pccts/antlr/hash.h new file mode 100644 index 0000000000..3969c40b4a --- /dev/null +++ b/BaseTools/Source/C/VfrCompile/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/BaseTools/Source/C/VfrCompile/Pccts/antlr/lex.c b/BaseTools/Source/C/VfrCompile/Pccts/antlr/lex.c new file mode 100644 index 0000000000..8c524fe465 --- /dev/null +++ b/BaseTools/Source/C/VfrCompile/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 +#include +/* 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 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; inext; 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; i1 ) + { + 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 ) + { + 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; irname, 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/BaseTools/Source/C/VfrCompile/Pccts/antlr/main.c b/BaseTools/Source/C/VfrCompile/Pccts/antlr/main.c new file mode 100644 index 0000000000..051ee4ec5d --- /dev/null +++ b/BaseTools/Source/C/VfrCompile/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 + +#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 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 /* */ +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 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; inext; 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 <> 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 <> 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; j0, "pushint: stack overflow"); + istack[--isp] = i; +} + +int +#ifdef __USE_PROTOS +popint( void ) +#else +popint( ) +#endif +{ + require(isp 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 && 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/BaseTools/Source/C/VfrCompile/Pccts/antlr/makefile b/BaseTools/Source/C/VfrCompile/Pccts/antlr/makefile new file mode 100644 index 0000000000..478a3a1ccf --- /dev/null +++ b/BaseTools/Source/C/VfrCompile/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 + +$(BIN_DIR)/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 $(BIN_DIR)/antlr *.$(OBJ_EXT) core + +#remove everything in clean plus the PCCTS files generated +scrub: + rm -f $(PCCTS_GEN) *.$(OBJ_EXT) core diff --git a/BaseTools/Source/C/VfrCompile/Pccts/antlr/makefile.cygwin b/BaseTools/Source/C/VfrCompile/Pccts/antlr/makefile.cygwin new file mode 100644 index 0000000000..956de0be07 --- /dev/null +++ b/BaseTools/Source/C/VfrCompile/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/BaseTools/Source/C/VfrCompile/Pccts/antlr/makefile1 b/BaseTools/Source/C/VfrCompile/Pccts/antlr/makefile1 new file mode 100644 index 0000000000..dffc709478 --- /dev/null +++ b/BaseTools/Source/C/VfrCompile/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/BaseTools/Source/C/VfrCompile/Pccts/antlr/misc.c b/BaseTools/Source/C/VfrCompile/Pccts/antlr/misc.c new file mode 100644 index 0000000000..3f58da34c5 --- /dev/null +++ b/BaseTools/Source/C/VfrCompile/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 +#include "pcctscfg.h" +#include "set.h" +#include "syn.h" +#include "hash.h" +#include "generic.h" +#include "dlgdef.h" +#include + +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; iexpr = 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(iaction!=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; inext; 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; itnum]!=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; itoken = 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][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 f = TFoo(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/BaseTools/Source/C/VfrCompile/Pccts/antlr/mode.h b/BaseTools/Source/C/VfrCompile/Pccts/antlr/mode.h new file mode 100644 index 0000000000..c08bf31ac7 --- /dev/null +++ b/BaseTools/Source/C/VfrCompile/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/BaseTools/Source/C/VfrCompile/Pccts/antlr/mrhoist.c b/BaseTools/Source/C/VfrCompile/Pccts/antlr/mrhoist.c new file mode 100644 index 0000000000..110bf5996f --- /dev/null +++ b/BaseTools/Source/C/VfrCompile/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 + +#include "pcctscfg.h" + +#include "set.h" +#include "syn.h" +#include "hash.h" +#include "generic.h" +#include "dlgdef.h" +#include + +#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; irname,rrn->line,FileStr[rrn->file],rrn->text); + }; + lastOne=MR_ruleReferenced(rrn); + if (lastOne != NULL) { + for (j=0; jrname,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)? => <

>? r2; */ + /* r2: (B)? => <>? 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)? => <

>? sub1; /* 1 */ + | (B)? => <>? sub2 /* 2 */ + sub1 : (A)? => <>? 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 && ip2) { + + /* 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: + * + * ( <>? a1 a2 a3 | <>? 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 : <>? X". It cannot be set under any + * other circumstances. In particular it cannot be set by + * "#pred NotA !A" or by "#pred Nota <>?". 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)? => <

>? r2 (A|B) + r1b : (A)? => <

>? 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/BaseTools/Source/C/VfrCompile/Pccts/antlr/parser.dlg b/BaseTools/Source/C/VfrCompile/Pccts/antlr/parser.dlg new file mode 100644 index 0000000000..8c43dff300 --- /dev/null +++ b/BaseTools/Source/C/VfrCompile/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 +#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> + +<<%%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/BaseTools/Source/C/VfrCompile/Pccts/antlr/pred.c b/BaseTools/Source/C/VfrCompile/Pccts/antlr/pred.c new file mode 100644 index 0000000000..eb11c4d950 --- /dev/null +++ b/BaseTools/Source/C/VfrCompile/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 +#include "pcctscfg.h" +#include "set.h" +#include "syn.h" +#include "hash.h" +#include "generic.h" +#include "dlgdef.h" +#include + +#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/BaseTools/Source/C/VfrCompile/Pccts/antlr/proto.h b/BaseTools/Source/C/VfrCompile/Pccts/antlr/proto.h new file mode 100644 index 0000000000..53035e720e --- /dev/null +++ b/BaseTools/Source/C/VfrCompile/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 +#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/BaseTools/Source/C/VfrCompile/Pccts/antlr/scan.c b/BaseTools/Source/C/VfrCompile/Pccts/antlr/scan.c new file mode 100644 index 0000000000..9b4bde08e6 --- /dev/null +++ b/BaseTools/Source/C/VfrCompile/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 +#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; + (ielem->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/BaseTools/Source/C/VfrCompile/Pccts/antlr/stdpccts.h b/BaseTools/Source/C/VfrCompile/Pccts/antlr/stdpccts.h new file mode 100644 index 0000000000..ccdc21c3c9 --- /dev/null +++ b/BaseTools/Source/C/VfrCompile/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 +#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/BaseTools/Source/C/VfrCompile/Pccts/antlr/syn.h b/BaseTools/Source/C/VfrCompile/Pccts/antlr/syn.h new file mode 100644 index 0000000000..a23d196d77 --- /dev/null +++ b/BaseTools/Source/C/VfrCompile/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)? && <

>? */ + 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)? && <

>? expr */ +#ifdef __cplusplus + Junction *guardNodes; /* MR11 */ +#else + struct _junct *guardNodes; /* MR11 */ +#endif + struct _PredEntry *predEntry; /* MR11 */ + int inverted; /* MR11 <>? */ +#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/BaseTools/Source/C/VfrCompile/Pccts/antlr/tokens.h b/BaseTools/Source/C/VfrCompile/Pccts/antlr/tokens.h new file mode 100644 index 0000000000..91a53a8471 --- /dev/null +++ b/BaseTools/Source/C/VfrCompile/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/BaseTools/Source/C/VfrCompile/Pccts/dlg/DlgDDK.mak b/BaseTools/Source/C/VfrCompile/Pccts/dlg/DlgDDK.mak new file mode 100644 index 0000000000..156d524acc --- /dev/null +++ b/BaseTools/Source/C/VfrCompile/Pccts/dlg/DlgDDK.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= +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 bufferoverflowu.lib $(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/BaseTools/Source/C/VfrCompile/Pccts/dlg/DlgMS.mak b/BaseTools/Source/C/VfrCompile/Pccts/dlg/DlgMS.mak new file mode 100644 index 0000000000..18c37d3656 --- /dev/null +++ b/BaseTools/Source/C/VfrCompile/Pccts/dlg/DlgMS.mak @@ -0,0 +1,125 @@ +# 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= +PCCTS_HOME=$(BASE_TOOLS_PATH)\Source\C\VfrCompile\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 \ + /D _CRT_SECURE_NO_DEPRECATE /D _CRT_NONSTDC_NO_DEPRECATE + +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) -Fedlg.exe $(DLG_OBJS) $(SUPPORT_OBJS) + copy dlg.exe $(EDK_TOOLS_PATH)\Bin\Win32 + +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 + -del *.ilk + -del *.pdb + +cleanall: + -del *.obj + -del *.ilk + -del *.pdb + -del *.exe + -del $(EDK_TOOLS_PATH)\Bin\Win32\dlg.exe + diff --git a/BaseTools/Source/C/VfrCompile/Pccts/dlg/DlgPPC.mak b/BaseTools/Source/C/VfrCompile/Pccts/dlg/DlgPPC.mak new file mode 100644 index 0000000000..55b643ad88 --- /dev/null +++ b/BaseTools/Source/C/VfrCompile/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/BaseTools/Source/C/VfrCompile/Pccts/dlg/automata.c b/BaseTools/Source/C/VfrCompile/Pccts/dlg/automata.c new file mode 100644 index 0000000000..d6d5d7809d --- /dev/null +++ b/BaseTools/Source/C/VfrCompile/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 +#include "pcctscfg.h" +#include "dlg.h" +#ifdef MEMCHK +#include "trax.h" +#else +#ifdef __STDC__ +#include +#else +#include +#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; itrans[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; jtrans[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; at, 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; inext; + } + 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/BaseTools/Source/C/VfrCompile/Pccts/dlg/dlg.1 b/BaseTools/Source/C/VfrCompile/Pccts/dlg/dlg.1 new file mode 100644 index 0000000000..f68e3ae8a7 --- /dev/null +++ b/BaseTools/Source/C/VfrCompile/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/BaseTools/Source/C/VfrCompile/Pccts/dlg/dlg.h b/BaseTools/Source/C/VfrCompile/Pccts/dlg/dlg.h new file mode 100644 index 0000000000..9f387c0a1c --- /dev/null +++ b/BaseTools/Source/C/VfrCompile/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/BaseTools/Source/C/VfrCompile/Pccts/dlg/dlg.r b/BaseTools/Source/C/VfrCompile/Pccts/dlg/dlg.r new file mode 100644 index 0000000000..c5311fa1b8 --- /dev/null +++ b/BaseTools/Source/C/VfrCompile/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/BaseTools/Source/C/VfrCompile/Pccts/dlg/dlg1.txt b/BaseTools/Source/C/VfrCompile/Pccts/dlg/dlg1.txt new file mode 100644 index 0000000000..06b320de2a --- /dev/null +++ b/BaseTools/Source/C/VfrCompile/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/BaseTools/Source/C/VfrCompile/Pccts/dlg/dlg_a.c b/BaseTools/Source/C/VfrCompile/Pccts/dlg/dlg_a.c new file mode 100644 index 0000000000..0b8982cf2a --- /dev/null +++ b/BaseTools/Source/C/VfrCompile/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 +#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/BaseTools/Source/C/VfrCompile/Pccts/dlg/dlg_p.c b/BaseTools/Source/C/VfrCompile/Pccts/dlg/dlg_p.c new file mode 100644 index 0000000000..e726ae3983 --- /dev/null +++ b/BaseTools/Source/C/VfrCompile/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 +#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/BaseTools/Source/C/VfrCompile/Pccts/dlg/dlg_p.g b/BaseTools/Source/C/VfrCompile/Pccts/dlg/dlg_p.g new file mode 100644 index 0000000000..58ca110693 --- /dev/null +++ b/BaseTools/Source/C/VfrCompile/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 +#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 */ + <> /* MR1 */ +#token LEXACTION "\<\<\%\%lexaction" /* MR1 */ + <> /* MR1 */ +#token PARSERCLASS "\<\<\%\%parserclass" /* MR1 */ + <> /* MR1 */ +#token LEXPREFIX "\<\<\%\%lexprefix" /* MR1 */ + <> /* 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 */ + <> + 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 : <> + 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 */ <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 <>)* + ; + +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;>> + ; + +<> + +#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/BaseTools/Source/C/VfrCompile/Pccts/dlg/err.c b/BaseTools/Source/C/VfrCompile/Pccts/dlg/err.c new file mode 100644 index 0000000000..c3eaeae6d1 --- /dev/null +++ b/BaseTools/Source/C/VfrCompile/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 +#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/BaseTools/Source/C/VfrCompile/Pccts/dlg/main.c b/BaseTools/Source/C/VfrCompile/Pccts/dlg/main.c new file mode 100644 index 0000000000..35bd827f8c --- /dev/null +++ b/BaseTools/Source/C/VfrCompile/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 +#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 +#include +#include "dlg.h" +#ifdef MEMCHK +#include "trax.h" +#else +#ifdef __STDC__ +#include +#else +#include +#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> */ +/* 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 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]; itrans[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=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; itrans[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/BaseTools/Source/C/VfrCompile/Pccts/dlg/parser.dlg b/BaseTools/Source/C/VfrCompile/Pccts/dlg/parser.dlg new file mode 100644 index 0000000000..df9a637f9e --- /dev/null +++ b/BaseTools/Source/C/VfrCompile/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 +#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/BaseTools/Source/C/VfrCompile/Pccts/dlg/relabel.c b/BaseTools/Source/C/VfrCompile/Pccts/dlg/relabel.c new file mode 100644 index 0000000000..0b8bc163d1 --- /dev/null +++ b/BaseTools/Source/C/VfrCompile/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 +#include "dlg.h" +#ifdef MEMCHK +#include "trax.h" +#else +#ifdef __STDC__ +#include +#else +#include +#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,¤t_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; ilabel)) + 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/BaseTools/Source/C/VfrCompile/Pccts/dlg/stdpccts.h b/BaseTools/Source/C/VfrCompile/Pccts/dlg/stdpccts.h new file mode 100644 index 0000000000..06ec67e44d --- /dev/null +++ b/BaseTools/Source/C/VfrCompile/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 +#include "dlg.h" +#define zzSET_SIZE 8 +#include "antlr.h" +#include "tokens.h" +#include "dlgdef.h" +#include "mode.h" +#endif diff --git a/BaseTools/Source/C/VfrCompile/Pccts/dlg/support.c b/BaseTools/Source/C/VfrCompile/Pccts/dlg/support.c new file mode 100644 index 0000000000..84fe99d69c --- /dev/null +++ b/BaseTools/Source/C/VfrCompile/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 +#include +#include "dlg.h" +#ifdef MEMCHK +#include "trax.h" +#else +#ifdef __STDC__ +#include +#else +#include +#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/BaseTools/Source/C/VfrCompile/Pccts/dlg/tokens.h b/BaseTools/Source/C/VfrCompile/Pccts/dlg/tokens.h new file mode 100644 index 0000000000..73e502b7e1 --- /dev/null +++ b/BaseTools/Source/C/VfrCompile/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/BaseTools/Source/C/VfrCompile/Pccts/h/AParser.cpp b/BaseTools/Source/C/VfrCompile/Pccts/h/AParser.cpp new file mode 100644 index 0000000000..720fe75af1 --- /dev/null +++ b/BaseTools/Source/C/VfrCompile/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 + "" 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 = ""; + } + /* 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] == '@')?"":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] == '@')?"":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/BaseTools/Source/C/VfrCompile/Pccts/h/AParser.h b/BaseTools/Source/C/VfrCompile/Pccts/h/AParser.h new file mode 100644 index 0000000000..fe405f4167 --- /dev/null +++ b/BaseTools/Source/C/VfrCompile/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/BaseTools/Source/C/VfrCompile/Pccts/h/ASTBase.cpp b/BaseTools/Source/C/VfrCompile/Pccts/h/ASTBase.cpp new file mode 100644 index 0000000000..a94f080c86 --- /dev/null +++ b/BaseTools/Source/C/VfrCompile/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/BaseTools/Source/C/VfrCompile/Pccts/h/ASTBase.h b/BaseTools/Source/C/VfrCompile/Pccts/h/ASTBase.h new file mode 100644 index 0000000000..912f4b8482 --- /dev/null +++ b/BaseTools/Source/C/VfrCompile/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/BaseTools/Source/C/VfrCompile/Pccts/h/ATokPtr.h b/BaseTools/Source/C/VfrCompile/Pccts/h/ATokPtr.h new file mode 100644 index 0000000000..75b4c86cbf --- /dev/null +++ b/BaseTools/Source/C/VfrCompile/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/BaseTools/Source/C/VfrCompile/Pccts/h/ATokPtrImpl.h b/BaseTools/Source/C/VfrCompile/Pccts/h/ATokPtrImpl.h new file mode 100644 index 0000000000..9c07cf52a9 --- /dev/null +++ b/BaseTools/Source/C/VfrCompile/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/BaseTools/Source/C/VfrCompile/Pccts/h/AToken.h b/BaseTools/Source/C/VfrCompile/Pccts/h/AToken.h new file mode 100644 index 0000000000..6167c21ef5 --- /dev/null +++ b/BaseTools/Source/C/VfrCompile/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/BaseTools/Source/C/VfrCompile/Pccts/h/ATokenBuffer.cpp b/BaseTools/Source/C/VfrCompile/Pccts/h/ATokenBuffer.cpp new file mode 100644 index 0000000000..9a2f2fc88b --- /dev/null +++ b/BaseTools/Source/C/VfrCompile/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/BaseTools/Source/C/VfrCompile/Pccts/h/ATokenBuffer.h b/BaseTools/Source/C/VfrCompile/Pccts/h/ATokenBuffer.h new file mode 100644 index 0000000000..1c008fd59e --- /dev/null +++ b/BaseTools/Source/C/VfrCompile/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/BaseTools/Source/C/VfrCompile/Pccts/h/ATokenStream.h b/BaseTools/Source/C/VfrCompile/Pccts/h/ATokenStream.h new file mode 100644 index 0000000000..3dfea6ebff --- /dev/null +++ b/BaseTools/Source/C/VfrCompile/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/BaseTools/Source/C/VfrCompile/Pccts/h/BufFileInput.cpp b/BaseTools/Source/C/VfrCompile/Pccts/h/BufFileInput.cpp new file mode 100644 index 0000000000..99d08a42a4 --- /dev/null +++ b/BaseTools/Source/C/VfrCompile/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/BaseTools/Source/C/VfrCompile/Pccts/h/BufFileInput.h b/BaseTools/Source/C/VfrCompile/Pccts/h/BufFileInput.h new file mode 100644 index 0000000000..ea54c0ee26 --- /dev/null +++ b/BaseTools/Source/C/VfrCompile/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/BaseTools/Source/C/VfrCompile/Pccts/h/DLG_stream_input.h b/BaseTools/Source/C/VfrCompile/Pccts/h/DLG_stream_input.h new file mode 100644 index 0000000000..d2147f5217 --- /dev/null +++ b/BaseTools/Source/C/VfrCompile/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 + > +class DLG_stream_input : public DLGInputStream +{ +public: + + DLG_stream_input(::std::basic_istream * 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 * input; + +private: + + void purge() + { + // nothing to do! + }; +}; + +#endif /* _DLG_STREAM_INPUT_H */ + diff --git a/BaseTools/Source/C/VfrCompile/Pccts/h/DLexer.h b/BaseTools/Source/C/VfrCompile/Pccts/h/DLexer.h new file mode 100644 index 0000000000..37cac24f14 --- /dev/null +++ b/BaseTools/Source/C/VfrCompile/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*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/BaseTools/Source/C/VfrCompile/Pccts/h/DLexerBase.cpp b/BaseTools/Source/C/VfrCompile/Pccts/h/DLexerBase.cpp new file mode 100644 index 0000000000..b218afc038 --- /dev/null +++ b/BaseTools/Source/C/VfrCompile/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/BaseTools/Source/C/VfrCompile/Pccts/h/DLexerBase.h b/BaseTools/Source/C/VfrCompile/Pccts/h/DLexerBase.h new file mode 100644 index 0000000000..db6cc1890c --- /dev/null +++ b/BaseTools/Source/C/VfrCompile/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/BaseTools/Source/C/VfrCompile/Pccts/h/PBlackBox.h b/BaseTools/Source/C/VfrCompile/Pccts/h/PBlackBox.h new file mode 100644 index 0000000000..d25b8d6939 --- /dev/null +++ b/BaseTools/Source/C/VfrCompile/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 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/BaseTools/Source/C/VfrCompile/Pccts/h/PCCTSAST.cpp b/BaseTools/Source/C/VfrCompile/Pccts/h/PCCTSAST.cpp new file mode 100644 index 0000000000..a8249cdac0 --- /dev/null +++ b/BaseTools/Source/C/VfrCompile/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 + +//#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 */ (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 ""; + else return ""; +} + +//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/BaseTools/Source/C/VfrCompile/Pccts/h/PCCTSAST.h b/BaseTools/Source/C/VfrCompile/Pccts/h/PCCTSAST.h new file mode 100644 index 0000000000..3485da7d1b --- /dev/null +++ b/BaseTools/Source/C/VfrCompile/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/BaseTools/Source/C/VfrCompile/Pccts/h/SList.h b/BaseTools/Source/C/VfrCompile/Pccts/h/SList.h new file mode 100644 index 0000000000..5b8bf97427 --- /dev/null +++ b/BaseTools/Source/C/VfrCompile/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/BaseTools/Source/C/VfrCompile/Pccts/h/antlr.h b/BaseTools/Source/C/VfrCompile/Pccts/h/antlr.h new file mode 100644 index 0000000000..80664535d3 --- /dev/null +++ b/BaseTools/Source/C/VfrCompile/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 +#else +#include +#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/BaseTools/Source/C/VfrCompile/Pccts/h/ast.c b/BaseTools/Source/C/VfrCompile/Pccts/h/ast.c new file mode 100644 index 0000000000..9326ae16ae --- /dev/null +++ b/BaseTools/Source/C/VfrCompile/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 +#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/BaseTools/Source/C/VfrCompile/Pccts/h/ast.h b/BaseTools/Source/C/VfrCompile/Pccts/h/ast.h new file mode 100644 index 0000000000..5ff84bd76c --- /dev/null +++ b/BaseTools/Source/C/VfrCompile/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/BaseTools/Source/C/VfrCompile/Pccts/h/charbuf.h b/BaseTools/Source/C/VfrCompile/Pccts/h/charbuf.h new file mode 100644 index 0000000000..5f01c8ba35 --- /dev/null +++ b/BaseTools/Source/C/VfrCompile/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/BaseTools/Source/C/VfrCompile/Pccts/h/charptr.c b/BaseTools/Source/C/VfrCompile/Pccts/h/charptr.c new file mode 100644 index 0000000000..d3f80e60ba --- /dev/null +++ b/BaseTools/Source/C/VfrCompile/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 +#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/BaseTools/Source/C/VfrCompile/Pccts/h/charptr.h b/BaseTools/Source/C/VfrCompile/Pccts/h/charptr.h new file mode 100644 index 0000000000..e73da681a4 --- /dev/null +++ b/BaseTools/Source/C/VfrCompile/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/BaseTools/Source/C/VfrCompile/Pccts/h/config.h b/BaseTools/Source/C/VfrCompile/Pccts/h/config.h new file mode 100644 index 0000000000..8aa50ad618 --- /dev/null +++ b/BaseTools/Source/C/VfrCompile/Pccts/h/config.h @@ -0,0 +1 @@ +#include "pcctscfg.h" diff --git a/BaseTools/Source/C/VfrCompile/Pccts/h/dlgauto.h b/BaseTools/Source/C/VfrCompile/Pccts/h/dlgauto.h new file mode 100644 index 0000000000..db94cefaca --- /dev/null +++ b/BaseTools/Source/C/VfrCompile/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 +#include + +/* */ +/* 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 +#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; itokenLA[i] = zztokenLA[i]; + for (i=0; itextLA[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; itokenLA[i]; + for (i=0; itextLA[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)?"":(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)?"":(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/BaseTools/Source/C/VfrCompile/Pccts/h/int.h b/BaseTools/Source/C/VfrCompile/Pccts/h/int.h new file mode 100644 index 0000000000..cdcaa92426 --- /dev/null +++ b/BaseTools/Source/C/VfrCompile/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/BaseTools/Source/C/VfrCompile/Pccts/h/pccts_assert.h b/BaseTools/Source/C/VfrCompile/Pccts/h/pccts_assert.h new file mode 100644 index 0000000000..ff0dfb5126 --- /dev/null +++ b/BaseTools/Source/C/VfrCompile/Pccts/h/pccts_assert.h @@ -0,0 +1,10 @@ +#ifndef __PCCTS_ASSERT_H__ +#define __PCCTS_ASSERT_H__ + +#ifdef PCCTS_USE_NAMESPACE_STD +#include +#else +#include +#endif + +#endif diff --git a/BaseTools/Source/C/VfrCompile/Pccts/h/pccts_iostream.h b/BaseTools/Source/C/VfrCompile/Pccts/h/pccts_iostream.h new file mode 100644 index 0000000000..972b32cbd1 --- /dev/null +++ b/BaseTools/Source/C/VfrCompile/Pccts/h/pccts_iostream.h @@ -0,0 +1,10 @@ +#ifndef __PCCTS_IOSTREAM_H__ +#define __PCCTS_IOSTREAM_H__ + +#ifdef PCCTS_USE_NAMESPACE_STD +#include +#else +#include +#endif + +#endif diff --git a/BaseTools/Source/C/VfrCompile/Pccts/h/pccts_istream.h b/BaseTools/Source/C/VfrCompile/Pccts/h/pccts_istream.h new file mode 100644 index 0000000000..e25cb8c483 --- /dev/null +++ b/BaseTools/Source/C/VfrCompile/Pccts/h/pccts_istream.h @@ -0,0 +1,10 @@ +#ifndef __PCCTS_ISTREAM_H__ +#define __PCCTS_ISTREAM_H__ + +#ifdef PCCTS_USE_NAMESPACE_STD +#include +#else +#include +#endif + +#endif diff --git a/BaseTools/Source/C/VfrCompile/Pccts/h/pccts_setjmp.h b/BaseTools/Source/C/VfrCompile/Pccts/h/pccts_setjmp.h new file mode 100644 index 0000000000..9ea185ca73 --- /dev/null +++ b/BaseTools/Source/C/VfrCompile/Pccts/h/pccts_setjmp.h @@ -0,0 +1,10 @@ +#ifndef __PCCTS_SETJMP_H__ +#define __PCCTS_SETJMP_H__ + +#ifdef PCCTS_USE_NAMESPACE_STD +#include +#else +#include +#endif + +#endif diff --git a/BaseTools/Source/C/VfrCompile/Pccts/h/pccts_stdarg.h b/BaseTools/Source/C/VfrCompile/Pccts/h/pccts_stdarg.h new file mode 100644 index 0000000000..e957430c32 --- /dev/null +++ b/BaseTools/Source/C/VfrCompile/Pccts/h/pccts_stdarg.h @@ -0,0 +1,10 @@ +#ifndef __PCCTS_STDARG_H__ +#define __PCCTS_STDARG_H__ + +#ifdef PCCTS_USE_NAMESPACE_STD +#include +#else +#include +#endif + +#endif diff --git a/BaseTools/Source/C/VfrCompile/Pccts/h/pccts_stdio.h b/BaseTools/Source/C/VfrCompile/Pccts/h/pccts_stdio.h new file mode 100644 index 0000000000..ac34d1086d --- /dev/null +++ b/BaseTools/Source/C/VfrCompile/Pccts/h/pccts_stdio.h @@ -0,0 +1,10 @@ +#ifndef __PCCTS_STDIO_H__ +#define __PCCTS_STDIO_H__ + +#ifdef PCCTS_USE_NAMESPACE_STD +#include +#else +#include +#endif + +#endif diff --git a/BaseTools/Source/C/VfrCompile/Pccts/h/pccts_stdlib.h b/BaseTools/Source/C/VfrCompile/Pccts/h/pccts_stdlib.h new file mode 100644 index 0000000000..f0b344e8dc --- /dev/null +++ b/BaseTools/Source/C/VfrCompile/Pccts/h/pccts_stdlib.h @@ -0,0 +1,10 @@ +#ifndef __PCCTS_STDLIB_H__ +#define __PCCTS_STDLIB_H__ + +#ifdef PCCTS_USE_NAMESPACE_STD +#include +#else +#include +#endif + +#endif diff --git a/BaseTools/Source/C/VfrCompile/Pccts/h/pccts_string.h b/BaseTools/Source/C/VfrCompile/Pccts/h/pccts_string.h new file mode 100644 index 0000000000..458a08a94b --- /dev/null +++ b/BaseTools/Source/C/VfrCompile/Pccts/h/pccts_string.h @@ -0,0 +1,10 @@ +#ifndef __PCCTS_STRING_H__ +#define __PCCTS_STRING_H__ + +#ifdef PCCTS_USE_NAMESPACE_STD +#include +#else +#include +#endif + +#endif diff --git a/BaseTools/Source/C/VfrCompile/Pccts/h/pcctscfg.h b/BaseTools/Source/C/VfrCompile/Pccts/h/pcctscfg.h new file mode 100644 index 0000000000..0c3c5ba6fd --- /dev/null +++ b/BaseTools/Source/C/VfrCompile/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 +#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 +#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/BaseTools/Source/C/VfrCompile/Pccts/h/pcnames.bat b/BaseTools/Source/C/VfrCompile/Pccts/h/pcnames.bat new file mode 100644 index 0000000000..8784aee9ab --- /dev/null +++ b/BaseTools/Source/C/VfrCompile/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/BaseTools/Source/C/VfrCompile/Pccts/h/slist.cpp b/BaseTools/Source/C/VfrCompile/Pccts/h/slist.cpp new file mode 100644 index 0000000000..faf2fe4967 --- /dev/null +++ b/BaseTools/Source/C/VfrCompile/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/BaseTools/Source/C/VfrCompile/Pccts/history.ps b/BaseTools/Source/C/VfrCompile/Pccts/history.ps new file mode 100644 index 0000000000..e2600d5129 --- /dev/null +++ b/BaseTools/Source/C/VfrCompile/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/BaseTools/Source/C/VfrCompile/Pccts/history.txt b/BaseTools/Source/C/VfrCompile/Pccts/history.txt new file mode 100644 index 0000000000..89ad8408c9 --- /dev/null +++ b/BaseTools/Source/C/VfrCompile/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/BaseTools/Source/C/VfrCompile/Pccts/makefile.old b/BaseTools/Source/C/VfrCompile/Pccts/makefile.old new file mode 100644 index 0000000000..f9b2dd2b9b --- /dev/null +++ b/BaseTools/Source/C/VfrCompile/Pccts/makefile.old @@ -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/BaseTools/Source/C/VfrCompile/Pccts/support/genmk/genmk.c b/BaseTools/Source/C/VfrCompile/Pccts/support/genmk/genmk.c new file mode 100644 index 0000000000..4952a30b38 --- /dev/null +++ b/BaseTools/Source/C/VfrCompile/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 +#include +#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_sors0 ) { + 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; i0) { + 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;i0) + 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;i0) 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; i0) + { + 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;i0 ) + { + 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/BaseTools/Source/C/VfrCompile/Pccts/support/genmk/genmk_old.c b/BaseTools/Source/C/VfrCompile/Pccts/support/genmk/genmk_old.c new file mode 100644 index 0000000000..2cf9fad727 --- /dev/null +++ b/BaseTools/Source/C/VfrCompile/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 +#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_files0 ) { + 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; i0 ) + { + 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/BaseTools/Source/C/VfrCompile/Pccts/support/genmk/makefile b/BaseTools/Source/C/VfrCompile/Pccts/support/genmk/makefile new file mode 100644 index 0000000000..a003c2f321 --- /dev/null +++ b/BaseTools/Source/C/VfrCompile/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/BaseTools/Source/C/VfrCompile/Pccts/support/rexpr/makefile b/BaseTools/Source/C/VfrCompile/Pccts/support/rexpr/makefile new file mode 100644 index 0000000000..44caef1aa5 --- /dev/null +++ b/BaseTools/Source/C/VfrCompile/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/BaseTools/Source/C/VfrCompile/Pccts/support/rexpr/rexpr.c b/BaseTools/Source/C/VfrCompile/Pccts/support/rexpr/rexpr.c new file mode 100644 index 0000000000..805bf65533 --- /dev/null +++ b/BaseTools/Source/C/VfrCompile/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: + * + * ::= ( '|' )* + * + * ::= ( )* + * + * ::= {'~'} '[' ']' + * | '(' ')' + * | '{' '}' + * | + * + * ::= { '*' | '+' } + * + * ::= ( )* + * | { } '-' { } + * + * ::= 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 +#include +#ifdef __STDC__ +#include +#else +#include +#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; +} + +/* + * ::= ( '|' {} )* + * + * 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; +} + +/* + * ::= ( )* + */ + +#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; +} + +/* + * ::= {'~'} '[' ']' + * | '(' ')' + * | '{' '}' + * | + */ + +#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; +} + +/* + * ::= { '*' | '+' } + */ +#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; +} + +/* + * ::= { }* + * { } '-' { } + * + * 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/BaseTools/Source/C/VfrCompile/Pccts/support/rexpr/rexpr.h b/BaseTools/Source/C/VfrCompile/Pccts/support/rexpr/rexpr.h new file mode 100644 index 0000000000..e67a9652fb --- /dev/null +++ b/BaseTools/Source/C/VfrCompile/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/BaseTools/Source/C/VfrCompile/Pccts/support/rexpr/test.c b/BaseTools/Source/C/VfrCompile/Pccts/support/rexpr/test.c new file mode 100644 index 0000000000..2619539e4b --- /dev/null +++ b/BaseTools/Source/C/VfrCompile/Pccts/support/rexpr/test.c @@ -0,0 +1,19 @@ +#include +#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/BaseTools/Source/C/VfrCompile/Pccts/support/set/set.c b/BaseTools/Source/C/VfrCompile/Pccts/support/set/set.c new file mode 100644 index 0000000000..eb6fba7393 --- /dev/null +++ b/BaseTools/Source/C/VfrCompile/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 +#include "pcctscfg.h" +#ifdef __STDC__ +#include +#else +#include +#endif +#include + +#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 ) 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> 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/BaseTools/Source/C/VfrCompile/Pccts/support/sym/sym.c b/BaseTools/Source/C/VfrCompile/Pccts/support/sym/sym.c new file mode 100644 index 0000000000..eccce059bb --- /dev/null +++ b/BaseTools/Source/C/VfrCompile/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 + * #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 +#if defined(__STDC__) || defined(__USE_PROTOS) +#include +#include +#else +#include +#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/BaseTools/Source/C/VfrCompile/Pccts/support/sym/template.h b/BaseTools/Source/C/VfrCompile/Pccts/support/sym/template.h new file mode 100644 index 0000000000..ee6e665e34 --- /dev/null +++ b/BaseTools/Source/C/VfrCompile/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/BaseTools/Source/C/VfrCompile/VfrCompiler.cpp b/BaseTools/Source/C/VfrCompile/VfrCompiler.cpp new file mode 100644 index 0000000000..195727c2eb --- /dev/null +++ b/BaseTools/Source/C/VfrCompile/VfrCompiler.cpp @@ -0,0 +1,741 @@ +/** @file + + VfrCompiler main class and main function. + +Copyright (c) 2004 - 2008, 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. + +**/ + +#include "stdio.h" +#include "stdlib.h" +#include "string.h" +#include "VfrCompiler.h" +#include "CommonLib.h" +#include "EfiUtilityMsgs.h" + +PACKAGE_DATA gCBuffer; +PACKAGE_DATA gRBuffer; + +VOID +CVfrCompiler::DebugError () { + Error (NULL, 0, 0001, "Error parsing vfr file", " %s", mOptions.VfrFileName); + //_asm int 3; +} + +VOID +CVfrCompiler::SET_RUN_STATUS ( + IN COMPILER_RUN_STATUS Status + ) +{ + mRunStatus = Status; +} + +BOOLEAN +CVfrCompiler::IS_RUN_STATUS ( + IN COMPILER_RUN_STATUS Status + ) +{ + return mRunStatus == Status; +} + +VOID +CVfrCompiler::OptionInitialization ( + IN INT32 Argc, + IN CHAR8 **Argv + ) +{ + INT32 Index; + + SetUtilityName (PROGRAM_NAME); + + mOptions.VfrFileName[0] = '\0'; + mOptions.RecordListFile[0] = '\0'; + mOptions.CreateRecordListFile = FALSE; + mOptions.CreateIfrPkgFile = FALSE; + mOptions.PkgOutputFileName[0] = '\0'; + mOptions.COutputFileName[0] = '\0'; + mOptions.OutputDirectory[0] = '\0'; + mOptions.PreprocessorOutputFileName[0] = '\0'; + mOptions.VfrBaseFileName[0] = '\0'; + mOptions.IncludePaths = NULL; + mOptions.SkipCPreprocessor = TRUE; + mOptions.CPreprocessorOptions = NULL; + mOptions.CompatibleMode = FALSE; + + if (Argc == 1) { + Usage (); + SET_RUN_STATUS (STATUS_DEAD); + return; + } + + for (Index = 1; (Index < Argc) && (Argv[Index][0] == '-'); Index++) { + if ((stricmp(Argv[Index], "-h") == 0) || (stricmp(Argv[Index], "--help") == 0)) { + Usage (); + SET_RUN_STATUS (STATUS_DEAD); + return; + } else if (stricmp(Argv[Index], "-l") == 0) { + mOptions.CreateRecordListFile = TRUE; + gCIfrRecordInfoDB.TurnOn (); + } else if (stricmp(Argv[Index], "-i") == 0) { + Error (NULL, 0, 1000, "Unknown option", "unrecognized option %s", Argv[Index]); + goto Fail; + Index++; + if ((Index >= Argc) || (Argv[Index][0] == '-')) { + Error (NULL, 0, 1001, "Missing option", "-i missing path argument"); + goto Fail; + } + + AppendIncludePath(Argv[Index]); + } else if (stricmp(Argv[Index], "-o") == 0 || stricmp(Argv[Index], "--output-directory") == 0 || stricmp(Argv[Index], "-od") == 0) { + Index++; + if ((Index >= Argc) || (Argv[Index][0] == '-')) { + Error (NULL, 0, 1001, "Missing option", "-o missing output directory name"); + goto Fail; + } + strcpy (mOptions.OutputDirectory, Argv[Index]); + + CHAR8 lastChar = mOptions.OutputDirectory[strlen(mOptions.OutputDirectory) - 1]; + if ((lastChar != '/') && (lastChar != '\\')) { + if (strchr(mOptions.OutputDirectory, '/') != NULL) { + strcat (mOptions.OutputDirectory, "/"); + } else { + strcat (mOptions.OutputDirectory, "\\"); + } + } + DebugMsg (NULL, 0, 9, "Output Directory", mOptions.OutputDirectory); + } else if (stricmp(Argv[Index], "-b") == 0 || stricmp(Argv[Index], "--create-ifr-package") == 0 || stricmp(Argv[Index], "-ibin") == 0) { + mOptions.CreateIfrPkgFile = TRUE; + } else if (stricmp(Argv[Index], "-n") == 0 || stricmp(Argv[Index], "--no-pre-processing") == 0 || stricmp(Argv[Index], "-nopp") == 0) { + mOptions.SkipCPreprocessor = TRUE; + } else if (stricmp(Argv[Index], "-f") == 0 || stricmp(Argv[Index], "--pre-processing-flag") == 0 || stricmp(Argv[Index], "-ppflag") == 0) { + Error (NULL, 0, 1000, "Unknown option", "unrecognized option %s", Argv[Index]); + goto Fail; + Index++; + if ((Index >= Argc) || (Argv[Index][0] == '-')) { + Error (NULL, 0, 1001, "Missing option", "-od - missing C-preprocessor argument"); + goto Fail; + } + + AppendCPreprocessorOptions (Argv[Index]); + } else if (stricmp(Argv[Index], "-c") == 0 || stricmp(Argv[Index], "--compatible-framework") == 0) { + mOptions.CompatibleMode = TRUE; + } else { + Error (NULL, 0, 1000, "Unknown option", "unrecognized option %s", Argv[Index]); + goto Fail; + } + } + + if (Index != Argc - 1) { + Error (NULL, 0, 1001, "Missing option", "VFR file name is not specified."); + goto Fail; + } else { + strcpy (mOptions.VfrFileName, Argv[Index]); + } + + if (SetBaseFileName() != 0) { + goto Fail; + } + if (SetPkgOutputFileName () != 0) { + goto Fail; + } + if (SetCOutputFileName() != 0) { + goto Fail; + } + if (SetPreprocessorOutputFileName () != 0) { + goto Fail; + } + if (SetRecordListFileName () != 0) { + goto Fail; + } + return; + +Fail: + SET_RUN_STATUS (STATUS_DEAD); + + mOptions.VfrFileName[0] = '\0'; + mOptions.RecordListFile[0] = '\0'; + mOptions.CreateRecordListFile = FALSE; + mOptions.CreateIfrPkgFile = FALSE; + mOptions.PkgOutputFileName[0] = '\0'; + mOptions.COutputFileName[0] = '\0'; + mOptions.OutputDirectory[0] = '\0'; + mOptions.PreprocessorOutputFileName[0] = '\0'; + mOptions.VfrBaseFileName[0] = '\0'; + if (mOptions.IncludePaths != NULL) { + delete mOptions.IncludePaths; + mOptions.IncludePaths = NULL; + } + if (mOptions.CPreprocessorOptions != NULL) { + delete mOptions.CPreprocessorOptions; + mOptions.CPreprocessorOptions = NULL; + } +} + +VOID +CVfrCompiler::AppendIncludePath ( + IN CHAR8 *PathStr + ) +{ + UINT32 Len = 0; + CHAR8 *IncludePaths = NULL; + + Len = strlen (" -I ") + strlen (PathStr) + 1; + if (mOptions.IncludePaths != NULL) { + Len += strlen (mOptions.IncludePaths); + } + IncludePaths = new CHAR8[Len]; + if (IncludePaths == NULL) { + Error (NULL, 0, 4001, "Resource: memory can't be allocated", NULL); + return; + } + IncludePaths[0] = '\0'; + if (mOptions.IncludePaths != NULL) { + strcat (IncludePaths, mOptions.IncludePaths); + } + strcat (IncludePaths, " -I "); + strcat (IncludePaths, PathStr); + if (mOptions.IncludePaths != NULL) { + delete mOptions.IncludePaths; + } + mOptions.IncludePaths = IncludePaths; +} + +VOID +CVfrCompiler::AppendCPreprocessorOptions ( + IN CHAR8 *Options + ) +{ + UINT32 Len = 0; + CHAR8 *Opt = NULL; + + Len = strlen (Options) + strlen (" ") + 1; + if (mOptions.CPreprocessorOptions != NULL) { + Len += strlen (mOptions.CPreprocessorOptions); + } + Opt = new CHAR8[Len]; + if (Opt == NULL) { + Error (NULL, 0, 4001, "Resource: memory can't be allocated", NULL); + return; + } + Opt[0] = 0; + if (mOptions.CPreprocessorOptions != NULL) { + strcat (Opt, mOptions.CPreprocessorOptions); + } + strcat (Opt, " "); + strcat (Opt, Options); + if (mOptions.CPreprocessorOptions != NULL) { + delete mOptions.CPreprocessorOptions; + } + mOptions.CPreprocessorOptions = Opt; +} + +INT8 +CVfrCompiler::SetBaseFileName ( + VOID + ) +{ + CHAR8 *pFileName, *pPath, *pExt; + + if (mOptions.VfrFileName[0] == '\0') { + return -1; + } + + pFileName = mOptions.VfrFileName; + while ( + ((pPath = strchr (pFileName, '\\')) != NULL) || + ((pPath = strchr (pFileName, '/')) != NULL) + ) + { + pFileName = pPath + 1; + } + + if (pFileName == NULL) { + return -1; + } + + if ((pExt = strchr (pFileName, '.')) == NULL) { + return -1; + } + + strncpy (mOptions.VfrBaseFileName, pFileName, pExt - pFileName); + mOptions.VfrBaseFileName[pExt - pFileName] = '\0'; + + return 0; +} + +INT8 +CVfrCompiler::SetPkgOutputFileName ( + VOID + ) +{ + if (mOptions.VfrBaseFileName[0] == '\0') { + return -1; + } + + strcpy (mOptions.PkgOutputFileName, mOptions.OutputDirectory); + strcat (mOptions.PkgOutputFileName, mOptions.VfrBaseFileName); + strcat (mOptions.PkgOutputFileName, VFR_PACKAGE_FILENAME_EXTENSION); + + return 0; +} + +INT8 +CVfrCompiler::SetCOutputFileName ( + VOID + ) +{ + if (mOptions.VfrBaseFileName[0] == '\0') { + return -1; + } + + strcpy (mOptions.COutputFileName, mOptions.OutputDirectory); + strcat (mOptions.COutputFileName, mOptions.VfrBaseFileName); + strcat (mOptions.COutputFileName, ".c"); + + return 0; +} + +INT8 +CVfrCompiler::SetPreprocessorOutputFileName ( + VOID + ) +{ + if (mOptions.VfrBaseFileName[0] == '\0') { + return -1; + } + + strcpy (mOptions.PreprocessorOutputFileName, mOptions.OutputDirectory); + strcat (mOptions.PreprocessorOutputFileName, mOptions.VfrBaseFileName); + strcat (mOptions.PreprocessorOutputFileName, VFR_PREPROCESS_FILENAME_EXTENSION); + + return 0; +} + +INT8 +CVfrCompiler::SetRecordListFileName ( + VOID + ) +{ + if (mOptions.VfrBaseFileName[0] == '\0') { + return -1; + } + + strcpy (mOptions.RecordListFile, mOptions.OutputDirectory); + strcat (mOptions.RecordListFile, mOptions.VfrBaseFileName); + strcat (mOptions.RecordListFile, VFR_RECORDLIST_FILENAME_EXTENSION); + + return 0; +} + +CVfrCompiler::CVfrCompiler ( + IN INT32 Argc, + IN CHAR8 **Argv + ) +{ + mPreProcessCmd = PREPROCESSOR_COMMAND; + mPreProcessOpt = PREPROCESSOR_OPTIONS; + + OptionInitialization(Argc, Argv); + + if ((IS_RUN_STATUS(STATUS_FAILED)) || (IS_RUN_STATUS(STATUS_DEAD))) { + return; + } + + SET_RUN_STATUS(STATUS_INITIALIZED); +} + +CVfrCompiler::~CVfrCompiler ( + VOID + ) +{ + if (mOptions.IncludePaths != NULL) { + delete mOptions.IncludePaths; + mOptions.IncludePaths = NULL; + } + + if (mOptions.CPreprocessorOptions != NULL) { + delete mOptions.CPreprocessorOptions; + mOptions.CPreprocessorOptions = NULL; + } + + SET_RUN_STATUS(STATUS_DEAD); +} + +VOID +CVfrCompiler::Usage ( + VOID + ) +{ + UINT32 Index; + CONST CHAR8 *Help[] = { + " ", + "VfrCompile version " VFR_COMPILER_VERSION VFR_COMPILER_UPDATE_TIME, + " ", + "Usage: VfrCompile [options] VfrFile", + " ", + "Options:", + " -h, --help prints this help", + " -l create an output IFR listing file", + " -o DIR, --output-directory DIR", + " deposit all output files to directory OutputDir", + " default is current directory", + " -b, --create-ifr-package", + " create an IFR HII pack file", + " -n, --no-pre-processing", + " do not preprocessing input file", + " -c, --compatible-framework", + " compatible framework vfr file", + NULL + }; + for (Index = 0; Help[Index] != NULL; Index++) { + fprintf (stdout, "%s\n", Help[Index]); + } +} + +VOID +CVfrCompiler::PreProcess ( + VOID + ) +{ + FILE *pVfrFile = NULL; + UINT32 CmdLen = 0; + CHAR8 *PreProcessCmd = NULL; + + if (!IS_RUN_STATUS(STATUS_INITIALIZED)) { + goto Fail; + } + + if (mOptions.SkipCPreprocessor == TRUE) { + goto Out; + } + + if ((pVfrFile = fopen (mOptions.VfrFileName, "r")) == NULL) { + Error (NULL, 0, 0001, "Error opening the input VFR file", mOptions.VfrFileName); + goto Fail; + } + fclose (pVfrFile); + + CmdLen = strlen (mPreProcessCmd) + strlen (mPreProcessOpt) + + strlen (mOptions.VfrFileName) + strlen (mOptions.PreprocessorOutputFileName); + if (mOptions.CPreprocessorOptions != NULL) { + CmdLen += strlen (mOptions.CPreprocessorOptions); + } + if (mOptions.IncludePaths != NULL) { + CmdLen += strlen (mOptions.IncludePaths); + } + + PreProcessCmd = new CHAR8[CmdLen + 10]; + if (PreProcessCmd == NULL) { + Error (NULL, 0, 4001, "Resource: memory can't be allocated", NULL); + goto Fail; + } + strcpy (PreProcessCmd, mPreProcessCmd), strcat (PreProcessCmd, " "); + strcat (PreProcessCmd, mPreProcessOpt), strcat (PreProcessCmd, " "); + if (mOptions.IncludePaths != NULL) { + strcat (PreProcessCmd, mOptions.IncludePaths), strcat (PreProcessCmd, " "); + } + if (mOptions.CPreprocessorOptions != NULL) { + strcat (PreProcessCmd, mOptions.CPreprocessorOptions), strcat (PreProcessCmd, " "); + } + strcat (PreProcessCmd, mOptions.VfrFileName), strcat (PreProcessCmd, " > "); + strcat (PreProcessCmd, mOptions.PreprocessorOutputFileName); + + if (system (PreProcessCmd) != 0) { + Error (NULL, 0, 0003, "Error parsing file", "failed to spawn C preprocessor on VFR file %s\n", PreProcessCmd); + goto Fail; + } + + delete PreProcessCmd; + +Out: + SET_RUN_STATUS (STATUS_PREPROCESSED); + return; + +Fail: + if (!IS_RUN_STATUS(STATUS_DEAD)) { + SET_RUN_STATUS (STATUS_FAILED); + } + delete PreProcessCmd; +} + +extern UINT8 VfrParserStart (IN FILE *, IN BOOLEAN); + +VOID +CVfrCompiler::Compile ( + VOID + ) +{ + FILE *pInFile = NULL; + CHAR8 *InFileName = NULL; + + if (!IS_RUN_STATUS(STATUS_PREPROCESSED)) { + goto Fail; + } + + InFileName = (mOptions.SkipCPreprocessor == TRUE) ? mOptions.VfrFileName : mOptions.PreprocessorOutputFileName; + + gCVfrErrorHandle.SetInputFile (InFileName); + + if ((pInFile = fopen (InFileName, "r")) == NULL) { + Error (NULL, 0, 0001, "Error opening the input file", InFileName); + goto Fail; + } + + if (VfrParserStart (pInFile, mOptions.CompatibleMode) != 0) { + goto Fail; + } + + fclose (pInFile); + + if (gCFormPkg.HavePendingUnassigned () == TRUE) { + gCFormPkg.PendingAssignPrintAll (); + goto Fail; + } + + SET_RUN_STATUS (STATUS_COMPILEED); + return; + +Fail: + if (!IS_RUN_STATUS(STATUS_DEAD)) { + Error (NULL, 0, 0003, "Error parsing", "compile error in file %s", InFileName); + SET_RUN_STATUS (STATUS_FAILED); + } + if (pInFile != NULL) { + fclose (pInFile); + } +} + +VOID +CVfrCompiler::AdjustBin ( + VOID + ) +{ + EFI_VFR_RETURN_CODE Status; + // + // Check Binary Code consistent between Form and IfrRecord + // + + // + // Get Package Data and IfrRecord Data + // + gCFormPkg.BuildPkg (gCBuffer); + gCIfrRecordInfoDB.IfrRecordOutput (gRBuffer); + + // + // Compare Form and Record data + // + if (gCBuffer.Buffer != NULL && gRBuffer.Buffer != NULL) { + UINT32 Index; + if (gCBuffer.Size != gRBuffer.Size) { + Error (NULL, 0, 0001, "Error parsing vfr file", " %s. FormBinary Size 0x%X is not same to RecordBuffer Size 0x%X", mOptions.VfrFileName, gCBuffer.Size, gRBuffer.Size); + } + for (Index = 0; Index < gCBuffer.Size; Index ++) { + if (gCBuffer.Buffer[Index] != gRBuffer.Buffer[Index]) { + break; + } + } + if (Index != gCBuffer.Size) { + Error (NULL, 0, 0001, "Error parsing vfr file", " %s. the 0x%X byte is different between Form and Record", mOptions.VfrFileName, Index); + } + DebugMsg (NULL, 0, 9, "IFR Buffer", "Form Buffer same to Record Buffer and Size is 0x%X", Index); + } else if (gCBuffer.Buffer == NULL && gRBuffer.Buffer == NULL) { + //ok + } else { + Error (NULL, 0, 0001, "Error parsing vfr file", " %s.Buffer not allocated.", mOptions.VfrFileName); + } + + // + // For UEFI mode, not do OpCode Adjust + // + if (mOptions.CompatibleMode) { + // + // Adjust Opcode to be compatible with framework vfr + // + Status = gCIfrRecordInfoDB.IfrRecordAdjust (); + if (Status != VFR_RETURN_SUCCESS) { + // + // Record List Adjust Failed + // + SET_RUN_STATUS (STATUS_FAILED); + return; + } + // + // Re get the IfrRecord Buffer. + // + gCIfrRecordInfoDB.IfrRecordOutput (gRBuffer); + } + + return; +} + +VOID +CVfrCompiler::GenBinary ( + VOID + ) +{ + FILE *pFile = NULL; + + if (!IS_RUN_STATUS(STATUS_COMPILEED)) { + goto Fail; + } + + if (mOptions.CreateIfrPkgFile == TRUE) { + if ((pFile = fopen (mOptions.PkgOutputFileName, "wb")) == NULL) { + Error (NULL, 0, 0001, "Error opening file", mOptions.PkgOutputFileName); + goto Fail; + } + if (gCFormPkg.BuildPkg (pFile, &gRBuffer) != VFR_RETURN_SUCCESS) { + fclose (pFile); + goto Fail; + } + fclose (pFile); + } + + SET_RUN_STATUS (STATUS_GENBINARY); + + return; + +Fail: + if (!IS_RUN_STATUS(STATUS_DEAD)) { + SET_RUN_STATUS (STATUS_FAILED); + } +} + +static const char *gSourceFileHeader[] = { + "//", + "// DO NOT EDIT -- auto-generated file", + "//", + "// This file is generated by the vfrcompiler utility", + "//", + NULL +}; + +VOID +CVfrCompiler::GenCFile ( + VOID + ) +{ + FILE *pFile; + UINT32 Index; + + if (!IS_RUN_STATUS(STATUS_GENBINARY)) { + goto Fail; + } + + if ((pFile = fopen (mOptions.COutputFileName, "w")) == NULL) { + Error (NULL, 0, 0001, "Error opening output C file", mOptions.COutputFileName); + goto Fail; + } + + for (Index = 0; gSourceFileHeader[Index] != NULL; Index++) { + fprintf (pFile, "%s\n", gSourceFileHeader[Index]); + } + + gCVfrBufferConfig.OutputCFile (pFile, mOptions.VfrBaseFileName); + + if (gCFormPkg.GenCFile (mOptions.VfrBaseFileName, pFile, &gRBuffer) != VFR_RETURN_SUCCESS) { + fclose (pFile); + goto Fail; + } + fclose (pFile); + + SET_RUN_STATUS (STATUS_FINISHED); + return; + +Fail: + if (!IS_RUN_STATUS(STATUS_DEAD)) { + SET_RUN_STATUS (STATUS_FAILED); + } +} + +VOID +CVfrCompiler::GenRecordListFile ( + VOID + ) +{ + CHAR8 *InFileName = NULL; + FILE *pInFile = NULL; + FILE *pOutFile = NULL; + CHAR8 LineBuf[MAX_VFR_LINE_LEN]; + UINT32 LineNo; + + InFileName = (mOptions.SkipCPreprocessor == TRUE) ? mOptions.VfrFileName : mOptions.PreprocessorOutputFileName; + + if (mOptions.CreateRecordListFile == TRUE) { + if ((InFileName[0] == '\0') || (mOptions.RecordListFile[0] == '\0')) { + return; + } + + if ((pInFile = fopen (InFileName, "r")) == NULL) { + Error (NULL, 0, 0001, "Error opening the input VFR preprocessor output file", InFileName); + return; + } + + if ((pOutFile = fopen (mOptions.RecordListFile, "w")) == NULL) { + Error (NULL, 0, 0001, "Error opening the record list file", mOptions.RecordListFile); + goto Err1; + } + + fprintf (pOutFile, "//\n// VFR compiler version " VFR_COMPILER_VERSION "\n//\n"); + LineNo = 0; + while (!feof (pInFile)) { + if (fgets (LineBuf, MAX_VFR_LINE_LEN, pInFile) != NULL) { + fprintf (pOutFile, "%s", LineBuf); + LineNo++; + gCIfrRecordInfoDB.IfrRecordOutput (pOutFile, LineNo); + } + } + + fprintf (pOutFile, "\n//\n// All Opcode Record List \n//\n"); + gCIfrRecordInfoDB.IfrRecordOutput (pOutFile, 0); + gCVfrVarDataTypeDB.Dump(pOutFile); + + fclose (pOutFile); + fclose (pInFile); + } + + return; + +Err1: + fclose (pInFile); +} + +int +main ( + IN INT32 Argc, + IN CHAR8 **Argv + ) +{ + COMPILER_RUN_STATUS Status; + CVfrCompiler Compiler(Argc, Argv); + + Compiler.PreProcess(); + Compiler.Compile(); + Compiler.AdjustBin(); + Compiler.GenBinary(); + Compiler.GenCFile(); + Compiler.GenRecordListFile (); + + Status = Compiler.RunStatus (); + if ((Status == STATUS_DEAD) || (Status == STATUS_FAILED)) { + return 2; + } + + if (gCBuffer.Buffer != NULL) { + delete gCBuffer.Buffer; + } + + if (gRBuffer.Buffer != NULL) { + delete gRBuffer.Buffer; + } + + return GetUtilityStatus (); +} + diff --git a/BaseTools/Source/C/VfrCompile/VfrCompiler.h b/BaseTools/Source/C/VfrCompile/VfrCompiler.h new file mode 100644 index 0000000000..d3aa8ca56a --- /dev/null +++ b/BaseTools/Source/C/VfrCompile/VfrCompiler.h @@ -0,0 +1,108 @@ +/** @file + + VfrCompiler internal defintions. + +Copyright (c) 2004 - 2008, 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. + +**/ + +#ifndef _VFRCOMPILER_H_ +#define _VFRCOMPILER_H_ + +#include "Common/UefiBaseTypes.h" +#include "EfiVfr.h" +#include "VfrFormPkg.h" +#include "VfrUtilityLib.h" + +#define PROGRAM_NAME "VfrCompile" +#define VFR_COMPILER_VERSION " 1.95 (UEFI 2.1)" +#define VFR_COMPILER_UPDATE_TIME " updated on 2009/05/20" +// +// 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. +// +#define PREPROCESSOR_COMMAND "cl " +#define PREPROCESSOR_OPTIONS "/nologo /E /TC /DVFRCOMPILE " + +// +// Specify the filename extensions for the files we generate. +// +#define VFR_PREPROCESS_FILENAME_EXTENSION ".i" +#define VFR_PACKAGE_FILENAME_EXTENSION ".hpk" +#define VFR_RECORDLIST_FILENAME_EXTENSION ".lst" + +typedef struct { + CHAR8 VfrFileName[MAX_PATH]; + CHAR8 RecordListFile[MAX_PATH]; + CHAR8 PkgOutputFileName[MAX_PATH]; + CHAR8 COutputFileName[MAX_PATH]; + bool CreateRecordListFile; + bool CreateIfrPkgFile; + CHAR8 OutputDirectory[MAX_PATH]; + CHAR8 PreprocessorOutputFileName[MAX_PATH]; + CHAR8 VfrBaseFileName[MAX_PATH]; // name of input VFR file with no path or extension + CHAR8 *IncludePaths; + bool SkipCPreprocessor; + CHAR8 *CPreprocessorOptions; + BOOLEAN CompatibleMode; +} OPTIONS; + +typedef enum { + STATUS_INITIALIZED = 1, + STATUS_PREPROCESSED, + STATUS_COMPILEED, + STATUS_GENBINARY, + STATUS_FINISHED, + STATUS_FAILED, + STATUS_DEAD, +} COMPILER_RUN_STATUS; + +class CVfrCompiler { +private: + COMPILER_RUN_STATUS mRunStatus; + OPTIONS mOptions; + CHAR8 *mPreProcessCmd; + CHAR8 *mPreProcessOpt; + + VOID OptionInitialization (IN INT32 , IN CHAR8 **); + VOID AppendIncludePath (IN CHAR8 *); + VOID AppendCPreprocessorOptions (IN CHAR8 *); + INT8 SetBaseFileName (VOID); + INT8 SetPkgOutputFileName (VOID); + INT8 SetCOutputFileName(VOID); + INT8 SetPreprocessorOutputFileName (VOID); + INT8 SetRecordListFileName (VOID); + + VOID SET_RUN_STATUS (IN COMPILER_RUN_STATUS); + BOOLEAN IS_RUN_STATUS (IN COMPILER_RUN_STATUS); + +public: + COMPILER_RUN_STATUS RunStatus (VOID) { + return mRunStatus; + } + +public: + CVfrCompiler (IN INT32 , IN CHAR8 **); + ~CVfrCompiler (); + + VOID Usage (VOID); + + VOID PreProcess (VOID); + VOID Compile (VOID); + VOID AdjustBin (VOID); + VOID GenBinary (VOID); + VOID GenCFile (VOID); + VOID GenRecordListFile (VOID); + VOID DebugError (VOID); +}; + +#endif diff --git a/BaseTools/Source/C/VfrCompile/VfrError.cpp b/BaseTools/Source/C/VfrCompile/VfrError.cpp new file mode 100644 index 0000000000..b24cc725f0 --- /dev/null +++ b/BaseTools/Source/C/VfrCompile/VfrError.cpp @@ -0,0 +1,241 @@ +/** @file + + VfrCompiler error handler. + +Copyright (c) 2004 - 2008, 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. + +**/ + +#include "stdio.h" +#include "string.h" +#include "stdlib.h" +#include "VfrError.h" +#include "EfiUtilityMsgs.h" + +static SVFR_ERROR_HANDLE VFR_ERROR_HANDLE_TABLE [] = { + { VFR_RETURN_SUCCESS, NULL }, + { VFR_RETURN_ERROR_SKIPED, NULL }, + { VFR_RETURN_FATAL_ERROR, ": fatal error!!" }, + + { VFR_RETURN_MISMATCHED, ": unexpected token" }, + { VFR_RETURN_INVALID_PARAMETER, ": invalid parameter" }, + { VFR_RETURN_OUT_FOR_RESOURCES, ": system out of memory" }, + { VFR_RETURN_UNSUPPORTED, ": unsupported" }, + { VFR_RETURN_REDEFINED, ": already defined" }, + { VFR_RETURN_FORMID_REDEFINED, ": form id already defined" }, + { VFR_RETURN_QUESTIONID_REDEFINED, ": question id already defined" }, + { VFR_RETURN_VARSTOREID_REDEFINED, ": varstore id already defined" }, + { VFR_RETURN_UNDEFINED, ": undefined" }, + { VFR_RETURN_VAR_NOTDEFINED_BY_QUESTION, ": some variable has not defined by a question"}, + { VFR_RETURN_GET_EFIVARSTORE_ERROR, ": get efi varstore error"}, + { VFR_RETURN_EFIVARSTORE_USE_ERROR, ": can not use the efi varstore like this" }, + { VFR_RETURN_EFIVARSTORE_SIZE_ERROR, ": unsupport efi varstore size should be <= 8 bytes" }, + { VFR_RETURN_GET_NVVARSTORE_ERROR, ": get name value varstore error" }, + { VFR_RETURN_QVAR_REUSE, ": variable reused by more than one question" }, + { VFR_RETURN_FLAGS_UNSUPPORTED, ": flags unsupported" }, + { VFR_RETURN_ERROR_ARRARY_NUM, ": array number error, the valid value is in (0 ~ MAX_INDEX-1) for UEFI vfr and in (1 ~ MAX_INDEX) for Framework Vfr" }, + { VFR_RETURN_DATA_STRING_ERROR, ": data field string error or not support"}, + { VFR_RETURN_DEFAULT_VALUE_REDEFINED, ": default value re-defined with different value"}, + { VFR_RETURN_CONSTANT_ONLY, ": only constant is allowed in the expression"}, + { VFR_RETURN_CODEUNDEFINED, ": undefined Error Code" } +}; + +CVfrErrorHandle::CVfrErrorHandle ( + VOID + ) +{ + mInputFileName = NULL; + mScopeRecordListHead = NULL; + mScopeRecordListTail = NULL; + mVfrErrorHandleTable = VFR_ERROR_HANDLE_TABLE; +} + +CVfrErrorHandle::~CVfrErrorHandle ( + VOID + ) +{ + SVfrFileScopeRecord *pNode = NULL; + + if (mInputFileName != NULL) { + delete mInputFileName; + } + + while (mScopeRecordListHead != NULL) { + pNode = mScopeRecordListHead; + mScopeRecordListHead = mScopeRecordListHead->mNext; + delete pNode; + } + + mScopeRecordListHead = NULL; + mScopeRecordListTail = NULL; + mVfrErrorHandleTable = NULL; +} + +VOID +CVfrErrorHandle::SetInputFile ( + IN CHAR8 *InputFile + ) +{ + if (InputFile != NULL) { + mInputFileName = new CHAR8[strlen(InputFile) + 1]; + strcpy (mInputFileName, InputFile); + } +} + +SVfrFileScopeRecord::SVfrFileScopeRecord ( + IN CHAR8 *Record, + IN UINT32 LineNum + ) +{ + UINT32 Index; + CHAR8 *FileName = NULL; + CHAR8 *Str = NULL; + + mWholeScopeLine = LineNum; + mNext = NULL; + + Str = strchr (Record, ' '); + mScopeLineStart = atoi (++Str); + + Str = strchr (Str, '\"'); + FileName = ++Str; + + while((Str = strstr (FileName, "\\\\")) != NULL) { + FileName = Str + 2; + } + if ((mFileName = new CHAR8[strlen(FileName)]) != NULL) { + for (Index = 0; FileName[Index] != '\"'; Index++) { + mFileName[Index] = FileName[Index]; + } + mFileName[Index] = '\0'; + } + + return; +} + +SVfrFileScopeRecord::~SVfrFileScopeRecord ( + VOID + ) +{ + if (mFileName != NULL) { + delete mFileName; + } +} + +VOID +CVfrErrorHandle::ParseFileScopeRecord ( + IN CHAR8 *Record, + IN UINT32 WholeScopeLine + ) +{ + CHAR8 *FullPathName = NULL; + SVfrFileScopeRecord *pNode = NULL; + + if (Record == NULL) { + return; + } + + if ((pNode = new SVfrFileScopeRecord(Record, WholeScopeLine)) == NULL) { + return; + } + + if (mScopeRecordListHead == NULL) { + mScopeRecordListTail = mScopeRecordListHead = pNode; + } else { + mScopeRecordListTail->mNext = pNode; + mScopeRecordListTail = pNode; + } +} + +VOID +CVfrErrorHandle::GetFileNameLineNum ( + IN UINT32 LineNum, + OUT CHAR8 **FileName, + OUT UINT32 *FileLine + ) +{ + SVfrFileScopeRecord *pNode = NULL; + + if ((FileName == NULL) || (FileLine == NULL)) { + return; + } + + *FileName = NULL; + *FileLine = 0xFFFFFFFF; + + // + // Some errors occur before scope record list been built. + // + if (mScopeRecordListHead == NULL) { + *FileLine = LineNum; + *FileName = mInputFileName; + return ; + } + + for (pNode = mScopeRecordListHead; pNode->mNext != NULL; pNode = pNode->mNext) { + if ((LineNum > pNode->mWholeScopeLine) && (pNode->mNext->mWholeScopeLine > LineNum)) { + *FileName = pNode->mFileName; + *FileLine = LineNum - pNode->mWholeScopeLine + pNode->mScopeLineStart - 1; + return ; + } + } + + *FileName = pNode->mFileName; + *FileLine = LineNum - pNode->mWholeScopeLine + pNode->mScopeLineStart - 1; +} + +VOID +CVfrErrorHandle::PrintMsg ( + IN UINT32 LineNum, + IN CHAR8 *TokName, + IN CHAR8 *MsgType, + IN CHAR8 *ErrorMsg + ) +{ + CHAR8 *FileName = NULL; + UINT32 FileLine; + + GetFileNameLineNum (LineNum, &FileName, &FileLine); + Error (FileName, FileLine, 0x3000, TokName, "\t%s\n", ErrorMsg); +} + +UINT8 +CVfrErrorHandle::HandleError ( + IN EFI_VFR_RETURN_CODE ErrorCode, + IN UINT32 LineNum, + IN CHAR8 *TokName + ) +{ + UINT32 Index; + CHAR8 *FileName = NULL; + UINT32 FileLine; + CHAR8 *ErrorMsg = NULL; + + if (mVfrErrorHandleTable == NULL) { + return 1; + } + + for (Index = 0; mVfrErrorHandleTable[Index].mErrorCode != VFR_RETURN_CODEUNDEFINED; Index++) { + if (ErrorCode == mVfrErrorHandleTable[Index].mErrorCode) { + ErrorMsg = mVfrErrorHandleTable[Index].mErrorMsg; + break; + } + } + + if (ErrorMsg != NULL) { + GetFileNameLineNum (LineNum, &FileName, &FileLine); + Error (FileName, FileLine, 0x3000, TokName, "\t%s\n", ErrorMsg); + return 1; + } else { + return 0; + } +} + +CVfrErrorHandle gCVfrErrorHandle; diff --git a/BaseTools/Source/C/VfrCompile/VfrError.h b/BaseTools/Source/C/VfrCompile/VfrError.h new file mode 100644 index 0000000000..500926af6a --- /dev/null +++ b/BaseTools/Source/C/VfrCompile/VfrError.h @@ -0,0 +1,85 @@ +/** @file + + VfrCompiler Error definition + +Copyright (c) 2004 - 2008, 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. + +**/ + +#ifndef _VFRERROR_H_ +#define _VFRERROR_H_ + +#include "Common/UefiBaseTypes.h" + +typedef enum { + VFR_RETURN_SUCCESS = 0, + VFR_RETURN_ERROR_SKIPED, + VFR_RETURN_FATAL_ERROR, + VFR_RETURN_MISMATCHED, + VFR_RETURN_INVALID_PARAMETER, + VFR_RETURN_OUT_FOR_RESOURCES, + VFR_RETURN_UNSUPPORTED, + VFR_RETURN_REDEFINED, + VFR_RETURN_FORMID_REDEFINED, + VFR_RETURN_QUESTIONID_REDEFINED, + VFR_RETURN_VARSTOREID_REDEFINED, + VFR_RETURN_UNDEFINED, + VFR_RETURN_VAR_NOTDEFINED_BY_QUESTION, + VFR_RETURN_GET_EFIVARSTORE_ERROR, + VFR_RETURN_EFIVARSTORE_USE_ERROR, + VFR_RETURN_EFIVARSTORE_SIZE_ERROR, + VFR_RETURN_GET_NVVARSTORE_ERROR, + VFR_RETURN_QVAR_REUSE, + VFR_RETURN_FLAGS_UNSUPPORTED, + VFR_RETURN_ERROR_ARRARY_NUM, + VFR_RETURN_DATA_STRING_ERROR, + VFR_RETURN_DEFAULT_VALUE_REDEFINED, + VFR_RETURN_CONSTANT_ONLY, + VFR_RETURN_CODEUNDEFINED +} EFI_VFR_RETURN_CODE; + +typedef struct _SVFR_ERROR_HANDLE { + EFI_VFR_RETURN_CODE mErrorCode; + CHAR8 *mErrorMsg; +} SVFR_ERROR_HANDLE; + +struct SVfrFileScopeRecord { + CHAR8 *mFileName; + UINT32 mWholeScopeLine; + UINT32 mScopeLineStart; + SVfrFileScopeRecord *mNext; + + SVfrFileScopeRecord (IN CHAR8 *, IN UINT32); + ~SVfrFileScopeRecord(); +}; + +class CVfrErrorHandle { +private: + CHAR8 *mInputFileName; + SVFR_ERROR_HANDLE *mVfrErrorHandleTable; + SVfrFileScopeRecord *mScopeRecordListHead; + SVfrFileScopeRecord *mScopeRecordListTail; + +public: + CVfrErrorHandle (VOID); + ~CVfrErrorHandle (VOID); + + VOID SetInputFile (IN CHAR8 *); + VOID ParseFileScopeRecord (IN CHAR8 *, IN UINT32); + VOID GetFileNameLineNum (IN UINT32, OUT CHAR8 **, OUT UINT32 *); + UINT8 HandleError (IN EFI_VFR_RETURN_CODE, IN UINT32 LineNum = 0, IN CHAR8 *TokName = "\0"); + VOID PrintMsg (IN UINT32 LineNum = 0, IN CHAR8 *TokName = "\0", IN CHAR8 *MsgType = "Error", IN CHAR8 *ErrorMsg = "\0"); +}; + +#define CHECK_ERROR_RETURN(f, v) do { EFI_VFR_RETURN_CODE r; if ((r = (f)) != (v)) { return r; } } while (0) + +extern CVfrErrorHandle gCVfrErrorHandle; + +#endif diff --git a/BaseTools/Source/C/VfrCompile/VfrFormPkg.cpp b/BaseTools/Source/C/VfrCompile/VfrFormPkg.cpp new file mode 100644 index 0000000000..654daed549 --- /dev/null +++ b/BaseTools/Source/C/VfrCompile/VfrFormPkg.cpp @@ -0,0 +1,1386 @@ +/** @file + + The definition of CFormPkg's member function + +Copyright (c) 2004 - 2008, 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. + +**/ + +#include "stdio.h" +#include "VfrFormPkg.h" + +/* + * The definition of CFormPkg's member function + */ + +SPendingAssign::SPendingAssign ( + IN CHAR8 *Key, + IN VOID *Addr, + IN UINT32 Len, + IN UINT32 LineNo, + IN CHAR8 *Msg + ) +{ + mKey = NULL; + mAddr = Addr; + mLen = Len; + mFlag = PENDING; + mLineNo = LineNo; + mMsg = NULL; + mNext = NULL; + if (Key != NULL) { + mKey = new CHAR8[strlen (Key) + 1]; + if (mKey != NULL) { + strcpy (mKey, Key); + } + } + + if (Msg != NULL) { + mMsg = new CHAR8[strlen (Msg) + 1]; + if (mMsg != NULL) { + strcpy (mMsg, Msg); + } + } +} + +SPendingAssign::~SPendingAssign ( + VOID + ) +{ + if (mKey != NULL) { + delete mKey; + } + mAddr = NULL; + mLen = 0; + mLineNo = 0; + if (mMsg != NULL) { + delete mMsg; + } + mNext = NULL; +} + +VOID +SPendingAssign::SetAddrAndLen ( + IN VOID *Addr, + IN UINT32 LineNo + ) +{ + mAddr = Addr; + mLineNo = LineNo; +} + +VOID +SPendingAssign::AssignValue ( + IN VOID *Addr, + IN UINT32 Len + ) +{ + memcpy (mAddr, Addr, (mLen < Len ? mLen : Len)); + mFlag = ASSIGNED; +} + +CHAR8 * +SPendingAssign::GetKey ( + VOID + ) +{ + return mKey; +} + +CFormPkg::CFormPkg ( + IN UINT32 BufferSize = 4096 + ) +{ + CHAR8 *BufferStart; + CHAR8 *BufferEnd; + SBufferNode *Node; + + mPkgLength = 0; + mBufferNodeQueueHead = NULL; + mCurrBufferNode = NULL; + + Node = new SBufferNode; + if (Node == NULL) { + return ; + } + BufferStart = new CHAR8[BufferSize]; + if (BufferStart == NULL) { + return; + } + BufferEnd = BufferStart + BufferSize; + + memset (BufferStart, 0, BufferSize); + Node->mBufferStart = BufferStart; + Node->mBufferEnd = BufferEnd; + Node->mBufferFree = BufferStart; + Node->mNext = NULL; + + mBufferSize = BufferSize; + mBufferNodeQueueHead = Node; + mBufferNodeQueueTail = Node; + mCurrBufferNode = Node; +} + +CFormPkg::~CFormPkg () +{ + SBufferNode *pBNode; + SPendingAssign *pPNode; + + while (mBufferNodeQueueHead != NULL) { + pBNode = mBufferNodeQueueHead; + mBufferNodeQueueHead = mBufferNodeQueueHead->mNext; + if (pBNode->mBufferStart != NULL) { + delete pBNode->mBufferStart; + delete pBNode; + } + } + mBufferNodeQueueTail = NULL; + mCurrBufferNode = NULL; + + while (PendingAssignList != NULL) { + pPNode = PendingAssignList; + PendingAssignList = PendingAssignList->mNext; + delete pPNode; + } + PendingAssignList = NULL; +} + +CHAR8 * +CFormPkg::IfrBinBufferGet ( + IN UINT32 Len + ) +{ + CHAR8 *BinBuffer = NULL; + + if ((Len == 0) || (Len > mBufferSize)) { + return NULL; + } + + if ((mCurrBufferNode->mBufferFree + Len) <= mCurrBufferNode->mBufferEnd) { + BinBuffer = mCurrBufferNode->mBufferFree; + mCurrBufferNode->mBufferFree += Len; + } else { + SBufferNode *Node; + + Node = new SBufferNode; + if (Node == NULL) { + return NULL; + } + + Node->mBufferStart = new CHAR8[mBufferSize]; + if (Node->mBufferStart == NULL) { + delete Node; + return NULL; + } else { + memset (Node->mBufferStart, 0, mBufferSize); + Node->mBufferEnd = Node->mBufferStart + mBufferSize; + Node->mBufferFree = Node->mBufferStart; + Node->mNext = NULL; + } + + if (mBufferNodeQueueTail == NULL) { + mBufferNodeQueueHead = mBufferNodeQueueTail = Node; + } else { + mBufferNodeQueueTail->mNext = Node; + mBufferNodeQueueTail = Node; + } + mCurrBufferNode = Node; + + // + // Now try again. + // + BinBuffer = mCurrBufferNode->mBufferFree; + mCurrBufferNode->mBufferFree += Len; + } + + mPkgLength += Len; + + return BinBuffer; +} + +inline +UINT32 +CFormPkg::GetPkgLength ( + VOID + ) +{ + return mPkgLength; +} + +VOID +CFormPkg::Open ( + VOID + ) +{ + mReadBufferNode = mBufferNodeQueueHead; + mReadBufferOffset = 0; +} + +VOID +CFormPkg::Close ( + VOID + ) +{ + mReadBufferNode = NULL; + mReadBufferOffset = 0; +} + +UINT32 +CFormPkg::Read ( + IN CHAR8 *Buffer, + IN UINT32 Size + ) +{ + UINT32 Index; + + if ((Size == 0) || (Buffer == NULL)) { + return 0; + } + + if (mReadBufferNode == NULL) { + return 0; + } + + for (Index = 0; Index < Size; Index++) { + if ((mReadBufferNode->mBufferStart + mReadBufferOffset) < mReadBufferNode->mBufferFree) { + Buffer[Index] = mReadBufferNode->mBufferStart[mReadBufferOffset++]; + } else { + if ((mReadBufferNode = mReadBufferNode->mNext) == NULL) { + return Index; + } else { + mReadBufferOffset = 0; + Buffer[Index] = mReadBufferNode->mBufferStart[mReadBufferOffset++]; + } + } + } + + return Size; +} + +EFI_VFR_RETURN_CODE +CFormPkg::BuildPkgHdr ( + OUT EFI_HII_PACKAGE_HEADER **PkgHdr + ) +{ + if (PkgHdr == NULL) { + return VFR_RETURN_FATAL_ERROR; + } + + if (((*PkgHdr) = new EFI_HII_PACKAGE_HEADER) == NULL) { + return VFR_RETURN_OUT_FOR_RESOURCES; + } + + (*PkgHdr)->Type = EFI_HII_PACKAGE_FORM; + (*PkgHdr)->Length = mPkgLength + sizeof (EFI_HII_PACKAGE_HEADER); + + return VFR_RETURN_SUCCESS; +} + +EFI_VFR_RETURN_CODE +CFormPkg::BuildPkg ( + OUT PACKAGE_DATA &TBuffer + ) +{ + + CHAR8 *Temp; + UINT32 Size; + CHAR8 Buffer[1024]; + + if (TBuffer.Buffer != NULL) { + delete TBuffer.Buffer; + } + + TBuffer.Size = mPkgLength; + TBuffer.Buffer = NULL; + if (TBuffer.Size != 0) { + TBuffer.Buffer = new CHAR8[TBuffer.Size]; + } else { + return VFR_RETURN_SUCCESS; + } + + Temp = TBuffer.Buffer; + Open (); + while ((Size = Read (Buffer, 1024)) != 0) { + memcpy (Temp, Buffer, Size); + Temp += Size; + } + Close (); + return VFR_RETURN_SUCCESS; +} + + +EFI_VFR_RETURN_CODE +CFormPkg::BuildPkg ( + IN FILE *Output, + IN PACKAGE_DATA *PkgData + ) +{ + EFI_VFR_RETURN_CODE Ret; + CHAR8 Buffer[1024]; + UINT32 Size; + EFI_HII_PACKAGE_HEADER *PkgHdr; + + if (Output == NULL) { + return VFR_RETURN_FATAL_ERROR; + } + + if ((Ret = BuildPkgHdr(&PkgHdr)) != VFR_RETURN_SUCCESS) { + return Ret; + } + fwrite (PkgHdr, sizeof (EFI_HII_PACKAGE_HEADER), 1, Output); + delete PkgHdr; + + if (PkgData == NULL) { + Open (); + while ((Size = Read (Buffer, 1024)) != 0) { + fwrite (Buffer, Size, 1, Output); + } + Close (); + } else { + fwrite (PkgData->Buffer, PkgData->Size, 1, Output); + } + + return VFR_RETURN_SUCCESS; +} + +VOID +CFormPkg::_WRITE_PKG_LINE ( + IN FILE *pFile, + IN UINT32 LineBytes, + IN CHAR8 *LineHeader, + IN CHAR8 *BlkBuf, + IN UINT32 BlkSize + ) +{ + UINT32 Index; + + if ((pFile == NULL) || (LineHeader == NULL) || (BlkBuf == NULL)) { + return; + } + + for (Index = 0; Index < BlkSize; Index++) { + if ((Index % LineBytes) == 0) { + fprintf (pFile, "\n%s", LineHeader); + } + fprintf (pFile, "0x%02X, ", (UINT8)BlkBuf[Index]); + } +} + +VOID +CFormPkg::_WRITE_PKG_END ( + IN FILE *pFile, + IN UINT32 LineBytes, + IN CHAR8 *LineHeader, + IN CHAR8 *BlkBuf, + IN UINT32 BlkSize + ) +{ + UINT32 Index; + + if ((BlkSize == 0) || (pFile == NULL) || (LineHeader == NULL) || (BlkBuf == NULL)) { + return; + } + + for (Index = 0; Index < BlkSize - 1; Index++) { + if ((Index % LineBytes) == 0) { + fprintf (pFile, "\n%s", LineHeader); + } + fprintf (pFile, "0x%02X, ", (UINT8)BlkBuf[Index]); + } + + if ((Index % LineBytes) == 0) { + fprintf (pFile, "\n%s", LineHeader); + } + fprintf (pFile, "0x%02X\n", (UINT8)BlkBuf[Index]); +} + +#define BYTES_PRE_LINE 0x10 + +EFI_VFR_RETURN_CODE +CFormPkg::GenCFile ( + IN CHAR8 *BaseName, + IN FILE *pFile, + IN PACKAGE_DATA *PkgData + ) +{ + EFI_VFR_RETURN_CODE Ret; + CHAR8 Buffer[BYTES_PRE_LINE * 8]; + EFI_HII_PACKAGE_HEADER *PkgHdr; + UINT32 PkgLength = 0; + UINT32 ReadSize = 0; + + if ((BaseName == NULL) || (pFile == NULL)) { + return VFR_RETURN_FATAL_ERROR; + } + + fprintf (pFile, "\nunsigned char %sBin[] = {\n", BaseName); + + if ((Ret = BuildPkgHdr(&PkgHdr)) != VFR_RETURN_SUCCESS) { + return Ret; + } + + // + // For framework vfr file, the extension framework header will be added. + // + if (VfrCompatibleMode) { + fprintf (pFile, " // FRAMEWORK PACKAGE HEADER Length\n"); + PkgLength = PkgHdr->Length + sizeof (UINT32) + 2; + _WRITE_PKG_LINE(pFile, BYTES_PRE_LINE, " ", (CHAR8 *)&PkgLength, sizeof (UINT32)); + fprintf (pFile, "\n\n // FRAMEWORK PACKAGE HEADER Type\n"); + PkgLength = 3; + _WRITE_PKG_LINE(pFile, BYTES_PRE_LINE, " ", (CHAR8 *)&PkgLength, sizeof (UINT16)); + } else { + fprintf (pFile, " // ARRAY LENGTH\n"); + PkgLength = PkgHdr->Length + sizeof (UINT32); + _WRITE_PKG_LINE(pFile, BYTES_PRE_LINE, " ", (CHAR8 *)&PkgLength, sizeof (UINT32)); + } + + fprintf (pFile, "\n\n // PACKAGE HEADER\n"); + _WRITE_PKG_LINE(pFile, BYTES_PRE_LINE, " ", (CHAR8 *)PkgHdr, sizeof (EFI_HII_PACKAGE_HEADER)); + PkgLength = sizeof (EFI_HII_PACKAGE_HEADER); + + fprintf (pFile, "\n\n // PACKAGE DATA\n"); + + if (PkgData == NULL) { + Open (); + while ((ReadSize = Read ((CHAR8 *)Buffer, BYTES_PRE_LINE * 8)) != 0) { + PkgLength += ReadSize; + if (PkgLength < PkgHdr->Length) { + _WRITE_PKG_LINE (pFile, BYTES_PRE_LINE, " ", Buffer, ReadSize); + } else { + _WRITE_PKG_END (pFile, BYTES_PRE_LINE, " ", Buffer, ReadSize); + } + } + Close (); + } else { + if (PkgData->Size % BYTES_PRE_LINE != 0) { + PkgLength = PkgData->Size - (PkgData->Size % BYTES_PRE_LINE); + _WRITE_PKG_LINE (pFile, BYTES_PRE_LINE, " ", PkgData->Buffer, PkgLength); + _WRITE_PKG_END (pFile, BYTES_PRE_LINE, " ", PkgData->Buffer + PkgLength, PkgData->Size % BYTES_PRE_LINE); + } else { + PkgLength = PkgData->Size - BYTES_PRE_LINE; + _WRITE_PKG_LINE (pFile, BYTES_PRE_LINE, " ", PkgData->Buffer, PkgLength); + _WRITE_PKG_END (pFile, BYTES_PRE_LINE, " ", PkgData->Buffer + PkgLength, BYTES_PRE_LINE); + } + } + + delete PkgHdr; + fprintf (pFile, "\n};\n"); + + return VFR_RETURN_SUCCESS; +} + +EFI_VFR_RETURN_CODE +CFormPkg::AssignPending ( + IN CHAR8 *Key, + IN VOID *ValAddr, + IN UINT32 ValLen, + IN UINT32 LineNo, + IN CHAR8 *Msg + ) +{ + SPendingAssign *pNew; + + pNew = new SPendingAssign (Key, ValAddr, ValLen, LineNo, Msg); + if (pNew == NULL) { + return VFR_RETURN_OUT_FOR_RESOURCES; + } + + pNew->mNext = PendingAssignList; + PendingAssignList = pNew; + return VFR_RETURN_SUCCESS; +} + +VOID +CFormPkg::DoPendingAssign ( + IN CHAR8 *Key, + IN VOID *ValAddr, + IN UINT32 ValLen + ) +{ + SPendingAssign *pNode; + + if ((Key == NULL) || (ValAddr == NULL)) { + return; + } + + for (pNode = PendingAssignList; pNode != NULL; pNode = pNode->mNext) { + if (strcmp (pNode->mKey, Key) == 0) { + pNode->AssignValue (ValAddr, ValLen); + } + } +} + +bool +CFormPkg::HavePendingUnassigned ( + VOID + ) +{ + SPendingAssign *pNode; + + for (pNode = PendingAssignList; pNode != NULL; pNode = pNode->mNext) { + if (pNode->mFlag == PENDING) { + return TRUE; + } + } + + return FALSE; +} + +VOID +CFormPkg::PendingAssignPrintAll ( + VOID + ) +{ + SPendingAssign *pNode; + + for (pNode = PendingAssignList; pNode != NULL; pNode = pNode->mNext) { + if (pNode->mFlag == PENDING) { + gCVfrErrorHandle.PrintMsg (pNode->mLineNo, pNode->mKey, "Error", pNode->mMsg); + } + } +} + +EFI_VFR_RETURN_CODE +CFormPkg::DeclarePendingQuestion ( + IN CVfrVarDataTypeDB &lCVfrVarDataTypeDB, + IN CVfrDataStorage &lCVfrDataStorage, + IN CVfrQuestionDB &lCVfrQuestionDB, + IN EFI_GUID *LocalFormSetGuid, + IN UINT32 LineNo + ) +{ + SPendingAssign *pNode; + CHAR8 *VarStr; + UINT32 ArrayIdx; + CHAR8 FName[MAX_NAME_LEN]; + EFI_VFR_RETURN_CODE ReturnCode; + EFI_VFR_VARSTORE_TYPE VarStoreType = EFI_VFR_VARSTORE_INVALID; + + for (pNode = PendingAssignList; pNode != NULL; pNode = pNode->mNext) { + if (pNode->mFlag == PENDING) { + // + // declare this question as Numeric in SuppressIf True + // + // SuppressIf + CIfrSuppressIf SIObj; + SIObj.SetLineNo (LineNo); + + //TrueOpcode + CIfrTrue TObj (LineNo); + + //Numeric qeustion + CIfrNumeric CNObj; + EFI_VARSTORE_INFO Info; + EFI_QUESTION_ID QId = EFI_QUESTION_ID_INVALID; + + CNObj.SetLineNo (LineNo); + CNObj.SetPrompt (0x0); + CNObj.SetHelp (0x0); + + // + // Register this question, assume it is normal question, not date or time question + // + VarStr = pNode->mKey; + ReturnCode = lCVfrQuestionDB.RegisterQuestion (NULL, VarStr, QId); + if (ReturnCode != VFR_RETURN_SUCCESS) { + gCVfrErrorHandle.HandleError (ReturnCode, pNode->mLineNo, pNode->mKey); + return ReturnCode; + } + +#ifdef VFREXP_DEBUG + printf ("Undefined Question name is %s and Id is 0x%x\n", VarStr, QId); +#endif + // + // Get Question Info, framework vfr VarName == StructName + // + ReturnCode = lCVfrVarDataTypeDB.ExtractFieldNameAndArrary (VarStr, FName, ArrayIdx); + if (ReturnCode != VFR_RETURN_SUCCESS) { + gCVfrErrorHandle.PrintMsg (pNode->mLineNo, pNode->mKey, "Error", "Var string is not the valid C variable"); + return ReturnCode; + } + // + // Get VarStoreType + // + ReturnCode = lCVfrDataStorage.GetVarStoreType (FName, VarStoreType); + if (ReturnCode == VFR_RETURN_UNDEFINED) { + lCVfrDataStorage.DeclareBufferVarStore ( + FName, + LocalFormSetGuid, + &lCVfrVarDataTypeDB, + FName, + EFI_VARSTORE_ID_INVALID, + FALSE + ); + ReturnCode = lCVfrDataStorage.GetVarStoreType (FName, VarStoreType); + } + if (ReturnCode != VFR_RETURN_SUCCESS) { + gCVfrErrorHandle.PrintMsg (pNode->mLineNo, FName, "Error", "Var Store Type is not defined"); + return ReturnCode; + } + + ReturnCode = lCVfrDataStorage.GetVarStoreId (FName, &Info.mVarStoreId); + if (ReturnCode != VFR_RETURN_SUCCESS) { + gCVfrErrorHandle.PrintMsg (pNode->mLineNo, FName, "Error", "Var Store Type is not defined"); + return ReturnCode; + } + + if (*VarStr == '\0' && ArrayIdx != INVALID_ARRAY_INDEX) { + ReturnCode = lCVfrDataStorage.GetNameVarStoreInfo (&Info, ArrayIdx); + } else { + if (VarStoreType == EFI_VFR_VARSTORE_EFI) { + ReturnCode = lCVfrDataStorage.GetEfiVarStoreInfo (&Info); + } else if (VarStoreType == EFI_VFR_VARSTORE_BUFFER) { + VarStr = pNode->mKey; + ReturnCode = lCVfrVarDataTypeDB.GetDataFieldInfo (VarStr, Info.mInfo.mVarOffset, Info.mVarType, Info.mVarTotalSize); + } else { + ReturnCode = VFR_RETURN_UNSUPPORTED; + } + } + if (ReturnCode != VFR_RETURN_SUCCESS) { + gCVfrErrorHandle.HandleError (ReturnCode, pNode->mLineNo, pNode->mKey); + return ReturnCode; + } + + CNObj.SetQuestionId (QId); + CNObj.SetVarStoreInfo (&Info); + CNObj.SetFlags (0, Info.mVarType); + + // + // For undefined Efi VarStore type question + // Append the extended guided opcode to contain VarName + // + if (VarStoreType == EFI_VFR_VARSTORE_EFI) { + CIfrVarEqName CVNObj (QId, Info.mInfo.mVarName); + CVNObj.SetLineNo (LineNo); + } + + // + // End for Numeric + // + CIfrEnd CEObj; + CEObj.SetLineNo (LineNo); + // + // End for SuppressIf + // + CIfrEnd SEObj; + SEObj.SetLineNo (LineNo); + } + } + return VFR_RETURN_SUCCESS; +} + +CFormPkg gCFormPkg; + +SIfrRecord::SIfrRecord ( + VOID + ) +{ + mIfrBinBuf = NULL; + mBinBufLen = 0; + mLineNo = 0xFFFFFFFF; + mOffset = 0xFFFFFFFF; + mNext = NULL; +} + +SIfrRecord::~SIfrRecord ( + VOID + ) +{ + if (mIfrBinBuf != NULL) { + //delete mIfrBinBuf; + mIfrBinBuf = NULL; + } + mLineNo = 0xFFFFFFFF; + mOffset = 0xFFFFFFFF; + mBinBufLen = 0; + mNext = NULL; +} + +CIfrRecordInfoDB::CIfrRecordInfoDB ( + VOID + ) +{ + mSwitch = TRUE; + mRecordCount = EFI_IFR_RECORDINFO_IDX_START; + mIfrRecordListHead = NULL; + mIfrRecordListTail = NULL; +} + +CIfrRecordInfoDB::~CIfrRecordInfoDB ( + VOID + ) +{ + SIfrRecord *pNode; + + while (mIfrRecordListHead != NULL) { + pNode = mIfrRecordListHead; + mIfrRecordListHead = mIfrRecordListHead->mNext; + delete pNode; + } +} + +SIfrRecord * +CIfrRecordInfoDB::GetRecordInfoFromIdx ( + IN UINT32 RecordIdx + ) +{ + UINT32 Idx; + SIfrRecord *pNode = NULL; + + if (RecordIdx == EFI_IFR_RECORDINFO_IDX_INVALUD) { + return NULL; + } + + for (Idx = (EFI_IFR_RECORDINFO_IDX_START + 1), pNode = mIfrRecordListHead; + (Idx != RecordIdx) && (pNode != NULL); + Idx++, pNode = pNode->mNext) + ; + + return pNode; +} + +UINT32 +CIfrRecordInfoDB::IfrRecordRegister ( + IN UINT32 LineNo, + IN CHAR8 *IfrBinBuf, + IN UINT8 BinBufLen, + IN UINT32 Offset + ) +{ + SIfrRecord *pNew; + + if (mSwitch == FALSE) { + return EFI_IFR_RECORDINFO_IDX_INVALUD; + } + + if ((pNew = new SIfrRecord) == NULL) { + return EFI_IFR_RECORDINFO_IDX_INVALUD; + } + + if (mIfrRecordListHead == NULL) { + mIfrRecordListHead = pNew; + mIfrRecordListTail = pNew; + } else { + mIfrRecordListTail->mNext = pNew; + mIfrRecordListTail = pNew; + } + mRecordCount++; + + return mRecordCount; +} + +VOID +CIfrRecordInfoDB::IfrRecordInfoUpdate ( + IN UINT32 RecordIdx, + IN UINT32 LineNo, + IN CHAR8 *BinBuf, + IN UINT8 BinBufLen, + IN UINT32 Offset + ) +{ + SIfrRecord *pNode; + + if ((pNode = GetRecordInfoFromIdx (RecordIdx)) == NULL) { + return; + } + + pNode->mLineNo = LineNo; + pNode->mOffset = Offset; + pNode->mBinBufLen = BinBufLen; + pNode->mIfrBinBuf = BinBuf; + +} + +VOID +CIfrRecordInfoDB::IfrRecordOutput ( + OUT PACKAGE_DATA &TBuffer + ) +{ + CHAR8 *Temp; + SIfrRecord *pNode; + + if (TBuffer.Buffer != NULL) { + delete TBuffer.Buffer; + } + + TBuffer.Size = 0; + TBuffer.Buffer = NULL; + + + if (mSwitch == FALSE) { + return; + } + + for (pNode = mIfrRecordListHead; pNode != NULL; pNode = pNode->mNext) { + TBuffer.Size += pNode->mBinBufLen; + } + + if (TBuffer.Size != 0) { + TBuffer.Buffer = new CHAR8[TBuffer.Size]; + } else { + return; + } + + Temp = TBuffer.Buffer; + + for (pNode = mIfrRecordListHead; pNode != NULL; pNode = pNode->mNext) { + if (pNode->mIfrBinBuf != NULL) { + memcpy (Temp, pNode->mIfrBinBuf, pNode->mBinBufLen); + Temp += pNode->mBinBufLen; + } + } + + return; +} + +VOID +CIfrRecordInfoDB::IfrRecordOutput ( + IN FILE *File, + IN UINT32 LineNo + ) +{ + SIfrRecord *pNode; + UINT8 Index; + UINT32 TotalSize; + + if (mSwitch == FALSE) { + return; + } + + if (File == NULL) { + return; + } + + TotalSize = 0; + + for (pNode = mIfrRecordListHead; pNode != NULL; pNode = pNode->mNext) { + if (pNode->mLineNo == LineNo || LineNo == 0) { + fprintf (File, ">%08X: ", pNode->mOffset); + TotalSize += pNode->mBinBufLen; + if (pNode->mIfrBinBuf != NULL) { + for (Index = 0; Index < pNode->mBinBufLen; Index++) { + fprintf (File, "%02X ", (UINT8)(pNode->mIfrBinBuf[Index])); + } + } + fprintf (File, "\n"); + } + } + + if (LineNo == 0) { + fprintf (File, "\nTotal Size of all record is 0x%08X\n", TotalSize); + } +} + +// +// for framework vfr file +// adjust opcode sequence for uefi IFR format +// adjust inconsistent and varstore into the right position. +// +BOOLEAN +CIfrRecordInfoDB::CheckQuestionOpCode ( + IN UINT8 OpCode + ) +{ + switch (OpCode) { + case EFI_IFR_CHECKBOX_OP: + case EFI_IFR_NUMERIC_OP: + case EFI_IFR_PASSWORD_OP: + case EFI_IFR_ONE_OF_OP: + case EFI_IFR_ACTION_OP: + case EFI_IFR_STRING_OP: + case EFI_IFR_DATE_OP: + case EFI_IFR_TIME_OP: + case EFI_IFR_ORDERED_LIST_OP: + return TRUE; + default: + return FALSE; + } +} + +BOOLEAN +CIfrRecordInfoDB::CheckIdOpCode ( + IN UINT8 OpCode + ) +{ + switch (OpCode) { + case EFI_IFR_EQ_ID_VAL_OP: + case EFI_IFR_EQ_ID_ID_OP: + case EFI_IFR_EQ_ID_LIST_OP: + case EFI_IFR_QUESTION_REF1_OP: + return TRUE; + default: + return FALSE; + } +} + +EFI_QUESTION_ID +CIfrRecordInfoDB::GetOpcodeQuestionId ( + IN EFI_IFR_OP_HEADER *OpHead + ) +{ + EFI_IFR_QUESTION_HEADER *QuestionHead; + + QuestionHead = (EFI_IFR_QUESTION_HEADER *) (OpHead + 1); + + return QuestionHead->QuestionId; +} + +EFI_VFR_RETURN_CODE +CIfrRecordInfoDB::IfrRecordAdjust ( + VOID + ) +{ + SIfrRecord *pNode, *preNode; + SIfrRecord *uNode, *tNode; + EFI_IFR_OP_HEADER *OpHead, *tOpHead; + EFI_QUESTION_ID QuestionId; + UINT32 StackCount; + UINT32 QuestionScope; + UINT32 OpcodeOffset; + CHAR8 ErrorMsg[MAX_STRING_LEN] = {0, }; + EFI_VFR_RETURN_CODE Status; + + // + // Init local variable + // + Status = VFR_RETURN_SUCCESS; + pNode = mIfrRecordListHead; + preNode = pNode; + QuestionScope = 0; + while (pNode != NULL) { + OpHead = (EFI_IFR_OP_HEADER *) pNode->mIfrBinBuf; + + // + // make sure the inconsistent opcode in question scope + // + if (QuestionScope > 0) { + QuestionScope += OpHead->Scope; + if (OpHead->OpCode == EFI_IFR_END_OP) { + QuestionScope --; + } + } + + if (CheckQuestionOpCode (OpHead->OpCode)) { + QuestionScope = 1; + } + // + // for the inconsistent opcode not in question scope, adjust it + // + if (OpHead->OpCode == EFI_IFR_INCONSISTENT_IF_OP && QuestionScope == 0) { + // + // for inconsistent opcode not in question scope + // + + // + // Count inconsistent opcode Scope + // + StackCount = OpHead->Scope; + QuestionId = EFI_QUESTION_ID_INVALID; + tNode = pNode; + while (tNode != NULL && StackCount > 0) { + tNode = tNode->mNext; + tOpHead = (EFI_IFR_OP_HEADER *) tNode->mIfrBinBuf; + // + // Calculate Scope Number + // + StackCount += tOpHead->Scope; + if (tOpHead->OpCode == EFI_IFR_END_OP) { + StackCount --; + } + // + // by IdEqual opcode to get QuestionId + // + if (QuestionId == EFI_QUESTION_ID_INVALID && + CheckIdOpCode (tOpHead->OpCode)) { + QuestionId = *(EFI_QUESTION_ID *) (tOpHead + 1); + } + } + if (tNode == NULL || QuestionId == EFI_QUESTION_ID_INVALID) { + // + // report error; not found + // + sprintf (ErrorMsg, "Inconsistent OpCode Record list invalid QuestionId is 0x%X", QuestionId); + gCVfrErrorHandle.PrintMsg (0, NULL, "Error", ErrorMsg); + Status = VFR_RETURN_MISMATCHED; + break; + } + // + // extract inconsistent opcode list + // pNode is Incosistent opcode, tNode is End Opcode + // + + // + // insert inconsistent opcode list into the right question scope by questionid + // + for (uNode = mIfrRecordListHead; uNode != NULL; uNode = uNode->mNext) { + tOpHead = (EFI_IFR_OP_HEADER *) uNode->mIfrBinBuf; + if (CheckQuestionOpCode (tOpHead->OpCode) && + (QuestionId == GetOpcodeQuestionId (tOpHead))) { + break; + } + } + // + // insert inconsistent opcode list and check LATE_CHECK flag + // + if (uNode != NULL) { + if ((((EFI_IFR_QUESTION_HEADER *)(tOpHead + 1))->Flags & 0x20) != 0) { + // + // if LATE_CHECK flag is set, change inconsistent to nosumbit + // + OpHead->OpCode = EFI_IFR_NO_SUBMIT_IF_OP; + } + + // + // skip the default storage for Date and Time + // + if ((uNode->mNext != NULL) && (*uNode->mNext->mIfrBinBuf == EFI_IFR_DEFAULT_OP)) { + uNode = uNode->mNext; + } + + preNode->mNext = tNode->mNext; + tNode->mNext = uNode->mNext; + uNode->mNext = pNode; + // + // reset pNode to head list, scan the whole list again. + // + pNode = mIfrRecordListHead; + preNode = pNode; + QuestionScope = 0; + continue; + } else { + // + // not found matched question id, report error + // + sprintf (ErrorMsg, "QuestionId required by Inconsistent OpCode is not found. QuestionId is 0x%X", QuestionId); + gCVfrErrorHandle.PrintMsg (0, NULL, "Error", ErrorMsg); + Status = VFR_RETURN_MISMATCHED; + break; + } + } else if (OpHead->OpCode == EFI_IFR_VARSTORE_OP || + OpHead->OpCode == EFI_IFR_VARSTORE_EFI_OP) { + // + // for new added group of varstore opcode + // + tNode = pNode; + while (tNode->mNext != NULL) { + tOpHead = (EFI_IFR_OP_HEADER *) tNode->mNext->mIfrBinBuf; + if (tOpHead->OpCode != EFI_IFR_VARSTORE_OP && + tOpHead->OpCode != EFI_IFR_VARSTORE_EFI_OP) { + break; + } + tNode = tNode->mNext; + } + + if (tNode->mNext == NULL) { + // + // invalid IfrCode, IfrCode end by EndOpCode + // + gCVfrErrorHandle.PrintMsg (0, NULL, "Error", "No found End Opcode in the end"); + Status = VFR_RETURN_MISMATCHED; + break; + } + + if (tOpHead->OpCode != EFI_IFR_END_OP) { + // + // not new added varstore, which are not needed to be adjust. + // + preNode = tNode; + pNode = tNode->mNext; + continue; + } else { + // + // move new added varstore opcode to the position befor form opcode + // varstore opcode between pNode and tNode + // + + // + // search form opcode from begin + // + for (uNode = mIfrRecordListHead; uNode->mNext != NULL; uNode = uNode->mNext) { + tOpHead = (EFI_IFR_OP_HEADER *) uNode->mNext->mIfrBinBuf; + if (tOpHead->OpCode == EFI_IFR_FORM_OP) { + break; + } + } + // + // Insert varstore opcode beform form opcode if form opcode is found + // + if (uNode->mNext != NULL) { + preNode->mNext = tNode->mNext; + tNode->mNext = uNode->mNext; + uNode->mNext = pNode; + // + // reset pNode to head list, scan the whole list again. + // + pNode = mIfrRecordListHead; + preNode = pNode; + QuestionScope = 0; + continue; + } else { + // + // not found form, continue scan IfrRecord list + // + preNode = tNode; + pNode = tNode->mNext; + continue; + } + } + } + // + // next node + // + preNode = pNode; + pNode = pNode->mNext; + } + + // + // Update Ifr Opcode Offset + // + if (Status == VFR_RETURN_SUCCESS) { + OpcodeOffset = 0; + for (pNode = mIfrRecordListHead; pNode != NULL; pNode = pNode->mNext) { + pNode->mOffset = OpcodeOffset; + OpcodeOffset += pNode->mBinBufLen; + } + } + return Status; +} + +CIfrRecordInfoDB gCIfrRecordInfoDB; + +VOID +CIfrObj::_EMIT_PENDING_OBJ ( + VOID + ) +{ + CHAR8 *ObjBinBuf = NULL; + + // + // do nothing + // + if (!mDelayEmit || !gCreateOp) { + return; + } + + mPkgOffset = gCFormPkg.GetPkgLength (); + // + // update data buffer to package data + // + ObjBinBuf = gCFormPkg.IfrBinBufferGet (mObjBinLen); + if (ObjBinBuf != NULL) { + memcpy (ObjBinBuf, mObjBinBuf, mObjBinLen); + } + + // + // update bin buffer to package data buffer + // + if (mObjBinBuf != NULL) { + delete mObjBinBuf; + mObjBinBuf = ObjBinBuf; + } + + mDelayEmit = FALSE; +} + +/* + * The definition of CIfrObj's member function + */ +static struct { + UINT8 mSize; + UINT8 mScope; +} gOpcodeSizesScopeTable[] = { + { 0, 0 }, // EFI_IFR_INVALID - 0x00 + { sizeof (EFI_IFR_FORM), 1 }, // EFI_IFR_FORM_OP + { sizeof (EFI_IFR_SUBTITLE), 1 }, // EFI_IFR_SUBTITLE_OP + { sizeof (EFI_IFR_TEXT), 0 }, // EFI_IFR_TEXT_OP + { sizeof (EFI_IFR_IMAGE), 0 }, // EFI_IFR_IMAGE_OP + { sizeof (EFI_IFR_ONE_OF), 1 }, // EFI_IFR_ONE_OF_OP - 0x05 + { sizeof (EFI_IFR_CHECKBOX), 1}, // EFI_IFR_CHECKBOX_OP + { sizeof (EFI_IFR_NUMERIC), 1 }, // EFI_IFR_NUMERIC_OP + { sizeof (EFI_IFR_PASSWORD), 1 }, // EFI_IFR_PASSWORD_OP + { sizeof (EFI_IFR_ONE_OF_OPTION), 0 }, // EFI_IFR_ONE_OF_OPTION_OP + { sizeof (EFI_IFR_SUPPRESS_IF), 1 }, // EFI_IFR_SUPPRESS_IF - 0x0A + { sizeof (EFI_IFR_LOCKED), 0 }, // EFI_IFR_LOCKED_OP + { sizeof (EFI_IFR_ACTION), 1 }, // EFI_IFR_ACTION_OP + { sizeof (EFI_IFR_RESET_BUTTON), 1 }, // EFI_IFR_RESET_BUTTON_OP + { sizeof (EFI_IFR_FORM_SET), 1 }, // EFI_IFR_FORM_SET_OP -0xE + { sizeof (EFI_IFR_REF), 0 }, // EFI_IFR_REF_OP + { sizeof (EFI_IFR_NO_SUBMIT_IF), 1}, // EFI_IFR_NO_SUBMIT_IF_OP -0x10 + { sizeof (EFI_IFR_INCONSISTENT_IF), 1 }, // EFI_IFR_INCONSISTENT_IF_OP + { sizeof (EFI_IFR_EQ_ID_VAL), 0 }, // EFI_IFR_EQ_ID_VAL_OP + { sizeof (EFI_IFR_EQ_ID_ID), 0 }, // EFI_IFR_EQ_ID_ID_OP + { sizeof (EFI_IFR_EQ_ID_LIST), 0 }, // EFI_IFR_EQ_ID_LIST_OP - 0x14 + { sizeof (EFI_IFR_AND), 0 }, // EFI_IFR_AND_OP + { sizeof (EFI_IFR_OR), 0 }, // EFI_IFR_OR_OP + { sizeof (EFI_IFR_NOT), 0 }, // EFI_IFR_NOT_OP + { sizeof (EFI_IFR_RULE), 1 }, // EFI_IFR_RULE_OP + { sizeof (EFI_IFR_GRAY_OUT_IF), 1 }, // EFI_IFR_GRAYOUT_IF_OP - 0x19 + { sizeof (EFI_IFR_DATE), 1 }, // EFI_IFR_DATE_OP + { sizeof (EFI_IFR_TIME), 1 }, // EFI_IFR_TIME_OP + { sizeof (EFI_IFR_STRING), 1 }, // EFI_IFR_STRING_OP + { sizeof (EFI_IFR_REFRESH), 0 }, // EFI_IFR_REFRESH_OP + { sizeof (EFI_IFR_DISABLE_IF), 1 }, // EFI_IFR_DISABLE_IF_OP - 0x1E + { 0, 0 }, // 0x1F + { sizeof (EFI_IFR_TO_LOWER), 0 }, // EFI_IFR_TO_LOWER_OP - 0x20 + { sizeof (EFI_IFR_TO_UPPER), 0 }, // EFI_IFR_TO_UPPER_OP - 0x21 + { 0, 0 }, // 0x22 + { sizeof (EFI_IFR_ORDERED_LIST), 1 }, // EFI_IFR_ORDERED_LIST_OP - 0x23 + { sizeof (EFI_IFR_VARSTORE), 0 }, // EFI_IFR_VARSTORE_OP + { sizeof (EFI_IFR_VARSTORE_NAME_VALUE), 0 }, // EFI_IFR_VARSTORE_NAME_VALUE_OP + { sizeof (EFI_IFR_VARSTORE_EFI), 0 }, // EFI_IFR_VARSTORE_EFI_OP + { sizeof (EFI_IFR_VARSTORE_DEVICE), 1 }, // EFI_IFR_VARSTORE_DEVICE_OP + { sizeof (EFI_IFR_VERSION), 0 }, // EFI_IFR_VERSION_OP - 0x28 + { sizeof (EFI_IFR_END), 0 }, // EFI_IFR_END_OP + { sizeof (EFI_IFR_MATCH), 1 }, // EFI_IFR_MATCH_OP - 0x2A + { 0, 0 }, { 0, 0} , { 0, 0} , { 0, 0} , // 0x2B ~ 0x2E + { sizeof (EFI_IFR_EQUAL), 0 }, // EFI_IFR_EQUAL_OP - 0x2F + { sizeof (EFI_IFR_NOT_EQUAL), 0 }, // EFI_IFR_NOT_EQUAL_OP + { sizeof (EFI_IFR_GREATER_THAN), 0 }, // EFI_IFR_GREATER_THAN_OP + { sizeof (EFI_IFR_GREATER_EQUAL), 0 }, // EFI_IFR_GREATER_EQUAL_OP + { sizeof (EFI_IFR_LESS_THAN), 0 }, // EFI_IFR_LESS_THAN_OP + { sizeof (EFI_IFR_LESS_EQUAL), 0 }, // EFI_IFR_LESS_EQUAL_OP - 0x34 + { sizeof (EFI_IFR_BITWISE_AND), 0 }, // EFI_IFR_BITWISE_AND_OP + { sizeof (EFI_IFR_BITWISE_OR), 0 }, // EFI_IFR_BITWISE_OR_OP + { sizeof (EFI_IFR_BITWISE_NOT), 0 }, // EFI_IFR_BITWISE_NOT_OP + { sizeof (EFI_IFR_SHIFT_LEFT), 0 }, // EFI_IFR_SHIFT_LEFT_OP + { sizeof (EFI_IFR_SHIFT_RIGHT), 0 }, // EFI_IFR_SHIFT_RIGHT_OP + { sizeof (EFI_IFR_ADD), 0 }, // EFI_IFR_ADD_OP - 0x3A + { sizeof (EFI_IFR_SUBTRACT), 0 }, // EFI_IFR_SUBTRACT_OP + { sizeof (EFI_IFR_MULTIPLY), 0 }, // EFI_IFR_MULTIPLY_OP + { sizeof (EFI_IFR_DIVIDE), 0 }, // EFI_IFR_DIVIDE_OP + { sizeof (EFI_IFR_MODULO), 0 }, // EFI_IFR_MODULO_OP - 0x3E + { sizeof (EFI_IFR_RULE_REF), 0 }, // EFI_IFR_RULE_REF_OP + { sizeof (EFI_IFR_QUESTION_REF1), 0 }, // EFI_IFR_QUESTION_REF1_OP + { sizeof (EFI_IFR_QUESTION_REF2), 0 }, // EFI_IFR_QUESTION_REF2_OP - 0x41 + { sizeof (EFI_IFR_UINT8), 0}, // EFI_IFR_UINT8 + { sizeof (EFI_IFR_UINT16), 0}, // EFI_IFR_UINT16 + { sizeof (EFI_IFR_UINT32), 0}, // EFI_IFR_UINT32 + { sizeof (EFI_IFR_UINT64), 0}, // EFI_IFR_UTNT64 + { sizeof (EFI_IFR_TRUE), 0 }, // EFI_IFR_TRUE_OP - 0x46 + { sizeof (EFI_IFR_FALSE), 0 }, // EFI_IFR_FALSE_OP + { sizeof (EFI_IFR_TO_UINT), 0 }, // EFI_IFR_TO_UINT_OP + { sizeof (EFI_IFR_TO_STRING), 0 }, // EFI_IFR_TO_STRING_OP + { sizeof (EFI_IFR_TO_BOOLEAN), 0 }, // EFI_IFR_TO_BOOLEAN_OP + { sizeof (EFI_IFR_MID), 0 }, // EFI_IFR_MID_OP + { sizeof (EFI_IFR_FIND), 0 }, // EFI_IFR_FIND_OP + { sizeof (EFI_IFR_TOKEN), 0 }, // EFI_IFR_TOKEN_OP + { sizeof (EFI_IFR_STRING_REF1), 0 }, // EFI_IFR_STRING_REF1_OP - 0x4E + { sizeof (EFI_IFR_STRING_REF2), 0 }, // EFI_IFR_STRING_REF2_OP + { sizeof (EFI_IFR_CONDITIONAL), 0 }, // EFI_IFR_CONDITIONAL_OP + { sizeof (EFI_IFR_QUESTION_REF3), 0 }, // EFI_IFR_QUESTION_REF3_OP + { sizeof (EFI_IFR_ZERO), 0 }, // EFI_IFR_ZERO_OP + { sizeof (EFI_IFR_ONE), 0 }, // EFI_IFR_ONE_OP + { sizeof (EFI_IFR_ONES), 0 }, // EFI_IFR_ONES_OP + { sizeof (EFI_IFR_UNDEFINED), 0 }, // EFI_IFR_UNDEFINED_OP + { sizeof (EFI_IFR_LENGTH), 0 }, // EFI_IFR_LENGTH_OP + { sizeof (EFI_IFR_DUP), 0 }, // EFI_IFR_DUP_OP - 0x57 + { sizeof (EFI_IFR_THIS), 0 }, // EFI_IFR_THIS_OP + { sizeof (EFI_IFR_SPAN), 0 }, // EFI_IFR_SPAN_OP + { sizeof (EFI_IFR_VALUE), 1 }, // EFI_IFR_VALUE_OP + { sizeof (EFI_IFR_DEFAULT), 0 }, // EFI_IFR_DEFAULT_OP + { sizeof (EFI_IFR_DEFAULTSTORE), 0 }, // EFI_IFR_DEFAULTSTORE_OP - 0x5C + { 0, 0}, // 0x5D + { sizeof (EFI_IFR_CATENATE), 0 }, // EFI_IFR_CATENATE_OP + { sizeof (EFI_IFR_GUID), 0 }, // EFI_IFR_GUID_OP +}; + +#ifdef CIFROBJ_DEUBG +static struct { + CHAR8 *mIfrName; +} gIfrObjPrintDebugTable[] = { + "EFI_IFR_INVALID", "EFI_IFR_FORM", "EFI_IFR_SUBTITLE", "EFI_IFR_TEXT", "EFI_IFR_IMAGE", "EFI_IFR_ONE_OF", + "EFI_IFR_CHECKBOX", "EFI_IFR_NUMERIC", "EFI_IFR_PASSWORD", "EFI_IFR_ONE_OF_OPTION", "EFI_IFR_SUPPRESS_IF", "EFI_IFR_LOCKED", + "EFI_IFR_ACTION", "EFI_IFR_RESET_BUTTON", "EFI_IFR_FORM_SET", "EFI_IFR_REF", "EFI_IFR_NO_SUBMIT_IF", "EFI_IFR_INCONSISTENT_IF", + "EFI_IFR_EQ_ID_VAL", "EFI_IFR_EQ_ID_ID", "EFI_IFR_EQ_ID_LIST", "EFI_IFR_AND", "EFI_IFR_OR", "EFI_IFR_NOT", + "EFI_IFR_RULE", "EFI_IFR_GRAY_OUT_IF", "EFI_IFR_DATE", "EFI_IFR_TIME", "EFI_IFR_STRING", "EFI_IFR_REFRESH", + "EFI_IFR_DISABLE_IF", "EFI_IFR_INVALID", "EFI_IFR_TO_LOWER", "EFI_IFR_TO_UPPER", "EFI_IFR_INVALID", "EFI_IFR_ORDERED_LIST", + "EFI_IFR_VARSTORE", "EFI_IFR_VARSTORE_NAME_VALUE", "EFI_IFR_VARSTORE_EFI", "EFI_IFR_VARSTORE_DEVICE", "EFI_IFR_VERSION", "EFI_IFR_END", + "EFI_IFR_MATCH", "EFI_IFR_INVALID", "EFI_IFR_INVALID", "EFI_IFR_INVALID", "EFI_IFR_INVALID", "EFI_IFR_EQUAL", + "EFI_IFR_NOT_EQUAL", "EFI_IFR_GREATER_THAN", "EFI_IFR_GREATER_EQUAL", "EFI_IFR_LESS_THAN", "EFI_IFR_LESS_EQUAL", "EFI_IFR_BITWISE_AND", + "EFI_IFR_BITWISE_OR", "EFI_IFR_BITWISE_NOT", "EFI_IFR_SHIFT_LEFT", "EFI_IFR_SHIFT_RIGHT", "EFI_IFR_ADD", "EFI_IFR_SUBTRACT", + "EFI_IFR_MULTIPLY", "EFI_IFR_DIVIDE", "EFI_IFR_MODULO", "EFI_IFR_RULE_REF", "EFI_IFR_QUESTION_REF1", "EFI_IFR_QUESTION_REF2", + "EFI_IFR_UINT8", "EFI_IFR_UINT16", "EFI_IFR_UINT32", "EFI_IFR_UINT64", "EFI_IFR_TRUE", "EFI_IFR_FALSE", + "EFI_IFR_TO_UINT", "EFI_IFR_TO_STRING", "EFI_IFR_TO_BOOLEAN", "EFI_IFR_MID", "EFI_IFR_FIND", "EFI_IFR_TOKEN", + "EFI_IFR_STRING_REF1","EFI_IFR_STRING_REF2", "EFI_IFR_CONDITIONAL", "EFI_IFR_QUESTION_REF3", "EFI_IFR_ZERO", "EFI_IFR_ONE", + "EFI_IFR_ONES", "EFI_IFR_UNDEFINED", "EFI_IFR_LENGTH", "EFI_IFR_DUP", "EFI_IFR_THIS", "EFI_IFR_SPAN", + "EFI_IFR_VALUE", "EFI_IFR_DEFAULT", "EFI_IFR_DEFAULTSTORE", "EFI_IFR_INVALID", "EFI_IFR_CATENATE", "EFI_IFR_GUID", +}; + +VOID +CIFROBJ_DEBUG_PRINT ( + IN UINT8 OpCode + ) +{ + printf ("======Create IFR [%s]\n", gIfrObjPrintDebugTable[OpCode].mIfrName); +} +#else + +#define CIFROBJ_DEBUG_PRINT(OpCode) + +#endif + +bool gCreateOp = TRUE; + +CIfrObj::CIfrObj ( + IN UINT8 OpCode, + OUT CHAR8 **IfrObj, + IN UINT8 ObjBinLen, + IN BOOLEAN DelayEmit + ) +{ + mDelayEmit = DelayEmit; + mPkgOffset = gCFormPkg.GetPkgLength (); + mObjBinLen = (ObjBinLen == 0) ? gOpcodeSizesScopeTable[OpCode].mSize : ObjBinLen; + mObjBinBuf = ((DelayEmit == FALSE) && (gCreateOp == TRUE)) ? gCFormPkg.IfrBinBufferGet (mObjBinLen) : new CHAR8[EFI_IFR_MAX_LENGTH]; + mRecordIdx = (gCreateOp == TRUE) ? gCIfrRecordInfoDB.IfrRecordRegister (0xFFFFFFFF, mObjBinBuf, mObjBinLen, mPkgOffset) : EFI_IFR_RECORDINFO_IDX_INVALUD; + + if (IfrObj != NULL) { + *IfrObj = mObjBinBuf; + } + + CIFROBJ_DEBUG_PRINT (OpCode); +} + +CIfrObj::~CIfrObj ( + VOID + ) +{ + if ((mDelayEmit == TRUE) && ((gCreateOp == TRUE))) { + _EMIT_PENDING_OBJ (); + } + + gCIfrRecordInfoDB.IfrRecordInfoUpdate (mRecordIdx, mLineNo, mObjBinBuf, mObjBinLen, mPkgOffset); +} + +/* + * The definition of CIfrObj's member function + */ +UINT8 gScopeCount = 0; + +CIfrOpHeader::CIfrOpHeader ( + IN UINT8 OpCode, + IN VOID *StartAddr, + IN UINT8 Length + ) : mHeader ((EFI_IFR_OP_HEADER *)StartAddr) +{ + mHeader->OpCode = OpCode; + mHeader->Length = (Length == 0) ? gOpcodeSizesScopeTable[OpCode].mSize : Length; + mHeader->Scope = (gOpcodeSizesScopeTable[OpCode].mScope + gScopeCount > 0) ? 1 : 0; +} + +CIfrOpHeader::CIfrOpHeader ( + IN CIfrOpHeader &OpHdr + ) +{ + mHeader = OpHdr.mHeader; +} + +UINT32 CIfrForm::FormIdBitMap[EFI_FREE_FORM_ID_BITMAP_SIZE] = {0, }; diff --git a/BaseTools/Source/C/VfrCompile/VfrFormPkg.h b/BaseTools/Source/C/VfrCompile/VfrFormPkg.h new file mode 100644 index 0000000000..3f387666bd --- /dev/null +++ b/BaseTools/Source/C/VfrCompile/VfrFormPkg.h @@ -0,0 +1,2358 @@ +/** @file + + The definition of CFormPkg's member function + +Copyright (c) 2004 - 2008, 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. + +**/ + +#ifndef _EFIIFRCLASS_H_ +#define _EFIIFRCLASS_H_ + +#include "string.h" +#include "EfiVfr.h" +#include "VfrError.h" +#include "VfrUtilityLib.h" + +#define NO_QST_REFED "no question refered" + +struct PACKAGE_DATA { + CHAR8 *Buffer; + UINT32 Size; +}; + +/* + * The functions below are used for flags setting + */ +static inline BOOLEAN _FLAGS_ZERO ( + IN UINT8 &Flags + ) +{ + return Flags == 0; +} + +static inline VOID _FLAG_CLEAR ( + IN UINT8 &Flags, + IN UINT8 Mask + ) +{ + Flags &= (~Mask); +} + +static inline UINT8 _FLAG_TEST_AND_CLEAR ( + IN UINT8 &Flags, + IN UINT8 Mask + ) +{ + UINT8 Ret = Flags & Mask; + Flags &= (~Mask); + return Ret; +} + +static inline UINT8 _IS_EQUAL ( + IN UINT8 &Flags, + IN UINT8 Value + ) +{ + return Flags == Value; +} + +/* + * The definition of CIfrBin + */ +typedef enum { + PENDING, + ASSIGNED +} ASSIGN_FLAG; + +struct SPendingAssign { + CHAR8 *mKey; // key ! unique + VOID *mAddr; + UINT32 mLen; + ASSIGN_FLAG mFlag; + UINT32 mLineNo; + CHAR8 *mMsg; + struct SPendingAssign *mNext; + + SPendingAssign (IN CHAR8 *, IN VOID *, IN UINT32, IN UINT32, IN CHAR8 *); + ~SPendingAssign (); + + VOID SetAddrAndLen (IN VOID *, IN UINT32); + VOID AssignValue (IN VOID *, IN UINT32); + CHAR8 * GetKey (VOID); +}; + +struct SBufferNode { + CHAR8 *mBufferStart; + CHAR8 *mBufferEnd; + CHAR8 *mBufferFree; + struct SBufferNode *mNext; +}; + +class CFormPkg { +private: + UINT32 mBufferSize; + SBufferNode *mBufferNodeQueueHead; + SBufferNode *mBufferNodeQueueTail; + SBufferNode *mCurrBufferNode; + + SBufferNode *mReadBufferNode; + UINT32 mReadBufferOffset; + + UINT32 mPkgLength; + + VOID _WRITE_PKG_LINE (IN FILE *, IN UINT32 , IN CHAR8 *, IN CHAR8 *, IN UINT32); + VOID _WRITE_PKG_END (IN FILE *, IN UINT32 , IN CHAR8 *, IN CHAR8 *, IN UINT32); + +private: + SPendingAssign *PendingAssignList; + +public: + CFormPkg (IN UINT32 BufferSize); + ~CFormPkg (); + + CHAR8 * IfrBinBufferGet (IN UINT32); + inline UINT32 GetPkgLength (VOID); + + VOID Open (); + UINT32 Read (IN CHAR8 *, IN UINT32); + VOID Close (); + + EFI_VFR_RETURN_CODE BuildPkgHdr (OUT EFI_HII_PACKAGE_HEADER **); + EFI_VFR_RETURN_CODE BuildPkg (IN FILE *, IN PACKAGE_DATA *PkgData = NULL); + EFI_VFR_RETURN_CODE BuildPkg (OUT PACKAGE_DATA &); + EFI_VFR_RETURN_CODE GenCFile (IN CHAR8 *, IN FILE *, IN PACKAGE_DATA *PkgData = NULL); + +public: + EFI_VFR_RETURN_CODE AssignPending (IN CHAR8 *, IN VOID *, IN UINT32, IN UINT32, IN CHAR8 *Msg = NULL); + VOID DoPendingAssign (IN CHAR8 *, IN VOID *, IN UINT32); + bool HavePendingUnassigned (VOID); + VOID PendingAssignPrintAll (VOID); + EFI_VFR_RETURN_CODE DeclarePendingQuestion ( + IN CVfrVarDataTypeDB &lCVfrVarDataTypeDB, + IN CVfrDataStorage &lCVfrDataStorage, + IN CVfrQuestionDB &lCVfrQuestionDB, + IN EFI_GUID *LocalFormSetGuid, + IN UINT32 LineNo + ); +}; + +extern CFormPkg gCFormPkg; + +struct SIfrRecord { + UINT32 mLineNo; + CHAR8 *mIfrBinBuf; + UINT8 mBinBufLen; + UINT32 mOffset; + SIfrRecord *mNext; + + SIfrRecord (VOID); + ~SIfrRecord (VOID); +}; + +#define EFI_IFR_RECORDINFO_IDX_INVALUD 0xFFFFFF +#define EFI_IFR_RECORDINFO_IDX_START 0x0 + +class CIfrRecordInfoDB { +private: + bool mSwitch; + UINT32 mRecordCount; + SIfrRecord *mIfrRecordListHead; + SIfrRecord *mIfrRecordListTail; + + SIfrRecord * GetRecordInfoFromIdx (IN UINT32); + BOOLEAN CheckQuestionOpCode (IN UINT8); + BOOLEAN CheckIdOpCode (IN UINT8); + EFI_QUESTION_ID GetOpcodeQuestionId (IN EFI_IFR_OP_HEADER *); +public: + CIfrRecordInfoDB (VOID); + ~CIfrRecordInfoDB (VOID); + + inline VOID TurnOn (VOID) { + mSwitch = TRUE; + } + + inline VOID TurnOff (VOID) { + mSwitch = FALSE; + } + + UINT32 IfrRecordRegister (IN UINT32, IN CHAR8 *, IN UINT8, IN UINT32); + VOID IfrRecordInfoUpdate (IN UINT32, IN UINT32, IN CHAR8*, IN UINT8, IN UINT32); + VOID IfrRecordOutput (IN FILE *, IN UINT32 LineNo); + VOID IfrRecordOutput (OUT PACKAGE_DATA &); + EFI_VFR_RETURN_CODE IfrRecordAdjust (VOID); +}; + +extern CIfrRecordInfoDB gCIfrRecordInfoDB; + +/* + * The definition of CIfrObj + */ +extern bool gCreateOp; + +class CIfrObj { +private: + bool mDelayEmit; + + CHAR8 *mObjBinBuf; + UINT8 mObjBinLen; + UINT32 mLineNo; + UINT32 mRecordIdx; + UINT32 mPkgOffset; + +public: + CIfrObj (IN UINT8 OpCode, OUT CHAR8 **IfrObj = NULL, IN UINT8 ObjBinLen = 0, IN BOOLEAN DelayEmit = FALSE); + virtual ~CIfrObj(VOID); + + VOID _EMIT_PENDING_OBJ (VOID); + + inline VOID SetLineNo (IN UINT32 LineNo) { + mLineNo = LineNo; + } + + inline CHAR8 * GetObjBinAddr (VOID) { + return mObjBinBuf; + } + + inline UINT8 GetObjBinLen (VOID) { + return mObjBinLen; + } + + inline bool ExpendObjBin (IN UINT8 Size) { + if ((mDelayEmit == TRUE) && ((mObjBinLen + Size) > mObjBinLen)) { + mObjBinLen += Size; + return TRUE; + } else { + return FALSE; + } + } +}; + +/* + * The definition of CIfrOpHeader + */ +class CIfrOpHeader { +private: + EFI_IFR_OP_HEADER *mHeader; + +public: + CIfrOpHeader (IN UINT8 OpCode, IN VOID *StartAddr, IN UINT8 Length = 0); + CIfrOpHeader (IN CIfrOpHeader &); + + VOID IncLength (UINT8 Size) { + if ((mHeader->Length + Size) > mHeader->Length) { + mHeader->Length += Size; + } + } + + VOID DecLength (UINT8 Size) { + if (mHeader->Length >= Size) { + mHeader -= Size; + } + } + + UINT8 GetLength () { + return mHeader->Length; + } + + UINT8 GetScope () { + return mHeader->Scope; + } + + VOID SetScope (IN UINT8 Scope) { + mHeader->Scope = Scope; + } + + VOID UpdateHeader (IN EFI_IFR_OP_HEADER *Header) { + mHeader = Header; + } +}; + +extern UINT8 gScopeCount; + +/* + * The definition of CIfrStatementHeader + */ +class CIfrStatementHeader { +private: + EFI_IFR_STATEMENT_HEADER *mHeader; + +public: + CIfrStatementHeader ( + IN EFI_IFR_STATEMENT_HEADER *StartAddr + ) : mHeader ((EFI_IFR_STATEMENT_HEADER *)StartAddr) { + mHeader = StartAddr; + mHeader->Help = EFI_STRING_ID_INVALID; + mHeader->Prompt = EFI_STRING_ID_INVALID; + } + + EFI_IFR_STATEMENT_HEADER *GetStatementHeader () { + return mHeader; + } + + VOID SetPrompt (IN EFI_STRING_ID Prompt) { + mHeader->Prompt = Prompt; + } + + VOID SetHelp (IN EFI_STRING_ID Help) { + mHeader->Help = Help; + } +}; + +/* + * The definition of CIfrQuestionHeader + */ +#define EFI_IFR_QUESTION_FLAG_DEFAULT 0 + +class CIfrQuestionHeader : public CIfrStatementHeader { +private: + EFI_IFR_QUESTION_HEADER *mHeader; + + EFI_IFR_STATEMENT_HEADER * QH2SH (EFI_IFR_QUESTION_HEADER *Qheader) { + return &(Qheader)->Header; + } + +public: + EFI_QUESTION_ID QUESTION_ID (VOID) { + return mHeader->QuestionId; + } + + EFI_VARSTORE_ID VARSTORE_ID (VOID) { + return mHeader->VarStoreId; + } + + VOID VARSTORE_INFO (OUT EFI_VARSTORE_INFO *Info) { + if (Info != NULL) { + Info->mVarStoreId = mHeader->VarStoreId; + memcpy (&Info->mVarStoreId, &mHeader->VarStoreInfo, sizeof (Info->mVarStoreId)); + } + } + + UINT8 FLAGS (VOID) { + return mHeader->Flags; + } + +public: + CIfrQuestionHeader ( + IN EFI_IFR_QUESTION_HEADER *StartAddr, + IN UINT8 Flags = EFI_IFR_QUESTION_FLAG_DEFAULT + ) : CIfrStatementHeader (QH2SH(StartAddr)) { + mHeader = StartAddr; + mHeader->QuestionId = EFI_QUESTION_ID_INVALID; + mHeader->VarStoreId = EFI_VARSTORE_ID_INVALID; + mHeader->VarStoreInfo.VarName = EFI_STRING_ID_INVALID; + mHeader->VarStoreInfo.VarOffset = EFI_VAROFFSET_INVALID; + mHeader->Flags = Flags; + } + + VOID SetQuestionId (IN EFI_QUESTION_ID QuestionId) { + mHeader->QuestionId = QuestionId; + } + + VOID SetVarStoreInfo (IN EFI_VARSTORE_INFO *Info) { + mHeader->VarStoreId = Info->mVarStoreId; + mHeader->VarStoreInfo.VarName = Info->mInfo.mVarName; + mHeader->VarStoreInfo.VarOffset = Info->mInfo.mVarOffset; + } + + EFI_VFR_RETURN_CODE SetFlags (IN UINT8 Flags) { + if (_FLAG_TEST_AND_CLEAR (Flags, EFI_IFR_FLAG_READ_ONLY)) { + mHeader->Flags |= EFI_IFR_FLAG_READ_ONLY; + } + + _FLAG_CLEAR (Flags, 0x02); + + if (_FLAG_TEST_AND_CLEAR (Flags, EFI_IFR_FLAG_CALLBACK)) { + mHeader->Flags |= EFI_IFR_FLAG_CALLBACK; + } + + // + // ignore NVAccessFlag + // + _FLAG_CLEAR (Flags, 0x08); + + if (_FLAG_TEST_AND_CLEAR (Flags, EFI_IFR_FLAG_RESET_REQUIRED)) { + mHeader->Flags |= EFI_IFR_FLAG_RESET_REQUIRED; + } + + // + // Set LateCheck Flag to compatible for framework flag + // but it uses 0x20 as its flag, if in the future UEFI may take this flag + // + if (_FLAG_TEST_AND_CLEAR (Flags, 0x20)) { + mHeader->Flags |= 0x20; + } + + if (_FLAG_TEST_AND_CLEAR (Flags, EFI_IFR_FLAG_OPTIONS_ONLY)) { + mHeader->Flags |= EFI_IFR_FLAG_OPTIONS_ONLY; + } + + return _FLAGS_ZERO (Flags) ? VFR_RETURN_SUCCESS : VFR_RETURN_FLAGS_UNSUPPORTED; + } +}; + +static CIfrQuestionHeader *gCurrentQuestion = NULL; + +/* + * The definition of CIfrMinMaxStepData + */ +class CIfrMinMaxStepData { +private: + MINMAXSTEP_DATA *mMinMaxStepData; + +public: + CIfrMinMaxStepData (MINMAXSTEP_DATA *DataAddr) : mMinMaxStepData (DataAddr) { + mMinMaxStepData->u64.MinValue = 0; + mMinMaxStepData->u64.MaxValue = 0; + mMinMaxStepData->u64.Step = 0; + } + + VOID SetMinMaxStepData (IN UINT64 MinValue, IN UINT64 MaxValue, IN UINT64 Step) { + mMinMaxStepData->u64.MinValue = MinValue; + mMinMaxStepData->u64.MaxValue = MaxValue; + mMinMaxStepData->u64.Step = Step; + } + + VOID SetMinMaxStepData (IN UINT32 MinValue, IN UINT32 MaxValue, IN UINT32 Step) { + mMinMaxStepData->u32.MinValue = MinValue; + mMinMaxStepData->u32.MaxValue = MaxValue; + mMinMaxStepData->u32.Step = Step; + } + + VOID SetMinMaxStepData (IN UINT16 MinValue, IN UINT16 MaxValue, IN UINT16 Step) { + mMinMaxStepData->u16.MinValue = MinValue; + mMinMaxStepData->u16.MaxValue = MaxValue; + mMinMaxStepData->u16.Step = Step; + } + + VOID SetMinMaxStepData (IN UINT8 MinValue, IN UINT8 MaxValue, IN UINT8 Step) { + mMinMaxStepData->u8.MinValue = MinValue; + mMinMaxStepData->u8.MaxValue = MaxValue; + mMinMaxStepData->u8.Step = Step; + } + +}; + +/* + * The definition of all of the UEFI IFR Objects + */ +class CIfrFormSet : public CIfrObj, public CIfrOpHeader { +private: + EFI_IFR_FORM_SET *mFormSet; + +public: + CIfrFormSet (UINT8 Size) : CIfrObj (EFI_IFR_FORM_SET_OP, (CHAR8 **)&mFormSet, Size), + CIfrOpHeader (EFI_IFR_FORM_SET_OP, &mFormSet->Header, Size) { + mFormSet->Help = EFI_STRING_ID_INVALID; + mFormSet->FormSetTitle = EFI_STRING_ID_INVALID; + mFormSet->Flags = 0; + memset (&mFormSet->Guid, 0, sizeof (EFI_GUID)); + } + + VOID SetGuid (IN EFI_GUID *Guid) { + memcpy (&mFormSet->Guid, Guid, sizeof (EFI_GUID)); + } + + VOID SetFormSetTitle (IN EFI_STRING_ID FormSetTitle) { + mFormSet->FormSetTitle = FormSetTitle; + } + + VOID SetHelp (IN EFI_STRING_ID Help) { + mFormSet->Help = Help; + } + + VOID SetClassGuid (IN EFI_GUID *Guid) { + memcpy (&(mFormSet->ClassGuid[mFormSet->Flags++]), Guid, sizeof (EFI_GUID)); + } + + UINT8 GetFlags() { + return mFormSet->Flags; + } +}; + +class CIfrEnd : public CIfrObj, public CIfrOpHeader { +private: + EFI_IFR_END *mEnd; + +public: + CIfrEnd () : CIfrObj (EFI_IFR_END_OP, (CHAR8 **)&mEnd), + CIfrOpHeader (EFI_IFR_END_OP, &mEnd->Header) {} +}; + +class CIfrDefaultStore : public CIfrObj, public CIfrOpHeader { +private: + EFI_IFR_DEFAULTSTORE *mDefaultStore; + +public: + CIfrDefaultStore () : CIfrObj (EFI_IFR_DEFAULTSTORE_OP, (CHAR8 **)&mDefaultStore), + CIfrOpHeader (EFI_IFR_DEFAULTSTORE_OP, &mDefaultStore->Header) { + mDefaultStore->DefaultId = EFI_VARSTORE_ID_INVALID; + mDefaultStore->DefaultName = EFI_STRING_ID_INVALID; + } + + VOID SetDefaultName (IN EFI_STRING_ID DefaultName) { + mDefaultStore->DefaultName = DefaultName; + } + + VOID SetDefaultId (IN UINT16 DefaultId) { + mDefaultStore->DefaultId = DefaultId; + } +}; + +#define EFI_FORM_ID_MAX 0xFFFF +#define EFI_FREE_FORM_ID_BITMAP_SIZE ((EFI_FORM_ID_MAX + 1) / EFI_BITS_PER_UINT32) + +class CIfrForm : public CIfrObj, public CIfrOpHeader { +private: + EFI_IFR_FORM *mForm; + + STATIC UINT32 FormIdBitMap[EFI_FREE_FORM_ID_BITMAP_SIZE]; + + STATIC BOOLEAN ChekFormIdFree (IN EFI_FORM_ID FormId) { + UINT32 Index = (FormId / EFI_BITS_PER_UINT32); + UINT32 Offset = (FormId % EFI_BITS_PER_UINT32); + + return (FormIdBitMap[Index] & (0x80000000 >> Offset)) == 0; + } + + STATIC VOID MarkFormIdUsed (IN EFI_FORM_ID FormId) { + UINT32 Index = (FormId / EFI_BITS_PER_UINT32); + UINT32 Offset = (FormId % EFI_BITS_PER_UINT32); + + FormIdBitMap[Index] |= (0x80000000 >> Offset); + } + +public: + CIfrForm () : CIfrObj (EFI_IFR_FORM_OP, (CHAR8 **)&mForm), + CIfrOpHeader (EFI_IFR_FORM_OP, &mForm->Header) { + mForm->FormId = 0; + mForm->FormTitle = EFI_STRING_ID_INVALID; + } + + EFI_VFR_RETURN_CODE SetFormId (IN EFI_FORM_ID FormId) { + if (CIfrForm::ChekFormIdFree (FormId) == FALSE) { + return VFR_RETURN_FORMID_REDEFINED; + } + mForm->FormId = FormId; + CIfrForm::MarkFormIdUsed (FormId); + return VFR_RETURN_SUCCESS; + } + + VOID SetFormTitle (IN EFI_STRING_ID FormTitle) { + mForm->FormTitle = FormTitle; + } +}; + +class CIfrVarStore : public CIfrObj, public CIfrOpHeader { +private: + EFI_IFR_VARSTORE *mVarStore; + +public: + CIfrVarStore () : CIfrObj (EFI_IFR_VARSTORE_OP, (CHAR8 **)&mVarStore, sizeof (EFI_IFR_VARSTORE), TRUE), + CIfrOpHeader (EFI_IFR_VARSTORE_OP, &mVarStore->Header) { + mVarStore->VarStoreId = EFI_VARSTORE_ID_INVALID; + mVarStore->Size = 0; + memset (&mVarStore->Guid, 0, sizeof (EFI_GUID)); + mVarStore->Name[0] = '\0'; + } + + VOID SetGuid (IN EFI_GUID *Guid) { + memcpy (&mVarStore->Guid, Guid, sizeof (EFI_GUID)); + } + + VOID SetVarStoreId (IN EFI_VARSTORE_ID VarStoreId) { + mVarStore->VarStoreId = VarStoreId; + } + + VOID SetSize (IN UINT16 Size) { + mVarStore->Size = Size; + } + + VOID SetName (IN CHAR8 *Name) { + UINT8 Len; + + if (Name != NULL) { + Len = strlen (Name); + if (Len != 0) { + if (ExpendObjBin (Len) == TRUE) { + IncLength (Len); + strcpy ((CHAR8 *)(mVarStore->Name), Name); + } + } + } + } +}; + +class CIfrVarStoreEfi : public CIfrObj, public CIfrOpHeader { +private: + EFI_IFR_VARSTORE_EFI *mVarStoreEfi; + +public: + CIfrVarStoreEfi () : CIfrObj (EFI_IFR_VARSTORE_EFI_OP, (CHAR8 **)&mVarStoreEfi), + CIfrOpHeader (EFI_IFR_VARSTORE_EFI_OP, &mVarStoreEfi->Header) { + mVarStoreEfi->VarStoreId = EFI_VAROFFSET_INVALID; + memset (&mVarStoreEfi->Guid, 0, sizeof (EFI_GUID)); + } + + VOID SetGuid (IN EFI_GUID *Guid) { + memcpy (&mVarStoreEfi->Guid, Guid, sizeof (EFI_GUID)); + } + + VOID SetVarStoreId (IN UINT16 VarStoreId) { + mVarStoreEfi->VarStoreId = VarStoreId; + } + + VOID SetAttributes (IN UINT32 Attributes) { + mVarStoreEfi->Attributes = Attributes; + } +}; + +class CIfrVarStoreNameValue : public CIfrObj, public CIfrOpHeader { +private: + EFI_IFR_VARSTORE_NAME_VALUE *mVarStoreNameValue; + +public: + CIfrVarStoreNameValue () : CIfrObj (EFI_IFR_VARSTORE_NAME_VALUE_OP, (CHAR8 **)&mVarStoreNameValue), + CIfrOpHeader (EFI_IFR_VARSTORE_NAME_VALUE_OP, &mVarStoreNameValue->Header) { + mVarStoreNameValue->VarStoreId = EFI_VAROFFSET_INVALID; + memset (&mVarStoreNameValue->Guid, 0, sizeof (EFI_GUID)); + } + + VOID SetGuid (IN EFI_GUID *Guid) { + memcpy (&mVarStoreNameValue->Guid, Guid, sizeof (EFI_GUID)); + } + + VOID SetVarStoreId (IN UINT16 VarStoreId) { + mVarStoreNameValue->VarStoreId = VarStoreId; + } +}; + +class CIfrImage : public CIfrObj, public CIfrOpHeader { +private: + EFI_IFR_IMAGE *mImage; + +public: + CIfrImage () : CIfrObj (EFI_IFR_IMAGE_OP, (CHAR8 **)&mImage), + CIfrOpHeader (EFI_IFR_FORM_OP, &mImage->Header) { + mImage->Id = EFI_IMAGE_ID_INVALID; + } + + VOID SetImageId (IN EFI_IMAGE_ID ImageId) { + mImage->Id = ImageId; + } +}; + +class CIfrLocked : public CIfrObj, public CIfrOpHeader { +private: + EFI_IFR_LOCKED *mLocked; + +public: + CIfrLocked () : CIfrObj (EFI_IFR_LOCKED_OP, (CHAR8 **)&mLocked), + CIfrOpHeader (EFI_IFR_LOCKED_OP, &mLocked->Header) {} +}; + +class CIfrRule : public CIfrObj, public CIfrOpHeader { +private: + EFI_IFR_RULE *mRule; + +public: + CIfrRule () : CIfrObj (EFI_IFR_RULE_OP, (CHAR8 **)&mRule), + mRule ((EFI_IFR_RULE *)GetObjBinAddr()), + CIfrOpHeader (EFI_IFR_RULE_OP, &mRule->Header) { + mRule->RuleId = EFI_RULE_ID_INVALID; + } + + VOID SetRuleId (IN UINT8 RuleId) { + mRule->RuleId = RuleId; + } +}; + +static EFI_IFR_TYPE_VALUE gZeroEfiIfrTypeValue = {0, }; + +class CIfrDefault : public CIfrObj, public CIfrOpHeader { +private: + EFI_IFR_DEFAULT *mDefault; + +public: + CIfrDefault ( + IN UINT16 DefaultId = EFI_HII_DEFAULT_CLASS_STANDARD, + IN UINT8 Type = EFI_IFR_TYPE_OTHER, + IN EFI_IFR_TYPE_VALUE Value = gZeroEfiIfrTypeValue + ) : CIfrObj (EFI_IFR_DEFAULT_OP, (CHAR8 **)&mDefault), + CIfrOpHeader (EFI_IFR_DEFAULT_OP, &mDefault->Header) { + mDefault->Type = Type; + mDefault->Value = Value; + mDefault->DefaultId = DefaultId; + } + + VOID SetDefaultId (IN UINT16 DefaultId) { + mDefault->DefaultId = DefaultId; + } + + VOID SetType (IN UINT8 Type) { + mDefault->Type = Type; + } + + VOID SetValue (IN EFI_IFR_TYPE_VALUE Value) { + mDefault->Value = Value; + } +}; + +class CIfrValue : public CIfrObj, public CIfrOpHeader{ +private: + EFI_IFR_VALUE *mValue; + +public: + CIfrValue () : CIfrObj (EFI_IFR_VALUE_OP, (CHAR8 **)&mValue), + CIfrOpHeader (EFI_IFR_VALUE_OP, &mValue->Header) {} + +}; + +class CIfrSubtitle : public CIfrObj, public CIfrOpHeader, public CIfrStatementHeader { +private: + EFI_IFR_SUBTITLE *mSubtitle; + +public: + CIfrSubtitle () : CIfrObj (EFI_IFR_SUBTITLE_OP, (CHAR8 **)&mSubtitle), + CIfrOpHeader (EFI_IFR_SUBTITLE_OP, &mSubtitle->Header), + CIfrStatementHeader (&mSubtitle->Statement) { + mSubtitle->Flags = 0; + } + + EFI_VFR_RETURN_CODE SetFlags (IN UINT8 LFlags) { + if (_FLAG_TEST_AND_CLEAR (LFlags, EFI_IFR_FLAGS_HORIZONTAL)) { + mSubtitle->Flags |= EFI_IFR_FLAGS_HORIZONTAL; + } + + return _FLAGS_ZERO (LFlags) ? VFR_RETURN_SUCCESS : VFR_RETURN_FLAGS_UNSUPPORTED; + } +}; + +class CIfrText : public CIfrObj, public CIfrOpHeader, public CIfrStatementHeader { +private: + EFI_IFR_TEXT *mText; + +public: + CIfrText () : CIfrObj (EFI_IFR_TEXT_OP, (CHAR8 **)&mText), + CIfrOpHeader (EFI_IFR_TEXT_OP, &mText->Header), + CIfrStatementHeader (&mText->Statement) { + mText->TextTwo = EFI_STRING_ID_INVALID; + } + + VOID SetTextTwo (IN EFI_STRING_ID StringId) { + mText->TextTwo = StringId; + } +}; + +class CIfrRef : public CIfrObj, public CIfrOpHeader, public CIfrQuestionHeader { +private: + EFI_IFR_REF *mRef; + +public: + CIfrRef () : CIfrObj (EFI_IFR_REF_OP, (CHAR8 **)&mRef), + CIfrOpHeader (EFI_IFR_REF_OP, &mRef->Header), + CIfrQuestionHeader (&mRef->Question) { + mRef->FormId = 0; + } + + VOID SetFormId (IN EFI_FORM_ID FormId) { + mRef->FormId = FormId; + } +}; + +class CIfrRef2 : public CIfrObj, public CIfrOpHeader, public CIfrQuestionHeader { +private: + EFI_IFR_REF2 *mRef2; + +public: + CIfrRef2 () : CIfrObj (EFI_IFR_REF_OP, (CHAR8 **)&mRef2, sizeof (EFI_IFR_REF2)), + CIfrOpHeader (EFI_IFR_REF_OP, &mRef2->Header, sizeof (EFI_IFR_REF2)), + CIfrQuestionHeader (&mRef2->Question) { + mRef2->FormId = 0; + mRef2->QuestionId = EFI_QUESTION_ID_INVALID; + } + + VOID SetFormId (IN EFI_FORM_ID FormId) { + mRef2->FormId = FormId; + } + + EFI_VFR_RETURN_CODE SetQuestionId (IN EFI_QUESTION_ID QuestionId) { + if (QuestionId == EFI_QUESTION_ID_INVALID) { + return VFR_RETURN_UNDEFINED; + } + mRef2->QuestionId = QuestionId; + return VFR_RETURN_SUCCESS; + } +}; + +class CIfrRef3 : public CIfrObj, public CIfrOpHeader, public CIfrQuestionHeader { +private: + EFI_IFR_REF3 *mRef3; + +public: + CIfrRef3 () : CIfrObj (EFI_IFR_REF_OP, (CHAR8 **)&mRef3, sizeof(EFI_IFR_REF3)), + CIfrOpHeader (EFI_IFR_REF_OP, &mRef3->Header, sizeof (EFI_IFR_REF3)), + CIfrQuestionHeader (&mRef3->Question) { + mRef3->FormId = 0; + mRef3->QuestionId = EFI_QUESTION_ID_INVALID; + memset (&mRef3->FormSetId, 0, sizeof (EFI_GUID)); + } + + VOID SetFormId (IN EFI_FORM_ID FormId) { + mRef3->FormId = FormId; + } + + VOID SetQuestionId (IN EFI_QUESTION_ID QuestionId) { + mRef3->QuestionId = QuestionId; + } + + VOID SetFormSetId (IN EFI_GUID FormSetId) { + mRef3->FormSetId = FormSetId; + } +}; + +class CIfrRef4 : public CIfrObj, public CIfrOpHeader, public CIfrQuestionHeader { +private: + EFI_IFR_REF4 *mRef4; + +public: + CIfrRef4 () : CIfrObj (EFI_IFR_REF_OP, (CHAR8 **)&mRef4, sizeof(EFI_IFR_REF3)), + CIfrOpHeader (EFI_IFR_REF_OP, &mRef4->Header, sizeof (EFI_IFR_REF3)), + CIfrQuestionHeader (&mRef4->Question) { + mRef4->FormId = 0; + mRef4->QuestionId = EFI_QUESTION_ID_INVALID; + memset (&mRef4->FormSetId, 0, sizeof (EFI_GUID)); + mRef4->DevicePath = EFI_STRING_ID_INVALID; + } + + VOID SetFormId (IN EFI_FORM_ID FormId) { + mRef4->FormId = FormId; + } + + VOID SetQuestionId (IN EFI_QUESTION_ID QuestionId) { + mRef4->QuestionId = QuestionId; + } + + VOID SetFormSetId (IN EFI_GUID FormSetId) { + mRef4->FormSetId = FormSetId; + } + + VOID SetDevicePath (IN EFI_STRING_ID DevicePath) { + mRef4->DevicePath = DevicePath; + } +}; + +class CIfrResetButton : public CIfrObj, public CIfrOpHeader, public CIfrStatementHeader { +private: + EFI_IFR_RESET_BUTTON *mResetButton; + +public: + CIfrResetButton () : CIfrObj (EFI_IFR_RESET_BUTTON_OP, (CHAR8 **)&mResetButton), + CIfrOpHeader (EFI_IFR_RESET_BUTTON_OP, &mResetButton->Header), + CIfrStatementHeader (&mResetButton->Question.Header) { + mResetButton->DefaultId = EFI_HII_DEFAULT_CLASS_STANDARD; + } + + VOID SetDefaultId (IN UINT16 DefaultId) { + mResetButton->DefaultId = DefaultId; + } +}; + +class CIfrCheckBox : public CIfrObj, public CIfrOpHeader, public CIfrQuestionHeader { +private: + EFI_IFR_CHECKBOX *mCheckBox; + +public: + CIfrCheckBox () : CIfrObj (EFI_IFR_CHECKBOX_OP, (CHAR8 **)&mCheckBox), + CIfrOpHeader (EFI_IFR_CHECKBOX_OP, &mCheckBox->Header), + CIfrQuestionHeader (&mCheckBox->Question) { + mCheckBox->Flags = 0; + gCurrentQuestion = this; + } + + ~CIfrCheckBox () { + gCurrentQuestion = NULL; + } + + EFI_VFR_RETURN_CODE SetFlags (IN UINT8 HFlags, UINT8 LFlags) { + EFI_VFR_RETURN_CODE Ret; + + Ret = CIfrQuestionHeader::SetFlags (HFlags); + if (Ret != VFR_RETURN_SUCCESS) { + return Ret; + } + + if (_FLAG_TEST_AND_CLEAR (LFlags, EFI_IFR_CHECKBOX_DEFAULT)) { + mCheckBox->Flags |= EFI_IFR_CHECKBOX_DEFAULT; + } + + if (_FLAG_TEST_AND_CLEAR (LFlags, EFI_IFR_CHECKBOX_DEFAULT_MFG)) { + mCheckBox->Flags |= EFI_IFR_CHECKBOX_DEFAULT_MFG; + } + + return _FLAGS_ZERO (LFlags) ? VFR_RETURN_SUCCESS : VFR_RETURN_FLAGS_UNSUPPORTED; + } + + UINT8 GetFlags (VOID) { + return mCheckBox->Flags; + } +}; + +class CIfrAction : public CIfrObj, public CIfrOpHeader, public CIfrQuestionHeader { +private: + EFI_IFR_ACTION *mAction; + +public: + CIfrAction () : CIfrObj (EFI_IFR_ACTION_OP, (CHAR8 **)&mAction), + CIfrOpHeader (EFI_IFR_ACTION_OP, &mAction->Header), + CIfrQuestionHeader (&mAction->Question) { + mAction->QuestionConfig = EFI_STRING_ID_INVALID; + } + + VOID SetQuestionConfig (IN EFI_STRING_ID QuestionConfig) { + mAction->QuestionConfig = QuestionConfig; + } +}; + +class CIfrDate : public CIfrObj, public CIfrOpHeader, public CIfrQuestionHeader { +private: + EFI_IFR_DATE *mDate; + +public: + CIfrDate () : CIfrObj (EFI_IFR_DATE_OP, (CHAR8 **)&mDate), + CIfrOpHeader (EFI_IFR_DATE_OP, &mDate->Header), + CIfrQuestionHeader (&mDate->Question) { + mDate->Flags = 0; + } + + EFI_VFR_RETURN_CODE SetFlags (IN UINT8 HFlags, IN UINT8 LFlags) { + EFI_VFR_RETURN_CODE Ret; + + Ret = CIfrQuestionHeader::SetFlags (HFlags); + if (Ret != VFR_RETURN_SUCCESS) { + return Ret; + } + + if (_FLAG_TEST_AND_CLEAR (LFlags, EFI_QF_DATE_YEAR_SUPPRESS)) { + mDate->Flags |= EFI_QF_DATE_YEAR_SUPPRESS; + } + + if (_FLAG_TEST_AND_CLEAR (LFlags, EFI_QF_DATE_MONTH_SUPPRESS)) { + mDate->Flags |= EFI_QF_DATE_MONTH_SUPPRESS; + } + + if (_FLAG_TEST_AND_CLEAR (LFlags, EFI_QF_DATE_DAY_SUPPRESS)) { + mDate->Flags |= EFI_QF_DATE_DAY_SUPPRESS; + } + + if (_FLAG_TEST_AND_CLEAR (LFlags, QF_DATE_STORAGE_NORMAL)) { + mDate->Flags |= QF_DATE_STORAGE_NORMAL; + } else if (_FLAG_TEST_AND_CLEAR (LFlags, QF_DATE_STORAGE_TIME)) { + mDate->Flags |= QF_DATE_STORAGE_TIME; + } else if (_FLAG_TEST_AND_CLEAR (LFlags, QF_DATE_STORAGE_WAKEUP)) { + mDate->Flags |= QF_DATE_STORAGE_WAKEUP; + } + + return _FLAGS_ZERO (LFlags) ? VFR_RETURN_SUCCESS : VFR_RETURN_FLAGS_UNSUPPORTED; + } +}; + +class CIfrNumeric : public CIfrObj, public CIfrOpHeader, public CIfrQuestionHeader, public CIfrMinMaxStepData { +private: + EFI_IFR_NUMERIC *mNumeric; + +public: + CIfrNumeric () : CIfrObj (EFI_IFR_NUMERIC_OP, (CHAR8 **)&mNumeric), + CIfrOpHeader (EFI_IFR_NUMERIC_OP, &mNumeric->Header), + CIfrQuestionHeader (&mNumeric->Question), + CIfrMinMaxStepData (&mNumeric->data) { + mNumeric->Flags = EFI_IFR_NUMERIC_SIZE_1 | EFI_IFR_DISPLAY_UINT_DEC; + gCurrentQuestion = this; + } + + ~CIfrNumeric () { + gCurrentQuestion = NULL; + } + + EFI_VFR_RETURN_CODE SetFlags (IN UINT8 HFlags, IN UINT8 LFlags) { + EFI_VFR_RETURN_CODE Ret; + + Ret = CIfrQuestionHeader::SetFlags (HFlags); + if (Ret != VFR_RETURN_SUCCESS) { + return Ret; + } + + if (LFlags & EFI_IFR_DISPLAY) { + mNumeric->Flags = LFlags; + } else { + mNumeric->Flags = LFlags | EFI_IFR_DISPLAY_UINT_DEC; + } + return VFR_RETURN_SUCCESS; + } +}; + +class CIfrOneOf : public CIfrObj, public CIfrOpHeader, public CIfrQuestionHeader, public CIfrMinMaxStepData { +private: + EFI_IFR_ONE_OF *mOneOf; + +public: + CIfrOneOf () : CIfrObj (EFI_IFR_ONE_OF_OP, (CHAR8 **)&mOneOf), + CIfrOpHeader (EFI_IFR_ONE_OF_OP, &mOneOf->Header), + CIfrQuestionHeader (&mOneOf->Question), + CIfrMinMaxStepData (&mOneOf->data) { + mOneOf->Flags = 0; + gCurrentQuestion = this; + } + + ~CIfrOneOf () { + gCurrentQuestion = NULL; + } + + EFI_VFR_RETURN_CODE SetFlags (IN UINT8 HFlags, IN UINT8 LFlags) { + EFI_VFR_RETURN_CODE Ret; + + Ret = CIfrQuestionHeader::SetFlags (HFlags); + if (Ret != VFR_RETURN_SUCCESS) { + return Ret; + } + + if (LFlags & EFI_IFR_DISPLAY) { + mOneOf->Flags = LFlags; + } else { + mOneOf->Flags = LFlags | EFI_IFR_DISPLAY_UINT_DEC; + } + return VFR_RETURN_SUCCESS; + } +}; + +class CIfrString : public CIfrObj, public CIfrOpHeader, public CIfrQuestionHeader { +private: + EFI_IFR_STRING *mString; + +public: + CIfrString () : CIfrObj (EFI_IFR_STRING_OP, (CHAR8 **)&mString), + CIfrOpHeader (EFI_IFR_STRING_OP, &mString->Header), + CIfrQuestionHeader (&mString->Question) { + mString->Flags = 0; + mString->MinSize = 0; + mString->MaxSize = 0; + gCurrentQuestion = this; + } + + ~CIfrString () { + gCurrentQuestion = NULL; + } + + EFI_VFR_RETURN_CODE SetFlags (IN UINT8 HFlags, IN UINT8 LFlags) { + EFI_VFR_RETURN_CODE Ret; + + Ret = CIfrQuestionHeader::SetFlags (HFlags); + if (Ret != VFR_RETURN_SUCCESS) { + return Ret; + } + + if (_FLAG_TEST_AND_CLEAR (LFlags, EFI_IFR_STRING_MULTI_LINE)) { + mString->Flags |= EFI_IFR_STRING_MULTI_LINE; + } + + return _FLAGS_ZERO (LFlags) ? VFR_RETURN_SUCCESS : VFR_RETURN_FLAGS_UNSUPPORTED; + } + + VOID SetMinSize (IN UINT8 Flags) { + mString->MinSize = Flags; + } + + VOID SetMaxSize (IN UINT8 MaxSize) { + mString->MaxSize = MaxSize; + } +}; + +class CIfrPassword : public CIfrObj, public CIfrOpHeader, public CIfrQuestionHeader { +private: + EFI_IFR_PASSWORD *mPassword; + +public: + CIfrPassword () : CIfrObj (EFI_IFR_PASSWORD_OP, (CHAR8 **)&mPassword), + CIfrOpHeader (EFI_IFR_PASSWORD_OP, &mPassword->Header), + CIfrQuestionHeader (&mPassword->Question) { + mPassword->MinSize = 0; + mPassword->MaxSize = 0; + gCurrentQuestion = this; + } + + ~CIfrPassword () { + gCurrentQuestion = NULL; + } + + VOID SetMinSize (IN UINT16 MinSize) { + mPassword->MinSize = MinSize; + } + + VOID SetMaxSize (IN UINT16 MaxSize) { + mPassword->MaxSize = MaxSize; + } +}; + +class CIfrOrderedList : public CIfrObj, public CIfrOpHeader, public CIfrQuestionHeader { +private: + EFI_IFR_ORDERED_LIST *mOrderedList; + +public: + CIfrOrderedList () : CIfrObj (EFI_IFR_ORDERED_LIST_OP, (CHAR8 **)&mOrderedList), + CIfrOpHeader (EFI_IFR_ORDERED_LIST_OP, &mOrderedList->Header), + CIfrQuestionHeader (&mOrderedList->Question) { + mOrderedList->MaxContainers = 0; + mOrderedList->Flags = 0; + gCurrentQuestion = this; + } + + ~CIfrOrderedList () { + gCurrentQuestion = NULL; + } + + VOID SetMaxContainers (IN UINT8 MaxContainers) { + mOrderedList->MaxContainers = MaxContainers; + } + + EFI_VFR_RETURN_CODE SetFlags (IN UINT8 HFlags, IN UINT8 LFlags) { + EFI_VFR_RETURN_CODE Ret; + + Ret = CIfrQuestionHeader::SetFlags (HFlags); + if (Ret != VFR_RETURN_SUCCESS) { + return Ret; + } + + if (_FLAG_TEST_AND_CLEAR (LFlags, EFI_IFR_UNIQUE_SET)) { + mOrderedList->Flags |= EFI_IFR_UNIQUE_SET; + } + + if (_FLAG_TEST_AND_CLEAR (LFlags, EFI_IFR_NO_EMPTY_SET)) { + mOrderedList->Flags |= EFI_IFR_NO_EMPTY_SET; + } + + return _FLAGS_ZERO (LFlags) ? VFR_RETURN_SUCCESS : VFR_RETURN_FLAGS_UNSUPPORTED; + } +}; + +class CIfrTime : public CIfrObj, public CIfrOpHeader, public CIfrQuestionHeader { +private: + EFI_IFR_TIME *mTime; + +public: + CIfrTime () : CIfrObj (EFI_IFR_TIME_OP, (CHAR8 **)&mTime), + CIfrOpHeader (EFI_IFR_TIME_OP, &mTime->Header), + CIfrQuestionHeader (&mTime->Question) { + mTime->Flags = 0; + } + + EFI_VFR_RETURN_CODE SetFlags (IN UINT8 HFlags, IN UINT8 LFlags) { + EFI_VFR_RETURN_CODE Ret; + + Ret = CIfrQuestionHeader::SetFlags (HFlags); + if (Ret != VFR_RETURN_SUCCESS) { + return Ret; + } + + if (_FLAG_TEST_AND_CLEAR (LFlags, QF_TIME_HOUR_SUPPRESS)) { + mTime->Flags |= QF_TIME_HOUR_SUPPRESS; + } + + if (_FLAG_TEST_AND_CLEAR (LFlags, QF_TIME_MINUTE_SUPPRESS)) { + mTime->Flags |= QF_TIME_MINUTE_SUPPRESS; + } + + if (_FLAG_TEST_AND_CLEAR (LFlags, QF_TIME_SECOND_SUPPRESS)) { + mTime->Flags |= QF_TIME_SECOND_SUPPRESS; + } + + if (_FLAG_TEST_AND_CLEAR (LFlags, QF_TIME_STORAGE_NORMAL)) { + mTime->Flags |= QF_TIME_STORAGE_NORMAL; + } else if (_FLAG_TEST_AND_CLEAR (LFlags, QF_TIME_STORAGE_TIME)) { + mTime->Flags |= QF_TIME_STORAGE_TIME; + } else if (_FLAG_TEST_AND_CLEAR (LFlags, QF_TIME_STORAGE_WAKEUP)) { + mTime->Flags |= QF_TIME_STORAGE_WAKEUP; + } + + return _FLAGS_ZERO (LFlags) ? VFR_RETURN_SUCCESS : VFR_RETURN_FLAGS_UNSUPPORTED; + } +}; + +class CIfrDisableIf : public CIfrObj, public CIfrOpHeader { +private: + EFI_IFR_DISABLE_IF *mDisableIf; + +public: + CIfrDisableIf () : CIfrObj (EFI_IFR_DISABLE_IF_OP, (CHAR8 **)&mDisableIf), + mDisableIf ((EFI_IFR_DISABLE_IF *) GetObjBinAddr()), + CIfrOpHeader (EFI_IFR_DISABLE_IF_OP, &mDisableIf->Header) {} +}; + +class CIfrSuppressIf : public CIfrObj, public CIfrOpHeader { +private: + EFI_IFR_SUPPRESS_IF *mSuppressIf; + +public: + CIfrSuppressIf () : CIfrObj (EFI_IFR_SUPPRESS_IF_OP, (CHAR8 **)&mSuppressIf), + CIfrOpHeader (EFI_IFR_SUPPRESS_IF_OP, &mSuppressIf->Header) {} +}; + +class CIfrGrayOutIf : public CIfrObj, public CIfrOpHeader { +private: + EFI_IFR_GRAY_OUT_IF *mGrayOutIf; + +public: + CIfrGrayOutIf () : CIfrObj (EFI_IFR_GRAY_OUT_IF_OP, (CHAR8 **)&mGrayOutIf), + CIfrOpHeader (EFI_IFR_GRAY_OUT_IF_OP, &mGrayOutIf->Header) {} +}; + +class CIfrInconsistentIf : public CIfrObj, public CIfrOpHeader { +private: + EFI_IFR_INCONSISTENT_IF *mInconsistentIf; + +public: + CIfrInconsistentIf () : CIfrObj (EFI_IFR_INCONSISTENT_IF_OP, (CHAR8 **)&mInconsistentIf), + CIfrOpHeader (EFI_IFR_INCONSISTENT_IF_OP, &mInconsistentIf->Header) { + mInconsistentIf->Error = EFI_STRING_ID_INVALID; + } + + VOID SetError (IN EFI_STRING_ID Error) { + mInconsistentIf->Error = Error; + } +}; + +class CIfrNoSubmitIf : public CIfrObj, public CIfrOpHeader { +private: + EFI_IFR_NO_SUBMIT_IF *mNoSubmitIf; + +public: + CIfrNoSubmitIf () : CIfrObj (EFI_IFR_NO_SUBMIT_IF_OP, (CHAR8 **)&mNoSubmitIf), + CIfrOpHeader (EFI_IFR_NO_SUBMIT_IF_OP, &mNoSubmitIf->Header) { + mNoSubmitIf->Error = EFI_STRING_ID_INVALID; + } + + VOID SetError (IN EFI_STRING_ID Error) { + mNoSubmitIf->Error = Error; + } +}; + +class CIfrRefresh : public CIfrObj, public CIfrOpHeader { +private: + EFI_IFR_REFRESH *mRefresh; + +public: + CIfrRefresh () : CIfrObj (EFI_IFR_REFRESH_OP, (CHAR8 **)&mRefresh), + CIfrOpHeader (EFI_IFR_REFRESH_OP, &mRefresh->Header) { + mRefresh->RefreshInterval = 0; + } + + VOID SetRefreshInterval (IN UINT8 RefreshInterval) { + mRefresh->RefreshInterval = RefreshInterval; + } +}; + +class CIfrVarStoreDevice : public CIfrObj, public CIfrOpHeader { +private: + EFI_IFR_VARSTORE_DEVICE *mVarStoreDevice; + +public: + CIfrVarStoreDevice () : CIfrObj (EFI_IFR_VARSTORE_DEVICE_OP, (CHAR8 **)&mVarStoreDevice), + CIfrOpHeader (EFI_IFR_VARSTORE_DEVICE_OP, &mVarStoreDevice->Header) { + mVarStoreDevice->DevicePath = EFI_STRING_ID_INVALID; + } + + VOID SetDevicePath (IN EFI_STRING_ID DevicePath) { + mVarStoreDevice->DevicePath = DevicePath; + } +}; + +class CIfrOneOfOption : public CIfrObj, public CIfrOpHeader { +private: + EFI_IFR_ONE_OF_OPTION *mOneOfOption; + +public: + CIfrOneOfOption () : CIfrObj (EFI_IFR_ONE_OF_OPTION_OP, (CHAR8 **)&mOneOfOption), + CIfrOpHeader (EFI_IFR_ONE_OF_OPTION_OP, &mOneOfOption->Header) { + mOneOfOption->Flags = 0; + mOneOfOption->Option = EFI_STRING_ID_INVALID; + mOneOfOption->Type = EFI_IFR_TYPE_OTHER; + memset (&mOneOfOption->Value, 0, sizeof (mOneOfOption->Value)); + } + + VOID SetOption (IN EFI_STRING_ID Option) { + mOneOfOption->Option = Option; + } + + EFI_VFR_RETURN_CODE SetFlags (IN UINT8 LFlags) { + if (_FLAG_TEST_AND_CLEAR (LFlags, EFI_IFR_OPTION_DEFAULT)) { + mOneOfOption->Flags |= EFI_IFR_OPTION_DEFAULT; + } + + if (_FLAG_TEST_AND_CLEAR (LFlags, EFI_IFR_OPTION_DEFAULT_MFG)) { + mOneOfOption->Flags |= EFI_IFR_OPTION_DEFAULT_MFG; + } + + if (_IS_EQUAL (LFlags, EFI_IFR_TYPE_NUM_SIZE_8)) { + _FLAG_CLEAR (LFlags, EFI_IFR_TYPE_NUM_SIZE_8); + mOneOfOption->Flags |= EFI_IFR_TYPE_NUM_SIZE_8; + } else if (_IS_EQUAL (LFlags, EFI_IFR_TYPE_NUM_SIZE_16)) { + _FLAG_CLEAR (LFlags, EFI_IFR_TYPE_NUM_SIZE_16); + mOneOfOption->Flags |= EFI_IFR_TYPE_NUM_SIZE_16; + } else if (_IS_EQUAL (LFlags, EFI_IFR_TYPE_NUM_SIZE_32)) { + _FLAG_CLEAR (LFlags, EFI_IFR_TYPE_NUM_SIZE_32); + mOneOfOption->Flags |= EFI_IFR_TYPE_NUM_SIZE_32; + } else if (_IS_EQUAL (LFlags, EFI_IFR_TYPE_NUM_SIZE_64)) { + _FLAG_CLEAR (LFlags, EFI_IFR_TYPE_NUM_SIZE_64); + mOneOfOption->Flags |= EFI_IFR_TYPE_NUM_SIZE_64; + } else if (_IS_EQUAL (LFlags, EFI_IFR_TYPE_BOOLEAN)) { + _FLAG_CLEAR (LFlags, EFI_IFR_TYPE_BOOLEAN); + mOneOfOption->Flags |= EFI_IFR_TYPE_BOOLEAN; + } else if (_IS_EQUAL (LFlags, EFI_IFR_TYPE_TIME)) { + _FLAG_CLEAR (LFlags, EFI_IFR_TYPE_TIME); + mOneOfOption->Flags |= EFI_IFR_TYPE_TIME; + } else if (_IS_EQUAL (LFlags, EFI_IFR_TYPE_DATE)) { + _FLAG_CLEAR (LFlags, EFI_IFR_TYPE_DATE); + mOneOfOption->Flags |= EFI_IFR_TYPE_DATE; + } else if (_IS_EQUAL (LFlags, EFI_IFR_TYPE_STRING)) { + _FLAG_CLEAR (LFlags, EFI_IFR_TYPE_STRING); + mOneOfOption->Flags |= EFI_IFR_TYPE_STRING; + } else if (_IS_EQUAL (LFlags, EFI_IFR_TYPE_OTHER)) { + _FLAG_CLEAR (LFlags, EFI_IFR_TYPE_OTHER); + mOneOfOption->Flags |= EFI_IFR_TYPE_OTHER; + } + + return _FLAGS_ZERO (LFlags) ? VFR_RETURN_SUCCESS : VFR_RETURN_FLAGS_UNSUPPORTED; + } + + VOID SetType (IN UINT8 Type) { + mOneOfOption->Type = Type; + } + + VOID SetValue (IN EFI_IFR_TYPE_VALUE Value) { + mOneOfOption->Value = Value; + } + + UINT8 GetFlags (VOID) { + return mOneOfOption->Flags; + } +}; + +static EFI_GUID IfrTianoGuid = EFI_IFR_TIANO_GUID; +static EFI_GUID IfrFrameworkGuid = EFI_IFR_FRAMEWORK_GUID; + +class CIfrClass : public CIfrObj, public CIfrOpHeader { +private: + EFI_IFR_GUID_CLASS *mClass; + +public: + CIfrClass () : CIfrObj (EFI_IFR_GUID_OP, (CHAR8 **)&mClass, sizeof (EFI_IFR_GUID_CLASS)), + CIfrOpHeader (EFI_IFR_GUID_OP, &mClass->Header, sizeof (EFI_IFR_GUID_CLASS)) { + mClass->ExtendOpCode = EFI_IFR_EXTEND_OP_CLASS; + mClass->Guid = IfrTianoGuid; + mClass->Class = EFI_NON_DEVICE_CLASS; + } + + VOID SetClass (IN UINT16 Class) { + mClass->Class = Class; + } +}; + +class CIfrSubClass : public CIfrObj, public CIfrOpHeader { +private: + EFI_IFR_GUID_SUBCLASS *mSubClass; + +public: + CIfrSubClass () : CIfrObj (EFI_IFR_GUID_OP, (CHAR8 **)&mSubClass, sizeof (EFI_IFR_GUID_SUBCLASS)), + CIfrOpHeader (EFI_IFR_GUID_OP, &mSubClass->Header, sizeof (EFI_IFR_GUID_SUBCLASS)) { + mSubClass->ExtendOpCode = EFI_IFR_EXTEND_OP_SUBCLASS; + mSubClass->Guid = IfrTianoGuid; + mSubClass->SubClass = EFI_SETUP_APPLICATION_SUBCLASS; + } + + VOID SetSubClass (IN UINT16 SubClass) { + mSubClass->SubClass = SubClass; + } +}; + +class CIfrLabel : public CIfrObj, public CIfrOpHeader { +private: + EFI_IFR_GUID_LABEL *mLabel; + +public: + CIfrLabel () : CIfrObj (EFI_IFR_GUID_OP, (CHAR8 **)&mLabel, sizeof (EFI_IFR_GUID_LABEL)), + CIfrOpHeader (EFI_IFR_GUID_OP, &mLabel->Header, sizeof (EFI_IFR_GUID_LABEL)) { + mLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL; + mLabel->Guid = IfrTianoGuid; + } + + VOID SetNumber (IN UINT16 Number) { + mLabel->Number = Number; + } +}; + +class CIfrBanner : public CIfrObj, public CIfrOpHeader { +private: + EFI_IFR_GUID_BANNER *mBanner; + +public: + CIfrBanner () : CIfrObj (EFI_IFR_GUID_OP, (CHAR8 **)&mBanner, sizeof (EFI_IFR_GUID_BANNER)), + CIfrOpHeader (EFI_IFR_GUID_OP, &mBanner->Header, sizeof (EFI_IFR_GUID_BANNER)) { + mBanner->ExtendOpCode = EFI_IFR_EXTEND_OP_BANNER; + mBanner->Guid = IfrTianoGuid; + } + + VOID SetTitle (IN EFI_STRING_ID StringId) { + mBanner->Title = StringId; + } + + VOID SetLine (IN UINT16 Line) { + mBanner->LineNumber = Line; + } + + VOID SetAlign (IN UINT8 Align) { + mBanner->Alignment = Align; + } +}; + +class CIfrOptionKey : public CIfrObj, public CIfrOpHeader { +private: + EFI_IFR_GUID_OPTIONKEY *mOptionKey; + +public: + CIfrOptionKey ( + IN EFI_QUESTION_ID QuestionId, + IN EFI_IFR_TYPE_VALUE &OptionValue, + IN EFI_QUESTION_ID KeyValue + ) : CIfrObj (EFI_IFR_GUID_OP, (CHAR8 **)&mOptionKey, sizeof (EFI_IFR_GUID_OPTIONKEY)), + CIfrOpHeader (EFI_IFR_GUID_OP, &mOptionKey->Header, sizeof (EFI_IFR_GUID_OPTIONKEY)) { + mOptionKey->ExtendOpCode = EFI_IFR_EXTEND_OP_OPTIONKEY; + mOptionKey->Guid = IfrFrameworkGuid; + mOptionKey->QuestionId = QuestionId; + mOptionKey->OptionValue = OptionValue; + mOptionKey->KeyValue = KeyValue; + } +}; + +class CIfrVarEqName : public CIfrObj, public CIfrOpHeader { +private: + EFI_IFR_GUID_VAREQNAME *mVarEqName; + +public: + CIfrVarEqName ( + IN EFI_QUESTION_ID QuestionId, + IN EFI_STRING_ID NameId + ) : CIfrObj (EFI_IFR_GUID_OP, (CHAR8 **)&mVarEqName, sizeof (EFI_IFR_GUID_VAREQNAME)), + CIfrOpHeader (EFI_IFR_GUID_OP, &mVarEqName->Header, sizeof (EFI_IFR_GUID_VAREQNAME)) { + mVarEqName->ExtendOpCode = EFI_IFR_EXTEND_OP_VAREQNAME; + mVarEqName->Guid = IfrFrameworkGuid; + mVarEqName->QuestionId = QuestionId; + mVarEqName->NameId = NameId; + } +}; + +class CIfrTimeout : public CIfrObj, public CIfrOpHeader { +private: + EFI_IFR_GUID_TIMEOUT *mTimeout; + +public: + CIfrTimeout (IN UINT16 Timeout = 0) : CIfrObj (EFI_IFR_GUID_OP, (CHAR8 **)&mTimeout, sizeof (EFI_IFR_GUID_TIMEOUT)), + CIfrOpHeader (EFI_IFR_GUID_OP, &mTimeout->Header, sizeof (EFI_IFR_GUID_TIMEOUT)) { + mTimeout->ExtendOpCode = EFI_IFR_EXTEND_OP_TIMEOUT; + mTimeout->Guid = IfrTianoGuid; + mTimeout->TimeOut = Timeout; + } + + VOID SetTimeout (IN UINT16 Timeout) { + mTimeout->TimeOut = Timeout; + } +}; + +class CIfrDup : public CIfrObj, public CIfrOpHeader { +private: + EFI_IFR_DUP *mDup; + +public: + CIfrDup ( + IN UINT32 LineNo + ) : CIfrObj (EFI_IFR_DUP_OP, (CHAR8 **)&mDup), + CIfrOpHeader (EFI_IFR_DUP_OP, &mDup->Header) { + SetLineNo (LineNo); + } +}; + +class CIfrEqIdId : public CIfrObj, public CIfrOpHeader { +private: + EFI_IFR_EQ_ID_ID *mEqIdId; + +public: + CIfrEqIdId ( + IN UINT32 LineNo + ) : CIfrObj (EFI_IFR_EQ_ID_ID_OP, (CHAR8 **)&mEqIdId), + CIfrOpHeader (EFI_IFR_EQ_ID_ID_OP, &mEqIdId->Header) { + SetLineNo (LineNo); + mEqIdId->QuestionId1 = EFI_QUESTION_ID_INVALID; + mEqIdId->QuestionId2 = EFI_QUESTION_ID_INVALID; + } + + VOID SetQuestionId1 ( + IN EFI_QUESTION_ID QuestionId, + IN CHAR8 *VarIdStr, + IN UINT32 LineNo + ) { + if (QuestionId != EFI_QUESTION_ID_INVALID) { + mEqIdId->QuestionId1 = QuestionId; + } else { + gCFormPkg.AssignPending (VarIdStr, (VOID *)(&mEqIdId->QuestionId1), sizeof (EFI_QUESTION_ID), LineNo, NO_QST_REFED); + } + } + + VOID SetQuestionId2 ( + IN EFI_QUESTION_ID QuestionId, + IN CHAR8 *VarIdStr, + IN UINT32 LineNo + ) { + if (QuestionId != EFI_QUESTION_ID_INVALID) { + mEqIdId->QuestionId2 = QuestionId; + } else { + gCFormPkg.AssignPending (VarIdStr, (VOID *)(&mEqIdId->QuestionId2), sizeof (EFI_QUESTION_ID), LineNo, NO_QST_REFED); + } + } +}; + +class CIfrEqIdVal : public CIfrObj, public CIfrOpHeader { +private: + EFI_IFR_EQ_ID_VAL *mEqIdVal; + +public: + CIfrEqIdVal ( + IN UINT32 LineNo + ) : CIfrObj (EFI_IFR_EQ_ID_VAL_OP, (CHAR8 **)&mEqIdVal), + CIfrOpHeader (EFI_IFR_EQ_ID_VAL_OP, &mEqIdVal->Header) { + SetLineNo (LineNo); + mEqIdVal->QuestionId = EFI_QUESTION_ID_INVALID; + } + + VOID SetQuestionId ( + IN EFI_QUESTION_ID QuestionId, + IN CHAR8 *VarIdStr, + IN UINT32 LineNo + ) { + if (QuestionId != EFI_QUESTION_ID_INVALID) { + mEqIdVal->QuestionId = QuestionId; + } else { + gCFormPkg.AssignPending (VarIdStr, (VOID *)(&mEqIdVal->QuestionId), sizeof (EFI_QUESTION_ID), LineNo, NO_QST_REFED); + } + } + + VOID SetValue (IN UINT16 Value) { + mEqIdVal->Value = Value; + } +}; + +class CIfrEqIdList : public CIfrObj, public CIfrOpHeader { +private: + EFI_IFR_EQ_ID_LIST *mEqIdVList; + +public: + CIfrEqIdList ( + IN UINT32 LineNo + ) : CIfrObj (EFI_IFR_EQ_ID_LIST_OP, (CHAR8 **)&mEqIdVList, sizeof (EFI_IFR_EQ_ID_LIST), TRUE), + CIfrOpHeader (EFI_IFR_EQ_ID_LIST_OP, &mEqIdVList->Header) { + SetLineNo (LineNo); + mEqIdVList->QuestionId = EFI_QUESTION_ID_INVALID; + mEqIdVList->ListLength = 0; + mEqIdVList->ValueList[0] = 0; + } + + VOID UpdateIfrBuffer ( + ) { + _EMIT_PENDING_OBJ(); + mEqIdVList = (EFI_IFR_EQ_ID_LIST *) GetObjBinAddr(); + UpdateHeader (&mEqIdVList->Header); + } + + VOID SetQuestionId ( + IN EFI_QUESTION_ID QuestionId, + IN CHAR8 *VarIdStr, + IN UINT32 LineNo + ) { + if (QuestionId != EFI_QUESTION_ID_INVALID) { + mEqIdVList->QuestionId = QuestionId; + } else { + gCFormPkg.AssignPending (VarIdStr, (VOID *)(&mEqIdVList->QuestionId), sizeof (EFI_QUESTION_ID), LineNo, NO_QST_REFED); + } + } + + VOID SetListLength (IN UINT16 ListLength) { + mEqIdVList->ListLength = ListLength; + } + + VOID SetValueList (IN UINT16 Index, IN UINT16 Value) { + if (Index == 0) { + mEqIdVList->ValueList[0] = Value; + return; + } + + if (ExpendObjBin (sizeof (UINT16)) ==TRUE) { + IncLength (sizeof (UINT16)); + mEqIdVList->ValueList[Index] = Value; + } + } +}; + +class CIfrQuestionRef1 : public CIfrObj, public CIfrOpHeader { +private: + EFI_IFR_QUESTION_REF1 *mQuestionRef1; + +public: + CIfrQuestionRef1 ( + IN UINT32 LineNo + ) : CIfrObj (EFI_IFR_QUESTION_REF1_OP, (CHAR8 **)&mQuestionRef1), + CIfrOpHeader (EFI_IFR_QUESTION_REF1_OP, &mQuestionRef1->Header) { + SetLineNo (LineNo); + mQuestionRef1->QuestionId = EFI_QUESTION_ID_INVALID; + } + + VOID SetQuestionId ( + IN EFI_QUESTION_ID QuestionId, + IN CHAR8 *VarIdStr, + IN UINT32 LineNo + ) { + if (QuestionId != EFI_QUESTION_ID_INVALID) { + mQuestionRef1->QuestionId = QuestionId; + } else { + gCFormPkg.AssignPending (VarIdStr, (VOID *)(&mQuestionRef1->QuestionId), sizeof (EFI_QUESTION_ID), LineNo, NO_QST_REFED); + } + } +}; + +class CIfrQuestionRef2 : public CIfrObj, public CIfrOpHeader { +private: + EFI_IFR_QUESTION_REF2 *mQuestionRef2; + +public: + CIfrQuestionRef2 ( + IN UINT32 LineNo + ) : CIfrObj (EFI_IFR_QUESTION_REF2_OP, (CHAR8 **)&mQuestionRef2), + CIfrOpHeader (EFI_IFR_QUESTION_REF2_OP, &mQuestionRef2->Header) { + SetLineNo (LineNo); + } +}; + +class CIfrQuestionRef3 : public CIfrObj, public CIfrOpHeader { +private: + EFI_IFR_QUESTION_REF3 *mQuestionRef3; + +public: + CIfrQuestionRef3 ( + IN UINT32 LineNo + ) : CIfrObj (EFI_IFR_QUESTION_REF3_OP, (CHAR8 **)&mQuestionRef3), + CIfrOpHeader (EFI_IFR_QUESTION_REF3_OP, &mQuestionRef3->Header) { + SetLineNo (LineNo); + } +}; + +class CIfrQuestionRef3_2 : public CIfrObj, public CIfrOpHeader { +private: + EFI_IFR_QUESTION_REF3_2 *mQuestionRef3_2; + +public: + CIfrQuestionRef3_2 ( + IN UINT32 LineNo + ) : CIfrObj (EFI_IFR_QUESTION_REF3_OP, (CHAR8 **)&mQuestionRef3_2, sizeof (EFI_IFR_QUESTION_REF3_2)), + CIfrOpHeader (EFI_IFR_QUESTION_REF3_OP, &mQuestionRef3_2->Header, sizeof (EFI_IFR_QUESTION_REF3_2)) { + SetLineNo (LineNo); + mQuestionRef3_2->DevicePath = EFI_STRING_ID_INVALID; + } + + VOID SetDevicePath (IN EFI_STRING_ID DevicePath) { + mQuestionRef3_2->DevicePath = DevicePath; + } +}; + +class CIfrQuestionRef3_3 : public CIfrObj, public CIfrOpHeader { +private: + EFI_IFR_QUESTION_REF3_3 *mQuestionRef3_3; + +public: + CIfrQuestionRef3_3 ( + IN UINT32 LineNo + ) : CIfrObj (EFI_IFR_QUESTION_REF3_OP, (CHAR8 **)&mQuestionRef3_3, sizeof (EFI_IFR_QUESTION_REF3_3)), + CIfrOpHeader (EFI_IFR_QUESTION_REF3_OP, &mQuestionRef3_3->Header, sizeof (EFI_IFR_QUESTION_REF3_3)) { + SetLineNo (LineNo); + mQuestionRef3_3->DevicePath = EFI_STRING_ID_INVALID; + memset (&mQuestionRef3_3->Guid, 0, sizeof (EFI_GUID)); + } + + VOID SetDevicePath (IN EFI_STRING_ID DevicePath) { + mQuestionRef3_3->DevicePath = DevicePath; + } + + VOID SetGuid (IN EFI_GUID *Guid) { + mQuestionRef3_3->Guid = *Guid; + } +}; + +class CIfrRuleRef : public CIfrObj, public CIfrOpHeader { +private: + EFI_IFR_RULE_REF *mRuleRef; + +public: + CIfrRuleRef ( + IN UINT32 LineNo + ) : CIfrObj (EFI_IFR_RULE_REF_OP, (CHAR8 **)&mRuleRef), + CIfrOpHeader (EFI_IFR_RULE_REF_OP, &mRuleRef->Header) { + SetLineNo (LineNo); + mRuleRef->RuleId = EFI_RULE_ID_INVALID; + } + + VOID SetRuleId (IN UINT8 RuleId) { + mRuleRef->RuleId = RuleId; + } +}; + +class CIfrStringRef1 : public CIfrObj, public CIfrOpHeader { +private: + EFI_IFR_STRING_REF1 *mStringRef1; + +public: + CIfrStringRef1 ( + IN UINT32 LineNo + ) : CIfrObj (EFI_IFR_STRING_REF1_OP, (CHAR8 **)&mStringRef1), + CIfrOpHeader (EFI_IFR_STRING_REF1_OP, &mStringRef1->Header) { + SetLineNo (LineNo); + mStringRef1->StringId = EFI_STRING_ID_INVALID; + } + + VOID SetStringId (IN EFI_STRING_ID StringId) { + mStringRef1->StringId = StringId; + } +}; + +class CIfrStringRef2 : public CIfrObj, public CIfrOpHeader { +private: + EFI_IFR_STRING_REF2 *mStringRef2; + +public: + CIfrStringRef2 ( + IN UINT32 LineNo + ) : CIfrObj (EFI_IFR_STRING_REF2_OP, (CHAR8 **)&mStringRef2), + CIfrOpHeader (EFI_IFR_STRING_REF2_OP, &mStringRef2->Header) { + SetLineNo (LineNo); + } +}; + +class CIfrThis : public CIfrObj, public CIfrOpHeader { +private: + EFI_IFR_THIS *mThis; + +public: + CIfrThis ( + IN UINT32 LineNo + ) : CIfrObj (EFI_IFR_THIS_OP, (CHAR8 **)&mThis), + CIfrOpHeader (EFI_IFR_THIS_OP, &mThis->Header) { + SetLineNo (LineNo); + } +}; + +class CIfrUint8 : public CIfrObj, public CIfrOpHeader { +private: + EFI_IFR_UINT8 *mUint8; + +public: + CIfrUint8 ( + IN UINT32 LineNo + ) : CIfrObj (EFI_IFR_UINT8_OP, (CHAR8 **)&mUint8), + CIfrOpHeader (EFI_IFR_UINT8_OP, &mUint8->Header) { + SetLineNo (LineNo); + } + + VOID SetValue (IN UINT8 Value) { + mUint8->Value = Value; + } +}; + +class CIfrUint16 : public CIfrObj, public CIfrOpHeader { +private: + EFI_IFR_UINT16 *mUint16; + +public: + CIfrUint16 ( + IN UINT32 LineNo + ) : CIfrObj (EFI_IFR_UINT16_OP, (CHAR8 **)&mUint16), + CIfrOpHeader (EFI_IFR_UINT16_OP, &mUint16->Header) { + SetLineNo (LineNo); + } + + VOID SetValue (IN UINT16 Value) { + mUint16->Value = Value; + } +}; + +class CIfrUint32 : public CIfrObj, public CIfrOpHeader { +private: + EFI_IFR_UINT32 *mUint32; + +public: + CIfrUint32 ( + IN UINT32 LineNo + ) : CIfrObj (EFI_IFR_UINT32_OP, (CHAR8 **)&mUint32), + CIfrOpHeader (EFI_IFR_UINT32_OP, &mUint32->Header) { + SetLineNo (LineNo); + } + + VOID SetValue (IN UINT32 Value) { + mUint32->Value = Value; + } +}; + +class CIfrUint64 : public CIfrObj, public CIfrOpHeader { +private: + EFI_IFR_UINT64 *mUint64; + +public: + CIfrUint64 ( + IN UINT32 LineNo + ) : CIfrObj (EFI_IFR_UINT64_OP, (CHAR8 **)&mUint64), + CIfrOpHeader (EFI_IFR_UINT64_OP, &mUint64->Header) { + SetLineNo (LineNo); + } + + VOID SetValue (IN UINT64 Value) { + mUint64->Value = Value; + } +}; + +class CIfrTrue : public CIfrObj, public CIfrOpHeader { +private: + EFI_IFR_TRUE *mTrue; + +public: + CIfrTrue ( + IN UINT32 LineNo + ) : CIfrObj (EFI_IFR_TRUE_OP, (CHAR8 **)&mTrue), + CIfrOpHeader (EFI_IFR_TRUE_OP, &mTrue->Header) { + SetLineNo (LineNo); + } +}; + +class CIfrFalse : public CIfrObj, public CIfrOpHeader { +private: + EFI_IFR_FALSE *mFalse; + +public: + CIfrFalse ( + IN UINT32 LineNo + ) : CIfrObj (EFI_IFR_FALSE_OP, (CHAR8 **)&mFalse), + CIfrOpHeader (EFI_IFR_FALSE_OP, &mFalse->Header) { + SetLineNo (LineNo); + } +}; + +class CIfrOne : public CIfrObj, public CIfrOpHeader { +private: + EFI_IFR_ONE *mOne; + +public: + CIfrOne ( + IN UINT32 LineNo + ) : CIfrObj (EFI_IFR_ONE_OP, (CHAR8 **)&mOne), + CIfrOpHeader (EFI_IFR_ONE_OP, &mOne->Header) { + SetLineNo (LineNo); + } +}; + +class CIfrOnes : public CIfrObj, public CIfrOpHeader { +private: + EFI_IFR_ONES *mOnes; + +public: + CIfrOnes ( + IN UINT32 LineNo + ) : CIfrObj (EFI_IFR_ONES_OP, (CHAR8 **)&mOnes), + CIfrOpHeader (EFI_IFR_ONES_OP, &mOnes->Header) { + SetLineNo (LineNo); + } +}; + +class CIfrZero : public CIfrObj, public CIfrOpHeader { +private: + EFI_IFR_ZERO *mZero; + +public: + CIfrZero ( + IN UINT32 LineNo + ) : CIfrObj (EFI_IFR_ZERO_OP, (CHAR8 **)&mZero), + CIfrOpHeader (EFI_IFR_ZERO_OP, &mZero->Header) { + SetLineNo (LineNo); + } +}; + +class CIfrUndefined : public CIfrObj, public CIfrOpHeader { +private: + EFI_IFR_UNDEFINED *mUndefined; + +public: + CIfrUndefined ( + IN UINT32 LineNo + ) : CIfrObj (EFI_IFR_UNDEFINED_OP, (CHAR8 **)&mUndefined), + CIfrOpHeader (EFI_IFR_UNDEFINED_OP, &mUndefined->Header) { + SetLineNo (LineNo); + } +}; + +class CIfrVersion : public CIfrObj, public CIfrOpHeader { +private: + EFI_IFR_VERSION *mVersion; + +public: + CIfrVersion ( + IN UINT32 LineNo + ) : CIfrObj (EFI_IFR_VERSION_OP, (CHAR8 **)&mVersion), + CIfrOpHeader (EFI_IFR_VERSION_OP, &mVersion->Header) { + SetLineNo (LineNo); + } +}; + +class CIfrLength : public CIfrObj, public CIfrOpHeader { +private: + EFI_IFR_LENGTH *mLength; + +public: + CIfrLength ( + IN UINT32 LineNo + ) : CIfrObj (EFI_IFR_LENGTH_OP, (CHAR8 **)&mLength), + CIfrOpHeader (EFI_IFR_LENGTH_OP, &mLength->Header) { + SetLineNo (LineNo); + } +}; + +class CIfrNot : public CIfrObj, public CIfrOpHeader { +private: + EFI_IFR_NOT *mNot; + +public: + CIfrNot ( + IN UINT32 LineNo + ) : CIfrObj (EFI_IFR_NOT_OP, (CHAR8 **)&mNot), + CIfrOpHeader (EFI_IFR_NOT_OP, &mNot->Header) { + SetLineNo (LineNo); + } +}; + +class CIfrBitWiseNot : public CIfrObj, public CIfrOpHeader { +private: + EFI_IFR_BITWISE_NOT *mBitWise; + +public: + CIfrBitWiseNot ( + IN UINT32 LineNo + ) : CIfrObj (EFI_IFR_BITWISE_NOT_OP, (CHAR8 **)&mBitWise), + CIfrOpHeader (EFI_IFR_BITWISE_NOT_OP, &mBitWise->Header) { + SetLineNo (LineNo); + } +}; + +class CIfrToBoolean : public CIfrObj, public CIfrOpHeader { +private: + EFI_IFR_TO_BOOLEAN *mToBoolean; + +public: + CIfrToBoolean ( + IN UINT32 LineNo + ) : CIfrObj (EFI_IFR_TO_BOOLEAN_OP, (CHAR8 **)&mToBoolean), + CIfrOpHeader (EFI_IFR_TO_BOOLEAN_OP, &mToBoolean->Header) { + SetLineNo (LineNo); + } +}; + +class CIfrToString : public CIfrObj, public CIfrOpHeader { +private: + EFI_IFR_TO_STRING *mToString; + +public: + CIfrToString ( + IN UINT32 LineNo + ) : CIfrObj (EFI_IFR_TO_STRING_OP, (CHAR8 **)&mToString), + CIfrOpHeader (EFI_IFR_TO_STRING_OP, &mToString->Header) { + SetLineNo (LineNo); + } + + VOID SetFormat (IN UINT8 Format) { + mToString->Format = Format; + } +}; + +class CIfrToUint : public CIfrObj, public CIfrOpHeader { +private: + EFI_IFR_TO_UINT *mToUint; + +public: + CIfrToUint ( + IN UINT32 LineNo + ) : CIfrObj (EFI_IFR_TO_UINT_OP, (CHAR8 **)&mToUint), + CIfrOpHeader (EFI_IFR_TO_UINT_OP, &mToUint->Header) { + SetLineNo (LineNo); + } +}; + +class CIfrToUpper : public CIfrObj, public CIfrOpHeader { +private: + EFI_IFR_TO_UPPER *mToUpper; + +public: + CIfrToUpper ( + IN UINT32 LineNo + ) : CIfrObj (EFI_IFR_TO_UPPER_OP, (CHAR8 **)&mToUpper), + CIfrOpHeader (EFI_IFR_TO_UPPER_OP, &mToUpper->Header) { + SetLineNo (LineNo); + } +}; + +class CIfrToLower : public CIfrObj, public CIfrOpHeader { +private: + EFI_IFR_TO_LOWER *mToLower; + +public: + CIfrToLower ( + IN UINT32 LineNo + ) : CIfrObj (EFI_IFR_TO_LOWER_OP, (CHAR8 **)&mToLower), + CIfrOpHeader (EFI_IFR_TO_LOWER_OP, &mToLower->Header) { + SetLineNo (LineNo); + } +}; + +class CIfrAdd : public CIfrObj, public CIfrOpHeader { +private: + EFI_IFR_ADD *mAdd; + +public: + CIfrAdd ( + IN UINT32 LineNo + ) : CIfrObj (EFI_IFR_ADD_OP, (CHAR8 **)&mAdd), + CIfrOpHeader (EFI_IFR_ADD_OP, &mAdd->Header) { + SetLineNo (LineNo); + } +}; + +class CIfrBitWiseAnd : public CIfrObj, public CIfrOpHeader { +private: + EFI_IFR_BITWISE_AND *mBitWiseAnd; + +public: + CIfrBitWiseAnd ( + IN UINT32 LineNo + ) : CIfrObj (EFI_IFR_BITWISE_AND_OP, (CHAR8 **)&mBitWiseAnd), + CIfrOpHeader (EFI_IFR_BITWISE_AND_OP, &mBitWiseAnd->Header) { + SetLineNo(LineNo); + } +}; + +class CIfrBitWiseOr : public CIfrObj, public CIfrOpHeader { +private: + EFI_IFR_BITWISE_OR *mBitWiseOr; + +public: + CIfrBitWiseOr ( + IN UINT32 LineNo + ) : CIfrObj (EFI_IFR_BITWISE_OR_OP, (CHAR8 **)&mBitWiseOr), + CIfrOpHeader (EFI_IFR_BITWISE_OR_OP, &mBitWiseOr->Header) { + SetLineNo (LineNo); + } +}; + +class CIfrAnd : public CIfrObj, public CIfrOpHeader { +private: + EFI_IFR_AND *mAnd; + +public: + CIfrAnd ( + IN UINT32 LineNo + ) : CIfrObj (EFI_IFR_AND_OP, (CHAR8 **)&mAnd), + CIfrOpHeader (EFI_IFR_AND_OP, &mAnd->Header) { + SetLineNo (LineNo); + } +}; + +class CIfrCatenate : public CIfrObj, public CIfrOpHeader { +private: + EFI_IFR_CATENATE *mCatenate; + +public: + CIfrCatenate ( + IN UINT32 LineNo + ) : CIfrObj (EFI_IFR_CATENATE_OP, (CHAR8 **)&mCatenate), + CIfrOpHeader (EFI_IFR_CATENATE_OP, &mCatenate->Header) { + SetLineNo (LineNo); + } +}; + +class CIfrDivide : public CIfrObj, public CIfrOpHeader { +private: + EFI_IFR_DIVIDE *mDivide; + +public: + CIfrDivide ( + IN UINT32 LineNo + ) : CIfrObj (EFI_IFR_DIVIDE_OP, (CHAR8 **)&mDivide), + CIfrOpHeader (EFI_IFR_DIVIDE_OP, &mDivide->Header) { + SetLineNo (LineNo); + } +}; + +class CIfrEqual : public CIfrObj, public CIfrOpHeader { +private: + EFI_IFR_EQUAL *mEqual; + +public: + CIfrEqual ( + IN UINT32 LineNo + ) : CIfrObj (EFI_IFR_EQUAL_OP, (CHAR8 **)&mEqual), + CIfrOpHeader (EFI_IFR_EQUAL_OP, &mEqual->Header) { + SetLineNo (LineNo); + } +}; + +class CIfrGreaterEqual : public CIfrObj, public CIfrOpHeader { +private: + EFI_IFR_GREATER_EQUAL *mGreaterEqual; + +public: + CIfrGreaterEqual ( + IN UINT32 LineNo + ) : CIfrObj (EFI_IFR_GREATER_EQUAL_OP, (CHAR8 **)&mGreaterEqual), + CIfrOpHeader (EFI_IFR_GREATER_EQUAL_OP, &mGreaterEqual->Header) { + SetLineNo (LineNo); + } +}; + +class CIfrGreaterThan : public CIfrObj, public CIfrOpHeader { +private: + EFI_IFR_GREATER_THAN *mGreaterThan; + +public: + CIfrGreaterThan ( + IN UINT32 LineNo + ) : CIfrObj (EFI_IFR_GREATER_THAN_OP, (CHAR8 **)&mGreaterThan), + CIfrOpHeader (EFI_IFR_GREATER_THAN_OP, &mGreaterThan->Header) { + SetLineNo (LineNo); + } +}; + +class CIfrLessEqual : public CIfrObj, public CIfrOpHeader { +private: + EFI_IFR_LESS_EQUAL *mLessEqual; + +public: + CIfrLessEqual ( + IN UINT32 LineNo + ) : CIfrObj (EFI_IFR_LESS_EQUAL_OP, (CHAR8 **)&mLessEqual), + CIfrOpHeader (EFI_IFR_LESS_EQUAL_OP, &mLessEqual->Header) { + SetLineNo (LineNo); + } +}; + +class CIfrLessThan : public CIfrObj, public CIfrOpHeader { +private: + EFI_IFR_LESS_THAN *mLessThan; + +public: + CIfrLessThan ( + IN UINT32 LineNo + ) : CIfrObj (EFI_IFR_LESS_THAN_OP, (CHAR8 **)&mLessThan), + CIfrOpHeader (EFI_IFR_LESS_THAN_OP, &mLessThan->Header) { + SetLineNo (LineNo); + } +}; + +class CIfrMatch : public CIfrObj, public CIfrOpHeader { +private: + EFI_IFR_MATCH *mMatch; + +public: + CIfrMatch ( + IN UINT32 LineNo + ) : CIfrObj (EFI_IFR_MATCH_OP, (CHAR8 **)&mMatch), + CIfrOpHeader (EFI_IFR_MATCH_OP, &mMatch->Header) { + SetLineNo (LineNo); + } +}; + +class CIfrMultiply : public CIfrObj, public CIfrOpHeader { +private: + EFI_IFR_MULTIPLY *mMultiply; + +public: + CIfrMultiply ( + IN UINT32 LineNo + ) : CIfrObj (EFI_IFR_MULTIPLY_OP, (CHAR8 **)&mMultiply), + CIfrOpHeader (EFI_IFR_MULTIPLY_OP, &mMultiply->Header) { + SetLineNo (LineNo); + } +}; + +class CIfrModulo : public CIfrObj, public CIfrOpHeader { +private: + EFI_IFR_MODULO *mModulo; + +public: + CIfrModulo ( + IN UINT32 LineNo + ) : CIfrObj (EFI_IFR_MODULO_OP, (CHAR8 **)&mModulo), + CIfrOpHeader (EFI_IFR_MODULO_OP, &mModulo->Header) { + SetLineNo (LineNo); + } +}; + +class CIfrNotEqual : public CIfrObj, public CIfrOpHeader { +private: + EFI_IFR_NOT_EQUAL *mNotEqual; + +public: + CIfrNotEqual ( + IN UINT32 LineNo + ) : CIfrObj (EFI_IFR_NOT_EQUAL_OP, (CHAR8 **)&mNotEqual), + CIfrOpHeader (EFI_IFR_NOT_EQUAL_OP, &mNotEqual->Header) { + SetLineNo (LineNo); + } +}; + +class CIfrOr : public CIfrObj, public CIfrOpHeader { +private: + EFI_IFR_OR *mOr; + +public: + CIfrOr ( + IN UINT32 LineNo + ) : CIfrObj (EFI_IFR_OR_OP, (CHAR8 **)&mOr), + CIfrOpHeader (EFI_IFR_OR_OP, &mOr->Header) { + SetLineNo (LineNo); + } +}; + +class CIfrShiftLeft : public CIfrObj, public CIfrOpHeader { +private: + EFI_IFR_SHIFT_LEFT *mShiftLeft; + +public: + CIfrShiftLeft ( + IN UINT32 LineNo + ) : CIfrObj (EFI_IFR_SHIFT_LEFT_OP, (CHAR8 **)&mShiftLeft), + CIfrOpHeader (EFI_IFR_SHIFT_LEFT_OP, &mShiftLeft->Header) { + SetLineNo (LineNo); + } +}; + +class CIfrShiftRight : public CIfrObj, public CIfrOpHeader { +private: + EFI_IFR_SHIFT_RIGHT *mShiftRight; + +public: + CIfrShiftRight ( + IN UINT32 LineNo + ) : CIfrObj (EFI_IFR_SHIFT_RIGHT_OP, (CHAR8 **)&mShiftRight), + CIfrOpHeader (EFI_IFR_SHIFT_RIGHT_OP, &mShiftRight->Header) { + SetLineNo (LineNo); + } +}; + +class CIfrSubtract : public CIfrObj, public CIfrOpHeader { +private: + EFI_IFR_SUBTRACT *mSubtract; + +public: + CIfrSubtract ( + IN UINT32 LineNo + ) : CIfrObj (EFI_IFR_SUBTRACT_OP, (CHAR8 **)&mSubtract), + CIfrOpHeader (EFI_IFR_SUBTRACT_OP, &mSubtract->Header) { + SetLineNo (LineNo); + } +}; + +class CIfrConditional : public CIfrObj, public CIfrOpHeader { +private: + EFI_IFR_CONDITIONAL *mConditional; + +public: + CIfrConditional ( + IN UINT32 LineNo + ) : CIfrObj (EFI_IFR_CONDITIONAL_OP, (CHAR8 **)&mConditional), + CIfrOpHeader (EFI_IFR_CONDITIONAL_OP, &mConditional->Header) { + SetLineNo (LineNo); + } +}; + +class CIfrFind : public CIfrObj, public CIfrOpHeader { +private: + EFI_IFR_FIND *mFind; + +public: + CIfrFind ( + IN UINT32 LineNo + ) : CIfrObj (EFI_IFR_FIND_OP, (CHAR8 **)&mFind), + CIfrOpHeader (EFI_IFR_FIND_OP, &mFind->Header) { + SetLineNo (LineNo); + } + + VOID SetFormat (IN UINT8 Format) { + mFind->Format = Format; + } +}; + +class CIfrMid : public CIfrObj, public CIfrOpHeader { +private: + EFI_IFR_MID *mMid; + +public: + CIfrMid ( + IN UINT32 LineNo + ) : CIfrObj (EFI_IFR_MID_OP, (CHAR8 **)&mMid), + CIfrOpHeader (EFI_IFR_MID_OP, &mMid->Header) { + SetLineNo (LineNo); + } +}; + +class CIfrToken : public CIfrObj, public CIfrOpHeader { +private: + EFI_IFR_TOKEN *mToken; + +public: + CIfrToken ( + IN UINT32 LineNo + ) : CIfrObj (EFI_IFR_TOKEN_OP, (CHAR8 **)&mToken), + CIfrOpHeader (EFI_IFR_TOKEN_OP, &mToken->Header) { + SetLineNo (LineNo); + } +}; + +class CIfrSpan : public CIfrObj, public CIfrOpHeader { +private: + EFI_IFR_SPAN *mSpan; + +public: + CIfrSpan ( + IN UINT32 LineNo + ) : CIfrObj (EFI_IFR_SPAN_OP, (CHAR8 **)&mSpan), + CIfrOpHeader (EFI_IFR_SPAN_OP, &mSpan->Header) { + SetLineNo (LineNo); + mSpan->Flags = EFI_IFR_FLAGS_FIRST_MATCHING; + } + + EFI_VFR_RETURN_CODE SetFlags (IN UINT8 LFlags) { + if (_IS_EQUAL (LFlags, EFI_IFR_FLAGS_FIRST_MATCHING)) { + mSpan->Flags |= EFI_IFR_FLAGS_FIRST_MATCHING; + } else if (_FLAG_TEST_AND_CLEAR (LFlags, EFI_IFR_FLAGS_FIRST_NON_MATCHING)) { + mSpan->Flags |= EFI_IFR_FLAGS_FIRST_NON_MATCHING; + } + + return _FLAGS_ZERO (LFlags) ? VFR_RETURN_SUCCESS : VFR_RETURN_FLAGS_UNSUPPORTED; + } +}; + +#endif diff --git a/BaseTools/Source/C/VfrCompile/VfrSyntax.g b/BaseTools/Source/C/VfrCompile/VfrSyntax.g new file mode 100644 index 0000000000..2aee307781 --- /dev/null +++ b/BaseTools/Source/C/VfrCompile/VfrSyntax.g @@ -0,0 +1,3893 @@ +/*++ +Copyright (c) 2004 - 2008, 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: + VfrSyntax.g + +Abstract: + +--*/ + +#header<< + +#include "EfiVfr.h" +#include "VfrFormPkg.h" +#include "VfrError.h" +#include "VfrUtilityLib.h" +#include "AToken.h" +#include "ATokPtr.h" +>> + +<< +#include "stdio.h" +#include "PBlackBox.h" +#include "DLexerBase.h" +#include "VfrLexer.h" +#include "AToken.h" + +#define GET_LINENO(Obj) ((Obj)->getLine()) +#define SET_LINE_INFO(Obj, L) {(Obj).SetLineNo((L)->getLine());} while (0) +#define CRT_END_OP(Obj) {CIfrEnd EObj; if (Obj != NULL) EObj.SetLineNo ((Obj)->getLine());} while (0) + +typedef ANTLRCommonToken ANTLRToken; + +class CVfrDLGLexer : public VfrLexer +{ +public: + CVfrDLGLexer (DLGFileInput *F) : VfrLexer (F) {}; + INT32 errstd (char *Text) + { + printf ("unrecognized input '%s'\n", Text); + } +}; + +UINT8 +VfrParserStart ( + IN FILE *File, + IN BOOLEAN CompatibleMode + ) +{ + ParserBlackBox VfrParser(File); + VfrParser.parser()->SetCompatibleMode (CompatibleMode); + return VfrParser.parser()->vfrProgram(); +} +>> + +// +// 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 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 over 'extern' in any included .H file +// +#token "extern" << skip (); mode (CPP_COMMENT); >> + +// +// 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 FormPkgType("formpkgtype") "formpkgtype" +#token OpenBrace("{") "\{" +#token CloseBrace("}") "\}" +#token OpenParen("(") "\(" +#token CloseParen(")") "\)" +#token OpenBracket("[") "\[" +#token CloseBracket("]") "\]" + +#token LineDefinition "#line\ [0-9]+\ \"~[\"]+\"[\ \t]*\n" << gCVfrErrorHandle.ParseFileScopeRecord (begexpr (), line ()); skip (); newline (); >> +#token DevicePath("devicepath") "devicepath" +#token FormSet("formset") "formset" +#token FormSetId("formsetid") "formsetid" +#token EndFormSet("endformset") "endformset" +#token Title("title") "title" +#token FormId("formid") "formid" +#token OneOf("oneof") "oneof" +#token EndOneOf("endoneof") "endoneof" +#token Prompt("prompt") "prompt" +#token OrderedList("orderedlist") "orderedlist" +#token MaxContainers("maxcontainers") "maxcontainers" +#token EndList("endlist") "endlist" +#token EndForm("endform") "endform" +#token Form("form") "form" +#token Subtitle("subtitle") "subtitle" +#token Help("help") "help" +#token Text("text") "text" +#token Option("option") "option" +#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 GrayOutIf("grayoutif") "grayoutif" +#token Label("label") "label" +#token Timeout("timeout") "timeout" +#token Inventory("inventory") "inventory" +#token NonNvDataMap("_NON_NV_DATA_MAP") "_NON_NV_DATA_MAP" +#token Struct("struct") "struct" +#token Boolean("BOOLEAN") "BOOLEAN" +#token Uint64("UINT64") "UINT64" +#token Uint32("UINT32") "UINT32" +#token Uint16("UINT16") "UINT16" +#token Char16("CHAR16") "CHAR16" +#token Uint8("UINT8") "UINT8" +#token Uuid("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 DisableIf("disableif") "disableif" +#token Hidden("hidden") "hidden" +#token Goto("goto") "goto" +#token FormSetGuid("formsetguid") "formsetguid" +#token InconsistentIf("inconsistentif") "inconsistentif" +#token NoSubmitIf("nosubmitif") "nosubmitif" +#token EndIf("endif") "endif" +#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 ReadOnlyFlag("READ_ONLY") "READ_ONLY" +#token OptionOnlyFlag("OPTIONS_ONLY") "OPTIONS_ONLY" +#token Class("class") "class" +#token Subclass("subclass") "subclass" +#token ClassGuid("classguid") "classguid" +#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 Name("name") "name" + +#token VarId("varid") "varid" +#token Question("question") "question" +#token QuestionId("questionid") "questionid" +#token Image("image") "image" +#token Locked("locked") "locked" +#token Rule("rule") "rule" +#token EndRule("endrule") "endrule" +#token Value("value") "value" +#token ResetButton("resetbutton") "resetbutton" +#token EndResetButton("endresetbutton") "endresetbutton" +#token DefaultStore("defaultstore") "defaultstore" +#token Attribute("attribute") "attribute" +#token Varstore("varstore") "varstore" +#token Efivarstore("efivarstore") "efivarstore" +#token VarSize("varsize") "varsize" +#token NameValueVarStore("namevaluevarstore") "namevaluevarstore" +#token Action("action") "action" +#token Config("config") "config" +#token EndAction("endaction") "endaction" +#token Refresh("refresh") "refresh" +#token Interval("interval") "interval" +#token VarstoreDevice("varstoredevice") "varstoredevice" +// +// 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" + +// +// This is the overall definition of a VFR form definition script. +// + +vfrProgram > [UINT8 Return] : + << + mParserStatus = 0; + mConstantOnlyInExpression = FALSE; + >> + ( + vfrPragmaPackDefinition + | vfrDataStructDefinition + )* + vfrFormSetDefinition + << $Return = mParserStatus; >> + ; + +pragmaPackShowDef : + L:"show" << gCVfrVarDataTypeDB.Pack (L->getLine(), VFR_PACK_SHOW); >> + ; + +pragmaPackStackDef : + << + UINT32 LineNum; + UINT8 PackAction; + CHAR8 *Identifier = NULL; + UINT32 PackNumber = DEFAULT_PACK_ALIGN; + >> + ( + L1:"push" << LineNum = L1->getLine(); PackAction = VFR_PACK_PUSH; >> + | L2:"pop" << LineNum = L2->getLine(); PackAction = VFR_PACK_POP; >> + ) + { + "," ID:StringIdentifier << Identifier = ID->getText(); >> + } + { + "," N:Number << PackAction |= VFR_PACK_ASSIGN; PackNumber = _STOU32(N->getText()); >> + } + << gCVfrVarDataTypeDB.Pack (LineNum, PackAction, Identifier, PackNumber); >> + ; + +pragmaPackNumber : + << + UINT32 LineNum; + UINT32 PackNumber = DEFAULT_PACK_ALIGN; + >> + N:Number << LineNum = N->getLine(); PackNumber = _STOU32(N->getText()); >> + << gCVfrVarDataTypeDB.Pack (LineNum, VFR_PACK_ASSIGN, NULL, PackNumber); >> + ; + +vfrPragmaPackDefinition : + "\#pragma" "pack" "\(" + { + pragmaPackShowDef + | pragmaPackStackDef + | pragmaPackNumber + } + "\)" + ; + +vfrDataStructDefinition : + { TypeDef } Struct << gCVfrVarDataTypeDB.DeclareDataTypeBegin (); >> + { NonNvDataMap } + { + N1:StringIdentifier << _PCATCH(gCVfrVarDataTypeDB.SetNewTypeName (N1->getText()), N1); >> + } + OpenBrace + vfrDataStructFields + CloseBrace + { + N2:StringIdentifier << _PCATCH(gCVfrVarDataTypeDB.SetNewTypeName (N2->getText()), N2); >> + } + ";" << gCVfrVarDataTypeDB.DeclareDataTypeEnd (); >> + ; + +vfrDataStructFields : + ( + dataStructField64 | + dataStructField32 | + dataStructField16 | + dataStructField8 | + dataStructFieldBool | + dataStructFieldString | + dataStructFieldDate | + dataStructFieldTime | + dataStructFieldUser + )* + ; + +dataStructField64 : + << UINT32 ArrayNum = 0; >> + "UINT64" + N:StringIdentifier + { + OpenBracket I:Number CloseBracket << ArrayNum = _STOU32(I->getText()); >> + } + ";" << _PCATCH(gCVfrVarDataTypeDB.DataTypeAddField (N->getText(), "UINT64", ArrayNum), N); >> + ; + +dataStructField32 : + << UINT32 ArrayNum = 0; >> + "UINT32" + N:StringIdentifier + { + OpenBracket I:Number CloseBracket << ArrayNum = _STOU32(I->getText()); >> + } + ";" << _PCATCH(gCVfrVarDataTypeDB.DataTypeAddField (N->getText(), "UINT32", ArrayNum), N); >> + ; + +dataStructField16 : + << UINT32 ArrayNum = 0; >> + ("UINT16" | "CHAR16") + N:StringIdentifier + { + OpenBracket I:Number CloseBracket << ArrayNum = _STOU32(I->getText()); >> + } + ";" << _PCATCH(gCVfrVarDataTypeDB.DataTypeAddField (N->getText(), "UINT16", ArrayNum), N); >> + ; + +dataStructField8 : + << UINT32 ArrayNum = 0; >> + "UINT8" + N:StringIdentifier + { + OpenBracket I:Number CloseBracket << ArrayNum = _STOU32(I->getText()); >> + } + ";" << _PCATCH(gCVfrVarDataTypeDB.DataTypeAddField (N->getText(), "UINT8", ArrayNum), N); >> + ; + +dataStructFieldBool : + << UINT32 ArrayNum = 0; >> + "BOOLEAN" + N:StringIdentifier + { + OpenBracket I:Number CloseBracket << ArrayNum = _STOU32(I->getText()); >> + } + ";" << _PCATCH(gCVfrVarDataTypeDB.DataTypeAddField (N->getText(), "BOOLEAN", ArrayNum), N); >> + ; + +dataStructFieldString : + << UINT32 ArrayNum = 0; >> + "EFI_STRING_ID" + N:StringIdentifier + { + OpenBracket I:Number CloseBracket << ArrayNum = _STOU32(I->getText()); >> + } + ";" << _PCATCH(gCVfrVarDataTypeDB.DataTypeAddField (N->getText(), "EFI_STRING_ID", ArrayNum), N); >> + ; + +dataStructFieldDate : + << UINT32 ArrayNum = 0; >> + "EFI_HII_DATE" + N:StringIdentifier + { + OpenBracket I:Number CloseBracket << ArrayNum = _STOU32(I->getText()); >> + } + ";" << _PCATCH(gCVfrVarDataTypeDB.DataTypeAddField (N->getText(), "EFI_HII_DATE", ArrayNum), N); >> + ; + +dataStructFieldTime : + << UINT32 ArrayNum = 0; >> + "EFI_HII_TIME" + N:StringIdentifier + { + OpenBracket I:Number CloseBracket << ArrayNum = _STOU32(I->getText()); >> + } + ";" << _PCATCH(gCVfrVarDataTypeDB.DataTypeAddField (N->getText(), "EFI_HII_TIME", ArrayNum), N); >> + ; + +dataStructFieldUser : + << UINT32 ArrayNum = 0; >> + T:StringIdentifier + N:StringIdentifier + { + OpenBracket I:Number CloseBracket << ArrayNum = _STOU32(I->getText()); >> + } + ";" << _PCATCH(gCVfrVarDataTypeDB.DataTypeAddField (N->getText(), T->getText(), ArrayNum), T); >> + ; + +//***************************************************************************** +// +// the syntax of GUID definition +// +guidSubDefinition [EFI_GUID &Guid] : + G4:Number "," G5:Number "," G6:Number "," G7:Number "," G8:Number "," G9:Number "," G10:Number "," G11:Number + << + Guid.Data4[0] = _STOU8(G4->getText()); + Guid.Data4[1] = _STOU8(G5->getText()); + Guid.Data4[2] = _STOU8(G6->getText()); + Guid.Data4[3] = _STOU8(G7->getText()); + Guid.Data4[4] = _STOU8(G8->getText()); + Guid.Data4[5] = _STOU8(G9->getText()); + Guid.Data4[6] = _STOU8(G10->getText()); + Guid.Data4[7] = _STOU8(G11->getText()); + >> + ; + +guidDefinition [EFI_GUID &Guid] : + OpenBrace + G1:Number "," G2:Number "," G3:Number "," + << + Guid.Data1 = _STOU32 (G1->getText()); + Guid.Data2 = _STOU16 (G2->getText()); + Guid.Data3 = _STOU16 (G3->getText()); + >> + ( + OpenBrace guidSubDefinition[Guid] CloseBrace + | guidSubDefinition[Guid] + ) + CloseBrace + ; + +//***************************************************************************** +// +// the syntax of form set definition +// +vfrFormSetDefinition : + << + EFI_GUID Guid; + EFI_GUID DefaultClassGuid = EFI_HII_PLATFORM_SETUP_FORMSET_GUID; + EFI_GUID ClassGuid1, ClassGuid2, ClassGuid3; + UINT8 ClassGuidNum = 0; + CIfrFormSet *FSObj = NULL; + UINT16 C, SC; + >> + L:FormSet + Uuid "=" guidDefinition[Guid] "," + Title "=" "STRING_TOKEN" "\(" S1:Number "\)" "," + Help "=" "STRING_TOKEN" "\(" S2:Number "\)" "," + { + ClassGuid "=" guidDefinition[ClassGuid1] << ++ClassGuidNum; >> + { + "\|" guidDefinition[ClassGuid2] << ++ClassGuidNum; >> + } + { + "\|" guidDefinition[ClassGuid3] << ++ClassGuidNum; >> + } + "," + } + << + switch (ClassGuidNum) { + case 0: + FSObj = new CIfrFormSet(sizeof(EFI_IFR_FORM_SET)); + FSObj->SetClassGuid(&DefaultClassGuid); + break; + case 1: + FSObj = new CIfrFormSet(sizeof(EFI_IFR_FORM_SET)); + FSObj->SetClassGuid(&ClassGuid1); + break; + case 2: + FSObj = new CIfrFormSet(sizeof(EFI_IFR_FORM_SET) + sizeof(EFI_GUID)); + FSObj->SetClassGuid(&ClassGuid1); + FSObj->SetClassGuid(&ClassGuid2); + break; + default: + FSObj = new CIfrFormSet(sizeof(EFI_IFR_FORM_SET) + 2 * sizeof(EFI_GUID)); + FSObj->SetClassGuid(&ClassGuid1); + FSObj->SetClassGuid(&ClassGuid2); + FSObj->SetClassGuid(&ClassGuid3); + break; + } + + SET_LINE_INFO (*FSObj, L); + FSObj->SetGuid (&Guid); + // + // for framework vfr to store formset guid used by varstore and efivarstore + // + if (mCompatibleMode) { + memcpy (&mFormsetGuid, &Guid, sizeof (EFI_GUID)); + } + FSObj->SetFormSetTitle (_STOSID(S1->getText())); + FSObj->SetHelp (_STOSID(S2->getText())); + >> + { + FC:Class "=" classDefinition[C] "," << {CIfrClass CObj;SET_LINE_INFO (CObj, FC); CObj.SetClass(C);} >> + } + { + FSC:Subclass "=" subclassDefinition[SC] "," << {CIfrSubClass SCObj; SET_LINE_INFO (SCObj, FSC); SCObj.SetSubClass(SC);} >> + } + << + _DeclareStandardDefaultStorage (GET_LINENO (L)); + >> + vfrFormSetList + E:EndFormSet << + if (mCompatibleMode) { + // + // declare all undefined varstore and efivarstore + // + _DeclareDefaultFrameworkVarStore (GET_LINENO(E)); + } + CRT_END_OP (E); if (FSObj != NULL) delete FSObj; + >> + ";" + ; + +vfrFormSetList : + ( + vfrFormDefinition | + vfrStatementImage | + vfrStatementVarStoreLinear | + vfrStatementVarStoreEfi | + vfrStatementVarStoreNameValue | + vfrStatementDefaultStore | + vfrStatementDisableIfFormSet + )* + ; + +vfrStatementDefaultStore : + << UINT16 DefaultId = EFI_HII_DEFAULT_CLASS_STANDARD; >> + D:DefaultStore N:StringIdentifier "," + Prompt "=" "STRING_TOKEN" "\(" S:Number "\)" + { + "," Attribute "=" A:Number << DefaultId = _STOU16(A->getText()); >> + } + << + if (mCVfrDefaultStore.DefaultIdRegistered (DefaultId) == FALSE) { + CIfrDefaultStore DSObj; + _PCATCH(mCVfrDefaultStore.RegisterDefaultStore (DSObj.GetObjBinAddr(), N->getText(), _STOSID(S->getText()), DefaultId)), D->getLine(); + DSObj.SetLineNo(D->getLine()); + DSObj.SetDefaultName (_STOSID(S->getText())); + DSObj.SetDefaultId (DefaultId); + } else { + _PCATCH(mCVfrDefaultStore.ReRegisterDefaultStoreById (DefaultId, N->getText(), _STOSID(S->getText()))), D->getLine(); + } + >> + ";" + ; + +vfrStatementVarStoreLinear : + << + EFI_GUID Guid; + CIfrVarStore VSObj; + CHAR8 *TypeName; + CHAR8 *StoreName; + UINT32 LineNum; + EFI_VARSTORE_ID VarStoreId = EFI_VARSTORE_ID_INVALID; + UINT32 Size; + >> + V:Varstore << VSObj.SetLineNo(V->getLine()); >> + ( + TN:StringIdentifier "," << TypeName = TN->getText(); LineNum = TN->getLine(); >> + | U8:"UINT8" "," << TypeName = "UINT8"; LineNum = U8->getLine(); >> + | U16:"UINT16" "," << TypeName = "UINT16"; LineNum = U16->getLine(); >> + | U32:"UINT32" "," << TypeName = "UINT32"; LineNum = U32->getLine(); >> + | U64:"UINT64" "," << TypeName = "UINT64"; LineNum = U64->getLine(); >> + | D:"EFI_HII_DATE" "," << TypeName = "EFI_HII_DATE"; LineNum = D->getLine(); >> + | T:"EFI_HII_TIME" "," << TypeName = "EFI_HII_TIME"; LineNum = T->getLine(); >> + ) + { Key "=" FID:Number "," << // Key is used to assign Varid in Framework VFR but no use in UEFI2.1 VFR + if (mCompatibleMode) { + VarStoreId = _STOU16(FID->getText()); + } + >> + } + { + VarId "=" ID:Number "," << + _PCATCH( + (INTN)(VarStoreId = _STOU16(ID->getText())) != 0, + (INTN)TRUE, + ID, + "varid 0 is not allowed." + ); + >> + } + Name "=" SN:StringIdentifier "," + Uuid "=" guidDefinition[Guid] + << + if (mCompatibleMode) { + StoreName = TypeName; + } else { + StoreName = SN->getText(); + } + _PCATCH(mCVfrDataStorage.DeclareBufferVarStore ( + StoreName, + &Guid, + &gCVfrVarDataTypeDB, + TypeName, + VarStoreId + ), LineNum); + >> + << + VSObj.SetGuid (&Guid); + _PCATCH(mCVfrDataStorage.GetVarStoreId(StoreName, &VarStoreId), SN); + VSObj.SetVarStoreId (VarStoreId); + _PCATCH(gCVfrVarDataTypeDB.GetDataTypeSize(TypeName, &Size), LineNum); + VSObj.SetSize (Size); + VSObj.SetName (StoreName); + >> + ";" + ; + +vfrStatementVarStoreEfi : + << + EFI_GUID Guid; + CIfrVarStoreEfi VSEObj; + EFI_VARSTORE_ID VarStoreId; + UINT32 Attr = 0; + >> + E:Efivarstore << VSEObj.SetLineNo(E->getLine()); >> + SN:StringIdentifier "," + Attribute "=" vfrVarStoreEfiAttr[Attr] ( "\|" vfrVarStoreEfiAttr[Attr] )* "," + << VSEObj.SetAttributes (Attr); >> + Name "=" "STRING_TOKEN" "\(" VN:Number "\)" "," + VarSize "=" N:Number "," + Uuid "=" guidDefinition[Guid] << mCVfrDataStorage.DeclareEfiVarStore (SN->getText(), &Guid, _STOSID(VN->getText()), _STOU32(N->getText())); >> + << + VSEObj.SetGuid (&Guid); + _PCATCH(mCVfrDataStorage.GetVarStoreId(SN->getText(), &VarStoreId), SN); + VSEObj.SetVarStoreId (VarStoreId); + >> + ";" + ; + +vfrVarStoreEfiAttr [UINT32 & Attr] : + N:Number << $Attr |= _STOU32(N->getText()); >> + ; + +vfrStatementVarStoreNameValue : + << + EFI_GUID Guid; + CIfrVarStoreNameValue VSNVObj; + EFI_VARSTORE_ID VarStoreId; + >> + L:NameValueVarStore << VSNVObj.SetLineNo(L->getLine()); >> + SN:StringIdentifier "," << _PCATCH(mCVfrDataStorage.DeclareNameVarStoreBegin (SN->getText()), SN); >> + ( + Name "=" "STRING_TOKEN" "\(" N:Number "\)" "," << _PCATCH(mCVfrDataStorage.NameTableAddItem (_STOSID(N->getText())), SN); >> + )+ + Uuid "=" guidDefinition[Guid] << _PCATCH(mCVfrDataStorage.DeclareNameVarStoreEnd (&Guid), SN); >> + << + VSNVObj.SetGuid (&Guid); + _PCATCH(mCVfrDataStorage.GetVarStoreId(SN->getText(), &VarStoreId), SN); + VSNVObj.SetVarStoreId (VarStoreId); + >> + ";" + ; + +// +// keep classDeinition and validClassNames for compatibility but not generate +// any IFR object +// +classDefinition[UINT16 & Class] : + << $Class = 0; >> + validClassNames[$Class] ( "\|" validClassNames[$Class] )* + ; + +validClassNames[UINT16 & Class] : + ClassNonDevice << $Class |= EFI_NON_DEVICE_CLASS; >> + | ClassDiskDevice << $Class |= EFI_DISK_DEVICE_CLASS; >> + | ClassVideoDevice << $Class |= EFI_VIDEO_DEVICE_CLASS; >> + | ClassNetworkDevice << $Class |= EFI_NETWORK_DEVICE_CLASS; >> + | ClassInputDevice << $Class |= EFI_INPUT_DEVICE_CLASS; >> + | ClassOnBoardDevice << $Class |= EFI_ON_BOARD_DEVICE_CLASS; >> + | ClassOtherDevice << $Class |= EFI_OTHER_DEVICE_CLASS; >> + | N:Number << $Class |= _STOU16(N->getText()); >> + ; + +subclassDefinition[UINT16 & SubClass] : + << $SubClass = 0; >> + SubclassSetupApplication << $SubClass |= EFI_SETUP_APPLICATION_SUBCLASS; >> + | SubclassGeneralApplication << $SubClass |= EFI_GENERAL_APPLICATION_SUBCLASS; >> + | SubclassFrontPage << $SubClass |= EFI_FRONT_PAGE_SUBCLASS; >> + | SubclassSingleUse << $SubClass |= EFI_SINGLE_USE_SUBCLASS; >> + | N:Number << $SubClass |= _STOU16(N->getText()); >> + ; + +vfrStatementDisableIfFormSet : + << + CIfrDisableIf DIObj; + mConstantOnlyInExpression = TRUE; + >> + D:DisableIf << DIObj.SetLineNo(D->getLine()); >> + vfrStatementExpression[0] ";" << mConstantOnlyInExpression = FALSE; >> + vfrFormSetList + E:EndIf << CRT_END_OP (E); >> + ";" + ; + +//***************************************************************************** +// +// the syntax of question header and statement header +// +vfrStatementHeader[CIfrStatementHeader *SHObj] : + Prompt "=" "STRING_TOKEN" "\(" S1:Number "\)" "," << $SHObj->SetPrompt (_STOSID(S1->getText())); >> + Help "=" "STRING_TOKEN" "\(" S2:Number "\)" << $SHObj->SetHelp (_STOSID(S2->getText())); >> + ; + +vfrQuestionHeader[CIfrQuestionHeader & QHObj, EFI_QUESION_TYPE QType = QUESTION_NORMAL]: + << + EFI_VARSTORE_INFO Info; + EFI_QUESTION_ID QId = EFI_QUESTION_ID_INVALID; + CHAR8 *QName = NULL; + CHAR8 *VarIdStr = NULL; + >> + { + Name "=" QN:StringIdentifier "," << + QName = QN->getText(); + _PCATCH(mCVfrQuestionDB.FindQuestion (QName), VFR_RETURN_UNDEFINED, QN, "has already been used please used anther name"); + >> + } + { V:VarId "=" vfrStorageVarId[Info, VarIdStr] "," } + { + QuestionId "=" ID:Number "," << + QId = _STOQID(ID->getText()); + _PCATCH(mCVfrQuestionDB.FindQuestion (QId), VFR_RETURN_UNDEFINED, ID, "has already been used please assign another number"); + >> + } + << + switch (QType) { + case QUESTION_NORMAL: + mCVfrQuestionDB.RegisterQuestion (QName, VarIdStr, QId); + break; + case QUESTION_DATE: + mCVfrQuestionDB.RegisterNewDateQuestion (QName, VarIdStr, QId); + break; + case QUESTION_TIME: + mCVfrQuestionDB.RegisterNewTimeQuestion (QName, VarIdStr, QId); + break; + default: + _PCATCH(VFR_RETURN_FATAL_ERROR); + } + $QHObj.SetQuestionId (QId); + $QHObj.SetVarStoreInfo (&Info); + >> + vfrStatementHeader[&$QHObj] + << _SAVE_CURRQEST_VARINFO (Info); >> + << if (VarIdStr != NULL) delete VarIdStr; >> + ; + +vfrQuestionHeaderWithNoStorage[CIfrQuestionHeader *QHObj] : + << + EFI_QUESTION_ID QId = EFI_QUESTION_ID_INVALID; + CHAR8 *QName = NULL; + >> + { + Name "=" QN:StringIdentifier "," << + QName = QN->getText(); + _PCATCH(mCVfrQuestionDB.FindQuestion (QName), VFR_RETURN_UNDEFINED, QN, "has already been used please used anther name"); + >> + } + { + QuestionId "=" ID:Number "," << + QId = _STOQID(ID->getText()); + _PCATCH(mCVfrQuestionDB.FindQuestion (QId), VFR_RETURN_UNDEFINED, ID, "redefined quesiont ID"); + >> + } + << + mCVfrQuestionDB.RegisterQuestion (QName, NULL, QId); + $QHObj->SetQuestionId (QId); + >> + vfrStatementHeader[$QHObj] + ; + +questionheaderFlagsField[UINT8 & Flags] : + ReadOnlyFlag << $Flags |= 0x01; >> + | InteractiveFlag << $Flags |= 0x04; >> + | ResetRequiredFlag << $Flags |= 0x10; >> + | OptionOnlyFlag << $Flags |= 0x80; >> + | NVAccessFlag + | LateCheckFlag + ; + +vfrStorageVarId[EFI_VARSTORE_INFO & Info, CHAR8 *&QuestVarIdStr] : + << + UINT32 Idx; + UINT32 LineNo; + EFI_VFR_VARSTORE_TYPE VarStoreType = EFI_VFR_VARSTORE_INVALID; + CHAR8 *VarIdStr = NULL; + CHAR8 *VarStr = NULL; + CHAR8 *SName = NULL; + CHAR8 *TName = NULL; + EFI_VFR_RETURN_CODE VfrReturnCode = VFR_RETURN_SUCCESS; + EFI_IFR_TYPE_VALUE Dummy = gZeroEfiIfrTypeValue; + >> + ( + SN1:StringIdentifier << SName = SN1->getText(); _STRCAT(&VarIdStr, SN1->getText()); >> + OpenBracket I1:Number CloseBracket << + Idx = _STOU32(I1->getText()); + _STRCAT(&VarIdStr, "["); + _STRCAT(&VarIdStr, I1->getText()); + _STRCAT(&VarIdStr, "]"); + >> + << + VfrReturnCode = mCVfrDataStorage.GetVarStoreType (SName, VarStoreType); + if (mCompatibleMode && VfrReturnCode == VFR_RETURN_UNDEFINED) { + mCVfrDataStorage.DeclareBufferVarStore ( + SName, + &mFormsetGuid, + &gCVfrVarDataTypeDB, + SName, + EFI_VARSTORE_ID_INVALID, + FALSE + ); + VfrReturnCode = mCVfrDataStorage.GetVarStoreType (SName, VarStoreType); + } + _PCATCH(VfrReturnCode, SN1); + _PCATCH(mCVfrDataStorage.GetVarStoreId (SName, &$Info.mVarStoreId), SN1); + _PCATCH(mCVfrDataStorage.GetNameVarStoreInfo (&$Info, Idx), SN1); + >> + ) + | + ( + SN2:StringIdentifier << SName = SN2->getText(); _STRCAT(&VarIdStr, SName); >> + << + VfrReturnCode = mCVfrDataStorage.GetVarStoreType (SName, VarStoreType); + if (mCompatibleMode && VfrReturnCode == VFR_RETURN_UNDEFINED) { + mCVfrDataStorage.DeclareBufferVarStore ( + SName, + &mFormsetGuid, + &gCVfrVarDataTypeDB, + SName, + EFI_VARSTORE_ID_INVALID, + FALSE + ); + VfrReturnCode = mCVfrDataStorage.GetVarStoreType (SName, VarStoreType); + } + _PCATCH(VfrReturnCode, SN2); + _PCATCH(mCVfrDataStorage.GetVarStoreId (SName, &$Info.mVarStoreId), SN2); + if (VarStoreType == EFI_VFR_VARSTORE_BUFFER) { + _PCATCH(mCVfrDataStorage.GetBufferVarStoreDataTypeName(SName, &TName), SN2); + _STRCAT(&VarStr, TName); + } + >> + + ( + "." << + _PCATCH(((VarStoreType != EFI_VFR_VARSTORE_BUFFER) ? VFR_RETURN_EFIVARSTORE_USE_ERROR : VFR_RETURN_SUCCESS), SN2); + _STRCAT(&VarIdStr, "."); _STRCAT(&VarStr, "."); + >> + SF:StringIdentifier << _STRCAT(&VarIdStr, SF->getText()); _STRCAT(&VarStr, SF->getText()); >> + { + OpenBracket I2:Number CloseBracket << + Idx = _STOU32(I2->getText()); + if (mCompatibleMode) Idx --; + if (Idx > 0) { + // + // Idx == 0, [0] can be ignored. + // Array[0] is same to Array for unify the varid name to cover [0] + // + _STRCAT(&VarIdStr, "["); + _STRCAT(&VarIdStr, I2->getText()); + _STRCAT(&VarIdStr, "]"); + } + _STRCAT(&VarStr, "["); + _STRCAT(&VarStr, I2->getText()); + _STRCAT(&VarStr, "]"); + >> + } + )* << + switch (VarStoreType) { + case EFI_VFR_VARSTORE_EFI: + _PCATCH(mCVfrDataStorage.GetEfiVarStoreInfo (&$Info), SN2); + break; + case EFI_VFR_VARSTORE_BUFFER: + _PCATCH(gCVfrVarDataTypeDB.GetDataFieldInfo (VarStr, $Info.mInfo.mVarOffset, $Info.mVarType, $Info.mVarTotalSize), SN2->getLine(), VarStr); + _PCATCH((EFI_VFR_RETURN_CODE)gCVfrBufferConfig.Register ( + SName, + NULL), + SN2->getLine()); + _PCATCH((EFI_VFR_RETURN_CODE)gCVfrBufferConfig.Write ( + 'a', + SName, + NULL, + $Info.mVarType, + $Info.mInfo.mVarOffset, + $Info.mVarTotalSize, + Dummy), + SN2->getLine()); + break; + case EFI_VFR_VARSTORE_NAME: + default: break; + } + + QuestVarIdStr = VarIdStr; + if (VarStr != NULL) {delete VarStr;} + >> + ) + ; + +vfrQuestionDataFieldName [EFI_QUESTION_ID &QId, UINT32 &Mask, CHAR8 *&VarIdStr, UINT32 &LineNo] : + << + UINT32 Idx; + VarIdStr = NULL; LineNo = 0; + >> + ( + SN1:StringIdentifier << _STRCAT(&VarIdStr, SN1->getText()); LineNo = SN1->getLine(); >> + OpenBracket I1:Number CloseBracket << + _STRCAT(&VarIdStr, "["); + _STRCAT(&VarIdStr, I1->getText()); + _STRCAT(&VarIdStr, "]"); + mCVfrQuestionDB.GetQuestionId (NULL, VarIdStr, $QId, $Mask); + if (mConstantOnlyInExpression) { + _PCATCH(VFR_RETURN_CONSTANT_ONLY, LineNo); + } + >> + ) + | + ( + SN2:StringIdentifier << _STRCAT (&VarIdStr, SN2->getText()); LineNo = SN2->getLine(); >> + ( + "." << + _STRCAT (&VarIdStr, "."); + if (mConstantOnlyInExpression) { + _PCATCH(VFR_RETURN_CONSTANT_ONLY, LineNo); + } + >> + SF:StringIdentifier << _STRCAT (&VarIdStr, SF->getText()); >> + { + OpenBracket I2:Number CloseBracket << + Idx = _STOU32(I2->getText()); + if (mCompatibleMode) Idx --; + if (Idx > 0) { + // + // Idx == 0, [0] can be ignored. + // Array[0] is same to Array + // + _STRCAT(&VarIdStr, "["); + _STRCAT(&VarIdStr, I2->getText()); + _STRCAT(&VarIdStr, "]"); + } + >> + } + )* + << mCVfrQuestionDB.GetQuestionId (NULL, VarIdStr, $QId, $Mask); >> + ) + ; + +vfrConstantValueField[UINT8 Type] > [EFI_IFR_TYPE_VALUE Value] : + N1:Number << + switch ($Type) { + case EFI_IFR_TYPE_NUM_SIZE_8 : + $Value.u8 = _STOU8(N1->getText()); + break; + case EFI_IFR_TYPE_NUM_SIZE_16 : + $Value.u16 = _STOU16(N1->getText()); + break; + case EFI_IFR_TYPE_NUM_SIZE_32 : + $Value.u32 = _STOU32(N1->getText()); + break; + case EFI_IFR_TYPE_NUM_SIZE_64 : + $Value.u64 = _STOU64(N1->getText()); + break; + case EFI_IFR_TYPE_BOOLEAN : + $Value.b = _STOU8(N1->getText()); + break; + case EFI_IFR_TYPE_STRING : + $Value.string = _STOU16(N1->getText()); + break; + case EFI_IFR_TYPE_TIME : + case EFI_IFR_TYPE_DATE : + default : + break; + } + >> + | B1:True << $Value.b = TRUE; >> + | B2:False << $Value.b = FALSE; >> + | O1:One << $Value.u8 = _STOU8(O1->getText()); >> + | O2:Ones << $Value.u64 = _STOU64(O2->getText()); >> + | Z:Zero << $Value.u8 = _STOU8(Z->getText()); >> + | HOUR:Number ":" MINUTE:Number ":" SECOND:Number << $Value.time = _STOT(HOUR->getText(), MINUTE->getText(), SECOND->getText()); >> + | YEAR:Number "/" MONTH:Number "/" DAY:Number << $Value.date = _STOD(YEAR->getText(), MONTH->getText(), DAY->getText()); >> + | "STRING_TOKEN" "\(" S1:Number "\)" << $Value.string = _STOSID(S1->getText()); >> + ; + +//***************************************************************************** +// +// the syntax of form definition +// +vfrFormDefinition : + << CIfrForm FObj; >> + F:Form << FObj.SetLineNo(F->getLine()); >> + FormId "=" S1:Number "," << _PCATCH(FObj.SetFormId (_STOFID(S1->getText())), S1); >> + Title "=" "STRING_TOKEN" "\(" S2:Number "\)" ";" << FObj.SetFormTitle (_STOSID(S2->getText())); >> + ( + vfrStatementImage | + vfrStatementLocked | + vfrStatementRules | + vfrStatementDefault | + vfrStatementStat | + vfrStatementQuestions | + vfrStatementConditional | + vfrStatementLabel | + vfrStatementBanner | + // Just for framework vfr compatibility + vfrStatementInvalid + )* + E:EndForm << + if (mCompatibleMode) { + // + // Add Label for Framework Vfr + // + CIfrLabel LObj1; + LObj1.SetLineNo(E->getLine()); + LObj1.SetNumber (0xffff); //add end label for UEFI, label number hardcode 0xffff + CIfrLabel LObj2; + LObj2.SetLineNo(E->getLine()); + LObj2.SetNumber (0x0); //add dummy label for UEFI, label number hardcode 0x0 + CIfrLabel LObj3; + LObj3.SetLineNo(E->getLine()); + LObj3.SetNumber (0xffff); //add end label for UEFI, label number hardcode 0xffff + // + // Declare undefined Question + // + if (gCFormPkg.HavePendingUnassigned()) { + gCFormPkg.DeclarePendingQuestion ( + gCVfrVarDataTypeDB, + mCVfrDataStorage, + mCVfrQuestionDB, + &mFormsetGuid, + E->getLine() + ); + } + } + // + // mCVfrQuestionDB.PrintAllQuestion(); + // + CRT_END_OP (E); + >> + ";" + ; + +vfrStatementRules : + << CIfrRule RObj; >> + R:Rule << RObj.SetLineNo(R->getLine()); >> + S1:StringIdentifier "," << + mCVfrRulesDB.RegisterRule (S1->getText()); + RObj.SetRuleId (mCVfrRulesDB.GetRuleId(S1->getText())); + >> + vfrStatementExpression[0] + E:EndRule << CRT_END_OP (E); >> + ";" + ; + +vfrStatementDefault : + << + BOOLEAN IsExp = FALSE; + EFI_IFR_TYPE_VALUE Val = gZeroEfiIfrTypeValue; + CIfrDefault DObj; + EFI_DEFAULT_ID DefaultId = EFI_HII_DEFAULT_CLASS_STANDARD; + CHAR8 *VarStoreName = NULL; + EFI_VFR_VARSTORE_TYPE VarStoreType = EFI_VFR_VARSTORE_INVALID; + >> + D:Default << DObj.SetLineNo(D->getLine()); >> + ( + ( + vfrStatementValue "," << IsExp = TRUE; DObj.SetScope (1); >> + | "=" vfrConstantValueField[_GET_CURRQEST_DATATYPE()] > [Val] "," + << DObj.SetType (_GET_CURRQEST_DATATYPE()); DObj.SetValue(Val); >> + ) + { + DefaultStore "=" SN:StringIdentifier "," << _PCATCH(mCVfrDefaultStore.GetDefaultId (SN->getText(), &DefaultId), SN); DObj.SetDefaultId (DefaultId); >> + } + << + _PCATCH(mCVfrDataStorage.GetVarStoreName (_GET_CURRQEST_VARTINFO().mVarStoreId, &VarStoreName), D->getLine()); + _PCATCH(mCVfrDataStorage.GetVarStoreType (VarStoreName, VarStoreType), D->getLine()); + if ((IsExp == FALSE) && (VarStoreType == EFI_VFR_VARSTORE_BUFFER)) { + _PCATCH(mCVfrDefaultStore.BufferVarStoreAltConfigAdd ( + DefaultId, + _GET_CURRQEST_VARTINFO(), + VarStoreName, + _GET_CURRQEST_DATATYPE (), + Val), + D->getLine() + ); + } + >> + ) + ; + +vfrStatementStat : + vfrStatementSubTitle | + vfrStatementStaticText | + vfrStatementCrossReference + ; + +vfrStatementQuestions : + vfrStatementBooleanType | + vfrStatementDate | + vfrStatementNumericType | + vfrStatementStringType | + vfrStatementOrderedList | + vfrStatementTime + ; + +vfrStatementConditional : + vfrStatementDisableIfStat | + vfrStatementSuppressIfStat | //enhance to be compatible for framework endif + vfrStatementGrayOutIfStat | + vfrStatementInconsistentIfStat //to be compatible for framework + ; + +vfrStatementConditionalNew : + vfrStatementDisableIfStat | + vfrStatementSuppressIfStatNew | + vfrStatementGrayOutIfStatNew | + vfrStatementInconsistentIfStat //to be compatible for framework + ; + +vfrStatementSuppressIfStat : + <>? vfrStatementSuppressIfStatOld + | vfrStatementSuppressIfStatNew + ; + +vfrStatementGrayOutIfStat : + <>? vfrStatementGrayOutIfStatOld + | vfrStatementGrayOutIfStatNew + ; + +vfrStatementInvalid : + ( + vfrStatementInvalidHidden | + vfrStatementInvalidInventory | + vfrStatementInvalidSaveRestoreDefaults + ) + << _CRT_OP (TRUE); >> + ; + +flagsField : + Number | InteractiveFlag | ManufacturingFlag | DefaultFlag | + NVAccessFlag | ResetRequiredFlag | LateCheckFlag + ; + +vfrStatementValue : + << CIfrValue VObj; >> + V:Value << VObj.SetLineNo(V->getLine()); >> + "=" vfrStatementExpression[0] + ; + +vfrStatementSubTitle : + << CIfrSubtitle SObj; >> + L:Subtitle << SObj.SetLineNo(L->getLine()); >> + Text "=" "STRING_TOKEN" "\(" S:Number "\)" << SObj.SetPrompt (_STOSID(S->getText())); >> + { + "," FLAGS "=" vfrSubtitleFlags[SObj] + } + { vfrStatementStatTagList "," } + E:";" << CRT_END_OP (E); >> + ; + +vfrSubtitleFlags [CIfrSubtitle & SObj] : + << UINT8 LFlags = 0; >> + subtitleFlagsField[LFlags] ( "\|" subtitleFlagsField[LFlags] )* + << _PCATCH(SObj.SetFlags (LFlags)); >> + ; + +subtitleFlagsField [UINT8 & Flags] : + N:Number << $Flags |= _STOU8(N->getText()); >> + | "HORIZONTAL" << $Flags |= 0x01; >> + ; + +vfrStatementStaticText : + << + UINT8 Flags = 0; + EFI_QUESTION_ID QId = EFI_QUESTION_ID_INVALID; + EFI_STRING_ID TxtTwo = EFI_STRING_ID_INVALID; + >> + T:Text + Help "=" "STRING_TOKEN" "\(" S1:Number "\)" "," + Text "=" "STRING_TOKEN" "\(" S2:Number "\)" + { + "," Text "=" "STRING_TOKEN" "\(" S3:Number "\)" << TxtTwo = _STOSID(S3->getText()); >> + } + { + "," F:FLAGS "=" staticTextFlagsField[Flags] ( "\|" staticTextFlagsField[Flags] )* + "," Key "=" KN:Number + } + << + if (Flags & EFI_IFR_FLAG_CALLBACK) { + CIfrAction AObj; + mCVfrQuestionDB.RegisterQuestion (NULL, NULL, QId); + AObj.SetLineNo (F->getLine()); + AObj.SetQuestionId (QId); + AObj.SetPrompt (_STOSID(S2->getText())); + AObj.SetHelp (_STOSID(S1->getText())); + _PCATCH(AObj.SetFlags (Flags), F->getLine()); + AssignQuestionKey (AObj, KN); + CRT_END_OP (KN); + } else { + CIfrText TObj; + TObj.SetLineNo (T->getLine()); + TObj.SetHelp (_STOSID(S1->getText())); + TObj.SetPrompt (_STOSID(S2->getText())); + TObj.SetTextTwo (TxtTwo); + } + >> + { "," vfrStatementStatTagList } + ";" + ; + +staticTextFlagsField[UINT8 & HFlags] : + N:Number << _PCATCH(_STOU8(N->getText()) == 0 ? VFR_RETURN_SUCCESS : VFR_RETURN_UNSUPPORTED, N->getLine()); >> + | questionheaderFlagsField[HFlags] + ; + +vfrStatementCrossReference : + vfrStatementGoto | + vfrStatementResetButton + ; + +vfrStatementGoto : + << + UINT8 RefType = 1; + EFI_STRING_ID DevPath; + EFI_GUID FSId; + EFI_FORM_ID FId; + EFI_QUESTION_ID QId = EFI_QUESTION_ID_INVALID; + UINT32 BitMask; + CIfrQuestionHeader *QHObj = NULL; + CIfrRef *R1Obj = NULL; + CIfrRef2 *R2Obj = NULL; + CIfrRef3 *R3Obj = NULL; + CIfrRef4 *R4Obj = NULL; + >> + G:Goto + ( + ( + DevicePath "=" "STRING_TOKEN" "\(" P:Number "\)" "," + FormSetGuid "=" guidDefinition[FSId] "," + FormId "=" F1:Number "," + Question "=" QN1:Number "," + << + RefType = 4; + DevPath = _STOSID(P->getText()); + FId = _STOFID(F1->getText()); + QId = _STOQID(QN1->getText()); + >> + ) + | + ( + FormSetGuid "=" guidDefinition[FSId] "," + FormId "=" F2:Number "," + Question "=" QN2:Number "," + << + RefType = 3; + FId = _STOFID(F2->getText()); + QId = _STOQID(QN2->getText()); + >> + ) + | + ( + FormId "=" F3:Number "," << RefType = 2; FId = _STOFID(F3->getText()); >> + Question "=" + ( + QN3:StringIdentifier "," << mCVfrQuestionDB.GetQuestionId (QN3->getText (), NULL, QId, BitMask); >> + | QN4:Number "," << QId = _STOQID(QN4->getText()); >> + ) + ) + | + ( + F4:Number "," << + RefType = 1; + FId = _STOFID(F4->getText()); + >> + ) + ) + << + switch (RefType) { + case 4: + { + R4Obj = new CIfrRef4; + QHObj = R4Obj; + R4Obj->SetLineNo(G->getLine()); + R4Obj->SetDevicePath (DevPath); + R4Obj->SetFormSetId (FSId); + R4Obj->SetFormId (FId); + R4Obj->SetQuestionId (QId); + break; + } + case 3: + { + R3Obj = new CIfrRef3; + QHObj = R3Obj; + R3Obj->SetLineNo(G->getLine()); + R3Obj->SetFormSetId (FSId); + R3Obj->SetFormId (FId); + R3Obj->SetQuestionId (QId); + break; + } + case 2: + { + R2Obj = new CIfrRef2; + QHObj = R2Obj; + R2Obj->SetLineNo(G->getLine()); + R2Obj->SetFormId (FId); + _PCATCH(R2Obj->SetQuestionId (QId), QN3); + break; + } + case 1: + { + R1Obj = new CIfrRef; + QHObj = R1Obj; + R1Obj->SetLineNo(G->getLine()); + R1Obj->SetFormId (FId); + break; + } + default: break; + } + >> + vfrQuestionHeaderWithNoStorage[QHObj] + { "," vfrStatementStatTagList } + { "," F:FLAGS "=" vfrGotoFlags[QHObj, F->getLine()] } + { + "," Key "=" KN:Number << AssignQuestionKey (*QHObj, KN); >> + } + ";" << if (R1Obj != NULL) {delete R1Obj;} if (R2Obj != NULL) {delete R2Obj;} if (R3Obj != NULL) {delete R3Obj;} if (R4Obj != NULL) {delete R4Obj;} >> + ; + +vfrGotoFlags [CIfrQuestionHeader *QHObj, UINT32 LineNum] : + << UINT8 HFlags = 0; >> + gotoFlagsField[HFlags] ( "\|" gotoFlagsField[HFlags] )* + << _PCATCH(QHObj->SetFlags (HFlags), LineNum); >> + ; + +gotoFlagsField[UINT8 & HFlags] : + N:Number << _PCATCH(_STOU8(N->getText()) == 0 ? VFR_RETURN_SUCCESS : VFR_RETURN_UNSUPPORTED, N->getLine()); >> + | questionheaderFlagsField[HFlags] + ; + +getStringId : + "STRING_TOKEN" "\(" + IdVal:Number + "\)" + ; + +vfrStatementResetButton : + << + CIfrResetButton RBObj; + UINT16 DefaultId; + >> + L:ResetButton << RBObj.SetLineNo(L->getLine()); >> + DefaultStore + "=" N:StringIdentifier "," << + _PCATCH(mCVfrDefaultStore.GetDefaultId (N->getText(), &DefaultId), N->getLine()); + RBObj.SetDefaultId (DefaultId); + >> + vfrStatementHeader[&RBObj] "," + { vfrStatementStatTagList "," } + E:EndResetButton << CRT_END_OP (E); >> + ";" + ; + +vfrStatementBooleanType : + vfrStatementCheckBox | + vfrStatementAction + ; + +//***************************************************** +// Syntax of checkbox +// +// Example: +// checkbox +// varid = MySTestData.mField1, +// prompt = STRING_TOKEN(STR_CHECK_BOX_PROMPT), +// help = STRING_TOKEN(STR_CHECK_BOX_HELP), +// flags = CHECKBOX_DEFAULT | CALLBACK, +// default value = TRUE, defaultstore = MyDefaultStore, +// endcheckbox; +// +vfrStatementCheckBox : + << + CIfrCheckBox CBObj; + EFI_IFR_TYPE_VALUE Val = gZeroEfiIfrTypeValue; + CHAR8 *VarStoreName = NULL; + UINT32 DataTypeSize; + >> + L:CheckBox << CBObj.SetLineNo(L->getLine()); >> + vfrQuestionHeader[CBObj] "," << //check data type + _PCATCH (gCVfrVarDataTypeDB.GetDataTypeSize (_GET_CURRQEST_DATATYPE(), &DataTypeSize), L->getLine(), "CheckBox varid is not the valid data type"); + if (DataTypeSize != 0 && DataTypeSize != _GET_CURRQEST_VARSIZE()) { + _PCATCH (VFR_RETURN_INVALID_PARAMETER, L->getLine(), "CheckBox varid doesn't support array"); + } else if ((mCVfrDataStorage.GetVarStoreType (_GET_CURRQEST_VARTINFO().mVarStoreId) == EFI_VFR_VARSTORE_BUFFER) && + (_GET_CURRQEST_VARSIZE() != sizeof (BOOLEAN))) { + _PCATCH (VFR_RETURN_INVALID_PARAMETER, L->getLine(), "CheckBox varid only support BOOLEAN data type"); + } + >> + { + F:FLAGS "=" vfrCheckBoxFlags[CBObj, F->getLine()] "," + << + _PCATCH(mCVfrDataStorage.GetVarStoreName (_GET_CURRQEST_VARTINFO().mVarStoreId, &VarStoreName), VFR_RETURN_SUCCESS, L, "Failed to retrieve varstore name"); + Val.b = TRUE; + if (CBObj.GetFlags () & 0x01) { + _PCATCH( + mCVfrDefaultStore.BufferVarStoreAltConfigAdd ( + EFI_HII_DEFAULT_CLASS_STANDARD, + _GET_CURRQEST_VARTINFO(), + VarStoreName, + _GET_CURRQEST_DATATYPE (), + Val + ), + VFR_RETURN_SUCCESS, + L, + "No standard default storage found" + ); + } + if (CBObj.GetFlags () & 0x02) { + _PCATCH( + mCVfrDefaultStore.BufferVarStoreAltConfigAdd ( + EFI_HII_DEFAULT_CLASS_MANUFACTURING, + _GET_CURRQEST_VARTINFO(), + VarStoreName, + _GET_CURRQEST_DATATYPE (), + Val + ), + VFR_RETURN_SUCCESS, + L, + "No manufacturing default storage found" + ); + } + >> + } + { + Key "=" KN:Number "," << AssignQuestionKey (CBObj, KN); >> + } + vfrStatementQuestionOptionList + E:EndCheckBox << CRT_END_OP (E); >> + ";" + ; + +vfrCheckBoxFlags [CIfrCheckBox & CBObj, UINT32 LineNum] : + << + UINT8 LFlags = 0; + UINT8 HFlags = 0; + >> + checkboxFlagsField[LFlags, HFlags] ( "\|" checkboxFlagsField[LFlags, HFlags] )* + << _PCATCH(CBObj.SetFlags (HFlags, LFlags), LineNum); >> + ; + +checkboxFlagsField[UINT8 & LFlags, UINT8 & HFlags] : + N:Number << + if (mCompatibleMode) { + // + // set question flag + // + $LFlags |= _STOU8(N->getText()); + } else { + _PCATCH(_STOU8(N->getText()) == 0 ? VFR_RETURN_SUCCESS : VFR_RETURN_UNSUPPORTED, N->getLine()); + } + >> + | D:"DEFAULT" << + if (mCompatibleMode) { + // + // set question Default flag + // + $LFlags |= 0x01; + } else { + _PCATCH (VFR_RETURN_UNSUPPORTED, D); + } + >> + | M:"MANUFACTURING" << + if (mCompatibleMode) { + // + // set question MFG flag + // + $LFlags |= 0x02; + } else { + _PCATCH (VFR_RETURN_UNSUPPORTED, M); + } + >> + | "CHECKBOX_DEFAULT" << $LFlags |= 0x01; >> + | "CHECKBOX_DEFAULT_MFG" << $LFlags |= 0x02; >> + | questionheaderFlagsField[HFlags] + ; + +//***************************************************** +// Syntax of action +// +// Example: +// action +// prompt = STRING_TOKEN(STR_ACTION_PROMPT), +// help = STRING_TOKEN(STR_ACTION_HELP), +// flags = CALLBACK, +// config = STRING_TOKEN(STR_ACTION_CONFIG), +// endaction; +// +vfrStatementAction : + << CIfrAction AObj; >> + L:Action << AObj.SetLineNo(L->getLine()); >> + vfrQuestionHeaderWithNoStorage[&AObj] "," + { F:FLAGS "=" vfrActionFlags[AObj, F->getLine()] "," } + Config "=" "STRING_TOKEN" "\(" S:Number "\)" "," << AObj.SetQuestionConfig (_STOSID(S->getText())); >> + vfrStatementQuestionTagList + E:EndAction << CRT_END_OP (E); >> + ";" + ; + +vfrActionFlags[CIfrAction & AObj, UINT32 LineNum] : + << UINT8 HFlags = 0; >> + actionFlagsField[HFlags] ( "\|" actionFlagsField[HFlags] )* + << _PCATCH(AObj.SetFlags (HFlags), LineNum); >> + ; + +actionFlagsField[UINT8 & HFlags] : + N:Number << _PCATCH(_STOU8(N->getText()) == 0 ? VFR_RETURN_SUCCESS : VFR_RETURN_UNSUPPORTED, N->getLine()); >> + | questionheaderFlagsField[HFlags] + ; + +vfrStatementDate : + << + EFI_QUESTION_ID QId = EFI_QUESTION_ID_INVALID; + CHAR8 *VarIdStr[3] = {NULL, }; + CIfrDate DObj; + EFI_IFR_TYPE_VALUE Val = gZeroEfiIfrTypeValue; + >> + L:Date << DObj.SetLineNo(L->getLine()); >> + ( + ( + vfrQuestionHeader[DObj, QUESTION_DATE] "," + { F:FLAGS "=" vfrDateFlags[DObj, F->getLine()] "," } + vfrStatementQuestionOptionList + ) + | + ( + Year VarId "=" D1:StringIdentifier "." D1Y:StringIdentifier "," + << _STRCAT(&VarIdStr[0], D1->getText()); _STRCAT(&VarIdStr[0], "."); _STRCAT(&VarIdStr[0], D1Y->getText()); >> + Prompt "=" "STRING_TOKEN" "\(" YP:Number "\)" "," + Help "=" "STRING_TOKEN" "\(" YH:Number "\)" "," + minMaxDateStepDefault[Val.date, 0] + + Month VarId "=" D2:StringIdentifier "." D2M:StringIdentifier "," + << _STRCAT(&VarIdStr[1], D2->getText()); _STRCAT(&VarIdStr[1], "."); _STRCAT(&VarIdStr[1], D2M->getText()); >> + Prompt "=" "STRING_TOKEN" "\(" MP:Number "\)" "," + Help "=" "STRING_TOKEN" "\(" MH:Number "\)" "," + minMaxDateStepDefault[Val.date, 1] + + Day VarId "=" D3:StringIdentifier "." D3D:StringIdentifier "," + << _STRCAT(&VarIdStr[2], D3->getText()); _STRCAT(&VarIdStr[2], "."); _STRCAT(&VarIdStr[2], D3D->getText()); >> + Prompt "=" "STRING_TOKEN" "\(" DP:Number "\)" "," + Help "=" "STRING_TOKEN" "\(" DH:Number "\)" "," + minMaxDateStepDefault[Val.date, 2] + << + mCVfrQuestionDB.RegisterOldDateQuestion (VarIdStr[0], VarIdStr[1], VarIdStr[2], QId); + DObj.SetQuestionId (QId); + DObj.SetFlags (EFI_IFR_QUESTION_FLAG_DEFAULT, QF_DATE_STORAGE_TIME); + DObj.SetPrompt (_STOSID(YP->getText())); + DObj.SetHelp (_STOSID(YH->getText())); + if (VarIdStr[0] != NULL) { delete VarIdStr[0]; } if (VarIdStr[1] != NULL) { delete VarIdStr[1]; } if (VarIdStr[2] != NULL) { delete VarIdStr[2]; } + >> + << {CIfrDefault DefaultObj(EFI_HII_DEFAULT_CLASS_STANDARD, EFI_IFR_TYPE_DATE, Val); DefaultObj.SetLineNo(L->getLine());} >> + ) + ( vfrStatementInconsistentIf )* + ) + E:EndDate << CRT_END_OP (E); >> + ";" + ; + +minMaxDateStepDefault[EFI_HII_DATE & D, UINT8 KeyValue] : + Minimum "=" Number "," + Maximum "=" Number "," + { "step" "=" Number "," } + { + "default" "=" N:Number "," << + switch (KeyValue) { + case 0: D.Year = _STOU16(N->getText()); break; + case 1: D.Month = _STOU8(N->getText()); break; + case 2: D.Day = _STOU8(N->getText()); break; + } + >> + } + ; + +vfrDateFlags [CIfrDate & DObj, UINT32 LineNum] : + << UINT8 LFlags = 0; >> + dateFlagsField[LFlags] ( "\|" dateFlagsField[LFlags] )* + << _PCATCH(DObj.SetFlags (EFI_IFR_QUESTION_FLAG_DEFAULT, LFlags), LineNum); >> + ; + +dateFlagsField [UINT8 & Flags] : + N:Number << $Flags |= _STOU8(N->getText()); >> + | "YEAR_SUPPRESS" << $Flags |= 0x01; >> + | "MONTH_SUPPRESS" << $Flags |= 0x02; >> + | "DAY_SUPPRESS" << $Flags |= 0x04; >> + | "STORAGE_NORMAL" << $Flags |= 0x00; >> + | "STORAGE_TIME" << $Flags |= 0x10; >> + | "STORAGE_WAKEUP" << $Flags |= 0x20; >> + ; + +vfrStatementNumericType : + vfrStatementNumeric | + vfrStatementOneOf + ; + +vfrSetMinMaxStep[CIfrMinMaxStepData & MMSDObj] : + << + UINT64 MaxU8 = 0, MinU8 = 0, StepU8 = 0; + UINT32 MaxU4 = 0, MinU4 = 0, StepU4 = 0; + UINT16 MaxU2 = 0, MinU2 = 0, StepU2 = 0; + UINT8 MaxU1 = 0, MinU1 = 0, StepU1 = 0; + >> + Minimum "=" I:Number "," + << + switch (_GET_CURRQEST_DATATYPE ()) { + case EFI_IFR_TYPE_NUM_SIZE_64 : MinU8 = _STOU64(I->getText()); break; + case EFI_IFR_TYPE_NUM_SIZE_32 : MinU4 = _STOU32(I->getText()); break; + case EFI_IFR_TYPE_NUM_SIZE_16 : MinU2 = _STOU16(I->getText()); break; + case EFI_IFR_TYPE_NUM_SIZE_8 : MinU1 = _STOU8(I->getText()); break; + } + >> + Maximum "=" A:Number "," + << + switch (_GET_CURRQEST_DATATYPE ()) { + case EFI_IFR_TYPE_NUM_SIZE_64 : MaxU8 = _STOU64(A->getText()); break; + case EFI_IFR_TYPE_NUM_SIZE_32 : MaxU4 = _STOU32(A->getText()); break; + case EFI_IFR_TYPE_NUM_SIZE_16 : MaxU2 = _STOU16(A->getText()); break; + case EFI_IFR_TYPE_NUM_SIZE_8 : MaxU1 = _STOU8(A->getText()); break; + } + >> + { + STEP "=" S:Number "," + << + switch (_GET_CURRQEST_DATATYPE ()) { + case EFI_IFR_TYPE_NUM_SIZE_64 : StepU8 = _STOU64(S->getText()); break; + case EFI_IFR_TYPE_NUM_SIZE_32 : StepU4 = _STOU32(S->getText()); break; + case EFI_IFR_TYPE_NUM_SIZE_16 : StepU2 = _STOU16(S->getText()); break; + case EFI_IFR_TYPE_NUM_SIZE_8 : StepU1 = _STOU8(S->getText()); break; + } + >> + } + << + switch (_GET_CURRQEST_DATATYPE ()) { + case EFI_IFR_TYPE_NUM_SIZE_64 : $MMSDObj.SetMinMaxStepData (MinU8, MaxU8, StepU8); break; + case EFI_IFR_TYPE_NUM_SIZE_32 : $MMSDObj.SetMinMaxStepData (MinU4, MaxU4, StepU4); break; + case EFI_IFR_TYPE_NUM_SIZE_16 : $MMSDObj.SetMinMaxStepData (MinU2, MaxU2, StepU2); break; + case EFI_IFR_TYPE_NUM_SIZE_8 : $MMSDObj.SetMinMaxStepData (MinU1, MaxU1, StepU1); break; + } + >> + ; + +vfrStatementNumeric : + << + CIfrNumeric NObj; + UINT32 DataTypeSize; + >> + L:Numeric << NObj.SetLineNo(L->getLine()); >> + vfrQuestionHeader[NObj] "," << // check data type + _PCATCH (gCVfrVarDataTypeDB.GetDataTypeSize (_GET_CURRQEST_DATATYPE(), &DataTypeSize), L->getLine(), "Numeric varid is not the valid data type"); + if (DataTypeSize != 0 && DataTypeSize != _GET_CURRQEST_VARSIZE()) { + _PCATCH (VFR_RETURN_INVALID_PARAMETER, L->getLine(), "Numeric varid doesn't support array"); + } + _PCATCH(NObj.SetFlags (NObj.FLAGS(), _GET_CURRQEST_DATATYPE()), L->getLine()); + >> + { F:FLAGS "=" vfrNumericFlags[NObj, F->getLine()] "," } + { + Key "=" KN:Number "," << AssignQuestionKey (NObj, KN); >> + } + vfrSetMinMaxStep[NObj] + vfrStatementQuestionOptionList + E:EndNumeric << CRT_END_OP (E); >> + ";" + ; + +vfrNumericFlags [CIfrNumeric & NObj, UINT32 LineNum] : + << + UINT8 LFlags = _GET_CURRQEST_DATATYPE(); + UINT8 HFlags = 0; + >> + numericFlagsField[HFlags, LFlags] ( "\|" numericFlagsField[HFlags, LFlags] )* + << _PCATCH(NObj.SetFlags (HFlags, LFlags), LineNum); >> + ; + +numericFlagsField [UINT8 & HFlags, UINT8 & LFlags] : + N:Number << _PCATCH(_STOU8(N->getText()) == 0 ? VFR_RETURN_SUCCESS : VFR_RETURN_UNSUPPORTED, N->getLine()); >> + | "DISPLAY_INT_DEC" << $LFlags |= 0x00; >> + | "DISPLAY_UINT_DEC" << $LFlags |= 0x10; >> + | "DISPLAY_UINT_HEX" << $LFlags |= 0x20; >> + | questionheaderFlagsField[HFlags] + ; + +vfrStatementOneOf : + << + CIfrOneOf OObj; + UINT32 DataTypeSize; + >> + L:OneOf << OObj.SetLineNo(L->getLine()); >> + vfrQuestionHeader[OObj] "," << //check data type + _PCATCH (gCVfrVarDataTypeDB.GetDataTypeSize (_GET_CURRQEST_DATATYPE(), &DataTypeSize), L->getLine(), "OneOf varid is not the valid data type"); + if (DataTypeSize != 0 && DataTypeSize != _GET_CURRQEST_VARSIZE()) { + _PCATCH (VFR_RETURN_INVALID_PARAMETER, L->getLine(), "OneOf varid doesn't support array"); + } + _PCATCH(OObj.SetFlags (OObj.FLAGS(), _GET_CURRQEST_DATATYPE()), L->getLine()); + >> + { F:FLAGS "=" vfrOneofFlagsField[OObj, F->getLine()] "," } + { + vfrSetMinMaxStep[OObj] + } + vfrStatementQuestionOptionList + E:EndOneOf << CRT_END_OP (E); >> + ";" + ; + +vfrOneofFlagsField [CIfrOneOf & OObj, UINT32 LineNum] : + << + UINT8 LFlags = _GET_CURRQEST_DATATYPE(); + UINT8 HFlags = 0; + >> + numericFlagsField[HFlags, LFlags] ( "\|" numericFlagsField[HFlags, LFlags] )* + << _PCATCH(OObj.SetFlags (HFlags, LFlags), LineNum); >> + ; + +vfrStatementStringType : + vfrStatementString | + vfrStatementPassword + ; + +vfrStatementString : + << + CIfrString SObj; + >> + L:String << SObj.SetLineNo(L->getLine()); >> + vfrQuestionHeader[SObj] "," + { F:FLAGS "=" vfrStringFlagsField[SObj, F->getLine()] "," } + { + Key "=" KN:Number "," << AssignQuestionKey (SObj, KN); >> + } + MinSize "=" MIN:Number "," << SObj.SetMinSize (_STOU8(MIN->getText())); >> + MaxSize "=" MAX:Number "," << SObj.SetMaxSize (_STOU8(MAX->getText())); >> + vfrStatementQuestionOptionList + E:EndString << CRT_END_OP (E); >> + ";" + ; + +vfrStringFlagsField [CIfrString & SObj, UINT32 LineNum] : + << + UINT8 LFlags = 0; + UINT8 HFlags = 0; + >> + stringFlagsField[HFlags, LFlags] ( "\|" stringFlagsField[HFlags, LFlags] )* + << _PCATCH(SObj.SetFlags (HFlags, LFlags), LineNum); >> + ; + +stringFlagsField [UINT8 & HFlags, UINT8 & LFlags] : + N:Number << _PCATCH(_STOU8(N->getText()) == 0 ? VFR_RETURN_SUCCESS : VFR_RETURN_UNSUPPORTED, N->getLine()); >> + | "MULTI_LINE" << $LFlags = 0x01; >> + | questionheaderFlagsField[HFlags] + ; + +vfrStatementPassword : + << + CIfrPassword PObj; + >> + L:Password << PObj.SetLineNo(L->getLine()); >> + vfrQuestionHeader[PObj] "," + { F:FLAGS "=" vfrPasswordFlagsField[PObj, F->getLine()] "," } + { + Key "=" KN:Number "," << AssignQuestionKey (PObj, KN); >> + } + MinSize "=" MIN:Number "," << PObj.SetMinSize (_STOU16(MIN->getText())); >> + MaxSize "=" MAX:Number "," << PObj.SetMaxSize (_STOU16(MAX->getText())); >> + { Encoding "=" Number "," } + vfrStatementQuestionOptionList + E:EndPassword << CRT_END_OP (E); >> + ";" + ; + +vfrPasswordFlagsField [CIfrPassword & PObj, UINT32 LineNum] : + << UINT8 HFlags = 0; >> + passwordFlagsField[HFlags] ( "\|" passwordFlagsField[HFlags] )* + << _PCATCH(PObj.SetFlags(HFlags), LineNum); >> + ; + +passwordFlagsField [UINT8 & HFlags] : + N:Number << _PCATCH(_STOU8(N->getText()) == 0 ? VFR_RETURN_SUCCESS : VFR_RETURN_UNSUPPORTED, N->getLine()); >> + | questionheaderFlagsField[HFlags] + ; + +vfrStatementOrderedList : + << + CIfrOrderedList OLObj; + >> + L:OrderedList << OLObj.SetLineNo(L->getLine()); >> + vfrQuestionHeader[OLObj] "," + << OLObj.SetMaxContainers ((UINT8)_GET_CURRQEST_VARSIZE()); >> + { + MaxContainers "=" M:Number "," << OLObj.SetMaxContainers (_STOU8(M->getText())); >> + } + { F:FLAGS "=" vfrOrderedListFlags[OLObj, F->getLine()] } + vfrStatementQuestionOptionList + E:EndList << CRT_END_OP (E); >> + ";" + ; + +vfrOrderedListFlags [CIfrOrderedList & OLObj, UINT32 LineNum] : + << + UINT8 HFlags = 0; + UINT8 LFlags = 0; + >> + orderedlistFlagsField[HFlags, LFlags] ( "\|" orderedlistFlagsField[HFlags, LFlags] )* + << _PCATCH(OLObj.SetFlags (HFlags, LFlags), LineNum); >> + ; + +orderedlistFlagsField [UINT8 & HFlags, UINT8 & LFlags] : + N:Number << _PCATCH(_STOU8(N->getText()) == 0 ? VFR_RETURN_SUCCESS : VFR_RETURN_UNSUPPORTED, N->getLine()); >> + | "UNIQUE" << $LFlags |= 0x01; >> + | "NOEMPTY" << $LFlags |= 0x02; >> + | questionheaderFlagsField[HFlags] + ; + +vfrStatementTime : + << + EFI_QUESTION_ID QId = EFI_QUESTION_ID_INVALID; + CHAR8 *VarIdStr[3] = {NULL, }; + CIfrTime TObj; + EFI_IFR_TYPE_VALUE Val = gZeroEfiIfrTypeValue; + >> + L:Time << TObj.SetLineNo(L->getLine()); >> + ( + ( + vfrQuestionHeader[TObj, QUESTION_TIME] "," + { F:FLAGS "=" vfrTimeFlags[TObj, F->getLine()] "," } + vfrStatementDefault + ) + | + ( + Hour VarId "=" T1:StringIdentifier "." T1H:StringIdentifier "," + << _STRCAT(&VarIdStr[0], T1->getText()); _STRCAT(&VarIdStr[0], "."); _STRCAT(&VarIdStr[0], T1H->getText()); >> + Prompt "=" "STRING_TOKEN" "\(" HP:Number "\)" "," + Help "=" "STRING_TOKEN" "\(" HH:Number "\)" "," + minMaxTimeStepDefault[Val.time, 0] + + Minute VarId "=" T2:StringIdentifier "." T2M:StringIdentifier "," + << _STRCAT(&VarIdStr[1], T2->getText()); _STRCAT(&VarIdStr[1], "."); _STRCAT(&VarIdStr[1], T2M->getText()); >> + Prompt "=" "STRING_TOKEN" "\(" MP:Number "\)" "," + Help "=" "STRING_TOKEN" "\(" MH:Number "\)" "," + minMaxTimeStepDefault[Val.time, 1] + + Second VarId "=" T3:StringIdentifier "." T3S:StringIdentifier "," + << _STRCAT(&VarIdStr[2], T3->getText()); _STRCAT(&VarIdStr[2], "."); _STRCAT(&VarIdStr[2], T3S->getText()); >> + Prompt "=" "STRING_TOKEN" "\(" SP:Number "\)" "," + Help "=" "STRING_TOKEN" "\(" SH:Number "\)" "," + minMaxTimeStepDefault[Val.time, 2] + << + mCVfrQuestionDB.RegisterOldTimeQuestion (VarIdStr[0], VarIdStr[1], VarIdStr[2], QId); + TObj.SetQuestionId (QId); + TObj.SetFlags (EFI_IFR_QUESTION_FLAG_DEFAULT, QF_TIME_STORAGE_TIME); + TObj.SetPrompt (_STOSID(HP->getText())); + TObj.SetHelp (_STOSID(HH->getText())); + if (VarIdStr[0] != NULL) { delete VarIdStr[0]; } if (VarIdStr[1] != NULL) { delete VarIdStr[1]; } if (VarIdStr[2] != NULL) { delete VarIdStr[2]; } + >> + << {CIfrDefault DefaultObj(EFI_HII_DEFAULT_CLASS_STANDARD, EFI_IFR_TYPE_TIME, Val); DefaultObj.SetLineNo(L->getLine());} >> + ) + ( vfrStatementInconsistentIf )* + ) + E:EndTime << CRT_END_OP (E); >> + ";" + ; + +minMaxTimeStepDefault[EFI_HII_TIME & T, UINT8 KeyValue] : + Minimum "=" Number "," + Maximum "=" Number "," + { "step" "=" Number "," } + { + "default" "=" N:Number "," << + switch (KeyValue) { + case 0: T.Hour = _STOU8(N->getText()); break; + case 1: T.Minute = _STOU8(N->getText()); break; + case 2: T.Second = _STOU8(N->getText()); break; + } + >> + } + ; + +vfrTimeFlags [CIfrTime & TObj, UINT32 LineNum] : + << UINT8 LFlags = 0; >> + timeFlagsField[LFlags] ( "\|" timeFlagsField[LFlags] )* + << _PCATCH(TObj.SetFlags(EFI_IFR_QUESTION_FLAG_DEFAULT, LFlags), LineNum); >> + ; + +timeFlagsField [UINT8 & Flags] : + N:Number << $Flags |= _STOU8(N->getText()); >> + | "HOUR_SUPPRESS" << $Flags |= 0x01; >> + | "MINUTE_SUPPRESS" << $Flags |= 0x02; >> + | "SECOND_SUPPRESS" << $Flags |= 0x04; >> + | "STORAGE_NORMAL" << $Flags |= 0x00; >> + | "STORAGE_TIME" << $Flags |= 0x10; >> + | "STORAGE_WAKEUP" << $Flags |= 0x20; >> + ; + +vfrStatementQuestionTag : + vfrStatementStatTag "," | + vfrStatementInconsistentIf | + vfrStatementNoSubmitIf | + vfrStatementDisableIfQuest | + vfrStatementRefresh | + vfrStatementVarstoreDevice + ; + +vfrStatementQuestionTagList : + ( vfrStatementQuestionTag )* + ; + +vfrStatementQuestionOptionTag : + vfrStatementSuppressIfQuest | + vfrStatementGrayOutIfQuest | + vfrStatementValue | + vfrStatementDefault | + vfrStatementOptions + ; + +vfrStatementQuestionOptionList : + ( + vfrStatementQuestionTag | + vfrStatementQuestionOptionTag + )* + ; + +vfrStatementStatList : + vfrStatementStat | + vfrStatementQuestions | + vfrStatementConditionalNew | + vfrStatementLabel | + // Just for framework vfr compatibility + vfrStatementInvalid + ; + +vfrStatementStatListOld : + vfrStatementStat | + vfrStatementQuestions | + vfrStatementLabel | + // Just for framework vfr compatibility + vfrStatementInvalid + ; + +vfrStatementDisableIfStat : + << + CIfrDisableIf DIObj; + mConstantOnlyInExpression = TRUE; + >> + L:DisableIf << DIObj.SetLineNo(L->getLine()); >> + vfrStatementExpression[0] ";" << mConstantOnlyInExpression = FALSE; >> + ( vfrStatementStatList )* + E:EndIf << CRT_END_OP (E); >> + ";" + ; + +vfrStatementInconsistentIfStat : + << CIfrInconsistentIf IIObj; >> + L:InconsistentIf << + if (!mCompatibleMode) { + _PCATCH (VFR_RETURN_UNSUPPORTED, L); + } + IIObj.SetLineNo(L->getLine()); + >> + Prompt "=" "STRING_TOKEN" "\(" S:Number "\)" "," << IIObj.SetError (_STOSID(S->getText())); >> + { FLAGS "=" flagsField ( "\|" flagsField )* "," } + vfrStatementExpression[0] + E:EndIf << CRT_END_OP (E); >> + ";" + ; + +// +// Compatible for framework vfr file +// +vfrStatementgrayoutIfSuppressIf: + << CIfrSuppressIf SIObj; >> + L:SuppressIf << SIObj.SetLineNo(L->getLine()); >> + { FLAGS "=" flagsField ( "\|" flagsField )* "," } + vfrStatementExpression[0] + ";" + ; + +vfrStatementsuppressIfGrayOutIf: + << CIfrGrayOutIf GOIObj; >> + L:GrayOutIf << GOIObj.SetLineNo(L->getLine()); >> + { FLAGS "=" flagsField ( "\|" flagsField )* "," } + vfrStatementExpression[0] + ";" + ; + +vfrStatementSuppressIfStatNew : + << CIfrSuppressIf SIObj;>> + L:SuppressIf << SIObj.SetLineNo(L->getLine()); >> + { FLAGS "=" flagsField ( "\|" flagsField )* "," } + vfrStatementExpression[0] + ";" + ( vfrStatementStatList )* + E: EndIf ";" << CRT_END_OP (E); >> + ; + +vfrStatementGrayOutIfStatNew : + << CIfrGrayOutIf GOIObj;>> + L:GrayOutIf << GOIObj.SetLineNo(L->getLine()); >> + { FLAGS "=" flagsField ( "\|" flagsField )* "," } + vfrStatementExpression[0] + ";" + ( vfrStatementStatList )* + E: EndIf ";" << CRT_END_OP (E); >> + ; + +vfrStatementSuppressIfStatOld : + << + CIfrSuppressIf SIObj; + BOOLEAN GrayOutExist = FALSE; + >> + L:SuppressIf << SIObj.SetLineNo(L->getLine()); >> + { FLAGS "=" flagsField ( "\|" flagsField )* "," } + vfrStatementExpression[0] + ";" + { + vfrStatementsuppressIfGrayOutIf + << GrayOutExist = TRUE; >> + } + ( vfrStatementStatListOld )* + E: EndIf ";" << if (GrayOutExist) CRT_END_OP (E); CRT_END_OP (E);>> + ; + +vfrStatementGrayOutIfStatOld : + << + CIfrGrayOutIf GOIObj; + BOOLEAN SuppressExist = FALSE; + >> + L:GrayOutIf << GOIObj.SetLineNo(L->getLine()); >> + { FLAGS "=" flagsField ( "\|" flagsField )* "," } + vfrStatementExpression[0] + ";" + { + vfrStatementgrayoutIfSuppressIf + << SuppressExist = TRUE; >> + } + ( vfrStatementStatListOld )* + E: EndIf ";" << if (SuppressExist) CRT_END_OP (E); CRT_END_OP (E); >> + ; + +vfrImageTag : + << CIfrImage IObj; >> + L:Image "=" "IMAGE_TOKEN" "\(" S1:Number "\)" << IObj.SetImageId (_STOSID(S1->getText())); IObj.SetLineNo(L->getLine()); >> + ; + +vfrLockedTag : + << CIfrLocked LObj; >> + L:Locked << LObj.SetLineNo(L->getLine()); >> + ; + +vfrStatementStatTag : + vfrImageTag | + vfrLockedTag + ; + +vfrStatementStatTagList : + vfrStatementStatTag ( "," vfrStatementStatTag )* + ; + +vfrStatementImage : + vfrImageTag + ";" + ; + +vfrStatementLocked : + vfrLockedTag + ";" + ; + +vfrStatementInconsistentIf : + << CIfrInconsistentIf IIObj; >> + L:InconsistentIf << IIObj.SetLineNo(L->getLine()); >> + Prompt "=" "STRING_TOKEN" "\(" S:Number "\)" "," << IIObj.SetError (_STOSID(S->getText())); >> + { FLAGS "=" flagsField ( "\|" flagsField )* "," } + vfrStatementExpression[0] + E:EndIf << CRT_END_OP (E); >> + ; + +vfrStatementNoSubmitIf : + << CIfrNoSubmitIf NSIObj; >> + L:NoSubmitIf << NSIObj.SetLineNo(L->getLine()); >> + Prompt "=" "STRING_TOKEN" "\(" S:Number "\)" "," << NSIObj.SetError (_STOSID(S->getText())); >> + { FLAGS "=" flagsField ( "\|" flagsField )* "," } + vfrStatementExpression[0] + E:EndIf << CRT_END_OP (E); >> + ; + +vfrStatementDisableIfQuest : + << + CIfrDisableIf DIObj; + mConstantOnlyInExpression = TRUE; + >> + L:DisableIf << DIObj.SetLineNo(L->getLine()); >> + vfrStatementExpression[0] ";" << mConstantOnlyInExpression = FALSE; >> + vfrStatementQuestionOptionList + E:EndIf << CRT_END_OP (E); >> + ; + +vfrStatementRefresh : + << CIfrRefresh RObj; >> + L:Refresh << RObj.SetLineNo(L->getLine()); >> + Interval "=" I:Number << RObj.SetRefreshInterval (_STOU8(I->getText())); >> + ; + +vfrStatementVarstoreDevice : + << CIfrVarStoreDevice VDObj; >> + L:VarstoreDevice << VDObj.SetLineNo(L->getLine()); >> + "=" "STRING_TOKEN" "\(" S:Number "\)" "," << VDObj.SetDevicePath (_STOSID(S->getText())); >> + ; + +vfrStatementSuppressIfQuest : + << CIfrSuppressIf SIObj; >> + L:SuppressIf << SIObj.SetLineNo(L->getLine()); >> + { FLAGS "=" flagsField ( "\|" flagsField )* "," } + vfrStatementExpression[0] ";" + vfrStatementQuestionOptionList + E:EndIf << CRT_END_OP (E); >> + ; + +vfrStatementGrayOutIfQuest : + << CIfrGrayOutIf GOIObj; >> + L:GrayOutIf << GOIObj.SetLineNo(L->getLine()); >> + { FLAGS "=" flagsField ( "\|" flagsField )* "," } + vfrStatementExpression[0] ";" + vfrStatementQuestionOptionList + E:EndIf << CRT_END_OP (E); >> + ; + +vfrStatementOptions : + vfrStatementOneOfOption + ; + +vfrStatementOneOfOption : + << + EFI_IFR_TYPE_VALUE Val = gZeroEfiIfrTypeValue; + CIfrOneOfOption OOOObj; + CHAR8 *VarStoreName = NULL; + >> + L:Option << OOOObj.SetLineNo(L->getLine()); >> + Text "=" "STRING_TOKEN" "\(" S:Number "\)" "," << OOOObj.SetOption (_STOSID(S->getText())); >> + Value "=" vfrConstantValueField[_GET_CURRQEST_DATATYPE()] >[Val] "," << OOOObj.SetType (_GET_CURRQEST_DATATYPE()); OOOObj.SetValue (Val); >> + F:FLAGS "=" vfrOneOfOptionFlags[OOOObj, F->getLine()] + << + _PCATCH(mCVfrDataStorage.GetVarStoreName (_GET_CURRQEST_VARTINFO().mVarStoreId, &VarStoreName), L->getLine()); + if (OOOObj.GetFlags () & 0x10) { + _PCATCH(mCVfrDefaultStore.BufferVarStoreAltConfigAdd ( + EFI_HII_DEFAULT_CLASS_STANDARD, + _GET_CURRQEST_VARTINFO(), + VarStoreName, + _GET_CURRQEST_DATATYPE (), + Val + ), L->getLine()); + } + if (OOOObj.GetFlags () & 0x20) { + _PCATCH(mCVfrDefaultStore.BufferVarStoreAltConfigAdd ( + EFI_HII_DEFAULT_CLASS_MANUFACTURING, + _GET_CURRQEST_VARTINFO(), + VarStoreName, + _GET_CURRQEST_DATATYPE (), + Val + ), L->getLine()); + } + >> + { + "," Key "=" KN:Number << + if (!mCompatibleMode) { + _PCATCH (VFR_RETURN_UNSUPPORTED, KN); + } + // + // Guid Option Key + // + CIfrOptionKey IfrOptionKey ( + gCurrentQuestion->QUESTION_ID(), + Val, + _STOQID(KN->getText()) + ); + SET_LINE_INFO (IfrOptionKey, KN); + >> + } + ( + T:"," vfrImageTag << OOOObj.SetScope (1); CRT_END_OP (T); >> + )* + ";" + ; + +vfrOneOfOptionFlags [CIfrOneOfOption & OOOObj, UINT32 LineNum] : + << + UINT8 LFlags = _GET_CURRQEST_DATATYPE(); + UINT8 HFlags = 0; + >> + oneofoptionFlagsField[HFlags, LFlags] ( "\|" oneofoptionFlagsField[HFlags, LFlags] )* + << _PCATCH(gCurrentQuestion->SetFlags(HFlags), LineNum); >> + << _PCATCH(OOOObj.SetFlags(LFlags), LineNum); >> + ; + +oneofoptionFlagsField [UINT8 & HFlags, UINT8 & LFlags] : + N:Number << $LFlags |= _STOU8(N->getText()); >> + | "OPTION_DEFAULT" << $LFlags |= 0x10; >> + | "OPTION_DEFAULT_MFG" << $LFlags |= 0x20; >> + | InteractiveFlag << $HFlags |= 0x04; >> + | NVAccessFlag << $HFlags |= 0x08; >> + | ResetRequiredFlag << $HFlags |= 0x10; >> + | LateCheckFlag << $HFlags |= 0x20; >> + | ManufacturingFlag << $LFlags |= 0x20; >> + | DefaultFlag << $LFlags |= 0x10; >> + ; + +vfrStatementLabel : + L:Label + N:Number << + if (mCompatibleMode) { + // + // Add end Label for Framework Vfr + // + CIfrLabel LObj1; + LObj1.SetLineNo(L->getLine()); + LObj1.SetNumber (0xffff); //add end label for UEFI, label number hardcode 0xffff + } + + { + CIfrLabel LObj2; + LObj2.SetLineNo(L->getLine()); + LObj2.SetNumber (_STOU16(N->getText())); + } + >> + ";" + ; + +vfrStatementBanner : + << CIfrBanner BObj; >> + B:Banner { "," } << BObj.SetLineNo(B->getLine()); >> + Title "=" "STRING_TOKEN" "\(" S:Number "\)" "," << BObj.SetTitle (_STOSID(S->getText())); >> + ( + ( + Line L:Number "," << BObj.SetLine (_STOU16(L->getText())); >> + Align + ( + Left << BObj.SetAlign (0); >> + | Center << BObj.SetAlign (1); >> + | Right << BObj.SetAlign (2); >> + ) ";" + ) + | + ( + Timeout "=" T:Number ";" << {CIfrTimeout TObj(_STOU16(T->getText()));} >> + ) + ) + ; + +//****************************************************************************** +// +// keep some syntax for compatibility but not generate any IFR object +// +vfrStatementInvalidHidden : + L:Hidden << + if (!mCompatibleMode) { + _PCATCH (VFR_RETURN_UNSUPPORTED, L); + } + >> + Value "=" Number "," + Key "=" Number ";" + ; + +vfrStatementInvalidInconsistentIf : + InconsistentIf + Prompt "=" "STRING_TOKEN" "\(" S:Number "\)" "," + { FLAGS "=" flagsField ( "\|" flagsField )* "," } + vfrStatementExpression[0] + EndIf + ";" + ; + +vfrStatementInvalidInventory : + L:Inventory << + if (!mCompatibleMode) { + _PCATCH (VFR_RETURN_UNSUPPORTED, L); + } + >> + Help "=" "STRING_TOKEN" "\(" Number "\)" "," + Text "=" "STRING_TOKEN" "\(" Number "\)" "," + { + Text "=" "STRING_TOKEN" "\(" Number "\)" + } + ";" + ; + +vfrStatementInvalidSaveRestoreDefaults : + ( + L:Save << + if (!mCompatibleMode) { + _PCATCH (VFR_RETURN_UNSUPPORTED, L); + } + >> + | + K:Restore << + if (!mCompatibleMode) { + _PCATCH (VFR_RETURN_UNSUPPORTED, K); + } + >> + ) + Defaults "," + FormId "=" Number "," + Prompt "=" "STRING_TOKEN" "\(" Number "\)" "," + Help "=" "STRING_TOKEN" "\(" Number "\)" + { "," FLAGS "=" flagsField ( "\|" flagsField )* } + { "," Key "=" Number } + ";" + ; + +//****************************************************************************** +// +// The syntax of expression +// +#token Dup("dup") "dup" +#token VarEqVal("vareqval") "vareqval" +#token Var("var") "var" +#token IdEqVal("ideqval") "ideqval" +#token IdEqId("ideqid") "ideqid" +#token IdEqValList("ideqvallist") "ideqvallist" +#token QuestionRef("questionref") "questionref" +#token RuleRef("ruleref") "ruleref" +#token StringRef("stringref") "stringref" +#token PushThis("pushthis") "pushthis" +#token True("TRUE") "TRUE" +#token False("FALSE") "FALSE" +#token One("ONE") "ONE" +#token Ones("ONES") "ONES" +#token Zero("ZERO") "ZERO" +#token Undefined("UNDEFINED") "UNDEFINED" +#token Version("VERSION") "VERSION" +#token Length("length") "length" +#token AND("AND") "AND" +#token OR("OR") "OR" +#token NOT("NOT") "NOT" +#token BitWiseNot("~") "\~" +#token BoolVal("boolval") "boolval" +#token StringVal("stringval") "stringval" +#token UnIntVal("unintval") "unintval" +#token ToUpper("toupper") "toupper" +#token ToLower("tolower") "tolower" +#token Match("match") "match" +#token Catenate("catenate") "catenate" +#token QuestionRefVal("questionrefval") "questionrefval" +#token StringRefVal("stringrefval") "stringrefval" + +// +// Root expression extension function called by other function. +// +vfrStatementExpression [UINT32 RootLevel, UINT32 ExpOpCount = 0] : + << if ($RootLevel == 0) {_CLEAR_SAVED_OPHDR ();} >> + andTerm[$RootLevel, $ExpOpCount] + ( + L:OR andTerm[$RootLevel, $ExpOpCount] << $ExpOpCount++; CIfrOr OObj(L->getLine()); >> + )* + << + // + // Extend OpCode Scope only for the root expression. + // + if ($ExpOpCount > 1 && $RootLevel == 0) { + if (_SET_SAVED_OPHDR_SCOPE()) { + CIfrEnd EObj; + if (mCIfrOpHdrLineNo != 0) { + EObj.SetLineNo (mCIfrOpHdrLineNo); + } + } + } + >> + ; + +// +// Add new sub function for the sub expression extension to remember the ExpOpCount +// This funciton is only called by sub expression. +// +vfrStatementExpressionSub [UINT32 RootLevel, UINT32 & ExpOpCount] : + andTerm[$RootLevel, $ExpOpCount] + ( + L:OR andTerm[$RootLevel, $ExpOpCount] << $ExpOpCount++; CIfrOr OObj(L->getLine()); >> + )* + ; + +andTerm[UINT32 & RootLevel, UINT32 & ExpOpCount] : + bitwiseorTerm[$RootLevel, $ExpOpCount] + ( + L:AND bitwiseorTerm [$RootLevel, $ExpOpCount] << $ExpOpCount++; CIfrAnd AObj(L->getLine()); >> + )* + ; + +bitwiseorTerm [UINT32 & RootLevel, UINT32 & ExpOpCount]: + bitwiseandTerm[$RootLevel, $ExpOpCount] + ( + L:"\|" bitwiseandTerm[$RootLevel, $ExpOpCount] << $ExpOpCount++; CIfrBitWiseOr BWOObj(L->getLine()); >> + )* + ; + +bitwiseandTerm [UINT32 & RootLevel, UINT32 & ExpOpCount]: + equalTerm[$RootLevel, $ExpOpCount] + ( + L:"&" equalTerm[$RootLevel, $ExpOpCount] << $ExpOpCount++; CIfrBitWiseAnd BWAObj(L->getLine()); >> + )* + ; + +equalTerm [UINT32 & RootLevel, UINT32 & ExpOpCount]: + compareTerm[$RootLevel, $ExpOpCount] + ( + ( + L1:"==" compareTerm[$RootLevel, $ExpOpCount] << $ExpOpCount++; CIfrEqual EObj(L1->getLine()); >> + ) + | + ( + L2:"!=" compareTerm[$RootLevel, $ExpOpCount] << $ExpOpCount++; CIfrNotEqual NEObj(L2->getLine()); >> + ) + )* + ; + +compareTerm [UINT32 & RootLevel, UINT32 & ExpOpCount]: + shiftTerm[$RootLevel, $ExpOpCount] + ( + ( + L1:"<" shiftTerm[$RootLevel, $ExpOpCount] << $ExpOpCount++; CIfrLessThan LTObj(L1->getLine()); >> + ) + | + ( + L2:"<=" shiftTerm[$RootLevel, $ExpOpCount] << $ExpOpCount++; CIfrLessEqual LEObj(L2->getLine()); >> + ) + | + ( + L3:">" shiftTerm[$RootLevel, $ExpOpCount] << $ExpOpCount++; CIfrGreaterThan GTObj(L3->getLine()); >> + ) + | + ( + L4:">=" shiftTerm[$RootLevel, $ExpOpCount] << $ExpOpCount++; CIfrGreaterEqual GEObj(L4->getLine()); >> + ) + )* + ; + +shiftTerm [UINT32 & RootLevel, UINT32 & ExpOpCount]: + addMinusTerm[$RootLevel, $ExpOpCount] + ( + ( + L1:"\<<" addMinusTerm[$RootLevel, $ExpOpCount] << $ExpOpCount++; CIfrShiftLeft SLObj(L1->getLine()); >> + ) + | + ( + L2:"\>>" addMinusTerm[$RootLevel, $ExpOpCount] << $ExpOpCount++; CIfrShiftRight SRObj(L2->getLine()); >> + ) + )* + ; + +addMinusTerm [UINT32 & RootLevel, UINT32 & ExpOpCount]: + multdivmodTerm[$RootLevel, $ExpOpCount] + ( + ( + L1:"\+" multdivmodTerm[$RootLevel, $ExpOpCount] << $ExpOpCount++; CIfrAdd AObj(L1->getLine()); >> + ) + | + ( + L2:"\-" multdivmodTerm[$RootLevel, $ExpOpCount] << $ExpOpCount++; CIfrSubtract SObj(L2->getLine()); >> + ) + )* + ; + +multdivmodTerm [UINT32 & RootLevel, UINT32 & ExpOpCount]: + castTerm[$RootLevel, $ExpOpCount] + ( + ( + L1:"\*" castTerm[$RootLevel, $ExpOpCount] << $ExpOpCount++; CIfrMultiply MObj(L1->getLine()); >> + ) + | + ( + L2:"/" castTerm[$RootLevel, $ExpOpCount] << $ExpOpCount++; CIfrDivide DObj(L2->getLine()); >> + ) + | + ( + L3:"%" castTerm[$RootLevel, $ExpOpCount] << $ExpOpCount++; CIfrModulo MObj(L3->getLine()); >> + ) + )* + ; + +castTerm [UINT32 & RootLevel, UINT32 & ExpOpCount]: + << UINT8 CastType = 0xFF; >> + ( + L:"\(" + ( + Boolean << CastType = 0; >> + | Uint64 << CastType = 1; >> + | Uint32 << CastType = 1; >> + | Uint16 << CastType = 1; >> + | Uint8 << CastType = 1; >> + ) + "\)" + )* + atomTerm[$RootLevel, $ExpOpCount] + << + switch (CastType) { + case 0: { CIfrToBoolean TBObj(L->getLine()); $ExpOpCount++; } break; + case 1: { CIfrToUint TUObj(L->getLine()); $ExpOpCount++; } break; + } + >> + ; + +atomTerm [UINT32 & RootLevel, UINT32 & ExpOpCount]: + vfrExpressionCatenate[$RootLevel, $ExpOpCount] + | vfrExpressionMatch[$RootLevel, $ExpOpCount] + | vfrExpressionParen[$RootLevel, $ExpOpCount] + | vfrExpressionBuildInFunction[$RootLevel, $ExpOpCount] + | vfrExpressionConstant[$RootLevel, $ExpOpCount] + | vfrExpressionUnaryOp[$RootLevel, $ExpOpCount] + | vfrExpressionTernaryOp[$RootLevel, $ExpOpCount] + | ( + L:NOT + atomTerm[$RootLevel, $ExpOpCount] << { CIfrNot NObj(L->getLine()); $ExpOpCount++; } >> + ) + ; + +vfrExpressionCatenate [UINT32 & RootLevel, UINT32 & ExpOpCount]: + L:Catenate + "\(" + vfrStatementExpressionSub[$RootLevel + 1, $ExpOpCount] + "," + vfrStatementExpressionSub[$RootLevel + 1, $ExpOpCount] + "\)" << { CIfrCatenate CObj(L->getLine()); $ExpOpCount++; } >> + ; + +vfrExpressionMatch [UINT32 & RootLevel, UINT32 & ExpOpCount]: + L:Match + "\(" + vfrStatementExpressionSub[$RootLevel + 1, $ExpOpCount] + "," + vfrStatementExpressionSub[$RootLevel + 1, $ExpOpCount] + "\)" << { CIfrMatch MObj(L->getLine()); $ExpOpCount++; } >> + ; + +vfrExpressionParen [UINT32 & RootLevel, UINT32 & ExpOpCount]: + "\(" + vfrStatementExpressionSub[$RootLevel + 1, $ExpOpCount] + "\)" + ; + +vfrExpressionBuildInFunction [UINT32 & RootLevel, UINT32 & ExpOpCount] : + dupExp[$RootLevel, $ExpOpCount] + | vareqvalExp[$RootLevel, $ExpOpCount] //Compatible for Framework vareqval + | ideqvalExp[$RootLevel, $ExpOpCount] + | ideqidExp[$RootLevel, $ExpOpCount] + | ideqvallistExp[$RootLevel, $ExpOpCount] + | questionref13Exp[$RootLevel, $ExpOpCount] + | rulerefExp[$RootLevel, $ExpOpCount] + | stringref1Exp[$RootLevel, $ExpOpCount] + | pushthisExp[$RootLevel, $ExpOpCount] + ; + +dupExp [UINT32 & RootLevel, UINT32 & ExpOpCount] : + L:Dup << { CIfrDup DObj(L->getLine()); _SAVE_OPHDR_COND(DObj, ($ExpOpCount == 0), L->getLine()); $ExpOpCount++; } >> + ; + +vareqvalExp [UINT32 & RootLevel, UINT32 & ExpOpCount] : + << + EFI_QUESTION_ID QId; + UINT32 Mask; + UINT16 ConstVal; + CHAR8 *VarIdStr; + UINT32 LineNo; + EFI_VFR_VARSTORE_TYPE VarStoreType = EFI_VFR_VARSTORE_INVALID; + EFI_VFR_RETURN_CODE VfrReturnCode = VFR_RETURN_SUCCESS; + >> + L:VarEqVal << + if (!mCompatibleMode) { + _PCATCH (VFR_RETURN_UNSUPPORTED, L); + } + >> + VK:Var + OpenParen + VN:Number << + VarIdStr = NULL; _STRCAT(&VarIdStr, VK->getText()); _STRCAT(&VarIdStr, VN->getText()); + VfrReturnCode = mCVfrDataStorage.GetVarStoreType (VarIdStr, VarStoreType); + if (VfrReturnCode == VFR_RETURN_UNDEFINED) { + _PCATCH (mCVfrDataStorage.DeclareEfiVarStore ( + VarIdStr, + &mFormsetGuid, + _STOSID(VN->getText()), + 0x2, //default type is UINT16 + FALSE + ), VN); + } else { + _PCATCH (VfrReturnCode, VN); + } + mCVfrQuestionDB.GetQuestionId (NULL, VarIdStr, QId, Mask); + LineNo = GET_LINENO(VN); + >> + CloseParen + ( + ( + "==" + V1:Number << ConstVal = _STOU16(V1->getText()); >> + << + if (Mask == 0) { + CIfrEqIdVal EIVObj (L->getLine()); + _SAVE_OPHDR_COND (EIVObj, ($ExpOpCount == 0), L->getLine()); + EIVObj.SetQuestionId (QId, VarIdStr, LineNo); + EIVObj.SetValue (ConstVal); + $ExpOpCount++; + } else { + IdEqValDoSpecial ($ExpOpCount, L->getLine(), QId, VarIdStr, Mask, ConstVal, EQUAL); + } + >> + ) + | + ( + "<=" + V2:Number << ConstVal = _STOU16(V2->getText()); >> + << IdEqValDoSpecial ($ExpOpCount, L->getLine(), QId, VarIdStr, Mask, ConstVal, LESS_EQUAL); >> + ) + | + ( + "<" + V3:Number << ConstVal = _STOU16(V3->getText()); >> + << IdEqValDoSpecial ($ExpOpCount, L->getLine(), QId, VarIdStr, Mask, ConstVal, LESS_THAN); >> + ) + | + ( + ">=" + V4:Number << ConstVal = _STOU16(V4->getText()); >> + << IdEqValDoSpecial ($ExpOpCount, L->getLine(), QId, VarIdStr, Mask, ConstVal, GREATER_EQUAL); >> + ) + | + ( + ">" + V5:Number << ConstVal = _STOU16(V5->getText()); >> + << IdEqValDoSpecial ($ExpOpCount, L->getLine(), QId, VarIdStr, Mask, ConstVal, GREATER_THAN); >> + ) + ) + ; + +ideqvalExp [UINT32 & RootLevel, UINT32 & ExpOpCount] : + << + EFI_QUESTION_ID QId; + UINT32 Mask; + UINT16 ConstVal; + CHAR8 *VarIdStr; + UINT32 LineNo; + >> + L:IdEqVal + vfrQuestionDataFieldName[QId, Mask, VarIdStr, LineNo] + ( + ( + "==" + V1:Number << ConstVal = _STOU16(V1->getText()); >> + << + if (Mask == 0) { + CIfrEqIdVal EIVObj (L->getLine()); + _SAVE_OPHDR_COND (EIVObj, ($ExpOpCount == 0), L->getLine()); + EIVObj.SetQuestionId (QId, VarIdStr, LineNo); + EIVObj.SetValue (ConstVal); + $ExpOpCount++; + } else { + IdEqValDoSpecial ($ExpOpCount, L->getLine(), QId, VarIdStr, Mask, ConstVal, EQUAL); + } + >> + ) + | + ( + "<=" + V2:Number << ConstVal = _STOU16(V2->getText()); >> + << IdEqValDoSpecial ($ExpOpCount, L->getLine(), QId, VarIdStr, Mask, ConstVal, LESS_EQUAL); >> + ) + | + ( + "<" + V3:Number << ConstVal = _STOU16(V3->getText()); >> + << IdEqValDoSpecial ($ExpOpCount, L->getLine(), QId, VarIdStr, Mask, ConstVal, LESS_THAN); >> + ) + | + ( + ">=" + V4:Number << ConstVal = _STOU16(V4->getText()); >> + << IdEqValDoSpecial ($ExpOpCount, L->getLine(), QId, VarIdStr, Mask, ConstVal, GREATER_EQUAL); >> + ) + | + ( + ">" + V5:Number << ConstVal = _STOU16(V5->getText()); >> + << IdEqValDoSpecial ($ExpOpCount, L->getLine(), QId, VarIdStr, Mask, ConstVal, GREATER_THAN); >> + ) + ) + ; + +ideqidExp[UINT32 & RootLevel, UINT32 & ExpOpCount] : + << + EFI_QUESTION_ID QId[2]; + UINT32 Mask[2]; + CHAR8 *VarIdStr[2]; + UINT32 LineNo[2]; + >> + L:IdEqId + vfrQuestionDataFieldName[QId[0], Mask[0], VarIdStr[0], LineNo[0]] + ( + ( + "==" + vfrQuestionDataFieldName[QId[1], Mask[1], VarIdStr[1], LineNo[1]] + << + if (Mask[0] & Mask[1]) { + IdEqIdDoSpecial ($ExpOpCount, L->getLine(), QId[0], VarIdStr[0], Mask[0], QId[1], VarIdStr[1], Mask[1], EQUAL); + } else { + CIfrEqIdId EIIObj(L->getLine()); + _SAVE_OPHDR_COND (EIIObj, ($ExpOpCount == 0), L->getLine()); + EIIObj.SetQuestionId1 (QId[0], VarIdStr[0], LineNo[0]); + EIIObj.SetQuestionId2 (QId[1], VarIdStr[1], LineNo[1]); + $ExpOpCount++; + } + >> + ) + | + ( + "<=" + vfrQuestionDataFieldName[QId[1], Mask[1], VarIdStr[1], LineNo[1]] + << IdEqIdDoSpecial ($ExpOpCount, L->getLine(), QId[0], VarIdStr[0], Mask[0], QId[1], VarIdStr[1], Mask[1], LESS_EQUAL); >> + ) + | + ( + "<" + vfrQuestionDataFieldName[QId[1], Mask[1], VarIdStr[1], LineNo[1]] + << IdEqIdDoSpecial ($ExpOpCount, L->getLine(), QId[0], VarIdStr[0], Mask[0], QId[1], VarIdStr[1], Mask[1], LESS_THAN); >> + ) + | + ( + ">=" + vfrQuestionDataFieldName[QId[1], Mask[1], VarIdStr[1], LineNo[1]] + << IdEqIdDoSpecial ($ExpOpCount, L->getLine(), QId[0], VarIdStr[0], Mask[0], QId[1], VarIdStr[1], Mask[1], GREATER_EQUAL); >> + ) + | + ( + ">" + vfrQuestionDataFieldName[QId[1], Mask[1], VarIdStr[1], LineNo[1]] + << IdEqIdDoSpecial ($ExpOpCount, L->getLine(), QId[0], VarIdStr[0], Mask[0], QId[1], VarIdStr[1], Mask[1], GREATER_THAN); >> + ) + ) + ; + +ideqvallistExp[UINT32 & RootLevel, UINT32 & ExpOpCount] : + << + UINT16 ListLen = 0; + EFI_QUESTION_ID QId; + UINT32 Mask; + UINT16 ValueList[EFI_IFR_MAX_LENGTH] = {0,}; + CHAR8 *VarIdStr; + UINT32 LineNo; + >> + L:IdEqValList + vfrQuestionDataFieldName[QId, Mask, VarIdStr, LineNo] + "==" + ( + V:Number << ValueList[ListLen] = _STOU16(V->getText()); ListLen++; >> + )+ + << + if (Mask != 0) { + IdEqListDoSpecial ($ExpOpCount, LineNo, QId, VarIdStr, Mask, ListLen, ValueList); + } else { + UINT16 Index; + CIfrEqIdList EILObj(L->getLine()); + if (QId != EFI_QUESTION_ID_INVALID) { + EILObj.SetQuestionId (QId, VarIdStr, LineNo); + } + EILObj.SetListLength (ListLen); + for (Index = 0; Index < ListLen; Index++) { + EILObj.SetValueList (Index, ValueList[Index]); + } + + EILObj.UpdateIfrBuffer(); + _SAVE_OPHDR_COND (EILObj, ($ExpOpCount == 0), L->getLine()); + + if (QId == EFI_QUESTION_ID_INVALID) { + EILObj.SetQuestionId (QId, VarIdStr, LineNo); + } + $ExpOpCount++; + } + >> + ; + +questionref13Exp[UINT32 & RootLevel, UINT32 & ExpOpCount] : + << + UINT8 Type = 0x1; + EFI_STRING_ID DevPath; + EFI_GUID Guid; + EFI_QUESTION_ID QId = EFI_QUESTION_ID_INVALID; + UINT32 BitMask; + CHAR8 *QName = NULL; + UINT32 LineNo = 0; + >> + L:QuestionRef + ( + ( + << Type = 0x3; >> + { + Path "=" "STRING_TOKEN" "\(" S:Number "\)" << Type = 0x4; DevPath = _STOSID(S->getText()); >> + } + { + Uuid "=" guidDefinition[Guid] << Type = 0x5; >> + } + ) + | + ( + "\(" + ( + QN:StringIdentifier << + QName = QN->getText(); + LineNo = QN->getLine(); + mCVfrQuestionDB.GetQuestionId (QN->getText(), NULL, QId, BitMask); + >> + | ID:Number << QId = _STOQID(ID->getText()); >> + ) + "\)" + ) + ) + << + switch (Type) { + case 0x1: {CIfrQuestionRef1 QR1Obj(L->getLine()); _SAVE_OPHDR_COND (QR1Obj, ($ExpOpCount == 0), L->getLine()); QR1Obj.SetQuestionId (QId, QName, LineNo); break;} + case 0x3: {CIfrQuestionRef3 QR3Obj(L->getLine()); _SAVE_OPHDR_COND (QR3Obj, ($ExpOpCount == 0), L->getLine()); break;} + case 0x4: {CIfrQuestionRef3_2 QR3_2Obj(L->getLine()); _SAVE_OPHDR_COND (QR3_2Obj, ($ExpOpCount == 0), L->getLine()); QR3_2Obj.SetDevicePath (DevPath); break;} + case 0x5: {CIfrQuestionRef3_3 QR3_3Obj(L->getLine()); _SAVE_OPHDR_COND (QR3_3Obj, ($ExpOpCount == 0), L->getLine()); QR3_3Obj.SetDevicePath (DevPath); QR3_3Obj.SetGuid (&Guid); break;} + } + $ExpOpCount++; + >> + ; + +rulerefExp[UINT32 & RootLevel, UINT32 & ExpOpCount] : + L:RuleRef + "\(" RN:StringIdentifier "\)" << { CIfrRuleRef RRObj(L->getLine()); _SAVE_OPHDR_COND (RRObj, ($ExpOpCount == 0), L->getLine()); RRObj.SetRuleId (mCVfrRulesDB.GetRuleId (RN->getText())); } $ExpOpCount++; >> + ; + +//****************************************************** +// PARSE: +// stringref (STR_FORM_SET_TITLE) +// +stringref1Exp[UINT32 & RootLevel, UINT32 & ExpOpCount] : + L:StringRef + "\(" S:Number "\)" << { CIfrStringRef1 SR1Obj(L->getLine()); _SAVE_OPHDR_COND (SR1Obj, ($ExpOpCount == 0), L->getLine()); SR1Obj.SetStringId (_STOSID(S->getText())); $ExpOpCount++; } >> + ; + +pushthisExp[UINT32 & RootLevel, UINT32 & ExpOpCount] : + L:PushThis << { CIfrThis TObj(L->getLine()); _SAVE_OPHDR_COND (TObj, ($ExpOpCount == 0), L->getLine()); $ExpOpCount++; } >> + ; + +vfrExpressionConstant[UINT32 & RootLevel, UINT32 & ExpOpCount] : + L1:True << CIfrTrue TObj(L1->getLine()); _SAVE_OPHDR_COND (TObj, ($ExpOpCount == 0), L1->getLine()); $ExpOpCount++; >> + | L2:False << CIfrFalse FObj(L2->getLine()); _SAVE_OPHDR_COND (FObj, ($ExpOpCount == 0), L2->getLine()); $ExpOpCount++; >> + | L3:One << CIfrOne OObj(L3->getLine()); _SAVE_OPHDR_COND (OObj, ($ExpOpCount == 0), L3->getLine()); $ExpOpCount++; >> + | L4:Ones << CIfrOnes OObj(L4->getLine()); _SAVE_OPHDR_COND (OObj, ($ExpOpCount == 0), L4->getLine()); $ExpOpCount++; >> + | L5:Zero << CIfrZero ZObj(L5->getLine()); _SAVE_OPHDR_COND (ZObj, ($ExpOpCount == 0), L5->getLine()); $ExpOpCount++; >> + | L6:Undefined << CIfrUndefined UObj(L6->getLine()); _SAVE_OPHDR_COND (UObj, ($ExpOpCount == 0), L6->getLine()); $ExpOpCount++; >> + | L7:Version << CIfrVersion VObj(L7->getLine()); _SAVE_OPHDR_COND (VObj, ($ExpOpCount == 0), L7->getLine()); $ExpOpCount++; >> + | V:Number << CIfrUint64 U64Obj(V->getLine()); U64Obj.SetValue (_STOU64(V->getText())); _SAVE_OPHDR_COND (U64Obj, ($ExpOpCount == 0), V->getLine()); $ExpOpCount++; >> + ; + +vfrExpressionUnaryOp[UINT32 & RootLevel, UINT32 & ExpOpCount] : + lengthExp[$RootLevel, $ExpOpCount] + | bitwisenotExp[$RootLevel, $ExpOpCount] + | question2refExp[$RootLevel, $ExpOpCount] + | stringref2Exp[$RootLevel, $ExpOpCount] + | toboolExp[$RootLevel, $ExpOpCount] + | unintExp[$RootLevel, $ExpOpCount] + | toupperExp[$RootLevel, $ExpOpCount] + | tolwerExp[$RootLevel, $ExpOpCount] + ; + +lengthExp[UINT32 & RootLevel, UINT32 & ExpOpCount] : + L:Length + "\(" vfrStatementExpressionSub[$RootLevel + 1, $ExpOpCount] "\)" + << { CIfrLength LObj(L->getLine()); $ExpOpCount++; } >> + ; + +bitwisenotExp[UINT32 & RootLevel, UINT32 & ExpOpCount] : + L:BitWiseNot + "\(" vfrStatementExpressionSub[$RootLevel + 1, $ExpOpCount] "\)" + << { CIfrBitWiseNot BWNObj(L->getLine()); $ExpOpCount++; } >> + ; + +question2refExp[UINT32 & RootLevel, UINT32 & ExpOpCount] : + L:QuestionRefVal + "\(" vfrStatementExpressionSub[$RootLevel + 1, $ExpOpCount] "\)" + << { CIfrQuestionRef2 QR2Obj(L->getLine()); $ExpOpCount++; } >> + ; + +stringref2Exp[UINT32 & RootLevel, UINT32 & ExpOpCount] : + L:StringRefVal + "\(" vfrStatementExpressionSub[$RootLevel + 1, $ExpOpCount] "\)" + << { CIfrStringRef2 SR2Obj(L->getLine()); $ExpOpCount++; } >> + ; + +toboolExp[UINT32 & RootLevel, UINT32 & ExpOpCount] : + L:BoolVal + "\(" vfrStatementExpressionSub[$RootLevel + 1, $ExpOpCount] "\)" + << { CIfrToBoolean TBObj(L->getLine()); $ExpOpCount++; } >> + ; + +tostringExp[UINT32 & RootLevel, UINT32 & ExpOpCount] : + << UINT8 Fmt = 0; >> + L:StringVal + { + Format "=" F:Number "," << Fmt = _STOU8(F->getText()); >> + } + "\(" vfrStatementExpressionSub[$RootLevel + 1, $ExpOpCount] "\)" + << { CIfrToString TSObj(L->getLine()); TSObj.SetFormat (Fmt); $ExpOpCount++; } >> + ; + +unintExp[UINT32 & RootLevel, UINT32 & ExpOpCount] : + L:UnIntVal + "\(" vfrStatementExpressionSub[$RootLevel + 1, $ExpOpCount] "\)" + << { CIfrToUint TUObj(L->getLine()); $ExpOpCount++; } >> + ; + +toupperExp[UINT32 & RootLevel, UINT32 & ExpOpCount] : + L:ToUpper + "\(" vfrStatementExpressionSub[$RootLevel + 1, $ExpOpCount] "\)" + << { CIfrToUpper TUObj(L->getLine()); $ExpOpCount++; } >> + ; + +tolwerExp[UINT32 & RootLevel, UINT32 & ExpOpCount] : + L:ToLower + "\(" vfrStatementExpressionSub[$RootLevel + 1, $ExpOpCount] "\)" + << { CIfrToLower TLObj(L->getLine()); $ExpOpCount++; } >> + ; + +vfrExpressionTernaryOp[UINT32 & RootLevel, UINT32 & ExpOpCount] : + conditionalExp[$RootLevel, $ExpOpCount] + | findExp[$RootLevel, $ExpOpCount] + | midExp[$RootLevel, $ExpOpCount] + | tokenExp[$RootLevel, $ExpOpCount] + | spanExp[$RootLevel, $ExpOpCount] + ; + +#token Cond("cond") "cond" +#token Find("find") "find" +#token Mid("mid") "mid" +#token Tok("token") "token" +#token Span("span") "span" + +conditionalExp[UINT32 & RootLevel, UINT32 & ExpOpCount] : + L:Cond "\(" + vfrStatementExpressionSub[$RootLevel + 1, $ExpOpCount] + "?" + vfrStatementExpressionSub[$RootLevel + 1, $ExpOpCount] + ":" + vfrStatementExpressionSub[$RootLevel + 1, $ExpOpCount] + "\)" << { CIfrConditional CObj(L->getLine()); $ExpOpCount++; } >> + ; + +findExp[UINT32 & RootLevel, UINT32 & ExpOpCount] : + << UINT8 Format; >> + L:Find "\(" + findFormat[Format] ( "\|" findFormat[Format] )* + "," + vfrStatementExpressionSub[$RootLevel + 1, $ExpOpCount] + "," + vfrStatementExpressionSub[$RootLevel + 1, $ExpOpCount] + "," + vfrStatementExpressionSub[$RootLevel + 1, $ExpOpCount] + "\)" << { CIfrFind FObj(L->getLine()); FObj.SetFormat (Format); $ExpOpCount++; } >> + ; + +findFormat [UINT8 & Format] : + "SENSITIVE" << $Format = 0x00; >> + | "INSENSITIVE" << $Format = 0x01; >> + ; + +midExp[UINT32 & RootLevel, UINT32 & ExpOpCount] : + L:Mid "\(" + vfrStatementExpressionSub[$RootLevel + 1, $ExpOpCount] + "," + vfrStatementExpressionSub[$RootLevel + 1, $ExpOpCount] + "," + vfrStatementExpressionSub[$RootLevel + 1, $ExpOpCount] + "\)" << { CIfrMid MObj(L->getLine()); $ExpOpCount++; } >> + ; + +tokenExp[UINT32 & RootLevel, UINT32 & ExpOpCount] : + L:Tok "\(" + vfrStatementExpressionSub[$RootLevel + 1, $ExpOpCount] + "," + vfrStatementExpressionSub[$RootLevel + 1, $ExpOpCount] + "," + vfrStatementExpressionSub[$RootLevel + 1, $ExpOpCount] + "\)" << { CIfrToken TObj(L->getLine()); $ExpOpCount++; } >> + ; + +spanExp[UINT32 & RootLevel, UINT32 & ExpOpCount] : + << UINT8 Flags = 0; >> + S:Span "\(" + FLAGS "=" spanFlags[Flags] ( "\|" spanFlags[Flags] )* + "," + vfrStatementExpressionSub[$RootLevel + 1, $ExpOpCount] + "," + vfrStatementExpressionSub[$RootLevel + 1, $ExpOpCount] + "," + vfrStatementExpressionSub[$RootLevel + 1, $ExpOpCount] + "\)" << { CIfrSpan SObj(S->getLine()); SObj.SetFlags(Flags); $ExpOpCount++; } >> + ; + +spanFlags [UINT8 & Flags] : + N:Number << $Flags |= _STOU8(N->getText()); >> + | "LAST_NON_MATCH" << $Flags |= 0x00; >> + | "FIRST_NON_MATCH" << $Flags |= 0x01; >> + ; + +#token StringIdentifier("string identifier") "[A-Za-z_][A-Za-z_0-9]*" +#token Number("numeric value") "(0x[0-9A-Fa-f]+) | [0-9]+" + +//****************************************************************************** +// +// Parser class definition. +// +class EfiVfrParser { +<< +private: + UINT8 mParserStatus; + BOOLEAN mConstantOnlyInExpression; + + CVfrDefaultStore mCVfrDefaultStore; + CVfrDataStorage mCVfrDataStorage; + CVfrQuestionDB mCVfrQuestionDB; + CVfrRulesDB mCVfrRulesDB; + + CIfrOpHeader *mCIfrOpHdr; + UINT32 mCIfrOpHdrLineNo; + VOID _SAVE_OPHDR_COND (IN CIfrOpHeader &, IN BOOLEAN, UINT32 LineNo = 0); + VOID _CLEAR_SAVED_OPHDR (VOID); + BOOLEAN _SET_SAVED_OPHDR_SCOPE (VOID); + + + EFI_VARSTORE_INFO mCurrQestVarInfo; + +// +// For framework vfr compatibility +// + BOOLEAN mCompatibleMode; + EFI_GUID mFormsetGuid; + + VOID _CRT_OP (IN BOOLEAN); + + VOID _SAVE_CURRQEST_VARINFO (IN EFI_VARSTORE_INFO &); + EFI_VARSTORE_INFO & _GET_CURRQEST_VARTINFO (VOID); + + UINT8 _GET_CURRQEST_DATATYPE (); + UINT32 _GET_CURRQEST_VARSIZE (); + +public: + VOID _PCATCH (IN INTN, IN INTN, IN ANTLRTokenPtr, IN CHAR8 *); + VOID _PCATCH (IN EFI_VFR_RETURN_CODE); + VOID _PCATCH (IN EFI_VFR_RETURN_CODE, IN ANTLRTokenPtr); + VOID _PCATCH (IN EFI_VFR_RETURN_CODE, IN UINT32); + VOID _PCATCH (IN EFI_VFR_RETURN_CODE, IN UINT32, IN CHAR8 *); + + VOID syn (ANTLRAbstractToken *, ANTLRChar *, SetWordType *, ANTLRTokenType, INT32); + + CHAR8* TrimHex (IN CHAR8 *, OUT BOOLEAN *); + CHAR8* _U32TOS (IN UINT32); + UINT8 _STOU8 (IN CHAR8 *); + UINT16 _STOU16 (IN CHAR8 *); + UINT32 _STOU32 (IN CHAR8 *); + UINT64 _STOU64 (IN CHAR8 *); + EFI_HII_DATE _STOD (IN CHAR8 *, IN CHAR8 *, IN CHAR8 *); + EFI_HII_TIME _STOT (IN CHAR8 *, IN CHAR8 *, IN CHAR8 *); + + EFI_STRING_ID _STOSID (IN CHAR8 *); + EFI_FORM_ID _STOFID (IN CHAR8 *); + EFI_QUESTION_ID _STOQID (IN CHAR8 *); + + VOID _STRCAT (IN OUT CHAR8 **, IN CHAR8 *); + + VOID _CRGUID (EFI_GUID *, CHAR8 *, CHAR8 *, CHAR8 *, CHAR8 *, CHAR8 *, CHAR8 *, CHAR8 *, CHAR8 *, CHAR8 *, CHAR8 *, CHAR8 *); + VOID _DeclareDefaultLinearVarStore (IN UINT32); + VOID _DeclareStandardDefaultStorage (IN UINT32); + VOID _DeclareDefaultFrameworkVarStore (IN UINT32); + + VOID AssignQuestionKey (IN CIfrQuestionHeader &, IN ANTLRTokenPtr); + + VOID ConvertIdExpr (IN UINT32 &, IN UINT32, IN EFI_QUESTION_ID, IN CHAR8 *, IN UINT32); + VOID IdEqValDoSpecial (IN UINT32 &, IN UINT32, IN EFI_QUESTION_ID, IN CHAR8 *, IN UINT32, IN UINT16, IN EFI_COMPARE_TYPE); + VOID IdEqIdDoSpecial (IN UINT32 &, IN UINT32, IN EFI_QUESTION_ID, IN CHAR8 *, IN UINT32, IN EFI_QUESTION_ID, IN CHAR8 *, IN UINT32, IN EFI_COMPARE_TYPE); + VOID IdEqListDoSpecial (IN UINT32 &, IN UINT32, IN EFI_QUESTION_ID, IN CHAR8 *, IN UINT32, IN UINT16, IN UINT16 *); +// +// For framework vfr compatibility +// + VOID SetCompatibleMode (IN BOOLEAN); +>> +} + +<< +VOID +EfiVfrParser::_SAVE_OPHDR_COND ( + IN CIfrOpHeader &OpHdr, + IN BOOLEAN Cond, + IN UINT32 LineNo + ) +{ + if (Cond == TRUE) { + if (mCIfrOpHdr != NULL) { + return ; + } + mCIfrOpHdr = new CIfrOpHeader(OpHdr); + mCIfrOpHdrLineNo = LineNo; + } +} + +VOID +EfiVfrParser::_CLEAR_SAVED_OPHDR ( + VOID + ) +{ + mCIfrOpHdr = NULL; + mCIfrOpHdrLineNo = 0; +} + +BOOLEAN +EfiVfrParser::_SET_SAVED_OPHDR_SCOPE ( + VOID + ) +{ + if (mCIfrOpHdr != NULL) { + mCIfrOpHdr->SetScope (1); + return TRUE; + } + // + // IfrOpHdr is not set, FALSE is return. + // + return FALSE; +} + +VOID +EfiVfrParser::_CRT_OP ( + IN BOOLEAN Crt + ) +{ + gCreateOp = Crt; +} + +VOID +EfiVfrParser::_SAVE_CURRQEST_VARINFO ( + IN EFI_VARSTORE_INFO &Info + ) +{ + mCurrQestVarInfo = Info; +} + +EFI_VARSTORE_INFO & +EfiVfrParser::_GET_CURRQEST_VARTINFO ( + VOID + ) +{ + return mCurrQestVarInfo; +} + +UINT8 +EfiVfrParser::_GET_CURRQEST_DATATYPE ( + VOID + ) +{ + return mCurrQestVarInfo.mVarType; +} + +UINT32 +EfiVfrParser::_GET_CURRQEST_VARSIZE ( + VOID + ) +{ + return mCurrQestVarInfo.mVarTotalSize; +} + +VOID +EfiVfrParser::_PCATCH ( + IN INTN ReturnCode, + IN INTN ExpectCode, + IN ANTLRTokenPtr Tok, + IN CHAR8 *ErrorMsg + ) +{ + if (ReturnCode != ExpectCode) { + mParserStatus++; + gCVfrErrorHandle.PrintMsg (Tok->getLine(), Tok->getText(), "Error", ErrorMsg); + } +} + +VOID +EfiVfrParser::_PCATCH ( + IN EFI_VFR_RETURN_CODE ReturnCode + ) +{ + mParserStatus += gCVfrErrorHandle.HandleError (ReturnCode); +} + +VOID +EfiVfrParser::_PCATCH ( + IN EFI_VFR_RETURN_CODE ReturnCode, + IN ANTLRTokenPtr Tok + ) +{ + mParserStatus += gCVfrErrorHandle.HandleError (ReturnCode, Tok->getLine(), Tok->getText()); +} + +VOID +EfiVfrParser::_PCATCH ( + IN EFI_VFR_RETURN_CODE ReturnCode, + IN UINT32 LineNum + ) +{ + mParserStatus += gCVfrErrorHandle.HandleError (ReturnCode, LineNum); +} + +VOID +EfiVfrParser::_PCATCH ( + IN EFI_VFR_RETURN_CODE ReturnCode, + IN UINT32 LineNum, + IN CHAR8 *ErrorMsg + ) +{ + mParserStatus += gCVfrErrorHandle.HandleError (ReturnCode, LineNum, ErrorMsg); +} + +VOID +EfiVfrParser::syn ( + ANTLRAbstractToken *Tok, + ANTLRChar *Egroup, + SetWordType *Eset, + ANTLRTokenType ETok, + INT32 Huh + ) +{ + gCVfrErrorHandle.HandleError (VFR_RETURN_MISMATCHED, Tok->getLine(), Tok->getText()); + + mParserStatus += 1; +} + +CHAR8 * +EfiVfrParser::TrimHex ( + IN CHAR8 *Str, + OUT BOOLEAN *IsHex + ) +{ + *IsHex = FALSE; + + while (*Str && *Str == ' ') { + Str++; + } + while (*Str && *Str == '0') { + Str++; + } + if (*Str && (*Str == 'x' || *Str == 'X')) { + Str++; + *IsHex = TRUE; + } + + return Str; +} + +CHAR8 * +EfiVfrParser::_U32TOS ( + IN UINT32 Value + ) +{ + CHAR8 *Str; + Str = new CHAR8[20]; + sprintf (Str, "%d", Value); + return Str; +} + +UINT8 +EfiVfrParser::_STOU8 ( + IN CHAR8*Str + ) +{ + BOOLEAN IsHex; + UINT8 Value; + CHAR8 c; + + Str = TrimHex (Str, &IsHex); + for (Value = 0; (c = *Str) != '\0'; Str++) { + // + // BUG: does not handle overflow here + // + (IsHex == TRUE) ? (Value <<= 4) : (Value *= 10); + + if ((IsHex == TRUE) && (c >= 'a') && (c <= 'f')) { + Value += (c - 'a' + 10); + } + if ((IsHex == TRUE) && (c >= 'A') && (c <= 'F')) { + Value += (c - 'A' + 10); + } + if (c >= '0' && c <= '9') { + Value += (c - '0'); + } + } + + return Value; +} + +UINT16 +EfiVfrParser::_STOU16 ( + IN CHAR8*Str + ) +{ + BOOLEAN IsHex; + UINT16 Value; + CHAR8 c; + + Str = TrimHex (Str, &IsHex); + for (Value = 0; (c = *Str) != '\0'; Str++) { + // + // BUG: does not handle overflow here + // + (IsHex == TRUE) ? (Value <<= 4) : (Value *= 10); + + if ((IsHex == TRUE) && (c >= 'a') && (c <= 'f')) { + Value += (c - 'a' + 10); + } + if ((IsHex == TRUE) && (c >= 'A') && (c <= 'F')) { + Value += (c - 'A' + 10); + } + if (c >= '0' && c <= '9') { + Value += (c - '0'); + } + } + + return Value; +} + +UINT32 +EfiVfrParser::_STOU32 ( + IN CHAR8*Str + ) +{ + BOOLEAN IsHex; + UINT32 Value; + CHAR8 c; + + Str = TrimHex (Str, &IsHex); + for (Value = 0; (c = *Str) != '\0'; Str++) { + // + // BUG: does not handle overflow here + // + (IsHex == TRUE) ? (Value <<= 4) : (Value *= 10); + + if ((IsHex == TRUE) && (c >= 'a') && (c <= 'f')) { + Value += (c - 'a' + 10); + } + if ((IsHex == TRUE) && (c >= 'A') && (c <= 'F')) { + Value += (c - 'A' + 10); + } + if (c >= '0' && c <= '9') { + Value += (c - '0'); + } + } + + return Value; +} + +UINT64 +EfiVfrParser::_STOU64 ( + IN CHAR8*Str + ) +{ + BOOLEAN IsHex; + UINT64 Value; + CHAR8 c; + + Str = TrimHex (Str, &IsHex); + for (Value = 0; (c = *Str) != '\0'; Str++) { + // + // BUG: does not handle overflow here + // + (IsHex == TRUE) ? (Value <<= 4) : (Value *= 10); + + if ((IsHex == TRUE) && (c >= 'a') && (c <= 'f')) { + Value += (c - 'a' + 10); + } + if ((IsHex == TRUE) && (c >= 'A') && (c <= 'F')) { + Value += (c - 'A' + 10); + } + if (c >= '0' && c <= '9') { + Value += (c - '0'); + } + } + + return Value; +} + +EFI_HII_DATE +EfiVfrParser::_STOD ( + IN CHAR8 *Year, + IN CHAR8 *Month, + IN CHAR8 *Day + ) +{ + EFI_HII_DATE Date; + + Date.Year = _STOU16 (Year); + Date.Month = _STOU8 (Month); + Date.Day = _STOU8 (Day); + + return Date; +} + +EFI_HII_TIME +EfiVfrParser::_STOT ( + IN CHAR8 *Hour, + IN CHAR8 *Minute, + IN CHAR8 *Second + ) +{ + EFI_HII_TIME Time; + + Time.Hour = _STOU8 (Hour); + Time.Minute = _STOU8 (Minute); + Time.Second = _STOU8 (Second); + + return Time; +} + +EFI_STRING_ID +EfiVfrParser::_STOSID ( + IN CHAR8 *Str + ) +{ + return (EFI_STRING_ID)_STOU16(Str); +} + +EFI_FORM_ID +EfiVfrParser::_STOFID ( + IN CHAR8 *Str + ) +{ + return (EFI_FORM_ID)_STOU16(Str); +} + +EFI_QUESTION_ID +EfiVfrParser::_STOQID ( + IN CHAR8 *Str + ) +{ + return (EFI_QUESTION_ID)_STOU16(Str); +} + +VOID +EfiVfrParser::_STRCAT ( + IN OUT CHAR8 **Dest, + IN CHAR8 *Src + ) +{ + CHAR8 *NewStr; + UINT32 Len; + + if ((Dest == NULL) || (Src == NULL)) { + return; + } + + Len = (*Dest == NULL) ? 0 : strlen (*Dest); + Len += strlen (Src); + if ((NewStr = new CHAR8[Len + 1]) == NULL) { + return; + } + NewStr[0] = '\0'; + if (*Dest != NULL) { + strcpy (NewStr, *Dest); + delete *Dest; + } + strcat (NewStr, Src); + + *Dest = NewStr; +} + +VOID +EfiVfrParser::_CRGUID ( + IN EFI_GUID *Guid, + IN CHAR8 *G1, + IN CHAR8 *G2, + IN CHAR8 *G3, + IN CHAR8 *G4, + IN CHAR8 *G5, + IN CHAR8 *G6, + IN CHAR8 *G7, + IN CHAR8 *G8, + IN CHAR8 *G9, + IN CHAR8 *G10, + IN CHAR8 *G11 + ) +{ + Guid->Data1 = _STOU32 (G1); + Guid->Data2 = _STOU16 (G2); + Guid->Data3 = _STOU16 (G3); + Guid->Data4[0] = _STOU8(G4); + Guid->Data4[1] = _STOU8(G5); + Guid->Data4[2] = _STOU8(G6); + Guid->Data4[3] = _STOU8(G7); + Guid->Data4[4] = _STOU8(G8); + Guid->Data4[5] = _STOU8(G9); + Guid->Data4[6] = _STOU8(G10); + Guid->Data4[7] = _STOU8(G11); +} + +// +// framework vfr to default declare varstore for each structure +// +VOID +EfiVfrParser::_DeclareDefaultFrameworkVarStore ( + IN UINT32 LineNo + ) +{ + SVfrVarStorageNode *pNode; + UINT32 TypeSize; + BOOLEAN FirstNode; + + FirstNode = TRUE; + pNode = mCVfrDataStorage.GetBufferVarStoreList(); + if (pNode == NULL && gCVfrVarDataTypeDB.mFirstNewDataTypeName != NULL) { + // + // Create the default Buffer Var Store when no VarStore is defined. + // its name should be "Setup" + // + gCVfrVarDataTypeDB.GetDataTypeSize (gCVfrVarDataTypeDB.mFirstNewDataTypeName, &TypeSize); + CIfrVarStore VSObj; + VSObj.SetLineNo (LineNo); + VSObj.SetVarStoreId (0x1); //the first and only one Buffer Var Store + VSObj.SetSize (TypeSize); + //VSObj.SetName (gCVfrVarDataTypeDB.mFirstNewDataTypeName); + VSObj.SetName ("Setup"); + VSObj.SetGuid (&mFormsetGuid); +#ifdef VFREXP_DEBUG + printf ("Create the default VarStoreName is %s\n", gCVfrVarDataTypeDB.mFirstNewDataTypeName); +#endif + } else { + for (; pNode != NULL; pNode = pNode->mNext) { + // + // create the default varstore opcode for not declared varstore + // the first varstore name should be "Setup" + // + if (!pNode->mAssignedFlag) { + CIfrVarStore VSObj; + VSObj.SetLineNo (LineNo); + VSObj.SetVarStoreId (pNode->mVarStoreId); + VSObj.SetSize (pNode->mStorageInfo.mDataType->mTotalSize); + if (FirstNode) { + VSObj.SetName ("Setup"); + FirstNode = FALSE; + } else { + VSObj.SetName (pNode->mVarStoreName); + } + VSObj.SetGuid (&pNode->mGuid); +#ifdef VFREXP_DEBUG + printf ("undefined VarStoreName is %s and Id is 0x%x\n", pNode->mVarStoreName, pNode->mVarStoreId); +#endif + } + } + } + + pNode = mCVfrDataStorage.GetEfiVarStoreList(); + for (; pNode != NULL; pNode = pNode->mNext) { + // + // create the default efi varstore opcode for not exist varstore + // + if (!pNode->mAssignedFlag) { + CIfrVarStoreEfi VSEObj; + VSEObj.SetLineNo (LineNo); + VSEObj.SetAttributes (0x00000002); //hardcode EFI_VARIABLE_BOOTSERVICE_ACCESS attribute + VSEObj.SetGuid (&pNode->mGuid); + VSEObj.SetVarStoreId (pNode->mVarStoreId); +#ifdef VFREXP_DEBUG + printf ("undefined Efi VarStoreName is %s and Id is 0x%x\n", pNode->mVarStoreName, pNode->mVarStoreId); +#endif + } + } + +} + +VOID +EfiVfrParser::_DeclareDefaultLinearVarStore ( + IN UINT32 LineNo + ) +{ + UINT32 Index; + CHAR8 **TypeNameList; + UINT32 ListSize; + + gCVfrVarDataTypeDB.GetUserDefinedTypeNameList (&TypeNameList, &ListSize); + + for (Index = 0; Index < ListSize; Index++) { + UINT32 Size; + EFI_VARSTORE_ID VarStoreId; + CIfrVarStore VSObj; + + VSObj.SetLineNo (LineNo); + mCVfrDataStorage.DeclareBufferVarStore ( + TypeNameList[Index], + &mFormsetGuid, + &gCVfrVarDataTypeDB, + TypeNameList[Index], + EFI_VARSTORE_ID_INVALID + ); + mCVfrDataStorage.GetVarStoreId(TypeNameList[Index], &VarStoreId); + VSObj.SetVarStoreId (VarStoreId); + gCVfrVarDataTypeDB.GetDataTypeSize(TypeNameList[Index], &Size); + VSObj.SetSize (Size); + VSObj.SetName (TypeNameList[Index]); + VSObj.SetGuid (&mFormsetGuid); + } + +// +// not required to declare Date and Time VarStore, +// because code to support old format Data and Time +// + if (gCVfrVarDataTypeDB.IsTypeNameDefined ("Date") == FALSE) { + UINT32 Size; + EFI_VARSTORE_ID VarStoreId; + CIfrVarStore VSObj; + + VSObj.SetLineNo (LineNo); + mCVfrDataStorage.DeclareBufferVarStore ( + "Date", + &mFormsetGuid, + &gCVfrVarDataTypeDB, + "EFI_HII_DATE", + EFI_VARSTORE_ID_INVALID + ); + mCVfrDataStorage.GetVarStoreId("Date", &VarStoreId); + VSObj.SetVarStoreId (VarStoreId); + gCVfrVarDataTypeDB.GetDataTypeSize("EFI_HII_DATE", &Size); + VSObj.SetSize (Size); + VSObj.SetName ("Date"); + VSObj.SetGuid (&mFormsetGuid); + } + + if (gCVfrVarDataTypeDB.IsTypeNameDefined ("Time") == FALSE) { + UINT32 Size; + EFI_VARSTORE_ID VarStoreId; + CIfrVarStore VSObj; + + VSObj.SetLineNo (LineNo); + mCVfrDataStorage.DeclareBufferVarStore ( + "Time", + &mFormsetGuid, + &gCVfrVarDataTypeDB, + "EFI_HII_TIME", + EFI_VARSTORE_ID_INVALID + ); + mCVfrDataStorage.GetVarStoreId("Time", &VarStoreId); + VSObj.SetVarStoreId (VarStoreId); + gCVfrVarDataTypeDB.GetDataTypeSize("EFI_HII_TIME", &Size); + VSObj.SetSize (Size); + VSObj.SetName ("Time"); + VSObj.SetGuid (&mFormsetGuid); + } +} + +VOID +EfiVfrParser::_DeclareStandardDefaultStorage ( + IN UINT32 LineNo + ) +{ + // + // Default Store is declared. + // + CIfrDefaultStore DSObj; + + mCVfrDefaultStore.RegisterDefaultStore (DSObj.GetObjBinAddr(), "Standard Defaults", EFI_STRING_ID_INVALID, EFI_HII_DEFAULT_CLASS_STANDARD); + DSObj.SetLineNo (LineNo); + DSObj.SetDefaultName (EFI_STRING_ID_INVALID); + DSObj.SetDefaultId (EFI_HII_DEFAULT_CLASS_STANDARD); + + // + // Default MANUFACTURING Store is declared. + // + CIfrDefaultStore DSObjMF; + + mCVfrDefaultStore.RegisterDefaultStore (DSObjMF.GetObjBinAddr(), "Standard ManuFacturing", EFI_STRING_ID_INVALID, EFI_HII_DEFAULT_CLASS_MANUFACTURING); + DSObjMF.SetLineNo (LineNo); + DSObjMF.SetDefaultName (EFI_STRING_ID_INVALID); + DSObjMF.SetDefaultId (EFI_HII_DEFAULT_CLASS_MANUFACTURING); +} + +VOID +EfiVfrParser::AssignQuestionKey ( + IN CIfrQuestionHeader &QHObj, + IN ANTLRTokenPtr KeyTok + ) +{ + UINT16 KeyValue; + + if (KeyTok == NULL) { + return; + } + + KeyValue = _STOU16 (KeyTok->getText()); + + if (QHObj.FLAGS () & EFI_IFR_FLAG_CALLBACK) { + /* + * if the question is not CALLBACK ignore the key. + */ + _PCATCH(mCVfrQuestionDB.UpdateQuestionId (QHObj.QUESTION_ID(), KeyValue), KeyTok); + QHObj.SetQuestionId (KeyValue); + } +} + +VOID +EfiVfrParser::ConvertIdExpr ( + IN UINT32 &ExpOpCount, + IN UINT32 LineNo, + IN EFI_QUESTION_ID QId, + IN CHAR8 *VarIdStr, + IN UINT32 BitMask + ) +{ + CIfrQuestionRef1 QR1Obj(LineNo); + QR1Obj.SetQuestionId (QId, VarIdStr, LineNo); + _SAVE_OPHDR_COND (QR1Obj, (ExpOpCount == 0)); + + if (BitMask != 0) { + CIfrUint32 U32Obj(LineNo); + U32Obj.SetValue (BitMask); + + CIfrBitWiseAnd BWAObj(LineNo); + + CIfrUint8 U8Obj(LineNo); + switch (BitMask) { + case DATE_YEAR_BITMASK : U8Obj.SetValue (0); break; + case TIME_SECOND_BITMASK : U8Obj.SetValue (0x10); break; + case DATE_DAY_BITMASK : U8Obj.SetValue (0x18); break; + case TIME_HOUR_BITMASK : U8Obj.SetValue (0); break; + case TIME_MINUTE_BITMASK : U8Obj.SetValue (0x8); break; + } + + CIfrShiftRight SRObj(LineNo); + } + + ExpOpCount += 4; +} + +VOID +EfiVfrParser::IdEqValDoSpecial ( + IN UINT32 &ExpOpCount, + IN UINT32 LineNo, + IN EFI_QUESTION_ID QId, + IN CHAR8 *VarIdStr, + IN UINT32 BitMask, + IN UINT16 ConstVal, + IN EFI_COMPARE_TYPE CompareType + ) +{ + ConvertIdExpr (ExpOpCount, LineNo, QId, VarIdStr, BitMask); + + if (ConstVal > 0xFF) { + CIfrUint16 U16Obj(LineNo); + U16Obj.SetValue (ConstVal); + } else { + CIfrUint8 U8Obj(LineNo); + U8Obj.SetValue ((UINT8)ConstVal); + } + + switch (CompareType) { + case EQUAL : + { + CIfrEqual EObj(LineNo); + break; + } + case LESS_EQUAL : + { + CIfrLessEqual LEObj(LineNo); + break; + } + case LESS_THAN : + { + CIfrLessThan LTObj(LineNo); + break; + } + case GREATER_EQUAL : + { + CIfrGreaterEqual GEObj(LineNo); + break; + } + case GREATER_THAN : + { + CIfrGreaterThan GTObj(LineNo); + break; + } + } + + ExpOpCount += 2; +} + +VOID +EfiVfrParser::IdEqIdDoSpecial ( + IN UINT32 &ExpOpCount, + IN UINT32 LineNo, + IN EFI_QUESTION_ID QId1, + IN CHAR8 *VarId1Str, + IN UINT32 BitMask1, + IN EFI_QUESTION_ID QId2, + IN CHAR8 *VarId2Str, + IN UINT32 BitMask2, + IN EFI_COMPARE_TYPE CompareType + ) +{ + ConvertIdExpr (ExpOpCount, LineNo, QId1, VarId1Str, BitMask1); + ConvertIdExpr (ExpOpCount, LineNo, QId2, VarId2Str, BitMask2); + + switch (CompareType) { + case EQUAL : + { + CIfrEqual EObj(LineNo); + break; + } + case LESS_EQUAL : + { + CIfrLessEqual LEObj(LineNo); + break; + } + case LESS_THAN : + { + CIfrLessThan LTObj(LineNo); + break; + } + case GREATER_EQUAL : + { + CIfrGreaterEqual GEObj(LineNo); + break; + } + case GREATER_THAN : + { + CIfrGreaterThan GTObj(LineNo); + break; + } + } + + ExpOpCount++; +} + +VOID +EfiVfrParser::IdEqListDoSpecial ( + IN UINT32 &ExpOpCount, + IN UINT32 LineNo, + IN EFI_QUESTION_ID QId, + IN CHAR8 *VarIdStr, + IN UINT32 BitMask, + IN UINT16 ListLen, + IN UINT16 *ValueList + ) +{ + UINT16 Index; + + if (ListLen == 0) { + return; + } + + IdEqValDoSpecial (ExpOpCount, LineNo, QId, VarIdStr, BitMask, ValueList[0], EQUAL); + for (Index = 1; Index < ListLen; Index++) { + IdEqValDoSpecial (ExpOpCount, LineNo, QId, VarIdStr, BitMask, ValueList[Index], EQUAL); + CIfrOr OObj (LineNo); + ExpOpCount++; + } +} + +// +// For framework vfr compatibility +// +VOID +EfiVfrParser::SetCompatibleMode (IN BOOLEAN Mode) +{ + mCompatibleMode = Mode; + mCVfrQuestionDB.SetCompatibleMode (Mode); +} +>> diff --git a/BaseTools/Source/C/VfrCompile/VfrUtilityLib.cpp b/BaseTools/Source/C/VfrCompile/VfrUtilityLib.cpp new file mode 100644 index 0000000000..df179225d9 --- /dev/null +++ b/BaseTools/Source/C/VfrCompile/VfrUtilityLib.cpp @@ -0,0 +1,2879 @@ +/** @file + + Vfr common library functions. + +Copyright (c) 2004 - 2008, 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. + +**/ + +#include "stdio.h" +#include "stdlib.h" +#include "VfrUtilityLib.h" +#include "VfrFormPkg.h" + +VOID +CVfrBinaryOutput::WriteLine ( + IN FILE *pFile, + IN UINT32 LineBytes, + IN CHAR8 *LineHeader, + IN CHAR8 *BlkBuf, + IN UINT32 BlkSize + ) +{ + UINT32 Index; + + if ((pFile == NULL) || (LineHeader == NULL) || (BlkBuf == NULL)) { + return; + } + + for (Index = 0; Index < BlkSize; Index++) { + if ((Index % LineBytes) == 0) { + fprintf (pFile, "\n%s", LineHeader); + } + fprintf (pFile, "0x%02X, ", (UINT8)BlkBuf[Index]); + } +} + +VOID +CVfrBinaryOutput::WriteEnd ( + IN FILE *pFile, + IN UINT32 LineBytes, + IN CHAR8 *LineHeader, + IN CHAR8 *BlkBuf, + IN UINT32 BlkSize + ) +{ + UINT32 Index; + + if ((BlkSize == 0) || (pFile == NULL) || (LineHeader == NULL) || (BlkBuf == NULL)) { + return; + } + + for (Index = 0; Index < BlkSize - 1; Index++) { + if ((Index % LineBytes) == 0) { + fprintf (pFile, "\n%s", LineHeader); + } + fprintf (pFile, "0x%02X, ", (UINT8)BlkBuf[Index]); + } + + if ((Index % LineBytes) == 0) { + fprintf (pFile, "\n%s", LineHeader); + } + fprintf (pFile, "0x%02X\n", (UINT8)BlkBuf[Index]); +} + +SConfigInfo::SConfigInfo ( + IN UINT8 Type, + IN UINT16 Offset, + IN UINT32 Width, + IN EFI_IFR_TYPE_VALUE Value + ) +{ + mNext = NULL; + mOffset = Offset; + mWidth = (UINT16)Width; + mValue = new UINT8[mWidth]; + if (mValue == NULL) { + return; + } + + switch (Type) { + case EFI_IFR_TYPE_NUM_SIZE_8 : + memcpy (mValue, &Value.u8, mWidth); + break; + case EFI_IFR_TYPE_NUM_SIZE_16 : + memcpy (mValue, &Value.u16, mWidth); + break; + case EFI_IFR_TYPE_NUM_SIZE_32 : + memcpy (mValue, &Value.u32, mWidth); + break; + case EFI_IFR_TYPE_NUM_SIZE_64 : + memcpy (mValue, &Value.u64, mWidth); + break; + case EFI_IFR_TYPE_BOOLEAN : + memcpy (mValue, &Value.b, mWidth); + break; + case EFI_IFR_TYPE_TIME : + memcpy (mValue, &Value.time, mWidth); + break; + case EFI_IFR_TYPE_DATE : + memcpy (mValue, &Value.date, mWidth); + break; + case EFI_IFR_TYPE_STRING : + memcpy (mValue, &Value.string, mWidth); + break; + case EFI_IFR_TYPE_OTHER : + return; + } +} + +SConfigInfo::~SConfigInfo ( + VOID + ) +{ + BUFFER_SAFE_FREE (mValue); +} + +SConfigItem::SConfigItem ( + IN CHAR8 *Name, + IN CHAR8 *Id + ) +{ + mName = NULL; + mId = 0; + mInfoStrList = NULL; + mNext = NULL; + + if (Name != NULL) { + if ((mName = new CHAR8[strlen (Name) + 1]) != NULL) { + strcpy (mName, Name); + } + } + + if (Id != NULL) { + if ((mId = new CHAR8[strlen (Id) + 1]) != NULL) { + strcpy (mId, Id); + } + } +} + +SConfigItem::SConfigItem ( + IN CHAR8 *Name, + IN CHAR8 *Id, + IN UINT8 Type, + IN UINT16 Offset, + IN UINT16 Width, + IN EFI_IFR_TYPE_VALUE Value + ) +{ + mName = NULL; + mId = NULL; + mInfoStrList = NULL; + mNext = NULL; + + if (Name != NULL) { + if ((mName = new CHAR8[strlen (Name) + 1]) != NULL) { + strcpy (mName, Name); + } + } + + if (Id != NULL) { + if ((mId = new CHAR8[strlen (Id) + 1]) != NULL) { + strcpy (mId, Id); + } + } + + mInfoStrList = new SConfigInfo(Type, Offset, Width, Value); +} + +SConfigItem::~SConfigItem ( + VOID + ) +{ + SConfigInfo *Info; + + BUFFER_SAFE_FREE (mName); + BUFFER_SAFE_FREE (mId); + while (mInfoStrList != NULL) { + Info = mInfoStrList; + mInfoStrList = mInfoStrList->mNext; + + BUFFER_SAFE_FREE (Info); + } +} + +UINT8 +CVfrBufferConfig::Register ( + IN CHAR8 *Name, + IN CHAR8 *Id + ) +{ + SConfigItem *pNew; + + if (Select (Name) == 0) { + return 1; + } + + if ((pNew = new SConfigItem (Name, Id)) == NULL) { + return 2; + } + if (mItemListHead == NULL) { + mItemListHead = pNew; + mItemListTail = pNew; + } else { + mItemListTail->mNext = pNew; + mItemListTail = pNew; + } + mItemListPos = pNew; + + return 0; +} + +VOID +CVfrBufferConfig::Open ( + VOID + ) +{ + mItemListPos = mItemListHead; +} + +BOOLEAN +CVfrBufferConfig::Eof( + VOID + ) +{ + return (mItemListPos == NULL) ? TRUE : FALSE; +} + +UINT8 +CVfrBufferConfig::Select ( + IN CHAR8 *Name, + IN CHAR8 *Id + ) +{ + SConfigItem *p; + + if (Name == NULL) { + mItemListPos = mItemListHead; + return 0; + } else { + for (p = mItemListHead; p != NULL; p = p->mNext) { + if (strcmp (p->mName, Name) != 0) { + continue; + } + + if (Id != NULL) { + if (p->mId == NULL || strcmp (p->mId, Id) != 0) { + continue; + } + } else if (p->mId != NULL) { + continue; + } + + mItemListPos = p; + return 0; + } + } + + return 1; +} + +UINT8 +CVfrBufferConfig::Write ( + IN CONST CHAR8 Mode, + IN CHAR8 *Name, + IN CHAR8 *Id, + IN UINT8 Type, + IN UINT16 Offset, + IN UINT32 Width, + IN EFI_IFR_TYPE_VALUE Value + ) +{ + UINT8 Ret; + SConfigItem *pItem; + SConfigInfo *pInfo; + + if ((Ret = Select (Name)) != 0) { + return Ret; + } + + switch (Mode) { + case 'a' : // add + if (Select (Name, Id) != 0) { + if ((pItem = new SConfigItem (Name, Id, Type, Offset, Width, Value)) == NULL) { + return 2; + } + if (mItemListHead == NULL) { + mItemListHead = pItem; + mItemListTail = pItem; + } else { + mItemListTail->mNext = pItem; + mItemListTail = pItem; + } + mItemListPos = pItem; + } else { + // tranverse the list to find out if there's already the value for the same offset + for (pInfo = mItemListPos->mInfoStrList; pInfo != NULL; pInfo = pInfo->mNext) { + if (pInfo->mOffset == Offset) { + // check if the value and width are the same; return error if not + if ((Id != NULL) && (pInfo->mWidth != Width || memcmp(pInfo->mValue, &Value, Width) != 0)) { + return VFR_RETURN_DEFAULT_VALUE_REDEFINED; + } + return 0; + } + } + if((pInfo = new SConfigInfo (Type, Offset, Width, Value)) == NULL) { + return 2; + } + pInfo->mNext = mItemListPos->mInfoStrList; + mItemListPos->mInfoStrList = pInfo; + } + break; + + case 'd' : // delete + if (mItemListHead == mItemListPos) { + mItemListHead = mItemListPos->mNext; + delete mItemListPos; + break; + } + + for (pItem = mItemListHead; pItem->mNext != mItemListPos; pItem = pItem->mNext) + ; + + pItem->mNext = mItemListPos->mNext; + if (mItemListTail == mItemListPos) { + mItemListTail = pItem; + } + delete mItemListPos; + mItemListPos = pItem->mNext; + break; + + case 'i' : // set info + if (mItemListPos->mId != NULL) { + delete mItemListPos->mId; + } + mItemListPos->mId = NULL; + if (Id != NULL) { + if ((mItemListPos->mId = new CHAR8[strlen (Id) + 1]) == NULL) { + return 2; + } + strcpy (mItemListPos->mId, Id); + } + break; + + default : + return 1; + } + + return 0; +} + + +VOID +CVfrBufferConfig::Close ( + VOID + ) +{ + mItemListPos = NULL; +} + +#define BYTES_PRE_LINE 0x10 + +VOID +CVfrBufferConfig::OutputCFile ( + IN FILE *pFile, + IN CHAR8 *BaseName + ) +{ + CVfrBinaryOutput Output; + SConfigItem *Item; + SConfigInfo *Info; + UINT32 TotalLen; + + if (pFile == NULL) { + return; + } + + for (Item = mItemListHead; Item != NULL; Item = Item->mNext) { + if (Item->mId != NULL || Item->mInfoStrList == NULL) { + continue; + } + fprintf (pFile, "\nunsigned char %s%sBlockName[] = {", BaseName, Item->mName); + + TotalLen = sizeof (UINT32); + for (Info = Item->mInfoStrList; Info != NULL; Info = Info->mNext) { + TotalLen += sizeof (UINT16) * 2; + } + Output.WriteLine (pFile, BYTES_PRE_LINE, " ", (CHAR8 *)&TotalLen, sizeof (UINT32)); + + for (Info = Item->mInfoStrList; Info != NULL; Info = Info->mNext) { + fprintf (pFile, "\n"); + Output.WriteLine (pFile, BYTES_PRE_LINE, " ", (CHAR8 *)&Info->mOffset, sizeof (UINT16)); + Output.WriteLine (pFile, BYTES_PRE_LINE, " ", (CHAR8 *)&Info->mWidth, sizeof (UINT16)); + } + fprintf (pFile, "\n};\n"); + } + + for (Item = mItemListHead; Item != NULL; Item = Item->mNext) { + if (Item->mId != NULL && Item->mInfoStrList != NULL) { + fprintf (pFile, "\nunsigned char %s%sDefault%s[] = {", BaseName, Item->mName, Item->mId); + + TotalLen = sizeof (UINT32); + for (Info = Item->mInfoStrList; Info != NULL; Info = Info->mNext) { + TotalLen += Info->mWidth + sizeof (UINT16) * 2; + } + Output.WriteLine (pFile, BYTES_PRE_LINE, " ", (CHAR8 *)&TotalLen, sizeof (UINT32)); + + for (Info = Item->mInfoStrList; Info != NULL; Info = Info->mNext) { + fprintf (pFile, "\n"); + Output.WriteLine (pFile, BYTES_PRE_LINE, " ", (CHAR8 *)&Info->mOffset, sizeof (UINT16)); + Output.WriteLine (pFile, BYTES_PRE_LINE, " ", (CHAR8 *)&Info->mWidth, sizeof (UINT16)); + if (Info->mNext == NULL) { + Output.WriteEnd (pFile, BYTES_PRE_LINE, " ", (CHAR8 *)Info->mValue, Info->mWidth); + } else { + Output.WriteLine (pFile, BYTES_PRE_LINE, " ", (CHAR8 *)Info->mValue, Info->mWidth); + } + } + fprintf (pFile, "\n};\n"); + } + } +} + +CVfrBufferConfig::CVfrBufferConfig ( + VOID + ) +{ + mItemListHead = NULL; + mItemListTail = NULL; + mItemListPos = NULL; +} + +CVfrBufferConfig::~CVfrBufferConfig ( + VOID + ) +{ + SConfigItem *p; + + while (mItemListHead != NULL) { + p = mItemListHead; + mItemListHead = mItemListHead->mNext; + delete p; + } + + mItemListHead = NULL; + mItemListTail = NULL; + mItemListPos = NULL; +} + +CVfrBufferConfig gCVfrBufferConfig; + +static struct { + CHAR8 *mTypeName; + UINT8 mType; + UINT32 mSize; + UINT32 mAlign; +} gInternalTypesTable [] = { + {"UINT64", EFI_IFR_TYPE_NUM_SIZE_64, sizeof (UINT64), sizeof (UINT64)}, + {"UINT32", EFI_IFR_TYPE_NUM_SIZE_32, sizeof (UINT32), sizeof (UINT32)}, + {"UINT16", EFI_IFR_TYPE_NUM_SIZE_16, sizeof (UINT16), sizeof (UINT16)}, + {"UINT8", EFI_IFR_TYPE_NUM_SIZE_8, sizeof (UINT8), sizeof (UINT8)}, + {"BOOLEAN", EFI_IFR_TYPE_BOOLEAN, sizeof (BOOLEAN), sizeof (BOOLEAN)}, + {"EFI_HII_DATE", EFI_IFR_TYPE_DATE, sizeof (EFI_HII_DATE), sizeof (UINT16)}, + {"EFI_STRING_ID", EFI_IFR_TYPE_STRING, sizeof (EFI_STRING_ID),sizeof (EFI_STRING_ID)}, + {"EFI_HII_TIME", EFI_IFR_TYPE_TIME, sizeof (EFI_HII_TIME), sizeof (UINT8)}, + {NULL, EFI_IFR_TYPE_OTHER, 0, 0} +}; + +STATIC +BOOLEAN +_IS_INTERNAL_TYPE ( + IN CHAR8 *TypeName + ) +{ + UINT32 Index; + + if (TypeName == NULL) { + return FALSE; + } + + for (Index = 0; gInternalTypesTable[Index].mTypeName != NULL; Index++) { + if (strcmp (TypeName, gInternalTypesTable[Index].mTypeName) == 0) { + return TRUE; + } + } + + return FALSE; +} + +STATIC +CHAR8 * +TrimHex ( + IN CHAR8 *Str, + OUT bool *IsHex + ) +{ + *IsHex = FALSE; + + while (*Str && *Str == ' ') { + Str++; + } + while (*Str && *Str == '0') { + Str++; + } + if (*Str && (*Str == 'x' || *Str == 'X')) { + Str++; + *IsHex = TRUE; + } + + return Str; +} + +UINT32 +_STR2U32 ( + IN CHAR8 *Str + ) +{ + bool IsHex; + UINT32 Value; + CHAR8 c; + + Str = TrimHex (Str, &IsHex); + for (Value = 0; (c = *Str) != '\0'; Str++) { + // + // BUG: does not handle overflow here + // + (IsHex == TRUE) ? (Value <<= 4) : (Value *= 10); + + if ((IsHex == TRUE) && (c >= 'a') && (c <= 'f')) { + Value += (c - 'a' + 10); + } + if ((IsHex == TRUE) && (c >= 'A') && (c <= 'F')) { + Value += (c - 'A' + 10); + } + if (c >= '0' && c <= '9') { + Value += (c - '0'); + } + } + + return Value; +} + +VOID +CVfrVarDataTypeDB::RegisterNewType ( + IN SVfrDataType *New + ) +{ + New->mNext = mDataTypeList; + mDataTypeList = New; +} + +EFI_VFR_RETURN_CODE +CVfrVarDataTypeDB::ExtractStructTypeName ( + IN CHAR8 *&VarStr, + OUT CHAR8 *TName + ) +{ + if (TName == NULL) { + return VFR_RETURN_FATAL_ERROR; + } + + while((*VarStr != '\0') && (*VarStr != '.')) { + *TName = *VarStr; + VarStr++; + TName++; + } + *TName = '\0'; + if (*VarStr == '.') { + VarStr++; + } + + return VFR_RETURN_SUCCESS; +} + +EFI_VFR_RETURN_CODE +CVfrVarDataTypeDB::ExtractFieldNameAndArrary ( + IN CHAR8 *&VarStr, + IN CHAR8 *FName, + OUT UINT32 &ArrayIdx + ) +{ + UINT32 Idx; + CHAR8 ArrayStr[MAX_NAME_LEN + 1]; + + ArrayIdx = INVALID_ARRAY_INDEX; + + if (FName == NULL) { + return VFR_RETURN_FATAL_ERROR; + } + + while((*VarStr != '\0') && + (*VarStr != '.') && + (*VarStr != '[') && + (*VarStr != ']')) { + *FName = *VarStr; + VarStr++; + FName++; + } + *FName = '\0'; + + switch (*VarStr) { + case '.' : + VarStr++; + case '\0': + return VFR_RETURN_SUCCESS; + case '[' : + VarStr++; + for (Idx = 0; (Idx < MAX_NAME_LEN) && (*VarStr != '\0') && (*VarStr != ']'); VarStr++, Idx++) { + ArrayStr[Idx] = *VarStr; + } + ArrayStr[Idx] = '\0'; + + if ((*VarStr != ']') && (ArrayStr[0] == '\0')) { + return VFR_RETURN_DATA_STRING_ERROR; + } + ArrayIdx = _STR2U32 (ArrayStr); + if (*VarStr == ']') { + VarStr++; + } + return VFR_RETURN_SUCCESS; + case ']': + return VFR_RETURN_DATA_STRING_ERROR; + } + + return VFR_RETURN_SUCCESS; +} + +EFI_VFR_RETURN_CODE +CVfrVarDataTypeDB::GetTypeField ( + IN CHAR8 *FName, + IN SVfrDataType *Type, + OUT SVfrDataField *&Field + ) +{ + SVfrDataField *pField = NULL; + + if ((FName == NULL) && (Type == NULL)) { + return VFR_RETURN_FATAL_ERROR; + } + + for (pField = Type->mMembers; pField != NULL; pField = pField->mNext) { + if (strcmp (pField->mFieldName, FName) == 0) { + Field = pField; + return VFR_RETURN_SUCCESS; + } + } + + return VFR_RETURN_UNDEFINED; +} + +EFI_VFR_RETURN_CODE +CVfrVarDataTypeDB::GetFieldOffset ( + IN SVfrDataField *Field, + IN UINT32 ArrayIdx, + OUT UINT32 &Offset + ) +{ + if (Field == NULL) { + return VFR_RETURN_FATAL_ERROR; + } + + // + // Framework Vfr file Array Index is from 1. + // But Uefi Vfr file Array Index is from 0. + // + if (VfrCompatibleMode && ArrayIdx != INVALID_ARRAY_INDEX) { + if (ArrayIdx == 0) { + return VFR_RETURN_ERROR_ARRARY_NUM; + } + ArrayIdx = ArrayIdx - 1; + } + + if ((ArrayIdx != INVALID_ARRAY_INDEX) && ((Field->mArrayNum == 0) || (Field->mArrayNum <= ArrayIdx))) { + return VFR_RETURN_ERROR_ARRARY_NUM; + } + + // + // Be compatible with the current usage + // If ArraryIdx is not specified, the first one is used. + // + // if ArrayNum is larger than zero, ArraryIdx must be specified. + // + // if ((ArrayIdx == INVALID_ARRAY_INDEX) && (Field->mArrayNum > 0)) { + // return VFR_RETURN_ERROR_ARRARY_NUM; + // } + // + + Offset = Field->mOffset + Field->mFieldType->mTotalSize * ((ArrayIdx == INVALID_ARRAY_INDEX) ? 0 : ArrayIdx); + return VFR_RETURN_SUCCESS; +} + +UINT8 +CVfrVarDataTypeDB::GetFieldWidth ( + IN SVfrDataField *Field + ) +{ + if (Field == NULL) { + return 0; + } + + return Field->mFieldType->mType; +} + +UINT32 +CVfrVarDataTypeDB::GetFieldSize ( + IN SVfrDataField *Field, + IN UINT32 ArrayIdx + ) +{ + if (Field == NULL) { + return VFR_RETURN_FATAL_ERROR; + } + + if ((ArrayIdx == INVALID_ARRAY_INDEX) && (Field->mArrayNum != 0)) { + return Field->mFieldType->mTotalSize * Field->mArrayNum; + } else { + return Field->mFieldType->mTotalSize; + } +} + +VOID +CVfrVarDataTypeDB::InternalTypesListInit ( + VOID + ) +{ + SVfrDataType *New = NULL; + UINT32 Index; + + for (Index = 0; gInternalTypesTable[Index].mTypeName != NULL; Index++) { + New = new SVfrDataType; + if (New != NULL) { + strcpy (New->mTypeName, gInternalTypesTable[Index].mTypeName); + New->mType = gInternalTypesTable[Index].mType; + New->mAlign = gInternalTypesTable[Index].mAlign; + New->mTotalSize = gInternalTypesTable[Index].mSize; + if (strcmp (gInternalTypesTable[Index].mTypeName, "EFI_HII_DATE") == 0) { + SVfrDataField *pYearField = new SVfrDataField; + SVfrDataField *pMonthField = new SVfrDataField; + SVfrDataField *pDayField = new SVfrDataField; + + strcpy (pYearField->mFieldName, "Year"); + GetDataType ("UINT8", &pYearField->mFieldType); + pYearField->mOffset = 0; + pYearField->mNext = pMonthField; + pYearField->mArrayNum = 0; + + strcpy (pMonthField->mFieldName, "Month"); + GetDataType ("UINT8", &pMonthField->mFieldType); + pMonthField->mOffset = 1; + pMonthField->mNext = pDayField; + pMonthField->mArrayNum = 0; + + strcpy (pDayField->mFieldName, "Day"); + GetDataType ("UINT8", &pDayField->mFieldType); + pDayField->mOffset = 2; + pDayField->mNext = NULL; + pDayField->mArrayNum = 0; + + New->mMembers = pYearField; + } else if (strcmp (gInternalTypesTable[Index].mTypeName, "EFI_HII_TIME") == 0) { + SVfrDataField *pHoursField = new SVfrDataField; + SVfrDataField *pMinutesField = new SVfrDataField; + SVfrDataField *pSecondsField = new SVfrDataField; + + strcpy (pHoursField->mFieldName, "Hours"); + GetDataType ("UINT8", &pHoursField->mFieldType); + pHoursField->mOffset = 0; + pHoursField->mNext = pMinutesField; + pHoursField->mArrayNum = 0; + + strcpy (pMinutesField->mFieldName, "Minutes"); + GetDataType ("UINT8", &pMinutesField->mFieldType); + pMinutesField->mOffset = 1; + pMinutesField->mNext = pSecondsField; + pMinutesField->mArrayNum = 0; + + strcpy (pSecondsField->mFieldName, "Seconds"); + GetDataType ("UINT8", &pSecondsField->mFieldType); + pSecondsField->mOffset = 2; + pSecondsField->mNext = NULL; + pSecondsField->mArrayNum = 0; + + New->mMembers = pHoursField; + } else { + New->mMembers = NULL; + } + New->mNext = NULL; + RegisterNewType (New); + New = NULL; + } + } +} + +CVfrVarDataTypeDB::CVfrVarDataTypeDB ( + VOID + ) +{ + mDataTypeList = NULL; + mNewDataType = NULL; + mCurrDataField = NULL; + mPackAlign = DEFAULT_PACK_ALIGN; + mPackStack = NULL; + mFirstNewDataTypeName = NULL; + + InternalTypesListInit (); +} + +CVfrVarDataTypeDB::~CVfrVarDataTypeDB ( + VOID + ) +{ + SVfrDataType *pType; + SVfrDataField *pField; + SVfrPackStackNode *pPack; + + if (mNewDataType != NULL) { + delete mNewDataType; + } + + while (mDataTypeList != NULL) { + pType = mDataTypeList; + mDataTypeList = mDataTypeList->mNext; + while(pType->mMembers != NULL) { + pField = pType->mMembers; + pType->mMembers = pType->mMembers->mNext; + delete pField; + } + delete pType; + } + + while (mPackStack != NULL) { + pPack = mPackStack; + mPackStack = mPackStack->mNext; + delete pPack; + } +} + +EFI_VFR_RETURN_CODE +CVfrVarDataTypeDB::Pack ( + IN UINT32 LineNum, + IN UINT8 Action, + IN CHAR8 *Identifier, + IN UINT32 Number + ) +{ + UINT32 PackAlign; + CHAR8 Msg[MAX_STRING_LEN] = {0, }; + + if (Action & VFR_PACK_SHOW) { + sprintf (Msg, "value of pragma pack(show) == %d", mPackAlign); + gCVfrErrorHandle.PrintMsg (LineNum, "", "Warning", Msg); + } + + if (Action & VFR_PACK_PUSH) { + SVfrPackStackNode *pNew = NULL; + + if ((pNew = new SVfrPackStackNode (Identifier, mPackAlign)) == NULL) { + return VFR_RETURN_FATAL_ERROR; + } + pNew->mNext = mPackStack; + mPackStack = pNew; + } + + if (Action & VFR_PACK_POP) { + SVfrPackStackNode *pNode = NULL; + + if (mPackStack == NULL) { + gCVfrErrorHandle.PrintMsg (LineNum, "", "Warning", "#pragma pack(pop...) : more pops than pushes"); + } + + for (pNode = mPackStack; pNode != NULL; pNode = pNode->mNext) { + if (pNode->Match (Identifier) == TRUE) { + mPackAlign = pNode->mNumber; + mPackStack = pNode->mNext; + } + } + } + + if (Action & VFR_PACK_ASSIGN) { + PackAlign = (Number > 1) ? Number + Number % 2 : Number; + if ((PackAlign == 0) || (PackAlign > 16)) { + gCVfrErrorHandle.PrintMsg (LineNum, "", "Warning", "expected pragma parameter to be '1', '2', '4', '8', or '16'"); + } else { + mPackAlign = PackAlign; + } + } + + return VFR_RETURN_SUCCESS; +} + +VOID +CVfrVarDataTypeDB::DeclareDataTypeBegin ( + VOID + ) +{ + SVfrDataType *pNewType = NULL; + + pNewType = new SVfrDataType; + pNewType->mTypeName[0] = '\0'; + pNewType->mType = EFI_IFR_TYPE_OTHER; + pNewType->mAlign = DEFAULT_ALIGN; + pNewType->mTotalSize = 0; + pNewType->mMembers = NULL; + pNewType->mNext = NULL; + + mNewDataType = pNewType; +} + +EFI_VFR_RETURN_CODE +CVfrVarDataTypeDB::SetNewTypeName ( + IN CHAR8 *TypeName + ) +{ + SVfrDataType *pType; + + if (mNewDataType == NULL) { + return VFR_RETURN_ERROR_SKIPED; + } + if (TypeName == NULL) { + return VFR_RETURN_FATAL_ERROR; + } + if (strlen(TypeName) >= MAX_NAME_LEN) { + return VFR_RETURN_INVALID_PARAMETER; + } + + for (pType = mDataTypeList; pType != NULL; pType = pType->mNext) { + if (strcmp(pType->mTypeName, TypeName) == 0) { + return VFR_RETURN_REDEFINED; + } + } + + strcpy(mNewDataType->mTypeName, TypeName); + return VFR_RETURN_SUCCESS; +} + +EFI_VFR_RETURN_CODE +CVfrVarDataTypeDB::DataTypeAddField ( + IN CHAR8 *FieldName, + IN CHAR8 *TypeName, + IN UINT32 ArrayNum + ) +{ + SVfrDataField *pNewField = NULL; + SVfrDataType *pFieldType = NULL; + SVfrDataField *pTmp; + UINT32 Align; + + CHECK_ERROR_RETURN (GetDataType (TypeName, &pFieldType), VFR_RETURN_SUCCESS); + + if (strlen (FieldName) >= MAX_NAME_LEN) { + return VFR_RETURN_INVALID_PARAMETER; + } + + for (pTmp = mNewDataType->mMembers; pTmp != NULL; pTmp = pTmp->mNext) { + if (strcmp (pTmp->mFieldName, FieldName) == 0) { + return VFR_RETURN_REDEFINED; + } + } + + Align = MIN (mPackAlign, pFieldType->mAlign); + + if ((pNewField = new SVfrDataField) == NULL) { + return VFR_RETURN_OUT_FOR_RESOURCES; + } + strcpy (pNewField->mFieldName, FieldName); + pNewField->mFieldType = pFieldType; + pNewField->mArrayNum = ArrayNum; + if ((mNewDataType->mTotalSize % Align) == 0) { + pNewField->mOffset = mNewDataType->mTotalSize; + } else { + pNewField->mOffset = mNewDataType->mTotalSize + ALIGN_STUFF(mNewDataType->mTotalSize, Align); + } + if (mNewDataType->mMembers == NULL) { + mNewDataType->mMembers = pNewField; + pNewField->mNext = NULL; + } else { + for (pTmp = mNewDataType->mMembers; pTmp->mNext != NULL; pTmp = pTmp->mNext) + ; + pTmp->mNext = pNewField; + pNewField->mNext = NULL; + } + + mNewDataType->mAlign = MIN (mPackAlign, MAX (pFieldType->mAlign, mNewDataType->mAlign)); + mNewDataType->mTotalSize = pNewField->mOffset + (pNewField->mFieldType->mTotalSize) * ((ArrayNum == 0) ? 1 : ArrayNum); + + return VFR_RETURN_SUCCESS; +} + +VOID +CVfrVarDataTypeDB::DeclareDataTypeEnd ( + VOID + ) +{ + if (mNewDataType->mTypeName[0] == '\0') { + return; + } + + if ((mNewDataType->mTotalSize % mNewDataType->mAlign) !=0) { + mNewDataType->mTotalSize += ALIGN_STUFF (mNewDataType->mTotalSize, mNewDataType->mAlign); + } + + RegisterNewType (mNewDataType); + if (mFirstNewDataTypeName == NULL) { + mFirstNewDataTypeName = mNewDataType->mTypeName; + } + + mNewDataType = NULL; +} + +EFI_VFR_RETURN_CODE +CVfrVarDataTypeDB::GetDataType ( + IN CHAR8 *TypeName, + OUT SVfrDataType **DataType + ) +{ + SVfrDataType *pDataType = NULL; + + if (TypeName == NULL) { + return VFR_RETURN_ERROR_SKIPED; + } + + if (DataType == NULL) { + return VFR_RETURN_FATAL_ERROR; + } + + *DataType = NULL; + + for (pDataType = mDataTypeList; pDataType != NULL; pDataType = pDataType->mNext) { + if (strcmp (TypeName, pDataType->mTypeName) == 0) { + *DataType = pDataType; + return VFR_RETURN_SUCCESS; + } + } + + return VFR_RETURN_UNDEFINED; +} + +EFI_VFR_RETURN_CODE +CVfrVarDataTypeDB::GetDataTypeSize ( + IN UINT8 DataType, + OUT UINT32 *Size + ) +{ + SVfrDataType *pDataType = NULL; + + if (Size == NULL) { + return VFR_RETURN_FATAL_ERROR; + } + + *Size = 0; + DataType = DataType & 0x0F; + + // + // For user defined data type, the size can't be got by this function. + // + if (DataType == EFI_IFR_TYPE_OTHER) { + return VFR_RETURN_SUCCESS; + } + + for (pDataType = mDataTypeList; pDataType != NULL; pDataType = pDataType->mNext) { + if (DataType == pDataType->mType) { + *Size = pDataType->mTotalSize; + return VFR_RETURN_SUCCESS; + } + } + + return VFR_RETURN_UNDEFINED; +} + +EFI_VFR_RETURN_CODE +CVfrVarDataTypeDB::GetDataTypeSize ( + IN CHAR8 *TypeName, + OUT UINT32 *Size + ) +{ + SVfrDataType *pDataType = NULL; + + if (Size == NULL) { + return VFR_RETURN_FATAL_ERROR; + } + + *Size = 0; + + for (pDataType = mDataTypeList; pDataType != NULL; pDataType = pDataType->mNext) { + if (strcmp (TypeName, pDataType->mTypeName) == 0) { + *Size = pDataType->mTotalSize; + return VFR_RETURN_SUCCESS; + } + } + + return VFR_RETURN_UNDEFINED; +} + +EFI_VFR_RETURN_CODE +CVfrVarDataTypeDB::GetDataFieldInfo ( + IN CHAR8 *VarStr, + OUT UINT16 &Offset, + OUT UINT8 &Type, + OUT UINT32 &Size + ) +{ + CHAR8 TName[MAX_NAME_LEN], FName[MAX_NAME_LEN]; + UINT32 ArrayIdx, Tmp; + SVfrDataType *pType = NULL; + SVfrDataField *pField = NULL; + + Offset = 0; + Type = EFI_IFR_TYPE_OTHER; + Size = 0; + + CHECK_ERROR_RETURN (ExtractStructTypeName (VarStr, TName), VFR_RETURN_SUCCESS); + CHECK_ERROR_RETURN (GetDataType (TName, &pType), VFR_RETURN_SUCCESS); + + // + // if it is not struct data type + // + Type = pType->mType; + Size = pType->mTotalSize; + + while (*VarStr != '\0') { + CHECK_ERROR_RETURN(ExtractFieldNameAndArrary(VarStr, FName, ArrayIdx), VFR_RETURN_SUCCESS); + CHECK_ERROR_RETURN(GetTypeField (FName, pType, pField), VFR_RETURN_SUCCESS); + pType = pField->mFieldType; + CHECK_ERROR_RETURN(GetFieldOffset (pField, ArrayIdx, Tmp), VFR_RETURN_SUCCESS); + Offset += Tmp; + Type = GetFieldWidth (pField); + Size = GetFieldSize (pField, ArrayIdx); + } + return VFR_RETURN_SUCCESS; +} + +EFI_VFR_RETURN_CODE +CVfrVarDataTypeDB::GetUserDefinedTypeNameList ( + OUT CHAR8 ***NameList, + OUT UINT32 *ListSize + ) +{ + UINT32 Index; + SVfrDataType *pType; + + if ((NameList == NULL) || (ListSize == NULL)) { + return VFR_RETURN_FATAL_ERROR; + } + + *NameList = NULL; + *ListSize = 0; + + for (pType = mDataTypeList; pType != NULL; pType = pType->mNext) { + if (_IS_INTERNAL_TYPE(pType->mTypeName) == FALSE) { + (*ListSize)++; + } + } + + if (*ListSize == 0) { + return VFR_RETURN_SUCCESS; + } + + if ((*NameList = new CHAR8*[*ListSize]) == NULL) { + *ListSize = 0; + return VFR_RETURN_OUT_FOR_RESOURCES; + } + + for (Index = 0, pType = mDataTypeList; pType != NULL; pType = pType->mNext, Index++) { + if (_IS_INTERNAL_TYPE(pType->mTypeName) == FALSE) { + (*NameList)[Index] = pType->mTypeName; + } + } + return VFR_RETURN_SUCCESS; +} + +BOOLEAN +CVfrVarDataTypeDB::IsTypeNameDefined ( + IN CHAR8 *TypeName + ) +{ + SVfrDataType *pType; + + if (TypeName == NULL) { + return FALSE; + } + + for (pType = mDataTypeList; pType != NULL; pType = pType->mNext) { + if (strcmp (pType->mTypeName, TypeName) == 0) { + return TRUE; + } + } + + return FALSE; +} + +VOID +CVfrVarDataTypeDB::Dump ( + IN FILE *File + ) +{ + SVfrDataType *pTNode; + SVfrDataField *pFNode; + + fprintf (File, "\n\n***************************************************************\n"); + fprintf (File, "\t\tmPackAlign = %x\n", mPackAlign); + for (pTNode = mDataTypeList; pTNode != NULL; pTNode = pTNode->mNext) { + fprintf (File, "\t\tstruct %s : mAlign [%d] mTotalSize [0x%x]\n\n", pTNode->mTypeName, pTNode->mAlign, pTNode->mTotalSize); + fprintf (File, "\t\tstruct %s {\n", pTNode->mTypeName); + for (pFNode = pTNode->mMembers; pFNode != NULL; pFNode = pFNode->mNext) { + if (pFNode->mArrayNum > 0) { + fprintf (File, "\t\t\t+%08d[%08x] %s[%d] <%s>\n", pFNode->mOffset, pFNode->mOffset, + pFNode->mFieldName, pFNode->mArrayNum, pFNode->mFieldType->mTypeName); + } else { + fprintf (File, "\t\t\t+%08d[%08x] %s <%s>\n", pFNode->mOffset, pFNode->mOffset, + pFNode->mFieldName, pFNode->mFieldType->mTypeName); + } + } + fprintf (File, "\t\t};\n"); + fprintf (File, "---------------------------------------------------------------\n"); + } + fprintf (File, "***************************************************************\n"); +} + +#ifdef CVFR_VARDATATYPEDB_DEBUG +VOID +CVfrVarDataTypeDB::ParserDB ( + VOID + ) +{ + SVfrDataType *pTNode; + SVfrDataField *pFNode; + + printf ("***************************************************************\n"); + printf ("\t\tmPackAlign = %x\n", mPackAlign); + for (pTNode = mDataTypeList; pTNode != NULL; pTNode = pTNode->mNext) { + printf ("\t\tstruct %s : mAlign [%x] mTotalSize [%x]\n\n", pTNode->mTypeName, pTNode->mAlign, pTNode->mTotalSize); + printf ("\t\tstruct %s {\n", pTNode->mTypeName); + for (pFNode = pTNode->mMembers; pFNode != NULL; pFNode = pFNode->mNext) { + printf ("\t\t\t%s\t%s\n", pFNode->mFieldType->mTypeName, pFNode->mFieldName); + } + printf ("\t\t};\n"); + printf ("---------------------------------------------------------------\n"); + } + printf ("***************************************************************\n"); +} +#endif + +SVfrVarStorageNode::SVfrVarStorageNode ( + IN EFI_GUID *Guid, + IN CHAR8 *StoreName, + IN EFI_VARSTORE_ID VarStoreId, + IN EFI_STRING_ID VarName, + IN UINT32 VarSize, + IN BOOLEAN Flag + ) +{ + if (Guid != NULL) { + mGuid = *Guid; + } else { + memset (&Guid, 0, sizeof (EFI_GUID)); + } + if (StoreName != NULL) { + mVarStoreName = new CHAR8[strlen(StoreName) + 1]; + strcpy (mVarStoreName, StoreName); + } else { + mVarStoreName = NULL; + } + mNext = NULL; + mVarStoreId = VarStoreId; + mVarStoreType = EFI_VFR_VARSTORE_EFI; + mStorageInfo.mEfiVar.mEfiVarName = VarName; + mStorageInfo.mEfiVar.mEfiVarSize = VarSize; + mAssignedFlag = Flag; +} + +SVfrVarStorageNode::SVfrVarStorageNode ( + IN EFI_GUID *Guid, + IN CHAR8 *StoreName, + IN EFI_VARSTORE_ID VarStoreId, + IN SVfrDataType *DataType, + IN BOOLEAN Flag + ) +{ + if (Guid != NULL) { + mGuid = *Guid; + } else { + memset (&Guid, 0, sizeof (EFI_GUID)); + } + if (StoreName != NULL) { + mVarStoreName = new CHAR8[strlen(StoreName) + 1]; + strcpy (mVarStoreName, StoreName); + } else { + mVarStoreName = NULL; + } + mNext = NULL; + mVarStoreId = VarStoreId; + mVarStoreType = EFI_VFR_VARSTORE_BUFFER; + mStorageInfo.mDataType = DataType; + mAssignedFlag = Flag; +} + +SVfrVarStorageNode::SVfrVarStorageNode ( + IN CHAR8 *StoreName, + IN EFI_VARSTORE_ID VarStoreId + ) +{ + if (StoreName != NULL) { + mVarStoreName = new CHAR8[strlen(StoreName) + 1]; + strcpy (mVarStoreName, StoreName); + } else { + mVarStoreName = NULL; + } + mNext = NULL; + mVarStoreId = VarStoreId; + mVarStoreType = EFI_VFR_VARSTORE_NAME; + mStorageInfo.mNameSpace.mNameTable = new EFI_VARSTORE_ID[DEFAULT_NAME_TABLE_ITEMS]; + mStorageInfo.mNameSpace.mTableSize = 0; +} + +SVfrVarStorageNode::~SVfrVarStorageNode ( + VOID + ) +{ + if (mVarStoreName != NULL) { + delete mVarStoreName; + } + + if (mVarStoreType == EFI_VFR_VARSTORE_NAME) { + delete mStorageInfo.mNameSpace.mNameTable; + } +} + +CVfrDataStorage::CVfrDataStorage ( + VOID + ) +{ + UINT32 Index; + + for (Index = 0; Index < EFI_FREE_VARSTORE_ID_BITMAP_SIZE; Index++) { + mFreeVarStoreIdBitMap[Index] = 0; + } + + // Question ID 0 is reserved. + mFreeVarStoreIdBitMap[0] = 0x80000000; + + mBufferVarStoreList = NULL; + mEfiVarStoreList = NULL; + mNameVarStoreList = NULL; + mCurrVarStorageNode = NULL; + mNewVarStorageNode = NULL; +} + +CVfrDataStorage::~CVfrDataStorage ( + VOID + ) +{ + SVfrVarStorageNode *pNode; + + while (mBufferVarStoreList != NULL) { + pNode = mBufferVarStoreList; + mBufferVarStoreList = mBufferVarStoreList->mNext; + delete pNode; + } + while (mEfiVarStoreList != NULL) { + pNode = mEfiVarStoreList; + mEfiVarStoreList = mEfiVarStoreList->mNext; + delete pNode; + } + while (mNameVarStoreList != NULL) { + pNode = mNameVarStoreList; + mNameVarStoreList = mNameVarStoreList->mNext; + delete pNode; + } + if (mNewVarStorageNode != NULL) { + delete mNewVarStorageNode; + } +} + +EFI_VARSTORE_ID +CVfrDataStorage::GetFreeVarStoreId ( + EFI_VFR_VARSTORE_TYPE VarType + ) +{ + UINT32 Index, Mask, Offset; + + // + // Assign the different ID range for the different type VarStore to support Framework Vfr + // + if ((!VfrCompatibleMode) || (VarType == EFI_VFR_VARSTORE_BUFFER)) { + Index = 0; + } else if (VarType == EFI_VFR_VARSTORE_EFI) { + Index = 1; + } else if (VarType == EFI_VFR_VARSTORE_NAME) { + Index = 2; + } + + for (; Index < EFI_FREE_VARSTORE_ID_BITMAP_SIZE; Index++) { + if (mFreeVarStoreIdBitMap[Index] != 0xFFFFFFFF) { + break; + } + } + + for (Offset = 0, Mask = 0x80000000; Mask != 0; Mask >>= 1, Offset++) { + if ((mFreeVarStoreIdBitMap[Index] & Mask) == 0) { + mFreeVarStoreIdBitMap[Index] |= Mask; + return (EFI_VARSTORE_ID)((Index << EFI_BITS_SHIFT_PER_UINT32) + Offset); + } + } + + return EFI_VARSTORE_ID_INVALID; +} + +BOOLEAN +CVfrDataStorage::ChekVarStoreIdFree ( + IN EFI_VARSTORE_ID VarStoreId + ) +{ + UINT32 Index = (VarStoreId / EFI_BITS_PER_UINT32); + UINT32 Offset = (VarStoreId % EFI_BITS_PER_UINT32); + + return (mFreeVarStoreIdBitMap[Index] & (0x80000000 >> Offset)) == 0; +} + +VOID +CVfrDataStorage::MarkVarStoreIdUsed ( + IN EFI_VARSTORE_ID VarStoreId + ) +{ + UINT32 Index = (VarStoreId / EFI_BITS_PER_UINT32); + UINT32 Offset = (VarStoreId % EFI_BITS_PER_UINT32); + + mFreeVarStoreIdBitMap[Index] |= (0x80000000 >> Offset); +} + +VOID +CVfrDataStorage::MarkVarStoreIdUnused ( + IN EFI_VARSTORE_ID VarStoreId + ) +{ + UINT32 Index = (VarStoreId / EFI_BITS_PER_UINT32); + UINT32 Offset = (VarStoreId % EFI_BITS_PER_UINT32); + + mFreeVarStoreIdBitMap[Index] &= ~(0x80000000 >> Offset); +} + +EFI_VFR_RETURN_CODE +CVfrDataStorage::DeclareNameVarStoreBegin ( + IN CHAR8 *StoreName + ) +{ + SVfrVarStorageNode *pNode = NULL; + EFI_VARSTORE_ID VarStoreId; + + if (StoreName == NULL) { + return VFR_RETURN_FATAL_ERROR; + } + + for (pNode = mNameVarStoreList; pNode != NULL; pNode = pNode->mNext) { + if (strcmp (pNode->mVarStoreName, StoreName) == 0) { + return VFR_RETURN_REDEFINED; + } + } + + VarStoreId = GetFreeVarStoreId (EFI_VFR_VARSTORE_NAME); + if ((pNode = new SVfrVarStorageNode (StoreName, VarStoreId)) == NULL) { + return VFR_RETURN_UNDEFINED; + } + + mNewVarStorageNode = pNode; + + return VFR_RETURN_SUCCESS; +} + +EFI_VFR_RETURN_CODE +CVfrDataStorage::NameTableAddItem ( + IN EFI_STRING_ID Item + ) +{ + EFI_VARSTORE_ID *NewTable, *OldTable; + UINT32 TableSize; + + OldTable = mNewVarStorageNode->mStorageInfo.mNameSpace.mNameTable; + TableSize = mNewVarStorageNode->mStorageInfo.mNameSpace.mTableSize; + + if ((TableSize != 0) && ((TableSize % DEFAULT_NAME_TABLE_ITEMS) == 0)) { + if ((NewTable = new EFI_VARSTORE_ID[TableSize + DEFAULT_NAME_TABLE_ITEMS]) == NULL) { + return VFR_RETURN_OUT_FOR_RESOURCES; + } + memcpy (NewTable, OldTable, TableSize); + mNewVarStorageNode->mStorageInfo.mNameSpace.mNameTable = NewTable; + } + + mNewVarStorageNode->mStorageInfo.mNameSpace.mNameTable[TableSize++] = Item; + mNewVarStorageNode->mStorageInfo.mNameSpace.mTableSize = TableSize; + + return VFR_RETURN_SUCCESS; +} + +EFI_VFR_RETURN_CODE +CVfrDataStorage::DeclareNameVarStoreEnd ( + IN EFI_GUID *Guid + ) +{ + mNewVarStorageNode->mGuid = *Guid; + mNewVarStorageNode->mNext = mNameVarStoreList; + mNameVarStoreList = mNewVarStorageNode; + + mNewVarStorageNode = NULL; + + return VFR_RETURN_SUCCESS; +} + +EFI_VFR_RETURN_CODE +CVfrDataStorage::DeclareEfiVarStore ( + IN CHAR8 *StoreName, + IN EFI_GUID *Guid, + IN EFI_STRING_ID NameStrId, + IN UINT32 VarSize, + IN BOOLEAN Flag + ) +{ + SVfrVarStorageNode *pNode; + EFI_VARSTORE_ID VarStoreId; + + if ((StoreName == NULL) || (Guid == NULL)) { + return VFR_RETURN_FATAL_ERROR; + } + + if (VarSize > sizeof (UINT64)) { + return VFR_RETURN_EFIVARSTORE_SIZE_ERROR; + } + + for (pNode = mEfiVarStoreList; pNode != NULL; pNode = pNode->mNext) { + if (strcmp (pNode->mVarStoreName, StoreName) == 0) { + return VFR_RETURN_REDEFINED; + } + } + + VarStoreId = GetFreeVarStoreId (EFI_VFR_VARSTORE_EFI); + if ((pNode = new SVfrVarStorageNode (Guid, StoreName, VarStoreId, NameStrId, VarSize, Flag)) == NULL) { + return VFR_RETURN_OUT_FOR_RESOURCES; + } + + pNode->mNext = mEfiVarStoreList; + mEfiVarStoreList = pNode; + + return VFR_RETURN_SUCCESS; +} + +EFI_VFR_RETURN_CODE +CVfrDataStorage::DeclareBufferVarStore ( + IN CHAR8 *StoreName, + IN EFI_GUID *Guid, + IN CVfrVarDataTypeDB *DataTypeDB, + IN CHAR8 *TypeName, + IN EFI_VARSTORE_ID VarStoreId, + IN BOOLEAN Flag + ) +{ + SVfrVarStorageNode *pNew = NULL; + SVfrDataType *pDataType = NULL; + + if ((StoreName == NULL) || (Guid == NULL) || (DataTypeDB == NULL)) { + return VFR_RETURN_FATAL_ERROR; + } + + CHECK_ERROR_RETURN(DataTypeDB->GetDataType (TypeName, &pDataType), VFR_RETURN_SUCCESS); + + if (VarStoreId == EFI_VARSTORE_ID_INVALID) { + VarStoreId = GetFreeVarStoreId (EFI_VFR_VARSTORE_BUFFER); + } else { + if (ChekVarStoreIdFree (VarStoreId) == FALSE) { + return VFR_RETURN_VARSTOREID_REDEFINED; + } + MarkVarStoreIdUsed (VarStoreId); + } + + if ((pNew = new SVfrVarStorageNode (Guid, StoreName, VarStoreId, pDataType, Flag)) == NULL) { + return VFR_RETURN_OUT_FOR_RESOURCES; + } + + pNew->mNext = mBufferVarStoreList; + mBufferVarStoreList = pNew; + + if (gCVfrBufferConfig.Register(StoreName) != 0) { + return VFR_RETURN_FATAL_ERROR; + } + + return VFR_RETURN_SUCCESS; +} + +EFI_VFR_RETURN_CODE +CVfrDataStorage::GetVarStoreId ( + IN CHAR8 *StoreName, + OUT EFI_VARSTORE_ID *VarStoreId + ) +{ + SVfrVarStorageNode *pNode; + + for (pNode = mBufferVarStoreList; pNode != NULL; pNode = pNode->mNext) { + if (strcmp (pNode->mVarStoreName, StoreName) == 0) { + mCurrVarStorageNode = pNode; + *VarStoreId = pNode->mVarStoreId; + return VFR_RETURN_SUCCESS; + } + } + + for (pNode = mEfiVarStoreList; pNode != NULL; pNode = pNode->mNext) { + if (strcmp (pNode->mVarStoreName, StoreName) == 0) { + mCurrVarStorageNode = pNode; + *VarStoreId = pNode->mVarStoreId; + return VFR_RETURN_SUCCESS; + } + } + + for (pNode = mNameVarStoreList; pNode != NULL; pNode = pNode->mNext) { + if (strcmp (pNode->mVarStoreName, StoreName) == 0) { + mCurrVarStorageNode = pNode; + *VarStoreId = pNode->mVarStoreId; + return VFR_RETURN_SUCCESS; + } + } + + mCurrVarStorageNode = NULL; + *VarStoreId = EFI_VARSTORE_ID_INVALID; + return VFR_RETURN_UNDEFINED; +} + +EFI_VFR_RETURN_CODE +CVfrDataStorage::GetBufferVarStoreDataTypeName ( + IN CHAR8 *StoreName, + OUT CHAR8 **DataTypeName + ) +{ + SVfrVarStorageNode *pNode; + + if ((StoreName == NULL) || (DataTypeName == NULL)) { + return VFR_RETURN_FATAL_ERROR; + } + + for (pNode = mBufferVarStoreList; pNode != NULL; pNode = pNode->mNext) { + if (strcmp (pNode->mVarStoreName, StoreName) == 0) { + break; + } + } + + if (pNode == NULL) { + return VFR_RETURN_UNDEFINED; + } + + if (pNode->mStorageInfo.mDataType == NULL) { + return VFR_RETURN_FATAL_ERROR; + } + + *DataTypeName = pNode->mStorageInfo.mDataType->mTypeName; + return VFR_RETURN_SUCCESS; +} + +EFI_VFR_RETURN_CODE +CVfrDataStorage::GetVarStoreType ( + IN CHAR8 *StoreName, + OUT EFI_VFR_VARSTORE_TYPE &VarStoreType + ) +{ + SVfrVarStorageNode *pNode; + + if (StoreName == NULL) { + return VFR_RETURN_FATAL_ERROR; + } + + for (pNode = mBufferVarStoreList; pNode != NULL; pNode = pNode->mNext) { + if (strcmp (pNode->mVarStoreName, StoreName) == NULL) { + VarStoreType = pNode->mVarStoreType; + return VFR_RETURN_SUCCESS; + } + } + + for (pNode = mEfiVarStoreList; pNode != NULL; pNode = pNode->mNext) { + if (strcmp (pNode->mVarStoreName, StoreName) == NULL) { + VarStoreType = pNode->mVarStoreType; + return VFR_RETURN_SUCCESS; + } + } + + for (pNode = mNameVarStoreList; pNode != NULL; pNode = pNode->mNext) { + if (strcmp (pNode->mVarStoreName, StoreName) == NULL) { + VarStoreType = pNode->mVarStoreType; + return VFR_RETURN_SUCCESS; + } + } + + VarStoreType = EFI_VFR_VARSTORE_INVALID; + return VFR_RETURN_UNDEFINED; +} + +EFI_VFR_VARSTORE_TYPE +CVfrDataStorage::GetVarStoreType ( + IN EFI_VARSTORE_ID VarStoreId + ) +{ + SVfrVarStorageNode *pNode; + EFI_VFR_VARSTORE_TYPE VarStoreType; + + VarStoreType = EFI_VFR_VARSTORE_INVALID; + + if (VarStoreId == EFI_VARSTORE_ID_INVALID) { + return VarStoreType; + } + + for (pNode = mBufferVarStoreList; pNode != NULL; pNode = pNode->mNext) { + if (pNode->mVarStoreId == VarStoreId) { + VarStoreType = pNode->mVarStoreType; + return VarStoreType; + } + } + + for (pNode = mEfiVarStoreList; pNode != NULL; pNode = pNode->mNext) { + if (pNode->mVarStoreId == VarStoreId) { + VarStoreType = pNode->mVarStoreType; + return VarStoreType; + } + } + + for (pNode = mNameVarStoreList; pNode != NULL; pNode = pNode->mNext) { + if (pNode->mVarStoreId == VarStoreId) { + VarStoreType = pNode->mVarStoreType; + return VarStoreType; + } + } + + return VarStoreType; +} + +EFI_VFR_RETURN_CODE +CVfrDataStorage::GetVarStoreName ( + IN EFI_VARSTORE_ID VarStoreId, + OUT CHAR8 **VarStoreName + ) +{ + SVfrVarStorageNode *pNode; + + if (VarStoreName == NULL) { + return VFR_RETURN_FATAL_ERROR; + } + + for (pNode = mBufferVarStoreList; pNode != NULL; pNode = pNode->mNext) { + if (pNode->mVarStoreId == VarStoreId) { + *VarStoreName = pNode->mVarStoreName; + return VFR_RETURN_SUCCESS; + } + } + + for (pNode = mEfiVarStoreList; pNode != NULL; pNode = pNode->mNext) { + if (pNode->mVarStoreId == VarStoreId) { + *VarStoreName = pNode->mVarStoreName; + return VFR_RETURN_SUCCESS; + } + } + + for (pNode = mNameVarStoreList; pNode != NULL; pNode = pNode->mNext) { + if (pNode->mVarStoreId == VarStoreId) { + *VarStoreName = pNode->mVarStoreName; + return VFR_RETURN_SUCCESS; + } + } + + *VarStoreName = NULL; + return VFR_RETURN_UNDEFINED; +} + +EFI_VFR_RETURN_CODE +CVfrDataStorage::GetEfiVarStoreInfo ( + IN OUT EFI_VARSTORE_INFO *Info + ) +{ + if (Info == NULL) { + return VFR_RETURN_FATAL_ERROR; + } + + if (mCurrVarStorageNode == NULL) { + return VFR_RETURN_GET_EFIVARSTORE_ERROR; + } + + Info->mInfo.mVarName = mCurrVarStorageNode->mStorageInfo.mEfiVar.mEfiVarName; + Info->mVarTotalSize = mCurrVarStorageNode->mStorageInfo.mEfiVar.mEfiVarSize; + switch (Info->mVarTotalSize) { + case 1: + Info->mVarType = EFI_IFR_TYPE_NUM_SIZE_8; + break; + case 2: + Info->mVarType = EFI_IFR_TYPE_NUM_SIZE_16; + break; + case 4: + Info->mVarType = EFI_IFR_TYPE_NUM_SIZE_32; + break; + case 8: + Info->mVarType = EFI_IFR_TYPE_NUM_SIZE_64; + break; + default : + return VFR_RETURN_FATAL_ERROR; + } + + return VFR_RETURN_SUCCESS; +} + +EFI_VFR_RETURN_CODE +CVfrDataStorage::GetNameVarStoreInfo ( + OUT EFI_VARSTORE_INFO *Info, + IN UINT32 Index + ) +{ + if (Info == NULL) { + return VFR_RETURN_FATAL_ERROR; + } + + if (mCurrVarStorageNode == NULL) { + return VFR_RETURN_GET_NVVARSTORE_ERROR; + } + + // + // Framework Vfr file Index is from 1, but Uefi Vfr file Index is from 0. + // + if (VfrCompatibleMode) { + if (Index == 0) { + return VFR_RETURN_ERROR_ARRARY_NUM; + } + Index --; + } + + Info->mInfo.mVarName = mCurrVarStorageNode->mStorageInfo.mNameSpace.mNameTable[Index]; + + return VFR_RETURN_SUCCESS; +} + +EFI_VFR_RETURN_CODE +CVfrDataStorage::BufferVarStoreRequestElementAdd ( + IN CHAR8 *StoreName, + IN EFI_VARSTORE_INFO &Info + ) +{ + CHAR8 NewReqElt[128] = {'\0',}; + CHAR8 *OldReqElt = NULL; + SVfrVarStorageNode *pNode = NULL; + EFI_IFR_TYPE_VALUE Value = gZeroEfiIfrTypeValue; + + for (pNode = mBufferVarStoreList; pNode != NULL; pNode = pNode->mNext) { + if (strcmp (pNode->mVarStoreName, StoreName) == NULL) { + break; + } + } + + if (pNode == NULL) { + return VFR_RETURN_UNDEFINED; + } + + gCVfrBufferConfig.Open (); + Value.u8 = 0; + if (gCVfrBufferConfig.Write ('a', StoreName, NULL, EFI_IFR_TYPE_NUM_SIZE_8, Info.mInfo.mVarOffset, Info.mVarTotalSize, Value) != 0) { + return VFR_RETURN_FATAL_ERROR; + } + gCVfrBufferConfig.Close (); + + return VFR_RETURN_SUCCESS; +} + +SVfrDefaultStoreNode::SVfrDefaultStoreNode ( + IN EFI_IFR_DEFAULTSTORE *ObjBinAddr, + IN CHAR8 *RefName, + IN EFI_STRING_ID DefaultStoreNameId, + IN UINT16 DefaultId + ) +{ + mObjBinAddr = ObjBinAddr; + + if (RefName != NULL) { + mRefName = new CHAR8[strlen (RefName) + 1]; + strcpy (mRefName, RefName); + } else { + mRefName = NULL; + } + + mNext = NULL; + mDefaultId = DefaultId; + mDefaultStoreNameId = DefaultStoreNameId; +} + +SVfrDefaultStoreNode::~SVfrDefaultStoreNode ( + VOID + ) +{ + if (mRefName != NULL) { + delete mRefName; + } +} + +CVfrDefaultStore::CVfrDefaultStore ( + VOID + ) +{ + mDefaultStoreList = NULL; +} + +CVfrDefaultStore::~CVfrDefaultStore ( + VOID + ) +{ + SVfrDefaultStoreNode *pTmp = NULL; + + while (mDefaultStoreList != NULL) { + pTmp = mDefaultStoreList; + mDefaultStoreList = mDefaultStoreList->mNext; + delete pTmp; + } +} + +EFI_VFR_RETURN_CODE +CVfrDefaultStore::RegisterDefaultStore ( + IN CHAR8 *ObjBinAddr, + IN CHAR8 *RefName, + IN EFI_STRING_ID DefaultStoreNameId, + IN UINT16 DefaultId + ) +{ + SVfrDefaultStoreNode *pNode = NULL; + + if (RefName == NULL) { + return VFR_RETURN_FATAL_ERROR; + } + + for (pNode = mDefaultStoreList; pNode != NULL; pNode = pNode->mNext) { + if (strcmp (pNode->mRefName, RefName) == 0) { + return VFR_RETURN_REDEFINED; + } + } + + if ((pNode = new SVfrDefaultStoreNode ((EFI_IFR_DEFAULTSTORE *)ObjBinAddr, RefName, DefaultStoreNameId, DefaultId)) == NULL) { + return VFR_RETURN_OUT_FOR_RESOURCES; + } + + pNode->mNext = mDefaultStoreList; + mDefaultStoreList = pNode; + + return VFR_RETURN_SUCCESS; +} + +/* + * assign new reference name or new default store name id only if + * the original is invalid + */ +EFI_VFR_RETURN_CODE +CVfrDefaultStore::ReRegisterDefaultStoreById ( + IN UINT16 DefaultId, + IN CHAR8 *RefName, + IN EFI_STRING_ID DefaultStoreNameId + ) +{ + SVfrDefaultStoreNode *pNode = NULL; + + for (pNode = mDefaultStoreList; pNode != NULL; pNode = pNode->mNext) { + if (pNode->mDefaultId == DefaultId) { + break; + } + } + + if (pNode == NULL) { + return VFR_RETURN_UNDEFINED; + } else { + if (pNode->mDefaultStoreNameId == EFI_STRING_ID_INVALID) { + pNode->mDefaultStoreNameId = DefaultStoreNameId; + if (pNode->mObjBinAddr != NULL) { + pNode->mObjBinAddr->DefaultName = DefaultStoreNameId; + } + } else { + return VFR_RETURN_REDEFINED; + } + + if (RefName != NULL) { + delete pNode->mRefName; + pNode->mRefName = new CHAR8[strlen (RefName) + 1]; + if (pNode->mRefName != NULL) { + strcpy (pNode->mRefName, RefName); + } + } + } + + return VFR_RETURN_SUCCESS; +} + +BOOLEAN +CVfrDefaultStore::DefaultIdRegistered ( + IN UINT16 DefaultId + ) +{ + SVfrDefaultStoreNode *pNode = NULL; + + for (pNode = mDefaultStoreList; pNode != NULL; pNode = pNode->mNext) { + if (pNode->mDefaultId == DefaultId) { + return TRUE; + } + } + + return FALSE; +} + +EFI_VFR_RETURN_CODE +CVfrDefaultStore::GetDefaultId ( + IN CHAR8 *RefName, + OUT UINT16 *DefaultId + ) +{ + SVfrDefaultStoreNode *pTmp = NULL; + + if (DefaultId == NULL) { + return VFR_RETURN_FATAL_ERROR; + } + + for (pTmp = mDefaultStoreList; pTmp != NULL; pTmp = pTmp->mNext) { + if (strcmp (pTmp->mRefName, RefName) == 0) { + *DefaultId = pTmp->mDefaultId; + return VFR_RETURN_SUCCESS; + } + } + + return VFR_RETURN_UNDEFINED; +} + +STATIC +EFI_VFR_RETURN_CODE +AltCfgItemPrintToBuffer ( + IN CHAR8 *NewAltCfg, + IN EFI_VARSTORE_INFO Info, + IN UINT8 Type, + IN EFI_IFR_TYPE_VALUE Value + ) +{ + UINT32 Index; + UINT8 *BufChar = NULL; + UINT32 Count = 0; + + if (NewAltCfg != NULL) { + Count = sprintf ( + NewAltCfg, + "&OFFSET=%x&WIDTH=%x&VALUE=", + Info.mInfo.mVarOffset, + Info.mVarTotalSize + ); + NewAltCfg += Count; + + switch (Type) { + case EFI_IFR_TYPE_NUM_SIZE_8 : + Count = sprintf (NewAltCfg, "%x", Value.u8); + NewAltCfg += Count; + break; + case EFI_IFR_TYPE_NUM_SIZE_16 : + Count = sprintf (NewAltCfg, "%x", Value.u16); + NewAltCfg += Count; + break; + case EFI_IFR_TYPE_NUM_SIZE_32 : + Count = sprintf (NewAltCfg, "%x", Value.u32); + NewAltCfg += Count; + break; + case EFI_IFR_TYPE_NUM_SIZE_64 : + Count = sprintf (NewAltCfg, "%x", Value.u64); + NewAltCfg += Count; + break; + case EFI_IFR_TYPE_BOOLEAN : + Count = sprintf (NewAltCfg, "%x", Value.b); + NewAltCfg += Count; + break; + case EFI_IFR_TYPE_TIME : +#if 1 + Count = sprintf (NewAltCfg, "%x", *((UINT32 *)(&Value.time))); + NewAltCfg += Count; +#else + BufChar = (UINT8 *)&Value.time; + for (Index = 0; Index < sizeof(EFI_HII_TIME); Index++) { + Count = sprintf (NewAltCfg, "%02x", (UINT8)BufChar[Index]); + NewAltCfg += Count; + } +#endif + break; + case EFI_IFR_TYPE_DATE : +#if 1 + Count = sprintf (NewAltCfg, "%x", *((UINT32 *)(&Value.date))); + NewAltCfg += Count; +#else + BufChar = (UINT8 *)&Value.date; + for (Index = 0; Index < sizeof(EFI_HII_DATE); Index++) { + Count = sprintf (NewAltCfg, "%02x", (UINT8)BufChar[Index]); + NewAltCfg += Count; + } +#endif + break; + case EFI_IFR_TYPE_STRING : + Count = sprintf (NewAltCfg, "%x", Value.string); + NewAltCfg += Count; + break; + case EFI_IFR_TYPE_OTHER : + return VFR_RETURN_UNSUPPORTED; + } + } + + return VFR_RETURN_FATAL_ERROR; +} + +EFI_VFR_RETURN_CODE +CVfrDefaultStore::BufferVarStoreAltConfigAdd ( + IN EFI_VARSTORE_ID DefaultId, + IN EFI_VARSTORE_INFO &Info, + IN CHAR8 *VarStoreName, + IN UINT8 Type, + IN EFI_IFR_TYPE_VALUE Value + ) +{ + SVfrDefaultStoreNode *pNode = NULL; + CHAR8 NewAltCfg[2 * 2 * sizeof (UINT16) + 1] = {0,}; + INTN Returnvalue = 0; + + if (VarStoreName == NULL) { + return VFR_RETURN_FATAL_ERROR; + } + + for (pNode = mDefaultStoreList; pNode != NULL; pNode = pNode->mNext) { + if (pNode->mDefaultId == DefaultId) { + break; + } + } + + if (pNode == NULL) { + return VFR_RETURN_UNDEFINED; + } + + gCVfrBufferConfig.Open (); + + sprintf (NewAltCfg, "%04x", pNode->mDefaultId); + if ((Returnvalue = gCVfrBufferConfig.Select(VarStoreName)) == 0) { + if ((Returnvalue = gCVfrBufferConfig.Write ('a', VarStoreName, NewAltCfg, Type, Info.mInfo.mVarOffset, Info.mVarTotalSize, Value)) != 0) { + goto WriteError; + } + } + + gCVfrBufferConfig.Close (); + + return VFR_RETURN_SUCCESS; + +WriteError: + gCVfrBufferConfig.Close (); + return (EFI_VFR_RETURN_CODE)Returnvalue; +} + +SVfrRuleNode::SVfrRuleNode ( + IN CHAR8 *RuleName, + IN UINT8 RuleId + ) +{ + if (RuleName != NULL) { + mRuleName = new CHAR8[strlen (RuleName) + 1]; + strcpy (mRuleName, RuleName); + } else { + mRuleName = NULL; + } + + mNext = NULL; + mRuleId = RuleId; +} + +SVfrRuleNode::~SVfrRuleNode ( + VOID + ) +{ + if (mRuleName != NULL) { + delete mRuleName; + } +} + +CVfrRulesDB::CVfrRulesDB () +{ + mRuleList = NULL; + mFreeRuleId = EFI_VARSTORE_ID_START; +} + +CVfrRulesDB::~CVfrRulesDB () +{ + SVfrRuleNode *pNode; + + while(mRuleList != NULL) { + pNode = mRuleList; + mRuleList = mRuleList->mNext; + delete pNode; + } +} + +VOID +CVfrRulesDB::RegisterRule ( + IN CHAR8 *RuleName + ) +{ + SVfrRuleNode *pNew; + + if (RuleName == NULL) { + return ; + } + + if ((pNew = new SVfrRuleNode (RuleName, mFreeRuleId)) == NULL) { + return ; + } + + mFreeRuleId++; + + pNew->mNext = mRuleList; + mRuleList = pNew; +} + +UINT8 +CVfrRulesDB::GetRuleId ( + IN CHAR8 *RuleName + ) +{ + SVfrRuleNode *pNode; + + if (RuleName == NULL) { + return EFI_RULE_ID_INVALID; + } + + for (pNode = mRuleList; pNode != NULL; pNode = pNode->mNext) { + if (strcmp (pNode->mRuleName, RuleName) == 0) { + return pNode->mRuleId; + } + } + + return EFI_RULE_ID_INVALID; +} + +CVfrRulesDB gCVfrRulesDB; + +EFI_VARSTORE_INFO::EFI_VARSTORE_INFO ( + VOID + ) +{ + mVarStoreId = EFI_VARSTORE_ID_INVALID; + mInfo.mVarName = EFI_STRING_ID_INVALID; + mInfo.mVarOffset = EFI_VAROFFSET_INVALID; + mVarType = EFI_IFR_TYPE_OTHER; + mVarTotalSize = 0; +} + +EFI_VARSTORE_INFO::EFI_VARSTORE_INFO ( + IN EFI_VARSTORE_INFO &Info + ) +{ + mVarStoreId = Info.mVarStoreId; + mInfo.mVarName = Info.mInfo.mVarName; + mInfo.mVarOffset = Info.mInfo.mVarOffset; + mVarType = Info.mVarType; + mVarTotalSize = Info.mVarTotalSize; +} + +BOOLEAN +EFI_VARSTORE_INFO::operator == ( + IN EFI_VARSTORE_INFO *Info + ) +{ + if ((mVarStoreId == Info->mVarStoreId) && + (mInfo.mVarName == Info->mInfo.mVarName) && + (mInfo.mVarOffset == Info->mInfo.mVarOffset) && + (mVarType == Info->mVarType) && + (mVarTotalSize == Info->mVarTotalSize)) { + return TRUE; + } + + return FALSE; +} + +static EFI_VARSTORE_INFO gEfiInvalidVarStoreInfo; + +EFI_QUESTION_ID +CVfrQuestionDB::GetFreeQuestionId ( + VOID + ) +{ + UINT32 Index, Mask, Offset; + + for (Index = 0; Index < EFI_FREE_QUESTION_ID_BITMAP_SIZE; Index++) { + if (mFreeQIdBitMap[Index] != 0xFFFFFFFF) { + break; + } + } + + for (Offset = 0, Mask = 0x80000000; Mask != 0; Mask >>= 1, Offset++) { + if ((mFreeQIdBitMap[Index] & Mask) == 0) { + mFreeQIdBitMap[Index] |= Mask; + return (EFI_QUESTION_ID)((Index << EFI_BITS_SHIFT_PER_UINT32) + Offset); + } + } + + return EFI_QUESTION_ID_INVALID; +} + +BOOLEAN +CVfrQuestionDB::ChekQuestionIdFree ( + IN EFI_QUESTION_ID QId + ) +{ + UINT32 Index = (QId / EFI_BITS_PER_UINT32); + UINT32 Offset = (QId % EFI_BITS_PER_UINT32); + + return (mFreeQIdBitMap[Index] & (0x80000000 >> Offset)) == 0; +} + +VOID +CVfrQuestionDB::MarkQuestionIdUsed ( + IN EFI_QUESTION_ID QId + ) +{ + UINT32 Index = (QId / EFI_BITS_PER_UINT32); + UINT32 Offset = (QId % EFI_BITS_PER_UINT32); + + mFreeQIdBitMap[Index] |= (0x80000000 >> Offset); +} + +VOID +CVfrQuestionDB::MarkQuestionIdUnused ( + IN EFI_QUESTION_ID QId + ) +{ + UINT32 Index = (QId / EFI_BITS_PER_UINT32); + UINT32 Offset = (QId % EFI_BITS_PER_UINT32); + + mFreeQIdBitMap[Index] &= ~(0x80000000 >> Offset); +} + +SVfrQuestionNode::SVfrQuestionNode ( + IN CHAR8 *Name, + IN CHAR8 *VarIdStr, + IN UINT32 BitMask + ) +{ + mName = NULL; + mVarIdStr = NULL; + mQuestionId = EFI_QUESTION_ID_INVALID; + mBitMask = BitMask; + mNext = NULL; + + if (Name == NULL) { + mName = new CHAR8[strlen ("$DEFAULT") + 1]; + strcpy (mName, "$DEFAULT"); + } else { + mName = new CHAR8[strlen (Name) + 1]; + strcpy (mName, Name); + } + + if (VarIdStr != NULL) { + mVarIdStr = new CHAR8[strlen (VarIdStr) + 1]; + strcpy (mVarIdStr, VarIdStr); + } else { + mVarIdStr = new CHAR8[strlen ("$") + 1]; + strcpy (mVarIdStr, "$"); + } +} + +SVfrQuestionNode::~SVfrQuestionNode ( + VOID + ) +{ + if (mName != NULL) { + delete mName; + } + + if (mVarIdStr != NULL) { + delete mVarIdStr; + } +} + +CVfrQuestionDB::CVfrQuestionDB () +{ + UINT32 Index; + + for (Index = 0; Index < EFI_FREE_QUESTION_ID_BITMAP_SIZE; Index++) { + mFreeQIdBitMap[Index] = 0; + } + + // Question ID 0 is reserved. + mFreeQIdBitMap[0] = 0x80000000; + mQuestionList = NULL; +} + +CVfrQuestionDB::~CVfrQuestionDB () +{ + SVfrQuestionNode *pNode; + + while (mQuestionList != NULL) { + pNode = mQuestionList; + mQuestionList = mQuestionList->mNext; + delete pNode; + } +} + +// +// Reset to init state +// +VOID +CVfrQuestionDB::ResetInit( + IN VOID + ) +{ + UINT32 Index; + SVfrQuestionNode *pNode; + + while (mQuestionList != NULL) { + pNode = mQuestionList; + mQuestionList = mQuestionList->mNext; + delete pNode; + } + + for (Index = 0; Index < EFI_FREE_QUESTION_ID_BITMAP_SIZE; Index++) { + mFreeQIdBitMap[Index] = 0; + } + + // Question ID 0 is reserved. + mFreeQIdBitMap[0] = 0x80000000; + mQuestionList = NULL; +} + +VOID +CVfrQuestionDB::PrintAllQuestion ( + VOID + ) +{ + SVfrQuestionNode *pNode = NULL; + + for (pNode = mQuestionList; pNode != NULL; pNode = pNode->mNext) { + printf ("Question VarId is %s and QuesitonId is 0x%x\n", pNode->mVarIdStr, pNode->mQuestionId); + } +} + +EFI_VFR_RETURN_CODE +CVfrQuestionDB::RegisterQuestion ( + IN CHAR8 *Name, + IN CHAR8 *VarIdStr, + IN OUT EFI_QUESTION_ID &QuestionId + ) +{ + SVfrQuestionNode *pNode = NULL; + + if ((Name != NULL) && (FindQuestion(Name) == VFR_RETURN_SUCCESS)) { + return VFR_RETURN_REDEFINED; + } + + if ((pNode = new SVfrQuestionNode (Name, VarIdStr)) == NULL) { + return VFR_RETURN_OUT_FOR_RESOURCES; + } + + if (QuestionId == EFI_QUESTION_ID_INVALID) { + QuestionId = GetFreeQuestionId (); + } else { + // + // For Framework Vfr, don't check question ID conflict. + // + if (!VfrCompatibleMode && ChekQuestionIdFree (QuestionId) == FALSE) { + delete pNode; + return VFR_RETURN_QUESTIONID_REDEFINED; + } + MarkQuestionIdUsed (QuestionId); + } + pNode->mQuestionId = QuestionId; + + pNode->mNext = mQuestionList; + mQuestionList = pNode; + + gCFormPkg.DoPendingAssign (VarIdStr, (VOID *)&QuestionId, sizeof(EFI_QUESTION_ID)); + + return VFR_RETURN_SUCCESS; +} + +VOID +CVfrQuestionDB::RegisterOldDateQuestion ( + IN CHAR8 *YearVarId, + IN CHAR8 *MonthVarId, + IN CHAR8 *DayVarId, + IN OUT EFI_QUESTION_ID &QuestionId + ) +{ + SVfrQuestionNode *pNode[3] = {NULL, }; + UINT32 Index; + + if ((YearVarId == NULL) || (MonthVarId == NULL) || (DayVarId == NULL)) { + return; + } + + if ((pNode[0] = new SVfrQuestionNode (NULL, YearVarId, DATE_YEAR_BITMASK)) == NULL) { + goto Err; + } + if ((pNode[1] = new SVfrQuestionNode (NULL, MonthVarId, DATE_MONTH_BITMASK)) == NULL) { + goto Err; + } + if ((pNode[2] = new SVfrQuestionNode (NULL, DayVarId, DATE_DAY_BITMASK)) == NULL) { + goto Err; + } + + if (QuestionId == EFI_QUESTION_ID_INVALID) { + QuestionId = GetFreeQuestionId (); + } else { + if (ChekQuestionIdFree (QuestionId) == FALSE) { + goto Err; + } + MarkQuestionIdUsed (QuestionId); + } + + pNode[0]->mQuestionId = QuestionId; + pNode[1]->mQuestionId = QuestionId; + pNode[2]->mQuestionId = QuestionId; + pNode[0]->mNext = pNode[1]; + pNode[1]->mNext = pNode[2]; + pNode[2]->mNext = mQuestionList; + mQuestionList = pNode[0]; + + gCFormPkg.DoPendingAssign (YearVarId, (VOID *)&QuestionId, sizeof(EFI_QUESTION_ID)); + gCFormPkg.DoPendingAssign (MonthVarId, (VOID *)&QuestionId, sizeof(EFI_QUESTION_ID)); + gCFormPkg.DoPendingAssign (DayVarId, (VOID *)&QuestionId, sizeof(EFI_QUESTION_ID)); + + return; + +Err: + for (Index = 0; Index < 3; Index++) { + if (pNode[Index] != NULL) { + delete pNode[Index]; + } + } + QuestionId = EFI_QUESTION_ID_INVALID; +} + +VOID +CVfrQuestionDB::RegisterNewDateQuestion ( + IN CHAR8 *Name, + IN CHAR8 *BaseVarId, + IN OUT EFI_QUESTION_ID &QuestionId + ) +{ + SVfrQuestionNode *pNode[3] = {NULL, }; + UINT32 Len; + CHAR8 *VarIdStr[3] = {NULL, }; + CHAR8 Index; + + if (BaseVarId == NULL) { + return; + } + + Len = strlen (BaseVarId); + + VarIdStr[0] = new CHAR8[Len + strlen (".Year") + 1]; + if (VarIdStr[0] != NULL) { + strcpy (VarIdStr[0], BaseVarId); + strcat (VarIdStr[0], ".Year"); + } + VarIdStr[1] = new CHAR8[Len + strlen (".Month") + 1]; + if (VarIdStr[1] != NULL) { + strcpy (VarIdStr[1], BaseVarId); + strcat (VarIdStr[1], ".Month"); + } + VarIdStr[2] = new CHAR8[Len + strlen (".Day") + 1]; + if (VarIdStr[2] != NULL) { + strcpy (VarIdStr[2], BaseVarId); + strcat (VarIdStr[2], ".Day"); + } + + if ((pNode[0] = new SVfrQuestionNode (Name, VarIdStr[0], DATE_YEAR_BITMASK)) == NULL) { + goto Err; + } + if ((pNode[1] = new SVfrQuestionNode (Name, VarIdStr[1], DATE_MONTH_BITMASK)) == NULL) { + goto Err; + } + if ((pNode[2] = new SVfrQuestionNode (Name, VarIdStr[2], DATE_DAY_BITMASK)) == NULL) { + goto Err; + } + + if (QuestionId == EFI_QUESTION_ID_INVALID) { + QuestionId = GetFreeQuestionId (); + } else { + if (ChekQuestionIdFree (QuestionId) == FALSE) { + goto Err; + } + MarkQuestionIdUsed (QuestionId); + } + + pNode[0]->mQuestionId = QuestionId; + pNode[1]->mQuestionId = QuestionId; + pNode[2]->mQuestionId = QuestionId; + pNode[0]->mNext = pNode[1]; + pNode[1]->mNext = pNode[2]; + pNode[2]->mNext = mQuestionList; + mQuestionList = pNode[0]; + + for (Index = 0; Index < 3; Index++) { + if (VarIdStr[Index] != NULL) { + delete VarIdStr[Index]; + } + } + + gCFormPkg.DoPendingAssign (VarIdStr[0], (VOID *)&QuestionId, sizeof(EFI_QUESTION_ID)); + gCFormPkg.DoPendingAssign (VarIdStr[1], (VOID *)&QuestionId, sizeof(EFI_QUESTION_ID)); + gCFormPkg.DoPendingAssign (VarIdStr[2], (VOID *)&QuestionId, sizeof(EFI_QUESTION_ID)); + + return; + +Err: + for (Index = 0; Index < 3; Index++) { + if (pNode[Index] != NULL) { + delete pNode[Index]; + } + + if (VarIdStr[Index] != NULL) { + delete VarIdStr[Index]; + } + } +} + +VOID +CVfrQuestionDB::RegisterOldTimeQuestion ( + IN CHAR8 *HourVarId, + IN CHAR8 *MinuteVarId, + IN CHAR8 *SecondVarId, + IN OUT EFI_QUESTION_ID &QuestionId + ) +{ + SVfrQuestionNode *pNode[3] = {NULL, }; + UINT32 Index; + + if ((HourVarId == NULL) || (MinuteVarId == NULL) || (SecondVarId == NULL)) { + return; + } + + if ((pNode[0] = new SVfrQuestionNode (NULL, HourVarId, TIME_HOUR_BITMASK)) == NULL) { + goto Err; + } + if ((pNode[1] = new SVfrQuestionNode (NULL, MinuteVarId, TIME_MINUTE_BITMASK)) == NULL) { + goto Err; + } + if ((pNode[2] = new SVfrQuestionNode (NULL, SecondVarId, TIME_SECOND_BITMASK)) == NULL) { + goto Err; + } + + if (QuestionId == EFI_QUESTION_ID_INVALID) { + QuestionId = GetFreeQuestionId (); + } else { + if (ChekQuestionIdFree (QuestionId) == FALSE) { + goto Err; + } + MarkQuestionIdUsed (QuestionId); + } + + pNode[0]->mQuestionId = QuestionId; + pNode[1]->mQuestionId = QuestionId; + pNode[2]->mQuestionId = QuestionId; + pNode[0]->mNext = pNode[1]; + pNode[1]->mNext = pNode[2]; + pNode[2]->mNext = mQuestionList; + mQuestionList = pNode[0]; + + gCFormPkg.DoPendingAssign (HourVarId, (VOID *)&QuestionId, sizeof(EFI_QUESTION_ID)); + gCFormPkg.DoPendingAssign (MinuteVarId, (VOID *)&QuestionId, sizeof(EFI_QUESTION_ID)); + gCFormPkg.DoPendingAssign (SecondVarId, (VOID *)&QuestionId, sizeof(EFI_QUESTION_ID)); + + return; + +Err: + for (Index = 0; Index < 3; Index++) { + if (pNode[Index] != NULL) { + delete pNode[Index]; + } + } + QuestionId = EFI_QUESTION_ID_INVALID; +} + +VOID +CVfrQuestionDB::RegisterNewTimeQuestion ( + IN CHAR8 *Name, + IN CHAR8 *BaseVarId, + IN OUT EFI_QUESTION_ID &QuestionId + ) +{ + SVfrQuestionNode *pNode[3] = {NULL, }; + UINT32 Len; + CHAR8 *VarIdStr[3] = {NULL, }; + CHAR8 Index; + + if (BaseVarId == NULL) { + return; + } + + Len = strlen (BaseVarId); + + VarIdStr[0] = new CHAR8[Len + strlen (".Hour") + 1]; + if (VarIdStr[0] != NULL) { + strcpy (VarIdStr[0], BaseVarId); + strcat (VarIdStr[0], ".Hour"); + } + VarIdStr[1] = new CHAR8[Len + strlen (".Minute") + 1]; + if (VarIdStr[1] != NULL) { + strcpy (VarIdStr[1], BaseVarId); + strcat (VarIdStr[1], ".Minute"); + } + VarIdStr[2] = new CHAR8[Len + strlen (".Second") + 1]; + if (VarIdStr[2] != NULL) { + strcpy (VarIdStr[2], BaseVarId); + strcat (VarIdStr[2], ".Second"); + } + + if ((pNode[0] = new SVfrQuestionNode (Name, VarIdStr[0], TIME_HOUR_BITMASK)) == NULL) { + goto Err; + } + if ((pNode[1] = new SVfrQuestionNode (Name, VarIdStr[1], TIME_MINUTE_BITMASK)) == NULL) { + goto Err; + } + if ((pNode[2] = new SVfrQuestionNode (Name, VarIdStr[2], TIME_SECOND_BITMASK)) == NULL) { + goto Err; + } + + if (QuestionId == EFI_QUESTION_ID_INVALID) { + QuestionId = GetFreeQuestionId (); + } else { + if (ChekQuestionIdFree (QuestionId) == FALSE) { + goto Err; + } + MarkQuestionIdUsed (QuestionId); + } + + pNode[0]->mQuestionId = QuestionId; + pNode[1]->mQuestionId = QuestionId; + pNode[2]->mQuestionId = QuestionId; + pNode[0]->mNext = pNode[1]; + pNode[1]->mNext = pNode[2]; + pNode[2]->mNext = mQuestionList; + mQuestionList = pNode[0]; + + for (Index = 0; Index < 3; Index++) { + if (VarIdStr[Index] != NULL) { + delete VarIdStr[Index]; + } + } + + gCFormPkg.DoPendingAssign (VarIdStr[0], (VOID *)&QuestionId, sizeof(EFI_QUESTION_ID)); + gCFormPkg.DoPendingAssign (VarIdStr[1], (VOID *)&QuestionId, sizeof(EFI_QUESTION_ID)); + gCFormPkg.DoPendingAssign (VarIdStr[2], (VOID *)&QuestionId, sizeof(EFI_QUESTION_ID)); + + return; + +Err: + for (Index = 0; Index < 3; Index++) { + if (pNode[Index] != NULL) { + delete pNode[Index]; + } + + if (VarIdStr[Index] != NULL) { + delete VarIdStr[Index]; + } + } +} + +EFI_VFR_RETURN_CODE +CVfrQuestionDB::UpdateQuestionId ( + IN EFI_QUESTION_ID QId, + IN EFI_QUESTION_ID NewQId + ) +{ + SVfrQuestionNode *pNode = NULL; + + if (QId == NewQId) { + // don't update + return VFR_RETURN_SUCCESS; + } + + // + // For Framework Vfr, don't check question ID conflict. + // + if (!VfrCompatibleMode && ChekQuestionIdFree (NewQId) == FALSE) { + return VFR_RETURN_REDEFINED; + } + + for (pNode = mQuestionList; pNode != NULL; pNode = pNode->mNext) { + if (pNode->mQuestionId == QId) { + break; + } + } + + if (pNode == NULL) { + return VFR_RETURN_UNDEFINED; + } + + MarkQuestionIdUnused (QId); + pNode->mQuestionId = NewQId; + MarkQuestionIdUsed (NewQId); + + gCFormPkg.DoPendingAssign (pNode->mVarIdStr, (VOID *)&NewQId, sizeof(EFI_QUESTION_ID)); + + return VFR_RETURN_SUCCESS; +} + +VOID +CVfrQuestionDB::GetQuestionId ( + IN CHAR8 *Name, + IN CHAR8 *VarIdStr, + OUT EFI_QUESTION_ID &QuestionId, + OUT UINT32 &BitMask + ) +{ + SVfrQuestionNode *pNode; + + QuestionId = EFI_QUESTION_ID_INVALID; + BitMask = 0x00000000; + + if ((Name == NULL) && (VarIdStr == NULL)) { + return ; + } + + for (pNode = mQuestionList; pNode != NULL; pNode = pNode->mNext) { + if (Name != NULL) { + if (strcmp (pNode->mName, Name) != 0) { + continue; + } + } + + if (VarIdStr != NULL) { + if (strcmp (pNode->mVarIdStr, VarIdStr) != 0) { + continue; + } + } + + QuestionId = pNode->mQuestionId; + BitMask = pNode->mBitMask; + break; + } + + return ; +} + +EFI_VFR_RETURN_CODE +CVfrQuestionDB::FindQuestion ( + IN EFI_QUESTION_ID QuestionId + ) +{ + SVfrQuestionNode *pNode; + + if (QuestionId == EFI_QUESTION_ID_INVALID) { + return VFR_RETURN_INVALID_PARAMETER; + } + + for (pNode = mQuestionList; pNode != NULL; pNode = pNode->mNext) { + if (pNode->mQuestionId == QuestionId) { + return VFR_RETURN_SUCCESS; + } + } + + return VFR_RETURN_UNDEFINED; +} + +EFI_VFR_RETURN_CODE +CVfrQuestionDB::FindQuestion ( + IN CHAR8 *Name + ) +{ + SVfrQuestionNode *pNode; + + if (Name == NULL) { + return VFR_RETURN_FATAL_ERROR; + } + + for (pNode = mQuestionList; pNode != NULL; pNode = pNode->mNext) { + if (strcmp (pNode->mName, Name) == 0) { + return VFR_RETURN_SUCCESS; + } + } + + return VFR_RETURN_UNDEFINED; +} + +BOOLEAN VfrCompatibleMode = FALSE; + +CVfrVarDataTypeDB gCVfrVarDataTypeDB; + diff --git a/BaseTools/Source/C/VfrCompile/VfrUtilityLib.h b/BaseTools/Source/C/VfrCompile/VfrUtilityLib.h new file mode 100644 index 0000000000..76d7873e54 --- /dev/null +++ b/BaseTools/Source/C/VfrCompile/VfrUtilityLib.h @@ -0,0 +1,427 @@ +/** @file + + Vfr common library functions. + +Copyright (c) 2004 - 2008, 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. + +**/ + +#ifndef _VFRUTILITYLIB_H_ +#define _VFRUTILITYLIB_H_ + +#include "string.h" +#include "Common/UefiBaseTypes.h" +#include "EfiVfr.h" +#include "VfrError.h" + +extern BOOLEAN VfrCompatibleMode; + +#define MAX_NAME_LEN 64 +#define MAX_STRING_LEN 0x100 +#define DEFAULT_ALIGN 1 +#define DEFAULT_PACK_ALIGN 0x8 +#define DEFAULT_NAME_TABLE_ITEMS 1024 + +#define EFI_BITS_SHIFT_PER_UINT32 0x5 +#define EFI_BITS_PER_UINT32 (1 << EFI_BITS_SHIFT_PER_UINT32) + +#define BUFFER_SAFE_FREE(Buf) do { if ((Buf) != NULL) { delete (Buf); } } while (0); + +class CVfrBinaryOutput { +public: + virtual VOID WriteLine (IN FILE *, IN UINT32, IN CHAR8 *, IN CHAR8 *, IN UINT32); + virtual VOID WriteEnd (IN FILE *, IN UINT32, IN CHAR8 *, IN CHAR8 *, IN UINT32); +}; + +UINT32 +_STR2U32 ( + IN CHAR8 *Str + ); + +struct SConfigInfo { + UINT16 mOffset; + UINT16 mWidth; + UINT8 *mValue; + SConfigInfo *mNext; + + SConfigInfo (IN UINT8, IN UINT16, IN UINT32, IN EFI_IFR_TYPE_VALUE); + ~SConfigInfo (VOID); +}; + +struct SConfigItem { + CHAR8 *mName; // varstore name + CHAR8 *mId; // varstore ID + SConfigInfo *mInfoStrList; // list of Offset/Value in the varstore + SConfigItem *mNext; + +public: + SConfigItem (IN CHAR8 *, IN CHAR8 *); + SConfigItem (IN CHAR8 *, IN CHAR8 *, IN UINT8, IN UINT16, IN UINT16, IN EFI_IFR_TYPE_VALUE); + virtual ~SConfigItem (); +}; + +class CVfrBufferConfig { +private: + SConfigItem *mItemListHead; + SConfigItem *mItemListTail; + SConfigItem *mItemListPos; + +public: + CVfrBufferConfig (VOID); + virtual ~CVfrBufferConfig (VOID); + + virtual UINT8 Register (IN CHAR8 *, IN CHAR8 *Info = NULL); + virtual VOID Open (VOID); + virtual BOOLEAN Eof(VOID); + virtual UINT8 Select (IN CHAR8 *, IN CHAR8 *Info = NULL); + virtual UINT8 Write (IN CONST CHAR8, IN CHAR8 *, IN CHAR8 *, IN UINT8, IN UINT16, IN UINT32, IN EFI_IFR_TYPE_VALUE); +#if 0 + virtual UINT8 Read (OUT CHAR8 **, OUT CHAR8 **, OUT CHAR8 **, OUT CHAR8 **, OUT CHAR8 **); +#endif + virtual VOID Close (VOID); + virtual VOID OutputCFile (IN FILE *, IN CHAR8 *); +}; + +extern CVfrBufferConfig gCVfrBufferConfig; + +#define ALIGN_STUFF(Size, Align) ((Align) - (Size) % (Align)) +#define INVALID_ARRAY_INDEX 0xFFFFFFFF + +struct SVfrDataType; + +struct SVfrDataField { + CHAR8 mFieldName[MAX_NAME_LEN]; + SVfrDataType *mFieldType; + UINT32 mOffset; + UINT32 mArrayNum; + SVfrDataField *mNext; +}; + +struct SVfrDataType { + CHAR8 mTypeName[MAX_NAME_LEN]; + UINT8 mType; + UINT32 mAlign; + UINT32 mTotalSize; + SVfrDataField *mMembers; + SVfrDataType *mNext; +}; + +#define VFR_PACK_ASSIGN 0x01 +#define VFR_PACK_SHOW 0x02 +#define VFR_PACK_PUSH 0x04 +#define VFR_PACK_POP 0x08 + +#define PACKSTACK_MAX_SIZE 0x400 + +struct SVfrPackStackNode { + CHAR8 *mIdentifier; + UINT32 mNumber; + SVfrPackStackNode *mNext; + + SVfrPackStackNode (IN CHAR8 *Identifier, IN UINT32 Number) { + mIdentifier = NULL; + mNumber = Number; + mNext = NULL; + + if (Identifier != NULL) { + mIdentifier = new CHAR8[strlen (Identifier) + 1]; + strcpy (mIdentifier, Identifier); + } + } + + ~SVfrPackStackNode (VOID) { + if (mIdentifier != NULL) { + delete mIdentifier; + } + mNext = NULL; + } + + bool Match (IN CHAR8 *Identifier) { + if (Identifier == NULL) { + return TRUE; + } else if (mIdentifier == NULL) { + return FALSE; + } else if (strcmp (Identifier, mIdentifier) == 0) { + return TRUE; + } else { + return FALSE; + } + } +}; + +class CVfrVarDataTypeDB { +private: + UINT32 mPackAlign; + SVfrPackStackNode *mPackStack; + +public: + EFI_VFR_RETURN_CODE Pack (IN UINT32, IN UINT8, IN CHAR8 *Identifier = NULL, IN UINT32 Number = DEFAULT_PACK_ALIGN); + +private: + SVfrDataType *mDataTypeList; + + SVfrDataType *mNewDataType; + SVfrDataType *mCurrDataType; + SVfrDataField *mCurrDataField; + + VOID InternalTypesListInit (VOID); + VOID RegisterNewType (IN SVfrDataType *); + + EFI_VFR_RETURN_CODE ExtractStructTypeName (IN CHAR8 *&, OUT CHAR8 *); + EFI_VFR_RETURN_CODE GetTypeField (IN CHAR8 *, IN SVfrDataType *, IN SVfrDataField *&); + EFI_VFR_RETURN_CODE GetFieldOffset (IN SVfrDataField *, IN UINT32, OUT UINT32 &); + UINT8 GetFieldWidth (IN SVfrDataField *); + UINT32 GetFieldSize (IN SVfrDataField *, IN UINT32); + +public: + CVfrVarDataTypeDB (VOID); + ~CVfrVarDataTypeDB (VOID); + + VOID DeclareDataTypeBegin (VOID); + EFI_VFR_RETURN_CODE SetNewTypeName (IN CHAR8 *); + EFI_VFR_RETURN_CODE DataTypeAddField (IN CHAR8 *, IN CHAR8 *, IN UINT32); + VOID DeclareDataTypeEnd (VOID); + + EFI_VFR_RETURN_CODE GetDataType (IN CHAR8 *, OUT SVfrDataType **); + EFI_VFR_RETURN_CODE GetDataTypeSize (IN CHAR8 *, OUT UINT32 *); + EFI_VFR_RETURN_CODE GetDataTypeSize (IN UINT8, OUT UINT32 *); + EFI_VFR_RETURN_CODE GetDataFieldInfo (IN CHAR8 *, OUT UINT16 &, OUT UINT8 &, OUT UINT32 &); + + EFI_VFR_RETURN_CODE GetUserDefinedTypeNameList (OUT CHAR8 ***, OUT UINT32 *); + EFI_VFR_RETURN_CODE ExtractFieldNameAndArrary (IN CHAR8 *&, OUT CHAR8 *, OUT UINT32 &); + + BOOLEAN IsTypeNameDefined (IN CHAR8 *); + + VOID Dump(IN FILE *); + // + // First the declared + // + CHAR8 *mFirstNewDataTypeName; +#ifdef CVFR_VARDATATYPEDB_DEBUG + VOID ParserDB (); +#endif +}; + +extern CVfrVarDataTypeDB gCVfrVarDataTypeDB; + +typedef enum { + EFI_VFR_VARSTORE_INVALID, + EFI_VFR_VARSTORE_BUFFER, + EFI_VFR_VARSTORE_EFI, + EFI_VFR_VARSTORE_NAME +} EFI_VFR_VARSTORE_TYPE; + +struct SVfrVarStorageNode { + EFI_GUID mGuid; + CHAR8 *mVarStoreName; + EFI_VARSTORE_ID mVarStoreId; + BOOLEAN mAssignedFlag; //Create varstore opcode + struct SVfrVarStorageNode *mNext; + + EFI_VFR_VARSTORE_TYPE mVarStoreType; + union { + // EFI Variable + struct { + EFI_STRING_ID mEfiVarName; + UINT32 mEfiVarSize; + } mEfiVar; + + // Buffer Storage + SVfrDataType *mDataType; + + // NameValue Storage + struct { + EFI_STRING_ID *mNameTable; + UINT32 mTableSize; + } mNameSpace; + } mStorageInfo; + +public: + SVfrVarStorageNode (IN EFI_GUID *, IN CHAR8 *, IN EFI_VARSTORE_ID, IN EFI_STRING_ID, IN UINT32, IN BOOLEAN Flag = TRUE); + SVfrVarStorageNode (IN EFI_GUID *, IN CHAR8 *, IN EFI_VARSTORE_ID, IN SVfrDataType *, IN BOOLEAN Flag = TRUE); + SVfrVarStorageNode (IN CHAR8 *, IN EFI_VARSTORE_ID); + ~SVfrVarStorageNode (VOID); +}; + +struct EFI_VARSTORE_INFO { + EFI_VARSTORE_ID mVarStoreId; + union { + EFI_STRING_ID mVarName; + UINT16 mVarOffset; + } mInfo; + UINT8 mVarType; + UINT32 mVarTotalSize; + + EFI_VARSTORE_INFO (VOID); + EFI_VARSTORE_INFO (IN EFI_VARSTORE_INFO &); + BOOLEAN operator == (IN EFI_VARSTORE_INFO *); +}; + +#define EFI_VARSTORE_ID_MAX 0xFFFF +#define EFI_FREE_VARSTORE_ID_BITMAP_SIZE ((EFI_VARSTORE_ID_MAX + 1) / EFI_BITS_PER_UINT32) + +class CVfrDataStorage { +private: + UINT32 mFreeVarStoreIdBitMap[EFI_FREE_VARSTORE_ID_BITMAP_SIZE]; + + struct SVfrVarStorageNode *mBufferVarStoreList; + struct SVfrVarStorageNode *mEfiVarStoreList; + struct SVfrVarStorageNode *mNameVarStoreList; + + struct SVfrVarStorageNode *mCurrVarStorageNode; + struct SVfrVarStorageNode *mNewVarStorageNode; + +private: + + EFI_VARSTORE_ID GetFreeVarStoreId (EFI_VFR_VARSTORE_TYPE VarType = EFI_VFR_VARSTORE_BUFFER); + BOOLEAN ChekVarStoreIdFree (IN EFI_VARSTORE_ID); + VOID MarkVarStoreIdUsed (IN EFI_VARSTORE_ID); + VOID MarkVarStoreIdUnused (IN EFI_VARSTORE_ID); + +public: + CVfrDataStorage (); + ~CVfrDataStorage (); + + SVfrVarStorageNode * GetBufferVarStoreList () { + return mBufferVarStoreList; + } + SVfrVarStorageNode * GetEfiVarStoreList () { + return mEfiVarStoreList; + } + EFI_VFR_RETURN_CODE DeclareNameVarStoreBegin (CHAR8 *); + EFI_VFR_RETURN_CODE NameTableAddItem (EFI_STRING_ID); + EFI_VFR_RETURN_CODE DeclareNameVarStoreEnd (EFI_GUID *); + + EFI_VFR_RETURN_CODE DeclareEfiVarStore (IN CHAR8 *, IN EFI_GUID *, IN EFI_STRING_ID, IN UINT32, IN BOOLEAN Flag = TRUE); + + EFI_VFR_RETURN_CODE DeclareBufferVarStore (IN CHAR8 *, IN EFI_GUID *, IN CVfrVarDataTypeDB *, IN CHAR8 *, IN EFI_VARSTORE_ID, IN BOOLEAN Flag = TRUE); + + EFI_VFR_RETURN_CODE GetVarStoreId (IN CHAR8 *, OUT EFI_VARSTORE_ID *); + EFI_VFR_RETURN_CODE GetVarStoreType (IN CHAR8 *, OUT EFI_VFR_VARSTORE_TYPE &); + EFI_VFR_VARSTORE_TYPE GetVarStoreType (IN EFI_VARSTORE_ID); + EFI_VFR_RETURN_CODE GetVarStoreName (IN EFI_VARSTORE_ID, OUT CHAR8 **); + + EFI_VFR_RETURN_CODE GetBufferVarStoreDataTypeName (IN CHAR8 *, OUT CHAR8 **); + EFI_VFR_RETURN_CODE GetEfiVarStoreInfo (IN EFI_VARSTORE_INFO *); + EFI_VFR_RETURN_CODE GetNameVarStoreInfo (IN EFI_VARSTORE_INFO *, IN UINT32); + + EFI_VFR_RETURN_CODE BufferVarStoreRequestElementAdd (IN CHAR8 *, IN EFI_VARSTORE_INFO &); +}; + +#define EFI_QUESTION_ID_MAX 0xFFFF +#define EFI_FREE_QUESTION_ID_BITMAP_SIZE ((EFI_QUESTION_ID_MAX + 1) / EFI_BITS_PER_UINT32) +#define EFI_QUESTION_ID_INVALID 0x0 + +#define DATE_YEAR_BITMASK 0x0000FFFF +#define DATE_MONTH_BITMASK 0x00FF0000 +#define DATE_DAY_BITMASK 0xFF000000 +#define TIME_HOUR_BITMASK 0x000000FF +#define TIME_MINUTE_BITMASK 0x0000FF00 +#define TIME_SECOND_BITMASK 0x00FF0000 + +struct SVfrQuestionNode { + CHAR8 *mName; + CHAR8 *mVarIdStr; + EFI_QUESTION_ID mQuestionId; + UINT32 mBitMask; + SVfrQuestionNode *mNext; + + SVfrQuestionNode (IN CHAR8 *, IN CHAR8 *, IN UINT32 BitMask = 0); + ~SVfrQuestionNode (); +}; + +class CVfrQuestionDB { +private: + SVfrQuestionNode *mQuestionList; + UINT32 mFreeQIdBitMap[EFI_FREE_QUESTION_ID_BITMAP_SIZE]; + +private: + EFI_QUESTION_ID GetFreeQuestionId (VOID); + BOOLEAN ChekQuestionIdFree (IN EFI_QUESTION_ID); + VOID MarkQuestionIdUsed (IN EFI_QUESTION_ID); + VOID MarkQuestionIdUnused (IN EFI_QUESTION_ID); + +public: + CVfrQuestionDB (); + ~CVfrQuestionDB(); + + EFI_VFR_RETURN_CODE RegisterQuestion (IN CHAR8 *, IN CHAR8 *, IN OUT EFI_QUESTION_ID &); + VOID RegisterOldDateQuestion (IN CHAR8 *, IN CHAR8 *, IN CHAR8 *, IN OUT EFI_QUESTION_ID &); + VOID RegisterNewDateQuestion (IN CHAR8 *, IN CHAR8 *, IN OUT EFI_QUESTION_ID &); + VOID RegisterOldTimeQuestion (IN CHAR8 *, IN CHAR8 *, IN CHAR8 *, IN OUT EFI_QUESTION_ID &); + VOID RegisterNewTimeQuestion (IN CHAR8 *, IN CHAR8 *, IN OUT EFI_QUESTION_ID &); + EFI_VFR_RETURN_CODE UpdateQuestionId (IN EFI_QUESTION_ID, IN EFI_QUESTION_ID); + VOID GetQuestionId (IN CHAR8 *, IN CHAR8 *, OUT EFI_QUESTION_ID &, OUT UINT32 &); + EFI_VFR_RETURN_CODE FindQuestion (IN EFI_QUESTION_ID); + EFI_VFR_RETURN_CODE FindQuestion (IN CHAR8 *); + VOID PrintAllQuestion (IN VOID); + VOID ResetInit (IN VOID); + + VOID SetCompatibleMode (IN BOOLEAN Mode) { + VfrCompatibleMode = Mode; + } +}; + +struct SVfrDefaultStoreNode { + EFI_IFR_DEFAULTSTORE *mObjBinAddr; + CHAR8 *mRefName; + EFI_STRING_ID mDefaultStoreNameId; + UINT16 mDefaultId; + + SVfrDefaultStoreNode *mNext; + + SVfrDefaultStoreNode (IN EFI_IFR_DEFAULTSTORE *, IN CHAR8 *, IN EFI_STRING_ID, IN UINT16); + ~SVfrDefaultStoreNode(); +}; + +class CVfrDefaultStore { +private: + SVfrDefaultStoreNode *mDefaultStoreList; + +public: + CVfrDefaultStore (); + ~CVfrDefaultStore (); + + EFI_VFR_RETURN_CODE RegisterDefaultStore (IN CHAR8 *, IN CHAR8 *, IN EFI_STRING_ID, IN UINT16); + EFI_VFR_RETURN_CODE ReRegisterDefaultStoreById (IN UINT16, IN CHAR8 *, IN EFI_STRING_ID); + BOOLEAN DefaultIdRegistered (IN UINT16); + EFI_VFR_RETURN_CODE GetDefaultId (IN CHAR8 *, OUT UINT16 *); + EFI_VFR_RETURN_CODE BufferVarStoreAltConfigAdd (IN EFI_VARSTORE_ID, IN EFI_VARSTORE_INFO &, IN CHAR8 *, IN UINT8, IN EFI_IFR_TYPE_VALUE); +}; + +#define EFI_RULE_ID_START 0x01 +#define EFI_RULE_ID_INVALID 0x00 + +struct SVfrRuleNode { + UINT8 mRuleId; + CHAR8 *mRuleName; + SVfrRuleNode *mNext; + + SVfrRuleNode(IN CHAR8 *, IN UINT8); + ~SVfrRuleNode(); +}; + +class CVfrRulesDB { +private: + SVfrRuleNode *mRuleList; + UINT8 mFreeRuleId; + +public: + CVfrRulesDB (); + ~CVfrRulesDB(); + + VOID RegisterRule (IN CHAR8 *); + UINT8 GetRuleId (IN CHAR8 *); +}; + +#define MIN(v1, v2) (((v1) < (v2)) ? (v1) : (v2)) +#define MAX(v1, v2) (((v1) > (v2)) ? (v1) : (v2)) + +#endif diff --git a/BaseTools/Source/C/VolInfo/GNUmakefile b/BaseTools/Source/C/VolInfo/GNUmakefile new file mode 100644 index 0000000000..309f9ccf8c --- /dev/null +++ b/BaseTools/Source/C/VolInfo/GNUmakefile @@ -0,0 +1,12 @@ +ARCH ?= IA32 +MAKEROOT ?= .. + +APPNAME = VolInfo + +OBJECTS = VolInfo.o + +include $(MAKEROOT)/Makefiles/app.makefile + +LIBS = -lCommon + + diff --git a/BaseTools/Source/C/VolInfo/Makefile b/BaseTools/Source/C/VolInfo/Makefile new file mode 100644 index 0000000000..6bf58de80c --- /dev/null +++ b/BaseTools/Source/C/VolInfo/Makefile @@ -0,0 +1,10 @@ +!INCLUDE ..\Makefiles\ms.common + +APPNAME = VolInfo + +LIBS = $(LIB_PATH)\Common.lib + +OBJECTS = VolInfo.obj + +!INCLUDE ..\Makefiles\ms.app + diff --git a/BaseTools/Source/C/VolInfo/VolInfo.c b/BaseTools/Source/C/VolInfo/VolInfo.c new file mode 100644 index 0000000000..1df182e4d6 --- /dev/null +++ b/BaseTools/Source/C/VolInfo/VolInfo.c @@ -0,0 +1,1798 @@ +/** @file + +Copyright (c) 1999 - 2008, 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: + + VolInfo.c + +Abstract: + + The tool dumps the contents of a firmware volume + +**/ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "Compress.h" +#include "Decompress.h" +#include "VolInfo.h" +#include "CommonLib.h" +#include "EfiUtilityMsgs.h" +#include "FirmwareVolumeBufferLib.h" +#include "OsPath.h" +#include "ParseGuidedSectionTools.h" +#include "StringFuncs.h" + +// +// Utility global variables +// + +EFI_GUID gEfiCrc32GuidedSectionExtractionProtocolGuid = EFI_CRC32_GUIDED_SECTION_EXTRACTION_PROTOCOL_GUID; + +#define UTILITY_MAJOR_VERSION 0 +#define UTILITY_MINOR_VERSION 82 + +#define UTILITY_NAME "VolInfo" + +#define EFI_SECTION_ERROR EFIERR (100) + +#define MAX_BASENAME_LEN 60 // not good to hardcode, but let's be reasonable + +// +// Structure to keep a list of guid-to-basenames +// +typedef struct _GUID_TO_BASENAME { + struct _GUID_TO_BASENAME *Next; + INT8 Guid[PRINTED_GUID_BUFFER_SIZE]; + INT8 BaseName[MAX_BASENAME_LEN]; +} GUID_TO_BASENAME; + +static GUID_TO_BASENAME *mGuidBaseNameList = NULL; + +// +// Store GUIDed Section guid->tool mapping +// +EFI_HANDLE mParsedGuidedSectionTools = NULL; + +CHAR8* mUtilityFilename = NULL; + +EFI_STATUS +ParseGuidBaseNameFile ( + CHAR8 *FileName + ); + +EFI_STATUS +FreeGuidBaseNameList ( + VOID + ); + +EFI_STATUS +PrintGuidName ( + IN UINT8 *GuidStr + ); + +EFI_STATUS +ParseSection ( + IN UINT8 *SectionBuffer, + IN UINT32 BufferLength + ); + +EFI_STATUS +DumpDepexSection ( + IN UINT8 *Ptr, + IN UINT32 SectionLength + ); + +STATIC +EFI_STATUS +ReadHeader ( + IN FILE *InputFile, + OUT UINT32 *FvSize, + OUT BOOLEAN *ErasePolarity + ); + +STATIC +EFI_STATUS +PrintFileInfo ( + EFI_FIRMWARE_VOLUME_HEADER *FvImage, + EFI_FFS_FILE_HEADER *FileHeader, + BOOLEAN ErasePolarity + ); + +static +EFI_STATUS +PrintFvInfo ( + IN VOID *Fv + ); + +static +VOID +LoadGuidedSectionToolsTxt ( + IN CHAR8* FirmwareVolumeFilename + ); + +void +Usage ( + VOID + ); + +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 *InputFile; + int BytesRead; + EFI_FIRMWARE_VOLUME_HEADER *FvImage; + UINT32 FvSize; + EFI_STATUS Status; + UINT32 Offset; + BOOLEAN ErasePolarity; + + SetUtilityName (UTILITY_NAME); + // + // Print utility header + // + printf ("%s Tiano Firmware Volume FFS image info. Version %d.%d, %s\n", + UTILITY_NAME, + UTILITY_MAJOR_VERSION, + UTILITY_MINOR_VERSION, + __DATE__ + ); + + // + // Save, and then skip filename arg + // + mUtilityFilename = argv[0]; + argc--; + argv++; + + Offset = 0; + + // + // If they specified -x xref guid/basename cross-reference files, process it. + // This will print the basename beside each file guid. To use it, specify + // -x xref_filename to processdsc, then use xref_filename as a parameter + // here. + // + while (argc > 2) { + if ((strcmp(argv[0], "-x") == 0) || (strcmp(argv[0], "--xref") == 0)) { + ParseGuidBaseNameFile (argv[1]); + printf("ParseGuidBaseNameFile: %s\n", argv[1]); + argc -= 2; + argv += 2; + } else if (strcmp(argv[0], "--offset") == 0) { + // + // Hex or decimal? + // + if ((argv[1][0] == '0') && (tolower (argv[1][1]) == 'x')) { + if (sscanf (argv[1], "%x", &Offset) != 1) { + Error (NULL, 0, 1003, "Invalid option value", "Offset = %s", argv[1]); + return GetUtilityStatus (); + } + } else { + if (sscanf (argv[1], "%d", &Offset) != 1) { + Error (NULL, 0, 1003, "Invalid option value", "Offset = %s", argv[1]); + return GetUtilityStatus (); + } + // + // See if they said something like "64K" + // + if (tolower (argv[1][strlen (argv[1]) - 1]) == 'k') { + Offset *= 1024; + } + } + + argc -= 2; + argv += 2; + } else { + Usage (); + return -1; + } + } + // + // Check for proper number of arguments + // + if (argc != 1) { + Usage (); + return -1; + } + // + // Look for help options + // + if ((strcmp(argv[0], "-h") == 0) || (strcmp(argv[0], "--help") == 0) || + (strcmp(argv[0], "-?") == 0) || (strcmp(argv[0], "/?") == 0)) { + Usage(); + return STATUS_ERROR; + } + + // + // Open the file containing the FV + // + InputFile = fopen (argv[0], "rb"); + if (InputFile == NULL) { + Error (NULL, 0, 0001, "Error opening the input file", argv[0]); + return GetUtilityStatus (); + } + // + // Skip over pad bytes if specified. This is used if they prepend 0xff + // data to the FV image binary. + // + if (Offset != 0) { + fseek (InputFile, Offset, SEEK_SET); + } + // + // Determine size of FV + // + Status = ReadHeader (InputFile, &FvSize, &ErasePolarity); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 0003, "error parsing FV image", "%s Header is invalid", argv[0]); + fclose (InputFile); + return GetUtilityStatus (); + } + // + // Allocate a buffer for the FV image + // + FvImage = malloc (FvSize); + if (FvImage == NULL) { + Error (NULL, 0, 4001, "Resource: Memory can't be allocated", NULL); + fclose (InputFile); + return GetUtilityStatus (); + } + // + // Seek to the start of the image, then read the entire FV to the buffer + // + fseek (InputFile, Offset, SEEK_SET); + BytesRead = fread (FvImage, 1, FvSize, InputFile); + fclose (InputFile); + if ((unsigned int) BytesRead != FvSize) { + Error (NULL, 0, 0004, "error reading FvImage from", argv[0]); + free (FvImage); + return GetUtilityStatus (); + } + + LoadGuidedSectionToolsTxt (argv[0]); + + PrintFvInfo (FvImage); + + // + // Clean up + // + free (FvImage); + FreeGuidBaseNameList (); + return GetUtilityStatus (); +} + + +static +EFI_STATUS +PrintFvInfo ( + IN VOID *Fv + ) +/*++ + +Routine Description: + + GC_TODO: Add function description + +Arguments: + + Fv - Firmware Volume to print information about + +Returns: + + EFI_STATUS + +--*/ +{ + EFI_STATUS Status; + UINTN NumberOfFiles; + BOOLEAN ErasePolarity; + UINTN FvSize; + EFI_FFS_FILE_HEADER *CurrentFile; + UINTN Key; + + Status = FvBufGetSize (Fv, &FvSize); + + NumberOfFiles = 0; + ErasePolarity = + (((EFI_FIRMWARE_VOLUME_HEADER*)Fv)->Attributes & EFI_FVB2_ERASE_POLARITY) ? + TRUE : FALSE; + + // + // Get the first file + // + Key = 0; + Status = FvBufFindNextFile (Fv, &Key, (VOID **) &CurrentFile); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 0003, "error parsing FV image", "cannot find the first file in the FV image"); + return GetUtilityStatus (); + } + // + // Display information about files found + // + while (CurrentFile != NULL) { + // + // Increment the number of files counter + // + NumberOfFiles++; + + // + // Display info about this file + // + Status = PrintFileInfo (Fv, CurrentFile, ErasePolarity); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 0003, "error parsing FV image", "failed to parse a file in the FV"); + return GetUtilityStatus (); + } + // + // Get the next file + // + Status = FvBufFindNextFile (Fv, &Key, (VOID **) &CurrentFile); + if (Status == EFI_NOT_FOUND) { + CurrentFile = NULL; + } else if (EFI_ERROR (Status)) { + Error (NULL, 0, 0003, "error parsing FV image", "cannot find the next file in the FV image"); + return GetUtilityStatus (); + } + } + + printf ("There are a total of %d files in this FV\n", (int) NumberOfFiles); + + return EFI_SUCCESS; +} + +UINT32 +GetOccupiedSize ( + IN UINT32 ActualSize, + IN UINT32 Alignment + ) +/*++ + +Routine Description: + + This function returns the next larger size that meets the alignment + requirement specified. + +Arguments: + + ActualSize The size. + Alignment The desired alignment. + +Returns: + + EFI_SUCCESS Function completed successfully. + EFI_ABORTED The function encountered an error. + +--*/ +{ + UINT32 OccupiedSize; + + OccupiedSize = ActualSize; + while ((OccupiedSize & (Alignment - 1)) != 0) { + OccupiedSize++; + } + + return OccupiedSize; +} + +static +CHAR8 * +SectionNameToStr ( + IN EFI_SECTION_TYPE Type + ) +/*++ + +Routine Description: + + Converts EFI Section names to Strings + +Arguments: + + Type - The EFI Section type + +Returns: + + CHAR8* - Pointer to the String containing the section name. + +--*/ +{ + CHAR8 *SectionStr; + CHAR8 *SectionTypeStringTable[] = { + "EFI_SECTION_ALL", + // + // 0X00 + // + "EFI_SECTION_COMPRESSION", + // + // 0x01 + // + "EFI_SECTION_GUID_DEFINED", + // + // 0x02 + // + "Unknown section type - Reserved 0x03", + // + // 0x03 + // + "Unknown section type - Reserved 0x04", + // + // 0x04 + // + "Unknown section type - Reserved 0x05", + // + // 0x05 + // + "Unknown section type - Reserved 0x06", + // + // 0x06 + // + "Unknown section type - Reserved 0x07", + // + // 0x07 + // + "Unknown section type - Reserved 0x08", + // + // 0x08 + // + "Unknown section type - Reserved 0x09", + // + // 0x09 + // + "Unknown section type - Reserved 0x0A", + // + // 0x0A + // + "Unknown section type - Reserved 0x0B", + // + // 0x0B + // + "Unknown section type - Reserved 0x0C", + // + // 0x0C + // + "Unknown section type - Reserved 0x0D", + // + // 0x0D + // + "Unknown section type - Reserved 0x0E", + // + // 0x0E + // + "Unknown section type - Reserved 0x0F", + // + // 0x0F + // + "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 + // + "Unknown section type - 0x1A", + // + // 0x1A + // + "EFI_SECTION_PEI_DEPEX", + // + // 0x1B + // + "Unknown section type - Reserved - beyond last defined section" + // + // 0x1C+ + // + }; + + if (Type > EFI_SECTION_LAST_SECTION_TYPE) { + Type = EFI_SECTION_LAST_SECTION_TYPE + 1; + } + + SectionStr = malloc (100); + if (SectionStr == NULL) { + printf ("Error: Out of memory resources.\n"); + return SectionStr; + } + strcpy (SectionStr, SectionTypeStringTable[Type]); + return SectionStr; +} + +STATIC +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 (__FILE__, __LINE__, 0, "application error", "invalid parameter to function"); + 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; + + // + // Print FV header information + // + printf ("Signature: %s (%X)\n", (char *) Signature, VolumeHeader.Signature); + printf ("Attributes: %X\n", VolumeHeader.Attributes); + + if (VolumeHeader.Attributes & EFI_FVB2_READ_DISABLED_CAP) { + printf (" EFI_FVB2_READ_DISABLED_CAP\n"); + } + + if (VolumeHeader.Attributes & EFI_FVB2_READ_ENABLED_CAP) { + printf (" EFI_FVB2_READ_ENABLED_CAP\n"); + } + + if (VolumeHeader.Attributes & EFI_FVB2_READ_STATUS) { + printf (" EFI_FVB2_READ_STATUS\n"); + } + + if (VolumeHeader.Attributes & EFI_FVB2_WRITE_DISABLED_CAP) { + printf (" EFI_FVB2_WRITE_DISABLED_CAP\n"); + } + + if (VolumeHeader.Attributes & EFI_FVB2_WRITE_ENABLED_CAP) { + printf (" EFI_FVB2_WRITE_ENABLED_CAP\n"); + } + + if (VolumeHeader.Attributes & EFI_FVB2_WRITE_STATUS) { + printf (" EFI_FVB2_WRITE_STATUS\n"); + } + + if (VolumeHeader.Attributes & EFI_FVB2_LOCK_CAP) { + printf (" EFI_FVB2_LOCK_CAP\n"); + } + + if (VolumeHeader.Attributes & EFI_FVB2_LOCK_STATUS) { + printf (" EFI_FVB2_LOCK_STATUS\n"); + } + + if (VolumeHeader.Attributes & EFI_FVB2_STICKY_WRITE) { + printf (" EFI_FVB2_STICKY_WRITE\n"); + } + + if (VolumeHeader.Attributes & EFI_FVB2_MEMORY_MAPPED) { + printf (" EFI_FVB2_MEMORY_MAPPED\n"); + } + + if (VolumeHeader.Attributes & EFI_FVB2_ERASE_POLARITY) { + printf (" EFI_FVB2_ERASE_POLARITY\n"); + *ErasePolarity = TRUE; + } + +#if (PI_SPECIFICATION_VERSION < 0x00010000) + if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT) { + printf (" EFI_FVB2_ALIGNMENT\n"); + } + + if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_2) { + printf (" EFI_FVB2_ALIGNMENT_2\n"); + } + + if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_4) { + printf (" EFI_FVB2_ALIGNMENT_4\n"); + } + + if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_8) { + printf (" EFI_FVB2_ALIGNMENT_8\n"); + } + + if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_16) { + printf (" EFI_FVB2_ALIGNMENT_16\n"); + } + + if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_32) { + printf (" EFI_FVB2_ALIGNMENT_32\n"); + } + + if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_64) { + printf (" EFI_FVB2_ALIGNMENT_64\n"); + } + + if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_128) { + printf (" EFI_FVB2_ALIGNMENT_128\n"); + } + + if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_256) { + printf (" EFI_FVB2_ALIGNMENT_256\n"); + } + + if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_512) { + printf (" EFI_FVB2_ALIGNMENT_512\n"); + } + + if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_1K) { + printf (" EFI_FVB2_ALIGNMENT_1K\n"); + } + + if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_2K) { + printf (" EFI_FVB2_ALIGNMENT_2K\n"); + } + + if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_4K) { + printf (" EFI_FVB2_ALIGNMENT_4K\n"); + } + + if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_8K) { + printf (" EFI_FVB2_ALIGNMENT_8K\n"); + } + + if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_16K) { + printf (" EFI_FVB2_ALIGNMENT_16K\n"); + } + + if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_32K) { + printf (" EFI_FVB2_ALIGNMENT_32K\n"); + } + + if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_64K) { + printf (" EFI_FVB2_ALIGNMENT_64K\n"); + } + +#else + + if (VolumeHeader.Attributes & EFI_FVB2_READ_LOCK_CAP) { + printf (" EFI_FVB2_READ_LOCK_CAP\n"); + } + + if (VolumeHeader.Attributes & EFI_FVB2_READ_LOCK_STATUS) { + printf (" EFI_FVB2_READ_LOCK_STATUS\n"); + } + + if (VolumeHeader.Attributes & EFI_FVB2_WRITE_LOCK_CAP) { + printf (" EFI_FVB2_WRITE_LOCK_CAP\n"); + } + + if (VolumeHeader.Attributes & EFI_FVB2_WRITE_LOCK_STATUS) { + printf (" EFI_FVB2_WRITE_LOCK_STATUS\n"); + } + + if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_1) { + printf (" EFI_FVB2_ALIGNMENT_1\n"); + } + + if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_2) { + printf (" EFI_FVB2_ALIGNMENT_2\n"); + } + + if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_4) { + printf (" EFI_FVB2_ALIGNMENT_4\n"); + } + + if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_8) { + printf (" EFI_FVB2_ALIGNMENT_8\n"); + } + + if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_16) { + printf (" EFI_FVB2_ALIGNMENT_16\n"); + } + + if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_32) { + printf (" EFI_FVB2_ALIGNMENT_32\n"); + } + + if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_64) { + printf (" EFI_FVB2_ALIGNMENT_64\n"); + } + + if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_128) { + printf (" EFI_FVB2_ALIGNMENT_128\n"); + } + + if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_256) { + printf (" EFI_FVB2_ALIGNMENT_256\n"); + } + + if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_512) { + printf (" EFI_FVB2_ALIGNMENT_512\n"); + } + + if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_1K) { + printf (" EFI_FVB2_ALIGNMENT_1K\n"); + } + + if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_2K) { + printf (" EFI_FVB2_ALIGNMENT_2K\n"); + } + + if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_4K) { + printf (" EFI_FVB2_ALIGNMENT_4K\n"); + } + + if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_8K) { + printf (" EFI_FVB2_ALIGNMENT_8K\n"); + } + + if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_16K) { + printf (" EFI_FVB2_ALIGNMENT_16K\n"); + } + + if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_32K) { + printf (" EFI_FVB2_ALIGNMENT_32K\n"); + } + + if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_64K) { + printf (" EFI_FVB2_ALIGNMENT_64K\n"); + } + + if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_128K) { + printf (" EFI_FVB2_ALIGNMENT_128K\n"); + } + + if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_256K) { + printf (" EFI_FVB2_ALIGNMENT_256K\n"); + } + + if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMNET_512K) { + printf (" EFI_FVB2_ALIGNMNET_512K\n"); + } + + if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_1M) { + printf (" EFI_FVB2_ALIGNMENT_1M\n"); + } + + if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_2M) { + printf (" EFI_FVB2_ALIGNMENT_2M\n"); + } + + if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_4M) { + printf (" EFI_FVB2_ALIGNMENT_4M\n"); + } + + if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_8M) { + printf (" EFI_FVB2_ALIGNMENT_8M\n"); + } + + if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_16M) { + printf (" EFI_FVB2_ALIGNMENT_16M\n"); + } + + if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_32M) { + printf (" EFI_FVB2_ALIGNMENT_32M\n"); + } + + if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_64M) { + printf (" EFI_FVB2_ALIGNMENT_64M\n"); + } + + if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_128M) { + printf (" EFI_FVB2_ALIGNMENT_128M\n"); + } + + if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_64M) { + printf (" EFI_FVB2_ALIGNMENT_64M\n"); + } + + if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_128M) { + printf (" EFI_FVB2_ALIGNMENT_128M\n"); + } + + if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_256M) { + printf (" EFI_FVB2_ALIGNMENT_256M\n"); + } + + if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_512M) { + printf (" EFI_FVB2_ALIGNMENT_512M\n"); + } + + if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_1G) { + printf (" EFI_FVB2_ALIGNMENT_1G\n"); + } + + if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_2G) { + printf (" EFI_FVB2_ALIGNMENT_2G\n"); + } + +#endif + printf ("Header Length: 0x%08X\n", VolumeHeader.HeaderLength); + printf ("File System ID: "); + PrintGuid (&VolumeHeader.FileSystemGuid); + // + // printf ("\n"); + // + printf ("Revision: 0x%04X\n", VolumeHeader.Revision); + + do { + fread (&BlockMap, sizeof (EFI_FV_BLOCK_MAP_ENTRY), 1, InputFile); + BytesRead += sizeof (EFI_FV_BLOCK_MAP_ENTRY); + + if (BlockMap.NumBlocks != 0) { + printf ("Number of Blocks: 0x%08X\n", BlockMap.NumBlocks); + printf ("Block Length: 0x%08X\n", BlockMap.Length); + Size += BlockMap.NumBlocks * BlockMap.Length; + } + + } while (!(BlockMap.NumBlocks == 0 && BlockMap.Length == 0)); + + if (BytesRead != VolumeHeader.HeaderLength) { + printf ("ERROR: Header length not consistent with Block Maps!\n"); + return EFI_ABORTED; + } + + if (VolumeHeader.FvLength != Size) { + printf ("ERROR: Volume Size not consistant with Block Maps!\n"); + return EFI_ABORTED; + } + + printf ("Total Volume Size: 0x%08X\n", Size); + + *FvSize = Size; + + // + // rewind (InputFile); + // + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +PrintFileInfo ( + EFI_FIRMWARE_VOLUME_HEADER *FvImage, + EFI_FFS_FILE_HEADER *FileHeader, + BOOLEAN ErasePolarity + ) +/*++ + +Routine Description: + + GC_TODO: Add function description + +Arguments: + + FvImage - GC_TODO: add argument description + FileHeader - GC_TODO: add argument description + ErasePolarity - GC_TODO: add argument description + +Returns: + + EFI_SUCCESS - GC_TODO: Add description for return value + EFI_ABORTED - GC_TODO: Add description for return value + +--*/ +{ + UINT32 FileLength; + UINT8 FileState; + UINT8 Checksum; + EFI_FFS_FILE_HEADER BlankHeader; + EFI_STATUS Status; + UINT8 GuidBuffer[PRINTED_GUID_BUFFER_SIZE]; +#if (PI_SPECIFICATION_VERSION < 0x00010000) + UINT16 *Tail; +#endif + // + // 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, FileHeader, sizeof (EFI_FFS_FILE_HEADER)) == 0) { + return EFI_SUCCESS; + } + // + // Print file information. + // + printf ("============================================================\n"); + + printf ("File Name: "); + PrintGuidToBuffer (&FileHeader->Name, GuidBuffer, sizeof (GuidBuffer), TRUE); + printf ("%s ", GuidBuffer); + PrintGuidName (GuidBuffer); + printf ("\n"); + + // + // PrintGuid (&FileHeader->Name); + // printf ("\n"); + // + FileLength = GetLength (FileHeader->Size); + printf ("File Offset: 0x%08X\n", (unsigned) ((UINTN) FileHeader - (UINTN) FvImage)); + printf ("File Length: 0x%08X\n", FileLength); + printf ("File Attributes: 0x%02X\n", FileHeader->Attributes); + printf ("File State: 0x%02X\n", FileHeader->State); + + // + // Print file state + // + FileState = GetFileState (ErasePolarity, FileHeader); + + switch (FileState) { + + case EFI_FILE_HEADER_CONSTRUCTION: + printf (" EFI_FILE_HEADER_CONSTRUCTION\n"); + return EFI_SUCCESS; + + case EFI_FILE_HEADER_INVALID: + printf (" EFI_FILE_HEADER_INVALID\n"); + return EFI_SUCCESS; + + case EFI_FILE_HEADER_VALID: + printf (" EFI_FILE_HEADER_VALID\n"); + Checksum = CalculateSum8 ((UINT8 *) FileHeader, sizeof (EFI_FFS_FILE_HEADER)); + Checksum = (UINT8) (Checksum - FileHeader->IntegrityCheck.Checksum.File); + Checksum = (UINT8) (Checksum - FileHeader->State); + if (Checksum != 0) { + printf ("ERROR: Header checksum invalid.\n"); + return EFI_ABORTED; + } + + return EFI_SUCCESS; + + case EFI_FILE_DELETED: + printf (" EFI_FILE_DELETED\n"); + + case EFI_FILE_MARKED_FOR_UPDATE: + printf (" EFI_FILE_MARKED_FOR_UPDATE\n"); + + case EFI_FILE_DATA_VALID: + printf (" EFI_FILE_DATA_VALID\n"); + + // + // 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) { + Error (NULL, 0, 0003, "error parsing FFS file", "FFS file with Guid %s has invalid header checksum", GuidBuffer); + return EFI_ABORTED; + } + + FileLength = GetLength (FileHeader->Size); + + if (FileHeader->Attributes & FFS_ATTRIB_CHECKSUM) { + // + // Calculate file checksum + // + Checksum = CalculateSum8 ((UINT8 *) FileHeader, FileLength); + Checksum = (UINT8) (Checksum - FileHeader->State); + if (Checksum != 0) { + Error (NULL, 0, 0003, "error parsing FFS file", "FFS file with Guid %s has invalid file checksum", GuidBuffer); + return EFI_ABORTED; + } + } else { + if (FileHeader->IntegrityCheck.Checksum.File != FFS_FIXED_CHECKSUM) { + Error (NULL, 0, 0003, "error parsing FFS file", "FFS file with Guid %s has invalid header checksum -- not set to fixed value of 0x5A", GuidBuffer); + return EFI_ABORTED; + } + } +#if (PI_SPECIFICATION_VERSION < 0x00010000) + // + // Verify tail if present + // + if (FileHeader->Attributes & FFS_ATTRIB_TAIL_PRESENT) { + // + // Verify tail is complement of integrity check field in the header. + // + Tail = (UINT16 *) ((UINTN) FileHeader + GetLength (FileHeader->Size) - sizeof (EFI_FFS_INTEGRITY_CHECK)); + if (FileHeader->IntegrityCheck.TailReference != (UINT16)~(*Tail)) { + Error (NULL, 0, 0003, "error parsing FFS file", \ + "FFS file with Guid %s failed in the integrity check, tail is not the complement of the header field", GuidBuffer); + return EFI_ABORTED; + } + } + #endif + break; + + default: + Error (NULL, 0, 0003, "error parsing FFS file", "FFS file with Guid %s has the invalid/unrecognized file state bits", GuidBuffer); + return EFI_ABORTED; + } + + printf ("File Type: 0x%02X ", FileHeader->Type); + + switch (FileHeader->Type) { + + case EFI_FV_FILETYPE_RAW: + printf ("EFI_FV_FILETYPE_RAW\n"); + break; + + case EFI_FV_FILETYPE_FREEFORM: + printf ("EFI_FV_FILETYPE_FREEFORM\n"); + break; + + case EFI_FV_FILETYPE_SECURITY_CORE: + printf ("EFI_FV_FILETYPE_SECURITY_CORE\n"); + break; + + case EFI_FV_FILETYPE_PEI_CORE: + printf ("EFI_FV_FILETYPE_PEI_CORE\n"); + break; + + case EFI_FV_FILETYPE_DXE_CORE: + printf ("EFI_FV_FILETYPE_DXE_CORE\n"); + break; + + case EFI_FV_FILETYPE_PEIM: + printf ("EFI_FV_FILETYPE_PEIM\n"); + break; + + case EFI_FV_FILETYPE_DRIVER: + printf ("EFI_FV_FILETYPE_DRIVER\n"); + break; + + case EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER: + printf ("EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER\n"); + break; + + case EFI_FV_FILETYPE_APPLICATION: + printf ("EFI_FV_FILETYPE_APPLICATION\n"); + break; + + case EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE: + printf ("EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE\n"); + break; + + case EFI_FV_FILETYPE_FFS_PAD: + printf ("EFI_FV_FILETYPE_FFS_PAD\n"); + break; + + default: + printf ("\nERROR: Unrecognized file type %X.\n", FileHeader->Type); + return EFI_ABORTED; + break; + } + + switch (FileHeader->Type) { + + case EFI_FV_FILETYPE_ALL: + case EFI_FV_FILETYPE_RAW: + case EFI_FV_FILETYPE_FFS_PAD: + break; + + default: + // + // All other files have sections + // + Status = ParseSection ( + (UINT8 *) ((UINTN) FileHeader + sizeof (EFI_FFS_FILE_HEADER)), + GetLength (FileHeader->Size) - sizeof (EFI_FFS_FILE_HEADER) + ); + if (EFI_ERROR (Status)) { + // + // printf ("ERROR: Parsing the FFS file.\n"); + // + return EFI_ABORTED; + } + break; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +ParseSection ( + IN UINT8 *SectionBuffer, + IN UINT32 BufferLength + ) +/*++ + +Routine Description: + + Parses EFI Sections + +Arguments: + + SectionBuffer - Buffer containing the section to parse. + BufferLength - Length of SectionBuffer + +Returns: + + EFI_SECTION_ERROR - Problem with section parsing. + (a) compression errors + (b) unrecognized section + EFI_UNSUPPORTED - Do not know how to parse the section. + EFI_SUCCESS - Section successfully parsed. + EFI_OUT_OF_RESOURCES - Memory allocation failed. + +--*/ +{ + EFI_SECTION_TYPE Type; + UINT8 *Ptr; + UINT32 SectionLength; + CHAR8 *SectionName; + EFI_STATUS Status; + UINT32 ParsedLength; + UINT8 *CompressedBuffer; + UINT32 CompressedLength; + UINT8 *UncompressedBuffer; + UINT32 UncompressedLength; + UINT8 *ToolOutputBuffer; + UINT32 ToolOutputLength; + UINT8 CompressionType; + UINT32 DstSize; + UINT32 ScratchSize; + UINT8 *ScratchBuffer; + DECOMPRESS_FUNCTION DecompressFunction; + GETINFO_FUNCTION GetInfoFunction; + // CHAR16 *name; + CHAR8 *ExtractionTool; + CHAR8 *ToolInputFile; + CHAR8 *ToolOutputFile; + CHAR8 *SystemCommandFormatString; + CHAR8 *SystemCommand; + + ParsedLength = 0; + while (ParsedLength < BufferLength) { + Ptr = SectionBuffer + ParsedLength; + + SectionLength = GetLength (((EFI_COMMON_SECTION_HEADER *) Ptr)->Size); + Type = ((EFI_COMMON_SECTION_HEADER *) Ptr)->Type; + + // + // This is sort of an odd check, but is necessary because FFS files are + // padded to a QWORD boundary, meaning there is potentially a whole section + // header worth of 0xFF bytes. + // + if (SectionLength == 0xffffff && Type == 0xff) { + ParsedLength += 4; + continue; + } + + SectionName = SectionNameToStr (Type); + printf ("------------------------------------------------------------\n"); + printf (" Type: %s\n Size: 0x%08X\n", SectionName, SectionLength); + free (SectionName); + + switch (Type) { + case EFI_SECTION_RAW: + case EFI_SECTION_PE32: + case EFI_SECTION_PIC: + case EFI_SECTION_TE: + // default is no more information + break; + + case EFI_SECTION_USER_INTERFACE: + // name = &((EFI_USER_INTERFACE_SECTION *) Ptr)->FileNameString; + // printf (" String: %s\n", &name); + break; + + case EFI_SECTION_FIRMWARE_VOLUME_IMAGE: + Status = PrintFvInfo (((EFI_FIRMWARE_VOLUME_IMAGE_SECTION*)Ptr) + 1); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 0003, "printing of FV section contents failed", NULL); + return EFI_SECTION_ERROR; + } + break; + + case EFI_SECTION_COMPATIBILITY16: + case EFI_SECTION_FREEFORM_SUBTYPE_GUID: + // + // Section does not contain any further header information. + // + break; + + case EFI_SECTION_DXE_DEPEX: + case EFI_SECTION_PEI_DEPEX: + DumpDepexSection (Ptr, SectionLength); + break; + + case EFI_SECTION_VERSION: + printf (" Build Number: 0x%02X\n", ((EFI_VERSION_SECTION *) Ptr)->BuildNumber); + printf (" Version Strg: %s\n", (char*) ((EFI_VERSION_SECTION *) Ptr)->VersionString); + break; + + case EFI_SECTION_COMPRESSION: + UncompressedBuffer = NULL; + CompressedLength = SectionLength - sizeof (EFI_COMPRESSION_SECTION); + UncompressedLength = ((EFI_COMPRESSION_SECTION *) Ptr)->UncompressedLength; + CompressionType = ((EFI_COMPRESSION_SECTION *) Ptr)->CompressionType; + printf (" Uncompressed Length: 0x%08X\n", UncompressedLength); + + if (CompressionType == EFI_NOT_COMPRESSED) { + printf (" Compression Type: EFI_NOT_COMPRESSED\n"); + if (CompressedLength != UncompressedLength) { + Error ( + NULL, + 0, + 0, + "file is not compressed, but the compressed length does not match the uncompressed length", + NULL + ); + return EFI_SECTION_ERROR; + } + + UncompressedBuffer = Ptr + sizeof (EFI_COMPRESSION_SECTION); + } else if (CompressionType == EFI_STANDARD_COMPRESSION) { + GetInfoFunction = EfiGetInfo; + DecompressFunction = EfiDecompress; + printf (" Compression Type: EFI_STANDARD_COMPRESSION\n"); + + CompressedBuffer = Ptr + sizeof (EFI_COMPRESSION_SECTION); + + Status = GetInfoFunction (CompressedBuffer, CompressedLength, &DstSize, &ScratchSize); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 0003, "error getting compression info from compression section", NULL); + return EFI_SECTION_ERROR; + } + + if (DstSize != UncompressedLength) { + Error (NULL, 0, 0003, "compression error in the compression section", NULL); + return EFI_SECTION_ERROR; + } + + ScratchBuffer = malloc (ScratchSize); + UncompressedBuffer = malloc (UncompressedLength); + if ((ScratchBuffer == NULL) || (UncompressedBuffer == NULL)) { + return EFI_OUT_OF_RESOURCES; + } + Status = DecompressFunction ( + CompressedBuffer, + CompressedLength, + UncompressedBuffer, + UncompressedLength, + ScratchBuffer, + ScratchSize + ); + free (ScratchBuffer); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 0003, "decompress failed", NULL); + free (UncompressedBuffer); + return EFI_SECTION_ERROR; + } + } else { + Error (NULL, 0, 0003, "unrecognized compression type", "type 0x%X", (UINT32) CompressionType); + return EFI_SECTION_ERROR; + } + + Status = ParseSection (UncompressedBuffer, UncompressedLength); + + if (CompressionType == EFI_STANDARD_COMPRESSION) { + // + // We need to deallocate Buffer + // + free (UncompressedBuffer); + } + + if (EFI_ERROR (Status)) { + Error (NULL, 0, 0003, "failed to parse section", NULL); + return EFI_SECTION_ERROR; + } + break; + + case EFI_SECTION_GUID_DEFINED: + printf (" SectionDefinitionGuid: "); + PrintGuid (&((EFI_GUID_DEFINED_SECTION *) Ptr)->SectionDefinitionGuid); + printf ("\n"); + printf (" DataOffset: 0x%04X\n", ((EFI_GUID_DEFINED_SECTION *) Ptr)->DataOffset); + printf (" Attributes: 0x%04X\n", ((EFI_GUID_DEFINED_SECTION *) Ptr)->Attributes); + + ExtractionTool = + LookupGuidedSectionToolPath ( + mParsedGuidedSectionTools, + &((EFI_GUID_DEFINED_SECTION *) Ptr)->SectionDefinitionGuid + ); + + if (ExtractionTool != NULL) { + + ToolInputFile = CloneString (tmpnam (NULL)); + ToolOutputFile = CloneString (tmpnam (NULL)); + + // + // Construction 'system' command string + // + SystemCommandFormatString = "%s -d -o %s %s"; + SystemCommand = malloc ( + strlen (SystemCommandFormatString) + + strlen (ExtractionTool) + + strlen (ToolInputFile) + + strlen (ToolOutputFile) + + 1 + ); + sprintf ( + SystemCommand, + SystemCommandFormatString, + ExtractionTool, + ToolOutputFile, + ToolInputFile + ); + free (ExtractionTool); + + Status = + PutFileImage ( + ToolInputFile, + (CHAR8*) SectionBuffer + ((EFI_GUID_DEFINED_SECTION *) Ptr)->DataOffset, + BufferLength - ((EFI_GUID_DEFINED_SECTION *) Ptr)->DataOffset + ); + + system (SystemCommand); + remove (ToolInputFile); + free (ToolInputFile); + + Status = + GetFileImage ( + ToolOutputFile, + (CHAR8 **)&ToolOutputBuffer, + &ToolOutputLength + ); + remove (ToolOutputFile); + free (ToolOutputFile); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 0004, "unable to read decoded GUIDED section", NULL); + return EFI_SECTION_ERROR; + } + + Status = ParseSection ( + ToolOutputBuffer, + ToolOutputLength + ); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 0003, "parse of decoded GUIDED section failed", NULL); + return EFI_SECTION_ERROR; + } + + // + // Check for CRC32 sections which we can handle internally if needed. + // + } else if (!CompareGuid ( + &((EFI_GUID_DEFINED_SECTION *) Ptr)->SectionDefinitionGuid, + &gEfiCrc32GuidedSectionExtractionProtocolGuid + ) + ) { + // + // CRC32 guided section + // + Status = ParseSection ( + SectionBuffer + ((EFI_GUID_DEFINED_SECTION *) Ptr)->DataOffset, + BufferLength - ((EFI_GUID_DEFINED_SECTION *) Ptr)->DataOffset + ); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 0003, "parse of CRC32 GUIDED section failed", NULL); + return EFI_SECTION_ERROR; + } + } else { + // + // We don't know how to parse it now. + // + Error (NULL, 0, 0003, "Error parsing section", \ + "EFI_SECTION_GUID_DEFINED cannot be parsed at this time. Tool to decode this section should have been defined in GuidedSectionTools.txt (built in the FV directory)."); + return EFI_UNSUPPORTED; + } + break; + + default: + // + // Unknown section, return error + // + Error (NULL, 0, 0003, "unrecognized section type found", "section type = 0x%X", (UINT32) Type); + return EFI_SECTION_ERROR; + } + + ParsedLength += SectionLength; + // + // We make then next section begin on a 4-byte boundary + // + ParsedLength = GetOccupiedSize (ParsedLength, 4); + } + + if (ParsedLength < BufferLength) { + Error (NULL, 0, 0003, "sections do not completely fill the sectioned buffer being parsed", NULL); + return EFI_SECTION_ERROR; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +DumpDepexSection ( + IN UINT8 *Ptr, + IN UINT32 SectionLength + ) +/*++ + +Routine Description: + + GC_TODO: Add function description + +Arguments: + + Ptr - GC_TODO: add argument description + SectionLength - GC_TODO: add argument description + +Returns: + + EFI_SUCCESS - GC_TODO: Add description for return value + +--*/ +{ + UINT8 GuidBuffer[PRINTED_GUID_BUFFER_SIZE]; + + // + // Need at least a section header + data + // + if (SectionLength <= sizeof (EFI_COMMON_SECTION_HEADER)) { + return EFI_SUCCESS; + } + + Ptr += sizeof (EFI_COMMON_SECTION_HEADER); + SectionLength -= sizeof (EFI_COMMON_SECTION_HEADER); + while (SectionLength > 0) { + printf (" "); + switch (*Ptr) { + case EFI_DEP_BEFORE: + printf ("BEFORE\n"); + Ptr++; + SectionLength--; + break; + + case EFI_DEP_AFTER: + printf ("AFTER\n"); + Ptr++; + SectionLength--; + break; + + case EFI_DEP_PUSH: + printf ("PUSH\n "); + PrintGuidToBuffer ((EFI_GUID *) (Ptr + 1), GuidBuffer, sizeof (GuidBuffer), TRUE); + printf ("%s ", GuidBuffer); + PrintGuidName (GuidBuffer); + printf ("\n"); + // + // PrintGuid ((EFI_GUID *)(Ptr + 1)); + // + Ptr += 17; + SectionLength -= 17; + break; + + case EFI_DEP_AND: + printf ("AND\n"); + Ptr++; + SectionLength--; + break; + + case EFI_DEP_OR: + printf ("OR\n"); + Ptr++; + SectionLength--; + break; + + case EFI_DEP_NOT: + printf ("NOT\n"); + Ptr++; + SectionLength--; + break; + + case EFI_DEP_TRUE: + printf ("TRUE\n"); + Ptr++; + SectionLength--; + break; + + case EFI_DEP_FALSE: + printf ("FALSE\n"); + Ptr++; + SectionLength--; + break; + + case EFI_DEP_END: + printf ("END DEPEX\n"); + Ptr++; + SectionLength--; + break; + + case EFI_DEP_SOR: + printf ("SOR\n"); + Ptr++; + SectionLength--; + break; + + default: + printf ("Unrecognized byte in depex: 0x%X\n", (UINT32) *Ptr); + return EFI_SUCCESS; + } + } + + return EFI_SUCCESS; +} + +EFI_STATUS +PrintGuidName ( + IN UINT8 *GuidStr + ) +/*++ + +Routine Description: + + GC_TODO: Add function description + +Arguments: + + GuidStr - GC_TODO: add argument description + +Returns: + + EFI_SUCCESS - GC_TODO: Add description for return value + EFI_INVALID_PARAMETER - GC_TODO: Add description for return value + +--*/ +{ + GUID_TO_BASENAME *GPtr; + // + // If we have a list of guid-to-basenames, then go through the list to + // look for a guid string match. If found, print the basename to stdout, + // otherwise return a failure. + // + GPtr = mGuidBaseNameList; + while (GPtr != NULL) { + if (_stricmp ((CHAR8*) GuidStr, (CHAR8*) GPtr->Guid) == 0) { + printf ("%s", GPtr->BaseName); + return EFI_SUCCESS; + } + + GPtr = GPtr->Next; + } + + return EFI_INVALID_PARAMETER; +} + +EFI_STATUS +ParseGuidBaseNameFile ( + CHAR8 *FileName + ) +/*++ + +Routine Description: + + GC_TODO: Add function description + +Arguments: + + FileName - GC_TODO: add argument description + +Returns: + + EFI_DEVICE_ERROR - GC_TODO: Add description for return value + EFI_OUT_OF_RESOURCES - GC_TODO: Add description for return value + EFI_SUCCESS - GC_TODO: Add description for return value + +--*/ +{ + FILE *Fptr; + CHAR8 Line[MAX_LINE_LEN]; + GUID_TO_BASENAME *GPtr; + + if ((Fptr = fopen (FileName, "r")) == NULL) { + printf ("ERROR: Failed to open input cross-reference file '%s'\n", FileName); + return EFI_DEVICE_ERROR; + } + + while (fgets (Line, sizeof (Line), Fptr) != NULL) { + // + // Allocate space for another guid/basename element + // + GPtr = malloc (sizeof (GUID_TO_BASENAME)); + if (GPtr == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + memset ((char *) GPtr, 0, sizeof (GUID_TO_BASENAME)); + if (sscanf (Line, "%s %s", GPtr->Guid, GPtr->BaseName) == 2) { + GPtr->Next = mGuidBaseNameList; + mGuidBaseNameList = GPtr; + } else { + // + // Some sort of error. Just continue. + // + free (GPtr); + } + } + + fclose (Fptr); + return EFI_SUCCESS; +} + +EFI_STATUS +FreeGuidBaseNameList ( + VOID + ) +/*++ + +Routine Description: + + GC_TODO: Add function description + +Arguments: + + None + +Returns: + + EFI_SUCCESS - GC_TODO: Add description for return value + +--*/ +{ + GUID_TO_BASENAME *Next; + + while (mGuidBaseNameList != NULL) { + Next = mGuidBaseNameList->Next; + free (mGuidBaseNameList); + mGuidBaseNameList = Next; + } + + return EFI_SUCCESS; +} + + +static +VOID +LoadGuidedSectionToolsTxt ( + IN CHAR8* FirmwareVolumeFilename + ) +{ + CHAR8* PeerFilename; + CHAR8* Places[] = { + FirmwareVolumeFilename, + //mUtilityFilename, + }; + UINTN Index; + + mParsedGuidedSectionTools = NULL; + + for (Index = 0; Index < (sizeof(Places)/sizeof(Places[0])); Index++) { + PeerFilename = OsPathPeerFilePath (Places[Index], "GuidedSectionTools.txt"); + //printf("Loading %s...\n", PeerFilename); + if (OsPathExists (PeerFilename)) { + mParsedGuidedSectionTools = ParseGuidedSectionToolsFile (PeerFilename); + } + free (PeerFilename); + if (mParsedGuidedSectionTools != NULL) { + return; + } + } +} + + +void +Usage ( + VOID + ) +/*++ + +Routine Description: + + GC_TODO: Add function description + +Arguments: + + None + +Returns: + + GC_TODO: add return values + +--*/ +{ + // + // Summary usage + // + fprintf (stdout, "Usage: %s [options] \n\n", UTILITY_NAME); + + // + // Copyright declaration + // + fprintf (stdout, "Copyright (c) 2007, Intel Corporation. All rights reserved.\n\n"); + + // + // Details Option + // + fprintf (stdout, "Options:\n"); + fprintf (stdout, " -x xref, --xref xref\n\ + Parse basename to file-guid cross reference file(s).\n"); + fprintf (stdout, " --offset offset\n\ + Offset of file to start processing FV at.\n"); + fprintf (stdout, " -h, --help\n\ + Show this help message and exit.\n"); + +} + diff --git a/BaseTools/Source/C/VolInfo/VolInfo.h b/BaseTools/Source/C/VolInfo/VolInfo.h new file mode 100644 index 0000000000..2bee33ad1e --- /dev/null +++ b/BaseTools/Source/C/VolInfo/VolInfo.h @@ -0,0 +1,41 @@ +/** @file + +Copyright (c) 1999 - 2008, 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: + + VolInfo.c + +Abstract: + + Local Definitions for the VolInfo utility + +**/ + +#ifndef _VOLINFO_H_ +#define _VOLINFO_H_ 1 + +#define PI_SPECIFICATION_VERSION 0x00010000 + +#define EFI_DEP_BEFORE 0x00 +#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 +#define EFI_DEP_SOR 0x09 + +#define EFI_SECTION_LAST_LEAF_SECTION_TYPE 0x1B +#define EFI_SECTION_LAST_SECTION_TYPE 0x1B + +#endif diff --git a/BaseTools/Source/Python/AutoGen/AutoGen.py b/BaseTools/Source/Python/AutoGen/AutoGen.py new file mode 100644 index 0000000000..86f33fbd86 --- /dev/null +++ b/BaseTools/Source/Python/AutoGen/AutoGen.py @@ -0,0 +1,1919 @@ +## @file +# Generate AutoGen.h, AutoGen.c and *.depex files +# +# Copyright (c) 2007, 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. +# + +## Import Modules +# +import os +import re +import os.path as path +import copy + +import GenC +import GenMake +import GenDepex + +from StrGather import * +from BuildEngine import BuildRule + +from Common.BuildToolError import * +from Common.DataType import * +from Common.Misc import * +from Common.String import * +import Common.GlobalData as GlobalData +from GenFds.FdfParser import * +from CommonDataClass.CommonClass import SkuInfoClass +from Workspace.BuildClassObject import * + +## Regular expression for splitting Dependency Expression stirng into tokens +gDepexTokenPattern = re.compile("(\(|\)|\w+| \S+\.inf)") + +## Mapping Makefile type +gMakeTypeMap = {"MSFT":"nmake", "GCC":"gmake"} + + +## Build rule configuration file +gBuildRuleFile = 'Conf/build_rule.txt' + +## default file name for AutoGen +gAutoGenCodeFileName = "AutoGen.c" +gAutoGenHeaderFileName = "AutoGen.h" +gAutoGenStringFileName = "%(module_name)sStrDefs.h" +gAutoGenDepexFileName = "%(module_name)s.depex" +gAutoGenSmmDepexFileName = "%(module_name)s.smm" + +## Base class for AutoGen +# +# This class just implements the cache mechanism of AutoGen objects. +# +class AutoGen(object): + # database to maintain the objects of xxxAutoGen + _CACHE_ = {} # (BuildTarget, ToolChain) : {ARCH : {platform file: AutoGen object}}} + + ## Factory method + # + # @param Class class object of real AutoGen class + # (WorkspaceAutoGen, ModuleAutoGen or PlatformAutoGen) + # @param Workspace Workspace directory or WorkspaceAutoGen object + # @param MetaFile The path of meta file + # @param Target Build target + # @param Toolchain Tool chain name + # @param Arch Target arch + # @param *args The specific class related parameters + # @param **kwargs The specific class related dict parameters + # + def __new__(Class, Workspace, MetaFile, Target, Toolchain, Arch, *args, **kwargs): + # check if the object has been created + Key = (Target, Toolchain) + if Key not in Class._CACHE_ or Arch not in Class._CACHE_[Key] \ + or MetaFile not in Class._CACHE_[Key][Arch]: + AutoGenObject = super(AutoGen, Class).__new__(Class) + # call real constructor + if not AutoGenObject._Init(Workspace, MetaFile, Target, Toolchain, Arch, *args, **kwargs): + return None + if Key not in Class._CACHE_: + Class._CACHE_[Key] = {} + if Arch not in Class._CACHE_[Key]: + Class._CACHE_[Key][Arch] = {} + Class._CACHE_[Key][Arch][MetaFile] = AutoGenObject + else: + AutoGenObject = Class._CACHE_[Key][Arch][MetaFile] + + return AutoGenObject + + ## hash() operator + # + # The file path of platform file will be used to represent hash value of this object + # + # @retval int Hash value of the file path of platform file + # + def __hash__(self): + return hash(self.MetaFile) + + ## str() operator + # + # The file path of platform file will be used to represent this object + # + # @retval string String of platform file path + # + def __str__(self): + return str(self.MetaFile) + + ## "==" operator + def __eq__(self, Other): + return Other and self.MetaFile == Other + +## Workspace AutoGen class +# +# This class is used mainly to control the whole platform build for different +# architecture. This class will generate top level makefile. +# +class WorkspaceAutoGen(AutoGen): + ## Real constructor of WorkspaceAutoGen + # + # This method behaves the same as __init__ except that it needs explict invoke + # (in super class's __new__ method) + # + # @param WorkspaceDir Root directory of workspace + # @param ActivePlatform Meta-file of active platform + # @param Target Build target + # @param Toolchain Tool chain name + # @param ArchList List of architecture of current build + # @param MetaFileDb Database containing meta-files + # @param BuildConfig Configuration of build + # @param ToolDefinition Tool chain definitions + # @param FlashDefinitionFile File of flash definition + # @param Fds FD list to be generated + # @param Fvs FV list to be generated + # @param SkuId SKU id from command line + # + def _Init(self, WorkspaceDir, ActivePlatform, Target, Toolchain, ArchList, MetaFileDb, + BuildConfig, ToolDefinition, FlashDefinitionFile='', Fds=[], Fvs=[], SkuId=''): + self.MetaFile = ActivePlatform.MetaFile + self.WorkspaceDir = WorkspaceDir + self.Platform = ActivePlatform + self.BuildTarget = Target + self.ToolChain = Toolchain + self.ArchList = ArchList + self.SkuId = SkuId + + self.BuildDatabase = MetaFileDb + self.TargetTxt = BuildConfig + self.ToolDef = ToolDefinition + self.FdfFile = FlashDefinitionFile + self.FdTargetList = Fds + self.FvTargetList = Fvs + self.AutoGenObjectList = [] + + # there's many relative directory operations, so ... + os.chdir(self.WorkspaceDir) + + # parse FDF file to get PCDs in it, if any + if self.FdfFile != None and self.FdfFile != '': + Fdf = FdfParser(self.FdfFile.Path) + Fdf.ParseFile() + PcdSet = Fdf.Profile.PcdDict + ModuleList = Fdf.Profile.InfList + else: + PcdSet = {} + ModuleList = [] + + # apply SKU and inject PCDs from Flash Definition file + for Arch in self.ArchList: + Platform = self.BuildDatabase[self.MetaFile, Arch] + Platform.SkuName = self.SkuId + for Name, Guid in PcdSet: + Platform.AddPcd(Name, Guid, PcdSet[Name, Guid]) + + Pa = PlatformAutoGen(self, self.MetaFile, Target, Toolchain, Arch) + # + # Explicitly collect platform's dynamic PCDs + # + Pa.CollectPlatformDynamicPcds() + self.AutoGenObjectList.append(Pa) + + self._BuildDir = None + self._FvDir = None + self._MakeFileDir = None + self._BuildCommand = None + + return True + + def __repr__(self): + return "%s [%s]" % (self.MetaFile, ", ".join(self.ArchList)) + + ## Return the directory to store FV files + def _GetFvDir(self): + if self._FvDir == None: + self._FvDir = path.join(self.BuildDir, 'FV') + return self._FvDir + + ## Return the directory to store all intermediate and final files built + def _GetBuildDir(self): + return self.AutoGenObjectList[0].BuildDir + + ## Return the build output directory platform specifies + def _GetOutputDir(self): + return self.Platform.OutputDirectory + + ## Return platform name + def _GetName(self): + return self.Platform.PlatformName + + ## Return meta-file GUID + def _GetGuid(self): + return self.Platform.Guid + + ## Return platform version + def _GetVersion(self): + return self.Platform.Version + + ## Return paths of tools + def _GetToolDefinition(self): + return self.AutoGenObjectList[0].ToolDefinition + + ## Return directory of platform makefile + # + # @retval string Makefile directory + # + def _GetMakeFileDir(self): + if self._MakeFileDir == None: + self._MakeFileDir = self.BuildDir + return self._MakeFileDir + + ## Return build command string + # + # @retval string Build command string + # + def _GetBuildCommand(self): + if self._BuildCommand == None: + # BuildCommand should be all the same. So just get one from platform AutoGen + self._BuildCommand = self.AutoGenObjectList[0].BuildCommand + return self._BuildCommand + + ## Create makefile for the platform and mdoules in it + # + # @param CreateDepsMakeFile Flag indicating if the makefile for + # modules will be created as well + # + def CreateMakeFile(self, CreateDepsMakeFile=False): + # create makefile for platform + Makefile = GenMake.TopLevelMakefile(self) + if Makefile.Generate(): + EdkLogger.debug(EdkLogger.DEBUG_9, "Generated makefile for platform [%s] %s\n" % + (self.MetaFile, self.ArchList)) + else: + EdkLogger.debug(EdkLogger.DEBUG_9, "Skipped the generation of makefile for platform [%s] %s\n" % + (self.MetaFile, self.ArchList)) + + if CreateDepsMakeFile: + for Pa in self.AutoGenObjectList: + Pa.CreateMakeFile(CreateDepsMakeFile) + + ## Create autogen code for platform and modules + # + # Since there's no autogen code for platform, this method will do nothing + # if CreateModuleCodeFile is set to False. + # + # @param CreateDepsCodeFile Flag indicating if creating module's + # autogen code file or not + # + def CreateCodeFile(self, CreateDepsCodeFile=False): + if not CreateDepsCodeFile: + return + for Pa in self.AutoGenObjectList: + Pa.CreateCodeFile(CreateDepsCodeFile) + + Name = property(_GetName) + Guid = property(_GetGuid) + Version = property(_GetVersion) + OutputDir = property(_GetOutputDir) + + ToolDefinition = property(_GetToolDefinition) # toolcode : tool path + + BuildDir = property(_GetBuildDir) + FvDir = property(_GetFvDir) + MakeFileDir = property(_GetMakeFileDir) + BuildCommand = property(_GetBuildCommand) + +## AutoGen class for platform +# +# PlatformAutoGen class will process the original information in platform +# file in order to generate makefile for platform. +# +class PlatformAutoGen(AutoGen): + # + # Used to store all PCDs for both PEI and DXE phase, in order to generate + # correct PCD database + # + _DynaPcdList_ = [] + _NonDynaPcdList_ = [] + + ## The real constructor of PlatformAutoGen + # + # This method is not supposed to be called by users of PlatformAutoGen. It's + # only used by factory method __new__() to do real initialization work for an + # object of PlatformAutoGen + # + # @param Workspace WorkspaceAutoGen object + # @param PlatformFile Platform file (DSC file) + # @param Target Build target (DEBUG, RELEASE) + # @param Toolchain Name of tool chain + # @param Arch arch of the platform supports + # + def _Init(self, Workspace, PlatformFile, Target, Toolchain, Arch): + EdkLogger.debug(EdkLogger.DEBUG_9, "AutoGen platform [%s] [%s]" % (PlatformFile, Arch)) + GlobalData.gProcessingFile = "%s [%s, %s, %s]" % (PlatformFile, Arch, Toolchain, Target) + + self.MetaFile = PlatformFile + self.Workspace = Workspace + self.WorkspaceDir = Workspace.WorkspaceDir + self.ToolChain = Toolchain + self.BuildTarget = Target + self.Arch = Arch + self.SourceDir = PlatformFile.SubDir + self.SourceOverrideDir = None + self.FdTargetList = self.Workspace.FdTargetList + self.FvTargetList = self.Workspace.FvTargetList + + # flag indicating if the makefile/C-code file has been created or not + self.IsMakeFileCreated = False + self.IsCodeFileCreated = False + + self._Platform = None + self._Name = None + self._Guid = None + self._Version = None + + self._BuildRule = None + self._SourceDir = None + self._BuildDir = None + self._OutputDir = None + self._FvDir = None + self._MakeFileDir = None + self._FdfFile = None + + self._PcdTokenNumber = None # (TokenCName, TokenSpaceGuidCName) : GeneratedTokenNumber + self._DynamicPcdList = None # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...] + self._NonDynamicPcdList = None # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...] + + self._ToolDefinitions = None + self._ToolDefFile = None # toolcode : tool path + self._ToolChainFamily = None + self._BuildRuleFamily = None + self._BuildOption = None # toolcode : option + self._PackageList = None + self._ModuleAutoGenList = None + self._LibraryAutoGenList = None + self._BuildCommand = None + + # get the original module/package/platform objects + self.BuildDatabase = Workspace.BuildDatabase + return True + + def __repr__(self): + return "%s [%s]" % (self.MetaFile, self.Arch) + + ## Create autogen code for platform and modules + # + # Since there's no autogen code for platform, this method will do nothing + # if CreateModuleCodeFile is set to False. + # + # @param CreateModuleCodeFile Flag indicating if creating module's + # autogen code file or not + # + def CreateCodeFile(self, CreateModuleCodeFile=False): + # only module has code to be greated, so do nothing if CreateModuleCodeFile is False + if self.IsCodeFileCreated or not CreateModuleCodeFile: + return + + for Ma in self.ModuleAutoGenList: + Ma.CreateCodeFile(True) + + # don't do this twice + self.IsCodeFileCreated = True + + ## Create makefile for the platform and mdoules in it + # + # @param CreateModuleMakeFile Flag indicating if the makefile for + # modules will be created as well + # + def CreateMakeFile(self, CreateModuleMakeFile=False): + if CreateModuleMakeFile: + for ModuleFile in self.Platform.Modules: + Ma = ModuleAutoGen(self.Workspace, ModuleFile, self.BuildTarget, + self.ToolChain, self.Arch, self.MetaFile) + Ma.CreateMakeFile(True) + + # no need to create makefile for the platform more than once + if self.IsMakeFileCreated: + return + + # create makefile for platform + Makefile = GenMake.PlatformMakefile(self) + if Makefile.Generate(): + EdkLogger.debug(EdkLogger.DEBUG_9, "Generated makefile for platform [%s] [%s]\n" % + (self.MetaFile, self.Arch)) + else: + EdkLogger.debug(EdkLogger.DEBUG_9, "Skipped the generation of makefile for platform [%s] [%s]\n" % + (self.MetaFile, self.Arch)) + self.IsMakeFileCreated = True + + ## Collect dynamic PCDs + # + # Gather dynamic PCDs list from each module and their settings from platform + # This interface should be invoked explicitly when platform action is created. + # + def CollectPlatformDynamicPcds(self): + # for gathering error information + NoDatumTypePcdList = set() + + self._GuidValue = {} + for F in self.Platform.Modules.keys(): + M = ModuleAutoGen(self.Workspace, F, self.BuildTarget, self.ToolChain, self.Arch, self.MetaFile) + #GuidValue.update(M.Guids) + for PcdFromModule in M.ModulePcdList+M.LibraryPcdList: + # make sure that the "VOID*" kind of datum has MaxDatumSize set + if PcdFromModule.DatumType == "VOID*" and PcdFromModule.MaxDatumSize == None: + NoDatumTypePcdList.add("%s.%s [%s]" % (PcdFromModule.TokenSpaceGuidCName, PcdFromModule.TokenCName, F)) + + if PcdFromModule.Type in GenC.gDynamicPcd or PcdFromModule.Type in GenC.gDynamicExPcd: + # + # If a dynamic PCD used by a PEM module/PEI module & DXE module, + # it should be stored in Pcd PEI database, If a dynamic only + # used by DXE module, it should be stored in DXE PCD database. + # The default Phase is DXE + # + if M.ModuleType in ["PEIM", "PEI_CORE"]: + PcdFromModule.Phase = "PEI" + if PcdFromModule not in self._DynaPcdList_: + self._DynaPcdList_.append(PcdFromModule) + elif PcdFromModule.Phase == 'PEI': + # overwrite any the same PCD existing, if Phase is PEI + Index = self._DynaPcdList_.index(PcdFromModule) + self._DynaPcdList_[Index] = PcdFromModule + elif PcdFromModule not in self._NonDynaPcdList_: + self._NonDynaPcdList_.append(PcdFromModule) + + # print out error information and break the build, if error found + if len(NoDatumTypePcdList) > 0: + NoDatumTypePcdListString = "\n\t\t".join(NoDatumTypePcdList) + EdkLogger.error("build", AUTOGEN_ERROR, "PCD setting error", + File=self.MetaFile, + ExtraData="\n\tPCD(s) without MaxDatumSize:\n\t\t%s\n" + % NoDatumTypePcdListString) + self._NonDynamicPcdList = self._NonDynaPcdList_ + self._DynamicPcdList = self._DynaPcdList_ + + # + # Sort dynamic PCD list to: + # 1) If PCD's datum type is VOID* and value is unicode string which starts with L, the PCD item should + # try to be put header of dynamicd List + # 2) If PCD is HII type, the PCD item should be put after unicode type PCD + # + # The reason of sorting is make sure the unicode string is in double-byte alignment in string table. + # + UnicodePcdArray = [] + HiiPcdArray = [] + OtherPcdArray = [] + for Pcd in self._DynamicPcdList: + # just pick the a value to determine whether is unicode string type + Sku = Pcd.SkuInfoList[Pcd.SkuInfoList.keys()[0]] + PcdValue = Sku.DefaultValue + if Pcd.DatumType == 'VOID*' and PcdValue.startswith("L"): + # if found PCD which datum value is unicode string the insert to left size of UnicodeIndex + UnicodePcdArray.append(Pcd) + elif len(Sku.VariableName) > 0: + # if found HII type PCD then insert to right of UnicodeIndex + HiiPcdArray.append(Pcd) + else: + OtherPcdArray.append(Pcd) + del self._DynamicPcdList[:] + self._DynamicPcdList.extend(UnicodePcdArray) + self._DynamicPcdList.extend(HiiPcdArray) + self._DynamicPcdList.extend(OtherPcdArray) + + + ## Return the platform build data object + def _GetPlatform(self): + if self._Platform == None: + self._Platform = self.BuildDatabase[self.MetaFile, self.Arch] + return self._Platform + + ## Return platform name + def _GetName(self): + return self.Platform.PlatformName + + ## Return the meta file GUID + def _GetGuid(self): + return self.Platform.Guid + + ## Return the platform version + def _GetVersion(self): + return self.Platform.Version + + ## Return the FDF file name + def _GetFdfFile(self): + if self._FdfFile == None: + if self.Workspace.FdfFile != "": + self._FdfFile= path.join(self.WorkspaceDir, self.Workspace.FdfFile) + else: + self._FdfFile = '' + return self._FdfFile + + ## Return the build output directory platform specifies + def _GetOutputDir(self): + return self.Platform.OutputDirectory + + ## Return the directory to store all intermediate and final files built + def _GetBuildDir(self): + if self._BuildDir == None: + if os.path.isabs(self.OutputDir): + self._BuildDir = path.join( + path.abspath(self.OutputDir), + self.BuildTarget + "_" + self.ToolChain, + ) + else: + self._BuildDir = path.join( + self.WorkspaceDir, + self.OutputDir, + self.BuildTarget + "_" + self.ToolChain, + ) + return self._BuildDir + + ## Return directory of platform makefile + # + # @retval string Makefile directory + # + def _GetMakeFileDir(self): + if self._MakeFileDir == None: + self._MakeFileDir = path.join(self.BuildDir, self.Arch) + return self._MakeFileDir + + ## Return build command string + # + # @retval string Build command string + # + def _GetBuildCommand(self): + if self._BuildCommand == None: + self._BuildCommand = [] + if "MAKE" in self.ToolDefinition and "PATH" in self.ToolDefinition["MAKE"]: + self._BuildCommand += SplitOption(self.ToolDefinition["MAKE"]["PATH"]) + if "FLAGS" in self.ToolDefinition["MAKE"]: + NewOption = self.ToolDefinition["MAKE"]["FLAGS"].strip() + if NewOption != '': + self._BuildCommand += SplitOption(NewOption) + return self._BuildCommand + + ## Get tool chain definition + # + # Get each tool defition for given tool chain from tools_def.txt and platform + # + def _GetToolDefinition(self): + if self._ToolDefinitions == None: + ToolDefinition = self.Workspace.ToolDef.ToolsDefTxtDictionary + if TAB_TOD_DEFINES_COMMAND_TYPE not in self.Workspace.ToolDef.ToolsDefTxtDatabase: + EdkLogger.error('build', RESOURCE_NOT_AVAILABLE, "No tools found in configuration", + ExtraData="[%s]" % self.MetaFile) + self._ToolDefinitions = {} + DllPathList = set() + for Def in ToolDefinition: + Target, Tag, Arch, Tool, Attr = Def.split("_") + if Target != self.BuildTarget or Tag != self.ToolChain or Arch != self.Arch: + continue + + Value = ToolDefinition[Def] + # don't record the DLL + if Attr == "DLL": + DllPathList.add(Value) + continue + + if Tool not in self._ToolDefinitions: + self._ToolDefinitions[Tool] = {} + self._ToolDefinitions[Tool][Attr] = Value + + ToolsDef = '' + MakePath = '' + if GlobalData.gOptions.SilentMode and "MAKE" in self._ToolDefinitions: + if "FLAGS" not in self._ToolDefinitions["MAKE"]: + self._ToolDefinitions["MAKE"]["FLAGS"] = "" + self._ToolDefinitions["MAKE"]["FLAGS"] += " -s" + MakeFlags = '' + for Tool in self._ToolDefinitions: + for Attr in self._ToolDefinitions[Tool]: + Value = self._ToolDefinitions[Tool][Attr] + if Tool in self.BuildOption and Attr in self.BuildOption[Tool]: + # check if override is indicated + if self.BuildOption[Tool][Attr].startswith('='): + Value = self.BuildOption[Tool][Attr][1:] + else: + Value += " " + self.BuildOption[Tool][Attr] + + if Attr == "PATH": + # Don't put MAKE definition in the file + if Tool == "MAKE": + MakePath = Value + else: + ToolsDef += "%s = %s\n" % (Tool, Value) + elif Attr != "DLL": + # Don't put MAKE definition in the file + if Tool == "MAKE": + if Attr == "FLAGS": + MakeFlags = Value + else: + ToolsDef += "%s_%s = %s\n" % (Tool, Attr, Value) + ToolsDef += "\n" + + SaveFileOnChange(self.ToolDefinitionFile, ToolsDef) + for DllPath in DllPathList: + os.environ["PATH"] = DllPath + os.pathsep + os.environ["PATH"] + os.environ["MAKE_FLAGS"] = MakeFlags + + return self._ToolDefinitions + + ## Return the paths of tools + def _GetToolDefFile(self): + if self._ToolDefFile == None: + self._ToolDefFile = os.path.join(self.MakeFileDir, "TOOLS_DEF." + self.Arch) + return self._ToolDefFile + + ## Retrieve the toolchain family of given toolchain tag. Default to 'MSFT'. + def _GetToolChainFamily(self): + if self._ToolChainFamily == None: + ToolDefinition = self.Workspace.ToolDef.ToolsDefTxtDatabase + if TAB_TOD_DEFINES_FAMILY not in ToolDefinition \ + or self.ToolChain not in ToolDefinition[TAB_TOD_DEFINES_FAMILY] \ + or not ToolDefinition[TAB_TOD_DEFINES_FAMILY][self.ToolChain]: + EdkLogger.verbose("No tool chain family found in configuration for %s. Default to MSFT." \ + % self.ToolChain) + self._ToolChainFamily = "MSFT" + else: + self._ToolChainFamily = ToolDefinition[TAB_TOD_DEFINES_FAMILY][self.ToolChain] + return self._ToolChainFamily + + def _GetBuildRuleFamily(self): + if self._BuildRuleFamily == None: + ToolDefinition = self.Workspace.ToolDef.ToolsDefTxtDatabase + if TAB_TOD_DEFINES_BUILDRULEFAMILY not in ToolDefinition \ + or self.ToolChain not in ToolDefinition[TAB_TOD_DEFINES_BUILDRULEFAMILY] \ + or not ToolDefinition[TAB_TOD_DEFINES_BUILDRULEFAMILY][self.ToolChain]: + EdkLogger.verbose("No tool chain family found in configuration for %s. Default to MSFT." \ + % self.ToolChain) + self._BuildRuleFamily = "MSFT" + else: + self._BuildRuleFamily = ToolDefinition[TAB_TOD_DEFINES_BUILDRULEFAMILY][self.ToolChain] + return self._BuildRuleFamily + + ## Return the build options specific to this platform + def _GetBuildOptions(self): + if self._BuildOption == None: + self._BuildOption = self._ExpandBuildOption(self.Platform.BuildOptions) + return self._BuildOption + + ## Parse build_rule.txt in $(WORKSPACE)/Conf/build_rule.txt + # + # @retval BuildRule object + # + def _GetBuildRule(self): + if self._BuildRule == None: + BuildRuleFile = None + if TAB_TAT_DEFINES_BUILD_RULE_CONF in self.Workspace.TargetTxt.TargetTxtDictionary: + BuildRuleFile = self.Workspace.TargetTxt.TargetTxtDictionary[TAB_TAT_DEFINES_BUILD_RULE_CONF] + if BuildRuleFile in [None, '']: + BuildRuleFile = gBuildRuleFile + self._BuildRule = BuildRule(BuildRuleFile) + return self._BuildRule + + ## Summarize the packages used by modules in this platform + def _GetPackageList(self): + if self._PackageList == None: + self._PackageList = set() + for La in self.LibraryAutoGenList: + self._PackageList.update(La.DependentPackageList) + for Ma in self.ModuleAutoGenList: + self._PackageList.update(Ma.DependentPackageList) + self._PackageList = list(self._PackageList) + return self._PackageList + + ## Get list of non-dynamic PCDs + def _GetNonDynamicPcdList(self): + return self._NonDynamicPcdList + + ## Get list of dynamic PCDs + def _GetDynamicPcdList(self): + return self._DynamicPcdList + + ## Generate Token Number for all PCD + def _GetPcdTokenNumbers(self): + if self._PcdTokenNumber == None: + self._PcdTokenNumber = sdict() + TokenNumber = 1 + for Pcd in self.DynamicPcdList: + if Pcd.Phase == "PEI": + EdkLogger.debug(EdkLogger.DEBUG_5, "%s %s (%s) -> %d" % (Pcd.TokenCName, Pcd.TokenSpaceGuidCName, Pcd.Phase, TokenNumber)) + self._PcdTokenNumber[Pcd.TokenCName, Pcd.TokenSpaceGuidCName] = TokenNumber + TokenNumber += 1 + + for Pcd in self.DynamicPcdList: + if Pcd.Phase == "DXE": + EdkLogger.debug(EdkLogger.DEBUG_5, "%s %s (%s) -> %d" % (Pcd.TokenCName, Pcd.TokenSpaceGuidCName, Pcd.Phase, TokenNumber)) + self._PcdTokenNumber[Pcd.TokenCName, Pcd.TokenSpaceGuidCName] = TokenNumber + TokenNumber += 1 + + for Pcd in self.NonDynamicPcdList: + self._PcdTokenNumber[Pcd.TokenCName, Pcd.TokenSpaceGuidCName] = TokenNumber + TokenNumber += 1 + return self._PcdTokenNumber + + ## Summarize ModuleAutoGen objects of all modules/libraries to be built for this platform + def _GetAutoGenObjectList(self): + self._ModuleAutoGenList = [] + self._LibraryAutoGenList = [] + for ModuleFile in self.Platform.Modules: + Ma = ModuleAutoGen( + self.Workspace, + ModuleFile, + self.BuildTarget, + self.ToolChain, + self.Arch, + self.MetaFile + ) + if Ma not in self._ModuleAutoGenList: + self._ModuleAutoGenList.append(Ma) + for La in Ma.LibraryAutoGenList: + if La not in self._LibraryAutoGenList: + self._LibraryAutoGenList.append(La) + + ## Summarize ModuleAutoGen objects of all modules to be built for this platform + def _GetModuleAutoGenList(self): + if self._ModuleAutoGenList == None: + self._GetAutoGenObjectList() + return self._ModuleAutoGenList + + ## Summarize ModuleAutoGen objects of all libraries to be built for this platform + def _GetLibraryAutoGenList(self): + if self._LibraryAutoGenList == None: + self._GetAutoGenObjectList() + return self._LibraryAutoGenList + + ## Test if a module is supported by the platform + # + # An error will be raised directly if the module or its arch is not supported + # by the platform or current configuration + # + def ValidModule(self, Module): + return Module in self.Platform.Modules or Module in self.Platform.LibraryInstances + + ## Resolve the library classes in a module to library instances + # + # This method will not only resolve library classes but also sort the library + # instances according to the dependency-ship. + # + # @param Module The module from which the library classes will be resolved + # + # @retval library_list List of library instances sorted + # + def ApplyLibraryInstance(self, Module): + ModuleType = Module.ModuleType + + # for overridding library instances with module specific setting + PlatformModule = self.Platform.Modules[str(Module)] + + # add forced library instance + for LibraryClass in PlatformModule.LibraryClasses: + if LibraryClass.startswith("NULL"): + Module.LibraryClasses[LibraryClass] = PlatformModule.LibraryClasses[LibraryClass] + + # R9 module + LibraryConsumerList = [Module] + Constructor = [] + ConsumedByList = sdict() + LibraryInstance = sdict() + + EdkLogger.verbose("") + EdkLogger.verbose("Library instances of module [%s] [%s]:" % (str(Module), self.Arch)) + while len(LibraryConsumerList) > 0: + M = LibraryConsumerList.pop() + for LibraryClassName in M.LibraryClasses: + if LibraryClassName not in LibraryInstance: + # override library instance for this module + if LibraryClassName in PlatformModule.LibraryClasses: + LibraryPath = PlatformModule.LibraryClasses[LibraryClassName] + else: + LibraryPath = self.Platform.LibraryClasses[LibraryClassName, ModuleType] + if LibraryPath == None or LibraryPath == "": + LibraryPath = M.LibraryClasses[LibraryClassName] + if LibraryPath == None or LibraryPath == "": + EdkLogger.error("build", RESOURCE_NOT_AVAILABLE, + "Instance of library class [%s] is not found" % LibraryClassName, + File=self.MetaFile, + ExtraData="in [%s] [%s]\n\tconsumed by module [%s]" % (str(M), self.Arch, str(Module))) + + LibraryModule = self.BuildDatabase[LibraryPath, self.Arch] + # for those forced library instance (NULL library), add a fake library class + if LibraryClassName.startswith("NULL"): + LibraryModule.LibraryClass.append(LibraryClassObject(LibraryClassName, [ModuleType])) + elif LibraryModule.LibraryClass == None \ + or len(LibraryModule.LibraryClass) == 0 \ + or (ModuleType != 'USER_DEFINED' + and ModuleType not in LibraryModule.LibraryClass[0].SupModList): + # only USER_DEFINED can link against any library instance despite of its SupModList + EdkLogger.error("build", OPTION_MISSING, + "Module type [%s] is not supported by library instance [%s]" \ + % (ModuleType, LibraryPath), File=self.MetaFile, + ExtraData="consumed by [%s]" % str(Module)) + + LibraryInstance[LibraryClassName] = LibraryModule + LibraryConsumerList.append(LibraryModule) + EdkLogger.verbose("\t" + str(LibraryClassName) + " : " + str(LibraryModule)) + else: + LibraryModule = LibraryInstance[LibraryClassName] + + if LibraryModule == None: + continue + + if LibraryModule.ConstructorList != [] and LibraryModule not in Constructor: + Constructor.append(LibraryModule) + + if LibraryModule not in ConsumedByList: + ConsumedByList[LibraryModule] = [] + # don't add current module itself to consumer list + if M != Module: + if M in ConsumedByList[LibraryModule]: + continue + ConsumedByList[LibraryModule].append(M) + # + # Initialize the sorted output list to the empty set + # + SortedLibraryList = [] + # + # Q <- Set of all nodes with no incoming edges + # + LibraryList = [] #LibraryInstance.values() + Q = [] + for LibraryClassName in LibraryInstance: + M = LibraryInstance[LibraryClassName] + LibraryList.append(M) + if ConsumedByList[M] == []: + Q.insert(0, M) + + # + # start the DAG algorithm + # + while True: + EdgeRemoved = True + while Q == [] and EdgeRemoved: + EdgeRemoved = False + # for each node Item with a Constructor + for Item in LibraryList: + if Item not in Constructor: + continue + # for each Node without a constructor with an edge e from Item to Node + for Node in ConsumedByList[Item]: + if Node in Constructor: + continue + # remove edge e from the graph if Node has no constructor + ConsumedByList[Item].remove(Node) + EdgeRemoved = True + if ConsumedByList[Item] == []: + # insert Item into Q + Q.insert(0, Item) + break + if Q != []: + break + # DAG is done if there's no more incoming edge for all nodes + if Q == []: + break + + # remove node from Q + Node = Q.pop() + # output Node + SortedLibraryList.append(Node) + + # for each node Item with an edge e from Node to Item do + for Item in LibraryList: + if Node not in ConsumedByList[Item]: + continue + # remove edge e from the graph + ConsumedByList[Item].remove(Node) + + if ConsumedByList[Item] != []: + continue + # insert Item into Q, if Item has no other incoming edges + Q.insert(0, Item) + + # + # if any remaining node Item in the graph has a constructor and an incoming edge, then the graph has a cycle + # + for Item in LibraryList: + if ConsumedByList[Item] != [] and Item in Constructor and len(Constructor) > 1: + ErrorMessage = "\tconsumed by " + "\n\tconsumed by ".join([str(L) for L in ConsumedByList[Item]]) + EdkLogger.error("build", BUILD_ERROR, 'Library [%s] with constructors has a cycle' % str(Item), + ExtraData=ErrorMessage, File=self.MetaFile) + if Item not in SortedLibraryList: + SortedLibraryList.append(Item) + + # + # Build the list of constructor and destructir names + # The DAG Topo sort produces the destructor order, so the list of constructors must generated in the reverse order + # + SortedLibraryList.reverse() + return SortedLibraryList + + + ## Override PCD setting (type, value, ...) + # + # @param ToPcd The PCD to be overrided + # @param FromPcd The PCD overrideing from + # + def _OverridePcd(self, ToPcd, FromPcd, Module=""): + # + # in case there's PCDs coming from FDF file, which have no type given. + # at this point, ToPcd.Type has the type found from dependent + # package + # + if FromPcd != None: + if ToPcd.Pending and FromPcd.Type not in [None, '']: + ToPcd.Type = FromPcd.Type + elif ToPcd.Type not in [None, ''] and FromPcd.Type not in [None, ''] \ + and ToPcd.Type != FromPcd.Type: + EdkLogger.error("build", OPTION_CONFLICT, "Mismatched PCD type", + ExtraData="%s.%s is defined as [%s] in module %s, but as [%s] in platform."\ + % (ToPcd.TokenSpaceGuidCName, ToPcd.TokenCName, + ToPcd.Type, Module, FromPcd.Type), + File=self.MetaFile) + + if FromPcd.MaxDatumSize not in [None, '']: + ToPcd.MaxDatumSize = FromPcd.MaxDatumSize + if FromPcd.DefaultValue not in [None, '']: + ToPcd.DefaultValue = FromPcd.DefaultValue + if FromPcd.TokenValue not in [None, '']: + ToPcd.TokenValue = FromPcd.TokenValue + if FromPcd.MaxDatumSize not in [None, '']: + ToPcd.MaxDatumSize = FromPcd.MaxDatumSize + if FromPcd.DatumType not in [None, '']: + ToPcd.DatumType = FromPcd.DatumType + if FromPcd.SkuInfoList not in [None, '', []]: + ToPcd.SkuInfoList = FromPcd.SkuInfoList + + # check the validation of datum + IsValid, Cause = CheckPcdDatum(ToPcd.DatumType, ToPcd.DefaultValue) + if not IsValid: + EdkLogger.error('build', FORMAT_INVALID, Cause, File=self.MetaFile, + ExtraData="%s.%s" % (ToPcd.TokenSpaceGuidCName, ToPcd.TokenCName)) + + if ToPcd.DatumType == "VOID*" and ToPcd.MaxDatumSize in ['', None]: + EdkLogger.debug(EdkLogger.DEBUG_9, "No MaxDatumSize specified for PCD %s.%s" \ + % (ToPcd.TokenSpaceGuidCName, ToPcd.TokenCName)) + Value = ToPcd.DefaultValue + if Value in [None, '']: + ToPcd.MaxDatumSize = 1 + elif Value[0] == 'L': + ToPcd.MaxDatumSize = str(len(Value) * 2) + elif Value[0] == '{': + ToPcd.MaxDatumSize = str(len(Value.split(','))) + else: + ToPcd.MaxDatumSize = str(len(Value)) + + # apply default SKU for dynamic PCDS if specified one is not available + if (ToPcd.Type in PCD_DYNAMIC_TYPE_LIST or ToPcd.Type in PCD_DYNAMIC_EX_TYPE_LIST) \ + and ToPcd.SkuInfoList in [None, {}, '']: + if self.Platform.SkuName in self.Platform.SkuIds: + SkuName = self.Platform.SkuName + else: + SkuName = 'DEFAULT' + ToPcd.SkuInfoList = { + SkuName : SkuInfoClass(SkuName, self.Platform.SkuIds[SkuName], '', '', '', '', '', ToPcd.DefaultValue) + } + + ## Apply PCD setting defined platform to a module + # + # @param Module The module from which the PCD setting will be overrided + # + # @retval PCD_list The list PCDs with settings from platform + # + def ApplyPcdSetting(self, Module, Pcds): + # for each PCD in module + for Name,Guid in Pcds: + PcdInModule = Pcds[Name,Guid] + # find out the PCD setting in platform + if (Name,Guid) in self.Platform.Pcds: + PcdInPlatform = self.Platform.Pcds[Name,Guid] + else: + PcdInPlatform = None + # then override the settings if any + self._OverridePcd(PcdInModule, PcdInPlatform, Module) + # resolve the VariableGuid value + for SkuId in PcdInModule.SkuInfoList: + Sku = PcdInModule.SkuInfoList[SkuId] + if Sku.VariableGuid == '': continue + Sku.VariableGuidValue = GuidValue(Sku.VariableGuid, self.PackageList) + if Sku.VariableGuidValue == None: + PackageList = "\n\t".join([str(P) for P in self.PackageList]) + EdkLogger.error( + 'build', + RESOURCE_NOT_AVAILABLE, + "Value of GUID [%s] is not found in" % Sku.VariableGuid, + ExtraData=PackageList + "\n\t(used with %s.%s from module %s)" \ + % (Guid, Name, str(Module)), + File=self.MetaFile + ) + + # override PCD settings with module specific setting + if Module in self.Platform.Modules: + PlatformModule = self.Platform.Modules[str(Module)] + for Key in PlatformModule.Pcds: + if Key in Pcds: + self._OverridePcd(Pcds[Key], PlatformModule.Pcds[Key], Module) + return Pcds.values() + + ## Resolve library names to library modules + # + # (for R8.x modules) + # + # @param Module The module from which the library names will be resolved + # + # @retval library_list The list of library modules + # + def ResolveLibraryReference(self, Module): + EdkLogger.verbose("") + EdkLogger.verbose("Library instances of module [%s] [%s]:" % (str(Module), self.Arch)) + LibraryConsumerList = [Module] + + # "CompilerStub" is a must for R8 modules + if Module.Libraries: + Module.Libraries.append("CompilerStub") + LibraryList = [] + while len(LibraryConsumerList) > 0: + M = LibraryConsumerList.pop() + for LibraryName in M.Libraries: + Library = self.Platform.LibraryClasses[LibraryName, ':dummy:'] + if Library == None: + for Key in self.Platform.LibraryClasses.data.keys(): + if LibraryName.upper() == Key.upper(): + Library = self.Platform.LibraryClasses[Key, ':dummy:'] + break + if Library == None: + EdkLogger.warn("build", "Library [%s] is not found" % LibraryName, File=str(M), + ExtraData="\t%s [%s]" % (str(Module), self.Arch)) + continue + + if Library not in LibraryList: + LibraryList.append(Library) + LibraryConsumerList.append(Library) + EdkLogger.verbose("\t" + LibraryName + " : " + str(Library) + ' ' + str(type(Library))) + return LibraryList + + ## Expand * in build option key + # + # @param Options Options to be expanded + # + # @retval options Options expanded + # + def _ExpandBuildOption(self, Options): + BuildOptions = {} + for Key in Options: + Family = Key[0] + Target, Tag, Arch, Tool, Attr = Key[1].split("_") + # if tool chain family doesn't match, skip it + if Family and Tool in self.ToolDefinition and Family != self.ToolDefinition[Tool]["FAMILY"]: + continue + # expand any wildcard + if Target == "*" or Target == self.BuildTarget: + if Tag == "*" or Tag == self.ToolChain: + if Arch == "*" or Arch == self.Arch: + if Tool not in BuildOptions: + BuildOptions[Tool] = {} + if Attr != "FLAGS" or Attr not in BuildOptions[Tool]: + BuildOptions[Tool][Attr] = Options[Key] + else: + # append options for the same tool + BuildOptions[Tool][Attr] += " " + Options[Key] + return BuildOptions + + ## Append build options in platform to a module + # + # @param Module The module to which the build options will be appened + # + # @retval options The options appended with build options in platform + # + def ApplyBuildOption(self, Module): + PlatformOptions = self.BuildOption + ModuleOptions = self._ExpandBuildOption(Module.BuildOptions) + if Module in self.Platform.Modules: + PlatformModule = self.Platform.Modules[str(Module)] + PlatformModuleOptions = self._ExpandBuildOption(PlatformModule.BuildOptions) + else: + PlatformModuleOptions = {} + + AllTools = set(ModuleOptions.keys() + PlatformOptions.keys() + PlatformModuleOptions.keys() + self.ToolDefinition.keys()) + BuildOptions = {} + for Tool in AllTools: + if Tool not in BuildOptions: + BuildOptions[Tool] = {} + + for Options in [self.ToolDefinition, ModuleOptions, PlatformOptions, PlatformModuleOptions]: + if Tool not in Options: + continue + for Attr in Options[Tool]: + Value = Options[Tool][Attr] + if Attr not in BuildOptions[Tool]: + BuildOptions[Tool][Attr] = "" + # check if override is indicated + if Value.startswith('='): + BuildOptions[Tool][Attr] = Value[1:] + else: + BuildOptions[Tool][Attr] += " " + Value + return BuildOptions + + Platform = property(_GetPlatform) + Name = property(_GetName) + Guid = property(_GetGuid) + Version = property(_GetVersion) + + OutputDir = property(_GetOutputDir) + BuildDir = property(_GetBuildDir) + MakeFileDir = property(_GetMakeFileDir) + FdfFile = property(_GetFdfFile) + + PcdTokenNumber = property(_GetPcdTokenNumbers) # (TokenCName, TokenSpaceGuidCName) : GeneratedTokenNumber + DynamicPcdList = property(_GetDynamicPcdList) # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...] + NonDynamicPcdList = property(_GetNonDynamicPcdList) # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...] + PackageList = property(_GetPackageList) + + ToolDefinition = property(_GetToolDefinition) # toolcode : tool path + ToolDefinitionFile = property(_GetToolDefFile) # toolcode : lib path + ToolChainFamily = property(_GetToolChainFamily) + BuildRuleFamily = property(_GetBuildRuleFamily) + BuildOption = property(_GetBuildOptions) # toolcode : option + + BuildCommand = property(_GetBuildCommand) + BuildRule = property(_GetBuildRule) + ModuleAutoGenList = property(_GetModuleAutoGenList) + LibraryAutoGenList = property(_GetLibraryAutoGenList) + +## ModuleAutoGen class +# +# This class encapsules the AutoGen behaviors for the build tools. In addition to +# the generation of AutoGen.h and AutoGen.c, it will generate *.depex file according +# to the [depex] section in module's inf file. +# +class ModuleAutoGen(AutoGen): + ## The real constructor of ModuleAutoGen + # + # This method is not supposed to be called by users of ModuleAutoGen. It's + # only used by factory method __new__() to do real initialization work for an + # object of ModuleAutoGen + # + # @param Workspace EdkIIWorkspaceBuild object + # @param ModuleFile The path of module file + # @param Target Build target (DEBUG, RELEASE) + # @param Toolchain Name of tool chain + # @param Arch The arch the module supports + # @param PlatformFile Platform meta-file + # + def _Init(self, Workspace, ModuleFile, Target, Toolchain, Arch, PlatformFile): + EdkLogger.debug(EdkLogger.DEBUG_9, "AutoGen module [%s] [%s]" % (ModuleFile, Arch)) + GlobalData.gProcessingFile = "%s [%s, %s, %s]" % (ModuleFile, Arch, Toolchain, Target) + + self.Workspace = Workspace + self.WorkspaceDir = Workspace.WorkspaceDir + + self.MetaFile = ModuleFile + self.PlatformInfo = PlatformAutoGen(Workspace, PlatformFile, Target, Toolchain, Arch) + # check if this module is employed by active platform + if not self.PlatformInfo.ValidModule(self.MetaFile): + EdkLogger.verbose("Module [%s] for [%s] is not employed by active platform\n" \ + % (self.MetaFile, Arch)) + return False + + self.SourceDir = self.MetaFile.SubDir + self.SourceOverrideDir = None + # use overrided path defined in DSC file + if self.MetaFile.Key in GlobalData.gOverrideDir: + self.SourceOverrideDir = GlobalData.gOverrideDir[self.MetaFile.Key] + + self.ToolChain = Toolchain + self.BuildTarget = Target + self.Arch = Arch + self.ToolChainFamily = self.PlatformInfo.ToolChainFamily + self.BuildRuleFamily = self.PlatformInfo.BuildRuleFamily + + self.IsMakeFileCreated = False + self.IsCodeFileCreated = False + + self.BuildDatabase = self.Workspace.BuildDatabase + + self._Module = None + self._Name = None + self._Guid = None + self._Version = None + self._ModuleType = None + self._ComponentType = None + self._PcdIsDriver = None + self._AutoGenVersion = None + self._LibraryFlag = None + self._CustomMakefile = None + self._Macro = None + + self._BuildDir = None + self._OutputDir = None + self._DebugDir = None + self._MakeFileDir = None + + self._IncludePathList = None + self._AutoGenFileList = None + self._UnicodeFileList = None + self._SourceFileList = None + self._ObjectFileList = None + self._BinaryFileList = None + + self._DependentPackageList = None + self._DependentLibraryList = None + self._LibraryAutoGenList = None + self._DerivedPackageList = None + self._ModulePcdList = None + self._LibraryPcdList = None + self._GuidList = None + self._ProtocolList = None + self._PpiList = None + self._DepexList = None + self._BuildOption = None + self._BuildTargets = None + self._IntroBuildTargetList = None + self._FinalBuildTargetList = None + self._FileTypes = None + self._BuildRules = None + + return True + + def __repr__(self): + return "%s [%s]" % (self.MetaFile, self.Arch) + + # Macros could be used in build_rule.txt (also Makefile) + def _GetMacros(self): + if self._Macro == None: + self._Macro = sdict() + self._Macro["WORKSPACE" ] = self.WorkspaceDir + self._Macro["MODULE_NAME" ] = self.Name + self._Macro["MODULE_GUID" ] = self.Guid + self._Macro["MODULE_VERSION" ] = self.Version + self._Macro["MODULE_TYPE" ] = self.ModuleType + self._Macro["MODULE_FILE" ] = str(self.MetaFile) + self._Macro["MODULE_FILE_BASE_NAME" ] = self.MetaFile.BaseName + self._Macro["MODULE_RELATIVE_DIR" ] = self.SourceDir + self._Macro["MODULE_DIR" ] = self.SourceDir + + self._Macro["BASE_NAME" ] = self.Name + + self._Macro["ARCH" ] = self.Arch + self._Macro["TOOLCHAIN" ] = self.ToolChain + self._Macro["TOOLCHAIN_TAG" ] = self.ToolChain + self._Macro["TARGET" ] = self.BuildTarget + + self._Macro["BUILD_DIR" ] = self.PlatformInfo.BuildDir + self._Macro["BIN_DIR" ] = os.path.join(self.PlatformInfo.BuildDir, self.Arch) + self._Macro["LIB_DIR" ] = os.path.join(self.PlatformInfo.BuildDir, self.Arch) + self._Macro["MODULE_BUILD_DIR" ] = self.BuildDir + self._Macro["OUTPUT_DIR" ] = self.OutputDir + self._Macro["DEBUG_DIR" ] = self.DebugDir + return self._Macro + + ## Return the module build data object + def _GetModule(self): + if self._Module == None: + self._Module = self.Workspace.BuildDatabase[self.MetaFile, self.Arch] + return self._Module + + ## Return the module name + def _GetBaseName(self): + return self.Module.BaseName + + ## Return the module SourceOverridePath + def _GetSourceOverridePath(self): + return self.Module.SourceOverridePath + + ## Return the module meta-file GUID + def _GetGuid(self): + return self.Module.Guid + + ## Return the module version + def _GetVersion(self): + return self.Module.Version + + ## Return the module type + def _GetModuleType(self): + return self.Module.ModuleType + + ## Return the component type (for R8.x style of module) + def _GetComponentType(self): + return self.Module.ComponentType + + ## Return the build type + def _GetBuildType(self): + return self.Module.BuildType + + ## Return the PCD_IS_DRIVER setting + def _GetPcdIsDriver(self): + return self.Module.PcdIsDriver + + ## Return the autogen version, i.e. module meta-file version + def _GetAutoGenVersion(self): + return self.Module.AutoGenVersion + + ## Check if the module is library or not + def _IsLibrary(self): + if self._LibraryFlag == None: + if self.Module.LibraryClass != None and self.Module.LibraryClass != []: + self._LibraryFlag = True + else: + self._LibraryFlag = False + return self._LibraryFlag + + ## Return the directory to store intermediate files of the module + def _GetBuildDir(self): + if self._BuildDir == None: + self._BuildDir = path.join( + self.PlatformInfo.BuildDir, + self.Arch, + self.SourceDir, + self.MetaFile.BaseName + ) + CreateDirectory(self._BuildDir) + return self._BuildDir + + ## Return the directory to store the intermediate object files of the mdoule + def _GetOutputDir(self): + if self._OutputDir == None: + self._OutputDir = path.join(self.BuildDir, "OUTPUT") + CreateDirectory(self._OutputDir) + return self._OutputDir + + ## Return the directory to store auto-gened source files of the mdoule + def _GetDebugDir(self): + if self._DebugDir == None: + self._DebugDir = path.join(self.BuildDir, "DEBUG") + CreateDirectory(self._DebugDir) + return self._DebugDir + + ## Return the path of custom file + def _GetCustomMakefile(self): + if self._CustomMakefile == None: + self._CustomMakefile = {} + for Type in self.Module.CustomMakefile: + if Type in gMakeTypeMap: + MakeType = gMakeTypeMap[Type] + else: + MakeType = 'nmake' + if self.SourceOverrideDir != None: + File = os.path.join(self.SourceOverrideDir, self.Module.CustomMakefile[Type]) + if not os.path.exists(File): + File = os.path.join(self.SourceDir, self.Module.CustomMakefile[Type]) + else: + File = os.path.join(self.SourceDir, self.Module.CustomMakefile[Type]) + self._CustomMakefile[MakeType] = File + return self._CustomMakefile + + ## Return the directory of the makefile + # + # @retval string The directory string of module's makefile + # + def _GetMakeFileDir(self): + return self.BuildDir + + ## Return build command string + # + # @retval string Build command string + # + def _GetBuildCommand(self): + return self.PlatformInfo.BuildCommand + + ## Get object list of all packages the module and its dependent libraries belong to + # + # @retval list The list of package object + # + def _GetDerivedPackageList(self): + PackageList = [] + for M in [self.Module] + self.DependentLibraryList: + for Package in M.Packages: + if Package in PackageList: + continue + PackageList.append(Package) + return PackageList + + ## Merge dependency expression + # + # @retval list The token list of the dependency expression after parsed + # + def _GetDepexTokenList(self): + if self._DepexList == None: + self._DepexList = {} + if self.IsLibrary or TAB_DEPENDENCY_EXPRESSION_FILE in self.FileTypes: + return self._DepexList + + if self.ModuleType == "DXE_SMM_DRIVER": + self._DepexList["DXE_DRIVER"] = [] + self._DepexList["SMM_DRIVER"] = [] + else: + self._DepexList[self.ModuleType] = [] + + for ModuleType in self._DepexList: + DepexList = self._DepexList[ModuleType] + # + # Append depex from dependent libraries, if not "BEFORE", "AFTER" expresion + # + for M in [self.Module] + self.DependentLibraryList: + Inherited = False + for D in M.Depex[self.Arch, ModuleType]: + if DepexList != []: + DepexList.append('AND') + DepexList.append('(') + DepexList.extend(D) + if DepexList[-1] == 'END': # no need of a END at this time + DepexList.pop() + DepexList.append(')') + Inherited = True + if Inherited: + EdkLogger.verbose("DEPEX[%s] (+%s) = %s" % (self.Name, M.BaseName, DepexList)) + if 'BEFORE' in DepexList or 'AFTER' in DepexList: + break + if len(DepexList) > 0: + EdkLogger.verbose('') + return self._DepexList + + ## Return the list of specification version required for the module + # + # @retval list The list of specification defined in module file + # + def _GetSpecification(self): + return self.Module.Specification + + ## Tool option for the module build + # + # @param PlatformInfo The object of PlatformBuildInfo + # @retval dict The dict containing valid options + # + def _GetModuleBuildOption(self): + if self._BuildOption == None: + self._BuildOption = self.PlatformInfo.ApplyBuildOption(self.Module) + return self._BuildOption + + ## Return a list of files which can be built from source + # + # What kind of files can be built is determined by build rules in + # $(WORKSPACE)/Conf/build_rule.txt and toolchain family. + # + def _GetSourceFileList(self): + if self._SourceFileList == None: + self._SourceFileList = [] + for F in self.Module.Sources: + # match tool chain + if F.TagName != "" and F.TagName != self.ToolChain: + EdkLogger.debug(EdkLogger.DEBUG_9, "The toolchain [%s] for processing file [%s] is found, " + "but [%s] is needed" % (F.TagName, str(F), self.ToolChain)) + continue + # match tool chain family + if F.ToolChainFamily != "" and F.ToolChainFamily != self.ToolChainFamily: + EdkLogger.debug( + EdkLogger.DEBUG_0, + "The file [%s] must be built by tools of [%s], " \ + "but current toolchain family is [%s]" \ + % (str(F), F.ToolChainFamily, self.ToolChainFamily)) + continue + + # add the file path into search path list for file including + if F.Dir not in self.IncludePathList and self.AutoGenVersion >= 0x00010005: + self.IncludePathList.insert(0, F.Dir) + self._SourceFileList.append(F) + self._ApplyBuildRule(F, TAB_UNKNOWN_FILE) + return self._SourceFileList + + ## Return the list of unicode files + def _GetUnicodeFileList(self): + if self._UnicodeFileList == None: + if TAB_UNICODE_FILE in self.FileTypes: + self._UnicodeFileList = self.FileTypes[TAB_UNICODE_FILE] + else: + self._UnicodeFileList = [] + return self._UnicodeFileList + + ## Return a list of files which can be built from binary + # + # "Build" binary files are just to copy them to build directory. + # + # @retval list The list of files which can be built later + # + def _GetBinaryFiles(self): + if self._BinaryFileList == None: + self._BinaryFileList = [] + for F in self.Module.Binaries: + if F.Target not in ['COMMON', '*'] and F.Target != self.BuildTarget: + continue + self._BinaryFileList.append(F) + self._ApplyBuildRule(F, F.Type) + return self._BinaryFileList + + def _GetBuildRules(self): + if self._BuildRules == None: + BuildRules = {} + BuildRuleDatabase = self.PlatformInfo.BuildRule + for Type in BuildRuleDatabase.FileTypeList: + #first try getting build rule by BuildRuleFamily + RuleObject = BuildRuleDatabase[Type, self.BuildType, self.Arch, self.BuildRuleFamily] + if not RuleObject: + # build type is always module type, but ... + if self.ModuleType != self.BuildType: + RuleObject = BuildRuleDatabase[Type, self.ModuleType, self.Arch, self.BuildRuleFamily] + #second try getting build rule by ToolChainFamily + if not RuleObject: + RuleObject = BuildRuleDatabase[Type, self.BuildType, self.Arch, self.ToolChainFamily] + if not RuleObject: + # build type is always module type, but ... + if self.ModuleType != self.BuildType: + RuleObject = BuildRuleDatabase[Type, self.ModuleType, self.Arch, self.ToolChainFamily] + if not RuleObject: + continue + RuleObject = RuleObject.Instantiate(self.Macros) + BuildRules[Type] = RuleObject + for Ext in RuleObject.SourceFileExtList: + BuildRules[Ext] = RuleObject + self._BuildRules = BuildRules + return self._BuildRules + + def _ApplyBuildRule(self, File, FileType): + if self._BuildTargets == None: + self._IntroBuildTargetList = set() + self._FinalBuildTargetList = set() + self._BuildTargets = {} + self._FileTypes = {} + + LastTarget = None + RuleChain = [] + SourceList = [File] + Index = 0 + while Index < len(SourceList): + Source = SourceList[Index] + Index = Index + 1 + + if Source != File: + CreateDirectory(Source.Dir) + + if FileType in self.BuildRules: + RuleObject = self.BuildRules[FileType] + elif Source.Ext in self.BuildRules: + RuleObject = self.BuildRules[Source.Ext] + elif File.IsBinary and File == Source: + RuleObject = self.BuildRules[TAB_DEFAULT_BINARY_FILE] + else: + # stop at no more rules + if LastTarget: + self._FinalBuildTargetList.add(LastTarget) + break + + FileType = RuleObject.SourceFileType + if FileType not in self._FileTypes: + self._FileTypes[FileType] = set() + self._FileTypes[FileType].add(Source) + + # stop at STATIC_LIBRARY for library + if self.IsLibrary and FileType == TAB_STATIC_LIBRARY: + self._FinalBuildTargetList.add(LastTarget) + break + + Target = RuleObject.Apply(Source) + if not Target: + if LastTarget: + self._FinalBuildTargetList.add(LastTarget) + break + elif not Target.Outputs: + # Only do build for target with outputs + self._FinalBuildTargetList.add(Target) + + if FileType not in self._BuildTargets: + self._BuildTargets[FileType] = set() + self._BuildTargets[FileType].add(Target) + + if not Source.IsBinary and Source == File: + self._IntroBuildTargetList.add(Target) + + # to avoid cyclic rule + if FileType in RuleChain: + break + + RuleChain.append(FileType) + SourceList.extend(Target.Outputs) + LastTarget = Target + FileType = TAB_UNKNOWN_FILE + + def _GetTargets(self): + if self._BuildTargets == None: + self._IntroBuildTargetList = set() + self._FinalBuildTargetList = set() + self._BuildTargets = {} + self._FileTypes = {} + + #TRICK: call _GetSourceFileList to apply build rule for binary files + if self.SourceFileList: + pass + + #TRICK: call _GetBinaryFileList to apply build rule for binary files + if self.BinaryFileList: + pass + + return self._BuildTargets + + def _GetIntroTargetList(self): + self._GetTargets() + return self._IntroBuildTargetList + + def _GetFinalTargetList(self): + self._GetTargets() + return self._FinalBuildTargetList + + def _GetFileTypes(self): + self._GetTargets() + return self._FileTypes + + ## Get the list of package object the module depends on + # + # @retval list The package object list + # + def _GetDependentPackageList(self): + return self.Module.Packages + + ## Return the list of auto-generated code file + # + # @retval list The list of auto-generated file + # + def _GetAutoGenFileList(self): + if self._AutoGenFileList == None: + self._AutoGenFileList = {} + AutoGenC = TemplateString() + AutoGenH = TemplateString() + StringH = TemplateString() + GenC.CreateCode(self, AutoGenC, AutoGenH, StringH) + if str(AutoGenC) != "" and TAB_C_CODE_FILE in self.FileTypes: + AutoFile = PathClass(gAutoGenCodeFileName, self.DebugDir) + self._AutoGenFileList[AutoFile] = str(AutoGenC) + self._ApplyBuildRule(AutoFile, TAB_UNKNOWN_FILE) + if str(AutoGenH) != "": + AutoFile = PathClass(gAutoGenHeaderFileName, self.DebugDir) + self._AutoGenFileList[AutoFile] = str(AutoGenH) + self._ApplyBuildRule(AutoFile, TAB_UNKNOWN_FILE) + if str(StringH) != "": + AutoFile = PathClass(gAutoGenStringFileName % {"module_name":self.Name}, self.DebugDir) + self._AutoGenFileList[AutoFile] = str(StringH) + self._ApplyBuildRule(AutoFile, TAB_UNKNOWN_FILE) + return self._AutoGenFileList + + ## Return the list of library modules explicitly or implicityly used by this module + def _GetLibraryList(self): + if self._DependentLibraryList == None: + # only merge library classes and PCD for non-library module + if self.IsLibrary: + self._DependentLibraryList = [] + else: + if self.AutoGenVersion < 0x00010005: + self._DependentLibraryList = self.PlatformInfo.ResolveLibraryReference(self.Module) + else: + self._DependentLibraryList = self.PlatformInfo.ApplyLibraryInstance(self.Module) + return self._DependentLibraryList + + ## Get the list of PCDs from current module + # + # @retval list The list of PCD + # + def _GetModulePcdList(self): + if self._ModulePcdList == None: + # apply PCD settings from platform + self._ModulePcdList = self.PlatformInfo.ApplyPcdSetting(self.Module, self.Module.Pcds) + return self._ModulePcdList + + ## Get the list of PCDs from dependent libraries + # + # @retval list The list of PCD + # + def _GetLibraryPcdList(self): + if self._LibraryPcdList == None: + Pcds = {} + if not self.IsLibrary: + # get PCDs from dependent libraries + for Library in self.DependentLibraryList: + for Key in Library.Pcds: + # skip duplicated PCDs + if Key in self.Module.Pcds or Key in Pcds: + continue + Pcds[Key] = copy.copy(Library.Pcds[Key]) + # apply PCD settings from platform + self._LibraryPcdList = self.PlatformInfo.ApplyPcdSetting(self.Module, Pcds) + else: + self._LibraryPcdList = [] + return self._LibraryPcdList + + ## Get the GUID value mapping + # + # @retval dict The mapping between GUID cname and its value + # + def _GetGuidList(self): + if self._GuidList == None: + self._GuidList = self.Module.Guids + for Library in self.DependentLibraryList: + self._GuidList.update(Library.Guids) + return self._GuidList + + ## Get the protocol value mapping + # + # @retval dict The mapping between protocol cname and its value + # + def _GetProtocolList(self): + if self._ProtocolList == None: + self._ProtocolList = self.Module.Protocols + for Library in self.DependentLibraryList: + self._ProtocolList.update(Library.Protocols) + return self._ProtocolList + + ## Get the PPI value mapping + # + # @retval dict The mapping between PPI cname and its value + # + def _GetPpiList(self): + if self._PpiList == None: + self._PpiList = self.Module.Ppis + for Library in self.DependentLibraryList: + self._PpiList.update(Library.Ppis) + return self._PpiList + + ## Get the list of include search path + # + # @retval list The list path + # + def _GetIncludePathList(self): + if self._IncludePathList == None: + self._IncludePathList = [] + if self.AutoGenVersion < 0x00010005: + for Inc in self.Module.Includes: + if Inc not in self._IncludePathList: + self._IncludePathList.append(Inc) + # for r8 modules + Inc = path.join(Inc, self.Arch.capitalize()) + if os.path.exists(Inc) and Inc not in self._IncludePathList: + self._IncludePathList.append(Inc) + # r8 module needs to put DEBUG_DIR at the end of search path and not to use SOURCE_DIR all the time + self._IncludePathList.append(self.DebugDir) + else: + self._IncludePathList.append(self.MetaFile.Dir) + self._IncludePathList.append(self.DebugDir) + + for Package in self.Module.Packages: + PackageDir = path.join(self.WorkspaceDir, Package.MetaFile.Dir) + if PackageDir not in self._IncludePathList: + self._IncludePathList.append(PackageDir) + for Inc in Package.Includes: + if Inc not in self._IncludePathList: + self._IncludePathList.append(str(Inc)) + return self._IncludePathList + + ## Create makefile for the module and its dependent libraries + # + # @param CreateLibraryMakeFile Flag indicating if or not the makefiles of + # dependent libraries will be created + # + def CreateMakeFile(self, CreateLibraryMakeFile=True): + if self.IsMakeFileCreated: + return + + if not self.IsLibrary and CreateLibraryMakeFile: + for LibraryAutoGen in self.LibraryAutoGenList: + LibraryAutoGen.CreateMakeFile() + + if len(self.CustomMakefile) == 0: + Makefile = GenMake.ModuleMakefile(self) + else: + Makefile = GenMake.CustomMakefile(self) + if Makefile.Generate(): + EdkLogger.debug(EdkLogger.DEBUG_9, "Generated makefile for module %s [%s]" % + (self.Name, self.Arch)) + else: + EdkLogger.debug(EdkLogger.DEBUG_9, "Skipped the generation of makefile for module %s [%s]" % + (self.Name, self.Arch)) + + self.IsMakeFileCreated = True + + ## Create autogen code for the module and its dependent libraries + # + # @param CreateLibraryCodeFile Flag indicating if or not the code of + # dependent libraries will be created + # + def CreateCodeFile(self, CreateLibraryCodeFile=True): + if self.IsCodeFileCreated: + return + + if not self.IsLibrary and CreateLibraryCodeFile: + for LibraryAutoGen in self.LibraryAutoGenList: + LibraryAutoGen.CreateCodeFile() + + AutoGenList = [] + IgoredAutoGenList = [] + + for File in self.AutoGenFileList: + if GenC.Generate(File.Path, self.AutoGenFileList[File]): + #Ignore R8 AutoGen.c + if self.AutoGenVersion < 0x00010005 and File.Name == 'AutoGen.c': + continue + + AutoGenList.append(str(File)) + else: + IgoredAutoGenList.append(str(File)) + + for ModuleType in self.DepexList: + if len(self.DepexList[ModuleType]) == 0: + continue + Dpx = GenDepex.DependencyExpression(self.DepexList[ModuleType], ModuleType, True) + if ModuleType == 'SMM_DRIVER': + DpxFile = gAutoGenSmmDepexFileName % {"module_name" : self.Name} + else: + DpxFile = gAutoGenDepexFileName % {"module_name" : self.Name} + + if Dpx.Generate(path.join(self.OutputDir, DpxFile)): + AutoGenList.append(str(DpxFile)) + else: + IgoredAutoGenList.append(str(DpxFile)) + + if IgoredAutoGenList == []: + EdkLogger.debug(EdkLogger.DEBUG_9, "Generated [%s] files for module %s [%s]" % + (" ".join(AutoGenList), self.Name, self.Arch)) + elif AutoGenList == []: + EdkLogger.debug(EdkLogger.DEBUG_9, "Skipped the generation of [%s] files for module %s [%s]" % + (" ".join(IgoredAutoGenList), self.Name, self.Arch)) + else: + EdkLogger.debug(EdkLogger.DEBUG_9, "Generated [%s] (skipped %s) files for module %s [%s]" % + (" ".join(AutoGenList), " ".join(IgoredAutoGenList), self.Name, self.Arch)) + + self.IsCodeFileCreated = True + return AutoGenList + + ## Summarize the ModuleAutoGen objects of all libraries used by this module + def _GetLibraryAutoGenList(self): + if self._LibraryAutoGenList == None: + self._LibraryAutoGenList = [] + for Library in self.DependentLibraryList: + La = ModuleAutoGen( + self.Workspace, + Library.MetaFile, + self.BuildTarget, + self.ToolChain, + self.Arch, + self.PlatformInfo.MetaFile + ) + if La not in self._LibraryAutoGenList: + self._LibraryAutoGenList.append(La) + for Lib in La.CodaTargetList: + self._ApplyBuildRule(Lib.Target, TAB_UNKNOWN_FILE) + return self._LibraryAutoGenList + + ## Return build command string + # + # @retval string Build command string + # + def _GetBuildCommand(self): + return self.PlatformInfo.BuildCommand + + + Module = property(_GetModule) + Name = property(_GetBaseName) + Guid = property(_GetGuid) + Version = property(_GetVersion) + ModuleType = property(_GetModuleType) + ComponentType = property(_GetComponentType) + BuildType = property(_GetBuildType) + PcdIsDriver = property(_GetPcdIsDriver) + AutoGenVersion = property(_GetAutoGenVersion) + Macros = property(_GetMacros) + Specification = property(_GetSpecification) + + IsLibrary = property(_IsLibrary) + + BuildDir = property(_GetBuildDir) + OutputDir = property(_GetOutputDir) + DebugDir = property(_GetDebugDir) + MakeFileDir = property(_GetMakeFileDir) + CustomMakefile = property(_GetCustomMakefile) + + IncludePathList = property(_GetIncludePathList) + AutoGenFileList = property(_GetAutoGenFileList) + UnicodeFileList = property(_GetUnicodeFileList) + SourceFileList = property(_GetSourceFileList) + BinaryFileList = property(_GetBinaryFiles) # FileType : [File List] + Targets = property(_GetTargets) + IntroTargetList = property(_GetIntroTargetList) + CodaTargetList = property(_GetFinalTargetList) + FileTypes = property(_GetFileTypes) + BuildRules = property(_GetBuildRules) + + DependentPackageList = property(_GetDependentPackageList) + DependentLibraryList = property(_GetLibraryList) + LibraryAutoGenList = property(_GetLibraryAutoGenList) + DerivedPackageList = property(_GetDerivedPackageList) + + ModulePcdList = property(_GetModulePcdList) + LibraryPcdList = property(_GetLibraryPcdList) + GuidList = property(_GetGuidList) + ProtocolList = property(_GetProtocolList) + PpiList = property(_GetPpiList) + DepexList = property(_GetDepexTokenList) + BuildOption = property(_GetModuleBuildOption) + BuildCommand = property(_GetBuildCommand) + +# This acts like the main() function for the script, unless it is 'import'ed into another script. +if __name__ == '__main__': + pass + diff --git a/BaseTools/Source/Python/AutoGen/BuildEngine.py b/BaseTools/Source/Python/AutoGen/BuildEngine.py new file mode 100644 index 0000000000..cbe7d60f3f --- /dev/null +++ b/BaseTools/Source/Python/AutoGen/BuildEngine.py @@ -0,0 +1,622 @@ +## @file +# The engine for building files +# +# Copyright (c) 2007, 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. +# + +## +# Import Modules +# +import os +import re +import copy +import string + +from Common.GlobalData import * +from Common.BuildToolError import * +from Common.Misc import tdict, PathClass +from Common.String import NormPath +from Common.DataType import * + +import Common.EdkLogger as EdkLogger + +## Convert file type to file list macro name +# +# @param FileType The name of file type +# +# @retval string The name of macro +# +def FileListMacro(FileType): + return "%sS" % FileType.replace("-", "_").upper() + +## Convert file type to list file macro name +# +# @param FileType The name of file type +# +# @retval string The name of macro +# +def ListFileMacro(FileType): + return "%s_LIST" % FileListMacro(FileType) + +class TargetDescBlock(object): + _Cache_ = {} # {TargetFile : TargetDescBlock object} + + # Factory method + def __new__(Class, Inputs, Outputs, Commands, Dependencies): + if Outputs[0] in Class._Cache_: + Tdb = Class._Cache_[Outputs[0]] + for File in Inputs: + Tdb.AddInput(File) + else: + Tdb = super(TargetDescBlock, Class).__new__(Class) + Tdb._Init(Inputs, Outputs, Commands, Dependencies) + #Class._Cache_[Outputs[0]] = Tdb + return Tdb + + def _Init(self, Inputs, Outputs, Commands, Dependencies): + self.Inputs = Inputs + self.Outputs = Outputs + self.Commands = Commands + self.Dependencies = Dependencies + if self.Outputs: + self.Target = self.Outputs[0] + else: + self.Target = None + + def __str__(self): + return self.Target.Path + + def __hash__(self): + return hash(self.Target.Path) + + def __eq__(self, Other): + if type(Other) == type(self): + return Other.Target.Path == self.Target.Path + else: + return str(Other) == self.Target.Path + + def AddInput(self, Input): + if Input not in self.Inputs: + self.Inputs.append(Input) + + def IsMultipleInput(self): + return len(self.Inputs) > 1 + + @staticmethod + def Renew(): + TargetDescBlock._Cache_ = {} + +## Class for one build rule +# +# This represents a build rule which can give out corresponding command list for +# building the given source file(s). The result can be used for generating the +# target for makefile. +# +class FileBuildRule: + INC_LIST_MACRO = "INC_LIST" + INC_MACRO = "INC" + + ## constructor + # + # @param Input The dictionary represeting input file(s) for a rule + # @param Output The list represeting output file(s) for a rule + # @param Command The list containing commands to generate the output from input + # + def __init__(self, Type, Input, Output, Command, ExtraDependency=None): + # The Input should not be empty + if not Input: + Input = [] + if not Output: + Output = [] + if not Command: + Command = [] + + self.FileListMacro = FileListMacro(Type) + self.ListFileMacro = ListFileMacro(Type) + self.IncListFileMacro = self.INC_LIST_MACRO + + self.SourceFileType = Type + # source files listed not in "*" or "?" pattern format + if not ExtraDependency: + self.ExtraSourceFileList = [] + else: + self.ExtraSourceFileList = ExtraDependency + + # + # Search macros used in command lines for _LIST and INC_LIST. + # If found, generate a file to keep the input files used to get over the + # limitation of command line length + # + self.MacroList = [] + self.CommandList = [] + for CmdLine in Command: + self.MacroList.extend(gMacroPattern.findall(CmdLine)) + # replace path separator with native one + self.CommandList.append(CmdLine) + + # Indicate what should be generated + if self.FileListMacro in self.MacroList: + self.GenFileListMacro = True + else: + self.GenFileListMacro = False + + if self.ListFileMacro in self.MacroList: + self.GenListFile = True + self.GenFileListMacro = True + else: + self.GenListFile = False + + if self.INC_LIST_MACRO in self.MacroList: + self.GenIncListFile = True + else: + self.GenIncListFile = False + + # Check input files + self.IsMultipleInput = False + self.SourceFileExtList = [] + for File in Input: + Base, Ext = os.path.splitext(File) + if Base.find("*") >= 0: + # There's "*" in the file name + self.IsMultipleInput = True + self.GenFileListMacro = True + elif Base.find("?") < 0: + # There's no "*" and "?" in file name + self.ExtraSourceFileList.append(File) + continue + if Ext not in self.SourceFileExtList: + self.SourceFileExtList.append(Ext) + + # Check output files + self.DestFileList = [] + for File in Output: + self.DestFileList.append(File) + + # All build targets generated by this rule for a module + self.BuildTargets = {} + + ## str() function support + # + # @retval string + # + def __str__(self): + SourceString = "" + SourceString += " %s %s %s" % (self.SourceFileType, " ".join(self.SourceFileExtList), self.ExtraSourceFileList) + DestString = ", ".join(self.DestFileList) + CommandString = "\n\t".join(self.CommandList) + return "%s : %s\n\t%s" % (DestString, SourceString, CommandString) + + ## Check if given file extension is supported by this rule + # + # @param FileExt The extension of a file + # + # @retval True If the extension is supported + # @retval False If the extension is not supported + # + def IsSupported(self, FileExt): + return FileExt in self.SourceFileExtList + + def Instantiate(self, Macros={}): + NewRuleObject = copy.copy(self) + NewRuleObject.BuildTargets = {} + NewRuleObject.DestFileList = [] + for File in self.DestFileList: + NewRuleObject.DestFileList.append(PathClass(NormPath(File, Macros))) + return NewRuleObject + + ## Apply the rule to given source file(s) + # + # @param SourceFile One file or a list of files to be built + # @param RelativeToDir The relative path of the source file + # @param PathSeparator Path separator + # + # @retval tuple (Source file in full path, List of individual sourcefiles, Destionation file, List of build commands) + # + def Apply(self, SourceFile): + if not self.CommandList or not self.DestFileList: + return None + + # source file + if self.IsMultipleInput: + SrcFileName = "" + SrcFileBase = "" + SrcFileExt = "" + SrcFileDir = "" + SrcPath = "" + # SourceFile must be a list + SrcFile = "$(%s)" % self.FileListMacro + else: + SrcFileName, SrcFileBase, SrcFileExt = SourceFile.Name, SourceFile.BaseName, SourceFile.Ext + if SourceFile.Root: + SrcFileDir = SourceFile.SubDir + if SrcFileDir == "": + SrcFileDir = "." + else: + SrcFileDir = "." + SrcFile = SourceFile.Path + SrcPath = SourceFile.Dir + + # destination file (the first one) + if self.DestFileList: + DestFile = self.DestFileList[0].Path + DestPath = self.DestFileList[0].Dir + DestFileName = self.DestFileList[0].Name + DestFileBase, DestFileExt = self.DestFileList[0].BaseName, self.DestFileList[0].Ext + else: + DestFile = "" + DestPath = "" + DestFileName = "" + DestFileBase = "" + DestFileExt = "" + + BuildRulePlaceholderDict = { + # source file + "src" : SrcFile, + "s_path" : SrcPath, + "s_dir" : SrcFileDir, + "s_name" : SrcFileName, + "s_base" : SrcFileBase, + "s_ext" : SrcFileExt, + # destination file + "dst" : DestFile, + "d_path" : DestPath, + "d_name" : DestFileName, + "d_base" : DestFileBase, + "d_ext" : DestFileExt, + } + + DstFile = [] + for File in self.DestFileList: + File = string.Template(str(File)).safe_substitute(BuildRulePlaceholderDict) + File = string.Template(str(File)).safe_substitute(BuildRulePlaceholderDict) + DstFile.append(PathClass(File, IsBinary=True)) + + if DstFile[0] in self.BuildTargets: + TargetDesc = self.BuildTargets[DstFile[0]] + TargetDesc.AddInput(SourceFile) + else: + CommandList = [] + for CommandString in self.CommandList: + CommandString = string.Template(CommandString).safe_substitute(BuildRulePlaceholderDict) + CommandString = string.Template(CommandString).safe_substitute(BuildRulePlaceholderDict) + CommandList.append(CommandString) + TargetDesc = TargetDescBlock([SourceFile], DstFile, CommandList, self.ExtraSourceFileList) + TargetDesc.ListFileMacro = self.ListFileMacro + TargetDesc.FileListMacro = self.FileListMacro + TargetDesc.IncListFileMacro = self.IncListFileMacro + TargetDesc.GenFileListMacro = self.GenFileListMacro + TargetDesc.GenListFile = self.GenListFile + TargetDesc.GenIncListFile = self.GenIncListFile + self.BuildTargets[DstFile[0]] = TargetDesc + return TargetDesc + +## Class for build rules +# +# BuildRule class parses rules defined in a file or passed by caller, and converts +# the rule into FileBuildRule object. +# +class BuildRule: + _SectionHeader = "SECTIONHEADER" + _Section = "SECTION" + _SubSectionHeader = "SUBSECTIONHEADER" + _SubSection = "SUBSECTION" + _InputFile = "INPUTFILE" + _OutputFile = "OUTPUTFILE" + _ExtraDependency = "EXTRADEPENDENCY" + _Command = "COMMAND" + _UnknownSection = "UNKNOWNSECTION" + + _SubSectionList = [_InputFile, _OutputFile, _Command] + + _PATH_SEP = "(+)" + _FileTypePattern = re.compile("^[_a-zA-Z][_\-0-9a-zA-Z]*$") + _BinaryFileRule = FileBuildRule(TAB_DEFAULT_BINARY_FILE, [], [os.path.join("$(OUTPUT_DIR)", "${s_name}")], + ["$(CP) ${src} ${dst}"], []) + + ## Constructor + # + # @param File The file containing build rules in a well defined format + # @param Content The string list of build rules in a well defined format + # @param LineIndex The line number from which the parsing will begin + # @param SupportedFamily The list of supported tool chain families + # + def __init__(self, File=None, Content=None, LineIndex=0, SupportedFamily=["MSFT", "INTEL", "GCC", "RVCT"]): + self.RuleFile = File + # Read build rules from file if it's not none + if File != None: + try: + self.RuleContent = open(File, 'r').readlines() + except: + EdkLogger.error("build", FILE_OPEN_FAILURE, ExtraData=File) + elif Content != None: + self.RuleContent = Content + else: + EdkLogger.error("build", PARAMETER_MISSING, ExtraData="No rule file or string given") + + self.SupportedToolChainFamilyList = SupportedFamily + self.RuleDatabase = tdict(True, 4) # {FileExt, ModuleType, Arch, Family : FileBuildRule object} + self.Ext2FileType = {} # {ext : file-type} + self.FileTypeList = set() + + self._LineIndex = LineIndex + self._State = "" + self._RuleInfo = tdict(True, 2) # {toolchain family : {"InputFile": {}, "OutputFile" : [], "Command" : []}} + self._FileType = '' + self._BuildTypeList = [] + self._ArchList = [] + self._FamilyList = [] + self._TotalToolChainFamilySet = set() + self._RuleObjectList = [] # FileBuildRule object list + + self.Parse() + + # some intrinsic rules + self.RuleDatabase[TAB_DEFAULT_BINARY_FILE, "COMMON", "COMMON", "COMMON"] = self._BinaryFileRule + self.FileTypeList.add(TAB_DEFAULT_BINARY_FILE) + + ## Parse the build rule strings + def Parse(self): + self._State = self._Section + for Index in range(self._LineIndex, len(self.RuleContent)): + # Clean up the line and replace path separator with native one + Line = self.RuleContent[Index].strip().replace(self._PATH_SEP, os.path.sep) + self.RuleContent[Index] = Line + + # skip empty or comment line + if Line == "" or Line[0] == "#": + continue + + # find out section header, enclosed by [] + if Line[0] == '[' and Line[-1] == ']': + # merge last section information into rule database + self.EndOfSection() + self._State = self._SectionHeader + # find out sub-section header, enclosed by <> + elif Line[0] == '<' and Line[-1] == '>': + if self._State != self._UnknownSection: + self._State = self._SubSectionHeader + + # call section handler to parse each (sub)section + self._StateHandler[self._State](self, Index) + # merge last section information into rule database + self.EndOfSection() + + ## Parse definitions under a section + # + # @param LineIndex The line index of build rule text + # + def ParseSection(self, LineIndex): + pass + + ## Parse definitions under a subsection + # + # @param LineIndex The line index of build rule text + # + def ParseSubSection(self, LineIndex): + # currenly nothing here + pass + + ## Placeholder for not supported sections + # + # @param LineIndex The line index of build rule text + # + def SkipSection(self, LineIndex): + pass + + ## Merge section information just got into rule database + def EndOfSection(self): + Database = self.RuleDatabase + # if there's specific toochain family, 'COMMON' doesn't make sense any more + if len(self._TotalToolChainFamilySet) > 1 and 'COMMON' in self._TotalToolChainFamilySet: + self._TotalToolChainFamilySet.remove('COMMON') + for Family in self._TotalToolChainFamilySet: + Input = self._RuleInfo[Family, self._InputFile] + Output = self._RuleInfo[Family, self._OutputFile] + Command = self._RuleInfo[Family, self._Command] + ExtraDependency = self._RuleInfo[Family, self._ExtraDependency] + + BuildRule = FileBuildRule(self._FileType, Input, Output, Command, ExtraDependency) + for BuildType in self._BuildTypeList: + for Arch in self._ArchList: + Database[self._FileType, BuildType, Arch, Family] = BuildRule + for FileExt in BuildRule.SourceFileExtList: + self.Ext2FileType[FileExt] = self._FileType + + ## Parse section header + # + # @param LineIndex The line index of build rule text + # + def ParseSectionHeader(self, LineIndex): + self._RuleInfo = tdict(True, 2) + self._BuildTypeList = [] + self._ArchList = [] + self._FamilyList = [] + self._TotalToolChainFamilySet = set() + FileType = '' + RuleNameList = self.RuleContent[LineIndex][1:-1].split(',') + for RuleName in RuleNameList: + Arch = 'COMMON' + BuildType = 'COMMON' + TokenList = [Token.strip().upper() for Token in RuleName.split('.')] + # old format: Build.File-Type + if TokenList[0] == "BUILD": + if len(TokenList) == 1: + EdkLogger.error("build", FORMAT_INVALID, "Invalid rule section", + File=self.RuleFile, Line=LineIndex+1, + ExtraData=self.RuleContent[LineIndex]) + + FileType = TokenList[1] + if FileType == '': + EdkLogger.error("build", FORMAT_INVALID, "No file type given", + File=self.RuleFile, Line=LineIndex+1, + ExtraData=self.RuleContent[LineIndex]) + if self._FileTypePattern.match(FileType) == None: + EdkLogger.error("build", FORMAT_INVALID, File=self.RuleFile, Line=LineIndex+1, + ExtraData="Only character, number (non-first character), '_' and '-' are allowed in file type") + # new format: File-Type.Build-Type.Arch + else: + if FileType == '': + FileType = TokenList[0] + elif FileType != TokenList[0]: + EdkLogger.error("build", FORMAT_INVALID, + "Different file types are not allowed in the same rule section", + File=self.RuleFile, Line=LineIndex+1, + ExtraData=self.RuleContent[LineIndex]) + if len(TokenList) > 1: + BuildType = TokenList[1] + if len(TokenList) > 2: + Arch = TokenList[2] + if BuildType not in self._BuildTypeList: + self._BuildTypeList.append(BuildType) + if Arch not in self._ArchList: + self._ArchList.append(Arch) + + if 'COMMON' in self._BuildTypeList and len(self._BuildTypeList) > 1: + EdkLogger.error("build", FORMAT_INVALID, + "Specific build types must not be mixed with common one", + File=self.RuleFile, Line=LineIndex+1, + ExtraData=self.RuleContent[LineIndex]) + if 'COMMON' in self._ArchList and len(self._ArchList) > 1: + EdkLogger.error("build", FORMAT_INVALID, + "Specific ARCH must not be mixed with common one", + File=self.RuleFile, Line=LineIndex+1, + ExtraData=self.RuleContent[LineIndex]) + + self._FileType = FileType + self._State = self._Section + self.FileTypeList.add(FileType) + + ## Parse sub-section header + # + # @param LineIndex The line index of build rule text + # + def ParseSubSectionHeader(self, LineIndex): + SectionType = "" + List = self.RuleContent[LineIndex][1:-1].split(',') + FamilyList = [] + for Section in List: + TokenList = Section.split('.') + Type = TokenList[0].strip().upper() + + if SectionType == "": + SectionType = Type + elif SectionType != Type: + EdkLogger.error("build", FORMAT_INVALID, + "Two different section types are not allowed in the same sub-section", + File=self.RuleFile, Line=LineIndex+1, + ExtraData=self.RuleContent[LineIndex]) + + if len(TokenList) > 1: + Family = TokenList[1].strip().upper() + else: + Family = "COMMON" + + if Family not in FamilyList: + FamilyList.append(Family) + + self._FamilyList = FamilyList + self._TotalToolChainFamilySet.update(FamilyList) + self._State = SectionType.upper() + if 'COMMON' in FamilyList and len(FamilyList) > 1: + EdkLogger.error("build", FORMAT_INVALID, + "Specific tool chain family should not be mixed with general one", + File=self.RuleFile, Line=LineIndex+1, + ExtraData=self.RuleContent[LineIndex]) + if self._State not in self._StateHandler: + EdkLogger.error("build", FORMAT_INVALID, File=self.RuleFile, Line=LineIndex+1, + ExtraData="Unknown subsection: %s" % self.RuleContent[LineIndex]) + ## Parse sub-section + # + # @param LineIndex The line index of build rule text + # + def ParseInputFile(self, LineIndex): + FileList = [File.strip() for File in self.RuleContent[LineIndex].split(",")] + for ToolChainFamily in self._FamilyList: + InputFiles = self._RuleInfo[ToolChainFamily, self._State] + if InputFiles == None: + InputFiles = [] + self._RuleInfo[ToolChainFamily, self._State] = InputFiles + InputFiles.extend(FileList) + + ## Parse sub-section + # + # @param LineIndex The line index of build rule text + # + def ParseCommon(self, LineIndex): + for ToolChainFamily in self._FamilyList: + Items = self._RuleInfo[ToolChainFamily, self._State] + if Items == None: + Items = [] + self._RuleInfo[ToolChainFamily, self._State] = Items + Items.append(self.RuleContent[LineIndex]) + + ## Get a build rule via [] operator + # + # @param FileExt The extension of a file + # @param ToolChainFamily The tool chain family name + # @param BuildVersion The build version number. "*" means any rule + # is applicalbe. + # + # @retval FileType The file type string + # @retval FileBuildRule The object of FileBuildRule + # + # Key = (FileExt, ModuleType, Arch, ToolChainFamily) + def __getitem__(self, Key): + if not Key: + return None + + if Key[0] in self.Ext2FileType: + Type = self.Ext2FileType[Key[0]] + elif Key[0].upper() in self.FileTypeList: + Type = Key[0].upper() + else: + return None + + if len(Key) > 1: + Key = (Type,) + Key[1:] + else: + Key = (Type,) + return self.RuleDatabase[Key] + + _StateHandler = { + _SectionHeader : ParseSectionHeader, + _Section : ParseSection, + _SubSectionHeader : ParseSubSectionHeader, + _SubSection : ParseSubSection, + _InputFile : ParseInputFile, + _OutputFile : ParseCommon, + _ExtraDependency : ParseCommon, + _Command : ParseCommon, + _UnknownSection : SkipSection, + } + +# This acts like the main() function for the script, unless it is 'import'ed into another +# script. +if __name__ == '__main__': + import sys + EdkLogger.Initialize() + if len(sys.argv) > 1: + Br = BuildRule(sys.argv[1]) + print str(Br[".c", "DXE_DRIVER", "IA32", "MSFT"][1]) + print + print str(Br[".c", "DXE_DRIVER", "IA32", "INTEL"][1]) + print + print str(Br[".c", "DXE_DRIVER", "IA32", "GCC"][1]) + print + print str(Br[".ac", "ACPI_TABLE", "IA32", "MSFT"][1]) + print + print str(Br[".h", "ACPI_TABLE", "IA32", "INTEL"][1]) + print + print str(Br[".ac", "ACPI_TABLE", "IA32", "MSFT"][1]) + print + print str(Br[".s", "SEC", "IPF", "COMMON"][1]) + print + print str(Br[".s", "SEC"][1]) + diff --git a/BaseTools/Source/Python/AutoGen/GenC.py b/BaseTools/Source/Python/AutoGen/GenC.py new file mode 100644 index 0000000000..b62a12708b --- /dev/null +++ b/BaseTools/Source/Python/AutoGen/GenC.py @@ -0,0 +1,1931 @@ +## @file +# Routines for generating AutoGen.h and AutoGen.c +# +# Copyright (c) 2007, 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. +# + +## Import Modules +# +import string + +from Common import EdkLogger + +from Common.BuildToolError import * +from Common.DataType import * +from Common.Misc import * +from Common.String import StringToArray +from StrGather import * + +## PCD type string +gItemTypeStringDatabase = { + TAB_PCDS_FEATURE_FLAG : 'FixedAtBuild', + TAB_PCDS_FIXED_AT_BUILD : 'FixedAtBuild', + TAB_PCDS_PATCHABLE_IN_MODULE: 'BinaryPatch', + TAB_PCDS_DYNAMIC : '', + TAB_PCDS_DYNAMIC_DEFAULT : '', + TAB_PCDS_DYNAMIC_VPD : '', + TAB_PCDS_DYNAMIC_HII : '', + TAB_PCDS_DYNAMIC_EX : '', + TAB_PCDS_DYNAMIC_EX_DEFAULT : '', + TAB_PCDS_DYNAMIC_EX_VPD : '', + TAB_PCDS_DYNAMIC_EX_HII : '', +} + +## Dynamic PCD types +gDynamicPcd = [TAB_PCDS_DYNAMIC, TAB_PCDS_DYNAMIC_DEFAULT, TAB_PCDS_DYNAMIC_VPD, TAB_PCDS_DYNAMIC_HII] + +## Dynamic-ex PCD types +gDynamicExPcd = [TAB_PCDS_DYNAMIC_EX, TAB_PCDS_DYNAMIC_EX_DEFAULT, TAB_PCDS_DYNAMIC_EX_VPD, TAB_PCDS_DYNAMIC_EX_HII] + +## Datum size +gDatumSizeStringDatabase = {'UINT8':'8','UINT16':'16','UINT32':'32','UINT64':'64','BOOLEAN':'BOOLEAN','VOID*':'8'} +gDatumSizeStringDatabaseH = {'UINT8':'8','UINT16':'16','UINT32':'32','UINT64':'64','BOOLEAN':'BOOL','VOID*':'PTR'} +gDatumSizeStringDatabaseLib = {'UINT8':'8','UINT16':'16','UINT32':'32','UINT64':'64','BOOLEAN':'Bool','VOID*':'Ptr'} + +## Mapping between PCD driver type and EFI phase +gPcdPhaseMap = { + "PEI_PCD_DRIVER" : "PEI", + "DXE_PCD_DRIVER" : "DXE" +} + +gPcdDatabaseCommonAutoGenH = """ +// +// The following definition will be generated by build tool +// + +// +// Common definitions +// +typedef UINT8 SKU_ID; + +#define PCD_TYPE_SHIFT 28 + +#define PCD_TYPE_DATA (0x0 << PCD_TYPE_SHIFT) +#define PCD_TYPE_HII (0x8 << PCD_TYPE_SHIFT) +#define PCD_TYPE_VPD (0x4 << PCD_TYPE_SHIFT) +#define PCD_TYPE_SKU_ENABLED (0x2 << PCD_TYPE_SHIFT) +#define PCD_TYPE_STRING (0x1 << PCD_TYPE_SHIFT) + +#define PCD_TYPE_ALL_SET (PCD_TYPE_DATA | PCD_TYPE_HII | PCD_TYPE_VPD | PCD_TYPE_SKU_ENABLED | PCD_TYPE_STRING) + +#define PCD_DATUM_TYPE_SHIFT 24 + +#define PCD_DATUM_TYPE_POINTER (0x0 << PCD_DATUM_TYPE_SHIFT) +#define PCD_DATUM_TYPE_UINT8 (0x1 << PCD_DATUM_TYPE_SHIFT) +#define PCD_DATUM_TYPE_UINT16 (0x2 << PCD_DATUM_TYPE_SHIFT) +#define PCD_DATUM_TYPE_UINT32 (0x4 << PCD_DATUM_TYPE_SHIFT) +#define PCD_DATUM_TYPE_UINT64 (0x8 << PCD_DATUM_TYPE_SHIFT) + +#define PCD_DATUM_TYPE_ALL_SET (PCD_DATUM_TYPE_POINTER | \\ + PCD_DATUM_TYPE_UINT8 | \\ + PCD_DATUM_TYPE_UINT16 | \\ + PCD_DATUM_TYPE_UINT32 | \\ + PCD_DATUM_TYPE_UINT64) + +#define PCD_DATABASE_OFFSET_MASK (~(PCD_TYPE_ALL_SET | PCD_DATUM_TYPE_ALL_SET)) + +typedef struct { + UINT32 ExTokenNumber; + UINT16 LocalTokenNumber; // PCD Number of this particular platform build + UINT16 ExGuidIndex; // Index of GuidTable +} DYNAMICEX_MAPPING; + +typedef struct { + UINT32 SkuDataStartOffset; //We have to use offsetof MACRO as we don't know padding done by compiler + UINT32 SkuIdTableOffset; //Offset from the PCD_DB +} SKU_HEAD; + +typedef struct { + UINT16 GuidTableIndex; // Offset in Guid Table in units of GUID. + UINT16 StringIndex; // Offset in String Table in units of UINT16. + UINT16 Offset; // Offset in Variable + UINT16 DefaultValueOffset; // Offset of the Default Value +} VARIABLE_HEAD; + +typedef struct { + UINT32 Offset; +} VPD_HEAD; + +typedef UINT16 STRING_HEAD; + +typedef UINT16 SIZE_INFO; + +#define offsetof(s,m) (UINT32) (UINTN) &(((s *)0)->m) + +""" + +gPcdDatabaseEpilogueAutoGenH = """ +typedef struct { + PEI_PCD_DATABASE PeiDb; + DXE_PCD_DATABASE DxeDb; +} PCD_DATABASE; + +#define PCD_TOTAL_TOKEN_NUMBER (PEI_LOCAL_TOKEN_NUMBER + DXE_LOCAL_TOKEN_NUMBER) + +""" + +gPcdDatabaseAutoGenH = TemplateString(""" +#define ${PHASE}_GUID_TABLE_SIZE ${GUID_TABLE_SIZE} +#define ${PHASE}_STRING_TABLE_SIZE ${STRING_TABLE_SIZE} +#define ${PHASE}_SKUID_TABLE_SIZE ${SKUID_TABLE_SIZE} +#define ${PHASE}_LOCAL_TOKEN_NUMBER_TABLE_SIZE ${LOCAL_TOKEN_NUMBER_TABLE_SIZE} +#define ${PHASE}_LOCAL_TOKEN_NUMBER ${LOCAL_TOKEN_NUMBER} +#define ${PHASE}_EXMAPPING_TABLE_SIZE ${EXMAPPING_TABLE_SIZE} +#define ${PHASE}_EX_TOKEN_NUMBER ${EX_TOKEN_NUMBER} +#define ${PHASE}_SIZE_TABLE_SIZE ${SIZE_TABLE_SIZE} +#define ${PHASE}_GUID_TABLE_EMPTY ${GUID_TABLE_EMPTY} +#define ${PHASE}_STRING_TABLE_EMPTY ${STRING_TABLE_EMPTY} +#define ${PHASE}_SKUID_TABLE_EMPTY ${SKUID_TABLE_EMPTY} +#define ${PHASE}_DATABASE_EMPTY ${DATABASE_EMPTY} +#define ${PHASE}_EXMAP_TABLE_EMPTY ${EXMAP_TABLE_EMPTY} + +typedef struct { +${BEGIN} UINT64 ${INIT_CNAME_DECL_UINT64}_${INIT_GUID_DECL_UINT64}[${INIT_NUMSKUS_DECL_UINT64}]; +${END} +${BEGIN} UINT64 ${VARDEF_CNAME_UINT64}_${VARDEF_GUID_UINT64}_VariableDefault_${VARDEF_SKUID_UINT64}; +${END} +${BEGIN} UINT32 ${INIT_CNAME_DECL_UINT32}_${INIT_GUID_DECL_UINT32}[${INIT_NUMSKUS_DECL_UINT32}]; +${END} +${BEGIN} UINT32 ${VARDEF_CNAME_UINT32}_${VARDEF_GUID_UINT32}_VariableDefault_${VARDEF_SKUID_UINT32}; +${END} +${BEGIN} VPD_HEAD ${VPD_HEAD_CNAME_DECL}_${VPD_HEAD_GUID_DECL}[${VPD_HEAD_NUMSKUS_DECL}]; +${END} + DYNAMICEX_MAPPING ExMapTable[${PHASE}_EXMAPPING_TABLE_SIZE]; + UINT32 LocalTokenNumberTable[${PHASE}_LOCAL_TOKEN_NUMBER_TABLE_SIZE]; + GUID GuidTable[${PHASE}_GUID_TABLE_SIZE]; +${BEGIN} STRING_HEAD ${STRING_HEAD_CNAME_DECL}_${STRING_HEAD_GUID_DECL}[${STRING_HEAD_NUMSKUS_DECL}]; +${END} +${BEGIN} VARIABLE_HEAD ${VARIABLE_HEAD_CNAME_DECL}_${VARIABLE_HEAD_GUID_DECL}[${VARIABLE_HEAD_NUMSKUS_DECL}]; +${END} +${BEGIN} UINT8 StringTable${STRING_TABLE_INDEX}[${STRING_TABLE_LENGTH}]; /* ${STRING_TABLE_CNAME}_${STRING_TABLE_GUID} */ +${END} + SIZE_INFO SizeTable[${PHASE}_SIZE_TABLE_SIZE]; +${BEGIN} UINT16 ${INIT_CNAME_DECL_UINT16}_${INIT_GUID_DECL_UINT16}[${INIT_NUMSKUS_DECL_UINT16}]; +${END} +${BEGIN} UINT16 ${VARDEF_CNAME_UINT16}_${VARDEF_GUID_UINT16}_VariableDefault_${VARDEF_SKUID_UINT16}; +${END} +${BEGIN} UINT8 ${INIT_CNAME_DECL_UINT8}_${INIT_GUID_DECL_UINT8}[${INIT_NUMSKUS_DECL_UINT8}]; +${END} +${BEGIN} UINT8 ${VARDEF_CNAME_UINT8}_${VARDEF_GUID_UINT8}_VariableDefault_${VARDEF_SKUID_UINT8}; +${END} +${BEGIN} BOOLEAN ${INIT_CNAME_DECL_BOOLEAN}_${INIT_GUID_DECL_BOOLEAN}[${INIT_NUMSKUS_DECL_BOOLEAN}]; +${END} +${BEGIN} BOOLEAN ${VARDEF_CNAME_BOOLEAN}_${VARDEF_GUID_BOOLEAN}_VariableDefault_${VARDEF_SKUID_BOOLEAN}; +${END} + UINT8 SkuIdTable[${PHASE}_SKUID_TABLE_SIZE]; +${SYSTEM_SKU_ID} +} ${PHASE}_PCD_DATABASE_INIT; + +typedef struct { +${PCD_DATABASE_UNINIT_EMPTY} +${BEGIN} UINT64 ${UNINIT_CNAME_DECL_UINT64}_${UNINIT_GUID_DECL_UINT64}[${UNINIT_NUMSKUS_DECL_UINT64}]; +${END} +${BEGIN} UINT32 ${UNINIT_CNAME_DECL_UINT32}_${UNINIT_GUID_DECL_UINT32}[${UNINIT_NUMSKUS_DECL_UINT32}]; +${END} +${BEGIN} UINT16 ${UNINIT_CNAME_DECL_UINT16}_${UNINIT_GUID_DECL_UINT16}[${UNINIT_NUMSKUS_DECL_UINT16}]; +${END} +${BEGIN} UINT8 ${UNINIT_CNAME_DECL_UINT8}_${UNINIT_GUID_DECL_UINT8}[${UNINIT_NUMSKUS_DECL_UINT8}]; +${END} +${BEGIN} BOOLEAN ${UNINIT_CNAME_DECL_BOOLEAN}_${UNINIT_GUID_DECL_BOOLEAN}[${UNINIT_NUMSKUS_DECL_BOOLEAN}]; +${END} +} ${PHASE}_PCD_DATABASE_UNINIT; + +#define PCD_${PHASE}_SERVICE_DRIVER_VERSION 2 + +typedef struct { + ${PHASE}_PCD_DATABASE_INIT Init; + ${PHASE}_PCD_DATABASE_UNINIT Uninit; +} ${PHASE}_PCD_DATABASE; + +#define ${PHASE}_NEX_TOKEN_NUMBER (${PHASE}_LOCAL_TOKEN_NUMBER - ${PHASE}_EX_TOKEN_NUMBER) +""") + +gEmptyPcdDatabaseAutoGenC = TemplateString(""" +${PHASE}_PCD_DATABASE_INIT g${PHASE}PcdDbInit = { + /* ExMapTable */ + { + {0, 0, 0} + }, + /* LocalTokenNumberTable */ + { + 0 + }, + /* GuidTable */ + { + {0x00000000, 0x0000, 0x0000, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}} + }, + /* StringTable */ + { 0 }, + /* SizeTable */ + { + 0, 0 + }, + /* SkuIdTable */ + { 0 }, + ${SYSTEM_SKU_ID_VALUE} +}; +""") + +gPcdDatabaseAutoGenC = TemplateString(""" +${PHASE}_PCD_DATABASE_INIT g${PHASE}PcdDbInit = { +${BEGIN} { ${INIT_VALUE_UINT64} }, /* ${INIT_CNAME_DECL_UINT64}_${INIT_GUID_DECL_UINT64}[${INIT_NUMSKUS_DECL_UINT64}] */ +${END} +${BEGIN} ${VARDEF_VALUE_UINT64}, /* ${VARDEF_CNAME_UINT64}_${VARDEF_GUID_UINT64}_VariableDefault_${VARDEF_SKUID_UINT64} */ +${END} +${BEGIN} { ${INIT_VALUE_UINT32} }, /* ${INIT_CNAME_DECL_UINT32}_${INIT_GUID_DECL_UINT32}[${INIT_NUMSKUS_DECL_UINT32}] */ +${END} +${BEGIN} ${VARDEF_VALUE_UINT32}, /* ${VARDEF_CNAME_UINT32}_${VARDEF_GUID_UINT32}_VariableDefault_${VARDEF_SKUID_UINT32} */ +${END} + /* VPD */ +${BEGIN} { ${VPD_HEAD_VALUE} }, /* ${VPD_HEAD_CNAME_DECL}_${VPD_HEAD_GUID_DECL}[${VPD_HEAD_NUMSKUS_DECL}] */ +${END} + /* ExMapTable */ + { +${BEGIN} { ${EXMAPPING_TABLE_EXTOKEN}, ${EXMAPPING_TABLE_LOCAL_TOKEN}, ${EXMAPPING_TABLE_GUID_INDEX} }, +${END} + }, + /* LocalTokenNumberTable */ + { +${BEGIN} offsetof(${PHASE}_PCD_DATABASE, ${TOKEN_INIT}.${TOKEN_CNAME}_${TOKEN_GUID}) | ${TOKEN_TYPE}, +${END} + }, + /* GuidTable */ + { +${BEGIN} ${GUID_STRUCTURE}, +${END} + }, +${BEGIN} { ${STRING_HEAD_VALUE} }, /* ${STRING_HEAD_CNAME_DECL}_${STRING_HEAD_GUID_DECL}[${STRING_HEAD_NUMSKUS_DECL}] */ +${END} +${BEGIN} /* ${VARIABLE_HEAD_CNAME_DECL}_${VARIABLE_HEAD_GUID_DECL}[${VARIABLE_HEAD_NUMSKUS_DECL}] */ + { + ${VARIABLE_HEAD_VALUE} + }, +${END} + /* StringTable */ +${BEGIN} ${STRING_TABLE_VALUE}, /* ${STRING_TABLE_CNAME}_${STRING_TABLE_GUID} */ +${END} + /* SizeTable */ + { +${BEGIN} ${SIZE_TABLE_MAXIMUM_LENGTH}, ${SIZE_TABLE_CURRENT_LENGTH}, /* ${SIZE_TABLE_CNAME}_${SIZE_TABLE_GUID} */ +${END} + }, +${BEGIN} { ${INIT_VALUE_UINT16} }, /* ${INIT_CNAME_DECL_UINT16}_${INIT_GUID_DECL_UINT16}[${INIT_NUMSKUS_DECL_UINT16}] */ +${END} +${BEGIN} ${VARDEF_VALUE_UINT16}, /* ${VARDEF_CNAME_UINT16}_${VARDEF_GUID_UINT16}_VariableDefault_${VARDEF_SKUID_UINT16} */ +${END} +${BEGIN} { ${INIT_VALUE_UINT8} }, /* ${INIT_CNAME_DECL_UINT8}_${INIT_GUID_DECL_UINT8}[${INIT_NUMSKUS_DECL_UINT8}] */ +${END} +${BEGIN} ${VARDEF_VALUE_UINT8}, /* ${VARDEF_CNAME_UINT8}_${VARDEF_GUID_UINT8}_VariableDefault_${VARDEF_SKUID_UINT8} */ +${END} +${BEGIN} { ${INIT_VALUE_BOOLEAN} }, /* ${INIT_CNAME_DECL_BOOLEAN}_${INIT_GUID_DECL_BOOLEAN}[${INIT_NUMSKUS_DECL_BOOLEAN}] */ +${END} +${BEGIN} ${VARDEF_VALUE_BOOLEAN}, /* ${VARDEF_CNAME_BOOLEAN}_${VARDEF_GUID_BOOLEAN}_VariableDefault_${VARDEF_SKUID_BOOLEAN} */ +${END} + /* SkuIdTable */ + { ${BEGIN}${SKUID_VALUE}, ${END} }, + ${SYSTEM_SKU_ID_VALUE} +}; +""") + + +## AutoGen File Header Templates +gAutoGenHeaderString = TemplateString("""\ +/** + DO NOT EDIT + FILE auto-generated + Module name: + ${FileName} + Abstract: Auto-generated ${FileName} for building module or library. +**/ +""") + +gAutoGenHPrologueString = TemplateString(""" +#ifndef _${File}_${Guid} +#define _${File}_${Guid} + +""") + +gAutoGenHEpilogueString = """ +#endif +""" + +## PEI Core Entry Point Templates +gPeiCoreEntryPointPrototype = TemplateString(""" +${BEGIN} +VOID +EFIAPI +${Function} ( + IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData, + IN CONST EFI_PEI_PPI_DESCRIPTOR *PpiList, + IN VOID *Context + ); +${END} +""") + +gPeiCoreEntryPointString = TemplateString(""" +${BEGIN} +VOID +EFIAPI +ProcessModuleEntryPointList ( + IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData, + IN CONST EFI_PEI_PPI_DESCRIPTOR *PpiList, + IN VOID *Context + ) + +{ + ${Function} (SecCoreData, PpiList, Context); +} +${END} +""") + + +## DXE Core Entry Point Templates +gDxeCoreEntryPointPrototype = TemplateString(""" +${BEGIN} +VOID +EFIAPI +${Function} ( + IN VOID *HobStart + ); +${END} +""") + +gDxeCoreEntryPointString = TemplateString(""" +${BEGIN} +VOID +EFIAPI +ProcessModuleEntryPointList ( + IN VOID *HobStart + ) + +{ + ${Function} (HobStart); +} +${END} +""") + +## PEIM Entry Point Templates +gPeimEntryPointPrototype = TemplateString(""" +${BEGIN} +EFI_STATUS +EFIAPI +${Function} ( + IN EFI_PEI_FILE_HANDLE FileHandle, + IN CONST EFI_PEI_SERVICES **PeiServices + ); +${END} +""") + +## SMM_CORE Entry Point Templates +gSmmCoreEntryPointString = TemplateString(""" +const UINT32 _gUefiDriverRevision = 0; +${BEGIN} +EFI_STATUS +${Function} ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +EFI_STATUS +EFIAPI +ProcessModuleEntryPointList ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + return ${Function} (ImageHandle, SystemTable); +} +${END} +""") + +gPeimEntryPointString = [ +TemplateString(""" +GLOBAL_REMOVE_IF_UNREFERENCED const UINT32 _gPeimRevision = ${PiSpecVersion}; + +EFI_STATUS +EFIAPI +ProcessModuleEntryPointList ( + IN EFI_PEI_FILE_HANDLE FileHandle, + IN CONST EFI_PEI_SERVICES **PeiServices + ) + +{ + return EFI_SUCCESS; +} +"""), +TemplateString(""" +GLOBAL_REMOVE_IF_UNREFERENCED const UINT32 _gPeimRevision = ${PiSpecVersion}; +${BEGIN} +EFI_STATUS +EFIAPI +ProcessModuleEntryPointList ( + IN EFI_PEI_FILE_HANDLE FileHandle, + IN CONST EFI_PEI_SERVICES **PeiServices + ) + +{ + return ${Function} (FileHandle, PeiServices); +} +${END} +"""), +TemplateString(""" +GLOBAL_REMOVE_IF_UNREFERENCED const UINT32 _gPeimRevision = ${PiSpecVersion}; + +EFI_STATUS +EFIAPI +ProcessModuleEntryPointList ( + IN EFI_PEI_FILE_HANDLE FileHandle, + IN CONST EFI_PEI_SERVICES **PeiServices + ) + +{ + EFI_STATUS Status; + EFI_STATUS CombinedStatus; + + CombinedStatus = EFI_LOAD_ERROR; +${BEGIN} + Status = ${Function} (FileHandle, PeiServices); + if (!EFI_ERROR (Status) || EFI_ERROR (CombinedStatus)) { + CombinedStatus = Status; + } +${END} + return CombinedStatus; +} +""") +] + +## DXE SMM Entry Point Templates +gDxeSmmEntryPointPrototype = TemplateString(""" +${BEGIN} +EFI_STATUS +EFIAPI +${Function} ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); +${END} +""") + +gDxeSmmEntryPointString = [ +TemplateString(""" +const UINT32 _gUefiDriverRevision = ${EfiSpecVersion}; +const UINT32 _gDxeRevision = ${PiSpecVersion}; + +EFI_STATUS +EFIAPI +ProcessModuleEntryPointList ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) + +{ + return EFI_SUCCESS; +} +"""), +TemplateString(""" +const UINT32 _gUefiDriverRevision = ${EfiSpecVersion}; +const UINT32 _gDxeRevision = ${PiSpecVersion}; + +static BASE_LIBRARY_JUMP_BUFFER mJumpContext; +static EFI_STATUS mDriverEntryPointStatus = EFI_LOAD_ERROR; + +VOID +EFIAPI +ExitDriver ( + IN EFI_STATUS Status + ) +{ + if (!EFI_ERROR (Status) || EFI_ERROR (mDriverEntryPointStatus)) { + mDriverEntryPointStatus = Status; + } + LongJump (&mJumpContext, (UINTN)-1); + ASSERT (FALSE); +} + +EFI_STATUS +EFIAPI +ProcessModuleEntryPointList ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) + +{ +${BEGIN} + if (SetJump (&mJumpContext) == 0) { + ExitDriver (${Function} (ImageHandle, SystemTable)); + ASSERT (FALSE); + } +${END} + + return mDriverEntryPointStatus; +} +""") +] + +## UEFI Driver Entry Point Templates +gUefiDriverEntryPointPrototype = TemplateString(""" +${BEGIN} +EFI_STATUS +EFIAPI +${Function} ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); +${END} +""") + +gUefiDriverEntryPointString = [ +TemplateString(""" +const UINT32 _gUefiDriverRevision = ${EfiSpecVersion}; +const UINT32 _gDxeRevision = ${PiSpecVersion}; + +EFI_STATUS +EFIAPI +ProcessModuleEntryPointList ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + return EFI_SUCCESS; +} +"""), +TemplateString(""" +const UINT32 _gUefiDriverRevision = ${EfiSpecVersion}; +const UINT32 _gDxeRevision = ${PiSpecVersion}; + +${BEGIN} +EFI_STATUS +EFIAPI +ProcessModuleEntryPointList ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) + +{ + return ${Function} (ImageHandle, SystemTable); +} +${END} +VOID +EFIAPI +ExitDriver ( + IN EFI_STATUS Status + ) +{ + if (EFI_ERROR (Status)) { + ProcessLibraryDestructorList (gImageHandle, gST); + } + gBS->Exit (gImageHandle, Status, 0, NULL); +} +"""), +TemplateString(""" +const UINT32 _gUefiDriverRevision = ${EfiSpecVersion}; +const UINT32 _gDxeRevision = ${PiSpecVersion}; + +EFI_STATUS +EFIAPI +ProcessModuleEntryPointList ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) + +{ + ${BEGIN} + if (SetJump (&mJumpContext) == 0) { + ExitDriver (${Function} (ImageHandle, SystemTable)); + ASSERT (FALSE); + } + ${END} + return mDriverEntryPointStatus; +} + +static BASE_LIBRARY_JUMP_BUFFER mJumpContext; +static EFI_STATUS mDriverEntryPointStatus = EFI_LOAD_ERROR; + +VOID +EFIAPI +ExitDriver ( + IN EFI_STATUS Status + ) +{ + if (!EFI_ERROR (Status) || EFI_ERROR (mDriverEntryPointStatus)) { + mDriverEntryPointStatus = Status; + } + LongJump (&mJumpContext, (UINTN)-1); + ASSERT (FALSE); +} +""") +] + + +## UEFI Application Entry Point Templates +gUefiApplicationEntryPointPrototype = TemplateString(""" +${BEGIN} +EFI_STATUS +EFIAPI +${Function} ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); +${END} +""") + +gUefiApplicationEntryPointString = [ +TemplateString(""" +const UINT32 _gUefiDriverRevision = ${EfiSpecVersion}; + +EFI_STATUS +EFIAPI +ProcessModuleEntryPointList ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + return EFI_SUCCESS; +} +"""), +TemplateString(""" +const UINT32 _gUefiDriverRevision = ${EfiSpecVersion}; + +${BEGIN} +EFI_STATUS +EFIAPI +ProcessModuleEntryPointList ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) + +{ + return ${Function} (ImageHandle, SystemTable); +} +${END} +VOID +EFIAPI +ExitDriver ( + IN EFI_STATUS Status + ) +{ + if (EFI_ERROR (Status)) { + ProcessLibraryDestructorList (gImageHandle, gST); + } + gBS->Exit (gImageHandle, Status, 0, NULL); +} +"""), +TemplateString(""" +const UINT32 _gUefiDriverRevision = ${EfiSpecVersion}; + +EFI_STATUS +EFIAPI +ProcessModuleEntryPointList ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) + +{ + ${BEGIN} + if (SetJump (&mJumpContext) == 0) { + ExitDriver (${Function} (ImageHandle, SystemTable)); + ASSERT (FALSE); + } + ${END} + return mDriverEntryPointStatus; +} + +static BASE_LIBRARY_JUMP_BUFFER mJumpContext; +static EFI_STATUS mDriverEntryPointStatus = EFI_LOAD_ERROR; + +VOID +EFIAPI +ExitDriver ( + IN EFI_STATUS Status + ) +{ + if (!EFI_ERROR (Status) || EFI_ERROR (mDriverEntryPointStatus)) { + mDriverEntryPointStatus = Status; + } + LongJump (&mJumpContext, (UINTN)-1); + ASSERT (FALSE); +} +""") +] + +## UEFI Unload Image Templates +gUefiUnloadImagePrototype = TemplateString(""" +${BEGIN} +EFI_STATUS +EFIAPI +${Function} ( + IN EFI_HANDLE ImageHandle + ); +${END} +""") + +gUefiUnloadImageString = [ +TemplateString(""" +GLOBAL_REMOVE_IF_UNREFERENCED const UINT8 _gDriverUnloadImageCount = ${Count}; + +EFI_STATUS +EFIAPI +ProcessModuleUnloadList ( + IN EFI_HANDLE ImageHandle + ) +{ + return EFI_SUCCESS; +} +"""), +TemplateString(""" +GLOBAL_REMOVE_IF_UNREFERENCED const UINT8 _gDriverUnloadImageCount = ${Count}; + +${BEGIN} +EFI_STATUS +EFIAPI +ProcessModuleUnloadList ( + IN EFI_HANDLE ImageHandle + ) +{ + return ${Function} (ImageHandle); +} +${END} +"""), +TemplateString(""" +GLOBAL_REMOVE_IF_UNREFERENCED const UINT8 _gDriverUnloadImageCount = ${Count}; + +EFI_STATUS +EFIAPI +ProcessModuleUnloadList ( + IN EFI_HANDLE ImageHandle + ) +{ + EFI_STATUS Status; + + Status = EFI_SUCCESS; +${BEGIN} + if (EFI_ERROR (Status)) { + ${Function} (ImageHandle); + } else { + Status = ${Function} (ImageHandle); + } +${END} + return Status; +} +""") +] + +gLibraryStructorPrototype = { +'BASE' : TemplateString("""${BEGIN} +RETURN_STATUS +EFIAPI +${Function} ( + VOID + );${END} +"""), + +'PEI' : TemplateString("""${BEGIN} +EFI_STATUS +EFIAPI +${Function} ( + IN EFI_PEI_FILE_HANDLE FileHandle, + IN CONST EFI_PEI_SERVICES **PeiServices + );${END} +"""), + +'DXE' : TemplateString("""${BEGIN} +EFI_STATUS +EFIAPI +${Function} ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + );${END} +"""), +} + +gLibraryStructorCall = { +'BASE' : TemplateString("""${BEGIN} + Status = ${Function} (); + ASSERT_EFI_ERROR (Status);${END} +"""), + +'PEI' : TemplateString("""${BEGIN} + Status = ${Function} (FileHandle, PeiServices); + ASSERT_EFI_ERROR (Status);${END} +"""), + +'DXE' : TemplateString("""${BEGIN} + Status = ${Function} (ImageHandle, SystemTable); + ASSERT_EFI_ERROR (Status);${END} +"""), +} + +## Library Constructor and Destructor Templates +gLibraryString = { +'BASE' : TemplateString(""" +${BEGIN}${FunctionPrototype}${END} + +VOID +EFIAPI +ProcessLibrary${Type}List ( + VOID + ) +{ +${BEGIN} EFI_STATUS Status; +${FunctionCall}${END} +} +"""), + +'PEI' : TemplateString(""" +${BEGIN}${FunctionPrototype}${END} + +VOID +EFIAPI +ProcessLibrary${Type}List ( + IN EFI_PEI_FILE_HANDLE FileHandle, + IN CONST EFI_PEI_SERVICES **PeiServices + ) +{ +${BEGIN} EFI_STATUS Status; +${FunctionCall}${END} +} +"""), + +'DXE' : TemplateString(""" +${BEGIN}${FunctionPrototype}${END} + +VOID +EFIAPI +ProcessLibrary${Type}List ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ +${BEGIN} EFI_STATUS Status; +${FunctionCall}${END} +} +"""), +} + +gSpecificationString = TemplateString(""" +${BEGIN} +#undef ${SpecificationName} +#define ${SpecificationName} ${SpecificationValue} +${END} +""") + +gBasicHeaderFile = "Base.h" + +gModuleTypeHeaderFile = { + "BASE" : [gBasicHeaderFile], + "SEC" : ["PiPei.h", "Library/DebugLib.h"], + "PEI_CORE" : ["PiPei.h", "Library/DebugLib.h", "Library/PeiCoreEntryPoint.h"], + "PEIM" : ["PiPei.h", "Library/DebugLib.h", "Library/PeimEntryPoint.h"], + "DXE_CORE" : ["PiDxe.h", "Library/DebugLib.h", "Library/DxeCoreEntryPoint.h"], + "DXE_DRIVER" : ["PiDxe.h", "Library/BaseLib.h", "Library/DebugLib.h", "Library/UefiBootServicesTableLib.h", "Library/UefiDriverEntryPoint.h"], + "DXE_SMM_DRIVER" : ["PiDxe.h", "Library/BaseLib.h", "Library/DebugLib.h", "Library/UefiBootServicesTableLib.h", "Library/UefiDriverEntryPoint.h"], + "DXE_RUNTIME_DRIVER": ["PiDxe.h", "Library/BaseLib.h", "Library/DebugLib.h", "Library/UefiBootServicesTableLib.h", "Library/UefiDriverEntryPoint.h"], + "DXE_SAL_DRIVER" : ["PiDxe.h", "Library/BaseLib.h", "Library/DebugLib.h", "Library/UefiBootServicesTableLib.h", "Library/UefiDriverEntryPoint.h"], + "UEFI_DRIVER" : ["Uefi.h", "Library/BaseLib.h", "Library/DebugLib.h", "Library/UefiBootServicesTableLib.h", "Library/UefiDriverEntryPoint.h"], + "UEFI_APPLICATION" : ["Uefi.h", "Library/BaseLib.h", "Library/DebugLib.h", "Library/UefiBootServicesTableLib.h", "Library/UefiApplicationEntryPoint.h"], + "SMM_DRIVER" : ["PiDxe.h", "Library/BaseLib.h", "Library/DebugLib.h", "Library/SmmDriverEntryPoint.h"], + "SMM_CORE" : ["PiDxe.h", "Library/DebugLib.h"], + "USER_DEFINED" : [gBasicHeaderFile] +} + +## Create code for module PCDs +# +# @param Info The ModuleAutoGen object +# @param AutoGenC The TemplateString object for C code +# @param AutoGenH The TemplateString object for header file +# @param Pcd The PCD object +# +def CreateModulePcdCode(Info, AutoGenC, AutoGenH, Pcd): + TokenSpaceGuidValue = Pcd.TokenSpaceGuidValue #Info.GuidList[Pcd.TokenSpaceGuidCName] + PcdTokenNumber = Info.PlatformInfo.PcdTokenNumber + # + # Write PCDs + # + PcdTokenName = '_PCD_TOKEN_' + Pcd.TokenCName + if Pcd.Type in gDynamicExPcd: + TokenNumber = int(Pcd.TokenValue, 0) + else: + if (Pcd.TokenCName, Pcd.TokenSpaceGuidCName) not in PcdTokenNumber: + EdkLogger.error("build", AUTOGEN_ERROR, + "No generated token number for %s.%s\n" % (Pcd.TokenSpaceGuidCName, Pcd.TokenCName), + ExtraData="[%s]" % str(Info)) + TokenNumber = PcdTokenNumber[Pcd.TokenCName, Pcd.TokenSpaceGuidCName] + AutoGenH.Append('\n#define %s %d\n' % (PcdTokenName, TokenNumber)) + + EdkLogger.debug(EdkLogger.DEBUG_3, "Creating code for " + Pcd.TokenCName + "." + Pcd.TokenSpaceGuidCName) + if Pcd.Type not in gItemTypeStringDatabase: + EdkLogger.error("build", AUTOGEN_ERROR, + "Unknown PCD type [%s] of PCD %s.%s" % (Pcd.Type, Pcd.TokenSpaceGuidCName, Pcd.TokenCName), + ExtraData="[%s]" % str(Info)) + if Pcd.DatumType not in gDatumSizeStringDatabase: + EdkLogger.error("build", AUTOGEN_ERROR, + "Unknown datum type [%s] of PCD %s.%s" % (Pcd.DatumType, Pcd.TokenSpaceGuidCName, Pcd.TokenCName), + ExtraData="[%s]" % str(Info)) + + DatumSize = gDatumSizeStringDatabase[Pcd.DatumType] + DatumSizeLib = gDatumSizeStringDatabaseLib[Pcd.DatumType] + GetModeName = '_PCD_GET_MODE_' + gDatumSizeStringDatabaseH[Pcd.DatumType] + '_' + Pcd.TokenCName + SetModeName = '_PCD_SET_MODE_' + gDatumSizeStringDatabaseH[Pcd.DatumType] + '_' + Pcd.TokenCName + + if Pcd.Type in gDynamicExPcd: + AutoGenH.Append('#define %s LibPcdGetEx%s(&%s, %s)\n' % (GetModeName, DatumSizeLib, Pcd.TokenSpaceGuidCName, PcdTokenName)) + if Pcd.DatumType == 'VOID*': + AutoGenH.Append('#define %s(SizeOfBuffer, Buffer) LibPcdSetEx%s(&%s, %s, (SizeOfBuffer), (Buffer))\n' % (SetModeName, DatumSizeLib, Pcd.TokenSpaceGuidCName, PcdTokenName)) + else: + AutoGenH.Append('#define %s(Value) LibPcdSetEx%s(&%s, %s, (Value))\n' % (SetModeName, DatumSizeLib, Pcd.TokenSpaceGuidCName, PcdTokenName)) + elif Pcd.Type in gDynamicPcd: + AutoGenH.Append('#define %s LibPcdGet%s(%s)\n' % (GetModeName, DatumSizeLib, PcdTokenName)) + if Pcd.DatumType == 'VOID*': + AutoGenH.Append('#define %s(SizeOfBuffer, Buffer) LibPcdSet%s(%s, (SizeOfBuffer), (Buffer))\n' %(SetModeName, DatumSizeLib, PcdTokenName)) + else: + AutoGenH.Append('#define %s(Value) LibPcdSet%s(%s, (Value))\n' % (SetModeName, DatumSizeLib, PcdTokenName)) + else: + PcdVariableName = '_gPcd_' + gItemTypeStringDatabase[Pcd.Type] + '_' + Pcd.TokenCName + Const = 'const' + if Pcd.Type == TAB_PCDS_PATCHABLE_IN_MODULE: + Const = '' + Type = '' + Array = '' + Value = Pcd.DefaultValue + Unicode = False + if Pcd.DatumType == 'UINT64': + if not Value.endswith('ULL'): + Value += 'ULL' + if Pcd.DatumType == 'VOID*': + if Pcd.MaxDatumSize == None or Pcd.MaxDatumSize == '': + EdkLogger.error("build", AUTOGEN_ERROR, + "Unknown [MaxDatumSize] of PCD [%s.%s]" % (Pcd.TokenSpaceGuidCName, Pcd.TokenCName), + ExtraData="[%s]" % str(Info)) + + ArraySize = int(Pcd.MaxDatumSize, 0) + if Value[0] == '{': + Type = '(VOID *)' + else: + if Value[0] == 'L': + Unicode = True + Value = Value.lstrip('L') #.strip('"') + Value = eval(Value) # translate escape character + NewValue = '{' + for Index in range(0,len(Value)): + if Unicode: + NewValue = NewValue + str(ord(Value[Index]) % 0x10000) + ', ' + else: + NewValue = NewValue + str(ord(Value[Index]) % 0x100) + ', ' + if Unicode: + ArraySize = ArraySize / 2; + + if ArraySize < (len(Value) + 1): + ArraySize = len(Value) + 1 + Value = NewValue + '0 }' + Array = '[%d]' % ArraySize + # + # skip casting for fixed at build since it breaks ARM assembly. + # Long term we need PCD macros that work in assembly + # + elif Pcd.Type != TAB_PCDS_FIXED_AT_BUILD: + Value = "((%s)%s)" % (Pcd.DatumType, Value) + + if Pcd.Type == TAB_PCDS_PATCHABLE_IN_MODULE: + PcdValueName = '_PCD_PATCHABLE_VALUE_' + Pcd.TokenCName + else: + PcdValueName = '_PCD_VALUE_' + Pcd.TokenCName + + if Pcd.DatumType == 'VOID*': + # + # For unicode, UINT16 array will be generated, so the alignment of unicode is guaranteed. + # + if Unicode: + AutoGenH.Append('#define _PCD_PATCHABLE_%s_SIZE %s\n' % (Pcd.TokenCName, Pcd.MaxDatumSize)) + AutoGenH.Append('#define %s %s%s\n' %(PcdValueName, Type, PcdVariableName)) + AutoGenC.Append('GLOBAL_REMOVE_IF_UNREFERENCED %s UINT16 %s%s = %s;\n' % (Const, PcdVariableName, Array, Value)) + AutoGenH.Append('extern %s UINT16 %s%s;\n' %(Const, PcdVariableName, Array)) + AutoGenH.Append('#define %s %s%s\n' %(GetModeName, Type, PcdVariableName)) + else: + AutoGenH.Append('#define _PCD_PATCHABLE_%s_SIZE %s\n' % (Pcd.TokenCName, Pcd.MaxDatumSize)) + AutoGenH.Append('#define %s %s%s\n' %(PcdValueName, Type, PcdVariableName)) + AutoGenC.Append('GLOBAL_REMOVE_IF_UNREFERENCED %s UINT8 %s%s = %s;\n' % (Const, PcdVariableName, Array, Value)) + AutoGenH.Append('extern %s UINT8 %s%s;\n' %(Const, PcdVariableName, Array)) + AutoGenH.Append('#define %s %s%s\n' %(GetModeName, Type, PcdVariableName)) + elif Pcd.Type == TAB_PCDS_PATCHABLE_IN_MODULE: + AutoGenH.Append('#define %s %s\n' %(PcdValueName, Value)) + AutoGenC.Append('GLOBAL_REMOVE_IF_UNREFERENCED volatile %s %s %s = %s;\n' %(Const, Pcd.DatumType, PcdVariableName, PcdValueName)) + AutoGenH.Append('extern volatile %s %s %s%s;\n' % (Const, Pcd.DatumType, PcdVariableName, Array)) + AutoGenH.Append('#define %s %s%s\n' % (GetModeName, Type, PcdVariableName)) + else: + AutoGenH.Append('#define %s %s\n' %(PcdValueName, Value)) + AutoGenC.Append('GLOBAL_REMOVE_IF_UNREFERENCED %s %s %s = %s;\n' %(Const, Pcd.DatumType, PcdVariableName, PcdValueName)) + AutoGenH.Append('extern %s %s %s%s;\n' % (Const, Pcd.DatumType, PcdVariableName, Array)) + AutoGenH.Append('#define %s %s%s\n' % (GetModeName, Type, PcdVariableName)) + + if Pcd.Type == TAB_PCDS_PATCHABLE_IN_MODULE: + if Pcd.DatumType == 'VOID*': + AutoGenH.Append('#define %s(SizeOfBuffer, Buffer) LibPatchPcdSetPtr(_gPcd_BinaryPatch_%s, (UINTN)_PCD_PATCHABLE_%s_SIZE, (SizeOfBuffer), (Buffer))\n' % (SetModeName, Pcd.TokenCName, Pcd.TokenCName)) + else: + AutoGenH.Append('#define %s(Value) (%s = (Value))\n' % (SetModeName, PcdVariableName)) + else: + AutoGenH.Append('//#define %s ASSERT(FALSE) // It is not allowed to set value for a FIXED_AT_BUILD PCD\n' % SetModeName) + +## Create code for library module PCDs +# +# @param Info The ModuleAutoGen object +# @param AutoGenC The TemplateString object for C code +# @param AutoGenH The TemplateString object for header file +# @param Pcd The PCD object +# +def CreateLibraryPcdCode(Info, AutoGenC, AutoGenH, Pcd): + PcdTokenNumber = Info.PlatformInfo.PcdTokenNumber + TokenSpaceGuidCName = Pcd.TokenSpaceGuidCName + TokenCName = Pcd.TokenCName + TokenSpaceGuidValue = Pcd.TokenSpaceGuidValue #Info.GuidList[TokenSpaceGuidCName] + if (Pcd.TokenCName, Pcd.TokenSpaceGuidCName) not in PcdTokenNumber: + EdkLogger.error("build", AUTOGEN_ERROR, + "No generated token number for %s.%s\n" % (Pcd.TokenSpaceGuidCName, Pcd.TokenCName), + ExtraData="[%s]" % str(Info)) + TokenNumber = PcdTokenNumber[TokenCName, TokenSpaceGuidCName] + + if Pcd.Type not in gItemTypeStringDatabase: + EdkLogger.error("build", AUTOGEN_ERROR, + "Unknown PCD type [%s] of PCD %s.%s" % (Pcd.Type, Pcd.TokenSpaceGuidCName, Pcd.TokenCName), + ExtraData="[%s]" % str(Info)) + if Pcd.DatumType not in gDatumSizeStringDatabase: + EdkLogger.error("build", AUTOGEN_ERROR, + "Unknown datum type [%s] of PCD %s.%s" % (Pcd.DatumType, Pcd.TokenSpaceGuidCName, Pcd.TokenCName), + ExtraData="[%s]" % str(Info)) + + DatumType = Pcd.DatumType + DatumSize = gDatumSizeStringDatabaseH[DatumType] + DatumSizeLib= gDatumSizeStringDatabaseLib[DatumType] + GetModeName = '_PCD_GET_MODE_' + DatumSize + '_' + TokenCName + SetModeName = '_PCD_SET_MODE_' + DatumSize + '_' + TokenCName + + Type = '' + Array = '' + if Pcd.DatumType == 'VOID*': + Type = '(VOID *)' + Array = '[]' + + AutoGenH.Append('#define _PCD_TOKEN_%s %d\n' % (TokenCName, TokenNumber)) + + PcdItemType = Pcd.Type + #if PcdItemType in gDynamicPcd: + # PcdItemType = TAB_PCDS_FIXED_AT_BUILD + # if (TokenCName, TokenSpaceGuidCName) in Info.PlatformInfo.Platform.Pcds: + # PcdItemType = Info.PlatformInfo.Platform.Pcds[TokenCName, TokenSpaceGuidCName].Type + if PcdItemType in gDynamicExPcd: + PcdTokenName = '_PCD_TOKEN_' + TokenCName + AutoGenH.Append('#define %s LibPcdGetEx%s(&%s, %s)\n' % (GetModeName, DatumSizeLib, TokenSpaceGuidCName, PcdTokenName)) + if DatumType == 'VOID*': + AutoGenH.Append('#define %s(SizeOfBuffer, Buffer) LibPcdSetEx%s(&%s, %s, (SizeOfBuffer), (Buffer))\n' % (SetModeName,DatumSizeLib, TokenSpaceGuidCName, PcdTokenName)) + else: + AutoGenH.Append('#define %s(Value) LibPcdSetEx%s(&%s, %s, (Value))\n' % (SetModeName, DatumSizeLib, TokenSpaceGuidCName, PcdTokenName)) + if PcdItemType in gDynamicPcd: + PcdTokenName = '_PCD_TOKEN_' + TokenCName + AutoGenH.Append('#define %s LibPcdGet%s(%s)\n' % (GetModeName, DatumSizeLib, PcdTokenName)) + if DatumType == 'VOID*': + AutoGenH.Append('#define %s(SizeOfBuffer, Buffer) LibPcdSet%s(%s, (SizeOfBuffer), (Buffer))\n' %(SetModeName, DatumSizeLib, PcdTokenName)) + else: + AutoGenH.Append('#define %s(Value) LibPcdSet%s(%s, (Value))\n' % (SetModeName, DatumSizeLib, PcdTokenName)) + if PcdItemType == TAB_PCDS_PATCHABLE_IN_MODULE: + PcdVariableName = '_gPcd_' + gItemTypeStringDatabase[TAB_PCDS_PATCHABLE_IN_MODULE] + '_' + TokenCName + AutoGenH.Append('extern %s _gPcd_BinaryPatch_%s%s;\n' %(DatumType, TokenCName, Array) ) + AutoGenH.Append('#define %s %s_gPcd_BinaryPatch_%s\n' %(GetModeName, Type, TokenCName)) + AutoGenH.Append('#define %s(Value) (%s = (Value))\n' % (SetModeName, PcdVariableName)) + if PcdItemType == TAB_PCDS_FIXED_AT_BUILD or PcdItemType == TAB_PCDS_FEATURE_FLAG: + AutoGenH.Append('extern const %s _gPcd_FixedAtBuild_%s%s;\n' %(DatumType, TokenCName, Array)) + #AutoGenH.Append('#define _PCD_VALUE_%s _gPcd_FixedAtBuild_%s\n' %(TokenCName, TokenCName)) + AutoGenH.Append('#define %s %s_gPcd_FixedAtBuild_%s\n' %(GetModeName, Type, TokenCName)) + AutoGenH.Append('//#define %s ASSERT(FALSE) // It is not allowed to set value for a FIXED_AT_BUILD PCD\n' % SetModeName) + +## Create code for PCD database in DXE or PEI phase +# +# @param Platform The platform object +# @retval tuple Two TemplateString objects for C code and header file, +# respectively +# +def CreatePcdDatabasePhaseSpecificAutoGen (Platform, Phase): + AutoGenC = TemplateString() + AutoGenH = TemplateString() + + Dict = { + 'PHASE' : Phase, + 'GUID_TABLE_SIZE' : '1', + 'STRING_TABLE_SIZE' : '1', + 'SKUID_TABLE_SIZE' : '1', + 'LOCAL_TOKEN_NUMBER_TABLE_SIZE' : '1', + 'LOCAL_TOKEN_NUMBER' : '0', + 'EXMAPPING_TABLE_SIZE' : '1', + 'EX_TOKEN_NUMBER' : '0', + 'SIZE_TABLE_SIZE' : '2', + 'GUID_TABLE_EMPTY' : 'TRUE', + 'STRING_TABLE_EMPTY' : 'TRUE', + 'SKUID_TABLE_EMPTY' : 'TRUE', + 'DATABASE_EMPTY' : 'TRUE', + 'EXMAP_TABLE_EMPTY' : 'TRUE', + 'PCD_DATABASE_UNINIT_EMPTY' : ' UINT8 dummy; /* PCD_DATABASE_UNINIT is emptry */', + 'SYSTEM_SKU_ID' : ' SKU_ID SystemSkuId;', + 'SYSTEM_SKU_ID_VALUE' : '0' + } + + for DatumType in ['UINT64','UINT32','UINT16','UINT8','BOOLEAN']: + Dict['VARDEF_CNAME_' + DatumType] = [] + Dict['VARDEF_GUID_' + DatumType] = [] + Dict['VARDEF_SKUID_' + DatumType] = [] + Dict['VARDEF_VALUE_' + DatumType] = [] + for Init in ['INIT','UNINIT']: + Dict[Init+'_CNAME_DECL_' + DatumType] = [] + Dict[Init+'_GUID_DECL_' + DatumType] = [] + Dict[Init+'_NUMSKUS_DECL_' + DatumType] = [] + Dict[Init+'_VALUE_' + DatumType] = [] + + for Type in ['STRING_HEAD','VPD_HEAD','VARIABLE_HEAD']: + Dict[Type + '_CNAME_DECL'] = [] + Dict[Type + '_GUID_DECL'] = [] + Dict[Type + '_NUMSKUS_DECL'] = [] + Dict[Type + '_VALUE'] = [] + + Dict['STRING_TABLE_INDEX'] = [] + Dict['STRING_TABLE_LENGTH'] = [] + Dict['STRING_TABLE_CNAME'] = [] + Dict['STRING_TABLE_GUID'] = [] + Dict['STRING_TABLE_VALUE'] = [] + + Dict['SIZE_TABLE_CNAME'] = [] + Dict['SIZE_TABLE_GUID'] = [] + Dict['SIZE_TABLE_CURRENT_LENGTH'] = [] + Dict['SIZE_TABLE_MAXIMUM_LENGTH'] = [] + + Dict['EXMAPPING_TABLE_EXTOKEN'] = [] + Dict['EXMAPPING_TABLE_LOCAL_TOKEN'] = [] + Dict['EXMAPPING_TABLE_GUID_INDEX'] = [] + + Dict['GUID_STRUCTURE'] = [] + + Dict['SKUID_VALUE'] = [] + + if Phase == 'DXE': + Dict['SYSTEM_SKU_ID'] = '' + Dict['SYSTEM_SKU_ID_VALUE'] = '' + + StringTableIndex = 0 + StringTableSize = 0 + NumberOfLocalTokens = 0 + NumberOfPeiLocalTokens = 0 + NumberOfDxeLocalTokens = 0 + NumberOfExTokens = 0 + NumberOfSizeItems = 0 + GuidList = [] + + for Pcd in Platform.DynamicPcdList: + CName = Pcd.TokenCName + TokenSpaceGuidCName = Pcd.TokenSpaceGuidCName + + EdkLogger.debug(EdkLogger.DEBUG_3, "PCD: %s %s (%s : %s)" % (CName, TokenSpaceGuidCName, Pcd.Phase, Phase)) + if Pcd.DatumType not in gDatumSizeStringDatabase: + EdkLogger.error("build", AUTOGEN_ERROR, + "Unknown datum type [%s] of PCD %s.%s" % (Pcd.DatumType, Pcd.TokenSpaceGuidCName, Pcd.TokenCName), + ExtraData="[%s]" % str(Platform)) + + if Pcd.Phase == 'PEI': + NumberOfPeiLocalTokens += 1 + if Pcd.Phase == 'DXE': + NumberOfDxeLocalTokens += 1 + if Pcd.Phase != Phase: + continue + + # + # TODO: need GetGuidValue() definition + # + TokenSpaceGuidStructure = Pcd.TokenSpaceGuidValue + TokenSpaceGuid = GuidStructureStringToGuidValueName(TokenSpaceGuidStructure) + if Pcd.Type in gDynamicExPcd: + if TokenSpaceGuid not in GuidList: + GuidList += [TokenSpaceGuid] + Dict['GUID_STRUCTURE'].append(TokenSpaceGuidStructure) + NumberOfExTokens += 1 + + ValueList = [] + StringHeadOffsetList = [] + VpdHeadOffsetList = [] + VariableHeadValueList = [] + Pcd.InitString = 'UNINIT' + + if Pcd.DatumType == 'VOID*': + Pcd.TokenTypeList = ['PCD_DATUM_TYPE_POINTER'] + elif Pcd.DatumType == 'BOOLEAN': + Pcd.TokenTypeList = ['PCD_DATUM_TYPE_UINT8'] + else: + Pcd.TokenTypeList = ['PCD_DATUM_TYPE_' + Pcd.DatumType] + + if len(Pcd.SkuInfoList) > 1: + Pcd.TokenTypeList += ['PCD_TYPE_SKU_ENABLED'] + + for SkuName in Pcd.SkuInfoList: + Sku = Pcd.SkuInfoList[SkuName] + SkuId = Sku.SkuId + if SkuId == None or SkuId == '': + continue + + if SkuId not in Dict['SKUID_VALUE']: + Dict['SKUID_VALUE'].append(SkuId) + + SkuIdIndex = Dict['SKUID_VALUE'].index(SkuId) + if len(Sku.VariableName) > 0: + Pcd.TokenTypeList += ['PCD_TYPE_HII'] + Pcd.InitString = 'INIT' + VariableNameStructure = StringToArray(Sku.VariableName) + if VariableNameStructure not in Dict['STRING_TABLE_VALUE']: + Dict['STRING_TABLE_CNAME'].append(CName) + Dict['STRING_TABLE_GUID'].append(TokenSpaceGuid) + if StringTableIndex == 0: + Dict['STRING_TABLE_INDEX'].append('') + else: + Dict['STRING_TABLE_INDEX'].append('_%d' % StringTableIndex) + + Dict['STRING_TABLE_LENGTH'].append((len(Sku.VariableName) - 3 + 1) * 2) + Dict['STRING_TABLE_VALUE'].append(VariableNameStructure) + StringTableIndex += 1 + StringTableSize += (len(Sku.VariableName) - 3 + 1) * 2 + + VariableHeadStringIndex = 0 + for Index in range(Dict['STRING_TABLE_VALUE'].index(VariableNameStructure)): + VariableHeadStringIndex += Dict['STRING_TABLE_LENGTH'][Index] + + VariableGuidStructure = Sku.VariableGuidValue + VariableGuid = GuidStructureStringToGuidValueName(VariableGuidStructure) + if VariableGuid not in GuidList: + GuidList += [VariableGuid] + Dict['GUID_STRUCTURE'].append(VariableGuidStructure) + VariableHeadGuidIndex = GuidList.index(VariableGuid) + + VariableHeadValueList.append('%d, %d, %s, offsetof(%s_PCD_DATABASE, Init.%s_%s_VariableDefault_%s)' % + (VariableHeadGuidIndex, VariableHeadStringIndex, Sku.VariableOffset, + Phase, CName, TokenSpaceGuid, SkuIdIndex)) + Dict['VARDEF_CNAME_'+Pcd.DatumType].append(CName) + Dict['VARDEF_GUID_'+Pcd.DatumType].append(TokenSpaceGuid) + Dict['VARDEF_SKUID_'+Pcd.DatumType].append(SkuIdIndex) + Dict['VARDEF_VALUE_'+Pcd.DatumType].append(Sku.HiiDefaultValue) + elif Sku.VpdOffset != '': + Pcd.TokenTypeList += ['PCD_TYPE_VPD'] + Pcd.InitString = 'INIT' + VpdHeadOffsetList.append(Sku.VpdOffset) + else: + if Pcd.DatumType == 'VOID*': + Pcd.TokenTypeList += ['PCD_TYPE_STRING'] + Pcd.InitString = 'INIT' + if Sku.DefaultValue != '': + NumberOfSizeItems += 1 + Dict['STRING_TABLE_CNAME'].append(CName) + Dict['STRING_TABLE_GUID'].append(TokenSpaceGuid) + + if StringTableIndex == 0: + Dict['STRING_TABLE_INDEX'].append('') + else: + Dict['STRING_TABLE_INDEX'].append('_%d' % StringTableIndex) + if Sku.DefaultValue[0] == 'L': + Size = (len(Sku.DefaultValue) - 3 + 1) * 2 + Dict['STRING_TABLE_VALUE'].append(StringToArray(Sku.DefaultValue)) + elif Sku.DefaultValue[0] == '"': + Size = len(Sku.DefaultValue) - 2 + 1 + Dict['STRING_TABLE_VALUE'].append(StringToArray(Sku.DefaultValue)) + elif Sku.DefaultValue[0] == '{': + Size = len(Sku.DefaultValue.replace(',',' ').split()) + Dict['STRING_TABLE_VALUE'].append(Sku.DefaultValue) + + StringHeadOffsetList.append(str(StringTableSize)) + Dict['SIZE_TABLE_CNAME'].append(CName) + Dict['SIZE_TABLE_GUID'].append(TokenSpaceGuid) + Dict['SIZE_TABLE_CURRENT_LENGTH'].append(Size) + Dict['SIZE_TABLE_MAXIMUM_LENGTH'].append(Pcd.MaxDatumSize) + if Pcd.MaxDatumSize != '': + MaxDatumSize = int(Pcd.MaxDatumSize, 0) + if MaxDatumSize > Size: + Size = MaxDatumSize + Dict['STRING_TABLE_LENGTH'].append(Size) + StringTableIndex += 1 + StringTableSize += (Size) + else: + Pcd.TokenTypeList += ['PCD_TYPE_DATA'] + if Sku.DefaultValue == 'TRUE': + Pcd.InitString = 'INIT' + else: + try: + if int(Sku.DefaultValue, 0) != 0: + Pcd.InitString = 'INIT' + except: + pass + + # + # For UNIT64 type PCD's value, ULL should be append to avoid + # warning under linux building environment. + # + if Pcd.DatumType == "UINT64": + ValueList.append(Sku.DefaultValue + "ULL") + else: + ValueList.append(Sku.DefaultValue) + + Pcd.TokenTypeList = list(set(Pcd.TokenTypeList)) + + if 'PCD_TYPE_HII' in Pcd.TokenTypeList: + Dict['VARIABLE_HEAD_CNAME_DECL'].append(CName) + Dict['VARIABLE_HEAD_GUID_DECL'].append(TokenSpaceGuid) + Dict['VARIABLE_HEAD_NUMSKUS_DECL'].append(len(Pcd.SkuInfoList)) + Dict['VARIABLE_HEAD_VALUE'].append('{ %s }\n' % ' },\n { '.join(VariableHeadValueList)) + if 'PCD_TYPE_VPD' in Pcd.TokenTypeList: + Dict['VPD_HEAD_CNAME_DECL'].append(CName) + Dict['VPD_HEAD_GUID_DECL'].append(TokenSpaceGuid) + Dict['VPD_HEAD_NUMSKUS_DECL'].append(len(Pcd.SkuInfoList)) + Dict['VPD_HEAD_VALUE'].append('{ %s }' % ' }, { '.join(VpdHeadOffsetList)) + if 'PCD_TYPE_STRING' in Pcd.TokenTypeList: + Dict['STRING_HEAD_CNAME_DECL'].append(CName) + Dict['STRING_HEAD_GUID_DECL'].append(TokenSpaceGuid) + Dict['STRING_HEAD_NUMSKUS_DECL'].append(len(Pcd.SkuInfoList)) + Dict['STRING_HEAD_VALUE'].append(', '.join(StringHeadOffsetList)) + if 'PCD_TYPE_DATA' in Pcd.TokenTypeList: + Dict[Pcd.InitString+'_CNAME_DECL_'+Pcd.DatumType].append(CName) + Dict[Pcd.InitString+'_GUID_DECL_'+Pcd.DatumType].append(TokenSpaceGuid) + Dict[Pcd.InitString+'_NUMSKUS_DECL_'+Pcd.DatumType].append(len(Pcd.SkuInfoList)) + if Pcd.InitString == 'UNINIT': + Dict['PCD_DATABASE_UNINIT_EMPTY'] = '' + else: + Dict[Pcd.InitString+'_VALUE_'+Pcd.DatumType].append(', '.join(ValueList)) + + if Phase == 'PEI': + NumberOfLocalTokens = NumberOfPeiLocalTokens + if Phase == 'DXE': + NumberOfLocalTokens = NumberOfDxeLocalTokens + + Dict['TOKEN_INIT'] = ['' for x in range(NumberOfLocalTokens)] + Dict['TOKEN_CNAME'] = ['' for x in range(NumberOfLocalTokens)] + Dict['TOKEN_GUID'] = ['' for x in range(NumberOfLocalTokens)] + Dict['TOKEN_TYPE'] = ['' for x in range(NumberOfLocalTokens)] + + for Pcd in Platform.DynamicPcdList: + CName = Pcd.TokenCName + TokenSpaceGuidCName = Pcd.TokenSpaceGuidCName + if Pcd.Phase != Phase: + continue + + TokenSpaceGuid = GuidStructureStringToGuidValueName(Pcd.TokenSpaceGuidValue) #(Platform.PackageList, TokenSpaceGuidCName)) + GeneratedTokenNumber = Platform.PcdTokenNumber[CName, TokenSpaceGuidCName] - 1 + if Phase == 'DXE': + GeneratedTokenNumber -= NumberOfPeiLocalTokens + + EdkLogger.debug(EdkLogger.DEBUG_1, "PCD = %s.%s" % (CName, TokenSpaceGuidCName)) + EdkLogger.debug(EdkLogger.DEBUG_1, "phase = %s" % Phase) + EdkLogger.debug(EdkLogger.DEBUG_1, "GeneratedTokenNumber = %s" % str(GeneratedTokenNumber)) + + Dict['TOKEN_INIT'][GeneratedTokenNumber] = 'Init' + if Pcd.InitString == 'UNINIT': + Dict['TOKEN_INIT'][GeneratedTokenNumber] = 'Uninit' + Dict['TOKEN_CNAME'][GeneratedTokenNumber] = CName + Dict['TOKEN_GUID'][GeneratedTokenNumber] = TokenSpaceGuid + Dict['TOKEN_TYPE'][GeneratedTokenNumber] = ' | '.join(Pcd.TokenTypeList) + if Pcd.Type in gDynamicExPcd: + Dict['EXMAPPING_TABLE_EXTOKEN'].append(Pcd.TokenValue) + if Phase == 'DXE': + GeneratedTokenNumber += NumberOfPeiLocalTokens + # + # Per, PCD architecture specification, PCD Token Number is 1 based and 0 is defined as invalid token number. + # For each EX type PCD, a PCD Token Number is assigned. When the + # PCD Driver/PEIM map EX_GUID and EX_TOKEN_NUMBER to the PCD Token Number, + # the non-EX Protocol/PPI interface can be called to get/set the value. This assumption is made by + # Pcd Driver/PEIM in MdeModulePkg. + # Therefore, 1 is added to GeneratedTokenNumber to generate a PCD Token Number before being inserted + # to the EXMAPPING_TABLE. + # + Dict['EXMAPPING_TABLE_LOCAL_TOKEN'].append(GeneratedTokenNumber + 1) + Dict['EXMAPPING_TABLE_GUID_INDEX'].append(GuidList.index(TokenSpaceGuid)) + + if GuidList != []: + Dict['GUID_TABLE_EMPTY'] = 'FALSE' + Dict['GUID_TABLE_SIZE'] = len(GuidList) + else: + Dict['GUID_STRUCTURE'] = [GuidStringToGuidStructureString('00000000-0000-0000-0000-000000000000')] + + if StringTableIndex == 0: + Dict['STRING_TABLE_INDEX'].append('') + Dict['STRING_TABLE_LENGTH'].append(1) + Dict['STRING_TABLE_CNAME'].append('') + Dict['STRING_TABLE_GUID'].append('') + Dict['STRING_TABLE_VALUE'].append('{ 0 }') + else: + Dict['STRING_TABLE_EMPTY'] = 'FALSE' + Dict['STRING_TABLE_SIZE'] = StringTableSize + + if Dict['SIZE_TABLE_CNAME'] == []: + Dict['SIZE_TABLE_CNAME'].append('') + Dict['SIZE_TABLE_GUID'].append('') + Dict['SIZE_TABLE_CURRENT_LENGTH'].append(0) + Dict['SIZE_TABLE_MAXIMUM_LENGTH'].append(0) + + if NumberOfLocalTokens != 0: + Dict['DATABASE_EMPTY'] = 'FALSE' + Dict['LOCAL_TOKEN_NUMBER_TABLE_SIZE'] = NumberOfLocalTokens + Dict['LOCAL_TOKEN_NUMBER'] = NumberOfLocalTokens + + if NumberOfExTokens != 0: + Dict['EXMAP_TABLE_EMPTY'] = 'FALSE' + Dict['EXMAPPING_TABLE_SIZE'] = NumberOfExTokens + Dict['EX_TOKEN_NUMBER'] = NumberOfExTokens + else: + Dict['EXMAPPING_TABLE_EXTOKEN'].append(0) + Dict['EXMAPPING_TABLE_LOCAL_TOKEN'].append(0) + Dict['EXMAPPING_TABLE_GUID_INDEX'].append(0) + + if NumberOfSizeItems != 0: + Dict['SIZE_TABLE_SIZE'] = NumberOfSizeItems * 2 + + AutoGenH.Append(gPcdDatabaseAutoGenH.Replace(Dict)) + if NumberOfLocalTokens == 0: + AutoGenC.Append(gEmptyPcdDatabaseAutoGenC.Replace(Dict)) + else: + AutoGenC.Append(gPcdDatabaseAutoGenC.Replace(Dict)) + + return AutoGenH, AutoGenC + +## Create code for PCD database +# +# @param Info The ModuleAutoGen object +# @param AutoGenC The TemplateString object for C code +# @param AutoGenH The TemplateString object for header file +# +def CreatePcdDatabaseCode (Info, AutoGenC, AutoGenH): + if Info.PcdIsDriver == "": + return + if Info.PcdIsDriver not in gPcdPhaseMap: + EdkLogger.error("build", AUTOGEN_ERROR, "Not supported PcdIsDriver type:%s" % Info.PcdIsDriver, + ExtraData="[%s]" % str(Info)) + + AutoGenH.Append(gPcdDatabaseCommonAutoGenH) + AdditionalAutoGenH, AdditionalAutoGenC = CreatePcdDatabasePhaseSpecificAutoGen (Info.PlatformInfo, 'PEI') + AutoGenH.Append(AdditionalAutoGenH.String) + + Phase = gPcdPhaseMap[Info.PcdIsDriver] + if Phase == 'PEI': + AutoGenC.Append(AdditionalAutoGenC.String) + + if Phase == 'DXE': + AdditionalAutoGenH, AdditionalAutoGenC = CreatePcdDatabasePhaseSpecificAutoGen (Info.PlatformInfo, Phase) + AutoGenH.Append(AdditionalAutoGenH.String) + AutoGenC.Append(AdditionalAutoGenC.String) + AutoGenH.Append(gPcdDatabaseEpilogueAutoGenH) + +## Create code for library constructor +# +# @param Info The ModuleAutoGen object +# @param AutoGenC The TemplateString object for C code +# @param AutoGenH The TemplateString object for header file +# +def CreateLibraryConstructorCode(Info, AutoGenC, AutoGenH): + # + # Library Constructors + # + ConstructorPrototypeString = TemplateString() + ConstructorCallingString = TemplateString() + if Info.IsLibrary: + DependentLibraryList = [Info.Module] + else: + DependentLibraryList = Info.DependentLibraryList + for Lib in DependentLibraryList: + if len(Lib.ConstructorList) <= 0: + continue + Dict = {'Function':Lib.ConstructorList} + if Lib.ModuleType in ['BASE', 'SEC']: + ConstructorPrototypeString.Append(gLibraryStructorPrototype['BASE'].Replace(Dict)) + ConstructorCallingString.Append(gLibraryStructorCall['BASE'].Replace(Dict)) + elif Lib.ModuleType in ['PEI_CORE','PEIM']: + ConstructorPrototypeString.Append(gLibraryStructorPrototype['PEI'].Replace(Dict)) + ConstructorCallingString.Append(gLibraryStructorCall['PEI'].Replace(Dict)) + elif Lib.ModuleType in ['DXE_CORE','DXE_DRIVER','DXE_SMM_DRIVER','DXE_RUNTIME_DRIVER', + 'DXE_SAL_DRIVER','UEFI_DRIVER','UEFI_APPLICATION', 'SMM_DRIVER', 'SMM_CORE']: + ConstructorPrototypeString.Append(gLibraryStructorPrototype['DXE'].Replace(Dict)) + ConstructorCallingString.Append(gLibraryStructorCall['DXE'].Replace(Dict)) + + if str(ConstructorPrototypeString) == '': + ConstructorPrototypeList = [] + else: + ConstructorPrototypeList = [str(ConstructorPrototypeString)] + if str(ConstructorCallingString) == '': + ConstructorCallingList = [] + else: + ConstructorCallingList = [str(ConstructorCallingString)] + + Dict = { + 'Type' : 'Constructor', + 'FunctionPrototype' : ConstructorPrototypeList, + 'FunctionCall' : ConstructorCallingList + } + if Info.IsLibrary: + AutoGenH.Append("${BEGIN}${FunctionPrototype}${END}", Dict) + else: + if Info.ModuleType in ['BASE', 'SEC']: + AutoGenC.Append(gLibraryString['BASE'].Replace(Dict)) + elif Info.ModuleType in ['PEI_CORE','PEIM']: + AutoGenC.Append(gLibraryString['PEI'].Replace(Dict)) + elif Info.ModuleType in ['DXE_CORE','DXE_DRIVER','DXE_SMM_DRIVER','DXE_RUNTIME_DRIVER', + 'DXE_SAL_DRIVER','UEFI_DRIVER','UEFI_APPLICATION', 'SMM_DRIVER', 'SMM_CORE']: + AutoGenC.Append(gLibraryString['DXE'].Replace(Dict)) + +## Create code for library destructor +# +# @param Info The ModuleAutoGen object +# @param AutoGenC The TemplateString object for C code +# @param AutoGenH The TemplateString object for header file +# +def CreateLibraryDestructorCode(Info, AutoGenC, AutoGenH): + # + # Library Destructors + # + DestructorPrototypeString = TemplateString() + DestructorCallingString = TemplateString() + if Info.IsLibrary: + DependentLibraryList = [Info.Module] + else: + DependentLibraryList = Info.DependentLibraryList + for Index in range(len(DependentLibraryList)-1, -1, -1): + Lib = DependentLibraryList[Index] + if len(Lib.DestructorList) <= 0: + continue + Dict = {'Function':Lib.DestructorList} + if Lib.ModuleType in ['BASE', 'SEC']: + DestructorPrototypeString.Append(gLibraryStructorPrototype['BASE'].Replace(Dict)) + DestructorCallingString.Append(gLibraryStructorCall['BASE'].Replace(Dict)) + elif Lib.ModuleType in ['PEI_CORE','PEIM']: + DestructorPrototypeString.Append(gLibraryStructorPrototype['PEI'].Replace(Dict)) + DestructorCallingString.Append(gLibraryStructorCall['PEI'].Replace(Dict)) + elif Lib.ModuleType in ['DXE_CORE','DXE_DRIVER','DXE_SMM_DRIVER','DXE_RUNTIME_DRIVER', + 'DXE_SAL_DRIVER','UEFI_DRIVER','UEFI_APPLICATION', 'SMM_DRIVER', 'SMM_CORE']: + DestructorPrototypeString.Append(gLibraryStructorPrototype['DXE'].Replace(Dict)) + DestructorCallingString.Append(gLibraryStructorCall['DXE'].Replace(Dict)) + + if str(DestructorPrototypeString) == '': + DestructorPrototypeList = [] + else: + DestructorPrototypeList = [str(DestructorPrototypeString)] + if str(DestructorCallingString) == '': + DestructorCallingList = [] + else: + DestructorCallingList = [str(DestructorCallingString)] + + Dict = { + 'Type' : 'Destructor', + 'FunctionPrototype' : DestructorPrototypeList, + 'FunctionCall' : DestructorCallingList + } + if Info.IsLibrary: + AutoGenH.Append("${BEGIN}${FunctionPrototype}${END}", Dict) + else: + if Info.ModuleType in ['BASE', 'SEC']: + AutoGenC.Append(gLibraryString['BASE'].Replace(Dict)) + elif Info.ModuleType in ['PEI_CORE','PEIM']: + AutoGenC.Append(gLibraryString['PEI'].Replace(Dict)) + elif Info.ModuleType in ['DXE_CORE','DXE_DRIVER','DXE_SMM_DRIVER','DXE_RUNTIME_DRIVER', + 'DXE_SAL_DRIVER','UEFI_DRIVER','UEFI_APPLICATION', 'SMM_DRIVER', 'SMM_CORE']: + AutoGenC.Append(gLibraryString['DXE'].Replace(Dict)) + + +## Create code for ModuleEntryPoint +# +# @param Info The ModuleAutoGen object +# @param AutoGenC The TemplateString object for C code +# @param AutoGenH The TemplateString object for header file +# +def CreateModuleEntryPointCode(Info, AutoGenC, AutoGenH): + if Info.IsLibrary or Info.ModuleType in ['USER_DEFINED', 'SEC']: + return + # + # Module Entry Points + # + NumEntryPoints = len(Info.Module.ModuleEntryPointList) + if 'PI_SPECIFICATION_VERSION' in Info.Module.Specification: + PiSpecVersion = Info.Module.Specification['PI_SPECIFICATION_VERSION'] + else: + PiSpecVersion = 0 + if 'EFI_SPECIFICATION_VERSION' in Info.Module.Specification: + EfiSpecVersion = Info.Module.Specification['EFI_SPECIFICATION_VERSION'] + else: + EfiSpecVersion = 0 + Dict = { + 'Function' : Info.Module.ModuleEntryPointList, + 'PiSpecVersion' : PiSpecVersion, + 'EfiSpecVersion': EfiSpecVersion + } + + if Info.ModuleType in ['PEI_CORE', 'DXE_CORE', 'SMM_CORE']: + if NumEntryPoints != 1: + EdkLogger.error( + "build", + AUTOGEN_ERROR, + '%s must have exactly one entry point' % Info.ModuleType, + File=str(Info), + ExtraData= ", ".join(Info.Module.ModuleEntryPointList) + ) + if Info.ModuleType == 'PEI_CORE': + AutoGenC.Append(gPeiCoreEntryPointString.Replace(Dict)) + AutoGenH.Append(gPeiCoreEntryPointPrototype.Replace(Dict)) + elif Info.ModuleType == 'DXE_CORE': + AutoGenC.Append(gDxeCoreEntryPointString.Replace(Dict)) + AutoGenH.Append(gDxeCoreEntryPointPrototype.Replace(Dict)) + elif Info.ModuleType == 'SMM_CORE': + AutoGenC.Append(gSmmCoreEntryPointString.Replace(Dict)) + elif Info.ModuleType == 'PEIM': + if NumEntryPoints < 2: + AutoGenC.Append(gPeimEntryPointString[NumEntryPoints].Replace(Dict)) + else: + AutoGenC.Append(gPeimEntryPointString[2].Replace(Dict)) + AutoGenH.Append(gPeimEntryPointPrototype.Replace(Dict)) + elif Info.ModuleType in ['DXE_RUNTIME_DRIVER','DXE_DRIVER','DXE_SMM_DRIVER', + 'DXE_SAL_DRIVER','UEFI_DRIVER', 'SMM_DRIVER']: + if Info.ModuleType in ['DXE_SMM_DRIVER', 'SMM_DRIVER']: + if NumEntryPoints == 0: + AutoGenC.Append(gDxeSmmEntryPointString[0].Replace(Dict)) + else: + AutoGenC.Append(gDxeSmmEntryPointString[1].Replace(Dict)) + AutoGenH.Append(gDxeSmmEntryPointPrototype.Replace(Dict)) + else: + if NumEntryPoints < 2: + AutoGenC.Append(gUefiDriverEntryPointString[NumEntryPoints].Replace(Dict)) + else: + AutoGenC.Append(gUefiDriverEntryPointString[2].Replace(Dict)) + AutoGenH.Append(gUefiDriverEntryPointPrototype.Replace(Dict)) + elif Info.ModuleType == 'UEFI_APPLICATION': + if NumEntryPoints < 2: + AutoGenC.Append(gUefiApplicationEntryPointString[NumEntryPoints].Replace(Dict)) + else: + AutoGenC.Append(gUefiApplicationEntryPointString[2].Replace(Dict)) + AutoGenH.Append(gUefiApplicationEntryPointPrototype.Replace(Dict)) + +## Create code for ModuleUnloadImage +# +# @param Info The ModuleAutoGen object +# @param AutoGenC The TemplateString object for C code +# @param AutoGenH The TemplateString object for header file +# +def CreateModuleUnloadImageCode(Info, AutoGenC, AutoGenH): + if Info.IsLibrary or Info.ModuleType in ['USER_DEFINED', 'SEC']: + return + # + # Unload Image Handlers + # + NumUnloadImage = len(Info.Module.ModuleUnloadImageList) + Dict = {'Count':NumUnloadImage, 'Function':Info.Module.ModuleUnloadImageList} + if NumUnloadImage < 2: + AutoGenC.Append(gUefiUnloadImageString[NumUnloadImage].Replace(Dict)) + else: + AutoGenC.Append(gUefiUnloadImageString[2].Replace(Dict)) + AutoGenH.Append(gUefiUnloadImagePrototype.Replace(Dict)) + +## Create code for GUID +# +# @param Info The ModuleAutoGen object +# @param AutoGenC The TemplateString object for C code +# @param AutoGenH The TemplateString object for header file +# +def CreateGuidDefinitionCode(Info, AutoGenC, AutoGenH): + if Info.IsLibrary: + return + + if Info.ModuleType in ["USER_DEFINED", "BASE"]: + GuidType = "GUID" + else: + GuidType = "EFI_GUID" + + if Info.GuidList: + AutoGenC.Append("\n// Guids\n") + # + # GUIDs + # + for Key in Info.GuidList: + AutoGenC.Append('GLOBAL_REMOVE_IF_UNREFERENCED %s %s = %s;\n' % (GuidType, Key, Info.GuidList[Key])) + +## Create code for protocol +# +# @param Info The ModuleAutoGen object +# @param AutoGenC The TemplateString object for C code +# @param AutoGenH The TemplateString object for header file +# +def CreateProtocolDefinitionCode(Info, AutoGenC, AutoGenH): + if Info.IsLibrary: + return + + if Info.ModuleType in ["USER_DEFINED", "BASE"]: + GuidType = "GUID" + else: + GuidType = "EFI_GUID" + + if Info.ProtocolList: + AutoGenC.Append("\n// Protocols\n") + # + # Protocol GUIDs + # + for Key in Info.ProtocolList: + AutoGenC.Append('GLOBAL_REMOVE_IF_UNREFERENCED %s %s = %s;\n' % (GuidType, Key, Info.ProtocolList[Key])) + +## Create code for PPI +# +# @param Info The ModuleAutoGen object +# @param AutoGenC The TemplateString object for C code +# @param AutoGenH The TemplateString object for header file +# +def CreatePpiDefinitionCode(Info, AutoGenC, AutoGenH): + if Info.IsLibrary: + return + + if Info.ModuleType in ["USER_DEFINED", "BASE"]: + GuidType = "GUID" + else: + GuidType = "EFI_GUID" + + if Info.PpiList: + AutoGenC.Append("\n// PPIs\n") + # + # PPI GUIDs + # + for Key in Info.PpiList: + AutoGenC.Append('GLOBAL_REMOVE_IF_UNREFERENCED %s %s = %s;\n' % (GuidType, Key, Info.PpiList[Key])) + +## Create code for PCD +# +# @param Info The ModuleAutoGen object +# @param AutoGenC The TemplateString object for C code +# @param AutoGenH The TemplateString object for header file +# +def CreatePcdCode(Info, AutoGenC, AutoGenH): + if Info.IsLibrary: + if Info.ModulePcdList: + AutoGenH.Append("\n// PCD definitions\n") + for Pcd in Info.ModulePcdList: + CreateLibraryPcdCode(Info, AutoGenC, AutoGenH, Pcd) + else: + if Info.ModulePcdList: + AutoGenH.Append("\n// Definition of PCDs used in this module\n") + AutoGenC.Append("\n// Definition of PCDs used in this module\n") + for Pcd in Info.ModulePcdList: + CreateModulePcdCode(Info, AutoGenC, AutoGenH, Pcd) + + if Info.LibraryPcdList: + AutoGenH.Append("\n// Definition of PCDs used in libraries is in AutoGen.c\n") + AutoGenC.Append("\n// Definition of PCDs used in libraries\n") + for Pcd in Info.LibraryPcdList: + CreateModulePcdCode(Info, AutoGenC, AutoGenC, Pcd) + CreatePcdDatabaseCode(Info, AutoGenC, AutoGenH) + +## Create code for unicode string definition +# +# @param Info The ModuleAutoGen object +# @param AutoGenC The TemplateString object for C code +# @param AutoGenH The TemplateString object for header file +# +def CreateUnicodeStringCode(Info, AutoGenC, AutoGenH): + WorkingDir = os.getcwd() + os.chdir(Info.WorkspaceDir) + + IncList = [Info.MetaFile.Dir] + # Get all files under [Sources] section in inf file for EDK-II module + SrcList = [F for F in Info.SourceFileList] + if Info.AutoGenVersion < 0x00010005: + # Get all files under the module directory for EDK-I module + Cwd = os.getcwd() + os.chdir(Info.MetaFile.Dir) + for Root, Dirs, Files in os.walk("."): + if 'CVS' in Dirs: + Dirs.remove('CVS') + if '.svn' in Dirs: + Dirs.remove('.svn') + for File in Files: + File = PathClass(os.path.join(Root, File), Info.MetaFile.Dir) + if File in SrcList: + continue + SrcList.append(File) + os.chdir(Cwd) + + if 'BUILD' in Info.BuildOption and Info.BuildOption['BUILD']['FLAGS'].find('-c') > -1: + CompatibleMode = True + else: + CompatibleMode = False + + # + # -s is a temporary option dedicated for building .UNI files with ISO 639-2 lanauge codes of EDK Shell in EDK2 + # + if 'BUILD' in Info.BuildOption and Info.BuildOption['BUILD']['FLAGS'].find('-s') > -1: + if CompatibleMode: + EdkLogger.error("build", AUTOGEN_ERROR, + "-c and -s build options should be used exclusively", + ExtraData="[%s]" % str(Info)) + ShellMode = True + else: + ShellMode = False + + Header, Code = GetStringFiles(Info.UnicodeFileList, SrcList, IncList, ['.uni', '.inf'], Info.Name, CompatibleMode, ShellMode) + AutoGenC.Append("\n//\n//Unicode String Pack Definition\n//\n") + AutoGenC.Append(Code) + AutoGenC.Append("\n") + AutoGenH.Append("\n//\n//Unicode String ID\n//\n") + AutoGenH.Append(Header) + AutoGenH.Append("\n#define STRING_ARRAY_NAME %sStrings\n" % Info.Name) + os.chdir(WorkingDir) + +## Create common code +# +# @param Info The ModuleAutoGen object +# @param AutoGenC The TemplateString object for C code +# @param AutoGenH The TemplateString object for header file +# +def CreateHeaderCode(Info, AutoGenC, AutoGenH): + # file header + AutoGenH.Append(gAutoGenHeaderString.Replace({'FileName':'AutoGen.h'})) + # header file Prologue + AutoGenH.Append(gAutoGenHPrologueString.Replace({'File':'AUTOGENH','Guid':Info.Guid.replace('-','_')})) + if Info.AutoGenVersion >= 0x00010005: + # specification macros + AutoGenH.Append(gSpecificationString.Replace({'SpecificationName':Info.Specification.keys(), + 'SpecificationValue':Info.Specification.values()})) + # header files includes + AutoGenH.Append("#include <%s>\n" % gBasicHeaderFile) + if Info.ModuleType in gModuleTypeHeaderFile \ + and gModuleTypeHeaderFile[Info.ModuleType][0] != gBasicHeaderFile: + AutoGenH.Append("#include <%s>\n" % gModuleTypeHeaderFile[Info.ModuleType][0]) + AutoGenH.Append('\nextern GUID gEfiCallerIdGuid;\n\n') + + if Info.IsLibrary: + return + + AutoGenH.Append("#define EFI_CALLER_ID_GUID \\\n %s\n" % GuidStringToGuidStructureString(Info.Guid)) + + if Info.IsLibrary: + return + # C file header + AutoGenC.Append(gAutoGenHeaderString.Replace({'FileName':'AutoGen.c'})) + if Info.AutoGenVersion >= 0x00010005: + # C file header files includes + if Info.ModuleType in gModuleTypeHeaderFile: + for Inc in gModuleTypeHeaderFile[Info.ModuleType]: + AutoGenC.Append("#include <%s>\n" % Inc) + else: + AutoGenC.Append("#include <%s>\n" % gBasicHeaderFile) + + # + # Publish the CallerId Guid + # + AutoGenC.Append('\nGLOBAL_REMOVE_IF_UNREFERENCED GUID gEfiCallerIdGuid = %s;\n' % GuidStringToGuidStructureString(Info.Guid)) + +## Create common code for header file +# +# @param Info The ModuleAutoGen object +# @param AutoGenC The TemplateString object for C code +# @param AutoGenH The TemplateString object for header file +# +def CreateFooterCode(Info, AutoGenC, AutoGenH): + AutoGenH.Append(gAutoGenHEpilogueString) + +## Create code for a module +# +# @param Info The ModuleAutoGen object +# @param AutoGenC The TemplateString object for C code +# @param AutoGenH The TemplateString object for header file +# +def CreateCode(Info, AutoGenC, AutoGenH, StringH): + CreateHeaderCode(Info, AutoGenC, AutoGenH) + + if Info.AutoGenVersion >= 0x00010005: + CreateGuidDefinitionCode(Info, AutoGenC, AutoGenH) + CreateProtocolDefinitionCode(Info, AutoGenC, AutoGenH) + CreatePpiDefinitionCode(Info, AutoGenC, AutoGenH) + CreatePcdCode(Info, AutoGenC, AutoGenH) + CreateLibraryConstructorCode(Info, AutoGenC, AutoGenH) + CreateLibraryDestructorCode(Info, AutoGenC, AutoGenH) + CreateModuleEntryPointCode(Info, AutoGenC, AutoGenH) + CreateModuleUnloadImageCode(Info, AutoGenC, AutoGenH) + + if Info.UnicodeFileList: + FileName = "%sStrDefs.h" % Info.Name + StringH.Append(gAutoGenHeaderString.Replace({'FileName':FileName})) + StringH.Append(gAutoGenHPrologueString.Replace({'File':'STRDEFS', 'Guid':Info.Guid.replace('-','_')})) + CreateUnicodeStringCode(Info, AutoGenC, StringH) + StringH.Append("\n#endif\n") + AutoGenH.Append('#include "%s"\n' % FileName) + + CreateFooterCode(Info, AutoGenC, AutoGenH) + + # no generation of AutoGen.c for R8 modules without unicode file + if Info.AutoGenVersion < 0x00010005 and len(Info.UnicodeFileList) == 0: + AutoGenC.String = '' + +## Create the code file +# +# @param FilePath The path of code file +# @param Content The content of code file +# +# @retval True If file content is changed or file doesn't exist +# @retval False If the file exists and the content is not changed +# +def Generate(FilePath, Content): + return SaveFileOnChange(FilePath, Content, False) + diff --git a/BaseTools/Source/Python/AutoGen/GenDepex.py b/BaseTools/Source/Python/AutoGen/GenDepex.py new file mode 100644 index 0000000000..a3d07b83f2 --- /dev/null +++ b/BaseTools/Source/Python/AutoGen/GenDepex.py @@ -0,0 +1,441 @@ +## @file +# This file is used to generate DEPEX file for module's dependency expression +# +# Copyright (c) 2007, 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. + +## Import Modules +# +import sys +import os +import re +import traceback + +from StringIO import StringIO +from struct import pack +from Common.BuildToolError import * +from Common.Misc import SaveFileOnChange +from Common.Misc import GuidStructureStringToGuidString +from Common import EdkLogger as EdkLogger + + +## Regular expression for matching "DEPENDENCY_START ... DEPENDENCY_END" +gStartClosePattern = re.compile(".*DEPENDENCY_START(.+)DEPENDENCY_END.*", re.S) + +## Mapping between module type and EFI phase +gType2Phase = { + "BASE" : None, + "SEC" : "PEI", + "PEI_CORE" : "PEI", + "PEIM" : "PEI", + "DXE_CORE" : "DXE", + "DXE_DRIVER" : "DXE", + "DXE_SMM_DRIVER" : "DXE", + "DXE_RUNTIME_DRIVER": "DXE", + "DXE_SAL_DRIVER" : "DXE", + "UEFI_DRIVER" : "DXE", + "UEFI_APPLICATION" : "DXE", + "SMM_DRIVER" : "DXE", +} + +## Convert dependency expression string into EFI internal representation +# +# DependencyExpression class is used to parse dependency expression string and +# convert it into its binary form. +# +class DependencyExpression: + + ArchProtocols = set([ + '665e3ff6-46cc-11d4-9a38-0090273fc14d', # 'gEfiBdsArchProtocolGuid' + '26baccb1-6f42-11d4-bce7-0080c73c8881', # 'gEfiCpuArchProtocolGuid' + '26baccb2-6f42-11d4-bce7-0080c73c8881', # 'gEfiMetronomeArchProtocolGuid' + '1da97072-bddc-4b30-99f1-72a0b56fff2a', # 'gEfiMonotonicCounterArchProtocolGuid' + '27cfac87-46cc-11d4-9a38-0090273fc14d', # 'gEfiRealTimeClockArchProtocolGuid' + '27cfac88-46cc-11d4-9a38-0090273fc14d', # 'gEfiResetArchProtocolGuid' + 'b7dfb4e1-052f-449f-87be-9818fc91b733', # 'gEfiRuntimeArchProtocolGuid' + 'a46423e3-4617-49f1-b9ff-d1bfa9115839', # 'gEfiSecurityArchProtocolGuid' + '26baccb3-6f42-11d4-bce7-0080c73c8881', # 'gEfiTimerArchProtocolGuid' + '6441f818-6362-4e44-b570-7dba31dd2453', # 'gEfiVariableWriteArchProtocolGuid' + '1e5668e2-8481-11d4-bcf1-0080c73c8881', # 'gEfiVariableArchProtocolGuid' + '665e3ff5-46cc-11d4-9a38-0090273fc14d' # 'gEfiWatchdogTimerArchProtocolGuid' + ] + ) + + OpcodePriority = { + "AND" : 1, + "OR" : 1, + "NOT" : 2, + # "SOR" : 9, + # "BEFORE": 9, + # "AFTER" : 9, + } + + Opcode = { + "PEI" : { + "PUSH" : 0x02, + "AND" : 0x03, + "OR" : 0x04, + "NOT" : 0x05, + "TRUE" : 0x06, + "FALSE" : 0x07, + "END" : 0x08 + }, + + "DXE" : { + "BEFORE": 0x00, + "AFTER" : 0x01, + "PUSH" : 0x02, + "AND" : 0x03, + "OR" : 0x04, + "NOT" : 0x05, + "TRUE" : 0x06, + "FALSE" : 0x07, + "END" : 0x08, + "SOR" : 0x09 + } + } + + # all supported op codes and operands + SupportedOpcode = ["BEFORE", "AFTER", "PUSH", "AND", "OR", "NOT", "END", "SOR"] + SupportedOperand = ["TRUE", "FALSE"] + + OpcodeWithSingleOperand = ['NOT', 'BEFORE', 'AFTER'] + OpcodeWithTwoOperand = ['AND', 'OR'] + + # op code that should not be the last one + NonEndingOpcode = ["AND", "OR", "NOT", 'SOR'] + # op code must not present at the same time + ExclusiveOpcode = ["BEFORE", "AFTER"] + # op code that should be the first one if it presents + AboveAllOpcode = ["SOR", "BEFORE", "AFTER"] + + # + # open and close brace must be taken as individual tokens + # + TokenPattern = re.compile("(\(|\)|\{[^{}]+\{?[^{}]+\}?[ ]*\}|\w+)") + + ## Constructor + # + # @param Expression The list or string of dependency expression + # @param ModuleType The type of the module using the dependency expression + # + def __init__(self, Expression, ModuleType, Optimize=False): + self.ModuleType = ModuleType + self.Phase = gType2Phase[ModuleType] + if type(Expression) == type([]): + self.ExpressionString = " ".join(Expression) + self.TokenList = Expression + else: + self.ExpressionString = Expression + self.GetExpressionTokenList() + + self.PostfixNotation = [] + self.OpcodeList = [] + + self.GetPostfixNotation() + self.ValidateOpcode() + + EdkLogger.debug(EdkLogger.DEBUG_8, repr(self)) + if Optimize: + self.Optimize() + EdkLogger.debug(EdkLogger.DEBUG_8, "\n Optimized: " + repr(self)) + + def __str__(self): + return " ".join(self.TokenList) + + def __repr__(self): + WellForm = '' + for Token in self.PostfixNotation: + if Token in self.SupportedOpcode: + WellForm += "\n " + Token + else: + WellForm += ' ' + Token + return WellForm + + ## Split the expression string into token list + def GetExpressionTokenList(self): + self.TokenList = self.TokenPattern.findall(self.ExpressionString) + + ## Convert token list into postfix notation + def GetPostfixNotation(self): + Stack = [] + LastToken = '' + for Token in self.TokenList: + if Token == "(": + if LastToken not in self.SupportedOpcode + ['(', '', None]: + EdkLogger.error("GenDepex", PARSER_ERROR, "Invalid dependency expression: missing operator before open parentheses", + ExtraData="Near %s" % LastToken) + Stack.append(Token) + elif Token == ")": + if '(' not in Stack: + EdkLogger.error("GenDepex", PARSER_ERROR, "Invalid dependency expression: mismatched parentheses", + ExtraData=str(self)) + elif LastToken in self.SupportedOpcode + ['', None]: + EdkLogger.error("GenDepex", PARSER_ERROR, "Invalid dependency expression: missing operand before close parentheses", + ExtraData="Near %s" % LastToken) + while len(Stack) > 0: + if Stack[-1] == '(': + Stack.pop() + break + self.PostfixNotation.append(Stack.pop()) + elif Token in self.OpcodePriority: + if Token == "NOT": + if LastToken not in self.SupportedOpcode + ['(', '', None]: + EdkLogger.error("GenDepex", PARSER_ERROR, "Invalid dependency expression: missing operator before NOT", + ExtraData="Near %s" % LastToken) + elif LastToken in self.SupportedOpcode + ['(', '', None]: + EdkLogger.error("GenDepex", PARSER_ERROR, "Invalid dependency expression: missing operand before " + Token, + ExtraData="Near %s" % LastToken) + + while len(Stack) > 0: + if Stack[-1] == "(" or self.OpcodePriority[Token] >= self.OpcodePriority[Stack[-1]]: + break + self.PostfixNotation.append(Stack.pop()) + Stack.append(Token) + self.OpcodeList.append(Token) + else: + if Token not in self.SupportedOpcode: + # not OP, take it as GUID + if LastToken not in self.SupportedOpcode + ['(', '', None]: + EdkLogger.error("GenDepex", PARSER_ERROR, "Invalid dependency expression: missing operator before %s" % Token, + ExtraData="Near %s" % LastToken) + if len(self.OpcodeList) == 0 or self.OpcodeList[-1] not in self.ExclusiveOpcode: + if Token not in self.SupportedOperand: + self.PostfixNotation.append("PUSH") + # check if OP is valid in this phase + elif Token in self.Opcode[self.Phase]: + if Token == "END": + break + self.OpcodeList.append(Token) + else: + EdkLogger.error("GenDepex", PARSER_ERROR, + "Opcode=%s doesn't supported in %s stage " % (Token, self.Phase), + ExtraData=str(self)) + self.PostfixNotation.append(Token) + LastToken = Token + + # there should not be parentheses in Stack + if '(' in Stack or ')' in Stack: + EdkLogger.error("GenDepex", PARSER_ERROR, "Invalid dependency expression: mismatched parentheses", + ExtraData=str(self)) + while len(Stack) > 0: + self.PostfixNotation.append(Stack.pop()) + if self.PostfixNotation[-1] != 'END': + self.PostfixNotation.append("END") + + ## Validate the dependency expression + def ValidateOpcode(self): + for Op in self.AboveAllOpcode: + if Op in self.PostfixNotation: + if Op != self.PostfixNotation[0]: + EdkLogger.error("GenDepex", PARSER_ERROR, "%s should be the first opcode in the expression" % Op, + ExtraData=str(self)) + if len(self.PostfixNotation) < 3: + EdkLogger.error("GenDepex", PARSER_ERROR, "Missing operand for %s" % Op, + ExtraData=str(self)) + for Op in self.ExclusiveOpcode: + if Op in self.OpcodeList: + if len(self.OpcodeList) > 1: + EdkLogger.error("GenDepex", PARSER_ERROR, "%s should be the only opcode in the expression" % Op, + ExtraData=str(self)) + if len(self.PostfixNotation) < 3: + EdkLogger.error("GenDepex", PARSER_ERROR, "Missing operand for %s" % Op, + ExtraData=str(self)) + if self.TokenList[-1] != 'END' and self.TokenList[-1] in self.NonEndingOpcode: + EdkLogger.error("GenDepex", PARSER_ERROR, "Extra %s at the end of the dependency expression" % self.TokenList[-1], + ExtraData=str(self)) + if self.TokenList[-1] == 'END' and self.TokenList[-2] in self.NonEndingOpcode: + EdkLogger.error("GenDepex", PARSER_ERROR, "Extra %s at the end of the dependency expression" % self.TokenList[-2], + ExtraData=str(self)) + if "END" in self.TokenList and "END" != self.TokenList[-1]: + EdkLogger.error("GenDepex", PARSER_ERROR, "Extra expressions after END", + ExtraData=str(self)) + + ## Simply optimize the dependency expression by removing duplicated operands + def Optimize(self): + ValidOpcode = list(set(self.OpcodeList)) + if len(ValidOpcode) != 1 or ValidOpcode[0] not in ['AND', 'OR']: + return + Op = ValidOpcode[0] + NewOperand = [] + AllOperand = set() + for Token in self.PostfixNotation: + if Token in self.SupportedOpcode or Token in NewOperand: + continue + AllOperand.add(Token) + if Token == 'TRUE': + if Op == 'AND': + continue + else: + NewOperand.append(Token) + break + elif Token == 'FALSE': + if Op == 'OR': + continue + else: + NewOperand.append(Token) + break + NewOperand.append(Token) + + # don't generate depex if only TRUE operand left + if self.ModuleType == 'PEIM' and len(NewOperand) == 1 and NewOperand[0] == 'TRUE': + self.PostfixNotation = [] + return + + # don't generate depex if all operands are architecture protocols + if self.ModuleType in ['UEFI_DRIVER', 'DXE_DRIVER', 'DXE_RUNTIME_DRIVER', 'DXE_SAL_DRIVER', 'DXE_SMM_DRIVER'] and \ + Op == 'AND' and \ + self.ArchProtocols == set([GuidStructureStringToGuidString(Guid) for Guid in AllOperand]): + self.PostfixNotation = [] + return + + if len(NewOperand) == 0: + self.TokenList = list(AllOperand) + else: + self.TokenList = [] + while True: + self.TokenList.append(NewOperand.pop(0)) + if NewOperand == []: + break + self.TokenList.append(Op) + self.PostfixNotation = [] + self.GetPostfixNotation() + + + ## Convert a GUID value in C structure format into its binary form + # + # @param Guid The GUID value in C structure format + # + # @retval array The byte array representing the GUID value + # + def GetGuidValue(self, Guid): + GuidValueString = Guid.replace("{", "").replace("}", "").replace(" ", "") + GuidValueList = GuidValueString.split(",") + if len(GuidValueList) != 11: + EdkLogger.error("GenDepex", PARSER_ERROR, "Invalid GUID value string or opcode: %s" % Guid) + return pack("1I2H8B", *(int(value, 16) for value in GuidValueList)) + + ## Save the binary form of dependency expression in file + # + # @param File The path of file. If None is given, put the data on console + # + # @retval True If the file doesn't exist or file is changed + # @retval False If file exists and is not changed. + # + def Generate(self, File=None): + Buffer = StringIO() + if len(self.PostfixNotation) == 0: + return False + + for Item in self.PostfixNotation: + if Item in self.Opcode[self.Phase]: + Buffer.write(pack("B", self.Opcode[self.Phase][Item])) + elif Item in self.SupportedOpcode: + EdkLogger.error("GenDepex", FORMAT_INVALID, + "Opcode [%s] is not expected in %s phase" % (Item, self.Phase), + ExtraData=self.ExpressionString) + else: + Buffer.write(self.GetGuidValue(Item)) + + FilePath = "" + FileChangeFlag = True + if File == None: + sys.stdout.write(Buffer.getvalue()) + FilePath = "STDOUT" + else: + FileChangeFlag = SaveFileOnChange(File, Buffer.getvalue(), True) + + Buffer.close() + return FileChangeFlag + +versionNumber = "0.04" +__version__ = "%prog Version " + versionNumber +__copyright__ = "Copyright (c) 2007-2008, Intel Corporation All rights reserved." +__usage__ = "%prog [options] [dependency_expression_file]" + +## Parse command line options +# +# @retval OptionParser +# +def GetOptions(): + from optparse import OptionParser + + Parser = OptionParser(description=__copyright__, version=__version__, usage=__usage__) + + Parser.add_option("-o", "--output", dest="OutputFile", default=None, metavar="FILE", + help="Specify the name of depex file to be generated") + Parser.add_option("-t", "--module-type", dest="ModuleType", default=None, + help="The type of module for which the dependency expression serves") + Parser.add_option("-e", "--dependency-expression", dest="Expression", default="", + help="The string of dependency expression. If this option presents, the input file will be ignored.") + Parser.add_option("-m", "--optimize", dest="Optimize", default=False, action="store_true", + help="Do some simple optimization on the expression.") + Parser.add_option("-v", "--verbose", dest="verbose", default=False, action="store_true", + help="build with verbose information") + Parser.add_option("-d", "--debug", action="store", type="int", help="Enable debug messages at specified level.") + Parser.add_option("-q", "--quiet", dest="quiet", default=False, action="store_true", + help="build with little information") + + return Parser.parse_args() + + +## Entrance method +# +# @retval 0 Tool was successful +# @retval 1 Tool failed +# +def Main(): + EdkLogger.Initialize() + Option, Input = GetOptions() + + # Set log level + if Option.quiet: + EdkLogger.SetLevel(EdkLogger.QUIET) + elif Option.verbose: + EdkLogger.SetLevel(EdkLogger.VERBOSE) + elif Option.debug != None: + EdkLogger.SetLevel(Option.debug + 1) + else: + EdkLogger.SetLevel(EdkLogger.INFO) + + try: + if Option.ModuleType == None or Option.ModuleType not in gType2Phase: + EdkLogger.error("GenDepex", OPTION_MISSING, "Module type is not specified or supported") + + DxsFile = '' + if len(Input) > 0 and Option.Expression == "": + DxsFile = Input[0] + DxsString = open(DxsFile, 'r').read().replace("\n", " ").replace("\r", " ") + DxsString = gStartClosePattern.sub("\\1", DxsString) + elif Option.Expression != "": + if Option.Expression[0] == '"': + DxsString = Option.Expression[1:-1] + else: + DxsString = Option.Expression + else: + EdkLogger.error("GenDepex", OPTION_MISSING, "No expression string or file given") + + Dpx = DependencyExpression(DxsString, Option.ModuleType, Option.Optimize) + if Option.OutputFile != None: + Dpx.Generate(Option.OutputFile) + else: + Dpx.Generate() + except BaseException, X: + EdkLogger.quiet("") + if Option != None and Option.debug != None: + EdkLogger.quiet(traceback.format_exc()) + else: + EdkLogger.quiet(str(X)) + return 1 + + return 0 + +if __name__ == '__main__': + sys.exit(Main()) + diff --git a/BaseTools/Source/Python/AutoGen/GenMake.py b/BaseTools/Source/Python/AutoGen/GenMake.py new file mode 100644 index 0000000000..f689a8692d --- /dev/null +++ b/BaseTools/Source/Python/AutoGen/GenMake.py @@ -0,0 +1,1389 @@ +## @file +# Create makefile for MS nmake and GNU make +# +# Copyright (c) 2007, 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. +# + +## Import Modules +# +import os +import sys +import string +import re +import os.path as path + +from Common.BuildToolError import * +from Common.Misc import * +from Common.String import * +from BuildEngine import * +import Common.GlobalData as GlobalData + +## Regular expression for finding header file inclusions +gIncludePattern = re.compile(r"^[ \t]*#[ \t]*include(?:[ \t]*(?:\\(?:\r\n|\r|\n))*[ \t]*)*(?:[\"<][ \t]*)([\w.\\/]+)(?:[ \t]*[\">])", re.MULTILINE|re.UNICODE) + +## Regular expression for matching macro used in header file inclusion +gMacroPattern = re.compile("([_A-Z][_A-Z0-9]*)[ \t]*\((.+)\)", re.UNICODE) + +## pattern for include style in R8.x code +gProtocolDefinition = "Protocol/%(HeaderKey)s/%(HeaderKey)s.h" +gGuidDefinition = "Guid/%(HeaderKey)s/%(HeaderKey)s.h" +gArchProtocolDefinition = "ArchProtocol/%(HeaderKey)s/%(HeaderKey)s.h" +gPpiDefinition = "Ppi/%(HeaderKey)s/%(HeaderKey)s.h" +gIncludeMacroConversion = { + "EFI_PROTOCOL_DEFINITION" : gProtocolDefinition, + "EFI_GUID_DEFINITION" : gGuidDefinition, + "EFI_ARCH_PROTOCOL_DEFINITION" : gArchProtocolDefinition, + "EFI_PROTOCOL_PRODUCER" : gProtocolDefinition, + "EFI_PROTOCOL_CONSUMER" : gProtocolDefinition, + "EFI_PROTOCOL_DEPENDENCY" : gProtocolDefinition, + "EFI_ARCH_PROTOCOL_PRODUCER" : gArchProtocolDefinition, + "EFI_ARCH_PROTOCOL_CONSUMER" : gArchProtocolDefinition, + "EFI_ARCH_PROTOCOL_DEPENDENCY" : gArchProtocolDefinition, + "EFI_PPI_DEFINITION" : gPpiDefinition, + "EFI_PPI_PRODUCER" : gPpiDefinition, + "EFI_PPI_CONSUMER" : gPpiDefinition, + "EFI_PPI_DEPENDENCY" : gPpiDefinition, +} + +## default makefile type +gMakeType = "" +if sys.platform == "win32": + gMakeType = "nmake" +else: + gMakeType = "gmake" + + +## BuildFile class +# +# This base class encapsules build file and its generation. It uses template to generate +# the content of build file. The content of build file will be got from AutoGen objects. +# +class BuildFile(object): + ## template used to generate the build file (i.e. makefile if using make) + _TEMPLATE_ = TemplateString('') + + _DEFAULT_FILE_NAME_ = "Makefile" + + ## default file name for each type of build file + _FILE_NAME_ = { + "nmake" : "Makefile", + "gmake" : "GNUmakefile" + } + + ## Fixed header string for makefile + _MAKEFILE_HEADER = '''# +# DO NOT EDIT +# This file is auto-generated by build utility +# +# Module Name: +# +# %s +# +# Abstract: +# +# Auto-generated makefile for building modules, libraries or platform +# + ''' + + ## Header string for each type of build file + _FILE_HEADER_ = { + "nmake" : _MAKEFILE_HEADER % _FILE_NAME_["nmake"], + "gmake" : _MAKEFILE_HEADER % _FILE_NAME_["gmake"] + } + + ## shell commands which can be used in build file in the form of macro + # $(CP) copy file command + # $(MV) move file command + # $(RM) remove file command + # $(MD) create dir command + # $(RD) remove dir command + # + _SHELL_CMD_ = { + "nmake" : { + "CP" : "copy /y", + "MV" : "move /y", + "RM" : "del /f /q", + "MD" : "mkdir", + "RD" : "rmdir /s /q", + }, + + "gmake" : { + "CP" : "cp -f", + "MV" : "mv -f", + "RM" : "rm -f", + "MD" : "mkdir -p", + "RD" : "rm -r -f", + } + } + + ## directory separator + _SEP_ = { + "nmake" : "\\", + "gmake" : "/" + } + + ## directory creation template + _MD_TEMPLATE_ = { + "nmake" : 'if not exist %(dir)s $(MD) %(dir)s', + "gmake" : "$(MD) %(dir)s" + } + + ## directory removal template + _RD_TEMPLATE_ = { + "nmake" : 'if exist %(dir)s $(RD) %(dir)s', + "gmake" : "$(RD) %(dir)s" + } + + _CD_TEMPLATE_ = { + "nmake" : 'if exist %(dir)s cd %(dir)s', + "gmake" : "test -e %(dir)s && cd %(dir)s" + } + + _MAKE_TEMPLATE_ = { + "nmake" : 'if exist %(file)s "$(MAKE)" $(MAKE_FLAGS) -f %(file)s', + "gmake" : 'test -e %(file)s && "$(MAKE)" $(MAKE_FLAGS) -f %(file)s' + } + + _INCLUDE_CMD_ = { + "nmake" : '!INCLUDE', + "gmake" : "include" + } + + _INC_FLAG_ = {"MSFT" : "/I", "GCC" : "-I", "INTEL" : "-I", "RVCT" : "-I"} + + ## Constructor of BuildFile + # + # @param AutoGenObject Object of AutoGen class + # + def __init__(self, AutoGenObject): + self._AutoGenObject = AutoGenObject + self._FileType = gMakeType + + ## Create build file + # + # @param FileType Type of build file. Only nmake and gmake are supported now. + # + # @retval TRUE The build file is created or re-created successfully + # @retval FALSE The build file exists and is the same as the one to be generated + # + def Generate(self, FileType=gMakeType): + if FileType not in self._FILE_NAME_: + EdkLogger.error("build", PARAMETER_INVALID, "Invalid build type [%s]" % FileType, + ExtraData="[%s]" % str(self._AutoGenObject)) + self._FileType = FileType + FileContent = self._TEMPLATE_.Replace(self._TemplateDict) + FileName = self._FILE_NAME_[FileType] + return SaveFileOnChange(os.path.join(self._AutoGenObject.MakeFileDir, FileName), FileContent, False) + + ## Return a list of directory creation command string + # + # @param DirList The list of directory to be created + # + # @retval list The directory creation command list + # + def GetCreateDirectoryCommand(self, DirList): + return [self._MD_TEMPLATE_[self._FileType] % {'dir':Dir} for Dir in DirList] + + ## Return a list of directory removal command string + # + # @param DirList The list of directory to be removed + # + # @retval list The directory removal command list + # + def GetRemoveDirectoryCommand(self, DirList): + return [self._RD_TEMPLATE_[self._FileType] % {'dir':Dir} for Dir in DirList] + + def PlaceMacro(self, Path, MacroDefinitions={}): + if Path.startswith("$("): + return Path + else: + PathLength = len(Path) + for MacroName in MacroDefinitions: + MacroValue = MacroDefinitions[MacroName] + MacroValueLength = len(MacroValue) + if MacroValueLength <= PathLength and Path.startswith(MacroValue): + Path = "$(%s)%s" % (MacroName, Path[MacroValueLength:]) + break + return Path + +## ModuleMakefile class +# +# This class encapsules makefie and its generation for module. It uses template to generate +# the content of makefile. The content of makefile will be got from ModuleAutoGen object. +# +class ModuleMakefile(BuildFile): + ## template used to generate the makefile for module + _TEMPLATE_ = TemplateString('''\ +${makefile_header} + +# +# Platform Macro Definition +# +PLATFORM_NAME = ${platform_name} +PLATFORM_GUID = ${platform_guid} +PLATFORM_VERSION = ${platform_version} +PLATFORM_RELATIVE_DIR = ${platform_relative_directory} +PLATFORM_DIR = $(WORKSPACE)${separator}${platform_relative_directory} +PLATFORM_OUTPUT_DIR = ${platform_output_directory} + +# +# Module Macro Definition +# +MODULE_NAME = ${module_name} +MODULE_GUID = ${module_guid} +MODULE_VERSION = ${module_version} +MODULE_TYPE = ${module_type} +MODULE_FILE = ${module_file} +MODULE_FILE_BASE_NAME = ${module_file_base_name} +BASE_NAME = $(MODULE_NAME) +MODULE_RELATIVE_DIR = ${module_relative_directory} +MODULE_DIR = $(WORKSPACE)${separator}${module_relative_directory} + +MODULE_ENTRY_POINT = ${module_entry_point} +ARCH_ENTRY_POINT = ${arch_entry_point} +IMAGE_ENTRY_POINT = ${image_entry_point} + +${BEGIN}${module_extra_defines} +${END} +# +# Build Configuration Macro Definition +# +ARCH = ${architecture} +TOOLCHAIN = ${toolchain_tag} +TOOLCHAIN_TAG = ${toolchain_tag} +TARGET = ${build_target} + +# +# Build Directory Macro Definition +# +# PLATFORM_BUILD_DIR = ${platform_build_directory} +BUILD_DIR = ${platform_build_directory} +BIN_DIR = $(BUILD_DIR)${separator}${architecture} +LIB_DIR = $(BIN_DIR) +MODULE_BUILD_DIR = ${module_build_directory} +OUTPUT_DIR = ${module_output_directory} +DEBUG_DIR = ${module_debug_directory} +DEST_DIR_OUTPUT = $(OUTPUT_DIR) +DEST_DIR_DEBUG = $(DEBUG_DIR) + +# +# Shell Command Macro +# +${BEGIN}${shell_command_code} = ${shell_command} +${END} + +# +# Tools definitions specific to this module +# +${BEGIN}${module_tool_definitions} +${END} +MAKE_FILE = ${makefile_path} + +# +# Build Macro +# +${BEGIN}${file_macro} +${END} + +COMMON_DEPS = ${BEGIN}${common_dependency_file} \\ + ${END} + +# +# Overridable Target Macro Definitions +# +FORCE_REBUILD = force_build +INIT_TARGET = init +PCH_TARGET = +BC_TARGET = ${BEGIN}${backward_compatible_target} ${END} +CODA_TARGET = ${BEGIN}${remaining_build_target} \\ + ${END} + +# +# Default target, which will build dependent libraries in addition to source files +# + +all: mbuild + + +# +# Target used when called from platform makefile, which will bypass the build of dependent libraries +# + +pbuild: $(INIT_TARGET) $(BC_TARGET) $(PCH_TARGET) $(CODA_TARGET) + +# +# ModuleTarget +# + +mbuild: $(INIT_TARGET) $(BC_TARGET) gen_libs $(PCH_TARGET) $(CODA_TARGET) + +# +# Build Target used in multi-thread build mode, which will bypass the init and gen_libs targets +# + +tbuild: $(BC_TARGET) $(PCH_TARGET) $(CODA_TARGET) + +# +# Phony target which is used to force executing commands for a target +# +force_build: +\t-@ + +# +# Target to update the FD +# + +fds: mbuild gen_fds + +# +# Initialization target: print build information and create necessary directories +# +init: info dirs + +info: +\t-@echo Building ... $(MODULE_DIR)${separator}$(MODULE_FILE) [$(ARCH)] + +dirs: +${BEGIN}\t-@${create_directory_command}\n${END} + +strdefs: +\t-@$(CP) $(DEBUG_DIR)${separator}AutoGen.h $(DEBUG_DIR)${separator}$(MODULE_NAME)StrDefs.h + +# +# GenLibsTarget +# +gen_libs: +\t${BEGIN}@"$(MAKE)" $(MAKE_FLAGS) -f ${dependent_library_build_directory}${separator}${makefile_name} +\t${END}@cd $(MODULE_BUILD_DIR) + +# +# Build Flash Device Image +# +gen_fds: +\t@"$(MAKE)" $(MAKE_FLAGS) -f $(BUILD_DIR)${separator}${makefile_name} fds +\t@cd $(MODULE_BUILD_DIR) + +# +# Individual Object Build Targets +# +${BEGIN}${file_build_target} +${END} + +# +# clean all intermediate files +# +clean: +\t${BEGIN}${clean_command} +\t${END} + +# +# clean all generated files +# +cleanall: +${BEGIN}\t${cleanall_command} +${END}\t$(RM) *.pdb *.idb > NUL 2>&1 +\t$(RM) $(BIN_DIR)${separator}$(MODULE_NAME).efi + +# +# clean all dependent libraries built +# +cleanlib: +\t${BEGIN}-@${library_build_command} cleanall +\t${END}@cd $(MODULE_BUILD_DIR)\n\n''') + + _FILE_MACRO_TEMPLATE = TemplateString("${macro_name} = ${BEGIN} \\\n ${source_file}${END}\n") + _BUILD_TARGET_TEMPLATE = TemplateString("${BEGIN}${target} : ${deps}\n${END}\t${cmd}\n") + + ## Constructor of ModuleMakefile + # + # @param ModuleAutoGen Object of ModuleAutoGen class + # + def __init__(self, ModuleAutoGen): + BuildFile.__init__(self, ModuleAutoGen) + self.PlatformInfo = self._AutoGenObject.PlatformInfo + + self.ResultFileList = [] + self.IntermediateDirectoryList = ["$(DEBUG_DIR)", "$(OUTPUT_DIR)"] + + self.SourceFileDatabase = {} # {file type : file path} + self.DestFileDatabase = {} # {file type : file path} + self.FileBuildTargetList = [] # [(src, target string)] + self.BuildTargetList = [] # [target string] + self.PendingBuildTargetList = [] # [FileBuildRule objects] + self.CommonFileDependency = [] + self.FileListMacros = {} + self.ListFileMacros = {} + + self.FileDependency = [] + self.LibraryBuildCommandList = [] + self.LibraryFileList = [] + self.LibraryMakefileList = [] + self.LibraryBuildDirectoryList = [] + self.SystemLibraryList = [] + self.Macros = sdict() + self.Macros["OUTPUT_DIR" ] = self._AutoGenObject.Macros["OUTPUT_DIR"] + self.Macros["DEBUG_DIR" ] = self._AutoGenObject.Macros["DEBUG_DIR"] + self.Macros["MODULE_BUILD_DIR"] = self._AutoGenObject.Macros["MODULE_BUILD_DIR"] + self.Macros["BIN_DIR" ] = self._AutoGenObject.Macros["BIN_DIR"] + self.Macros["BUILD_DIR" ] = self._AutoGenObject.Macros["BUILD_DIR"] + self.Macros["WORKSPACE" ] = self._AutoGenObject.Macros["WORKSPACE"] + + # Compose a dict object containing information used to do replacement in template + def _CreateTemplateDict(self): + if self._FileType not in self._SEP_: + EdkLogger.error("build", PARAMETER_INVALID, "Invalid Makefile type [%s]" % self._FileType, + ExtraData="[%s]" % str(self._AutoGenObject)) + Separator = self._SEP_[self._FileType] + + # break build if no source files and binary files are found + if len(self._AutoGenObject.SourceFileList) == 0 and len(self._AutoGenObject.BinaryFileList) == 0: + EdkLogger.error("build", AUTOGEN_ERROR, "No files to be built in module [%s, %s, %s]" + % (self._AutoGenObject.BuildTarget, self._AutoGenObject.ToolChain, self._AutoGenObject.Arch), + ExtraData="[%s]" % str(self._AutoGenObject)) + + # convert dependent libaries to build command + self.ProcessDependentLibrary() + if len(self._AutoGenObject.Module.ModuleEntryPointList) > 0: + ModuleEntryPoint = self._AutoGenObject.Module.ModuleEntryPointList[0] + else: + ModuleEntryPoint = "_ModuleEntryPoint" + + # Intel EBC compiler enforces EfiMain + if self._AutoGenObject.AutoGenVersion < 0x00010005 and self._AutoGenObject.Arch == "EBC": + ArchEntryPoint = "EfiMain" + else: + ArchEntryPoint = ModuleEntryPoint + + if self._AutoGenObject.Arch == "EBC": + # EBC compiler always use "EfiStart" as entry point. Only applies to R9 modules + ImageEntryPoint = "EfiStart" + elif self._AutoGenObject.AutoGenVersion < 0x00010005: + # R8 modules use entry point specified in INF file + ImageEntryPoint = ModuleEntryPoint + else: + # R9 modules always use "_ModuleEntryPoint" as entry point + ImageEntryPoint = "_ModuleEntryPoint" + + # tools definitions + ToolsDef = [] + IncPrefix = self._INC_FLAG_[self._AutoGenObject.ToolChainFamily] + for Tool in self._AutoGenObject.BuildOption: + for Attr in self._AutoGenObject.BuildOption[Tool]: + Value = self._AutoGenObject.BuildOption[Tool][Attr] + if Attr == "FAMILY": + continue + elif Attr == "PATH": + ToolsDef.append("%s = %s" % (Tool, Value)) + else: + # Don't generate MAKE_FLAGS in makefile. It's put in environment variable. + if Tool == "MAKE": + continue + # Remove duplicated include path, if any + if Attr == "FLAGS": + Value = RemoveDupOption(Value, IncPrefix, self._AutoGenObject.IncludePathList) + ToolsDef.append("%s_%s = %s" % (Tool, Attr, Value)) + ToolsDef.append("") + + # convert source files and binary files to build targets + self.ResultFileList = [str(T.Target) for T in self._AutoGenObject.CodaTargetList] + if len(self.ResultFileList) == 0: + EdkLogger.error("build", AUTOGEN_ERROR, "Nothing to build", + ExtraData="[%s]" % str(self._AutoGenObject)) + + self.ProcessBuildTargetList() + + # Generate macros used to represent input files + FileMacroList = [] # macro name = file list + for FileListMacro in self.FileListMacros: + FileMacro = self._FILE_MACRO_TEMPLATE.Replace( + { + "macro_name" : FileListMacro, + "source_file" : self.FileListMacros[FileListMacro] + } + ) + FileMacroList.append(FileMacro) + + # INC_LIST is special + FileMacro = "" + IncludePathList = [] + for P in self._AutoGenObject.IncludePathList: + IncludePathList.append(IncPrefix+self.PlaceMacro(P, self.Macros)) + if FileBuildRule.INC_LIST_MACRO in self.ListFileMacros: + self.ListFileMacros[FileBuildRule.INC_LIST_MACRO].append(IncPrefix+P) + FileMacro += self._FILE_MACRO_TEMPLATE.Replace( + { + "macro_name" : "INC", + "source_file" : IncludePathList + } + ) + FileMacroList.append(FileMacro) + + # Generate macros used to represent files containing list of input files + for ListFileMacro in self.ListFileMacros: + ListFileName = os.path.join(self._AutoGenObject.OutputDir, "%s.lst" % ListFileMacro.lower()[:len(ListFileMacro)-5]) + FileMacroList.append("%s = %s" % (ListFileMacro, ListFileName)) + SaveFileOnChange( + ListFileName, + "\n".join(self.ListFileMacros[ListFileMacro]), + False + ) + + # R8 modules need StrDefs.h for string ID + #if self._AutoGenObject.AutoGenVersion < 0x00010005 and len(self._AutoGenObject.UnicodeFileList) > 0: + # BcTargetList = ['strdefs'] + #else: + # BcTargetList = [] + BcTargetList = [] + + MakefileName = self._FILE_NAME_[self._FileType] + LibraryMakeCommandList = [] + for D in self.LibraryBuildDirectoryList: + Command = self._MAKE_TEMPLATE_[self._FileType] % {"file":os.path.join(D, MakefileName)} + LibraryMakeCommandList.append(Command) + + MakefileTemplateDict = { + "makefile_header" : self._FILE_HEADER_[self._FileType], + "makefile_path" : os.path.join("$(MODULE_BUILD_DIR)", MakefileName), + "makefile_name" : MakefileName, + "platform_name" : self.PlatformInfo.Name, + "platform_guid" : self.PlatformInfo.Guid, + "platform_version" : self.PlatformInfo.Version, + "platform_relative_directory": self.PlatformInfo.SourceDir, + "platform_output_directory" : self.PlatformInfo.OutputDir, + + "module_name" : self._AutoGenObject.Name, + "module_guid" : self._AutoGenObject.Guid, + "module_version" : self._AutoGenObject.Version, + "module_type" : self._AutoGenObject.ModuleType, + "module_file" : self._AutoGenObject.MetaFile.Name, + "module_file_base_name" : self._AutoGenObject.MetaFile.BaseName, + "module_relative_directory" : self._AutoGenObject.SourceDir, + "module_extra_defines" : ["%s = %s" % (k, v) for k,v in self._AutoGenObject.Module.Defines.iteritems()], + + "architecture" : self._AutoGenObject.Arch, + "toolchain_tag" : self._AutoGenObject.ToolChain, + "build_target" : self._AutoGenObject.BuildTarget, + + "platform_build_directory" : self.PlatformInfo.BuildDir, + "module_build_directory" : self._AutoGenObject.BuildDir, + "module_output_directory" : self._AutoGenObject.OutputDir, + "module_debug_directory" : self._AutoGenObject.DebugDir, + + "separator" : Separator, + "module_tool_definitions" : ToolsDef, + + "shell_command_code" : self._SHELL_CMD_[self._FileType].keys(), + "shell_command" : self._SHELL_CMD_[self._FileType].values(), + + "module_entry_point" : ModuleEntryPoint, + "image_entry_point" : ImageEntryPoint, + "arch_entry_point" : ArchEntryPoint, + "remaining_build_target" : self.ResultFileList, + "common_dependency_file" : self.CommonFileDependency, + "create_directory_command" : self.GetCreateDirectoryCommand(self.IntermediateDirectoryList), + "clean_command" : self.GetRemoveDirectoryCommand(["$(OUTPUT_DIR)"]), + "cleanall_command" : self.GetRemoveDirectoryCommand(["$(DEBUG_DIR)", "$(OUTPUT_DIR)"]), + "dependent_library_build_directory" : self.LibraryBuildDirectoryList, + "library_build_command" : LibraryMakeCommandList, + "file_macro" : FileMacroList, + "file_build_target" : self.BuildTargetList, + "backward_compatible_target": BcTargetList, + } + + return MakefileTemplateDict + + def ProcessBuildTargetList(self): + # + # Search dependency file list for each source file + # + ForceIncludedFile = [] + for File in self._AutoGenObject.AutoGenFileList: + if File.Ext == '.h': + ForceIncludedFile.append(File) + SourceFileList = [] + for Target in self._AutoGenObject.IntroTargetList: + SourceFileList.extend(Target.Inputs) + + self.FileDependency = self.GetFileDependency( + SourceFileList, + ForceIncludedFile, + self._AutoGenObject.IncludePathList + ) + DepSet = None + for File in self.FileDependency: + if not self.FileDependency[File]: + self.FileDependency[File] = ['$(FORCE_REBUILD)'] + continue + # skip non-C files + if File.Ext not in [".c", ".C"] or File.Name == "AutoGen.c": + continue + elif DepSet == None: + DepSet = set(self.FileDependency[File]) + else: + DepSet &= set(self.FileDependency[File]) + # in case nothing in SourceFileList + if DepSet == None: + DepSet = set() + # + # Extract comman files list in the dependency files + # + for File in DepSet: + self.CommonFileDependency.append(self.PlaceMacro(File.Path, self.Macros)) + + for File in self.FileDependency: + # skip non-C files + if File.Ext not in [".c", ".C"] or File.Name == "AutoGen.c": + continue + NewDepSet = set(self.FileDependency[File]) + NewDepSet -= DepSet + self.FileDependency[File] = ["$(COMMON_DEPS)"] + list(NewDepSet) + + # Convert target description object to target string in makefile + for Type in self._AutoGenObject.Targets: + for T in self._AutoGenObject.Targets[Type]: + # Generate related macros if needed + if T.GenFileListMacro and T.FileListMacro not in self.FileListMacros: + self.FileListMacros[T.FileListMacro] = [] + if T.GenListFile and T.ListFileMacro not in self.ListFileMacros: + self.ListFileMacros[T.ListFileMacro] = [] + if T.GenIncListFile and T.IncListFileMacro not in self.ListFileMacros: + self.ListFileMacros[T.IncListFileMacro] = [] + + Deps = [] + # Add force-dependencies + for Dep in T.Dependencies: + Deps.append(self.PlaceMacro(str(Dep), self.Macros)) + # Add inclusion-dependencies + if len(T.Inputs) == 1 and T.Inputs[0] in self.FileDependency: + for F in self.FileDependency[T.Inputs[0]]: + Deps.append(self.PlaceMacro(str(F), self.Macros)) + # Add source-dependencies + for F in T.Inputs: + NewFile = self.PlaceMacro(str(F), self.Macros) + # In order to use file list macro as dependency + if T.GenListFile: + self.ListFileMacros[T.ListFileMacro].append(str(F)) + self.FileListMacros[T.FileListMacro].append(NewFile) + elif T.GenFileListMacro: + self.FileListMacros[T.FileListMacro].append(NewFile) + else: + Deps.append(NewFile) + + # Use file list macro as dependency + if T.GenFileListMacro: + Deps.append("$(%s)" % T.FileListMacro) + + TargetDict = { + "target" : self.PlaceMacro(T.Target.Path, self.Macros), + "cmd" : "\n\t".join(T.Commands), + "deps" : Deps + } + self.BuildTargetList.append(self._BUILD_TARGET_TEMPLATE.Replace(TargetDict)) + + ## For creating makefile targets for dependent libraries + def ProcessDependentLibrary(self): + for LibraryAutoGen in self._AutoGenObject.LibraryAutoGenList: + self.LibraryBuildDirectoryList.append(self.PlaceMacro(LibraryAutoGen.BuildDir, self.Macros)) + + ## Return a list containing source file's dependencies + # + # @param FileList The list of source files + # @param ForceInculeList The list of files which will be included forcely + # @param SearchPathList The list of search path + # + # @retval dict The mapping between source file path and its dependencies + # + def GetFileDependency(self, FileList, ForceInculeList, SearchPathList): + Dependency = {} + for F in FileList: + Dependency[F] = self.GetDependencyList(F, ForceInculeList, SearchPathList) + return Dependency + + ## Find dependencies for one source file + # + # By searching recursively "#include" directive in file, find out all the + # files needed by given source file. The dependecies will be only searched + # in given search path list. + # + # @param File The source file + # @param ForceInculeList The list of files which will be included forcely + # @param SearchPathList The list of search path + # + # @retval list The list of files the given source file depends on + # + def GetDependencyList(self, File, ForceList, SearchPathList): + EdkLogger.debug(EdkLogger.DEBUG_1, "Try to get dependency files for %s" % File) + FileStack = [File] + ForceList + DependencySet = set() + MacroUsedByIncludedFile = False + + if self._AutoGenObject.Arch not in gDependencyDatabase: + gDependencyDatabase[self._AutoGenObject.Arch] = {} + DepDb = gDependencyDatabase[self._AutoGenObject.Arch] + + while len(FileStack) > 0: + F = FileStack.pop() + + CurrentFileDependencyList = [] + if F in DepDb: + CurrentFileDependencyList = DepDb[F] + for Dep in CurrentFileDependencyList: + if Dep not in FileStack and Dep not in DependencySet: + FileStack.append(Dep) + else: + try: + Fd = open(F.Path, 'r') + except BaseException, X: + EdkLogger.error("build", FILE_OPEN_FAILURE, ExtraData=F.Path+"\n\t"+str(X)) + + FileContent = Fd.read() + Fd.close() + if len(FileContent) == 0: + continue + + if FileContent[0] == 0xff or FileContent[0] == 0xfe: + FileContent = unicode(FileContent, "utf-16") + IncludedFileList = gIncludePattern.findall(FileContent) + + CurrentFilePath = F.Dir + for Inc in IncludedFileList: + # if there's macro used to reference header file, expand it + HeaderList = gMacroPattern.findall(Inc) + if len(HeaderList) == 1 and len(HeaderList[0]) == 2: + HeaderType = HeaderList[0][0] + HeaderKey = HeaderList[0][1] + if HeaderType in gIncludeMacroConversion: + Inc = gIncludeMacroConversion[HeaderType] % {"HeaderKey" : HeaderKey} + else: + # not known macro used in #include + MacroUsedByIncludedFile = True + continue + Inc = os.path.normpath(Inc) + for SearchPath in [CurrentFilePath] + SearchPathList: + FilePath = os.path.join(SearchPath, Inc) + if not os.path.exists(FilePath) or FilePath in CurrentFileDependencyList: + continue + FilePath = PathClass(FilePath) + CurrentFileDependencyList.append(FilePath) + if FilePath not in FileStack and FilePath not in DependencySet: + FileStack.append(FilePath) + break + else: + EdkLogger.debug(EdkLogger.DEBUG_9, "%s included by %s was not found"\ + "in any given path:\n\t%s" % (Inc, F, "\n\t".join(SearchPathList))) + + if not MacroUsedByIncludedFile: + if F == File: + CurrentFileDependencyList += ForceList + # + # Don't keep the file in cache if it uses macro in included file. + # So it will be scanned again if another file includes this file. + # + DepDb[F] = CurrentFileDependencyList + DependencySet.update(CurrentFileDependencyList) + + # + # If there's macro used in included file, always build the file by + # returning a empty dependency + # + if MacroUsedByIncludedFile: + DependencyList = [] + else: + DependencyList = list(DependencySet) # remove duplicate ones + + return DependencyList + + _TemplateDict = property(_CreateTemplateDict) + +## CustomMakefile class +# +# This class encapsules makefie and its generation for module. It uses template to generate +# the content of makefile. The content of makefile will be got from ModuleAutoGen object. +# +class CustomMakefile(BuildFile): + ## template used to generate the makefile for module with custom makefile + _TEMPLATE_ = TemplateString('''\ +${makefile_header} + +# +# Platform Macro Definition +# +PLATFORM_NAME = ${platform_name} +PLATFORM_GUID = ${platform_guid} +PLATFORM_VERSION = ${platform_version} +PLATFORM_RELATIVE_DIR = ${platform_relative_directory} +PLATFORM_DIR = $(WORKSPACE)${separator}${platform_relative_directory} +PLATFORM_OUTPUT_DIR = ${platform_output_directory} + +# +# Module Macro Definition +# +MODULE_NAME = ${module_name} +MODULE_GUID = ${module_guid} +MODULE_VERSION = ${module_version} +MODULE_TYPE = ${module_type} +MODULE_FILE = ${module_file} +MODULE_FILE_BASE_NAME = ${module_file_base_name} +BASE_NAME = $(MODULE_NAME) +MODULE_RELATIVE_DIR = ${module_relative_directory} +MODULE_DIR = $(WORKSPACE)${separator}${module_relative_directory} + +# +# Build Configuration Macro Definition +# +ARCH = ${architecture} +TOOLCHAIN = ${toolchain_tag} +TOOLCHAIN_TAG = ${toolchain_tag} +TARGET = ${build_target} + +# +# Build Directory Macro Definition +# +# PLATFORM_BUILD_DIR = ${platform_build_directory} +BUILD_DIR = ${platform_build_directory} +BIN_DIR = $(BUILD_DIR)${separator}${architecture} +LIB_DIR = $(BIN_DIR) +MODULE_BUILD_DIR = ${module_build_directory} +OUTPUT_DIR = ${module_output_directory} +DEBUG_DIR = ${module_debug_directory} +DEST_DIR_OUTPUT = $(OUTPUT_DIR) +DEST_DIR_DEBUG = $(DEBUG_DIR) + +# +# Tools definitions specific to this module +# +${BEGIN}${module_tool_definitions} +${END} +MAKE_FILE = ${makefile_path} + +# +# Shell Command Macro +# +${BEGIN}${shell_command_code} = ${shell_command} +${END} + +${custom_makefile_content} + +# +# Target used when called from platform makefile, which will bypass the build of dependent libraries +# + +pbuild: init all + + +# +# ModuleTarget +# + +mbuild: init all + +# +# Build Target used in multi-thread build mode, which no init target is needed +# + +tbuild: all + +# +# Initialization target: print build information and create necessary directories +# +init: +\t-@echo Building ... $(MODULE_DIR)${separator}$(MODULE_FILE) [$(ARCH)] +${BEGIN}\t-@${create_directory_command}\n${END}\ + +''') + + ## Constructor of CustomMakefile + # + # @param ModuleAutoGen Object of ModuleAutoGen class + # + def __init__(self, ModuleAutoGen): + BuildFile.__init__(self, ModuleAutoGen) + self.PlatformInfo = self._AutoGenObject.PlatformInfo + self.IntermediateDirectoryList = ["$(DEBUG_DIR)", "$(OUTPUT_DIR)"] + + # Compose a dict object containing information used to do replacement in template + def _CreateTemplateDict(self): + Separator = self._SEP_[self._FileType] + if self._FileType not in self._AutoGenObject.CustomMakefile: + EdkLogger.error('build', OPTION_NOT_SUPPORTED, "No custom makefile for %s" % self._FileType, + ExtraData="[%s]" % str(self._AutoGenObject)) + MakefilePath = os.path.join( + self._AutoGenObject.WorkspaceDir, + self._AutoGenObject.CustomMakefile[self._FileType] + ) + try: + CustomMakefile = open(MakefilePath, 'r').read() + except: + EdkLogger.error('build', FILE_OPEN_FAILURE, File=str(self._AutoGenObject), + ExtraData=self._AutoGenObject.CustomMakefile[self._FileType]) + + # tools definitions + ToolsDef = [] + for Tool in self._AutoGenObject.BuildOption: + # Don't generate MAKE_FLAGS in makefile. It's put in environment variable. + if Tool == "MAKE": + continue + for Attr in self._AutoGenObject.BuildOption[Tool]: + if Attr == "FAMILY": + continue + elif Attr == "PATH": + ToolsDef.append("%s = %s" % (Tool, self._AutoGenObject.BuildOption[Tool][Attr])) + else: + ToolsDef.append("%s_%s = %s" % (Tool, Attr, self._AutoGenObject.BuildOption[Tool][Attr])) + ToolsDef.append("") + + MakefileName = self._FILE_NAME_[self._FileType] + MakefileTemplateDict = { + "makefile_header" : self._FILE_HEADER_[self._FileType], + "makefile_path" : os.path.join("$(MODULE_BUILD_DIR)", MakefileName), + "platform_name" : self.PlatformInfo.Name, + "platform_guid" : self.PlatformInfo.Guid, + "platform_version" : self.PlatformInfo.Version, + "platform_relative_directory": self.PlatformInfo.SourceDir, + "platform_output_directory" : self.PlatformInfo.OutputDir, + + "module_name" : self._AutoGenObject.Name, + "module_guid" : self._AutoGenObject.Guid, + "module_version" : self._AutoGenObject.Version, + "module_type" : self._AutoGenObject.ModuleType, + "module_file" : self._AutoGenObject.MetaFile, + "module_file_base_name" : self._AutoGenObject.MetaFile.BaseName, + "module_relative_directory" : self._AutoGenObject.SourceDir, + + "architecture" : self._AutoGenObject.Arch, + "toolchain_tag" : self._AutoGenObject.ToolChain, + "build_target" : self._AutoGenObject.BuildTarget, + + "platform_build_directory" : self.PlatformInfo.BuildDir, + "module_build_directory" : self._AutoGenObject.BuildDir, + "module_output_directory" : self._AutoGenObject.OutputDir, + "module_debug_directory" : self._AutoGenObject.DebugDir, + + "separator" : Separator, + "module_tool_definitions" : ToolsDef, + + "shell_command_code" : self._SHELL_CMD_[self._FileType].keys(), + "shell_command" : self._SHELL_CMD_[self._FileType].values(), + + "create_directory_command" : self.GetCreateDirectoryCommand(self.IntermediateDirectoryList), + "custom_makefile_content" : CustomMakefile + } + + return MakefileTemplateDict + + _TemplateDict = property(_CreateTemplateDict) + +## PlatformMakefile class +# +# This class encapsules makefie and its generation for platform. It uses +# template to generate the content of makefile. The content of makefile will be +# got from PlatformAutoGen object. +# +class PlatformMakefile(BuildFile): + ## template used to generate the makefile for platform + _TEMPLATE_ = TemplateString('''\ +${makefile_header} + +# +# Platform Macro Definition +# +PLATFORM_NAME = ${platform_name} +PLATFORM_GUID = ${platform_guid} +PLATFORM_VERSION = ${platform_version} +PLATFORM_FILE = ${platform_file} +PLATFORM_DIR = $(WORKSPACE)${separator}${platform_relative_directory} +PLATFORM_OUTPUT_DIR = ${platform_output_directory} + +# +# Build Configuration Macro Definition +# +TOOLCHAIN = ${toolchain_tag} +TOOLCHAIN_TAG = ${toolchain_tag} +TARGET = ${build_target} + +# +# Build Directory Macro Definition +# +BUILD_DIR = ${platform_build_directory} +FV_DIR = ${platform_build_directory}${separator}FV + +# +# Shell Command Macro +# +${BEGIN}${shell_command_code} = ${shell_command} +${END} + +MAKE = ${make_path} +MAKE_FILE = ${makefile_path} + +# +# Default target +# +all: init build_libraries build_modules + +# +# Initialization target: print build information and create necessary directories +# +init: +\t-@echo Building ... $(PLATFORM_FILE) [${build_architecture_list}] +\t${BEGIN}-@${create_directory_command} +\t${END} +# +# library build target +# +libraries: init build_libraries + +# +# module build target +# +modules: init build_libraries build_modules + +# +# Build all libraries: +# +build_libraries: +${BEGIN}\t@"$(MAKE)" $(MAKE_FLAGS) -f ${library_makefile_list} pbuild +${END}\t@cd $(BUILD_DIR) + +# +# Build all modules: +# +build_modules: +${BEGIN}\t@"$(MAKE)" $(MAKE_FLAGS) -f ${module_makefile_list} pbuild +${END}\t@cd $(BUILD_DIR) + +# +# Clean intermediate files +# +clean: +\t${BEGIN}-@${library_build_command} clean +\t${END}${BEGIN}-@${module_build_command} clean +\t${END}@cd $(BUILD_DIR) + +# +# Clean all generated files except to makefile +# +cleanall: +${BEGIN}\t${cleanall_command} +${END} + +# +# Clean all library files +# +cleanlib: +\t${BEGIN}-@${library_build_command} cleanall +\t${END}@cd $(BUILD_DIR)\n +''') + + ## Constructor of PlatformMakefile + # + # @param ModuleAutoGen Object of PlatformAutoGen class + # + def __init__(self, PlatformAutoGen): + BuildFile.__init__(self, PlatformAutoGen) + self.ModuleBuildCommandList = [] + self.ModuleMakefileList = [] + self.IntermediateDirectoryList = [] + self.ModuleBuildDirectoryList = [] + self.LibraryBuildDirectoryList = [] + + # Compose a dict object containing information used to do replacement in template + def _CreateTemplateDict(self): + Separator = self._SEP_[self._FileType] + + PlatformInfo = self._AutoGenObject + if "MAKE" not in PlatformInfo.ToolDefinition or "PATH" not in PlatformInfo.ToolDefinition["MAKE"]: + EdkLogger.error("build", OPTION_MISSING, "No MAKE command defined. Please check your tools_def.txt!", + ExtraData="[%s]" % str(self._AutoGenObject)) + + self.IntermediateDirectoryList = ["$(BUILD_DIR)"] + self.ModuleBuildDirectoryList = self.GetModuleBuildDirectoryList() + self.LibraryBuildDirectoryList = self.GetLibraryBuildDirectoryList() + + MakefileName = self._FILE_NAME_[self._FileType] + LibraryMakefileList = [] + LibraryMakeCommandList = [] + for D in self.LibraryBuildDirectoryList: + D = self.PlaceMacro(D, {"BUILD_DIR":PlatformInfo.BuildDir}) + Makefile = os.path.join(D, MakefileName) + Command = self._MAKE_TEMPLATE_[self._FileType] % {"file":Makefile} + LibraryMakefileList.append(Makefile) + LibraryMakeCommandList.append(Command) + + ModuleMakefileList = [] + ModuleMakeCommandList = [] + for D in self.ModuleBuildDirectoryList: + D = self.PlaceMacro(D, {"BUILD_DIR":PlatformInfo.BuildDir}) + Makefile = os.path.join(D, MakefileName) + Command = self._MAKE_TEMPLATE_[self._FileType] % {"file":Makefile} + ModuleMakefileList.append(Makefile) + ModuleMakeCommandList.append(Command) + + MakefileTemplateDict = { + "makefile_header" : self._FILE_HEADER_[self._FileType], + "makefile_path" : os.path.join("$(BUILD_DIR)", MakefileName), + "make_path" : PlatformInfo.ToolDefinition["MAKE"]["PATH"], + "makefile_name" : MakefileName, + "platform_name" : PlatformInfo.Name, + "platform_guid" : PlatformInfo.Guid, + "platform_version" : PlatformInfo.Version, + "platform_file" : self._AutoGenObject.MetaFile, + "platform_relative_directory": PlatformInfo.SourceDir, + "platform_output_directory" : PlatformInfo.OutputDir, + "platform_build_directory" : PlatformInfo.BuildDir, + + "toolchain_tag" : PlatformInfo.ToolChain, + "build_target" : PlatformInfo.BuildTarget, + "shell_command_code" : self._SHELL_CMD_[self._FileType].keys(), + "shell_command" : self._SHELL_CMD_[self._FileType].values(), + "build_architecture_list" : self._AutoGenObject.Arch, + "architecture" : self._AutoGenObject.Arch, + "separator" : Separator, + "create_directory_command" : self.GetCreateDirectoryCommand(self.IntermediateDirectoryList), + "cleanall_command" : self.GetRemoveDirectoryCommand(self.IntermediateDirectoryList), + "library_makefile_list" : LibraryMakefileList, + "module_makefile_list" : ModuleMakefileList, + "library_build_command" : LibraryMakeCommandList, + "module_build_command" : ModuleMakeCommandList, + } + + return MakefileTemplateDict + + ## Get the root directory list for intermediate files of all modules build + # + # @retval list The list of directory + # + def GetModuleBuildDirectoryList(self): + DirList = [] + for ModuleAutoGen in self._AutoGenObject.ModuleAutoGenList: + DirList.append(os.path.join(self._AutoGenObject.BuildDir, ModuleAutoGen.BuildDir)) + return DirList + + ## Get the root directory list for intermediate files of all libraries build + # + # @retval list The list of directory + # + def GetLibraryBuildDirectoryList(self): + DirList = [] + for LibraryAutoGen in self._AutoGenObject.LibraryAutoGenList: + DirList.append(os.path.join(self._AutoGenObject.BuildDir, LibraryAutoGen.BuildDir)) + return DirList + + _TemplateDict = property(_CreateTemplateDict) + +## TopLevelMakefile class +# +# This class encapsules makefie and its generation for entrance makefile. It +# uses template to generate the content of makefile. The content of makefile +# will be got from WorkspaceAutoGen object. +# +class TopLevelMakefile(BuildFile): + ## template used to generate toplevel makefile + _TEMPLATE_ = TemplateString('''\ +${makefile_header} + +# +# Platform Macro Definition +# +PLATFORM_NAME = ${platform_name} +PLATFORM_GUID = ${platform_guid} +PLATFORM_VERSION = ${platform_version} + +# +# Build Configuration Macro Definition +# +TOOLCHAIN = ${toolchain_tag} +TOOLCHAIN_TAG = ${toolchain_tag} +TARGET = ${build_target} + +# +# Build Directory Macro Definition +# +BUILD_DIR = ${platform_build_directory} +FV_DIR = ${platform_build_directory}${separator}FV + +# +# Shell Command Macro +# +${BEGIN}${shell_command_code} = ${shell_command} +${END} + +MAKE = ${make_path} +MAKE_FILE = ${makefile_path} + +# +# Default target +# +all: modules fds + +# +# Initialization target: print build information and create necessary directories +# +init: +\t-@ +\t${BEGIN}-@${create_directory_command} +\t${END} +# +# library build target +# +libraries: init +${BEGIN}\t@cd $(BUILD_DIR)${separator}${arch} && "$(MAKE)" $(MAKE_FLAGS) libraries +${END}\t@cd $(BUILD_DIR) + +# +# module build target +# +modules: init +${BEGIN}\t@cd $(BUILD_DIR)${separator}${arch} && "$(MAKE)" $(MAKE_FLAGS) modules +${END}\t@cd $(BUILD_DIR) + +# +# Flash Device Image Target +# +fds: init +\t-@cd $(FV_DIR) +${BEGIN}\tGenFds -f ${fdf_file} -o $(BUILD_DIR) -t $(TOOLCHAIN) -b $(TARGET) -p ${active_platform} -a ${build_architecture_list} ${extra_options}${END}${BEGIN} -r ${fd} ${END}${BEGIN} -i ${fv} ${END}${BEGIN} -D ${macro} ${END} + +# +# run command for emulator platform only +# +run: +\tcd $(BUILD_DIR)${separator}IA32 && ".${separator}SecMain" +\tcd $(BUILD_DIR) + +# +# Clean intermediate files +# +clean: +${BEGIN}\t-@${sub_build_command} clean +${END}\t@cd $(BUILD_DIR) + +# +# Clean all generated files except to makefile +# +cleanall: +${BEGIN}\t${cleanall_command} +${END} + +# +# Clean all library files +# +cleanlib: +${BEGIN}\t-@${sub_build_command} cleanlib +${END}\t@cd $(BUILD_DIR)\n +''') + + ## Constructor of TopLevelMakefile + # + # @param Workspace Object of WorkspaceAutoGen class + # + def __init__(self, Workspace): + BuildFile.__init__(self, Workspace) + self.IntermediateDirectoryList = [] + + # Compose a dict object containing information used to do replacement in template + def _CreateTemplateDict(self): + Separator = self._SEP_[self._FileType] + + # any platform autogen object is ok because we just need common information + PlatformInfo = self._AutoGenObject + + if "MAKE" not in PlatformInfo.ToolDefinition or "PATH" not in PlatformInfo.ToolDefinition["MAKE"]: + EdkLogger.error("build", OPTION_MISSING, "No MAKE command defined. Please check your tools_def.txt!", + ExtraData="[%s]" % str(self._AutoGenObject)) + + for Arch in PlatformInfo.ArchList: + self.IntermediateDirectoryList.append(Separator.join(["$(BUILD_DIR)", Arch])) + self.IntermediateDirectoryList.append("$(FV_DIR)") + + # TRICK: for not generating GenFds call in makefile if no FDF file + MacroList = [] + if PlatformInfo.FdfFile != None and PlatformInfo.FdfFile != "": + FdfFileList = [PlatformInfo.FdfFile] + # macros passed to GenFds + for MacroName in GlobalData.gGlobalDefines: + MacroList.append('"%s=%s"' % (MacroName, GlobalData.gGlobalDefines[MacroName])) + else: + FdfFileList = [] + + # pass extra common options to external program called in makefile, currently GenFds.exe + ExtraOption = '' + LogLevel = EdkLogger.GetLevel() + if LogLevel == EdkLogger.VERBOSE: + ExtraOption += " -v" + elif LogLevel <= EdkLogger.DEBUG_9: + ExtraOption += " -d %d" % (LogLevel - 1) + elif LogLevel == EdkLogger.QUIET: + ExtraOption += " -q" + + if GlobalData.gCaseInsensitive: + ExtraOption += " -c" + + MakefileName = self._FILE_NAME_[self._FileType] + SubBuildCommandList = [] + for A in PlatformInfo.ArchList: + Command = self._MAKE_TEMPLATE_[self._FileType] % {"file":os.path.join("$(BUILD_DIR)", A, MakefileName)} + SubBuildCommandList.append(Command) + + MakefileTemplateDict = { + "makefile_header" : self._FILE_HEADER_[self._FileType], + "makefile_path" : os.path.join("$(BUILD_DIR)", MakefileName), + "make_path" : PlatformInfo.ToolDefinition["MAKE"]["PATH"], + "platform_name" : PlatformInfo.Name, + "platform_guid" : PlatformInfo.Guid, + "platform_version" : PlatformInfo.Version, + "platform_build_directory" : PlatformInfo.BuildDir, + + "toolchain_tag" : PlatformInfo.ToolChain, + "build_target" : PlatformInfo.BuildTarget, + "shell_command_code" : self._SHELL_CMD_[self._FileType].keys(), + "shell_command" : self._SHELL_CMD_[self._FileType].values(), + 'arch' : list(PlatformInfo.ArchList), + "build_architecture_list" : ','.join(PlatformInfo.ArchList), + "separator" : Separator, + "create_directory_command" : self.GetCreateDirectoryCommand(self.IntermediateDirectoryList), + "cleanall_command" : self.GetRemoveDirectoryCommand(self.IntermediateDirectoryList), + "sub_build_command" : SubBuildCommandList, + "fdf_file" : FdfFileList, + "active_platform" : str(PlatformInfo), + "fd" : PlatformInfo.FdTargetList, + "fv" : PlatformInfo.FvTargetList, + "extra_options" : ExtraOption, + "macro" : MacroList, + } + + return MakefileTemplateDict + + ## Get the root directory list for intermediate files of all modules build + # + # @retval list The list of directory + # + def GetModuleBuildDirectoryList(self): + DirList = [] + for ModuleAutoGen in self._AutoGenObject.ModuleAutoGenList: + DirList.append(os.path.join(self._AutoGenObject.BuildDir, ModuleAutoGen.BuildDir)) + return DirList + + ## Get the root directory list for intermediate files of all libraries build + # + # @retval list The list of directory + # + def GetLibraryBuildDirectoryList(self): + DirList = [] + for LibraryAutoGen in self._AutoGenObject.LibraryAutoGenList: + DirList.append(os.path.join(self._AutoGenObject.BuildDir, LibraryAutoGen.BuildDir)) + return DirList + + _TemplateDict = property(_CreateTemplateDict) + +# This acts like the main() function for the script, unless it is 'import'ed into another script. +if __name__ == '__main__': + pass + diff --git a/BaseTools/Source/Python/AutoGen/StrGather.py b/BaseTools/Source/Python/AutoGen/StrGather.py new file mode 100644 index 0000000000..e82ad3a10b --- /dev/null +++ b/BaseTools/Source/Python/AutoGen/StrGather.py @@ -0,0 +1,532 @@ +# Copyright (c) 2007, 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. + +# +#This file is used to parse a strings file and create or add to a string database file. +# + +## +# Import Modules +# +import re +import Common.EdkLogger as EdkLogger +from Common.BuildToolError import * +from UniClassObject import * + +## +# Static definitions +# +EFI_HII_SIBT_END = '0x00' +EFI_HII_SIBT_STRING_SCSU = '0x10' +EFI_HII_SIBT_STRING_SCSU_FONT = '0x11' +EFI_HII_SIBT_STRINGS_SCSU = '0x12' +EFI_HII_SIBT_STRINGS_SCSU_FONT = '0x13' +EFI_HII_SIBT_STRING_UCS2 = '0x14' +EFI_HII_SIBT_STRING_UCS2_FONT = '0x15' +EFI_HII_SIBT_STRINGS_UCS2 = '0x16' +EFI_HII_SIBT_STRINGS_UCS2_FONT = '0x17' +EFI_HII_SIBT_DUPLICATE = '0x20' +EFI_HII_SIBT_SKIP2 = '0x21' +EFI_HII_SIBT_SKIP1 = '0x22' +EFI_HII_SIBT_EXT1 = '0x30' +EFI_HII_SIBT_EXT2 = '0x31' +EFI_HII_SIBT_EXT4 = '0x32' +EFI_HII_SIBT_FONT = '0x40' + +EFI_HII_PACKAGE_STRINGS = '0x04' +EFI_HII_PACKAGE_FORM = '0x02' + +StringPackageType = EFI_HII_PACKAGE_STRINGS +StringPackageForm = EFI_HII_PACKAGE_FORM +StringBlockType = EFI_HII_SIBT_STRING_UCS2 +StringSkipType = EFI_HII_SIBT_SKIP2 + +HexHeader = '0x' + +COMMENT = '// ' +DEFINE_STR = '#define' +COMMENT_DEFINE_STR = COMMENT + DEFINE_STR +NOT_REFERENCED = 'not referenced' +COMMENT_NOT_REFERENCED = ' ' + COMMENT + NOT_REFERENCED +CHAR_ARRAY_DEFIN = 'unsigned char' +COMMON_FILE_NAME = 'Strings' +OFFSET = 'offset' +STRING = 'string' +TO = 'to' +STRING_TOKEN = re.compile('STRING_TOKEN *\(([A-Z0-9_]+) *\)', re.MULTILINE | re.UNICODE) + +EFI_HII_ARRAY_SIZE_LENGTH = 4 +EFI_HII_PACKAGE_HEADER_LENGTH = 4 +EFI_HII_HDR_SIZE_LENGTH = 4 +EFI_HII_STRING_OFFSET_LENGTH = 4 +EFI_STRING_ID = 1 +EFI_STRING_ID_LENGTH = 2 +EFI_HII_LANGUAGE_WINDOW = 0 +EFI_HII_LANGUAGE_WINDOW_LENGTH = 2 +EFI_HII_LANGUAGE_WINDOW_NUMBER = 16 +EFI_HII_STRING_PACKAGE_HDR_LENGTH = EFI_HII_PACKAGE_HEADER_LENGTH + EFI_HII_HDR_SIZE_LENGTH + EFI_HII_STRING_OFFSET_LENGTH + EFI_HII_LANGUAGE_WINDOW_LENGTH * EFI_HII_LANGUAGE_WINDOW_NUMBER + EFI_STRING_ID_LENGTH + +H_C_FILE_HEADER = ['//', \ + '// DO NOT EDIT -- auto-generated file', \ + '//', \ + '// This file is generated by the StrGather utility', \ + '//'] +LANGUAGE_NAME_STRING_NAME = '$LANGUAGE_NAME' +PRINTABLE_LANGUAGE_NAME_STRING_NAME = '$PRINTABLE_LANGUAGE_NAME' + +## Convert a dec number to a hex string +# +# Convert a dec number to a formatted hex string in length digit +# The digit is set to default 8 +# The hex string starts with "0x" +# DecToHexStr(1000) is '0x000003E8' +# DecToHexStr(1000, 6) is '0x0003E8' +# +# @param Dec: The number in dec format +# @param Digit: The needed digit of hex string +# +# @retval: The formatted hex string +# +def DecToHexStr(Dec, Digit = 8): + return eval("'0x%0" + str(Digit) + "X' % int(Dec)") + +## Convert a dec number to a hex list +# +# Convert a dec number to a formatted hex list in size digit +# The digit is set to default 8 +# DecToHexList(1000) is ['0xE8', '0x03', '0x00', '0x00'] +# DecToHexList(1000, 6) is ['0xE8', '0x03', '0x00'] +# +# @param Dec: The number in dec format +# @param Digit: The needed digit of hex list +# +# @retval: A list for formatted hex string +# +def DecToHexList(Dec, Digit = 8): + Hex = eval("'%0" + str(Digit) + "X' % int(Dec)" ) + List = [] + for Bit in range(Digit - 2, -1, -2): + List.append(HexHeader + Hex[Bit:Bit + 2]) + return List + +## Convert a acsii string to a hex list +# +# Convert a acsii string to a formatted hex list +# AscToHexList('en-US') is ['0x65', '0x6E', '0x2D', '0x55', '0x53'] +# +# @param Ascii: The acsii string +# +# @retval: A list for formatted hex string +# +def AscToHexList(Ascii): + List = [] + for Item in Ascii: + List.append('0x%2X' % ord(Item)) + + return List + +## Create header of .h file +# +# Create a header of .h file +# +# @param BaseName: The basename of strings +# +# @retval Str: A string for .h file header +# +def CreateHFileHeader(BaseName): + Str = '' + for Item in H_C_FILE_HEADER: + Str = WriteLine(Str, Item) + Str = WriteLine(Str, '#ifndef _' + BaseName.upper() + '_STRINGS_DEFINE_H_') + Str = WriteLine(Str, '#define _' + BaseName.upper() + '_STRINGS_DEFINE_H_') + return Str + +## Create content of .h file +# +# Create content of .h file +# +# @param BaseName: The basename of strings +# @param UniObjectClass: A UniObjectClass instance +# +# @retval Str: A string of .h file content +# +def CreateHFileContent(BaseName, UniObjectClass): + Str = '' + ValueStartPtr = 60 + Line = COMMENT_DEFINE_STR + ' ' + LANGUAGE_NAME_STRING_NAME + ' ' * (ValueStartPtr - len(DEFINE_STR + LANGUAGE_NAME_STRING_NAME)) + DecToHexStr(0, 4) + COMMENT_NOT_REFERENCED + Str = WriteLine(Str, Line) + Line = COMMENT_DEFINE_STR + ' ' + PRINTABLE_LANGUAGE_NAME_STRING_NAME + ' ' * (ValueStartPtr - len(DEFINE_STR + PRINTABLE_LANGUAGE_NAME_STRING_NAME)) + DecToHexStr(1, 4) + COMMENT_NOT_REFERENCED + Str = WriteLine(Str, Line) + for Index in range(2, len(UniObjectClass.OrderedStringList[UniObjectClass.LanguageDef[0][0]])): + StringItem = UniObjectClass.OrderedStringList[UniObjectClass.LanguageDef[0][0]][Index] + Name = StringItem.StringName + Token = StringItem.Token + Referenced = StringItem.Referenced + if Name != None: + Line = '' + if Referenced == True: + Line = DEFINE_STR + ' ' + Name + ' ' * (ValueStartPtr - len(DEFINE_STR + Name)) + DecToHexStr(Token, 4) + else: + Line = COMMENT_DEFINE_STR + ' ' + Name + ' ' * (ValueStartPtr - len(DEFINE_STR + Name)) + DecToHexStr(Token, 4) + COMMENT_NOT_REFERENCED + Str = WriteLine(Str, Line) + + Str = WriteLine(Str, '') + Str = WriteLine(Str, 'extern unsigned char ' + BaseName + 'Strings[];') + return Str + +## Create a complete .h file +# +# Create a complet .h file with file header and file content +# +# @param BaseName: The basename of strings +# @param UniObjectClass: A UniObjectClass instance +# +# @retval Str: A string of complete .h file +# +def CreateHFile(BaseName, UniObjectClass): + HFile = WriteLine('', CreateHFileContent(BaseName, UniObjectClass)) + + return HFile + +## Create header of .c file +# +# Create a header of .c file +# +# @retval Str: A string for .c file header +# +def CreateCFileHeader(): + Str = '' + for Item in H_C_FILE_HEADER: + Str = WriteLine(Str, Item) + + return Str + +## Create a formatted string all items in an array +# +# Use ',' to join each item in an array, and break an new line when reaching the width (default is 16) +# +# @param Array: The array need to be formatted +# @param Width: The line length, the default value is set to 16 +# +# @retval ArrayItem: A string for all formatted array items +# +def CreateArrayItem(Array, Width = 16): + MaxLength = Width + Index = 0 + Line = ' ' + ArrayItem = '' + + for Item in Array: + if Index < MaxLength: + Line = Line + Item + ', ' + Index = Index + 1 + else: + ArrayItem = WriteLine(ArrayItem, Line) + Line = ' ' + Item + ', ' + Index = 1 + ArrayItem = Write(ArrayItem, Line.rstrip()) + + return ArrayItem + +## CreateCFileStringValue +# +# Create a line with string value +# +# @param Value: Value of the string +# +# @retval Str: A formatted string with string value +# + +def CreateCFileStringValue(Value): + Value = [StringBlockType] + Value + Str = WriteLine('', CreateArrayItem(Value)) + + return Str + + +## Create content of .c file +# +# Create content of .c file +# +# @param BaseName: The basename of strings +# @param UniObjectClass: A UniObjectClass instance +# +# @retval Str: A string of .c file content +# +def CreateCFileContent(BaseName, UniObjectClass, IsCompatibleMode): + # + # Init array length + # + TotalLength = EFI_HII_ARRAY_SIZE_LENGTH + Str = '' + Offset = 0 + + # + # Create lines for each language's strings + # + for IndexI in range(len(UniObjectClass.LanguageDef)): + Language = UniObjectClass.LanguageDef[IndexI][0] + LangPrintName = UniObjectClass.LanguageDef[IndexI][1] + + StrStringValue = '' + ArrayLength = 0 + NumberOfUseOhterLangDef = 0 + Index = 0 + for IndexJ in range(1, len(UniObjectClass.OrderedStringList[UniObjectClass.LanguageDef[IndexI][0]])): + Item = UniObjectClass.FindByToken(IndexJ, Language) + Name = Item.StringName + Value = Item.StringValueByteList + Referenced = Item.Referenced + Token = Item.Token + Length = Item.Length + UseOtherLangDef = Item.UseOtherLangDef + + if UseOtherLangDef != '' and Referenced: + NumberOfUseOhterLangDef = NumberOfUseOhterLangDef + 1 + Index = Index + 1 + else: + if NumberOfUseOhterLangDef > 0: + StrStringValue = WriteLine(StrStringValue, CreateArrayItem([StringSkipType] + DecToHexList(NumberOfUseOhterLangDef, 4))) + NumberOfUseOhterLangDef = 0 + ArrayLength = ArrayLength + 3 + if Referenced and Item.Token > 0: + Index = Index + 1 + StrStringValue = WriteLine(StrStringValue, "// %s: %s:%s" % (DecToHexStr(Index, 4), Name, DecToHexStr(Token, 4))) + StrStringValue = Write(StrStringValue, CreateCFileStringValue(Value)) + Offset = Offset + Length + ArrayLength = ArrayLength + Item.Length + 1 # 1 is for the length of string type + + # + # EFI_HII_PACKAGE_HEADER + # + Offset = EFI_HII_STRING_PACKAGE_HDR_LENGTH + len(Language) + 1 + ArrayLength = Offset + ArrayLength + 1 + + # + # Create PACKAGE HEADER + # + Str = WriteLine(Str, '// PACKAGE HEADER\n') + TotalLength = TotalLength + ArrayLength + + List = DecToHexList(ArrayLength, 6) + \ + [StringPackageType] + \ + DecToHexList(Offset) + \ + DecToHexList(Offset) + \ + DecToHexList(EFI_HII_LANGUAGE_WINDOW, EFI_HII_LANGUAGE_WINDOW_LENGTH * 2) * EFI_HII_LANGUAGE_WINDOW_NUMBER + \ + DecToHexList(EFI_STRING_ID, 4) + \ + AscToHexList(Language) + \ + DecToHexList(0, 2) + Str = WriteLine(Str, CreateArrayItem(List, 16) + '\n') + + # + # Create PACKAGE DATA + # + Str = WriteLine(Str, '// PACKAGE DATA\n') + Str = Write(Str, StrStringValue) + + # + # Add an EFI_HII_SIBT_END at last + # + Str = WriteLine(Str, ' ' + EFI_HII_SIBT_END + ",") + + # + # Create line for string variable name + # "unsigned char $(BaseName)Strings[] = {" + # + AllStr = WriteLine('', CHAR_ARRAY_DEFIN + ' ' + BaseName + COMMON_FILE_NAME + '[] = {\n' ) + + # + # Create FRAMEWORK_EFI_HII_PACK_HEADER in compatible mode + # + if IsCompatibleMode: + AllStr = WriteLine(AllStr, '// FRAMEWORK PACKAGE HEADER Length') + AllStr = WriteLine(AllStr, CreateArrayItem(DecToHexList(TotalLength + 2)) + '\n') + AllStr = WriteLine(AllStr, '// FRAMEWORK PACKAGE HEADER Type') + AllStr = WriteLine(AllStr, CreateArrayItem(DecToHexList(2, 4)) + '\n') + + # + # Create whole array length in UEFI mode + # + if not IsCompatibleMode: + AllStr = WriteLine(AllStr, '// STRGATHER_OUTPUT_HEADER') + AllStr = WriteLine(AllStr, CreateArrayItem(DecToHexList(TotalLength)) + '\n') + + # + # Join package data + # + AllStr = Write(AllStr, Str) + + return AllStr + +## Create end of .c file +# +# Create end of .c file +# +# @retval Str: A string of .h file end +# +def CreateCFileEnd(): + Str = Write('', '};') + return Str + +## Create a .c file +# +# Create a complete .c file +# +# @param BaseName: The basename of strings +# @param UniObjectClass: A UniObjectClass instance +# +# @retval CFile: A string of complete .c file +# +def CreateCFile(BaseName, UniObjectClass, IsCompatibleMode): + CFile = '' + #CFile = WriteLine(CFile, CreateCFileHeader()) + CFile = WriteLine(CFile, CreateCFileContent(BaseName, UniObjectClass, IsCompatibleMode)) + CFile = WriteLine(CFile, CreateCFileEnd()) + return CFile + +## GetFileList +# +# Get a list for all files +# +# @param IncludeList: A list of all path to be searched +# @param SkipList: A list of all types of file could be skipped +# +# @retval FileList: A list of all files found +# +def GetFileList(SourceFileList, IncludeList, SkipList): + if IncludeList == None: + EdkLogger.error("UnicodeStringGather", AUTOGEN_ERROR, "Include path for unicode file is not defined") + + FileList = [] + if SkipList == None: + SkipList = [] + + for File in SourceFileList: + for Dir in IncludeList: + if not os.path.exists(Dir): + continue + File = os.path.join(Dir, File.Path) + # + # Ignore Dir + # + if os.path.isfile(File) != True: + continue + # + # Ignore file listed in skip list + # + IsSkip = False + for Skip in SkipList: + if os.path.splitext(File)[1].upper() == Skip.upper(): + EdkLogger.verbose("Skipped %s for string token uses search" % File) + IsSkip = True + break + + if not IsSkip: + FileList.append(File) + + break + + return FileList + +## SearchString +# +# Search whether all string defined in UniObjectClass are referenced +# All string used should be set to Referenced +# +# @param UniObjectClass: Input UniObjectClass +# @param FileList: Search path list +# +# @retval UniObjectClass: UniObjectClass after searched +# +def SearchString(UniObjectClass, FileList): + if FileList == []: + return UniObjectClass + + for File in FileList: + if os.path.isfile(File): + Lines = open(File, 'r') + for Line in Lines: + StringTokenList = STRING_TOKEN.findall(Line) + for StrName in StringTokenList: + EdkLogger.debug(EdkLogger.DEBUG_5, "Found string identifier: " + StrName) + UniObjectClass.SetStringReferenced(StrName) + + UniObjectClass.ReToken() + + return UniObjectClass + +## GetStringFiles +# +# This function is used for UEFI2.1 spec +# +# +def GetStringFiles(UniFilList, SourceFileList, IncludeList, SkipList, BaseName, IsCompatibleMode = False, ShellMode = False): + Status = True + ErrorMessage = '' + + if len(UniFilList) > 0: + if ShellMode: + # + # support ISO 639-2 codes in .UNI files of EDK Shell + # + Uni = UniFileClassObject(UniFilList, True) + else: + Uni = UniFileClassObject(UniFilList, IsCompatibleMode) + else: + EdkLogger.error("UnicodeStringGather", AUTOGEN_ERROR, 'No unicode files given') + + FileList = GetFileList(SourceFileList, IncludeList, SkipList) + + Uni = SearchString(Uni, FileList) + + HFile = CreateHFile(BaseName, Uni) + CFile = CreateCFile(BaseName, Uni, IsCompatibleMode) + + return HFile, CFile + +# +# Write an item +# +def Write(Target, Item): + return Target + Item + +# +# Write an item with a break line +# +def WriteLine(Target, Item): + return Target + Item + '\n' + +# This acts like the main() function for the script, unless it is 'import'ed into another +# script. +if __name__ == '__main__': + EdkLogger.info('start') + + UniFileList = [ + r'C:\\Edk\\Strings2.uni', + r'C:\\Edk\\Strings.uni' + ] + + SrcFileList = [] + for Root, Dirs, Files in os.walk('C:\\Edk'): + for File in Files: + SrcFileList.append(File) + + IncludeList = [ + r'C:\\Edk' + ] + + SkipList = ['.inf', '.uni'] + BaseName = 'DriverSample' + (h, c) = GetStringFiles(UniFileList, SrcFileList, IncludeList, SkipList, BaseName, True) + hfile = open('unistring.h', 'w') + cfile = open('unistring.c', 'w') + hfile.write(h) + cfile.write(c) + + EdkLogger.info('end') diff --git a/BaseTools/Source/Python/AutoGen/UniClassObject.py b/BaseTools/Source/Python/AutoGen/UniClassObject.py new file mode 100644 index 0000000000..412fa72df0 --- /dev/null +++ b/BaseTools/Source/Python/AutoGen/UniClassObject.py @@ -0,0 +1,530 @@ +# Copyright (c) 2007, 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. + +# +#This file is used to collect all defined strings in multiple uni files +# + +## +# Import Modules +# +import os, codecs, re +import Common.EdkLogger as EdkLogger +from Common.BuildToolError import * +from Common.String import GetLineNo +from Common.Misc import PathClass + +## +# Static definitions +# +UNICODE_WIDE_CHAR = u'\\wide' +UNICODE_NARROW_CHAR = u'\\narrow' +UNICODE_NON_BREAKING_CHAR = u'\\nbr' +UNICODE_UNICODE_CR = '\r' +UNICODE_UNICODE_LF = '\n' + +NARROW_CHAR = u'\uFFF0' +WIDE_CHAR = u'\uFFF1' +NON_BREAKING_CHAR = u'\uFFF2' +CR = u'\u000D' +LF = u'\u000A' +NULL = u'\u0000' +TAB = u'\t' +BACK_SPLASH = u'\\' + +gIncludePattern = re.compile("^#include +[\"<]+([^\"< >]+)[>\"]+$", re.MULTILINE | re.UNICODE) + +## Convert a python unicode string to a normal string +# +# Convert a python unicode string to a normal string +# UniToStr(u'I am a string') is 'I am a string' +# +# @param Uni: The python unicode string +# +# @retval: The formatted normal string +# +def UniToStr(Uni): + return repr(Uni)[2:-1] + +## Convert a unicode string to a Hex list +# +# Convert a unicode string to a Hex list +# UniToHexList('ABC') is ['0x41', '0x00', '0x42', '0x00', '0x43', '0x00'] +# +# @param Uni: The python unicode string +# +# @retval List: The formatted hex list +# +def UniToHexList(Uni): + List = [] + for Item in Uni: + Temp = '%04X' % ord(Item) + List.append('0x' + Temp[2:4]) + List.append('0x' + Temp[0:2]) + return List + +LangConvTable = {'eng':'en', 'fra':'fr', \ + 'aar':'aa', 'abk':'ab', 'ave':'ae', 'afr':'af', 'aka':'ak', 'amh':'am', \ + 'arg':'an', 'ara':'ar', 'asm':'as', 'ava':'av', 'aym':'ay', 'aze':'az', \ + 'bak':'ba', 'bel':'be', 'bul':'bg', 'bih':'bh', 'bis':'bi', 'bam':'bm', \ + 'ben':'bn', 'bod':'bo', 'bre':'br', 'bos':'bs', 'cat':'ca', 'che':'ce', \ + 'cha':'ch', 'cos':'co', 'cre':'cr', 'ces':'cs', 'chu':'cu', 'chv':'cv', \ + 'cym':'cy', 'dan':'da', 'deu':'de', 'div':'dv', 'dzo':'dz', 'ewe':'ee', \ + 'ell':'el', 'epo':'eo', 'spa':'es', 'est':'et', 'eus':'eu', 'fas':'fa', \ + 'ful':'ff', 'fin':'fi', 'fij':'fj', 'fao':'fo', 'fry':'fy', 'gle':'ga', \ + 'gla':'gd', 'glg':'gl', 'grn':'gn', 'guj':'gu', 'glv':'gv', 'hau':'ha', \ + 'heb':'he', 'hin':'hi', 'hmo':'ho', 'hrv':'hr', 'hat':'ht', 'hun':'hu', \ + 'hye':'hy', 'her':'hz', 'ina':'ia', 'ind':'id', 'ile':'ie', 'ibo':'ig', \ + 'iii':'ii', 'ipk':'ik', 'ido':'io', 'isl':'is', 'ita':'it', 'iku':'iu', \ + 'jpn':'ja', 'jav':'jv', 'kat':'ka', 'kon':'kg', 'kik':'ki', 'kua':'kj', \ + 'kaz':'kk', 'kal':'kl', 'khm':'km', 'kan':'kn', 'kor':'ko', 'kau':'kr', \ + 'kas':'ks', 'kur':'ku', 'kom':'kv', 'cor':'kw', 'kir':'ky', 'lat':'la', \ + 'ltz':'lb', 'lug':'lg', 'lim':'li', 'lin':'ln', 'lao':'lo', 'lit':'lt', \ + 'lub':'lu', 'lav':'lv', 'mlg':'mg', 'mah':'mh', 'mri':'mi', 'mkd':'mk', \ + 'mal':'ml', 'mon':'mn', 'mar':'mr', 'msa':'ms', 'mlt':'mt', 'mya':'my', \ + 'nau':'na', 'nob':'nb', 'nde':'nd', 'nep':'ne', 'ndo':'ng', 'nld':'nl', \ + 'nno':'nn', 'nor':'no', 'nbl':'nr', 'nav':'nv', 'nya':'ny', 'oci':'oc', \ + 'oji':'oj', 'orm':'om', 'ori':'or', 'oss':'os', 'pan':'pa', 'pli':'pi', \ + 'pol':'pl', 'pus':'ps', 'por':'pt', 'que':'qu', 'roh':'rm', 'run':'rn', \ + 'ron':'ro', 'rus':'ru', 'kin':'rw', 'san':'sa', 'srd':'sc', 'snd':'sd', \ + 'sme':'se', 'sag':'sg', 'sin':'si', 'slk':'sk', 'slv':'sl', 'smo':'sm', \ + 'sna':'sn', 'som':'so', 'sqi':'sq', 'srp':'sr', 'ssw':'ss', 'sot':'st', \ + 'sun':'su', 'swe':'sv', 'swa':'sw', 'tam':'ta', 'tel':'te', 'tgk':'tg', \ + 'tha':'th', 'tir':'ti', 'tuk':'tk', 'tgl':'tl', 'tsn':'tn', 'ton':'to', \ + 'tur':'tr', 'tso':'ts', 'tat':'tt', 'twi':'tw', 'tah':'ty', 'uig':'ug', \ + 'ukr':'uk', 'urd':'ur', 'uzb':'uz', 'ven':'ve', 'vie':'vi', 'vol':'vo', \ + 'wln':'wa', 'wol':'wo', 'xho':'xh', 'yid':'yi', 'yor':'yo', 'zha':'za', \ + 'zho':'zh', 'zul':'zu'} + +## GetLanguageCode +# +# Check the language code read from .UNI file and convert ISO 639-2 codes to RFC 4646 codes if appropriate +# ISO 639-2 language codes supported in compatiblity mode +# RFC 4646 language codes supported in native mode +# +# @param LangName: Language codes read from .UNI file +# +# @retval LangName: Valid lanugage code in RFC 4646 format or None +# +def GetLanguageCode(LangName, IsCompatibleMode, File): + global LangConvTable + + length = len(LangName) + if IsCompatibleMode: + if length == 3 and LangName.isalpha(): + TempLangName = LangConvTable.get(LangName.lower()) + if TempLangName != None: + return TempLangName + return LangName + else: + EdkLogger.error("Unicode File Parser", FORMAT_INVALID, "Invalid ISO 639-2 language code : %s" % LangName, File) + + if length == 2: + if LangName.isalpha(): + return LangName + elif length == 3: + if LangName.isalpha() and LangConvTable.get(LangName.lower()) == None: + return LangName + elif length == 5: + if LangName[0:2].isalpha() and LangName[2] == '-': + return LangName + elif length >= 6: + if LangName[0:2].isalpha() and LangName[2] == '-': + return LangName + if LangName[0:3].isalpha() and LangConvTable.get(LangName.lower()) == None and LangName[3] == '-': + return LangName + + EdkLogger.error("Unicode File Parser", FORMAT_INVALID, "Invalid RFC 4646 language code : %s" % LangName, File) + +## StringDefClassObject +# +# A structure for language definition +# +class StringDefClassObject(object): + def __init__(self, Name = None, Value = None, Referenced = False, Token = None, UseOtherLangDef = ''): + self.StringName = '' + self.StringNameByteList = [] + self.StringValue = '' + self.StringValueByteList = '' + self.Token = 0 + self.Referenced = Referenced + self.UseOtherLangDef = UseOtherLangDef + self.Length = 0 + + if Name != None: + self.StringName = Name + self.StringNameByteList = UniToHexList(Name) + if Value != None: + self.StringValue = Value + u'\x00' # Add a NULL at string tail + self.StringValueByteList = UniToHexList(self.StringValue) + self.Length = len(self.StringValueByteList) + if Token != None: + self.Token = Token + + def __str__(self): + return repr(self.StringName) + ' ' + \ + repr(self.Token) + ' ' + \ + repr(self.Referenced) + ' ' + \ + repr(self.StringValue) + ' ' + \ + repr(self.UseOtherLangDef) + +## UniFileClassObject +# +# A structure for .uni file definition +# +class UniFileClassObject(object): + def __init__(self, FileList = [], IsCompatibleMode = False): + self.FileList = FileList + self.Token = 2 + self.LanguageDef = [] #[ [u'LanguageIdentifier', u'PrintableName'], ... ] + self.OrderedStringList = {} #{ u'LanguageIdentifier' : [StringDefClassObject] } + self.IsCompatibleMode = IsCompatibleMode + + if len(self.FileList) > 0: + self.LoadUniFiles(FileList) + + # + # Get Language definition + # + def GetLangDef(self, File, Line): + Lang = Line.split() + if len(Lang) != 3: + try: + FileIn = codecs.open(File, mode='rb', encoding='utf-16').read() + except UnicodeError, X: + EdkLogger.error("build", FILE_READ_FAILURE, "File read failure: %s" % str(X), ExtraData=File); + except: + EdkLogger.error("build", FILE_OPEN_FAILURE, ExtraData=File); + LineNo = GetLineNo(FileIn, Line, False) + EdkLogger.error("Unicode File Parser", PARSER_ERROR, "Wrong language definition", + ExtraData="""%s\n\t*Correct format is like '#langdef eng "English"'""" % Line, File = File, Line = LineNo) + else: + LangName = GetLanguageCode(Lang[1], self.IsCompatibleMode, self.File) + LangPrintName = Lang[2][1:-1] + + IsLangInDef = False + for Item in self.LanguageDef: + if Item[0] == LangName: + IsLangInDef = True + break; + + if not IsLangInDef: + self.LanguageDef.append([LangName, LangPrintName]) + + # + # Add language string + # + self.AddStringToList(u'$LANGUAGE_NAME', LangName, LangName, 0, True, Index=0) + self.AddStringToList(u'$PRINTABLE_LANGUAGE_NAME', LangName, LangPrintName, 1, True, Index=1) + + return True + + # + # Get String name and value + # + def GetStringObject(self, Item): + Name = '' + Language = '' + Value = '' + + Name = Item.split()[1] + LanguageList = Item.split(u'#language ') + for IndexI in range(len(LanguageList)): + if IndexI == 0: + continue + else: + Language = LanguageList[IndexI].split()[0] + Value = LanguageList[IndexI][LanguageList[IndexI].find(u'\"') + len(u'\"') : LanguageList[IndexI].rfind(u'\"')] #.replace(u'\r\n', u'') + Language = GetLanguageCode(Language, self.IsCompatibleMode, self.File) + self.AddStringToList(Name, Language, Value) + + # + # Get include file list and load them + # + def GetIncludeFile(self, Item, Dir): + FileName = Item[Item.find(u'#include ') + len(u'#include ') :Item.find(u' ', len(u'#include '))][1:-1] + self.LoadUniFile(FileName) + + # + # Pre-process before parse .uni file + # + def PreProcess(self, File): + if not os.path.exists(File.Path) or not os.path.isfile(File.Path): + EdkLogger.error("Unicode File Parser", FILE_NOT_FOUND, ExtraData=File.Path) + + Dir = File.Dir + try: + FileIn = codecs.open(File.Path, mode='rb', encoding='utf-16').readlines() + except UnicodeError, X: + EdkLogger.error("build", FILE_READ_FAILURE, "File read failure: %s" % str(X), ExtraData=File.Path); + except: + EdkLogger.error("build", FILE_OPEN_FAILURE, ExtraData=File.Path); + + Lines = [] + # + # Use unique identifier + # + for Line in FileIn: + Line = Line.strip() + # + # Ignore comment line and empty line + # + if Line == u'' or Line.startswith(u'//'): + continue + Line = Line.replace(u'/langdef', u'#langdef') + Line = Line.replace(u'/string', u'#string') + Line = Line.replace(u'/language', u'#language') + Line = Line.replace(u'/include', u'#include') + + Line = Line.replace(UNICODE_WIDE_CHAR, WIDE_CHAR) + Line = Line.replace(UNICODE_NARROW_CHAR, NARROW_CHAR) + Line = Line.replace(UNICODE_NON_BREAKING_CHAR, NON_BREAKING_CHAR) + + Line = Line.replace(u'\\\\', u'\u0006') + Line = Line.replace(u'\\r\\n', CR + LF) + Line = Line.replace(u'\\n', CR + LF) + Line = Line.replace(u'\\r', CR) + Line = Line.replace(u'\\t', u'\t') + Line = Line.replace(u'''\"''', u'''"''') + Line = Line.replace(u'\t', u' ') + Line = Line.replace(u'\u0006', u'\\') + +# if Line.find(u'\\x'): +# hex = Line[Line.find(u'\\x') + 2 : Line.find(u'\\x') + 6] +# hex = "u'\\u" + hex + "'" + + IncList = gIncludePattern.findall(Line) + if len(IncList) == 1: + Lines.extend(self.PreProcess(PathClass(str(IncList[0]), Dir))) + continue + + Lines.append(Line) + + return Lines + + # + # Load a .uni file + # + def LoadUniFile(self, File = None): + if File == None: + EdkLogger.error("Unicode File Parser", PARSER_ERROR, 'No unicode file is given') + self.File = File + # + # Process special char in file + # + Lines = self.PreProcess(File) + + # + # Get Unicode Information + # + for IndexI in range(len(Lines)): + Line = Lines[IndexI] + if (IndexI + 1) < len(Lines): + SecondLine = Lines[IndexI + 1] + if (IndexI + 2) < len(Lines): + ThirdLine = Lines[IndexI + 2] + + # + # Get Language def information + # + if Line.find(u'#langdef ') >= 0: + self.GetLangDef(File, Line) + continue + + Name = '' + Language = '' + Value = '' + # + # Get string def information format 1 as below + # + # #string MY_STRING_1 + # #language eng + # My first English string line 1 + # My first English string line 2 + # #string MY_STRING_1 + # #language spa + # Mi segunda secuencia 1 + # Mi segunda secuencia 2 + # + if Line.find(u'#string ') >= 0 and Line.find(u'#language ') < 0 and \ + SecondLine.find(u'#string ') < 0 and SecondLine.find(u'#language ') >= 0 and \ + ThirdLine.find(u'#string ') < 0 and ThirdLine.find(u'#language ') < 0: + Name = Line[Line.find(u'#string ') + len(u'#string ') : ].strip(' ') + Language = SecondLine[SecondLine.find(u'#language ') + len(u'#language ') : ].strip(' ') + for IndexJ in range(IndexI + 2, len(Lines)): + if Lines[IndexJ].find(u'#string ') < 0 and Lines[IndexJ].find(u'#language ') < 0: + Value = Value + Lines[IndexJ] + else: + IndexI = IndexJ + break + # Value = Value.replace(u'\r\n', u'') + Language = GetLanguageCode(Language, self.IsCompatibleMode, self.File) + self.AddStringToList(Name, Language, Value) + continue + + # + # Get string def information format 2 as below + # + # #string MY_STRING_1 #language eng "My first English string line 1" + # "My first English string line 2" + # #language spa "Mi segunda secuencia 1" + # "Mi segunda secuencia 2" + # #string MY_STRING_2 #language eng "My first English string line 1" + # "My first English string line 2" + # #string MY_STRING_2 #language spa "Mi segunda secuencia 1" + # "Mi segunda secuencia 2" + # + if Line.find(u'#string ') >= 0 and Line.find(u'#language ') >= 0: + StringItem = Line + for IndexJ in range(IndexI + 1, len(Lines)): + if Lines[IndexJ].find(u'#string ') >= 0 and Lines[IndexJ].find(u'#language ') >= 0: + IndexI = IndexJ + break + elif Lines[IndexJ].find(u'#string ') < 0 and Lines[IndexJ].find(u'#language ') >= 0: + StringItem = StringItem + Lines[IndexJ] + elif Lines[IndexJ].count(u'\"') >= 2: + StringItem = StringItem[ : StringItem.rfind(u'\"')] + Lines[IndexJ][Lines[IndexJ].find(u'\"') + len(u'\"') : ] + self.GetStringObject(StringItem) + continue + + # + # Load multiple .uni files + # + def LoadUniFiles(self, FileList = []): + if len(FileList) > 0: + if len(FileList) > 1: + NewList = []; + for File in FileList: + NewList.append (File) + NewList.sort() + for File in NewList: + self.LoadUniFile(File) + else: + for File in FileList: + self.LoadUniFile(File) + + # + # Add a string to list + # + def AddStringToList(self, Name, Language, Value, Token = None, Referenced = False, UseOtherLangDef = '', Index = -1): + if Language not in self.OrderedStringList: + self.OrderedStringList[Language] = [] + + IsAdded = False + for Item in self.OrderedStringList[Language]: + if Name == Item.StringName: + IsAdded = True + break + if not IsAdded: + Token = len(self.OrderedStringList[Language]) + if Index == -1: + self.OrderedStringList[Language].append(StringDefClassObject(Name, Value, Referenced, Token, UseOtherLangDef)) + else: + self.OrderedStringList[Language].insert(Index, StringDefClassObject(Name, Value, Referenced, Token, UseOtherLangDef)) + + # + # Set the string as referenced + # + def SetStringReferenced(self, Name): + for Lang in self.OrderedStringList: + for Item in self.OrderedStringList[Lang]: + if Name == Item.StringName: + Item.Referenced = True + break + # + # Search the string in language definition by Name + # + def FindStringValue(self, Name, Lang): + for Item in self.OrderedStringList[Lang]: + if Item.StringName == Name: + return Item + + return None + + # + # Search the string in language definition by Token + # + def FindByToken(self, Token, Lang): + for Item in self.OrderedStringList[Lang]: + if Item.Token == Token: + return Item + + return None + + # + # Re-order strings and re-generate tokens + # + def ReToken(self): + # + # Search each string to find if it is defined for each language + # Use secondary language value to replace if missing in any one language + # + for IndexI in range(0, len(self.LanguageDef)): + LangKey = self.LanguageDef[IndexI][0] + for Item in self.OrderedStringList[LangKey]: + Name = Item.StringName + Value = Item.StringValue[0:-1] + Referenced = Item.Referenced + Index = self.OrderedStringList[LangKey].index(Item) + for IndexJ in range(0, len(self.LanguageDef)): + LangFind = self.LanguageDef[IndexJ][0] + if self.FindStringValue(Name, LangFind) == None: + EdkLogger.debug(EdkLogger.DEBUG_5, Name) + Token = len(self.OrderedStringList[LangFind]) + self.AddStringToList(Name, LangFind, Value, Token, Referenced, LangKey, Index) + + # + # Retoken + # + # First re-token the first language + LangName = self.LanguageDef[0][0] + ReferencedStringList = [] + NotReferencedStringList = [] + Token = 0 + for Item in self.OrderedStringList[LangName]: + if Item.Referenced == True: + Item.Token = Token + ReferencedStringList.append(Item) + Token = Token + 1 + else: + NotReferencedStringList.append(Item) + self.OrderedStringList[LangName] = ReferencedStringList + for Index in range(len(NotReferencedStringList)): + NotReferencedStringList[Index].Token = Token + Index + self.OrderedStringList[LangName].append(NotReferencedStringList[Index]) + + # + # Adjust the orders of other languages + # + for IndexOfLanguage in range(1, len(self.LanguageDef)): + for OrderedString in self.OrderedStringList[LangName]: + for UnOrderedString in self.OrderedStringList[self.LanguageDef[IndexOfLanguage][0]]: + if OrderedString.StringName == UnOrderedString.StringName: + UnOrderedString.Token = OrderedString.Token + break + + # + # Show the instance itself + # + def ShowMe(self): + print self.LanguageDef + #print self.OrderedStringList + for Item in self.OrderedStringList: + print Item + for Member in self.OrderedStringList[Item]: + print str(Member) + +# This acts like the main() function for the script, unless it is 'import'ed into another +# script. +if __name__ == '__main__': + EdkLogger.Initialize() + EdkLogger.SetLevel(EdkLogger.DEBUG_0) + a = UniFileClassObject(['C:\\Edk\\Strings.uni', 'C:\\Edk\\Strings2.uni']) + a.ReToken() + a.ShowMe() diff --git a/BaseTools/Source/Python/AutoGen/__init__.py b/BaseTools/Source/Python/AutoGen/__init__.py new file mode 100644 index 0000000000..d6fa5ec126 --- /dev/null +++ b/BaseTools/Source/Python/AutoGen/__init__.py @@ -0,0 +1,10 @@ +# Copyright (c) 2007, 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. + +__all__ = ["AutoGen"] diff --git a/BaseTools/Source/Python/Common/BuildToolError.py b/BaseTools/Source/Python/Common/BuildToolError.py new file mode 100644 index 0000000000..982ea93659 --- /dev/null +++ b/BaseTools/Source/Python/Common/BuildToolError.py @@ -0,0 +1,152 @@ +## @file +# Standardized Error Hanlding infrastructures. +# +# Copyright (c) 2007, 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. +# + +FILE_OPEN_FAILURE = 1 +FILE_WRITE_FAILURE = 2 +FILE_PARSE_FAILURE = 3 +FILE_READ_FAILURE = 4 +FILE_CREATE_FAILURE = 5 +FILE_CHECKSUM_FAILURE = 6 +FILE_COMPRESS_FAILURE = 7 +FILE_DECOMPRESS_FAILURE = 8 +FILE_MOVE_FAILURE = 9 +FILE_DELETE_FAILURE = 10 +FILE_COPY_FAILURE = 11 +FILE_POSITIONING_FAILURE = 12 +FILE_ALREADY_EXIST = 13 +FILE_NOT_FOUND = 14 +FILE_TYPE_MISMATCH = 15 +FILE_CASE_MISMATCH = 16 +FILE_DUPLICATED = 17 +FILE_UNKNOWN_ERROR = 0x0FFF + +OPTION_UNKNOWN = 0x1000 +OPTION_MISSING = 0x1001 +OPTION_CONFLICT = 0x1002 +OPTION_VALUE_INVALID = 0x1003 +OPTION_DEPRECATED = 0x1004 +OPTION_NOT_SUPPORTED = 0x1005 +OPTION_UNKNOWN_ERROR = 0x1FFF + +PARAMETER_INVALID = 0x2000 +PARAMETER_MISSING = 0x2001 +PARAMETER_UNKNOWN_ERROR =0x2FFF + +FORMAT_INVALID = 0x3000 +FORMAT_NOT_SUPPORTED = 0x3001 +FORMAT_UNKNOWN = 0x3002 +FORMAT_UNKNOWN_ERROR = 0x3FFF + +RESOURCE_NOT_AVAILABLE = 0x4000 +RESOURCE_ALLOCATE_FAILURE = 0x4001 +RESOURCE_FULL = 0x4002 +RESOURCE_OVERFLOW = 0x4003 +RESOURCE_UNDERRUN = 0x4004 +RESOURCE_UNKNOWN_ERROR = 0x4FFF + +ATTRIBUTE_NOT_AVAILABLE = 0x5000 +ATTRIBUTE_GET_FAILURE = 0x5001 +ATTRIBUTE_SET_FAILURE = 0x5002 +ATTRIBUTE_UPDATE_FAILURE = 0x5003 +ATTRIBUTE_ACCESS_DENIED = 0x5004 +ATTRIBUTE_UNKNOWN_ERROR = 0x5FFF + +IO_NOT_READY = 0x6000 +IO_BUSY = 0x6001 +IO_TIMEOUT = 0x6002 +IO_UNKNOWN_ERROR = 0x6FFF + +COMMAND_FAILURE = 0x7000 + +CODE_ERROR = 0xC0DE + +AUTOGEN_ERROR = 0xF000 +PARSER_ERROR = 0xF001 +BUILD_ERROR = 0xF002 +GENFDS_ERROR = 0xF003 +ECC_ERROR = 0xF004 +EOT_ERROR = 0xF005 +DDC_ERROR = 0xF009 +WARNING_AS_ERROR = 0xF006 +MIGRATION_ERROR = 0xF010 +ABORT_ERROR = 0xFFFE +UNKNOWN_ERROR = 0xFFFF + +## Error message of each error code +gErrorMessage = { + FILE_NOT_FOUND : "File/directory not found", + FILE_OPEN_FAILURE : "File open failure", + FILE_WRITE_FAILURE : "File write failure", + FILE_PARSE_FAILURE : "File parse failure", + FILE_READ_FAILURE : "File read failure", + FILE_CREATE_FAILURE : "File create failure", + FILE_CHECKSUM_FAILURE : "Invalid checksum of file", + FILE_COMPRESS_FAILURE : "File compress failure", + FILE_DECOMPRESS_FAILURE : "File decompress failure", + FILE_MOVE_FAILURE : "File move failure", + FILE_DELETE_FAILURE : "File delete failure", + FILE_COPY_FAILURE : "File copy failure", + FILE_POSITIONING_FAILURE: "Failed to seeking position", + FILE_ALREADY_EXIST : "File or directory already exists", + FILE_TYPE_MISMATCH : "Incorrect file type", + FILE_CASE_MISMATCH : "File name case mismatch", + FILE_DUPLICATED : "Duplicated file found", + FILE_UNKNOWN_ERROR : "Unknown error encountered on file", + + OPTION_UNKNOWN : "Unknown option", + OPTION_MISSING : "Missing option", + OPTION_CONFLICT : "Conflict options", + OPTION_VALUE_INVALID : "Invalid value of option", + OPTION_DEPRECATED : "Deprecated option", + OPTION_NOT_SUPPORTED : "Unsupported option", + OPTION_UNKNOWN_ERROR : "Unknown error when processing options", + + PARAMETER_INVALID : "Invalid parameter", + PARAMETER_MISSING : "Missing parameter", + PARAMETER_UNKNOWN_ERROR : "Unknown error in parameters", + + FORMAT_INVALID : "Invalid syntax/format", + FORMAT_NOT_SUPPORTED : "Not supported syntax/format", + FORMAT_UNKNOWN : "Unknown format", + FORMAT_UNKNOWN_ERROR : "Unknown error in syntax/format ", + + RESOURCE_NOT_AVAILABLE : "Not available", + RESOURCE_ALLOCATE_FAILURE : "Allocate failure", + RESOURCE_FULL : "Full", + RESOURCE_OVERFLOW : "Overflow", + RESOURCE_UNDERRUN : "Underrun", + RESOURCE_UNKNOWN_ERROR : "Unkown error", + + ATTRIBUTE_NOT_AVAILABLE : "Not available", + ATTRIBUTE_GET_FAILURE : "Failed to retrieve", + ATTRIBUTE_SET_FAILURE : "Failed to set", + ATTRIBUTE_UPDATE_FAILURE: "Failed to update", + ATTRIBUTE_ACCESS_DENIED : "Access denied", + ATTRIBUTE_UNKNOWN_ERROR : "Unknown error when accessing", + + COMMAND_FAILURE : "Failed to execute command", + + IO_NOT_READY : "Not ready", + IO_BUSY : "Busy", + IO_TIMEOUT : "Timeout", + IO_UNKNOWN_ERROR : "Unknown error in IO operation", + + UNKNOWN_ERROR : "Unknown error", +} + +## Exception indicating a fatal error +class FatalError(Exception): + pass + +if __name__ == "__main__": + pass diff --git a/BaseTools/Source/Python/Common/DataType.py b/BaseTools/Source/Python/Common/DataType.py new file mode 100644 index 0000000000..8b6c4e4921 --- /dev/null +++ b/BaseTools/Source/Python/Common/DataType.py @@ -0,0 +1,401 @@ +## @file +# This file is used to define common static strings used by INF/DEC/DSC files +# +# Copyright (c) 2007 ~ 2008, 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. + +## +# Common Definitions +# +TAB_SPLIT = '.' +TAB_COMMENT_R8_START = '/*' +TAB_COMMENT_R8_END = '*/' +TAB_COMMENT_R8_SPLIT = '//' +TAB_COMMENT_SPLIT = '#' +TAB_EQUAL_SPLIT = '=' +TAB_VALUE_SPLIT = '|' +TAB_COMMA_SPLIT = ',' +TAB_SPACE_SPLIT = ' ' +TAB_SECTION_START = '[' +TAB_SECTION_END = ']' +TAB_OPTION_START = '<' +TAB_OPTION_END = '>' +TAB_SLASH = '\\' +TAB_BACK_SLASH = '/' + +TAB_EDK_SOURCE = '$(EDK_SOURCE)' +TAB_EFI_SOURCE = '$(EFI_SOURCE)' +TAB_WORKSPACE = '$(WORKSPACE)' + +TAB_ARCH_NULL = '' +TAB_ARCH_COMMON = 'COMMON' +TAB_ARCH_IA32 = 'IA32' +TAB_ARCH_X64 = 'X64' +TAB_ARCH_IPF = 'IPF' +TAB_ARCH_ARM = 'ARM' +TAB_ARCH_EBC = 'EBC' + +ARCH_LIST = [TAB_ARCH_IA32, TAB_ARCH_X64, TAB_ARCH_IPF, TAB_ARCH_ARM, TAB_ARCH_EBC] +ARCH_LIST_FULL = [TAB_ARCH_COMMON] + ARCH_LIST + +SUP_MODULE_BASE = 'BASE' +SUP_MODULE_SEC = 'SEC' +SUP_MODULE_PEI_CORE = 'PEI_CORE' +SUP_MODULE_PEIM = 'PEIM' +SUP_MODULE_DXE_CORE = 'DXE_CORE' +SUP_MODULE_DXE_DRIVER = 'DXE_DRIVER' +SUP_MODULE_DXE_RUNTIME_DRIVER = 'DXE_RUNTIME_DRIVER' +SUP_MODULE_DXE_SAL_DRIVER = 'DXE_SAL_DRIVER' +SUP_MODULE_DXE_SMM_DRIVER = 'DXE_SMM_DRIVER' +SUP_MODULE_UEFI_DRIVER = 'UEFI_DRIVER' +SUP_MODULE_UEFI_APPLICATION = 'UEFI_APPLICATION' +SUP_MODULE_USER_DEFINED = 'USER_DEFINED' +SUP_MODULE_SMM_DRIVER = 'SMM_DRIVER' +SUP_MODULE_SMM_CORE = 'SMM_CORE' + +SUP_MODULE_LIST = [SUP_MODULE_BASE, SUP_MODULE_SEC, SUP_MODULE_PEI_CORE, SUP_MODULE_PEIM, SUP_MODULE_DXE_CORE, SUP_MODULE_DXE_DRIVER, \ + SUP_MODULE_DXE_RUNTIME_DRIVER, SUP_MODULE_DXE_SAL_DRIVER, SUP_MODULE_DXE_SMM_DRIVER, SUP_MODULE_UEFI_DRIVER, \ + SUP_MODULE_UEFI_APPLICATION, SUP_MODULE_USER_DEFINED, SUP_MODULE_SMM_DRIVER, SUP_MODULE_SMM_CORE] +SUP_MODULE_LIST_STRING = TAB_VALUE_SPLIT.join(l for l in SUP_MODULE_LIST) + +EDK_COMPONENT_TYPE_LIBRARY = 'LIBRARY' +EDK_COMPONENT_TYPE_SECUARITY_CORE = 'SECUARITY_CORE' +EDK_COMPONENT_TYPE_PEI_CORE = 'PEI_CORE' +EDK_COMPONENT_TYPE_COMBINED_PEIM_DRIVER = 'COMBINED_PEIM_DRIVER' +EDK_COMPONENT_TYPE_PIC_PEIM = 'PIC_PEIM' +EDK_COMPONENT_TYPE_RELOCATABLE_PEIM = 'RELOCATABLE_PEIM' +EDK_COMPONENT_TYPE_BS_DRIVER = 'BS_DRIVER' +EDK_COMPONENT_TYPE_RT_DRIVER = 'RT_DRIVER' +EDK_COMPONENT_TYPE_SAL_RT_DRIVER = 'SAL_RT_DRIVER' +EDK_COMPONENT_TYPE_APPLICATION = 'APPLICATION' + +BINARY_FILE_TYPE_FW = 'FW' +BINARY_FILE_TYPE_GUID = 'GUID' +BINARY_FILE_TYPE_PREEFORM = 'PREEFORM' +BINARY_FILE_TYPE_UEFI_APP = 'UEFI_APP' +BINARY_FILE_TYPE_UNI_UI = 'UNI_UI' +BINARY_FILE_TYPE_UNI_VER = 'UNI_VER' +BINARY_FILE_TYPE_LIB = 'LIB' +BINARY_FILE_TYPE_PE32 = 'PE32' +BINARY_FILE_TYPE_PIC = 'PIC' +BINARY_FILE_TYPE_PEI_DEPEX = 'PEI_DEPEX' +BINARY_FILE_TYPE_DXE_DEPEX = 'DXE_DEPEX' +BINARY_FILE_TYPE_TE = 'TE' +BINARY_FILE_TYPE_VER = 'VER' +BINARY_FILE_TYPE_UI = 'UI' +BINARY_FILE_TYPE_BIN = 'BIN' +BINARY_FILE_TYPE_FV = 'FV' + +PLATFORM_COMPONENT_TYPE_LIBRARY = 'LIBRARY' +PLATFORM_COMPONENT_TYPE_LIBRARY_CLASS = 'LIBRARY_CLASS' +PLATFORM_COMPONENT_TYPE_MODULE = 'MODULE' + +TAB_LIBRARIES = 'Libraries' + +TAB_SOURCES = 'Sources' +TAB_SOURCES_COMMON = TAB_SOURCES + TAB_SPLIT + TAB_ARCH_COMMON +TAB_SOURCES_IA32 = TAB_SOURCES + TAB_SPLIT + TAB_ARCH_IA32 +TAB_SOURCES_X64 = TAB_SOURCES + TAB_SPLIT + TAB_ARCH_X64 +TAB_SOURCES_IPF = TAB_SOURCES + TAB_SPLIT + TAB_ARCH_IPF +TAB_SOURCES_ARM = TAB_SOURCES + TAB_SPLIT + TAB_ARCH_ARM +TAB_SOURCES_EBC = TAB_SOURCES + TAB_SPLIT + TAB_ARCH_EBC + +TAB_BINARIES = 'Binaries' +TAB_BINARIES_COMMON = TAB_BINARIES + TAB_SPLIT + TAB_ARCH_COMMON +TAB_BINARIES_IA32 = TAB_BINARIES + TAB_SPLIT + TAB_ARCH_IA32 +TAB_BINARIES_X64 = TAB_BINARIES + TAB_SPLIT + TAB_ARCH_X64 +TAB_BINARIES_IPF = TAB_BINARIES + TAB_SPLIT + TAB_ARCH_IPF +TAB_BINARIES_ARM = TAB_BINARIES + TAB_SPLIT + TAB_ARCH_ARM +TAB_BINARIES_EBC = TAB_BINARIES + TAB_SPLIT + TAB_ARCH_EBC + +TAB_INCLUDES = 'Includes' +TAB_INCLUDES_COMMON = TAB_INCLUDES + TAB_SPLIT + TAB_ARCH_COMMON +TAB_INCLUDES_IA32 = TAB_INCLUDES + TAB_SPLIT + TAB_ARCH_IA32 +TAB_INCLUDES_X64 = TAB_INCLUDES + TAB_SPLIT + TAB_ARCH_X64 +TAB_INCLUDES_IPF = TAB_INCLUDES + TAB_SPLIT + TAB_ARCH_IPF +TAB_INCLUDES_ARM = TAB_INCLUDES + TAB_SPLIT + TAB_ARCH_ARM +TAB_INCLUDES_EBC = TAB_INCLUDES + TAB_SPLIT + TAB_ARCH_EBC + +TAB_GUIDS = 'Guids' +TAB_GUIDS_COMMON = TAB_GUIDS + TAB_SPLIT + TAB_ARCH_COMMON +TAB_GUIDS_IA32 = TAB_GUIDS + TAB_SPLIT + TAB_ARCH_IA32 +TAB_GUIDS_X64 = TAB_GUIDS + TAB_SPLIT + TAB_ARCH_X64 +TAB_GUIDS_IPF = TAB_GUIDS + TAB_SPLIT + TAB_ARCH_IPF +TAB_GUIDS_ARM = TAB_GUIDS + TAB_SPLIT + TAB_ARCH_ARM +TAB_GUIDS_EBC = TAB_GUIDS + TAB_SPLIT + TAB_ARCH_EBC + +TAB_PROTOCOLS = 'Protocols' +TAB_PROTOCOLS_COMMON = TAB_PROTOCOLS + TAB_SPLIT + TAB_ARCH_COMMON +TAB_PROTOCOLS_IA32 = TAB_PROTOCOLS + TAB_SPLIT + TAB_ARCH_IA32 +TAB_PROTOCOLS_X64 = TAB_PROTOCOLS + TAB_SPLIT + TAB_ARCH_X64 +TAB_PROTOCOLS_IPF = TAB_PROTOCOLS + TAB_SPLIT + TAB_ARCH_IPF +TAB_PROTOCOLS_ARM = TAB_PROTOCOLS + TAB_SPLIT + TAB_ARCH_ARM +TAB_PROTOCOLS_EBC = TAB_PROTOCOLS + TAB_SPLIT + TAB_ARCH_EBC + +TAB_PPIS = 'Ppis' +TAB_PPIS_COMMON = TAB_PPIS + TAB_SPLIT + TAB_ARCH_COMMON +TAB_PPIS_IA32 = TAB_PPIS + TAB_SPLIT + TAB_ARCH_IA32 +TAB_PPIS_X64 = TAB_PPIS + TAB_SPLIT + TAB_ARCH_X64 +TAB_PPIS_IPF = TAB_PPIS + TAB_SPLIT + TAB_ARCH_IPF +TAB_PPIS_ARM = TAB_PPIS + TAB_SPLIT + TAB_ARCH_ARM +TAB_PPIS_EBC = TAB_PPIS + TAB_SPLIT + TAB_ARCH_EBC + +TAB_LIBRARY_CLASSES = 'LibraryClasses' +TAB_LIBRARY_CLASSES_COMMON = TAB_LIBRARY_CLASSES + TAB_SPLIT + TAB_ARCH_COMMON +TAB_LIBRARY_CLASSES_IA32 = TAB_LIBRARY_CLASSES + TAB_SPLIT + TAB_ARCH_IA32 +TAB_LIBRARY_CLASSES_X64 = TAB_LIBRARY_CLASSES + TAB_SPLIT + TAB_ARCH_X64 +TAB_LIBRARY_CLASSES_IPF = TAB_LIBRARY_CLASSES + TAB_SPLIT + TAB_ARCH_IPF +TAB_LIBRARY_CLASSES_ARM = TAB_LIBRARY_CLASSES + TAB_SPLIT + TAB_ARCH_ARM +TAB_LIBRARY_CLASSES_EBC = TAB_LIBRARY_CLASSES + TAB_SPLIT + TAB_ARCH_EBC + +TAB_PACKAGES = 'Packages' +TAB_PACKAGES_COMMON = TAB_PACKAGES + TAB_SPLIT + TAB_ARCH_COMMON +TAB_PACKAGES_IA32 = TAB_PACKAGES + TAB_SPLIT + TAB_ARCH_IA32 +TAB_PACKAGES_X64 = TAB_PACKAGES + TAB_SPLIT + TAB_ARCH_X64 +TAB_PACKAGES_IPF = TAB_PACKAGES + TAB_SPLIT + TAB_ARCH_IPF +TAB_PACKAGES_ARM = TAB_PACKAGES + TAB_SPLIT + TAB_ARCH_ARM +TAB_PACKAGES_EBC = TAB_PACKAGES + TAB_SPLIT + TAB_ARCH_EBC + +TAB_PCDS = 'Pcds' +TAB_PCDS_FIXED_AT_BUILD = 'FixedAtBuild' +TAB_PCDS_PATCHABLE_IN_MODULE = 'PatchableInModule' +TAB_PCDS_FEATURE_FLAG = 'FeatureFlag' +TAB_PCDS_DYNAMIC_EX = 'DynamicEx' +TAB_PCDS_DYNAMIC_EX_DEFAULT = 'DynamicExDefault' +TAB_PCDS_DYNAMIC_EX_VPD = 'DynamicExVpd' +TAB_PCDS_DYNAMIC_EX_HII = 'DynamicExHii' +TAB_PCDS_DYNAMIC = 'Dynamic' +TAB_PCDS_DYNAMIC_DEFAULT = 'DynamicDefault' +TAB_PCDS_DYNAMIC_VPD = 'DynamicVpd' +TAB_PCDS_DYNAMIC_HII = 'DynamicHii' + +PCD_DYNAMIC_TYPE_LIST = [TAB_PCDS_DYNAMIC, TAB_PCDS_DYNAMIC_DEFAULT, TAB_PCDS_DYNAMIC_VPD, TAB_PCDS_DYNAMIC_HII] +PCD_DYNAMIC_EX_TYPE_LIST = [TAB_PCDS_DYNAMIC_EX, TAB_PCDS_DYNAMIC_EX_DEFAULT, TAB_PCDS_DYNAMIC_EX_VPD, TAB_PCDS_DYNAMIC_EX_HII] + +## Dynamic-ex PCD types +gDynamicExPcd = [TAB_PCDS_DYNAMIC_EX, TAB_PCDS_DYNAMIC_EX_DEFAULT, TAB_PCDS_DYNAMIC_EX_VPD, TAB_PCDS_DYNAMIC_EX_HII] + +TAB_PCDS_FIXED_AT_BUILD_NULL = TAB_PCDS + TAB_PCDS_FIXED_AT_BUILD +TAB_PCDS_FIXED_AT_BUILD_COMMON = TAB_PCDS + TAB_PCDS_FIXED_AT_BUILD + TAB_SPLIT + TAB_ARCH_COMMON +TAB_PCDS_FIXED_AT_BUILD_IA32 = TAB_PCDS + TAB_PCDS_FIXED_AT_BUILD + TAB_SPLIT + TAB_ARCH_IA32 +TAB_PCDS_FIXED_AT_BUILD_X64 = TAB_PCDS + TAB_PCDS_FIXED_AT_BUILD + TAB_SPLIT + TAB_ARCH_X64 +TAB_PCDS_FIXED_AT_BUILD_IPF = TAB_PCDS + TAB_PCDS_FIXED_AT_BUILD + TAB_SPLIT + TAB_ARCH_IPF +TAB_PCDS_FIXED_AT_BUILD_ARM = TAB_PCDS + TAB_PCDS_FIXED_AT_BUILD + TAB_SPLIT + TAB_ARCH_ARM +TAB_PCDS_FIXED_AT_BUILD_EBC = TAB_PCDS + TAB_PCDS_FIXED_AT_BUILD + TAB_SPLIT + TAB_ARCH_EBC + +TAB_PCDS_PATCHABLE_IN_MODULE_NULL = TAB_PCDS + TAB_PCDS_PATCHABLE_IN_MODULE +TAB_PCDS_PATCHABLE_IN_MODULE_COMMON = TAB_PCDS + TAB_PCDS_PATCHABLE_IN_MODULE + TAB_SPLIT + TAB_ARCH_COMMON +TAB_PCDS_PATCHABLE_IN_MODULE_IA32 = TAB_PCDS + TAB_PCDS_PATCHABLE_IN_MODULE + TAB_SPLIT + TAB_ARCH_IA32 +TAB_PCDS_PATCHABLE_IN_MODULE_X64 = TAB_PCDS + TAB_PCDS_PATCHABLE_IN_MODULE + TAB_SPLIT + TAB_ARCH_X64 +TAB_PCDS_PATCHABLE_IN_MODULE_IPF = TAB_PCDS + TAB_PCDS_PATCHABLE_IN_MODULE + TAB_SPLIT + TAB_ARCH_IPF +TAB_PCDS_PATCHABLE_IN_MODULE_ARM = TAB_PCDS + TAB_PCDS_PATCHABLE_IN_MODULE + TAB_SPLIT + TAB_ARCH_ARM +TAB_PCDS_PATCHABLE_IN_MODULE_EBC = TAB_PCDS + TAB_PCDS_PATCHABLE_IN_MODULE + TAB_SPLIT + TAB_ARCH_EBC + +TAB_PCDS_FEATURE_FLAG_NULL = TAB_PCDS + TAB_PCDS_FEATURE_FLAG +TAB_PCDS_FEATURE_FLAG_COMMON = TAB_PCDS + TAB_PCDS_FEATURE_FLAG + TAB_SPLIT + TAB_ARCH_COMMON +TAB_PCDS_FEATURE_FLAG_IA32 = TAB_PCDS + TAB_PCDS_FEATURE_FLAG + TAB_SPLIT + TAB_ARCH_IA32 +TAB_PCDS_FEATURE_FLAG_X64 = TAB_PCDS + TAB_PCDS_FEATURE_FLAG + TAB_SPLIT + TAB_ARCH_X64 +TAB_PCDS_FEATURE_FLAG_IPF = TAB_PCDS + TAB_PCDS_FEATURE_FLAG + TAB_SPLIT + TAB_ARCH_IPF +TAB_PCDS_FEATURE_FLAG_ARM = TAB_PCDS + TAB_PCDS_FEATURE_FLAG + TAB_SPLIT + TAB_ARCH_ARM +TAB_PCDS_FEATURE_FLAG_EBC = TAB_PCDS + TAB_PCDS_FEATURE_FLAG + TAB_SPLIT + TAB_ARCH_EBC + +TAB_PCDS_DYNAMIC_EX_NULL = TAB_PCDS + TAB_PCDS_DYNAMIC_EX +TAB_PCDS_DYNAMIC_EX_DEFAULT_NULL = TAB_PCDS + TAB_PCDS_DYNAMIC_EX_DEFAULT +TAB_PCDS_DYNAMIC_EX_HII_NULL = TAB_PCDS + TAB_PCDS_DYNAMIC_EX_HII +TAB_PCDS_DYNAMIC_EX_VPD_NULL = TAB_PCDS + TAB_PCDS_DYNAMIC_EX_VPD +TAB_PCDS_DYNAMIC_EX_COMMON = TAB_PCDS + TAB_PCDS_DYNAMIC_EX + TAB_SPLIT + TAB_ARCH_COMMON +TAB_PCDS_DYNAMIC_EX_IA32 = TAB_PCDS + TAB_PCDS_DYNAMIC_EX + TAB_SPLIT + TAB_ARCH_IA32 +TAB_PCDS_DYNAMIC_EX_X64 = TAB_PCDS + TAB_PCDS_DYNAMIC_EX + TAB_SPLIT + TAB_ARCH_X64 +TAB_PCDS_DYNAMIC_EX_IPF = TAB_PCDS + TAB_PCDS_DYNAMIC_EX + TAB_SPLIT + TAB_ARCH_IPF +TAB_PCDS_DYNAMIC_EX_ARM = TAB_PCDS + TAB_PCDS_DYNAMIC_EX + TAB_SPLIT + TAB_ARCH_ARM +TAB_PCDS_DYNAMIC_EX_EBC = TAB_PCDS + TAB_PCDS_DYNAMIC_EX + TAB_SPLIT + TAB_ARCH_EBC + +TAB_PCDS_DYNAMIC_NULL = TAB_PCDS + TAB_PCDS_DYNAMIC +TAB_PCDS_DYNAMIC_DEFAULT_NULL = TAB_PCDS + TAB_PCDS_DYNAMIC_DEFAULT +TAB_PCDS_DYNAMIC_HII_NULL = TAB_PCDS + TAB_PCDS_DYNAMIC_HII +TAB_PCDS_DYNAMIC_VPD_NULL = TAB_PCDS + TAB_PCDS_DYNAMIC_VPD +TAB_PCDS_DYNAMIC_COMMON = TAB_PCDS + TAB_PCDS_DYNAMIC + TAB_SPLIT + TAB_ARCH_COMMON +TAB_PCDS_DYNAMIC_IA32 = TAB_PCDS + TAB_PCDS_DYNAMIC + TAB_SPLIT + TAB_ARCH_IA32 +TAB_PCDS_DYNAMIC_X64 = TAB_PCDS + TAB_PCDS_DYNAMIC + TAB_SPLIT + TAB_ARCH_X64 +TAB_PCDS_DYNAMIC_IPF = TAB_PCDS + TAB_PCDS_DYNAMIC + TAB_SPLIT + TAB_ARCH_IPF +TAB_PCDS_DYNAMIC_ARM = TAB_PCDS + TAB_PCDS_DYNAMIC + TAB_SPLIT + TAB_ARCH_ARM +TAB_PCDS_DYNAMIC_EBC = TAB_PCDS + TAB_PCDS_DYNAMIC + TAB_SPLIT + TAB_ARCH_EBC + +TAB_PCD_DYNAMIC_TYPE_LIST = [TAB_PCDS_DYNAMIC_DEFAULT_NULL, TAB_PCDS_DYNAMIC_VPD_NULL, TAB_PCDS_DYNAMIC_HII_NULL] +TAB_PCD_DYNAMIC_EX_TYPE_LIST = [TAB_PCDS_DYNAMIC_EX_DEFAULT_NULL, TAB_PCDS_DYNAMIC_EX_VPD_NULL, TAB_PCDS_DYNAMIC_EX_HII_NULL] + +TAB_DEPEX = 'Depex' +TAB_DEPEX_COMMON = TAB_DEPEX + TAB_SPLIT + TAB_ARCH_COMMON +TAB_DEPEX_IA32 = TAB_DEPEX + TAB_SPLIT + TAB_ARCH_IA32 +TAB_DEPEX_X64 = TAB_DEPEX + TAB_SPLIT + TAB_ARCH_X64 +TAB_DEPEX_IPF = TAB_DEPEX + TAB_SPLIT + TAB_ARCH_IPF +TAB_DEPEX_ARM = TAB_DEPEX + TAB_SPLIT + TAB_ARCH_ARM +TAB_DEPEX_EBC = TAB_DEPEX + TAB_SPLIT + TAB_ARCH_EBC + +TAB_SKUIDS = 'SkuIds' + +TAB_LIBRARIES = 'Libraries' +TAB_LIBRARIES_COMMON = TAB_LIBRARIES + TAB_SPLIT + TAB_ARCH_COMMON +TAB_LIBRARIES_IA32 = TAB_LIBRARIES + TAB_SPLIT + TAB_ARCH_IA32 +TAB_LIBRARIES_X64 = TAB_LIBRARIES + TAB_SPLIT + TAB_ARCH_X64 +TAB_LIBRARIES_IPF = TAB_LIBRARIES + TAB_SPLIT + TAB_ARCH_IPF +TAB_LIBRARIES_ARM = TAB_LIBRARIES + TAB_SPLIT + TAB_ARCH_ARM +TAB_LIBRARIES_EBC = TAB_LIBRARIES + TAB_SPLIT + TAB_ARCH_EBC + +TAB_COMPONENTS = 'Components' +TAB_COMPONENTS_COMMON = TAB_COMPONENTS + TAB_SPLIT + TAB_ARCH_COMMON +TAB_COMPONENTS_IA32 = TAB_COMPONENTS + TAB_SPLIT + TAB_ARCH_IA32 +TAB_COMPONENTS_X64 = TAB_COMPONENTS + TAB_SPLIT + TAB_ARCH_X64 +TAB_COMPONENTS_IPF = TAB_COMPONENTS + TAB_SPLIT + TAB_ARCH_IPF +TAB_COMPONENTS_ARM = TAB_COMPONENTS + TAB_SPLIT + TAB_ARCH_ARM +TAB_COMPONENTS_EBC = TAB_COMPONENTS + TAB_SPLIT + TAB_ARCH_EBC + +TAB_COMPONENTS_SOURCE_OVERRIDE_PATH = 'SOURCE_OVERRIDE_PATH' + +TAB_BUILD_OPTIONS = 'BuildOptions' + +TAB_DEFINE = 'DEFINE' +TAB_NMAKE = 'Nmake' +TAB_USER_EXTENSIONS = 'UserExtensions' +TAB_INCLUDE = '!include' + +# +# Common Define +# +TAB_COMMON_DEFINES = 'Defines' + +# +# Inf Definitions +# +TAB_INF_DEFINES = TAB_COMMON_DEFINES +TAB_INF_DEFINES_INF_VERSION = 'INF_VERSION' +TAB_INF_DEFINES_BASE_NAME = 'BASE_NAME' +TAB_INF_DEFINES_FILE_GUID = 'FILE_GUID' +TAB_INF_DEFINES_MODULE_TYPE = 'MODULE_TYPE' +TAB_INF_DEFINES_EFI_SPECIFICATION_VERSION = 'EFI_SPECIFICATION_VERSION' +TAB_INF_DEFINES_UEFI_SPECIFICATION_VERSION = 'UEFI_SPECIFICATION_VERSION' +TAB_INF_DEFINES_PI_SPECIFICATION_VERSION = 'PI_SPECIFICATION_VERSION' +TAB_INF_DEFINES_EDK_RELEASE_VERSION = 'EDK_RELEASE_VERSION' +TAB_INF_DEFINES_BINARY_MODULE = 'BINARY_MODULE' +TAB_INF_DEFINES_LIBRARY_CLASS = 'LIBRARY_CLASS' +TAB_INF_DEFINES_COMPONENT_TYPE = 'COMPONENT_TYPE' +TAB_INF_DEFINES_MAKEFILE_NAME = 'MAKEFILE_NAME' +TAB_INF_DEFINES_BUILD_NUMBER = 'BUILD_NUMBER' +TAB_INF_DEFINES_BUILD_TYPE = 'BUILD_TYPE' +TAB_INF_DEFINES_FFS_EXT = 'FFS_EXT' +TAB_INF_DEFINES_FV_EXT = 'FV_EXT' +TAB_INF_DEFINES_SOURCE_FV = 'SOURCE_FV' +TAB_INF_DEFINES_VERSION_NUMBER = 'VERSION_NUMBER' +TAB_INF_DEFINES_VERSION = 'VERSION' # for R8 inf, the same as VERSION_NUMBER +TAB_INF_DEFINES_VERSION_STRING = 'VERSION_STRING' +TAB_INF_DEFINES_PCD_IS_DRIVER = 'PCD_IS_DRIVER' +TAB_INF_DEFINES_TIANO_R8_FLASHMAP_H = 'TIANO_R8_FLASHMAP_H' +TAB_INF_DEFINES_ENTRY_POINT = 'ENTRY_POINT' +TAB_INF_DEFINES_UNLOAD_IMAGE = 'UNLOAD_IMAGE' +TAB_INF_DEFINES_CONSTRUCTOR = 'CONSTRUCTOR' +TAB_INF_DEFINES_DESTRUCTOR = 'DESTRUCTOR' +TAB_INF_DEFINES_DEFINE = 'DEFINE' +TAB_INF_DEFINES_SPEC = 'SPEC' +TAB_INF_DEFINES_CUSTOM_MAKEFILE = 'CUSTOM_MAKEFILE' +TAB_INF_DEFINES_MACRO = '__MACROS__' +TAB_INF_DEFINES_SHADOW = 'SHADOW' +TAB_INF_FIXED_PCD = 'FixedPcd' +TAB_INF_FEATURE_PCD = 'FeaturePcd' +TAB_INF_PATCH_PCD = 'PatchPcd' +TAB_INF_PCD = 'Pcd' +TAB_INF_PCD_EX = 'PcdEx' + +# +# Dec Definitions +# +TAB_DEC_DEFINES = TAB_COMMON_DEFINES +TAB_DEC_DEFINES_DEC_SPECIFICATION = 'DEC_SPECIFICATION' +TAB_DEC_DEFINES_PACKAGE_NAME = 'PACKAGE_NAME' +TAB_DEC_DEFINES_PACKAGE_GUID = 'PACKAGE_GUID' +TAB_DEC_DEFINES_PACKAGE_VERSION = 'PACKAGE_VERSION' + +# +# Dsc Definitions +# +TAB_DSC_DEFINES = TAB_COMMON_DEFINES +TAB_DSC_DEFINES_PLATFORM_NAME = 'PLATFORM_NAME' +TAB_DSC_DEFINES_PLATFORM_GUID = 'PLATFORM_GUID' +TAB_DSC_DEFINES_PLATFORM_VERSION = 'PLATFORM_VERSION' +TAB_DSC_DEFINES_DSC_SPECIFICATION = 'DSC_SPECIFICATION' +TAB_DSC_DEFINES_OUTPUT_DIRECTORY = 'OUTPUT_DIRECTORY' +TAB_DSC_DEFINES_SUPPORTED_ARCHITECTURES = 'SUPPORTED_ARCHITECTURES' +TAB_DSC_DEFINES_BUILD_TARGETS = 'BUILD_TARGETS' +TAB_DSC_DEFINES_SKUID_IDENTIFIER = 'SKUID_IDENTIFIER' +TAB_DSC_DEFINES_FLASH_DEFINITION = 'FLASH_DEFINITION' +TAB_DSC_DEFINES_BUILD_NUMBER = 'BUILD_NUMBER' +TAB_DSC_DEFINES_MAKEFILE_NAME = 'MAKEFILE_NAME' +TAB_DSC_DEFINES_BS_BASE_ADDRESS = 'BsBaseAddress' +TAB_DSC_DEFINES_RT_BASE_ADDRESS = 'RtBaseAddress' +TAB_DSC_DEFINES_DEFINE = 'DEFINE' + +# +# TargetTxt Definitions +# +TAB_TAT_DEFINES_ACTIVE_PLATFORM = 'ACTIVE_PLATFORM' +TAB_TAT_DEFINES_ACTIVE_MODULE = 'ACTIVE_MODULE' +TAB_TAT_DEFINES_TOOL_CHAIN_CONF = 'TOOL_CHAIN_CONF' +TAB_TAT_DEFINES_MULTIPLE_THREAD = 'MULTIPLE_THREAD' +TAB_TAT_DEFINES_MAX_CONCURRENT_THREAD_NUMBER = 'MAX_CONCURRENT_THREAD_NUMBER' +TAB_TAT_DEFINES_TARGET = 'TARGET' +TAB_TAT_DEFINES_TOOL_CHAIN_TAG = 'TOOL_CHAIN_TAG' +TAB_TAT_DEFINES_TARGET_ARCH = 'TARGET_ARCH' +TAB_TAT_DEFINES_BUILD_RULE_CONF = "BUILD_RULE_CONF" + +# +# ToolDef Definitions +# +TAB_TOD_DEFINES_TARGET = 'TARGET' +TAB_TOD_DEFINES_TOOL_CHAIN_TAG = 'TOOL_CHAIN_TAG' +TAB_TOD_DEFINES_TARGET_ARCH = 'TARGET_ARCH' +TAB_TOD_DEFINES_COMMAND_TYPE = 'COMMAND_TYPE' +TAB_TOD_DEFINES_FAMILY = 'FAMILY' +TAB_TOD_DEFINES_BUILDRULEFAMILY = 'BUILDRULEFAMILY' + +# +# Conditional Statements +# +TAB_IF = '!if' +TAB_END_IF = '!endif' +TAB_ELSE_IF = '!elseif' +TAB_ELSE = '!else' +TAB_IF_DEF = '!ifdef' +TAB_IF_N_DEF = '!ifndef' +TAB_IF_EXIST = '!if exist' + +# +# Unknown section +# +TAB_UNKNOWN = 'UNKNOWN' + +# +# Build database path +# +DATABASE_PATH = ":memory:" #"BuildDatabase.db" + +# used by ECC +MODIFIER_LIST = ['IN', 'OUT', 'OPTIONAL', 'UNALIGNED', 'EFI_RUNTIMESERVICE', 'EFI_BOOTSERVICE', 'EFIAPI'] + +# Dependency Expression +DEPEX_SUPPORTED_OPCODE = ["BEFORE", "AFTER", "PUSH", "AND", "OR", "NOT", "END", "SOR", "TRUE", "FALSE", '(', ')'] + +TAB_STATIC_LIBRARY = "STATIC-LIBRARY-FILE" +TAB_DYNAMIC_LIBRARY = "DYNAMIC-LIBRARY-FILE" +TAB_FRAMEWORK_IMAGE = "EFI-IMAGE-FILE" +TAB_C_CODE_FILE = "C-CODE-FILE" +TAB_C_HEADER_FILE = "C-HEADER-FILE" +TAB_UNICODE_FILE = "UNICODE-TEXT-FILE" +TAB_DEPENDENCY_EXPRESSION_FILE = "DEPENDENCY-EXPRESSION-FILE" +TAB_UNKNOWN_FILE = "UNKNOWN-TYPE-FILE" +TAB_DEFAULT_BINARY_FILE = "_BINARY_FILE_" + diff --git a/BaseTools/Source/Python/Common/Database.py b/BaseTools/Source/Python/Common/Database.py new file mode 100644 index 0000000000..e645337a39 --- /dev/null +++ b/BaseTools/Source/Python/Common/Database.py @@ -0,0 +1,120 @@ +## @file +# This file is used to create a database used by ECC tool +# +# Copyright (c) 2007 ~ 2008, 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. +# + +## +# Import Modules +# +import sqlite3 +import os + +import EdkLogger as EdkLogger +from CommonDataClass.DataClass import * +from String import * +from DataType import * + +from Table.TableDataModel import TableDataModel +from Table.TableFile import TableFile +from Table.TableInf import TableInf +from Table.TableDec import TableDec +from Table.TableDsc import TableDsc + +## Database +# +# This class defined the build databse +# During the phase of initialization, the database will create all tables and +# insert all records of table DataModel +# +# @param object: Inherited from object class +# @param DbPath: A string for the path of the ECC database +# +# @var Conn: Connection of the ECC database +# @var Cur: Cursor of the connection +# @var TblDataModel: Local instance for TableDataModel +# +class Database(object): + def __init__(self, DbPath): + if os.path.exists(DbPath): + os.remove(DbPath) + self.Conn = sqlite3.connect(DbPath, isolation_level = 'DEFERRED') + self.Conn.execute("PRAGMA page_size=8192") + self.Conn.execute("PRAGMA synchronous=OFF") + self.Cur = self.Conn.cursor() + self.TblDataModel = TableDataModel(self.Cur) + self.TblFile = TableFile(self.Cur) + self.TblInf = TableInf(self.Cur) + self.TblDec = TableDec(self.Cur) + self.TblDsc = TableDsc(self.Cur) + + ## Initialize build database + # + # 1. Delete all old existing tables + # 2. Create new tables + # 3. Initialize table DataModel + # + def InitDatabase(self): + EdkLogger.verbose("\nInitialize ECC database started ...") + # + # Drop all old existing tables + # +# self.TblDataModel.Drop() +# self.TblDsc.Drop() +# self.TblFile.Drop() + + # + # Create new tables + # + self.TblDataModel.Create() + self.TblFile.Create() + self.TblInf.Create() + self.TblDec.Create() + self.TblDsc.Create() + + # + # Initialize table DataModel + # + self.TblDataModel.InitTable() + EdkLogger.verbose("Initialize ECC database ... DONE!") + + ## Query a table + # + # @param Table: The instance of the table to be queried + # + def QueryTable(self, Table): + Table.Query() + + ## Close entire database + # + # Commit all first + # Close the connection and cursor + # + def Close(self): + self.Conn.commit() + self.Cur.close() + self.Conn.close() + +## +# +# This acts like the main() function for the script, unless it is 'import'ed into another +# script. +# +if __name__ == '__main__': + EdkLogger.Initialize() + EdkLogger.SetLevel(EdkLogger.DEBUG_0) + + Db = Database(DATABASE_PATH) + Db.InitDatabase() + Db.QueryTable(Db.TblDataModel) + Db.QueryTable(Db.TblFile) + Db.QueryTable(Db.TblDsc) + Db.Close() + \ No newline at end of file diff --git a/BaseTools/Source/Python/Common/DecClassObject.py b/BaseTools/Source/Python/Common/DecClassObject.py new file mode 100644 index 0000000000..b95ff621cc --- /dev/null +++ b/BaseTools/Source/Python/Common/DecClassObject.py @@ -0,0 +1,563 @@ +## @file +# This file is used to define each component of DEC file +# +# Copyright (c) 2007, 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. +# + +## +# Import Modules +# +import os +from String import * +from DataType import * +from Identification import * +from Dictionary import * +from CommonDataClass.PackageClass import * +from CommonDataClass.CommonClass import PcdClass +from BuildToolError import * +from Table.TableDec import TableDec +import Database +from Parsing import * +import GlobalData + +# +# Global variable +# +Section = {TAB_UNKNOWN.upper() : MODEL_UNKNOWN, + TAB_DEC_DEFINES.upper() : MODEL_META_DATA_HEADER, + TAB_INCLUDES.upper() : MODEL_EFI_INCLUDE, + TAB_LIBRARY_CLASSES.upper() : MODEL_EFI_LIBRARY_CLASS, + TAB_COMPONENTS.upper() : MODEL_META_DATA_COMPONENT, + TAB_GUIDS.upper() : MODEL_EFI_GUID, + TAB_PROTOCOLS.upper() : MODEL_EFI_PROTOCOL, + TAB_PPIS.upper() : MODEL_EFI_PPI, + TAB_PCDS_FIXED_AT_BUILD_NULL.upper() : MODEL_PCD_FIXED_AT_BUILD, + TAB_PCDS_PATCHABLE_IN_MODULE_NULL.upper() : MODEL_PCD_PATCHABLE_IN_MODULE, + TAB_PCDS_FEATURE_FLAG_NULL.upper() : MODEL_PCD_FEATURE_FLAG, + TAB_PCDS_DYNAMIC_EX_NULL.upper() : MODEL_PCD_DYNAMIC_EX, + TAB_PCDS_DYNAMIC_NULL.upper() : MODEL_PCD_DYNAMIC, + TAB_USER_EXTENSIONS.upper() : MODEL_META_DATA_USER_EXTENSION + } + + +## DecObject +# +# This class defined basic Dec object which is used by inheriting +# +# @param object: Inherited from object class +# +class DecObject(object): + def __init__(self): + object.__init__() + +## Dec +# +# This class defined the structure used in Dec object +# +# @param DecObject: Inherited from DecObject class +# @param Filename: Input value for Filename of Dec file, default is None +# @param IsMergeAllArches: Input value for IsMergeAllArches +# True is to merge all arches +# Fales is not to merge all arches +# default is False +# @param IsToPackage: Input value for IsToPackage +# True is to transfer to PackageObject automatically +# False is not to transfer to PackageObject automatically +# default is False +# @param WorkspaceDir: Input value for current workspace directory, default is None +# +# @var Identification: To store value for Identification, it is a structure as Identification +# @var Defines: To store value for Defines, it is a structure as DecDefines +# @var UserExtensions: To store value for UserExtensions +# @var Package: To store value for Package, it is a structure as PackageClass +# @var WorkspaceDir: To store value for WorkspaceDir +# @var Contents: To store value for Contents, it is a structure as DecContents +# @var KeyList: To store value for KeyList, a list for all Keys used in Dec +# +class Dec(DecObject): + def __init__(self, Filename = None, IsToDatabase = False, IsToPackage = False, WorkspaceDir = None, Database = None, SupArchList = DataType.ARCH_LIST): + self.Identification = Identification() + self.Package = PackageClass() + self.UserExtensions = '' + self.WorkspaceDir = WorkspaceDir + self.SupArchList = SupArchList + self.IsToDatabase = IsToDatabase + + self.Cur = Database.Cur + self.TblFile = Database.TblFile + self.TblDec = Database.TblDec + self.FileID = -1 + + self.KeyList = [ + TAB_INCLUDES, TAB_GUIDS, TAB_PROTOCOLS, TAB_PPIS, TAB_LIBRARY_CLASSES, \ + TAB_PCDS_FIXED_AT_BUILD_NULL, TAB_PCDS_PATCHABLE_IN_MODULE_NULL, TAB_PCDS_FEATURE_FLAG_NULL, \ + TAB_PCDS_DYNAMIC_NULL, TAB_PCDS_DYNAMIC_EX_NULL, TAB_DEC_DEFINES + ] + # + # Upper all KEYs to ignore case sensitive when parsing + # + self.KeyList = map(lambda c: c.upper(), self.KeyList) + + # + # Init RecordSet + # + self.RecordSet = {} + for Key in self.KeyList: + self.RecordSet[Section[Key]] = [] + + # + # Load Dec file if filename is not None + # + if Filename != None: + self.LoadDecFile(Filename) + + # + # Transfer to Package Object if IsToPackage is True + # + if IsToPackage: + self.DecToPackage() + + ## Load Dec file + # + # Load the file if it exists + # + # @param Filename: Input value for filename of Dec file + # + def LoadDecFile(self, Filename): + # + # Insert a record for file + # + Filename = NormPath(Filename) + self.Identification.FileFullPath = Filename + (self.Identification.FileRelativePath, self.Identification.FileName) = os.path.split(Filename) + self.FileID = self.TblFile.InsertFile(Filename, MODEL_FILE_DEC) + + # + # Init DecTable + # + #self.TblDec.Table = "Dec%s" % self.FileID + #self.TblDec.Create() + + # + # Init common datas + # + IfDefList, SectionItemList, CurrentSection, ArchList, ThirdList, IncludeFiles = \ + [], [], TAB_UNKNOWN, [], [], [] + LineNo = 0 + + # + # Parse file content + # + IsFindBlockComment = False + ReservedLine = '' + for Line in open(Filename, 'r'): + LineNo = LineNo + 1 + # + # Remove comment block + # + if Line.find(TAB_COMMENT_R8_START) > -1: + ReservedLine = GetSplitValueList(Line, TAB_COMMENT_R8_START, 1)[0] + IsFindBlockComment = True + if Line.find(TAB_COMMENT_R8_END) > -1: + Line = ReservedLine + GetSplitValueList(Line, TAB_COMMENT_R8_END, 1)[1] + ReservedLine = '' + IsFindBlockComment = False + if IsFindBlockComment: + continue + + # + # Remove comments at tail and remove spaces again + # + Line = CleanString(Line) + if Line == '': + continue + + # + # Find a new section tab + # First insert previous section items + # And then parse the content of the new section + # + if Line.startswith(TAB_SECTION_START) and Line.endswith(TAB_SECTION_END): + # + # Insert items data of previous section + # + Model = Section[CurrentSection.upper()] + InsertSectionItemsIntoDatabase(self.TblDec, self.FileID, Filename, Model, CurrentSection, SectionItemList, ArchList, ThirdList, IfDefList, self.RecordSet) + + # + # Parse the new section + # + SectionItemList = [] + ArchList = [] + ThirdList = [] + + CurrentSection = '' + LineList = GetSplitValueList(Line[len(TAB_SECTION_START):len(Line) - len(TAB_SECTION_END)], TAB_COMMA_SPLIT) + for Item in LineList: + ItemList = GetSplitValueList(Item, TAB_SPLIT) + if CurrentSection == '': + CurrentSection = ItemList[0] + else: + if CurrentSection != ItemList[0]: + EdkLogger.error("Parser", PARSER_ERROR, "Different section names '%s' and '%s' are found in one section definition, this is not allowed." % (CurrentSection, ItemList[0]), File=Filename, Line=LineNo, RaiseError = EdkLogger.IsRaiseError) + if CurrentSection.upper() not in self.KeyList: + RaiseParserError(Line, CurrentSection, Filename, '', LineNo) + ItemList.append('') + ItemList.append('') + if len(ItemList) > 5: + RaiseParserError(Line, CurrentSection, Filename, '', LineNo) + else: + if ItemList[1] != '' and ItemList[1].upper() not in ARCH_LIST_FULL: + EdkLogger.error("Parser", PARSER_ERROR, "Invalid Arch definition '%s' found" % ItemList[1], File=Filename, Line=LineNo, RaiseError = EdkLogger.IsRaiseError) + ArchList.append(ItemList[1].upper()) + ThirdList.append(ItemList[2]) + + continue + + # + # Not in any defined section + # + if CurrentSection == TAB_UNKNOWN: + ErrorMsg = "%s is not in any defined section" % Line + EdkLogger.error("Parser", PARSER_ERROR, ErrorMsg, File=Filename, Line=LineNo, RaiseError = EdkLogger.IsRaiseError) + + # + # Add a section item + # + SectionItemList.append([Line, LineNo]) + # End of parse + #End of For + + # + # Insert items data of last section + # + Model = Section[CurrentSection.upper()] + InsertSectionItemsIntoDatabase(self.TblDec, self.FileID, Filename, Model, CurrentSection, SectionItemList, ArchList, ThirdList, IfDefList, self.RecordSet) + + # + # Replace all DEFINE macros with its actual values + # + ParseDefineMacro2(self.TblDec, self.RecordSet, GlobalData.gGlobalDefines) + + ## Transfer to Package Object + # + # Transfer all contents of a Dec file to a standard Package Object + # + def DecToPackage(self): + # + # Init global information for the file + # + ContainerFile = self.Identification.FileFullPath + + # + # Generate Package Header + # + self.GenPackageHeader(ContainerFile) + + # + # Generate Includes + # + self.GenIncludes(ContainerFile) + + # + # Generate Guids + # + self.GenGuidProtocolPpis(DataType.TAB_GUIDS, ContainerFile) + + # + # Generate Protocols + # + self.GenGuidProtocolPpis(DataType.TAB_PROTOCOLS, ContainerFile) + + # + # Generate Ppis + # + self.GenGuidProtocolPpis(DataType.TAB_PPIS, ContainerFile) + + # + # Generate LibraryClasses + # + self.GenLibraryClasses(ContainerFile) + + # + # Generate Pcds + # + self.GenPcds(ContainerFile) + + ## Get Package Header + # + # Gen Package Header of Dec as = + # + # @param ContainerFile: The Dec file full path + # + def GenPackageHeader(self, ContainerFile): + EdkLogger.debug(2, "Generate PackageHeader ...") + # + # Update all defines item in database + # + RecordSet = self.RecordSet[MODEL_META_DATA_HEADER] + for Record in RecordSet: + ValueList = GetSplitValueList(Record[0], TAB_EQUAL_SPLIT) + if len(ValueList) != 2: + RaiseParserError(Record[0], 'Defines', ContainerFile, ' = ', Record[2]) + ID, Value1, Value2, Arch, LineNo = Record[3], ValueList[0], ValueList[1], Record[1], Record[2] + SqlCommand = """update %s set Value1 = '%s', Value2 = '%s' + where ID = %s""" % (self.TblDec.Table, ConvertToSqlString2(Value1), ConvertToSqlString2(Value2), ID) + self.TblDec.Exec(SqlCommand) + + # + # Get detailed information + # + for Arch in self.SupArchList: + PackageHeader = PackageHeaderClass() + + PackageHeader.Name = QueryDefinesItem(self.TblDec, TAB_DEC_DEFINES_PACKAGE_NAME, Arch, self.FileID)[0] + PackageHeader.Guid = QueryDefinesItem(self.TblDec, TAB_DEC_DEFINES_PACKAGE_GUID, Arch, self.FileID)[0] + PackageHeader.Version = QueryDefinesItem(self.TblDec, TAB_DEC_DEFINES_PACKAGE_VERSION, Arch, self.FileID)[0] + PackageHeader.FileName = self.Identification.FileName + PackageHeader.FullPath = self.Identification.FileFullPath + PackageHeader.DecSpecification = QueryDefinesItem(self.TblDec, TAB_DEC_DEFINES_DEC_SPECIFICATION, Arch, self.FileID)[0] + + self.Package.Header[Arch] = PackageHeader + + ## GenIncludes + # + # Gen Includes of Dec + # + # + # @param ContainerFile: The Dec file full path + # + def GenIncludes(self, ContainerFile): + EdkLogger.debug(2, "Generate %s ..." % TAB_INCLUDES) + Includes = {} + # + # Get all Includes + # + RecordSet = self.RecordSet[MODEL_EFI_INCLUDE] + + # + # Go through each arch + # + for Arch in self.SupArchList: + for Record in RecordSet: + if Record[1] == Arch or Record[1] == TAB_ARCH_COMMON: + MergeArches(Includes, Record[0], Arch) + + for Key in Includes.keys(): + Include = IncludeClass() + Include.FilePath = NormPath(Key) + Include.SupArchList = Includes[Key] + self.Package.Includes.append(Include) + + ## GenPpis + # + # Gen Ppis of Dec + # = + # + # @param ContainerFile: The Dec file full path + # + def GenGuidProtocolPpis(self, Type, ContainerFile): + EdkLogger.debug(2, "Generate %s ..." % Type) + Lists = {} + # + # Get all Items + # + RecordSet = self.RecordSet[Section[Type.upper()]] + + # + # Go through each arch + # + for Arch in self.SupArchList: + for Record in RecordSet: + if Record[1] == Arch or Record[1] == TAB_ARCH_COMMON: + (Name, Value) = GetGuidsProtocolsPpisOfDec(Record[0], Type, ContainerFile, Record[2]) + MergeArches(Lists, (Name, Value), Arch) + if self.IsToDatabase: + SqlCommand = """update %s set Value1 = '%s', Value2 = '%s' + where ID = %s""" % (self.TblDec.Table, ConvertToSqlString2(Name), ConvertToSqlString2(Value), Record[3]) + self.TblDec.Exec(SqlCommand) + + ListMember = None + if Type == TAB_GUIDS: + ListMember = self.Package.GuidDeclarations + elif Type == TAB_PROTOCOLS: + ListMember = self.Package.ProtocolDeclarations + elif Type == TAB_PPIS: + ListMember = self.Package.PpiDeclarations + + for Key in Lists.keys(): + ListClass = GuidProtocolPpiCommonClass() + ListClass.CName = Key[0] + ListClass.Guid = Key[1] + ListClass.SupArchList = Lists[Key] + ListMember.append(ListClass) + + + ## GenLibraryClasses + # + # Gen LibraryClasses of Dec + # = + # + # @param ContainerFile: The Dec file full path + # + def GenLibraryClasses(self, ContainerFile): + EdkLogger.debug(2, "Generate %s ..." % TAB_LIBRARY_CLASSES) + LibraryClasses = {} + # + # Get all Guids + # + RecordSet = self.RecordSet[MODEL_EFI_LIBRARY_CLASS] + + # + # Go through each arch + # + for Arch in self.SupArchList: + for Record in RecordSet: + if Record[1] == Arch or Record[1] == TAB_ARCH_COMMON: + List = GetSplitValueList(Record[0], DataType.TAB_VALUE_SPLIT) + if len(List) != 2: + RaiseParserError(Record[0], 'LibraryClasses', ContainerFile, '|', Record[2]) + else: + CheckFileExist(self.Identification.FileRelativePath, List[1], ContainerFile, 'LibraryClasses', Record[0]) + MergeArches(LibraryClasses, (List[0], List[1]), Arch) + if self.IsToDatabase: + SqlCommand = """update %s set Value1 = '%s', Value2 = '%s', Value3 = '%s' + where ID = %s""" % (self.TblDec.Table, ConvertToSqlString2(List[0]), ConvertToSqlString2(List[1]), SUP_MODULE_LIST_STRING, Record[3]) + self.TblDec.Exec(SqlCommand) + + + for Key in LibraryClasses.keys(): + LibraryClass = LibraryClassClass() + LibraryClass.LibraryClass = Key[0] + LibraryClass.RecommendedInstance = NormPath(Key[1]) + LibraryClass.SupModuleList = SUP_MODULE_LIST + LibraryClass.SupArchList = LibraryClasses[Key] + self.Package.LibraryClassDeclarations.append(LibraryClass) + + ## GenPcds + # + # Gen Pcds of Dec + # .||| + # + # @param ContainerFile: The Dec file full path + # + def GenPcds(self, ContainerFile): + EdkLogger.debug(2, "Generate %s ..." % TAB_PCDS) + Pcds = {} + PcdToken = {} + # + # Get all Guids + # + RecordSet1 = self.RecordSet[MODEL_PCD_FIXED_AT_BUILD] + RecordSet2 = self.RecordSet[MODEL_PCD_PATCHABLE_IN_MODULE] + RecordSet3 = self.RecordSet[MODEL_PCD_FEATURE_FLAG] + RecordSet4 = self.RecordSet[MODEL_PCD_DYNAMIC_EX] + RecordSet5 = self.RecordSet[MODEL_PCD_DYNAMIC] + + # + # Go through each arch + # + for Arch in self.SupArchList: + for Record in RecordSet1: + if Record[1] == Arch or Record[1] == TAB_ARCH_COMMON: + (TokenGuidCName, TokenName, Value, DatumType, Token, Type) = GetPcdOfDec(Record[0], TAB_PCDS_FIXED_AT_BUILD, ContainerFile, Record[2]) + MergeArches(Pcds, (TokenGuidCName, TokenName, Value, DatumType, Token, Type), Arch) + PcdToken[Record[3]] = (TokenGuidCName, TokenName) + for Record in RecordSet2: + if Record[1] == Arch or Record[1] == TAB_ARCH_COMMON: + (TokenGuidCName, TokenName, Value, DatumType, Token, Type) = GetPcdOfDec(Record[0], TAB_PCDS_PATCHABLE_IN_MODULE, ContainerFile, Record[2]) + MergeArches(Pcds, (TokenGuidCName, TokenName, Value, DatumType, Token, Type), Arch) + PcdToken[Record[3]] = (TokenGuidCName, TokenName) + for Record in RecordSet3: + if Record[1] == Arch or Record[1] == TAB_ARCH_COMMON: + (TokenGuidCName, TokenName, Value, DatumType, Token, Type) = GetPcdOfDec(Record[0], TAB_PCDS_FEATURE_FLAG, ContainerFile, Record[2]) + MergeArches(Pcds, (TokenGuidCName, TokenName, Value, DatumType, Token, Type), Arch) + PcdToken[Record[3]] = (TokenGuidCName, TokenName) + for Record in RecordSet4: + if Record[1] == Arch or Record[1] == TAB_ARCH_COMMON: + (TokenGuidCName, TokenName, Value, DatumType, Token, Type) = GetPcdOfDec(Record[0], TAB_PCDS_DYNAMIC_EX, ContainerFile, Record[2]) + MergeArches(Pcds, (TokenGuidCName, TokenName, Value, DatumType, Token, Type), Arch) + PcdToken[Record[3]] = (TokenGuidCName, TokenName) + for Record in RecordSet5: + if Record[1] == Arch or Record[1] == TAB_ARCH_COMMON: + (TokenGuidCName, TokenName, Value, DatumType, Token, Type) = GetPcdOfDec(Record[0], TAB_PCDS_DYNAMIC, ContainerFile, Record[2]) + MergeArches(Pcds, (TokenGuidCName, TokenName, Value, DatumType, Token, Type), Arch) + PcdToken[Record[3]] = (TokenGuidCName, TokenName) + # + # Update to database + # + if self.IsToDatabase: + for Key in PcdToken.keys(): + SqlCommand = """update %s set Value2 = '%s' where ID = %s""" % (self.TblDec.Table, ".".join((PcdToken[Key][0], PcdToken[Key][1])), Key) + self.TblDec.Exec(SqlCommand) + + for Key in Pcds.keys(): + Pcd = PcdClass() + Pcd.CName = Key[1] + Pcd.Token = Key[4] + Pcd.TokenSpaceGuidCName = Key[0] + Pcd.DatumType = Key[3] + Pcd.DefaultValue = Key[2] + Pcd.ItemType = Key[5] + Pcd.SupArchList = Pcds[Key] + self.Package.PcdDeclarations.append(Pcd) + + ## Show detailed information of Package + # + # Print all members and their values of Package class + # + def ShowPackage(self): + M = self.Package + for Arch in M.Header.keys(): + print '\nArch =', Arch + print 'Filename =', M.Header[Arch].FileName + print 'FullPath =', M.Header[Arch].FullPath + print 'BaseName =', M.Header[Arch].Name + print 'Guid =', M.Header[Arch].Guid + print 'Version =', M.Header[Arch].Version + print 'DecSpecification =', M.Header[Arch].DecSpecification + print '\nIncludes =', M.Includes + for Item in M.Includes: + print Item.FilePath, Item.SupArchList + print '\nGuids =', M.GuidDeclarations + for Item in M.GuidDeclarations: + print Item.CName, Item.Guid, Item.SupArchList + print '\nProtocols =', M.ProtocolDeclarations + for Item in M.ProtocolDeclarations: + print Item.CName, Item.Guid, Item.SupArchList + print '\nPpis =', M.PpiDeclarations + for Item in M.PpiDeclarations: + print Item.CName, Item.Guid, Item.SupArchList + print '\nLibraryClasses =', M.LibraryClassDeclarations + for Item in M.LibraryClassDeclarations: + print Item.LibraryClass, Item.RecommendedInstance, Item.SupModuleList, Item.SupArchList + print '\nPcds =', M.PcdDeclarations + for Item in M.PcdDeclarations: + print 'CName=', Item.CName, 'TokenSpaceGuidCName=', Item.TokenSpaceGuidCName, 'DefaultValue=', Item.DefaultValue, 'ItemType=', Item.ItemType, 'Token=', Item.Token, 'DatumType=', Item.DatumType, Item.SupArchList + +## +# +# This acts like the main() function for the script, unless it is 'import'ed into another +# script. +# +if __name__ == '__main__': + EdkLogger.Initialize() + EdkLogger.SetLevel(EdkLogger.DEBUG_0) + + W = os.getenv('WORKSPACE') + F = os.path.join(W, 'Nt32Pkg/Nt32Pkg.dec') + + Db = Database.Database('Dec.db') + Db.InitDatabase() + + P = Dec(os.path.normpath(F), True, True, W, Db) + P.ShowPackage() + + Db.Close() diff --git a/BaseTools/Source/Python/Common/DecClassObjectLight.py b/BaseTools/Source/Python/Common/DecClassObjectLight.py new file mode 100644 index 0000000000..7c572a56f0 --- /dev/null +++ b/BaseTools/Source/Python/Common/DecClassObjectLight.py @@ -0,0 +1,580 @@ +## @file +# This file is used to define each component of DEC file in light mode +# +# Copyright (c) 2008, 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. +# + +## +# Import Modules +# +import os +from Misc import GetFiles +from String import * +from DataType import * +from CommonDataClass.PackageClass import * +from CommonDataClass import CommonClass +from BuildToolError import * +from Parsing import * + +# Global variable +Section = {TAB_UNKNOWN.upper() : MODEL_UNKNOWN, + TAB_DEC_DEFINES.upper() : MODEL_META_DATA_HEADER, + TAB_INCLUDES.upper() : MODEL_EFI_INCLUDE, + TAB_LIBRARY_CLASSES.upper() : MODEL_EFI_LIBRARY_CLASS, + TAB_COMPONENTS.upper() : MODEL_META_DATA_COMPONENT, + TAB_GUIDS.upper() : MODEL_EFI_GUID, + TAB_PROTOCOLS.upper() : MODEL_EFI_PROTOCOL, + TAB_PPIS.upper() : MODEL_EFI_PPI, + TAB_PCDS_FIXED_AT_BUILD_NULL.upper() : MODEL_PCD_FIXED_AT_BUILD, + TAB_PCDS_PATCHABLE_IN_MODULE_NULL.upper() : MODEL_PCD_PATCHABLE_IN_MODULE, + TAB_PCDS_FEATURE_FLAG_NULL.upper() : MODEL_PCD_FEATURE_FLAG, + TAB_PCDS_DYNAMIC_EX_NULL.upper() : MODEL_PCD_DYNAMIC_EX, + TAB_PCDS_DYNAMIC_NULL.upper() : MODEL_PCD_DYNAMIC, + TAB_USER_EXTENSIONS.upper() : MODEL_META_DATA_USER_EXTENSION + } + +## DecObject +# +# This class defined basic Dec object which is used by inheriting +# +# @param object: Inherited from object class +# +class DecObject(object): + def __init__(self): + object.__init__() + +## Dec +# +# This class defined the structure used in Dec object +# +# @param DecObject: Inherited from DecObject class +# @param Filename: Input value for Filename of Dec file, default is None +# @param IsMergeAllArches: Input value for IsMergeAllArches +# True is to merge all arches +# Fales is not to merge all arches +# default is False +# @param IsToPackage: Input value for IsToPackage +# True is to transfer to PackageObject automatically +# False is not to transfer to PackageObject automatically +# default is False +# @param WorkspaceDir: Input value for current workspace directory, default is None +# +# @var Identification: To store value for Identification, it is a structure as Identification +# @var Defines: To store value for Defines, it is a structure as DecDefines +# @var UserExtensions: To store value for UserExtensions +# @var Package: To store value for Package, it is a structure as PackageClass +# @var WorkspaceDir: To store value for WorkspaceDir +# @var Contents: To store value for Contents, it is a structure as DecContents +# @var KeyList: To store value for KeyList, a list for all Keys used in Dec +# +class Dec(DecObject): + def __init__(self, Filename = None, IsToPackage = False, WorkspaceDir = None, AllGuidVersionDict = None, SupArchList = DataType.ARCH_LIST): + self.Identification = IdentificationClass() + self.Package = PackageClass() + self.UserExtensions = '' + self.WorkspaceDir = WorkspaceDir + self.SupArchList = SupArchList + self.AllGuidVersionDict = {} + if AllGuidVersionDict: + self.AllGuidVersionDict = AllGuidVersionDict + + self.KeyList = [ + TAB_INCLUDES, TAB_GUIDS, TAB_PROTOCOLS, TAB_PPIS, TAB_LIBRARY_CLASSES, \ + TAB_PCDS_FIXED_AT_BUILD_NULL, TAB_PCDS_PATCHABLE_IN_MODULE_NULL, TAB_PCDS_FEATURE_FLAG_NULL, \ + TAB_PCDS_DYNAMIC_NULL, TAB_PCDS_DYNAMIC_EX_NULL, TAB_DEC_DEFINES + ] + # Upper all KEYs to ignore case sensitive when parsing + self.KeyList = map(lambda c: c.upper(), self.KeyList) + + # Init RecordSet + self.RecordSet = {} + for Key in self.KeyList: + self.RecordSet[Section[Key]] = [] + + # Init Comment + self.SectionHeaderCommentDict = {} + + # Load Dec file if filename is not None + if Filename != None: + self.LoadDecFile(Filename) + + # Transfer to Package Object if IsToPackage is True + if IsToPackage: + self.DecToPackage() + + ## Load Dec file + # + # Load the file if it exists + # + # @param Filename: Input value for filename of Dec file + # + def LoadDecFile(self, Filename): + # Insert a record for file + Filename = NormPath(Filename) + self.Identification.FullPath = Filename + (self.Identification.RelaPath, self.Identification.FileName) = os.path.split(Filename) + if self.Identification.FullPath.find(self.WorkspaceDir) > -1: + self.Identification.PackagePath = os.path.dirname(self.Identification.FullPath[len(self.WorkspaceDir) + 1:]) + + # Init common datas + IfDefList, SectionItemList, CurrentSection, ArchList, ThirdList, IncludeFiles = \ + [], [], TAB_UNKNOWN, [], [], [] + LineNo = 0 + + # Parse file content + IsFindBlockComment = False + ReservedLine = '' + Comment = '' + for Line in open(Filename, 'r'): + LineNo = LineNo + 1 + # Remove comment block + if Line.find(TAB_COMMENT_R8_START) > -1: + ReservedLine = GetSplitValueList(Line, TAB_COMMENT_R8_START, 1)[0] + if ReservedLine.strip().startswith(TAB_COMMENT_SPLIT): + Comment = Comment + Line.strip() + '\n' + ReservedLine = '' + else: + Comment = Comment + Line[len(ReservedLine):] + '\n' + IsFindBlockComment = True + if not ReservedLine: + continue + if Line.find(TAB_COMMENT_R8_END) > -1: + Comment = Comment + Line[:Line.find(TAB_COMMENT_R8_END) + len(TAB_COMMENT_R8_END)] + '\n' + Line = ReservedLine + GetSplitValueList(Line, TAB_COMMENT_R8_END, 1)[1] + ReservedLine = '' + IsFindBlockComment = False + if IsFindBlockComment: + Comment = Comment + Line.strip() + '\n' + continue + + # Remove comments at tail and remove spaces again + if Line.strip().startswith(TAB_COMMENT_SPLIT) or Line.strip().startswith('--/'): + Comment = Comment + Line.strip() + '\n' + Line = CleanString(Line) + if Line == '': + continue + + ## Find a new section tab + # First insert previous section items + # And then parse the content of the new section + # + if Line.startswith(TAB_SECTION_START) and Line.endswith(TAB_SECTION_END): + # Insert items data of previous section + Model = Section[CurrentSection.upper()] + InsertSectionItems(Model, CurrentSection, SectionItemList, ArchList, ThirdList, self.RecordSet) + # Parse the new section + SectionItemList = [] + ArchList = [] + ThirdList = [] + + CurrentSection = '' + LineList = GetSplitValueList(Line[len(TAB_SECTION_START):len(Line) - len(TAB_SECTION_END)], TAB_COMMA_SPLIT) + for Item in LineList: + ItemList = GetSplitValueList(Item, TAB_SPLIT) + if CurrentSection == '': + CurrentSection = ItemList[0] + else: + if CurrentSection != ItemList[0]: + EdkLogger.error("Parser", PARSER_ERROR, "Different section names '%s' and '%s' are found in one section definition, this is not allowed." % (CurrentSection, ItemList[0]), File=Filename, Line=LineNo, RaiseError = EdkLogger.IsRaiseError) + if CurrentSection.upper() not in self.KeyList: + RaiseParserError(Line, CurrentSection, Filename, '', LineNo) + ItemList.append('') + ItemList.append('') + if len(ItemList) > 5: + RaiseParserError(Line, CurrentSection, Filename, '', LineNo) + else: + if ItemList[1] != '' and ItemList[1].upper() not in ARCH_LIST_FULL: + EdkLogger.error("Parser", PARSER_ERROR, "Invalid Arch definition '%s' found" % ItemList[1], File=Filename, Line=LineNo, RaiseError = EdkLogger.IsRaiseError) + ArchList.append(ItemList[1].upper()) + ThirdList.append(ItemList[2]) + + if Comment: + if Comment.endswith('\n'): + Comment = Comment[:len(Comment) - len('\n')] + self.SectionHeaderCommentDict[Section[CurrentSection.upper()]] = Comment + Comment = '' + continue + + # Not in any defined section + if CurrentSection == TAB_UNKNOWN: + ErrorMsg = "%s is not in any defined section" % Line + EdkLogger.error("Parser", PARSER_ERROR, ErrorMsg, File=Filename, Line=LineNo, RaiseError = EdkLogger.IsRaiseError) + + # Add a section item + SectionItemList.append([Line, LineNo, Comment]) + Comment = '' + # End of parse + #End of For + + # + # Insert items data of last section + # + Model = Section[CurrentSection.upper()] + InsertSectionItems(Model, CurrentSection, SectionItemList, ArchList, ThirdList, self.RecordSet) + if Comment != '': + self.SectionHeaderCommentDict[Model] = Comment + Comment = '' + + ## Package Object to DEC file + def PackageToDec(self, Package): + Dec = '' + DecList = sdict() + SectionHeaderCommentDict = {} + if Package == None: + return Dec + + PackageHeader = Package.PackageHeader + TmpList = [] + if PackageHeader.Name: + TmpList.append(TAB_DEC_DEFINES_PACKAGE_NAME + ' = ' + PackageHeader.Name) + if PackageHeader.Guid: + TmpList.append(TAB_DEC_DEFINES_PACKAGE_GUID + ' = ' + PackageHeader.Guid) + if PackageHeader.Version: + TmpList.append(TAB_DEC_DEFINES_PACKAGE_VERSION + ' = ' + PackageHeader.Version) + if PackageHeader.DecSpecification: + TmpList.append(TAB_DEC_DEFINES_DEC_SPECIFICATION + ' = ' + PackageHeader.DecSpecification) + if Package.UserExtensions != None: + for Item in Package.UserExtensions.Defines: + TmpList.append(Item) + DecList['Defines'] =TmpList + if PackageHeader.Description != '': + SectionHeaderCommentDict['Defines'] = PackageHeader.Description + + for Item in Package.Includes: + Key = 'Includes.' + Item.SupArchList + Value = Item.FilePath + GenMetaDatSectionItem(Key, Value, DecList) + + for Item in Package.GuidDeclarations: + Key = 'Guids.' + Item.SupArchList + Value = Item.CName + '=' + Item.Guid + GenMetaDatSectionItem(Key, Value, DecList) + + for Item in Package.ProtocolDeclarations: + Key = 'Protocols.' + Item.SupArchList + Value = Item.CName + '=' + Item.Guid + GenMetaDatSectionItem(Key, Value, DecList) + + for Item in Package.PpiDeclarations: + Key = 'Ppis.' + Item.SupArchList + Value = Item.CName + '=' + Item.Guid + GenMetaDatSectionItem(Key, Value, DecList) + + for Item in Package.LibraryClassDeclarations: + Key = 'LibraryClasses.' + Item.SupArchList + Value = Item.LibraryClass + '|' + Item.RecommendedInstance + GenMetaDatSectionItem(Key, Value, DecList) + + for Item in Package.PcdDeclarations: + Key = 'Pcds' + Item.ItemType + '.' + Item.SupArchList + Value = Item.TokenSpaceGuidCName + '.' + Item.CName + if Item.DefaultValue != '': + Value = Value + '|' + Item.DefaultValue + if Item.DatumType != '': + Value = Value + '|' + Item.DatumType + if Item.Token != '': + Value = Value + '|' + Item.Token + GenMetaDatSectionItem(Key, Value, DecList) + + # Transfer Package to Inf + for Key in DecList: + if Key in SectionHeaderCommentDict: + List = SectionHeaderCommentDict[Key].split('\r') + for Item in List: + Dec = Dec + Item + '\n' + Dec = Dec + '[' + Key + ']' + '\n' + for Value in DecList[Key]: + if type(Value) == type([]): + for SubValue in Value: + Dec = Dec + ' ' + SubValue + '\n' + else: + Dec = Dec + ' ' + Value + '\n' + Dec = Dec + '\n' + + return Dec + + ## Transfer to Package Object + # + # Transfer all contents of a Dec file to a standard Package Object + # + def DecToPackage(self): + # Init global information for the file + ContainerFile = self.Identification.FullPath + + # Generate Package Header + self.GenPackageHeader(ContainerFile) + + # Generate Includes + # Only for R8 + self.GenIncludes(ContainerFile) + + # Generate Guids + self.GenGuidProtocolPpis(DataType.TAB_GUIDS, ContainerFile) + + # Generate Protocols + self.GenGuidProtocolPpis(DataType.TAB_PROTOCOLS, ContainerFile) + + # Generate Ppis + self.GenGuidProtocolPpis(DataType.TAB_PPIS, ContainerFile) + + # Generate LibraryClasses + self.GenLibraryClasses(ContainerFile) + + # Generate Pcds + self.GenPcds(ContainerFile) + + # Init MiscFiles + self.GenMiscFiles(ContainerFile) + + ## GenMiscFiles + # + def GenMiscFiles(self, ContainerFile): + MiscFiles = MiscFileClass() + MiscFiles.Name = 'ModuleFiles' + for Item in GetFiles(os.path.dirname(ContainerFile), ['CVS', '.svn'], False): + File = CommonClass.FileClass() + File.Filename = Item + MiscFiles.Files.append(File) + self.Package.MiscFiles = MiscFiles + + ## Get Package Header + # + # Gen Package Header of Dec as = + # + # @param ContainerFile: The Dec file full path + # + def GenPackageHeader(self, ContainerFile): + EdkLogger.debug(2, "Generate PackageHeader ...") + # + # Update all defines item in database + # + RecordSet = self.RecordSet[MODEL_META_DATA_HEADER] + PackageHeader = PackageHeaderClass() + OtherDefines = [] + for Record in RecordSet: + ValueList = GetSplitValueList(Record[0], TAB_EQUAL_SPLIT) + if len(ValueList) != 2: + OtherDefines.append(Record[0]) + else: + Name = ValueList[0] + Value = ValueList[1] + if Name == TAB_DEC_DEFINES_PACKAGE_NAME: + PackageHeader.Name = Value + elif Name == TAB_DEC_DEFINES_PACKAGE_GUID: + PackageHeader.Guid = Value + elif Name == TAB_DEC_DEFINES_PACKAGE_VERSION: + PackageHeader.Version = Value + elif Name == TAB_DEC_DEFINES_DEC_SPECIFICATION: + PackageHeader.DecSpecification = Value + else: + OtherDefines.append(Record[0]) + + PackageHeader.FileName = self.Identification.FileName + PackageHeader.FullPath = self.Identification.FullPath + PackageHeader.RelaPath = self.Identification.RelaPath + PackageHeader.PackagePath = self.Identification.PackagePath + PackageHeader.ModulePath = self.Identification.ModulePath + PackageHeader.CombinePath = os.path.normpath(os.path.join(PackageHeader.PackagePath, PackageHeader.ModulePath, PackageHeader.FileName)) + + if MODEL_META_DATA_HEADER in self.SectionHeaderCommentDict: + PackageHeader.Description = self.SectionHeaderCommentDict[MODEL_META_DATA_HEADER] + + self.Package.PackageHeader = PackageHeader + UE = UserExtensionsClass() + UE.Defines = OtherDefines + self.Package.UserExtensions = UE + + + ## GenIncludes + # + # Gen Includes of Dec + # + # @param ContainerFile: The Dec file full path + # + def GenIncludes(self, ContainerFile): + EdkLogger.debug(2, "Generate %s ..." % TAB_INCLUDES) + Includes = {} + # Get all Includes + RecordSet = self.RecordSet[MODEL_EFI_INCLUDE] + + # Go through each arch + for Record in RecordSet: + Arch = Record[1] + Key = Record[0] + Include = IncludeClass() + Include.FilePath = NormPath(Key) + Include.SupArchList = Arch + self.Package.Includes.append(Include) + + ## GenPpis + # + # Gen Ppis of Dec + # = + # + # @param ContainerFile: The Dec file full path + # + def GenGuidProtocolPpis(self, Type, ContainerFile): + EdkLogger.debug(2, "Generate %s ..." % Type) + Lists = {} + # Get all Items + RecordSet = self.RecordSet[Section[Type.upper()]] + + # Go through each arch + for Record in RecordSet: + Arch = Record[1] + (Name, Value) = GetGuidsProtocolsPpisOfDec(Record[0], Type, ContainerFile, Record[2]) + + ListMember = None + if Type == TAB_GUIDS: + ListMember = self.Package.GuidDeclarations + elif Type == TAB_PROTOCOLS: + ListMember = self.Package.ProtocolDeclarations + elif Type == TAB_PPIS: + ListMember = self.Package.PpiDeclarations + + ListClass = GuidProtocolPpiCommonClass() + ListClass.CName = Name + ListClass.Guid = Value + ListClass.SupArchList = Arch + ListMember.append(ListClass) + + ## GenLibraryClasses + # + # Gen LibraryClasses of Dec + # = + # + # @param ContainerFile: The Dec file full path + # + def GenLibraryClasses(self, ContainerFile): + EdkLogger.debug(2, "Generate %s ..." % TAB_LIBRARY_CLASSES) + LibraryClasses = {} + # Get all Guids + RecordSet = self.RecordSet[MODEL_EFI_LIBRARY_CLASS] + + # Go through each arch + for Record in RecordSet: + Arch = Record[1] + List = GetSplitValueList(Record[0], DataType.TAB_VALUE_SPLIT) + if len(List) != 2: + continue + LibraryClass = LibraryClassClass() + LibraryClass.LibraryClass = List[0] + LibraryClass.RecommendedInstance = NormPath(List[1]) + LibraryClass.SupArchList = Arch + self.Package.LibraryClassDeclarations.append(LibraryClass) + + def AddPcd(self, CName, Token, TokenSpaceGuidCName, DatumType, DefaultValue, ItemType, Arch): + Pcd = CommonClass.PcdClass() + Pcd.CName = CName + Pcd.Token = Token + Pcd.TokenSpaceGuidCName = TokenSpaceGuidCName + Pcd.DatumType = DatumType + Pcd.DefaultValue = DefaultValue + Pcd.ItemType = ItemType + Pcd.SupArchList = Arch + self.Package.PcdDeclarations.append(Pcd) + + ## GenPcds + # + # Gen Pcds of Dec + # .||| + # + # @param ContainerFile: The Dec file full path + # + def GenPcds(self, ContainerFile): + EdkLogger.debug(2, "Generate %s ..." % TAB_PCDS) + Pcds = {} + PcdToken = {} + # Get all Pcds + RecordSet1 = self.RecordSet[MODEL_PCD_FIXED_AT_BUILD] + RecordSet2 = self.RecordSet[MODEL_PCD_PATCHABLE_IN_MODULE] + RecordSet3 = self.RecordSet[MODEL_PCD_FEATURE_FLAG] + RecordSet4 = self.RecordSet[MODEL_PCD_DYNAMIC_EX] + RecordSet5 = self.RecordSet[MODEL_PCD_DYNAMIC] + + # Go through each pcd + for Record in RecordSet1: + Arch = Record[1] + (TokenGuidCName, TokenName, DefaultValue, DatumType, Token, ItemType) = GetPcdOfDec(Record[0], TAB_PCDS_FIXED_AT_BUILD, ContainerFile, Record[2]) + self.AddPcd(TokenName, Token, TokenGuidCName, DatumType, DefaultValue, ItemType, Arch) + for Record in RecordSet2: + Arch = Record[1] + (TokenGuidCName, TokenName, DefaultValue, DatumType, Token, ItemType) = GetPcdOfDec(Record[0], TAB_PCDS_PATCHABLE_IN_MODULE, ContainerFile, Record[2]) + self.AddPcd(TokenName, Token, TokenGuidCName, DatumType, DefaultValue, ItemType, Arch) + for Record in RecordSet3: + Arch = Record[1] + (TokenGuidCName, TokenName, DefaultValue, DatumType, Token, ItemType) = GetPcdOfDec(Record[0], TAB_PCDS_FEATURE_FLAG, ContainerFile, Record[2]) + self.AddPcd(TokenName, Token, TokenGuidCName, DatumType, DefaultValue, ItemType, Arch) + for Record in RecordSet4: + Arch = Record[1] + (TokenGuidCName, TokenName, DefaultValue, DatumType, Token, ItemType) = GetPcdOfDec(Record[0], TAB_PCDS_DYNAMIC_EX, ContainerFile, Record[2]) + self.AddPcd(TokenName, Token, TokenGuidCName, DatumType, DefaultValue, ItemType, Arch) + for Record in RecordSet5: + Arch = Record[1] + (TokenGuidCName, TokenName, DefaultValue, DatumType, Token, ItemType) = GetPcdOfDec(Record[0], TAB_PCDS_DYNAMIC, ContainerFile, Record[2]) + self.AddPcd(TokenName, Token, TokenGuidCName, DatumType, DefaultValue, ItemType, Arch) + + ## Show detailed information of Package + # + # Print all members and their values of Package class + # + def ShowPackage(self): + M = self.Package + print 'Filename =', M.PackageHeader.FileName + print 'FullPath =', M.PackageHeader.FullPath + print 'RelaPath =', M.PackageHeader.RelaPath + print 'PackagePath =', M.PackageHeader.PackagePath + print 'ModulePath =', M.PackageHeader.ModulePath + print 'CombinePath =', M.PackageHeader.CombinePath + + print 'BaseName =', M.PackageHeader.Name + print 'Guid =', M.PackageHeader.Guid + print 'Version =', M.PackageHeader.Version + print 'DecSpecification =', M.PackageHeader.DecSpecification + + print '\nIncludes ='#, M.Includes + for Item in M.Includes: + print Item.FilePath, Item.SupArchList + print '\nGuids ='#, M.GuidDeclarations + for Item in M.GuidDeclarations: + print Item.CName, Item.Guid, Item.SupArchList + print '\nProtocols ='#, M.ProtocolDeclarations + for Item in M.ProtocolDeclarations: + print Item.CName, Item.Guid, Item.SupArchList + print '\nPpis ='#, M.PpiDeclarations + for Item in M.PpiDeclarations: + print Item.CName, Item.Guid, Item.SupArchList + print '\nLibraryClasses ='#, M.LibraryClassDeclarations + for Item in M.LibraryClassDeclarations: + print Item.LibraryClass, Item.RecommendedInstance, Item.SupModuleList, Item.SupArchList + print '\nPcds ='#, M.PcdDeclarations + for Item in M.PcdDeclarations: + print 'CName=', Item.CName, 'TokenSpaceGuidCName=', Item.TokenSpaceGuidCName, 'DefaultValue=', Item.DefaultValue, 'ItemType=', Item.ItemType, 'Token=', Item.Token, 'DatumType=', Item.DatumType, Item.SupArchList + print '\nUserExtensions =', M.UserExtensions.Defines + print '\n*** FileList ***' + for Item in M.MiscFiles.Files: + print Item.Filename + print '****************\n' + +## +# +# This acts like the main() function for the script, unless it is 'import'ed into another +# script. +# +if __name__ == '__main__': + EdkLogger.Initialize() + EdkLogger.SetLevel(EdkLogger.QUIET) + + W = os.getenv('WORKSPACE') + F = os.path.join(W, 'MdeModulePkg/MdeModulePkg.dec') + + P = Dec(os.path.normpath(F), True, W) + P.ShowPackage() + print P.PackageToDec(P.Package) diff --git a/BaseTools/Source/Python/Common/Dictionary.py b/BaseTools/Source/Python/Common/Dictionary.py new file mode 100644 index 0000000000..3c968f5ec6 --- /dev/null +++ b/BaseTools/Source/Python/Common/Dictionary.py @@ -0,0 +1,75 @@ +## @file +# Define a dictionary structure +# +# Copyright (c) 2007, 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. +# + +## +# Import Modules +# +import EdkLogger +from DataType import * + +## Convert a text file to a dictionary +# +# Convert a text file to a dictionary of (name:value) pairs. +# +# @retval 0 Convert successful +# @retval 1 Open file failed +# +def ConvertTextFileToDictionary(FileName, Dictionary, CommentCharacter, KeySplitCharacter, ValueSplitFlag, ValueSplitCharacter): + try: + F = open(FileName,'r') + Keys = [] + for Line in F: + if Line.startswith(CommentCharacter): + continue + LineList = Line.split(KeySplitCharacter,1) + if len(LineList) >= 2: + Key = LineList[0].split() + if len(Key) == 1 and Key[0][0] != CommentCharacter and Key[0] not in Keys: + if ValueSplitFlag: + Dictionary[Key[0]] = LineList[1].replace('\\','/').split(ValueSplitCharacter) + else: + Dictionary[Key[0]] = LineList[1].strip().replace('\\','/') + Keys += [Key[0]] + F.close() + return 0 + except: + EdkLogger.info('Open file failed') + return 1 + +## Print the dictionary +# +# Print all items of dictionary one by one +# +# @param Dict: The dictionary to be printed +# +def printDict(Dict): + if Dict != None: + KeyList = Dict.keys() + for Key in KeyList: + if Dict[Key] != '': + print Key + ' = ' + str(Dict[Key]) + +## Print the dictionary +# +# Print the items of dictionary which matched with input key +# +# @param list: The dictionary to be printed +# @param key: The key of the item to be printed +# +def printList(Key, List): + if type(List) == type([]): + if len(List) > 0: + if key.find(TAB_SPLIT) != -1: + print "\n" + Key + for Item in List: + print Item diff --git a/BaseTools/Source/Python/Common/DscClassObject.py b/BaseTools/Source/Python/Common/DscClassObject.py new file mode 100644 index 0000000000..ddccf6507d --- /dev/null +++ b/BaseTools/Source/Python/Common/DscClassObject.py @@ -0,0 +1,1434 @@ +## @file +# This file is used to define each component of DSC file +# +# Copyright (c) 2007 ~ 2008, 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. +# + +## +# Import Modules +# +import os +import EdkLogger as EdkLogger +import Database +from String import * +from Parsing import * +from DataType import * +from Identification import * +from Dictionary import * +from CommonDataClass.PlatformClass import * +from CommonDataClass.CommonClass import SkuInfoClass +from BuildToolError import * +from Misc import sdict +import GlobalData +from Table.TableDsc import TableDsc + +# +# Global variable +# +Section = {TAB_UNKNOWN.upper() : MODEL_UNKNOWN, + TAB_DSC_DEFINES.upper() : MODEL_META_DATA_HEADER, + TAB_BUILD_OPTIONS.upper() : MODEL_META_DATA_BUILD_OPTION, + TAB_SKUIDS.upper() : MODEL_EFI_SKU_ID, + TAB_LIBRARIES.upper() : MODEL_EFI_LIBRARY_INSTANCE, + TAB_LIBRARY_CLASSES.upper() : MODEL_EFI_LIBRARY_CLASS, + TAB_PCDS_FIXED_AT_BUILD_NULL.upper() : MODEL_PCD_FIXED_AT_BUILD, + TAB_PCDS_PATCHABLE_IN_MODULE_NULL.upper() : MODEL_PCD_PATCHABLE_IN_MODULE, + TAB_PCDS_FEATURE_FLAG_NULL.upper() : MODEL_PCD_FEATURE_FLAG, + TAB_PCDS_DYNAMIC_EX_NULL.upper() : MODEL_PCD_DYNAMIC_EX, + TAB_PCDS_DYNAMIC_EX_DEFAULT_NULL.upper() : MODEL_PCD_DYNAMIC_EX_DEFAULT, + TAB_PCDS_DYNAMIC_EX_VPD_NULL.upper() : MODEL_PCD_DYNAMIC_EX_VPD, + TAB_PCDS_DYNAMIC_EX_HII_NULL.upper() : MODEL_PCD_DYNAMIC_EX_HII, + TAB_PCDS_DYNAMIC_NULL.upper() : MODEL_PCD_DYNAMIC, + TAB_PCDS_DYNAMIC_DEFAULT_NULL.upper() : MODEL_PCD_DYNAMIC_DEFAULT, + TAB_PCDS_DYNAMIC_VPD_NULL.upper() : MODEL_PCD_DYNAMIC_VPD, + TAB_PCDS_DYNAMIC_HII_NULL.upper() : MODEL_PCD_DYNAMIC_HII, + TAB_COMPONENTS.upper() : MODEL_META_DATA_COMPONENT, + TAB_USER_EXTENSIONS.upper() : MODEL_META_DATA_USER_EXTENSION + } + +## DscObject +# +# This class defined basic Dsc object which is used by inheriting +# +# @param object: Inherited from object class +# +class DscObject(object): + def __init__(self): + object.__init__() + +## Dsc +# +# This class defined the structure used in Dsc object +# +# @param DscObject: Inherited from InfObject class +# @param Ffilename: Input value for Ffilename of Inf file, default is None +# @param IsMergeAllArches: Input value for IsMergeAllArches +# True is to merge all arches +# Fales is not to merge all arches +# default is False +# @param IsToPlatform: Input value for IsToPlatform +# True is to transfer to ModuleObject automatically +# False is not to transfer to ModuleObject automatically +# default is False +# @param WorkspaceDir: Input value for current workspace directory, default is None +# +# @var _NullClassIndex: To store value for _NullClassIndex, default is 0 +# @var Identification: To store value for Identification, it is a structure as Identification +# @var Defines: To store value for Defines, it is a structure as DscDefines +# @var Contents: To store value for Contents, it is a structure as DscContents +# @var UserExtensions: To store value for UserExtensions +# @var Platform: To store value for Platform, it is a structure as PlatformClass +# @var WorkspaceDir: To store value for WorkspaceDir +# @var KeyList: To store value for KeyList, a list for all Keys used in Dec +# +class Dsc(DscObject): + _NullClassIndex = 0 + + def __init__(self, Filename = None, IsToDatabase = False, IsToPlatform = False, WorkspaceDir = None, Database = None): + self.Identification = Identification() + self.Platform = PlatformClass() + self.UserExtensions = '' + self.WorkspaceDir = WorkspaceDir + self.IsToDatabase = IsToDatabase + + self.Cur = Database.Cur + self.TblFile = Database.TblFile + self.TblDsc = Database.TblDsc + + + self.KeyList = [ + TAB_SKUIDS, TAB_LIBRARIES, TAB_LIBRARY_CLASSES, TAB_BUILD_OPTIONS, TAB_PCDS_FIXED_AT_BUILD_NULL, \ + TAB_PCDS_PATCHABLE_IN_MODULE_NULL, TAB_PCDS_FEATURE_FLAG_NULL, \ + TAB_PCDS_DYNAMIC_DEFAULT_NULL, TAB_PCDS_DYNAMIC_HII_NULL, TAB_PCDS_DYNAMIC_VPD_NULL, \ + TAB_PCDS_DYNAMIC_EX_DEFAULT_NULL, TAB_PCDS_DYNAMIC_EX_HII_NULL, TAB_PCDS_DYNAMIC_EX_VPD_NULL, \ + TAB_COMPONENTS, TAB_DSC_DEFINES + ] + + self.PcdToken = {} + + # + # Upper all KEYs to ignore case sensitive when parsing + # + self.KeyList = map(lambda c: c.upper(), self.KeyList) + + # + # Init RecordSet + # +# self.RecordSet = {} +# for Key in self.KeyList: +# self.RecordSet[Section[Key]] = [] + + # + # Load Dsc file if filename is not None + # + if Filename != None: + self.LoadDscFile(Filename) + + # + # Transfer to Platform Object if IsToPlatform is True + # + if IsToPlatform: + self.DscToPlatform() + + ## Transfer to Platform Object + # + # Transfer all contents of an Inf file to a standard Module Object + # + def DscToPlatform(self): + # + # Init global information for the file + # + ContainerFile = self.Identification.FileFullPath + + # + # Generate Platform Header + # + self.GenPlatformHeader(ContainerFile) + + # + # Generate BuildOptions + # + self.GenBuildOptions(ContainerFile) + + # + # Generate SkuInfos + # + self.GenSkuInfos(ContainerFile) + + # + # Generate Libraries + # + self.GenLibraries(ContainerFile) + + # + # Generate LibraryClasses + # + self.GenLibraryClasses(ContainerFile) + + # + # Generate Pcds + # + self.GenPcds(DataType.TAB_PCDS_FIXED_AT_BUILD, ContainerFile) + self.GenPcds(DataType.TAB_PCDS_PATCHABLE_IN_MODULE, ContainerFile) + self.GenFeatureFlagPcds(DataType.TAB_PCDS_FEATURE_FLAG, ContainerFile) + self.GenDynamicDefaultPcds(DataType.TAB_PCDS_DYNAMIC_DEFAULT, ContainerFile) + self.GenDynamicDefaultPcds(DataType.TAB_PCDS_DYNAMIC_EX_DEFAULT, ContainerFile) + self.GenDynamicHiiPcds(DataType.TAB_PCDS_DYNAMIC_HII, ContainerFile) + self.GenDynamicHiiPcds(DataType.TAB_PCDS_DYNAMIC_EX_HII, ContainerFile) + self.GenDynamicVpdPcds(DataType.TAB_PCDS_DYNAMIC_VPD, ContainerFile) + self.GenDynamicVpdPcds(DataType.TAB_PCDS_DYNAMIC_EX_VPD, ContainerFile) + + # + # Generate Components + # + self.GenComponents(ContainerFile) + + # + # Update to database + # + if self.IsToDatabase: + for Key in self.PcdToken.keys(): + SqlCommand = """update %s set Value2 = '%s' where ID = %s""" % (self.TblDsc.Table, ".".join((self.PcdToken[Key][0], self.PcdToken[Key][1])), Key) + self.TblDsc.Exec(SqlCommand) + #End of DscToPlatform + + ## Get Platform Header + # + # Gen Platform Header of Dsc as = + # + # @param ContainerFile: The Dsc file full path + # + def GenPlatformHeader(self, ContainerFile): + EdkLogger.debug(2, "Generate PlatformHeader ...") + # + # Update all defines item in database + # + SqlCommand = """select ID, Value1, Arch, StartLine from %s + where Model = %s + and BelongsToFile = %s + and Enabled > -1""" % (self.TblDsc.Table, MODEL_META_DATA_HEADER, self.FileID) + RecordSet = self.TblDsc.Exec(SqlCommand) + for Record in RecordSet: + ValueList = GetSplitValueList(Record[1], TAB_EQUAL_SPLIT) + if len(ValueList) != 2: + RaiseParserError(Record[1], 'Defines', ContainerFile, ' = ', Record[3]) + ID, Value1, Value2, Arch = Record[0], ValueList[0], ValueList[1], Record[2] + SqlCommand = """update %s set Value1 = '%s', Value2 = '%s' + where ID = %s""" % (self.TblDsc.Table, ConvertToSqlString2(Value1), ConvertToSqlString2(Value2), ID) + self.TblDsc.Exec(SqlCommand) + + # + # Get detailed information + # + for Arch in DataType.ARCH_LIST: + PlatformHeader = PlatformHeaderClass() + + PlatformHeader.Name = QueryDefinesItem(self.TblDsc, TAB_DSC_DEFINES_PLATFORM_NAME, Arch, self.FileID)[0] + PlatformHeader.Guid = QueryDefinesItem(self.TblDsc, TAB_DSC_DEFINES_PLATFORM_GUID, Arch, self.FileID)[0] + PlatformHeader.Version = QueryDefinesItem(self.TblDsc, TAB_DSC_DEFINES_PLATFORM_VERSION, Arch, self.FileID)[0] + PlatformHeader.FileName = self.Identification.FileName + PlatformHeader.FullPath = self.Identification.FileFullPath + PlatformHeader.DscSpecification = QueryDefinesItem(self.TblDsc, TAB_DSC_DEFINES_DSC_SPECIFICATION, Arch, self.FileID)[0] + + PlatformHeader.SkuIdName = QueryDefinesItem(self.TblDsc, TAB_DSC_DEFINES_SKUID_IDENTIFIER, Arch, self.FileID) + PlatformHeader.SupArchList = QueryDefinesItem(self.TblDsc, TAB_DSC_DEFINES_SUPPORTED_ARCHITECTURES, Arch, self.FileID) + PlatformHeader.BuildTargets = QueryDefinesItem(self.TblDsc, TAB_DSC_DEFINES_BUILD_TARGETS, Arch, self.FileID) + PlatformHeader.OutputDirectory = NormPath(QueryDefinesItem(self.TblDsc, TAB_DSC_DEFINES_OUTPUT_DIRECTORY, Arch, self.FileID)[0]) + PlatformHeader.BuildNumber = QueryDefinesItem(self.TblDsc, TAB_DSC_DEFINES_BUILD_NUMBER, Arch, self.FileID)[0] + PlatformHeader.MakefileName = QueryDefinesItem(self.TblDsc, TAB_DSC_DEFINES_MAKEFILE_NAME, Arch, self.FileID)[0] + + PlatformHeader.BsBaseAddress = QueryDefinesItem(self.TblDsc, TAB_DSC_DEFINES_BS_BASE_ADDRESS, Arch, self.FileID)[0] + PlatformHeader.RtBaseAddress = QueryDefinesItem(self.TblDsc, TAB_DSC_DEFINES_RT_BASE_ADDRESS, Arch, self.FileID)[0] + + self.Platform.Header[Arch] = PlatformHeader + Fdf = PlatformFlashDefinitionFileClass() + Fdf.FilePath = NormPath(QueryDefinesItem(self.TblDsc, TAB_DSC_DEFINES_FLASH_DEFINITION, Arch, self.FileID)[0]) + self.Platform.FlashDefinitionFile = Fdf + + ## GenBuildOptions + # + # Gen BuildOptions of Dsc + # [:]=Flag + # + # @param ContainerFile: The Dsc file full path + # + def GenBuildOptions(self, ContainerFile): + EdkLogger.debug(2, "Generate %s ..." % TAB_BUILD_OPTIONS) + BuildOptions = {} + # + # Get all include files + # + IncludeFiles = QueryDscItem(self.TblDsc, MODEL_META_DATA_INCLUDE, MODEL_META_DATA_BUILD_OPTION, self.FileID) + + # + # Get all BuildOptions + # + RecordSet = QueryDscItem(self.TblDsc, MODEL_META_DATA_BUILD_OPTION, -1, self.FileID) + + # + # Go through each arch + # + for Arch in DataType.ARCH_LIST: + for IncludeFile in IncludeFiles: + if IncludeFile[1] == Arch or IncludeFile[1] == TAB_ARCH_COMMON.upper(): + Filename = CheckFileExist(self.WorkspaceDir, IncludeFile[0], ContainerFile, TAB_BUILD_OPTIONS, '', IncludeFile[2]) + for NewItem in open(Filename, 'r').readlines(): + if CleanString(NewItem) == '': + continue + (Family, ToolChain, Flag) = GetBuildOption(NewItem, Filename, -1) + MergeArches(BuildOptions, (Family, ToolChain, Flag), Arch) + + for Record in RecordSet: + if Record[1] == Arch or Record[1] == TAB_ARCH_COMMON.upper(): + (Family, ToolChain, Flag) = GetBuildOption(Record[0], ContainerFile, Record[2]) + MergeArches(BuildOptions, (Family, ToolChain, Flag), Arch) + # + # Update to Database + # + if self.IsToDatabase: + SqlCommand = """update %s set Value1 = '%s', Value2 = '%s', Value3 = '%s' + where ID = %s""" % (self.TblDsc.Table, ConvertToSqlString2(Family), ConvertToSqlString2(ToolChain), ConvertToSqlString2(Flag), Record[3]) + self.TblDsc.Exec(SqlCommand) + + for Key in BuildOptions.keys(): + BuildOption = BuildOptionClass(Key[0], Key[1], Key[2]) + BuildOption.SupArchList = BuildOptions[Key] + self.Platform.BuildOptions.BuildOptionList.append(BuildOption) + + ## GenSkuInfos + # + # Gen SkuInfos of Dsc + # | + # + # @param ContainerFile: The Dsc file full path + # + def GenSkuInfos(self, ContainerFile): + EdkLogger.debug(2, "Generate %s ..." % TAB_SKUIDS) + # + # SkuIds + # | + # + self.Platform.SkuInfos.SkuInfoList['DEFAULT'] = '0' + + # + # Get all include files + # + IncludeFiles = QueryDscItem(self.TblDsc, MODEL_META_DATA_INCLUDE, MODEL_EFI_SKU_ID, self.FileID) + + # + # Get all SkuInfos + # + RecordSet = QueryDscItem(self.TblDsc, MODEL_EFI_SKU_ID, -1, self.FileID) + + # + # Go through each arch + # + for Arch in DataType.ARCH_LIST: + for IncludeFile in IncludeFiles: + if IncludeFile[1] == Arch or IncludeFile[1] == TAB_ARCH_COMMON.upper(): + Filename = CheckFileExist(self.WorkspaceDir, IncludeFile[0], ContainerFile, TAB_SKUIDS, '', IncludeFile[2]) + for NewItem in open(Filename, 'r').readlines(): + if CleanString(NewItem) == '': + continue + List = GetSplitValueList(NewItem) + if len(List) != 2: + RaiseParserError(NewItem, TAB_SKUIDS, Filename, '|') + else: + self.Platform.SkuInfos.SkuInfoList[List[1]] = List[0] + + for Record in RecordSet: + if Record[1] == Arch or Record[1] == TAB_ARCH_COMMON.upper(): + List = GetSplitValueList(Record[0]) + if len(List) != 2: + RaiseParserError(Record[0], TAB_SKUIDS, ContainerFile, '|') + else: + self.Platform.SkuInfos.SkuInfoList[List[1]] = List[0] + # + # Update to Database + # + if self.IsToDatabase: + SqlCommand = """update %s set Value1 = '%s', Value2 = '%s' + where ID = %s""" % (self.TblDsc.Table, ConvertToSqlString2(List[0]), ConvertToSqlString2(List[1]), Record[3]) + self.TblDsc.Exec(SqlCommand) + + ## GenLibraries + # + # Gen Libraries of Dsc + # + # + # @param ContainerFile: The Dsc file full path + # + def GenLibraries(self, ContainerFile): + EdkLogger.debug(2, "Generate %s ..." % TAB_LIBRARIES) + Libraries = {} + # + # Get all include files + # + IncludeFiles = QueryDscItem(self.TblDsc, MODEL_META_DATA_INCLUDE, MODEL_EFI_LIBRARY_INSTANCE, self.FileID) + + # + # Get all Libraries + # + RecordSet = QueryDscItem(self.TblDsc, MODEL_EFI_LIBRARY_INSTANCE, -1, self.FileID) + + # + # Go through each arch + # + for Arch in DataType.ARCH_LIST: + for IncludeFile in IncludeFiles: + if IncludeFile[1] == Arch or IncludeFile[1] == TAB_ARCH_COMMON.upper(): + Filename = CheckFileExist(self.WorkspaceDir, IncludeFile[0], ContainerFile, TAB_LIBRARIES, '', IncludeFile[2]) + for NewItem in open(Filename, 'r').readlines(): + if CleanString(NewItem) == '': + continue + MergeArches(Libraries, NewItem, Arch) + + for Record in RecordSet: + if Record[1] == Arch or Record[1] == TAB_ARCH_COMMON.upper(): + MergeArches(Libraries, Record[0], Arch) + + for Key in Libraries.keys(): + Library = PlatformLibraryClass() + Library.FilePath = NormPath(Key) + Library.SupArchList = Libraries[Key] + self.Platform.Libraries.LibraryList.append(Library) + + ## GenLibraryClasses + # + # Get LibraryClasses of Dsc + # | + # + # @param ContainerFile: The Dsc file full path + # + def GenLibraryClasses(self, ContainerFile): + EdkLogger.debug(2, "Generate %s ..." % TAB_LIBRARY_CLASSES) + LibraryClasses = {} + # + # Get all include files + # + IncludeFiles = QueryDscItem(self.TblDsc, MODEL_META_DATA_INCLUDE, MODEL_EFI_LIBRARY_CLASS, self.FileID) + + # + # Get all LibraryClasses + # + RecordSet = QueryDscItem(self.TblDsc, MODEL_EFI_LIBRARY_CLASS, -1, self.FileID) + + # + # Go through each arch + # + for Arch in DataType.ARCH_LIST: + for IncludeFile in IncludeFiles: + if IncludeFile[1] == Arch or IncludeFile[1] == TAB_ARCH_COMMON.upper(): + Filename = CheckFileExist(self.WorkspaceDir, IncludeFile[0], ContainerFile, TAB_LIBRARY_CLASSES, '', IncludeFile[2]) + for NewItem in open(Filename, 'r').readlines(): + if CleanString(NewItem) == '': + continue + MergeArches(LibraryClasses, GetLibraryClass([NewItem, IncludeFile[4]], Filename, self.WorkspaceDir, -1), Arch) + + for Record in RecordSet: + if Record[1] == Arch or Record[1] == TAB_ARCH_COMMON.upper(): + (LibClassName, LibClassIns, SupModelList) = GetLibraryClass([Record[0], Record[4]], ContainerFile, self.WorkspaceDir, Record[2]) + MergeArches(LibraryClasses, (LibClassName, LibClassIns, SupModelList), Arch) + # + # Update to Database + # + if self.IsToDatabase: + SqlCommand = """update %s set Value1 = '%s', Value2 = '%s', Value3 = '%s' + where ID = %s""" % (self.TblDsc.Table, ConvertToSqlString2(LibClassName), ConvertToSqlString2(LibClassIns), ConvertToSqlString2(SupModelList), Record[3]) + self.TblDsc.Exec(SqlCommand) + + for Key in LibraryClasses.keys(): + Library = PlatformLibraryClass() + Library.Name = Key[0] + Library.FilePath = NormPath(Key[1]) + Library.SupModuleList = GetSplitValueList(Key[2]) + Library.SupArchList = LibraryClasses[Key] + self.Platform.LibraryClasses.LibraryList.append(Library) + + ## Gen Pcds + # + # Gen Pcd of Dsc as .|[||] + # + # @param Type: The type of Pcd + # @param ContainerFile: The file which describes the pcd, used for error report + # + def GenPcds(self, Type = '', ContainerFile = ''): + Pcds = {} + if Type == DataType.TAB_PCDS_PATCHABLE_IN_MODULE: + Model = MODEL_PCD_PATCHABLE_IN_MODULE + elif Type == DataType.TAB_PCDS_FIXED_AT_BUILD: + Model = MODEL_PCD_FIXED_AT_BUILD + else: + pass + EdkLogger.debug(2, "Generate %s ..." % Type) + + # + # Get all include files + # + IncludeFiles = QueryDscItem(self.TblDsc, MODEL_META_DATA_INCLUDE, Model, self.FileID) + + # + # Get all Pcds + # + RecordSet = QueryDscItem(self.TblDsc, Model, -1, self.FileID) + + # + # Go through each arch + # + for Arch in DataType.ARCH_LIST: + for IncludeFile in IncludeFiles: + if IncludeFile[1] == Arch or IncludeFile[1] == TAB_ARCH_COMMON.upper(): + Filename = CheckFileExist(self.WorkspaceDir, IncludeFile[0], ContainerFile, Type, '', IncludeFile[2]) + for NewItem in open(Filename, 'r').readlines(): + if CleanString(NewItem) == '': + continue + (TokenName, TokenGuidCName, Value, DatumType, MaxDatumSize, Type) = GetPcd(NewItem, Type, Filename, -1) + MergeArches(Pcds, (TokenName, TokenGuidCName, Value, DatumType, MaxDatumSize, Type), Arch) + self.PcdToken[Record[3]] = (TokenGuidCName, TokenName) + + for Record in RecordSet: + if Record[1] == Arch or Record[1] == TAB_ARCH_COMMON.upper(): + (TokenName, TokenGuidCName, Value, DatumType, MaxDatumSize, Type) = GetPcd(Record[0], Type, ContainerFile, Record[2]) + MergeArches(Pcds, (TokenName, TokenGuidCName, Value, DatumType, MaxDatumSize, Type), Arch) + self.PcdToken[Record[3]] = (TokenGuidCName, TokenName) + + for Key in Pcds: + Pcd = PcdClass(Key[0], '', Key[1], Key[3], Key[4], Key[2], Key[5], [], {}, []) + Pcd.SupArchList = Pcds[Key] + self.Platform.DynamicPcdBuildDefinitions.append(Pcd) + + ## Gen FeatureFlagPcds + # + # Gen FeatureFlagPcds of Dsc file as .|TRUE/FALSE + # + # @param Type: The type of Pcd + # @param ContainerFile: The file which describes the pcd, used for error report + # + def GenFeatureFlagPcds(self, Type = '', ContainerFile = ''): + Pcds = {} + if Type == DataType.TAB_PCDS_FEATURE_FLAG: + Model = MODEL_PCD_FEATURE_FLAG + else: + pass + EdkLogger.debug(2, "Generate %s ..." % Type) + + # + # Get all include files + # + IncludeFiles = QueryDscItem(self.TblDsc, MODEL_META_DATA_INCLUDE, Model, self.FileID) + + # + # Get all FeatureFlagPcds + # + RecordSet = QueryDscItem(self.TblDsc, Model, -1, self.FileID) + + # + # Go through each arch + # + for Arch in DataType.ARCH_LIST: + for IncludeFile in IncludeFiles: + if IncludeFile[1] == Arch or IncludeFile[1] == TAB_ARCH_COMMON.upper(): + Filename = CheckFileExist(self.WorkspaceDir, IncludeFile[0], ContainerFile, Type, '', IncludeFile[2]) + for NewItem in open(Filename, 'r').readlines(): + if CleanString(NewItem) == '': + continue + (TokenName, TokenGuidCName, Value, Type) = GetFeatureFlagPcd(NewItem, Type, Filename, -1) + MergeArches(Pcds, (TokenName, TokenGuidCName, Value, Type), Arch) + self.PcdToken[Record[3]] = (TokenGuidCName, TokenName) + + for Record in RecordSet: + if Record[1] == Arch or Record[1] == TAB_ARCH_COMMON.upper(): + (TokenName, TokenGuidCName, Value, Type) = GetFeatureFlagPcd(Record[0], Type, ContainerFile, Record[2]) + MergeArches(Pcds, (TokenName, TokenGuidCName, Value, Type), Arch) + self.PcdToken[Record[3]] = (TokenGuidCName, TokenName) + + for Key in Pcds: + Pcd = PcdClass(Key[0], '', Key[1], '', '', Key[2], Key[3], [], {}, []) + Pcd.SupArchList = Pcds[Key] + self.Platform.DynamicPcdBuildDefinitions.append(Pcd) + + ## Gen DynamicDefaultPcds + # + # Gen DynamicDefaultPcds of Dsc as .|[|[|]] + # + # @param Type: The type of Pcd + # @param ContainerFile: The file which describes the pcd, used for error report + # + def GenDynamicDefaultPcds(self, Type = '', ContainerFile = ''): + Pcds = {} + SkuInfoList = {} + if Type == DataType.TAB_PCDS_DYNAMIC_DEFAULT: + Model = MODEL_PCD_DYNAMIC_DEFAULT + elif Type == DataType.TAB_PCDS_DYNAMIC_EX_DEFAULT: + Model = MODEL_PCD_DYNAMIC_EX_DEFAULT + else: + pass + EdkLogger.debug(2, "Generate %s ..." % Type) + + # + # Get all include files + # + IncludeFiles = QueryDscItem(self.TblDsc, MODEL_META_DATA_INCLUDE, Model, self.FileID) + + # + # Get all DynamicDefaultPcds + # + RecordSet = QueryDscItem(self.TblDsc, Model, -1, self.FileID) + + # + # Go through each arch + # + for Arch in DataType.ARCH_LIST: + for IncludeFile in IncludeFiles: + if IncludeFile[1] == Arch or IncludeFile[1] == TAB_ARCH_COMMON.upper(): + Filename = CheckFileExist(self.WorkspaceDir, IncludeFile[0], ContainerFile, Type, '', IncludeFile[2]) + for NewItem in open(Filename, 'r').readlines(): + if CleanString(NewItem) == '': + continue + (K1, K2, K3, K4, K5, K6) = GetDynamicDefaultPcd(NewItem, Type, Filename, -1) + MergeArches(Pcds, (K1, K2, K3, K4, K5, K6, IncludeFile[4]), Arch) + self.PcdToken[Record[3]] = (K2, K1) + + for Record in RecordSet: + if Record[1] == Arch or Record[1] == TAB_ARCH_COMMON.upper(): + (K1, K2, K3, K4, K5, K6) = GetDynamicDefaultPcd(Record[0], Type, ContainerFile, Record[2]) + MergeArches(Pcds, (K1, K2, K3, K4, K5, K6, Record[4]), Arch) + self.PcdToken[Record[3]] = (K2, K1) + + for Key in Pcds: + (Status, SkuInfoList) = self.GenSkuInfoList(Key[6], self.Platform.SkuInfos.SkuInfoList, '', '', '', '', '', Key[2]) + if Status == False: + ErrorMsg = "The SKUID '%s' used in section '%s' is not defined in section [SkuIds]" % (SkuInfoList, Type) + EdkLogger.error("DSC File Parser", PARSER_ERROR, ErrorMsg, ContainerFile, RaiseError = EdkLogger.IsRaiseError) + Pcd = PcdClass(Key[0], '', Key[1], Key[3], Key[4], Key[2], Key[5], [], SkuInfoList, []) + Pcd.SupArchList = Pcds[Key] + self.Platform.DynamicPcdBuildDefinitions.append(Pcd) + + ## Gen DynamicHiiPcds + # + # Gen DynamicHiiPcds of Dsc as .|||[|[|]] + # + # @param Type: The type of Pcd + # @param ContainerFile: The file which describes the pcd, used for error report + # + def GenDynamicHiiPcds(self, Type = '', ContainerFile = ''): + Pcds = {} + SkuInfoList = {} + if Type == DataType.TAB_PCDS_DYNAMIC_HII: + Model = MODEL_PCD_DYNAMIC_HII + elif Type == DataType.TAB_PCDS_DYNAMIC_EX_HII: + Model = MODEL_PCD_DYNAMIC_EX_HII + else: + pass + EdkLogger.debug(2, "Generate %s ..." % Type) + + # + # Get all include files + # + IncludeFiles = QueryDscItem(self.TblDsc, MODEL_META_DATA_INCLUDE, Model, self.FileID) + + # + # Get all DynamicHiiPcds + # + RecordSet = QueryDscItem(self.TblDsc, Model, -1, self.FileID) + + # + # Go through each arch + # + for Arch in DataType.ARCH_LIST: + for IncludeFile in IncludeFiles: + if IncludeFile[1] == Arch or IncludeFile[1] == TAB_ARCH_COMMON.upper(): + Filename = CheckFileExist(self.WorkspaceDir, IncludeFile[0], ContainerFile, Type, '', IncludeFile[2]) + for NewItem in open(Filename, 'r').readlines(): + if CleanString(NewItem) == '': + continue + (K1, K2, K3, K4, K5, K6, K7, K8) = GetDynamicHiiPcd(NewItem, Type, Filename, -1) + MergeArches(Pcds, (K1, K2, K3, K4, K5, K6, K7, K8, IncludeFile[4]), Arch) + self.PcdToken[Record[3]] = (K2, K1) + + for Record in RecordSet: + if Record[1] == Arch or Record[1] == TAB_ARCH_COMMON.upper(): + (K1, K2, K3, K4, K5, K6, K7, K8) = GetDynamicHiiPcd(Record[0], Type, ContainerFile, Record[2]) + MergeArches(Pcds, (K1, K2, K3, K4, K5, K6, K7, K8, Record[4]), Arch) + self.PcdToken[Record[3]] = (K2, K1) + + for Key in Pcds: + (Status, SkuInfoList) = self.GenSkuInfoList(Key[8], self.Platform.SkuInfos.SkuInfoList, Key[2], Key[3], Key[4], Key[5], '', '') + if Status == False: + ErrorMsg = "The SKUID '%s' used in section '%s' is not defined in section [SkuIds]" % (SkuInfoList, Type) + EdkLogger.error("DSC File Parser", PARSER_ERROR, ErrorMsg, ContainerFile, RaiseError = EdkLogger.IsRaiseError) + Pcd = PcdClass(Key[0], '', Key[1], '', Key[6], Key[5], Key[7], [], SkuInfoList, []) + Pcd.SupArchList = Pcds[Key] + self.Platform.DynamicPcdBuildDefinitions.append(Pcd) + + ## Gen DynamicVpdPcds + # + # Gen DynamicVpdPcds of Dsc as .|[|] + # + # @param Type: The type of Pcd + # @param ContainerFile: The file which describes the pcd, used for error report + # + def GenDynamicVpdPcds(self, Type = '', ContainerFile = ''): + Pcds = {} + SkuInfoList = {} + if Type == DataType.TAB_PCDS_DYNAMIC_VPD: + Model = MODEL_PCD_DYNAMIC_VPD + elif Type == DataType.TAB_PCDS_DYNAMIC_EX_VPD: + Model = MODEL_PCD_DYNAMIC_EX_VPD + else: + pass + EdkLogger.debug(2, "Generate %s ..." % Type) + + # + # Get all include files + # + IncludeFiles = QueryDscItem(self.TblDsc, MODEL_META_DATA_INCLUDE, Model, self.FileID) + + # + # Get all DynamicVpdPcds + # + RecordSet = QueryDscItem(self.TblDsc, Model, -1, self.FileID) + + # + # Go through each arch + # + for Arch in DataType.ARCH_LIST: + for IncludeFile in IncludeFiles: + if IncludeFile[1] == Arch or IncludeFile[1] == TAB_ARCH_COMMON.upper(): + Filename = CheckFileExist(self.WorkspaceDir, IncludeFile[0], ContainerFile, Type, '', IncludeFile[2]) + for NewItem in open(Filename, 'r').readlines(): + if CleanString(NewItem) == '': + continue + (K1, K2, K3, K4, K5) = GetDynamicVpdPcd(NewItem, Type, Filename, -1) + MergeArches(Pcds, (K1, K2, K3, K4, K5, IncludeFile[4]), Arch) + self.PcdToken[Record[3]] = (K2, K1) + + for Record in RecordSet: + if Record[1] == Arch or Record[1] == TAB_ARCH_COMMON.upper(): + (K1, K2, K3, K4, K5) = GetDynamicVpdPcd(Record[0], Type, ContainerFile, Record[2]) + MergeArches(Pcds, (K1, K2, K3, K4, K5, Record[4]), Arch) + self.PcdToken[Record[3]] = (K2, K1) + + for Key in Pcds: + (Status, SkuInfoList) = self.GenSkuInfoList(Key[5], self.Platform.SkuInfos.SkuInfoList, '', '', '', '', Key[2], '') + if Status == False: + ErrorMsg = "The SKUID '%s' used in section '%s' is not defined in section [SkuIds]" % (SkuInfoList, Type) + EdkLogger.error("DSC File Parser", PARSER_ERROR, ErrorMsg, ContainerFile, RaiseError = EdkLogger.IsRaiseError) + Pcd = PcdClass(Key[0], '', Key[1], '', Key[3], '', Key[4], [], SkuInfoList, []) + Pcd.SupArchList = Pcds[Key] + self.Platform.DynamicPcdBuildDefinitions.append(Pcd) + + + ## Get Component + # + # Get Component section defined in Dsc file + # + # @param ContainerFile: The file which describes the Components, used for error report + # + # @retval PlatformModuleClass() A instance for PlatformModuleClass + # + def GenComponents(self, ContainerFile): + EdkLogger.debug(2, "Generate %s ..." % TAB_COMPONENTS) + Components = sdict() + # + # Get all include files + # + IncludeFiles = QueryDscItem(self.TblDsc, MODEL_META_DATA_INCLUDE, MODEL_META_DATA_COMPONENT, self.FileID) + + # + # Get all Components + # + RecordSet = QueryDscItem(self.TblDsc, MODEL_META_DATA_COMPONENT, -1, self.FileID) + + # + # Go through each arch + # + for Arch in DataType.ARCH_LIST: + for IncludeFile in IncludeFiles: + if IncludeFile[1] == Arch or IncludeFile[1] == TAB_ARCH_COMMON.upper(): + Filename = CheckFileExist(self.WorkspaceDir, IncludeFile[0], ContainerFile, TAB_COMPONENTS, '', IncludeFile[2]) + for NewItem in open(Filename, 'r').readlines(): + if CleanString(NewItem) == '': + continue + NewItems = [] + GetComponents(open(Filename, 'r').read(), TAB_COMPONENTS, NewItems, TAB_COMMENT_SPLIT) + for NewComponent in NewItems: + MergeArches(Components, self.GenComponent(NewComponent, Filename), Arch) + + for Record in RecordSet: + if Record[1] == Arch or Record[1] == TAB_ARCH_COMMON.upper(): + Lib, Bo, Pcd = [], [], [] + + SubLibSet = QueryDscItem(self.TblDsc, MODEL_EFI_LIBRARY_CLASS, Record[3], self.FileID) + for SubLib in SubLibSet: + Lib.append(TAB_VALUE_SPLIT.join([SubLib[0],SubLib[4]])) + + SubBoSet = QueryDscItem(self.TblDsc, MODEL_META_DATA_BUILD_OPTION, Record[3], self.FileID) + for SubBo in SubBoSet: + Bo.append(SubBo[0]) + + SubPcdSet1 = QueryDscItem(self.TblDsc, MODEL_PCD_FIXED_AT_BUILD, Record[3], self.FileID) + SubPcdSet2 = QueryDscItem(self.TblDsc, MODEL_PCD_PATCHABLE_IN_MODULE, Record[3], self.FileID) + SubPcdSet3 = QueryDscItem(self.TblDsc, MODEL_PCD_FEATURE_FLAG, Record[3], self.FileID) + SubPcdSet4 = QueryDscItem(self.TblDsc, MODEL_PCD_DYNAMIC_EX_DEFAULT, Record[3], self.FileID) + SubPcdSet5 = QueryDscItem(self.TblDsc, MODEL_PCD_DYNAMIC_DEFAULT, Record[3], self.FileID) + for SubPcd in SubPcdSet1: + Pcd.append([DataType.TAB_PCDS_FIXED_AT_BUILD, SubPcd[0], SubPcd[3]]) + for SubPcd in SubPcdSet2: + Pcd.append([DataType.TAB_PCDS_PATCHABLE_IN_MODULE, SubPcd[0], SubPcd[3]]) + for SubPcd in SubPcdSet3: + Pcd.append([DataType.TAB_PCDS_FEATURE_FLAG, SubPcd[0], SubPcd[3]]) + for SubPcd in SubPcdSet4: + Pcd.append([DataType.TAB_PCDS_DYNAMIC_EX, SubPcd[0], SubPcd[3]]) + for SubPcd in SubPcdSet5: + Pcd.append([DataType.TAB_PCDS_DYNAMIC, SubPcd[0], SubPcd[3]]) + Item = [Record[0], Lib, Bo, Pcd] + MergeArches(Components, self.GenComponent(Item, ContainerFile), Arch) + + for Key in Components.keys(): + Key.SupArchList = Components[Key] + self.Platform.Modules.ModuleList.append(Key) + + ## Get Component + # + # Get Component section defined in Dsc file + # + # @param Item: Contents includes a component block + # @param ContainerFile: The file which describes the library class, used for error report + # + # @retval PlatformModuleClass() A instance for PlatformModuleClass + # + def GenComponent(self, Item, ContainerFile, LineNo = -1): + (InfFilename, ExecFilename) = GetExec(Item[0]) + LibraryClasses = Item[1] + BuildOptions = Item[2] + Pcds = Item[3] + Component = PlatformModuleClass() + Component.FilePath = NormPath(InfFilename) + Component.ExecFilePath = NormPath(ExecFilename) + CheckFileType(Component.FilePath, '.Inf', ContainerFile, 'component name', Item[0], LineNo) + CheckFileExist(self.WorkspaceDir, Component.FilePath, ContainerFile, 'component', Item[0], LineNo) + for Lib in LibraryClasses: + List = GetSplitValueList(Lib) + if len(List) != 2: + RaiseParserError(Lib, 'LibraryClasses', ContainerFile, '|') + LibName = List[0] + LibFile = NormPath(List[1]) + if LibName == "" or LibName == "NULL": + LibName = "NULL%d" % self._NullClassIndex + self._NullClassIndex += 1 + CheckFileType(List[1], '.Inf', ContainerFile, 'library instance of component ', Lib, LineNo) + CheckFileExist(self.WorkspaceDir, LibFile, ContainerFile, 'library instance of component', Lib, LineNo) + Component.LibraryClasses.LibraryList.append(PlatformLibraryClass(LibName, LibFile)) + for BuildOption in BuildOptions: + Key = GetBuildOption(BuildOption, ContainerFile) + Component.ModuleSaBuildOption.BuildOptionList.append(BuildOptionClass(Key[0], Key[1], Key[2])) + for Pcd in Pcds: + Type = Pcd[0] + List = GetSplitValueList(Pcd[1]) + PcdId = Pcd[2] + + TokenInfo = None + # + # For FeatureFlag + # + if Type == DataType.TAB_PCDS_FEATURE_FLAG: + if len(List) != 2: + RaiseParserError(Pcd[1], 'Components', ContainerFile, '.|TRUE/FALSE') + + CheckPcdTokenInfo(List[0], 'Components', ContainerFile) + TokenInfo = GetSplitValueList(List[0], DataType.TAB_SPLIT) + Component.PcdBuildDefinitions.append(PcdClass(TokenInfo[1], '', TokenInfo[0], '', '', List[1], Type, [], {}, [])) + # + # For FixedAtBuild or PatchableInModule + # + if Type == DataType.TAB_PCDS_FIXED_AT_BUILD or Type == DataType.TAB_PCDS_PATCHABLE_IN_MODULE: + List.append('') + if len(List) != 3 and len(List) != 4: + RaiseParserError(Pcd[1], 'Components', ContainerFile, '.|[|]') + + CheckPcdTokenInfo(List[0], 'Components', ContainerFile) + TokenInfo = GetSplitValueList(List[0], DataType.TAB_SPLIT) + Component.PcdBuildDefinitions.append(PcdClass(TokenInfo[1], '', TokenInfo[0], '', List[2], List[1], Type, [], {}, [])) + + # + # For Dynamic or DynamicEx + # + if Type == DataType.TAB_PCDS_DYNAMIC or Type == DataType.TAB_PCDS_DYNAMIC_EX: + if len(List) != 1: + RaiseParserError(Pcd[1], 'Components', ContainerFile, '.') + + CheckPcdTokenInfo(List[0], 'Components', ContainerFile) + TokenInfo = GetSplitValueList(List[0], DataType.TAB_SPLIT) + Component.PcdBuildDefinitions.append(PcdClass(TokenInfo[1], '', TokenInfo[0], '', '', '', Type, [], {}, [])) + + # + # Add to PcdToken + # + self.PcdToken[PcdId] = (TokenInfo[0], TokenInfo[1]) + + return Component + #End of GenComponent + + ## Gen SkuInfoList + # + # Gen SkuInfoList section defined in Dsc file + # + # @param SkuNameList: Input value for SkuNameList + # @param SkuInfo: Input value for SkuInfo + # @param VariableName: Input value for VariableName + # @param VariableGuid: Input value for VariableGuid + # @param VariableOffset: Input value for VariableOffset + # @param HiiDefaultValue: Input value for HiiDefaultValue + # @param VpdOffset: Input value for VpdOffset + # @param DefaultValue: Input value for DefaultValue + # + # @retval (False, SkuName) Not found in section SkuId Dsc file + # @retval (True, SkuInfoList) Found in section SkuId of Dsc file + # + def GenSkuInfoList(self, SkuNameList, SkuInfo, VariableName = '', VariableGuid = '', VariableOffset = '', HiiDefaultValue = '', VpdOffset = '', DefaultValue = ''): + SkuNameList = GetSplitValueList(SkuNameList) + if SkuNameList == None or SkuNameList == [] or SkuNameList == ['']: + SkuNameList = ['DEFAULT'] + SkuInfoList = {} + for Item in SkuNameList: + if Item not in SkuInfo: + return False, Item + Sku = SkuInfoClass(Item, SkuInfo[Item], VariableName, VariableGuid, VariableOffset, HiiDefaultValue, VpdOffset, DefaultValue) + SkuInfoList[Item] = Sku + + return True, SkuInfoList + + ## Parse Include statement + # + # Get include file path + # + # 1. Insert a record into TblFile ??? + # 2. Insert a record into TblDsc + # Value1: IncludeFilePath + # + # @param LineValue: The line of incude statement + def ParseInclude(self, LineValue, StartLine, Table, FileID, Filename, SectionName, Model, Arch): + EdkLogger.debug(EdkLogger.DEBUG_2, "!include statement '%s' found in section %s" % (LineValue, SectionName)) + SectionModel = Section[SectionName.upper()] + IncludeFile = CleanString(LineValue[LineValue.upper().find(DataType.TAB_INCLUDE.upper() + ' ') + len(DataType.TAB_INCLUDE + ' ') : ]) + Table.Insert(Model, IncludeFile, '', '', Arch, SectionModel, FileID, StartLine, -1, StartLine, -1, 0) + + ## Parse DEFINE statement + # + # Get DEFINE macros + # + # 1. Insert a record into TblDsc + # Value1: Macro Name + # Value2: Macro Value + # + def ParseDefine(self, LineValue, StartLine, Table, FileID, Filename, SectionName, Model, Arch): + EdkLogger.debug(EdkLogger.DEBUG_2, "DEFINE statement '%s' found in section %s" % (LineValue, SectionName)) + SectionModel = Section[SectionName.upper()] + Define = GetSplitValueList(CleanString(LineValue[LineValue.upper().find(DataType.TAB_DEFINE.upper() + ' ') + len(DataType.TAB_DEFINE + ' ') : ]), TAB_EQUAL_SPLIT, 1) + Table.Insert(Model, Define[0], Define[1], '', Arch, SectionModel, FileID, StartLine, -1, StartLine, -1, 0) + + ## Parse Defines section + # + # Get one item in defines section + # + # Value1: Item Name + # Value2: Item Value + # + def ParseDefinesSection(self, LineValue, StartLine, Table, FileID, Filename, SectionName, Model, Arch): + EdkLogger.debug(EdkLogger.DEBUG_2, "Parse '%s' found in section %s" % (LineValue, SectionName)) + Defines = GetSplitValueList(LineValue, TAB_EQUAL_SPLIT, 1) + if len(Defines) != 2: + RaiseParserError(LineValue, SectionName, Filename, '', StartLine) + self.TblDsc.Insert(Model, Defines[0], Defines[1], '', Arch, -1, FileID, StartLine, -1, StartLine, -1, 0) + + ## Insert conditional statements + # + # Pop an item from IfDefList + # Insert conditional statements to database + # + # @param Filename: Path of parsing file + # @param IfDefList: A list stored current conditional statements + # @param EndLine: The end line no + # @param ArchList: Support arch list + # + def InsertConditionalStatement(self, Filename, FileID, BelongsToItem, IfDefList, EndLine, ArchList): + (Value1, Value2, Value3, Model, StartColumn, EndColumn, Enabled) = ('', '', '', -1, -1, -1, 0) + if IfDefList == []: + ErrorMsg = 'Not suited conditional statement in file %s' % Filename + EdkLogger.error("DSC File Parser", PARSER_ERROR, ErrorMsg, Filename, RaiseError = EdkLogger.IsRaiseError) + else: + # + # Get New Dsc item ID + # + DscID = self.TblDsc.GetCount() + 1 + + # + # Pop the conditional statements which is closed + # + PreviousIf = IfDefList.pop() + EdkLogger.debug(EdkLogger.DEBUG_5, 'Previous IfDef: ' + str(PreviousIf)) + + # + # !ifdef and !ifndef + # + if PreviousIf[2] in (MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF, MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF): + Value1 = PreviousIf[0] + Model = PreviousIf[2] + self.TblDsc.Insert(Model, Value1, Value2, Value3, ArchList, BelongsToItem, self.FileID, PreviousIf[1], StartColumn, EndLine, EndColumn, Enabled) + # + # !if and !elseif + # + elif PreviousIf[2] in (MODEL_META_DATA_CONDITIONAL_STATEMENT_IF, Model): + List = PreviousIf[0].split(' ') + Value1 = List[0] + Value2 = List[1] + Value3 = List[2] + Value3 = SplitString(Value3) + Model = PreviousIf[2] + self.TblDsc.Insert(Model, Value1, Value2, Value3, ArchList, BelongsToItem, self.FileID, PreviousIf[1], StartColumn, EndLine, EndColumn, Enabled) + # + # !else + # + elif PreviousIf[2] in (MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE, Model): + Value1 = PreviousIf[0].strip() + Model = PreviousIf[2] + self.TblDsc.Insert(Model, Value1, Value2, Value3, ArchList, BelongsToItem, self.FileID, PreviousIf[1], StartColumn, EndLine, EndColumn, Enabled) + + ## Load Dsc file + # + # Load the file if it exists + # + # @param Filename: Input value for filename of Dsc file + # + def LoadDscFile(self, Filename): + # + # Insert a record for file + # + Filename = NormPath(Filename) + self.Identification.FileFullPath = Filename + (self.Identification.FileRelativePath, self.Identification.FileName) = os.path.split(Filename) + self.FileID = self.TblFile.InsertFile(Filename, MODEL_FILE_DSC) + + # + # Init DscTable + # + #self.TblDsc.Table = "Dsc%s" % FileID + #self.TblDsc.Create() + + # + # Init common datas + # + IfDefList, SectionItemList, CurrentSection, ArchList, ThirdList, IncludeFiles = \ + [], [], TAB_UNKNOWN, [], [], [] + LineNo = 0 + + # + # Parse file content + # + IsFindBlockComment = False + ReservedLine = '' + for Line in open(Filename, 'r'): + LineNo = LineNo + 1 + # + # Remove comment block + # + if Line.find(TAB_COMMENT_R8_START) > -1: + ReservedLine = GetSplitValueList(Line, TAB_COMMENT_R8_START, 1)[0] + IsFindBlockComment = True + if Line.find(TAB_COMMENT_R8_END) > -1: + Line = ReservedLine + GetSplitValueList(Line, TAB_COMMENT_R8_END, 1)[1] + ReservedLine = '' + IsFindBlockComment = False + if IsFindBlockComment: + continue + + # + # Remove comments at tail and remove spaces again + # + Line = CleanString(Line) + if Line == '': + continue + + # + # Find a new section tab + # First insert previous section items + # And then parse the content of the new section + # + if Line.startswith(TAB_SECTION_START) and Line.endswith(TAB_SECTION_END): + # + # Insert items data of previous section + # + self.InsertSectionItemsIntoDatabase(self.FileID, Filename, CurrentSection, SectionItemList, ArchList, ThirdList, IfDefList) + # + # Parse the new section + # + SectionItemList = [] + ArchList = [] + ThirdList = [] + + CurrentSection = '' + LineList = GetSplitValueList(Line[len(TAB_SECTION_START):len(Line) - len(TAB_SECTION_END)], TAB_COMMA_SPLIT) + for Item in LineList: + ItemList = GetSplitValueList(Item, TAB_SPLIT) + if CurrentSection == '': + CurrentSection = ItemList[0] + else: + if CurrentSection != ItemList[0]: + EdkLogger.error("Parser", PARSER_ERROR, "Different section names '%s' and '%s' are found in one section definition, this is not allowed." % (CurrentSection, ItemList[0]), File=Filename, Line=LineNo, RaiseError = EdkLogger.IsRaiseError) + if CurrentSection.upper() not in self.KeyList: + RaiseParserError(Line, CurrentSection, Filename, '', LineNo) + CurrentSection = TAB_UNKNOWN + continue + ItemList.append('') + ItemList.append('') + if len(ItemList) > 5: + RaiseParserError(Line, CurrentSection, Filename, '', LineNo) + else: + if ItemList[1] != '' and ItemList[1].upper() not in ARCH_LIST_FULL: + EdkLogger.error("Parser", PARSER_ERROR, "Invalid Arch definition '%s' found" % ItemList[1], File=Filename, Line=LineNo, RaiseError = EdkLogger.IsRaiseError) + ArchList.append(ItemList[1].upper()) + ThirdList.append(ItemList[2]) + + continue + + # + # Not in any defined section + # + if CurrentSection == TAB_UNKNOWN: + ErrorMsg = "%s is not in any defined section" % Line + EdkLogger.error("Parser", PARSER_ERROR, ErrorMsg, File=Filename, Line=LineNo, RaiseError = EdkLogger.IsRaiseError) + + # + # Add a section item + # + SectionItemList.append([Line, LineNo]) + # End of parse + #End of For + + # + # Insert items data of last section + # + self.InsertSectionItemsIntoDatabase(self.FileID, Filename, CurrentSection, SectionItemList, ArchList, ThirdList, IfDefList) + + # + # Parse conditional statements + # + self.ParseConditionalStatement() + + # + # Replace all DEFINE macros with its actual values + # + #ParseDefineMacro2(self.TblDsc, self.RecordSet, GlobalData.gGlobalDefines) + ParseDefineMacro(self.TblDsc, GlobalData.gGlobalDefines) + + + ## ParseConditionalStatement + # + # Search all conditional statement and disable no match records + # + def ParseConditionalStatement(self): + # + # Disabled all !if/!elif/!ifdef statements without DEFINE + # + SqlCommand = """select A.StartLine, A.EndLine from %s as A + where A.Model in (%s, %s, %s) + and A.Enabled = 0 + and A.BelongsToFile = %s + and A.Value1 not in (select B.Value1 from %s as B + where B.Model = %s + and B.Enabled = 0 + and A.StartLine > B.StartLine + and A.Arch = B.Arch + and A.BelongsToItem = B.BelongsToItem + and A.BelongsToFile = B.BelongsToFile) """ % \ + (self.TblDsc.Table, \ + MODEL_META_DATA_CONDITIONAL_STATEMENT_IF, MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE, MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF, \ + self.FileID, \ + self.TblDsc.Table, \ + MODEL_META_DATA_DEFINE) + RecordSet = self.TblDsc.Exec(SqlCommand) + for Record in RecordSet: + SqlCommand = """Update %s set Enabled = -1 where StartLine >= %s and EndLine <= %s""" %(self.TblDsc.Table, Record[0], Record[1]) + self.TblDsc.Exec(SqlCommand) + + # + # Disabled !ifndef with DEFINE + # + SqlCommand = """select A.StartLine, A.EndLine from %s as A + where A.Model = %s + and A.Enabled = 0 + and A.BelongsToFile = %s + and A.Value1 in (select B.Value1 from %s as B + where B.Model = %s + and B.Enabled = 0 + and A.StartLine > B.StartLine + and A.Arch = B.Arch + and A.BelongsToItem = B.BelongsToItem + and A.BelongsToFile = B.BelongsToFile)""" % \ + (self.TblDsc.Table, \ + MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF, \ + self.FileID, \ + self.TblDsc.Table, \ + MODEL_META_DATA_DEFINE) + RecordSet = self.TblDsc.Exec(SqlCommand) + for Record in RecordSet: + SqlCommand = """Update %s set Enabled = -1 where StartLine >= %s and EndLine <= %s""" %(self.TblDsc.Table, Record[0], Record[1]) + EdkLogger.debug(4, "SqlCommand: %s" %SqlCommand) + self.Cur.execute(SqlCommand) + + # + # Disabled !if, !elif and !else with un-match value + # + SqlCommand = """select A.Model, A.Value1, A.Value2, A.Value3, A.StartLine, A.EndLine, B.Value2 from %s as A join %s as B + where A.Model in (%s, %s) + and A.Enabled = 0 + and A.BelongsToFile = %s + and B.Enabled = 0 + and B.Model = %s + and A.Value1 = B.Value1 + and A.StartLine > B.StartLine + and A.BelongsToItem = B.BelongsToItem + and A.BelongsToFile = B.BelongsToFile""" % \ + (self.TblDsc.Table, self.TblDsc.Table, \ + MODEL_META_DATA_CONDITIONAL_STATEMENT_IF, MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE, \ + self.FileID, MODEL_META_DATA_DEFINE) + RecordSet = self.TblDsc.Exec(SqlCommand) + DisabledList = [] + for Record in RecordSet: + if Record[0] == MODEL_META_DATA_CONDITIONAL_STATEMENT_IF: + if not self.Compare(Record[6], Record[2], Record[3]): + SqlCommand = """Update %s set Enabled = -1 where StartLine >= %s and EndLine <= %s""" %(self.TblDsc.Table, Record[4], Record[5]) + self.TblDsc.Exec(SqlCommand) + else: + DisabledList.append(Record[1]) + continue + if Record[0] == MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE and Record[1] in DisabledList: + SqlCommand = """Update %s set Enabled = -1 where StartLine >= %s and EndLine <= %s""" %(self.TblDsc.Table, Record[4], Record[5]) + self.TblDsc.Exec(SqlCommand) + + ## Compare + # + # Compare two values + # @param Value1: + # @param CompareType: + # @param Value2: + # + def Compare(self, Value1, CompareType, Value2): + Command = """Value1 %s Value2""" %CompareType + return eval(Command) + + ## First time to insert records to database + # + # Insert item data of a section to database + # @param FileID: The ID of belonging file + # @param Filename: The name of belonging file + # @param CurrentSection: The name of currect section + # @param SectionItemList: A list of items of the section + # @param ArchList: A list of arches + # @param ThirdList: A list of third parameters, ModuleType for LibraryClass and SkuId for Dynamic Pcds + # @param IfDefList: A list of all conditional statements + # + def InsertSectionItemsIntoDatabase(self, FileID, Filename, CurrentSection, SectionItemList, ArchList, ThirdList, IfDefList): + # + # Insert each item data of a section + # + for Index in range(0, len(ArchList)): + Arch = ArchList[Index] + Third = ThirdList[Index] + if Arch == '': + Arch = TAB_ARCH_COMMON.upper() + + Model = Section[CurrentSection.upper()] + #Records = self.RecordSet[Model] + + for SectionItem in SectionItemList: + BelongsToItem, EndLine, EndColumn = -1, -1, -1 + LineValue, StartLine, EndLine = SectionItem[0], SectionItem[1], SectionItem[1] + + + EdkLogger.debug(4, "Parsing %s ..." %LineValue) + # + # Parse '!ifdef' + # + if LineValue.upper().find(TAB_IF_DEF.upper()) > -1: + IfDefList.append((LineValue[len(TAB_IF_N_DEF):].strip(), StartLine, MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF)) + continue + + # + # Parse '!ifndef' + # + if LineValue.upper().find(TAB_IF_N_DEF.upper()) > -1: + IfDefList.append((LineValue[len(TAB_IF_N_DEF):].strip(), StartLine, MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF)) + continue + + # + # Parse '!endif' + # + if LineValue.upper().find(TAB_END_IF.upper()) > -1: + self.InsertConditionalStatement(Filename, FileID, Model, IfDefList, StartLine, Arch) + continue + # + # Parse '!if' + # + if LineValue.upper().find(TAB_IF.upper()) > -1: + IfDefList.append((LineValue[len(TAB_IF):].strip(), StartLine, MODEL_META_DATA_CONDITIONAL_STATEMENT_IF)) + continue + + # + # Parse '!elseif' + # + if LineValue.upper().find(TAB_ELSE_IF.upper()) > -1: + self.InsertConditionalStatement(Filename, FileID, Model, IfDefList, StartLine - 1, Arch) + IfDefList.append((LineValue[len(TAB_ELSE_IF):].strip(), StartLine, MODEL_META_DATA_CONDITIONAL_STATEMENT_IF)) + continue + + # + # Parse '!else' + # + if LineValue.upper().find(TAB_ELSE.upper()) > -1: + Key = IfDefList[-1][0].split(' ' , 1)[0].strip() + self.InsertConditionalStatement(Filename, FileID, Model, IfDefList, StartLine, Arch) + IfDefList.append((Key, StartLine, MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE)) + continue + + # + # Parse !include statement first + # + if LineValue.upper().find(DataType.TAB_INCLUDE.upper() + ' ') > -1: + self.ParseInclude(LineValue, StartLine, self.TblDsc, FileID, Filename, CurrentSection, MODEL_META_DATA_INCLUDE, Arch) + continue + + # + # And then parse DEFINE statement + # + if LineValue.upper().find(DataType.TAB_DEFINE.upper() + ' ') > -1: + self.ParseDefine(LineValue, StartLine, self.TblDsc, FileID, Filename, CurrentSection, MODEL_META_DATA_DEFINE, Arch) + continue + + # + # At last parse other sections + # + if CurrentSection == TAB_LIBRARY_CLASSES or CurrentSection in TAB_PCD_DYNAMIC_TYPE_LIST or CurrentSection in TAB_PCD_DYNAMIC_EX_TYPE_LIST: + ID = self.TblDsc.Insert(Model, LineValue, Third, '', Arch, -1, FileID, StartLine, -1, StartLine, -1, 0) + #Records.append([LineValue, Arch, StartLine, ID, Third]) + continue + elif CurrentSection != TAB_COMPONENTS: + ID = self.TblDsc.Insert(Model, LineValue, '', '', Arch, -1, FileID, StartLine, -1, StartLine, -1, 0) + #Records.append([LineValue, Arch, StartLine, ID, Third]) + continue + + # + # Parse COMPONENT section + # + if CurrentSection == TAB_COMPONENTS: + Components = [] + GetComponent(SectionItemList, Components) + for Component in Components: + EdkLogger.debug(4, "Parsing component %s ..." %Component) + DscItmeID = self.TblDsc.Insert(MODEL_META_DATA_COMPONENT, Component[0], '', '', Arch, -1, FileID, StartLine, -1, StartLine, -1, 0) + for Item in Component[1]: + List = GetSplitValueList(Item, MaxSplit = 2) + LibName, LibIns = '', '' + if len(List) == 2: + LibName = List[0] + LibIns = List[1] + else: + LibName = List[0] + self.TblDsc.Insert(MODEL_EFI_LIBRARY_CLASS, LibName, LibIns, '', Arch, DscItmeID, FileID, StartLine, -1, StartLine, -1, 0) + for Item in Component[2]: + self.TblDsc.Insert(MODEL_META_DATA_BUILD_OPTION, Item, '', '', Arch, DscItmeID, FileID, StartLine, -1, StartLine, -1, 0) + for Item in Component[3]: + Model = Section[Item[0].upper()] + self.TblDsc.Insert(Model, Item[1], '', '', Arch, DscItmeID, FileID, StartLine, -1, StartLine, -1, 0) + + ## Show detailed information of Dsc + # + # Print all members and their values of Dsc class + # + def ShowDsc(self): + print TAB_SECTION_START + TAB_INF_DEFINES + TAB_SECTION_END + printDict(self.Defines.DefinesDictionary) + + for Key in self.KeyList: + for Arch in DataType.ARCH_LIST_FULL: + Command = "printList(TAB_SECTION_START + '" + \ + Key + DataType.TAB_SPLIT + Arch + \ + "' + TAB_SECTION_END, self.Contents[arch]." + Key + ')' + eval(Command) + + ## Show detailed information of Platform + # + # Print all members and their values of Platform class + # + def ShowPlatform(self): + M = self.Platform + for Arch in M.Header.keys(): + print '\nArch =', Arch + print 'Filename =', M.Header[Arch].FileName + print 'FullPath =', M.Header[Arch].FullPath + print 'BaseName =', M.Header[Arch].Name + print 'Guid =', M.Header[Arch].Guid + print 'Version =', M.Header[Arch].Version + print 'DscSpecification =', M.Header[Arch].DscSpecification + print 'SkuId =', M.Header[Arch].SkuIdName + print 'SupArchList =', M.Header[Arch].SupArchList + print 'BuildTargets =', M.Header[Arch].BuildTargets + print 'OutputDirectory =', M.Header[Arch].OutputDirectory + print 'BuildNumber =', M.Header[Arch].BuildNumber + print 'MakefileName =', M.Header[Arch].MakefileName + print 'BsBaseAddress =', M.Header[Arch].BsBaseAddress + print 'RtBaseAddress =', M.Header[Arch].RtBaseAddress + print 'Define =', M.Header[Arch].Define + print 'Fdf =', M.FlashDefinitionFile.FilePath + print '\nBuildOptions =', M.BuildOptions, M.BuildOptions.IncludeFiles + for Item in M.BuildOptions.BuildOptionList: + print '\t', 'ToolChainFamily =', Item.ToolChainFamily, 'ToolChain =', Item.ToolChain, 'Option =', Item.Option, 'Arch =', Item.SupArchList + print '\nSkuIds =', M.SkuInfos.SkuInfoList, M.SkuInfos.IncludeFiles + print '\nLibraries =', M.Libraries, M.Libraries.IncludeFiles + for Item in M.Libraries.LibraryList: + print '\t', Item.FilePath, Item.SupArchList, Item.Define + print '\nLibraryClasses =', M.LibraryClasses, M.LibraryClasses.IncludeFiles + for Item in M.LibraryClasses.LibraryList: + print '\t', Item.Name, Item.FilePath, Item.SupModuleList, Item.SupArchList, Item.Define + print '\nPcds =', M.DynamicPcdBuildDefinitions + for Item in M.DynamicPcdBuildDefinitions: + print '\tCname=', Item.CName, 'TSG=', Item.TokenSpaceGuidCName, 'Value=', Item.DefaultValue, 'Token=', Item.Token, 'Type=', Item.ItemType, 'Datum=', Item.DatumType, 'Size=', Item.MaxDatumSize, 'Arch=', Item.SupArchList, Item.SkuInfoList + for Sku in Item.SkuInfoList.values(): + print '\t\t', str(Sku) + print '\nComponents =', M.Modules.ModuleList, M.Modules.IncludeFiles + for Item in M.Modules.ModuleList: + print '\t', Item.FilePath, Item.ExecFilePath, Item.SupArchList + for Lib in Item.LibraryClasses.LibraryList: + print '\t\tLib:', Lib.Name, Lib.FilePath + for Bo in Item.ModuleSaBuildOption.BuildOptionList: + print '\t\tBuildOption:', Bo.ToolChainFamily, Bo.ToolChain, Bo.Option + for Pcd in Item.PcdBuildDefinitions: + print '\t\tPcd:', Pcd.CName, Pcd.TokenSpaceGuidCName, Pcd.MaxDatumSize, Pcd.DefaultValue, Pcd.ItemType + +## +# +# This acts like the main() function for the script, unless it is 'import'ed into another +# script. +# +if __name__ == '__main__': + EdkLogger.Initialize() + EdkLogger.SetLevel(EdkLogger.DEBUG_0) + + W = os.getenv('WORKSPACE') + F = os.path.join(W, 'Nt32Pkg/Nt32Pkg.dsc') + + Db = Database.Database('Dsc.db') + Db.InitDatabase() + + P = Dsc(os.path.normpath(F), True, True, W, Db) + P.ShowPlatform() + + Db.Close() diff --git a/BaseTools/Source/Python/Common/EdkIIWorkspace.py b/BaseTools/Source/Python/Common/EdkIIWorkspace.py new file mode 100644 index 0000000000..a494e814a6 --- /dev/null +++ b/BaseTools/Source/Python/Common/EdkIIWorkspace.py @@ -0,0 +1,318 @@ +## @file +# This is the base class for applications that operate on an EDK II Workspace +# +# Copyright (c) 2007, 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. +# + +## +# Import Modules +# +import os, sys, time +from DataType import * + +## EdkIIWorkspace +# +# Collect WorkspaceDir from the environment, the Verbose command line flag, and detect an icon bitmap file. +# +# @var StartTime: Time of build system starting +# @var PrintRunTime: Printable time of build system running +# @var PrintRunStatus: Printable status of build system running +# @var RunStatus: Status of build system running +# +class EdkIIWorkspace: + def __init__(self): + self.StartTime = time.time() + self.PrintRunTime = False + self.PrintRunStatus = False + self.RunStatus = '' + + # + # Check environment valiable 'WORKSPACE' + # + if os.environ.get('WORKSPACE') == None: + print 'ERROR: WORKSPACE not defined. Please run EdkSetup from the EDK II install directory.' + return False + + self.CurrentWorkingDir = os.getcwd() + + self.WorkspaceDir = os.path.realpath(os.environ.get('WORKSPACE')) + (Drive, Path) = os.path.splitdrive(self.WorkspaceDir) + if Drive == '': + (Drive, CwdPath) = os.path.splitdrive(self.CurrentWorkingDir) + if Drive != '': + self.WorkspaceDir = Drive + Path + else: + self.WorkspaceDir = Drive.upper() + Path + + self.WorkspaceRelativeWorkingDir = self.WorkspaceRelativePath (self.CurrentWorkingDir) + + try: + # + # Load TianoCoreOrgLogo, used for GUI tool + # + self.Icon = wx.Icon(self.WorkspaceFile('tools/Python/TianoCoreOrgLogo.gif'),wx.BITMAP_TYPE_GIF) + except: + self.Icon = None + + self.Verbose = False + for Arg in sys.argv: + if Arg.lower() == '-v': + self.Verbose = True + + ## Close build system + # + # Close build system and print running time and status + # + def Close(self): + if self.PrintRunTime: + Seconds = int(time.time() - self.StartTime) + if Seconds < 60: + print 'Run Time: %d seconds' % (Seconds) + else: + Minutes = Seconds / 60 + Seconds = Seconds % 60 + if Minutes < 60: + print 'Run Time: %d minutes %d seconds' % (Minutes, Seconds) + else: + Hours = Minutes / 60 + Minutes = Minutes % 60 + print 'Run Time: %d hours %d minutes %d seconds' % (Hours, Minutes, Seconds) + if self.RunStatus != '': + print self.RunStatus + + ## Convert to a workspace relative filename + # + # Convert a full path filename to a workspace relative filename. + # + # @param FileName: The filename to be Converted + # + # @retval None Workspace dir is not found in the full path + # @retval string The relative filename + # + def WorkspaceRelativePath(self, FileName): + FileName = os.path.realpath(FileName) + if FileName.find(self.WorkspaceDir) != 0: + return None + return FileName.replace (self.WorkspaceDir, '').strip('\\').strip('/') + + ## Convert to a full path filename + # + # Convert a workspace relative filename to a full path filename. + # + # @param FileName: The filename to be Converted + # + # @retval string The full path filename + # + def WorkspaceFile(self, FileName): + return os.path.realpath(os.path.join(self.WorkspaceDir,FileName)) + + ## Convert to a real path filename + # + # Convert ${WORKSPACE} to real path + # + # @param FileName: The filename to be Converted + # + # @retval string The full path filename + # + def WorkspacePathConvert(self, FileName): + return os.path.realpath(FileName.replace(TAB_WORKSPACE, self.WorkspaceDir)) + + ## Convert XML into a DOM + # + # Parse an XML file into a DOM and return the DOM. + # + # @param FileName: The filename to be parsed + # + # @retval XmlParseFile (self.WorkspaceFile(FileName)) + # + def XmlParseFile (self, FileName): + if self.Verbose: + print FileName + return XmlParseFile (self.WorkspaceFile(FileName)) + + ## Convert a XML section + # + # Parse a section of an XML file into a DOM(Document Object Model) and return the DOM. + # + # @param FileName: The filename to be parsed + # @param SectionTag: The tag name of the section to be parsed + # + # @retval XmlParseFileSection (self.WorkspaceFile(FileName), SectionTag) + # + def XmlParseFileSection (self, FileName, SectionTag): + if self.Verbose: + print FileName + return XmlParseFileSection (self.WorkspaceFile(FileName), SectionTag) + + ## Save a XML file + # + # Save a DOM(Document Object Model) into an XML file. + # + # @param Dom: The Dom to be saved + # @param FileName: The filename + # + # @retval XmlSaveFile (Dom, self.WorkspaceFile(FileName)) + # + def XmlSaveFile (self, Dom, FileName): + if self.Verbose: + print FileName + return XmlSaveFile (Dom, self.WorkspaceFile(FileName)) + + ## Convert Text File To Dictionary + # + # Convert a workspace relative text file to a dictionary of (name:value) pairs. + # + # @param FileName: Text filename + # @param Dictionary: Dictionary to store data + # @param CommentCharacter: Comment char, be used to ignore comment content + # @param KeySplitCharacter: Key split char, between key name and key value. Key1 = Value1, '=' is the key split char + # @param ValueSplitFlag: Value split flag, be used to decide if has multiple values + # @param ValueSplitCharacter: Value split char, be used to split multiple values. Key1 = Value1|Value2, '|' is the value split char + # + # @retval ConvertTextFileToDictionary(self.WorkspaceFile(FileName), Dictionary, CommentCharacter, KeySplitCharacter, ValueSplitFlag, ValueSplitCharacter) + # + def ConvertTextFileToDictionary(self, FileName, Dictionary, CommentCharacter, KeySplitCharacter, ValueSplitFlag, ValueSplitCharacter): + if self.Verbose: + print FileName + return ConvertTextFileToDictionary(self.WorkspaceFile(FileName), Dictionary, CommentCharacter, KeySplitCharacter, ValueSplitFlag, ValueSplitCharacter) + + ## Convert Dictionary To Text File + # + # Convert a dictionary of (name:value) pairs to a workspace relative text file. + # + # @param FileName: Text filename + # @param Dictionary: Dictionary to store data + # @param CommentCharacter: Comment char, be used to ignore comment content + # @param KeySplitCharacter: Key split char, between key name and key value. Key1 = Value1, '=' is the key split char + # @param ValueSplitFlag: Value split flag, be used to decide if has multiple values + # @param ValueSplitCharacter: Value split char, be used to split multiple values. Key1 = Value1|Value2, '|' is the value split char + # + # @retval ConvertDictionaryToTextFile(self.WorkspaceFile(FileName), Dictionary, CommentCharacter, KeySplitCharacter, ValueSplitFlag, ValueSplitCharacter) + # + def ConvertDictionaryToTextFile(self, FileName, Dictionary, CommentCharacter, KeySplitCharacter, ValueSplitFlag, ValueSplitCharacter): + if self.Verbose: + print FileName + return ConvertDictionaryToTextFile(self.WorkspaceFile(FileName), Dictionary, CommentCharacter, KeySplitCharacter, ValueSplitFlag, ValueSplitCharacter) + +## Convert Text File To Dictionary +# +# Convert a text file to a dictionary of (name:value) pairs. +# +# @param FileName: Text filename +# @param Dictionary: Dictionary to store data +# @param CommentCharacter: Comment char, be used to ignore comment content +# @param KeySplitCharacter: Key split char, between key name and key value. Key1 = Value1, '=' is the key split char +# @param ValueSplitFlag: Value split flag, be used to decide if has multiple values +# @param ValueSplitCharacter: Value split char, be used to split multiple values. Key1 = Value1|Value2, '|' is the value split char +# +# @retval True Convert successfully +# @retval False Open file failed +# +def ConvertTextFileToDictionary(FileName, Dictionary, CommentCharacter, KeySplitCharacter, ValueSplitFlag, ValueSplitCharacter): + try: + F = open(FileName,'r') + except: + return False + Keys = [] + for Line in F: + LineList = Line.split(KeySplitCharacter,1) + if len(LineList) >= 2: + Key = LineList[0].split() + if len(Key) == 1 and Key[0][0] != CommentCharacter and Key[0] not in Keys: + if ValueSplitFlag: + Dictionary[Key[0]] = LineList[1].replace('\\','/').split(ValueSplitCharacter) + else: + Dictionary[Key[0]] = LineList[1].strip().replace('\\','/') + Keys += [Key[0]] + F.close() + return True + +## Convert Dictionary To Text File +# +# Convert a dictionary of (name:value) pairs to a text file. +# +# @param FileName: Text filename +# @param Dictionary: Dictionary to store data +# @param CommentCharacter: Comment char, be used to ignore comment content +# @param KeySplitCharacter: Key split char, between key name and key value. Key1 = Value1, '=' is the key split char +# @param ValueSplitFlag: Value split flag, be used to decide if has multiple values +# @param ValueSplitCharacter: Value split char, be used to split multiple values. Key1 = Value1|Value2, '|' is the value split char +# +# @retval True Convert successfully +# @retval False Open file failed +# +def ConvertDictionaryToTextFile(FileName, Dictionary, CommentCharacter, KeySplitCharacter, ValueSplitFlag, ValueSplitCharacter): + try: + F = open(FileName,'r') + Lines = [] + Lines = F.readlines() + F.close() + except: + Lines = [] + Keys = Dictionary.keys() + MaxLength = 0 + for Key in Keys: + if len(Key) > MaxLength: + MaxLength = len(Key) + Index = 0 + for Line in Lines: + LineList = Line.split(KeySplitCharacter,1) + if len(LineList) >= 2: + Key = LineList[0].split() + if len(Key) == 1 and Key[0][0] != CommentCharacter and Key[0] in Dictionary: + if ValueSplitFlag: + Line = '%-*s %c %s\n' % (MaxLength, Key[0], KeySplitCharacter, ' '.join(Dictionary[Key[0]])) + else: + Line = '%-*s %c %s\n' % (MaxLength, Key[0], KeySplitCharacter, Dictionary[Key[0]]) + Lines.pop(Index) + if Key[0] in Keys: + Lines.insert(Index,Line) + Keys.remove(Key[0]) + Index += 1 + for RemainingKey in Keys: + if ValueSplitFlag: + Line = '%-*s %c %s\n' % (MaxLength, RemainingKey, KeySplitCharacter,' '.join(Dictionary[RemainingKey])) + else: + Line = '%-*s %c %s\n' % (MaxLength, RemainingKey, KeySplitCharacter, Dictionary[RemainingKey]) + Lines.append(Line) + try: + F = open(FileName,'w') + except: + return False + F.writelines(Lines) + F.close() + return True + +## Create a new directory +# +# @param Directory: Directory to be created +# +def CreateDirectory(Directory): + if not os.access(Directory, os.F_OK): + os.makedirs (Directory) + +## Create a new file +# +# @param Directory: Directory to be created +# @param FileName: Filename to be created +# @param Mode: The mode of open file, defautl is 'w' +# +def CreateFile(Directory, FileName, Mode='w'): + CreateDirectory (Directory) + return open(os.path.join(Directory, FileName), Mode) + +## +# +# This acts like the main() function for the script, unless it is 'import'ed into another +# script. +# +if __name__ == '__main__': + # Nothing to do here. Could do some unit tests + pass \ No newline at end of file diff --git a/BaseTools/Source/Python/Common/EdkIIWorkspaceBuild.py b/BaseTools/Source/Python/Common/EdkIIWorkspaceBuild.py new file mode 100644 index 0000000000..82ab1796ad --- /dev/null +++ b/BaseTools/Source/Python/Common/EdkIIWorkspaceBuild.py @@ -0,0 +1,1669 @@ +## @file +# This file is used to define each component of the build database +# +# Copyright (c) 2007 ~ 2008, 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. +# + +## +# Import Modules +# +import os, string, copy, pdb, copy +import EdkLogger +import DataType +from InfClassObject import * +from DecClassObject import * +from DscClassObject import * +from String import * +from BuildToolError import * +from Misc import sdict +import Database as Database +import time as time + +## PcdClassObject +# +# This Class is used for PcdObject +# +# @param object: Inherited from object class +# @param Name: Input value for Name of Pcd, default is None +# @param Guid: Input value for Guid of Pcd, default is None +# @param Type: Input value for Type of Pcd, default is None +# @param DatumType: Input value for DatumType of Pcd, default is None +# @param Value: Input value for Value of Pcd, default is None +# @param Token: Input value for Token of Pcd, default is None +# @param MaxDatumSize: Input value for MaxDatumSize of Pcd, default is None +# @param SkuInfoList: Input value for SkuInfoList of Pcd, default is {} +# @param IsOverrided: Input value for IsOverrided of Pcd, default is False +# +# @var TokenCName: To store value for TokenCName +# @var TokenSpaceGuidCName: To store value for TokenSpaceGuidCName +# @var Type: To store value for Type +# @var DatumType: To store value for DatumType +# @var TokenValue: To store value for TokenValue +# @var MaxDatumSize: To store value for MaxDatumSize +# @var SkuInfoList: To store value for SkuInfoList +# @var IsOverrided: To store value for IsOverrided +# @var Phase: To store value for Phase, default is "DXE" +# +class PcdClassObject(object): + def __init__(self, Name = None, Guid = None, Type = None, DatumType = None, Value = None, Token = None, MaxDatumSize = None, SkuInfoList = {}, IsOverrided = False): + self.TokenCName = Name + self.TokenSpaceGuidCName = Guid + self.Type = Type + self.DatumType = DatumType + self.DefaultValue = Value + self.TokenValue = Token + self.MaxDatumSize = MaxDatumSize + self.SkuInfoList = SkuInfoList + self.IsOverrided = IsOverrided + self.Phase = "DXE" + + ## Convert the class to a string + # + # Convert each member of the class to string + # Organize to a signle line format string + # + # @retval Rtn Formatted String + # + def __str__(self): + Rtn = '\tTokenCName=' + str(self.TokenCName) + ', ' + \ + 'TokenSpaceGuidCName=' + str(self.TokenSpaceGuidCName) + ', ' + \ + 'Type=' + str(self.Type) + ', ' + \ + 'DatumType=' + str(self.DatumType) + ', ' + \ + 'DefaultValue=' + str(self.DefaultValue) + ', ' + \ + 'TokenValue=' + str(self.TokenValue) + ', ' + \ + 'MaxDatumSize=' + str(self.MaxDatumSize) + ', ' + for Item in self.SkuInfoList.values(): + Rtn = Rtn + 'SkuId=' + Item.SkuId + ', ' + 'SkuIdName=' + Item.SkuIdName + Rtn = Rtn + str(self.IsOverrided) + + return Rtn + + ## Override __eq__ function + # + # Check whether pcds are the same + # + # @retval False The two pcds are different + # @retval True The two pcds are the same + # + def __eq__(self, Other): + return Other != None and self.TokenCName == Other.TokenCName and self.TokenSpaceGuidCName == Other.TokenSpaceGuidCName + + ## Override __hash__ function + # + # Use (TokenCName, TokenSpaceGuidCName) as key in hash table + # + # @retval truple() Key for hash table + # + def __hash__(self): + return hash((self.TokenCName, self.TokenSpaceGuidCName)) + +## LibraryClassObject +# +# This Class defines LibraryClassObject used in BuildDatabase +# +# @param object: Inherited from object class +# @param Name: Input value for LibraryClassName, default is None +# @param SupModList: Input value for SupModList, default is [] +# @param Type: Input value for Type, default is None +# +# @var LibraryClass: To store value for LibraryClass +# @var SupModList: To store value for SupModList +# @var Type: To store value for Type +# +class LibraryClassObject(object): + def __init__(self, Name = None, SupModList = [], Type = None): + self.LibraryClass = Name + self.SupModList = SupModList + if Type != None: + self.SupModList = CleanString(Type).split(DataType.TAB_SPACE_SPLIT) + +## ModuleBuildClassObject +# +# This Class defines ModuleBuildClass +# +# @param object: Inherited from object class +# +# @var DescFilePath: To store value for DescFilePath +# @var BaseName: To store value for BaseName +# @var ModuleType: To store value for ModuleType +# @var Guid: To store value for Guid +# @var Version: To store value for Version +# @var PcdIsDriver: To store value for PcdIsDriver +# @var BinaryModule: To store value for BinaryModule +# @var CustomMakefile: To store value for CustomMakefile +# @var Specification: To store value for Specification +# @var Shadow To store value for Shadow +# @var LibraryClass: To store value for LibraryClass, it is a list structure as +# [ LibraryClassObject, ...] +# @var ModuleEntryPointList: To store value for ModuleEntryPointList +# @var ModuleUnloadImageList: To store value for ModuleUnloadImageList +# @var ConstructorList: To store value for ConstructorList +# @var DestructorList: To store value for DestructorList +# @var Binaries: To store value for Binaries, it is a list structure as +# [ ModuleBinaryClassObject, ...] +# @var Sources: To store value for Sources, it is a list structure as +# [ ModuleSourceFilesClassObject, ... ] +# @var LibraryClasses: To store value for LibraryClasses, it is a set structure as +# { [LibraryClassName, ModuleType] : LibraryClassInfFile } +# @var Protocols: To store value for Protocols, it is a list structure as +# [ ProtocolName, ... ] +# @var Ppis: To store value for Ppis, it is a list structure as +# [ PpiName, ... ] +# @var Guids: To store value for Guids, it is a list structure as +# [ GuidName, ... ] +# @var Includes: To store value for Includes, it is a list structure as +# [ IncludePath, ... ] +# @var Packages: To store value for Packages, it is a list structure as +# [ DecFileName, ... ] +# @var Pcds: To store value for Pcds, it is a set structure as +# { [(PcdCName, PcdGuidCName)] : PcdClassObject} +# @var BuildOptions: To store value for BuildOptions, it is a set structure as +# { [BuildOptionKey] : BuildOptionValue} +# @var Depex: To store value for Depex +# +class ModuleBuildClassObject(object): + def __init__(self): + self.AutoGenVersion = 0 + self.DescFilePath = '' + self.BaseName = '' + self.ModuleType = '' + self.Guid = '' + self.Version = '' + self.PcdIsDriver = '' + self.BinaryModule = '' + self.Shadow = '' + self.CustomMakefile = {} + self.Specification = {} + self.LibraryClass = [] + self.ModuleEntryPointList = [] + self.ModuleUnloadImageList = [] + self.ConstructorList = [] + self.DestructorList = [] + + self.Binaries = [] + self.Sources = [] + self.LibraryClasses = sdict() + self.Libraries = [] + self.Protocols = [] + self.Ppis = [] + self.Guids = [] + self.Includes = [] + self.Packages = [] + self.Pcds = {} + self.BuildOptions = {} + self.Depex = '' + + ## Convert the class to a string + # + # Convert member DescFilePath of the class to a string + # + # @retval string Formatted String + # + def __str__(self): + return self.DescFilePath + + ## Override __eq__ function + # + # Check whether ModuleBuildClassObjects are the same + # + # @retval False The two ModuleBuildClassObjects are different + # @retval True The two ModuleBuildClassObjects are the same + # + def __eq__(self, Other): + return self.DescFilePath == str(Other) + + ## Override __hash__ function + # + # Use DescFilePath as key in hash table + # + # @retval string Key for hash table + # + def __hash__(self): + return hash(self.DescFilePath) + +## PackageBuildClassObject +# +# This Class defines PackageBuildClass +# +# @param object: Inherited from object class +# +# @var DescFilePath: To store value for DescFilePath +# @var PackageName: To store value for PackageName +# @var Guid: To store value for Guid +# @var Version: To store value for Version +# @var Protocols: To store value for Protocols, it is a set structure as +# { [ProtocolName] : Protocol Guid, ... } +# @var Ppis: To store value for Ppis, it is a set structure as +# { [PpiName] : Ppi Guid, ... } +# @var Guids: To store value for Guids, it is a set structure as +# { [GuidName] : Guid, ... } +# @var Includes: To store value for Includes, it is a list structure as +# [ IncludePath, ... ] +# @var LibraryClasses: To store value for LibraryClasses, it is a set structure as +# { [LibraryClassName] : LibraryClassInfFile } +# @var Pcds: To store value for Pcds, it is a set structure as +# { [(PcdCName, PcdGuidCName)] : PcdClassObject} +# +class PackageBuildClassObject(object): + def __init__(self): + self.DescFilePath = '' + self.PackageName = '' + self.Guid = '' + self.Version = '' + + self.Protocols = {} + self.Ppis = {} + self.Guids = {} + self.Includes = [] + self.LibraryClasses = {} + self.Pcds = {} + + ## Convert the class to a string + # + # Convert member DescFilePath of the class to a string + # + # @retval string Formatted String + # + def __str__(self): + return self.DescFilePath + + ## Override __eq__ function + # + # Check whether PackageBuildClassObjects are the same + # + # @retval False The two PackageBuildClassObjects are different + # @retval True The two PackageBuildClassObjects are the same + # + def __eq__(self, Other): + return self.DescFilePath == str(Other) + + ## Override __hash__ function + # + # Use DescFilePath as key in hash table + # + # @retval string Key for hash table + # + def __hash__(self): + return hash(self.DescFilePath) + +## PlatformBuildClassObject +# +# This Class defines PlatformBuildClass +# +# @param object: Inherited from object class +# +# @var DescFilePath: To store value for DescFilePath +# @var PlatformName: To store value for PlatformName +# @var Guid: To store value for Guid +# @var Version: To store value for Version +# @var DscSpecification: To store value for DscSpecification +# @var OutputDirectory: To store value for OutputDirectory +# @var FlashDefinition: To store value for FlashDefinition +# @var BuildNumber: To store value for BuildNumber +# @var MakefileName: To store value for MakefileName +# @var SkuIds: To store value for SkuIds, it is a set structure as +# { 'SkuName' : SkuId, '!include' : includefilename, ...} +# @var Modules: To store value for Modules, it is a list structure as +# [ InfFileName, ... ] +# @var Libraries: To store value for Libraries, it is a list structure as +# [ InfFileName, ... ] +# @var LibraryClasses: To store value for LibraryClasses, it is a set structure as +# { (LibraryClassName, ModuleType) : LibraryClassInfFile } +# @var Pcds: To store value for Pcds, it is a set structure as +# { [(PcdCName, PcdGuidCName)] : PcdClassObject } +# @var BuildOptions: To store value for BuildOptions, it is a set structure as +# { [BuildOptionKey] : BuildOptionValue } +# +class PlatformBuildClassObject(object): + def __init__(self): + self.DescFilePath = '' + self.PlatformName = '' + self.Guid = '' + self.Version = '' + self.DscSpecification = '' + self.OutputDirectory = '' + self.FlashDefinition = '' + self.BuildNumber = '' + self.MakefileName = '' + + self.SkuIds = {} + self.Modules = [] + self.LibraryInstances = [] + self.LibraryClasses = {} + self.Libraries = {} + self.Pcds = {} + self.BuildOptions = {} + + ## Convert the class to a string + # + # Convert member DescFilePath of the class to a string + # + # @retval string Formatted String + # + def __str__(self): + return self.DescFilePath + + ## Override __eq__ function + # + # Check whether PlatformBuildClassObjects are the same + # + # @retval False The two PlatformBuildClassObjects are different + # @retval True The two PlatformBuildClassObjects are the same + # + def __eq__(self, other): + return self.DescFilePath == str(other) + + ## Override __hash__ function + # + # Use DescFilePath as key in hash table + # + # @retval string Key for hash table + # + def __hash__(self): + return hash(self.DescFilePath) + +## ItemBuild +# +# This Class defines Module/Platform/Package databases for build system +# +# @param object: Inherited from object class +# @param Arch: Build arch +# @param Platform: Build Platform +# @param Package: Build Package +# @param Module: Build Module +# +# @var Arch: To store value for Build Arch +# @var PlatformDatabase: To store value for PlatformDatabase, it is a set structure as +# { [DscFileName] : PlatformBuildClassObject, ...} +# @var PackageDatabase: To store value for PackageDatabase, it is a set structure as +# { [DecFileName] : PacakgeBuildClassObject, ...} +# @var ModuleDatabase: To store value for ModuleDatabase, it is a list structure as +# { [InfFileName] : ModuleBuildClassObject, ...} +# +class ItemBuild(object): + def __init__(self, Arch, Platform = None, Package = None, Module = None): + self.Arch = Arch + self.PlatformDatabase = {} + self.PackageDatabase = {} + self.ModuleDatabase = {} + +## WorkspaceBuild +# +# This class is used to parse active platform to init all inf/dec/dsc files +# Generate module/package/platform databases for build +# +# @param object: Inherited from object class +# @param ActivePlatform: Input value for current active platform +# @param WorkspaceDir: Input value for current WorkspaceDir +# +# @var WorkspaceDir: To store value for WorkspaceDir +# @var SupArchList: To store value for SupArchList, selection scope is in below list +# EBC | IA32 | X64 | IPF | ARM | PPC +# @var BuildTarget: To store value for WorkspaceDir, selection scope is in below list +# RELEASE | DEBUG +# @var SkuId: To store value for SkuId +# @var Fdf: To store value for Fdf +# @var FdTargetList: To store value for FdTargetList +# @var FvTargetList: To store value for FvTargetList +# @var TargetTxt: To store value for TargetTxt, it is a set structure as +# TargetTxtClassObject +# @var ToolDef: To store value for ToolDef, it is a set structure as +# ToolDefClassObject +# @var InfDatabase: To store value for InfDatabase, it is a set structure as +# { [InfFileName] : InfClassObject} +# @var DecDatabase: To store value for DecDatabase, it is a set structure as +# { [DecFileName] : DecClassObject} +# @var DscDatabase: To store value for DscDatabase, it is a set structure as +# { [DscFileName] : DscClassObject} +# @var Build: To store value for DscDatabase, it is a set structure as +# ItemBuild +# @var DscFileName: To store value for Active Platform +# @var UnFoundPcdInDsc: To store values for the pcds defined in INF/DEC but not found in DSC, it is a set structure as +# { (PcdGuid, PcdCName, Arch) : DecFileName } +# +class WorkspaceBuild(object): + def __init__(self, ActivePlatform, WorkspaceDir): + self.WorkspaceDir = NormPath(WorkspaceDir) + self.SupArchList = [] + self.BuildTarget = [] + self.SkuId = '' + self.Fdf = '' + self.FdTargetList = [] + self.FvTargetList = [] + self.TargetTxt = None + self.ToolDef = None + + self.InfDatabase = {} + self.DecDatabase = {} + self.DscDatabase = {} + + self.UnFoundPcdInDsc = {} + + # + # Init build for all arches + # + self.Build = {} + for Arch in DataType.ARCH_LIST: + self.Build[Arch] = ItemBuild(Arch) + + # + # Init build database + # + self.Db = Database.Database(DATABASE_PATH) + self.Db.InitDatabase() + + # + # Get active platform + # + self.DscFileName = NormPath(ActivePlatform) + File = self.WorkspaceFile(self.DscFileName) + if os.path.exists(File) and os.path.isfile(File): + self.DscDatabase[self.DscFileName] = Dsc(File, False, True, self.WorkspaceDir, self.Db) + else: + EdkLogger.error("AutoGen", FILE_NOT_FOUND, ExtraData = File) + + # + # Parse platform to get module + # + for DscFile in self.DscDatabase.keys(): + Platform = self.DscDatabase[DscFile].Platform + + # + # Get global information + # + Tmp = set() + for Arch in DataType.ARCH_LIST: + for Item in Platform.Header[Arch].SupArchList: + Tmp.add(Item) + self.SupArchList = list(Tmp) + Tmp = set() + for Arch in DataType.ARCH_LIST: + for Item in Platform.Header[Arch].BuildTargets: + Tmp.add(Item) + self.BuildTarget = list(Tmp) + for Arch in self.SupArchList: + self.SkuId = Platform.Header[Arch].SkuIdName + self.Fdf = Platform.FlashDefinitionFile.FilePath + + # + # Get all inf files + # + for Item in Platform.LibraryClasses.LibraryList: + for Arch in Item.SupArchList: + self.AddToInfDatabase(Item.FilePath) + + for Item in Platform.Libraries.LibraryList: + for Arch in Item.SupArchList: + self.AddToInfDatabase(Item.FilePath) + + for Item in Platform.Modules.ModuleList: + for Arch in Item.SupArchList: + # + # Add modules + # + Module = Item.FilePath + self.AddToInfDatabase(Module) + # + # Add library used in modules + # + for Lib in Item.LibraryClasses.LibraryList: + self.AddToInfDatabase(Lib.FilePath) + self.UpdateLibraryClassOfModule(Module, Lib.Name, Arch, Lib.FilePath) + + # + # Parse module to get package + # + for InfFile in self.InfDatabase.keys(): + Module = self.InfDatabase[InfFile].Module + # + # Get all dec + # + for Item in Module.PackageDependencies: + for Arch in Item.SupArchList: + self.AddToDecDatabase(Item.FilePath) + # End of self.Init() + + ## Generate PlatformDatabase + # + # Go through each arch to get all items in DscDatabase to PlatformDatabase + # + def GenPlatformDatabase(self, PcdsSet={}): + for Dsc in self.DscDatabase.keys(): + Platform = self.DscDatabase[Dsc].Platform + for Arch in self.SupArchList: + Pb = PlatformBuildClassObject() + + # + # Defines + # + Pb.DescFilePath = Dsc + Pb.PlatformName = Platform.Header[Arch].Name + if Pb.PlatformName == '': + EdkLogger.error("AutoGen", PARSER_ERROR, "The BaseName of platform %s is not defined for arch %s" % (Dsc, Arch)) + Pb.Guid = Platform.Header[Arch].Guid + Pb.Version = Platform.Header[Arch].Version + Pb.DscSpecification = Platform.Header[Arch].DscSpecification + Pb.OutputDirectory = Platform.Header[Arch].OutputDirectory + Pb.FlashDefinition = Platform.FlashDefinitionFile.FilePath + Pb.BuildNumber = Platform.Header[Arch].BuildNumber + + # + # SkuId + # + for Key in Platform.SkuInfos.SkuInfoList.keys(): + Pb.SkuIds[Key] = Platform.SkuInfos.SkuInfoList[Key] + + # + # Module + # + for Item in Platform.Modules.ModuleList: + if Arch in Item.SupArchList: + Pb.Modules.append(Item.FilePath) + + # + # BuildOptions + # + for Item in Platform.BuildOptions.BuildOptionList: + if Arch in Item.SupArchList: + Pb.BuildOptions[(Item.ToolChainFamily, Item.ToolChain)] = Item.Option + + # + # LibraryClass + # + for Item in Platform.LibraryClasses.LibraryList: + SupModuleList = self.FindSupModuleListOfLibraryClass(Item, Platform.LibraryClasses.LibraryList, Arch) + if Arch in Item.SupArchList: + for ModuleType in SupModuleList: + Pb.LibraryClasses[(Item.Name, ModuleType)] = Item.FilePath + + # + # Libraries + # + for Item in Platform.Libraries.LibraryList: + for ItemArch in Item.SupArchList: + Library = self.InfDatabase[Item.FilePath] + if ItemArch not in Library.Module.Header: + continue + Pb.Libraries[Library.Module.Header[ItemArch].Name] = Item.FilePath + + # + # Pcds + # + for Item in Platform.DynamicPcdBuildDefinitions: + if Arch in Item.SupArchList: + Name = Item.CName + Guid = Item.TokenSpaceGuidCName + Type = Item.ItemType + DatumType = Item.DatumType + Value = Item.DefaultValue + Token = Item.Token + MaxDatumSize = Item.MaxDatumSize + SkuInfoList = Item.SkuInfoList + Pb.Pcds[(Name, Guid)] = PcdClassObject(Name, Guid, Type, DatumType, Value, Token, MaxDatumSize, SkuInfoList, False) + + for (Name, Guid) in PcdsSet: + Value = PcdsSet[Name, Guid] + for PcdType in ["FixedAtBuild", "PatchableInModule", "FeatureFlag", "Dynamic", "DynamicEx"]: + for Dec in self.Build[Arch].PackageDatabase: + Pcds = self.Build[Arch].PackageDatabase[Dec].Pcds + if (Name, Guid, PcdType) in Pcds: + Pcd = Pcds[(Name, Guid, PcdType)] + Type = PcdType + DatumType = Pcd.DatumType + Token = Pcd.TokenValue + MaxDatumSize = Pcd.MaxDatumSize + SkuInfoList = Pcd.SkuInfoList + Pb.Pcds[(Name, Guid)] = PcdClassObject(Name, Guid, Type, DatumType, Value, Token, MaxDatumSize, SkuInfoList, False) + break + else: + # nothing found + continue + # found in one package, find next PCD + break + else: + EdkLogger.error("AutoGen", PARSER_ERROR, "PCD is not found in any package", ExtraData="%s.%s" % (Guid, Name)) + # + # Add to database + # + self.Build[Arch].PlatformDatabase[Dsc] = Pb + Pb = None + + ## Generate PackageDatabase + # + # Go through each arch to get all items in DecDatabase to PackageDatabase + # + def GenPackageDatabase(self): + for Dec in self.DecDatabase.keys(): + Package = self.DecDatabase[Dec].Package + + for Arch in self.SupArchList: + Pb = PackageBuildClassObject() + + # + # Defines + # + Pb.DescFilePath = Dec + Pb.PackageName = Package.Header[Arch].Name + if Pb.PackageName == '': + EdkLogger.error("AutoGen", PARSER_ERROR, "The BaseName of package %s is not defined for arch %s" % (Dec, Arch)) + + Pb.Guid = Package.Header[Arch].Guid + Pb.Version = Package.Header[Arch].Version + + # + # Protocols + # + for Item in Package.ProtocolDeclarations: + if Arch in Item.SupArchList: + Pb.Protocols[Item.CName] = Item.Guid + + # + # Ppis + # + for Item in Package.PpiDeclarations: + if Arch in Item.SupArchList: + Pb.Ppis[Item.CName] = Item.Guid + + # + # Guids + # + for Item in Package.GuidDeclarations: + if Arch in Item.SupArchList: + Pb.Guids[Item.CName] = Item.Guid + + # + # Includes + # + for Item in Package.Includes: + if Arch in Item.SupArchList: + Pb.Includes.append(Item.FilePath) + + # + # LibraryClasses + # + for Item in Package.LibraryClassDeclarations: + if Arch in Item.SupArchList: + Pb.LibraryClasses[Item.LibraryClass] = Item.RecommendedInstance + + # + # Pcds + # + for Item in Package.PcdDeclarations: + if Arch in Item.SupArchList: + Name = Item.CName + Guid = Item.TokenSpaceGuidCName + Type = Item.ItemType + DatumType = Item.DatumType + Value = Item.DefaultValue + Token = Item.Token + MaxDatumSize = Item.MaxDatumSize + SkuInfoList = Item.SkuInfoList + Pb.Pcds[(Name, Guid, Type)] = PcdClassObject(Name, Guid, Type, DatumType, Value, Token, MaxDatumSize, SkuInfoList, False) + + # + # Add to database + # + self.Build[Arch].PackageDatabase[Dec] = Pb + Pb = None + + ## Generate ModuleDatabase + # + # Go through each arch to get all items in InfDatabase to ModuleDatabase + # + def GenModuleDatabase(self, InfList = []): + for Inf in self.InfDatabase.keys(): + Module = self.InfDatabase[Inf].Module + + for Arch in self.SupArchList: + if not self.IsModuleDefinedInPlatform(Inf, Arch, InfList) or Arch not in Module.Header: + continue + + ModuleHeader = Module.Header[Arch] + Pb = ModuleBuildClassObject() + + # + # Defines + # + Pb.DescFilePath = Inf + Pb.BaseName = ModuleHeader.Name + if Pb.BaseName == '': + EdkLogger.error("AutoGen", PARSER_ERROR, "The BaseName of module %s is not defined for arch %s" % (Inf, Arch)) + Pb.Guid = ModuleHeader.Guid + Pb.Version = ModuleHeader.Version + Pb.ModuleType = ModuleHeader.ModuleType + Pb.PcdIsDriver = ModuleHeader.PcdIsDriver + Pb.BinaryModule = ModuleHeader.BinaryModule + Pb.CustomMakefile = ModuleHeader.CustomMakefile + Pb.Shadow = ModuleHeader.Shadow + + # + # Specs os Defines + # + Pb.Specification = ModuleHeader.Specification + Pb.Specification[TAB_INF_DEFINES_EDK_RELEASE_VERSION] = ModuleHeader.EdkReleaseVersion + Pb.Specification[TAB_INF_DEFINES_EFI_SPECIFICATION_VERSION] = ModuleHeader.EfiSpecificationVersion + Pb.AutoGenVersion = int(ModuleHeader.InfVersion, 0) + + # + # LibraryClass of Defines + # + for Item in ModuleHeader.LibraryClass: + Pb.LibraryClass.append(LibraryClassObject(Item.LibraryClass, Item.SupModuleList, None)) + + # + # Module image and library of Defines + # + for Item in Module.ExternImages: + if Item.ModuleEntryPoint != '' and Item.ModuleEntryPoint not in Pb.ModuleEntryPointList: + Pb.ModuleEntryPointList.append(Item.ModuleEntryPoint) + if Item.ModuleUnloadImage != '' and Item.ModuleUnloadImage not in Pb.ModuleUnloadImageList: + Pb.ModuleUnloadImageList.append(Item.ModuleUnloadImage) + for Item in Module.ExternLibraries: + if Item.Constructor != '' and Item.Constructor not in Pb.ConstructorList: + Pb.ConstructorList.append(Item.Constructor) + if Item.Destructor != '' and Item.Destructor not in Pb.DestructorList: + Pb.DestructorList.append(Item.Destructor) + + # + # Binaries + # + for Item in Module.Binaries: + if Arch in Item.SupArchList: + FileName = Item.BinaryFile + FileType = Item.FileType + Target = Item.Target + FeatureFlag = Item.FeatureFlag + Pb.Binaries.append(ModuleBinaryFileClass(FileName, FileType, Target, FeatureFlag, Arch.split())) + + # + # Sources + # + for Item in Module.Sources: + if Arch in Item.SupArchList: + SourceFile = Item.SourceFile + TagName = Item.TagName + ToolCode = Item.ToolCode + ToolChainFamily = Item.ToolChainFamily + FeatureFlag = Item.FeatureFlag + Pb.Sources.append(ModuleSourceFileClass(SourceFile, TagName, ToolCode, ToolChainFamily, FeatureFlag)) + + # + # Protocols + # + for Item in Module.Protocols: + if Arch in Item.SupArchList: + Pb.Protocols.append(Item.CName) + + # + # Ppis + # + for Item in Module.Ppis: + if Arch in Item.SupArchList: + Pb.Ppis.append(Item.CName) + + # + # Guids + # + for Item in Module.Guids: + if Arch in Item.SupArchList: + Pb.Ppis.append(Item.CName) + + # + # Includes + # + for Item in Module.Includes: + if Arch in Item.SupArchList: + Pb.Includes.append(Item.FilePath) + + # + # Packages + # + for Item in Module.PackageDependencies: + if Arch in Item.SupArchList: + Pb.Packages.append(Item.FilePath) + + # + # BuildOptions + # + for Item in Module.BuildOptions: + if Arch in Item.SupArchList: + if (Item.ToolChainFamily, Item.ToolChain) not in Pb.BuildOptions: + Pb.BuildOptions[(Item.ToolChainFamily, Item.ToolChain)] = Item.Option + else: + OptionString = Pb.BuildOptions[(Item.ToolChainFamily, Item.ToolChain)] + Pb.BuildOptions[(Item.ToolChainFamily, Item.ToolChain)] = OptionString + " " + Item.Option + self.FindBuildOptions(Arch, Inf, Pb.BuildOptions) + + # + # Depex + # + for Item in Module.Depex: + if Arch in Item.SupArchList: + Pb.Depex = Pb.Depex + Item.Depex + ' ' + Pb.Depex = Pb.Depex.strip() + + # + # LibraryClasses + # + for Item in Module.LibraryClasses: + if Arch in Item.SupArchList: + Lib = Item.LibraryClass + RecommendedInstance = Item.RecommendedInstance + if Pb.LibraryClass != []: + # + # For Library + # + for Libs in Pb.LibraryClass: + for Type in Libs.SupModList: + Instance = self.FindLibraryClassInstanceOfLibrary(Lib, Arch, Type) + if Instance == None: + Instance = RecommendedInstance + Pb.LibraryClasses[(Lib, Type)] = Instance + else: + # + # For Module + # + Instance = self.FindLibraryClassInstanceOfModule(Lib, Arch, Pb.ModuleType, Inf) + if Instance == None: + Instance = RecommendedInstance + Pb.LibraryClasses[(Lib, Pb.ModuleType)] = Instance + + # + # Libraries + # + for Item in Module.Libraries: + if Arch in Item.SupArchList: + Pb.Libraries.append(Item.Library) + + # + # Pcds + # + for Item in Module.PcdCodes: + if Arch in Item.SupArchList: + Name = Item.CName + Guid = Item.TokenSpaceGuidCName + Type = Item.ItemType + Pb.Pcds[(Name, Guid)] = self.FindPcd(Arch, Inf, Name, Guid, Type) + + # + # Add to database + # + self.Build[Arch].ModuleDatabase[Inf] = Pb + Pb = None + + ## Update Libraries Of Platform Database + # + # @param InfList: A list for all inf files + # + def UpdateLibrariesOfPlatform(self, InfList = []): + for Arch in self.SupArchList: + PlatformDatabase = self.Build[Arch].PlatformDatabase + for Dsc in PlatformDatabase: + Platform = PlatformDatabase[Dsc] + for Inf in Platform.Modules: + if not self.IsModuleDefinedInPlatform(Inf, Arch, InfList): + continue + Module = self.Build[Arch].ModuleDatabase[Inf] + if Module.LibraryClass == None or Module.LibraryClass == []: + self.UpdateLibrariesOfModule(Platform, Module, Arch) + for Key in Module.LibraryClasses: + Lib = Module.LibraryClasses[Key] + if Lib not in Platform.LibraryInstances: + Platform.LibraryInstances.append(Lib) + + + ## Update Libraries Of Module Database + # + # @param Module: The module need to be updated libraries + # @param Arch: The supportted arch of the module + # + def UpdateLibrariesOfModule(self, Platform, Module, Arch): + ModuleDatabase = self.Build[Arch].ModuleDatabase + ModuleType = Module.ModuleType + + # check R8 module + if Module.AutoGenVersion < 0x00010005: + EdkLogger.verbose("") + EdkLogger.verbose("Library instances of module [%s] [%s]:" % (str(Module), Arch)) + LibraryConsumerList = [Module] + + # "CompilerStub" is a must for R8 modules + Module.Libraries.append("CompilerStub") + while len(LibraryConsumerList) > 0: + M = LibraryConsumerList.pop() + for LibraryName in M.Libraries: + if LibraryName not in Platform.Libraries: + EdkLogger.warn("AutoGen", "Library [%s] is not found" % LibraryName, + ExtraData="\t%s [%s]" % (str(Module), Arch)) + continue + + LibraryFile = Platform.Libraries[LibraryName] + if (LibraryName, ModuleType) not in Module.LibraryClasses: + Module.LibraryClasses[LibraryName, ModuleType] = LibraryFile + LibraryConsumerList.append(ModuleDatabase[LibraryFile]) + EdkLogger.verbose("\t" + LibraryName + " : " + LibraryFile) + return + + # R9 module + LibraryConsumerList = [Module] + Constructor = [] + ConsumedByList = sdict() + LibraryInstance = sdict() + + EdkLogger.verbose("") + EdkLogger.verbose("Library instances of module [%s] [%s]:" % (str(Module), Arch)) + while len(LibraryConsumerList) > 0: + M = LibraryConsumerList.pop() + for Key, LibraryPath in M.LibraryClasses.iteritems(): + # The "Key" is in format of (library_class_name, supported_module_type) + if ModuleType != "USER_DEFINED" and ModuleType not in Key: + EdkLogger.debug(EdkLogger.DEBUG_3, "%s for module type %s is not supported (%s)" % (Key + (LibraryPath,))) + continue + + LibraryClassName = Key[0] + if LibraryClassName not in LibraryInstance or LibraryInstance[LibraryClassName] == None: + if LibraryPath == None or LibraryPath == "": + LibraryInstance[LibraryClassName] = None + continue + LibraryModule = ModuleDatabase[LibraryPath] + LibraryInstance[LibraryClassName] = LibraryModule + LibraryConsumerList.append(LibraryModule) + EdkLogger.verbose("\t" + LibraryClassName + " : " + str(LibraryModule)) + elif LibraryPath == None or LibraryPath == "": + continue + else: + LibraryModule = LibraryInstance[LibraryClassName] + + if LibraryModule.ConstructorList != [] and LibraryModule not in Constructor: + Constructor.append(LibraryModule) + + if LibraryModule not in ConsumedByList: + ConsumedByList[LibraryModule] = [] + if M != Module: + if M in ConsumedByList[LibraryModule]: + continue + ConsumedByList[LibraryModule].append(M) + # + # Initialize the sorted output list to the empty set + # + SortedLibraryList = [] + # + # Q <- Set of all nodes with no incoming edges + # + LibraryList = [] #LibraryInstance.values() + Q = [] + for LibraryClassName in LibraryInstance: + M = LibraryInstance[LibraryClassName] + if M == None: + EdkLogger.error("AutoGen", AUTOGEN_ERROR, + "Library instance for library class [%s] is not found" % LibraryClassName, + ExtraData="\t%s [%s]" % (str(Module), Arch)) + LibraryList.append(M) + # + # check if there're duplicate library classes + # + for Lc in M.LibraryClass: + if Lc.SupModList != None and ModuleType not in Lc.SupModList: + EdkLogger.error("AutoGen", AUTOGEN_ERROR, + "Module type [%s] is not supported by library instance [%s]" % (ModuleType, str(M)), + ExtraData="\t%s" % str(Module)) + + if Lc.LibraryClass in LibraryInstance and str(M) != str(LibraryInstance[Lc.LibraryClass]): + EdkLogger.error("AutoGen", AUTOGEN_ERROR, + "More than one library instance found for library class [%s] in module [%s]" % (Lc.LibraryClass, Module), + ExtraData="\t%s\n\t%s" % (LibraryInstance[Lc.LibraryClass], str(M)) + ) + if ConsumedByList[M] == []: + Q.insert(0, M) + # + # while Q is not empty do + # + while Q != []: + # + # remove node from Q + # + Node = Q.pop() + # + # output Node + # + SortedLibraryList.append(Node) + # + # for each node Item with an edge e from Node to Item do + # + for Item in LibraryList: + if Node not in ConsumedByList[Item]: + continue + # + # remove edge e from the graph + # + ConsumedByList[Item].remove(Node) + # + # If Item has no other incoming edges then + # + if ConsumedByList[Item] == []: + # + # insert Item into Q + # + Q.insert(0, Item) + + EdgeRemoved = True + while Q == [] and EdgeRemoved: + EdgeRemoved = False + # + # for each node Item with a Constructor + # + for Item in LibraryList: + if Item in Constructor: + # + # for each Node without a constructor with an edge e from Item to Node + # + for Node in ConsumedByList[Item]: + if Node not in Constructor: + # + # remove edge e from the graph + # + ConsumedByList[Item].remove(Node) + EdgeRemoved = True + if ConsumedByList[Item] == []: + # + # insert Item into Q + # + Q.insert(0, Item) + break + if Q != []: + break + + # + # if any remaining node Item in the graph has a constructor and an incoming edge, then the graph has a cycle + # + for Item in LibraryList: + if ConsumedByList[Item] != [] and Item in Constructor and len(Constructor) > 1: + ErrorMessage = 'Library [%s] with constructors has a cycle' % str(Item) + EdkLogger.error("AutoGen", AUTOGEN_ERROR, ErrorMessage, + "\tconsumed by " + "\n\tconsumed by ".join([str(L) for L in ConsumedByList[Item]])) + if Item not in SortedLibraryList: + SortedLibraryList.append(Item) + + # + # Build the list of constructor and destructir names + # The DAG Topo sort produces the destructor order, so the list of constructors must generated in the reverse order + # + SortedLibraryList.reverse() + Module.LibraryClasses = sdict() + for L in SortedLibraryList: + for Lc in L.LibraryClass: + Module.LibraryClasses[Lc.LibraryClass, ModuleType] = str(L) + # + # Merge PCDs from library instance + # + for Key in L.Pcds: + if Key not in Module.Pcds: + LibPcd = L.Pcds[Key] + Module.Pcds[Key] = self.FindPcd(Arch, str(Module), LibPcd.TokenCName, LibPcd.TokenSpaceGuidCName, LibPcd.Type) + # + # Merge GUIDs from library instance + # + for CName in L.Guids: + if CName not in Module.Guids: + Module.Guids.append(CName) + # + # Merge Protocols from library instance + # + for CName in L.Protocols: + if CName not in Module.Protocols: + Module.Protocols.append(CName) + # + # Merge Ppis from library instance + # + for CName in L.Ppis: + if CName not in Module.Ppis: + Module.Ppis.append(CName) + + ## GenBuildDatabase + # + # Generate build database for all arches + # + # @param PcdsSet: Pcd list for override from Fdf parse result + # @param InfList: Inf list for override from Fdf parse result + # + def GenBuildDatabase(self, PcdsSet = {}, InfList = []): + # + # Add additional inf file defined in Fdf file + # + for InfFile in InfList: + self.AddToInfDatabase(NormPath(InfFile)) + + # + # Generate PlatformDatabase, PackageDatabase and ModuleDatabase + # + self.GenPackageDatabase() + self.GenPlatformDatabase(PcdsSet) + self.GenModuleDatabase(InfList) + + self.Db.Close() + + # + # Update Libraries Of Platform + # + self.UpdateLibrariesOfPlatform(InfList) + + # + # Output used Pcds not found in DSC file + # + self.ShowUnFoundPcds() + + ## ShowUnFoundPcds() + # + # If there is any pcd used but not defined in DSC + # Print warning message on screen and output a list of pcds + # + def ShowUnFoundPcds(self): + if self.UnFoundPcdInDsc != {}: + WrnMessage = '**** WARNING ****\n' + WrnMessage += 'The following Pcds were not defined in the DSC file: %s\n' % self.DscFileName + WrnMessage += 'The default values were obtained from the DEC file that declares the PCD and the PCD default value\n' + for (Guid, Name, Type, Arch) in self.UnFoundPcdInDsc: + Dec = self.UnFoundPcdInDsc[(Guid, Name, Type, Arch)] + Pcds = self.Build[Arch].PackageDatabase[Dec].Pcds + if (Name, Guid, Type) in Pcds: + Pcd = Pcds[(Name, Guid, Type)] + PcdItemTypeUsed = Pcd.Type + DefaultValue = Pcd.DefaultValue + WrnMessage += '%s.%s: Defined in file %s, PcdItemType is Pcds%s, DefaultValue is %s\n' % (Guid, Name, Dec, PcdItemTypeUsed, DefaultValue) + EdkLogger.verbose(WrnMessage) + + ## Create a full path with workspace dir + # + # Convert Filename with workspace dir to create a full path + # + # @param Filename: The filename need to be added workspace dir + # + # @retval string Full path + # + def WorkspaceFile(self, Filename): + return WorkspaceFile(self.WorkspaceDir, Filename) + + ## Update LibraryClass of Module + # + # If a module of a platform has its own override libraryclass but the libraryclass not defined in the module + # Add this libraryclass to the module + # + # @param InfFileName: InfFileName specificed in platform + # @param LibraryClass: LibraryClass specificed in platform + # @param Arch: Supportted Arch + # @param InstanceFilePath: InstanceFilePath specificed in platform + # + def UpdateLibraryClassOfModule(self, InfFileName, LibraryClass, Arch, InstanceFilePath): + # + # Update the library instance itself to add this libraryclass name + # + LibraryModule = self.InfDatabase[InstanceFilePath].Module + LibList = LibraryModule.Header[Arch].LibraryClass + NotFound = True + for Lib in LibList: + # + # Find this LibraryClass + # + if Lib.LibraryClass == LibraryClass: + NotFound = False; + break; + if NotFound: + NewLib = LibraryClassClass() + NewLib.LibraryClass = LibraryClass + NewLib.SupModuleList = DataType.SUP_MODULE_LIST # LibraryModule.Header[Arch].ModuleType.split() + LibraryModule.Header[Arch].LibraryClass.append(NewLib) + + # + # Add it to LibraryClasses Section for the module which is using the library + # + Module = self.InfDatabase[InfFileName].Module + LibList = Module.LibraryClasses + NotFound = True + for Lib in LibList: + # + # Find this LibraryClass + # + if Lib.LibraryClass == LibraryClass: + if Arch in Lib.SupArchList: + return + else: + Lib.SupArchList.append(Arch) + return + if NotFound: + Lib = LibraryClassClass() + Lib.LibraryClass = LibraryClass + Lib.SupArchList = [Arch] + Module.LibraryClasses.append(Lib) + + ## Add Inf file to InfDatabase + # + # Create a Inf instance for input inf file and add it to InfDatabase + # + # @param InfFileName: The InfFileName need to be added to database + # + def AddToInfDatabase(self, InfFileName): + File = self.WorkspaceFile(InfFileName) + if os.path.exists(File) and os.path.isfile(File): + if InfFileName not in self.InfDatabase: + self.InfDatabase[InfFileName] = Inf(File, False, True, self.WorkspaceDir, self.Db, self.SupArchList) + else: + EdkLogger.error("AutoGen", FILE_NOT_FOUND, ExtraData=File) + + ## Add Dec file to DecDatabase + # + # Create a Dec instance for input dec file and add it to DecDatabase + # + # @param DecFileName: The DecFileName need to be added to database + # + def AddToDecDatabase(self, DecFileName): + File = self.WorkspaceFile(DecFileName) + if os.path.exists(File) and os.path.isfile(File): + if DecFileName not in self.DecDatabase: + self.DecDatabase[DecFileName] = Dec(File, False, True, self.WorkspaceDir, self.Db, self.SupArchList) + else: + EdkLogger.error("AutoGen", FILE_NOT_FOUND, ExtraData=File) + + ## Search LibraryClass Instance for Module + # + # Search PlatformBuildDatabase to find LibraryClass Instance for Module + # Return the instance if found + # + # @param Lib: Input value for Library Class Name + # @param Arch: Supportted Arch + # @param ModuleType: Supportted ModuleType + # @param ModuleName: Input value for Module Name + # + # @retval string Found LibraryClass Instance file path + # + def FindLibraryClassInstanceOfModule(self, Lib, Arch, ModuleType, ModuleName): + # + # First find if exist in of from dsc file + # + for Dsc in self.DscDatabase.keys(): + Platform = self.DscDatabase[Dsc].Platform + for Module in Platform.Modules.ModuleList: + if Arch in Module.SupArchList: + if Module.FilePath == ModuleName: + for LibraryClass in Module.LibraryClasses.LibraryList: + if LibraryClass.Name == Lib: + return LibraryClass.FilePath + # + #Second find if exist in of from dsc file + # + return self.FindLibraryClassInstanceOfLibrary(Lib, Arch, ModuleType) + + ## Search LibraryClass Instance for Library + # + # Search PlatformBuildDatabase to find LibraryClass Instance for Library + # Return the instance if found + # + # @param Lib: Input value for Library Class Name + # @param Arch: Supportted Arch + # @param Type: Supportted Library Usage Type + # + # @retval string Found LibraryClass Instance file path + # @retval None Not Found + # + def FindLibraryClassInstanceOfLibrary(self, Lib, Arch, Type): + for Dsc in self.DscDatabase.keys(): + Platform = self.DscDatabase[Dsc].Platform + if (Lib, Type) in self.Build[Arch].PlatformDatabase[Dsc].LibraryClasses: + return self.Build[Arch].PlatformDatabase[Dsc].LibraryClasses[(Lib, Type)] + elif (Lib, '') in self.Build[Arch].PlatformDatabase[Dsc].LibraryClasses: + return self.Build[Arch].PlatformDatabase[Dsc].LibraryClasses[(Lib, '')] + return None + + ## Find BuildOptions + # + # Search DscDatabase to find component definition of ModuleName + # Override BuildOption if it is defined in component + # + # @param Arch: Supportted Arch + # @param ModuleName: The module which has buildoption definition in component of platform + # @param BuildOptions: The set of all buildopitons + # + def FindBuildOptions(self, Arch, ModuleName, BuildOptions): + for Dsc in self.DscDatabase.keys(): + # + # First find if exist in of from dsc file + # if find, use that override the one defined in inf file + # + Platform = self.DscDatabase[Dsc].Platform + for Module in Platform.Modules.ModuleList: + if Arch in Module.SupArchList: + if Module.FilePath == ModuleName: + for BuildOption in Module.ModuleSaBuildOption.BuildOptionList: + # + # Add to BuildOptions + # + BuildOptions[(BuildOption.ToolChainFamily, BuildOption.ToolChain)] = BuildOption.Option + + ## Find Pcd + # + # Search platform database, package database, module database and PcdsSet from Fdf + # Return found Pcd + # + # @param Arch: Supportted Arch + # @param ModuleName: The module which has pcd definition in component of platform + # @param Name: Name of Pcd + # @param Guid: Guid of Pcd + # @param Type: Type of Pcd + # + # @retval PcdClassObject An instance for PcdClassObject with all members filled + # + def FindPcd(self, Arch, ModuleName, Name, Guid, Type): + NewType = '' + DatumType = '' + Value = '' + Token = '' + MaxDatumSize = '' + SkuInfoList = {} + IsOverrided = False + IsFoundInDsc = False + IsFoundInDec = False + FoundInDecFile = '' + + # + # Second get information from platform database + # + OwnerPlatform = '' + for Dsc in self.Build[Arch].PlatformDatabase.keys(): + Pcds = self.Build[Arch].PlatformDatabase[Dsc].Pcds + if (Name, Guid) in Pcds: + OwnerPlatform = Dsc + Pcd = Pcds[(Name, Guid)] + if Pcd.Type != '' and Pcd.Type != None: + NewType = Pcd.Type + if NewType in DataType.PCD_DYNAMIC_TYPE_LIST: + NewType = DataType.TAB_PCDS_DYNAMIC + elif NewType in DataType.PCD_DYNAMIC_EX_TYPE_LIST: + NewType = DataType.TAB_PCDS_DYNAMIC_EX + else: + NewType = Type + + if Type != '' and Type != NewType: + ErrorMsg = "PCD %s.%s is declared as [%s] in module\n\t%s\n\n"\ + " But it's used as [%s] in platform\n\t%s"\ + % (Guid, Name, Type, ModuleName, NewType, OwnerPlatform) + EdkLogger.error("AutoGen", PARSER_ERROR, ErrorMsg) + + + if Pcd.DatumType != '' and Pcd.DatumType != None: + DatumType = Pcd.DatumType + if Pcd.TokenValue != '' and Pcd.TokenValue != None: + Token = Pcd.TokenValue + if Pcd.DefaultValue != '' and Pcd.DefaultValue != None: + Value = Pcd.DefaultValue + if Pcd.MaxDatumSize != '' and Pcd.MaxDatumSize != None: + MaxDatumSize = Pcd.MaxDatumSize + SkuInfoList = Pcd.SkuInfoList + + IsOverrided = True + IsFoundInDsc = True + break + + # + # Third get information from of from module database + # + for Dsc in self.DscDatabase.keys(): + for Module in self.DscDatabase[Dsc].Platform.Modules.ModuleList: + if Arch in Module.SupArchList: + if Module.FilePath == ModuleName: + for Pcd in Module.PcdBuildDefinitions: + if (Name, Guid) == (Pcd.CName, Pcd.TokenSpaceGuidCName): + if Pcd.DefaultValue != '': + Value = Pcd.DefaultValue + if Pcd.MaxDatumSize != '': + MaxDatumSize = Pcd.MaxDatumSize + + IsFoundInDsc = True + IsOverrided = True + break + + # + # First get information from package database + # + Pcd = None + if NewType == '': + if Type != '': + PcdTypeList = [Type] + else: + PcdTypeList = ["FixedAtBuild", "PatchableInModule", "FeatureFlag", "Dynamic", "DynamicEx"] + + for Dec in self.Build[Arch].PackageDatabase.keys(): + Pcds = self.Build[Arch].PackageDatabase[Dec].Pcds + for PcdType in PcdTypeList: + if (Name, Guid, PcdType) in Pcds: + Pcd = Pcds[(Name, Guid, PcdType)] + NewType = PcdType + IsOverrided = True + IsFoundInDec = True + FoundInDecFile = Dec + break + else: + continue + break + else: + for Dec in self.Build[Arch].PackageDatabase.keys(): + Pcds = self.Build[Arch].PackageDatabase[Dec].Pcds + if (Name, Guid, NewType) in Pcds: + Pcd = Pcds[(Name, Guid, NewType)] + IsOverrided = True + IsFoundInDec = True + FoundInDecFile = Dec + break + + if not IsFoundInDec: + ErrorMsg = "Pcd '%s.%s [%s]' defined in module '%s' is not found in any package for Arch '%s'" % (Guid, Name, NewType, ModuleName, Arch) + EdkLogger.error("AutoGen", PARSER_ERROR, ErrorMsg) + + # + # Not found in any platform and fdf + # + if not IsFoundInDsc: + Value = Pcd.DefaultValue + if NewType.startswith("Dynamic") and SkuInfoList == {}: + SkuIds = self.Build[Arch].PlatformDatabase.values()[0].SkuIds + SkuInfoList['DEFAULT'] = SkuInfoClass(SkuIdName='DEFAULT', SkuId=SkuIds['DEFAULT'], DefaultValue=Value) + self.UnFoundPcdInDsc[(Guid, Name, NewType, Arch)] = FoundInDecFile + #elif Type != '' and NewType.startswith("Dynamic"): + # NewType = Pcd.Type + DatumType = Pcd.DatumType + if Token in [None, '']: + Token = Pcd.TokenValue + if DatumType == "VOID*" and MaxDatumSize in ['', None]: + EdkLogger.verbose("No MaxDatumSize specified for PCD %s.%s in module [%s]" % (Guid, Name, ModuleName)) + if Value[0] == 'L': + MaxDatumSize = str(len(Value) * 2) + elif Value[0] == '{': + MaxDatumSize = str(len(Value.split(','))) + else: + MaxDatumSize = str(len(Value)) + + return PcdClassObject(Name, Guid, NewType, DatumType, Value, Token, MaxDatumSize, SkuInfoList, IsOverrided) + + ## Find Supportted Module List Of LibraryClass + # + # Search in InfDatabase, find the supmodulelist of the libraryclass + # + # @param LibraryClass: LibraryClass name for search + # @param OverridedLibraryClassList: A list of all LibraryClass + # @param Arch: Supportted Arch + # + # @retval list SupModuleList + # + def FindSupModuleListOfLibraryClass(self, LibraryClass, OverridedLibraryClassList, Arch): + Name = LibraryClass.Name + FilePath = LibraryClass.FilePath + SupModuleList = copy.copy(LibraryClass.SupModuleList) + + # + # If the SupModuleList means all, remove overrided module types of platform + # + if SupModuleList == DataType.SUP_MODULE_LIST: + EdkLogger.debug(EdkLogger.DEBUG_3, "\tLibraryClass %s supports all module types" % Name) + for Item in OverridedLibraryClassList: + # + # Find a library class (Item) with the same name + # + if Item.Name == Name: + # + # Do nothing if it is itself + # + if Item.SupModuleList == DataType.SUP_MODULE_LIST: + continue + # + # If not itself, check arch first + # + if Arch in LibraryClass.SupArchList: + # + # If arch is supportted, remove all related module type + # + if Arch in Item.SupArchList: + for ModuleType in Item.SupModuleList: + EdkLogger.debug(EdkLogger.DEBUG_3, "\tLibraryClass %s has specific defined module types" % Name) + if ModuleType in SupModuleList: + SupModuleList.remove(ModuleType) + + return SupModuleList + + ## Find Module inf Platform + # + # Check if the module is defined in of + # + # @param Inf: Inf file (Module) need to be searched + # @param Arch: Supportted Arch + # @param InfList: A list for all Inf file + # + # @retval True Mudule Found + # @retval Flase Module Not Found + # + def IsModuleDefinedInPlatform(self, Inf, Arch, InfList): + for Dsc in self.DscDatabase.values(): + for LibraryClass in Dsc.Platform.LibraryClasses.LibraryList: + if Inf == LibraryClass.FilePath and Arch in LibraryClass.SupArchList: + return True + for Module in Dsc.Platform.Modules.ModuleList: + if Inf == Module.FilePath and Arch in Module.SupArchList: + return True + for Item in Module.LibraryClasses.LibraryList: + if Inf == Item.FilePath: + return True + for Library in Dsc.Platform.Libraries.LibraryList: + if Inf == Library.FilePath and Arch in Library.SupArchList: + return True + + return False + + ## Show all content of the workspacebuild + # + # Print each item of the workspacebuild with (Key = Value) pair + # + def ShowWorkspaceBuild(self): + print self.DscDatabase + print self.InfDatabase + print self.DecDatabase + print 'SupArchList', self.SupArchList + print 'BuildTarget', self.BuildTarget + print 'SkuId', self.SkuId + + for Arch in self.SupArchList: + print Arch + print 'Platform' + for Platform in self.Build[Arch].PlatformDatabase.keys(): + P = self.Build[Arch].PlatformDatabase[Platform] + print 'DescFilePath = ', P.DescFilePath + print 'PlatformName = ', P.PlatformName + print 'Guid = ', P.Guid + print 'Version = ', P.Version + print 'OutputDirectory = ', P.OutputDirectory + print 'FlashDefinition = ', P.FlashDefinition + print 'SkuIds = ', P.SkuIds + print 'Modules = ', P.Modules + print 'LibraryClasses = ', P.LibraryClasses + print 'Pcds = ', P.Pcds + for item in P.Pcds.keys(): + print P.Pcds[item] + print 'BuildOptions = ', P.BuildOptions + print '' + # End of Platform + + print 'package' + for Package in self.Build[Arch].PackageDatabase.keys(): + P = self.Build[Arch].PackageDatabase[Package] + print 'DescFilePath = ', P.DescFilePath + print 'PackageName = ', P.PackageName + print 'Guid = ', P.Guid + print 'Version = ', P.Version + print 'Protocols = ', P.Protocols + print 'Ppis = ', P.Ppis + print 'Guids = ', P.Guids + print 'Includes = ', P.Includes + print 'LibraryClasses = ', P.LibraryClasses + print 'Pcds = ', P.Pcds + for item in P.Pcds.keys(): + print P.Pcds[item] + print '' + # End of Package + + print 'module' + for Module in self.Build[Arch].ModuleDatabase.keys(): + P = self.Build[Arch].ModuleDatabase[Module] + print 'DescFilePath = ', P.DescFilePath + print 'BaseName = ', P.BaseName + print 'ModuleType = ', P.ModuleType + print 'Guid = ', P.Guid + print 'Version = ', P.Version + print 'CustomMakefile = ', P.CustomMakefile + print 'Specification = ', P.Specification + print 'Shadow = ', P.Shadow + print 'PcdIsDriver = ', P.PcdIsDriver + for Lib in P.LibraryClass: + print 'LibraryClassDefinition = ', Lib.LibraryClass, 'SupModList = ', Lib.SupModList + print 'ModuleEntryPointList = ', P.ModuleEntryPointList + print 'ModuleUnloadImageList = ', P.ModuleUnloadImageList + print 'ConstructorList = ', P.ConstructorList + print 'DestructorList = ', P.DestructorList + + print 'Binaries = ' + for item in P.Binaries: + print item.BinaryFile, item.FeatureFlag, item.SupArchList + print 'Sources = ' + for item in P.Sources: + print item.SourceFile + print 'LibraryClasses = ', P.LibraryClasses + print 'Protocols = ', P.Protocols + print 'Ppis = ', P.Ppis + print 'Guids = ', P.Guids + print 'Includes = ', P.Includes + print 'Packages = ', P.Packages + print 'Pcds = ', P.Pcds + for item in P.Pcds.keys(): + print P.Pcds[item] + print 'BuildOptions = ', P.BuildOptions + print 'Depex = ', P.Depex + print '' + # End of Module + +## +# +# This acts like the main() function for the script, unless it is 'import'ed into another +# script. +# +if __name__ == '__main__': + print 'Start!', time.strftime('%H:%M:%S', time.localtime()) + EdkLogger.Initialize() + EdkLogger.SetLevel(EdkLogger.QUIET) + + W = os.getenv('WORKSPACE') + Ewb = WorkspaceBuild('Nt32Pkg/Nt32Pkg.dsc', W) + Ewb.GenBuildDatabase({('PcdDevicePathSupportDevicePathFromText', 'gEfiMdeModulePkgTokenSpaceGuid') : 'KKKKKKKKKKKKKKKKKKKKK'}, ['Test.Inf']) + print 'Done!', time.strftime('%H:%M:%S', time.localtime()) + Ewb.ShowWorkspaceBuild() diff --git a/BaseTools/Source/Python/Common/EdkLogger.py b/BaseTools/Source/Python/Common/EdkLogger.py new file mode 100644 index 0000000000..ce4cfa14bb --- /dev/null +++ b/BaseTools/Source/Python/Common/EdkLogger.py @@ -0,0 +1,269 @@ +## @file +# This file implements the log mechanism for Python tools. +# +# Copyright (c) 2007, 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. +# + +## Import modules +import sys, os, logging +import traceback +from BuildToolError import * + +## Log level constants +DEBUG_0 = 1 +DEBUG_1 = 2 +DEBUG_2 = 3 +DEBUG_3 = 4 +DEBUG_4 = 5 +DEBUG_5 = 6 +DEBUG_6 = 7 +DEBUG_7 = 8 +DEBUG_8 = 9 +DEBUG_9 = 10 +VERBOSE = 15 +INFO = 20 +WARN = 30 +QUIET = 40 +ERROR = 50 + +IsRaiseError = True + +# Tool name +_ToolName = os.path.basename(sys.argv[0]) + +# For validation purpose +_LogLevels = [DEBUG_0, DEBUG_1, DEBUG_2, DEBUG_3, DEBUG_4, DEBUG_5, DEBUG_6, DEBUG_7, DEBUG_8, DEBUG_9, VERBOSE, WARN, INFO, ERROR, QUIET] + +# For DEBUG level (All DEBUG_0~9 are applicable) +_DebugLogger = logging.getLogger("tool_debug") +_DebugFormatter = logging.Formatter("[%(asctime)s.%(msecs)d]: %(message)s", datefmt="%H:%M:%S") + +# For VERBOSE, INFO, WARN level +_InfoLogger = logging.getLogger("tool_info") +_InfoFormatter = logging.Formatter("%(message)s") + +# For ERROR level +_ErrorLogger = logging.getLogger("tool_error") +_ErrorFormatter = logging.Formatter("%(message)s") + +# String templates for ERROR/WARN/DEBUG log message +_ErrorMessageTemplate = '\n\n%(tool)s...\n%(file)s(%(line)s): error %(errorcode)04X: %(msg)s\n\t%(extra)s' +_ErrorMessageTemplateWithoutFile = '\n\n%(tool)s...\n : error %(errorcode)04X: %(msg)s\n\t%(extra)s' +_WarningMessageTemplate = '%(tool)s...\n%(file)s(%(line)s): warning: %(msg)s' +_WarningMessageTemplateWithoutFile = '%(tool)s: : warning: %(msg)s' +_DebugMessageTemplate = '%(file)s(%(line)s): debug: \n %(msg)s' + +# +# Flag used to take WARN as ERROR. +# By default, only ERROR message will break the tools execution. +# +_WarningAsError = False + +## Log debug message +# +# @param Level DEBUG level (DEBUG0~9) +# @param Message Debug information +# @param ExtraData More information associated with "Message" +# +def debug(Level, Message, ExtraData=None): + if _DebugLogger.level > Level: + return + if Level > DEBUG_9: + return + + # Find out the caller method information + CallerStack = traceback.extract_stack()[-2] + TemplateDict = { + "file" : CallerStack[0], + "line" : CallerStack[1], + "msg" : Message, + } + + if ExtraData != None: + LogText = _DebugMessageTemplate % TemplateDict + "\n %s" % ExtraData + else: + LogText = _DebugMessageTemplate % TemplateDict + + _DebugLogger.log(Level, LogText) + +## Log verbose message +# +# @param Message Verbose information +# +def verbose(Message): + return _InfoLogger.log(VERBOSE, Message) + +## Log warning message +# +# Warning messages are those which might be wrong but won't fail the tool. +# +# @param ToolName The name of the tool. If not given, the name of caller +# method will be used. +# @param Message Warning information +# @param File The name of file which caused the warning. +# @param Line The line number in the "File" which caused the warning. +# @param ExtraData More information associated with "Message" +# +def warn(ToolName, Message, File=None, Line=None, ExtraData=None): + if _InfoLogger.level > WARN: + return + + # if no tool name given, use caller's source file name as tool name + if ToolName == None or ToolName == "": + ToolName = os.path.basename(traceback.extract_stack()[-2][0]) + + if Line == None: + Line = "..." + else: + Line = "%d" % Line + + TemplateDict = { + "tool" : ToolName, + "file" : File, + "line" : Line, + "msg" : Message, + } + + if File != None: + LogText = _WarningMessageTemplate % TemplateDict + else: + LogText = _WarningMessageTemplateWithoutFile % TemplateDict + + if ExtraData != None: + LogText += "\n %s" % ExtraData + + _InfoLogger.log(WARN, LogText) + + # Raise an execption if indicated + if _WarningAsError == True: + raise FatalError(WARNING_AS_ERROR) + +## Log INFO message +info = _InfoLogger.info + +## Log ERROR message +# +# Once an error messages is logged, the tool's execution will be broken by raising +# an execption. If you don't want to break the execution later, you can give +# "RaiseError" with "False" value. +# +# @param ToolName The name of the tool. If not given, the name of caller +# method will be used. +# @param ErrorCode The error code +# @param Message Warning information +# @param File The name of file which caused the error. +# @param Line The line number in the "File" which caused the warning. +# @param ExtraData More information associated with "Message" +# @param RaiseError Raise an exception to break the tool's executuion if +# it's True. This is the default behavior. +# +def error(ToolName, ErrorCode, Message=None, File=None, Line=None, ExtraData=None, RaiseError=IsRaiseError): + if Line == None: + Line = "..." + else: + Line = "%d" % Line + + if Message == None: + if ErrorCode in gErrorMessage: + Message = gErrorMessage[ErrorCode] + else: + Message = gErrorMessage[UNKNOWN_ERROR] + + if ExtraData == None: + ExtraData = "" + + TemplateDict = { + "tool" : _ToolName, + "file" : File, + "line" : Line, + "errorcode" : ErrorCode, + "msg" : Message, + "extra" : ExtraData + } + + if File != None: + LogText = _ErrorMessageTemplate % TemplateDict + else: + LogText = _ErrorMessageTemplateWithoutFile % TemplateDict + + _ErrorLogger.log(ERROR, LogText) + if RaiseError: + raise FatalError(ErrorCode) + +# Log information which should be always put out +quiet = _ErrorLogger.error + +## Initialize log system +def Initialize(): + # + # Since we use different format to log different levels of message into different + # place (stdout or stderr), we have to use different "Logger" objects to do this. + # + # For DEBUG level (All DEBUG_0~9 are applicable) + _DebugLogger.setLevel(INFO) + _DebugChannel = logging.StreamHandler(sys.stdout) + _DebugChannel.setFormatter(_DebugFormatter) + _DebugLogger.addHandler(_DebugChannel) + + # For VERBOSE, INFO, WARN level + _InfoLogger.setLevel(INFO) + _InfoChannel = logging.StreamHandler(sys.stdout) + _InfoChannel.setFormatter(_InfoFormatter) + _InfoLogger.addHandler(_InfoChannel) + + # For ERROR level + _ErrorLogger.setLevel(INFO) + _ErrorCh = logging.StreamHandler(sys.stderr) + _ErrorCh.setFormatter(_ErrorFormatter) + _ErrorLogger.addHandler(_ErrorCh) + +## Set log level +# +# @param Level One of log level in _LogLevel +def SetLevel(Level): + if Level not in _LogLevels: + info("Not supported log level (%d). Use default level instead." % Level) + Level = INFO + _DebugLogger.setLevel(Level) + _InfoLogger.setLevel(Level) + _ErrorLogger.setLevel(Level) + +## Get current log level +def GetLevel(): + return _InfoLogger.getEffectiveLevel() + +## Raise up warning as error +def SetWarningAsError(): + global _WarningAsError + _WarningAsError = True + +## Specify a file to store the log message as well as put on console +# +# @param LogFile The file path used to store the log message +# +def SetLogFile(LogFile): + if os.path.exists(LogFile): + os.remove(LogFile) + + _Ch = logging.FileHandler(LogFile) + _Ch.setFormatter(_DebugFormatter) + _DebugLogger.addHandler(_Ch) + + _Ch= logging.FileHandler(LogFile) + _Ch.setFormatter(_InfoFormatter) + _InfoLogger.addHandler(_Ch) + + _Ch = logging.FileHandler(LogFile) + _Ch.setFormatter(_ErrorFormatter) + _ErrorLogger.addHandler(_Ch) + +if __name__ == '__main__': + pass + diff --git a/BaseTools/Source/Python/Common/FdfClassObject.py b/BaseTools/Source/Python/Common/FdfClassObject.py new file mode 100644 index 0000000000..e0df1c20c2 --- /dev/null +++ b/BaseTools/Source/Python/Common/FdfClassObject.py @@ -0,0 +1,116 @@ +## @file +# This file is used to define each component of FDF file +# +# Copyright (c) 2008, 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. +# + +## +# Import Modules +# +from FdfParserLite import FdfParser +from Table.TableFdf import TableFdf +from CommonDataClass.DataClass import MODEL_FILE_FDF, MODEL_PCD, MODEL_META_DATA_COMPONENT +from String import NormPath + +## FdfObject +# +# This class defined basic Fdf object which is used by inheriting +# +# @param object: Inherited from object class +# +class FdfObject(object): + def __init__(self): + object.__init__() + +## Fdf +# +# This class defined the structure used in Fdf object +# +# @param FdfObject: Inherited from FdfObject class +# @param Filename: Input value for Ffilename of Fdf file, default is None +# @param WorkspaceDir: Input value for current workspace directory, default is None +# +class Fdf(FdfObject): + def __init__(self, Filename = None, IsToDatabase = False, WorkspaceDir = None, Database = None): + self.WorkspaceDir = WorkspaceDir + self.IsToDatabase = IsToDatabase + + self.Cur = Database.Cur + self.TblFile = Database.TblFile + self.TblFdf = Database.TblFdf + self.FileID = -1 + self.FileList = {} + + # + # Load Fdf file if filename is not None + # + if Filename != None: + self.LoadFdfFile(Filename) + + # + # Insert a FDF file record into database + # + def InsertFile(self, Filename): + FileID = -1 + Filename = NormPath(Filename) + if Filename not in self.FileList: + FileID = self.TblFile.InsertFile(Filename, MODEL_FILE_FDF) + self.FileList[Filename] = FileID + + return self.FileList[Filename] + + + ## Load Fdf file + # + # Load the file if it exists + # + # @param Filename: Input value for filename of Fdf file + # + def LoadFdfFile(self, Filename): + FileList = [] + # + # Parse Fdf file + # + Filename = NormPath(Filename) + Fdf = FdfParser(Filename) + Fdf.ParseFile() + + # + # Insert inf file and pcd information + # + if self.IsToDatabase: + (Model, Value1, Value2, Value3, Arch, BelongsToItem, BelongsToFile, StartLine, StartColumn, EndLine, EndColumn, Enabled) = \ + (0, '', '', '', 'COMMON', -1, -1, -1, -1, -1, -1, 0) + for Index in range(0, len(Fdf.Profile.PcdDict)): + pass + for Key in Fdf.Profile.PcdDict.keys(): + Model = MODEL_PCD + Value1 = '' + Value2 = ".".join((Key[1], Key[0])) + FileName = Fdf.Profile.PcdFileLineDict[Key][0] + StartLine = Fdf.Profile.PcdFileLineDict[Key][1] + BelongsToFile = self.InsertFile(FileName) + self.TblFdf.Insert(Model, Value1, Value2, Value3, Arch, BelongsToItem, BelongsToFile, StartLine, StartColumn, EndLine, EndColumn, Enabled) + for Index in range(0, len(Fdf.Profile.InfList)): + Model = MODEL_META_DATA_COMPONENT + Value1 = Fdf.Profile.InfList[Index] + Value2 = '' + FileName = Fdf.Profile.InfFileLineList[Index][0] + StartLine = Fdf.Profile.InfFileLineList[Index][1] + BelongsToFile = self.InsertFile(FileName) + self.TblFdf.Insert(Model, Value1, Value2, Value3, Arch, BelongsToItem, BelongsToFile, StartLine, StartColumn, EndLine, EndColumn, Enabled) + +## +# +# This acts like the main() function for the script, unless it is 'import'ed into another +# script. +# +if __name__ == '__main__': + pass diff --git a/BaseTools/Source/Python/Common/FdfParserLite.py b/BaseTools/Source/Python/Common/FdfParserLite.py new file mode 100644 index 0000000000..59006fa5c5 --- /dev/null +++ b/BaseTools/Source/Python/Common/FdfParserLite.py @@ -0,0 +1,3603 @@ +## @file +# parse FDF file +# +# Copyright (c) 2007, 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. +# + +## +# Import Modules +# +import re +import os + +import CommonDataClass.FdfClass + +##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_SINGLE_QUOTE '\'' +##define T_CHAR_STAR '*' +##define T_CHAR_HASH '#' + +(T_CHAR_SPACE, T_CHAR_NULL, T_CHAR_CR, T_CHAR_TAB, T_CHAR_LF, T_CHAR_SLASH, \ +T_CHAR_BACKSLASH, T_CHAR_DOUBLE_QUOTE, T_CHAR_SINGLE_QUOTE, T_CHAR_STAR, T_CHAR_HASH) = \ +(' ', '\0', '\r', '\t', '\n', '/', '\\', '\"', '\'', '*', '#') + +SEPERATOR_TUPLE = ('=', '|', ',', '{', '}') + +IncludeFileList = [] +# Macro passed from command line, which has greatest priority and can NOT be overridden by those in FDF +InputMacroDict = {} +# All Macro values when parsing file, not replace existing Macro +AllMacroList = [] + +def GetRealFileLine (File, Line): + + InsertedLines = 0 + for Profile in IncludeFileList: + if Line >= Profile.InsertStartLineNumber and Line < Profile.InsertStartLineNumber + Profile.InsertAdjust + len(Profile.FileLinesList): + return (Profile.FileName, Line - Profile.InsertStartLineNumber + 1) + if Line >= Profile.InsertStartLineNumber + Profile.InsertAdjust + len(Profile.FileLinesList): + InsertedLines += Profile.InsertAdjust + len(Profile.FileLinesList) + + return (File, Line - InsertedLines) + +## The exception class that used to report error messages when parsing FDF +# +# Currently the "ToolName" is set to be "FDF Parser". +# +class Warning (Exception): + ## The constructor + # + # @param self The object pointer + # @param Str The message to record + # @param File The FDF name + # @param Line The Line number that error occurs + # + def __init__(self, Str, File = None, Line = None): + + FileLineTuple = GetRealFileLine(File, Line) + self.FileName = FileLineTuple[0] + self.LineNumber = FileLineTuple[1] + self.message = Str + str(self.LineNumber) + self.ToolName = 'FDF Parser' + +## The MACRO class that used to record macro value data when parsing include file +# +# +class MacroProfile : + ## The constructor + # + # @param self The object pointer + # @param FileName The file that to be parsed + # + def __init__(self, FileName, Line): + self.FileName = FileName + self.DefinedAtLine = Line + self.MacroName = None + self.MacroValue = None + +## The Include file content class that used to record file data when parsing include file +# +# May raise Exception when opening file. +# +class IncludeFileProfile : + ## The constructor + # + # @param self The object pointer + # @param FileName The file that to be parsed + # + def __init__(self, FileName): + self.FileName = FileName + self.FileLinesList = [] + try: + fsock = open(FileName, "rb", 0) + try: + self.FileLinesList = fsock.readlines() + finally: + fsock.close() + + except IOError: + raise Warning("Error when opening file %s" % FileName) + + self.InsertStartLineNumber = None + self.InsertAdjust = 0 + +## The FDF content class that used to record file data when parsing FDF +# +# May raise Exception when opening file. +# +class FileProfile : + ## The constructor + # + # @param self The object pointer + # @param FileName The file that to be parsed + # + def __init__(self, FileName): + self.FileLinesList = [] + try: + fsock = open(FileName, "rb", 0) + try: + self.FileLinesList = fsock.readlines() + finally: + fsock.close() + + except IOError: + raise Warning("Error when opening file %s" % FileName) + + self.PcdDict = {} + self.InfList = [] + + self.PcdFileLineDict = {} + self.InfFileLineList = [] + + self.FdDict = {} + self.FvDict = {} + self.CapsuleList = [] +# self.VtfList = [] +# self.RuleDict = {} + +## The syntax parser for FDF +# +# PreprocessFile method should be called prior to ParseFile +# CycleReferenceCheck method can detect cycles in FDF contents +# +# GetNext*** procedures mean these procedures will get next token first, then make judgement. +# Get*** procedures mean these procedures will make judgement on current token only. +# +class FdfParser(object): + ## The constructor + # + # @param self The object pointer + # @param FileName The file that to be parsed + # + def __init__(self, FileName): + self.Profile = FileProfile(FileName) + self.FileName = FileName + self.CurrentLineNumber = 1 + self.CurrentOffsetWithinLine = 0 + self.CurrentFdName = None + self.CurrentFvName = None + self.__Token = "" + self.__SkippedChars = "" + + self.__WipeOffArea = [] + + ## __IsWhiteSpace() method + # + # Whether char at current FileBufferPos is whitespace + # + # @param self The object pointer + # @param Char The char to test + # @retval True The char is a kind of white space + # @retval False The char is NOT a kind of white space + # + def __IsWhiteSpace(self, Char): + if Char in (T_CHAR_NULL, T_CHAR_CR, T_CHAR_SPACE, T_CHAR_TAB, T_CHAR_LF): + return True + else: + return False + + ## __SkipWhiteSpace() method + # + # Skip white spaces from current char, return number of chars skipped + # + # @param self The object pointer + # @retval Count The number of chars skipped + # + def __SkipWhiteSpace(self): + Count = 0 + while not self.__EndOfFile(): + Count += 1 + if self.__CurrentChar() in (T_CHAR_NULL, T_CHAR_CR, T_CHAR_LF, T_CHAR_SPACE, T_CHAR_TAB): + self.__SkippedChars += str(self.__CurrentChar()) + self.__GetOneChar() + + else: + Count = Count - 1 + return Count + + ## __EndOfFile() method + # + # Judge current buffer pos is at file end + # + # @param self The object pointer + # @retval True Current File buffer position is at file end + # @retval False Current File buffer position is NOT at file end + # + def __EndOfFile(self): + NumberOfLines = len(self.Profile.FileLinesList) + SizeOfLastLine = len(self.Profile.FileLinesList[-1]) + if self.CurrentLineNumber == NumberOfLines and self.CurrentOffsetWithinLine >= SizeOfLastLine - 1: + return True + elif self.CurrentLineNumber > NumberOfLines: + return True + else: + return False + + ## __EndOfLine() method + # + # Judge current buffer pos is at line end + # + # @param self The object pointer + # @retval True Current File buffer position is at line end + # @retval False Current File buffer position is NOT at line end + # + def __EndOfLine(self): + if self.CurrentLineNumber > len(self.Profile.FileLinesList): + return True + SizeOfCurrentLine = len(self.Profile.FileLinesList[self.CurrentLineNumber - 1]) + if self.CurrentOffsetWithinLine >= SizeOfCurrentLine: + return True + else: + return False + + ## Rewind() method + # + # Reset file data buffer to the initial state + # + # @param self The object pointer + # + def Rewind(self): + self.CurrentLineNumber = 1 + self.CurrentOffsetWithinLine = 0 + + ## __UndoOneChar() method + # + # Go back one char in the file buffer + # + # @param self The object pointer + # @retval True Successfully go back one char + # @retval False Not able to go back one char as file beginning reached + # + def __UndoOneChar(self): + + if self.CurrentLineNumber == 1 and self.CurrentOffsetWithinLine == 0: + return False + elif self.CurrentOffsetWithinLine == 0: + self.CurrentLineNumber -= 1 + self.CurrentOffsetWithinLine = len(self.__CurrentLine()) - 1 + else: + self.CurrentOffsetWithinLine -= 1 + return True + + ## __GetOneChar() method + # + # Move forward one char in the file buffer + # + # @param self The object pointer + # + def __GetOneChar(self): + if self.CurrentOffsetWithinLine == len(self.Profile.FileLinesList[self.CurrentLineNumber - 1]) - 1: + self.CurrentLineNumber += 1 + self.CurrentOffsetWithinLine = 0 + else: + self.CurrentOffsetWithinLine += 1 + + ## __CurrentChar() method + # + # Get the char pointed to by the file buffer pointer + # + # @param self The object pointer + # @retval Char Current char + # + def __CurrentChar(self): + return self.Profile.FileLinesList[self.CurrentLineNumber - 1][self.CurrentOffsetWithinLine] + + ## __NextChar() method + # + # Get the one char pass the char pointed to by the file buffer pointer + # + # @param self The object pointer + # @retval Char Next char + # + def __NextChar(self): + if self.CurrentOffsetWithinLine == len(self.Profile.FileLinesList[self.CurrentLineNumber - 1]) - 1: + return self.Profile.FileLinesList[self.CurrentLineNumber][0] + else: + return self.Profile.FileLinesList[self.CurrentLineNumber - 1][self.CurrentOffsetWithinLine + 1] + + ## __SetCurrentCharValue() method + # + # Modify the value of current char + # + # @param self The object pointer + # @param Value The new value of current char + # + def __SetCurrentCharValue(self, Value): + self.Profile.FileLinesList[self.CurrentLineNumber - 1][self.CurrentOffsetWithinLine] = Value + + ## __CurrentLine() method + # + # Get the list that contains current line contents + # + # @param self The object pointer + # @retval List current line contents + # + def __CurrentLine(self): + return self.Profile.FileLinesList[self.CurrentLineNumber - 1] + + def __StringToList(self): + self.Profile.FileLinesList = [list(s) for s in self.Profile.FileLinesList] + self.Profile.FileLinesList[-1].append(' ') + + def __ReplaceMacros(self, Str, File, Line): + MacroEnd = 0 + while Str.find('$(', MacroEnd) >= 0: + MacroStart = Str.find('$(', MacroEnd) + if Str.find(')', MacroStart) > 0: + MacroEnd = Str.find(')', MacroStart) + Name = Str[MacroStart + 2 : MacroEnd] + Value = None + if Name in InputMacroDict: + Value = InputMacroDict[Name] + + else: + for Profile in AllMacroList: + if Profile.FileName == File and Profile.MacroName == Name and Profile.DefinedAtLine <= Line: + Value = Profile.MacroValue + + if Value != None: + Str = Str.replace('$(' + Name + ')', Value) + MacroEnd = MacroStart + len(Value) + + else: + raise Warning("Macro not complete At Line ", self.FileName, self.CurrentLineNumber) + return Str + + def __ReplaceFragment(self, StartPos, EndPos, Value = ' '): + if StartPos[0] == EndPos[0]: + Offset = StartPos[1] + while Offset <= EndPos[1]: + self.Profile.FileLinesList[StartPos[0]][Offset] = Value + Offset += 1 + return + + Offset = StartPos[1] + while self.Profile.FileLinesList[StartPos[0]][Offset] not in ('\r', '\n'): + self.Profile.FileLinesList[StartPos[0]][Offset] = Value + Offset += 1 + + Line = StartPos[0] + while Line < EndPos[0]: + Offset = 0 + while self.Profile.FileLinesList[Line][Offset] not in ('\r', '\n'): + self.Profile.FileLinesList[Line][Offset] = Value + Offset += 1 + Line += 1 + + Offset = 0 + while Offset <= EndPos[1]: + self.Profile.FileLinesList[EndPos[0]][Offset] = Value + Offset += 1 + + + ## PreprocessFile() method + # + # Preprocess file contents, replace comments with spaces. + # In the end, rewind the file buffer pointer to the beginning + # BUGBUG: No !include statement processing contained in this procedure + # !include statement should be expanded at the same FileLinesList[CurrentLineNumber - 1] + # + # @param self The object pointer + # + def PreprocessFile(self): + + self.Rewind() + InComment = False + DoubleSlashComment = False + HashComment = False + # HashComment in quoted string " " is ignored. + InString = False + + while not self.__EndOfFile(): + + if self.__CurrentChar() == T_CHAR_DOUBLE_QUOTE and not InComment: + InString = not InString + # meet new line, then no longer in a comment for // and '#' + if self.__CurrentChar() == T_CHAR_LF: + self.CurrentLineNumber += 1 + self.CurrentOffsetWithinLine = 0 + if InComment and DoubleSlashComment: + InComment = False + DoubleSlashComment = False + if InComment and HashComment: + InComment = False + HashComment = False + # check for */ comment end + elif InComment and not DoubleSlashComment and not HashComment and self.__CurrentChar() == T_CHAR_STAR and self.__NextChar() == T_CHAR_SLASH: + self.__SetCurrentCharValue(T_CHAR_SPACE) + self.__GetOneChar() + self.__SetCurrentCharValue(T_CHAR_SPACE) + self.__GetOneChar() + InComment = False + # set comments to spaces + elif InComment: + self.__SetCurrentCharValue(T_CHAR_SPACE) + self.__GetOneChar() + # check for // comment + elif self.__CurrentChar() == T_CHAR_SLASH and self.__NextChar() == T_CHAR_SLASH and not self.__EndOfLine(): + InComment = True + DoubleSlashComment = True + # check for '#' comment + elif self.__CurrentChar() == T_CHAR_HASH and not self.__EndOfLine() and not InString: + InComment = True + HashComment = True + # check for /* comment start + elif self.__CurrentChar() == T_CHAR_SLASH and self.__NextChar() == T_CHAR_STAR: + self.__SetCurrentCharValue( T_CHAR_SPACE) + self.__GetOneChar() + self.__SetCurrentCharValue( T_CHAR_SPACE) + self.__GetOneChar() + InComment = True + else: + self.__GetOneChar() + + # restore from ListOfList to ListOfString + self.Profile.FileLinesList = ["".join(list) for list in self.Profile.FileLinesList] + self.Rewind() + + ## PreprocessIncludeFile() method + # + # Preprocess file contents, replace !include statements with file contents. + # In the end, rewind the file buffer pointer to the beginning + # + # @param self The object pointer + # + def PreprocessIncludeFile(self): + + while self.__GetNextToken(): + + if self.__Token == '!include': + IncludeLine = self.CurrentLineNumber + IncludeOffset = self.CurrentOffsetWithinLine - len('!include') + if not self.__GetNextToken(): + raise Warning("expected include file name At Line ", self.FileName, self.CurrentLineNumber) + IncFileName = self.__Token + if not os.path.isabs(IncFileName): + if IncFileName.startswith('$(WORKSPACE)'): + Str = IncFileName.replace('$(WORKSPACE)', os.environ.get('WORKSPACE')) + if os.path.exists(Str): + if not os.path.isabs(Str): + Str = os.path.abspath(Str) + IncFileName = Str + else: + # file is in the same dir with FDF file + FullFdf = self.FileName + if not os.path.isabs(self.FileName): + FullFdf = os.path.join(os.environ.get('WORKSPACE'), self.FileName) + + IncFileName = os.path.join(os.path.dirname(FullFdf), IncFileName) + + if not os.path.exists(os.path.normpath(IncFileName)): + raise Warning("Include file not exists At Line ", self.FileName, self.CurrentLineNumber) + + IncFileProfile = IncludeFileProfile(os.path.normpath(IncFileName)) + + CurrentLine = self.CurrentLineNumber + CurrentOffset = self.CurrentOffsetWithinLine + # list index of the insertion, note that line number is 'CurrentLine + 1' + InsertAtLine = CurrentLine + IncFileProfile.InsertStartLineNumber = InsertAtLine + 1 + # deal with remaining portions after "!include filename", if exists. + if self.__GetNextToken(): + if self.CurrentLineNumber == CurrentLine: + RemainingLine = self.__CurrentLine()[CurrentOffset:] + self.Profile.FileLinesList.insert(self.CurrentLineNumber, RemainingLine) + IncFileProfile.InsertAdjust += 1 + self.CurrentLineNumber += 1 + self.CurrentOffsetWithinLine = 0 + + for Line in IncFileProfile.FileLinesList: + self.Profile.FileLinesList.insert(InsertAtLine, Line) + self.CurrentLineNumber += 1 + InsertAtLine += 1 + + IncludeFileList.append(IncFileProfile) + + # comment out the processed include file statement + TempList = list(self.Profile.FileLinesList[IncludeLine - 1]) + TempList.insert(IncludeOffset, '#') + self.Profile.FileLinesList[IncludeLine - 1] = ''.join(TempList) + + self.Rewind() + + ## PreprocessIncludeFile() method + # + # Preprocess file contents, replace !include statements with file contents. + # In the end, rewind the file buffer pointer to the beginning + # + # @param self The object pointer + # + def PreprocessConditionalStatement(self): + # IfList is a stack of if branches with elements of list [Pos, CondSatisfied, BranchDetermined] + IfList = [] + while self.__GetNextToken(): + if self.__Token == 'DEFINE': + DefineLine = self.CurrentLineNumber - 1 + DefineOffset = self.CurrentOffsetWithinLine - len('DEFINE') + if not self.__GetNextToken(): + raise Warning("expected Macro name At Line ", self.FileName, self.CurrentLineNumber) + Macro = self.__Token + if not self.__IsToken( "="): + raise Warning("expected '=' At Line ", self.FileName, self.CurrentLineNumber) + + if not self.__GetNextToken(): + raise Warning("expected value At Line ", self.FileName, self.CurrentLineNumber) + + if self.__GetStringData(): + pass + Value = self.__Token + if not Macro in InputMacroDict: + FileLineTuple = GetRealFileLine(self.FileName, DefineLine + 1) + MacProfile = MacroProfile(FileLineTuple[0], FileLineTuple[1]) + MacProfile.MacroName = Macro + MacProfile.MacroValue = Value + AllMacroList.append(MacProfile) + self.__WipeOffArea.append(((DefineLine, DefineOffset), (self.CurrentLineNumber - 1, self.CurrentOffsetWithinLine - 1))) + + elif self.__Token in ('!ifdef', '!ifndef', '!if'): + IfStartPos = (self.CurrentLineNumber - 1, self.CurrentOffsetWithinLine - len(self.__Token)) + IfList.append([IfStartPos, None, None]) + CondLabel = self.__Token + + if not self.__GetNextToken(): + raise Warning("expected Macro name At Line ", self.FileName, self.CurrentLineNumber) + MacroName = self.__Token + NotFlag = False + if MacroName.startswith('!'): + NotFlag = True + MacroName = MacroName[1:] + + NotDefineFlag = False + if CondLabel == '!ifndef': + NotDefineFlag = True + if CondLabel == '!ifdef' or CondLabel == '!ifndef': + if NotFlag: + raise Warning("'NOT' operation not allowed for Macro name At Line ", self.FileName, self.CurrentLineNumber) + + if CondLabel == '!if': + + if not self.__GetNextOp(): + raise Warning("expected !endif At Line ", self.FileName, self.CurrentLineNumber) + + if self.__Token in ('!=', '==', '>', '<', '>=', '<='): + Op = self.__Token + if not self.__GetNextToken(): + raise Warning("expected value At Line ", self.FileName, self.CurrentLineNumber) + if self.__GetStringData(): + pass + MacroValue = self.__Token + ConditionSatisfied = self.__EvaluateConditional(MacroName, IfList[-1][0][0] + 1, Op, MacroValue) + if NotFlag: + ConditionSatisfied = not ConditionSatisfied + BranchDetermined = ConditionSatisfied + else: + self.CurrentOffsetWithinLine -= len(self.__Token) + ConditionSatisfied = self.__EvaluateConditional(MacroName, IfList[-1][0][0] + 1, None, 'Bool') + if NotFlag: + ConditionSatisfied = not ConditionSatisfied + BranchDetermined = ConditionSatisfied + IfList[-1] = [IfList[-1][0], ConditionSatisfied, BranchDetermined] + if ConditionSatisfied: + self.__WipeOffArea.append((IfList[-1][0], (self.CurrentLineNumber - 1, self.CurrentOffsetWithinLine - 1))) + + else: + ConditionSatisfied = self.__EvaluateConditional(MacroName, IfList[-1][0][0] + 1) + if NotDefineFlag: + ConditionSatisfied = not ConditionSatisfied + BranchDetermined = ConditionSatisfied + IfList[-1] = [IfList[-1][0], ConditionSatisfied, BranchDetermined] + if ConditionSatisfied: + self.__WipeOffArea.append((IfStartPos, (self.CurrentLineNumber - 1, self.CurrentOffsetWithinLine - 1))) + + elif self.__Token in ('!elseif', '!else'): + ElseStartPos = (self.CurrentLineNumber - 1, self.CurrentOffsetWithinLine - len(self.__Token)) + if len(IfList) <= 0: + raise Warning("Missing !if statement At Line ", self.FileName, self.CurrentLineNumber) + if IfList[-1][1]: + IfList[-1] = [ElseStartPos, False, True] + self.__WipeOffArea.append((ElseStartPos, (self.CurrentLineNumber - 1, self.CurrentOffsetWithinLine - 1))) + else: + self.__WipeOffArea.append((IfList[-1][0], ElseStartPos)) + IfList[-1] = [ElseStartPos, True, IfList[-1][2]] + if self.__Token == '!elseif': + if not self.__GetNextToken(): + raise Warning("expected Macro name At Line ", self.FileName, self.CurrentLineNumber) + MacroName = self.__Token + NotFlag = False + if MacroName.startswith('!'): + NotFlag = True + MacroName = MacroName[1:] + + if not self.__GetNextOp(): + raise Warning("expected !endif At Line ", self.FileName, self.CurrentLineNumber) + + if self.__Token in ('!=', '==', '>', '<', '>=', '<='): + Op = self.__Token + if not self.__GetNextToken(): + raise Warning("expected value At Line ", self.FileName, self.CurrentLineNumber) + if self.__GetStringData(): + pass + MacroValue = self.__Token + ConditionSatisfied = self.__EvaluateConditional(MacroName, IfList[-1][0][0] + 1, Op, MacroValue) + if NotFlag: + ConditionSatisfied = not ConditionSatisfied + + else: + self.CurrentOffsetWithinLine -= len(self.__Token) + ConditionSatisfied = self.__EvaluateConditional(MacroName, IfList[-1][0][0] + 1, None, 'Bool') + if NotFlag: + ConditionSatisfied = not ConditionSatisfied + + IfList[-1] = [IfList[-1][0], ConditionSatisfied, IfList[-1][2]] + + if IfList[-1][1]: + if IfList[-1][2]: + IfList[-1][1] = False + else: + IfList[-1][2] = True + self.__WipeOffArea.append((IfList[-1][0], (self.CurrentLineNumber - 1, self.CurrentOffsetWithinLine - 1))) + + + elif self.__Token == '!endif': + if IfList[-1][1]: + self.__WipeOffArea.append(((self.CurrentLineNumber - 1, self.CurrentOffsetWithinLine - len('!endif')), (self.CurrentLineNumber - 1, self.CurrentOffsetWithinLine - 1))) + else: + self.__WipeOffArea.append((IfList[-1][0], (self.CurrentLineNumber - 1, self.CurrentOffsetWithinLine - 1))) + + IfList.pop() + + + if len(IfList) > 0: + raise Warning("Missing !endif At Line ", self.FileName, self.CurrentLineNumber) + self.Rewind() + + def __EvaluateConditional(self, Name, Line, Op = None, Value = None): + + FileLineTuple = GetRealFileLine(self.FileName, Line) + if Name in InputMacroDict: + MacroValue = InputMacroDict[Name] + if Op == None: + if Value == 'Bool' and MacroValue == None or MacroValue.upper() == 'FALSE': + return False + return True + elif Op == '!=': + if Value != MacroValue: + return True + else: + return False + elif Op == '==': + if Value == MacroValue: + return True + else: + return False + else: + if (self.__IsHex(Value) or Value.isdigit()) and (self.__IsHex(MacroValue) or (MacroValue != None and MacroValue.isdigit())): + InputVal = long(Value, 0) + MacroVal = long(MacroValue, 0) + if Op == '>': + if MacroVal > InputVal: + return True + else: + return False + elif Op == '>=': + if MacroVal >= InputVal: + return True + else: + return False + elif Op == '<': + if MacroVal < InputVal: + return True + else: + return False + elif Op == '<=': + if MacroVal <= InputVal: + return True + else: + return False + else: + return False + else: + raise Warning("Value %s is not a number At Line ", self.FileName, Line) + + for Profile in AllMacroList: + if Profile.FileName == FileLineTuple[0] and Profile.MacroName == Name and Profile.DefinedAtLine <= FileLineTuple[1]: + if Op == None: + if Value == 'Bool' and Profile.MacroValue == None or Profile.MacroValue.upper() == 'FALSE': + return False + return True + elif Op == '!=': + if Value != Profile.MacroValue: + return True + else: + return False + elif Op == '==': + if Value == Profile.MacroValue: + return True + else: + return False + else: + if (self.__IsHex(Value) or Value.isdigit()) and (self.__IsHex(Profile.MacroValue) or (Profile.MacroValue != None and Profile.MacroValue.isdigit())): + InputVal = long(Value, 0) + MacroVal = long(Profile.MacroValue, 0) + if Op == '>': + if MacroVal > InputVal: + return True + else: + return False + elif Op == '>=': + if MacroVal >= InputVal: + return True + else: + return False + elif Op == '<': + if MacroVal < InputVal: + return True + else: + return False + elif Op == '<=': + if MacroVal <= InputVal: + return True + else: + return False + else: + return False + else: + raise Warning("Value %s is not a number At Line ", self.FileName, Line) + + return False + + ## __IsToken() method + # + # Check whether input string is found from current char position along + # If found, the string value is put into self.__Token + # + # @param self The object pointer + # @param String The string to search + # @param IgnoreCase Indicate case sensitive/non-sensitive search, default is case sensitive + # @retval True Successfully find string, file buffer pointer moved forward + # @retval False Not able to find string, file buffer pointer not changed + # + def __IsToken(self, String, IgnoreCase = False): + self.__SkipWhiteSpace() + + # Only consider the same line, no multi-line token allowed + StartPos = self.CurrentOffsetWithinLine + index = -1 + if IgnoreCase: + index = self.__CurrentLine()[self.CurrentOffsetWithinLine : ].upper().find(String.upper()) + else: + index = self.__CurrentLine()[self.CurrentOffsetWithinLine : ].find(String) + if index == 0: + self.CurrentOffsetWithinLine += len(String) + self.__Token = self.__CurrentLine()[StartPos : self.CurrentOffsetWithinLine] + return True + return False + + ## __IsKeyword() method + # + # Check whether input keyword is found from current char position along, whole word only! + # If found, the string value is put into self.__Token + # + # @param self The object pointer + # @param Keyword The string to search + # @param IgnoreCase Indicate case sensitive/non-sensitive search, default is case sensitive + # @retval True Successfully find string, file buffer pointer moved forward + # @retval False Not able to find string, file buffer pointer not changed + # + def __IsKeyword(self, KeyWord, IgnoreCase = False): + self.__SkipWhiteSpace() + + # Only consider the same line, no multi-line token allowed + StartPos = self.CurrentOffsetWithinLine + index = -1 + if IgnoreCase: + index = self.__CurrentLine()[self.CurrentOffsetWithinLine : ].upper().find(KeyWord.upper()) + else: + index = self.__CurrentLine()[self.CurrentOffsetWithinLine : ].find(KeyWord) + if index == 0: + followingChar = self.__CurrentLine()[self.CurrentOffsetWithinLine + len(KeyWord)] + if not str(followingChar).isspace() and followingChar not in SEPERATOR_TUPLE: + return False + self.CurrentOffsetWithinLine += len(KeyWord) + self.__Token = self.__CurrentLine()[StartPos : self.CurrentOffsetWithinLine] + return True + return False + + ## __GetNextWord() method + # + # Get next C name from file lines + # If found, the string value is put into self.__Token + # + # @param self The object pointer + # @retval True Successfully find a C name string, file buffer pointer moved forward + # @retval False Not able to find a C name string, file buffer pointer not changed + # + def __GetNextWord(self): + self.__SkipWhiteSpace() + if self.__EndOfFile(): + return False + + TempChar = self.__CurrentChar() + StartPos = self.CurrentOffsetWithinLine + if (TempChar >= 'a' and TempChar <= 'z') or (TempChar >= 'A' and TempChar <= 'Z') or TempChar == '_': + self.__GetOneChar() + while not self.__EndOfLine(): + TempChar = self.__CurrentChar() + if (TempChar >= 'a' and TempChar <= 'z') or (TempChar >= 'A' and TempChar <= 'Z') \ + or (TempChar >= '0' and TempChar <= '9') or TempChar == '_' or TempChar == '-': + self.__GetOneChar() + + else: + break + + self.__Token = self.__CurrentLine()[StartPos : self.CurrentOffsetWithinLine] + return True + + return False + + ## __GetNextToken() method + # + # Get next token unit before a seperator + # If found, the string value is put into self.__Token + # + # @param self The object pointer + # @retval True Successfully find a token unit, file buffer pointer moved forward + # @retval False Not able to find a token unit, file buffer pointer not changed + # + def __GetNextToken(self): + # Skip leading spaces, if exist. + self.__SkipWhiteSpace() + if self.__EndOfFile(): + return False + # Record the token start position, the position of the first non-space char. + StartPos = self.CurrentOffsetWithinLine + StartLine = self.CurrentLineNumber + while not self.__EndOfLine(): + TempChar = self.__CurrentChar() + # Try to find the end char that is not a space and not in seperator tuple. + # That is, when we got a space or any char in the tuple, we got the end of token. + if not str(TempChar).isspace() and TempChar not in SEPERATOR_TUPLE: + self.__GetOneChar() + # if we happen to meet a seperator as the first char, we must proceed to get it. + # That is, we get a token that is a seperator char. nomally it is the boundary of other tokens. + elif StartPos == self.CurrentOffsetWithinLine and TempChar in SEPERATOR_TUPLE: + self.__GetOneChar() + break + else: + break +# else: +# return False + + EndPos = self.CurrentOffsetWithinLine + if self.CurrentLineNumber != StartLine: + EndPos = len(self.Profile.FileLinesList[StartLine-1]) + self.__Token = self.Profile.FileLinesList[StartLine-1][StartPos : EndPos] + if StartPos != self.CurrentOffsetWithinLine: + return True + else: + return False + + def __GetNextOp(self): + # Skip leading spaces, if exist. + self.__SkipWhiteSpace() + if self.__EndOfFile(): + return False + # Record the token start position, the position of the first non-space char. + StartPos = self.CurrentOffsetWithinLine + while not self.__EndOfLine(): + TempChar = self.__CurrentChar() + # Try to find the end char that is not a space + if not str(TempChar).isspace(): + self.__GetOneChar() + else: + break + else: + return False + + if StartPos != self.CurrentOffsetWithinLine: + self.__Token = self.__CurrentLine()[StartPos : self.CurrentOffsetWithinLine] + return True + else: + return False + ## __GetNextGuid() method + # + # Get next token unit before a seperator + # If found, the GUID string is put into self.__Token + # + # @param self The object pointer + # @retval True Successfully find a registry format GUID, file buffer pointer moved forward + # @retval False Not able to find a registry format GUID, file buffer pointer not changed + # + def __GetNextGuid(self): + + if not self.__GetNextToken(): + return False + p = re.compile('[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}') + if p.match(self.__Token) != None: + return True + else: + self.__UndoToken() + return False + + ## __UndoToken() method + # + # Go back one token unit in file buffer + # + # @param self The object pointer + # + def __UndoToken(self): + self.__UndoOneChar() + while self.__CurrentChar().isspace(): + if not self.__UndoOneChar(): + self.__GetOneChar() + return + + + StartPos = self.CurrentOffsetWithinLine + CurrentLine = self.CurrentLineNumber + while CurrentLine == self.CurrentLineNumber: + + TempChar = self.__CurrentChar() + # Try to find the end char that is not a space and not in seperator tuple. + # That is, when we got a space or any char in the tuple, we got the end of token. + if not str(TempChar).isspace() and not TempChar in SEPERATOR_TUPLE: + if not self.__UndoOneChar(): + break + # if we happen to meet a seperator as the first char, we must proceed to get it. + # That is, we get a token that is a seperator char. nomally it is the boundary of other tokens. + elif StartPos == self.CurrentOffsetWithinLine and TempChar in SEPERATOR_TUPLE: + return + else: + break + + self.__GetOneChar() + + ## __HexDigit() method + # + # Whether char input is a Hex data bit + # + # @param self The object pointer + # @param TempChar The char to test + # @retval True The char is a Hex data bit + # @retval False The char is NOT a Hex data bit + # + def __HexDigit(self, TempChar): + if (TempChar >= 'a' and TempChar <= 'f') or (TempChar >= 'A' and TempChar <= 'F') \ + or (TempChar >= '0' and TempChar <= '9'): + return True + else: + return False + + def __IsHex(self, HexStr): + if not HexStr.upper().startswith("0X"): + return False + if len(self.__Token) <= 2: + return False + charList = [c for c in HexStr[2 : ] if not self.__HexDigit( c)] + if len(charList) == 0: + return True + else: + return False + ## __GetNextHexNumber() method + # + # Get next HEX data before a seperator + # If found, the HEX data is put into self.__Token + # + # @param self The object pointer + # @retval True Successfully find a HEX data, file buffer pointer moved forward + # @retval False Not able to find a HEX data, file buffer pointer not changed + # + def __GetNextHexNumber(self): + if not self.__GetNextToken(): + return False + if self.__IsHex(self.__Token): + return True + else: + self.__UndoToken() + return False + + ## __GetNextDecimalNumber() method + # + # Get next decimal data before a seperator + # If found, the decimal data is put into self.__Token + # + # @param self The object pointer + # @retval True Successfully find a decimal data, file buffer pointer moved forward + # @retval False Not able to find a decimal data, file buffer pointer not changed + # + def __GetNextDecimalNumber(self): + if not self.__GetNextToken(): + return False + if self.__Token.isdigit(): + return True + else: + self.__UndoToken() + return False + + ## __GetNextPcdName() method + # + # Get next PCD token space C name and PCD C name pair before a seperator + # If found, the decimal data is put into self.__Token + # + # @param self The object pointer + # @retval Tuple PCD C name and PCD token space C name pair + # + def __GetNextPcdName(self): + if not self.__GetNextWord(): + raise Warning("expected PcdTokenSpaceCName.PcdCName At Line ", self.FileName, self.CurrentLineNumber) + pcdTokenSpaceCName = self.__Token + + if not self.__IsToken( "."): + raise Warning("expected PcdTokenSpaceCName.PcdCName At Line ", self.FileName, self.CurrentLineNumber) + + if not self.__GetNextWord(): + raise Warning("expected PcdTokenSpaceCName.PcdCName At Line ", self.FileName, self.CurrentLineNumber) + pcdCName = self.__Token + + return (pcdCName, pcdTokenSpaceCName) + + ## __GetStringData() method + # + # Get string contents quoted in "" + # If found, the decimal data is put into self.__Token + # + # @param self The object pointer + # @retval True Successfully find a string data, file buffer pointer moved forward + # @retval False Not able to find a string data, file buffer pointer not changed + # + def __GetStringData(self): + if self.__Token.startswith("\"") or self.__Token.startswith("L\""): + self.__UndoToken() + self.__SkipToToken("\"") + currentLineNumber = self.CurrentLineNumber + + if not self.__SkipToToken("\""): + raise Warning("Missing Quote \" for String At Line ", self.FileName, self.CurrentLineNumber) + if currentLineNumber != self.CurrentLineNumber: + raise Warning("Missing Quote \" for String At Line ", self.FileName, self.CurrentLineNumber) + self.__Token = self.__SkippedChars.rstrip('\"') + return True + + elif self.__Token.startswith("\'") or self.__Token.startswith("L\'"): + self.__UndoToken() + self.__SkipToToken("\'") + currentLineNumber = self.CurrentLineNumber + + if not self.__SkipToToken("\'"): + raise Warning("Missing Quote \' for String At Line ", self.FileName, self.CurrentLineNumber) + if currentLineNumber != self.CurrentLineNumber: + raise Warning("Missing Quote \' for String At Line ", self.FileName, self.CurrentLineNumber) + self.__Token = self.__SkippedChars.rstrip('\'') + return True + + else: + return False + + ## __SkipToToken() method + # + # Search forward in file buffer for the string + # The skipped chars are put into self.__SkippedChars + # + # @param self The object pointer + # @param String The string to search + # @param IgnoreCase Indicate case sensitive/non-sensitive search, default is case sensitive + # @retval True Successfully find the string, file buffer pointer moved forward + # @retval False Not able to find the string, file buffer pointer not changed + # + def __SkipToToken(self, String, IgnoreCase = False): + StartPos = self.GetFileBufferPos() + + self.__SkippedChars = "" + while not self.__EndOfFile(): + index = -1 + if IgnoreCase: + index = self.__CurrentLine()[self.CurrentOffsetWithinLine : ].upper().find(String.upper()) + else: + index = self.__CurrentLine()[self.CurrentOffsetWithinLine : ].find(String) + if index == 0: + self.CurrentOffsetWithinLine += len(String) + self.__SkippedChars += String + return True + self.__SkippedChars += str(self.__CurrentChar()) + self.__GetOneChar() + + self.SetFileBufferPos( StartPos) + self.__SkippedChars = "" + return False + + ## GetFileBufferPos() method + # + # Return the tuple of current line and offset within the line + # + # @param self The object pointer + # @retval Tuple Line number and offset pair + # + def GetFileBufferPos(self): + return (self.CurrentLineNumber, self.CurrentOffsetWithinLine) + + ## SetFileBufferPos() method + # + # Restore the file buffer position + # + # @param self The object pointer + # @param Pos The new file buffer position + # + def SetFileBufferPos(self, Pos): + (self.CurrentLineNumber, self.CurrentOffsetWithinLine) = Pos + + ## ParseFile() method + # + # Parse the file profile buffer to extract fd, fv ... information + # Exception will be raised if syntax error found + # + # @param self The object pointer + # + def ParseFile(self): + + try: + self.__StringToList() + self.PreprocessFile() + self.PreprocessIncludeFile() + self.__StringToList() + self.PreprocessFile() + self.PreprocessConditionalStatement() + self.__StringToList() + for Pos in self.__WipeOffArea: + self.__ReplaceFragment(Pos[0], Pos[1]) + self.Profile.FileLinesList = ["".join(list) for list in self.Profile.FileLinesList] + + while self.__GetDefines(): + pass + + Index = 0 + while Index < len(self.Profile.FileLinesList): + FileLineTuple = GetRealFileLine(self.FileName, Index + 1) + self.Profile.FileLinesList[Index] = self.__ReplaceMacros(self.Profile.FileLinesList[Index], FileLineTuple[0], FileLineTuple[1]) + Index += 1 + + while self.__GetFd(): + pass + + while self.__GetFv(): + pass + + while self.__GetCapsule(): + pass + +# while self.__GetVtf(): +# pass +# +# while self.__GetRule(): +# pass + + + except Warning, X: + self.__UndoToken() + FileLineTuple = GetRealFileLine(self.FileName, self.CurrentLineNumber) + X.message += '\nGot Token: \"%s\" from File %s\n' % (self.__Token, FileLineTuple[0]) + \ + 'Previous Token: \"%s\" At line: %d, Offset Within Line: %d\n' \ + % (self.Profile.FileLinesList[self.CurrentLineNumber - 1][self.CurrentOffsetWithinLine :].rstrip('\n').rstrip('\r'), FileLineTuple[1], self.CurrentOffsetWithinLine) + raise + + ## __GetDefines() method + # + # Get Defines section contents and store its data into AllMacrosList + # + # @param self The object pointer + # @retval True Successfully find a Defines + # @retval False Not able to find a Defines + # + def __GetDefines(self): + + if not self.__GetNextToken(): + return False + + S = self.__Token.upper() + if S.startswith("[") and not S.startswith("[DEFINES"): + if not S.startswith("[FD.") and not S.startswith("[FV.") and not S.startswith("[CAPSULE.") \ + and not S.startswith("[VTF.") and not S.startswith("[RULE.") and not S.startswith("[OPTIONROM."): + raise Warning("Unknown section or section appear sequence error (The correct sequence should be [DEFINES], [FD.], [FV.], [Capsule.], [VTF.], [Rule.], [OptionRom.])", self.FileName, self.CurrentLineNumber) + self.__UndoToken() + return False + + self.__UndoToken() + if not self.__IsToken("[DEFINES", True): + FileLineTuple = GetRealFileLine(self.FileName, self.CurrentLineNumber) + #print 'Parsing String: %s in File %s, At line: %d, Offset Within Line: %d' \ + # % (self.Profile.FileLinesList[self.CurrentLineNumber - 1][self.CurrentOffsetWithinLine :], FileLineTuple[0], FileLineTuple[1], self.CurrentOffsetWithinLine) + raise Warning("expected [DEFINES", self.FileName, self.CurrentLineNumber) + + if not self.__IsToken( "]"): + raise Warning("expected ']'", self.FileName, self.CurrentLineNumber) + + while self.__GetNextWord(): + Macro = self.__Token + + if not self.__IsToken("="): + raise Warning("expected '='", self.FileName, self.CurrentLineNumber) + if not self.__GetNextToken() or self.__Token.startswith('['): + raise Warning("expected MACRO value", self.FileName, self.CurrentLineNumber) + Value = self.__Token + FileLineTuple = GetRealFileLine(self.FileName, self.CurrentLineNumber) + MacProfile = MacroProfile(FileLineTuple[0], FileLineTuple[1]) + MacProfile.MacroName = Macro + MacProfile.MacroValue = Value + AllMacroList.append(MacProfile) + + return False + + ## __GetFd() method + # + # Get FD section contents and store its data into FD dictionary of self.Profile + # + # @param self The object pointer + # @retval True Successfully find a FD + # @retval False Not able to find a FD + # + def __GetFd(self): + + if not self.__GetNextToken(): + return False + + S = self.__Token.upper() + if S.startswith("[") and not S.startswith("[FD."): + if not S.startswith("[FV.") and not S.startswith("[CAPSULE.") \ + and not S.startswith("[VTF.") and not S.startswith("[RULE."): + raise Warning("Unknown section At Line ", self.FileName, self.CurrentLineNumber) + self.__UndoToken() + return False + + self.__UndoToken() + if not self.__IsToken("[FD.", True): + FileLineTuple = GetRealFileLine(self.FileName, self.CurrentLineNumber) + print 'Parsing String: %s in File %s, At line: %d, Offset Within Line: %d' \ + % (self.Profile.FileLinesList[self.CurrentLineNumber - 1][self.CurrentOffsetWithinLine :], FileLineTuple[0], FileLineTuple[1], self.CurrentOffsetWithinLine) + raise Warning("expected [FD.] At Line ", self.FileName, self.CurrentLineNumber) + + FdName = self.__GetUiName() + self.CurrentFdName = FdName.upper() + + if not self.__IsToken( "]"): + raise Warning("expected ']' At Line ", self.FileName, self.CurrentLineNumber) + + FdObj = CommonDataClass.FdfClass.FDClassObject() + FdObj.FdUiName = self.CurrentFdName + self.Profile.FdDict[self.CurrentFdName] = FdObj + Status = self.__GetCreateFile(FdObj) + if not Status: + raise Warning("FD name error At Line ", self.FileName, self.CurrentLineNumber) + + if not self.__GetTokenStatements(FdObj): + return False + + self.__GetDefineStatements(FdObj) + + self.__GetSetStatements(FdObj) + + if not self.__GetRegionLayout(FdObj): + raise Warning("expected region layout At Line ", self.FileName, self.CurrentLineNumber) + + while self.__GetRegionLayout(FdObj): + pass + return True + + ## __GetUiName() method + # + # Return the UI name of a section + # + # @param self The object pointer + # @retval FdName UI name + # + def __GetUiName(self): + FdName = "" + if self.__GetNextWord(): + FdName = self.__Token + + return FdName + + ## __GetCreateFile() method + # + # Return the output file name of object + # + # @param self The object pointer + # @param Obj object whose data will be stored in file + # @retval FdName UI name + # + def __GetCreateFile(self, Obj): + + if self.__IsKeyword( "CREATE_FILE"): + if not self.__IsToken( "="): + raise Warning("expected '=' At Line ", self.FileName, self.CurrentLineNumber) + + if not self.__GetNextToken(): + raise Warning("expected file name At Line ", self.FileName, self.CurrentLineNumber) + + FileName = self.__Token + Obj.CreateFileName = FileName + + return True + + ## __GetTokenStatements() method + # + # Get token statements + # + # @param self The object pointer + # @param Obj for whom token statement is got + # @retval True Successfully find a token statement + # @retval False Not able to find a token statement + # + def __GetTokenStatements(self, Obj): + if not self.__IsKeyword( "BaseAddress"): + raise Warning("BaseAddress missing At Line ", self.FileName, self.CurrentLineNumber) + + if not self.__IsToken( "="): + raise Warning("expected '=' At Line ", self.FileName, self.CurrentLineNumber) + + if not self.__GetNextHexNumber(): + raise Warning("expected Hex base address At Line ", self.FileName, self.CurrentLineNumber) + + Obj.BaseAddress = self.__Token + + if self.__IsToken( "|"): + pcdPair = self.__GetNextPcdName() + Obj.BaseAddressPcd = pcdPair + self.Profile.PcdDict[pcdPair] = long(Obj.BaseAddress, 0) + FileLineTuple = GetRealFileLine(self.FileName, self.CurrentLineNumber) + self.Profile.PcdFileLineDict[pcdPair] = FileLineTuple + + if not self.__IsKeyword( "Size"): + raise Warning("Size missing At Line ", self.FileName, self.CurrentLineNumber) + + if not self.__IsToken( "="): + raise Warning("expected '=' At Line ", self.FileName, self.CurrentLineNumber) + + if not self.__GetNextHexNumber(): + raise Warning("expected Hex size At Line ", self.FileName, self.CurrentLineNumber) + + + Obj.Size = long(self.__Token, 0) + + if self.__IsToken( "|"): + pcdPair = self.__GetNextPcdName() + Obj.SizePcd = pcdPair + self.Profile.PcdDict[pcdPair] = Obj.Size + FileLineTuple = GetRealFileLine(self.FileName, self.CurrentLineNumber) + self.Profile.PcdFileLineDict[pcdPair] = FileLineTuple + + if not self.__IsKeyword( "ErasePolarity"): + raise Warning("ErasePolarity missing At Line ", self.FileName, self.CurrentLineNumber) + + if not self.__IsToken( "="): + raise Warning("expected '=' At Line ", self.FileName, self.CurrentLineNumber) + + if not self.__GetNextToken(): + raise Warning("expected Erase Polarity At Line ", self.FileName, self.CurrentLineNumber) + + if self.__Token != "1" and self.__Token != "0": + raise Warning("expected 1 or 0 Erase Polarity At Line ", self.FileName, self.CurrentLineNumber) + + Obj.ErasePolarity = self.__Token + + Status = self.__GetBlockStatements(Obj) + return Status + + ## __GetAddressStatements() method + # + # Get address statements + # + # @param self The object pointer + # @param Obj for whom address statement is got + # @retval True Successfully find + # @retval False Not able to find + # + def __GetAddressStatements(self, Obj): + + if self.__IsKeyword("BsBaseAddress"): + if not self.__IsToken( "="): + raise Warning("expected '=' At Line ", self.FileName, self.CurrentLineNumber) + + if not self.__GetNextDecimalNumber() and not self.__GetNextHexNumber(): + raise Warning("expected address At Line ", self.FileName, self.CurrentLineNumber) + + BsAddress = long(self.__Token, 0) + Obj.BsBaseAddress = BsAddress + + if self.__IsKeyword("RtBaseAddress"): + if not self.__IsToken( "="): + raise Warning("expected '=' At Line ", self.FileName, self.CurrentLineNumber) + + if not self.__GetNextDecimalNumber() and not self.__GetNextHexNumber(): + raise Warning("expected address At Line ", self.FileName, self.CurrentLineNumber) + + RtAddress = long(self.__Token, 0) + Obj.RtBaseAddress = RtAddress + + ## __GetBlockStatements() method + # + # Get block statements + # + # @param self The object pointer + # @param Obj for whom block statement is got + # @retval True Successfully find + # @retval False Not able to find + # + def __GetBlockStatements(self, Obj): + + if not self.__GetBlockStatement(Obj): + raise Warning("expected block statement At Line ", self.FileName, self.CurrentLineNumber) + + while self.__GetBlockStatement(Obj): + pass + return True + + ## __GetBlockStatement() method + # + # Get block statement + # + # @param self The object pointer + # @param Obj for whom block statement is got + # @retval True Successfully find + # @retval False Not able to find + # + def __GetBlockStatement(self, Obj): + if not self.__IsKeyword( "BlockSize"): + return False + + if not self.__IsToken( "="): + raise Warning("expected '=' At Line ", self.FileName, self.CurrentLineNumber) + + if not self.__GetNextHexNumber() and not self.__GetNextDecimalNumber(): + raise Warning("expected Hex block size At Line ", self.FileName, self.CurrentLineNumber) + + BlockSize = long(self.__Token, 0) + BlockSizePcd = None + if self.__IsToken( "|"): + PcdPair = self.__GetNextPcdName() + BlockSizePcd = PcdPair + self.Profile.PcdDict[PcdPair] = BlockSize + FileLineTuple = GetRealFileLine(self.FileName, self.CurrentLineNumber) + self.Profile.PcdFileLineDict[pcdPair] = FileLineTuple + + BlockNumber = None + if self.__IsKeyword( "NumBlocks"): + if not self.__IsToken( "="): + raise Warning("expected '=' At Line ", self.FileName, self.CurrentLineNumber) + + if not self.__GetNextDecimalNumber() and not self.__GetNextHexNumber(): + raise Warning("expected block numbers At Line ", self.FileName, self.CurrentLineNumber) + + BlockNumber = long(self.__Token, 0) + + Obj.BlockSizeList.append((BlockSize, BlockNumber, BlockSizePcd)) + return True + + ## __GetDefineStatements() method + # + # Get define statements + # + # @param self The object pointer + # @param Obj for whom define statement is got + # @retval True Successfully find + # @retval False Not able to find + # + def __GetDefineStatements(self, Obj): + while self.__GetDefineStatement( Obj): + pass + + ## __GetDefineStatement() method + # + # Get define statement + # + # @param self The object pointer + # @param Obj for whom define statement is got + # @retval True Successfully find + # @retval False Not able to find + # + def __GetDefineStatement(self, Obj): + if self.__IsKeyword("DEFINE"): + self.__GetNextToken() + Macro = self.__Token + if not self.__IsToken( "="): + raise Warning("expected '=' At Line ", self.FileName, self.CurrentLineNumber) + + if not self.__GetNextToken(): + raise Warning("expected value At Line ", self.FileName, self.CurrentLineNumber) + + Value = self.__Token + Macro = '$(' + Macro + ')' + Obj.DefineVarDict[Macro] = Value + return True + + return False + + ## __GetSetStatements() method + # + # Get set statements + # + # @param self The object pointer + # @param Obj for whom set statement is got + # @retval True Successfully find + # @retval False Not able to find + # + def __GetSetStatements(self, Obj): + while self.__GetSetStatement(Obj): + pass + + ## __GetSetStatement() method + # + # Get set statement + # + # @param self The object pointer + # @param Obj for whom set statement is got + # @retval True Successfully find + # @retval False Not able to find + # + def __GetSetStatement(self, Obj): + if self.__IsKeyword("SET"): + PcdPair = self.__GetNextPcdName() + + if not self.__IsToken( "="): + raise Warning("expected '=' At Line ", self.FileName, self.CurrentLineNumber) + + if not self.__GetNextToken(): + raise Warning("expected value At Line ", self.FileName, self.CurrentLineNumber) + + Value = self.__Token + if Value.startswith("{"): + # deal with value with {} + if not self.__SkipToToken( "}"): + raise Warning("expected '}' At Line ", self.FileName, self.CurrentLineNumber) + Value += self.__SkippedChars + + Obj.SetVarDict[PcdPair] = Value + self.Profile.PcdDict[PcdPair] = Value + FileLineTuple = GetRealFileLine(self.FileName, self.CurrentLineNumber) + self.Profile.PcdFileLineDict[PcdPair] = FileLineTuple + return True + + return False + + ## __GetRegionLayout() method + # + # Get region layout for FD + # + # @param self The object pointer + # @param Fd for whom region is got + # @retval True Successfully find + # @retval False Not able to find + # + def __GetRegionLayout(self, Fd): + if not self.__GetNextHexNumber(): + return False + + RegionObj = CommonDataClass.FdfClass.RegionClassObject() + RegionObj.Offset = long(self.__Token, 0) + Fd.RegionList.append(RegionObj) + + if not self.__IsToken( "|"): + raise Warning("expected '|' At Line ", self.FileName, self.CurrentLineNumber) + + if not self.__GetNextHexNumber(): + raise Warning("expected Region Size At Line ", self.FileName, self.CurrentLineNumber) + RegionObj.Size = long(self.__Token, 0) + + if not self.__GetNextWord(): + return True + + if not self.__Token in ("SET", "FV", "FILE", "DATA"): + self.__UndoToken() + RegionObj.PcdOffset = self.__GetNextPcdName() + self.Profile.PcdDict[RegionObj.PcdOffset] = RegionObj.Offset + long(Fd.BaseAddress, 0) + FileLineTuple = GetRealFileLine(self.FileName, self.CurrentLineNumber) + self.Profile.PcdFileLineDict[RegionObj.PcdOffset] = FileLineTuple + if self.__IsToken( "|"): + RegionObj.PcdSize = self.__GetNextPcdName() + self.Profile.PcdDict[RegionObj.PcdSize] = RegionObj.Size + FileLineTuple = GetRealFileLine(self.FileName, self.CurrentLineNumber) + self.Profile.PcdFileLineDict[RegionObj.PcdSize] = FileLineTuple + + if not self.__GetNextWord(): + return True + + if self.__Token == "SET": + self.__UndoToken() + self.__GetSetStatements( RegionObj) + if not self.__GetNextWord(): + return True + + if self.__Token == "FV": + self.__UndoToken() + self.__GetRegionFvType( RegionObj) + + elif self.__Token == "FILE": + self.__UndoToken() + self.__GetRegionFileType( RegionObj) + + else: + self.__UndoToken() + self.__GetRegionDataType( RegionObj) + + return True + + ## __GetRegionFvType() method + # + # Get region fv data for region + # + # @param self The object pointer + # @param RegionObj for whom region data is got + # + def __GetRegionFvType(self, RegionObj): + + if not self.__IsKeyword( "FV"): + raise Warning("expected Keyword 'FV' At Line ", self.FileName, self.CurrentLineNumber) + + if not self.__IsToken( "="): + raise Warning("expected '=' At Line ", self.FileName, self.CurrentLineNumber) + + if not self.__GetNextToken(): + raise Warning("expected FV name At Line ", self.FileName, self.CurrentLineNumber) + + RegionObj.RegionType = "FV" + RegionObj.RegionDataList.append(self.__Token) + + while self.__IsKeyword( "FV"): + + if not self.__IsToken( "="): + raise Warning("expected '=' At Line ", self.FileName, self.CurrentLineNumber) + + if not self.__GetNextToken(): + raise Warning("expected FV name At Line ", self.FileName, self.CurrentLineNumber) + + RegionObj.RegionDataList.append(self.__Token) + + ## __GetRegionFileType() method + # + # Get region file data for region + # + # @param self The object pointer + # @param RegionObj for whom region data is got + # + def __GetRegionFileType(self, RegionObj): + + if not self.__IsKeyword( "FILE"): + raise Warning("expected Keyword 'FILE' At Line ", self.FileName, self.CurrentLineNumber) + + if not self.__IsToken( "="): + raise Warning("expected '=' At Line ", self.FileName, self.CurrentLineNumber) + + if not self.__GetNextToken(): + raise Warning("expected File name At Line ", self.FileName, self.CurrentLineNumber) + + RegionObj.RegionType = "FILE" + RegionObj.RegionDataList.append( self.__Token) + + while self.__IsKeyword( "FILE"): + + if not self.__IsToken( "="): + raise Warning("expected '=' At Line ", self.FileName, self.CurrentLineNumber) + + if not self.__GetNextToken(): + raise Warning("expected FILE name At Line ", self.FileName, self.CurrentLineNumber) + + RegionObj.RegionDataList.append(self.__Token) + + ## __GetRegionDataType() method + # + # Get region array data for region + # + # @param self The object pointer + # @param RegionObj for whom region data is got + # + def __GetRegionDataType(self, RegionObj): + + if not self.__IsKeyword( "DATA"): + raise Warning("expected Region Data type At Line ", self.FileName, self.CurrentLineNumber) + + if not self.__IsToken( "="): + raise Warning("expected '=' At Line ", self.FileName, self.CurrentLineNumber) + + if not self.__IsToken( "{"): + raise Warning("expected '{' At Line ", self.FileName, self.CurrentLineNumber) + + if not self.__GetNextHexNumber(): + raise Warning("expected Hex byte At Line ", self.FileName, self.CurrentLineNumber) + + if len(self.__Token) > 4: + raise Warning("Hex byte(must be 2 digits) too long At Line ", self.FileName, self.CurrentLineNumber) + + DataString = self.__Token + DataString += "," + + while self.__IsToken(","): + if not self.__GetNextHexNumber(): + raise Warning("Invalid Hex number At Line ", self.FileName, self.CurrentLineNumber) + if len(self.__Token) > 4: + raise Warning("Hex byte(must be 2 digits) too long At Line ", self.FileName, self.CurrentLineNumber) + DataString += self.__Token + DataString += "," + + if not self.__IsToken( "}"): + raise Warning("expected '}' At Line ", self.FileName, self.CurrentLineNumber) + + DataString = DataString.rstrip(",") + RegionObj.RegionType = "DATA" + RegionObj.RegionDataList.append( DataString) + + while self.__IsKeyword( "DATA"): + + if not self.__IsToken( "="): + raise Warning("expected '=' At Line ", self.FileName, self.CurrentLineNumber) + + if not self.__IsToken( "{"): + raise Warning("expected '{' At Line ", self.FileName, self.CurrentLineNumber) + + if not self.__GetNextHexNumber(): + raise Warning("expected Hex byte At Line ", self.FileName, self.CurrentLineNumber) + + if len(self.__Token) > 4: + raise Warning("Hex byte(must be 2 digits) too long At Line ", self.FileName, self.CurrentLineNumber) + + DataString = self.__Token + DataString += "," + + while self.__IsToken(","): + self.__GetNextHexNumber() + if len(self.__Token) > 4: + raise Warning("Hex byte(must be 2 digits) too long At Line ", self.FileName, self.CurrentLineNumber) + DataString += self.__Token + DataString += "," + + if not self.__IsToken( "}"): + raise Warning("expected '}' At Line ", self.FileName, self.CurrentLineNumber) + + DataString = DataString.rstrip(",") + RegionObj.RegionDataList.append( DataString) + + ## __GetFv() method + # + # Get FV section contents and store its data into FV dictionary of self.Profile + # + # @param self The object pointer + # @retval True Successfully find a FV + # @retval False Not able to find a FV + # + def __GetFv(self): + if not self.__GetNextToken(): + return False + + S = self.__Token.upper() + if S.startswith("[") and not S.startswith("[FV."): + if not S.startswith("[CAPSULE.") \ + and not S.startswith("[VTF.") and not S.startswith("[RULE."): + raise Warning("Unknown section or section appear sequence error \n(The correct sequence should be [FD.], [FV.], [Capsule.], [VTF.], [Rule.]) At Line ", self.FileName, self.CurrentLineNumber) + self.__UndoToken() + return False + + self.__UndoToken() + if not self.__IsToken("[FV.", True): + FileLineTuple = GetRealFileLine(self.FileName, self.CurrentLineNumber) + print 'Parsing String: %s in File %s, At line: %d, Offset Within Line: %d' \ + % (self.Profile.FileLinesList[self.CurrentLineNumber - 1][self.CurrentOffsetWithinLine :], FileLineTuple[0], FileLineTuple[1], self.CurrentOffsetWithinLine) + raise Warning("Unknown Keyword At Line ", self.FileName, self.CurrentLineNumber) + + FvName = self.__GetUiName() + self.CurrentFvName = FvName.upper() + + if not self.__IsToken( "]"): + raise Warning("expected ']' At Line ", self.FileName, self.CurrentLineNumber) + + FvObj = CommonDataClass.FdfClass.FvClassObject() + FvObj.UiFvName = self.CurrentFvName + self.Profile.FvDict[self.CurrentFvName] = FvObj + + Status = self.__GetCreateFile(FvObj) + if not Status: + raise Warning("FV name error At Line ", self.FileName, self.CurrentLineNumber) + + self.__GetDefineStatements(FvObj) + + self.__GetAddressStatements(FvObj) + + self.__GetBlockStatement(FvObj) + + self.__GetSetStatements(FvObj) + + self.__GetFvAlignment(FvObj) + + self.__GetFvAttributes(FvObj) + + self.__GetFvNameGuid(FvObj) + + self.__GetAprioriSection(FvObj, FvObj.DefineVarDict.copy()) + self.__GetAprioriSection(FvObj, FvObj.DefineVarDict.copy()) + + while True: + isInf = self.__GetInfStatement(FvObj, MacroDict = FvObj.DefineVarDict.copy()) + isFile = self.__GetFileStatement(FvObj, MacroDict = FvObj.DefineVarDict.copy()) + if not isInf and not isFile: + break + + return True + + ## __GetFvAlignment() method + # + # Get alignment for FV + # + # @param self The object pointer + # @param Obj for whom alignment is got + # @retval True Successfully find a alignment statement + # @retval False Not able to find a alignment statement + # + def __GetFvAlignment(self, Obj): + + if not self.__IsKeyword( "FvAlignment"): + return False + + if not self.__IsToken( "="): + raise Warning("expected '=' At Line ", self.FileName, self.CurrentLineNumber) + + if not self.__GetNextToken(): + raise Warning("expected alignment value At Line ", self.FileName, self.CurrentLineNumber) + + if self.__Token.upper() not in ("1", "2", "4", "8", "16", "32", "64", "128", "256", "512", \ + "1K", "2K", "4K", "8K", "16K", "32K", "64K", "128K", "256K", "512K", \ + "1M", "2M", "4M", "8M", "16M", "32M", "64M", "128M", "256M", "512M", \ + "1G", "2G"): + raise Warning("Unknown alignment value At Line ", self.FileName, self.CurrentLineNumber) + Obj.FvAlignment = self.__Token + return True + + ## __GetFvAttributes() method + # + # Get attributes for FV + # + # @param self The object pointer + # @param Obj for whom attribute is got + # @retval None + # + def __GetFvAttributes(self, FvObj): + + while self.__GetNextWord(): + name = self.__Token + if name not in ("ERASE_POLARITY", "MEMORY_MAPPED", \ + "STICKY_WRITE", "LOCK_CAP", "LOCK_STATUS", "WRITE_ENABLED_CAP", \ + "WRITE_DISABLED_CAP", "WRITE_STATUS", "READ_ENABLED_CAP", \ + "READ_DISABLED_CAP", "READ_STATUS", "READ_LOCK_CAP", \ + "READ_LOCK_STATUS", "WRITE_LOCK_CAP", "WRITE_LOCK_STATUS", \ + "WRITE_POLICY_RELIABLE"): + self.__UndoToken() + return + + if not self.__IsToken( "="): + raise Warning("expected '=' At Line ", self.FileName, self.CurrentLineNumber) + + if not self.__GetNextToken() or self.__Token.upper() not in ("TRUE", "FALSE", "1", "0"): + raise Warning("expected TRUE/FALSE (1/0) At Line ", self.FileName, self.CurrentLineNumber) + + FvObj.FvAttributeDict[name] = self.__Token + + return + + ## __GetFvNameGuid() method + # + # Get FV GUID for FV + # + # @param self The object pointer + # @param Obj for whom GUID is got + # @retval None + # + def __GetFvNameGuid(self, FvObj): + + if not self.__IsKeyword( "FvNameGuid"): + return + + if not self.__IsToken( "="): + raise Warning("expected '='", self.FileName, self.CurrentLineNumber) + + if not self.__GetNextGuid(): + raise Warning("expected FV GUID value", self.FileName, self.CurrentLineNumber) + + FvObj.FvNameGuid = self.__Token + + return + + ## __GetAprioriSection() method + # + # Get token statements + # + # @param self The object pointer + # @param FvObj for whom apriori is got + # @param MacroDict dictionary used to replace macro + # @retval True Successfully find apriori statement + # @retval False Not able to find apriori statement + # + def __GetAprioriSection(self, FvObj, MacroDict = {}): + + if not self.__IsKeyword( "APRIORI"): + return False + + if not self.__IsKeyword("PEI") and not self.__IsKeyword("DXE"): + raise Warning("expected Apriori file type At Line ", self.FileName, self.CurrentLineNumber) + AprType = self.__Token + + if not self.__IsToken( "{"): + raise Warning("expected '{' At Line ", self.FileName, self.CurrentLineNumber) + + AprSectionObj = CommonDataClass.FdfClass.AprioriSectionClassObject() + AprSectionObj.AprioriType = AprType + + self.__GetDefineStatements(AprSectionObj) + MacroDict.update(AprSectionObj.DefineVarDict) + + while True: + IsInf = self.__GetInfStatement( AprSectionObj, MacroDict = MacroDict) + IsFile = self.__GetFileStatement( AprSectionObj) + if not IsInf and not IsFile: + break + + if not self.__IsToken( "}"): + raise Warning("expected '}' At Line ", self.FileName, self.CurrentLineNumber) + + FvObj.AprioriSectionList.append(AprSectionObj) + return True + + ## __GetInfStatement() method + # + # Get INF statements + # + # @param self The object pointer + # @param Obj for whom inf statement is got + # @param MacroDict dictionary used to replace macro + # @retval True Successfully find inf statement + # @retval False Not able to find inf statement + # + def __GetInfStatement(self, Obj, ForCapsule = False, MacroDict = {}): + + if not self.__IsKeyword( "INF"): + return False + + ffsInf = CommonDataClass.FdfClass.FfsInfStatementClassObject() + self.__GetInfOptions( ffsInf) + + if not self.__GetNextToken(): + raise Warning("expected INF file path At Line ", self.FileName, self.CurrentLineNumber) + ffsInf.InfFileName = self.__Token + +# if ffsInf.InfFileName.find('$') >= 0: +# ffsInf.InfFileName = GenFdsGlobalVariable.GenFdsGlobalVariable.MacroExtend(ffsInf.InfFileName, MacroDict) + + if not ffsInf.InfFileName in self.Profile.InfList: + self.Profile.InfList.append(ffsInf.InfFileName) + FileLineTuple = GetRealFileLine(self.FileName, self.CurrentLineNumber) + self.Profile.InfFileLineList.append(FileLineTuple) + + if self.__IsToken('|'): + if self.__IsKeyword('RELOCS_STRIPPED'): + ffsInf.KeepReloc = False + elif self.__IsKeyword('RELOCS_RETAINED'): + ffsInf.KeepReloc = True + else: + raise Warning("Unknown reloc strip flag At Line ", self.FileName, self.CurrentLineNumber) + + if ForCapsule: + capsuleFfs = CapsuleData.CapsuleFfs() + capsuleFfs.Ffs = ffsInf + Obj.CapsuleDataList.append(capsuleFfs) + else: + Obj.FfsList.append(ffsInf) + return True + + ## __GetInfOptions() method + # + # Get options for INF + # + # @param self The object pointer + # @param FfsInfObj for whom option is got + # + def __GetInfOptions(self, FfsInfObj): + + if self.__IsKeyword( "RuleOverride"): + if not self.__IsToken( "="): + raise Warning("expected '=' At Line ", self.FileName, self.CurrentLineNumber) + if not self.__GetNextToken(): + raise Warning("expected Rule name At Line ", self.FileName, self.CurrentLineNumber) + FfsInfObj.Rule = self.__Token + + if self.__IsKeyword( "VERSION"): + if not self.__IsToken( "="): + raise Warning("expected '=' At Line ", self.FileName, self.CurrentLineNumber) + if not self.__GetNextToken(): + raise Warning("expected Version At Line ", self.FileName, self.CurrentLineNumber) + + if self.__GetStringData(): + FfsInfObj.Version = self.__Token + + if self.__IsKeyword( "UI"): + if not self.__IsToken( "="): + raise Warning("expected '=' At Line ", self.FileName, self.CurrentLineNumber) + if not self.__GetNextToken(): + raise Warning("expected UI name At Line ", self.FileName, self.CurrentLineNumber) + + if self.__GetStringData(): + FfsInfObj.Ui = self.__Token + + if self.__IsKeyword( "USE"): + if not self.__IsToken( "="): + raise Warning("expected '='", self.FileName, self.CurrentLineNumber) + if not self.__GetNextToken(): + raise Warning("expected ARCH name", self.FileName, self.CurrentLineNumber) + FfsInfObj.UseArch = self.__Token + + + if self.__GetNextToken(): + p = re.compile(r'([a-zA-Z0-9\-]+|\$\(TARGET\)|\*)_([a-zA-Z0-9\-]+|\$\(TOOL_CHAIN_TAG\)|\*)_([a-zA-Z0-9\-]+|\$\(ARCH\)|\*)') + if p.match(self.__Token): + FfsInfObj.KeyStringList.append(self.__Token) + if not self.__IsToken(","): + return + else: + self.__UndoToken() + return + + while self.__GetNextToken(): + if not p.match(self.__Token): + raise Warning("expected KeyString \"Target_Tag_Arch\" At Line ", self.FileName, self.CurrentLineNumber) + FfsInfObj.KeyStringList.append(self.__Token) + + if not self.__IsToken(","): + break + + ## __GetFileStatement() method + # + # Get FILE statements + # + # @param self The object pointer + # @param Obj for whom FILE statement is got + # @param MacroDict dictionary used to replace macro + # @retval True Successfully find FILE statement + # @retval False Not able to find FILE statement + # + def __GetFileStatement(self, Obj, ForCapsule = False, MacroDict = {}): + + if not self.__IsKeyword( "FILE"): + return False + + FfsFileObj = CommonDataClass.FdfClass.FileStatementClassObject() + + if not self.__GetNextWord(): + raise Warning("expected FFS type At Line ", self.FileName, self.CurrentLineNumber) + FfsFileObj.FvFileType = self.__Token + + if not self.__IsToken( "="): + raise Warning("expected '=' At Line ", self.FileName, self.CurrentLineNumber) + + if not self.__GetNextGuid(): + if not self.__GetNextWord(): + raise Warning("expected File GUID", self.FileName, self.CurrentLineNumber) + if self.__Token == 'PCD': + if not self.__IsToken( "("): + raise Warning("expected '('", self.FileName, self.CurrentLineNumber) + PcdPair = self.__GetNextPcdName() + if not self.__IsToken( ")"): + raise Warning("expected ')'", self.FileName, self.CurrentLineNumber) + self.__Token = 'PCD('+PcdPair[1]+'.'+PcdPair[0]+')' + + FfsFileObj.NameGuid = self.__Token + + self.__GetFilePart( FfsFileObj, MacroDict.copy()) + + if ForCapsule: + capsuleFfs = CapsuleData.CapsuleFfs() + capsuleFfs.Ffs = FfsFileObj + Obj.CapsuleDataList.append(capsuleFfs) + else: + Obj.FfsList.append(FfsFileObj) + + return True + + ## __FileCouldHaveRelocFlag() method + # + # Check whether reloc strip flag can be set for a file type. + # + # @param self The object pointer + # @param FileType The file type to check with + # @retval True This type could have relocation strip flag + # @retval False No way to have it + # + + def __FileCouldHaveRelocFlag (self, FileType): + if FileType in ('SEC', 'PEI_CORE', 'PEIM', 'PEI_DXE_COMBO'): + return True + else: + return False + + ## __SectionCouldHaveRelocFlag() method + # + # Check whether reloc strip flag can be set for a section type. + # + # @param self The object pointer + # @param SectionType The section type to check with + # @retval True This type could have relocation strip flag + # @retval False No way to have it + # + + def __SectionCouldHaveRelocFlag (self, SectionType): + if SectionType in ('TE', 'PE32'): + return True + else: + return False + + ## __GetFilePart() method + # + # Get components for FILE statement + # + # @param self The object pointer + # @param FfsFileObj for whom component is got + # @param MacroDict dictionary used to replace macro + # + def __GetFilePart(self, FfsFileObj, MacroDict = {}): + + self.__GetFileOpts( FfsFileObj) + + if not self.__IsToken("{"): +# if self.__IsKeyword('RELOCS_STRIPPED') or self.__IsKeyword('RELOCS_RETAINED'): +# if self.__FileCouldHaveRelocFlag(FfsFileObj.FvFileType): +# if self.__Token == 'RELOCS_STRIPPED': +# FfsFileObj.KeepReloc = False +# else: +# FfsFileObj.KeepReloc = True +# else: +# raise Warning("File type %s could not have reloc strip flag At Line %d" % (FfsFileObj.FvFileType, self.CurrentLineNumber), self.FileName, self.CurrentLineNumber) +# +# if not self.__IsToken("{"): + raise Warning("expected '{' At Line ", self.FileName, self.CurrentLineNumber) + + if not self.__GetNextToken(): + raise Warning("expected File name or section data At Line ", self.FileName, self.CurrentLineNumber) + + if self.__Token == "FV": + if not self.__IsToken( "="): + raise Warning("expected '=' At Line ", self.FileName, self.CurrentLineNumber) + if not self.__GetNextToken(): + raise Warning("expected FV name At Line ", self.FileName, self.CurrentLineNumber) + FfsFileObj.FvName = self.__Token + + elif self.__Token == "FD": + if not self.__IsToken( "="): + raise Warning("expected '=' At Line ", self.FileName, self.CurrentLineNumber) + if not self.__GetNextToken(): + raise Warning("expected FD name At Line ", self.FileName, self.CurrentLineNumber) + FfsFileObj.FdName = self.__Token + + elif self.__Token in ("DEFINE", "APRIORI", "SECTION"): + self.__UndoToken() + self.__GetSectionData( FfsFileObj, MacroDict) + else: + FfsFileObj.FileName = self.__Token + + if not self.__IsToken( "}"): + raise Warning("expected '}' At Line ", self.FileName, self.CurrentLineNumber) + + ## __GetFileOpts() method + # + # Get options for FILE statement + # + # @param self The object pointer + # @param FfsFileObj for whom options is got + # + def __GetFileOpts(self, FfsFileObj): + + if self.__GetNextToken(): + Pattern = re.compile(r'([a-zA-Z0-9\-]+|\$\(TARGET\)|\*)_([a-zA-Z0-9\-]+|\$\(TOOL_CHAIN_TAG\)|\*)_([a-zA-Z0-9\-]+|\$\(ARCH\)|\*)') + if Pattern.match(self.__Token): + FfsFileObj.KeyStringList.append(self.__Token) + if self.__IsToken(","): + while self.__GetNextToken(): + if not Pattern.match(self.__Token): + raise Warning("expected KeyString \"Target_Tag_Arch\" At Line ", self.FileName, self.CurrentLineNumber) + FfsFileObj.KeyStringList.append(self.__Token) + + if not self.__IsToken(","): + break + + else: + self.__UndoToken() + + if self.__IsKeyword( "FIXED", True): + FfsFileObj.Fixed = True + + if self.__IsKeyword( "CHECKSUM", True): + FfsFileObj.CheckSum = True + + if self.__GetAlignment(): + FfsFileObj.Alignment = self.__Token + + + + ## __GetAlignment() method + # + # Return the alignment value + # + # @param self The object pointer + # @retval True Successfully find alignment + # @retval False Not able to find alignment + # + def __GetAlignment(self): + if self.__IsKeyword( "Align", True): + if not self.__IsToken( "="): + raise Warning("expected '=' At Line ", self.FileName, self.CurrentLineNumber) + + if not self.__GetNextToken(): + raise Warning("expected alignment value At Line ", self.FileName, self.CurrentLineNumber) + return True + + return False + + ## __GetFilePart() method + # + # Get section data for FILE statement + # + # @param self The object pointer + # @param FfsFileObj for whom section is got + # @param MacroDict dictionary used to replace macro + # + def __GetSectionData(self, FfsFileObj, MacroDict = {}): + Dict = {} + Dict.update(MacroDict) + + self.__GetDefineStatements(FfsFileObj) + + Dict.update(FfsFileObj.DefineVarDict) + self.__GetAprioriSection(FfsFileObj, Dict.copy()) + self.__GetAprioriSection(FfsFileObj, Dict.copy()) + + while True: + IsLeafSection = self.__GetLeafSection(FfsFileObj, Dict) + IsEncapSection = self.__GetEncapsulationSec(FfsFileObj) + if not IsLeafSection and not IsEncapSection: + break + + ## __GetLeafSection() method + # + # Get leaf section for Obj + # + # @param self The object pointer + # @param Obj for whom leaf section is got + # @param MacroDict dictionary used to replace macro + # @retval True Successfully find section statement + # @retval False Not able to find section statement + # + def __GetLeafSection(self, Obj, MacroDict = {}): + + OldPos = self.GetFileBufferPos() + + if not self.__IsKeyword( "SECTION"): + if len(Obj.SectionList) == 0: + raise Warning("expected SECTION At Line ", self.FileName, self.CurrentLineNumber) + else: + return False + + AlignValue = None + if self.__GetAlignment(): + AlignValue = self.__Token + + BuildNum = None + if self.__IsKeyword( "BUILD_NUM"): + if not self.__IsToken( "="): + raise Warning("expected '=' At Line ", self.FileName, self.CurrentLineNumber) + + if not self.__GetNextToken(): + raise Warning("expected Build number value At Line ", self.FileName, self.CurrentLineNumber) + + BuildNum = self.__Token + + if self.__IsKeyword( "VERSION"): + if not self.__IsToken( "="): + raise Warning("expected '=' At Line ", self.FileName, self.CurrentLineNumber) + if not self.__GetNextToken(): + raise Warning("expected version At Line ", self.FileName, self.CurrentLineNumber) + VerSectionObj = CommonDataClass.FdfClass.VerSectionClassObject() + VerSectionObj.Alignment = AlignValue + VerSectionObj.BuildNum = BuildNum + if self.__GetStringData(): + VerSectionObj.StringData = self.__Token + else: + VerSectionObj.FileName = self.__Token + Obj.SectionList.append(VerSectionObj) + + elif self.__IsKeyword( "UI"): + if not self.__IsToken( "="): + raise Warning("expected '=' At Line ", self.FileName, self.CurrentLineNumber) + if not self.__GetNextToken(): + raise Warning("expected UI At Line ", self.FileName, self.CurrentLineNumber) + UiSectionObj = CommonDataClass.FdfClass.UiSectionClassObject() + UiSectionObj.Alignment = AlignValue + if self.__GetStringData(): + UiSectionObj.StringData = self.__Token + else: + UiSectionObj.FileName = self.__Token + Obj.SectionList.append(UiSectionObj) + + elif self.__IsKeyword( "FV_IMAGE"): + if not self.__IsToken( "="): + raise Warning("expected '=' At Line ", self.FileName, self.CurrentLineNumber) + if not self.__GetNextWord(): + raise Warning("expected FV name At Line ", self.FileName, self.CurrentLineNumber) + + FvName = self.__Token.upper() + FvObj = None + + if self.__IsToken( "{"): + FvObj = Fv.FV() + FvObj.UiFvName = FvName + self.__GetDefineStatements(FvObj) + MacroDict.update(FvObj.DefineVarDict) + self.__GetBlockStatement(FvObj) + self.__GetSetStatements(FvObj) + self.__GetFvAlignment(FvObj) + self.__GetFvAttributes(FvObj) + self.__GetAprioriSection(FvObj, MacroDict.copy()) + self.__GetAprioriSection(FvObj, MacroDict.copy()) + + while True: + IsInf = self.__GetInfStatement(FvObj, MacroDict.copy()) + IsFile = self.__GetFileStatement(FvObj, MacroDict.copy()) + if not IsInf and not IsFile: + break + + if not self.__IsToken( "}"): + raise Warning("expected '}' At Line ", self.FileName, self.CurrentLineNumber) + + FvImageSectionObj = CommonDataClass.FdfClass.FvImageSectionClassObject() + FvImageSectionObj.Alignment = AlignValue + if FvObj != None: + FvImageSectionObj.Fv = FvObj + FvImageSectionObj.FvName = None + else: + FvImageSectionObj.FvName = FvName + + Obj.SectionList.append(FvImageSectionObj) + + elif self.__IsKeyword("PEI_DEPEX_EXP") or self.__IsKeyword("DXE_DEPEX_EXP"): + DepexSectionObj = CommonDataClass.FdfClass.DepexSectionClassObject() + DepexSectionObj.Alignment = AlignValue + DepexSectionObj.DepexType = self.__Token + + if not self.__IsToken( "="): + raise Warning("expected '=' At Line ", self.FileName, self.CurrentLineNumber) + if not self.__IsToken( "{"): + raise Warning("expected '{' At Line ", self.FileName, self.CurrentLineNumber) + if not self.__SkipToToken( "}"): + raise Warning("expected Depex expression ending '}' At Line ", self.FileName, self.CurrentLineNumber) + + DepexSectionObj.Expression = self.__SkippedChars.rstrip('}') + Obj.SectionList.append(DepexSectionObj) + + else: + + if not self.__GetNextWord(): + raise Warning("expected section type At Line ", self.FileName, self.CurrentLineNumber) + + # Encapsulation section appear, UndoToken and return + if self.__Token == "COMPRESS" or self.__Token == "GUIDED": + self.SetFileBufferPos(OldPos) + return False + + if self.__Token not in ("COMPAT16", "PE32", "PIC", "TE", "FV_IMAGE", "RAW", "DXE_DEPEX",\ + "UI", "VERSION", "PEI_DEPEX", "SUBTYPE_GUID", "SMM_DEPEX"): + raise Warning("Unknown section type '%s'" % self.__Token, self.FileName, self.CurrentLineNumber) + # DataSection + DataSectionObj = CommonDataClass.FdfClass.DataSectionClassObject() + DataSectionObj.Alignment = AlignValue + DataSectionObj.SecType = self.__Token + + if self.__IsKeyword('RELOCS_STRIPPED') or self.__IsKeyword('RELOCS_RETAINED'): + if self.__FileCouldHaveRelocFlag(Obj.FvFileType) and self.__SectionCouldHaveRelocFlag(DataSectionObj.SecType): + if self.__Token == 'RELOCS_STRIPPED': + DataSectionObj.KeepReloc = False + else: + DataSectionObj.KeepReloc = True + else: + raise Warning("File type %s, section type %s, could not have reloc strip flag At Line %d" % (Obj.FvFileType, DataSectionObj.SecType, self.CurrentLineNumber), self.FileName, self.CurrentLineNumber) + + if self.__IsToken("="): + if not self.__GetNextToken(): + raise Warning("expected section file path At Line ", self.FileName, self.CurrentLineNumber) + DataSectionObj.SectFileName = self.__Token + else: + if not self.__GetCglSection(DataSectionObj): + return False + + Obj.SectionList.append(DataSectionObj) + + return True + + ## __GetCglSection() method + # + # Get compressed or GUIDed section for Obj + # + # @param self The object pointer + # @param Obj for whom leaf section is got + # @param AlignValue alignment value for complex section + # @retval True Successfully find section statement + # @retval False Not able to find section statement + # + def __GetCglSection(self, Obj, AlignValue = None): + + if self.__IsKeyword( "COMPRESS"): + type = "PI_STD" + if self.__IsKeyword("PI_STD") or self.__IsKeyword("PI_NONE"): + type = self.__Token + + if not self.__IsToken("{"): + raise Warning("expected '{' At Line ", self.FileName, self.CurrentLineNumber) + + CompressSectionObj = CommonDataClass.FdfClass.CompressSectionClassObject() + CompressSectionObj.Alignment = AlignValue + CompressSectionObj.CompType = type + # Recursive sections... + while True: + IsLeafSection = self.__GetLeafSection(CompressSectionObj) + IsEncapSection = self.__GetEncapsulationSec(CompressSectionObj) + if not IsLeafSection and not IsEncapSection: + break + + + if not self.__IsToken( "}"): + raise Warning("expected '}' At Line ", self.FileName, self.CurrentLineNumber) + Obj.SectionList.append(CompressSectionObj) + +# else: +# raise Warning("Compress type not known At Line ") + + return True + + elif self.__IsKeyword( "GUIDED"): + GuidValue = None + if self.__GetNextGuid(): + GuidValue = self.__Token + + AttribDict = self.__GetGuidAttrib() + if not self.__IsToken("{"): + raise Warning("expected '{' At Line ", self.FileName, self.CurrentLineNumber) + GuidSectionObj = CommonDataClass.FdfClass.GuidSectionClassObject() + GuidSectionObj.Alignment = AlignValue + GuidSectionObj.NameGuid = GuidValue + GuidSectionObj.SectionType = "GUIDED" + GuidSectionObj.ProcessRequired = AttribDict["PROCESSING_REQUIRED"] + GuidSectionObj.AuthStatusValid = AttribDict["AUTH_STATUS_VALID"] + # Recursive sections... + while True: + IsLeafSection = self.__GetLeafSection(GuidSectionObj) + IsEncapSection = self.__GetEncapsulationSec(GuidSectionObj) + if not IsLeafSection and not IsEncapSection: + break + + if not self.__IsToken( "}"): + raise Warning("expected '}' At Line ", self.FileName, self.CurrentLineNumber) + Obj.SectionList.append(GuidSectionObj) + + return True + + return False + + ## __GetGuidAttri() method + # + # Get attributes for GUID section + # + # @param self The object pointer + # @retval AttribDict Dictionary of key-value pair of section attributes + # + def __GetGuidAttrib(self): + + AttribDict = {} + AttribDict["PROCESSING_REQUIRED"] = False + AttribDict["AUTH_STATUS_VALID"] = False + if self.__IsKeyword("PROCESSING_REQUIRED") or self.__IsKeyword("AUTH_STATUS_VALID"): + AttribKey = self.__Token + + if not self.__IsToken("="): + raise Warning("expected '=' At Line ", self.FileName, self.CurrentLineNumber) + + if not self.__GetNextToken() or self.__Token.upper() not in ("TRUE", "FALSE", "1", "0"): + raise Warning("expected TRUE/FALSE (1/0) At Line ", self.FileName, self.CurrentLineNumber) + AttribDict[AttribKey] = self.__Token + + if self.__IsKeyword("PROCESSING_REQUIRED") or self.__IsKeyword("AUTH_STATUS_VALID"): + AttribKey = self.__Token + + if not self.__IsToken("="): + raise Warning("expected '=' At Line ") + + if not self.__GetNextToken() or self.__Token.upper() not in ("TRUE", "FALSE", "1", "0"): + raise Warning("expected TRUE/FALSE (1/0) At Line ", self.FileName, self.CurrentLineNumber) + AttribDict[AttribKey] = self.__Token + + return AttribDict + + ## __GetEncapsulationSec() method + # + # Get encapsulation section for FILE + # + # @param self The object pointer + # @param FfsFile for whom section is got + # @retval True Successfully find section statement + # @retval False Not able to find section statement + # + def __GetEncapsulationSec(self, FfsFileObj): + + OldPos = self.GetFileBufferPos() + if not self.__IsKeyword( "SECTION"): + if len(FfsFileObj.SectionList) == 0: + raise Warning("expected SECTION At Line ", self.FileName, self.CurrentLineNumber) + else: + return False + + AlignValue = None + if self.__GetAlignment(): + AlignValue = self.__Token + + if not self.__GetCglSection(FfsFileObj, AlignValue): + self.SetFileBufferPos(OldPos) + return False + else: + return True + + ## __GetCapsule() method + # + # Get capsule section contents and store its data into capsule list of self.Profile + # + # @param self The object pointer + # @retval True Successfully find a capsule + # @retval False Not able to find a capsule + # + def __GetCapsule(self): + + if not self.__GetNextToken(): + return False + + S = self.__Token.upper() + if S.startswith("[") and not S.startswith("[CAPSULE."): + if not S.startswith("[VTF.") and not S.startswith("[RULE.") and not S.startswith("[OPTIONROM."): + raise Warning("Unknown section or section appear sequence error (The correct sequence should be [FD.], [FV.], [Capsule.], [VTF.], [Rule.], [OptionRom.])", self.FileName, self.CurrentLineNumber) + self.__UndoToken() + return False + + self.__UndoToken() + if not self.__IsToken("[CAPSULE.", True): + FileLineTuple = GetRealFileLine(self.FileName, self.CurrentLineNumber) + print 'Parsing String: %s in File %s, At line: %d, Offset Within Line: %d' \ + % (self.Profile.FileLinesList[self.CurrentLineNumber - 1][self.CurrentOffsetWithinLine :], FileLineTuple[0], FileLineTuple[1], self.CurrentOffsetWithinLine) + raise Warning("expected [Capsule.] At Line ", self.FileName, self.CurrentLineNumber) + + CapsuleObj = CommonDataClass.FdfClass.CapsuleClassObject() + + CapsuleName = self.__GetUiName() + if not CapsuleName: + raise Warning("expected capsule name At line ", self.FileName, self.CurrentLineNumber) + + CapsuleObj.UiCapsuleName = CapsuleName.upper() + + if not self.__IsToken( "]"): + raise Warning("expected ']' At Line ", self.FileName, self.CurrentLineNumber) + + if self.__IsKeyword("CREATE_FILE"): + if not self.__IsToken( "="): + raise Warning("expected '=' At Line ", self.FileName, self.CurrentLineNumber) + + if not self.__GetNextToken(): + raise Warning("expected file name At Line ", self.FileName, self.CurrentLineNumber) + + CapsuleObj.CreateFile = self.__Token + + self.__GetCapsuleStatements(CapsuleObj) + self.Profile.CapsuleList.append(CapsuleObj) + return True + + ## __GetCapsuleStatements() method + # + # Get statements for capsule + # + # @param self The object pointer + # @param Obj for whom statements are got + # + def __GetCapsuleStatements(self, Obj): + self.__GetCapsuleTokens(Obj) + self.__GetDefineStatements(Obj) + self.__GetSetStatements(Obj) + + self.__GetCapsuleData(Obj) + + ## __GetCapsuleStatements() method + # + # Get token statements for capsule + # + # @param self The object pointer + # @param Obj for whom token statements are got + # + def __GetCapsuleTokens(self, Obj): + + if not self.__IsKeyword("CAPSULE_GUID"): + raise Warning("expected 'CAPSULE_GUID' At Line ", self.FileName, self.CurrentLineNumber) + + while self.__CurrentLine().find("=") != -1: + NameValue = self.__CurrentLine().split("=") + Obj.TokensDict[NameValue[0].strip()] = NameValue[1].strip() + self.CurrentLineNumber += 1 + self.CurrentOffsetWithinLine = 0 + + ## __GetCapsuleData() method + # + # Get capsule data for capsule + # + # @param self The object pointer + # @param Obj for whom capsule data are got + # + def __GetCapsuleData(self, Obj): + + while True: + IsInf = self.__GetInfStatement(Obj, True) + IsFile = self.__GetFileStatement(Obj, True) + IsFv = self.__GetFvStatement(Obj) + if not IsInf and not IsFile and not IsFv: + break + + ## __GetFvStatement() method + # + # Get FV for capsule + # + # @param self The object pointer + # @param CapsuleObj for whom FV is got + # @retval True Successfully find a FV statement + # @retval False Not able to find a FV statement + # + def __GetFvStatement(self, CapsuleObj): + + if not self.__IsKeyword("FV"): + return False + + if not self.__IsToken("="): + raise Warning("expected '=' At Line ", self.FileName, self.CurrentLineNumber) + + if not self.__GetNextToken(): + raise Warning("expected FV name At Line ", self.FileName, self.CurrentLineNumber) + +# CapsuleFv = CapsuleData.CapsuleFv() +# CapsuleFv.FvName = self.__Token +# CapsuleObj.CapsuleDataList.append(CapsuleFv) + return True + + ## __GetRule() method + # + # Get Rule section contents and store its data into rule list of self.Profile + # + # @param self The object pointer + # @retval True Successfully find a Rule + # @retval False Not able to find a Rule + # + def __GetRule(self): + + if not self.__GetNextToken(): + return False + + S = self.__Token.upper() + if S.startswith("[") and not S.startswith("[RULE."): + if not S.startswith("[OPTIONROM."): + raise Warning("Unknown section or section appear sequence error (The correct sequence should be [FD.], [FV.], [Capsule.], [VTF.], [Rule.], [OptionRom.])", self.FileName, self.CurrentLineNumber) + self.__UndoToken() + return False + self.__UndoToken() + if not self.__IsToken("[Rule.", True): + FileLineTuple = GetRealFileLine(self.FileName, self.CurrentLineNumber) + print 'Parsing String: %s in File %s, At line: %d, Offset Within Line: %d' \ + % (self.Profile.FileLinesList[self.CurrentLineNumber - 1][self.CurrentOffsetWithinLine :], FileLineTuple[0], FileLineTuple[1], self.CurrentOffsetWithinLine) + raise Warning("expected [Rule.] At Line ", self.FileName, self.CurrentLineNumber) + + if not self.__SkipToToken("."): + raise Warning("expected '.' At Line ", self.FileName, self.CurrentLineNumber) + + Arch = self.__SkippedChars.rstrip(".") + if Arch.upper() not in ("IA32", "X64", "IPF", "EBC", "ARM", "COMMON"): + raise Warning("Unknown Arch At line ", self.FileName, self.CurrentLineNumber) + + ModuleType = self.__GetModuleType() + + TemplateName = "" + if self.__IsToken("."): + if not self.__GetNextWord(): + raise Warning("expected template name At Line ", self.FileName, self.CurrentLineNumber) + TemplateName = self.__Token + + if not self.__IsToken( "]"): + raise Warning("expected ']' At Line ", self.FileName, self.CurrentLineNumber) + + RuleObj = self.__GetRuleFileStatements() + RuleObj.Arch = Arch.upper() + RuleObj.ModuleType = ModuleType + RuleObj.TemplateName = TemplateName + if TemplateName == '' : + self.Profile.RuleDict['RULE' + \ + '.' + \ + Arch.upper() + \ + '.' + \ + ModuleType.upper() ] = RuleObj + else : + self.Profile.RuleDict['RULE' + \ + '.' + \ + Arch.upper() + \ + '.' + \ + ModuleType.upper() + \ + '.' + \ + TemplateName.upper() ] = RuleObj +# self.Profile.RuleList.append(rule) + return True + + ## __GetModuleType() method + # + # Return the module type + # + # @param self The object pointer + # @retval string module type + # + def __GetModuleType(self): + + if not self.__GetNextWord(): + raise Warning("expected Module type At Line ", self.FileName, self.CurrentLineNumber) + if self.__Token.upper() not in ("SEC", "PEI_CORE", "PEIM", "DXE_CORE", \ + "DXE_DRIVER", "DXE_SAL_DRIVER", \ + "DXE_SMM_DRIVER", "DXE_RUNTIME_DRIVER", \ + "UEFI_DRIVER", "UEFI_APPLICATION", "USER_DEFINED", "DEFAULT", "BASE", \ + "SECURITY_CORE", "COMBINED_PEIM_DRIVER", "PIC_PEIM", "RELOCATABLE_PEIM", \ + "PE32_PEIM", "BS_DRIVER", "RT_DRIVER", "SAL_RT_DRIVER", "APPLICATION"): + raise Warning("Unknown Module type At line ", self.FileName, self.CurrentLineNumber) + return self.__Token + + ## __GetFileExtension() method + # + # Return the file extension + # + # @param self The object pointer + # @retval string file name extension + # + def __GetFileExtension(self): + if not self.__IsToken("."): + raise Warning("expected '.' At Line ", self.FileName, self.CurrentLineNumber) + + Ext = "" + if self.__GetNextToken(): + Pattern = re.compile(r'([a-zA-Z][a-zA-Z0-9]*)') + if Pattern.match(self.__Token): + Ext = self.__Token + return '.' + Ext + else: + raise Warning("Unknown file extension At Line ", self.FileName, self.CurrentLineNumber) + + else: + raise Warning("expected file extension At Line ", self.FileName, self.CurrentLineNumber) + + ## __GetRuleFileStatement() method + # + # Get rule contents + # + # @param self The object pointer + # @retval Rule Rule object + # + def __GetRuleFileStatements(self): + + if not self.__IsKeyword("FILE"): + raise Warning("expected FILE At Line ", self.FileName, self.CurrentLineNumber) + + if not self.__GetNextWord(): + raise Warning("expected FV type At Line ", self.FileName, self.CurrentLineNumber) + + Type = self.__Token.strip().upper() + if Type not in ("RAW", "FREEFORM", "SEC", "PEI_CORE", "PEIM",\ + "PEI_DXE_COMBO", "DRIVER", "DXE_CORE", "APPLICATION", "FV_IMAGE"): + raise Warning("Unknown FV type At line ", self.FileName, self.CurrentLineNumber) + + if not self.__IsToken("="): + raise Warning("expected '=' At Line ", self.FileName, self.CurrentLineNumber) + + if not self.__IsKeyword("$(NAMED_GUID)"): + if not self.__GetNextWord(): + raise Warning("expected $(NAMED_GUID)", self.FileName, self.CurrentLineNumber) + if self.__Token == 'PCD': + if not self.__IsToken( "("): + raise Warning("expected '('", self.FileName, self.CurrentLineNumber) + PcdPair = self.__GetNextPcdName() + if not self.__IsToken( ")"): + raise Warning("expected ')'", self.FileName, self.CurrentLineNumber) + self.__Token = 'PCD('+PcdPair[1]+'.'+PcdPair[0]+')' + + NameGuid = self.__Token + + KeepReloc = None + if self.__IsKeyword('RELOCS_STRIPPED') or self.__IsKeyword('RELOCS_RETAINED'): + if self.__FileCouldHaveRelocFlag(Type): + if self.__Token == 'RELOCS_STRIPPED': + KeepReloc = False + else: + KeepReloc = True + else: + raise Warning("File type %s could not have reloc strip flag At Line %d" % (Type, self.CurrentLineNumber), self.FileName, self.CurrentLineNumber) + + KeyStringList = [] + if self.__GetNextToken(): + Pattern = re.compile(r'([a-zA-Z0-9\-]+|\$\(TARGET\)|\*)_([a-zA-Z0-9\-]+|\$\(TOOL_CHAIN_TAG\)|\*)_([a-zA-Z0-9\-]+|\$\(ARCH\)|\*)') + if Pattern.match(self.__Token): + KeyStringList.append(self.__Token) + if self.__IsToken(","): + while self.__GetNextToken(): + if not Pattern.match(self.__Token): + raise Warning("expected KeyString \"Target_Tag_Arch\" At Line ", self.FileName, self.CurrentLineNumber) + KeyStringList.append(self.__Token) + + if not self.__IsToken(","): + break + + else: + self.__UndoToken() + + + Fixed = False + if self.__IsKeyword("Fixed", True): + Fixed = True + + CheckSum = False + if self.__IsKeyword("CheckSum", True): + CheckSum = True + + AlignValue = "" + if self.__GetAlignment(): + if self.__Token not in ("8", "16", "32", "64", "128", "512", "1K", "4K", "32K" ,"64K"): + raise Warning("Incorrect alignment At Line ", self.FileName, self.CurrentLineNumber) + AlignValue = self.__Token + + if self.__IsToken("{"): + # Complex file rule expected + Rule = RuleComplexFile.RuleComplexFile() + Rule.FvFileType = Type + Rule.NameGuid = NameGuid + Rule.Alignment = AlignValue + Rule.CheckSum = CheckSum + Rule.Fixed = Fixed + Rule.KeyStringList = KeyStringList + if KeepReloc != None: + Rule.KeepReloc = KeepReloc + + while True: + IsEncapsulate = self.__GetRuleEncapsulationSection(Rule) + IsLeaf = self.__GetEfiSection(Rule) + if not IsEncapsulate and not IsLeaf: + break + + if not self.__IsToken("}"): + raise Warning("expected '}' At Line ", self.FileName, self.CurrentLineNumber) + + return Rule + + elif self.__IsToken("|"): + # Ext rule expected + Ext = self.__GetFileExtension() + + Rule = RuleSimpleFile.RuleSimpleFile() + + Rule.FvFileType = Type + Rule.NameGuid = NameGuid + Rule.Alignment = AlignValue + Rule.CheckSum = CheckSum + Rule.Fixed = Fixed + Rule.FileExtension = Ext + Rule.KeyStringList = KeyStringList + if KeepReloc != None: + Rule.KeepReloc = KeepReloc + + return Rule + + else: + # Simple file rule expected + if not self.__GetNextWord(): + raise Warning("expected leaf section type At Line ", self.FileName, self.CurrentLineNumber) + + SectionName = self.__Token + + if SectionName not in ("COMPAT16", "PE32", "PIC", "TE", "FV_IMAGE", "RAW", "DXE_DEPEX",\ + "UI", "PEI_DEPEX", "VERSION", "SUBTYPE_GUID", "SMM_DEPEX"): + raise Warning("Unknown leaf section name '%s'" % SectionName, self.FileName, self.CurrentLineNumber) + + + if self.__IsKeyword("Fixed", True): + Fixed = True + + if self.__IsKeyword("CheckSum", True): + CheckSum = True + + if self.__GetAlignment(): + if self.__Token not in ("8", "16", "32", "64", "128", "512", "1K", "4K", "32K" ,"64K"): + raise Warning("Incorrect alignment At Line ", self.FileName, self.CurrentLineNumber) + AlignValue = self.__Token + + if not self.__GetNextToken(): + raise Warning("expected File name At Line ", self.FileName, self.CurrentLineNumber) + + Rule = RuleSimpleFile.RuleSimpleFile() + Rule.SectionType = SectionName + Rule.FvFileType = Type + Rule.NameGuid = NameGuid + Rule.Alignment = AlignValue + Rule.CheckSum = CheckSum + Rule.Fixed = Fixed + Rule.FileName = self.__Token + Rule.KeyStringList = KeyStringList + if KeepReloc != None: + Rule.KeepReloc = KeepReloc + return Rule + + ## __GetEfiSection() method + # + # Get section list for Rule + # + # @param self The object pointer + # @param Obj for whom section is got + # @retval True Successfully find section statement + # @retval False Not able to find section statement + # + def __GetEfiSection(self, Obj): + + OldPos = self.GetFileBufferPos() + if not self.__GetNextWord(): + return False + SectionName = self.__Token + + if SectionName not in ("COMPAT16", "PE32", "PIC", "TE", "FV_IMAGE", "RAW", "DXE_DEPEX",\ + "UI", "VERSION", "PEI_DEPEX", "GUID", "SMM_DEPEX"): + self.__UndoToken() + return False + + if SectionName == "FV_IMAGE": + FvImageSectionObj = FvImageSection.FvImageSection() + if self.__IsKeyword("FV_IMAGE"): + pass + if self.__IsToken( "{"): + FvObj = Fv.FV() + self.__GetDefineStatements(FvObj) + self.__GetBlockStatement(FvObj) + self.__GetSetStatements(FvObj) + self.__GetFvAlignment(FvObj) + self.__GetFvAttributes(FvObj) + self.__GetAprioriSection(FvObj) + self.__GetAprioriSection(FvObj) + + while True: + IsInf = self.__GetInfStatement(FvObj) + IsFile = self.__GetFileStatement(FvObj) + if not IsInf and not IsFile: + break + + if not self.__IsToken( "}"): + raise Warning("expected '}' At Line ", self.FileName, self.CurrentLineNumber) + FvImageSectionObj.Fv = FvObj + FvImageSectionObj.FvName = None + + else: + if not self.__IsKeyword("FV"): + raise Warning("expected 'FV' At Line ", self.FileName, self.CurrentLineNumber) + FvImageSectionObj.FvFileType = self.__Token + + if self.__GetAlignment(): + if self.__Token not in ("8", "16", "32", "64", "128", "512", "1K", "4K", "32K" ,"64K"): + raise Warning("Incorrect alignment At Line ", self.FileName, self.CurrentLineNumber) + FvImageSectionObj.Alignment = self.__Token + + if self.__IsKeyword("FV"): + FvImageSectionObj.FvFileType = self.__Token + + if self.__GetAlignment(): + if self.__Token not in ("8", "16", "32", "64", "128", "512", "1K", "4K", "32K" ,"64K"): + raise Warning("Incorrect alignment At Line ", self.FileName, self.CurrentLineNumber) + FvImageSectionObj.Alignment = self.__Token + + if self.__IsToken('|'): + FvImageSectionObj.FvFileExtension = self.__GetFileExtension() + elif self.__GetNextToken(): + if self.__Token not in ("}", "COMPAT16", "PE32", "PIC", "TE", "FV_IMAGE", "RAW", "DXE_DEPEX",\ + "UI", "VERSION", "PEI_DEPEX", "GUID", "SMM_DEPEX"): + FvImageSectionObj.FvFileName = self.__Token + else: + self.__UndoToken() + else: + raise Warning("expected FV file name At Line ", self.FileName, self.CurrentLineNumber) + + Obj.SectionList.append(FvImageSectionObj) + return True + + EfiSectionObj = EfiSection.EfiSection() + EfiSectionObj.SectionType = SectionName + + if not self.__GetNextToken(): + raise Warning("expected file type At Line ", self.FileName, self.CurrentLineNumber) + + if self.__Token == "STRING": + if not self.__RuleSectionCouldHaveString(EfiSectionObj.SectionType): + raise Warning("%s section could NOT have string data At Line %d" % (EfiSectionObj.SectionType, self.CurrentLineNumber), self.FileName, self.CurrentLineNumber) + + if not self.__IsToken('='): + raise Warning("expected '=' At Line ", self.FileName, self.CurrentLineNumber) + + if not self.__GetNextToken(): + raise Warning("expected Quoted String At Line ", self.FileName, self.CurrentLineNumber) + + if self.__GetStringData(): + EfiSectionObj.StringData = self.__Token + + if self.__IsKeyword("BUILD_NUM"): + if not self.__RuleSectionCouldHaveBuildNum(EfiSectionObj.SectionType): + raise Warning("%s section could NOT have BUILD_NUM At Line %d" % (EfiSectionObj.SectionType, self.CurrentLineNumber), self.FileName, self.CurrentLineNumber) + + if not self.__IsToken("="): + raise Warning("expected '=' At Line ", self.FileName, self.CurrentLineNumber) + if not self.__GetNextToken(): + raise Warning("expected Build number At Line ", self.FileName, self.CurrentLineNumber) + EfiSectionObj.BuildNum = self.__Token + + else: + EfiSectionObj.FileType = self.__Token + self.__CheckRuleSectionFileType(EfiSectionObj.SectionType, EfiSectionObj.FileType) + + if self.__IsKeyword("Optional"): + if not self.__RuleSectionCouldBeOptional(EfiSectionObj.SectionType): + raise Warning("%s section could NOT be optional At Line %d" % (EfiSectionObj.SectionType, self.CurrentLineNumber), self.FileName, self.CurrentLineNumber) + EfiSectionObj.Optional = True + + if self.__IsKeyword("BUILD_NUM"): + if not self.__RuleSectionCouldHaveBuildNum(EfiSectionObj.SectionType): + raise Warning("%s section could NOT have BUILD_NUM At Line %d" % (EfiSectionObj.SectionType, self.CurrentLineNumber), self.FileName, self.CurrentLineNumber) + + if not self.__IsToken("="): + raise Warning("expected '=' At Line ", self.FileName, self.CurrentLineNumber) + if not self.__GetNextToken(): + raise Warning("expected Build number At Line ", self.FileName, self.CurrentLineNumber) + EfiSectionObj.BuildNum = self.__Token + + if self.__GetAlignment(): + EfiSectionObj.Alignment = self.__Token + + if self.__IsKeyword('RELOCS_STRIPPED') or self.__IsKeyword('RELOCS_RETAINED'): + if self.__SectionCouldHaveRelocFlag(EfiSectionObj.SectionType): + if self.__Token == 'RELOCS_STRIPPED': + EfiSectionObj.KeepReloc = False + else: + EfiSectionObj.KeepReloc = True + if Obj.KeepReloc != None and Obj.KeepReloc != EfiSectionObj.KeepReloc: + raise Warning("Section type %s has reloc strip flag conflict with Rule At Line %d" % (EfiSectionObj.SectionType, self.CurrentLineNumber), self.FileName, self.CurrentLineNumber) + else: + raise Warning("Section type %s could not have reloc strip flag At Line %d" % (EfiSectionObj.SectionType, self.CurrentLineNumber), self.FileName, self.CurrentLineNumber) + + + if self.__IsToken('|'): + EfiSectionObj.FileExtension = self.__GetFileExtension() + elif self.__GetNextToken(): + if self.__Token not in ("}", "COMPAT16", "PE32", "PIC", "TE", "FV_IMAGE", "RAW", "DXE_DEPEX",\ + "UI", "VERSION", "PEI_DEPEX", "GUID", "SMM_DEPEX"): + + if self.__Token.startswith('PCD'): + self.__UndoToken() + self.__GetNextWord() + + if self.__Token == 'PCD': + if not self.__IsToken( "("): + raise Warning("expected '('", self.FileName, self.CurrentLineNumber) + PcdPair = self.__GetNextPcdName() + if not self.__IsToken( ")"): + raise Warning("expected ')'", self.FileName, self.CurrentLineNumber) + self.__Token = 'PCD('+PcdPair[1]+'.'+PcdPair[0]+')' + + EfiSectionObj.FileName = self.__Token + + else: + self.__UndoToken() + else: + raise Warning("expected section file name At Line ", self.FileName, self.CurrentLineNumber) + + Obj.SectionList.append(EfiSectionObj) + return True + + ## __RuleSectionCouldBeOptional() method + # + # Get whether a section could be optional + # + # @param self The object pointer + # @param SectionType The section type to check + # @retval True section could be optional + # @retval False section never optional + # + def __RuleSectionCouldBeOptional(self, SectionType): + if SectionType in ("DXE_DEPEX", "UI", "VERSION", "PEI_DEPEX", "RAW", "SMM_DEPEX"): + return True + else: + return False + + ## __RuleSectionCouldHaveBuildNum() method + # + # Get whether a section could have build number information + # + # @param self The object pointer + # @param SectionType The section type to check + # @retval True section could have build number information + # @retval False section never have build number information + # + def __RuleSectionCouldHaveBuildNum(self, SectionType): + if SectionType in ("VERSION"): + return True + else: + return False + + ## __RuleSectionCouldHaveString() method + # + # Get whether a section could have string + # + # @param self The object pointer + # @param SectionType The section type to check + # @retval True section could have string + # @retval False section never have string + # + def __RuleSectionCouldHaveString(self, SectionType): + if SectionType in ("UI", "VERSION"): + return True + else: + return False + + ## __CheckRuleSectionFileType() method + # + # Get whether a section matches a file type + # + # @param self The object pointer + # @param SectionType The section type to check + # @param FileType The file type to check + # + def __CheckRuleSectionFileType(self, SectionType, FileType): + if SectionType == "COMPAT16": + if FileType not in ("COMPAT16", "SEC_COMPAT16"): + raise Warning("Incorrect section file type At Line ", self.FileName, self.CurrentLineNumber) + elif SectionType == "PE32": + if FileType not in ("PE32", "SEC_PE32"): + raise Warning("Incorrect section file type At Line ", self.FileName, self.CurrentLineNumber) + elif SectionType == "PIC": + if FileType not in ("PIC", "PIC"): + raise Warning("Incorrect section file type At Line ", self.FileName, self.CurrentLineNumber) + elif SectionType == "TE": + if FileType not in ("TE", "SEC_TE"): + raise Warning("Incorrect section file type At Line ", self.FileName, self.CurrentLineNumber) + elif SectionType == "RAW": + if FileType not in ("BIN", "SEC_BIN", "RAW", "ASL", "ACPI"): + raise Warning("Incorrect section file type At Line ", self.FileName, self.CurrentLineNumber) + elif SectionType == "DXE_DEPEX": + if FileType not in ("DXE_DEPEX", "SEC_DXE_DEPEX"): + raise Warning("Incorrect section file type At Line ", self.FileName, self.CurrentLineNumber) + elif SectionType == "UI": + if FileType not in ("UI", "SEC_UI"): + raise Warning("Incorrect section file type At Line ", self.FileName, self.CurrentLineNumber) + elif SectionType == "VERSION": + if FileType not in ("VERSION", "SEC_VERSION"): + raise Warning("Incorrect section file type At Line ", self.FileName, self.CurrentLineNumber) + elif SectionType == "PEI_DEPEX": + if FileType not in ("PEI_DEPEX", "SEC_PEI_DEPEX"): + raise Warning("Incorrect section file type At Line ", self.FileName, self.CurrentLineNumber) + elif SectionType == "GUID": + if FileType not in ("PE32", "SEC_GUID"): + raise Warning("Incorrect section file type At Line ", self.FileName, self.CurrentLineNumber) + + ## __GetRuleEncapsulationSection() method + # + # Get encapsulation section for Rule + # + # @param self The object pointer + # @param Rule for whom section is got + # @retval True Successfully find section statement + # @retval False Not able to find section statement + # + def __GetRuleEncapsulationSection(self, Rule): + + if self.__IsKeyword( "COMPRESS"): + Type = "PI_STD" + if self.__IsKeyword("PI_STD") or self.__IsKeyword("PI_NONE"): + Type = self.__Token + + if not self.__IsToken("{"): + raise Warning("expected '{' At Line ", self.FileName, self.CurrentLineNumber) + + CompressSectionObj = CompressSection.CompressSection() + + CompressSectionObj.CompType = Type + # Recursive sections... + while True: + IsEncapsulate = self.__GetRuleEncapsulationSection(CompressSectionObj) + IsLeaf = self.__GetEfiSection(CompressSectionObj) + if not IsEncapsulate and not IsLeaf: + break + + if not self.__IsToken( "}"): + raise Warning("expected '}' At Line ", self.FileName, self.CurrentLineNumber) + Rule.SectionList.append(CompressSectionObj) + + return True + + elif self.__IsKeyword( "GUIDED"): + GuidValue = None + if self.__GetNextGuid(): + GuidValue = self.__Token + + if self.__IsKeyword( "$(NAMED_GUID)"): + GuidValue = self.__Token + + AttribDict = self.__GetGuidAttrib() + + if not self.__IsToken("{"): + raise Warning("expected '{' At Line ", self.FileName, self.CurrentLineNumber) + GuidSectionObj = GuidSection.GuidSection() + GuidSectionObj.NameGuid = GuidValue + GuidSectionObj.SectionType = "GUIDED" + GuidSectionObj.ProcessRequired = AttribDict["PROCESSING_REQUIRED"] + GuidSectionObj.AuthStatusValid = AttribDict["AUTH_STATUS_VALID"] + + # Efi sections... + while True: + IsEncapsulate = self.__GetRuleEncapsulationSection(GuidSectionObj) + IsLeaf = self.__GetEfiSection(GuidSectionObj) + if not IsEncapsulate and not IsLeaf: + break + + if not self.__IsToken( "}"): + raise Warning("expected '}' At Line ", self.FileName, self.CurrentLineNumber) + Rule.SectionList.append(GuidSectionObj) + + return True + + return False + + ## __GetVtf() method + # + # Get VTF section contents and store its data into VTF list of self.Profile + # + # @param self The object pointer + # @retval True Successfully find a VTF + # @retval False Not able to find a VTF + # + def __GetVtf(self): + + if not self.__GetNextToken(): + return False + + S = self.__Token.upper() + if S.startswith("[") and not S.startswith("[VTF."): + if not S.startswith("[RULE.") and not S.startswith("[OPTIONROM."): + raise Warning("Unknown section or section appear sequence error (The correct sequence should be [FD.], [FV.], [Capsule.], [VTF.], [Rule.], [OptionRom.])", self.FileName, self.CurrentLineNumber) + self.__UndoToken() + return False + + self.__UndoToken() + if not self.__IsToken("[VTF.", True): + FileLineTuple = GetRealFileLine(self.FileName, self.CurrentLineNumber) + print 'Parsing String: %s in File %s, At line: %d, Offset Within Line: %d' \ + % (self.Profile.FileLinesList[self.CurrentLineNumber - 1][self.CurrentOffsetWithinLine :], FileLineTuple[0], FileLineTuple[1], self.CurrentOffsetWithinLine) + raise Warning("expected [VTF.] At Line ", self.FileName, self.CurrentLineNumber) + + if not self.__SkipToToken("."): + raise Warning("expected '.' At Line ", self.FileName, self.CurrentLineNumber) + + Arch = self.__SkippedChars.rstrip(".").upper() + if Arch not in ("IA32", "X64", "IPF", "ARM"): + raise Warning("Unknown Arch At line ", self.FileName, self.CurrentLineNumber) + + if not self.__GetNextWord(): + raise Warning("expected VTF name At Line ", self.FileName, self.CurrentLineNumber) + Name = self.__Token.upper() + + VtfObj = Vtf.Vtf() + VtfObj.UiName = Name + VtfObj.KeyArch = Arch + + if self.__IsToken(","): + if not self.__GetNextWord(): + raise Warning("expected Arch list At Line ", self.FileName, self.CurrentLineNumber) + if self.__Token.upper() not in ("IA32", "X64", "IPF", "ARM"): + raise Warning("Unknown Arch At line ", self.FileName, self.CurrentLineNumber) + VtfObj.ArchList = self.__Token.upper() + + if not self.__IsToken( "]"): + raise Warning("expected ']' At Line ", self.FileName, self.CurrentLineNumber) + + if self.__IsKeyword("IA32_RST_BIN"): + if not self.__IsToken("="): + raise Warning("expected '=' At Line ", self.FileName, self.CurrentLineNumber) + + if not self.__GetNextToken(): + raise Warning("expected Reset file At Line ", self.FileName, self.CurrentLineNumber) + + VtfObj.ResetBin = self.__Token + + while self.__GetComponentStatement(VtfObj): + pass + + self.Profile.VtfList.append(VtfObj) + return True + + ## __GetComponentStatement() method + # + # Get components in VTF + # + # @param self The object pointer + # @param VtfObj for whom component is got + # @retval True Successfully find a component + # @retval False Not able to find a component + # + def __GetComponentStatement(self, VtfObj): + + if not self.__IsKeyword("COMP_NAME"): + return False + + if not self.__IsToken("="): + raise Warning("expected '=' At Line ", self.FileName, self.CurrentLineNumber) + + if not self.__GetNextWord(): + raise Warning("expected Component Name At Line ", self.FileName, self.CurrentLineNumber) + + CompStatementObj = ComponentStatement.ComponentStatement() + CompStatementObj.CompName = self.__Token + + if not self.__IsKeyword("COMP_LOC"): + raise Warning("expected COMP_LOC At Line ", self.FileName, self.CurrentLineNumber) + + if not self.__IsToken("="): + raise Warning("expected '=' At Line ", self.FileName, self.CurrentLineNumber) + + CompStatementObj.CompLoc = "" + if self.__GetNextWord(): + CompStatementObj.CompLoc = self.__Token + if self.__IsToken('|'): + if not self.__GetNextWord(): + raise Warning("Expected Region Name At Line ", self.FileName, self.CurrentLineNumber) + + if self.__Token not in ("F", "N", "S"): #, "H", "L", "PH", "PL"): not support + raise Warning("Unknown location type At line ", self.FileName, self.CurrentLineNumber) + + CompStatementObj.FilePos = self.__Token + else: + self.CurrentLineNumber += 1 + self.CurrentOffsetWithinLine = 0 + + if not self.__IsKeyword("COMP_TYPE"): + raise Warning("expected COMP_TYPE At Line ", self.FileName, self.CurrentLineNumber) + + if not self.__IsToken("="): + raise Warning("expected '=' At Line ", self.FileName, self.CurrentLineNumber) + + if not self.__GetNextToken(): + raise Warning("expected Component type At Line ", self.FileName, self.CurrentLineNumber) + if self.__Token not in ("FIT", "PAL_B", "PAL_A", "OEM"): + if not self.__Token.startswith("0x") or len(self.__Token) < 3 or len(self.__Token) > 4 or \ + not self.__HexDigit(self.__Token[2]) or not self.__HexDigit(self.__Token[-1]): + raise Warning("Unknown location type At line ", self.FileName, self.CurrentLineNumber) + CompStatementObj.CompType = self.__Token + + if not self.__IsKeyword("COMP_VER"): + raise Warning("expected COMP_VER At Line ", self.FileName, self.CurrentLineNumber) + + if not self.__IsToken("="): + raise Warning("expected '=' At Line ", self.FileName, self.CurrentLineNumber) + + if not self.__GetNextToken(): + raise Warning("expected Component version At Line ", self.FileName, self.CurrentLineNumber) + + Pattern = re.compile('-$|[0-9]{0,1}[0-9]{1}\.[0-9]{0,1}[0-9]{1}') + if Pattern.match(self.__Token) == None: + raise Warning("Unknown version format At line ", self.FileName, self.CurrentLineNumber) + CompStatementObj.CompVer = self.__Token + + if not self.__IsKeyword("COMP_CS"): + raise Warning("expected COMP_CS At Line ", self.FileName, self.CurrentLineNumber) + + if not self.__IsToken("="): + raise Warning("expected '=' At Line ", self.FileName, self.CurrentLineNumber) + + if not self.__GetNextToken(): + raise Warning("expected Component CS At Line ", self.FileName, self.CurrentLineNumber) + if self.__Token not in ("1", "0"): + raise Warning("Unknown Component CS At line ", self.FileName, self.CurrentLineNumber) + CompStatementObj.CompCs = self.__Token + + + if not self.__IsKeyword("COMP_BIN"): + raise Warning("expected COMP_BIN At Line ", self.FileName, self.CurrentLineNumber) + + if not self.__IsToken("="): + raise Warning("expected '=' At Line ", self.FileName, self.CurrentLineNumber) + + if not self.__GetNextToken(): + raise Warning("expected Component file At Line ", self.FileName, self.CurrentLineNumber) + + CompStatementObj.CompBin = self.__Token + + if not self.__IsKeyword("COMP_SYM"): + raise Warning("expected COMP_SYM At Line ", self.FileName, self.CurrentLineNumber) + + if not self.__IsToken("="): + raise Warning("expected '=' At Line ", self.FileName, self.CurrentLineNumber) + + if not self.__GetNextToken(): + raise Warning("expected Component symbol file At Line ", self.FileName, self.CurrentLineNumber) + + CompStatementObj.CompSym = self.__Token + + if not self.__IsKeyword("COMP_SIZE"): + raise Warning("expected COMP_SIZE At Line ", self.FileName, self.CurrentLineNumber) + + if not self.__IsToken("="): + raise Warning("expected '=' At Line ", self.FileName, self.CurrentLineNumber) + + if self.__IsToken("-"): + CompStatementObj.CompSize = self.__Token + elif self.__GetNextDecimalNumber(): + CompStatementObj.CompSize = self.__Token + elif self.__GetNextHexNumber(): + CompStatementObj.CompSize = self.__Token + else: + raise Warning("Unknown size At line ", self.FileName, self.CurrentLineNumber) + + VtfObj.ComponentStatementList.append(CompStatementObj) + return True + + ## __GetFvInFd() method + # + # Get FV list contained in FD + # + # @param self The object pointer + # @param FdName FD name + # @retval FvList list of FV in FD + # + def __GetFvInFd (self, FdName): + + FvList = [] + if FdName.upper() in self.Profile.FdDict.keys(): + FdObj = self.Profile.FdDict[FdName.upper()] + for elementRegion in FdObj.RegionList: + if elementRegion.RegionType == 'FV': + for elementRegionData in elementRegion.RegionDataList: + if elementRegionData != None and elementRegionData.upper() not in FvList: + FvList.append(elementRegionData.upper()) + return FvList + + ## __GetReferencedFdFvTuple() method + # + # Get FD and FV list referenced by a FFS file + # + # @param self The object pointer + # @param FfsFile contains sections to be searched + # @param RefFdList referenced FD by section + # @param RefFvList referenced FV by section + # + def __GetReferencedFdFvTuple(self, FvObj, RefFdList = [], RefFvList = []): + + for FfsObj in FvObj.FfsList: + if isinstance(FfsObj, FfsFileStatement.FileStatement): + if FfsObj.FvName != None and FfsObj.FvName.upper() not in RefFvList: + RefFvList.append(FfsObj.FvName.upper()) + elif FfsObj.FdName != None and FfsObj.FdName.upper() not in RefFdList: + RefFdList.append(FfsObj.FdName.upper()) + else: + self.__GetReferencedFdFvTupleFromSection(FfsObj, RefFdList, RefFvList) + + ## __GetReferencedFdFvTupleFromSection() method + # + # Get FD and FV list referenced by a FFS section + # + # @param self The object pointer + # @param FfsFile contains sections to be searched + # @param FdList referenced FD by section + # @param FvList referenced FV by section + # + def __GetReferencedFdFvTupleFromSection(self, FfsFile, FdList = [], FvList = []): + + SectionStack = [] + SectionStack.extend(FfsFile.SectionList) + while SectionStack != []: + SectionObj = SectionStack.pop() + if isinstance(SectionObj, FvImageSection.FvImageSection): + if SectionObj.FvName != None and SectionObj.FvName.upper() not in FvList: + FvList.append(SectionObj.FvName.upper()) + if SectionObj.Fv != None and SectionObj.Fv.UiFvName != None and SectionObj.Fv.UiFvName.upper() not in FvList: + FvList.append(SectionObj.Fv.UiFvName.upper()) + self.__GetReferencedFdFvTuple(SectionObj.Fv, FdList, FvList) + + if isinstance(SectionObj, CompressSection.CompressSection) or isinstance(SectionObj, GuidSection.GuidSection): + SectionStack.extend(SectionObj.SectionList) + + ## CycleReferenceCheck() method + # + # Check whether cycle reference exists in FDF + # + # @param self The object pointer + # @retval True cycle reference exists + # @retval False Not exists cycle reference + # + def CycleReferenceCheck(self): + + CycleRefExists = False + + try: + for FvName in self.Profile.FvDict.keys(): + LogStr = "Cycle Reference Checking for FV: %s\n" % FvName + RefFvStack = [] + RefFvStack.append(FvName) + FdAnalyzedList = [] + + while RefFvStack != []: + FvNameFromStack = RefFvStack.pop() + if FvNameFromStack.upper() in self.Profile.FvDict.keys(): + FvObj = self.Profile.FvDict[FvNameFromStack.upper()] + else: + continue + + RefFdList = [] + RefFvList = [] + self.__GetReferencedFdFvTuple(FvObj, RefFdList, RefFvList) + + for RefFdName in RefFdList: + if RefFdName in FdAnalyzedList: + continue + + LogStr += "FD %s is referenced by FV %s\n" % (RefFdName, FvNameFromStack) + FvInFdList = self.__GetFvInFd(RefFdName) + if FvInFdList != []: + LogStr += "FD %s contains FV: " % RefFdName + for FvObj in FvInFdList: + LogStr += FvObj + LogStr += ' \n' + if FvObj not in RefFvStack: + RefFvStack.append(FvObj) + + if FvName in RefFvStack: + CycleRefExists = True + raise Warning(LogStr) + FdAnalyzedList.append(RefFdName) + + for RefFvName in RefFvList: + LogStr += "FV %s is referenced by FV %s\n" % (RefFvName, FvNameFromStack) + if RefFvName not in RefFvStack: + RefFvStack.append(RefFvName) + + if FvName in RefFvStack: + CycleRefExists = True + raise Warning(LogStr) + + except Warning: + print LogStr + + finally: + return CycleRefExists + +if __name__ == "__main__": + parser = FdfParser("..\LakeportX64Pkg.fdf") + try: + parser.ParseFile() + parser.CycleReferenceCheck() + except Warning, X: + print X.message + else: + print "Success!" + diff --git a/BaseTools/Source/Python/Common/GlobalData.py b/BaseTools/Source/Python/Common/GlobalData.py new file mode 100644 index 0000000000..d56152ec8a --- /dev/null +++ b/BaseTools/Source/Python/Common/GlobalData.py @@ -0,0 +1,37 @@ +## @file +# This file is used to define common static strings used by INF/DEC/DSC files +# +# Copyright (c) 2007, 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. + +import re + +gIsWindows = None + +gEdkCompatibilityPkg = "EdkCompatibilityPkg" +gWorkspace = "." +gEdkSource = "EdkCompatibilityPkg" +gEfiSource = "." +gEcpSource = "EdkCompatibilityPkg" + +gOptions = None +gCaseInsensitive = False +gGlobalDefines = {} +gAllFiles = None + +gEdkGlobal = {} +gOverrideDir = {} + +# for debug trace purpose when problem occurs +gProcessingFile = '' +gBuildingModule = '' + +## Regular expression for matching macro used in DSC/DEC/INF file inclusion +gMacroPattern = re.compile("\$\(([_A-Z][_A-Z0-9]*)\)", re.UNICODE) + diff --git a/BaseTools/Source/Python/Common/Identification.py b/BaseTools/Source/Python/Common/Identification.py new file mode 100644 index 0000000000..a9b2f33d55 --- /dev/null +++ b/BaseTools/Source/Python/Common/Identification.py @@ -0,0 +1,58 @@ +## @file +# This file is used to define the identification of INF/DEC/DSC files +# +# Copyright (c) 2007, 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. + +## Identification +# +# This class defined basic Identification information structure which is used by INF/DEC/DSC files +# +# @param object: Inherited from object class +# +# @var FileName: To store data for Filename +# @var FileFullPath: To store data for full path of the file +# @var FileRelativePath: To store data for relative path of the file +# @var RunStatus: Status of build system running +# +class Identification(object): + def __init__(self): + self.FileName = '' + self.FileFullPath = '' + self.FileRelativePath = '' + self.PackagePath = '' + + ## GetFileName + # + # Reserved + # + def GetFileName(self, FileFullPath, FileRelativePath): + pass + + ## GetFileName + # + # Reserved + # + def GetFileFullPath(self, FileName, FileRelativePath): + pass + + ## GetFileName + # + # Reserved + # + def GetFileRelativePath(self, FileName, FileFullPath): + pass + +## +# +# This acts like the main() function for the script, unless it is 'import'ed into another +# script. +# +if __name__ == '__main__': + id = Identification() diff --git a/BaseTools/Source/Python/Common/InfClassObject.py b/BaseTools/Source/Python/Common/InfClassObject.py new file mode 100644 index 0000000000..a772840227 --- /dev/null +++ b/BaseTools/Source/Python/Common/InfClassObject.py @@ -0,0 +1,1116 @@ +## @file +# This file is used to define each component of INF file +# +# Copyright (c) 2007, 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. +# + +## +# Import Modules +# +import os +import re +import EdkLogger +from CommonDataClass.CommonClass import LibraryClassClass +from CommonDataClass.ModuleClass import * +from String import * +from DataType import * +from Identification import * +from Dictionary import * +from BuildToolError import * +from Misc import sdict +import GlobalData +from Table.TableInf import TableInf +import Database +from Parsing import * + +# +# Global variable +# +Section = {TAB_UNKNOWN.upper() : MODEL_UNKNOWN, + TAB_INF_DEFINES.upper() : MODEL_META_DATA_HEADER, + TAB_BUILD_OPTIONS.upper() : MODEL_META_DATA_BUILD_OPTION, + TAB_INCLUDES.upper() : MODEL_EFI_INCLUDE, + TAB_LIBRARIES.upper() : MODEL_EFI_LIBRARY_INSTANCE, + TAB_LIBRARY_CLASSES.upper() : MODEL_EFI_LIBRARY_CLASS, + TAB_PACKAGES.upper() : MODEL_META_DATA_PACKAGE, + TAB_NMAKE.upper() : MODEL_META_DATA_NMAKE, + TAB_INF_FIXED_PCD.upper() : MODEL_PCD_FIXED_AT_BUILD, + TAB_INF_PATCH_PCD.upper() : MODEL_PCD_PATCHABLE_IN_MODULE, + TAB_INF_FEATURE_PCD.upper() : MODEL_PCD_FEATURE_FLAG, + TAB_INF_PCD_EX.upper() : MODEL_PCD_DYNAMIC_EX, + TAB_INF_PCD.upper() : MODEL_PCD_DYNAMIC, + TAB_SOURCES.upper() : MODEL_EFI_SOURCE_FILE, + TAB_GUIDS.upper() : MODEL_EFI_GUID, + TAB_PROTOCOLS.upper() : MODEL_EFI_PROTOCOL, + TAB_PPIS.upper() : MODEL_EFI_PPI, + TAB_DEPEX.upper() : MODEL_EFI_DEPEX, + TAB_BINARIES.upper() : MODEL_EFI_BINARY_FILE, + TAB_USER_EXTENSIONS.upper() : MODEL_META_DATA_USER_EXTENSION + } + +gComponentType2ModuleType = { + "LIBRARY" : "BASE", + "SECURITY_CORE" : "SEC", + "PEI_CORE" : "PEI_CORE", + "COMBINED_PEIM_DRIVER" : "PEIM", + "PIC_PEIM" : "PEIM", + "RELOCATABLE_PEIM" : "PEIM", + "PE32_PEIM" : "PEIM", + "BS_DRIVER" : "DXE_DRIVER", + "RT_DRIVER" : "DXE_RUNTIME_DRIVER", + "SAL_RT_DRIVER" : "DXE_SAL_DRIVER", +# "BS_DRIVER" : "DXE_SMM_DRIVER", +# "BS_DRIVER" : "UEFI_DRIVER", + "APPLICATION" : "UEFI_APPLICATION", + "LOGO" : "BASE", +} + +gNmakeFlagPattern = re.compile("(?:EBC_)?([A-Z]+)_(?:STD_|PROJ_|ARCH_)?FLAGS(?:_DLL|_ASL|_EXE)?", re.UNICODE) +gNmakeFlagName2ToolCode = { + "C" : "CC", + "LIB" : "SLINK", + "LINK" : "DLINK", +} + +class InfHeader(ModuleHeaderClass): + _Mapping_ = { + # + # Required Fields + # + TAB_INF_DEFINES_BASE_NAME : "Name", + TAB_INF_DEFINES_FILE_GUID : "Guid", + TAB_INF_DEFINES_MODULE_TYPE : "ModuleType", + TAB_INF_DEFINES_EFI_SPECIFICATION_VERSION : "EfiSpecificationVersion", + TAB_INF_DEFINES_EDK_RELEASE_VERSION : "EdkReleaseVersion", + # + # Optional Fields + # + TAB_INF_DEFINES_INF_VERSION : "InfVersion", + TAB_INF_DEFINES_BINARY_MODULE : "BinaryModule", + TAB_INF_DEFINES_COMPONENT_TYPE : "ComponentType", + TAB_INF_DEFINES_MAKEFILE_NAME : "MakefileName", + TAB_INF_DEFINES_BUILD_NUMBER : "BuildNumber", + TAB_INF_DEFINES_BUILD_TYPE : "BuildType", + TAB_INF_DEFINES_FFS_EXT : "FfsExt", + TAB_INF_DEFINES_FV_EXT : "FvExt", + TAB_INF_DEFINES_SOURCE_FV : "SourceFv", + TAB_INF_DEFINES_VERSION_NUMBER : "VersionNumber", + TAB_INF_DEFINES_VERSION_STRING : "VersionString", + TAB_INF_DEFINES_VERSION : "Version", + TAB_INF_DEFINES_PCD_IS_DRIVER : "PcdIsDriver", + TAB_INF_DEFINES_TIANO_R8_FLASHMAP_H : "TianoR8FlashMap_h", + TAB_INF_DEFINES_SHADOW : "Shadow", +# TAB_INF_DEFINES_LIBRARY_CLASS : "LibraryClass", +# TAB_INF_DEFINES_ENTRY_POINT : "ExternImages", +# TAB_INF_DEFINES_UNLOAD_IMAGE : "ExternImages", +# TAB_INF_DEFINES_CONSTRUCTOR : , +# TAB_INF_DEFINES_DESTRUCTOR : , +# TAB_INF_DEFINES_DEFINE : "Define", +# TAB_INF_DEFINES_SPEC : "Specification", +# TAB_INF_DEFINES_CUSTOM_MAKEFILE : "CustomMakefile", +# TAB_INF_DEFINES_MACRO : + } + + def __init__(self): + ModuleHeaderClass.__init__(self) + self.VersionNumber = '' + self.VersionString = '' + #print self.__dict__ + def __setitem__(self, key, value): + self.__dict__[self._Mapping_[key]] = value + def __getitem__(self, key): + return self.__dict__[self._Mapping_[key]] + ## "in" test support + def __contains__(self, key): + return key in self._Mapping_ + +## InfObject +# +# This class defined basic Inf object which is used by inheriting +# +# @param object: Inherited from object class +# +class InfObject(object): + def __init__(self): + object.__init__() + +## Inf +# +# This class defined the structure used in Inf object +# +# @param InfObject: Inherited from InfObject class +# @param Ffilename: Input value for Ffilename of Inf file, default is None +# @param IsMergeAllArches: Input value for IsMergeAllArches +# True is to merge all arches +# Fales is not to merge all arches +# default is False +# @param IsToModule: Input value for IsToModule +# True is to transfer to ModuleObject automatically +# False is not to transfer to ModuleObject automatically +# default is False +# @param WorkspaceDir: Input value for current workspace directory, default is None +# +# @var Identification: To store value for Identification, it is a structure as Identification +# @var UserExtensions: To store value for UserExtensions +# @var Module: To store value for Module, it is a structure as ModuleClass +# @var WorkspaceDir: To store value for WorkspaceDir +# @var KeyList: To store value for KeyList, a list for all Keys used in Inf +# +class Inf(InfObject): + def __init__(self, Filename = None, IsToDatabase = False, IsToModule = False, WorkspaceDir = None, Database = None, SupArchList = DataType.ARCH_LIST): + self.Identification = Identification() + self.Module = ModuleClass() + self.UserExtensions = '' + self.WorkspaceDir = WorkspaceDir + self.SupArchList = SupArchList + self.IsToDatabase = IsToDatabase + + self.Cur = Database.Cur + self.TblFile = Database.TblFile + self.TblInf = Database.TblInf + self.FileID = -1 + #self.TblInf = TableInf(Database.Cur) + + self.KeyList = [ + TAB_SOURCES, TAB_BUILD_OPTIONS, TAB_BINARIES, TAB_INCLUDES, TAB_GUIDS, + TAB_PROTOCOLS, TAB_PPIS, TAB_LIBRARY_CLASSES, TAB_PACKAGES, TAB_LIBRARIES, + TAB_INF_FIXED_PCD, TAB_INF_PATCH_PCD, TAB_INF_FEATURE_PCD, TAB_INF_PCD, + TAB_INF_PCD_EX, TAB_DEPEX, TAB_NMAKE, TAB_INF_DEFINES + ] + # + # Upper all KEYs to ignore case sensitive when parsing + # + self.KeyList = map(lambda c: c.upper(), self.KeyList) + + # + # Init RecordSet + # + self.RecordSet = {} + for Key in self.KeyList: + self.RecordSet[Section[Key]] = [] + + # + # Load Inf file if filename is not None + # + if Filename != None: + self.LoadInfFile(Filename) + + # + # Transfer to Module Object if IsToModule is True + # + if IsToModule: + self.InfToModule() + + ## Transfer to Module Object + # + # Transfer all contents of an Inf file to a standard Module Object + # + def InfToModule(self): + # + # Init global information for the file + # + ContainerFile = self.Identification.FileFullPath + + # + # Generate Package Header + # + self.GenModuleHeader(ContainerFile) + + # + # Generate BuildOptions + # + self.GenBuildOptions(ContainerFile) + + # + # Generate Includes + # + self.GenIncludes(ContainerFile) + + # + # Generate Libraries + # + self.GenLibraries(ContainerFile) + + # + # Generate LibraryClasses + # + self.GenLibraryClasses(ContainerFile) + + # + # Generate Packages + # + self.GenPackages(ContainerFile) + + # + # Generate Nmakes + # + self.GenNmakes(ContainerFile) + + # + # Generate Pcds + # + self.GenPcds(ContainerFile) + + # + # Generate Sources + # + self.GenSources(ContainerFile) + + # + # Generate UserExtensions + # + self.GenUserExtensions(ContainerFile) + + # + # Generate Guids + # + self.GenGuidProtocolPpis(DataType.TAB_GUIDS, ContainerFile) + + # + # Generate Protocols + # + self.GenGuidProtocolPpis(DataType.TAB_PROTOCOLS, ContainerFile) + + # + # Generate Ppis + # + self.GenGuidProtocolPpis(DataType.TAB_PPIS, ContainerFile) + + # + # Generate Depexes + # + self.GenDepexes(ContainerFile) + + # + # Generate Binaries + # + self.GenBinaries(ContainerFile) + + ## Parse [Defines] section + # + # Parse [Defines] section into InfDefines object + # + # @param InfFile The path of the INF file + # @param Section The title of "Defines" section + # @param Lines The content of "Defines" section + # + def ParseDefines(self, InfFile, Section, Lines): + TokenList = Section.split(TAB_SPLIT) + if len(TokenList) == 3: + RaiseParserError(Section, "Defines", InfFile, "[xx.yy.%s] format (with platform) is not supported") + if len(TokenList) == 2: + Arch = TokenList[1].upper() + else: + Arch = TAB_ARCH_COMMON + + if Arch not in self.Defines: + self.Defines[Arch] = InfDefines() + GetSingleValueOfKeyFromLines(Lines, self.Defines[Arch].DefinesDictionary, + TAB_COMMENT_SPLIT, TAB_EQUAL_SPLIT, False, None) + + ## Load Inf file + # + # Load the file if it exists + # + # @param Filename: Input value for filename of Inf file + # + def LoadInfFile(self, Filename): + # + # Insert a record for file + # + Filename = NormPath(Filename) + self.Identification.FileFullPath = Filename + (self.Identification.FileRelativePath, self.Identification.FileName) = os.path.split(Filename) + self.FileID = self.TblFile.InsertFile(Filename, MODEL_FILE_INF) + + # + # Init InfTable + # + #self.TblInf.Table = "Inf%s" % self.FileID + #self.TblInf.Create() + + # + # Init common datas + # + IfDefList, SectionItemList, CurrentSection, ArchList, ThirdList, IncludeFiles = \ + [], [], TAB_UNKNOWN, [], [], [] + LineNo = 0 + + # + # Parse file content + # + IsFindBlockComment = False + ReservedLine = '' + for Line in open(Filename, 'r'): + LineNo = LineNo + 1 + # + # Remove comment block + # + if Line.find(TAB_COMMENT_R8_START) > -1: + ReservedLine = GetSplitValueList(Line, TAB_COMMENT_R8_START, 1)[0] + IsFindBlockComment = True + if Line.find(TAB_COMMENT_R8_END) > -1: + Line = ReservedLine + GetSplitValueList(Line, TAB_COMMENT_R8_END, 1)[1] + ReservedLine = '' + IsFindBlockComment = False + if IsFindBlockComment: + continue + + # + # Remove comments at tail and remove spaces again + # + Line = CleanString(Line) + if Line == '': + continue + + # + # Find a new section tab + # First insert previous section items + # And then parse the content of the new section + # + if Line.startswith(TAB_SECTION_START) and Line.endswith(TAB_SECTION_END): + if Line[1:3] == "--": + continue + Model = Section[CurrentSection.upper()] + # + # Insert items data of previous section + # + InsertSectionItemsIntoDatabase(self.TblInf, self.FileID, Filename, Model, CurrentSection, SectionItemList, ArchList, ThirdList, IfDefList, self.RecordSet) + # + # Parse the new section + # + SectionItemList = [] + ArchList = [] + ThirdList = [] + + CurrentSection = '' + LineList = GetSplitValueList(Line[len(TAB_SECTION_START):len(Line) - len(TAB_SECTION_END)], TAB_COMMA_SPLIT) + for Item in LineList: + ItemList = GetSplitValueList(Item, TAB_SPLIT) + if CurrentSection == '': + CurrentSection = ItemList[0] + else: + if CurrentSection != ItemList[0]: + EdkLogger.error("Parser", PARSER_ERROR, "Different section names '%s' and '%s' are found in one section definition, this is not allowed." % (CurrentSection, ItemList[0]), File=Filename, Line=LineNo, RaiseError = EdkLogger.IsRaiseError) + if CurrentSection.upper() not in self.KeyList: + RaiseParserError(Line, CurrentSection, Filename, '', LineNo) + CurrentSection = TAB_UNKNOWN + continue + ItemList.append('') + ItemList.append('') + if len(ItemList) > 5: + RaiseParserError(Line, CurrentSection, Filename, '', LineNo) + else: + if ItemList[1] != '' and ItemList[1].upper() not in ARCH_LIST_FULL: + EdkLogger.error("Parser", PARSER_ERROR, "Invalid Arch definition '%s' found" % ItemList[1], File=Filename, Line=LineNo, RaiseError = EdkLogger.IsRaiseError) + ArchList.append(ItemList[1].upper()) + ThirdList.append(ItemList[2]) + + continue + + # + # Not in any defined section + # + if CurrentSection == TAB_UNKNOWN: + ErrorMsg = "%s is not in any defined section" % Line + EdkLogger.error("Parser", PARSER_ERROR, ErrorMsg, File=Filename, Line=LineNo, RaiseError = EdkLogger.IsRaiseError) + + # + # Add a section item + # + SectionItemList.append([Line, LineNo]) + # End of parse + #End of For + + # + # Insert items data of last section + # + Model = Section[CurrentSection.upper()] + InsertSectionItemsIntoDatabase(self.TblInf, self.FileID, Filename, Model, CurrentSection, SectionItemList, ArchList, ThirdList, IfDefList, self.RecordSet) + + # + # Replace all DEFINE macros with its actual values + # + ParseDefineMacro2(self.TblInf, self.RecordSet, GlobalData.gGlobalDefines) + + ## Show detailed information of Module + # + # Print all members and their values of Module class + # + def ShowModule(self): + M = self.Module + for Arch in M.Header.keys(): + print '\nArch =', Arch + print 'Filename =', M.Header[Arch].FileName + print 'FullPath =', M.Header[Arch].FullPath + print 'BaseName =', M.Header[Arch].Name + print 'Guid =', M.Header[Arch].Guid + print 'Version =', M.Header[Arch].Version + print 'InfVersion =', M.Header[Arch].InfVersion + print 'EfiSpecificationVersion =', M.Header[Arch].EfiSpecificationVersion + print 'EdkReleaseVersion =', M.Header[Arch].EdkReleaseVersion + print 'ModuleType =', M.Header[Arch].ModuleType + print 'BinaryModule =', M.Header[Arch].BinaryModule + print 'ComponentType =', M.Header[Arch].ComponentType + print 'MakefileName =', M.Header[Arch].MakefileName + print 'BuildNumber =', M.Header[Arch].BuildNumber + print 'BuildType =', M.Header[Arch].BuildType + print 'FfsExt =', M.Header[Arch].FfsExt + print 'FvExt =', M.Header[Arch].FvExt + print 'SourceFv =', M.Header[Arch].SourceFv + print 'PcdIsDriver =', M.Header[Arch].PcdIsDriver + print 'TianoR8FlashMap_h =', M.Header[Arch].TianoR8FlashMap_h + print 'Shadow =', M.Header[Arch].Shadow + print 'LibraryClass =', M.Header[Arch].LibraryClass + for Item in M.Header[Arch].LibraryClass: + print Item.LibraryClass, DataType.TAB_VALUE_SPLIT.join(Item.SupModuleList) + print 'CustomMakefile =', M.Header[Arch].CustomMakefile + print 'Define =', M.Header[Arch].Define + print 'Specification =', M.Header[Arch].Specification + for Item in self.Module.ExternImages: + print '\nEntry_Point = %s, UnloadImage = %s' % (Item.ModuleEntryPoint, Item.ModuleUnloadImage) + for Item in self.Module.ExternLibraries: + print 'Constructor = %s, Destructor = %s' % (Item.Constructor, Item.Destructor) + print '\nBuildOptions =', M.BuildOptions + for Item in M.BuildOptions: + print Item.ToolChainFamily, Item.ToolChain, Item.Option, Item.SupArchList + print '\nIncludes =', M.Includes + for Item in M.Includes: + print Item.FilePath, Item.SupArchList + print '\nLibraries =', M.Libraries + for Item in M.Libraries: + print Item.Library, Item.SupArchList + print '\nLibraryClasses =', M.LibraryClasses + for Item in M.LibraryClasses: + print Item.LibraryClass, Item.RecommendedInstance, Item.FeatureFlag, Item.SupModuleList, Item.SupArchList, Item.Define + print '\nPackageDependencies =', M.PackageDependencies + for Item in M.PackageDependencies: + print Item.FilePath, Item.SupArchList, Item.FeatureFlag + print '\nNmake =', M.Nmake + for Item in M.Nmake: + print Item.Name, Item.Value, Item.SupArchList + print '\nPcds =', M.PcdCodes + for Item in M.PcdCodes: + print '\tCName=',Item.CName, 'TokenSpaceGuidCName=', Item.TokenSpaceGuidCName, 'DefaultValue=', Item.DefaultValue, 'ItemType=', Item.ItemType, Item.SupArchList + print '\nSources =', M.Sources + for Source in M.Sources: + print Source.SourceFile, 'Fam=', Source.ToolChainFamily, 'Pcd=', Source.FeatureFlag, 'Tag=', Source.TagName, 'ToolCode=', Source.ToolCode, Source.SupArchList + print '\nUserExtensions =', M.UserExtensions + for UserExtension in M.UserExtensions: + print UserExtension.UserID, UserExtension.Identifier,UserExtension.Content + print '\nGuids =', M.Guids + for Item in M.Guids: + print Item.CName, Item.SupArchList, Item.FeatureFlag + print '\nProtocols =', M.Protocols + for Item in M.Protocols: + print Item.CName, Item.SupArchList, Item.FeatureFlag + print '\nPpis =', M.Ppis + for Item in M.Ppis: + print Item.CName, Item.SupArchList, Item.FeatureFlag + print '\nDepex =', M.Depex + for Item in M.Depex: + print Item.Depex, Item.SupArchList, Item.Define + print '\nBinaries =', M.Binaries + for Binary in M.Binaries: + print 'Type=', Binary.FileType, 'Target=', Binary.Target, 'Name=', Binary.BinaryFile, 'FeatureFlag=', Binary.FeatureFlag, 'SupArchList=', Binary.SupArchList + + ## Convert [Defines] section content to ModuleHeaderClass + # + # Convert [Defines] section content to ModuleHeaderClass + # + # @param Defines The content under [Defines] section + # @param ModuleHeader An object of ModuleHeaderClass + # @param Arch The supported ARCH + # + def GenModuleHeader(self, ContainerFile): + EdkLogger.debug(2, "Generate ModuleHeader ...") + File = self.Identification.FileFullPath + # + # Update all defines item in database + # + RecordSet = self.RecordSet[MODEL_META_DATA_HEADER] + for Record in RecordSet: + ValueList = GetSplitValueList(Record[0], TAB_EQUAL_SPLIT) + if len(ValueList) != 2: + RaiseParserError(Record[0], 'Defines', ContainerFile, ' = ', Record[2]) + ID, Value1, Value2, Arch, LineNo = Record[3], ValueList[0], ValueList[1], Record[1], Record[2] + SqlCommand = """update %s set Value1 = '%s', Value2 = '%s' + where ID = %s""" % (self.TblInf.Table, ConvertToSqlString2(Value1), ConvertToSqlString2(Value2), ID) + self.TblInf.Exec(SqlCommand) + + for Arch in DataType.ARCH_LIST: + ModuleHeader = InfHeader() + ModuleHeader.FileName = self.Identification.FileName + ModuleHeader.FullPath = self.Identification.FileFullPath + DefineList = QueryDefinesItem2(self.TblInf, Arch, self.FileID) + + NotProcessedDefineList = [] + for D in DefineList: + if D[0] in ModuleHeader: + ModuleHeader[D[0]] = GetSplitValueList(D[1])[0] + else: + NotProcessedDefineList.append(D) + + if ModuleHeader.ComponentType == "LIBRARY": + Lib = LibraryClassClass() + Lib.LibraryClass = ModuleHeader.Name + Lib.SupModuleList = DataType.SUP_MODULE_LIST + ModuleHeader.LibraryClass.append(Lib) + + # we need to make some key defines resolved first + for D in NotProcessedDefineList: + if D[0] == TAB_INF_DEFINES_LIBRARY_CLASS: + List = GetSplitValueList(D[1], DataType.TAB_VALUE_SPLIT, 1) + Lib = LibraryClassClass() + Lib.LibraryClass = CleanString(List[0]) + if len(List) == 1: + Lib.SupModuleList = DataType.SUP_MODULE_LIST + elif len(List) == 2: + Lib.SupModuleList = GetSplitValueList(CleanString(List[1]), ' ') + ModuleHeader.LibraryClass.append(Lib) + elif D[0] == TAB_INF_DEFINES_CUSTOM_MAKEFILE: + List = D[1].split(DataType.TAB_VALUE_SPLIT) + if len(List) == 2: + ModuleHeader.CustomMakefile[CleanString(List[0])] = CleanString(List[1]) + else: + RaiseParserError(D[1], 'CUSTOM_MAKEFILE of Defines', File, 'CUSTOM_MAKEFILE=|', D[2]) + elif D[0] == TAB_INF_DEFINES_ENTRY_POINT: + Image = ModuleExternImageClass() + Image.ModuleEntryPoint = CleanString(D[1]) + self.Module.ExternImages.append(Image) + elif D[0] == TAB_INF_DEFINES_UNLOAD_IMAGE: + Image = ModuleExternImageClass() + Image.ModuleUnloadImage = CleanString(D[1]) + self.Module.ExternImages.append(Image) + elif D[0] == TAB_INF_DEFINES_CONSTRUCTOR: + LibraryClass = ModuleExternLibraryClass() + LibraryClass.Constructor = CleanString(D[1]) + self.Module.ExternLibraries.append(LibraryClass) + elif D[0] == TAB_INF_DEFINES_DESTRUCTOR: + LibraryClass = ModuleExternLibraryClass() + LibraryClass.Destructor = CleanString(D[1]) + self.Module.ExternLibraries.append(LibraryClass) + elif D[0] == TAB_INF_DEFINES_DEFINE: + List = D[1].split(DataType.TAB_EQUAL_SPLIT) + if len(List) != 2: + RaiseParserError(Item, 'DEFINE of Defines', File, 'DEFINE = ', D[2]) + else: + ModuleHeader.Define[CleanString(List[0])] = CleanString(List[1]) + elif D[0] == TAB_INF_DEFINES_SPEC: + List = D[1].split(DataType.TAB_EQUAL_SPLIT) + if len(List) != 2: + RaiseParserError(Item, 'SPEC of Defines', File, 'SPEC = ', D[2]) + else: + ModuleHeader.Specification[CleanString(List[0])] = CleanString(List[1]) + + # + # Get version of INF + # + if ModuleHeader.InfVersion != "": + # R9 inf + VersionNumber = ModuleHeader.VersionNumber + VersionString = ModuleHeader.VersionString + if len(VersionNumber) > 0 and len(VersionString) == 0: + EdkLogger.warn(2000, 'VERSION_NUMBER depricated; INF file %s should be modified to use VERSION_STRING instead.' % self.Identification.FileFullPath) + ModuleHeader.Version = VersionNumber + if len(VersionString) > 0: + if len(VersionNumber) > 0: + EdkLogger.warn(2001, 'INF file %s defines both VERSION_NUMBER and VERSION_STRING, using VERSION_STRING' % self.Identification.FileFullPath) + ModuleHeader.Version = VersionString + else: + # R8 inf + ModuleHeader.InfVersion = "0x00010000" + if ModuleHeader.ComponentType in gComponentType2ModuleType: + ModuleHeader.ModuleType = gComponentType2ModuleType[ModuleHeader.ComponentType] + elif ModuleHeader.ComponentType != '': + EdkLogger.error("Parser", PARSER_ERROR, "Unsupported R8 component type [%s]" % ModuleHeader.ComponentType, ExtraData=File, RaiseError = EdkLogger.IsRaiseError) + + self.Module.Header[Arch] = ModuleHeader + + + ## GenBuildOptions + # + # Gen BuildOptions of Inf + # [:]=Flag + # + # @param ContainerFile: The Inf file full path + # + def GenBuildOptions(self, ContainerFile): + EdkLogger.debug(2, "Generate %s ..." % TAB_BUILD_OPTIONS) + BuildOptions = {} + # + # Get all BuildOptions + # + RecordSet = self.RecordSet[MODEL_META_DATA_BUILD_OPTION] + + # + # Go through each arch + # + for Arch in self.SupArchList: + for Record in RecordSet: + if Record[1] == Arch or Record[1] == TAB_ARCH_COMMON: + (Family, ToolChain, Flag) = GetBuildOption(Record[0], ContainerFile, Record[2]) + MergeArches(BuildOptions, (Family, ToolChain, Flag), Arch) + # + # Update to Database + # + if self.IsToDatabase: + SqlCommand = """update %s set Value1 = '%s', Value2 = '%s', Value3 = '%s' + where ID = %s""" % (self.TblInf.Table, ConvertToSqlString2(Family), ConvertToSqlString2(ToolChain), ConvertToSqlString2(Flag), Record[3]) + self.TblInf.Exec(SqlCommand) + + for Key in BuildOptions.keys(): + BuildOption = BuildOptionClass(Key[0], Key[1], Key[2]) + BuildOption.SupArchList = BuildOptions[Key] + self.Module.BuildOptions.append(BuildOption) + + ## GenIncludes + # + # Gen Includes of Inf + # + # + # @param ContainerFile: The Inf file full path + # + def GenIncludes(self, ContainerFile): + EdkLogger.debug(2, "Generate %s ..." % TAB_INCLUDES) + Includes = sdict() + # + # Get all Includes + # + RecordSet = self.RecordSet[MODEL_EFI_INCLUDE] + + # + # Go through each arch + # + for Arch in self.SupArchList: + for Record in RecordSet: + if Record[1] == Arch or Record[1] == TAB_ARCH_COMMON: + MergeArches(Includes, Record[0], Arch) + + for Key in Includes.keys(): + Include = IncludeClass() + Include.FilePath = NormPath(Key) + Include.SupArchList = Includes[Key] + self.Module.Includes.append(Include) + + ## GenLibraries + # + # Gen Libraries of Inf + # + # + # @param ContainerFile: The Inf file full path + # + def GenLibraries(self, ContainerFile): + EdkLogger.debug(2, "Generate %s ..." % TAB_LIBRARIES) + Libraries = sdict() + # + # Get all Includes + # + RecordSet = self.RecordSet[MODEL_EFI_LIBRARY_INSTANCE] + + # + # Go through each arch + # + for Arch in self.SupArchList: + for Record in RecordSet: + if Record[1] == Arch or Record[1] == TAB_ARCH_COMMON: + MergeArches(Libraries, Record[0], Arch) + + for Key in Libraries.keys(): + Library = ModuleLibraryClass() + # replace macro and remove file extension + Library.Library = Key.rsplit('.', 1)[0] + Library.SupArchList = Libraries[Key] + self.Module.Libraries.append(Library) + + ## GenLibraryClasses + # + # Get LibraryClass of Inf + # | + # + # @param ContainerFile: The Inf file full path + # + def GenLibraryClasses(self, ContainerFile): + EdkLogger.debug(2, "Generate %s ..." % TAB_LIBRARY_CLASSES) + LibraryClasses = {} + # + # Get all LibraryClasses + # + RecordSet = self.RecordSet[MODEL_EFI_LIBRARY_CLASS] + + # + # Go through each arch + # + for Arch in self.SupArchList: + for Record in RecordSet: + if Record[1] == Arch or Record[1] == TAB_ARCH_COMMON: + (LibClassName, LibClassIns, Pcd, SupModelList) = GetLibraryClassOfInf([Record[0], Record[4]], ContainerFile, self.WorkspaceDir, Record[2]) + MergeArches(LibraryClasses, (LibClassName, LibClassIns, Pcd, SupModelList), Arch) + # + # Update to Database + # + if self.IsToDatabase: + SqlCommand = """update %s set Value1 = '%s', Value2 = '%s', Value3 = '%s' + where ID = %s""" % (self.TblInf.Table, ConvertToSqlString2(LibClassName), ConvertToSqlString2(LibClassIns), ConvertToSqlString2(SupModelList), Record[3]) + self.TblInf.Exec(SqlCommand) + + for Key in LibraryClasses.keys(): + KeyList = Key[0].split(DataType.TAB_VALUE_SPLIT) + LibraryClass = LibraryClassClass() + LibraryClass.LibraryClass = Key[0] + LibraryClass.RecommendedInstance = NormPath(Key[1]) + LibraryClass.FeatureFlag = Key[2] + LibraryClass.SupArchList = LibraryClasses[Key] + LibraryClass.SupModuleList = GetSplitValueList(Key[3]) + self.Module.LibraryClasses.append(LibraryClass) + + ## GenPackages + # + # Gen Packages of Inf + # + # + # @param ContainerFile: The Inf file full path + # + def GenPackages(self, ContainerFile): + EdkLogger.debug(2, "Generate %s ..." % TAB_PACKAGES) + Packages = {} + # + # Get all Packages + # + RecordSet = self.RecordSet[MODEL_META_DATA_PACKAGE] + + # + # Go through each arch + # + for Arch in self.SupArchList: + for Record in RecordSet: + if Record[1] == Arch or Record[1] == TAB_ARCH_COMMON: + (Package, Pcd) = GetPackage(Record[0], ContainerFile, self.WorkspaceDir, Record[2]) + MergeArches(Packages, (Package, Pcd), Arch) + if self.IsToDatabase: + SqlCommand = """update %s set Value1 = '%s', Value2 = '%s' + where ID = %s""" % (self.TblInf.Table, ConvertToSqlString2(Package), ConvertToSqlString2(Pcd), Record[3]) + self.TblInf.Exec(SqlCommand) + + + for Key in Packages.keys(): + Package = ModulePackageDependencyClass() + Package.FilePath = NormPath(Key[0]) + Package.SupArchList = Packages[Key] + Package.FeatureFlag = Key[1] + self.Module.PackageDependencies.append(Package) + + ## GenNmakes + # + # Gen Nmakes of Inf + # + # + # @param ContainerFile: The Inf file full path + # + def GenNmakes(self, ContainerFile): + EdkLogger.debug(2, "Generate %s ..." % TAB_NMAKE) + Nmakes = sdict() + # + # Get all Nmakes + # + RecordSet = self.RecordSet[MODEL_META_DATA_NMAKE] + + + # + # Go through each arch + # + for Arch in self.SupArchList: + for Record in RecordSet: + if Record[1] == Arch or Record[1] == TAB_ARCH_COMMON: + MergeArches(Nmakes, Record[0], Arch) + + for Key in Nmakes.keys(): + List = GetSplitValueList(Key, DataType.TAB_EQUAL_SPLIT, MaxSplit=1) + if len(List) != 2: + RaiseParserError(Key, 'Nmake', ContainerFile, ' = ') + continue + Nmake = ModuleNmakeClass() + Nmake.Name = List[0] + Nmake.Value = List[1] + Nmake.SupArchList = Nmakes[Key] + self.Module.Nmake.append(Nmake) + + # convert R8 format to R9 format + if Nmake.Name == "IMAGE_ENTRY_POINT": + Image = ModuleExternImageClass() + Image.ModuleEntryPoint = Nmake.Value + self.Module.ExternImages.append(Image) + elif Nmake.Name == "DPX_SOURCE": + Source = ModuleSourceFileClass(NormPath(Nmake.Value), "", "", "", "", Nmake.SupArchList) + self.Module.Sources.append(Source) + else: + ToolList = gNmakeFlagPattern.findall(Nmake.Name) + if len(ToolList) == 0 or len(ToolList) != 1: + EdkLogger.warn("\nParser", "Don't know how to do with MACRO: %s" % Nmake.Name, + ExtraData=ContainerFile) + else: + if ToolList[0] in gNmakeFlagName2ToolCode: + Tool = gNmakeFlagName2ToolCode[ToolList[0]] + else: + Tool = ToolList[0] + BuildOption = BuildOptionClass("MSFT", "*_*_*_%s_FLAGS" % Tool, Nmake.Value) + BuildOption.SupArchList = Nmake.SupArchList + self.Module.BuildOptions.append(BuildOption) + + ## GenPcds + # + # Gen Pcds of Inf + # .[|] + # + # @param ContainerFile: The Dec file full path + # + def GenPcds(self, ContainerFile): + EdkLogger.debug(2, "Generate %s ..." % TAB_PCDS) + Pcds = {} + PcdToken = {} + + # + # Get all Guids + # + RecordSet1 = self.RecordSet[MODEL_PCD_FIXED_AT_BUILD] + RecordSet2 = self.RecordSet[MODEL_PCD_PATCHABLE_IN_MODULE] + RecordSet3 = self.RecordSet[MODEL_PCD_FEATURE_FLAG] + RecordSet4 = self.RecordSet[MODEL_PCD_DYNAMIC_EX] + RecordSet5 = self.RecordSet[MODEL_PCD_DYNAMIC] + + # + # Go through each arch + # + for Arch in self.SupArchList: + for Record in RecordSet1: + if Record[1] == Arch or Record[1] == TAB_ARCH_COMMON: + if self.Module.Header[Arch].LibraryClass != {}: + pass + (TokenGuidCName, TokenName, Value, Type) = GetPcdOfInf(Record[0], TAB_PCDS_FIXED_AT_BUILD, ContainerFile, Record[2]) + MergeArches(Pcds, (TokenGuidCName, TokenName, Value, Type), Arch) + PcdToken[Record[3]] = (TokenGuidCName, TokenName) + for Record in RecordSet2: + if Record[1] == Arch or Record[1] == TAB_ARCH_COMMON: + (TokenGuidCName, TokenName, Value, Type) = GetPcdOfInf(Record[0], TAB_PCDS_PATCHABLE_IN_MODULE, ContainerFile, Record[2]) + MergeArches(Pcds, (TokenGuidCName, TokenName, Value, Type), Arch) + PcdToken[Record[3]] = (TokenGuidCName, TokenName) + for Record in RecordSet3: + if Record[1] == Arch or Record[1] == TAB_ARCH_COMMON: + (TokenGuidCName, TokenName, Value, Type) = GetPcdOfInf(Record[0], TAB_PCDS_FEATURE_FLAG, ContainerFile, Record[2]) + MergeArches(Pcds, (TokenGuidCName, TokenName, Value, Type), Arch) + PcdToken[Record[3]] = (TokenGuidCName, TokenName) + for Record in RecordSet4: + if Record[1] == Arch or Record[1] == TAB_ARCH_COMMON: + (TokenGuidCName, TokenName, Value, Type) = GetPcdOfInf(Record[0], TAB_PCDS_DYNAMIC_EX, ContainerFile, Record[2]) + MergeArches(Pcds, (TokenGuidCName, TokenName, Value, Type), Arch) + PcdToken[Record[3]] = (TokenGuidCName, TokenName) + for Record in RecordSet5: + if Record[1] == Arch or Record[1] == TAB_ARCH_COMMON: + (TokenGuidCName, TokenName, Value, Type) = GetPcdOfInf(Record[0], "", ContainerFile, Record[2]) + MergeArches(Pcds, (TokenGuidCName, TokenName, Value, Type), Arch) + PcdToken[Record[3]] = (TokenGuidCName, TokenName) + # + # Update to database + # + if self.IsToDatabase: + for Key in PcdToken.keys(): + SqlCommand = """update %s set Value2 = '%s' where ID = %s""" % (self.TblInf.Table, ".".join((PcdToken[Key][0], PcdToken[Key][1])), Key) + self.TblInf.Exec(SqlCommand) + + for Key in Pcds.keys(): + Pcd = PcdClass() + Pcd.CName = Key[1] + Pcd.TokenSpaceGuidCName = Key[0] + Pcd.DefaultValue = Key[2] + Pcd.ItemType = Key[3] + Pcd.SupArchList = Pcds[Key] + self.Module.PcdCodes.append(Pcd) + + ## GenSources + # + # Gen Sources of Inf + # [|[|[|[|]]]] + # + # @param ContainerFile: The Dec file full path + # + def GenSources(self, ContainerFile): + EdkLogger.debug(2, "Generate %s ..." % TAB_SOURCES) + Sources = {} + + # + # Get all Nmakes + # + RecordSet = self.RecordSet[MODEL_EFI_SOURCE_FILE] + + # + # Go through each arch + # + for Arch in self.SupArchList: + for Record in RecordSet: + if Record[1] == Arch or Record[1] == TAB_ARCH_COMMON: + (Filename, Family, TagName, ToolCode, Pcd) = GetSource(Record[0], ContainerFile, self.Identification.FileRelativePath, Record[2]) + MergeArches(Sources, (Filename, Family, TagName, ToolCode, Pcd), Arch) + if self.IsToDatabase: + SqlCommand = """update %s set Value1 = '%s', Value2 = '%s', Value3 = '%s', Value4 = '%s', Value5 = '%s' + where ID = %s""" % (self.TblInf.Table, ConvertToSqlString2(Filename), ConvertToSqlString2(Family), ConvertToSqlString2(TagName), ConvertToSqlString2(ToolCode), ConvertToSqlString2(Pcd), Record[3]) + self.TblInf.Exec(SqlCommand) + + for Key in Sources.keys(): + Source = ModuleSourceFileClass(Key[0], Key[2], Key[3], Key[1], Key[4], Sources[Key]) + self.Module.Sources.append(Source) + + ## GenUserExtensions + # + # Gen UserExtensions of Inf + # + def GenUserExtensions(self, ContainerFile): +# # +# # UserExtensions +# # +# if self.UserExtensions != '': +# UserExtension = UserExtensionsClass() +# Lines = self.UserExtensions.splitlines() +# List = GetSplitValueList(Lines[0], DataType.TAB_SPLIT, 2) +# if len(List) != 3: +# RaiseParserError(Lines[0], 'UserExtensions', File, "UserExtensions.UserId.'Identifier'") +# else: +# UserExtension.UserID = List[1] +# UserExtension.Identifier = List[2][0:-1].replace("'", '').replace('\"', '') +# for Line in Lines[1:]: +# UserExtension.Content = UserExtension.Content + CleanString(Line) + '\n' +# self.Module.UserExtensions.append(UserExtension) + pass + + ## GenDepexes + # + # Gen Depex of Inf + # + # @param ContainerFile: The Inf file full path + # + def GenDepexes(self, ContainerFile): + EdkLogger.debug(2, "Generate %s ..." % TAB_DEPEX) + Depex = {} + # + # Get all Depexes + # + RecordSet = self.RecordSet[MODEL_EFI_DEPEX] + + # + # Go through each arch + # + for Arch in self.SupArchList: + Line = '' + for Record in RecordSet: + if Record[1] == Arch or Record[1] == TAB_ARCH_COMMON: + Line = Line + Record[0] + ' ' + if Line != '': + MergeArches(Depex, Line, Arch) + + for Key in Depex.keys(): + Dep = ModuleDepexClass() + Dep.Depex = Key + Dep.SupArchList = Depex[Key] + self.Module.Depex.append(Dep) + + ## GenBinaries + # + # Gen Binary of Inf + # ||[|.] + # + # @param ContainerFile: The Dec file full path + # + def GenBinaries(self, ContainerFile): + EdkLogger.debug(2, "Generate %s ..." % TAB_BINARIES) + Binaries = {} + + # + # Get all Guids + # + RecordSet = self.RecordSet[MODEL_EFI_BINARY_FILE] + + # + # Go through each arch + # + for Arch in self.SupArchList: + for Record in RecordSet: + if Record[1] == Arch or Record[1] == TAB_ARCH_COMMON: + (FileType, Filename, Target, Pcd) = GetBinary(Record[0], ContainerFile, self.Identification.FileRelativePath, Record[2]) + MergeArches(Binaries, (FileType, Filename, Target, Pcd), Arch) + if self.IsToDatabase: + SqlCommand = """update %s set Value1 = '%s', Value2 = '%s', Value3 = '%s', Value4 = '%s' + where ID = %s""" % (self.TblInf.Table, ConvertToSqlString2(FileType), ConvertToSqlString2(Filename), ConvertToSqlString2(Target), ConvertToSqlString2(Pcd), Record[3]) + self.TblInf.Exec(SqlCommand) + + for Key in Binaries.keys(): + Binary = ModuleBinaryFileClass(NormPath(Key[1]), Key[0], Key[2], Key[3], Binaries[Key]) + self.Module.Binaries.append(Binary) + + ## GenGuids + # + # Gen Guids of Inf + # = + # + # @param ContainerFile: The Inf file full path + # + def GenGuidProtocolPpis(self, Type, ContainerFile): + EdkLogger.debug(2, "Generate %s ..." % Type) + Lists = {} + # + # Get all Items + # + RecordSet = self.RecordSet[Section[Type.upper()]] + + # + # Go through each arch + # + for Arch in self.SupArchList: + for Record in RecordSet: + if Record[1] == Arch or Record[1] == TAB_ARCH_COMMON: + (Name, Value) = GetGuidsProtocolsPpisOfInf(Record[0], Type, ContainerFile, Record[2]) + MergeArches(Lists, (Name, Value), Arch) + if self.IsToDatabase: + SqlCommand = """update %s set Value1 = '%s', Value2 = '%s' + where ID = %s""" % (self.TblInf.Table, ConvertToSqlString2(Name), ConvertToSqlString2(Value), Record[3]) + self.TblInf.Exec(SqlCommand) + + ListMember = None + if Type == TAB_GUIDS: + ListMember = self.Module.Guids + elif Type == TAB_PROTOCOLS: + ListMember = self.Module.Protocols + elif Type == TAB_PPIS: + ListMember = self.Module.Ppis + + for Key in Lists.keys(): + ListClass = GuidProtocolPpiCommonClass() + ListClass.CName = Key[0] + ListClass.SupArchList = Lists[Key] + ListClass.FeatureFlag = Key[1] + ListMember.append(ListClass) + +## +# +# This acts like the main() function for the script, unless it is 'import'ed into another +# script. +# +if __name__ == '__main__': + EdkLogger.Initialize() + EdkLogger.SetLevel(EdkLogger.DEBUG_0) + + W = os.getenv('WORKSPACE') + F = os.path.join(W, 'MdeModulePkg/Application/HelloWorld/HelloWorld.inf') + + Db = Database.Database('Inf.db') + Db.InitDatabase() + + P = Inf(os.path.normpath(F), True, True, W, Db) + P.ShowModule() + + Db.Close() diff --git a/BaseTools/Source/Python/Common/InfClassObjectLight.py b/BaseTools/Source/Python/Common/InfClassObjectLight.py new file mode 100644 index 0000000000..a655828e6a --- /dev/null +++ b/BaseTools/Source/Python/Common/InfClassObjectLight.py @@ -0,0 +1,876 @@ +## @file +# This file is used to define each component of INF file +# +# Copyright (c) 2007, 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. +# + +## +# Import Modules +# +import os +import re +import EdkLogger + +from CommonDataClass.ModuleClass import * +from CommonDataClass import CommonClass +from String import * +from DataType import * +from BuildToolError import * +from Misc import sdict +from Misc import GetFiles +from Parsing import * + +# Global variable +Section = {TAB_UNKNOWN.upper() : MODEL_UNKNOWN, + TAB_INF_DEFINES.upper() : MODEL_META_DATA_HEADER, + TAB_BUILD_OPTIONS.upper() : MODEL_META_DATA_BUILD_OPTION, + TAB_INCLUDES.upper() : MODEL_EFI_INCLUDE, + TAB_LIBRARIES.upper() : MODEL_EFI_LIBRARY_INSTANCE, + TAB_LIBRARY_CLASSES.upper() : MODEL_EFI_LIBRARY_CLASS, + TAB_PACKAGES.upper() : MODEL_META_DATA_PACKAGE, + TAB_NMAKE.upper() : MODEL_META_DATA_NMAKE, + TAB_INF_FIXED_PCD.upper() : MODEL_PCD_FIXED_AT_BUILD, + TAB_INF_PATCH_PCD.upper() : MODEL_PCD_PATCHABLE_IN_MODULE, + TAB_INF_FEATURE_PCD.upper() : MODEL_PCD_FEATURE_FLAG, + TAB_INF_PCD_EX.upper() : MODEL_PCD_DYNAMIC_EX, + TAB_INF_PCD.upper() : MODEL_PCD_DYNAMIC, + TAB_SOURCES.upper() : MODEL_EFI_SOURCE_FILE, + TAB_GUIDS.upper() : MODEL_EFI_GUID, + TAB_PROTOCOLS.upper() : MODEL_EFI_PROTOCOL, + TAB_PPIS.upper() : MODEL_EFI_PPI, + TAB_DEPEX.upper() : MODEL_EFI_DEPEX, + TAB_BINARIES.upper() : MODEL_EFI_BINARY_FILE, + TAB_USER_EXTENSIONS.upper() : MODEL_META_DATA_USER_EXTENSION + } + +gComponentType2ModuleType = { + "LIBRARY" : "BASE", + "SECURITY_CORE" : "SEC", + "PEI_CORE" : "PEI_CORE", + "COMBINED_PEIM_DRIVER" : "PEIM", + "PIC_PEIM" : "PEIM", + "RELOCATABLE_PEIM" : "PEIM", + "PE32_PEIM" : "PEIM", + "BS_DRIVER" : "DXE_DRIVER", + "RT_DRIVER" : "DXE_RUNTIME_DRIVER", + "SAL_RT_DRIVER" : "DXE_SAL_DRIVER", + "APPLICATION" : "UEFI_APPLICATION", + "LOGO" : "BASE", +} + +class InfHeader(ModuleHeaderClass): + _Mapping_ = { + # Required Fields + TAB_INF_DEFINES_BASE_NAME : "Name", + TAB_INF_DEFINES_FILE_GUID : "Guid", + TAB_INF_DEFINES_MODULE_TYPE : "ModuleType", + TAB_INF_DEFINES_EFI_SPECIFICATION_VERSION : "EfiSpecificationVersion", + TAB_INF_DEFINES_EDK_RELEASE_VERSION : "EdkReleaseVersion", + + # Optional Fields + TAB_INF_DEFINES_INF_VERSION : "InfVersion", + TAB_INF_DEFINES_BINARY_MODULE : "BinaryModule", + TAB_INF_DEFINES_COMPONENT_TYPE : "ComponentType", + TAB_INF_DEFINES_MAKEFILE_NAME : "MakefileName", + TAB_INF_DEFINES_BUILD_NUMBER : "BuildNumber", + TAB_INF_DEFINES_BUILD_TYPE : "BuildType", + TAB_INF_DEFINES_FFS_EXT : "FfsExt", + TAB_INF_DEFINES_FV_EXT : "FvExt", + TAB_INF_DEFINES_SOURCE_FV : "SourceFv", + TAB_INF_DEFINES_VERSION_NUMBER : "VersionNumber", + TAB_INF_DEFINES_VERSION_STRING : "VersionString", + TAB_INF_DEFINES_VERSION : "Version", + TAB_INF_DEFINES_PCD_IS_DRIVER : "PcdIsDriver", + TAB_INF_DEFINES_TIANO_R8_FLASHMAP_H : "TianoR8FlashMap_h", + TAB_INF_DEFINES_SHADOW : "Shadow", + } + + def __init__(self): + ModuleHeaderClass.__init__(self) + self.VersionNumber = '' + self.VersionString = '' + #print self.__dict__ + def __setitem__(self, key, value): + self.__dict__[self._Mapping_[key]] = value + def __getitem__(self, key): + return self.__dict__[self._Mapping_[key]] + ## "in" test support + def __contains__(self, key): + return key in self._Mapping_ + +## InfObject +# +# This class defined basic Inf object which is used by inheriting +# +# @param object: Inherited from object class +# +class InfObject(object): + def __init__(self): + object.__init__() + +## Inf +# +# This class defined the structure used in Inf object +# +# @param InfObject: Inherited from InfObject class +# @param Ffilename: Input value for Ffilename of Inf file, default is None +# @param IsMergeAllArches: Input value for IsMergeAllArches +# True is to merge all arches +# Fales is not to merge all arches +# default is False +# @param IsToModule: Input value for IsToModule +# True is to transfer to ModuleObject automatically +# False is not to transfer to ModuleObject automatically +# default is False +# @param WorkspaceDir: Input value for current workspace directory, default is None +# +# @var Identification: To store value for Identification, it is a structure as Identification +# @var UserExtensions: To store value for UserExtensions +# @var Module: To store value for Module, it is a structure as ModuleClass +# @var WorkspaceDir: To store value for WorkspaceDir +# @var KeyList: To store value for KeyList, a list for all Keys used in Inf +# +class Inf(InfObject): + def __init__(self, Filename = None, IsToModule = False, WorkspaceDir = None, PackageDir = None, SupArchList = DataType.ARCH_LIST): + self.Identification = IdentificationClass() + self.Module = ModuleClass() + self.WorkspaceDir = WorkspaceDir + self.PackageDir = PackageDir + self.SupArchList = SupArchList + + self.KeyList = [ + TAB_SOURCES, TAB_BUILD_OPTIONS, TAB_BINARIES, TAB_INCLUDES, TAB_GUIDS, + TAB_PROTOCOLS, TAB_PPIS, TAB_LIBRARY_CLASSES, TAB_PACKAGES, TAB_INF_FIXED_PCD, + TAB_INF_PATCH_PCD, TAB_INF_FEATURE_PCD, TAB_INF_PCD, TAB_INF_PCD_EX, + TAB_DEPEX, TAB_INF_DEFINES + ] + # Upper all KEYs to ignore case sensitive when parsing + self.KeyList = map(lambda c: c.upper(), self.KeyList) + + # Init RecordSet + self.RecordSet = {} + for Key in self.KeyList: + self.RecordSet[Section[Key]] = [] + + # Init Comment + self.SectionHeaderCommentDict = {} + + # Load Inf file if filename is not None + if Filename != None: + self.LoadInfFile(Filename) + + # Transfer to Module Object if IsToModule is True + if IsToModule: + self.InfToModule() + + ## Module Object to INF file + def ModuleToInf(self, Module): + Inf = '' + InfList = sdict() + SectionHeaderCommentDict = {} + if Module == None: + return Inf + + ModuleHeader = Module.ModuleHeader + TmpList = [] + # Common define items + if ModuleHeader.Name: + TmpList.append(TAB_INF_DEFINES_BASE_NAME + ' = ' + ModuleHeader.Name) + if ModuleHeader.Guid: + TmpList.append(TAB_INF_DEFINES_FILE_GUID + ' = ' + ModuleHeader.Guid) + if ModuleHeader.Version: + TmpList.append(TAB_INF_DEFINES_VERSION_STRING + ' = ' + ModuleHeader.Version) + if ModuleHeader.ModuleType: + TmpList.append(TAB_INF_DEFINES_MODULE_TYPE + ' = ' + ModuleHeader.ModuleType) + if ModuleHeader.PcdIsDriver: + TmpList.append(TAB_INF_DEFINES_PCD_IS_DRIVER + ' = ' + ModuleHeader.PcdIsDriver) + # Externs + for Item in Module.Externs: + if Item.EntryPoint: + TmpList.append(TAB_INF_DEFINES_ENTRY_POINT + ' = ' + Item.EntryPoint) + if Item.UnloadImage: + TmpList.append(TAB_INF_DEFINES_UNLOAD_IMAGE + ' = ' + Item.UnloadImage) + if Item.Constructor: + TmpList.append(TAB_INF_DEFINES_CONSTRUCTOR + ' = ' + Item.Constructor) + if Item.Destructor: + TmpList.append(TAB_INF_DEFINES_DESTRUCTOR + ' = ' + Item.Destructor) + # Other define items + if Module.UserExtensions != None: + for Item in Module.UserExtensions.Defines: + TmpList.append(Item) + InfList['Defines'] = TmpList + if ModuleHeader.Description != '': + SectionHeaderCommentDict['Defines'] = ModuleHeader.Description + + if Module.UserExtensions != None: + InfList['BuildOptions'] = Module.UserExtensions.BuildOptions + + for Item in Module.Includes: + Key = 'Includes.' + GetStringOfList(Item.SupArchList) + Value = GetHelpTextList(Item.HelpTextList) + Value.append(Item.FilePath) + GenMetaDatSectionItem(Key, Value, InfList) + + for Item in Module.LibraryClasses: + Key = 'LibraryClasses.' + GetStringOfList(Item.SupArchList) + Value = GetHelpTextList(Item.HelpTextList) + NewValue = Item.LibraryClass + if Item.RecommendedInstance: + NewValue = NewValue + '|' + Item.RecommendedInstance + if Item.FeatureFlag: + NewValue = NewValue + '|' + Item.FeatureFlag + Value.append(NewValue) + GenMetaDatSectionItem(Key, Value, InfList) + + for Item in Module.PackageDependencies: + Key = 'Packages.' + GetStringOfList(Item.SupArchList) + Value = GetHelpTextList(Item.HelpTextList) + Value.append(Item.FilePath) + GenMetaDatSectionItem(Key, Value, InfList) + + for Item in Module.PcdCodes: + Key = 'Pcds' + Item.ItemType + '.' + GetStringOfList(Item.SupArchList) + Value = GetHelpTextList(Item.HelpTextList) + NewValue = Item.TokenSpaceGuidCName + '.' + Item.CName + if Item.DefaultValue != '': + NewValue = NewValue + '|' + Item.DefaultValue + Value.append(NewValue) + GenMetaDatSectionItem(Key, Value, InfList) + + for Item in Module.Sources: + Key = 'Sources.' + GetStringOfList(Item.SupArchList) + Value = GetHelpTextList(Item.HelpTextList) + NewValue = Item.SourceFile + if Item.ToolChainFamily != '': + NewValue = NewValue + '|' + Item.ToolChainFamily + if Item.TagName != '': + NewValue = NewValue + '|' + Item.TagName + if Item.ToolCode != '': + NewValue = NewValue + '|' + Item.ToolCode + if Item.FeatureFlag != '': + NewValue = NewValue + '|' + Item.FeatureFlag + Value.append(NewValue) + if Item.HelpText != '': + SectionHeaderCommentDict[Key] = Item.HelpText + GenMetaDatSectionItem(Key, Value, InfList) + + for Item in Module.Guids: + Key = 'Guids.' + GetStringOfList(Item.SupArchList) + Value = GetHelpTextList(Item.HelpTextList) + Value.append(Item.CName) + GenMetaDatSectionItem(Key, Value, InfList) + + for Item in Module.Protocols: + Key = 'Protocols.' + GetStringOfList(Item.SupArchList) + Value = GetHelpTextList(Item.HelpTextList) + Value.append(Item.CName) + GenMetaDatSectionItem(Key, Value, InfList) + + for Item in Module.Ppis: + Key = 'Ppis.' + GetStringOfList(Item.SupArchList) + Value = GetHelpTextList(Item.HelpTextList) + Value.append(Item.CName) + GenMetaDatSectionItem(Key, Value, InfList) + + if Module.PeiDepex: + Key = 'Depex' + Value = Module.PeiDepex.Depex + GenMetaDatSectionItem(Key, Value, InfList) + + if Module.DxeDepex: + Key = 'Depex' + Value = Module.DxeDepex.Depex + GenMetaDatSectionItem(Key, Value, InfList) + + if Module.SmmDepex: + Key = 'Depex' + Value = Module.SmmDepex.Depex + GenMetaDatSectionItem(Key, Value, InfList) + + for Item in Module.Binaries: + Key = 'Binaries.' + GetStringOfList(Item.SupArchList) + Value = GetHelpTextList(Item.HelpTextList) + NewValue = Item.FileType + '|' + Item.BinaryFile + '|' + Item.Target + if Item.FeatureFlag != '': + NewValue = NewValue + '|' + Item.FeatureFlag + Value.append(NewValue) + GenMetaDatSectionItem(Key, Value, InfList) + + # Transfer Module to Inf + for Key in InfList: + if Key in SectionHeaderCommentDict: + List = SectionHeaderCommentDict[Key].split('\r') + for Item in List: + Inf = Inf + Item + '\n' + Inf = Inf + '[' + Key + ']' + '\n' + for Value in InfList[Key]: + if type(Value) == type([]): + for SubValue in Value: + Inf = Inf + ' ' + SubValue + '\n' + else: + Inf = Inf + ' ' + Value + '\n' + Inf = Inf + '\n' + + return Inf + + + ## Transfer to Module Object + # + # Transfer all contents of an Inf file to a standard Module Object + # + def InfToModule(self): + # Init global information for the file + ContainerFile = self.Identification.FullPath + + # Generate Module Header + self.GenModuleHeader(ContainerFile) + + # Generate BuildOptions + self.GenBuildOptions(ContainerFile) + + # Generate Includes + self.GenIncludes(ContainerFile) + + # Generate LibraryClasses + self.GenLibraryClasses(ContainerFile) + + # Generate Packages + self.GenPackages(ContainerFile) + + # Generate Pcds + self.GenPcds(ContainerFile) + + # Generate Sources + self.GenSources(ContainerFile) + + # Generate Guids + self.GenGuidProtocolPpis(DataType.TAB_GUIDS, ContainerFile) + + # Generate Protocols + self.GenGuidProtocolPpis(DataType.TAB_PROTOCOLS, ContainerFile) + + # Generate Ppis + self.GenGuidProtocolPpis(DataType.TAB_PPIS, ContainerFile) + + # Generate Depexes + self.GenDepexes(ContainerFile) + + # Generate Binaries + self.GenBinaries(ContainerFile) + + # Init MiscFiles + self.GenMiscFiles(ContainerFile) + + ## GenMiscFiles + # + def GenMiscFiles(self, ContainerFile): + MiscFiles = MiscFileClass() + MiscFiles.Name = 'ModuleFiles' + for Item in GetFiles(os.path.dirname(ContainerFile), ['CVS', '.svn'], False): + File = CommonClass.FileClass() + File.Filename = Item + MiscFiles.Files.append(File) + self.Module.MiscFiles = MiscFiles + + ## Load Inf file + # + # Load the file if it exists + # + # @param Filename: Input value for filename of Inf file + # + def LoadInfFile(self, Filename): + # Insert a record for file + Filename = NormPath(Filename) + + self.Identification.FullPath = Filename + (self.Identification.RelaPath, self.Identification.FileName) = os.path.split(Filename) + if self.Identification.FullPath.find(self.WorkspaceDir) > -1: + self.Identification.ModulePath = os.path.dirname(self.Identification.FullPath[len(self.WorkspaceDir) + 1:]) + if self.PackageDir: + self.Identification.PackagePath = self.PackageDir + if self.Identification.ModulePath.find(self.PackageDir) == 0: + self.Identification.ModulePath = self.Identification.ModulePath[len(self.PackageDir) + 1:] + + # Init common datas + IfDefList, SectionItemList, CurrentSection, ArchList, ThirdList, IncludeFiles = \ + [], [], TAB_UNKNOWN, [], [], [] + LineNo = 0 + + # Parse file content + IsFindBlockComment = False + ReservedLine = '' + Comment = '' + for Line in open(Filename, 'r'): + LineNo = LineNo + 1 + # Remove comment block + if Line.find(TAB_COMMENT_R8_START) > -1: + ReservedLine = GetSplitValueList(Line, TAB_COMMENT_R8_START, 1)[0] + if ReservedLine.strip().startswith(TAB_COMMENT_SPLIT): + Comment = Comment + Line.strip() + '\n' + ReservedLine = '' + else: + Comment = Comment + Line[len(ReservedLine):] + '\n' + IsFindBlockComment = True + if not ReservedLine: + continue + if Line.find(TAB_COMMENT_R8_END) > -1: + Comment = Comment + Line[:Line.find(TAB_COMMENT_R8_END) + len(TAB_COMMENT_R8_END)] + '\n' + Line = ReservedLine + GetSplitValueList(Line, TAB_COMMENT_R8_END, 1)[1] + ReservedLine = '' + IsFindBlockComment = False + if IsFindBlockComment: + Comment = Comment + Line.strip() + '\n' + continue + + # Remove comments at tail and remove spaces again + if Line.strip().startswith(TAB_COMMENT_SPLIT) or Line.strip().startswith('--/'): + Comment = Comment + Line.strip() + '\n' + Line = CleanString(Line) + if Line == '': + continue + + ## Find a new section tab + # First insert previous section items + # And then parse the content of the new section + if Line.startswith(TAB_SECTION_START) and Line.endswith(TAB_SECTION_END): + if Line[1:3] == "--": + continue + Model = Section[CurrentSection.upper()] + # Insert items data of previous section + InsertSectionItems(Model, CurrentSection, SectionItemList, ArchList, ThirdList, self.RecordSet) + + # Parse the new section + SectionItemList = [] + ArchList = [] + ThirdList = [] + + CurrentSection = '' + LineList = GetSplitValueList(Line[len(TAB_SECTION_START):len(Line) - len(TAB_SECTION_END)], TAB_COMMA_SPLIT) + for Item in LineList: + ItemList = GetSplitValueList(Item, TAB_SPLIT) + if CurrentSection == '': + CurrentSection = ItemList[0] + else: + if CurrentSection != ItemList[0]: + EdkLogger.error("Parser", PARSER_ERROR, "Different section names '%s' and '%s' are found in one section definition, this is not allowed." % (CurrentSection, ItemList[0]), File=Filename, Line=LineNo, RaiseError = EdkLogger.IsRaiseError) + if CurrentSection.upper() not in self.KeyList: + RaiseParserError(Line, CurrentSection, Filename, '', LineNo) + ItemList.append('') + ItemList.append('') + if len(ItemList) > 5: + RaiseParserError(Line, CurrentSection, Filename, '', LineNo) + else: + if ItemList[1] != '' and ItemList[1].upper() not in ARCH_LIST_FULL: + EdkLogger.error("Parser", PARSER_ERROR, "Invalid Arch definition '%s' found" % ItemList[1], File=Filename, Line=LineNo, RaiseError = EdkLogger.IsRaiseError) + ArchList.append(ItemList[1].upper()) + ThirdList.append(ItemList[2]) + + if Comment: + if Comment.endswith('\n'): + Comment = Comment[:len(Comment) - len('\n')] + self.SectionHeaderCommentDict[Section[CurrentSection.upper()]] = Comment + Comment = '' + continue + + # Not in any defined section + if CurrentSection == TAB_UNKNOWN: + ErrorMsg = "%s is not in any defined section" % Line + EdkLogger.error("Parser", PARSER_ERROR, ErrorMsg, File=Filename, Line=LineNo, RaiseError = EdkLogger.IsRaiseError) + + # Add a section item + SectionItemList.append([Line, LineNo, Comment]) + Comment = '' + # End of parse + #End of For + + # Insert items data of last section + Model = Section[CurrentSection.upper()] + InsertSectionItems(Model, CurrentSection, SectionItemList, ArchList, ThirdList, self.RecordSet) + if Comment != '': + self.SectionHeaderCommentDict[Model] = Comment + Comment = '' + + ## Show detailed information of Module + # + # Print all members and their values of Module class + # + def ShowModule(self): + M = self.Module + print 'Filename =', M.ModuleHeader.FileName + print 'FullPath =', M.ModuleHeader.FullPath + print 'RelaPath =', M.ModuleHeader.RelaPath + print 'PackagePath =', M.ModuleHeader.PackagePath + print 'ModulePath =', M.ModuleHeader.ModulePath + print 'CombinePath =', M.ModuleHeader.CombinePath + + print 'BaseName =', M.ModuleHeader.Name + print 'Guid =', M.ModuleHeader.Guid + print 'Version =', M.ModuleHeader.Version + + print '\nIncludes =' + for Item in M.Includes: + print Item.FilePath, Item.SupArchList + print '\nLibraryClasses =' + for Item in M.LibraryClasses: + print Item.LibraryClass, Item.RecommendedInstance, Item.RecommendedInstanceGuid, Item.RecommendedInstanceVersion, Item.FeatureFlag, Item.SupModuleList, Item.SupArchList, Item.Define + print '\nPackageDependencies =' + for Item in M.PackageDependencies: + print Item.FilePath, Item.SupArchList, Item.FeatureFlag + print '\nPcds =' + for Item in M.PcdCodes: + print '\tCName=',Item.CName, 'TokenSpaceGuidCName=', Item.TokenSpaceGuidCName, 'DefaultValue=', Item.DefaultValue, 'ItemType=', Item.ItemType, Item.SupArchList + print '\nSources =' + for Source in M.Sources: + print Source.SourceFile, 'Fam=', Source.ToolChainFamily, 'Pcd=', Source.FeatureFlag, 'Tag=', Source.TagName, 'ToolCode=', Source.ToolCode, Source.SupArchList + print '\nGuids =' + for Item in M.Guids: + print Item.CName, Item.SupArchList, Item.FeatureFlag + print '\nProtocols =' + for Item in M.Protocols: + print Item.CName, Item.SupArchList, Item.FeatureFlag + print '\nPpis =' + for Item in M.Ppis: + print Item.CName, Item.SupArchList, Item.FeatureFlag + print '\nDepex =' + for Item in M.Depex: + print Item.Depex, Item.SupArchList, Item.Define + print '\nBinaries =' + for Binary in M.Binaries: + print 'Type=', Binary.FileType, 'Target=', Binary.Target, 'Name=', Binary.BinaryFile, 'FeatureFlag=', Binary.FeatureFlag, 'SupArchList=', Binary.SupArchList + print '\n*** FileList ***' + for Item in M.MiscFiles.Files: + print Item.Filename + print '****************\n' + + ## Convert [Defines] section content to ModuleHeaderClass + # + # Convert [Defines] section content to ModuleHeaderClass + # + # @param Defines The content under [Defines] section + # @param ModuleHeader An object of ModuleHeaderClass + # @param Arch The supported ARCH + # + def GenModuleHeader(self, ContainerFile): + EdkLogger.debug(2, "Generate ModuleHeader ...") + # Update all defines item in database + RecordSet = self.RecordSet[MODEL_META_DATA_HEADER] + + ModuleHeader = ModuleHeaderClass() + ModuleExtern = ModuleExternClass() + OtherDefines = [] + for Record in RecordSet: + ValueList = GetSplitValueList(Record[0], TAB_EQUAL_SPLIT) + if len(ValueList) != 2: + OtherDefines.append(Record[0]) + else: + Name = ValueList[0] + Value = ValueList[1] + if Name == TAB_INF_DEFINES_BASE_NAME: + ModuleHeader.Name = Value + ModuleHeader.BaseName = Value + elif Name == TAB_INF_DEFINES_FILE_GUID: + ModuleHeader.Guid = Value + elif Name == TAB_INF_DEFINES_VERSION_STRING: + ModuleHeader.Version = Value + elif Name == TAB_INF_DEFINES_PCD_IS_DRIVER: + ModuleHeader.PcdIsDriver = Value + elif Name == TAB_INF_DEFINES_MODULE_TYPE: + ModuleHeader.ModuleType = Value + elif Name == TAB_INF_DEFINES_UEFI_SPECIFICATION_VERSION: + ModuleHeader.UefiSpecificationVersion = Value + elif Name == TAB_INF_DEFINES_PI_SPECIFICATION_VERSION: + ModuleHeader.PiSpecificationVersion = Value + elif Name == TAB_INF_DEFINES_ENTRY_POINT: + ModuleExtern.EntryPoint = Value + elif Name == TAB_INF_DEFINES_UNLOAD_IMAGE: + ModuleExtern.UnloadImage = Value + elif Name == TAB_INF_DEFINES_CONSTRUCTOR: + ModuleExtern.Constructor = Value + elif Name == TAB_INF_DEFINES_DESTRUCTOR: + ModuleExtern.Destructor = Value + else: + OtherDefines.append(Record[0]) + ModuleHeader.FileName = self.Identification.FileName + ModuleHeader.FullPath = self.Identification.FullPath + ModuleHeader.RelaPath = self.Identification.RelaPath + ModuleHeader.PackagePath = self.Identification.PackagePath + ModuleHeader.ModulePath = self.Identification.ModulePath + ModuleHeader.CombinePath = os.path.normpath(os.path.join(ModuleHeader.PackagePath, ModuleHeader.ModulePath, ModuleHeader.FileName)) + + if MODEL_META_DATA_HEADER in self.SectionHeaderCommentDict: + ModuleHeader.Description = self.SectionHeaderCommentDict[MODEL_META_DATA_HEADER] + self.Module.ModuleHeader = ModuleHeader + self.Module.Externs.append(ModuleExtern) + UE = self.Module.UserExtensions + if UE == None: + UE = UserExtensionsClass() + UE.Defines = OtherDefines + self.Module.UserExtensions = UE + + ## GenBuildOptions + # + # Gen BuildOptions of Inf + # [:]=Flag + # + # @param ContainerFile: The Inf file full path + # + def GenBuildOptions(self, ContainerFile): + EdkLogger.debug(2, "Generate %s ..." % TAB_BUILD_OPTIONS) + BuildOptions = {} + # Get all BuildOptions + RecordSet = self.RecordSet[MODEL_META_DATA_BUILD_OPTION] + UE = self.Module.UserExtensions + if UE == None: + UE = UserExtensionsClass() + for Record in RecordSet: + UE.BuildOptions.append(Record[0]) + self.Module.UserExtensions = UE + + ## GenIncludes + # + # Gen Includes of Inf + # + # @param ContainerFile: The Inf file full path + # + def GenIncludes(self, ContainerFile): + EdkLogger.debug(2, "Generate %s ..." % TAB_INCLUDES) + Includes = sdict() + # Get all Includes + RecordSet = self.RecordSet[MODEL_EFI_INCLUDE] + for Record in RecordSet: + Include = IncludeClass() + Include.FilePath = Record[0] + Include.SupArchList = Record[1] + if GenerateHelpText(Record[5], ''): + Include.HelpTextList.append(GenerateHelpText(Record[5], '')) + self.Module.Includes.append(Include) + #self.Module.FileList.extend(GetFiles(os.path.normpath(os.path.join(self.Identification.FileRelativePath, Include.FilePath)), ['CVS', '.svn'])) + + ## GenLibraryClasses + # + # Get LibraryClass of Inf + # | + # + # @param ContainerFile: The Inf file full path + # + def GenLibraryClasses(self, ContainerFile): + EdkLogger.debug(2, "Generate %s ..." % TAB_LIBRARY_CLASSES) + LibraryClasses = {} + # Get all LibraryClasses + RecordSet = self.RecordSet[MODEL_EFI_LIBRARY_CLASS] + for Record in RecordSet: + (LibClassName, LibClassIns, Pcd, SupModelList) = GetLibraryClassOfInf([Record[0], Record[4]], ContainerFile, self.WorkspaceDir, Record[2]) + LibraryClass = CommonClass.LibraryClassClass() + LibraryClass.LibraryClass = LibClassName + LibraryClass.RecommendedInstance = LibClassIns + LibraryClass.FeatureFlag = Pcd + LibraryClass.SupArchList = Record[1] + LibraryClass.SupModuleList = Record[4] + if GenerateHelpText(Record[5], ''): + LibraryClass.HelpTextList.append(GenerateHelpText(Record[5], '')) + self.Module.LibraryClasses.append(LibraryClass) + + ## GenPackages + # + # Gen Packages of Inf + # + # @param ContainerFile: The Inf file full path + # + def GenPackages(self, ContainerFile): + EdkLogger.debug(2, "Generate %s ..." % TAB_PACKAGES) + Packages = {} + # Get all Packages + RecordSet = self.RecordSet[MODEL_META_DATA_PACKAGE] + for Record in RecordSet: + (PackagePath, Pcd) = GetPackage(Record[0], ContainerFile, self.WorkspaceDir, Record[2]) + Package = ModulePackageDependencyClass() + Package.FilePath = NormPath(PackagePath) + Package.SupArchList = Record[1] + Package.FeatureFlag = Pcd + if GenerateHelpText(Record[5], ''): + Package.HelpTextList.append(GenerateHelpText(Record[5], '')) + self.Module.PackageDependencies.append(Package) + + def AddPcd(self, CName, TokenSpaceGuidCName, DefaultValue, ItemType, Arch, HelpTextList): + Pcd = PcdClass() + Pcd.CName = CName + Pcd.TokenSpaceGuidCName = TokenSpaceGuidCName + Pcd.DefaultValue = DefaultValue + Pcd.ItemType = ItemType + Pcd.SupArchList = Arch + if GenerateHelpText(HelpTextList, ''): + Pcd.HelpTextList.append(GenerateHelpText(HelpTextList, '')) + self.Module.PcdCodes.append(Pcd) + + ## GenPcds + # + # Gen Pcds of Inf + # .[|] + # + # @param ContainerFile: The Dec file full path + # + def GenPcds(self, ContainerFile): + EdkLogger.debug(2, "Generate %s ..." % TAB_PCDS) + Pcds = {} + PcdToken = {} + + # Get all Pcds + RecordSet1 = self.RecordSet[MODEL_PCD_FIXED_AT_BUILD] + RecordSet2 = self.RecordSet[MODEL_PCD_PATCHABLE_IN_MODULE] + RecordSet3 = self.RecordSet[MODEL_PCD_FEATURE_FLAG] + RecordSet4 = self.RecordSet[MODEL_PCD_DYNAMIC_EX] + RecordSet5 = self.RecordSet[MODEL_PCD_DYNAMIC] + + # Go through each arch + for Record in RecordSet1: + (TokenSpaceGuidCName, TokenName, Value, Type) = GetPcdOfInf(Record[0], TAB_PCDS_FIXED_AT_BUILD, ContainerFile, Record[2]) + self.AddPcd(TokenName, TokenSpaceGuidCName, Value, Type, Record[1], Record[5]) + for Record in RecordSet2: + (TokenSpaceGuidCName, TokenName, Value, Type) = GetPcdOfInf(Record[0], TAB_PCDS_PATCHABLE_IN_MODULE, ContainerFile, Record[2]) + self.AddPcd(TokenName, TokenSpaceGuidCName, Value, Type, Record[1], Record[5]) + for Record in RecordSet3: + (TokenSpaceGuidCName, TokenName, Value, Type) = GetPcdOfInf(Record[0], TAB_PCDS_FEATURE_FLAG, ContainerFile, Record[2]) + self.AddPcd(TokenName, TokenSpaceGuidCName, Value, Type, Record[1], Record[5]) + for Record in RecordSet4: + (TokenSpaceGuidCName, TokenName, Value, Type) = GetPcdOfInf(Record[0], TAB_PCDS_DYNAMIC_EX, ContainerFile, Record[2]) + self.AddPcd(TokenName, TokenSpaceGuidCName, Value, Type, Record[1], Record[5]) + for Record in RecordSet5: + (TokenSpaceGuidCName, TokenName, Value, Type) = GetPcdOfInf(Record[0], '', ContainerFile, Record[2]) + self.AddPcd(TokenName, TokenSpaceGuidCName, Value, Type, Record[1], Record[5]) + + ## GenSources + # + # Gen Sources of Inf + # [|[|[|[|]]]] + # + # @param ContainerFile: The Dec file full path + # + def GenSources(self, ContainerFile): + EdkLogger.debug(2, "Generate %s ..." % TAB_SOURCES) + Sources = {} + + # Get all Sources + RecordSet = self.RecordSet[MODEL_EFI_SOURCE_FILE] + for Record in RecordSet: + (Filename, Family, TagName, ToolCode, Pcd) = GetSource(Record[0], ContainerFile, self.Identification.RelaPath, Record[2]) + Source = ModuleSourceFileClass(Filename, TagName, ToolCode, Family, Pcd, Record[1]) + if GenerateHelpText(Record[5], ''): + Source.HelpTextList.append(GenerateHelpText(Record[5], '')) + if MODEL_EFI_SOURCE_FILE in self.SectionHeaderCommentDict: + Source.HelpText = self.SectionHeaderCommentDict[MODEL_EFI_SOURCE_FILE] + self.Module.Sources.append(Source) + #self.Module.FileList.append(os.path.normpath(os.path.join(self.Identification.RelaPath, Filename))) + + ## GenDepexes + # + # Gen Depex of Inf + # + # @param ContainerFile: The Inf file full path + # + def GenDepexes(self, ContainerFile): + EdkLogger.debug(2, "Generate %s ..." % TAB_DEPEX) + Depex = {} + # Get all Depexes + RecordSet = self.RecordSet[MODEL_EFI_DEPEX] + DepexString = '' + for Record in RecordSet: + DepexString = DepexString + Record[0] + '\n' + Dep = ModuleDepexClass() + if DepexString.endswith('\n'): + DepexString = DepexString[:len(DepexString) - len('\n')] + Dep.Depex = DepexString + if self.Module.ModuleHeader.ModuleType in ['DXE_SMM_DRIVER']: + self.Module.SmmDepex = Dep + elif self.Module.ModuleHeader.ModuleType in ['PEI_CORE', 'PEIM']: + self.Module.PeiDepex = Dep + else: + self.Module.DxeDepex = Dep +# for Record in RecordSet: +# +# Dep = ModuleDepexClass() +# Dep.Depex = Record[0] +# Dep.SupArchList = Record[1] +# if GenerateHelpText(Record[5], ''): +# Dep.HelpTextList.append(GenerateHelpText(Record[5], '')) +# DepexString = DepexString + Dep +# List.append(Dep) +# self.Module.Depex = List +# if self.Module.ModuleHeader.ModuleType in ['DXE_SMM_DRIVER']: +# self.Module.SmmDepex = List +# elif self.Module.ModuleHeader.ModuleType in ['PEI_CORE', 'PEIM']: +# self.Module.PeiDepex = List +# else: +# self.Module.DxeDepex = List + + ## GenBinaries + # + # Gen Binary of Inf + # ||[|.] + # + # @param ContainerFile: The Dec file full path + # + def GenBinaries(self, ContainerFile): + EdkLogger.debug(2, "Generate %s ..." % TAB_BINARIES) + Binaries = {} + + # Get all Guids + RecordSet = self.RecordSet[MODEL_EFI_BINARY_FILE] + for Record in RecordSet: + (FileType, Filename, Target, Pcd) = GetBinary(Record[0], ContainerFile, self.Identification.RelaPath, Record[2]) + Binary = ModuleBinaryFileClass(Filename, FileType, Target, Pcd, Record[1]) + if GenerateHelpText(Record[5], ''): + Binary.HelpTextList.append(GenerateHelpText(Record[5], '')) + self.Module.Binaries.append(Binary) + #self.Module.FileList.append(os.path.normpath(os.path.join(self.Identification.RelaPath, Filename))) + + ## GenGuids + # + # Gen Guids of Inf + # = + # + # @param ContainerFile: The Inf file full path + # + def GenGuidProtocolPpis(self, Type, ContainerFile): + EdkLogger.debug(2, "Generate %s ..." % Type) + Lists = {} + # Get all Items + if Type == TAB_GUIDS: + ListMember = self.Module.Guids + elif Type == TAB_PROTOCOLS: + ListMember = self.Module.Protocols + elif Type == TAB_PPIS: + ListMember = self.Module.Ppis + + RecordSet = self.RecordSet[Section[Type.upper()]] + for Record in RecordSet: + (Name, Value) = GetGuidsProtocolsPpisOfInf(Record[0], Type, ContainerFile, Record[2]) + ListClass = GuidProtocolPpiCommonClass() + ListClass.CName = Name + ListClass.SupArchList = Record[1] + ListClass.FeatureFlag = Value + if GenerateHelpText(Record[5], ''): + ListClass.HelpTextList.append(GenerateHelpText(Record[5], '')) + ListMember.append(ListClass) + +## +# +# This acts like the main() function for the script, unless it is 'import'ed into another +# script. +# +if __name__ == '__main__': + EdkLogger.Initialize() + EdkLogger.SetLevel(EdkLogger.QUIET) + + W = os.getenv('WORKSPACE') + F = os.path.join(W, 'MdeModulePkg/Application/HelloWorld/HelloWorld.inf') + + P = Inf(os.path.normpath(F), True, W, 'MdeModulePkg') + P.ShowModule() + print P.ModuleToInf(P.Module) diff --git a/BaseTools/Source/Python/Common/MigrationUtilities.py b/BaseTools/Source/Python/Common/MigrationUtilities.py new file mode 100644 index 0000000000..8573f0b692 --- /dev/null +++ b/BaseTools/Source/Python/Common/MigrationUtilities.py @@ -0,0 +1,567 @@ +## @file +# Contains several utilitities shared by migration tools. +# +# Copyright (c) 2007, 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. +# + +## +# Import Modules +# +import os +import re +import EdkLogger +from optparse import OptionParser +from Common.BuildToolError import * +from XmlRoutines import * +from CommonDataClass.CommonClass import * + +## Set all fields of CommonClass object. +# +# Set all attributes of CommonClass object from XML Dom object of XmlCommon. +# +# @param Common The destine CommonClass object. +# @param XmlCommon The source XML Dom object. +# +def SetCommon(Common, XmlCommon): + XmlTag = "Usage" + Common.Usage = XmlAttribute(XmlCommon, XmlTag).split() + + XmlTag = "FeatureFlag" + Common.FeatureFlag = XmlAttribute(XmlCommon, XmlTag) + + XmlTag = "SupArchList" + Common.SupArchList = XmlAttribute(XmlCommon, XmlTag).split() + + XmlTag = XmlNodeName(XmlCommon) + "/" + "HelpText" + Common.HelpText = XmlElement(XmlCommon, XmlTag) + + +## Set some fields of CommonHeaderClass object. +# +# Set Name, Guid, FileName and FullPath fields of CommonHeaderClass object from +# XML Dom object of XmlCommonHeader, NameTag and FileName. +# +# @param CommonHeader The destine CommonClass object. +# @param XmlCommonHeader The source XML Dom object. +# @param NameTag The name tag in XML Dom object. +# @param FileName The file name of the XML file. +# +def SetIdentification(CommonHeader, XmlCommonHeader, NameTag, FileName): + XmlParentTag = XmlNodeName(XmlCommonHeader) + + XmlTag = XmlParentTag + "/" + NameTag + CommonHeader.Name = XmlElement(XmlCommonHeader, XmlTag) + + XmlTag = XmlParentTag + "/" + "GuidValue" + CommonHeader.Guid = XmlElement(XmlCommonHeader, XmlTag) + + XmlTag = XmlParentTag + "/" + "Version" + CommonHeader.Version = XmlElement(XmlCommonHeader, XmlTag) + + CommonHeader.FileName = os.path.basename(FileName) + CommonHeader.FullPath = os.path.abspath(FileName) + + +## Regular expression to match specification and value. +mReSpecification = re.compile(r"(?P\w+)\s+(?P\w*)") + +## Add specification to specification dictionary. +# +# Abstract specification name, value pair from Specification String and add them +# to specification dictionary. +# +# @param SpecificationDict The destine Specification dictionary. +# @param SpecificationString The source Specification String from which the +# specification name and value pair is abstracted. +# +def AddToSpecificationDict(SpecificationDict, SpecificationString): + """Abstract specification name, value pair from Specification String""" + for SpecificationMatch in mReSpecification.finditer(SpecificationString): + Specification = SpecificationMatch.group("Specification") + Value = SpecificationMatch.group("Value") + SpecificationDict[Specification] = Value + +## Set all fields of CommonHeaderClass object. +# +# Set all attributes of CommonHeaderClass object from XML Dom object of +# XmlCommonHeader, NameTag and FileName. +# +# @param CommonHeader The destine CommonClass object. +# @param XmlCommonHeader The source XML Dom object. +# @param NameTag The name tag in XML Dom object. +# @param FileName The file name of the XML file. +# +def SetCommonHeader(CommonHeader, XmlCommonHeader): + """Set all attributes of CommonHeaderClass object from XmlCommonHeader""" + XmlParent = XmlNodeName(XmlCommonHeader) + + XmlTag = XmlParent + "/" + "Abstract" + CommonHeader.Abstract = XmlElement(XmlCommonHeader, XmlTag) + + XmlTag = XmlParent + "/" + "Description" + CommonHeader.Description = XmlElement(XmlCommonHeader, XmlTag) + + XmlTag = XmlParent + "/" + "Copyright" + CommonHeader.Copyright = XmlElement(XmlCommonHeader, XmlTag) + + XmlTag = XmlParent + "/" + "License" + CommonHeader.License = XmlElement(XmlCommonHeader, XmlTag) + + XmlTag = XmlParent + "/" + "Specification" + Specification = XmlElement(XmlCommonHeader, XmlTag) + + AddToSpecificationDict(CommonHeader.Specification, Specification) + + XmlTag = XmlParent + "/" + "ModuleType" + CommonHeader.ModuleType = XmlElement(XmlCommonHeader, XmlTag) + + +## Load a new Cloned Record class object. +# +# Read an input XML ClonedRecord DOM object and return an object of Cloned Record +# contained in the DOM object. +# +# @param XmlCloned A child XML DOM object in a Common XML DOM. +# +# @retvel ClonedRecord A new Cloned Record object created by XmlCloned. +# +def LoadClonedRecord(XmlCloned): + ClonedRecord = ClonedRecordClass() + + XmlTag = "Id" + ClonedRecord.Id = int(XmlAttribute(XmlCloned, XmlTag)) + + XmlTag = "FarGuid" + ClonedRecord.FarGuid = XmlAttribute(XmlCloned, XmlTag) + + XmlTag = "Cloned/PackageGuid" + ClonedRecord.PackageGuid = XmlElement(XmlCloned, XmlTag) + + XmlTag = "Cloned/PackageVersion" + ClonedRecord.PackageVersion = XmlElement(XmlCloned, XmlTag) + + XmlTag = "Cloned/ModuleGuid" + ClonedRecord.ModuleGuid = XmlElement(XmlCloned, XmlTag) + + XmlTag = "Cloned/ModuleVersion" + ClonedRecord.ModuleVersion = XmlElement(XmlCloned, XmlTag) + + return ClonedRecord + + +## Load a new Guid/Protocol/Ppi common class object. +# +# Read an input XML Guid/Protocol/Ppi DOM object and return an object of +# Guid/Protocol/Ppi contained in the DOM object. +# +# @param XmlGuidProtocolPpiCommon A child XML DOM object in a Common XML DOM. +# +# @retvel GuidProtocolPpiCommon A new GuidProtocolPpiCommon class object +# created by XmlGuidProtocolPpiCommon. +# +def LoadGuidProtocolPpiCommon(XmlGuidProtocolPpiCommon): + GuidProtocolPpiCommon = GuidProtocolPpiCommonClass() + + XmlTag = "Name" + GuidProtocolPpiCommon.Name = XmlAttribute(XmlGuidProtocolPpiCommon, XmlTag) + + XmlParent = XmlNodeName(XmlGuidProtocolPpiCommon) + if XmlParent == "Entry": + XmlTag = "%s/C_Name" % XmlParent + elif XmlParent == "GuidCNames": + XmlTag = "%s/GuidCName" % XmlParent + else: + XmlTag = "%s/%sCName" % (XmlParent, XmlParent) + + GuidProtocolPpiCommon.CName = XmlElement(XmlGuidProtocolPpiCommon, XmlTag) + + XmlTag = XmlParent + "/" + "GuidValue" + GuidProtocolPpiCommon.Guid = XmlElement(XmlGuidProtocolPpiCommon, XmlTag) + + if XmlParent.endswith("Notify"): + GuidProtocolPpiCommon.Notify = True + + XmlTag = "GuidTypeList" + GuidTypes = XmlAttribute(XmlGuidProtocolPpiCommon, XmlTag) + GuidProtocolPpiCommon.GuidTypeList = GuidTypes.split() + + XmlTag = "SupModuleList" + SupModules = XmlAttribute(XmlGuidProtocolPpiCommon, XmlTag) + GuidProtocolPpiCommon.SupModuleList = SupModules.split() + + SetCommon(GuidProtocolPpiCommon, XmlGuidProtocolPpiCommon) + + return GuidProtocolPpiCommon + + +## Load a new Pcd class object. +# +# Read an input XML Pcd DOM object and return an object of Pcd +# contained in the DOM object. +# +# @param XmlPcd A child XML DOM object in a Common XML DOM. +# +# @retvel Pcd A new Pcd object created by XmlPcd. +# +def LoadPcd(XmlPcd): + """Return a new PcdClass object equivalent to XmlPcd""" + Pcd = PcdClass() + + XmlTag = "PcdEntry/C_Name" + Pcd.CName = XmlElement(XmlPcd, XmlTag) + + XmlTag = "PcdEntry/Token" + Pcd.Token = XmlElement(XmlPcd, XmlTag) + + XmlTag = "PcdEntry/TokenSpaceGuidCName" + Pcd.TokenSpaceGuidCName = XmlElement(XmlPcd, XmlTag) + + XmlTag = "PcdEntry/DatumType" + Pcd.DatumType = XmlElement(XmlPcd, XmlTag) + + XmlTag = "PcdEntry/MaxDatumSize" + Pcd.MaxDatumSize = XmlElement(XmlPcd, XmlTag) + + XmlTag = "PcdEntry/DefaultValue" + Pcd.DefaultValue = XmlElement(XmlPcd, XmlTag) + + XmlTag = "PcdItemType" + Pcd.ItemType = XmlAttribute(XmlPcd, XmlTag) + + XmlTag = "PcdEntry/ValidUsage" + Pcd.ValidUsage = XmlElement(XmlPcd, XmlTag).split() + + XmlTag = "SupModuleList" + Pcd.SupModuleList = XmlAttribute(XmlPcd, XmlTag).split() + + SetCommon(Pcd, XmlPcd) + + return Pcd + + +## Load a new LibraryClass class object. +# +# Read an input XML LibraryClass DOM object and return an object of LibraryClass +# contained in the DOM object. +# +# @param XmlLibraryClass A child XML DOM object in a Common XML DOM. +# +# @retvel LibraryClass A new LibraryClass object created by XmlLibraryClass. +# +def LoadLibraryClass(XmlLibraryClass): + LibraryClass = LibraryClassClass() + + XmlTag = "LibraryClass/Keyword" + LibraryClass.LibraryClass = XmlElement(XmlLibraryClass, XmlTag) + if LibraryClass.LibraryClass == "": + XmlTag = "Name" + LibraryClass.LibraryClass = XmlAttribute(XmlLibraryClass, XmlTag) + + XmlTag = "LibraryClass/IncludeHeader" + LibraryClass.IncludeHeader = XmlElement(XmlLibraryClass, XmlTag) + + XmlTag = "RecommendedInstanceVersion" + RecommendedInstanceVersion = XmlAttribute(XmlLibraryClass, XmlTag) + LibraryClass.RecommendedInstanceVersion = RecommendedInstanceVersion + + XmlTag = "RecommendedInstanceGuid" + RecommendedInstanceGuid = XmlAttribute(XmlLibraryClass, XmlTag) + LibraryClass.RecommendedInstanceGuid = RecommendedInstanceGuid + + XmlTag = "SupModuleList" + SupModules = XmlAttribute(XmlLibraryClass, XmlTag) + LibraryClass.SupModuleList = SupModules.split() + + SetCommon(LibraryClass, XmlLibraryClass) + + return LibraryClass + + +## Load a new Build Option class object. +# +# Read an input XML BuildOption DOM object and return an object of Build Option +# contained in the DOM object. +# +# @param XmlBuildOption A child XML DOM object in a Common XML DOM. +# +# @retvel BuildOption A new Build Option object created by XmlBuildOption. +# +def LoadBuildOption(XmlBuildOption): + """Return a new BuildOptionClass object equivalent to XmlBuildOption""" + BuildOption = BuildOptionClass() + + BuildOption.Option = XmlElementData(XmlBuildOption) + + XmlTag = "BuildTargets" + BuildOption.BuildTargetList = XmlAttribute(XmlBuildOption, XmlTag).split() + + XmlTag = "ToolChainFamily" + BuildOption.ToolChainFamily = XmlAttribute(XmlBuildOption, XmlTag) + + XmlTag = "TagName" + BuildOption.TagName = XmlAttribute(XmlBuildOption, XmlTag) + + XmlTag = "ToolCode" + BuildOption.ToolCode = XmlAttribute(XmlBuildOption, XmlTag) + + XmlTag = "SupArchList" + BuildOption.SupArchList = XmlAttribute(XmlBuildOption, XmlTag).split() + + return BuildOption + + +## Load a new User Extensions class object. +# +# Read an input XML UserExtensions DOM object and return an object of User +# Extensions contained in the DOM object. +# +# @param XmlUserExtensions A child XML DOM object in a Common XML DOM. +# +# @retvel UserExtensions A new User Extensions object created by +# XmlUserExtensions. +# +def LoadUserExtensions(XmlUserExtensions): + UserExtensions = UserExtensionsClass() + + XmlTag = "UserID" + UserExtensions.UserID = XmlAttribute(XmlUserExtensions, XmlTag) + + XmlTag = "Identifier" + UserExtensions.Identifier = XmlAttribute(XmlUserExtensions, XmlTag) + + UserExtensions.Content = XmlElementData(XmlUserExtensions) + + return UserExtensions + + +## Store content to a text file object. +# +# Write some text file content to a text file object. The contents may echo +# in screen in a verbose way. +# +# @param TextFile The text file object. +# @param Content The string object to be written to a text file. +# +def StoreTextFile(TextFile, Content): + EdkLogger.verbose(Content) + TextFile.write(Content) + + +## Add item to a section. +# +# Add an Item with specific CPU architecture to section dictionary. +# The possible duplication is ensured to be removed. +# +# @param Section Section dictionary indexed by CPU architecture. +# @param Arch CPU architecture: Ia32, X64, Ipf, ARM, Ebc or Common. +# @param Item The Item to be added to section dictionary. +# +def AddToSection(Section, Arch, Item): + SectionArch = Section.get(Arch, []) + if Item not in SectionArch: + SectionArch.append(Item) + Section[Arch] = SectionArch + + +## Get section contents. +# +# Return the content of section named SectionName. +# the contents is based on Methods and ObjectLists. +# +# @param SectionName The name of the section. +# @param Method A function returning a string item of an object. +# @param ObjectList The list of object. +# +# @retval Section The string content of a section. +# +def GetSection(SectionName, Method, ObjectList): + SupportedArches = ["common", "Ia32", "X64", "Ipf", "Ebc", "ARM"] + SectionDict = {} + for Object in ObjectList: + Item = Method(Object) + if Item == "": + continue + Item = " %s" % Item + Arches = Object.SupArchList + if len(Arches) == 0: + AddToSection(SectionDict, "common", Item) + else: + for Arch in SupportedArches: + if Arch.upper() in Arches: + AddToSection(SectionDict, Arch, Item) + + Section = "" + for Arch in SupportedArches: + SectionArch = "\n".join(SectionDict.get(Arch, [])) + if SectionArch != "": + Section += "[%s.%s]\n%s\n" % (SectionName, Arch, SectionArch) + Section += "\n" + if Section != "": + Section += "\n" + return Section + + +## Store file header to a text file. +# +# Write standard file header to a text file. The content includes copyright, +# abstract, description and license extracted from CommonHeader class object. +# +# @param TextFile The text file object. +# @param CommonHeader The source CommonHeader class object. +# +def StoreHeader(TextFile, CommonHeader): + CopyRight = CommonHeader.Copyright + Abstract = CommonHeader.Abstract + Description = CommonHeader.Description + License = CommonHeader.License + + Header = "#/** @file\n#\n" + Header += "# " + Abstract + "\n#\n" + Header += "# " + Description.strip().replace("\n", "\n# ") + "\n" + Header += "# " + CopyRight + "\n#\n" + Header += "# " + License.replace("\n", "\n# ").replace(" ", " ") + Header += "\n#\n#**/\n\n" + + StoreTextFile(TextFile, Header) + +## Store file header to a text file. +# +# Write Defines section to a text file. DefinesTupleList determines the content. +# +# @param TextFile The text file object. +# @param DefinesTupleList The list of (Tag, Value) to be added as one item. +# +def StoreDefinesSection(TextFile, DefinesTupleList): + Section = "[Defines]\n" + for DefineItem in DefinesTupleList: + Section += " %-30s = %s\n" % DefineItem + + Section += "\n\n" + StoreTextFile(TextFile, Section) + + +## Return one User Extension section. +# +# Read the input UserExtentsions class object and return one section. +# +# @param UserExtensions An input UserExtensions class object. +# +# @retval UserExtensionSection A section representing UserExtensions object. +# +def GetUserExtensions(UserExtensions): + UserId = UserExtensions.UserID + Identifier = UserExtensions.Identifier + Content = UserExtensions.Content + + return "[UserExtensions.%s.%s]\n %s\n\n" % (UserId, Identifier, Content) + +## Regular expression to match an equation. +mReEquation = re.compile(r"\s*(\S+)\s*=\s*(\S*)\s*") + +## Return a value tuple matching information in a text fle. +# +# Parse the text file and return a value tuple corresponding to an input tag +# tuple. In case of any error, an tuple of empty strings is returned. +# +# @param FileName The file name of the text file. +# @param TagTuple A tuple of tags as the key to the value. +# +# @param ValueTupe The returned tuple corresponding to the tag tuple. +# +def GetTextFileInfo(FileName, TagTuple): + ValueTuple = [""] * len(TagTuple) + try: + for Line in open(FileName): + Line = Line.split("#", 1)[0] + MatchEquation = mReEquation.match(Line) + if MatchEquation: + Tag = MatchEquation.group(1).upper() + Value = MatchEquation.group(2) + for Index in range(len(TagTuple)): + if TagTuple[Index] == Tag: + ValueTuple[Index] = Value + except: + EdkLogger.info("IO Error in reading file %s" % FileName) + + return ValueTuple + + +## Return a value tuple matching information in an XML fle. +# +# Parse the XML file and return a value tuple corresponding to an input tag +# tuple. In case of any error, an tuple of empty strings is returned. +# +# @param FileName The file name of the XML file. +# @param TagTuple A tuple of tags as the key to the value. +# +# @param ValueTupe The returned tuple corresponding to the tag tuple. +# +def GetXmlFileInfo(FileName, TagTuple): + XmlDom = XmlParseFile(FileName) + return tuple([XmlElement(XmlDom, XmlTag) for XmlTag in TagTuple]) + + +## Parse migration command line options +# +# Use standard Python module optparse to parse command line option of this tool. +# +# @param Source The source file type. +# @param Destinate The destinate file type. +# +# @retval Options A optparse object containing the parsed options. +# @retval InputFile Path of an source file to be migrated. +# +def MigrationOptionParser(Source, Destinate, ToolName, VersionNumber = 1.0): + # use clearer usage to override default usage message + UsageString = "%s [-a] [-v|-q] [-o ] " % ToolName + Version = "%s Version %.2f" % (ToolName, VersionNumber) + Copyright = "Copyright (c) 2007, Intel Corporation. All rights reserved." + + Parser = OptionParser(description=Copyright, version=Version, usage=UsageString) + Parser.add_option("-o", "--output", dest="OutputFile", help="The name of the %s file to be created." % Destinate) + Parser.add_option("-a", "--auto", dest="AutoWrite", action="store_true", default=False, help="Automatically create the %s file using the name of the %s file and replacing file extension" % (Source, Destinate)) + Parser.add_option("-q", "--quiet", action="store_true", type=None, help="Disable all messages except FATAL ERRORS.") + Parser.add_option("-v", "--verbose", action="store_true", type=None, help="Turn on verbose output with informational messages printed.") + + Options, Args = Parser.parse_args() + + # Set logging level + if Options.verbose: + EdkLogger.setLevel(EdkLogger.VERBOSE) + elif Options.quiet: + EdkLogger.setLevel(EdkLogger.QUIET) + else: + EdkLogger.setLevel(EdkLogger.INFO) + + # error check + if len(Args) == 0: + raise MigrationError(PARAMETER_MISSING, name="Input file", usage=Parser.get_usage()) + if len(Args) > 1: + raise MigrationError(PARAMETER_INVALID, name="Too many input files", usage=Parser.get_usage()) + + InputFile = Args[0] + if not os.path.exists(InputFile): + raise MigrationError(FILE_NOT_FOUND, name=InputFile) + + if Options.OutputFile: + if Options.AutoWrite: + raise MigrationError(OPTION_CONFLICT, arg1="-o", arg2="-a", usage=Parser.get_usage()) + else: + if Options.AutoWrite: + Options.OutputFile = os.path.splitext(InputFile)[0] + "." + Destinate.lower() + else: + raise MigrationError(OPTION_MISSING, name="-o", usage=Parser.get_usage()) + + return Options, InputFile + +# This acts like the main() function for the script, unless it is 'import'ed +# into another script. +if __name__ == '__main__': + pass diff --git a/BaseTools/Source/Python/Common/Misc.py b/BaseTools/Source/Python/Common/Misc.py new file mode 100644 index 0000000000..14f6550f29 --- /dev/null +++ b/BaseTools/Source/Python/Common/Misc.py @@ -0,0 +1,1327 @@ +## @file +# Common routines used by all tools +# +# Copyright (c) 2007, 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. +# + +## +# Import Modules +# +import os +import sys +import string +import thread +import threading +import time +import re +import cPickle +from UserDict import IterableUserDict +from UserList import UserList + +from Common import EdkLogger as EdkLogger +from Common import GlobalData as GlobalData + +from BuildToolError import * + +## Regular expression used to find out place holders in string template +gPlaceholderPattern = re.compile("\$\{([^$()\s]+)\}", re.MULTILINE|re.UNICODE) + +## Dictionary used to store file time stamp for quick re-access +gFileTimeStampCache = {} # {file path : file time stamp} + +## Dictionary used to store dependencies of files +gDependencyDatabase = {} # arch : {file path : [dependent files list]} + +## callback routine for processing variable option +# +# This function can be used to process variable number of option values. The +# typical usage of it is specify architecure list on command line. +# (e.g. -a IA32 X64 IPF) +# +# @param Option Standard callback function parameter +# @param OptionString Standard callback function parameter +# @param Value Standard callback function parameter +# @param Parser Standard callback function parameter +# +# @retval +# +def ProcessVariableArgument(Option, OptionString, Value, Parser): + assert Value is None + Value = [] + RawArgs = Parser.rargs + while RawArgs: + Arg = RawArgs[0] + if (Arg[:2] == "--" and len(Arg) > 2) or \ + (Arg[:1] == "-" and len(Arg) > 1 and Arg[1] != "-"): + break + Value.append(Arg) + del RawArgs[0] + setattr(Parser.values, Option.dest, Value) + +## Convert GUID string in xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx style to C structure style +# +# @param Guid The GUID string +# +# @retval string The GUID string in C structure style +# +def GuidStringToGuidStructureString(Guid): + GuidList = Guid.split('-') + Result = '{' + for Index in range(0,3,1): + Result = Result + '0x' + GuidList[Index] + ', ' + Result = Result + '{0x' + GuidList[3][0:2] + ', 0x' + GuidList[3][2:4] + for Index in range(0,12,2): + Result = Result + ', 0x' + GuidList[4][Index:Index+2] + Result += '}}' + return Result + +## Convert GUID structure in byte array to xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx +# +# @param GuidValue The GUID value in byte array +# +# @retval string The GUID value in xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx format +# +def GuidStructureByteArrayToGuidString(GuidValue): + guidValueString = GuidValue.lower().replace("{", "").replace("}", "").replace(" ", "").replace(";", "") + guidValueList = guidValueString.split(",") + if len(guidValueList) != 16: + return '' + #EdkLogger.error(None, None, "Invalid GUID value string %s" % GuidValue) + try: + return "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x" % ( + int(guidValueList[3], 16), + int(guidValueList[2], 16), + int(guidValueList[1], 16), + int(guidValueList[0], 16), + int(guidValueList[5], 16), + int(guidValueList[4], 16), + int(guidValueList[7], 16), + int(guidValueList[6], 16), + int(guidValueList[8], 16), + int(guidValueList[9], 16), + int(guidValueList[10], 16), + int(guidValueList[11], 16), + int(guidValueList[12], 16), + int(guidValueList[13], 16), + int(guidValueList[14], 16), + int(guidValueList[15], 16) + ) + except: + return '' + +## Convert GUID string in C structure style to xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx +# +# @param GuidValue The GUID value in C structure format +# +# @retval string The GUID value in xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx format +# +def GuidStructureStringToGuidString(GuidValue): + guidValueString = GuidValue.lower().replace("{", "").replace("}", "").replace(" ", "").replace(";", "") + guidValueList = guidValueString.split(",") + if len(guidValueList) != 11: + return '' + #EdkLogger.error(None, None, "Invalid GUID value string %s" % GuidValue) + try: + return "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x" % ( + int(guidValueList[0], 16), + int(guidValueList[1], 16), + int(guidValueList[2], 16), + int(guidValueList[3], 16), + int(guidValueList[4], 16), + int(guidValueList[5], 16), + int(guidValueList[6], 16), + int(guidValueList[7], 16), + int(guidValueList[8], 16), + int(guidValueList[9], 16), + int(guidValueList[10], 16) + ) + except: + return '' + +## Convert GUID string in C structure style to xxxxxxxx_xxxx_xxxx_xxxx_xxxxxxxxxxxx +# +# @param GuidValue The GUID value in C structure format +# +# @retval string The GUID value in xxxxxxxx_xxxx_xxxx_xxxx_xxxxxxxxxxxx format +# +def GuidStructureStringToGuidValueName(GuidValue): + guidValueString = GuidValue.lower().replace("{", "").replace("}", "").replace(" ", "") + guidValueList = guidValueString.split(",") + if len(guidValueList) != 11: + EdkLogger.error(None, None, "Invalid GUID value string %s" % GuidValue) + return "%08x_%04x_%04x_%02x%02x_%02x%02x%02x%02x%02x%02x" % ( + int(guidValueList[0], 16), + int(guidValueList[1], 16), + int(guidValueList[2], 16), + int(guidValueList[3], 16), + int(guidValueList[4], 16), + int(guidValueList[5], 16), + int(guidValueList[6], 16), + int(guidValueList[7], 16), + int(guidValueList[8], 16), + int(guidValueList[9], 16), + int(guidValueList[10], 16) + ) + +## Create directories +# +# @param Directory The directory name +# +def CreateDirectory(Directory): + if Directory == None or Directory.strip() == "": + return True + try: + if not os.access(Directory, os.F_OK): + os.makedirs(Directory) + except: + return False + return True + +## Remove directories, including files and sub-directories in it +# +# @param Directory The directory name +# +def RemoveDirectory(Directory, Recursively=False): + if Directory == None or Directory.strip() == "" or not os.path.exists(Directory): + return + if Recursively: + CurrentDirectory = os.getcwd() + os.chdir(Directory) + for File in os.listdir("."): + if os.path.isdir(File): + RemoveDirectory(File, Recursively) + else: + os.remove(File) + os.chdir(CurrentDirectory) + os.rmdir(Directory) + +## Check if given file is changed or not +# +# This method is used to check if a file is changed or not between two build +# actions. It makes use a cache to store files timestamp. +# +# @param File The path of file +# +# @retval True If the given file is changed, doesn't exist, or can't be +# found in timestamp cache +# @retval False If the given file is changed +# +def IsChanged(File): + if not os.path.exists(File): + return True + + FileState = os.stat(File) + TimeStamp = FileState[-2] + + if File in gFileTimeStampCache and TimeStamp == gFileTimeStampCache[File]: + FileChanged = False + else: + FileChanged = True + gFileTimeStampCache[File] = TimeStamp + + return FileChanged + +## Store content in file +# +# This method is used to save file only when its content is changed. This is +# quite useful for "make" system to decide what will be re-built and what won't. +# +# @param File The path of file +# @param Content The new content of the file +# @param IsBinaryFile The flag indicating if the file is binary file or not +# +# @retval True If the file content is changed and the file is renewed +# @retval False If the file content is the same +# +def SaveFileOnChange(File, Content, IsBinaryFile=True): + if not IsBinaryFile: + Content = Content.replace("\n", os.linesep) + + if os.path.exists(File): + try: + if Content == open(File, "rb").read(): + return False + except: + EdkLogger.error(None, FILE_OPEN_FAILURE, ExtraData=File) + + CreateDirectory(os.path.dirname(File)) + try: + if GlobalData.gIsWindows: + try: + from PyUtility import SaveFileToDisk + if not SaveFileToDisk(File, Content): + EdkLogger.error(None, FILE_CREATE_FAILURE, ExtraData=File) + except: + Fd = open(File, "wb") + Fd.write(Content) + Fd.close() + else: + Fd = open(File, "wb") + Fd.write(Content) + Fd.close() + except: + EdkLogger.error(None, FILE_CREATE_FAILURE, ExtraData=File) + + return True + +## Make a Python object persistent on file system +# +# @param Data The object to be stored in file +# @param File The path of file to store the object +# +def DataDump(Data, File): + Fd = None + try: + Fd = open(File, 'wb') + cPickle.dump(Data, Fd, cPickle.HIGHEST_PROTOCOL) + except: + EdkLogger.error("", FILE_OPEN_FAILURE, ExtraData=File, RaiseError=False) + finally: + if Fd != None: + Fd.close() + +## Restore a Python object from a file +# +# @param File The path of file stored the object +# +# @retval object A python object +# @retval None If failure in file operation +# +def DataRestore(File): + Data = None + Fd = None + try: + Fd = open(File, 'rb') + Data = cPickle.load(Fd) + except Exception, e: + EdkLogger.verbose("Failed to load [%s]\n\t%s" % (File, str(e))) + Data = None + finally: + if Fd != None: + Fd.close() + return Data + +## Retrieve and cache the real path name in file system +# +# @param Root The root directory of path relative to +# +# @retval str The path string if the path exists +# @retval None If path doesn't exist +# +class DirCache: + _CACHE_ = {} + + def __init__(self, Root): + self._Root = Root + for F in os.listdir(Root): + self._CACHE_[F.upper()] = F + + # =[] operator + def __getitem__(self, Path): + Path = Path[len(os.path.commonprefix([Path, self._Root])):] + if not Path: + return self._Root + if Path and Path[0] == os.path.sep: + Path = Path[1:] + Path = Path.upper() + if Path in self._CACHE_: + return os.path.join(self._Root, self._CACHE_[Path]) + + IndexList = [] + LastSepIndex = -1 + SepIndex = Path.find(os.path.sep) + while SepIndex > -1: + Parent = Path[:SepIndex] + if Parent not in self._CACHE_: + break + LastSepIndex = SepIndex + SepIndex = Path.find(os.path.sep, LastSepIndex + 1) + + if LastSepIndex == -1: + return None + + Cwd = os.getcwd() + os.chdir(self._Root) + SepIndex = LastSepIndex + while SepIndex > -1: + ParentKey = Path[:SepIndex] + if ParentKey not in self._CACHE_: + os.chdir(Cwd) + return None + + ParentDir = self._CACHE_[ParentKey] + for F in os.listdir(ParentDir): + Dir = os.path.join(ParentDir, F) + self._CACHE_[Dir.upper()] = Dir + + SepIndex = Path.find(os.path.sep, SepIndex + 1) + + os.chdir(Cwd) + if Path not in self._CACHE_: + return None + return os.path.join(self._Root, self._CACHE_[Path]) + +## Get all files of a directory +# +# @param Root: Root dir +# @param SkipList : The files need be skipped +# +# @retval A list of all files +# +def GetFiles(Root, SkipList=None, FullPath = True): + OriPath = Root + FileList = [] + for Root, Dirs, Files in os.walk(Root): + if SkipList: + for Item in SkipList: + if Item in Dirs: + Dirs.remove(Item) + + for File in Files: + File = os.path.normpath(os.path.join(Root, File)) + if not FullPath: + File = File[len(OriPath) + 1:] + FileList.append(File) + + return FileList + +## Check if gvien file exists or not +# +# @param File File name or path to be checked +# @param Dir The directory the file is relative to +# +# @retval True if file exists +# @retval False if file doesn't exists +# +def ValidFile(File, Ext=None): + if Ext != None: + Dummy, FileExt = os.path.splitext(File) + if FileExt.lower() != Ext.lower(): + return False + if not os.path.exists(File): + return False + return True + +def RealPath(File, Dir='', OverrideDir=''): + NewFile = os.path.normpath(os.path.join(Dir, File)) + NewFile = GlobalData.gAllFiles[NewFile] + if not NewFile and OverrideDir: + NewFile = os.path.normpath(os.path.join(OverrideDir, File)) + NewFile = GlobalData.gAllFiles[NewFile] + return NewFile + +def RealPath2(File, Dir='', OverrideDir=''): + NewFile = GlobalData.gAllFiles[os.path.normpath(os.path.join(Dir, File))] + if NewFile: + if Dir: + if Dir[-1] == os.path.sep: + return NewFile[len(Dir):], NewFile[0:len(Dir)] + else: + return NewFile[len(Dir)+1:], NewFile[0:len(Dir)] + else: + return NewFile, '' + + if OverrideDir: + NewFile = GlobalData.gAllFiles[os.path.normpath(os.path.join(OverrideDir, File))] + if NewFile: + return NewFile[len(OverrideDir)+1:], NewFile[0:len(OverrideDir)] + return None, None + +## Check if gvien file exists or not +# +# +def ValidFile2(AllFiles, File, Ext=None, Workspace='', EfiSource='', EdkSource='', Dir='.', OverrideDir=''): + NewFile = File + if Ext != None: + Dummy, FileExt = os.path.splitext(File) + if FileExt.lower() != Ext.lower(): + return False, File + + # Replace the R8 macros + if OverrideDir != '' and OverrideDir != None: + if OverrideDir.find('$(EFI_SOURCE)') > -1: + OverrideDir = OverrideDir.replace('$(EFI_SOURCE)', EfiSource) + if OverrideDir.find('$(EDK_SOURCE)') > -1: + OverrideDir = OverrideDir.replace('$(EDK_SOURCE)', EdkSource) + + # Replace the default dir to current dir + if Dir == '.': + Dir = os.getcwd() + Dir = Dir[len(Workspace)+1:] + + # First check if File has R8 definition itself + if File.find('$(EFI_SOURCE)') > -1 or File.find('$(EDK_SOURCE)') > -1: + NewFile = File.replace('$(EFI_SOURCE)', EfiSource) + NewFile = NewFile.replace('$(EDK_SOURCE)', EdkSource) + NewFile = AllFiles[os.path.normpath(NewFile)] + if NewFile != None: + return True, NewFile + + # Second check the path with override value + if OverrideDir != '' and OverrideDir != None: + NewFile = AllFiles[os.path.normpath(os.path.join(OverrideDir, File))] + if NewFile != None: + return True, NewFile + + # Last check the path with normal definitions + File = os.path.join(Dir, File) + NewFile = AllFiles[os.path.normpath(File)] + if NewFile != None: + return True, NewFile + + return False, File + +## Check if gvien file exists or not +# +# +def ValidFile3(AllFiles, File, Workspace='', EfiSource='', EdkSource='', Dir='.', OverrideDir=''): + # Replace the R8 macros + if OverrideDir != '' and OverrideDir != None: + if OverrideDir.find('$(EFI_SOURCE)') > -1: + OverrideDir = OverrideDir.replace('$(EFI_SOURCE)', EfiSource) + if OverrideDir.find('$(EDK_SOURCE)') > -1: + OverrideDir = OverrideDir.replace('$(EDK_SOURCE)', EdkSource) + + # Replace the default dir to current dir + # Dir is current module dir related to workspace + if Dir == '.': + Dir = os.getcwd() + Dir = Dir[len(Workspace)+1:] + + NewFile = File + RelaPath = AllFiles[os.path.normpath(Dir)] + NewRelaPath = RelaPath + + while(True): + # First check if File has R8 definition itself + if File.find('$(EFI_SOURCE)') > -1 or File.find('$(EDK_SOURCE)') > -1: + File = File.replace('$(EFI_SOURCE)', EfiSource) + File = File.replace('$(EDK_SOURCE)', EdkSource) + NewFile = AllFiles[os.path.normpath(File)] + if NewFile != None: + NewRelaPath = os.path.dirname(NewFile) + File = os.path.basename(NewFile) + #NewRelaPath = NewFile[:len(NewFile) - len(File.replace("..\\", '').replace("../", '')) - 1] + break + + # Second check the path with override value + if OverrideDir != '' and OverrideDir != None: + NewFile = AllFiles[os.path.normpath(os.path.join(OverrideDir, File))] + if NewFile != None: + #NewRelaPath = os.path.dirname(NewFile) + NewRelaPath = NewFile[:len(NewFile) - len(File.replace("..\\", '').replace("../", '')) - 1] + break + + # Last check the path with normal definitions + NewFile = AllFiles[os.path.normpath(os.path.join(Dir, File))] + if NewFile != None: + break + + # No file found + break + + return NewRelaPath, RelaPath, File + + +def GetRelPath(Path1, Path2): + FileName = os.path.basename(Path2) + L1 = os.path.normpath(Path1).split(os.path.normpath('/')) + L2 = os.path.normpath(Path2).split(os.path.normpath('/')) + for Index in range(0, len(L1)): + if L1[Index] != L2[Index]: + FileName = '../' * (len(L1) - Index) + for Index2 in range(Index, len(L2)): + FileName = os.path.join(FileName, L2[Index2]) + break + return os.path.normpath(FileName) + + +## Get GUID value from given packages +# +# @param CName The CName of the GUID +# @param PackageList List of packages looking-up in +# +# @retval GuidValue if the CName is found in any given package +# @retval None if the CName is not found in all given packages +# +def GuidValue(CName, PackageList): + for P in PackageList: + if CName in P.Guids: + return P.Guids[CName] + return None + +## Get Protocol value from given packages +# +# @param CName The CName of the GUID +# @param PackageList List of packages looking-up in +# +# @retval GuidValue if the CName is found in any given package +# @retval None if the CName is not found in all given packages +# +def ProtocolValue(CName, PackageList): + for P in PackageList: + if CName in P.Protocols: + return P.Protocols[CName] + return None + +## Get PPI value from given packages +# +# @param CName The CName of the GUID +# @param PackageList List of packages looking-up in +# +# @retval GuidValue if the CName is found in any given package +# @retval None if the CName is not found in all given packages +# +def PpiValue(CName, PackageList): + for P in PackageList: + if CName in P.Ppis: + return P.Ppis[CName] + return None + +## A string template class +# +# This class implements a template for string replacement. A string template +# looks like following +# +# ${BEGIN} other_string ${placeholder_name} other_string ${END} +# +# The string between ${BEGIN} and ${END} will be repeated as many times as the +# length of "placeholder_name", which is a list passed through a dict. The +# "placeholder_name" is the key name of the dict. The ${BEGIN} and ${END} can +# be not used and, in this case, the "placeholder_name" must not a list and it +# will just be replaced once. +# +class TemplateString(object): + _REPEAT_START_FLAG = "BEGIN" + _REPEAT_END_FLAG = "END" + + class Section(object): + _LIST_TYPES = [type([]), type(set()), type((0,))] + + def __init__(self, TemplateSection, PlaceHolderList): + self._Template = TemplateSection + self._PlaceHolderList = [] + + # Split the section into sub-sections according to the position of placeholders + if PlaceHolderList: + self._SubSectionList = [] + SubSectionStart = 0 + # + # The placeholders passed in must be in the format of + # + # PlaceHolderName, PlaceHolderStartPoint, PlaceHolderEndPoint + # + for PlaceHolder,Start,End in PlaceHolderList: + self._SubSectionList.append(TemplateSection[SubSectionStart:Start]) + self._SubSectionList.append(TemplateSection[Start:End]) + self._PlaceHolderList.append(PlaceHolder) + SubSectionStart = End + if SubSectionStart < len(TemplateSection): + self._SubSectionList.append(TemplateSection[SubSectionStart:]) + else: + self._SubSectionList = [TemplateSection] + + def __str__(self): + return self._Template + " : " + str(self._PlaceHolderList) + + def Instantiate(self, PlaceHolderValues): + RepeatTime = -1 + RepeatPlaceHolders = {} + NonRepeatPlaceHolders = {} + + for PlaceHolder in self._PlaceHolderList: + if PlaceHolder not in PlaceHolderValues: + continue + Value = PlaceHolderValues[PlaceHolder] + if type(Value) in self._LIST_TYPES: + if RepeatTime < 0: + RepeatTime = len(Value) + elif RepeatTime != len(Value): + EdkLogger.error( + "TemplateString", + PARAMETER_INVALID, + "${%s} has different repeat time from others!" % PlaceHolder, + ExtraData=str(self._Template) + ) + RepeatPlaceHolders["${%s}" % PlaceHolder] = Value + else: + NonRepeatPlaceHolders["${%s}" % PlaceHolder] = Value + + if NonRepeatPlaceHolders: + StringList = [] + for S in self._SubSectionList: + if S not in NonRepeatPlaceHolders: + StringList.append(S) + else: + StringList.append(str(NonRepeatPlaceHolders[S])) + else: + StringList = self._SubSectionList + + if RepeatPlaceHolders: + TempStringList = [] + for Index in range(RepeatTime): + for S in StringList: + if S not in RepeatPlaceHolders: + TempStringList.append(S) + else: + TempStringList.append(str(RepeatPlaceHolders[S][Index])) + StringList = TempStringList + + return "".join(StringList) + + ## Constructor + def __init__(self, Template=None): + self.String = '' + self._Template = Template + self._TemplateSectionList = self._Parse(Template) + + ## str() operator + # + # @retval string The string replaced + # + def __str__(self): + return self.String + + ## Split the template string into fragments per the ${BEGIN} and ${END} flags + # + # @retval list A list of TemplateString.Section objects + # + def _Parse(self, Template): + SectionStart = 0 + SearchFrom = 0 + MatchEnd = 0 + PlaceHolderList = [] + TemplateSectionList = [] + while Template: + MatchObj = gPlaceholderPattern.search(Template, SearchFrom) + if not MatchObj: + if MatchEnd < len(Template): + TemplateSection = TemplateString.Section(Template[SectionStart:], PlaceHolderList) + TemplateSectionList.append(TemplateSection) + break + + MatchString = MatchObj.group(1) + MatchStart = MatchObj.start() + MatchEnd = MatchObj.end() + + if MatchString == self._REPEAT_START_FLAG: + if MatchStart > SectionStart: + TemplateSection = TemplateString.Section(Template[SectionStart:MatchStart], PlaceHolderList) + TemplateSectionList.append(TemplateSection) + SectionStart = MatchEnd + PlaceHolderList = [] + elif MatchString == self._REPEAT_END_FLAG: + TemplateSection = TemplateString.Section(Template[SectionStart:MatchStart], PlaceHolderList) + TemplateSectionList.append(TemplateSection) + SectionStart = MatchEnd + PlaceHolderList = [] + else: + PlaceHolderList.append((MatchString, MatchStart - SectionStart, MatchEnd - SectionStart)) + SearchFrom = MatchEnd + return TemplateSectionList + + ## Replace the string template with dictionary of placeholders and append it to previous one + # + # @param AppendString The string template to append + # @param Dictionary The placeholder dictionaries + # + def Append(self, AppendString, Dictionary=None): + if Dictionary: + SectionList = self._Parse(AppendString) + self.String += "".join([S.Instantiate(Dictionary) for S in SectionList]) + else: + self.String += AppendString + + ## Replace the string template with dictionary of placeholders + # + # @param Dictionary The placeholder dictionaries + # + # @retval str The string replaced with placeholder values + # + def Replace(self, Dictionary=None): + return "".join([S.Instantiate(Dictionary) for S in self._TemplateSectionList]) + +## Progress indicator class +# +# This class makes use of thread to print progress on console. +# +class Progressor: + # for avoiding deadloop + _StopFlag = None + _ProgressThread = None + _CheckInterval = 0.25 + + ## Constructor + # + # @param OpenMessage The string printed before progress charaters + # @param CloseMessage The string printed after progress charaters + # @param ProgressChar The charater used to indicate the progress + # @param Interval The interval in seconds between two progress charaters + # + def __init__(self, OpenMessage="", CloseMessage="", ProgressChar='.', Interval=1.0): + self.PromptMessage = OpenMessage + self.CodaMessage = CloseMessage + self.ProgressChar = ProgressChar + self.Interval = Interval + if Progressor._StopFlag == None: + Progressor._StopFlag = threading.Event() + + ## Start to print progress charater + # + # @param OpenMessage The string printed before progress charaters + # + def Start(self, OpenMessage=None): + if OpenMessage != None: + self.PromptMessage = OpenMessage + Progressor._StopFlag.clear() + if Progressor._ProgressThread == None: + Progressor._ProgressThread = threading.Thread(target=self._ProgressThreadEntry) + Progressor._ProgressThread.setDaemon(False) + Progressor._ProgressThread.start() + + ## Stop printing progress charater + # + # @param CloseMessage The string printed after progress charaters + # + def Stop(self, CloseMessage=None): + OriginalCodaMessage = self.CodaMessage + if CloseMessage != None: + self.CodaMessage = CloseMessage + self.Abort() + self.CodaMessage = OriginalCodaMessage + + ## Thread entry method + def _ProgressThreadEntry(self): + sys.stdout.write(self.PromptMessage + " ") + sys.stdout.flush() + TimeUp = 0.0 + while not Progressor._StopFlag.isSet(): + if TimeUp <= 0.0: + sys.stdout.write(self.ProgressChar) + sys.stdout.flush() + TimeUp = self.Interval + time.sleep(self._CheckInterval) + TimeUp -= self._CheckInterval + sys.stdout.write(" " + self.CodaMessage + "\n") + sys.stdout.flush() + + ## Abort the progress display + @staticmethod + def Abort(): + if Progressor._StopFlag != None: + Progressor._StopFlag.set() + if Progressor._ProgressThread != None: + Progressor._ProgressThread.join() + Progressor._ProgressThread = None + +## A dict which can access its keys and/or values orderly +# +# The class implements a new kind of dict which its keys or values can be +# accessed in the order they are added into the dict. It guarantees the order +# by making use of an internal list to keep a copy of keys. +# +class sdict(IterableUserDict): + ## Constructor + def __init__(self): + IterableUserDict.__init__(self) + self._key_list = [] + + ## [] operator + def __setitem__(self, key, value): + if key not in self._key_list: + self._key_list.append(key) + IterableUserDict.__setitem__(self, key, value) + + ## del operator + def __delitem__(self, key): + self._key_list.remove(key) + IterableUserDict.__delitem__(self, key) + + ## used in "for k in dict" loop to ensure the correct order + def __iter__(self): + return self.iterkeys() + + ## len() support + def __len__(self): + return len(self._key_list) + + ## "in" test support + def __contains__(self, key): + return key in self._key_list + + ## indexof support + def index(self, key): + return self._key_list.index(key) + + ## insert support + def insert(self, key, newkey, newvalue, order): + index = self._key_list.index(key) + if order == 'BEFORE': + self._key_list.insert(index, newkey) + IterableUserDict.__setitem__(self, newkey, newvalue) + elif order == 'AFTER': + self._key_list.insert(index + 1, newkey) + IterableUserDict.__setitem__(self, newkey, newvalue) + + ## append support + def append(self, sdict): + for key in sdict: + if key not in self._key_list: + self._key_list.append(key) + IterableUserDict.__setitem__(self, key, sdict[key]) + + def has_key(self, key): + return key in self._key_list + + ## Empty the dict + def clear(self): + self._key_list = [] + IterableUserDict.clear(self) + + ## Return a copy of keys + def keys(self): + keys = [] + for key in self._key_list: + keys.append(key) + return keys + + ## Return a copy of values + def values(self): + values = [] + for key in self._key_list: + values.append(self[key]) + return values + + ## Return a copy of (key, value) list + def items(self): + items = [] + for key in self._key_list: + items.append((key, self[key])) + return items + + ## Iteration support + def iteritems(self): + return iter(self.items()) + + ## Keys interation support + def iterkeys(self): + return iter(self.keys()) + + ## Values interation support + def itervalues(self): + return iter(self.values()) + + ## Return value related to a key, and remove the (key, value) from the dict + def pop(self, key, *dv): + value = None + if key in self._key_list: + value = self[key] + self.__delitem__(key) + elif len(dv) != 0 : + value = kv[0] + return value + + ## Return (key, value) pair, and remove the (key, value) from the dict + def popitem(self): + key = self._key_list[-1] + value = self[key] + self.__delitem__(key) + return key, value + + def update(self, dict=None, **kwargs): + if dict != None: + for k, v in dict.items(): + self[k] = v + if len(kwargs): + for k, v in kwargs.items(): + self[k] = v + +## Dictionary with restricted keys +# +class rdict(dict): + ## Constructor + def __init__(self, KeyList): + for Key in KeyList: + dict.__setitem__(self, Key, "") + + ## []= operator + def __setitem__(self, key, value): + if key not in self: + EdkLogger.error("RestrictedDict", ATTRIBUTE_SET_FAILURE, "Key [%s] is not allowed" % key, + ExtraData=", ".join(dict.keys(self))) + dict.__setitem__(self, key, value) + + ## =[] operator + def __getitem__(self, key): + if key not in self: + return "" + return dict.__getitem__(self, key) + + ## del operator + def __delitem__(self, key): + EdkLogger.error("RestrictedDict", ATTRIBUTE_ACCESS_DENIED, ExtraData="del") + + ## Empty the dict + def clear(self): + for Key in self: + self.__setitem__(Key, "") + + ## Return value related to a key, and remove the (key, value) from the dict + def pop(self, key, *dv): + EdkLogger.error("RestrictedDict", ATTRIBUTE_ACCESS_DENIED, ExtraData="pop") + + ## Return (key, value) pair, and remove the (key, value) from the dict + def popitem(self): + EdkLogger.error("RestrictedDict", ATTRIBUTE_ACCESS_DENIED, ExtraData="popitem") + +## Dictionary using prioritized list as key +# +class tdict: + _ListType = type([]) + _TupleType = type(()) + _Wildcard = 'COMMON' + _ValidWildcardList = ['COMMON', 'DEFAULT', 'ALL', '*', 'PLATFORM'] + + def __init__(self, _Single_=False, _Level_=2): + self._Level_ = _Level_ + self.data = {} + self._Single_ = _Single_ + + # =[] operator + def __getitem__(self, key): + KeyType = type(key) + RestKeys = None + if KeyType == self._ListType or KeyType == self._TupleType: + FirstKey = key[0] + if len(key) > 1: + RestKeys = key[1:] + elif self._Level_ > 1: + RestKeys = [self._Wildcard for i in range(0, self._Level_-1)] + else: + FirstKey = key + if self._Level_ > 1: + RestKeys = [self._Wildcard for i in range(0, self._Level_-1)] + + if FirstKey == None or str(FirstKey).upper() in self._ValidWildcardList: + FirstKey = self._Wildcard + + if self._Single_: + return self._GetSingleValue(FirstKey, RestKeys) + else: + return self._GetAllValues(FirstKey, RestKeys) + + def _GetSingleValue(self, FirstKey, RestKeys): + Value = None + #print "%s-%s" % (FirstKey, self._Level_) , + if self._Level_ > 1: + if FirstKey == self._Wildcard: + if FirstKey in self.data: + Value = self.data[FirstKey][RestKeys] + if Value == None: + for Key in self.data: + Value = self.data[Key][RestKeys] + if Value != None: break + else: + if FirstKey in self.data: + Value = self.data[FirstKey][RestKeys] + if Value == None and self._Wildcard in self.data: + #print "Value=None" + Value = self.data[self._Wildcard][RestKeys] + else: + if FirstKey == self._Wildcard: + if FirstKey in self.data: + Value = self.data[FirstKey] + if Value == None: + for Key in self.data: + Value = self.data[Key] + if Value != None: break + else: + if FirstKey in self.data: + Value = self.data[FirstKey] + elif self._Wildcard in self.data: + Value = self.data[self._Wildcard] + return Value + + def _GetAllValues(self, FirstKey, RestKeys): + Value = [] + if self._Level_ > 1: + if FirstKey == self._Wildcard: + for Key in self.data: + Value += self.data[Key][RestKeys] + else: + if FirstKey in self.data: + Value += self.data[FirstKey][RestKeys] + if self._Wildcard in self.data: + Value += self.data[self._Wildcard][RestKeys] + else: + if FirstKey == self._Wildcard: + for Key in self.data: + Value.append(self.data[Key]) + else: + if FirstKey in self.data: + Value.append(self.data[FirstKey]) + if self._Wildcard in self.data: + Value.append(self.data[self._Wildcard]) + return Value + + ## []= operator + def __setitem__(self, key, value): + KeyType = type(key) + RestKeys = None + if KeyType == self._ListType or KeyType == self._TupleType: + FirstKey = key[0] + if len(key) > 1: + RestKeys = key[1:] + else: + RestKeys = [self._Wildcard for i in range(0, self._Level_-1)] + else: + FirstKey = key + if self._Level_ > 1: + RestKeys = [self._Wildcard for i in range(0, self._Level_-1)] + + if FirstKey in self._ValidWildcardList: + FirstKey = self._Wildcard + + if FirstKey not in self.data and self._Level_ > 0: + self.data[FirstKey] = tdict(self._Single_, self._Level_ - 1) + + if self._Level_ > 1: + self.data[FirstKey][RestKeys] = value + else: + self.data[FirstKey] = value + + def SetGreedyMode(self): + self._Single_ = False + if self._Level_ > 1: + for Key in self.data: + self.data[Key].SetGreedyMode() + + def SetSingleMode(self): + self._Single_ = True + if self._Level_ > 1: + for Key in self.data: + self.data[Key].SetSingleMode() + +## Boolean chain list +# +class Blist(UserList): + def __init__(self, initlist=None): + UserList.__init__(self, initlist) + def __setitem__(self, i, item): + if item not in [True, False]: + if item == 0: + item = False + else: + item = True + self.data[i] = item + def _GetResult(self): + Value = True + for item in self.data: + Value &= item + return Value + Result = property(_GetResult) + +def ParseConsoleLog(Filename): + Opr = open(os.path.normpath(Filename), 'r') + Opw = open(os.path.normpath(Filename + '.New'), 'w+') + for Line in Opr.readlines(): + if Line.find('.efi') > -1: + Line = Line[Line.rfind(' ') : Line.rfind('.efi')].strip() + Opw.write('%s\n' % Line) + + Opr.close() + Opw.close() + +## check format of PCD value against its the datum type +# +# For PCD value setting +# +def CheckPcdDatum(Type, Value): + if Type == "VOID*": + if not ((Value.startswith('L"') or Value.startswith('"') and Value.endswith('"')) + or (Value.startswith('{') and Value.endswith('}')) + ): + return False, "Invalid value [%s] of type [%s]; must be in the form of {...} for array"\ + ", or \"...\" for string, or L\"...\" for unicode string" % (Value, Type) + elif Type == 'BOOLEAN': + if Value not in ['TRUE', 'FALSE']: + return False, "Invalid value [%s] of type [%s]; must be TRUE or FALSE" % (Value, Type) + elif type(Value) == type(""): + try: + Value = long(Value, 0) + except: + return False, "Invalid value [%s] of type [%s];"\ + " must be a hexadecimal, decimal or octal in C language format."\ + % (Value, Type) + + return True, "" + +## Split command line option string to list +# +# subprocess.Popen needs the args to be a sequence. Otherwise there's problem +# in non-windows platform to launch command +# +def SplitOption(OptionString): + OptionList = [] + LastChar = " " + OptionStart = 0 + QuotationMark = "" + for Index in range(0, len(OptionString)): + CurrentChar = OptionString[Index] + if CurrentChar in ['"', "'"]: + if QuotationMark == CurrentChar: + QuotationMark = "" + elif QuotationMark == "": + QuotationMark = CurrentChar + continue + elif QuotationMark: + continue + + if CurrentChar in ["/", "-"] and LastChar in [" ", "\t", "\r", "\n"]: + if Index > OptionStart: + OptionList.append(OptionString[OptionStart:Index-1]) + OptionStart = Index + LastChar = CurrentChar + OptionList.append(OptionString[OptionStart:]) + return OptionList + +def CommonPath(PathList): + P1 = min(PathList).split(os.path.sep) + P2 = max(PathList).split(os.path.sep) + for Index in xrange(min(len(P1), len(P2))): + if P1[Index] != P2[Index]: + return os.path.sep.join(P1[:Index]) + return os.path.sep.join(P1) + +class PathClass(object): + def __init__(self, File='', Root='', AlterRoot='', Type='', IsBinary=False, + Arch='COMMON', ToolChainFamily='', Target='', TagName='', ToolCode=''): + self.Arch = Arch + self.File = str(File) + if os.path.isabs(self.File): + self.Root = '' + self.AlterRoot = '' + else: + self.Root = str(Root) + self.AlterRoot = str(AlterRoot) + + # Remove any '.' and '..' in path + if self.Root: + self.Path = os.path.normpath(os.path.join(self.Root, self.File)) + self.Root = os.path.normpath(CommonPath([self.Root, self.Path])) + # eliminate the side-effect of 'C:' + if self.Root[-1] == ':': + self.Root += os.path.sep + # file path should not start with path separator + if self.Root[-1] == os.path.sep: + self.File = self.Path[len(self.Root):] + else: + self.File = self.Path[len(self.Root)+1:] + else: + self.Path = os.path.normpath(self.File) + + self.SubDir, self.Name = os.path.split(self.File) + self.BaseName, self.Ext = os.path.splitext(self.Name) + + if self.Root: + if self.SubDir: + self.Dir = os.path.join(self.Root, self.SubDir) + else: + self.Dir = self.Root + else: + self.Dir = self.SubDir + + if IsBinary: + self.Type = Type + else: + self.Type = self.Ext.lower() + + self.IsBinary = IsBinary + self.Target = Target + self.TagName = TagName + self.ToolCode = ToolCode + self.ToolChainFamily = ToolChainFamily + + self._Key = None + + ## Convert the object of this class to a string + # + # Convert member Path of the class to a string + # + # @retval string Formatted String + # + def __str__(self): + return self.Path + + ## Override __eq__ function + # + # Check whether PathClass are the same + # + # @retval False The two PathClass are different + # @retval True The two PathClass are the same + # + def __eq__(self, Other): + if type(Other) == type(self): + return self.Path == Other.Path + else: + return self.Path == str(Other) + + ## Override __hash__ function + # + # Use Path as key in hash table + # + # @retval string Key for hash table + # + def __hash__(self): + return hash(self.Path) + + def _GetFileKey(self): + if self._Key == None: + self._Key = self.Path.upper() # + self.ToolChainFamily + self.TagName + self.ToolCode + self.Target + return self._Key + + def Validate(self, Type='', CaseSensitive=True): + if GlobalData.gCaseInsensitive: + CaseSensitive = False + if Type and Type.lower() != self.Type: + return FILE_TYPE_MISMATCH, '%s (expect %s but got %s)' % (self.File, Type, self.Type) + + RealFile, RealRoot = RealPath2(self.File, self.Root, self.AlterRoot) + if not RealRoot and not RealFile: + return FILE_NOT_FOUND, self.File + + ErrorCode = 0 + ErrorInfo = '' + if RealRoot != self.Root or RealFile != self.File: + if CaseSensitive and (RealFile != self.File or (RealRoot != self.Root and RealRoot != self.AlterRoot)): + ErrorCode = FILE_CASE_MISMATCH + ErrorInfo = self.File + '\n\t' + RealFile + " [in file system]" + + self.SubDir, self.Name = os.path.split(RealFile) + self.BaseName, self.Ext = os.path.splitext(self.Name) + if self.SubDir: + self.Dir = os.path.join(RealRoot, self.SubDir) + else: + self.Dir = RealRoot + self.File = RealFile + self.Root = RealRoot + self.Path = os.path.join(RealRoot, RealFile) + return ErrorCode, ErrorInfo + + Key = property(_GetFileKey) + +## +# +# This acts like the main() function for the script, unless it is 'import'ed into another +# script. +# +if __name__ == '__main__': + pass + diff --git a/BaseTools/Source/Python/Common/Parsing.py b/BaseTools/Source/Python/Common/Parsing.py new file mode 100644 index 0000000000..755f7901b5 --- /dev/null +++ b/BaseTools/Source/Python/Common/Parsing.py @@ -0,0 +1,935 @@ +## @file +# This file is used to define common parsing related functions used in parsing INF/DEC/DSC process +# +# Copyright (c) 2008, 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. +# + +## +# Import Modules +# +from String import * +from CommonDataClass.DataClass import * +from DataType import * + +## ParseContent +# +# Parse content of a DSC/INF/DEC file +# +def ParseContent(Lines, ): + for Line in Lines: + LineNo = LineNo + 1 + # + # Remove comments at tail and remove spaces again + # + Line = CleanString(Line) + if Line == '': + continue + + # + # Find a new section tab + # First insert previous section items + # And then parse the content of the new section + # + if Line.startswith(TAB_SECTION_START) and Line.endswith(TAB_SECTION_END): + # + # Insert items data of previous section + # + self.InsertSectionItemsIntoDatabase(FileID, Filename, CurrentSection, SectionItemList, ArchList, ThirdList, IfDefList) + # + # Parse the new section + # + SectionItemList = [] + ArchList = [] + ThirdList = [] + + LineList = GetSplitValueList(Line[len(TAB_SECTION_START):len(Line) - len(TAB_SECTION_END)], TAB_COMMA_SPLIT) + for Item in LineList: + ItemList = GetSplitValueList(Item, TAB_SPLIT) + CurrentSection = ItemList[0] + if CurrentSection.upper() not in self.KeyList: + RaiseParserError(Line, CurrentSection, Filename, '', LineNo) + ItemList.append('') + ItemList.append('') + if len(ItemList) > 5: + RaiseParserError(Line, CurrentSection, Filename, '', LineNo) + else: + if ItemList[1] != '' and ItemList[1].upper() not in ARCH_LIST_FULL: + EdkLogger.error("Parser", PARSER_ERROR, "Invalid Arch definition '%s' found" % ItemList[1], File=Filename, Line=LineNo) + ArchList.append(ItemList[1].upper()) + ThirdList.append(ItemList[2]) + + continue + + # + # Not in any defined section + # + if CurrentSection == TAB_UNKNOWN: + ErrorMsg = "%s is not in any defined section" % Line + EdkLogger.error("Parser", PARSER_ERROR, ErrorMsg, File=Filename, Line=LineNo) + + # + # Add a section item + # + SectionItemList.append([Line, LineNo]) + # End of parse + #End of For + + +## ParseDefineMacro +# +# Search whole table to find all defined Macro and replaced them with the real values +# +def ParseDefineMacro2(Table, RecordSets, GlobalMacro): + Macros = {} + # + # Find all DEFINE macros in section [Header] and its section + # + SqlCommand = """select Value1, Value2, BelongsToItem, StartLine, Arch from %s + where Model = %s + and Enabled > -1""" % (Table.Table, MODEL_META_DATA_DEFINE) + RecordSet = Table.Exec(SqlCommand) + for Record in RecordSet: + Macros[Record[0]] = Record[1] + + # + # Overrided by Global Macros + # + for Key in GlobalMacro.keys(): + Macros[Key] = GlobalMacro[Key] + + # + # Replace the Macros + # + for Key in RecordSets.keys(): + if RecordSets[Key] != []: + for Item in RecordSets[Key]: + Item[0] = ReplaceMacro(Item[0], Macros) + +## ParseDefineMacro +# +# Search whole table to find all defined Macro and replaced them with the real values +# +def ParseDefineMacro(Table, GlobalMacro): + Macros = {} + # + # Find all DEFINE macros + # + SqlCommand = """select Value1, Value2, BelongsToItem, StartLine, Arch from %s + where Model = %s + and Enabled > -1""" % (Table.Table, MODEL_META_DATA_DEFINE) + RecordSet = Table.Exec(SqlCommand) + for Record in RecordSet: +#*************************************************************************************************************************************************** +# The follow SqlCommand (expr replace) is not supported in Sqlite 3.3.4 which is used in Python 2.5 * +# Reserved Only * +# SqlCommand = """update %s set Value1 = replace(Value1, '%s', '%s') * +# where ID in (select ID from %s * +# where Model = %s * +# and Value1 like '%%%s%%' * +# and StartLine > %s * +# and Enabled > -1 * +# and Arch = '%s')""" % \ * +# (self.TblDsc.Table, Record[0], Record[1], self.TblDsc.Table, Record[2], Record[1], Record[3], Record[4]) * +#*************************************************************************************************************************************************** + Macros[Record[0]] = Record[1] + + # + # Overrided by Global Macros + # + for Key in GlobalMacro.keys(): + Macros[Key] = GlobalMacro[Key] + + # + # Found all defined macro and replaced + # + SqlCommand = """select ID, Value1 from %s + where Model != %s + and Value1 like '%%$(%%' and Value1 like '%%)%%' + and Enabled > -1""" % (Table.Table, MODEL_META_DATA_DEFINE) + FoundRecords = Table.Exec(SqlCommand) + for FoundRecord in FoundRecords: + NewValue = ReplaceMacro(FoundRecord[1], Macros) + SqlCommand = """update %s set Value1 = '%s' + where ID = %s""" % (Table.Table, ConvertToSqlString2(NewValue), FoundRecord[0]) + Table.Exec(SqlCommand) + +##QueryDefinesItem +# +# Search item of section [Defines] by name, return its values +# +# @param Table: The Table to be executed +# @param Name: The Name of item of section [Defines] +# @param Arch: The Arch of item of section [Defines] +# +# @retval RecordSet: A list of all matched records +# +def QueryDefinesItem(Table, Name, Arch, BelongsToFile): + SqlCommand = """select Value2 from %s + where Model = %s + and Value1 = '%s' + and Arch = '%s' + and BelongsToFile = %s + and Enabled > -1""" % (Table.Table, MODEL_META_DATA_HEADER, ConvertToSqlString2(Name), ConvertToSqlString2(Arch), BelongsToFile) + RecordSet = Table.Exec(SqlCommand) + if len(RecordSet) < 1: + SqlCommand = """select Value2 from %s + where Model = %s + and Value1 = '%s' + and Arch = '%s' + and BelongsToFile = %s + and Enabled > -1""" % (Table.Table, MODEL_META_DATA_HEADER, ConvertToSqlString2(Name), ConvertToSqlString2(TAB_ARCH_COMMON.upper()), BelongsToFile) + RecordSet = Table.Exec(SqlCommand) + if len(RecordSet) == 1: + if Name == TAB_INF_DEFINES_LIBRARY_CLASS: + return [RecordSet[0][0]] + else: + return GetSplitValueList(RecordSet[0][0]) + elif len(RecordSet) < 1: + return [''] + elif len(RecordSet) > 1: + RetVal = [] + for Record in RecordSet: + if Name == TAB_INF_DEFINES_LIBRARY_CLASS: + RetVal.append(Record[0]) + else: + Items = GetSplitValueList(Record[0]) + for Item in Items: + RetVal.append(Item) + return RetVal + +##QueryDefinesItem +# +# Search item of section [Defines] by name, return its values +# +# @param Table: The Table to be executed +# @param Name: The Name of item of section [Defines] +# @param Arch: The Arch of item of section [Defines] +# +# @retval RecordSet: A list of all matched records +# +def QueryDefinesItem2(Table, Arch, BelongsToFile): + SqlCommand = """select Value1, Value2, StartLine from %s + where Model = %s + and Arch = '%s' + and BelongsToFile = %s + and Enabled > -1""" % (Table.Table, MODEL_META_DATA_HEADER, ConvertToSqlString2(Arch), BelongsToFile) + RecordSet = Table.Exec(SqlCommand) + if len(RecordSet) < 1: + SqlCommand = """select Value1, Value2, StartLine from %s + where Model = %s + and Arch = '%s' + and BelongsToFile = %s + and Enabled > -1""" % (Table.Table, MODEL_META_DATA_HEADER, ConvertToSqlString2(TAB_ARCH_COMMON), BelongsToFile) + RecordSet = Table.Exec(SqlCommand) + + return RecordSet + +##QueryDscItem +# +# Search all dsc item for a specific section +# +# @param Table: The Table to be executed +# @param Model: The type of section +# +# @retval RecordSet: A list of all matched records +# +def QueryDscItem(Table, Model, BelongsToItem, BelongsToFile): + SqlCommand = """select Value1, Arch, StartLine, ID, Value2 from %s + where Model = %s + and BelongsToItem = %s + and BelongsToFile = %s + and Enabled > -1""" % (Table.Table, Model, BelongsToItem, BelongsToFile) + return Table.Exec(SqlCommand) + +##QueryDecItem +# +# Search all dec item for a specific section +# +# @param Table: The Table to be executed +# @param Model: The type of section +# +# @retval RecordSet: A list of all matched records +# +def QueryDecItem(Table, Model, BelongsToItem): + SqlCommand = """select Value1, Arch, StartLine, ID, Value2 from %s + where Model = %s + and BelongsToItem = %s + and Enabled > -1""" % (Table.Table, Model, BelongsToItem) + return Table.Exec(SqlCommand) + +##QueryInfItem +# +# Search all dec item for a specific section +# +# @param Table: The Table to be executed +# @param Model: The type of section +# +# @retval RecordSet: A list of all matched records +# +def QueryInfItem(Table, Model, BelongsToItem): + SqlCommand = """select Value1, Arch, StartLine, ID, Value2 from %s + where Model = %s + and BelongsToItem = %s + and Enabled > -1""" % (Table.Table, Model, BelongsToItem) + return Table.Exec(SqlCommand) + +## GetBuildOption +# +# Parse a string with format "[:]=Flag" +# Return (Family, ToolFlag, Flag) +# +# @param String: String with BuildOption statement +# @param File: The file which defines build option, used in error report +# +# @retval truple() A truple structure as (Family, ToolChain, Flag) +# +def GetBuildOption(String, File, LineNo = -1): + if String.find(TAB_EQUAL_SPLIT) < 0: + RaiseParserError(String, 'BuildOptions', File, '[:]=Flag', LineNo) + (Family, ToolChain, Flag) = ('', '', '') + List = GetSplitValueList(String, TAB_EQUAL_SPLIT, MaxSplit = 1) + if List[0].find(':') > -1: + Family = List[0][ : List[0].find(':')].strip() + ToolChain = List[0][List[0].find(':') + 1 : ].strip() + else: + ToolChain = List[0].strip() + Flag = List[1].strip() + + return (Family, ToolChain, Flag) + +## Get Library Class +# +# Get Library of Dsc as | +# +# @param Item: String as | +# @param ContainerFile: The file which describes the library class, used for error report +# +# @retval (LibraryClassKeyWord, LibraryInstance, [SUP_MODULE_LIST]) Formatted Library Item +# +def GetLibraryClass(Item, ContainerFile, WorkspaceDir, LineNo = -1): + List = GetSplitValueList(Item[0]) + SupMod = SUP_MODULE_LIST_STRING + if len(List) != 2: + RaiseParserError(Item[0], 'LibraryClasses', ContainerFile, '|') + else: + CheckFileType(List[1], '.Inf', ContainerFile, 'library class instance', Item[0], LineNo) + CheckFileExist(WorkspaceDir, List[1], ContainerFile, 'LibraryClasses', Item[0], LineNo) + if Item[1] != '': + SupMod = Item[1] + + return (List[0], List[1], SupMod) + +## Get Library Class +# +# Get Library of Dsc as [|][|.] +# +# @param Item: String as | +# @param ContainerFile: The file which describes the library class, used for error report +# +# @retval (LibraryClassKeyWord, LibraryInstance, [SUP_MODULE_LIST]) Formatted Library Item +# +def GetLibraryClassOfInf(Item, ContainerFile, WorkspaceDir, LineNo = -1): + ItemList = GetSplitValueList((Item[0] + DataType.TAB_VALUE_SPLIT * 2)) + SupMod = SUP_MODULE_LIST_STRING + + if len(ItemList) > 5: + RaiseParserError(Item[0], 'LibraryClasses', ContainerFile, '[|][|.]') + else: + CheckFileType(ItemList[1], '.Inf', ContainerFile, 'LibraryClasses', Item[0], LineNo) + CheckFileExist(WorkspaceDir, ItemList[1], ContainerFile, 'LibraryClasses', Item[0], LineNo) + if ItemList[2] != '': + CheckPcdTokenInfo(ItemList[2], 'LibraryClasses', ContainerFile, LineNo) + if Item[1] != '': + SupMod = Item[1] + + return (ItemList[0], ItemList[1], ItemList[2], SupMod) + +## CheckPcdTokenInfo +# +# Check if PcdTokenInfo is following . +# +# @param TokenInfoString: String to be checked +# @param Section: Used for error report +# @param File: Used for error report +# +# @retval True PcdTokenInfo is in correct format +# +def CheckPcdTokenInfo(TokenInfoString, Section, File, LineNo = -1): + Format = '.' + if TokenInfoString != '' and TokenInfoString != None: + TokenInfoList = GetSplitValueList(TokenInfoString, TAB_SPLIT) + if len(TokenInfoList) == 2: + return True + + RaiseParserError(TokenInfoString, Section, File, Format, LineNo) + +## Get Pcd +# +# Get Pcd of Dsc as .|[||] +# +# @param Item: String as .|[||] +# @param ContainerFile: The file which describes the pcd, used for error report +# +# @retval (TokenInfo[1], TokenInfo[0], List[1], List[2], List[3], Type) +# +def GetPcd(Item, Type, ContainerFile, LineNo = -1): + TokenGuid, TokenName, Value, MaximumDatumSize, Token = '', '', '', '', '' + List = GetSplitValueList(Item + TAB_VALUE_SPLIT * 2) + + if len(List) < 4 or len(List) > 6: + RaiseParserError(Item, 'Pcds' + Type, ContainerFile, '.|[||]', LineNo) + else: + Value = List[1] + MaximumDatumSize = List[2] + Token = List[3] + + if CheckPcdTokenInfo(List[0], 'Pcds' + Type, ContainerFile, LineNo): + (TokenGuid, TokenName) = GetSplitValueList(List[0], TAB_SPLIT) + + return (TokenName, TokenGuid, Value, MaximumDatumSize, Token, Type) + +## Get FeatureFlagPcd +# +# Get FeatureFlagPcd of Dsc as .|TRUE/FALSE +# +# @param Item: String as .|TRUE/FALSE +# @param ContainerFile: The file which describes the pcd, used for error report +# +# @retval (TokenInfo[1], TokenInfo[0], List[1], Type) +# +def GetFeatureFlagPcd(Item, Type, ContainerFile, LineNo = -1): + TokenGuid, TokenName, Value = '', '', '' + List = GetSplitValueList(Item) + if len(List) != 2: + RaiseParserError(Item, 'Pcds' + Type, ContainerFile, '.|TRUE/FALSE', LineNo) + else: + Value = List[1] + if CheckPcdTokenInfo(List[0], 'Pcds' + Type, ContainerFile, LineNo): + (TokenGuid, TokenName) = GetSplitValueList(List[0], DataType.TAB_SPLIT) + + return (TokenName, TokenGuid, Value, Type) + +## Get DynamicDefaultPcd +# +# Get DynamicDefaultPcd of Dsc as .|[|[|]] +# +# @param Item: String as .|TRUE/FALSE +# @param ContainerFile: The file which describes the pcd, used for error report +# +# @retval (TokenInfo[1], TokenInfo[0], List[1], List[2], List[3], Type) +# +def GetDynamicDefaultPcd(Item, Type, ContainerFile, LineNo = -1): + TokenGuid, TokenName, Value, DatumTyp, MaxDatumSize = '', '', '', '', '' + List = GetSplitValueList(Item + TAB_VALUE_SPLIT * 2) + if len(List) < 4 or len(List) > 8: + RaiseParserError(Item, 'Pcds' + Type, ContainerFile, '.|[|[|]]', LineNo) + else: + Value = List[1] + DatumTyp = List[2] + MaxDatumSize = List[3] + if CheckPcdTokenInfo(List[0], 'Pcds' + Type, ContainerFile, LineNo): + (TokenGuid, TokenName) = GetSplitValueList(List[0], TAB_SPLIT) + + return (TokenName, TokenGuid, Value, DatumTyp, MaxDatumSize, Type) + +## Get DynamicHiiPcd +# +# Get DynamicHiiPcd of Dsc as .|||[|[|]] +# +# @param Item: String as .|TRUE/FALSE +# @param ContainerFile: The file which describes the pcd, used for error report +# +# @retval (TokenInfo[1], TokenInfo[0], List[1], List[2], List[3], List[4], List[5], Type) +# +def GetDynamicHiiPcd(Item, Type, ContainerFile, LineNo = -1): + TokenGuid, TokenName, L1, L2, L3, L4, L5 = '', '', '', '', '', '', '' + List = GetSplitValueList(Item + TAB_VALUE_SPLIT * 2) + if len(List) < 6 or len(List) > 8: + RaiseParserError(Item, 'Pcds' + Type, ContainerFile, '.|||[|[|]]', LineNo) + else: + L1, L2, L3, L4, L5 = List[1], List[2], List[3], List[4], List[5] + if CheckPcdTokenInfo(List[0], 'Pcds' + Type, ContainerFile, LineNo): + (TokenGuid, TokenName) = GetSplitValueList(List[0], DataType.TAB_SPLIT) + + return (TokenName, TokenGuid, L1, L2, L3, L4, L5, Type) + +## Get DynamicVpdPcd +# +# Get DynamicVpdPcd of Dsc as .|[|] +# +# @param Item: String as .|TRUE/FALSE +# @param ContainerFile: The file which describes the pcd, used for error report +# +# @retval (TokenInfo[1], TokenInfo[0], List[1], List[2], Type) +# +def GetDynamicVpdPcd(Item, Type, ContainerFile, LineNo = -1): + TokenGuid, TokenName, L1, L2 = '', '', '', '' + List = GetSplitValueList(Item + TAB_VALUE_SPLIT) + if len(List) < 3 or len(List) > 4: + RaiseParserError(Item, 'Pcds' + Type, ContainerFile, '.|[|]', LineNo) + else: + L1, L2 = List[1], List[2] + if CheckPcdTokenInfo(List[0], 'Pcds' + Type, ContainerFile, LineNo): + (TokenGuid, TokenName) = GetSplitValueList(List[0], DataType.TAB_SPLIT) + + return (TokenName, TokenGuid, L1, L2, Type) + +## GetComponent +# +# Parse block of the components defined in dsc file +# Set KeyValues as [ ['component name', [lib1, lib2, lib3], [bo1, bo2, bo3], [pcd1, pcd2, pcd3]], ...] +# +# @param Lines: The content to be parsed +# @param KeyValues: To store data after parsing +# +# @retval True Get component successfully +# +def GetComponent(Lines, KeyValues): + (findBlock, findLibraryClass, findBuildOption, findPcdsFeatureFlag, findPcdsPatchableInModule, findPcdsFixedAtBuild, findPcdsDynamic, findPcdsDynamicEx) = (False, False, False, False, False, False, False, False) + ListItem = None + LibraryClassItem = [] + BuildOption = [] + Pcd = [] + + for Line in Lines: + Line = Line[0] + + # + # Ignore !include statement + # + if Line.upper().find(TAB_INCLUDE.upper() + ' ') > -1 or Line.upper().find(TAB_DEFINE + ' ') > -1: + continue + + if findBlock == False: + ListItem = Line + # + # find '{' at line tail + # + if Line.endswith('{'): + findBlock = True + ListItem = CleanString(Line.rsplit('{', 1)[0], DataType.TAB_COMMENT_SPLIT) + + # + # Parse a block content + # + if findBlock: + if Line.find('') != -1: + (findLibraryClass, findBuildOption, findPcdsFeatureFlag, findPcdsPatchableInModule, findPcdsFixedAtBuild, findPcdsDynamic, findPcdsDynamicEx) = (True, False, False, False, False, False, False) + continue + if Line.find('') != -1: + (findLibraryClass, findBuildOption, findPcdsFeatureFlag, findPcdsPatchableInModule, findPcdsFixedAtBuild, findPcdsDynamic, findPcdsDynamicEx) = (False, True, False, False, False, False, False) + continue + if Line.find('') != -1: + (findLibraryClass, findBuildOption, findPcdsFeatureFlag, findPcdsPatchableInModule, findPcdsFixedAtBuild, findPcdsDynamic, findPcdsDynamicEx) = (False, False, True, False, False, False, False) + continue + if Line.find('') != -1: + (findLibraryClass, findBuildOption, findPcdsFeatureFlag, findPcdsPatchableInModule, findPcdsFixedAtBuild, findPcdsDynamic, findPcdsDynamicEx) = (False, False, False, True, False, False, False) + continue + if Line.find('') != -1: + (findLibraryClass, findBuildOption, findPcdsFeatureFlag, findPcdsPatchableInModule, findPcdsFixedAtBuild, findPcdsDynamic, findPcdsDynamicEx) = (False, False, False, False, True, False, False) + continue + if Line.find('') != -1: + (findLibraryClass, findBuildOption, findPcdsFeatureFlag, findPcdsPatchableInModule, findPcdsFixedAtBuild, findPcdsDynamic, findPcdsDynamicEx) = (False, False, False, False, False, True, False) + continue + if Line.find('') != -1: + (findLibraryClass, findBuildOption, findPcdsFeatureFlag, findPcdsPatchableInModule, findPcdsFixedAtBuild, findPcdsDynamic, findPcdsDynamicEx) = (False, False, False, False, False, False, True) + continue + if Line.endswith('}'): + # + # find '}' at line tail + # + KeyValues.append([ListItem, LibraryClassItem, BuildOption, Pcd]) + (findBlock, findLibraryClass, findBuildOption, findPcdsFeatureFlag, findPcdsPatchableInModule, findPcdsFixedAtBuild, findPcdsDynamic, findPcdsDynamicEx) = (False, False, False, False, False, False, False, False) + LibraryClassItem, BuildOption, Pcd = [], [], [] + continue + + if findBlock: + if findLibraryClass: + LibraryClassItem.append(Line) + elif findBuildOption: + BuildOption.append(Line) + elif findPcdsFeatureFlag: + Pcd.append((DataType.TAB_PCDS_FEATURE_FLAG_NULL, Line)) + elif findPcdsPatchableInModule: + Pcd.append((DataType.TAB_PCDS_PATCHABLE_IN_MODULE_NULL, Line)) + elif findPcdsFixedAtBuild: + Pcd.append((DataType.TAB_PCDS_FIXED_AT_BUILD_NULL, Line)) + elif findPcdsDynamic: + Pcd.append((DataType.TAB_PCDS_DYNAMIC_DEFAULT_NULL, Line)) + elif findPcdsDynamicEx: + Pcd.append((DataType.TAB_PCDS_DYNAMIC_EX_DEFAULT_NULL, Line)) + else: + KeyValues.append([ListItem, [], [], []]) + + return True + +## GetExec +# +# Parse a string with format "InfFilename [EXEC = ExecFilename]" +# Return (InfFilename, ExecFilename) +# +# @param String: String with EXEC statement +# +# @retval truple() A pair as (InfFilename, ExecFilename) +# +def GetExec(String): + InfFilename = '' + ExecFilename = '' + if String.find('EXEC') > -1: + InfFilename = String[ : String.find('EXEC')].strip() + ExecFilename = String[String.find('EXEC') + len('EXEC') : ].strip() + else: + InfFilename = String.strip() + + return (InfFilename, ExecFilename) + +## GetComponents +# +# Parse block of the components defined in dsc file +# Set KeyValues as [ ['component name', [lib1, lib2, lib3], [bo1, bo2, bo3], [pcd1, pcd2, pcd3]], ...] +# +# @param Lines: The content to be parsed +# @param Key: Reserved +# @param KeyValues: To store data after parsing +# @param CommentCharacter: Comment char, used to ignore comment content +# +# @retval True Get component successfully +# +def GetComponents(Lines, Key, KeyValues, CommentCharacter): + if Lines.find(DataType.TAB_SECTION_END) > -1: + Lines = Lines.split(DataType.TAB_SECTION_END, 1)[1] + (findBlock, findLibraryClass, findBuildOption, findPcdsFeatureFlag, findPcdsPatchableInModule, findPcdsFixedAtBuild, findPcdsDynamic, findPcdsDynamicEx) = (False, False, False, False, False, False, False, False) + ListItem = None + LibraryClassItem = [] + BuildOption = [] + Pcd = [] + + LineList = Lines.split('\n') + for Line in LineList: + Line = CleanString(Line, CommentCharacter) + if Line == None or Line == '': + continue + + if findBlock == False: + ListItem = Line + # + # find '{' at line tail + # + if Line.endswith('{'): + findBlock = True + ListItem = CleanString(Line.rsplit('{', 1)[0], CommentCharacter) + + # + # Parse a block content + # + if findBlock: + if Line.find('') != -1: + (findLibraryClass, findBuildOption, findPcdsFeatureFlag, findPcdsPatchableInModule, findPcdsFixedAtBuild, findPcdsDynamic, findPcdsDynamicEx) = (True, False, False, False, False, False, False) + continue + if Line.find('') != -1: + (findLibraryClass, findBuildOption, findPcdsFeatureFlag, findPcdsPatchableInModule, findPcdsFixedAtBuild, findPcdsDynamic, findPcdsDynamicEx) = (False, True, False, False, False, False, False) + continue + if Line.find('') != -1: + (findLibraryClass, findBuildOption, findPcdsFeatureFlag, findPcdsPatchableInModule, findPcdsFixedAtBuild, findPcdsDynamic, findPcdsDynamicEx) = (False, False, True, False, False, False, False) + continue + if Line.find('') != -1: + (findLibraryClass, findBuildOption, findPcdsFeatureFlag, findPcdsPatchableInModule, findPcdsFixedAtBuild, findPcdsDynamic, findPcdsDynamicEx) = (False, False, False, True, False, False, False) + continue + if Line.find('') != -1: + (findLibraryClass, findBuildOption, findPcdsFeatureFlag, findPcdsPatchableInModule, findPcdsFixedAtBuild, findPcdsDynamic, findPcdsDynamicEx) = (False, False, False, False, True, False, False) + continue + if Line.find('') != -1: + (findLibraryClass, findBuildOption, findPcdsFeatureFlag, findPcdsPatchableInModule, findPcdsFixedAtBuild, findPcdsDynamic, findPcdsDynamicEx) = (False, False, False, False, False, True, False) + continue + if Line.find('') != -1: + (findLibraryClass, findBuildOption, findPcdsFeatureFlag, findPcdsPatchableInModule, findPcdsFixedAtBuild, findPcdsDynamic, findPcdsDynamicEx) = (False, False, False, False, False, False, True) + continue + if Line.endswith('}'): + # + # find '}' at line tail + # + KeyValues.append([ListItem, LibraryClassItem, BuildOption, Pcd]) + (findBlock, findLibraryClass, findBuildOption, findPcdsFeatureFlag, findPcdsPatchableInModule, findPcdsFixedAtBuild, findPcdsDynamic, findPcdsDynamicEx) = (False, False, False, False, False, False, False, False) + LibraryClassItem, BuildOption, Pcd = [], [], [] + continue + + if findBlock: + if findLibraryClass: + LibraryClassItem.append(Line) + elif findBuildOption: + BuildOption.append(Line) + elif findPcdsFeatureFlag: + Pcd.append((DataType.TAB_PCDS_FEATURE_FLAG, Line)) + elif findPcdsPatchableInModule: + Pcd.append((DataType.TAB_PCDS_PATCHABLE_IN_MODULE, Line)) + elif findPcdsFixedAtBuild: + Pcd.append((DataType.TAB_PCDS_FIXED_AT_BUILD, Line)) + elif findPcdsDynamic: + Pcd.append((DataType.TAB_PCDS_DYNAMIC, Line)) + elif findPcdsDynamicEx: + Pcd.append((DataType.TAB_PCDS_DYNAMIC_EX, Line)) + else: + KeyValues.append([ListItem, [], [], []]) + + return True + +## Get Source +# +# Get Source of Inf as [|[|[|[|]]]] +# +# @param Item: String as [|[|[|[|]]]] +# @param ContainerFile: The file which describes the library class, used for error report +# +# @retval (List[0], List[1], List[2], List[3], List[4]) +# +def GetSource(Item, ContainerFile, FileRelativePath, LineNo = -1): + ItemNew = Item + DataType.TAB_VALUE_SPLIT * 4 + List = GetSplitValueList(ItemNew) + if len(List) < 5 or len(List) > 9: + RaiseParserError(Item, 'Sources', ContainerFile, '[|[|[|[|]]]]', LineNo) + List[0] = NormPath(List[0]) + CheckFileExist(FileRelativePath, List[0], ContainerFile, 'Sources', Item, LineNo) + if List[4] != '': + CheckPcdTokenInfo(List[4], 'Sources', ContainerFile, LineNo) + + return (List[0], List[1], List[2], List[3], List[4]) + +## Get Binary +# +# Get Binary of Inf as [|[|[|[|]]]] +# +# @param Item: String as [|[|[|[|]]]] +# @param ContainerFile: The file which describes the library class, used for error report +# +# @retval (List[0], List[1], List[2], List[3]) +# +def GetBinary(Item, ContainerFile, FileRelativePath, LineNo = -1): + ItemNew = Item + DataType.TAB_VALUE_SPLIT + List = GetSplitValueList(ItemNew) + if len(List) != 4 and len(List) != 5: + RaiseParserError(Item, 'Binaries', ContainerFile, "||[|.]", LineNo) + else: + if List[3] != '': + CheckPcdTokenInfo(List[3], 'Binaries', ContainerFile, LineNo) + + return (List[0], List[1], List[2], List[3]) + +## Get Guids/Protocols/Ppis +# +# Get Guids/Protocols/Ppis of Inf as [|] +# +# @param Item: String as [|] +# @param Type: Type of parsing string +# @param ContainerFile: The file which describes the library class, used for error report +# +# @retval (List[0], List[1]) +# +def GetGuidsProtocolsPpisOfInf(Item, Type, ContainerFile, LineNo = -1): + ItemNew = Item + TAB_VALUE_SPLIT + List = GetSplitValueList(ItemNew) + if List[1] != '': + CheckPcdTokenInfo(List[1], Type, ContainerFile, LineNo) + + return (List[0], List[1]) + +## Get Guids/Protocols/Ppis +# +# Get Guids/Protocols/Ppis of Dec as = +# +# @param Item: String as = +# @param Type: Type of parsing string +# @param ContainerFile: The file which describes the library class, used for error report +# +# @retval (List[0], List[1]) +# +def GetGuidsProtocolsPpisOfDec(Item, Type, ContainerFile, LineNo = -1): + List = GetSplitValueList(Item, DataType.TAB_EQUAL_SPLIT) + if len(List) != 2: + RaiseParserError(Item, Type, ContainerFile, '=', LineNo) + + return (List[0], List[1]) + +## GetPackage +# +# Get Package of Inf as [|] +# +# @param Item: String as [|] +# @param Type: Type of parsing string +# @param ContainerFile: The file which describes the library class, used for error report +# +# @retval (List[0], List[1]) +# +def GetPackage(Item, ContainerFile, FileRelativePath, LineNo = -1): + ItemNew = Item + TAB_VALUE_SPLIT + List = GetSplitValueList(ItemNew) + CheckFileType(List[0], '.Dec', ContainerFile, 'package', List[0], LineNo) + CheckFileExist(FileRelativePath, List[0], ContainerFile, 'Packages', List[0], LineNo) + + if List[1] != '': + CheckPcdTokenInfo(List[1], 'Packages', ContainerFile, LineNo) + + return (List[0], List[1]) + +## Get Pcd Values of Inf +# +# Get Pcd of Inf as .[|] +# +# @param Item: The string describes pcd +# @param Type: The type of Pcd +# @param File: The file which describes the pcd, used for error report +# +# @retval (TokenSpcCName, TokenCName, Value, ItemType) Formatted Pcd Item +# +def GetPcdOfInf(Item, Type, File, LineNo): + Format = '.[|]' + TokenGuid, TokenName, Value, InfType = '', '', '', '' + + if Type == TAB_PCDS_FIXED_AT_BUILD: + InfType = TAB_INF_FIXED_PCD + elif Type == TAB_PCDS_PATCHABLE_IN_MODULE: + InfType = TAB_INF_PATCH_PCD + elif Type == TAB_PCDS_FEATURE_FLAG: + InfType = TAB_INF_FEATURE_PCD + elif Type == TAB_PCDS_DYNAMIC_EX: + InfType = TAB_INF_PCD_EX + elif Type == TAB_PCDS_DYNAMIC: + InfType = TAB_INF_PCD + List = GetSplitValueList(Item + DataType.TAB_VALUE_SPLIT) + if len(List) < 2 or len(List) > 3: + RaiseParserError(Item, InfType, File, Format, LineNo) + else: + Value = List[1] + TokenInfo = GetSplitValueList(List[0], DataType.TAB_SPLIT) + if len(TokenInfo) != 2: + RaiseParserError(Item, InfType, File, Format, LineNo) + else: + TokenGuid = TokenInfo[0] + TokenName = TokenInfo[1] + + return (TokenGuid, TokenName, Value, Type) + + +## Get Pcd Values of Dec +# +# Get Pcd of Dec as .||| +# @retval (TokenSpcCName, TokenCName, Value, DatumType, Token, ItemType) Formatted Pcd Item +# +def GetPcdOfDec(Item, Type, File, LineNo = -1): + Format = '.|||' + TokenGuid, TokenName, Value, DatumType, Token = '', '', '', '', '' + List = GetSplitValueList(Item) + if len(List) != 4: + RaiseParserError(Item, 'Pcds' + Type, File, Format, LineNo) + else: + Value = List[1] + DatumType = List[2] + Token = List[3] + TokenInfo = GetSplitValueList(List[0], DataType.TAB_SPLIT) + if len(TokenInfo) != 2: + RaiseParserError(Item, 'Pcds' + Type, File, Format, LineNo) + else: + TokenGuid = TokenInfo[0] + TokenName = TokenInfo[1] + + return (TokenGuid, TokenName, Value, DatumType, Token, Type) + +## Parse DEFINE statement +# +# Get DEFINE macros +# +# 1. Insert a record into TblDec +# Value1: Macro Name +# Value2: Macro Value +# +def ParseDefine(LineValue, StartLine, Table, FileID, Filename, SectionName, SectionModel, Arch): + EdkLogger.debug(EdkLogger.DEBUG_2, "DEFINE statement '%s' found in section %s" % (LineValue, SectionName)) + Define = GetSplitValueList(CleanString(LineValue[LineValue.upper().find(DataType.TAB_DEFINE.upper() + ' ') + len(DataType.TAB_DEFINE + ' ') : ]), TAB_EQUAL_SPLIT, 1) + Table.Insert(MODEL_META_DATA_DEFINE, Define[0], Define[1], '', '', '', Arch, SectionModel, FileID, StartLine, -1, StartLine, -1, 0) + +## InsertSectionItems +# +# Insert item data of a section to a dict +# +def InsertSectionItems(Model, CurrentSection, SectionItemList, ArchList, ThirdList, RecordSet): + # Insert each item data of a section + for Index in range(0, len(ArchList)): + Arch = ArchList[Index] + Third = ThirdList[Index] + if Arch == '': + Arch = TAB_ARCH_COMMON + + Records = RecordSet[Model] + for SectionItem in SectionItemList: + BelongsToItem, EndLine, EndColumn = -1, -1, -1 + LineValue, StartLine, EndLine, Comment = SectionItem[0], SectionItem[1], SectionItem[1], SectionItem[2] + + EdkLogger.debug(4, "Parsing %s ..." %LineValue) + # And then parse DEFINE statement + if LineValue.upper().find(DataType.TAB_DEFINE.upper() + ' ') > -1: + continue + + # At last parse other sections + ID = -1 + Records.append([LineValue, Arch, StartLine, ID, Third, Comment]) + + if RecordSet != {}: + RecordSet[Model] = Records + +## Insert records to database +# +# Insert item data of a section to database +# @param Table: The Table to be inserted +# @param FileID: The ID of belonging file +# @param Filename: The name of belonging file +# @param CurrentSection: The name of currect section +# @param SectionItemList: A list of items of the section +# @param ArchList: A list of arches +# @param ThirdList: A list of third parameters, ModuleType for LibraryClass and SkuId for Dynamic Pcds +# @param IfDefList: A list of all conditional statements +# @param RecordSet: A dict of all parsed records +# +def InsertSectionItemsIntoDatabase(Table, FileID, Filename, Model, CurrentSection, SectionItemList, ArchList, ThirdList, IfDefList, RecordSet): + # + # Insert each item data of a section + # + for Index in range(0, len(ArchList)): + Arch = ArchList[Index] + Third = ThirdList[Index] + if Arch == '': + Arch = TAB_ARCH_COMMON + + Records = RecordSet[Model] + for SectionItem in SectionItemList: + BelongsToItem, EndLine, EndColumn = -1, -1, -1 + LineValue, StartLine, EndLine = SectionItem[0], SectionItem[1], SectionItem[1] + + EdkLogger.debug(4, "Parsing %s ..." %LineValue) + # + # And then parse DEFINE statement + # + if LineValue.upper().find(DataType.TAB_DEFINE.upper() + ' ') > -1: + ParseDefine(LineValue, StartLine, Table, FileID, Filename, CurrentSection, Model, Arch) + continue + + # + # At last parse other sections + # + ID = Table.Insert(Model, LineValue, Third, Third, '', '', Arch, -1, FileID, StartLine, -1, StartLine, -1, 0) + Records.append([LineValue, Arch, StartLine, ID, Third]) + + if RecordSet != {}: + RecordSet[Model] = Records + +## GenMetaDatSectionItem +def GenMetaDatSectionItem(Key, Value, List): + if Key not in List: + List[Key] = [Value] + else: + List[Key].append(Value) \ No newline at end of file diff --git a/BaseTools/Source/Python/Common/PyUtility.pyd b/BaseTools/Source/Python/Common/PyUtility.pyd new file mode 100644 index 0000000000..5bb57d91e0 Binary files /dev/null and b/BaseTools/Source/Python/Common/PyUtility.pyd differ diff --git a/BaseTools/Source/Python/Common/String.py b/BaseTools/Source/Python/Common/String.py new file mode 100644 index 0000000000..5da0cacfb0 --- /dev/null +++ b/BaseTools/Source/Python/Common/String.py @@ -0,0 +1,703 @@ +## @file +# This file is used to define common string related functions used in parsing process +# +# Copyright (c) 2007 ~ 2008, 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. +# + +## +# Import Modules +# +import re +import DataType +import os.path +import string +import EdkLogger as EdkLogger + +from GlobalData import * +from BuildToolError import * + +## GetSplitValueList +# +# Get a value list from a string with multiple values splited with SplitTag +# The default SplitTag is DataType.TAB_VALUE_SPLIT +# 'AAA|BBB|CCC' -> ['AAA', 'BBB', 'CCC'] +# +# @param String: The input string to be splitted +# @param SplitTag: The split key, default is DataType.TAB_VALUE_SPLIT +# @param MaxSplit: The max number of split values, default is -1 +# +# @retval list() A list for splitted string +# +def GetSplitValueList(String, SplitTag = DataType.TAB_VALUE_SPLIT, MaxSplit = -1): + return map(lambda l: l.strip(), String.split(SplitTag, MaxSplit)) + +## MergeArches +# +# Find a key's all arches in dict, add the new arch to the list +# If not exist any arch, set the arch directly +# +# @param Dict: The input value for Dict +# @param Key: The input value for Key +# @param Arch: The Arch to be added or merged +# +def MergeArches(Dict, Key, Arch): + if Key in Dict.keys(): + Dict[Key].append(Arch) + else: + Dict[Key] = Arch.split() + +## GenDefines +# +# Parse a string with format "DEFINE = " +# Generate a map Defines[VarName] = PATH +# Return False if invalid format +# +# @param String: String with DEFINE statement +# @param Arch: Supportted Arch +# @param Defines: DEFINE statement to be parsed +# +# @retval 0 DEFINE statement found, and valid +# @retval 1 DEFINE statement found, but not valid +# @retval -1 DEFINE statement not found +# +def GenDefines(String, Arch, Defines): + if String.find(DataType.TAB_DEFINE + ' ') > -1: + List = String.replace(DataType.TAB_DEFINE + ' ', '').split(DataType.TAB_EQUAL_SPLIT) + if len(List) == 2: + Defines[(CleanString(List[0]), Arch)] = CleanString(List[1]) + return 0 + else: + return -1 + + return 1 + +## GenInclude +# +# Parse a string with format "!include " +# Return the file path +# Return False if invalid format or NOT FOUND +# +# @param String: String with INCLUDE statement +# @param IncludeFiles: INCLUDE statement to be parsed +# @param Arch: Supportted Arch +# +# @retval True +# @retval False +# +def GenInclude(String, IncludeFiles, Arch): + if String.upper().find(DataType.TAB_INCLUDE.upper() + ' ') > -1: + IncludeFile = CleanString(String[String.upper().find(DataType.TAB_INCLUDE.upper() + ' ') + len(DataType.TAB_INCLUDE + ' ') : ]) + MergeArches(IncludeFiles, IncludeFile, Arch) + return True + else: + return False + +## GetLibraryClassesWithModuleType +# +# Get Library Class definition when no module type defined +# +# @param Lines: The content to be parsed +# @param Key: Reserved +# @param KeyValues: To store data after parsing +# @param CommentCharacter: Comment char, used to ignore comment content +# +# @retval True Get library classes successfully +# +def GetLibraryClassesWithModuleType(Lines, Key, KeyValues, CommentCharacter): + newKey = SplitModuleType(Key) + Lines = Lines.split(DataType.TAB_SECTION_END, 1)[1] + LineList = Lines.splitlines() + for Line in LineList: + Line = CleanString(Line, CommentCharacter) + if Line != '' and Line[0] != CommentCharacter: + KeyValues.append([CleanString(Line, CommentCharacter), newKey[1]]) + + return True + +## GetDynamics +# +# Get Dynamic Pcds +# +# @param Lines: The content to be parsed +# @param Key: Reserved +# @param KeyValues: To store data after parsing +# @param CommentCharacter: Comment char, used to ignore comment content +# +# @retval True Get Dynamic Pcds successfully +# +def GetDynamics(Lines, Key, KeyValues, CommentCharacter): + # + # Get SkuId Name List + # + SkuIdNameList = SplitModuleType(Key) + + Lines = Lines.split(DataType.TAB_SECTION_END, 1)[1] + LineList = Lines.splitlines() + for Line in LineList: + Line = CleanString(Line, CommentCharacter) + if Line != '' and Line[0] != CommentCharacter: + KeyValues.append([CleanString(Line, CommentCharacter), SkuIdNameList[1]]) + + return True + +## SplitModuleType +# +# Split ModuleType out of section defien to get key +# [LibraryClass.Arch.ModuleType|ModuleType|ModuleType] -> [ 'LibraryClass.Arch', ['ModuleType', 'ModuleType', 'ModuleType'] ] +# +# @param Key: String to be parsed +# +# @retval ReturnValue A list for module types +# +def SplitModuleType(Key): + KeyList = Key.split(DataType.TAB_SPLIT) + # + # Fill in for arch + # + KeyList.append('') + # + # Fill in for moduletype + # + KeyList.append('') + ReturnValue = [] + KeyValue = KeyList[0] + if KeyList[1] != '': + KeyValue = KeyValue + DataType.TAB_SPLIT + KeyList[1] + ReturnValue.append(KeyValue) + ReturnValue.append(GetSplitValueList(KeyList[2])) + + return ReturnValue + +## Replace macro in strings list +# +# This method replace macros used in a given string list. The macros are +# given in a dictionary. +# +# @param StringList StringList to be processed +# @param MacroDefinitions The macro definitions in the form of dictionary +# @param SelfReplacement To decide whether replace un-defined macro to '' +# +# @retval NewList A new string list whose macros are replaced +# +def ReplaceMacros(StringList, MacroDefinitions={}, SelfReplacement = False): + NewList = [] + for String in StringList: + if type(String) == type(''): + NewList.append(ReplaceMacro(String, MacroDefinitions, SelfReplacement)) + else: + NewList.append(String) + + return NewList + +## Replace macro in string +# +# This method replace macros used in given string. The macros are given in a +# dictionary. +# +# @param String String to be processed +# @param MacroDefinitions The macro definitions in the form of dictionary +# @param SelfReplacement To decide whether replace un-defined macro to '' +# +# @retval string The string whose macros are replaced +# +def ReplaceMacro(String, MacroDefinitions={}, SelfReplacement = False): + LastString = String + while MacroDefinitions: + MacroUsed = gMacroPattern.findall(String) + # no macro found in String, stop replacing + if len(MacroUsed) == 0: + break + + for Macro in MacroUsed: + if Macro not in MacroDefinitions: + if SelfReplacement: + String = String.replace("$(%s)" % Macro, '') + continue + String = String.replace("$(%s)" % Macro, MacroDefinitions[Macro]) + # in case there's macro not defined + if String == LastString: + break + LastString = String + + return String + +## NormPath +# +# Create a normal path +# And replace DFEINE in the path +# +# @param Path: The input value for Path to be converted +# @param Defines: A set for DEFINE statement +# +# @retval Path Formatted path +# +def NormPath(Path, Defines = {}): + IsRelativePath = False + if Path: + if Path[0] == '.': + IsRelativePath = True + # + # Replace with Define + # + if Defines: + Path = ReplaceMacro(Path, Defines) + # + # To local path format + # + Path = os.path.normpath(Path) + + if IsRelativePath and Path[0] != '.': + Path = os.path.join('.', Path) + + return Path + +## CleanString +# +# Remove comments in a string +# Remove spaces +# +# @param Line: The string to be cleaned +# @param CommentCharacter: Comment char, used to ignore comment content, default is DataType.TAB_COMMENT_SPLIT +# +# @retval Path Formatted path +# +def CleanString(Line, CommentCharacter = DataType.TAB_COMMENT_SPLIT, AllowCppStyleComment=False): + # + # remove whitespace + # + Line = Line.strip(); + # + # Replace R8's comment character + # + if AllowCppStyleComment: + Line = Line.replace(DataType.TAB_COMMENT_R8_SPLIT, CommentCharacter) + # + # remove comments + # + Line = Line.split(CommentCharacter, 1)[0]; + # + # remove whitespace again + # + Line = Line.strip(); + + return Line + +## GetMultipleValuesOfKeyFromLines +# +# Parse multiple strings to clean comment and spaces +# The result is saved to KeyValues +# +# @param Lines: The content to be parsed +# @param Key: Reserved +# @param KeyValues: To store data after parsing +# @param CommentCharacter: Comment char, used to ignore comment content +# +# @retval True Successfully executed +# +def GetMultipleValuesOfKeyFromLines(Lines, Key, KeyValues, CommentCharacter): + Lines = Lines.split(DataType.TAB_SECTION_END, 1)[1] + LineList = Lines.split('\n') + for Line in LineList: + Line = CleanString(Line, CommentCharacter) + if Line != '' and Line[0] != CommentCharacter: + KeyValues += [Line] + + return True + +## GetDefineValue +# +# Parse a DEFINE statement to get defined value +# DEFINE Key Value +# +# @param String: The content to be parsed +# @param Key: The key of DEFINE statement +# @param CommentCharacter: Comment char, used to ignore comment content +# +# @retval string The defined value +# +def GetDefineValue(String, Key, CommentCharacter): + String = CleanString(String) + return String[String.find(Key + ' ') + len(Key + ' ') : ] + +## GetSingleValueOfKeyFromLines +# +# Parse multiple strings as below to get value of each definition line +# Key1 = Value1 +# Key2 = Value2 +# The result is saved to Dictionary +# +# @param Lines: The content to be parsed +# @param Dictionary: To store data after parsing +# @param CommentCharacter: Comment char, be used to ignore comment content +# @param KeySplitCharacter: Key split char, between key name and key value. Key1 = Value1, '=' is the key split char +# @param ValueSplitFlag: Value split flag, be used to decide if has multiple values +# @param ValueSplitCharacter: Value split char, be used to split multiple values. Key1 = Value1|Value2, '|' is the value split char +# +# @retval True Successfully executed +# +def GetSingleValueOfKeyFromLines(Lines, Dictionary, CommentCharacter, KeySplitCharacter, ValueSplitFlag, ValueSplitCharacter): + Lines = Lines.split('\n') + Keys = [] + Value = '' + DefineValues = [''] + SpecValues = [''] + + for Line in Lines: + # + # Handle DEFINE and SPEC + # + if Line.find(DataType.TAB_INF_DEFINES_DEFINE + ' ') > -1: + if '' in DefineValues: + DefineValues.remove('') + DefineValues.append(GetDefineValue(Line, DataType.TAB_INF_DEFINES_DEFINE, CommentCharacter)) + continue + if Line.find(DataType.TAB_INF_DEFINES_SPEC + ' ') > -1: + if '' in SpecValues: + SpecValues.remove('') + SpecValues.append(GetDefineValue(Line, DataType.TAB_INF_DEFINES_SPEC, CommentCharacter)) + continue + + # + # Handle Others + # + LineList = Line.split(KeySplitCharacter, 1) + if len(LineList) >= 2: + Key = LineList[0].split() + if len(Key) == 1 and Key[0][0] != CommentCharacter: + # + # Remove comments and white spaces + # + LineList[1] = CleanString(LineList[1], CommentCharacter) + if ValueSplitFlag: + Value = map(string.strip, LineList[1].split(ValueSplitCharacter)) + else: + Value = CleanString(LineList[1], CommentCharacter).splitlines() + + if Key[0] in Dictionary: + if Key[0] not in Keys: + Dictionary[Key[0]] = Value + Keys.append(Key[0]) + else: + Dictionary[Key[0]].extend(Value) + else: + Dictionary[DataType.TAB_INF_DEFINES_MACRO][Key[0]] = Value[0] + + if DefineValues == []: + DefineValues = [''] + if SpecValues == []: + SpecValues = [''] + Dictionary[DataType.TAB_INF_DEFINES_DEFINE] = DefineValues + Dictionary[DataType.TAB_INF_DEFINES_SPEC] = SpecValues + + return True + +## The content to be parsed +# +# Do pre-check for a file before it is parsed +# Check $() +# Check [] +# +# @param FileName: Used for error report +# @param FileContent: File content to be parsed +# @param SupSectionTag: Used for error report +# +def PreCheck(FileName, FileContent, SupSectionTag): + LineNo = 0 + IsFailed = False + NewFileContent = '' + for Line in FileContent.splitlines(): + LineNo = LineNo + 1 + # + # Clean current line + # + Line = CleanString(Line) + + # + # Remove commented line + # + if Line.find(DataType.TAB_COMMA_SPLIT) == 0: + Line = '' + # + # Check $() + # + if Line.find('$') > -1: + if Line.find('$(') < 0 or Line.find(')') < 0: + EdkLogger.error("Parser", FORMAT_INVALID, Line=LineNo, File=FileName, RaiseError = EdkLogger.IsRaiseError) + + # + # Check [] + # + if Line.find('[') > -1 or Line.find(']') > -1: + # + # Only get one '[' or one ']' + # + if not (Line.find('[') > -1 and Line.find(']') > -1): + EdkLogger.error("Parser", FORMAT_INVALID, Line=LineNo, File=FileName, RaiseError = EdkLogger.IsRaiseError) + + # + # Regenerate FileContent + # + NewFileContent = NewFileContent + Line + '\r\n' + + if IsFailed: + EdkLogger.error("Parser", FORMAT_INVALID, Line=LineNo, File=FileName, RaiseError = EdkLogger.IsRaiseError) + + return NewFileContent + +## CheckFileType +# +# Check if the Filename is including ExtName +# Return True if it exists +# Raise a error message if it not exists +# +# @param CheckFilename: Name of the file to be checked +# @param ExtName: Ext name of the file to be checked +# @param ContainerFilename: The container file which describes the file to be checked, used for error report +# @param SectionName: Used for error report +# @param Line: The line in container file which defines the file to be checked +# +# @retval True The file type is correct +# +def CheckFileType(CheckFilename, ExtName, ContainerFilename, SectionName, Line, LineNo = -1): + if CheckFilename != '' and CheckFilename != None: + (Root, Ext) = os.path.splitext(CheckFilename) + if Ext.upper() != ExtName.upper(): + ContainerFile = open(ContainerFilename, 'r').read() + if LineNo == -1: + LineNo = GetLineNo(ContainerFile, Line) + ErrorMsg = "Invalid %s. '%s' is found, but '%s' file is needed" % (SectionName, CheckFilename, ExtName) + EdkLogger.error("Parser", PARSER_ERROR, ErrorMsg, Line=LineNo, + File=ContainerFilename, RaiseError = EdkLogger.IsRaiseError) + + return True + +## CheckFileExist +# +# Check if the file exists +# Return True if it exists +# Raise a error message if it not exists +# +# @param CheckFilename: Name of the file to be checked +# @param WorkspaceDir: Current workspace dir +# @param ContainerFilename: The container file which describes the file to be checked, used for error report +# @param SectionName: Used for error report +# @param Line: The line in container file which defines the file to be checked +# +# @retval The file full path if the file exists +# +def CheckFileExist(WorkspaceDir, CheckFilename, ContainerFilename, SectionName, Line, LineNo = -1): + CheckFile = '' + if CheckFilename != '' and CheckFilename != None: + CheckFile = WorkspaceFile(WorkspaceDir, CheckFilename) + if not os.path.isfile(CheckFile): + ContainerFile = open(ContainerFilename, 'r').read() + if LineNo == -1: + LineNo = GetLineNo(ContainerFile, Line) + ErrorMsg = "Can't find file '%s' defined in section '%s'" % (CheckFile, SectionName) + EdkLogger.error("Parser", PARSER_ERROR, ErrorMsg, + File=ContainerFilename, Line = LineNo, RaiseError = EdkLogger.IsRaiseError) + + return CheckFile + +## GetLineNo +# +# Find the index of a line in a file +# +# @param FileContent: Search scope +# @param Line: Search key +# +# @retval int Index of the line +# @retval -1 The line is not found +# +def GetLineNo(FileContent, Line, IsIgnoreComment = True): + LineList = FileContent.splitlines() + for Index in range(len(LineList)): + if LineList[Index].find(Line) > -1: + # + # Ignore statement in comment + # + if IsIgnoreComment: + if LineList[Index].strip()[0] == DataType.TAB_COMMENT_SPLIT: + continue + return Index + 1 + + return -1 + +## RaiseParserError +# +# Raise a parser error +# +# @param Line: String which has error +# @param Section: Used for error report +# @param File: File which has the string +# @param Format: Correct format +# +def RaiseParserError(Line, Section, File, Format = '', LineNo = -1): + if LineNo == -1: + LineNo = GetLineNo(open(os.path.normpath(File), 'r').read(), Line) + ErrorMsg = "Invalid statement '%s' is found in section '%s'" % (Line, Section) + if Format != '': + Format = "Correct format is " + Format + EdkLogger.error("Parser", PARSER_ERROR, ErrorMsg, File=File, Line=LineNo, ExtraData=Format, RaiseError = EdkLogger.IsRaiseError) + +## WorkspaceFile +# +# Return a full path with workspace dir +# +# @param WorkspaceDir: Workspace dir +# @param Filename: Relative file name +# +# @retval string A full path +# +def WorkspaceFile(WorkspaceDir, Filename): + return os.path.join(NormPath(WorkspaceDir), NormPath(Filename)) + +## Split string +# +# Revmove '"' which startswith and endswith string +# +# @param String: The string need to be splited +# +# @retval String: The string after removed '""' +# +def SplitString(String): + if String.startswith('\"'): + String = String[1:] + if String.endswith('\"'): + String = String[:-1] + + return String + +## Convert To Sql String +# +# 1. Replace "'" with "''" in each item of StringList +# +# @param StringList: A list for strings to be converted +# +def ConvertToSqlString(StringList): + return map(lambda s: s.replace("'", "''") , StringList) + +## Convert To Sql String +# +# 1. Replace "'" with "''" in the String +# +# @param String: A String to be converted +# +def ConvertToSqlString2(String): + return String.replace("'", "''") + +# +# Remove comment block +# +def RemoveBlockComment(Lines): + IsFindBlockComment = False + IsFindBlockCode = False + ReservedLine = '' + NewLines = [] + + for Line in Lines: + Line = Line.strip() + # + # Remove comment block + # + if Line.find(DataType.TAB_COMMENT_R8_START) > -1: + ReservedLine = GetSplitValueList(Line, DataType.TAB_COMMENT_R8_START, 1)[0] + IsFindBlockComment = True + if Line.find(DataType.TAB_COMMENT_R8_END) > -1: + Line = ReservedLine + GetSplitValueList(Line, DataType.TAB_COMMENT_R8_END, 1)[1] + ReservedLine = '' + IsFindBlockComment = False + if IsFindBlockComment: + NewLines.append('') + continue + + NewLines.append(Line) + return NewLines + +# +# Get String of a List +# +def GetStringOfList(List, Split = ' '): + if type(List) != type([]): + return List + Str = '' + for Item in List: + Str = Str + Item + Split + + return Str.strip() + +# +# Get HelpTextList from HelpTextClassList +# +def GetHelpTextList(HelpTextClassList): + List = [] + if HelpTextClassList: + for HelpText in HelpTextClassList: + if HelpText.String.endswith('\n'): + HelpText.String = HelpText.String[0: len(HelpText.String) - len('\n')] + List.extend(HelpText.String.split('\n')) + + return List + +def StringToArray(String): + if isinstance(String, unicode): + if len(unicode) ==0: + return "{0x00, 0x00}" + return "{%s, 0x00, 0x00}" % ", ".join(["0x%02x, 0x00" % ord(C) for C in String]) + elif String.startswith('L"'): + if String == "L\"\"": + return "{0x00, 0x00}" + else: + return "{%s, 0x00, 0x00}" % ", ".join(["0x%02x, 0x00" % ord(C) for C in String[2:-1]]) + elif String.startswith('"'): + if String == "\"\"": + return "{0x00}"; + else: + return "{%s, 0x00}" % ", ".join(["0x%02x" % ord(C) for C in String[1:-1]]) + else: + return '{%s, 0}' % ', '.join(String.split()) + +def StringArrayLength(String): + if isinstance(String, unicode): + return (len(String) + 1) * 2 + 1; + elif String.startswith('L"'): + return (len(String) - 3 + 1) * 2 + elif String.startswith('"'): + return (len(String) - 2 + 1) + else: + return len(String.split()) + 1 + +def RemoveDupOption(OptionString, Which="/I", Against=None): + OptionList = OptionString.split() + ValueList = [] + if Against: + ValueList += Against + for Index in range(len(OptionList)): + Opt = OptionList[Index] + if not Opt.startswith(Which): + continue + if len(Opt) > len(Which): + Val = Opt[len(Which):] + else: + Val = "" + if Val in ValueList: + OptionList[Index] = "" + else: + ValueList.append(Val) + return " ".join(OptionList) + +## +# +# This acts like the main() function for the script, unless it is 'import'ed into another +# script. +# +if __name__ == '__main__': + pass + diff --git a/BaseTools/Source/Python/Common/TargetTxtClassObject.py b/BaseTools/Source/Python/Common/TargetTxtClassObject.py new file mode 100644 index 0000000000..70178f54ce --- /dev/null +++ b/BaseTools/Source/Python/Common/TargetTxtClassObject.py @@ -0,0 +1,174 @@ +## @file +# This file is used to define each component of Target.txt file +# +# Copyright (c) 2007, 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. +# + +## +# Import Modules +# +import os +import EdkLogger +import DataType +from BuildToolError import * +import GlobalData + +gDefaultTargetTxtFile = "Conf/target.txt" + +## TargetTxtClassObject +# +# This class defined content used in file target.txt +# +# @param object: Inherited from object class +# @param Filename: Input value for full path of target.txt +# +# @var TargetTxtDictionary: To store keys and values defined in target.txt +# +class TargetTxtClassObject(object): + def __init__(self, Filename = None): + self.TargetTxtDictionary = { + DataType.TAB_TAT_DEFINES_ACTIVE_PLATFORM : '', + DataType.TAB_TAT_DEFINES_ACTIVE_MODULE : '', + DataType.TAB_TAT_DEFINES_TOOL_CHAIN_CONF : '', + DataType.TAB_TAT_DEFINES_MULTIPLE_THREAD : '', + DataType.TAB_TAT_DEFINES_MAX_CONCURRENT_THREAD_NUMBER : '', + DataType.TAB_TAT_DEFINES_TARGET : [], + DataType.TAB_TAT_DEFINES_TOOL_CHAIN_TAG : [], + DataType.TAB_TAT_DEFINES_TARGET_ARCH : [], + DataType.TAB_TAT_DEFINES_BUILD_RULE_CONF : '', + } + if Filename != None: + self.LoadTargetTxtFile(Filename) + + ## LoadTargetTxtFile + # + # Load target.txt file and parse it, return a set structure to store keys and values + # + # @param Filename: Input value for full path of target.txt + # + # @retval set() A set structure to store keys and values + # @retval 1 Error happenes in parsing + # + def LoadTargetTxtFile(self, Filename): + if os.path.exists(Filename) and os.path.isfile(Filename): + return self.ConvertTextFileToDict(Filename, '#', '=') + else: + EdkLogger.error("Target.txt Parser", FILE_NOT_FOUND, ExtraData=Filename) + return 1 + + ## ConvertTextFileToDict + # + # Convert a text file to a dictionary of (name:value) pairs. + # The data is saved to self.TargetTxtDictionary + # + # @param FileName: Text filename + # @param CommentCharacter: Comment char, be used to ignore comment content + # @param KeySplitCharacter: Key split char, between key name and key value. Key1 = Value1, '=' is the key split char + # + # @retval 0 Convert successfully + # @retval 1 Open file failed + # + def ConvertTextFileToDict(self, FileName, CommentCharacter, KeySplitCharacter): + F = None + try: + F = open(FileName,'r') + except: + EdkLogger.error("build", FILE_OPEN_FAILURE, ExtraData=FileName) + if F != None: + F.close() + + for Line in F: + Line = Line.strip() + if Line.startswith(CommentCharacter) or Line == '': + continue + + LineList = Line.split(KeySplitCharacter, 1) + Key = LineList[0].strip() + if len(LineList) == 2: + Value = LineList[1].strip() + else: + Value = "" + + if Key in [DataType.TAB_TAT_DEFINES_ACTIVE_PLATFORM, DataType.TAB_TAT_DEFINES_TOOL_CHAIN_CONF, \ + DataType.TAB_TAT_DEFINES_ACTIVE_MODULE, DataType.TAB_TAT_DEFINES_BUILD_RULE_CONF]: + self.TargetTxtDictionary[Key] = Value.replace('\\', '/') + elif Key in [DataType.TAB_TAT_DEFINES_TARGET, DataType.TAB_TAT_DEFINES_TARGET_ARCH, \ + DataType.TAB_TAT_DEFINES_TOOL_CHAIN_TAG]: + self.TargetTxtDictionary[Key] = Value.split() + elif Key == DataType.TAB_TAT_DEFINES_MULTIPLE_THREAD: + if Value not in ["Enable", "Disable"]: + EdkLogger.error("build", FORMAT_INVALID, "Invalid setting of [%s]: %s." % (Key, Value), + ExtraData="\tSetting must be one of [Enable, Disable]", + File=FileName) + self.TargetTxtDictionary[Key] = Value + elif Key == DataType.TAB_TAT_DEFINES_MAX_CONCURRENT_THREAD_NUMBER: + try: + V = int(Value, 0) + except: + EdkLogger.error("build", FORMAT_INVALID, "Invalid number of [%s]: %s." % (Key, Value), + File=FileName) + self.TargetTxtDictionary[Key] = Value + #elif Key not in GlobalData.gGlobalDefines: + # GlobalData.gGlobalDefines[Key] = Value + + F.close() + return 0 + + ## Print the dictionary + # + # Print all items of dictionary one by one + # + # @param Dict: The dictionary to be printed + # + def printDict(Dict): + if Dict != None: + KeyList = Dict.keys() + for Key in KeyList: + if Dict[Key] != '': + print Key + ' = ' + str(Dict[Key]) + + ## Print the dictionary + # + # Print the items of dictionary which matched with input key + # + # @param list: The dictionary to be printed + # @param key: The key of the item to be printed + # + def printList(Key, List): + if type(List) == type([]): + if len(List) > 0: + if Key.find(TAB_SPLIT) != -1: + print "\n" + Key + for Item in List: + print Item +## TargetTxtDict +# +# Load target.txt in input workspace dir +# +# @param WorkSpace: Workspace dir +# +# @retval Target An instance of TargetTxtClassObject() with loaded target.txt +# +def TargetTxtDict(WorkSpace): + Target = TargetTxtClassObject() + Target.LoadTargetTxtFile(os.path.normpath(os.path.join(WorkSpace, gDefaultTargetTxtFile))) + return Target + +## +# +# This acts like the main() function for the script, unless it is 'import'ed into another +# script. +# +if __name__ == '__main__': + pass + Target = TargetTxtDict(os.getenv("WORKSPACE")) + print Target.TargetTxtDictionary[DataType.TAB_TAT_DEFINES_MAX_CONCURRENT_THREAD_NUMBER] + print Target.TargetTxtDictionary[DataType.TAB_TAT_DEFINES_TARGET] + print Target.TargetTxtDictionary diff --git a/BaseTools/Source/Python/Common/ToolDefClassObject.py b/BaseTools/Source/Python/Common/ToolDefClassObject.py new file mode 100644 index 0000000000..5a9a3096bb --- /dev/null +++ b/BaseTools/Source/Python/Common/ToolDefClassObject.py @@ -0,0 +1,217 @@ +## @file +# This file is used to define each component of tools_def.txt file +# +# Copyright (c) 2007, 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. +# + +## +# Import Modules +# +import os +import re +import EdkLogger + +from Dictionary import * +from BuildToolError import * +from TargetTxtClassObject import * + +## +# Static vailabes used for pattern +# +gMacroRefPattern = re.compile('(DEF\([^\(\)]+\))') +gEnvRefPattern = re.compile('(ENV\([^\(\)]+\))') +gMacroDefPattern = re.compile("DEFINE\s+([^\s]+)") +gDefaultToolsDefFile = "Conf/tools_def.txt" + +## ToolDefClassObject +# +# This class defined content used in file tools_def.txt +# +# @param object: Inherited from object class +# @param Filename: Input value for full path of tools_def.txt +# +# @var ToolsDefTxtDictionary: To store keys and values defined in target.txt +# @var MacroDictionary: To store keys and values defined in DEFINE statement +# +class ToolDefClassObject(object): + def __init__(self, FileName = None): + self.ToolsDefTxtDictionary = {} + self.MacroDictionary = {} + for Env in os.environ: + self.MacroDictionary["ENV(%s)" % Env] = os.environ[Env] + + if FileName != None: + self.LoadToolDefFile(FileName) + + ## LoadToolDefFile + # + # Load target.txt file and parse it, return a set structure to store keys and values + # + # @param Filename: Input value for full path of tools_def.txt + # + def LoadToolDefFile(self, FileName): + FileContent = [] + if os.path.isfile(FileName): + try: + F = open(FileName,'r') + FileContent = F.readlines() + except: + EdkLogger.error("tools_def.txt parser", FILE_OPEN_FAILURE, ExtraData=FileName) + else: + EdkLogger.error("tools_def.txt parser", FILE_NOT_FOUND, ExtraData=FileName) + + self.ToolsDefTxtDatabase = { + TAB_TOD_DEFINES_TARGET : [], + TAB_TOD_DEFINES_TOOL_CHAIN_TAG : [], + TAB_TOD_DEFINES_TARGET_ARCH : [], + TAB_TOD_DEFINES_COMMAND_TYPE : [] + } + + for Index in range(len(FileContent)): + Line = FileContent[Index].strip() + if Line == "" or Line[0] == '#': + continue + NameValuePair = Line.split("=", 1) + if len(NameValuePair) != 2: + EdkLogger.warn("tools_def.txt parser", "Line %d: not correct assignment statement, skipped" % (Index + 1)) + continue + + Name = NameValuePair[0].strip() + Value = NameValuePair[1].strip() + + if Name == "IDENTIFIER": + EdkLogger.debug(EdkLogger.DEBUG_8, "Line %d: Found identifier statement, skipped: %s" % ((Index + 1), Value)) + continue + + MacroDefinition = gMacroDefPattern.findall(Name) + if MacroDefinition != []: + Done, Value = self.ExpandMacros(Value) + if not Done: + EdkLogger.error("tools_def.txt parser", ATTRIBUTE_NOT_AVAILABLE, + "Macro or Environment has not been defined", + ExtraData=Value[4:-1], File=FileName, Line=Index+1) + + MacroName = MacroDefinition[0].strip() + self.MacroDictionary["DEF(%s)" % MacroName] = Value + EdkLogger.debug(EdkLogger.DEBUG_8, "Line %d: Found macro: %s = %s" % ((Index + 1), MacroName, Value)) + continue + + Done, Value = self.ExpandMacros(Value) + if not Done: + EdkLogger.error("tools_def.txt parser", ATTRIBUTE_NOT_AVAILABLE, + "Macro or Environment has not been defined", + ExtraData=Value[4:-1], File=FileName, Line=Index+1) + + List = Name.split('_') + if len(List) != 5: + EdkLogger.verbose("Line %d: Not a valid name of definition: %s" % ((Index + 1), Name)) + continue + elif List[4] == '*': + EdkLogger.verbose("Line %d: '*' is not allowed in last field: %s" % ((Index + 1), Name)) + continue + else: + self.ToolsDefTxtDictionary[Name] = Value + if List[0] != '*': + self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_TARGET] += [List[0]] + if List[1] != '*': + self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_TOOL_CHAIN_TAG] += [List[1]] + if List[2] != '*': + self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_TARGET_ARCH] += [List[2]] + if List[3] != '*': + self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_COMMAND_TYPE] += [List[3]] + if List[4] == TAB_TOD_DEFINES_FAMILY and List[2] == '*' and List[3] == '*': + if TAB_TOD_DEFINES_FAMILY not in self.ToolsDefTxtDatabase: + self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_FAMILY] = {} + self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_FAMILY][List[1]] = Value + self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_BUILDRULEFAMILY] = {} + self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_BUILDRULEFAMILY][List[1]] = Value + elif List[1] not in self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_FAMILY]: + self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_FAMILY][List[1]] = Value + self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_BUILDRULEFAMILY][List[1]] = Value + elif self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_FAMILY][List[1]] != Value: + EdkLogger.verbose("Line %d: No override allowed for the family of a tool chain: %s" % ((Index + 1), Name)) + if List[4] == TAB_TOD_DEFINES_BUILDRULEFAMILY and List[2] == '*' and List[3] == '*': + if TAB_TOD_DEFINES_BUILDRULEFAMILY not in self.ToolsDefTxtDatabase \ + or List[1] not in self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_FAMILY]: + EdkLogger.verbose("Line %d: The family is not specified, but BuildRuleFamily is specified for the tool chain: %s" % ((Index + 1), Name)) + self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_BUILDRULEFAMILY][List[1]] = Value + + self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_TARGET] = list(set(self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_TARGET])) + self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_TOOL_CHAIN_TAG] = list(set(self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_TOOL_CHAIN_TAG])) + self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_TARGET_ARCH] = list(set(self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_TARGET_ARCH])) + self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_COMMAND_TYPE] = list(set(self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_COMMAND_TYPE])) + + self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_TARGET].sort() + self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_TOOL_CHAIN_TAG].sort() + self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_TARGET_ARCH].sort() + self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_COMMAND_TYPE].sort() + + KeyList = [TAB_TOD_DEFINES_TARGET, TAB_TOD_DEFINES_TOOL_CHAIN_TAG, TAB_TOD_DEFINES_TARGET_ARCH, TAB_TOD_DEFINES_COMMAND_TYPE] + for Index in range(3,-1,-1): + for Key in dict(self.ToolsDefTxtDictionary): + List = Key.split('_') + if List[Index] == '*': + for String in self.ToolsDefTxtDatabase[KeyList[Index]]: + List[Index] = String + NewKey = '%s_%s_%s_%s_%s' % tuple(List) + if NewKey not in self.ToolsDefTxtDictionary: + self.ToolsDefTxtDictionary[NewKey] = self.ToolsDefTxtDictionary[Key] + continue + del self.ToolsDefTxtDictionary[Key] + elif List[Index] not in self.ToolsDefTxtDatabase[KeyList[Index]]: + del self.ToolsDefTxtDictionary[Key] + + ## ExpandMacros + # + # Replace defined macros with real value + # + # @param Value: The string with unreplaced macros + # + # @retval Value: The string which has been replaced with real value + # + def ExpandMacros(self, Value): + EnvReference = gEnvRefPattern.findall(Value) + for Ref in EnvReference: + if Ref not in self.MacroDictionary: + return False, Ref + Value = Value.replace(Ref, self.MacroDictionary[Ref]) + + MacroReference = gMacroRefPattern.findall(Value) + for Ref in MacroReference: + if Ref not in self.MacroDictionary: + return False, Ref + Value = Value.replace(Ref, self.MacroDictionary[Ref]) + + return True, Value + +## ToolDefDict +# +# Load tools_def.txt in input workspace dir +# +# @param WorkSpace: Workspace dir +# +# @retval ToolDef An instance of ToolDefClassObject() with loaded tools_def.txt +# +def ToolDefDict(WorkSpace): + Target = TargetTxtDict(WorkSpace) + ToolDef = ToolDefClassObject() + if DataType.TAB_TAT_DEFINES_TOOL_CHAIN_CONF in Target.TargetTxtDictionary: + gDefaultToolsDefFile = Target.TargetTxtDictionary[DataType.TAB_TAT_DEFINES_TOOL_CHAIN_CONF] + ToolDef.LoadToolDefFile(os.path.normpath(os.path.join(WorkSpace, gDefaultToolsDefFile))) + return ToolDef + +## +# +# This acts like the main() function for the script, unless it is 'import'ed into another +# script. +# +if __name__ == '__main__': + ToolDef = ToolDefDict(os.getenv("WORKSPACE")) + pass diff --git a/BaseTools/Source/Python/Common/XmlParser.py b/BaseTools/Source/Python/Common/XmlParser.py new file mode 100644 index 0000000000..4d60115925 --- /dev/null +++ b/BaseTools/Source/Python/Common/XmlParser.py @@ -0,0 +1,1754 @@ +## @file +# This file is used to parse a xml file of .PKG file +# +# Copyright (c) 2008, 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. +# + +## +# Import Modules +# +from xml.dom import minidom +from XmlRoutines import * +from CommonDataClass.DistributionPackageClass import * +from CommonDataClass.PackageClass import * +from CommonDataClass.ModuleClass import * +from Common.String import GetStringOfList + +# +# Get Help Text +# +def GetHelpTextList(HelpText): + HelpTextList = [] + for HT in HelpText: + HelpTextObj = HelpTextClass() + HelpTextObj.Lang = HT.Lang + HelpTextObj.String = HT.HelpText + HelpTextList.append(HelpTextObj) + return HelpTextList + +# HeaderXml +class HeaderXml(object): + def __init__(self): + self.Name = '' + self.BaseName = '' + self.GUID = '' + self.Version = '' + self.Copyright = '' + self.License = '' + self.Abstract = '' + self.Description = '' + + def FromXml(self, Item, Key): + self.Name = XmlElement(Item, '%s/Name' % Key) + self.BaseName = XmlAttribute(XmlNode(Item, '%s/Name' % Key), 'BaseName') + self.GUID = XmlElement(Item, '%s/GUID' % Key) + self.Version = XmlAttribute(XmlNode(Item, '%s/GUID' % Key), 'Version') + self.Copyright = XmlElement(Item, '%s/Copyright' % Key) + self.License = XmlElement(Item, '%s/License' % Key) + self.Abstract = XmlElement(Item, '%s/Abstract' % Key) + self.Description = XmlElement(Item, '%s/Description' % Key) + + ModuleHeader = ModuleHeaderClass() + ModuleHeader.Name = self.Name + ModuleHeader.BaseName = self.BaseName + ModuleHeader.Guid = self.GUID + ModuleHeader.Version = self.Version + ModuleHeader.Copyright = self.Copyright + ModuleHeader.License = self.License + ModuleHeader.Abstract = self.Abstract + ModuleHeader.Description = self.Description + + return ModuleHeader + + def ToXml(self, Header, Key): + Element1 = CreateXmlElement('Name', Header.Name, [], [['BaseName', Header.BaseName]]) + Element2 = CreateXmlElement('GUID', Header.Guid, [], [['Version', Header.Version]]) + AttributeList = [] + NodeList = [Element1, + Element2, + ['Abstract', Header.Abstract], + ['Copyright', Header.Copyright], + ['License', Header.License], + ['Description', Header.Description], + ] + Root = CreateXmlElement('%s' % Key, '', NodeList, AttributeList) + + return Root + + def __str__(self): + return "Name = %s BaseName = %s GUID = %s Version = %s Copyright = %s License = %s Abstract = %s Description = %s" \ + % (self.Name, self.BaseName, self.GUID, self.Version, self.Copyright, self.License, self.Abstract, self.Description) + +# DistributionPackageHeaderXml +class DistributionPackageHeaderXml(object): + def __init__(self): + self.Header = HeaderXml() + self.ReadOnly = False + self.RePackage = True + self.Vendor = '' + self.Date = '' + self.Signature = '' + self.XmlSpecification = '' + + def FromXml(self, Item, Key): + self.ReadOnly = XmlAttribute(XmlNode(Item, '%s' % Key), 'ReadOnly') + self.RePackage = XmlAttribute(XmlNode(Item, '%s' % Key), 'RePackage') + self.Vendor = XmlElement(Item, '%s/Vendor' % Key) + self.Date = XmlElement(Item, '%s/Date' % Key) + self.Signature = XmlElement(Item, '%s/Signature' % Key) + self.XmlSpecification = XmlElement(Item, '%s/XmlSpecification' % Key) + self.Header.FromXml(Item, Key) + + DistributionPackageHeader = DistributionPackageHeaderClass() + DistributionPackageHeader.ReadOnly = self.ReadOnly + DistributionPackageHeader.RePackage = self.RePackage + DistributionPackageHeader.Name = self.Header.Name + DistributionPackageHeader.BaseName = self.Header.BaseName + DistributionPackageHeader.Guid = self.Header.GUID + DistributionPackageHeader.Version = self.Header.Version + DistributionPackageHeader.Vendor = self.Vendor + DistributionPackageHeader.Date = self.Date + DistributionPackageHeader.Copyright = self.Header.Copyright + DistributionPackageHeader.License = self.Header.License + DistributionPackageHeader.Abstract = self.Header.Abstract + DistributionPackageHeader.Description = self.Header.Description + DistributionPackageHeader.Signature = self.Signature + DistributionPackageHeader.XmlSpecification = self.XmlSpecification + + return DistributionPackageHeader + + def ToXml(self, DistributionPackageHeader, Key): + Element1 = CreateXmlElement('Name', DistributionPackageHeader.Name, [], [['BaseName', DistributionPackageHeader.BaseName]]) + Element2 = CreateXmlElement('GUID', DistributionPackageHeader.Guid, [], [['Version', DistributionPackageHeader.Version]]) + AttributeList = [['ReadOnly', str(DistributionPackageHeader.ReadOnly)], ['RePackage', str(DistributionPackageHeader.RePackage)]] + NodeList = [Element1, + Element2, + ['Vendor', DistributionPackageHeader.Vendor], + ['Date', DistributionPackageHeader.Date], + ['Copyright', DistributionPackageHeader.Copyright], + ['License', DistributionPackageHeader.License], + ['Abstract', DistributionPackageHeader.Abstract], + ['Description', DistributionPackageHeader.Description], + ['Signature', DistributionPackageHeader.Signature], + ['XmlSpecification', DistributionPackageHeader.XmlSpecification], + ] + Root = CreateXmlElement('%s' % Key, '', NodeList, AttributeList) + + return Root + + def __str__(self): + return "ReadOnly = %s RePackage = %s Vendor = %s Date = %s Signature = %s XmlSpecification = %s %s" \ + % (self.ReadOnly, self.RePackage, self.Vendor, self.Date, self.Signature, self.XmlSpecification, self.Header) + +# PackageHeaderXml +class PackageHeaderXml(object): + def __init__(self): + self.Header = HeaderXml() + self.PackagePath = '' + + def FromXml(self, Item, Key): + self.PackagePath = XmlElement(Item, '%s/PackagePath' % Key) + self.Header.FromXml(Item, Key) + + PackageHeader = PackageHeaderClass() + PackageHeader.Name = self.Header.Name + PackageHeader.BaseName = self.Header.BaseName + PackageHeader.Guid = self.Header.GUID + PackageHeader.Version = self.Header.Version + PackageHeader.Copyright = self.Header.Copyright + PackageHeader.License = self.Header.License + PackageHeader.Abstract = self.Header.Abstract + PackageHeader.Description = self.Header.Description + PackageHeader.CombinePath = self.PackagePath + + return PackageHeader + + def ToXml(self, PackageHeader, Key): + Element1 = CreateXmlElement('Name', PackageHeader.Name, [], [['BaseName', PackageHeader.BaseName]]) + Element2 = CreateXmlElement('GUID', PackageHeader.Guid, [], [['Version', PackageHeader.Version]]) + AttributeList = [] + NodeList = [Element1, + Element2, + ['Copyright', PackageHeader.Copyright], + ['License', PackageHeader.License], + ['Abstract', PackageHeader.Abstract], + ['Description', PackageHeader.Description], + ['PackagePath', PackageHeader.CombinePath], + ] + Root = CreateXmlElement('%s' % Key, '', NodeList, AttributeList) + + return Root + + def __str__(self): + return "PackagePath = %s %s" \ + % (self.PackagePath, self.Header) + +# ClonedFromXml +class ClonedFromXml(object): + def __init__(self): + self.GUID = '' + self.Version = '' + + def FromXml(self, Item, Key): + self.GUID = XmlElement(Item, '%s/GUID' % Key) + self.Version = XmlAttribute(XmlNode(Item, '%s/GUID' % Key), 'Version') + + if self.GUID == '' and self.Version == '': + return None + + ClonedFrom = ClonedRecordClass() + ClonedFrom.PackageGuid = self.GUID + ClonedFrom.PackageVersion = self.Version + + return ClonedFrom + + def ToXml(self, ClonedFrom, Key): + Root = minidom.Document() + Element1 = CreateXmlElement('GUID', ClonedFrom.PackageGuid, [], [['Version', ClonedFrom.PackageVersion]]) + AttributeList = [] + NodeList = [Element1] + Root = CreateXmlElement('%s' % Key, '', NodeList, AttributeList) + + return Root + + def __str__(self): + return "GUID = %s Version = %s" % (self.GUID, self.Version) + +# CommonDefinesXml +class CommonDefinesXml(object): + def __init__(self): + self.Usage = '' + self.SupArchList = '' + self.SupModList = '' + self.FeatureFlag = '' + + def FromXml(self, Item, Key): + self.Usage = XmlAttribute(Item, 'Usage') + self.SupArchList = XmlAttribute(Item, 'SupArchList') + self.SupModList = XmlAttribute(Item, 'SupModList') + self.FeatureFlag = XmlAttribute(Item, 'FeatureFlag') + + def ToXml(self): + pass + + def __str__(self): + return "Usage = %s SupArchList = %s SupModList = %s FeatureFlag = %s" % (self.Usage, self.SupArchList, self.SupModList, self.FeatureFlag) + +# HelpTextXml +class HelpTextXml(object): + def __init__(self): + self.HelpText = '' + self.Lang = '' + + def FromXml(self, Item, Key): + self.HelpText = XmlElement(Item, 'HelpText') + self.Lang = XmlAttribute(Item, 'Lang') + + def ToXml(self, HelpText, Key = 'HelpText'): + return CreateXmlElement('%s' % Key, HelpText.String, [], [['Lang', HelpText.Lang]]) + + def __str__(self): + return "HelpText = %s Lang = %s" % (self.HelpText, self.Lang) + +# LibraryClassXml +class LibraryClassXml(object): + def __init__(self): + self.Keyword = '' + self.HeaderFile = '' + self.RecommendedInstanceGuid = '' + self.RecommendedInstanceVersion = '' + self.CommonDefines = CommonDefinesXml() + self.HelpText = [] + + def FromXml(self, Item, Key): + self.Keyword = XmlAttribute(XmlNode(Item, '%s' % Key), 'Keyword') + if self.Keyword == '': + self.Keyword = XmlElement(Item, '%s/Keyword' % Key) + self.HeaderFile = XmlElement(Item, '%s/HeaderFile' % Key) + self.RecommendedInstanceGuid = XmlElement(Item, '%s/RecommendedInstance/GUID' % Key) + self.RecommendedInstanceVersion = XmlAttribute(XmlNode(Item, '%s/RecommendedInstance/GUID' % Key), 'Version') + self.CommonDefines.FromXml(XmlNode(Item, '%s' % Key), Key) + for HelpTextItem in XmlList(Item, '%s/HelpText' % Key): + HelpTextObj = HelpTextXml() + HelpTextObj.FromXml(HelpTextItem, '%s/HelpText' % Key) + self.HelpText.append(HelpTextObj) + + LibraryClass = LibraryClassClass() + LibraryClass.LibraryClass = self.Keyword + LibraryClass.IncludeHeader = self.HeaderFile + LibraryClass.SupArchList = self.CommonDefines.SupArchList + LibraryClass.SupModuleList = self.CommonDefines.SupModList + LibraryClass.RecommendedInstanceGuid = self.RecommendedInstanceGuid + LibraryClass.RecommendedInstanceVersion = self.RecommendedInstanceVersion + LibraryClass.HelpTextList = GetHelpTextList(self.HelpText) + + return LibraryClass + + def ToXml(self, LibraryClass, Key): + Element1 = CreateXmlElement('GUID', LibraryClass.RecommendedInstanceGuid, [], [['Version', LibraryClass.RecommendedInstanceVersion]]) + Element2 = CreateXmlElement('RecommendedInstance', '', [Element1], []) + AttributeList = [['Keyword', LibraryClass.LibraryClass], + ['SupArchList', GetStringOfList(LibraryClass.SupArchList)], + ['SupModList', GetStringOfList(LibraryClass.SupModuleList)] + ] + NodeList = [['HeaderFile', LibraryClass.IncludeHeader], + Element2 + ] + for Item in LibraryClass.HelpTextList: + Tmp = HelpTextXml() + NodeList.append(Tmp.ToXml(Item)) + Root = CreateXmlElement('%s' % Key, '', NodeList, AttributeList) + + return Root + + def __str__(self): + Str = "Keyword = %s HeaderFile = %s RecommendedInstanceGuid = %s RecommendedInstanceVersion = %s %s" \ + % (self.Keyword, self.HeaderFile, self.RecommendedInstanceGuid, self.RecommendedInstanceVersion, \ + self.CommonDefines) + for Item in self.HelpText: + Str = Str + "\n\t" + str(Item) + return Str + +# IndustryStandardHeaderXml +class IndustryStandardHeaderXml(object): + def __init__(self): + self.HeaderFile = '' + self.HelpText = [] + + def FromXml(self, Item, Key): + self.HeaderFile = XmlElement(Item, '%s/HeaderFile' % Key) + for HelpTextItem in XmlList(Item, '%s/HelpText' % Key): + HelpTextObj = HelpTextXml() + HelpTextObj.FromXml(HelpTextItem, '%s/HelpText' % Key) + self.HelpText.append(HelpTextObj) + + Include = IncludeClass() + Include.FilePath = self.HeaderFile + Include.HelpTextList = GetHelpTextList(self.HelpText) + + return Include + + def ToXml(self, IndustryStandardHeader, Key): + AttributeList = [] + NodeList = [['HeaderFile', IndustryStandardHeader.FilePath]] + for Item in IndustryStandardHeader.HelpTextList: + Tmp = HelpTextXml() + NodeList.append(Tmp.ToXml(Item)) + Root = CreateXmlElement('%s' % Key, '', NodeList, AttributeList) + + return Root + + def __str__(self): + Str = "HeaderFile = %s" % (self.HeaderFile) + for Item in self.HelpText: + Str = Str + "\n\t" + str(Item) + return Str + +# PackageIncludeHeaderXml +class PackageIncludeHeaderXml(object): + def __init__(self): + self.HeaderFile = '' + self.CommonDefines = CommonDefinesXml() + self.HelpText = [] + + def FromXml(self, Item, Key): + self.HeaderFile = XmlElement(Item, '%s/HeaderFile' % Key) + self.CommonDefines.FromXml(XmlNode(Item, '%s/HeaderFile' % Key), Key) + for HelpTextItem in XmlList(Item, '%s/HelpText' % Key): + HelpTextObj = HelpTextXml() + HelpTextObj.FromXml(HelpTextItem, '%s/HelpText' % Key) + self.HelpText.append(HelpTextObj) + + Include = IncludeClass() + Include.FilePath = self.HeaderFile + Include.SupArchList = self.CommonDefines.SupArchList + Include.SupModuleList = self.CommonDefines.SupModList + Include.HelpTextList = GetHelpTextList(self.HelpText) + + return Include + + def ToXml(self, PackageIncludeHeader, Key): + AttributeList = [['SupArchList', PackageIncludeHeader.SupArchList], + ['SupModList', PackageIncludeHeader.SupModuleList] + ] + NodeList = [['HeaderFile', PackageIncludeHeader.FilePath]] + for Item in PackageIncludeHeader.HelpTextList: + Tmp = HelpTextXml() + NodeList.append(Tmp.ToXml(Item)) + Root = CreateXmlElement('%s' % Key, '', NodeList, AttributeList) + + return Root + + def __str__(self): + Str = "HeaderFile = %s\n\t%s" % (self.HeaderFile, self.CommonDefines) + for Item in self.HelpText: + Str = Str + "\n\t" + str(Item) + return Str + +#GUID/Protocol/Ppi +class GuidProtocolPpiXml(object): + def __init__(self): + self.UiName = '' + self.GuidTypes = '' + self.Notify = '' + self.CName = '' + self.GuidValue = '' + self.CommonDefines = CommonDefinesXml() + self.HelpText = [] + + def FromXml(self, Item, Key): + self.UiName = XmlAttribute(XmlNode(Item, '%s' % Key), 'UiName') + self.GuidTypes = XmlAttribute(XmlNode(Item, '%s' % Key), 'GuidTypes') + self.GuidType = XmlAttribute(XmlNode(Item, '%s' % Key), 'GuidType') + self.Notify = XmlAttribute(XmlNode(Item, '%s' % Key), 'Notify') + self.CName = XmlElement(Item, '%s/CName' % Key) + self.GuidValue = XmlElement(Item, '%s/GuidValue' % Key) + self.VariableName = XmlElement(Item, '%s/VariableName' % Key) + self.CommonDefines.FromXml(XmlNode(Item, '%s' % Key), Key) + for HelpTextItem in XmlList(Item, '%s/HelpText' % Key): + HelpTextObj = HelpTextXml() + HelpTextObj.FromXml(HelpTextItem, '%s/HelpText' % Key) + self.HelpText.append(HelpTextObj) + + GuidProtocolPpi = GuidProtocolPpiCommonClass() + GuidProtocolPpi.Name = self.UiName + GuidProtocolPpi.CName = self.CName + GuidProtocolPpi.Guid = self.GuidValue + GuidProtocolPpi.VariableName = self.VariableName + GuidProtocolPpi.Notify = self.Notify + GuidProtocolPpi.Usage = self.CommonDefines.Usage + GuidProtocolPpi.FeatureFlag = self.CommonDefines.FeatureFlag + GuidProtocolPpi.SupArchList = self.CommonDefines.SupArchList + GuidProtocolPpi.SupModuleList = self.CommonDefines.SupModList + GuidProtocolPpi.GuidTypeLists = self.GuidTypes + GuidProtocolPpi.GuidTypeList = self.GuidType + GuidProtocolPpi.HelpTextList = GetHelpTextList(self.HelpText) + + return GuidProtocolPpi + + def ToXml(self, GuidProtocolPpi, Key): + AttributeList = [['Usage', GetStringOfList(GuidProtocolPpi.Usage)], + ['UiName', GuidProtocolPpi.Name], + ['GuidTypes', GetStringOfList(GuidProtocolPpi.GuidTypeLists)], + ['GuidType', GetStringOfList(GuidProtocolPpi.GuidTypeList)], + ['Notify', str(GuidProtocolPpi.Notify)], + ['SupArchList', GetStringOfList(GuidProtocolPpi.SupArchList)], + ['SupModList', GetStringOfList(GuidProtocolPpi.SupModuleList)], + ['FeatureFlag', GuidProtocolPpi.FeatureFlag] + ] + NodeList = [['CName', GuidProtocolPpi.CName], + ['GuidValue', GuidProtocolPpi.Guid], + ['VariableName', GuidProtocolPpi.VariableName] + ] + for Item in GuidProtocolPpi.HelpTextList: + Tmp = HelpTextXml() + NodeList.append(Tmp.ToXml(Item)) + Root = CreateXmlElement('%s' % Key, '', NodeList, AttributeList) + + return Root + + def __str__(self): + Str = "UiName = %s Notify = %s GuidTypes = %s CName = %s GuidValue = %s %s" \ + % (self.UiName, self.Notify, self.GuidTypes, self.CName, self.GuidValue, self.CommonDefines) + for Item in self.HelpText: + Str = Str + "\n\t" + str(Item) + return Str + +# PcdErrorXml +class PcdErrorXml(object): + def __init__(self): + self.ValidValueList = '' + self.ValidValueListLang = '' + self.ValidValueRange = '' + self.Expression = '' + self.ErrorNumber = '' + self.ErrorMessage = [] + + def FromXml(self, Item, Key): + self.ValidValueList = XmlElement(Item, '%s/ValidValueList' % Key) + self.ValidValueListLang = XmlAttribute(XmlNode(Item, '%s/ValidValueList' % Key), 'Lang') + self.ValidValueRange = XmlElement(Item, '%s/ValidValueRange' % Key) + self.Expression = XmlElement(Item, '%s/Expression' % Key) + self.ErrorNumber = XmlElement(Item, '%s/ErrorNumber' % Key) + for ErrMsg in XmlList(Item, '%s/ErrorMessage' % Key): + ErrorMessageString = XmlElement(ErrMsg, 'ErrorMessage') + ErrorMessageLang = XmlAttribute(XmlNode(ErrMsg, 'ErrorMessage'), 'Lang') + self.ErrorMessage.append((ErrorMessageLang, ErrorMessageString)) + + Error = PcdErrorClass() + Error.ValidValueList = self.ValidValueList + Error.ValidValueListLang = self.ValidValueListLang + Error.ValidValueRange = self.ValidValueRange + Error.Expression = self.Expression + Error.ErrorNumber = self.ErrorNumber + Error.ErrorMessage = self.ErrorMessage + + return Error + + def ToXml(self, PcdError, Key): + AttributeList = [] + Element1 = CreateXmlElement('ValidValueList', PcdError.ValidValueList, [], [['Lang', PcdError.ValidValueListLang]]) + NodeList = [Element1, + ['ValidValueRange', PcdError.ValidValueRange], + ['Expression', PcdError.Expression], + ['ErrorNumber', PcdError.ErrorNumber], + ] + for Item in PcdError.ErrorMessage: + Element = CreateXmlElement('ErrorMessage', Item[1], [], [['Lang', Item[0]]]) + NodeList.append(Element) + Root = CreateXmlElement('%s' % Key, '', NodeList, AttributeList) + + return Root + + def __str__(self): + return "ValidValueList = %s ValidValueListLang = %s ValidValueRange = %s Expression = %s ErrorNumber = %s %s" \ + % (self.ValidValueList, self.ValidValueListLang, self.ValidValueRange, self.Expression, self.ErrorNumber, self.ErrorMessage) + +# PcdEntryXml +class PcdEntryXml(object): + def __init__(self): + self.PcdItemType = '' + self.PcdUsage = '' + self.TokenSpaceGuidCName = '' + self.TokenSpaceGuidValue = '' + self.Token = '' + self.CName = '' + self.PcdCName = '' + self.DatumType = '' + self.ValidUsage = '' + self.DefaultValue = '' + self.MaxDatumSize = '' + self.Value = '' + self.Offset = '' + self.CommonDefines = CommonDefinesXml() + self.HelpText = [] + self.PcdError = [] + + def FromXml(self, Item, Key): + self.PcdItemType = XmlAttribute(XmlNode(Item, '%s' % Key), 'PcdItemType') + self.PcdUsage = XmlAttribute(XmlNode(Item, '%s' % Key), 'PcdUsage') + self.TokenSpaceGuidCName = XmlElement(Item, '%s/TokenSpaceGuidCName' % Key) + self.TokenSpaceGuidValue = XmlElement(Item, '%s/TokenSpaceGuidValue' % Key) + self.Token = XmlElement(Item, '%s/Token' % Key) + self.CName = XmlElement(Item, '%s/CName' % Key) + self.PcdCName = XmlElement(Item, '%s/PcdCName' % Key) + self.DatumType = XmlElement(Item, '%s/DatumType' % Key) + self.ValidUsage = XmlElement(Item, '%s/ValidUsage' % Key) + self.DefaultValue = XmlElement(Item, '%s/DefaultValue' % Key) + self.MaxDatumSize = XmlElement(Item, '%s/MaxDatumSize' % Key) + self.Value = XmlElement(Item, '%s/Value' % Key) + self.Offset = XmlElement(Item, '%s/Offset' % Key) + self.CommonDefines.FromXml(XmlNode(Item, '%s' % Key), Key) + for HelpTextItem in XmlList(Item, '%s/HelpText' % Key): + HelpTextObj = HelpTextXml() + HelpTextObj.FromXml(HelpTextItem, '%s/HelpText' % Key) + self.HelpText.append(HelpTextObj) + for PcdErrorItem in XmlList(Item, '%s/PcdError' % Key): + PcdErrorObj = PcdErrorXml() + PcdErrorObj.FromXml(PcdErrorItem, 'PcdError') + self.PcdError.append(PcdErrorObj) + + PcdEntry = PcdClass() + PcdEntry.SupArchList = self.CommonDefines.SupArchList + PcdEntry.SupModuleList = self.CommonDefines.SupModList + PcdEntry.TokenSpaceGuidCName = self.TokenSpaceGuidCName + PcdEntry.TokenSpaceGuidValue = self.TokenSpaceGuidValue + PcdEntry.Token = self.Token + PcdEntry.CName = self.CName + PcdEntry.PcdCName = self.PcdCName + PcdEntry.DatumType = self.DatumType + PcdEntry.ValidUsage = self.ValidUsage + PcdEntry.PcdUsage = self.PcdUsage + PcdEntry.Usage = self.CommonDefines.Usage + PcdEntry.DefaultValue = self.DefaultValue + PcdEntry.Value = self.Value + PcdEntry.Offset = self.Offset + PcdEntry.MaxDatumSize = self.MaxDatumSize + PcdEntry.FeatureFlag = self.CommonDefines.FeatureFlag + PcdEntry.PcdItemType = self.PcdItemType + PcdEntry.HelpTextList = GetHelpTextList(self.HelpText) + PcdEntry.PcdErrors = self.PcdError + + return PcdEntry + + def ToXml(self, PcdEntry, Key): + AttributeList = [['SupArchList', GetStringOfList(PcdEntry.SupArchList)], + ['PcdUsage', PcdEntry.PcdUsage], + ['PcdItemType', PcdEntry.PcdItemType], + ['FeatureFlag', PcdEntry.FeatureFlag], + ['SupModList', GetStringOfList(PcdEntry.SupModuleList)] + ] + NodeList = [['TokenSpaceGuidCName', PcdEntry.TokenSpaceGuidCName], + ['TokenSpaceGuidValue', PcdEntry.TokenSpaceGuidValue], + ['Token', PcdEntry.Token], + ['CName', PcdEntry.CName], + ['PcdCName', PcdEntry.PcdCName], + ['DatumType', PcdEntry.DatumType], + ['ValidUsage', GetStringOfList(PcdEntry.ValidUsage)], + ['DefaultValue', PcdEntry.DefaultValue], + ['Value', PcdEntry.Value], + ['Offset', PcdEntry.Offset], + ['MaxDatumSize', PcdEntry.MaxDatumSize], + ] + for Item in PcdEntry.HelpTextList: + Tmp = HelpTextXml() + NodeList.append(Tmp.ToXml(Item, 'HelpText')) + for Item in PcdEntry.PcdErrors: + Tmp = PcdErrorXml() + NodeList.append(Tmp.ToXml(Item, 'PcdError')) + + Root = CreateXmlElement('%s' % Key, '', NodeList, AttributeList) + + return Root + + def __str__(self): + Str = "PcdItemType = %s PcdUsage = %s TokenSpaceGuidCName = %s TokenSpaceGuidValue = %s Token = %s CName = %s PcdCName = %s DatumType = %s ValidUsage = %s DefaultValue = %s MaxDatumSize = %s Value = %s Offset = %s %s" \ + % (self.PcdItemType, self.PcdUsage, self.TokenSpaceGuidCName, self.TokenSpaceGuidValue, self.Token, self.CName, self.PcdCName, self.DatumType, self.ValidUsage, self.DefaultValue, self.MaxDatumSize, self.Value, self.Offset, self.CommonDefines) + for Item in self.HelpText: + Str = Str + "\n\t" + str(Item) + for Item in self.PcdError: + Str = Str + "\n\tPcdError:" + str(Item) + return Str + +# PcdCheckXml +class PcdCheckXml(object): + def __init__(self): + self.PcdCheck = '' + + def FromXml(self, Item, Key): + self.PcdCheck = XmlElement(Item, 'PcdCheck') + + return self.PcdCheck + + def ToXml(self, PcdCheck, Key): + Root = CreateXmlElement('%s' % Key, PcdCheck, [], []) + return Root + + def __str__(self): + return "PcdCheck = %s" % (self.PcdCheck) + +# MiscellaneousFileXml +class MiscellaneousFileXml(object): + def __init__(self): + self.Header = HeaderXml() + self.Files = [] + + def FromXml(self, Item, Key): + self.Header.FromXml(Item, Key) + NewItem = XmlNode(Item, '%s/Header' % Key) + self.Header.FromXml(NewItem, 'Header') + + for SubItem in XmlList(Item, '%s/Filename' % Key): + Filename = XmlElement(SubItem, '%s/Filename' % Key) + Executable = XmlAttribute(XmlNode(SubItem, '%s/Filename' % Key), 'Executable') + self.Files.append([Filename, Executable]) + + MiscFile = MiscFileClass() + MiscFile.Copyright = self.Header.Copyright + MiscFile.License = self.Header.License + MiscFile.Abstract = self.Header.Abstract + MiscFile.Description = self.Header.Description + for File in self.Files: + FileObj = FileClass() + FileObj.Filename = File[0] + FileObj.Executable = File[1] + MiscFile.Files.append(FileObj) + + return MiscFile + + def FromXml2(self, Item, Key): + NewItem = XmlNode(Item, '%s/Header' % Key) + self.Header.FromXml(NewItem, 'Header') + + for SubItem in XmlList(Item, '%s/Filename' % Key): + Filename = XmlElement(SubItem, '%s/Filename' % Key) + Executable = XmlAttribute(XmlNode(SubItem, '%s/Filename' % Key), 'Executable') + self.Files.append([Filename, Executable]) + + MiscFile = MiscFileClass() + MiscFile.Name = self.Header.Name + MiscFile.Copyright = self.Header.Copyright + MiscFile.License = self.Header.License + MiscFile.Abstract = self.Header.Abstract + MiscFile.Description = self.Header.Description + for File in self.Files: + FileObj = FileClass() + FileObj.Filename = File[0] + FileObj.Executable = File[1] + MiscFile.Files.append(FileObj) + + return MiscFile + + + def ToXml(self, MiscFile, Key): + if MiscFile: + NodeList = [['Copyright', MiscFile.Copyright], + ['License', MiscFile.License], + ['Abstract', MiscFile.Abstract], + ['Description', MiscFile.Description], + ] + if MiscFile != None: + for File in MiscFile.Files: + NodeList.append(CreateXmlElement('Filename', File.Filename, [], [['Executable', File.Executable]])) + Root = CreateXmlElement('%s' % Key, '', NodeList, []) + + return Root + + def ToXml2(self, MiscFile, Key): + if MiscFile: + NodeList = [['Name', MiscFile.Name], + ['Copyright', MiscFile.Copyright], + ['License', MiscFile.License], + ['Abstract', MiscFile.Abstract], + ['Description', MiscFile.Description], + ] + HeaderNode = CreateXmlElement('Header', '', NodeList, []) + NodeList = [HeaderNode] + + for File in MiscFile.Files: + NodeList.append(CreateXmlElement('Filename', File.Filename, [], [['Executable', File.Executable]])) + Root = CreateXmlElement('%s' % Key, '', NodeList, []) + + return Root + + def __str__(self): + Str = str(self.Header) + for Item in self.Files: + Str = Str + '\n\tFilename:' + str(Item) + return Str + +# UserExtensionsXml +class UserExtensionsXml(object): + def __init__(self): + self.UserId = '' + self.Identifier = '' + self.Defines = [] + self.BuildOptions = [] + + def FromXml(self, Item, Key): + self.UserId = XmlAttribute(XmlNode(Item, '%s' % Key), 'UserId') + self.Identifier = XmlAttribute(XmlNode(Item, '%s' % Key), 'Identifier') + for SubItem in XmlList(Item, '%s/Define' % Key): + self.Defines.append(XmlElement(SubItem, '%s/Define' % Key)) + for SubItem in XmlList(Item, '%s/BuildOption' % Key): + self.BuildOptions.append(XmlElement(SubItem, '%s/BuildOption' % Key)) + + UserExtension = UserExtensionsClass() + UserExtension.UserID = self.UserId + UserExtension.Identifier = self.Identifier + UserExtension.Defines = self.Defines + UserExtension.BuildOptions = self.BuildOptions + + return UserExtension + + def ToXml(self, UserExtension, Key): + AttributeList = [['UserId', str(UserExtension.UserID)], + ['Identifier', str(UserExtension.Identifier)] + ] + NodeList = [] + for Item in UserExtension.Defines: + NodeList.append(['Define', Item]) + for Item in UserExtension.BuildOptions: + NodeList.append(['BuildOption', Item]) + Root = CreateXmlElement('%s' % Key, UserExtension.Content, NodeList, AttributeList) + + return Root + + def __str__(self): + Str = "UserId = %s Identifier = %s" % (self.UserId, self.Identifier) + Str = Str + '\n\tDefines:' + str(self.Defines) + Str = Str + '\n\tBuildOptions:' + str(self.BuildOptions) + return Str + +# BootModeXml +class BootModeXml(object): + def __init__(self): + self.SupportedBootModes = '' + self.CommonDefines = CommonDefinesXml() + self.HelpText = [] + + def FromXml(self, Item, Key): + self.SupportedBootModes = XmlElement(Item, '%s/SupportedBootModes' % Key) + self.CommonDefines.FromXml(Item, Key) + for HelpTextItem in XmlList(Item, '%s/HelpText' % Key): + HelpTextObj = HelpTextXml() + HelpTextObj.FromXml(HelpTextItem, '%s/HelpText' % Key) + self.HelpText.append(HelpTextObj) + + BootMode = ModuleBootModeClass() + BootMode.Name = self.SupportedBootModes + BootMode.SupArchList = self.CommonDefines.SupArchList + BootMode.Usage = self.CommonDefines.Usage + BootMode.FeatureFlag = self.CommonDefines.FeatureFlag + BootMode.HelpTextList = GetHelpTextList(self.HelpText) + + return BootMode + + def ToXml(self, BootMode, Key): + AttributeList = [['Usage', BootMode.Usage], + ['SupArchList', GetStringOfList(BootMode.SupArchList)], + ['FeatureFlag', BootMode.FeatureFlag], + ] + NodeList = [['SupportedBootModes', BootMode.Name]] + for Item in BootMode.HelpTextList: + Tmp = HelpTextXml() + NodeList.append(Tmp.ToXml(Item, 'HelpText')) + Root = CreateXmlElement('%s' % Key, '', NodeList, AttributeList) + + return Root + + def __str__(self): + Str = "SupportedBootModes = %s %s" % (self.SupportedBootModes, self.CommonDefines) + for Item in self.HelpText: + Str = Str + '\n\t' + str(Item) + return Str + +# EventXml +class EventXml(object): + def __init__(self): + self.EventType = '' + self.Name = '' + self.CommonDefines = CommonDefinesXml() + self.HelpText = [] + + def FromXml(self, Item, Key): + self.EventType = XmlAttribute(XmlNode(Item, '%s' % Key), 'EventType') + self.Name = XmlElement(Item, '%s' % Key) + self.CommonDefines.FromXml(Item, Key) + for HelpTextItem in XmlList(Item, '%s/HelpText' % Key): + HelpTextObj = HelpTextXml() + HelpTextObj.FromXml(HelpTextItem, '%s/HelpText' % Key) + self.HelpText.append(HelpTextObj) + + Event = ModuleEventClass() + Event.Type = self.EventType + Event.GuidCName = self.Name + Event.SupArchList = self.CommonDefines.SupArchList + Event.Usage = self.CommonDefines.Usage + Event.FeatureFlag = self.CommonDefines.FeatureFlag + Event.HelpTextList = GetHelpTextList(self.HelpText) + + return Event + + def ToXml(self, Event, Key): + AttributeList = [['EventType', Event.Type], + ['Usage', Event.Usage], + ['SupArchList', GetStringOfList(Event.SupArchList)], + ['FeatureFlag', Event.FeatureFlag], + ] + NodeList = [] + for Item in Event.HelpTextList: + Tmp = HelpTextXml() + NodeList.append(Tmp.ToXml(Item, 'HelpText')) + Root = CreateXmlElement('%s' % Key, Event.GuidCName, NodeList, AttributeList) + + return Root + + def __str__(self): + Str = "EventType = %s %s" % (self.EventType, self.CommonDefines) + for Item in self.HelpText: + Str = Str + '\n\t' + str(Item) + return Str + +# HobXml +class HobXml(object): + def __init__(self): + self.HobType = '' + self.Name = '' + self.CommonDefines = CommonDefinesXml() + self.HelpText = [] + + def FromXml(self, Item, Key): + self.HobType = XmlAttribute(XmlNode(Item, '%s' % Key), 'HobType') + self.Name = XmlElement(Item, '%s' % Key) + self.CommonDefines.FromXml(Item, Key) + for HelpTextItem in XmlList(Item, '%s/HelpText' % Key): + HelpTextObj = HelpTextXml() + HelpTextObj.FromXml(HelpTextItem, '%s/HelpText' % Key) + self.HelpText.append(HelpTextObj) + + Hob = ModuleHobClass() + Hob.Type = self.HobType + Hob.GuidCName = self.Name + Hob.SupArchList = self.CommonDefines.SupArchList + Hob.Usage = self.CommonDefines.Usage + Hob.FeatureFlag = self.CommonDefines.FeatureFlag + Hob.HelpTextList = GetHelpTextList(self.HelpText) + + return Hob + + def ToXml(self, Hob, Key): + AttributeList = [['EventType', Hob.Type], + ['Usage', Hob.Usage], + ['SupArchList', GetStringOfList(Hob.SupArchList)], + ['FeatureFlag', Hob.FeatureFlag], + ] + NodeList = [] + for Item in Hob.HelpTextList: + Tmp = HelpTextXml() + NodeList.append(Tmp.ToXml(Item, 'HelpText')) + Root = CreateXmlElement('%s' % Key, Hob.GuidCName, NodeList, AttributeList) + + return Root + + def __str__(self): + Str = "HobType = %s %s" % (self.HobType, self.CommonDefines) + for Item in self.HelpText: + Str = Str + '\n\t' + str(Item) + return Str + +# ModulePropertyXml +class ModulePropertyXml(object): + def __init__(self): + self.CommonDefines = CommonDefinesXml() + self.ModuleType = '' + self.Path = '' + self.PcdIsDriver = '' + self.UefiSpecificationVersion = '' + self.PiSpecificationVersion = '' + self.Specification = '' + self.SpecificationVersion = '' + self.BootModes = [] + self.Events = [] + self.HOBs = [] + + def FromXml(self, Item, Key, Header = None): + self.CommonDefines.FromXml(Item, Key) + self.ModuleType = XmlElement(Item, '%s/ModuleType' % Key) + self.Path = XmlElement(Item, '%s/Path' % Key) + self.PcdIsDriver = XmlElement(Item, '%s/PcdIsDriver' % Key) + self.UefiSpecificationVersion = XmlElement(Item, '%s/UefiSpecificationVersion' % Key) + self.PiSpecificationVersion = XmlElement(Item, '%s/PiSpecificationVersion' % Key) + self.Specification = XmlElement(Item, '%s/Specification' % Key) + self.SpecificationVersion = XmlAttribute(XmlNode(Item, '%s/Specification' % Key), 'Version') + for SubItem in XmlList(Item, '%s/BootMode' % Key): + A = BootModeXml() + BootMode = A.FromXml(SubItem, 'BootMode') + self.BootModes.append(BootMode) + for SubItem in XmlList(Item, '%s/Event' % Key): + A = EventXml() + Event = A.FromXml(SubItem, 'Event') + self.Events.append(Event) + for SubItem in XmlList(Item, '%s/HOB' % Key): + A = HobXml() + Hob = A.FromXml(SubItem, 'HOB') + self.HOBs.append(Hob) + + if Header == None: + Header = ModuleHeaderClass() + + Header.ModuleType = self.ModuleType + Header.SupArchList = self.CommonDefines.SupArchList + Header.SupModuleList = self.CommonDefines.SupModList + Header.CombinePath = self.Path + Header.PcdIsDriver = self.PcdIsDriver + Header.UefiSpecificationVersion = self.UefiSpecificationVersion + Header.PiSpecificationVersion = self.PiSpecificationVersion + + return Header, self.BootModes, self.Events, self.HOBs + + + def ToXml(self, Header, BootModes, Events, Hobs, Key): + AttributeList = [['SupArchList', GetStringOfList(Header.SupArchList)], + ['SupModList', GetStringOfList(Header.SupModuleList)], + ] + NodeList = [['ModuleType', Header.ModuleType], + ['Path', Header.CombinePath], + ['PcdIsDriver', Header.PcdIsDriver], + ['UefiSpecificationVersion', Header.UefiSpecificationVersion], + ['PiSpecificationVersion', Header.PiSpecificationVersion], + ] + for Item in BootModes: + Tmp = BootModeXml() + NodeList.append(Tmp.ToXml(Item, 'BootMode')) + for Item in Events: + Tmp = EventXml() + NodeList.append(Tmp.ToXml(Item, 'Event')) + for Item in Hobs: + Tmp = HobXml() + NodeList.append(Tmp.ToXml(Item, 'Hob')) + Root = CreateXmlElement('%s' % Key, '', NodeList, AttributeList) + + return Root + + def __str__(self): + Str = "ModuleType = %s Path = %s PcdIsDriver = %s UefiSpecificationVersion = %s PiSpecificationVersion = %s Specification = %s SpecificationVersion = %s %s" \ + % (self.ModuleType, self.Path, self.PcdIsDriver, self.UefiSpecificationVersion, self.PiSpecificationVersion, \ + self.Specification, self.SpecificationVersion, self.CommonDefines) + for Item in self.BootModes: + Str = Str + '\n\t' + str(Item) + for Item in self.Events: + Str = Str + '\n\t' + str(Item) + for Item in self.HOBs: + Str = Str + '\n\t' + str(Item) + return Str + +# SourceFileXml +class SourceFileXml(object): + def __init__(self): + self.SourceFile = '' + self.ToolChainFamily = '' + self.FileType = '' + self.CommonDefines = CommonDefinesXml() + + def FromXml(self, Item, Key): + self.ToolChainFamily = XmlAttribute(Item, 'Family') + self.FileType = XmlAttribute(Item, 'FileType') + self.SourceFile = XmlElement(Item, 'Filename') + self.CommonDefines.FromXml(Item, Key) + + SourceFile = ModuleSourceFileClass() + SourceFile.SourceFile = self.SourceFile + SourceFile.FileType = self.FileType + SourceFile.ToolChainFamily = self.ToolChainFamily + SourceFile.SupArchList = self.CommonDefines.SupArchList + SourceFile.FeatureFlag = self.CommonDefines.FeatureFlag + + return SourceFile + + def ToXml(self, SourceFile, Key): + AttributeList = [['SupArchList', GetStringOfList(SourceFile.SupArchList)], + ['Family', SourceFile.ToolChainFamily], + ['FileType', SourceFile.FileType], + ['FeatureFlag', SourceFile.FeatureFlag], + ] + Root = CreateXmlElement('%s' % Key, SourceFile.SourceFile, [], AttributeList) + + return Root + +# FilenameXml +class FilenameXml(object): + def __init__(self): + self.OS = '' + self.Family = '' + self.FileType = '' + self.Filename = '' + self.Executable = '' + self.CommonDefines = CommonDefinesXml() + + def FromXml(self, Item, Key): + self.OS = XmlAttribute(Item, 'OS') + self.Family = XmlAttribute(Item, 'Family') + self.FileType = XmlAttribute(Item, 'FileType') + self.Filename = XmlElement(Item, 'Filename') + self.Executable = XmlElement(Item, 'Executable') + self.CommonDefines.FromXml(Item, Key) + + Filename = FileClass() + Filename.Family = self.Family + Filename.FileType = self.FileType + Filename.Filename = self.Filename + Filename.Executable = self.Executable + Filename.SupArchList = self.CommonDefines.SupArchList + Filename.FeatureFlag = self.CommonDefines.FeatureFlag + + return Filename + + def ToXml(self, Filename, Key): + AttributeList = [['SupArchList', GetStringOfList(Filename.SupArchList)], + ['Family', Filename.Family], + ['FileType', Filename.FileType], + ['Executable', Filename.Executable], + ['FeatureFlag', Filename.FeatureFlag], + ] + NodeList = [['Filename', Filename.Filename], + ] + Root = CreateXmlElement('%s' % Key, '', NodeList, AttributeList) + + return Root + + def __str__(self): + return "OS = %s Family = %s FileType = %s Filename = %s Executable = %s %s" \ + % (self.OS, self.Family, self.FileType, self.Filename, self.Executable, self.CommonDefines) + +class BinaryFileXml(object): + def __init__(self): + self.Filenames = [] + self.PatchPcdValues = [] + self.PcdExValues = [] + self.LibraryInstances = [] + self.BuildFlags = [] + + def FromXml(self, Item, Key): + BinaryFile = ModuleBinaryFileClass() + for SubItem in XmlList(Item, '%s/Filename' % Key): + A = FilenameXml() + B = A.FromXml(SubItem, 'Filename') + BinaryFile.Filenames.append(B) + for SubItem in XmlList(Item, '%s/AsBuilt/PatchPcdValue' % Key): + A = PcdEntryXml() + B = A.FromXml(SubItem, 'PatchPcdValue') + BinaryFile.PatchPcdValues.append(B) + for SubItem in XmlList(Item, '%s/AsBuilt/PcdExValue' % Key): + A = PcdEntryXml() + B = A.FromXml(SubItem, 'PcdExValue') + BinaryFile.PatchPcdValues.append(B) + for SubItem in XmlList(Item, '%s/AsBuilt/LibraryInstances/GUID' % Key): + GUID = XmlElement(SubItem, 'GUID') + Version = XmlAttribute(XmlNode(SubItem, 'GUID'), 'Version') + BinaryFile.LibraryInstances.append([GUID, Version]) + for SubItem in XmlList(Item, '%s/AsBuilt/BuildFlags' % Key): + BinaryFile.BuildFlags.append(XmlElement(SubItem, 'BuildFlags')) + + return BinaryFile + + def ToXml(self, BinaryFile, Key): + NodeList = [] + for Item in BinaryFile.Filenames: + Tmp = FilenameXml() + NodeList.append(Tmp.ToXml(Item, 'Filename')) + AsBuiltNodeList = [] + for Item in BinaryFile.PatchPcdValues: + Tmp = PcdEntryXml() + AsBuiltNodeList.append(Tmp.ToXml(Item, 'PatchPcdValue')) + for Item in BinaryFile.PcdExValues: + Tmp = PcdEntryXml() + AsBuiltNodeList.append(Tmp.ToXml(Item, 'PcdExValue')) + LibNodeList = [] + for Item in BinaryFile.LibraryInstances: + LibNode = CreateXmlElement('GUID', Item[0], [], [['Version', Item[1]]]) + LibNodeList.append(LibNode) + if LibNodeList: + AsBuiltNodeList.append(CreateXmlElement('LibraryInstances', '', LibNodeList, [])) + for Item in BinaryFile.BuildFlags: + AsBuiltNodeList.append(CreateXmlElement('BuildFlags', Item, [], [])) + Element = CreateXmlElement('AsBuilt', '', AsBuiltNodeList, []) + NodeList.append(Element) + + Root = CreateXmlElement('%s' % Key, '', NodeList, []) + + return Root + + def __str__(self): + Str = "BinaryFiles:" + for Item in self.Filenames: + Str = Str + '\n\t' + str(Item) + for Item in self.PatchPcdValues: + Str = Str + '\n\t' + str(Item) + for Item in self.PcdExValues: + Str = Str + '\n\t' + str(Item) + for Item in self.LibraryInstances: + Str = Str + '\n\t' + str(Item) + for Item in self.BuildFlags: + Str = Str + '\n\t' + str(Item) + return Str + +# PackageXml +class PackageXml(object): + def __init__(self): + self.Description = '' + self.Guid = '' + self.Version = '' + self.CommonDefines = CommonDefinesXml() + + def FromXml(self, Item, Key): + self.Description = XmlElement(Item, '%s/Description' % Key) + self.Guid = XmlElement(Item, '%s/GUID' % Key) + self.Version = XmlAttribute(XmlNode(Item, '%s/GUID' % Key), 'Version') + self.CommonDefines.FromXml(XmlNode(Item, '%s' % Key), Key) + + PackageDependency = ModulePackageDependencyClass() + PackageDependency.FilePath = self.Description + PackageDependency.PackageGuid = self.Guid + PackageDependency.PackageVersion = self.Version + PackageDependency.FeatureFlag = self.CommonDefines.FeatureFlag + PackageDependency.SupArchList = self.CommonDefines.SupArchList + + return PackageDependency + + def ToXml(self, PackageDependency, Key): + AttributeList = [['SupArchList', GetStringOfList(PackageDependency.SupArchList)], + ['FeatureFlag', PackageDependency.FeatureFlag], + ] + Element1 = CreateXmlElement('GUID', PackageDependency.PackageGuid, [], [['Version', PackageDependency.PackageVersion]]) + NodeList = [['Description', PackageDependency.FilePath], + Element1, + ] + + Root = CreateXmlElement('%s' % Key, '', NodeList, AttributeList) + + return Root + + def __str__(self): + Str = "Description = %s Guid = %s Version = %s %s" \ + % (self.Description, self.Guid, self.Version, self.CommonDefines) + return Str + +# ExternXml +class ExternXml(object): + def __init__(self): + self.CommonDefines = CommonDefinesXml() + self.EntryPoint = '' + self.UnloadImage = '' + self.Constructor = '' + self.Destructor = '' + self.HelpText = [] + + def FromXml(self, Item, Key): + self.CommonDefines.FromXml(Item, Key) + self.EntryPoint = XmlElement(Item, '%s/EntryPoint' % Key) + self.UnloadImage = XmlElement(Item, '%s/UnloadImage' % Key) + self.Constructor = XmlElement(Item, '%s/Constructor' % Key) + self.Destructor = XmlElement(Item, '%s/Destructor' % Key) + for HelpTextItem in XmlList(Item, '%s/HelpText' % Key): + HelpTextObj = HelpTextXml() + HelpTextObj.FromXml(HelpTextItem, '%s/HelpText' % Key) + self.HelpText.append(HelpTextObj) + + Extern = ModuleExternClass() + Extern.EntryPoint = self.EntryPoint + Extern.UnloadImage = self.UnloadImage + Extern.Constructor = self.Constructor + Extern.Destructor = self.Destructor + Extern.SupArchList = self.CommonDefines.SupArchList + Extern.FeatureFlag = self.CommonDefines.FeatureFlag + Extern.HelpTextList = GetHelpTextList(self.HelpText) + + return Extern + + def ToXml(self, Extern, Key): + AttributeList = [['SupArchList', GetStringOfList(Extern.SupArchList)], + ['FeatureFlag', Extern.FeatureFlag], + ] + NodeList = [['EntryPoint', Extern.EntryPoint], + ['UnloadImage', Extern.UnloadImage], + ['Constructor', Extern.Constructor], + ['Destructor', Extern.Destructor], + ] + for Item in Extern.HelpTextList: + Tmp = HelpTextXml() + NodeList.append(Tmp.ToXml(Item, 'HelpText')) + + Root = CreateXmlElement('%s' % Key, '', NodeList, AttributeList) + + return Root + + def __str__(self): + Str = "EntryPoint = %s UnloadImage = %s Constructor = %s Destructor = %s %s" \ + % (self.EntryPoint, self.UnloadImage, self.Constructor, self.Destructor, self.CommonDefines) + for Item in self.HelpText: + Str = Str + '\n\t' + str(Item) + return Str +# DepexXml +class DepexXml(object): + def __init__(self): + self.Expression = '' + #self.HelpText = HelpTextXml() + self.HelpText = [] + + def FromXml(self, Item, Key): + self.Expression = XmlElement(Item, '%s/Expression' % Key) + for HelpTextItem in XmlList(Item, '%s/HelpText' % Key): + HelpTextObj = HelpTextXml() + HelpTextObj.FromXml(HelpTextItem, '%s/HelpText' % Key) + self.HelpText.append(HelpTextObj) + + Depex = ModuleDepexClass() + Depex.Depex = self.Expression + Depex.HelpTextList = GetHelpTextList(self.HelpText) + + return Depex + + def ToXml(self, Depex, Key): + AttributeList = [] + NodeList = [['Expression', Depex.Depex], + ] + for Item in Depex.HelpTextList: + Tmp = HelpTextXml() + NodeList.append(Tmp.ToXml(Item, 'HelpText')) + + Root = CreateXmlElement('%s' % Key, '', NodeList, AttributeList) + + return Root + + def __str__(self): + Str = "Expression = %s" % (self.Expression) + for Item in self.HelpText: + Str = Str + '\n\t' + str(Item) + return Str + +# PackageSurfaceAreaXml +class PackageSurfaceAreaXml(object): + def __init__(self): + self.Package = None + + def FromXml(self, Item, Key): + # Create a package object + Package = PackageClass() + + # Header + Tmp = PackageHeaderXml() + PackageHeader = Tmp.FromXml(XmlNode(Item, '/PackageSurfaceArea/Header'), 'Header') + Package.PackageHeader = PackageHeader + + # ClonedFrom + Tmp = ClonedFromXml() + ClonedFrom = Tmp.FromXml(XmlNode(Item, '/PackageSurfaceArea/ClonedFrom'), 'ClonedFrom') + if ClonedFrom: + Package.PackageHeader.ClonedFrom.append(ClonedFrom) + + # LibraryClass + for SubItem in XmlList(Item, '/PackageSurfaceArea/LibraryClassDeclarations/LibraryClass'): + Tmp = LibraryClassXml() + LibraryClass = Tmp.FromXml(SubItem, 'LibraryClass') + Package.LibraryClassDeclarations.append(LibraryClass) + + # IndustryStandardHeader + for SubItem in XmlList(Item, '/PackageSurfaceArea/IndustryStandardIncludes/IndustryStandardHeader'): + Tmp = IndustryStandardHeaderXml() + Include = Tmp.FromXml(SubItem, 'IndustryStandardHeader') + Package.IndustryStdHeaders.append(Include) + + # PackageHeader + for SubItem in XmlList(Item, '/PackageSurfaceArea/PackageIncludes/PackageHeader'): + Tmp = PackageIncludeHeaderXml() + Include = Tmp.FromXml(SubItem, 'PackageHeader') + Package.PackageIncludePkgHeaders.append(Include) + + # Guid + for SubItem in XmlList(Item, '/PackageSurfaceArea/GuidDeclarations/Entry'): + Tmp = GuidProtocolPpiXml() + GuidProtocolPpi = Tmp.FromXml(SubItem, 'Entry') + Package.GuidDeclarations.append(GuidProtocolPpi) + + # Protocol + for SubItem in XmlList(Item, '/PackageSurfaceArea/ProtocolDeclarations/Entry'): + Tmp = GuidProtocolPpiXml() + GuidProtocolPpi = Tmp.FromXml(SubItem, 'Entry') + Package.ProtocolDeclarations.append(GuidProtocolPpi) + + # Ppi + for SubItem in XmlList(Item, '/PackageSurfaceArea/PpiDeclarations/Entry'): + Tmp = GuidProtocolPpiXml() + GuidProtocolPpi = Tmp.FromXml(SubItem, 'Entry') + Package.PpiDeclarations.append(GuidProtocolPpi) + + # PcdEntry + for SubItem in XmlList(Item, '/PackageSurfaceArea/PcdDeclarations/PcdEntry'): + Tmp = PcdEntryXml() + PcdEntry = Tmp.FromXml(SubItem, 'PcdEntry') + Package.PcdDeclarations.append(PcdEntry) + + # PcdCheck + for SubItem in XmlList(Item, '/PackageSurfaceArea/PcdRelationshipChecks/PcdCheck'): + Tmp = PcdCheckXml() + PcdCheck = Tmp.FromXml(SubItem, 'PcdCheck') + Package.PcdChecks.append(PcdCheck) + + # MiscellaneousFile + Tmp = MiscellaneousFileXml() + Package.MiscFiles = Tmp.FromXml(XmlNode(Item, '/PackageSurfaceArea/MiscellaneousFiles'), 'MiscellaneousFiles') + + # UserExtensions + Tmp = UserExtensionsXml() + Package.UserExtensions = Tmp.FromXml(XmlNode(Item, '/PackageSurfaceArea/UserExtensions'), 'UserExtensions') + + # Modules + for SubItem in XmlList(Item, '/PackageSurfaceArea/Modules/ModuleSurfaceArea'): + Tmp = ModuleSurfaceAreaXml() + Module = Tmp.FromXml(SubItem, 'ModuleSurfaceArea') + Package.Modules[(Module.ModuleHeader.Guid, Module.ModuleHeader.Version, Module.ModuleHeader.CombinePath)] = Module + + self.Package = Package + return self.Package + + def ToXml(self, Package): + # Create PackageSurfaceArea node + DomPackage = minidom.Document().createElement('PackageSurfaceArea') + + # Header + Tmp = PackageHeaderXml() + DomPackage.appendChild(Tmp.ToXml(Package.PackageHeader, 'Header')) + + # ClonedFrom + Tmp = ClonedFromXml() + if Package.PackageHeader.ClonedFrom != []: + DomPackage.appendChild(Tmp.ToXml(Package.PackageHeader.ClonedFrom[0], 'ClonedFrom')) + + # LibraryClass + LibraryClassNode = CreateXmlElement('LibraryClassDeclarations', '', [], []) + for LibraryClass in Package.LibraryClassDeclarations: + Tmp = LibraryClassXml() + LibraryClassNode.appendChild(Tmp.ToXml(LibraryClass, 'LibraryClass')) + DomPackage.appendChild(LibraryClassNode) + + # IndustryStandardHeader + IndustryStandardHeaderNode = CreateXmlElement('IndustryStandardIncludes', '', [], []) + for Include in Package.IndustryStdHeaders: + Tmp = IndustryStandardHeaderXml() + IndustryStandardHeaderNode.appendChild(Tmp.ToXml(Include, 'IndustryStandardHeader')) + DomPackage.appendChild(IndustryStandardHeaderNode) + + # PackageHeader + PackageIncludeHeaderNode = CreateXmlElement('PackageIncludes', '', [], []) + for Include in Package.PackageIncludePkgHeaders: + Tmp = PackageIncludeHeaderXml() + PackageIncludeHeaderNode.appendChild(Tmp.ToXml(Include, 'PackageHeader')) + DomPackage.appendChild(PackageIncludeHeaderNode) + + # Guid + GuidProtocolPpiNode = CreateXmlElement('GuidDeclarations', '', [], []) + for GuidProtocolPpi in Package.GuidDeclarations: + Tmp = GuidProtocolPpiXml() + GuidProtocolPpiNode.appendChild(Tmp.ToXml(GuidProtocolPpi, 'Entry')) + DomPackage.appendChild(GuidProtocolPpiNode) + + # Protocol + GuidProtocolPpiNode = CreateXmlElement('ProtocolDeclarations', '', [], []) + for GuidProtocolPpi in Package.ProtocolDeclarations: + Tmp = GuidProtocolPpiXml() + GuidProtocolPpiNode.appendChild(Tmp.ToXml(GuidProtocolPpi, 'Entry')) + DomPackage.appendChild(GuidProtocolPpiNode) + + # Ppi + GuidProtocolPpiNode = CreateXmlElement('PpiDeclarations', '', [], []) + for GuidProtocolPpi in Package.PpiDeclarations: + Tmp = GuidProtocolPpiXml() + GuidProtocolPpiNode.appendChild(Tmp.ToXml(GuidProtocolPpi, 'Entry')) + DomPackage.appendChild(GuidProtocolPpiNode) + + # PcdEntry + PcdEntryNode = CreateXmlElement('PcdDeclarations', '', [], []) + for PcdEntry in Package.PcdDeclarations: + Tmp = PcdEntryXml() + PcdEntryNode.appendChild(Tmp.ToXml(PcdEntry, 'PcdEntry')) + DomPackage.appendChild(PcdEntryNode) + + # PcdCheck + PcdCheckNode = CreateXmlElement('PcdRelationshipChecks', '', [], []) + for PcdCheck in Package.PcdChecks: + Tmp = PcdCheckXml() + PcdCheckNode.appendChild(Tmp.ToXml(PcdCheck, 'PcdCheck')) + DomPackage.appendChild(PcdCheckNode) + + # MiscellaneousFile + Tmp = MiscellaneousFileXml() + DomPackage.appendChild(Tmp.ToXml(Package.MiscFiles, 'MiscellaneousFiles')) + + # UserExtensions + Tmp = UserExtensionsXml() + DomPackage.appendChild(Tmp.ToXml(Package.UserExtensions, 'UserExtensions')) + + # Modules + ModuleNode = CreateXmlElement('Modules', '', [], []) + for Module in Package.Modules.values(): + Tmp = ModuleSurfaceAreaXml() + ModuleNode.appendChild(Tmp.ToXml(Module)) + DomPackage.appendChild(ModuleNode) + + return DomPackage + +# ModuleXml +class ModuleSurfaceAreaXml(object): + def __init__(self): + self.Module = None + + def FromXml(self, Item, Key): + # Create a package object + Module = ModuleClass() + + # Header + Tmp = HeaderXml() + ModuleHeader = Tmp.FromXml(XmlNode(Item, '/ModuleSurfaceArea/Header'), 'Header') + Module.ModuleHeader = ModuleHeader + + # ModuleProperties + Tmp = ModulePropertyXml() + (Header, BootModes, Events, HOBs) = Tmp.FromXml(XmlNode(Item, '/ModuleSurfaceArea/ModuleProperties'), 'ModuleProperties', ModuleHeader) + Module.ModuleHeader = Header + Module.BootModes = BootModes + Module.Events = Events + Module.Hobs = HOBs + + # ClonedFrom + Tmp = ClonedFromXml() + ClonedFrom = Tmp.FromXml(XmlNode(Item, '/ModuleSurfaceArea/ClonedFrom'), 'ClonedFrom') + if ClonedFrom: + Module.ModuleHeader.ClonedFrom.append(ClonedFrom) + + # LibraryClass + #LibraryClassNode = CreateXmlElement('LibraryClassDefinitions', '', [], []) + for SubItem in XmlList(Item, '/ModuleSurfaceArea/LibraryClassDefinitions/LibraryClass'): + Tmp = LibraryClassXml() + LibraryClass = Tmp.FromXml(SubItem, 'LibraryClass') + Module.LibraryClasses.append(LibraryClass) + + # SourceFile + #SourceFileNode = CreateXmlElement('SourceFiles', '', [], []) + for SubItem in XmlList(Item, '/ModuleSurfaceArea/SourceFiles/Filename'): + Tmp = SourceFileXml() + SourceFile = Tmp.FromXml(SubItem, 'Filename') + Module.Sources.append(SourceFile) + + # BinaryFile + #BinaryFileNode = CreateXmlElement('BinaryFiles', '', [], []) + for SubItem in XmlList(Item, '/ModuleSurfaceArea/BinaryFiles/BinaryFile'): + Tmp = BinaryFileXml() + BinaryFile = Tmp.FromXml(SubItem, 'BinaryFile') + Module.Binaries.append(BinaryFile) + + # PackageDependencies + #PackageDependencyNode = CreateXmlElement('PackageDependencies', '', [], []) + for SubItem in XmlList(Item, '/ModuleSurfaceArea/PackageDependencies/Package'): + Tmp = PackageXml() + PackageDependency = Tmp.FromXml(SubItem, 'Package') + Module.PackageDependencies.append(PackageDependency) + + # Guid + #GuidProtocolPpiNode = CreateXmlElement('Guids', '', [], []) + for SubItem in XmlList(Item, '/ModuleSurfaceArea/Guids/GuidCName'): + Tmp = GuidProtocolPpiXml() + GuidProtocolPpi = Tmp.FromXml(SubItem, 'GuidCName') + Module.Guids.append(GuidProtocolPpi) + + # Protocol + #GuidProtocolPpiNode = CreateXmlElement('Protocols', '', [], []) + for SubItem in XmlList(Item, '/ModuleSurfaceArea/Protocols/Protocol'): + Tmp = GuidProtocolPpiXml() + GuidProtocolPpi = Tmp.FromXml(SubItem, 'Protocol') + Module.Protocols.append(GuidProtocolPpi) + + # Ppi + #GuidProtocolPpiNode = CreateXmlElement('PPIs', '', [], []) + for SubItem in XmlList(Item, '/ModuleSurfaceArea/PPIs/Ppi'): + Tmp = GuidProtocolPpiXml() + GuidProtocolPpi = Tmp.FromXml(SubItem, 'Ppi') + Module.Ppis.append(GuidProtocolPpi) + + # Extern + #ExternNode = CreateXmlElement('Externs', '', [], []) + for SubItem in XmlList(Item, '/ModuleSurfaceArea/Externs/Extern'): + Tmp = ExternXml() + Extern = Tmp.FromXml(SubItem, 'Extern') + Module.Externs.append(Extern) + + # PcdCoded + #PcdEntryNode = CreateXmlElement('PcdCoded', '', [], []) + for SubItem in XmlList(Item, '/ModuleSurfaceArea/PcdCoded/PcdEntry'): + Tmp = PcdEntryXml() + PcdEntry = Tmp.FromXml(SubItem, 'PcdEntry') + Module.PcdCodes.append(PcdEntry) + + # PeiDepex + #DepexNode = CreateXmlElement('PeiDepex', '', [], []) + Tmp = DepexXml() + Module.PeiDepex = Tmp.FromXml(XmlNode(Item, '/ModuleSurfaceArea/PeiDepex'), 'PeiDepex') + + # DxeDepex + #DepexNode = CreateXmlElement('DxeDepex', '', [], []) + Tmp = DepexXml() + Module.DxeDepex = Tmp.FromXml(XmlNode(Item, '/ModuleSurfaceArea/DxeDepex'), 'DxeDepex') + + # SmmDepex + #DepexNode = CreateXmlElement('SmmDepex', '', [], []) + Tmp = DepexXml() + Module.SmmDepex = Tmp.FromXml(XmlNode(Item, '/ModuleSurfaceArea/DxeDepex'), 'SmmDepex') + + # MiscellaneousFile + Tmp = MiscellaneousFileXml() + Module.MiscFiles = Tmp.FromXml(XmlNode(Item, '/ModuleSurfaceArea/MiscellaneousFiles'), 'MiscellaneousFiles') + + # UserExtensions + Tmp = UserExtensionsXml() + Module.UserExtensions = Tmp.FromXml(XmlNode(Item, '/ModuleSurfaceArea/UserExtensions'), 'UserExtensions') + + # return the module object + self.Module = Module + return self.Module + + def ToXml(self, Module): + # Create root node of module surface area + DomModule = minidom.Document().createElement('ModuleSurfaceArea') + + # Header + Tmp = HeaderXml() + DomModule.appendChild(Tmp.ToXml(Module.ModuleHeader, 'Header')) + + # ModuleProperties + Tmp = ModulePropertyXml() + DomModule.appendChild(Tmp.ToXml(Module.ModuleHeader, Module.BootModes, Module.Events, Module.Hobs, 'ModuleProperties')) + + # ClonedFrom + Tmp = ClonedFromXml() + if Module.ModuleHeader.ClonedFrom != []: + DomModule.appendChild(Tmp.ToXml(Module.ModuleHeader.ClonedFrom[0], 'ClonedFrom')) + + # LibraryClass + LibraryClassNode = CreateXmlElement('LibraryClassDefinitions', '', [], []) + for LibraryClass in Module.LibraryClasses: + Tmp = LibraryClassXml() + LibraryClassNode.appendChild(Tmp.ToXml(LibraryClass, 'LibraryClass')) + DomModule.appendChild(LibraryClassNode) + + # SourceFile + SourceFileNode = CreateXmlElement('SourceFiles', '', [], []) + for SourceFile in Module.Sources: + Tmp = SourceFileXml() + SourceFileNode.appendChild(Tmp.ToXml(SourceFile, 'Filename')) + DomModule.appendChild(SourceFileNode) + + # BinaryFile + BinaryFileNode = CreateXmlElement('BinaryFiles', '', [], []) + for BinaryFile in Module.Binaries: + Tmp = BinaryFileXml() + BinaryFileNode.appendChild(Tmp.ToXml(BinaryFile, 'BinaryFile')) + DomModule.appendChild(BinaryFileNode) + + # PackageDependencies + PackageDependencyNode = CreateXmlElement('PackageDependencies', '', [], []) + for PackageDependency in Module.PackageDependencies: + Tmp = PackageXml() + PackageDependencyNode.appendChild(Tmp.ToXml(PackageDependency, 'Package')) + DomModule.appendChild(PackageDependencyNode) + + # Guid + GuidProtocolPpiNode = CreateXmlElement('Guids', '', [], []) + for GuidProtocolPpi in Module.Guids: + Tmp = GuidProtocolPpiXml() + GuidProtocolPpiNode.appendChild(Tmp.ToXml(GuidProtocolPpi, 'GuidCName')) + DomModule.appendChild(GuidProtocolPpiNode) + + # Protocol + GuidProtocolPpiNode = CreateXmlElement('Protocols', '', [], []) + for GuidProtocolPpi in Module.Protocols: + Tmp = GuidProtocolPpiXml() + GuidProtocolPpiNode.appendChild(Tmp.ToXml(GuidProtocolPpi, 'Protocol')) + DomModule.appendChild(GuidProtocolPpiNode) + + # Ppi + GuidProtocolPpiNode = CreateXmlElement('PPIs', '', [], []) + for GuidProtocolPpi in Module.Ppis: + Tmp = GuidProtocolPpiXml() + GuidProtocolPpiNode.appendChild(Tmp.ToXml(GuidProtocolPpi, 'Ppi')) + DomModule.appendChild(GuidProtocolPpiNode) + + # Extern + ExternNode = CreateXmlElement('Externs', '', [], []) + for Extern in Module.Externs: + Tmp = ExternXml() + ExternNode.appendChild(Tmp.ToXml(Extern, 'Extern')) + DomModule.appendChild(ExternNode) + + # PcdCoded + PcdEntryNode = CreateXmlElement('PcdCoded', '', [], []) + for PcdEntry in Module.PcdCodes: + Tmp = PcdEntryXml() + PcdEntryNode.appendChild(Tmp.ToXml(PcdEntry, 'PcdEntry')) + DomModule.appendChild(PcdEntryNode) + + # PeiDepex + if Module.PeiDepex: + DepexNode = CreateXmlElement('PeiDepex', '', [], []) + Tmp = DepexXml() + DomModule.appendChild(Tmp.ToXml(Module.PeiDepex, 'PeiDepex')) + + # DxeDepex + if Module.DxeDepex: + DepexNode = CreateXmlElement('DxeDepex', '', [], []) + Tmp = DepexXml() + DomModule.appendChild(Tmp.ToXml(Module.DxeDepex, 'DxeDepex')) + + # SmmDepex + if Module.SmmDepex: + DepexNode = CreateXmlElement('SmmDepex', '', [], []) + Tmp = DepexXml() + DomModule.appendChild(Tmp.ToXml(Module.SmmDepex, 'SmmDepex')) + + # MiscellaneousFile + Tmp = MiscellaneousFileXml() + DomModule.appendChild(Tmp.ToXml(Module.MiscFiles, 'MiscellaneousFiles')) + + # UserExtensions + Tmp = UserExtensionsXml() + DomModule.appendChild(Tmp.ToXml(Module.UserExtensions, 'UserExtensions')) + + return DomModule + +# DistributionPackageXml +class DistributionPackageXml(object): + def __init__(self): + self.Dp = DistributionPackageClass() + + def FromXml(self, Filename = None): + if Filename != None: + self.Dp = DistributionPackageClass() + + # Load to XML + self.Pkg = XmlParseFile(Filename) + + # Parse Header information + Tmp = DistributionPackageHeaderXml() + DistributionPackageHeader = Tmp.FromXml(XmlNode(self.Pkg, '/DistributionPackage/DistributionHeader'), 'DistributionHeader') + self.Dp.Header = DistributionPackageHeader + + # Parse each PackageSurfaceArea + for Item in XmlList(self.Pkg, '/DistributionPackage/PackageSurfaceArea'): + Psa = PackageSurfaceAreaXml() + Package = Psa.FromXml(Item, 'PackageSurfaceArea') + self.Dp.PackageSurfaceArea[(Package.PackageHeader.Guid, Package.PackageHeader.Version, Package.PackageHeader.CombinePath)] = Package + + # Parse each ModuleSurfaceArea + for Item in XmlList(self.Pkg, '/DistributionPackage/ModuleSurfaceArea'): + Msa = ModuleSurfaceAreaXml() + Module = Msa.FromXml(Item, 'ModuleSurfaceArea') + self.Dp.ModuleSurfaceArea[(Module.ModuleHeader.Guid, Module.ModuleHeader.Version, Module.ModuleHeader.CombinePath)] = Module + + # Parse Tools + Tmp = MiscellaneousFileXml() + self.Dp.Tools = Tmp.FromXml2(XmlNode(self.Pkg, '/DistributionPackage/Tools'), 'Tools') + + # Parse MiscFiles + Tmp = MiscellaneousFileXml() + self.Dp.MiscellaneousFiles = Tmp.FromXml2(XmlNode(self.Pkg, '/DistributionPackage/MiscellaneousFiles'), 'MiscellaneousFiles') + + return self.Dp + + def ToXml(self, Dp): + if Dp != None: + # Parse DistributionPackageHeader + Attrs = [['xmlns', 'http://www.uefi.org/2008/2.1'], + ['xmlns:xsi', 'http:/www.w3.org/2001/XMLSchema-instance'], + ] + Root = CreateXmlElement('DistributionPackage', '', [], Attrs) + + Tmp = DistributionPackageHeaderXml() + Root.appendChild(Tmp.ToXml(Dp.Header, 'DistributionHeader')) + + # Parse each PackageSurfaceArea + for Package in Dp.PackageSurfaceArea.values(): + Psa = PackageSurfaceAreaXml() + DomPackage = Psa.ToXml(Package) + Root.appendChild(DomPackage) + + # Parse each ModuleSurfaceArea + for Module in Dp.ModuleSurfaceArea.values(): + Msa = ModuleSurfaceAreaXml() + DomModule = Msa.ToXml(Module) + Root.appendChild(DomModule) + + # Parse Tools + Tmp = MiscellaneousFileXml() + #Tools = Tmp.FromXml2(XmlNode(self.Pkg, '/DistributionPackage/Tools'), 'Tools') + Root.appendChild(Tmp.ToXml2(Dp.Tools, 'Tools')) + + # Parse MiscFiles + Tmp = MiscellaneousFileXml() + #Tools = Tmp.FromXml2(XmlNode(self.Pkg, '/DistributionPackage/MiscellaneousFiles'), 'MiscellaneousFiles') + Root.appendChild(Tmp.ToXml2(Dp.MiscellaneousFiles, 'MiscellaneousFiles')) + + return Root.toprettyxml(indent = ' ') + + return '' + +if __name__ == '__main__': + M = DistributionPackageXml() + M.FromXml('C:\Test.xml') + print M.ToXml(M.Dp) + \ No newline at end of file diff --git a/BaseTools/Source/Python/Common/XmlRoutines.py b/BaseTools/Source/Python/Common/XmlRoutines.py new file mode 100644 index 0000000000..e5fedae83d --- /dev/null +++ b/BaseTools/Source/Python/Common/XmlRoutines.py @@ -0,0 +1,228 @@ +## @file +# This is an XML API that uses a syntax similar to XPath, but it is written in +# standard python so that no extra python packages are required to use it. +# +# Copyright (c) 2007, 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. +# + +## +# Import Modules +# +import xml.dom.minidom + +## Create a element of XML +# +# @param Name +# @param String +# @param NodeList +# @param AttributeList +# +# @revel Element +# +def CreateXmlElement(Name, String, NodeList, AttributeList): + Doc = xml.dom.minidom.Document() + Element = Doc.createElement(Name) + if String != '' and String != None: + Element.appendChild(Doc.createTextNode(String)) + + for Item in NodeList: + if type(Item) == type([]): + Key = Item[0] + Value = Item[1] + if Key != '' and Key != None and Value != '' and Value != None: + Node = Doc.createElement(Key) + Node.appendChild(Doc.createTextNode(Value)) + Element.appendChild(Node) + else: + Element.appendChild(Item) + for Item in AttributeList: + Key = Item[0] + Value = Item[1] + if Key != '' and Key != None and Value != '' and Value != None: + Element.setAttribute(Key, Value) + + return Element + +## Get a list of XML nodes using XPath style syntax. +# +# Return a list of XML DOM nodes from the root Dom specified by XPath String. +# If the input Dom or String is not valid, then an empty list is returned. +# +# @param Dom The root XML DOM node. +# @param String A XPath style path. +# +# @revel Nodes A list of XML nodes matching XPath style Sting. +# +def XmlList(Dom, String): + if String == None or String == "" or Dom == None or Dom == "": + return [] + if Dom.nodeType == Dom.DOCUMENT_NODE: + Dom = Dom.documentElement + if String[0] == "/": + String = String[1:] + TagList = String.split('/') + Nodes = [Dom] + Index = 0 + End = len(TagList) - 1 + while Index <= End: + ChildNodes = [] + for Node in Nodes: + if Node.nodeType == Node.ELEMENT_NODE and Node.tagName == TagList[Index]: + if Index < End: + ChildNodes.extend(Node.childNodes) + else: + ChildNodes.append(Node) + Nodes = ChildNodes + ChildNodes = [] + Index += 1 + + return Nodes + + +## Get a single XML node using XPath style syntax. +# +# Return a single XML DOM node from the root Dom specified by XPath String. +# If the input Dom or String is not valid, then an empty string is returned. +# +# @param Dom The root XML DOM node. +# @param String A XPath style path. +# +# @revel Node A single XML node matching XPath style Sting. +# +def XmlNode(Dom, String): + if String == None or String == "" or Dom == None or Dom == "": + return "" + if Dom.nodeType == Dom.DOCUMENT_NODE: + Dom = Dom.documentElement + if String[0] == "/": + String = String[1:] + TagList = String.split('/') + Index = 0 + End = len(TagList) - 1 + ChildNodes = [Dom] + while Index <= End: + for Node in ChildNodes: + if Node.nodeType == Node.ELEMENT_NODE and Node.tagName == TagList[Index]: + if Index < End: + ChildNodes = Node.childNodes + else: + return Node + break + Index += 1 + return "" + + +## Get a single XML element using XPath style syntax. +# +# Return a single XML element from the root Dom specified by XPath String. +# If the input Dom or String is not valid, then an empty string is returned. +# +# @param Dom The root XML DOM object. +# @param Strin A XPath style path. +# +# @revel Element An XML element matching XPath style Sting. +# +def XmlElement(Dom, String): + try: + return XmlNode(Dom, String).firstChild.data.strip() + except: + return "" + + +## Get a single XML element of the current node. +# +# Return a single XML element specified by the current root Dom. +# If the input Dom is not valid, then an empty string is returned. +# +# @param Dom The root XML DOM object. +# +# @revel Element An XML element in current root Dom. +# +def XmlElementData(Dom): + try: + return Dom.firstChild.data.strip() + except: + return "" + + +## Get a list of XML elements using XPath style syntax. +# +# Return a list of XML elements from the root Dom specified by XPath String. +# If the input Dom or String is not valid, then an empty list is returned. +# +# @param Dom The root XML DOM object. +# @param String A XPath style path. +# +# @revel Elements A list of XML elements matching XPath style Sting. +# +def XmlElementList(Dom, String): + return map(XmlElementData, XmlList(Dom, String)) + + +## Get the XML attribute of the current node. +# +# Return a single XML attribute named Attribute from the current root Dom. +# If the input Dom or Attribute is not valid, then an empty string is returned. +# +# @param Dom The root XML DOM object. +# @param Attribute The name of Attribute. +# +# @revel Element A single XML element matching XPath style Sting. +# +def XmlAttribute(Dom, Attribute): + try: + return Dom.getAttribute(Attribute).strip() + except: + return '' + + +## Get the XML node name of the current node. +# +# Return a single XML node name from the current root Dom. +# If the input Dom is not valid, then an empty string is returned. +# +# @param Dom The root XML DOM object. +# +# @revel Element A single XML element matching XPath style Sting. +# +def XmlNodeName(Dom): + try: + return Dom.nodeName.strip() + except: + return '' + +## Parse an XML file. +# +# Parse the input XML file named FileName and return a XML DOM it stands for. +# If the input File is not a valid XML file, then an empty string is returned. +# +# @param FileName The XML file name. +# +# @revel Dom The Dom object achieved from the XML file. +# +def XmlParseFile(FileName): + try: + XmlFile = open(FileName) + Dom = xml.dom.minidom.parse(XmlFile) + XmlFile.close() + return Dom + except Exception, X: + print X + return "" + +# This acts like the main() function for the script, unless it is 'import'ed +# into another script. +if __name__ == '__main__': + # Nothing to do here. Could do some unit tests. + A = CreateXmlElement('AAA', 'CCC', [['AAA', '111'], ['BBB', '222']], [['A', '1'], ['B', '2']]) + B = CreateXmlElement('ZZZ', 'CCC', [['XXX', '111'], ['YYY', '222']], [['A', '1'], ['B', '2']]) + C = CreateXmlList('DDD', 'EEE', [A, B], ['FFF', 'GGG']) + print C.toprettyxml(indent = " ") + pass diff --git a/BaseTools/Source/Python/Common/__init__.py b/BaseTools/Source/Python/Common/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/BaseTools/Source/Python/CommonDataClass/CommonClass.py b/BaseTools/Source/Python/CommonDataClass/CommonClass.py new file mode 100644 index 0000000000..763550fe47 --- /dev/null +++ b/BaseTools/Source/Python/CommonDataClass/CommonClass.py @@ -0,0 +1,473 @@ +## @file +# This file is used to define common items of class object +# +# Copyright (c) 2007, 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. + + +# +# Generate help text +# +def GenerateHelpText(Text, Lang): + if Text: + Ht = HelpTextClass() + Ht.Lang = Lang + Ht.String = Text + + return Ht + + return None + +## CommonClass +# +# This class defined common items used in Module/Platform/Package files +# +# @param object: Inherited from object class +# @param Usage: Input value for Usage, default is [] +# @param FeatureFlag: Input value for FeatureFalg, default is '' +# @param SupArchList: Input value for SupArchList, default is [] +# @param HelpText: Input value for HelpText, default is '' +# +# @var Usage: To store value for Usage, selection scope is in below list +# ALWAYS_CONSUMED | SOMETIMES_CONSUMED | ALWAYS_PRODUCED | SOMETIMES_PRODUCED | TO_START | BY_START | PRIVATE +# @var FeatureFlag: To store value for FeatureFlag +# @var SupArchList: To store value for SupArchList, selection scope is in below list +# EBC | IA32 | X64 | IPF | ARM | PPC +# @var HelpText: To store value for HelpText +# +class CommonClass(object): + def __init__(self, Usage = None, FeatureFlag = '', SupArchList = None, HelpText = ''): + self.Usage = Usage + if self.Usage == None: + self.Usage = [] + self.FeatureFlag = FeatureFlag + self.SupArchList = SupArchList + if self.SupArchList == None: + self.SupArchList = [] + self.HelpText = HelpText + self.HelpTextList = [] + +## CommonClass +# +# This class defined common items used in Module/Platform/Package files +# +# @param object: Inherited from object class +# +# @var Abstract: To store value for Abstract +# @var Description: To store value for Description +# @var Copyright: To store value for Copyright +# @var License: To store value for License +# @var Specification: To store value for Specification +# +class CommonHeaderClass(object): + def __init__(self): + self.Abstract = '' + self.Description = '' + self.Copyright = '' + self.License = '' + self.Specification = {} + +## HelpTextClass +# +# This class defined HelpText item used in PKG file +# +# @param object: Inherited from object class +# +# @var Lang: To store value for Lang +# @var String: To store value for String +# +class HelpTextClass(object): + def __init__(self): + self.Lang = '' + self.String = '' + +## DefineClass +# +# This class defined item DEFINE used in Module/Platform/Package files +# +# @param object: Inherited from object class +# +# @var Define: To store value for Define, it is a set structure as +# { (DefineName, Arch) : DefineValue, ... } +# +class DefineClass(object): + def __init__(self): + self.Define = {} + +## ClonedRecordClass +# +# This class defined ClonedRecord items used in Module/Platform/Package files +# +# @param object: Inherited from object class +# +# @var Id: To store value for Id +# @var FarGuid: To store value for FarGuid +# @var PackageGuid: To store value for PackageGuid +# @var PackageVersion: To store value for PackageVersion +# @var ModuleGuid: To store value for ModuleGuid +# @var ModuleVersion: To store value for ModuleVersion +# +class ClonedRecordClass(object): + def __init__(self): + self.Id = 0 + self.FarGuid = '' + self.PackageGuid = '' + self.PackageVersion = '' + self.ModuleGuid = '' + self.ModuleVersion = '' + +## IdentificationClass +# +# This class defined Identification items used in Module/Platform/Package files +# +# @param object: Inherited from object class +# +# @var Name: To store value for Name +# ModuleName(Inf) / PackageName(Dec) / PlatformName(Dsc) +# @var Guid: To store value for Guid +# @var Version: To store value for Version +# @var FileName: To store value for FileName +# @var FullPath: To store value for FullPath +# +class IdentificationClass(object): + def __init__(self): + self.Name = '' + self.BaseName = '' + self.Guid = '' + self.Version = '' + self.FileName = '' + self.FullPath = '' + self.RelaPath = '' + self.PackagePath = '' + self.ModulePath = '' + self.CombinePath = '' + +## IncludeStatementClass +# +# This class defined IncludeFiles item used in Module/Platform/Package files +# +# @param object: Inherited from object class +# +# @var IncludeFiles: To store value for IncludeFiles +# It is a set structure as { IncludeFile : [Arch1, Arch2, ...], ... } +# +class IncludeStatementClass(object): + def __init__(self): + self.IncludeFiles = {} + +## GuidProtocolPpiCommonClass +# +# This class defined Guid, Protocol and Ppi like items used in Module/Platform/Package files +# +# @param CommonClass: Inherited from CommonClass class +# +# @var Name: To store value for Name +# @var CName: To store value for CName +# @var Guid: To store value for Guid +# @var Notify: To store value for Notify +# @var GuidTypeList: To store value for GuidTypeList, selection scope is in below list +# DATA_HUB_RECORD | EFI_EVENT | EFI_SYSTEM_CONFIGURATION_TABLE | EFI_VARIABLE | GUID | HII_PACKAGE_LIST | HOB | TOKEN_SPACE_GUID +# @var SupModuleList: To store value for SupModuleList, selection scope is in below list +# BASE | SEC | PEI_CORE | PEIM | DXE_CORE | DXE_DRIVER | DXE_RUNTIME_DRIVER | DXE_SAL_DRIVER | DXE_SMM_DRIVER | UEFI_DRIVER | UEFI_APPLICATION | USER_DEFINED +# +class GuidProtocolPpiCommonClass(CommonClass): + def __init__(self): + self.Name = '' + self.CName = '' + self.Guid = '' + self.VariableName = '' + self.Notify = False + self.GuidTypeList = [] + self.GuidTypeLists = [] + self.SupModuleList = [] + CommonClass.__init__(self) + +## LibraryClassClass +# +# This class defined Library item used in Module/Platform/Package files +# +# @param CommonClass: Inherited from CommonClass class +# @param DefineClass: Inherited from DefineClass class +# +# @var LibraryClass: To store value for LibraryClass +# @var IncludeHeader: To store value for IncludeHeader +# @var RecommendedInstanceVersion: To store value for RecommendedInstanceVersion +# @var RecommendedInstanceGuid: To store value for RecommendedInstanceGuid +# @var RecommendedInstance: To store value for RecommendedInstance, selection scope is in below list +# DATA_HUB_RECORD | EFI_EVENT | EFI_SYSTEM_CONFIGURATION_TABLE | EFI_VARIABLE | GUID | HII_PACKAGE_LIST | HOB | TOKEN_SPACE_GUID +# @var SupModuleList: To store value for SupModuleList, selection scope is in below list +# BASE | SEC | PEI_CORE | PEIM | DXE_CORE | DXE_DRIVER | DXE_RUNTIME_DRIVER | DXE_SAL_DRIVER | DXE_SMM_DRIVER | UEFI_DRIVER | UEFI_APPLICATION | USER_DEFINED +# +class LibraryClassClass(CommonClass, DefineClass): + def __init__(self): + self.LibraryClass = '' + self.IncludeHeader = '' + self.RecommendedInstanceVersion = '' + self.RecommendedInstanceGuid = '' + self.RecommendedInstance = '' + self.SupModuleList = [] + CommonClass.__init__(self) + DefineClass.__init__(self) + +## GuidClass +# +# This class defined Guid item used in Module/Platform/Package files +# +# @param GuidProtocolPpiCommonClass: Inherited from GuidProtocolPpiCommonClass class +# +class GuidClass(GuidProtocolPpiCommonClass): + def __init__(self): + GuidProtocolPpiCommonClass.__init__(self) + +## ProtocolClass +# +# This class defined Protocol item used in Module/Platform/Package files +# +# @param GuidProtocolPpiCommonClass: Inherited from GuidProtocolPpiCommonClass class +# +class ProtocolClass(GuidProtocolPpiCommonClass): + def __init__(self): + GuidProtocolPpiCommonClass.__init__(self) + +## PpiClass +# +# This class defined Ppi item used in Module/Platform/Package files +# +# @param GuidProtocolPpiCommonClass: Inherited from GuidProtocolPpiCommonClass class +# +class PpiClass(GuidProtocolPpiCommonClass): + def __init__(self): + GuidProtocolPpiCommonClass.__init__(self) + +## SkuInfoClass +# +# This class defined SkuInfo item used in Module/Platform/Package files +# +# @param object: Inherited from object class +# @param SkuIdName: Input value for SkuIdName, default is '' +# @param SkuId: Input value for SkuId, default is '' +# @param VariableName: Input value for VariableName, default is '' +# @param VariableGuid: Input value for VariableGuid, default is '' +# @param VariableOffset: Input value for VariableOffset, default is '' +# @param HiiDefaultValue: Input value for HiiDefaultValue, default is '' +# @param VpdOffset: Input value for VpdOffset, default is '' +# @param DefaultValue: Input value for DefaultValue, default is '' +# +# @var SkuIdName: To store value for SkuIdName +# @var SkuId: To store value for SkuId +# @var VariableName: To store value for VariableName +# @var VariableGuid: To store value for VariableGuid +# @var VariableOffset: To store value for VariableOffset +# @var HiiDefaultValue: To store value for HiiDefaultValue +# @var VpdOffset: To store value for VpdOffset +# @var DefaultValue: To store value for DefaultValue +# +class SkuInfoClass(object): + def __init__(self, SkuIdName = '', SkuId = '', VariableName = '', VariableGuid = '', VariableOffset = '', + HiiDefaultValue = '', VpdOffset = '', DefaultValue = '', VariableGuidValue = ''): + self.SkuIdName = SkuIdName + self.SkuId = SkuId + + # + # Used by Hii + # + self.VariableName = VariableName + self.VariableGuid = VariableGuid + self.VariableGuidValue = VariableGuidValue + self.VariableOffset = VariableOffset + self.HiiDefaultValue = HiiDefaultValue + + # + # Used by Vpd + # + self.VpdOffset = VpdOffset + + # + # Used by Default + # + self.DefaultValue = DefaultValue + + ## Convert the class to a string + # + # Convert each member of the class to string + # Organize to a signle line format string + # + # @retval Rtn Formatted String + # + def __str__(self): + Rtn = Rtn = 'SkuId = ' + str(self.SkuId) + "," + \ + 'SkuIdName = ' + str(self.SkuIdName) + "," + \ + 'VariableName = ' + str(self.VariableName) + "," + \ + 'VariableGuid = ' + str(self.VariableGuid) + "," + \ + 'VariableOffset = ' + str(self.VariableOffset) + "," + \ + 'HiiDefaultValue = ' + str(self.HiiDefaultValue) + "," + \ + 'VpdOffset = ' + str(self.VpdOffset) + "," + \ + 'DefaultValue = ' + str(self.DefaultValue) + "," + return Rtn +## PcdErrorClass +# +# +# +class PcdErrorClass(object): + def __init__(self): + self.ValidValueList = '' + self.ValidValueListLang = '' + self.ValidValueRange = '' + self.Expression = '' + self.ErrorNumber = '' + self.ErrorMessage = [] + +## PcdClass +# +# This class defined Pcd item used in Module/Platform/Package files +# +# @param CommonClass: Inherited from CommonClass class +# @param CName: Input value for CName, default is '' +# @param Token: Input value for Token, default is '' +# @param TokenSpaceGuidCName: Input value for TokenSpaceGuidCName, default is '' +# @param DatumType: Input value for DatumType, default is '' +# @param MaxDatumSize: Input value for MaxDatumSize, default is '' +# @param DefaultValue: Input value for DefaultValue, default is '' +# @param ItemType: Input value for ItemType, default is '' +# @param ValidUsage: Input value for ValidUsage, default is [] +# @param SkuInfoList: Input value for SkuInfoList, default is {} +# @param SupModuleList: Input value for SupModuleList, default is [] +# +# @var CName: To store value for CName +# @var Token: To store value for Token +# @var TokenSpaceGuidCName: To store value for TokenSpaceGuidCName +# @var DatumType: To store value for DatumType, selection scope is in below list +# UINT8 | UINT16 | UINT32 | UINT64 | VOID* | BOOLEAN +# @var MaxDatumSize: To store value for MaxDatumSize +# @var DefaultValue: To store value for DefaultValue +# @var ItemType: To store value for ItemType, selection scope is in below list +# FEATURE_FLAG | FIXED_AT_BUILD | PATCHABLE_IN_MODULE | DYNAMIC | DYNAMIC_EX +# @var ValidUsage: To store value for ValidUsage, selection scope is in below list +# FEATURE_FLAG | FIXED_AT_BUILD | PATCHABLE_IN_MODULE | DYNAMIC | DYNAMIC_EX +# @var SkuInfoList: To store value for SkuInfoList +# It is a set structure as { [SkuIdName] : SkuInfoClass } +# @var SupModuleList: To store value for SupModuleList, selection scope is in below list +# BASE | SEC | PEI_CORE | PEIM | DXE_CORE | DXE_DRIVER | DXE_RUNTIME_DRIVER | DXE_SAL_DRIVER | DXE_SMM_DRIVER | UEFI_DRIVER | UEFI_APPLICATION | USER_DEFINED +# +class PcdClass(CommonClass): + def __init__(self, CName = '', Token = '', TokenSpaceGuidCName = '', DatumType = '', MaxDatumSize = '', DefaultValue = '', ItemType = '', ValidUsage = None, SkuInfoList = None, SupModuleList = None): + self.CName = CName + self.Token = Token + self.TokenSpaceGuidCName = TokenSpaceGuidCName + self.DatumType = DatumType + self.MaxDatumSize = MaxDatumSize + self.DefaultValue = DefaultValue + self.ItemType = ItemType + self.ValidUsage = ValidUsage + self.PcdItemType = '' + self.TokenSpaceGuidValue = '' + self.PcdUsage = '' + self.PcdCName = '' + self.Value = '' + self.Offset = '' + if self.ValidUsage == None: + self.ValidUsage = [] + self.SkuInfoList = SkuInfoList + if self.SkuInfoList == None: + self.SkuInfoList = {} + self.SupModuleList = SupModuleList + if self.SupModuleList == None: + self.SupModuleList = [] + CommonClass.__init__(self) + self.PcdErrors = [] + +## BuildOptionClass +# +# This class defined BuildOption item used in Module/Platform/Package files +# +# @param IncludeStatementClass: Inherited from IncludeStatementClass class +# @param ToolChainFamily: Input value for ToolChainFamily, default is '' +# @param ToolChain: Input value for ToolChain, default is '' +# @param Option: Input value for Option, default is '' +# +# @var Statement: To store value for Statement +# It is a string in a special format as "Family:Target_TagName_Tarch_ToolCode_FLAGS = String" +# @var ToolChainFamily: To store value for ToolChainFamily +# @var ToolChain: To store value for ToolChain +# @var Option: To store value for Option +# @var BuildTarget: To store value for BuildTarget +# @var TagName: To store value for TagName +# @var ToolCode: To store value for ToolCode +# @var SupArchList: To store value for SupArchList, selection scope is in below list +# EBC | IA32 | X64 | IPF | ARM | PPC +# +class BuildOptionClass(IncludeStatementClass): + def __init__(self, ToolChainFamily = '', ToolChain = '', Option = ''): + IncludeStatementClass.__init__(self) + self.Statement = '' + self.ToolChainFamily = ToolChainFamily + self.ToolChain = ToolChain + self.Option = Option + self.BuildTarget = '' + self.TagName = '' + self.ToolCode = '' + self.SupArchList = [] + +## IncludeClass +# +# This class defined Include item used in Module/Platform/Package files +# +# @param CommonClass: Inherited from CommonClass class +# +# @var FilePath: To store value for FilePath +# @var ModuleType: To store value for ModuleType +# @var Comment: To store value for Comment +# +class IncludeClass(CommonClass): + def __init__(self): + self.FilePath = '' + self.ModuleType = '' + self.SupModuleList = [] + self.Comment = '' + CommonClass.__init__(self) + +## FileClass +# +# +class FileClass(CommonClass): + def __init__(self): + self.Filename = '' + self.Executable = '' + self.Family = '' + self.FileType = '' + CommonClass.__init__(self) + + +## MiscFileClass +# +# +class MiscFileClass(CommonHeaderClass): + def __init__(self): + CommonHeaderClass.__init__(self) + self.Name = '' + self.Files = [] + + +## UserExtensionsClass +# +# This class defined UserExtensions item used in Module/Platform/Package files +# +# @param object: Inherited from object class +# +# @var UserID: To store value for UserID +# @var Identifier: To store value for Identifier +# @var Content: To store value for Content +# +class UserExtensionsClass(object): + def __init__(self): + self.UserID = '' + self.Identifier = 0 + self.Content = '' + self.Defines = [] + self.BuildOptions = [] diff --git a/BaseTools/Source/Python/CommonDataClass/DataClass.py b/BaseTools/Source/Python/CommonDataClass/DataClass.py new file mode 100644 index 0000000000..00f4be8332 --- /dev/null +++ b/BaseTools/Source/Python/CommonDataClass/DataClass.py @@ -0,0 +1,351 @@ +## @file +# This file is used to define class for data sturcture used in ECC +# +# Copyright (c) 2008, 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. + +## +# Import Modules +# +import Common.EdkLogger as EdkLogger + +## +# Static values for data models +# +MODEL_UNKNOWN = 0 + +MODEL_FILE_C = 1001 +MODEL_FILE_H = 1002 +MODEL_FILE_ASM = 1003 +MODEL_FILE_INF = 1011 +MODEL_FILE_DEC = 1012 +MODEL_FILE_DSC = 1013 +MODEL_FILE_FDF = 1014 +MODEL_FILE_INC = 1015 +MODEL_FILE_CIF = 1016 + +MODEL_IDENTIFIER_FILE_HEADER = 2001 +MODEL_IDENTIFIER_FUNCTION_HEADER = 2002 +MODEL_IDENTIFIER_COMMENT = 2003 +MODEL_IDENTIFIER_PARAMETER = 2004 +MODEL_IDENTIFIER_STRUCTURE = 2005 +MODEL_IDENTIFIER_VARIABLE = 2006 +MODEL_IDENTIFIER_INCLUDE = 2007 +MODEL_IDENTIFIER_PREDICATE_EXPRESSION = 2008 +MODEL_IDENTIFIER_ENUMERATE = 2009 +MODEL_IDENTIFIER_PCD = 2010 +MODEL_IDENTIFIER_UNION = 2011 +MODEL_IDENTIFIER_MACRO_IFDEF = 2012 +MODEL_IDENTIFIER_MACRO_IFNDEF = 2013 +MODEL_IDENTIFIER_MACRO_DEFINE = 2014 +MODEL_IDENTIFIER_MACRO_ENDIF = 2015 +MODEL_IDENTIFIER_MACRO_PROGMA = 2016 +MODEL_IDENTIFIER_FUNCTION_CALLING = 2018 +MODEL_IDENTIFIER_TYPEDEF = 2017 +MODEL_IDENTIFIER_FUNCTION_DECLARATION = 2019 +MODEL_IDENTIFIER_ASSIGNMENT_EXPRESSION = 2020 + +MODEL_EFI_PROTOCOL = 3001 +MODEL_EFI_PPI = 3002 +MODEL_EFI_GUID = 3003 +MODEL_EFI_LIBRARY_CLASS = 3004 +MODEL_EFI_LIBRARY_INSTANCE = 3005 +MODEL_EFI_PCD = 3006 +MODEL_EFI_SOURCE_FILE = 3007 +MODEL_EFI_BINARY_FILE = 3008 +MODEL_EFI_SKU_ID = 3009 +MODEL_EFI_INCLUDE = 3010 +MODEL_EFI_DEPEX = 3011 + +MODEL_PCD = 4000 +MODEL_PCD_FIXED_AT_BUILD = 4001 +MODEL_PCD_PATCHABLE_IN_MODULE = 4002 +MODEL_PCD_FEATURE_FLAG = 4003 +MODEL_PCD_DYNAMIC_EX = 4004 +MODEL_PCD_DYNAMIC_EX_DEFAULT = 4005 +MODEL_PCD_DYNAMIC_EX_VPD = 4006 +MODEL_PCD_DYNAMIC_EX_HII = 4007 +MODEL_PCD_DYNAMIC = 4008 +MODEL_PCD_DYNAMIC_DEFAULT = 4009 +MODEL_PCD_DYNAMIC_VPD = 4010 +MODEL_PCD_DYNAMIC_HII = 4011 + +MODEL_META_DATA_HEADER = 5001 +MODEL_META_DATA_INCLUDE = 5002 +MODEL_META_DATA_DEFINE = 5003 +MODEL_META_DATA_CONDITIONAL_STATEMENT_IF = 5004 +MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE = 5005 +MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF = 5006 +MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF = 5007 +MODEL_META_DATA_BUILD_OPTION = 5008 +MODEL_META_DATA_COMPONENT = 5009 +MODEL_META_DATA_USER_EXTENSION = 5010 +MODEL_META_DATA_PACKAGE = 5011 +MODEL_META_DATA_NMAKE = 5012 +MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF = 50013 +MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF = 5014 +MODEL_META_DATA_COMPONENT_SOURCE_OVERRIDE_PATH = 5015 + +MODEL_LIST = [('MODEL_UNKNOWN', MODEL_UNKNOWN), + ('MODEL_FILE_C', MODEL_FILE_C), + ('MODEL_FILE_H', MODEL_FILE_H), + ('MODEL_FILE_ASM', MODEL_FILE_ASM), + ('MODEL_FILE_INF', MODEL_FILE_INF), + ('MODEL_FILE_DEC', MODEL_FILE_DEC), + ('MODEL_FILE_DSC', MODEL_FILE_DSC), + ('MODEL_FILE_FDF', MODEL_FILE_FDF), + ('MODEL_FILE_INC', MODEL_FILE_INC), + ('MODEL_IDENTIFIER_FILE_HEADER', MODEL_IDENTIFIER_FILE_HEADER), + ('MODEL_IDENTIFIER_FUNCTION_HEADER', MODEL_IDENTIFIER_FUNCTION_HEADER), + ('MODEL_IDENTIFIER_COMMENT', MODEL_IDENTIFIER_COMMENT), + ('MODEL_IDENTIFIER_PARAMETER', MODEL_IDENTIFIER_PARAMETER), + ('MODEL_IDENTIFIER_STRUCTURE', MODEL_IDENTIFIER_STRUCTURE), + ('MODEL_IDENTIFIER_VARIABLE', MODEL_IDENTIFIER_VARIABLE), + ('MODEL_IDENTIFIER_INCLUDE', MODEL_IDENTIFIER_INCLUDE), + ('MODEL_IDENTIFIER_PREDICATE_EXPRESSION', MODEL_IDENTIFIER_PREDICATE_EXPRESSION), + ('MODEL_IDENTIFIER_ENUMERATE', MODEL_IDENTIFIER_ENUMERATE), + ('MODEL_IDENTIFIER_PCD', MODEL_IDENTIFIER_PCD), + ('MODEL_IDENTIFIER_UNION', MODEL_IDENTIFIER_UNION), + ('MODEL_IDENTIFIER_MACRO_IFDEF', MODEL_IDENTIFIER_MACRO_IFDEF), + ('MODEL_IDENTIFIER_MACRO_IFNDEF', MODEL_IDENTIFIER_MACRO_IFNDEF), + ('MODEL_IDENTIFIER_MACRO_DEFINE', MODEL_IDENTIFIER_MACRO_DEFINE), + ('MODEL_IDENTIFIER_MACRO_ENDIF', MODEL_IDENTIFIER_MACRO_ENDIF), + ('MODEL_IDENTIFIER_MACRO_PROGMA', MODEL_IDENTIFIER_MACRO_PROGMA), + ('MODEL_IDENTIFIER_FUNCTION_CALLING', MODEL_IDENTIFIER_FUNCTION_CALLING), + ('MODEL_IDENTIFIER_TYPEDEF', MODEL_IDENTIFIER_TYPEDEF), + ('MODEL_IDENTIFIER_FUNCTION_DECLARATION', MODEL_IDENTIFIER_FUNCTION_DECLARATION), + ('MODEL_IDENTIFIER_ASSIGNMENT_EXPRESSION', MODEL_IDENTIFIER_ASSIGNMENT_EXPRESSION), + ('MODEL_EFI_PROTOCOL', MODEL_EFI_PROTOCOL), + ('MODEL_EFI_PPI', MODEL_EFI_PPI), + ('MODEL_EFI_GUID', MODEL_EFI_GUID), + ('MODEL_EFI_LIBRARY_CLASS', MODEL_EFI_LIBRARY_CLASS), + ('MODEL_EFI_LIBRARY_INSTANCE', MODEL_EFI_LIBRARY_INSTANCE), + ('MODEL_EFI_PCD', MODEL_EFI_PCD), + ('MODEL_EFI_SKU_ID', MODEL_EFI_SKU_ID), + ('MODEL_EFI_INCLUDE', MODEL_EFI_INCLUDE), + ('MODEL_EFI_DEPEX', MODEL_EFI_DEPEX), + ('MODEL_IDENTIFIER_UNION', MODEL_IDENTIFIER_UNION), + ('MODEL_EFI_SOURCE_FILE', MODEL_EFI_SOURCE_FILE), + ('MODEL_EFI_BINARY_FILE', MODEL_EFI_BINARY_FILE), + ('MODEL_PCD', MODEL_PCD), + ('MODEL_PCD_FIXED_AT_BUILD', MODEL_PCD_FIXED_AT_BUILD), + ('MODEL_PCD_PATCHABLE_IN_MODULE', MODEL_PCD_PATCHABLE_IN_MODULE), + ('MODEL_PCD_FEATURE_FLAG', MODEL_PCD_FEATURE_FLAG), + ('MODEL_PCD_DYNAMIC_EX', MODEL_PCD_DYNAMIC_EX), + ('MODEL_PCD_DYNAMIC_EX_DEFAULT', MODEL_PCD_DYNAMIC_EX_DEFAULT), + ('MODEL_PCD_DYNAMIC_EX_VPD', MODEL_PCD_DYNAMIC_EX_VPD), + ('MODEL_PCD_DYNAMIC_EX_HII', MODEL_PCD_DYNAMIC_EX_HII), + ('MODEL_PCD_DYNAMIC', MODEL_PCD_DYNAMIC), + ('MODEL_PCD_DYNAMIC_DEFAULT', MODEL_PCD_DYNAMIC_DEFAULT), + ('MODEL_PCD_DYNAMIC_VPD', MODEL_PCD_DYNAMIC_VPD), + ('MODEL_PCD_DYNAMIC_HII', MODEL_PCD_DYNAMIC_HII), + ("MODEL_META_DATA_HEADER", MODEL_META_DATA_HEADER), + ("MODEL_META_DATA_INCLUDE", MODEL_META_DATA_INCLUDE), + ("MODEL_META_DATA_DEFINE", MODEL_META_DATA_DEFINE), + ("MODEL_META_DATA_CONDITIONAL_STATEMENT_IF", MODEL_META_DATA_CONDITIONAL_STATEMENT_IF), + ("MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE", MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE), + ("MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF", MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF), + ("MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF", MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF), + ("MODEL_META_DATA_COMPONENT_SOURCE_OVERRIDE_PATH", MODEL_META_DATA_COMPONENT_SOURCE_OVERRIDE_PATH), + ("MODEL_META_DATA_BUILD_OPTION", MODEL_META_DATA_BUILD_OPTION), + ("MODEL_META_DATA_COMPONENT", MODEL_META_DATA_COMPONENT), + ('MODEL_META_DATA_USER_EXTENSION', MODEL_META_DATA_USER_EXTENSION), + ('MODEL_META_DATA_PACKAGE', MODEL_META_DATA_PACKAGE), + ('MODEL_META_DATA_NMAKE', MODEL_META_DATA_NMAKE) + ] + +## FunctionClass +# +# This class defines a structure of a function +# +# @param ID: ID of a Function +# @param Header: Header of a Function +# @param Modifier: Modifier of a Function +# @param Name: Name of a Function +# @param ReturnStatement: ReturnStatement of a Funciont +# @param StartLine: StartLine of a Function +# @param StartColumn: StartColumn of a Function +# @param EndLine: EndLine of a Function +# @param EndColumn: EndColumn of a Function +# @param BodyStartLine: BodyStartLine of a Function Body +# @param BodyStartColumn: BodyStartColumn of a Function Body +# @param BelongsToFile: The Function belongs to which file +# @param IdentifierList: IdentifierList of a File +# @param PcdList: PcdList of a File +# +# @var ID: ID of a Function +# @var Header: Header of a Function +# @var Modifier: Modifier of a Function +# @var Name: Name of a Function +# @var ReturnStatement: ReturnStatement of a Funciont +# @var StartLine: StartLine of a Function +# @var StartColumn: StartColumn of a Function +# @var EndLine: EndLine of a Function +# @var EndColumn: EndColumn of a Function +# @var BodyStartLine: StartLine of a Function Body +# @var BodyStartColumn: StartColumn of a Function Body +# @var BelongsToFile: The Function belongs to which file +# @var IdentifierList: IdentifierList of a File +# @var PcdList: PcdList of a File +# +class FunctionClass(object): + def __init__(self, ID = -1, Header = '', Modifier = '', Name = '', ReturnStatement = '', \ + StartLine = -1, StartColumn = -1, EndLine = -1, EndColumn = -1, \ + BodyStartLine = -1, BodyStartColumn = -1, BelongsToFile = -1, \ + IdentifierList = [], PcdList = [], \ + FunNameStartLine = -1, FunNameStartColumn = -1): + self.ID = ID + self.Header = Header + self.Modifier = Modifier + self.Name = Name + self.ReturnStatement = ReturnStatement + self.StartLine = StartLine + self.StartColumn = StartColumn + self.EndLine = EndLine + self.EndColumn = EndColumn + self.BodyStartLine = BodyStartLine + self.BodyStartColumn = BodyStartColumn + self.BelongsToFile = BelongsToFile + self.FunNameStartLine = FunNameStartLine + self.FunNameStartColumn = FunNameStartColumn + + self.IdentifierList = IdentifierList + self.PcdList = PcdList + +## IdentifierClass +# +# This class defines a structure of a variable +# +# @param ID: ID of a Identifier +# @param Modifier: Modifier of a Identifier +# @param Type: Type of a Identifier +# @param Name: Name of a Identifier +# @param Value: Value of a Identifier +# @param Model: Model of a Identifier +# @param BelongsToFile: The Identifier belongs to which file +# @param BelongsToFunction: The Identifier belongs to which function +# @param StartLine: StartLine of a Identifier +# @param StartColumn: StartColumn of a Identifier +# @param EndLine: EndLine of a Identifier +# @param EndColumn: EndColumn of a Identifier +# +# @var ID: ID of a Identifier +# @var Modifier: Modifier of a Identifier +# @var Type: Type of a Identifier +# @var Name: Name of a Identifier +# @var Value: Value of a Identifier +# @var Model: Model of a Identifier +# @var BelongsToFile: The Identifier belongs to which file +# @var BelongsToFunction: The Identifier belongs to which function +# @var StartLine: StartLine of a Identifier +# @var StartColumn: StartColumn of a Identifier +# @var EndLine: EndLine of a Identifier +# @var EndColumn: EndColumn of a Identifier +# +class IdentifierClass(object): + def __init__(self, ID = -1, Modifier = '', Type = '', Name = '', Value = '', Model = MODEL_UNKNOWN, \ + BelongsToFile = -1, BelongsToFunction = -1, StartLine = -1, StartColumn = -1, EndLine = -1, EndColumn = -1): + self.ID = ID + self.Modifier = Modifier + self.Type = Type + self.Name = Name + self.Value = Value + self.Model = Model + self.BelongsToFile = BelongsToFile + self.BelongsToFunction = BelongsToFunction + self.StartLine = StartLine + self.StartColumn = StartColumn + self.EndLine = EndLine + self.EndColumn = EndColumn + +## PcdClass +# +# This class defines a structure of a Pcd +# +# @param ID: ID of a Pcd +# @param CName: CName of a Pcd +# @param TokenSpaceGuidCName: TokenSpaceGuidCName of a Pcd +# @param Token: Token of a Pcd +# @param DatumType: DatumType of a Pcd +# @param Model: Model of a Pcd +# @param BelongsToFile: The Pcd belongs to which file +# @param BelongsToFunction: The Pcd belongs to which function +# @param StartLine: StartLine of a Pcd +# @param StartColumn: StartColumn of a Pcd +# @param EndLine: EndLine of a Pcd +# @param EndColumn: EndColumn of a Pcd +# +# @var ID: ID of a Pcd +# @var CName: CName of a Pcd +# @var TokenSpaceGuidCName: TokenSpaceGuidCName of a Pcd +# @var Token: Token of a Pcd +# @var DatumType: DatumType of a Pcd +# @var Model: Model of a Pcd +# @var BelongsToFile: The Pcd belongs to which file +# @var BelongsToFunction: The Pcd belongs to which function +# @var StartLine: StartLine of a Pcd +# @var StartColumn: StartColumn of a Pcd +# @var EndLine: EndLine of a Pcd +# @var EndColumn: EndColumn of a Pcd +# +class PcdDataClass(object): + def __init__(self, ID = -1, CName = '', TokenSpaceGuidCName = '', Token = '', DatumType = '', Model = MODEL_UNKNOWN, \ + BelongsToFile = -1, BelongsToFunction = -1, StartLine = -1, StartColumn = -1, EndLine = -1, EndColumn = -1): + self.ID = ID + self.CName = CName + self.TokenSpaceGuidCName = TokenSpaceGuidCName + self.Token = Token + self.DatumType = DatumType + self.BelongsToFile = BelongsToFile + self.BelongsToFunction = BelongsToFunction + self.StartLine = StartLine + self.StartColumn = StartColumn + self.EndLine = EndLine + self.EndColumn = EndColumn + +## FileClass +# +# This class defines a structure of a file +# +# @param ID: ID of a File +# @param Name: Name of a File +# @param ExtName: ExtName of a File +# @param Path: Path of a File +# @param FullPath: FullPath of a File +# @param Model: Model of a File +# @param TimeStamp: TimeStamp of a File +# @param FunctionList: FunctionList of a File +# @param IdentifierList: IdentifierList of a File +# @param PcdList: PcdList of a File +# +# @var ID: ID of a File +# @var Name: Name of a File +# @var ExtName: ExtName of a File +# @var Path: Path of a File +# @var FullPath: FullPath of a File +# @var Model: Model of a File +# @var TimeStamp: TimeStamp of a File +# @var FunctionList: FunctionList of a File +# @var IdentifierList: IdentifierList of a File +# @var PcdList: PcdList of a File +# +class FileClass(object): + def __init__(self, ID = -1, Name = '', ExtName = '', Path = '', FullPath = '', Model = MODEL_UNKNOWN, TimeStamp = '', \ + FunctionList = [], IdentifierList = [], PcdList = []): + self.ID = ID + self.Name = Name + self.ExtName = ExtName + self.Path = Path + self.FullPath = FullPath + self.Model = Model + self.TimeStamp = TimeStamp + + self.FunctionList = FunctionList + self.IdentifierList = IdentifierList + self.PcdList = PcdList diff --git a/BaseTools/Source/Python/CommonDataClass/DistributionPackageClass.py b/BaseTools/Source/Python/CommonDataClass/DistributionPackageClass.py new file mode 100644 index 0000000000..cd8bd4cb7f --- /dev/null +++ b/BaseTools/Source/Python/CommonDataClass/DistributionPackageClass.py @@ -0,0 +1,159 @@ +## @file +# This file is used to define a class object to describe a distribution package +# +# Copyright (c) 2008, 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. + +## +# Import Modules +# +import os.path +from CommonClass import * +from Common.Misc import sdict +from Common.Misc import GetFiles +from Common.DecClassObjectLight import Dec +from Common.InfClassObjectLight import Inf +from Common.XmlParser import * + +## DistributionPackageHeaderClass +# +class DistributionPackageHeaderClass(IdentificationClass, CommonHeaderClass): + def __init__(self): + IdentificationClass.__init__(self) + CommonHeaderClass.__init__(self) + self.ReadOnly = 'False' + self.RePackage = 'True' + self.Vendor = '' + self.Date = '' + self.Signature = 'Md5Sum' + self.XmlSpecification = '' + +## DistributionPackageClass +# +# +class DistributionPackageClass(object): + def __init__(self): + self.Header = DistributionPackageHeaderClass() + self.PackageSurfaceArea = sdict() # {(Guid, Version, Path) : PackageObj} + self.ModuleSurfaceArea = sdict() # {(Guid, Version, Path) : ModuleObj} + self.Tools = MiscFileClass() + self.MiscellaneousFiles = MiscFileClass() + self.UserExtensions = [] + + ## Get all included packages and modules for a distribution package + # + # @param WorkspaceDir: WorkspaceDir + # @param PackageList: A list of all packages + # @param ModuleList: A list of all modules + # + def GetDistributionPackage(self, WorkspaceDir, PackageList, ModuleList): + AllGuidVersionDict = {} + # Get Packages + if PackageList: + for PackageFile in PackageList: + PackageFileFullPath = os.path.normpath(os.path.join(WorkspaceDir, PackageFile)) + DecObj = Dec(PackageFileFullPath, True, WorkspaceDir) + PackageObj = DecObj.Package + AllGuidVersionDict[PackageFileFullPath] = [PackageObj.PackageHeader.Guid, PackageObj.PackageHeader.Version] + + # Parser inf file one bye one + for File in PackageObj.MiscFiles.Files: + Filename = os.path.normpath(os.path.join(PackageObj.PackageHeader.RelaPath, File.Filename)) + (Name, ExtName) = os.path.splitext(Filename) + if ExtName.upper() == '.INF': + InfObj = Inf(Filename, True, WorkspaceDir, DecObj.Identification.PackagePath) + ModuleObj = InfObj.Module + AllGuidVersionDict[File] = [ModuleObj.ModuleHeader.Guid, ModuleObj.ModuleHeader.Version] + # Find and update Guid/Version of LibraryClass + for Item in ModuleObj.LibraryClasses: + if Item.RecommendedInstance: + LibClassIns = os.path.normpath(os.path.join(WorkspaceDir, Item.RecommendedInstance)) + Guid, Version = '', '' + if LibClassIns in AllGuidVersionDict: + Guid = AllGuidVersionDict[LibClassIns][0] + Version = AllGuidVersionDict[LibClassIns][1] + else: + Lib = Inf(LibClassIns, True, WorkspaceDir) + Guid = Lib.Module.ModuleHeader.Guid + Version = Lib.Module.ModuleHeader.Version + AllGuidVersionDict[LibClassIns] = [Guid, Version] + Item.RecommendedInstanceGuid = Guid + Item.RecommendedInstanceVersion = Version + # Find and update Guid/Version of + for Item in ModuleObj.PackageDependencies: + if Item.FilePath: + PackageFilePath = os.path.normpath(os.path.join(WorkspaceDir, Item.FilePath)) + Guid, Version = '', '' + if PackageFilePath in AllGuidVersionDict: + Guid = AllGuidVersionDict[PackageFilePath][0] + Version = AllGuidVersionDict[PackageFilePath][1] + else: + PackageDependencies = Dec(PackageFilePath, True, WorkspaceDir) + Guid = PackageDependencies.Package.PackageHeader.Guid + Version = PackageDependencies.Package.PackageHeader.Version + AllGuidVersionDict[PackageFilePath] = [Guid, Version] + Item.PackageGuid = Guid + Item.PackageVersion = Version + + # Add module to package + PackageObj.Modules[(ModuleObj.ModuleHeader.Guid, ModuleObj.ModuleHeader.Version, ModuleObj.ModuleHeader.CombinePath)] = ModuleObj + self.PackageSurfaceArea[(PackageObj.PackageHeader.Guid, PackageObj.PackageHeader.Version, PackageObj.PackageHeader.CombinePath)] = PackageObj + + # Get Modules + if ModuleList: + for ModuleFile in ModuleList: + ModuleFileFullPath = os.path.normpath(os.path.join(WorkspaceDir, ModuleFile)) + InfObj = Inf(ModuleFileFullPath, True, WorkspaceDir) + ModuleObj = InfObj.Module + AllGuidVersionDict[ModuleFileFullPath] = [ModuleObj.ModuleHeader.Guid, ModuleObj.ModuleHeader.Version] + # Find and update Guid/Version of LibraryClass + for Item in ModuleObj.LibraryClasses: + if Item.RecommendedInstance: + LibClassIns = os.path.normpath(os.path.join(WorkspaceDir, Item.RecommendedInstance)) + Guid, Version = '', '' + if LibClassIns in AllGuidVersionDict: + Guid = AllGuidVersionDict[LibClassIns][0] + Version = AllGuidVersionDict[LibClassIns][1] + else: + Lib = Inf(LibClassIns, True, WorkspaceDir) + Guid = Lib.Module.ModuleHeader.Guid + Version = Lib.Module.ModuleHeader.Version + AllGuidVersionDict[LibClassIns] = [Guid, Version] + Item.RecommendedInstanceGuid = Guid + Item.RecommendedInstanceVersion = Version + # Find and update Guid/Version of + for Item in ModuleObj.PackageDependencies: + if Item.FilePath: + PackageFilePath = os.path.normpath(os.path.join(WorkspaceDir, Item.FilePath)) + Guid, Version = '', '' + if PackageFilePath in AllGuidVersionDict: + Guid = AllGuidVersionDict[PackageFilePath][0] + Version = AllGuidVersionDict[PackageFilePath][1] + else: + PackageDependencies = Dec(PackageFilePath, True, WorkspaceDir) + Guid = PackageDependencies.Package.PackageHeader.Guid + Version = PackageDependencies.Package.PackageHeader.Version + AllGuidVersionDict[PackageFilePath] = [Guid, Version] + Item.PackageGuid = Guid + Item.PackageVersion = Version + self.ModuleSurfaceArea[(ModuleObj.ModuleHeader.Guid, ModuleObj.ModuleHeader.Version, ModuleObj.ModuleHeader.CombinePath)] = ModuleObj + +## +# +# This acts like the main() function for the script, unless it is 'import'ed into another +# script. +# +if __name__ == '__main__': + pass + D = DistributionPackageClass() + D.GetDistributionPackage(os.getenv('WORKSPACE'), ['MdePkg/MdePkg.dec', 'TianoModulePkg/TianoModulePkg.dec'], ['MdeModulePkg/Application/HelloWorld/HelloWorld.inf']) + Xml = DistributionPackageXml() + print Xml.ToXml(D) + E = Xml.FromXml('C:\\2.xml') + #print Xml.ToXml(E) diff --git a/BaseTools/Source/Python/CommonDataClass/FdfClass.py b/BaseTools/Source/Python/CommonDataClass/FdfClass.py new file mode 100644 index 0000000000..a9e12ed46d --- /dev/null +++ b/BaseTools/Source/Python/CommonDataClass/FdfClass.py @@ -0,0 +1,402 @@ +## @file +# classes represent data in FDF +# +# Copyright (c) 2007, 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. +# + +## FD data in FDF +# +# +class FDClassObject: + ## The constructor + # + # @param self The object pointer + # + def __init__(self): + self.FdUiName = '' + self.CreateFileName = None + self.BaseAddress = None + self.BaseAddressPcd = None + self.Size = None + self.SizePcd = None + self.ErasePolarity = '1' + # 3-tuple list (blockSize, numBlocks, pcd) + self.BlockSizeList = [] + # DefineVarDict[var] = value + self.DefineVarDict = {} + # SetVarDict[var] = value + self.SetVarDict = {} + self.RegionList = [] + self.vtfRawDict = {} + +## FV data in FDF +# +# +class FvClassObject: + ## The constructor + # + # @param self The object pointer + # + def __init__(self): + self.UiFvName = None + self.CreateFileName = None + # 3-tuple list (blockSize, numBlocks, pcd) + self.BlockSizeList = [] + # DefineVarDict[var] = value + self.DefineVarDict = {} + # SetVarDict[var] = value + self.SetVarDict = {} + self.FvAlignment = None + # FvAttributeDict[attribute] = TRUE/FALSE (1/0) + self.FvAttributeDict = {} + self.FvNameGuid = None + self.AprioriSectionList = [] + self.FfsList = [] + self.BsBaseAddress = None + self.RtBaseAddress = None + +## Region data in FDF +# +# +class RegionClassObject: + ## The constructor + # + # @param self The object pointer + # + def __init__(self): + self.Offset = None # The begin position of the Region + self.Size = None # The Size of the Region + self.PcdOffset = None + self.PcdSize = None + self.SetVarDict = {} + self.RegionType = None + self.RegionDataList = [] + +## FFS data in FDF +# +# +class FfsClassObject: + ## The constructor + # + # @param self The object pointer + # + def __init__(self): + self.NameGuid = None + self.Fixed = False + self.CheckSum = False + self.Alignment = None + self.SectionList = [] + +## FILE statement data in FDF +# +# +class FileStatementClassObject (FfsClassObject) : + ## The constructor + # + # @param self The object pointer + # + def __init__(self): + FfsClassObject.__init__(self) + self.FvFileType = None + self.FileName = None + self.KeyStringList = [] + self.FvName = None + self.FdName = None + self.DefineVarDict = {} + self.AprioriSection = None + self.KeepReloc = None + +## INF statement data in FDF +# +# +class FfsInfStatementClassObject(FfsClassObject): + ## The constructor + # + # @param self The object pointer + # + def __init__(self): + FfsClassObject.__init__(self) + self.Rule = None + self.Version = None + self.Ui = None + self.InfFileName = None + self.BuildNum = '' + self.KeyStringList = [] + self.KeepReloc = None + self.UseArch = None + +## APRIORI section data in FDF +# +# +class AprioriSectionClassObject: + ## The constructor + # + # @param self The object pointer + # + def __init__(self): + # DefineVarDict[var] = value + self.DefineVarDict = {} + self.FfsList = [] + +## section data in FDF +# +# +class SectionClassObject: + ## The constructor + # + # @param self The object pointer + # + def __init__(self): + self.Alignment = None + +## Depex expression section in FDF +# +# +class DepexSectionClassObject (SectionClassObject): + ## The constructor + # + # @param self The object pointer + # + def __init__(self): + self.DepexType = None + self.Expression = None + +## Compress section data in FDF +# +# +class CompressSectionClassObject (SectionClassObject) : + ## The constructor + # + # @param self The object pointer + # + def __init__(self): + SectionClassObject.__init__(self) + self.CompType = None + self.SectionList = [] + +## Data section data in FDF +# +# +class DataSectionClassObject (SectionClassObject): + ## The constructor + # + # @param self The object pointer + # + def __init__(self): + SectionClassObject.__init__(self) + self.SecType = None + self.SectFileName = None + self.SectionList = [] + self.KeepReloc = True + +## Rule section data in FDF +# +# +class EfiSectionClassObject (SectionClassObject): + ## The constructor + # + # @param self The object pointer + # + def __init__(self): + SectionClassObject.__init__(self) + self.SectionType = None + self.Optional = False + self.FileType = None + self.StringData = None + self.FileName = None + self.FileExtension = None + self.BuildNum = None + self.KeepReloc = None + +## FV image section data in FDF +# +# +class FvImageSectionClassObject (SectionClassObject): + ## The constructor + # + # @param self The object pointer + # + def __init__(self): + SectionClassObject.__init__(self) + self.Fv = None + self.FvName = None + self.FvFileType = None + self.FvFileName = None + self.FvFileExtension = None + +## GUIDed section data in FDF +# +# +class GuidSectionClassObject (SectionClassObject) : + ## The constructor + # + # @param self The object pointer + # + def __init__(self): + SectionClassObject.__init__(self) + self.NameGuid = None + self.SectionList = [] + self.SectionType = None + self.ProcessRequired = False + self.AuthStatusValid = False + +## UI section data in FDF +# +# +class UiSectionClassObject (SectionClassObject): + ## The constructor + # + # @param self The object pointer + # + def __init__(self): + SectionClassObject.__init__(self) + self.StringData = None + self.FileName = None + +## Version section data in FDF +# +# +class VerSectionClassObject (SectionClassObject): + ## The constructor + # + # @param self The object pointer + # + def __init__(self): + SectionClassObject.__init__(self) + self.BuildNum = None + self.StringData = None + self.FileName = None + +## Rule data in FDF +# +# +class RuleClassObject : + ## The constructor + # + # @param self The object pointer + # + def __init__(self): + self.Arch = None + self.ModuleType = None # For Module Type + self.TemplateName = None + self.NameGuid = None + self.Fixed = False + self.Alignment = None + self.CheckSum = False + self.FvFileType = None # for Ffs File Type + self.KeyStringList = [] + self.KeepReloc = None + +## Complex rule data in FDF +# +# +class RuleComplexFileClassObject(RuleClassObject) : + ## The constructor + # + # @param self The object pointer + # + def __init__(self): + RuleClassObject.__init__(self) + self.SectionList = [] + +## Simple rule data in FDF +# +# +class RuleSimpleFileClassObject(RuleClassObject) : + ## The constructor + # + # @param self The object pointer + # + def __init__(self): + RuleClassObject.__init__(self) + self.FileName = None + self.SectionType = '' + self.FileExtension = None + +## File extension rule data in FDF +# +# +class RuleFileExtensionClassObject(RuleClassObject): + ## The constructor + # + # @param self The object pointer + # + def __init__(self): + RuleClassObject.__init__(self) + self.FileExtension = None + +## Capsule data in FDF +# +# +class CapsuleClassObject : + ## The constructor + # + # @param self The object pointer + # + def __init__(self): + self.SpecName = None + self.UiCapsuleName = None + self.CreateFile = None + self.GroupIdNumber = None + # DefineVarDict[var] = value + self.DefineVarDict = {} + # SetVarDict[var] = value + self.SetVarDict = {} + # TokensDict[var] = value + self.TokensDict = {} + self.CapsuleDataList = [] + +## VTF data in FDF +# +# +class VtfClassObject : + ## The constructor + # + # @param self The object pointer + # + def __init__(self): + self.KeyArch = None + self.ArchList = None + self.UiName = None + self.ResetBin = None + self.ComponentStatementList = [] + +## VTF component data in FDF +# +# +class ComponentStatementClassObject : + ## The constructor + # + # @param self The object pointer + # + def __init__(self): + self.CompName = None + self.CompLoc = None + self.CompType = None + self.CompVer = None + self.CompCs = None + self.CompBin = None + self.CompSym = None + self.CompSize = None + self.FilePos = None + +## OptionROM data in FDF +# +# +class OptionRomClassObject: + ## The constructor + # + # @param self The object pointer + # + def __init__(self): + self.DriverName = None + self.FfsList = [] + \ No newline at end of file diff --git a/BaseTools/Source/Python/CommonDataClass/ModuleClass.py b/BaseTools/Source/Python/CommonDataClass/ModuleClass.py new file mode 100644 index 0000000000..9d780725b9 --- /dev/null +++ b/BaseTools/Source/Python/CommonDataClass/ModuleClass.py @@ -0,0 +1,486 @@ +## @file +# This file is used to define a class object to describe a module +# +# Copyright (c) 2007, 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. + +## +# Import Modules +# +from CommonClass import * + +## ModuleHeaderClass +# +# This class defined header items used in Module file +# +# @param IdentificationClass: Inherited from IdentificationClass class +# @param CommonHeaderClass: Inherited from CommonHeaderClass class +# @param DefineClass: Inherited from DefineClass class +# +# @var ModuleType: To store value for ModuleType +# @var SupArchList: To store value for SupArchList, selection scope is in below list +# EBC | IA32 | X64 | IPF | ARM | PPC +# @var BinaryModule: To store value for BinaryModule +# @var OutputFileBasename: To store value for OutputFileBasename +# @var ClonedFrom: To store value for ClonedFrom, it is a set structure as +# [ ClonedRecordClass, ... ] +# @var PcdIsDriver: To store value for PcdIsDriver, selection scope is in below list +# PEI_PCD_DRIVER | DXE_PCD_DRIVER +# @var TianoR8FlashMap_h: To store value for TianoR8FlashMap_h +# @var InfVersion: To store value for InfVersion +# @var EfiSpecificationVersion: To store value for EfiSpecificationVersion +# @var EdkReleaseVersion: To store value for EdkReleaseVersion +# @var LibraryClass: To store value for LibraryClass, it is a set structure as +# [ LibraryClassClass, ...] +# @var ComponentType: To store value for ComponentType, selection scope is in below list +# LIBRARY | SECURITY_CORE | PEI_CORE | COMBINED_PEIM_DRIVER | PIC_PEIM | RELOCATABLE_PEIM | BS_DRIVER | RT_DRIVER | SAL_RT_DRIVER | APPLICATION +# @var MakefileName: To store value for MakefileName +# @var BuildNumber: To store value for BuildNumber +# @var BuildType: To store value for BuildType +# @var FfsExt: To store value for FfsExt +# @var FvExt: To store value for FvExt +# @var SourceFv: To store value for SourceFv +# @var CustomMakefile: To store value for CustomMakefile, it is a set structure as +# { Family : Filename, ... } +# @var Shadow: To store value for Shadow +# @var MacroDefines To store the defined macros +# +class ModuleHeaderClass(IdentificationClass, CommonHeaderClass, DefineClass): + def __init__(self): + IdentificationClass.__init__(self) + CommonHeaderClass.__init__(self) + DefineClass.__init__(self) + self.ModuleType = '' + self.SupModuleList = [] + self.SupArchList = [] + self.BinaryModule = False + self.OutputFileBasename = '' + self.ClonedFrom = [] + self.PcdIsDriver = '' + self.TianoR8FlashMap_h = False + self.InfVersion = '' + self.EfiSpecificationVersion = '' + self.PiSpecificationVersion = '' + self.UefiSpecificationVersion = '' + self.EdkReleaseVersion = '' + self.LibraryClass = [] + self.ComponentType = '' + self.MakefileName = '' + self.BuildNumber = '' + self.BuildType = '' + self.FfsExt = '' + self.FvExt = '' + self.SourceFv = '' + self.CustomMakefile = {} + self.Shadow = '' + self.MacroDefines = {} + self.SourceOverridePath = '' + self.Specification = [] + +## ModuleSourceFileClass +# +# This class defined source file item used in Module file +# +# @param CommonClass: Inherited from CommonClass class +# @param SourceFile: Input value for SourceFile, default is '' +# @param TagName: Input value for TagName, default is '' +# @param ToolCode: Input value for ToolCode, default is '' +# @param ToolChainFamily: Input value for ToolChainFamily, default is '' +# @param FeatureFlag: Input value for FeatureFlag, default is '' +# @param SupArchList: Input value for SupArchList, default is [] +# +# @var SourceFile: To store value for SourceFile +# @var TagName: To store value for TagName +# @var ToolCode: To store value for ToolCode +# @var ToolChainFamily: To store value for ToolChainFamily +# +class ModuleSourceFileClass(CommonClass): + def __init__(self, SourceFile = '', TagName = '', ToolCode = '', ToolChainFamily = '', FeatureFlag = '', SupArchList = None): + self.SourceFile = SourceFile + self.TagName = TagName + self.ToolCode = ToolCode + self.ToolChainFamily = ToolChainFamily + self.FileType = '' + CommonClass.__init__(self, FeatureFlag = FeatureFlag, SupArchList = SupArchList) + +## ModuleBinaryFileClass +# +# This class defined binary file item used in Module file +# +# @param CommonClass: Inherited from CommonClass class +# @param BinaryFile: Input value for BinaryFile, default is '' +# @param FileType: Input value for FileType, default is '' +# @param FeatureFlag: Input value for FeatureFlag, default is '' +# @param SupArchList: Input value for SupArchList, default is [] +# +# @var BinaryFile: To store value for BinaryFile +# @var FileType: To store value for FileType, selection scope is in below list +# FW | GUID | PREEFORM | UEFI_APP | UNI_UI | UNI_VER | LIB | PE32 | PIC | PEI_DEPEX | DXE_DEPEX | TE | VER | UI | BIN | FV +# @var Target: To store value for Target +# @var ToolChainFamily: To store value for ToolChainFamily +# +class ModuleBinaryFileClass(CommonClass): + def __init__(self, BinaryFile = '', FileType = '', Target = '', FeatureFlag = '', SupArchList = None): + self.BinaryFile = BinaryFile + self.FileType = FileType + self.Target = Target + CommonClass.__init__(self, FeatureFlag = FeatureFlag, SupArchList = SupArchList) + self.Filenames = [] + self.PatchPcdValues = [] + self.PcdExValues = [] + self.LibraryInstances = [] + self.BuildFlags = [] + +## ModulePackageDependencyClass +# +# This class defined package dependency item used in Module file +# +# @param CommonClass: Inherited from CommonClass class +# @param DefineClass: Input value for DefineClass class +# +# @var FilePath: To store value for FilePath +# @var PackageName: To store value for PackageName +# @var PackageVersion: To store value for PackageVersion +# @var PackageGuid: To store value for PackageGuid +# +class ModulePackageDependencyClass(CommonClass, DefineClass): + def __init__(self): + self.FilePath = '' + self.PackageName = '' + self.PackageVersion = '' + self.PackageGuid = '' + self.Description = '' + CommonClass.__init__(self) + DefineClass.__init__(self) + +## ModuleLibraryClass +# +# This class defined library item used in Module file +# +# @param CommonClass: Inherited from CommonClass class +# +# @var Library: To store value for Library +# +class ModuleLibraryClass(CommonClass): + def __init__(self): + self.Library = '' + CommonClass.__init__(self) + +## ModuleEventClass +# +# This class defined event item used in Module file +# +# @param CommonClass: Inherited from CommonClass class +# +# @var CName: To store value for CName +# @var GuidCName: To store value for GuidCName +# @var Type: To store value for Type, selection scope is in below list +# CREATE_EVENT | SIGNAL_EVENT +# +class ModuleEventClass(CommonClass): + def __init__(self): + self.CName = '' + self.GuidCName = '' + self.Type = '' + CommonClass.__init__(self) + +## ModuleHobClass +# +# This class defined hob item used in Module file +# +# @param CommonClass: Inherited from CommonClass class +# +# @var GuidCName: To store value for GuidCName +# @var Type: To store value for Type, selection scope is in below list +# PHIT | MEMORY_ALLOCATION | RESOURCE_DESCRIPTOR | GUID_EXTENSION | FIRMWARE_VOLUME | CPU | POOL | CAPSULE_VOLUME +# +class ModuleHobClass(CommonClass): + def __init__(self): + self.Type = '' + self.GuidCName = '' + CommonClass.__init__(self) + +## ModuleVariableClass +# +# This class defined variable item used in Module file +# +# @param CommonClass: Inherited from CommonClass class +# +# @var GuidCName: To store value for GuidCName +# @var Name: To store value for Name +# +class ModuleVariableClass(CommonClass): + def __init__(self): + self.Name = '' + self.GuidCName = '' + CommonClass.__init__(self) + +## ModuleBootModeClass +# +# This class defined boot mode item used in Module file +# +# @param CommonClass: Inherited from CommonClass class +# +# @var Name: To store value for Name, selection scope is in below list +# FULL | MINIMAL | NO_CHANGE | DIAGNOSTICS | DEFAULT | S2_RESUME | S3_RESUME | S4_RESUME | S5_RESUME | FLASH_UPDATE | RECOVERY_FULL | RECOVERY_MINIMAL | RECOVERY_NO_CHANGE | RECOVERY_DIAGNOSTICS | RECOVERY_DEFAULT | RECOVERY_S2_RESUME | RECOVERY_S3_RESUME | RECOVERY_S4_RESUME | RECOVERY_S5_RESUME | RECOVERY_FLASH_UPDATE +# +class ModuleBootModeClass(CommonClass): + def __init__(self): + self.Name = '' + CommonClass.__init__(self) + +## ModuleSystemTableClass +# +# This class defined system table item used in Module file +# +# @param CommonClass: Inherited from CommonClass class +# +# @var CName: To store value for CName +# +class ModuleSystemTableClass(CommonClass): + def __init__(self): + self.CName = '' + CommonClass.__init__(self) + +## ModuleDataHubClass +# +# This class defined data hub item used in Module file +# +# @param CommonClass: Inherited from CommonClass class +# +# @var CName: To store value for CName +# +class ModuleDataHubClass(CommonClass): + def __init__(self): + self.CName = '' + CommonClass.__init__(self) + +## ModuleHiiPackageClass +# +# This class defined Hii package item used in Module file +# +# @param CommonClass: Inherited from CommonClass class +# +# @var CName: To store value for CName +# +class ModuleHiiPackageClass(CommonClass): + def __init__(self): + self.CName = '' + CommonClass.__init__(self) + +## ModuleExternImageClass +# +# This class defined Extern Image item used in Module file +# +# @param object: Inherited from object class +# +# @var ModuleEntryPoint: To store value for ModuleEntryPoint +# @var ModuleUnloadImage: To store value for ModuleUnloadImage +# +class ModuleExternImageClass(object): + def __init__(self): + self.ModuleEntryPoint = '' + self.ModuleUnloadImage = '' + +## ModuleExternLibraryClass +# +# This class defined Extern Library item used in Module file +# +# @param object: Inherited from object class +# +# @var Constructor: To store value for Constructor +# @var Destructor: To store value for Destructor +# +class ModuleExternLibraryClass(object): + def __init__(self): + self.Constructor = '' + self.Destructor = '' + +## ModuleExternDriverClass +# +# This class defined Extern Driver item used in Module file +# +# @param object: Inherited from object class +# +# @var DriverBinding: To store value for DriverBinding +# @var ComponentName: To store value for ComponentName +# @var DriverConfig: To store value for DriverConfig +# @var DriverDiag: To store value for DriverDiag +# +class ModuleExternDriverClass(object): + def __init__(self): + self.DriverBinding= '' + self.ComponentName = '' + self.DriverConfig = '' + self.DriverDiag = '' + +## ModuleExternCallBackClass +# +# This class defined Extern Call Back item used in Module file +# +# @param object: Inherited from object class +# +# @var SetVirtualAddressMapCallBack: To store value for SetVirtualAddressMapCallBack +# @var ExitBootServicesCallBack: To store value for ExitBootServicesCallBack +# +class ModuleExternCallBackClass(object): + def __init__(self): + self.SetVirtualAddressMapCallBack = '' + self.ExitBootServicesCallBack = '' + +## ModuleExternClass +# +# This class defined Extern used in Module file +# +# @param object: Inherited from object class +# +# +class ModuleExternClass(CommonClass): + def __init__(self): + self.EntryPoint = '' + self.UnloadImage = '' + self.Constructor = '' + self.Destructor = '' + CommonClass.__init__(self) + +## ModuleDepexClass +# +# This class defined depex item used in Module file +# +# @param CommonClass: Inherited from CommonClass class +# @param DefineClass: Input value for DefineClass class +# +# @var Depex: To store value for Depex +# +class ModuleDepexClass(CommonClass, DefineClass): + def __init__(self): + CommonClass.__init__(self) + DefineClass.__init__(self) + self.Depex = '' + +## ModuleNmakeClass +# +# This class defined nmake item used in Module file +# +# @param CommonClass: Inherited from CommonClass class +# +# @var Name: To store value for Name +# @var Value: To store value for Value +# +class ModuleNmakeClass(CommonClass): + def __init__(self): + CommonClass.__init__(self) + self.Name = '' + self.Value = '' + +## ModuleClass +# +# This class defined a complete module item +# +# @param object: Inherited from object class +# +# @var Header: To store value for Header, it is a structure as +# {Arch : ModuleHeaderClass} +# @var LibraryClasses: To store value for LibraryClasses, it is a list structure as +# [ LibraryClassClass, ...] +# @var Libraries: To store value for Libraries, it is a list structure as +# [ ModuleLibraryClass, ...] +# @var Sources: To store value for Sources, it is a list structure as +# [ ModuleSourceFileClass, ...] +# @var Binaries: To store value for Binaries, it is a list structure as +# [ ModuleBinaryFileClass, ...] +# @var NonProcessedFiles: To store value for NonProcessedFiles, it is a list structure as +# [ '', '', ...] +# @var PackageDependencies: To store value for PackageDependencies, it is a list structure as +# [ ModulePackageDependencyClass, ... ] +# @var Nmake: To store value for Nmake, it is a list structure as +# [ ModuleNmakeClass, ... ] +# @var Depex: To store value for Depex, it is a list structure as +# [ ModuleDepexClass, ... ] +# @var Includes: To store value for Includes, it is a list structure as +# [ IncludeClass, ...] +# @var Protocols: To store value for Protocols, it is a list structure as +# [ ProtocolClass, ...] +# @var Ppis: To store value for Ppis, it is a list structure as +# [ PpiClass, ...] +# @var Events: To store value for Events, it is a list structure as +# [ ModuleEventClass, ...] +# @var Hobs: To store value for Hobs, it is a list structure as +# [ ModuleHobClass, ...] +# @var Variables: To store value for Variables, it is a list structure as +# [ ModuleVariableClass, ...] +# @var BootModes: To store value for BootModes, it is a list structure as +# [ ModuleBootModeClass, ...] +# @var SystemTables: To store value for SystemTables, it is a list structure as +# [ ModuleSystemTableClass, ...] +# @var DataHubs: To store value for DataHubs, it is a list structure as +# [ ModuleDataHubClass, ...] +# @var HiiPackages: To store value for HiiPackages, it is a list structure as +# [ ModuleHiiPackageClass, ...] +# @var Guids: To store value for Guids, it is a list structure as +# [ GuidClass, ...] +# @var PcdCodes: To store value for PcdCodes, it is a list structure as +# [ PcdClass, ...] +# @var ExternImages: To store value for ExternImages, it is a list structure as +# [ ModuleExternImageClass, ...] +# @var ExternLibraries: To store value for ExternLibraries, it is a list structure as +# [ ModuleExternLibraryClass, ...] +# @var ExternDrivers: To store value for ExternDrivers, it is a list structure as +# [ ModuleExternDriverClass, ...] +# @var ExternCallBacks: To store value for ExternCallBacks, it is a list structure as +# [ ModuleExternCallBackClass, ...] +# @var BuildOptions: To store value for BuildOptions, it is a list structure as +# [ BuildOptionClass, ...] +# @var UserExtensions: To store value for UserExtensions, it is a list structure as +# [ UserExtensionsClass, ...] +# +class ModuleClass(object): + def __init__(self): + self.Header = {} + self.ModuleHeader = ModuleHeaderClass() + self.LibraryClasses = [] + self.Libraries = [] + self.Sources = [] + self.Binaries = [] + self.NonProcessedFiles = [] + self.PackageDependencies = [] + self.Nmake = [] + self.Depex = [] + self.PeiDepex = None + self.DxeDepex = None + self.SmmDepex = None + self.Includes = [] + self.Protocols = [] + self.Ppis = [] + self.Events = [] + self.Hobs = [] + self.Variables = [] + self.BootModes = [] + self.SystemTables = [] + self.DataHubs = [] + self.HiiPackages = [] + self.Guids = [] + self.PcdCodes = [] + self.ExternImages = [] + self.ExternLibraries = [] + self.ExternDrivers = [] + self.ExternCallBacks = [] + self.Externs = [] + self.BuildOptions = [] + self.UserExtensions = None + self.MiscFiles = None + self.FileList = [] + +## +# +# This acts like the main() function for the script, unless it is 'import'ed into another +# script. +# +if __name__ == '__main__': + M = ModuleClass() diff --git a/BaseTools/Source/Python/CommonDataClass/PackageClass.py b/BaseTools/Source/Python/CommonDataClass/PackageClass.py new file mode 100644 index 0000000000..c064f25ddb --- /dev/null +++ b/BaseTools/Source/Python/CommonDataClass/PackageClass.py @@ -0,0 +1,127 @@ +## @file +# This file is used to define a class object to describe a package +# +# Copyright (c) 2007, 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. + +## +# Import Modules +# +from CommonClass import * +from Common.Misc import sdict + +## PackageHeaderClass +# +# This class defined header items used in Package file +# +# @param IdentificationClass: Inherited from IdentificationClass class +# @param CommonHeaderClass: Inherited from CommonHeaderClass class +# +# @var DecSpecification: To store value for DecSpecification +# @var ReadOnly: To store value for ReadOnly +# @var RePackage: To store value for RePackage +# @var ClonedFrom: To store value for ClonedFrom, it is a set structure as +# [ ClonedRecordClass, ...] +# +class PackageHeaderClass(IdentificationClass, CommonHeaderClass): + def __init__(self): + IdentificationClass.__init__(self) + CommonHeaderClass.__init__(self) + self.DecSpecification = '' + self.ReadOnly = False + self.RePackage = False + self.PackagePath = '' + self.ClonedFrom = [] + +## PackageIndustryStdHeaderClass +# +# This class defined industry std header items used in Package file +# +# @param CommonHeaderClass: Inherited from CommonHeaderClass class +# +# @var Name: To store value for Name +# @var IncludeHeader: To store value for IncludeHeader +# +class PackageIndustryStdHeaderClass(CommonClass): + def __init__(self): + self.Name = '' + self.IncludeHeader = '' + CommonClass.__init__(self) + +## PackageIncludePkgHeaderClass +# +# This class defined include Pkg header items used in Package file +# +# @param object: Inherited from object class +# +# @var IncludeHeader: To store value for IncludeHeader +# @var ModuleType: To store value for ModuleType, it is a set structure as +# 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 +# +class PackageIncludePkgHeaderClass(object): + def __init__(self): + self.IncludeHeader = '' + self.ModuleType = [] + +## PackageClass +# +# This class defined a complete package item +# +# @param object: Inherited from object class +# +# @var Header: To store value for Header, it is a structure as +# {Arch : PackageHeaderClass} +# @var Includes: To store value for Includes, it is a list structure as +# [ IncludeClass, ...] +# @var LibraryClassDeclarations: To store value for LibraryClassDeclarations, it is a list structure as +# [ LibraryClassClass, ...] +# @var IndustryStdHeaders: To store value for IndustryStdHeaders, it is a list structure as +# [ PackageIndustryStdHeader, ...] +# @var ModuleFiles: To store value for ModuleFiles, it is a list structure as +# [ '', '', ...] +# @var PackageIncludePkgHeaders: To store value for PackageIncludePkgHeaders, it is a list structure as +# [ PackageIncludePkgHeader, ...] +# @var GuidDeclarations: To store value for GuidDeclarations, it is a list structure as +# [ GuidClass, ...] +# @var ProtocolDeclarations: To store value for ProtocolDeclarations, it is a list structure as +# [ ProtocolClass, ...] +# @var PpiDeclarations: To store value for PpiDeclarations, it is a list structure as +# [ PpiClass, ...] +# @var PcdDeclarations: To store value for PcdDeclarations, it is a list structure as +# [ PcdClass, ...] +# @var UserExtensions: To store value for UserExtensions, it is a list structure as +# [ UserExtensionsClass, ...] +# +class PackageClass(object): + def __init__(self): + self.PackageHeader = PackageHeaderClass() + self.Header = {} + self.Includes = [] + self.LibraryClassDeclarations = [] + self.IndustryStdHeaders = [] + self.ModuleFiles = [] + # {[Guid, Value, Path(relative to WORKSPACE)]: ModuleClassObj} + self.Modules = sdict() + self.PackageIncludePkgHeaders = [] + self.GuidDeclarations = [] + self.ProtocolDeclarations = [] + self.PpiDeclarations = [] + self.PcdDeclarations = [] + self.PcdChecks = [] + self.UserExtensions = UserExtensionsClass() + self.MiscFiles = MiscFileClass() + self.FileList = [] + +## +# +# This acts like the main() function for the script, unless it is 'import'ed into another +# script. +# +if __name__ == '__main__': + P = PackageClass() diff --git a/BaseTools/Source/Python/CommonDataClass/PlatformClass.py b/BaseTools/Source/Python/CommonDataClass/PlatformClass.py new file mode 100644 index 0000000000..1966fb9f8c --- /dev/null +++ b/BaseTools/Source/Python/CommonDataClass/PlatformClass.py @@ -0,0 +1,432 @@ +## @file +# This file is used to define a class object to describe a platform +# +# Copyright (c) 2007, 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. + +## +# Import Modules +# +from CommonClass import * + +## SkuInfoListClass +# +# This class defined sku info list item used in platform file +# +# @param IncludeStatementClass: Inherited from IncludeStatementClass class +# +# @var SkuInfoList: To store value for SkuInfoList, it is a set structure as +# { SkuName : SkuId } +# +class SkuInfoListClass(IncludeStatementClass): + def __init__(self): + IncludeStatementClass.__init__(self) + self.SkuInfoList = {} + +## PlatformHeaderClass +# +# This class defined header items used in Platform file +# +# @param IdentificationClass: Inherited from IdentificationClass class +# @param CommonHeaderClass: Inherited from CommonHeaderClass class +# @param DefineClass: Inherited from DefineClass class +# +# @var DscSpecification: To store value for DscSpecification +# @var SupArchList: To store value for SupArchList, selection scope is in below list +# EBC | IA32 | X64 | IPF | ARM | PPC +# @var BuildTargets: To store value for BuildTargets, selection scope is in below list +# RELEASE | DEBUG +# @var IntermediateDirectories: To store value for IntermediateDirectories, selection scope is in below list +# MODULE | UNIFIED +# @var OutputDirectory: To store value for OutputDirectory +# @var ForceDebugTarget: To store value for ForceDebugTarget +# @var SkuIdName: To store value for SkuIdName +# @var BuildNumber: To store value for BuildNumber +# @var MakefileName: To store value for MakefileName +# @var ClonedFrom: To store value for ClonedFrom, it is a list structure as +# [ ClonedRecordClass, ... ] +# +class PlatformHeaderClass(IdentificationClass, CommonHeaderClass, DefineClass): + def __init__(self): + IdentificationClass.__init__(self) + CommonHeaderClass.__init__(self) + DefineClass.__init__(self) + self.DscSpecification = '' + self.SupArchList = [] + self.BuildTargets = [] + self.IntermediateDirectories = '' + self.OutputDirectory = '' + self.ForceDebugTarget = '' + self.SkuIdName = [] + self.BuildNumber = '' + self.MakefileName = '' + self.ClonedFrom = [] + +## PlatformFlashDefinitionFileClass +# +# This class defined FlashDefinitionFile item used in platform file +# +# @param object: Inherited from object class +# +# @var Id: To store value for Id +# @var UiName: To store value for UiName +# @var Preferred: To store value for Preferred +# @var FilePath: To store value for FilePath +# +class PlatformFlashDefinitionFileClass(object): + def __init__(self): + self.Id = '' + self.UiName = '' + self.Preferred = False + self.FilePath = '' + +## PlatformFvImageOptionClass +# +# This class defined FvImageOption item used in platform file +# +# @param object: Inherited from object class +# +# @var FvImageOptionName: To store value for FvImageOptionName +# @var FvImageOptionValues: To store value for FvImageOptionValues +# +class PlatformFvImageOptionClass(object): + def __init__(self): + self.FvImageOptionName = '' + self.FvImageOptionValues = [] + +## PlatformFvImageClass +# +# This class defined FvImage item used in platform file +# +# @param object: Inherited from object class +# +# @var Name: To store value for Name +# @var Value: To store value for Value +# @var Type: To store value for Type, selection scope is in below list +# Attributes | Options | Components | ImageName +# @var FvImageNames: To store value for FvImageNames +# @var FvImageOptions: To store value for FvImageOptions, it is a list structure as +# [ PlatformFvImageOption, ...] +# +class PlatformFvImageClass(object): + def __init__(self): + self.Name = '' + self.Value = '' + self.Type = '' + self.FvImageNames = [] + self.FvImageOptions = [] + +## PlatformFvImageNameClass +# +# This class defined FvImageName item used in platform file +# +# @param object: Inherited from object class +# +# @var Name: To store value for Name +# @var Type: To store value for Type, selection scope is in below list +# FV_MAIN | FV_MAIN_COMPACT | NV_STORAGE | FV_RECOVERY | FV_RECOVERY_FLOPPY | FV_FILE | CAPSULE_CARGO | NULL | USER_DEFINED +# @var FvImageOptions: To store value for FvImageOptions, it is a list structure as +# [ PlatformFvImageOption, ...] +# +class PlatformFvImageNameClass(object): + def __init__(self): + self.Name = '' + self.Type = '' + self.FvImageOptions = [] + +## PlatformFvImagesClass +# +# This class defined FvImages item used in platform file +# +# @param object: Inherited from object class +# +# @var FvImages: To store value for FvImages +# +class PlatformFvImagesClass(object): + def __init__(self): + self.FvImages = [] + +## PlatformAntTaskClass +# +# This class defined AntTask item used in platform file +# +# @param object: Inherited from object class +# +# @var Id: To store value for Id +# @var AntCmdOptions: To store value for AntCmdOptions +# @var FilePath: To store value for FilePath +# +class PlatformAntTaskClass(object): + def __init__(self): + self.Id = '' + self.AntCmdOptions = '' + self.FilePath = '' + +## PlatformFfsSectionClass +# +# This class defined FfsSection item used in platform file +# +# @param CommonClass: Inherited from CommonClass class +# +# @var BindingOrder: To store value for BindingOrder +# @var Compressible: To store value for Compressible +# @var SectionType: To store value for SectionType +# @var EncapsulationType: To store value for EncapsulationType +# @var ToolName: To store value for ToolName +# @var Filenames: To store value for Filenames +# @var Args: To store value for Args +# @var OutFile: To store value for OutFile +# @var OutputFileExtension: To store value for OutputFileExtension +# @var ToolNameElement: To store value for ToolNameElement +# +class PlatformFfsSectionClass(CommonClass): + def __init__(self): + CommonClass.__init__(self) + self.BindingOrder = '' + self.Compressible = '' + self.SectionType = '' + self.EncapsulationType = '' + self.ToolName = '' + self.Filenames = [] + self.Args = '' + self.OutFile = '' + self.OutputFileExtension = '' + self.ToolNameElement = '' + +## PlatformFfsSectionsClass +# +# This class defined FfsSections item used in platform file +# +# @param CommonClass: Inherited from CommonClass class +# +# @var BindingOrder: To store value for BindingOrder +# @var Compressible: To store value for Compressible +# @var SectionType: To store value for SectionType +# @var EncapsulationType: To store value for EncapsulationType +# @var ToolName: To store value for ToolName +# @var Section: To store value for Section, it is a list structure as +# [ PlatformFfsSectionClass, ... ] +# @var Sections: To store value for Sections, it is a list structure as +# [ PlatformFfsSectionsClass, ...] +# +class PlatformFfsSectionsClass(CommonClass): + def __init__(self): + CommonClass.__init__(self) + self.BindingOrder = '' + self.Compressible = '' + self.SectionType = '' + self.EncapsulationType = '' + self.ToolName = '' + self.Section = [] + self.Sections = [] + +## PlatformFfsClass +# +# This class defined Ffs item used in platform file +# +# @param object: Inherited from object class +# +# @var Attribute: To store value for Attribute, it is a set structure as +# { [(Name, PlatformFfsSectionsClass)] : Value} +# @var Sections: To store value for Sections, it is a list structure as +# [ PlatformFfsSectionsClass] +# @var ToolName: To store value for ToolName +# +class PlatformFfsClass(object): + def __init__(self): + self.Attribute = {} + self.Sections = [] + self.Key = '' + +## PlatformBuildOptionClass +# +# This class defined BuildOption item used in platform file +# +# @param object: Inherited from object class +# +# @var UserDefinedAntTasks: To store value for UserDefinedAntTasks, it is a set structure as +# { [Id] : PlatformAntTaskClass, ...} +# @var Options: To store value for Options, it is a list structure as +# [ BuildOptionClass, ...] +# @var UserExtensions: To store value for UserExtensions, it is a set structure as +# { [(UserID, Identifier)] : UserExtensionsClass, ...} +# @var FfsKeyList: To store value for FfsKeyList, it is a set structure as +# { [FfsKey]: PlatformFfsClass, ...} +# +class PlatformBuildOptionClass(object): + def __init__(self): + self.UserDefinedAntTasks = {} + self.Options = [] + self.UserExtensions = {} + self.FfsKeyList = {} + +## PlatformBuildOptionClasses +# +# This class defined BuildOption item list used in platform file +# +# @param IncludeStatementClass: Inherited from IncludeStatementClass class +# +# @var FvBinding: To store value for FvBinding +# @var FfsFileNameGuid: To store value for FfsFileNameGuid +# @var FfsFormatKey: To store value for FfsFormatKey +# @var BuildOptionList: To store value for BuildOptionList, it is a list structure as +# [ BuildOptionClass, ... ] +# +class PlatformBuildOptionClasses(IncludeStatementClass): + def __init__(self): + IncludeStatementClass.__init__(self) + self.FvBinding = '' + self.FfsFileNameGuid = '' + self.FfsFormatKey = '' + self.BuildOptionList = [] + +## PlatformLibraryClass +# +# This class defined Library item used in platform file +# +# @param CommonClass: Inherited from CommonClass class +# @param DefineClass: Inherited from DefineClass class +# @param Name: Input value for Name, default is '' +# @param FilePath: Input value for FilePath, default is '' +# +# @var Name: To store value for Name +# @var FilePath: To store value for FilePath +# @var ModuleType: To store value for ModuleType +# @var SupModuleList: To store value for SupModuleList +# @var ModuleGuid: To store value for ModuleGuid +# @var ModuleVersion: To store value for ModuleVersion +# @var PackageGuid: To store value for PackageGuid +# @var PackageVersion: To store value for PackageVersion +# +class PlatformLibraryClass(CommonClass, DefineClass): + def __init__(self, Name = '', FilePath = ''): + CommonClass.__init__(self) + DefineClass.__init__(self) + self.Name = Name + self.FilePath = FilePath + self.ModuleType = [] + self.SupModuleList = [] + self.ModuleGuid = '' + self.ModuleVersion = '' + self.PackageGuid = '' + self.PackageVersion = '' + +## PlatformLibraryClasses +# +# This class defined Library item list used in platform file +# +# @param IncludeStatementClass: Inherited from IncludeStatementClass class +# +# @var LibraryList: To store value for LibraryList, it is a list structure as +# [ PlatformLibraryClass, ... ] +# +class PlatformLibraryClasses(IncludeStatementClass): + def __init__(self): + IncludeStatementClass.__init__(self) + self.LibraryList = [] + +## PlatformModuleClass +# +# This class defined Module item used in platform file +# +# @param CommonClass: Inherited from CommonClass class +# @param DefineClass: Inherited from DefineClass class +# @param IncludeStatementClass: Inherited from IncludeStatementClass class +# +# @var Name: To store value for Name (Library name or libraryclass name or module name) +# @var FilePath: To store value for FilePath +# @var Type: To store value for Type, selection scope is in below list +# LIBRARY | LIBRARY_CLASS | MODULE +# @var ModuleType: To store value for ModuleType +# @var ExecFilePath: To store value for ExecFilePath +# @var LibraryClasses: To store value for LibraryClasses, it is a structure as +# PlatformLibraryClasses +# @var PcdBuildDefinitions: To store value for PcdBuildDefinitions, it is a list structure as +# [ PcdClass, ...] +# @var ModuleSaBuildOption: To store value for ModuleSaBuildOption, it is a structure as +# PlatformBuildOptionClasses +# @var Specifications: To store value for Specifications, it is a list structure as +# [ '', '', ...] +# +class PlatformModuleClass(CommonClass, DefineClass, IncludeStatementClass): + def __init__(self): + CommonClass.__init__(self) + DefineClass.__init__(self) + self.Name = '' + self.FilePath = '' + self.Type = '' + self.ModuleType = '' + self.ExecFilePath = '' + self.LibraryClasses = PlatformLibraryClasses() + self.PcdBuildDefinitions = [] + self.ModuleSaBuildOption = PlatformBuildOptionClasses() + self.Specifications = [] + self.SourceOverridePath = '' + +## PlatformModuleClasses +# +# This class defined Module item list used in platform file +# +# @param IncludeStatementClass: Inherited from IncludeStatementClass class +# +# @var ModuleList: To store value for ModuleList, it is a list structure as +# [ PlatformModuleClass, ... ] +# +class PlatformModuleClasses(IncludeStatementClass): + def __init__(self): + IncludeStatementClass.__init__(self) + self.ModuleList = [] + +## PlatformClass +# +# This class defined a complete platform item +# +# @param object: Inherited from object class +# +# @var Header: To store value for Header, it is a structure as +# {Arch : PlatformHeaderClass()} +# @var SkuInfos: To store value for SkuInfos, it is a structure as +# SkuInfoListClass +# @var Libraries: To store value for Libraries, it is a structure as +# PlatformLibraryClasses +# @var LibraryClasses: To store value for LibraryClasses, it is a structure as +# PlatformLibraryClasses +# @var Modules: To store value for Modules, it is a structure as +# PlatformModuleClasses +# @var FlashDefinitionFile: To store value for FlashDefinitionFile, it is a structure as +# PlatformFlashDefinitionFileClass +# @var BuildOptions: To store value for BuildOptions, it is a structure as +# PlatformBuildOptionClasses +# @var DynamicPcdBuildDefinitions: To store value for DynamicPcdBuildDefinitions, it is a list structure as +# [ PcdClass, ...] +# @var Fdf: To store value for Fdf, it is a list structure as +# [ FdfClass, ...] +# @var UserExtensions: To store value for UserExtensions, it is a list structure as +# [ UserExtensionsClass, ...] +# +class PlatformClass(object): + def __init__(self): + self.Header = {} + self.SkuInfos = SkuInfoListClass() + self.Libraries = PlatformLibraryClasses() + self.LibraryClasses = PlatformLibraryClasses() + self.Modules = PlatformModuleClasses() + self.FlashDefinitionFile = PlatformFlashDefinitionFileClass() + self.BuildOptions = PlatformBuildOptionClasses() + self.DynamicPcdBuildDefinitions = [] + self.Fdf = [] + self.UserExtensions = [] + +## +# +# This acts like the main() function for the script, unless it is 'import'ed into another +# script. +# +if __name__ == '__main__': + P = PlatformClass() diff --git a/BaseTools/Source/Python/CommonDataClass/__init__.py b/BaseTools/Source/Python/CommonDataClass/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/BaseTools/Source/Python/Ecc/C.g b/BaseTools/Source/Python/Ecc/C.g new file mode 100644 index 0000000000..6aa50460de --- /dev/null +++ b/BaseTools/Source/Python/Ecc/C.g @@ -0,0 +1,626 @@ + +grammar C; +options { + language=Python; + backtrack=true; + memoize=true; + k=2; +} + +@header { + import CodeFragment + import FileProfile +} + +@members { + + def printTokenInfo(self, line, offset, tokenText): + print str(line)+ ',' + str(offset) + ':' + str(tokenText) + + def StorePredicateExpression(self, StartLine, StartOffset, EndLine, EndOffset, Text): + PredExp = CodeFragment.PredicateExpression(Text, (StartLine, StartOffset), (EndLine, EndOffset)) + FileProfile.PredicateExpressionList.append(PredExp) + + def StoreEnumerationDefinition(self, StartLine, StartOffset, EndLine, EndOffset, Text): + EnumDef = CodeFragment.EnumerationDefinition(Text, (StartLine, StartOffset), (EndLine, EndOffset)) + FileProfile.EnumerationDefinitionList.append(EnumDef) + + def StoreStructUnionDefinition(self, StartLine, StartOffset, EndLine, EndOffset, Text): + SUDef = CodeFragment.StructUnionDefinition(Text, (StartLine, StartOffset), (EndLine, EndOffset)) + FileProfile.StructUnionDefinitionList.append(SUDef) + + def StoreTypedefDefinition(self, StartLine, StartOffset, EndLine, EndOffset, FromText, ToText): + Tdef = CodeFragment.TypedefDefinition(FromText, ToText, (StartLine, StartOffset), (EndLine, EndOffset)) + FileProfile.TypedefDefinitionList.append(Tdef) + + def StoreFunctionDefinition(self, StartLine, StartOffset, EndLine, EndOffset, ModifierText, DeclText, LeftBraceLine, LeftBraceOffset, DeclLine, DeclOffset): + FuncDef = CodeFragment.FunctionDefinition(ModifierText, DeclText, (StartLine, StartOffset), (EndLine, EndOffset), (LeftBraceLine, LeftBraceOffset), (DeclLine, DeclOffset)) + FileProfile.FunctionDefinitionList.append(FuncDef) + + def StoreVariableDeclaration(self, StartLine, StartOffset, EndLine, EndOffset, ModifierText, DeclText): + VarDecl = CodeFragment.VariableDeclaration(ModifierText, DeclText, (StartLine, StartOffset), (EndLine, EndOffset)) + FileProfile.VariableDeclarationList.append(VarDecl) + + def StoreFunctionCalling(self, StartLine, StartOffset, EndLine, EndOffset, FuncName, ParamList): + FuncCall = CodeFragment.FunctionCalling(FuncName, ParamList, (StartLine, StartOffset), (EndLine, EndOffset)) + FileProfile.FunctionCallingList.append(FuncCall) + +} + +translation_unit + : external_declaration* + ; + + +/*function_declaration +@after{ + print $function_declaration.text +} + : declaration_specifiers IDENTIFIER '(' parameter_list ')' ';' + ; +*/ +external_declaration +options {k=1;} +/*@after{ + print $external_declaration.text +}*/ + : ( declaration_specifiers? declarator declaration* '{' )=> function_definition + | declaration + | macro_statement (';')? + ; + + + +function_definition +scope { + ModifierText; + DeclText; + LBLine; + LBOffset; + DeclLine; + DeclOffset; +} +@init { + $function_definition::ModifierText = ''; + $function_definition::DeclText = ''; + $function_definition::LBLine = 0; + $function_definition::LBOffset = 0; + $function_definition::DeclLine = 0; + $function_definition::DeclOffset = 0; +} +@after{ + self.StoreFunctionDefinition($function_definition.start.line, $function_definition.start.charPositionInLine, $function_definition.stop.line, $function_definition.stop.charPositionInLine, $function_definition::ModifierText, $function_definition::DeclText, $function_definition::LBLine, $function_definition::LBOffset, $function_definition::DeclLine, $function_definition::DeclOffset) +} + : d=declaration_specifiers? declarator + ( declaration+ a=compound_statement // K&R style + | b=compound_statement // ANSI style + ) { + if d != None: + $function_definition::ModifierText = $declaration_specifiers.text + else: + $function_definition::ModifierText = '' + $function_definition::DeclText = $declarator.text + $function_definition::DeclLine = $declarator.start.line + $function_definition::DeclOffset = $declarator.start.charPositionInLine + if a != None: + $function_definition::LBLine = $a.start.line + $function_definition::LBOffset = $a.start.charPositionInLine + else: + $function_definition::LBLine = $b.start.line + $function_definition::LBOffset = $b.start.charPositionInLine + } + ; + +declaration + : a='typedef' b=declaration_specifiers? + c=init_declarator_list d=';' + { + if b != None: + self.StoreTypedefDefinition($a.line, $a.charPositionInLine, $d.line, $d.charPositionInLine, $b.text, $c.text) + else: + self.StoreTypedefDefinition($a.line, $a.charPositionInLine, $d.line, $d.charPositionInLine, '', $c.text) + } + | s=declaration_specifiers t=init_declarator_list? e=';' + { + if t != None: + self.StoreVariableDeclaration($s.start.line, $s.start.charPositionInLine, $t.start.line, $t.start.charPositionInLine, $s.text, $t.text) + } + ; + +declaration_specifiers + : ( storage_class_specifier + | type_specifier + | type_qualifier + )+ + ; + +init_declarator_list + : init_declarator (',' init_declarator)* + ; + +init_declarator + : declarator ('=' initializer)? + ; + +storage_class_specifier + : 'extern' + | 'static' + | 'auto' + | 'register' + | 'STATIC' + ; + +type_specifier + : 'void' + | 'char' + | 'short' + | 'int' + | 'long' + | 'float' + | 'double' + | 'signed' + | 'unsigned' + | s=struct_or_union_specifier + { + if s.stop != None: + self.StoreStructUnionDefinition($s.start.line, $s.start.charPositionInLine, $s.stop.line, $s.stop.charPositionInLine, $s.text) + } + | e=enum_specifier + { + if e.stop != None: + self.StoreEnumerationDefinition($e.start.line, $e.start.charPositionInLine, $e.stop.line, $e.stop.charPositionInLine, $e.text) + } + | (IDENTIFIER type_qualifier* declarator)=> type_id + ; + +type_id + : IDENTIFIER + //{self.printTokenInfo($a.line, $a.pos, $a.text)} + ; + +struct_or_union_specifier +options {k=3;} + : struct_or_union IDENTIFIER? '{' struct_declaration_list '}' + | struct_or_union IDENTIFIER + ; + +struct_or_union + : 'struct' + | 'union' + ; + +struct_declaration_list + : struct_declaration+ + ; + +struct_declaration + : specifier_qualifier_list struct_declarator_list ';' + ; + +specifier_qualifier_list + : ( type_qualifier | type_specifier )+ + ; + +struct_declarator_list + : struct_declarator (',' struct_declarator)* + ; + +struct_declarator + : declarator (':' constant_expression)? + | ':' constant_expression + ; + +enum_specifier +options {k=3;} + : 'enum' '{' enumerator_list ','? '}' + | 'enum' IDENTIFIER '{' enumerator_list ','? '}' + | 'enum' IDENTIFIER + ; + +enumerator_list + : enumerator (',' enumerator)* + ; + +enumerator + : IDENTIFIER ('=' constant_expression)? + ; + +type_qualifier + : 'const' + | 'volatile' + | 'IN' + | 'OUT' + | 'OPTIONAL' + | 'CONST' + | 'UNALIGNED' + | 'VOLATILE' + | 'GLOBAL_REMOVE_IF_UNREFERENCED' + | 'EFIAPI' + | 'EFI_BOOTSERVICE' + | 'EFI_RUNTIMESERVICE' + ; + +declarator + : pointer? ('EFIAPI')? ('EFI_BOOTSERVICE')? ('EFI_RUNTIMESERVICE')? direct_declarator +// | ('EFIAPI')? ('EFI_BOOTSERVICE')? ('EFI_RUNTIMESERVICE')? pointer? direct_declarator + | pointer + ; + +direct_declarator + : IDENTIFIER declarator_suffix* + | '(' ('EFIAPI')? declarator ')' declarator_suffix+ + ; + +declarator_suffix + : '[' constant_expression ']' + | '[' ']' + | '(' parameter_type_list ')' + | '(' identifier_list ')' + | '(' ')' + ; + +pointer + : '*' type_qualifier+ pointer? + | '*' pointer + | '*' + ; + +parameter_type_list + : parameter_list (',' ('OPTIONAL')? '...')? + ; + +parameter_list + : parameter_declaration (',' ('OPTIONAL')? parameter_declaration)* + ; + +parameter_declaration + : declaration_specifiers (declarator|abstract_declarator)* ('OPTIONAL')? + //accomerdate user-defined type only, no declarator follow. + | pointer* IDENTIFIER + ; + +identifier_list + : IDENTIFIER + (',' IDENTIFIER)* + ; + +type_name + : specifier_qualifier_list abstract_declarator? + | type_id + ; + +abstract_declarator + : pointer direct_abstract_declarator? + | direct_abstract_declarator + ; + +direct_abstract_declarator + : ( '(' abstract_declarator ')' | abstract_declarator_suffix ) abstract_declarator_suffix* + ; + +abstract_declarator_suffix + : '[' ']' + | '[' constant_expression ']' + | '(' ')' + | '(' parameter_type_list ')' + ; + +initializer + + : assignment_expression + | '{' initializer_list ','? '}' + ; + +initializer_list + : initializer (',' initializer )* + ; + +// E x p r e s s i o n s + +argument_expression_list + : assignment_expression ('OPTIONAL')? (',' assignment_expression ('OPTIONAL')?)* + ; + +additive_expression + : (multiplicative_expression) ('+' multiplicative_expression | '-' multiplicative_expression)* + ; + +multiplicative_expression + : (cast_expression) ('*' cast_expression | '/' cast_expression | '%' cast_expression)* + ; + +cast_expression + : '(' type_name ')' cast_expression + | unary_expression + ; + +unary_expression + : postfix_expression + | '++' unary_expression + | '--' unary_expression + | unary_operator cast_expression + | 'sizeof' unary_expression + | 'sizeof' '(' type_name ')' + ; + +postfix_expression +scope { + FuncCallText; +} +@init { + $postfix_expression::FuncCallText = ''; +} + : p=primary_expression {$postfix_expression::FuncCallText += $p.text} + ( '[' expression ']' + | '(' a=')'{self.StoreFunctionCalling($p.start.line, $p.start.charPositionInLine, $a.line, $a.charPositionInLine, $postfix_expression::FuncCallText, '')} + | '(' c=argument_expression_list b=')' {self.StoreFunctionCalling($p.start.line, $p.start.charPositionInLine, $b.line, $b.charPositionInLine, $postfix_expression::FuncCallText, $c.text)} + | '(' macro_parameter_list ')' + | '.' x=IDENTIFIER {$postfix_expression::FuncCallText += '.' + $x.text} + | '*' y=IDENTIFIER {$postfix_expression::FuncCallText = $y.text} + | '->' z=IDENTIFIER {$postfix_expression::FuncCallText += '->' + $z.text} + | '++' + | '--' + )* + ; + +macro_parameter_list + : parameter_declaration (',' parameter_declaration)* + ; + +unary_operator + : '&' + | '*' + | '+' + | '-' + | '~' + | '!' + ; + +primary_expression + : IDENTIFIER + | constant + | '(' expression ')' + ; + +constant + : HEX_LITERAL + | OCTAL_LITERAL + | DECIMAL_LITERAL + | CHARACTER_LITERAL + | (IDENTIFIER* STRING_LITERAL+)+ IDENTIFIER* + | FLOATING_POINT_LITERAL + ; + +///// + +expression + : assignment_expression (',' assignment_expression)* + ; + +constant_expression + : conditional_expression + ; + +assignment_expression + : lvalue assignment_operator assignment_expression + | conditional_expression + ; + +lvalue + : unary_expression + ; + +assignment_operator + : '=' + | '*=' + | '/=' + | '%=' + | '+=' + | '-=' + | '<<=' + | '>>=' + | '&=' + | '^=' + | '|=' + ; + +conditional_expression + : e=logical_or_expression ('?' expression ':' conditional_expression {self.StorePredicateExpression($e.start.line, $e.start.charPositionInLine, $e.stop.line, $e.stop.charPositionInLine, $e.text)})? + ; + +logical_or_expression + : logical_and_expression ('||' logical_and_expression)* + ; + +logical_and_expression + : inclusive_or_expression ('&&' inclusive_or_expression)* + ; + +inclusive_or_expression + : exclusive_or_expression ('|' exclusive_or_expression)* + ; + +exclusive_or_expression + : and_expression ('^' and_expression)* + ; + +and_expression + : equality_expression ('&' equality_expression)* + ; +equality_expression + : relational_expression (('=='|'!=') relational_expression )* + ; + +relational_expression + : shift_expression (('<'|'>'|'<='|'>=') shift_expression)* + ; + +shift_expression + : additive_expression (('<<'|'>>') additive_expression)* + ; + +// S t a t e m e n t s + +statement + : labeled_statement + | compound_statement + | expression_statement + | selection_statement + | iteration_statement + | jump_statement + | macro_statement + | asm2_statement + | asm1_statement + | asm_statement + | declaration + ; + +asm2_statement + : '__asm__'? IDENTIFIER '(' (~(';'))* ')' ';' + ; + +asm1_statement + : '_asm' '{' (~('}'))* '}' + ; + +asm_statement + : '__asm' '{' (~('}'))* '}' + ; + +macro_statement + : IDENTIFIER '(' declaration* statement_list? expression? ')' + ; + +labeled_statement + : IDENTIFIER ':' statement + | 'case' constant_expression ':' statement + | 'default' ':' statement + ; + +compound_statement + : '{' declaration* statement_list? '}' + ; + +statement_list + : statement+ + ; + +expression_statement + : ';' + | expression ';' + ; + +selection_statement + : 'if' '(' e=expression ')' {self.StorePredicateExpression($e.start.line, $e.start.charPositionInLine, $e.stop.line, $e.stop.charPositionInLine, $e.text)} statement (options {k=1; backtrack=false;}:'else' statement)? + | 'switch' '(' expression ')' statement + ; + +iteration_statement + : 'while' '(' e=expression ')' statement {self.StorePredicateExpression($e.start.line, $e.start.charPositionInLine, $e.stop.line, $e.stop.charPositionInLine, $e.text)} + | 'do' statement 'while' '(' e=expression ')' ';' {self.StorePredicateExpression($e.start.line, $e.start.charPositionInLine, $e.stop.line, $e.stop.charPositionInLine, $e.text)} + | 'for' '(' expression_statement e=expression_statement expression? ')' statement {self.StorePredicateExpression($e.start.line, $e.start.charPositionInLine, $e.stop.line, $e.stop.charPositionInLine, $e.text)} + ; + +jump_statement + : 'goto' IDENTIFIER ';' + | 'continue' ';' + | 'break' ';' + | 'return' ';' + | 'return' expression ';' + ; + +IDENTIFIER + : LETTER (LETTER|'0'..'9')* + ; + +fragment +LETTER + : '$' + | 'A'..'Z' + | 'a'..'z' + | '_' + ; + +CHARACTER_LITERAL + : ('L')? '\'' ( EscapeSequence | ~('\''|'\\') ) '\'' + ; + +STRING_LITERAL + : ('L')? '"' ( EscapeSequence | ~('\\'|'"') )* '"' + ; + +HEX_LITERAL : '0' ('x'|'X') HexDigit+ IntegerTypeSuffix? ; + +DECIMAL_LITERAL : ('0' | '1'..'9' '0'..'9'*) IntegerTypeSuffix? ; + +OCTAL_LITERAL : '0' ('0'..'7')+ IntegerTypeSuffix? ; + +fragment +HexDigit : ('0'..'9'|'a'..'f'|'A'..'F') ; + +fragment +IntegerTypeSuffix + : ('u'|'U') + | ('l'|'L') + | ('u'|'U') ('l'|'L') + | ('u'|'U') ('l'|'L') ('l'|'L') + ; + +FLOATING_POINT_LITERAL + : ('0'..'9')+ '.' ('0'..'9')* Exponent? FloatTypeSuffix? + | '.' ('0'..'9')+ Exponent? FloatTypeSuffix? + | ('0'..'9')+ Exponent FloatTypeSuffix? + | ('0'..'9')+ Exponent? FloatTypeSuffix + ; + +fragment +Exponent : ('e'|'E') ('+'|'-')? ('0'..'9')+ ; + +fragment +FloatTypeSuffix : ('f'|'F'|'d'|'D') ; + +fragment +EscapeSequence + : '\\' ('b'|'t'|'n'|'f'|'r'|'\"'|'\''|'\\') + | OctalEscape + ; + +fragment +OctalEscape + : '\\' ('0'..'3') ('0'..'7') ('0'..'7') + | '\\' ('0'..'7') ('0'..'7') + | '\\' ('0'..'7') + ; + +fragment +UnicodeEscape + : '\\' 'u' HexDigit HexDigit HexDigit HexDigit + ; + +WS : (' '|'\r'|'\t'|'\u000C'|'\n') {$channel=HIDDEN;} + ; + +// ingore '\' of line concatenation +BS : ('\\') {$channel=HIDDEN;} + ; + +// ingore function modifiers +//FUNC_MODIFIERS : 'EFIAPI' {$channel=HIDDEN;} +// ; + +UnicodeVocabulary + : '\u0003'..'\uFFFE' + ; +COMMENT + : '/*' ( options {greedy=false;} : . )* '*/' {$channel=HIDDEN;} + ; + + +LINE_COMMENT + : '//' ~('\n'|'\r')* '\r'? '\n' {$channel=HIDDEN;} + ; + +// ignore #line info for now +LINE_COMMAND + : '#' ~('\n'|'\r')* '\r'? '\n' {$channel=HIDDEN;} + ; diff --git a/BaseTools/Source/Python/Ecc/CLexer.py b/BaseTools/Source/Python/Ecc/CLexer.py new file mode 100644 index 0000000000..cc437e0821 --- /dev/null +++ b/BaseTools/Source/Python/Ecc/CLexer.py @@ -0,0 +1,4887 @@ +# $ANTLR 3.0.1 C.g 2009-02-16 16:02:51 + +from antlr3 import * +from antlr3.compat import set, frozenset + + +# for convenience in actions +HIDDEN = BaseRecognizer.HIDDEN + +# token types +T29=29 +HexDigit=13 +T70=70 +T74=74 +T85=85 +T102=102 +T114=114 +T103=103 +STRING_LITERAL=9 +T32=32 +T81=81 +T41=41 +FloatTypeSuffix=16 +T113=113 +T62=62 +T109=109 +DECIMAL_LITERAL=7 +IntegerTypeSuffix=14 +T68=68 +T73=73 +T84=84 +T33=33 +UnicodeVocabulary=21 +T78=78 +T115=115 +WS=19 +LINE_COMMAND=24 +T42=42 +T96=96 +T71=71 +LINE_COMMENT=23 +T72=72 +T94=94 +FLOATING_POINT_LITERAL=10 +T76=76 +UnicodeEscape=18 +T75=75 +T89=89 +T67=67 +T31=31 +T60=60 +T82=82 +T100=100 +T49=49 +IDENTIFIER=4 +T30=30 +CHARACTER_LITERAL=8 +T79=79 +T36=36 +T58=58 +T93=93 +T35=35 +T107=107 +OCTAL_LITERAL=6 +T83=83 +T61=61 +HEX_LITERAL=5 +T45=45 +T34=34 +T101=101 +T64=64 +T25=25 +T91=91 +T105=105 +T37=37 +T86=86 +T116=116 +EscapeSequence=12 +T26=26 +T51=51 +T111=111 +T46=46 +T77=77 +T38=38 +T106=106 +T112=112 +T69=69 +T39=39 +T44=44 +T55=55 +LETTER=11 +Exponent=15 +T95=95 +T50=50 +T110=110 +T108=108 +BS=20 +T92=92 +T43=43 +T28=28 +T40=40 +T66=66 +COMMENT=22 +T88=88 +T63=63 +T57=57 +T65=65 +T98=98 +T56=56 +T87=87 +T80=80 +T59=59 +T97=97 +T48=48 +T54=54 +EOF=-1 +T104=104 +T47=47 +Tokens=117 +T53=53 +OctalEscape=17 +T99=99 +T27=27 +T52=52 +T90=90 + +class CLexer(Lexer): + + grammarFileName = "C.g" + + def __init__(self, input=None): + Lexer.__init__(self, input) + self.dfa25 = self.DFA25( + self, 25, + eot = self.DFA25_eot, + eof = self.DFA25_eof, + min = self.DFA25_min, + max = self.DFA25_max, + accept = self.DFA25_accept, + special = self.DFA25_special, + transition = self.DFA25_transition + ) + self.dfa35 = self.DFA35( + self, 35, + eot = self.DFA35_eot, + eof = self.DFA35_eof, + min = self.DFA35_min, + max = self.DFA35_max, + accept = self.DFA35_accept, + special = self.DFA35_special, + transition = self.DFA35_transition + ) + + + + + + + # $ANTLR start T25 + def mT25(self, ): + + try: + self.type = T25 + + # C.g:7:5: ( ';' ) + # C.g:7:7: ';' + self.match(u';') + + + + + + finally: + + pass + + # $ANTLR end T25 + + + + # $ANTLR start T26 + def mT26(self, ): + + try: + self.type = T26 + + # C.g:8:5: ( 'typedef' ) + # C.g:8:7: 'typedef' + self.match("typedef") + + + + + + + finally: + + pass + + # $ANTLR end T26 + + + + # $ANTLR start T27 + def mT27(self, ): + + try: + self.type = T27 + + # C.g:9:5: ( ',' ) + # C.g:9:7: ',' + self.match(u',') + + + + + + finally: + + pass + + # $ANTLR end T27 + + + + # $ANTLR start T28 + def mT28(self, ): + + try: + self.type = T28 + + # C.g:10:5: ( '=' ) + # C.g:10:7: '=' + self.match(u'=') + + + + + + finally: + + pass + + # $ANTLR end T28 + + + + # $ANTLR start T29 + def mT29(self, ): + + try: + self.type = T29 + + # C.g:11:5: ( 'extern' ) + # C.g:11:7: 'extern' + self.match("extern") + + + + + + + finally: + + pass + + # $ANTLR end T29 + + + + # $ANTLR start T30 + def mT30(self, ): + + try: + self.type = T30 + + # C.g:12:5: ( 'static' ) + # C.g:12:7: 'static' + self.match("static") + + + + + + + finally: + + pass + + # $ANTLR end T30 + + + + # $ANTLR start T31 + def mT31(self, ): + + try: + self.type = T31 + + # C.g:13:5: ( 'auto' ) + # C.g:13:7: 'auto' + self.match("auto") + + + + + + + finally: + + pass + + # $ANTLR end T31 + + + + # $ANTLR start T32 + def mT32(self, ): + + try: + self.type = T32 + + # C.g:14:5: ( 'register' ) + # C.g:14:7: 'register' + self.match("register") + + + + + + + finally: + + pass + + # $ANTLR end T32 + + + + # $ANTLR start T33 + def mT33(self, ): + + try: + self.type = T33 + + # C.g:15:5: ( 'STATIC' ) + # C.g:15:7: 'STATIC' + self.match("STATIC") + + + + + + + finally: + + pass + + # $ANTLR end T33 + + + + # $ANTLR start T34 + def mT34(self, ): + + try: + self.type = T34 + + # C.g:16:5: ( 'void' ) + # C.g:16:7: 'void' + self.match("void") + + + + + + + finally: + + pass + + # $ANTLR end T34 + + + + # $ANTLR start T35 + def mT35(self, ): + + try: + self.type = T35 + + # C.g:17:5: ( 'char' ) + # C.g:17:7: 'char' + self.match("char") + + + + + + + finally: + + pass + + # $ANTLR end T35 + + + + # $ANTLR start T36 + def mT36(self, ): + + try: + self.type = T36 + + # C.g:18:5: ( 'short' ) + # C.g:18:7: 'short' + self.match("short") + + + + + + + finally: + + pass + + # $ANTLR end T36 + + + + # $ANTLR start T37 + def mT37(self, ): + + try: + self.type = T37 + + # C.g:19:5: ( 'int' ) + # C.g:19:7: 'int' + self.match("int") + + + + + + + finally: + + pass + + # $ANTLR end T37 + + + + # $ANTLR start T38 + def mT38(self, ): + + try: + self.type = T38 + + # C.g:20:5: ( 'long' ) + # C.g:20:7: 'long' + self.match("long") + + + + + + + finally: + + pass + + # $ANTLR end T38 + + + + # $ANTLR start T39 + def mT39(self, ): + + try: + self.type = T39 + + # C.g:21:5: ( 'float' ) + # C.g:21:7: 'float' + self.match("float") + + + + + + + finally: + + pass + + # $ANTLR end T39 + + + + # $ANTLR start T40 + def mT40(self, ): + + try: + self.type = T40 + + # C.g:22:5: ( 'double' ) + # C.g:22:7: 'double' + self.match("double") + + + + + + + finally: + + pass + + # $ANTLR end T40 + + + + # $ANTLR start T41 + def mT41(self, ): + + try: + self.type = T41 + + # C.g:23:5: ( 'signed' ) + # C.g:23:7: 'signed' + self.match("signed") + + + + + + + finally: + + pass + + # $ANTLR end T41 + + + + # $ANTLR start T42 + def mT42(self, ): + + try: + self.type = T42 + + # C.g:24:5: ( 'unsigned' ) + # C.g:24:7: 'unsigned' + self.match("unsigned") + + + + + + + finally: + + pass + + # $ANTLR end T42 + + + + # $ANTLR start T43 + def mT43(self, ): + + try: + self.type = T43 + + # C.g:25:5: ( '{' ) + # C.g:25:7: '{' + self.match(u'{') + + + + + + finally: + + pass + + # $ANTLR end T43 + + + + # $ANTLR start T44 + def mT44(self, ): + + try: + self.type = T44 + + # C.g:26:5: ( '}' ) + # C.g:26:7: '}' + self.match(u'}') + + + + + + finally: + + pass + + # $ANTLR end T44 + + + + # $ANTLR start T45 + def mT45(self, ): + + try: + self.type = T45 + + # C.g:27:5: ( 'struct' ) + # C.g:27:7: 'struct' + self.match("struct") + + + + + + + finally: + + pass + + # $ANTLR end T45 + + + + # $ANTLR start T46 + def mT46(self, ): + + try: + self.type = T46 + + # C.g:28:5: ( 'union' ) + # C.g:28:7: 'union' + self.match("union") + + + + + + + finally: + + pass + + # $ANTLR end T46 + + + + # $ANTLR start T47 + def mT47(self, ): + + try: + self.type = T47 + + # C.g:29:5: ( ':' ) + # C.g:29:7: ':' + self.match(u':') + + + + + + finally: + + pass + + # $ANTLR end T47 + + + + # $ANTLR start T48 + def mT48(self, ): + + try: + self.type = T48 + + # C.g:30:5: ( 'enum' ) + # C.g:30:7: 'enum' + self.match("enum") + + + + + + + finally: + + pass + + # $ANTLR end T48 + + + + # $ANTLR start T49 + def mT49(self, ): + + try: + self.type = T49 + + # C.g:31:5: ( 'const' ) + # C.g:31:7: 'const' + self.match("const") + + + + + + + finally: + + pass + + # $ANTLR end T49 + + + + # $ANTLR start T50 + def mT50(self, ): + + try: + self.type = T50 + + # C.g:32:5: ( 'volatile' ) + # C.g:32:7: 'volatile' + self.match("volatile") + + + + + + + finally: + + pass + + # $ANTLR end T50 + + + + # $ANTLR start T51 + def mT51(self, ): + + try: + self.type = T51 + + # C.g:33:5: ( 'IN' ) + # C.g:33:7: 'IN' + self.match("IN") + + + + + + + finally: + + pass + + # $ANTLR end T51 + + + + # $ANTLR start T52 + def mT52(self, ): + + try: + self.type = T52 + + # C.g:34:5: ( 'OUT' ) + # C.g:34:7: 'OUT' + self.match("OUT") + + + + + + + finally: + + pass + + # $ANTLR end T52 + + + + # $ANTLR start T53 + def mT53(self, ): + + try: + self.type = T53 + + # C.g:35:5: ( 'OPTIONAL' ) + # C.g:35:7: 'OPTIONAL' + self.match("OPTIONAL") + + + + + + + finally: + + pass + + # $ANTLR end T53 + + + + # $ANTLR start T54 + def mT54(self, ): + + try: + self.type = T54 + + # C.g:36:5: ( 'CONST' ) + # C.g:36:7: 'CONST' + self.match("CONST") + + + + + + + finally: + + pass + + # $ANTLR end T54 + + + + # $ANTLR start T55 + def mT55(self, ): + + try: + self.type = T55 + + # C.g:37:5: ( 'UNALIGNED' ) + # C.g:37:7: 'UNALIGNED' + self.match("UNALIGNED") + + + + + + + finally: + + pass + + # $ANTLR end T55 + + + + # $ANTLR start T56 + def mT56(self, ): + + try: + self.type = T56 + + # C.g:38:5: ( 'VOLATILE' ) + # C.g:38:7: 'VOLATILE' + self.match("VOLATILE") + + + + + + + finally: + + pass + + # $ANTLR end T56 + + + + # $ANTLR start T57 + def mT57(self, ): + + try: + self.type = T57 + + # C.g:39:5: ( 'GLOBAL_REMOVE_IF_UNREFERENCED' ) + # C.g:39:7: 'GLOBAL_REMOVE_IF_UNREFERENCED' + self.match("GLOBAL_REMOVE_IF_UNREFERENCED") + + + + + + + finally: + + pass + + # $ANTLR end T57 + + + + # $ANTLR start T58 + def mT58(self, ): + + try: + self.type = T58 + + # C.g:40:5: ( 'EFIAPI' ) + # C.g:40:7: 'EFIAPI' + self.match("EFIAPI") + + + + + + + finally: + + pass + + # $ANTLR end T58 + + + + # $ANTLR start T59 + def mT59(self, ): + + try: + self.type = T59 + + # C.g:41:5: ( 'EFI_BOOTSERVICE' ) + # C.g:41:7: 'EFI_BOOTSERVICE' + self.match("EFI_BOOTSERVICE") + + + + + + + finally: + + pass + + # $ANTLR end T59 + + + + # $ANTLR start T60 + def mT60(self, ): + + try: + self.type = T60 + + # C.g:42:5: ( 'EFI_RUNTIMESERVICE' ) + # C.g:42:7: 'EFI_RUNTIMESERVICE' + self.match("EFI_RUNTIMESERVICE") + + + + + + + finally: + + pass + + # $ANTLR end T60 + + + + # $ANTLR start T61 + def mT61(self, ): + + try: + self.type = T61 + + # C.g:43:5: ( '(' ) + # C.g:43:7: '(' + self.match(u'(') + + + + + + finally: + + pass + + # $ANTLR end T61 + + + + # $ANTLR start T62 + def mT62(self, ): + + try: + self.type = T62 + + # C.g:44:5: ( ')' ) + # C.g:44:7: ')' + self.match(u')') + + + + + + finally: + + pass + + # $ANTLR end T62 + + + + # $ANTLR start T63 + def mT63(self, ): + + try: + self.type = T63 + + # C.g:45:5: ( '[' ) + # C.g:45:7: '[' + self.match(u'[') + + + + + + finally: + + pass + + # $ANTLR end T63 + + + + # $ANTLR start T64 + def mT64(self, ): + + try: + self.type = T64 + + # C.g:46:5: ( ']' ) + # C.g:46:7: ']' + self.match(u']') + + + + + + finally: + + pass + + # $ANTLR end T64 + + + + # $ANTLR start T65 + def mT65(self, ): + + try: + self.type = T65 + + # C.g:47:5: ( '*' ) + # C.g:47:7: '*' + self.match(u'*') + + + + + + finally: + + pass + + # $ANTLR end T65 + + + + # $ANTLR start T66 + def mT66(self, ): + + try: + self.type = T66 + + # C.g:48:5: ( '...' ) + # C.g:48:7: '...' + self.match("...") + + + + + + + finally: + + pass + + # $ANTLR end T66 + + + + # $ANTLR start T67 + def mT67(self, ): + + try: + self.type = T67 + + # C.g:49:5: ( '+' ) + # C.g:49:7: '+' + self.match(u'+') + + + + + + finally: + + pass + + # $ANTLR end T67 + + + + # $ANTLR start T68 + def mT68(self, ): + + try: + self.type = T68 + + # C.g:50:5: ( '-' ) + # C.g:50:7: '-' + self.match(u'-') + + + + + + finally: + + pass + + # $ANTLR end T68 + + + + # $ANTLR start T69 + def mT69(self, ): + + try: + self.type = T69 + + # C.g:51:5: ( '/' ) + # C.g:51:7: '/' + self.match(u'/') + + + + + + finally: + + pass + + # $ANTLR end T69 + + + + # $ANTLR start T70 + def mT70(self, ): + + try: + self.type = T70 + + # C.g:52:5: ( '%' ) + # C.g:52:7: '%' + self.match(u'%') + + + + + + finally: + + pass + + # $ANTLR end T70 + + + + # $ANTLR start T71 + def mT71(self, ): + + try: + self.type = T71 + + # C.g:53:5: ( '++' ) + # C.g:53:7: '++' + self.match("++") + + + + + + + finally: + + pass + + # $ANTLR end T71 + + + + # $ANTLR start T72 + def mT72(self, ): + + try: + self.type = T72 + + # C.g:54:5: ( '--' ) + # C.g:54:7: '--' + self.match("--") + + + + + + + finally: + + pass + + # $ANTLR end T72 + + + + # $ANTLR start T73 + def mT73(self, ): + + try: + self.type = T73 + + # C.g:55:5: ( 'sizeof' ) + # C.g:55:7: 'sizeof' + self.match("sizeof") + + + + + + + finally: + + pass + + # $ANTLR end T73 + + + + # $ANTLR start T74 + def mT74(self, ): + + try: + self.type = T74 + + # C.g:56:5: ( '.' ) + # C.g:56:7: '.' + self.match(u'.') + + + + + + finally: + + pass + + # $ANTLR end T74 + + + + # $ANTLR start T75 + def mT75(self, ): + + try: + self.type = T75 + + # C.g:57:5: ( '->' ) + # C.g:57:7: '->' + self.match("->") + + + + + + + finally: + + pass + + # $ANTLR end T75 + + + + # $ANTLR start T76 + def mT76(self, ): + + try: + self.type = T76 + + # C.g:58:5: ( '&' ) + # C.g:58:7: '&' + self.match(u'&') + + + + + + finally: + + pass + + # $ANTLR end T76 + + + + # $ANTLR start T77 + def mT77(self, ): + + try: + self.type = T77 + + # C.g:59:5: ( '~' ) + # C.g:59:7: '~' + self.match(u'~') + + + + + + finally: + + pass + + # $ANTLR end T77 + + + + # $ANTLR start T78 + def mT78(self, ): + + try: + self.type = T78 + + # C.g:60:5: ( '!' ) + # C.g:60:7: '!' + self.match(u'!') + + + + + + finally: + + pass + + # $ANTLR end T78 + + + + # $ANTLR start T79 + def mT79(self, ): + + try: + self.type = T79 + + # C.g:61:5: ( '*=' ) + # C.g:61:7: '*=' + self.match("*=") + + + + + + + finally: + + pass + + # $ANTLR end T79 + + + + # $ANTLR start T80 + def mT80(self, ): + + try: + self.type = T80 + + # C.g:62:5: ( '/=' ) + # C.g:62:7: '/=' + self.match("/=") + + + + + + + finally: + + pass + + # $ANTLR end T80 + + + + # $ANTLR start T81 + def mT81(self, ): + + try: + self.type = T81 + + # C.g:63:5: ( '%=' ) + # C.g:63:7: '%=' + self.match("%=") + + + + + + + finally: + + pass + + # $ANTLR end T81 + + + + # $ANTLR start T82 + def mT82(self, ): + + try: + self.type = T82 + + # C.g:64:5: ( '+=' ) + # C.g:64:7: '+=' + self.match("+=") + + + + + + + finally: + + pass + + # $ANTLR end T82 + + + + # $ANTLR start T83 + def mT83(self, ): + + try: + self.type = T83 + + # C.g:65:5: ( '-=' ) + # C.g:65:7: '-=' + self.match("-=") + + + + + + + finally: + + pass + + # $ANTLR end T83 + + + + # $ANTLR start T84 + def mT84(self, ): + + try: + self.type = T84 + + # C.g:66:5: ( '<<=' ) + # C.g:66:7: '<<=' + self.match("<<=") + + + + + + + finally: + + pass + + # $ANTLR end T84 + + + + # $ANTLR start T85 + def mT85(self, ): + + try: + self.type = T85 + + # C.g:67:5: ( '>>=' ) + # C.g:67:7: '>>=' + self.match(">>=") + + + + + + + finally: + + pass + + # $ANTLR end T85 + + + + # $ANTLR start T86 + def mT86(self, ): + + try: + self.type = T86 + + # C.g:68:5: ( '&=' ) + # C.g:68:7: '&=' + self.match("&=") + + + + + + + finally: + + pass + + # $ANTLR end T86 + + + + # $ANTLR start T87 + def mT87(self, ): + + try: + self.type = T87 + + # C.g:69:5: ( '^=' ) + # C.g:69:7: '^=' + self.match("^=") + + + + + + + finally: + + pass + + # $ANTLR end T87 + + + + # $ANTLR start T88 + def mT88(self, ): + + try: + self.type = T88 + + # C.g:70:5: ( '|=' ) + # C.g:70:7: '|=' + self.match("|=") + + + + + + + finally: + + pass + + # $ANTLR end T88 + + + + # $ANTLR start T89 + def mT89(self, ): + + try: + self.type = T89 + + # C.g:71:5: ( '?' ) + # C.g:71:7: '?' + self.match(u'?') + + + + + + finally: + + pass + + # $ANTLR end T89 + + + + # $ANTLR start T90 + def mT90(self, ): + + try: + self.type = T90 + + # C.g:72:5: ( '||' ) + # C.g:72:7: '||' + self.match("||") + + + + + + + finally: + + pass + + # $ANTLR end T90 + + + + # $ANTLR start T91 + def mT91(self, ): + + try: + self.type = T91 + + # C.g:73:5: ( '&&' ) + # C.g:73:7: '&&' + self.match("&&") + + + + + + + finally: + + pass + + # $ANTLR end T91 + + + + # $ANTLR start T92 + def mT92(self, ): + + try: + self.type = T92 + + # C.g:74:5: ( '|' ) + # C.g:74:7: '|' + self.match(u'|') + + + + + + finally: + + pass + + # $ANTLR end T92 + + + + # $ANTLR start T93 + def mT93(self, ): + + try: + self.type = T93 + + # C.g:75:5: ( '^' ) + # C.g:75:7: '^' + self.match(u'^') + + + + + + finally: + + pass + + # $ANTLR end T93 + + + + # $ANTLR start T94 + def mT94(self, ): + + try: + self.type = T94 + + # C.g:76:5: ( '==' ) + # C.g:76:7: '==' + self.match("==") + + + + + + + finally: + + pass + + # $ANTLR end T94 + + + + # $ANTLR start T95 + def mT95(self, ): + + try: + self.type = T95 + + # C.g:77:5: ( '!=' ) + # C.g:77:7: '!=' + self.match("!=") + + + + + + + finally: + + pass + + # $ANTLR end T95 + + + + # $ANTLR start T96 + def mT96(self, ): + + try: + self.type = T96 + + # C.g:78:5: ( '<' ) + # C.g:78:7: '<' + self.match(u'<') + + + + + + finally: + + pass + + # $ANTLR end T96 + + + + # $ANTLR start T97 + def mT97(self, ): + + try: + self.type = T97 + + # C.g:79:5: ( '>' ) + # C.g:79:7: '>' + self.match(u'>') + + + + + + finally: + + pass + + # $ANTLR end T97 + + + + # $ANTLR start T98 + def mT98(self, ): + + try: + self.type = T98 + + # C.g:80:5: ( '<=' ) + # C.g:80:7: '<=' + self.match("<=") + + + + + + + finally: + + pass + + # $ANTLR end T98 + + + + # $ANTLR start T99 + def mT99(self, ): + + try: + self.type = T99 + + # C.g:81:5: ( '>=' ) + # C.g:81:7: '>=' + self.match(">=") + + + + + + + finally: + + pass + + # $ANTLR end T99 + + + + # $ANTLR start T100 + def mT100(self, ): + + try: + self.type = T100 + + # C.g:82:6: ( '<<' ) + # C.g:82:8: '<<' + self.match("<<") + + + + + + + finally: + + pass + + # $ANTLR end T100 + + + + # $ANTLR start T101 + def mT101(self, ): + + try: + self.type = T101 + + # C.g:83:6: ( '>>' ) + # C.g:83:8: '>>' + self.match(">>") + + + + + + + finally: + + pass + + # $ANTLR end T101 + + + + # $ANTLR start T102 + def mT102(self, ): + + try: + self.type = T102 + + # C.g:84:6: ( '__asm__' ) + # C.g:84:8: '__asm__' + self.match("__asm__") + + + + + + + finally: + + pass + + # $ANTLR end T102 + + + + # $ANTLR start T103 + def mT103(self, ): + + try: + self.type = T103 + + # C.g:85:6: ( '_asm' ) + # C.g:85:8: '_asm' + self.match("_asm") + + + + + + + finally: + + pass + + # $ANTLR end T103 + + + + # $ANTLR start T104 + def mT104(self, ): + + try: + self.type = T104 + + # C.g:86:6: ( '__asm' ) + # C.g:86:8: '__asm' + self.match("__asm") + + + + + + + finally: + + pass + + # $ANTLR end T104 + + + + # $ANTLR start T105 + def mT105(self, ): + + try: + self.type = T105 + + # C.g:87:6: ( 'case' ) + # C.g:87:8: 'case' + self.match("case") + + + + + + + finally: + + pass + + # $ANTLR end T105 + + + + # $ANTLR start T106 + def mT106(self, ): + + try: + self.type = T106 + + # C.g:88:6: ( 'default' ) + # C.g:88:8: 'default' + self.match("default") + + + + + + + finally: + + pass + + # $ANTLR end T106 + + + + # $ANTLR start T107 + def mT107(self, ): + + try: + self.type = T107 + + # C.g:89:6: ( 'if' ) + # C.g:89:8: 'if' + self.match("if") + + + + + + + finally: + + pass + + # $ANTLR end T107 + + + + # $ANTLR start T108 + def mT108(self, ): + + try: + self.type = T108 + + # C.g:90:6: ( 'else' ) + # C.g:90:8: 'else' + self.match("else") + + + + + + + finally: + + pass + + # $ANTLR end T108 + + + + # $ANTLR start T109 + def mT109(self, ): + + try: + self.type = T109 + + # C.g:91:6: ( 'switch' ) + # C.g:91:8: 'switch' + self.match("switch") + + + + + + + finally: + + pass + + # $ANTLR end T109 + + + + # $ANTLR start T110 + def mT110(self, ): + + try: + self.type = T110 + + # C.g:92:6: ( 'while' ) + # C.g:92:8: 'while' + self.match("while") + + + + + + + finally: + + pass + + # $ANTLR end T110 + + + + # $ANTLR start T111 + def mT111(self, ): + + try: + self.type = T111 + + # C.g:93:6: ( 'do' ) + # C.g:93:8: 'do' + self.match("do") + + + + + + + finally: + + pass + + # $ANTLR end T111 + + + + # $ANTLR start T112 + def mT112(self, ): + + try: + self.type = T112 + + # C.g:94:6: ( 'for' ) + # C.g:94:8: 'for' + self.match("for") + + + + + + + finally: + + pass + + # $ANTLR end T112 + + + + # $ANTLR start T113 + def mT113(self, ): + + try: + self.type = T113 + + # C.g:95:6: ( 'goto' ) + # C.g:95:8: 'goto' + self.match("goto") + + + + + + + finally: + + pass + + # $ANTLR end T113 + + + + # $ANTLR start T114 + def mT114(self, ): + + try: + self.type = T114 + + # C.g:96:6: ( 'continue' ) + # C.g:96:8: 'continue' + self.match("continue") + + + + + + + finally: + + pass + + # $ANTLR end T114 + + + + # $ANTLR start T115 + def mT115(self, ): + + try: + self.type = T115 + + # C.g:97:6: ( 'break' ) + # C.g:97:8: 'break' + self.match("break") + + + + + + + finally: + + pass + + # $ANTLR end T115 + + + + # $ANTLR start T116 + def mT116(self, ): + + try: + self.type = T116 + + # C.g:98:6: ( 'return' ) + # C.g:98:8: 'return' + self.match("return") + + + + + + + finally: + + pass + + # $ANTLR end T116 + + + + # $ANTLR start IDENTIFIER + def mIDENTIFIER(self, ): + + try: + self.type = IDENTIFIER + + # C.g:533:2: ( LETTER ( LETTER | '0' .. '9' )* ) + # C.g:533:4: LETTER ( LETTER | '0' .. '9' )* + self.mLETTER() + + # C.g:533:11: ( LETTER | '0' .. '9' )* + while True: #loop1 + alt1 = 2 + LA1_0 = self.input.LA(1) + + if (LA1_0 == u'$' or (u'0' <= LA1_0 <= u'9') or (u'A' <= LA1_0 <= u'Z') or LA1_0 == u'_' or (u'a' <= LA1_0 <= u'z')) : + alt1 = 1 + + + if alt1 == 1: + # C.g: + if self.input.LA(1) == u'$' or (u'0' <= self.input.LA(1) <= u'9') or (u'A' <= self.input.LA(1) <= u'Z') or self.input.LA(1) == u'_' or (u'a' <= self.input.LA(1) <= u'z'): + self.input.consume(); + + else: + mse = MismatchedSetException(None, self.input) + self.recover(mse) + raise mse + + + + + else: + break #loop1 + + + + + + + finally: + + pass + + # $ANTLR end IDENTIFIER + + + + # $ANTLR start LETTER + def mLETTER(self, ): + + try: + # C.g:538:2: ( '$' | 'A' .. 'Z' | 'a' .. 'z' | '_' ) + # C.g: + if self.input.LA(1) == u'$' or (u'A' <= self.input.LA(1) <= u'Z') or self.input.LA(1) == u'_' or (u'a' <= self.input.LA(1) <= u'z'): + self.input.consume(); + + else: + mse = MismatchedSetException(None, self.input) + self.recover(mse) + raise mse + + + + + + + finally: + + pass + + # $ANTLR end LETTER + + + + # $ANTLR start CHARACTER_LITERAL + def mCHARACTER_LITERAL(self, ): + + try: + self.type = CHARACTER_LITERAL + + # C.g:545:5: ( ( 'L' )? '\\'' ( EscapeSequence | ~ ( '\\'' | '\\\\' ) ) '\\'' ) + # C.g:545:9: ( 'L' )? '\\'' ( EscapeSequence | ~ ( '\\'' | '\\\\' ) ) '\\'' + # C.g:545:9: ( 'L' )? + alt2 = 2 + LA2_0 = self.input.LA(1) + + if (LA2_0 == u'L') : + alt2 = 1 + if alt2 == 1: + # C.g:545:10: 'L' + self.match(u'L') + + + + + self.match(u'\'') + + # C.g:545:21: ( EscapeSequence | ~ ( '\\'' | '\\\\' ) ) + alt3 = 2 + LA3_0 = self.input.LA(1) + + if (LA3_0 == u'\\') : + alt3 = 1 + elif ((u'\u0000' <= LA3_0 <= u'&') or (u'(' <= LA3_0 <= u'[') or (u']' <= LA3_0 <= u'\uFFFE')) : + alt3 = 2 + else: + nvae = NoViableAltException("545:21: ( EscapeSequence | ~ ( '\\'' | '\\\\' ) )", 3, 0, self.input) + + raise nvae + + if alt3 == 1: + # C.g:545:23: EscapeSequence + self.mEscapeSequence() + + + + elif alt3 == 2: + # C.g:545:40: ~ ( '\\'' | '\\\\' ) + if (u'\u0000' <= self.input.LA(1) <= u'&') or (u'(' <= self.input.LA(1) <= u'[') or (u']' <= self.input.LA(1) <= u'\uFFFE'): + self.input.consume(); + + else: + mse = MismatchedSetException(None, self.input) + self.recover(mse) + raise mse + + + + + + self.match(u'\'') + + + + + + finally: + + pass + + # $ANTLR end CHARACTER_LITERAL + + + + # $ANTLR start STRING_LITERAL + def mSTRING_LITERAL(self, ): + + try: + self.type = STRING_LITERAL + + # C.g:549:5: ( ( 'L' )? '\"' ( EscapeSequence | ~ ( '\\\\' | '\"' ) )* '\"' ) + # C.g:549:8: ( 'L' )? '\"' ( EscapeSequence | ~ ( '\\\\' | '\"' ) )* '\"' + # C.g:549:8: ( 'L' )? + alt4 = 2 + LA4_0 = self.input.LA(1) + + if (LA4_0 == u'L') : + alt4 = 1 + if alt4 == 1: + # C.g:549:9: 'L' + self.match(u'L') + + + + + self.match(u'"') + + # C.g:549:19: ( EscapeSequence | ~ ( '\\\\' | '\"' ) )* + while True: #loop5 + alt5 = 3 + LA5_0 = self.input.LA(1) + + if (LA5_0 == u'\\') : + alt5 = 1 + elif ((u'\u0000' <= LA5_0 <= u'!') or (u'#' <= LA5_0 <= u'[') or (u']' <= LA5_0 <= u'\uFFFE')) : + alt5 = 2 + + + if alt5 == 1: + # C.g:549:21: EscapeSequence + self.mEscapeSequence() + + + + elif alt5 == 2: + # C.g:549:38: ~ ( '\\\\' | '\"' ) + if (u'\u0000' <= self.input.LA(1) <= u'!') or (u'#' <= self.input.LA(1) <= u'[') or (u']' <= self.input.LA(1) <= u'\uFFFE'): + self.input.consume(); + + else: + mse = MismatchedSetException(None, self.input) + self.recover(mse) + raise mse + + + + + else: + break #loop5 + + + self.match(u'"') + + + + + + finally: + + pass + + # $ANTLR end STRING_LITERAL + + + + # $ANTLR start HEX_LITERAL + def mHEX_LITERAL(self, ): + + try: + self.type = HEX_LITERAL + + # C.g:552:13: ( '0' ( 'x' | 'X' ) ( HexDigit )+ ( IntegerTypeSuffix )? ) + # C.g:552:15: '0' ( 'x' | 'X' ) ( HexDigit )+ ( IntegerTypeSuffix )? + self.match(u'0') + + if self.input.LA(1) == u'X' or self.input.LA(1) == u'x': + self.input.consume(); + + else: + mse = MismatchedSetException(None, self.input) + self.recover(mse) + raise mse + + + # C.g:552:29: ( HexDigit )+ + cnt6 = 0 + while True: #loop6 + alt6 = 2 + LA6_0 = self.input.LA(1) + + if ((u'0' <= LA6_0 <= u'9') or (u'A' <= LA6_0 <= u'F') or (u'a' <= LA6_0 <= u'f')) : + alt6 = 1 + + + if alt6 == 1: + # C.g:552:29: HexDigit + self.mHexDigit() + + + + else: + if cnt6 >= 1: + break #loop6 + + eee = EarlyExitException(6, self.input) + raise eee + + cnt6 += 1 + + + # C.g:552:39: ( IntegerTypeSuffix )? + alt7 = 2 + LA7_0 = self.input.LA(1) + + if (LA7_0 == u'L' or LA7_0 == u'U' or LA7_0 == u'l' or LA7_0 == u'u') : + alt7 = 1 + if alt7 == 1: + # C.g:552:39: IntegerTypeSuffix + self.mIntegerTypeSuffix() + + + + + + + + + finally: + + pass + + # $ANTLR end HEX_LITERAL + + + + # $ANTLR start DECIMAL_LITERAL + def mDECIMAL_LITERAL(self, ): + + try: + self.type = DECIMAL_LITERAL + + # C.g:554:17: ( ( '0' | '1' .. '9' ( '0' .. '9' )* ) ( IntegerTypeSuffix )? ) + # C.g:554:19: ( '0' | '1' .. '9' ( '0' .. '9' )* ) ( IntegerTypeSuffix )? + # C.g:554:19: ( '0' | '1' .. '9' ( '0' .. '9' )* ) + alt9 = 2 + LA9_0 = self.input.LA(1) + + if (LA9_0 == u'0') : + alt9 = 1 + elif ((u'1' <= LA9_0 <= u'9')) : + alt9 = 2 + else: + nvae = NoViableAltException("554:19: ( '0' | '1' .. '9' ( '0' .. '9' )* )", 9, 0, self.input) + + raise nvae + + if alt9 == 1: + # C.g:554:20: '0' + self.match(u'0') + + + + elif alt9 == 2: + # C.g:554:26: '1' .. '9' ( '0' .. '9' )* + self.matchRange(u'1', u'9') + + # C.g:554:35: ( '0' .. '9' )* + while True: #loop8 + alt8 = 2 + LA8_0 = self.input.LA(1) + + if ((u'0' <= LA8_0 <= u'9')) : + alt8 = 1 + + + if alt8 == 1: + # C.g:554:35: '0' .. '9' + self.matchRange(u'0', u'9') + + + + else: + break #loop8 + + + + + + # C.g:554:46: ( IntegerTypeSuffix )? + alt10 = 2 + LA10_0 = self.input.LA(1) + + if (LA10_0 == u'L' or LA10_0 == u'U' or LA10_0 == u'l' or LA10_0 == u'u') : + alt10 = 1 + if alt10 == 1: + # C.g:554:46: IntegerTypeSuffix + self.mIntegerTypeSuffix() + + + + + + + + + finally: + + pass + + # $ANTLR end DECIMAL_LITERAL + + + + # $ANTLR start OCTAL_LITERAL + def mOCTAL_LITERAL(self, ): + + try: + self.type = OCTAL_LITERAL + + # C.g:556:15: ( '0' ( '0' .. '7' )+ ( IntegerTypeSuffix )? ) + # C.g:556:17: '0' ( '0' .. '7' )+ ( IntegerTypeSuffix )? + self.match(u'0') + + # C.g:556:21: ( '0' .. '7' )+ + cnt11 = 0 + while True: #loop11 + alt11 = 2 + LA11_0 = self.input.LA(1) + + if ((u'0' <= LA11_0 <= u'7')) : + alt11 = 1 + + + if alt11 == 1: + # C.g:556:22: '0' .. '7' + self.matchRange(u'0', u'7') + + + + else: + if cnt11 >= 1: + break #loop11 + + eee = EarlyExitException(11, self.input) + raise eee + + cnt11 += 1 + + + # C.g:556:33: ( IntegerTypeSuffix )? + alt12 = 2 + LA12_0 = self.input.LA(1) + + if (LA12_0 == u'L' or LA12_0 == u'U' or LA12_0 == u'l' or LA12_0 == u'u') : + alt12 = 1 + if alt12 == 1: + # C.g:556:33: IntegerTypeSuffix + self.mIntegerTypeSuffix() + + + + + + + + + finally: + + pass + + # $ANTLR end OCTAL_LITERAL + + + + # $ANTLR start HexDigit + def mHexDigit(self, ): + + try: + # C.g:559:10: ( ( '0' .. '9' | 'a' .. 'f' | 'A' .. 'F' ) ) + # C.g:559:12: ( '0' .. '9' | 'a' .. 'f' | 'A' .. 'F' ) + if (u'0' <= self.input.LA(1) <= u'9') or (u'A' <= self.input.LA(1) <= u'F') or (u'a' <= self.input.LA(1) <= u'f'): + self.input.consume(); + + else: + mse = MismatchedSetException(None, self.input) + self.recover(mse) + raise mse + + + + + + + finally: + + pass + + # $ANTLR end HexDigit + + + + # $ANTLR start IntegerTypeSuffix + def mIntegerTypeSuffix(self, ): + + try: + # C.g:563:2: ( ( 'u' | 'U' ) | ( 'l' | 'L' ) | ( 'u' | 'U' ) ( 'l' | 'L' ) | ( 'u' | 'U' ) ( 'l' | 'L' ) ( 'l' | 'L' ) ) + alt13 = 4 + LA13_0 = self.input.LA(1) + + if (LA13_0 == u'U' or LA13_0 == u'u') : + LA13_1 = self.input.LA(2) + + if (LA13_1 == u'L' or LA13_1 == u'l') : + LA13_3 = self.input.LA(3) + + if (LA13_3 == u'L' or LA13_3 == u'l') : + alt13 = 4 + else: + alt13 = 3 + else: + alt13 = 1 + elif (LA13_0 == u'L' or LA13_0 == u'l') : + alt13 = 2 + else: + nvae = NoViableAltException("561:1: fragment IntegerTypeSuffix : ( ( 'u' | 'U' ) | ( 'l' | 'L' ) | ( 'u' | 'U' ) ( 'l' | 'L' ) | ( 'u' | 'U' ) ( 'l' | 'L' ) ( 'l' | 'L' ) );", 13, 0, self.input) + + raise nvae + + if alt13 == 1: + # C.g:563:4: ( 'u' | 'U' ) + if self.input.LA(1) == u'U' or self.input.LA(1) == u'u': + self.input.consume(); + + else: + mse = MismatchedSetException(None, self.input) + self.recover(mse) + raise mse + + + + + elif alt13 == 2: + # C.g:564:4: ( 'l' | 'L' ) + if self.input.LA(1) == u'L' or self.input.LA(1) == u'l': + self.input.consume(); + + else: + mse = MismatchedSetException(None, self.input) + self.recover(mse) + raise mse + + + + + elif alt13 == 3: + # C.g:565:4: ( 'u' | 'U' ) ( 'l' | 'L' ) + if self.input.LA(1) == u'U' or self.input.LA(1) == u'u': + self.input.consume(); + + else: + mse = MismatchedSetException(None, self.input) + self.recover(mse) + raise mse + + + if self.input.LA(1) == u'L' or self.input.LA(1) == u'l': + self.input.consume(); + + else: + mse = MismatchedSetException(None, self.input) + self.recover(mse) + raise mse + + + + + elif alt13 == 4: + # C.g:566:4: ( 'u' | 'U' ) ( 'l' | 'L' ) ( 'l' | 'L' ) + if self.input.LA(1) == u'U' or self.input.LA(1) == u'u': + self.input.consume(); + + else: + mse = MismatchedSetException(None, self.input) + self.recover(mse) + raise mse + + + if self.input.LA(1) == u'L' or self.input.LA(1) == u'l': + self.input.consume(); + + else: + mse = MismatchedSetException(None, self.input) + self.recover(mse) + raise mse + + + if self.input.LA(1) == u'L' or self.input.LA(1) == u'l': + self.input.consume(); + + else: + mse = MismatchedSetException(None, self.input) + self.recover(mse) + raise mse + + + + + + finally: + + pass + + # $ANTLR end IntegerTypeSuffix + + + + # $ANTLR start FLOATING_POINT_LITERAL + def mFLOATING_POINT_LITERAL(self, ): + + try: + self.type = FLOATING_POINT_LITERAL + + # C.g:570:5: ( ( '0' .. '9' )+ '.' ( '0' .. '9' )* ( Exponent )? ( FloatTypeSuffix )? | '.' ( '0' .. '9' )+ ( Exponent )? ( FloatTypeSuffix )? | ( '0' .. '9' )+ Exponent ( FloatTypeSuffix )? | ( '0' .. '9' )+ ( Exponent )? FloatTypeSuffix ) + alt25 = 4 + alt25 = self.dfa25.predict(self.input) + if alt25 == 1: + # C.g:570:9: ( '0' .. '9' )+ '.' ( '0' .. '9' )* ( Exponent )? ( FloatTypeSuffix )? + # C.g:570:9: ( '0' .. '9' )+ + cnt14 = 0 + while True: #loop14 + alt14 = 2 + LA14_0 = self.input.LA(1) + + if ((u'0' <= LA14_0 <= u'9')) : + alt14 = 1 + + + if alt14 == 1: + # C.g:570:10: '0' .. '9' + self.matchRange(u'0', u'9') + + + + else: + if cnt14 >= 1: + break #loop14 + + eee = EarlyExitException(14, self.input) + raise eee + + cnt14 += 1 + + + self.match(u'.') + + # C.g:570:25: ( '0' .. '9' )* + while True: #loop15 + alt15 = 2 + LA15_0 = self.input.LA(1) + + if ((u'0' <= LA15_0 <= u'9')) : + alt15 = 1 + + + if alt15 == 1: + # C.g:570:26: '0' .. '9' + self.matchRange(u'0', u'9') + + + + else: + break #loop15 + + + # C.g:570:37: ( Exponent )? + alt16 = 2 + LA16_0 = self.input.LA(1) + + if (LA16_0 == u'E' or LA16_0 == u'e') : + alt16 = 1 + if alt16 == 1: + # C.g:570:37: Exponent + self.mExponent() + + + + + # C.g:570:47: ( FloatTypeSuffix )? + alt17 = 2 + LA17_0 = self.input.LA(1) + + if (LA17_0 == u'D' or LA17_0 == u'F' or LA17_0 == u'd' or LA17_0 == u'f') : + alt17 = 1 + if alt17 == 1: + # C.g:570:47: FloatTypeSuffix + self.mFloatTypeSuffix() + + + + + + + elif alt25 == 2: + # C.g:571:9: '.' ( '0' .. '9' )+ ( Exponent )? ( FloatTypeSuffix )? + self.match(u'.') + + # C.g:571:13: ( '0' .. '9' )+ + cnt18 = 0 + while True: #loop18 + alt18 = 2 + LA18_0 = self.input.LA(1) + + if ((u'0' <= LA18_0 <= u'9')) : + alt18 = 1 + + + if alt18 == 1: + # C.g:571:14: '0' .. '9' + self.matchRange(u'0', u'9') + + + + else: + if cnt18 >= 1: + break #loop18 + + eee = EarlyExitException(18, self.input) + raise eee + + cnt18 += 1 + + + # C.g:571:25: ( Exponent )? + alt19 = 2 + LA19_0 = self.input.LA(1) + + if (LA19_0 == u'E' or LA19_0 == u'e') : + alt19 = 1 + if alt19 == 1: + # C.g:571:25: Exponent + self.mExponent() + + + + + # C.g:571:35: ( FloatTypeSuffix )? + alt20 = 2 + LA20_0 = self.input.LA(1) + + if (LA20_0 == u'D' or LA20_0 == u'F' or LA20_0 == u'd' or LA20_0 == u'f') : + alt20 = 1 + if alt20 == 1: + # C.g:571:35: FloatTypeSuffix + self.mFloatTypeSuffix() + + + + + + + elif alt25 == 3: + # C.g:572:9: ( '0' .. '9' )+ Exponent ( FloatTypeSuffix )? + # C.g:572:9: ( '0' .. '9' )+ + cnt21 = 0 + while True: #loop21 + alt21 = 2 + LA21_0 = self.input.LA(1) + + if ((u'0' <= LA21_0 <= u'9')) : + alt21 = 1 + + + if alt21 == 1: + # C.g:572:10: '0' .. '9' + self.matchRange(u'0', u'9') + + + + else: + if cnt21 >= 1: + break #loop21 + + eee = EarlyExitException(21, self.input) + raise eee + + cnt21 += 1 + + + self.mExponent() + + # C.g:572:30: ( FloatTypeSuffix )? + alt22 = 2 + LA22_0 = self.input.LA(1) + + if (LA22_0 == u'D' or LA22_0 == u'F' or LA22_0 == u'd' or LA22_0 == u'f') : + alt22 = 1 + if alt22 == 1: + # C.g:572:30: FloatTypeSuffix + self.mFloatTypeSuffix() + + + + + + + elif alt25 == 4: + # C.g:573:9: ( '0' .. '9' )+ ( Exponent )? FloatTypeSuffix + # C.g:573:9: ( '0' .. '9' )+ + cnt23 = 0 + while True: #loop23 + alt23 = 2 + LA23_0 = self.input.LA(1) + + if ((u'0' <= LA23_0 <= u'9')) : + alt23 = 1 + + + if alt23 == 1: + # C.g:573:10: '0' .. '9' + self.matchRange(u'0', u'9') + + + + else: + if cnt23 >= 1: + break #loop23 + + eee = EarlyExitException(23, self.input) + raise eee + + cnt23 += 1 + + + # C.g:573:21: ( Exponent )? + alt24 = 2 + LA24_0 = self.input.LA(1) + + if (LA24_0 == u'E' or LA24_0 == u'e') : + alt24 = 1 + if alt24 == 1: + # C.g:573:21: Exponent + self.mExponent() + + + + + self.mFloatTypeSuffix() + + + + + finally: + + pass + + # $ANTLR end FLOATING_POINT_LITERAL + + + + # $ANTLR start Exponent + def mExponent(self, ): + + try: + # C.g:577:10: ( ( 'e' | 'E' ) ( '+' | '-' )? ( '0' .. '9' )+ ) + # C.g:577:12: ( 'e' | 'E' ) ( '+' | '-' )? ( '0' .. '9' )+ + if self.input.LA(1) == u'E' or self.input.LA(1) == u'e': + self.input.consume(); + + else: + mse = MismatchedSetException(None, self.input) + self.recover(mse) + raise mse + + + # C.g:577:22: ( '+' | '-' )? + alt26 = 2 + LA26_0 = self.input.LA(1) + + if (LA26_0 == u'+' or LA26_0 == u'-') : + alt26 = 1 + if alt26 == 1: + # C.g: + if self.input.LA(1) == u'+' or self.input.LA(1) == u'-': + self.input.consume(); + + else: + mse = MismatchedSetException(None, self.input) + self.recover(mse) + raise mse + + + + + + # C.g:577:33: ( '0' .. '9' )+ + cnt27 = 0 + while True: #loop27 + alt27 = 2 + LA27_0 = self.input.LA(1) + + if ((u'0' <= LA27_0 <= u'9')) : + alt27 = 1 + + + if alt27 == 1: + # C.g:577:34: '0' .. '9' + self.matchRange(u'0', u'9') + + + + else: + if cnt27 >= 1: + break #loop27 + + eee = EarlyExitException(27, self.input) + raise eee + + cnt27 += 1 + + + + + + + finally: + + pass + + # $ANTLR end Exponent + + + + # $ANTLR start FloatTypeSuffix + def mFloatTypeSuffix(self, ): + + try: + # C.g:580:17: ( ( 'f' | 'F' | 'd' | 'D' ) ) + # C.g:580:19: ( 'f' | 'F' | 'd' | 'D' ) + if self.input.LA(1) == u'D' or self.input.LA(1) == u'F' or self.input.LA(1) == u'd' or self.input.LA(1) == u'f': + self.input.consume(); + + else: + mse = MismatchedSetException(None, self.input) + self.recover(mse) + raise mse + + + + + + + finally: + + pass + + # $ANTLR end FloatTypeSuffix + + + + # $ANTLR start EscapeSequence + def mEscapeSequence(self, ): + + try: + # C.g:584:5: ( '\\\\' ( 'b' | 't' | 'n' | 'f' | 'r' | '\\\"' | '\\'' | '\\\\' ) | OctalEscape ) + alt28 = 2 + LA28_0 = self.input.LA(1) + + if (LA28_0 == u'\\') : + LA28_1 = self.input.LA(2) + + if (LA28_1 == u'"' or LA28_1 == u'\'' or LA28_1 == u'\\' or LA28_1 == u'b' or LA28_1 == u'f' or LA28_1 == u'n' or LA28_1 == u'r' or LA28_1 == u't') : + alt28 = 1 + elif ((u'0' <= LA28_1 <= u'7')) : + alt28 = 2 + else: + nvae = NoViableAltException("582:1: fragment EscapeSequence : ( '\\\\' ( 'b' | 't' | 'n' | 'f' | 'r' | '\\\"' | '\\'' | '\\\\' ) | OctalEscape );", 28, 1, self.input) + + raise nvae + + else: + nvae = NoViableAltException("582:1: fragment EscapeSequence : ( '\\\\' ( 'b' | 't' | 'n' | 'f' | 'r' | '\\\"' | '\\'' | '\\\\' ) | OctalEscape );", 28, 0, self.input) + + raise nvae + + if alt28 == 1: + # C.g:584:8: '\\\\' ( 'b' | 't' | 'n' | 'f' | 'r' | '\\\"' | '\\'' | '\\\\' ) + self.match(u'\\') + + if self.input.LA(1) == u'"' or self.input.LA(1) == u'\'' or self.input.LA(1) == u'\\' or self.input.LA(1) == u'b' or self.input.LA(1) == u'f' or self.input.LA(1) == u'n' or self.input.LA(1) == u'r' or self.input.LA(1) == u't': + self.input.consume(); + + else: + mse = MismatchedSetException(None, self.input) + self.recover(mse) + raise mse + + + + + elif alt28 == 2: + # C.g:585:9: OctalEscape + self.mOctalEscape() + + + + + finally: + + pass + + # $ANTLR end EscapeSequence + + + + # $ANTLR start OctalEscape + def mOctalEscape(self, ): + + try: + # C.g:590:5: ( '\\\\' ( '0' .. '3' ) ( '0' .. '7' ) ( '0' .. '7' ) | '\\\\' ( '0' .. '7' ) ( '0' .. '7' ) | '\\\\' ( '0' .. '7' ) ) + alt29 = 3 + LA29_0 = self.input.LA(1) + + if (LA29_0 == u'\\') : + LA29_1 = self.input.LA(2) + + if ((u'0' <= LA29_1 <= u'3')) : + LA29_2 = self.input.LA(3) + + if ((u'0' <= LA29_2 <= u'7')) : + LA29_4 = self.input.LA(4) + + if ((u'0' <= LA29_4 <= u'7')) : + alt29 = 1 + else: + alt29 = 2 + else: + alt29 = 3 + elif ((u'4' <= LA29_1 <= u'7')) : + LA29_3 = self.input.LA(3) + + if ((u'0' <= LA29_3 <= u'7')) : + alt29 = 2 + else: + alt29 = 3 + else: + nvae = NoViableAltException("588:1: fragment OctalEscape : ( '\\\\' ( '0' .. '3' ) ( '0' .. '7' ) ( '0' .. '7' ) | '\\\\' ( '0' .. '7' ) ( '0' .. '7' ) | '\\\\' ( '0' .. '7' ) );", 29, 1, self.input) + + raise nvae + + else: + nvae = NoViableAltException("588:1: fragment OctalEscape : ( '\\\\' ( '0' .. '3' ) ( '0' .. '7' ) ( '0' .. '7' ) | '\\\\' ( '0' .. '7' ) ( '0' .. '7' ) | '\\\\' ( '0' .. '7' ) );", 29, 0, self.input) + + raise nvae + + if alt29 == 1: + # C.g:590:9: '\\\\' ( '0' .. '3' ) ( '0' .. '7' ) ( '0' .. '7' ) + self.match(u'\\') + + # C.g:590:14: ( '0' .. '3' ) + # C.g:590:15: '0' .. '3' + self.matchRange(u'0', u'3') + + + + + # C.g:590:25: ( '0' .. '7' ) + # C.g:590:26: '0' .. '7' + self.matchRange(u'0', u'7') + + + + + # C.g:590:36: ( '0' .. '7' ) + # C.g:590:37: '0' .. '7' + self.matchRange(u'0', u'7') + + + + + + + elif alt29 == 2: + # C.g:591:9: '\\\\' ( '0' .. '7' ) ( '0' .. '7' ) + self.match(u'\\') + + # C.g:591:14: ( '0' .. '7' ) + # C.g:591:15: '0' .. '7' + self.matchRange(u'0', u'7') + + + + + # C.g:591:25: ( '0' .. '7' ) + # C.g:591:26: '0' .. '7' + self.matchRange(u'0', u'7') + + + + + + + elif alt29 == 3: + # C.g:592:9: '\\\\' ( '0' .. '7' ) + self.match(u'\\') + + # C.g:592:14: ( '0' .. '7' ) + # C.g:592:15: '0' .. '7' + self.matchRange(u'0', u'7') + + + + + + + + finally: + + pass + + # $ANTLR end OctalEscape + + + + # $ANTLR start UnicodeEscape + def mUnicodeEscape(self, ): + + try: + # C.g:597:5: ( '\\\\' 'u' HexDigit HexDigit HexDigit HexDigit ) + # C.g:597:9: '\\\\' 'u' HexDigit HexDigit HexDigit HexDigit + self.match(u'\\') + + self.match(u'u') + + self.mHexDigit() + + self.mHexDigit() + + self.mHexDigit() + + self.mHexDigit() + + + + + + finally: + + pass + + # $ANTLR end UnicodeEscape + + + + # $ANTLR start WS + def mWS(self, ): + + try: + self.type = WS + + # C.g:600:5: ( ( ' ' | '\\r' | '\\t' | '\\u000C' | '\\n' ) ) + # C.g:600:8: ( ' ' | '\\r' | '\\t' | '\\u000C' | '\\n' ) + if (u'\t' <= self.input.LA(1) <= u'\n') or (u'\f' <= self.input.LA(1) <= u'\r') or self.input.LA(1) == u' ': + self.input.consume(); + + else: + mse = MismatchedSetException(None, self.input) + self.recover(mse) + raise mse + + + #action start + self.channel=HIDDEN; + #action end + + + + + finally: + + pass + + # $ANTLR end WS + + + + # $ANTLR start BS + def mBS(self, ): + + try: + self.type = BS + + # C.g:604:5: ( ( '\\\\' ) ) + # C.g:604:7: ( '\\\\' ) + # C.g:604:7: ( '\\\\' ) + # C.g:604:8: '\\\\' + self.match(u'\\') + + + + + #action start + self.channel=HIDDEN; + #action end + + + + + finally: + + pass + + # $ANTLR end BS + + + + # $ANTLR start UnicodeVocabulary + def mUnicodeVocabulary(self, ): + + try: + self.type = UnicodeVocabulary + + # C.g:612:5: ( '\\u0003' .. '\\uFFFE' ) + # C.g:612:7: '\\u0003' .. '\\uFFFE' + self.matchRange(u'\u0003', u'\uFFFE') + + + + + + finally: + + pass + + # $ANTLR end UnicodeVocabulary + + + + # $ANTLR start COMMENT + def mCOMMENT(self, ): + + try: + self.type = COMMENT + + # C.g:615:5: ( '/*' ( options {greedy=false; } : . )* '*/' ) + # C.g:615:9: '/*' ( options {greedy=false; } : . )* '*/' + self.match("/*") + + + # C.g:615:14: ( options {greedy=false; } : . )* + while True: #loop30 + alt30 = 2 + LA30_0 = self.input.LA(1) + + if (LA30_0 == u'*') : + LA30_1 = self.input.LA(2) + + if (LA30_1 == u'/') : + alt30 = 2 + elif ((u'\u0000' <= LA30_1 <= u'.') or (u'0' <= LA30_1 <= u'\uFFFE')) : + alt30 = 1 + + + elif ((u'\u0000' <= LA30_0 <= u')') or (u'+' <= LA30_0 <= u'\uFFFE')) : + alt30 = 1 + + + if alt30 == 1: + # C.g:615:42: . + self.matchAny() + + + + else: + break #loop30 + + + self.match("*/") + + + #action start + self.channel=HIDDEN; + #action end + + + + + finally: + + pass + + # $ANTLR end COMMENT + + + + # $ANTLR start LINE_COMMENT + def mLINE_COMMENT(self, ): + + try: + self.type = LINE_COMMENT + + # C.g:620:5: ( '//' (~ ( '\\n' | '\\r' ) )* ( '\\r' )? '\\n' ) + # C.g:620:7: '//' (~ ( '\\n' | '\\r' ) )* ( '\\r' )? '\\n' + self.match("//") + + + # C.g:620:12: (~ ( '\\n' | '\\r' ) )* + while True: #loop31 + alt31 = 2 + LA31_0 = self.input.LA(1) + + if ((u'\u0000' <= LA31_0 <= u'\t') or (u'\u000B' <= LA31_0 <= u'\f') or (u'\u000E' <= LA31_0 <= u'\uFFFE')) : + alt31 = 1 + + + if alt31 == 1: + # C.g:620:12: ~ ( '\\n' | '\\r' ) + if (u'\u0000' <= self.input.LA(1) <= u'\t') or (u'\u000B' <= self.input.LA(1) <= u'\f') or (u'\u000E' <= self.input.LA(1) <= u'\uFFFE'): + self.input.consume(); + + else: + mse = MismatchedSetException(None, self.input) + self.recover(mse) + raise mse + + + + + else: + break #loop31 + + + # C.g:620:26: ( '\\r' )? + alt32 = 2 + LA32_0 = self.input.LA(1) + + if (LA32_0 == u'\r') : + alt32 = 1 + if alt32 == 1: + # C.g:620:26: '\\r' + self.match(u'\r') + + + + + self.match(u'\n') + + #action start + self.channel=HIDDEN; + #action end + + + + + finally: + + pass + + # $ANTLR end LINE_COMMENT + + + + # $ANTLR start LINE_COMMAND + def mLINE_COMMAND(self, ): + + try: + self.type = LINE_COMMAND + + # C.g:625:5: ( '#' (~ ( '\\n' | '\\r' ) )* ( '\\r' )? '\\n' ) + # C.g:625:7: '#' (~ ( '\\n' | '\\r' ) )* ( '\\r' )? '\\n' + self.match(u'#') + + # C.g:625:11: (~ ( '\\n' | '\\r' ) )* + while True: #loop33 + alt33 = 2 + LA33_0 = self.input.LA(1) + + if ((u'\u0000' <= LA33_0 <= u'\t') or (u'\u000B' <= LA33_0 <= u'\f') or (u'\u000E' <= LA33_0 <= u'\uFFFE')) : + alt33 = 1 + + + if alt33 == 1: + # C.g:625:11: ~ ( '\\n' | '\\r' ) + if (u'\u0000' <= self.input.LA(1) <= u'\t') or (u'\u000B' <= self.input.LA(1) <= u'\f') or (u'\u000E' <= self.input.LA(1) <= u'\uFFFE'): + self.input.consume(); + + else: + mse = MismatchedSetException(None, self.input) + self.recover(mse) + raise mse + + + + + else: + break #loop33 + + + # C.g:625:25: ( '\\r' )? + alt34 = 2 + LA34_0 = self.input.LA(1) + + if (LA34_0 == u'\r') : + alt34 = 1 + if alt34 == 1: + # C.g:625:25: '\\r' + self.match(u'\r') + + + + + self.match(u'\n') + + #action start + self.channel=HIDDEN; + #action end + + + + + finally: + + pass + + # $ANTLR end LINE_COMMAND + + + + def mTokens(self): + # C.g:1:8: ( T25 | T26 | T27 | T28 | T29 | T30 | T31 | T32 | T33 | T34 | T35 | T36 | T37 | T38 | T39 | T40 | T41 | T42 | T43 | T44 | T45 | T46 | T47 | T48 | T49 | T50 | T51 | T52 | T53 | T54 | T55 | T56 | T57 | T58 | T59 | T60 | T61 | T62 | T63 | T64 | T65 | T66 | T67 | T68 | T69 | T70 | T71 | T72 | T73 | T74 | T75 | T76 | T77 | T78 | T79 | T80 | T81 | T82 | T83 | T84 | T85 | T86 | T87 | T88 | T89 | T90 | T91 | T92 | T93 | T94 | T95 | T96 | T97 | T98 | T99 | T100 | T101 | T102 | T103 | T104 | T105 | T106 | T107 | T108 | T109 | T110 | T111 | T112 | T113 | T114 | T115 | T116 | IDENTIFIER | CHARACTER_LITERAL | STRING_LITERAL | HEX_LITERAL | DECIMAL_LITERAL | OCTAL_LITERAL | FLOATING_POINT_LITERAL | WS | BS | UnicodeVocabulary | COMMENT | LINE_COMMENT | LINE_COMMAND ) + alt35 = 105 + alt35 = self.dfa35.predict(self.input) + if alt35 == 1: + # C.g:1:10: T25 + self.mT25() + + + + elif alt35 == 2: + # C.g:1:14: T26 + self.mT26() + + + + elif alt35 == 3: + # C.g:1:18: T27 + self.mT27() + + + + elif alt35 == 4: + # C.g:1:22: T28 + self.mT28() + + + + elif alt35 == 5: + # C.g:1:26: T29 + self.mT29() + + + + elif alt35 == 6: + # C.g:1:30: T30 + self.mT30() + + + + elif alt35 == 7: + # C.g:1:34: T31 + self.mT31() + + + + elif alt35 == 8: + # C.g:1:38: T32 + self.mT32() + + + + elif alt35 == 9: + # C.g:1:42: T33 + self.mT33() + + + + elif alt35 == 10: + # C.g:1:46: T34 + self.mT34() + + + + elif alt35 == 11: + # C.g:1:50: T35 + self.mT35() + + + + elif alt35 == 12: + # C.g:1:54: T36 + self.mT36() + + + + elif alt35 == 13: + # C.g:1:58: T37 + self.mT37() + + + + elif alt35 == 14: + # C.g:1:62: T38 + self.mT38() + + + + elif alt35 == 15: + # C.g:1:66: T39 + self.mT39() + + + + elif alt35 == 16: + # C.g:1:70: T40 + self.mT40() + + + + elif alt35 == 17: + # C.g:1:74: T41 + self.mT41() + + + + elif alt35 == 18: + # C.g:1:78: T42 + self.mT42() + + + + elif alt35 == 19: + # C.g:1:82: T43 + self.mT43() + + + + elif alt35 == 20: + # C.g:1:86: T44 + self.mT44() + + + + elif alt35 == 21: + # C.g:1:90: T45 + self.mT45() + + + + elif alt35 == 22: + # C.g:1:94: T46 + self.mT46() + + + + elif alt35 == 23: + # C.g:1:98: T47 + self.mT47() + + + + elif alt35 == 24: + # C.g:1:102: T48 + self.mT48() + + + + elif alt35 == 25: + # C.g:1:106: T49 + self.mT49() + + + + elif alt35 == 26: + # C.g:1:110: T50 + self.mT50() + + + + elif alt35 == 27: + # C.g:1:114: T51 + self.mT51() + + + + elif alt35 == 28: + # C.g:1:118: T52 + self.mT52() + + + + elif alt35 == 29: + # C.g:1:122: T53 + self.mT53() + + + + elif alt35 == 30: + # C.g:1:126: T54 + self.mT54() + + + + elif alt35 == 31: + # C.g:1:130: T55 + self.mT55() + + + + elif alt35 == 32: + # C.g:1:134: T56 + self.mT56() + + + + elif alt35 == 33: + # C.g:1:138: T57 + self.mT57() + + + + elif alt35 == 34: + # C.g:1:142: T58 + self.mT58() + + + + elif alt35 == 35: + # C.g:1:146: T59 + self.mT59() + + + + elif alt35 == 36: + # C.g:1:150: T60 + self.mT60() + + + + elif alt35 == 37: + # C.g:1:154: T61 + self.mT61() + + + + elif alt35 == 38: + # C.g:1:158: T62 + self.mT62() + + + + elif alt35 == 39: + # C.g:1:162: T63 + self.mT63() + + + + elif alt35 == 40: + # C.g:1:166: T64 + self.mT64() + + + + elif alt35 == 41: + # C.g:1:170: T65 + self.mT65() + + + + elif alt35 == 42: + # C.g:1:174: T66 + self.mT66() + + + + elif alt35 == 43: + # C.g:1:178: T67 + self.mT67() + + + + elif alt35 == 44: + # C.g:1:182: T68 + self.mT68() + + + + elif alt35 == 45: + # C.g:1:186: T69 + self.mT69() + + + + elif alt35 == 46: + # C.g:1:190: T70 + self.mT70() + + + + elif alt35 == 47: + # C.g:1:194: T71 + self.mT71() + + + + elif alt35 == 48: + # C.g:1:198: T72 + self.mT72() + + + + elif alt35 == 49: + # C.g:1:202: T73 + self.mT73() + + + + elif alt35 == 50: + # C.g:1:206: T74 + self.mT74() + + + + elif alt35 == 51: + # C.g:1:210: T75 + self.mT75() + + + + elif alt35 == 52: + # C.g:1:214: T76 + self.mT76() + + + + elif alt35 == 53: + # C.g:1:218: T77 + self.mT77() + + + + elif alt35 == 54: + # C.g:1:222: T78 + self.mT78() + + + + elif alt35 == 55: + # C.g:1:226: T79 + self.mT79() + + + + elif alt35 == 56: + # C.g:1:230: T80 + self.mT80() + + + + elif alt35 == 57: + # C.g:1:234: T81 + self.mT81() + + + + elif alt35 == 58: + # C.g:1:238: T82 + self.mT82() + + + + elif alt35 == 59: + # C.g:1:242: T83 + self.mT83() + + + + elif alt35 == 60: + # C.g:1:246: T84 + self.mT84() + + + + elif alt35 == 61: + # C.g:1:250: T85 + self.mT85() + + + + elif alt35 == 62: + # C.g:1:254: T86 + self.mT86() + + + + elif alt35 == 63: + # C.g:1:258: T87 + self.mT87() + + + + elif alt35 == 64: + # C.g:1:262: T88 + self.mT88() + + + + elif alt35 == 65: + # C.g:1:266: T89 + self.mT89() + + + + elif alt35 == 66: + # C.g:1:270: T90 + self.mT90() + + + + elif alt35 == 67: + # C.g:1:274: T91 + self.mT91() + + + + elif alt35 == 68: + # C.g:1:278: T92 + self.mT92() + + + + elif alt35 == 69: + # C.g:1:282: T93 + self.mT93() + + + + elif alt35 == 70: + # C.g:1:286: T94 + self.mT94() + + + + elif alt35 == 71: + # C.g:1:290: T95 + self.mT95() + + + + elif alt35 == 72: + # C.g:1:294: T96 + self.mT96() + + + + elif alt35 == 73: + # C.g:1:298: T97 + self.mT97() + + + + elif alt35 == 74: + # C.g:1:302: T98 + self.mT98() + + + + elif alt35 == 75: + # C.g:1:306: T99 + self.mT99() + + + + elif alt35 == 76: + # C.g:1:310: T100 + self.mT100() + + + + elif alt35 == 77: + # C.g:1:315: T101 + self.mT101() + + + + elif alt35 == 78: + # C.g:1:320: T102 + self.mT102() + + + + elif alt35 == 79: + # C.g:1:325: T103 + self.mT103() + + + + elif alt35 == 80: + # C.g:1:330: T104 + self.mT104() + + + + elif alt35 == 81: + # C.g:1:335: T105 + self.mT105() + + + + elif alt35 == 82: + # C.g:1:340: T106 + self.mT106() + + + + elif alt35 == 83: + # C.g:1:345: T107 + self.mT107() + + + + elif alt35 == 84: + # C.g:1:350: T108 + self.mT108() + + + + elif alt35 == 85: + # C.g:1:355: T109 + self.mT109() + + + + elif alt35 == 86: + # C.g:1:360: T110 + self.mT110() + + + + elif alt35 == 87: + # C.g:1:365: T111 + self.mT111() + + + + elif alt35 == 88: + # C.g:1:370: T112 + self.mT112() + + + + elif alt35 == 89: + # C.g:1:375: T113 + self.mT113() + + + + elif alt35 == 90: + # C.g:1:380: T114 + self.mT114() + + + + elif alt35 == 91: + # C.g:1:385: T115 + self.mT115() + + + + elif alt35 == 92: + # C.g:1:390: T116 + self.mT116() + + + + elif alt35 == 93: + # C.g:1:395: IDENTIFIER + self.mIDENTIFIER() + + + + elif alt35 == 94: + # C.g:1:406: CHARACTER_LITERAL + self.mCHARACTER_LITERAL() + + + + elif alt35 == 95: + # C.g:1:424: STRING_LITERAL + self.mSTRING_LITERAL() + + + + elif alt35 == 96: + # C.g:1:439: HEX_LITERAL + self.mHEX_LITERAL() + + + + elif alt35 == 97: + # C.g:1:451: DECIMAL_LITERAL + self.mDECIMAL_LITERAL() + + + + elif alt35 == 98: + # C.g:1:467: OCTAL_LITERAL + self.mOCTAL_LITERAL() + + + + elif alt35 == 99: + # C.g:1:481: FLOATING_POINT_LITERAL + self.mFLOATING_POINT_LITERAL() + + + + elif alt35 == 100: + # C.g:1:504: WS + self.mWS() + + + + elif alt35 == 101: + # C.g:1:507: BS + self.mBS() + + + + elif alt35 == 102: + # C.g:1:510: UnicodeVocabulary + self.mUnicodeVocabulary() + + + + elif alt35 == 103: + # C.g:1:528: COMMENT + self.mCOMMENT() + + + + elif alt35 == 104: + # C.g:1:536: LINE_COMMENT + self.mLINE_COMMENT() + + + + elif alt35 == 105: + # C.g:1:549: LINE_COMMAND + self.mLINE_COMMAND() + + + + + + + + + # lookup tables for DFA #25 + + DFA25_eot = DFA.unpack( + u"\7\uffff\1\10\2\uffff" + ) + + DFA25_eof = DFA.unpack( + u"\12\uffff" + ) + + DFA25_min = DFA.unpack( + u"\2\56\1\uffff\1\53\2\uffff\2\60\2\uffff" + ) + + DFA25_max = DFA.unpack( + u"\1\71\1\146\1\uffff\1\71\2\uffff\1\71\1\146\2\uffff" + ) + + DFA25_accept = DFA.unpack( + u"\2\uffff\1\2\1\uffff\1\4\1\1\2\uffff\2\3" + ) + + DFA25_special = DFA.unpack( + u"\12\uffff" + ) + + + DFA25_transition = [ + DFA.unpack(u"\1\2\1\uffff\12\1"), + DFA.unpack(u"\1\5\1\uffff\12\1\12\uffff\1\4\1\3\1\4\35\uffff\1\4" + u"\1\3\1\4"), + DFA.unpack(u""), + DFA.unpack(u"\1\6\1\uffff\1\6\2\uffff\12\7"), + DFA.unpack(u""), + DFA.unpack(u""), + DFA.unpack(u"\12\7"), + DFA.unpack(u"\12\7\12\uffff\1\11\1\uffff\1\11\35\uffff\1\11\1\uffff" + u"\1\11"), + DFA.unpack(u""), + DFA.unpack(u"") + ] + + # class definition for DFA #25 + + DFA25 = DFA + # lookup tables for DFA #35 + + DFA35_eot = DFA.unpack( + u"\2\uffff\1\75\1\uffff\1\100\14\75\3\uffff\7\75\4\uffff\1\147\1" + u"\151\1\155\1\161\1\165\1\167\1\172\1\uffff\1\175\1\u0080\1\u0083" + u"\1\u0085\1\u0088\1\uffff\5\75\1\uffff\2\72\2\u0092\2\uffff\1\72" + u"\2\uffff\1\75\4\uffff\16\75\1\u00ab\4\75\1\u00b1\2\75\3\uffff\1" + u"\u00b5\7\75\35\uffff\1\u00be\1\uffff\1\u00c0\10\uffff\5\75\4\uffff" + u"\1\u00c6\1\u0092\3\uffff\23\75\1\uffff\1\u00db\1\75\1\u00dd\2\75" + u"\1\uffff\3\75\1\uffff\1\u00e3\6\75\4\uffff\5\75\1\uffff\1\75\1" + u"\u00f1\1\u00f2\7\75\1\u00fa\3\75\1\u00fe\3\75\1\u0102\1\u0103\1" + u"\uffff\1\u0104\1\uffff\5\75\1\uffff\10\75\1\u0113\1\75\1\u0115" + u"\2\75\2\uffff\6\75\1\u011e\1\uffff\3\75\1\uffff\2\75\1\u0124\3" + u"\uffff\1\u0125\3\75\1\u0129\1\75\1\u012b\6\75\1\u0133\1\uffff\1" + u"\u0134\1\uffff\1\u0135\1\75\1\u0137\1\u0138\1\u0139\1\u013a\1\u013b" + u"\1\u013c\1\uffff\1\75\1\u013e\1\u013f\2\75\2\uffff\1\u0142\2\75" + u"\1\uffff\1\75\1\uffff\5\75\1\u014b\1\75\3\uffff\1\u014d\6\uffff" + u"\1\75\2\uffff\2\75\1\uffff\1\u0151\7\75\1\uffff\1\u0159\1\uffff" + u"\1\u015a\1\u015b\1\u015c\1\uffff\1\u015d\1\u015e\1\75\1\u0160\3" + u"\75\6\uffff\1\u0164\1\uffff\3\75\1\uffff\20\75\1\u0178\2\75\1\uffff" + u"\4\75\1\u017f\1\75\1\uffff\11\75\1\u018a\1\uffff" + ) + + DFA35_eof = DFA.unpack( + u"\u018b\uffff" + ) + + DFA35_min = DFA.unpack( + u"\1\3\1\uffff\1\171\1\uffff\1\75\1\154\1\150\1\165\1\145\1\124\1" + u"\157\1\141\1\146\1\157\1\154\1\145\1\156\3\uffff\1\116\1\120\1" + u"\117\1\116\1\117\1\114\1\106\4\uffff\1\75\1\56\1\53\1\55\1\52\1" + u"\75\1\46\1\uffff\1\75\1\74\3\75\1\uffff\1\137\1\150\1\157\1\162" + u"\1\42\1\uffff\2\0\2\56\2\uffff\1\0\2\uffff\1\160\4\uffff\1\165" + u"\1\163\1\164\1\141\1\151\1\147\1\157\1\164\1\147\1\101\1\151\1" + u"\156\1\163\1\141\1\44\1\164\1\156\1\162\1\157\1\44\1\146\1\151" + u"\3\uffff\1\44\2\124\1\116\1\101\1\114\1\117\1\111\35\uffff\1\75" + u"\1\uffff\1\75\10\uffff\1\141\1\163\1\151\1\164\1\145\4\uffff\2" + u"\56\3\uffff\1\145\1\155\2\145\1\165\2\164\1\156\1\145\1\162\1\157" + u"\1\151\1\165\1\124\1\144\1\141\1\163\1\145\1\162\1\uffff\1\44\1" + u"\147\1\44\1\141\1\142\1\uffff\1\141\1\151\1\157\1\uffff\1\44\1" + u"\111\1\123\1\114\1\101\1\102\1\101\4\uffff\1\163\1\155\1\154\1" + u"\157\1\141\1\uffff\1\144\2\44\1\162\1\143\1\151\1\143\1\145\1\157" + u"\1\164\1\44\1\163\1\162\1\111\1\44\1\164\1\151\1\164\2\44\1\uffff" + u"\1\44\1\uffff\1\164\1\154\1\165\1\147\1\156\1\uffff\1\117\1\124" + u"\1\111\1\124\1\101\1\102\1\120\1\155\1\44\1\145\1\44\1\153\1\145" + u"\2\uffff\1\156\1\164\1\143\1\150\1\144\1\146\1\44\1\uffff\1\164" + u"\1\156\1\103\1\uffff\1\151\1\156\1\44\3\uffff\1\44\1\145\1\154" + u"\1\156\1\44\1\116\1\44\1\107\1\111\1\114\1\117\1\125\1\111\1\44" + u"\1\uffff\1\44\1\uffff\1\44\1\146\6\44\1\uffff\1\145\2\44\1\154" + u"\1\165\2\uffff\1\44\1\164\1\145\1\uffff\1\101\1\uffff\1\116\1\114" + u"\1\137\1\117\1\116\1\44\1\137\3\uffff\1\44\6\uffff\1\162\2\uffff" + u"\2\145\1\uffff\1\44\1\144\1\114\2\105\1\122\2\124\1\uffff\1\44" + u"\1\uffff\3\44\1\uffff\2\44\1\104\1\44\1\105\1\123\1\111\6\uffff" + u"\1\44\1\uffff\1\115\1\105\1\115\1\uffff\1\117\1\122\1\105\2\126" + u"\1\123\1\105\1\111\1\105\1\137\1\103\1\122\1\111\1\105\1\126\1" + u"\106\1\44\1\111\1\137\1\uffff\1\103\1\125\1\105\1\116\1\44\1\122" + u"\1\uffff\1\105\1\106\1\105\1\122\1\105\1\116\1\103\1\105\1\104" + u"\1\44\1\uffff" + ) + + DFA35_max = DFA.unpack( + u"\1\ufffe\1\uffff\1\171\1\uffff\1\75\1\170\1\167\1\165\1\145\1\124" + u"\2\157\1\156\3\157\1\156\3\uffff\1\116\1\125\1\117\1\116\1\117" + u"\1\114\1\106\4\uffff\1\75\1\71\1\75\1\76\3\75\1\uffff\2\75\1\76" + u"\1\75\1\174\1\uffff\1\141\1\150\1\157\1\162\1\47\1\uffff\2\ufffe" + u"\1\170\1\146\2\uffff\1\ufffe\2\uffff\1\160\4\uffff\1\165\1\163" + u"\1\164\1\162\1\151\1\172\1\157\2\164\1\101\1\154\1\156\1\163\1" + u"\141\1\172\1\164\1\156\1\162\1\157\1\172\1\146\1\163\3\uffff\1" + u"\172\2\124\1\116\1\101\1\114\1\117\1\111\35\uffff\1\75\1\uffff" + u"\1\75\10\uffff\1\141\1\163\1\151\1\164\1\145\4\uffff\2\146\3\uffff" + u"\1\145\1\155\2\145\1\165\2\164\1\156\1\145\1\162\1\157\1\151\1" + u"\165\1\124\1\144\1\141\1\164\1\145\1\162\1\uffff\1\172\1\147\1" + u"\172\1\141\1\142\1\uffff\1\141\1\151\1\157\1\uffff\1\172\1\111" + u"\1\123\1\114\1\101\1\102\1\137\4\uffff\1\163\1\155\1\154\1\157" + u"\1\141\1\uffff\1\144\2\172\1\162\1\143\1\151\1\143\1\145\1\157" + u"\1\164\1\172\1\163\1\162\1\111\1\172\1\164\1\151\1\164\2\172\1" + u"\uffff\1\172\1\uffff\1\164\1\154\1\165\1\147\1\156\1\uffff\1\117" + u"\1\124\1\111\1\124\1\101\1\122\1\120\1\155\1\172\1\145\1\172\1" + u"\153\1\145\2\uffff\1\156\1\164\1\143\1\150\1\144\1\146\1\172\1" + u"\uffff\1\164\1\156\1\103\1\uffff\1\151\1\156\1\172\3\uffff\1\172" + u"\1\145\1\154\1\156\1\172\1\116\1\172\1\107\1\111\1\114\1\117\1" + u"\125\1\111\1\172\1\uffff\1\172\1\uffff\1\172\1\146\6\172\1\uffff" + u"\1\145\2\172\1\154\1\165\2\uffff\1\172\1\164\1\145\1\uffff\1\101" + u"\1\uffff\1\116\1\114\1\137\1\117\1\116\1\172\1\137\3\uffff\1\172" + u"\6\uffff\1\162\2\uffff\2\145\1\uffff\1\172\1\144\1\114\2\105\1" + u"\122\2\124\1\uffff\1\172\1\uffff\3\172\1\uffff\2\172\1\104\1\172" + u"\1\105\1\123\1\111\6\uffff\1\172\1\uffff\1\115\1\105\1\115\1\uffff" + u"\1\117\1\122\1\105\2\126\1\123\1\105\1\111\1\105\1\137\1\103\1" + u"\122\1\111\1\105\1\126\1\106\1\172\1\111\1\137\1\uffff\1\103\1" + u"\125\1\105\1\116\1\172\1\122\1\uffff\1\105\1\106\1\105\1\122\1" + u"\105\1\116\1\103\1\105\1\104\1\172\1\uffff" + ) + + DFA35_accept = DFA.unpack( + u"\1\uffff\1\1\1\uffff\1\3\15\uffff\1\23\1\24\1\27\7\uffff\1\45\1" + u"\46\1\47\1\50\7\uffff\1\65\5\uffff\1\101\5\uffff\1\135\4\uffff" + u"\1\144\1\145\1\uffff\1\146\1\1\1\uffff\1\135\1\3\1\106\1\4\26\uffff" + u"\1\23\1\24\1\27\10\uffff\1\45\1\46\1\47\1\50\1\67\1\51\1\52\1\62" + u"\1\143\1\57\1\72\1\53\1\63\1\73\1\60\1\54\1\70\1\150\1\147\1\55" + u"\1\71\1\56\1\76\1\103\1\64\1\65\1\107\1\66\1\112\1\uffff\1\110" + u"\1\uffff\1\113\1\111\1\77\1\105\1\100\1\102\1\104\1\101\5\uffff" + u"\1\136\1\137\1\140\1\141\2\uffff\1\144\1\145\1\151\23\uffff\1\123" + u"\5\uffff\1\127\3\uffff\1\33\7\uffff\1\74\1\114\1\75\1\115\5\uffff" + u"\1\142\24\uffff\1\15\1\uffff\1\130\5\uffff\1\34\15\uffff\1\30\1" + u"\124\7\uffff\1\7\3\uffff\1\12\3\uffff\1\121\1\13\1\16\16\uffff" + u"\1\117\1\uffff\1\131\10\uffff\1\14\5\uffff\1\31\1\17\3\uffff\1" + u"\26\1\uffff\1\36\7\uffff\1\120\1\126\1\133\1\uffff\1\5\1\25\1\6" + u"\1\125\1\21\1\61\1\uffff\1\134\1\11\2\uffff\1\20\10\uffff\1\42" + u"\1\uffff\1\2\3\uffff\1\122\7\uffff\1\116\1\10\1\32\1\132\1\22\1" + u"\35\1\uffff\1\40\3\uffff\1\37\23\uffff\1\43\6\uffff\1\44\12\uffff" + u"\1\41" + ) + + DFA35_special = DFA.unpack( + u"\u018b\uffff" + ) + + + DFA35_transition = [ + DFA.unpack(u"\6\72\2\67\1\72\2\67\22\72\1\67\1\47\1\64\1\71\1\62" + u"\1\44\1\45\1\63\1\33\1\34\1\37\1\41\1\3\1\42\1\40\1\43\1\65\11" + u"\66\1\23\1\1\1\50\1\4\1\51\1\54\1\72\2\62\1\26\1\62\1\32\1\62\1" + u"\31\1\62\1\24\2\62\1\61\2\62\1\25\3\62\1\11\1\62\1\27\1\30\4\62" + u"\1\35\1\70\1\36\1\52\1\55\1\72\1\7\1\60\1\13\1\17\1\5\1\16\1\57" + u"\1\62\1\14\2\62\1\15\5\62\1\10\1\6\1\2\1\20\1\12\1\56\3\62\1\21" + u"\1\53\1\22\1\46\uff80\72"), + DFA.unpack(u""), + DFA.unpack(u"\1\74"), + DFA.unpack(u""), + DFA.unpack(u"\1\77"), + DFA.unpack(u"\1\102\1\uffff\1\101\11\uffff\1\103"), + DFA.unpack(u"\1\107\1\106\12\uffff\1\104\2\uffff\1\105"), + DFA.unpack(u"\1\110"), + DFA.unpack(u"\1\111"), + DFA.unpack(u"\1\112"), + DFA.unpack(u"\1\113"), + DFA.unpack(u"\1\115\6\uffff\1\116\6\uffff\1\114"), + DFA.unpack(u"\1\117\7\uffff\1\120"), + DFA.unpack(u"\1\121"), + DFA.unpack(u"\1\123\2\uffff\1\122"), + DFA.unpack(u"\1\125\11\uffff\1\124"), + DFA.unpack(u"\1\126"), + DFA.unpack(u""), + DFA.unpack(u""), + DFA.unpack(u""), + DFA.unpack(u"\1\132"), + DFA.unpack(u"\1\134\4\uffff\1\133"), + DFA.unpack(u"\1\135"), + DFA.unpack(u"\1\136"), + DFA.unpack(u"\1\137"), + DFA.unpack(u"\1\140"), + DFA.unpack(u"\1\141"), + DFA.unpack(u""), + DFA.unpack(u""), + DFA.unpack(u""), + DFA.unpack(u""), + DFA.unpack(u"\1\146"), + DFA.unpack(u"\1\150\1\uffff\12\152"), + DFA.unpack(u"\1\153\21\uffff\1\154"), + DFA.unpack(u"\1\160\17\uffff\1\157\1\156"), + DFA.unpack(u"\1\164\4\uffff\1\163\15\uffff\1\162"), + DFA.unpack(u"\1\166"), + DFA.unpack(u"\1\171\26\uffff\1\170"), + DFA.unpack(u""), + DFA.unpack(u"\1\174"), + DFA.unpack(u"\1\177\1\176"), + DFA.unpack(u"\1\u0082\1\u0081"), + DFA.unpack(u"\1\u0084"), + DFA.unpack(u"\1\u0086\76\uffff\1\u0087"), + DFA.unpack(u""), + DFA.unpack(u"\1\u008a\1\uffff\1\u008b"), + DFA.unpack(u"\1\u008c"), + DFA.unpack(u"\1\u008d"), + DFA.unpack(u"\1\u008e"), + DFA.unpack(u"\1\u0090\4\uffff\1\u008f"), + DFA.unpack(u""), + DFA.unpack(u"\47\u008f\1\uffff\uffd7\u008f"), + DFA.unpack(u"\uffff\u0090"), + DFA.unpack(u"\1\152\1\uffff\10\u0093\2\152\12\uffff\3\152\21\uffff" + u"\1\u0091\13\uffff\3\152\21\uffff\1\u0091"), + DFA.unpack(u"\1\152\1\uffff\12\u0094\12\uffff\3\152\35\uffff\3\152"), + DFA.unpack(u""), + DFA.unpack(u""), + DFA.unpack(u"\uffff\u0097"), + DFA.unpack(u""), + DFA.unpack(u""), + DFA.unpack(u"\1\u0098"), + DFA.unpack(u""), + DFA.unpack(u""), + DFA.unpack(u""), + DFA.unpack(u""), + DFA.unpack(u"\1\u0099"), + DFA.unpack(u"\1\u009a"), + DFA.unpack(u"\1\u009b"), + DFA.unpack(u"\1\u009d\20\uffff\1\u009c"), + DFA.unpack(u"\1\u009e"), + DFA.unpack(u"\1\u009f\22\uffff\1\u00a0"), + DFA.unpack(u"\1\u00a1"), + DFA.unpack(u"\1\u00a2"), + DFA.unpack(u"\1\u00a3\14\uffff\1\u00a4"), + DFA.unpack(u"\1\u00a5"), + DFA.unpack(u"\1\u00a6\2\uffff\1\u00a7"), + DFA.unpack(u"\1\u00a8"), + DFA.unpack(u"\1\u00a9"), + DFA.unpack(u"\1\u00aa"), + DFA.unpack(u"\1\75\13\uffff\12\75\7\uffff\32\75\4\uffff\1\75\1\uffff" + u"\32\75"), + DFA.unpack(u"\1\u00ac"), + DFA.unpack(u"\1\u00ad"), + DFA.unpack(u"\1\u00ae"), + DFA.unpack(u"\1\u00af"), + DFA.unpack(u"\1\75\13\uffff\12\75\7\uffff\32\75\4\uffff\1\75\1\uffff" + u"\24\75\1\u00b0\5\75"), + DFA.unpack(u"\1\u00b2"), + DFA.unpack(u"\1\u00b4\11\uffff\1\u00b3"), + DFA.unpack(u""), + DFA.unpack(u""), + DFA.unpack(u""), + DFA.unpack(u"\1\75\13\uffff\12\75\7\uffff\32\75\4\uffff\1\75\1\uffff" + u"\32\75"), + DFA.unpack(u"\1\u00b6"), + DFA.unpack(u"\1\u00b7"), + DFA.unpack(u"\1\u00b8"), + DFA.unpack(u"\1\u00b9"), + DFA.unpack(u"\1\u00ba"), + DFA.unpack(u"\1\u00bb"), + DFA.unpack(u"\1\u00bc"), + DFA.unpack(u""), + DFA.unpack(u""), + DFA.unpack(u""), + DFA.unpack(u""), + DFA.unpack(u""), + DFA.unpack(u""), + DFA.unpack(u""), + DFA.unpack(u""), + DFA.unpack(u""), + DFA.unpack(u""), + DFA.unpack(u""), + DFA.unpack(u""), + DFA.unpack(u""), + DFA.unpack(u""), + DFA.unpack(u""), + DFA.unpack(u""), + DFA.unpack(u""), + DFA.unpack(u""), + DFA.unpack(u""), + DFA.unpack(u""), + DFA.unpack(u""), + DFA.unpack(u""), + DFA.unpack(u""), + DFA.unpack(u""), + DFA.unpack(u""), + DFA.unpack(u""), + DFA.unpack(u""), + DFA.unpack(u""), + DFA.unpack(u""), + DFA.unpack(u"\1\u00bd"), + DFA.unpack(u""), + DFA.unpack(u"\1\u00bf"), + DFA.unpack(u""), + DFA.unpack(u""), + DFA.unpack(u""), + DFA.unpack(u""), + DFA.unpack(u""), + DFA.unpack(u""), + DFA.unpack(u""), + DFA.unpack(u""), + DFA.unpack(u"\1\u00c1"), + DFA.unpack(u"\1\u00c2"), + DFA.unpack(u"\1\u00c3"), + DFA.unpack(u"\1\u00c4"), + DFA.unpack(u"\1\u00c5"), + DFA.unpack(u""), + DFA.unpack(u""), + DFA.unpack(u""), + DFA.unpack(u""), + DFA.unpack(u"\1\152\1\uffff\10\u0093\2\152\12\uffff\3\152\35\uffff" + u"\3\152"), + DFA.unpack(u"\1\152\1\uffff\12\u0094\12\uffff\3\152\35\uffff\3\152"), + DFA.unpack(u""), + DFA.unpack(u""), + DFA.unpack(u""), + DFA.unpack(u"\1\u00c7"), + DFA.unpack(u"\1\u00c8"), + DFA.unpack(u"\1\u00c9"), + DFA.unpack(u"\1\u00ca"), + DFA.unpack(u"\1\u00cb"), + DFA.unpack(u"\1\u00cc"), + DFA.unpack(u"\1\u00cd"), + DFA.unpack(u"\1\u00ce"), + DFA.unpack(u"\1\u00cf"), + DFA.unpack(u"\1\u00d0"), + DFA.unpack(u"\1\u00d1"), + DFA.unpack(u"\1\u00d2"), + DFA.unpack(u"\1\u00d3"), + DFA.unpack(u"\1\u00d4"), + DFA.unpack(u"\1\u00d5"), + DFA.unpack(u"\1\u00d6"), + DFA.unpack(u"\1\u00d8\1\u00d7"), + DFA.unpack(u"\1\u00d9"), + DFA.unpack(u"\1\u00da"), + DFA.unpack(u""), + DFA.unpack(u"\1\75\13\uffff\12\75\7\uffff\32\75\4\uffff\1\75\1\uffff" + u"\32\75"), + DFA.unpack(u"\1\u00dc"), + DFA.unpack(u"\1\75\13\uffff\12\75\7\uffff\32\75\4\uffff\1\75\1\uffff" + u"\32\75"), + DFA.unpack(u"\1\u00de"), + DFA.unpack(u"\1\u00df"), + DFA.unpack(u""), + DFA.unpack(u"\1\u00e0"), + DFA.unpack(u"\1\u00e1"), + DFA.unpack(u"\1\u00e2"), + DFA.unpack(u""), + DFA.unpack(u"\1\75\13\uffff\12\75\7\uffff\32\75\4\uffff\1\75\1\uffff" + u"\32\75"), + DFA.unpack(u"\1\u00e4"), + DFA.unpack(u"\1\u00e5"), + DFA.unpack(u"\1\u00e6"), + DFA.unpack(u"\1\u00e7"), + DFA.unpack(u"\1\u00e8"), + DFA.unpack(u"\1\u00ea\35\uffff\1\u00e9"), + DFA.unpack(u""), + DFA.unpack(u""), + DFA.unpack(u""), + DFA.unpack(u""), + DFA.unpack(u"\1\u00eb"), + DFA.unpack(u"\1\u00ec"), + DFA.unpack(u"\1\u00ed"), + DFA.unpack(u"\1\u00ee"), + DFA.unpack(u"\1\u00ef"), + DFA.unpack(u""), + DFA.unpack(u"\1\u00f0"), + DFA.unpack(u"\1\75\13\uffff\12\75\7\uffff\32\75\4\uffff\1\75\1\uffff" + u"\32\75"), + DFA.unpack(u"\1\75\13\uffff\12\75\7\uffff\32\75\4\uffff\1\75\1\uffff" + u"\32\75"), + DFA.unpack(u"\1\u00f3"), + DFA.unpack(u"\1\u00f4"), + DFA.unpack(u"\1\u00f5"), + DFA.unpack(u"\1\u00f6"), + DFA.unpack(u"\1\u00f7"), + DFA.unpack(u"\1\u00f8"), + DFA.unpack(u"\1\u00f9"), + DFA.unpack(u"\1\75\13\uffff\12\75\7\uffff\32\75\4\uffff\1\75\1\uffff" + u"\32\75"), + DFA.unpack(u"\1\u00fb"), + DFA.unpack(u"\1\u00fc"), + DFA.unpack(u"\1\u00fd"), + DFA.unpack(u"\1\75\13\uffff\12\75\7\uffff\32\75\4\uffff\1\75\1\uffff" + u"\32\75"), + DFA.unpack(u"\1\u00ff"), + DFA.unpack(u"\1\u0100"), + DFA.unpack(u"\1\u0101"), + DFA.unpack(u"\1\75\13\uffff\12\75\7\uffff\32\75\4\uffff\1\75\1\uffff" + u"\32\75"), + DFA.unpack(u"\1\75\13\uffff\12\75\7\uffff\32\75\4\uffff\1\75\1\uffff" + u"\32\75"), + DFA.unpack(u""), + DFA.unpack(u"\1\75\13\uffff\12\75\7\uffff\32\75\4\uffff\1\75\1\uffff" + u"\32\75"), + DFA.unpack(u""), + DFA.unpack(u"\1\u0105"), + DFA.unpack(u"\1\u0106"), + DFA.unpack(u"\1\u0107"), + DFA.unpack(u"\1\u0108"), + DFA.unpack(u"\1\u0109"), + DFA.unpack(u""), + DFA.unpack(u"\1\u010a"), + DFA.unpack(u"\1\u010b"), + DFA.unpack(u"\1\u010c"), + DFA.unpack(u"\1\u010d"), + DFA.unpack(u"\1\u010e"), + DFA.unpack(u"\1\u010f\17\uffff\1\u0110"), + DFA.unpack(u"\1\u0111"), + DFA.unpack(u"\1\u0112"), + DFA.unpack(u"\1\75\13\uffff\12\75\7\uffff\32\75\4\uffff\1\75\1\uffff" + u"\32\75"), + DFA.unpack(u"\1\u0114"), + DFA.unpack(u"\1\75\13\uffff\12\75\7\uffff\32\75\4\uffff\1\75\1\uffff" + u"\32\75"), + DFA.unpack(u"\1\u0116"), + DFA.unpack(u"\1\u0117"), + DFA.unpack(u""), + DFA.unpack(u""), + DFA.unpack(u"\1\u0118"), + DFA.unpack(u"\1\u0119"), + DFA.unpack(u"\1\u011a"), + DFA.unpack(u"\1\u011b"), + DFA.unpack(u"\1\u011c"), + DFA.unpack(u"\1\u011d"), + DFA.unpack(u"\1\75\13\uffff\12\75\7\uffff\32\75\4\uffff\1\75\1\uffff" + u"\32\75"), + DFA.unpack(u""), + DFA.unpack(u"\1\u011f"), + DFA.unpack(u"\1\u0120"), + DFA.unpack(u"\1\u0121"), + DFA.unpack(u""), + DFA.unpack(u"\1\u0122"), + DFA.unpack(u"\1\u0123"), + DFA.unpack(u"\1\75\13\uffff\12\75\7\uffff\32\75\4\uffff\1\75\1\uffff" + u"\32\75"), + DFA.unpack(u""), + DFA.unpack(u""), + DFA.unpack(u""), + DFA.unpack(u"\1\75\13\uffff\12\75\7\uffff\32\75\4\uffff\1\75\1\uffff" + u"\32\75"), + DFA.unpack(u"\1\u0126"), + DFA.unpack(u"\1\u0127"), + DFA.unpack(u"\1\u0128"), + DFA.unpack(u"\1\75\13\uffff\12\75\7\uffff\32\75\4\uffff\1\75\1\uffff" + u"\32\75"), + DFA.unpack(u"\1\u012a"), + DFA.unpack(u"\1\75\13\uffff\12\75\7\uffff\32\75\4\uffff\1\75\1\uffff" + u"\32\75"), + DFA.unpack(u"\1\u012c"), + DFA.unpack(u"\1\u012d"), + DFA.unpack(u"\1\u012e"), + DFA.unpack(u"\1\u012f"), + DFA.unpack(u"\1\u0130"), + DFA.unpack(u"\1\u0131"), + DFA.unpack(u"\1\75\13\uffff\12\75\7\uffff\32\75\4\uffff\1\u0132\1" + u"\uffff\32\75"), + DFA.unpack(u""), + DFA.unpack(u"\1\75\13\uffff\12\75\7\uffff\32\75\4\uffff\1\75\1\uffff" + u"\32\75"), + DFA.unpack(u""), + DFA.unpack(u"\1\75\13\uffff\12\75\7\uffff\32\75\4\uffff\1\75\1\uffff" + u"\32\75"), + DFA.unpack(u"\1\u0136"), + DFA.unpack(u"\1\75\13\uffff\12\75\7\uffff\32\75\4\uffff\1\75\1\uffff" + u"\32\75"), + DFA.unpack(u"\1\75\13\uffff\12\75\7\uffff\32\75\4\uffff\1\75\1\uffff" + u"\32\75"), + DFA.unpack(u"\1\75\13\uffff\12\75\7\uffff\32\75\4\uffff\1\75\1\uffff" + u"\32\75"), + DFA.unpack(u"\1\75\13\uffff\12\75\7\uffff\32\75\4\uffff\1\75\1\uffff" + u"\32\75"), + DFA.unpack(u"\1\75\13\uffff\12\75\7\uffff\32\75\4\uffff\1\75\1\uffff" + u"\32\75"), + DFA.unpack(u"\1\75\13\uffff\12\75\7\uffff\32\75\4\uffff\1\75\1\uffff" + u"\32\75"), + DFA.unpack(u""), + DFA.unpack(u"\1\u013d"), + DFA.unpack(u"\1\75\13\uffff\12\75\7\uffff\32\75\4\uffff\1\75\1\uffff" + u"\32\75"), + DFA.unpack(u"\1\75\13\uffff\12\75\7\uffff\32\75\4\uffff\1\75\1\uffff" + u"\32\75"), + DFA.unpack(u"\1\u0140"), + DFA.unpack(u"\1\u0141"), + DFA.unpack(u""), + DFA.unpack(u""), + DFA.unpack(u"\1\75\13\uffff\12\75\7\uffff\32\75\4\uffff\1\75\1\uffff" + u"\32\75"), + DFA.unpack(u"\1\u0143"), + DFA.unpack(u"\1\u0144"), + DFA.unpack(u""), + DFA.unpack(u"\1\u0145"), + DFA.unpack(u""), + DFA.unpack(u"\1\u0146"), + DFA.unpack(u"\1\u0147"), + DFA.unpack(u"\1\u0148"), + DFA.unpack(u"\1\u0149"), + DFA.unpack(u"\1\u014a"), + DFA.unpack(u"\1\75\13\uffff\12\75\7\uffff\32\75\4\uffff\1\75\1\uffff" + u"\32\75"), + DFA.unpack(u"\1\u014c"), + DFA.unpack(u""), + DFA.unpack(u""), + DFA.unpack(u""), + DFA.unpack(u"\1\75\13\uffff\12\75\7\uffff\32\75\4\uffff\1\75\1\uffff" + u"\32\75"), + DFA.unpack(u""), + DFA.unpack(u""), + DFA.unpack(u""), + DFA.unpack(u""), + DFA.unpack(u""), + DFA.unpack(u""), + DFA.unpack(u"\1\u014e"), + DFA.unpack(u""), + DFA.unpack(u""), + DFA.unpack(u"\1\u014f"), + DFA.unpack(u"\1\u0150"), + DFA.unpack(u""), + DFA.unpack(u"\1\75\13\uffff\12\75\7\uffff\32\75\4\uffff\1\75\1\uffff" + u"\32\75"), + DFA.unpack(u"\1\u0152"), + DFA.unpack(u"\1\u0153"), + DFA.unpack(u"\1\u0154"), + DFA.unpack(u"\1\u0155"), + DFA.unpack(u"\1\u0156"), + DFA.unpack(u"\1\u0157"), + DFA.unpack(u"\1\u0158"), + DFA.unpack(u""), + DFA.unpack(u"\1\75\13\uffff\12\75\7\uffff\32\75\4\uffff\1\75\1\uffff" + u"\32\75"), + DFA.unpack(u""), + DFA.unpack(u"\1\75\13\uffff\12\75\7\uffff\32\75\4\uffff\1\75\1\uffff" + u"\32\75"), + DFA.unpack(u"\1\75\13\uffff\12\75\7\uffff\32\75\4\uffff\1\75\1\uffff" + u"\32\75"), + DFA.unpack(u"\1\75\13\uffff\12\75\7\uffff\32\75\4\uffff\1\75\1\uffff" + u"\32\75"), + DFA.unpack(u""), + DFA.unpack(u"\1\75\13\uffff\12\75\7\uffff\32\75\4\uffff\1\75\1\uffff" + u"\32\75"), + DFA.unpack(u"\1\75\13\uffff\12\75\7\uffff\32\75\4\uffff\1\75\1\uffff" + u"\32\75"), + DFA.unpack(u"\1\u015f"), + DFA.unpack(u"\1\75\13\uffff\12\75\7\uffff\32\75\4\uffff\1\75\1\uffff" + u"\32\75"), + DFA.unpack(u"\1\u0161"), + DFA.unpack(u"\1\u0162"), + DFA.unpack(u"\1\u0163"), + DFA.unpack(u""), + DFA.unpack(u""), + DFA.unpack(u""), + DFA.unpack(u""), + DFA.unpack(u""), + DFA.unpack(u""), + DFA.unpack(u"\1\75\13\uffff\12\75\7\uffff\32\75\4\uffff\1\75\1\uffff" + u"\32\75"), + DFA.unpack(u""), + DFA.unpack(u"\1\u0165"), + DFA.unpack(u"\1\u0166"), + DFA.unpack(u"\1\u0167"), + DFA.unpack(u""), + DFA.unpack(u"\1\u0168"), + DFA.unpack(u"\1\u0169"), + DFA.unpack(u"\1\u016a"), + DFA.unpack(u"\1\u016b"), + DFA.unpack(u"\1\u016c"), + DFA.unpack(u"\1\u016d"), + DFA.unpack(u"\1\u016e"), + DFA.unpack(u"\1\u016f"), + DFA.unpack(u"\1\u0170"), + DFA.unpack(u"\1\u0171"), + DFA.unpack(u"\1\u0172"), + DFA.unpack(u"\1\u0173"), + DFA.unpack(u"\1\u0174"), + DFA.unpack(u"\1\u0175"), + DFA.unpack(u"\1\u0176"), + DFA.unpack(u"\1\u0177"), + DFA.unpack(u"\1\75\13\uffff\12\75\7\uffff\32\75\4\uffff\1\75\1\uffff" + u"\32\75"), + DFA.unpack(u"\1\u0179"), + DFA.unpack(u"\1\u017a"), + DFA.unpack(u""), + DFA.unpack(u"\1\u017b"), + DFA.unpack(u"\1\u017c"), + DFA.unpack(u"\1\u017d"), + DFA.unpack(u"\1\u017e"), + DFA.unpack(u"\1\75\13\uffff\12\75\7\uffff\32\75\4\uffff\1\75\1\uffff" + u"\32\75"), + DFA.unpack(u"\1\u0180"), + DFA.unpack(u""), + DFA.unpack(u"\1\u0181"), + DFA.unpack(u"\1\u0182"), + DFA.unpack(u"\1\u0183"), + DFA.unpack(u"\1\u0184"), + DFA.unpack(u"\1\u0185"), + DFA.unpack(u"\1\u0186"), + DFA.unpack(u"\1\u0187"), + DFA.unpack(u"\1\u0188"), + DFA.unpack(u"\1\u0189"), + DFA.unpack(u"\1\75\13\uffff\12\75\7\uffff\32\75\4\uffff\1\75\1\uffff" + u"\32\75"), + DFA.unpack(u"") + ] + + # class definition for DFA #35 + + DFA35 = DFA + + diff --git a/BaseTools/Source/Python/Ecc/CParser.py b/BaseTools/Source/Python/Ecc/CParser.py new file mode 100644 index 0000000000..194a6aa451 --- /dev/null +++ b/BaseTools/Source/Python/Ecc/CParser.py @@ -0,0 +1,18825 @@ +# $ANTLR 3.0.1 C.g 2009-02-16 16:02:50 + +from antlr3 import * +from antlr3.compat import set, frozenset + +import CodeFragment +import FileProfile + + + +# for convenience in actions +HIDDEN = BaseRecognizer.HIDDEN + +# token types +CHARACTER_LITERAL=8 +LETTER=11 +Exponent=15 +DECIMAL_LITERAL=7 +IntegerTypeSuffix=14 +UnicodeVocabulary=21 +HexDigit=13 +BS=20 +WS=19 +LINE_COMMAND=24 +COMMENT=22 +LINE_COMMENT=23 +OCTAL_LITERAL=6 +HEX_LITERAL=5 +FLOATING_POINT_LITERAL=10 +UnicodeEscape=18 +EscapeSequence=12 +EOF=-1 +STRING_LITERAL=9 +OctalEscape=17 +IDENTIFIER=4 +FloatTypeSuffix=16 + +# token names +tokenNames = [ + "", "", "", "", + "IDENTIFIER", "HEX_LITERAL", "OCTAL_LITERAL", "DECIMAL_LITERAL", "CHARACTER_LITERAL", + "STRING_LITERAL", "FLOATING_POINT_LITERAL", "LETTER", "EscapeSequence", + "HexDigit", "IntegerTypeSuffix", "Exponent", "FloatTypeSuffix", "OctalEscape", + "UnicodeEscape", "WS", "BS", "UnicodeVocabulary", "COMMENT", "LINE_COMMENT", + "LINE_COMMAND", "';'", "'typedef'", "','", "'='", "'extern'", "'static'", + "'auto'", "'register'", "'STATIC'", "'void'", "'char'", "'short'", "'int'", + "'long'", "'float'", "'double'", "'signed'", "'unsigned'", "'{'", "'}'", + "'struct'", "'union'", "':'", "'enum'", "'const'", "'volatile'", "'IN'", + "'OUT'", "'OPTIONAL'", "'CONST'", "'UNALIGNED'", "'VOLATILE'", "'GLOBAL_REMOVE_IF_UNREFERENCED'", + "'EFIAPI'", "'EFI_BOOTSERVICE'", "'EFI_RUNTIMESERVICE'", "'('", "')'", + "'['", "']'", "'*'", "'...'", "'+'", "'-'", "'/'", "'%'", "'++'", "'--'", + "'sizeof'", "'.'", "'->'", "'&'", "'~'", "'!'", "'*='", "'/='", "'%='", + "'+='", "'-='", "'<<='", "'>>='", "'&='", "'^='", "'|='", "'?'", "'||'", + "'&&'", "'|'", "'^'", "'=='", "'!='", "'<'", "'>'", "'<='", "'>='", + "'<<'", "'>>'", "'__asm__'", "'_asm'", "'__asm'", "'case'", "'default'", + "'if'", "'else'", "'switch'", "'while'", "'do'", "'for'", "'goto'", + "'continue'", "'break'", "'return'" +] + + +class function_definition_scope(object): + def __init__(self): + self.ModifierText = None + self.DeclText = None + self.LBLine = None + self.LBOffset = None + self.DeclLine = None + self.DeclOffset = None +class postfix_expression_scope(object): + def __init__(self): + self.FuncCallText = None + + +class CParser(Parser): + grammarFileName = "C.g" + tokenNames = tokenNames + + def __init__(self, input): + Parser.__init__(self, input) + self.ruleMemo = {} + + self.function_definition_stack = [] + self.postfix_expression_stack = [] + + + + + + + + + def printTokenInfo(self, line, offset, tokenText): + print str(line)+ ',' + str(offset) + ':' + str(tokenText) + + def StorePredicateExpression(self, StartLine, StartOffset, EndLine, EndOffset, Text): + PredExp = CodeFragment.PredicateExpression(Text, (StartLine, StartOffset), (EndLine, EndOffset)) + FileProfile.PredicateExpressionList.append(PredExp) + + def StoreEnumerationDefinition(self, StartLine, StartOffset, EndLine, EndOffset, Text): + EnumDef = CodeFragment.EnumerationDefinition(Text, (StartLine, StartOffset), (EndLine, EndOffset)) + FileProfile.EnumerationDefinitionList.append(EnumDef) + + def StoreStructUnionDefinition(self, StartLine, StartOffset, EndLine, EndOffset, Text): + SUDef = CodeFragment.StructUnionDefinition(Text, (StartLine, StartOffset), (EndLine, EndOffset)) + FileProfile.StructUnionDefinitionList.append(SUDef) + + def StoreTypedefDefinition(self, StartLine, StartOffset, EndLine, EndOffset, FromText, ToText): + Tdef = CodeFragment.TypedefDefinition(FromText, ToText, (StartLine, StartOffset), (EndLine, EndOffset)) + FileProfile.TypedefDefinitionList.append(Tdef) + + def StoreFunctionDefinition(self, StartLine, StartOffset, EndLine, EndOffset, ModifierText, DeclText, LeftBraceLine, LeftBraceOffset, DeclLine, DeclOffset): + FuncDef = CodeFragment.FunctionDefinition(ModifierText, DeclText, (StartLine, StartOffset), (EndLine, EndOffset), (LeftBraceLine, LeftBraceOffset), (DeclLine, DeclOffset)) + FileProfile.FunctionDefinitionList.append(FuncDef) + + def StoreVariableDeclaration(self, StartLine, StartOffset, EndLine, EndOffset, ModifierText, DeclText): + VarDecl = CodeFragment.VariableDeclaration(ModifierText, DeclText, (StartLine, StartOffset), (EndLine, EndOffset)) + FileProfile.VariableDeclarationList.append(VarDecl) + + def StoreFunctionCalling(self, StartLine, StartOffset, EndLine, EndOffset, FuncName, ParamList): + FuncCall = CodeFragment.FunctionCalling(FuncName, ParamList, (StartLine, StartOffset), (EndLine, EndOffset)) + FileProfile.FunctionCallingList.append(FuncCall) + + + + + # $ANTLR start translation_unit + # C.g:50:1: translation_unit : ( external_declaration )* ; + def translation_unit(self, ): + + translation_unit_StartIndex = self.input.index() + try: + try: + if self.backtracking > 0 and self.alreadyParsedRule(self.input, 1): + return + + # C.g:51:2: ( ( external_declaration )* ) + # C.g:51:4: ( external_declaration )* + # C.g:51:4: ( external_declaration )* + while True: #loop1 + alt1 = 2 + LA1_0 = self.input.LA(1) + + if (LA1_0 == IDENTIFIER or LA1_0 == 26 or (29 <= LA1_0 <= 42) or (45 <= LA1_0 <= 46) or (48 <= LA1_0 <= 61) or LA1_0 == 65) : + alt1 = 1 + + + if alt1 == 1: + # C.g:0:0: external_declaration + self.following.append(self.FOLLOW_external_declaration_in_translation_unit64) + self.external_declaration() + self.following.pop() + if self.failed: + return + + + else: + break #loop1 + + + + + + + except RecognitionException, re: + self.reportError(re) + self.recover(self.input, re) + finally: + if self.backtracking > 0: + self.memoize(self.input, 1, translation_unit_StartIndex) + + pass + + return + + # $ANTLR end translation_unit + + + # $ANTLR start external_declaration + # C.g:62:1: external_declaration options {k=1; } : ( ( ( declaration_specifiers )? declarator ( declaration )* '{' )=> function_definition | declaration | macro_statement ( ';' )? ); + def external_declaration(self, ): + + external_declaration_StartIndex = self.input.index() + try: + try: + if self.backtracking > 0 and self.alreadyParsedRule(self.input, 2): + return + + # C.g:67:2: ( ( ( declaration_specifiers )? declarator ( declaration )* '{' )=> function_definition | declaration | macro_statement ( ';' )? ) + alt3 = 3 + LA3_0 = self.input.LA(1) + + if ((29 <= LA3_0 <= 33)) : + LA3_1 = self.input.LA(2) + + if (self.synpred4()) : + alt3 = 1 + elif (self.synpred5()) : + alt3 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("62:1: external_declaration options {k=1; } : ( ( ( declaration_specifiers )? declarator ( declaration )* '{' )=> function_definition | declaration | macro_statement ( ';' )? );", 3, 1, self.input) + + raise nvae + + elif (LA3_0 == 34) : + LA3_2 = self.input.LA(2) + + if (self.synpred4()) : + alt3 = 1 + elif (self.synpred5()) : + alt3 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("62:1: external_declaration options {k=1; } : ( ( ( declaration_specifiers )? declarator ( declaration )* '{' )=> function_definition | declaration | macro_statement ( ';' )? );", 3, 2, self.input) + + raise nvae + + elif (LA3_0 == 35) : + LA3_3 = self.input.LA(2) + + if (self.synpred4()) : + alt3 = 1 + elif (self.synpred5()) : + alt3 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("62:1: external_declaration options {k=1; } : ( ( ( declaration_specifiers )? declarator ( declaration )* '{' )=> function_definition | declaration | macro_statement ( ';' )? );", 3, 3, self.input) + + raise nvae + + elif (LA3_0 == 36) : + LA3_4 = self.input.LA(2) + + if (self.synpred4()) : + alt3 = 1 + elif (self.synpred5()) : + alt3 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("62:1: external_declaration options {k=1; } : ( ( ( declaration_specifiers )? declarator ( declaration )* '{' )=> function_definition | declaration | macro_statement ( ';' )? );", 3, 4, self.input) + + raise nvae + + elif (LA3_0 == 37) : + LA3_5 = self.input.LA(2) + + if (self.synpred4()) : + alt3 = 1 + elif (self.synpred5()) : + alt3 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("62:1: external_declaration options {k=1; } : ( ( ( declaration_specifiers )? declarator ( declaration )* '{' )=> function_definition | declaration | macro_statement ( ';' )? );", 3, 5, self.input) + + raise nvae + + elif (LA3_0 == 38) : + LA3_6 = self.input.LA(2) + + if (self.synpred4()) : + alt3 = 1 + elif (self.synpred5()) : + alt3 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("62:1: external_declaration options {k=1; } : ( ( ( declaration_specifiers )? declarator ( declaration )* '{' )=> function_definition | declaration | macro_statement ( ';' )? );", 3, 6, self.input) + + raise nvae + + elif (LA3_0 == 39) : + LA3_7 = self.input.LA(2) + + if (self.synpred4()) : + alt3 = 1 + elif (self.synpred5()) : + alt3 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("62:1: external_declaration options {k=1; } : ( ( ( declaration_specifiers )? declarator ( declaration )* '{' )=> function_definition | declaration | macro_statement ( ';' )? );", 3, 7, self.input) + + raise nvae + + elif (LA3_0 == 40) : + LA3_8 = self.input.LA(2) + + if (self.synpred4()) : + alt3 = 1 + elif (self.synpred5()) : + alt3 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("62:1: external_declaration options {k=1; } : ( ( ( declaration_specifiers )? declarator ( declaration )* '{' )=> function_definition | declaration | macro_statement ( ';' )? );", 3, 8, self.input) + + raise nvae + + elif (LA3_0 == 41) : + LA3_9 = self.input.LA(2) + + if (self.synpred4()) : + alt3 = 1 + elif (self.synpred5()) : + alt3 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("62:1: external_declaration options {k=1; } : ( ( ( declaration_specifiers )? declarator ( declaration )* '{' )=> function_definition | declaration | macro_statement ( ';' )? );", 3, 9, self.input) + + raise nvae + + elif (LA3_0 == 42) : + LA3_10 = self.input.LA(2) + + if (self.synpred4()) : + alt3 = 1 + elif (self.synpred5()) : + alt3 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("62:1: external_declaration options {k=1; } : ( ( ( declaration_specifiers )? declarator ( declaration )* '{' )=> function_definition | declaration | macro_statement ( ';' )? );", 3, 10, self.input) + + raise nvae + + elif ((45 <= LA3_0 <= 46)) : + LA3_11 = self.input.LA(2) + + if (self.synpred4()) : + alt3 = 1 + elif (self.synpred5()) : + alt3 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("62:1: external_declaration options {k=1; } : ( ( ( declaration_specifiers )? declarator ( declaration )* '{' )=> function_definition | declaration | macro_statement ( ';' )? );", 3, 11, self.input) + + raise nvae + + elif (LA3_0 == 48) : + LA3_12 = self.input.LA(2) + + if (self.synpred4()) : + alt3 = 1 + elif (self.synpred5()) : + alt3 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("62:1: external_declaration options {k=1; } : ( ( ( declaration_specifiers )? declarator ( declaration )* '{' )=> function_definition | declaration | macro_statement ( ';' )? );", 3, 12, self.input) + + raise nvae + + elif (LA3_0 == IDENTIFIER) : + LA3_13 = self.input.LA(2) + + if (self.synpred4()) : + alt3 = 1 + elif (self.synpred5()) : + alt3 = 2 + elif (True) : + alt3 = 3 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("62:1: external_declaration options {k=1; } : ( ( ( declaration_specifiers )? declarator ( declaration )* '{' )=> function_definition | declaration | macro_statement ( ';' )? );", 3, 13, self.input) + + raise nvae + + elif (LA3_0 == 58) : + LA3_14 = self.input.LA(2) + + if (self.synpred4()) : + alt3 = 1 + elif (self.synpred5()) : + alt3 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("62:1: external_declaration options {k=1; } : ( ( ( declaration_specifiers )? declarator ( declaration )* '{' )=> function_definition | declaration | macro_statement ( ';' )? );", 3, 14, self.input) + + raise nvae + + elif (LA3_0 == 65) and (self.synpred4()): + alt3 = 1 + elif (LA3_0 == 59) : + LA3_16 = self.input.LA(2) + + if (self.synpred4()) : + alt3 = 1 + elif (self.synpred5()) : + alt3 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("62:1: external_declaration options {k=1; } : ( ( ( declaration_specifiers )? declarator ( declaration )* '{' )=> function_definition | declaration | macro_statement ( ';' )? );", 3, 16, self.input) + + raise nvae + + elif (LA3_0 == 60) : + LA3_17 = self.input.LA(2) + + if (self.synpred4()) : + alt3 = 1 + elif (self.synpred5()) : + alt3 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("62:1: external_declaration options {k=1; } : ( ( ( declaration_specifiers )? declarator ( declaration )* '{' )=> function_definition | declaration | macro_statement ( ';' )? );", 3, 17, self.input) + + raise nvae + + elif ((49 <= LA3_0 <= 57)) : + LA3_18 = self.input.LA(2) + + if (self.synpred4()) : + alt3 = 1 + elif (self.synpred5()) : + alt3 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("62:1: external_declaration options {k=1; } : ( ( ( declaration_specifiers )? declarator ( declaration )* '{' )=> function_definition | declaration | macro_statement ( ';' )? );", 3, 18, self.input) + + raise nvae + + elif (LA3_0 == 61) and (self.synpred4()): + alt3 = 1 + elif (LA3_0 == 26) : + alt3 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("62:1: external_declaration options {k=1; } : ( ( ( declaration_specifiers )? declarator ( declaration )* '{' )=> function_definition | declaration | macro_statement ( ';' )? );", 3, 0, self.input) + + raise nvae + + if alt3 == 1: + # C.g:67:4: ( ( declaration_specifiers )? declarator ( declaration )* '{' )=> function_definition + self.following.append(self.FOLLOW_function_definition_in_external_declaration103) + self.function_definition() + self.following.pop() + if self.failed: + return + + + elif alt3 == 2: + # C.g:68:4: declaration + self.following.append(self.FOLLOW_declaration_in_external_declaration108) + self.declaration() + self.following.pop() + if self.failed: + return + + + elif alt3 == 3: + # C.g:69:4: macro_statement ( ';' )? + self.following.append(self.FOLLOW_macro_statement_in_external_declaration113) + self.macro_statement() + self.following.pop() + if self.failed: + return + # C.g:69:20: ( ';' )? + alt2 = 2 + LA2_0 = self.input.LA(1) + + if (LA2_0 == 25) : + alt2 = 1 + if alt2 == 1: + # C.g:69:21: ';' + self.match(self.input, 25, self.FOLLOW_25_in_external_declaration116) + if self.failed: + return + + + + + + + except RecognitionException, re: + self.reportError(re) + self.recover(self.input, re) + finally: + if self.backtracking > 0: + self.memoize(self.input, 2, external_declaration_StartIndex) + + pass + + return + + # $ANTLR end external_declaration + + class function_definition_return(object): + def __init__(self): + self.start = None + self.stop = None + + + + # $ANTLR start function_definition + # C.g:74:1: function_definition : (d= declaration_specifiers )? declarator ( ( declaration )+ a= compound_statement | b= compound_statement ) ; + def function_definition(self, ): + self.function_definition_stack.append(function_definition_scope()) + retval = self.function_definition_return() + retval.start = self.input.LT(1) + function_definition_StartIndex = self.input.index() + d = None + + a = None + + b = None + + declarator1 = None + + + + self.function_definition_stack[-1].ModifierText = '' + self.function_definition_stack[-1].DeclText = '' + self.function_definition_stack[-1].LBLine = 0 + self.function_definition_stack[-1].LBOffset = 0 + self.function_definition_stack[-1].DeclLine = 0 + self.function_definition_stack[-1].DeclOffset = 0 + + try: + try: + if self.backtracking > 0 and self.alreadyParsedRule(self.input, 3): + return retval + + # C.g:94:2: ( (d= declaration_specifiers )? declarator ( ( declaration )+ a= compound_statement | b= compound_statement ) ) + # C.g:94:4: (d= declaration_specifiers )? declarator ( ( declaration )+ a= compound_statement | b= compound_statement ) + # C.g:94:5: (d= declaration_specifiers )? + alt4 = 2 + LA4 = self.input.LA(1) + if LA4 == 29 or LA4 == 30 or LA4 == 31 or LA4 == 32 or LA4 == 33 or LA4 == 34 or LA4 == 35 or LA4 == 36 or LA4 == 37 or LA4 == 38 or LA4 == 39 or LA4 == 40 or LA4 == 41 or LA4 == 42 or LA4 == 45 or LA4 == 46 or LA4 == 48 or LA4 == 49 or LA4 == 50 or LA4 == 51 or LA4 == 52 or LA4 == 53 or LA4 == 54 or LA4 == 55 or LA4 == 56 or LA4 == 57: + alt4 = 1 + elif LA4 == IDENTIFIER: + LA4 = self.input.LA(2) + if LA4 == 65: + alt4 = 1 + elif LA4 == 58: + LA4_21 = self.input.LA(3) + + if (self.synpred7()) : + alt4 = 1 + elif LA4 == 59: + LA4_22 = self.input.LA(3) + + if (self.synpred7()) : + alt4 = 1 + elif LA4 == 60: + LA4_23 = self.input.LA(3) + + if (self.synpred7()) : + alt4 = 1 + elif LA4 == IDENTIFIER: + LA4_24 = self.input.LA(3) + + if (self.synpred7()) : + alt4 = 1 + elif LA4 == 61: + LA4_25 = self.input.LA(3) + + if (self.synpred7()) : + alt4 = 1 + elif LA4 == 29 or LA4 == 30 or LA4 == 31 or LA4 == 32 or LA4 == 33: + LA4_26 = self.input.LA(3) + + if (self.synpred7()) : + alt4 = 1 + elif LA4 == 34: + LA4_27 = self.input.LA(3) + + if (self.synpred7()) : + alt4 = 1 + elif LA4 == 35: + LA4_28 = self.input.LA(3) + + if (self.synpred7()) : + alt4 = 1 + elif LA4 == 36: + LA4_29 = self.input.LA(3) + + if (self.synpred7()) : + alt4 = 1 + elif LA4 == 37: + LA4_30 = self.input.LA(3) + + if (self.synpred7()) : + alt4 = 1 + elif LA4 == 38: + LA4_31 = self.input.LA(3) + + if (self.synpred7()) : + alt4 = 1 + elif LA4 == 39: + LA4_32 = self.input.LA(3) + + if (self.synpred7()) : + alt4 = 1 + elif LA4 == 40: + LA4_33 = self.input.LA(3) + + if (self.synpred7()) : + alt4 = 1 + elif LA4 == 41: + LA4_34 = self.input.LA(3) + + if (self.synpred7()) : + alt4 = 1 + elif LA4 == 42: + LA4_35 = self.input.LA(3) + + if (self.synpred7()) : + alt4 = 1 + elif LA4 == 45 or LA4 == 46: + LA4_36 = self.input.LA(3) + + if (self.synpred7()) : + alt4 = 1 + elif LA4 == 48: + LA4_37 = self.input.LA(3) + + if (self.synpred7()) : + alt4 = 1 + elif LA4 == 49 or LA4 == 50 or LA4 == 51 or LA4 == 52 or LA4 == 53 or LA4 == 54 or LA4 == 55 or LA4 == 56 or LA4 == 57: + LA4_38 = self.input.LA(3) + + if (self.synpred7()) : + alt4 = 1 + elif LA4 == 58: + LA4_14 = self.input.LA(2) + + if (self.synpred7()) : + alt4 = 1 + elif LA4 == 59: + LA4_16 = self.input.LA(2) + + if (self.synpred7()) : + alt4 = 1 + elif LA4 == 60: + LA4_17 = self.input.LA(2) + + if (self.synpred7()) : + alt4 = 1 + if alt4 == 1: + # C.g:0:0: d= declaration_specifiers + self.following.append(self.FOLLOW_declaration_specifiers_in_function_definition147) + d = self.declaration_specifiers() + self.following.pop() + if self.failed: + return retval + + + + self.following.append(self.FOLLOW_declarator_in_function_definition150) + declarator1 = self.declarator() + self.following.pop() + if self.failed: + return retval + # C.g:95:3: ( ( declaration )+ a= compound_statement | b= compound_statement ) + alt6 = 2 + LA6_0 = self.input.LA(1) + + if (LA6_0 == IDENTIFIER or LA6_0 == 26 or (29 <= LA6_0 <= 42) or (45 <= LA6_0 <= 46) or (48 <= LA6_0 <= 60)) : + alt6 = 1 + elif (LA6_0 == 43) : + alt6 = 2 + else: + if self.backtracking > 0: + self.failed = True + return retval + + nvae = NoViableAltException("95:3: ( ( declaration )+ a= compound_statement | b= compound_statement )", 6, 0, self.input) + + raise nvae + + if alt6 == 1: + # C.g:95:5: ( declaration )+ a= compound_statement + # C.g:95:5: ( declaration )+ + cnt5 = 0 + while True: #loop5 + alt5 = 2 + LA5_0 = self.input.LA(1) + + if (LA5_0 == IDENTIFIER or LA5_0 == 26 or (29 <= LA5_0 <= 42) or (45 <= LA5_0 <= 46) or (48 <= LA5_0 <= 60)) : + alt5 = 1 + + + if alt5 == 1: + # C.g:0:0: declaration + self.following.append(self.FOLLOW_declaration_in_function_definition156) + self.declaration() + self.following.pop() + if self.failed: + return retval + + + else: + if cnt5 >= 1: + break #loop5 + + if self.backtracking > 0: + self.failed = True + return retval + + eee = EarlyExitException(5, self.input) + raise eee + + cnt5 += 1 + + + self.following.append(self.FOLLOW_compound_statement_in_function_definition161) + a = self.compound_statement() + self.following.pop() + if self.failed: + return retval + + + elif alt6 == 2: + # C.g:96:5: b= compound_statement + self.following.append(self.FOLLOW_compound_statement_in_function_definition170) + b = self.compound_statement() + self.following.pop() + if self.failed: + return retval + + + + if self.backtracking == 0: + + if d != None: + self.function_definition_stack[-1].ModifierText = self.input.toString(d.start,d.stop) + else: + self.function_definition_stack[-1].ModifierText = '' + self.function_definition_stack[-1].DeclText = self.input.toString(declarator1.start,declarator1.stop) + self.function_definition_stack[-1].DeclLine = declarator1.start.line + self.function_definition_stack[-1].DeclOffset = declarator1.start.charPositionInLine + if a != None: + self.function_definition_stack[-1].LBLine = a.start.line + self.function_definition_stack[-1].LBOffset = a.start.charPositionInLine + else: + self.function_definition_stack[-1].LBLine = b.start.line + self.function_definition_stack[-1].LBOffset = b.start.charPositionInLine + + + + + + retval.stop = self.input.LT(-1) + + if self.backtracking == 0: + + self.StoreFunctionDefinition(retval.start.line, retval.start.charPositionInLine, retval.stop.line, retval.stop.charPositionInLine, self.function_definition_stack[-1].ModifierText, self.function_definition_stack[-1].DeclText, self.function_definition_stack[-1].LBLine, self.function_definition_stack[-1].LBOffset, self.function_definition_stack[-1].DeclLine, self.function_definition_stack[-1].DeclOffset) + + + + except RecognitionException, re: + self.reportError(re) + self.recover(self.input, re) + finally: + if self.backtracking > 0: + self.memoize(self.input, 3, function_definition_StartIndex) + + self.function_definition_stack.pop() + pass + + return retval + + # $ANTLR end function_definition + + + # $ANTLR start declaration + # C.g:114:1: declaration : (a= 'typedef' (b= declaration_specifiers )? c= init_declarator_list d= ';' | s= declaration_specifiers (t= init_declarator_list )? e= ';' ); + def declaration(self, ): + + declaration_StartIndex = self.input.index() + a = None + d = None + e = None + b = None + + c = None + + s = None + + t = None + + + try: + try: + if self.backtracking > 0 and self.alreadyParsedRule(self.input, 4): + return + + # C.g:115:2: (a= 'typedef' (b= declaration_specifiers )? c= init_declarator_list d= ';' | s= declaration_specifiers (t= init_declarator_list )? e= ';' ) + alt9 = 2 + LA9_0 = self.input.LA(1) + + if (LA9_0 == 26) : + alt9 = 1 + elif (LA9_0 == IDENTIFIER or (29 <= LA9_0 <= 42) or (45 <= LA9_0 <= 46) or (48 <= LA9_0 <= 60)) : + alt9 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("114:1: declaration : (a= 'typedef' (b= declaration_specifiers )? c= init_declarator_list d= ';' | s= declaration_specifiers (t= init_declarator_list )? e= ';' );", 9, 0, self.input) + + raise nvae + + if alt9 == 1: + # C.g:115:4: a= 'typedef' (b= declaration_specifiers )? c= init_declarator_list d= ';' + a = self.input.LT(1) + self.match(self.input, 26, self.FOLLOW_26_in_declaration193) + if self.failed: + return + # C.g:115:17: (b= declaration_specifiers )? + alt7 = 2 + LA7 = self.input.LA(1) + if LA7 == 29 or LA7 == 30 or LA7 == 31 or LA7 == 32 or LA7 == 33 or LA7 == 34 or LA7 == 35 or LA7 == 36 or LA7 == 37 or LA7 == 38 or LA7 == 39 or LA7 == 40 or LA7 == 41 or LA7 == 42 or LA7 == 45 or LA7 == 46 or LA7 == 48 or LA7 == 49 or LA7 == 50 or LA7 == 51 or LA7 == 52 or LA7 == 53 or LA7 == 54 or LA7 == 55 or LA7 == 56 or LA7 == 57: + alt7 = 1 + elif LA7 == IDENTIFIER: + LA7_13 = self.input.LA(2) + + if (LA7_13 == IDENTIFIER or (29 <= LA7_13 <= 42) or (45 <= LA7_13 <= 46) or (48 <= LA7_13 <= 60) or LA7_13 == 65) : + alt7 = 1 + elif (LA7_13 == 61) : + LA7_25 = self.input.LA(3) + + if (self.synpred10()) : + alt7 = 1 + elif LA7 == 58: + LA7_14 = self.input.LA(2) + + if (self.synpred10()) : + alt7 = 1 + elif LA7 == 59: + LA7_16 = self.input.LA(2) + + if (self.synpred10()) : + alt7 = 1 + elif LA7 == 60: + LA7_17 = self.input.LA(2) + + if (self.synpred10()) : + alt7 = 1 + if alt7 == 1: + # C.g:0:0: b= declaration_specifiers + self.following.append(self.FOLLOW_declaration_specifiers_in_declaration197) + b = self.declaration_specifiers() + self.following.pop() + if self.failed: + return + + + + self.following.append(self.FOLLOW_init_declarator_list_in_declaration206) + c = self.init_declarator_list() + self.following.pop() + if self.failed: + return + d = self.input.LT(1) + self.match(self.input, 25, self.FOLLOW_25_in_declaration210) + if self.failed: + return + if self.backtracking == 0: + + if b != None: + self.StoreTypedefDefinition(a.line, a.charPositionInLine, d.line, d.charPositionInLine, self.input.toString(b.start,b.stop), self.input.toString(c.start,c.stop)) + else: + self.StoreTypedefDefinition(a.line, a.charPositionInLine, d.line, d.charPositionInLine, '', self.input.toString(c.start,c.stop)) + + + + + elif alt9 == 2: + # C.g:123:4: s= declaration_specifiers (t= init_declarator_list )? e= ';' + self.following.append(self.FOLLOW_declaration_specifiers_in_declaration224) + s = self.declaration_specifiers() + self.following.pop() + if self.failed: + return + # C.g:123:30: (t= init_declarator_list )? + alt8 = 2 + LA8_0 = self.input.LA(1) + + if (LA8_0 == IDENTIFIER or (58 <= LA8_0 <= 61) or LA8_0 == 65) : + alt8 = 1 + if alt8 == 1: + # C.g:0:0: t= init_declarator_list + self.following.append(self.FOLLOW_init_declarator_list_in_declaration228) + t = self.init_declarator_list() + self.following.pop() + if self.failed: + return + + + + e = self.input.LT(1) + self.match(self.input, 25, self.FOLLOW_25_in_declaration233) + if self.failed: + return + if self.backtracking == 0: + + if t != None: + self.StoreVariableDeclaration(s.start.line, s.start.charPositionInLine, t.start.line, t.start.charPositionInLine, self.input.toString(s.start,s.stop), self.input.toString(t.start,t.stop)) + + + + + + except RecognitionException, re: + self.reportError(re) + self.recover(self.input, re) + finally: + if self.backtracking > 0: + self.memoize(self.input, 4, declaration_StartIndex) + + pass + + return + + # $ANTLR end declaration + + class declaration_specifiers_return(object): + def __init__(self): + self.start = None + self.stop = None + + + + # $ANTLR start declaration_specifiers + # C.g:130:1: declaration_specifiers : ( storage_class_specifier | type_specifier | type_qualifier )+ ; + def declaration_specifiers(self, ): + + retval = self.declaration_specifiers_return() + retval.start = self.input.LT(1) + declaration_specifiers_StartIndex = self.input.index() + try: + try: + if self.backtracking > 0 and self.alreadyParsedRule(self.input, 5): + return retval + + # C.g:131:2: ( ( storage_class_specifier | type_specifier | type_qualifier )+ ) + # C.g:131:6: ( storage_class_specifier | type_specifier | type_qualifier )+ + # C.g:131:6: ( storage_class_specifier | type_specifier | type_qualifier )+ + cnt10 = 0 + while True: #loop10 + alt10 = 4 + LA10 = self.input.LA(1) + if LA10 == 58: + LA10_2 = self.input.LA(2) + + if (self.synpred15()) : + alt10 = 3 + + + elif LA10 == 59: + LA10_3 = self.input.LA(2) + + if (self.synpred15()) : + alt10 = 3 + + + elif LA10 == 60: + LA10_4 = self.input.LA(2) + + if (self.synpred15()) : + alt10 = 3 + + + elif LA10 == IDENTIFIER: + LA10_5 = self.input.LA(2) + + if (self.synpred14()) : + alt10 = 2 + + + elif LA10 == 53: + LA10_9 = self.input.LA(2) + + if (self.synpred15()) : + alt10 = 3 + + + elif LA10 == 29 or LA10 == 30 or LA10 == 31 or LA10 == 32 or LA10 == 33: + alt10 = 1 + elif LA10 == 34 or LA10 == 35 or LA10 == 36 or LA10 == 37 or LA10 == 38 or LA10 == 39 or LA10 == 40 or LA10 == 41 or LA10 == 42 or LA10 == 45 or LA10 == 46 or LA10 == 48: + alt10 = 2 + elif LA10 == 49 or LA10 == 50 or LA10 == 51 or LA10 == 52 or LA10 == 54 or LA10 == 55 or LA10 == 56 or LA10 == 57: + alt10 = 3 + + if alt10 == 1: + # C.g:131:10: storage_class_specifier + self.following.append(self.FOLLOW_storage_class_specifier_in_declaration_specifiers254) + self.storage_class_specifier() + self.following.pop() + if self.failed: + return retval + + + elif alt10 == 2: + # C.g:132:7: type_specifier + self.following.append(self.FOLLOW_type_specifier_in_declaration_specifiers262) + self.type_specifier() + self.following.pop() + if self.failed: + return retval + + + elif alt10 == 3: + # C.g:133:13: type_qualifier + self.following.append(self.FOLLOW_type_qualifier_in_declaration_specifiers276) + self.type_qualifier() + self.following.pop() + if self.failed: + return retval + + + else: + if cnt10 >= 1: + break #loop10 + + if self.backtracking > 0: + self.failed = True + return retval + + eee = EarlyExitException(10, self.input) + raise eee + + cnt10 += 1 + + + + + + retval.stop = self.input.LT(-1) + + + except RecognitionException, re: + self.reportError(re) + self.recover(self.input, re) + finally: + if self.backtracking > 0: + self.memoize(self.input, 5, declaration_specifiers_StartIndex) + + pass + + return retval + + # $ANTLR end declaration_specifiers + + class init_declarator_list_return(object): + def __init__(self): + self.start = None + self.stop = None + + + + # $ANTLR start init_declarator_list + # C.g:137:1: init_declarator_list : init_declarator ( ',' init_declarator )* ; + def init_declarator_list(self, ): + + retval = self.init_declarator_list_return() + retval.start = self.input.LT(1) + init_declarator_list_StartIndex = self.input.index() + try: + try: + if self.backtracking > 0 and self.alreadyParsedRule(self.input, 6): + return retval + + # C.g:138:2: ( init_declarator ( ',' init_declarator )* ) + # C.g:138:4: init_declarator ( ',' init_declarator )* + self.following.append(self.FOLLOW_init_declarator_in_init_declarator_list298) + self.init_declarator() + self.following.pop() + if self.failed: + return retval + # C.g:138:20: ( ',' init_declarator )* + while True: #loop11 + alt11 = 2 + LA11_0 = self.input.LA(1) + + if (LA11_0 == 27) : + alt11 = 1 + + + if alt11 == 1: + # C.g:138:21: ',' init_declarator + self.match(self.input, 27, self.FOLLOW_27_in_init_declarator_list301) + if self.failed: + return retval + self.following.append(self.FOLLOW_init_declarator_in_init_declarator_list303) + self.init_declarator() + self.following.pop() + if self.failed: + return retval + + + else: + break #loop11 + + + + + + retval.stop = self.input.LT(-1) + + + except RecognitionException, re: + self.reportError(re) + self.recover(self.input, re) + finally: + if self.backtracking > 0: + self.memoize(self.input, 6, init_declarator_list_StartIndex) + + pass + + return retval + + # $ANTLR end init_declarator_list + + + # $ANTLR start init_declarator + # C.g:141:1: init_declarator : declarator ( '=' initializer )? ; + def init_declarator(self, ): + + init_declarator_StartIndex = self.input.index() + try: + try: + if self.backtracking > 0 and self.alreadyParsedRule(self.input, 7): + return + + # C.g:142:2: ( declarator ( '=' initializer )? ) + # C.g:142:4: declarator ( '=' initializer )? + self.following.append(self.FOLLOW_declarator_in_init_declarator316) + self.declarator() + self.following.pop() + if self.failed: + return + # C.g:142:15: ( '=' initializer )? + alt12 = 2 + LA12_0 = self.input.LA(1) + + if (LA12_0 == 28) : + alt12 = 1 + if alt12 == 1: + # C.g:142:16: '=' initializer + self.match(self.input, 28, self.FOLLOW_28_in_init_declarator319) + if self.failed: + return + self.following.append(self.FOLLOW_initializer_in_init_declarator321) + self.initializer() + self.following.pop() + if self.failed: + return + + + + + + + + except RecognitionException, re: + self.reportError(re) + self.recover(self.input, re) + finally: + if self.backtracking > 0: + self.memoize(self.input, 7, init_declarator_StartIndex) + + pass + + return + + # $ANTLR end init_declarator + + + # $ANTLR start storage_class_specifier + # C.g:145:1: storage_class_specifier : ( 'extern' | 'static' | 'auto' | 'register' | 'STATIC' ); + def storage_class_specifier(self, ): + + storage_class_specifier_StartIndex = self.input.index() + try: + try: + if self.backtracking > 0 and self.alreadyParsedRule(self.input, 8): + return + + # C.g:146:2: ( 'extern' | 'static' | 'auto' | 'register' | 'STATIC' ) + # C.g: + if (29 <= self.input.LA(1) <= 33): + self.input.consume(); + self.errorRecovery = False + self.failed = False + + else: + if self.backtracking > 0: + self.failed = True + return + + mse = MismatchedSetException(None, self.input) + self.recoverFromMismatchedSet( + self.input, mse, self.FOLLOW_set_in_storage_class_specifier0 + ) + raise mse + + + + + + + except RecognitionException, re: + self.reportError(re) + self.recover(self.input, re) + finally: + if self.backtracking > 0: + self.memoize(self.input, 8, storage_class_specifier_StartIndex) + + pass + + return + + # $ANTLR end storage_class_specifier + + + # $ANTLR start type_specifier + # C.g:153:1: type_specifier : ( 'void' | 'char' | 'short' | 'int' | 'long' | 'float' | 'double' | 'signed' | 'unsigned' | s= struct_or_union_specifier | e= enum_specifier | ( IDENTIFIER ( type_qualifier )* declarator )=> type_id ); + def type_specifier(self, ): + + type_specifier_StartIndex = self.input.index() + s = None + + e = None + + + try: + try: + if self.backtracking > 0 and self.alreadyParsedRule(self.input, 9): + return + + # C.g:154:2: ( 'void' | 'char' | 'short' | 'int' | 'long' | 'float' | 'double' | 'signed' | 'unsigned' | s= struct_or_union_specifier | e= enum_specifier | ( IDENTIFIER ( type_qualifier )* declarator )=> type_id ) + alt13 = 12 + LA13_0 = self.input.LA(1) + + if (LA13_0 == 34) : + alt13 = 1 + elif (LA13_0 == 35) : + alt13 = 2 + elif (LA13_0 == 36) : + alt13 = 3 + elif (LA13_0 == 37) : + alt13 = 4 + elif (LA13_0 == 38) : + alt13 = 5 + elif (LA13_0 == 39) : + alt13 = 6 + elif (LA13_0 == 40) : + alt13 = 7 + elif (LA13_0 == 41) : + alt13 = 8 + elif (LA13_0 == 42) : + alt13 = 9 + elif ((45 <= LA13_0 <= 46)) : + alt13 = 10 + elif (LA13_0 == 48) : + alt13 = 11 + elif (LA13_0 == IDENTIFIER) and (self.synpred34()): + alt13 = 12 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("153:1: type_specifier : ( 'void' | 'char' | 'short' | 'int' | 'long' | 'float' | 'double' | 'signed' | 'unsigned' | s= struct_or_union_specifier | e= enum_specifier | ( IDENTIFIER ( type_qualifier )* declarator )=> type_id );", 13, 0, self.input) + + raise nvae + + if alt13 == 1: + # C.g:154:4: 'void' + self.match(self.input, 34, self.FOLLOW_34_in_type_specifier366) + if self.failed: + return + + + elif alt13 == 2: + # C.g:155:4: 'char' + self.match(self.input, 35, self.FOLLOW_35_in_type_specifier371) + if self.failed: + return + + + elif alt13 == 3: + # C.g:156:4: 'short' + self.match(self.input, 36, self.FOLLOW_36_in_type_specifier376) + if self.failed: + return + + + elif alt13 == 4: + # C.g:157:4: 'int' + self.match(self.input, 37, self.FOLLOW_37_in_type_specifier381) + if self.failed: + return + + + elif alt13 == 5: + # C.g:158:4: 'long' + self.match(self.input, 38, self.FOLLOW_38_in_type_specifier386) + if self.failed: + return + + + elif alt13 == 6: + # C.g:159:4: 'float' + self.match(self.input, 39, self.FOLLOW_39_in_type_specifier391) + if self.failed: + return + + + elif alt13 == 7: + # C.g:160:4: 'double' + self.match(self.input, 40, self.FOLLOW_40_in_type_specifier396) + if self.failed: + return + + + elif alt13 == 8: + # C.g:161:4: 'signed' + self.match(self.input, 41, self.FOLLOW_41_in_type_specifier401) + if self.failed: + return + + + elif alt13 == 9: + # C.g:162:4: 'unsigned' + self.match(self.input, 42, self.FOLLOW_42_in_type_specifier406) + if self.failed: + return + + + elif alt13 == 10: + # C.g:163:4: s= struct_or_union_specifier + self.following.append(self.FOLLOW_struct_or_union_specifier_in_type_specifier413) + s = self.struct_or_union_specifier() + self.following.pop() + if self.failed: + return + if self.backtracking == 0: + + if s.stop != None: + self.StoreStructUnionDefinition(s.start.line, s.start.charPositionInLine, s.stop.line, s.stop.charPositionInLine, self.input.toString(s.start,s.stop)) + + + + + elif alt13 == 11: + # C.g:168:4: e= enum_specifier + self.following.append(self.FOLLOW_enum_specifier_in_type_specifier423) + e = self.enum_specifier() + self.following.pop() + if self.failed: + return + if self.backtracking == 0: + + if e.stop != None: + self.StoreEnumerationDefinition(e.start.line, e.start.charPositionInLine, e.stop.line, e.stop.charPositionInLine, self.input.toString(e.start,e.stop)) + + + + + elif alt13 == 12: + # C.g:173:4: ( IDENTIFIER ( type_qualifier )* declarator )=> type_id + self.following.append(self.FOLLOW_type_id_in_type_specifier441) + self.type_id() + self.following.pop() + if self.failed: + return + + + + except RecognitionException, re: + self.reportError(re) + self.recover(self.input, re) + finally: + if self.backtracking > 0: + self.memoize(self.input, 9, type_specifier_StartIndex) + + pass + + return + + # $ANTLR end type_specifier + + + # $ANTLR start type_id + # C.g:176:1: type_id : IDENTIFIER ; + def type_id(self, ): + + type_id_StartIndex = self.input.index() + try: + try: + if self.backtracking > 0 and self.alreadyParsedRule(self.input, 10): + return + + # C.g:177:5: ( IDENTIFIER ) + # C.g:177:9: IDENTIFIER + self.match(self.input, IDENTIFIER, self.FOLLOW_IDENTIFIER_in_type_id457) + if self.failed: + return + + + + + except RecognitionException, re: + self.reportError(re) + self.recover(self.input, re) + finally: + if self.backtracking > 0: + self.memoize(self.input, 10, type_id_StartIndex) + + pass + + return + + # $ANTLR end type_id + + class struct_or_union_specifier_return(object): + def __init__(self): + self.start = None + self.stop = None + + + + # $ANTLR start struct_or_union_specifier + # C.g:181:1: struct_or_union_specifier options {k=3; } : ( struct_or_union ( IDENTIFIER )? '{' struct_declaration_list '}' | struct_or_union IDENTIFIER ); + def struct_or_union_specifier(self, ): + + retval = self.struct_or_union_specifier_return() + retval.start = self.input.LT(1) + struct_or_union_specifier_StartIndex = self.input.index() + try: + try: + if self.backtracking > 0 and self.alreadyParsedRule(self.input, 11): + return retval + + # C.g:183:2: ( struct_or_union ( IDENTIFIER )? '{' struct_declaration_list '}' | struct_or_union IDENTIFIER ) + alt15 = 2 + LA15_0 = self.input.LA(1) + + if ((45 <= LA15_0 <= 46)) : + LA15_1 = self.input.LA(2) + + if (LA15_1 == IDENTIFIER) : + LA15_2 = self.input.LA(3) + + if (LA15_2 == 43) : + alt15 = 1 + elif (LA15_2 == EOF or LA15_2 == IDENTIFIER or LA15_2 == 25 or LA15_2 == 27 or (29 <= LA15_2 <= 42) or (45 <= LA15_2 <= 63) or LA15_2 == 65) : + alt15 = 2 + else: + if self.backtracking > 0: + self.failed = True + return retval + + nvae = NoViableAltException("181:1: struct_or_union_specifier options {k=3; } : ( struct_or_union ( IDENTIFIER )? '{' struct_declaration_list '}' | struct_or_union IDENTIFIER );", 15, 2, self.input) + + raise nvae + + elif (LA15_1 == 43) : + alt15 = 1 + else: + if self.backtracking > 0: + self.failed = True + return retval + + nvae = NoViableAltException("181:1: struct_or_union_specifier options {k=3; } : ( struct_or_union ( IDENTIFIER )? '{' struct_declaration_list '}' | struct_or_union IDENTIFIER );", 15, 1, self.input) + + raise nvae + + else: + if self.backtracking > 0: + self.failed = True + return retval + + nvae = NoViableAltException("181:1: struct_or_union_specifier options {k=3; } : ( struct_or_union ( IDENTIFIER )? '{' struct_declaration_list '}' | struct_or_union IDENTIFIER );", 15, 0, self.input) + + raise nvae + + if alt15 == 1: + # C.g:183:4: struct_or_union ( IDENTIFIER )? '{' struct_declaration_list '}' + self.following.append(self.FOLLOW_struct_or_union_in_struct_or_union_specifier484) + self.struct_or_union() + self.following.pop() + if self.failed: + return retval + # C.g:183:20: ( IDENTIFIER )? + alt14 = 2 + LA14_0 = self.input.LA(1) + + if (LA14_0 == IDENTIFIER) : + alt14 = 1 + if alt14 == 1: + # C.g:0:0: IDENTIFIER + self.match(self.input, IDENTIFIER, self.FOLLOW_IDENTIFIER_in_struct_or_union_specifier486) + if self.failed: + return retval + + + + self.match(self.input, 43, self.FOLLOW_43_in_struct_or_union_specifier489) + if self.failed: + return retval + self.following.append(self.FOLLOW_struct_declaration_list_in_struct_or_union_specifier491) + self.struct_declaration_list() + self.following.pop() + if self.failed: + return retval + self.match(self.input, 44, self.FOLLOW_44_in_struct_or_union_specifier493) + if self.failed: + return retval + + + elif alt15 == 2: + # C.g:184:4: struct_or_union IDENTIFIER + self.following.append(self.FOLLOW_struct_or_union_in_struct_or_union_specifier498) + self.struct_or_union() + self.following.pop() + if self.failed: + return retval + self.match(self.input, IDENTIFIER, self.FOLLOW_IDENTIFIER_in_struct_or_union_specifier500) + if self.failed: + return retval + + + retval.stop = self.input.LT(-1) + + + except RecognitionException, re: + self.reportError(re) + self.recover(self.input, re) + finally: + if self.backtracking > 0: + self.memoize(self.input, 11, struct_or_union_specifier_StartIndex) + + pass + + return retval + + # $ANTLR end struct_or_union_specifier + + + # $ANTLR start struct_or_union + # C.g:187:1: struct_or_union : ( 'struct' | 'union' ); + def struct_or_union(self, ): + + struct_or_union_StartIndex = self.input.index() + try: + try: + if self.backtracking > 0 and self.alreadyParsedRule(self.input, 12): + return + + # C.g:188:2: ( 'struct' | 'union' ) + # C.g: + if (45 <= self.input.LA(1) <= 46): + self.input.consume(); + self.errorRecovery = False + self.failed = False + + else: + if self.backtracking > 0: + self.failed = True + return + + mse = MismatchedSetException(None, self.input) + self.recoverFromMismatchedSet( + self.input, mse, self.FOLLOW_set_in_struct_or_union0 + ) + raise mse + + + + + + + except RecognitionException, re: + self.reportError(re) + self.recover(self.input, re) + finally: + if self.backtracking > 0: + self.memoize(self.input, 12, struct_or_union_StartIndex) + + pass + + return + + # $ANTLR end struct_or_union + + + # $ANTLR start struct_declaration_list + # C.g:192:1: struct_declaration_list : ( struct_declaration )+ ; + def struct_declaration_list(self, ): + + struct_declaration_list_StartIndex = self.input.index() + try: + try: + if self.backtracking > 0 and self.alreadyParsedRule(self.input, 13): + return + + # C.g:193:2: ( ( struct_declaration )+ ) + # C.g:193:4: ( struct_declaration )+ + # C.g:193:4: ( struct_declaration )+ + cnt16 = 0 + while True: #loop16 + alt16 = 2 + LA16_0 = self.input.LA(1) + + if (LA16_0 == IDENTIFIER or (34 <= LA16_0 <= 42) or (45 <= LA16_0 <= 46) or (48 <= LA16_0 <= 60)) : + alt16 = 1 + + + if alt16 == 1: + # C.g:0:0: struct_declaration + self.following.append(self.FOLLOW_struct_declaration_in_struct_declaration_list527) + self.struct_declaration() + self.following.pop() + if self.failed: + return + + + else: + if cnt16 >= 1: + break #loop16 + + if self.backtracking > 0: + self.failed = True + return + + eee = EarlyExitException(16, self.input) + raise eee + + cnt16 += 1 + + + + + + + except RecognitionException, re: + self.reportError(re) + self.recover(self.input, re) + finally: + if self.backtracking > 0: + self.memoize(self.input, 13, struct_declaration_list_StartIndex) + + pass + + return + + # $ANTLR end struct_declaration_list + + + # $ANTLR start struct_declaration + # C.g:196:1: struct_declaration : specifier_qualifier_list struct_declarator_list ';' ; + def struct_declaration(self, ): + + struct_declaration_StartIndex = self.input.index() + try: + try: + if self.backtracking > 0 and self.alreadyParsedRule(self.input, 14): + return + + # C.g:197:2: ( specifier_qualifier_list struct_declarator_list ';' ) + # C.g:197:4: specifier_qualifier_list struct_declarator_list ';' + self.following.append(self.FOLLOW_specifier_qualifier_list_in_struct_declaration539) + self.specifier_qualifier_list() + self.following.pop() + if self.failed: + return + self.following.append(self.FOLLOW_struct_declarator_list_in_struct_declaration541) + self.struct_declarator_list() + self.following.pop() + if self.failed: + return + self.match(self.input, 25, self.FOLLOW_25_in_struct_declaration543) + if self.failed: + return + + + + + except RecognitionException, re: + self.reportError(re) + self.recover(self.input, re) + finally: + if self.backtracking > 0: + self.memoize(self.input, 14, struct_declaration_StartIndex) + + pass + + return + + # $ANTLR end struct_declaration + + + # $ANTLR start specifier_qualifier_list + # C.g:200:1: specifier_qualifier_list : ( type_qualifier | type_specifier )+ ; + def specifier_qualifier_list(self, ): + + specifier_qualifier_list_StartIndex = self.input.index() + try: + try: + if self.backtracking > 0 and self.alreadyParsedRule(self.input, 15): + return + + # C.g:201:2: ( ( type_qualifier | type_specifier )+ ) + # C.g:201:4: ( type_qualifier | type_specifier )+ + # C.g:201:4: ( type_qualifier | type_specifier )+ + cnt17 = 0 + while True: #loop17 + alt17 = 3 + LA17 = self.input.LA(1) + if LA17 == 58: + LA17_2 = self.input.LA(2) + + if (self.synpred39()) : + alt17 = 1 + + + elif LA17 == 59: + LA17_3 = self.input.LA(2) + + if (self.synpred39()) : + alt17 = 1 + + + elif LA17 == 60: + LA17_4 = self.input.LA(2) + + if (self.synpred39()) : + alt17 = 1 + + + elif LA17 == IDENTIFIER: + LA17 = self.input.LA(2) + if LA17 == EOF or LA17 == IDENTIFIER or LA17 == 34 or LA17 == 35 or LA17 == 36 or LA17 == 37 or LA17 == 38 or LA17 == 39 or LA17 == 40 or LA17 == 41 or LA17 == 42 or LA17 == 45 or LA17 == 46 or LA17 == 48 or LA17 == 49 or LA17 == 50 or LA17 == 51 or LA17 == 52 or LA17 == 53 or LA17 == 54 or LA17 == 55 or LA17 == 56 or LA17 == 57 or LA17 == 58 or LA17 == 59 or LA17 == 60 or LA17 == 62 or LA17 == 65: + alt17 = 2 + elif LA17 == 61: + LA17_94 = self.input.LA(3) + + if (self.synpred40()) : + alt17 = 2 + + + elif LA17 == 47: + LA17_95 = self.input.LA(3) + + if (self.synpred40()) : + alt17 = 2 + + + elif LA17 == 63: + LA17_96 = self.input.LA(3) + + if (self.synpred40()) : + alt17 = 2 + + + + elif LA17 == 49 or LA17 == 50 or LA17 == 51 or LA17 == 52 or LA17 == 53 or LA17 == 54 or LA17 == 55 or LA17 == 56 or LA17 == 57: + alt17 = 1 + elif LA17 == 34 or LA17 == 35 or LA17 == 36 or LA17 == 37 or LA17 == 38 or LA17 == 39 or LA17 == 40 or LA17 == 41 or LA17 == 42 or LA17 == 45 or LA17 == 46 or LA17 == 48: + alt17 = 2 + + if alt17 == 1: + # C.g:201:6: type_qualifier + self.following.append(self.FOLLOW_type_qualifier_in_specifier_qualifier_list556) + self.type_qualifier() + self.following.pop() + if self.failed: + return + + + elif alt17 == 2: + # C.g:201:23: type_specifier + self.following.append(self.FOLLOW_type_specifier_in_specifier_qualifier_list560) + self.type_specifier() + self.following.pop() + if self.failed: + return + + + else: + if cnt17 >= 1: + break #loop17 + + if self.backtracking > 0: + self.failed = True + return + + eee = EarlyExitException(17, self.input) + raise eee + + cnt17 += 1 + + + + + + + except RecognitionException, re: + self.reportError(re) + self.recover(self.input, re) + finally: + if self.backtracking > 0: + self.memoize(self.input, 15, specifier_qualifier_list_StartIndex) + + pass + + return + + # $ANTLR end specifier_qualifier_list + + + # $ANTLR start struct_declarator_list + # C.g:204:1: struct_declarator_list : struct_declarator ( ',' struct_declarator )* ; + def struct_declarator_list(self, ): + + struct_declarator_list_StartIndex = self.input.index() + try: + try: + if self.backtracking > 0 and self.alreadyParsedRule(self.input, 16): + return + + # C.g:205:2: ( struct_declarator ( ',' struct_declarator )* ) + # C.g:205:4: struct_declarator ( ',' struct_declarator )* + self.following.append(self.FOLLOW_struct_declarator_in_struct_declarator_list574) + self.struct_declarator() + self.following.pop() + if self.failed: + return + # C.g:205:22: ( ',' struct_declarator )* + while True: #loop18 + alt18 = 2 + LA18_0 = self.input.LA(1) + + if (LA18_0 == 27) : + alt18 = 1 + + + if alt18 == 1: + # C.g:205:23: ',' struct_declarator + self.match(self.input, 27, self.FOLLOW_27_in_struct_declarator_list577) + if self.failed: + return + self.following.append(self.FOLLOW_struct_declarator_in_struct_declarator_list579) + self.struct_declarator() + self.following.pop() + if self.failed: + return + + + else: + break #loop18 + + + + + + + except RecognitionException, re: + self.reportError(re) + self.recover(self.input, re) + finally: + if self.backtracking > 0: + self.memoize(self.input, 16, struct_declarator_list_StartIndex) + + pass + + return + + # $ANTLR end struct_declarator_list + + + # $ANTLR start struct_declarator + # C.g:208:1: struct_declarator : ( declarator ( ':' constant_expression )? | ':' constant_expression ); + def struct_declarator(self, ): + + struct_declarator_StartIndex = self.input.index() + try: + try: + if self.backtracking > 0 and self.alreadyParsedRule(self.input, 17): + return + + # C.g:209:2: ( declarator ( ':' constant_expression )? | ':' constant_expression ) + alt20 = 2 + LA20_0 = self.input.LA(1) + + if (LA20_0 == IDENTIFIER or (58 <= LA20_0 <= 61) or LA20_0 == 65) : + alt20 = 1 + elif (LA20_0 == 47) : + alt20 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("208:1: struct_declarator : ( declarator ( ':' constant_expression )? | ':' constant_expression );", 20, 0, self.input) + + raise nvae + + if alt20 == 1: + # C.g:209:4: declarator ( ':' constant_expression )? + self.following.append(self.FOLLOW_declarator_in_struct_declarator592) + self.declarator() + self.following.pop() + if self.failed: + return + # C.g:209:15: ( ':' constant_expression )? + alt19 = 2 + LA19_0 = self.input.LA(1) + + if (LA19_0 == 47) : + alt19 = 1 + if alt19 == 1: + # C.g:209:16: ':' constant_expression + self.match(self.input, 47, self.FOLLOW_47_in_struct_declarator595) + if self.failed: + return + self.following.append(self.FOLLOW_constant_expression_in_struct_declarator597) + self.constant_expression() + self.following.pop() + if self.failed: + return + + + + + + elif alt20 == 2: + # C.g:210:4: ':' constant_expression + self.match(self.input, 47, self.FOLLOW_47_in_struct_declarator604) + if self.failed: + return + self.following.append(self.FOLLOW_constant_expression_in_struct_declarator606) + self.constant_expression() + self.following.pop() + if self.failed: + return + + + + except RecognitionException, re: + self.reportError(re) + self.recover(self.input, re) + finally: + if self.backtracking > 0: + self.memoize(self.input, 17, struct_declarator_StartIndex) + + pass + + return + + # $ANTLR end struct_declarator + + class enum_specifier_return(object): + def __init__(self): + self.start = None + self.stop = None + + + + # $ANTLR start enum_specifier + # C.g:213:1: enum_specifier options {k=3; } : ( 'enum' '{' enumerator_list ( ',' )? '}' | 'enum' IDENTIFIER '{' enumerator_list ( ',' )? '}' | 'enum' IDENTIFIER ); + def enum_specifier(self, ): + + retval = self.enum_specifier_return() + retval.start = self.input.LT(1) + enum_specifier_StartIndex = self.input.index() + try: + try: + if self.backtracking > 0 and self.alreadyParsedRule(self.input, 18): + return retval + + # C.g:215:2: ( 'enum' '{' enumerator_list ( ',' )? '}' | 'enum' IDENTIFIER '{' enumerator_list ( ',' )? '}' | 'enum' IDENTIFIER ) + alt23 = 3 + LA23_0 = self.input.LA(1) + + if (LA23_0 == 48) : + LA23_1 = self.input.LA(2) + + if (LA23_1 == IDENTIFIER) : + LA23_2 = self.input.LA(3) + + if (LA23_2 == 43) : + alt23 = 2 + elif (LA23_2 == EOF or LA23_2 == IDENTIFIER or LA23_2 == 25 or LA23_2 == 27 or (29 <= LA23_2 <= 42) or (45 <= LA23_2 <= 63) or LA23_2 == 65) : + alt23 = 3 + else: + if self.backtracking > 0: + self.failed = True + return retval + + nvae = NoViableAltException("213:1: enum_specifier options {k=3; } : ( 'enum' '{' enumerator_list ( ',' )? '}' | 'enum' IDENTIFIER '{' enumerator_list ( ',' )? '}' | 'enum' IDENTIFIER );", 23, 2, self.input) + + raise nvae + + elif (LA23_1 == 43) : + alt23 = 1 + else: + if self.backtracking > 0: + self.failed = True + return retval + + nvae = NoViableAltException("213:1: enum_specifier options {k=3; } : ( 'enum' '{' enumerator_list ( ',' )? '}' | 'enum' IDENTIFIER '{' enumerator_list ( ',' )? '}' | 'enum' IDENTIFIER );", 23, 1, self.input) + + raise nvae + + else: + if self.backtracking > 0: + self.failed = True + return retval + + nvae = NoViableAltException("213:1: enum_specifier options {k=3; } : ( 'enum' '{' enumerator_list ( ',' )? '}' | 'enum' IDENTIFIER '{' enumerator_list ( ',' )? '}' | 'enum' IDENTIFIER );", 23, 0, self.input) + + raise nvae + + if alt23 == 1: + # C.g:215:4: 'enum' '{' enumerator_list ( ',' )? '}' + self.match(self.input, 48, self.FOLLOW_48_in_enum_specifier624) + if self.failed: + return retval + self.match(self.input, 43, self.FOLLOW_43_in_enum_specifier626) + if self.failed: + return retval + self.following.append(self.FOLLOW_enumerator_list_in_enum_specifier628) + self.enumerator_list() + self.following.pop() + if self.failed: + return retval + # C.g:215:31: ( ',' )? + alt21 = 2 + LA21_0 = self.input.LA(1) + + if (LA21_0 == 27) : + alt21 = 1 + if alt21 == 1: + # C.g:0:0: ',' + self.match(self.input, 27, self.FOLLOW_27_in_enum_specifier630) + if self.failed: + return retval + + + + self.match(self.input, 44, self.FOLLOW_44_in_enum_specifier633) + if self.failed: + return retval + + + elif alt23 == 2: + # C.g:216:4: 'enum' IDENTIFIER '{' enumerator_list ( ',' )? '}' + self.match(self.input, 48, self.FOLLOW_48_in_enum_specifier638) + if self.failed: + return retval + self.match(self.input, IDENTIFIER, self.FOLLOW_IDENTIFIER_in_enum_specifier640) + if self.failed: + return retval + self.match(self.input, 43, self.FOLLOW_43_in_enum_specifier642) + if self.failed: + return retval + self.following.append(self.FOLLOW_enumerator_list_in_enum_specifier644) + self.enumerator_list() + self.following.pop() + if self.failed: + return retval + # C.g:216:42: ( ',' )? + alt22 = 2 + LA22_0 = self.input.LA(1) + + if (LA22_0 == 27) : + alt22 = 1 + if alt22 == 1: + # C.g:0:0: ',' + self.match(self.input, 27, self.FOLLOW_27_in_enum_specifier646) + if self.failed: + return retval + + + + self.match(self.input, 44, self.FOLLOW_44_in_enum_specifier649) + if self.failed: + return retval + + + elif alt23 == 3: + # C.g:217:4: 'enum' IDENTIFIER + self.match(self.input, 48, self.FOLLOW_48_in_enum_specifier654) + if self.failed: + return retval + self.match(self.input, IDENTIFIER, self.FOLLOW_IDENTIFIER_in_enum_specifier656) + if self.failed: + return retval + + + retval.stop = self.input.LT(-1) + + + except RecognitionException, re: + self.reportError(re) + self.recover(self.input, re) + finally: + if self.backtracking > 0: + self.memoize(self.input, 18, enum_specifier_StartIndex) + + pass + + return retval + + # $ANTLR end enum_specifier + + + # $ANTLR start enumerator_list + # C.g:220:1: enumerator_list : enumerator ( ',' enumerator )* ; + def enumerator_list(self, ): + + enumerator_list_StartIndex = self.input.index() + try: + try: + if self.backtracking > 0 and self.alreadyParsedRule(self.input, 19): + return + + # C.g:221:2: ( enumerator ( ',' enumerator )* ) + # C.g:221:4: enumerator ( ',' enumerator )* + self.following.append(self.FOLLOW_enumerator_in_enumerator_list667) + self.enumerator() + self.following.pop() + if self.failed: + return + # C.g:221:15: ( ',' enumerator )* + while True: #loop24 + alt24 = 2 + LA24_0 = self.input.LA(1) + + if (LA24_0 == 27) : + LA24_1 = self.input.LA(2) + + if (LA24_1 == IDENTIFIER) : + alt24 = 1 + + + + + if alt24 == 1: + # C.g:221:16: ',' enumerator + self.match(self.input, 27, self.FOLLOW_27_in_enumerator_list670) + if self.failed: + return + self.following.append(self.FOLLOW_enumerator_in_enumerator_list672) + self.enumerator() + self.following.pop() + if self.failed: + return + + + else: + break #loop24 + + + + + + + except RecognitionException, re: + self.reportError(re) + self.recover(self.input, re) + finally: + if self.backtracking > 0: + self.memoize(self.input, 19, enumerator_list_StartIndex) + + pass + + return + + # $ANTLR end enumerator_list + + + # $ANTLR start enumerator + # C.g:224:1: enumerator : IDENTIFIER ( '=' constant_expression )? ; + def enumerator(self, ): + + enumerator_StartIndex = self.input.index() + try: + try: + if self.backtracking > 0 and self.alreadyParsedRule(self.input, 20): + return + + # C.g:225:2: ( IDENTIFIER ( '=' constant_expression )? ) + # C.g:225:4: IDENTIFIER ( '=' constant_expression )? + self.match(self.input, IDENTIFIER, self.FOLLOW_IDENTIFIER_in_enumerator685) + if self.failed: + return + # C.g:225:15: ( '=' constant_expression )? + alt25 = 2 + LA25_0 = self.input.LA(1) + + if (LA25_0 == 28) : + alt25 = 1 + if alt25 == 1: + # C.g:225:16: '=' constant_expression + self.match(self.input, 28, self.FOLLOW_28_in_enumerator688) + if self.failed: + return + self.following.append(self.FOLLOW_constant_expression_in_enumerator690) + self.constant_expression() + self.following.pop() + if self.failed: + return + + + + + + + + except RecognitionException, re: + self.reportError(re) + self.recover(self.input, re) + finally: + if self.backtracking > 0: + self.memoize(self.input, 20, enumerator_StartIndex) + + pass + + return + + # $ANTLR end enumerator + + + # $ANTLR start type_qualifier + # C.g:228:1: type_qualifier : ( 'const' | 'volatile' | 'IN' | 'OUT' | 'OPTIONAL' | 'CONST' | 'UNALIGNED' | 'VOLATILE' | 'GLOBAL_REMOVE_IF_UNREFERENCED' | 'EFIAPI' | 'EFI_BOOTSERVICE' | 'EFI_RUNTIMESERVICE' ); + def type_qualifier(self, ): + + type_qualifier_StartIndex = self.input.index() + try: + try: + if self.backtracking > 0 and self.alreadyParsedRule(self.input, 21): + return + + # C.g:229:2: ( 'const' | 'volatile' | 'IN' | 'OUT' | 'OPTIONAL' | 'CONST' | 'UNALIGNED' | 'VOLATILE' | 'GLOBAL_REMOVE_IF_UNREFERENCED' | 'EFIAPI' | 'EFI_BOOTSERVICE' | 'EFI_RUNTIMESERVICE' ) + # C.g: + if (49 <= self.input.LA(1) <= 60): + self.input.consume(); + self.errorRecovery = False + self.failed = False + + else: + if self.backtracking > 0: + self.failed = True + return + + mse = MismatchedSetException(None, self.input) + self.recoverFromMismatchedSet( + self.input, mse, self.FOLLOW_set_in_type_qualifier0 + ) + raise mse + + + + + + + except RecognitionException, re: + self.reportError(re) + self.recover(self.input, re) + finally: + if self.backtracking > 0: + self.memoize(self.input, 21, type_qualifier_StartIndex) + + pass + + return + + # $ANTLR end type_qualifier + + class declarator_return(object): + def __init__(self): + self.start = None + self.stop = None + + + + # $ANTLR start declarator + # C.g:243:1: declarator : ( ( pointer )? ( 'EFIAPI' )? ( 'EFI_BOOTSERVICE' )? ( 'EFI_RUNTIMESERVICE' )? direct_declarator | pointer ); + def declarator(self, ): + + retval = self.declarator_return() + retval.start = self.input.LT(1) + declarator_StartIndex = self.input.index() + try: + try: + if self.backtracking > 0 and self.alreadyParsedRule(self.input, 22): + return retval + + # C.g:244:2: ( ( pointer )? ( 'EFIAPI' )? ( 'EFI_BOOTSERVICE' )? ( 'EFI_RUNTIMESERVICE' )? direct_declarator | pointer ) + alt30 = 2 + LA30_0 = self.input.LA(1) + + if (LA30_0 == 65) : + LA30_1 = self.input.LA(2) + + if (self.synpred65()) : + alt30 = 1 + elif (True) : + alt30 = 2 + else: + if self.backtracking > 0: + self.failed = True + return retval + + nvae = NoViableAltException("243:1: declarator : ( ( pointer )? ( 'EFIAPI' )? ( 'EFI_BOOTSERVICE' )? ( 'EFI_RUNTIMESERVICE' )? direct_declarator | pointer );", 30, 1, self.input) + + raise nvae + + elif (LA30_0 == IDENTIFIER or (58 <= LA30_0 <= 61)) : + alt30 = 1 + else: + if self.backtracking > 0: + self.failed = True + return retval + + nvae = NoViableAltException("243:1: declarator : ( ( pointer )? ( 'EFIAPI' )? ( 'EFI_BOOTSERVICE' )? ( 'EFI_RUNTIMESERVICE' )? direct_declarator | pointer );", 30, 0, self.input) + + raise nvae + + if alt30 == 1: + # C.g:244:4: ( pointer )? ( 'EFIAPI' )? ( 'EFI_BOOTSERVICE' )? ( 'EFI_RUNTIMESERVICE' )? direct_declarator + # C.g:244:4: ( pointer )? + alt26 = 2 + LA26_0 = self.input.LA(1) + + if (LA26_0 == 65) : + alt26 = 1 + if alt26 == 1: + # C.g:0:0: pointer + self.following.append(self.FOLLOW_pointer_in_declarator769) + self.pointer() + self.following.pop() + if self.failed: + return retval + + + + # C.g:244:13: ( 'EFIAPI' )? + alt27 = 2 + LA27_0 = self.input.LA(1) + + if (LA27_0 == 58) : + alt27 = 1 + if alt27 == 1: + # C.g:244:14: 'EFIAPI' + self.match(self.input, 58, self.FOLLOW_58_in_declarator773) + if self.failed: + return retval + + + + # C.g:244:25: ( 'EFI_BOOTSERVICE' )? + alt28 = 2 + LA28_0 = self.input.LA(1) + + if (LA28_0 == 59) : + alt28 = 1 + if alt28 == 1: + # C.g:244:26: 'EFI_BOOTSERVICE' + self.match(self.input, 59, self.FOLLOW_59_in_declarator778) + if self.failed: + return retval + + + + # C.g:244:46: ( 'EFI_RUNTIMESERVICE' )? + alt29 = 2 + LA29_0 = self.input.LA(1) + + if (LA29_0 == 60) : + alt29 = 1 + if alt29 == 1: + # C.g:244:47: 'EFI_RUNTIMESERVICE' + self.match(self.input, 60, self.FOLLOW_60_in_declarator783) + if self.failed: + return retval + + + + self.following.append(self.FOLLOW_direct_declarator_in_declarator787) + self.direct_declarator() + self.following.pop() + if self.failed: + return retval + + + elif alt30 == 2: + # C.g:246:4: pointer + self.following.append(self.FOLLOW_pointer_in_declarator793) + self.pointer() + self.following.pop() + if self.failed: + return retval + + + retval.stop = self.input.LT(-1) + + + except RecognitionException, re: + self.reportError(re) + self.recover(self.input, re) + finally: + if self.backtracking > 0: + self.memoize(self.input, 22, declarator_StartIndex) + + pass + + return retval + + # $ANTLR end declarator + + + # $ANTLR start direct_declarator + # C.g:249:1: direct_declarator : ( IDENTIFIER ( declarator_suffix )* | '(' ( 'EFIAPI' )? declarator ')' ( declarator_suffix )+ ); + def direct_declarator(self, ): + + direct_declarator_StartIndex = self.input.index() + try: + try: + if self.backtracking > 0 and self.alreadyParsedRule(self.input, 23): + return + + # C.g:250:2: ( IDENTIFIER ( declarator_suffix )* | '(' ( 'EFIAPI' )? declarator ')' ( declarator_suffix )+ ) + alt34 = 2 + LA34_0 = self.input.LA(1) + + if (LA34_0 == IDENTIFIER) : + alt34 = 1 + elif (LA34_0 == 61) : + alt34 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("249:1: direct_declarator : ( IDENTIFIER ( declarator_suffix )* | '(' ( 'EFIAPI' )? declarator ')' ( declarator_suffix )+ );", 34, 0, self.input) + + raise nvae + + if alt34 == 1: + # C.g:250:4: IDENTIFIER ( declarator_suffix )* + self.match(self.input, IDENTIFIER, self.FOLLOW_IDENTIFIER_in_direct_declarator804) + if self.failed: + return + # C.g:250:15: ( declarator_suffix )* + while True: #loop31 + alt31 = 2 + LA31_0 = self.input.LA(1) + + if (LA31_0 == 61) : + LA31 = self.input.LA(2) + if LA31 == 62: + LA31_30 = self.input.LA(3) + + if (self.synpred66()) : + alt31 = 1 + + + elif LA31 == 58: + LA31_31 = self.input.LA(3) + + if (self.synpred66()) : + alt31 = 1 + + + elif LA31 == 65: + LA31_32 = self.input.LA(3) + + if (self.synpred66()) : + alt31 = 1 + + + elif LA31 == 59: + LA31_33 = self.input.LA(3) + + if (self.synpred66()) : + alt31 = 1 + + + elif LA31 == 60: + LA31_34 = self.input.LA(3) + + if (self.synpred66()) : + alt31 = 1 + + + elif LA31 == IDENTIFIER: + LA31_35 = self.input.LA(3) + + if (self.synpred66()) : + alt31 = 1 + + + elif LA31 == 29 or LA31 == 30 or LA31 == 31 or LA31 == 32 or LA31 == 33: + LA31_37 = self.input.LA(3) + + if (self.synpred66()) : + alt31 = 1 + + + elif LA31 == 34: + LA31_38 = self.input.LA(3) + + if (self.synpred66()) : + alt31 = 1 + + + elif LA31 == 35: + LA31_39 = self.input.LA(3) + + if (self.synpred66()) : + alt31 = 1 + + + elif LA31 == 36: + LA31_40 = self.input.LA(3) + + if (self.synpred66()) : + alt31 = 1 + + + elif LA31 == 37: + LA31_41 = self.input.LA(3) + + if (self.synpred66()) : + alt31 = 1 + + + elif LA31 == 38: + LA31_42 = self.input.LA(3) + + if (self.synpred66()) : + alt31 = 1 + + + elif LA31 == 39: + LA31_43 = self.input.LA(3) + + if (self.synpred66()) : + alt31 = 1 + + + elif LA31 == 40: + LA31_44 = self.input.LA(3) + + if (self.synpred66()) : + alt31 = 1 + + + elif LA31 == 41: + LA31_45 = self.input.LA(3) + + if (self.synpred66()) : + alt31 = 1 + + + elif LA31 == 42: + LA31_46 = self.input.LA(3) + + if (self.synpred66()) : + alt31 = 1 + + + elif LA31 == 45 or LA31 == 46: + LA31_47 = self.input.LA(3) + + if (self.synpred66()) : + alt31 = 1 + + + elif LA31 == 48: + LA31_48 = self.input.LA(3) + + if (self.synpred66()) : + alt31 = 1 + + + elif LA31 == 49 or LA31 == 50 or LA31 == 51 or LA31 == 52 or LA31 == 53 or LA31 == 54 or LA31 == 55 or LA31 == 56 or LA31 == 57: + LA31_49 = self.input.LA(3) + + if (self.synpred66()) : + alt31 = 1 + + + + elif (LA31_0 == 63) : + LA31 = self.input.LA(2) + if LA31 == 64: + LA31_51 = self.input.LA(3) + + if (self.synpred66()) : + alt31 = 1 + + + elif LA31 == 61: + LA31_52 = self.input.LA(3) + + if (self.synpred66()) : + alt31 = 1 + + + elif LA31 == IDENTIFIER: + LA31_53 = self.input.LA(3) + + if (self.synpred66()) : + alt31 = 1 + + + elif LA31 == HEX_LITERAL: + LA31_54 = self.input.LA(3) + + if (self.synpred66()) : + alt31 = 1 + + + elif LA31 == OCTAL_LITERAL: + LA31_55 = self.input.LA(3) + + if (self.synpred66()) : + alt31 = 1 + + + elif LA31 == DECIMAL_LITERAL: + LA31_56 = self.input.LA(3) + + if (self.synpred66()) : + alt31 = 1 + + + elif LA31 == CHARACTER_LITERAL: + LA31_57 = self.input.LA(3) + + if (self.synpred66()) : + alt31 = 1 + + + elif LA31 == STRING_LITERAL: + LA31_58 = self.input.LA(3) + + if (self.synpred66()) : + alt31 = 1 + + + elif LA31 == FLOATING_POINT_LITERAL: + LA31_59 = self.input.LA(3) + + if (self.synpred66()) : + alt31 = 1 + + + elif LA31 == 71: + LA31_60 = self.input.LA(3) + + if (self.synpred66()) : + alt31 = 1 + + + elif LA31 == 72: + LA31_61 = self.input.LA(3) + + if (self.synpred66()) : + alt31 = 1 + + + elif LA31 == 65 or LA31 == 67 or LA31 == 68 or LA31 == 76 or LA31 == 77 or LA31 == 78: + LA31_62 = self.input.LA(3) + + if (self.synpred66()) : + alt31 = 1 + + + elif LA31 == 73: + LA31_63 = self.input.LA(3) + + if (self.synpred66()) : + alt31 = 1 + + + + + + if alt31 == 1: + # C.g:0:0: declarator_suffix + self.following.append(self.FOLLOW_declarator_suffix_in_direct_declarator806) + self.declarator_suffix() + self.following.pop() + if self.failed: + return + + + else: + break #loop31 + + + + + elif alt34 == 2: + # C.g:251:4: '(' ( 'EFIAPI' )? declarator ')' ( declarator_suffix )+ + self.match(self.input, 61, self.FOLLOW_61_in_direct_declarator812) + if self.failed: + return + # C.g:251:8: ( 'EFIAPI' )? + alt32 = 2 + LA32_0 = self.input.LA(1) + + if (LA32_0 == 58) : + LA32_1 = self.input.LA(2) + + if (self.synpred68()) : + alt32 = 1 + if alt32 == 1: + # C.g:251:9: 'EFIAPI' + self.match(self.input, 58, self.FOLLOW_58_in_direct_declarator815) + if self.failed: + return + + + + self.following.append(self.FOLLOW_declarator_in_direct_declarator819) + self.declarator() + self.following.pop() + if self.failed: + return + self.match(self.input, 62, self.FOLLOW_62_in_direct_declarator821) + if self.failed: + return + # C.g:251:35: ( declarator_suffix )+ + cnt33 = 0 + while True: #loop33 + alt33 = 2 + LA33_0 = self.input.LA(1) + + if (LA33_0 == 61) : + LA33 = self.input.LA(2) + if LA33 == 62: + LA33_30 = self.input.LA(3) + + if (self.synpred69()) : + alt33 = 1 + + + elif LA33 == 58: + LA33_31 = self.input.LA(3) + + if (self.synpred69()) : + alt33 = 1 + + + elif LA33 == 65: + LA33_32 = self.input.LA(3) + + if (self.synpred69()) : + alt33 = 1 + + + elif LA33 == 59: + LA33_33 = self.input.LA(3) + + if (self.synpred69()) : + alt33 = 1 + + + elif LA33 == 60: + LA33_34 = self.input.LA(3) + + if (self.synpred69()) : + alt33 = 1 + + + elif LA33 == IDENTIFIER: + LA33_35 = self.input.LA(3) + + if (self.synpred69()) : + alt33 = 1 + + + elif LA33 == 29 or LA33 == 30 or LA33 == 31 or LA33 == 32 or LA33 == 33: + LA33_37 = self.input.LA(3) + + if (self.synpred69()) : + alt33 = 1 + + + elif LA33 == 34: + LA33_38 = self.input.LA(3) + + if (self.synpred69()) : + alt33 = 1 + + + elif LA33 == 35: + LA33_39 = self.input.LA(3) + + if (self.synpred69()) : + alt33 = 1 + + + elif LA33 == 36: + LA33_40 = self.input.LA(3) + + if (self.synpred69()) : + alt33 = 1 + + + elif LA33 == 37: + LA33_41 = self.input.LA(3) + + if (self.synpred69()) : + alt33 = 1 + + + elif LA33 == 38: + LA33_42 = self.input.LA(3) + + if (self.synpred69()) : + alt33 = 1 + + + elif LA33 == 39: + LA33_43 = self.input.LA(3) + + if (self.synpred69()) : + alt33 = 1 + + + elif LA33 == 40: + LA33_44 = self.input.LA(3) + + if (self.synpred69()) : + alt33 = 1 + + + elif LA33 == 41: + LA33_45 = self.input.LA(3) + + if (self.synpred69()) : + alt33 = 1 + + + elif LA33 == 42: + LA33_46 = self.input.LA(3) + + if (self.synpred69()) : + alt33 = 1 + + + elif LA33 == 45 or LA33 == 46: + LA33_47 = self.input.LA(3) + + if (self.synpred69()) : + alt33 = 1 + + + elif LA33 == 48: + LA33_48 = self.input.LA(3) + + if (self.synpred69()) : + alt33 = 1 + + + elif LA33 == 49 or LA33 == 50 or LA33 == 51 or LA33 == 52 or LA33 == 53 or LA33 == 54 or LA33 == 55 or LA33 == 56 or LA33 == 57: + LA33_49 = self.input.LA(3) + + if (self.synpred69()) : + alt33 = 1 + + + + elif (LA33_0 == 63) : + LA33 = self.input.LA(2) + if LA33 == 64: + LA33_51 = self.input.LA(3) + + if (self.synpred69()) : + alt33 = 1 + + + elif LA33 == 61: + LA33_52 = self.input.LA(3) + + if (self.synpred69()) : + alt33 = 1 + + + elif LA33 == IDENTIFIER: + LA33_53 = self.input.LA(3) + + if (self.synpred69()) : + alt33 = 1 + + + elif LA33 == HEX_LITERAL: + LA33_54 = self.input.LA(3) + + if (self.synpred69()) : + alt33 = 1 + + + elif LA33 == OCTAL_LITERAL: + LA33_55 = self.input.LA(3) + + if (self.synpred69()) : + alt33 = 1 + + + elif LA33 == DECIMAL_LITERAL: + LA33_56 = self.input.LA(3) + + if (self.synpred69()) : + alt33 = 1 + + + elif LA33 == CHARACTER_LITERAL: + LA33_57 = self.input.LA(3) + + if (self.synpred69()) : + alt33 = 1 + + + elif LA33 == STRING_LITERAL: + LA33_58 = self.input.LA(3) + + if (self.synpred69()) : + alt33 = 1 + + + elif LA33 == FLOATING_POINT_LITERAL: + LA33_59 = self.input.LA(3) + + if (self.synpred69()) : + alt33 = 1 + + + elif LA33 == 71: + LA33_60 = self.input.LA(3) + + if (self.synpred69()) : + alt33 = 1 + + + elif LA33 == 72: + LA33_61 = self.input.LA(3) + + if (self.synpred69()) : + alt33 = 1 + + + elif LA33 == 65 or LA33 == 67 or LA33 == 68 or LA33 == 76 or LA33 == 77 or LA33 == 78: + LA33_62 = self.input.LA(3) + + if (self.synpred69()) : + alt33 = 1 + + + elif LA33 == 73: + LA33_63 = self.input.LA(3) + + if (self.synpred69()) : + alt33 = 1 + + + + + + if alt33 == 1: + # C.g:0:0: declarator_suffix + self.following.append(self.FOLLOW_declarator_suffix_in_direct_declarator823) + self.declarator_suffix() + self.following.pop() + if self.failed: + return + + + else: + if cnt33 >= 1: + break #loop33 + + if self.backtracking > 0: + self.failed = True + return + + eee = EarlyExitException(33, self.input) + raise eee + + cnt33 += 1 + + + + + + except RecognitionException, re: + self.reportError(re) + self.recover(self.input, re) + finally: + if self.backtracking > 0: + self.memoize(self.input, 23, direct_declarator_StartIndex) + + pass + + return + + # $ANTLR end direct_declarator + + + # $ANTLR start declarator_suffix + # C.g:254:1: declarator_suffix : ( '[' constant_expression ']' | '[' ']' | '(' parameter_type_list ')' | '(' identifier_list ')' | '(' ')' ); + def declarator_suffix(self, ): + + declarator_suffix_StartIndex = self.input.index() + try: + try: + if self.backtracking > 0 and self.alreadyParsedRule(self.input, 24): + return + + # C.g:255:2: ( '[' constant_expression ']' | '[' ']' | '(' parameter_type_list ')' | '(' identifier_list ')' | '(' ')' ) + alt35 = 5 + LA35_0 = self.input.LA(1) + + if (LA35_0 == 63) : + LA35_1 = self.input.LA(2) + + if (LA35_1 == 64) : + alt35 = 2 + elif ((IDENTIFIER <= LA35_1 <= FLOATING_POINT_LITERAL) or LA35_1 == 61 or LA35_1 == 65 or (67 <= LA35_1 <= 68) or (71 <= LA35_1 <= 73) or (76 <= LA35_1 <= 78)) : + alt35 = 1 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("254:1: declarator_suffix : ( '[' constant_expression ']' | '[' ']' | '(' parameter_type_list ')' | '(' identifier_list ')' | '(' ')' );", 35, 1, self.input) + + raise nvae + + elif (LA35_0 == 61) : + LA35 = self.input.LA(2) + if LA35 == 62: + alt35 = 5 + elif LA35 == IDENTIFIER: + LA35_17 = self.input.LA(3) + + if (self.synpred72()) : + alt35 = 3 + elif (self.synpred73()) : + alt35 = 4 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("254:1: declarator_suffix : ( '[' constant_expression ']' | '[' ']' | '(' parameter_type_list ')' | '(' identifier_list ')' | '(' ')' );", 35, 17, self.input) + + raise nvae + + elif LA35 == 29 or LA35 == 30 or LA35 == 31 or LA35 == 32 or LA35 == 33 or LA35 == 34 or LA35 == 35 or LA35 == 36 or LA35 == 37 or LA35 == 38 or LA35 == 39 or LA35 == 40 or LA35 == 41 or LA35 == 42 or LA35 == 45 or LA35 == 46 or LA35 == 48 or LA35 == 49 or LA35 == 50 or LA35 == 51 or LA35 == 52 or LA35 == 53 or LA35 == 54 or LA35 == 55 or LA35 == 56 or LA35 == 57 or LA35 == 58 or LA35 == 59 or LA35 == 60 or LA35 == 65: + alt35 = 3 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("254:1: declarator_suffix : ( '[' constant_expression ']' | '[' ']' | '(' parameter_type_list ')' | '(' identifier_list ')' | '(' ')' );", 35, 2, self.input) + + raise nvae + + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("254:1: declarator_suffix : ( '[' constant_expression ']' | '[' ']' | '(' parameter_type_list ')' | '(' identifier_list ')' | '(' ')' );", 35, 0, self.input) + + raise nvae + + if alt35 == 1: + # C.g:255:6: '[' constant_expression ']' + self.match(self.input, 63, self.FOLLOW_63_in_declarator_suffix837) + if self.failed: + return + self.following.append(self.FOLLOW_constant_expression_in_declarator_suffix839) + self.constant_expression() + self.following.pop() + if self.failed: + return + self.match(self.input, 64, self.FOLLOW_64_in_declarator_suffix841) + if self.failed: + return + + + elif alt35 == 2: + # C.g:256:9: '[' ']' + self.match(self.input, 63, self.FOLLOW_63_in_declarator_suffix851) + if self.failed: + return + self.match(self.input, 64, self.FOLLOW_64_in_declarator_suffix853) + if self.failed: + return + + + elif alt35 == 3: + # C.g:257:9: '(' parameter_type_list ')' + self.match(self.input, 61, self.FOLLOW_61_in_declarator_suffix863) + if self.failed: + return + self.following.append(self.FOLLOW_parameter_type_list_in_declarator_suffix865) + self.parameter_type_list() + self.following.pop() + if self.failed: + return + self.match(self.input, 62, self.FOLLOW_62_in_declarator_suffix867) + if self.failed: + return + + + elif alt35 == 4: + # C.g:258:9: '(' identifier_list ')' + self.match(self.input, 61, self.FOLLOW_61_in_declarator_suffix877) + if self.failed: + return + self.following.append(self.FOLLOW_identifier_list_in_declarator_suffix879) + self.identifier_list() + self.following.pop() + if self.failed: + return + self.match(self.input, 62, self.FOLLOW_62_in_declarator_suffix881) + if self.failed: + return + + + elif alt35 == 5: + # C.g:259:9: '(' ')' + self.match(self.input, 61, self.FOLLOW_61_in_declarator_suffix891) + if self.failed: + return + self.match(self.input, 62, self.FOLLOW_62_in_declarator_suffix893) + if self.failed: + return + + + + except RecognitionException, re: + self.reportError(re) + self.recover(self.input, re) + finally: + if self.backtracking > 0: + self.memoize(self.input, 24, declarator_suffix_StartIndex) + + pass + + return + + # $ANTLR end declarator_suffix + + + # $ANTLR start pointer + # C.g:262:1: pointer : ( '*' ( type_qualifier )+ ( pointer )? | '*' pointer | '*' ); + def pointer(self, ): + + pointer_StartIndex = self.input.index() + try: + try: + if self.backtracking > 0 and self.alreadyParsedRule(self.input, 25): + return + + # C.g:263:2: ( '*' ( type_qualifier )+ ( pointer )? | '*' pointer | '*' ) + alt38 = 3 + LA38_0 = self.input.LA(1) + + if (LA38_0 == 65) : + LA38 = self.input.LA(2) + if LA38 == 58: + LA38_2 = self.input.LA(3) + + if (self.synpred76()) : + alt38 = 1 + elif (True) : + alt38 = 3 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("262:1: pointer : ( '*' ( type_qualifier )+ ( pointer )? | '*' pointer | '*' );", 38, 2, self.input) + + raise nvae + + elif LA38 == 59: + LA38_3 = self.input.LA(3) + + if (self.synpred76()) : + alt38 = 1 + elif (True) : + alt38 = 3 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("262:1: pointer : ( '*' ( type_qualifier )+ ( pointer )? | '*' pointer | '*' );", 38, 3, self.input) + + raise nvae + + elif LA38 == 60: + LA38_4 = self.input.LA(3) + + if (self.synpred76()) : + alt38 = 1 + elif (True) : + alt38 = 3 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("262:1: pointer : ( '*' ( type_qualifier )+ ( pointer )? | '*' pointer | '*' );", 38, 4, self.input) + + raise nvae + + elif LA38 == EOF or LA38 == IDENTIFIER or LA38 == 25 or LA38 == 26 or LA38 == 27 or LA38 == 28 or LA38 == 29 or LA38 == 30 or LA38 == 31 or LA38 == 32 or LA38 == 33 or LA38 == 34 or LA38 == 35 or LA38 == 36 or LA38 == 37 or LA38 == 38 or LA38 == 39 or LA38 == 40 or LA38 == 41 or LA38 == 42 or LA38 == 43 or LA38 == 45 or LA38 == 46 or LA38 == 47 or LA38 == 48 or LA38 == 61 or LA38 == 62 or LA38 == 63: + alt38 = 3 + elif LA38 == 53: + LA38_20 = self.input.LA(3) + + if (self.synpred76()) : + alt38 = 1 + elif (True) : + alt38 = 3 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("262:1: pointer : ( '*' ( type_qualifier )+ ( pointer )? | '*' pointer | '*' );", 38, 20, self.input) + + raise nvae + + elif LA38 == 49 or LA38 == 50 or LA38 == 51 or LA38 == 52 or LA38 == 54 or LA38 == 55 or LA38 == 56 or LA38 == 57: + LA38_28 = self.input.LA(3) + + if (self.synpred76()) : + alt38 = 1 + elif (True) : + alt38 = 3 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("262:1: pointer : ( '*' ( type_qualifier )+ ( pointer )? | '*' pointer | '*' );", 38, 28, self.input) + + raise nvae + + elif LA38 == 65: + LA38_29 = self.input.LA(3) + + if (self.synpred77()) : + alt38 = 2 + elif (True) : + alt38 = 3 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("262:1: pointer : ( '*' ( type_qualifier )+ ( pointer )? | '*' pointer | '*' );", 38, 29, self.input) + + raise nvae + + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("262:1: pointer : ( '*' ( type_qualifier )+ ( pointer )? | '*' pointer | '*' );", 38, 1, self.input) + + raise nvae + + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("262:1: pointer : ( '*' ( type_qualifier )+ ( pointer )? | '*' pointer | '*' );", 38, 0, self.input) + + raise nvae + + if alt38 == 1: + # C.g:263:4: '*' ( type_qualifier )+ ( pointer )? + self.match(self.input, 65, self.FOLLOW_65_in_pointer904) + if self.failed: + return + # C.g:263:8: ( type_qualifier )+ + cnt36 = 0 + while True: #loop36 + alt36 = 2 + LA36 = self.input.LA(1) + if LA36 == 58: + LA36_2 = self.input.LA(2) + + if (self.synpred74()) : + alt36 = 1 + + + elif LA36 == 59: + LA36_3 = self.input.LA(2) + + if (self.synpred74()) : + alt36 = 1 + + + elif LA36 == 60: + LA36_4 = self.input.LA(2) + + if (self.synpred74()) : + alt36 = 1 + + + elif LA36 == 53: + LA36_20 = self.input.LA(2) + + if (self.synpred74()) : + alt36 = 1 + + + elif LA36 == 49 or LA36 == 50 or LA36 == 51 or LA36 == 52 or LA36 == 54 or LA36 == 55 or LA36 == 56 or LA36 == 57: + LA36_28 = self.input.LA(2) + + if (self.synpred74()) : + alt36 = 1 + + + + if alt36 == 1: + # C.g:0:0: type_qualifier + self.following.append(self.FOLLOW_type_qualifier_in_pointer906) + self.type_qualifier() + self.following.pop() + if self.failed: + return + + + else: + if cnt36 >= 1: + break #loop36 + + if self.backtracking > 0: + self.failed = True + return + + eee = EarlyExitException(36, self.input) + raise eee + + cnt36 += 1 + + + # C.g:263:24: ( pointer )? + alt37 = 2 + LA37_0 = self.input.LA(1) + + if (LA37_0 == 65) : + LA37_1 = self.input.LA(2) + + if (self.synpred75()) : + alt37 = 1 + if alt37 == 1: + # C.g:0:0: pointer + self.following.append(self.FOLLOW_pointer_in_pointer909) + self.pointer() + self.following.pop() + if self.failed: + return + + + + + + elif alt38 == 2: + # C.g:264:4: '*' pointer + self.match(self.input, 65, self.FOLLOW_65_in_pointer915) + if self.failed: + return + self.following.append(self.FOLLOW_pointer_in_pointer917) + self.pointer() + self.following.pop() + if self.failed: + return + + + elif alt38 == 3: + # C.g:265:4: '*' + self.match(self.input, 65, self.FOLLOW_65_in_pointer922) + if self.failed: + return + + + + except RecognitionException, re: + self.reportError(re) + self.recover(self.input, re) + finally: + if self.backtracking > 0: + self.memoize(self.input, 25, pointer_StartIndex) + + pass + + return + + # $ANTLR end pointer + + + # $ANTLR start parameter_type_list + # C.g:268:1: parameter_type_list : parameter_list ( ',' ( 'OPTIONAL' )? '...' )? ; + def parameter_type_list(self, ): + + parameter_type_list_StartIndex = self.input.index() + try: + try: + if self.backtracking > 0 and self.alreadyParsedRule(self.input, 26): + return + + # C.g:269:2: ( parameter_list ( ',' ( 'OPTIONAL' )? '...' )? ) + # C.g:269:4: parameter_list ( ',' ( 'OPTIONAL' )? '...' )? + self.following.append(self.FOLLOW_parameter_list_in_parameter_type_list933) + self.parameter_list() + self.following.pop() + if self.failed: + return + # C.g:269:19: ( ',' ( 'OPTIONAL' )? '...' )? + alt40 = 2 + LA40_0 = self.input.LA(1) + + if (LA40_0 == 27) : + alt40 = 1 + if alt40 == 1: + # C.g:269:20: ',' ( 'OPTIONAL' )? '...' + self.match(self.input, 27, self.FOLLOW_27_in_parameter_type_list936) + if self.failed: + return + # C.g:269:24: ( 'OPTIONAL' )? + alt39 = 2 + LA39_0 = self.input.LA(1) + + if (LA39_0 == 53) : + alt39 = 1 + if alt39 == 1: + # C.g:269:25: 'OPTIONAL' + self.match(self.input, 53, self.FOLLOW_53_in_parameter_type_list939) + if self.failed: + return + + + + self.match(self.input, 66, self.FOLLOW_66_in_parameter_type_list943) + if self.failed: + return + + + + + + + + except RecognitionException, re: + self.reportError(re) + self.recover(self.input, re) + finally: + if self.backtracking > 0: + self.memoize(self.input, 26, parameter_type_list_StartIndex) + + pass + + return + + # $ANTLR end parameter_type_list + + + # $ANTLR start parameter_list + # C.g:272:1: parameter_list : parameter_declaration ( ',' ( 'OPTIONAL' )? parameter_declaration )* ; + def parameter_list(self, ): + + parameter_list_StartIndex = self.input.index() + try: + try: + if self.backtracking > 0 and self.alreadyParsedRule(self.input, 27): + return + + # C.g:273:2: ( parameter_declaration ( ',' ( 'OPTIONAL' )? parameter_declaration )* ) + # C.g:273:4: parameter_declaration ( ',' ( 'OPTIONAL' )? parameter_declaration )* + self.following.append(self.FOLLOW_parameter_declaration_in_parameter_list956) + self.parameter_declaration() + self.following.pop() + if self.failed: + return + # C.g:273:26: ( ',' ( 'OPTIONAL' )? parameter_declaration )* + while True: #loop42 + alt42 = 2 + LA42_0 = self.input.LA(1) + + if (LA42_0 == 27) : + LA42_1 = self.input.LA(2) + + if (LA42_1 == 53) : + LA42_3 = self.input.LA(3) + + if (self.synpred81()) : + alt42 = 1 + + + elif (LA42_1 == IDENTIFIER or (29 <= LA42_1 <= 42) or (45 <= LA42_1 <= 46) or (48 <= LA42_1 <= 52) or (54 <= LA42_1 <= 60) or LA42_1 == 65) : + alt42 = 1 + + + + + if alt42 == 1: + # C.g:273:27: ',' ( 'OPTIONAL' )? parameter_declaration + self.match(self.input, 27, self.FOLLOW_27_in_parameter_list959) + if self.failed: + return + # C.g:273:31: ( 'OPTIONAL' )? + alt41 = 2 + LA41_0 = self.input.LA(1) + + if (LA41_0 == 53) : + LA41_1 = self.input.LA(2) + + if (self.synpred80()) : + alt41 = 1 + if alt41 == 1: + # C.g:273:32: 'OPTIONAL' + self.match(self.input, 53, self.FOLLOW_53_in_parameter_list962) + if self.failed: + return + + + + self.following.append(self.FOLLOW_parameter_declaration_in_parameter_list966) + self.parameter_declaration() + self.following.pop() + if self.failed: + return + + + else: + break #loop42 + + + + + + + except RecognitionException, re: + self.reportError(re) + self.recover(self.input, re) + finally: + if self.backtracking > 0: + self.memoize(self.input, 27, parameter_list_StartIndex) + + pass + + return + + # $ANTLR end parameter_list + + + # $ANTLR start parameter_declaration + # C.g:276:1: parameter_declaration : ( declaration_specifiers ( declarator | abstract_declarator )* ( 'OPTIONAL' )? | ( pointer )* IDENTIFIER ); + def parameter_declaration(self, ): + + parameter_declaration_StartIndex = self.input.index() + try: + try: + if self.backtracking > 0 and self.alreadyParsedRule(self.input, 28): + return + + # C.g:277:2: ( declaration_specifiers ( declarator | abstract_declarator )* ( 'OPTIONAL' )? | ( pointer )* IDENTIFIER ) + alt46 = 2 + LA46 = self.input.LA(1) + if LA46 == 29 or LA46 == 30 or LA46 == 31 or LA46 == 32 or LA46 == 33 or LA46 == 34 or LA46 == 35 or LA46 == 36 or LA46 == 37 or LA46 == 38 or LA46 == 39 or LA46 == 40 or LA46 == 41 or LA46 == 42 or LA46 == 45 or LA46 == 46 or LA46 == 48 or LA46 == 49 or LA46 == 50 or LA46 == 51 or LA46 == 52 or LA46 == 53 or LA46 == 54 or LA46 == 55 or LA46 == 56 or LA46 == 57 or LA46 == 58 or LA46 == 59 or LA46 == 60: + alt46 = 1 + elif LA46 == IDENTIFIER: + LA46_13 = self.input.LA(2) + + if (self.synpred85()) : + alt46 = 1 + elif (True) : + alt46 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("276:1: parameter_declaration : ( declaration_specifiers ( declarator | abstract_declarator )* ( 'OPTIONAL' )? | ( pointer )* IDENTIFIER );", 46, 13, self.input) + + raise nvae + + elif LA46 == 65: + alt46 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("276:1: parameter_declaration : ( declaration_specifiers ( declarator | abstract_declarator )* ( 'OPTIONAL' )? | ( pointer )* IDENTIFIER );", 46, 0, self.input) + + raise nvae + + if alt46 == 1: + # C.g:277:4: declaration_specifiers ( declarator | abstract_declarator )* ( 'OPTIONAL' )? + self.following.append(self.FOLLOW_declaration_specifiers_in_parameter_declaration979) + self.declaration_specifiers() + self.following.pop() + if self.failed: + return + # C.g:277:27: ( declarator | abstract_declarator )* + while True: #loop43 + alt43 = 3 + LA43 = self.input.LA(1) + if LA43 == 65: + LA43_5 = self.input.LA(2) + + if (self.synpred82()) : + alt43 = 1 + elif (self.synpred83()) : + alt43 = 2 + + + elif LA43 == IDENTIFIER or LA43 == 58 or LA43 == 59 or LA43 == 60: + alt43 = 1 + elif LA43 == 61: + LA43 = self.input.LA(2) + if LA43 == 29 or LA43 == 30 or LA43 == 31 or LA43 == 32 or LA43 == 33 or LA43 == 34 or LA43 == 35 or LA43 == 36 or LA43 == 37 or LA43 == 38 or LA43 == 39 or LA43 == 40 or LA43 == 41 or LA43 == 42 or LA43 == 45 or LA43 == 46 or LA43 == 48 or LA43 == 49 or LA43 == 50 or LA43 == 51 or LA43 == 52 or LA43 == 53 or LA43 == 54 or LA43 == 55 or LA43 == 56 or LA43 == 57 or LA43 == 62 or LA43 == 63: + alt43 = 2 + elif LA43 == IDENTIFIER: + LA43_37 = self.input.LA(3) + + if (self.synpred82()) : + alt43 = 1 + elif (self.synpred83()) : + alt43 = 2 + + + elif LA43 == 58: + LA43_38 = self.input.LA(3) + + if (self.synpred82()) : + alt43 = 1 + elif (self.synpred83()) : + alt43 = 2 + + + elif LA43 == 65: + LA43_39 = self.input.LA(3) + + if (self.synpred82()) : + alt43 = 1 + elif (self.synpred83()) : + alt43 = 2 + + + elif LA43 == 59: + LA43_40 = self.input.LA(3) + + if (self.synpred82()) : + alt43 = 1 + elif (self.synpred83()) : + alt43 = 2 + + + elif LA43 == 60: + LA43_41 = self.input.LA(3) + + if (self.synpred82()) : + alt43 = 1 + elif (self.synpred83()) : + alt43 = 2 + + + elif LA43 == 61: + LA43_43 = self.input.LA(3) + + if (self.synpred82()) : + alt43 = 1 + elif (self.synpred83()) : + alt43 = 2 + + + + elif LA43 == 63: + alt43 = 2 + + if alt43 == 1: + # C.g:277:28: declarator + self.following.append(self.FOLLOW_declarator_in_parameter_declaration982) + self.declarator() + self.following.pop() + if self.failed: + return + + + elif alt43 == 2: + # C.g:277:39: abstract_declarator + self.following.append(self.FOLLOW_abstract_declarator_in_parameter_declaration984) + self.abstract_declarator() + self.following.pop() + if self.failed: + return + + + else: + break #loop43 + + + # C.g:277:61: ( 'OPTIONAL' )? + alt44 = 2 + LA44_0 = self.input.LA(1) + + if (LA44_0 == 53) : + alt44 = 1 + if alt44 == 1: + # C.g:277:62: 'OPTIONAL' + self.match(self.input, 53, self.FOLLOW_53_in_parameter_declaration989) + if self.failed: + return + + + + + + elif alt46 == 2: + # C.g:279:4: ( pointer )* IDENTIFIER + # C.g:279:4: ( pointer )* + while True: #loop45 + alt45 = 2 + LA45_0 = self.input.LA(1) + + if (LA45_0 == 65) : + alt45 = 1 + + + if alt45 == 1: + # C.g:0:0: pointer + self.following.append(self.FOLLOW_pointer_in_parameter_declaration998) + self.pointer() + self.following.pop() + if self.failed: + return + + + else: + break #loop45 + + + self.match(self.input, IDENTIFIER, self.FOLLOW_IDENTIFIER_in_parameter_declaration1001) + if self.failed: + return + + + + except RecognitionException, re: + self.reportError(re) + self.recover(self.input, re) + finally: + if self.backtracking > 0: + self.memoize(self.input, 28, parameter_declaration_StartIndex) + + pass + + return + + # $ANTLR end parameter_declaration + + + # $ANTLR start identifier_list + # C.g:282:1: identifier_list : IDENTIFIER ( ',' IDENTIFIER )* ; + def identifier_list(self, ): + + identifier_list_StartIndex = self.input.index() + try: + try: + if self.backtracking > 0 and self.alreadyParsedRule(self.input, 29): + return + + # C.g:283:2: ( IDENTIFIER ( ',' IDENTIFIER )* ) + # C.g:283:4: IDENTIFIER ( ',' IDENTIFIER )* + self.match(self.input, IDENTIFIER, self.FOLLOW_IDENTIFIER_in_identifier_list1012) + if self.failed: + return + # C.g:284:2: ( ',' IDENTIFIER )* + while True: #loop47 + alt47 = 2 + LA47_0 = self.input.LA(1) + + if (LA47_0 == 27) : + alt47 = 1 + + + if alt47 == 1: + # C.g:284:3: ',' IDENTIFIER + self.match(self.input, 27, self.FOLLOW_27_in_identifier_list1016) + if self.failed: + return + self.match(self.input, IDENTIFIER, self.FOLLOW_IDENTIFIER_in_identifier_list1018) + if self.failed: + return + + + else: + break #loop47 + + + + + + + except RecognitionException, re: + self.reportError(re) + self.recover(self.input, re) + finally: + if self.backtracking > 0: + self.memoize(self.input, 29, identifier_list_StartIndex) + + pass + + return + + # $ANTLR end identifier_list + + + # $ANTLR start type_name + # C.g:287:1: type_name : ( specifier_qualifier_list ( abstract_declarator )? | type_id ); + def type_name(self, ): + + type_name_StartIndex = self.input.index() + try: + try: + if self.backtracking > 0 and self.alreadyParsedRule(self.input, 30): + return + + # C.g:288:2: ( specifier_qualifier_list ( abstract_declarator )? | type_id ) + alt49 = 2 + LA49_0 = self.input.LA(1) + + if ((34 <= LA49_0 <= 42) or (45 <= LA49_0 <= 46) or (48 <= LA49_0 <= 60)) : + alt49 = 1 + elif (LA49_0 == IDENTIFIER) : + LA49_13 = self.input.LA(2) + + if (self.synpred89()) : + alt49 = 1 + elif (True) : + alt49 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("287:1: type_name : ( specifier_qualifier_list ( abstract_declarator )? | type_id );", 49, 13, self.input) + + raise nvae + + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("287:1: type_name : ( specifier_qualifier_list ( abstract_declarator )? | type_id );", 49, 0, self.input) + + raise nvae + + if alt49 == 1: + # C.g:288:4: specifier_qualifier_list ( abstract_declarator )? + self.following.append(self.FOLLOW_specifier_qualifier_list_in_type_name1031) + self.specifier_qualifier_list() + self.following.pop() + if self.failed: + return + # C.g:288:29: ( abstract_declarator )? + alt48 = 2 + LA48_0 = self.input.LA(1) + + if (LA48_0 == 61 or LA48_0 == 63 or LA48_0 == 65) : + alt48 = 1 + if alt48 == 1: + # C.g:0:0: abstract_declarator + self.following.append(self.FOLLOW_abstract_declarator_in_type_name1033) + self.abstract_declarator() + self.following.pop() + if self.failed: + return + + + + + + elif alt49 == 2: + # C.g:289:4: type_id + self.following.append(self.FOLLOW_type_id_in_type_name1039) + self.type_id() + self.following.pop() + if self.failed: + return + + + + except RecognitionException, re: + self.reportError(re) + self.recover(self.input, re) + finally: + if self.backtracking > 0: + self.memoize(self.input, 30, type_name_StartIndex) + + pass + + return + + # $ANTLR end type_name + + + # $ANTLR start abstract_declarator + # C.g:292:1: abstract_declarator : ( pointer ( direct_abstract_declarator )? | direct_abstract_declarator ); + def abstract_declarator(self, ): + + abstract_declarator_StartIndex = self.input.index() + try: + try: + if self.backtracking > 0 and self.alreadyParsedRule(self.input, 31): + return + + # C.g:293:2: ( pointer ( direct_abstract_declarator )? | direct_abstract_declarator ) + alt51 = 2 + LA51_0 = self.input.LA(1) + + if (LA51_0 == 65) : + alt51 = 1 + elif (LA51_0 == 61 or LA51_0 == 63) : + alt51 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("292:1: abstract_declarator : ( pointer ( direct_abstract_declarator )? | direct_abstract_declarator );", 51, 0, self.input) + + raise nvae + + if alt51 == 1: + # C.g:293:4: pointer ( direct_abstract_declarator )? + self.following.append(self.FOLLOW_pointer_in_abstract_declarator1050) + self.pointer() + self.following.pop() + if self.failed: + return + # C.g:293:12: ( direct_abstract_declarator )? + alt50 = 2 + LA50_0 = self.input.LA(1) + + if (LA50_0 == 61) : + LA50 = self.input.LA(2) + if LA50 == 62: + LA50_12 = self.input.LA(3) + + if (self.synpred90()) : + alt50 = 1 + elif LA50 == 58: + LA50_13 = self.input.LA(3) + + if (self.synpred90()) : + alt50 = 1 + elif LA50 == 65: + LA50_14 = self.input.LA(3) + + if (self.synpred90()) : + alt50 = 1 + elif LA50 == 59: + LA50_15 = self.input.LA(3) + + if (self.synpred90()) : + alt50 = 1 + elif LA50 == 60: + LA50_16 = self.input.LA(3) + + if (self.synpred90()) : + alt50 = 1 + elif LA50 == IDENTIFIER: + LA50_17 = self.input.LA(3) + + if (self.synpred90()) : + alt50 = 1 + elif LA50 == 61: + LA50_18 = self.input.LA(3) + + if (self.synpred90()) : + alt50 = 1 + elif LA50 == 29 or LA50 == 30 or LA50 == 31 or LA50 == 32 or LA50 == 33: + LA50_19 = self.input.LA(3) + + if (self.synpred90()) : + alt50 = 1 + elif LA50 == 34: + LA50_20 = self.input.LA(3) + + if (self.synpred90()) : + alt50 = 1 + elif LA50 == 35: + LA50_21 = self.input.LA(3) + + if (self.synpred90()) : + alt50 = 1 + elif LA50 == 36: + LA50_22 = self.input.LA(3) + + if (self.synpred90()) : + alt50 = 1 + elif LA50 == 37: + LA50_23 = self.input.LA(3) + + if (self.synpred90()) : + alt50 = 1 + elif LA50 == 38: + LA50_24 = self.input.LA(3) + + if (self.synpred90()) : + alt50 = 1 + elif LA50 == 39: + LA50_25 = self.input.LA(3) + + if (self.synpred90()) : + alt50 = 1 + elif LA50 == 40: + LA50_26 = self.input.LA(3) + + if (self.synpred90()) : + alt50 = 1 + elif LA50 == 41: + LA50_27 = self.input.LA(3) + + if (self.synpred90()) : + alt50 = 1 + elif LA50 == 42: + LA50_28 = self.input.LA(3) + + if (self.synpred90()) : + alt50 = 1 + elif LA50 == 45 or LA50 == 46: + LA50_29 = self.input.LA(3) + + if (self.synpred90()) : + alt50 = 1 + elif LA50 == 48: + LA50_30 = self.input.LA(3) + + if (self.synpred90()) : + alt50 = 1 + elif LA50 == 49 or LA50 == 50 or LA50 == 51 or LA50 == 52 or LA50 == 53 or LA50 == 54 or LA50 == 55 or LA50 == 56 or LA50 == 57: + LA50_31 = self.input.LA(3) + + if (self.synpred90()) : + alt50 = 1 + elif LA50 == 63: + LA50_32 = self.input.LA(3) + + if (self.synpred90()) : + alt50 = 1 + elif (LA50_0 == 63) : + LA50 = self.input.LA(2) + if LA50 == 64: + LA50_33 = self.input.LA(3) + + if (self.synpred90()) : + alt50 = 1 + elif LA50 == 61: + LA50_34 = self.input.LA(3) + + if (self.synpred90()) : + alt50 = 1 + elif LA50 == IDENTIFIER: + LA50_35 = self.input.LA(3) + + if (self.synpred90()) : + alt50 = 1 + elif LA50 == HEX_LITERAL: + LA50_36 = self.input.LA(3) + + if (self.synpred90()) : + alt50 = 1 + elif LA50 == OCTAL_LITERAL: + LA50_37 = self.input.LA(3) + + if (self.synpred90()) : + alt50 = 1 + elif LA50 == DECIMAL_LITERAL: + LA50_38 = self.input.LA(3) + + if (self.synpred90()) : + alt50 = 1 + elif LA50 == CHARACTER_LITERAL: + LA50_39 = self.input.LA(3) + + if (self.synpred90()) : + alt50 = 1 + elif LA50 == STRING_LITERAL: + LA50_40 = self.input.LA(3) + + if (self.synpred90()) : + alt50 = 1 + elif LA50 == FLOATING_POINT_LITERAL: + LA50_41 = self.input.LA(3) + + if (self.synpred90()) : + alt50 = 1 + elif LA50 == 71: + LA50_42 = self.input.LA(3) + + if (self.synpred90()) : + alt50 = 1 + elif LA50 == 72: + LA50_43 = self.input.LA(3) + + if (self.synpred90()) : + alt50 = 1 + elif LA50 == 65 or LA50 == 67 or LA50 == 68 or LA50 == 76 or LA50 == 77 or LA50 == 78: + LA50_44 = self.input.LA(3) + + if (self.synpred90()) : + alt50 = 1 + elif LA50 == 73: + LA50_45 = self.input.LA(3) + + if (self.synpred90()) : + alt50 = 1 + if alt50 == 1: + # C.g:0:0: direct_abstract_declarator + self.following.append(self.FOLLOW_direct_abstract_declarator_in_abstract_declarator1052) + self.direct_abstract_declarator() + self.following.pop() + if self.failed: + return + + + + + + elif alt51 == 2: + # C.g:294:4: direct_abstract_declarator + self.following.append(self.FOLLOW_direct_abstract_declarator_in_abstract_declarator1058) + self.direct_abstract_declarator() + self.following.pop() + if self.failed: + return + + + + except RecognitionException, re: + self.reportError(re) + self.recover(self.input, re) + finally: + if self.backtracking > 0: + self.memoize(self.input, 31, abstract_declarator_StartIndex) + + pass + + return + + # $ANTLR end abstract_declarator + + + # $ANTLR start direct_abstract_declarator + # C.g:297:1: direct_abstract_declarator : ( '(' abstract_declarator ')' | abstract_declarator_suffix ) ( abstract_declarator_suffix )* ; + def direct_abstract_declarator(self, ): + + direct_abstract_declarator_StartIndex = self.input.index() + try: + try: + if self.backtracking > 0 and self.alreadyParsedRule(self.input, 32): + return + + # C.g:298:2: ( ( '(' abstract_declarator ')' | abstract_declarator_suffix ) ( abstract_declarator_suffix )* ) + # C.g:298:4: ( '(' abstract_declarator ')' | abstract_declarator_suffix ) ( abstract_declarator_suffix )* + # C.g:298:4: ( '(' abstract_declarator ')' | abstract_declarator_suffix ) + alt52 = 2 + LA52_0 = self.input.LA(1) + + if (LA52_0 == 61) : + LA52 = self.input.LA(2) + if LA52 == IDENTIFIER or LA52 == 29 or LA52 == 30 or LA52 == 31 or LA52 == 32 or LA52 == 33 or LA52 == 34 or LA52 == 35 or LA52 == 36 or LA52 == 37 or LA52 == 38 or LA52 == 39 or LA52 == 40 or LA52 == 41 or LA52 == 42 or LA52 == 45 or LA52 == 46 or LA52 == 48 or LA52 == 49 or LA52 == 50 or LA52 == 51 or LA52 == 52 or LA52 == 53 or LA52 == 54 or LA52 == 55 or LA52 == 56 or LA52 == 57 or LA52 == 58 or LA52 == 59 or LA52 == 60 or LA52 == 62: + alt52 = 2 + elif LA52 == 65: + LA52_18 = self.input.LA(3) + + if (self.synpred92()) : + alt52 = 1 + elif (True) : + alt52 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("298:4: ( '(' abstract_declarator ')' | abstract_declarator_suffix )", 52, 18, self.input) + + raise nvae + + elif LA52 == 61 or LA52 == 63: + alt52 = 1 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("298:4: ( '(' abstract_declarator ')' | abstract_declarator_suffix )", 52, 1, self.input) + + raise nvae + + elif (LA52_0 == 63) : + alt52 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("298:4: ( '(' abstract_declarator ')' | abstract_declarator_suffix )", 52, 0, self.input) + + raise nvae + + if alt52 == 1: + # C.g:298:6: '(' abstract_declarator ')' + self.match(self.input, 61, self.FOLLOW_61_in_direct_abstract_declarator1071) + if self.failed: + return + self.following.append(self.FOLLOW_abstract_declarator_in_direct_abstract_declarator1073) + self.abstract_declarator() + self.following.pop() + if self.failed: + return + self.match(self.input, 62, self.FOLLOW_62_in_direct_abstract_declarator1075) + if self.failed: + return + + + elif alt52 == 2: + # C.g:298:36: abstract_declarator_suffix + self.following.append(self.FOLLOW_abstract_declarator_suffix_in_direct_abstract_declarator1079) + self.abstract_declarator_suffix() + self.following.pop() + if self.failed: + return + + + + # C.g:298:65: ( abstract_declarator_suffix )* + while True: #loop53 + alt53 = 2 + LA53_0 = self.input.LA(1) + + if (LA53_0 == 61) : + LA53 = self.input.LA(2) + if LA53 == 62: + LA53_12 = self.input.LA(3) + + if (self.synpred93()) : + alt53 = 1 + + + elif LA53 == 58: + LA53_13 = self.input.LA(3) + + if (self.synpred93()) : + alt53 = 1 + + + elif LA53 == 65: + LA53_14 = self.input.LA(3) + + if (self.synpred93()) : + alt53 = 1 + + + elif LA53 == 59: + LA53_15 = self.input.LA(3) + + if (self.synpred93()) : + alt53 = 1 + + + elif LA53 == 60: + LA53_16 = self.input.LA(3) + + if (self.synpred93()) : + alt53 = 1 + + + elif LA53 == IDENTIFIER: + LA53_17 = self.input.LA(3) + + if (self.synpred93()) : + alt53 = 1 + + + elif LA53 == 29 or LA53 == 30 or LA53 == 31 or LA53 == 32 or LA53 == 33: + LA53_19 = self.input.LA(3) + + if (self.synpred93()) : + alt53 = 1 + + + elif LA53 == 34: + LA53_20 = self.input.LA(3) + + if (self.synpred93()) : + alt53 = 1 + + + elif LA53 == 35: + LA53_21 = self.input.LA(3) + + if (self.synpred93()) : + alt53 = 1 + + + elif LA53 == 36: + LA53_22 = self.input.LA(3) + + if (self.synpred93()) : + alt53 = 1 + + + elif LA53 == 37: + LA53_23 = self.input.LA(3) + + if (self.synpred93()) : + alt53 = 1 + + + elif LA53 == 38: + LA53_24 = self.input.LA(3) + + if (self.synpred93()) : + alt53 = 1 + + + elif LA53 == 39: + LA53_25 = self.input.LA(3) + + if (self.synpred93()) : + alt53 = 1 + + + elif LA53 == 40: + LA53_26 = self.input.LA(3) + + if (self.synpred93()) : + alt53 = 1 + + + elif LA53 == 41: + LA53_27 = self.input.LA(3) + + if (self.synpred93()) : + alt53 = 1 + + + elif LA53 == 42: + LA53_28 = self.input.LA(3) + + if (self.synpred93()) : + alt53 = 1 + + + elif LA53 == 45 or LA53 == 46: + LA53_29 = self.input.LA(3) + + if (self.synpred93()) : + alt53 = 1 + + + elif LA53 == 48: + LA53_30 = self.input.LA(3) + + if (self.synpred93()) : + alt53 = 1 + + + elif LA53 == 49 or LA53 == 50 or LA53 == 51 or LA53 == 52 or LA53 == 53 or LA53 == 54 or LA53 == 55 or LA53 == 56 or LA53 == 57: + LA53_31 = self.input.LA(3) + + if (self.synpred93()) : + alt53 = 1 + + + + elif (LA53_0 == 63) : + LA53 = self.input.LA(2) + if LA53 == 64: + LA53_33 = self.input.LA(3) + + if (self.synpred93()) : + alt53 = 1 + + + elif LA53 == 61: + LA53_34 = self.input.LA(3) + + if (self.synpred93()) : + alt53 = 1 + + + elif LA53 == IDENTIFIER: + LA53_35 = self.input.LA(3) + + if (self.synpred93()) : + alt53 = 1 + + + elif LA53 == HEX_LITERAL: + LA53_36 = self.input.LA(3) + + if (self.synpred93()) : + alt53 = 1 + + + elif LA53 == OCTAL_LITERAL: + LA53_37 = self.input.LA(3) + + if (self.synpred93()) : + alt53 = 1 + + + elif LA53 == DECIMAL_LITERAL: + LA53_38 = self.input.LA(3) + + if (self.synpred93()) : + alt53 = 1 + + + elif LA53 == CHARACTER_LITERAL: + LA53_39 = self.input.LA(3) + + if (self.synpred93()) : + alt53 = 1 + + + elif LA53 == STRING_LITERAL: + LA53_40 = self.input.LA(3) + + if (self.synpred93()) : + alt53 = 1 + + + elif LA53 == FLOATING_POINT_LITERAL: + LA53_41 = self.input.LA(3) + + if (self.synpred93()) : + alt53 = 1 + + + elif LA53 == 71: + LA53_42 = self.input.LA(3) + + if (self.synpred93()) : + alt53 = 1 + + + elif LA53 == 72: + LA53_43 = self.input.LA(3) + + if (self.synpred93()) : + alt53 = 1 + + + elif LA53 == 65 or LA53 == 67 or LA53 == 68 or LA53 == 76 or LA53 == 77 or LA53 == 78: + LA53_44 = self.input.LA(3) + + if (self.synpred93()) : + alt53 = 1 + + + elif LA53 == 73: + LA53_45 = self.input.LA(3) + + if (self.synpred93()) : + alt53 = 1 + + + + + + if alt53 == 1: + # C.g:0:0: abstract_declarator_suffix + self.following.append(self.FOLLOW_abstract_declarator_suffix_in_direct_abstract_declarator1083) + self.abstract_declarator_suffix() + self.following.pop() + if self.failed: + return + + + else: + break #loop53 + + + + + + + except RecognitionException, re: + self.reportError(re) + self.recover(self.input, re) + finally: + if self.backtracking > 0: + self.memoize(self.input, 32, direct_abstract_declarator_StartIndex) + + pass + + return + + # $ANTLR end direct_abstract_declarator + + + # $ANTLR start abstract_declarator_suffix + # C.g:301:1: abstract_declarator_suffix : ( '[' ']' | '[' constant_expression ']' | '(' ')' | '(' parameter_type_list ')' ); + def abstract_declarator_suffix(self, ): + + abstract_declarator_suffix_StartIndex = self.input.index() + try: + try: + if self.backtracking > 0 and self.alreadyParsedRule(self.input, 33): + return + + # C.g:302:2: ( '[' ']' | '[' constant_expression ']' | '(' ')' | '(' parameter_type_list ')' ) + alt54 = 4 + LA54_0 = self.input.LA(1) + + if (LA54_0 == 63) : + LA54_1 = self.input.LA(2) + + if (LA54_1 == 64) : + alt54 = 1 + elif ((IDENTIFIER <= LA54_1 <= FLOATING_POINT_LITERAL) or LA54_1 == 61 or LA54_1 == 65 or (67 <= LA54_1 <= 68) or (71 <= LA54_1 <= 73) or (76 <= LA54_1 <= 78)) : + alt54 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("301:1: abstract_declarator_suffix : ( '[' ']' | '[' constant_expression ']' | '(' ')' | '(' parameter_type_list ')' );", 54, 1, self.input) + + raise nvae + + elif (LA54_0 == 61) : + LA54_2 = self.input.LA(2) + + if (LA54_2 == 62) : + alt54 = 3 + elif (LA54_2 == IDENTIFIER or (29 <= LA54_2 <= 42) or (45 <= LA54_2 <= 46) or (48 <= LA54_2 <= 60) or LA54_2 == 65) : + alt54 = 4 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("301:1: abstract_declarator_suffix : ( '[' ']' | '[' constant_expression ']' | '(' ')' | '(' parameter_type_list ')' );", 54, 2, self.input) + + raise nvae + + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("301:1: abstract_declarator_suffix : ( '[' ']' | '[' constant_expression ']' | '(' ')' | '(' parameter_type_list ')' );", 54, 0, self.input) + + raise nvae + + if alt54 == 1: + # C.g:302:4: '[' ']' + self.match(self.input, 63, self.FOLLOW_63_in_abstract_declarator_suffix1095) + if self.failed: + return + self.match(self.input, 64, self.FOLLOW_64_in_abstract_declarator_suffix1097) + if self.failed: + return + + + elif alt54 == 2: + # C.g:303:4: '[' constant_expression ']' + self.match(self.input, 63, self.FOLLOW_63_in_abstract_declarator_suffix1102) + if self.failed: + return + self.following.append(self.FOLLOW_constant_expression_in_abstract_declarator_suffix1104) + self.constant_expression() + self.following.pop() + if self.failed: + return + self.match(self.input, 64, self.FOLLOW_64_in_abstract_declarator_suffix1106) + if self.failed: + return + + + elif alt54 == 3: + # C.g:304:4: '(' ')' + self.match(self.input, 61, self.FOLLOW_61_in_abstract_declarator_suffix1111) + if self.failed: + return + self.match(self.input, 62, self.FOLLOW_62_in_abstract_declarator_suffix1113) + if self.failed: + return + + + elif alt54 == 4: + # C.g:305:4: '(' parameter_type_list ')' + self.match(self.input, 61, self.FOLLOW_61_in_abstract_declarator_suffix1118) + if self.failed: + return + self.following.append(self.FOLLOW_parameter_type_list_in_abstract_declarator_suffix1120) + self.parameter_type_list() + self.following.pop() + if self.failed: + return + self.match(self.input, 62, self.FOLLOW_62_in_abstract_declarator_suffix1122) + if self.failed: + return + + + + except RecognitionException, re: + self.reportError(re) + self.recover(self.input, re) + finally: + if self.backtracking > 0: + self.memoize(self.input, 33, abstract_declarator_suffix_StartIndex) + + pass + + return + + # $ANTLR end abstract_declarator_suffix + + + # $ANTLR start initializer + # C.g:308:1: initializer : ( assignment_expression | '{' initializer_list ( ',' )? '}' ); + def initializer(self, ): + + initializer_StartIndex = self.input.index() + try: + try: + if self.backtracking > 0 and self.alreadyParsedRule(self.input, 34): + return + + # C.g:310:2: ( assignment_expression | '{' initializer_list ( ',' )? '}' ) + alt56 = 2 + LA56_0 = self.input.LA(1) + + if ((IDENTIFIER <= LA56_0 <= FLOATING_POINT_LITERAL) or LA56_0 == 61 or LA56_0 == 65 or (67 <= LA56_0 <= 68) or (71 <= LA56_0 <= 73) or (76 <= LA56_0 <= 78)) : + alt56 = 1 + elif (LA56_0 == 43) : + alt56 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("308:1: initializer : ( assignment_expression | '{' initializer_list ( ',' )? '}' );", 56, 0, self.input) + + raise nvae + + if alt56 == 1: + # C.g:310:4: assignment_expression + self.following.append(self.FOLLOW_assignment_expression_in_initializer1135) + self.assignment_expression() + self.following.pop() + if self.failed: + return + + + elif alt56 == 2: + # C.g:311:4: '{' initializer_list ( ',' )? '}' + self.match(self.input, 43, self.FOLLOW_43_in_initializer1140) + if self.failed: + return + self.following.append(self.FOLLOW_initializer_list_in_initializer1142) + self.initializer_list() + self.following.pop() + if self.failed: + return + # C.g:311:25: ( ',' )? + alt55 = 2 + LA55_0 = self.input.LA(1) + + if (LA55_0 == 27) : + alt55 = 1 + if alt55 == 1: + # C.g:0:0: ',' + self.match(self.input, 27, self.FOLLOW_27_in_initializer1144) + if self.failed: + return + + + + self.match(self.input, 44, self.FOLLOW_44_in_initializer1147) + if self.failed: + return + + + + except RecognitionException, re: + self.reportError(re) + self.recover(self.input, re) + finally: + if self.backtracking > 0: + self.memoize(self.input, 34, initializer_StartIndex) + + pass + + return + + # $ANTLR end initializer + + + # $ANTLR start initializer_list + # C.g:314:1: initializer_list : initializer ( ',' initializer )* ; + def initializer_list(self, ): + + initializer_list_StartIndex = self.input.index() + try: + try: + if self.backtracking > 0 and self.alreadyParsedRule(self.input, 35): + return + + # C.g:315:2: ( initializer ( ',' initializer )* ) + # C.g:315:4: initializer ( ',' initializer )* + self.following.append(self.FOLLOW_initializer_in_initializer_list1158) + self.initializer() + self.following.pop() + if self.failed: + return + # C.g:315:16: ( ',' initializer )* + while True: #loop57 + alt57 = 2 + LA57_0 = self.input.LA(1) + + if (LA57_0 == 27) : + LA57_1 = self.input.LA(2) + + if ((IDENTIFIER <= LA57_1 <= FLOATING_POINT_LITERAL) or LA57_1 == 43 or LA57_1 == 61 or LA57_1 == 65 or (67 <= LA57_1 <= 68) or (71 <= LA57_1 <= 73) or (76 <= LA57_1 <= 78)) : + alt57 = 1 + + + + + if alt57 == 1: + # C.g:315:17: ',' initializer + self.match(self.input, 27, self.FOLLOW_27_in_initializer_list1161) + if self.failed: + return + self.following.append(self.FOLLOW_initializer_in_initializer_list1163) + self.initializer() + self.following.pop() + if self.failed: + return + + + else: + break #loop57 + + + + + + + except RecognitionException, re: + self.reportError(re) + self.recover(self.input, re) + finally: + if self.backtracking > 0: + self.memoize(self.input, 35, initializer_list_StartIndex) + + pass + + return + + # $ANTLR end initializer_list + + class argument_expression_list_return(object): + def __init__(self): + self.start = None + self.stop = None + + + + # $ANTLR start argument_expression_list + # C.g:320:1: argument_expression_list : assignment_expression ( 'OPTIONAL' )? ( ',' assignment_expression ( 'OPTIONAL' )? )* ; + def argument_expression_list(self, ): + + retval = self.argument_expression_list_return() + retval.start = self.input.LT(1) + argument_expression_list_StartIndex = self.input.index() + try: + try: + if self.backtracking > 0 and self.alreadyParsedRule(self.input, 36): + return retval + + # C.g:321:2: ( assignment_expression ( 'OPTIONAL' )? ( ',' assignment_expression ( 'OPTIONAL' )? )* ) + # C.g:321:6: assignment_expression ( 'OPTIONAL' )? ( ',' assignment_expression ( 'OPTIONAL' )? )* + self.following.append(self.FOLLOW_assignment_expression_in_argument_expression_list1181) + self.assignment_expression() + self.following.pop() + if self.failed: + return retval + # C.g:321:28: ( 'OPTIONAL' )? + alt58 = 2 + LA58_0 = self.input.LA(1) + + if (LA58_0 == 53) : + alt58 = 1 + if alt58 == 1: + # C.g:321:29: 'OPTIONAL' + self.match(self.input, 53, self.FOLLOW_53_in_argument_expression_list1184) + if self.failed: + return retval + + + + # C.g:321:42: ( ',' assignment_expression ( 'OPTIONAL' )? )* + while True: #loop60 + alt60 = 2 + LA60_0 = self.input.LA(1) + + if (LA60_0 == 27) : + alt60 = 1 + + + if alt60 == 1: + # C.g:321:43: ',' assignment_expression ( 'OPTIONAL' )? + self.match(self.input, 27, self.FOLLOW_27_in_argument_expression_list1189) + if self.failed: + return retval + self.following.append(self.FOLLOW_assignment_expression_in_argument_expression_list1191) + self.assignment_expression() + self.following.pop() + if self.failed: + return retval + # C.g:321:69: ( 'OPTIONAL' )? + alt59 = 2 + LA59_0 = self.input.LA(1) + + if (LA59_0 == 53) : + alt59 = 1 + if alt59 == 1: + # C.g:321:70: 'OPTIONAL' + self.match(self.input, 53, self.FOLLOW_53_in_argument_expression_list1194) + if self.failed: + return retval + + + + + + else: + break #loop60 + + + + + + retval.stop = self.input.LT(-1) + + + except RecognitionException, re: + self.reportError(re) + self.recover(self.input, re) + finally: + if self.backtracking > 0: + self.memoize(self.input, 36, argument_expression_list_StartIndex) + + pass + + return retval + + # $ANTLR end argument_expression_list + + + # $ANTLR start additive_expression + # C.g:324:1: additive_expression : ( multiplicative_expression ) ( '+' multiplicative_expression | '-' multiplicative_expression )* ; + def additive_expression(self, ): + + additive_expression_StartIndex = self.input.index() + try: + try: + if self.backtracking > 0 and self.alreadyParsedRule(self.input, 37): + return + + # C.g:325:2: ( ( multiplicative_expression ) ( '+' multiplicative_expression | '-' multiplicative_expression )* ) + # C.g:325:4: ( multiplicative_expression ) ( '+' multiplicative_expression | '-' multiplicative_expression )* + # C.g:325:4: ( multiplicative_expression ) + # C.g:325:5: multiplicative_expression + self.following.append(self.FOLLOW_multiplicative_expression_in_additive_expression1210) + self.multiplicative_expression() + self.following.pop() + if self.failed: + return + + + + # C.g:325:32: ( '+' multiplicative_expression | '-' multiplicative_expression )* + while True: #loop61 + alt61 = 3 + LA61_0 = self.input.LA(1) + + if (LA61_0 == 67) : + alt61 = 1 + elif (LA61_0 == 68) : + alt61 = 2 + + + if alt61 == 1: + # C.g:325:33: '+' multiplicative_expression + self.match(self.input, 67, self.FOLLOW_67_in_additive_expression1214) + if self.failed: + return + self.following.append(self.FOLLOW_multiplicative_expression_in_additive_expression1216) + self.multiplicative_expression() + self.following.pop() + if self.failed: + return + + + elif alt61 == 2: + # C.g:325:65: '-' multiplicative_expression + self.match(self.input, 68, self.FOLLOW_68_in_additive_expression1220) + if self.failed: + return + self.following.append(self.FOLLOW_multiplicative_expression_in_additive_expression1222) + self.multiplicative_expression() + self.following.pop() + if self.failed: + return + + + else: + break #loop61 + + + + + + + except RecognitionException, re: + self.reportError(re) + self.recover(self.input, re) + finally: + if self.backtracking > 0: + self.memoize(self.input, 37, additive_expression_StartIndex) + + pass + + return + + # $ANTLR end additive_expression + + + # $ANTLR start multiplicative_expression + # C.g:328:1: multiplicative_expression : ( cast_expression ) ( '*' cast_expression | '/' cast_expression | '%' cast_expression )* ; + def multiplicative_expression(self, ): + + multiplicative_expression_StartIndex = self.input.index() + try: + try: + if self.backtracking > 0 and self.alreadyParsedRule(self.input, 38): + return + + # C.g:329:2: ( ( cast_expression ) ( '*' cast_expression | '/' cast_expression | '%' cast_expression )* ) + # C.g:329:4: ( cast_expression ) ( '*' cast_expression | '/' cast_expression | '%' cast_expression )* + # C.g:329:4: ( cast_expression ) + # C.g:329:5: cast_expression + self.following.append(self.FOLLOW_cast_expression_in_multiplicative_expression1236) + self.cast_expression() + self.following.pop() + if self.failed: + return + + + + # C.g:329:22: ( '*' cast_expression | '/' cast_expression | '%' cast_expression )* + while True: #loop62 + alt62 = 4 + LA62 = self.input.LA(1) + if LA62 == 65: + alt62 = 1 + elif LA62 == 69: + alt62 = 2 + elif LA62 == 70: + alt62 = 3 + + if alt62 == 1: + # C.g:329:23: '*' cast_expression + self.match(self.input, 65, self.FOLLOW_65_in_multiplicative_expression1240) + if self.failed: + return + self.following.append(self.FOLLOW_cast_expression_in_multiplicative_expression1242) + self.cast_expression() + self.following.pop() + if self.failed: + return + + + elif alt62 == 2: + # C.g:329:45: '/' cast_expression + self.match(self.input, 69, self.FOLLOW_69_in_multiplicative_expression1246) + if self.failed: + return + self.following.append(self.FOLLOW_cast_expression_in_multiplicative_expression1248) + self.cast_expression() + self.following.pop() + if self.failed: + return + + + elif alt62 == 3: + # C.g:329:67: '%' cast_expression + self.match(self.input, 70, self.FOLLOW_70_in_multiplicative_expression1252) + if self.failed: + return + self.following.append(self.FOLLOW_cast_expression_in_multiplicative_expression1254) + self.cast_expression() + self.following.pop() + if self.failed: + return + + + else: + break #loop62 + + + + + + + except RecognitionException, re: + self.reportError(re) + self.recover(self.input, re) + finally: + if self.backtracking > 0: + self.memoize(self.input, 38, multiplicative_expression_StartIndex) + + pass + + return + + # $ANTLR end multiplicative_expression + + + # $ANTLR start cast_expression + # C.g:332:1: cast_expression : ( '(' type_name ')' cast_expression | unary_expression ); + def cast_expression(self, ): + + cast_expression_StartIndex = self.input.index() + try: + try: + if self.backtracking > 0 and self.alreadyParsedRule(self.input, 39): + return + + # C.g:333:2: ( '(' type_name ')' cast_expression | unary_expression ) + alt63 = 2 + LA63_0 = self.input.LA(1) + + if (LA63_0 == 61) : + LA63 = self.input.LA(2) + if LA63 == IDENTIFIER: + LA63_13 = self.input.LA(3) + + if (self.synpred108()) : + alt63 = 1 + elif (True) : + alt63 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("332:1: cast_expression : ( '(' type_name ')' cast_expression | unary_expression );", 63, 13, self.input) + + raise nvae + + elif LA63 == HEX_LITERAL or LA63 == OCTAL_LITERAL or LA63 == DECIMAL_LITERAL or LA63 == CHARACTER_LITERAL or LA63 == STRING_LITERAL or LA63 == FLOATING_POINT_LITERAL or LA63 == 61 or LA63 == 65 or LA63 == 67 or LA63 == 68 or LA63 == 71 or LA63 == 72 or LA63 == 73 or LA63 == 76 or LA63 == 77 or LA63 == 78: + alt63 = 2 + elif LA63 == 34 or LA63 == 35 or LA63 == 36 or LA63 == 37 or LA63 == 38 or LA63 == 39 or LA63 == 40 or LA63 == 41 or LA63 == 42 or LA63 == 45 or LA63 == 46 or LA63 == 48 or LA63 == 49 or LA63 == 50 or LA63 == 51 or LA63 == 52 or LA63 == 53 or LA63 == 54 or LA63 == 55 or LA63 == 56 or LA63 == 57 or LA63 == 58 or LA63 == 59 or LA63 == 60: + alt63 = 1 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("332:1: cast_expression : ( '(' type_name ')' cast_expression | unary_expression );", 63, 1, self.input) + + raise nvae + + elif ((IDENTIFIER <= LA63_0 <= FLOATING_POINT_LITERAL) or LA63_0 == 65 or (67 <= LA63_0 <= 68) or (71 <= LA63_0 <= 73) or (76 <= LA63_0 <= 78)) : + alt63 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("332:1: cast_expression : ( '(' type_name ')' cast_expression | unary_expression );", 63, 0, self.input) + + raise nvae + + if alt63 == 1: + # C.g:333:4: '(' type_name ')' cast_expression + self.match(self.input, 61, self.FOLLOW_61_in_cast_expression1267) + if self.failed: + return + self.following.append(self.FOLLOW_type_name_in_cast_expression1269) + self.type_name() + self.following.pop() + if self.failed: + return + self.match(self.input, 62, self.FOLLOW_62_in_cast_expression1271) + if self.failed: + return + self.following.append(self.FOLLOW_cast_expression_in_cast_expression1273) + self.cast_expression() + self.following.pop() + if self.failed: + return + + + elif alt63 == 2: + # C.g:334:4: unary_expression + self.following.append(self.FOLLOW_unary_expression_in_cast_expression1278) + self.unary_expression() + self.following.pop() + if self.failed: + return + + + + except RecognitionException, re: + self.reportError(re) + self.recover(self.input, re) + finally: + if self.backtracking > 0: + self.memoize(self.input, 39, cast_expression_StartIndex) + + pass + + return + + # $ANTLR end cast_expression + + + # $ANTLR start unary_expression + # C.g:337:1: unary_expression : ( postfix_expression | '++' unary_expression | '--' unary_expression | unary_operator cast_expression | 'sizeof' unary_expression | 'sizeof' '(' type_name ')' ); + def unary_expression(self, ): + + unary_expression_StartIndex = self.input.index() + try: + try: + if self.backtracking > 0 and self.alreadyParsedRule(self.input, 40): + return + + # C.g:338:2: ( postfix_expression | '++' unary_expression | '--' unary_expression | unary_operator cast_expression | 'sizeof' unary_expression | 'sizeof' '(' type_name ')' ) + alt64 = 6 + LA64 = self.input.LA(1) + if LA64 == IDENTIFIER or LA64 == HEX_LITERAL or LA64 == OCTAL_LITERAL or LA64 == DECIMAL_LITERAL or LA64 == CHARACTER_LITERAL or LA64 == STRING_LITERAL or LA64 == FLOATING_POINT_LITERAL or LA64 == 61: + alt64 = 1 + elif LA64 == 71: + alt64 = 2 + elif LA64 == 72: + alt64 = 3 + elif LA64 == 65 or LA64 == 67 or LA64 == 68 or LA64 == 76 or LA64 == 77 or LA64 == 78: + alt64 = 4 + elif LA64 == 73: + LA64_12 = self.input.LA(2) + + if (LA64_12 == 61) : + LA64_13 = self.input.LA(3) + + if (self.synpred113()) : + alt64 = 5 + elif (True) : + alt64 = 6 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("337:1: unary_expression : ( postfix_expression | '++' unary_expression | '--' unary_expression | unary_operator cast_expression | 'sizeof' unary_expression | 'sizeof' '(' type_name ')' );", 64, 13, self.input) + + raise nvae + + elif ((IDENTIFIER <= LA64_12 <= FLOATING_POINT_LITERAL) or LA64_12 == 65 or (67 <= LA64_12 <= 68) or (71 <= LA64_12 <= 73) or (76 <= LA64_12 <= 78)) : + alt64 = 5 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("337:1: unary_expression : ( postfix_expression | '++' unary_expression | '--' unary_expression | unary_operator cast_expression | 'sizeof' unary_expression | 'sizeof' '(' type_name ')' );", 64, 12, self.input) + + raise nvae + + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("337:1: unary_expression : ( postfix_expression | '++' unary_expression | '--' unary_expression | unary_operator cast_expression | 'sizeof' unary_expression | 'sizeof' '(' type_name ')' );", 64, 0, self.input) + + raise nvae + + if alt64 == 1: + # C.g:338:4: postfix_expression + self.following.append(self.FOLLOW_postfix_expression_in_unary_expression1289) + self.postfix_expression() + self.following.pop() + if self.failed: + return + + + elif alt64 == 2: + # C.g:339:4: '++' unary_expression + self.match(self.input, 71, self.FOLLOW_71_in_unary_expression1294) + if self.failed: + return + self.following.append(self.FOLLOW_unary_expression_in_unary_expression1296) + self.unary_expression() + self.following.pop() + if self.failed: + return + + + elif alt64 == 3: + # C.g:340:4: '--' unary_expression + self.match(self.input, 72, self.FOLLOW_72_in_unary_expression1301) + if self.failed: + return + self.following.append(self.FOLLOW_unary_expression_in_unary_expression1303) + self.unary_expression() + self.following.pop() + if self.failed: + return + + + elif alt64 == 4: + # C.g:341:4: unary_operator cast_expression + self.following.append(self.FOLLOW_unary_operator_in_unary_expression1308) + self.unary_operator() + self.following.pop() + if self.failed: + return + self.following.append(self.FOLLOW_cast_expression_in_unary_expression1310) + self.cast_expression() + self.following.pop() + if self.failed: + return + + + elif alt64 == 5: + # C.g:342:4: 'sizeof' unary_expression + self.match(self.input, 73, self.FOLLOW_73_in_unary_expression1315) + if self.failed: + return + self.following.append(self.FOLLOW_unary_expression_in_unary_expression1317) + self.unary_expression() + self.following.pop() + if self.failed: + return + + + elif alt64 == 6: + # C.g:343:4: 'sizeof' '(' type_name ')' + self.match(self.input, 73, self.FOLLOW_73_in_unary_expression1322) + if self.failed: + return + self.match(self.input, 61, self.FOLLOW_61_in_unary_expression1324) + if self.failed: + return + self.following.append(self.FOLLOW_type_name_in_unary_expression1326) + self.type_name() + self.following.pop() + if self.failed: + return + self.match(self.input, 62, self.FOLLOW_62_in_unary_expression1328) + if self.failed: + return + + + + except RecognitionException, re: + self.reportError(re) + self.recover(self.input, re) + finally: + if self.backtracking > 0: + self.memoize(self.input, 40, unary_expression_StartIndex) + + pass + + return + + # $ANTLR end unary_expression + + + # $ANTLR start postfix_expression + # C.g:346:1: postfix_expression : p= primary_expression ( '[' expression ']' | '(' a= ')' | '(' c= argument_expression_list b= ')' | '(' macro_parameter_list ')' | '.' x= IDENTIFIER | '*' y= IDENTIFIER | '->' z= IDENTIFIER | '++' | '--' )* ; + def postfix_expression(self, ): + self.postfix_expression_stack.append(postfix_expression_scope()) + postfix_expression_StartIndex = self.input.index() + a = None + b = None + x = None + y = None + z = None + p = None + + c = None + + + + self.postfix_expression_stack[-1].FuncCallText = '' + + try: + try: + if self.backtracking > 0 and self.alreadyParsedRule(self.input, 41): + return + + # C.g:353:2: (p= primary_expression ( '[' expression ']' | '(' a= ')' | '(' c= argument_expression_list b= ')' | '(' macro_parameter_list ')' | '.' x= IDENTIFIER | '*' y= IDENTIFIER | '->' z= IDENTIFIER | '++' | '--' )* ) + # C.g:353:6: p= primary_expression ( '[' expression ']' | '(' a= ')' | '(' c= argument_expression_list b= ')' | '(' macro_parameter_list ')' | '.' x= IDENTIFIER | '*' y= IDENTIFIER | '->' z= IDENTIFIER | '++' | '--' )* + self.following.append(self.FOLLOW_primary_expression_in_postfix_expression1352) + p = self.primary_expression() + self.following.pop() + if self.failed: + return + if self.backtracking == 0: + self.postfix_expression_stack[-1].FuncCallText += self.input.toString(p.start,p.stop) + + # C.g:354:9: ( '[' expression ']' | '(' a= ')' | '(' c= argument_expression_list b= ')' | '(' macro_parameter_list ')' | '.' x= IDENTIFIER | '*' y= IDENTIFIER | '->' z= IDENTIFIER | '++' | '--' )* + while True: #loop65 + alt65 = 10 + LA65 = self.input.LA(1) + if LA65 == 65: + LA65_1 = self.input.LA(2) + + if (LA65_1 == IDENTIFIER) : + LA65_30 = self.input.LA(3) + + if (self.synpred119()) : + alt65 = 6 + + + + + elif LA65 == 63: + alt65 = 1 + elif LA65 == 61: + LA65 = self.input.LA(2) + if LA65 == 62: + alt65 = 2 + elif LA65 == IDENTIFIER: + LA65_43 = self.input.LA(3) + + if (self.synpred116()) : + alt65 = 3 + elif (self.synpred117()) : + alt65 = 4 + + + elif LA65 == HEX_LITERAL or LA65 == OCTAL_LITERAL or LA65 == DECIMAL_LITERAL or LA65 == CHARACTER_LITERAL or LA65 == STRING_LITERAL or LA65 == FLOATING_POINT_LITERAL or LA65 == 61 or LA65 == 67 or LA65 == 68 or LA65 == 71 or LA65 == 72 or LA65 == 73 or LA65 == 76 or LA65 == 77 or LA65 == 78: + alt65 = 3 + elif LA65 == 65: + LA65_53 = self.input.LA(3) + + if (self.synpred116()) : + alt65 = 3 + elif (self.synpred117()) : + alt65 = 4 + + + elif LA65 == 29 or LA65 == 30 or LA65 == 31 or LA65 == 32 or LA65 == 33 or LA65 == 34 or LA65 == 35 or LA65 == 36 or LA65 == 37 or LA65 == 38 or LA65 == 39 or LA65 == 40 or LA65 == 41 or LA65 == 42 or LA65 == 45 or LA65 == 46 or LA65 == 48 or LA65 == 49 or LA65 == 50 or LA65 == 51 or LA65 == 52 or LA65 == 53 or LA65 == 54 or LA65 == 55 or LA65 == 56 or LA65 == 57 or LA65 == 58 or LA65 == 59 or LA65 == 60: + alt65 = 4 + + elif LA65 == 74: + alt65 = 5 + elif LA65 == 75: + alt65 = 7 + elif LA65 == 71: + alt65 = 8 + elif LA65 == 72: + alt65 = 9 + + if alt65 == 1: + # C.g:354:13: '[' expression ']' + self.match(self.input, 63, self.FOLLOW_63_in_postfix_expression1368) + if self.failed: + return + self.following.append(self.FOLLOW_expression_in_postfix_expression1370) + self.expression() + self.following.pop() + if self.failed: + return + self.match(self.input, 64, self.FOLLOW_64_in_postfix_expression1372) + if self.failed: + return + + + elif alt65 == 2: + # C.g:355:13: '(' a= ')' + self.match(self.input, 61, self.FOLLOW_61_in_postfix_expression1386) + if self.failed: + return + a = self.input.LT(1) + self.match(self.input, 62, self.FOLLOW_62_in_postfix_expression1390) + if self.failed: + return + if self.backtracking == 0: + self.StoreFunctionCalling(p.start.line, p.start.charPositionInLine, a.line, a.charPositionInLine, self.postfix_expression_stack[-1].FuncCallText, '') + + + + elif alt65 == 3: + # C.g:356:13: '(' c= argument_expression_list b= ')' + self.match(self.input, 61, self.FOLLOW_61_in_postfix_expression1405) + if self.failed: + return + self.following.append(self.FOLLOW_argument_expression_list_in_postfix_expression1409) + c = self.argument_expression_list() + self.following.pop() + if self.failed: + return + b = self.input.LT(1) + self.match(self.input, 62, self.FOLLOW_62_in_postfix_expression1413) + if self.failed: + return + if self.backtracking == 0: + self.StoreFunctionCalling(p.start.line, p.start.charPositionInLine, b.line, b.charPositionInLine, self.postfix_expression_stack[-1].FuncCallText, self.input.toString(c.start,c.stop)) + + + + elif alt65 == 4: + # C.g:357:13: '(' macro_parameter_list ')' + self.match(self.input, 61, self.FOLLOW_61_in_postfix_expression1429) + if self.failed: + return + self.following.append(self.FOLLOW_macro_parameter_list_in_postfix_expression1431) + self.macro_parameter_list() + self.following.pop() + if self.failed: + return + self.match(self.input, 62, self.FOLLOW_62_in_postfix_expression1433) + if self.failed: + return + + + elif alt65 == 5: + # C.g:358:13: '.' x= IDENTIFIER + self.match(self.input, 74, self.FOLLOW_74_in_postfix_expression1447) + if self.failed: + return + x = self.input.LT(1) + self.match(self.input, IDENTIFIER, self.FOLLOW_IDENTIFIER_in_postfix_expression1451) + if self.failed: + return + if self.backtracking == 0: + self.postfix_expression_stack[-1].FuncCallText += '.' + x.text + + + + elif alt65 == 6: + # C.g:359:13: '*' y= IDENTIFIER + self.match(self.input, 65, self.FOLLOW_65_in_postfix_expression1467) + if self.failed: + return + y = self.input.LT(1) + self.match(self.input, IDENTIFIER, self.FOLLOW_IDENTIFIER_in_postfix_expression1471) + if self.failed: + return + if self.backtracking == 0: + self.postfix_expression_stack[-1].FuncCallText = y.text + + + + elif alt65 == 7: + # C.g:360:13: '->' z= IDENTIFIER + self.match(self.input, 75, self.FOLLOW_75_in_postfix_expression1487) + if self.failed: + return + z = self.input.LT(1) + self.match(self.input, IDENTIFIER, self.FOLLOW_IDENTIFIER_in_postfix_expression1491) + if self.failed: + return + if self.backtracking == 0: + self.postfix_expression_stack[-1].FuncCallText += '->' + z.text + + + + elif alt65 == 8: + # C.g:361:13: '++' + self.match(self.input, 71, self.FOLLOW_71_in_postfix_expression1507) + if self.failed: + return + + + elif alt65 == 9: + # C.g:362:13: '--' + self.match(self.input, 72, self.FOLLOW_72_in_postfix_expression1521) + if self.failed: + return + + + else: + break #loop65 + + + + + + + except RecognitionException, re: + self.reportError(re) + self.recover(self.input, re) + finally: + if self.backtracking > 0: + self.memoize(self.input, 41, postfix_expression_StartIndex) + + self.postfix_expression_stack.pop() + pass + + return + + # $ANTLR end postfix_expression + + + # $ANTLR start macro_parameter_list + # C.g:366:1: macro_parameter_list : parameter_declaration ( ',' parameter_declaration )* ; + def macro_parameter_list(self, ): + + macro_parameter_list_StartIndex = self.input.index() + try: + try: + if self.backtracking > 0 and self.alreadyParsedRule(self.input, 42): + return + + # C.g:367:2: ( parameter_declaration ( ',' parameter_declaration )* ) + # C.g:367:4: parameter_declaration ( ',' parameter_declaration )* + self.following.append(self.FOLLOW_parameter_declaration_in_macro_parameter_list1544) + self.parameter_declaration() + self.following.pop() + if self.failed: + return + # C.g:367:26: ( ',' parameter_declaration )* + while True: #loop66 + alt66 = 2 + LA66_0 = self.input.LA(1) + + if (LA66_0 == 27) : + alt66 = 1 + + + if alt66 == 1: + # C.g:367:27: ',' parameter_declaration + self.match(self.input, 27, self.FOLLOW_27_in_macro_parameter_list1547) + if self.failed: + return + self.following.append(self.FOLLOW_parameter_declaration_in_macro_parameter_list1549) + self.parameter_declaration() + self.following.pop() + if self.failed: + return + + + else: + break #loop66 + + + + + + + except RecognitionException, re: + self.reportError(re) + self.recover(self.input, re) + finally: + if self.backtracking > 0: + self.memoize(self.input, 42, macro_parameter_list_StartIndex) + + pass + + return + + # $ANTLR end macro_parameter_list + + + # $ANTLR start unary_operator + # C.g:370:1: unary_operator : ( '&' | '*' | '+' | '-' | '~' | '!' ); + def unary_operator(self, ): + + unary_operator_StartIndex = self.input.index() + try: + try: + if self.backtracking > 0 and self.alreadyParsedRule(self.input, 43): + return + + # C.g:371:2: ( '&' | '*' | '+' | '-' | '~' | '!' ) + # C.g: + if self.input.LA(1) == 65 or (67 <= self.input.LA(1) <= 68) or (76 <= self.input.LA(1) <= 78): + self.input.consume(); + self.errorRecovery = False + self.failed = False + + else: + if self.backtracking > 0: + self.failed = True + return + + mse = MismatchedSetException(None, self.input) + self.recoverFromMismatchedSet( + self.input, mse, self.FOLLOW_set_in_unary_operator0 + ) + raise mse + + + + + + + except RecognitionException, re: + self.reportError(re) + self.recover(self.input, re) + finally: + if self.backtracking > 0: + self.memoize(self.input, 43, unary_operator_StartIndex) + + pass + + return + + # $ANTLR end unary_operator + + class primary_expression_return(object): + def __init__(self): + self.start = None + self.stop = None + + + + # $ANTLR start primary_expression + # C.g:379:1: primary_expression : ( IDENTIFIER | constant | '(' expression ')' ); + def primary_expression(self, ): + + retval = self.primary_expression_return() + retval.start = self.input.LT(1) + primary_expression_StartIndex = self.input.index() + try: + try: + if self.backtracking > 0 and self.alreadyParsedRule(self.input, 44): + return retval + + # C.g:380:2: ( IDENTIFIER | constant | '(' expression ')' ) + alt67 = 3 + LA67 = self.input.LA(1) + if LA67 == IDENTIFIER: + LA67_1 = self.input.LA(2) + + if (LA67_1 == IDENTIFIER or LA67_1 == STRING_LITERAL) : + alt67 = 2 + elif (LA67_1 == EOF or LA67_1 == 25 or (27 <= LA67_1 <= 28) or LA67_1 == 44 or LA67_1 == 47 or LA67_1 == 53 or (61 <= LA67_1 <= 65) or (67 <= LA67_1 <= 72) or (74 <= LA67_1 <= 76) or (79 <= LA67_1 <= 101)) : + alt67 = 1 + else: + if self.backtracking > 0: + self.failed = True + return retval + + nvae = NoViableAltException("379:1: primary_expression : ( IDENTIFIER | constant | '(' expression ')' );", 67, 1, self.input) + + raise nvae + + elif LA67 == HEX_LITERAL or LA67 == OCTAL_LITERAL or LA67 == DECIMAL_LITERAL or LA67 == CHARACTER_LITERAL or LA67 == STRING_LITERAL or LA67 == FLOATING_POINT_LITERAL: + alt67 = 2 + elif LA67 == 61: + alt67 = 3 + else: + if self.backtracking > 0: + self.failed = True + return retval + + nvae = NoViableAltException("379:1: primary_expression : ( IDENTIFIER | constant | '(' expression ')' );", 67, 0, self.input) + + raise nvae + + if alt67 == 1: + # C.g:380:4: IDENTIFIER + self.match(self.input, IDENTIFIER, self.FOLLOW_IDENTIFIER_in_primary_expression1598) + if self.failed: + return retval + + + elif alt67 == 2: + # C.g:381:4: constant + self.following.append(self.FOLLOW_constant_in_primary_expression1603) + self.constant() + self.following.pop() + if self.failed: + return retval + + + elif alt67 == 3: + # C.g:382:4: '(' expression ')' + self.match(self.input, 61, self.FOLLOW_61_in_primary_expression1608) + if self.failed: + return retval + self.following.append(self.FOLLOW_expression_in_primary_expression1610) + self.expression() + self.following.pop() + if self.failed: + return retval + self.match(self.input, 62, self.FOLLOW_62_in_primary_expression1612) + if self.failed: + return retval + + + retval.stop = self.input.LT(-1) + + + except RecognitionException, re: + self.reportError(re) + self.recover(self.input, re) + finally: + if self.backtracking > 0: + self.memoize(self.input, 44, primary_expression_StartIndex) + + pass + + return retval + + # $ANTLR end primary_expression + + + # $ANTLR start constant + # C.g:385:1: constant : ( HEX_LITERAL | OCTAL_LITERAL | DECIMAL_LITERAL | CHARACTER_LITERAL | ( ( IDENTIFIER )* ( STRING_LITERAL )+ )+ ( IDENTIFIER )* | FLOATING_POINT_LITERAL ); + def constant(self, ): + + constant_StartIndex = self.input.index() + try: + try: + if self.backtracking > 0 and self.alreadyParsedRule(self.input, 45): + return + + # C.g:386:5: ( HEX_LITERAL | OCTAL_LITERAL | DECIMAL_LITERAL | CHARACTER_LITERAL | ( ( IDENTIFIER )* ( STRING_LITERAL )+ )+ ( IDENTIFIER )* | FLOATING_POINT_LITERAL ) + alt72 = 6 + LA72 = self.input.LA(1) + if LA72 == HEX_LITERAL: + alt72 = 1 + elif LA72 == OCTAL_LITERAL: + alt72 = 2 + elif LA72 == DECIMAL_LITERAL: + alt72 = 3 + elif LA72 == CHARACTER_LITERAL: + alt72 = 4 + elif LA72 == IDENTIFIER or LA72 == STRING_LITERAL: + alt72 = 5 + elif LA72 == FLOATING_POINT_LITERAL: + alt72 = 6 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("385:1: constant : ( HEX_LITERAL | OCTAL_LITERAL | DECIMAL_LITERAL | CHARACTER_LITERAL | ( ( IDENTIFIER )* ( STRING_LITERAL )+ )+ ( IDENTIFIER )* | FLOATING_POINT_LITERAL );", 72, 0, self.input) + + raise nvae + + if alt72 == 1: + # C.g:386:9: HEX_LITERAL + self.match(self.input, HEX_LITERAL, self.FOLLOW_HEX_LITERAL_in_constant1628) + if self.failed: + return + + + elif alt72 == 2: + # C.g:387:9: OCTAL_LITERAL + self.match(self.input, OCTAL_LITERAL, self.FOLLOW_OCTAL_LITERAL_in_constant1638) + if self.failed: + return + + + elif alt72 == 3: + # C.g:388:9: DECIMAL_LITERAL + self.match(self.input, DECIMAL_LITERAL, self.FOLLOW_DECIMAL_LITERAL_in_constant1648) + if self.failed: + return + + + elif alt72 == 4: + # C.g:389:7: CHARACTER_LITERAL + self.match(self.input, CHARACTER_LITERAL, self.FOLLOW_CHARACTER_LITERAL_in_constant1656) + if self.failed: + return + + + elif alt72 == 5: + # C.g:390:7: ( ( IDENTIFIER )* ( STRING_LITERAL )+ )+ ( IDENTIFIER )* + # C.g:390:7: ( ( IDENTIFIER )* ( STRING_LITERAL )+ )+ + cnt70 = 0 + while True: #loop70 + alt70 = 2 + LA70_0 = self.input.LA(1) + + if (LA70_0 == IDENTIFIER) : + LA70_1 = self.input.LA(2) + + if (LA70_1 == IDENTIFIER) : + LA70_61 = self.input.LA(3) + + if (self.synpred137()) : + alt70 = 1 + + + elif (LA70_1 == STRING_LITERAL) : + alt70 = 1 + + + elif (LA70_0 == STRING_LITERAL) : + alt70 = 1 + + + if alt70 == 1: + # C.g:390:8: ( IDENTIFIER )* ( STRING_LITERAL )+ + # C.g:390:8: ( IDENTIFIER )* + while True: #loop68 + alt68 = 2 + LA68_0 = self.input.LA(1) + + if (LA68_0 == IDENTIFIER) : + alt68 = 1 + + + if alt68 == 1: + # C.g:0:0: IDENTIFIER + self.match(self.input, IDENTIFIER, self.FOLLOW_IDENTIFIER_in_constant1665) + if self.failed: + return + + + else: + break #loop68 + + + # C.g:390:20: ( STRING_LITERAL )+ + cnt69 = 0 + while True: #loop69 + alt69 = 2 + LA69_0 = self.input.LA(1) + + if (LA69_0 == STRING_LITERAL) : + LA69_31 = self.input.LA(2) + + if (self.synpred136()) : + alt69 = 1 + + + + + if alt69 == 1: + # C.g:0:0: STRING_LITERAL + self.match(self.input, STRING_LITERAL, self.FOLLOW_STRING_LITERAL_in_constant1668) + if self.failed: + return + + + else: + if cnt69 >= 1: + break #loop69 + + if self.backtracking > 0: + self.failed = True + return + + eee = EarlyExitException(69, self.input) + raise eee + + cnt69 += 1 + + + + + else: + if cnt70 >= 1: + break #loop70 + + if self.backtracking > 0: + self.failed = True + return + + eee = EarlyExitException(70, self.input) + raise eee + + cnt70 += 1 + + + # C.g:390:38: ( IDENTIFIER )* + while True: #loop71 + alt71 = 2 + LA71_0 = self.input.LA(1) + + if (LA71_0 == IDENTIFIER) : + alt71 = 1 + + + if alt71 == 1: + # C.g:0:0: IDENTIFIER + self.match(self.input, IDENTIFIER, self.FOLLOW_IDENTIFIER_in_constant1673) + if self.failed: + return + + + else: + break #loop71 + + + + + elif alt72 == 6: + # C.g:391:9: FLOATING_POINT_LITERAL + self.match(self.input, FLOATING_POINT_LITERAL, self.FOLLOW_FLOATING_POINT_LITERAL_in_constant1684) + if self.failed: + return + + + + except RecognitionException, re: + self.reportError(re) + self.recover(self.input, re) + finally: + if self.backtracking > 0: + self.memoize(self.input, 45, constant_StartIndex) + + pass + + return + + # $ANTLR end constant + + class expression_return(object): + def __init__(self): + self.start = None + self.stop = None + + + + # $ANTLR start expression + # C.g:396:1: expression : assignment_expression ( ',' assignment_expression )* ; + def expression(self, ): + + retval = self.expression_return() + retval.start = self.input.LT(1) + expression_StartIndex = self.input.index() + try: + try: + if self.backtracking > 0 and self.alreadyParsedRule(self.input, 46): + return retval + + # C.g:397:2: ( assignment_expression ( ',' assignment_expression )* ) + # C.g:397:4: assignment_expression ( ',' assignment_expression )* + self.following.append(self.FOLLOW_assignment_expression_in_expression1700) + self.assignment_expression() + self.following.pop() + if self.failed: + return retval + # C.g:397:26: ( ',' assignment_expression )* + while True: #loop73 + alt73 = 2 + LA73_0 = self.input.LA(1) + + if (LA73_0 == 27) : + alt73 = 1 + + + if alt73 == 1: + # C.g:397:27: ',' assignment_expression + self.match(self.input, 27, self.FOLLOW_27_in_expression1703) + if self.failed: + return retval + self.following.append(self.FOLLOW_assignment_expression_in_expression1705) + self.assignment_expression() + self.following.pop() + if self.failed: + return retval + + + else: + break #loop73 + + + + + + retval.stop = self.input.LT(-1) + + + except RecognitionException, re: + self.reportError(re) + self.recover(self.input, re) + finally: + if self.backtracking > 0: + self.memoize(self.input, 46, expression_StartIndex) + + pass + + return retval + + # $ANTLR end expression + + + # $ANTLR start constant_expression + # C.g:400:1: constant_expression : conditional_expression ; + def constant_expression(self, ): + + constant_expression_StartIndex = self.input.index() + try: + try: + if self.backtracking > 0 and self.alreadyParsedRule(self.input, 47): + return + + # C.g:401:2: ( conditional_expression ) + # C.g:401:4: conditional_expression + self.following.append(self.FOLLOW_conditional_expression_in_constant_expression1718) + self.conditional_expression() + self.following.pop() + if self.failed: + return + + + + + except RecognitionException, re: + self.reportError(re) + self.recover(self.input, re) + finally: + if self.backtracking > 0: + self.memoize(self.input, 47, constant_expression_StartIndex) + + pass + + return + + # $ANTLR end constant_expression + + + # $ANTLR start assignment_expression + # C.g:404:1: assignment_expression : ( lvalue assignment_operator assignment_expression | conditional_expression ); + def assignment_expression(self, ): + + assignment_expression_StartIndex = self.input.index() + try: + try: + if self.backtracking > 0 and self.alreadyParsedRule(self.input, 48): + return + + # C.g:405:2: ( lvalue assignment_operator assignment_expression | conditional_expression ) + alt74 = 2 + LA74 = self.input.LA(1) + if LA74 == IDENTIFIER: + LA74 = self.input.LA(2) + if LA74 == STRING_LITERAL: + LA74_13 = self.input.LA(3) + + if (self.synpred141()) : + alt74 = 1 + elif (True) : + alt74 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("404:1: assignment_expression : ( lvalue assignment_operator assignment_expression | conditional_expression );", 74, 13, self.input) + + raise nvae + + elif LA74 == IDENTIFIER: + LA74_14 = self.input.LA(3) + + if (self.synpred141()) : + alt74 = 1 + elif (True) : + alt74 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("404:1: assignment_expression : ( lvalue assignment_operator assignment_expression | conditional_expression );", 74, 14, self.input) + + raise nvae + + elif LA74 == 63: + LA74_15 = self.input.LA(3) + + if (self.synpred141()) : + alt74 = 1 + elif (True) : + alt74 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("404:1: assignment_expression : ( lvalue assignment_operator assignment_expression | conditional_expression );", 74, 15, self.input) + + raise nvae + + elif LA74 == 61: + LA74_16 = self.input.LA(3) + + if (self.synpred141()) : + alt74 = 1 + elif (True) : + alt74 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("404:1: assignment_expression : ( lvalue assignment_operator assignment_expression | conditional_expression );", 74, 16, self.input) + + raise nvae + + elif LA74 == 74: + LA74_17 = self.input.LA(3) + + if (self.synpred141()) : + alt74 = 1 + elif (True) : + alt74 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("404:1: assignment_expression : ( lvalue assignment_operator assignment_expression | conditional_expression );", 74, 17, self.input) + + raise nvae + + elif LA74 == 65: + LA74_18 = self.input.LA(3) + + if (self.synpred141()) : + alt74 = 1 + elif (True) : + alt74 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("404:1: assignment_expression : ( lvalue assignment_operator assignment_expression | conditional_expression );", 74, 18, self.input) + + raise nvae + + elif LA74 == 75: + LA74_19 = self.input.LA(3) + + if (self.synpred141()) : + alt74 = 1 + elif (True) : + alt74 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("404:1: assignment_expression : ( lvalue assignment_operator assignment_expression | conditional_expression );", 74, 19, self.input) + + raise nvae + + elif LA74 == 71: + LA74_20 = self.input.LA(3) + + if (self.synpred141()) : + alt74 = 1 + elif (True) : + alt74 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("404:1: assignment_expression : ( lvalue assignment_operator assignment_expression | conditional_expression );", 74, 20, self.input) + + raise nvae + + elif LA74 == 72: + LA74_21 = self.input.LA(3) + + if (self.synpred141()) : + alt74 = 1 + elif (True) : + alt74 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("404:1: assignment_expression : ( lvalue assignment_operator assignment_expression | conditional_expression );", 74, 21, self.input) + + raise nvae + + elif LA74 == EOF or LA74 == 25 or LA74 == 27 or LA74 == 44 or LA74 == 47 or LA74 == 53 or LA74 == 62 or LA74 == 64 or LA74 == 67 or LA74 == 68 or LA74 == 69 or LA74 == 70 or LA74 == 76 or LA74 == 89 or LA74 == 90 or LA74 == 91 or LA74 == 92 or LA74 == 93 or LA74 == 94 or LA74 == 95 or LA74 == 96 or LA74 == 97 or LA74 == 98 or LA74 == 99 or LA74 == 100 or LA74 == 101: + alt74 = 2 + elif LA74 == 28 or LA74 == 79 or LA74 == 80 or LA74 == 81 or LA74 == 82 or LA74 == 83 or LA74 == 84 or LA74 == 85 or LA74 == 86 or LA74 == 87 or LA74 == 88: + alt74 = 1 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("404:1: assignment_expression : ( lvalue assignment_operator assignment_expression | conditional_expression );", 74, 1, self.input) + + raise nvae + + elif LA74 == HEX_LITERAL: + LA74 = self.input.LA(2) + if LA74 == 63: + LA74_44 = self.input.LA(3) + + if (self.synpred141()) : + alt74 = 1 + elif (True) : + alt74 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("404:1: assignment_expression : ( lvalue assignment_operator assignment_expression | conditional_expression );", 74, 44, self.input) + + raise nvae + + elif LA74 == 61: + LA74_45 = self.input.LA(3) + + if (self.synpred141()) : + alt74 = 1 + elif (True) : + alt74 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("404:1: assignment_expression : ( lvalue assignment_operator assignment_expression | conditional_expression );", 74, 45, self.input) + + raise nvae + + elif LA74 == 74: + LA74_46 = self.input.LA(3) + + if (self.synpred141()) : + alt74 = 1 + elif (True) : + alt74 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("404:1: assignment_expression : ( lvalue assignment_operator assignment_expression | conditional_expression );", 74, 46, self.input) + + raise nvae + + elif LA74 == 65: + LA74_47 = self.input.LA(3) + + if (self.synpred141()) : + alt74 = 1 + elif (True) : + alt74 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("404:1: assignment_expression : ( lvalue assignment_operator assignment_expression | conditional_expression );", 74, 47, self.input) + + raise nvae + + elif LA74 == 75: + LA74_48 = self.input.LA(3) + + if (self.synpred141()) : + alt74 = 1 + elif (True) : + alt74 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("404:1: assignment_expression : ( lvalue assignment_operator assignment_expression | conditional_expression );", 74, 48, self.input) + + raise nvae + + elif LA74 == 71: + LA74_49 = self.input.LA(3) + + if (self.synpred141()) : + alt74 = 1 + elif (True) : + alt74 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("404:1: assignment_expression : ( lvalue assignment_operator assignment_expression | conditional_expression );", 74, 49, self.input) + + raise nvae + + elif LA74 == 72: + LA74_50 = self.input.LA(3) + + if (self.synpred141()) : + alt74 = 1 + elif (True) : + alt74 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("404:1: assignment_expression : ( lvalue assignment_operator assignment_expression | conditional_expression );", 74, 50, self.input) + + raise nvae + + elif LA74 == 28 or LA74 == 79 or LA74 == 80 or LA74 == 81 or LA74 == 82 or LA74 == 83 or LA74 == 84 or LA74 == 85 or LA74 == 86 or LA74 == 87 or LA74 == 88: + alt74 = 1 + elif LA74 == EOF or LA74 == 25 or LA74 == 27 or LA74 == 44 or LA74 == 47 or LA74 == 53 or LA74 == 62 or LA74 == 64 or LA74 == 67 or LA74 == 68 or LA74 == 69 or LA74 == 70 or LA74 == 76 or LA74 == 89 or LA74 == 90 or LA74 == 91 or LA74 == 92 or LA74 == 93 or LA74 == 94 or LA74 == 95 or LA74 == 96 or LA74 == 97 or LA74 == 98 or LA74 == 99 or LA74 == 100 or LA74 == 101: + alt74 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("404:1: assignment_expression : ( lvalue assignment_operator assignment_expression | conditional_expression );", 74, 2, self.input) + + raise nvae + + elif LA74 == OCTAL_LITERAL: + LA74 = self.input.LA(2) + if LA74 == 63: + LA74_73 = self.input.LA(3) + + if (self.synpred141()) : + alt74 = 1 + elif (True) : + alt74 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("404:1: assignment_expression : ( lvalue assignment_operator assignment_expression | conditional_expression );", 74, 73, self.input) + + raise nvae + + elif LA74 == 61: + LA74_74 = self.input.LA(3) + + if (self.synpred141()) : + alt74 = 1 + elif (True) : + alt74 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("404:1: assignment_expression : ( lvalue assignment_operator assignment_expression | conditional_expression );", 74, 74, self.input) + + raise nvae + + elif LA74 == 74: + LA74_75 = self.input.LA(3) + + if (self.synpred141()) : + alt74 = 1 + elif (True) : + alt74 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("404:1: assignment_expression : ( lvalue assignment_operator assignment_expression | conditional_expression );", 74, 75, self.input) + + raise nvae + + elif LA74 == 65: + LA74_76 = self.input.LA(3) + + if (self.synpred141()) : + alt74 = 1 + elif (True) : + alt74 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("404:1: assignment_expression : ( lvalue assignment_operator assignment_expression | conditional_expression );", 74, 76, self.input) + + raise nvae + + elif LA74 == 75: + LA74_77 = self.input.LA(3) + + if (self.synpred141()) : + alt74 = 1 + elif (True) : + alt74 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("404:1: assignment_expression : ( lvalue assignment_operator assignment_expression | conditional_expression );", 74, 77, self.input) + + raise nvae + + elif LA74 == 71: + LA74_78 = self.input.LA(3) + + if (self.synpred141()) : + alt74 = 1 + elif (True) : + alt74 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("404:1: assignment_expression : ( lvalue assignment_operator assignment_expression | conditional_expression );", 74, 78, self.input) + + raise nvae + + elif LA74 == 72: + LA74_79 = self.input.LA(3) + + if (self.synpred141()) : + alt74 = 1 + elif (True) : + alt74 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("404:1: assignment_expression : ( lvalue assignment_operator assignment_expression | conditional_expression );", 74, 79, self.input) + + raise nvae + + elif LA74 == 28 or LA74 == 79 or LA74 == 80 or LA74 == 81 or LA74 == 82 or LA74 == 83 or LA74 == 84 or LA74 == 85 or LA74 == 86 or LA74 == 87 or LA74 == 88: + alt74 = 1 + elif LA74 == EOF or LA74 == 25 or LA74 == 27 or LA74 == 44 or LA74 == 47 or LA74 == 53 or LA74 == 62 or LA74 == 64 or LA74 == 67 or LA74 == 68 or LA74 == 69 or LA74 == 70 or LA74 == 76 or LA74 == 89 or LA74 == 90 or LA74 == 91 or LA74 == 92 or LA74 == 93 or LA74 == 94 or LA74 == 95 or LA74 == 96 or LA74 == 97 or LA74 == 98 or LA74 == 99 or LA74 == 100 or LA74 == 101: + alt74 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("404:1: assignment_expression : ( lvalue assignment_operator assignment_expression | conditional_expression );", 74, 3, self.input) + + raise nvae + + elif LA74 == DECIMAL_LITERAL: + LA74 = self.input.LA(2) + if LA74 == 63: + LA74_102 = self.input.LA(3) + + if (self.synpred141()) : + alt74 = 1 + elif (True) : + alt74 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("404:1: assignment_expression : ( lvalue assignment_operator assignment_expression | conditional_expression );", 74, 102, self.input) + + raise nvae + + elif LA74 == 61: + LA74_103 = self.input.LA(3) + + if (self.synpred141()) : + alt74 = 1 + elif (True) : + alt74 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("404:1: assignment_expression : ( lvalue assignment_operator assignment_expression | conditional_expression );", 74, 103, self.input) + + raise nvae + + elif LA74 == 74: + LA74_104 = self.input.LA(3) + + if (self.synpred141()) : + alt74 = 1 + elif (True) : + alt74 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("404:1: assignment_expression : ( lvalue assignment_operator assignment_expression | conditional_expression );", 74, 104, self.input) + + raise nvae + + elif LA74 == 65: + LA74_105 = self.input.LA(3) + + if (self.synpred141()) : + alt74 = 1 + elif (True) : + alt74 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("404:1: assignment_expression : ( lvalue assignment_operator assignment_expression | conditional_expression );", 74, 105, self.input) + + raise nvae + + elif LA74 == 75: + LA74_106 = self.input.LA(3) + + if (self.synpred141()) : + alt74 = 1 + elif (True) : + alt74 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("404:1: assignment_expression : ( lvalue assignment_operator assignment_expression | conditional_expression );", 74, 106, self.input) + + raise nvae + + elif LA74 == 71: + LA74_107 = self.input.LA(3) + + if (self.synpred141()) : + alt74 = 1 + elif (True) : + alt74 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("404:1: assignment_expression : ( lvalue assignment_operator assignment_expression | conditional_expression );", 74, 107, self.input) + + raise nvae + + elif LA74 == 72: + LA74_108 = self.input.LA(3) + + if (self.synpred141()) : + alt74 = 1 + elif (True) : + alt74 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("404:1: assignment_expression : ( lvalue assignment_operator assignment_expression | conditional_expression );", 74, 108, self.input) + + raise nvae + + elif LA74 == EOF or LA74 == 25 or LA74 == 27 or LA74 == 44 or LA74 == 47 or LA74 == 53 or LA74 == 62 or LA74 == 64 or LA74 == 67 or LA74 == 68 or LA74 == 69 or LA74 == 70 or LA74 == 76 or LA74 == 89 or LA74 == 90 or LA74 == 91 or LA74 == 92 or LA74 == 93 or LA74 == 94 or LA74 == 95 or LA74 == 96 or LA74 == 97 or LA74 == 98 or LA74 == 99 or LA74 == 100 or LA74 == 101: + alt74 = 2 + elif LA74 == 28 or LA74 == 79 or LA74 == 80 or LA74 == 81 or LA74 == 82 or LA74 == 83 or LA74 == 84 or LA74 == 85 or LA74 == 86 or LA74 == 87 or LA74 == 88: + alt74 = 1 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("404:1: assignment_expression : ( lvalue assignment_operator assignment_expression | conditional_expression );", 74, 4, self.input) + + raise nvae + + elif LA74 == CHARACTER_LITERAL: + LA74 = self.input.LA(2) + if LA74 == 63: + LA74_131 = self.input.LA(3) + + if (self.synpred141()) : + alt74 = 1 + elif (True) : + alt74 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("404:1: assignment_expression : ( lvalue assignment_operator assignment_expression | conditional_expression );", 74, 131, self.input) + + raise nvae + + elif LA74 == 61: + LA74_132 = self.input.LA(3) + + if (self.synpred141()) : + alt74 = 1 + elif (True) : + alt74 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("404:1: assignment_expression : ( lvalue assignment_operator assignment_expression | conditional_expression );", 74, 132, self.input) + + raise nvae + + elif LA74 == 74: + LA74_133 = self.input.LA(3) + + if (self.synpred141()) : + alt74 = 1 + elif (True) : + alt74 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("404:1: assignment_expression : ( lvalue assignment_operator assignment_expression | conditional_expression );", 74, 133, self.input) + + raise nvae + + elif LA74 == 65: + LA74_134 = self.input.LA(3) + + if (self.synpred141()) : + alt74 = 1 + elif (True) : + alt74 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("404:1: assignment_expression : ( lvalue assignment_operator assignment_expression | conditional_expression );", 74, 134, self.input) + + raise nvae + + elif LA74 == 75: + LA74_135 = self.input.LA(3) + + if (self.synpred141()) : + alt74 = 1 + elif (True) : + alt74 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("404:1: assignment_expression : ( lvalue assignment_operator assignment_expression | conditional_expression );", 74, 135, self.input) + + raise nvae + + elif LA74 == 71: + LA74_136 = self.input.LA(3) + + if (self.synpred141()) : + alt74 = 1 + elif (True) : + alt74 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("404:1: assignment_expression : ( lvalue assignment_operator assignment_expression | conditional_expression );", 74, 136, self.input) + + raise nvae + + elif LA74 == 72: + LA74_137 = self.input.LA(3) + + if (self.synpred141()) : + alt74 = 1 + elif (True) : + alt74 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("404:1: assignment_expression : ( lvalue assignment_operator assignment_expression | conditional_expression );", 74, 137, self.input) + + raise nvae + + elif LA74 == 28 or LA74 == 79 or LA74 == 80 or LA74 == 81 or LA74 == 82 or LA74 == 83 or LA74 == 84 or LA74 == 85 or LA74 == 86 or LA74 == 87 or LA74 == 88: + alt74 = 1 + elif LA74 == EOF or LA74 == 25 or LA74 == 27 or LA74 == 44 or LA74 == 47 or LA74 == 53 or LA74 == 62 or LA74 == 64 or LA74 == 67 or LA74 == 68 or LA74 == 69 or LA74 == 70 or LA74 == 76 or LA74 == 89 or LA74 == 90 or LA74 == 91 or LA74 == 92 or LA74 == 93 or LA74 == 94 or LA74 == 95 or LA74 == 96 or LA74 == 97 or LA74 == 98 or LA74 == 99 or LA74 == 100 or LA74 == 101: + alt74 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("404:1: assignment_expression : ( lvalue assignment_operator assignment_expression | conditional_expression );", 74, 5, self.input) + + raise nvae + + elif LA74 == STRING_LITERAL: + LA74 = self.input.LA(2) + if LA74 == IDENTIFIER: + LA74_160 = self.input.LA(3) + + if (self.synpred141()) : + alt74 = 1 + elif (True) : + alt74 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("404:1: assignment_expression : ( lvalue assignment_operator assignment_expression | conditional_expression );", 74, 160, self.input) + + raise nvae + + elif LA74 == 63: + LA74_161 = self.input.LA(3) + + if (self.synpred141()) : + alt74 = 1 + elif (True) : + alt74 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("404:1: assignment_expression : ( lvalue assignment_operator assignment_expression | conditional_expression );", 74, 161, self.input) + + raise nvae + + elif LA74 == 61: + LA74_162 = self.input.LA(3) + + if (self.synpred141()) : + alt74 = 1 + elif (True) : + alt74 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("404:1: assignment_expression : ( lvalue assignment_operator assignment_expression | conditional_expression );", 74, 162, self.input) + + raise nvae + + elif LA74 == 74: + LA74_163 = self.input.LA(3) + + if (self.synpred141()) : + alt74 = 1 + elif (True) : + alt74 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("404:1: assignment_expression : ( lvalue assignment_operator assignment_expression | conditional_expression );", 74, 163, self.input) + + raise nvae + + elif LA74 == 65: + LA74_164 = self.input.LA(3) + + if (self.synpred141()) : + alt74 = 1 + elif (True) : + alt74 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("404:1: assignment_expression : ( lvalue assignment_operator assignment_expression | conditional_expression );", 74, 164, self.input) + + raise nvae + + elif LA74 == 75: + LA74_165 = self.input.LA(3) + + if (self.synpred141()) : + alt74 = 1 + elif (True) : + alt74 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("404:1: assignment_expression : ( lvalue assignment_operator assignment_expression | conditional_expression );", 74, 165, self.input) + + raise nvae + + elif LA74 == 71: + LA74_166 = self.input.LA(3) + + if (self.synpred141()) : + alt74 = 1 + elif (True) : + alt74 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("404:1: assignment_expression : ( lvalue assignment_operator assignment_expression | conditional_expression );", 74, 166, self.input) + + raise nvae + + elif LA74 == 72: + LA74_167 = self.input.LA(3) + + if (self.synpred141()) : + alt74 = 1 + elif (True) : + alt74 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("404:1: assignment_expression : ( lvalue assignment_operator assignment_expression | conditional_expression );", 74, 167, self.input) + + raise nvae + + elif LA74 == 28 or LA74 == 79 or LA74 == 80 or LA74 == 81 or LA74 == 82 or LA74 == 83 or LA74 == 84 or LA74 == 85 or LA74 == 86 or LA74 == 87 or LA74 == 88: + alt74 = 1 + elif LA74 == STRING_LITERAL: + LA74_169 = self.input.LA(3) + + if (self.synpred141()) : + alt74 = 1 + elif (True) : + alt74 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("404:1: assignment_expression : ( lvalue assignment_operator assignment_expression | conditional_expression );", 74, 169, self.input) + + raise nvae + + elif LA74 == EOF or LA74 == 25 or LA74 == 27 or LA74 == 44 or LA74 == 47 or LA74 == 53 or LA74 == 62 or LA74 == 64 or LA74 == 67 or LA74 == 68 or LA74 == 69 or LA74 == 70 or LA74 == 76 or LA74 == 89 or LA74 == 90 or LA74 == 91 or LA74 == 92 or LA74 == 93 or LA74 == 94 or LA74 == 95 or LA74 == 96 or LA74 == 97 or LA74 == 98 or LA74 == 99 or LA74 == 100 or LA74 == 101: + alt74 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("404:1: assignment_expression : ( lvalue assignment_operator assignment_expression | conditional_expression );", 74, 6, self.input) + + raise nvae + + elif LA74 == FLOATING_POINT_LITERAL: + LA74 = self.input.LA(2) + if LA74 == 63: + LA74_191 = self.input.LA(3) + + if (self.synpred141()) : + alt74 = 1 + elif (True) : + alt74 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("404:1: assignment_expression : ( lvalue assignment_operator assignment_expression | conditional_expression );", 74, 191, self.input) + + raise nvae + + elif LA74 == 61: + LA74_192 = self.input.LA(3) + + if (self.synpred141()) : + alt74 = 1 + elif (True) : + alt74 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("404:1: assignment_expression : ( lvalue assignment_operator assignment_expression | conditional_expression );", 74, 192, self.input) + + raise nvae + + elif LA74 == 74: + LA74_193 = self.input.LA(3) + + if (self.synpred141()) : + alt74 = 1 + elif (True) : + alt74 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("404:1: assignment_expression : ( lvalue assignment_operator assignment_expression | conditional_expression );", 74, 193, self.input) + + raise nvae + + elif LA74 == 65: + LA74_194 = self.input.LA(3) + + if (self.synpred141()) : + alt74 = 1 + elif (True) : + alt74 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("404:1: assignment_expression : ( lvalue assignment_operator assignment_expression | conditional_expression );", 74, 194, self.input) + + raise nvae + + elif LA74 == 75: + LA74_195 = self.input.LA(3) + + if (self.synpred141()) : + alt74 = 1 + elif (True) : + alt74 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("404:1: assignment_expression : ( lvalue assignment_operator assignment_expression | conditional_expression );", 74, 195, self.input) + + raise nvae + + elif LA74 == 71: + LA74_196 = self.input.LA(3) + + if (self.synpred141()) : + alt74 = 1 + elif (True) : + alt74 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("404:1: assignment_expression : ( lvalue assignment_operator assignment_expression | conditional_expression );", 74, 196, self.input) + + raise nvae + + elif LA74 == 72: + LA74_197 = self.input.LA(3) + + if (self.synpred141()) : + alt74 = 1 + elif (True) : + alt74 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("404:1: assignment_expression : ( lvalue assignment_operator assignment_expression | conditional_expression );", 74, 197, self.input) + + raise nvae + + elif LA74 == EOF or LA74 == 25 or LA74 == 27 or LA74 == 44 or LA74 == 47 or LA74 == 53 or LA74 == 62 or LA74 == 64 or LA74 == 67 or LA74 == 68 or LA74 == 69 or LA74 == 70 or LA74 == 76 or LA74 == 89 or LA74 == 90 or LA74 == 91 or LA74 == 92 or LA74 == 93 or LA74 == 94 or LA74 == 95 or LA74 == 96 or LA74 == 97 or LA74 == 98 or LA74 == 99 or LA74 == 100 or LA74 == 101: + alt74 = 2 + elif LA74 == 28 or LA74 == 79 or LA74 == 80 or LA74 == 81 or LA74 == 82 or LA74 == 83 or LA74 == 84 or LA74 == 85 or LA74 == 86 or LA74 == 87 or LA74 == 88: + alt74 = 1 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("404:1: assignment_expression : ( lvalue assignment_operator assignment_expression | conditional_expression );", 74, 7, self.input) + + raise nvae + + elif LA74 == 61: + LA74 = self.input.LA(2) + if LA74 == IDENTIFIER: + LA74_220 = self.input.LA(3) + + if (self.synpred141()) : + alt74 = 1 + elif (True) : + alt74 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("404:1: assignment_expression : ( lvalue assignment_operator assignment_expression | conditional_expression );", 74, 220, self.input) + + raise nvae + + elif LA74 == HEX_LITERAL: + LA74_221 = self.input.LA(3) + + if (self.synpred141()) : + alt74 = 1 + elif (True) : + alt74 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("404:1: assignment_expression : ( lvalue assignment_operator assignment_expression | conditional_expression );", 74, 221, self.input) + + raise nvae + + elif LA74 == OCTAL_LITERAL: + LA74_222 = self.input.LA(3) + + if (self.synpred141()) : + alt74 = 1 + elif (True) : + alt74 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("404:1: assignment_expression : ( lvalue assignment_operator assignment_expression | conditional_expression );", 74, 222, self.input) + + raise nvae + + elif LA74 == DECIMAL_LITERAL: + LA74_223 = self.input.LA(3) + + if (self.synpred141()) : + alt74 = 1 + elif (True) : + alt74 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("404:1: assignment_expression : ( lvalue assignment_operator assignment_expression | conditional_expression );", 74, 223, self.input) + + raise nvae + + elif LA74 == CHARACTER_LITERAL: + LA74_224 = self.input.LA(3) + + if (self.synpred141()) : + alt74 = 1 + elif (True) : + alt74 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("404:1: assignment_expression : ( lvalue assignment_operator assignment_expression | conditional_expression );", 74, 224, self.input) + + raise nvae + + elif LA74 == STRING_LITERAL: + LA74_225 = self.input.LA(3) + + if (self.synpred141()) : + alt74 = 1 + elif (True) : + alt74 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("404:1: assignment_expression : ( lvalue assignment_operator assignment_expression | conditional_expression );", 74, 225, self.input) + + raise nvae + + elif LA74 == FLOATING_POINT_LITERAL: + LA74_226 = self.input.LA(3) + + if (self.synpred141()) : + alt74 = 1 + elif (True) : + alt74 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("404:1: assignment_expression : ( lvalue assignment_operator assignment_expression | conditional_expression );", 74, 226, self.input) + + raise nvae + + elif LA74 == 61: + LA74_227 = self.input.LA(3) + + if (self.synpred141()) : + alt74 = 1 + elif (True) : + alt74 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("404:1: assignment_expression : ( lvalue assignment_operator assignment_expression | conditional_expression );", 74, 227, self.input) + + raise nvae + + elif LA74 == 71: + LA74_228 = self.input.LA(3) + + if (self.synpred141()) : + alt74 = 1 + elif (True) : + alt74 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("404:1: assignment_expression : ( lvalue assignment_operator assignment_expression | conditional_expression );", 74, 228, self.input) + + raise nvae + + elif LA74 == 72: + LA74_229 = self.input.LA(3) + + if (self.synpred141()) : + alt74 = 1 + elif (True) : + alt74 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("404:1: assignment_expression : ( lvalue assignment_operator assignment_expression | conditional_expression );", 74, 229, self.input) + + raise nvae + + elif LA74 == 65 or LA74 == 67 or LA74 == 68 or LA74 == 76 or LA74 == 77 or LA74 == 78: + LA74_230 = self.input.LA(3) + + if (self.synpred141()) : + alt74 = 1 + elif (True) : + alt74 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("404:1: assignment_expression : ( lvalue assignment_operator assignment_expression | conditional_expression );", 74, 230, self.input) + + raise nvae + + elif LA74 == 73: + LA74_231 = self.input.LA(3) + + if (self.synpred141()) : + alt74 = 1 + elif (True) : + alt74 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("404:1: assignment_expression : ( lvalue assignment_operator assignment_expression | conditional_expression );", 74, 231, self.input) + + raise nvae + + elif LA74 == 34 or LA74 == 35 or LA74 == 36 or LA74 == 37 or LA74 == 38 or LA74 == 39 or LA74 == 40 or LA74 == 41 or LA74 == 42 or LA74 == 45 or LA74 == 46 or LA74 == 48 or LA74 == 49 or LA74 == 50 or LA74 == 51 or LA74 == 52 or LA74 == 53 or LA74 == 54 or LA74 == 55 or LA74 == 56 or LA74 == 57 or LA74 == 58 or LA74 == 59 or LA74 == 60: + alt74 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("404:1: assignment_expression : ( lvalue assignment_operator assignment_expression | conditional_expression );", 74, 8, self.input) + + raise nvae + + elif LA74 == 71: + LA74 = self.input.LA(2) + if LA74 == IDENTIFIER: + LA74_244 = self.input.LA(3) + + if (self.synpred141()) : + alt74 = 1 + elif (True) : + alt74 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("404:1: assignment_expression : ( lvalue assignment_operator assignment_expression | conditional_expression );", 74, 244, self.input) + + raise nvae + + elif LA74 == HEX_LITERAL: + LA74_245 = self.input.LA(3) + + if (self.synpred141()) : + alt74 = 1 + elif (True) : + alt74 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("404:1: assignment_expression : ( lvalue assignment_operator assignment_expression | conditional_expression );", 74, 245, self.input) + + raise nvae + + elif LA74 == OCTAL_LITERAL: + LA74_246 = self.input.LA(3) + + if (self.synpred141()) : + alt74 = 1 + elif (True) : + alt74 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("404:1: assignment_expression : ( lvalue assignment_operator assignment_expression | conditional_expression );", 74, 246, self.input) + + raise nvae + + elif LA74 == DECIMAL_LITERAL: + LA74_247 = self.input.LA(3) + + if (self.synpred141()) : + alt74 = 1 + elif (True) : + alt74 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("404:1: assignment_expression : ( lvalue assignment_operator assignment_expression | conditional_expression );", 74, 247, self.input) + + raise nvae + + elif LA74 == CHARACTER_LITERAL: + LA74_248 = self.input.LA(3) + + if (self.synpred141()) : + alt74 = 1 + elif (True) : + alt74 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("404:1: assignment_expression : ( lvalue assignment_operator assignment_expression | conditional_expression );", 74, 248, self.input) + + raise nvae + + elif LA74 == STRING_LITERAL: + LA74_249 = self.input.LA(3) + + if (self.synpred141()) : + alt74 = 1 + elif (True) : + alt74 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("404:1: assignment_expression : ( lvalue assignment_operator assignment_expression | conditional_expression );", 74, 249, self.input) + + raise nvae + + elif LA74 == FLOATING_POINT_LITERAL: + LA74_250 = self.input.LA(3) + + if (self.synpred141()) : + alt74 = 1 + elif (True) : + alt74 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("404:1: assignment_expression : ( lvalue assignment_operator assignment_expression | conditional_expression );", 74, 250, self.input) + + raise nvae + + elif LA74 == 61: + LA74_251 = self.input.LA(3) + + if (self.synpred141()) : + alt74 = 1 + elif (True) : + alt74 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("404:1: assignment_expression : ( lvalue assignment_operator assignment_expression | conditional_expression );", 74, 251, self.input) + + raise nvae + + elif LA74 == 71: + LA74_252 = self.input.LA(3) + + if (self.synpred141()) : + alt74 = 1 + elif (True) : + alt74 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("404:1: assignment_expression : ( lvalue assignment_operator assignment_expression | conditional_expression );", 74, 252, self.input) + + raise nvae + + elif LA74 == 72: + LA74_253 = self.input.LA(3) + + if (self.synpred141()) : + alt74 = 1 + elif (True) : + alt74 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("404:1: assignment_expression : ( lvalue assignment_operator assignment_expression | conditional_expression );", 74, 253, self.input) + + raise nvae + + elif LA74 == 65 or LA74 == 67 or LA74 == 68 or LA74 == 76 or LA74 == 77 or LA74 == 78: + LA74_254 = self.input.LA(3) + + if (self.synpred141()) : + alt74 = 1 + elif (True) : + alt74 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("404:1: assignment_expression : ( lvalue assignment_operator assignment_expression | conditional_expression );", 74, 254, self.input) + + raise nvae + + elif LA74 == 73: + LA74_255 = self.input.LA(3) + + if (self.synpred141()) : + alt74 = 1 + elif (True) : + alt74 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("404:1: assignment_expression : ( lvalue assignment_operator assignment_expression | conditional_expression );", 74, 255, self.input) + + raise nvae + + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("404:1: assignment_expression : ( lvalue assignment_operator assignment_expression | conditional_expression );", 74, 9, self.input) + + raise nvae + + elif LA74 == 72: + LA74 = self.input.LA(2) + if LA74 == IDENTIFIER: + LA74_256 = self.input.LA(3) + + if (self.synpred141()) : + alt74 = 1 + elif (True) : + alt74 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("404:1: assignment_expression : ( lvalue assignment_operator assignment_expression | conditional_expression );", 74, 256, self.input) + + raise nvae + + elif LA74 == HEX_LITERAL: + LA74_257 = self.input.LA(3) + + if (self.synpred141()) : + alt74 = 1 + elif (True) : + alt74 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("404:1: assignment_expression : ( lvalue assignment_operator assignment_expression | conditional_expression );", 74, 257, self.input) + + raise nvae + + elif LA74 == OCTAL_LITERAL: + LA74_258 = self.input.LA(3) + + if (self.synpred141()) : + alt74 = 1 + elif (True) : + alt74 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("404:1: assignment_expression : ( lvalue assignment_operator assignment_expression | conditional_expression );", 74, 258, self.input) + + raise nvae + + elif LA74 == DECIMAL_LITERAL: + LA74_259 = self.input.LA(3) + + if (self.synpred141()) : + alt74 = 1 + elif (True) : + alt74 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("404:1: assignment_expression : ( lvalue assignment_operator assignment_expression | conditional_expression );", 74, 259, self.input) + + raise nvae + + elif LA74 == CHARACTER_LITERAL: + LA74_260 = self.input.LA(3) + + if (self.synpred141()) : + alt74 = 1 + elif (True) : + alt74 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("404:1: assignment_expression : ( lvalue assignment_operator assignment_expression | conditional_expression );", 74, 260, self.input) + + raise nvae + + elif LA74 == STRING_LITERAL: + LA74_261 = self.input.LA(3) + + if (self.synpred141()) : + alt74 = 1 + elif (True) : + alt74 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("404:1: assignment_expression : ( lvalue assignment_operator assignment_expression | conditional_expression );", 74, 261, self.input) + + raise nvae + + elif LA74 == FLOATING_POINT_LITERAL: + LA74_262 = self.input.LA(3) + + if (self.synpred141()) : + alt74 = 1 + elif (True) : + alt74 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("404:1: assignment_expression : ( lvalue assignment_operator assignment_expression | conditional_expression );", 74, 262, self.input) + + raise nvae + + elif LA74 == 61: + LA74_263 = self.input.LA(3) + + if (self.synpred141()) : + alt74 = 1 + elif (True) : + alt74 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("404:1: assignment_expression : ( lvalue assignment_operator assignment_expression | conditional_expression );", 74, 263, self.input) + + raise nvae + + elif LA74 == 71: + LA74_264 = self.input.LA(3) + + if (self.synpred141()) : + alt74 = 1 + elif (True) : + alt74 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("404:1: assignment_expression : ( lvalue assignment_operator assignment_expression | conditional_expression );", 74, 264, self.input) + + raise nvae + + elif LA74 == 72: + LA74_265 = self.input.LA(3) + + if (self.synpred141()) : + alt74 = 1 + elif (True) : + alt74 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("404:1: assignment_expression : ( lvalue assignment_operator assignment_expression | conditional_expression );", 74, 265, self.input) + + raise nvae + + elif LA74 == 65 or LA74 == 67 or LA74 == 68 or LA74 == 76 or LA74 == 77 or LA74 == 78: + LA74_266 = self.input.LA(3) + + if (self.synpred141()) : + alt74 = 1 + elif (True) : + alt74 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("404:1: assignment_expression : ( lvalue assignment_operator assignment_expression | conditional_expression );", 74, 266, self.input) + + raise nvae + + elif LA74 == 73: + LA74_267 = self.input.LA(3) + + if (self.synpred141()) : + alt74 = 1 + elif (True) : + alt74 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("404:1: assignment_expression : ( lvalue assignment_operator assignment_expression | conditional_expression );", 74, 267, self.input) + + raise nvae + + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("404:1: assignment_expression : ( lvalue assignment_operator assignment_expression | conditional_expression );", 74, 10, self.input) + + raise nvae + + elif LA74 == 65 or LA74 == 67 or LA74 == 68 or LA74 == 76 or LA74 == 77 or LA74 == 78: + LA74 = self.input.LA(2) + if LA74 == 61: + LA74_268 = self.input.LA(3) + + if (self.synpred141()) : + alt74 = 1 + elif (True) : + alt74 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("404:1: assignment_expression : ( lvalue assignment_operator assignment_expression | conditional_expression );", 74, 268, self.input) + + raise nvae + + elif LA74 == IDENTIFIER: + LA74_269 = self.input.LA(3) + + if (self.synpred141()) : + alt74 = 1 + elif (True) : + alt74 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("404:1: assignment_expression : ( lvalue assignment_operator assignment_expression | conditional_expression );", 74, 269, self.input) + + raise nvae + + elif LA74 == HEX_LITERAL: + LA74_270 = self.input.LA(3) + + if (self.synpred141()) : + alt74 = 1 + elif (True) : + alt74 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("404:1: assignment_expression : ( lvalue assignment_operator assignment_expression | conditional_expression );", 74, 270, self.input) + + raise nvae + + elif LA74 == OCTAL_LITERAL: + LA74_271 = self.input.LA(3) + + if (self.synpred141()) : + alt74 = 1 + elif (True) : + alt74 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("404:1: assignment_expression : ( lvalue assignment_operator assignment_expression | conditional_expression );", 74, 271, self.input) + + raise nvae + + elif LA74 == DECIMAL_LITERAL: + LA74_272 = self.input.LA(3) + + if (self.synpred141()) : + alt74 = 1 + elif (True) : + alt74 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("404:1: assignment_expression : ( lvalue assignment_operator assignment_expression | conditional_expression );", 74, 272, self.input) + + raise nvae + + elif LA74 == CHARACTER_LITERAL: + LA74_273 = self.input.LA(3) + + if (self.synpred141()) : + alt74 = 1 + elif (True) : + alt74 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("404:1: assignment_expression : ( lvalue assignment_operator assignment_expression | conditional_expression );", 74, 273, self.input) + + raise nvae + + elif LA74 == STRING_LITERAL: + LA74_274 = self.input.LA(3) + + if (self.synpred141()) : + alt74 = 1 + elif (True) : + alt74 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("404:1: assignment_expression : ( lvalue assignment_operator assignment_expression | conditional_expression );", 74, 274, self.input) + + raise nvae + + elif LA74 == FLOATING_POINT_LITERAL: + LA74_275 = self.input.LA(3) + + if (self.synpred141()) : + alt74 = 1 + elif (True) : + alt74 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("404:1: assignment_expression : ( lvalue assignment_operator assignment_expression | conditional_expression );", 74, 275, self.input) + + raise nvae + + elif LA74 == 71: + LA74_276 = self.input.LA(3) + + if (self.synpred141()) : + alt74 = 1 + elif (True) : + alt74 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("404:1: assignment_expression : ( lvalue assignment_operator assignment_expression | conditional_expression );", 74, 276, self.input) + + raise nvae + + elif LA74 == 72: + LA74_277 = self.input.LA(3) + + if (self.synpred141()) : + alt74 = 1 + elif (True) : + alt74 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("404:1: assignment_expression : ( lvalue assignment_operator assignment_expression | conditional_expression );", 74, 277, self.input) + + raise nvae + + elif LA74 == 65 or LA74 == 67 or LA74 == 68 or LA74 == 76 or LA74 == 77 or LA74 == 78: + LA74_278 = self.input.LA(3) + + if (self.synpred141()) : + alt74 = 1 + elif (True) : + alt74 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("404:1: assignment_expression : ( lvalue assignment_operator assignment_expression | conditional_expression );", 74, 278, self.input) + + raise nvae + + elif LA74 == 73: + LA74_279 = self.input.LA(3) + + if (self.synpred141()) : + alt74 = 1 + elif (True) : + alt74 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("404:1: assignment_expression : ( lvalue assignment_operator assignment_expression | conditional_expression );", 74, 279, self.input) + + raise nvae + + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("404:1: assignment_expression : ( lvalue assignment_operator assignment_expression | conditional_expression );", 74, 11, self.input) + + raise nvae + + elif LA74 == 73: + LA74 = self.input.LA(2) + if LA74 == 61: + LA74_280 = self.input.LA(3) + + if (self.synpred141()) : + alt74 = 1 + elif (True) : + alt74 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("404:1: assignment_expression : ( lvalue assignment_operator assignment_expression | conditional_expression );", 74, 280, self.input) + + raise nvae + + elif LA74 == IDENTIFIER: + LA74_281 = self.input.LA(3) + + if (self.synpred141()) : + alt74 = 1 + elif (True) : + alt74 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("404:1: assignment_expression : ( lvalue assignment_operator assignment_expression | conditional_expression );", 74, 281, self.input) + + raise nvae + + elif LA74 == HEX_LITERAL: + LA74_282 = self.input.LA(3) + + if (self.synpred141()) : + alt74 = 1 + elif (True) : + alt74 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("404:1: assignment_expression : ( lvalue assignment_operator assignment_expression | conditional_expression );", 74, 282, self.input) + + raise nvae + + elif LA74 == OCTAL_LITERAL: + LA74_283 = self.input.LA(3) + + if (self.synpred141()) : + alt74 = 1 + elif (True) : + alt74 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("404:1: assignment_expression : ( lvalue assignment_operator assignment_expression | conditional_expression );", 74, 283, self.input) + + raise nvae + + elif LA74 == DECIMAL_LITERAL: + LA74_284 = self.input.LA(3) + + if (self.synpred141()) : + alt74 = 1 + elif (True) : + alt74 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("404:1: assignment_expression : ( lvalue assignment_operator assignment_expression | conditional_expression );", 74, 284, self.input) + + raise nvae + + elif LA74 == CHARACTER_LITERAL: + LA74_285 = self.input.LA(3) + + if (self.synpred141()) : + alt74 = 1 + elif (True) : + alt74 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("404:1: assignment_expression : ( lvalue assignment_operator assignment_expression | conditional_expression );", 74, 285, self.input) + + raise nvae + + elif LA74 == STRING_LITERAL: + LA74_286 = self.input.LA(3) + + if (self.synpred141()) : + alt74 = 1 + elif (True) : + alt74 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("404:1: assignment_expression : ( lvalue assignment_operator assignment_expression | conditional_expression );", 74, 286, self.input) + + raise nvae + + elif LA74 == FLOATING_POINT_LITERAL: + LA74_287 = self.input.LA(3) + + if (self.synpred141()) : + alt74 = 1 + elif (True) : + alt74 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("404:1: assignment_expression : ( lvalue assignment_operator assignment_expression | conditional_expression );", 74, 287, self.input) + + raise nvae + + elif LA74 == 71: + LA74_288 = self.input.LA(3) + + if (self.synpred141()) : + alt74 = 1 + elif (True) : + alt74 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("404:1: assignment_expression : ( lvalue assignment_operator assignment_expression | conditional_expression );", 74, 288, self.input) + + raise nvae + + elif LA74 == 72: + LA74_289 = self.input.LA(3) + + if (self.synpred141()) : + alt74 = 1 + elif (True) : + alt74 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("404:1: assignment_expression : ( lvalue assignment_operator assignment_expression | conditional_expression );", 74, 289, self.input) + + raise nvae + + elif LA74 == 65 or LA74 == 67 or LA74 == 68 or LA74 == 76 or LA74 == 77 or LA74 == 78: + LA74_290 = self.input.LA(3) + + if (self.synpred141()) : + alt74 = 1 + elif (True) : + alt74 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("404:1: assignment_expression : ( lvalue assignment_operator assignment_expression | conditional_expression );", 74, 290, self.input) + + raise nvae + + elif LA74 == 73: + LA74_291 = self.input.LA(3) + + if (self.synpred141()) : + alt74 = 1 + elif (True) : + alt74 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("404:1: assignment_expression : ( lvalue assignment_operator assignment_expression | conditional_expression );", 74, 291, self.input) + + raise nvae + + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("404:1: assignment_expression : ( lvalue assignment_operator assignment_expression | conditional_expression );", 74, 12, self.input) + + raise nvae + + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("404:1: assignment_expression : ( lvalue assignment_operator assignment_expression | conditional_expression );", 74, 0, self.input) + + raise nvae + + if alt74 == 1: + # C.g:405:4: lvalue assignment_operator assignment_expression + self.following.append(self.FOLLOW_lvalue_in_assignment_expression1729) + self.lvalue() + self.following.pop() + if self.failed: + return + self.following.append(self.FOLLOW_assignment_operator_in_assignment_expression1731) + self.assignment_operator() + self.following.pop() + if self.failed: + return + self.following.append(self.FOLLOW_assignment_expression_in_assignment_expression1733) + self.assignment_expression() + self.following.pop() + if self.failed: + return + + + elif alt74 == 2: + # C.g:406:4: conditional_expression + self.following.append(self.FOLLOW_conditional_expression_in_assignment_expression1738) + self.conditional_expression() + self.following.pop() + if self.failed: + return + + + + except RecognitionException, re: + self.reportError(re) + self.recover(self.input, re) + finally: + if self.backtracking > 0: + self.memoize(self.input, 48, assignment_expression_StartIndex) + + pass + + return + + # $ANTLR end assignment_expression + + + # $ANTLR start lvalue + # C.g:409:1: lvalue : unary_expression ; + def lvalue(self, ): + + lvalue_StartIndex = self.input.index() + try: + try: + if self.backtracking > 0 and self.alreadyParsedRule(self.input, 49): + return + + # C.g:410:2: ( unary_expression ) + # C.g:410:4: unary_expression + self.following.append(self.FOLLOW_unary_expression_in_lvalue1750) + self.unary_expression() + self.following.pop() + if self.failed: + return + + + + + except RecognitionException, re: + self.reportError(re) + self.recover(self.input, re) + finally: + if self.backtracking > 0: + self.memoize(self.input, 49, lvalue_StartIndex) + + pass + + return + + # $ANTLR end lvalue + + + # $ANTLR start assignment_operator + # C.g:413:1: assignment_operator : ( '=' | '*=' | '/=' | '%=' | '+=' | '-=' | '<<=' | '>>=' | '&=' | '^=' | '|=' ); + def assignment_operator(self, ): + + assignment_operator_StartIndex = self.input.index() + try: + try: + if self.backtracking > 0 and self.alreadyParsedRule(self.input, 50): + return + + # C.g:414:2: ( '=' | '*=' | '/=' | '%=' | '+=' | '-=' | '<<=' | '>>=' | '&=' | '^=' | '|=' ) + # C.g: + if self.input.LA(1) == 28 or (79 <= self.input.LA(1) <= 88): + self.input.consume(); + self.errorRecovery = False + self.failed = False + + else: + if self.backtracking > 0: + self.failed = True + return + + mse = MismatchedSetException(None, self.input) + self.recoverFromMismatchedSet( + self.input, mse, self.FOLLOW_set_in_assignment_operator0 + ) + raise mse + + + + + + + except RecognitionException, re: + self.reportError(re) + self.recover(self.input, re) + finally: + if self.backtracking > 0: + self.memoize(self.input, 50, assignment_operator_StartIndex) + + pass + + return + + # $ANTLR end assignment_operator + + + # $ANTLR start conditional_expression + # C.g:427:1: conditional_expression : e= logical_or_expression ( '?' expression ':' conditional_expression )? ; + def conditional_expression(self, ): + + conditional_expression_StartIndex = self.input.index() + e = None + + + try: + try: + if self.backtracking > 0 and self.alreadyParsedRule(self.input, 51): + return + + # C.g:428:2: (e= logical_or_expression ( '?' expression ':' conditional_expression )? ) + # C.g:428:4: e= logical_or_expression ( '?' expression ':' conditional_expression )? + self.following.append(self.FOLLOW_logical_or_expression_in_conditional_expression1824) + e = self.logical_or_expression() + self.following.pop() + if self.failed: + return + # C.g:428:28: ( '?' expression ':' conditional_expression )? + alt75 = 2 + LA75_0 = self.input.LA(1) + + if (LA75_0 == 89) : + alt75 = 1 + if alt75 == 1: + # C.g:428:29: '?' expression ':' conditional_expression + self.match(self.input, 89, self.FOLLOW_89_in_conditional_expression1827) + if self.failed: + return + self.following.append(self.FOLLOW_expression_in_conditional_expression1829) + self.expression() + self.following.pop() + if self.failed: + return + self.match(self.input, 47, self.FOLLOW_47_in_conditional_expression1831) + if self.failed: + return + self.following.append(self.FOLLOW_conditional_expression_in_conditional_expression1833) + self.conditional_expression() + self.following.pop() + if self.failed: + return + if self.backtracking == 0: + self.StorePredicateExpression(e.start.line, e.start.charPositionInLine, e.stop.line, e.stop.charPositionInLine, self.input.toString(e.start,e.stop)) + + + + + + + + + except RecognitionException, re: + self.reportError(re) + self.recover(self.input, re) + finally: + if self.backtracking > 0: + self.memoize(self.input, 51, conditional_expression_StartIndex) + + pass + + return + + # $ANTLR end conditional_expression + + class logical_or_expression_return(object): + def __init__(self): + self.start = None + self.stop = None + + + + # $ANTLR start logical_or_expression + # C.g:431:1: logical_or_expression : logical_and_expression ( '||' logical_and_expression )* ; + def logical_or_expression(self, ): + + retval = self.logical_or_expression_return() + retval.start = self.input.LT(1) + logical_or_expression_StartIndex = self.input.index() + try: + try: + if self.backtracking > 0 and self.alreadyParsedRule(self.input, 52): + return retval + + # C.g:432:2: ( logical_and_expression ( '||' logical_and_expression )* ) + # C.g:432:4: logical_and_expression ( '||' logical_and_expression )* + self.following.append(self.FOLLOW_logical_and_expression_in_logical_or_expression1848) + self.logical_and_expression() + self.following.pop() + if self.failed: + return retval + # C.g:432:27: ( '||' logical_and_expression )* + while True: #loop76 + alt76 = 2 + LA76_0 = self.input.LA(1) + + if (LA76_0 == 90) : + alt76 = 1 + + + if alt76 == 1: + # C.g:432:28: '||' logical_and_expression + self.match(self.input, 90, self.FOLLOW_90_in_logical_or_expression1851) + if self.failed: + return retval + self.following.append(self.FOLLOW_logical_and_expression_in_logical_or_expression1853) + self.logical_and_expression() + self.following.pop() + if self.failed: + return retval + + + else: + break #loop76 + + + + + + retval.stop = self.input.LT(-1) + + + except RecognitionException, re: + self.reportError(re) + self.recover(self.input, re) + finally: + if self.backtracking > 0: + self.memoize(self.input, 52, logical_or_expression_StartIndex) + + pass + + return retval + + # $ANTLR end logical_or_expression + + + # $ANTLR start logical_and_expression + # C.g:435:1: logical_and_expression : inclusive_or_expression ( '&&' inclusive_or_expression )* ; + def logical_and_expression(self, ): + + logical_and_expression_StartIndex = self.input.index() + try: + try: + if self.backtracking > 0 and self.alreadyParsedRule(self.input, 53): + return + + # C.g:436:2: ( inclusive_or_expression ( '&&' inclusive_or_expression )* ) + # C.g:436:4: inclusive_or_expression ( '&&' inclusive_or_expression )* + self.following.append(self.FOLLOW_inclusive_or_expression_in_logical_and_expression1866) + self.inclusive_or_expression() + self.following.pop() + if self.failed: + return + # C.g:436:28: ( '&&' inclusive_or_expression )* + while True: #loop77 + alt77 = 2 + LA77_0 = self.input.LA(1) + + if (LA77_0 == 91) : + alt77 = 1 + + + if alt77 == 1: + # C.g:436:29: '&&' inclusive_or_expression + self.match(self.input, 91, self.FOLLOW_91_in_logical_and_expression1869) + if self.failed: + return + self.following.append(self.FOLLOW_inclusive_or_expression_in_logical_and_expression1871) + self.inclusive_or_expression() + self.following.pop() + if self.failed: + return + + + else: + break #loop77 + + + + + + + except RecognitionException, re: + self.reportError(re) + self.recover(self.input, re) + finally: + if self.backtracking > 0: + self.memoize(self.input, 53, logical_and_expression_StartIndex) + + pass + + return + + # $ANTLR end logical_and_expression + + + # $ANTLR start inclusive_or_expression + # C.g:439:1: inclusive_or_expression : exclusive_or_expression ( '|' exclusive_or_expression )* ; + def inclusive_or_expression(self, ): + + inclusive_or_expression_StartIndex = self.input.index() + try: + try: + if self.backtracking > 0 and self.alreadyParsedRule(self.input, 54): + return + + # C.g:440:2: ( exclusive_or_expression ( '|' exclusive_or_expression )* ) + # C.g:440:4: exclusive_or_expression ( '|' exclusive_or_expression )* + self.following.append(self.FOLLOW_exclusive_or_expression_in_inclusive_or_expression1884) + self.exclusive_or_expression() + self.following.pop() + if self.failed: + return + # C.g:440:28: ( '|' exclusive_or_expression )* + while True: #loop78 + alt78 = 2 + LA78_0 = self.input.LA(1) + + if (LA78_0 == 92) : + alt78 = 1 + + + if alt78 == 1: + # C.g:440:29: '|' exclusive_or_expression + self.match(self.input, 92, self.FOLLOW_92_in_inclusive_or_expression1887) + if self.failed: + return + self.following.append(self.FOLLOW_exclusive_or_expression_in_inclusive_or_expression1889) + self.exclusive_or_expression() + self.following.pop() + if self.failed: + return + + + else: + break #loop78 + + + + + + + except RecognitionException, re: + self.reportError(re) + self.recover(self.input, re) + finally: + if self.backtracking > 0: + self.memoize(self.input, 54, inclusive_or_expression_StartIndex) + + pass + + return + + # $ANTLR end inclusive_or_expression + + + # $ANTLR start exclusive_or_expression + # C.g:443:1: exclusive_or_expression : and_expression ( '^' and_expression )* ; + def exclusive_or_expression(self, ): + + exclusive_or_expression_StartIndex = self.input.index() + try: + try: + if self.backtracking > 0 and self.alreadyParsedRule(self.input, 55): + return + + # C.g:444:2: ( and_expression ( '^' and_expression )* ) + # C.g:444:4: and_expression ( '^' and_expression )* + self.following.append(self.FOLLOW_and_expression_in_exclusive_or_expression1902) + self.and_expression() + self.following.pop() + if self.failed: + return + # C.g:444:19: ( '^' and_expression )* + while True: #loop79 + alt79 = 2 + LA79_0 = self.input.LA(1) + + if (LA79_0 == 93) : + alt79 = 1 + + + if alt79 == 1: + # C.g:444:20: '^' and_expression + self.match(self.input, 93, self.FOLLOW_93_in_exclusive_or_expression1905) + if self.failed: + return + self.following.append(self.FOLLOW_and_expression_in_exclusive_or_expression1907) + self.and_expression() + self.following.pop() + if self.failed: + return + + + else: + break #loop79 + + + + + + + except RecognitionException, re: + self.reportError(re) + self.recover(self.input, re) + finally: + if self.backtracking > 0: + self.memoize(self.input, 55, exclusive_or_expression_StartIndex) + + pass + + return + + # $ANTLR end exclusive_or_expression + + + # $ANTLR start and_expression + # C.g:447:1: and_expression : equality_expression ( '&' equality_expression )* ; + def and_expression(self, ): + + and_expression_StartIndex = self.input.index() + try: + try: + if self.backtracking > 0 and self.alreadyParsedRule(self.input, 56): + return + + # C.g:448:2: ( equality_expression ( '&' equality_expression )* ) + # C.g:448:4: equality_expression ( '&' equality_expression )* + self.following.append(self.FOLLOW_equality_expression_in_and_expression1920) + self.equality_expression() + self.following.pop() + if self.failed: + return + # C.g:448:24: ( '&' equality_expression )* + while True: #loop80 + alt80 = 2 + LA80_0 = self.input.LA(1) + + if (LA80_0 == 76) : + alt80 = 1 + + + if alt80 == 1: + # C.g:448:25: '&' equality_expression + self.match(self.input, 76, self.FOLLOW_76_in_and_expression1923) + if self.failed: + return + self.following.append(self.FOLLOW_equality_expression_in_and_expression1925) + self.equality_expression() + self.following.pop() + if self.failed: + return + + + else: + break #loop80 + + + + + + + except RecognitionException, re: + self.reportError(re) + self.recover(self.input, re) + finally: + if self.backtracking > 0: + self.memoize(self.input, 56, and_expression_StartIndex) + + pass + + return + + # $ANTLR end and_expression + + + # $ANTLR start equality_expression + # C.g:450:1: equality_expression : relational_expression ( ( '==' | '!=' ) relational_expression )* ; + def equality_expression(self, ): + + equality_expression_StartIndex = self.input.index() + try: + try: + if self.backtracking > 0 and self.alreadyParsedRule(self.input, 57): + return + + # C.g:451:2: ( relational_expression ( ( '==' | '!=' ) relational_expression )* ) + # C.g:451:4: relational_expression ( ( '==' | '!=' ) relational_expression )* + self.following.append(self.FOLLOW_relational_expression_in_equality_expression1937) + self.relational_expression() + self.following.pop() + if self.failed: + return + # C.g:451:26: ( ( '==' | '!=' ) relational_expression )* + while True: #loop81 + alt81 = 2 + LA81_0 = self.input.LA(1) + + if ((94 <= LA81_0 <= 95)) : + alt81 = 1 + + + if alt81 == 1: + # C.g:451:27: ( '==' | '!=' ) relational_expression + if (94 <= self.input.LA(1) <= 95): + self.input.consume(); + self.errorRecovery = False + self.failed = False + + else: + if self.backtracking > 0: + self.failed = True + return + + mse = MismatchedSetException(None, self.input) + self.recoverFromMismatchedSet( + self.input, mse, self.FOLLOW_set_in_equality_expression1940 + ) + raise mse + + + self.following.append(self.FOLLOW_relational_expression_in_equality_expression1946) + self.relational_expression() + self.following.pop() + if self.failed: + return + + + else: + break #loop81 + + + + + + + except RecognitionException, re: + self.reportError(re) + self.recover(self.input, re) + finally: + if self.backtracking > 0: + self.memoize(self.input, 57, equality_expression_StartIndex) + + pass + + return + + # $ANTLR end equality_expression + + + # $ANTLR start relational_expression + # C.g:454:1: relational_expression : shift_expression ( ( '<' | '>' | '<=' | '>=' ) shift_expression )* ; + def relational_expression(self, ): + + relational_expression_StartIndex = self.input.index() + try: + try: + if self.backtracking > 0 and self.alreadyParsedRule(self.input, 58): + return + + # C.g:455:2: ( shift_expression ( ( '<' | '>' | '<=' | '>=' ) shift_expression )* ) + # C.g:455:4: shift_expression ( ( '<' | '>' | '<=' | '>=' ) shift_expression )* + self.following.append(self.FOLLOW_shift_expression_in_relational_expression1960) + self.shift_expression() + self.following.pop() + if self.failed: + return + # C.g:455:21: ( ( '<' | '>' | '<=' | '>=' ) shift_expression )* + while True: #loop82 + alt82 = 2 + LA82_0 = self.input.LA(1) + + if ((96 <= LA82_0 <= 99)) : + alt82 = 1 + + + if alt82 == 1: + # C.g:455:22: ( '<' | '>' | '<=' | '>=' ) shift_expression + if (96 <= self.input.LA(1) <= 99): + self.input.consume(); + self.errorRecovery = False + self.failed = False + + else: + if self.backtracking > 0: + self.failed = True + return + + mse = MismatchedSetException(None, self.input) + self.recoverFromMismatchedSet( + self.input, mse, self.FOLLOW_set_in_relational_expression1963 + ) + raise mse + + + self.following.append(self.FOLLOW_shift_expression_in_relational_expression1973) + self.shift_expression() + self.following.pop() + if self.failed: + return + + + else: + break #loop82 + + + + + + + except RecognitionException, re: + self.reportError(re) + self.recover(self.input, re) + finally: + if self.backtracking > 0: + self.memoize(self.input, 58, relational_expression_StartIndex) + + pass + + return + + # $ANTLR end relational_expression + + + # $ANTLR start shift_expression + # C.g:458:1: shift_expression : additive_expression ( ( '<<' | '>>' ) additive_expression )* ; + def shift_expression(self, ): + + shift_expression_StartIndex = self.input.index() + try: + try: + if self.backtracking > 0 and self.alreadyParsedRule(self.input, 59): + return + + # C.g:459:2: ( additive_expression ( ( '<<' | '>>' ) additive_expression )* ) + # C.g:459:4: additive_expression ( ( '<<' | '>>' ) additive_expression )* + self.following.append(self.FOLLOW_additive_expression_in_shift_expression1986) + self.additive_expression() + self.following.pop() + if self.failed: + return + # C.g:459:24: ( ( '<<' | '>>' ) additive_expression )* + while True: #loop83 + alt83 = 2 + LA83_0 = self.input.LA(1) + + if ((100 <= LA83_0 <= 101)) : + alt83 = 1 + + + if alt83 == 1: + # C.g:459:25: ( '<<' | '>>' ) additive_expression + if (100 <= self.input.LA(1) <= 101): + self.input.consume(); + self.errorRecovery = False + self.failed = False + + else: + if self.backtracking > 0: + self.failed = True + return + + mse = MismatchedSetException(None, self.input) + self.recoverFromMismatchedSet( + self.input, mse, self.FOLLOW_set_in_shift_expression1989 + ) + raise mse + + + self.following.append(self.FOLLOW_additive_expression_in_shift_expression1995) + self.additive_expression() + self.following.pop() + if self.failed: + return + + + else: + break #loop83 + + + + + + + except RecognitionException, re: + self.reportError(re) + self.recover(self.input, re) + finally: + if self.backtracking > 0: + self.memoize(self.input, 59, shift_expression_StartIndex) + + pass + + return + + # $ANTLR end shift_expression + + + # $ANTLR start statement + # C.g:464:1: statement : ( labeled_statement | compound_statement | expression_statement | selection_statement | iteration_statement | jump_statement | macro_statement | asm2_statement | asm1_statement | asm_statement | declaration ); + def statement(self, ): + + statement_StartIndex = self.input.index() + try: + try: + if self.backtracking > 0 and self.alreadyParsedRule(self.input, 60): + return + + # C.g:465:2: ( labeled_statement | compound_statement | expression_statement | selection_statement | iteration_statement | jump_statement | macro_statement | asm2_statement | asm1_statement | asm_statement | declaration ) + alt84 = 11 + LA84 = self.input.LA(1) + if LA84 == IDENTIFIER: + LA84 = self.input.LA(2) + if LA84 == 47: + alt84 = 1 + elif LA84 == 61: + LA84_44 = self.input.LA(3) + + if (self.synpred168()) : + alt84 = 3 + elif (self.synpred172()) : + alt84 = 7 + elif (self.synpred173()) : + alt84 = 8 + elif (True) : + alt84 = 11 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("464:1: statement : ( labeled_statement | compound_statement | expression_statement | selection_statement | iteration_statement | jump_statement | macro_statement | asm2_statement | asm1_statement | asm_statement | declaration );", 84, 44, self.input) + + raise nvae + + elif LA84 == STRING_LITERAL or LA84 == 27 or LA84 == 28 or LA84 == 63 or LA84 == 67 or LA84 == 68 or LA84 == 69 or LA84 == 70 or LA84 == 71 or LA84 == 72 or LA84 == 74 or LA84 == 75 or LA84 == 76 or LA84 == 79 or LA84 == 80 or LA84 == 81 or LA84 == 82 or LA84 == 83 or LA84 == 84 or LA84 == 85 or LA84 == 86 or LA84 == 87 or LA84 == 88 or LA84 == 89 or LA84 == 90 or LA84 == 91 or LA84 == 92 or LA84 == 93 or LA84 == 94 or LA84 == 95 or LA84 == 96 or LA84 == 97 or LA84 == 98 or LA84 == 99 or LA84 == 100 or LA84 == 101: + alt84 = 3 + elif LA84 == 65: + LA84_47 = self.input.LA(3) + + if (self.synpred168()) : + alt84 = 3 + elif (True) : + alt84 = 11 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("464:1: statement : ( labeled_statement | compound_statement | expression_statement | selection_statement | iteration_statement | jump_statement | macro_statement | asm2_statement | asm1_statement | asm_statement | declaration );", 84, 47, self.input) + + raise nvae + + elif LA84 == 25: + LA84_65 = self.input.LA(3) + + if (self.synpred168()) : + alt84 = 3 + elif (True) : + alt84 = 11 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("464:1: statement : ( labeled_statement | compound_statement | expression_statement | selection_statement | iteration_statement | jump_statement | macro_statement | asm2_statement | asm1_statement | asm_statement | declaration );", 84, 65, self.input) + + raise nvae + + elif LA84 == IDENTIFIER: + LA84_67 = self.input.LA(3) + + if (self.synpred168()) : + alt84 = 3 + elif (True) : + alt84 = 11 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("464:1: statement : ( labeled_statement | compound_statement | expression_statement | selection_statement | iteration_statement | jump_statement | macro_statement | asm2_statement | asm1_statement | asm_statement | declaration );", 84, 67, self.input) + + raise nvae + + elif LA84 == 29 or LA84 == 30 or LA84 == 31 or LA84 == 32 or LA84 == 33 or LA84 == 34 or LA84 == 35 or LA84 == 36 or LA84 == 37 or LA84 == 38 or LA84 == 39 or LA84 == 40 or LA84 == 41 or LA84 == 42 or LA84 == 45 or LA84 == 46 or LA84 == 48 or LA84 == 49 or LA84 == 50 or LA84 == 51 or LA84 == 52 or LA84 == 53 or LA84 == 54 or LA84 == 55 or LA84 == 56 or LA84 == 57 or LA84 == 58 or LA84 == 59 or LA84 == 60: + alt84 = 11 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("464:1: statement : ( labeled_statement | compound_statement | expression_statement | selection_statement | iteration_statement | jump_statement | macro_statement | asm2_statement | asm1_statement | asm_statement | declaration );", 84, 1, self.input) + + raise nvae + + elif LA84 == 105 or LA84 == 106: + alt84 = 1 + elif LA84 == 43: + alt84 = 2 + elif LA84 == HEX_LITERAL or LA84 == OCTAL_LITERAL or LA84 == DECIMAL_LITERAL or LA84 == CHARACTER_LITERAL or LA84 == STRING_LITERAL or LA84 == FLOATING_POINT_LITERAL or LA84 == 25 or LA84 == 61 or LA84 == 65 or LA84 == 67 or LA84 == 68 or LA84 == 71 or LA84 == 72 or LA84 == 73 or LA84 == 76 or LA84 == 77 or LA84 == 78: + alt84 = 3 + elif LA84 == 107 or LA84 == 109: + alt84 = 4 + elif LA84 == 110 or LA84 == 111 or LA84 == 112: + alt84 = 5 + elif LA84 == 113 or LA84 == 114 or LA84 == 115 or LA84 == 116: + alt84 = 6 + elif LA84 == 102: + alt84 = 8 + elif LA84 == 103: + alt84 = 9 + elif LA84 == 104: + alt84 = 10 + elif LA84 == 26 or LA84 == 29 or LA84 == 30 or LA84 == 31 or LA84 == 32 or LA84 == 33 or LA84 == 34 or LA84 == 35 or LA84 == 36 or LA84 == 37 or LA84 == 38 or LA84 == 39 or LA84 == 40 or LA84 == 41 or LA84 == 42 or LA84 == 45 or LA84 == 46 or LA84 == 48 or LA84 == 49 or LA84 == 50 or LA84 == 51 or LA84 == 52 or LA84 == 53 or LA84 == 54 or LA84 == 55 or LA84 == 56 or LA84 == 57 or LA84 == 58 or LA84 == 59 or LA84 == 60: + alt84 = 11 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("464:1: statement : ( labeled_statement | compound_statement | expression_statement | selection_statement | iteration_statement | jump_statement | macro_statement | asm2_statement | asm1_statement | asm_statement | declaration );", 84, 0, self.input) + + raise nvae + + if alt84 == 1: + # C.g:465:4: labeled_statement + self.following.append(self.FOLLOW_labeled_statement_in_statement2010) + self.labeled_statement() + self.following.pop() + if self.failed: + return + + + elif alt84 == 2: + # C.g:466:4: compound_statement + self.following.append(self.FOLLOW_compound_statement_in_statement2015) + self.compound_statement() + self.following.pop() + if self.failed: + return + + + elif alt84 == 3: + # C.g:467:4: expression_statement + self.following.append(self.FOLLOW_expression_statement_in_statement2020) + self.expression_statement() + self.following.pop() + if self.failed: + return + + + elif alt84 == 4: + # C.g:468:4: selection_statement + self.following.append(self.FOLLOW_selection_statement_in_statement2025) + self.selection_statement() + self.following.pop() + if self.failed: + return + + + elif alt84 == 5: + # C.g:469:4: iteration_statement + self.following.append(self.FOLLOW_iteration_statement_in_statement2030) + self.iteration_statement() + self.following.pop() + if self.failed: + return + + + elif alt84 == 6: + # C.g:470:4: jump_statement + self.following.append(self.FOLLOW_jump_statement_in_statement2035) + self.jump_statement() + self.following.pop() + if self.failed: + return + + + elif alt84 == 7: + # C.g:471:4: macro_statement + self.following.append(self.FOLLOW_macro_statement_in_statement2040) + self.macro_statement() + self.following.pop() + if self.failed: + return + + + elif alt84 == 8: + # C.g:472:4: asm2_statement + self.following.append(self.FOLLOW_asm2_statement_in_statement2045) + self.asm2_statement() + self.following.pop() + if self.failed: + return + + + elif alt84 == 9: + # C.g:473:4: asm1_statement + self.following.append(self.FOLLOW_asm1_statement_in_statement2050) + self.asm1_statement() + self.following.pop() + if self.failed: + return + + + elif alt84 == 10: + # C.g:474:4: asm_statement + self.following.append(self.FOLLOW_asm_statement_in_statement2055) + self.asm_statement() + self.following.pop() + if self.failed: + return + + + elif alt84 == 11: + # C.g:475:4: declaration + self.following.append(self.FOLLOW_declaration_in_statement2060) + self.declaration() + self.following.pop() + if self.failed: + return + + + + except RecognitionException, re: + self.reportError(re) + self.recover(self.input, re) + finally: + if self.backtracking > 0: + self.memoize(self.input, 60, statement_StartIndex) + + pass + + return + + # $ANTLR end statement + + + # $ANTLR start asm2_statement + # C.g:478:1: asm2_statement : ( '__asm__' )? IDENTIFIER '(' (~ ( ';' ) )* ')' ';' ; + def asm2_statement(self, ): + + asm2_statement_StartIndex = self.input.index() + try: + try: + if self.backtracking > 0 and self.alreadyParsedRule(self.input, 61): + return + + # C.g:479:2: ( ( '__asm__' )? IDENTIFIER '(' (~ ( ';' ) )* ')' ';' ) + # C.g:479:4: ( '__asm__' )? IDENTIFIER '(' (~ ( ';' ) )* ')' ';' + # C.g:479:4: ( '__asm__' )? + alt85 = 2 + LA85_0 = self.input.LA(1) + + if (LA85_0 == 102) : + alt85 = 1 + if alt85 == 1: + # C.g:0:0: '__asm__' + self.match(self.input, 102, self.FOLLOW_102_in_asm2_statement2071) + if self.failed: + return + + + + self.match(self.input, IDENTIFIER, self.FOLLOW_IDENTIFIER_in_asm2_statement2074) + if self.failed: + return + self.match(self.input, 61, self.FOLLOW_61_in_asm2_statement2076) + if self.failed: + return + # C.g:479:30: (~ ( ';' ) )* + while True: #loop86 + alt86 = 2 + LA86_0 = self.input.LA(1) + + if (LA86_0 == 62) : + LA86_1 = self.input.LA(2) + + if ((IDENTIFIER <= LA86_1 <= LINE_COMMAND) or (26 <= LA86_1 <= 116)) : + alt86 = 1 + + + elif ((IDENTIFIER <= LA86_0 <= LINE_COMMAND) or (26 <= LA86_0 <= 61) or (63 <= LA86_0 <= 116)) : + alt86 = 1 + + + if alt86 == 1: + # C.g:479:31: ~ ( ';' ) + if (IDENTIFIER <= self.input.LA(1) <= LINE_COMMAND) or (26 <= self.input.LA(1) <= 116): + self.input.consume(); + self.errorRecovery = False + self.failed = False + + else: + if self.backtracking > 0: + self.failed = True + return + + mse = MismatchedSetException(None, self.input) + self.recoverFromMismatchedSet( + self.input, mse, self.FOLLOW_set_in_asm2_statement2079 + ) + raise mse + + + + + else: + break #loop86 + + + self.match(self.input, 62, self.FOLLOW_62_in_asm2_statement2086) + if self.failed: + return + self.match(self.input, 25, self.FOLLOW_25_in_asm2_statement2088) + if self.failed: + return + + + + + except RecognitionException, re: + self.reportError(re) + self.recover(self.input, re) + finally: + if self.backtracking > 0: + self.memoize(self.input, 61, asm2_statement_StartIndex) + + pass + + return + + # $ANTLR end asm2_statement + + + # $ANTLR start asm1_statement + # C.g:482:1: asm1_statement : '_asm' '{' (~ ( '}' ) )* '}' ; + def asm1_statement(self, ): + + asm1_statement_StartIndex = self.input.index() + try: + try: + if self.backtracking > 0 and self.alreadyParsedRule(self.input, 62): + return + + # C.g:483:2: ( '_asm' '{' (~ ( '}' ) )* '}' ) + # C.g:483:4: '_asm' '{' (~ ( '}' ) )* '}' + self.match(self.input, 103, self.FOLLOW_103_in_asm1_statement2100) + if self.failed: + return + self.match(self.input, 43, self.FOLLOW_43_in_asm1_statement2102) + if self.failed: + return + # C.g:483:15: (~ ( '}' ) )* + while True: #loop87 + alt87 = 2 + LA87_0 = self.input.LA(1) + + if ((IDENTIFIER <= LA87_0 <= 43) or (45 <= LA87_0 <= 116)) : + alt87 = 1 + + + if alt87 == 1: + # C.g:483:16: ~ ( '}' ) + if (IDENTIFIER <= self.input.LA(1) <= 43) or (45 <= self.input.LA(1) <= 116): + self.input.consume(); + self.errorRecovery = False + self.failed = False + + else: + if self.backtracking > 0: + self.failed = True + return + + mse = MismatchedSetException(None, self.input) + self.recoverFromMismatchedSet( + self.input, mse, self.FOLLOW_set_in_asm1_statement2105 + ) + raise mse + + + + + else: + break #loop87 + + + self.match(self.input, 44, self.FOLLOW_44_in_asm1_statement2112) + if self.failed: + return + + + + + except RecognitionException, re: + self.reportError(re) + self.recover(self.input, re) + finally: + if self.backtracking > 0: + self.memoize(self.input, 62, asm1_statement_StartIndex) + + pass + + return + + # $ANTLR end asm1_statement + + + # $ANTLR start asm_statement + # C.g:486:1: asm_statement : '__asm' '{' (~ ( '}' ) )* '}' ; + def asm_statement(self, ): + + asm_statement_StartIndex = self.input.index() + try: + try: + if self.backtracking > 0 and self.alreadyParsedRule(self.input, 63): + return + + # C.g:487:2: ( '__asm' '{' (~ ( '}' ) )* '}' ) + # C.g:487:4: '__asm' '{' (~ ( '}' ) )* '}' + self.match(self.input, 104, self.FOLLOW_104_in_asm_statement2123) + if self.failed: + return + self.match(self.input, 43, self.FOLLOW_43_in_asm_statement2125) + if self.failed: + return + # C.g:487:16: (~ ( '}' ) )* + while True: #loop88 + alt88 = 2 + LA88_0 = self.input.LA(1) + + if ((IDENTIFIER <= LA88_0 <= 43) or (45 <= LA88_0 <= 116)) : + alt88 = 1 + + + if alt88 == 1: + # C.g:487:17: ~ ( '}' ) + if (IDENTIFIER <= self.input.LA(1) <= 43) or (45 <= self.input.LA(1) <= 116): + self.input.consume(); + self.errorRecovery = False + self.failed = False + + else: + if self.backtracking > 0: + self.failed = True + return + + mse = MismatchedSetException(None, self.input) + self.recoverFromMismatchedSet( + self.input, mse, self.FOLLOW_set_in_asm_statement2128 + ) + raise mse + + + + + else: + break #loop88 + + + self.match(self.input, 44, self.FOLLOW_44_in_asm_statement2135) + if self.failed: + return + + + + + except RecognitionException, re: + self.reportError(re) + self.recover(self.input, re) + finally: + if self.backtracking > 0: + self.memoize(self.input, 63, asm_statement_StartIndex) + + pass + + return + + # $ANTLR end asm_statement + + + # $ANTLR start macro_statement + # C.g:490:1: macro_statement : IDENTIFIER '(' ( declaration )* ( statement_list )? ( expression )? ')' ; + def macro_statement(self, ): + + macro_statement_StartIndex = self.input.index() + try: + try: + if self.backtracking > 0 and self.alreadyParsedRule(self.input, 64): + return + + # C.g:491:2: ( IDENTIFIER '(' ( declaration )* ( statement_list )? ( expression )? ')' ) + # C.g:491:4: IDENTIFIER '(' ( declaration )* ( statement_list )? ( expression )? ')' + self.match(self.input, IDENTIFIER, self.FOLLOW_IDENTIFIER_in_macro_statement2147) + if self.failed: + return + self.match(self.input, 61, self.FOLLOW_61_in_macro_statement2149) + if self.failed: + return + # C.g:491:19: ( declaration )* + while True: #loop89 + alt89 = 2 + LA89 = self.input.LA(1) + if LA89 == IDENTIFIER: + LA89 = self.input.LA(2) + if LA89 == 61: + LA89_45 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 65: + LA89_48 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 25: + LA89_66 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == IDENTIFIER: + LA89_69 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 58: + LA89_70 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 59: + LA89_71 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 60: + LA89_72 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 29 or LA89 == 30 or LA89 == 31 or LA89 == 32 or LA89 == 33: + LA89_73 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 34: + LA89_74 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 35: + LA89_75 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 36: + LA89_76 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 37: + LA89_77 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 38: + LA89_78 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 39: + LA89_79 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 40: + LA89_80 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 41: + LA89_81 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 42: + LA89_82 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 45 or LA89 == 46: + LA89_83 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 48: + LA89_84 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 49 or LA89 == 50 or LA89 == 51 or LA89 == 52 or LA89 == 53 or LA89 == 54 or LA89 == 55 or LA89 == 56 or LA89 == 57: + LA89_85 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + + elif LA89 == 26: + LA89 = self.input.LA(2) + if LA89 == 29 or LA89 == 30 or LA89 == 31 or LA89 == 32 or LA89 == 33: + LA89_87 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 34: + LA89_88 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 35: + LA89_89 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 36: + LA89_90 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 37: + LA89_91 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 38: + LA89_92 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 39: + LA89_93 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 40: + LA89_94 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 41: + LA89_95 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 42: + LA89_96 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 45 or LA89 == 46: + LA89_97 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 48: + LA89_98 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == IDENTIFIER: + LA89_99 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 58: + LA89_100 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 65: + LA89_101 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 59: + LA89_102 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 60: + LA89_103 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 49 or LA89 == 50 or LA89 == 51 or LA89 == 52 or LA89 == 53 or LA89 == 54 or LA89 == 55 or LA89 == 56 or LA89 == 57: + LA89_104 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 61: + LA89_105 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + + elif LA89 == 29 or LA89 == 30 or LA89 == 31 or LA89 == 32 or LA89 == 33: + LA89 = self.input.LA(2) + if LA89 == 65: + LA89_106 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 58: + LA89_107 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 59: + LA89_108 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 60: + LA89_109 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == IDENTIFIER: + LA89_110 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 61: + LA89_111 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 25: + LA89_112 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 29 or LA89 == 30 or LA89 == 31 or LA89 == 32 or LA89 == 33: + LA89_113 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 34: + LA89_114 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 35: + LA89_115 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 36: + LA89_116 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 37: + LA89_117 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 38: + LA89_118 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 39: + LA89_119 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 40: + LA89_120 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 41: + LA89_121 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 42: + LA89_122 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 45 or LA89 == 46: + LA89_123 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 48: + LA89_124 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 49 or LA89 == 50 or LA89 == 51 or LA89 == 52 or LA89 == 53 or LA89 == 54 or LA89 == 55 or LA89 == 56 or LA89 == 57: + LA89_125 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + + elif LA89 == 34: + LA89 = self.input.LA(2) + if LA89 == 65: + LA89_126 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 58: + LA89_127 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 59: + LA89_128 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 60: + LA89_129 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == IDENTIFIER: + LA89_130 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 61: + LA89_131 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 25: + LA89_132 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 29 or LA89 == 30 or LA89 == 31 or LA89 == 32 or LA89 == 33: + LA89_133 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 34: + LA89_134 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 35: + LA89_135 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 36: + LA89_136 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 37: + LA89_137 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 38: + LA89_138 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 39: + LA89_139 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 40: + LA89_140 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 41: + LA89_141 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 42: + LA89_142 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 45 or LA89 == 46: + LA89_143 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 48: + LA89_144 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 49 or LA89 == 50 or LA89 == 51 or LA89 == 52 or LA89 == 53 or LA89 == 54 or LA89 == 55 or LA89 == 56 or LA89 == 57: + LA89_145 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + + elif LA89 == 35: + LA89 = self.input.LA(2) + if LA89 == 65: + LA89_146 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 58: + LA89_147 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 59: + LA89_148 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 60: + LA89_149 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == IDENTIFIER: + LA89_150 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 61: + LA89_151 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 25: + LA89_152 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 29 or LA89 == 30 or LA89 == 31 or LA89 == 32 or LA89 == 33: + LA89_153 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 34: + LA89_154 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 35: + LA89_155 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 36: + LA89_156 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 37: + LA89_157 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 38: + LA89_158 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 39: + LA89_159 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 40: + LA89_160 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 41: + LA89_161 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 42: + LA89_162 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 45 or LA89 == 46: + LA89_163 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 48: + LA89_164 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 49 or LA89 == 50 or LA89 == 51 or LA89 == 52 or LA89 == 53 or LA89 == 54 or LA89 == 55 or LA89 == 56 or LA89 == 57: + LA89_165 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + + elif LA89 == 36: + LA89 = self.input.LA(2) + if LA89 == 65: + LA89_166 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 58: + LA89_167 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 59: + LA89_168 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 60: + LA89_169 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == IDENTIFIER: + LA89_170 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 61: + LA89_171 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 25: + LA89_172 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 29 or LA89 == 30 or LA89 == 31 or LA89 == 32 or LA89 == 33: + LA89_173 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 34: + LA89_174 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 35: + LA89_175 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 36: + LA89_176 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 37: + LA89_177 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 38: + LA89_178 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 39: + LA89_179 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 40: + LA89_180 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 41: + LA89_181 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 42: + LA89_182 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 45 or LA89 == 46: + LA89_183 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 48: + LA89_184 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 49 or LA89 == 50 or LA89 == 51 or LA89 == 52 or LA89 == 53 or LA89 == 54 or LA89 == 55 or LA89 == 56 or LA89 == 57: + LA89_185 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + + elif LA89 == 37: + LA89 = self.input.LA(2) + if LA89 == 65: + LA89_186 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 58: + LA89_187 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 59: + LA89_188 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 60: + LA89_189 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == IDENTIFIER: + LA89_190 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 61: + LA89_191 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 25: + LA89_192 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 29 or LA89 == 30 or LA89 == 31 or LA89 == 32 or LA89 == 33: + LA89_193 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 34: + LA89_194 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 35: + LA89_195 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 36: + LA89_196 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 37: + LA89_197 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 38: + LA89_198 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 39: + LA89_199 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 40: + LA89_200 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 41: + LA89_201 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 42: + LA89_202 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 45 or LA89 == 46: + LA89_203 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 48: + LA89_204 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 49 or LA89 == 50 or LA89 == 51 or LA89 == 52 or LA89 == 53 or LA89 == 54 or LA89 == 55 or LA89 == 56 or LA89 == 57: + LA89_205 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + + elif LA89 == 38: + LA89 = self.input.LA(2) + if LA89 == 65: + LA89_206 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 58: + LA89_207 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 59: + LA89_208 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 60: + LA89_209 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == IDENTIFIER: + LA89_210 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 61: + LA89_211 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 25: + LA89_212 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 29 or LA89 == 30 or LA89 == 31 or LA89 == 32 or LA89 == 33: + LA89_213 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 34: + LA89_214 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 35: + LA89_215 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 36: + LA89_216 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 37: + LA89_217 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 38: + LA89_218 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 39: + LA89_219 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 40: + LA89_220 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 41: + LA89_221 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 42: + LA89_222 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 45 or LA89 == 46: + LA89_223 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 48: + LA89_224 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 49 or LA89 == 50 or LA89 == 51 or LA89 == 52 or LA89 == 53 or LA89 == 54 or LA89 == 55 or LA89 == 56 or LA89 == 57: + LA89_225 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + + elif LA89 == 39: + LA89 = self.input.LA(2) + if LA89 == 65: + LA89_226 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 58: + LA89_227 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 59: + LA89_228 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 60: + LA89_229 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == IDENTIFIER: + LA89_230 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 61: + LA89_231 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 25: + LA89_232 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 29 or LA89 == 30 or LA89 == 31 or LA89 == 32 or LA89 == 33: + LA89_233 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 34: + LA89_234 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 35: + LA89_235 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 36: + LA89_236 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 37: + LA89_237 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 38: + LA89_238 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 39: + LA89_239 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 40: + LA89_240 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 41: + LA89_241 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 42: + LA89_242 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 45 or LA89 == 46: + LA89_243 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 48: + LA89_244 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 49 or LA89 == 50 or LA89 == 51 or LA89 == 52 or LA89 == 53 or LA89 == 54 or LA89 == 55 or LA89 == 56 or LA89 == 57: + LA89_245 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + + elif LA89 == 40: + LA89 = self.input.LA(2) + if LA89 == 65: + LA89_246 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 58: + LA89_247 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 59: + LA89_248 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 60: + LA89_249 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == IDENTIFIER: + LA89_250 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 61: + LA89_251 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 25: + LA89_252 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 29 or LA89 == 30 or LA89 == 31 or LA89 == 32 or LA89 == 33: + LA89_253 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 34: + LA89_254 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 35: + LA89_255 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 36: + LA89_256 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 37: + LA89_257 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 38: + LA89_258 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 39: + LA89_259 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 40: + LA89_260 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 41: + LA89_261 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 42: + LA89_262 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 45 or LA89 == 46: + LA89_263 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 48: + LA89_264 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 49 or LA89 == 50 or LA89 == 51 or LA89 == 52 or LA89 == 53 or LA89 == 54 or LA89 == 55 or LA89 == 56 or LA89 == 57: + LA89_265 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + + elif LA89 == 41: + LA89 = self.input.LA(2) + if LA89 == 65: + LA89_266 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 58: + LA89_267 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 59: + LA89_268 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 60: + LA89_269 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == IDENTIFIER: + LA89_270 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 61: + LA89_271 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 25: + LA89_272 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 29 or LA89 == 30 or LA89 == 31 or LA89 == 32 or LA89 == 33: + LA89_273 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 34: + LA89_274 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 35: + LA89_275 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 36: + LA89_276 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 37: + LA89_277 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 38: + LA89_278 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 39: + LA89_279 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 40: + LA89_280 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 41: + LA89_281 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 42: + LA89_282 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 45 or LA89 == 46: + LA89_283 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 48: + LA89_284 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 49 or LA89 == 50 or LA89 == 51 or LA89 == 52 or LA89 == 53 or LA89 == 54 or LA89 == 55 or LA89 == 56 or LA89 == 57: + LA89_285 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + + elif LA89 == 42: + LA89 = self.input.LA(2) + if LA89 == 65: + LA89_286 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 58: + LA89_287 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 59: + LA89_288 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 60: + LA89_289 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == IDENTIFIER: + LA89_290 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 61: + LA89_291 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 25: + LA89_292 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 29 or LA89 == 30 or LA89 == 31 or LA89 == 32 or LA89 == 33: + LA89_293 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 34: + LA89_294 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 35: + LA89_295 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 36: + LA89_296 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 37: + LA89_297 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 38: + LA89_298 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 39: + LA89_299 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 40: + LA89_300 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 41: + LA89_301 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 42: + LA89_302 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 45 or LA89 == 46: + LA89_303 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 48: + LA89_304 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 49 or LA89 == 50 or LA89 == 51 or LA89 == 52 or LA89 == 53 or LA89 == 54 or LA89 == 55 or LA89 == 56 or LA89 == 57: + LA89_305 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + + elif LA89 == 45 or LA89 == 46: + LA89_40 = self.input.LA(2) + + if (LA89_40 == IDENTIFIER) : + LA89_306 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif (LA89_40 == 43) : + LA89_307 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + + + elif LA89 == 48: + LA89_41 = self.input.LA(2) + + if (LA89_41 == IDENTIFIER) : + LA89_308 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif (LA89_41 == 43) : + LA89_309 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + + + elif LA89 == 49 or LA89 == 50 or LA89 == 51 or LA89 == 52 or LA89 == 53 or LA89 == 54 or LA89 == 55 or LA89 == 56 or LA89 == 57 or LA89 == 58 or LA89 == 59 or LA89 == 60: + LA89 = self.input.LA(2) + if LA89 == 65: + LA89_310 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 58: + LA89_311 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 59: + LA89_312 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 60: + LA89_313 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == IDENTIFIER: + LA89_314 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 61: + LA89_315 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 25: + LA89_316 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 29 or LA89 == 30 or LA89 == 31 or LA89 == 32 or LA89 == 33: + LA89_317 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 34: + LA89_318 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 35: + LA89_319 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 36: + LA89_320 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 37: + LA89_321 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 38: + LA89_322 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 39: + LA89_323 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 40: + LA89_324 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 41: + LA89_325 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 42: + LA89_326 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 45 or LA89 == 46: + LA89_327 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 48: + LA89_328 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + elif LA89 == 49 or LA89 == 50 or LA89 == 51 or LA89 == 52 or LA89 == 53 or LA89 == 54 or LA89 == 55 or LA89 == 56 or LA89 == 57: + LA89_329 = self.input.LA(3) + + if (self.synpred180()) : + alt89 = 1 + + + + + if alt89 == 1: + # C.g:0:0: declaration + self.following.append(self.FOLLOW_declaration_in_macro_statement2151) + self.declaration() + self.following.pop() + if self.failed: + return + + + else: + break #loop89 + + + # C.g:491:33: ( statement_list )? + alt90 = 2 + LA90 = self.input.LA(1) + if LA90 == IDENTIFIER: + LA90 = self.input.LA(2) + if LA90 == 61: + LA90_44 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 25 or LA90 == 29 or LA90 == 30 or LA90 == 31 or LA90 == 32 or LA90 == 33 or LA90 == 34 or LA90 == 35 or LA90 == 36 or LA90 == 37 or LA90 == 38 or LA90 == 39 or LA90 == 40 or LA90 == 41 or LA90 == 42 or LA90 == 45 or LA90 == 46 or LA90 == 47 or LA90 == 48 or LA90 == 49 or LA90 == 50 or LA90 == 51 or LA90 == 52 or LA90 == 53 or LA90 == 54 or LA90 == 55 or LA90 == 56 or LA90 == 57 or LA90 == 58 or LA90 == 59 or LA90 == 60: + alt90 = 1 + elif LA90 == STRING_LITERAL: + LA90_46 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == IDENTIFIER: + LA90_47 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 63: + LA90_48 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 74: + LA90_49 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 65: + LA90_50 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 75: + LA90_51 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 71: + LA90_52 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 72: + LA90_53 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 28 or LA90 == 79 or LA90 == 80 or LA90 == 81 or LA90 == 82 or LA90 == 83 or LA90 == 84 or LA90 == 85 or LA90 == 86 or LA90 == 87 or LA90 == 88: + LA90_54 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 69: + LA90_72 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 70: + LA90_73 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 67: + LA90_74 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 68: + LA90_75 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 100 or LA90 == 101: + LA90_76 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 96 or LA90 == 97 or LA90 == 98 or LA90 == 99: + LA90_77 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 94 or LA90 == 95: + LA90_78 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 76: + LA90_79 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 93: + LA90_80 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 92: + LA90_81 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 91: + LA90_82 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 90: + LA90_83 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 89: + LA90_84 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 27: + LA90_85 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 25 or LA90 == 26 or LA90 == 29 or LA90 == 30 or LA90 == 31 or LA90 == 32 or LA90 == 33 or LA90 == 34 or LA90 == 35 or LA90 == 36 or LA90 == 37 or LA90 == 38 or LA90 == 39 or LA90 == 40 or LA90 == 41 or LA90 == 42 or LA90 == 43 or LA90 == 45 or LA90 == 46 or LA90 == 48 or LA90 == 49 or LA90 == 50 or LA90 == 51 or LA90 == 52 or LA90 == 53 or LA90 == 54 or LA90 == 55 or LA90 == 56 or LA90 == 57 or LA90 == 58 or LA90 == 59 or LA90 == 60 or LA90 == 102 or LA90 == 103 or LA90 == 104 or LA90 == 105 or LA90 == 106 or LA90 == 107 or LA90 == 109 or LA90 == 110 or LA90 == 111 or LA90 == 112 or LA90 == 113 or LA90 == 114 or LA90 == 115 or LA90 == 116: + alt90 = 1 + elif LA90 == HEX_LITERAL: + LA90 = self.input.LA(2) + if LA90 == 63: + LA90_87 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 61: + LA90_88 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 74: + LA90_89 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 65: + LA90_90 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 75: + LA90_91 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 71: + LA90_92 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 72: + LA90_93 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 69: + LA90_94 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 70: + LA90_95 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 67: + LA90_96 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 68: + LA90_97 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 100 or LA90 == 101: + LA90_98 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 96 or LA90 == 97 or LA90 == 98 or LA90 == 99: + LA90_99 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 94 or LA90 == 95: + LA90_100 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 76: + LA90_101 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 93: + LA90_102 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 92: + LA90_103 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 91: + LA90_104 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 90: + LA90_105 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 89: + LA90_106 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 27: + LA90_107 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 25: + alt90 = 1 + elif LA90 == 28 or LA90 == 79 or LA90 == 80 or LA90 == 81 or LA90 == 82 or LA90 == 83 or LA90 == 84 or LA90 == 85 or LA90 == 86 or LA90 == 87 or LA90 == 88: + LA90_110 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == OCTAL_LITERAL: + LA90 = self.input.LA(2) + if LA90 == 63: + LA90_111 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 61: + LA90_112 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 74: + LA90_113 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 65: + LA90_114 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 75: + LA90_115 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 71: + LA90_116 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 72: + LA90_117 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 28 or LA90 == 79 or LA90 == 80 or LA90 == 81 or LA90 == 82 or LA90 == 83 or LA90 == 84 or LA90 == 85 or LA90 == 86 or LA90 == 87 or LA90 == 88: + LA90_118 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 69: + LA90_119 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 70: + LA90_120 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 67: + LA90_121 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 68: + LA90_122 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 100 or LA90 == 101: + LA90_123 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 96 or LA90 == 97 or LA90 == 98 or LA90 == 99: + LA90_124 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 94 or LA90 == 95: + LA90_125 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 76: + LA90_126 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 93: + LA90_127 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 92: + LA90_128 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 91: + LA90_129 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 90: + LA90_130 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 89: + LA90_131 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 27: + LA90_132 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 25: + alt90 = 1 + elif LA90 == DECIMAL_LITERAL: + LA90 = self.input.LA(2) + if LA90 == 63: + LA90_135 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 61: + LA90_136 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 74: + LA90_137 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 65: + LA90_138 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 75: + LA90_139 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 71: + LA90_140 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 72: + LA90_141 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 28 or LA90 == 79 or LA90 == 80 or LA90 == 81 or LA90 == 82 or LA90 == 83 or LA90 == 84 or LA90 == 85 or LA90 == 86 or LA90 == 87 or LA90 == 88: + LA90_142 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 69: + LA90_143 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 70: + LA90_144 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 67: + LA90_145 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 68: + LA90_146 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 100 or LA90 == 101: + LA90_147 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 96 or LA90 == 97 or LA90 == 98 or LA90 == 99: + LA90_148 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 94 or LA90 == 95: + LA90_149 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 76: + LA90_150 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 93: + LA90_151 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 92: + LA90_152 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 91: + LA90_153 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 90: + LA90_154 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 89: + LA90_155 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 27: + LA90_156 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 25: + alt90 = 1 + elif LA90 == CHARACTER_LITERAL: + LA90 = self.input.LA(2) + if LA90 == 63: + LA90_159 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 61: + LA90_160 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 74: + LA90_161 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 65: + LA90_162 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 75: + LA90_163 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 71: + LA90_164 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 72: + LA90_165 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 28 or LA90 == 79 or LA90 == 80 or LA90 == 81 or LA90 == 82 or LA90 == 83 or LA90 == 84 or LA90 == 85 or LA90 == 86 or LA90 == 87 or LA90 == 88: + LA90_166 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 69: + LA90_167 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 70: + LA90_168 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 67: + LA90_169 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 68: + LA90_170 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 100 or LA90 == 101: + LA90_171 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 96 or LA90 == 97 or LA90 == 98 or LA90 == 99: + LA90_172 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 94 or LA90 == 95: + LA90_173 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 76: + LA90_174 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 93: + LA90_175 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 92: + LA90_176 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 91: + LA90_177 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 90: + LA90_178 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 89: + LA90_179 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 27: + LA90_180 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 25: + alt90 = 1 + elif LA90 == STRING_LITERAL: + LA90 = self.input.LA(2) + if LA90 == IDENTIFIER: + LA90_183 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 63: + LA90_184 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 61: + LA90_185 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 74: + LA90_186 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 65: + LA90_187 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 75: + LA90_188 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 71: + LA90_189 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 72: + LA90_190 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 69: + LA90_191 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 70: + LA90_192 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 67: + LA90_193 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 68: + LA90_194 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 100 or LA90 == 101: + LA90_195 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 96 or LA90 == 97 or LA90 == 98 or LA90 == 99: + LA90_196 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 94 or LA90 == 95: + LA90_197 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 76: + LA90_198 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 93: + LA90_199 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 92: + LA90_200 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 91: + LA90_201 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 90: + LA90_202 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 89: + LA90_203 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 27: + LA90_204 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 25: + alt90 = 1 + elif LA90 == STRING_LITERAL: + LA90_206 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 28 or LA90 == 79 or LA90 == 80 or LA90 == 81 or LA90 == 82 or LA90 == 83 or LA90 == 84 or LA90 == 85 or LA90 == 86 or LA90 == 87 or LA90 == 88: + LA90_207 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == FLOATING_POINT_LITERAL: + LA90 = self.input.LA(2) + if LA90 == 63: + LA90_209 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 61: + LA90_210 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 74: + LA90_211 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 65: + LA90_212 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 75: + LA90_213 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 71: + LA90_214 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 72: + LA90_215 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 69: + LA90_216 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 70: + LA90_217 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 67: + LA90_218 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 68: + LA90_219 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 100 or LA90 == 101: + LA90_220 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 96 or LA90 == 97 or LA90 == 98 or LA90 == 99: + LA90_221 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 94 or LA90 == 95: + LA90_222 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 76: + LA90_223 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 93: + LA90_224 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 92: + LA90_225 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 91: + LA90_226 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 90: + LA90_227 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 89: + LA90_228 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 27: + LA90_229 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 25: + alt90 = 1 + elif LA90 == 28 or LA90 == 79 or LA90 == 80 or LA90 == 81 or LA90 == 82 or LA90 == 83 or LA90 == 84 or LA90 == 85 or LA90 == 86 or LA90 == 87 or LA90 == 88: + LA90_231 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 61: + LA90 = self.input.LA(2) + if LA90 == IDENTIFIER: + LA90_233 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == HEX_LITERAL: + LA90_234 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == OCTAL_LITERAL: + LA90_235 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == DECIMAL_LITERAL: + LA90_236 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == CHARACTER_LITERAL: + LA90_237 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == STRING_LITERAL: + LA90_238 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == FLOATING_POINT_LITERAL: + LA90_239 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 61: + LA90_240 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 71: + LA90_241 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 72: + LA90_242 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 65 or LA90 == 67 or LA90 == 68 or LA90 == 76 or LA90 == 77 or LA90 == 78: + LA90_243 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 73: + LA90_244 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 49 or LA90 == 50 or LA90 == 51 or LA90 == 52 or LA90 == 53 or LA90 == 54 or LA90 == 55 or LA90 == 56 or LA90 == 57 or LA90 == 58 or LA90 == 59 or LA90 == 60: + LA90_245 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 34: + LA90_246 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 35: + LA90_247 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 36: + LA90_248 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 37: + LA90_249 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 38: + LA90_250 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 39: + LA90_251 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 40: + LA90_252 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 41: + LA90_253 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 42: + LA90_254 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 45 or LA90 == 46: + LA90_255 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 48: + LA90_256 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 71: + LA90 = self.input.LA(2) + if LA90 == IDENTIFIER: + LA90_257 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == HEX_LITERAL: + LA90_258 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == OCTAL_LITERAL: + LA90_259 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == DECIMAL_LITERAL: + LA90_260 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == CHARACTER_LITERAL: + LA90_261 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == STRING_LITERAL: + LA90_262 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == FLOATING_POINT_LITERAL: + LA90_263 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 61: + LA90_264 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 71: + LA90_265 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 72: + LA90_266 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 65 or LA90 == 67 or LA90 == 68 or LA90 == 76 or LA90 == 77 or LA90 == 78: + LA90_267 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 73: + LA90_268 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 72: + LA90 = self.input.LA(2) + if LA90 == IDENTIFIER: + LA90_269 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == HEX_LITERAL: + LA90_270 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == OCTAL_LITERAL: + LA90_271 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == DECIMAL_LITERAL: + LA90_272 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == CHARACTER_LITERAL: + LA90_273 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == STRING_LITERAL: + LA90_274 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == FLOATING_POINT_LITERAL: + LA90_275 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 61: + LA90_276 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 71: + LA90_277 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 72: + LA90_278 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 65 or LA90 == 67 or LA90 == 68 or LA90 == 76 or LA90 == 77 or LA90 == 78: + LA90_279 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 73: + LA90_280 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 65 or LA90 == 67 or LA90 == 68 or LA90 == 76 or LA90 == 77 or LA90 == 78: + LA90 = self.input.LA(2) + if LA90 == 61: + LA90_281 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == IDENTIFIER: + LA90_282 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == HEX_LITERAL: + LA90_283 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == OCTAL_LITERAL: + LA90_284 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == DECIMAL_LITERAL: + LA90_285 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == CHARACTER_LITERAL: + LA90_286 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == STRING_LITERAL: + LA90_287 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == FLOATING_POINT_LITERAL: + LA90_288 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 71: + LA90_289 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 72: + LA90_290 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 65 or LA90 == 67 or LA90 == 68 or LA90 == 76 or LA90 == 77 or LA90 == 78: + LA90_291 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 73: + LA90_292 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 73: + LA90 = self.input.LA(2) + if LA90 == 61: + LA90_293 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == IDENTIFIER: + LA90_294 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == HEX_LITERAL: + LA90_295 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == OCTAL_LITERAL: + LA90_296 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == DECIMAL_LITERAL: + LA90_297 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == CHARACTER_LITERAL: + LA90_298 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == STRING_LITERAL: + LA90_299 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == FLOATING_POINT_LITERAL: + LA90_300 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 71: + LA90_301 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 72: + LA90_302 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 65 or LA90 == 67 or LA90 == 68 or LA90 == 76 or LA90 == 77 or LA90 == 78: + LA90_303 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + elif LA90 == 73: + LA90_304 = self.input.LA(3) + + if (self.synpred181()) : + alt90 = 1 + if alt90 == 1: + # C.g:0:0: statement_list + self.following.append(self.FOLLOW_statement_list_in_macro_statement2155) + self.statement_list() + self.following.pop() + if self.failed: + return + + + + # C.g:491:49: ( expression )? + alt91 = 2 + LA91_0 = self.input.LA(1) + + if ((IDENTIFIER <= LA91_0 <= FLOATING_POINT_LITERAL) or LA91_0 == 61 or LA91_0 == 65 or (67 <= LA91_0 <= 68) or (71 <= LA91_0 <= 73) or (76 <= LA91_0 <= 78)) : + alt91 = 1 + if alt91 == 1: + # C.g:0:0: expression + self.following.append(self.FOLLOW_expression_in_macro_statement2158) + self.expression() + self.following.pop() + if self.failed: + return + + + + self.match(self.input, 62, self.FOLLOW_62_in_macro_statement2161) + if self.failed: + return + + + + + except RecognitionException, re: + self.reportError(re) + self.recover(self.input, re) + finally: + if self.backtracking > 0: + self.memoize(self.input, 64, macro_statement_StartIndex) + + pass + + return + + # $ANTLR end macro_statement + + + # $ANTLR start labeled_statement + # C.g:494:1: labeled_statement : ( IDENTIFIER ':' statement | 'case' constant_expression ':' statement | 'default' ':' statement ); + def labeled_statement(self, ): + + labeled_statement_StartIndex = self.input.index() + try: + try: + if self.backtracking > 0 and self.alreadyParsedRule(self.input, 65): + return + + # C.g:495:2: ( IDENTIFIER ':' statement | 'case' constant_expression ':' statement | 'default' ':' statement ) + alt92 = 3 + LA92 = self.input.LA(1) + if LA92 == IDENTIFIER: + alt92 = 1 + elif LA92 == 105: + alt92 = 2 + elif LA92 == 106: + alt92 = 3 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("494:1: labeled_statement : ( IDENTIFIER ':' statement | 'case' constant_expression ':' statement | 'default' ':' statement );", 92, 0, self.input) + + raise nvae + + if alt92 == 1: + # C.g:495:4: IDENTIFIER ':' statement + self.match(self.input, IDENTIFIER, self.FOLLOW_IDENTIFIER_in_labeled_statement2173) + if self.failed: + return + self.match(self.input, 47, self.FOLLOW_47_in_labeled_statement2175) + if self.failed: + return + self.following.append(self.FOLLOW_statement_in_labeled_statement2177) + self.statement() + self.following.pop() + if self.failed: + return + + + elif alt92 == 2: + # C.g:496:4: 'case' constant_expression ':' statement + self.match(self.input, 105, self.FOLLOW_105_in_labeled_statement2182) + if self.failed: + return + self.following.append(self.FOLLOW_constant_expression_in_labeled_statement2184) + self.constant_expression() + self.following.pop() + if self.failed: + return + self.match(self.input, 47, self.FOLLOW_47_in_labeled_statement2186) + if self.failed: + return + self.following.append(self.FOLLOW_statement_in_labeled_statement2188) + self.statement() + self.following.pop() + if self.failed: + return + + + elif alt92 == 3: + # C.g:497:4: 'default' ':' statement + self.match(self.input, 106, self.FOLLOW_106_in_labeled_statement2193) + if self.failed: + return + self.match(self.input, 47, self.FOLLOW_47_in_labeled_statement2195) + if self.failed: + return + self.following.append(self.FOLLOW_statement_in_labeled_statement2197) + self.statement() + self.following.pop() + if self.failed: + return + + + + except RecognitionException, re: + self.reportError(re) + self.recover(self.input, re) + finally: + if self.backtracking > 0: + self.memoize(self.input, 65, labeled_statement_StartIndex) + + pass + + return + + # $ANTLR end labeled_statement + + class compound_statement_return(object): + def __init__(self): + self.start = None + self.stop = None + + + + # $ANTLR start compound_statement + # C.g:500:1: compound_statement : '{' ( declaration )* ( statement_list )? '}' ; + def compound_statement(self, ): + + retval = self.compound_statement_return() + retval.start = self.input.LT(1) + compound_statement_StartIndex = self.input.index() + try: + try: + if self.backtracking > 0 and self.alreadyParsedRule(self.input, 66): + return retval + + # C.g:501:2: ( '{' ( declaration )* ( statement_list )? '}' ) + # C.g:501:4: '{' ( declaration )* ( statement_list )? '}' + self.match(self.input, 43, self.FOLLOW_43_in_compound_statement2208) + if self.failed: + return retval + # C.g:501:8: ( declaration )* + while True: #loop93 + alt93 = 2 + LA93 = self.input.LA(1) + if LA93 == IDENTIFIER: + LA93 = self.input.LA(2) + if LA93 == 61: + LA93_44 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 65: + LA93_48 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 25: + LA93_67 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == IDENTIFIER: + LA93_69 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 58: + LA93_70 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 59: + LA93_71 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 60: + LA93_72 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 29 or LA93 == 30 or LA93 == 31 or LA93 == 32 or LA93 == 33: + LA93_73 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 34: + LA93_74 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 35: + LA93_75 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 36: + LA93_76 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 37: + LA93_77 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 38: + LA93_78 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 39: + LA93_79 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 40: + LA93_80 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 41: + LA93_81 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 42: + LA93_82 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 45 or LA93 == 46: + LA93_83 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 48: + LA93_84 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 49 or LA93 == 50 or LA93 == 51 or LA93 == 52 or LA93 == 53 or LA93 == 54 or LA93 == 55 or LA93 == 56 or LA93 == 57: + LA93_85 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + + elif LA93 == 26: + LA93 = self.input.LA(2) + if LA93 == 29 or LA93 == 30 or LA93 == 31 or LA93 == 32 or LA93 == 33: + LA93_86 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 34: + LA93_87 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 35: + LA93_88 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 36: + LA93_89 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 37: + LA93_90 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 38: + LA93_91 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 39: + LA93_92 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 40: + LA93_93 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 41: + LA93_94 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 42: + LA93_95 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 45 or LA93 == 46: + LA93_96 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 48: + LA93_97 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == IDENTIFIER: + LA93_98 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 58: + LA93_99 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 65: + LA93_100 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 59: + LA93_101 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 60: + LA93_102 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 49 or LA93 == 50 or LA93 == 51 or LA93 == 52 or LA93 == 53 or LA93 == 54 or LA93 == 55 or LA93 == 56 or LA93 == 57: + LA93_103 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 61: + LA93_104 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + + elif LA93 == 29 or LA93 == 30 or LA93 == 31 or LA93 == 32 or LA93 == 33: + LA93 = self.input.LA(2) + if LA93 == 65: + LA93_105 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 58: + LA93_106 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 59: + LA93_107 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 60: + LA93_108 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == IDENTIFIER: + LA93_109 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 61: + LA93_110 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 25: + LA93_111 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 29 or LA93 == 30 or LA93 == 31 or LA93 == 32 or LA93 == 33: + LA93_112 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 34: + LA93_113 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 35: + LA93_114 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 36: + LA93_115 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 37: + LA93_116 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 38: + LA93_117 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 39: + LA93_118 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 40: + LA93_119 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 41: + LA93_120 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 42: + LA93_121 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 45 or LA93 == 46: + LA93_122 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 48: + LA93_123 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 49 or LA93 == 50 or LA93 == 51 or LA93 == 52 or LA93 == 53 or LA93 == 54 or LA93 == 55 or LA93 == 56 or LA93 == 57: + LA93_124 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + + elif LA93 == 34: + LA93 = self.input.LA(2) + if LA93 == 65: + LA93_125 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 58: + LA93_126 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 59: + LA93_127 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 60: + LA93_128 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == IDENTIFIER: + LA93_129 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 61: + LA93_130 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 25: + LA93_131 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 29 or LA93 == 30 or LA93 == 31 or LA93 == 32 or LA93 == 33: + LA93_132 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 34: + LA93_133 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 35: + LA93_134 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 36: + LA93_135 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 37: + LA93_136 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 38: + LA93_137 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 39: + LA93_138 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 40: + LA93_139 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 41: + LA93_140 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 42: + LA93_141 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 45 or LA93 == 46: + LA93_142 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 48: + LA93_143 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 49 or LA93 == 50 or LA93 == 51 or LA93 == 52 or LA93 == 53 or LA93 == 54 or LA93 == 55 or LA93 == 56 or LA93 == 57: + LA93_144 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + + elif LA93 == 35: + LA93 = self.input.LA(2) + if LA93 == 65: + LA93_145 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 58: + LA93_146 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 59: + LA93_147 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 60: + LA93_148 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == IDENTIFIER: + LA93_149 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 61: + LA93_150 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 25: + LA93_151 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 29 or LA93 == 30 or LA93 == 31 or LA93 == 32 or LA93 == 33: + LA93_152 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 34: + LA93_153 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 35: + LA93_154 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 36: + LA93_155 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 37: + LA93_156 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 38: + LA93_157 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 39: + LA93_158 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 40: + LA93_159 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 41: + LA93_160 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 42: + LA93_161 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 45 or LA93 == 46: + LA93_162 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 48: + LA93_163 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 49 or LA93 == 50 or LA93 == 51 or LA93 == 52 or LA93 == 53 or LA93 == 54 or LA93 == 55 or LA93 == 56 or LA93 == 57: + LA93_164 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + + elif LA93 == 36: + LA93 = self.input.LA(2) + if LA93 == 65: + LA93_165 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 58: + LA93_166 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 59: + LA93_167 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 60: + LA93_168 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == IDENTIFIER: + LA93_169 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 61: + LA93_170 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 25: + LA93_171 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 29 or LA93 == 30 or LA93 == 31 or LA93 == 32 or LA93 == 33: + LA93_172 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 34: + LA93_173 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 35: + LA93_174 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 36: + LA93_175 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 37: + LA93_176 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 38: + LA93_177 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 39: + LA93_178 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 40: + LA93_179 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 41: + LA93_180 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 42: + LA93_181 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 45 or LA93 == 46: + LA93_182 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 48: + LA93_183 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 49 or LA93 == 50 or LA93 == 51 or LA93 == 52 or LA93 == 53 or LA93 == 54 or LA93 == 55 or LA93 == 56 or LA93 == 57: + LA93_184 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + + elif LA93 == 37: + LA93 = self.input.LA(2) + if LA93 == 65: + LA93_185 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 58: + LA93_186 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 59: + LA93_187 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 60: + LA93_188 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == IDENTIFIER: + LA93_189 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 61: + LA93_190 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 25: + LA93_191 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 29 or LA93 == 30 or LA93 == 31 or LA93 == 32 or LA93 == 33: + LA93_192 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 34: + LA93_193 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 35: + LA93_194 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 36: + LA93_195 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 37: + LA93_196 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 38: + LA93_197 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 39: + LA93_198 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 40: + LA93_199 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 41: + LA93_200 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 42: + LA93_201 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 45 or LA93 == 46: + LA93_202 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 48: + LA93_203 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 49 or LA93 == 50 or LA93 == 51 or LA93 == 52 or LA93 == 53 or LA93 == 54 or LA93 == 55 or LA93 == 56 or LA93 == 57: + LA93_204 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + + elif LA93 == 38: + LA93 = self.input.LA(2) + if LA93 == 65: + LA93_205 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 58: + LA93_206 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 59: + LA93_207 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 60: + LA93_208 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == IDENTIFIER: + LA93_209 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 61: + LA93_210 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 25: + LA93_211 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 29 or LA93 == 30 or LA93 == 31 or LA93 == 32 or LA93 == 33: + LA93_212 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 34: + LA93_213 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 35: + LA93_214 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 36: + LA93_215 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 37: + LA93_216 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 38: + LA93_217 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 39: + LA93_218 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 40: + LA93_219 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 41: + LA93_220 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 42: + LA93_221 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 45 or LA93 == 46: + LA93_222 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 48: + LA93_223 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 49 or LA93 == 50 or LA93 == 51 or LA93 == 52 or LA93 == 53 or LA93 == 54 or LA93 == 55 or LA93 == 56 or LA93 == 57: + LA93_224 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + + elif LA93 == 39: + LA93 = self.input.LA(2) + if LA93 == 65: + LA93_225 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 58: + LA93_226 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 59: + LA93_227 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 60: + LA93_228 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == IDENTIFIER: + LA93_229 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 61: + LA93_230 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 25: + LA93_231 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 29 or LA93 == 30 or LA93 == 31 or LA93 == 32 or LA93 == 33: + LA93_232 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 34: + LA93_233 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 35: + LA93_234 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 36: + LA93_235 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 37: + LA93_236 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 38: + LA93_237 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 39: + LA93_238 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 40: + LA93_239 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 41: + LA93_240 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 42: + LA93_241 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 45 or LA93 == 46: + LA93_242 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 48: + LA93_243 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 49 or LA93 == 50 or LA93 == 51 or LA93 == 52 or LA93 == 53 or LA93 == 54 or LA93 == 55 or LA93 == 56 or LA93 == 57: + LA93_244 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + + elif LA93 == 40: + LA93 = self.input.LA(2) + if LA93 == 65: + LA93_245 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 58: + LA93_246 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 59: + LA93_247 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 60: + LA93_248 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == IDENTIFIER: + LA93_249 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 61: + LA93_250 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 25: + LA93_251 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 29 or LA93 == 30 or LA93 == 31 or LA93 == 32 or LA93 == 33: + LA93_252 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 34: + LA93_253 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 35: + LA93_254 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 36: + LA93_255 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 37: + LA93_256 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 38: + LA93_257 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 39: + LA93_258 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 40: + LA93_259 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 41: + LA93_260 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 42: + LA93_261 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 45 or LA93 == 46: + LA93_262 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 48: + LA93_263 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 49 or LA93 == 50 or LA93 == 51 or LA93 == 52 or LA93 == 53 or LA93 == 54 or LA93 == 55 or LA93 == 56 or LA93 == 57: + LA93_264 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + + elif LA93 == 41: + LA93 = self.input.LA(2) + if LA93 == 65: + LA93_265 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 58: + LA93_266 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 59: + LA93_267 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 60: + LA93_268 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == IDENTIFIER: + LA93_269 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 61: + LA93_270 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 25: + LA93_271 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 29 or LA93 == 30 or LA93 == 31 or LA93 == 32 or LA93 == 33: + LA93_272 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 34: + LA93_273 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 35: + LA93_274 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 36: + LA93_275 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 37: + LA93_276 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 38: + LA93_277 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 39: + LA93_278 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 40: + LA93_279 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 41: + LA93_280 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 42: + LA93_281 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 45 or LA93 == 46: + LA93_282 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 48: + LA93_283 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 49 or LA93 == 50 or LA93 == 51 or LA93 == 52 or LA93 == 53 or LA93 == 54 or LA93 == 55 or LA93 == 56 or LA93 == 57: + LA93_284 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + + elif LA93 == 42: + LA93 = self.input.LA(2) + if LA93 == 65: + LA93_285 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 58: + LA93_286 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 59: + LA93_287 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 60: + LA93_288 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == IDENTIFIER: + LA93_289 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 61: + LA93_290 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 25: + LA93_291 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 29 or LA93 == 30 or LA93 == 31 or LA93 == 32 or LA93 == 33: + LA93_292 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 34: + LA93_293 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 35: + LA93_294 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 36: + LA93_295 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 37: + LA93_296 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 38: + LA93_297 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 39: + LA93_298 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 40: + LA93_299 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 41: + LA93_300 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 42: + LA93_301 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 45 or LA93 == 46: + LA93_302 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 48: + LA93_303 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 49 or LA93 == 50 or LA93 == 51 or LA93 == 52 or LA93 == 53 or LA93 == 54 or LA93 == 55 or LA93 == 56 or LA93 == 57: + LA93_304 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + + elif LA93 == 45 or LA93 == 46: + LA93_40 = self.input.LA(2) + + if (LA93_40 == IDENTIFIER) : + LA93_305 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif (LA93_40 == 43) : + LA93_306 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + + + elif LA93 == 48: + LA93_41 = self.input.LA(2) + + if (LA93_41 == IDENTIFIER) : + LA93_307 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif (LA93_41 == 43) : + LA93_308 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + + + elif LA93 == 49 or LA93 == 50 or LA93 == 51 or LA93 == 52 or LA93 == 53 or LA93 == 54 or LA93 == 55 or LA93 == 56 or LA93 == 57 or LA93 == 58 or LA93 == 59 or LA93 == 60: + LA93 = self.input.LA(2) + if LA93 == 65: + LA93_309 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 58: + LA93_310 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 59: + LA93_311 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 60: + LA93_312 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == IDENTIFIER: + LA93_313 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 61: + LA93_314 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 25: + LA93_315 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 29 or LA93 == 30 or LA93 == 31 or LA93 == 32 or LA93 == 33: + LA93_316 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 34: + LA93_317 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 35: + LA93_318 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 36: + LA93_319 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 37: + LA93_320 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 38: + LA93_321 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 39: + LA93_322 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 40: + LA93_323 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 41: + LA93_324 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 42: + LA93_325 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 45 or LA93 == 46: + LA93_326 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 48: + LA93_327 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + elif LA93 == 49 or LA93 == 50 or LA93 == 51 or LA93 == 52 or LA93 == 53 or LA93 == 54 or LA93 == 55 or LA93 == 56 or LA93 == 57: + LA93_328 = self.input.LA(3) + + if (self.synpred185()) : + alt93 = 1 + + + + + if alt93 == 1: + # C.g:0:0: declaration + self.following.append(self.FOLLOW_declaration_in_compound_statement2210) + self.declaration() + self.following.pop() + if self.failed: + return retval + + + else: + break #loop93 + + + # C.g:501:21: ( statement_list )? + alt94 = 2 + LA94_0 = self.input.LA(1) + + if ((IDENTIFIER <= LA94_0 <= FLOATING_POINT_LITERAL) or (25 <= LA94_0 <= 26) or (29 <= LA94_0 <= 43) or (45 <= LA94_0 <= 46) or (48 <= LA94_0 <= 61) or LA94_0 == 65 or (67 <= LA94_0 <= 68) or (71 <= LA94_0 <= 73) or (76 <= LA94_0 <= 78) or (102 <= LA94_0 <= 107) or (109 <= LA94_0 <= 116)) : + alt94 = 1 + if alt94 == 1: + # C.g:0:0: statement_list + self.following.append(self.FOLLOW_statement_list_in_compound_statement2213) + self.statement_list() + self.following.pop() + if self.failed: + return retval + + + + self.match(self.input, 44, self.FOLLOW_44_in_compound_statement2216) + if self.failed: + return retval + + + + retval.stop = self.input.LT(-1) + + + except RecognitionException, re: + self.reportError(re) + self.recover(self.input, re) + finally: + if self.backtracking > 0: + self.memoize(self.input, 66, compound_statement_StartIndex) + + pass + + return retval + + # $ANTLR end compound_statement + + + # $ANTLR start statement_list + # C.g:504:1: statement_list : ( statement )+ ; + def statement_list(self, ): + + statement_list_StartIndex = self.input.index() + try: + try: + if self.backtracking > 0 and self.alreadyParsedRule(self.input, 67): + return + + # C.g:505:2: ( ( statement )+ ) + # C.g:505:4: ( statement )+ + # C.g:505:4: ( statement )+ + cnt95 = 0 + while True: #loop95 + alt95 = 2 + LA95 = self.input.LA(1) + if LA95 == IDENTIFIER: + LA95 = self.input.LA(2) + if LA95 == 25 or LA95 == 29 or LA95 == 30 or LA95 == 31 or LA95 == 32 or LA95 == 33 or LA95 == 34 or LA95 == 35 or LA95 == 36 or LA95 == 37 or LA95 == 38 or LA95 == 39 or LA95 == 40 or LA95 == 41 or LA95 == 42 or LA95 == 45 or LA95 == 46 or LA95 == 47 or LA95 == 48 or LA95 == 49 or LA95 == 50 or LA95 == 51 or LA95 == 52 or LA95 == 53 or LA95 == 54 or LA95 == 55 or LA95 == 56 or LA95 == 57 or LA95 == 58 or LA95 == 59 or LA95 == 60: + alt95 = 1 + elif LA95 == 61: + LA95_47 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 63: + LA95_48 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 74: + LA95_49 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 65: + LA95_50 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 75: + LA95_51 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 71: + LA95_52 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 72: + LA95_53 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 28 or LA95 == 79 or LA95 == 80 or LA95 == 81 or LA95 == 82 or LA95 == 83 or LA95 == 84 or LA95 == 85 or LA95 == 86 or LA95 == 87 or LA95 == 88: + LA95_54 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == STRING_LITERAL: + LA95_55 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == IDENTIFIER: + LA95_56 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 69: + LA95_57 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 70: + LA95_58 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 67: + LA95_59 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 68: + LA95_60 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 100 or LA95 == 101: + LA95_61 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 96 or LA95 == 97 or LA95 == 98 or LA95 == 99: + LA95_62 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 94 or LA95 == 95: + LA95_63 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 76: + LA95_64 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 93: + LA95_65 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 92: + LA95_66 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 91: + LA95_67 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 90: + LA95_68 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 89: + LA95_69 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 27: + LA95_70 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + + elif LA95 == HEX_LITERAL: + LA95 = self.input.LA(2) + if LA95 == 63: + LA95_89 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 61: + LA95_90 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 74: + LA95_91 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 65: + LA95_92 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 75: + LA95_93 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 71: + LA95_94 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 72: + LA95_95 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 69: + LA95_96 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 70: + LA95_97 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 67: + LA95_98 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 68: + LA95_99 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 100 or LA95 == 101: + LA95_100 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 96 or LA95 == 97 or LA95 == 98 or LA95 == 99: + LA95_101 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 94 or LA95 == 95: + LA95_102 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 76: + LA95_103 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 93: + LA95_104 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 92: + LA95_105 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 91: + LA95_106 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 90: + LA95_107 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 89: + LA95_108 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 27: + LA95_109 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 25: + alt95 = 1 + elif LA95 == 28 or LA95 == 79 or LA95 == 80 or LA95 == 81 or LA95 == 82 or LA95 == 83 or LA95 == 84 or LA95 == 85 or LA95 == 86 or LA95 == 87 or LA95 == 88: + LA95_112 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + + elif LA95 == OCTAL_LITERAL: + LA95 = self.input.LA(2) + if LA95 == 63: + LA95_113 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 61: + LA95_114 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 74: + LA95_115 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 65: + LA95_116 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 75: + LA95_117 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 71: + LA95_118 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 72: + LA95_119 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 28 or LA95 == 79 or LA95 == 80 or LA95 == 81 or LA95 == 82 or LA95 == 83 or LA95 == 84 or LA95 == 85 or LA95 == 86 or LA95 == 87 or LA95 == 88: + LA95_120 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 69: + LA95_121 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 70: + LA95_122 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 67: + LA95_123 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 68: + LA95_124 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 100 or LA95 == 101: + LA95_125 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 96 or LA95 == 97 or LA95 == 98 or LA95 == 99: + LA95_126 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 94 or LA95 == 95: + LA95_127 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 76: + LA95_128 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 93: + LA95_129 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 92: + LA95_130 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 91: + LA95_131 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 90: + LA95_132 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 89: + LA95_133 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 27: + LA95_134 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 25: + alt95 = 1 + + elif LA95 == DECIMAL_LITERAL: + LA95 = self.input.LA(2) + if LA95 == 63: + LA95_137 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 61: + LA95_138 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 74: + LA95_139 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 65: + LA95_140 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 75: + LA95_141 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 71: + LA95_142 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 72: + LA95_143 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 28 or LA95 == 79 or LA95 == 80 or LA95 == 81 or LA95 == 82 or LA95 == 83 or LA95 == 84 or LA95 == 85 or LA95 == 86 or LA95 == 87 or LA95 == 88: + LA95_144 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 69: + LA95_145 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 70: + LA95_146 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 67: + LA95_147 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 68: + LA95_148 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 100 or LA95 == 101: + LA95_149 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 96 or LA95 == 97 or LA95 == 98 or LA95 == 99: + LA95_150 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 94 or LA95 == 95: + LA95_151 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 76: + LA95_152 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 93: + LA95_153 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 92: + LA95_154 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 91: + LA95_155 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 90: + LA95_156 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 89: + LA95_157 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 27: + LA95_158 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 25: + alt95 = 1 + + elif LA95 == CHARACTER_LITERAL: + LA95 = self.input.LA(2) + if LA95 == 63: + LA95_161 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 61: + LA95_162 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 74: + LA95_163 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 65: + LA95_164 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 75: + LA95_165 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 71: + LA95_166 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 72: + LA95_167 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 28 or LA95 == 79 or LA95 == 80 or LA95 == 81 or LA95 == 82 or LA95 == 83 or LA95 == 84 or LA95 == 85 or LA95 == 86 or LA95 == 87 or LA95 == 88: + LA95_168 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 69: + LA95_169 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 70: + LA95_170 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 67: + LA95_171 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 68: + LA95_172 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 100 or LA95 == 101: + LA95_173 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 96 or LA95 == 97 or LA95 == 98 or LA95 == 99: + LA95_174 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 94 or LA95 == 95: + LA95_175 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 76: + LA95_176 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 93: + LA95_177 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 92: + LA95_178 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 91: + LA95_179 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 90: + LA95_180 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 89: + LA95_181 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 27: + LA95_182 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 25: + alt95 = 1 + + elif LA95 == STRING_LITERAL: + LA95 = self.input.LA(2) + if LA95 == IDENTIFIER: + LA95_185 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 63: + LA95_186 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 61: + LA95_187 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 74: + LA95_188 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 65: + LA95_189 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 75: + LA95_190 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 71: + LA95_191 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 72: + LA95_192 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 69: + LA95_193 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 70: + LA95_194 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 67: + LA95_195 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 68: + LA95_196 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 100 or LA95 == 101: + LA95_197 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 96 or LA95 == 97 or LA95 == 98 or LA95 == 99: + LA95_198 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 94 or LA95 == 95: + LA95_199 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 76: + LA95_200 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 93: + LA95_201 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 92: + LA95_202 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 91: + LA95_203 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 90: + LA95_204 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 89: + LA95_205 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 27: + LA95_206 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 25: + alt95 = 1 + elif LA95 == STRING_LITERAL: + LA95_208 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 28 or LA95 == 79 or LA95 == 80 or LA95 == 81 or LA95 == 82 or LA95 == 83 or LA95 == 84 or LA95 == 85 or LA95 == 86 or LA95 == 87 or LA95 == 88: + LA95_210 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + + elif LA95 == FLOATING_POINT_LITERAL: + LA95 = self.input.LA(2) + if LA95 == 63: + LA95_211 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 61: + LA95_212 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 74: + LA95_213 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 65: + LA95_214 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 75: + LA95_215 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 71: + LA95_216 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 72: + LA95_217 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 69: + LA95_218 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 70: + LA95_219 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 67: + LA95_220 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 68: + LA95_221 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 100 or LA95 == 101: + LA95_222 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 96 or LA95 == 97 or LA95 == 98 or LA95 == 99: + LA95_223 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 94 or LA95 == 95: + LA95_224 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 76: + LA95_225 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 93: + LA95_226 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 92: + LA95_227 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 91: + LA95_228 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 90: + LA95_229 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 89: + LA95_230 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 27: + LA95_231 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 28 or LA95 == 79 or LA95 == 80 or LA95 == 81 or LA95 == 82 or LA95 == 83 or LA95 == 84 or LA95 == 85 or LA95 == 86 or LA95 == 87 or LA95 == 88: + LA95_233 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 25: + alt95 = 1 + + elif LA95 == 61: + LA95 = self.input.LA(2) + if LA95 == IDENTIFIER: + LA95_235 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == HEX_LITERAL: + LA95_236 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == OCTAL_LITERAL: + LA95_237 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == DECIMAL_LITERAL: + LA95_238 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == CHARACTER_LITERAL: + LA95_239 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == STRING_LITERAL: + LA95_240 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == FLOATING_POINT_LITERAL: + LA95_241 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 61: + LA95_242 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 71: + LA95_243 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 72: + LA95_244 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 65 or LA95 == 67 or LA95 == 68 or LA95 == 76 or LA95 == 77 or LA95 == 78: + LA95_245 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 73: + LA95_246 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 49 or LA95 == 50 or LA95 == 51 or LA95 == 52 or LA95 == 53 or LA95 == 54 or LA95 == 55 or LA95 == 56 or LA95 == 57 or LA95 == 58 or LA95 == 59 or LA95 == 60: + LA95_247 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 34: + LA95_248 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 35: + LA95_249 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 36: + LA95_250 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 37: + LA95_251 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 38: + LA95_252 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 39: + LA95_253 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 40: + LA95_254 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 41: + LA95_255 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 42: + LA95_256 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 45 or LA95 == 46: + LA95_257 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 48: + LA95_258 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + + elif LA95 == 71: + LA95 = self.input.LA(2) + if LA95 == IDENTIFIER: + LA95_259 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == HEX_LITERAL: + LA95_260 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == OCTAL_LITERAL: + LA95_261 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == DECIMAL_LITERAL: + LA95_262 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == CHARACTER_LITERAL: + LA95_263 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == STRING_LITERAL: + LA95_264 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == FLOATING_POINT_LITERAL: + LA95_265 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 61: + LA95_266 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 71: + LA95_267 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 72: + LA95_268 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 65 or LA95 == 67 or LA95 == 68 or LA95 == 76 or LA95 == 77 or LA95 == 78: + LA95_269 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 73: + LA95_270 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + + elif LA95 == 72: + LA95 = self.input.LA(2) + if LA95 == IDENTIFIER: + LA95_271 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == HEX_LITERAL: + LA95_272 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == OCTAL_LITERAL: + LA95_273 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == DECIMAL_LITERAL: + LA95_274 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == CHARACTER_LITERAL: + LA95_275 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == STRING_LITERAL: + LA95_276 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == FLOATING_POINT_LITERAL: + LA95_277 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 61: + LA95_278 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 71: + LA95_279 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 72: + LA95_280 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 65 or LA95 == 67 or LA95 == 68 or LA95 == 76 or LA95 == 77 or LA95 == 78: + LA95_281 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 73: + LA95_282 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + + elif LA95 == 65 or LA95 == 67 or LA95 == 68 or LA95 == 76 or LA95 == 77 or LA95 == 78: + LA95 = self.input.LA(2) + if LA95 == 61: + LA95_283 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == IDENTIFIER: + LA95_284 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == HEX_LITERAL: + LA95_285 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == OCTAL_LITERAL: + LA95_286 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == DECIMAL_LITERAL: + LA95_287 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == CHARACTER_LITERAL: + LA95_288 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == STRING_LITERAL: + LA95_289 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == FLOATING_POINT_LITERAL: + LA95_290 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 71: + LA95_291 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 72: + LA95_292 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 65 or LA95 == 67 or LA95 == 68 or LA95 == 76 or LA95 == 77 or LA95 == 78: + LA95_293 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 73: + LA95_294 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + + elif LA95 == 73: + LA95 = self.input.LA(2) + if LA95 == 61: + LA95_295 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == IDENTIFIER: + LA95_296 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == HEX_LITERAL: + LA95_297 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == OCTAL_LITERAL: + LA95_298 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == DECIMAL_LITERAL: + LA95_299 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == CHARACTER_LITERAL: + LA95_300 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == STRING_LITERAL: + LA95_301 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == FLOATING_POINT_LITERAL: + LA95_302 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 71: + LA95_303 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 72: + LA95_304 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 65 or LA95 == 67 or LA95 == 68 or LA95 == 76 or LA95 == 77 or LA95 == 78: + LA95_305 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + elif LA95 == 73: + LA95_306 = self.input.LA(3) + + if (self.synpred187()) : + alt95 = 1 + + + + elif LA95 == 25 or LA95 == 26 or LA95 == 29 or LA95 == 30 or LA95 == 31 or LA95 == 32 or LA95 == 33 or LA95 == 34 or LA95 == 35 or LA95 == 36 or LA95 == 37 or LA95 == 38 or LA95 == 39 or LA95 == 40 or LA95 == 41 or LA95 == 42 or LA95 == 43 or LA95 == 45 or LA95 == 46 or LA95 == 48 or LA95 == 49 or LA95 == 50 or LA95 == 51 or LA95 == 52 or LA95 == 53 or LA95 == 54 or LA95 == 55 or LA95 == 56 or LA95 == 57 or LA95 == 58 or LA95 == 59 or LA95 == 60 or LA95 == 102 or LA95 == 103 or LA95 == 104 or LA95 == 105 or LA95 == 106 or LA95 == 107 or LA95 == 109 or LA95 == 110 or LA95 == 111 or LA95 == 112 or LA95 == 113 or LA95 == 114 or LA95 == 115 or LA95 == 116: + alt95 = 1 + + if alt95 == 1: + # C.g:0:0: statement + self.following.append(self.FOLLOW_statement_in_statement_list2227) + self.statement() + self.following.pop() + if self.failed: + return + + + else: + if cnt95 >= 1: + break #loop95 + + if self.backtracking > 0: + self.failed = True + return + + eee = EarlyExitException(95, self.input) + raise eee + + cnt95 += 1 + + + + + + + except RecognitionException, re: + self.reportError(re) + self.recover(self.input, re) + finally: + if self.backtracking > 0: + self.memoize(self.input, 67, statement_list_StartIndex) + + pass + + return + + # $ANTLR end statement_list + + class expression_statement_return(object): + def __init__(self): + self.start = None + self.stop = None + + + + # $ANTLR start expression_statement + # C.g:508:1: expression_statement : ( ';' | expression ';' ); + def expression_statement(self, ): + + retval = self.expression_statement_return() + retval.start = self.input.LT(1) + expression_statement_StartIndex = self.input.index() + try: + try: + if self.backtracking > 0 and self.alreadyParsedRule(self.input, 68): + return retval + + # C.g:509:2: ( ';' | expression ';' ) + alt96 = 2 + LA96_0 = self.input.LA(1) + + if (LA96_0 == 25) : + alt96 = 1 + elif ((IDENTIFIER <= LA96_0 <= FLOATING_POINT_LITERAL) or LA96_0 == 61 or LA96_0 == 65 or (67 <= LA96_0 <= 68) or (71 <= LA96_0 <= 73) or (76 <= LA96_0 <= 78)) : + alt96 = 2 + else: + if self.backtracking > 0: + self.failed = True + return retval + + nvae = NoViableAltException("508:1: expression_statement : ( ';' | expression ';' );", 96, 0, self.input) + + raise nvae + + if alt96 == 1: + # C.g:509:4: ';' + self.match(self.input, 25, self.FOLLOW_25_in_expression_statement2239) + if self.failed: + return retval + + + elif alt96 == 2: + # C.g:510:4: expression ';' + self.following.append(self.FOLLOW_expression_in_expression_statement2244) + self.expression() + self.following.pop() + if self.failed: + return retval + self.match(self.input, 25, self.FOLLOW_25_in_expression_statement2246) + if self.failed: + return retval + + + retval.stop = self.input.LT(-1) + + + except RecognitionException, re: + self.reportError(re) + self.recover(self.input, re) + finally: + if self.backtracking > 0: + self.memoize(self.input, 68, expression_statement_StartIndex) + + pass + + return retval + + # $ANTLR end expression_statement + + + # $ANTLR start selection_statement + # C.g:513:1: selection_statement : ( 'if' '(' e= expression ')' statement ( options {k=1; backtrack=false; } : 'else' statement )? | 'switch' '(' expression ')' statement ); + def selection_statement(self, ): + + selection_statement_StartIndex = self.input.index() + e = None + + + try: + try: + if self.backtracking > 0 and self.alreadyParsedRule(self.input, 69): + return + + # C.g:514:2: ( 'if' '(' e= expression ')' statement ( options {k=1; backtrack=false; } : 'else' statement )? | 'switch' '(' expression ')' statement ) + alt98 = 2 + LA98_0 = self.input.LA(1) + + if (LA98_0 == 107) : + alt98 = 1 + elif (LA98_0 == 109) : + alt98 = 2 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("513:1: selection_statement : ( 'if' '(' e= expression ')' statement ( options {k=1; backtrack=false; } : 'else' statement )? | 'switch' '(' expression ')' statement );", 98, 0, self.input) + + raise nvae + + if alt98 == 1: + # C.g:514:4: 'if' '(' e= expression ')' statement ( options {k=1; backtrack=false; } : 'else' statement )? + self.match(self.input, 107, self.FOLLOW_107_in_selection_statement2257) + if self.failed: + return + self.match(self.input, 61, self.FOLLOW_61_in_selection_statement2259) + if self.failed: + return + self.following.append(self.FOLLOW_expression_in_selection_statement2263) + e = self.expression() + self.following.pop() + if self.failed: + return + self.match(self.input, 62, self.FOLLOW_62_in_selection_statement2265) + if self.failed: + return + if self.backtracking == 0: + self.StorePredicateExpression(e.start.line, e.start.charPositionInLine, e.stop.line, e.stop.charPositionInLine, self.input.toString(e.start,e.stop)) + + self.following.append(self.FOLLOW_statement_in_selection_statement2269) + self.statement() + self.following.pop() + if self.failed: + return + # C.g:514:167: ( options {k=1; backtrack=false; } : 'else' statement )? + alt97 = 2 + LA97_0 = self.input.LA(1) + + if (LA97_0 == 108) : + alt97 = 1 + if alt97 == 1: + # C.g:514:200: 'else' statement + self.match(self.input, 108, self.FOLLOW_108_in_selection_statement2284) + if self.failed: + return + self.following.append(self.FOLLOW_statement_in_selection_statement2286) + self.statement() + self.following.pop() + if self.failed: + return + + + + + + elif alt98 == 2: + # C.g:515:4: 'switch' '(' expression ')' statement + self.match(self.input, 109, self.FOLLOW_109_in_selection_statement2293) + if self.failed: + return + self.match(self.input, 61, self.FOLLOW_61_in_selection_statement2295) + if self.failed: + return + self.following.append(self.FOLLOW_expression_in_selection_statement2297) + self.expression() + self.following.pop() + if self.failed: + return + self.match(self.input, 62, self.FOLLOW_62_in_selection_statement2299) + if self.failed: + return + self.following.append(self.FOLLOW_statement_in_selection_statement2301) + self.statement() + self.following.pop() + if self.failed: + return + + + + except RecognitionException, re: + self.reportError(re) + self.recover(self.input, re) + finally: + if self.backtracking > 0: + self.memoize(self.input, 69, selection_statement_StartIndex) + + pass + + return + + # $ANTLR end selection_statement + + + # $ANTLR start iteration_statement + # C.g:518:1: iteration_statement : ( 'while' '(' e= expression ')' statement | 'do' statement 'while' '(' e= expression ')' ';' | 'for' '(' expression_statement e= expression_statement ( expression )? ')' statement ); + def iteration_statement(self, ): + + iteration_statement_StartIndex = self.input.index() + e = None + + + try: + try: + if self.backtracking > 0 and self.alreadyParsedRule(self.input, 70): + return + + # C.g:519:2: ( 'while' '(' e= expression ')' statement | 'do' statement 'while' '(' e= expression ')' ';' | 'for' '(' expression_statement e= expression_statement ( expression )? ')' statement ) + alt100 = 3 + LA100 = self.input.LA(1) + if LA100 == 110: + alt100 = 1 + elif LA100 == 111: + alt100 = 2 + elif LA100 == 112: + alt100 = 3 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("518:1: iteration_statement : ( 'while' '(' e= expression ')' statement | 'do' statement 'while' '(' e= expression ')' ';' | 'for' '(' expression_statement e= expression_statement ( expression )? ')' statement );", 100, 0, self.input) + + raise nvae + + if alt100 == 1: + # C.g:519:4: 'while' '(' e= expression ')' statement + self.match(self.input, 110, self.FOLLOW_110_in_iteration_statement2312) + if self.failed: + return + self.match(self.input, 61, self.FOLLOW_61_in_iteration_statement2314) + if self.failed: + return + self.following.append(self.FOLLOW_expression_in_iteration_statement2318) + e = self.expression() + self.following.pop() + if self.failed: + return + self.match(self.input, 62, self.FOLLOW_62_in_iteration_statement2320) + if self.failed: + return + self.following.append(self.FOLLOW_statement_in_iteration_statement2322) + self.statement() + self.following.pop() + if self.failed: + return + if self.backtracking == 0: + self.StorePredicateExpression(e.start.line, e.start.charPositionInLine, e.stop.line, e.stop.charPositionInLine, self.input.toString(e.start,e.stop)) + + + + elif alt100 == 2: + # C.g:520:4: 'do' statement 'while' '(' e= expression ')' ';' + self.match(self.input, 111, self.FOLLOW_111_in_iteration_statement2329) + if self.failed: + return + self.following.append(self.FOLLOW_statement_in_iteration_statement2331) + self.statement() + self.following.pop() + if self.failed: + return + self.match(self.input, 110, self.FOLLOW_110_in_iteration_statement2333) + if self.failed: + return + self.match(self.input, 61, self.FOLLOW_61_in_iteration_statement2335) + if self.failed: + return + self.following.append(self.FOLLOW_expression_in_iteration_statement2339) + e = self.expression() + self.following.pop() + if self.failed: + return + self.match(self.input, 62, self.FOLLOW_62_in_iteration_statement2341) + if self.failed: + return + self.match(self.input, 25, self.FOLLOW_25_in_iteration_statement2343) + if self.failed: + return + if self.backtracking == 0: + self.StorePredicateExpression(e.start.line, e.start.charPositionInLine, e.stop.line, e.stop.charPositionInLine, self.input.toString(e.start,e.stop)) + + + + elif alt100 == 3: + # C.g:521:4: 'for' '(' expression_statement e= expression_statement ( expression )? ')' statement + self.match(self.input, 112, self.FOLLOW_112_in_iteration_statement2350) + if self.failed: + return + self.match(self.input, 61, self.FOLLOW_61_in_iteration_statement2352) + if self.failed: + return + self.following.append(self.FOLLOW_expression_statement_in_iteration_statement2354) + self.expression_statement() + self.following.pop() + if self.failed: + return + self.following.append(self.FOLLOW_expression_statement_in_iteration_statement2358) + e = self.expression_statement() + self.following.pop() + if self.failed: + return + # C.g:521:58: ( expression )? + alt99 = 2 + LA99_0 = self.input.LA(1) + + if ((IDENTIFIER <= LA99_0 <= FLOATING_POINT_LITERAL) or LA99_0 == 61 or LA99_0 == 65 or (67 <= LA99_0 <= 68) or (71 <= LA99_0 <= 73) or (76 <= LA99_0 <= 78)) : + alt99 = 1 + if alt99 == 1: + # C.g:0:0: expression + self.following.append(self.FOLLOW_expression_in_iteration_statement2360) + self.expression() + self.following.pop() + if self.failed: + return + + + + self.match(self.input, 62, self.FOLLOW_62_in_iteration_statement2363) + if self.failed: + return + self.following.append(self.FOLLOW_statement_in_iteration_statement2365) + self.statement() + self.following.pop() + if self.failed: + return + if self.backtracking == 0: + self.StorePredicateExpression(e.start.line, e.start.charPositionInLine, e.stop.line, e.stop.charPositionInLine, self.input.toString(e.start,e.stop)) + + + + + except RecognitionException, re: + self.reportError(re) + self.recover(self.input, re) + finally: + if self.backtracking > 0: + self.memoize(self.input, 70, iteration_statement_StartIndex) + + pass + + return + + # $ANTLR end iteration_statement + + + # $ANTLR start jump_statement + # C.g:524:1: jump_statement : ( 'goto' IDENTIFIER ';' | 'continue' ';' | 'break' ';' | 'return' ';' | 'return' expression ';' ); + def jump_statement(self, ): + + jump_statement_StartIndex = self.input.index() + try: + try: + if self.backtracking > 0 and self.alreadyParsedRule(self.input, 71): + return + + # C.g:525:2: ( 'goto' IDENTIFIER ';' | 'continue' ';' | 'break' ';' | 'return' ';' | 'return' expression ';' ) + alt101 = 5 + LA101 = self.input.LA(1) + if LA101 == 113: + alt101 = 1 + elif LA101 == 114: + alt101 = 2 + elif LA101 == 115: + alt101 = 3 + elif LA101 == 116: + LA101_4 = self.input.LA(2) + + if (LA101_4 == 25) : + alt101 = 4 + elif ((IDENTIFIER <= LA101_4 <= FLOATING_POINT_LITERAL) or LA101_4 == 61 or LA101_4 == 65 or (67 <= LA101_4 <= 68) or (71 <= LA101_4 <= 73) or (76 <= LA101_4 <= 78)) : + alt101 = 5 + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("524:1: jump_statement : ( 'goto' IDENTIFIER ';' | 'continue' ';' | 'break' ';' | 'return' ';' | 'return' expression ';' );", 101, 4, self.input) + + raise nvae + + else: + if self.backtracking > 0: + self.failed = True + return + + nvae = NoViableAltException("524:1: jump_statement : ( 'goto' IDENTIFIER ';' | 'continue' ';' | 'break' ';' | 'return' ';' | 'return' expression ';' );", 101, 0, self.input) + + raise nvae + + if alt101 == 1: + # C.g:525:4: 'goto' IDENTIFIER ';' + self.match(self.input, 113, self.FOLLOW_113_in_jump_statement2378) + if self.failed: + return + self.match(self.input, IDENTIFIER, self.FOLLOW_IDENTIFIER_in_jump_statement2380) + if self.failed: + return + self.match(self.input, 25, self.FOLLOW_25_in_jump_statement2382) + if self.failed: + return + + + elif alt101 == 2: + # C.g:526:4: 'continue' ';' + self.match(self.input, 114, self.FOLLOW_114_in_jump_statement2387) + if self.failed: + return + self.match(self.input, 25, self.FOLLOW_25_in_jump_statement2389) + if self.failed: + return + + + elif alt101 == 3: + # C.g:527:4: 'break' ';' + self.match(self.input, 115, self.FOLLOW_115_in_jump_statement2394) + if self.failed: + return + self.match(self.input, 25, self.FOLLOW_25_in_jump_statement2396) + if self.failed: + return + + + elif alt101 == 4: + # C.g:528:4: 'return' ';' + self.match(self.input, 116, self.FOLLOW_116_in_jump_statement2401) + if self.failed: + return + self.match(self.input, 25, self.FOLLOW_25_in_jump_statement2403) + if self.failed: + return + + + elif alt101 == 5: + # C.g:529:4: 'return' expression ';' + self.match(self.input, 116, self.FOLLOW_116_in_jump_statement2408) + if self.failed: + return + self.following.append(self.FOLLOW_expression_in_jump_statement2410) + self.expression() + self.following.pop() + if self.failed: + return + self.match(self.input, 25, self.FOLLOW_25_in_jump_statement2412) + if self.failed: + return + + + + except RecognitionException, re: + self.reportError(re) + self.recover(self.input, re) + finally: + if self.backtracking > 0: + self.memoize(self.input, 71, jump_statement_StartIndex) + + pass + + return + + # $ANTLR end jump_statement + + # $ANTLR start synpred2 + def synpred2_fragment(self, ): + # C.g:67:6: ( declaration_specifiers ) + # C.g:67:6: declaration_specifiers + self.following.append(self.FOLLOW_declaration_specifiers_in_synpred290) + self.declaration_specifiers() + self.following.pop() + if self.failed: + return + + + # $ANTLR end synpred2 + + + + # $ANTLR start synpred4 + def synpred4_fragment(self, ): + # C.g:67:4: ( ( declaration_specifiers )? declarator ( declaration )* '{' ) + # C.g:67:6: ( declaration_specifiers )? declarator ( declaration )* '{' + # C.g:67:6: ( declaration_specifiers )? + alt102 = 2 + LA102 = self.input.LA(1) + if LA102 == 29 or LA102 == 30 or LA102 == 31 or LA102 == 32 or LA102 == 33 or LA102 == 34 or LA102 == 35 or LA102 == 36 or LA102 == 37 or LA102 == 38 or LA102 == 39 or LA102 == 40 or LA102 == 41 or LA102 == 42 or LA102 == 45 or LA102 == 46 or LA102 == 48 or LA102 == 49 or LA102 == 50 or LA102 == 51 or LA102 == 52 or LA102 == 53 or LA102 == 54 or LA102 == 55 or LA102 == 56 or LA102 == 57: + alt102 = 1 + elif LA102 == IDENTIFIER: + LA102 = self.input.LA(2) + if LA102 == 65: + alt102 = 1 + elif LA102 == 58: + LA102_21 = self.input.LA(3) + + if (self.synpred2()) : + alt102 = 1 + elif LA102 == 59: + LA102_22 = self.input.LA(3) + + if (self.synpred2()) : + alt102 = 1 + elif LA102 == 60: + LA102_23 = self.input.LA(3) + + if (self.synpred2()) : + alt102 = 1 + elif LA102 == IDENTIFIER: + LA102_24 = self.input.LA(3) + + if (self.synpred2()) : + alt102 = 1 + elif LA102 == 61: + LA102_25 = self.input.LA(3) + + if (self.synpred2()) : + alt102 = 1 + elif LA102 == 29 or LA102 == 30 or LA102 == 31 or LA102 == 32 or LA102 == 33: + LA102_26 = self.input.LA(3) + + if (self.synpred2()) : + alt102 = 1 + elif LA102 == 34: + LA102_27 = self.input.LA(3) + + if (self.synpred2()) : + alt102 = 1 + elif LA102 == 35: + LA102_28 = self.input.LA(3) + + if (self.synpred2()) : + alt102 = 1 + elif LA102 == 36: + LA102_29 = self.input.LA(3) + + if (self.synpred2()) : + alt102 = 1 + elif LA102 == 37: + LA102_30 = self.input.LA(3) + + if (self.synpred2()) : + alt102 = 1 + elif LA102 == 38: + LA102_31 = self.input.LA(3) + + if (self.synpred2()) : + alt102 = 1 + elif LA102 == 39: + LA102_32 = self.input.LA(3) + + if (self.synpred2()) : + alt102 = 1 + elif LA102 == 40: + LA102_33 = self.input.LA(3) + + if (self.synpred2()) : + alt102 = 1 + elif LA102 == 41: + LA102_34 = self.input.LA(3) + + if (self.synpred2()) : + alt102 = 1 + elif LA102 == 42: + LA102_35 = self.input.LA(3) + + if (self.synpred2()) : + alt102 = 1 + elif LA102 == 45 or LA102 == 46: + LA102_36 = self.input.LA(3) + + if (self.synpred2()) : + alt102 = 1 + elif LA102 == 48: + LA102_37 = self.input.LA(3) + + if (self.synpred2()) : + alt102 = 1 + elif LA102 == 49 or LA102 == 50 or LA102 == 51 or LA102 == 52 or LA102 == 53 or LA102 == 54 or LA102 == 55 or LA102 == 56 or LA102 == 57: + LA102_38 = self.input.LA(3) + + if (self.synpred2()) : + alt102 = 1 + elif LA102 == 58: + LA102_14 = self.input.LA(2) + + if (self.synpred2()) : + alt102 = 1 + elif LA102 == 59: + LA102_16 = self.input.LA(2) + + if (self.synpred2()) : + alt102 = 1 + elif LA102 == 60: + LA102_17 = self.input.LA(2) + + if (self.synpred2()) : + alt102 = 1 + if alt102 == 1: + # C.g:0:0: declaration_specifiers + self.following.append(self.FOLLOW_declaration_specifiers_in_synpred490) + self.declaration_specifiers() + self.following.pop() + if self.failed: + return + + + + self.following.append(self.FOLLOW_declarator_in_synpred493) + self.declarator() + self.following.pop() + if self.failed: + return + # C.g:67:41: ( declaration )* + while True: #loop103 + alt103 = 2 + LA103_0 = self.input.LA(1) + + if (LA103_0 == IDENTIFIER or LA103_0 == 26 or (29 <= LA103_0 <= 42) or (45 <= LA103_0 <= 46) or (48 <= LA103_0 <= 60)) : + alt103 = 1 + + + if alt103 == 1: + # C.g:0:0: declaration + self.following.append(self.FOLLOW_declaration_in_synpred495) + self.declaration() + self.following.pop() + if self.failed: + return + + + else: + break #loop103 + + + self.match(self.input, 43, self.FOLLOW_43_in_synpred498) + if self.failed: + return + + + # $ANTLR end synpred4 + + + + # $ANTLR start synpred5 + def synpred5_fragment(self, ): + # C.g:68:4: ( declaration ) + # C.g:68:4: declaration + self.following.append(self.FOLLOW_declaration_in_synpred5108) + self.declaration() + self.following.pop() + if self.failed: + return + + + # $ANTLR end synpred5 + + + + # $ANTLR start synpred7 + def synpred7_fragment(self, ): + # C.g:94:6: ( declaration_specifiers ) + # C.g:94:6: declaration_specifiers + self.following.append(self.FOLLOW_declaration_specifiers_in_synpred7147) + self.declaration_specifiers() + self.following.pop() + if self.failed: + return + + + # $ANTLR end synpred7 + + + + # $ANTLR start synpred10 + def synpred10_fragment(self, ): + # C.g:115:18: ( declaration_specifiers ) + # C.g:115:18: declaration_specifiers + self.following.append(self.FOLLOW_declaration_specifiers_in_synpred10197) + self.declaration_specifiers() + self.following.pop() + if self.failed: + return + + + # $ANTLR end synpred10 + + + + # $ANTLR start synpred14 + def synpred14_fragment(self, ): + # C.g:132:7: ( type_specifier ) + # C.g:132:7: type_specifier + self.following.append(self.FOLLOW_type_specifier_in_synpred14262) + self.type_specifier() + self.following.pop() + if self.failed: + return + + + # $ANTLR end synpred14 + + + + # $ANTLR start synpred15 + def synpred15_fragment(self, ): + # C.g:133:13: ( type_qualifier ) + # C.g:133:13: type_qualifier + self.following.append(self.FOLLOW_type_qualifier_in_synpred15276) + self.type_qualifier() + self.following.pop() + if self.failed: + return + + + # $ANTLR end synpred15 + + + + # $ANTLR start synpred33 + def synpred33_fragment(self, ): + # C.g:173:16: ( type_qualifier ) + # C.g:173:16: type_qualifier + self.following.append(self.FOLLOW_type_qualifier_in_synpred33434) + self.type_qualifier() + self.following.pop() + if self.failed: + return + + + # $ANTLR end synpred33 + + + + # $ANTLR start synpred34 + def synpred34_fragment(self, ): + # C.g:173:4: ( IDENTIFIER ( type_qualifier )* declarator ) + # C.g:173:5: IDENTIFIER ( type_qualifier )* declarator + self.match(self.input, IDENTIFIER, self.FOLLOW_IDENTIFIER_in_synpred34432) + if self.failed: + return + # C.g:173:16: ( type_qualifier )* + while True: #loop106 + alt106 = 2 + LA106 = self.input.LA(1) + if LA106 == 58: + LA106_2 = self.input.LA(2) + + if (self.synpred33()) : + alt106 = 1 + + + elif LA106 == 59: + LA106_3 = self.input.LA(2) + + if (self.synpred33()) : + alt106 = 1 + + + elif LA106 == 60: + LA106_4 = self.input.LA(2) + + if (self.synpred33()) : + alt106 = 1 + + + elif LA106 == 49 or LA106 == 50 or LA106 == 51 or LA106 == 52 or LA106 == 53 or LA106 == 54 or LA106 == 55 or LA106 == 56 or LA106 == 57: + alt106 = 1 + + if alt106 == 1: + # C.g:0:0: type_qualifier + self.following.append(self.FOLLOW_type_qualifier_in_synpred34434) + self.type_qualifier() + self.following.pop() + if self.failed: + return + + + else: + break #loop106 + + + self.following.append(self.FOLLOW_declarator_in_synpred34437) + self.declarator() + self.following.pop() + if self.failed: + return + + + # $ANTLR end synpred34 + + + + # $ANTLR start synpred39 + def synpred39_fragment(self, ): + # C.g:201:6: ( type_qualifier ) + # C.g:201:6: type_qualifier + self.following.append(self.FOLLOW_type_qualifier_in_synpred39556) + self.type_qualifier() + self.following.pop() + if self.failed: + return + + + # $ANTLR end synpred39 + + + + # $ANTLR start synpred40 + def synpred40_fragment(self, ): + # C.g:201:23: ( type_specifier ) + # C.g:201:23: type_specifier + self.following.append(self.FOLLOW_type_specifier_in_synpred40560) + self.type_specifier() + self.following.pop() + if self.failed: + return + + + # $ANTLR end synpred40 + + + + # $ANTLR start synpred65 + def synpred65_fragment(self, ): + # C.g:244:4: ( ( pointer )? ( 'EFIAPI' )? ( 'EFI_BOOTSERVICE' )? ( 'EFI_RUNTIMESERVICE' )? direct_declarator ) + # C.g:244:4: ( pointer )? ( 'EFIAPI' )? ( 'EFI_BOOTSERVICE' )? ( 'EFI_RUNTIMESERVICE' )? direct_declarator + # C.g:244:4: ( pointer )? + alt111 = 2 + LA111_0 = self.input.LA(1) + + if (LA111_0 == 65) : + alt111 = 1 + if alt111 == 1: + # C.g:0:0: pointer + self.following.append(self.FOLLOW_pointer_in_synpred65769) + self.pointer() + self.following.pop() + if self.failed: + return + + + + # C.g:244:13: ( 'EFIAPI' )? + alt112 = 2 + LA112_0 = self.input.LA(1) + + if (LA112_0 == 58) : + alt112 = 1 + if alt112 == 1: + # C.g:244:14: 'EFIAPI' + self.match(self.input, 58, self.FOLLOW_58_in_synpred65773) + if self.failed: + return + + + + # C.g:244:25: ( 'EFI_BOOTSERVICE' )? + alt113 = 2 + LA113_0 = self.input.LA(1) + + if (LA113_0 == 59) : + alt113 = 1 + if alt113 == 1: + # C.g:244:26: 'EFI_BOOTSERVICE' + self.match(self.input, 59, self.FOLLOW_59_in_synpred65778) + if self.failed: + return + + + + # C.g:244:46: ( 'EFI_RUNTIMESERVICE' )? + alt114 = 2 + LA114_0 = self.input.LA(1) + + if (LA114_0 == 60) : + alt114 = 1 + if alt114 == 1: + # C.g:244:47: 'EFI_RUNTIMESERVICE' + self.match(self.input, 60, self.FOLLOW_60_in_synpred65783) + if self.failed: + return + + + + self.following.append(self.FOLLOW_direct_declarator_in_synpred65787) + self.direct_declarator() + self.following.pop() + if self.failed: + return + + + # $ANTLR end synpred65 + + + + # $ANTLR start synpred66 + def synpred66_fragment(self, ): + # C.g:250:15: ( declarator_suffix ) + # C.g:250:15: declarator_suffix + self.following.append(self.FOLLOW_declarator_suffix_in_synpred66806) + self.declarator_suffix() + self.following.pop() + if self.failed: + return + + + # $ANTLR end synpred66 + + + + # $ANTLR start synpred68 + def synpred68_fragment(self, ): + # C.g:251:9: ( 'EFIAPI' ) + # C.g:251:9: 'EFIAPI' + self.match(self.input, 58, self.FOLLOW_58_in_synpred68815) + if self.failed: + return + + + # $ANTLR end synpred68 + + + + # $ANTLR start synpred69 + def synpred69_fragment(self, ): + # C.g:251:35: ( declarator_suffix ) + # C.g:251:35: declarator_suffix + self.following.append(self.FOLLOW_declarator_suffix_in_synpred69823) + self.declarator_suffix() + self.following.pop() + if self.failed: + return + + + # $ANTLR end synpred69 + + + + # $ANTLR start synpred72 + def synpred72_fragment(self, ): + # C.g:257:9: ( '(' parameter_type_list ')' ) + # C.g:257:9: '(' parameter_type_list ')' + self.match(self.input, 61, self.FOLLOW_61_in_synpred72863) + if self.failed: + return + self.following.append(self.FOLLOW_parameter_type_list_in_synpred72865) + self.parameter_type_list() + self.following.pop() + if self.failed: + return + self.match(self.input, 62, self.FOLLOW_62_in_synpred72867) + if self.failed: + return + + + # $ANTLR end synpred72 + + + + # $ANTLR start synpred73 + def synpred73_fragment(self, ): + # C.g:258:9: ( '(' identifier_list ')' ) + # C.g:258:9: '(' identifier_list ')' + self.match(self.input, 61, self.FOLLOW_61_in_synpred73877) + if self.failed: + return + self.following.append(self.FOLLOW_identifier_list_in_synpred73879) + self.identifier_list() + self.following.pop() + if self.failed: + return + self.match(self.input, 62, self.FOLLOW_62_in_synpred73881) + if self.failed: + return + + + # $ANTLR end synpred73 + + + + # $ANTLR start synpred74 + def synpred74_fragment(self, ): + # C.g:263:8: ( type_qualifier ) + # C.g:263:8: type_qualifier + self.following.append(self.FOLLOW_type_qualifier_in_synpred74906) + self.type_qualifier() + self.following.pop() + if self.failed: + return + + + # $ANTLR end synpred74 + + + + # $ANTLR start synpred75 + def synpred75_fragment(self, ): + # C.g:263:24: ( pointer ) + # C.g:263:24: pointer + self.following.append(self.FOLLOW_pointer_in_synpred75909) + self.pointer() + self.following.pop() + if self.failed: + return + + + # $ANTLR end synpred75 + + + + # $ANTLR start synpred76 + def synpred76_fragment(self, ): + # C.g:263:4: ( '*' ( type_qualifier )+ ( pointer )? ) + # C.g:263:4: '*' ( type_qualifier )+ ( pointer )? + self.match(self.input, 65, self.FOLLOW_65_in_synpred76904) + if self.failed: + return + # C.g:263:8: ( type_qualifier )+ + cnt116 = 0 + while True: #loop116 + alt116 = 2 + LA116_0 = self.input.LA(1) + + if ((49 <= LA116_0 <= 60)) : + alt116 = 1 + + + if alt116 == 1: + # C.g:0:0: type_qualifier + self.following.append(self.FOLLOW_type_qualifier_in_synpred76906) + self.type_qualifier() + self.following.pop() + if self.failed: + return + + + else: + if cnt116 >= 1: + break #loop116 + + if self.backtracking > 0: + self.failed = True + return + + eee = EarlyExitException(116, self.input) + raise eee + + cnt116 += 1 + + + # C.g:263:24: ( pointer )? + alt117 = 2 + LA117_0 = self.input.LA(1) + + if (LA117_0 == 65) : + alt117 = 1 + if alt117 == 1: + # C.g:0:0: pointer + self.following.append(self.FOLLOW_pointer_in_synpred76909) + self.pointer() + self.following.pop() + if self.failed: + return + + + + + + # $ANTLR end synpred76 + + + + # $ANTLR start synpred77 + def synpred77_fragment(self, ): + # C.g:264:4: ( '*' pointer ) + # C.g:264:4: '*' pointer + self.match(self.input, 65, self.FOLLOW_65_in_synpred77915) + if self.failed: + return + self.following.append(self.FOLLOW_pointer_in_synpred77917) + self.pointer() + self.following.pop() + if self.failed: + return + + + # $ANTLR end synpred77 + + + + # $ANTLR start synpred80 + def synpred80_fragment(self, ): + # C.g:273:32: ( 'OPTIONAL' ) + # C.g:273:32: 'OPTIONAL' + self.match(self.input, 53, self.FOLLOW_53_in_synpred80962) + if self.failed: + return + + + # $ANTLR end synpred80 + + + + # $ANTLR start synpred81 + def synpred81_fragment(self, ): + # C.g:273:27: ( ',' ( 'OPTIONAL' )? parameter_declaration ) + # C.g:273:27: ',' ( 'OPTIONAL' )? parameter_declaration + self.match(self.input, 27, self.FOLLOW_27_in_synpred81959) + if self.failed: + return + # C.g:273:31: ( 'OPTIONAL' )? + alt119 = 2 + LA119_0 = self.input.LA(1) + + if (LA119_0 == 53) : + LA119_1 = self.input.LA(2) + + if (self.synpred80()) : + alt119 = 1 + if alt119 == 1: + # C.g:273:32: 'OPTIONAL' + self.match(self.input, 53, self.FOLLOW_53_in_synpred81962) + if self.failed: + return + + + + self.following.append(self.FOLLOW_parameter_declaration_in_synpred81966) + self.parameter_declaration() + self.following.pop() + if self.failed: + return + + + # $ANTLR end synpred81 + + + + # $ANTLR start synpred82 + def synpred82_fragment(self, ): + # C.g:277:28: ( declarator ) + # C.g:277:28: declarator + self.following.append(self.FOLLOW_declarator_in_synpred82982) + self.declarator() + self.following.pop() + if self.failed: + return + + + # $ANTLR end synpred82 + + + + # $ANTLR start synpred83 + def synpred83_fragment(self, ): + # C.g:277:39: ( abstract_declarator ) + # C.g:277:39: abstract_declarator + self.following.append(self.FOLLOW_abstract_declarator_in_synpred83984) + self.abstract_declarator() + self.following.pop() + if self.failed: + return + + + # $ANTLR end synpred83 + + + + # $ANTLR start synpred85 + def synpred85_fragment(self, ): + # C.g:277:4: ( declaration_specifiers ( declarator | abstract_declarator )* ( 'OPTIONAL' )? ) + # C.g:277:4: declaration_specifiers ( declarator | abstract_declarator )* ( 'OPTIONAL' )? + self.following.append(self.FOLLOW_declaration_specifiers_in_synpred85979) + self.declaration_specifiers() + self.following.pop() + if self.failed: + return + # C.g:277:27: ( declarator | abstract_declarator )* + while True: #loop120 + alt120 = 3 + LA120 = self.input.LA(1) + if LA120 == 65: + LA120_3 = self.input.LA(2) + + if (self.synpred82()) : + alt120 = 1 + elif (self.synpred83()) : + alt120 = 2 + + + elif LA120 == IDENTIFIER or LA120 == 58 or LA120 == 59 or LA120 == 60: + alt120 = 1 + elif LA120 == 61: + LA120 = self.input.LA(2) + if LA120 == 29 or LA120 == 30 or LA120 == 31 or LA120 == 32 or LA120 == 33 or LA120 == 34 or LA120 == 35 or LA120 == 36 or LA120 == 37 or LA120 == 38 or LA120 == 39 or LA120 == 40 or LA120 == 41 or LA120 == 42 or LA120 == 45 or LA120 == 46 or LA120 == 48 or LA120 == 49 or LA120 == 50 or LA120 == 51 or LA120 == 52 or LA120 == 53 or LA120 == 54 or LA120 == 55 or LA120 == 56 or LA120 == 57 or LA120 == 62 or LA120 == 63: + alt120 = 2 + elif LA120 == 58: + LA120_21 = self.input.LA(3) + + if (self.synpred82()) : + alt120 = 1 + elif (self.synpred83()) : + alt120 = 2 + + + elif LA120 == 65: + LA120_22 = self.input.LA(3) + + if (self.synpred82()) : + alt120 = 1 + elif (self.synpred83()) : + alt120 = 2 + + + elif LA120 == 59: + LA120_23 = self.input.LA(3) + + if (self.synpred82()) : + alt120 = 1 + elif (self.synpred83()) : + alt120 = 2 + + + elif LA120 == 60: + LA120_24 = self.input.LA(3) + + if (self.synpred82()) : + alt120 = 1 + elif (self.synpred83()) : + alt120 = 2 + + + elif LA120 == IDENTIFIER: + LA120_25 = self.input.LA(3) + + if (self.synpred82()) : + alt120 = 1 + elif (self.synpred83()) : + alt120 = 2 + + + elif LA120 == 61: + LA120_26 = self.input.LA(3) + + if (self.synpred82()) : + alt120 = 1 + elif (self.synpred83()) : + alt120 = 2 + + + + elif LA120 == 63: + alt120 = 2 + + if alt120 == 1: + # C.g:277:28: declarator + self.following.append(self.FOLLOW_declarator_in_synpred85982) + self.declarator() + self.following.pop() + if self.failed: + return + + + elif alt120 == 2: + # C.g:277:39: abstract_declarator + self.following.append(self.FOLLOW_abstract_declarator_in_synpred85984) + self.abstract_declarator() + self.following.pop() + if self.failed: + return + + + else: + break #loop120 + + + # C.g:277:61: ( 'OPTIONAL' )? + alt121 = 2 + LA121_0 = self.input.LA(1) + + if (LA121_0 == 53) : + alt121 = 1 + if alt121 == 1: + # C.g:277:62: 'OPTIONAL' + self.match(self.input, 53, self.FOLLOW_53_in_synpred85989) + if self.failed: + return + + + + + + # $ANTLR end synpred85 + + + + # $ANTLR start synpred89 + def synpred89_fragment(self, ): + # C.g:288:4: ( specifier_qualifier_list ( abstract_declarator )? ) + # C.g:288:4: specifier_qualifier_list ( abstract_declarator )? + self.following.append(self.FOLLOW_specifier_qualifier_list_in_synpred891031) + self.specifier_qualifier_list() + self.following.pop() + if self.failed: + return + # C.g:288:29: ( abstract_declarator )? + alt122 = 2 + LA122_0 = self.input.LA(1) + + if (LA122_0 == 61 or LA122_0 == 63 or LA122_0 == 65) : + alt122 = 1 + if alt122 == 1: + # C.g:0:0: abstract_declarator + self.following.append(self.FOLLOW_abstract_declarator_in_synpred891033) + self.abstract_declarator() + self.following.pop() + if self.failed: + return + + + + + + # $ANTLR end synpred89 + + + + # $ANTLR start synpred90 + def synpred90_fragment(self, ): + # C.g:293:12: ( direct_abstract_declarator ) + # C.g:293:12: direct_abstract_declarator + self.following.append(self.FOLLOW_direct_abstract_declarator_in_synpred901052) + self.direct_abstract_declarator() + self.following.pop() + if self.failed: + return + + + # $ANTLR end synpred90 + + + + # $ANTLR start synpred92 + def synpred92_fragment(self, ): + # C.g:298:6: ( '(' abstract_declarator ')' ) + # C.g:298:6: '(' abstract_declarator ')' + self.match(self.input, 61, self.FOLLOW_61_in_synpred921071) + if self.failed: + return + self.following.append(self.FOLLOW_abstract_declarator_in_synpred921073) + self.abstract_declarator() + self.following.pop() + if self.failed: + return + self.match(self.input, 62, self.FOLLOW_62_in_synpred921075) + if self.failed: + return + + + # $ANTLR end synpred92 + + + + # $ANTLR start synpred93 + def synpred93_fragment(self, ): + # C.g:298:65: ( abstract_declarator_suffix ) + # C.g:298:65: abstract_declarator_suffix + self.following.append(self.FOLLOW_abstract_declarator_suffix_in_synpred931083) + self.abstract_declarator_suffix() + self.following.pop() + if self.failed: + return + + + # $ANTLR end synpred93 + + + + # $ANTLR start synpred108 + def synpred108_fragment(self, ): + # C.g:333:4: ( '(' type_name ')' cast_expression ) + # C.g:333:4: '(' type_name ')' cast_expression + self.match(self.input, 61, self.FOLLOW_61_in_synpred1081267) + if self.failed: + return + self.following.append(self.FOLLOW_type_name_in_synpred1081269) + self.type_name() + self.following.pop() + if self.failed: + return + self.match(self.input, 62, self.FOLLOW_62_in_synpred1081271) + if self.failed: + return + self.following.append(self.FOLLOW_cast_expression_in_synpred1081273) + self.cast_expression() + self.following.pop() + if self.failed: + return + + + # $ANTLR end synpred108 + + + + # $ANTLR start synpred113 + def synpred113_fragment(self, ): + # C.g:342:4: ( 'sizeof' unary_expression ) + # C.g:342:4: 'sizeof' unary_expression + self.match(self.input, 73, self.FOLLOW_73_in_synpred1131315) + if self.failed: + return + self.following.append(self.FOLLOW_unary_expression_in_synpred1131317) + self.unary_expression() + self.following.pop() + if self.failed: + return + + + # $ANTLR end synpred113 + + + + # $ANTLR start synpred116 + def synpred116_fragment(self, ): + # C.g:356:13: ( '(' argument_expression_list ')' ) + # C.g:356:13: '(' argument_expression_list ')' + self.match(self.input, 61, self.FOLLOW_61_in_synpred1161405) + if self.failed: + return + self.following.append(self.FOLLOW_argument_expression_list_in_synpred1161409) + self.argument_expression_list() + self.following.pop() + if self.failed: + return + self.match(self.input, 62, self.FOLLOW_62_in_synpred1161413) + if self.failed: + return + + + # $ANTLR end synpred116 + + + + # $ANTLR start synpred117 + def synpred117_fragment(self, ): + # C.g:357:13: ( '(' macro_parameter_list ')' ) + # C.g:357:13: '(' macro_parameter_list ')' + self.match(self.input, 61, self.FOLLOW_61_in_synpred1171429) + if self.failed: + return + self.following.append(self.FOLLOW_macro_parameter_list_in_synpred1171431) + self.macro_parameter_list() + self.following.pop() + if self.failed: + return + self.match(self.input, 62, self.FOLLOW_62_in_synpred1171433) + if self.failed: + return + + + # $ANTLR end synpred117 + + + + # $ANTLR start synpred119 + def synpred119_fragment(self, ): + # C.g:359:13: ( '*' IDENTIFIER ) + # C.g:359:13: '*' IDENTIFIER + self.match(self.input, 65, self.FOLLOW_65_in_synpred1191467) + if self.failed: + return + self.match(self.input, IDENTIFIER, self.FOLLOW_IDENTIFIER_in_synpred1191471) + if self.failed: + return + + + # $ANTLR end synpred119 + + + + # $ANTLR start synpred136 + def synpred136_fragment(self, ): + # C.g:390:20: ( STRING_LITERAL ) + # C.g:390:20: STRING_LITERAL + self.match(self.input, STRING_LITERAL, self.FOLLOW_STRING_LITERAL_in_synpred1361668) + if self.failed: + return + + + # $ANTLR end synpred136 + + + + # $ANTLR start synpred137 + def synpred137_fragment(self, ): + # C.g:390:8: ( ( IDENTIFIER )* ( STRING_LITERAL )+ ) + # C.g:390:8: ( IDENTIFIER )* ( STRING_LITERAL )+ + # C.g:390:8: ( IDENTIFIER )* + while True: #loop125 + alt125 = 2 + LA125_0 = self.input.LA(1) + + if (LA125_0 == IDENTIFIER) : + alt125 = 1 + + + if alt125 == 1: + # C.g:0:0: IDENTIFIER + self.match(self.input, IDENTIFIER, self.FOLLOW_IDENTIFIER_in_synpred1371665) + if self.failed: + return + + + else: + break #loop125 + + + # C.g:390:20: ( STRING_LITERAL )+ + cnt126 = 0 + while True: #loop126 + alt126 = 2 + LA126_0 = self.input.LA(1) + + if (LA126_0 == STRING_LITERAL) : + alt126 = 1 + + + if alt126 == 1: + # C.g:0:0: STRING_LITERAL + self.match(self.input, STRING_LITERAL, self.FOLLOW_STRING_LITERAL_in_synpred1371668) + if self.failed: + return + + + else: + if cnt126 >= 1: + break #loop126 + + if self.backtracking > 0: + self.failed = True + return + + eee = EarlyExitException(126, self.input) + raise eee + + cnt126 += 1 + + + + + # $ANTLR end synpred137 + + + + # $ANTLR start synpred141 + def synpred141_fragment(self, ): + # C.g:405:4: ( lvalue assignment_operator assignment_expression ) + # C.g:405:4: lvalue assignment_operator assignment_expression + self.following.append(self.FOLLOW_lvalue_in_synpred1411729) + self.lvalue() + self.following.pop() + if self.failed: + return + self.following.append(self.FOLLOW_assignment_operator_in_synpred1411731) + self.assignment_operator() + self.following.pop() + if self.failed: + return + self.following.append(self.FOLLOW_assignment_expression_in_synpred1411733) + self.assignment_expression() + self.following.pop() + if self.failed: + return + + + # $ANTLR end synpred141 + + + + # $ANTLR start synpred168 + def synpred168_fragment(self, ): + # C.g:467:4: ( expression_statement ) + # C.g:467:4: expression_statement + self.following.append(self.FOLLOW_expression_statement_in_synpred1682020) + self.expression_statement() + self.following.pop() + if self.failed: + return + + + # $ANTLR end synpred168 + + + + # $ANTLR start synpred172 + def synpred172_fragment(self, ): + # C.g:471:4: ( macro_statement ) + # C.g:471:4: macro_statement + self.following.append(self.FOLLOW_macro_statement_in_synpred1722040) + self.macro_statement() + self.following.pop() + if self.failed: + return + + + # $ANTLR end synpred172 + + + + # $ANTLR start synpred173 + def synpred173_fragment(self, ): + # C.g:472:4: ( asm2_statement ) + # C.g:472:4: asm2_statement + self.following.append(self.FOLLOW_asm2_statement_in_synpred1732045) + self.asm2_statement() + self.following.pop() + if self.failed: + return + + + # $ANTLR end synpred173 + + + + # $ANTLR start synpred180 + def synpred180_fragment(self, ): + # C.g:491:19: ( declaration ) + # C.g:491:19: declaration + self.following.append(self.FOLLOW_declaration_in_synpred1802151) + self.declaration() + self.following.pop() + if self.failed: + return + + + # $ANTLR end synpred180 + + + + # $ANTLR start synpred181 + def synpred181_fragment(self, ): + # C.g:491:33: ( statement_list ) + # C.g:491:33: statement_list + self.following.append(self.FOLLOW_statement_list_in_synpred1812155) + self.statement_list() + self.following.pop() + if self.failed: + return + + + # $ANTLR end synpred181 + + + + # $ANTLR start synpred185 + def synpred185_fragment(self, ): + # C.g:501:8: ( declaration ) + # C.g:501:8: declaration + self.following.append(self.FOLLOW_declaration_in_synpred1852210) + self.declaration() + self.following.pop() + if self.failed: + return + + + # $ANTLR end synpred185 + + + + # $ANTLR start synpred187 + def synpred187_fragment(self, ): + # C.g:505:4: ( statement ) + # C.g:505:4: statement + self.following.append(self.FOLLOW_statement_in_synpred1872227) + self.statement() + self.following.pop() + if self.failed: + return + + + # $ANTLR end synpred187 + + + + def synpred185(self): + self.backtracking += 1 + start = self.input.mark() + self.synpred185_fragment() + success = not self.failed + self.input.rewind(start) + self.backtracking -= 1 + self.failed = False + return success + + def synpred7(self): + self.backtracking += 1 + start = self.input.mark() + self.synpred7_fragment() + success = not self.failed + self.input.rewind(start) + self.backtracking -= 1 + self.failed = False + return success + + def synpred14(self): + self.backtracking += 1 + start = self.input.mark() + self.synpred14_fragment() + success = not self.failed + self.input.rewind(start) + self.backtracking -= 1 + self.failed = False + return success + + def synpred65(self): + self.backtracking += 1 + start = self.input.mark() + self.synpred65_fragment() + success = not self.failed + self.input.rewind(start) + self.backtracking -= 1 + self.failed = False + return success + + def synpred15(self): + self.backtracking += 1 + start = self.input.mark() + self.synpred15_fragment() + success = not self.failed + self.input.rewind(start) + self.backtracking -= 1 + self.failed = False + return success + + def synpred117(self): + self.backtracking += 1 + start = self.input.mark() + self.synpred117_fragment() + success = not self.failed + self.input.rewind(start) + self.backtracking -= 1 + self.failed = False + return success + + def synpred173(self): + self.backtracking += 1 + start = self.input.mark() + self.synpred173_fragment() + success = not self.failed + self.input.rewind(start) + self.backtracking -= 1 + self.failed = False + return success + + def synpred68(self): + self.backtracking += 1 + start = self.input.mark() + self.synpred68_fragment() + success = not self.failed + self.input.rewind(start) + self.backtracking -= 1 + self.failed = False + return success + + def synpred40(self): + self.backtracking += 1 + start = self.input.mark() + self.synpred40_fragment() + success = not self.failed + self.input.rewind(start) + self.backtracking -= 1 + self.failed = False + return success + + def synpred141(self): + self.backtracking += 1 + start = self.input.mark() + self.synpred141_fragment() + success = not self.failed + self.input.rewind(start) + self.backtracking -= 1 + self.failed = False + return success + + def synpred75(self): + self.backtracking += 1 + start = self.input.mark() + self.synpred75_fragment() + success = not self.failed + self.input.rewind(start) + self.backtracking -= 1 + self.failed = False + return success + + def synpred92(self): + self.backtracking += 1 + start = self.input.mark() + self.synpred92_fragment() + success = not self.failed + self.input.rewind(start) + self.backtracking -= 1 + self.failed = False + return success + + def synpred4(self): + self.backtracking += 1 + start = self.input.mark() + self.synpred4_fragment() + success = not self.failed + self.input.rewind(start) + self.backtracking -= 1 + self.failed = False + return success + + def synpred85(self): + self.backtracking += 1 + start = self.input.mark() + self.synpred85_fragment() + success = not self.failed + self.input.rewind(start) + self.backtracking -= 1 + self.failed = False + return success + + def synpred39(self): + self.backtracking += 1 + start = self.input.mark() + self.synpred39_fragment() + success = not self.failed + self.input.rewind(start) + self.backtracking -= 1 + self.failed = False + return success + + def synpred76(self): + self.backtracking += 1 + start = self.input.mark() + self.synpred76_fragment() + success = not self.failed + self.input.rewind(start) + self.backtracking -= 1 + self.failed = False + return success + + def synpred119(self): + self.backtracking += 1 + start = self.input.mark() + self.synpred119_fragment() + success = not self.failed + self.input.rewind(start) + self.backtracking -= 1 + self.failed = False + return success + + def synpred90(self): + self.backtracking += 1 + start = self.input.mark() + self.synpred90_fragment() + success = not self.failed + self.input.rewind(start) + self.backtracking -= 1 + self.failed = False + return success + + def synpred187(self): + self.backtracking += 1 + start = self.input.mark() + self.synpred187_fragment() + success = not self.failed + self.input.rewind(start) + self.backtracking -= 1 + self.failed = False + return success + + def synpred33(self): + self.backtracking += 1 + start = self.input.mark() + self.synpred33_fragment() + success = not self.failed + self.input.rewind(start) + self.backtracking -= 1 + self.failed = False + return success + + def synpred2(self): + self.backtracking += 1 + start = self.input.mark() + self.synpred2_fragment() + success = not self.failed + self.input.rewind(start) + self.backtracking -= 1 + self.failed = False + return success + + def synpred83(self): + self.backtracking += 1 + start = self.input.mark() + self.synpred83_fragment() + success = not self.failed + self.input.rewind(start) + self.backtracking -= 1 + self.failed = False + return success + + def synpred69(self): + self.backtracking += 1 + start = self.input.mark() + self.synpred69_fragment() + success = not self.failed + self.input.rewind(start) + self.backtracking -= 1 + self.failed = False + return success + + def synpred72(self): + self.backtracking += 1 + start = self.input.mark() + self.synpred72_fragment() + success = not self.failed + self.input.rewind(start) + self.backtracking -= 1 + self.failed = False + return success + + def synpred168(self): + self.backtracking += 1 + start = self.input.mark() + self.synpred168_fragment() + success = not self.failed + self.input.rewind(start) + self.backtracking -= 1 + self.failed = False + return success + + def synpred34(self): + self.backtracking += 1 + start = self.input.mark() + self.synpred34_fragment() + success = not self.failed + self.input.rewind(start) + self.backtracking -= 1 + self.failed = False + return success + + def synpred181(self): + self.backtracking += 1 + start = self.input.mark() + self.synpred181_fragment() + success = not self.failed + self.input.rewind(start) + self.backtracking -= 1 + self.failed = False + return success + + def synpred116(self): + self.backtracking += 1 + start = self.input.mark() + self.synpred116_fragment() + success = not self.failed + self.input.rewind(start) + self.backtracking -= 1 + self.failed = False + return success + + def synpred113(self): + self.backtracking += 1 + start = self.input.mark() + self.synpred113_fragment() + success = not self.failed + self.input.rewind(start) + self.backtracking -= 1 + self.failed = False + return success + + def synpred80(self): + self.backtracking += 1 + start = self.input.mark() + self.synpred80_fragment() + success = not self.failed + self.input.rewind(start) + self.backtracking -= 1 + self.failed = False + return success + + def synpred73(self): + self.backtracking += 1 + start = self.input.mark() + self.synpred73_fragment() + success = not self.failed + self.input.rewind(start) + self.backtracking -= 1 + self.failed = False + return success + + def synpred89(self): + self.backtracking += 1 + start = self.input.mark() + self.synpred89_fragment() + success = not self.failed + self.input.rewind(start) + self.backtracking -= 1 + self.failed = False + return success + + def synpred10(self): + self.backtracking += 1 + start = self.input.mark() + self.synpred10_fragment() + success = not self.failed + self.input.rewind(start) + self.backtracking -= 1 + self.failed = False + return success + + def synpred81(self): + self.backtracking += 1 + start = self.input.mark() + self.synpred81_fragment() + success = not self.failed + self.input.rewind(start) + self.backtracking -= 1 + self.failed = False + return success + + def synpred180(self): + self.backtracking += 1 + start = self.input.mark() + self.synpred180_fragment() + success = not self.failed + self.input.rewind(start) + self.backtracking -= 1 + self.failed = False + return success + + def synpred136(self): + self.backtracking += 1 + start = self.input.mark() + self.synpred136_fragment() + success = not self.failed + self.input.rewind(start) + self.backtracking -= 1 + self.failed = False + return success + + def synpred77(self): + self.backtracking += 1 + start = self.input.mark() + self.synpred77_fragment() + success = not self.failed + self.input.rewind(start) + self.backtracking -= 1 + self.failed = False + return success + + def synpred172(self): + self.backtracking += 1 + start = self.input.mark() + self.synpred172_fragment() + success = not self.failed + self.input.rewind(start) + self.backtracking -= 1 + self.failed = False + return success + + def synpred137(self): + self.backtracking += 1 + start = self.input.mark() + self.synpred137_fragment() + success = not self.failed + self.input.rewind(start) + self.backtracking -= 1 + self.failed = False + return success + + def synpred74(self): + self.backtracking += 1 + start = self.input.mark() + self.synpred74_fragment() + success = not self.failed + self.input.rewind(start) + self.backtracking -= 1 + self.failed = False + return success + + def synpred5(self): + self.backtracking += 1 + start = self.input.mark() + self.synpred5_fragment() + success = not self.failed + self.input.rewind(start) + self.backtracking -= 1 + self.failed = False + return success + + def synpred108(self): + self.backtracking += 1 + start = self.input.mark() + self.synpred108_fragment() + success = not self.failed + self.input.rewind(start) + self.backtracking -= 1 + self.failed = False + return success + + def synpred82(self): + self.backtracking += 1 + start = self.input.mark() + self.synpred82_fragment() + success = not self.failed + self.input.rewind(start) + self.backtracking -= 1 + self.failed = False + return success + + def synpred93(self): + self.backtracking += 1 + start = self.input.mark() + self.synpred93_fragment() + success = not self.failed + self.input.rewind(start) + self.backtracking -= 1 + self.failed = False + return success + + def synpred66(self): + self.backtracking += 1 + start = self.input.mark() + self.synpred66_fragment() + success = not self.failed + self.input.rewind(start) + self.backtracking -= 1 + self.failed = False + return success + + + + + + FOLLOW_external_declaration_in_translation_unit64 = frozenset([1, 4, 26, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 45, 46, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 65]) + FOLLOW_function_definition_in_external_declaration103 = frozenset([1]) + FOLLOW_declaration_in_external_declaration108 = frozenset([1]) + FOLLOW_macro_statement_in_external_declaration113 = frozenset([1, 25]) + FOLLOW_25_in_external_declaration116 = frozenset([1]) + FOLLOW_declaration_specifiers_in_function_definition147 = frozenset([4, 58, 59, 60, 61, 65]) + FOLLOW_declarator_in_function_definition150 = frozenset([4, 26, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 45, 46, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60]) + FOLLOW_declaration_in_function_definition156 = frozenset([4, 26, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 45, 46, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60]) + FOLLOW_compound_statement_in_function_definition161 = frozenset([1]) + FOLLOW_compound_statement_in_function_definition170 = frozenset([1]) + FOLLOW_26_in_declaration193 = frozenset([4, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 45, 46, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 65]) + FOLLOW_declaration_specifiers_in_declaration197 = frozenset([4, 58, 59, 60, 61, 65]) + FOLLOW_init_declarator_list_in_declaration206 = frozenset([25]) + FOLLOW_25_in_declaration210 = frozenset([1]) + FOLLOW_declaration_specifiers_in_declaration224 = frozenset([4, 25, 58, 59, 60, 61, 65]) + FOLLOW_init_declarator_list_in_declaration228 = frozenset([25]) + FOLLOW_25_in_declaration233 = frozenset([1]) + FOLLOW_storage_class_specifier_in_declaration_specifiers254 = frozenset([1, 4, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 45, 46, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60]) + FOLLOW_type_specifier_in_declaration_specifiers262 = frozenset([1, 4, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 45, 46, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60]) + FOLLOW_type_qualifier_in_declaration_specifiers276 = frozenset([1, 4, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 45, 46, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60]) + FOLLOW_init_declarator_in_init_declarator_list298 = frozenset([1, 27]) + FOLLOW_27_in_init_declarator_list301 = frozenset([4, 58, 59, 60, 61, 65]) + FOLLOW_init_declarator_in_init_declarator_list303 = frozenset([1, 27]) + FOLLOW_declarator_in_init_declarator316 = frozenset([1, 28]) + FOLLOW_28_in_init_declarator319 = frozenset([4, 5, 6, 7, 8, 9, 10, 43, 61, 65, 67, 68, 71, 72, 73, 76, 77, 78]) + FOLLOW_initializer_in_init_declarator321 = frozenset([1]) + FOLLOW_set_in_storage_class_specifier0 = frozenset([1]) + FOLLOW_34_in_type_specifier366 = frozenset([1]) + FOLLOW_35_in_type_specifier371 = frozenset([1]) + FOLLOW_36_in_type_specifier376 = frozenset([1]) + FOLLOW_37_in_type_specifier381 = frozenset([1]) + FOLLOW_38_in_type_specifier386 = frozenset([1]) + FOLLOW_39_in_type_specifier391 = frozenset([1]) + FOLLOW_40_in_type_specifier396 = frozenset([1]) + FOLLOW_41_in_type_specifier401 = frozenset([1]) + FOLLOW_42_in_type_specifier406 = frozenset([1]) + FOLLOW_struct_or_union_specifier_in_type_specifier413 = frozenset([1]) + FOLLOW_enum_specifier_in_type_specifier423 = frozenset([1]) + FOLLOW_type_id_in_type_specifier441 = frozenset([1]) + FOLLOW_IDENTIFIER_in_type_id457 = frozenset([1]) + FOLLOW_struct_or_union_in_struct_or_union_specifier484 = frozenset([4, 43]) + FOLLOW_IDENTIFIER_in_struct_or_union_specifier486 = frozenset([43]) + FOLLOW_43_in_struct_or_union_specifier489 = frozenset([4, 34, 35, 36, 37, 38, 39, 40, 41, 42, 45, 46, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60]) + FOLLOW_struct_declaration_list_in_struct_or_union_specifier491 = frozenset([44]) + FOLLOW_44_in_struct_or_union_specifier493 = frozenset([1]) + FOLLOW_struct_or_union_in_struct_or_union_specifier498 = frozenset([4]) + FOLLOW_IDENTIFIER_in_struct_or_union_specifier500 = frozenset([1]) + FOLLOW_set_in_struct_or_union0 = frozenset([1]) + FOLLOW_struct_declaration_in_struct_declaration_list527 = frozenset([1, 4, 34, 35, 36, 37, 38, 39, 40, 41, 42, 45, 46, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60]) + FOLLOW_specifier_qualifier_list_in_struct_declaration539 = frozenset([4, 47, 58, 59, 60, 61, 65]) + FOLLOW_struct_declarator_list_in_struct_declaration541 = frozenset([25]) + FOLLOW_25_in_struct_declaration543 = frozenset([1]) + FOLLOW_type_qualifier_in_specifier_qualifier_list556 = frozenset([1, 4, 34, 35, 36, 37, 38, 39, 40, 41, 42, 45, 46, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60]) + FOLLOW_type_specifier_in_specifier_qualifier_list560 = frozenset([1, 4, 34, 35, 36, 37, 38, 39, 40, 41, 42, 45, 46, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60]) + FOLLOW_struct_declarator_in_struct_declarator_list574 = frozenset([1, 27]) + FOLLOW_27_in_struct_declarator_list577 = frozenset([4, 47, 58, 59, 60, 61, 65]) + FOLLOW_struct_declarator_in_struct_declarator_list579 = frozenset([1, 27]) + FOLLOW_declarator_in_struct_declarator592 = frozenset([1, 47]) + FOLLOW_47_in_struct_declarator595 = frozenset([4, 5, 6, 7, 8, 9, 10, 61, 65, 67, 68, 71, 72, 73, 76, 77, 78]) + FOLLOW_constant_expression_in_struct_declarator597 = frozenset([1]) + FOLLOW_47_in_struct_declarator604 = frozenset([4, 5, 6, 7, 8, 9, 10, 61, 65, 67, 68, 71, 72, 73, 76, 77, 78]) + FOLLOW_constant_expression_in_struct_declarator606 = frozenset([1]) + FOLLOW_48_in_enum_specifier624 = frozenset([43]) + FOLLOW_43_in_enum_specifier626 = frozenset([4]) + FOLLOW_enumerator_list_in_enum_specifier628 = frozenset([27, 44]) + FOLLOW_27_in_enum_specifier630 = frozenset([44]) + FOLLOW_44_in_enum_specifier633 = frozenset([1]) + FOLLOW_48_in_enum_specifier638 = frozenset([4]) + FOLLOW_IDENTIFIER_in_enum_specifier640 = frozenset([43]) + FOLLOW_43_in_enum_specifier642 = frozenset([4]) + FOLLOW_enumerator_list_in_enum_specifier644 = frozenset([27, 44]) + FOLLOW_27_in_enum_specifier646 = frozenset([44]) + FOLLOW_44_in_enum_specifier649 = frozenset([1]) + FOLLOW_48_in_enum_specifier654 = frozenset([4]) + FOLLOW_IDENTIFIER_in_enum_specifier656 = frozenset([1]) + FOLLOW_enumerator_in_enumerator_list667 = frozenset([1, 27]) + FOLLOW_27_in_enumerator_list670 = frozenset([4]) + FOLLOW_enumerator_in_enumerator_list672 = frozenset([1, 27]) + FOLLOW_IDENTIFIER_in_enumerator685 = frozenset([1, 28]) + FOLLOW_28_in_enumerator688 = frozenset([4, 5, 6, 7, 8, 9, 10, 61, 65, 67, 68, 71, 72, 73, 76, 77, 78]) + FOLLOW_constant_expression_in_enumerator690 = frozenset([1]) + FOLLOW_set_in_type_qualifier0 = frozenset([1]) + FOLLOW_pointer_in_declarator769 = frozenset([4, 58, 59, 60, 61]) + FOLLOW_58_in_declarator773 = frozenset([4, 59, 60, 61]) + FOLLOW_59_in_declarator778 = frozenset([4, 60, 61]) + FOLLOW_60_in_declarator783 = frozenset([4, 61]) + FOLLOW_direct_declarator_in_declarator787 = frozenset([1]) + FOLLOW_pointer_in_declarator793 = frozenset([1]) + FOLLOW_IDENTIFIER_in_direct_declarator804 = frozenset([1, 61, 63]) + FOLLOW_declarator_suffix_in_direct_declarator806 = frozenset([1, 61, 63]) + FOLLOW_61_in_direct_declarator812 = frozenset([4, 58, 59, 60, 61, 65]) + FOLLOW_58_in_direct_declarator815 = frozenset([4, 58, 59, 60, 61, 65]) + FOLLOW_declarator_in_direct_declarator819 = frozenset([62]) + FOLLOW_62_in_direct_declarator821 = frozenset([61, 63]) + FOLLOW_declarator_suffix_in_direct_declarator823 = frozenset([1, 61, 63]) + FOLLOW_63_in_declarator_suffix837 = frozenset([4, 5, 6, 7, 8, 9, 10, 61, 65, 67, 68, 71, 72, 73, 76, 77, 78]) + FOLLOW_constant_expression_in_declarator_suffix839 = frozenset([64]) + FOLLOW_64_in_declarator_suffix841 = frozenset([1]) + FOLLOW_63_in_declarator_suffix851 = frozenset([64]) + FOLLOW_64_in_declarator_suffix853 = frozenset([1]) + FOLLOW_61_in_declarator_suffix863 = frozenset([4, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 45, 46, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 65]) + FOLLOW_parameter_type_list_in_declarator_suffix865 = frozenset([62]) + FOLLOW_62_in_declarator_suffix867 = frozenset([1]) + FOLLOW_61_in_declarator_suffix877 = frozenset([4]) + FOLLOW_identifier_list_in_declarator_suffix879 = frozenset([62]) + FOLLOW_62_in_declarator_suffix881 = frozenset([1]) + FOLLOW_61_in_declarator_suffix891 = frozenset([62]) + FOLLOW_62_in_declarator_suffix893 = frozenset([1]) + FOLLOW_65_in_pointer904 = frozenset([49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60]) + FOLLOW_type_qualifier_in_pointer906 = frozenset([1, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 65]) + FOLLOW_pointer_in_pointer909 = frozenset([1]) + FOLLOW_65_in_pointer915 = frozenset([65]) + FOLLOW_pointer_in_pointer917 = frozenset([1]) + FOLLOW_65_in_pointer922 = frozenset([1]) + FOLLOW_parameter_list_in_parameter_type_list933 = frozenset([1, 27]) + FOLLOW_27_in_parameter_type_list936 = frozenset([53, 66]) + FOLLOW_53_in_parameter_type_list939 = frozenset([66]) + FOLLOW_66_in_parameter_type_list943 = frozenset([1]) + FOLLOW_parameter_declaration_in_parameter_list956 = frozenset([1, 27]) + FOLLOW_27_in_parameter_list959 = frozenset([4, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 45, 46, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 65]) + FOLLOW_53_in_parameter_list962 = frozenset([4, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 45, 46, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 65]) + FOLLOW_parameter_declaration_in_parameter_list966 = frozenset([1, 27]) + FOLLOW_declaration_specifiers_in_parameter_declaration979 = frozenset([1, 4, 53, 58, 59, 60, 61, 63, 65]) + FOLLOW_declarator_in_parameter_declaration982 = frozenset([1, 4, 53, 58, 59, 60, 61, 63, 65]) + FOLLOW_abstract_declarator_in_parameter_declaration984 = frozenset([1, 4, 53, 58, 59, 60, 61, 63, 65]) + FOLLOW_53_in_parameter_declaration989 = frozenset([1]) + FOLLOW_pointer_in_parameter_declaration998 = frozenset([4, 65]) + FOLLOW_IDENTIFIER_in_parameter_declaration1001 = frozenset([1]) + FOLLOW_IDENTIFIER_in_identifier_list1012 = frozenset([1, 27]) + FOLLOW_27_in_identifier_list1016 = frozenset([4]) + FOLLOW_IDENTIFIER_in_identifier_list1018 = frozenset([1, 27]) + FOLLOW_specifier_qualifier_list_in_type_name1031 = frozenset([1, 61, 63, 65]) + FOLLOW_abstract_declarator_in_type_name1033 = frozenset([1]) + FOLLOW_type_id_in_type_name1039 = frozenset([1]) + FOLLOW_pointer_in_abstract_declarator1050 = frozenset([1, 61, 63]) + FOLLOW_direct_abstract_declarator_in_abstract_declarator1052 = frozenset([1]) + FOLLOW_direct_abstract_declarator_in_abstract_declarator1058 = frozenset([1]) + FOLLOW_61_in_direct_abstract_declarator1071 = frozenset([61, 63, 65]) + FOLLOW_abstract_declarator_in_direct_abstract_declarator1073 = frozenset([62]) + FOLLOW_62_in_direct_abstract_declarator1075 = frozenset([1, 61, 63]) + FOLLOW_abstract_declarator_suffix_in_direct_abstract_declarator1079 = frozenset([1, 61, 63]) + FOLLOW_abstract_declarator_suffix_in_direct_abstract_declarator1083 = frozenset([1, 61, 63]) + FOLLOW_63_in_abstract_declarator_suffix1095 = frozenset([64]) + FOLLOW_64_in_abstract_declarator_suffix1097 = frozenset([1]) + FOLLOW_63_in_abstract_declarator_suffix1102 = frozenset([4, 5, 6, 7, 8, 9, 10, 61, 65, 67, 68, 71, 72, 73, 76, 77, 78]) + FOLLOW_constant_expression_in_abstract_declarator_suffix1104 = frozenset([64]) + FOLLOW_64_in_abstract_declarator_suffix1106 = frozenset([1]) + FOLLOW_61_in_abstract_declarator_suffix1111 = frozenset([62]) + FOLLOW_62_in_abstract_declarator_suffix1113 = frozenset([1]) + FOLLOW_61_in_abstract_declarator_suffix1118 = frozenset([4, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 45, 46, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 65]) + FOLLOW_parameter_type_list_in_abstract_declarator_suffix1120 = frozenset([62]) + FOLLOW_62_in_abstract_declarator_suffix1122 = frozenset([1]) + FOLLOW_assignment_expression_in_initializer1135 = frozenset([1]) + FOLLOW_43_in_initializer1140 = frozenset([4, 5, 6, 7, 8, 9, 10, 43, 61, 65, 67, 68, 71, 72, 73, 76, 77, 78]) + FOLLOW_initializer_list_in_initializer1142 = frozenset([27, 44]) + FOLLOW_27_in_initializer1144 = frozenset([44]) + FOLLOW_44_in_initializer1147 = frozenset([1]) + FOLLOW_initializer_in_initializer_list1158 = frozenset([1, 27]) + FOLLOW_27_in_initializer_list1161 = frozenset([4, 5, 6, 7, 8, 9, 10, 43, 61, 65, 67, 68, 71, 72, 73, 76, 77, 78]) + FOLLOW_initializer_in_initializer_list1163 = frozenset([1, 27]) + FOLLOW_assignment_expression_in_argument_expression_list1181 = frozenset([1, 27, 53]) + FOLLOW_53_in_argument_expression_list1184 = frozenset([1, 27]) + FOLLOW_27_in_argument_expression_list1189 = frozenset([4, 5, 6, 7, 8, 9, 10, 61, 65, 67, 68, 71, 72, 73, 76, 77, 78]) + FOLLOW_assignment_expression_in_argument_expression_list1191 = frozenset([1, 27, 53]) + FOLLOW_53_in_argument_expression_list1194 = frozenset([1, 27]) + FOLLOW_multiplicative_expression_in_additive_expression1210 = frozenset([1, 67, 68]) + FOLLOW_67_in_additive_expression1214 = frozenset([4, 5, 6, 7, 8, 9, 10, 61, 65, 67, 68, 71, 72, 73, 76, 77, 78]) + FOLLOW_multiplicative_expression_in_additive_expression1216 = frozenset([1, 67, 68]) + FOLLOW_68_in_additive_expression1220 = frozenset([4, 5, 6, 7, 8, 9, 10, 61, 65, 67, 68, 71, 72, 73, 76, 77, 78]) + FOLLOW_multiplicative_expression_in_additive_expression1222 = frozenset([1, 67, 68]) + FOLLOW_cast_expression_in_multiplicative_expression1236 = frozenset([1, 65, 69, 70]) + FOLLOW_65_in_multiplicative_expression1240 = frozenset([4, 5, 6, 7, 8, 9, 10, 61, 65, 67, 68, 71, 72, 73, 76, 77, 78]) + FOLLOW_cast_expression_in_multiplicative_expression1242 = frozenset([1, 65, 69, 70]) + FOLLOW_69_in_multiplicative_expression1246 = frozenset([4, 5, 6, 7, 8, 9, 10, 61, 65, 67, 68, 71, 72, 73, 76, 77, 78]) + FOLLOW_cast_expression_in_multiplicative_expression1248 = frozenset([1, 65, 69, 70]) + FOLLOW_70_in_multiplicative_expression1252 = frozenset([4, 5, 6, 7, 8, 9, 10, 61, 65, 67, 68, 71, 72, 73, 76, 77, 78]) + FOLLOW_cast_expression_in_multiplicative_expression1254 = frozenset([1, 65, 69, 70]) + FOLLOW_61_in_cast_expression1267 = frozenset([4, 34, 35, 36, 37, 38, 39, 40, 41, 42, 45, 46, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60]) + FOLLOW_type_name_in_cast_expression1269 = frozenset([62]) + FOLLOW_62_in_cast_expression1271 = frozenset([4, 5, 6, 7, 8, 9, 10, 61, 65, 67, 68, 71, 72, 73, 76, 77, 78]) + FOLLOW_cast_expression_in_cast_expression1273 = frozenset([1]) + FOLLOW_unary_expression_in_cast_expression1278 = frozenset([1]) + FOLLOW_postfix_expression_in_unary_expression1289 = frozenset([1]) + FOLLOW_71_in_unary_expression1294 = frozenset([4, 5, 6, 7, 8, 9, 10, 61, 65, 67, 68, 71, 72, 73, 76, 77, 78]) + FOLLOW_unary_expression_in_unary_expression1296 = frozenset([1]) + FOLLOW_72_in_unary_expression1301 = frozenset([4, 5, 6, 7, 8, 9, 10, 61, 65, 67, 68, 71, 72, 73, 76, 77, 78]) + FOLLOW_unary_expression_in_unary_expression1303 = frozenset([1]) + FOLLOW_unary_operator_in_unary_expression1308 = frozenset([4, 5, 6, 7, 8, 9, 10, 61, 65, 67, 68, 71, 72, 73, 76, 77, 78]) + FOLLOW_cast_expression_in_unary_expression1310 = frozenset([1]) + FOLLOW_73_in_unary_expression1315 = frozenset([4, 5, 6, 7, 8, 9, 10, 61, 65, 67, 68, 71, 72, 73, 76, 77, 78]) + FOLLOW_unary_expression_in_unary_expression1317 = frozenset([1]) + FOLLOW_73_in_unary_expression1322 = frozenset([61]) + FOLLOW_61_in_unary_expression1324 = frozenset([4, 34, 35, 36, 37, 38, 39, 40, 41, 42, 45, 46, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60]) + FOLLOW_type_name_in_unary_expression1326 = frozenset([62]) + FOLLOW_62_in_unary_expression1328 = frozenset([1]) + FOLLOW_primary_expression_in_postfix_expression1352 = frozenset([1, 61, 63, 65, 71, 72, 74, 75]) + FOLLOW_63_in_postfix_expression1368 = frozenset([4, 5, 6, 7, 8, 9, 10, 61, 65, 67, 68, 71, 72, 73, 76, 77, 78]) + FOLLOW_expression_in_postfix_expression1370 = frozenset([64]) + FOLLOW_64_in_postfix_expression1372 = frozenset([1, 61, 63, 65, 71, 72, 74, 75]) + FOLLOW_61_in_postfix_expression1386 = frozenset([62]) + FOLLOW_62_in_postfix_expression1390 = frozenset([1, 61, 63, 65, 71, 72, 74, 75]) + FOLLOW_61_in_postfix_expression1405 = frozenset([4, 5, 6, 7, 8, 9, 10, 61, 65, 67, 68, 71, 72, 73, 76, 77, 78]) + FOLLOW_argument_expression_list_in_postfix_expression1409 = frozenset([62]) + FOLLOW_62_in_postfix_expression1413 = frozenset([1, 61, 63, 65, 71, 72, 74, 75]) + FOLLOW_61_in_postfix_expression1429 = frozenset([4, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 45, 46, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 65]) + FOLLOW_macro_parameter_list_in_postfix_expression1431 = frozenset([62]) + FOLLOW_62_in_postfix_expression1433 = frozenset([1, 61, 63, 65, 71, 72, 74, 75]) + FOLLOW_74_in_postfix_expression1447 = frozenset([4]) + FOLLOW_IDENTIFIER_in_postfix_expression1451 = frozenset([1, 61, 63, 65, 71, 72, 74, 75]) + FOLLOW_65_in_postfix_expression1467 = frozenset([4]) + FOLLOW_IDENTIFIER_in_postfix_expression1471 = frozenset([1, 61, 63, 65, 71, 72, 74, 75]) + FOLLOW_75_in_postfix_expression1487 = frozenset([4]) + FOLLOW_IDENTIFIER_in_postfix_expression1491 = frozenset([1, 61, 63, 65, 71, 72, 74, 75]) + FOLLOW_71_in_postfix_expression1507 = frozenset([1, 61, 63, 65, 71, 72, 74, 75]) + FOLLOW_72_in_postfix_expression1521 = frozenset([1, 61, 63, 65, 71, 72, 74, 75]) + FOLLOW_parameter_declaration_in_macro_parameter_list1544 = frozenset([1, 27]) + FOLLOW_27_in_macro_parameter_list1547 = frozenset([4, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 45, 46, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 65]) + FOLLOW_parameter_declaration_in_macro_parameter_list1549 = frozenset([1, 27]) + FOLLOW_set_in_unary_operator0 = frozenset([1]) + FOLLOW_IDENTIFIER_in_primary_expression1598 = frozenset([1]) + FOLLOW_constant_in_primary_expression1603 = frozenset([1]) + FOLLOW_61_in_primary_expression1608 = frozenset([4, 5, 6, 7, 8, 9, 10, 61, 65, 67, 68, 71, 72, 73, 76, 77, 78]) + FOLLOW_expression_in_primary_expression1610 = frozenset([62]) + FOLLOW_62_in_primary_expression1612 = frozenset([1]) + FOLLOW_HEX_LITERAL_in_constant1628 = frozenset([1]) + FOLLOW_OCTAL_LITERAL_in_constant1638 = frozenset([1]) + FOLLOW_DECIMAL_LITERAL_in_constant1648 = frozenset([1]) + FOLLOW_CHARACTER_LITERAL_in_constant1656 = frozenset([1]) + FOLLOW_IDENTIFIER_in_constant1665 = frozenset([4, 9]) + FOLLOW_STRING_LITERAL_in_constant1668 = frozenset([1, 4, 9]) + FOLLOW_IDENTIFIER_in_constant1673 = frozenset([1, 4]) + FOLLOW_FLOATING_POINT_LITERAL_in_constant1684 = frozenset([1]) + FOLLOW_assignment_expression_in_expression1700 = frozenset([1, 27]) + FOLLOW_27_in_expression1703 = frozenset([4, 5, 6, 7, 8, 9, 10, 61, 65, 67, 68, 71, 72, 73, 76, 77, 78]) + FOLLOW_assignment_expression_in_expression1705 = frozenset([1, 27]) + FOLLOW_conditional_expression_in_constant_expression1718 = frozenset([1]) + FOLLOW_lvalue_in_assignment_expression1729 = frozenset([28, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88]) + FOLLOW_assignment_operator_in_assignment_expression1731 = frozenset([4, 5, 6, 7, 8, 9, 10, 61, 65, 67, 68, 71, 72, 73, 76, 77, 78]) + FOLLOW_assignment_expression_in_assignment_expression1733 = frozenset([1]) + FOLLOW_conditional_expression_in_assignment_expression1738 = frozenset([1]) + FOLLOW_unary_expression_in_lvalue1750 = frozenset([1]) + FOLLOW_set_in_assignment_operator0 = frozenset([1]) + FOLLOW_logical_or_expression_in_conditional_expression1824 = frozenset([1, 89]) + FOLLOW_89_in_conditional_expression1827 = frozenset([4, 5, 6, 7, 8, 9, 10, 61, 65, 67, 68, 71, 72, 73, 76, 77, 78]) + FOLLOW_expression_in_conditional_expression1829 = frozenset([47]) + FOLLOW_47_in_conditional_expression1831 = frozenset([4, 5, 6, 7, 8, 9, 10, 61, 65, 67, 68, 71, 72, 73, 76, 77, 78]) + FOLLOW_conditional_expression_in_conditional_expression1833 = frozenset([1]) + FOLLOW_logical_and_expression_in_logical_or_expression1848 = frozenset([1, 90]) + FOLLOW_90_in_logical_or_expression1851 = frozenset([4, 5, 6, 7, 8, 9, 10, 61, 65, 67, 68, 71, 72, 73, 76, 77, 78]) + FOLLOW_logical_and_expression_in_logical_or_expression1853 = frozenset([1, 90]) + FOLLOW_inclusive_or_expression_in_logical_and_expression1866 = frozenset([1, 91]) + FOLLOW_91_in_logical_and_expression1869 = frozenset([4, 5, 6, 7, 8, 9, 10, 61, 65, 67, 68, 71, 72, 73, 76, 77, 78]) + FOLLOW_inclusive_or_expression_in_logical_and_expression1871 = frozenset([1, 91]) + FOLLOW_exclusive_or_expression_in_inclusive_or_expression1884 = frozenset([1, 92]) + FOLLOW_92_in_inclusive_or_expression1887 = frozenset([4, 5, 6, 7, 8, 9, 10, 61, 65, 67, 68, 71, 72, 73, 76, 77, 78]) + FOLLOW_exclusive_or_expression_in_inclusive_or_expression1889 = frozenset([1, 92]) + FOLLOW_and_expression_in_exclusive_or_expression1902 = frozenset([1, 93]) + FOLLOW_93_in_exclusive_or_expression1905 = frozenset([4, 5, 6, 7, 8, 9, 10, 61, 65, 67, 68, 71, 72, 73, 76, 77, 78]) + FOLLOW_and_expression_in_exclusive_or_expression1907 = frozenset([1, 93]) + FOLLOW_equality_expression_in_and_expression1920 = frozenset([1, 76]) + FOLLOW_76_in_and_expression1923 = frozenset([4, 5, 6, 7, 8, 9, 10, 61, 65, 67, 68, 71, 72, 73, 76, 77, 78]) + FOLLOW_equality_expression_in_and_expression1925 = frozenset([1, 76]) + FOLLOW_relational_expression_in_equality_expression1937 = frozenset([1, 94, 95]) + FOLLOW_set_in_equality_expression1940 = frozenset([4, 5, 6, 7, 8, 9, 10, 61, 65, 67, 68, 71, 72, 73, 76, 77, 78]) + FOLLOW_relational_expression_in_equality_expression1946 = frozenset([1, 94, 95]) + FOLLOW_shift_expression_in_relational_expression1960 = frozenset([1, 96, 97, 98, 99]) + FOLLOW_set_in_relational_expression1963 = frozenset([4, 5, 6, 7, 8, 9, 10, 61, 65, 67, 68, 71, 72, 73, 76, 77, 78]) + FOLLOW_shift_expression_in_relational_expression1973 = frozenset([1, 96, 97, 98, 99]) + FOLLOW_additive_expression_in_shift_expression1986 = frozenset([1, 100, 101]) + FOLLOW_set_in_shift_expression1989 = frozenset([4, 5, 6, 7, 8, 9, 10, 61, 65, 67, 68, 71, 72, 73, 76, 77, 78]) + FOLLOW_additive_expression_in_shift_expression1995 = frozenset([1, 100, 101]) + FOLLOW_labeled_statement_in_statement2010 = frozenset([1]) + FOLLOW_compound_statement_in_statement2015 = frozenset([1]) + FOLLOW_expression_statement_in_statement2020 = frozenset([1]) + FOLLOW_selection_statement_in_statement2025 = frozenset([1]) + FOLLOW_iteration_statement_in_statement2030 = frozenset([1]) + FOLLOW_jump_statement_in_statement2035 = frozenset([1]) + FOLLOW_macro_statement_in_statement2040 = frozenset([1]) + FOLLOW_asm2_statement_in_statement2045 = frozenset([1]) + FOLLOW_asm1_statement_in_statement2050 = frozenset([1]) + FOLLOW_asm_statement_in_statement2055 = frozenset([1]) + FOLLOW_declaration_in_statement2060 = frozenset([1]) + FOLLOW_102_in_asm2_statement2071 = frozenset([4]) + FOLLOW_IDENTIFIER_in_asm2_statement2074 = frozenset([61]) + FOLLOW_61_in_asm2_statement2076 = frozenset([4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116]) + FOLLOW_set_in_asm2_statement2079 = frozenset([4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116]) + FOLLOW_62_in_asm2_statement2086 = frozenset([25]) + FOLLOW_25_in_asm2_statement2088 = frozenset([1]) + FOLLOW_103_in_asm1_statement2100 = frozenset([43]) + FOLLOW_43_in_asm1_statement2102 = frozenset([4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116]) + FOLLOW_set_in_asm1_statement2105 = frozenset([4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116]) + FOLLOW_44_in_asm1_statement2112 = frozenset([1]) + FOLLOW_104_in_asm_statement2123 = frozenset([43]) + FOLLOW_43_in_asm_statement2125 = frozenset([4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116]) + FOLLOW_set_in_asm_statement2128 = frozenset([4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116]) + FOLLOW_44_in_asm_statement2135 = frozenset([1]) + FOLLOW_IDENTIFIER_in_macro_statement2147 = frozenset([61]) + FOLLOW_61_in_macro_statement2149 = frozenset([4, 5, 6, 7, 8, 9, 10, 25, 26, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 45, 46, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 65, 67, 68, 71, 72, 73, 76, 77, 78, 102, 103, 104, 105, 106, 107, 109, 110, 111, 112, 113, 114, 115, 116]) + FOLLOW_declaration_in_macro_statement2151 = frozenset([4, 5, 6, 7, 8, 9, 10, 25, 26, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 45, 46, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 65, 67, 68, 71, 72, 73, 76, 77, 78, 102, 103, 104, 105, 106, 107, 109, 110, 111, 112, 113, 114, 115, 116]) + FOLLOW_statement_list_in_macro_statement2155 = frozenset([4, 5, 6, 7, 8, 9, 10, 61, 62, 65, 67, 68, 71, 72, 73, 76, 77, 78]) + FOLLOW_expression_in_macro_statement2158 = frozenset([62]) + FOLLOW_62_in_macro_statement2161 = frozenset([1]) + FOLLOW_IDENTIFIER_in_labeled_statement2173 = frozenset([47]) + FOLLOW_47_in_labeled_statement2175 = frozenset([4, 5, 6, 7, 8, 9, 10, 25, 26, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 45, 46, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 65, 67, 68, 71, 72, 73, 76, 77, 78, 102, 103, 104, 105, 106, 107, 109, 110, 111, 112, 113, 114, 115, 116]) + FOLLOW_statement_in_labeled_statement2177 = frozenset([1]) + FOLLOW_105_in_labeled_statement2182 = frozenset([4, 5, 6, 7, 8, 9, 10, 61, 65, 67, 68, 71, 72, 73, 76, 77, 78]) + FOLLOW_constant_expression_in_labeled_statement2184 = frozenset([47]) + FOLLOW_47_in_labeled_statement2186 = frozenset([4, 5, 6, 7, 8, 9, 10, 25, 26, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 45, 46, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 65, 67, 68, 71, 72, 73, 76, 77, 78, 102, 103, 104, 105, 106, 107, 109, 110, 111, 112, 113, 114, 115, 116]) + FOLLOW_statement_in_labeled_statement2188 = frozenset([1]) + FOLLOW_106_in_labeled_statement2193 = frozenset([47]) + FOLLOW_47_in_labeled_statement2195 = frozenset([4, 5, 6, 7, 8, 9, 10, 25, 26, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 45, 46, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 65, 67, 68, 71, 72, 73, 76, 77, 78, 102, 103, 104, 105, 106, 107, 109, 110, 111, 112, 113, 114, 115, 116]) + FOLLOW_statement_in_labeled_statement2197 = frozenset([1]) + FOLLOW_43_in_compound_statement2208 = frozenset([4, 5, 6, 7, 8, 9, 10, 25, 26, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 65, 67, 68, 71, 72, 73, 76, 77, 78, 102, 103, 104, 105, 106, 107, 109, 110, 111, 112, 113, 114, 115, 116]) + FOLLOW_declaration_in_compound_statement2210 = frozenset([4, 5, 6, 7, 8, 9, 10, 25, 26, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 65, 67, 68, 71, 72, 73, 76, 77, 78, 102, 103, 104, 105, 106, 107, 109, 110, 111, 112, 113, 114, 115, 116]) + FOLLOW_statement_list_in_compound_statement2213 = frozenset([44]) + FOLLOW_44_in_compound_statement2216 = frozenset([1]) + FOLLOW_statement_in_statement_list2227 = frozenset([1, 4, 5, 6, 7, 8, 9, 10, 25, 26, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 45, 46, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 65, 67, 68, 71, 72, 73, 76, 77, 78, 102, 103, 104, 105, 106, 107, 109, 110, 111, 112, 113, 114, 115, 116]) + FOLLOW_25_in_expression_statement2239 = frozenset([1]) + FOLLOW_expression_in_expression_statement2244 = frozenset([25]) + FOLLOW_25_in_expression_statement2246 = frozenset([1]) + FOLLOW_107_in_selection_statement2257 = frozenset([61]) + FOLLOW_61_in_selection_statement2259 = frozenset([4, 5, 6, 7, 8, 9, 10, 61, 65, 67, 68, 71, 72, 73, 76, 77, 78]) + FOLLOW_expression_in_selection_statement2263 = frozenset([62]) + FOLLOW_62_in_selection_statement2265 = frozenset([4, 5, 6, 7, 8, 9, 10, 25, 26, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 45, 46, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 65, 67, 68, 71, 72, 73, 76, 77, 78, 102, 103, 104, 105, 106, 107, 109, 110, 111, 112, 113, 114, 115, 116]) + FOLLOW_statement_in_selection_statement2269 = frozenset([1, 108]) + FOLLOW_108_in_selection_statement2284 = frozenset([4, 5, 6, 7, 8, 9, 10, 25, 26, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 45, 46, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 65, 67, 68, 71, 72, 73, 76, 77, 78, 102, 103, 104, 105, 106, 107, 109, 110, 111, 112, 113, 114, 115, 116]) + FOLLOW_statement_in_selection_statement2286 = frozenset([1]) + FOLLOW_109_in_selection_statement2293 = frozenset([61]) + FOLLOW_61_in_selection_statement2295 = frozenset([4, 5, 6, 7, 8, 9, 10, 61, 65, 67, 68, 71, 72, 73, 76, 77, 78]) + FOLLOW_expression_in_selection_statement2297 = frozenset([62]) + FOLLOW_62_in_selection_statement2299 = frozenset([4, 5, 6, 7, 8, 9, 10, 25, 26, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 45, 46, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 65, 67, 68, 71, 72, 73, 76, 77, 78, 102, 103, 104, 105, 106, 107, 109, 110, 111, 112, 113, 114, 115, 116]) + FOLLOW_statement_in_selection_statement2301 = frozenset([1]) + FOLLOW_110_in_iteration_statement2312 = frozenset([61]) + FOLLOW_61_in_iteration_statement2314 = frozenset([4, 5, 6, 7, 8, 9, 10, 61, 65, 67, 68, 71, 72, 73, 76, 77, 78]) + FOLLOW_expression_in_iteration_statement2318 = frozenset([62]) + FOLLOW_62_in_iteration_statement2320 = frozenset([4, 5, 6, 7, 8, 9, 10, 25, 26, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 45, 46, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 65, 67, 68, 71, 72, 73, 76, 77, 78, 102, 103, 104, 105, 106, 107, 109, 110, 111, 112, 113, 114, 115, 116]) + FOLLOW_statement_in_iteration_statement2322 = frozenset([1]) + FOLLOW_111_in_iteration_statement2329 = frozenset([4, 5, 6, 7, 8, 9, 10, 25, 26, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 45, 46, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 65, 67, 68, 71, 72, 73, 76, 77, 78, 102, 103, 104, 105, 106, 107, 109, 110, 111, 112, 113, 114, 115, 116]) + FOLLOW_statement_in_iteration_statement2331 = frozenset([110]) + FOLLOW_110_in_iteration_statement2333 = frozenset([61]) + FOLLOW_61_in_iteration_statement2335 = frozenset([4, 5, 6, 7, 8, 9, 10, 61, 65, 67, 68, 71, 72, 73, 76, 77, 78]) + FOLLOW_expression_in_iteration_statement2339 = frozenset([62]) + FOLLOW_62_in_iteration_statement2341 = frozenset([25]) + FOLLOW_25_in_iteration_statement2343 = frozenset([1]) + FOLLOW_112_in_iteration_statement2350 = frozenset([61]) + FOLLOW_61_in_iteration_statement2352 = frozenset([4, 5, 6, 7, 8, 9, 10, 25, 61, 65, 67, 68, 71, 72, 73, 76, 77, 78]) + FOLLOW_expression_statement_in_iteration_statement2354 = frozenset([4, 5, 6, 7, 8, 9, 10, 25, 61, 65, 67, 68, 71, 72, 73, 76, 77, 78]) + FOLLOW_expression_statement_in_iteration_statement2358 = frozenset([4, 5, 6, 7, 8, 9, 10, 61, 62, 65, 67, 68, 71, 72, 73, 76, 77, 78]) + FOLLOW_expression_in_iteration_statement2360 = frozenset([62]) + FOLLOW_62_in_iteration_statement2363 = frozenset([4, 5, 6, 7, 8, 9, 10, 25, 26, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 45, 46, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 65, 67, 68, 71, 72, 73, 76, 77, 78, 102, 103, 104, 105, 106, 107, 109, 110, 111, 112, 113, 114, 115, 116]) + FOLLOW_statement_in_iteration_statement2365 = frozenset([1]) + FOLLOW_113_in_jump_statement2378 = frozenset([4]) + FOLLOW_IDENTIFIER_in_jump_statement2380 = frozenset([25]) + FOLLOW_25_in_jump_statement2382 = frozenset([1]) + FOLLOW_114_in_jump_statement2387 = frozenset([25]) + FOLLOW_25_in_jump_statement2389 = frozenset([1]) + FOLLOW_115_in_jump_statement2394 = frozenset([25]) + FOLLOW_25_in_jump_statement2396 = frozenset([1]) + FOLLOW_116_in_jump_statement2401 = frozenset([25]) + FOLLOW_25_in_jump_statement2403 = frozenset([1]) + FOLLOW_116_in_jump_statement2408 = frozenset([4, 5, 6, 7, 8, 9, 10, 61, 65, 67, 68, 71, 72, 73, 76, 77, 78]) + FOLLOW_expression_in_jump_statement2410 = frozenset([25]) + FOLLOW_25_in_jump_statement2412 = frozenset([1]) + FOLLOW_declaration_specifiers_in_synpred290 = frozenset([1]) + FOLLOW_declaration_specifiers_in_synpred490 = frozenset([4, 58, 59, 60, 61, 65]) + FOLLOW_declarator_in_synpred493 = frozenset([4, 26, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 45, 46, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60]) + FOLLOW_declaration_in_synpred495 = frozenset([4, 26, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 45, 46, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60]) + FOLLOW_43_in_synpred498 = frozenset([1]) + FOLLOW_declaration_in_synpred5108 = frozenset([1]) + FOLLOW_declaration_specifiers_in_synpred7147 = frozenset([1]) + FOLLOW_declaration_specifiers_in_synpred10197 = frozenset([1]) + FOLLOW_type_specifier_in_synpred14262 = frozenset([1]) + FOLLOW_type_qualifier_in_synpred15276 = frozenset([1]) + FOLLOW_type_qualifier_in_synpred33434 = frozenset([1]) + FOLLOW_IDENTIFIER_in_synpred34432 = frozenset([4, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 65]) + FOLLOW_type_qualifier_in_synpred34434 = frozenset([4, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 65]) + FOLLOW_declarator_in_synpred34437 = frozenset([1]) + FOLLOW_type_qualifier_in_synpred39556 = frozenset([1]) + FOLLOW_type_specifier_in_synpred40560 = frozenset([1]) + FOLLOW_pointer_in_synpred65769 = frozenset([4, 58, 59, 60, 61]) + FOLLOW_58_in_synpred65773 = frozenset([4, 59, 60, 61]) + FOLLOW_59_in_synpred65778 = frozenset([4, 60, 61]) + FOLLOW_60_in_synpred65783 = frozenset([4, 61]) + FOLLOW_direct_declarator_in_synpred65787 = frozenset([1]) + FOLLOW_declarator_suffix_in_synpred66806 = frozenset([1]) + FOLLOW_58_in_synpred68815 = frozenset([1]) + FOLLOW_declarator_suffix_in_synpred69823 = frozenset([1]) + FOLLOW_61_in_synpred72863 = frozenset([4, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 45, 46, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 65]) + FOLLOW_parameter_type_list_in_synpred72865 = frozenset([62]) + FOLLOW_62_in_synpred72867 = frozenset([1]) + FOLLOW_61_in_synpred73877 = frozenset([4]) + FOLLOW_identifier_list_in_synpred73879 = frozenset([62]) + FOLLOW_62_in_synpred73881 = frozenset([1]) + FOLLOW_type_qualifier_in_synpred74906 = frozenset([1]) + FOLLOW_pointer_in_synpred75909 = frozenset([1]) + FOLLOW_65_in_synpred76904 = frozenset([49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60]) + FOLLOW_type_qualifier_in_synpred76906 = frozenset([1, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 65]) + FOLLOW_pointer_in_synpred76909 = frozenset([1]) + FOLLOW_65_in_synpred77915 = frozenset([65]) + FOLLOW_pointer_in_synpred77917 = frozenset([1]) + FOLLOW_53_in_synpred80962 = frozenset([1]) + FOLLOW_27_in_synpred81959 = frozenset([4, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 45, 46, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 65]) + FOLLOW_53_in_synpred81962 = frozenset([4, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 45, 46, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 65]) + FOLLOW_parameter_declaration_in_synpred81966 = frozenset([1]) + FOLLOW_declarator_in_synpred82982 = frozenset([1]) + FOLLOW_abstract_declarator_in_synpred83984 = frozenset([1]) + FOLLOW_declaration_specifiers_in_synpred85979 = frozenset([1, 4, 53, 58, 59, 60, 61, 63, 65]) + FOLLOW_declarator_in_synpred85982 = frozenset([1, 4, 53, 58, 59, 60, 61, 63, 65]) + FOLLOW_abstract_declarator_in_synpred85984 = frozenset([1, 4, 53, 58, 59, 60, 61, 63, 65]) + FOLLOW_53_in_synpred85989 = frozenset([1]) + FOLLOW_specifier_qualifier_list_in_synpred891031 = frozenset([1, 61, 63, 65]) + FOLLOW_abstract_declarator_in_synpred891033 = frozenset([1]) + FOLLOW_direct_abstract_declarator_in_synpred901052 = frozenset([1]) + FOLLOW_61_in_synpred921071 = frozenset([61, 63, 65]) + FOLLOW_abstract_declarator_in_synpred921073 = frozenset([62]) + FOLLOW_62_in_synpred921075 = frozenset([1]) + FOLLOW_abstract_declarator_suffix_in_synpred931083 = frozenset([1]) + FOLLOW_61_in_synpred1081267 = frozenset([4, 34, 35, 36, 37, 38, 39, 40, 41, 42, 45, 46, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60]) + FOLLOW_type_name_in_synpred1081269 = frozenset([62]) + FOLLOW_62_in_synpred1081271 = frozenset([4, 5, 6, 7, 8, 9, 10, 61, 65, 67, 68, 71, 72, 73, 76, 77, 78]) + FOLLOW_cast_expression_in_synpred1081273 = frozenset([1]) + FOLLOW_73_in_synpred1131315 = frozenset([4, 5, 6, 7, 8, 9, 10, 61, 65, 67, 68, 71, 72, 73, 76, 77, 78]) + FOLLOW_unary_expression_in_synpred1131317 = frozenset([1]) + FOLLOW_61_in_synpred1161405 = frozenset([4, 5, 6, 7, 8, 9, 10, 61, 65, 67, 68, 71, 72, 73, 76, 77, 78]) + FOLLOW_argument_expression_list_in_synpred1161409 = frozenset([62]) + FOLLOW_62_in_synpred1161413 = frozenset([1]) + FOLLOW_61_in_synpred1171429 = frozenset([4, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 45, 46, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 65]) + FOLLOW_macro_parameter_list_in_synpred1171431 = frozenset([62]) + FOLLOW_62_in_synpred1171433 = frozenset([1]) + FOLLOW_65_in_synpred1191467 = frozenset([4]) + FOLLOW_IDENTIFIER_in_synpred1191471 = frozenset([1]) + FOLLOW_STRING_LITERAL_in_synpred1361668 = frozenset([1]) + FOLLOW_IDENTIFIER_in_synpred1371665 = frozenset([4, 9]) + FOLLOW_STRING_LITERAL_in_synpred1371668 = frozenset([1, 9]) + FOLLOW_lvalue_in_synpred1411729 = frozenset([28, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88]) + FOLLOW_assignment_operator_in_synpred1411731 = frozenset([4, 5, 6, 7, 8, 9, 10, 61, 65, 67, 68, 71, 72, 73, 76, 77, 78]) + FOLLOW_assignment_expression_in_synpred1411733 = frozenset([1]) + FOLLOW_expression_statement_in_synpred1682020 = frozenset([1]) + FOLLOW_macro_statement_in_synpred1722040 = frozenset([1]) + FOLLOW_asm2_statement_in_synpred1732045 = frozenset([1]) + FOLLOW_declaration_in_synpred1802151 = frozenset([1]) + FOLLOW_statement_list_in_synpred1812155 = frozenset([1]) + FOLLOW_declaration_in_synpred1852210 = frozenset([1]) + FOLLOW_statement_in_synpred1872227 = frozenset([1]) + diff --git a/BaseTools/Source/Python/Ecc/Check.py b/BaseTools/Source/Python/Ecc/Check.py new file mode 100644 index 0000000000..c8bc54de3e --- /dev/null +++ b/BaseTools/Source/Python/Ecc/Check.py @@ -0,0 +1,865 @@ +## @file +# This file is used to define checkpoints used by ECC tool +# +# Copyright (c) 2008, 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. +# +import os +import re +from CommonDataClass.DataClass import * +from Common.DataType import SUP_MODULE_LIST_STRING, TAB_VALUE_SPLIT +from EccToolError import * +import EccGlobalData +import c + +## Check +# +# This class is to define checkpoints used by ECC tool +# +# @param object: Inherited from object class +# +class Check(object): + def __init__(self): + pass + + # Check all required checkpoints + def Check(self): + self.MetaDataFileCheck() + self.DoxygenCheck() + self.IncludeFileCheck() + self.PredicateExpressionCheck() + self.DeclAndDataTypeCheck() + self.FunctionLayoutCheck() + self.NamingConventionCheck() + + # C Function Layout Checking + def FunctionLayoutCheck(self): + self.FunctionLayoutCheckReturnType() + self.FunctionLayoutCheckModifier() + self.FunctionLayoutCheckName() + self.FunctionLayoutCheckPrototype() + self.FunctionLayoutCheckBody() + self.FunctionLayoutCheckLocalVariable() + + def WalkTree(self): + IgnoredPattern = c.GetIgnoredDirListPattern() + for Dirpath, Dirnames, Filenames in os.walk(EccGlobalData.gTarget): + for Dir in Dirnames: + Dirname = os.path.join(Dirpath, Dir) + if os.path.islink(Dirname): + Dirname = os.path.realpath(Dirname) + if os.path.isdir(Dirname): + # symlinks to directories are treated as directories + Dirnames.remove(Dir) + Dirnames.append(Dirname) + if IgnoredPattern.match(Dirpath.upper()): + continue + yield (Dirpath, Dirnames, Filenames) + + # Check whether return type exists and in the first line + def FunctionLayoutCheckReturnType(self): + if EccGlobalData.gConfig.CFunctionLayoutCheckReturnType == '1' or EccGlobalData.gConfig.CFunctionLayoutCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1': + EdkLogger.quiet("Checking function layout return type ...") + + for Dirpath, Dirnames, Filenames in self.WalkTree(): + for F in Filenames: + if os.path.splitext(F)[1] in ('.c', '.h'): + FullName = os.path.join(Dirpath, F) + c.CheckFuncLayoutReturnType(FullName) + + # Check whether any optional functional modifiers exist and next to the return type + def FunctionLayoutCheckModifier(self): + if EccGlobalData.gConfig.CFunctionLayoutCheckOptionalFunctionalModifier == '1' or EccGlobalData.gConfig.CFunctionLayoutCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1': + EdkLogger.quiet("Checking function layout modifier ...") + + for Dirpath, Dirnames, Filenames in self.WalkTree(): + for F in Filenames: + if os.path.splitext(F)[1] in ('.c', '.h'): + FullName = os.path.join(Dirpath, F) + c.CheckFuncLayoutModifier(FullName) + + # Check whether the next line contains the function name, left justified, followed by the beginning of the parameter list + # Check whether the closing parenthesis is on its own line and also indented two spaces + def FunctionLayoutCheckName(self): + if EccGlobalData.gConfig.CFunctionLayoutCheckFunctionName == '1' or EccGlobalData.gConfig.CFunctionLayoutCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1': + EdkLogger.quiet("Checking function layout function name ...") + + for Dirpath, Dirnames, Filenames in self.WalkTree(): + for F in Filenames: + if os.path.splitext(F)[1] in ('.c', '.h'): + FullName = os.path.join(Dirpath, F) + c.CheckFuncLayoutName(FullName) + # Check whether the function prototypes in include files have the same form as function definitions + def FunctionLayoutCheckPrototype(self): + if EccGlobalData.gConfig.CFunctionLayoutCheckFunctionPrototype == '1' or EccGlobalData.gConfig.CFunctionLayoutCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1': + EdkLogger.quiet("Checking function layout function prototype ...") + + for Dirpath, Dirnames, Filenames in self.WalkTree(): + for F in Filenames: + if os.path.splitext(F)[1] in ('.c'): + FullName = os.path.join(Dirpath, F) + EdkLogger.quiet("[PROTOTYPE]" + FullName) + c.CheckFuncLayoutPrototype(FullName) + + # Check whether the body of a function is contained by open and close braces that must be in the first column + def FunctionLayoutCheckBody(self): + if EccGlobalData.gConfig.CFunctionLayoutCheckFunctionBody == '1' or EccGlobalData.gConfig.CFunctionLayoutCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1': + EdkLogger.quiet("Checking function layout function body ...") + + for Dirpath, Dirnames, Filenames in self.WalkTree(): + for F in Filenames: + if os.path.splitext(F)[1] in ('.c'): + FullName = os.path.join(Dirpath, F) + c.CheckFuncLayoutBody(FullName) + + # Check whether the data declarations is the first code in a module. + # self.CFunctionLayoutCheckDataDeclaration = 1 + # Check whether no initialization of a variable as part of its declaration + def FunctionLayoutCheckLocalVariable(self): + if EccGlobalData.gConfig.CFunctionLayoutCheckNoInitOfVariable == '1' or EccGlobalData.gConfig.CFunctionLayoutCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1': + EdkLogger.quiet("Checking function layout local variables ...") + + for Dirpath, Dirnames, Filenames in self.WalkTree(): + for F in Filenames: + if os.path.splitext(F)[1] in ('.c'): + FullName = os.path.join(Dirpath, F) + c.CheckFuncLayoutLocalVariable(FullName) + + # Check whether no use of STATIC for functions + # self.CFunctionLayoutCheckNoStatic = 1 + + # Declarations and Data Types Checking + def DeclAndDataTypeCheck(self): + self.DeclCheckNoUseCType() + self.DeclCheckInOutModifier() + self.DeclCheckEFIAPIModifier() + self.DeclCheckEnumeratedType() + self.DeclCheckStructureDeclaration() + self.DeclCheckSameStructure() + self.DeclCheckUnionType() + + + # Check whether no use of int, unsigned, char, void, static, long in any .c, .h or .asl files. + def DeclCheckNoUseCType(self): + if EccGlobalData.gConfig.DeclarationDataTypeCheckNoUseCType == '1' or EccGlobalData.gConfig.DeclarationDataTypeCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1': + EdkLogger.quiet("Checking Declaration No use C type ...") + + for Dirpath, Dirnames, Filenames in self.WalkTree(): + for F in Filenames: + if os.path.splitext(F)[1] in ('.h', '.c'): + FullName = os.path.join(Dirpath, F) + c.CheckDeclNoUseCType(FullName) + + # Check whether the modifiers IN, OUT, OPTIONAL, and UNALIGNED are used only to qualify arguments to a function and should not appear in a data type declaration + def DeclCheckInOutModifier(self): + if EccGlobalData.gConfig.DeclarationDataTypeCheckInOutModifier == '1' or EccGlobalData.gConfig.DeclarationDataTypeCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1': + EdkLogger.quiet("Checking Declaration argument modifier ...") + + for Dirpath, Dirnames, Filenames in self.WalkTree(): + for F in Filenames: + if os.path.splitext(F)[1] in ('.h', '.c'): + FullName = os.path.join(Dirpath, F) + c.CheckDeclArgModifier(FullName) + + # Check whether the EFIAPI modifier should be used at the entry of drivers, events, and member functions of protocols + def DeclCheckEFIAPIModifier(self): + if EccGlobalData.gConfig.DeclarationDataTypeCheckEFIAPIModifier == '1' or EccGlobalData.gConfig.DeclarationDataTypeCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1': + pass + + # Check whether Enumerated Type has a 'typedef' and the name is capital + def DeclCheckEnumeratedType(self): + if EccGlobalData.gConfig.DeclarationDataTypeCheckEnumeratedType == '1' or EccGlobalData.gConfig.DeclarationDataTypeCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1': + EdkLogger.quiet("Checking Declaration enum typedef ...") + + for Dirpath, Dirnames, Filenames in self.WalkTree(): + for F in Filenames: + if os.path.splitext(F)[1] in ('.h', '.c'): + FullName = os.path.join(Dirpath, F) + EdkLogger.quiet("[ENUM]" + FullName) + c.CheckDeclEnumTypedef(FullName) + + # Check whether Structure Type has a 'typedef' and the name is capital + def DeclCheckStructureDeclaration(self): + if EccGlobalData.gConfig.DeclarationDataTypeCheckStructureDeclaration == '1' or EccGlobalData.gConfig.DeclarationDataTypeCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1': + EdkLogger.quiet("Checking Declaration struct typedef ...") + + for Dirpath, Dirnames, Filenames in self.WalkTree(): + for F in Filenames: + if os.path.splitext(F)[1] in ('.h', '.c'): + FullName = os.path.join(Dirpath, F) + EdkLogger.quiet("[STRUCT]" + FullName) + c.CheckDeclStructTypedef(FullName) + + # Check whether having same Structure + def DeclCheckSameStructure(self): + if EccGlobalData.gConfig.DeclarationDataTypeCheckSameStructure == '1' or EccGlobalData.gConfig.DeclarationDataTypeCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1': + EdkLogger.quiet("Checking same struct ...") + AllStructure = {} + for IdentifierTable in EccGlobalData.gIdentifierTableList: + SqlCommand = """select ID, Name, BelongsToFile from %s where Model = %s""" %(IdentifierTable, MODEL_IDENTIFIER_STRUCTURE) + RecordSet = EccGlobalData.gDb.TblFile.Exec(SqlCommand) + for Record in RecordSet: + if Record[1] != '': + if Record[1] not in AllStructure.keys(): + AllStructure[Record[1]] = Record[2] + else: + ID = AllStructure[Record[1]] + SqlCommand = """select FullPath from File where ID = %s """ % ID + NewRecordSet = EccGlobalData.gDb.TblFile.Exec(SqlCommand) + OtherMsg = "The structure name '%s' is duplicate" % Record[1] + if NewRecordSet != []: + OtherMsg = "The structure name [%s] is duplicate with the one defined in %s, maybe struct NOT typedefed or the typedef new type NOT used to qualify variables" % (Record[1], NewRecordSet[0][0]) + if not EccGlobalData.gException.IsException(ERROR_DECLARATION_DATA_TYPE_CHECK_SAME_STRUCTURE, Record[1]): + EccGlobalData.gDb.TblReport.Insert(ERROR_DECLARATION_DATA_TYPE_CHECK_SAME_STRUCTURE, OtherMsg = OtherMsg, BelongsToTable = IdentifierTable, BelongsToItem = Record[0]) + + # Check whether Union Type has a 'typedef' and the name is capital + def DeclCheckUnionType(self): + if EccGlobalData.gConfig.DeclarationDataTypeCheckUnionType == '1' or EccGlobalData.gConfig.DeclarationDataTypeCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1': + EdkLogger.quiet("Checking Declaration union typedef ...") + + for Dirpath, Dirnames, Filenames in self.WalkTree(): + for F in Filenames: + if os.path.splitext(F)[1] in ('.h', '.c'): + FullName = os.path.join(Dirpath, F) + EdkLogger.quiet("[UNION]" + FullName) + c.CheckDeclUnionTypedef(FullName) + + # Predicate Expression Checking + def PredicateExpressionCheck(self): + self.PredicateExpressionCheckBooleanValue() + self.PredicateExpressionCheckNonBooleanOperator() + self.PredicateExpressionCheckComparisonNullType() + + # Check whether Boolean values, variable type BOOLEAN not use explicit comparisons to TRUE or FALSE + def PredicateExpressionCheckBooleanValue(self): + if EccGlobalData.gConfig.PredicateExpressionCheckBooleanValue == '1' or EccGlobalData.gConfig.PredicateExpressionCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1': + EdkLogger.quiet("Checking predicate expression Boolean value ...") + + for Dirpath, Dirnames, Filenames in self.WalkTree(): + for F in Filenames: + if os.path.splitext(F)[1] in ('.c'): + FullName = os.path.join(Dirpath, F) + EdkLogger.quiet("[BOOLEAN]" + FullName) + c.CheckBooleanValueComparison(FullName) + + # Check whether Non-Boolean comparisons use a compare operator (==, !=, >, < >=, <=). + def PredicateExpressionCheckNonBooleanOperator(self): + if EccGlobalData.gConfig.PredicateExpressionCheckNonBooleanOperator == '1' or EccGlobalData.gConfig.PredicateExpressionCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1': + EdkLogger.quiet("Checking predicate expression Non-Boolean variable...") + + for Dirpath, Dirnames, Filenames in self.WalkTree(): + for F in Filenames: + if os.path.splitext(F)[1] in ('.c'): + FullName = os.path.join(Dirpath, F) + EdkLogger.quiet("[NON-BOOLEAN]" + FullName) + c.CheckNonBooleanValueComparison(FullName) + # Check whether a comparison of any pointer to zero must be done via the NULL type + def PredicateExpressionCheckComparisonNullType(self): + if EccGlobalData.gConfig.PredicateExpressionCheckComparisonNullType == '1' or EccGlobalData.gConfig.PredicateExpressionCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1': + EdkLogger.quiet("Checking predicate expression NULL pointer ...") + + for Dirpath, Dirnames, Filenames in self.WalkTree(): + for F in Filenames: + if os.path.splitext(F)[1] in ('.c'): + FullName = os.path.join(Dirpath, F) + EdkLogger.quiet("[POINTER]" + FullName) + c.CheckPointerNullComparison(FullName) + # Include file checking + def IncludeFileCheck(self): + self.IncludeFileCheckIfndef() + self.IncludeFileCheckData() + self.IncludeFileCheckSameName() + + # Check whether having include files with same name + def IncludeFileCheckSameName(self): + if EccGlobalData.gConfig.IncludeFileCheckSameName == '1' or EccGlobalData.gConfig.IncludeFileCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1': + EdkLogger.quiet("Checking same header file name ...") + SqlCommand = """select ID, FullPath from File + where Model = 1002 order by Name """ + RecordDict = {} + RecordSet = EccGlobalData.gDb.TblFile.Exec(SqlCommand) + for Record in RecordSet: + List = Record[1].replace('/', '\\').split('\\') + if len(List) >= 2: + Key = List[-2] + '\\' + List[-1] + else: + Key = List[0] + if Key not in RecordDict: + RecordDict[Key] = [Record] + else: + RecordDict[Key].append(Record) + + for Key in RecordDict: + if len(RecordDict[Key]) > 1: + for Item in RecordDict[Key]: + EccGlobalData.gDb.TblReport.Insert(ERROR_INCLUDE_FILE_CHECK_NAME, OtherMsg = "The file name for '%s' is duplicate" % (Item[1]), BelongsToTable = 'File', BelongsToItem = Item[0]) + + # Check whether all include file contents is guarded by a #ifndef statement. + def IncludeFileCheckIfndef(self): + if EccGlobalData.gConfig.IncludeFileCheckIfndefStatement == '1' or EccGlobalData.gConfig.IncludeFileCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1': + EdkLogger.quiet("Checking header file ifndef ...") + + for Dirpath, Dirnames, Filenames in self.WalkTree(): + for F in Filenames: + if os.path.splitext(F)[1] in ('.h'): + FullName = os.path.join(Dirpath, F) + MsgList = c.CheckHeaderFileIfndef(FullName) + + # Check whether include files NOT contain code or define data variables + def IncludeFileCheckData(self): + if EccGlobalData.gConfig.IncludeFileCheckData == '1' or EccGlobalData.gConfig.IncludeFileCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1': + EdkLogger.quiet("Checking header file data ...") + + for Dirpath, Dirnames, Filenames in self.WalkTree(): + for F in Filenames: + if os.path.splitext(F)[1] in ('.h'): + FullName = os.path.join(Dirpath, F) + MsgList = c.CheckHeaderFileData(FullName) + + # Doxygen document checking + def DoxygenCheck(self): + self.DoxygenCheckFileHeader() + self.DoxygenCheckFunctionHeader() + self.DoxygenCheckCommentDescription() + self.DoxygenCheckCommentFormat() + self.DoxygenCheckCommand() + + # Check whether the file headers are followed Doxygen special documentation blocks in section 2.3.5 + def DoxygenCheckFileHeader(self): + if EccGlobalData.gConfig.DoxygenCheckFileHeader == '1' or EccGlobalData.gConfig.DoxygenCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1': + EdkLogger.quiet("Checking Doxygen file header ...") + + for Dirpath, Dirnames, Filenames in self.WalkTree(): + for F in Filenames: + if os.path.splitext(F)[1] in ('.h', '.c'): + FullName = os.path.join(Dirpath, F) + MsgList = c.CheckFileHeaderDoxygenComments(FullName) + + # Check whether the function headers are followed Doxygen special documentation blocks in section 2.3.5 + def DoxygenCheckFunctionHeader(self): + if EccGlobalData.gConfig.DoxygenCheckFunctionHeader == '1' or EccGlobalData.gConfig.DoxygenCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1': + EdkLogger.quiet("Checking Doxygen function header ...") + + for Dirpath, Dirnames, Filenames in self.WalkTree(): + for F in Filenames: + if os.path.splitext(F)[1] in ('.h', '.c'): + FullName = os.path.join(Dirpath, F) + MsgList = c.CheckFuncHeaderDoxygenComments(FullName) + + # Check whether the first line of text in a comment block is a brief description of the element being documented. + # The brief description must end with a period. + def DoxygenCheckCommentDescription(self): + if EccGlobalData.gConfig.DoxygenCheckCommentDescription == '1' or EccGlobalData.gConfig.DoxygenCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1': + pass + + # Check whether comment lines with '///< ... text ...' format, if it is used, it should be after the code section. + def DoxygenCheckCommentFormat(self): + if EccGlobalData.gConfig.DoxygenCheckCommentFormat == '1' or EccGlobalData.gConfig.DoxygenCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1': + EdkLogger.quiet("Checking Doxygen comment ///< ...") + + for Dirpath, Dirnames, Filenames in self.WalkTree(): + for F in Filenames: + if os.path.splitext(F)[1] in ('.h', '.c'): + FullName = os.path.join(Dirpath, F) + MsgList = c.CheckDoxygenTripleForwardSlash(FullName) + + # Check whether only Doxygen commands allowed to mark the code are @bug and @todo. + def DoxygenCheckCommand(self): + if EccGlobalData.gConfig.DoxygenCheckCommand == '1' or EccGlobalData.gConfig.DoxygenCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1': + EdkLogger.quiet("Checking Doxygen command ...") + + for Dirpath, Dirnames, Filenames in self.WalkTree(): + for F in Filenames: + if os.path.splitext(F)[1] in ('.h', '.c'): + FullName = os.path.join(Dirpath, F) + MsgList = c.CheckDoxygenCommand(FullName) + + # Meta-Data File Processing Checking + def MetaDataFileCheck(self): + self.MetaDataFileCheckPathName() + self.MetaDataFileCheckGenerateFileList() + self.MetaDataFileCheckLibraryInstance() + self.MetaDataFileCheckLibraryInstanceDependent() + self.MetaDataFileCheckLibraryInstanceOrder() + self.MetaDataFileCheckLibraryNoUse() + self.MetaDataFileCheckBinaryInfInFdf() + self.MetaDataFileCheckPcdDuplicate() + self.MetaDataFileCheckPcdFlash() + self.MetaDataFileCheckPcdNoUse() + self.MetaDataFileCheckGuidDuplicate() + self.MetaDataFileCheckModuleFileNoUse() + self.MetaDataFileCheckPcdType() + + # Check whether each file defined in meta-data exists + def MetaDataFileCheckPathName(self): + if EccGlobalData.gConfig.MetaDataFileCheckPathName == '1' or EccGlobalData.gConfig.MetaDataFileCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1': + # This item is covered when parsing Inf/Dec/Dsc files + pass + + # Generate a list for all files defined in meta-data files + def MetaDataFileCheckGenerateFileList(self): + if EccGlobalData.gConfig.MetaDataFileCheckGenerateFileList == '1' or EccGlobalData.gConfig.MetaDataFileCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1': + # This item is covered when parsing Inf/Dec/Dsc files + pass + + # Check whether all Library Instances defined for a given module (or dependent library instance) match the module's type. + # Each Library Instance must specify the Supported Module Types in its Inf file, + # and any module specifying the library instance must be one of the supported types. + def MetaDataFileCheckLibraryInstance(self): + if EccGlobalData.gConfig.MetaDataFileCheckLibraryInstance == '1' or EccGlobalData.gConfig.MetaDataFileCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1': + EdkLogger.quiet("Checking for library instance type issue ...") + SqlCommand = """select A.ID, A.Value2, B.Value2 from Inf as A left join Inf as B + where A.Value1 = 'LIBRARY_CLASS' and A.Model = %s + and B.Value1 = 'MODULE_TYPE' and B.Model = %s and A.BelongsToFile = B.BelongsToFile + group by A.BelongsToFile""" % (MODEL_META_DATA_HEADER, MODEL_META_DATA_HEADER) + RecordSet = EccGlobalData.gDb.TblInf.Exec(SqlCommand) + LibraryClasses = {} + for Record in RecordSet: + List = Record[1].split('|', 1) + SupModType = [] + if len(List) == 1: + SupModType = SUP_MODULE_LIST_STRING.split(TAB_VALUE_SPLIT) + elif len(List) == 2: + SupModType = List[1].split() + + if List[0] not in LibraryClasses: + LibraryClasses[List[0]] = SupModType + else: + for Item in SupModType: + if Item not in LibraryClasses[List[0]]: + LibraryClasses[List[0]].append(Item) + + if Record[2] != 'BASE' and Record[2] not in SupModType: + EccGlobalData.gDb.TblReport.Insert(ERROR_META_DATA_FILE_CHECK_LIBRARY_INSTANCE_2, OtherMsg = "The Library Class '%s' does not specify its supported module types" % (List[0]), BelongsToTable = 'Inf', BelongsToItem = Record[0]) + + SqlCommand = """select A.ID, A.Value1, B.Value2 from Inf as A left join Inf as B + where A.Model = %s and B.Value1 = '%s' and B.Model = %s + and B.BelongsToFile = A.BelongsToFile""" \ + % (MODEL_EFI_LIBRARY_CLASS, 'MODULE_TYPE', MODEL_META_DATA_HEADER) + RecordSet = EccGlobalData.gDb.TblInf.Exec(SqlCommand) + # Merge all LibraryClasses' supmodlist + RecordDict = {} + for Record in RecordSet: + if Record[1] not in RecordDict: + RecordDict[Record[1]] = [str(Record[2])] + else: + if Record[2] not in RecordDict[Record[1]]: + RecordDict[Record[1]].append(Record[2]) + + for Record in RecordSet: + if Record[1] in LibraryClasses: + if Record[2] not in LibraryClasses[Record[1]] and 'BASE' not in RecordDict[Record[1]]: + if not EccGlobalData.gException.IsException(ERROR_META_DATA_FILE_CHECK_LIBRARY_INSTANCE_1, Record[1]): + EccGlobalData.gDb.TblReport.Insert(ERROR_META_DATA_FILE_CHECK_LIBRARY_INSTANCE_1, OtherMsg = "The type of Library Class [%s] defined in Inf file does not match the type of the module" % (Record[1]), BelongsToTable = 'Inf', BelongsToItem = Record[0]) + else: + if not EccGlobalData.gException.IsException(ERROR_META_DATA_FILE_CHECK_LIBRARY_INSTANCE_1, Record[1]): + EccGlobalData.gDb.TblReport.Insert(ERROR_META_DATA_FILE_CHECK_LIBRARY_INSTANCE_1, OtherMsg = "The type of Library Class [%s] defined in Inf file does not match the type of the module" % (Record[1]), BelongsToTable = 'Inf', BelongsToItem = Record[0]) + + # Check whether a Library Instance has been defined for all dependent library classes + def MetaDataFileCheckLibraryInstanceDependent(self): + if EccGlobalData.gConfig.MetaDataFileCheckLibraryInstanceDependent == '1' or EccGlobalData.gConfig.MetaDataFileCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1': + EdkLogger.quiet("Checking for library instance dependent issue ...") + SqlCommand = """select ID, Value1, Value2 from Dsc where Model = %s""" % MODEL_EFI_LIBRARY_CLASS + LibraryClasses = EccGlobalData.gDb.TblDsc.Exec(SqlCommand) + for LibraryClass in LibraryClasses: + if LibraryClass[1].upper() != 'NULL': + LibraryIns = os.path.normpath(os.path.join(EccGlobalData.gWorkspace, LibraryClass[2])) + SqlCommand = """select Value2 from Inf where BelongsToFile = + (select ID from File where lower(FullPath) = lower('%s')) + and Value1 = '%s'""" % (LibraryIns, 'LIBRARY_CLASS') + RecordSet = EccGlobalData.gDb.TblInf.Exec(SqlCommand) + IsFound = False + for Record in RecordSet: + LibName = Record[0].split('|', 1)[0] + if LibraryClass[1] == LibName: + IsFound = True + if not IsFound: + if not EccGlobalData.gException.IsException(ERROR_META_DATA_FILE_CHECK_LIBRARY_INSTANCE_DEPENDENT, LibraryClass[1]): + EccGlobalData.gDb.TblReport.Insert(ERROR_META_DATA_FILE_CHECK_LIBRARY_INSTANCE_DEPENDENT, OtherMsg = "The Library Class [%s] is not specified in '%s'" % (LibraryClass[1], LibraryClass[2]), BelongsToTable = 'Dsc', BelongsToItem = LibraryClass[0]) + + # Check whether the Library Instances specified by the LibraryClasses sections are listed in order of dependencies + def MetaDataFileCheckLibraryInstanceOrder(self): + if EccGlobalData.gConfig.MetaDataFileCheckLibraryInstanceOrder == '1' or EccGlobalData.gConfig.MetaDataFileCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1': + # This checkpoint is not necessary for Ecc check + pass + + # Check whether the unnecessary inclusion of library classes in the Inf file + def MetaDataFileCheckLibraryNoUse(self): + if EccGlobalData.gConfig.MetaDataFileCheckLibraryNoUse == '1' or EccGlobalData.gConfig.MetaDataFileCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1': + EdkLogger.quiet("Checking for library instance not used ...") + SqlCommand = """select ID, Value1 from Inf as A where A.Model = %s and A.Value1 not in (select B.Value1 from Dsc as B where Model = %s)""" % (MODEL_EFI_LIBRARY_CLASS, MODEL_EFI_LIBRARY_CLASS) + RecordSet = EccGlobalData.gDb.TblInf.Exec(SqlCommand) + for Record in RecordSet: + if not EccGlobalData.gException.IsException(ERROR_META_DATA_FILE_CHECK_LIBRARY_NO_USE, Record[1]): + EccGlobalData.gDb.TblReport.Insert(ERROR_META_DATA_FILE_CHECK_LIBRARY_NO_USE, OtherMsg = "The Library Class [%s] is not used in any platform" % (Record[1]), BelongsToTable = 'Inf', BelongsToItem = Record[0]) + + # Check whether an Inf file is specified in the FDF file, but not in the Dsc file, then the Inf file must be for a Binary module only + def MetaDataFileCheckBinaryInfInFdf(self): + if EccGlobalData.gConfig.MetaDataFileCheckBinaryInfInFdf == '1' or EccGlobalData.gConfig.MetaDataFileCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1': + EdkLogger.quiet("Checking for non-binary modules defined in FDF files ...") + SqlCommand = """select A.ID, A.Value1 from Fdf as A + where A.Model = %s + and A.Enabled > -1 + and A.Value1 not in + (select B.Value1 from Dsc as B + where B.Model = %s + and B.Enabled > -1)""" % (MODEL_META_DATA_COMPONENT, MODEL_META_DATA_COMPONENT) + RecordSet = EccGlobalData.gDb.TblFdf.Exec(SqlCommand) + for Record in RecordSet: + FdfID = Record[0] + FilePath = Record[1] + FilePath = os.path.normpath(os.path.join(EccGlobalData.gWorkspace, FilePath)) + SqlCommand = """select ID from Inf where Model = %s and BelongsToFile = (select ID from File where FullPath like '%s') + """ % (MODEL_EFI_SOURCE_FILE, FilePath) + NewRecordSet = EccGlobalData.gDb.TblFile.Exec(SqlCommand) + if NewRecordSet!= []: + if not EccGlobalData.gException.IsException(ERROR_META_DATA_FILE_CHECK_BINARY_INF_IN_FDF, FilePath): + EccGlobalData.gDb.TblReport.Insert(ERROR_META_DATA_FILE_CHECK_BINARY_INF_IN_FDF, OtherMsg = "File [%s] defined in FDF file and not in DSC file must be a binary module" % (FilePath), BelongsToTable = 'Fdf', BelongsToItem = FdfID) + + # Check whether a PCD is set in a Dsc file or the FDF file, but not in both. + def MetaDataFileCheckPcdDuplicate(self): + if EccGlobalData.gConfig.MetaDataFileCheckPcdDuplicate == '1' or EccGlobalData.gConfig.MetaDataFileCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1': + EdkLogger.quiet("Checking for duplicate PCDs defined in both DSC and FDF files ...") + SqlCommand = """ + select A.ID, A.Value2, B.ID, B.Value2 from Dsc as A, Fdf as B + where A.Model >= %s and A.Model < %s + and B.Model >= %s and B.Model < %s + and A.Value2 = B.Value2 + and A.Enabled > -1 + and B.Enabled > -1 + group by A.ID + """% (MODEL_PCD, MODEL_META_DATA_HEADER, MODEL_PCD, MODEL_META_DATA_HEADER) + RecordSet = EccGlobalData.gDb.TblDsc.Exec(SqlCommand) + for Record in RecordSet: + if not EccGlobalData.gException.IsException(ERROR_META_DATA_FILE_CHECK_PCD_DUPLICATE, Record[1]): + EccGlobalData.gDb.TblReport.Insert(ERROR_META_DATA_FILE_CHECK_PCD_DUPLICATE, OtherMsg = "The PCD [%s] is defined in both FDF file and DSC file" % (Record[1]), BelongsToTable = 'Dsc', BelongsToItem = Record[0]) + if not EccGlobalData.gException.IsException(ERROR_META_DATA_FILE_CHECK_PCD_DUPLICATE, Record[3]): + EccGlobalData.gDb.TblReport.Insert(ERROR_META_DATA_FILE_CHECK_PCD_DUPLICATE, OtherMsg = "The PCD [%s] is defined in both FDF file and DSC file" % (Record[3]), BelongsToTable = 'Fdf', BelongsToItem = Record[2]) + + EdkLogger.quiet("Checking for duplicate PCDs defined in DEC files ...") + SqlCommand = """ + select A.ID, A.Value2 from Dec as A, Dec as B + where A.Model >= %s and A.Model < %s + and B.Model >= %s and B.Model < %s + and A.Value2 = B.Value2 + and ((A.Arch = B.Arch) and (A.Arch != 'COMMON' or B.Arch != 'COMMON')) + and A.ID != B.ID + and A.Enabled > -1 + and B.Enabled > -1 + and A.BelongsToFile = B.BelongsToFile + group by A.ID + """% (MODEL_PCD, MODEL_META_DATA_HEADER, MODEL_PCD, MODEL_META_DATA_HEADER) + RecordSet = EccGlobalData.gDb.TblDsc.Exec(SqlCommand) + for Record in RecordSet: + if not EccGlobalData.gException.IsException(ERROR_META_DATA_FILE_CHECK_PCD_DUPLICATE, Record[1]): + EccGlobalData.gDb.TblReport.Insert(ERROR_META_DATA_FILE_CHECK_PCD_DUPLICATE, OtherMsg = "The PCD [%s] is defined duplicated in DEC file" % (Record[1]), BelongsToTable = 'Dec', BelongsToItem = Record[0]) + + # Check whether PCD settings in the FDF file can only be related to flash. + def MetaDataFileCheckPcdFlash(self): + if EccGlobalData.gConfig.MetaDataFileCheckPcdFlash == '1' or EccGlobalData.gConfig.MetaDataFileCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1': + EdkLogger.quiet("Checking only Flash related PCDs are used in FDF ...") + SqlCommand = """ + select ID, Value2, BelongsToFile from Fdf as A + where A.Model >= %s and Model < %s + and A.Enabled > -1 + and A.Value2 not like '%%Flash%%' + """% (MODEL_PCD, MODEL_META_DATA_HEADER) + RecordSet = EccGlobalData.gDb.TblFdf.Exec(SqlCommand) + for Record in RecordSet: + if not EccGlobalData.gException.IsException(ERROR_META_DATA_FILE_CHECK_PCD_FLASH, Record[1]): + EccGlobalData.gDb.TblReport.Insert(ERROR_META_DATA_FILE_CHECK_PCD_FLASH, OtherMsg = "The PCD [%s] defined in FDF file is not related to Flash" % (Record[1]), BelongsToTable = 'Fdf', BelongsToItem = Record[0]) + + # Check whether PCDs used in Inf files but not specified in Dsc or FDF files + def MetaDataFileCheckPcdNoUse(self): + if EccGlobalData.gConfig.MetaDataFileCheckPcdNoUse == '1' or EccGlobalData.gConfig.MetaDataFileCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1': + EdkLogger.quiet("Checking for non-specified PCDs ...") + SqlCommand = """ + select ID, Value2, BelongsToFile from Inf as A + where A.Model >= %s and Model < %s + and A.Enabled > -1 + and A.Value2 not in + (select Value2 from Dsc as B + where B.Model >= %s and B.Model < %s + and B.Enabled > -1) + and A.Value2 not in + (select Value2 from Fdf as C + where C.Model >= %s and C.Model < %s + and C.Enabled > -1) + """% (MODEL_PCD, MODEL_META_DATA_HEADER, MODEL_PCD, MODEL_META_DATA_HEADER, MODEL_PCD, MODEL_META_DATA_HEADER) + RecordSet = EccGlobalData.gDb.TblInf.Exec(SqlCommand) + for Record in RecordSet: + if not EccGlobalData.gException.IsException(ERROR_META_DATA_FILE_CHECK_PCD_NO_USE, Record[1]): + EccGlobalData.gDb.TblReport.Insert(ERROR_META_DATA_FILE_CHECK_PCD_NO_USE, OtherMsg = "The PCD [%s] defined in INF file is not specified in either DSC or FDF files" % (Record[1]), BelongsToTable = 'Inf', BelongsToItem = Record[0]) + + # Check whether having duplicate guids defined for Guid/Protocol/Ppi + def MetaDataFileCheckGuidDuplicate(self): + if EccGlobalData.gConfig.MetaDataFileCheckGuidDuplicate == '1' or EccGlobalData.gConfig.MetaDataFileCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1': + EdkLogger.quiet("Checking for duplicate GUID/PPI/PROTOCOL ...") + # Check Guid + self.CheckGuidProtocolPpi(ERROR_META_DATA_FILE_CHECK_DUPLICATE_GUID, MODEL_EFI_GUID, EccGlobalData.gDb.TblDec) + self.CheckGuidProtocolPpi(ERROR_META_DATA_FILE_CHECK_DUPLICATE_GUID, MODEL_EFI_GUID, EccGlobalData.gDb.TblDsc) + self.CheckGuidProtocolPpiValue(ERROR_META_DATA_FILE_CHECK_DUPLICATE_GUID, MODEL_EFI_GUID) + # Check protocol + self.CheckGuidProtocolPpi(ERROR_META_DATA_FILE_CHECK_DUPLICATE_PROTOCOL, MODEL_EFI_PROTOCOL, EccGlobalData.gDb.TblDec) + self.CheckGuidProtocolPpi(ERROR_META_DATA_FILE_CHECK_DUPLICATE_PROTOCOL, MODEL_EFI_PROTOCOL, EccGlobalData.gDb.TblDsc) + self.CheckGuidProtocolPpiValue(ERROR_META_DATA_FILE_CHECK_DUPLICATE_PROTOCOL, MODEL_EFI_PROTOCOL) + # Check ppi + self.CheckGuidProtocolPpi(ERROR_META_DATA_FILE_CHECK_DUPLICATE_PPI, MODEL_EFI_PPI, EccGlobalData.gDb.TblDec) + self.CheckGuidProtocolPpi(ERROR_META_DATA_FILE_CHECK_DUPLICATE_PPI, MODEL_EFI_PPI, EccGlobalData.gDb.TblDsc) + self.CheckGuidProtocolPpiValue(ERROR_META_DATA_FILE_CHECK_DUPLICATE_PPI, MODEL_EFI_PPI) + + # Check whether all files under module directory are described in INF files + def MetaDataFileCheckModuleFileNoUse(self): + if EccGlobalData.gConfig.MetaDataFileCheckModuleFileNoUse == '1' or EccGlobalData.gConfig.MetaDataFileCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1': + EdkLogger.quiet("Checking for no used module files ...") + SqlCommand = """ + select upper(Path) from File where ID in (select BelongsToFile from INF where BelongsToFile != -1) + """ + InfPathSet = EccGlobalData.gDb.TblInf.Exec(SqlCommand) + InfPathList = [] + for Item in InfPathSet: + if Item[0] not in InfPathList: + InfPathList.append(Item[0]) + SqlCommand = """ + select ID, Path, FullPath from File where upper(FullPath) not in + (select upper(A.Path) || '\\' || upper(B.Value1) from File as A, INF as B + where A.ID in (select BelongsToFile from INF where Model = %s group by BelongsToFile) and + B.BelongsToFile = A.ID and B.Model = %s) + and (Model = %s or Model = %s) + """ % (MODEL_EFI_SOURCE_FILE, MODEL_EFI_SOURCE_FILE, MODEL_FILE_C, MODEL_FILE_H) + RecordSet = EccGlobalData.gDb.TblInf.Exec(SqlCommand) + for Record in RecordSet: + Path = Record[1] + Path = Path.upper().replace('\X64', '').replace('\IA32', '').replace('\EBC', '').replace('\IPF', '').replace('\ARM', '') + if Path in InfPathList: + if not EccGlobalData.gException.IsException(ERROR_META_DATA_FILE_CHECK_MODULE_FILE_NO_USE, Record[2]): + EccGlobalData.gDb.TblReport.Insert(ERROR_META_DATA_FILE_CHECK_MODULE_FILE_NO_USE, OtherMsg = "The source file [%s] is existing in module directory but it is not described in INF file." % (Record[2]), BelongsToTable = 'File', BelongsToItem = Record[0]) + + # Check whether the PCD is correctly used in C function via its type + def MetaDataFileCheckPcdType(self): + if EccGlobalData.gConfig.MetaDataFileCheckPcdType == '1' or EccGlobalData.gConfig.MetaDataFileCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1': + EdkLogger.quiet("Checking for pcd type in c code function usage ...") + SqlCommand = """ + select ID, Model, Value1, BelongsToFile from INF where Model > %s and Model < %s + """ % (MODEL_PCD, MODEL_META_DATA_HEADER) + PcdSet = EccGlobalData.gDb.TblInf.Exec(SqlCommand) + for Pcd in PcdSet: + Model = Pcd[1] + PcdName = Pcd[2] + if len(Pcd[2].split(".")) > 1: + PcdName = Pcd[2].split(".")[1] + BelongsToFile = Pcd[3] + SqlCommand = """ + select ID from File where FullPath in + (select B.Path || '\\' || A.Value1 from INF as A, File as B where A.Model = %s and A.BelongsToFile = %s + and B.ID = %s) + """ %(MODEL_EFI_SOURCE_FILE, BelongsToFile, BelongsToFile) + TableSet = EccGlobalData.gDb.TblFile.Exec(SqlCommand) + for Tbl in TableSet: + TblName = 'Identifier' + str(Tbl[0]) + SqlCommand = """ + select Name, ID from %s where value like '%%%s%%' and Model = %s + """ % (TblName, PcdName, MODEL_IDENTIFIER_FUNCTION_CALLING) + RecordSet = EccGlobalData.gDb.TblInf.Exec(SqlCommand) + TblNumber = TblName.replace('Identifier', '') + for Record in RecordSet: + FunName = Record[0] + if not EccGlobalData.gException.IsException(ERROR_META_DATA_FILE_CHECK_PCD_TYPE, FunName): + if Model in [MODEL_PCD_FIXED_AT_BUILD] and not FunName.startswith('FixedPcdGet'): + EccGlobalData.gDb.TblReport.Insert(ERROR_META_DATA_FILE_CHECK_PCD_TYPE, OtherMsg = "The pcd '%s' is defined as a FixPcd but now it is called by c function [%s]" % (PcdName, FunName), BelongsToTable = TblName, BelongsToItem = Record[1]) + if Model in [MODEL_PCD_FEATURE_FLAG] and (not FunName.startswith('FeaturePcdGet') and not FunName.startswith('FeaturePcdSet')): + EccGlobalData.gDb.TblReport.Insert(ERROR_META_DATA_FILE_CHECK_PCD_TYPE, OtherMsg = "The pcd '%s' is defined as a FeaturePcd but now it is called by c function [%s]" % (PcdName, FunName), BelongsToTable = TblName, BelongsToItem = Record[1]) + if Model in [MODEL_PCD_PATCHABLE_IN_MODULE] and (not FunName.startswith('PatchablePcdGet') and not FunName.startswith('PatchablePcdSet')): + EccGlobalData.gDb.TblReport.Insert(ERROR_META_DATA_FILE_CHECK_PCD_TYPE, OtherMsg = "The pcd '%s' is defined as a PatchablePcd but now it is called by c function [%s]" % (PcdName, FunName), BelongsToTable = TblName, BelongsToItem = Record[1]) + + #ERROR_META_DATA_FILE_CHECK_PCD_TYPE + pass + + # Check whether these is duplicate Guid/Ppi/Protocol name + def CheckGuidProtocolPpi(self, ErrorID, Model, Table): + Name = '' + if Model == MODEL_EFI_GUID: + Name = 'guid' + if Model == MODEL_EFI_PROTOCOL: + Name = 'protocol' + if Model == MODEL_EFI_PPI: + Name = 'ppi' + SqlCommand = """ + select A.ID, A.Value1 from %s as A, %s as B + where A.Model = %s and B.Model = %s + and A.Value1 = B.Value1 and A.ID <> B.ID + and A.Enabled > -1 + and B.Enabled > -1 + group by A.ID + """ % (Table.Table, Table.Table, Model, Model) + RecordSet = Table.Exec(SqlCommand) + for Record in RecordSet: + if not EccGlobalData.gException.IsException(ErrorID, Record[1]): + EccGlobalData.gDb.TblReport.Insert(ErrorID, OtherMsg = "The %s name [%s] is defined more than one time" % (Name.upper(), Record[1]), BelongsToTable = Table.Table, BelongsToItem = Record[0]) + + # Check whether these is duplicate Guid/Ppi/Protocol value + def CheckGuidProtocolPpiValue(self, ErrorID, Model): + Name = '' + Table = EccGlobalData.gDb.TblDec + if Model == MODEL_EFI_GUID: + Name = 'guid' + if Model == MODEL_EFI_PROTOCOL: + Name = 'protocol' + if Model == MODEL_EFI_PPI: + Name = 'ppi' + SqlCommand = """ + select A.ID, A.Value2 from %s as A, %s as B + where A.Model = %s and B.Model = %s + and A.Value2 = B.Value2 and A.ID <> B.ID + group by A.ID + """ % (Table.Table, Table.Table, Model, Model) + RecordSet = Table.Exec(SqlCommand) + for Record in RecordSet: + if not EccGlobalData.gException.IsException(ErrorID, Record[1]): + EccGlobalData.gDb.TblReport.Insert(ErrorID, OtherMsg = "The %s value [%s] is used more than one time" % (Name.upper(), Record[1]), BelongsToTable = Table.Table, BelongsToItem = Record[0]) + + # Naming Convention Check + def NamingConventionCheck(self): + + for Dirpath, Dirnames, Filenames in self.WalkTree(): + for F in Filenames: + if os.path.splitext(F)[1] in ('.h', '.c'): + FullName = os.path.join(Dirpath, F) + Id = c.GetTableID(FullName) + if Id < 0: + continue + FileTable = 'Identifier' + str(Id) + self.NamingConventionCheckDefineStatement(FileTable) + self.NamingConventionCheckTypedefStatement(FileTable) + self.NamingConventionCheckIfndefStatement(FileTable) + self.NamingConventionCheckVariableName(FileTable) + self.NamingConventionCheckSingleCharacterVariable(FileTable) + + self.NamingConventionCheckPathName() + self.NamingConventionCheckFunctionName() + + # Check whether only capital letters are used for #define declarations + def NamingConventionCheckDefineStatement(self, FileTable): + if EccGlobalData.gConfig.NamingConventionCheckDefineStatement == '1' or EccGlobalData.gConfig.NamingConventionCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1': + EdkLogger.quiet("Checking naming covention of #define statement ...") + + SqlCommand = """select ID, Value from %s where Model = %s""" %(FileTable, MODEL_IDENTIFIER_MACRO_DEFINE) + RecordSet = EccGlobalData.gDb.TblFile.Exec(SqlCommand) + for Record in RecordSet: + Name = Record[1].strip().split()[1] + if Name.find('(') != -1: + Name = Name[0:Name.find('(')] + if Name.upper() != Name: + if not EccGlobalData.gException.IsException(ERROR_NAMING_CONVENTION_CHECK_DEFINE_STATEMENT, Name): + EccGlobalData.gDb.TblReport.Insert(ERROR_NAMING_CONVENTION_CHECK_DEFINE_STATEMENT, OtherMsg = "The #define name [%s] does not follow the rules" % (Name), BelongsToTable = FileTable, BelongsToItem = Record[0]) + + # Check whether only capital letters are used for typedef declarations + def NamingConventionCheckTypedefStatement(self, FileTable): + if EccGlobalData.gConfig.NamingConventionCheckTypedefStatement == '1' or EccGlobalData.gConfig.NamingConventionCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1': + EdkLogger.quiet("Checking naming covention of #typedef statement ...") + + SqlCommand = """select ID, Name from %s where Model = %s""" %(FileTable, MODEL_IDENTIFIER_TYPEDEF) + RecordSet = EccGlobalData.gDb.TblFile.Exec(SqlCommand) + for Record in RecordSet: + Name = Record[1].strip() + if Name != '' and Name != None: + if Name[0] == '(': + Name = Name[1:Name.find(')')] + if Name.find('(') > -1: + Name = Name[Name.find('(') + 1 : Name.find(')')] + Name = Name.replace('WINAPI', '') + Name = Name.replace('*', '').strip() + if Name.upper() != Name: + if not EccGlobalData.gException.IsException(ERROR_NAMING_CONVENTION_CHECK_TYPEDEF_STATEMENT, Name): + EccGlobalData.gDb.TblReport.Insert(ERROR_NAMING_CONVENTION_CHECK_TYPEDEF_STATEMENT, OtherMsg = "The #typedef name [%s] does not follow the rules" % (Name), BelongsToTable = FileTable, BelongsToItem = Record[0]) + + # Check whether the #ifndef at the start of an include file uses both prefix and postfix underscore characters, '_'. + def NamingConventionCheckIfndefStatement(self, FileTable): + if EccGlobalData.gConfig.NamingConventionCheckTypedefStatement == '1' or EccGlobalData.gConfig.NamingConventionCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1': + EdkLogger.quiet("Checking naming covention of #ifndef statement ...") + + SqlCommand = """select ID, Value from %s where Model = %s""" %(FileTable, MODEL_IDENTIFIER_MACRO_IFNDEF) + RecordSet = EccGlobalData.gDb.TblFile.Exec(SqlCommand) + for Record in RecordSet: + Name = Record[1].replace('#ifndef', '').strip() + if Name[0] != '_' or Name[-1] != '_': + if not EccGlobalData.gException.IsException(ERROR_NAMING_CONVENTION_CHECK_IFNDEF_STATEMENT, Name): + EccGlobalData.gDb.TblReport.Insert(ERROR_NAMING_CONVENTION_CHECK_IFNDEF_STATEMENT, OtherMsg = "The #ifndef name [%s] does not follow the rules" % (Name), BelongsToTable = FileTable, BelongsToItem = Record[0]) + + # Rule for path name, variable name and function name + # 1. First character should be upper case + # 2. Existing lower case in a word + # 3. No space existence + # Check whether the path name followed the rule + def NamingConventionCheckPathName(self): + if EccGlobalData.gConfig.NamingConventionCheckPathName == '1' or EccGlobalData.gConfig.NamingConventionCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1': + EdkLogger.quiet("Checking naming covention of file path name ...") + Pattern = re.compile(r'^[A-Z]+\S*[a-z]\S*$') + SqlCommand = """select ID, Name from File""" + RecordSet = EccGlobalData.gDb.TblFile.Exec(SqlCommand) + for Record in RecordSet: + if not Pattern.match(Record[1]): + if not EccGlobalData.gException.IsException(ERROR_NAMING_CONVENTION_CHECK_PATH_NAME, Record[1]): + EccGlobalData.gDb.TblReport.Insert(ERROR_NAMING_CONVENTION_CHECK_PATH_NAME, OtherMsg = "The file path [%s] does not follow the rules" % (Record[1]), BelongsToTable = 'File', BelongsToItem = Record[0]) + + # Rule for path name, variable name and function name + # 1. First character should be upper case + # 2. Existing lower case in a word + # 3. No space existence + # 4. Global variable name must start with a 'g' + # Check whether the variable name followed the rule + def NamingConventionCheckVariableName(self, FileTable): + if EccGlobalData.gConfig.NamingConventionCheckVariableName == '1' or EccGlobalData.gConfig.NamingConventionCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1': + EdkLogger.quiet("Checking naming covention of variable name ...") + Pattern = re.compile(r'^[A-Zgm]+\S*[a-z]\S*$') + + SqlCommand = """select ID, Name from %s where Model = %s""" %(FileTable, MODEL_IDENTIFIER_VARIABLE) + RecordSet = EccGlobalData.gDb.TblFile.Exec(SqlCommand) + for Record in RecordSet: + if not Pattern.match(Record[1]): + if not EccGlobalData.gException.IsException(ERROR_NAMING_CONVENTION_CHECK_VARIABLE_NAME, Record[1]): + EccGlobalData.gDb.TblReport.Insert(ERROR_NAMING_CONVENTION_CHECK_VARIABLE_NAME, OtherMsg = "The variable name [%s] does not follow the rules" % (Record[1]), BelongsToTable = FileTable, BelongsToItem = Record[0]) + + # Rule for path name, variable name and function name + # 1. First character should be upper case + # 2. Existing lower case in a word + # 3. No space existence + # Check whether the function name followed the rule + def NamingConventionCheckFunctionName(self): + if EccGlobalData.gConfig.NamingConventionCheckFunctionName == '1' or EccGlobalData.gConfig.NamingConventionCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1': + EdkLogger.quiet("Checking naming covention of function name ...") + Pattern = re.compile(r'^[A-Z]+\S*[a-z]\S*$') + SqlCommand = """select ID, Name from Function""" + RecordSet = EccGlobalData.gDb.TblFile.Exec(SqlCommand) + for Record in RecordSet: + if not Pattern.match(Record[1]): + if not EccGlobalData.gException.IsException(ERROR_NAMING_CONVENTION_CHECK_FUNCTION_NAME, Record[1]): + EccGlobalData.gDb.TblReport.Insert(ERROR_NAMING_CONVENTION_CHECK_FUNCTION_NAME, OtherMsg = "The function name [%s] does not follow the rules" % (Record[1]), BelongsToTable = 'Function', BelongsToItem = Record[0]) + + # Check whether NO use short variable name with single character + def NamingConventionCheckSingleCharacterVariable(self, FileTable): + if EccGlobalData.gConfig.NamingConventionCheckSingleCharacterVariable == '1' or EccGlobalData.gConfig.NamingConventionCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1': + EdkLogger.quiet("Checking naming covention of single character variable name ...") + + SqlCommand = """select ID, Name from %s where Model = %s""" %(FileTable, MODEL_IDENTIFIER_VARIABLE) + RecordSet = EccGlobalData.gDb.TblFile.Exec(SqlCommand) + for Record in RecordSet: + Variable = Record[1].replace('*', '') + if len(Variable) == 1: + if not EccGlobalData.gException.IsException(ERROR_NAMING_CONVENTION_CHECK_SINGLE_CHARACTER_VARIABLE, Record[1]): + EccGlobalData.gDb.TblReport.Insert(ERROR_NAMING_CONVENTION_CHECK_SINGLE_CHARACTER_VARIABLE, OtherMsg = "The variable name [%s] does not follow the rules" % (Record[1]), BelongsToTable = FileTable, BelongsToItem = Record[0]) + +## +# +# This acts like the main() function for the script, unless it is 'import'ed into another +# script. +# +if __name__ == '__main__': + Check = Check() + Check.Check() diff --git a/BaseTools/Source/Python/Ecc/CodeFragment.py b/BaseTools/Source/Python/Ecc/CodeFragment.py new file mode 100644 index 0000000000..1c5c5e4df2 --- /dev/null +++ b/BaseTools/Source/Python/Ecc/CodeFragment.py @@ -0,0 +1,165 @@ +## @file +# fragments of source file +# +# Copyright (c) 2007, 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. +# + + +## The description of comment contents and start & end position +# +# +class Comment : + ## The constructor + # + # @param self The object pointer + # @param Str The message to record + # @param Begin The start position tuple. + # @param End The end position tuple. + # @param CommentType The type of comment (T_COMMENT_TWO_SLASH or T_COMMENT_SLASH_STAR). + # + def __init__(self, Str, Begin, End, CommentType): + self.Content = Str + self.StartPos = Begin + self.EndPos = End + self.Type = CommentType + +## The description of preprocess directives and start & end position +# +# +class PP_Directive : + ## The constructor + # + # @param self The object pointer + # @param Str The message to record + # @param Begin The start position tuple. + # @param End The end position tuple. + # + def __init__(self, Str, Begin, End): + self.Content = Str + self.StartPos = Begin + self.EndPos = End + +## The description of predicate expression and start & end position +# +# +class PredicateExpression : + ## The constructor + # + # @param self The object pointer + # @param Str The message to record + # @param Begin The start position tuple. + # @param End The end position tuple. + # + def __init__(self, Str, Begin, End): + self.Content = Str + self.StartPos = Begin + self.EndPos = End + +## The description of function definition and start & end position +# +# +class FunctionDefinition : + ## The constructor + # + # @param self The object pointer + # @param Str The message to record + # @param Begin The start position tuple. + # @param End The end position tuple. + # @param LBPos The left brace position tuple. + # + def __init__(self, ModifierStr, DeclStr, Begin, End, LBPos, NamePos): + self.Modifier = ModifierStr + self.Declarator = DeclStr + self.StartPos = Begin + self.EndPos = End + self.LeftBracePos = LBPos + self.NamePos = NamePos + +## The description of variable declaration and start & end position +# +# +class VariableDeclaration : + ## The constructor + # + # @param self The object pointer + # @param Str The message to record + # @param Begin The start position tuple. + # @param NamePos The name position tuple. + # + def __init__(self, ModifierStr, DeclStr, Begin, NamePos): + self.Modifier = ModifierStr + self.Declarator = DeclStr + self.StartPos = Begin + self.NameStartPos = NamePos + +## The description of enum definition and start & end position +# +# +class EnumerationDefinition : + ## The constructor + # + # @param self The object pointer + # @param Str The message to record + # @param Begin The start position tuple. + # @param End The end position tuple. + # + def __init__(self, Str, Begin, End): + self.Content = Str + self.StartPos = Begin + self.EndPos = End + +## The description of struct/union definition and start & end position +# +# +class StructUnionDefinition : + ## The constructor + # + # @param self The object pointer + # @param Str The message to record + # @param Begin The start position tuple. + # @param End The end position tuple. + # + def __init__(self, Str, Begin, End): + self.Content = Str + self.StartPos = Begin + self.EndPos = End + +## The description of 'Typedef' definition and start & end position +# +# +class TypedefDefinition : + ## The constructor + # + # @param self The object pointer + # @param Str The message to record + # @param Begin The start position tuple. + # @param End The end position tuple. + # + def __init__(self, FromStr, ToStr, Begin, End): + self.FromType = FromStr + self.ToType = ToStr + self.StartPos = Begin + self.EndPos = End + +class FunctionCalling: + ## The constructor + # + # @param self The object pointer + # @param Str The message to record + # @param Begin The start position tuple. + # @param End The end position tuple. + # + def __init__(self, Name, Param, Begin, End): + self.FuncName = Name + self.ParamList = Param + self.StartPos = Begin + self.EndPos = End + \ No newline at end of file diff --git a/BaseTools/Source/Python/Ecc/CodeFragmentCollector.py b/BaseTools/Source/Python/Ecc/CodeFragmentCollector.py new file mode 100644 index 0000000000..d95faeef6a --- /dev/null +++ b/BaseTools/Source/Python/Ecc/CodeFragmentCollector.py @@ -0,0 +1,624 @@ +## @file +# preprocess source file +# +# Copyright (c) 2007, 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. +# + +## +# Import Modules +# + +import re +import os +import sys + +import antlr3 +from CLexer import CLexer +from CParser import CParser + +import FileProfile +from CodeFragment import Comment +from CodeFragment import PP_Directive +from ParserWarning import Warning + + +##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_SINGLE_QUOTE '\'' +##define T_CHAR_STAR '*' +##define T_CHAR_HASH '#' + +(T_CHAR_SPACE, T_CHAR_NULL, T_CHAR_CR, T_CHAR_TAB, T_CHAR_LF, T_CHAR_SLASH, \ +T_CHAR_BACKSLASH, T_CHAR_DOUBLE_QUOTE, T_CHAR_SINGLE_QUOTE, T_CHAR_STAR, T_CHAR_HASH) = \ +(' ', '\0', '\r', '\t', '\n', '/', '\\', '\"', '\'', '*', '#') + +SEPERATOR_TUPLE = ('=', '|', ',', '{', '}') + +(T_COMMENT_TWO_SLASH, T_COMMENT_SLASH_STAR) = (0, 1) + +(T_PP_INCLUDE, T_PP_DEFINE, T_PP_OTHERS) = (0, 1, 2) + +## The collector for source code fragments. +# +# PreprocessFile method should be called prior to ParseFile +# +# GetNext*** procedures mean these procedures will get next token first, then make judgement. +# Get*** procedures mean these procedures will make judgement on current token only. +# +class CodeFragmentCollector: + ## The constructor + # + # @param self The object pointer + # @param FileName The file that to be parsed + # + def __init__(self, FileName): + self.Profile = FileProfile.FileProfile(FileName) + self.Profile.FileLinesList.append(T_CHAR_LF) + self.FileName = FileName + self.CurrentLineNumber = 1 + self.CurrentOffsetWithinLine = 0 + + self.__Token = "" + self.__SkippedChars = "" + + ## __IsWhiteSpace() method + # + # Whether char at current FileBufferPos is whitespace + # + # @param self The object pointer + # @param Char The char to test + # @retval True The char is a kind of white space + # @retval False The char is NOT a kind of white space + # + def __IsWhiteSpace(self, Char): + if Char in (T_CHAR_NULL, T_CHAR_CR, T_CHAR_SPACE, T_CHAR_TAB, T_CHAR_LF): + return True + else: + return False + + ## __SkipWhiteSpace() method + # + # Skip white spaces from current char, return number of chars skipped + # + # @param self The object pointer + # @retval Count The number of chars skipped + # + def __SkipWhiteSpace(self): + Count = 0 + while not self.__EndOfFile(): + Count += 1 + if self.__CurrentChar() in (T_CHAR_NULL, T_CHAR_CR, T_CHAR_LF, T_CHAR_SPACE, T_CHAR_TAB): + self.__SkippedChars += str(self.__CurrentChar()) + self.__GetOneChar() + + else: + Count = Count - 1 + return Count + + ## __EndOfFile() method + # + # Judge current buffer pos is at file end + # + # @param self The object pointer + # @retval True Current File buffer position is at file end + # @retval False Current File buffer position is NOT at file end + # + def __EndOfFile(self): + NumberOfLines = len(self.Profile.FileLinesList) + SizeOfLastLine = NumberOfLines + if NumberOfLines > 0: + SizeOfLastLine = len(self.Profile.FileLinesList[-1]) + + if self.CurrentLineNumber == NumberOfLines and self.CurrentOffsetWithinLine >= SizeOfLastLine - 1: + return True + elif self.CurrentLineNumber > NumberOfLines: + return True + else: + return False + + ## __EndOfLine() method + # + # Judge current buffer pos is at line end + # + # @param self The object pointer + # @retval True Current File buffer position is at line end + # @retval False Current File buffer position is NOT at line end + # + def __EndOfLine(self): + SizeOfCurrentLine = len(self.Profile.FileLinesList[self.CurrentLineNumber - 1]) + if self.CurrentOffsetWithinLine >= SizeOfCurrentLine - 1: + return True + else: + return False + + ## Rewind() method + # + # Reset file data buffer to the initial state + # + # @param self The object pointer + # + def Rewind(self): + self.CurrentLineNumber = 1 + self.CurrentOffsetWithinLine = 0 + + ## __UndoOneChar() method + # + # Go back one char in the file buffer + # + # @param self The object pointer + # @retval True Successfully go back one char + # @retval False Not able to go back one char as file beginning reached + # + def __UndoOneChar(self): + + if self.CurrentLineNumber == 1 and self.CurrentOffsetWithinLine == 0: + return False + elif self.CurrentOffsetWithinLine == 0: + self.CurrentLineNumber -= 1 + self.CurrentOffsetWithinLine = len(self.__CurrentLine()) - 1 + else: + self.CurrentOffsetWithinLine -= 1 + return True + + ## __GetOneChar() method + # + # Move forward one char in the file buffer + # + # @param self The object pointer + # + def __GetOneChar(self): + if self.CurrentOffsetWithinLine == len(self.Profile.FileLinesList[self.CurrentLineNumber - 1]) - 1: + self.CurrentLineNumber += 1 + self.CurrentOffsetWithinLine = 0 + else: + self.CurrentOffsetWithinLine += 1 + + ## __CurrentChar() method + # + # Get the char pointed to by the file buffer pointer + # + # @param self The object pointer + # @retval Char Current char + # + def __CurrentChar(self): + CurrentChar = self.Profile.FileLinesList[self.CurrentLineNumber - 1][self.CurrentOffsetWithinLine] +# if CurrentChar > 255: +# raise Warning("Non-Ascii char found At Line %d, offset %d" % (self.CurrentLineNumber, self.CurrentOffsetWithinLine), self.FileName, self.CurrentLineNumber) + return CurrentChar + + ## __NextChar() method + # + # Get the one char pass the char pointed to by the file buffer pointer + # + # @param self The object pointer + # @retval Char Next char + # + def __NextChar(self): + if self.CurrentOffsetWithinLine == len(self.Profile.FileLinesList[self.CurrentLineNumber - 1]) - 1: + return self.Profile.FileLinesList[self.CurrentLineNumber][0] + else: + return self.Profile.FileLinesList[self.CurrentLineNumber - 1][self.CurrentOffsetWithinLine + 1] + + ## __SetCurrentCharValue() method + # + # Modify the value of current char + # + # @param self The object pointer + # @param Value The new value of current char + # + def __SetCurrentCharValue(self, Value): + self.Profile.FileLinesList[self.CurrentLineNumber - 1][self.CurrentOffsetWithinLine] = Value + + ## __SetCharValue() method + # + # Modify the value of current char + # + # @param self The object pointer + # @param Value The new value of current char + # + def __SetCharValue(self, Line, Offset, Value): + self.Profile.FileLinesList[Line - 1][Offset] = Value + + ## __CurrentLine() method + # + # Get the list that contains current line contents + # + # @param self The object pointer + # @retval List current line contents + # + def __CurrentLine(self): + return self.Profile.FileLinesList[self.CurrentLineNumber - 1] + + ## __InsertComma() method + # + # Insert ',' to replace PP + # + # @param self The object pointer + # @retval List current line contents + # + def __InsertComma(self, Line): + + + if self.Profile.FileLinesList[Line - 1][0] != T_CHAR_HASH: + BeforeHashPart = str(self.Profile.FileLinesList[Line - 1]).split(T_CHAR_HASH)[0] + if BeforeHashPart.rstrip().endswith(T_CHAR_COMMA) or BeforeHashPart.rstrip().endswith(';'): + return + + if Line - 2 >= 0 and str(self.Profile.FileLinesList[Line - 2]).rstrip().endswith(','): + return + + if Line - 2 >= 0 and str(self.Profile.FileLinesList[Line - 2]).rstrip().endswith(';'): + return + + if str(self.Profile.FileLinesList[Line]).lstrip().startswith(',') or str(self.Profile.FileLinesList[Line]).lstrip().startswith(';'): + return + + self.Profile.FileLinesList[Line - 1].insert(self.CurrentOffsetWithinLine, ',') + + ## PreprocessFile() method + # + # Preprocess file contents, replace comments with spaces. + # In the end, rewind the file buffer pointer to the beginning + # BUGBUG: No !include statement processing contained in this procedure + # !include statement should be expanded at the same FileLinesList[CurrentLineNumber - 1] + # + # @param self The object pointer + # + def PreprocessFile(self): + + self.Rewind() + InComment = False + DoubleSlashComment = False + HashComment = False + PPExtend = False + CommentObj = None + PPDirectiveObj = None + # HashComment in quoted string " " is ignored. + InString = False + InCharLiteral = False + + self.Profile.FileLinesList = [list(s) for s in self.Profile.FileLinesListFromFile] + while not self.__EndOfFile(): + + if not InComment and self.__CurrentChar() == T_CHAR_DOUBLE_QUOTE: + InString = not InString + + if not InComment and self.__CurrentChar() == T_CHAR_SINGLE_QUOTE: + InCharLiteral = not InCharLiteral + # meet new line, then no longer in a comment for // and '#' + if self.__CurrentChar() == T_CHAR_LF: + if HashComment and PPDirectiveObj != None: + if PPDirectiveObj.Content.rstrip(T_CHAR_CR).endswith(T_CHAR_BACKSLASH): + PPDirectiveObj.Content += T_CHAR_LF + PPExtend = True + else: + PPExtend = False + + EndLinePos = (self.CurrentLineNumber, self.CurrentOffsetWithinLine) + + if InComment and DoubleSlashComment: + InComment = False + DoubleSlashComment = False + CommentObj.Content += T_CHAR_LF + CommentObj.EndPos = EndLinePos + FileProfile.CommentList.append(CommentObj) + CommentObj = None + if InComment and HashComment and not PPExtend: + InComment = False + HashComment = False + PPDirectiveObj.Content += T_CHAR_LF + PPDirectiveObj.EndPos = EndLinePos + FileProfile.PPDirectiveList.append(PPDirectiveObj) + PPDirectiveObj = None + + if InString or InCharLiteral: + CurrentLine = "".join(self.__CurrentLine()) + if CurrentLine.rstrip(T_CHAR_LF).rstrip(T_CHAR_CR).endswith(T_CHAR_BACKSLASH): + SlashIndex = CurrentLine.rindex(T_CHAR_BACKSLASH) + self.__SetCharValue(self.CurrentLineNumber, SlashIndex, T_CHAR_SPACE) + + if InComment and not DoubleSlashComment and not HashComment: + CommentObj.Content += T_CHAR_LF + self.CurrentLineNumber += 1 + self.CurrentOffsetWithinLine = 0 + # check for */ comment end + elif InComment and not DoubleSlashComment and not HashComment and self.__CurrentChar() == T_CHAR_STAR and self.__NextChar() == T_CHAR_SLASH: + CommentObj.Content += self.__CurrentChar() +# self.__SetCurrentCharValue(T_CHAR_SPACE) + self.__GetOneChar() + CommentObj.Content += self.__CurrentChar() +# self.__SetCurrentCharValue(T_CHAR_SPACE) + CommentObj.EndPos = (self.CurrentLineNumber, self.CurrentOffsetWithinLine) + FileProfile.CommentList.append(CommentObj) + CommentObj = None + self.__GetOneChar() + InComment = False + # set comments to spaces + elif InComment: + if HashComment: + # // follows hash PP directive + if self.__CurrentChar() == T_CHAR_SLASH and self.__NextChar() == T_CHAR_SLASH: + InComment = False + HashComment = False + PPDirectiveObj.EndPos = (self.CurrentLineNumber, self.CurrentOffsetWithinLine - 1) + FileProfile.PPDirectiveList.append(PPDirectiveObj) + PPDirectiveObj = None + continue + else: + PPDirectiveObj.Content += self.__CurrentChar() + if PPExtend: + self.__SetCurrentCharValue(T_CHAR_SPACE) + else: + CommentObj.Content += self.__CurrentChar() +# self.__SetCurrentCharValue(T_CHAR_SPACE) + self.__GetOneChar() + # check for // comment + elif self.__CurrentChar() == T_CHAR_SLASH and self.__NextChar() == T_CHAR_SLASH: + InComment = True + DoubleSlashComment = True + CommentObj = Comment('', (self.CurrentLineNumber, self.CurrentOffsetWithinLine), None, T_COMMENT_TWO_SLASH) + # check for '#' comment + elif self.__CurrentChar() == T_CHAR_HASH and not InString and not InCharLiteral: + InComment = True + HashComment = True + PPDirectiveObj = PP_Directive('', (self.CurrentLineNumber, self.CurrentOffsetWithinLine), None) + # check for /* comment start + elif self.__CurrentChar() == T_CHAR_SLASH and self.__NextChar() == T_CHAR_STAR: + CommentObj = Comment('', (self.CurrentLineNumber, self.CurrentOffsetWithinLine), None, T_COMMENT_SLASH_STAR) + CommentObj.Content += self.__CurrentChar() +# self.__SetCurrentCharValue( T_CHAR_SPACE) + self.__GetOneChar() + CommentObj.Content += self.__CurrentChar() +# self.__SetCurrentCharValue( T_CHAR_SPACE) + self.__GetOneChar() + InComment = True + else: + self.__GetOneChar() + + EndLinePos = (self.CurrentLineNumber, self.CurrentOffsetWithinLine) + + if InComment and DoubleSlashComment: + CommentObj.EndPos = EndLinePos + FileProfile.CommentList.append(CommentObj) + if InComment and HashComment and not PPExtend: + PPDirectiveObj.EndPos = EndLinePos + FileProfile.PPDirectiveList.append(PPDirectiveObj) + + self.Rewind() + + def PreprocessFileWithClear(self): + + self.Rewind() + InComment = False + DoubleSlashComment = False + HashComment = False + PPExtend = False + CommentObj = None + PPDirectiveObj = None + # HashComment in quoted string " " is ignored. + InString = False + InCharLiteral = False + + self.Profile.FileLinesList = [list(s) for s in self.Profile.FileLinesListFromFile] + while not self.__EndOfFile(): + + if not InComment and self.__CurrentChar() == T_CHAR_DOUBLE_QUOTE: + InString = not InString + + if not InComment and self.__CurrentChar() == T_CHAR_SINGLE_QUOTE: + InCharLiteral = not InCharLiteral + # meet new line, then no longer in a comment for // and '#' + if self.__CurrentChar() == T_CHAR_LF: + if HashComment and PPDirectiveObj != None: + if PPDirectiveObj.Content.rstrip(T_CHAR_CR).endswith(T_CHAR_BACKSLASH): + PPDirectiveObj.Content += T_CHAR_LF + PPExtend = True + else: + PPExtend = False + + EndLinePos = (self.CurrentLineNumber, self.CurrentOffsetWithinLine) + + if InComment and DoubleSlashComment: + InComment = False + DoubleSlashComment = False + CommentObj.Content += T_CHAR_LF + CommentObj.EndPos = EndLinePos + FileProfile.CommentList.append(CommentObj) + CommentObj = None + if InComment and HashComment and not PPExtend: + InComment = False + HashComment = False + PPDirectiveObj.Content += T_CHAR_LF + PPDirectiveObj.EndPos = EndLinePos + FileProfile.PPDirectiveList.append(PPDirectiveObj) + PPDirectiveObj = None + + if InString or InCharLiteral: + CurrentLine = "".join(self.__CurrentLine()) + if CurrentLine.rstrip(T_CHAR_LF).rstrip(T_CHAR_CR).endswith(T_CHAR_BACKSLASH): + SlashIndex = CurrentLine.rindex(T_CHAR_BACKSLASH) + self.__SetCharValue(self.CurrentLineNumber, SlashIndex, T_CHAR_SPACE) + + if InComment and not DoubleSlashComment and not HashComment: + CommentObj.Content += T_CHAR_LF + self.CurrentLineNumber += 1 + self.CurrentOffsetWithinLine = 0 + # check for */ comment end + elif InComment and not DoubleSlashComment and not HashComment and self.__CurrentChar() == T_CHAR_STAR and self.__NextChar() == T_CHAR_SLASH: + CommentObj.Content += self.__CurrentChar() + self.__SetCurrentCharValue(T_CHAR_SPACE) + self.__GetOneChar() + CommentObj.Content += self.__CurrentChar() + self.__SetCurrentCharValue(T_CHAR_SPACE) + CommentObj.EndPos = (self.CurrentLineNumber, self.CurrentOffsetWithinLine) + FileProfile.CommentList.append(CommentObj) + CommentObj = None + self.__GetOneChar() + InComment = False + # set comments to spaces + elif InComment: + if HashComment: + # // follows hash PP directive + if self.__CurrentChar() == T_CHAR_SLASH and self.__NextChar() == T_CHAR_SLASH: + InComment = False + HashComment = False + PPDirectiveObj.EndPos = (self.CurrentLineNumber, self.CurrentOffsetWithinLine - 1) + FileProfile.PPDirectiveList.append(PPDirectiveObj) + PPDirectiveObj = None + continue + else: + PPDirectiveObj.Content += self.__CurrentChar() +# if PPExtend: +# self.__SetCurrentCharValue(T_CHAR_SPACE) + else: + CommentObj.Content += self.__CurrentChar() + self.__SetCurrentCharValue(T_CHAR_SPACE) + self.__GetOneChar() + # check for // comment + elif self.__CurrentChar() == T_CHAR_SLASH and self.__NextChar() == T_CHAR_SLASH: + InComment = True + DoubleSlashComment = True + CommentObj = Comment('', (self.CurrentLineNumber, self.CurrentOffsetWithinLine), None, T_COMMENT_TWO_SLASH) + # check for '#' comment + elif self.__CurrentChar() == T_CHAR_HASH and not InString and not InCharLiteral: + InComment = True + HashComment = True + PPDirectiveObj = PP_Directive('', (self.CurrentLineNumber, self.CurrentOffsetWithinLine), None) + # check for /* comment start + elif self.__CurrentChar() == T_CHAR_SLASH and self.__NextChar() == T_CHAR_STAR: + CommentObj = Comment('', (self.CurrentLineNumber, self.CurrentOffsetWithinLine), None, T_COMMENT_SLASH_STAR) + CommentObj.Content += self.__CurrentChar() + self.__SetCurrentCharValue( T_CHAR_SPACE) + self.__GetOneChar() + CommentObj.Content += self.__CurrentChar() + self.__SetCurrentCharValue( T_CHAR_SPACE) + self.__GetOneChar() + InComment = True + else: + self.__GetOneChar() + + EndLinePos = (self.CurrentLineNumber, self.CurrentOffsetWithinLine) + + if InComment and DoubleSlashComment: + CommentObj.EndPos = EndLinePos + FileProfile.CommentList.append(CommentObj) + if InComment and HashComment and not PPExtend: + PPDirectiveObj.EndPos = EndLinePos + FileProfile.PPDirectiveList.append(PPDirectiveObj) + self.Rewind() + + ## ParseFile() method + # + # Parse the file profile buffer to extract fd, fv ... information + # Exception will be raised if syntax error found + # + # @param self The object pointer + # + def ParseFile(self): + self.PreprocessFile() + # restore from ListOfList to ListOfString + self.Profile.FileLinesList = ["".join(list) for list in self.Profile.FileLinesList] + FileStringContents = '' + for fileLine in self.Profile.FileLinesList: + FileStringContents += fileLine + cStream = antlr3.StringStream(FileStringContents) + lexer = CLexer(cStream) + tStream = antlr3.CommonTokenStream(lexer) + parser = CParser(tStream) + parser.translation_unit() + + def ParseFileWithClearedPPDirective(self): + self.PreprocessFileWithClear() + # restore from ListOfList to ListOfString + self.Profile.FileLinesList = ["".join(list) for list in self.Profile.FileLinesList] + FileStringContents = '' + for fileLine in self.Profile.FileLinesList: + FileStringContents += fileLine + cStream = antlr3.StringStream(FileStringContents) + lexer = CLexer(cStream) + tStream = antlr3.CommonTokenStream(lexer) + parser = CParser(tStream) + parser.translation_unit() + + def CleanFileProfileBuffer(self): + FileProfile.CommentList = [] + FileProfile.PPDirectiveList = [] + FileProfile.PredicateExpressionList = [] + FileProfile.FunctionDefinitionList = [] + FileProfile.VariableDeclarationList = [] + FileProfile.EnumerationDefinitionList = [] + FileProfile.StructUnionDefinitionList = [] + FileProfile.TypedefDefinitionList = [] + FileProfile.FunctionCallingList = [] + + def PrintFragments(self): + + print '################# ' + self.FileName + '#####################' + + print '/****************************************/' + print '/*************** COMMENTS ***************/' + print '/****************************************/' + for comment in FileProfile.CommentList: + print str(comment.StartPos) + comment.Content + + print '/****************************************/' + print '/********* PREPROCESS DIRECTIVES ********/' + print '/****************************************/' + for pp in FileProfile.PPDirectiveList: + print str(pp.StartPos) + pp.Content + + print '/****************************************/' + print '/********* VARIABLE DECLARATIONS ********/' + print '/****************************************/' + for var in FileProfile.VariableDeclarationList: + print str(var.StartPos) + var.Modifier + ' '+ var.Declarator + + print '/****************************************/' + print '/********* FUNCTION DEFINITIONS *********/' + print '/****************************************/' + for func in FileProfile.FunctionDefinitionList: + print str(func.StartPos) + func.Modifier + ' '+ func.Declarator + ' ' + str(func.NamePos) + + print '/****************************************/' + print '/************ ENUMERATIONS **************/' + print '/****************************************/' + for enum in FileProfile.EnumerationDefinitionList: + print str(enum.StartPos) + enum.Content + + print '/****************************************/' + print '/*********** STRUCTS/UNIONS *************/' + print '/****************************************/' + for su in FileProfile.StructUnionDefinitionList: + print str(su.StartPos) + su.Content + + print '/****************************************/' + print '/********* PREDICATE EXPRESSIONS ********/' + print '/****************************************/' + for predexp in FileProfile.PredicateExpressionList: + print str(predexp.StartPos) + predexp.Content + + print '/****************************************/' + print '/************** TYPEDEFS ****************/' + print '/****************************************/' + for typedef in FileProfile.TypedefDefinitionList: + print str(typedef.StartPos) + typedef.ToType + +if __name__ == "__main__": + + collector = CodeFragmentCollector(sys.argv[1]) + collector.PreprocessFile() + print "For Test." diff --git a/BaseTools/Source/Python/Ecc/Configuration.py b/BaseTools/Source/Python/Ecc/Configuration.py new file mode 100644 index 0000000000..bd9313cef4 --- /dev/null +++ b/BaseTools/Source/Python/Ecc/Configuration.py @@ -0,0 +1,264 @@ +## @file +# This file is used to define class Configuration +# +# Copyright (c) 2008, 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. +# + +## +# Import Modules +# +import os +import Common.EdkLogger as EdkLogger +from Common.DataType import * +from Common.String import * + +## Configuration +# +# This class is used to define all items in configuration file +# +# @param Filename: The name of configuration file, the default is config.ini +# +class Configuration(object): + def __init__(self, Filename): + self.Filename = Filename + + self.Version = 0.1 + + ## Identify to if check all items + # 1 - Check all items and ignore all other detailed items + # 0 - Not check all items, the tool will go through all other detailed items to decide to check or not + # + self.CheckAll = 0 + + ## Identify to if automatically correct mistakes + # 1 - Automatically correct + # 0 - Not automatically correct + # Only the following check points can be automatically corrected, others not listed below are not supported even it is 1 + # + # GeneralCheckTab + # GeneralCheckIndentation + # GeneralCheckLine + # GeneralCheckCarriageReturn + # SpaceCheckAll + # + self.AutoCorrect = 0 + + # List customized Modifer here, split with ',' + # Defaultly use the definition in class DataType + self.ModifierList = MODIFIER_LIST + + ## General Checking + self.GeneralCheckAll = 0 + + # Check whether NO Tab is used, replaced with spaces + self.GeneralCheckNoTab = 1 + # The width of Tab + self.GeneralCheckTabWidth = 2 + # Check whether the indentation is followed coding style + self.GeneralCheckIndentation = 1 + # The width of indentation + self.GeneralCheckIndentationWidth = 2 + # Check whether no line is exceeding defined widty + self.GeneralCheckLine = 1 + # The width of a line + self.GeneralCheckLineWidth = 120 + # Check whether no use of _asm in the source file + self.GeneralCheckNo_Asm = 1 + # Check whether no use of "#progma" in source file except "#pragma pack(#)". + self.GeneralCheckNoProgma = 1 + # Check whether there is a carriage return at the end of the file + self.GeneralCheckCarriageReturn = 1 + # Check whether the file exists + self.GeneralCheckFileExistence = 1 + + ## Space Checking + self.SpaceCheckAll = 1 + + ## Predicate Expression Checking + self.PredicateExpressionCheckAll = 0 + + # Check whether Boolean values, variable type BOOLEAN not use explicit comparisons to TRUE or FALSE + self.PredicateExpressionCheckBooleanValue = 1 + # Check whether Non-Boolean comparisons use a compare operator (==, !=, >, < >=, <=). + self.PredicateExpressionCheckNonBooleanOperator = 1 + # Check whether a comparison of any pointer to zero must be done via the NULL type + self.PredicateExpressionCheckComparisonNullType = 1 + + ## Headers Checking + self.HeaderCheckAll = 0 + + # Check whether File header exists + self.HeaderCheckFile = 1 + # Check whether Function header exists + self.HeaderCheckFunction = 1 + + ## C Function Layout Checking + self.CFunctionLayoutCheckAll = 0 + + # Check whether return type exists and in the first line + self.CFunctionLayoutCheckReturnType = 1 + # Check whether any optional functional modifiers exist and next to the return type + self.CFunctionLayoutCheckOptionalFunctionalModifier = 1 + # Check whether the next line contains the function name, left justified, followed by the beginning of the parameter list + # Check whether the closing parenthesis is on its own line and also indented two spaces + self.CFunctionLayoutCheckFunctionName = 1 + # Check whether the function prototypes in include files have the same form as function definitions + self.CFunctionLayoutCheckFunctionPrototype = 1 + # Check whether the body of a function is contained by open and close braces that must be in the first column + self.CFunctionLayoutCheckFunctionBody = 1 + # Check whether the data declarations is the first code in a module. + self.CFunctionLayoutCheckDataDeclaration = 1 + # Check whether no initialization of a variable as part of its declaration + self.CFunctionLayoutCheckNoInitOfVariable = 1 + # Check whether no use of STATIC for functions + self.CFunctionLayoutCheckNoStatic = 1 + + ## Include Files Checking + self.IncludeFileCheckAll = 0 + + #Check whether having include files with same name + self.IncludeFileCheckSameName = 1 + # Check whether all include file contents is guarded by a #ifndef statement. + # the #ifndef must be the first line of code following the file header comment + # the #endif must appear on the last line in the file + self.IncludeFileCheckIfndefStatement = 1 + # Check whether include files contain only public or only private data + # Check whether include files NOT contain code or define data variables + self.IncludeFileCheckData = 1 + + ## Declarations and Data Types Checking + self.DeclarationDataTypeCheckAll = 0 + + # Check whether no use of int, unsigned, char, void, static, long in any .c, .h or .asl files. + self.DeclarationDataTypeCheckNoUseCType = 1 + # Check whether the modifiers IN, OUT, OPTIONAL, and UNALIGNED are used only to qualify arguments to a function and should not appear in a data type declaration + self.DeclarationDataTypeCheckInOutModifier = 1 + # Check whether the EFIAPI modifier should be used at the entry of drivers, events, and member functions of protocols + self.DeclarationDataTypeCheckEFIAPIModifier = 1 + # Check whether Enumerated Type has a 'typedef' and the name is capital + self.DeclarationDataTypeCheckEnumeratedType = 1 + # Check whether Structure Type has a 'typedef' and the name is capital + self.DeclarationDataTypeCheckStructureDeclaration = 1 + # Check whether having same Structure + self.DeclarationDataTypeCheckSameStructure = 1 + # Check whether Union Type has a 'typedef' and the name is capital + self.DeclarationDataTypeCheckUnionType = 1 + + ## Naming Conventions Checking + self.NamingConventionCheckAll = 0 + + # Check whether only capital letters are used for #define declarations + self.NamingConventionCheckDefineStatement = 1 + # Check whether only capital letters are used for typedef declarations + self.NamingConventionCheckTypedefStatement = 1 + # Check whether the #ifndef at the start of an include file uses both prefix and postfix underscore characters, '_'. + self.NamingConventionCheckIfndefStatement = 1 + # Rule for path name, variable name and function name + # 1. First character should be upper case + # 2. Existing lower case in a word + # 3. No space existence + # Check whether the path name followed the rule + self.NamingConventionCheckPathName = 1 + # Check whether the variable name followed the rule + self.NamingConventionCheckVariableName = 1 + # Check whether the function name followed the rule + self.NamingConventionCheckFunctionName = 1 + # Check whether NO use short variable name with single character + self.NamingConventionCheckSingleCharacterVariable = 1 + + ## Doxygen Checking + self.DoxygenCheckAll = 0 + + # Check whether the file headers are followed Doxygen special documentation blocks in section 2.3.5 + self.DoxygenCheckFileHeader = 1 + # Check whether the function headers are followed Doxygen special documentation blocks in section 2.3.5 + self.DoxygenCheckFunctionHeader = 1 + # Check whether the first line of text in a comment block is a brief description of the element being documented. + # The brief description must end with a period. + self.DoxygenCheckCommentDescription = 1 + # Check whether comment lines with '///< ... text ...' format, if it is used, it should be after the code section. + self.DoxygenCheckCommentFormat = 1 + # Check whether only Doxygen commands allowed to mark the code are @bug and @todo. + self.DoxygenCheckCommand = 1 + + ## Meta-Data File Processing Checking + self.MetaDataFileCheckAll = 0 + + # Check whether each file defined in meta-data exists + self.MetaDataFileCheckPathName = 1 + # Generate a list for all files defined in meta-data files + self.MetaDataFileCheckGenerateFileList = 1 + # The path of log file + self.MetaDataFileCheckPathOfGenerateFileList = 'File.log' + # Check whether all Library Instances defined for a given module (or dependent library instance) match the module's type. + # Each Library Instance must specify the Supported Module Types in its INF file, + # and any module specifying the library instance must be one of the supported types. + self.MetaDataFileCheckLibraryInstance = 1 + # Check whether a Library Instance has been defined for all dependent library classes + self.MetaDataFileCheckLibraryInstanceDependent = 1 + # Check whether the Library Instances specified by the LibraryClasses sections are listed in order of dependencies + self.MetaDataFileCheckLibraryInstanceOrder = 1 + # Check whether the unnecessary inclusion of library classes in the INF file + self.MetaDataFileCheckLibraryNoUse = 1 + # Check whether an INF file is specified in the FDF file, but not in the DSC file, then the INF file must be for a Binary module only + self.MetaDataFileCheckBinaryInfInFdf = 1 + # Not to report error and warning related OS include file such as "windows.h" and "stdio.h" + # Check whether a PCD is set in a DSC file or the FDF file, but not in both. + self.MetaDataFileCheckPcdDuplicate = 1 + # Check whether PCD settings in the FDF file can only be related to flash. + self.MetaDataFileCheckPcdFlash = 1 + # Check whether PCDs used in INF files but not specified in DSC or FDF files + self.MetaDataFileCheckPcdNoUse = 1 + # Check whether having duplicate guids defined for Guid/Protocol/Ppi + self.MetaDataFileCheckGuidDuplicate = 1 + # Check whether all files under module directory are described in INF files + self.MetaDataFileCheckModuleFileNoUse = 1 + # Check whether the PCD is correctly used in C function via its type + self.MetaDataFileCheckPcdType = 1 + + # + # The check points in this section are reserved + # + # GotoStatementCheckAll = 0 + # + self.SpellingCheckAll = 0 + + # The directory listed here will not be parsed, split with ',' + self.SkipDirList = [] + + self.ParseConfig() + + def ParseConfig(self): + Filepath = os.path.normpath(self.Filename) + if not os.path.isfile(Filepath): + ErrorMsg = "Can't find configuration file '%s'" % Filepath + EdkLogger.error("Ecc", EdkLogger.ECC_ERROR, ErrorMsg, File = Filepath) + + LineNo = 0 + for Line in open(Filepath, 'r'): + LineNo = LineNo + 1 + Line = CleanString(Line) + if Line != '': + List = GetSplitValueList(Line, TAB_EQUAL_SPLIT) + if List[0] not in self.__dict__: + ErrorMsg = "Invalid configuration option '%s' was found" % List[0] + EdkLogger.error("Ecc", EdkLogger.ECC_ERROR, ErrorMsg, File = Filepath, Line = LineNo) + if List[0] == 'ModifierList': + List[1] = GetSplitValueList(List[1], TAB_COMMA_SPLIT) + if List[0] == 'MetaDataFileCheckPathOfGenerateFileList' and List[1] == "": + continue + if List[0] == 'SkipDirList': + List[1] = GetSplitValueList(List[1], TAB_COMMA_SPLIT) + self.__dict__[List[0]] = List[1] + + def ShowMe(self): + print self.Filename + for Key in self.__dict__.keys(): + print Key, '=', self.__dict__[Key] diff --git a/BaseTools/Source/Python/Ecc/Database.py b/BaseTools/Source/Python/Ecc/Database.py new file mode 100644 index 0000000000..c9311f65a5 --- /dev/null +++ b/BaseTools/Source/Python/Ecc/Database.py @@ -0,0 +1,344 @@ +## @file +# This file is used to create a database used by ECC tool +# +# Copyright (c) 2007 ~ 2008, 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. +# + +## +# Import Modules +# +import sqlite3 +import os, time + +import Common.EdkLogger as EdkLogger +import CommonDataClass.DataClass as DataClass + +from Table.TableDataModel import TableDataModel +from Table.TableFile import TableFile +from Table.TableFunction import TableFunction +from Table.TablePcd import TablePcd +from Table.TableIdentifier import TableIdentifier +from Table.TableReport import TableReport +from Table.TableInf import TableInf +from Table.TableDec import TableDec +from Table.TableDsc import TableDsc +from Table.TableFdf import TableFdf + +## +# Static definitions +# +DATABASE_PATH = "Ecc.db" + +## Database +# +# This class defined the ECC databse +# During the phase of initialization, the database will create all tables and +# insert all records of table DataModel +# +# @param object: Inherited from object class +# @param DbPath: A string for the path of the ECC database +# +# @var Conn: Connection of the ECC database +# @var Cur: Cursor of the connection +# @var TblDataModel: Local instance for TableDataModel +# +class Database(object): + def __init__(self, DbPath): + self.DbPath = DbPath + self.Conn = None + self.Cur = None + self.TblDataModel = None + self.TblFile = None + self.TblFunction = None + self.TblIdentifier = None + self.TblPcd = None + self.TblReport = None + self.TblInf = None + self.TblDec = None + self.TblDsc = None + self.TblFdf = None + + ## Initialize ECC database + # + # 1. Delete all old existing tables + # 2. Create new tables + # 3. Initialize table DataModel + # + def InitDatabase(self, NewDatabase = True): + EdkLogger.verbose("\nInitialize ECC database started ...") + # + # Drop all old existing tables + # + if NewDatabase: + if os.path.exists(self.DbPath): + os.remove(self.DbPath) + self.Conn = sqlite3.connect(self.DbPath, isolation_level = 'DEFERRED') + self.Conn.execute("PRAGMA page_size=4096") + self.Conn.execute("PRAGMA synchronous=OFF") + # to avoid non-ascii charater conversion error + self.Conn.text_factory = str + self.Cur = self.Conn.cursor() + + self.TblDataModel = TableDataModel(self.Cur) + self.TblFile = TableFile(self.Cur) + self.TblFunction = TableFunction(self.Cur) + self.TblIdentifier = TableIdentifier(self.Cur) + self.TblPcd = TablePcd(self.Cur) + self.TblReport = TableReport(self.Cur) + self.TblInf = TableInf(self.Cur) + self.TblDec = TableDec(self.Cur) + self.TblDsc = TableDsc(self.Cur) + self.TblFdf = TableFdf(self.Cur) + + # + # Create new tables + # + if NewDatabase: + self.TblDataModel.Create() + self.TblFile.Create() + self.TblFunction.Create() + self.TblPcd.Create() + self.TblReport.Create() + self.TblInf.Create() + self.TblDec.Create() + self.TblDsc.Create() + self.TblFdf.Create() + + # + # Init each table's ID + # + self.TblDataModel.InitID() + self.TblFile.InitID() + self.TblFunction.InitID() + self.TblPcd.InitID() + self.TblReport.InitID() + self.TblInf.InitID() + self.TblDec.InitID() + self.TblDsc.InitID() + self.TblFdf.InitID() + + # + # Initialize table DataModel + # + if NewDatabase: + self.TblDataModel.InitTable() + + EdkLogger.verbose("Initialize ECC database ... DONE!") + + ## Query a table + # + # @param Table: The instance of the table to be queried + # + def QueryTable(self, Table): + Table.Query() + + ## Close entire database + # + # Commit all first + # Close the connection and cursor + # + def Close(self): + # + # Commit to file + # + self.Conn.commit() + + # + # Close connection and cursor + # + self.Cur.close() + self.Conn.close() + + ## Insert one file information + # + # Insert one file's information to the database + # 1. Create a record in TableFile + # 2. Create functions one by one + # 2.1 Create variables of function one by one + # 2.2 Create pcds of function one by one + # 3. Create variables one by one + # 4. Create pcds one by one + # + def InsertOneFile(self, File): + # + # Insert a record for file + # + FileID = self.TblFile.Insert(File.Name, File.ExtName, File.Path, File.FullPath, Model = File.Model, TimeStamp = File.TimeStamp) + IdTable = TableIdentifier(self.Cur) + IdTable.Table = "Identifier%s" % FileID + IdTable.Create() + + # + # Insert function of file + # + for Function in File.FunctionList: + FunctionID = self.TblFunction.Insert(Function.Header, Function.Modifier, Function.Name, Function.ReturnStatement, \ + Function.StartLine, Function.StartColumn, Function.EndLine, Function.EndColumn, \ + Function.BodyStartLine, Function.BodyStartColumn, FileID, \ + Function.FunNameStartLine, Function.FunNameStartColumn) + # + # Insert Identifier of function + # + for Identifier in Function.IdentifierList: + IdentifierID = IdTable.Insert(Identifier.Modifier, Identifier.Type, Identifier.Name, Identifier.Value, Identifier.Model, \ + FileID, FunctionID, Identifier.StartLine, Identifier.StartColumn, Identifier.EndLine, Identifier.EndColumn) + # + # Insert Pcd of function + # + for Pcd in Function.PcdList: + PcdID = self.TblPcd.Insert(Pcd.CName, Pcd.TokenSpaceGuidCName, Pcd.Token, Pcd.DatumType, Pcd.Model, \ + FileID, FunctionID, Pcd.StartLine, Pcd.StartColumn, Pcd.EndLine, Pcd.EndColumn) + # + # Insert Identifier of file + # + for Identifier in File.IdentifierList: + IdentifierID = IdTable.Insert(Identifier.Modifier, Identifier.Type, Identifier.Name, Identifier.Value, Identifier.Model, \ + FileID, -1, Identifier.StartLine, Identifier.StartColumn, Identifier.EndLine, Identifier.EndColumn) + # + # Insert Pcd of file + # + for Pcd in File.PcdList: + PcdID = self.TblPcd.Insert(Pcd.CName, Pcd.TokenSpaceGuidCName, Pcd.Token, Pcd.DatumType, Pcd.Model, \ + FileID, -1, Pcd.StartLine, Pcd.StartColumn, Pcd.EndLine, Pcd.EndColumn) + + EdkLogger.verbose("Insert information from file %s ... DONE!" % File.FullPath) + + ## UpdateIdentifierBelongsToFunction + # + # Update the field "BelongsToFunction" for each Indentifier + # + # + def UpdateIdentifierBelongsToFunction_disabled(self): + EdkLogger.verbose("Update 'BelongsToFunction' for Identifiers started ...") + + SqlCommand = """select ID, BelongsToFile, StartLine, EndLine, Model from Identifier""" + EdkLogger.debug(4, "SqlCommand: %s" %SqlCommand) + self.Cur.execute(SqlCommand) + Records = self.Cur.fetchall() + for Record in Records: + IdentifierID = Record[0] + BelongsToFile = Record[1] + StartLine = Record[2] + EndLine = Record[3] + Model = Record[4] + + # + # Check whether an identifier belongs to a function + # + EdkLogger.debug(4, "For common identifiers ... ") + SqlCommand = """select ID from Function + where StartLine < %s and EndLine > %s + and BelongsToFile = %s""" % (StartLine, EndLine, BelongsToFile) + EdkLogger.debug(4, "SqlCommand: %s" %SqlCommand) + self.Cur.execute(SqlCommand) + IDs = self.Cur.fetchall() + for ID in IDs: + SqlCommand = """Update Identifier set BelongsToFunction = %s where ID = %s""" % (ID[0], IdentifierID) + EdkLogger.debug(4, "SqlCommand: %s" %SqlCommand) + self.Cur.execute(SqlCommand) + + # + # Check whether the identifier is a function header + # + EdkLogger.debug(4, "For function headers ... ") + if Model == DataClass.MODEL_IDENTIFIER_COMMENT: + SqlCommand = """select ID from Function + where StartLine = %s + 1 + and BelongsToFile = %s""" % (EndLine, BelongsToFile) + EdkLogger.debug(4, "SqlCommand: %s" %SqlCommand) + self.Cur.execute(SqlCommand) + IDs = self.Cur.fetchall() + for ID in IDs: + SqlCommand = """Update Identifier set BelongsToFunction = %s, Model = %s where ID = %s""" % (ID[0], DataClass.MODEL_IDENTIFIER_FUNCTION_HEADER, IdentifierID) + EdkLogger.debug(4, "SqlCommand: %s" %SqlCommand) + self.Cur.execute(SqlCommand) + + EdkLogger.verbose("Update 'BelongsToFunction' for Identifiers ... DONE") + + + ## UpdateIdentifierBelongsToFunction + # + # Update the field "BelongsToFunction" for each Indentifier + # + # + def UpdateIdentifierBelongsToFunction(self): + EdkLogger.verbose("Update 'BelongsToFunction' for Identifiers started ...") + + SqlCommand = """select ID, BelongsToFile, StartLine, EndLine from Function""" + Records = self.TblFunction.Exec(SqlCommand) + Data1 = [] + Data2 = [] + for Record in Records: + FunctionID = Record[0] + BelongsToFile = Record[1] + StartLine = Record[2] + EndLine = Record[3] + #Data1.append(("'file%s'" % BelongsToFile, FunctionID, BelongsToFile, StartLine, EndLine)) + #Data2.append(("'file%s'" % BelongsToFile, FunctionID, DataClass.MODEL_IDENTIFIER_FUNCTION_HEADER, BelongsToFile, DataClass.MODEL_IDENTIFIER_COMMENT, StartLine - 1)) + + SqlCommand = """Update Identifier%s set BelongsToFunction = %s where BelongsToFile = %s and StartLine > %s and EndLine < %s""" % \ + (BelongsToFile, FunctionID, BelongsToFile, StartLine, EndLine) + self.TblIdentifier.Exec(SqlCommand) + + SqlCommand = """Update Identifier%s set BelongsToFunction = %s, Model = %s where BelongsToFile = %s and Model = %s and EndLine = %s""" % \ + (BelongsToFile, FunctionID, DataClass.MODEL_IDENTIFIER_FUNCTION_HEADER, BelongsToFile, DataClass.MODEL_IDENTIFIER_COMMENT, StartLine - 1) + self.TblIdentifier.Exec(SqlCommand) +# # +# # Check whether an identifier belongs to a function +# # +# print Data1 +# SqlCommand = """Update ? set BelongsToFunction = ? where BelongsToFile = ? and StartLine > ? and EndLine < ?""" +# print SqlCommand +# EdkLogger.debug(4, "SqlCommand: %s" %SqlCommand) +# self.Cur.executemany(SqlCommand, Data1) +# +# # +# # Check whether the identifier is a function header +# # +# EdkLogger.debug(4, "For function headers ... ") +# SqlCommand = """Update ? set BelongsToFunction = ?, Model = ? where BelongsToFile = ? and Model = ? and EndLine = ?""" +# EdkLogger.debug(4, "SqlCommand: %s" %SqlCommand) +# self.Cur.executemany(SqlCommand, Data2) +# +# EdkLogger.verbose("Update 'BelongsToFunction' for Identifiers ... DONE") + + +## +# +# This acts like the main() function for the script, unless it is 'import'ed into another +# script. +# +if __name__ == '__main__': + EdkLogger.Initialize() + #EdkLogger.SetLevel(EdkLogger.VERBOSE) + EdkLogger.SetLevel(EdkLogger.DEBUG_0) + EdkLogger.verbose("Start at " + time.strftime('%H:%M:%S', time.localtime())) + + Db = Database(DATABASE_PATH) + Db.InitDatabase() + Db.QueryTable(Db.TblDataModel) + + identifier1 = DataClass.IdentifierClass(-1, '', '', "i''1", 'aaa', DataClass.MODEL_IDENTIFIER_COMMENT, 1, -1, 32, 43, 54, 43) + identifier2 = DataClass.IdentifierClass(-1, '', '', 'i1', 'aaa', DataClass.MODEL_IDENTIFIER_COMMENT, 1, -1, 15, 43, 20, 43) + identifier3 = DataClass.IdentifierClass(-1, '', '', 'i1', 'aaa', DataClass.MODEL_IDENTIFIER_COMMENT, 1, -1, 55, 43, 58, 43) + identifier4 = DataClass.IdentifierClass(-1, '', '', "i1'", 'aaa', DataClass.MODEL_IDENTIFIER_COMMENT, 1, -1, 77, 43, 88, 43) + fun1 = DataClass.FunctionClass(-1, '', '', 'fun1', '', 21, 2, 60, 45, 1, 23, 0, [], []) + file = DataClass.FileClass(-1, 'F1', 'c', 'C:\\', 'C:\\F1.exe', DataClass.MODEL_FILE_C, '2007-12-28', [fun1], [identifier1, identifier2, identifier3, identifier4], []) + Db.InsertOneFile(file) + Db.UpdateIdentifierBelongsToFunction() + + Db.QueryTable(Db.TblFile) + Db.QueryTable(Db.TblFunction) + Db.QueryTable(Db.TblPcd) + Db.QueryTable(Db.TblIdentifier) + + Db.Close() + EdkLogger.verbose("End at " + time.strftime('%H:%M:%S', time.localtime())) + diff --git a/BaseTools/Source/Python/Ecc/Ecc.py b/BaseTools/Source/Python/Ecc/Ecc.py new file mode 100644 index 0000000000..4767645d05 --- /dev/null +++ b/BaseTools/Source/Python/Ecc/Ecc.py @@ -0,0 +1,329 @@ +## @file +# This file is used to be the main entrance of ECC tool +# +# Copyright (c) 2009, 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. +# + +## +# Import Modules +# +import os, time, glob, sys +import Common.EdkLogger as EdkLogger +import Database +import EccGlobalData +from MetaDataParser import * +from optparse import OptionParser +from Configuration import Configuration +from Check import Check +from Common.InfClassObject import Inf +from Common.DecClassObject import Dec +from Common.DscClassObject import Dsc +from Common.FdfClassObject import Fdf +from Common.String import NormPath +from Common import BuildToolError +import c +from Exception import * + +## Ecc +# +# This class is used to define Ecc main entrance +# +# @param object: Inherited from object class +# +class Ecc(object): + def __init__(self): + # Version and Copyright + self.VersionNumber = "0.01" + self.Version = "%prog Version " + self.VersionNumber + self.Copyright = "Copyright (c) 2009, Intel Corporation All rights reserved." + + self.InitDefaultConfigIni() + self.OutputFile = 'output.txt' + self.ReportFile = 'Report.csv' + self.ExceptionFile = 'exception.xml' + self.IsInit = True + self.ScanSourceCode = True + self.ScanMetaData = True + + # Parse the options and args + self.ParseOption() + + # Generate checkpoints list + EccGlobalData.gConfig = Configuration(self.ConfigFile) + + # Generate exception list + EccGlobalData.gException = ExceptionCheck(self.ExceptionFile) + + # Init Ecc database + EccGlobalData.gDb = Database.Database(Database.DATABASE_PATH) + EccGlobalData.gDb.InitDatabase(self.IsInit) + + # Build ECC database + self.BuildDatabase() + + # Start to check + self.Check() + + # Show report + self.GenReport() + + # Close Database + EccGlobalData.gDb.Close() + + def InitDefaultConfigIni(self): + paths = map(lambda p: os.path.join(p, 'Ecc', 'config.ini'), sys.path) + paths = (os.path.realpath('config.ini'),) + tuple(paths) + for path in paths: + if os.path.exists(path): + self.ConfigFile = path + return + self.ConfigFile = 'config.ini' + + ## BuildDatabase + # + # Build the database for target + # + def BuildDatabase(self): + # Clean report table + EccGlobalData.gDb.TblReport.Drop() + EccGlobalData.gDb.TblReport.Create() + + # Build database + if self.IsInit: + if self.ScanSourceCode: + EdkLogger.quiet("Building database for source code ...") + c.CollectSourceCodeDataIntoDB(EccGlobalData.gTarget) + if self.ScanMetaData: + EdkLogger.quiet("Building database for source code done!") + self.BuildMetaDataFileDatabase() + + EccGlobalData.gIdentifierTableList = GetTableList((MODEL_FILE_C, MODEL_FILE_H), 'Identifier', EccGlobalData.gDb) + + ## BuildMetaDataFileDatabase + # + # Build the database for meta data files + # + def BuildMetaDataFileDatabase(self): + EdkLogger.quiet("Building database for meta data files ...") + Op = open(EccGlobalData.gConfig.MetaDataFileCheckPathOfGenerateFileList, 'w+') + #SkipDirs = Read from config file + SkipDirs = EccGlobalData.gConfig.SkipDirList + for Root, Dirs, Files in os.walk(EccGlobalData.gTarget): + for Dir in Dirs: + if Dir.upper() in SkipDirs: + Dirs.remove(Dir) + + for Dir in Dirs: + Dirname = os.path.join(Root, Dir) + if os.path.islink(Dirname): + Dirname = os.path.realpath(Dirname) + if os.path.isdir(Dirname): + # symlinks to directories are treated as directories + Dirs.remove(Dir) + Dirs.append(Dirname) + + for File in Files: + if len(File) > 4 and File[-4:].upper() == ".DEC": + Filename = os.path.normpath(os.path.join(Root, File)) + EdkLogger.quiet("Parsing %s" % Filename) + Op.write("%s\r" % Filename) + Dec(Filename, True, True, EccGlobalData.gWorkspace, EccGlobalData.gDb) + continue + if len(File) > 4 and File[-4:].upper() == ".DSC": + Filename = os.path.normpath(os.path.join(Root, File)) + EdkLogger.quiet("Parsing %s" % Filename) + Op.write("%s\r" % Filename) + Dsc(Filename, True, True, EccGlobalData.gWorkspace, EccGlobalData.gDb) + continue + if len(File) > 4 and File[-4:].upper() == ".INF": + Filename = os.path.normpath(os.path.join(Root, File)) + EdkLogger.quiet("Parsing %s" % Filename) + Op.write("%s\r" % Filename) + Inf(Filename, True, True, EccGlobalData.gWorkspace, EccGlobalData.gDb) + continue + if len(File) > 4 and File[-4:].upper() == ".FDF": + Filename = os.path.normpath(os.path.join(Root, File)) + EdkLogger.quiet("Parsing %s" % Filename) + Op.write("%s\r" % Filename) + Fdf(Filename, True, EccGlobalData.gWorkspace, EccGlobalData.gDb) + continue + Op.close() + + # Commit to database + EccGlobalData.gDb.Conn.commit() + + EdkLogger.quiet("Building database for meta data files done!") + + ## + # + # Check each checkpoint + # + def Check(self): + EdkLogger.quiet("Checking ...") + EccCheck = Check() + EccCheck.Check() + EdkLogger.quiet("Checking done!") + + ## + # + # Generate the scan report + # + def GenReport(self): + EdkLogger.quiet("Generating report ...") + EccGlobalData.gDb.TblReport.ToCSV(self.ReportFile) + EdkLogger.quiet("Generating report done!") + + def GetRealPathCase(self, path): + TmpPath = path.rstrip(os.sep) + PathParts = TmpPath.split(os.sep) + if len(PathParts) == 0: + return path + if len(PathParts) == 1: + if PathParts[0].strip().endswith(':'): + return PathParts[0].upper() + # Relative dir, list . current dir + Dirs = os.listdir('.') + for Dir in Dirs: + if Dir.upper() == PathParts[0].upper(): + return Dir + + if PathParts[0].strip().endswith(':'): + PathParts[0] = PathParts[0].upper() + ParentDir = PathParts[0] + RealPath = ParentDir + if PathParts[0] == '': + RealPath = os.sep + ParentDir = os.sep + + PathParts.remove(PathParts[0]) # need to remove the parent + for Part in PathParts: + Dirs = os.listdir(ParentDir + os.sep) + for Dir in Dirs: + if Dir.upper() == Part.upper(): + RealPath += os.sep + RealPath += Dir + break + ParentDir += os.sep + ParentDir += Dir + + return RealPath + + ## ParseOption + # + # Parse options + # + def ParseOption(self): + EdkLogger.quiet("Loading ECC configuration ... done") + (Options, Target) = self.EccOptionParser() + + # Check workspace envirnoment + if "WORKSPACE" not in os.environ: + EdkLogger.error("ECC", BuildToolError.ATTRIBUTE_NOT_AVAILABLE, "Environment variable not found", + ExtraData="WORKSPACE") + else: + EccGlobalData.gWorkspace = os.path.normpath(os.getenv("WORKSPACE")) + if not os.path.exists(EccGlobalData.gWorkspace): + EdkLogger.error("ECC", BuildToolError.FILE_NOT_FOUND, ExtraData="WORKSPACE = %s" % EccGlobalData.gWorkspace) + os.environ["WORKSPACE"] = EccGlobalData.gWorkspace + # Set log level + self.SetLogLevel(Options) + + # Set other options + if Options.ConfigFile != None: + self.ConfigFile = Options.ConfigFile + if Options.OutputFile != None: + self.OutputFile = Options.OutputFile + if Options.ReportFile != None: + self.ReportFile = Options.ReportFile + if Options.Target != None: + if not os.path.isdir(Options.Target): + EdkLogger.error("ECC", BuildToolError.OPTION_VALUE_INVALID, ExtraData="Target [%s] does NOT exist" % Options.Target) + else: + EccGlobalData.gTarget = self.GetRealPathCase(os.path.normpath(Options.Target)) + else: + EdkLogger.warn("Ecc", EdkLogger.ECC_ERROR, "The target source tree was not specified, using current WORKSPACE instead!") + EccGlobalData.gTarget = os.path.normpath(os.getenv("WORKSPACE")) + if Options.keepdatabase != None: + self.IsInit = False + if Options.metadata != None and Options.sourcecode != None: + EdkLogger.error("ECC", BuildToolError.OPTION_CONFLICT, ExtraData="-m and -s can't be specified at one time") + if Options.metadata != None: + self.ScanSourceCode = False + if Options.sourcecode != None: + self.ScanMetaData = False + + ## SetLogLevel + # + # Set current log level of the tool based on args + # + # @param Option: The option list including log level setting + # + def SetLogLevel(self, Option): + if Option.verbose != None: + EdkLogger.SetLevel(EdkLogger.VERBOSE) + elif Option.quiet != None: + EdkLogger.SetLevel(EdkLogger.QUIET) + elif Option.debug != None: + EdkLogger.SetLevel(Option.debug + 1) + else: + EdkLogger.SetLevel(EdkLogger.INFO) + + ## Parse command line options + # + # Using standard Python module optparse to parse command line option of this tool. + # + # @retval Opt A optparse.Values object containing the parsed options + # @retval Args Target of build command + # + def EccOptionParser(self): + Parser = OptionParser(description = self.Copyright, version = self.Version, prog = "Ecc.exe", usage = "%prog [options]") + Parser.add_option("-t", "--target sourcepath", action="store", type="string", dest='Target', + help="Check all files under the target workspace.") + Parser.add_option("-c", "--config filename", action="store", type="string", dest="ConfigFile", + help="Specify a configuration file. Defaultly use config.ini under ECC tool directory.") + Parser.add_option("-o", "--outfile filename", action="store", type="string", dest="OutputFile", + help="Specify the name of an output file, if and only if one filename was specified.") + Parser.add_option("-r", "--reportfile filename", action="store", type="string", dest="ReportFile", + help="Specify the name of an report file, if and only if one filename was specified.") + Parser.add_option("-m", "--metadata", action="store_true", type=None, help="Only scan meta-data files information if this option is specified.") + Parser.add_option("-s", "--sourcecode", action="store_true", type=None, help="Only scan source code files information if this option is specified.") + Parser.add_option("-k", "--keepdatabase", action="store_true", type=None, help="The existing Ecc database will not be cleaned except report information if this option is specified.") + Parser.add_option("-l", "--log filename", action="store", dest="LogFile", help="""If specified, the tool should emit the changes that + were made by the tool after printing the result message. + If filename, the emit to the file, otherwise emit to + standard output. If no modifications were made, then do not + create a log file, or output a log message.""") + Parser.add_option("-q", "--quiet", action="store_true", type=None, help="Disable all messages except FATAL ERRORS.") + Parser.add_option("-v", "--verbose", action="store_true", type=None, help="Turn on verbose output with informational messages printed, "\ + "including library instances selected, final dependency expression, "\ + "and warning messages, etc.") + Parser.add_option("-d", "--debug", action="store", type="int", help="Enable debug messages at specified level.") + + (Opt, Args)=Parser.parse_args() + + return (Opt, Args) + +## +# +# This acts like the main() function for the script, unless it is 'import'ed into another +# script. +# +if __name__ == '__main__': + # Initialize log system + EdkLogger.Initialize() + EdkLogger.IsRaiseError = False + EdkLogger.quiet(time.strftime("%H:%M:%S, %b.%d %Y ", time.localtime()) + "[00:00]" + "\n") + + StartTime = time.clock() + Ecc = Ecc() + FinishTime = time.clock() + + BuildDuration = time.strftime("%M:%S", time.gmtime(int(round(FinishTime - StartTime)))) + EdkLogger.quiet("\n%s [%s]" % (time.strftime("%H:%M:%S, %b.%d %Y", time.localtime()), BuildDuration)) diff --git a/BaseTools/Source/Python/Ecc/EccGlobalData.py b/BaseTools/Source/Python/Ecc/EccGlobalData.py new file mode 100644 index 0000000000..8e8f24b8c8 --- /dev/null +++ b/BaseTools/Source/Python/Ecc/EccGlobalData.py @@ -0,0 +1,24 @@ +## @file +# This file is used to save global datas used by ECC tool +# +# Copyright (c) 2008, 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. +# + +## +# Import Modules +# +import os + +gWorkspace = '' +gTarget = '' +gConfig = None +gDb = None +gIdentifierTableList = [] +gException = None \ No newline at end of file diff --git a/BaseTools/Source/Python/Ecc/EccToolError.py b/BaseTools/Source/Python/Ecc/EccToolError.py new file mode 100644 index 0000000000..9c4d10d55b --- /dev/null +++ b/BaseTools/Source/Python/Ecc/EccToolError.py @@ -0,0 +1,179 @@ +## @file +# Standardized Error Hanlding infrastructures. +# +# Copyright (c) 20087, 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. +# + +ERROR_GENERAL_CHECK_ALL = 1000 +ERROR_GENERAL_CHECK_NO_TAB = 1001 +ERROR_GENERAL_CHECK_INDENTATION = 1002 +ERROR_GENERAL_CHECK_LINE = 1003 +ERROR_GENERAL_CHECK_NO_ASM = 1004 +ERROR_GENERAL_CHECK_NO_PROGMA = 1005 +ERROR_GENERAL_CHECK_CARRIAGE_RETURN = 1006 +ERROR_GENERAL_CHECK_FILE_EXISTENCE = 1007 + +ERROR_SPACE_CHECK_ALL = 2000 + +ERROR_PREDICATE_EXPRESSION_CHECK_ALL = 3000 +ERROR_PREDICATE_EXPRESSION_CHECK_BOOLEAN_VALUE = 3001 +ERROR_PREDICATE_EXPRESSION_CHECK_NO_BOOLEAN_OPERATOR = 3002 +ERROR_PREDICATE_EXPRESSION_CHECK_COMPARISON_NULL_TYPE = 3003 + +ERROR_HEADER_CHECK_ALL = 4000 +ERROR_HEADER_CHECK_FILE = 4001 +ERROR_HEADER_CHECK_FUNCTION = 4002 + +ERROR_C_FUNCTION_LAYOUT_CHECK_ALL = 5000 +ERROR_C_FUNCTION_LAYOUT_CHECK_RETURN_TYPE = 5001 +ERROR_C_FUNCTION_LAYOUT_CHECK_OPTIONAL_FUNCTIONAL_MODIFIER = 5002 +ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME = 5003 +ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE = 5004 +ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_BODY = 5005 +ERROR_C_FUNCTION_LAYOUT_CHECK_DATA_DECLARATION = 5006 +ERROR_C_FUNCTION_LAYOUT_CHECK_NO_INIT_OF_VARIABLE = 5007 +ERROR_C_FUNCTION_LAYOUT_CHECK_NO_STATIC = 5008 + +ERROR_INCLUDE_FILE_CHECK_ALL = 6000 +ERROR_INCLUDE_FILE_CHECK_IFNDEF_STATEMENT_1 = 6001 +ERROR_INCLUDE_FILE_CHECK_IFNDEF_STATEMENT_2 = 6002 +ERROR_INCLUDE_FILE_CHECK_IFNDEF_STATEMENT_3 = 6003 +ERROR_INCLUDE_FILE_CHECK_DATA = 6004 +ERROR_INCLUDE_FILE_CHECK_NAME = 6005 + +ERROR_DECLARATION_DATA_TYPE_CHECK_ALL = 7000 +ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE = 7001 +ERROR_DECLARATION_DATA_TYPE_CHECK_IN_OUT_MODIFIER = 7002 +ERROR_DECLARATION_DATA_TYPE_CHECK_EFI_API_MODIFIER = 7003 +ERROR_DECLARATION_DATA_TYPE_CHECK_ENUMERATED_TYPE = 7004 +ERROR_DECLARATION_DATA_TYPE_CHECK_STRUCTURE_DECLARATION = 7005 +ERROR_DECLARATION_DATA_TYPE_CHECK_SAME_STRUCTURE = 7007 +ERROR_DECLARATION_DATA_TYPE_CHECK_UNION_TYPE = 7006 +ERROR_DECLARATION_DATA_TYPE_CHECK_NESTED_STRUCTURE = 7008 + +ERROR_NAMING_CONVENTION_CHECK_ALL = 8000 +ERROR_NAMING_CONVENTION_CHECK_DEFINE_STATEMENT = 8001 +ERROR_NAMING_CONVENTION_CHECK_TYPEDEF_STATEMENT = 8002 +ERROR_NAMING_CONVENTION_CHECK_IFNDEF_STATEMENT = 8003 +ERROR_NAMING_CONVENTION_CHECK_PATH_NAME = 8004 +ERROR_NAMING_CONVENTION_CHECK_VARIABLE_NAME = 8005 +ERROR_NAMING_CONVENTION_CHECK_FUNCTION_NAME = 8006 +ERROR_NAMING_CONVENTION_CHECK_SINGLE_CHARACTER_VARIABLE = 8007 + +ERROR_DOXYGEN_CHECK_ALL = 9000 +ERROR_DOXYGEN_CHECK_FILE_HEADER = 9001 +ERROR_DOXYGEN_CHECK_FUNCTION_HEADER = 9002 +ERROR_DOXYGEN_CHECK_COMMENT_DESCRIPTION = 9003 +ERROR_DOXYGEN_CHECK_COMMENT_FORMAT = 9004 +ERROR_DOXYGEN_CHECK_COMMAND = 9005 + +ERROR_META_DATA_FILE_CHECK_ALL = 10000 +ERROR_META_DATA_FILE_CHECK_PATH_NAME = 10001 +ERROR_META_DATA_FILE_CHECK_LIBRARY_INSTANCE_1 = 10002 +ERROR_META_DATA_FILE_CHECK_LIBRARY_INSTANCE_2 = 10003 +ERROR_META_DATA_FILE_CHECK_LIBRARY_INSTANCE_DEPENDENT = 10004 +ERROR_META_DATA_FILE_CHECK_LIBRARY_INSTANCE_ORDER = 10005 +ERROR_META_DATA_FILE_CHECK_LIBRARY_NO_USE = 10006 +ERROR_META_DATA_FILE_CHECK_BINARY_INF_IN_FDF = 10007 +ERROR_META_DATA_FILE_CHECK_PCD_DUPLICATE = 10008 +ERROR_META_DATA_FILE_CHECK_PCD_FLASH = 10009 +ERROR_META_DATA_FILE_CHECK_PCD_NO_USE = 10010 +ERROR_META_DATA_FILE_CHECK_DUPLICATE_GUID = 10011 +ERROR_META_DATA_FILE_CHECK_DUPLICATE_PROTOCOL = 10012 +ERROR_META_DATA_FILE_CHECK_DUPLICATE_PPI = 10013 +ERROR_META_DATA_FILE_CHECK_MODULE_FILE_NO_USE = 10014 +ERROR_META_DATA_FILE_CHECK_PCD_TYPE = 10015 + +ERROR_SPELLING_CHECK_ALL = 11000 + +gEccErrorMessage = { + ERROR_GENERAL_CHECK_ALL : "", + ERROR_GENERAL_CHECK_NO_TAB : "'TAB' character is not allowed in source code, please replace each 'TAB' with two spaces", + ERROR_GENERAL_CHECK_INDENTATION : "Indentation does not follow coding style", + ERROR_GENERAL_CHECK_LINE : "The width of each line does not follow coding style", + ERROR_GENERAL_CHECK_NO_ASM : "There should be no use of _asm in the source file", + ERROR_GENERAL_CHECK_NO_PROGMA : """There should be no use of "#progma" in source file except "#pragma pack(#)\"""", + ERROR_GENERAL_CHECK_CARRIAGE_RETURN : "There should be a carriage return at the end of the file", + ERROR_GENERAL_CHECK_FILE_EXISTENCE : "File not found", + + ERROR_SPACE_CHECK_ALL : "", + + ERROR_PREDICATE_EXPRESSION_CHECK_ALL : "", + ERROR_PREDICATE_EXPRESSION_CHECK_BOOLEAN_VALUE : "Boolean values and variable type BOOLEAN should not use explicit comparisons to TRUE or FALSE", + ERROR_PREDICATE_EXPRESSION_CHECK_NO_BOOLEAN_OPERATOR : "Non-Boolean comparisons should use a compare operator (==, !=, >, < >=, <=)", + ERROR_PREDICATE_EXPRESSION_CHECK_COMPARISON_NULL_TYPE : "A comparison of any pointer to zero must be done via the NULL type", + + ERROR_HEADER_CHECK_ALL : "", + ERROR_HEADER_CHECK_FILE : "File header doesn't exist", + ERROR_HEADER_CHECK_FUNCTION : "Function header doesn't exist", + + ERROR_C_FUNCTION_LAYOUT_CHECK_ALL : "", + ERROR_C_FUNCTION_LAYOUT_CHECK_RETURN_TYPE : "Return type of a function should exist and in the first line", + ERROR_C_FUNCTION_LAYOUT_CHECK_OPTIONAL_FUNCTIONAL_MODIFIER : "Any optional functional modifiers should exist and next to the return type", + ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME : """Function name should be left justified, followed by the beginning of the parameter list, with the closing parenthesis on its own line, indented two spaces""", + ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE : "Function prototypes in include files have the same form as function definitions", + ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_BODY : "The body of a function should be contained by open and close braces that must be in the first column", + ERROR_C_FUNCTION_LAYOUT_CHECK_DATA_DECLARATION : "The data declarations should be the first code in a module", + ERROR_C_FUNCTION_LAYOUT_CHECK_NO_INIT_OF_VARIABLE : "There should be no initialization of a variable as part of its declaration", + ERROR_C_FUNCTION_LAYOUT_CHECK_NO_STATIC : "There should be no use of STATIC for functions", + + ERROR_INCLUDE_FILE_CHECK_ALL : "", + ERROR_INCLUDE_FILE_CHECK_IFNDEF_STATEMENT_1 : "All include file contents should be guarded by a #ifndef statement.", + ERROR_INCLUDE_FILE_CHECK_IFNDEF_STATEMENT_2 : "The #ifndef must be the first line of code following the file header comment", + ERROR_INCLUDE_FILE_CHECK_IFNDEF_STATEMENT_3 : "The #endif must appear on the last line in the file", + ERROR_INCLUDE_FILE_CHECK_DATA : "Include files should contain only public or only private data and cannot contain code or define data variables", + ERROR_INCLUDE_FILE_CHECK_NAME : "No permission for the inlcude file with same names", + + ERROR_DECLARATION_DATA_TYPE_CHECK_ALL : "", + ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE : "There should be no use of int, unsigned, char, void, static, long in any .c, .h or .asl files", + ERROR_DECLARATION_DATA_TYPE_CHECK_IN_OUT_MODIFIER : """The modifiers IN, OUT, OPTIONAL, and UNALIGNED should be used only to qualify arguments to a function and should not appear in a data type declaration""", + ERROR_DECLARATION_DATA_TYPE_CHECK_EFI_API_MODIFIER : "The EFIAPI modifier should be used at the entry of drivers, events, and member functions of protocols", + ERROR_DECLARATION_DATA_TYPE_CHECK_ENUMERATED_TYPE : "Enumerated Type should have a 'typedef' and the name must be in capital letters", + ERROR_DECLARATION_DATA_TYPE_CHECK_STRUCTURE_DECLARATION : "Structure Type should have a 'typedef' and the name must be in capital letters", + ERROR_DECLARATION_DATA_TYPE_CHECK_SAME_STRUCTURE : "No permission for the structure with same names", + ERROR_DECLARATION_DATA_TYPE_CHECK_UNION_TYPE : "Union Type should have a 'typedef' and the name must be in capital letters", + ERROR_DECLARATION_DATA_TYPE_CHECK_NESTED_STRUCTURE : "Complex types should be typedef-ed", + + ERROR_NAMING_CONVENTION_CHECK_ALL : "", + ERROR_NAMING_CONVENTION_CHECK_DEFINE_STATEMENT : "Only capital letters are allowed to be used for #define declarations", + ERROR_NAMING_CONVENTION_CHECK_TYPEDEF_STATEMENT : "Only capital letters are allowed to be used for typedef declarations", + ERROR_NAMING_CONVENTION_CHECK_IFNDEF_STATEMENT : "The #ifndef at the start of an include file should use both prefix and postfix underscore characters, '_'", + ERROR_NAMING_CONVENTION_CHECK_PATH_NAME : """Path name does not follow the rules: 1. First character should be upper case 2. Must contain lower case characters 3. No white space characters""", + ERROR_NAMING_CONVENTION_CHECK_VARIABLE_NAME : """Variable name does not follow the rules: 1. First character should be upper case 2. Must contain lower case characters 3. No white space characters 4. Global variable name must start with a 'g'""", + ERROR_NAMING_CONVENTION_CHECK_FUNCTION_NAME : """Function name does not follow the rules: 1. First character should be upper case 2. Must contain lower case characters 3. No white space characters""", + ERROR_NAMING_CONVENTION_CHECK_SINGLE_CHARACTER_VARIABLE : "There should be no use of short (single character) variable names", + + ERROR_DOXYGEN_CHECK_ALL : "", + ERROR_DOXYGEN_CHECK_FILE_HEADER : "The file headers should follow Doxygen special documentation blocks in section 2.3.5", + ERROR_DOXYGEN_CHECK_FUNCTION_HEADER : "The function headers should follow Doxygen special documentation blocks in section 2.3.5", + ERROR_DOXYGEN_CHECK_COMMENT_DESCRIPTION : """The first line of text in a comment block should be a brief description of the element being documented and the brief description must end with a period.""", + ERROR_DOXYGEN_CHECK_COMMENT_FORMAT : "For comment line with '///< ... text ...' format, if it is used, it should be after the code section", + ERROR_DOXYGEN_CHECK_COMMAND : "Only Doxygen commands @bug and @todo are allowed to mark the code", + + ERROR_META_DATA_FILE_CHECK_ALL : "", + ERROR_META_DATA_FILE_CHECK_PATH_NAME : "The file defined in meta-data does not exist", + ERROR_META_DATA_FILE_CHECK_LIBRARY_INSTANCE_1 : "A library instances defined for a given module (or dependent library instance) doesn't match the module's type.", + ERROR_META_DATA_FILE_CHECK_LIBRARY_INSTANCE_2 : "A library instance must specify the Supported Module Types in its INF file", + ERROR_META_DATA_FILE_CHECK_LIBRARY_INSTANCE_DEPENDENT : "A library instance must be defined for all dependent library classes", + ERROR_META_DATA_FILE_CHECK_LIBRARY_INSTANCE_ORDER : "The library Instances specified by the LibraryClasses sections should be listed in order of dependencies", + ERROR_META_DATA_FILE_CHECK_LIBRARY_NO_USE : "There should be no unnecessary inclusion of library classes in the INF file", + ERROR_META_DATA_FILE_CHECK_BINARY_INF_IN_FDF : "An INF file is specified in the FDF file, but not in the DSC file, therefore the INF file must be for a Binary module only", + ERROR_META_DATA_FILE_CHECK_PCD_DUPLICATE : "Duplicate PCDs found", + ERROR_META_DATA_FILE_CHECK_PCD_FLASH : "PCD settings in the FDF file should only be related to flash", + ERROR_META_DATA_FILE_CHECK_PCD_NO_USE : "There should be no PCDs declared in INF files that are not specified in in either a DSC or FDF file", + ERROR_META_DATA_FILE_CHECK_DUPLICATE_GUID : "Duplicate GUID found", + ERROR_META_DATA_FILE_CHECK_DUPLICATE_PROTOCOL : "Duplicate PROTOCOL found", + ERROR_META_DATA_FILE_CHECK_DUPLICATE_PPI : "Duplicate PPI found", + ERROR_META_DATA_FILE_CHECK_MODULE_FILE_NO_USE : "No used module files found", + ERROR_META_DATA_FILE_CHECK_PCD_TYPE : "Wrong C code function used for this kind of PCD", + + ERROR_SPELLING_CHECK_ALL : "", + } + diff --git a/BaseTools/Source/Python/Ecc/Exception.py b/BaseTools/Source/Python/Ecc/Exception.py new file mode 100644 index 0000000000..733408551a --- /dev/null +++ b/BaseTools/Source/Python/Ecc/Exception.py @@ -0,0 +1,87 @@ +## @file +# This file is used to parse exception items found by ECC tool +# +# Copyright (c) 2009, 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. +# + +## +# Import Modules +# +from Common.XmlRoutines import * +import os.path + +# ExceptionXml to parse Exception Node of XML file +class ExceptionXml(object): + def __init__(self): + self.KeyWord = '' + self.ErrorID = '' + self.FilePath = '' + + def FromXml(self, Item, Key): + self.KeyWord = XmlElement(Item, '%s/KeyWord' % Key) + self.ErrorID = XmlElement(Item, '%s/ErrorID' % Key) + self.FilePath = os.path.normpath(XmlElement(Item, '%s/FilePath' % Key)) + + def __str__(self): + return 'ErrorID = %s KeyWord = %s FilePath = %s' %(self.ErrorID, self.KeyWord, self.FilePath) + +# ExceptionListXml to parse Exception Node List of XML file +class ExceptionListXml(object): + def __init__(self): + self.List = [] + + def FromXmlFile(self, FilePath): + XmlContent = XmlParseFile(FilePath) + for Item in XmlList(XmlContent, '/ExceptionList/Exception'): + Exp = ExceptionXml() + Exp.FromXml(Item, 'Exception') + self.List.append(Exp) + + def ToList(self): + RtnList = [] + for Item in self.List: + #RtnList.append((Item.ErrorID, Item.KeyWord, Item.FilePath)) + RtnList.append((Item.ErrorID, Item.KeyWord)) + + return RtnList + + def __str__(self): + RtnStr = '' + if self.List: + for Item in self.List: + RtnStr = RtnStr + str(Item) + '\n' + return RtnStr + +# A class to check exception +class ExceptionCheck(object): + def __init__(self, FilePath = None): + self.ExceptionList = [] + self.ExceptionListXml = ExceptionListXml() + self.LoadExceptionListXml(FilePath) + + def LoadExceptionListXml(self, FilePath): + if FilePath and os.path.isfile(FilePath): + self.ExceptionListXml.FromXmlFile(FilePath) + self.ExceptionList = self.ExceptionListXml.ToList() + + def IsException(self, ErrorID, KeyWord, FileID=-1): + if (str(ErrorID), KeyWord) in self.ExceptionList: + return True + else: + return False + +## +# +# This acts like the main() function for the script, unless it is 'import'ed into another +# script. +# +if __name__ == '__main__': + El = ExceptionCheck('C:\\Hess\\Project\\BuildTool\\src\\Ecc\\exception.xml') + print El.ExceptionList diff --git a/BaseTools/Source/Python/Ecc/FileProfile.py b/BaseTools/Source/Python/Ecc/FileProfile.py new file mode 100644 index 0000000000..810087ea07 --- /dev/null +++ b/BaseTools/Source/Python/Ecc/FileProfile.py @@ -0,0 +1,57 @@ +## @file +# fragments of source file +# +# Copyright (c) 2007, 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. +# + +## +# Import Modules +# + +import re +import os +from ParserWarning import Warning + +CommentList = [] +PPDirectiveList = [] +PredicateExpressionList = [] +FunctionDefinitionList = [] +VariableDeclarationList = [] +EnumerationDefinitionList = [] +StructUnionDefinitionList = [] +TypedefDefinitionList = [] +FunctionCallingList = [] + +## record file data when parsing source +# +# May raise Exception when opening file. +# +class FileProfile : + + ## The constructor + # + # @param self The object pointer + # @param FileName The file that to be parsed + # + def __init__(self, FileName): + self.FileLinesList = [] + self.FileLinesListFromFile = [] + try: + fsock = open(FileName, "rb", 0) + try: + self.FileLinesListFromFile = fsock.readlines() + finally: + fsock.close() + + except IOError: + raise Warning("Error when opening file %s" % FileName) + + \ No newline at end of file diff --git a/BaseTools/Source/Python/Ecc/MetaDataParser.py b/BaseTools/Source/Python/Ecc/MetaDataParser.py new file mode 100644 index 0000000000..fb4239f474 --- /dev/null +++ b/BaseTools/Source/Python/Ecc/MetaDataParser.py @@ -0,0 +1,65 @@ +## @file +# This file is used to define common parser functions for meta-data +# +# Copyright (c) 2008, 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. +# + +import os +from CommonDataClass.DataClass import * + + +## Get the inlcude path list for a source file +# +# 1. Find the source file belongs to which inf file +# 2. Find the inf's package +# 3. Return the include path list of the package +# +def GetIncludeListOfFile(WorkSpace, Filepath, Db): + IncludeList = [] + Filepath = os.path.normpath(Filepath) + SqlCommand = """ + select Value1, FullPath from Inf, File where Inf.Model = %s and Inf.BelongsToFile in( + select distinct B.BelongsToFile from File as A left join Inf as B + where A.ID = B.BelongsToFile and B.Model = %s and (A.Path || '%s' || B.Value1) = '%s') + and Inf.BelongsToFile = File.ID""" \ + % (MODEL_META_DATA_PACKAGE, MODEL_EFI_SOURCE_FILE, '\\', Filepath) + RecordSet = Db.TblFile.Exec(SqlCommand) + for Record in RecordSet: + DecFullPath = os.path.normpath(os.path.join(WorkSpace, Record[0])) + InfFullPath = os.path.normpath(os.path.join(WorkSpace, Record[1])) + (DecPath, DecName) = os.path.split(DecFullPath) + (InfPath, InfName) = os.path.split(InfFullPath) + SqlCommand = """select Value1 from Dec where BelongsToFile = + (select ID from File where FullPath = '%s') and Model = %s""" \ + % (DecFullPath, MODEL_EFI_INCLUDE) + NewRecordSet = Db.TblDec.Exec(SqlCommand) + if InfPath not in IncludeList: + IncludeList.append(InfPath) + for NewRecord in NewRecordSet: + IncludePath = os.path.normpath(os.path.join(DecPath, NewRecord[0])) + if IncludePath not in IncludeList: + IncludeList.append(IncludePath) + + return IncludeList + +## Get the table list +# +# Search table file and find all small tables +# +def GetTableList(FileModelList, Table, Db): + TableList = [] + SqlCommand = """select ID from File where Model in %s""" % str(FileModelList) + RecordSet = Db.TblFile.Exec(SqlCommand) + for Record in RecordSet: + TableName = Table + str(Record[0]) + TableList.append(TableName) + + return TableList + diff --git a/BaseTools/Source/Python/Ecc/ParserWarning.py b/BaseTools/Source/Python/Ecc/ParserWarning.py new file mode 100644 index 0000000000..547360d927 --- /dev/null +++ b/BaseTools/Source/Python/Ecc/ParserWarning.py @@ -0,0 +1,17 @@ +## The exception class that used to report error messages when preprocessing +# +# Currently the "ToolName" is set to be "ECC PP". +# +class Warning (Exception): + ## The constructor + # + # @param self The object pointer + # @param Str The message to record + # @param File The FDF name + # @param Line The Line number that error occurs + # + def __init__(self, Str, File = None, Line = None): + self.message = Str + self.FileName = File + self.LineNumber = Line + self.ToolName = 'ECC PP' \ No newline at end of file diff --git a/BaseTools/Source/Python/Ecc/__init__.py b/BaseTools/Source/Python/Ecc/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/BaseTools/Source/Python/Ecc/c.py b/BaseTools/Source/Python/Ecc/c.py new file mode 100644 index 0000000000..b8b1d2d6f5 --- /dev/null +++ b/BaseTools/Source/Python/Ecc/c.py @@ -0,0 +1,2503 @@ +import sys +import os +import re +import string +import CodeFragmentCollector +import FileProfile +from CommonDataClass import DataClass +import Database +from Common import EdkLogger +from EccToolError import * +import EccGlobalData +import MetaDataParser + +IncludeFileListDict = {} +AllIncludeFileListDict = {} +IncludePathListDict = {} +ComplexTypeDict = {} +SUDict = {} +IgnoredKeywordList = ['EFI_ERROR'] + +def GetIgnoredDirListPattern(): + skipList = list(EccGlobalData.gConfig.SkipDirList) + ['.svn'] + DirString = string.join(skipList, '|') + p = re.compile(r'.*[\\/](?:%s)[\\/]?.*' % DirString) + return p + +def GetFuncDeclPattern(): + p = re.compile(r'(?:EFIAPI|EFI_BOOT_SERVICE|EFI_RUNTIME_SERVICE)?\s*[_\w]+\s*\(.*\)$', re.DOTALL) + return p + +def GetArrayPattern(): + p = re.compile(r'[_\w]*\s*[\[.*\]]+') + return p + +def GetTypedefFuncPointerPattern(): + p = re.compile('[_\w\s]*\([\w\s]*\*+\s*[_\w]+\s*\)\s*\(.*\)', re.DOTALL) + return p + +def GetDB(): + return EccGlobalData.gDb + +def GetConfig(): + return EccGlobalData.gConfig + +def PrintErrorMsg(ErrorType, Msg, TableName, ItemId): + Msg = Msg.replace('\n', '').replace('\r', '') + MsgPartList = Msg.split() + Msg = '' + for Part in MsgPartList: + Msg += Part + Msg += ' ' + GetDB().TblReport.Insert(ErrorType, OtherMsg = Msg, BelongsToTable = TableName, BelongsToItem = ItemId) + +def GetIdType(Str): + Type = DataClass.MODEL_UNKNOWN + Str = Str.replace('#', '# ') + List = Str.split() + if List[1] == 'include': + Type = DataClass.MODEL_IDENTIFIER_INCLUDE + elif List[1] == 'define': + Type = DataClass.MODEL_IDENTIFIER_MACRO_DEFINE + elif List[1] == 'ifdef': + Type = DataClass.MODEL_IDENTIFIER_MACRO_IFDEF + elif List[1] == 'ifndef': + Type = DataClass.MODEL_IDENTIFIER_MACRO_IFNDEF + elif List[1] == 'endif': + Type = DataClass.MODEL_IDENTIFIER_MACRO_ENDIF + elif List[1] == 'pragma': + Type = DataClass.MODEL_IDENTIFIER_MACRO_PROGMA + else: + Type = DataClass.MODEL_UNKNOWN + return Type + +def SuOccurInTypedef (Su, TdList): + for Td in TdList: + if Su.StartPos[0] == Td.StartPos[0] and Su.EndPos[0] == Td.EndPos[0]: + return True + return False + +def GetIdentifierList(): + IdList = [] + for comment in FileProfile.CommentList: + IdComment = DataClass.IdentifierClass(-1, '', '', '', comment.Content, DataClass.MODEL_IDENTIFIER_COMMENT, -1, -1, comment.StartPos[0],comment.StartPos[1],comment.EndPos[0],comment.EndPos[1]) + IdList.append(IdComment) + + for pp in FileProfile.PPDirectiveList: + Type = GetIdType(pp.Content) + IdPP = DataClass.IdentifierClass(-1, '', '', '', pp.Content, Type, -1, -1, pp.StartPos[0],pp.StartPos[1],pp.EndPos[0],pp.EndPos[1]) + IdList.append(IdPP) + + for pe in FileProfile.PredicateExpressionList: + IdPE = DataClass.IdentifierClass(-1, '', '', '', pe.Content, DataClass.MODEL_IDENTIFIER_PREDICATE_EXPRESSION, -1, -1, pe.StartPos[0],pe.StartPos[1],pe.EndPos[0],pe.EndPos[1]) + IdList.append(IdPE) + + FuncDeclPattern = GetFuncDeclPattern() + ArrayPattern = GetArrayPattern() + for var in FileProfile.VariableDeclarationList: + DeclText = var.Declarator.lstrip() + FuncPointerPattern = GetTypedefFuncPointerPattern() + if FuncPointerPattern.match(DeclText): + continue + VarNameStartLine = var.NameStartPos[0] + VarNameStartColumn = var.NameStartPos[1] + FirstChar = DeclText[0] + while not FirstChar.isalpha() and FirstChar != '_': + if FirstChar == '*': + var.Modifier += '*' + VarNameStartColumn += 1 + DeclText = DeclText.lstrip('*') + elif FirstChar == '\r': + DeclText = DeclText.lstrip('\r\n').lstrip('\r') + VarNameStartLine += 1 + VarNameStartColumn = 0 + elif FirstChar == '\n': + DeclText = DeclText.lstrip('\n') + VarNameStartLine += 1 + VarNameStartColumn = 0 + elif FirstChar == ' ': + DeclText = DeclText.lstrip(' ') + VarNameStartColumn += 1 + elif FirstChar == '\t': + DeclText = DeclText.lstrip('\t') + VarNameStartColumn += 8 + else: + DeclText = DeclText[1:] + VarNameStartColumn += 1 + FirstChar = DeclText[0] + + var.Declarator = DeclText + if FuncDeclPattern.match(var.Declarator): + DeclSplitList = var.Declarator.split('(') + FuncName = DeclSplitList[0].strip() + FuncNamePartList = FuncName.split() + if len(FuncNamePartList) > 1: + FuncName = FuncNamePartList[-1].strip() + NameStart = DeclSplitList[0].rfind(FuncName) + var.Declarator = var.Declarator[NameStart:] + if NameStart > 0: + var.Modifier += ' ' + DeclSplitList[0][0:NameStart] + Index = 0 + PreChar = '' + while Index < NameStart: + FirstChar = DeclSplitList[0][Index] + if DeclSplitList[0][Index:].startswith('EFIAPI'): + Index += 6 + VarNameStartColumn += 6 + PreChar = '' + continue + elif FirstChar == '\r': + Index += 1 + VarNameStartLine += 1 + VarNameStartColumn = 0 + elif FirstChar == '\n': + Index += 1 + if PreChar != '\r': + VarNameStartLine += 1 + VarNameStartColumn = 0 + elif FirstChar == ' ': + Index += 1 + VarNameStartColumn += 1 + elif FirstChar == '\t': + Index += 1 + VarNameStartColumn += 8 + else: + Index += 1 + VarNameStartColumn += 1 + PreChar = FirstChar + IdVar = DataClass.IdentifierClass(-1, var.Modifier, '', var.Declarator, FuncName, DataClass.MODEL_IDENTIFIER_FUNCTION_DECLARATION, -1, -1, var.StartPos[0], var.StartPos[1], VarNameStartLine, VarNameStartColumn) + IdList.append(IdVar) + continue + + if var.Declarator.find('{') == -1: + for decl in var.Declarator.split(','): + DeclList = decl.split('=') + Name = DeclList[0].strip() + if ArrayPattern.match(Name): + LSBPos = var.Declarator.find('[') + var.Modifier += ' ' + Name[LSBPos:] + Name = Name[0:LSBPos] + + IdVar = DataClass.IdentifierClass(-1, var.Modifier, '', Name, (len(DeclList) > 1 and [DeclList[1]]or [''])[0], DataClass.MODEL_IDENTIFIER_VARIABLE, -1, -1, var.StartPos[0],var.StartPos[1], VarNameStartLine, VarNameStartColumn) + IdList.append(IdVar) + else: + DeclList = var.Declarator.split('=') + Name = DeclList[0].strip() + if ArrayPattern.match(Name): + LSBPos = var.Declarator.find('[') + var.Modifier += ' ' + Name[LSBPos:] + Name = Name[0:LSBPos] + IdVar = DataClass.IdentifierClass(-1, var.Modifier, '', Name, (len(DeclList) > 1 and [DeclList[1]]or [''])[0], DataClass.MODEL_IDENTIFIER_VARIABLE, -1, -1, var.StartPos[0],var.StartPos[1], VarNameStartLine, VarNameStartColumn) + IdList.append(IdVar) + + for enum in FileProfile.EnumerationDefinitionList: + LBPos = enum.Content.find('{') + RBPos = enum.Content.find('}') + Name = enum.Content[4:LBPos].strip() + Value = enum.Content[LBPos+1:RBPos] + IdEnum = DataClass.IdentifierClass(-1, '', '', Name, Value, DataClass.MODEL_IDENTIFIER_ENUMERATE, -1, -1, enum.StartPos[0],enum.StartPos[1],enum.EndPos[0],enum.EndPos[1]) + IdList.append(IdEnum) + + for su in FileProfile.StructUnionDefinitionList: + if SuOccurInTypedef(su, FileProfile.TypedefDefinitionList): + continue + Type = DataClass.MODEL_IDENTIFIER_STRUCTURE + SkipLen = 6 + if su.Content.startswith('union'): + Type = DataClass.MODEL_IDENTIFIER_UNION + SkipLen = 5 + LBPos = su.Content.find('{') + RBPos = su.Content.find('}') + if LBPos == -1 or RBPos == -1: + Name = su.Content[SkipLen:].strip() + Value = '' + else: + Name = su.Content[SkipLen:LBPos].strip() + Value = su.Content[LBPos:RBPos+1] + IdPE = DataClass.IdentifierClass(-1, '', '', Name, Value, Type, -1, -1, su.StartPos[0],su.StartPos[1],su.EndPos[0],su.EndPos[1]) + IdList.append(IdPE) + + TdFuncPointerPattern = GetTypedefFuncPointerPattern() + for td in FileProfile.TypedefDefinitionList: + Modifier = '' + Name = td.ToType + Value = td.FromType + if TdFuncPointerPattern.match(td.ToType): + Modifier = td.FromType + LBPos = td.ToType.find('(') + TmpStr = td.ToType[LBPos+1:].strip() + StarPos = TmpStr.find('*') + if StarPos != -1: + Modifier += ' ' + TmpStr[0:StarPos] + while TmpStr[StarPos] == '*': +# Modifier += ' ' + '*' + StarPos += 1 + TmpStr = TmpStr[StarPos:].strip() + RBPos = TmpStr.find(')') + Name = TmpStr[0:RBPos] + Value = 'FP' + TmpStr[RBPos + 1:] + else: + while Name.startswith('*'): + Value += ' ' + '*' + Name = Name.lstrip('*').strip() + + if Name.find('[') != -1: + LBPos = Name.find('[') + RBPos = Name.rfind(']') + Value += Name[LBPos : RBPos + 1] + Name = Name[0 : LBPos] + + IdTd = DataClass.IdentifierClass(-1, Modifier, '', Name, Value, DataClass.MODEL_IDENTIFIER_TYPEDEF, -1, -1, td.StartPos[0],td.StartPos[1],td.EndPos[0],td.EndPos[1]) + IdList.append(IdTd) + + for funcCall in FileProfile.FunctionCallingList: + IdFC = DataClass.IdentifierClass(-1, '', '', funcCall.FuncName, funcCall.ParamList, DataClass.MODEL_IDENTIFIER_FUNCTION_CALLING, -1, -1, funcCall.StartPos[0],funcCall.StartPos[1],funcCall.EndPos[0],funcCall.EndPos[1]) + IdList.append(IdFC) + return IdList + +def StripNonAlnumChars(Str): + StrippedStr = '' + for Char in Str: + if Char.isalnum(): + StrippedStr += Char + return StrippedStr + +def GetParamList(FuncDeclarator, FuncNameLine = 0, FuncNameOffset = 0): + FuncDeclarator = StripComments(FuncDeclarator) + ParamIdList = [] + #DeclSplitList = FuncDeclarator.split('(') + LBPos = FuncDeclarator.find('(') + #if len(DeclSplitList) < 2: + if LBPos == -1: + return ParamIdList + #FuncName = DeclSplitList[0] + FuncName = FuncDeclarator[0:LBPos] + #ParamStr = DeclSplitList[1].rstrip(')') + ParamStr = FuncDeclarator[LBPos + 1:].rstrip(')') + LineSkipped = 0 + OffsetSkipped = 0 + TailChar = FuncName[-1] + while not TailChar.isalpha() and TailChar != '_': + + if TailChar == '\n': + FuncName = FuncName.rstrip('\r\n').rstrip('\n') + LineSkipped += 1 + OffsetSkipped = 0 + elif TailChar == '\r': + FuncName = FuncName.rstrip('\r') + LineSkipped += 1 + OffsetSkipped = 0 + elif TailChar == ' ': + FuncName = FuncName.rstrip(' ') + OffsetSkipped += 1 + elif TailChar == '\t': + FuncName = FuncName.rstrip('\t') + OffsetSkipped += 8 + else: + FuncName = FuncName[:-1] + TailChar = FuncName[-1] + + OffsetSkipped += 1 #skip '(' + + for p in ParamStr.split(','): + ListP = p.split() + if len(ListP) == 0: + continue + ParamName = ListP[-1] + DeclText = ParamName.strip() + RightSpacePos = p.rfind(ParamName) + ParamModifier = p[0:RightSpacePos] + if ParamName == 'OPTIONAL': + if ParamModifier == '': + ParamModifier += ' ' + 'OPTIONAL' + DeclText = '' + else: + ParamName = ListP[-2] + DeclText = ParamName.strip() + RightSpacePos = p.rfind(ParamName) + ParamModifier = p[0:RightSpacePos] + ParamModifier += 'OPTIONAL' + while DeclText.startswith('*'): + ParamModifier += ' ' + '*' + DeclText = DeclText.lstrip('*').strip() + ParamName = DeclText + # ignore array length if exists. + LBIndex = ParamName.find('[') + if LBIndex != -1: + ParamName = ParamName[0:LBIndex] + + Start = RightSpacePos + Index = 0 + PreChar = '' + while Index < Start: + FirstChar = p[Index] + + if FirstChar == '\r': + Index += 1 + LineSkipped += 1 + OffsetSkipped = 0 + elif FirstChar == '\n': + Index += 1 + if PreChar != '\r': + LineSkipped += 1 + OffsetSkipped = 0 + elif FirstChar == ' ': + Index += 1 + OffsetSkipped += 1 + elif FirstChar == '\t': + Index += 1 + OffsetSkipped += 8 + else: + Index += 1 + OffsetSkipped += 1 + PreChar = FirstChar + + ParamBeginLine = FuncNameLine + LineSkipped + ParamBeginOffset = FuncNameOffset + OffsetSkipped + + Index = Start + len(ParamName) + PreChar = '' + while Index < len(p): + FirstChar = p[Index] + + if FirstChar == '\r': + Index += 1 + LineSkipped += 1 + OffsetSkipped = 0 + elif FirstChar == '\n': + Index += 1 + if PreChar != '\r': + LineSkipped += 1 + OffsetSkipped = 0 + elif FirstChar == ' ': + Index += 1 + OffsetSkipped += 1 + elif FirstChar == '\t': + Index += 1 + OffsetSkipped += 8 + else: + Index += 1 + OffsetSkipped += 1 + PreChar = FirstChar + + ParamEndLine = FuncNameLine + LineSkipped + ParamEndOffset = FuncNameOffset + OffsetSkipped + if ParamName != '...': + ParamName = StripNonAlnumChars(ParamName) + IdParam = DataClass.IdentifierClass(-1, ParamModifier, '', ParamName, '', DataClass.MODEL_IDENTIFIER_PARAMETER, -1, -1, ParamBeginLine, ParamBeginOffset, ParamEndLine, ParamEndOffset) + ParamIdList.append(IdParam) + + OffsetSkipped += 1 #skip ',' + + return ParamIdList + +def GetFunctionList(): + FuncObjList = [] + for FuncDef in FileProfile.FunctionDefinitionList: + ParamIdList = [] + DeclText = FuncDef.Declarator.lstrip() + FuncNameStartLine = FuncDef.NamePos[0] + FuncNameStartColumn = FuncDef.NamePos[1] + FirstChar = DeclText[0] + while not FirstChar.isalpha() and FirstChar != '_': + if FirstChar == '*': + FuncDef.Modifier += '*' + FuncNameStartColumn += 1 + DeclText = DeclText.lstrip('*') + elif FirstChar == '\r': + DeclText = DeclText.lstrip('\r\n').lstrip('\r') + FuncNameStartLine += 1 + FuncNameStartColumn = 0 + elif FirstChar == '\n': + DeclText = DeclText.lstrip('\n') + FuncNameStartLine += 1 + FuncNameStartColumn = 0 + elif FirstChar == ' ': + DeclText = DeclText.lstrip(' ') + FuncNameStartColumn += 1 + elif FirstChar == '\t': + DeclText = DeclText.lstrip('\t') + FuncNameStartColumn += 8 + else: + DeclText = DeclText[1:] + FuncNameStartColumn += 1 + FirstChar = DeclText[0] + + FuncDef.Declarator = DeclText + DeclSplitList = FuncDef.Declarator.split('(') + if len(DeclSplitList) < 2: + continue + + FuncName = DeclSplitList[0] + FuncNamePartList = FuncName.split() + if len(FuncNamePartList) > 1: + FuncName = FuncNamePartList[-1] + NameStart = DeclSplitList[0].rfind(FuncName) + if NameStart > 0: + FuncDef.Modifier += ' ' + DeclSplitList[0][0:NameStart] + Index = 0 + PreChar = '' + while Index < NameStart: + FirstChar = DeclSplitList[0][Index] + if DeclSplitList[0][Index:].startswith('EFIAPI'): + Index += 6 + FuncNameStartColumn += 6 + PreChar = '' + continue + elif FirstChar == '\r': + Index += 1 + FuncNameStartLine += 1 + FuncNameStartColumn = 0 + elif FirstChar == '\n': + Index += 1 + if PreChar != '\r': + FuncNameStartLine += 1 + FuncNameStartColumn = 0 + elif FirstChar == ' ': + Index += 1 + FuncNameStartColumn += 1 + elif FirstChar == '\t': + Index += 1 + FuncNameStartColumn += 8 + else: + Index += 1 + FuncNameStartColumn += 1 + PreChar = FirstChar + + FuncObj = DataClass.FunctionClass(-1, FuncDef.Declarator, FuncDef.Modifier, FuncName.strip(), '', FuncDef.StartPos[0],FuncDef.StartPos[1],FuncDef.EndPos[0],FuncDef.EndPos[1], FuncDef.LeftBracePos[0], FuncDef.LeftBracePos[1], -1, ParamIdList, [], FuncNameStartLine, FuncNameStartColumn) + FuncObjList.append(FuncObj) + + return FuncObjList + +def GetFileModificationTimeFromDB(FullFileName): + TimeValue = 0.0 + Db = GetDB() + SqlStatement = """ select TimeStamp + from File + where FullPath = \'%s\' + """ % (FullFileName) + ResultSet = Db.TblFile.Exec(SqlStatement) + for Result in ResultSet: + TimeValue = Result[0] + return TimeValue + +def CollectSourceCodeDataIntoDB(RootDir): + FileObjList = [] + tuple = os.walk(RootDir) + IgnoredPattern = GetIgnoredDirListPattern() + ParseErrorFileList = [] + + for dirpath, dirnames, filenames in tuple: + if IgnoredPattern.match(dirpath.upper()): + continue + + for Dir in dirnames: + Dirname = os.path.join(dirpath, Dir) + if os.path.islink(Dirname): + Dirname = os.path.realpath(Dirname) + if os.path.isdir(Dirname): + # symlinks to directories are treated as directories + dirnames.remove(Dir) + dirnames.append(Dirname) + + for f in filenames: + FullName = os.path.normpath(os.path.join(dirpath, f)) + if os.path.splitext(f)[1] in ('.h', '.c'): + EdkLogger.info("Parsing " + FullName) + model = f.endswith('c') and DataClass.MODEL_FILE_C or DataClass.MODEL_FILE_H + collector = CodeFragmentCollector.CodeFragmentCollector(FullName) + try: + collector.ParseFile() + except UnicodeError: + ParseErrorFileList.append(FullName) + collector.CleanFileProfileBuffer() + collector.ParseFileWithClearedPPDirective() +# collector.PrintFragments() + BaseName = os.path.basename(f) + DirName = os.path.dirname(FullName) + Ext = os.path.splitext(f)[1].lstrip('.') + ModifiedTime = os.path.getmtime(FullName) + FileObj = DataClass.FileClass(-1, BaseName, Ext, DirName, FullName, model, ModifiedTime, GetFunctionList(), GetIdentifierList(), []) + FileObjList.append(FileObj) + collector.CleanFileProfileBuffer() + + if len(ParseErrorFileList) > 0: + EdkLogger.info("Found unrecoverable error during parsing:\n\t%s\n" % "\n\t".join(ParseErrorFileList)) + + Db = GetDB() + for file in FileObjList: + Db.InsertOneFile(file) + + Db.UpdateIdentifierBelongsToFunction() + +def GetTableID(FullFileName, ErrorMsgList = None): + if ErrorMsgList == None: + ErrorMsgList = [] + + Db = GetDB() + SqlStatement = """ select ID + from File + where FullPath like '%s' + """ % FullFileName + + ResultSet = Db.TblFile.Exec(SqlStatement) + + FileID = -1 + for Result in ResultSet: + if FileID != -1: + ErrorMsgList.append('Duplicate file ID found in DB for file %s' % FullFileName) + return -2 + FileID = Result[0] + if FileID == -1: + ErrorMsgList.append('NO file ID found in DB for file %s' % FullFileName) + return -1 + return FileID + +def GetIncludeFileList(FullFileName): + IFList = IncludeFileListDict.get(FullFileName) + if IFList != None: + return IFList + + FileID = GetTableID(FullFileName) + if FileID < 0: + return [] + + Db = GetDB() + FileTable = 'Identifier' + str(FileID) + SqlStatement = """ select Value + from %s + where Model = %d + """ % (FileTable, DataClass.MODEL_IDENTIFIER_INCLUDE) + ResultSet = Db.TblFile.Exec(SqlStatement) + IncludeFileListDict[FullFileName] = ResultSet + return ResultSet + +def GetFullPathOfIncludeFile(Str, IncludePathList): + for IncludePath in IncludePathList: + FullPath = os.path.join(IncludePath, Str) + FullPath = os.path.normpath(FullPath) + if os.path.exists(FullPath): + return FullPath + return None + +def GetAllIncludeFiles(FullFileName): + if AllIncludeFileListDict.get(FullFileName) != None: + return AllIncludeFileListDict.get(FullFileName) + + FileDirName = os.path.dirname(FullFileName) + IncludePathList = IncludePathListDict.get(FileDirName) + if IncludePathList == None: + IncludePathList = MetaDataParser.GetIncludeListOfFile(EccGlobalData.gWorkspace, FullFileName, GetDB()) + if FileDirName not in IncludePathList: + IncludePathList.insert(0, FileDirName) + IncludePathListDict[FileDirName] = IncludePathList + IncludeFileQueue = [] + for IncludeFile in GetIncludeFileList(FullFileName): + FileName = IncludeFile[0].lstrip('#').strip() + FileName = FileName.lstrip('include').strip() + FileName = FileName.strip('\"') + FileName = FileName.lstrip('<').rstrip('>').strip() + FullPath = GetFullPathOfIncludeFile(FileName, IncludePathList) + if FullPath != None: + IncludeFileQueue.append(FullPath) + + i = 0 + while i < len(IncludeFileQueue): + for IncludeFile in GetIncludeFileList(IncludeFileQueue[i]): + FileName = IncludeFile[0].lstrip('#').strip() + FileName = FileName.lstrip('include').strip() + FileName = FileName.strip('\"') + FileName = FileName.lstrip('<').rstrip('>').strip() + FullPath = GetFullPathOfIncludeFile(FileName, IncludePathList) + if FullPath != None and FullPath not in IncludeFileQueue: + IncludeFileQueue.insert(i + 1, FullPath) + i += 1 + + AllIncludeFileListDict[FullFileName] = IncludeFileQueue + return IncludeFileQueue + +def GetPredicateListFromPredicateExpStr(PES): + + PredicateList = [] + i = 0 + PredicateBegin = 0 + #PredicateEnd = 0 + LogicOpPos = -1 + p = GetFuncDeclPattern() + while i < len(PES) - 1: + if (PES[i].isalnum() or PES[i] == '_' or PES[i] == '*') and LogicOpPos > PredicateBegin: + PredicateBegin = i + if (PES[i] == '&' and PES[i+1] == '&') or (PES[i] == '|' and PES[i+1] == '|'): + LogicOpPos = i + Exp = PES[PredicateBegin:i].strip() + # Exp may contain '.' or '->' + TmpExp = Exp.replace('.', '').replace('->', '') + if p.match(TmpExp): + PredicateList.append(Exp) + else: + PredicateList.append(Exp.rstrip(';').rstrip(')').strip()) + i += 1 + + if PredicateBegin > LogicOpPos: + while PredicateBegin < len(PES): + if PES[PredicateBegin].isalnum() or PES[PredicateBegin] == '_' or PES[PredicateBegin] == '*': + break + PredicateBegin += 1 + Exp = PES[PredicateBegin:len(PES)].strip() + # Exp may contain '.' or '->' + TmpExp = Exp.replace('.', '').replace('->', '') + if p.match(TmpExp): + PredicateList.append(Exp) + else: + PredicateList.append(Exp.rstrip(';').rstrip(')').strip()) + return PredicateList + +def GetCNameList(Lvalue, StarList = []): + Lvalue += ' ' + i = 0 + SearchBegin = 0 + VarStart = -1 + VarEnd = -1 + VarList = [] + + while SearchBegin < len(Lvalue): + while i < len(Lvalue): + if Lvalue[i].isalnum() or Lvalue[i] == '_': + if VarStart == -1: + VarStart = i + VarEnd = i + i += 1 + elif VarEnd != -1: + VarList.append(Lvalue[VarStart:VarEnd+1]) + i += 1 + break + else: + if VarStart == -1 and Lvalue[i] == '*': + StarList.append('*') + i += 1 + if VarEnd == -1: + break + + + DotIndex = Lvalue[VarEnd:].find('.') + ArrowIndex = Lvalue[VarEnd:].find('->') + if DotIndex == -1 and ArrowIndex == -1: + break + elif DotIndex == -1 and ArrowIndex != -1: + SearchBegin = VarEnd + ArrowIndex + elif ArrowIndex == -1 and DotIndex != -1: + SearchBegin = VarEnd + DotIndex + else: + SearchBegin = VarEnd + ((DotIndex < ArrowIndex) and DotIndex or ArrowIndex) + + i = SearchBegin + VarStart = -1 + VarEnd = -1 + + return VarList + +def SplitPredicateByOp(Str, Op, IsFuncCalling = False): + + Name = Str.strip() + Value = None + + if IsFuncCalling: + Index = 0 + LBFound = False + UnmatchedLBCount = 0 + while Index < len(Str): + while not LBFound and Str[Index] != '_' and not Str[Index].isalnum(): + Index += 1 + + while not LBFound and (Str[Index].isalnum() or Str[Index] == '_'): + Index += 1 + # maybe type-cast at the begining, skip it. + RemainingStr = Str[Index:].lstrip() + if RemainingStr.startswith(')') and not LBFound: + Index += 1 + continue + + if RemainingStr.startswith('(') and not LBFound: + LBFound = True + + if Str[Index] == '(': + UnmatchedLBCount += 1 + Index += 1 + continue + + if Str[Index] == ')': + UnmatchedLBCount -= 1 + Index += 1 + if UnmatchedLBCount == 0: + break + continue + + Index += 1 + + if UnmatchedLBCount > 0: + return [Name] + + IndexInRemainingStr = Str[Index:].find(Op) + if IndexInRemainingStr == -1: + return [Name] + + Name = Str[0:Index + IndexInRemainingStr].strip() + Value = Str[Index+IndexInRemainingStr+len(Op):].strip() + return [Name, Value] + + TmpStr = Str.rstrip(';').rstrip(')') + while True: + Index = TmpStr.rfind(Op) + if Index == -1: + return [Name] + + if Str[Index - 1].isalnum() or Str[Index - 1].isspace() or Str[Index - 1] == ')': + Name = Str[0:Index].strip() + Value = Str[Index + len(Op):].strip() + return [Name, Value] + + TmpStr = Str[0:Index - 1] + +def SplitPredicateStr(Str): + IsFuncCalling = False + p = GetFuncDeclPattern() + TmpStr = Str.replace('.', '').replace('->', '') + if p.match(TmpStr): + IsFuncCalling = True + + PredPartList = SplitPredicateByOp(Str, '==', IsFuncCalling) + if len(PredPartList) > 1: + return [PredPartList, '=='] + + PredPartList = SplitPredicateByOp(Str, '!=', IsFuncCalling) + if len(PredPartList) > 1: + return [PredPartList, '!='] + + PredPartList = SplitPredicateByOp(Str, '>=', IsFuncCalling) + if len(PredPartList) > 1: + return [PredPartList, '>='] + + PredPartList = SplitPredicateByOp(Str, '<=', IsFuncCalling) + if len(PredPartList) > 1: + return [PredPartList, '<='] + + PredPartList = SplitPredicateByOp(Str, '>', IsFuncCalling) + if len(PredPartList) > 1: + return [PredPartList, '>'] + + PredPartList = SplitPredicateByOp(Str, '<', IsFuncCalling) + if len(PredPartList) > 1: + return [PredPartList, '<'] + + return [[Str, None], None] + +def GetFuncContainsPE(ExpLine, ResultSet): + for Result in ResultSet: + if Result[0] < ExpLine and Result[1] > ExpLine: + return Result + return None + +def PatternInModifier(Modifier, SubStr): + PartList = Modifier.split() + for Part in PartList: + if Part == SubStr: + return True + return False + +def GetDataTypeFromModifier(ModifierStr): + MList = ModifierStr.split() + for M in MList: + if M in EccGlobalData.gConfig.ModifierList: + MList.remove(M) + # remove array sufix + if M.startswith('['): + MList.remove(M) + + ReturnType = '' + for M in MList: + ReturnType += M + ' ' + + ReturnType = ReturnType.strip() + if len(ReturnType) == 0: + ReturnType = 'VOID' + return ReturnType + +def DiffModifier(Str1, Str2): + PartList1 = Str1.split() + PartList2 = Str2.split() + if PartList1 == PartList2: + return False + else: + return True + +def GetTypedefDict(FullFileName): + + Dict = ComplexTypeDict.get(FullFileName) + if Dict != None: + return Dict + + FileID = GetTableID(FullFileName) + FileTable = 'Identifier' + str(FileID) + Db = GetDB() + SqlStatement = """ select Modifier, Name, Value, ID + from %s + where Model = %d + """ % (FileTable, DataClass.MODEL_IDENTIFIER_TYPEDEF) + ResultSet = Db.TblFile.Exec(SqlStatement) + + Dict = {} + for Result in ResultSet: + if len(Result[0]) == 0: + Dict[Result[1]] = Result[2] + + IncludeFileList = GetAllIncludeFiles(FullFileName) + for F in IncludeFileList: + FileID = GetTableID(F) + if FileID < 0: + continue + + FileTable = 'Identifier' + str(FileID) + SqlStatement = """ select Modifier, Name, Value, ID + from %s + where Model = %d + """ % (FileTable, DataClass.MODEL_IDENTIFIER_TYPEDEF) + ResultSet = Db.TblFile.Exec(SqlStatement) + + for Result in ResultSet: + if not Result[2].startswith('FP ('): + Dict[Result[1]] = Result[2] + else: + if len(Result[0]) == 0: + Dict[Result[1]] = 'VOID' + else: + Dict[Result[1]] = GetDataTypeFromModifier(Result[0]) + + ComplexTypeDict[FullFileName] = Dict + return Dict + +def GetSUDict(FullFileName): + + Dict = SUDict.get(FullFileName) + if Dict != None: + return Dict + + FileID = GetTableID(FullFileName) + FileTable = 'Identifier' + str(FileID) + Db = GetDB() + SqlStatement = """ select Name, Value, ID + from %s + where Model = %d or Model = %d + """ % (FileTable, DataClass.MODEL_IDENTIFIER_STRUCTURE, DataClass.MODEL_IDENTIFIER_UNION) + ResultSet = Db.TblFile.Exec(SqlStatement) + + Dict = {} + for Result in ResultSet: + if len(Result[1]) > 0: + Dict[Result[0]] = Result[1] + + IncludeFileList = GetAllIncludeFiles(FullFileName) + for F in IncludeFileList: + FileID = GetTableID(F) + if FileID < 0: + continue + + FileTable = 'Identifier' + str(FileID) + SqlStatement = """ select Name, Value, ID + from %s + where Model = %d or Model = %d + """ % (FileTable, DataClass.MODEL_IDENTIFIER_STRUCTURE, DataClass.MODEL_IDENTIFIER_UNION) + ResultSet = Db.TblFile.Exec(SqlStatement) + + for Result in ResultSet: + if len(Result[1]) > 0: + Dict[Result[0]] = Result[1] + + SUDict[FullFileName] = Dict + return Dict + +def StripComments(Str): + Str += ' ' + ListFromStr = list(Str) + + InComment = False + DoubleSlashComment = False + Index = 0 + while Index < len(ListFromStr): + # meet new line, then no longer in a comment for // + if ListFromStr[Index] == '\n': + if InComment and DoubleSlashComment: + InComment = False + DoubleSlashComment = False + Index += 1 + # check for */ comment end + elif InComment and not DoubleSlashComment and ListFromStr[Index] == '*' and ListFromStr[Index+1] == '/': + ListFromStr[Index] = ' ' + Index += 1 + ListFromStr[Index] = ' ' + Index += 1 + InComment = False + # set comments to spaces + elif InComment: + ListFromStr[Index] = ' ' + Index += 1 + # check for // comment + elif ListFromStr[Index] == '/' and ListFromStr[Index+1] == '/' and ListFromStr[Index+2] != '\n': + InComment = True + DoubleSlashComment = True + + # check for /* comment start + elif ListFromStr[Index] == '/' and ListFromStr[Index+1] == '*': + ListFromStr[Index] = ' ' + Index += 1 + ListFromStr[Index] = ' ' + Index += 1 + InComment = True + else: + Index += 1 + + # restore from List to String + Str = "".join(ListFromStr) + Str = Str.rstrip(' ') + + return Str + +def GetFinalTypeValue(Type, FieldName, TypedefDict, SUDict): + Value = TypedefDict.get(Type) + if Value == None: + Value = SUDict.get(Type) + if Value == None: + return None + + LBPos = Value.find('{') + while LBPos == -1: + FTList = Value.split() + for FT in FTList: + if FT not in ('struct', 'union'): + Value = TypedefDict.get(FT) + if Value == None: + Value = SUDict.get(FT) + break + + if Value == None: + return None + + LBPos = Value.find('{') + +# RBPos = Value.find('}') + Fields = Value[LBPos + 1:] + Fields = StripComments(Fields) + FieldsList = Fields.split(';') + for Field in FieldsList: + Field = Field.strip() + Index = Field.rfind(FieldName) + if Index < 1: + continue + if not Field[Index - 1].isalnum(): + if Index + len(FieldName) == len(Field): + Type = GetDataTypeFromModifier(Field[0:Index]) + return Type.strip() + else: + # For the condition that the field in struct is an array with [] sufixes... + if not Field[Index + len(FieldName)].isalnum(): + Type = GetDataTypeFromModifier(Field[0:Index]) + return Type.strip() + + return None + +def GetRealType(Type, TypedefDict, TargetType = None): + if TargetType != None and Type == TargetType: + return Type + while TypedefDict.get(Type): + Type = TypedefDict.get(Type) + if TargetType != None and Type == TargetType: + return Type + return Type + +def GetTypeInfo(RefList, Modifier, FullFileName, TargetType = None): + TypedefDict = GetTypedefDict(FullFileName) + SUDict = GetSUDict(FullFileName) + Type = GetDataTypeFromModifier(Modifier).replace('*', '').strip() + + Type = Type.split()[-1] + Index = 0 + while Index < len(RefList): + FieldName = RefList[Index] + FromType = GetFinalTypeValue(Type, FieldName, TypedefDict, SUDict) + if FromType == None: + return None + # we want to determine the exact type. + if TargetType != None: + Type = FromType.split()[0] + # we only want to check if it is a pointer + else: + Type = FromType + if Type.find('*') != -1 and Index == len(RefList)-1: + return Type + Type = FromType.split()[0] + + Index += 1 + + Type = GetRealType(Type, TypedefDict, TargetType) + + return Type + +def GetVarInfo(PredVarList, FuncRecord, FullFileName, IsFuncCall = False, TargetType = None, StarList = None): + + PredVar = PredVarList[0] + FileID = GetTableID(FullFileName) + + Db = GetDB() + FileTable = 'Identifier' + str(FileID) + # search variable in include files + + # it is a function call, search function declarations and definitions + if IsFuncCall: + SqlStatement = """ select Modifier, ID + from %s + where Model = %d and Value = \'%s\' + """ % (FileTable, DataClass.MODEL_IDENTIFIER_FUNCTION_DECLARATION, PredVar) + ResultSet = Db.TblFile.Exec(SqlStatement) + + for Result in ResultSet: + Type = GetDataTypeFromModifier(Result[0]).split()[-1] + TypedefDict = GetTypedefDict(FullFileName) + Type = GetRealType(Type, TypedefDict, TargetType) + return Type + + IncludeFileList = GetAllIncludeFiles(FullFileName) + for F in IncludeFileList: + FileID = GetTableID(F) + if FileID < 0: + continue + + FileTable = 'Identifier' + str(FileID) + SqlStatement = """ select Modifier, ID + from %s + where Model = %d and Value = \'%s\' + """ % (FileTable, DataClass.MODEL_IDENTIFIER_FUNCTION_DECLARATION, PredVar) + ResultSet = Db.TblFile.Exec(SqlStatement) + + for Result in ResultSet: + Type = GetDataTypeFromModifier(Result[0]).split()[-1] + TypedefDict = GetTypedefDict(FullFileName) + Type = GetRealType(Type, TypedefDict, TargetType) + return Type + + FileID = GetTableID(FullFileName) + SqlStatement = """ select Modifier, ID + from Function + where BelongsToFile = %d and Name = \'%s\' + """ % (FileID, PredVar) + ResultSet = Db.TblFile.Exec(SqlStatement) + + for Result in ResultSet: + Type = GetDataTypeFromModifier(Result[0]).split()[-1] + TypedefDict = GetTypedefDict(FullFileName) + Type = GetRealType(Type, TypedefDict, TargetType) + return Type + + for F in IncludeFileList: + FileID = GetTableID(F) + if FileID < 0: + continue + + FileTable = 'Identifier' + str(FileID) + SqlStatement = """ select Modifier, ID + from Function + where BelongsToFile = %d and Name = \'%s\' + """ % (FileID, PredVar) + ResultSet = Db.TblFile.Exec(SqlStatement) + + for Result in ResultSet: + Type = GetDataTypeFromModifier(Result[0]).split()[-1] + TypedefDict = GetTypedefDict(FullFileName) + Type = GetRealType(Type, TypedefDict, TargetType) + return Type + + return None + + # really variable, search local variable first + SqlStatement = """ select Modifier, ID + from %s + where Model = %d and Name = \'%s\' and StartLine >= %d and StartLine <= %d + """ % (FileTable, DataClass.MODEL_IDENTIFIER_VARIABLE, PredVar, FuncRecord[0], FuncRecord[1]) + ResultSet = Db.TblFile.Exec(SqlStatement) + VarFound = False + for Result in ResultSet: + if len(PredVarList) > 1: + Type = GetTypeInfo(PredVarList[1:], Result[0], FullFileName, TargetType) + return Type + else: +# Type = GetDataTypeFromModifier(Result[0]).split()[-1] + TypeList = GetDataTypeFromModifier(Result[0]).split() + Type = TypeList[-1] + if len(TypeList) > 1 and StarList != None: + for Star in StarList: + Type = Type.strip() + Type = Type.rstrip(Star) + # Get real type after de-reference pointers. + if len(Type.strip()) == 0: + Type = TypeList[-2] + TypedefDict = GetTypedefDict(FullFileName) + Type = GetRealType(Type, TypedefDict, TargetType) + return Type + + # search function parameters second + ParamList = GetParamList(FuncRecord[2]) + for Param in ParamList: + if Param.Name.strip() == PredVar: + if len(PredVarList) > 1: + Type = GetTypeInfo(PredVarList[1:], Param.Modifier, FullFileName, TargetType) + return Type + else: + TypeList = GetDataTypeFromModifier(Param.Modifier).split() + Type = TypeList[-1] + if len(TypeList) > 1 and StarList != None: + for Star in StarList: + Type = Type.strip() + Type = Type.rstrip(Star) + # Get real type after de-reference pointers. + if len(Type.strip()) == 0: + Type = TypeList[-2] + TypedefDict = GetTypedefDict(FullFileName) + Type = GetRealType(Type, TypedefDict, TargetType) + return Type + + # search global variable next + SqlStatement = """ select Modifier, ID + from %s + where Model = %d and Name = \'%s\' and BelongsToFunction = -1 + """ % (FileTable, DataClass.MODEL_IDENTIFIER_VARIABLE, PredVar) + ResultSet = Db.TblFile.Exec(SqlStatement) + + for Result in ResultSet: + if len(PredVarList) > 1: + Type = GetTypeInfo(PredVarList[1:], Result[0], FullFileName, TargetType) + return Type + else: + TypeList = GetDataTypeFromModifier(Result[0]).split() + Type = TypeList[-1] + if len(TypeList) > 1 and StarList != None: + for Star in StarList: + Type = Type.strip() + Type = Type.rstrip(Star) + # Get real type after de-reference pointers. + if len(Type.strip()) == 0: + Type = TypeList[-2] + TypedefDict = GetTypedefDict(FullFileName) + Type = GetRealType(Type, TypedefDict, TargetType) + return Type + + IncludeFileList = GetAllIncludeFiles(FullFileName) + for F in IncludeFileList: + FileID = GetTableID(F) + if FileID < 0: + continue + + FileTable = 'Identifier' + str(FileID) + SqlStatement = """ select Modifier, ID + from %s + where Model = %d and BelongsToFunction = -1 and Name = \'%s\' + """ % (FileTable, DataClass.MODEL_IDENTIFIER_VARIABLE, PredVar) + ResultSet = Db.TblFile.Exec(SqlStatement) + + for Result in ResultSet: + if len(PredVarList) > 1: + Type = GetTypeInfo(PredVarList[1:], Result[0], FullFileName, TargetType) + return Type + else: + TypeList = GetDataTypeFromModifier(Result[0]).split() + Type = TypeList[-1] + if len(TypeList) > 1 and StarList != None: + for Star in StarList: + Type = Type.strip() + Type = Type.rstrip(Star) + # Get real type after de-reference pointers. + if len(Type.strip()) == 0: + Type = TypeList[-2] + TypedefDict = GetTypedefDict(FullFileName) + Type = GetRealType(Type, TypedefDict, TargetType) + return Type + +def CheckFuncLayoutReturnType(FullFileName): + ErrorMsgList = [] + + FileID = GetTableID(FullFileName, ErrorMsgList) + if FileID < 0: + return ErrorMsgList + + Db = GetDB() + FileTable = 'Identifier' + str(FileID) + SqlStatement = """ select Modifier, ID, StartLine, StartColumn, EndLine, Value + from %s + where Model = %d + """ % (FileTable, DataClass.MODEL_IDENTIFIER_FUNCTION_DECLARATION) + ResultSet = Db.TblFile.Exec(SqlStatement) + for Result in ResultSet: + ReturnType = GetDataTypeFromModifier(Result[0]) + TypeStart = ReturnType.split()[0] + FuncName = Result[5] + if EccGlobalData.gException.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_RETURN_TYPE, FuncName): + continue + Index = Result[0].find(TypeStart) + if Index != 0 or Result[3] != 0: + PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_RETURN_TYPE, '[%s] Return Type should appear at the start of line' % FuncName, FileTable, Result[1]) + + if Result[2] == Result[4]: + PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_RETURN_TYPE, '[%s] Return Type should appear on its own line' % FuncName, FileTable, Result[1]) + + SqlStatement = """ select Modifier, ID, StartLine, StartColumn, FunNameStartLine, Name + from Function + where BelongsToFile = %d + """ % (FileID) + ResultSet = Db.TblFile.Exec(SqlStatement) + for Result in ResultSet: + ReturnType = GetDataTypeFromModifier(Result[0]) + TypeStart = ReturnType.split()[0] + FuncName = Result[5] + if EccGlobalData.gException.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_RETURN_TYPE, FuncName): + continue + Index = Result[0].find(ReturnType) + if Index != 0 or Result[3] != 0: + PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_RETURN_TYPE, '[%s] Return Type should appear at the start of line' % FuncName, 'Function', Result[1]) + + if Result[2] == Result[4]: + PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_RETURN_TYPE, '[%s] Return Type should appear on its own line' % FuncName, 'Function', Result[1]) + +def CheckFuncLayoutModifier(FullFileName): + ErrorMsgList = [] + + FileID = GetTableID(FullFileName, ErrorMsgList) + if FileID < 0: + return ErrorMsgList + + Db = GetDB() + FileTable = 'Identifier' + str(FileID) + SqlStatement = """ select Modifier, ID + from %s + where Model = %d + """ % (FileTable, DataClass.MODEL_IDENTIFIER_FUNCTION_DECLARATION) + ResultSet = Db.TblFile.Exec(SqlStatement) + for Result in ResultSet: + ReturnType = GetDataTypeFromModifier(Result[0]) + TypeStart = ReturnType.split()[0] +# if len(ReturnType) == 0: +# continue + Index = Result[0].find(TypeStart) + if Index != 0: + PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_OPTIONAL_FUNCTIONAL_MODIFIER, '', FileTable, Result[1]) + + SqlStatement = """ select Modifier, ID + from Function + where BelongsToFile = %d + """ % (FileID) + ResultSet = Db.TblFile.Exec(SqlStatement) + for Result in ResultSet: + ReturnType = GetDataTypeFromModifier(Result[0]) + TypeStart = ReturnType.split()[0] +# if len(ReturnType) == 0: +# continue + Index = Result[0].find(TypeStart) + if Index != 0: + PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_OPTIONAL_FUNCTIONAL_MODIFIER, '', 'Function', Result[1]) + +def CheckFuncLayoutName(FullFileName): + ErrorMsgList = [] + # Parameter variable format pattern. + Pattern = re.compile(r'^[A-Z]+\S*[a-z]\S*$') + ParamIgnoreList = ('VOID', '...') + FileID = GetTableID(FullFileName, ErrorMsgList) + if FileID < 0: + return ErrorMsgList + + Db = GetDB() + FileTable = 'Identifier' + str(FileID) + SqlStatement = """ select Name, ID, EndColumn, Value + from %s + where Model = %d + """ % (FileTable, DataClass.MODEL_IDENTIFIER_FUNCTION_DECLARATION) + ResultSet = Db.TblFile.Exec(SqlStatement) + for Result in ResultSet: + FuncName = Result[3] + if EccGlobalData.gException.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME, FuncName): + continue + if Result[2] != 0: + PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME, 'Function name [%s] should appear at the start of a line' % FuncName, FileTable, Result[1]) + ParamList = GetParamList(Result[0]) + if len(ParamList) == 0: + continue + StartLine = 0 + for Param in ParamList: + if Param.StartLine <= StartLine: + PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME, 'Parameter %s should be in its own line.' % Param.Name, FileTable, Result[1]) + if Param.StartLine - StartLine > 1: + PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME, 'Empty line appears before Parameter %s.' % Param.Name, FileTable, Result[1]) + if not Pattern.match(Param.Name) and not Param.Name in ParamIgnoreList and not EccGlobalData.gException.IsException(ERROR_NAMING_CONVENTION_CHECK_VARIABLE_NAME, Param.Name): + PrintErrorMsg(ERROR_NAMING_CONVENTION_CHECK_VARIABLE_NAME, 'Parameter [%s] NOT follow naming convention.' % Param.Name, FileTable, Result[1]) + StartLine = Param.StartLine + + if not Result[0].endswith('\n )') and not Result[0].endswith('\r )'): + PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME, '\')\' should be on a new line and indented two spaces', FileTable, Result[1]) + + SqlStatement = """ select Modifier, ID, FunNameStartColumn, Name + from Function + where BelongsToFile = %d + """ % (FileID) + ResultSet = Db.TblFile.Exec(SqlStatement) + for Result in ResultSet: + FuncName = Result[3] + if EccGlobalData.gException.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME, FuncName): + continue + if Result[2] != 0: + PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME, 'Function name [%s] should appear at the start of a line' % FuncName, 'Function', Result[1]) + ParamList = GetParamList(Result[0]) + if len(ParamList) == 0: + continue + StartLine = 0 + for Param in ParamList: + if Param.StartLine <= StartLine: + PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME, 'Parameter %s should be in its own line.' % Param.Name, 'Function', Result[1]) + if Param.StartLine - StartLine > 1: + PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME, 'Empty line appears before Parameter %s.' % Param.Name, 'Function', Result[1]) + if not Pattern.match(Param.Name) and not Param.Name in ParamIgnoreList and not EccGlobalData.gException.IsException(ERROR_NAMING_CONVENTION_CHECK_VARIABLE_NAME, Param.Name): + PrintErrorMsg(ERROR_NAMING_CONVENTION_CHECK_VARIABLE_NAME, 'Parameter [%s] NOT follow naming convention.' % Param.Name, FileTable, Result[1]) + StartLine = Param.StartLine + if not Result[0].endswith('\n )') and not Result[0].endswith('\r )'): + PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME, '\')\' should be on a new line and indented two spaces', 'Function', Result[1]) + +def CheckFuncLayoutPrototype(FullFileName): + ErrorMsgList = [] + + FileID = GetTableID(FullFileName, ErrorMsgList) + if FileID < 0: + return ErrorMsgList + + FileTable = 'Identifier' + str(FileID) + Db = GetDB() + SqlStatement = """ select Modifier, Header, Name, ID + from Function + where BelongsToFile = %d + """ % (FileID) + ResultSet = Db.TblFile.Exec(SqlStatement) + if len(ResultSet) == 0: + return ErrorMsgList + + FuncDefList = [] + for Result in ResultSet: + FuncDefList.append(Result) + + SqlStatement = """ select Modifier, Name, ID + from %s + where Model = %d + """ % (FileTable, DataClass.MODEL_IDENTIFIER_FUNCTION_DECLARATION) + ResultSet = Db.TblFile.Exec(SqlStatement) + FuncDeclList = [] + for Result in ResultSet: + FuncDeclList.append(Result) + + UndeclFuncList = [] + for FuncDef in FuncDefList: + FuncName = FuncDef[2].strip() + FuncModifier = FuncDef[0] + FuncDefHeader = FuncDef[1] + for FuncDecl in FuncDeclList: + LBPos = FuncDecl[1].find('(') + DeclName = FuncDecl[1][0:LBPos].strip() + DeclModifier = FuncDecl[0] + if DeclName == FuncName: + if DiffModifier(FuncModifier, DeclModifier) and not EccGlobalData.gException.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE, FuncName): + PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE, 'Function [%s] modifier different with prototype.' % FuncName, 'Function', FuncDef[3]) + ParamListOfDef = GetParamList(FuncDefHeader) + ParamListOfDecl = GetParamList(FuncDecl[1]) + if len(ParamListOfDef) != len(ParamListOfDecl): + PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE, 'Parameter number different.', 'Function', FuncDef[3]) + break + + Index = 0 + while Index < len(ParamListOfDef): + if DiffModifier(ParamListOfDef[Index].Modifier, ParamListOfDecl[Index].Modifier): + PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE, 'Parameter %s has different modifier with prototype.' % ParamListOfDef[Index].Name, 'Function', FuncDef[3]) + Index += 1 + break + else: + UndeclFuncList.append(FuncDef) + + IncludeFileList = GetAllIncludeFiles(FullFileName) + FuncDeclList = [] + for F in IncludeFileList: + FileID = GetTableID(F, ErrorMsgList) + if FileID < 0: + continue + + FileTable = 'Identifier' + str(FileID) + SqlStatement = """ select Modifier, Name, ID + from %s + where Model = %d + """ % (FileTable, DataClass.MODEL_IDENTIFIER_FUNCTION_DECLARATION) + ResultSet = Db.TblFile.Exec(SqlStatement) + + for Result in ResultSet: + FuncDeclList.append(Result) + + for FuncDef in UndeclFuncList: + FuncName = FuncDef[2].strip() + FuncModifier = FuncDef[0] + FuncDefHeader = FuncDef[1] + for FuncDecl in FuncDeclList: + LBPos = FuncDecl[1].find('(') + DeclName = FuncDecl[1][0:LBPos].strip() + DeclModifier = FuncDecl[0] + if DeclName == FuncName: + if DiffModifier(FuncModifier, DeclModifier) and not EccGlobalData.gException.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE, FuncName): + PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE, 'Function [%s] modifier different with prototype.' % FuncName, 'Function', FuncDef[3]) + ParamListOfDef = GetParamList(FuncDefHeader) + ParamListOfDecl = GetParamList(FuncDecl[1]) + if len(ParamListOfDef) != len(ParamListOfDecl): + PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE, 'Parameter number different.', 'Function', FuncDef[3]) + break + + Index = 0 + while Index < len(ParamListOfDef): + if DiffModifier(ParamListOfDef[Index].Modifier, ParamListOfDecl[Index].Modifier): + PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE, 'Parameter %s has different modifier with prototype.' % ParamListOfDef[Index].Name, 'Function', FuncDef[3]) + Index += 1 + break + +def CheckFuncLayoutBody(FullFileName): + ErrorMsgList = [] + + FileID = GetTableID(FullFileName, ErrorMsgList) + if FileID < 0: + return ErrorMsgList + + FileTable = 'Identifier' + str(FileID) + Db = GetDB() + SqlStatement = """ select BodyStartColumn, EndColumn, ID + from Function + where BelongsToFile = %d + """ % (FileID) + ResultSet = Db.TblFile.Exec(SqlStatement) + if len(ResultSet) == 0: + return ErrorMsgList + for Result in ResultSet: + if Result[0] != 0: + PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_BODY, 'open brace should be at the very beginning of a line.', 'Function', Result[2]) + if Result[1] != 0: + PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_BODY, 'close brace should be at the very beginning of a line.', 'Function', Result[2]) + +def CheckFuncLayoutLocalVariable(FullFileName): + ErrorMsgList = [] + + FileID = GetTableID(FullFileName, ErrorMsgList) + if FileID < 0: + return ErrorMsgList + + Db = GetDB() + FileTable = 'Identifier' + str(FileID) + SqlStatement = """ select ID + from Function + where BelongsToFile = %d + """ % (FileID) + ResultSet = Db.TblFile.Exec(SqlStatement) + if len(ResultSet) == 0: + return ErrorMsgList + FL = [] + for Result in ResultSet: + FL.append(Result) + + for F in FL: + SqlStatement = """ select Name, Value, ID + from %s + where Model = %d and BelongsToFunction = %d + """ % (FileTable, DataClass.MODEL_IDENTIFIER_VARIABLE, F[0]) + ResultSet = Db.TblFile.Exec(SqlStatement) + if len(ResultSet) == 0: + continue + + for Result in ResultSet: + if len(Result[1]) > 0: + PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_NO_INIT_OF_VARIABLE, 'Variable Name: %s' % Result[0], FileTable, Result[2]) + +def CheckMemberVariableFormat(Name, Value, FileTable, TdId, ModelId): + ErrMsgList = [] + # Member variable format pattern. + Pattern = re.compile(r'^[A-Z]+\S*[a-z]\S*$') + + LBPos = Value.find('{') + RBPos = Value.rfind('}') + if LBPos == -1 or RBPos == -1: + return ErrMsgList + + Fields = Value[LBPos + 1 : RBPos] + Fields = StripComments(Fields).strip() + NestPos = Fields.find ('struct') + if NestPos != -1 and (NestPos + len('struct') < len(Fields)): + if not Fields[NestPos + len('struct') + 1].isalnum(): + if not EccGlobalData.gException.IsException(ERROR_DECLARATION_DATA_TYPE_CHECK_NESTED_STRUCTURE, Name): + PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NESTED_STRUCTURE, 'Nested struct in [%s].' % (Name), FileTable, TdId) + return ErrMsgList + NestPos = Fields.find ('union') + if NestPos != -1 and (NestPos + len('union') < len(Fields)): + if not Fields[NestPos + len('union') + 1].isalnum(): + if not EccGlobalData.gException.IsException(ERROR_DECLARATION_DATA_TYPE_CHECK_NESTED_STRUCTURE, Name): + PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NESTED_STRUCTURE, 'Nested union in [%s].' % (Name), FileTable, TdId) + return ErrMsgList + NestPos = Fields.find ('enum') + if NestPos != -1 and (NestPos + len('enum') < len(Fields)): + if not Fields[NestPos + len('enum') + 1].isalnum(): + if not EccGlobalData.gException.IsException(ERROR_DECLARATION_DATA_TYPE_CHECK_NESTED_STRUCTURE, Name): + PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NESTED_STRUCTURE, 'Nested enum in [%s].' % (Name), FileTable, TdId) + return ErrMsgList + + if ModelId == DataClass.MODEL_IDENTIFIER_ENUMERATE: + FieldsList = Fields.split(',') + # deal with enum is pre-assigned a value by function call ( , , , ...) + QuoteCount = 0 + Index = 0 + RemoveCurrentElement = False + while Index < len(FieldsList): + Field = FieldsList[Index] + + if Field.find('(') != -1: + QuoteCount += 1 + RemoveCurrentElement = True + Index += 1 + continue + + if Field.find(')') != -1 and QuoteCount > 0: + QuoteCount -= 1 + + if RemoveCurrentElement: + FieldsList.remove(Field) + if QuoteCount == 0: + RemoveCurrentElement = False + continue + + if QuoteCount == 0: + RemoveCurrentElement = False + + Index += 1 + else: + FieldsList = Fields.split(';') + + for Field in FieldsList: + Field = Field.strip() + if Field == '': + continue + # For the condition that the field in struct is an array with [] sufixes... + if Field[-1] == ']': + LBPos = Field.find('[') + Field = Field[0:LBPos] + # For the condition that bit field ": Number" + if Field.find(':') != -1: + ColonPos = Field.find(':') + Field = Field[0:ColonPos] + + Field = Field.strip() + if Field == '': + continue + # Enum could directly assign value to variable + Field = Field.split('=')[0].strip() + TokenList = Field.split() + # Remove pointers before variable + if not Pattern.match(TokenList[-1].lstrip('*')): + ErrMsgList.append(TokenList[-1].lstrip('*')) + + return ErrMsgList + +def CheckDeclTypedefFormat(FullFileName, ModelId): + ErrorMsgList = [] + + FileID = GetTableID(FullFileName, ErrorMsgList) + if FileID < 0: + return ErrorMsgList + + Db = GetDB() + FileTable = 'Identifier' + str(FileID) + SqlStatement = """ select Name, StartLine, EndLine, ID, Value + from %s + where Model = %d + """ % (FileTable, ModelId) + ResultSet = Db.TblFile.Exec(SqlStatement) + ResultList = [] + for Result in ResultSet: + ResultList.append(Result) + + ErrorType = ERROR_DECLARATION_DATA_TYPE_CHECK_ALL + if ModelId == DataClass.MODEL_IDENTIFIER_STRUCTURE: + ErrorType = ERROR_DECLARATION_DATA_TYPE_CHECK_STRUCTURE_DECLARATION + elif ModelId == DataClass.MODEL_IDENTIFIER_ENUMERATE: + ErrorType = ERROR_DECLARATION_DATA_TYPE_CHECK_ENUMERATED_TYPE + elif ModelId == DataClass.MODEL_IDENTIFIER_UNION: + ErrorType = ERROR_DECLARATION_DATA_TYPE_CHECK_UNION_TYPE + + SqlStatement = """ select Modifier, Name, Value, StartLine, EndLine, ID + from %s + where Model = %d + """ % (FileTable, DataClass.MODEL_IDENTIFIER_TYPEDEF) + TdSet = Db.TblFile.Exec(SqlStatement) + TdList = [] + for Td in TdSet: + TdList.append(Td) + # Check member variable name format that from typedefs of ONLY this file. + for Td in TdList: + Name = Td[1].strip() + Value = Td[2].strip() + if Value.startswith('enum'): + ValueModelId = DataClass.MODEL_IDENTIFIER_ENUMERATE + elif Value.startswith('struct'): + ValueModelId = DataClass.MODEL_IDENTIFIER_STRUCTURE + elif Value.startswith('union'): + ValueModelId = DataClass.MODEL_IDENTIFIER_UNION + else: + continue + + if ValueModelId != ModelId: + continue + # Check member variable format. + ErrMsgList = CheckMemberVariableFormat(Name, Value, FileTable, Td[5], ModelId) + for ErrMsg in ErrMsgList: + if EccGlobalData.gException.IsException(ERROR_NAMING_CONVENTION_CHECK_VARIABLE_NAME, Name+'.'+ErrMsg): + continue + PrintErrorMsg(ERROR_NAMING_CONVENTION_CHECK_VARIABLE_NAME, 'Member variable [%s] NOT follow naming convention.' % (Name+'.'+ErrMsg), FileTable, Td[5]) + + # First check in current file to see whether struct/union/enum is typedef-ed. + UntypedefedList = [] + for Result in ResultList: + # Check member variable format. + Name = Result[0].strip() + Value = Result[4].strip() + if Value.startswith('enum'): + ValueModelId = DataClass.MODEL_IDENTIFIER_ENUMERATE + elif Value.startswith('struct'): + ValueModelId = DataClass.MODEL_IDENTIFIER_STRUCTURE + elif Value.startswith('union'): + ValueModelId = DataClass.MODEL_IDENTIFIER_UNION + else: + continue + + if ValueModelId != ModelId: + continue + ErrMsgList = CheckMemberVariableFormat(Name, Value, FileTable, Result[3], ModelId) + for ErrMsg in ErrMsgList: + if EccGlobalData.gException.IsException(ERROR_NAMING_CONVENTION_CHECK_VARIABLE_NAME, Result[0]+'.'+ErrMsg): + continue + PrintErrorMsg(ERROR_NAMING_CONVENTION_CHECK_VARIABLE_NAME, 'Member variable [%s] NOT follow naming convention.' % (Result[0]+'.'+ErrMsg), FileTable, Result[3]) + # Check whether it is typedefed. + Found = False + for Td in TdList: + # skip function pointer + if len(Td[0]) > 0: + continue + if Result[1] >= Td[3] and Td[4] >= Result[2]: + Found = True + if not Td[1].isupper(): + PrintErrorMsg(ErrorType, 'Typedef should be UPPER case', FileTable, Td[5]) + if Result[0] in Td[2].split(): + Found = True + if not Td[1].isupper(): + PrintErrorMsg(ErrorType, 'Typedef should be UPPER case', FileTable, Td[5]) + if Found: + break + + if not Found: + UntypedefedList.append(Result) + continue + + if len(UntypedefedList) == 0: + return + + IncludeFileList = GetAllIncludeFiles(FullFileName) + TdList = [] + for F in IncludeFileList: + FileID = GetTableID(F, ErrorMsgList) + if FileID < 0: + continue + + IncludeFileTable = 'Identifier' + str(FileID) + SqlStatement = """ select Modifier, Name, Value, StartLine, EndLine, ID + from %s + where Model = %d + """ % (IncludeFileTable, DataClass.MODEL_IDENTIFIER_TYPEDEF) + ResultSet = Db.TblFile.Exec(SqlStatement) + TdList.extend(ResultSet) + + for Result in UntypedefedList: + + # Check whether it is typedefed. + Found = False + for Td in TdList: + + if len(Td[0]) > 0: + continue + if Result[1] >= Td[3] and Td[4] >= Result[2]: + Found = True + if not Td[1].isupper(): + PrintErrorMsg(ErrorType, 'Typedef should be UPPER case', FileTable, Td[5]) + if Result[0] in Td[2].split(): + Found = True + if not Td[1].isupper(): + PrintErrorMsg(ErrorType, 'Typedef should be UPPER case', FileTable, Td[5]) + if Found: + break + + if not Found: + PrintErrorMsg(ErrorType, 'No Typedef for %s' % Result[0], FileTable, Result[3]) + continue + +def CheckDeclStructTypedef(FullFileName): + CheckDeclTypedefFormat(FullFileName, DataClass.MODEL_IDENTIFIER_STRUCTURE) + +def CheckDeclEnumTypedef(FullFileName): + CheckDeclTypedefFormat(FullFileName, DataClass.MODEL_IDENTIFIER_ENUMERATE) + +def CheckDeclUnionTypedef(FullFileName): + CheckDeclTypedefFormat(FullFileName, DataClass.MODEL_IDENTIFIER_UNION) + +def CheckDeclArgModifier(FullFileName): + ErrorMsgList = [] + + FileID = GetTableID(FullFileName, ErrorMsgList) + if FileID < 0: + return ErrorMsgList + + Db = GetDB() + FileTable = 'Identifier' + str(FileID) + SqlStatement = """ select Modifier, Name, ID + from %s + where Model = %d + """ % (FileTable, DataClass.MODEL_IDENTIFIER_VARIABLE) + ResultSet = Db.TblFile.Exec(SqlStatement) + ModifierTuple = ('IN', 'OUT', 'OPTIONAL', 'UNALIGNED') + MAX_MODIFIER_LENGTH = 100 + for Result in ResultSet: + for Modifier in ModifierTuple: + if PatternInModifier(Result[0], Modifier) and len(Result[0]) < MAX_MODIFIER_LENGTH: + PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_IN_OUT_MODIFIER, 'Variable Modifier %s' % Result[0], FileTable, Result[2]) + break + + SqlStatement = """ select Modifier, Name, ID + from %s + where Model = %d + """ % (FileTable, DataClass.MODEL_IDENTIFIER_FUNCTION_DECLARATION) + ResultSet = Db.TblFile.Exec(SqlStatement) + for Result in ResultSet: + for Modifier in ModifierTuple: + if PatternInModifier(Result[0], Modifier): + PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_IN_OUT_MODIFIER, 'Return Type Modifier %s' % Result[0], FileTable, Result[2]) + break + + SqlStatement = """ select Modifier, Header, ID + from Function + where BelongsToFile = %d + """ % (FileID) + ResultSet = Db.TblFile.Exec(SqlStatement) + for Result in ResultSet: + for Modifier in ModifierTuple: + if PatternInModifier(Result[0], Modifier): + PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_IN_OUT_MODIFIER, 'Return Type Modifier %s' % Result[0], FileTable, Result[2]) + break + +def CheckDeclNoUseCType(FullFileName): + ErrorMsgList = [] + + FileID = GetTableID(FullFileName, ErrorMsgList) + if FileID < 0: + return ErrorMsgList + + Db = GetDB() + FileTable = 'Identifier' + str(FileID) + SqlStatement = """ select Modifier, Name, ID + from %s + where Model = %d + """ % (FileTable, DataClass.MODEL_IDENTIFIER_VARIABLE) + ResultSet = Db.TblFile.Exec(SqlStatement) + CTypeTuple = ('int', 'unsigned', 'char', 'void', 'static', 'long') + for Result in ResultSet: + for Type in CTypeTuple: + if PatternInModifier(Result[0], Type): + PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE, 'Variable type %s' % Type, FileTable, Result[2]) + break + + SqlStatement = """ select Modifier, Name, ID, Value + from %s + where Model = %d + """ % (FileTable, DataClass.MODEL_IDENTIFIER_FUNCTION_DECLARATION) + ResultSet = Db.TblFile.Exec(SqlStatement) + for Result in ResultSet: + ParamList = GetParamList(Result[1]) + FuncName = Result[3] + if EccGlobalData.gException.IsException(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE, FuncName): + continue + for Type in CTypeTuple: + if PatternInModifier(Result[0], Type): + PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE, '%s Return type %s' % (FuncName, Result[0]), FileTable, Result[2]) + + for Param in ParamList: + if PatternInModifier(Param.Modifier, Type): + PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE, 'Parameter %s' % Param.Name, FileTable, Result[2]) + + SqlStatement = """ select Modifier, Header, ID, Name + from Function + where BelongsToFile = %d + """ % (FileID) + ResultSet = Db.TblFile.Exec(SqlStatement) + for Result in ResultSet: + ParamList = GetParamList(Result[1]) + FuncName = Result[3] + if EccGlobalData.gException.IsException(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE, FuncName): + continue + for Type in CTypeTuple: + if PatternInModifier(Result[0], Type): + PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE, '[%s] Return type %s' % (FuncName, Result[0]), FileTable, Result[2]) + + for Param in ParamList: + if PatternInModifier(Param.Modifier, Type): + PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE, 'Parameter %s' % Param.Name, FileTable, Result[2]) + + +def CheckPointerNullComparison(FullFileName): + ErrorMsgList = [] + + FileID = GetTableID(FullFileName, ErrorMsgList) + if FileID < 0: + return ErrorMsgList + + # cache the found function return type to accelerate later checking in this file. + FuncReturnTypeDict = {} + + Db = GetDB() + FileTable = 'Identifier' + str(FileID) + SqlStatement = """ select Value, StartLine, ID + from %s + where Model = %d + """ % (FileTable, DataClass.MODEL_IDENTIFIER_PREDICATE_EXPRESSION) + ResultSet = Db.TblFile.Exec(SqlStatement) + if len(ResultSet) == 0: + return + PSL = [] + for Result in ResultSet: + PSL.append([Result[0], Result[1], Result[2]]) + + SqlStatement = """ select BodyStartLine, EndLine, Header, Modifier, ID + from Function + where BelongsToFile = %d + """ % (FileID) + ResultSet = Db.TblFile.Exec(SqlStatement) + FL = [] + for Result in ResultSet: + FL.append([Result[0], Result[1], Result[2], Result[3], Result[4]]) + + p = GetFuncDeclPattern() + for Str in PSL: + FuncRecord = GetFuncContainsPE(Str[1], FL) + if FuncRecord == None: + continue + + for Exp in GetPredicateListFromPredicateExpStr(Str[0]): + PredInfo = SplitPredicateStr(Exp) + if PredInfo[1] == None: + PredVarStr = PredInfo[0][0].strip() + IsFuncCall = False + SearchInCache = False + # PredVarStr may contain '.' or '->' + TmpStr = PredVarStr.replace('.', '').replace('->', '') + if p.match(TmpStr): + PredVarStr = PredVarStr[0:PredVarStr.find('(')] + SearchInCache = True + # Only direct function call using IsFuncCall branch. Multi-level ref. function call is considered a variable. + if TmpStr.startswith(PredVarStr): + IsFuncCall = True + + if PredVarStr.strip() in IgnoredKeywordList: + continue + StarList = [] + PredVarList = GetCNameList(PredVarStr, StarList) + # No variable found, maybe value first? like (0 == VarName) + if len(PredVarList) == 0: + continue + if SearchInCache: + Type = FuncReturnTypeDict.get(PredVarStr) + if Type != None: + if Type.find('*') != -1: + PrintErrorMsg(ERROR_PREDICATE_EXPRESSION_CHECK_COMPARISON_NULL_TYPE, 'Predicate Expression: %s' % Exp, FileTable, Str[2]) + continue + + if PredVarStr in FuncReturnTypeDict: + continue + + Type = GetVarInfo(PredVarList, FuncRecord, FullFileName, IsFuncCall, None, StarList) + if SearchInCache: + FuncReturnTypeDict[PredVarStr] = Type + if Type == None: + continue + if Type.find('*') != -1: + PrintErrorMsg(ERROR_PREDICATE_EXPRESSION_CHECK_COMPARISON_NULL_TYPE, 'Predicate Expression: %s' % Exp, FileTable, Str[2]) + +def CheckNonBooleanValueComparison(FullFileName): + ErrorMsgList = [] + + FileID = GetTableID(FullFileName, ErrorMsgList) + if FileID < 0: + return ErrorMsgList + + # cache the found function return type to accelerate later checking in this file. + FuncReturnTypeDict = {} + + Db = GetDB() + FileTable = 'Identifier' + str(FileID) + SqlStatement = """ select Value, StartLine, ID + from %s + where Model = %d + """ % (FileTable, DataClass.MODEL_IDENTIFIER_PREDICATE_EXPRESSION) + ResultSet = Db.TblFile.Exec(SqlStatement) + if len(ResultSet) == 0: + return + PSL = [] + for Result in ResultSet: + PSL.append([Result[0], Result[1], Result[2]]) + + SqlStatement = """ select BodyStartLine, EndLine, Header, Modifier, ID + from Function + where BelongsToFile = %d + """ % (FileID) + ResultSet = Db.TblFile.Exec(SqlStatement) + FL = [] + for Result in ResultSet: + FL.append([Result[0], Result[1], Result[2], Result[3], Result[4]]) + + p = GetFuncDeclPattern() + for Str in PSL: + FuncRecord = GetFuncContainsPE(Str[1], FL) + if FuncRecord == None: + continue + + for Exp in GetPredicateListFromPredicateExpStr(Str[0]): +# if p.match(Exp): +# continue + PredInfo = SplitPredicateStr(Exp) + if PredInfo[1] == None: + PredVarStr = PredInfo[0][0].strip() + IsFuncCall = False + SearchInCache = False + # PredVarStr may contain '.' or '->' + TmpStr = PredVarStr.replace('.', '').replace('->', '') + if p.match(TmpStr): + PredVarStr = PredVarStr[0:PredVarStr.find('(')] + SearchInCache = True + # Only direct function call using IsFuncCall branch. Multi-level ref. function call is considered a variable. + if TmpStr.startswith(PredVarStr): + IsFuncCall = True + + if PredVarStr.strip() in IgnoredKeywordList: + continue + StarList = [] + PredVarList = GetCNameList(PredVarStr, StarList) + # No variable found, maybe value first? like (0 == VarName) + if len(PredVarList) == 0: + continue + + if SearchInCache: + Type = FuncReturnTypeDict.get(PredVarStr) + if Type != None: + if Type.find('BOOLEAN') == -1: + PrintErrorMsg(ERROR_PREDICATE_EXPRESSION_CHECK_NO_BOOLEAN_OPERATOR, 'Predicate Expression: %s' % Exp, FileTable, Str[2]) + continue + + if PredVarStr in FuncReturnTypeDict: + continue + + Type = GetVarInfo(PredVarList, FuncRecord, FullFileName, IsFuncCall, 'BOOLEAN', StarList) + if SearchInCache: + FuncReturnTypeDict[PredVarStr] = Type + if Type == None: + continue + if Type.find('BOOLEAN') == -1: + PrintErrorMsg(ERROR_PREDICATE_EXPRESSION_CHECK_NO_BOOLEAN_OPERATOR, 'Predicate Expression: %s' % Exp, FileTable, Str[2]) + + +def CheckBooleanValueComparison(FullFileName): + ErrorMsgList = [] + + FileID = GetTableID(FullFileName, ErrorMsgList) + if FileID < 0: + return ErrorMsgList + + # cache the found function return type to accelerate later checking in this file. + FuncReturnTypeDict = {} + + Db = GetDB() + FileTable = 'Identifier' + str(FileID) + SqlStatement = """ select Value, StartLine, ID + from %s + where Model = %d + """ % (FileTable, DataClass.MODEL_IDENTIFIER_PREDICATE_EXPRESSION) + ResultSet = Db.TblFile.Exec(SqlStatement) + if len(ResultSet) == 0: + return + PSL = [] + for Result in ResultSet: + PSL.append([Result[0], Result[1], Result[2]]) + + SqlStatement = """ select BodyStartLine, EndLine, Header, Modifier, ID + from Function + where BelongsToFile = %d + """ % (FileID) + ResultSet = Db.TblFile.Exec(SqlStatement) + FL = [] + for Result in ResultSet: + FL.append([Result[0], Result[1], Result[2], Result[3], Result[4]]) + + p = GetFuncDeclPattern() + for Str in PSL: + FuncRecord = GetFuncContainsPE(Str[1], FL) + if FuncRecord == None: + continue + + for Exp in GetPredicateListFromPredicateExpStr(Str[0]): + PredInfo = SplitPredicateStr(Exp) + if PredInfo[1] in ('==', '!=') and PredInfo[0][1] in ('TRUE', 'FALSE'): + PredVarStr = PredInfo[0][0].strip() + IsFuncCall = False + SearchInCache = False + # PredVarStr may contain '.' or '->' + TmpStr = PredVarStr.replace('.', '').replace('->', '') + if p.match(TmpStr): + PredVarStr = PredVarStr[0:PredVarStr.find('(')] + SearchInCache = True + # Only direct function call using IsFuncCall branch. Multi-level ref. function call is considered a variable. + if TmpStr.startswith(PredVarStr): + IsFuncCall = True + + if PredVarStr.strip() in IgnoredKeywordList: + continue + StarList = [] + PredVarList = GetCNameList(PredVarStr, StarList) + # No variable found, maybe value first? like (0 == VarName) + if len(PredVarList) == 0: + continue + + if SearchInCache: + Type = FuncReturnTypeDict.get(PredVarStr) + if Type != None: + if Type.find('BOOLEAN') != -1: + PrintErrorMsg(ERROR_PREDICATE_EXPRESSION_CHECK_BOOLEAN_VALUE, 'Predicate Expression: %s' % Exp, FileTable, Str[2]) + continue + + if PredVarStr in FuncReturnTypeDict: + continue + + Type = GetVarInfo(PredVarList, FuncRecord, FullFileName, IsFuncCall, 'BOOLEAN', StarList) + if SearchInCache: + FuncReturnTypeDict[PredVarStr] = Type + if Type == None: + continue + if Type.find('BOOLEAN') != -1: + PrintErrorMsg(ERROR_PREDICATE_EXPRESSION_CHECK_BOOLEAN_VALUE, 'Predicate Expression: %s' % Exp, FileTable, Str[2]) + + +def CheckHeaderFileData(FullFileName): + ErrorMsgList = [] + + FileID = GetTableID(FullFileName, ErrorMsgList) + if FileID < 0: + return ErrorMsgList + + Db = GetDB() + FileTable = 'Identifier' + str(FileID) + SqlStatement = """ select ID, Modifier + from %s + where Model = %d + """ % (FileTable, DataClass.MODEL_IDENTIFIER_VARIABLE) + ResultSet = Db.TblFile.Exec(SqlStatement) + for Result in ResultSet: + if not Result[1].startswith('extern'): + PrintErrorMsg(ERROR_INCLUDE_FILE_CHECK_DATA, 'Variable definition appears in header file', FileTable, Result[0]) + + SqlStatement = """ select ID + from Function + where BelongsToFile = %d + """ % FileID + ResultSet = Db.TblFile.Exec(SqlStatement) + for Result in ResultSet: + PrintErrorMsg(ERROR_INCLUDE_FILE_CHECK_DATA, 'Function definition appears in header file', 'Function', Result[0]) + + return ErrorMsgList + +def CheckHeaderFileIfndef(FullFileName): + ErrorMsgList = [] + + FileID = GetTableID(FullFileName, ErrorMsgList) + if FileID < 0: + return ErrorMsgList + + Db = GetDB() + FileTable = 'Identifier' + str(FileID) + SqlStatement = """ select Value, StartLine + from %s + where Model = %d order by StartLine + """ % (FileTable, DataClass.MODEL_IDENTIFIER_MACRO_IFNDEF) + ResultSet = Db.TblFile.Exec(SqlStatement) + if len(ResultSet) == 0: + PrintErrorMsg(ERROR_INCLUDE_FILE_CHECK_IFNDEF_STATEMENT_1, '', 'File', FileID) + return ErrorMsgList + for Result in ResultSet: + SqlStatement = """ select Value, EndLine + from %s + where EndLine < %d + """ % (FileTable, Result[1]) + ResultSet = Db.TblFile.Exec(SqlStatement) + for Result in ResultSet: + if not Result[0].startswith('/*') and not Result[0].startswith('//'): + PrintErrorMsg(ERROR_INCLUDE_FILE_CHECK_IFNDEF_STATEMENT_2, '', 'File', FileID) + break + + SqlStatement = """ select Value + from %s + where StartLine > (select max(EndLine) from %s where Model = %d) + """ % (FileTable, FileTable, DataClass.MODEL_IDENTIFIER_MACRO_ENDIF) + ResultSet = Db.TblFile.Exec(SqlStatement) + for Result in ResultSet: + if not Result[0].startswith('/*') and not Result[0].startswith('//'): + PrintErrorMsg(ERROR_INCLUDE_FILE_CHECK_IFNDEF_STATEMENT_3, '', 'File', FileID) + return ErrorMsgList + +def CheckDoxygenCommand(FullFileName): + ErrorMsgList = [] + + FileID = GetTableID(FullFileName, ErrorMsgList) + if FileID < 0: + return ErrorMsgList + + Db = GetDB() + FileTable = 'Identifier' + str(FileID) + SqlStatement = """ select Value, ID + from %s + where Model = %d or Model = %d + """ % (FileTable, DataClass.MODEL_IDENTIFIER_COMMENT, DataClass.MODEL_IDENTIFIER_FUNCTION_HEADER) + ResultSet = Db.TblFile.Exec(SqlStatement) + DoxygenCommandList = ['bug', 'todo', 'example', 'file', 'attention', 'param', 'post', 'pre', 'retval', 'return', 'sa', 'since', 'test', 'note', 'par'] + for Result in ResultSet: + CommentStr = Result[0] + CommentPartList = CommentStr.split() + for Part in CommentPartList: + if Part.upper() == 'BUGBUG': + PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMAND, 'Bug should be marked with doxygen tag @bug', FileTable, Result[1]) + if Part.upper() == 'TODO': + PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMAND, 'ToDo should be marked with doxygen tag @todo', FileTable, Result[1]) + if Part.startswith('@'): + if EccGlobalData.gException.IsException(ERROR_DOXYGEN_CHECK_COMMAND, Part): + continue + if Part.lstrip('@').isalpha(): + if Part.lstrip('@') not in DoxygenCommandList: + PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMAND, 'Unknown doxygen command %s' % Part, FileTable, Result[1]) + else: + Index = Part.find('[') + if Index == -1: + PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMAND, 'Unknown doxygen command %s' % Part, FileTable, Result[1]) + RealCmd = Part[1:Index] + if RealCmd not in DoxygenCommandList: + PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMAND, 'Unknown doxygen command %s' % Part, FileTable, Result[1]) + + +def CheckDoxygenTripleForwardSlash(FullFileName): + ErrorMsgList = [] + + FileID = GetTableID(FullFileName, ErrorMsgList) + if FileID < 0: + return ErrorMsgList + + Db = GetDB() + + SqlStatement = """ select ID, BodyStartLine, BodyStartColumn, EndLine, EndColumn + from Function + where BelongsToFile = %d + """ % (FileID) + ResultSet = Db.TblFile.Exec(SqlStatement) + if len(ResultSet) == 0: + return + + FuncDefSet = [] + for Result in ResultSet: + FuncDefSet.append(Result) + + + FileTable = 'Identifier' + str(FileID) + SqlStatement = """ select Value, ID, StartLine, StartColumn, EndLine, EndColumn + from %s + where Model = %d + + """ % (FileTable, DataClass.MODEL_IDENTIFIER_COMMENT) + ResultSet = Db.TblFile.Exec(SqlStatement) + CommentSet = [] + try: + for Result in ResultSet: + CommentSet.append(Result) + except: + print 'Unrecognized chars in comment of file %s', FullFileName + + + for Result in CommentSet: + CommentStr = Result[0] + StartLine = Result[2] + StartColumn = Result[3] + EndLine = Result[4] + EndColumn = Result[5] + if not CommentStr.startswith('///<'): + continue + + Found = False + for FuncDef in FuncDefSet: + if StartLine == FuncDef[1] and StartColumn > FuncDef[2] and EndLine == FuncDef[3] and EndColumn < FuncDef[4]: + Found = True + break + if StartLine > FuncDef[1] and EndLine < FuncDef[3]: + Found = True + break + if StartLine == FuncDef[1] and StartColumn > FuncDef[2] and EndLine < FuncDef[3]: + Found = True + break + if StartLine > FuncDef[1] and EndLine == FuncDef[3] and EndColumn < FuncDef[4]: + Found = True + break + if Found: + PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMENT_FORMAT, '', FileTable, Result[1]) + + +def CheckFileHeaderDoxygenComments(FullFileName): + ErrorMsgList = [] + + FileID = GetTableID(FullFileName, ErrorMsgList) + if FileID < 0: + return ErrorMsgList + + Db = GetDB() + FileTable = 'Identifier' + str(FileID) + SqlStatement = """ select Value, ID + from %s + where Model = %d and StartLine = 1 and StartColumn = 0 + """ % (FileTable, DataClass.MODEL_IDENTIFIER_COMMENT) + ResultSet = Db.TblFile.Exec(SqlStatement) + if len(ResultSet) == 0: + PrintErrorMsg(ERROR_HEADER_CHECK_FILE, 'No Comment appear at the very beginning of file.', 'File', FileID) + return ErrorMsgList + + for Result in ResultSet: + CommentStr = Result[0] + if not CommentStr.startswith('/** @file'): + PrintErrorMsg(ERROR_DOXYGEN_CHECK_FILE_HEADER, 'File header comment should begin with ""/** @file""', FileTable, Result[1]) + if not CommentStr.endswith('**/'): + PrintErrorMsg(ERROR_HEADER_CHECK_FILE, 'File header comment should end with **/', FileTable, Result[1]) + if CommentStr.find('.') == -1: + PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMENT_DESCRIPTION, 'Comment description should end with period \'.\'', FileTable, Result[1]) + +def CheckFuncHeaderDoxygenComments(FullFileName): + ErrorMsgList = [] + + FileID = GetTableID(FullFileName, ErrorMsgList) + if FileID < 0: + return ErrorMsgList + + Db = GetDB() + FileTable = 'Identifier' + str(FileID) + SqlStatement = """ select Value, StartLine, EndLine, ID + from %s + where Model = %d + """ % (FileTable, DataClass.MODEL_IDENTIFIER_COMMENT) + + ResultSet = Db.TblFile.Exec(SqlStatement) + CommentSet = [] + try: + for Result in ResultSet: + CommentSet.append(Result) + except: + print 'Unrecognized chars in comment of file %s', FullFileName + + # Func Decl check + SqlStatement = """ select Modifier, Name, StartLine, ID, Value + from %s + where Model = %d + """ % (FileTable, DataClass.MODEL_IDENTIFIER_FUNCTION_DECLARATION) + ResultSet = Db.TblFile.Exec(SqlStatement) + for Result in ResultSet: + FuncName = Result[4] + FunctionHeaderComment = CheckCommentImmediatelyPrecedeFunctionHeader(Result[1], Result[2], CommentSet) + if FunctionHeaderComment: + CheckFunctionHeaderConsistentWithDoxygenComment(Result[0], Result[1], Result[2], FunctionHeaderComment[0], FunctionHeaderComment[1], ErrorMsgList, FunctionHeaderComment[3], FileTable) + else: + if EccGlobalData.gException.IsException(ERROR_HEADER_CHECK_FUNCTION, FuncName): + continue + ErrorMsgList.append('Line %d :Function %s has NO comment immediately preceding it.' % (Result[2], Result[1])) + PrintErrorMsg(ERROR_HEADER_CHECK_FUNCTION, 'Function [%s] has NO comment immediately preceding it.' % (FuncName), FileTable, Result[3]) + + # Func Def check + SqlStatement = """ select Value, StartLine, EndLine, ID + from %s + where Model = %d + """ % (FileTable, DataClass.MODEL_IDENTIFIER_FUNCTION_HEADER) + + ResultSet = Db.TblFile.Exec(SqlStatement) + CommentSet = [] + try: + for Result in ResultSet: + CommentSet.append(Result) + except: + print 'Unrecognized chars in comment of file %s', FullFileName + + SqlStatement = """ select Modifier, Header, StartLine, ID, Name + from Function + where BelongsToFile = %d + """ % (FileID) + ResultSet = Db.TblFile.Exec(SqlStatement) + for Result in ResultSet: + FuncName = Result[4] + FunctionHeaderComment = CheckCommentImmediatelyPrecedeFunctionHeader(Result[1], Result[2], CommentSet) + if FunctionHeaderComment: + CheckFunctionHeaderConsistentWithDoxygenComment(Result[0], Result[1], Result[2], FunctionHeaderComment[0], FunctionHeaderComment[1], ErrorMsgList, FunctionHeaderComment[3], FileTable) + else: + if EccGlobalData.gException.IsException(ERROR_HEADER_CHECK_FUNCTION, FuncName): + continue + ErrorMsgList.append('Line %d :Function [%s] has NO comment immediately preceding it.' % (Result[2], Result[1])) + PrintErrorMsg(ERROR_HEADER_CHECK_FUNCTION, 'Function [%s] has NO comment immediately preceding it.' % (FuncName), 'Function', Result[3]) + return ErrorMsgList + +def CheckCommentImmediatelyPrecedeFunctionHeader(FuncName, FuncStartLine, CommentSet): + + for Comment in CommentSet: + if Comment[2] == FuncStartLine - 1: + return Comment + return None + +def GetDoxygenStrFromComment(Str): + DoxygenStrList = [] + ParamTagList = Str.split('@param') + if len(ParamTagList) > 1: + i = 1 + while i < len(ParamTagList): + DoxygenStrList.append('@param' + ParamTagList[i]) + i += 1 + + Str = ParamTagList[0] + + RetvalTagList = ParamTagList[-1].split('@retval') + if len(RetvalTagList) > 1: + if len(ParamTagList) > 1: + DoxygenStrList[-1] = '@param' + RetvalTagList[0] + i = 1 + while i < len(RetvalTagList): + DoxygenStrList.append('@retval' + RetvalTagList[i]) + i += 1 + + ReturnTagList = RetvalTagList[-1].split('@return') + if len(ReturnTagList) > 1: + if len(RetvalTagList) > 1: + DoxygenStrList[-1] = '@retval' + ReturnTagList[0] + elif len(ParamTagList) > 1: + DoxygenStrList[-1] = '@param' + ReturnTagList[0] + i = 1 + while i < len(ReturnTagList): + DoxygenStrList.append('@return' + ReturnTagList[i]) + i += 1 + + if len(DoxygenStrList) > 0: + DoxygenStrList[-1] = DoxygenStrList[-1].rstrip('--*/') + + return DoxygenStrList + +def CheckGeneralDoxygenCommentLayout(Str, StartLine, ErrorMsgList, CommentId = -1, TableName = ''): + #/** --*/ @retval after @param + if not Str.startswith('/**'): + ErrorMsgList.append('Line %d : Comment does NOT have prefix /** ' % StartLine) + PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER, 'Comment does NOT have prefix /** ', TableName, CommentId) + if not Str.endswith('**/'): + ErrorMsgList.append('Line %d : Comment does NOT have tail **/ ' % StartLine) + PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER, 'Comment does NOT have tail **/ ', TableName, CommentId) + FirstRetvalIndex = Str.find('@retval') + LastParamIndex = Str.rfind('@param') + if (FirstRetvalIndex > 0) and (LastParamIndex > 0) and (FirstRetvalIndex < LastParamIndex): + ErrorMsgList.append('Line %d : @retval appear before @param ' % StartLine) + PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER, 'in Comment, @retval appear before @param ', TableName, CommentId) + +def CheckFunctionHeaderConsistentWithDoxygenComment(FuncModifier, FuncHeader, FuncStartLine, CommentStr, CommentStartLine, ErrorMsgList, CommentId = -1, TableName = ''): + + ParamList = GetParamList(FuncHeader) + CheckGeneralDoxygenCommentLayout(CommentStr, CommentStartLine, ErrorMsgList, CommentId, TableName) + DescriptionStr = CommentStr + DoxygenStrList = GetDoxygenStrFromComment(DescriptionStr) + if DescriptionStr.find('.') == -1: + PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMENT_DESCRIPTION, 'Comment description should end with period \'.\'', TableName, CommentId) + DoxygenTagNumber = len(DoxygenStrList) + ParamNumber = len(ParamList) + for Param in ParamList: + if Param.Name.upper() == 'VOID' and ParamNumber == 1: + ParamNumber -= 1 + Index = 0 + if ParamNumber > 0 and DoxygenTagNumber > 0: + while Index < ParamNumber and Index < DoxygenTagNumber: + ParamModifier = ParamList[Index].Modifier + ParamName = ParamList[Index].Name.strip() + Tag = DoxygenStrList[Index].strip(' ') + if (not Tag[-1] == ('\n')) and (not Tag[-1] == ('\r')): + ErrorMsgList.append('Line %d : in Comment, \"%s\" does NOT end with new line ' % (CommentStartLine, Tag.replace('\n', '').replace('\r', ''))) + PrintErrorMsg(ERROR_HEADER_CHECK_FUNCTION, 'in Comment, \"%s\" does NOT end with new line ' % (Tag.replace('\n', '').replace('\r', '')), TableName, CommentId) + TagPartList = Tag.split() + if len(TagPartList) < 2: + ErrorMsgList.append('Line %d : in Comment, \"%s\" does NOT contain doxygen contents ' % (CommentStartLine, Tag.replace('\n', '').replace('\r', ''))) + PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER, 'in Comment, \"%s\" does NOT contain doxygen contents ' % (Tag.replace('\n', '').replace('\r', '')), TableName, CommentId) + Index += 1 + continue + LBPos = Tag.find('[') + RBPos = Tag.find(']') + ParamToLBContent = Tag[len('@param'):LBPos].strip() + if LBPos > 0 and len(ParamToLBContent)==0 and RBPos > LBPos: + InOutStr = '' + ModifierPartList = ParamModifier.split() + for Part in ModifierPartList: + if Part.strip() == 'IN': + InOutStr += 'in' + if Part.strip() == 'OUT': + if InOutStr != '': + InOutStr += ', out' + else: + InOutStr = 'out' + + if InOutStr != '': + if Tag.find('['+InOutStr+']') == -1: + ErrorMsgList.append('Line %d : in Comment, \"%s\" does NOT have %s ' % (CommentStartLine, (TagPartList[0] + ' ' +TagPartList[1]).replace('\n', '').replace('\r', ''), '['+InOutStr+']')) + PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER, 'in Comment, \"%s\" does NOT have %s ' % ((TagPartList[0] + ' ' +TagPartList[1]).replace('\n', '').replace('\r', ''), '['+InOutStr+']'), TableName, CommentId) + if Tag.find(ParamName) == -1 and ParamName != 'VOID' and ParamName != 'void': + ErrorMsgList.append('Line %d : in Comment, \"%s\" does NOT consistent with parameter name %s ' % (CommentStartLine, (TagPartList[0] + ' ' +TagPartList[1]).replace('\n', '').replace('\r', ''), ParamName)) + PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER, 'in Comment, \"%s\" does NOT consistent with parameter name %s ' % ((TagPartList[0] + ' ' +TagPartList[1]).replace('\n', '').replace('\r', ''), ParamName), TableName, CommentId) + Index += 1 + + if Index < ParamNumber: + ErrorMsgList.append('Line %d : Number of doxygen tags in comment less than number of function parameters' % CommentStartLine) + PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER, 'Number of doxygen tags in comment less than number of function parameters ', TableName, CommentId) + # VOID return type, NOT VOID*. VOID* should be matched with a doxygen tag. + if (FuncModifier.find('VOID') != -1 or FuncModifier.find('void') != -1) and FuncModifier.find('*') == -1: + + # assume we allow a return description tag for void func. return. that's why 'DoxygenTagNumber - 1' is used instead of 'DoxygenTagNumber' + if Index < DoxygenTagNumber - 1 or (Index < DoxygenTagNumber and DoxygenStrList[Index].startswith('@retval')): + ErrorMsgList.append('Line %d : VOID return type need NO doxygen tags in comment' % CommentStartLine) + PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER, 'VOID return type need no doxygen tags in comment ', TableName, CommentId) + else: + if Index < DoxygenTagNumber and not DoxygenStrList[Index].startswith('@retval') and not DoxygenStrList[Index].startswith('@return'): + ErrorMsgList.append('Line %d : Number of @param doxygen tags in comment does NOT match number of function parameters' % CommentStartLine) + PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER, 'Number of @param doxygen tags in comment does NOT match number of function parameters ', TableName, CommentId) + else: + if ParamNumber == 0 and DoxygenTagNumber != 0 and ((FuncModifier.find('VOID') != -1 or FuncModifier.find('void') != -1) and FuncModifier.find('*') == -1): + ErrorMsgList.append('Line %d : VOID return type need NO doxygen tags in comment' % CommentStartLine) + PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER, 'VOID return type need NO doxygen tags in comment ', TableName, CommentId) + if ParamNumber != 0 and DoxygenTagNumber == 0: + ErrorMsgList.append('Line %d : No doxygen tags in comment' % CommentStartLine) + PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER, 'No doxygen tags in comment ', TableName, CommentId) + +if __name__ == '__main__': + +# EdkLogger.Initialize() +# EdkLogger.SetLevel(EdkLogger.QUIET) +# CollectSourceCodeDataIntoDB(sys.argv[1]) + MsgList = CheckFuncHeaderDoxygenComments('C:\\Combo\\R9\\LakeportX64Dev\\FlashDevicePkg\\Library\\SpiFlashChipM25P64\\SpiFlashChipM25P64.c') + for Msg in MsgList: + print Msg + print 'Done!' diff --git a/BaseTools/Source/Python/Ecc/config.ini b/BaseTools/Source/Python/Ecc/config.ini new file mode 100644 index 0000000000..a3215aedaa --- /dev/null +++ b/BaseTools/Source/Python/Ecc/config.ini @@ -0,0 +1,242 @@ +## @file +# This file is used to set configuration of ECC tool +# For the items listed below, 1 means valid, 0 means invalid +# +# Copyright (c) 2007, 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. +# + +# +# Identify the version of current configuration +# +Version = 0.1 + +# +# Identify to if check all items +# 1 - Check all items and ignore all other detailed items +# 0 - Not check all items, the tool will go through all other detailed items to decide to check or not +# +CheckAll = 0 + +# +# Identify to if automatically correct mistakes +# 1 - Automatically correct +# 0 - Not automatically correct +# Only the following check points can be automatically corrected, others not listed below are not supported even it is 1 +# +# GeneralCheckTab +# GeneralCheckIndentation +# GeneralCheckLine +# GeneralCheckCarriageReturn +# SpaceCheckAll +# +AutoCorrect = 1 + +# +# List customized Modifer here, split with ',' +# +ModifierList = IN, OUT, OPTIONAL, UNALIGNED, EFI_RUNTIMESERVICE, EFI_BOOTSERVICE, EFIAPI, TPMINTERNALAPI + +# +# General Checking +# +GeneralCheckAll = 0 + +# Check whether NO Tab is used, replaced with spaces +GeneralCheckNoTab = 1 +# The width of Tab +GeneralCheckTabWidth = 2 +# Check whether the indentation is followed coding style +GeneralCheckIndentation = 1 +# The width of indentation +GeneralCheckIndentationWidth = 2 +# Check whether no line is exceeding defined widty +GeneralCheckLine = 1 +# The width of a line +GeneralCheckLineWidth = 120 +# Check whether no use of _asm in the source file +GeneralCheckNo_Asm = 1 +# Check whether no use of "#progma" in source file except "#pragma pack(#)". +GeneralCheckNoProgma = 1 +# Check whether there is a carriage return at the end of the file +GeneralCheckCarriageReturn = 1 +# Check whether the file exists +GeneralCheckFileExistence = 1 + +# +# Space Checking +# +SpaceCheckAll = 1 + +# +# Predicate Expression Checking +# +PredicateExpressionCheckAll = 0 + +# Check whether Boolean values, variable type BOOLEAN not use explicit comparisons to TRUE or FALSE +PredicateExpressionCheckBooleanValue = 1 +# Check whether Non-Boolean comparisons use a compare operator (==, !=, >, < >=, <=). +PredicateExpressionCheckNonBooleanOperator = 1 +# Check whether a comparison of any pointer to zero must be done via the NULL type +PredicateExpressionCheckComparisonNullType = 1 + +# +# Headers Checking +# +HeaderCheckAll = 0 + +# Check whether File header exists +HeaderCheckFile = 1 +# Check whether Function header exists +HeaderCheckFunction = 1 + +# +# C Function Layout Checking +# +CFunctionLayoutCheckAll = 0 + +# Check whether return type exists and in the first line +CFunctionLayoutCheckReturnType = 1 +# Check whether any optional functional modifiers exist and next to the return type +CFunctionLayoutCheckOptionalFunctionalModifier = 1 +# Check whether the next line contains the function name, left justified, followed by the beginning of the parameter list +# Check whether the closing parenthesis is on its own line and also indented two spaces +CFunctionLayoutCheckFunctionName = 1 +# Check whether the function prototypes in include files have the same form as function definitions +CFunctionLayoutCheckFunctionPrototype = 1 +# Check whether the body of a function is contained by open and close braces that must be in the first column +CFunctionLayoutCheckFunctionBody = 1 +# Check whether the data declarations is the first code in a module. +CFunctionLayoutCheckDataDeclaration = 1 +# Check whether no initialization of a variable as part of its declaration +CFunctionLayoutCheckNoInitOfVariable = 1 +# Check whether no use of STATIC for functions +CFunctionLayoutCheckNoStatic = 1 + +# +# Include Files Checking +# +IncludeFileCheckAll = 0 + +#Check whether having include files with same name +IncludeFileCheckSameName = 1 +# Check whether all include file contents is guarded by a #ifndef statement. +# the #ifndef must be the first line of code following the file header comment +# the #endif must appear on the last line in the file +IncludeFileCheckIfndefStatement = 1 +# Check whether include files contain only public or only private data +# Check whether include files NOT contain code or define data variables +IncludeFileCheckData = 1 + +# +# Declarations and Data Types Checking +# +DeclarationDataTypeCheckAll = 0 + +# Check whether no use of int, unsigned, char, void, static, long in any .c, .h or .asl files. +DeclarationDataTypeCheckNoUseCType = 1 +# Check whether the modifiers IN, OUT, OPTIONAL, and UNALIGNED are used only to qualify arguments to a function and should not appear in a data type declaration +DeclarationDataTypeCheckInOutModifier = 1 +# Check whether the EFIAPI modifier should be used at the entry of drivers, events, and member functions of protocols +DeclarationDataTypeCheckEFIAPIModifier = 1 +# Check whether Enumerated Type has a 'typedef' and the name is capital +DeclarationDataTypeCheckEnumeratedType = 1 +# Check whether Structure Type has a 'typedef' and the name is capital +DeclarationDataTypeCheckStructureDeclaration = 1 +# Check whether having same Structure +DeclarationDataTypeCheckSameStructure = 1 +# Check whether Union Type has a 'typedef' and the name is capital +DeclarationDataTypeCheckUnionType = 1 + + +# +# Naming Conventions Checking +# +NamingConventionCheckAll = 0 + +# Check whether only capital letters are used for #define declarations +NamingConventionCheckDefineStatement = 1 +# Check whether only capital letters are used for typedef declarations +NamingConventionCheckTypedefStatement = 1 +# Check whether the #ifndef at the start of an include file uses both prefix and postfix underscore characters, '_'. +NamingConventionCheckIfndefStatement = 1 +# Rule for path name, variable name and function name +# 1. First character should be upper case +# 2. Existing lower case in a word +# 3. No space existence +# 4. Global variable name must start by a 'g' +# Check whether the path name followed the rule +NamingConventionCheckPathName = 1 +# Check whether the variable name followed the rule +NamingConventionCheckVariableName = 1 +# Check whether the function name followed the rule +NamingConventionCheckFunctionName = 1 +# Check whether NO use short variable name with single character +NamingConventionCheckSingleCharacterVariable = 1 + +# +# Doxygen Checking +# +DoxygenCheckAll = 0 + +# Check whether the file headers are followed Doxygen special documentation blocks in section 2.3.5 +DoxygenCheckFileHeader = 1 +# Check whether the function headers are followed Doxygen special documentation blocks in section 2.3.5 +DoxygenCheckFunctionHeader = 1 +# Check whether the first line of text in a comment block is a brief description of the element being documented. +# The brief description must end with a period. +DoxygenCheckCommentDescription = 1 +# Check whether comment lines with '///< ... text ...' format, if it is used, it should be after the code section. +DoxygenCheckCommentFormat = 1 +# Check whether only Doxygen commands allowed to mark the code are @bug and @todo. +DoxygenCheckCommand = 1 + +# +# Meta-Data File Processing Checking +# +MetaDataFileCheckAll = 0 + +# Check whether each file defined in meta-data exists +MetaDataFileCheckPathName = 1 +# Generate a list for all files defined in meta-data files +MetaDataFileCheckGenerateFileList = 1 +# The path of log file +MetaDataFileCheckPathOfGenerateFileList = File.log +# Check whether all Library Instances defined for a given module (or dependent library instance) match the module's type. +# Each Library Instance must specify the Supported Module Types in its INF file, +# and any module specifying the library instance must be one of the supported types. +MetaDataFileCheckLibraryInstance = 1 +# Check whether a Library Instance has been defined for all dependent library classes +MetaDataFileCheckLibraryInstanceDependent = 1 +# Check whether the Library Instances specified by the LibraryClasses sections are listed in order of dependencies +MetaDataFileCheckLibraryInstanceOrder = 1 +# Check whether the unnecessary inclusion of library classes in the INF file +MetaDataFileCheckLibraryNoUse = 1 +# Check whether an INF file is specified in the FDF file, but not in the DSC file, then the INF file must be for a Binary module only +MetaDataFileCheckBinaryInfInFdf = 1 +# Not to report error and warning related OS include file such as "windows.h" and "stdio.h". +# Check whether a PCD is set in a DSC file or the FDF file, but not in both. +MetaDataFileCheckPcdDuplicate = 1 +# Check whether PCD settings in the FDF file can only be related to flash. +MetaDataFileCheckPcdFlash = 1 +# Check whether PCDs used in INF files but not specified in DSC or FDF files +MetaDataFileCheckPcdNoUse = 1 +# Check whether having duplicate guids defined for Guid/Protocol/Ppi +MetaDataFileCheckGuidDuplicate = 1 +# Check whether all files under module directory are described in INF files +MetaDataFileCheckModuleFileNoUse = 1 +# Check whether the PCD is correctly used in C function via its type +MetaDataFileCheckPcdType = 1 + +# +# The check points in this section are reserved +# +# GotoStatementCheckAll = 0 +# SpellingCheckAll = 0 +# diff --git a/BaseTools/Source/Python/Ecc/exception.xml b/BaseTools/Source/Python/Ecc/exception.xml new file mode 100644 index 0000000000..0dc67527b5 --- /dev/null +++ b/BaseTools/Source/Python/Ecc/exception.xml @@ -0,0 +1,310 @@ + + + __debugbreak + 4002 + + + __readmsr + 4002 + + + __writemsr + 4002 + + + _InterlockedCompareExchange + 4002 + + + _InterlockedCompareExchange64 + 4002 + + + _InterlockedDecrement + 4002 + + + _InterlockedIncrement + 4002 + + + _break + 4002 + + + _inp + 4002 + + + _inpw + 4002 + + + _inpd + 4002 + + + _outp + 4002 + + + _outpw + 4002 + + + _outpd + 4002 + + + _ReadWriteBarrier + 4002 + + + InternalX86DisablePaging32 + 4002 + + + InternalX86EnablePaging32 + 4002 + + + InternalLongJump + 4002 + + + SetJump + 4002 + + + __debugbreak + 5001 + + + __readmsr + 5001 + + + __writemsr + 5001 + + + _InterlockedCompareExchange + 5001 + + + _InterlockedCompareExchange64 + 5001 + + + _InterlockedDecrement + 5001 + + + _InterlockedIncrement + 5001 + + + _inp + 5001 + + + _inpw + 5001 + + + _inpd + 5001 + + + _outp + 5001 + + + _outpw + 5001 + + + _outpd + 5001 + + + _ReadWriteBarrier + 5001 + + + IoRead8 + 5001 + + + IoWrite8 + 5001 + + + IoRead16 + 5001 + + + IoWrite16 + 5001 + + + IoRead32 + 5001 + + + IoWrite32 + 5001 + + + __debugbreak + 5003 + + + __readmsr + 5003 + + + __writemsr + 5003 + + + _InterlockedCompareExchange + 5003 + + + _InterlockedCompareExchange64 + 5003 + + + _InterlockedDecrement + 5003 + + + _InterlockedIncrement + 5003 + + + _inp + 5003 + + + _inpw + 5003 + + + _inpd + 5003 + + + _outp + 5003 + + + _outpw + 5003 + + + _outpd + 5003 + + + _ReadWriteBarrier + 5003 + + + __debugbreak + 7001 + + + __readmsr + 7001 + + + __writemsr + 7001 + + + _InterlockedCompareExchange + 7001 + + + _InterlockedCompareExchange64 + 7001 + + + _InterlockedDecrement + 7001 + + + _InterlockedIncrement + 7001 + + + _inp + 7001 + + + _inpw + 7001 + + + _inpd + 7001 + + + _outp + 7001 + + + _outpw + 7001 + + + _outpd + 7001 + + + _ReadWriteBarrier + 7001 + + + @ + 9005 + + + @R1 + 9005 + + + @R2 + 9005 + + + @Rx + 9005 + + + @R2. + 9005 + + + _DriverUnloadHandler + 8006 + + + ASSERT + 10015 + + + REPORT_STATUS_CODE + 10015 + + + REPORT_STATUS_CODE_WITH_EXTENDED_DATA + 10015 + + + REPORT_STATUS_CODE_WITH_DEVICE_PATH + 10015 + + \ No newline at end of file diff --git a/BaseTools/Source/Python/Fdb/__init__.py b/BaseTools/Source/Python/Fdb/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/BaseTools/Source/Python/FixFlash/__init__.py b/BaseTools/Source/Python/FixFlash/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/BaseTools/Source/Python/GNUmakefile b/BaseTools/Source/Python/GNUmakefile new file mode 100644 index 0000000000..aa569b3624 --- /dev/null +++ b/BaseTools/Source/Python/GNUmakefile @@ -0,0 +1,6 @@ + +all: + +clean: + find . -name '*.pyc' -exec rm '{}' ';' + diff --git a/BaseTools/Source/Python/GenFds/AprioriSection.py b/BaseTools/Source/Python/GenFds/AprioriSection.py new file mode 100644 index 0000000000..92a9794f51 --- /dev/null +++ b/BaseTools/Source/Python/GenFds/AprioriSection.py @@ -0,0 +1,118 @@ +## @file +# process APRIORI file data and generate PEI/DXE APRIORI file +# +# Copyright (c) 2007, 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. +# + +## +# Import Modules +# +from struct import * +import os +import StringIO +import FfsFileStatement +from GenFdsGlobalVariable import GenFdsGlobalVariable +from CommonDataClass.FdfClass import AprioriSectionClassObject +from Common.String import * +from Common.Misc import SaveFileOnChange,PathClass +from Common import EdkLogger +from Common.BuildToolError import * + +## process APRIORI file data and generate PEI/DXE APRIORI file +# +# +class AprioriSection (AprioriSectionClassObject): + ## The constructor + # + # @param self The object pointer + # + def __init__(self): + AprioriSectionClassObject.__init__(self) + self.AprioriType = "" + + ## GenFfs() method + # + # Generate FFS for APRIORI file + # + # @param self The object pointer + # @param FvName for whom apriori file generated + # @param Dict dictionary contains macro and its value + # @retval string Generated file name + # + def GenFfs (self, FvName, Dict = {}): + DXE_GUID = "FC510EE7-FFDC-11D4-BD41-0080C73C8881" + PEI_GUID = "1B45CC0A-156A-428A-AF62-49864DA0E6E6" + Buffer = StringIO.StringIO('') + AprioriFileGuid = DXE_GUID + if self.AprioriType == "PEI": + AprioriFileGuid = PEI_GUID + OutputAprFilePath = os.path.join (GenFdsGlobalVariable.WorkSpaceDir, \ + GenFdsGlobalVariable.FfsDir,\ + AprioriFileGuid + FvName) + if not os.path.exists(OutputAprFilePath) : + os.makedirs(OutputAprFilePath) + + OutputAprFileName = os.path.join( OutputAprFilePath, \ + AprioriFileGuid + FvName + '.Apri' ) + AprFfsFileName = os.path.join (OutputAprFilePath,\ + AprioriFileGuid + FvName + '.Ffs') + + Dict.update(self.DefineVarDict) + for FfsObj in self.FfsList : + Guid = "" + if isinstance(FfsObj, FfsFileStatement.FileStatement): + Guid = FfsObj.NameGuid + else: + InfFileName = NormPath(FfsObj.InfFileName) + Arch = FfsObj.GetCurrentArch() + + if Arch != None: + Dict['$(ARCH)'] = Arch + InfFileName = GenFdsGlobalVariable.MacroExtend(InfFileName, Dict, Arch) + + if Arch != None: + Inf = GenFdsGlobalVariable.WorkSpace.BuildObject[PathClass(InfFileName, GenFdsGlobalVariable.WorkSpaceDir), Arch] + Guid = Inf.Guid + + else: + Inf = GenFdsGlobalVariable.WorkSpace.BuildObject[PathClass(InfFileName, GenFdsGlobalVariable.WorkSpaceDir), 'COMMON'] + Guid = Inf.Guid + + self.BinFileList = Inf.Module.Binaries + if self.BinFileList == []: + EdkLogger.error("GenFds", RESOURCE_NOT_AVAILABLE, + "INF %s not found in build ARCH %s!" \ + % (InfFileName, GenFdsGlobalVariable.ArchList)) + + + GuidPart = Guid.split('-') + Buffer.write(pack('I', long(GuidPart[0], 16))) + Buffer.write(pack('H', int(GuidPart[1], 16))) + Buffer.write(pack('H', int(GuidPart[2], 16))) + + for Num in range(2): + Char = GuidPart[3][Num*2:Num*2+2] + Buffer.write(pack('B', int(Char, 16))) + + for Num in range(6): + Char = GuidPart[4][Num*2:Num*2+2] + Buffer.write(pack('B', int(Char, 16))) + + SaveFileOnChange(OutputAprFileName, Buffer.getvalue()) + + RawSectionFileName = os.path.join( OutputAprFilePath, \ + AprioriFileGuid + FvName + '.raw' ) + GenFdsGlobalVariable.GenerateSection(RawSectionFileName, [OutputAprFileName], 'EFI_SECTION_RAW') + GenFdsGlobalVariable.GenerateFfs(AprFfsFileName, [RawSectionFileName], + 'EFI_FV_FILETYPE_FREEFORM', AprioriFileGuid) + + return AprFfsFileName + diff --git a/BaseTools/Source/Python/GenFds/Attribute.py b/BaseTools/Source/Python/GenFds/Attribute.py new file mode 100644 index 0000000000..67f9956e1d --- /dev/null +++ b/BaseTools/Source/Python/GenFds/Attribute.py @@ -0,0 +1,28 @@ +## @file +# name value pair +# +# Copyright (c) 2007, 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. +# + +## +# Import Modules +# + +## name value pair +# +# +class Attribute: + ## The constructor + # + # @param self The object pointer + def __init__(self): + self.Name = None + self.Value = None \ No newline at end of file diff --git a/BaseTools/Source/Python/GenFds/Capsule.py b/BaseTools/Source/Python/GenFds/Capsule.py new file mode 100644 index 0000000000..7f17fcda68 --- /dev/null +++ b/BaseTools/Source/Python/GenFds/Capsule.py @@ -0,0 +1,89 @@ +## @file +# generate capsule +# +# Copyright (c) 2007, 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. +# + +## +# Import Modules +# +from GenFdsGlobalVariable import GenFdsGlobalVariable +from CommonDataClass.FdfClass import CapsuleClassObject +import os +import subprocess +import StringIO +from Common.Misc import SaveFileOnChange + + +T_CHAR_LF = '\n' + +## create inf file describes what goes into capsule and call GenFv to generate capsule +# +# +class Capsule (CapsuleClassObject) : + ## The constructor + # + # @param self The object pointer + # + def __init__(self): + CapsuleClassObject.__init__(self) + # For GenFv + self.BlockSize = None + # For GenFv + self.BlockNum = None + + ## Generate capsule + # + # @param self The object pointer + # + def GenCapsule(self): + CapInfFile = self.GenCapInf() + CapInfFile.writelines("[files]" + T_CHAR_LF) + + for CapsuleDataObj in self.CapsuleDataList : + FileName = CapsuleDataObj.GenCapsuleSubItem() + CapInfFile.writelines("EFI_FILE_NAME = " + \ + FileName + \ + T_CHAR_LF) + SaveFileOnChange(self.CapInfFileName, CapInfFile.getvalue(), False) + CapInfFile.close() + # + # Call GenFv tool to generate capsule + # + CapOutputFile = os.path.join(GenFdsGlobalVariable.FvDir, self.UiCapsuleName) + CapOutputFile = CapOutputFile + '.Cap' + GenFdsGlobalVariable.GenerateFirmwareVolume( + CapOutputFile, + [self.CapInfFileName], + Capsule=True + ) + GenFdsGlobalVariable.SharpCounter = 0 + + ## Generate inf file for capsule + # + # @param self The object pointer + # @retval file inf file object + # + def GenCapInf(self): + self.CapInfFileName = os.path.join(GenFdsGlobalVariable.FvDir, + self.UiCapsuleName + "_Cap" + '.inf') + CapInfFile = StringIO.StringIO() #open (self.CapInfFileName , 'w+') + + CapInfFile.writelines("[options]" + T_CHAR_LF) + + for Item in self.TokensDict.keys(): + CapInfFile.writelines("EFI_" + \ + Item + \ + ' = ' + \ + self.TokensDict.get(Item) + \ + T_CHAR_LF) + + return CapInfFile diff --git a/BaseTools/Source/Python/GenFds/CapsuleData.py b/BaseTools/Source/Python/GenFds/CapsuleData.py new file mode 100644 index 0000000000..db29737963 --- /dev/null +++ b/BaseTools/Source/Python/GenFds/CapsuleData.py @@ -0,0 +1,84 @@ +## @file +# generate capsule +# +# Copyright (c) 2007, 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. +# + +## +# Import Modules +# +import Ffs +from GenFdsGlobalVariable import GenFdsGlobalVariable +import StringIO + +## base class for capsule data +# +# +class CapsuleData: + ## The constructor + # + # @param self The object pointer + def __init__(self): + pass + + ## generate capsule data + # + # @param self The object pointer + def GenCapsuleSubItem(self): + pass + +## FFS class for capsule data +# +# +class CapsuleFfs (CapsuleData): + ## The constructor + # + # @param self The object pointer + # + def __init_(self) : + self.Ffs = None + + ## generate FFS capsule data + # + # @param self The object pointer + # @retval string Generated file name + # + def GenCapsuleSubItem(self): + FfsFile = self.Ffs.GenFfs() + return FfsFile + +## FV class for capsule data +# +# +class CapsuleFv (CapsuleData): + ## The constructor + # + # @param self The object pointer + # + def __init__(self) : + self.FvName = None + + ## generate FV capsule data + # + # @param self The object pointer + # @retval string Generated file name + # + def GenCapsuleSubItem(self): + if self.FvName.find('.fv') == -1: + if self.FvName.upper() in GenFdsGlobalVariable.FdfParser.Profile.FvDict.keys(): + FvObj = GenFdsGlobalVariable.FdfParser.Profile.FvDict.get(self.FvName.upper()) + FdBuffer = StringIO.StringIO('') + FvFile = FvObj.AddToBuffer(FdBuffer) + return FvFile + + else: + FvFile = GenFdsGlobalVariable.ReplaceWorkspaceMacro(self.FvName) + return FvFile diff --git a/BaseTools/Source/Python/GenFds/ComponentStatement.py b/BaseTools/Source/Python/GenFds/ComponentStatement.py new file mode 100644 index 0000000000..8a7540fe25 --- /dev/null +++ b/BaseTools/Source/Python/GenFds/ComponentStatement.py @@ -0,0 +1,29 @@ +## @file +# VTF components +# +# Copyright (c) 2007, 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. +# + +## +# Import Modules +# +from CommonDataClass.FdfClass import ComponentStatementClassObject + +## VTF components +# +# +class ComponentStatement (ComponentStatementClassObject) : + ## The constructor + # + # @param self The object pointer + # + def __init__(self): + ComponentStatementClassObject.__init__(self) diff --git a/BaseTools/Source/Python/GenFds/CompressSection.py b/BaseTools/Source/Python/GenFds/CompressSection.py new file mode 100644 index 0000000000..4a32ea4458 --- /dev/null +++ b/BaseTools/Source/Python/GenFds/CompressSection.py @@ -0,0 +1,87 @@ +## @file +# process compress section generation +# +# Copyright (c) 2007, 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. +# + +## +# Import Modules +# +from Ffs import Ffs +import Section +import subprocess +import os +from GenFdsGlobalVariable import GenFdsGlobalVariable +from CommonDataClass.FdfClass import CompressSectionClassObject + +## generate compress section +# +# +class CompressSection (CompressSectionClassObject) : + + ## compress types: PI standard and non PI standard + CompTypeDict = { + 'PI_STD' : 'PI_STD', + 'NON_PI_STD' : 'NON_PI_STD' + } + + ## The constructor + # + # @param self The object pointer + # + def __init__(self): + CompressSectionClassObject.__init__(self) + + ## GenSection() method + # + # Generate compressed section + # + # @param self The object pointer + # @param OutputPath Where to place output file + # @param ModuleName Which module this section belongs to + # @param SecNum Index of section + # @param KeyStringList Filter for inputs of section generation + # @param FfsInf FfsInfStatement object that contains this section data + # @param Dict dictionary contains macro and its value + # @retval tuple (Generated file name, section alignment) + # + def GenSection(self, OutputPath, ModuleName, SecNum, KeyStringList, FfsInf = None, Dict = {}): + + if FfsInf != None: + self.CompType = FfsInf.__ExtendMacro__(self.CompType) + self.Alignment = FfsInf.__ExtendMacro__(self.Alignment) + + SectFiles = tuple() + Index = 0 + for Sect in self.SectionList: + Index = Index + 1 + SecIndex = '%s.%d' %(SecNum, Index) + ReturnSectList, AlignValue = Sect.GenSection(OutputPath, ModuleName, SecIndex, KeyStringList, FfsInf, Dict) + if ReturnSectList != []: + for FileData in ReturnSectList: + SectFiles += (FileData,) + + + OutputFile = OutputPath + \ + os.sep + \ + ModuleName + \ + 'SEC' + \ + SecNum + \ + Ffs.SectionSuffix['COMPRESS'] + OutputFile = os.path.normpath(OutputFile) + + GenFdsGlobalVariable.GenerateSection(OutputFile, SectFiles, Section.Section.SectionType['COMPRESS'], + CompressionType=self.CompTypeDict[self.CompType]) + OutputFileList = [] + OutputFileList.append(OutputFile) + return OutputFileList, self.Alignment + + diff --git a/BaseTools/Source/Python/GenFds/DataSection.py b/BaseTools/Source/Python/GenFds/DataSection.py new file mode 100644 index 0000000000..7f24b51fc3 --- /dev/null +++ b/BaseTools/Source/Python/GenFds/DataSection.py @@ -0,0 +1,109 @@ +## @file +# process data section generation +# +# Copyright (c) 2007, 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. +# + +## +# Import Modules +# +import Section +from GenFdsGlobalVariable import GenFdsGlobalVariable +import subprocess +from Ffs import Ffs +import os +from CommonDataClass.FdfClass import DataSectionClassObject +import shutil + +## generate data section +# +# +class DataSection (DataSectionClassObject): + ## The constructor + # + # @param self The object pointer + # + def __init__(self): + DataSectionClassObject.__init__(self) + + ## GenSection() method + # + # Generate compressed section + # + # @param self The object pointer + # @param OutputPath Where to place output file + # @param ModuleName Which module this section belongs to + # @param SecNum Index of section + # @param KeyStringList Filter for inputs of section generation + # @param FfsInf FfsInfStatement object that contains this section data + # @param Dict dictionary contains macro and its value + # @retval tuple (Generated file name list, section alignment) + # + def GenSection(self, OutputPath, ModuleName, SecNum, keyStringList, FfsFile = None, Dict = {}): + # + # Prepare the parameter of GenSection + # + if FfsFile != None: + self.SectFileName = GenFdsGlobalVariable.ReplaceWorkspaceMacro(self.SectFileName) + self.SectFileName = GenFdsGlobalVariable.MacroExtend(self.SectFileName, Dict, FfsFile.CurrentArch) + else: + self.SectFileName = GenFdsGlobalVariable.ReplaceWorkspaceMacro(self.SectFileName) + self.SectFileName = GenFdsGlobalVariable.MacroExtend(self.SectFileName, Dict) + + """Check Section file exist or not !""" + + if not os.path.exists(self.SectFileName): + self.SectFileName = os.path.join (GenFdsGlobalVariable.WorkSpaceDir, + self.SectFileName) + + """Copy Map file to Ffs output""" + Filename = GenFdsGlobalVariable.MacroExtend(self.SectFileName) + if Filename[(len(Filename)-4):] == '.efi': + MapFile = Filename.replace('.efi', '.map') + if os.path.exists(MapFile): + CopyMapFile = os.path.join(OutputPath, ModuleName + '.map') + if not os.path.exists(CopyMapFile) or \ + (os.path.getmtime(MapFile) > os.path.getmtime(CopyMapFile)): + shutil.copyfile(MapFile, CopyMapFile) + + NoStrip = True + if self.SecType in ('TE', 'PE32'): + if self.KeepReloc != None: + NoStrip = self.KeepReloc + + if not NoStrip: + FileBeforeStrip = os.path.join(OutputPath, ModuleName + '.efi') + if not os.path.exists(FileBeforeStrip) or \ + (os.path.getmtime(self.SectFileName) > os.path.getmtime(FileBeforeStrip)): + shutil.copyfile(self.SectFileName, FileBeforeStrip) + StrippedFile = os.path.join(OutputPath, ModuleName + '.stripped') + GenFdsGlobalVariable.GenerateFirmwareImage( + StrippedFile, + [GenFdsGlobalVariable.MacroExtend(self.SectFileName, Dict)], + Strip=True + ) + self.SectFileName = StrippedFile + + if self.SecType == 'TE': + TeFile = os.path.join( OutputPath, ModuleName + 'Te.raw') + GenFdsGlobalVariable.GenerateFirmwareImage( + TeFile, + [GenFdsGlobalVariable.MacroExtend(self.SectFileName, Dict)], + Type='te' + ) + self.SectFileName = TeFile + + OutputFile = os.path.join (OutputPath, ModuleName + 'SEC' + SecNum + Ffs.SectionSuffix.get(self.SecType)) + OutputFile = os.path.normpath(OutputFile) + + GenFdsGlobalVariable.GenerateSection(OutputFile, [self.SectFileName], Section.Section.SectionType.get(self.SecType)) + FileList = [OutputFile] + return FileList, self.Alignment diff --git a/BaseTools/Source/Python/GenFds/DepexSection.py b/BaseTools/Source/Python/GenFds/DepexSection.py new file mode 100644 index 0000000000..1c8c82a72e --- /dev/null +++ b/BaseTools/Source/Python/GenFds/DepexSection.py @@ -0,0 +1,102 @@ +## @file +# process depex section generation +# +# Copyright (c) 2007, 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. +# + +## +# Import Modules +# +import Section +from GenFdsGlobalVariable import GenFdsGlobalVariable +import subprocess +from Ffs import Ffs +import os +from CommonDataClass.FdfClass import DepexSectionClassObject +from AutoGen.GenDepex import DependencyExpression +import shutil +from Common import EdkLogger +from Common.BuildToolError import * + +## generate data section +# +# +class DepexSection (DepexSectionClassObject): + ## The constructor + # + # @param self The object pointer + # + def __init__(self): + DepexSectionClassObject.__init__(self) + + def __FindGuidValue(self, CName): + for Arch in GenFdsGlobalVariable.ArchList: + for PkgDb in GenFdsGlobalVariable.WorkSpace.PackageList: + if CName in PkgDb.Ppis: + return PkgDb.Ppis[CName] + if CName in PkgDb.Protocols: + return PkgDb.Protocols[CName] + if CName in PkgDb.Guids: + return PkgDb.Guids[CName] + return None + + ## GenSection() method + # + # Generate compressed section + # + # @param self The object pointer + # @param OutputPath Where to place output file + # @param ModuleName Which module this section belongs to + # @param SecNum Index of section + # @param KeyStringList Filter for inputs of section generation + # @param FfsInf FfsInfStatement object that contains this section data + # @param Dict dictionary contains macro and its value + # @retval tuple (Generated file name list, section alignment) + # + def GenSection(self, OutputPath, ModuleName, SecNum, keyStringList, FfsFile = None, Dict = {}): + + self.Expression = self.Expression.replace("\n", " ").replace("\r", " ") + ExpList = self.Expression.split() + ExpGuidDict = {} + + for Exp in ExpList: + if Exp.upper() not in ('AND', 'OR', 'NOT', 'TRUE', 'FALSE', 'SOR', 'BEFORE', 'AFTER', 'END'): + GuidStr = self.__FindGuidValue(Exp) + if GuidStr == None: + EdkLogger.error("GenFds", RESOURCE_NOT_AVAILABLE, + "Depex GUID %s could not be found in build DB! (ModuleName: %s)" % (Exp, ModuleName)) + + ExpGuidDict[Exp] = GuidStr + + for Item in ExpGuidDict: + self.Expression = self.Expression.replace(Item, ExpGuidDict[Item]) + + self.Expression = self.Expression.strip() + ModuleType = (self.DepexType.startswith('PEI') and ['PEIM'] or ['DXE_DRIVER'])[0] + if self.DepexType.startswith('SMM'): + ModuleType = 'SMM_DRIVER' + InputFile = os.path.join (OutputPath, ModuleName + 'SEC' + SecNum + '.dpx') + InputFile = os.path.normpath(InputFile) + + Dpx = DependencyExpression(self.Expression, ModuleType) + Dpx.Generate(InputFile) + + OutputFile = os.path.join (OutputPath, ModuleName + 'SEC' + SecNum + '.depex') + if self.DepexType.startswith('SMM'): + OutputFile = os.path.join (OutputPath, ModuleName + 'SEC' + SecNum + '.smm') + OutputFile = os.path.normpath(OutputFile) + SecType = (self.DepexType.startswith('PEI') and ['PEI_DEPEX'] or ['DXE_DEPEX'])[0] + if self.DepexType.startswith('SMM'): + SecType = 'SMM_DEPEX' + + GenFdsGlobalVariable.GenerateSection(OutputFile, [InputFile], Section.Section.SectionType.get (SecType)) + FileList = [OutputFile] + return FileList, self.Alignment diff --git a/BaseTools/Source/Python/GenFds/EfiSection.py b/BaseTools/Source/Python/GenFds/EfiSection.py new file mode 100644 index 0000000000..2c112ed5cb --- /dev/null +++ b/BaseTools/Source/Python/GenFds/EfiSection.py @@ -0,0 +1,262 @@ +## @file +# process rule section generation +# +# Copyright (c) 2007, 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. +# + +## +# Import Modules +# +import Section +from GenFdsGlobalVariable import GenFdsGlobalVariable +import subprocess +from Ffs import Ffs +import os +from CommonDataClass.FdfClass import EfiSectionClassObject +import shutil +from Common import EdkLogger +from Common.BuildToolError import * + +## generate rule section +# +# +class EfiSection (EfiSectionClassObject): + + ## The constructor + # + # @param self The object pointer + # + def __init__(self): + EfiSectionClassObject.__init__(self) + + ## GenSection() method + # + # Generate rule section + # + # @param self The object pointer + # @param OutputPath Where to place output file + # @param ModuleName Which module this section belongs to + # @param SecNum Index of section + # @param KeyStringList Filter for inputs of section generation + # @param FfsInf FfsInfStatement object that contains this section data + # @param Dict dictionary contains macro and its value + # @retval tuple (Generated file name list, section alignment) + # + def GenSection(self, OutputPath, ModuleName, SecNum, KeyStringList, FfsInf = None, Dict = {}) : + + if self.FileName != None and self.FileName.startswith('PCD('): + self.FileName = GenFdsGlobalVariable.GetPcdValue(self.FileName) + """Prepare the parameter of GenSection""" + if FfsInf != None : + InfFileName = FfsInf.InfFileName + SectionType = FfsInf.__ExtendMacro__(self.SectionType) + Filename = FfsInf.__ExtendMacro__(self.FileName) + BuildNum = FfsInf.__ExtendMacro__(self.BuildNum) + StringData = FfsInf.__ExtendMacro__(self.StringData) + NoStrip = True + if FfsInf.ModuleType in ('SEC', 'PEI_CORE', 'PEIM') and SectionType in ('TE', 'PE32'): + if FfsInf.KeepReloc != None: + NoStrip = FfsInf.KeepReloc + elif FfsInf.KeepRelocFromRule != None: + NoStrip = FfsInf.KeepRelocFromRule + elif self.KeepReloc != None: + NoStrip = self.KeepReloc + elif FfsInf.ShadowFromInfFile != None: + NoStrip = FfsInf.ShadowFromInfFile + else: + EdkLogger.error("GenFds", GENFDS_ERROR, "Module %s apply rule for None!" %ModuleName) + + """If the file name was pointed out, add it in FileList""" + FileList = [] + if Filename != None: + Filename = GenFdsGlobalVariable.MacroExtend(Filename, Dict) + if not self.Optional: + FileList.append(Filename) + elif os.path.exists(Filename): + FileList.append(Filename) + else: + FileList, IsSect = Section.Section.GetFileList(FfsInf, self.FileType, self.FileExtension, Dict) + if IsSect : + return FileList, self.Alignment + + Index = 0 + + """ If Section type is 'VERSION'""" + OutputFileList = [] + if SectionType == 'VERSION': + + InfOverrideVerString = False + if FfsInf.Version != None: + #StringData = FfsInf.Version + BuildNum = FfsInf.Version + InfOverrideVerString = True + + if InfOverrideVerString: + #VerTuple = ('-n', '"' + StringData + '"') + if BuildNum != None and BuildNum != '': + BuildNumTuple = ('-j', BuildNum) + else: + BuildNumTuple = tuple() + + Num = SecNum + OutputFile = os.path.join( OutputPath, ModuleName + 'SEC' + str(Num) + Ffs.SectionSuffix.get(SectionType)) + GenFdsGlobalVariable.GenerateSection(OutputFile, [], 'EFI_SECTION_VERSION', + #Ui=StringData, + Ver=BuildNum) + OutputFileList.append(OutputFile) + + elif FileList != []: + for File in FileList: + Index = Index + 1 + Num = '%s.%d' %(SecNum , Index) + OutputFile = os.path.join(OutputPath, ModuleName + 'SEC' + Num + Ffs.SectionSuffix.get(SectionType)) + f = open(File, 'r') + VerString = f.read() + f.close() +# VerTuple = ('-n', '"' + VerString + '"') + BuildNum = VerString + if BuildNum != None and BuildNum != '': + BuildNumTuple = ('-j', BuildNum) + GenFdsGlobalVariable.GenerateSection(OutputFile, [], 'EFI_SECTION_VERSION', + #Ui=VerString, + Ver=BuildNum) + OutputFileList.append(OutputFile) + + else: +# if StringData != None and len(StringData) > 0: +# VerTuple = ('-n', '"' + StringData + '"') +# else: +# VerTuple = tuple() +# VerString = ' ' + ' '.join(VerTuple) + BuildNum = StringData + if BuildNum != None and BuildNum != '': + BuildNumTuple = ('-j', BuildNum) + else: + BuildNumTuple = tuple() + BuildNumString = ' ' + ' '.join(BuildNumTuple) + + #if VerString == '' and + if BuildNumString == '': + if self.Optional == True : + GenFdsGlobalVariable.VerboseLogger( "Optional Section don't exist!") + return [], None + else: + EdkLogger.error("GenFds", GENFDS_ERROR, "File: %s miss Version Section value" %InfFileName) + Num = SecNum + OutputFile = os.path.join( OutputPath, ModuleName + 'SEC' + str(Num) + Ffs.SectionSuffix.get(SectionType)) + GenFdsGlobalVariable.GenerateSection(OutputFile, [], 'EFI_SECTION_VERSION', + #Ui=VerString, + Ver=BuildNum) + OutputFileList.append(OutputFile) + + # + # If Section Type is 'UI' + # + elif SectionType == 'UI': + + InfOverrideUiString = False + if FfsInf.Ui != None: + StringData = FfsInf.Ui + InfOverrideUiString = True + + if InfOverrideUiString: + Num = SecNum + OutputFile = os.path.join( OutputPath, ModuleName + 'SEC' + str(Num) + Ffs.SectionSuffix.get(SectionType)) + GenFdsGlobalVariable.GenerateSection(OutputFile, [], 'EFI_SECTION_USER_INTERFACE', + Ui=StringData) + OutputFileList.append(OutputFile) + + elif FileList != []: + for File in FileList: + Index = Index + 1 + Num = '%s.%d' %(SecNum , Index) + OutputFile = os.path.join(OutputPath, ModuleName + 'SEC' + Num + Ffs.SectionSuffix.get(SectionType)) + f = open(File, 'r') + UiString = f.read() + f.close() + GenFdsGlobalVariable.GenerateSection(OutputFile, [], 'EFI_SECTION_USER_INTERFACE', + Ui=UiString) + OutputFileList.append(OutputFile) + else: + if StringData != None and len(StringData) > 0: + UiTuple = ('-n', '"' + StringData + '"') + else: + UiTuple = tuple() + + if self.Optional == True : + GenFdsGlobalVariable.VerboseLogger( "Optional Section don't exist!") + return '', None + else: + EdkLogger.error("GenFds", GENFDS_ERROR, "File: %s miss UI Section value" %InfFileName) + + Num = SecNum + OutputFile = os.path.join( OutputPath, ModuleName + 'SEC' + str(Num) + Ffs.SectionSuffix.get(SectionType)) + GenFdsGlobalVariable.GenerateSection(OutputFile, [], 'EFI_SECTION_USER_INTERFACE', + Ui=StringData) + OutputFileList.append(OutputFile) + + + else: + """If File List is empty""" + if FileList == [] : + if self.Optional == True: + GenFdsGlobalVariable.VerboseLogger( "Optional Section don't exist!") + return [], None + else: + EdkLogger.error("GenFds", GENFDS_ERROR, "Output file for %s section could not be found for %s" % (SectionType, InfFileName)) + + else: + """Convert the File to Section file one by one """ + for File in FileList: + """ Copy Map file to FFS output path """ + Index = Index + 1 + Num = '%s.%d' %(SecNum , Index) + OutputFile = os.path.join( OutputPath, ModuleName + 'SEC' + Num + Ffs.SectionSuffix.get(SectionType)) + File = GenFdsGlobalVariable.MacroExtend(File, Dict) + if File[(len(File)-4):] == '.efi': + MapFile = File.replace('.efi', '.map') + if os.path.exists(MapFile): + CopyMapFile = os.path.join(OutputPath, ModuleName + '.map') + if not os.path.exists(CopyMapFile) or \ + (os.path.getmtime(MapFile) > os.path.getmtime(CopyMapFile)): + shutil.copyfile(MapFile, CopyMapFile) + + if not NoStrip: + FileBeforeStrip = os.path.join(OutputPath, ModuleName + '.efi') + if not os.path.exists(FileBeforeStrip) or \ + (os.path.getmtime(File) > os.path.getmtime(FileBeforeStrip)): + shutil.copyfile(File, FileBeforeStrip) + StrippedFile = os.path.join(OutputPath, ModuleName + '.stripped') + GenFdsGlobalVariable.GenerateFirmwareImage( + StrippedFile, + [GenFdsGlobalVariable.MacroExtend(File, Dict)], + Strip=True + ) + File = StrippedFile + """For TE Section call GenFw to generate TE image""" + + if SectionType == 'TE': + TeFile = os.path.join( OutputPath, ModuleName + 'Te.raw') + GenFdsGlobalVariable.GenerateFirmwareImage( + TeFile, + [GenFdsGlobalVariable.MacroExtend(File, Dict)], + Type='te' + ) + File = TeFile + + """Call GenSection""" + GenFdsGlobalVariable.GenerateSection(OutputFile, + [GenFdsGlobalVariable.MacroExtend(File)], + Section.Section.SectionType.get (SectionType) + ) + OutputFileList.append(OutputFile) + + return OutputFileList, self.Alignment diff --git a/BaseTools/Source/Python/GenFds/Fd.py b/BaseTools/Source/Python/GenFds/Fd.py new file mode 100644 index 0000000000..99baa6abe5 --- /dev/null +++ b/BaseTools/Source/Python/GenFds/Fd.py @@ -0,0 +1,169 @@ +## @file +# process FD generation +# +# Copyright (c) 2007, 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. +# + +## +# Import Modules +# +import Region +import Fv +import os +import StringIO +import sys +from struct import * +from GenFdsGlobalVariable import GenFdsGlobalVariable +from CommonDataClass.FdfClass import FDClassObject +from Common import EdkLogger +from Common.BuildToolError import * +from Common.Misc import SaveFileOnChange + +## generate FD +# +# +class FD(FDClassObject): + ## The constructor + # + # @param self The object pointer + # + def __init__(self): + FDClassObject.__init__(self) + + ## GenFd() method + # + # Generate FD + # + # @param self The object pointer + # @param FvBinDict dictionary contains generated FV name and its file name + # @retval string Generated FD file name + # + def GenFd (self, FvBinDict): + # + # Print Information + # + GenFdsGlobalVariable.InfLogger("Fd File Name:%s" %self.FdUiName) + Offset = 0x00 + for item in self.BlockSizeList: + Offset = Offset + item[0] * item[1] + if Offset != self.Size: + EdkLogger.error("GenFds", GENFDS_ERROR, 'FD %s Size not consistent with block array' % self.FdUiName) + GenFdsGlobalVariable.VerboseLogger('Following Fv will be add to Fd !!!') + for FvObj in GenFdsGlobalVariable.FdfParser.Profile.FvDict: + GenFdsGlobalVariable.VerboseLogger(FvObj) + + GenFdsGlobalVariable.VerboseLogger('################### Gen VTF ####################') + self.GenVtfFile() + + FdBuffer = StringIO.StringIO('') + PreviousRegionStart = -1 + PreviousRegionSize = 1 + for RegionObj in self.RegionList : + if RegionObj.Offset + RegionObj.Size <= PreviousRegionStart: + EdkLogger.error("GenFds", GENFDS_ERROR, + 'Region offset 0x%X in wrong order with Region starting from 0x%X, size 0x%X\nRegions in FDF must have offsets appear in ascending order.'\ + % (RegionObj.Offset, PreviousRegionStart, PreviousRegionSize)) + elif RegionObj.Offset <= PreviousRegionStart or (RegionObj.Offset >=PreviousRegionStart and RegionObj.Offset < PreviousRegionStart + PreviousRegionSize): + EdkLogger.error("GenFds", GENFDS_ERROR, + 'Region offset 0x%X overlaps with Region starting from 0x%X, size 0x%X' \ + % (RegionObj.Offset, PreviousRegionStart, PreviousRegionSize)) + elif RegionObj.Offset > PreviousRegionStart + PreviousRegionSize: + GenFdsGlobalVariable.InfLogger('Padding region starting from offset 0x%X, with size 0x%X' %(PreviousRegionStart + PreviousRegionSize, RegionObj.Offset - (PreviousRegionStart + PreviousRegionSize))) + PadRegion = Region.Region() + PadRegion.Offset = PreviousRegionStart + PreviousRegionSize + PadRegion.Size = RegionObj.Offset - PadRegion.Offset + PadRegion.AddToBuffer(FdBuffer, self.BaseAddress, self.BlockSizeList, self.ErasePolarity, FvBinDict, self.vtfRawDict, self.DefineVarDict) + PreviousRegionStart = RegionObj.Offset + PreviousRegionSize = RegionObj.Size + # + # Call each region's AddToBuffer function + # + if PreviousRegionSize > self.Size: + EdkLogger.error("GenFds", GENFDS_ERROR, 'FD %s size too small' % self.FdUiName) + GenFdsGlobalVariable.VerboseLogger('Call each region\'s AddToBuffer function') + RegionObj.AddToBuffer (FdBuffer, self.BaseAddress, self.BlockSizeList, self.ErasePolarity, FvBinDict, self.vtfRawDict, self.DefineVarDict) + # + # Create a empty Fd file + # + GenFdsGlobalVariable.VerboseLogger ('Create an empty Fd file') + FdFileName = os.path.join(GenFdsGlobalVariable.FvDir, + self.FdUiName + '.fd') + #FdFile = open(FdFileName, 'wb') + + # + # Write the buffer contents to Fd file + # + GenFdsGlobalVariable.VerboseLogger('Write the buffer contents to Fd file') + SaveFileOnChange(FdFileName, FdBuffer.getvalue()) + #FdFile.write(FdBuffer.getvalue()); + #FdFile.close(); + FdBuffer.close(); + return FdFileName + + ## generate VTF + # + # @param self The object pointer + # + def GenVtfFile (self) : + # + # Get this Fd's all Fv name + # + FvAddDict ={} + FvList = [] + for RegionObj in self.RegionList: + if RegionObj.RegionType == 'FV': + if len(RegionObj.RegionDataList) == 1: + RegionData = RegionObj.RegionDataList[0] + FvList.append(RegionData.upper()) + FvAddDict[RegionData.upper()] = (int(self.BaseAddress,16) + \ + RegionObj.Offset, RegionObj.Size) + else: + Offset = RegionObj.Offset + for RegionData in RegionObj.RegionDataList: + FvList.append(RegionData.upper()) + FvObj = GenFdsGlobalVariable.FdfParser.Profile.FvDict.get(RegionData.upper()) + if len(FvObj.BlockSizeList) < 1: + EdkLogger.error("GenFds", GENFDS_ERROR, + 'FV.%s must point out FVs blocksize and Fv BlockNum' \ + % FvObj.UiFvName) + else: + Size = 0 + for blockStatement in FvObj.BlockSizeList: + Size = Size + blockStatement[0] * blockStatement[1] + FvAddDict[RegionData.upper()] = (int(self.BaseAddress,16) + \ + Offset, Size) + Offset = Offset + Size + # + # Check whether this Fd need VTF + # + Flag = False + for VtfObj in GenFdsGlobalVariable.FdfParser.Profile.VtfList: + compLocList = VtfObj.GetFvList() + if set(compLocList).issubset(FvList): + Flag = True + break + if Flag == True: + self.vtfRawDict = VtfObj.GenVtf(FvAddDict) + + ## generate flash map file + # + # @param self The object pointer + # + def GenFlashMap (self): + pass + + + + + + + + diff --git a/BaseTools/Source/Python/GenFds/FdfParser.py b/BaseTools/Source/Python/GenFds/FdfParser.py new file mode 100644 index 0000000000..0bf8f5514b --- /dev/null +++ b/BaseTools/Source/Python/GenFds/FdfParser.py @@ -0,0 +1,3778 @@ +## @file +# parse FDF file +# +# Copyright (c) 2007, 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. +# + +## +# Import Modules +# +import Fd +import Region +import Fv +import AprioriSection +import FfsInfStatement +import FfsFileStatement +import VerSection +import UiSection +import FvImageSection +import DataSection +import DepexSection +import CompressSection +import GuidSection +import Capsule +import CapsuleData +import Rule +import RuleComplexFile +import RuleSimpleFile +import EfiSection +import Vtf +import ComponentStatement +import OptionRom +import OptRomInfStatement +import OptRomFileStatement + +from Common.BuildToolError import * +from Common import EdkLogger + +import re +import os + +##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_SINGLE_QUOTE '\'' +##define T_CHAR_STAR '*' +##define T_CHAR_HASH '#' + +(T_CHAR_SPACE, T_CHAR_NULL, T_CHAR_CR, T_CHAR_TAB, T_CHAR_LF, T_CHAR_SLASH, \ +T_CHAR_BACKSLASH, T_CHAR_DOUBLE_QUOTE, T_CHAR_SINGLE_QUOTE, T_CHAR_STAR, T_CHAR_HASH) = \ +(' ', '\0', '\r', '\t', '\n', '/', '\\', '\"', '\'', '*', '#') + +SEPERATOR_TUPLE = ('=', '|', ',', '{', '}') + +IncludeFileList = [] +# Macro passed from command line, which has greatest priority and can NOT be overridden by those in FDF +InputMacroDict = {} +# All Macro values when parsing file, not replace existing Macro +AllMacroList = [] + +def GetRealFileLine (File, Line): + + InsertedLines = 0 + for Profile in IncludeFileList: + if Line >= Profile.InsertStartLineNumber and Line < Profile.InsertStartLineNumber + Profile.InsertAdjust + len(Profile.FileLinesList): + return (Profile.FileName, Line - Profile.InsertStartLineNumber + 1) + if Line >= Profile.InsertStartLineNumber + Profile.InsertAdjust + len(Profile.FileLinesList): + InsertedLines += Profile.InsertAdjust + len(Profile.FileLinesList) + + return (File, Line - InsertedLines) + +## The exception class that used to report error messages when parsing FDF +# +# Currently the "ToolName" is set to be "FDF Parser". +# +class Warning (Exception): + ## The constructor + # + # @param self The object pointer + # @param Str The message to record + # @param File The FDF name + # @param Line The Line number that error occurs + # + def __init__(self, Str, File = None, Line = None): + + FileLineTuple = GetRealFileLine(File, Line) + self.FileName = FileLineTuple[0] + self.LineNumber = FileLineTuple[1] + self.Message = Str + self.ToolName = 'FdfParser' + + def __str__(self): + return self.Message + +## The MACRO class that used to record macro value data when parsing include file +# +# +class MacroProfile : + ## The constructor + # + # @param self The object pointer + # @param FileName The file that to be parsed + # + def __init__(self, FileName, Line): + self.FileName = FileName + self.DefinedAtLine = Line + self.MacroName = None + self.MacroValue = None + +## The Include file content class that used to record file data when parsing include file +# +# May raise Exception when opening file. +# +class IncludeFileProfile : + ## The constructor + # + # @param self The object pointer + # @param FileName The file that to be parsed + # + def __init__(self, FileName): + self.FileName = FileName + self.FileLinesList = [] + try: + fsock = open(FileName, "rb", 0) + try: + self.FileLinesList = fsock.readlines() + finally: + fsock.close() + + except: + EdkLogger.error("FdfParser", FILE_OPEN_FAILURE, ExtraData=FileName) + + self.InsertStartLineNumber = None + self.InsertAdjust = 0 + +## The FDF content class that used to record file data when parsing FDF +# +# May raise Exception when opening file. +# +class FileProfile : + ## The constructor + # + # @param self The object pointer + # @param FileName The file that to be parsed + # + def __init__(self, FileName): + self.FileLinesList = [] + try: + fsock = open(FileName, "rb", 0) + try: + self.FileLinesList = fsock.readlines() + finally: + fsock.close() + + except: + EdkLogger.error("FdfParser", FILE_OPEN_FAILURE, ExtraData=FileName) + + + self.PcdDict = {} + self.InfList = [] + + self.FdDict = {} + self.FvDict = {} + self.CapsuleList = [] + self.VtfList = [] + self.RuleDict = {} + self.OptRomDict = {} + +## The syntax parser for FDF +# +# PreprocessFile method should be called prior to ParseFile +# CycleReferenceCheck method can detect cycles in FDF contents +# +# GetNext*** procedures mean these procedures will get next token first, then make judgement. +# Get*** procedures mean these procedures will make judgement on current token only. +# +class FdfParser: + ## The constructor + # + # @param self The object pointer + # @param FileName The file that to be parsed + # + def __init__(self, FileName): + self.Profile = FileProfile(FileName) + self.FileName = FileName + self.CurrentLineNumber = 1 + self.CurrentOffsetWithinLine = 0 + self.CurrentFdName = None + self.CurrentFvName = None + self.__Token = "" + self.__SkippedChars = "" + + self.__WipeOffArea = [] + + ## __IsWhiteSpace() method + # + # Whether char at current FileBufferPos is whitespace + # + # @param self The object pointer + # @param Char The char to test + # @retval True The char is a kind of white space + # @retval False The char is NOT a kind of white space + # + def __IsWhiteSpace(self, Char): + if Char in (T_CHAR_NULL, T_CHAR_CR, T_CHAR_SPACE, T_CHAR_TAB, T_CHAR_LF): + return True + else: + return False + + ## __SkipWhiteSpace() method + # + # Skip white spaces from current char, return number of chars skipped + # + # @param self The object pointer + # @retval Count The number of chars skipped + # + def __SkipWhiteSpace(self): + Count = 0 + while not self.__EndOfFile(): + Count += 1 + if self.__CurrentChar() in (T_CHAR_NULL, T_CHAR_CR, T_CHAR_LF, T_CHAR_SPACE, T_CHAR_TAB): + self.__SkippedChars += str(self.__CurrentChar()) + self.__GetOneChar() + + else: + Count = Count - 1 + return Count + + ## __EndOfFile() method + # + # Judge current buffer pos is at file end + # + # @param self The object pointer + # @retval True Current File buffer position is at file end + # @retval False Current File buffer position is NOT at file end + # + def __EndOfFile(self): + NumberOfLines = len(self.Profile.FileLinesList) + SizeOfLastLine = len(self.Profile.FileLinesList[-1]) + if self.CurrentLineNumber == NumberOfLines and self.CurrentOffsetWithinLine >= SizeOfLastLine - 1: + return True + elif self.CurrentLineNumber > NumberOfLines: + return True + else: + return False + + ## __EndOfLine() method + # + # Judge current buffer pos is at line end + # + # @param self The object pointer + # @retval True Current File buffer position is at line end + # @retval False Current File buffer position is NOT at line end + # + def __EndOfLine(self): + if self.CurrentLineNumber > len(self.Profile.FileLinesList): + return True + SizeOfCurrentLine = len(self.Profile.FileLinesList[self.CurrentLineNumber - 1]) + if self.CurrentOffsetWithinLine >= SizeOfCurrentLine: + return True + else: + return False + + ## Rewind() method + # + # Reset file data buffer to the initial state + # + # @param self The object pointer + # + def Rewind(self): + self.CurrentLineNumber = 1 + self.CurrentOffsetWithinLine = 0 + + ## __UndoOneChar() method + # + # Go back one char in the file buffer + # + # @param self The object pointer + # @retval True Successfully go back one char + # @retval False Not able to go back one char as file beginning reached + # + def __UndoOneChar(self): + + if self.CurrentLineNumber == 1 and self.CurrentOffsetWithinLine == 0: + return False + elif self.CurrentOffsetWithinLine == 0: + self.CurrentLineNumber -= 1 + self.CurrentOffsetWithinLine = len(self.__CurrentLine()) - 1 + else: + self.CurrentOffsetWithinLine -= 1 + return True + + ## __GetOneChar() method + # + # Move forward one char in the file buffer + # + # @param self The object pointer + # + def __GetOneChar(self): + if self.CurrentOffsetWithinLine == len(self.Profile.FileLinesList[self.CurrentLineNumber - 1]) - 1: + self.CurrentLineNumber += 1 + self.CurrentOffsetWithinLine = 0 + else: + self.CurrentOffsetWithinLine += 1 + + ## __CurrentChar() method + # + # Get the char pointed to by the file buffer pointer + # + # @param self The object pointer + # @retval Char Current char + # + def __CurrentChar(self): + return self.Profile.FileLinesList[self.CurrentLineNumber - 1][self.CurrentOffsetWithinLine] + + ## __NextChar() method + # + # Get the one char pass the char pointed to by the file buffer pointer + # + # @param self The object pointer + # @retval Char Next char + # + def __NextChar(self): + if self.CurrentOffsetWithinLine == len(self.Profile.FileLinesList[self.CurrentLineNumber - 1]) - 1: + return self.Profile.FileLinesList[self.CurrentLineNumber][0] + else: + return self.Profile.FileLinesList[self.CurrentLineNumber - 1][self.CurrentOffsetWithinLine + 1] + + ## __SetCurrentCharValue() method + # + # Modify the value of current char + # + # @param self The object pointer + # @param Value The new value of current char + # + def __SetCurrentCharValue(self, Value): + self.Profile.FileLinesList[self.CurrentLineNumber - 1][self.CurrentOffsetWithinLine] = Value + + ## __CurrentLine() method + # + # Get the list that contains current line contents + # + # @param self The object pointer + # @retval List current line contents + # + def __CurrentLine(self): + return self.Profile.FileLinesList[self.CurrentLineNumber - 1] + + def __StringToList(self): + self.Profile.FileLinesList = [list(s) for s in self.Profile.FileLinesList] + self.Profile.FileLinesList[-1].append(' ') + + def __ReplaceMacros(self, Str, File, Line): + MacroEnd = 0 + while Str.find('$(', MacroEnd) >= 0: + MacroStart = Str.find('$(', MacroEnd) + if Str.find(')', MacroStart) > 0: + MacroEnd = Str.find(')', MacroStart) + Name = Str[MacroStart + 2 : MacroEnd] + Value = None + if Name in InputMacroDict: + Value = InputMacroDict[Name] + + else: + for Profile in AllMacroList: + if Profile.FileName == File and Profile.MacroName == Name and Profile.DefinedAtLine <= Line: + Value = Profile.MacroValue + + if Value != None: + Str = Str.replace('$(' + Name + ')', Value) + MacroEnd = MacroStart + len(Value) + + else: + raise Warning("Macro not complete", self.FileName, self.CurrentLineNumber) + return Str + + def __ReplaceFragment(self, StartPos, EndPos, Value = ' '): + if StartPos[0] == EndPos[0]: + Offset = StartPos[1] + while Offset <= EndPos[1]: + self.Profile.FileLinesList[StartPos[0]][Offset] = Value + Offset += 1 + return + + Offset = StartPos[1] + while self.Profile.FileLinesList[StartPos[0]][Offset] not in ('\r', '\n'): + self.Profile.FileLinesList[StartPos[0]][Offset] = Value + Offset += 1 + + Line = StartPos[0] + while Line < EndPos[0]: + Offset = 0 + while self.Profile.FileLinesList[Line][Offset] not in ('\r', '\n'): + self.Profile.FileLinesList[Line][Offset] = Value + Offset += 1 + Line += 1 + + Offset = 0 + while Offset <= EndPos[1]: + self.Profile.FileLinesList[EndPos[0]][Offset] = Value + Offset += 1 + + + ## PreprocessFile() method + # + # Preprocess file contents, replace comments with spaces. + # In the end, rewind the file buffer pointer to the beginning + # BUGBUG: No !include statement processing contained in this procedure + # !include statement should be expanded at the same FileLinesList[CurrentLineNumber - 1] + # + # @param self The object pointer + # + def PreprocessFile(self): + + self.Rewind() + InComment = False + DoubleSlashComment = False + HashComment = False + # HashComment in quoted string " " is ignored. + InString = False + + while not self.__EndOfFile(): + + if self.__CurrentChar() == T_CHAR_DOUBLE_QUOTE and not InComment: + InString = not InString + # meet new line, then no longer in a comment for // and '#' + if self.__CurrentChar() == T_CHAR_LF: + self.CurrentLineNumber += 1 + self.CurrentOffsetWithinLine = 0 + if InComment and DoubleSlashComment: + InComment = False + DoubleSlashComment = False + if InComment and HashComment: + InComment = False + HashComment = False + # check for */ comment end + elif InComment and not DoubleSlashComment and not HashComment and self.__CurrentChar() == T_CHAR_STAR and self.__NextChar() == T_CHAR_SLASH: + self.__SetCurrentCharValue(T_CHAR_SPACE) + self.__GetOneChar() + self.__SetCurrentCharValue(T_CHAR_SPACE) + self.__GetOneChar() + InComment = False + # set comments to spaces + elif InComment: + self.__SetCurrentCharValue(T_CHAR_SPACE) + self.__GetOneChar() + # check for // comment + elif self.__CurrentChar() == T_CHAR_SLASH and self.__NextChar() == T_CHAR_SLASH and not self.__EndOfLine(): + InComment = True + DoubleSlashComment = True + # check for '#' comment + elif self.__CurrentChar() == T_CHAR_HASH and not self.__EndOfLine() and not InString: + InComment = True + HashComment = True + # check for /* comment start + elif self.__CurrentChar() == T_CHAR_SLASH and self.__NextChar() == T_CHAR_STAR: + self.__SetCurrentCharValue( T_CHAR_SPACE) + self.__GetOneChar() + self.__SetCurrentCharValue( T_CHAR_SPACE) + self.__GetOneChar() + InComment = True + else: + self.__GetOneChar() + + # restore from ListOfList to ListOfString + self.Profile.FileLinesList = ["".join(list) for list in self.Profile.FileLinesList] + self.Rewind() + + ## PreprocessIncludeFile() method + # + # Preprocess file contents, replace !include statements with file contents. + # In the end, rewind the file buffer pointer to the beginning + # + # @param self The object pointer + # + def PreprocessIncludeFile(self): + + while self.__GetNextToken(): + + if self.__Token == '!include': + IncludeLine = self.CurrentLineNumber + IncludeOffset = self.CurrentOffsetWithinLine - len('!include') + if not self.__GetNextToken(): + raise Warning("expected include file name", self.FileName, self.CurrentLineNumber) + IncFileName = self.__Token + if not os.path.isabs(IncFileName): + if IncFileName.startswith('$(WORKSPACE)'): + Str = IncFileName.replace('$(WORKSPACE)', os.environ.get('WORKSPACE')) + if os.path.exists(Str): + if not os.path.isabs(Str): + Str = os.path.abspath(Str) + IncFileName = Str + else: + # file is in the same dir with FDF file + FullFdf = self.FileName + if not os.path.isabs(self.FileName): + FullFdf = os.path.join(os.environ.get('WORKSPACE'), self.FileName) + + IncFileName = os.path.join(os.path.dirname(FullFdf), IncFileName) + + if not os.path.exists(os.path.normpath(IncFileName)): + raise Warning("Include file not exists", self.FileName, self.CurrentLineNumber) + + IncFileProfile = IncludeFileProfile(os.path.normpath(IncFileName)) + + CurrentLine = self.CurrentLineNumber + CurrentOffset = self.CurrentOffsetWithinLine + # list index of the insertion, note that line number is 'CurrentLine + 1' + InsertAtLine = CurrentLine + IncFileProfile.InsertStartLineNumber = InsertAtLine + 1 + # deal with remaining portions after "!include filename", if exists. + if self.__GetNextToken(): + if self.CurrentLineNumber == CurrentLine: + RemainingLine = self.__CurrentLine()[CurrentOffset:] + self.Profile.FileLinesList.insert(self.CurrentLineNumber, RemainingLine) + IncFileProfile.InsertAdjust += 1 + self.CurrentLineNumber += 1 + self.CurrentOffsetWithinLine = 0 + + for Line in IncFileProfile.FileLinesList: + self.Profile.FileLinesList.insert(InsertAtLine, Line) + self.CurrentLineNumber += 1 + InsertAtLine += 1 + + IncludeFileList.append(IncFileProfile) + + # comment out the processed include file statement + TempList = list(self.Profile.FileLinesList[IncludeLine - 1]) + TempList.insert(IncludeOffset, '#') + self.Profile.FileLinesList[IncludeLine - 1] = ''.join(TempList) + + self.Rewind() + + ## PreprocessIncludeFile() method + # + # Preprocess file contents, replace !include statements with file contents. + # In the end, rewind the file buffer pointer to the beginning + # + # @param self The object pointer + # + def PreprocessConditionalStatement(self): + # IfList is a stack of if branches with elements of list [Pos, CondSatisfied, BranchDetermined] + IfList = [] + while self.__GetNextToken(): + if self.__Token == 'DEFINE': + DefineLine = self.CurrentLineNumber - 1 + DefineOffset = self.CurrentOffsetWithinLine - len('DEFINE') + if not self.__GetNextToken(): + raise Warning("expected Macro name", self.FileName, self.CurrentLineNumber) + Macro = self.__Token + if not self.__IsToken( "="): + raise Warning("expected '='", self.FileName, self.CurrentLineNumber) + + if not self.__GetNextToken(): + raise Warning("expected value", self.FileName, self.CurrentLineNumber) + + if self.__GetStringData(): + pass + Value = self.__Token + if not Macro in InputMacroDict: + FileLineTuple = GetRealFileLine(self.FileName, DefineLine + 1) + MacProfile = MacroProfile(FileLineTuple[0], FileLineTuple[1]) + MacProfile.MacroName = Macro + MacProfile.MacroValue = Value + AllMacroList.append(MacProfile) + self.__WipeOffArea.append(((DefineLine, DefineOffset), (self.CurrentLineNumber - 1, self.CurrentOffsetWithinLine - 1))) + + elif self.__Token in ('!ifdef', '!ifndef', '!if'): + IfStartPos = (self.CurrentLineNumber - 1, self.CurrentOffsetWithinLine - len(self.__Token)) + IfList.append([IfStartPos, None, None]) + CondLabel = self.__Token + + if not self.__GetNextToken(): + raise Warning("expected Macro name", self.FileName, self.CurrentLineNumber) + MacroName = self.__Token + NotFlag = False + if MacroName.startswith('!'): + NotFlag = True + MacroName = MacroName[1:] + + NotDefineFlag = False + if CondLabel == '!ifndef': + NotDefineFlag = True + if CondLabel == '!ifdef' or CondLabel == '!ifndef': + if NotFlag: + raise Warning("'NOT' operation not allowed for Macro name", self.FileName, self.CurrentLineNumber) + + if CondLabel == '!if': + + if not self.__GetNextOp(): + raise Warning("expected !endif", self.FileName, self.CurrentLineNumber) + + if self.__Token in ('!=', '==', '>', '<', '>=', '<='): + Op = self.__Token + if not self.__GetNextToken(): + raise Warning("expected value", self.FileName, self.CurrentLineNumber) + if self.__GetStringData(): + pass + MacroValue = self.__Token + ConditionSatisfied = self.__EvaluateConditional(MacroName, IfList[-1][0][0] + 1, Op, MacroValue) + if NotFlag: + ConditionSatisfied = not ConditionSatisfied + BranchDetermined = ConditionSatisfied + else: + self.CurrentOffsetWithinLine -= len(self.__Token) + ConditionSatisfied = self.__EvaluateConditional(MacroName, IfList[-1][0][0] + 1, None, 'Bool') + if NotFlag: + ConditionSatisfied = not ConditionSatisfied + BranchDetermined = ConditionSatisfied + IfList[-1] = [IfList[-1][0], ConditionSatisfied, BranchDetermined] + if ConditionSatisfied: + self.__WipeOffArea.append((IfList[-1][0], (self.CurrentLineNumber - 1, self.CurrentOffsetWithinLine - 1))) + + else: + ConditionSatisfied = self.__EvaluateConditional(MacroName, IfList[-1][0][0] + 1) + if NotDefineFlag: + ConditionSatisfied = not ConditionSatisfied + BranchDetermined = ConditionSatisfied + IfList[-1] = [IfList[-1][0], ConditionSatisfied, BranchDetermined] + if ConditionSatisfied: + self.__WipeOffArea.append((IfStartPos, (self.CurrentLineNumber - 1, self.CurrentOffsetWithinLine - 1))) + + elif self.__Token in ('!elseif', '!else'): + ElseStartPos = (self.CurrentLineNumber - 1, self.CurrentOffsetWithinLine - len(self.__Token)) + if len(IfList) <= 0: + raise Warning("Missing !if statement", self.FileName, self.CurrentLineNumber) + if IfList[-1][1]: + IfList[-1] = [ElseStartPos, False, True] + self.__WipeOffArea.append((ElseStartPos, (self.CurrentLineNumber - 1, self.CurrentOffsetWithinLine - 1))) + else: + self.__WipeOffArea.append((IfList[-1][0], ElseStartPos)) + IfList[-1] = [ElseStartPos, True, IfList[-1][2]] + if self.__Token == '!elseif': + if not self.__GetNextToken(): + raise Warning("expected Macro name", self.FileName, self.CurrentLineNumber) + MacroName = self.__Token + NotFlag = False + if MacroName.startswith('!'): + NotFlag = True + MacroName = MacroName[1:] + + if not self.__GetNextOp(): + raise Warning("expected !endif", self.FileName, self.CurrentLineNumber) + + if self.__Token in ('!=', '==', '>', '<', '>=', '<='): + Op = self.__Token + if not self.__GetNextToken(): + raise Warning("expected value", self.FileName, self.CurrentLineNumber) + if self.__GetStringData(): + pass + MacroValue = self.__Token + ConditionSatisfied = self.__EvaluateConditional(MacroName, IfList[-1][0][0] + 1, Op, MacroValue) + if NotFlag: + ConditionSatisfied = not ConditionSatisfied + + else: + self.CurrentOffsetWithinLine -= len(self.__Token) + ConditionSatisfied = self.__EvaluateConditional(MacroName, IfList[-1][0][0] + 1, None, 'Bool') + if NotFlag: + ConditionSatisfied = not ConditionSatisfied + + IfList[-1] = [IfList[-1][0], ConditionSatisfied, IfList[-1][2]] + + if IfList[-1][1]: + if IfList[-1][2]: + IfList[-1][1] = False + else: + IfList[-1][2] = True + self.__WipeOffArea.append((IfList[-1][0], (self.CurrentLineNumber - 1, self.CurrentOffsetWithinLine - 1))) + + + elif self.__Token == '!endif': + if IfList[-1][1]: + self.__WipeOffArea.append(((self.CurrentLineNumber - 1, self.CurrentOffsetWithinLine - len('!endif')), (self.CurrentLineNumber - 1, self.CurrentOffsetWithinLine - 1))) + else: + self.__WipeOffArea.append((IfList[-1][0], (self.CurrentLineNumber - 1, self.CurrentOffsetWithinLine - 1))) + + IfList.pop() + + + if len(IfList) > 0: + raise Warning("Missing !endif", self.FileName, self.CurrentLineNumber) + self.Rewind() + + def __EvaluateConditional(self, Name, Line, Op = None, Value = None): + + FileLineTuple = GetRealFileLine(self.FileName, Line) + if Name in InputMacroDict: + MacroValue = InputMacroDict[Name] + if Op == None: + if Value == 'Bool' and MacroValue == None or MacroValue.upper() == 'FALSE': + return False + return True + elif Op == '!=': + if Value != MacroValue: + return True + else: + return False + elif Op == '==': + if Value == MacroValue: + return True + else: + return False + else: + if (self.__IsHex(Value) or Value.isdigit()) and (self.__IsHex(MacroValue) or (MacroValue != None and MacroValue.isdigit())): + InputVal = long(Value, 0) + MacroVal = long(MacroValue, 0) + if Op == '>': + if MacroVal > InputVal: + return True + else: + return False + elif Op == '>=': + if MacroVal >= InputVal: + return True + else: + return False + elif Op == '<': + if MacroVal < InputVal: + return True + else: + return False + elif Op == '<=': + if MacroVal <= InputVal: + return True + else: + return False + else: + return False + else: + raise Warning("Value %s is not a number", self.FileName, Line) + + for Profile in AllMacroList: + if Profile.FileName == FileLineTuple[0] and Profile.MacroName == Name and Profile.DefinedAtLine <= FileLineTuple[1]: + if Op == None: + if Value == 'Bool' and Profile.MacroValue == None or Profile.MacroValue.upper() == 'FALSE': + return False + return True + elif Op == '!=': + if Value != Profile.MacroValue: + return True + else: + return False + elif Op == '==': + if Value == Profile.MacroValue: + return True + else: + return False + else: + if (self.__IsHex(Value) or Value.isdigit()) and (self.__IsHex(Profile.MacroValue) or (Profile.MacroValue != None and Profile.MacroValue.isdigit())): + InputVal = long(Value, 0) + MacroVal = long(Profile.MacroValue, 0) + if Op == '>': + if MacroVal > InputVal: + return True + else: + return False + elif Op == '>=': + if MacroVal >= InputVal: + return True + else: + return False + elif Op == '<': + if MacroVal < InputVal: + return True + else: + return False + elif Op == '<=': + if MacroVal <= InputVal: + return True + else: + return False + else: + return False + else: + raise Warning("Value %s is not a number", self.FileName, Line) + + return False + + ## __IsToken() method + # + # Check whether input string is found from current char position along + # If found, the string value is put into self.__Token + # + # @param self The object pointer + # @param String The string to search + # @param IgnoreCase Indicate case sensitive/non-sensitive search, default is case sensitive + # @retval True Successfully find string, file buffer pointer moved forward + # @retval False Not able to find string, file buffer pointer not changed + # + def __IsToken(self, String, IgnoreCase = False): + self.__SkipWhiteSpace() + + # Only consider the same line, no multi-line token allowed + StartPos = self.CurrentOffsetWithinLine + index = -1 + if IgnoreCase: + index = self.__CurrentLine()[self.CurrentOffsetWithinLine : ].upper().find(String.upper()) + else: + index = self.__CurrentLine()[self.CurrentOffsetWithinLine : ].find(String) + if index == 0: + self.CurrentOffsetWithinLine += len(String) + self.__Token = self.__CurrentLine()[StartPos : self.CurrentOffsetWithinLine] + return True + return False + + ## __IsKeyword() method + # + # Check whether input keyword is found from current char position along, whole word only! + # If found, the string value is put into self.__Token + # + # @param self The object pointer + # @param Keyword The string to search + # @param IgnoreCase Indicate case sensitive/non-sensitive search, default is case sensitive + # @retval True Successfully find string, file buffer pointer moved forward + # @retval False Not able to find string, file buffer pointer not changed + # + def __IsKeyword(self, KeyWord, IgnoreCase = False): + self.__SkipWhiteSpace() + + # Only consider the same line, no multi-line token allowed + StartPos = self.CurrentOffsetWithinLine + index = -1 + if IgnoreCase: + index = self.__CurrentLine()[self.CurrentOffsetWithinLine : ].upper().find(KeyWord.upper()) + else: + index = self.__CurrentLine()[self.CurrentOffsetWithinLine : ].find(KeyWord) + if index == 0: + followingChar = self.__CurrentLine()[self.CurrentOffsetWithinLine + len(KeyWord)] + if not str(followingChar).isspace() and followingChar not in SEPERATOR_TUPLE: + return False + self.CurrentOffsetWithinLine += len(KeyWord) + self.__Token = self.__CurrentLine()[StartPos : self.CurrentOffsetWithinLine] + return True + return False + + ## __GetNextWord() method + # + # Get next C name from file lines + # If found, the string value is put into self.__Token + # + # @param self The object pointer + # @retval True Successfully find a C name string, file buffer pointer moved forward + # @retval False Not able to find a C name string, file buffer pointer not changed + # + def __GetNextWord(self): + self.__SkipWhiteSpace() + if self.__EndOfFile(): + return False + + TempChar = self.__CurrentChar() + StartPos = self.CurrentOffsetWithinLine + if (TempChar >= 'a' and TempChar <= 'z') or (TempChar >= 'A' and TempChar <= 'Z') or TempChar == '_': + self.__GetOneChar() + while not self.__EndOfLine(): + TempChar = self.__CurrentChar() + if (TempChar >= 'a' and TempChar <= 'z') or (TempChar >= 'A' and TempChar <= 'Z') \ + or (TempChar >= '0' and TempChar <= '9') or TempChar == '_' or TempChar == '-': + self.__GetOneChar() + + else: + break + + self.__Token = self.__CurrentLine()[StartPos : self.CurrentOffsetWithinLine] + return True + + return False + + ## __GetNextToken() method + # + # Get next token unit before a seperator + # If found, the string value is put into self.__Token + # + # @param self The object pointer + # @retval True Successfully find a token unit, file buffer pointer moved forward + # @retval False Not able to find a token unit, file buffer pointer not changed + # + def __GetNextToken(self): + # Skip leading spaces, if exist. + self.__SkipWhiteSpace() + if self.__EndOfFile(): + return False + # Record the token start position, the position of the first non-space char. + StartPos = self.CurrentOffsetWithinLine + StartLine = self.CurrentLineNumber + while not self.__EndOfLine(): + TempChar = self.__CurrentChar() + # Try to find the end char that is not a space and not in seperator tuple. + # That is, when we got a space or any char in the tuple, we got the end of token. + if not str(TempChar).isspace() and TempChar not in SEPERATOR_TUPLE: + self.__GetOneChar() + # if we happen to meet a seperator as the first char, we must proceed to get it. + # That is, we get a token that is a seperator char. nomally it is the boundary of other tokens. + elif StartPos == self.CurrentOffsetWithinLine and TempChar in SEPERATOR_TUPLE: + self.__GetOneChar() + break + else: + break +# else: +# return False + + EndPos = self.CurrentOffsetWithinLine + if self.CurrentLineNumber != StartLine: + EndPos = len(self.Profile.FileLinesList[StartLine-1]) + self.__Token = self.Profile.FileLinesList[StartLine-1][StartPos : EndPos] + if StartPos != self.CurrentOffsetWithinLine: + return True + else: + return False + + def __GetNextOp(self): + # Skip leading spaces, if exist. + self.__SkipWhiteSpace() + if self.__EndOfFile(): + return False + # Record the token start position, the position of the first non-space char. + StartPos = self.CurrentOffsetWithinLine + while not self.__EndOfLine(): + TempChar = self.__CurrentChar() + # Try to find the end char that is not a space + if not str(TempChar).isspace(): + self.__GetOneChar() + else: + break + else: + return False + + if StartPos != self.CurrentOffsetWithinLine: + self.__Token = self.__CurrentLine()[StartPos : self.CurrentOffsetWithinLine] + return True + else: + return False + ## __GetNextGuid() method + # + # Get next token unit before a seperator + # If found, the GUID string is put into self.__Token + # + # @param self The object pointer + # @retval True Successfully find a registry format GUID, file buffer pointer moved forward + # @retval False Not able to find a registry format GUID, file buffer pointer not changed + # + def __GetNextGuid(self): + + if not self.__GetNextToken(): + return False + p = re.compile('[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}') + if p.match(self.__Token) != None: + return True + else: + self.__UndoToken() + return False + + ## __UndoToken() method + # + # Go back one token unit in file buffer + # + # @param self The object pointer + # + def __UndoToken(self): + self.__UndoOneChar() + while self.__CurrentChar().isspace(): + if not self.__UndoOneChar(): + self.__GetOneChar() + return + + + StartPos = self.CurrentOffsetWithinLine + CurrentLine = self.CurrentLineNumber + while CurrentLine == self.CurrentLineNumber: + + TempChar = self.__CurrentChar() + # Try to find the end char that is not a space and not in seperator tuple. + # That is, when we got a space or any char in the tuple, we got the end of token. + if not str(TempChar).isspace() and not TempChar in SEPERATOR_TUPLE: + if not self.__UndoOneChar(): + break + # if we happen to meet a seperator as the first char, we must proceed to get it. + # That is, we get a token that is a seperator char. nomally it is the boundary of other tokens. + elif StartPos == self.CurrentOffsetWithinLine and TempChar in SEPERATOR_TUPLE: + return + else: + break + + self.__GetOneChar() + + ## __HexDigit() method + # + # Whether char input is a Hex data bit + # + # @param self The object pointer + # @param TempChar The char to test + # @retval True The char is a Hex data bit + # @retval False The char is NOT a Hex data bit + # + def __HexDigit(self, TempChar): + if (TempChar >= 'a' and TempChar <= 'f') or (TempChar >= 'A' and TempChar <= 'F') \ + or (TempChar >= '0' and TempChar <= '9'): + return True + else: + return False + + def __IsHex(self, HexStr): + if not HexStr.upper().startswith("0X"): + return False + if len(self.__Token) <= 2: + return False + charList = [c for c in HexStr[2 : ] if not self.__HexDigit( c)] + if len(charList) == 0: + return True + else: + return False + ## __GetNextHexNumber() method + # + # Get next HEX data before a seperator + # If found, the HEX data is put into self.__Token + # + # @param self The object pointer + # @retval True Successfully find a HEX data, file buffer pointer moved forward + # @retval False Not able to find a HEX data, file buffer pointer not changed + # + def __GetNextHexNumber(self): + if not self.__GetNextToken(): + return False + if self.__IsHex(self.__Token): + return True + else: + self.__UndoToken() + return False + + ## __GetNextDecimalNumber() method + # + # Get next decimal data before a seperator + # If found, the decimal data is put into self.__Token + # + # @param self The object pointer + # @retval True Successfully find a decimal data, file buffer pointer moved forward + # @retval False Not able to find a decimal data, file buffer pointer not changed + # + def __GetNextDecimalNumber(self): + if not self.__GetNextToken(): + return False + if self.__Token.isdigit(): + return True + else: + self.__UndoToken() + return False + + ## __GetNextPcdName() method + # + # Get next PCD token space C name and PCD C name pair before a seperator + # If found, the decimal data is put into self.__Token + # + # @param self The object pointer + # @retval Tuple PCD C name and PCD token space C name pair + # + def __GetNextPcdName(self): + if not self.__GetNextWord(): + raise Warning("expected format of .", self.FileName, self.CurrentLineNumber) + pcdTokenSpaceCName = self.__Token + + if not self.__IsToken( "."): + raise Warning("expected format of .", self.FileName, self.CurrentLineNumber) + + if not self.__GetNextWord(): + raise Warning("expected format of .", self.FileName, self.CurrentLineNumber) + pcdCName = self.__Token + + return (pcdCName, pcdTokenSpaceCName) + + ## __GetStringData() method + # + # Get string contents quoted in "" + # If found, the decimal data is put into self.__Token + # + # @param self The object pointer + # @retval True Successfully find a string data, file buffer pointer moved forward + # @retval False Not able to find a string data, file buffer pointer not changed + # + def __GetStringData(self): + if self.__Token.startswith("\"") or self.__Token.startswith("L\""): + self.__UndoToken() + self.__SkipToToken("\"") + currentLineNumber = self.CurrentLineNumber + + if not self.__SkipToToken("\""): + raise Warning("Missing Quote \" for String", self.FileName, self.CurrentLineNumber) + if currentLineNumber != self.CurrentLineNumber: + raise Warning("Missing Quote \" for String", self.FileName, self.CurrentLineNumber) + self.__Token = self.__SkippedChars.rstrip('\"') + return True + + elif self.__Token.startswith("\'") or self.__Token.startswith("L\'"): + self.__UndoToken() + self.__SkipToToken("\'") + currentLineNumber = self.CurrentLineNumber + + if not self.__SkipToToken("\'"): + raise Warning("Missing Quote \' for String", self.FileName, self.CurrentLineNumber) + if currentLineNumber != self.CurrentLineNumber: + raise Warning("Missing Quote \' for String", self.FileName, self.CurrentLineNumber) + self.__Token = self.__SkippedChars.rstrip('\'') + return True + + else: + return False + + ## __SkipToToken() method + # + # Search forward in file buffer for the string + # The skipped chars are put into self.__SkippedChars + # + # @param self The object pointer + # @param String The string to search + # @param IgnoreCase Indicate case sensitive/non-sensitive search, default is case sensitive + # @retval True Successfully find the string, file buffer pointer moved forward + # @retval False Not able to find the string, file buffer pointer not changed + # + def __SkipToToken(self, String, IgnoreCase = False): + StartPos = self.GetFileBufferPos() + + self.__SkippedChars = "" + while not self.__EndOfFile(): + index = -1 + if IgnoreCase: + index = self.__CurrentLine()[self.CurrentOffsetWithinLine : ].upper().find(String.upper()) + else: + index = self.__CurrentLine()[self.CurrentOffsetWithinLine : ].find(String) + if index == 0: + self.CurrentOffsetWithinLine += len(String) + self.__SkippedChars += String + return True + self.__SkippedChars += str(self.__CurrentChar()) + self.__GetOneChar() + + self.SetFileBufferPos( StartPos) + self.__SkippedChars = "" + return False + + ## GetFileBufferPos() method + # + # Return the tuple of current line and offset within the line + # + # @param self The object pointer + # @retval Tuple Line number and offset pair + # + def GetFileBufferPos(self): + return (self.CurrentLineNumber, self.CurrentOffsetWithinLine) + + ## SetFileBufferPos() method + # + # Restore the file buffer position + # + # @param self The object pointer + # @param Pos The new file buffer position + # + def SetFileBufferPos(self, Pos): + (self.CurrentLineNumber, self.CurrentOffsetWithinLine) = Pos + + ## ParseFile() method + # + # Parse the file profile buffer to extract fd, fv ... information + # Exception will be raised if syntax error found + # + # @param self The object pointer + # + def ParseFile(self): + + try: + self.__StringToList() + self.PreprocessFile() + self.PreprocessIncludeFile() + self.__StringToList() + self.PreprocessFile() + self.PreprocessConditionalStatement() + self.__StringToList() + for Pos in self.__WipeOffArea: + self.__ReplaceFragment(Pos[0], Pos[1]) + self.Profile.FileLinesList = ["".join(list) for list in self.Profile.FileLinesList] + + while self.__GetDefines(): + pass + + Index = 0 + while Index < len(self.Profile.FileLinesList): + FileLineTuple = GetRealFileLine(self.FileName, Index + 1) + self.Profile.FileLinesList[Index] = self.__ReplaceMacros(self.Profile.FileLinesList[Index], FileLineTuple[0], FileLineTuple[1]) + Index += 1 + + while self.__GetFd(): + pass + + while self.__GetFv(): + pass + + while self.__GetCapsule(): + pass + + while self.__GetVtf(): + pass + + while self.__GetRule(): + pass + + while self.__GetOptionRom(): + pass + + except Warning, X: + self.__UndoToken() + FileLineTuple = GetRealFileLine(self.FileName, self.CurrentLineNumber) + #'\n\tGot Token: \"%s\" from File %s\n' % (self.__Token, FileLineTuple[0]) + \ + X.Message += ' near line %d, column %d: %s' \ + % (FileLineTuple[1], self.CurrentOffsetWithinLine + 1, self.Profile.FileLinesList[self.CurrentLineNumber - 1][self.CurrentOffsetWithinLine :].rstrip('\n').rstrip('\r')) + raise + + ## __GetDefines() method + # + # Get Defines section contents and store its data into AllMacrosList + # + # @param self The object pointer + # @retval True Successfully find a Defines + # @retval False Not able to find a Defines + # + def __GetDefines(self): + + if not self.__GetNextToken(): + return False + + S = self.__Token.upper() + if S.startswith("[") and not S.startswith("[DEFINES"): + if not S.startswith("[FD.") and not S.startswith("[FV.") and not S.startswith("[CAPSULE.") \ + and not S.startswith("[VTF.") and not S.startswith("[RULE.") and not S.startswith("[OPTIONROM."): + raise Warning("Unknown section or section appear sequence error (The correct sequence should be [DEFINES], [FD.], [FV.], [Capsule.], [VTF.], [Rule.], [OptionRom.])", self.FileName, self.CurrentLineNumber) + self.__UndoToken() + return False + + self.__UndoToken() + if not self.__IsToken("[DEFINES", True): + FileLineTuple = GetRealFileLine(self.FileName, self.CurrentLineNumber) + #print 'Parsing String: %s in File %s, At line: %d, Offset Within Line: %d' \ + # % (self.Profile.FileLinesList[self.CurrentLineNumber - 1][self.CurrentOffsetWithinLine :], FileLineTuple[0], FileLineTuple[1], self.CurrentOffsetWithinLine) + raise Warning("expected [DEFINES", self.FileName, self.CurrentLineNumber) + + if not self.__IsToken( "]"): + raise Warning("expected ']'", self.FileName, self.CurrentLineNumber) + + while self.__GetNextWord(): + Macro = self.__Token + + if not self.__IsToken("="): + raise Warning("expected '='", self.FileName, self.CurrentLineNumber) + if not self.__GetNextToken() or self.__Token.startswith('['): + raise Warning("expected MACRO value", self.FileName, self.CurrentLineNumber) + Value = self.__Token + FileLineTuple = GetRealFileLine(self.FileName, self.CurrentLineNumber) + MacProfile = MacroProfile(FileLineTuple[0], FileLineTuple[1]) + MacProfile.MacroName = Macro + MacProfile.MacroValue = Value + AllMacroList.append(MacProfile) + + return False + + ## __GetFd() method + # + # Get FD section contents and store its data into FD dictionary of self.Profile + # + # @param self The object pointer + # @retval True Successfully find a FD + # @retval False Not able to find a FD + # + def __GetFd(self): + + if not self.__GetNextToken(): + return False + + S = self.__Token.upper() + if S.startswith("[") and not S.startswith("[FD."): + if not S.startswith("[FV.") and not S.startswith("[CAPSULE.") \ + and not S.startswith("[VTF.") and not S.startswith("[RULE.") and not S.startswith("[OPTIONROM."): + raise Warning("Unknown section", self.FileName, self.CurrentLineNumber) + self.__UndoToken() + return False + + self.__UndoToken() + if not self.__IsToken("[FD.", True): + FileLineTuple = GetRealFileLine(self.FileName, self.CurrentLineNumber) + #print 'Parsing String: %s in File %s, At line: %d, Offset Within Line: %d' \ + # % (self.Profile.FileLinesList[self.CurrentLineNumber - 1][self.CurrentOffsetWithinLine :], FileLineTuple[0], FileLineTuple[1], self.CurrentOffsetWithinLine) + raise Warning("expected [FD.]", self.FileName, self.CurrentLineNumber) + + FdName = self.__GetUiName() + self.CurrentFdName = FdName.upper() + + if not self.__IsToken( "]"): + raise Warning("expected ']'", self.FileName, self.CurrentLineNumber) + + FdObj = Fd.FD() + FdObj.FdUiName = self.CurrentFdName + self.Profile.FdDict[self.CurrentFdName] = FdObj + Status = self.__GetCreateFile(FdObj) + if not Status: + raise Warning("FD name error", self.FileName, self.CurrentLineNumber) + + if not self.__GetTokenStatements(FdObj): + return False + + self.__GetDefineStatements(FdObj) + + self.__GetSetStatements(FdObj) + + if not self.__GetRegionLayout(FdObj): + raise Warning("expected region layout", self.FileName, self.CurrentLineNumber) + + while self.__GetRegionLayout(FdObj): + pass + return True + + ## __GetUiName() method + # + # Return the UI name of a section + # + # @param self The object pointer + # @retval FdName UI name + # + def __GetUiName(self): + Name = "" + if self.__GetNextWord(): + Name = self.__Token + + return Name + + ## __GetCreateFile() method + # + # Return the output file name of object + # + # @param self The object pointer + # @param Obj object whose data will be stored in file + # @retval FdName UI name + # + def __GetCreateFile(self, Obj): + + if self.__IsKeyword( "CREATE_FILE"): + if not self.__IsToken( "="): + raise Warning("expected '='", self.FileName, self.CurrentLineNumber) + + if not self.__GetNextToken(): + raise Warning("expected file name", self.FileName, self.CurrentLineNumber) + + FileName = self.__Token + Obj.CreateFileName = FileName + + return True + + ## __GetTokenStatements() method + # + # Get token statements + # + # @param self The object pointer + # @param Obj for whom token statement is got + # @retval True Successfully find a token statement + # @retval False Not able to find a token statement + # + def __GetTokenStatements(self, Obj): + if not self.__IsKeyword( "BaseAddress"): + raise Warning("BaseAddress missing", self.FileName, self.CurrentLineNumber) + + if not self.__IsToken( "="): + raise Warning("expected '='", self.FileName, self.CurrentLineNumber) + + if not self.__GetNextHexNumber(): + raise Warning("expected Hex base address", self.FileName, self.CurrentLineNumber) + + Obj.BaseAddress = self.__Token + + if self.__IsToken( "|"): + pcdPair = self.__GetNextPcdName() + Obj.BaseAddressPcd = pcdPair + self.Profile.PcdDict[pcdPair] = Obj.BaseAddress + + if not self.__IsKeyword( "Size"): + raise Warning("Size missing", self.FileName, self.CurrentLineNumber) + + if not self.__IsToken( "="): + raise Warning("expected '='", self.FileName, self.CurrentLineNumber) + + if not self.__GetNextHexNumber(): + raise Warning("expected Hex size", self.FileName, self.CurrentLineNumber) + + + Size = self.__Token + if self.__IsToken( "|"): + pcdPair = self.__GetNextPcdName() + Obj.SizePcd = pcdPair + self.Profile.PcdDict[pcdPair] = Size + Obj.Size = long(Size, 0) + + if not self.__IsKeyword( "ErasePolarity"): + raise Warning("ErasePolarity missing", self.FileName, self.CurrentLineNumber) + + if not self.__IsToken( "="): + raise Warning("expected '='", self.FileName, self.CurrentLineNumber) + + if not self.__GetNextToken(): + raise Warning("expected Erase Polarity", self.FileName, self.CurrentLineNumber) + + if self.__Token != "1" and self.__Token != "0": + raise Warning("expected 1 or 0 Erase Polarity", self.FileName, self.CurrentLineNumber) + + Obj.ErasePolarity = self.__Token + + Status = self.__GetBlockStatements(Obj) + return Status + + ## __GetAddressStatements() method + # + # Get address statements + # + # @param self The object pointer + # @param Obj for whom address statement is got + # @retval True Successfully find + # @retval False Not able to find + # + def __GetAddressStatements(self, Obj): + + if self.__IsKeyword("BsBaseAddress"): + if not self.__IsToken( "="): + raise Warning("expected '='", self.FileName, self.CurrentLineNumber) + + if not self.__GetNextDecimalNumber() and not self.__GetNextHexNumber(): + raise Warning("expected address", self.FileName, self.CurrentLineNumber) + + BsAddress = long(self.__Token, 0) + Obj.BsBaseAddress = BsAddress + + if self.__IsKeyword("RtBaseAddress"): + if not self.__IsToken( "="): + raise Warning("expected '='", self.FileName, self.CurrentLineNumber) + + if not self.__GetNextDecimalNumber() and not self.__GetNextHexNumber(): + raise Warning("expected address", self.FileName, self.CurrentLineNumber) + + RtAddress = long(self.__Token, 0) + Obj.RtBaseAddress = RtAddress + + ## __GetBlockStatements() method + # + # Get block statements + # + # @param self The object pointer + # @param Obj for whom block statement is got + # @retval True Successfully find + # @retval False Not able to find + # + def __GetBlockStatements(self, Obj): + + if not self.__GetBlockStatement(Obj): + raise Warning("expected block statement", self.FileName, self.CurrentLineNumber) + + while self.__GetBlockStatement(Obj): + pass + return True + + ## __GetBlockStatement() method + # + # Get block statement + # + # @param self The object pointer + # @param Obj for whom block statement is got + # @retval True Successfully find + # @retval False Not able to find + # + def __GetBlockStatement(self, Obj): + if not self.__IsKeyword( "BlockSize"): + return False + + if not self.__IsToken( "="): + raise Warning("expected '='", self.FileName, self.CurrentLineNumber) + + if not self.__GetNextHexNumber() and not self.__GetNextDecimalNumber(): + raise Warning("expected Hex block size", self.FileName, self.CurrentLineNumber) + + BlockSize = self.__Token + BlockSizePcd = None + if self.__IsToken( "|"): + PcdPair = self.__GetNextPcdName() + BlockSizePcd = PcdPair + self.Profile.PcdDict[PcdPair] = BlockSize + BlockSize = long(self.__Token, 0) + + BlockNumber = None + if self.__IsKeyword( "NumBlocks"): + if not self.__IsToken( "="): + raise Warning("expected '='", self.FileName, self.CurrentLineNumber) + + if not self.__GetNextDecimalNumber() and not self.__GetNextHexNumber(): + raise Warning("expected block numbers", self.FileName, self.CurrentLineNumber) + + BlockNumber = long(self.__Token, 0) + + Obj.BlockSizeList.append((BlockSize, BlockNumber, BlockSizePcd)) + return True + + ## __GetDefineStatements() method + # + # Get define statements + # + # @param self The object pointer + # @param Obj for whom define statement is got + # @retval True Successfully find + # @retval False Not able to find + # + def __GetDefineStatements(self, Obj): + while self.__GetDefineStatement( Obj): + pass + + ## __GetDefineStatement() method + # + # Get define statement + # + # @param self The object pointer + # @param Obj for whom define statement is got + # @retval True Successfully find + # @retval False Not able to find + # + def __GetDefineStatement(self, Obj): + if self.__IsKeyword("DEFINE"): + self.__GetNextToken() + Macro = self.__Token + if not self.__IsToken( "="): + raise Warning("expected '='", self.FileName, self.CurrentLineNumber) + + if not self.__GetNextToken(): + raise Warning("expected value", self.FileName, self.CurrentLineNumber) + + Value = self.__Token + Macro = '$(' + Macro + ')' + Obj.DefineVarDict[Macro] = Value + return True + + return False + + ## __GetSetStatements() method + # + # Get set statements + # + # @param self The object pointer + # @param Obj for whom set statement is got + # @retval True Successfully find + # @retval False Not able to find + # + def __GetSetStatements(self, Obj): + while self.__GetSetStatement(Obj): + pass + + ## __GetSetStatement() method + # + # Get set statement + # + # @param self The object pointer + # @param Obj for whom set statement is got + # @retval True Successfully find + # @retval False Not able to find + # + def __GetSetStatement(self, Obj): + if self.__IsKeyword("SET"): + PcdPair = self.__GetNextPcdName() + + if not self.__IsToken( "="): + raise Warning("expected '='", self.FileName, self.CurrentLineNumber) + + if not self.__GetNextToken(): + raise Warning("expected value", self.FileName, self.CurrentLineNumber) + + Value = self.__Token + if Value.startswith("{"): + # deal with value with {} + if not self.__SkipToToken( "}"): + raise Warning("expected '}'", self.FileName, self.CurrentLineNumber) + Value += self.__SkippedChars + + Obj.SetVarDict[PcdPair] = Value + self.Profile.PcdDict[PcdPair] = Value + return True + + return False + + ## __GetRegionLayout() method + # + # Get region layout for FD + # + # @param self The object pointer + # @param Fd for whom region is got + # @retval True Successfully find + # @retval False Not able to find + # + def __GetRegionLayout(self, Fd): + if not self.__GetNextHexNumber(): + return False + + RegionObj = Region.Region() + RegionObj.Offset = long(self.__Token, 0) + Fd.RegionList.append(RegionObj) + + if not self.__IsToken( "|"): + raise Warning("expected '|'", self.FileName, self.CurrentLineNumber) + + if not self.__GetNextHexNumber(): + raise Warning("expected Region Size", self.FileName, self.CurrentLineNumber) + RegionObj.Size = long(self.__Token, 0) + + if not self.__GetNextWord(): + return True + + if not self.__Token in ("SET", "FV", "FILE", "DATA"): + self.__UndoToken() + RegionObj.PcdOffset = self.__GetNextPcdName() + self.Profile.PcdDict[RegionObj.PcdOffset] = "0x%08X" % (RegionObj.Offset + long(Fd.BaseAddress, 0)) + if self.__IsToken( "|"): + RegionObj.PcdSize = self.__GetNextPcdName() + self.Profile.PcdDict[RegionObj.PcdSize] = "0x%08X" % RegionObj.Size + + if not self.__GetNextWord(): + return True + + if self.__Token == "SET": + self.__UndoToken() + self.__GetSetStatements( RegionObj) + if not self.__GetNextWord(): + return True + + if self.__Token == "FV": + self.__UndoToken() + self.__GetRegionFvType( RegionObj) + + elif self.__Token == "FILE": + self.__UndoToken() + self.__GetRegionFileType( RegionObj) + + else: + self.__UndoToken() + self.__GetRegionDataType( RegionObj) + + return True + + ## __GetRegionFvType() method + # + # Get region fv data for region + # + # @param self The object pointer + # @param RegionObj for whom region data is got + # + def __GetRegionFvType(self, RegionObj): + + if not self.__IsKeyword( "FV"): + raise Warning("expected Keyword 'FV'", self.FileName, self.CurrentLineNumber) + + if not self.__IsToken( "="): + raise Warning("expected '='", self.FileName, self.CurrentLineNumber) + + if not self.__GetNextToken(): + raise Warning("expected FV name", self.FileName, self.CurrentLineNumber) + + RegionObj.RegionType = "FV" + RegionObj.RegionDataList.append(self.__Token) + + while self.__IsKeyword( "FV"): + + if not self.__IsToken( "="): + raise Warning("expected '='", self.FileName, self.CurrentLineNumber) + + if not self.__GetNextToken(): + raise Warning("expected FV name", self.FileName, self.CurrentLineNumber) + + RegionObj.RegionDataList.append(self.__Token) + + ## __GetRegionFileType() method + # + # Get region file data for region + # + # @param self The object pointer + # @param RegionObj for whom region data is got + # + def __GetRegionFileType(self, RegionObj): + + if not self.__IsKeyword( "FILE"): + raise Warning("expected Keyword 'FILE'", self.FileName, self.CurrentLineNumber) + + if not self.__IsToken( "="): + raise Warning("expected '='", self.FileName, self.CurrentLineNumber) + + if not self.__GetNextToken(): + raise Warning("expected File name", self.FileName, self.CurrentLineNumber) + + RegionObj.RegionType = "FILE" + RegionObj.RegionDataList.append( self.__Token) + + while self.__IsKeyword( "FILE"): + + if not self.__IsToken( "="): + raise Warning("expected '='", self.FileName, self.CurrentLineNumber) + + if not self.__GetNextToken(): + raise Warning("expected FILE name", self.FileName, self.CurrentLineNumber) + + RegionObj.RegionDataList.append(self.__Token) + + ## __GetRegionDataType() method + # + # Get region array data for region + # + # @param self The object pointer + # @param RegionObj for whom region data is got + # + def __GetRegionDataType(self, RegionObj): + + if not self.__IsKeyword( "DATA"): + raise Warning("expected Region Data type", self.FileName, self.CurrentLineNumber) + + if not self.__IsToken( "="): + raise Warning("expected '='", self.FileName, self.CurrentLineNumber) + + if not self.__IsToken( "{"): + raise Warning("expected '{'", self.FileName, self.CurrentLineNumber) + + if not self.__GetNextHexNumber(): + raise Warning("expected Hex byte", self.FileName, self.CurrentLineNumber) + + if len(self.__Token) > 4: + raise Warning("Hex byte(must be 2 digits) too long", self.FileName, self.CurrentLineNumber) + + DataString = self.__Token + DataString += "," + + while self.__IsToken(","): + if not self.__GetNextHexNumber(): + raise Warning("Invalid Hex number", self.FileName, self.CurrentLineNumber) + if len(self.__Token) > 4: + raise Warning("Hex byte(must be 2 digits) too long", self.FileName, self.CurrentLineNumber) + DataString += self.__Token + DataString += "," + + if not self.__IsToken( "}"): + raise Warning("expected '}'", self.FileName, self.CurrentLineNumber) + + DataString = DataString.rstrip(",") + RegionObj.RegionType = "DATA" + RegionObj.RegionDataList.append( DataString) + + while self.__IsKeyword( "DATA"): + + if not self.__IsToken( "="): + raise Warning("expected '='", self.FileName, self.CurrentLineNumber) + + if not self.__IsToken( "{"): + raise Warning("expected '{'", self.FileName, self.CurrentLineNumber) + + if not self.__GetNextHexNumber(): + raise Warning("expected Hex byte", self.FileName, self.CurrentLineNumber) + + if len(self.__Token) > 4: + raise Warning("Hex byte(must be 2 digits) too long", self.FileName, self.CurrentLineNumber) + + DataString = self.__Token + DataString += "," + + while self.__IsToken(","): + self.__GetNextHexNumber() + if len(self.__Token) > 4: + raise Warning("Hex byte(must be 2 digits) too long", self.FileName, self.CurrentLineNumber) + DataString += self.__Token + DataString += "," + + if not self.__IsToken( "}"): + raise Warning("expected '}'", self.FileName, self.CurrentLineNumber) + + DataString = DataString.rstrip(",") + RegionObj.RegionDataList.append( DataString) + + ## __GetFv() method + # + # Get FV section contents and store its data into FV dictionary of self.Profile + # + # @param self The object pointer + # @retval True Successfully find a FV + # @retval False Not able to find a FV + # + def __GetFv(self): + if not self.__GetNextToken(): + return False + + S = self.__Token.upper() + if S.startswith("[") and not S.startswith("[FV."): + if not S.startswith("[CAPSULE.") \ + and not S.startswith("[VTF.") and not S.startswith("[RULE.") and not S.startswith("[OPTIONROM."): + raise Warning("Unknown section or section appear sequence error (The correct sequence should be [FD.], [FV.], [Capsule.], [VTF.], [Rule.], [OptionRom.])", self.FileName, self.CurrentLineNumber) + self.__UndoToken() + return False + + self.__UndoToken() + if not self.__IsToken("[FV.", True): + FileLineTuple = GetRealFileLine(self.FileName, self.CurrentLineNumber) + #print 'Parsing String: %s in File %s, At line: %d, Offset Within Line: %d' \ + # % (self.Profile.FileLinesList[self.CurrentLineNumber - 1][self.CurrentOffsetWithinLine :], FileLineTuple[0], FileLineTuple[1], self.CurrentOffsetWithinLine) + raise Warning("Unknown Keyword '%s'" % self.__Token, self.FileName, self.CurrentLineNumber) + + FvName = self.__GetUiName() + self.CurrentFvName = FvName.upper() + + if not self.__IsToken( "]"): + raise Warning("expected ']'", self.FileName, self.CurrentLineNumber) + + FvObj = Fv.FV() + FvObj.UiFvName = self.CurrentFvName + self.Profile.FvDict[self.CurrentFvName] = FvObj + + Status = self.__GetCreateFile(FvObj) + if not Status: + raise Warning("FV name error", self.FileName, self.CurrentLineNumber) + + self.__GetDefineStatements(FvObj) + + self.__GetAddressStatements(FvObj) + + self.__GetBlockStatement(FvObj) + + self.__GetSetStatements(FvObj) + + self.__GetFvAlignment(FvObj) + + self.__GetFvAttributes(FvObj) + + self.__GetFvNameGuid(FvObj) + + self.__GetAprioriSection(FvObj, FvObj.DefineVarDict.copy()) + self.__GetAprioriSection(FvObj, FvObj.DefineVarDict.copy()) + + while True: + isInf = self.__GetInfStatement(FvObj, MacroDict = FvObj.DefineVarDict.copy()) + isFile = self.__GetFileStatement(FvObj, MacroDict = FvObj.DefineVarDict.copy()) + if not isInf and not isFile: + break + + return True + + ## __GetFvAlignment() method + # + # Get alignment for FV + # + # @param self The object pointer + # @param Obj for whom alignment is got + # @retval True Successfully find a alignment statement + # @retval False Not able to find a alignment statement + # + def __GetFvAlignment(self, Obj): + + if not self.__IsKeyword( "FvAlignment"): + return False + + if not self.__IsToken( "="): + raise Warning("expected '='", self.FileName, self.CurrentLineNumber) + + if not self.__GetNextToken(): + raise Warning("expected alignment value", self.FileName, self.CurrentLineNumber) + + if self.__Token.upper() not in ("1", "2", "4", "8", "16", "32", "64", "128", "256", "512", \ + "1K", "2K", "4K", "8K", "16K", "32K", "64K", "128K", "256K", "512K", \ + "1M", "2M", "4M", "8M", "16M", "32M", "64M", "128M", "256M", "512M", \ + "1G", "2G"): + raise Warning("Unknown alignment value '%s'" % self.__Token, self.FileName, self.CurrentLineNumber) + Obj.FvAlignment = self.__Token + return True + + ## __GetFvAttributes() method + # + # Get attributes for FV + # + # @param self The object pointer + # @param Obj for whom attribute is got + # @retval None + # + def __GetFvAttributes(self, FvObj): + + while self.__GetNextWord(): + name = self.__Token + if name not in ("ERASE_POLARITY", "MEMORY_MAPPED", \ + "STICKY_WRITE", "LOCK_CAP", "LOCK_STATUS", "WRITE_ENABLED_CAP", \ + "WRITE_DISABLED_CAP", "WRITE_STATUS", "READ_ENABLED_CAP", \ + "READ_DISABLED_CAP", "READ_STATUS", "READ_LOCK_CAP", \ + "READ_LOCK_STATUS", "WRITE_LOCK_CAP", "WRITE_LOCK_STATUS", \ + "WRITE_POLICY_RELIABLE"): + self.__UndoToken() + return + + if not self.__IsToken( "="): + raise Warning("expected '='", self.FileName, self.CurrentLineNumber) + + if not self.__GetNextToken() or self.__Token.upper() not in ("TRUE", "FALSE", "1", "0"): + raise Warning("expected TRUE/FALSE (1/0)", self.FileName, self.CurrentLineNumber) + + FvObj.FvAttributeDict[name] = self.__Token + + return + + ## __GetFvNameGuid() method + # + # Get FV GUID for FV + # + # @param self The object pointer + # @param Obj for whom GUID is got + # @retval None + # + def __GetFvNameGuid(self, FvObj): + + if not self.__IsKeyword( "FvNameGuid"): + return + + if not self.__IsToken( "="): + raise Warning("expected '='", self.FileName, self.CurrentLineNumber) + + if not self.__GetNextGuid(): + raise Warning("expected FV GUID value", self.FileName, self.CurrentLineNumber) + + FvObj.FvNameGuid = self.__Token + + return + + ## __GetAprioriSection() method + # + # Get token statements + # + # @param self The object pointer + # @param FvObj for whom apriori is got + # @param MacroDict dictionary used to replace macro + # @retval True Successfully find apriori statement + # @retval False Not able to find apriori statement + # + def __GetAprioriSection(self, FvObj, MacroDict = {}): + + if not self.__IsKeyword( "APRIORI"): + return False + + if not self.__IsKeyword("PEI") and not self.__IsKeyword("DXE"): + raise Warning("expected Apriori file type", self.FileName, self.CurrentLineNumber) + AprType = self.__Token + + if not self.__IsToken( "{"): + raise Warning("expected '{'", self.FileName, self.CurrentLineNumber) + + AprSectionObj = AprioriSection.AprioriSection() + AprSectionObj.AprioriType = AprType + + self.__GetDefineStatements(AprSectionObj) + MacroDict.update(AprSectionObj.DefineVarDict) + + while True: + IsInf = self.__GetInfStatement( AprSectionObj, MacroDict = MacroDict) + IsFile = self.__GetFileStatement( AprSectionObj) + if not IsInf and not IsFile: + break + + if not self.__IsToken( "}"): + raise Warning("expected '}'", self.FileName, self.CurrentLineNumber) + + FvObj.AprioriSectionList.append(AprSectionObj) + return True + + ## __GetInfStatement() method + # + # Get INF statements + # + # @param self The object pointer + # @param Obj for whom inf statement is got + # @param MacroDict dictionary used to replace macro + # @retval True Successfully find inf statement + # @retval False Not able to find inf statement + # + def __GetInfStatement(self, Obj, ForCapsule = False, MacroDict = {}): + + if not self.__IsKeyword( "INF"): + return False + + ffsInf = FfsInfStatement.FfsInfStatement() + self.__GetInfOptions( ffsInf) + + if not self.__GetNextToken(): + raise Warning("expected INF file path", self.FileName, self.CurrentLineNumber) + ffsInf.InfFileName = self.__Token + +# if ffsInf.InfFileName.find('$') >= 0: +# ffsInf.InfFileName = GenFdsGlobalVariable.GenFdsGlobalVariable.MacroExtend(ffsInf.InfFileName, MacroDict) + + if not ffsInf.InfFileName in self.Profile.InfList: + self.Profile.InfList.append(ffsInf.InfFileName) + + if self.__IsToken('|'): + if self.__IsKeyword('RELOCS_STRIPPED'): + ffsInf.KeepReloc = False + elif self.__IsKeyword('RELOCS_RETAINED'): + ffsInf.KeepReloc = True + else: + raise Warning("Unknown reloc strip flag '%s'" % self.__Token, self.FileName, self.CurrentLineNumber) + + if ForCapsule: + capsuleFfs = CapsuleData.CapsuleFfs() + capsuleFfs.Ffs = ffsInf + Obj.CapsuleDataList.append(capsuleFfs) + else: + Obj.FfsList.append(ffsInf) + return True + + ## __GetInfOptions() method + # + # Get options for INF + # + # @param self The object pointer + # @param FfsInfObj for whom option is got + # + def __GetInfOptions(self, FfsInfObj): + + if self.__IsKeyword( "RuleOverride"): + if not self.__IsToken( "="): + raise Warning("expected '='", self.FileName, self.CurrentLineNumber) + if not self.__GetNextToken(): + raise Warning("expected Rule name", self.FileName, self.CurrentLineNumber) + FfsInfObj.Rule = self.__Token + + if self.__IsKeyword( "VERSION"): + if not self.__IsToken( "="): + raise Warning("expected '='", self.FileName, self.CurrentLineNumber) + if not self.__GetNextToken(): + raise Warning("expected Version", self.FileName, self.CurrentLineNumber) + + if self.__GetStringData(): + FfsInfObj.Version = self.__Token + + if self.__IsKeyword( "UI"): + if not self.__IsToken( "="): + raise Warning("expected '='", self.FileName, self.CurrentLineNumber) + if not self.__GetNextToken(): + raise Warning("expected UI name", self.FileName, self.CurrentLineNumber) + + if self.__GetStringData(): + FfsInfObj.Ui = self.__Token + + if self.__IsKeyword( "USE"): + if not self.__IsToken( "="): + raise Warning("expected '='", self.FileName, self.CurrentLineNumber) + if not self.__GetNextToken(): + raise Warning("expected ARCH name", self.FileName, self.CurrentLineNumber) + FfsInfObj.UseArch = self.__Token + + + if self.__GetNextToken(): + p = re.compile(r'([a-zA-Z0-9\-]+|\$\(TARGET\)|\*)_([a-zA-Z0-9\-]+|\$\(TOOL_CHAIN_TAG\)|\*)_([a-zA-Z0-9\-]+|\$\(ARCH\)|\*)') + if p.match(self.__Token): + FfsInfObj.KeyStringList.append(self.__Token) + if not self.__IsToken(","): + return + else: + self.__UndoToken() + return + + while self.__GetNextToken(): + if not p.match(self.__Token): + raise Warning("expected KeyString \"Target_Tag_Arch\"", self.FileName, self.CurrentLineNumber) + FfsInfObj.KeyStringList.append(self.__Token) + + if not self.__IsToken(","): + break + + ## __GetFileStatement() method + # + # Get FILE statements + # + # @param self The object pointer + # @param Obj for whom FILE statement is got + # @param MacroDict dictionary used to replace macro + # @retval True Successfully find FILE statement + # @retval False Not able to find FILE statement + # + def __GetFileStatement(self, Obj, ForCapsule = False, MacroDict = {}): + + if not self.__IsKeyword( "FILE"): + return False + + FfsFileObj = FfsFileStatement.FileStatement() + + if not self.__GetNextWord(): + raise Warning("expected FFS type", self.FileName, self.CurrentLineNumber) + FfsFileObj.FvFileType = self.__Token + + if not self.__IsToken( "="): + raise Warning("expected '='", self.FileName, self.CurrentLineNumber) + + if not self.__GetNextGuid(): + if not self.__GetNextWord(): + raise Warning("expected File GUID", self.FileName, self.CurrentLineNumber) + if self.__Token == 'PCD': + if not self.__IsToken( "("): + raise Warning("expected '('", self.FileName, self.CurrentLineNumber) + PcdPair = self.__GetNextPcdName() + if not self.__IsToken( ")"): + raise Warning("expected ')'", self.FileName, self.CurrentLineNumber) + self.__Token = 'PCD('+PcdPair[1]+'.'+PcdPair[0]+')' + + FfsFileObj.NameGuid = self.__Token + + self.__GetFilePart( FfsFileObj, MacroDict.copy()) + + if ForCapsule: + capsuleFfs = CapsuleData.CapsuleFfs() + capsuleFfs.Ffs = FfsFileObj + Obj.CapsuleDataList.append(capsuleFfs) + else: + Obj.FfsList.append(FfsFileObj) + + return True + + ## __FileCouldHaveRelocFlag() method + # + # Check whether reloc strip flag can be set for a file type. + # + # @param self The object pointer + # @param FileType The file type to check with + # @retval True This type could have relocation strip flag + # @retval False No way to have it + # + + def __FileCouldHaveRelocFlag (self, FileType): + if FileType in ('SEC', 'PEI_CORE', 'PEIM', 'PEI_DXE_COMBO'): + return True + else: + return False + + ## __SectionCouldHaveRelocFlag() method + # + # Check whether reloc strip flag can be set for a section type. + # + # @param self The object pointer + # @param SectionType The section type to check with + # @retval True This type could have relocation strip flag + # @retval False No way to have it + # + + def __SectionCouldHaveRelocFlag (self, SectionType): + if SectionType in ('TE', 'PE32'): + return True + else: + return False + + ## __GetFilePart() method + # + # Get components for FILE statement + # + # @param self The object pointer + # @param FfsFileObj for whom component is got + # @param MacroDict dictionary used to replace macro + # + def __GetFilePart(self, FfsFileObj, MacroDict = {}): + + self.__GetFileOpts( FfsFileObj) + + if not self.__IsToken("{"): +# if self.__IsKeyword('RELOCS_STRIPPED') or self.__IsKeyword('RELOCS_RETAINED'): +# if self.__FileCouldHaveRelocFlag(FfsFileObj.FvFileType): +# if self.__Token == 'RELOCS_STRIPPED': +# FfsFileObj.KeepReloc = False +# else: +# FfsFileObj.KeepReloc = True +# else: +# raise Warning("File type %s could not have reloc strip flag%d" % (FfsFileObj.FvFileType, self.CurrentLineNumber), self.FileName, self.CurrentLineNumber) +# +# if not self.__IsToken("{"): + raise Warning("expected '{'", self.FileName, self.CurrentLineNumber) + + if not self.__GetNextToken(): + raise Warning("expected File name or section data", self.FileName, self.CurrentLineNumber) + + if self.__Token == "FV": + if not self.__IsToken( "="): + raise Warning("expected '='", self.FileName, self.CurrentLineNumber) + if not self.__GetNextToken(): + raise Warning("expected FV name", self.FileName, self.CurrentLineNumber) + FfsFileObj.FvName = self.__Token + + elif self.__Token == "FD": + if not self.__IsToken( "="): + raise Warning("expected '='", self.FileName, self.CurrentLineNumber) + if not self.__GetNextToken(): + raise Warning("expected FD name", self.FileName, self.CurrentLineNumber) + FfsFileObj.FdName = self.__Token + + elif self.__Token in ("DEFINE", "APRIORI", "SECTION"): + self.__UndoToken() + self.__GetSectionData( FfsFileObj, MacroDict) + else: + FfsFileObj.FileName = self.__Token + + if not self.__IsToken( "}"): + raise Warning("expected '}'", self.FileName, self.CurrentLineNumber) + + ## __GetFileOpts() method + # + # Get options for FILE statement + # + # @param self The object pointer + # @param FfsFileObj for whom options is got + # + def __GetFileOpts(self, FfsFileObj): + + if self.__GetNextToken(): + Pattern = re.compile(r'([a-zA-Z0-9\-]+|\$\(TARGET\)|\*)_([a-zA-Z0-9\-]+|\$\(TOOL_CHAIN_TAG\)|\*)_([a-zA-Z0-9\-]+|\$\(ARCH\)|\*)') + if Pattern.match(self.__Token): + FfsFileObj.KeyStringList.append(self.__Token) + if self.__IsToken(","): + while self.__GetNextToken(): + if not Pattern.match(self.__Token): + raise Warning("expected KeyString \"Target_Tag_Arch\"", self.FileName, self.CurrentLineNumber) + FfsFileObj.KeyStringList.append(self.__Token) + + if not self.__IsToken(","): + break + + else: + self.__UndoToken() + + if self.__IsKeyword( "FIXED", True): + FfsFileObj.Fixed = True + + if self.__IsKeyword( "CHECKSUM", True): + FfsFileObj.CheckSum = True + + if self.__GetAlignment(): + FfsFileObj.Alignment = self.__Token + + + + ## __GetAlignment() method + # + # Return the alignment value + # + # @param self The object pointer + # @retval True Successfully find alignment + # @retval False Not able to find alignment + # + def __GetAlignment(self): + if self.__IsKeyword( "Align", True): + if not self.__IsToken( "="): + raise Warning("expected '='", self.FileName, self.CurrentLineNumber) + + if not self.__GetNextToken(): + raise Warning("expected alignment value", self.FileName, self.CurrentLineNumber) + return True + + return False + + ## __GetFilePart() method + # + # Get section data for FILE statement + # + # @param self The object pointer + # @param FfsFileObj for whom section is got + # @param MacroDict dictionary used to replace macro + # + def __GetSectionData(self, FfsFileObj, MacroDict = {}): + Dict = {} + Dict.update(MacroDict) + + self.__GetDefineStatements(FfsFileObj) + + Dict.update(FfsFileObj.DefineVarDict) + self.__GetAprioriSection(FfsFileObj, Dict.copy()) + self.__GetAprioriSection(FfsFileObj, Dict.copy()) + + while True: + IsLeafSection = self.__GetLeafSection(FfsFileObj, Dict) + IsEncapSection = self.__GetEncapsulationSec(FfsFileObj) + if not IsLeafSection and not IsEncapSection: + break + + ## __GetLeafSection() method + # + # Get leaf section for Obj + # + # @param self The object pointer + # @param Obj for whom leaf section is got + # @param MacroDict dictionary used to replace macro + # @retval True Successfully find section statement + # @retval False Not able to find section statement + # + def __GetLeafSection(self, Obj, MacroDict = {}): + + OldPos = self.GetFileBufferPos() + + if not self.__IsKeyword( "SECTION"): + if len(Obj.SectionList) == 0: + raise Warning("expected SECTION", self.FileName, self.CurrentLineNumber) + else: + return False + + AlignValue = None + if self.__GetAlignment(): + AlignValue = self.__Token + + BuildNum = None + if self.__IsKeyword( "BUILD_NUM"): + if not self.__IsToken( "="): + raise Warning("expected '='", self.FileName, self.CurrentLineNumber) + + if not self.__GetNextToken(): + raise Warning("expected Build number value", self.FileName, self.CurrentLineNumber) + + BuildNum = self.__Token + + if self.__IsKeyword( "VERSION"): + if not self.__IsToken( "="): + raise Warning("expected '='", self.FileName, self.CurrentLineNumber) + if not self.__GetNextToken(): + raise Warning("expected version", self.FileName, self.CurrentLineNumber) + VerSectionObj = VerSection.VerSection() + VerSectionObj.Alignment = AlignValue + VerSectionObj.BuildNum = BuildNum + if self.__GetStringData(): + VerSectionObj.StringData = self.__Token + else: + VerSectionObj.FileName = self.__Token + Obj.SectionList.append(VerSectionObj) + + elif self.__IsKeyword( "UI"): + if not self.__IsToken( "="): + raise Warning("expected '='", self.FileName, self.CurrentLineNumber) + if not self.__GetNextToken(): + raise Warning("expected UI", self.FileName, self.CurrentLineNumber) + UiSectionObj = UiSection.UiSection() + UiSectionObj.Alignment = AlignValue + if self.__GetStringData(): + UiSectionObj.StringData = self.__Token + else: + UiSectionObj.FileName = self.__Token + Obj.SectionList.append(UiSectionObj) + + elif self.__IsKeyword( "FV_IMAGE"): + if not self.__IsToken( "="): + raise Warning("expected '='", self.FileName, self.CurrentLineNumber) + if not self.__GetNextToken(): + raise Warning("expected FV name or FV file path", self.FileName, self.CurrentLineNumber) + + FvName = self.__Token + FvObj = None + + if self.__IsToken( "{"): + FvObj = Fv.FV() + FvObj.UiFvName = FvName.upper() + self.__GetDefineStatements(FvObj) + MacroDict.update(FvObj.DefineVarDict) + self.__GetBlockStatement(FvObj) + self.__GetSetStatements(FvObj) + self.__GetFvAlignment(FvObj) + self.__GetFvAttributes(FvObj) + self.__GetAprioriSection(FvObj, MacroDict.copy()) + self.__GetAprioriSection(FvObj, MacroDict.copy()) + + while True: + IsInf = self.__GetInfStatement(FvObj, MacroDict.copy()) + IsFile = self.__GetFileStatement(FvObj, MacroDict.copy()) + if not IsInf and not IsFile: + break + + if not self.__IsToken( "}"): + raise Warning("expected '}'", self.FileName, self.CurrentLineNumber) + + FvImageSectionObj = FvImageSection.FvImageSection() + FvImageSectionObj.Alignment = AlignValue + if FvObj != None: + FvImageSectionObj.Fv = FvObj + FvImageSectionObj.FvName = None + else: + FvImageSectionObj.FvName = FvName.upper() + FvImageSectionObj.FvFileName = FvName + + Obj.SectionList.append(FvImageSectionObj) + + elif self.__IsKeyword("PEI_DEPEX_EXP") or self.__IsKeyword("DXE_DEPEX_EXP") or self.__IsKeyword("SMM_DEPEX_EXP"): + DepexSectionObj = DepexSection.DepexSection() + DepexSectionObj.Alignment = AlignValue + DepexSectionObj.DepexType = self.__Token + + if not self.__IsToken( "="): + raise Warning("expected '='", self.FileName, self.CurrentLineNumber) + if not self.__IsToken( "{"): + raise Warning("expected '{'", self.FileName, self.CurrentLineNumber) + if not self.__SkipToToken( "}"): + raise Warning("expected Depex expression ending '}'", self.FileName, self.CurrentLineNumber) + + DepexSectionObj.Expression = self.__SkippedChars.rstrip('}') + Obj.SectionList.append(DepexSectionObj) + + else: + + if not self.__GetNextWord(): + raise Warning("expected section type", self.FileName, self.CurrentLineNumber) + + # Encapsulation section appear, UndoToken and return + if self.__Token == "COMPRESS" or self.__Token == "GUIDED": + self.SetFileBufferPos(OldPos) + return False + + if self.__Token not in ("COMPAT16", "PE32", "PIC", "TE", "FV_IMAGE", "RAW", "DXE_DEPEX",\ + "UI", "VERSION", "PEI_DEPEX", "SUBTYPE_GUID", "SMM_DEPEX"): + raise Warning("Unknown section type '%s'" % self.__Token, self.FileName, self.CurrentLineNumber) + # DataSection + DataSectionObj = DataSection.DataSection() + DataSectionObj.Alignment = AlignValue + DataSectionObj.SecType = self.__Token + + if self.__IsKeyword('RELOCS_STRIPPED') or self.__IsKeyword('RELOCS_RETAINED'): + if self.__FileCouldHaveRelocFlag(Obj.FvFileType) and self.__SectionCouldHaveRelocFlag(DataSectionObj.SecType): + if self.__Token == 'RELOCS_STRIPPED': + DataSectionObj.KeepReloc = False + else: + DataSectionObj.KeepReloc = True + else: + raise Warning("File type %s, section type %s, could not have reloc strip flag%d" % (Obj.FvFileType, DataSectionObj.SecType, self.CurrentLineNumber), self.FileName, self.CurrentLineNumber) + + if self.__IsToken("="): + if not self.__GetNextToken(): + raise Warning("expected section file path", self.FileName, self.CurrentLineNumber) + DataSectionObj.SectFileName = self.__Token + else: + if not self.__GetCglSection(DataSectionObj): + return False + + Obj.SectionList.append(DataSectionObj) + + return True + + ## __GetCglSection() method + # + # Get compressed or GUIDed section for Obj + # + # @param self The object pointer + # @param Obj for whom leaf section is got + # @param AlignValue alignment value for complex section + # @retval True Successfully find section statement + # @retval False Not able to find section statement + # + def __GetCglSection(self, Obj, AlignValue = None): + + if self.__IsKeyword( "COMPRESS"): + type = "PI_STD" + if self.__IsKeyword("PI_STD") or self.__IsKeyword("PI_NONE"): + type = self.__Token + + if not self.__IsToken("{"): + raise Warning("expected '{'", self.FileName, self.CurrentLineNumber) + + CompressSectionObj = CompressSection.CompressSection() + CompressSectionObj.Alignment = AlignValue + CompressSectionObj.CompType = type + # Recursive sections... + while True: + IsLeafSection = self.__GetLeafSection(CompressSectionObj) + IsEncapSection = self.__GetEncapsulationSec(CompressSectionObj) + if not IsLeafSection and not IsEncapSection: + break + + + if not self.__IsToken( "}"): + raise Warning("expected '}'", self.FileName, self.CurrentLineNumber) + Obj.SectionList.append(CompressSectionObj) + +# else: +# raise Warning("Compress type not known") + + return True + + elif self.__IsKeyword( "GUIDED"): + GuidValue = None + if self.__GetNextGuid(): + GuidValue = self.__Token + + AttribDict = self.__GetGuidAttrib() + if not self.__IsToken("{"): + raise Warning("expected '{'", self.FileName, self.CurrentLineNumber) + GuidSectionObj = GuidSection.GuidSection() + GuidSectionObj.Alignment = AlignValue + GuidSectionObj.NameGuid = GuidValue + GuidSectionObj.SectionType = "GUIDED" + GuidSectionObj.ProcessRequired = AttribDict["PROCESSING_REQUIRED"] + GuidSectionObj.AuthStatusValid = AttribDict["AUTH_STATUS_VALID"] + # Recursive sections... + while True: + IsLeafSection = self.__GetLeafSection(GuidSectionObj) + IsEncapSection = self.__GetEncapsulationSec(GuidSectionObj) + if not IsLeafSection and not IsEncapSection: + break + + if not self.__IsToken( "}"): + raise Warning("expected '}'", self.FileName, self.CurrentLineNumber) + Obj.SectionList.append(GuidSectionObj) + + return True + + return False + + ## __GetGuidAttri() method + # + # Get attributes for GUID section + # + # @param self The object pointer + # @retval AttribDict Dictionary of key-value pair of section attributes + # + def __GetGuidAttrib(self): + + AttribDict = {} + AttribDict["PROCESSING_REQUIRED"] = False + AttribDict["AUTH_STATUS_VALID"] = False + if self.__IsKeyword("PROCESSING_REQUIRED") or self.__IsKeyword("AUTH_STATUS_VALID"): + AttribKey = self.__Token + + if not self.__IsToken("="): + raise Warning("expected '='", self.FileName, self.CurrentLineNumber) + + if not self.__GetNextToken() or self.__Token.upper() not in ("TRUE", "FALSE", "1", "0"): + raise Warning("expected TRUE/FALSE (1/0)", self.FileName, self.CurrentLineNumber) + AttribDict[AttribKey] = self.__Token + + if self.__IsKeyword("PROCESSING_REQUIRED") or self.__IsKeyword("AUTH_STATUS_VALID"): + AttribKey = self.__Token + + if not self.__IsToken("="): + raise Warning("expected '='") + + if not self.__GetNextToken() or self.__Token.upper() not in ("TRUE", "FALSE", "1", "0"): + raise Warning("expected TRUE/FALSE (1/0)", self.FileName, self.CurrentLineNumber) + AttribDict[AttribKey] = self.__Token + + return AttribDict + + ## __GetEncapsulationSec() method + # + # Get encapsulation section for FILE + # + # @param self The object pointer + # @param FfsFile for whom section is got + # @retval True Successfully find section statement + # @retval False Not able to find section statement + # + def __GetEncapsulationSec(self, FfsFileObj): + + OldPos = self.GetFileBufferPos() + if not self.__IsKeyword( "SECTION"): + if len(FfsFileObj.SectionList) == 0: + raise Warning("expected SECTION", self.FileName, self.CurrentLineNumber) + else: + return False + + AlignValue = None + if self.__GetAlignment(): + AlignValue = self.__Token + + if not self.__GetCglSection(FfsFileObj, AlignValue): + self.SetFileBufferPos(OldPos) + return False + else: + return True + + ## __GetCapsule() method + # + # Get capsule section contents and store its data into capsule list of self.Profile + # + # @param self The object pointer + # @retval True Successfully find a capsule + # @retval False Not able to find a capsule + # + def __GetCapsule(self): + + if not self.__GetNextToken(): + return False + + S = self.__Token.upper() + if S.startswith("[") and not S.startswith("[CAPSULE."): + if not S.startswith("[VTF.") and not S.startswith("[RULE.") and not S.startswith("[OPTIONROM."): + raise Warning("Unknown section or section appear sequence error (The correct sequence should be [FD.], [FV.], [Capsule.], [VTF.], [Rule.], [OptionRom.])", self.FileName, self.CurrentLineNumber) + self.__UndoToken() + return False + + self.__UndoToken() + if not self.__IsToken("[CAPSULE.", True): + FileLineTuple = GetRealFileLine(self.FileName, self.CurrentLineNumber) + #print 'Parsing String: %s in File %s, At line: %d, Offset Within Line: %d' \ + # % (self.Profile.FileLinesList[self.CurrentLineNumber - 1][self.CurrentOffsetWithinLine :], FileLineTuple[0], FileLineTuple[1], self.CurrentOffsetWithinLine) + raise Warning("expected [Capsule.]", self.FileName, self.CurrentLineNumber) + + CapsuleObj = Capsule.Capsule() + + CapsuleName = self.__GetUiName() + if not CapsuleName: + raise Warning("expected capsule name", self.FileName, self.CurrentLineNumber) + + CapsuleObj.UiCapsuleName = CapsuleName.upper() + + if not self.__IsToken( "]"): + raise Warning("expected ']'", self.FileName, self.CurrentLineNumber) + + if self.__IsKeyword("CREATE_FILE"): + if not self.__IsToken( "="): + raise Warning("expected '='", self.FileName, self.CurrentLineNumber) + + if not self.__GetNextToken(): + raise Warning("expected file name", self.FileName, self.CurrentLineNumber) + + CapsuleObj.CreateFile = self.__Token + + self.__GetCapsuleStatements(CapsuleObj) + self.Profile.CapsuleList.append(CapsuleObj) + return True + + ## __GetCapsuleStatements() method + # + # Get statements for capsule + # + # @param self The object pointer + # @param Obj for whom statements are got + # + def __GetCapsuleStatements(self, Obj): + self.__GetCapsuleTokens(Obj) + self.__GetDefineStatements(Obj) + self.__GetSetStatements(Obj) + + self.__GetCapsuleData(Obj) + + ## __GetCapsuleStatements() method + # + # Get token statements for capsule + # + # @param self The object pointer + # @param Obj for whom token statements are got + # + def __GetCapsuleTokens(self, Obj): + + if not self.__IsKeyword("CAPSULE_GUID"): + raise Warning("expected 'CAPSULE_GUID'", self.FileName, self.CurrentLineNumber) + + while self.__CurrentLine().find("=") != -1: + NameValue = self.__CurrentLine().split("=") + Obj.TokensDict[NameValue[0].strip()] = NameValue[1].strip() + self.CurrentLineNumber += 1 + self.CurrentOffsetWithinLine = 0 + + ## __GetCapsuleData() method + # + # Get capsule data for capsule + # + # @param self The object pointer + # @param Obj for whom capsule data are got + # + def __GetCapsuleData(self, Obj): + + while True: + IsInf = self.__GetInfStatement(Obj, True) + IsFile = self.__GetFileStatement(Obj, True) + IsFv = self.__GetFvStatement(Obj) + if not IsInf and not IsFile and not IsFv: + break + + ## __GetFvStatement() method + # + # Get FV for capsule + # + # @param self The object pointer + # @param CapsuleObj for whom FV is got + # @retval True Successfully find a FV statement + # @retval False Not able to find a FV statement + # + def __GetFvStatement(self, CapsuleObj): + + if not self.__IsKeyword("FV"): + return False + + if not self.__IsToken("="): + raise Warning("expected '='", self.FileName, self.CurrentLineNumber) + + if not self.__GetNextToken(): + raise Warning("expected FV name", self.FileName, self.CurrentLineNumber) + + CapsuleFv = CapsuleData.CapsuleFv() + CapsuleFv.FvName = self.__Token + CapsuleObj.CapsuleDataList.append(CapsuleFv) + return True + + ## __GetRule() method + # + # Get Rule section contents and store its data into rule list of self.Profile + # + # @param self The object pointer + # @retval True Successfully find a Rule + # @retval False Not able to find a Rule + # + def __GetRule(self): + + if not self.__GetNextToken(): + return False + + S = self.__Token.upper() + if S.startswith("[") and not S.startswith("[RULE."): + if not S.startswith("[OPTIONROM."): + raise Warning("Unknown section or section appear sequence error (The correct sequence should be [FD.], [FV.], [Capsule.], [VTF.], [Rule.], [OptionRom.])", self.FileName, self.CurrentLineNumber) + self.__UndoToken() + return False + self.__UndoToken() + if not self.__IsToken("[Rule.", True): + FileLineTuple = GetRealFileLine(self.FileName, self.CurrentLineNumber) + #print 'Parsing String: %s in File %s, At line: %d, Offset Within Line: %d' \ + # % (self.Profile.FileLinesList[self.CurrentLineNumber - 1][self.CurrentOffsetWithinLine :], FileLineTuple[0], FileLineTuple[1], self.CurrentOffsetWithinLine) + raise Warning("expected [Rule.]", self.FileName, self.CurrentLineNumber) + + if not self.__SkipToToken("."): + raise Warning("expected '.'", self.FileName, self.CurrentLineNumber) + + Arch = self.__SkippedChars.rstrip(".") + if Arch.upper() not in ("IA32", "X64", "IPF", "EBC", "ARM", "COMMON"): + raise Warning("Unknown Arch '%s'" % Arch, self.FileName, self.CurrentLineNumber) + + ModuleType = self.__GetModuleType() + + TemplateName = "" + if self.__IsToken("."): + if not self.__GetNextWord(): + raise Warning("expected template name", self.FileName, self.CurrentLineNumber) + TemplateName = self.__Token + + if not self.__IsToken( "]"): + raise Warning("expected ']'", self.FileName, self.CurrentLineNumber) + + RuleObj = self.__GetRuleFileStatements() + RuleObj.Arch = Arch.upper() + RuleObj.ModuleType = ModuleType + RuleObj.TemplateName = TemplateName + if TemplateName == '' : + self.Profile.RuleDict['RULE' + \ + '.' + \ + Arch.upper() + \ + '.' + \ + ModuleType.upper() ] = RuleObj + else : + self.Profile.RuleDict['RULE' + \ + '.' + \ + Arch.upper() + \ + '.' + \ + ModuleType.upper() + \ + '.' + \ + TemplateName.upper() ] = RuleObj +# self.Profile.RuleList.append(rule) + return True + + ## __GetModuleType() method + # + # Return the module type + # + # @param self The object pointer + # @retval string module type + # + def __GetModuleType(self): + + if not self.__GetNextWord(): + raise Warning("expected Module type", self.FileName, self.CurrentLineNumber) + if self.__Token.upper() not in ("SEC", "PEI_CORE", "PEIM", "DXE_CORE", \ + "DXE_DRIVER", "DXE_SAL_DRIVER", \ + "DXE_SMM_DRIVER", "DXE_RUNTIME_DRIVER", \ + "UEFI_DRIVER", "UEFI_APPLICATION", "USER_DEFINED", "DEFAULT", "BASE", \ + "SECURITY_CORE", "COMBINED_PEIM_DRIVER", "PIC_PEIM", "RELOCATABLE_PEIM", \ + "PE32_PEIM", "BS_DRIVER", "RT_DRIVER", "SAL_RT_DRIVER", "APPLICATION", "ACPITABLE", "SMM_DRIVER", "SMM_CORE"): + raise Warning("Unknown Module type '%s'" % self.__Token, self.FileName, self.CurrentLineNumber) + return self.__Token + + ## __GetFileExtension() method + # + # Return the file extension + # + # @param self The object pointer + # @retval string file name extension + # + def __GetFileExtension(self): + if not self.__IsToken("."): + raise Warning("expected '.'", self.FileName, self.CurrentLineNumber) + + Ext = "" + if self.__GetNextToken(): + Pattern = re.compile(r'([a-zA-Z][a-zA-Z0-9]*)') + if Pattern.match(self.__Token): + Ext = self.__Token + return '.' + Ext + else: + raise Warning("Unknown file extension '%s'" % self.__Token, self.FileName, self.CurrentLineNumber) + + else: + raise Warning("expected file extension", self.FileName, self.CurrentLineNumber) + + ## __GetRuleFileStatement() method + # + # Get rule contents + # + # @param self The object pointer + # @retval Rule Rule object + # + def __GetRuleFileStatements(self): + + if not self.__IsKeyword("FILE"): + raise Warning("expected FILE", self.FileName, self.CurrentLineNumber) + + if not self.__GetNextWord(): + raise Warning("expected FFS type", self.FileName, self.CurrentLineNumber) + + Type = self.__Token.strip().upper() + if Type not in ("RAW", "FREEFORM", "SEC", "PEI_CORE", "PEIM",\ + "PEI_DXE_COMBO", "DRIVER", "DXE_CORE", "APPLICATION", "FV_IMAGE", "SMM_DXE_COMBO", "SMM", "SMM_CORE"): + raise Warning("Unknown FV type '%s'" % self.__Token, self.FileName, self.CurrentLineNumber) + + if not self.__IsToken("="): + raise Warning("expected '='", self.FileName, self.CurrentLineNumber) + + if not self.__IsKeyword("$(NAMED_GUID)"): + if not self.__GetNextWord(): + raise Warning("expected $(NAMED_GUID)", self.FileName, self.CurrentLineNumber) + if self.__Token == 'PCD': + if not self.__IsToken( "("): + raise Warning("expected '('", self.FileName, self.CurrentLineNumber) + PcdPair = self.__GetNextPcdName() + if not self.__IsToken( ")"): + raise Warning("expected ')'", self.FileName, self.CurrentLineNumber) + self.__Token = 'PCD('+PcdPair[1]+'.'+PcdPair[0]+')' + + NameGuid = self.__Token + + KeepReloc = None + if self.__IsKeyword('RELOCS_STRIPPED') or self.__IsKeyword('RELOCS_RETAINED'): + if self.__FileCouldHaveRelocFlag(Type): + if self.__Token == 'RELOCS_STRIPPED': + KeepReloc = False + else: + KeepReloc = True + else: + raise Warning("File type %s could not have reloc strip flag%d" % (Type, self.CurrentLineNumber), self.FileName, self.CurrentLineNumber) + + KeyStringList = [] + if self.__GetNextToken(): + Pattern = re.compile(r'([a-zA-Z0-9\-]+|\$\(TARGET\)|\*)_([a-zA-Z0-9\-]+|\$\(TOOL_CHAIN_TAG\)|\*)_([a-zA-Z0-9\-]+|\$\(ARCH\)|\*)') + if Pattern.match(self.__Token): + KeyStringList.append(self.__Token) + if self.__IsToken(","): + while self.__GetNextToken(): + if not Pattern.match(self.__Token): + raise Warning("expected KeyString \"Target_Tag_Arch\"", self.FileName, self.CurrentLineNumber) + KeyStringList.append(self.__Token) + + if not self.__IsToken(","): + break + + else: + self.__UndoToken() + + + Fixed = False + if self.__IsKeyword("Fixed", True): + Fixed = True + + CheckSum = False + if self.__IsKeyword("CheckSum", True): + CheckSum = True + + AlignValue = "" + if self.__GetAlignment(): + if self.__Token not in ("8", "16", "32", "64", "128", "512", "1K", "4K", "32K" ,"64K"): + raise Warning("Incorrect alignment '%s'" % self.__Token, self.FileName, self.CurrentLineNumber) + AlignValue = self.__Token + + if self.__IsToken("{"): + # Complex file rule expected + Rule = RuleComplexFile.RuleComplexFile() + Rule.FvFileType = Type + Rule.NameGuid = NameGuid + Rule.Alignment = AlignValue + Rule.CheckSum = CheckSum + Rule.Fixed = Fixed + Rule.KeyStringList = KeyStringList + if KeepReloc != None: + Rule.KeepReloc = KeepReloc + + while True: + IsEncapsulate = self.__GetRuleEncapsulationSection(Rule) + IsLeaf = self.__GetEfiSection(Rule) + if not IsEncapsulate and not IsLeaf: + break + + if not self.__IsToken("}"): + raise Warning("expected '}'", self.FileName, self.CurrentLineNumber) + + return Rule + + elif self.__IsToken("|"): + # Ext rule expected + Ext = self.__GetFileExtension() + + Rule = RuleSimpleFile.RuleSimpleFile() + + Rule.FvFileType = Type + Rule.NameGuid = NameGuid + Rule.Alignment = AlignValue + Rule.CheckSum = CheckSum + Rule.Fixed = Fixed + Rule.FileExtension = Ext + Rule.KeyStringList = KeyStringList + if KeepReloc != None: + Rule.KeepReloc = KeepReloc + + return Rule + + else: + # Simple file rule expected + if not self.__GetNextWord(): + raise Warning("expected leaf section type", self.FileName, self.CurrentLineNumber) + + SectionName = self.__Token + + if SectionName not in ("COMPAT16", "PE32", "PIC", "TE", "FV_IMAGE", "RAW", "DXE_DEPEX",\ + "UI", "PEI_DEPEX", "VERSION", "SUBTYPE_GUID", "SMM_DEPEX"): + raise Warning("Unknown leaf section name '%s'" % SectionName, self.FileName, self.CurrentLineNumber) + + + if self.__IsKeyword("Fixed", True): + Fixed = True + + if self.__IsKeyword("CheckSum", True): + CheckSum = True + + if self.__GetAlignment(): + if self.__Token not in ("8", "16", "32", "64", "128", "512", "1K", "4K", "32K" ,"64K"): + raise Warning("Incorrect alignment '%s'" % self.__Token, self.FileName, self.CurrentLineNumber) + AlignValue = self.__Token + + if not self.__GetNextToken(): + raise Warning("expected File name", self.FileName, self.CurrentLineNumber) + + Rule = RuleSimpleFile.RuleSimpleFile() + Rule.SectionType = SectionName + Rule.FvFileType = Type + Rule.NameGuid = NameGuid + Rule.Alignment = AlignValue + Rule.CheckSum = CheckSum + Rule.Fixed = Fixed + Rule.FileName = self.__Token + Rule.KeyStringList = KeyStringList + if KeepReloc != None: + Rule.KeepReloc = KeepReloc + return Rule + + ## __GetEfiSection() method + # + # Get section list for Rule + # + # @param self The object pointer + # @param Obj for whom section is got + # @retval True Successfully find section statement + # @retval False Not able to find section statement + # + def __GetEfiSection(self, Obj): + + OldPos = self.GetFileBufferPos() + if not self.__GetNextWord(): + return False + SectionName = self.__Token + + if SectionName not in ("COMPAT16", "PE32", "PIC", "TE", "FV_IMAGE", "RAW", "DXE_DEPEX",\ + "UI", "VERSION", "PEI_DEPEX", "GUID", "SMM_DEPEX"): + self.__UndoToken() + return False + + if SectionName == "FV_IMAGE": + FvImageSectionObj = FvImageSection.FvImageSection() + if self.__IsKeyword("FV_IMAGE"): + pass + if self.__IsToken( "{"): + FvObj = Fv.FV() + self.__GetDefineStatements(FvObj) + self.__GetBlockStatement(FvObj) + self.__GetSetStatements(FvObj) + self.__GetFvAlignment(FvObj) + self.__GetFvAttributes(FvObj) + self.__GetAprioriSection(FvObj) + self.__GetAprioriSection(FvObj) + + while True: + IsInf = self.__GetInfStatement(FvObj) + IsFile = self.__GetFileStatement(FvObj) + if not IsInf and not IsFile: + break + + if not self.__IsToken( "}"): + raise Warning("expected '}'", self.FileName, self.CurrentLineNumber) + FvImageSectionObj.Fv = FvObj + FvImageSectionObj.FvName = None + + else: + if not self.__IsKeyword("FV"): + raise Warning("expected 'FV'", self.FileName, self.CurrentLineNumber) + FvImageSectionObj.FvFileType = self.__Token + + if self.__GetAlignment(): + if self.__Token not in ("8", "16", "32", "64", "128", "512", "1K", "4K", "32K" ,"64K"): + raise Warning("Incorrect alignment '%s'" % self.__Token, self.FileName, self.CurrentLineNumber) + FvImageSectionObj.Alignment = self.__Token + + if self.__IsKeyword("FV"): + FvImageSectionObj.FvFileType = self.__Token + + if self.__GetAlignment(): + if self.__Token not in ("8", "16", "32", "64", "128", "512", "1K", "4K", "32K" ,"64K"): + raise Warning("Incorrect alignment '%s'" % self.__Token, self.FileName, self.CurrentLineNumber) + FvImageSectionObj.Alignment = self.__Token + + if self.__IsToken('|'): + FvImageSectionObj.FvFileExtension = self.__GetFileExtension() + elif self.__GetNextToken(): + if self.__Token not in ("}", "COMPAT16", "PE32", "PIC", "TE", "FV_IMAGE", "RAW", "DXE_DEPEX",\ + "UI", "VERSION", "PEI_DEPEX", "GUID", "SMM_DEPEX"): + FvImageSectionObj.FvFileName = self.__Token + else: + self.__UndoToken() + else: + raise Warning("expected FV file name", self.FileName, self.CurrentLineNumber) + + Obj.SectionList.append(FvImageSectionObj) + return True + + EfiSectionObj = EfiSection.EfiSection() + EfiSectionObj.SectionType = SectionName + + if not self.__GetNextToken(): + raise Warning("expected file type", self.FileName, self.CurrentLineNumber) + + if self.__Token == "STRING": + if not self.__RuleSectionCouldHaveString(EfiSectionObj.SectionType): + raise Warning("%s section could NOT have string data%d" % (EfiSectionObj.SectionType, self.CurrentLineNumber), self.FileName, self.CurrentLineNumber) + + if not self.__IsToken('='): + raise Warning("expected '='", self.FileName, self.CurrentLineNumber) + + if not self.__GetNextToken(): + raise Warning("expected Quoted String", self.FileName, self.CurrentLineNumber) + + if self.__GetStringData(): + EfiSectionObj.StringData = self.__Token + + if self.__IsKeyword("BUILD_NUM"): + if not self.__RuleSectionCouldHaveBuildNum(EfiSectionObj.SectionType): + raise Warning("%s section could NOT have BUILD_NUM%d" % (EfiSectionObj.SectionType, self.CurrentLineNumber), self.FileName, self.CurrentLineNumber) + + if not self.__IsToken("="): + raise Warning("expected '='", self.FileName, self.CurrentLineNumber) + if not self.__GetNextToken(): + raise Warning("expected Build number", self.FileName, self.CurrentLineNumber) + EfiSectionObj.BuildNum = self.__Token + + else: + EfiSectionObj.FileType = self.__Token + self.__CheckRuleSectionFileType(EfiSectionObj.SectionType, EfiSectionObj.FileType) + + if self.__IsKeyword("Optional"): + if not self.__RuleSectionCouldBeOptional(EfiSectionObj.SectionType): + raise Warning("%s section could NOT be optional%d" % (EfiSectionObj.SectionType, self.CurrentLineNumber), self.FileName, self.CurrentLineNumber) + EfiSectionObj.Optional = True + + if self.__IsKeyword("BUILD_NUM"): + if not self.__RuleSectionCouldHaveBuildNum(EfiSectionObj.SectionType): + raise Warning("%s section could NOT have BUILD_NUM%d" % (EfiSectionObj.SectionType, self.CurrentLineNumber), self.FileName, self.CurrentLineNumber) + + if not self.__IsToken("="): + raise Warning("expected '='", self.FileName, self.CurrentLineNumber) + if not self.__GetNextToken(): + raise Warning("expected Build number", self.FileName, self.CurrentLineNumber) + EfiSectionObj.BuildNum = self.__Token + + if self.__GetAlignment(): + EfiSectionObj.Alignment = self.__Token + + if self.__IsKeyword('RELOCS_STRIPPED') or self.__IsKeyword('RELOCS_RETAINED'): + if self.__SectionCouldHaveRelocFlag(EfiSectionObj.SectionType): + if self.__Token == 'RELOCS_STRIPPED': + EfiSectionObj.KeepReloc = False + else: + EfiSectionObj.KeepReloc = True + if Obj.KeepReloc != None and Obj.KeepReloc != EfiSectionObj.KeepReloc: + raise Warning("Section type %s has reloc strip flag conflict with Rule" % EfiSectionObj.SectionType, self.FileName, self.CurrentLineNumber) + else: + raise Warning("Section type %s could not have reloc strip flag" % EfiSectionObj.SectionType, self.FileName, self.CurrentLineNumber) + + + if self.__IsToken('|'): + EfiSectionObj.FileExtension = self.__GetFileExtension() + elif self.__GetNextToken(): + if self.__Token not in ("}", "COMPAT16", "PE32", "PIC", "TE", "FV_IMAGE", "RAW", "DXE_DEPEX",\ + "UI", "VERSION", "PEI_DEPEX", "GUID", "SMM_DEPEX"): + + if self.__Token.startswith('PCD'): + self.__UndoToken() + self.__GetNextWord() + + if self.__Token == 'PCD': + if not self.__IsToken( "("): + raise Warning("expected '('", self.FileName, self.CurrentLineNumber) + PcdPair = self.__GetNextPcdName() + if not self.__IsToken( ")"): + raise Warning("expected ')'", self.FileName, self.CurrentLineNumber) + self.__Token = 'PCD('+PcdPair[1]+'.'+PcdPair[0]+')' + + EfiSectionObj.FileName = self.__Token + + else: + self.__UndoToken() + else: + raise Warning("expected section file name", self.FileName, self.CurrentLineNumber) + + Obj.SectionList.append(EfiSectionObj) + return True + + ## __RuleSectionCouldBeOptional() method + # + # Get whether a section could be optional + # + # @param self The object pointer + # @param SectionType The section type to check + # @retval True section could be optional + # @retval False section never optional + # + def __RuleSectionCouldBeOptional(self, SectionType): + if SectionType in ("DXE_DEPEX", "UI", "VERSION", "PEI_DEPEX", "RAW", "SMM_DEPEX"): + return True + else: + return False + + ## __RuleSectionCouldHaveBuildNum() method + # + # Get whether a section could have build number information + # + # @param self The object pointer + # @param SectionType The section type to check + # @retval True section could have build number information + # @retval False section never have build number information + # + def __RuleSectionCouldHaveBuildNum(self, SectionType): + if SectionType in ("VERSION"): + return True + else: + return False + + ## __RuleSectionCouldHaveString() method + # + # Get whether a section could have string + # + # @param self The object pointer + # @param SectionType The section type to check + # @retval True section could have string + # @retval False section never have string + # + def __RuleSectionCouldHaveString(self, SectionType): + if SectionType in ("UI", "VERSION"): + return True + else: + return False + + ## __CheckRuleSectionFileType() method + # + # Get whether a section matches a file type + # + # @param self The object pointer + # @param SectionType The section type to check + # @param FileType The file type to check + # + def __CheckRuleSectionFileType(self, SectionType, FileType): + if SectionType == "COMPAT16": + if FileType not in ("COMPAT16", "SEC_COMPAT16"): + raise Warning("Incorrect section file type '%s'" % FileType, self.FileName, self.CurrentLineNumber) + elif SectionType == "PE32": + if FileType not in ("PE32", "SEC_PE32"): + raise Warning("Incorrect section file type '%s'" % FileType, self.FileName, self.CurrentLineNumber) + elif SectionType == "PIC": + if FileType not in ("PIC", "PIC"): + raise Warning("Incorrect section file type '%s'" % FileType, self.FileName, self.CurrentLineNumber) + elif SectionType == "TE": + if FileType not in ("TE", "SEC_TE"): + raise Warning("Incorrect section file type '%s'" % FileType, self.FileName, self.CurrentLineNumber) + elif SectionType == "RAW": + if FileType not in ("BIN", "SEC_BIN", "RAW", "ASL", "ACPI"): + raise Warning("Incorrect section file type '%s'" % FileType, self.FileName, self.CurrentLineNumber) + elif SectionType == "DXE_DEPEX": + if FileType not in ("DXE_DEPEX", "SEC_DXE_DEPEX"): + raise Warning("Incorrect section file type '%s'" % FileType, self.FileName, self.CurrentLineNumber) + elif SectionType == "UI": + if FileType not in ("UI", "SEC_UI"): + raise Warning("Incorrect section file type '%s'" % FileType, self.FileName, self.CurrentLineNumber) + elif SectionType == "VERSION": + if FileType not in ("VERSION", "SEC_VERSION"): + raise Warning("Incorrect section file type '%s'" % FileType, self.FileName, self.CurrentLineNumber) + elif SectionType == "PEI_DEPEX": + if FileType not in ("PEI_DEPEX", "SEC_PEI_DEPEX"): + raise Warning("Incorrect section file type '%s'" % FileType, self.FileName, self.CurrentLineNumber) + elif SectionType == "GUID": + if FileType not in ("PE32", "SEC_GUID"): + raise Warning("Incorrect section file type '%s'" % FileType, self.FileName, self.CurrentLineNumber) + + ## __GetRuleEncapsulationSection() method + # + # Get encapsulation section for Rule + # + # @param self The object pointer + # @param Rule for whom section is got + # @retval True Successfully find section statement + # @retval False Not able to find section statement + # + def __GetRuleEncapsulationSection(self, Rule): + + if self.__IsKeyword( "COMPRESS"): + Type = "PI_STD" + if self.__IsKeyword("PI_STD") or self.__IsKeyword("PI_NONE"): + Type = self.__Token + + if not self.__IsToken("{"): + raise Warning("expected '{'", self.FileName, self.CurrentLineNumber) + + CompressSectionObj = CompressSection.CompressSection() + + CompressSectionObj.CompType = Type + # Recursive sections... + while True: + IsEncapsulate = self.__GetRuleEncapsulationSection(CompressSectionObj) + IsLeaf = self.__GetEfiSection(CompressSectionObj) + if not IsEncapsulate and not IsLeaf: + break + + if not self.__IsToken( "}"): + raise Warning("expected '}'", self.FileName, self.CurrentLineNumber) + Rule.SectionList.append(CompressSectionObj) + + return True + + elif self.__IsKeyword( "GUIDED"): + GuidValue = None + if self.__GetNextGuid(): + GuidValue = self.__Token + + if self.__IsKeyword( "$(NAMED_GUID)"): + GuidValue = self.__Token + + AttribDict = self.__GetGuidAttrib() + + if not self.__IsToken("{"): + raise Warning("expected '{'", self.FileName, self.CurrentLineNumber) + GuidSectionObj = GuidSection.GuidSection() + GuidSectionObj.NameGuid = GuidValue + GuidSectionObj.SectionType = "GUIDED" + GuidSectionObj.ProcessRequired = AttribDict["PROCESSING_REQUIRED"] + GuidSectionObj.AuthStatusValid = AttribDict["AUTH_STATUS_VALID"] + + # Efi sections... + while True: + IsEncapsulate = self.__GetRuleEncapsulationSection(GuidSectionObj) + IsLeaf = self.__GetEfiSection(GuidSectionObj) + if not IsEncapsulate and not IsLeaf: + break + + if not self.__IsToken( "}"): + raise Warning("expected '}'", self.FileName, self.CurrentLineNumber) + Rule.SectionList.append(GuidSectionObj) + + return True + + return False + + ## __GetVtf() method + # + # Get VTF section contents and store its data into VTF list of self.Profile + # + # @param self The object pointer + # @retval True Successfully find a VTF + # @retval False Not able to find a VTF + # + def __GetVtf(self): + + if not self.__GetNextToken(): + return False + + S = self.__Token.upper() + if S.startswith("[") and not S.startswith("[VTF."): + if not S.startswith("[RULE.") and not S.startswith("[OPTIONROM."): + raise Warning("Unknown section or section appear sequence error (The correct sequence should be [FD.], [FV.], [Capsule.], [VTF.], [Rule.], [OptionRom.])", self.FileName, self.CurrentLineNumber) + self.__UndoToken() + return False + + self.__UndoToken() + if not self.__IsToken("[VTF.", True): + FileLineTuple = GetRealFileLine(self.FileName, self.CurrentLineNumber) + #print 'Parsing String: %s in File %s, At line: %d, Offset Within Line: %d' \ + # % (self.Profile.FileLinesList[self.CurrentLineNumber - 1][self.CurrentOffsetWithinLine :], FileLineTuple[0], FileLineTuple[1], self.CurrentOffsetWithinLine) + raise Warning("expected [VTF.]", self.FileName, self.CurrentLineNumber) + + if not self.__SkipToToken("."): + raise Warning("expected '.'", self.FileName, self.CurrentLineNumber) + + Arch = self.__SkippedChars.rstrip(".").upper() + if Arch not in ("IA32", "X64", "IPF", "ARM"): + raise Warning("Unknown Arch '%s'" % Arch, self.FileName, self.CurrentLineNumber) + + if not self.__GetNextWord(): + raise Warning("expected VTF name", self.FileName, self.CurrentLineNumber) + Name = self.__Token.upper() + + VtfObj = Vtf.Vtf() + VtfObj.UiName = Name + VtfObj.KeyArch = Arch + + if self.__IsToken(","): + if not self.__GetNextWord(): + raise Warning("expected Arch list", self.FileName, self.CurrentLineNumber) + if self.__Token.upper() not in ("IA32", "X64", "IPF", "ARM"): + raise Warning("Unknown Arch '%s'" % self.__Token, self.FileName, self.CurrentLineNumber) + VtfObj.ArchList = self.__Token.upper() + + if not self.__IsToken( "]"): + raise Warning("expected ']'", self.FileName, self.CurrentLineNumber) + + if self.__IsKeyword("IA32_RST_BIN"): + if not self.__IsToken("="): + raise Warning("expected '='", self.FileName, self.CurrentLineNumber) + + if not self.__GetNextToken(): + raise Warning("expected Reset file", self.FileName, self.CurrentLineNumber) + + VtfObj.ResetBin = self.__Token + + while self.__GetComponentStatement(VtfObj): + pass + + self.Profile.VtfList.append(VtfObj) + return True + + ## __GetComponentStatement() method + # + # Get components in VTF + # + # @param self The object pointer + # @param VtfObj for whom component is got + # @retval True Successfully find a component + # @retval False Not able to find a component + # + def __GetComponentStatement(self, VtfObj): + + if not self.__IsKeyword("COMP_NAME"): + return False + + if not self.__IsToken("="): + raise Warning("expected '='", self.FileName, self.CurrentLineNumber) + + if not self.__GetNextWord(): + raise Warning("expected Component Name", self.FileName, self.CurrentLineNumber) + + CompStatementObj = ComponentStatement.ComponentStatement() + CompStatementObj.CompName = self.__Token + + if not self.__IsKeyword("COMP_LOC"): + raise Warning("expected COMP_LOC", self.FileName, self.CurrentLineNumber) + + if not self.__IsToken("="): + raise Warning("expected '='", self.FileName, self.CurrentLineNumber) + + CompStatementObj.CompLoc = "" + if self.__GetNextWord(): + CompStatementObj.CompLoc = self.__Token + if self.__IsToken('|'): + if not self.__GetNextWord(): + raise Warning("Expected Region Name", self.FileName, self.CurrentLineNumber) + + if self.__Token not in ("F", "N", "S"): #, "H", "L", "PH", "PL"): not support + raise Warning("Unknown location type '%s'" % self.__Token, self.FileName, self.CurrentLineNumber) + + CompStatementObj.FilePos = self.__Token + else: + self.CurrentLineNumber += 1 + self.CurrentOffsetWithinLine = 0 + + if not self.__IsKeyword("COMP_TYPE"): + raise Warning("expected COMP_TYPE", self.FileName, self.CurrentLineNumber) + + if not self.__IsToken("="): + raise Warning("expected '='", self.FileName, self.CurrentLineNumber) + + if not self.__GetNextToken(): + raise Warning("expected Component type", self.FileName, self.CurrentLineNumber) + if self.__Token not in ("FIT", "PAL_B", "PAL_A", "OEM"): + if not self.__Token.startswith("0x") or len(self.__Token) < 3 or len(self.__Token) > 4 or \ + not self.__HexDigit(self.__Token[2]) or not self.__HexDigit(self.__Token[-1]): + raise Warning("Unknown location type '%s'" % self.__Token, self.FileName, self.CurrentLineNumber) + CompStatementObj.CompType = self.__Token + + if not self.__IsKeyword("COMP_VER"): + raise Warning("expected COMP_VER", self.FileName, self.CurrentLineNumber) + + if not self.__IsToken("="): + raise Warning("expected '='", self.FileName, self.CurrentLineNumber) + + if not self.__GetNextToken(): + raise Warning("expected Component version", self.FileName, self.CurrentLineNumber) + + Pattern = re.compile('-$|[0-9]{0,1}[0-9]{1}\.[0-9]{0,1}[0-9]{1}') + if Pattern.match(self.__Token) == None: + raise Warning("Unknown version format '%s'" % self.__Token, self.FileName, self.CurrentLineNumber) + CompStatementObj.CompVer = self.__Token + + if not self.__IsKeyword("COMP_CS"): + raise Warning("expected COMP_CS", self.FileName, self.CurrentLineNumber) + + if not self.__IsToken("="): + raise Warning("expected '='", self.FileName, self.CurrentLineNumber) + + if not self.__GetNextToken(): + raise Warning("expected Component CS", self.FileName, self.CurrentLineNumber) + if self.__Token not in ("1", "0"): + raise Warning("Unknown Component CS '%s'" % self.__Token, self.FileName, self.CurrentLineNumber) + CompStatementObj.CompCs = self.__Token + + + if not self.__IsKeyword("COMP_BIN"): + raise Warning("expected COMP_BIN", self.FileName, self.CurrentLineNumber) + + if not self.__IsToken("="): + raise Warning("expected '='", self.FileName, self.CurrentLineNumber) + + if not self.__GetNextToken(): + raise Warning("expected Component file", self.FileName, self.CurrentLineNumber) + + CompStatementObj.CompBin = self.__Token + + if not self.__IsKeyword("COMP_SYM"): + raise Warning("expected COMP_SYM", self.FileName, self.CurrentLineNumber) + + if not self.__IsToken("="): + raise Warning("expected '='", self.FileName, self.CurrentLineNumber) + + if not self.__GetNextToken(): + raise Warning("expected Component symbol file", self.FileName, self.CurrentLineNumber) + + CompStatementObj.CompSym = self.__Token + + if not self.__IsKeyword("COMP_SIZE"): + raise Warning("expected COMP_SIZE", self.FileName, self.CurrentLineNumber) + + if not self.__IsToken("="): + raise Warning("expected '='", self.FileName, self.CurrentLineNumber) + + if self.__IsToken("-"): + CompStatementObj.CompSize = self.__Token + elif self.__GetNextDecimalNumber(): + CompStatementObj.CompSize = self.__Token + elif self.__GetNextHexNumber(): + CompStatementObj.CompSize = self.__Token + else: + raise Warning("Unknown size '%s'" % self.__Token, self.FileName, self.CurrentLineNumber) + + VtfObj.ComponentStatementList.append(CompStatementObj) + return True + + ## __GetOptionRom() method + # + # Get OptionROM section contents and store its data into OptionROM list of self.Profile + # + # @param self The object pointer + # @retval True Successfully find a OptionROM + # @retval False Not able to find a OptionROM + # + def __GetOptionRom(self): + + if not self.__GetNextToken(): + return False + + S = self.__Token.upper() + if S.startswith("[") and not S.startswith("[OPTIONROM."): + raise Warning("Unknown section or section appear sequence error (The correct sequence should be [FD.], [FV.], [Capsule.], [VTF.], [Rule.], [OptionRom.])", self.FileName, self.CurrentLineNumber) + + self.__UndoToken() + if not self.__IsToken("[OptionRom.", True): + raise Warning("Unknown Keyword '%s'" % self.__Token, self.FileName, self.CurrentLineNumber) + + OptRomName = self.__GetUiName() + + if not self.__IsToken( "]"): + raise Warning("expected ']'", self.FileName, self.CurrentLineNumber) + + OptRomObj = OptionRom.OPTIONROM() + OptRomObj.DriverName = OptRomName + self.Profile.OptRomDict[OptRomName] = OptRomObj + + while True: + isInf = self.__GetOptRomInfStatement(OptRomObj) + isFile = self.__GetOptRomFileStatement(OptRomObj) + if not isInf and not isFile: + break + + return True + + ## __GetOptRomInfStatement() method + # + # Get INF statements + # + # @param self The object pointer + # @param Obj for whom inf statement is got + # @retval True Successfully find inf statement + # @retval False Not able to find inf statement + # + def __GetOptRomInfStatement(self, Obj): + + if not self.__IsKeyword( "INF"): + return False + + ffsInf = OptRomInfStatement.OptRomInfStatement() + self.__GetInfOptions( ffsInf) + + if not self.__GetNextToken(): + raise Warning("expected INF file path", self.FileName, self.CurrentLineNumber) + ffsInf.InfFileName = self.__Token + + if not ffsInf.InfFileName in self.Profile.InfList: + self.Profile.InfList.append(ffsInf.InfFileName) + + + self.__GetOptRomOverrides (ffsInf) + + Obj.FfsList.append(ffsInf) + return True + + ## __GetOptRomOverrides() method + # + # Get overrides for OptROM INF & FILE + # + # @param self The object pointer + # @param FfsInfObj for whom overrides is got + # + def __GetOptRomOverrides(self, Obj): + if self.__IsToken('{'): + Overrides = OptionRom.OverrideAttribs() + if self.__IsKeyword( "PCI_VENDOR_ID"): + if not self.__IsToken( "="): + raise Warning("expected '='", self.FileName, self.CurrentLineNumber) + if not self.__GetNextHexNumber(): + raise Warning("expected Hex vendor id", self.FileName, self.CurrentLineNumber) + Overrides.PciVendorId = self.__Token + + if self.__IsKeyword( "PCI_CLASS_CODE"): + if not self.__IsToken( "="): + raise Warning("expected '='", self.FileName, self.CurrentLineNumber) + if not self.__GetNextHexNumber(): + raise Warning("expected Hex class code", self.FileName, self.CurrentLineNumber) + Overrides.PciClassCode = self.__Token + + if self.__IsKeyword( "PCI_DEVICE_ID"): + if not self.__IsToken( "="): + raise Warning("expected '='", self.FileName, self.CurrentLineNumber) + if not self.__GetNextHexNumber(): + raise Warning("expected Hex device id", self.FileName, self.CurrentLineNumber) + + Overrides.PciDeviceId = self.__Token + + if self.__IsKeyword( "PCI_REVISION"): + if not self.__IsToken( "="): + raise Warning("expected '='", self.FileName, self.CurrentLineNumber) + if not self.__GetNextHexNumber(): + raise Warning("expected Hex revision", self.FileName, self.CurrentLineNumber) + Overrides.PciRevision = self.__Token + + if self.__IsKeyword( "COMPRESS"): + if not self.__IsToken( "="): + raise Warning("expected '='", self.FileName, self.CurrentLineNumber) + if not self.__GetNextToken(): + raise Warning("expected TRUE/FALSE for compress", self.FileName, self.CurrentLineNumber) + + if self.__Token.upper() == 'TRUE': + Overrides.NeedCompress = True + + if not self.__IsToken( "}"): + + if self.__Token not in ("PCI_CLASS_CODE", "PCI_VENDOR_ID", "PCI_DEVICE_ID", "PCI_REVISION", "COMPRESS"): + raise Warning("unknown attribute %s" % self.__Token, self.FileName, self.CurrentLineNumber) + + raise Warning("expected '}'", self.FileName, self.CurrentLineNumber) + + Obj.OverrideAttribs = Overrides + + ## __GetOptRomFileStatement() method + # + # Get FILE statements + # + # @param self The object pointer + # @param Obj for whom FILE statement is got + # @retval True Successfully find FILE statement + # @retval False Not able to find FILE statement + # + def __GetOptRomFileStatement(self, Obj): + + if not self.__IsKeyword( "FILE"): + return False + + FfsFileObj = OptRomFileStatement.OptRomFileStatement() + + if not self.__IsKeyword("EFI") and not self.__IsKeyword("BIN"): + raise Warning("expected Binary type (EFI/BIN)", self.FileName, self.CurrentLineNumber) + FfsFileObj.FileType = self.__Token + + if not self.__GetNextToken(): + raise Warning("expected File path", self.FileName, self.CurrentLineNumber) + FfsFileObj.FileName = self.__Token + + if FfsFileObj.FileType == 'EFI': + self.__GetOptRomOverrides(FfsFileObj) + + Obj.FfsList.append(FfsFileObj) + + return True + + + ## __GetFvInFd() method + # + # Get FV list contained in FD + # + # @param self The object pointer + # @param FdName FD name + # @retval FvList list of FV in FD + # + def __GetFvInFd (self, FdName): + + FvList = [] + if FdName.upper() in self.Profile.FdDict.keys(): + FdObj = self.Profile.FdDict[FdName.upper()] + for elementRegion in FdObj.RegionList: + if elementRegion.RegionType == 'FV': + for elementRegionData in elementRegion.RegionDataList: + if elementRegionData != None and elementRegionData.upper() not in FvList: + FvList.append(elementRegionData.upper()) + return FvList + + ## __GetReferencedFdFvTuple() method + # + # Get FD and FV list referenced by a FFS file + # + # @param self The object pointer + # @param FfsFile contains sections to be searched + # @param RefFdList referenced FD by section + # @param RefFvList referenced FV by section + # + def __GetReferencedFdFvTuple(self, FvObj, RefFdList = [], RefFvList = []): + + for FfsObj in FvObj.FfsList: + if isinstance(FfsObj, FfsFileStatement.FileStatement): + if FfsObj.FvName != None and FfsObj.FvName.upper() not in RefFvList: + RefFvList.append(FfsObj.FvName.upper()) + elif FfsObj.FdName != None and FfsObj.FdName.upper() not in RefFdList: + RefFdList.append(FfsObj.FdName.upper()) + else: + self.__GetReferencedFdFvTupleFromSection(FfsObj, RefFdList, RefFvList) + + ## __GetReferencedFdFvTupleFromSection() method + # + # Get FD and FV list referenced by a FFS section + # + # @param self The object pointer + # @param FfsFile contains sections to be searched + # @param FdList referenced FD by section + # @param FvList referenced FV by section + # + def __GetReferencedFdFvTupleFromSection(self, FfsFile, FdList = [], FvList = []): + + SectionStack = [] + SectionStack.extend(FfsFile.SectionList) + while SectionStack != []: + SectionObj = SectionStack.pop() + if isinstance(SectionObj, FvImageSection.FvImageSection): + if SectionObj.FvName != None and SectionObj.FvName.upper() not in FvList: + FvList.append(SectionObj.FvName.upper()) + if SectionObj.Fv != None and SectionObj.Fv.UiFvName != None and SectionObj.Fv.UiFvName.upper() not in FvList: + FvList.append(SectionObj.Fv.UiFvName.upper()) + self.__GetReferencedFdFvTuple(SectionObj.Fv, FdList, FvList) + + if isinstance(SectionObj, CompressSection.CompressSection) or isinstance(SectionObj, GuidSection.GuidSection): + SectionStack.extend(SectionObj.SectionList) + + ## CycleReferenceCheck() method + # + # Check whether cycle reference exists in FDF + # + # @param self The object pointer + # @retval True cycle reference exists + # @retval False Not exists cycle reference + # + def CycleReferenceCheck(self): + + CycleRefExists = False + + try: + for FvName in self.Profile.FvDict.keys(): + LogStr = "Cycle Reference Checking for FV: %s\n" % FvName + RefFvStack = [] + RefFvStack.append(FvName) + FdAnalyzedList = [] + + while RefFvStack != []: + FvNameFromStack = RefFvStack.pop() + if FvNameFromStack.upper() in self.Profile.FvDict.keys(): + FvObj = self.Profile.FvDict[FvNameFromStack.upper()] + else: + continue + + RefFdList = [] + RefFvList = [] + self.__GetReferencedFdFvTuple(FvObj, RefFdList, RefFvList) + + for RefFdName in RefFdList: + if RefFdName in FdAnalyzedList: + continue + + LogStr += "FD %s is referenced by FV %s\n" % (RefFdName, FvNameFromStack) + FvInFdList = self.__GetFvInFd(RefFdName) + if FvInFdList != []: + LogStr += "FD %s contains FV: " % RefFdName + for FvObj in FvInFdList: + LogStr += FvObj + LogStr += ' \n' + if FvObj not in RefFvStack: + RefFvStack.append(FvObj) + + if FvName in RefFvStack: + CycleRefExists = True + raise Warning(LogStr) + FdAnalyzedList.append(RefFdName) + + for RefFvName in RefFvList: + LogStr += "FV %s is referenced by FV %s\n" % (RefFvName, FvNameFromStack) + if RefFvName not in RefFvStack: + RefFvStack.append(RefFvName) + + if FvName in RefFvStack: + CycleRefExists = True + raise Warning(LogStr) + + except Warning: + print LogStr + + finally: + return CycleRefExists + +if __name__ == "__main__": + parser = FdfParser("..\LakeportX64Pkg.fdf") + try: + parser.ParseFile() + parser.CycleReferenceCheck() + except Warning, X: + print str(X) + else: + print "Success!" + diff --git a/BaseTools/Source/Python/GenFds/Ffs.py b/BaseTools/Source/Python/GenFds/Ffs.py new file mode 100644 index 0000000000..aaa791763b --- /dev/null +++ b/BaseTools/Source/Python/GenFds/Ffs.py @@ -0,0 +1,81 @@ +## @file +# process FFS generation +# +# Copyright (c) 2007, 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. +# + +## +# Import Modules +# +from CommonDataClass.FdfClass import FDClassObject + +## generate FFS +# +# +class Ffs(FDClassObject): + + # mapping between MODULE type in FDF (from INF) and file type for GenFfs + ModuleTypeToFileType = { + 'SEC' : 'EFI_FV_FILETYPE_SECURITY_CORE', + 'PEI_CORE' : 'EFI_FV_FILETYPE_PEI_CORE', + 'PEIM' : 'EFI_FV_FILETYPE_PEIM', + 'DXE_CORE' : 'EFI_FV_FILETYPE_DXE_CORE', + 'DXE_DRIVER' : 'EFI_FV_FILETYPE_DRIVER', + 'DXE_SAL_DRIVER' : 'EFI_FV_FILETYPE_DRIVER', + 'DXE_SMM_DRIVER' : 'EFI_FV_FILETYPE_DRIVER', + 'DXE_RUNTIME_DRIVER': 'EFI_FV_FILETYPE_DRIVER', + 'UEFI_DRIVER' : 'EFI_FV_FILETYPE_DRIVER', + 'UEFI_APPLICATION' : 'EFI_FV_FILETYPE_APPLICATION', + 'SMM_DRIVER' : 'EFI_FV_FILETYPE_SMM', + 'SMM_CORE' : 'EFI_FV_FILETYPE_SMM_CORE' + } + + # mapping between FILE type in FDF and file type for GenFfs + FdfFvFileTypeToFileType = { + 'SEC' : 'EFI_FV_FILETYPE_SECURITY_CORE', + 'PEI_CORE' : 'EFI_FV_FILETYPE_PEI_CORE', + 'PEIM' : 'EFI_FV_FILETYPE_PEIM', + 'DXE_CORE' : 'EFI_FV_FILETYPE_DXE_CORE', + 'FREEFORM' : 'EFI_FV_FILETYPE_FREEFORM', + 'DRIVER' : 'EFI_FV_FILETYPE_DRIVER', + 'APPLICATION' : 'EFI_FV_FILETYPE_APPLICATION', + 'FV_IMAGE' : 'EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE', + 'RAW' : 'EFI_FV_FILETYPE_RAW', + 'PEI_DXE_COMBO' : 'EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER', + 'SMM_DXE_COMBO' : 'EFI_FV_FILETYPE_COMBINED_SMM_DXE', + 'SMM' : 'EFI_FV_FILETYPE_SMM', + 'SMM_CORE' : 'EFI_FV_FILETYPE_SMM_CORE' + } + + # mapping between section type in FDF and file suffix + SectionSuffix = { + 'PE32' : '.pe32', + 'PIC' : '.pic', + 'TE' : '.te', + 'DXE_DEPEX' : '.dpx', + 'VERSION' : '.ver', + 'UI' : '.ui', + 'COMPAT16' : '.com16', + 'RAW' : '.raw', + 'FREEFORM_SUBTYPE_GUID': '.guid', + 'FV_IMAGE' : 'fv.sec', + 'COMPRESS' : '.com', + 'GUIDED' : '.guided', + 'PEI_DEPEX' : '.dpx', + 'SMM_DEPEX' : '.smm' + } + + ## The constructor + # + # @param self The object pointer + # + def __init__(self): + FfsClassObject.__init__(self) diff --git a/BaseTools/Source/Python/GenFds/FfsFileStatement.py b/BaseTools/Source/Python/GenFds/FfsFileStatement.py new file mode 100644 index 0000000000..ed778f3d44 --- /dev/null +++ b/BaseTools/Source/Python/GenFds/FfsFileStatement.py @@ -0,0 +1,118 @@ +## @file +# process FFS generation from FILE statement +# +# Copyright (c) 2007, 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. +# + +## +# Import Modules +# +import Ffs +import Rule +from GenFdsGlobalVariable import GenFdsGlobalVariable +import os +import StringIO +import subprocess +from CommonDataClass.FdfClass import FileStatementClassObject +from Common import EdkLogger +from Common.BuildToolError import * +from Common.Misc import GuidStructureByteArrayToGuidString + +## generate FFS from FILE +# +# +class FileStatement (FileStatementClassObject) : + ## The constructor + # + # @param self The object pointer + # + def __init__(self): + FileStatementClassObject.__init__(self) + + ## GenFfs() method + # + # Generate FFS + # + # @param self The object pointer + # @param Dict dictionary contains macro and value pair + # @retval string Generated FFS file name + # + def GenFfs(self, Dict = {}): + + if self.NameGuid != None and self.NameGuid.startswith('PCD('): + PcdValue = GenFdsGlobalVariable.GetPcdValue(self.NameGuid) + if len(PcdValue) == 0: + EdkLogger.error("GenFds", GENFDS_ERROR, '%s NOT defined.' \ + % (self.NameGuid)) + if PcdValue.startswith('{'): + PcdValue = GuidStructureByteArrayToGuidString(PcdValue) + RegistryGuidStr = PcdValue + if len(RegistryGuidStr) == 0: + EdkLogger.error("GenFds", GENFDS_ERROR, 'GUID value for %s in wrong format.' \ + % (self.NameGuid)) + self.NameGuid = RegistryGuidStr + + OutputDir = os.path.join(GenFdsGlobalVariable.FfsDir, self.NameGuid) + if not os.path.exists(OutputDir): + os.makedirs(OutputDir) + + Dict.update(self.DefineVarDict) + SectionAlignments = None + if self.FvName != None : + Buffer = StringIO.StringIO('') + if self.FvName.upper() not in GenFdsGlobalVariable.FdfParser.Profile.FvDict.keys(): + EdkLogger.error("GenFds", GENFDS_ERROR, "FV (%s) is NOT described in FDF file!" % (self.FvName)) + Fv = GenFdsGlobalVariable.FdfParser.Profile.FvDict.get(self.FvName.upper()) + FileName = Fv.AddToBuffer(Buffer) + SectionFiles = [FileName] + + elif self.FdName != None: + if self.FdName.upper() not in GenFdsGlobalVariable.FdfParser.Profile.FdDict.keys(): + EdkLogger.error("GenFds", GENFDS_ERROR, "FD (%s) is NOT described in FDF file!" % (self.FdName)) + Fd = GenFdsGlobalVariable.FdfParser.Profile.FdDict.get(self.FdName.upper()) + FvBin = {} + FileName = Fd.GenFd(FvBin) + SectionFiles = [FileName] + + elif self.FileName != None: + self.FileName = GenFdsGlobalVariable.ReplaceWorkspaceMacro(self.FileName) + SectionFiles = [GenFdsGlobalVariable.MacroExtend(self.FileName, Dict)] + + else: + SectionFiles = [] + Index = 0 + SectionAlignments = [] + for section in self.SectionList : + Index = Index + 1 + SecIndex = '%d' %Index + sectList, align = section.GenSection(OutputDir, self.NameGuid, SecIndex, self.KeyStringList, None, Dict) + if sectList != []: + for sect in sectList: + SectionFiles.append(sect) + SectionAlignments.append(align) + + # + # Prepare the parameter + # + FfsFileOutput = os.path.join(OutputDir, self.NameGuid + '.ffs') + GenFdsGlobalVariable.GenerateFfs(FfsFileOutput, SectionFiles, + Ffs.Ffs.FdfFvFileTypeToFileType.get(self.FvFileType), + self.NameGuid, + Fixed=self.Fixed, + CheckSum=self.CheckSum, + Align=self.Alignment, + SectionAlign=SectionAlignments + ) + + return FfsFileOutput + + + diff --git a/BaseTools/Source/Python/GenFds/FfsInfStatement.py b/BaseTools/Source/Python/GenFds/FfsInfStatement.py new file mode 100644 index 0000000000..0dcd96da2e --- /dev/null +++ b/BaseTools/Source/Python/GenFds/FfsInfStatement.py @@ -0,0 +1,582 @@ +## @file +# process FFS generation from INF statement +# +# Copyright (c) 2007, 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. +# + +## +# Import Modules +# +import Rule +import os +import shutil +from GenFdsGlobalVariable import GenFdsGlobalVariable +import Ffs +import subprocess +import sys +import Section +import RuleSimpleFile +import RuleComplexFile +from CommonDataClass.FdfClass import FfsInfStatementClassObject +from Common.String import * +from Common.Misc import PathClass +from Common.Misc import GuidStructureByteArrayToGuidString +from Common import EdkLogger +from Common.BuildToolError import * + +## generate FFS from INF +# +# +class FfsInfStatement(FfsInfStatementClassObject): + ## The constructor + # + # @param self The object pointer + # + def __init__(self): + FfsInfStatementClassObject.__init__(self) + self.TargetOverrideList = [] + self.ShadowFromInfFile = None + self.KeepRelocFromRule = None + self.InDsc = True + self.OptRomDefs = {} + + ## __InfParse() method + # + # Parse inf file to get module information + # + # @param self The object pointer + # @param Dict dictionary contains macro and value pair + # + def __InfParse__(self, Dict = {}): + + GenFdsGlobalVariable.VerboseLogger( " Begine parsing INf file : %s" %self.InfFileName) + + self.InfFileName = self.InfFileName.replace('$(WORKSPACE)', '') + if self.InfFileName[0] == '\\' or self.InfFileName[0] == '/' : + self.InfFileName = self.InfFileName[1:] + + if self.InfFileName.find('$') == -1: + InfPath = NormPath(self.InfFileName) + if not os.path.exists(InfPath): + InfPath = GenFdsGlobalVariable.ReplaceWorkspaceMacro(InfPath) + if not os.path.exists(InfPath): + EdkLogger.error("GenFds", GENFDS_ERROR, "Non-existant Module %s !" % (self.InfFileName)) + + self.CurrentArch = self.GetCurrentArch() + # + # Get the InfClass object + # + + PathClassObj = PathClass(self.InfFileName, GenFdsGlobalVariable.WorkSpaceDir) + ErrorCode, ErrorInfo = PathClassObj.Validate() + if ErrorCode != 0: + EdkLogger.error("GenFds", ErrorCode, ExtraData=ErrorInfo) + + if self.CurrentArch != None: + + Inf = GenFdsGlobalVariable.WorkSpace.BuildObject[PathClassObj, self.CurrentArch] + # + # Set Ffs BaseName, MdouleGuid, ModuleType, Version, OutputPath + # + self.BaseName = Inf.BaseName + self.ModuleGuid = Inf.Guid + self.ModuleType = Inf.ModuleType + if Inf.AutoGenVersion < 0x00010005: + self.ModuleType = Inf.ComponentType + self.VersionString = Inf.Version + self.BinFileList = Inf.Binaries + self.SourceFileList = Inf.Sources + if self.KeepReloc == None and Inf.Shadow: + self.ShadowFromInfFile = Inf.Shadow + + else: + Inf = GenFdsGlobalVariable.WorkSpace.BuildObject[PathClassObj, 'COMMON'] + self.BaseName = Inf.BaseName + self.ModuleGuid = Inf.Guid + self.ModuleType = Inf.ModuleType + self.VersionString = Inf.Version + self.BinFileList = Inf.Binaries + self.SourceFileList = Inf.Sources + if self.BinFileList == []: + EdkLogger.error("GenFds", GENFDS_ERROR, + "INF %s specified in FDF could not be found in build ARCH %s!" \ + % (self.InfFileName, GenFdsGlobalVariable.ArchList)) + + if len(self.SourceFileList) != 0 and not self.InDsc: + EdkLogger.warn("GenFds", GENFDS_ERROR, "Module %s NOT found in DSC file; Is it really a binary module?" % (self.InfFileName)) + + if Inf._Defs != None and len(Inf._Defs) > 0: + self.OptRomDefs.update(Inf._Defs) + + GenFdsGlobalVariable.VerboseLogger( "BaseName : %s" %self.BaseName) + GenFdsGlobalVariable.VerboseLogger("ModuleGuid : %s" %self.ModuleGuid) + GenFdsGlobalVariable.VerboseLogger("ModuleType : %s" %self.ModuleType) + GenFdsGlobalVariable.VerboseLogger("VersionString : %s" %self.VersionString) + GenFdsGlobalVariable.VerboseLogger("InfFileName :%s" %self.InfFileName) + + # + # Set OutputPath = ${WorkSpace}\Build\Fv\Ffs\${ModuleGuid}+ ${MdouleName}\ + # + + self.OutputPath = os.path.join(GenFdsGlobalVariable.FfsDir, \ + self.ModuleGuid + self.BaseName) + if not os.path.exists(self.OutputPath) : + os.makedirs(self.OutputPath) + + self.EfiOutputPath = self.__GetEFIOutPutPath__() + GenFdsGlobalVariable.VerboseLogger( "ModuelEFIPath: " + self.EfiOutputPath) + + ## GenFfs() method + # + # Generate FFS + # + # @param self The object pointer + # @param Dict dictionary contains macro and value pair + # @retval string Generated FFS file name + # + def GenFfs(self, Dict = {}): + # + # Parse Inf file get Module related information + # + + self.__InfParse__(Dict) + # + # Get the rule of how to generate Ffs file + # + Rule = self.__GetRule__() + GenFdsGlobalVariable.VerboseLogger( "Packing binaries from inf file : %s" %self.InfFileName) + #FileType = Ffs.Ffs.ModuleTypeToFileType[Rule.ModuleType] + # + # For the rule only has simpleFile + # + if isinstance (Rule, RuleSimpleFile.RuleSimpleFile) : + SectionOutputList = self.__GenSimpleFileSection__(Rule) + FfsOutput = self.__GenSimpleFileFfs__(Rule, SectionOutputList) + return FfsOutput + # + # For Rule has ComplexFile + # + elif isinstance(Rule, RuleComplexFile.RuleComplexFile): + InputSectList, InputSectAlignments = self.__GenComplexFileSection__(Rule) + FfsOutput = self.__GenComplexFileFfs__(Rule, InputSectList, InputSectAlignments) + + return FfsOutput + + ## __ExtendMacro__() method + # + # Replace macro with its value + # + # @param self The object pointer + # @param String The string to be replaced + # @retval string Macro replaced string + # + def __ExtendMacro__ (self, String): + MacroDict = { + '$(INF_OUTPUT)' : self.EfiOutputPath, + '$(MODULE_NAME)' : self.BaseName, + '$(BUILD_NUMBER)': self.BuildNum, + '$(INF_VERSION)' : self.VersionString, + '$(NAMED_GUID)' : self.ModuleGuid + } + String = GenFdsGlobalVariable.MacroExtend(String, MacroDict) + return String + + ## __GetRule__() method + # + # Get correct rule for generating FFS for this INF + # + # @param self The object pointer + # @retval Rule Rule object + # + def __GetRule__ (self) : + CurrentArchList = [] + if self.CurrentArch == None: + CurrentArchList = ['common'] + else: + CurrentArchList.append(self.CurrentArch) + + for CurrentArch in CurrentArchList: + RuleName = 'RULE' + \ + '.' + \ + CurrentArch.upper() + \ + '.' + \ + self.ModuleType.upper() + if self.Rule != None: + RuleName = RuleName + \ + '.' + \ + self.Rule.upper() + + Rule = GenFdsGlobalVariable.FdfParser.Profile.RuleDict.get(RuleName) + if Rule != None: + GenFdsGlobalVariable.VerboseLogger ("Want To Find Rule Name is : " + RuleName) + return Rule + + RuleName = 'RULE' + \ + '.' + \ + 'COMMON' + \ + '.' + \ + self.ModuleType.upper() + + if self.Rule != None: + RuleName = RuleName + \ + '.' + \ + self.Rule.upper() + + GenFdsGlobalVariable.VerboseLogger ('Trying to apply common rule %s for INF %s' % (RuleName, self.InfFileName)) + + Rule = GenFdsGlobalVariable.FdfParser.Profile.RuleDict.get(RuleName) + if Rule != None: + GenFdsGlobalVariable.VerboseLogger ("Want To Find Rule Name is : " + RuleName) + return Rule + + if Rule == None : + EdkLogger.error("GenFds", GENFDS_ERROR, 'Don\'t Find common rule %s for INF %s' \ + % (RuleName, self.InfFileName)) + + ## __GetPlatformArchList__() method + # + # Get Arch list this INF built under + # + # @param self The object pointer + # @retval list Arch list + # + def __GetPlatformArchList__(self): + + InfFileKey = os.path.normpath(os.path.join(GenFdsGlobalVariable.WorkSpaceDir, self.InfFileName)) + DscArchList = [] + PlatformDataBase = GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, 'IA32'] + if PlatformDataBase != None: + if InfFileKey in PlatformDataBase.Modules: + DscArchList.append ('IA32') + + PlatformDataBase = GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, 'X64'] + if PlatformDataBase != None: + if InfFileKey in PlatformDataBase.Modules: + DscArchList.append ('X64') + + PlatformDataBase = GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, 'IPF'] + if PlatformDataBase != None: + if InfFileKey in (PlatformDataBase.Modules): + DscArchList.append ('IPF') + + PlatformDataBase = GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, 'ARM'] + if PlatformDataBase != None: + if InfFileKey in (PlatformDataBase.Modules): + DscArchList.append ('ARM') + + PlatformDataBase = GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, 'EBC'] + if PlatformDataBase != None: + if InfFileKey in (PlatformDataBase.Modules): + DscArchList.append ('EBC') + + return DscArchList + + ## GetCurrentArch() method + # + # Get Arch list of the module from this INF is to be placed into flash + # + # @param self The object pointer + # @retval list Arch list + # + def GetCurrentArch(self) : + + TargetArchList = GenFdsGlobalVariable.ArchList + + PlatformArchList = self.__GetPlatformArchList__() + + CurArchList = TargetArchList + if PlatformArchList != []: + CurArchList = list(set (TargetArchList) & set (PlatformArchList)) + GenFdsGlobalVariable.VerboseLogger ("Valid target architecture(s) is : " + " ".join(CurArchList)) + + ArchList = [] + if self.KeyStringList != []: + for Key in self.KeyStringList: + Key = GenFdsGlobalVariable.MacroExtend(Key) + Target, Tag, Arch = Key.split('_') + if Arch in CurArchList: + ArchList.append(Arch) + if Target not in self.TargetOverrideList: + self.TargetOverrideList.append(Target) + else: + ArchList = CurArchList + + UseArchList = TargetArchList + if self.UseArch != None: + UseArchList = [] + UseArchList.append(self.UseArch) + ArchList = list(set (UseArchList) & set (ArchList)) + + self.InfFileName = NormPath(self.InfFileName) + if len(PlatformArchList) == 0: + self.InDsc = False + PathClassObj = PathClass(self.InfFileName, GenFdsGlobalVariable.WorkSpaceDir) + ErrorCode, ErrorInfo = PathClassObj.Validate() + if ErrorCode != 0: + EdkLogger.error("GenFds", ErrorCode, ExtraData=ErrorInfo) + if len(ArchList) == 1: + Arch = ArchList[0] + return Arch + elif len(ArchList) > 1: + if len(PlatformArchList) == 0: + EdkLogger.error("GenFds", GENFDS_ERROR, "GenFds command line option has multiple ARCHs %s. Not able to determine which ARCH is valid for Module %s !" % (str(ArchList), self.InfFileName)) + else: + EdkLogger.error("GenFds", GENFDS_ERROR, "Module built under multiple ARCHs %s. Not able to determine which output to put into flash for Module %s !" % (str(ArchList), self.InfFileName)) + else: + EdkLogger.error("GenFds", GENFDS_ERROR, "Module %s appears under ARCH %s in platform %s, but current deduced ARCH is %s, so NO build output could be put into flash." \ + % (self.InfFileName, str(PlatformArchList), GenFdsGlobalVariable.ActivePlatform, str(set (UseArchList) & set (TargetArchList)))) + + ## __GetEFIOutPutPath__() method + # + # Get the output path for generated files + # + # @param self The object pointer + # @retval string Path that output files from this INF go to + # + def __GetEFIOutPutPath__(self): + Arch = '' + OutputPath = '' + (ModulePath, FileName) = os.path.split(self.InfFileName) + Index = FileName.find('.') + FileName = FileName[0:Index] + Arch = "NoneArch" + if self.CurrentArch != None: + Arch = self.CurrentArch + + OutputPath = os.path.join(GenFdsGlobalVariable.OutputDirDict[Arch], + Arch , + ModulePath, + FileName, + 'OUTPUT' + ) + OutputPath = os.path.realpath(OutputPath) + return OutputPath + + ## __GenSimpleFileSection__() method + # + # Generate section by specified file name or a list of files with file extension + # + # @param self The object pointer + # @param Rule The rule object used to generate section + # @retval string File name of the generated section file + # + def __GenSimpleFileSection__(self, Rule): + # + # Prepare the parameter of GenSection + # + FileList = [] + OutputFileList = [] + if Rule.FileName != None: + GenSecInputFile = self.__ExtendMacro__(Rule.FileName) + else: + FileList, IsSect = Section.Section.GetFileList(self, '', Rule.FileExtension) + + Index = 1 + SectionType = Rule.SectionType + NoStrip = True + if self.ModuleType in ('SEC', 'PEI_CORE', 'PEIM'): + if self.KeepReloc != None: + NoStrip = self.KeepReloc + elif Rule.KeepReloc != None: + NoStrip = Rule.KeepReloc + elif self.ShadowFromInfFile != None: + NoStrip = self.ShadowFromInfFile + + if FileList != [] : + for File in FileList: + + SecNum = '%d' %Index + GenSecOutputFile= self.__ExtendMacro__(Rule.NameGuid) + \ + Ffs.Ffs.SectionSuffix[SectionType] + 'SEC' + SecNum + Index = Index + 1 + OutputFile = os.path.join(self.OutputPath, GenSecOutputFile) + + if not NoStrip: + FileBeforeStrip = os.path.join(self.OutputPath, ModuleName + '.reloc') + if not os.path.exists(FileBeforeStrip) or \ + (os.path.getmtime(File) > os.path.getmtime(FileBeforeStrip)): + shutil.copyfile(File, FileBeforeStrip) + StrippedFile = os.path.join(self.OutputPath, ModuleName + '.stipped') + GenFdsGlobalVariable.GenerateFirmwareImage( + StrippedFile, + [GenFdsGlobalVariable.MacroExtend(File, Dict, self.CurrentArch)], + Strip=True + ) + File = StrippedFile + + if SectionType == 'TE': + TeFile = os.path.join( self.OutputPath, self.ModuleGuid + 'Te.raw') + GenFdsGlobalVariable.GenerateFirmwareImage( + TeFile, + [GenFdsGlobalVariable.MacroExtend(File, Dict, self.CurrentArch)], + Type='te' + ) + File = TeFile + + GenFdsGlobalVariable.GenerateSection(OutputFile, [File], Section.Section.SectionType[SectionType]) + OutputFileList.append(OutputFile) + else: + SecNum = '%d' %Index + GenSecOutputFile= self.__ExtendMacro__(Rule.NameGuid) + \ + Ffs.Ffs.SectionSuffix[SectionType] + 'SEC' + SecNum + OutputFile = os.path.join(self.OutputPath, GenSecOutputFile) + + if not NoStrip: + FileBeforeStrip = os.path.join(self.OutputPath, ModuleName + '.reloc') + if not os.path.exists(FileBeforeStrip) or \ + (os.path.getmtime(GenSecInputFile) > os.path.getmtime(FileBeforeStrip)): + shutil.copyfile(GenSecInputFile, FileBeforeStrip) + StrippedFile = os.path.join(self.OutputPath, ModuleName + '.stipped') + GenFdsGlobalVariable.GenerateFirmwareImage( + StrippedFile, + [GenFdsGlobalVariable.MacroExtend(GenSecInputFile, Dict, self.CurrentArch)], + Strip=True + ) + GenSecInputFile = StrippedFile + + if SectionType == 'TE': + TeFile = os.path.join( self.OutputPath, self.ModuleGuid + 'Te.raw') + GenFdsGlobalVariable.GenerateFirmwareImage( + TeFile, + [GenFdsGlobalVariable.MacroExtend(File, Dict, self.CurrentArch)], + Type='te' + ) + GenSecInputFile = TeFile + + GenFdsGlobalVariable.GenerateSection(OutputFile, [GenSecInputFile], Section.Section.SectionType[SectionType]) + OutputFileList.append(OutputFile) + + return OutputFileList + + ## __GenSimpleFileFfs__() method + # + # Generate FFS + # + # @param self The object pointer + # @param Rule The rule object used to generate section + # @param InputFileList The output file list from GenSection + # @retval string Generated FFS file name + # + def __GenSimpleFileFfs__(self, Rule, InputFileList): + FfsOutput = self.OutputPath + \ + os.sep + \ + self.__ExtendMacro__(Rule.NameGuid) + \ + '.ffs' + + GenFdsGlobalVariable.VerboseLogger(self.__ExtendMacro__(Rule.NameGuid)) + InputSection = [] + SectionAlignments = [] + for InputFile in InputFileList: + InputSection.append(InputFile) + SectionAlignments.append(Rule.Alignment) + + if Rule.NameGuid != None and Rule.NameGuid.startswith('PCD('): + PcdValue = GenFdsGlobalVariable.GetPcdValue(Rule.NameGuid) + if len(PcdValue) == 0: + EdkLogger.error("GenFds", GENFDS_ERROR, '%s NOT defined.' \ + % (Rule.NameGuid)) + if PcdValue.startswith('{'): + PcdValue = GuidStructureByteArrayToGuidString(PcdValue) + RegistryGuidStr = PcdValue + if len(RegistryGuidStr) == 0: + EdkLogger.error("GenFds", GENFDS_ERROR, 'GUID value for %s in wrong format.' \ + % (Rule.NameGuid)) + self.ModuleGuid = RegistryGuidStr + + GenFdsGlobalVariable.GenerateFfs(FfsOutput, InputSection, + Ffs.Ffs.FdfFvFileTypeToFileType[Rule.FvFileType], + self.ModuleGuid, Fixed=Rule.Fixed, + CheckSum=Rule.CheckSum, Align=Rule.Alignment, + SectionAlign=SectionAlignments + ) + return FfsOutput + + ## __GenComplexFileSection__() method + # + # Generate section by sections in Rule + # + # @param self The object pointer + # @param Rule The rule object used to generate section + # @retval string File name of the generated section file + # + def __GenComplexFileSection__(self, Rule): + if self.ModuleType in ('SEC', 'PEI_CORE', 'PEIM'): + if Rule.KeepReloc != None: + self.KeepRelocFromRule = Rule.KeepReloc + SectFiles = [] + SectAlignments = [] + Index = 1 + for Sect in Rule.SectionList: + SecIndex = '%d' %Index + SectList = [] + if Rule.KeyStringList != []: + SectList, Align = Sect.GenSection(self.OutputPath , self.ModuleGuid, SecIndex, Rule.KeyStringList, self) + else : + SectList, Align = Sect.GenSection(self.OutputPath , self.ModuleGuid, SecIndex, self.KeyStringList, self) + for SecName in SectList : + SectFiles.append(SecName) + SectAlignments.append(Align) + Index = Index + 1 + return SectFiles, SectAlignments + + ## __GenComplexFileFfs__() method + # + # Generate FFS + # + # @param self The object pointer + # @param Rule The rule object used to generate section + # @param InputFileList The output file list from GenSection + # @retval string Generated FFS file name + # + def __GenComplexFileFfs__(self, Rule, InputFile, Alignments): + + if Rule.NameGuid != None and Rule.NameGuid.startswith('PCD('): + PcdValue = GenFdsGlobalVariable.GetPcdValue(Rule.NameGuid) + if len(PcdValue) == 0: + EdkLogger.error("GenFds", GENFDS_ERROR, '%s NOT defined.' \ + % (Rule.NameGuid)) + if PcdValue.startswith('{'): + PcdValue = GuidStructureByteArrayToGuidString(PcdValue) + RegistryGuidStr = PcdValue + if len(RegistryGuidStr) == 0: + EdkLogger.error("GenFds", GENFDS_ERROR, 'GUID value for %s in wrong format.' \ + % (Rule.NameGuid)) + self.ModuleGuid = RegistryGuidStr + + FfsOutput = os.path.join( self.OutputPath, self.ModuleGuid + '.ffs') + GenFdsGlobalVariable.GenerateFfs(FfsOutput, InputFile, + Ffs.Ffs.FdfFvFileTypeToFileType[Rule.FvFileType], + self.ModuleGuid, Fixed=Rule.Fixed, + CheckSum=Rule.CheckSum, Align=Rule.Alignment, + SectionAlign=Alignments + ) + return FfsOutput + + ## __GetGenFfsCmdParameter__() method + # + # Create parameter string for GenFfs + # + # @param self The object pointer + # @param Rule The rule object used to generate section + # @retval tuple (FileType, Fixed, CheckSum, Alignment) + # + def __GetGenFfsCmdParameter__(self, Rule): + result = tuple() + result += ('-t', Ffs.Ffs.FdfFvFileTypeToFileType[Rule.FvFileType]) + if Rule.Fixed != False: + result += ('-x',) + if Rule.CheckSum != False: + result += ('-s',) + + if Rule.Alignment != None and Rule.Alignment != '': + result += ('-a', Rule.Alignment) + + return result diff --git a/BaseTools/Source/Python/GenFds/Fv.py b/BaseTools/Source/Python/GenFds/Fv.py new file mode 100644 index 0000000000..74248f71c3 --- /dev/null +++ b/BaseTools/Source/Python/GenFds/Fv.py @@ -0,0 +1,215 @@ +## @file +# process FV generation +# +# Copyright (c) 2007, 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. +# + +## +# Import Modules +# +import os +import shutil +import subprocess +import StringIO + +import Ffs +import AprioriSection +from GenFdsGlobalVariable import GenFdsGlobalVariable +from GenFds import GenFds +from CommonDataClass.FdfClass import FvClassObject +from Common.Misc import SaveFileOnChange + +T_CHAR_LF = '\n' + +## generate FV +# +# +class FV (FvClassObject): + ## The constructor + # + # @param self The object pointer + # + def __init__(self): + FvClassObject.__init__(self) + self.FvInfFile = None + self.FvAddressFile = None + self.BaseAddress = None + self.InfFileName = None + self.FvAddressFileName = None + + ## AddToBuffer() + # + # Generate Fv and add it to the Buffer + # + # @param self The object pointer + # @param Buffer The buffer generated FV data will be put + # @param BaseAddress base address of FV + # @param BlockSize block size of FV + # @param BlockNum How many blocks in FV + # @param ErasePolarity Flash erase polarity + # @param VtfDict VTF objects + # @param MacroDict macro value pair + # @retval string Generated FV file path + # + def AddToBuffer (self, Buffer, BaseAddress=None, BlockSize= None, BlockNum=None, ErasePloarity='1', VtfDict=None, MacroDict = {}) : + + if self.UiFvName.upper() in GenFds.FvBinDict.keys(): + return GenFds.FvBinDict[self.UiFvName.upper()] + + GenFdsGlobalVariable.InfLogger( "\nGenerating %s FV ..." %self.UiFvName) + + self.__InitializeInf__(BaseAddress, BlockSize, BlockNum, ErasePloarity, VtfDict) + # + # First Process the Apriori section + # + MacroDict.update(self.DefineVarDict) + + GenFdsGlobalVariable.VerboseLogger('First generate Apriori file !') + FfsFileList = [] + for AprSection in self.AprioriSectionList: + FileName = AprSection.GenFfs (self.UiFvName, MacroDict) + FfsFileList.append(FileName) + # Add Apriori file name to Inf file + self.FvInfFile.writelines("EFI_FILE_NAME = " + \ + FileName + \ + T_CHAR_LF) + + # Process Modules in FfsList + for FfsFile in self.FfsList : + FileName = FfsFile.GenFfs(MacroDict) + FfsFileList.append(FileName) + self.FvInfFile.writelines("EFI_FILE_NAME = " + \ + FileName + \ + T_CHAR_LF) + + SaveFileOnChange(self.InfFileName, self.FvInfFile.getvalue(), False) + self.FvInfFile.close() + # + # Call GenFv tool + # + FvOutputFile = os.path.join(GenFdsGlobalVariable.FvDir, self.UiFvName) + FvOutputFile = FvOutputFile + '.Fv' + # BUGBUG: FvOutputFile could be specified from FDF file (FV section, CreateFile statement) + if self.CreateFileName != None: + FvOutputFile = self.CreateFileName + + FvInfoFileName = os.path.join(GenFdsGlobalVariable.FfsDir, self.UiFvName + '.inf') + shutil.copy(GenFdsGlobalVariable.FvAddressFileName, FvInfoFileName) + GenFdsGlobalVariable.GenerateFirmwareVolume( + FvOutputFile, + [self.InfFileName], + AddressFile=FvInfoFileName, + FfsList=FfsFileList + ) + + # + # Write the Fv contents to Buffer + # + FvFileObj = open ( FvOutputFile,'r+b') + + GenFdsGlobalVariable.InfLogger( "\nGenerate %s FV Successfully" %self.UiFvName) + GenFdsGlobalVariable.SharpCounter = 0 + + Buffer.write(FvFileObj.read()) + FvFileObj.close() + GenFds.FvBinDict[self.UiFvName.upper()] = FvOutputFile + return FvOutputFile + + ## __InitializeInf__() + # + # Initilize the inf file to create FV + # + # @param self The object pointer + # @param BaseAddress base address of FV + # @param BlockSize block size of FV + # @param BlockNum How many blocks in FV + # @param ErasePolarity Flash erase polarity + # @param VtfDict VTF objects + # + def __InitializeInf__ (self, BaseAddress = None, BlockSize= None, BlockNum = None, ErasePloarity='1', VtfDict=None) : + # + # Create FV inf file + # + self.InfFileName = os.path.join(GenFdsGlobalVariable.FvDir, + self.UiFvName + '.inf') + self.FvInfFile = StringIO.StringIO() + + # + # Add [Options] + # + self.FvInfFile.writelines("[options]" + T_CHAR_LF) + if BaseAddress != None : + self.FvInfFile.writelines("EFI_BASE_ADDRESS = " + \ + BaseAddress + \ + T_CHAR_LF) + + if BlockSize != None: + self.FvInfFile.writelines("EFI_BLOCK_SIZE = " + \ + '0x%X' %BlockSize + \ + T_CHAR_LF) + if BlockNum != None: + self.FvInfFile.writelines("EFI_NUM_BLOCKS = " + \ + ' 0x%X' %BlockNum + \ + T_CHAR_LF) + else: + for BlockSize in self.BlockSizeList : + if BlockSize[0] != None: + self.FvInfFile.writelines("EFI_BLOCK_SIZE = " + \ + '0x%X' %BlockSize[0] + \ + T_CHAR_LF) + + if BlockSize[1] != None: + self.FvInfFile.writelines("EFI_NUM_BLOCKS = " + \ + ' 0x%X' %BlockSize[1] + \ + T_CHAR_LF) + + if self.BsBaseAddress != None: + self.FvInfFile.writelines('EFI_BOOT_DRIVER_BASE_ADDRESS = ' + \ + '0x%X' %self.BsBaseAddress) + if self.RtBaseAddress != None: + self.FvInfFile.writelines('EFI_RUNTIME_DRIVER_BASE_ADDRESS = ' + \ + '0x%X' %self.RtBaseAddress) + # + # Add attribute + # + self.FvInfFile.writelines("[attributes]" + T_CHAR_LF) + + self.FvInfFile.writelines("EFI_ERASE_POLARITY = " + \ + ' %s' %ErasePloarity + \ + T_CHAR_LF) + if not (self.FvAttributeDict == None): + for FvAttribute in self.FvAttributeDict.keys() : + self.FvInfFile.writelines("EFI_" + \ + FvAttribute + \ + ' = ' + \ + self.FvAttributeDict[FvAttribute] + \ + T_CHAR_LF ) + if self.FvAlignment != None: + self.FvInfFile.writelines("EFI_FVB2_ALIGNMENT_" + \ + self.FvAlignment.strip() + \ + " = TRUE" + \ + T_CHAR_LF) + + if self.FvNameGuid != None: + self.FvInfFile.writelines("EFI_FVNAME_GUID" + \ + " = %s" % self.FvNameGuid + \ + T_CHAR_LF) + # + # Add [Files] + # + + self.FvInfFile.writelines("[files]" + T_CHAR_LF) + if VtfDict != None and self.UiFvName in VtfDict.keys(): + self.FvInfFile.writelines("EFI_FILE_NAME = " + \ + VtfDict.get(self.UiFvName) + \ + T_CHAR_LF) + + diff --git a/BaseTools/Source/Python/GenFds/FvImageSection.py b/BaseTools/Source/Python/GenFds/FvImageSection.py new file mode 100644 index 0000000000..3a3e714228 --- /dev/null +++ b/BaseTools/Source/Python/GenFds/FvImageSection.py @@ -0,0 +1,90 @@ +## @file +# process FV image section generation +# +# Copyright (c) 2007, 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. +# + +## +# Import Modules +# +import Section +import StringIO +from Ffs import Ffs +import subprocess +from GenFdsGlobalVariable import GenFdsGlobalVariable +import os +from CommonDataClass.FdfClass import FvImageSectionClassObject +from Common import EdkLogger +from Common.BuildToolError import * + +## generate FV image section +# +# +class FvImageSection(FvImageSectionClassObject): + + ## The constructor + # + # @param self The object pointer + # + def __init__(self): + FvImageSectionClassObject.__init__(self) + + ## GenSection() method + # + # Generate FV image section + # + # @param self The object pointer + # @param OutputPath Where to place output file + # @param ModuleName Which module this section belongs to + # @param SecNum Index of section + # @param KeyStringList Filter for inputs of section generation + # @param FfsInf FfsInfStatement object that contains this section data + # @param Dict dictionary contains macro and its value + # @retval tuple (Generated file name, section alignment) + # + def GenSection(self, OutputPath, ModuleName, SecNum, KeyStringList, FfsInf = None, Dict = {}): + + OutputFileList = [] + if self.FvFileType != None: + FileList, IsSect = Section.Section.GetFileList(FfsInf, self.FvFileType, self.FvFileExtension) + if IsSect : + return FileList, self.Alignment + + Num = SecNum + + for FileName in FileList: + OutputFile = os.path.join(OutputPath, ModuleName + 'SEC' + Num + Ffs.SectionSuffix.get("FV_IMAGE")) + GenFdsGlobalVariable.GenerateSection(OutputFile, [FvFileName], 'EFI_SECTION_FIRMWARE_VOLUME_IMAGE') + OutputFileList.append(OutputFile) + return OutputFileList, self.Alignment + # + # Generate Fv + # + if self.FvName != None: + Buffer = StringIO.StringIO('') + Fv = GenFdsGlobalVariable.FdfParser.Profile.FvDict.get(self.FvName) + if Fv != None: + self.Fv = Fv + FvFileName = self.Fv.AddToBuffer(Buffer, MacroDict = Dict) + else: + if self.FvFileName != None: + FvFileName = GenFdsGlobalVariable.ReplaceWorkspaceMacro(self.FvFileName) + else: + EdkLogger.error("GenFds", GENFDS_ERROR, "FvImageSection Failed! %s NOT found in FDF" % self.FvName) + + # + # Prepare the parameter of GenSection + # + OutputFile = os.path.join(OutputPath, ModuleName + 'SEC' + SecNum + Ffs.SectionSuffix.get("FV_IMAGE")) + GenFdsGlobalVariable.GenerateSection(OutputFile, [FvFileName], 'EFI_SECTION_FIRMWARE_VOLUME_IMAGE') + OutputFileList.append(OutputFile) + + return OutputFileList, self.Alignment diff --git a/BaseTools/Source/Python/GenFds/GenFds.py b/BaseTools/Source/Python/GenFds/GenFds.py new file mode 100644 index 0000000000..2bc416f828 --- /dev/null +++ b/BaseTools/Source/Python/GenFds/GenFds.py @@ -0,0 +1,486 @@ +## @file +# generate flash image +# +# Copyright (c) 2007, 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. +# + +## +# Import Modules +# +from optparse import OptionParser +import sys +import os +import linecache +import FdfParser +from Common.BuildToolError import * +from GenFdsGlobalVariable import GenFdsGlobalVariable +from Workspace.WorkspaceDatabase import WorkspaceDatabase +from Workspace.BuildClassObject import PcdClassObject +from Workspace.BuildClassObject import ModuleBuildClassObject +import RuleComplexFile +from EfiSection import EfiSection +import StringIO +import Common.TargetTxtClassObject as TargetTxtClassObject +import Common.ToolDefClassObject as ToolDefClassObject +import Common.DataType +import Common.GlobalData as GlobalData +from Common import EdkLogger +from Common.String import * +from Common.Misc import DirCache,PathClass + +## Version and Copyright +versionNumber = "1.0" +__version__ = "%prog Version " + versionNumber +__copyright__ = "Copyright (c) 2007, Intel Corporation All rights reserved." + +## Tool entrance method +# +# This method mainly dispatch specific methods per the command line options. +# If no error found, return zero value so the caller of this tool can know +# if it's executed successfully or not. +# +# @retval 0 Tool was successful +# @retval 1 Tool failed +# +def main(): + global Options + Options = myOptionParser() + + global Workspace + Workspace = "" + ArchList = None + ReturnCode = 0 + + EdkLogger.Initialize() + try: + if Options.verbose != None: + EdkLogger.SetLevel(EdkLogger.VERBOSE) + GenFdsGlobalVariable.VerboseMode = True + + if Options.FixedAddress != None: + GenFdsGlobalVariable.FixedLoadAddress = True + + if Options.quiet != None: + EdkLogger.SetLevel(EdkLogger.QUIET) + if Options.debug != None: + EdkLogger.SetLevel(Options.debug + 1) + GenFdsGlobalVariable.DebugLevel = Options.debug + else: + EdkLogger.SetLevel(EdkLogger.INFO) + + if (Options.Workspace == None): + EdkLogger.error("GenFds", BuildToolError.OPTION_MISSING, "WORKSPACE not defined", + ExtraData="Please use '-w' switch to pass it or set the WORKSPACE environment variable.") + elif not os.path.exists(Options.Workspace): + EdkLogger.error("GenFds", BuildToolError.PARAMETER_INVALID, "WORKSPACE is invalid", + ExtraData="Please use '-w' switch to pass it or set the WORKSPACE environment variable.") + else: + Workspace = os.path.normcase(Options.Workspace) + GenFdsGlobalVariable.WorkSpaceDir = Workspace + if 'EDK_SOURCE' in os.environ.keys(): + GenFdsGlobalVariable.EdkSourceDir = os.path.normcase(os.environ['EDK_SOURCE']) + if (Options.debug): + GenFdsGlobalVariable.VerboseLogger( "Using Workspace:" + Workspace) + os.chdir(GenFdsGlobalVariable.WorkSpaceDir) + + if (Options.filename): + FdfFilename = Options.filename + FdfFilename = GenFdsGlobalVariable.ReplaceWorkspaceMacro(FdfFilename) + else: + EdkLogger.error("GenFds", BuildToolError.OPTION_MISSING, "Missing FDF filename") + + if (Options.BuildTarget): + GenFdsGlobalVariable.TargetName = Options.BuildTarget + else: + EdkLogger.error("GenFds", BuildToolError.OPTION_MISSING, "Missing build target") + + if (Options.ToolChain): + GenFdsGlobalVariable.ToolChainTag = Options.ToolChain + else: + EdkLogger.error("GenFds", BuildToolError.OPTION_MISSING, "Missing tool chain tag") + + if FdfFilename[0:2] == '..': + FdfFilename = os.path.realpath(FdfFilename) + if FdfFilename[1] != ':': + FdfFilename = os.path.join(GenFdsGlobalVariable.WorkSpaceDir, FdfFilename) + + if not os.path.exists(FdfFilename): + EdkLogger.error("GenFds", BuildToolError.FILE_NOT_FOUND, ExtraData=FdfFilename) + GenFdsGlobalVariable.FdfFile = FdfFilename + GenFdsGlobalVariable.FdfFileTimeStamp = os.path.getmtime(FdfFilename) + + if (Options.activePlatform): + ActivePlatform = Options.activePlatform + ActivePlatform = GenFdsGlobalVariable.ReplaceWorkspaceMacro(ActivePlatform) + + if ActivePlatform[0:2] == '..': + ActivePlatform = os.path.realpath(ActivePlatform) + + if ActivePlatform[1] != ':': + ActivePlatform = os.path.join(GenFdsGlobalVariable.WorkSpaceDir, ActivePlatform) + + if not os.path.exists(ActivePlatform) : + EdkLogger.error("GenFds", BuildToolError.FILE_NOT_FOUND, "ActivePlatform doesn't exist!") + + if ActivePlatform.find(Workspace) == -1: + EdkLogger.error("GenFds", BuildToolError.FILE_NOT_FOUND, "ActivePlatform doesn't exist in Workspace!") + + ActivePlatform = ActivePlatform.replace(Workspace, '') + if len(ActivePlatform) > 0 : + if ActivePlatform[0] == '\\' or ActivePlatform[0] == '/': + ActivePlatform = ActivePlatform[1:] + else: + EdkLogger.error("GenFds", BuildToolError.FILE_NOT_FOUND, "ActivePlatform doesn't exist!") + else : + EdkLogger.error("GenFds", BuildToolError.OPTION_MISSING, "Missing active platform") + + GenFdsGlobalVariable.ActivePlatform = PathClass(NormPath(ActivePlatform), Workspace) + + BuildConfigurationFile = os.path.normpath(os.path.join(GenFdsGlobalVariable.WorkSpaceDir, "Conf/target.txt")) + if os.path.isfile(BuildConfigurationFile) == True: + TargetTxtClassObject.TargetTxtClassObject(BuildConfigurationFile) + else: + EdkLogger.error("GenFds", BuildToolError.FILE_NOT_FOUND, ExtraData=BuildConfigurationFile) + + if Options.Macros: + for Pair in Options.Macros: + Pair.strip('"') + List = Pair.split('=') + if len(List) == 2: + FdfParser.InputMacroDict[List[0].strip()] = List[1].strip() + if List[0].strip() == "EFI_SOURCE": + GlobalData.gEfiSource = List[1].strip() + elif List[0].strip() == "EDK_SOURCE": + GlobalData.gEdkSource = List[1].strip() + else: + GlobalData.gEdkGlobal[List[0].strip()] = List[1].strip() + else: + FdfParser.InputMacroDict[List[0].strip()] = None + + """call Workspace build create database""" + os.environ["WORKSPACE"] = Workspace + BuildWorkSpace = WorkspaceDatabase(':memory:', GlobalData.gGlobalDefines) + BuildWorkSpace.InitDatabase() + + # + # Get files real name in workspace dir + # + GlobalData.gAllFiles = DirCache(Workspace) + GlobalData.gWorkspace = Workspace + + if (Options.archList) : + ArchList = Options.archList.split(',') + else: +# EdkLogger.error("GenFds", BuildToolError.OPTION_MISSING, "Missing build ARCH") + ArchList = BuildWorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, 'COMMON'].SupArchList + + TargetArchList = set(BuildWorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, 'COMMON'].SupArchList) & set(ArchList) + if len(TargetArchList) == 0: + EdkLogger.error("GenFds", GENFDS_ERROR, "Target ARCH %s not in platform supported ARCH %s" % (str(ArchList), str(BuildWorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, 'COMMON'].SupArchList))) + + for Arch in ArchList: + GenFdsGlobalVariable.OutputDirFromDscDict[Arch] = NormPath(BuildWorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, Arch].OutputDirectory) + + if (Options.outputDir): + OutputDirFromCommandLine = GenFdsGlobalVariable.ReplaceWorkspaceMacro(Options.outputDir) + for Arch in ArchList: + GenFdsGlobalVariable.OutputDirDict[Arch] = OutputDirFromCommandLine + else: + for Arch in ArchList: + GenFdsGlobalVariable.OutputDirDict[Arch] = os.path.join(GenFdsGlobalVariable.OutputDirFromDscDict[Arch], GenFdsGlobalVariable.TargetName + '_' + GenFdsGlobalVariable.ToolChainTag) + + for Key in GenFdsGlobalVariable.OutputDirDict: + OutputDir = GenFdsGlobalVariable.OutputDirDict[Key] + if OutputDir[0:2] == '..': + OutputDir = os.path.realpath(OutputDir) + + if OutputDir[1] != ':': + OutputDir = os.path.join (GenFdsGlobalVariable.WorkSpaceDir, OutputDir) + + if not os.path.exists(OutputDir): + EdkLogger.error("GenFds", BuildToolError.FILE_NOT_FOUND, ExtraData=OutputDir) + GenFdsGlobalVariable.OutputDirDict[Key] = OutputDir + + """ Parse Fdf file, has to place after build Workspace as FDF may contain macros from DSC file """ + FdfParserObj = FdfParser.FdfParser(FdfFilename) + FdfParserObj.ParseFile() + + if FdfParserObj.CycleReferenceCheck(): + EdkLogger.error("GenFds", BuildToolError.FORMAT_NOT_SUPPORTED, "Cycle Reference Detected in FDF file") + + if (Options.uiFdName) : + if Options.uiFdName.upper() in FdfParserObj.Profile.FdDict.keys(): + GenFds.OnlyGenerateThisFd = Options.uiFdName + else: + EdkLogger.error("GenFds", BuildToolError.OPTION_VALUE_INVALID, + "No such an FD in FDF file: %s" % Options.uiFdName) + + if (Options.uiFvName) : + if Options.uiFvName.upper() in FdfParserObj.Profile.FvDict.keys(): + GenFds.OnlyGenerateThisFv = Options.uiFvName + else: + EdkLogger.error("GenFds", BuildToolError.OPTION_VALUE_INVALID, + "No such an FV in FDF file: %s" % Options.uiFvName) + + """Modify images from build output if the feature of loading driver at fixed address is on.""" + if GenFdsGlobalVariable.FixedLoadAddress: + GenFds.PreprocessImage(BuildWorkSpace, GenFdsGlobalVariable.ActivePlatform) + """Call GenFds""" + GenFds.GenFd('', FdfParserObj, BuildWorkSpace, ArchList) + + """Display FV space info.""" + GenFds.DisplayFvSpaceInfo(FdfParserObj) + + except FdfParser.Warning, X: + EdkLogger.error(X.ToolName, BuildToolError.FORMAT_INVALID, File=X.FileName, Line=X.LineNumber, ExtraData=X.Message, RaiseError = False) + ReturnCode = BuildToolError.FORMAT_INVALID + except FatalError, X: + if Options.debug != None: + import traceback + EdkLogger.quiet(traceback.format_exc()) + ReturnCode = X.args[0] + except: + import traceback + EdkLogger.error( + "\nPython", + CODE_ERROR, + "Tools code failure", + ExtraData="Please submit bug report in www.TianoCore.org, attaching following call stack trace!\n", + RaiseError=False + ) + EdkLogger.quiet(traceback.format_exc()) + ReturnCode = CODE_ERROR + return ReturnCode + +gParamCheck = [] +def SingleCheckCallback(option, opt_str, value, parser): + if option not in gParamCheck: + setattr(parser.values, option.dest, value) + gParamCheck.append(option) + else: + parser.error("Option %s only allows one instance in command line!" % option) + +## Parse command line options +# +# Using standard Python module optparse to parse command line option of this tool. +# +# @retval Opt A optparse.Values object containing the parsed options +# @retval Args Target of build command +# +def myOptionParser(): + usage = "%prog [options] -f input_file -a arch_list -b build_target -p active_platform -t tool_chain_tag -D \"MacroName [= MacroValue]\"" + Parser = OptionParser(usage=usage,description=__copyright__,version="%prog " + str(versionNumber)) + Parser.add_option("-f", "--file", dest="filename", type="string", help="Name of FDF file to convert", action="callback", callback=SingleCheckCallback) + Parser.add_option("-a", "--arch", dest="archList", help="comma separated list containing one or more of: IA32, X64, IPF, ARM or EBC which should be built, overrides target.txt?s TARGET_ARCH") + Parser.add_option("-q", "--quiet", action="store_true", type=None, help="Disable all messages except FATAL ERRORS.") + Parser.add_option("-v", "--verbose", action="store_true", type=None, help="Turn on verbose output with informational messages printed.") + Parser.add_option("-d", "--debug", action="store", type="int", help="Enable debug messages at specified level.") + Parser.add_option("-p", "--platform", type="string", dest="activePlatform", help="Set the ACTIVE_PLATFORM, overrides target.txt ACTIVE_PLATFORM setting.", + action="callback", callback=SingleCheckCallback) + Parser.add_option("-w", "--workspace", type="string", dest="Workspace", default=os.environ.get('WORKSPACE'), help="Set the WORKSPACE", + action="callback", callback=SingleCheckCallback) + Parser.add_option("-o", "--outputDir", type="string", dest="outputDir", help="Name of Build Output directory", + action="callback", callback=SingleCheckCallback) + Parser.add_option("-r", "--rom_image", dest="uiFdName", help="Build the image using the [FD] section named by FdUiName.") + Parser.add_option("-i", "--FvImage", dest="uiFvName", help="Buld the FV image using the [FV] section named by UiFvName") + Parser.add_option("-b", "--buildtarget", type="choice", choices=['DEBUG','RELEASE'], dest="BuildTarget", help="Build TARGET is one of list: DEBUG, RELEASE.", + action="callback", callback=SingleCheckCallback) + Parser.add_option("-t", "--tagname", type="string", dest="ToolChain", help="Using the tools: TOOL_CHAIN_TAG name to build the platform.", + action="callback", callback=SingleCheckCallback) + Parser.add_option("-D", "--define", action="append", type="string", dest="Macros", help="Macro: \"Name [= Value]\".") + Parser.add_option("-s", "--specifyaddress", dest="FixedAddress", action="store_true", type=None, help="Specify driver load address.") + (Options, args) = Parser.parse_args() + return Options + +## The class implementing the EDK2 flash image generation process +# +# This process includes: +# 1. Collect workspace information, includes platform and module information +# 2. Call methods of Fd class to generate FD +# 3. Call methods of Fv class to generate FV that not belong to FD +# +class GenFds : + FdfParsef = None + # FvName in FDF, FvBinFile name + FvBinDict = {} + OnlyGenerateThisFd = None + OnlyGenerateThisFv = None + + ## GenFd() + # + # @param OutputDir Output directory + # @param FdfParser FDF contents parser + # @param Workspace The directory of workspace + # @param ArchList The Arch list of platform + # + def GenFd (OutputDir, FdfParser, WorkSpace, ArchList): + GenFdsGlobalVariable.SetDir ('', FdfParser, WorkSpace, ArchList) + + GenFdsGlobalVariable.VerboseLogger(" Gen Fd !") + if GenFds.OnlyGenerateThisFd != None and GenFds.OnlyGenerateThisFd.upper() in GenFdsGlobalVariable.FdfParser.Profile.FdDict.keys(): + FdObj = GenFdsGlobalVariable.FdfParser.Profile.FdDict.get(GenFds.OnlyGenerateThisFd.upper()) + if FdObj != None: + FdObj.GenFd(GenFds.FvBinDict) + elif GenFds.OnlyGenerateThisFv == None: + for FdName in GenFdsGlobalVariable.FdfParser.Profile.FdDict.keys(): + FdObj = GenFdsGlobalVariable.FdfParser.Profile.FdDict[FdName] + FdObj.GenFd(GenFds.FvBinDict) + + GenFdsGlobalVariable.VerboseLogger(" Gen FV ! ") + if GenFds.OnlyGenerateThisFv != None and GenFds.OnlyGenerateThisFv.upper() in GenFdsGlobalVariable.FdfParser.Profile.FvDict.keys(): + FvObj = GenFdsGlobalVariable.FdfParser.Profile.FvDict.get(GenFds.OnlyGenerateThisFv.upper()) + if FvObj != None: + Buffer = StringIO.StringIO() + # Get FV base Address + FvObj.AddToBuffer(Buffer, None, GenFds.GetFvBlockSize(FvObj)) + Buffer.close() + return + elif GenFds.OnlyGenerateThisFd == None: + for FvName in GenFdsGlobalVariable.FdfParser.Profile.FvDict.keys(): + Buffer = StringIO.StringIO('') + FvObj = GenFdsGlobalVariable.FdfParser.Profile.FvDict[FvName] + # Get FV base Address + FvObj.AddToBuffer(Buffer, None, GenFds.GetFvBlockSize(FvObj)) + Buffer.close() + + if GenFds.OnlyGenerateThisFv == None and GenFds.OnlyGenerateThisFd == None: + GenFdsGlobalVariable.VerboseLogger(" Gen Capsule !") + for CapsuleObj in GenFdsGlobalVariable.FdfParser.Profile.CapsuleList: + CapsuleObj.GenCapsule() + + if GenFdsGlobalVariable.FdfParser.Profile.OptRomDict != {}: + GenFdsGlobalVariable.VerboseLogger(" Gen Option ROM !") + for DriverName in GenFdsGlobalVariable.FdfParser.Profile.OptRomDict.keys(): + OptRomObj = GenFdsGlobalVariable.FdfParser.Profile.OptRomDict[DriverName] + OptRomObj.AddToBuffer(None) + + ## GetFvBlockSize() + # + # @param FvObj Whose block size to get + # @retval int Block size value + # + def GetFvBlockSize(FvObj): + DefaultBlockSize = 0x10000 + FdObj = None + if GenFds.OnlyGenerateThisFd != None and GenFds.OnlyGenerateThisFd.upper() in GenFdsGlobalVariable.FdfParser.Profile.FdDict.keys(): + FdObj = GenFdsGlobalVariable.FdfParser.Profile.FdDict[GenFds.OnlyGenerateThisFd.upper()] + if FdObj == None: + for ElementFd in GenFdsGlobalVariable.FdfParser.Profile.FdDict.values(): + for ElementRegion in ElementFd.RegionList: + if ElementRegion.RegionType == 'FV': + for ElementRegionData in ElementRegion.RegionDataList: + if ElementRegionData != None and ElementRegionData.upper() == FvObj.UiFvName: + if FvObj.BlockSizeList != []: + return FvObj.BlockSizeList[0][0] + else: + return ElementRegion.BlockSizeOfRegion(ElementFd.BlockSizeList) + if FvObj.BlockSizeList != []: + return FvObj.BlockSizeList[0][0] + return DefaultBlockSize + else: + for ElementRegion in FdObj.RegionList: + if ElementRegion.RegionType == 'FV': + for ElementRegionData in ElementRegion.RegionDataList: + if ElementRegionData != None and ElementRegionData.upper() == FvObj.UiFvName: + if FvObj.BlockSizeList != []: + return FvObj.BlockSizeList[0][0] + else: + return ElementRegion.BlockSizeOfRegion(ElementFd.BlockSizeList) + return DefaultBlockSize + + ## DisplayFvSpaceInfo() + # + # @param FvObj Whose block size to get + # @retval None + # + def DisplayFvSpaceInfo(FdfParser): + + FvSpaceInfoList = [] + MaxFvNameLength = 0 + for FvName in FdfParser.Profile.FvDict: + if len(FvName) > MaxFvNameLength: + MaxFvNameLength = len(FvName) + FvSpaceInfoFileName = os.path.join(GenFdsGlobalVariable.FvDir, FvName.upper() + '.Fv.map') + if os.path.exists(FvSpaceInfoFileName): + FileLinesList = linecache.getlines(FvSpaceInfoFileName) + TotalFound = False + Total = '' + UsedFound = False + Used = '' + FreeFound = False + Free = '' + for Line in FileLinesList: + NameValue = Line.split('=') + if len(NameValue) == 2: + if NameValue[0].strip() == 'EFI_FV_TOTAL_SIZE': + TotalFound = True + Total = NameValue[1].strip() + if NameValue[0].strip() == 'EFI_FV_TAKEN_SIZE': + UsedFound = True + Used = NameValue[1].strip() + if NameValue[0].strip() == 'EFI_FV_SPACE_SIZE': + FreeFound = True + Free = NameValue[1].strip() + + if TotalFound and UsedFound and FreeFound: + FvSpaceInfoList.append((FvName, Total, Used, Free)) + + GenFdsGlobalVariable.InfLogger('\nFV Space Information') + for FvSpaceInfo in FvSpaceInfoList: + Name = FvSpaceInfo[0] + TotalSizeValue = long(FvSpaceInfo[1], 0) + UsedSizeValue = long(FvSpaceInfo[2], 0) + FreeSizeValue = long(FvSpaceInfo[3], 0) + GenFdsGlobalVariable.InfLogger(Name + ' ' + '[' + str((UsedSizeValue+0.0)/TotalSizeValue)[0:4].lstrip('0.') + '%Full] ' + str(TotalSizeValue) + ' total, ' + str(UsedSizeValue) + ' used, ' + str(FreeSizeValue) + ' free') + + ## PreprocessImage() + # + # @param BuildDb Database from build meta data files + # @param DscFile modules from dsc file will be preprocessed + # @retval None + # + def PreprocessImage(BuildDb, DscFile): + PcdDict = BuildDb.BuildObject[DscFile, 'COMMON'].Pcds + PcdValue = '' + for Key in PcdDict: + PcdObj = PcdDict[Key] + if PcdObj.TokenCName == 'PcdBsBaseAddress': + PcdValue = PcdObj.DefaultValue + break + + if PcdValue == '': + return + + Int64PcdValue = long(PcdValue, 0) + if Int64PcdValue == 0 or Int64PcdValue < -1: + return + + TopAddress = 0 + if Int64PcdValue > 0: + TopAddress = Int64PcdValue + + ModuleDict = BuildDb.BuildObject[DscFile, 'COMMON'].Modules + for Key in ModuleDict: + ModuleObj = BuildDb.BuildObject[Key, 'COMMON'] + print ModuleObj.BaseName + ' ' + ModuleObj.ModuleType + + ##Define GenFd as static function + GenFd = staticmethod(GenFd) + GetFvBlockSize = staticmethod(GetFvBlockSize) + DisplayFvSpaceInfo = staticmethod(DisplayFvSpaceInfo) + PreprocessImage = staticmethod(PreprocessImage) + +if __name__ == '__main__': + r = main() + ## 0-127 is a safe return range, and 1 is a standard default error + if r < 0 or r > 127: r = 1 + sys.exit(r) + diff --git a/BaseTools/Source/Python/GenFds/GenFdsGlobalVariable.py b/BaseTools/Source/Python/GenFds/GenFdsGlobalVariable.py new file mode 100644 index 0000000000..d556ce7ade --- /dev/null +++ b/BaseTools/Source/Python/GenFds/GenFdsGlobalVariable.py @@ -0,0 +1,472 @@ +## @file +# Global variables for GenFds +# +# Copyright (c) 2007, 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. +# + +## +# Import Modules +# +import os +import sys +import subprocess +import struct +import array + +from Common.BuildToolError import * +from Common import EdkLogger +from Common.Misc import SaveFileOnChange + +## Global variables +# +# +class GenFdsGlobalVariable: + FvDir = '' + OutputDirDict = {} + BinDir = '' + # will be FvDir + os.sep + 'Ffs' + FfsDir = '' + FdfParser = None + LibDir = '' + WorkSpace = None + WorkSpaceDir = '' + EdkSourceDir = '' + OutputDirFromDscDict = {} + TargetName = '' + ToolChainTag = '' + RuleDict = {} + ArchList = None + VtfDict = {} + ActivePlatform = None + FvAddressFileName = '' + VerboseMode = False + DebugLevel = -1 + SharpCounter = 0 + SharpNumberPerLine = 40 + FdfFile = '' + FdfFileTimeStamp = 0 + FixedLoadAddress = False + + SectionHeader = struct.Struct("3B 1B") + + ## SetDir() + # + # @param OutputDir Output directory + # @param FdfParser FDF contents parser + # @param Workspace The directory of workspace + # @param ArchList The Arch list of platform + # + def SetDir (OutputDir, FdfParser, WorkSpace, ArchList): + GenFdsGlobalVariable.VerboseLogger( "GenFdsGlobalVariable.OutputDir :%s" %OutputDir) +# GenFdsGlobalVariable.OutputDirDict = OutputDir + GenFdsGlobalVariable.FdfParser = FdfParser + GenFdsGlobalVariable.WorkSpace = WorkSpace + GenFdsGlobalVariable.FvDir = os.path.join(GenFdsGlobalVariable.OutputDirDict[ArchList[0]], 'FV') + if not os.path.exists(GenFdsGlobalVariable.FvDir) : + os.makedirs(GenFdsGlobalVariable.FvDir) + GenFdsGlobalVariable.FfsDir = os.path.join(GenFdsGlobalVariable.FvDir, 'Ffs') + if not os.path.exists(GenFdsGlobalVariable.FfsDir) : + os.makedirs(GenFdsGlobalVariable.FfsDir) + if ArchList != None: + GenFdsGlobalVariable.ArchList = ArchList + + T_CHAR_LF = '\n' + # + # Create FV Address inf file + # + GenFdsGlobalVariable.FvAddressFileName = os.path.join(GenFdsGlobalVariable.FfsDir, 'FvAddress.inf') + FvAddressFile = open (GenFdsGlobalVariable.FvAddressFileName, 'w') + # + # Add [Options] + # + FvAddressFile.writelines("[options]" + T_CHAR_LF) + BsAddress = '0' + for Arch in ArchList: + if GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, Arch].BsBaseAddress: + BsAddress = GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, Arch].BsBaseAddress + break + + FvAddressFile.writelines("EFI_BOOT_DRIVER_BASE_ADDRESS = " + \ + BsAddress + \ + T_CHAR_LF) + + RtAddress = '0' + for Arch in ArchList: + if GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, Arch].RtBaseAddress: + RtAddress = GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, Arch].RtBaseAddress + + FvAddressFile.writelines("EFI_RUNTIME_DRIVER_BASE_ADDRESS = " + \ + RtAddress + \ + T_CHAR_LF) + + FvAddressFile.close() + + ## ReplaceWorkspaceMacro() + # + # @param String String that may contain macro + # + def ReplaceWorkspaceMacro(String): + Str = String.replace('$(WORKSPACE)', GenFdsGlobalVariable.WorkSpaceDir) + if os.path.exists(Str): + if not os.path.isabs(Str): + Str = os.path.abspath(Str) + else: + Str = os.path.join(GenFdsGlobalVariable.WorkSpaceDir, String) + return os.path.normpath(Str) + + ## Check if the input files are newer than output files + # + # @param Output Path of output file + # @param Input Path list of input files + # + # @retval True if Output doesn't exist, or any Input is newer + # @retval False if all Input is older than Output + # + @staticmethod + def NeedsUpdate(Output, Input): + if not os.path.exists(Output): + return True + # always update "Output" if no "Input" given + if Input == None or len(Input) == 0: + return True + + # if fdf file is changed after the 'Output" is generated, update the 'Output' + OutputTime = os.path.getmtime(Output) + if GenFdsGlobalVariable.FdfFileTimeStamp > OutputTime: + return True + + for F in Input: + # always update "Output" if any "Input" doesn't exist + if not os.path.exists(F): + return True + # always update "Output" if any "Input" is newer than "Output" + if os.path.getmtime(F) > OutputTime: + return True + return False + + @staticmethod + def GenerateSection(Output, Input, Type=None, CompressionType=None, Guid=None, + GuidHdrLen=None, GuidAttr=None, Ui=None, Ver=None): + if not GenFdsGlobalVariable.NeedsUpdate(Output, Input): + return + GenFdsGlobalVariable.DebugLogger(EdkLogger.DEBUG_5, "%s needs update because of newer %s" % (Output, Input)) + + Cmd = ["GenSec"] + if Type not in [None, '']: + Cmd += ["-s", Type] + if CompressionType not in [None, '']: + Cmd += ["-c", CompressionType] + if Guid != None: + Cmd += ["-g", Guid] + if GuidHdrLen not in [None, '']: + Cmd += ["-l", GuidHdrLen] + if GuidAttr not in [None, '']: + Cmd += ["-r", GuidAttr] + + if Ui not in [None, '']: + #Cmd += ["-n", '"' + Ui + '"'] + SectionData = array.array('B', [0,0,0,0]) + SectionData.fromstring(Ui.encode("utf_16_le")) + SectionData.append(0) + SectionData.append(0) + Len = len(SectionData) + GenFdsGlobalVariable.SectionHeader.pack_into(SectionData, 0, Len & 0xff, (Len >> 8) & 0xff, (Len >> 16) & 0xff, 0x15) + SaveFileOnChange(Output, SectionData.tostring()) + elif Ver not in [None, '']: + #Cmd += ["-j", Ver] + SectionData = array.array('B', [0,0,0,0]) + SectionData.fromstring(Ver.encode("utf_16_le")) + SectionData.append(0) + SectionData.append(0) + Len = len(SectionData) + GenFdsGlobalVariable.SectionHeader.pack_into(SectionData, 0, Len & 0xff, (Len >> 8) & 0xff, (Len >> 16) & 0xff, 0x14) + SaveFileOnChange(Output, SectionData.tostring()) + else: + Cmd += ["-o", Output] + Cmd += Input + GenFdsGlobalVariable.CallExternalTool(Cmd, "Failed to generate section") + + @staticmethod + def GenerateFfs(Output, Input, Type, Guid, Fixed=False, CheckSum=False, Align=None, + SectionAlign=None): + if not GenFdsGlobalVariable.NeedsUpdate(Output, Input): + return + GenFdsGlobalVariable.DebugLogger(EdkLogger.DEBUG_5, "%s needs update because of newer %s" % (Output, Input)) + + Cmd = ["GenFfs", "-t", Type, "-g", Guid] + if Fixed == True: + Cmd += ["-x"] + if CheckSum: + Cmd += ["-s"] + if Align not in [None, '']: + Cmd += ["-a", Align] + + Cmd += ["-o", Output] + for I in range(0, len(Input)): + Cmd += ("-i", Input[I]) + if SectionAlign not in [None, '', []] and SectionAlign[I] not in [None, '']: + Cmd += ("-n", SectionAlign[I]) + GenFdsGlobalVariable.CallExternalTool(Cmd, "Failed to generate FFS") + + @staticmethod + def GenerateFirmwareVolume(Output, Input, BaseAddress=None, Capsule=False, Dump=False, + AddressFile=None, MapFile=None, FfsList=[]): + if not GenFdsGlobalVariable.NeedsUpdate(Output, Input+FfsList): + return + GenFdsGlobalVariable.DebugLogger(EdkLogger.DEBUG_5, "%s needs update because of newer %s" % (Output, Input)) + + Cmd = ["GenFv"] + if BaseAddress not in [None, '']: + Cmd += ["-r", BaseAddress] + if Capsule: + Cmd += ["-c"] + if Dump: + Cmd += ["-p"] + if AddressFile not in [None, '']: + Cmd += ["-a", AddressFile] + if MapFile not in [None, '']: + Cmd += ["-m", MapFile] + Cmd += ["-o", Output] + for I in Input: + Cmd += ["-i", I] + + GenFdsGlobalVariable.CallExternalTool(Cmd, "Failed to generate FV") + + @staticmethod + def GenerateVtf(Output, Input, BaseAddress=None, FvSize=None): + if not GenFdsGlobalVariable.NeedsUpdate(Output, Input): + return + GenFdsGlobalVariable.DebugLogger(EdkLogger.DEBUG_5, "%s needs update because of newer %s" % (Output, Input)) + + Cmd = ["GenVtf"] + if BaseAddress not in [None, ''] and FvSize not in [None, ''] \ + and len(BaseAddress) == len(FvSize): + for I in range(0, len(BaseAddress)): + Cmd += ["-r", BaseAddress[I], "-s", FvSize[I]] + Cmd += ["-o", Output] + for F in Input: + Cmd += ["-f", F] + + GenFdsGlobalVariable.CallExternalTool(Cmd, "Failed to generate VTF") + + @staticmethod + def GenerateFirmwareImage(Output, Input, Type="efi", SubType=None, Zero=False, + Strip=False, Replace=False, TimeStamp=None, Join=False, + Align=None, Padding=None, Convert=False): + if not GenFdsGlobalVariable.NeedsUpdate(Output, Input): + return + GenFdsGlobalVariable.DebugLogger(EdkLogger.DEBUG_5, "%s needs update because of newer %s" % (Output, Input)) + + Cmd = ["GenFw"] + if Type.lower() == "te": + Cmd += ["-t"] + if SubType not in [None, '']: + Cmd += ["-e", SubType] + if TimeStamp not in [None, '']: + Cmd += ["-s", TimeStamp] + if Align not in [None, '']: + Cmd += ["-a", Align] + if Padding not in [None, '']: + Cmd += ["-p", Padding] + if Zero: + Cmd += ["-z"] + if Strip: + Cmd += ["-l"] + if Replace: + Cmd += ["-r"] + if Join: + Cmd += ["-j"] + if Convert: + Cmd += ["-m"] + Cmd += ["-o", Output] + Cmd += Input + + GenFdsGlobalVariable.CallExternalTool(Cmd, "Failed to generate firmware image") + + @staticmethod + def GenerateOptionRom(Output, EfiInput, BinaryInput, Compress=False, ClassCode=None, + Revision=None, DeviceId=None, VendorId=None): +# if not GenFdsGlobalVariable.NeedsUpdate(Output, Input): +# return +# GenFdsGlobalVariable.DebugLogger(EdkLogger.DEBUG_5, "%s needs update because of newer %s" % (Output, Input)) + + Cmd = ["EfiRom"] + if len(EfiInput) > 0: + + if Compress: + Cmd += ["-ec"] + else: + Cmd += ["-e"] + + for EfiFile in EfiInput: + Cmd += [EfiFile] + + if len(BinaryInput) > 0: + Cmd += ["-b"] + for BinFile in BinaryInput: + Cmd += [BinFile] + + if ClassCode != None: + Cmd += ["-l", ClassCode] + if Revision != None: + Cmd += ["-r", Revision] + if DeviceId != None: + Cmd += ["-i", DeviceId] + if VendorId != None: + Cmd += ["-f", VendorId] + + Cmd += ["-o", Output] + GenFdsGlobalVariable.CallExternalTool(Cmd, "Failed to generate option rom") + + @staticmethod + def GuidTool(Output, Input, ToolPath, Options=''): + if not GenFdsGlobalVariable.NeedsUpdate(Output, Input): + return + GenFdsGlobalVariable.DebugLogger(EdkLogger.DEBUG_5, "%s needs update because of newer %s" % (Output, Input)) + + Cmd = [ToolPath, Options] + Cmd += ["-o", Output] + Cmd += Input + + GenFdsGlobalVariable.CallExternalTool(Cmd, "Failed to call " + ToolPath) + + def CallExternalTool (cmd, errorMess): + + if type(cmd) not in (tuple, list): + GenFdsGlobalVariable.ErrorLogger("ToolError! Invalid parameter type in call to CallExternalTool") + + if GenFdsGlobalVariable.DebugLevel != -1: + cmd += ('--debug', str(GenFdsGlobalVariable.DebugLevel)) + GenFdsGlobalVariable.InfLogger (cmd) + + if GenFdsGlobalVariable.VerboseMode: + cmd += ('-v',) + GenFdsGlobalVariable.InfLogger (cmd) + else: + sys.stdout.write ('#') + sys.stdout.flush() + GenFdsGlobalVariable.SharpCounter = GenFdsGlobalVariable.SharpCounter + 1 + if GenFdsGlobalVariable.SharpCounter % GenFdsGlobalVariable.SharpNumberPerLine == 0: + sys.stdout.write('\n') + + try: + PopenObject = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr= subprocess.PIPE) + except Exception, X: + EdkLogger.error("GenFds", BuildToolError.COMMAND_FAILURE, ExtraData="%s: %s" % (str(X), cmd[0])) + (out, error) = PopenObject.communicate() + + while PopenObject.returncode == None : + PopenObject.wait() + if PopenObject.returncode != 0 or GenFdsGlobalVariable.VerboseMode or GenFdsGlobalVariable.DebugLevel != -1: + GenFdsGlobalVariable.InfLogger ("Return Value = %d" %PopenObject.returncode) + GenFdsGlobalVariable.InfLogger (out) + GenFdsGlobalVariable.InfLogger (error) + if PopenObject.returncode != 0: + print "###", cmd + EdkLogger.error("GenFds", BuildToolError.COMMAND_FAILURE, errorMess) + + def VerboseLogger (msg): + EdkLogger.verbose(msg) + + def InfLogger (msg): + EdkLogger.info(msg) + + def ErrorLogger (msg, File = None, Line = None, ExtraData = None): + EdkLogger.error('GenFds', BuildToolError.GENFDS_ERROR, msg, File, Line, ExtraData) + + def DebugLogger (Level, msg): + EdkLogger.debug(Level, msg) + + ## ReplaceWorkspaceMacro() + # + # @param Str String that may contain macro + # @param MacroDict Dictionary that contains macro value pair + # + def MacroExtend (Str, MacroDict = {}, Arch = 'COMMON'): + if Str == None : + return None + + Dict = {'$(WORKSPACE)' : GenFdsGlobalVariable.WorkSpaceDir, + '$(EDK_SOURCE)' : GenFdsGlobalVariable.EdkSourceDir, +# '$(OUTPUT_DIRECTORY)': GenFdsGlobalVariable.OutputDirFromDsc, + '$(TARGET)' : GenFdsGlobalVariable.TargetName, + '$(TOOL_CHAIN_TAG)' : GenFdsGlobalVariable.ToolChainTag + } + OutputDir = GenFdsGlobalVariable.OutputDirFromDscDict[GenFdsGlobalVariable.ArchList[0]] + if Arch != 'COMMON' and Arch in GenFdsGlobalVariable.ArchList: + OutputDir = GenFdsGlobalVariable.OutputDirFromDscDict[Arch] + + Dict['$(OUTPUT_DIRECTORY)'] = OutputDir + + if MacroDict != None and len (MacroDict) != 0: + Dict.update(MacroDict) + + for key in Dict.keys(): + if Str.find(key) >= 0 : + Str = Str.replace (key, Dict[key]) + + if Str.find('$(ARCH)') >= 0: + if len(GenFdsGlobalVariable.ArchList) == 1: + Str = Str.replace('$(ARCH)', GenFdsGlobalVariable.ArchList[0]) + else: + EdkLogger.error("GenFds", GENFDS_ERROR, "No way to determine $(ARCH) for %s" % Str) + + return Str + + ## GetPcdValue() + # + # @param PcdPattern pattern that labels a PCD. + # + def GetPcdValue (PcdPattern): + if PcdPattern == None : + return None + PcdPair = PcdPattern.lstrip('PCD(').rstrip(')').strip().split('.') + TokenSpace = PcdPair[0] + TokenCName = PcdPair[1] + + PcdValue = '' + for Platform in GenFdsGlobalVariable.WorkSpace.PlatformList: + PcdDict = Platform.Pcds + for Key in PcdDict: + PcdObj = PcdDict[Key] + if (PcdObj.TokenCName == TokenCName) and (PcdObj.TokenSpaceGuidCName == TokenSpace): + if PcdObj.Type != 'FixedAtBuild': + EdkLogger.error("GenFds", GENFDS_ERROR, "%s is not FixedAtBuild type." % PcdPattern) + if PcdObj.DatumType != 'VOID*': + EdkLogger.error("GenFds", GENFDS_ERROR, "%s is not VOID* datum type." % PcdPattern) + + PcdValue = PcdObj.DefaultValue + return PcdValue + + for Package in GenFdsGlobalVariable.WorkSpace.PackageList: + PcdDict = Package.Pcds + for Key in PcdDict: + PcdObj = PcdDict[Key] + if (PcdObj.TokenCName == TokenCName) and (PcdObj.TokenSpaceGuidCName == TokenSpace): + if PcdObj.Type != 'FixedAtBuild': + EdkLogger.error("GenFds", GENFDS_ERROR, "%s is not FixedAtBuild type." % PcdPattern) + if PcdObj.DatumType != 'VOID*': + EdkLogger.error("GenFds", GENFDS_ERROR, "%s is not VOID* datum type." % PcdPattern) + + PcdValue = PcdObj.DefaultValue + return PcdValue + + return PcdValue + + SetDir = staticmethod(SetDir) + ReplaceWorkspaceMacro = staticmethod(ReplaceWorkspaceMacro) + CallExternalTool = staticmethod(CallExternalTool) + VerboseLogger = staticmethod(VerboseLogger) + InfLogger = staticmethod(InfLogger) + ErrorLogger = staticmethod(ErrorLogger) + DebugLogger = staticmethod(DebugLogger) + MacroExtend = staticmethod (MacroExtend) + GetPcdValue = staticmethod(GetPcdValue) diff --git a/BaseTools/Source/Python/GenFds/GuidSection.py b/BaseTools/Source/Python/GenFds/GuidSection.py new file mode 100644 index 0000000000..e111e0fe50 --- /dev/null +++ b/BaseTools/Source/Python/GenFds/GuidSection.py @@ -0,0 +1,190 @@ +## @file +# process GUIDed section generation +# +# Copyright (c) 2007, 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. +# + +## +# Import Modules +# +import Section +import subprocess +from Ffs import Ffs +import os +from GenFdsGlobalVariable import GenFdsGlobalVariable +from CommonDataClass.FdfClass import GuidSectionClassObject +from Common import ToolDefClassObject +import sys +from Common import EdkLogger +from Common.BuildToolError import * + +## generate GUIDed section +# +# +class GuidSection(GuidSectionClassObject) : + + ## The constructor + # + # @param self The object pointer + # + def __init__(self): + GuidSectionClassObject.__init__(self) + + ## GenSection() method + # + # Generate GUIDed section + # + # @param self The object pointer + # @param OutputPath Where to place output file + # @param ModuleName Which module this section belongs to + # @param SecNum Index of section + # @param KeyStringList Filter for inputs of section generation + # @param FfsInf FfsInfStatement object that contains this section data + # @param Dict dictionary contains macro and its value + # @retval tuple (Generated file name, section alignment) + # + def GenSection(self, OutputPath, ModuleName, SecNum, KeyStringList, FfsInf = None, Dict = {}): + # + # Generate all section + # + self.KeyStringList = KeyStringList + self.CurrentArchList = GenFdsGlobalVariable.ArchList + if FfsInf != None: + self.Alignment = FfsInf.__ExtendMacro__(self.Alignment) + self.NameGuid = FfsInf.__ExtendMacro__(self.NameGuid) + self.SectionType = FfsInf.__ExtendMacro__(self.SectionType) + self.CurrentArchList = [FfsInf.CurrentArch] + + SectFile = tuple() + Index = 0 + for Sect in self.SectionList: + Index = Index + 1 + SecIndex = '%s.%d' %(SecNum,Index) + ReturnSectList, align = Sect.GenSection(OutputPath, ModuleName, SecIndex, KeyStringList,FfsInf, Dict) + if ReturnSectList != []: + for file in ReturnSectList: + SectFile += (file,) + + + OutputFile = OutputPath + \ + os.sep + \ + ModuleName + \ + 'SEC' + \ + SecNum + \ + Ffs.SectionSuffix['GUIDED'] + OutputFile = os.path.normpath(OutputFile) + + ExternalTool = None + if self.NameGuid != None: + ExternalTool = self.__FindExtendTool__() + # + # If not have GUID , call default + # GENCRC32 section + # + if self.NameGuid == None : + GenFdsGlobalVariable.VerboseLogger( "Use GenSection function Generate CRC32 Section") + GenFdsGlobalVariable.GenerateSection(OutputFile, SectFile, Section.Section.SectionType[self.SectionType]) + OutputFileList = [] + OutputFileList.append(OutputFile) + return OutputFileList, self.Alignment + #or GUID not in External Tool List + elif ExternalTool == None: + EdkLogger.error("GenFds", GENFDS_ERROR, "No tool found with GUID %s" % self.NameGuid) + else: + # + # Call GenSection with DUMMY section type. + # + GenFdsGlobalVariable.GenerateSection(OutputFile+".dummy", SectFile) + # + # Use external tool process the Output + # + InputFile = OutputFile+".dummy" + TempFile = OutputPath + \ + os.sep + \ + ModuleName + \ + 'SEC' + \ + SecNum + \ + '.tmp' + TempFile = os.path.normpath(TempFile) + + ExternalToolCmd = ( + ExternalTool, + '-e', + '-o', TempFile, + InputFile, + ) + + # + # Call external tool + # + GenFdsGlobalVariable.GuidTool(TempFile, [InputFile], ExternalTool, '-e') + + # + # Call Gensection Add Secntion Header + # + Attribute = None + if self.ProcessRequired == True: + Attribute = 'PROCSSING_REQUIRED' + if self.AuthStatusValid == True: + Attribute = 'AUTH_STATUS_VALID' + GenFdsGlobalVariable.GenerateSection(OutputFile, [TempFile], Section.Section.SectionType['GUIDED'], + Guid=self.NameGuid, GuidAttr=Attribute) + OutputFileList = [] + OutputFileList.append(OutputFile) + return OutputFileList, self.Alignment + + ## __FindExtendTool() + # + # Find location of tools to process section data + # + # @param self The object pointer + # + def __FindExtendTool__(self): + # if user not specify filter, try to deduce it from global data. + if self.KeyStringList == None or self.KeyStringList == []: + Target = GenFdsGlobalVariable.TargetName + ToolChain = GenFdsGlobalVariable.ToolChainTag + ToolDb = ToolDefClassObject.ToolDefDict(GenFdsGlobalVariable.WorkSpaceDir).ToolsDefTxtDatabase + if ToolChain not in ToolDb['TOOL_CHAIN_TAG']: + EdkLogger.error("GenFds", GENFDS_ERROR, "Can not find external tool because tool tag %s is not defined in tools_def.txt!" % ToolChain) + self.KeyStringList = [Target+'_'+ToolChain+'_'+self.CurrentArchList[0]] + for Arch in self.CurrentArchList: + if Target+'_'+ToolChain+'_'+Arch not in self.KeyStringList: + self.KeyStringList.append(Target+'_'+ToolChain+'_'+Arch) + + ToolDefinition = ToolDefClassObject.ToolDefDict(GenFdsGlobalVariable.WorkSpaceDir).ToolsDefTxtDictionary + ToolPathTmp = None + for ToolDef in ToolDefinition.items(): + if self.NameGuid == ToolDef[1]: + KeyList = ToolDef[0].split('_') + Key = KeyList[0] + \ + '_' + \ + KeyList[1] + \ + '_' + \ + KeyList[2] + if Key in self.KeyStringList and KeyList[4] == 'GUID': + + ToolPath = ToolDefinition.get( Key + \ + '_' + \ + KeyList[3] + \ + '_' + \ + 'PATH') + if ToolPathTmp == None: + ToolPathTmp = ToolPath + else: + if ToolPathTmp != ToolPath: + EdkLogger.error("GenFds", GENFDS_ERROR, "Don't know which tool to use, %s or %s ?" % (ToolPathTmp, ToolPath)) + + + return ToolPathTmp + + + diff --git a/BaseTools/Source/Python/GenFds/OptRomFileStatement.py b/BaseTools/Source/Python/GenFds/OptRomFileStatement.py new file mode 100644 index 0000000000..c360c6d9ad --- /dev/null +++ b/BaseTools/Source/Python/GenFds/OptRomFileStatement.py @@ -0,0 +1,50 @@ +## @file +# process OptionROM generation from FILE statement +# +# Copyright (c) 2007, 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. +# + +## +# Import Modules +# +import os + +from GenFdsGlobalVariable import GenFdsGlobalVariable +## +# +# +class OptRomFileStatement: + ## The constructor + # + # @param self The object pointer + # + def __init__(self): + self.FileName = None + self.FileType = None + self.OverrideAttribs = None + + ## GenFfs() method + # + # Generate FFS + # + # @param self The object pointer + # @param Dict dictionary contains macro and value pair + # @retval string Generated FFS file name + # + def GenFfs(self, Dict = {}): + + if self.FileName != None: + self.FileName = GenFdsGlobalVariable.ReplaceWorkspaceMacro(self.FileName) + + return self.FileName + + + diff --git a/BaseTools/Source/Python/GenFds/OptRomInfStatement.py b/BaseTools/Source/Python/GenFds/OptRomInfStatement.py new file mode 100644 index 0000000000..b9f0af54c9 --- /dev/null +++ b/BaseTools/Source/Python/GenFds/OptRomInfStatement.py @@ -0,0 +1,147 @@ +## @file +# process OptionROM generation from INF statement +# +# Copyright (c) 2007, 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. +# + +## +# Import Modules +# +import RuleSimpleFile +import RuleComplexFile +import Section +import OptionRom +import Common.GlobalData as GlobalData + +from Common.DataType import * +from Common.String import * +from FfsInfStatement import FfsInfStatement +from GenFdsGlobalVariable import GenFdsGlobalVariable + +## +# +# +class OptRomInfStatement (FfsInfStatement): + ## The constructor + # + # @param self The object pointer + # + def __init__(self): + FfsInfStatement.__init__(self) + self.OverrideAttribs = None + + ## __GetOptRomParams() method + # + # Parse inf file to get option ROM related parameters + # + # @param self The object pointer + # + def __GetOptRomParams(self): + + if self.OverrideAttribs == None: + self.OverrideAttribs = OptionRom.OverrideAttribs() + + if self.OverrideAttribs.PciVendorId == None: + self.OverrideAttribs.PciVendorId = self.OptRomDefs.get ('PCI_VENDOR_ID') + + if self.OverrideAttribs.PciClassCode == None: + self.OverrideAttribs.PciClassCode = self.OptRomDefs.get ('PCI_CLASS_CODE') + + if self.OverrideAttribs.PciDeviceId == None: + self.OverrideAttribs.PciDeviceId = self.OptRomDefs.get ('PCI_DEVICE_ID') + + if self.OverrideAttribs.PciRevision == None: + self.OverrideAttribs.PciRevision = self.OptRomDefs.get ('PCI_REVISION') + +# InfObj = GenFdsGlobalVariable.WorkSpace.BuildObject[self.PathClassObj, self.CurrentArch] +# RecordList = InfObj._RawData[MODEL_META_DATA_HEADER, InfObj._Arch, InfObj._Platform] +# for Record in RecordList: +# Record = ReplaceMacros(Record, GlobalData.gEdkGlobal, False) +# Name = Record[0] + ## GenFfs() method + # + # Generate FFS + # + # @param self The object pointer + # @retval string Generated .efi file name + # + def GenFfs(self): + # + # Parse Inf file get Module related information + # + + self.__InfParse__() + self.__GetOptRomParams() + # + # Get the rule of how to generate Ffs file + # + Rule = self.__GetRule__() + GenFdsGlobalVariable.VerboseLogger( "Packing binaries from inf file : %s" %self.InfFileName) + #FileType = Ffs.Ffs.ModuleTypeToFileType[Rule.ModuleType] + # + # For the rule only has simpleFile + # + if isinstance (Rule, RuleSimpleFile.RuleSimpleFile) : + EfiOutputList = self.__GenSimpleFileSection__(Rule) + return EfiOutputList + # + # For Rule has ComplexFile + # + elif isinstance(Rule, RuleComplexFile.RuleComplexFile): + EfiOutputList = self.__GenComplexFileSection__(Rule) + return EfiOutputList + + ## __GenSimpleFileSection__() method + # + # Get .efi files according to simple rule. + # + # @param self The object pointer + # @param Rule The rule object used to generate section + # @retval string File name of the generated section file + # + def __GenSimpleFileSection__(self, Rule): + # + # Prepare the parameter of GenSection + # + + OutputFileList = [] + if Rule.FileName != None: + GenSecInputFile = self.__ExtendMacro__(Rule.FileName) + OutputFileList.append(GenSecInputFile) + else: + OutputFileList, IsSect = Section.Section.GetFileList(self, '', Rule.FileExtension) + + return OutputFileList + + + ## __GenComplexFileSection__() method + # + # Get .efi by sections in complex Rule + # + # @param self The object pointer + # @param Rule The rule object used to generate section + # @retval string File name of the generated section file + # + def __GenComplexFileSection__(self, Rule): + + OutputFileList = [] + for Sect in Rule.SectionList: + if Sect.SectionType == 'PE32': + if Sect.FileName != None: + GenSecInputFile = self.__ExtendMacro__(Sect.FileName) + OutputFileList.append(GenSecInputFile) + else: + FileList, IsSect = Section.Section.GetFileList(self, '', Sect.FileExtension) + OutputFileList.extend(FileList) + + return OutputFileList + + \ No newline at end of file diff --git a/BaseTools/Source/Python/GenFds/OptionRom.py b/BaseTools/Source/Python/GenFds/OptionRom.py new file mode 100644 index 0000000000..e102e65f1c --- /dev/null +++ b/BaseTools/Source/Python/GenFds/OptionRom.py @@ -0,0 +1,140 @@ +## @file +# process OptionROM generation +# +# Copyright (c) 2007, 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. +# + +## +# Import Modules +# +import os +import shutil +import subprocess +import StringIO + +import OptRomInfStatement +from GenFdsGlobalVariable import GenFdsGlobalVariable +from GenFds import GenFds +from CommonDataClass.FdfClass import OptionRomClassObject +from Common.Misc import SaveFileOnChange +from Common import EdkLogger +from Common.BuildToolError import * + +T_CHAR_LF = '\n' + +## +# +# +class OPTIONROM (OptionRomClassObject): + ## The constructor + # + # @param self The object pointer + # + def __init__(self): + OptionRomClassObject.__init__(self) + + + ## AddToBuffer() + # + # Generate Option ROM + # + # @param self The object pointer + # @param Buffer The buffer generated OptROM data will be put + # @retval string Generated OptROM file path + # + def AddToBuffer (self, Buffer) : + + GenFdsGlobalVariable.InfLogger( "\nGenerating %s Option ROM ..." %self.DriverName) + + EfiFileList = [] + BinFileList = [] + + # Process Modules in FfsList + for FfsFile in self.FfsList : + + if isinstance(FfsFile, OptRomInfStatement.OptRomInfStatement): + FilePathNameList = FfsFile.GenFfs() + if len(FilePathNameList) == 0: + EdkLogger.error("GenFds", GENFDS_ERROR, "Module %s not produce .efi files, so NO file could be put into option ROM." % (FfsFile.InfFileName)) + if FfsFile.OverrideAttribs == None: + EfiFileList.extend(FilePathNameList) + else: + FileName = os.path.basename(FilePathNameList[0]) + TmpOutputDir = os.path.join(GenFdsGlobalVariable.FvDir, self.DriverName) + if not os.path.exists(TmpOutputDir) : + os.makedirs(TmpOutputDir) + TmpOutputFile = os.path.join(TmpOutputDir, FileName+'.tmp') + + GenFdsGlobalVariable.GenerateOptionRom(TmpOutputFile, + FilePathNameList, + [], + FfsFile.OverrideAttribs.NeedCompress, + FfsFile.OverrideAttribs.PciClassCode, + FfsFile.OverrideAttribs.PciRevision, + FfsFile.OverrideAttribs.PciDeviceId, + FfsFile.OverrideAttribs.PciVendorId) + BinFileList.append(TmpOutputFile) + else: + FilePathName = FfsFile.GenFfs() + if FfsFile.OverrideAttribs != None: + FileName = os.path.basename(FilePathName) + TmpOutputDir = os.path.join(GenFdsGlobalVariable.FvDir, self.DriverName) + if not os.path.exists(TmpOutputDir) : + os.makedirs(TmpOutputDir) + TmpOutputFile = os.path.join(TmpOutputDir, FileName+'.tmp') + + GenFdsGlobalVariable.GenerateOptionRom(TmpOutputFile, + [FilePathName], + [], + FfsFile.OverrideAttribs.NeedCompress, + FfsFile.OverrideAttribs.PciClassCode, + FfsFile.OverrideAttribs.PciRevision, + FfsFile.OverrideAttribs.PciDeviceId, + FfsFile.OverrideAttribs.PciVendorId) + BinFileList.append(TmpOutputFile) + else: + if FfsFile.FileType == 'EFI': + EfiFileList.append(FilePathName) + else: + BinFileList.append(FilePathName) + + # + # Call EfiRom tool + # + OutputFile = os.path.join(GenFdsGlobalVariable.FvDir, self.DriverName) + OutputFile = OutputFile + '.rom' + + GenFdsGlobalVariable.GenerateOptionRom( + OutputFile, + EfiFileList, + BinFileList + ) + + GenFdsGlobalVariable.InfLogger( "\nGenerate %s Option ROM Successfully" %self.DriverName) + GenFdsGlobalVariable.SharpCounter = 0 + + return OutputFile + +class OverrideAttribs: + + ## The constructor + # + # @param self The object pointer + # + def __init__(self): + + self.PciVendorId = None + self.PciClassCode = None + self.PciDeviceId = None + self.PciRevision = None + self.NeedCompress = False + + \ No newline at end of file diff --git a/BaseTools/Source/Python/GenFds/Region.py b/BaseTools/Source/Python/GenFds/Region.py new file mode 100644 index 0000000000..ed16c6fa98 --- /dev/null +++ b/BaseTools/Source/Python/GenFds/Region.py @@ -0,0 +1,240 @@ +## @file +# process FD Region generation +# +# Copyright (c) 2007, 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. +# + +## +# Import Modules +# +from struct import * +from GenFdsGlobalVariable import GenFdsGlobalVariable +import StringIO +from CommonDataClass.FdfClass import RegionClassObject +import os +from Common import EdkLogger +from Common.BuildToolError import * + + +## generate Region +# +# +class Region(RegionClassObject): + + ## The constructor + # + # @param self The object pointer + # + def __init__(self): + RegionClassObject.__init__(self) + + + ## AddToBuffer() + # + # Add region data to the Buffer + # + # @param self The object pointer + # @param Buffer The buffer generated region data will be put + # @param BaseAddress base address of region + # @param BlockSize block size of region + # @param BlockNum How many blocks in region + # @param ErasePolarity Flash erase polarity + # @param VtfDict VTF objects + # @param MacroDict macro value pair + # @retval string Generated FV file path + # + + def AddToBuffer(self, Buffer, BaseAddress, BlockSizeList, ErasePolarity, FvBinDict, vtfDict = None, MacroDict = {}): + Size = self.Size + GenFdsGlobalVariable.InfLogger('Generate Region at Offset 0x%X' % self.Offset) + GenFdsGlobalVariable.InfLogger(" Region Size = 0x%X" %Size) + GenFdsGlobalVariable.SharpCounter = 0 + + if self.RegionType == 'FV': + # + # Get Fv from FvDict + # + FvBuffer = StringIO.StringIO('') + RegionBlockSize = self.BlockSizeOfRegion(BlockSizeList) + RegionBlockNum = self.BlockNumOfRegion(RegionBlockSize) + + self.FvAddress = int(BaseAddress, 16) + self.Offset + FvBaseAddress = '0x%X' %self.FvAddress + + for RegionData in self.RegionDataList: + + if RegionData.endswith(".fv"): + RegionData = GenFdsGlobalVariable.MacroExtend(RegionData, MacroDict) + GenFdsGlobalVariable.InfLogger(' Region FV File Name = .fv : %s'%RegionData) + if RegionData[1] != ':' : + RegionData = os.path.join (GenFdsGlobalVariable.WorkSpaceDir, RegionData) + if not os.path.exists(RegionData): + EdkLogger.error("GenFds", FILE_NOT_FOUND, ExtraData=RegionData) + + BinFile = open (RegionData, 'r+b') + FvBuffer.write(BinFile.read()) + if FvBuffer.len > Size: + EdkLogger.error("GenFds", GENFDS_ERROR, + "Size of FV File (%s) is larger than Region Size 0x%X specified." \ + % (RegionData, Size)) + break + + if RegionData.upper() in FvBinDict.keys(): + continue + + FvObj = None + if RegionData.upper() in GenFdsGlobalVariable.FdfParser.Profile.FvDict.keys(): + FvObj = GenFdsGlobalVariable.FdfParser.Profile.FvDict.get(RegionData.upper()) + + if FvObj != None : + GenFdsGlobalVariable.InfLogger(' Region Name = FV') + # + # Call GenFv tool + # + BlockSize = RegionBlockSize + BlockNum = RegionBlockNum + if FvObj.BlockSizeList != []: + if FvObj.BlockSizeList[0][0] != None: + BlockSize = FvObj.BlockSizeList[0][0] + if FvObj.BlockSizeList[0][1] != None: + BlockNum = FvObj.BlockSizeList[0][1] + self.FvAddress = self.FvAddress + FvBuffer.len + FvAlignValue = self.GetFvAlignValue(FvObj.FvAlignment) + if self.FvAddress % FvAlignValue != 0: + EdkLogger.error("GenFds", GENFDS_ERROR, + "FV (%s) is NOT %s Aligned!" % (FvObj.UiFvName, FvObj.FvAlignment)) + FvBaseAddress = '0x%X' %self.FvAddress + FileName = FvObj.AddToBuffer(FvBuffer, FvBaseAddress, BlockSize, BlockNum, ErasePolarity, vtfDict) + + if FvBuffer.len > Size: + EdkLogger.error("GenFds", GENFDS_ERROR, + "Size of FV (%s) is larger than Region Size 0x%X specified." % (RegionData, Size)) + else: + EdkLogger.error("GenFds", GENFDS_ERROR, "FV (%s) is NOT described in FDF file!" % (RegionData)) + + + if FvBuffer.len > 0: + Buffer.write(FvBuffer.getvalue()) + else: + BinFile = open (FileName, 'rb') + Buffer.write(BinFile.read()) + + FvBuffer.close() + + if self.RegionType == 'FILE': + FvBuffer = StringIO.StringIO('') + for RegionData in self.RegionDataList: + RegionData = GenFdsGlobalVariable.MacroExtend(RegionData, MacroDict) + GenFdsGlobalVariable.InfLogger(' Region File Name = FILE: %s'%RegionData) + if RegionData[1] != ':' : + RegionData = os.path.join (GenFdsGlobalVariable.WorkSpaceDir, RegionData) + if not os.path.exists(RegionData): + EdkLogger.error("GenFds", FILE_NOT_FOUND, ExtraData=RegionData) + + BinFile = open (RegionData, 'r+b') + FvBuffer.write(BinFile.read()) + if FvBuffer.len > Size : + EdkLogger.error("GenFds", GENFDS_ERROR, + "Size of File (%s) large than Region Size " % RegionData) + + # + # If File contents less than region size, append "0xff" after it + # + if FvBuffer.len < Size: + for index in range(0, (Size-FvBuffer.len)): + if (ErasePolarity == '1'): + FvBuffer.write(pack('B', int('0xFF', 16))) + else: + FvBuffer.write(pack('B', int('0x00', 16))) + Buffer.write(FvBuffer.getvalue()) + FvBuffer.close() + + if self.RegionType == 'DATA' : + GenFdsGlobalVariable.InfLogger(' Region Name = DATA') + DataSize = 0 + for RegionData in self.RegionDataList: + Data = RegionData.split(',') + DataSize = DataSize + len(Data) + if DataSize > Size: + EdkLogger.error("GenFds", GENFDS_ERROR, "Size of DATA is larger than Region Size ") + else: + for item in Data : + Buffer.write(pack('B', int(item, 16))) + if DataSize < Size: + if (ErasePolarity == '1'): + PadData = 0xFF + else: + PadData = 0 + for i in range(Size - DataSize): + Buffer.write(pack('B', PadData)) + + if self.RegionType == None: + GenFdsGlobalVariable.InfLogger(' Region Name = None') + if (ErasePolarity == '1') : + PadData = 0xFF + else : + PadData = 0 + for i in range(0, Size): + Buffer.write(pack('B', PadData)) + + def GetFvAlignValue(self, Str): + AlignValue = 1 + Granu = 1 + Str = Str.strip().upper() + if Str.endswith('K'): + Granu = 1024 + Str = Str[:-1] + elif Str.endswith('M'): + Granu = 1024*1024 + Str = Str[:-1] + elif Str.endswith('G'): + Granu = 1024*1024*1024 + Str = Str[:-1] + else: + pass + + AlignValue = int(Str)*Granu + return AlignValue + ## BlockSizeOfRegion() + # + # @param BlockSizeList List of block information + # @retval int Block size of region + # + def BlockSizeOfRegion(self, BlockSizeList): + Offset = 0x00 + BlockSize = 0 + for item in BlockSizeList: + Offset = Offset + item[0] * item[1] + GenFdsGlobalVariable.VerboseLogger ("Offset = 0x%X" %Offset) + GenFdsGlobalVariable.VerboseLogger ("self.Offset 0x%X" %self.Offset) + + if self.Offset < Offset : + if Offset - self.Offset < self.Size: + EdkLogger.error("GenFds", GENFDS_ERROR, + "Region at Offset 0x%X can NOT fit into Block array with BlockSize %X" \ + % (self.Offset, item[0])) + BlockSize = item[0] + GenFdsGlobalVariable.VerboseLogger ("BlockSize = %X" %BlockSize) + return BlockSize + return BlockSize + + ## BlockNumOfRegion() + # + # @param BlockSize block size of region + # @retval int Block number of region + # + def BlockNumOfRegion (self, BlockSize): + if BlockSize == 0 : + EdkLogger.error("GenFds", GENFDS_ERROR, "Region: %s is not in the FD address scope!" % self.Offset) + BlockNum = self.Size / BlockSize + GenFdsGlobalVariable.VerboseLogger ("BlockNum = 0x%X" %BlockNum) + return BlockNum + diff --git a/BaseTools/Source/Python/GenFds/Rule.py b/BaseTools/Source/Python/GenFds/Rule.py new file mode 100644 index 0000000000..40a5f88bab --- /dev/null +++ b/BaseTools/Source/Python/GenFds/Rule.py @@ -0,0 +1,29 @@ +## @file +# Rule object for generating FFS +# +# Copyright (c) 2007, 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. +# + +## +# Import Modules +# +from CommonDataClass.FdfClass import RuleClassObject + +## Rule base class +# +# +class Rule(RuleClassObject): + ## The constructor + # + # @param self The object pointer + # + def __init__(self): + RuleClassObject.__init__(self) diff --git a/BaseTools/Source/Python/GenFds/RuleComplexFile.py b/BaseTools/Source/Python/GenFds/RuleComplexFile.py new file mode 100644 index 0000000000..63e65c5970 --- /dev/null +++ b/BaseTools/Source/Python/GenFds/RuleComplexFile.py @@ -0,0 +1,30 @@ +## @file +# Complex Rule object for generating FFS +# +# Copyright (c) 2007, 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. +# + +## +# Import Modules +# +import Rule +from CommonDataClass.FdfClass import RuleComplexFileClassObject + +## complex rule +# +# +class RuleComplexFile(RuleComplexFileClassObject) : + ## The constructor + # + # @param self The object pointer + # + def __init__(self): + RuleComplexFileClassObject.__init__(self) diff --git a/BaseTools/Source/Python/GenFds/RuleSimpleFile.py b/BaseTools/Source/Python/GenFds/RuleSimpleFile.py new file mode 100644 index 0000000000..c6fdbd88dc --- /dev/null +++ b/BaseTools/Source/Python/GenFds/RuleSimpleFile.py @@ -0,0 +1,30 @@ +## @file +# Simple Rule object for generating FFS +# +# Copyright (c) 2007, 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. +# + +## +# Import Modules +# +import Rule +from CommonDataClass.FdfClass import RuleSimpleFileClassObject + +## simple rule +# +# +class RuleSimpleFile (RuleSimpleFileClassObject) : + ## The constructor + # + # @param self The object pointer + # + def __init__(self): + RuleSimpleFileClassObject.__init__(self) diff --git a/BaseTools/Source/Python/GenFds/Section.py b/BaseTools/Source/Python/GenFds/Section.py new file mode 100644 index 0000000000..ffca3a11fe --- /dev/null +++ b/BaseTools/Source/Python/GenFds/Section.py @@ -0,0 +1,153 @@ +## @file +# section base class +# +# Copyright (c) 2007, 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. +# + +## +# Import Modules +# +from CommonDataClass.FdfClass import SectionClassObject +from GenFdsGlobalVariable import GenFdsGlobalVariable +import os, glob +from Common import EdkLogger +from Common.BuildToolError import * + +## section base class +# +# +class Section (SectionClassObject): + SectionType = { + 'RAW' : 'EFI_SECTION_RAW', + 'FREEFORM' : 'EFI_SECTION_FREEFORM_SUBTYPE_GUID', + 'PE32' : 'EFI_SECTION_PE32', + 'PIC' : 'EFI_SECTION_PIC', + 'TE' : 'EFI_SECTION_TE', + 'FV_IMAGE' : 'EFI_SECTION_FIRMWARE_VOLUME_IMAGE', + 'DXE_DEPEX' : 'EFI_SECTION_DXE_DEPEX', + 'PEI_DEPEX' : 'EFI_SECTION_PEI_DEPEX', + 'GUIDED' : 'EFI_SECTION_GUID_DEFINED', + 'COMPRESS' : 'EFI_SECTION_COMPRESSION', + 'UI' : 'EFI_SECTION_USER_INTERFACE', + 'SMM_DEPEX' : 'EFI_SECTION_SMM_DEPEX' + } + + BinFileType = { + 'GUID' : '.guid', + 'ACPI' : '.acpi', + 'ASL' : '.asl' , + 'UEFI_APP' : '.app', + 'LIB' : '.lib', + 'PE32' : '.pe32', + 'PIC' : '.pic', + 'PEI_DEPEX' : '.depex', + 'SEC_PEI_DEPEX' : '.depex', + 'TE' : '.te', + 'UNI_VER' : '.ver', + 'VER' : '.ver', + 'UNI_UI' : '.ui', + 'UI' : '.ui', + 'BIN' : '.bin', + 'RAW' : '.raw', + 'COMPAT16' : '.comp16', + 'FV' : '.fv' + } + + SectFileType = { + 'SEC_GUID' : '.sec' , + 'SEC_PE32' : '.sec' , + 'SEC_PIC' : '.sec', + 'SEC_TE' : '.sec', + 'SEC_VER' : '.sec', + 'SEC_UI' : '.sec', + 'SEC_COMPAT16' : '.sec', + 'SEC_BIN' : '.sec' + } + + ToolGuid = { + '0xa31280ad-0x481e-0x41b6-0x95e8-0x127f-0x4c984779' : 'TianoCompress', + '0xee4e5898-0x3914-0x4259-0x9d6e-0xdc7b-0xd79403cf' : 'LzmaCompress' + } + + ## The constructor + # + # @param self The object pointer + # + def __init__(self): + SectionClassObject.__init__(self) + + ## GenSection() method + # + # virtual function + # + # @param self The object pointer + # @param OutputPath Where to place output file + # @param ModuleName Which module this section belongs to + # @param SecNum Index of section + # @param KeyStringList Filter for inputs of section generation + # @param FfsInf FfsInfStatement object that contains this section data + # @param Dict dictionary contains macro and its value + # + def GenSection(self, OutputPath, GuidName, SecNum, keyStringList, FfsInf = None, Dict = {}): + pass + + ## GetFileList() method + # + # Generate compressed section + # + # @param self The object pointer + # @param FfsInf FfsInfStatement object that contains file list + # @param FileType File type to get + # @param FileExtension File extension to get + # @param Dict dictionary contains macro and its value + # @retval tuple (File list, boolean) + # + def GetFileList(FfsInf, FileType, FileExtension, Dict = {}): + if FileType in Section.SectFileType.keys() : + IsSect = True + else : + IsSect = False + + if FileExtension != None: + Suffix = FileExtension + elif IsSect : + Suffix = Section.SectionType.get(FileType) + else: + Suffix = Section.BinFileType.get(FileType) + if FfsInf == None: + EdkLogger.error("GenFds", GENFDS_ERROR, 'Inf File does not exist!') + + FileList = [] + if FileType != None: + for File in FfsInf.BinFileList: + if File.Arch == "COMMON" or FfsInf.CurrentArch == File.Arch: + if File.Type == FileType: + if '*' in FfsInf.TargetOverrideList or File.Target == '*' or File.Target in FfsInf.TargetOverrideList or FfsInf.TargetOverrideList == []: + FileList.append(File.Path) + else: + GenFdsGlobalVariable.InfLogger ("\nBuild Target \'%s\' of File %s is not in the Scope of %s specified by INF %s in FDF" %(File.Target, File.File, FfsInf.TargetOverrideList, FfsInf.InfFileName)) + else: + GenFdsGlobalVariable.VerboseLogger ("\nFile Type \'%s\' of File %s in %s is not same with file type \'%s\' from Rule in FDF" %(File.Type, File.File, FfsInf.InfFileName, FileType)) + else: + GenFdsGlobalVariable.InfLogger ("\nCurrent ARCH \'%s\' of File %s is not in the Support Arch Scope of %s specified by INF %s in FDF" %(FfsInf.CurrentArch, File.File, File.Arch, FfsInf.InfFileName)) + + if Suffix != None and os.path.exists(FfsInf.EfiOutputPath): +# FileList.extend(glob.glob(os.path.join(FfsInf.EfiOutputPath, "*" + Suffix))) + # Update to search files with suffix in all sub-dirs. + Tuple = os.walk(FfsInf.EfiOutputPath) + for Dirpath, Dirnames, Filenames in Tuple: + for F in Filenames: + if os.path.splitext(F)[1] in (Suffix): + FullName = os.path.join(Dirpath, F) + FileList.append(FullName) + + return FileList, IsSect + GetFileList = staticmethod(GetFileList) diff --git a/BaseTools/Source/Python/GenFds/UiSection.py b/BaseTools/Source/Python/GenFds/UiSection.py new file mode 100644 index 0000000000..e660055f9a --- /dev/null +++ b/BaseTools/Source/Python/GenFds/UiSection.py @@ -0,0 +1,77 @@ +## @file +# process UI section generation +# +# Copyright (c) 2007, 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. +# + +## +# Import Modules +# +import Section +from Ffs import Ffs +import subprocess +import os +from GenFdsGlobalVariable import GenFdsGlobalVariable +from CommonDataClass.FdfClass import UiSectionClassObject + +## generate UI section +# +# +class UiSection (UiSectionClassObject): + + ## The constructor + # + # @param self The object pointer + # + def __init__(self): + UiSectionClassObject.__init__(self) + + ## GenSection() method + # + # Generate UI section + # + # @param self The object pointer + # @param OutputPath Where to place output file + # @param ModuleName Which module this section belongs to + # @param SecNum Index of section + # @param KeyStringList Filter for inputs of section generation + # @param FfsInf FfsInfStatement object that contains this section data + # @param Dict dictionary contains macro and its value + # @retval tuple (Generated file name, section alignment) + # + def GenSection(self, OutputPath, ModuleName, SecNum, KeyStringList, FfsInf = None, Dict = {}): + # + # Prepare the parameter of GenSection + # + if FfsInf != None: + self.Alignment = FfsInf.__ExtendMacro__(self.Alignment) + self.StringData = FfsInf.__ExtendMacro__(self.StringData) + self.FileName = FfsInf.__ExtendMacro__(self.FileName) + + OutputFile = os.path.join(OutputPath, ModuleName + 'SEC' + SecNum + Ffs.SectionSuffix.get('UI')) + + if self.StringData != None : + NameString = self.StringData + elif self.FileName != None: + FileNameStr = GenFdsGlobalVariable.ReplaceWorkspaceMacro(self.FileName) + FileNameStr = GenFdsGlobalVariable.MacroExtend(FileNameStr, Dict) + FileObj = open(FileNameStr, 'r') + NameString = FileObj.read() + NameString = '\"' + NameString + "\"" + FileObj.close() + else: + NameString = '' + + GenFdsGlobalVariable.GenerateSection(OutputFile, None, 'EFI_SECTION_USER_INTERFACE', Ui=NameString) + + OutputFileList = [] + OutputFileList.append(OutputFile) + return OutputFileList, self.Alignment diff --git a/BaseTools/Source/Python/GenFds/VerSection.py b/BaseTools/Source/Python/GenFds/VerSection.py new file mode 100644 index 0000000000..e27d0a20f9 --- /dev/null +++ b/BaseTools/Source/Python/GenFds/VerSection.py @@ -0,0 +1,82 @@ +## @file +# process Version section generation +# +# Copyright (c) 2007, 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. +# + +## +# Import Modules +# +from Ffs import Ffs +import Section +import os +import subprocess +from GenFdsGlobalVariable import GenFdsGlobalVariable +from CommonDataClass.FdfClass import VerSectionClassObject + +## generate version section +# +# +class VerSection (VerSectionClassObject): + + ## The constructor + # + # @param self The object pointer + # + def __init__(self): + VerSectionClassObject.__init__(self) + + ## GenSection() method + # + # Generate version section + # + # @param self The object pointer + # @param OutputPath Where to place output file + # @param ModuleName Which module this section belongs to + # @param SecNum Index of section + # @param KeyStringList Filter for inputs of section generation + # @param FfsInf FfsInfStatement object that contains this section data + # @param Dict dictionary contains macro and its value + # @retval tuple (Generated file name, section alignment) + # + def GenSection(self,OutputPath, ModuleName, SecNum, KeyStringList, FfsInf = None, Dict = {}): + # + # Prepare the parameter of GenSection + # + if FfsInf != None: + self.Alignment = FfsInf.__ExtendMacro__(self.Alignment) + self.BuildNum = FfsInf.__ExtendMacro__(self.BuildNum) + self.StringData = FfsInf.__ExtendMacro__(self.StringData) + self.FileName = FfsInf.__ExtendMacro__(self.FileName) + + OutputFile = os.path.join(OutputPath, + ModuleName + 'SEC' + SecNum + Ffs.SectionSuffix.get('VERSION')) + OutputFile = os.path.normpath(OutputFile) + + # Get String Data + StringData = '' + if self.StringData != None: + StringData = self.StringData + elif self.FileName != None: + FileNameStr = GenFdsGlobalVariable.ReplaceWorkspaceMacro(self.FileName) + FileNameStr = GenFdsGlobalVariable.MacroExtend(FileNameStr, Dict) + FileObj = open(FileNameStr, 'r') + StringData = FileObj.read() + StringData = '"' + StringData + '"' + FileObj.close() + else: + StringData = '' + + GenFdsGlobalVariable.GenerateSection(OutputFile, None, 'EFI_SECTION_VERSION', + Ui=StringData, Ver=self.BuildNum) + OutputFileList = [] + OutputFileList.append(OutputFile) + return OutputFileList, self.Alignment diff --git a/BaseTools/Source/Python/GenFds/Vtf.py b/BaseTools/Source/Python/GenFds/Vtf.py new file mode 100644 index 0000000000..eebc7b1dab --- /dev/null +++ b/BaseTools/Source/Python/GenFds/Vtf.py @@ -0,0 +1,188 @@ +## @file +# process VTF generation +# +# Copyright (c) 2007, 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. +# + +## +# Import Modules +# +from GenFdsGlobalVariable import GenFdsGlobalVariable +import os +from CommonDataClass.FdfClass import VtfClassObject +T_CHAR_LF = '\n' + +## generate VTF +# +# +class Vtf (VtfClassObject): + + ## The constructor + # + # @param self The object pointer + # + def __init__(self): + VtfClassObject.__init__(self) + + ## GenVtf() method + # + # Generate VTF + # + # @param self The object pointer + # @param FdAddressDict dictionary contains FV name and its base address + # @retval Dict FV and corresponding VTF file name + # + def GenVtf(self, FdAddressDict) : + self.GenBsfInf() + OutputFile = os.path.join(GenFdsGlobalVariable.FvDir, self.UiName + '.Vtf') + BaseAddArg = self.GetBaseAddressArg(FdAddressDict) + OutputArg, VtfRawDict = self.GenOutputArg() + + Cmd = ( + 'GenVtf', + ) + OutputArg + ( + '-f', self.BsfInfName, + ) + BaseAddArg + + GenFdsGlobalVariable.CallExternalTool(Cmd, "GenFv -Vtf Failed!") + GenFdsGlobalVariable.SharpCounter = 0 + + return VtfRawDict + + ## GenBsfInf() method + # + # Generate inf used to generate VTF + # + # @param self The object pointer + # + def GenBsfInf (self): + FvList = self.GetFvList() + self.BsfInfName = os.path.join(GenFdsGlobalVariable.FvDir, self.UiName + '.inf') + BsfInf = open (self.BsfInfName, 'w+') + BsfInf.writelines ("[COMPONENTS]" + T_CHAR_LF) + + for ComponentObj in self.ComponentStatementList : + BsfInf.writelines ("COMP_NAME" + \ + " = " + \ + ComponentObj.CompName + \ + T_CHAR_LF ) + if ComponentObj.CompLoc.upper() == 'NONE': + BsfInf.writelines ("COMP_LOC" + \ + " = " + \ + 'N' + \ + T_CHAR_LF ) + + elif ComponentObj.FilePos != None: + BsfInf.writelines ("COMP_LOC" + \ + " = " + \ + ComponentObj.FilePos + \ + T_CHAR_LF ) + else: + Index = FvList.index(ComponentObj.CompLoc.upper()) + if Index == 0: + BsfInf.writelines ("COMP_LOC" + \ + " = " + \ + 'F' + \ + T_CHAR_LF ) + elif Index == 1: + BsfInf.writelines ("COMP_LOC" + \ + " = " + \ + 'S' + \ + T_CHAR_LF ) + + BsfInf.writelines ("COMP_TYPE" + \ + " = " + \ + ComponentObj.CompType + \ + T_CHAR_LF ) + BsfInf.writelines ("COMP_VER" + \ + " = " + \ + ComponentObj.CompVer + \ + T_CHAR_LF ) + BsfInf.writelines ("COMP_CS" + \ + " = " + \ + ComponentObj.CompCs + \ + T_CHAR_LF ) + + BinPath = ComponentObj.CompBin + if BinPath != '-': + BinPath = GenFdsGlobalVariable.MacroExtend(GenFdsGlobalVariable.ReplaceWorkspaceMacro(BinPath)) + BsfInf.writelines ("COMP_BIN" + \ + " = " + \ + BinPath + \ + T_CHAR_LF ) + + SymPath = ComponentObj.CompSym + if SymPath != '-': + SymPath = GenFdsGlobalVariable.MacroExtend(GenFdsGlobalVariable.ReplaceWorkspaceMacro(SymPath)) + BsfInf.writelines ("COMP_SYM" + \ + " = " + \ + SymPath + \ + T_CHAR_LF ) + BsfInf.writelines ("COMP_SIZE" + \ + " = " + \ + ComponentObj.CompSize + \ + T_CHAR_LF ) + BsfInf.writelines (T_CHAR_LF ) + + BsfInf.close() + + ## GenFvList() method + # + # Get FV list referenced by VTF components + # + # @param self The object pointer + # + def GetFvList(self): + FvList = [] + for component in self.ComponentStatementList : + if component.CompLoc.upper() != 'NONE' and not (component.CompLoc.upper() in FvList): + FvList.append(component.CompLoc.upper()) + + return FvList + + ## GetBaseAddressArg() method + # + # Get base address arguments for GenVtf + # + # @param self The object pointer + # + def GetBaseAddressArg(self, FdAddressDict): + FvList = self.GetFvList() + CmdStr = tuple() + for i in FvList: + (BaseAddress, Size) = FdAddressDict.get(i) + CmdStr += ( + '-r', '0x%x' % BaseAddress, + '-s', '0x%x' %Size, + ) + return CmdStr + + ## GenOutputArg() method + # + # Get output arguments for GenVtf + # + # @param self The object pointer + # + def GenOutputArg(self): + FvVtfDict = {} + OutputFileName = '' + FvList = self.GetFvList() + Index = 0 + Arg = tuple() + for FvObj in FvList: + Index = Index + 1 + OutputFileName = 'Vtf%d.raw' % Index + OutputFileName = os.path.join(GenFdsGlobalVariable.FvDir, OutputFileName) + Arg += ('-o', OutputFileName) + FvVtfDict[FvObj.upper()] = OutputFileName + + return Arg, FvVtfDict + diff --git a/BaseTools/Source/Python/GenFds/__init__.py b/BaseTools/Source/Python/GenFds/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/BaseTools/Source/Python/Makefile b/BaseTools/Source/Python/Makefile new file mode 100644 index 0000000000..a4e76592ab --- /dev/null +++ b/BaseTools/Source/Python/Makefile @@ -0,0 +1,89 @@ + +!IFNDEF PYTHON_FREEZER_PATH +!ERROR PYTHON_FREEZER_PATH must be defined! +!ENDIF + +FREEZE=$(PYTHON_FREEZER_PATH)\FreezePython.exe + +MODULES=encodings.cp437,encodings.gbk,encodings.utf_16,encodings.utf_8,encodings.utf_16_le,encodings.latin_1 + +BIN_DIR=$(EDK_TOOLS_PATH)\Bin\Win32 + + +APPLICATIONS=$(BIN_DIR)\build.exe $(BIN_DIR)\GenFds.exe $(BIN_DIR)\Trim.exe $(BIN_DIR)\MigrationMsa2Inf.exe $(BIN_DIR)\Fpd2Dsc.exe $(BIN_DIR)\TargetTool.exe $(BIN_DIR)\spd2dec.exe $(BIN_DIR)\GenDepex.exe + +COMMON_PYTHON=$(BASE_TOOLS_PATH)\Source\Python\Common\BuildToolError.py \ + $(BASE_TOOLS_PATH)\Source\Python\Common\Database.py \ + $(BASE_TOOLS_PATH)\Source\Python\Common\DataType.py \ + $(BASE_TOOLS_PATH)\Source\Python\Common\DecClassObject.py \ + $(BASE_TOOLS_PATH)\Source\Python\Common\DecClassObjectLight.py \ + $(BASE_TOOLS_PATH)\Source\Python\Common\Dictionary.py \ + $(BASE_TOOLS_PATH)\Source\Python\Common\DscClassObject.py \ + $(BASE_TOOLS_PATH)\Source\Python\Common\EdkIIWorkspace.py \ + $(BASE_TOOLS_PATH)\Source\Python\Common\EdkIIWorkspaceBuild.py \ + $(BASE_TOOLS_PATH)\Source\Python\Common\EdkLogger.py \ + $(BASE_TOOLS_PATH)\Source\Python\Common\FdfClassObject.py \ + $(BASE_TOOLS_PATH)\Source\Python\Common\FdfParserLite.py \ + $(BASE_TOOLS_PATH)\Source\Python\Common\GlobalData.py \ + $(BASE_TOOLS_PATH)\Source\Python\Common\Identification.py \ + $(BASE_TOOLS_PATH)\Source\Python\Common\InfClassObject.py \ + $(BASE_TOOLS_PATH)\Source\Python\Common\InfClassObjectLight.py \ + $(BASE_TOOLS_PATH)\Source\Python\Common\MigrationUtilities.py \ + $(BASE_TOOLS_PATH)\Source\Python\Common\Misc.py \ + $(BASE_TOOLS_PATH)\Source\Python\Common\Parsing.py \ + $(BASE_TOOLS_PATH)\Source\Python\Common\String.py \ + $(BASE_TOOLS_PATH)\Source\Python\Common\TargetTxtClassObject.py \ + $(BASE_TOOLS_PATH)\Source\Python\Common\ToolDefClassObject.py \ + $(BASE_TOOLS_PATH)\Source\Python\Common\XmlParser.py \ + $(BASE_TOOLS_PATH)\Source\Python\Common\XmlRoutines.py \ + $(BASE_TOOLS_PATH)\Source\Python\Common\__init__.py \ + $(BASE_TOOLS_PATH)\Source\Python\Workspace\BuildClassObject.py \ + $(BASE_TOOLS_PATH)\Source\Python\Workspace\MetaDataTable.py \ + $(BASE_TOOLS_PATH)\Source\Python\Workspace\MetaFileParser.py \ + $(BASE_TOOLS_PATH)\Source\Python\Workspace\MetaFileTable.py \ + $(BASE_TOOLS_PATH)\Source\Python\Workspace\WorkspaceDatabase.py \ + $(BASE_TOOLS_PATH)\Source\Python\Workspace\__init__.py \ + $(BASE_TOOLS_PATH)\Source\Python\Autogen\AutoGen.py \ + $(BASE_TOOLS_PATH)\Source\Python\Autogen\BuildEngine.py \ + $(BASE_TOOLS_PATH)\Source\Python\Autogen\GenC.py \ + $(BASE_TOOLS_PATH)\Source\Python\Autogen\GenDepex.py \ + $(BASE_TOOLS_PATH)\Source\Python\Autogen\GenMake.py \ + $(BASE_TOOLS_PATH)\Source\Python\Autogen\StrGather.py \ + $(BASE_TOOLS_PATH)\Source\Python\Autogen\UniClassObject.py \ + $(BASE_TOOLS_PATH)\Source\Python\Autogen\__init__.py + + +all: SetPythonPath $(APPLICATIONS) + +SetPythonPath: + set PYTHONPATH=$(BASE_TOOLS_PATH)\Source\Python + +$(BIN_DIR)\build.exe: $(BASE_TOOLS_PATH)\Source\Python\build\build.py $(COMMON_PYTHON) + @pushd . & @cd build & @$(FREEZE) --include-modules=$(MODULES) --install-dir=$(BIN_DIR) build.py & @popd + +$(BIN_DIR)\GenFds.exe: $(BASE_TOOLS_PATH)\Source\Python\GenFds\GenFds.py $(COMMON_PYTHON) + @pushd . & @cd GenFds & @$(FREEZE) --include-modules=$(MODULES) --install-dir=$(BIN_DIR) GenFds.py & @popd + +$(BIN_DIR)\Trim.exe: $(BASE_TOOLS_PATH)\Source\Python\Trim\Trim.py $(COMMON_PYTHON) + @pushd . & @cd Trim & @$(FREEZE) --include-modules=$(MODULES) --install-dir=$(BIN_DIR) Trim.py & @popd + +$(BIN_DIR)\MigrationMsa2Inf.exe: $(BASE_TOOLS_PATH)\Source\Python\MigrationMsa2Inf\MigrationMsa2Inf.py + @pushd . & @cd MigrationMsa2Inf & @$(FREEZE) --include-modules=$(MODULES) --install-dir=$(BIN_DIR) MigrationMsa2Inf.py & @popd + +$(BIN_DIR)\Fpd2Dsc.exe: $(BASE_TOOLS_PATH)\Source\Python\Fpd2Dsc\Fpd2Dsc.py $(COMMON_PYTHON) + @pushd . & @cd Fpd2Dsc & @$(FREEZE) --include-modules=$(MODULES) --install-dir=$(BIN_DIR) Fpd2Dsc.py & @popd + +$(BIN_DIR)\spd2dec.exe: $(BASE_TOOLS_PATH)\Source\Python\spd2dec\Spd2Dec.py $(COMMON_PYTHON) + @pushd . & @cd Spd2Dec & @$(FREEZE) --include-modules=$(MODULES) --install-dir=$(BIN_DIR) Spd2Dec.py & @popd + +$(BIN_DIR)\GenDepex.exe: $(BASE_TOOLS_PATH)\Source\Python\AutoGen\GenDepex.py $(COMMON_PYTHON) + @pushd . & @cd AutoGen & @$(FREEZE) --include-modules=$(MODULES) --install-dir=$(BIN_DIR) GenDepex.py & @popd + +$(BIN_DIR)\TargetTool.exe: $(BASE_TOOLS_PATH)\Source\Python\TargetTool\TargetTool.py $(COMMON_PYTHON) + @pushd . & @cd TargetTool & @$(FREEZE) --include-modules=$(MODULES) --install-dir=$(BIN_DIR) TargetTool.py & @popd + +clean: +cleanall: + @del /f /q $(BIN_DIR)\*.pyd $(BIN_DIR)\*.dll + @for %%i in ($(APPLICATIONS)) do @del /f /q %%i + diff --git a/BaseTools/Source/Python/MigrationMsa2Inf/AutoGenExterns.py b/BaseTools/Source/Python/MigrationMsa2Inf/AutoGenExterns.py new file mode 100644 index 0000000000..16f7a6bb2e --- /dev/null +++ b/BaseTools/Source/Python/MigrationMsa2Inf/AutoGenExterns.py @@ -0,0 +1,369 @@ +#!/usr/bin/env python +# +# +# Copyright (c) 2007, 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. + + +# +# Import Modules +# +import re, os, glob +from Common.XmlRoutines import * + +#"ModuleType"=>(PackageGuid, headerFileName) List +HeaderFiles = {} +GuidList = [] +GuidMap = {} +HeaderFileContents = {} +gTest = {} +GuidMacro2CName = {} +GuidAliasList = [] + +def collectIncludeFolder(pkgDirName, guidType, pkgName): + includeFolder = os.path.join(pkgDirName, "Include", guidType) + if os.path.exists(includeFolder) and os.path.isdir(includeFolder): + for headerFileName in os.listdir(includeFolder): + if headerFileName[-2:] == ".h": + headerFile = open(os.path.join(includeFolder, headerFileName)) + HeaderFileContents[(guidType, headerFileName, pkgName)] = headerFile.read() + headerFile.close() + +GuidMacroReg = re.compile(r"\b(?!EFI_GUID\b)[A-Z0-9_]+_GUID\b") +GuidCNameReg = re.compile(r"\bg\w+Guid\b") +GuidAliasReg = re.compile(r"#define\s+([A-Z0-9_]+_GUID)\s+([A-Z0-9_]+_GUID)\b") + +def collectPackageInfo(spdFileName): + pkgDirName = os.path.dirname(spdFileName) + + spd = XmlParseFile(spdFileName) + + pkgName = XmlElement(spd, "/PackageSurfaceArea/SpdHeader/PackageName") + pkgGuid = XmlElement(spd, "/PackageSurfaceArea/SpdHeader/GuidValue") + + + for IncludePkgHeader in XmlList(spd, "/PackageSurfaceArea/PackageHeaders/IncludePkgHeader"): + moduleType = XmlAttribute(IncludePkgHeader, "ModuleType") + headerFilePath = XmlElementData(IncludePkgHeader) + headerFilePath = re.sub("Include/", "", headerFilePath, 1) + + headerTuple = HeaderFiles.get(moduleType, []) + headerTuple.append((pkgGuid, headerFilePath)) + HeaderFiles[moduleType] = headerTuple + + guidTypes = ["Guid", "Protocol", "Ppi"] + + for guidType in guidTypes: + for guidEntry in XmlList(spd, "/PackageSurfaceArea/" + guidType + "Declarations/Entry"): + guidCName = XmlElement(guidEntry, "Entry/C_Name") + GuidList.append(guidCName) + + collectIncludeFolder(pkgDirName, guidType, pkgName) + + for DecFile in glob.glob(os.path.join(pkgDirName, "*.dec")): + fileContents = open(DecFile).read() + for GuidCNameMatch in GuidCNameReg.finditer(fileContents): + GuidCName = GuidCNameMatch.group(0) + if GuidCName not in GuidList: + GuidList.append(GuidCName) + +def AddGuidMacro2GuidCName(GuidMacros, GuidCNames): + for GuidMacro in GuidMacros: + GuessGuidCName = "g" + GuidMacro.lower().title().replace("_", "") + if GuessGuidCName in GuidCNames: + GuidMacro2CName[GuidMacro] = GuessGuidCName + elif len(GuidCNames) == 1: + GuidMacro2CName[GuidMacro] = GuidCNames[0] + else: + for GuidCName in GuidCNames: + if GuidCName.lower() == GuessGuidCName.lower(): + GuidMacro2CName[GuidMacro] = GuidCName + break + else: + pass + #print "No matching GuidMacro %s" % GuidMacro + + +def TranslateGuid(GuidMacroMatch): + GuidMacro = GuidMacroMatch.group(0) + return GuidMacro2CName.get(GuidMacro, GuidMacro) + +DepexReg = re.compile(r"DEPENDENCY_START(.*?)DEPENDENCY_END", re.DOTALL) + +def TranslateDpxSection(fileContents): + DepexMatch = DepexReg.search(fileContents) + if not DepexMatch: + return "", [] + + fileContents = DepexMatch.group(1) + fileContents = re.sub(r"\s+", " ", fileContents).strip() + fileContents = GuidMacroReg.sub(TranslateGuid, fileContents) + return fileContents, GuidMacroReg.findall(fileContents) + +def InitializeAutoGen(workspace, db): + + + for spdFile in XmlList(db, "/FrameworkDatabase/PackageList/Filename"): + spdFileName = XmlElementData(spdFile) + collectPackageInfo(os.path.join(workspace, spdFileName)) + + + BlockCommentReg = re.compile(r"/\*.*?\*/", re.DOTALL) + LineCommentReg = re.compile(r"//.*") + GuidReg = re.compile(r"\b(" + '|'.join(GuidList) + r")\b") + + for headerFile in HeaderFileContents: + Contents = HeaderFileContents[headerFile] + Contents = BlockCommentReg.sub("", Contents) + Contents = LineCommentReg.sub("", Contents) + + FoundGuids = GuidReg.findall(Contents) + for FoundGuid in FoundGuids: + GuidMap[FoundGuid] = "%s/%s" % (headerFile[0], headerFile[1]) + #print "%-40s %s/%s" % (FoundGuid, headerFile[0], headerFile[1]) + + GuidMacros = GuidMacroReg.findall(Contents) + GuidCNames = GuidCNameReg.findall(Contents) + + for GuidAliasMatch in GuidAliasReg.finditer(Contents): + Name1, Name2 = GuidAliasMatch.group(1), GuidAliasMatch.group(2) + GuidAliasList.append((Name1, Name2)) + + AddGuidMacro2GuidCName(GuidMacros, GuidCNames) + +def AddSystemIncludeStatement(moduleType, PackageList): + IncludeStatement = "\n" + + headerList = HeaderFiles.get(moduleType, []) + + for pkgGuid in PackageList: + + for pkgTuple in headerList: + if pkgTuple[0] == pkgGuid: + IncludeStatement += "#include <%s>\n" % pkgTuple[1] + + return IncludeStatement + + +def AddLibraryClassStatement(LibraryClassList): + IncludeStatement = "\n" + for LibraryClass in LibraryClassList: + IncludeStatement += "#include \n" % LibraryClass + + return IncludeStatement + +def AddGuidStatement(GuidList): + IncludeStatement = "\n" + GuidIncludeSet = {} + for Guid in GuidList: + if Guid in GuidMap: + GuidIncludeSet[GuidMap[Guid]] = 1 + else: + print "GUID CName: %s cannot be found in any public header file" % Guid + + for GuidInclude in GuidIncludeSet: + IncludeStatement += "#include <%s>\n" % GuidInclude + + return IncludeStatement + +DriverBindingMap = { + "gEfiDriverBindingProtocolGuid" : "EFI_DRIVER_BINDING_PROTOCOL", + "gEfiComponentNameProtocolGuid" : "EFI_COMPONENT_NAME_PROTOCOL", + "gEfiDriverConfigurationProtocolGuid" : "EFI_DRIVER_CONFIGURATION_PROTOCOL", + "gEfiDriverDiagnosticProtocolGuid" : "EFI_DRIVER_CONFIGURATION_PROTOCOL" + } + +def AddDriverBindingProtocolStatement(AutoGenDriverModel): + InstallStatement = "\n" + DBindingHandle = "ImageHandle" + GlobalDeclaration = "\n" + + + for DriverModelItem in AutoGenDriverModel: + + if DriverModelItem[1] == "NULL" and DriverModelItem[2] == "NULL" and DriverModelItem[3] == "NULL": + InstallStatement += " Status = EfiLibInstallDriverBinding (\n" + InstallStatement += " ImageHandle,\n" + InstallStatement += " SystemTable,\n" + InstallStatement += " %s,\n" % DriverModelItem[0] + InstallStatement += " %s\n" % DBindingHandle + InstallStatement += " );\n" + else: + InstallStatement += " Status = EfiLibInstallAllDriverProtocols (\n" + InstallStatement += " ImageHandle,\n" + InstallStatement += " SystemTable,\n" + InstallStatement += " %s,\n" % DriverModelItem[0] + InstallStatement += " %s,\n" % DBindingHandle + InstallStatement += " %s,\n" % DriverModelItem[1] + InstallStatement += " %s,\n" % DriverModelItem[2] + InstallStatement += " %s\n" % DriverModelItem[3] + InstallStatement += " );\n" + + InstallStatement += " ASSERT_EFI_ERROR (Status);\n\n" + + GlobalDeclaration += "extern EFI_DRIVER_BINDING_PROTOCOL %s;\n" % DriverModelItem[0][1:] + if (DriverModelItem[1] != "NULL"): + GlobalDeclaration += "extern EFI_COMPONENT_NAME_PROTOCOL %s;\n" % DriverModelItem[1][1:] + if (DriverModelItem[2] != "NULL"): + GlobalDeclaration += "extern EFI_DRIVER_CONFIGURATION_PROTOCOL %s;\n" % DriverModelItem[2][1:] + if (DriverModelItem[3] != "NULL"): + GlobalDeclaration += "extern EFI_DRIVER_CONFIGURATION_PROTOCOL %s;\n" % DriverModelItem[3][1:] + + DBindingHandle = "NULL" + + return (InstallStatement, "", "", GlobalDeclaration) + +EventDeclarationTemplate = """ +// +// Declaration for callback Event. +// +VOID +EFIAPI +%s ( + IN EFI_EVENT Event, + IN VOID *Context + ); +""" + +def AddBootServiceEventStatement(EventList): + FinalEvent = "" + if len(EventList) > 1: + + print "Current prototype does not support multi boot service event" + else: + FinalEvent = EventList[0] + + CreateStatement = "\n" + CreateStatement += " Status = gBS->CreateEvent (\n" + CreateStatement += " EVT_SIGNAL_EXIT_BOOT_SERVICES,\n" + CreateStatement += " EFI_TPL_NOTIFY,\n" + CreateStatement += " " + FinalEvent + ",\n" + CreateStatement += " NULL,\n" + CreateStatement += " &mExitBootServicesEvent\n" + CreateStatement += " );\n" + CreateStatement += " ASSERT_EFI_ERROR (Status);\n" + + GlobalDefinition = "\n" + GlobalDefinition += "STATIC EFI_EVENT mExitBootServicesEvent = NULL;\n" + + GlobalDeclaration = EventDeclarationTemplate % FinalEvent + + DestroyStatement = "\n" + DestroyStatement += " Status = gBS->CloseEvent (mExitBootServicesEvent);\n" + DestroyStatement += " ASSERT_EFI_ERROR (Status);\n" + return (CreateStatement, "", GlobalDefinition, GlobalDeclaration) + +def AddVirtualAddressEventStatement(EventList): + FinalEvent = "" + if len(EventList) > 1: + print "Current prototype does not support multi virtual address change event" + else: + FinalEvent = EventList[0] + + CreateStatement = "\n" + + CreateStatement += " Status = gBS->CreateEvent (\n" + CreateStatement += " EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE,\n" + CreateStatement += " TPL_NOTIFY,\n" + CreateStatement += " " + FinalEvent + ",\n" + CreateStatement += " NULL,\n" + CreateStatement += " &mVirtualAddressChangedEvent\n" + CreateStatement += " );\n" + CreateStatement += " ASSERT_EFI_ERROR (Status);\n" + + GlobalDefinition = "\n" + GlobalDefinition += "STATIC EFI_EVENT mVirtualAddressChangedEvent = NULL;\n" + + GlobalDeclaration = EventDeclarationTemplate % FinalEvent + + DestroyStatement = "\n" + DestroyStatement += " Status = gBS->CloseEvent (mVirtualAddressChangedEvent);\n" + DestroyStatement += " ASSERT_EFI_ERROR (Status);\n" + + return (CreateStatement, "", GlobalDefinition, GlobalDeclaration) + + +EntryPointDeclarationTemplate = """ +// +// Declaration for original Entry Point. +// +EFI_STATUS +EFIAPI +%s ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); +""" + +EntryPointHeader = r""" +/** + The user Entry Point for module %s. The user code starts with this function. + + @param[in] ImageHandle The firmware allocated handle for the EFI image. + @param[in] SystemTable A pointer to the EFI System Table. + + @retval EFI_SUCCESS The entry point is executed successfully. + @retval other Some error occurs when executing this entry point. + +**/ +""" +def AddNewEntryPointContentsStatement (moduleName, EntryPoint, InstallStatement = ""): + if EntryPoint != "Initialize%s" % moduleName: + NewEntryPoint = "Initialize%s" % moduleName + else: + NewEntryPoint = "NewInitialize%s" % moduleName + + EntryPointContents = EntryPointHeader % moduleName + EntryPointContents += "EFI_STATUS\n" + EntryPointContents += "EFIAPI\n" + EntryPointContents += NewEntryPoint + "(\n" + EntryPointContents += " IN EFI_HANDLE ImageHandle,\n" + EntryPointContents += " IN EFI_SYSTEM_TABLE *SystemTable\n" + EntryPointContents += " )\n" + EntryPointContents += "{\n" + EntryPointContents += " EFI_STATUS Status;\n" + EntryPointContents += InstallStatement + "\n" + GlobalDeclaration = "" + + if EntryPoint != "": + EntryPointContents += " //\n // Call the original Entry Point\n //\n" + EntryPointContents += " Status = %s (ImageHandle, SystemTable);\n\n" % EntryPoint + GlobalDeclaration += EntryPointDeclarationTemplate % EntryPoint + + EntryPointContents += " return Status;\n" + EntryPointContents += "}\n" + + return (NewEntryPoint, EntryPointContents, GlobalDeclaration) + +reFileHeader = re.compile(r"^\s*/\*.*?\*/\s*", re.DOTALL) +reNext = re.compile(r"#ifndef\s*(\w+)\s*#define\s*\1\s*") + +def AddCommonInclusionStatement(fileContents, includeStatement): + if includeStatement in fileContents: + return fileContents + + insertPos = 0 + matchFileHeader = reFileHeader.search(fileContents) + if matchFileHeader: + insertPos = matchFileHeader.end() + + matchFileHeader = reNext.search(fileContents, insertPos) + if matchFileHeader: + insertPos = matchFileHeader.end() + + includeStatement = "\n%s\n\n" % includeStatement + fileContents = fileContents[0:insertPos] + includeStatement + fileContents[insertPos:] + return fileContents + +# This acts like the main() function for the script, unless it is 'import'ed into another +# script. +if __name__ == '__main__': + + pass + diff --git a/BaseTools/Source/Python/MigrationMsa2Inf/MigrationMsa2Inf.py b/BaseTools/Source/Python/MigrationMsa2Inf/MigrationMsa2Inf.py new file mode 100644 index 0000000000..01de21239c --- /dev/null +++ b/BaseTools/Source/Python/MigrationMsa2Inf/MigrationMsa2Inf.py @@ -0,0 +1,2477 @@ +#!/usr/bin/env python +# +# +# Copyright (c) 2007, 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. + + +""" This program converts EDK II MSA files into EDK II Extended INF format files """ + +import os, re, sys, fnmatch, xml.dom.minidom +from optparse import OptionParser +from AutoGenExterns import * +from Common.XmlRoutines import * # XmlParseFile, XmlElement, XmlAttribute, XmlList, XmlElementData, XmlNode +from Common.EdkIIWorkspace import * + +versionNumber = "0.9" +__version__ = "%prog Version " + versionNumber +__copyright__ = "Copyright (c) 2007, Intel Corporation All rights reserved." + +commonHeaderFilename = "CommonHeader.h" +entryPointFilename = "EntryPoint.c" + +AutoGenLibraryMapping = { + "HiiLib":"HiiLibFramework", + "EdkIfrSupportLib":"IfrSupportLibFramework", + "EdkScsiLib":"ScsiLib", + "EdkUsbLib":"UsbLib", + "EdkFvbServiceLib":"FvbServiceLib", + "EdkGraphicsLib":"GraphicsLib" + } + +def myOptionParser(): + """ Argument Parser """ + usage = "%prog [options] -f input_filename" + parser = OptionParser(usage=usage,description=__copyright__,version="%prog " + str(versionNumber)) + parser.add_option("-f", "--file", dest="filename", help="Name of MSA file to convert") + parser.add_option("-o", "--output", dest="outfile", help="Specific Name of the INF file to create, otherwise it is the MSA filename with the extension repalced.") + parser.add_option("-a", "--auto", action="store_true", dest="autowrite", default=False, help="Automatically create output files and write the INF file") + parser.add_option("-i", "--interactive", action="store_true", dest="interactive", default=False, help="Set Interactive mode, user must approve each change.") + parser.add_option("-q", "--quiet", action="store_const", const=0, dest="verbose", help="Do not print any messages, just return either 0 for succes or 1 for failure") + parser.add_option("-v", "--verbose", action="count", dest="verbose", help="Do not print any messages, just return either 0 for succes or 1 for failure") + parser.add_option("-d", "--debug", action="store_true", dest="debug", default=False, help="Enable printing of debug messages.") + parser.add_option("-c", "--convert", action="store_true", dest="convert", default=False, help="Convert package: OldMdePkg->MdePkg EdkModulePkg->MdeModulePkg.") + parser.add_option("-e", "--event", action="store_true", dest="event", default=False, help="Enable handling of Exit Boot Services & Virtual Address Changed Event") + parser.add_option("-m", "--manual", action="store_true", dest="manual", default=False, help="Generate CommonHeader.txt, user picks up & copy it to a module common header") + parser.add_option("-w", "--workspace", dest="workspace", default=str(os.environ.get('WORKSPACE')), help="Specify workspace directory.") + (options, args) = parser.parse_args(sys.argv[1:]) + + return options,args + + +def openDatabase(f): + """ Parse XML in the FrameworkDatabase.db file pointed to by f """ + if (options.debug and options.verbose > 1): + print "Opening the database file:", f + if os.path.exists(f): + fdb = XmlParseFile(f) + else: + return "None" + return fdb + +def openSpd(s): + """ Parse XML in the SPD file pointed to by s """ + if (options.debug and options.verbose > 1): + print "Opening the SPD file:", s + if os.path.exists(s): + spd = XmlParseFile(s) + else: + return "None" + return spd + +def openMsa(m): + """ Parse XML in the MSA file pointed to by m """ + if (options.debug and options.verbose > 1): + print "Opening the MSA file:", m + if os.path.exists(m): + msa = XmlParseFile(m) + else: + return "None" + return msa + +def AddGuid(ArchList, CName, Usage): + """ Add a GUID to the Architecture array that the GUID is valid for. """ + if "IA32" in ArchList: + GuidCNameIa32.insert(0, str(" %-45s # %s" % (CName, Usage))) + if "X64" in ArchList: + GuidCNameX64.insert(0, str(" %-45s # %s" % (CName, Usage))) + if "IPF" in ArchList: + GuidCNameIPF.insert(0, str(" %-45s # %s" % (CName, Usage))) + if "EBC" in ArchList: + GuidCNameEBC.insert(0, str(" %-45s # %s" % (CName, Usage))) + if "ALL" in ArchList: + GuidCName.insert(0, str(" %-45s # %s" % (CName, Usage))) + + +def removeDups(CN, ListName): + """ Remove Duplicate Entries from the Guid List passed in """ + for Entry in ListName[:]: + if " " + CN + " " in Entry: + if (options.verbose > 1): + print "Removing C Name %s Entry from Guids List." % (CN) + ListName.remove(Entry) + +def chkArch(Archs): + """ Process the supported architectures passed in to combine if possible """ + Archs = Archs.upper() + if (("IA32" in Archs) & ("X64" in Archs) & ("IPF" in Archs) & ("EBC" in Archs)): + Archs = "ALL" + if (len(Archs) == 0): + Archs = "ALL" + return Archs + +def saveSourceFile(moduleDir, sourceFilename, sourceFileContents): + newFilename = os.path.join(moduleDir, sourceFilename) + + try: + f = open(newFilename, "w+") + f.write(sourceFileContents) + f.close() + except: + print "IO error in saving %s" % sourceFilename + + return sourceFilename + +def openSourceFile(moduleDir, sourceFilename): + newFilename = os.path.join(moduleDir, sourceFilename) + sourceFileContents = "" + try: + f = open(newFilename, "r") + sourceFileContents = f.read() + f.close() + except: + print "IO error in opening %s" % sourceFilename + + return sourceFileContents + +def MatchOption(eline, ToolChainFamily, Targets, Archs, ToolCode, Value): + IDs = eline.split("_") + + if len(IDs) < 5: + return [] + + MatchedTargets = [] + if (Targets[0] == "*") or IDs[0] in Targets: + MatchedTargets.append(IDs[0]) + elif IDs[0] == "*": + MatchedTargets = Targets + + MatchedArchs = [] + if Archs[0] == "*" or IDs[2] in Archs: + MatchedArchs.append(IDs[2]) + elif IDs[2] == "*": + MatchedArchs = Archs + + if IDs[3] != ToolCode and IDs[3] != "*": + return [] + + result = [] + for arch in MatchedArchs: + for target in MatchedTargets: + line = "%s:%s_%s_%s_%s_FLAGS = %s" % (ToolChainFamily, target, IDs[1], arch, ToolCode, Value) + result.append(line) + + return result + +def main(): + + AutoGenSource = "" + AutoGenHeader = "" + AutoGenDeclaration = "" + AutoGenModuleFolder = None + + workspace = "" + + if (options.workspace == None): + print "ERROR: E0000: WORKSPACE not defined.\n Please set the WORKSPACE environment variable to the location of the EDK II install directory." + sys.exit(1) + else: + workspace = options.workspace + if (options.debug): + print "Using Workspace:", workspace + + try: + options.verbose +=1 + except: + options.verbose = 1 + pass + + + FdbPath = os.path.join(workspace, "Conf") + FdbPath = os.path.join(FdbPath, "FrameworkDatabase.db") + if os.path.exists(FdbPath): + FdbFile = FdbPath + else: + print "ERROR: E0001: WORKSPACE does not contain the FrameworkDatabase File.\n Please run EdkSetup from the EDK II install directory.\n" + sys.exit(1) + + Fdb = openDatabase(FdbFile) + if (Fdb == 'None'): + print "ERROR: E0002 Could not open the Framework Database file:", FdbFile + sys.exit(1) + + if (options.debug): + print "FrameworkDataBase.db file:", FdbFile + + # + InitializeAutoGen(workspace, Fdb) + + if (options.filename): + filename = options.filename + if ((options.verbose > 1) | (options.autowrite)): + print "Filename:", filename + else: + print "ERROR: E0001 - You must specify an input filename" + sys.exit(1) + + if (options.outfile): + outputFile = options.outfile + else: + outputFile = filename.replace('.msa', '.inf') + + if ((options.verbose > 2) or (options.debug)): + print "Output Filename:", outputFile + + Msa = openMsa(filename) + if (Msa == 'None'): + ## Maybe developer think WORKSPACE macro is the root directory of file name + ## So we will try to add WORKSPACE path into filename + MsaFileName = "" + MsaFileName = os.path.join(workspace, filename) + Msa = openMsa(MsaFileName) + if (Msa == 'None'): + print "ERROR: E0002: Could not open the file:", filename + sys.exit(1) + + AutoGenModuleFolder = os.path.dirname(filename) + + MsaHeader = "/ModuleSurfaceArea/MsaHeader/" + MsaDefs = "/ModuleSurfaceArea/ModuleDefinitions/" + BaseName = str(XmlElement(Msa, MsaDefs + "OutputFileBasename")).strip() + + if (len(BaseName) < 1): + BaseName = str(XmlElement(Msa, MsaHeader + "BaseName")).strip() + BaseName = re.sub(' ', '_', BaseName) + + GuidValue = str(XmlElement(Msa, MsaHeader + "GuidValue")).strip() + VerString = str(XmlElement(Msa, MsaHeader + "Version")).strip() + ModType = str(XmlElement(Msa, MsaHeader + "ModuleType")).strip() + CopyRight = str(XmlElement(Msa, MsaHeader + "Copyright")).strip() + Abstract = str(XmlElement(Msa, MsaHeader + "Abstract")).strip() + Description = str(XmlElement(Msa, MsaHeader + "Description")).strip().replace(" ", " ").replace(" ", " ").replace(" ", " ") + if not CopyRight.find("2007"): + CopyRight = CopyRight.replace("2006", "2007") + License = str(XmlElement(Msa, MsaHeader + "License")).strip().replace(" ", " ") + MsaDefs = "/ModuleSurfaceArea/ModuleDefinitions/" + BinModule = "" + try: + BinModule = str(XmlElement(Msa, MsaDefs + "BinaryModule")).strip() + except: + pass + + SupportedArchitectures = "" + try: + SupportedArchitectures = str(XmlElement(Msa, MsaDefs + "SupportedArchitectures")).strip() + except: + pass + + DefinesComments = [] + if (len(SupportedArchitectures) > 0): + DefinesComments.insert(0, "\n#\n# The following information is for reference only and not required by the build tools.\n#\n") + DefinesComments.append("# VALID_ARCHITECTURES = " + SupportedArchitectures + "\n") + DefinesComments.append("#\n") + + MsaExtern = "/ModuleSurfaceArea/Externs/" + PcdIsDriver = "" + try: + PcdIsDriver = str(XmlElement(Msa, MsaExtern + "PcdIsDriver")).strip() + except: + pass + + SpecList = [] + List = [] + try: + List = XmlList(Msa, MsaExtern + "Specification") + except: + pass + + if (len(List) > 0): + for spec in List[:]: + SpecList.insert(0, str(XmlElementData(spec)).strip()) + + DriverModules = [] + LibraryModules = [] + Externlist = [] + Flag = (DefinesComments == []) + + # Data structure to insert autogen code + AutoGenDriverModel = [] + AutoGenExitBootServices = [] + AutoGenVirtualAddressChanged = [] + AutoGenEntryPoint = "" + AutoGenUnload = "" + AutoGenGuid = [] + AutoGenLibClass = [] + AutoGenPackage = [] + AutoGenSourceFiles = [] + OldEntryPoint = "" + OldUnload = "" + + try: + Externlist = XmlList(Msa, MsaExtern + "Extern") + except: + pass + + if (len(Externlist) > 0): + if (options.debug and options.verbose > 2): + print "In Extern Parsing Routine" + for extern in Externlist: + EntryPoint = "" + Unload = "" + DBinding = "" + CompName = "" + Diag = "" + Config = "" + Constr = "" + Destr = "" + CallBack = "" + lFlag = False + AutoGenDriverModelItem = [] + try: + EntryPoint = str(XmlElementData(extern.getElementsByTagName("ModuleEntryPoint")[0])).strip() + AutoGenEntryPoint = EntryPoint + #DriverModules.append(" %-30s = %s\n" % ("ENTRY_POINT" , EntryPoint)) + except: + pass + + try: + Unload = str(XmlElementData(extern.getElementsByTagName("ModuleUnloadImage")[0])).strip() + AutoGenUnload = Unload + DriverModules.append(" %-30s = %s\n" % ("UNLOAD_IMAGE", Unload)) + except: + pass + + try: + DBinding = str(XmlElementData(extern.getElementsByTagName("DriverBinding")[0])).strip() + AutoGenDriverModelItem.append("&" + DBinding) + DefinesComments.append("# %-29s = %-45s\n" % ("DRIVER_BINDING", DBinding)) + lFlag = True + except: + pass + + try: + CompName = str(XmlElementData(extern.getElementsByTagName("ComponentName")[0])).strip() + AutoGenDriverModelItem.append("&" + CompName) + DefinesComments.append("# %-29s = %-45s\n" % ("COMPONENT_NAME", CompName)) + lFlag = True + except: + if lFlag: + AutoGenDriverModelItem.append("NULL") + pass + + try: + Config = str(XmlElementData(extern.getElementsByTagName("DriverConfig")[0])).strip() + AutoGenDriverModelItem.append("&" + Config) + DefinesComments.append("# %-29s = %-45s\n" % ("DRIVER_CONFIG", Config)) + lFlag = True + except: + if lFlag: + AutoGenDriverModelItem.append("NULL") + pass + + try: + Diag = str(XmlElementData(extern.getElementsByTagName("DriverDiag")[0])).strip() + AutoGenDriverModelItem.append("&" + Diag) + DefinesComments.append("# %-29s = %-45s\n" % ("DRIVER_DIAG", Diag)) + lFlag = True + except: + if lFlag: + AutoGenDriverModelItem.append("NULL") + pass + + if len(AutoGenDriverModelItem) > 0: + AutoGenDriverModel.append(AutoGenDriverModelItem) + + try: + Constr = str(XmlElementData(extern.getElementsByTagName("Constructor")[0])).strip() + LibraryModules.append(" %-30s = %s\n" % ("CONSTRUCTOR", Constr)) + except: + pass + + try: + Destr = str(XmlElementData(extern.getElementsByTagName("Destructor")[0])).strip() + LibraryModules.append(" %-30s = %s\n" % ("DESTRUCTOR", Destr)) + except: + pass + + try: + CallBack = str(XmlElement(extern, "Extern/SetVirtualAddressMapCallBack")).strip() + if CallBack != "": + AutoGenVirtualAddressChanged.append(CallBack) + DefinesComments.append("# %-29s = %-45s\n" % ("VIRTUAL_ADDRESS_MAP_CALLBACK", CallBack)) + lFlag = True + except: + + pass + + try: + CallBack = str(XmlElement(extern, "Extern/ExitBootServicesCallBack")).strip() + if CallBack != "": + AutoGenExitBootServices.append(CallBack) + DefinesComments.append("# %-29s = %-45s\n" % ("EXIT_BOOT_SERVICES_CALLBACK", CallBack)) + lFlag = True + except: + pass + + + Flag = False + + """ Get the Module's custom build options """ + MBOlines = [] + MBO = "/ModuleSurfaceArea/ModuleBuildOptions/Options/Option" + mboList = [] + try: + mboList = XmlList(Msa, MBO) + except: + pass + + if (len(mboList) > 0): + for Option in mboList: + Targets = [] + Archs = [] + + bt = "" + try: + bt = str(Option.getAttribute("BuildTargets")) + except: + pass + + if (len(bt) > 0): + if (re.findall(" ", bt) > 0): + Targets = bt.split() + else: + Targets.insert(0, bt) + else: + Targets.insert(0, "*") + + if (options.debug and options.verbose > 2): + print "Targets", len(Targets), Targets + + pro = "" + try: + pro = Option.getAttribute("SupArchList") + if (re.findall(" ", pro) > 0): + Archs = pro.split() + elif (re.findall(",", pro) > 0): + Archs = pro.split(",") + except: + pass + + if (len(pro) == 0): + Archs.insert(0, "*") + + if (options.debug and options.verbose > 2): + print "Archs", len(Archs), Archs + + ToolCode = "" + try: + ToolCode = str(Option.getAttribute("ToolCode")) + except: + pass + + if (len(ToolCode) == 0): + ToolCode="*" + + value = "" + try: + value = str(XmlElementData(Option)) + except: + pass + Tags = [] + TagName = "" + try: + TagName = str(Option.getAttribute("TagName")) + except: + pass + + if (len(TagName) > 0) : + if (options.debug and options.verbose > 2): + print "TagName was defined:", TagName + Tags.insert(0, TagName) + else: + if (options.debug and options.verbose > 2): + print "TagName was NOT defined!" + TagName = "*" + Tags.insert(0, "*") + + Family = "" + try: + Family = str(Option.getAttribute("ToolChainFamily")).strip() + except: + pass + + if (len(Family) > 0): + if (options.debug): + print "Searching tools_def.txt for Tool Tags that belong to:", Family, "family" + TCF = [] + tdFile = "" + tdPath = os.path.join(workspace, "Tools") + tdPath = os.path.join(tdPath, "Conf") + tdPath = os.path.join(tdPath, "tools_def.txt") + tdPath = tdPath.replace("\\", "/") + if os.path.exists(tdPath): + tdFile = tdPath + else: + tdPath = os.path.join(workspace, "Conf") + tdPath = os.path.join(tdPath, "tools_def.txt") + if os.path.exists(tdPath): + tdFile = tdPath + else: + print "ERROR: E0001: WORKSPACE does not contain the tools_def.txt File.\n Please run EdkSetup from the EDK II install directory.\n" + sys.exit(1) + + if (options.debug and options.verbose > 2): + print "Opening:", tdFile + + TagNameList = [] + tools_def = open(tdFile, "r") + for tdline in tools_def: + if "# " in tdline: + continue + if "FAMILY" in tdline: + if (options.debug and options.verbose > 2): + print "Testing for FAMILY:", Family, "in the line:", tdline.strip() + if Family in tdline: + enter = tdline.split("=")[0] + if (options.debug and options.verbose > 2): + print "Adding TNL:", tdline + TagNameList.insert(0, enter) + tools_def.close() + + if (options.debug and options.verbose > 2): + print "TagNameList:", TagNameList + + olinesSet = {} + for eline in TagNameList: + if "# " in eline: + continue + if (options.debug and options.verbose > 2): + print "ToolsDef entry:", eline + + olines = MatchOption(eline, Family, Targets, Archs, ToolCode, value) + for oline in olines: + olinesSet[oline] = 1 + + for oline in olinesSet: + if (options.debug and options.verbose > 2): + print "Adding:", str(oline) + MBOlines.insert(0, oline) + else: + for targ in Targets: + for arch in Archs: + oline = " %s_%s_%s_%s_FLAGS = %s" % (targ, Tags[0], arch, str(ToolCode), str(Value)) + if (options.debug and options.verbose > 2): + print "Adding:", str(oline) + MBOlines.insert(0, oline) + + + + + for tag in Tags: + for targ in Targets: + for arch in Archs: + oline = " " + str(targ) + "_" + str(tag) + "_" + str(arch) + "_" + str(ToolCode) + "_FLAGS = " + str(value) + if (options.debug and options.verbose > 2): + print "Adding:", str(oline) + #MBOlines.insert(0, oline) + + + """ Get the Library Class information """ + MsaLcDefs = "/ModuleSurfaceArea/LibraryClassDefinitions/LibraryClass" + LcDefList = [] + try: + LcDefList = XmlList(Msa, MsaLcDefs) + except: + pass + + IamLibrary = [] + LibClassList = [] + LibClassListIa32 = [] + LibClassListX64 = [] + LibClassListIpf = [] + LibClassListEbc = [] + + + if (len(LcDefList) > 0): + for Lc in LcDefList: + lcKeyword = "" + try: + lcKeyword = str(XmlElementData(Lc.getElementsByTagName("Keyword")[0])) + except: + raise SyntaxError, "The MSA is not correctly formed, a Library Class Keyword Element is required" + + lcUsage = "" + try: + lcUsage = str(XmlAttribute(Lc, "Usage")) + except: + raise SyntaxError, "The MSA is not correctly formed, a Usage Attribute is required for all Library Class Elements" + + Archs = "" + try: + Archs = str(XmlAttribute(Lc, "SupArchList")) + except: + pass + + Archs = chkArch(Archs) + + if (options.debug and options.verbose > 2): + print "Attr: ", lcUsage, lcKeyword, Archs + + if (options.convert): + lcKeyword = AutoGenLibraryMapping.get(lcKeyword, lcKeyword) + + if re.findall("PRODUCED", lcUsage, re.IGNORECASE): + try: + lcSupModList = "" + + try: + lcSupModList = str(XmlAttribute(Lc, "SupModuleList")) + except: + lcSupModList = "" + pass + + lcLine = lcKeyword + AutoGenLibClass.append(lcKeyword) + if len(lcSupModList) > 0: + lcLine = lcLine + "|" + lcSupModList + IamLibrary.insert(0, lcLine) + except: + pass + elif lcKeyword != "UefiDriverModelLib": + AutoGenLibClass.append(lcKeyword) + # This section handles the library classes that are CONSUMED + if "IA32" in Archs: + LibClassListIa32.insert(0, lcKeyword) + if "X64" in Archs: + LibClassListX64.insert(0, lcKeyword) + if "IPF" in Archs: + LibClassListIpf.insert(0, lcKeyword) + if "EBC" in Archs: + LibClassListEbc.insert(0, lcKeyword) + if "ALL" in Archs: + LibClassList.insert(0, lcKeyword) + if len(AutoGenDriverModel) > 0 and "UefiLib" not in LibClassList: + AutoGenLibClass.append("UefiLib") + LibClassList.insert(0, "UefiLib") + + AutoGenDxsFiles = [] + """ Get the Source File list """ + SrcFilenames = [] + SrcFilenamesIa32 = [] + SrcFilenamesX64 = [] + SrcFilenamesIpf = [] + SrcFilenamesEbc = [] + SrcFiles = "/ModuleSurfaceArea/SourceFiles/Filename" + SrcList = [] + try: + SrcList = XmlList(Msa, SrcFiles) + except: + pass + + if (len(SrcList) > 0): + for fn in SrcList: + file = "" + Archs = "" + + try: + Archs = fn.getAttribute("SupArchList") + except: + pass + + Archs = chkArch(Archs) + + try: + file = str(XmlElementData(fn)) + except: + pass + + if file.endswith(".dxs"): + AutoGenDxsFiles.append((file, Archs)) + else: + AutoGenSourceFiles.append(file) + if "IA32" in Archs: + SrcFilenamesIa32.insert(0, file) + if "X64" in Archs: + SrcFilenamesX64.insert(0, file) + if "IPF" in Archs: + SrcFilenamesIpf.insert(0, file) + if "EBC" in Archs: + SrcFilenamesEbc.insert(0, file) + if "ALL" in Archs: + SrcFilenames.insert(0, file) + + """ Package Dependency section """ + DbPkgList = "/FrameworkDatabase/PackageList/Filename" + WorkspacePkgs = [] + try: + WorkspacePkgs = XmlList(Fdb, DbPkgList) + except: + print "Could not tet the package data from the database" + sys.exit(1) + + PkgDb = [] + HeaderLocations = [] + + if (options.debug and options.verbose > 1): + print "Found %s packages in the WORKSPACE" % (len(WorkspacePkgs)) + + Dirs = [] + GuidDecls = [] + if (len(WorkspacePkgs) > 0): + SpdHeader = "/PackageSurfaceArea/SpdHeader/" + for Pkg in WorkspacePkgs[:]: + PackageGuid = "" + PackageVersion = "" + file = "" + try: + file = str(XmlElementData(Pkg)) + except: + pass + + if (options.debug and options.verbose > 2): + print "PKG:", file + + if fnmatch.fnmatch(file, "*.dec"): + print "parsing " + os.path.join(workspace, file) + PackageGuid = "" + PackageVersion = "" + try: + Lines = open(os.path.join(workspace, file)).readlines() + except: + print "Could not parse the Package file:", file + sys.exit(1) + + for Line in Lines: + Line = Line.split("#")[0] + Items = Line.split("=") + if len(Items) != 2: + continue + + Key = Items[0].strip().upper() + if Key == "PACKAGE_GUID": + PackageGuid = Items[1].strip() + if Key == "PACKAGE_VERSION": + PackageVersion = Items[1].strip() + + else: + Spd = openSpd(os.path.join(workspace, file)) + if (Spd == 'None'): + print "Could not parse the Package file:", file + sys.exit(1) + + path = os.path.split(file)[0] + file = file.replace(".nspd", ".dec") + file = file.replace(".spd", ".dec") + + try: + PackageGuid = str(XmlElement(Spd, SpdHeader + "GuidValue")) + except: + pass + + try: + PackageVersion = str(XmlElement(Spd, SpdHeader + "Version")) + except: + pass + + file = file + "|" + PackageGuid + "|" + PackageVersion + PkgDb.insert(0, file) + + GuidEntries = [] + try: + GuidEntries = XmlList(Spd, "/PackageSurfaceArea/GuidDeclarations/Entry") + except: + pass + + if (len(GuidEntries) > 0): + for Entry in GuidEntries[:]: + try: + GuidDecls.append(str(XmlElementData(Entry.getElementsByTagName("C_Name")[0])).strip()) + except: + pass + + + pHdrs = [] + try: + pHdrs = XmlList(Spd, "/PackageSurfaceArea/PackageHeaders/IncludePkgHeader") + except: + pass + + if (len(pHdrs) > 0): + for Hdr in pHdrs[:]: + try: + ModTypeList = str(Hdr.getAttribute("ModuleType")) + if (ModType in ModTypeList): + HeaderName= str(XmlElementData(Hdr))[0] + Dirs.insert(0, os.path.join(packagepath,str(os.path.split(HeaderName)))) + except: + pass + + # Get the Guid:Header from the Packages + SpdLcDec = "/PackageSurfaceArea/LibraryClassDeclarations/LibraryClass" + lcList = [] + try: + lcList = XmlList(Spd, SpdLcDec) + except: + pass + + if (len(lcList) > 0): + for Lc in lcList[:]: + Name = "" + try: + Name = Lc.getAttribute("Name") + except: + pass + + Header = "" + try: + Header = XmlElementData(Lc.getElementsByTagName("IncludeHeader")[0]) + except: + pass + + if ((len(Name) > 0) and (len(Header) > 0)): + line = Name + "|" + os.path.join(path, Header) + if (options.debug and options.verbose > 2): + print "Adding:", line + HeaderLocations.insert(0, line) + + ishList = [] + try: + IndStdHeaders = "/PackageSurfaceArea/IndustryStdIncludes/IndustryStdHeader" + ishList = XmlList(Spd, IndStdHeaders) + except: + pass + + if (len(ishList) > 0): + for Lc in ishList[:]: + Name = "" + try: + Name = str(Lc.getAttribute("Name")).strip() + except: + pass + + Header = "" + try: + Header = str(XmlElementData(Lc.getElementsByTagName("IncludeHeader")[0])).strip() + except: + pass + + if ((len(Name) > 0) and (len(Header) > 0)): + line = Name + "|" + os.path.join(path, Header) + HeaderLocations.insert(0, str(line)) + + PkgList = [] + PkgListIa32 = [] + PkgListX64 = [] + PkgListIpf = [] + PkgListEbc = [] + Pkgs = "/ModuleSurfaceArea/PackageDependencies/Package" + pkgL = [] + try: + pkgL = XmlList(Msa, Pkgs) + except: + pass + + + gUnknownPkgGuid = {} + if (len(pkgL) > 0): + if (options.debug and options.verbose > 1): + print "Found %s packages in the module" % (len(pkgL)) + for pkg in pkgL[:]: + Archs = "" + pkgGuid = "" + pkgVer = "" + + FindPkgGuid = False + try: + Archs = pkg.getAttribute("SupArchList") + except: + pass + + Archs = chkArch(Archs) + + try: + pkgGuid = pkg.getAttribute("PackageGuid") + except: + pass + + if options.convert: + if pkgGuid.lower() == "5e0e9358-46b6-4ae2-8218-4ab8b9bbdcec": + pkgGuid = "1E73767F-8F52-4603-AEB4-F29B510B6766" + if pkgGuid.lower() == "68169ab0-d41b-4009-9060-292c253ac43d": + pkgGuid = "BA0D78D6-2CAF-414b-BD4D-B6762A894288" + AutoGenPackage.append(pkgGuid) + try: + pkgVer = pkg.getAttribute("PackageVersion") + except: + pass + + for PkgEntry in PkgDb[:]: + if pkgGuid in PkgEntry: + if len(pkgVer) > 0: + if pkgVer in PkgEntry: + FindPkgGuid = True + if "IA32" in Archs: + PkgListIa32.insert(0, PkgEntry.split("|")[0]) + if "X64" in Archs: + PkgListX64.insert(0, PkgEntry.split("|")[0]) + if "IPF" in Archs: + PkgListIpf.insert(0, PkgEntry.split("|")[0]) + if "EBC" in Archs: + PkgListEbc.insert(0, PkgEntry.split("|")[0]) + if "ALL" in Archs: + PkgList.insert(0, PkgEntry.split("|")[0]) + else: + FindPkgGuid = True + if "IA32" in Archs: + PkgListIa32.insert(0, PkgEntry.split("|")[0]) + if "X64" in Archs: + PkgListX64.insert(0, PkgEntry.split("|")[0]) + if "IPF" in Archs: + PkgListIpf.insert(0, PkgEntry.split("|")[0]) + if "EBC" in Archs: + PkgListEbc.insert(0, PkgEntry.split("|")[0]) + if "ALL" in Archs: + PkgList.insert(0, PkgEntry.split("|")[0]) + + if not FindPkgGuid: + gUnknownPkgGuid[str(pkgGuid)] = 1 + + for UnknownPkgGuid in gUnknownPkgGuid: + print "Cannot resolve package dependency Guid:", UnknownPkgGuid + + PkgList.reverse() + PkgListIa32.reverse() + PkgListX64.reverse() + PkgListIpf.reverse() + PkgListEbc.reverse() + if (options.debug): + print "Package List:", PkgList + + + + """ Setup the Global GuidCName arrays that will hold data from various MSA locations """ + global GuidCName + global GuidCNameIa32 + global GuidCNameX64 + global GuidCNameIPF + global GuidCNameEBC + GuidCName = [] + GuidCNameIa32 = [] + GuidCNameX64 = [] + GuidCNameIPF = [] + GuidCNameEBC = [] + + """ Check for the GUIDs Element """ + Guids = "/ModuleSurfaceArea/Guids/GuidCNames" + GuidList = [] + try: + GuidList = XmlList(Msa, Guids) + except: + pass + + if (len(GuidList) > 0): + for Guid in GuidList: + Archs = "" + Usage = "" + CName = "" + + try: + Archs = Guid.getAttribute("SupArchList") + except: + pass + + Archs = chkArch(Archs) + + try: + Usage = Guid.getAttribute("Usage") + except: + pass + + try: + CName = str(XmlElementData(Guid.getElementsByTagName("GuidCName")[0])) + if CName in GuidDecls: + if (options.debug and options.verbose > 1): + print "Guids Adding Guid CName: %-45s # %s Archs: %s" % (CName, Usage, Archs) + AddGuid(Archs, CName, Usage) + AutoGenGuid.append(CName) + else: + raise AssertionError, "Guid %s defined in %s is not declared in any package (.dec) file!" % (CName, filename) + except: + pass + + if (options.debug and options.verbose > 2): + print "Guid C Name List:", GuidCName + + """ Check for Events """ + Guids = "/ModuleSurfaceArea/Events/CreateEvents/EventTypes" + GuidList = [] + try: + GuidList = XmlList(Msa, Guids) + except: + pass + + if (len(GuidList) > 0): + for Guid in GuidList: + Archs = "" + Usage = "" + CName = "" + + try: + Archs = Guid.getAttribute("SupArchList") + except: + pass + + Archs = chkArch(Archs) + + try: + Usage = Guid.getAttribute("Usage") + Type = str(XmlElementData(Guid.getElementsByTagName("EventType")[0])) + Usage += " Create Event: " + Type + except: + pass + + try: + CName = str(Guid.getAttribute("EventGuidCName")) + if CName in GuidDecls: + if (options.debug and options.verbose > 1): + print "CreateEvent Adding Guid CName: %-45s # %s Archs: %s" % (CName, Usage, Archs) + AddGuid(Archs, CName, Usage) + AutoGenGuid.append(CName) + else: + if (len(DefinesComments) == 0): + DefinesComments.insert(0, "\n#\n# The following information is for reference only and not required by the build tools.\n#\n") + DefinesComments.append("# Create Event Guid C Name: " + CName + " Event Type: " + Type + "\n") + Flag = True + except: + pass + + if (Flag): + DefinesComments.append("#\n") + Flag = False + + Guids = "/ModuleSurfaceArea/Events/SignalEvents/EventTypes" + GuidList = [] + try: + GuidList = XmlList(Msa, Guids) + except: + pass + + if (len(GuidList) > 0): + for Guid in GuidList: + Archs = "" + Usage = "" + CName = "" + + try: + Archs = Guid.getAttribute("SupArchList") + except: + pass + + Archs = chkArch(Archs) + + try: + Usage = Guid.getAttribute("Usage") + Type = str(XmlElementData(Guid.getElementsByTagName("EventType")[0])) + Usage += " Signal Event: " + Type + except: + pass + + try: + CName = str(Guid.getAttribute("EventGuidCName")) + if CName in GuidDecls: + if (options.debug and options.verbose > 1): + print "SignalEvent Adding Guid CName: %-45s # %s Archs: %s" % (CName, Usage, Archs) + AddGuid(Archs, CName, Usage) + AutoGenGuid.append(CName) + else: + if (len(DefinesComments) == 0): + DefinesComments.insert(0, "\n#\n# The following information is for reference only and not required by the build tools.\n#\n") + DefinesComments.append("# Signal Event Guid C Name: " + CName + " Event Type: " + Type + "\n") + Flag = True + except: + pass + + if (Flag): + DefinesComments.append("#\n") + Flag = False + + """ Check the HOB guids """ + Guids = "/ModuleSurfaceArea/Hobs/HobTypes" + GuidList = [] + try: + GuidList = XmlList(Msa, Guids) + except: + pass + + if (len(GuidList) > 0): + for Guid in GuidList: + Archs = "" + Usage = "" + CName = "" + + try: + Archs = Guid.getAttribute("SupArchList") + except: + pass + + Archs = chkArch(Archs) + + try: + Usage = Guid.getAttribute("Usage") + Type = str(XmlElementData(Guid.getElementsByTagName("HobType")[0])) + Usage += " Hob: " + Type + except: + pass + + try: + CName = str(Guid.getAttribute("HobGuidCName")) + if CName in GuidDecls: + if (options.debug and options.verbose > 1): + print "Hob Adding Guid CName: %-45s # %s Archs: %s" % (CName, Usage, Archs) + AddGuid(Archs, CName, Usage) + AutoGenGuid.append(CName) + else: + if (len(DefinesComments) == 0): + DefinesComments.insert(0, "\n#\n# The following information is for reference only and not required by the build tools.\n#\n") + DefinesComments.append("# HOB Guid C Name: " + CName + " Hob Type: " + Type + "\n") + Flag = True + except: + if (len(DefinesComments) == 0): + DefinesComments.insert(0, "\n#\n# The following information is for reference only and not required by the build tools.\n#\n") + DefinesComments.append("# HOB: " + Type + "\n") + Flag = True + pass + + if (Flag): + DefinesComments.append("#\n") + Flag = False + + """ Check for the SystemTables Element """ + Guids = "/ModuleSurfaceArea/SystemTables/SystemTableCNames" + GuidList = [] + try: + GuidList = XmlList(Msa, Guids) + except: + pass + + if (len(GuidList) > 0): + for Guid in GuidList: + Archs = "" + Usage = "" + CName = "" + + try: + Archs = Guid.getAttribute("SupArchList") + except: + pass + + Archs = chkArch(Archs) + + try: + Usage = Guid.getAttribute("Usage") + Usage += " System Table" + except: + pass + + try: + CName = str(XmlElementData(Guid.getElementsByTagName("SystemTableCName")[0])) + if (options.debug and options.verbose > 1): + print "System Table Adding Guid CName: %-45s # %s Archs: %s" % (CName, Usage, Archs) + AddGuid(Archs, CName, Usage) + AutoGenGuid.append(CName) + except: + pass + + """ Check for the DataHubs Element """ + Guids = "/ModuleSurfaceArea/DataHubs/DataHubRecord" + GuidList = [] + try: + GuidList = XmlList(Msa, Guids) + except: + pass + + if (len(GuidList) > 0): + for Guid in GuidList: + Archs = "" + Usage = "" + CName = "" + + try: + Archs = Guid.getAttribute("SupArchList") + except: + pass + + Archs = chkArch(Archs) + + try: + Usage = Guid.getAttribute("Usage") + Usage += " Data Hub" + except: + pass + + try: + CName = str(XmlElementData(Guid.getElementsByTagName("DataHubCName")[0])) + if (options.debug and options.verbose > 1): + print "Data Hub Adding Guid CName: %-45s # %s Archs: %s" % (CName, Usage, Archs) + AddGuid(Archs, CName, Usage) + AutoGenGuid.append(CName) + except: + pass + + """ Check for the HiiPackages Element """ + Guids = "/ModuleSurfaceArea/HiiPackages/HiiPackage" + GuidList = [] + try: + GuidList = XmlList(Msa, Guids) + except: + pass + + if (len(GuidList) > 0): + for Guid in GuidList: + Archs = "" + Usage = "" + CName = "" + + try: + Archs = Guid.getAttribute("SupArchList") + except: + pass + + Archs = chkArch(Archs) + + try: + Usage = Guid.getAttribute("Usage") + Usage += " HII Formset" + except: + pass + + try: + CName = str(XmlElementData(Guid.getElementsByTagName("HiiCName")[0])) + if (options.debug and options.verbose > 1): + print "Hii Formset Adding Guid CName: %-45s # %s Archs: %s" % (CName, Usage, Archs) + AddGuid(Archs, CName, Usage) + AutoGenGuid.append(CName) + except: + pass + + """ Check for the Variables Element """ + Guids = "/ModuleSurfaceArea/Variables/Variable" + GuidList = [] + try: + GuidList = XmlList(Msa, Guids) + except: + pass + + if (len(GuidList) > 0): + for Guid in GuidList: + Archs = "" + Usage = "" + CName = "" + VariableName = "" + + try: + Archs = Guid.getAttribute("SupArchList") + except: + pass + + Archs = chkArch(Archs) + + try: + Usage = Guid.getAttribute("Usage") + except: + pass + + try: + VariableName = str(XmlElementData(Guid.getElementsByTagName("VariableName")[0])) + CName = str(XmlElementData(Guid.getElementsByTagName("GuidC_Name")[0])) + + HexData = VariableName.strip().split() + UniString = " L\"" + for dig in HexData[:]: + UniString += str(unichr(eval(dig))) + UniString += "\"" + + Usage += UniString + + if CName in set(GuidDecls): + removeDups(CName, GuidCName) + removeDups(CName, GuidCNameIa32) + removeDups(CName, GuidCNameX64) + removeDups(CName, GuidCNameIPF) + removeDups(CName, GuidCNameEBC) + + if (options.debug): + print "Variable Adding Guid CName: %-45s # %s Archs: %s" % (CName, Usage, Archs) + AddGuid(Archs, CName, Usage) + AutoGenGuid.append(CName) + else: + if (len(DefinesComments) == 0): + DefinesComments.insert(0, "\n#\n# The following information is for reference only and not required by the build tools.\n#\n") + DefinesComments.append("# Variable Guid C Name: " + CName + " Variable Name:" + UniString + "\n") + Flag = True + except: + pass + + if (Flag): + DefinesComments.append("#\n") + Flag = False + + """ Check for the Protocol Element """ + Protocols = "/ModuleSurfaceArea/Protocols/Protocol" + ProtocolList = [] + ProtocolCName = [] + ProtocolCNameIa32 = [] + ProtocolCNameX64 = [] + ProtocolCNameIPF = [] + ProtocolCNameEBC = [] + + try: + ProtocolList = XmlList(Msa, Protocols) + except: + pass + + if (len(ProtocolList) > 0): + for Protocol in ProtocolList: + Archs = "" + Usage = "" + CName = "" + + try: + Archs = Protocol.getAttribute("SupArchList") + except: + pass + + Archs = chkArch(Archs) + + try: + Usage = Protocol.getAttribute("Usage") + except: + pass + + try: + CName = str(XmlElementData(Protocol.getElementsByTagName("ProtocolCName")[0])) + AutoGenGuid.append(CName) + removeDups(CName, GuidCName) + removeDups(CName, GuidCNameIa32) + removeDups(CName, GuidCNameX64) + removeDups(CName, GuidCNameIPF) + removeDups(CName, GuidCNameEBC) + + if (options.debug and options.verbose > 1): + print "Found %s - %s - %s " % (CName, Usage, str(len(Archs))) + + if "IA32" in Archs: + ProtocolCNameIa32.insert(0, str(" %-45s # PROTOCOL %s" % (CName, Usage))) + if "X64" in Archs: + ProtocolCNameX64.insert(0, str(" %-45s # PROTOCOL %s" % (CName, Usage))) + if "IPF" in Archs: + ProtocolCNameIPF.insert(0, str(" %-45s # PROTOCOL %s" % (CName, Usage))) + if "EBC" in Archs: + ProtocolCNameEBC.insert(0, str(" %-45s # PROTOCOL %s" % (CName, Usage))) + if "ALL" in Archs: + ProtocolCName.insert(0, str(" %-45s # PROTOCOL %s" % (CName, Usage))) + except: + pass + + + Protocols = "/ModuleSurfaceArea/Protocols/ProtocolNotify" + try: + ProtocolList = XmlList(Msa, Protocols) + except: + pass + + if (len(ProtocolList) > 0): + for Protocol in ProtocolList: + Archs = "" + Usage = "" + CName = "" + + try: + Archs = Protocol.getAttribute("SupArchList") + except: + pass + + Archs = chkArch(Archs) + + try: + Usage = Protocol.getAttribute("Usage") + except: + pass + + try: + CName = str(XmlElementData(Protocol.getElementsByTagName("ProtocolNotifyCName")[0])) + AutoGenGuid.append(CName) + removeDups(CName, GuidCName) + removeDups(CName, GuidCNameIa32) + removeDups(CName, GuidCNameX64) + removeDups(CName, GuidCNameIPF) + removeDups(CName, GuidCNameEBC) + + if "IA32" in Archs: + ProtocolCNameIa32.insert(0, " %-45s # PROTOCOL_NOTIFY %s" % (CName, Usage)) + if "X64" in Archs: + ProtocolCNameX64.insert(0, " %-45s # PROTOCOL_NOTIFY %s" % (CName, Usage)) + if "IPF" in Archs: + ProtocolCNameIPF.insert(0, " %-45s # PROTOCOL_NOTIFY %s" % (CName, Usage)) + if "EBC" in Archs: + ProtocolCNameEBC.insert(0, " %-45s # PROTOCOL_NOTIFY %s" % (CName, Usage)) + if "ALL" in Archs: + ProtocolCName.insert(0, " %-45s # PROTOCOL_NOTIFY %s" % (CName, Usage)) + except: + pass + + """ Check for the PPIs Element """ + PPIs = "/ModuleSurfaceArea/PPIs/Ppi" + PPIsList = [] + PpiCName = [] + PpiCNameIa32 = [] + PpiCNameX64 = [] + PpiCNameIPF = [] + PpiCNameEBC = [] + + try: + PPIsList = XmlList(Msa, PPIs) + except: + pass + + if (len(PPIsList) > 0): + for Ppi in PPIsList: + Archs = "" + Usage = "" + CName = "" + + try: + Archs = str(Ppi.getAttribute("SupArchList")) + except: + pass + + Archs = chkArch(Archs) + + try: + Usage = str(Ppi.getAttribute("Usage")) + except: + pass + + try: + CName = str(XmlElementData(Ppi.getElementsByTagName("PpiCName")[0])).strip() + AutoGenGuid.append(CName) + removeDups(CName, GuidCName) + removeDups(CName, GuidCNameIa32) + removeDups(CName, GuidCNameX64) + removeDups(CName, GuidCNameIPF) + removeDups(CName, GuidCNameEBC) + + if "IA32" in Archs: + PpiCNameIa32.insert(0, " %-45s # PPI %s" % (CName, Usage)) + if "X64" in Archs: + PpiCNameX64.insert(0, " %-45s # PPI %s" % (CName, Usage)) + if "IPF" in Archs: + PpiCNameIPF.insert(0, " %-45s # PPI %s" % (CName, Usage)) + if "EBC" in Archs: + PpiCNameEBC.insert(0, " %-45s # PPI %s" % (CName, Usage)) + if "ALL" in Archs: + PpiCName.insert(0, " %-45s # PPI %s" % (CName, Usage)) + except: + pass + + + PPIs = "/ModuleSurfaceArea/PPIs/PpiNotify" + try: + PPIsList = XmlList(Msa, PPIs) + except: + pass + + if (len(PPIsList) > 0): + for Ppi in PPIsList: + Archs = "" + Usage = "" + CName = "" + + try: + Archs = Ppi.getAttribute("SupArchList") + except: + pass + + Archs = chkArch(Archs) + + try: + Usage = Ppi.getAttribute("Usage") + except: + pass + + try: + CName = str(XmlElementData(Ppi.getElementsByTagName("PpiNotifyCName")[0])) + AutoGenGuid.append(CName) + removeDups(CName, GuidCName) + removeDups(CName, GuidCNameIa32) + removeDups(CName, GuidCNameX64) + removeDups(CName, GuidCNameIPF) + removeDups(CName, GuidCNameEBC) + + if "IA32" in Archs: + PpiCNameIa32.insert(0, " %-45s # PPI_NOTIFY %s" % (CName, Usage)) + if "X64" in Archs: + PpiCNameX64.insert(0, " %-45s # PPI_NOTIFY %s" % (CName, Usage)) + if "IPF" in Archs: + PpiCNameIPF.insert(0, " %-45s # PPI_NOTIFY %s" % (CName, Usage)) + if "EBC" in Archs: + PpiCNameEBC.insert(0, " %-45s # PPI_NOTIFY %s" % (CName, Usage)) + if "ALL" in Archs: + PpiCName.insert(0, " %-45s # PPI_NOTIFY %s" % (CName, Usage)) + except: + pass + + + """ Get the PCD entries now """ + PcdCoded = "/ModuleSurfaceArea/PcdCoded/PcdEntry" + PcdList = [] + try: + PcdList = XmlList(Msa, PcdCoded) + except: + pass + + (PcdFF, PcdFFIa32, PcdFFX64, PcdFFIpf, PcdFFEbc) = ([],[],[],[],[]) + (PcdFAB, PcdFABIa32, PcdFABX64, PcdFABIpf, PcdFABEbc) = ([],[],[],[],[]) + (PcdPIM, PcdPIMIa32, PcdPIMX64, PcdPIMIpf, PcdPIMEbc) = ([],[],[],[],[]) + (PcdDY, PcdDYIa32, PcdDYX64, PcdDYIpf, PcdDYEbc) = ([],[],[],[],[]) + (PcdDYE, PcdDYEIa32, PcdDYEX64, PcdDYEIpf, PcdDYEEbc) = ([],[],[],[],[]) + + if (len(PcdList) > 0): + for Pcd in PcdList: + Archs = "" + Usage = "" + CName = "" + DefVal = "" + + try: + Archs = Pcd.getAttribute("SupArchList") + except: + pass + + Archs = chkArch(Archs) + + try: + ItemType = Pcd.getAttribute("PcdItemType") + except: + pass + + try: + CName = str(XmlElementData(Pcd.getElementsByTagName("C_Name")[0])) + except: + raise SyntaxError, "ERROR: MSA has a PCD with no Pcd C_Name defined" + + try: + TSGC = str(XmlElementData(Pcd.getElementsByTagName("TokenSpaceGuidCName")[0])) + except: + pass + + try: + DefVal = str(XmlElementData(Pcd.getElementsByTagName("DefaultValue"))) + except: + pass + + if (len(DefVal) > 0): + line = TSGC + "." + CName + "|" + DefVal + else: + line = TSGC + "." + CName + + if (ItemType == "FEATURE_FLAG"): + if ("IA32" in Archs): + PcdFFIa32.insert(0, line) + if ("IPF" in Archs): + PcdFFIpf.insert(0, line) + if ("X64" in Archs): + PcdFFX64.insert(0, line) + if ("EBC" in Archs): + PcdFFEbc.insert(0, line) + if ("ALL" in Archs): + PcdFF.insert(0, line) + elif (ItemType == "FIXED_AT_BUILD"): + if ("IA32" in Archs): + PcdFABIa32.insert(0, line) + if ("IPF" in Archs): + PcdFABIpf.insert(0, line) + if ("X64" in Archs): + PcdFABX64.insert(0, line) + if ("EBC" in Archs): + PcdFABEbc.insert(0, line) + if ("ALL" in Archs): + PcdFAB.insert(0, line) + elif (ItemType == "PATCHABLE_IN_MODULE"): + if ("IA32" in Archs): + PcdPIMIa32.insert(0, line) + if ("IPF" in Archs): + PcdPIMIpf.insert(0, line) + if ("X64" in Archs): + PcdPIMX64.insert(0, line) + if ("EBC" in Archs): + PcdPIMEbc.insert(0, line) + if ("ALL" in Archs): + PcdFAB.insert(0, line) + elif (ItemType == "DYNAMIC_EX"): + if ("IA32" in Archs): + PcdDYEIa32.insert(0, line) + if ("IPF" in Archs): + PcdDYEIpf.insert(0, line) + if ("X64" in Archs): + PcdDYEX64.insert(0, line) + if ("EBC" in Archs): + PcdDYEEbc.insert(0, line) + if ("ALL" in Archs): + PcdDYE.insert(0, line) + else: + if ("IA32" in Archs): + PcdDYIa32.insert(0, line) + if ("IPF" in Archs): + PcdDYIpf.insert(0, line) + if ("X64" in Archs): + PcdDYX64.insert(0, line) + if ("EBC" in Archs): + PcdDYEbc.insert(0, line) + if ("ALL" in Archs): + PcdDY.insert(0, line) + + """ User Extensions Section """ + UEList = [] + UESectionList = [] + try: + UESectionList = XmlList(Msa, "/ModuleSurfaceArea/UserExtensions") + except: + pass + + if (len(UESectionList) > 0): + for UE in UESectionList[:]: + UserId = "" + Identifier = "" + Value = "" + + try: + UserId = str(UE.getAttribute("UserID")) + except: + raise SyntaxError, "ERROR: Malformed MSA, No UserID Specified in UserExtensions element" + + try: + Identifier = str(UE.getAttribute("Identifier")) + except: + raise SyntaxError, "ERROR: Malformed MSA, No Identifier Specified in UserExtensions element" + + if (options.debug): + print "FOUND A UE Element", UserId, Identifier + + try: + Value = str(XmlElementData(UE)) + except: + pass + + Entry = [UserId, Identifier, Value] + UEList.insert(0, Entry) + + + + if (len(Externlist) > 0): + AutoGenSource = "" + AutoGenDefinitionSource = "" + AutoGenEntryPointSource = "" + AutoGenUnloadSource = "" + if (len(AutoGenDriverModel) > 0): + AutoGenCode = AddDriverBindingProtocolStatement(AutoGenDriverModel) + AutoGenEntryPointSource += AutoGenCode[0] + AutoGenUnloadSource += AutoGenCode[1] + AutoGenDeclaration += AutoGenCode[3] + + + if (len(AutoGenExitBootServices) > 0): + print "[Warning] Please manually add Create Event statement for Exit Boot Service Event!" + if options.event: + AutoGenCode = AddBootServiceEventStatement(AutoGenExitBootServices) + AutoGenEntryPointSource += AutoGenCode[0] + AutoGenUnloadSource += AutoGenCode[1] + AutoGenDefinitionSource += AutoGenCode[2] + AutoGenDeclaration += AutoGenCode[3] + + if (len(AutoGenVirtualAddressChanged) > 0): + print "[Warning] Please manually add Create Event statement for Virtual Address Change Event!" + if options.event: + AutoGenCode = AddVirtualAddressEventStatement(AutoGenVirtualAddressChanged) + AutoGenEntryPointSource += AutoGenCode[0] + AutoGenUnloadSource += AutoGenCode[1] + AutoGenDefinitionSource += AutoGenCode[2] + AutoGenDeclaration += AutoGenCode[3] + + if AutoGenEntryPointSource != "": + OldEntryPoint = AutoGenEntryPoint + AutoGenCode = AddNewEntryPointContentsStatement(BaseName, AutoGenEntryPoint, AutoGenEntryPointSource) + AutoGenEntryPoint = AutoGenCode[0] + AutoGenEntryPointSource = AutoGenCode[1] + AutoGenDeclaration += AutoGenCode[2] + + + if AutoGenEntryPoint != "": + DriverModules.insert(0, " %-30s = %s\n" % ("ENTRY_POINT" , AutoGenEntryPoint)) + + AutoGenSource = AutoGenDefinitionSource + AutoGenEntryPointSource + AutoGenUnloadSource + + if (lFlag): + DefinesComments.append("#\n") + + if (Flag and len(DefinesComments) > 0): + DefinesComments.insert(0, "\n#\n# The following information is for reference only and not required by the build tools.\n#\n") + + if (options.debug and options.verbose > 2): + if (len(DriverModules) > 0): + print DriverModules + if (len(LibraryModules) > 0): + print LibraryModules + if (len(DefinesComments) > 0): + print DefinesComments + + Depex = [] + DepexIa32 = [] + DepexX64 = [] + DepexIpf = [] + DepexEbc = [] + + for DxsFile, Archs in AutoGenDxsFiles: + fileContents = openSourceFile(AutoGenModuleFolder, DxsFile) + Contents, Unresolved = TranslateDpxSection(fileContents) + if Contents == "": + print "[warning] Cannot read dxs expression" + else: + if (len(Unresolved) > 0): + print "[warning] Guid Macro(s): %s cannot find corresponding cNames. Please resolve it in [depex] section in extened inf" % ",".join(Unresolved) + + if ("IA32" in Archs): + DepexIa32.insert(0, Contents) + if ("IPF" in Archs): + DepexIpf.insert(0, Contents) + if ("X64" in Archs): + DepexX64.insert(0, Contents) + if ("EBC" in Archs): + DepexEbc.insert(0, Contents) + if ("ALL" in Archs): + Depex.insert(0, Contents) + + AutoGenSourceHeaderFormat = "/**@file\n %s\n\n %s\n %s\n %s\n**/\n\n%s" + includeCommonHeaderFileStatement = "#include \"%s\"" % commonHeaderFilename + + AutoGenHeader += AddSystemIncludeStatement(ModType, AutoGenPackage) + AutoGenHeader += AddGuidStatement(AutoGenGuid) + AutoGenHeader += AddLibraryClassStatement(AutoGenLibClass) + + if options.manual: + saveSourceFile(AutoGenModuleFolder, "CommonHeader.txt", AutoGenHeader) + else: + + commonHeaderFilename2 = re.sub("(?=[^a-z])", "_", commonHeaderFilename) + commonHeaderFilename2 = "_" + commonHeaderFilename2.replace(".", "").upper() + "_" + briefDiscription = "Common header file shared by all source files." + detailedDiscription = "This file includes package header files, library classes and protocol, PPI & GUID definitions.\n" + AutoGenHeader += AutoGenDeclaration + AutoGenHeader = "#ifndef %s\n#define %s\n\n\n%s\n#endif\n" % (commonHeaderFilename2, commonHeaderFilename2, AutoGenHeader) + AutoGenHeader = AutoGenSourceHeaderFormat % (briefDiscription, detailedDiscription, CopyRight, License, AutoGenHeader) + saveSourceFile(AutoGenModuleFolder, commonHeaderFilename, AutoGenHeader) + SrcFilenames.append(commonHeaderFilename) + + for source in AutoGenSourceFiles: + extension = os.path.splitext(source)[1] + if extension == ".c": + sourceContents = openSourceFile(AutoGenModuleFolder, source) + sourceContents = AddCommonInclusionStatement(sourceContents, includeCommonHeaderFileStatement) + saveSourceFile(AutoGenModuleFolder, source, sourceContents) + + + if AutoGenSource != "": + briefDiscription = "Entry Point Source file." + detailedDiscription = "This file contains the user entry point \n" + AutoGenSource = AutoGenSourceHeaderFormat % (briefDiscription, detailedDiscription, CopyRight, License, AutoGenSource) + AutoGenSource = AddCommonInclusionStatement(AutoGenSource, includeCommonHeaderFileStatement) + + saveSourceFile(AutoGenModuleFolder, entryPointFilename, AutoGenSource) + SrcFilenames.append(entryPointFilename) + + + + + # DONE Getting data, now output it in INF format. + Msa.unlink() + Fdb.unlink() + Output = [] + + """ Print the converted data format """ + head = "#/** @file\n" + head += "# " + str(Abstract) + "\n#\n" + head += "# " + str(Description).strip().replace("\n", "\n# ") + "\n" + head += "# " + str(CopyRight) + "\n#\n" + head += "# " + str(License).replace("\n", "\n# ").replace(" ", " ").strip() + "\n#\n" + head += "#\n#**/\n" + + Output.append(head) + if (options.debug): + print head + +## Defines = "\n" + "#"*80+ "\n#\n" +## if (BinModule != "false"): +## Defines += "# Defines Section - statements that will be processed to generate a binary image.\n" +## else: +## Defines += "# Defines Section - statements that will be processed to create a Makefile.\n" +## Defines += "#\n" + "#"*80 + "\n" + + Defines = "\n" + Defines += "[Defines]\n" + Defines += " %-30s = %s\n" % ("INF_VERSION", "0x00010005") + Defines += " %-30s = %s\n" % ("BASE_NAME", BaseName) + Defines += " %-30s = %s\n" % ("FILE_GUID", GuidValue) + Defines += " %-30s = %s\n" % ("MODULE_TYPE", ModType) + Defines += " %-30s = %s\n" % ("VERSION_STRING", VerString) + + if (len(PcdIsDriver) > 0): + Defines += " %-30s = %s\n" % ("PCD_DRIVER", PcdIsDriver) + + if (len(IamLibrary) > 0): + lcstr = "" + for lc in IamLibrary[:]: + lcstr += lc + " " + Defines += " %-30s = %s" % ("LIBRARY_CLASS", lcstr) + Defines += "\n" + + if (len(SpecList) > 0): + for spec in SpecList[:]: + (specname, specval) = spec.split() + Defines += " %-30s = %s\n" % (specname, specval) + Defines += "\n" + + if (len(DriverModules) > 0): + for line in DriverModules[:]: + Defines += line + + if (len(LibraryModules) > 0): + for line in LibraryModules[:]: + Defines += line + + if (len(DefinesComments) > 0): + for line in DefinesComments[:]: + Defines += line + + Output.append(Defines) + + if (options.debug): + print Defines + + if (BinModule != "false"): + """ Binary Module, so sources are really binaries. """ +## Sources = "\n" + "#"*80 + "\n#\n" +## Sources += "# Binaries Section - list of binary files that are required for the build\n# to succeed.\n" +## Sources += "#\n" + "#"*80 + "\n\n" + Sources = "\n" + if ModType == "UEFI_APPLICATION": + FileType = "UEFI_APP" + if options.verbose > 0: + print "WARNING: Binary Module: %s is assuming UEFI_APPLICATION file type." % (options.filename) + else: + FileType = "FV" + if options.verbose > 0: + print "WARNING: Binary Module: %s is assuming FV file type." % (options.filename) + + if (len(SrcFilenames) > 0): + Sources += "[Binaries.common]\n" + for file in SrcFilenames[:]: + file = file.replace("\\", "/") + Sources += " " + FileType + "|" + file + "\n" + Sources += "\n" + + if (len(SrcFilenamesIa32) > 0): + Sources += "[Binaries.Ia32]\n" + for file in SrcFilenamesIa32[:]: + file = file.replace("\\", "/") + Sources += " " + FileType + "|" + file + "\n" + Sources += "\n" + + if (len(SrcFilenamesX64) > 0): + Sources += "[Binaries.X64]\n" + for file in SrcFilenamesX64[:]: + file = file.replace("\\", "/") + Sources += " " + FileType + "|" + file + "\n" + Sources += "\n" + + if (len(SrcFilenamesIpf) > 0): + Sources += "[Binaries.IPF]\n" + for file in SrcFilenamesIpf[:]: + file = file.replace("\\", "/") + Sources += " " + FileType + "|" + file + "\n" + Sources += "\n" + + if (len(SrcFilenamesEbc) > 0): + Sources += "[Binaries.EBC]\n" + for file in SrcFilenamesEbc[:]: + file = file.replace("\\", "/") + Sources += " " + FileType + "|" + file + "\n" + Sources += "\n" + + Output.append(Sources) + if (options.debug): + print Sources + else: +## Sources = "\n" + "#"*80 + "\n#\n" +## Sources += "# Sources Section - list of files that are required for the build to succeed.\n" +## Sources += "#\n" + "#"*80 + "\n\n" + Sources = "\n" + if (len(SrcFilenames) > 0): + Sources += "[Sources.common]\n" + for file in SrcFilenames[:]: + Sources += " " + file + "\n" + Sources += "\n" + + if (len(SrcFilenamesIa32) > 0): + Sources += "[Sources.Ia32]\n" + for file in SrcFilenamesIa32[:]: + Sources += " " + file + "\n" + Sources += "\n" + + if (len(SrcFilenamesX64) > 0): + Sources += "[Sources.X64]\n" + for file in SrcFilenamesX64[:]: + Sources += " " + file + "\n" + Sources += "\n" + + if (len(SrcFilenamesIpf) > 0): + Sources += "[Sources.IPF]\n" + for file in SrcFilenamesIpf[:]: + Sources += " " + file + "\n" + Sources += "\n" + + if (len(SrcFilenamesEbc) > 0): + Sources += "[Sources.EBC]\n" + for file in SrcFilenamesEbc[:]: + Sources += " " + file + "\n" + Sources += "\n" + + Output.append(Sources) + if (options.debug): + print Sources + + + includeLine = "" + if ((len(HeaderLocations) > 0) or (len(Dirs) > 0)): + allLcs = set(LibClassList + LibClassListIa32 + LibClassListX64 + LibClassListIpf + LibClassListEbc + Dirs) + Lines = [] + for line in HeaderLocations[:]: + for Lc in allLcs: + (keyword, header) = line.split("|") + if Lc in keyword: + if (options.debug): + print "FOUND", Lc, "in", keyword, "header", header + path = "$(WORKSPACE)/" + os.path.split(header)[0] + Lines.insert(0, path.strip()) + Includes = "" +## Includes = "\n" + "#"*80 + "\n#\n" +## Includes += "# Includes Section - list of Include locations that are required for\n" +## Includes += "# this module.\n" +## Includes += "#\n" + "#"*80 + "\n\n" +## Includes += "[Includes]\n" +## includeLines = [] +## includeLines = set(Lines) +## if (options.debug): +## print "There are", len(includeLines), "entries" +## for Line in includeLines: +## Includes += " " + str(Line).strip().replace("\\", "/") + "\n" + + Output.append(Includes) + if (options.debug): + print Includes + + + + if ((len(PkgList) + len(PkgListIa32) + len(PkgListX64) + len(PkgListIpf) + len(PkgListEbc)) > 0): + """ We do this if and only if we have Package Dependencies """ +## PackageDepends = "\n" + "#"*80 + "\n#\n" +## PackageDepends += "# Package Dependency Section - list of Package files that are required for\n" +## PackageDepends += "# this module.\n" +## PackageDepends += "#\n" + "#"*80 + "\n\n" + PackageDepends = "\n" + if (len(PkgList) > 0): + PackageDepends += "[Packages]\n" + for lc in PkgList[:]: + lc = lc.replace("\\", "/") + PackageDepends += " " + lc + "\n" + PackageDepends += "\n" + + if (len(PkgListIa32) > 0): + PackageDepends += "[Packages.IA32]\n" + for lc in PkgListIa32[:]: + lc = lc.replace("\\", "/") + PackageDepends += " " + lc + "\n" + PackageDepends += "\n" + + if (len(PkgListX64) > 0): + PackageDepends += "[Packages.X64]\n" + for lc in PkgListX64[:]: + lc = lc.replace("\\", "/") + PackageDepends += " " + lc + "\n" + PackageDepends += "\n" + + if (len(PkgListIpf) > 0): + PackageDepends += "[Packages.IPF]\n" + for lc in PkgListIpf[:]: + lc = lc.replace("\\", "/") + PackageDepends += " " + lc + "\n" + PackageDepends += "\n" + + if (len(PkgListEbc) > 0): + PackageDepends += "[Packages.EBC]\n" + for lc in PkgListEbc[:]: + lc = lc.replace("\\", "/") + PackageDepends += " " + lc + "\n" + PackageDepends += "\n" + + Output.append(PackageDepends) + if (options.debug): + print PackageDepends + + if ((len(LibClassList) + len(LibClassListIa32) + len(LibClassListX64) + len(LibClassListIpf) + len(LibClassListEbc)) > 0): +## LibraryClasses = "\n" + "#"*80 + "\n#\n" +## LibraryClasses += "# Library Class Section - list of Library Classes that are required for\n" +## LibraryClasses += "# this module.\n" +## LibraryClasses += "#\n" + "#"*80 + "\n\n" + + LibraryClasses = "\n" + if (len(LibClassList) > 0): + LibraryClasses += "[LibraryClasses]\n" + for lc in LibClassList[:]: + LibraryClasses += " " + lc + "\n" + LibraryClasses += "\n" + + if (len(LibClassListIa32) > 0): + LibraryClasses += "[LibraryClasses.IA32]\n" + for lc in LibClassListIa32[:]: + LibraryClasses += " " + lc + "\n" + LibraryClasses += "\n" + + if (len(LibClassListX64) > 0): + LibraryClasses += "[LibraryClasses.X64]\n" + for lc in LibClassListX64[:]: + LibraryClasses += " " + lc + "\n" + LibraryClasses += "\n" + + if (len(LibClassListIpf) > 0): + LibraryClasses += "[LibraryClasses.IPF]\n" + for lc in LibClassListIpf[:]: + LibraryClasses += " " + lc + "\n" + LibraryClasses += "\n" + + if (len(LibClassListEbc) > 0): + LibraryClasses += "[LibraryClasses.EBC]\n" + for lc in LibClassListEbc[:]: + LibraryClasses += " " + lc + "\n" + LibraryClasses += "\n" + + Output.append(LibraryClasses) + if (options.debug): + print LibraryClasses + + # Print the Guids sections + if (len(GuidCName) + len(GuidCNameIa32) + len(GuidCNameIPF) + len(GuidCNameX64) + len(GuidCNameEBC)) > 0: +## GuidSection = "\n" + "#"*80 + "\n#\n" +## GuidSection += "# Guid C Name Section - list of Guids that this module uses or produces.\n" +## GuidSection += "#\n" + "#"*80 + "\n\n" + GuidSection = "\n" + if (len(GuidCName) > 0): + GuidSection += "[Guids]\n" + for Guid in GuidCName[:]: + GuidSection += Guid + "\n" + GuidSection += "\n" + + if (len(GuidCNameIa32) > 0): + GuidSection += "[Guids.IA32]\n" + for Guid in GuidCNameIa32[:]: + GuidSection += Guid + "\n" + GuidSection += "\n" + + if (len(GuidCNameX64) > 0): + GuidSection += "[Guids.X64]\n" + for Guid in GuidCNameX64[:]: + GuidSection += Guid + "\n" + GuidSection += "\n" + + if (len(GuidCNameIPF) > 0): + GuidSection += "[Guids.IPF]\n" + for Guid in GuidCNameIPF[:]: + GuidSection += Guid + "\n" + GuidSection += "\n" + + if (len(GuidCNameEBC) > 0): + GuidSection += "[Guids.EBC]\n" + for Guid in GuidCNameEBC[:]: + GuidSection += Guid + "\n" + GuidSection += "\n" + + Output.append(GuidSection) + if (options.debug and options.verbose > 1): + print GuidSection + + # Print the Protocol sections + if (len(ProtocolCName) + len(ProtocolCNameIa32) + len(ProtocolCNameIPF) + len(ProtocolCNameX64) + len(ProtocolCNameEBC)) > 0: +## ProtocolsSection = "\n" + "#"*80 + "\n#\n" +## ProtocolsSection += "# Protocol C Name Section - list of Protocol and Protocol Notify C Names\n" +## ProtocolsSection += "# that this module uses or produces.\n" +## ProtocolsSection += "#\n" + "#"*80 + "\n\n" + + ProtocolsSection = "\n" + if (len(ProtocolCName) > 0): + ProtocolsSection += "[Protocols]\n" + for Guid in ProtocolCName[:]: + ProtocolsSection += Guid + "\n" + ProtocolsSection += "\n" + + if (len(ProtocolCNameIa32) > 0): + ProtocolsSection += "[Protocols.IA32]\n" + for Guid in ProtocolCNameIa32[:]: + ProtocolsSection += Guid + "\n" + ProtocolsSection += "\n" + + if (len(ProtocolCNameX64) > 0): + ProtocolsSection += "[Protocols.X64]\n" + for Guid in ProtocolCNameX64[:]: + ProtocolsSection += Guid + "\n" + ProtocolsSection += "\n" + + if (len(ProtocolCNameIPF) > 0): + ProtocolsSection += "[Protocols.IPF]\n" + for Guid in ProtocolCNameIPF[:]: + ProtocolsSection += Guid + "\n" + ProtocolsSection += "\n" + + if (len(ProtocolCNameEBC) > 0): + ProtocolsSection += "[Protocols.EBC]\n" + for Guid in ProtocolCNameEBC[:]: + ProtocolsSection += Guid + "\n" + ProtocolsSection += "\n" + + Output.append(ProtocolsSection) + if (options.debug): + print ProtocolsSection + + # Print the PPI sections + if (len(PpiCName) + len(PpiCNameIa32) + len(PpiCNameIPF) + len(PpiCNameX64) + len(PpiCNameEBC)) > 0: +## PpiSection = "\n" + "#"*80 + "\n#\n" +## PpiSection += "# PPI C Name Section - list of PPI and PPI Notify C Names that this module\n" +## PpiSection += "# uses or produces.\n" +## PpiSection += "#\n" + "#"*80 + "\n\n" + + PpiSection = "\n" + if (len(PpiCName) > 0): + PpiSection += "[Ppis]\n" + for Guid in PpiCName[:]: + PpiSection += Guid + "\n" + PpiSection += "\n" + + if (len(PpiCNameIa32) > 0): + PpiSection += "[Ppis.IA32]\n" + for Guid in PpiCNameIa32[:]: + PpiSection += Guid + "\n" + PpiSection += "\n" + + if (len(PpiCNameX64) > 0): + PpiSection += "[Ppis.X64]\n" + for Guid in PpiCNameX64[:]: + PpiSection += Guid + "\n" + PpiSection += "\n" + + if (len(PpiCNameIPF) > 0): + PpiSection += "[Ppis.IPF]\n" + for Guid in PpiCNameIPF[:]: + PpiSection += Guid + "\n" + PpiSection += "\n" + + if (len(PpiCNameEBC) > 0): + PpiSection += "[Ppis.EBC]\n" + for Guid in PpiCNameEBC[:]: + PpiSection += Guid + "\n" + PpiSection += "\n" + + Output.append(PpiSection) + if (options.debug): + print PpiSection + + # Print the PCD sections + if ((len(PcdFF)+len(PcdFFIa32)+len(PcdFFX64)+len(PcdFFIpf)+len(PcdFFEbc)) > 0): +## FeatureFlagSection = "\n" + "#"*80 + "\n#\n" +## FeatureFlagSection += "# Pcd FEATURE_FLAG - list of PCDs that this module is coded for.\n" +## FeatureFlagSection += "#\n" + "#"*80 + "\n\n" + + FeatureFlagSection = "\n" + if (len(PcdFF) > 0): + FeatureFlagSection += "[FeaturePcd.common]\n" + for Entry in PcdFF[:]: + FeatureFlagSection += " " + Entry + "\n" + FeatureFlagSection += "\n" + if (len(PcdFFIa32) > 0): + FeatureFlagSection += "[FeaturePcd.IA32]\n" + for Entry in PcdFFIa32[:]: + FeatureFlagSection += " " + Entry + "\n" + FeatureFlagSection += "\n" + if (len(PcdFFX64) > 0): + FeatureFlagSection += "[FeaturePcd.X64]\n" + for Entry in PcdFFX64[:]: + FeatureFlagSection += " " + Entry + "\n" + FeatureFlagSection += "\n" + if (len(PcdFFIpf) > 0): + FeatureFlagSection += "[PcdsFeatureFlag.IPF]\n" + for Entry in PcdFFIpf[:]: + FeatureFlagSection += " " + Entry + "\n" + FeatureFlagSection += "\n" + if (len(PcdFFEbc) > 0): + FeatureFlagSection += "[FeaturePcd.EBC]\n" + for Entry in PcdFFEbc[:]: + FeatureFlagSection += " " + Entry + "\n" + FeatureFlagSection += "\n" + + Output.append(FeatureFlagSection) + if (options.debug): + print FeatureFlagSection + + if ((len(PcdFAB)+len(PcdFABIa32)+len(PcdFABX64)+len(PcdFABIpf)+len(PcdFABEbc)) > 0): +## FixedAtBuildSection = "\n" + "#"*80 + "\n#\n" +## FixedAtBuildSection += "# Pcd FIXED_AT_BUILD - list of PCDs that this module is coded for.\n" +## FixedAtBuildSection += "#\n" + "#"*80 + "\n\n" + + FixedAtBuildSection = "\n" + if (len(PcdFAB) > 0): + FixedAtBuildSection += "[FixedPcd.common]\n" + for Entry in PcdFAB[:]: + FixedAtBuildSection += " " + Entry + "\n" + FixedAtBuildSection += "\n" + if (len(PcdFABIa32) > 0): + FixedAtBuildSection += "[FixedPcd.IA32]\n" + for Entry in PcdFABIa32[:]: + FixedAtBuildSection += " " + Entry + "\n" + FixedAtBuildSection += "\n" + if (len(PcdFABX64) > 0): + FixedAtBuildSection += "[FixedPcd.X64]\n" + for Entry in PcdFABX64[:]: + FixedAtBuildSection += " " + Entry + "\n" + FixedAtBuildSection += "\n" + if (len(PcdFABIpf) > 0): + FixedAtBuildSection += "[FixedPcd.IPF]\n" + for Entry in PcdFABIpf[:]: + FixedAtBuildSection += " " + Entry + "\n" + FixedAtBuildSection += "\n" + if (len(PcdFABEbc) > 0): + FixedAtBuildSection += "[FixedPcd.EBC]\n" + for Entry in PcdFABEbc[:]: + FixedAtBuildSection += " " + Entry + "\n" + FixedAtBuildSection += "\n" + + Output.append(FixedAtBuildSection) + if (options.debug): + print FixedAtBuildSection + + if ((len(PcdPIM)+len(PcdPIMIa32)+len(PcdPIMX64)+len(PcdPIMIpf)+len(PcdPIMEbc)) > 0): +## PatchableInModuleSection = "\n" + "#"*80 + "\n#\n" +## PatchableInModuleSection += "# Pcd PATCHABLE_IN_MODULE - list of PCDs that this module is coded for.\n" +## PatchableInModuleSection += "#\n" + "#"*80 + "\n\n" + + PatchableInModuleSection = "\n" + if (len(PcdPIM) > 0): + PatchableInModuleSection += "[PatchPcd.common]\n" + for Entry in PcdPIM[:]: + PatchableInModuleSection += " " + Entry + "\n" + PatchableInModuleSection += "\n" + if (len(PcdPIMIa32) > 0): + PatchableInModuleSection += "[PatchPcd.IA32]\n" + for Entry in PcdPIMIa32[:]: + PatchableInModuleSection += " " + Entry + "\n" + PatchableInModuleSection += "\n" + if (len(PcdPIMX64) > 0): + PatchableInModuleSection += "[PatchPcd.X64]\n" + for Entry in PcdPIMX64[:]: + PatchableInModuleSection += " " + Entry + "\n" + PatchableInModuleSection += "\n" + if (len(PcdPIMIpf) > 0): + PatchableInModuleSection += "[PatchPcd.IPF]\n" + for Entry in PcdPIMIpf[:]: + PatchableInModuleSection += " " + Entry + "\n" + PatchableInModuleSection += "\n" + if (len(PcdPIMEbc) > 0): + PatchableInModuleSection += "[PatchPcd.EBC]\n" + for Entry in PcdPIMEbc[:]: + PatchableInModuleSection += " " + Entry + "\n" + PatchableInModuleSection += "\n" + + Output.append(PatchableInModuleSection) + if (options.debug): + print PatchableInModuleSection + + if ((len(PcdDYE)+len(PcdDYEIa32)+len(PcdDYEX64)+len(PcdDYEIpf)+len(PcdDYEEbc)) > 0): +## DynamicExSection = "\n" + "#"*80 + "\n#\n" +## DynamicExSection += "# Pcd DYNAMIC_EX - list of PCDs that this module is coded for.\n" +## DynamicExSection += "#\n" + "#"*80 + "\n\n" + + DynamicExSection = "\n" + if (len(PcdDYE) > 0): + DynamicExSection += "[PcdEx.common]\n" + for Entry in PcdDYE[:]: + DynamicExSection += " " + Entry + "\n" + DynamicExSection += "\n" + if (len(PcdDYEIa32) > 0): + DynamicExSection += "[PcdEx.IA32]\n" + for Entry in PcdDYEIa32[:]: + DynamicExSection += " " + Entry + "\n" + DynamicExSection += "\n" + if (len(PcdDYEX64) > 0): + DynamicExSection += "[PcdEx.X64]\n" + for Entry in PcdDYEX64[:]: + DynamicExSection += " " + Entry + "\n" + DynamicExSection += "\n" + if (len(PcdDYEIpf) > 0): + DynamicExSection += "[PcdEx.IPF]\n" + for Entry in PcdDYEIpf[:]: + DynamicExSection += " " + Entry + "\n" + DynamicExSection += "\n" + if (len(PcdDYEEbc) > 0): + DynamicExSection += "[PcdEx.EBC]\n" + for Entry in PcdDYEEbc[:]: + DynamicExSection += " " + Entry + "\n" + DynamicExSection += "\n" + + Output.append(DynamicExSection) + if (options.debug): + print DynamicExSection + + if ((len(PcdDY)+len(PcdDYIa32)+len(PcdDYX64)+len(PcdDYIpf)+len(PcdDYEbc)) > 0): +## DynamicSection = "\n" + "#"*80 + "\n#\n" +## DynamicSection += "# Pcd DYNAMIC - list of PCDs that this module is coded for.\n" +## DynamicSection += "#\n" + "#"*80 + "\n\n" + + DynamicSection = "\n" + if (len(PcdDY) > 0): + DynamicSection += "[Pcd.common]\n" + for Entry in PcdDY[:]: + DynamicSection += " " + Entry + "\n" + DynamicSection += "\n" + if (len(PcdDYIa32) > 0): + DynamicSection += "[Pcd.IA32]\n" + for Entry in PcdDYIa32[:]: + DynamicSection += " " + Entry + "\n" + DynamicSection += "\n" + if (len(PcdDYX64) > 0): + DynamicSection += "[Pcd.X64]\n" + for Entry in PcdDYX64[:]: + DynamicSection += " " + Entry + "\n" + DynamicSection += "\n" + if (len(PcdDYIpf) > 0): + DynamicSection += "[Pcd.IPF]\n" + for Entry in PcdDYIpf[:]: + DynamicSection += " " + Entry + "\n" + DynamicSection += "\n" + if (len(PcdDYEbc) > 0): + DynamicSection += "[Pcd.EBC]\n" + for Entry in PcdDYEbc[:]: + DynamicSection += " " + Entry + "\n" + DynamicSection += "\n" + + Output.append(DynamicSection) + if (options.debug): + print DynamicSection + + if ((len(Depex) + len(DepexIa32) + len(DepexX64) + len(DepexIpf) + len(DepexEbc)) > 0): + """ We do this if and only if we have Package Dependencies """ +## Dpx = "\n" + "#"*80 + "\n#\n" +## Dpx += "# Dependency Expression Section - list of Dependency expressions that are required for\n" +## Dpx += "# this module.\n" +## Dpx += "#\n" + "#"*80 + "\n\n" + Dpx = "\n" + if (len(Depex) > 0): + Dpx += "[Depex]\n" + for lc in Depex[:]: + Dpx += " " + lc + "\n" + Dpx += "\n" + + if (len(DepexIa32) > 0): + Dpx += "[Depex.IA32]\n" + for lc in DepexIa32[:]: + Dpx += " " + lc + "\n" + Dpx += "\n" + + if (len(DepexX64) > 0): + Dpx += "[Depex.X64]\n" + for lc in DepexX64[:]: + Dpx += " " + lc + "\n" + Dpx += "\n" + + if (len(DepexIpf) > 0): + Dpx += "[Depex.IPF]\n" + for lc in DepexIpf[:]: + Dpx += " " + lc + "\n" + Dpx += "\n" + + if (len(DepexEbc) > 0): + Dpx += "[Depex.EBC]\n" + for lc in DepexEbc[:]: + Dpx += " " + lc + "\n" + Dpx += "\n" + + Output.append(Dpx) + if (options.debug): + print Dpx + + if (len(MBOlines) > 0): + BuildSection = "" +## BuildSection = "\n" + "#"*80 + "\n#\n" +## BuildSection += "# Build Options - list of custom build options for this module.\n" +## BuildSection += "#\n" + "#"*80 + "\n\n" + BuildSection += "\n[BuildOptions]\n" + for mbo in MBOlines: + tool, targs = mbo.split("=",2) + BuildSection += " %-40s = %s\n" % (tool.strip(), targs.strip()) + + Output.append(BuildSection) + if (options.debug): + print BuildSection + + + if (len(UEList) > 0): + UserExtensionSection = "" + for UE in UEList[:]: + UserExtensionSection += "[UserExtensions." + UE[0] + '."' + UE[1] + '"]\n' + if (len(UE[2]) > 0): + UserExtensionSection += '"' + UE[2] + '"\n' + else: + UserExtensionSection += "\n" + + Output.append(UserExtensionSection) + if (options.debug): + print UserExtensionSection + + print "write file", outputFile + if (options.autowrite): + fo = open(outputFile, "w") + for Section in Output[:]: + fo.writelines(Section) + if (options.verbose > 1): + print Section + fo.close() + elif (options.outfile): + fo = open(outputFile, "w") + for Section in Output[:]: + fo.writelines(Section) + fo.close() + else: + for Section in Output[:]: + print Section + + +if __name__ == '__main__': + + global options + global args + options,args = myOptionParser() + + main() + sys.exit(0) + diff --git a/BaseTools/Source/Python/MigrationMsa2Inf/__init__.py b/BaseTools/Source/Python/MigrationMsa2Inf/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/BaseTools/Source/Python/MkBOM/__init__.py b/BaseTools/Source/Python/MkBOM/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/BaseTools/Source/Python/PackagingTool/DependencyRules.py b/BaseTools/Source/Python/PackagingTool/DependencyRules.py new file mode 100644 index 0000000000..402694054e --- /dev/null +++ b/BaseTools/Source/Python/PackagingTool/DependencyRules.py @@ -0,0 +1,185 @@ +## @file +# This file is for installed package information database operations +# +# Copyright (c) 2007 ~ 2008, 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. +# + +## +# Import Modules +# +import sqlite3 +import os + +import Common.EdkLogger as EdkLogger +import IpiDb + +(DEPEX_CHECK_SUCCESS, DEPEX_CHECK_MODULE_NOT_FOUND, \ +DEPEX_CHECK_PACKAGE_NOT_FOUND, DEPEX_CHECK_DP_NOT_FOUND) = (0, 1, 2, 3) + +## IpiDb +# +# This class represents the installed package information databse +# Add/Remove/Get installed distribution package information here. +# +# +# @param object: Inherited from object class +# @param DbPath: A string for the path of the database +# +# @var Conn: Connection of the database +# @var Cur: Cursor of the connection +# +class DependencyRules(object): + def __init__(self, Db): + self.IpiDb = Db + + ## Check whether a module exists in current workspace. + # + # @param Guid: + # @param Version: + # + def CheckModuleExists(self, Guid, Version, ReturnCode = DEPEX_CHECK_SUCCESS): + EdkLogger.verbose("\nCheck module exists in workspace started ...") + ModuleList = [] + ModuleList = self.IpiDb.GetModInPackage(Guid, Version) + ModuleList.extend(self.IpiDb.GetStandaloneModule(Guid, Version)) + EdkLogger.verbose("Check module exists in workspace ... DONE!") + if len(ModuleList) > 0: + return True + else: + ReturnCode = DEPEX_CHECK_MODULE_NOT_FOUND + return False + + + ## Check whether a module depex satified by current workspace. + # + # @param ModuleObj: + # @param DpObj: + # + def CheckModuleDepexSatisfied(self, ModuleObj, DpObj = None, ReturnCode = DEPEX_CHECK_SUCCESS): + EdkLogger.verbose("\nCheck module depex met by workspace started ...") + for Dep in ModuleObj.PackageDependencies: + Exist = self.CheckPackageExists(Dep.PackageGuid, Dep.PackageVersion, ReturnCode) + if not Exist: + if DpObj == None: + ReturnCode = DEPEX_CHECK_PACKAGE_NOT_FOUND + return False + for GuidVerPair in DpObj.PackageSurfaceArea.keys(): + if Dep.PackageGuid == GuidVerPair[0]: + if Dep.PackageVersion == None or len(Dep.PackageVersion) == 0: + break + if Dep.PackageVersion == GuidVerPair[1]: + break + else: + ReturnCode = DEPEX_CHECK_PACKAGE_NOT_FOUND + return False + else: + ReturnCode = DEPEX_CHECK_PACKAGE_NOT_FOUND + return False + return True + + EdkLogger.verbose("Check module depex met by workspace ... DONE!") + + ## Check whether a package exists in current workspace. + # + # @param Guid: + # @param Version: + # + def CheckPackageExists(self, Guid, Version, ReturnCode = DEPEX_CHECK_SUCCESS): + EdkLogger.verbose("\nCheck package exists in workspace started ...") + PkgList = [] + PkgList = self.IpiDb.GetPackage(Guid, Version) + if len(PkgList) > 0: + return True + else: + ReturnCode = DEPEX_CHECK_PACKAGE_NOT_FOUND + return False + + EdkLogger.verbose("Check package exists in workspace ... DONE!") + + ## Check whether a package depex satified by current workspace. + # + # @param ModuleObj: + # @param DpObj: + # + def CheckPackageDepexSatisfied(self, PkgObj, DpObj = None, ReturnCode = DEPEX_CHECK_SUCCESS): + + for ModKey in PkgObj.Modules.keys(): + ModObj = PkgObj.Modules[ModKey] + if self.CheckModuleDepexSatisfied(ModObj, DpObj, ReturnCode): + continue + else: + return False + return True + + ## Check whether a DP exists in current workspace. + # + # @param Guid: + # @param Version: + # + def CheckDpExists(self, Guid, Version, ReturnCode = DEPEX_CHECK_SUCCESS): + EdkLogger.verbose("\nCheck DP exists in workspace started ...") + DpList = [] + DpList = self.IpiDb.GetDp(Guid, Version) + if len(DpList) > 0: + return True + else: + ReturnCode = DEPEX_CHECK_DP_NOT_FOUND + return False + + EdkLogger.verbose("Check DP exists in workspace ... DONE!") + + ## Check whether a DP depex satified by current workspace. + # + # @param ModuleObj: + # @param DpObj: + # + def CheckDpDepexSatisfied(self, DpObj, ReturnCode = DEPEX_CHECK_SUCCESS): + + for PkgKey in DpObj.PackageSurfaceArea.keys(): + PkgObj = DpObj.PackageSurfaceArea[PkgKey] + if self.CheckPackageDepexSatisfied(PkgObj, DpObj, ReturnCode): + continue + else: + return False + + for ModKey in DpObj.ModuleSurfaceArea.keys(): + ModObj = PkgObj.ModuleSurfaceArea[ModKey] + if self.CheckModuleDepexSatisfied(ModObj, DpObj, ReturnCode): + continue + else: + return False + + return True + + ## Check whether a DP depex satified by current workspace. + # + # @param ModuleObj: + # @param DpObj: + # + def CheckDpDepexForRemove(self, DpGuid, DpVersion, ReturnCode = DEPEX_CHECK_SUCCESS): + + # Get mod list that is dependent on pkg installed from this DP. + ModList = self.IpiDb.GetDpDependentModuleList(DpGuid, DpVersion) + + if len(ModList) > 0: + return False + + return True +## +# +# This acts like the main() function for the script, unless it is 'import'ed into another +# script. +# +if __name__ == '__main__': + EdkLogger.Initialize() + EdkLogger.SetLevel(EdkLogger.DEBUG_0) + + + \ No newline at end of file diff --git a/BaseTools/Source/Python/PackagingTool/InstallPkg.py b/BaseTools/Source/Python/PackagingTool/InstallPkg.py new file mode 100644 index 0000000000..963a654ea1 --- /dev/null +++ b/BaseTools/Source/Python/PackagingTool/InstallPkg.py @@ -0,0 +1,309 @@ +## @file +# Install distribution package. +# +# Copyright (c) 2007, 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. +# + +## +# Import Modules +# +import os +import sys +import glob +import shutil +import traceback +import platform +from optparse import OptionParser + +import Common.EdkLogger as EdkLogger +from Common.BuildToolError import * +from Common.Misc import * +from Common.XmlParser import * +from Common.InfClassObjectLight import Inf +from Common.DecClassObjectLight import Dec + +from PackageFile import * +from IpiDb import * +from DependencyRules import * +import md5 + +# Version and Copyright +VersionNumber = "0.1" +__version__ = "%prog Version " + VersionNumber +__copyright__ = "Copyright (c) 2008, Intel Corporation All rights reserved." + +## Check environment variables +# +# Check environment variables that must be set for build. Currently they are +# +# WORKSPACE The directory all packages/platforms start from +# EDK_TOOLS_PATH The directory contains all tools needed by the build +# PATH $(EDK_TOOLS_PATH)/Bin/ must be set in PATH +# +# If any of above environment variable is not set or has error, the build +# will be broken. +# +def CheckEnvVariable(): + # check WORKSPACE + if "WORKSPACE" not in os.environ: + EdkLogger.error("InstallPkg", ATTRIBUTE_NOT_AVAILABLE, "Environment variable not found", + ExtraData="WORKSPACE") + + WorkspaceDir = os.path.normpath(os.environ["WORKSPACE"]) + if not os.path.exists(WorkspaceDir): + EdkLogger.error("InstallPkg", FILE_NOT_FOUND, "WORKSPACE doesn't exist", ExtraData="%s" % WorkspaceDir) + elif ' ' in WorkspaceDir: + EdkLogger.error("InstallPkg", FORMAT_NOT_SUPPORTED, "No space is allowed in WORKSPACE path", + ExtraData=WorkspaceDir) + os.environ["WORKSPACE"] = WorkspaceDir + +## Parse command line options +# +# Using standard Python module optparse to parse command line option of this tool. +# +# @retval Opt A optparse.Values object containing the parsed options +# @retval Args Target of build command +# +def MyOptionParser(): + UsageString = "%prog -i [-t] [-f] [-q | -v] [-h]" + + Parser = OptionParser(description=__copyright__,version=__version__,prog="InstallPkg",usage=UsageString) + + Parser.add_option("-?", action="help", help="show this help message and exit") + + Parser.add_option("-i", "--distribution-package", action="store", type="string", dest="PackageFile", + help="The distribution package to be installed") + + Parser.add_option("-t", "--install-tools", action="store_true", type=None, dest="Tools", + help="Specify it to install tools or ignore the tools of the distribution package.") + + Parser.add_option("-f", "--misc-files", action="store_true", type=None, dest="MiscFiles", + help="Specify it to install misc file or ignore the misc files of the distribution package.") + + Parser.add_option("-q", "--quiet", action="store_const", dest="LogLevel", const=EdkLogger.QUIET, + help="Disable all messages except FATAL ERRORS.") + + Parser.add_option("-v", "--verbose", action="store_const", dest="LogLevel", const=EdkLogger.VERBOSE, + help="Turn on verbose output") + + Parser.add_option("-d", "--debug", action="store", type="int", dest="LogLevel", + help="Enable debug messages at specified level.") + + Parser.set_defaults(LogLevel=EdkLogger.INFO) + + (Opt, Args)=Parser.parse_args() + + return Opt + +def InstallNewPackage(WorkspaceDir, Path): + FullPath = os.path.normpath(os.path.join(WorkspaceDir, Path)) + if os.path.exists(FullPath): + print "Directory [%s] already exists, please select another location, press [Enter] with no input to quit:" %Path + Input = sys.stdin.readline() + Input = Input.replace('\r', '').replace('\n', '') + if Input == '': + EdkLogger.error("InstallPkg", UNKNOWN_ERROR, "User interrupt") + Input = Input.replace('\r', '').replace('\n', '') + return InstallNewPackage(WorkspaceDir, Input) + else: + return Path + +def InstallNewFile(WorkspaceDir, File): + FullPath = os.path.normpath(os.path.join(WorkspaceDir, File)) + if os.path.exists(FullPath): + print "File [%s] already exists, please select another path, press [Enter] with no input to quit:" %File + Input = sys.stdin.readline() + Input = Input.replace('\r', '').replace('\n', '') + if Input == '': + EdkLogger.error("InstallPkg", UNKNOWN_ERROR, "User interrupt") + Input = Input.replace('\r', '').replace('\n', '') + return InstallNewFile(WorkspaceDir, Input) + else: + return File + +## Tool entrance method +# +# This method mainly dispatch specific methods per the command line options. +# If no error found, return zero value so the caller of this tool can know +# if it's executed successfully or not. +# +# @retval 0 Tool was successful +# @retval 1 Tool failed +# +def Main(): + EdkLogger.Initialize() + Options = None + DistFileName = 'dist.pkg' + ContentFileName = 'content.zip' + DistFile, ContentZipFile, UnpackDir = None, None, None + + Options = MyOptionParser() + try: + if Options.LogLevel < EdkLogger.DEBUG_9: + EdkLogger.SetLevel(Options.LogLevel + 1) + else: + EdkLogger.SetLevel(Options.LogLevel) + + CheckEnvVariable() + WorkspaceDir = os.environ["WORKSPACE"] + if not Options.PackageFile: + EdkLogger.error("InstallPkg", OPTION_NOT_SUPPORTED, ExtraData="Must specify one distribution package") + + # unzip dist.pkg file + EdkLogger.quiet("Unzipping and parsing distribution package XML file ... ") + DistFile = PackageFile(Options.PackageFile) + UnpackDir = os.path.normpath(os.path.join(WorkspaceDir, ".tmp")) + DistPkgFile = DistFile.UnpackFile(DistFileName, os.path.normpath(os.path.join(UnpackDir, DistFileName))) + if not DistPkgFile: + EdkLogger.error("InstallPkg", FILE_NOT_FOUND, "File [%s] is broken in distribution package" %DistFileName) + + # Generate distpkg + DistPkgObj = DistributionPackageXml() + DistPkg = DistPkgObj.FromXml(DistPkgFile) + + # prepare check dependency + Db = IpiDatabase(os.path.normpath(os.path.join(WorkspaceDir, "Conf/DistributionPackageDatabase.db"))) + Db.InitDatabase() + Dep = DependencyRules(Db) + + # Check distribution package exist + if Dep.CheckDpExists(DistPkg.Header.Guid, DistPkg.Header.Version): + EdkLogger.error("InstallPkg", UNKNOWN_ERROR, "This distribution package has been installed", ExtraData=DistPkg.Header.Name) + + # unzip contents.zip file + ContentFile = DistFile.UnpackFile(ContentFileName, os.path.normpath(os.path.join(UnpackDir, ContentFileName))) + ContentZipFile = PackageFile(ContentFile) + if not ContentFile: + EdkLogger.error("InstallPkg", FILE_NOT_FOUND, "File [%s] is broken in distribution package" %ContentFileName) + + # verify MD5 signature + Md5Sigature = md5.new(open(ContentFile).read()) + if DistPkg.Header.Signature != Md5Sigature.hexdigest(): + EdkLogger.error("InstallPkg", FILE_CHECKSUM_FAILURE, ExtraData=ContentFile) + + # Check package exist and install + for Guid,Version,Path in DistPkg.PackageSurfaceArea: + PackagePath = os.path.dirname(Path) + NewPackagePath = PackagePath + Package = DistPkg.PackageSurfaceArea[Guid,Version,Path] + EdkLogger.info("Installing package ... %s" % Package.PackageHeader.Name) + if Dep.CheckPackageExists(Guid, Version): + EdkLogger.quiet("Package [%s] has been installed" %Path) + NewPackagePath = InstallNewPackage(WorkspaceDir, PackagePath) + Package.FileList = [] + for Item in Package.MiscFiles.Files: + FromFile = os.path.join(PackagePath, Item.Filename) + ToFile = os.path.normpath(os.path.join(WorkspaceDir, NewPackagePath, Item.Filename)) + ContentZipFile.UnpackFile(FromFile, ToFile) + Package.FileList.append(ToFile) + + # Update package + Package.PackageHeader.CombinePath = Package.PackageHeader.CombinePath.replace(PackagePath, NewPackagePath, 1) + # Update modules of package + Module = None + for ModuleGuid, ModuleVersion, ModulePath in Package.Modules: + Module = Package.Modules[ModuleGuid, ModuleVersion, ModulePath] + NewModulePath = ModulePath.replace(PackagePath, NewPackagePath, 1) + del Package.Modules[ModuleGuid, ModuleVersion, ModulePath] + Package.Modules[ModuleGuid, ModuleVersion, NewModulePath] = Module + del DistPkg.PackageSurfaceArea[Guid,Version,Path] + DistPkg.PackageSurfaceArea[Guid,Version,Package.PackageHeader.CombinePath] = Package + +# SaveFileOnChange(os.path.join(Options.InstallDir, ModulePath, Module.Header.Name, ".inf"), Inf.ModuleToInf(Module), False) +# EdkLogger.info("Installing package ... %s" % Package.Header.Name) +# shutil.copytree(os.path.join(ContentFileDir, Path), Options.InstallDir) +# SaveFileOnChange(os.path.join(Options.InstallDir, Path, Package.Header.Name, ".dec"), Dec.PackageToDec(Package), False) + + # Check module exist and install + Module = None + for Guid,Version,Path in DistPkg.ModuleSurfaceArea: + ModulePath = os.path.dirname(Path) + NewModulePath = ModulePath + Module = DistPkg.ModuleSurfaceArea[Guid,Version,Path] + EdkLogger.info("Installing module ... %s" % Module.ModuleHeader.Name) + if Dep.CheckModuleExists(Guid, Version): + EdkLogger.quiet("Module [%s] has been installed" %Path) + NewModulePath = InstallNewPackage(WorkspaceDir, ModulePath) + Module.FileList = [] + for Item in Module.MiscFiles.Files: + ModulePath = ModulePath[os.path.normpath(ModulePath).rfind(os.path.normpath('/'))+1:] + FromFile = os.path.join(ModulePath, Item.Filename) + ToFile = os.path.normpath(os.path.join(WorkspaceDir, NewModulePath, Item.Filename)) + ContentZipFile.UnpackFile(FromFile, ToFile) + Module.FileList.append(ToFile) + +# EdkLogger.info("Installing module ... %s" % Module.Header.Name) +# shutil.copytree(os.path.join(ContentFileDir, Path), Options.InstallDir) +# SaveFileOnChange(os.path.join(Options.InstallDir, Path, Module.Header.Name, ".inf"), Inf.ModuleToInf(Module), False) + + # Update module + Module.ModuleHeader.CombinePath = Module.ModuleHeader.CombinePath.replace(os.path.dirname(Path), NewModulePath, 1) + del DistPkg.ModuleSurfaceArea[Guid,Version,Path] + DistPkg.ModuleSurfaceArea[Guid,Version,Module.ModuleHeader.CombinePath] = Module +# +# +# for Guid,Version,Path in DistPkg.PackageSurfaceArea: +# print Guid,Version,Path +# for item in DistPkg.PackageSurfaceArea[Guid,Version,Path].FileList: +# print item +# for Guid,Version,Path in DistPkg.ModuleSurfaceArea: +# print Guid,Version,Path +# for item in DistPkg.ModuleSurfaceArea[Guid,Version,Path].FileList: +# print item + + if Options.Tools: + EdkLogger.info("Installing tools ... ") + for File in DistPkg.Tools.Files: + FromFile = File.Filename + ToFile = InstallNewFile(WorkspaceDir, FromFile) + ContentZipFile.UnpackFile(FromFile, ToFile) + if Options.MiscFiles: + EdkLogger.info("Installing misc files ... ") + for File in DistPkg.MiscellaneousFiles.Files: + FromFile = File.Filename + ToFile = InstallNewFile(WorkspaceDir, FromFile) + ContentZipFile.UnpackFile(FromFile, ToFile) + + # update database + EdkLogger.quiet("Update Distribution Package Database ...") + Db.AddDPObject(DistPkg) + + except FatalError, X: + if Options and Options.LogLevel < EdkLogger.DEBUG_9: + EdkLogger.quiet("(Python %s on %s) " % (platform.python_version(), sys.platform) + traceback.format_exc()) + ReturnCode = X.args[0] + except KeyboardInterrupt: + ReturnCode = ABORT_ERROR + if Options and Options.LogLevel < EdkLogger.DEBUG_9: + EdkLogger.quiet("(Python %s on %s) " % (platform.python_version(), sys.platform) + traceback.format_exc()) + except: + EdkLogger.error( + "\nInstallPkg", + CODE_ERROR, + "Unknown fatal error when installing [%s]" % Options.PackageFile, + ExtraData="\n(Please send email to dev@buildtools.tianocore.org for help, attaching following call stack trace!)\n", + RaiseError=False + ) + EdkLogger.quiet("(Python %s on %s) " % (platform.python_version(), sys.platform) + traceback.format_exc()) + ReturnCode = CODE_ERROR + finally: + EdkLogger.quiet("Removing temp files ... ") + if DistFile: + DistFile.Close() + if ContentZipFile: + ContentZipFile.Close() + if UnpackDir: + shutil.rmtree(UnpackDir) + + EdkLogger.quiet("DONE") + Progressor.Abort() + +if __name__ == '__main__': + sys.exit(Main()) diff --git a/BaseTools/Source/Python/PackagingTool/IpiDb.py b/BaseTools/Source/Python/PackagingTool/IpiDb.py new file mode 100644 index 0000000000..8661edbca4 --- /dev/null +++ b/BaseTools/Source/Python/PackagingTool/IpiDb.py @@ -0,0 +1,629 @@ +## @file +# This file is for installed package information database operations +# +# Copyright (c) 2007 ~ 2008, 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. +# + +## +# Import Modules +# +import sqlite3 +import os +import time +import Common.EdkLogger as EdkLogger + +from CommonDataClass import DistributionPackageClass + +## IpiDb +# +# This class represents the installed package information databse +# Add/Remove/Get installed distribution package information here. +# +# +# @param object: Inherited from object class +# @param DbPath: A string for the path of the database +# +# @var Conn: Connection of the database +# @var Cur: Cursor of the connection +# +class IpiDatabase(object): + def __init__(self, DbPath): + Dir = os.path.dirname(DbPath) + if not os.path.isdir(Dir): + os.mkdir(Dir) + self.Conn = sqlite3.connect(DbPath, isolation_level = 'DEFERRED') + self.Conn.execute("PRAGMA page_size=4096") + self.Conn.execute("PRAGMA synchronous=OFF") + self.Cur = self.Conn.cursor() + self.DpTable = 'DpInfo' + self.PkgTable = 'PkgInfo' + self.ModInPkgTable = 'ModInPkgInfo' + self.StandaloneModTable = 'StandaloneModInfo' + self.ModDepexTable = 'ModDepexInfo' + self.DpFileListTable = 'DpFileListInfo' + + ## Initialize build database + # + # + def InitDatabase(self): + EdkLogger.verbose("\nInitialize IPI database started ...") + + # + # Create new table + # + SqlCommand = """create table IF NOT EXISTS %s (DpGuid TEXT NOT NULL, + DpVersion TEXT NOT NULL, + InstallTime REAL NOT NULL, + PkgFileName TEXT, + PRIMARY KEY (DpGuid, DpVersion) + )""" % self.DpTable + self.Cur.execute(SqlCommand) + + SqlCommand = """create table IF NOT EXISTS %s (FilePath TEXT NOT NULL, + DpGuid TEXT, + DpVersion TEXT, + PRIMARY KEY (FilePath) + )""" % self.DpFileListTable + self.Cur.execute(SqlCommand) + + SqlCommand = """create table IF NOT EXISTS %s (PackageGuid TEXT NOT NULL, + PackageVersion TEXT NOT NULL, + InstallTime REAL NOT NULL, + DpGuid TEXT, + DpVersion TEXT, + InstallPath TEXT NOT NULL, + PRIMARY KEY (PackageGuid, PackageVersion, InstallPath) + )""" % self.PkgTable + self.Cur.execute(SqlCommand) + + SqlCommand = """create table IF NOT EXISTS %s (ModuleGuid TEXT NOT NULL, + ModuleVersion TEXT NOT NULL, + InstallTime REAL NOT NULL, + PackageGuid TEXT, + PackageVersion TEXT, + InstallPath TEXT NOT NULL, + PRIMARY KEY (ModuleGuid, ModuleVersion, InstallPath) + )""" % self.ModInPkgTable + self.Cur.execute(SqlCommand) + + SqlCommand = """create table IF NOT EXISTS %s (ModuleGuid TEXT NOT NULL, + ModuleVersion TEXT NOT NULL, + InstallTime REAL NOT NULL, + DpGuid TEXT, + DpVersion TEXT, + InstallPath TEXT NOT NULL, + PRIMARY KEY (ModuleGuid, ModuleVersion, InstallPath) + )""" % self.StandaloneModTable + self.Cur.execute(SqlCommand) + + SqlCommand = """create table IF NOT EXISTS %s (ModuleGuid TEXT NOT NULL, + ModuleVersion TEXT NOT NULL, + InstallPath TEXT NOT NULL, + DepexGuid TEXT, + DepexVersion TEXT + )""" % self.ModDepexTable + self.Cur.execute(SqlCommand) + + self.Conn.commit() + + EdkLogger.verbose("Initialize IPI database ... DONE!") + + ## Add a distribution install information from DpObj + # + # @param DpObj: + # + def AddDPObject(self, DpObj): + + for PkgKey in DpObj.PackageSurfaceArea.keys(): + PkgGuid = PkgKey[0] + PkgVersion = PkgKey[1] + PkgInstallPath = PkgKey[2] + self.AddPackage(PkgGuid, PkgVersion, DpObj.Header.Guid, DpObj.Header.Version, PkgInstallPath) + PkgObj = DpObj.PackageSurfaceArea[PkgKey] + for ModKey in PkgObj.Modules.keys(): + ModGuid = ModKey[0] + ModVersion = ModKey[1] + ModInstallPath = ModKey[2] + self.AddModuleInPackage(ModGuid, ModVersion, PkgGuid, PkgVersion, ModInstallPath) + ModObj = PkgObj.Modules[ModKey] + for Dep in ModObj.PackageDependencies: + DepexGuid = Dep.PackageGuid + DepexVersion = Dep.PackageVersion + self.AddModuleDepex(ModGuid, ModVersion, ModInstallPath, DepexGuid, DepexVersion) + for FilePath in PkgObj.FileList: + self.AddDpFilePathList(DpObj.Header.Guid, DpObj.Header.Version, FilePath) + + for ModKey in DpObj.ModuleSurfaceArea.keys(): + ModGuid = ModKey[0] + ModVersion = ModKey[1] + ModInstallPath = ModKey[2] + self.AddStandaloneModule(ModGuid, ModVersion, DpObj.Header.Guid, DpObj.Header.Version, ModInstallPath) + ModObj = DpObj.ModuleSurfaceArea[ModKey] + for Dep in ModObj.PackageDependencies: + DepexGuid = Dep.PackageGuid + DepexVersion = Dep.PackageVersion + self.AddModuleDepex(ModGuid, ModVersion, ModInstallPath, DepexGuid, DepexVersion) + for FilePath in ModObj.FileList: + self.AddDpFilePathList(DpObj.Header.Guid, DpObj.Header.Version, FilePath) + + self.AddDp(DpObj.Header.Guid, DpObj.Header.Version, DpObj.Header.FileName) + ## Add a distribution install information + # + # @param Guid: + # @param Version: + # @param PkgFileName: + # + def AddDp(self, Guid, Version, PkgFileName = None): + + if Version == None or len(Version.strip()) == 0: + Version = 'N/A' + + # + # Add newly installed DP information to DB. + # + if PkgFileName == None or len(PkgFileName.strip()) == 0: + PkgFileName = 'N/A' + (Guid, Version, PkgFileName) = (Guid, Version, PkgFileName) + CurrentTime = time.time() + SqlCommand = """insert into %s values('%s', '%s', %s, '%s')""" % (self.DpTable, Guid, Version, CurrentTime, PkgFileName) + self.Cur.execute(SqlCommand) + self.Conn.commit() + + ## Add a file list from DP + # + # @param DpGuid: + # @param DpVersion: + # @param Path + # + def AddDpFilePathList(self, DpGuid, DpVersion, Path): + + SqlCommand = """insert into %s values('%s', '%s', '%s')""" % (self.DpFileListTable, Path, DpGuid, DpVersion) + self.Cur.execute(SqlCommand) + self.Conn.commit() + + ## Add a package install information + # + # @param Guid: + # @param Version: + # @param DpGuid: + # @param DpVersion: + # @param Path + # + def AddPackage(self, Guid, Version, DpGuid = None, DpVersion = None, Path = ''): + + if Version == None or len(Version.strip()) == 0: + Version = 'N/A' + + if DpGuid == None or len(DpGuid.strip()) == 0: + DpGuid = 'N/A' + + if DpVersion == None or len(DpVersion.strip()) == 0: + DpVersion = 'N/A' + + # + # Add newly installed package information to DB. + # + + CurrentTime = time.time() + SqlCommand = """insert into %s values('%s', '%s', %s, '%s', '%s', '%s')""" % (self.PkgTable, Guid, Version, CurrentTime, DpGuid, DpVersion, Path) + self.Cur.execute(SqlCommand) + self.Conn.commit() + + ## Add a module that from a package install information + # + # @param Guid: + # @param Version: + # @param PkgFileName: + # + def AddModuleInPackage(self, Guid, Version, PkgGuid = None, PkgVersion = None, Path = ''): + + if Version == None or len(Version.strip()) == 0: + Version = 'N/A' + + if PkgGuid == None or len(PkgGuid.strip()) == 0: + PkgGuid = 'N/A' + + if PkgVersion == None or len(PkgVersion.strip()) == 0: + PkgVersion = 'N/A' + + # + # Add module from package information to DB. + # + CurrentTime = time.time() + SqlCommand = """insert into %s values('%s', '%s', %s, '%s', '%s', '%s')""" % (self.ModInPkgTable, Guid, Version, CurrentTime, PkgGuid, PkgVersion, Path) + self.Cur.execute(SqlCommand) + self.Conn.commit() + + ## Add a module that is standalone install information + # + # @param Guid: + # @param Version: + # @param PkgFileName: + # + def AddStandaloneModule(self, Guid, Version, DpGuid = None, DpVersion = None, Path = ''): + + if Version == None or len(Version.strip()) == 0: + Version = 'N/A' + + if DpGuid == None or len(DpGuid.strip()) == 0: + DpGuid = 'N/A' + + if DpVersion == None or len(DpVersion.strip()) == 0: + DpVersion = 'N/A' + + # + # Add module standalone information to DB. + # + CurrentTime = time.time() + SqlCommand = """insert into %s values('%s', '%s', %s, '%s', '%s', '%s')""" % (self.StandaloneModTable, Guid, Version, CurrentTime, DpGuid, DpVersion, Path) + self.Cur.execute(SqlCommand) + self.Conn.commit() + + ## Add a module depex + # + # @param Guid: + # @param Version: + # @param DepexGuid: + # @param DepexVersion: + # + def AddModuleDepex(self, Guid, Version, Path, DepexGuid = None, DepexVersion = None): + + if DepexGuid == None or len(DepexGuid.strip()) == 0: + DepexGuid = 'N/A' + + if DepexVersion == None or len(DepexVersion.strip()) == 0: + DepexVersion = 'N/A' + + # + # Add module depex information to DB. + # + + SqlCommand = """insert into %s values('%s', '%s', '%s', '%s', '%s')""" % (self.ModDepexTable, Guid, Version, Path, DepexGuid, DepexVersion) + self.Cur.execute(SqlCommand) + self.Conn.commit() + + ## Remove a distribution install information, if no version specified, remove all DPs with this Guid. + # + # @param DpObj: + # + def RemoveDpObj(self, DpGuid, DpVersion): + + PkgList = self.GetPackageListFromDp(DpGuid, DpVersion) + + # delete from ModDepex the standalone module's dependency + SqlCommand = """delete from ModDepexInfo where ModDepexInfo.ModuleGuid in + (select ModuleGuid from StandaloneModInfo as B where B.DpGuid = '%s' and B.DpVersion = '%s') + and ModDepexInfo.ModuleVersion in + (select ModuleVersion from StandaloneModInfo as B where B.DpGuid = '%s' and B.DpVersion = '%s') + and ModDepexInfo.InstallPath in + (select InstallPath from StandaloneModInfo as B where B.DpGuid = '%s' and B.DpVersion = '%s') """ \ + %(DpGuid, DpVersion, DpGuid, DpVersion, DpGuid, DpVersion) + +# SqlCommand = """delete from %s where %s.DpGuid ='%s' and %s.DpVersion = '%s' and +# %s.ModuleGuid = %s.ModuleGuid and %s.ModuleVersion = %s.ModuleVersion and +# %s.InstallPath = %s.InstallPath""" \ +# % (self.ModDepexTable, self.StandaloneModTable, DpGuid, self.StandaloneModTable, DpVersion, self.ModDepexTable, self.StandaloneModTable, self.ModDepexTable, self.StandaloneModTable, self.ModDepexTable, self.StandaloneModTable) +# print SqlCommand + self.Cur.execute(SqlCommand) + + # delete from ModDepex the from pkg module's dependency + for Pkg in PkgList: +# SqlCommand = """delete from %s where %s.PackageGuid ='%s' and %s.PackageVersion = '%s' and +# %s.ModuleGuid = %s.ModuleGuid and %s.ModuleVersion = %s.ModuleVersion and +# %s.InstallPath = %s.InstallPath""" \ +# % (self.ModDepexTable, self.ModInPkgTable, Pkg[0], self.ModInPkgTable, Pkg[1], self.ModDepexTable, self.ModInPkgTable, self.ModDepexTable, self.ModInPkgTable, self.ModDepexTable, self.ModInPkgTable) + SqlCommand = """delete from ModDepexInfo where ModDepexInfo.ModuleGuid in + (select ModuleGuid from ModInPkgInfo where ModInPkgInfo.PackageGuid ='%s' and ModInPkgInfo.PackageVersion = '%s') + and ModDepexInfo.ModuleVersion in + (select ModuleVersion from ModInPkgInfo where ModInPkgInfo.PackageGuid ='%s' and ModInPkgInfo.PackageVersion = '%s') + and ModDepexInfo.InstallPath in + (select InstallPath from ModInPkgInfo where ModInPkgInfo.PackageGuid ='%s' and ModInPkgInfo.PackageVersion = '%s')""" \ + % (Pkg[0], Pkg[1],Pkg[0], Pkg[1],Pkg[0], Pkg[1]) + + self.Cur.execute(SqlCommand) + + # delete the standalone module + SqlCommand = """delete from %s where DpGuid ='%s' and DpVersion = '%s'""" % (self.StandaloneModTable, DpGuid, DpVersion) + self.Cur.execute(SqlCommand) + + # delete the from pkg module + for Pkg in PkgList: + SqlCommand = """delete from %s where %s.PackageGuid ='%s' and %s.PackageVersion = '%s'""" \ + % (self.ModInPkgTable, self.ModInPkgTable, Pkg[0], self.ModInPkgTable, Pkg[1]) + self.Cur.execute(SqlCommand) + + # delete packages + SqlCommand = """delete from %s where DpGuid ='%s' and DpVersion = '%s'""" % (self.PkgTable, DpGuid, DpVersion) + self.Cur.execute(SqlCommand) + + # delete file list from DP + SqlCommand = """delete from %s where DpGuid ='%s' and DpVersion = '%s'""" % (self.DpFileListTable, DpGuid, DpVersion) + self.Cur.execute(SqlCommand) + + # delete DP + SqlCommand = """delete from %s where DpGuid ='%s' and DpVersion = '%s'""" % (self.DpTable, DpGuid, DpVersion) + self.Cur.execute(SqlCommand) + + self.Conn.commit() + + ## Get a list of distribution install information. + # + # @param Guid: + # @param Version: + # + def GetDp(self, Guid, Version): + + if Version == None or len(Version.strip()) == 0: + Version = 'N/A' + EdkLogger.verbose("\nGetting list of DP install information started ...") + (DpGuid, DpVersion) = (Guid, Version) + SqlCommand = """select * from %s where DpGuid ='%s'""" % (self.DpTable, DpGuid) + self.Cur.execute(SqlCommand) + + else: + EdkLogger.verbose("\nGetting DP install information started ...") + (DpGuid, DpVersion) = (Guid, Version) + SqlCommand = """select * from %s where DpGuid ='%s' and DpVersion = '%s'""" % (self.DpTable, DpGuid, DpVersion) + self.Cur.execute(SqlCommand) + + DpList = [] + for DpInfo in self.Cur: + DpGuid = DpInfo[0] + DpVersion = DpInfo[1] + InstallTime = DpInfo[2] + PkgFileName = DpInfo[3] + DpList.append((DpGuid, DpVersion, InstallTime, PkgFileName)) + + EdkLogger.verbose("Getting DP install information ... DONE!") + return DpList + + ## Get a list of distribution install file path information. + # + # @param Guid: + # @param Version: + # + def GetDpFileList(self, Guid, Version): + + (DpGuid, DpVersion) = (Guid, Version) + SqlCommand = """select * from %s where DpGuid ='%s' and DpVersion = '%s'""" % (self.DpFileListTable, DpGuid, DpVersion) + self.Cur.execute(SqlCommand) + + PathList = [] + for Result in self.Cur: + Path = Result[0] + PathList.append(Path) + + return PathList + + ## Get a list of package information. + # + # @param Guid: + # @param Version: + # + def GetPackage(self, Guid, Version, DpGuid = '', DpVersion = ''): + + if DpVersion == '' or DpGuid == '': + + (PackageGuid, PackageVersion) = (Guid, Version) + SqlCommand = """select * from %s where PackageGuid ='%s' and PackageVersion = '%s'""" % (self.PkgTable, PackageGuid, PackageVersion) + self.Cur.execute(SqlCommand) + + elif Version == None or len(Version.strip()) == 0: + + SqlCommand = """select * from %s where PackageGuid ='%s'""" % (self.PkgTable, Guid) + self.Cur.execute(SqlCommand) + else: + (PackageGuid, PackageVersion) = (Guid, Version) + SqlCommand = """select * from %s where PackageGuid ='%s' and PackageVersion = '%s' + and DpGuid = '%s' and DpVersion = '%s'""" % (self.PkgTable, PackageGuid, PackageVersion, DpGuid, DpVersion) + self.Cur.execute(SqlCommand) + + PkgList = [] + for PkgInfo in self.Cur: + PkgGuid = PkgInfo[0] + PkgVersion = PkgInfo[1] + InstallTime = PkgInfo[2] + InstallPath = PkgInfo[5] + PkgList.append((PkgGuid, PkgVersion, InstallTime, DpGuid, DpVersion, InstallPath)) + + return PkgList + + ## Get a list of module in package information. + # + # @param Guid: + # @param Version: + # + def GetModInPackage(self, Guid, Version, PkgGuid = '', PkgVersion = ''): + + if PkgVersion == '' or PkgGuid == '': + + (ModuleGuid, ModuleVersion) = (Guid, Version) + SqlCommand = """select * from %s where ModuleGuid ='%s' and ModuleVersion = '%s'""" % (self.ModInPkgTable, ModuleGuid, ModuleVersion) + self.Cur.execute(SqlCommand) + + else: + (ModuleGuid, ModuleVersion) = (Guid, Version) + SqlCommand = """select * from %s where ModuleGuid ='%s' and ModuleVersion = '%s' and PackageGuid ='%s' and PackageVersion = '%s' + """ % (self.ModInPkgTable, ModuleGuid, ModuleVersion, PkgGuid, PkgVersion) + self.Cur.execute(SqlCommand) + + ModList = [] + for ModInfo in self.Cur: + ModGuid = ModInfo[0] + ModVersion = ModInfo[1] + InstallTime = ModInfo[2] + InstallPath = ModInfo[5] + ModList.append((ModGuid, ModVersion, InstallTime, PkgGuid, PkgVersion, InstallPath)) + + return ModList + + ## Get a list of module standalone. + # + # @param Guid: + # @param Version: + # + def GetStandaloneModule(self, Guid, Version, DpGuid = '', DpVersion = ''): + + if DpGuid == '': + + (ModuleGuid, ModuleVersion) = (Guid, Version) + SqlCommand = """select * from %s where ModuleGuid ='%s' and ModuleVersion = '%s'""" % (self.StandaloneModTable, ModuleGuid, ModuleVersion) + self.Cur.execute(SqlCommand) + + else: + (ModuleGuid, ModuleVersion) = (Guid, Version) + SqlCommand = """select * from %s where ModuleGuid ='%s' and ModuleVersion = '%s' and DpGuid ='%s' and DpVersion = '%s' + """ % (self.StandaloneModTable, ModuleGuid, ModuleVersion, DpGuid, DpVersion) + self.Cur.execute(SqlCommand) + + ModList = [] + for ModInfo in self.Cur: + ModGuid = ModInfo[0] + ModVersion = ModInfo[1] + InstallTime = ModInfo[2] + InstallPath = ModInfo[5] + ModList.append((ModGuid, ModVersion, InstallTime, DpGuid, DpVersion, InstallPath)) + + return ModList + + ## Get a list of module information that comes from DP. + # + # @param DpGuid: + # @param DpVersion: + # + def GetStandaloneModuleInstallPathListFromDp(self, DpGuid, DpVersion): + + PathList = [] + SqlCommand = """select t1.InstallPath from %s t1 where t1.DpGuid ='%s' and t1.DpVersion = '%s' + """ % (self.StandaloneModTable, DpGuid, DpVersion) + self.Cur.execute(SqlCommand) + + for Result in self.Cur: + InstallPath = Result[0] + PathList.append(InstallPath) + + return PathList + + ## Get a list of package information. + # + # @param DpGuid: + # @param DpVersion: + # + def GetPackageListFromDp(self, DpGuid, DpVersion): + + + SqlCommand = """select * from %s where DpGuid ='%s' and DpVersion = '%s' + """ % (self.PkgTable, DpGuid, DpVersion) + self.Cur.execute(SqlCommand) + + PkgList = [] + for PkgInfo in self.Cur: + PkgGuid = PkgInfo[0] + PkgVersion = PkgInfo[1] + InstallPath = PkgInfo[5] + PkgList.append((PkgGuid, PkgVersion, InstallPath)) + + return PkgList + + ## Get a list of modules that depends on package information from a DP. + # + # @param DpGuid: + # @param DpVersion: + # + def GetDpDependentModuleList(self, DpGuid, DpVersion): + + ModList = [] + PkgList = self.GetPackageListFromDp(DpGuid, DpVersion) + if len(PkgList) > 0: + return ModList + + for Pkg in PkgList: + SqlCommand = """select t1.ModuleGuid, t1.ModuleVersion, t1.InstallPath + from %s as t1, %s as t2, where t1.ModuleGuid = t2.ModuleGuid and + t1.ModuleVersion = t2.ModuleVersion and t2.DepexGuid ='%s' and (t2.DepexVersion = '%s' or t2.DepexVersion = 'N/A') and + t1.PackageGuid != '%s' and t1.PackageVersion != '%s' + """ % (self.ModInPkgTable, self.ModDepexTable, Pkg[0], Pkg[1], Pkg[0], Pkg[1]) + self.Cur.execute(SqlCommand) + for ModInfo in self.Cur: + ModGuid = ModInfo[0] + ModVersion = ModInfo[1] + InstallPath = ModInfo[2] + ModList.append((ModGuid, ModVersion, InstallPath)) + + SqlCommand = """select t1.ModuleGuid, t1.ModuleVersion, t1.InstallPath + from %s as t1, %s as t2, where t1.ModuleGuid = t2.ModuleGuid and + t1.ModuleVersion = t2.ModuleVersion and t2.DepexGuid ='%s' and (t2.DepexVersion = '%s' or t2.DepexVersion = 'N/A') and + t1.DpGuid != '%s' and t1.DpVersion != '%s' + """ % (self.StandaloneModTable, self.ModDepexTable, Pkg[0], Pkg[1], DpGuid, DpVersion) + self.Cur.execute(SqlCommand) + for ModInfo in self.Cur: + ModGuid = ModInfo[0] + ModVersion = ModInfo[1] + InstallPath = ModInfo[2] + ModList.append((ModGuid, ModVersion, InstallPath)) + + + return ModList + + ## Get a module depex + # + # @param Guid: + # @param Version: + # @param Path: + # + def GetModuleDepex(self, Guid, Version, Path): + + # + # Get module depex information to DB. + # + + SqlCommand = """select * from %s where ModuleGuid ='%s' and ModuleVersion = '%s' and InstallPath ='%s' + """ % (self.ModDepexTable, Guid, Version, Path) + self.Cur.execute(SqlCommand) + self.Conn.commit() + + DepexList = [] + for DepInfo in self.Cur: + DepexGuid = DepInfo[3] + DepexVersion = DepInfo[4] + DepexList.append((DepexGuid, DepexVersion)) + + return DepexList + + ## Close entire database + # + # Close the connection and cursor + # + def CloseDb(self): + + self.Cur.close() + self.Conn.close() + + ## Convert To Sql String + # + # 1. Replace "'" with "''" in each item of StringList + # + # @param StringList: A list for strings to be converted + # + def __ConvertToSqlString(self, StringList): + return map(lambda s: s.replace("'", "''") , StringList) +## +# +# This acts like the main() function for the script, unless it is 'import'ed into another +# script. +# +if __name__ == '__main__': + EdkLogger.Initialize() + EdkLogger.SetLevel(EdkLogger.DEBUG_0) + DATABASE_PATH = "C://MyWork//Conf//.cache//XML.db" + Db = IpiDatabase(DATABASE_PATH) + Db.InitDatabase() + + \ No newline at end of file diff --git a/BaseTools/Source/Python/PackagingTool/MkPkg.py b/BaseTools/Source/Python/PackagingTool/MkPkg.py new file mode 100644 index 0000000000..660f48f05f --- /dev/null +++ b/BaseTools/Source/Python/PackagingTool/MkPkg.py @@ -0,0 +1,294 @@ +## @file +# Install distribution package. +# +# Copyright (c) 2007, 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. +# + +## +# Import Modules +# +import os +import os.path +import sys +import glob +import shutil +import traceback +import platform +from optparse import OptionParser +import md5 +import time +import uuid + +from PackageFile import * +import Common.EdkLogger as EdkLogger +from Common.BuildToolError import * +from Common.Misc import * +from Common.XmlParser import * +from CommonDataClass.DistributionPackageClass import * +from Common.DecClassObjectLight import Dec +from Common.InfClassObjectLight import Inf + +from PackageFile import * + +# Version and Copyright +VersionNumber = "0.1" +__version__ = "%prog Version " + VersionNumber +__copyright__ = "Copyright (c) 2008, Intel Corporation All rights reserved." + +## Check environment variables +# +# Check environment variables that must be set for build. Currently they are +# +# WORKSPACE The directory all packages/platforms start from +# EDK_TOOLS_PATH The directory contains all tools needed by the build +# PATH $(EDK_TOOLS_PATH)/Bin/ must be set in PATH +# +# If any of above environment variable is not set or has error, the build +# will be broken. +# +def CheckEnvVariable(): + # check WORKSPACE + if "WORKSPACE" not in os.environ: + EdkLogger.error("MkPkg", ATTRIBUTE_NOT_AVAILABLE, "Environment variable not found", + ExtraData="WORKSPACE") + + WorkspaceDir = os.path.normpath(os.environ["WORKSPACE"]) + if not os.path.exists(WorkspaceDir): + EdkLogger.error("MkPkg", FILE_NOT_FOUND, "WORKSPACE doesn't exist", ExtraData="%s" % WorkspaceDir) + elif ' ' in WorkspaceDir: + EdkLogger.error("MkPkg", FORMAT_NOT_SUPPORTED, "No space is allowed in WORKSPACE path", + ExtraData=WorkspaceDir) + os.environ["WORKSPACE"] = WorkspaceDir + +## Parse command line options +# +# Using standard Python module optparse to parse command line option of this tool. +# +# @retval Opt A optparse.Values object containing the parsed options +# @retval Args Target of build command +# +def MyOptionParser(): + UsageString = "%prog -m -p [-o distribution_file] " + \ + "[-x xml-file-header] [-t tools-directory] [-f misc-files] [-q | -v] [-h]" + + Parser = OptionParser(description=__copyright__,version=__version__,prog="MkPkg",usage=UsageString) + + Parser.add_option("-?", action="help", help="show this help message and exit") + + Parser.add_option("-o", "--output-file", action="store", type="string", dest="DistributionFile", + help="Specify the distribution file to be created.") + + Parser.add_option("-f", "--misc-files", action="append", type="string", dest="MiscFiles", + help="Specify any misc files.") + + Parser.add_option("-x", "--xml-file-header", action="store", type=None, dest="TemplateFile", + help="Specify the xml file which includes header information for creating the distribution file.") + + Parser.add_option("-t", "--tools-directory", action="store", type=None, dest="ToolsDir", + help="Specify the directory name of tools.") + + Parser.add_option("-m", "--module", action="append", type="string", dest="ModuleFileList", + help="The inf file of module to be distributed standalone.") + + Parser.add_option("-p", "--package", action="append", type="string", dest="PackageFileList", + help="The dec file of package to be distributed.") + + Parser.add_option("-q", "--quiet", action="store_const", dest="LogLevel", const=EdkLogger.QUIET, + help="Disable all messages except FATAL ERRORS.") + + Parser.add_option("-v", "--verbose", action="store_const", dest="LogLevel", const=EdkLogger.VERBOSE, + help="Turn on verbose output") + + Parser.add_option("-d", "--debug", action="store", type="int", dest="LogLevel", + help="Enable debug messages at specified level.") + + Parser.set_defaults(LogLevel=EdkLogger.INFO) + + (Opt, Args)=Parser.parse_args() + # error check + if not Opt.ModuleFileList and not Opt.PackageFileList: + EdkLogger.error("MkPkg", OPTION_NOT_SUPPORTED, ExtraData="At least one package file or module file must be specified") + if Opt.TemplateFile: + if not os.path.exists(Opt.TemplateFile): + EdkLogger.error( + "\nMkPkg", + FILE_NOT_FOUND, + "Template file [%s] not found" % Opt.TemplateFile + ) + return Opt + +## Tool entrance method +# +# This method mainly dispatch specific methods per the command line options. +# If no error found, return zero value so the caller of this tool can know +# if it's executed successfully or not. +# +# @retval 0 Tool was successful +# @retval 1 Tool failed +# +def Main(): + EdkLogger.Initialize() + Options = MyOptionParser() + try: + if Options.LogLevel < EdkLogger.DEBUG_9: + EdkLogger.SetLevel(Options.LogLevel + 1) + else: + EdkLogger.SetLevel(Options.LogLevel) + + CheckEnvVariable() + WorkspaceDir = os.environ["WORKSPACE"] + + # Init DistributionFile + if not Options.DistributionFile: + Options.DistributionFile = "DistributionPackage.zip" + + # Check Tools Dir + if Options.ToolsDir: + if not os.path.isdir(os.path.normpath(os.path.join(WorkspaceDir, Options.ToolsDir))): + EdkLogger.error( + "\nMkPkg", + FILE_NOT_FOUND, + "Tools directory [%s] not found" % Options.ToolsDir + ) + + # Check misc files + if Options.MiscFiles: + for Item in Options.MiscFiles: + FullPath = os.path.normpath(os.path.join(WorkspaceDir, Item)) + if not os.path.isfile(FullPath): + EdkLogger.error( + "\nMkPkg", + FILE_NOT_FOUND, + "Misc file [%s] not found" % Item + ) + + #Check package file existing and valid + if Options.PackageFileList: + for Item in Options.PackageFileList: + (Name, Ext) = os.path.splitext(Item) + if Ext.upper() != '.DEC': + EdkLogger.error( + "\nMkPkg", + OPTION_VALUE_INVALID, + "[%s] is not a valid package name" % Item + ) + Path = os.path.normpath(os.path.join(WorkspaceDir, Item)) + if not os.path.exists(Path): + EdkLogger.error( + "\nMkPkg", + FILE_NOT_FOUND, + "[%s] not found" % Item + ) + #Check module file existing and valid + if Options.ModuleFileList: + for Item in Options.ModuleFileList: + (Name, Ext) = os.path.splitext(Item) + if Ext.upper() != '.INF': + EdkLogger.error( + "\nMkPkg", + OPTION_VALUE_INVALID, + "[%s] is not a valid module name" % Item + ) + Path = os.path.normpath(os.path.join(WorkspaceDir, Item)) + if not os.path.exists(Path): + EdkLogger.error( + "\nMkPkg", + FILE_NOT_FOUND, + "[%s] not found" % Item + ) + + ContentFile = PackageFile("content.zip", "w") + DistPkg = DistributionPackageClass() + DistPkg.GetDistributionPackage(WorkspaceDir, Options.PackageFileList, Options.ModuleFileList) + DistPkgXml = DistributionPackageXml() + for Item in DistPkg.PackageSurfaceArea: + ContentFile.Pack(os.path.dirname(os.path.normpath(os.path.join(WorkspaceDir,Item[2])))) + for Item in DistPkg.ModuleSurfaceArea: + ContentFile.Pack(os.path.dirname(os.path.normpath(os.path.join(WorkspaceDir,Item[2])))) + + # Add tools files and information + if Options.ToolsDir: + ToolsFiles = MiscFileClass() + ToolsRoot = os.path.normpath(os.path.join(WorkspaceDir, Options.ToolsDir)) + ContentFile.Pack(ToolsRoot) + ToolsFileList = GetFiles(ToolsRoot, ['CVS', '.svn']) + for Item in ToolsFileList: + OriPath = Item[len(WorkspaceDir)+1:] + FileObj = FileClass() + FileObj.Filename = OriPath + (Name, Ext) = os.path.splitext(OriPath) + if Ext.upper() in ['EXE', 'COM', 'EFI']: + FileObj.Executable = 'True' + ToolsFiles.Files.append(FileObj) + DistPkg.Tools = ToolsFiles + + # Add misc files and information + if Options.MiscFiles: + MiscFiles = MiscFileClass() + for Item in Options.MiscFiles: + ContentFile.PackFile(Item) + FileObj = FileClass() + FileObj.Filename = Item + (Name, Ext) = os.path.splitext(Item) + if Ext.upper() in ['EXE', 'COM', 'EFI']: + FileObj.Executable = 'True' + MiscFiles.Files.append(FileObj) + DistPkg.MiscellaneousFiles = MiscFiles + + print "Compressing Distribution Package File ..." + ContentFile.Close() + + # Add temp distribution header + if Options.TemplateFile: + TempXML = DistributionPackageXml() + DistPkg.Header = TempXML.FromXml(Options.TemplateFile).Header + # Add init dp information + else: + DistPkg.Header.Name = 'Distribution Package' + DistPkg.Header.Guid = str(uuid.uuid4()) + DistPkg.Header.Version = '1.0' + + # Add Md5Sigature + Md5Sigature = md5.new(open(str(ContentFile)).read()) + DistPkg.Header.Signature = Md5Sigature.hexdigest() + # Add current Date + DistPkg.Header.Date = str(time.strftime("%Y-%m-%dT%H:%M:%S", time.localtime())) + + # Finish final dp file + DistPkgFile = PackageFile(Options.DistributionFile, "w") + DistPkgFile.PackFile(str(ContentFile)) + DistPkgFile.PackData(DistPkgXml.ToXml(DistPkg), "dist.pkg") + DistPkgFile.Close() + print "DONE" + + except FatalError, X: + if Options and Options.LogLevel < EdkLogger.DEBUG_9: + EdkLogger.quiet("(Python %s on %s) " % (platform.python_version(), sys.platform) + traceback.format_exc()) + ReturnCode = X.args[0] + except KeyboardInterrupt: + ReturnCode = ABORT_ERROR + if Options and Options.LogLevel < EdkLogger.DEBUG_9: + EdkLogger.quiet("(Python %s on %s) " % (platform.python_version(), sys.platform) + traceback.format_exc()) + except: + EdkLogger.error( + "\nMkPkg", + CODE_ERROR, + "Unknown fatal error when creating [%s]" % Options.DistributionFile, + ExtraData="\n(Please send email to dev@buildtools.tianocore.org for help, attaching following call stack trace!)\n", + RaiseError=False + ) + EdkLogger.quiet("(Python %s on %s) " % (platform.python_version(), sys.platform) + traceback.format_exc()) + ReturnCode = CODE_ERROR + finally: + Progressor.Abort() + +if __name__ == '__main__': + sys.exit(Main()) + diff --git a/BaseTools/Source/Python/PackagingTool/PackageFile.py b/BaseTools/Source/Python/PackagingTool/PackageFile.py new file mode 100644 index 0000000000..12544927c9 --- /dev/null +++ b/BaseTools/Source/Python/PackagingTool/PackageFile.py @@ -0,0 +1,160 @@ +## @file +# +# PackageFile class represents the zip file of a distribution package. +# +# Copyright (c) 2007, 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. +# + +## +# Import Modules +# +import os +import sys +import zipfile +import tempfile + +from Common import EdkLogger +from Common.Misc import * +from Common.BuildToolError import * + +class PackageFile: + def __init__(self, FileName, Mode="r"): + self._FileName = FileName + if Mode not in ["r", "w", "a"]: + Mode = "r" + try: + self._ZipFile = zipfile.ZipFile(FileName, Mode, zipfile.ZIP_DEFLATED) + self._Files = {} + for F in self._ZipFile.namelist(): + self._Files[os.path.normpath(F)] = F + except BaseException, X: + EdkLogger.error("PackagingTool", FILE_OPEN_FAILURE, + ExtraData="%s (%s)" % (FileName, str(X))) + + BadFile = self._ZipFile.testzip() + if BadFile != None: + EdkLogger.error("PackagingTool", FILE_CHECKSUM_FAILURE, + ExtraData="[%s] in %s" % (BadFile, FileName)) + + def __str__(self): + return self._FileName + + def Unpack(self, To): + for F in self._ZipFile.namelist(): + ToFile = os.path.normpath(os.path.join(To, F)) + print F, "->", ToFile + self.Extract(F, ToFile) + + def UnpackFile(self, File, ToFile): + File = File.replace('\\', '/') + if File in self._ZipFile.namelist(): + print File, "->", ToFile + self.Extract(File, ToFile) + + return ToFile + + return '' + + def Extract(self, Which, To): + Which = os.path.normpath(Which) + if Which not in self._Files: + EdkLogger.error("PackagingTool", FILE_NOT_FOUND, + ExtraData="[%s] in %s" % (Which, self._FileName)) + try: + FileContent = self._ZipFile.read(self._Files[Which]) + except BaseException, X: + EdkLogger.error("PackagingTool", FILE_DECOMPRESS_FAILURE, + ExtraData="[%s] in %s (%s)" % (Which, self._FileName, str(X))) + try: + CreateDirectory(os.path.dirname(To)) + ToFile = open(To, "wb") + except BaseException, X: + EdkLogger.error("PackagingTool", FILE_OPEN_FAILURE, + ExtraData="%s (%s)" % (To, str(X))) + + try: + ToFile.write(FileContent) + ToFile.close() + except BaseException, X: + EdkLogger.error("PackagingTool", FILE_WRITE_FAILURE, + ExtraData="%s (%s)" % (To, str(X))) + + def Remove(self, Files): + TmpDir = os.path.join(tempfile.gettempdir(), ".packaging") + if os.path.exists(TmpDir): + RemoveDirectory(TmpDir, True) + + os.mkdir(TmpDir) + self.Unpack(TmpDir) + for F in Files: + F = os.path.normpath(F) + if F not in self._Files: + EdkLogger.error("PackagingTool", FILE_NOT_FOUND, + ExtraData="%s is not in %s!" % (F, self._FileName)) + #os.remove(os.path.join(TmpDir, F)) # no need to really remove file + self._Files.pop(F) + self._ZipFile.close() + + self._ZipFile = zipfile.ZipFile(self._FileName, "w", zipfile.ZIP_DEFLATED) + Cwd = os.getcwd() + os.chdir(TmpDir) + self.PackFiles(self._Files) + os.chdir(Cwd) + RemoveDirectory(TmpDir, True) + + def Pack(self, Top): + if not os.path.isdir(Top): + EdkLogger.error("PackagingTool", FILE_UNKNOWN_ERROR, "%s is not a directory!" %Top) + + FilesToPack = [] + ParentDir = os.path.dirname(Top) + BaseDir = os.path.basename(Top) + Cwd = os.getcwd() + os.chdir(ParentDir) + for Root, Dirs, Files in os.walk(BaseDir): + if 'CVS' in Dirs: + Dirs.remove('CVS') + if '.svn' in Dirs: + Dirs.remove('.svn') + for F in Files: + FilesToPack.append(os.path.join(Root, F)) + self.PackFiles(FilesToPack) + os.chdir(Cwd) + + def PackFiles(self, Files): + for F in Files: + try: + print "packing ...", F + self._ZipFile.write(F) + except BaseException, X: + EdkLogger.error("PackagingTool", FILE_COMPRESS_FAILURE, + ExtraData="%s (%s)" % (F, str(X))) + + def PackFile(self, File, ArcName=None): + try: + print "packing ...", File + self._ZipFile.write(File, ArcName) + except BaseException, X: + EdkLogger.error("PackagingTool", FILE_COMPRESS_FAILURE, + ExtraData="%s (%s)" % (File, str(X))) + + def PackData(self, Data, ArcName): + try: + self._ZipFile.writestr(ArcName, Data) + except BaseException, X: + EdkLogger.error("PackagingTool", FILE_COMPRESS_FAILURE, + ExtraData="%s (%s)" % (ArcName, str(X))) + + def Close(self): + self._ZipFile.close() + +if __name__ == '__main__': + pass + diff --git a/BaseTools/Source/Python/PackagingTool/RmPkg.py b/BaseTools/Source/Python/PackagingTool/RmPkg.py new file mode 100644 index 0000000000..e7eedd0776 --- /dev/null +++ b/BaseTools/Source/Python/PackagingTool/RmPkg.py @@ -0,0 +1,218 @@ +## @file +# Install distribution package. +# +# Copyright (c) 2007, 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. +# + +## +# Import Modules +# +import os +import sys +import traceback +import platform +from optparse import OptionParser + +import Common.EdkLogger as EdkLogger +from Common.BuildToolError import * +from Common.Misc import * +from Common.XmlParser import * + +from IpiDb import * +from DependencyRules import * + +# Version and Copyright +VersionNumber = "0.1" +__version__ = "%prog Version " + VersionNumber +__copyright__ = "Copyright (c) 2008, Intel Corporation All rights reserved." + +## Check environment variables +# +# Check environment variables that must be set for build. Currently they are +# +# WORKSPACE The directory all packages/platforms start from +# EDK_TOOLS_PATH The directory contains all tools needed by the build +# PATH $(EDK_TOOLS_PATH)/Bin/ must be set in PATH +# +# If any of above environment variable is not set or has error, the build +# will be broken. +# +def CheckEnvVariable(): + # check WORKSPACE + if "WORKSPACE" not in os.environ: + EdkLogger.error("RmPkg", ATTRIBUTE_NOT_AVAILABLE, "Environment variable not found", + ExtraData="WORKSPACE") + + WorkspaceDir = os.path.normpath(os.environ["WORKSPACE"]) + if not os.path.exists(WorkspaceDir): + EdkLogger.error("RmPkg", FILE_NOT_FOUND, "WORKSPACE doesn't exist", ExtraData="%s" % WorkspaceDir) + elif ' ' in WorkspaceDir: + EdkLogger.error("RmPkg", FORMAT_NOT_SUPPORTED, "No space is allowed in WORKSPACE path", + ExtraData=WorkspaceDir) + os.environ["WORKSPACE"] = WorkspaceDir + +## Parse command line options +# +# Using standard Python module optparse to parse command line option of this tool. +# +# @retval Opt A optparse.Values object containing the parsed options +# @retval Args Target of build command +# +def MyOptionParser(): + UsageString = "%prog -g -n [-y] [-q | -v] [-h]" + + Parser = OptionParser(description=__copyright__,version=__version__,prog="RmPkg",usage=UsageString) + + Parser.add_option("-?", action="help", help="show this help message and exit") + +# Parser.add_option("-f", "--force", action="store_true", type=None, dest="ForceRemove", +# help="Force creation - overwrite existing one.") + + Parser.add_option("-y", "--yes", action="store_true", dest="Yes", + help="Not asking for confirmation when deleting files.") + + Parser.add_option("-n", "--package-version", action="store", type="string", dest="PackageVersion", + help="The version of distribution package to be removed.") + + Parser.add_option("-g", "--package-guid", action="store", type="string", dest="PackageGuid", + help="The GUID of distribution package to be removed.") + + Parser.add_option("-q", "--quiet", action="store_const", dest="LogLevel", const=EdkLogger.QUIET, + help="Disable all messages except FATAL ERRORS.") + + Parser.add_option("-v", "--verbose", action="store_const", dest="LogLevel", const=EdkLogger.VERBOSE, + help="Turn on verbose output") + + Parser.add_option("-d", "--debug", action="store", type="int", dest="LogLevel", + help="Enable debug messages at specified level.") + + Parser.set_defaults(LogLevel=EdkLogger.INFO) + + (Opt, Args)=Parser.parse_args() + + return Opt + +## Remove all empty dirs under the path +def RemoveEmptyDirs(Path): + # Remove all sub dirs + for Root, Dirs, Files in os.walk(Path): + for Dir in Dirs: + FullPath = os.path.normpath(os.path.join(Root, Dir)) + if os.path.isdir(FullPath): + if os.listdir(FullPath) == []: + os.rmdir(FullPath) + else: + RemoveEmptyDirs(FullPath) + # Remove itself + if os.path.isdir(Path) and os.listdir(Path) == []: + os.rmdir(Path) + + +## Tool entrance method +# +# This method mainly dispatch specific methods per the command line options. +# If no error found, return zero value so the caller of this tool can know +# if it's executed successfully or not. +# +# @retval 0 Tool was successful +# @retval 1 Tool failed +# +def Main(): + EdkLogger.Initialize() + Options = MyOptionParser() + try: + if not Options.PackageGuid and not Options.PackageVersion: + EdkLogger.error("RmPkg", OPTION_MISSING, ExtraData="The GUID and Version of distribution package must be specified") + + if Options.LogLevel < EdkLogger.DEBUG_9: + EdkLogger.SetLevel(Options.LogLevel + 1) + else: + EdkLogger.SetLevel(Options.LogLevel) + + CheckEnvVariable() + WorkspaceDir = os.environ["WORKSPACE"] + + # Prepare check dependency + Db = IpiDatabase(os.path.normpath(os.path.join(WorkspaceDir, "Conf/DistributionPackageDatabase.db"))) + Db.InitDatabase() + Dep = DependencyRules(Db) + + Guid = Options.PackageGuid + Version = Options.PackageVersion + + # Check Dp existing + if not Dep.CheckDpExists(Guid, Version): + EdkLogger.error("RmPkg", UNKNOWN_ERROR, "This distribution package are not installed!") + + # Check Dp depex + if not Dep.CheckDpDepexForRemove(Guid, Version): + print "Some packages/modules are depending on this distribution package, do you really want to remove it?" + print "Press Y to delete all files or press other keys to quit:" + Input = Input = sys.stdin.readline() + Input = Input.replace('\r', '').replace('\n', '') + if Input.upper() != 'Y': + EdkLogger.error("RmPkg", UNKNOWN_ERROR, "User interrupt") + + # Remove all files + if not Options.Yes: + print "All files of the distribution package will be removed, do you want to continue?" + print "Press Y to remove all files or press other keys to quit:" + Input = Input = sys.stdin.readline() + Input = Input.replace('\r', '').replace('\n', '') + if Input.upper() != 'Y': + EdkLogger.error("RmPkg", UNKNOWN_ERROR, "User interrupt") + + # Remove all files + MissingFileList = [] + for Item in Db.GetDpFileList(Guid, Version): + if os.path.isfile(Item): + print "Removing file [%s] ..." % Item + os.remove(Item) + else: + MissingFileList.append(Item) + + # Remove all empty dirs of package + for Item in Db.GetPackageListFromDp(Guid, Version): + Dir = os.path.dirname(Item[2]) + RemoveEmptyDirs(Dir) + + # Remove all empty dirs of module + for Item in Db.GetStandaloneModuleInstallPathListFromDp(Guid, Version): + Dir = os.path.dirname(Item) + RemoveEmptyDirs(Dir) + + # update database + EdkLogger.quiet("Update Distribution Package Database ...") + Db.RemoveDpObj(Guid, Version) + EdkLogger.quiet("DONE") + + except FatalError, X: + if Options and Options.LogLevel < EdkLogger.DEBUG_9: + EdkLogger.quiet("(Python %s on %s) " % (platform.python_version(), sys.platform) + traceback.format_exc()) + ReturnCode = X.args[0] + except KeyboardInterrupt: + ReturnCode = ABORT_ERROR + if Options and Options.LogLevel < EdkLogger.DEBUG_9: + EdkLogger.quiet("(Python %s on %s) " % (platform.python_version(), sys.platform) + traceback.format_exc()) + except: + EdkLogger.error( + "\nRmPkg", + CODE_ERROR, + "Unknown fatal error when removing package", + ExtraData="\n(Please send email to dev@buildtools.tianocore.org for help, attaching following call stack trace!)\n", + RaiseError=False + ) + EdkLogger.quiet("(Python %s on %s) " % (platform.python_version(), sys.platform) + traceback.format_exc()) + ReturnCode = CODE_ERROR + finally: + Progressor.Abort() + +if __name__ == '__main__': + sys.exit(Main()) diff --git a/BaseTools/Source/Python/Table/Table.py b/BaseTools/Source/Python/Table/Table.py new file mode 100644 index 0000000000..9a9657a4b3 --- /dev/null +++ b/BaseTools/Source/Python/Table/Table.py @@ -0,0 +1,120 @@ +## @file +# This file is used to create/update/query/erase a common table +# +# Copyright (c) 2008, 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. +# + +## +# Import Modules +# +import Common.EdkLogger as EdkLogger + +## TableFile +# +# This class defined a common table +# +# @param object: Inherited from object class +# +# @param Cursor: Cursor of the database +# @param TableName: Name of the table +# +class Table(object): + def __init__(self, Cursor): + self.Cur = Cursor + self.Table = '' + self.ID = 0 + + ## Create table + # + # Create a table + # + def Create(self, SqlCommand): + self.Cur.execute(SqlCommand) + self.ID = 0 + EdkLogger.verbose(SqlCommand + " ... DONE!") + + ## Insert table + # + # Insert a record into a table + # + def Insert(self, SqlCommand): + self.Exec(SqlCommand) + + ## Query table + # + # Query all records of the table + # + def Query(self): + EdkLogger.verbose("\nQuery tabel %s started ..." % self.Table) + SqlCommand = """select * from %s""" % self.Table + self.Cur.execute(SqlCommand) + for Rs in self.Cur: + EdkLogger.verbose(str(Rs)) + + TotalCount = self.GetCount() + EdkLogger.verbose("*** Total %s records in table %s ***" % (TotalCount, self.Table) ) + EdkLogger.verbose("Query tabel %s DONE!" % self.Table) + + ## Drop a table + # + # Drop the table + # + def Drop(self): + SqlCommand = """drop table IF EXISTS %s""" % self.Table + self.Cur.execute(SqlCommand) + EdkLogger.verbose("Drop tabel %s ... DONE!" % self.Table) + + ## Get count + # + # Get a count of all records of the table + # + # @retval Count: Total count of all records + # + def GetCount(self): + SqlCommand = """select count(ID) from %s""" % self.Table + self.Cur.execute(SqlCommand) + for Item in self.Cur: + return Item[0] + + ## Generate ID + # + # Generate an ID if input ID is -1 + # + # @param ID: Input ID + # + # @retval ID: New generated ID + # + def GenerateID(self, ID): + if ID == -1: + self.ID = self.ID + 1 + + return self.ID + + ## Init the ID of the table + # + # Init the ID of the table + # + def InitID(self): + self.ID = self.GetCount() + + ## Exec + # + # Exec Sql Command, return result + # + # @param SqlCommand: The SqlCommand to be executed + # + # @retval RecordSet: The result after executed + # + def Exec(self, SqlCommand): + EdkLogger.debug(4, "SqlCommand: %s" % SqlCommand) + self.Cur.execute(SqlCommand) + RecordSet = self.Cur.fetchall() + EdkLogger.debug(4, "RecordSet: %s" % RecordSet) + return RecordSet diff --git a/BaseTools/Source/Python/Table/TableDataModel.py b/BaseTools/Source/Python/Table/TableDataModel.py new file mode 100644 index 0000000000..1e5fe47af1 --- /dev/null +++ b/BaseTools/Source/Python/Table/TableDataModel.py @@ -0,0 +1,95 @@ +## @file +# This file is used to create/update/query/erase table for data models +# +# Copyright (c) 2008, 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. +# + +## +# Import Modules +# +import Common.EdkLogger as EdkLogger +import CommonDataClass.DataClass as DataClass +from Table import Table +from Common.String import ConvertToSqlString + +## TableDataModel +# +# This class defined a table used for data model +# +# @param object: Inherited from object class +# +# +class TableDataModel(Table): + def __init__(self, Cursor): + Table.__init__(self, Cursor) + self.Table = 'DataModel' + + ## Create table + # + # Create table DataModel + # + # @param ID: ID of a ModelType + # @param CrossIndex: CrossIndex of a ModelType + # @param Name: Name of a ModelType + # @param Description: Description of a ModelType + # + def Create(self): + SqlCommand = """create table IF NOT EXISTS %s (ID INTEGER PRIMARY KEY, + CrossIndex INTEGER NOT NULL, + Name VARCHAR NOT NULL, + Description VARCHAR + )""" % self.Table + Table.Create(self, SqlCommand) + + ## Insert table + # + # Insert a record into table DataModel + # + # @param ID: ID of a ModelType + # @param CrossIndex: CrossIndex of a ModelType + # @param Name: Name of a ModelType + # @param Description: Description of a ModelType + # + def Insert(self, CrossIndex, Name, Description): + self.ID = self.ID + 1 + (Name, Description) = ConvertToSqlString((Name, Description)) + SqlCommand = """insert into %s values(%s, %s, '%s', '%s')""" % (self.Table, self.ID, CrossIndex, Name, Description) + Table.Insert(self, SqlCommand) + + return self.ID + + ## Init table + # + # Create all default records of table DataModel + # + def InitTable(self): + EdkLogger.verbose("\nInitialize table DataModel started ...") + for Item in DataClass.MODEL_LIST: + CrossIndex = Item[1] + Name = Item[0] + Description = Item[0] + self.Insert(CrossIndex, Name, Description) + EdkLogger.verbose("Initialize table DataModel ... DONE!") + + ## Get CrossIndex + # + # Get a model's cross index from its name + # + # @param ModelName: Name of the model + # @retval CrossIndex: CrossIndex of the model + # + def GetCrossIndex(self, ModelName): + CrossIndex = -1 + SqlCommand = """select CrossIndex from DataModel where name = '""" + ModelName + """'""" + self.Cur.execute(SqlCommand) + for Item in self.Cur: + CrossIndex = Item[0] + + return CrossIndex diff --git a/BaseTools/Source/Python/Table/TableDec.py b/BaseTools/Source/Python/Table/TableDec.py new file mode 100644 index 0000000000..f570fd1d10 --- /dev/null +++ b/BaseTools/Source/Python/Table/TableDec.py @@ -0,0 +1,108 @@ +## @file +# This file is used to create/update/query/erase table for dec datas +# +# Copyright (c) 2008, 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. +# + +## +# Import Modules +# +import Common.EdkLogger as EdkLogger +import CommonDataClass.DataClass as DataClass +from Table import Table +from Common.String import ConvertToSqlString + +## TableDec +# +# This class defined a table used for data model +# +# @param object: Inherited from object class +# +# +class TableDec(Table): + def __init__(self, Cursor): + Table.__init__(self, Cursor) + self.Table = 'Dec' + + ## Create table + # + # Create table Dec + # + # @param ID: ID of a Dec item + # @param Model: Model of a Dec item + # @param Value1: Value1 of a Dec item + # @param Value2: Value2 of a Dec item + # @param Value3: Value3 of a Dec item + # @param Arch: Arch of a Dec item + # @param BelongsToItem: The item belongs to which another item + # @param BelongsToFile: The item belongs to which dsc file + # @param StartLine: StartLine of a Dec item + # @param StartColumn: StartColumn of a Dec item + # @param EndLine: EndLine of a Dec item + # @param EndColumn: EndColumn of a Dec item + # @param Enabled: If this item enabled + # + def Create(self): + SqlCommand = """create table IF NOT EXISTS %s (ID INTEGER PRIMARY KEY, + Model INTEGER NOT NULL, + Value1 VARCHAR NOT NULL, + Value2 VARCHAR, + Value3 VARCHAR, + Arch VarCHAR, + BelongsToItem SINGLE NOT NULL, + BelongsToFile SINGLE NOT NULL, + StartLine INTEGER NOT NULL, + StartColumn INTEGER NOT NULL, + EndLine INTEGER NOT NULL, + EndColumn INTEGER NOT NULL, + Enabled INTEGER DEFAULT 0 + )""" % self.Table + Table.Create(self, SqlCommand) + + ## Insert table + # + # Insert a record into table Dec + # + # @param ID: ID of a Dec item + # @param Model: Model of a Dec item + # @param Value1: Value1 of a Dec item + # @param Value2: Value2 of a Dec item + # @param Value3: Value3 of a Dec item + # @param Arch: Arch of a Dec item + # @param BelongsToItem: The item belongs to which another item + # @param BelongsToFile: The item belongs to which dsc file + # @param StartLine: StartLine of a Dec item + # @param StartColumn: StartColumn of a Dec item + # @param EndLine: EndLine of a Dec item + # @param EndColumn: EndColumn of a Dec item + # @param Enabled: If this item enabled + # + def Insert(self, Model, Value1, Value2, Value3, Value4, Value5, Arch, BelongsToItem, BelongsToFile, StartLine, StartColumn, EndLine, EndColumn, Enabled): + self.ID = self.ID + 1 + (Value1, Value2, Value3, Arch) = ConvertToSqlString((Value1, Value2, Value3, Arch)) + SqlCommand = """insert into %s values(%s, %s, '%s', '%s', '%s', '%s', %s, %s, %s, %s, %s, %s, %s)""" \ + % (self.Table, self.ID, Model, Value1, Value2, Value3, Arch, BelongsToItem, BelongsToFile, StartLine, StartColumn, EndLine, EndColumn, Enabled) + Table.Insert(self, SqlCommand) + + return self.ID + + ## Query table + # + # @param Model: The Model of Record + # + # @retval: A recordSet of all found records + # + def Query(self, Model): + SqlCommand = """select ID, Value1, Value2, Value3, Arch, BelongsToItem, BelongsToFile, StartLine from %s + where Model = %s + and Enabled > -1""" % (self.Table, Model) + EdkLogger.debug(4, "SqlCommand: %s" % SqlCommand) + self.Cur.execute(SqlCommand) + return self.Cur.fetchall() diff --git a/BaseTools/Source/Python/Table/TableDsc.py b/BaseTools/Source/Python/Table/TableDsc.py new file mode 100644 index 0000000000..62608a061a --- /dev/null +++ b/BaseTools/Source/Python/Table/TableDsc.py @@ -0,0 +1,108 @@ +## @file +# This file is used to create/update/query/erase table for dsc datas +# +# Copyright (c) 2008, 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. +# + +## +# Import Modules +# +import Common.EdkLogger as EdkLogger +import CommonDataClass.DataClass as DataClass +from Table import Table +from Common.String import ConvertToSqlString + +## TableDsc +# +# This class defined a table used for data model +# +# @param object: Inherited from object class +# +# +class TableDsc(Table): + def __init__(self, Cursor): + Table.__init__(self, Cursor) + self.Table = 'Dsc' + + ## Create table + # + # Create table Dsc + # + # @param ID: ID of a Dsc item + # @param Model: Model of a Dsc item + # @param Value1: Value1 of a Dsc item + # @param Value2: Value2 of a Dsc item + # @param Value3: Value3 of a Dsc item + # @param Arch: Arch of a Dsc item + # @param BelongsToItem: The item belongs to which another item + # @param BelongsToFile: The item belongs to which dsc file + # @param StartLine: StartLine of a Dsc item + # @param StartColumn: StartColumn of a Dsc item + # @param EndLine: EndLine of a Dsc item + # @param EndColumn: EndColumn of a Dsc item + # @param Enabled: If this item enabled + # + def Create(self): + SqlCommand = """create table IF NOT EXISTS %s (ID INTEGER PRIMARY KEY, + Model INTEGER NOT NULL, + Value1 VARCHAR NOT NULL, + Value2 VARCHAR, + Value3 VARCHAR, + Arch VarCHAR, + BelongsToItem SINGLE NOT NULL, + BelongsToFile SINGLE NOT NULL, + StartLine INTEGER NOT NULL, + StartColumn INTEGER NOT NULL, + EndLine INTEGER NOT NULL, + EndColumn INTEGER NOT NULL, + Enabled INTEGER DEFAULT 0 + )""" % self.Table + Table.Create(self, SqlCommand) + + ## Insert table + # + # Insert a record into table Dsc + # + # @param ID: ID of a Dsc item + # @param Model: Model of a Dsc item + # @param Value1: Value1 of a Dsc item + # @param Value2: Value2 of a Dsc item + # @param Value3: Value3 of a Dsc item + # @param Arch: Arch of a Dsc item + # @param BelongsToItem: The item belongs to which another item + # @param BelongsToFile: The item belongs to which dsc file + # @param StartLine: StartLine of a Dsc item + # @param StartColumn: StartColumn of a Dsc item + # @param EndLine: EndLine of a Dsc item + # @param EndColumn: EndColumn of a Dsc item + # @param Enabled: If this item enabled + # + def Insert(self, Model, Value1, Value2, Value3, Arch, BelongsToItem, BelongsToFile, StartLine, StartColumn, EndLine, EndColumn, Enabled): + self.ID = self.ID + 1 + (Value1, Value2, Value3, Arch) = ConvertToSqlString((Value1, Value2, Value3, Arch)) + SqlCommand = """insert into %s values(%s, %s, '%s', '%s', '%s', '%s', %s, %s, %s, %s, %s, %s, %s)""" \ + % (self.Table, self.ID, Model, Value1, Value2, Value3, Arch, BelongsToItem, BelongsToFile, StartLine, StartColumn, EndLine, EndColumn, Enabled) + Table.Insert(self, SqlCommand) + + return self.ID + + ## Query table + # + # @param Model: The Model of Record + # + # @retval: A recordSet of all found records + # + def Query(self, Model): + SqlCommand = """select ID, Value1, Value2, Value3, Arch, BelongsToItem, BelongsToFile, StartLine from %s + where Model = %s + and Enabled > -1""" % (self.Table, Model) + EdkLogger.debug(4, "SqlCommand: %s" % SqlCommand) + self.Cur.execute(SqlCommand) + return self.Cur.fetchall() diff --git a/BaseTools/Source/Python/Table/TableEotReport.py b/BaseTools/Source/Python/Table/TableEotReport.py new file mode 100644 index 0000000000..cdae3b2e39 --- /dev/null +++ b/BaseTools/Source/Python/Table/TableEotReport.py @@ -0,0 +1,76 @@ +## @file +# This file is used to create/update/query/erase table for ECC reports +# +# Copyright (c) 2008, 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. +# + +## +# Import Modules +# +import Common.EdkLogger as EdkLogger +import os, time +from Table import Table +from Common.String import ConvertToSqlString2 +import EotToolError as EotToolError +import EotGlobalData as EotGlobalData + +## TableReport +# +# This class defined a table used for data model +# +# @param object: Inherited from object class +# +# +class TableEotReport(Table): + def __init__(self, Cursor): + Table.__init__(self, Cursor) + self.Table = 'Report' + + ## Create table + # + # Create table report + # + # + def Create(self): + SqlCommand = """create table IF NOT EXISTS %s (ID INTEGER PRIMARY KEY, + ModuleID INTEGER DEFAULT -1, + ModuleName TEXT DEFAULT '', + ModuleGuid TEXT DEFAULT '', + SourceFileID INTEGER DEFAULT -1, + SourceFileFullPath TEXT DEFAULT '', + ItemName TEXT DEFAULT '', + ItemType TEXT DEFAULT '', + ItemMode TEXT DEFAULT '', + GuidName TEXT DEFAULT '', + GuidMacro TEXT DEFAULT '', + GuidValue TEXT DEFAULT '', + BelongsToFunction TEXT DEFAULT '', + Enabled INTEGER DEFAULT 0 + )""" % self.Table + Table.Create(self, SqlCommand) + + ## Insert table + # + # Insert a record into table report + # + # + def Insert(self, ModuleID = -1, ModuleName = '', ModuleGuid = '', SourceFileID = -1, SourceFileFullPath = '', \ + ItemName = '', ItemType = '', ItemMode = '', GuidName = '', GuidMacro = '', GuidValue = '', BelongsToFunction = '', Enabled = 0): + self.ID = self.ID + 1 + SqlCommand = """insert into %s values(%s, %s, '%s', '%s', %s, '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', %s)""" \ + % (self.Table, self.ID, ModuleID, ModuleName, ModuleGuid, SourceFileID, SourceFileFullPath, \ + ItemName, ItemType, ItemMode, GuidName, GuidMacro, GuidValue, BelongsToFunction, Enabled) + Table.Insert(self, SqlCommand) + + def GetMaxID(self): + SqlCommand = """select max(ID) from %s""" % self.Table + self.Cur.execute(SqlCommand) + for Item in self.Cur: + return Item[0] \ No newline at end of file diff --git a/BaseTools/Source/Python/Table/TableFdf.py b/BaseTools/Source/Python/Table/TableFdf.py new file mode 100644 index 0000000000..317bd4149b --- /dev/null +++ b/BaseTools/Source/Python/Table/TableFdf.py @@ -0,0 +1,108 @@ +## @file +# This file is used to create/update/query/erase table for fdf datas +# +# Copyright (c) 2008, 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. +# + +## +# Import Modules +# +import Common.EdkLogger as EdkLogger +import CommonDataClass.DataClass as DataClass +from Table import Table +from Common.String import ConvertToSqlString + +## TableFdf +# +# This class defined a table used for data model +# +# @param object: Inherited from object class +# +# +class TableFdf(Table): + def __init__(self, Cursor): + Table.__init__(self, Cursor) + self.Table = 'Fdf' + + ## Create table + # + # Create table Fdf + # + # @param ID: ID of a Fdf item + # @param Model: Model of a Fdf item + # @param Value1: Value1 of a Fdf item + # @param Value2: Value2 of a Fdf item + # @param Value3: Value3 of a Fdf item + # @param Arch: Arch of a Fdf item + # @param BelongsToItem: The item belongs to which another item + # @param BelongsToFile: The item belongs to which fdf file + # @param StartLine: StartLine of a Fdf item + # @param StartColumn: StartColumn of a Fdf item + # @param EndLine: EndLine of a Fdf item + # @param EndColumn: EndColumn of a Fdf item + # @param Enabled: If this item enabled + # + def Create(self): + SqlCommand = """create table IF NOT EXISTS %s (ID INTEGER PRIMARY KEY, + Model INTEGER NOT NULL, + Value1 VARCHAR NOT NULL, + Value2 VARCHAR, + Value3 VARCHAR, + Arch VarCHAR, + BelongsToItem SINGLE NOT NULL, + BelongsToFile SINGLE NOT NULL, + StartLine INTEGER NOT NULL, + StartColumn INTEGER NOT NULL, + EndLine INTEGER NOT NULL, + EndColumn INTEGER NOT NULL, + Enabled INTEGER DEFAULT 0 + )""" % self.Table + Table.Create(self, SqlCommand) + + ## Insert table + # + # Insert a record into table Fdf + # + # @param ID: ID of a Fdf item + # @param Model: Model of a Fdf item + # @param Value1: Value1 of a Fdf item + # @param Value2: Value2 of a Fdf item + # @param Value3: Value3 of a Fdf item + # @param Arch: Arch of a Fdf item + # @param BelongsToItem: The item belongs to which another item + # @param BelongsToFile: The item belongs to which fdf file + # @param StartLine: StartLine of a Fdf item + # @param StartColumn: StartColumn of a Fdf item + # @param EndLine: EndLine of a Fdf item + # @param EndColumn: EndColumn of a Fdf item + # @param Enabled: If this item enabled + # + def Insert(self, Model, Value1, Value2, Value3, Arch, BelongsToItem, BelongsToFile, StartLine, StartColumn, EndLine, EndColumn, Enabled): + self.ID = self.ID + 1 + (Value1, Value2, Value3, Arch) = ConvertToSqlString((Value1, Value2, Value3, Arch)) + SqlCommand = """insert into %s values(%s, %s, '%s', '%s', '%s', '%s', %s, %s, %s, %s, %s, %s, %s)""" \ + % (self.Table, self.ID, Model, Value1, Value2, Value3, Arch, BelongsToItem, BelongsToFile, StartLine, StartColumn, EndLine, EndColumn, Enabled) + Table.Insert(self, SqlCommand) + + return self.ID + + ## Query table + # + # @param Model: The Model of Record + # + # @retval: A recordSet of all found records + # + def Query(self, Model): + SqlCommand = """select ID, Value1, Value2, Value3, Arch, BelongsToItem, BelongsToFile, StartLine from %s + where Model = %s + and Enabled > -1""" % (self.Table, Model) + EdkLogger.debug(4, "SqlCommand: %s" % SqlCommand) + self.Cur.execute(SqlCommand) + return self.Cur.fetchall() diff --git a/BaseTools/Source/Python/Table/TableFile.py b/BaseTools/Source/Python/Table/TableFile.py new file mode 100644 index 0000000000..9be64942ec --- /dev/null +++ b/BaseTools/Source/Python/Table/TableFile.py @@ -0,0 +1,91 @@ +## @file +# This file is used to create/update/query/erase table for files +# +# Copyright (c) 2008, 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. +# + +## +# Import Modules +# +import Common.EdkLogger as EdkLogger +from Table import Table +from Common.String import ConvertToSqlString +import os +from CommonDataClass.DataClass import FileClass + +## TableFile +# +# This class defined a table used for file +# +# @param object: Inherited from object class +# +class TableFile(Table): + def __init__(self, Cursor): + Table.__init__(self, Cursor) + self.Table = 'File' + + ## Create table + # + # Create table File + # + # @param ID: ID of a File + # @param Name: Name of a File + # @param ExtName: ExtName of a File + # @param Path: Path of a File + # @param FullPath: FullPath of a File + # @param Model: Model of a File + # @param TimeStamp: TimeStamp of a File + # + def Create(self): + SqlCommand = """create table IF NOT EXISTS %s (ID INTEGER PRIMARY KEY, + Name VARCHAR NOT NULL, + ExtName VARCHAR, + Path VARCHAR, + FullPath VARCHAR NOT NULL, + Model INTEGER DEFAULT 0, + TimeStamp VARCHAR NOT NULL + )""" % self.Table + Table.Create(self, SqlCommand) + + ## Insert table + # + # Insert a record into table File + # + # @param ID: ID of a File + # @param Name: Name of a File + # @param ExtName: ExtName of a File + # @param Path: Path of a File + # @param FullPath: FullPath of a File + # @param Model: Model of a File + # @param TimeStamp: TimeStamp of a File + # + def Insert(self, Name, ExtName, Path, FullPath, Model, TimeStamp): + self.ID = self.ID + 1 + (Name, ExtName, Path, FullPath) = ConvertToSqlString((Name, ExtName, Path, FullPath)) + SqlCommand = """insert into %s values(%s, '%s', '%s', '%s', '%s', %s, '%s')""" \ + % (self.Table, self.ID, Name, ExtName, Path, FullPath, Model, TimeStamp) + Table.Insert(self, SqlCommand) + + return self.ID + ## InsertFile + # + # Insert one file to table + # + # @param FileFullPath: The full path of the file + # @param Model: The model of the file + # + # @retval FileID: The ID after record is inserted + # + def InsertFile(self, FileFullPath, Model): + (Filepath, Name) = os.path.split(FileFullPath) + (Root, Ext) = os.path.splitext(FileFullPath) + TimeStamp = os.stat(FileFullPath)[8] + File = FileClass(-1, Name, Ext, Filepath, FileFullPath, Model, '', [], [], []) + return self.Insert(File.Name, File.ExtName, File.Path, File.FullPath, File.Model, TimeStamp) diff --git a/BaseTools/Source/Python/Table/TableFunction.py b/BaseTools/Source/Python/Table/TableFunction.py new file mode 100644 index 0000000000..c013d0d2fe --- /dev/null +++ b/BaseTools/Source/Python/Table/TableFunction.py @@ -0,0 +1,95 @@ +## @file +# This file is used to create/update/query/erase table for functions +# +# Copyright (c) 2008, 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. +# + +## +# Import Modules +# +import Common.EdkLogger as EdkLogger +from Table import Table +from Common.String import ConvertToSqlString + +## TableFunction +# +# This class defined a table used for function +# +# @param Table: Inherited from Table class +# +class TableFunction(Table): + def __init__(self, Cursor): + Table.__init__(self, Cursor) + self.Table = 'Function' + + ## Create table + # + # Create table Function + # + # @param ID: ID of a Function + # @param Header: Header of a Function + # @param Modifier: Modifier of a Function + # @param Name: Name of a Function + # @param ReturnStatement: ReturnStatement of a Funciont + # @param StartLine: StartLine of a Function + # @param StartColumn: StartColumn of a Function + # @param EndLine: EndLine of a Function + # @param EndColumn: EndColumn of a Function + # @param BodyStartLine: StartLine of a Function body + # @param BodyStartColumn: StartColumn of a Function body + # @param BelongsToFile: The Function belongs to which file + # @param FunNameStartLine: StartLine of a Function name + # @param FunNameStartColumn: StartColumn of a Function name + # + def Create(self): + SqlCommand = """create table IF NOT EXISTS %s (ID INTEGER PRIMARY KEY, + Header TEXT, + Modifier VARCHAR, + Name VARCHAR NOT NULL, + ReturnStatement VARCHAR, + StartLine INTEGER NOT NULL, + StartColumn INTEGER NOT NULL, + EndLine INTEGER NOT NULL, + EndColumn INTEGER NOT NULL, + BodyStartLine INTEGER NOT NULL, + BodyStartColumn INTEGER NOT NULL, + BelongsToFile SINGLE NOT NULL, + FunNameStartLine INTEGER NOT NULL, + FunNameStartColumn INTEGER NOT NULL + )""" % self.Table + Table.Create(self, SqlCommand) + + ## Insert table + # + # Insert a record into table Function + # + # @param ID: ID of a Function + # @param Header: Header of a Function + # @param Modifier: Modifier of a Function + # @param Name: Name of a Function + # @param ReturnStatement: ReturnStatement of a Funciont + # @param StartLine: StartLine of a Function + # @param StartColumn: StartColumn of a Function + # @param EndLine: EndLine of a Function + # @param EndColumn: EndColumn of a Function + # @param BodyStartLine: StartLine of a Function body + # @param BodyStartColumn: StartColumn of a Function body + # @param BelongsToFile: The Function belongs to which file + # @param FunNameStartLine: StartLine of a Function name + # @param FunNameStartColumn: StartColumn of a Function name + # + def Insert(self, Header, Modifier, Name, ReturnStatement, StartLine, StartColumn, EndLine, EndColumn, BodyStartLine, BodyStartColumn, BelongsToFile, FunNameStartLine, FunNameStartColumn): + self.ID = self.ID + 1 + (Header, Modifier, Name, ReturnStatement) = ConvertToSqlString((Header, Modifier, Name, ReturnStatement)) + SqlCommand = """insert into %s values(%s, '%s', '%s', '%s', '%s', %s, %s, %s, %s, %s, %s, %s, %s, %s)""" \ + % (self.Table, self.ID, Header, Modifier, Name, ReturnStatement, StartLine, StartColumn, EndLine, EndColumn, BodyStartLine, BodyStartColumn, BelongsToFile, FunNameStartLine, FunNameStartColumn) + Table.Insert(self, SqlCommand) + + return self.ID diff --git a/BaseTools/Source/Python/Table/TableIdentifier.py b/BaseTools/Source/Python/Table/TableIdentifier.py new file mode 100644 index 0000000000..3cf33f20e2 --- /dev/null +++ b/BaseTools/Source/Python/Table/TableIdentifier.py @@ -0,0 +1,90 @@ +## @file +# This file is used to create/update/query/erase table for Identifiers +# +# Copyright (c) 2008, 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. +# + +## +# Import Modules +# +import Common.EdkLogger as EdkLogger +from Common.String import ConvertToSqlString +from Table import Table + +## TableIdentifier +# +# This class defined a table used for Identifier +# +# @param object: Inherited from object class +# +# +class TableIdentifier(Table): + def __init__(self, Cursor): + Table.__init__(self, Cursor) + self.Table = 'Identifier' + + ## Create table + # + # Create table Identifier + # + # @param ID: ID of a Identifier + # @param Modifier: Modifier of a Identifier + # @param Type: Type of a Identifier + # @param Name: Name of a Identifier + # @param Value: Value of a Identifier + # @param Model: Model of a Identifier + # @param BelongsToFile: The Identifier belongs to which file + # @param BelongsToFunction: The Identifier belongs to which function + # @param StartLine: StartLine of a Identifier + # @param StartColumn: StartColumn of a Identifier + # @param EndLine: EndLine of a Identifier + # @param EndColumn: EndColumn of a Identifier + # + def Create(self): + SqlCommand = """create table IF NOT EXISTS %s(ID INTEGER PRIMARY KEY, + Modifier VARCHAR, + Type VARCHAR, + Name VARCHAR NOT NULL, + Value VARCHAR NOT NULL, + Model INTEGER NOT NULL, + BelongsToFile SINGLE NOT NULL, + BelongsToFunction SINGLE DEFAULT -1, + StartLine INTEGER NOT NULL, + StartColumn INTEGER NOT NULL, + EndLine INTEGER NOT NULL, + EndColumn INTEGER NOT NULL + )""" % self.Table + Table.Create(self, SqlCommand) + + ## Insert table + # + # Insert a record into table Identifier + # + # @param ID: ID of a Identifier + # @param Modifier: Modifier of a Identifier + # @param Type: Type of a Identifier + # @param Name: Name of a Identifier + # @param Value: Value of a Identifier + # @param Model: Model of a Identifier + # @param BelongsToFile: The Identifier belongs to which file + # @param BelongsToFunction: The Identifier belongs to which function + # @param StartLine: StartLine of a Identifier + # @param StartColumn: StartColumn of a Identifier + # @param EndLine: EndLine of a Identifier + # @param EndColumn: EndColumn of a Identifier + # + def Insert(self, Modifier, Type, Name, Value, Model, BelongsToFile, BelongsToFunction, StartLine, StartColumn, EndLine, EndColumn): + self.ID = self.ID + 1 + (Modifier, Type, Name, Value) = ConvertToSqlString((Modifier, Type, Name, Value)) + SqlCommand = """insert into %s values(%s, '%s', '%s', '%s', '%s', %s, %s, %s, %s, %s, %s, %s)""" \ + % (self.Table, self.ID, Modifier, Type, Name, Value, Model, BelongsToFile, BelongsToFunction, StartLine, StartColumn, EndLine, EndColumn) + Table.Insert(self, SqlCommand) + + return self.ID \ No newline at end of file diff --git a/BaseTools/Source/Python/Table/TableInf.py b/BaseTools/Source/Python/Table/TableInf.py new file mode 100644 index 0000000000..65ca1ce25c --- /dev/null +++ b/BaseTools/Source/Python/Table/TableInf.py @@ -0,0 +1,114 @@ +## @file +# This file is used to create/update/query/erase table for inf datas +# +# Copyright (c) 2008, 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. +# + +## +# Import Modules +# +import Common.EdkLogger as EdkLogger +import CommonDataClass.DataClass as DataClass +from Table import Table +from Common.String import ConvertToSqlString + +## TableInf +# +# This class defined a table used for data model +# +# @param object: Inherited from object class +# +# +class TableInf(Table): + def __init__(self, Cursor): + Table.__init__(self, Cursor) + self.Table = 'Inf' + + ## Create table + # + # Create table Inf + # + # @param ID: ID of a Inf item + # @param Model: Model of a Inf item + # @param Value1: Value1 of a Inf item + # @param Value2: Value2 of a Inf item + # @param Value3: Value3 of a Inf item + # @param Value4: Value4 of a Inf item + # @param Value5: Value5 of a Inf item + # @param Arch: Arch of a Inf item + # @param BelongsToItem: The item belongs to which another item + # @param BelongsToFile: The item belongs to which dsc file + # @param StartLine: StartLine of a Inf item + # @param StartColumn: StartColumn of a Inf item + # @param EndLine: EndLine of a Inf item + # @param EndColumn: EndColumn of a Inf item + # @param Enabled: If this item enabled + # + def Create(self): + SqlCommand = """create table IF NOT EXISTS %s (ID INTEGER PRIMARY KEY, + Model INTEGER NOT NULL, + Value1 VARCHAR NOT NULL, + Value2 VARCHAR, + Value3 VARCHAR, + Value4 VARCHAR, + Value5 VARCHAR, + Arch VarCHAR, + BelongsToItem SINGLE NOT NULL, + BelongsToFile SINGLE NOT NULL, + StartLine INTEGER NOT NULL, + StartColumn INTEGER NOT NULL, + EndLine INTEGER NOT NULL, + EndColumn INTEGER NOT NULL, + Enabled INTEGER DEFAULT 0 + )""" % self.Table + Table.Create(self, SqlCommand) + + ## Insert table + # + # Insert a record into table Inf + # + # @param ID: ID of a Inf item + # @param Model: Model of a Inf item + # @param Value1: Value1 of a Inf item + # @param Value2: Value2 of a Inf item + # @param Value3: Value3 of a Inf item + # @param Value4: Value4 of a Inf item + # @param Value5: Value5 of a Inf item + # @param Arch: Arch of a Inf item + # @param BelongsToItem: The item belongs to which another item + # @param BelongsToFile: The item belongs to which dsc file + # @param StartLine: StartLine of a Inf item + # @param StartColumn: StartColumn of a Inf item + # @param EndLine: EndLine of a Inf item + # @param EndColumn: EndColumn of a Inf item + # @param Enabled: If this item enabled + # + def Insert(self, Model, Value1, Value2, Value3, Value4, Value5, Arch, BelongsToItem, BelongsToFile, StartLine, StartColumn, EndLine, EndColumn, Enabled): + self.ID = self.ID + 1 + (Value1, Value2, Value3, Value4, Value5, Arch) = ConvertToSqlString((Value1, Value2, Value3, Value4, Value5, Arch)) + SqlCommand = """insert into %s values(%s, %s, '%s', '%s', '%s', '%s', '%s', '%s', %s, %s, %s, %s, %s, %s, %s)""" \ + % (self.Table, self.ID, Model, Value1, Value2, Value3, Value4, Value5, Arch, BelongsToItem, BelongsToFile, StartLine, StartColumn, EndLine, EndColumn, Enabled) + Table.Insert(self, SqlCommand) + + return self.ID + + ## Query table + # + # @param Model: The Model of Record + # + # @retval: A recordSet of all found records + # + def Query(self, Model): + SqlCommand = """select ID, Value1, Value2, Value3, Arch, BelongsToItem, BelongsToFile, StartLine from %s + where Model = %s + and Enabled > -1""" % (self.Table, Model) + EdkLogger.debug(4, "SqlCommand: %s" % SqlCommand) + self.Cur.execute(SqlCommand) + return self.Cur.fetchall() diff --git a/BaseTools/Source/Python/Table/TablePcd.py b/BaseTools/Source/Python/Table/TablePcd.py new file mode 100644 index 0000000000..ba91d175f0 --- /dev/null +++ b/BaseTools/Source/Python/Table/TablePcd.py @@ -0,0 +1,90 @@ +## @file +# This file is used to create/update/query/erase table for pcds +# +# Copyright (c) 2008, 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. +# + +## +# Import Modules +# +import Common.EdkLogger as EdkLogger +from Table import Table +from Common.String import ConvertToSqlString + +## TablePcd +# +# This class defined a table used for pcds +# +# @param object: Inherited from object class +# +# +class TablePcd(Table): + def __init__(self, Cursor): + Table.__init__(self, Cursor) + self.Table = 'Pcd' + + ## Create table + # + # Create table Pcd + # + # @param ID: ID of a Pcd + # @param CName: CName of a Pcd + # @param TokenSpaceGuidCName: TokenSpaceGuidCName of a Pcd + # @param Token: Token of a Pcd + # @param DatumType: DatumType of a Pcd + # @param Model: Model of a Pcd + # @param BelongsToFile: The Pcd belongs to which file + # @param BelongsToFunction: The Pcd belongs to which function + # @param StartLine: StartLine of a Pcd + # @param StartColumn: StartColumn of a Pcd + # @param EndLine: EndLine of a Pcd + # @param EndColumn: EndColumn of a Pcd + # + def Create(self): + SqlCommand = """create table IF NOT EXISTS %s (ID INTEGER PRIMARY KEY, + CName VARCHAR NOT NULL, + TokenSpaceGuidCName VARCHAR NOT NULL, + Token INTEGER, + DatumType VARCHAR, + Model INTEGER NOT NULL, + BelongsToFile SINGLE NOT NULL, + BelongsToFunction SINGLE DEFAULT -1, + StartLine INTEGER NOT NULL, + StartColumn INTEGER NOT NULL, + EndLine INTEGER NOT NULL, + EndColumn INTEGER NOT NULL + )""" % self.Table + Table.Create(self, SqlCommand) + + ## Insert table + # + # Insert a record into table Pcd + # + # @param ID: ID of a Pcd + # @param CName: CName of a Pcd + # @param TokenSpaceGuidCName: TokenSpaceGuidCName of a Pcd + # @param Token: Token of a Pcd + # @param DatumType: DatumType of a Pcd + # @param Model: Model of a Pcd + # @param BelongsToFile: The Pcd belongs to which file + # @param BelongsToFunction: The Pcd belongs to which function + # @param StartLine: StartLine of a Pcd + # @param StartColumn: StartColumn of a Pcd + # @param EndLine: EndLine of a Pcd + # @param EndColumn: EndColumn of a Pcd + # + def Insert(self, CName, TokenSpaceGuidCName, Token, DatumType, Model, BelongsToFile, BelongsToFunction, StartLine, StartColumn, EndLine, EndColumn): + self.ID = self.ID + 1 + (CName, TokenSpaceGuidCName, DatumType) = ConvertToSqlString((CName, TokenSpaceGuidCName, DatumType)) + SqlCommand = """insert into %s values(%s, '%s', '%s', %s, '%s', %s, %s, %s, %s, %s, %s, %s)""" \ + % (self.Table, self.ID, CName, TokenSpaceGuidCName, Token, DatumType, Model, BelongsToFile, BelongsToFunction, StartLine, StartColumn, EndLine, EndColumn) + Table.Insert(self, SqlCommand) + + return self.ID \ No newline at end of file diff --git a/BaseTools/Source/Python/Table/TableQuery.py b/BaseTools/Source/Python/Table/TableQuery.py new file mode 100644 index 0000000000..9a9a66ccb6 --- /dev/null +++ b/BaseTools/Source/Python/Table/TableQuery.py @@ -0,0 +1,66 @@ +## @file +# This file is used to create/update/query/erase table for Queries +# +# Copyright (c) 2008, 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. +# + +## +# Import Modules +# +import Common.EdkLogger as EdkLogger +from Common.String import ConvertToSqlString +from Table import Table + +## TableQuery +# +# This class defined a table used for Query +# +# @param object: Inherited from object class +# +# +class TableQuery(Table): + def __init__(self, Cursor): + Table.__init__(self, Cursor) + self.Table = 'Query' + + ## Create table + # + # Create table Query + # + # @param ID: ID of a Query + # @param Name: Modifier of a Query + # @param Value: Type of a Query + # @param Model: Model of a Query + # + def Create(self): + SqlCommand = """create table IF NOT EXISTS %s(ID INTEGER PRIMARY KEY, + Name TEXT DEFAULT '', + Value TEXT DEFAULT '', + Model INTEGER DEFAULT 0 + )""" % self.Table + Table.Create(self, SqlCommand) + + ## Insert table + # + # Insert a record into table Query + # + # @param ID: ID of a Query + # @param Name: Modifier of a Query + # @param Value: Type of a Query + # @param Model: Model of a Query + # + def Insert(self, Name, Value, Model): + self.ID = self.ID + 1 + SqlCommand = """insert into %s values(%s, '%s', '%s', %s)""" \ + % (self.Table, self.ID, Name, Value, Model) + Table.Insert(self, SqlCommand) + + return self.ID + \ No newline at end of file diff --git a/BaseTools/Source/Python/Table/TableReport.py b/BaseTools/Source/Python/Table/TableReport.py new file mode 100644 index 0000000000..042c1b7e9e --- /dev/null +++ b/BaseTools/Source/Python/Table/TableReport.py @@ -0,0 +1,123 @@ +## @file +# This file is used to create/update/query/erase table for ECC reports +# +# Copyright (c) 2008, 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. +# + +## +# Import Modules +# +import Common.EdkLogger as EdkLogger +import os, time +from Table import Table +from Common.String import ConvertToSqlString2 +import EccToolError as EccToolError +import EccGlobalData as EccGlobalData + +## TableReport +# +# This class defined a table used for data model +# +# @param object: Inherited from object class +# +# +class TableReport(Table): + def __init__(self, Cursor): + Table.__init__(self, Cursor) + self.Table = 'Report' + + ## Create table + # + # Create table report + # + # @param ID: ID of an Error + # @param ErrorID: ID of an Error TypeModel of a Report item + # @param OtherMsg: Other error message besides the standard error message + # @param BelongsToItem: The error belongs to which item + # @param Enabled: If this error enabled + # @param Corrected: if this error corrected + # + def Create(self): + SqlCommand = """create table IF NOT EXISTS %s (ID INTEGER PRIMARY KEY, + ErrorID INTEGER NOT NULL, + OtherMsg TEXT, + BelongsToTable TEXT NOT NULL, + BelongsToItem SINGLE NOT NULL, + Enabled INTEGER DEFAULT 0, + Corrected INTEGER DEFAULT -1 + )""" % self.Table + Table.Create(self, SqlCommand) + + ## Insert table + # + # Insert a record into table report + # + # @param ID: ID of an Error + # @param ErrorID: ID of an Error TypeModel of a report item + # @param OtherMsg: Other error message besides the standard error message + # @param BelongsToTable: The error item belongs to which table + # @param BelongsToItem: The error belongs to which item + # @param Enabled: If this error enabled + # @param Corrected: if this error corrected + # + def Insert(self, ErrorID, OtherMsg = '', BelongsToTable = '', BelongsToItem = -1, Enabled = 0, Corrected = -1): + self.ID = self.ID + 1 + SqlCommand = """insert into %s values(%s, %s, '%s', '%s', %s, %s, %s)""" \ + % (self.Table, self.ID, ErrorID, ConvertToSqlString2(OtherMsg), BelongsToTable, BelongsToItem, Enabled, Corrected) + Table.Insert(self, SqlCommand) + + return self.ID + + ## Query table + # + # @retval: A recordSet of all found records + # + def Query(self): + SqlCommand = """select ID, ErrorID, OtherMsg, BelongsToTable, BelongsToItem, Corrected from %s + where Enabled > -1 order by ErrorID, BelongsToItem""" % (self.Table) + return self.Exec(SqlCommand) + + ## Convert to CSV + # + # Get all enabled records from table report and save them to a .csv file + # + # @param Filename: To filename to save the report content + # + def ToCSV(self, Filename = 'Report.csv'): + try: + File = open(Filename, 'w+') + File.write("""No, Error Code, Error Message, File, LineNo, Other Error Message\n""") + RecordSet = self.Query() + Index = 0 + for Record in RecordSet: + Index = Index + 1 + ErrorID = Record[1] + OtherMsg = Record[2] + BelongsToTable = Record[3] + BelongsToItem = Record[4] + IsCorrected = Record[5] + SqlCommand = '' + if BelongsToTable == 'File': + SqlCommand = """select 0, FullPath from %s where ID = %s + """ % (BelongsToTable, BelongsToItem) + else: + SqlCommand = """select A.StartLine, B.FullPath from %s as A, File as B + where A.ID = %s and B.ID = A.BelongsToFile + """ % (BelongsToTable, BelongsToItem) + NewRecord = self.Exec(SqlCommand) + if NewRecord != []: + File.write("""%s,%s,"%s",%s,%s,"%s"\n""" % (Index, ErrorID, EccToolError.gEccErrorMessage[ErrorID], NewRecord[0][1], NewRecord[0][0], OtherMsg)) + + File.close() + except IOError: + NewFilename = 'Report_' + time.strftime("%Y%m%d_%H%M%S.csv", time.localtime()) + EdkLogger.warn("ECC", "The report file %s is locked by other progress, use %s instead!" % (Filename, NewFilename)) + self.ToCSV(NewFilename) + diff --git a/BaseTools/Source/Python/Table/__init__.py b/BaseTools/Source/Python/Table/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/BaseTools/Source/Python/TargetTool/TargetTool.py b/BaseTools/Source/Python/TargetTool/TargetTool.py new file mode 100644 index 0000000000..69cac95d4f --- /dev/null +++ b/BaseTools/Source/Python/TargetTool/TargetTool.py @@ -0,0 +1,261 @@ +# +# Copyright (c) 2007, 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. +# + +import os +import sys +import traceback +from optparse import OptionParser + +import Common.EdkLogger as EdkLogger +import Common.BuildToolError as BuildToolError +from Common.DataType import * + +# To Do 1.set clean, 2. add item, if the line is disabled. + +class TargetTool(): + def __init__(self, opt, args): + self.WorkSpace = os.path.normpath(os.getenv('WORKSPACE')) + self.Opt = opt + self.Arg = args[0] + self.FileName = os.path.normpath(os.path.join(self.WorkSpace, 'Conf', 'target.txt')) + if os.path.isfile(self.FileName) == False: + print "%s does not exist." % self.FileName + sys.exit(1) + self.TargetTxtDictionary = { + TAB_TAT_DEFINES_ACTIVE_PLATFORM : None, + TAB_TAT_DEFINES_TOOL_CHAIN_CONF : None, + TAB_TAT_DEFINES_MULTIPLE_THREAD : None, + TAB_TAT_DEFINES_MAX_CONCURRENT_THREAD_NUMBER : None, + TAB_TAT_DEFINES_TARGET : None, + TAB_TAT_DEFINES_TOOL_CHAIN_TAG : None, + TAB_TAT_DEFINES_TARGET_ARCH : None, + TAB_TAT_DEFINES_BUILD_RULE_CONF : None, + } + self.LoadTargetTxtFile(self.FileName) + + def LoadTargetTxtFile(self, filename): + if os.path.exists(filename) and os.path.isfile(filename): + return self.ConvertTextFileToDict(filename, '#', '=') + else: + raise ParseError('LoadTargetTxtFile() : No Target.txt file exists.') + return 1 + +# +# Convert a text file to a dictionary +# + def ConvertTextFileToDict(self, FileName, CommentCharacter, KeySplitCharacter): + """Convert a text file to a dictionary of (name:value) pairs.""" + try: + f = open(FileName,'r') + for Line in f: + if Line.startswith(CommentCharacter) or Line.strip() == '': + continue + LineList = Line.split(KeySplitCharacter,1) + if len(LineList) >= 2: + Key = LineList[0].strip() + if Key.startswith(CommentCharacter) == False and Key in self.TargetTxtDictionary.keys(): + if Key == TAB_TAT_DEFINES_ACTIVE_PLATFORM or Key == TAB_TAT_DEFINES_TOOL_CHAIN_CONF \ + or Key == TAB_TAT_DEFINES_MULTIPLE_THREAD or Key == TAB_TAT_DEFINES_MAX_CONCURRENT_THREAD_NUMBER \ + or Key == TAB_TAT_DEFINES_ACTIVE_MODULE: + self.TargetTxtDictionary[Key] = LineList[1].replace('\\', '/').strip() + elif Key == TAB_TAT_DEFINES_TARGET or Key == TAB_TAT_DEFINES_TARGET_ARCH \ + or Key == TAB_TAT_DEFINES_TOOL_CHAIN_TAG or Key == TAB_TAT_DEFINES_BUILD_RULE_CONF: + self.TargetTxtDictionary[Key] = LineList[1].split() + f.close() + return 0 + except: + last_type, last_value, last_tb = sys.exc_info() + traceback.print_exception(last_type, last_value, last_tb) + + def Print(self): + KeyList = self.TargetTxtDictionary.keys() + errMsg = '' + for Key in KeyList: + if type(self.TargetTxtDictionary[Key]) == type([]): + print "%-30s = %s" % (Key, ''.join(elem + ' ' for elem in self.TargetTxtDictionary[Key])) + elif self.TargetTxtDictionary[Key] == None: + errMsg += " Missing %s configuration information, please use TargetTool to set value!" % Key + os.linesep + else: + print "%-30s = %s" % (Key, self.TargetTxtDictionary[Key]) + + if errMsg != '': + print os.linesep + 'Warning:' + os.linesep + errMsg + + def RWFile(self, CommentCharacter, KeySplitCharacter, Num): + try: + fr = open(self.FileName, 'r') + fw = open(os.path.normpath(os.path.join(self.WorkSpace, 'Conf\\targetnew.txt')), 'w') + + existKeys = [] + for Line in fr: + if Line.startswith(CommentCharacter) or Line.strip() == '': + fw.write(Line) + else: + LineList = Line.split(KeySplitCharacter,1) + if len(LineList) >= 2: + Key = LineList[0].strip() + if Key.startswith(CommentCharacter) == False and Key in self.TargetTxtDictionary.keys(): + if Key not in existKeys: + existKeys.append(Key) + else: + print "Warning: Found duplicate key item in original configuration files!" + + if Num == 0: + Line = "%-30s = \n" % Key + else: + ret = GetConfigureKeyValue(self, Key) + if ret != None: + Line = ret + fw.write(Line) + for key in self.TargetTxtDictionary.keys(): + if key not in existKeys: + print "Warning: %s does not exist in original configuration file" % key + Line = GetConfigureKeyValue(self, key) + if Line == None: + Line = "%-30s = " % key + fw.write(Line) + + fr.close() + fw.close() + os.remove(self.FileName) + os.rename(os.path.normpath(os.path.join(self.WorkSpace, 'Conf\\targetnew.txt')), self.FileName) + + except: + last_type, last_value, last_tb = sys.exc_info() + traceback.print_exception(last_type, last_value, last_tb) + +def GetConfigureKeyValue(self, Key): + Line = None + if Key == TAB_TAT_DEFINES_ACTIVE_PLATFORM and self.Opt.DSCFILE != None: + dscFullPath = os.path.join(self.WorkSpace, self.Opt.DSCFILE) + if os.path.exists(dscFullPath): + Line = "%-30s = %s\n" % (Key, self.Opt.DSCFILE) + else: + EdkLogger.error("TagetTool", BuildToolError.FILE_NOT_FOUND, + "DSC file %s does not exist!" % self.Opt.DSCFILE, RaiseError=False) + elif Key == TAB_TAT_DEFINES_TOOL_CHAIN_CONF and self.Opt.TOOL_DEFINITION_FILE != None: + tooldefFullPath = os.path.join(self.WorkSpace, self.Opt.TOOL_DEFINITION_FILE) + if os.path.exists(tooldefFullPath): + Line = "%-30s = %s\n" % (Key, self.Opt.TOOL_DEFINITION_FILE) + else: + EdkLogger.error("TagetTool", BuildToolError.FILE_NOT_FOUND, + "Tooldef file %s does not exist!" % self.Opt.TOOL_DEFINITION_FILE, RaiseError=False) + elif Key == TAB_TAT_DEFINES_MULTIPLE_THREAD and self.Opt.NUM != None: + if self.Opt.NUM >= 2: + Line = "%-30s = %s\n" % (Key, 'Enable') + else: + Line = "%-30s = %s\n" % (Key, 'Disable') + elif Key == TAB_TAT_DEFINES_MAX_CONCURRENT_THREAD_NUMBER and self.Opt.NUM != None: + Line = "%-30s = %s\n" % (Key, str(self.Opt.NUM)) + elif Key == TAB_TAT_DEFINES_MULTIPLE_THREAD and self.Opt.ENABLE_MULTI_THREAD != None: + Line = "%-30s = %s\n" % (Key, self.Opt.ENABLE_MULTI_THREAD) + elif Key == TAB_TAT_DEFINES_TARGET and self.Opt.TARGET != None: + Line = "%-30s = %s\n" % (Key, ''.join(elem + ' ' for elem in self.Opt.TARGET)) + elif Key == TAB_TAT_DEFINES_TARGET_ARCH and self.Opt.TARGET_ARCH != None: + Line = "%-30s = %s\n" % (Key, ''.join(elem + ' ' for elem in self.Opt.TARGET_ARCH)) + elif Key == TAB_TAT_DEFINES_TOOL_CHAIN_TAG and self.Opt.TOOL_CHAIN_TAG != None: + Line = "%-30s = %s\n" % (Key, self.Opt.TOOL_CHAIN_TAG) + elif Key == TAB_TAT_DEFINES_BUILD_RULE_CONF and self.Opt.BUILD_RULE_FILE != None: + buildruleFullPath = os.path.join(self.WorkSpace, self.Opt.BUILD_RULE_FILE) + if os.path.exists(buildruleFullPath): + Line = "%-30s = %s\n" % (Key, self.Opt.BUILD_RULE_FILE) + else: + EdkLogger.error("TagetTool", BuildToolError.FILE_NOT_FOUND, + "Build rule file %s does not exist!" % self.Opt.BUILD_RULE_FILE, RaiseError=False) + return Line + +VersionNumber = "0.01" +__version__ = "%prog Version " + VersionNumber +__copyright__ = "Copyright (c) 2007, Intel Corporation All rights reserved." +__usage__ = "%prog [options] {args} \ +\nArgs: \ +\n Clean clean the all default configuration of target.txt. \ +\n Print print the all default configuration of target.txt. \ +\n Set replace the default configuration with expected value specified by option." + +gParamCheck = [] +def SingleCheckCallback(option, opt_str, value, parser): + if option not in gParamCheck: + setattr(parser.values, option.dest, value) + gParamCheck.append(option) + else: + parser.error("Option %s only allows one instance in command line!" % option) + +def RangeCheckCallback(option, opt_str, value, parser): + if option not in gParamCheck: + gParamCheck.append(option) + if value < 1 or value > 8: + parser.error("The count of multi-thread is not in valid range of 1 ~ 8.") + else: + setattr(parser.values, option.dest, value) + else: + parser.error("Option %s only allows one instance in command line!" % option) + +def MyOptionParser(): + parser = OptionParser(version=__version__,prog="TargetTool.exe",usage=__usage__,description=__copyright__) + parser.add_option("-a", "--arch", action="append", type="choice", choices=['IA32','X64','IPF','EBC', 'ARM','0'], dest="TARGET_ARCH", + help="ARCHS is one of list: IA32, X64, IPF, ARM or EBC, which replaces target.txt's TARGET_ARCH definition. To specify more archs, please repeat this option. 0 will clear this setting in target.txt and can't combine with other value.") + parser.add_option("-p", "--platform", action="callback", type="string", dest="DSCFILE", callback=SingleCheckCallback, + help="Specify a DSC file, which replace target.txt's ACTIVE_PLATFORM definition. 0 will clear this setting in target.txt and can't combine with other value.") + parser.add_option("-c", "--tooldef", action="callback", type="string", dest="TOOL_DEFINITION_FILE", callback=SingleCheckCallback, + help="Specify the WORKSPACE relative path of tool_def.txt file, which replace target.txt's TOOL_CHAIN_CONF definition. 0 will clear this setting in target.txt and can't combine with other value.") + parser.add_option("-t", "--target", action="append", type="choice", choices=['DEBUG','RELEASE','0'], dest="TARGET", + help="TARGET is one of list: DEBUG, RELEASE, which replaces target.txt's TARGET definition. To specify more TARGET, please repeat this option. 0 will clear this setting in target.txt and can't combine with other value.") + parser.add_option("-n", "--tagname", action="callback", type="string", dest="TOOL_CHAIN_TAG", callback=SingleCheckCallback, + help="Specify the Tool Chain Tagname, which replaces target.txt's TOOL_CHAIN_TAG definition. 0 will clear this setting in target.txt and can't combine with other value.") + parser.add_option("-r", "--buildrule", action="callback", type="string", dest="BUILD_RULE_FILE", callback=SingleCheckCallback, + help="Specify the build rule configure file, which replaces target.txt's BUILD_RULE_CONF definition. If not specified, the default value Conf/build_rule.txt will be set.") + parser.add_option("-m", "--multithreadnum", action="callback", type="int", dest="NUM", callback=RangeCheckCallback, + help="Specify the multi-thread number which replace target.txt's MAX_CONCURRENT_THREAD_NUMBER. If the value is less than 2, MULTIPLE_THREAD will be disabled. If the value is larger than 1, MULTIPLE_THREAD will be enabled.") + parser.add_option("-e", "--enablemultithread", action="store", type="choice", choices=['Enable', 'Disable'], dest="ENABLE_MULTI_THREAD", + help="Specify whether enable multi-thread! If Enable, multi-thread is enabled; If Disable, mutli-thread is disable") + (opt, args)=parser.parse_args() + return (opt, args) + +if __name__ == '__main__': + EdkLogger.Initialize() + EdkLogger.SetLevel(EdkLogger.QUIET) + if os.getenv('WORKSPACE') == None: + print "ERROR: WORKSPACE should be specified or edksetup script should be executed before run TargetTool" + sys.exit(1) + + (opt, args) = MyOptionParser() + if len(args) != 1 or (args[0].lower() != 'print' and args[0].lower() != 'clean' and args[0].lower() != 'set'): + print "The number of args isn't 1 or the value of args is invalid." + sys.exit(1) + if opt.NUM != None and opt.NUM < 1: + print "The MAX_CONCURRENT_THREAD_NUMBER must be larger than 0." + sys.exit(1) + if opt.TARGET != None and len(opt.TARGET) > 1: + for elem in opt.TARGET: + if elem == '0': + print "0 will clear the TARGET setting in target.txt and can't combine with other value." + sys.exit(1) + if opt.TARGET_ARCH != None and len(opt.TARGET_ARCH) > 1: + for elem in opt.TARGET_ARCH: + if elem == '0': + print "0 will clear the TARGET_ARCH setting in target.txt and can't combine with other value." + sys.exit(1) + + try: + FileHandle = TargetTool(opt, args) + if FileHandle.Arg.lower() == 'print': + FileHandle.Print() + sys.exit(0) + elif FileHandle.Arg.lower() == 'clean': + FileHandle.RWFile('#', '=', 0) + else: + FileHandle.RWFile('#', '=', 1) + except Exception, e: + last_type, last_value, last_tb = sys.exc_info() + traceback.print_exception(last_type, last_value, last_tb) + diff --git a/BaseTools/Source/Python/TargetTool/__init__.py b/BaseTools/Source/Python/TargetTool/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/BaseTools/Source/Python/Trim/Trim.py b/BaseTools/Source/Python/Trim/Trim.py new file mode 100644 index 0000000000..a55c136edb --- /dev/null +++ b/BaseTools/Source/Python/Trim/Trim.py @@ -0,0 +1,520 @@ +## @file +# Trim files preprocessed by compiler +# +# Copyright (c) 2007, 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. +# + +## +# Import Modules +# +import os +import sys +import re + +from optparse import OptionParser +from optparse import make_option +from Common.BuildToolError import * +from Common.Misc import * + +import Common.EdkLogger as EdkLogger + +# Version and Copyright +__version_number__ = "0.10" +__version__ = "%prog Version " + __version_number__ +__copyright__ = "Copyright (c) 2007-2008, Intel Corporation. All rights reserved." + +## Regular expression for matching Line Control directive like "#line xxx" +gLineControlDirective = re.compile('^\s*#(?:line)?\s+([0-9]+)\s+"*([^"]*)"') +## Regular expression for matching "typedef struct" +gTypedefPattern = re.compile("^\s*typedef\s+struct\s*[{]*$", re.MULTILINE) +## Regular expression for matching "#pragma pack" +gPragmaPattern = re.compile("^\s*#pragma\s+pack", re.MULTILINE) +## Regular expression for matching HEX number +gHexNumberPattern = re.compile("0[xX]([0-9a-fA-F]+)") +## Regular expression for matching "Include ()" in asl file +gAslIncludePattern = re.compile("^(\s*)[iI]nclude\s*\(\"?([^\"\(\)]+)\"\)", re.MULTILINE) +## Patterns used to convert EDK conventions to EDK2 ECP conventions +gImportCodePatterns = [ + [ + re.compile('^(\s*)\(\*\*PeiServices\)\.PciCfg\s*=\s*([^;\s]+);', re.MULTILINE), + '''\\1{ +\\1 STATIC EFI_PEI_PPI_DESCRIPTOR gEcpPeiPciCfgPpiList = { +\\1 (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), +\\1 &gEcpPeiPciCfgPpiGuid, +\\1 \\2 +\\1 }; +\\1 (**PeiServices).InstallPpi (PeiServices, &gEcpPeiPciCfgPpiList); +\\1}''' + ], + + [ + re.compile('^(\s*)\(\*PeiServices\)->PciCfg\s*=\s*([^;\s]+);', re.MULTILINE), + '''\\1{ +\\1 STATIC EFI_PEI_PPI_DESCRIPTOR gEcpPeiPciCfgPpiList = { +\\1 (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), +\\1 &gEcpPeiPciCfgPpiGuid, +\\1 \\2 +\\1 }; +\\1 (**PeiServices).InstallPpi (PeiServices, &gEcpPeiPciCfgPpiList); +\\1}''' + ], + + [ + re.compile("(\s*).+->Modify[\s\n]*\(", re.MULTILINE), + '\\1PeiLibPciCfgModify (' + ], + + [ + re.compile("(\W*)gRT->ReportStatusCode[\s\n]*\(", re.MULTILINE), + '\\1EfiLibReportStatusCode (' + ], + + [ + re.compile('#include\s+["<]LoadFile\.h[">]', re.MULTILINE), + '#include ' + ], + + [ + re.compile("(\s*)\S*CreateEvent\s*\([\s\n]*EFI_EVENT_SIGNAL_READY_TO_BOOT[^,]*,((?:[^;]+\n)+)(\s*\));", re.MULTILINE), + '\\1EfiCreateEventReadyToBoot (\\2\\3;' + ], + + [ + re.compile("(\s*)\S*CreateEvent\s*\([\s\n]*EFI_EVENT_SIGNAL_LEGACY_BOOT[^,]*,((?:[^;]+\n)+)(\s*\));", re.MULTILINE), + '\\1EfiCreateEventLegacyBoot (\\2\\3;' + ], +# [ +# re.compile("(\W)(PEI_PCI_CFG_PPI)(\W)", re.MULTILINE), +# '\\1ECP_\\2\\3' +# ] +] + +## file cache to avoid circular include in ASL file +gIncludedAslFile = [] + +## Trim preprocessed source code +# +# Remove extra content made by preprocessor. The preprocessor must enable the +# line number generation option when preprocessing. +# +# @param Source File to be trimmed +# @param Target File to store the trimmed content +# @param Convert If True, convert standard HEX format to MASM format +# +def TrimPreprocessedFile(Source, Target, Convert): + CreateDirectory(os.path.dirname(Target)) + try: + f = open (Source, 'r') + except: + EdkLogger.error("Trim", FILE_OPEN_FAILURE, ExtraData=Source) + + # read whole file + Lines = f.readlines() + f.close() + + PreprocessedFile = "" + InjectedFile = "" + LineIndexOfOriginalFile = None + NewLines = [] + LineControlDirectiveFound = False + for Index in range(len(Lines)): + Line = Lines[Index] + # + # Find out the name of files injected by preprocessor from the lines + # with Line Control directive + # + MatchList = gLineControlDirective.findall(Line) + if MatchList != []: + MatchList = MatchList[0] + if len(MatchList) == 2: + LineNumber = int(MatchList[0], 0) + InjectedFile = MatchList[1] + # The first injetcted file must be the preprocessed file itself + if PreprocessedFile == "": + PreprocessedFile = InjectedFile + LineControlDirectiveFound = True + continue + elif PreprocessedFile == "" or InjectedFile != PreprocessedFile: + continue + + if LineIndexOfOriginalFile == None: + # + # Any non-empty lines must be from original preprocessed file. + # And this must be the first one. + # + LineIndexOfOriginalFile = Index + EdkLogger.verbose("Found original file content starting from line %d" + % (LineIndexOfOriginalFile + 1)) + + # convert HEX number format if indicated + if Convert: + Line = gHexNumberPattern.sub(r"0\1h", Line) + + if LineNumber != None: + EdkLogger.verbose("Got line directive: line=%d" % LineNumber) + # in case preprocessor removed some lines, like blank or comment lines + if LineNumber <= len(NewLines): + # possible? + NewLines[LineNumber - 1] = Line + else: + if LineNumber > (len(NewLines) + 1): + for LineIndex in range(len(NewLines), LineNumber-1): + NewLines.append(os.linesep) + NewLines.append(Line) + LineNumber = None + EdkLogger.verbose("Now we have lines: %d" % len(NewLines)) + else: + NewLines.append(Line) + + # in case there's no line directive or linemarker found + if (not LineControlDirectiveFound) and NewLines == []: + NewLines = Lines + + # save to file + try: + f = open (Target, 'wb') + except: + EdkLogger.error("Trim", FILE_OPEN_FAILURE, ExtraData=Target) + f.writelines(NewLines) + f.close() + +## Trim preprocessed VFR file +# +# Remove extra content made by preprocessor. The preprocessor doesn't need to +# enable line number generation option when preprocessing. +# +# @param Source File to be trimmed +# @param Target File to store the trimmed content +# +def TrimPreprocessedVfr(Source, Target): + CreateDirectory(os.path.dirname(Target)) + + try: + f = open (Source,'r') + except: + EdkLogger.error("Trim", FILE_OPEN_FAILURE, ExtraData=Source) + # read whole file + Lines = f.readlines() + f.close() + + FoundTypedef = False + Brace = 0 + TypedefStart = 0 + TypedefEnd = 0 + for Index in range(len(Lines)): + Line = Lines[Index] + # don't trim the lines from "formset" definition to the end of file + if Line.strip() == 'formset': + break + + if FoundTypedef == False and (Line.find('#line') == 0 or Line.find('# ') == 0): + # empty the line number directive if it's not aomong "typedef struct" + Lines[Index] = "\n" + continue + + if FoundTypedef == False and gTypedefPattern.search(Line) == None: + # keep "#pragram pack" directive + if gPragmaPattern.search(Line) == None: + Lines[Index] = "\n" + continue + elif FoundTypedef == False: + # found "typedef struct", keept its position and set a flag + FoundTypedef = True + TypedefStart = Index + + # match { and } to find the end of typedef definition + if Line.find("{") >= 0: + Brace += 1 + elif Line.find("}") >= 0: + Brace -= 1 + + # "typedef struct" must end with a ";" + if Brace == 0 and Line.find(";") >= 0: + FoundTypedef = False + TypedefEnd = Index + # keep all "typedef struct" except to GUID, EFI_PLABEL and PAL_CALL_RETURN + if Line.strip("} ;\r\n") in ["GUID", "EFI_PLABEL", "PAL_CALL_RETURN"]: + for i in range(TypedefStart, TypedefEnd+1): + Lines[i] = "\n" + + # save all lines trimmed + try: + f = open (Target,'w') + except: + EdkLogger.error("Trim", FILE_OPEN_FAILURE, ExtraData=Target) + f.writelines(Lines) + f.close() + +## Read the content ASL file, including ASL included, recursively +# +# @param Source File to be read +# @param Indent Spaces before the Include() statement +# +def DoInclude(Source, Indent=''): + NewFileContent = [] + # avoid A "include" B and B "include" A + if Source in gIncludedAslFile: + EdkLogger.warn("Trim", "Circular include", + ExtraData= "%s -> %s" % (" -> ".join(gIncludedAslFile), Source)) + return [] + gIncludedAslFile.append(Source) + + try: + F = open(Source,'r') + except: + EdkLogger.error("Trim", FILE_OPEN_FAILURE, ExtraData=Source) + + for Line in F: + Result = gAslIncludePattern.findall(Line) + if len(Result) == 0: + NewFileContent.append("%s%s" % (Indent, Line)) + continue + CurrentIndent = Indent + Result[0][0] + IncludedFile = Result[0][1] + NewFileContent.extend(DoInclude(IncludedFile, CurrentIndent)) + + gIncludedAslFile.pop() + F.close() + + return NewFileContent + + +## Trim ASL file +# +# Replace ASL include statement with the content the included file +# +# @param Source File to be trimmed +# @param Target File to store the trimmed content +# +def TrimAslFile(Source, Target): + CreateDirectory(os.path.dirname(Target)) + + Cwd = os.getcwd() + SourceDir = os.path.dirname(Source) + if SourceDir == '': + SourceDir = '.' + os.chdir(SourceDir) + Lines = DoInclude(Source) + os.chdir(Cwd) + + # save all lines trimmed + try: + f = open (Target,'w') + except: + EdkLogger.error("Trim", FILE_OPEN_FAILURE, ExtraData=Target) + + f.writelines(Lines) + f.close() + +## Trim EDK source code file(s) +# +# +# @param Source File or directory to be trimmed +# @param Target File or directory to store the trimmed content +# +def TrimR8Sources(Source, Target): + if os.path.isdir(Source): + for CurrentDir, Dirs, Files in os.walk(Source): + if '.svn' in Dirs: + Dirs.remove('.svn') + elif "CVS" in Dirs: + Dirs.remove("CVS") + + for FileName in Files: + Dummy, Ext = os.path.splitext(FileName) + if Ext.upper() not in ['.C', '.H']: continue + if Target == None or Target == '': + TrimR8SourceCode( + os.path.join(CurrentDir, FileName), + os.path.join(CurrentDir, FileName) + ) + else: + TrimR8SourceCode( + os.path.join(CurrentDir, FileName), + os.path.join(Target, CurrentDir[len(Source)+1:], FileName) + ) + else: + TrimR8SourceCode(Source, Target) + +## Trim one EDK source code file +# +# Do following replacement: +# +# (**PeiServices\).PciCfg = <*>; +# => { +# STATIC EFI_PEI_PPI_DESCRIPTOR gEcpPeiPciCfgPpiList = { +# (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), +# &gEcpPeiPciCfgPpiGuid, +# <*> +# }; +# (**PeiServices).InstallPpi (PeiServices, &gEcpPeiPciCfgPpiList); +# +# <*>Modify(<*>) +# => PeiLibPciCfgModify (<*>) +# +# gRT->ReportStatusCode (<*>) +# => EfiLibReportStatusCode (<*>) +# +# #include +# => #include +# +# CreateEvent (EFI_EVENT_SIGNAL_READY_TO_BOOT, <*>) +# => EfiCreateEventReadyToBoot (<*>) +# +# CreateEvent (EFI_EVENT_SIGNAL_LEGACY_BOOT, <*>) +# => EfiCreateEventLegacyBoot (<*>) +# +# @param Source File to be trimmed +# @param Target File to store the trimmed content +# +def TrimR8SourceCode(Source, Target): + EdkLogger.verbose("\t%s -> %s" % (Source, Target)) + CreateDirectory(os.path.dirname(Target)) + + try: + f = open (Source,'rb') + except: + EdkLogger.error("Trim", FILE_OPEN_FAILURE, ExtraData=Source) + # read whole file + Lines = f.read() + f.close() + + NewLines = None + for Re,Repl in gImportCodePatterns: + if NewLines == None: + NewLines = Re.sub(Repl, Lines) + else: + NewLines = Re.sub(Repl, NewLines) + + # save all lines if trimmed + if Source == Target and NewLines == Lines: + return + + try: + f = open (Target,'wb') + except: + EdkLogger.error("Trim", FILE_OPEN_FAILURE, ExtraData=Target) + f.write(NewLines) + f.close() + + +## Parse command line options +# +# Using standard Python module optparse to parse command line option of this tool. +# +# @retval Options A optparse.Values object containing the parsed options +# @retval InputFile Path of file to be trimmed +# +def Options(): + OptionList = [ + make_option("-s", "--source-code", dest="FileType", const="SourceCode", action="store_const", + help="The input file is preprocessed source code, including C or assembly code"), + make_option("-r", "--vfr-file", dest="FileType", const="Vfr", action="store_const", + help="The input file is preprocessed VFR file"), + make_option("-a", "--asl-file", dest="FileType", const="Asl", action="store_const", + help="The input file is ASL file"), + make_option("-8", "--r8-source-code", dest="FileType", const="R8SourceCode", action="store_const", + help="The input file is source code for R8 to be trimmed for ECP"), + + make_option("-c", "--convert-hex", dest="ConvertHex", action="store_true", + help="Convert standard hex format (0xabcd) to MASM format (abcdh)"), + + make_option("-o", "--output", dest="OutputFile", + help="File to store the trimmed content"), + make_option("-v", "--verbose", dest="LogLevel", action="store_const", const=EdkLogger.VERBOSE, + help="Run verbosely"), + make_option("-d", "--debug", dest="LogLevel", type="int", + help="Run with debug information"), + make_option("-q", "--quiet", dest="LogLevel", action="store_const", const=EdkLogger.QUIET, + help="Run quietly"), + make_option("-?", action="help", help="show this help message and exit"), + ] + + # use clearer usage to override default usage message + UsageString = "%prog [-s|-r|-a] [-c] [-v|-d |-q] [-o ] " + + Parser = OptionParser(description=__copyright__, version=__version__, option_list=OptionList, usage=UsageString) + Parser.set_defaults(FileType="Vfr") + Parser.set_defaults(ConvertHex=False) + Parser.set_defaults(LogLevel=EdkLogger.INFO) + + Options, Args = Parser.parse_args() + + # error check + if len(Args) == 0: + EdkLogger.error("Trim", OPTION_MISSING, ExtraData=Parser.get_usage()) + if len(Args) > 1: + EdkLogger.error("Trim", OPTION_NOT_SUPPORTED, ExtraData=Parser.get_usage()) + + InputFile = Args[0] + return Options, InputFile + +## Entrance method +# +# This method mainly dispatch specific methods per the command line options. +# If no error found, return zero value so the caller of this tool can know +# if it's executed successfully or not. +# +# @retval 0 Tool was successful +# @retval 1 Tool failed +# +def Main(): + try: + EdkLogger.Initialize() + CommandOptions, InputFile = Options() + if CommandOptions.LogLevel < EdkLogger.DEBUG_9: + EdkLogger.SetLevel(CommandOptions.LogLevel + 1) + else: + EdkLogger.SetLevel(CommandOptions.LogLevel) + except FatalError, X: + return 1 + + try: + if CommandOptions.FileType == "Vfr": + if CommandOptions.OutputFile == None: + CommandOptions.OutputFile = os.path.splitext(InputFile)[0] + '.iii' + TrimPreprocessedVfr(InputFile, CommandOptions.OutputFile) + elif CommandOptions.FileType == "Asl": + if CommandOptions.OutputFile == None: + CommandOptions.OutputFile = os.path.splitext(InputFile)[0] + '.iii' + TrimAslFile(InputFile, CommandOptions.OutputFile) + elif CommandOptions.FileType == "R8SourceCode": + TrimR8Sources(InputFile, CommandOptions.OutputFile) + else : + if CommandOptions.OutputFile == None: + CommandOptions.OutputFile = os.path.splitext(InputFile)[0] + '.iii' + TrimPreprocessedFile(InputFile, CommandOptions.OutputFile, CommandOptions.ConvertHex) + except FatalError, X: + import platform + import traceback + if CommandOptions != None and CommandOptions.LogLevel <= EdkLogger.DEBUG_9: + EdkLogger.quiet("(Python %s on %s) " % (platform.python_version(), sys.platform) + traceback.format_exc()) + return 1 + except: + import traceback + import platform + EdkLogger.error( + "\nTrim", + CODE_ERROR, + "Unknown fatal error when trimming [%s]" % InputFile, + ExtraData="\n(Please send email to dev@buildtools.tianocore.org for help, attaching following call stack trace!)\n", + RaiseError=False + ) + EdkLogger.quiet("(Python %s on %s) " % (platform.python_version(), sys.platform) + traceback.format_exc()) + return 1 + + return 0 + +if __name__ == '__main__': + r = Main() + ## 0-127 is a safe return range, and 1 is a standard default error + if r < 0 or r > 127: r = 1 + sys.exit(r) + diff --git a/BaseTools/Source/Python/Workspace/BuildClassObject.py b/BaseTools/Source/Python/Workspace/BuildClassObject.py new file mode 100644 index 0000000000..36c2ebf491 --- /dev/null +++ b/BaseTools/Source/Python/Workspace/BuildClassObject.py @@ -0,0 +1,364 @@ +## @file +# This file is used to define each component of the build database +# +# Copyright (c) 2007 ~ 2008, 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. +# + +import os + +from Common.Misc import sdict +from Common.Misc import RealPath2 +from Common.BuildToolError import * + +## PcdClassObject +# +# This Class is used for PcdObject +# +# @param object: Inherited from object class +# @param Name: Input value for Name of Pcd, default is None +# @param Guid: Input value for Guid of Pcd, default is None +# @param Type: Input value for Type of Pcd, default is None +# @param DatumType: Input value for DatumType of Pcd, default is None +# @param Value: Input value for Value of Pcd, default is None +# @param Token: Input value for Token of Pcd, default is None +# @param MaxDatumSize: Input value for MaxDatumSize of Pcd, default is None +# @param SkuInfoList: Input value for SkuInfoList of Pcd, default is {} +# @param IsOverrided: Input value for IsOverrided of Pcd, default is False +# +# @var TokenCName: To store value for TokenCName +# @var TokenSpaceGuidCName: To store value for TokenSpaceGuidCName +# @var Type: To store value for Type +# @var DatumType: To store value for DatumType +# @var TokenValue: To store value for TokenValue +# @var MaxDatumSize: To store value for MaxDatumSize +# @var SkuInfoList: To store value for SkuInfoList +# @var IsOverrided: To store value for IsOverrided +# @var Phase: To store value for Phase, default is "DXE" +# +class PcdClassObject(object): + def __init__(self, Name = None, Guid = None, Type = None, DatumType = None, Value = None, Token = None, MaxDatumSize = None, SkuInfoList = {}, GuidValue = None): + self.TokenCName = Name + self.TokenSpaceGuidCName = Guid + self.TokenSpaceGuidValue = GuidValue + self.Type = Type + self.DatumType = DatumType + self.DefaultValue = Value + self.TokenValue = Token + self.MaxDatumSize = MaxDatumSize + self.SkuInfoList = SkuInfoList + self.Phase = "DXE" + self.Pending = False + + ## Convert the class to a string + # + # Convert each member of the class to string + # Organize to a signle line format string + # + # @retval Rtn Formatted String + # + def __str__(self): + Rtn = '\tTokenCName=' + str(self.TokenCName) + ', ' + \ + 'TokenSpaceGuidCName=' + str(self.TokenSpaceGuidCName) + ', ' + \ + 'Type=' + str(self.Type) + ', ' + \ + 'DatumType=' + str(self.DatumType) + ', ' + \ + 'DefaultValue=' + str(self.DefaultValue) + ', ' + \ + 'TokenValue=' + str(self.TokenValue) + ', ' + \ + 'MaxDatumSize=' + str(self.MaxDatumSize) + ', ' + for Item in self.SkuInfoList.values(): + Rtn = Rtn + 'SkuId=' + Item.SkuId + ', ' + 'SkuIdName=' + Item.SkuIdName + Rtn = Rtn + str(self.IsOverrided) + + return Rtn + + ## Override __eq__ function + # + # Check whether pcds are the same + # + # @retval False The two pcds are different + # @retval True The two pcds are the same + # + def __eq__(self, Other): + return Other and self.TokenCName == Other.TokenCName and self.TokenSpaceGuidCName == Other.TokenSpaceGuidCName + + ## Override __hash__ function + # + # Use (TokenCName, TokenSpaceGuidCName) as key in hash table + # + # @retval truple() Key for hash table + # + def __hash__(self): + return hash((self.TokenCName, self.TokenSpaceGuidCName)) + +## LibraryClassObject +# +# This Class defines LibraryClassObject used in BuildDatabase +# +# @param object: Inherited from object class +# @param Name: Input value for LibraryClassName, default is None +# @param SupModList: Input value for SupModList, default is [] +# @param Type: Input value for Type, default is None +# +# @var LibraryClass: To store value for LibraryClass +# @var SupModList: To store value for SupModList +# @var Type: To store value for Type +# +class LibraryClassObject(object): + def __init__(self, Name = None, SupModList = [], Type = None): + self.LibraryClass = Name + self.SupModList = SupModList + if Type != None: + self.SupModList = CleanString(Type).split(DataType.TAB_SPACE_SPLIT) + +## ModuleBuildClassObject +# +# This Class defines ModuleBuildClass +# +# @param object: Inherited from object class +# +# @var MetaFile: To store value for module meta file path +# @var BaseName: To store value for BaseName +# @var ModuleType: To store value for ModuleType +# @var Guid: To store value for Guid +# @var Version: To store value for Version +# @var PcdIsDriver: To store value for PcdIsDriver +# @var BinaryModule: To store value for BinaryModule +# @var CustomMakefile: To store value for CustomMakefile +# @var Specification: To store value for Specification +# @var Shadow To store value for Shadow +# @var LibraryClass: To store value for LibraryClass, it is a list structure as +# [ LibraryClassObject, ...] +# @var ModuleEntryPointList: To store value for ModuleEntryPointList +# @var ModuleUnloadImageList: To store value for ModuleUnloadImageList +# @var ConstructorList: To store value for ConstructorList +# @var DestructorList: To store value for DestructorList +# @var Binaries: To store value for Binaries, it is a list structure as +# [ ModuleBinaryClassObject, ...] +# @var Sources: To store value for Sources, it is a list structure as +# [ ModuleSourceFilesClassObject, ... ] +# @var LibraryClasses: To store value for LibraryClasses, it is a set structure as +# { [LibraryClassName, ModuleType] : LibraryClassInfFile } +# @var Protocols: To store value for Protocols, it is a list structure as +# [ ProtocolName, ... ] +# @var Ppis: To store value for Ppis, it is a list structure as +# [ PpiName, ... ] +# @var Guids: To store value for Guids, it is a list structure as +# [ GuidName, ... ] +# @var Includes: To store value for Includes, it is a list structure as +# [ IncludePath, ... ] +# @var Packages: To store value for Packages, it is a list structure as +# [ DecFileName, ... ] +# @var Pcds: To store value for Pcds, it is a set structure as +# { [(PcdCName, PcdGuidCName)] : PcdClassObject} +# @var BuildOptions: To store value for BuildOptions, it is a set structure as +# { [BuildOptionKey] : BuildOptionValue} +# @var Depex: To store value for Depex +# +class ModuleBuildClassObject(object): + def __init__(self): + self.AutoGenVersion = 0 + self.MetaFile = '' + self.BaseName = '' + self.ModuleType = '' + self.Guid = '' + self.Version = '' + self.PcdIsDriver = '' + self.BinaryModule = '' + self.Shadow = '' + self.SourceOverridePath = '' + self.CustomMakefile = {} + self.Specification = {} + self.LibraryClass = [] + self.ModuleEntryPointList = [] + self.ModuleUnloadImageList = [] + self.ConstructorList = [] + self.DestructorList = [] + + self.Binaries = [] + self.Sources = [] + self.LibraryClasses = sdict() + self.Libraries = [] + self.Protocols = [] + self.Ppis = [] + self.Guids = [] + self.Includes = [] + self.Packages = [] + self.Pcds = {} + self.BuildOptions = {} + self.Depex = {} + + ## Convert the class to a string + # + # Convert member MetaFile of the class to a string + # + # @retval string Formatted String + # + def __str__(self): + return str(self.MetaFile) + + ## Override __eq__ function + # + # Check whether ModuleBuildClassObjects are the same + # + # @retval False The two ModuleBuildClassObjects are different + # @retval True The two ModuleBuildClassObjects are the same + # + def __eq__(self, Other): + return self.MetaFile == Other + + ## Override __hash__ function + # + # Use MetaFile as key in hash table + # + # @retval string Key for hash table + # + def __hash__(self): + return hash(self.MetaFile) + +## PackageBuildClassObject +# +# This Class defines PackageBuildClass +# +# @param object: Inherited from object class +# +# @var MetaFile: To store value for package meta file path +# @var PackageName: To store value for PackageName +# @var Guid: To store value for Guid +# @var Version: To store value for Version +# @var Protocols: To store value for Protocols, it is a set structure as +# { [ProtocolName] : Protocol Guid, ... } +# @var Ppis: To store value for Ppis, it is a set structure as +# { [PpiName] : Ppi Guid, ... } +# @var Guids: To store value for Guids, it is a set structure as +# { [GuidName] : Guid, ... } +# @var Includes: To store value for Includes, it is a list structure as +# [ IncludePath, ... ] +# @var LibraryClasses: To store value for LibraryClasses, it is a set structure as +# { [LibraryClassName] : LibraryClassInfFile } +# @var Pcds: To store value for Pcds, it is a set structure as +# { [(PcdCName, PcdGuidCName)] : PcdClassObject} +# +class PackageBuildClassObject(object): + def __init__(self): + self.MetaFile = '' + self.PackageName = '' + self.Guid = '' + self.Version = '' + + self.Protocols = {} + self.Ppis = {} + self.Guids = {} + self.Includes = [] + self.LibraryClasses = {} + self.Pcds = {} + + ## Convert the class to a string + # + # Convert member MetaFile of the class to a string + # + # @retval string Formatted String + # + def __str__(self): + return str(self.MetaFile) + + ## Override __eq__ function + # + # Check whether PackageBuildClassObjects are the same + # + # @retval False The two PackageBuildClassObjects are different + # @retval True The two PackageBuildClassObjects are the same + # + def __eq__(self, Other): + return self.MetaFile == Other + + ## Override __hash__ function + # + # Use MetaFile as key in hash table + # + # @retval string Key for hash table + # + def __hash__(self): + return hash(self.MetaFile) + +## PlatformBuildClassObject +# +# This Class defines PlatformBuildClass +# +# @param object: Inherited from object class +# +# @var MetaFile: To store value for platform meta-file path +# @var PlatformName: To store value for PlatformName +# @var Guid: To store value for Guid +# @var Version: To store value for Version +# @var DscSpecification: To store value for DscSpecification +# @var OutputDirectory: To store value for OutputDirectory +# @var FlashDefinition: To store value for FlashDefinition +# @var BuildNumber: To store value for BuildNumber +# @var MakefileName: To store value for MakefileName +# @var SkuIds: To store value for SkuIds, it is a set structure as +# { 'SkuName' : SkuId, '!include' : includefilename, ...} +# @var Modules: To store value for Modules, it is a list structure as +# [ InfFileName, ... ] +# @var Libraries: To store value for Libraries, it is a list structure as +# [ InfFileName, ... ] +# @var LibraryClasses: To store value for LibraryClasses, it is a set structure as +# { (LibraryClassName, ModuleType) : LibraryClassInfFile } +# @var Pcds: To store value for Pcds, it is a set structure as +# { [(PcdCName, PcdGuidCName)] : PcdClassObject } +# @var BuildOptions: To store value for BuildOptions, it is a set structure as +# { [BuildOptionKey] : BuildOptionValue } +# +class PlatformBuildClassObject(object): + def __init__(self): + self.MetaFile = '' + self.PlatformName = '' + self.Guid = '' + self.Version = '' + self.DscSpecification = '' + self.OutputDirectory = '' + self.FlashDefinition = '' + self.BuildNumber = '' + self.MakefileName = '' + + self.SkuIds = {} + self.Modules = [] + self.LibraryInstances = [] + self.LibraryClasses = {} + self.Libraries = {} + self.Pcds = {} + self.BuildOptions = {} + + ## Convert the class to a string + # + # Convert member MetaFile of the class to a string + # + # @retval string Formatted String + # + def __str__(self): + return str(self.MetaFile) + + ## Override __eq__ function + # + # Check whether PlatformBuildClassObjects are the same + # + # @retval False The two PlatformBuildClassObjects are different + # @retval True The two PlatformBuildClassObjects are the same + # + def __eq__(self, Other): + return self.MetaFile == Other + + ## Override __hash__ function + # + # Use MetaFile as key in hash table + # + # @retval string Key for hash table + # + def __hash__(self): + return hash(self.MetaFile) + diff --git a/BaseTools/Source/Python/Workspace/MetaDataTable.py b/BaseTools/Source/Python/Workspace/MetaDataTable.py new file mode 100644 index 0000000000..c8166bfa90 --- /dev/null +++ b/BaseTools/Source/Python/Workspace/MetaDataTable.py @@ -0,0 +1,335 @@ +## @file +# This file is used to create/update/query/erase table for files +# +# Copyright (c) 2008, 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. +# + +## +# Import Modules +# +import os + +import Common.EdkLogger as EdkLogger +from CommonDataClass import DataClass +from CommonDataClass.DataClass import FileClass + +## Convert to SQL required string format +def ConvertToSqlString(StringList): + return map(lambda s: "'" + s.replace("'", "''") + "'", StringList) + +## TableFile +# +# This class defined a common table +# +# @param object: Inherited from object class +# +# @param Cursor: Cursor of the database +# @param TableName: Name of the table +# +class Table(object): + _COLUMN_ = '' + _ID_STEP_ = 1 + _ID_MAX_ = 0x80000000 + _DUMMY_ = 0 + + def __init__(self, Cursor, Name='', IdBase=0, Temporary=False): + self.Cur = Cursor + self.Table = Name + self.IdBase = int(IdBase) + self.ID = int(IdBase) + self.Temporary = Temporary + + def __str__(self): + return self.Table + + ## Create table + # + # Create a table + # + def Create(self, NewTable=True): + if NewTable: + self.Drop() + + if self.Temporary: + SqlCommand = """create temp table IF NOT EXISTS %s (%s)""" % (self.Table, self._COLUMN_) + else: + SqlCommand = """create table IF NOT EXISTS %s (%s)""" % (self.Table, self._COLUMN_) + EdkLogger.debug(EdkLogger.DEBUG_8, SqlCommand) + self.Cur.execute(SqlCommand) + self.ID = self.GetId() + + ## Insert table + # + # Insert a record into a table + # + def Insert(self, *Args): + self.ID = self.ID + self._ID_STEP_ + if self.ID >= (self.IdBase + self._ID_MAX_): + self.ID = self.IdBase + self._ID_STEP_ + Values = ", ".join([str(Arg) for Arg in Args]) + SqlCommand = "insert into %s values(%s, %s)" % (self.Table, self.ID, Values) + EdkLogger.debug(EdkLogger.DEBUG_5, SqlCommand) + self.Cur.execute(SqlCommand) + return self.ID + + ## Query table + # + # Query all records of the table + # + def Query(self): + SqlCommand = """select * from %s""" % self.Table + self.Cur.execute(SqlCommand) + for Rs in self.Cur: + EdkLogger.verbose(str(Rs)) + TotalCount = self.GetId() + + ## Drop a table + # + # Drop the table + # + def Drop(self): + SqlCommand = """drop table IF EXISTS %s""" % self.Table + self.Cur.execute(SqlCommand) + + ## Get count + # + # Get a count of all records of the table + # + # @retval Count: Total count of all records + # + def GetCount(self): + SqlCommand = """select count(ID) from %s""" % self.Table + Record = self.Cur.execute(SqlCommand).fetchall() + return Record[0][0] + + def GetId(self): + SqlCommand = """select max(ID) from %s""" % self.Table + Record = self.Cur.execute(SqlCommand).fetchall() + Id = Record[0][0] + if Id == None: + Id = self.IdBase + return Id + + ## Init the ID of the table + # + # Init the ID of the table + # + def InitID(self): + self.ID = self.GetId() + + ## Exec + # + # Exec Sql Command, return result + # + # @param SqlCommand: The SqlCommand to be executed + # + # @retval RecordSet: The result after executed + # + def Exec(self, SqlCommand): + EdkLogger.debug(EdkLogger.DEBUG_5, SqlCommand) + self.Cur.execute(SqlCommand) + RecordSet = self.Cur.fetchall() + return RecordSet + + def SetEndFlag(self): + self.Exec("insert into %s values(%s)" % (self.Table, self._DUMMY_)) + + def IsIntegral(self): + Result = self.Exec("select min(ID) from %s" % (self.Table)) + if Result[0][0] != -1: + return False + return True + +## TableFile +# +# This class defined a table used for file +# +# @param object: Inherited from object class +# +class TableFile(Table): + _COLUMN_ = ''' + ID INTEGER PRIMARY KEY, + Name VARCHAR NOT NULL, + ExtName VARCHAR, + Path VARCHAR, + FullPath VARCHAR NOT NULL, + Model INTEGER DEFAULT 0, + TimeStamp SINGLE NOT NULL + ''' + def __init__(self, Cursor): + Table.__init__(self, Cursor, 'File') + + ## Insert table + # + # Insert a record into table File + # + # @param Name: Name of a File + # @param ExtName: ExtName of a File + # @param Path: Path of a File + # @param FullPath: FullPath of a File + # @param Model: Model of a File + # @param TimeStamp: TimeStamp of a File + # + def Insert(self, Name, ExtName, Path, FullPath, Model, TimeStamp): + (Name, ExtName, Path, FullPath) = ConvertToSqlString((Name, ExtName, Path, FullPath)) + return Table.Insert( + self, + Name, + ExtName, + Path, + FullPath, + Model, + TimeStamp + ) + + ## InsertFile + # + # Insert one file to table + # + # @param FileFullPath: The full path of the file + # @param Model: The model of the file + # + # @retval FileID: The ID after record is inserted + # + def InsertFile(self, FileFullPath, Model): + (Filepath, Name) = os.path.split(FileFullPath) + (Root, Ext) = os.path.splitext(FileFullPath) + TimeStamp = os.stat(FileFullPath)[8] + File = FileClass(-1, Name, Ext, Filepath, FileFullPath, Model, '', [], [], []) + return self.Insert( + Name, + Ext, + Filepath, + FileFullPath, + Model, + TimeStamp + ) + + ## Get ID of a given file + # + # @param FilePath Path of file + # + # @retval ID ID value of given file in the table + # + def GetFileId(self, FilePath): + QueryScript = "select ID from %s where FullPath = '%s'" % (self.Table, FilePath) + RecordList = self.Exec(QueryScript) + if len(RecordList) == 0: + return None + return RecordList[0][0] + + ## Get type of a given file + # + # @param FileId ID of a file + # + # @retval file_type Model value of given file in the table + # + def GetFileType(self, FileId): + QueryScript = "select Model from %s where ID = '%s'" % (self.Table, FileId) + RecordList = self.Exec(QueryScript) + if len(RecordList) == 0: + return None + return RecordList[0][0] + + ## Get file timestamp of a given file + # + # @param FileId ID of file + # + # @retval timestamp TimeStamp value of given file in the table + # + def GetFileTimeStamp(self, FileId): + QueryScript = "select TimeStamp from %s where ID = '%s'" % (self.Table, FileId) + RecordList = self.Exec(QueryScript) + if len(RecordList) == 0: + return None + return RecordList[0][0] + + ## Update the timestamp of a given file + # + # @param FileId ID of file + # @param TimeStamp Time stamp of file + # + def SetFileTimeStamp(self, FileId, TimeStamp): + self.Exec("update %s set TimeStamp=%s where ID='%s'" % (self.Table, TimeStamp, FileId)) + + ## Get list of file with given type + # + # @param FileType Type value of file + # + # @retval file_list List of files with the given type + # + def GetFileList(self, FileType): + RecordList = self.Exec("select FullPath from %s where Model=%s" % (self.Table, FileType)) + if len(RecordList) == 0: + return [] + return [R[0] for R in RecordList] + +## TableDataModel +# +# This class defined a table used for data model +# +# @param object: Inherited from object class +# +# +class TableDataModel(Table): + _COLUMN_ = """ + ID INTEGER PRIMARY KEY, + CrossIndex INTEGER NOT NULL, + Name VARCHAR NOT NULL, + Description VARCHAR + """ + def __init__(self, Cursor): + Table.__init__(self, Cursor, 'DataModel') + + ## Insert table + # + # Insert a record into table DataModel + # + # @param ID: ID of a ModelType + # @param CrossIndex: CrossIndex of a ModelType + # @param Name: Name of a ModelType + # @param Description: Description of a ModelType + # + def Insert(self, CrossIndex, Name, Description): + (Name, Description) = ConvertToSqlString((Name, Description)) + return Table.Insert(self, CrossIndex, Name, Description) + + ## Init table + # + # Create all default records of table DataModel + # + def InitTable(self): + EdkLogger.verbose("\nInitialize table DataModel started ...") + Count = self.GetCount() + if Count != None and Count != 0: + return + for Item in DataClass.MODEL_LIST: + CrossIndex = Item[1] + Name = Item[0] + Description = Item[0] + self.Insert(CrossIndex, Name, Description) + EdkLogger.verbose("Initialize table DataModel ... DONE!") + + ## Get CrossIndex + # + # Get a model's cross index from its name + # + # @param ModelName: Name of the model + # @retval CrossIndex: CrossIndex of the model + # + def GetCrossIndex(self, ModelName): + CrossIndex = -1 + SqlCommand = """select CrossIndex from DataModel where name = '""" + ModelName + """'""" + self.Cur.execute(SqlCommand) + for Item in self.Cur: + CrossIndex = Item[0] + + return CrossIndex + diff --git a/BaseTools/Source/Python/Workspace/MetaFileParser.py b/BaseTools/Source/Python/Workspace/MetaFileParser.py new file mode 100644 index 0000000000..294237daee --- /dev/null +++ b/BaseTools/Source/Python/Workspace/MetaFileParser.py @@ -0,0 +1,1131 @@ +## @file +# This file is used to parse meta files +# +# Copyright (c) 2008, 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. +# + +## +# Import Modules +# +import os +import time + +import Common.EdkLogger as EdkLogger +from CommonDataClass.DataClass import * +from Common.DataType import * +from Common.String import * +from Common.Misc import Blist, GuidStructureStringToGuidString, CheckPcdDatum + +## Base class of parser +# +# This class is used for derivation purpose. The specific parser for one kind +# type file must derive this class and implement some public interfaces. +# +# @param FilePath The path of platform description file +# @param FileType The raw data of DSC file +# @param Table Database used to retrieve module/package information +# @param Macros Macros used for replacement in file +# @param Owner Owner ID (for sub-section parsing) +# @param From ID from which the data comes (for !INCLUDE directive) +# +class MetaFileParser(object): + # data type (file content) for specific file type + DataType = {} + + ## Constructor of MetaFileParser + # + # Initialize object of MetaFileParser + # + # @param FilePath The path of platform description file + # @param FileType The raw data of DSC file + # @param Table Database used to retrieve module/package information + # @param Macros Macros used for replacement in file + # @param Owner Owner ID (for sub-section parsing) + # @param From ID from which the data comes (for !INCLUDE directive) + # + def __init__(self, FilePath, FileType, Table, Macros=None, Owner=-1, From=-1): + self._Table = Table + self._FileType = FileType + self.MetaFile = FilePath + self._FileDir = os.path.dirname(self.MetaFile) + self._Macros = {} + + # for recursive parsing + self._Owner = Owner + self._From = From + + # parsr status for parsing + self._Content = None + self._ValueList = ['', '', '', '', ''] + self._Scope = [] + self._LineIndex = 0 + self._CurrentLine = '' + self._SectionType = MODEL_UNKNOWN + self._SectionName = '' + self._InSubsection = False + self._SubsectionType = MODEL_UNKNOWN + self._SubsectionName = '' + self._LastItem = -1 + self._Enabled = 0 + self._Finished = False + + ## Store the parsed data in table + def _Store(self, *Args): + return self._Table.Insert(*Args) + + ## Virtual method for starting parse + def Start(self): + raise NotImplementedError + + ## Set parsing complete flag in both class and table + def _Done(self): + self._Finished = True + self._Table.SetEndFlag() + + ## Return the table containg parsed data + # + # If the parse complete flag is not set, this method will try to parse the + # file before return the table + # + def _GetTable(self): + if not self._Finished: + self.Start() + return self._Table + + ## Get the parse complete flag + def _GetFinished(self): + return self._Finished + + ## Set the complete flag + def _SetFinished(self, Value): + self._Finished = Value + + ## Use [] style to query data in table, just for readability + # + # DataInfo = [data_type, scope1(arch), scope2(platform,moduletype)] + # + def __getitem__(self, DataInfo): + if type(DataInfo) != type(()): + DataInfo = (DataInfo,) + return self.Table.Query(*DataInfo) + + ## Data parser for the common format in different type of file + # + # The common format in the meatfile is like + # + # xxx1 | xxx2 | xxx3 + # + def _CommonParser(self): + TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT) + self._ValueList[0:len(TokenList)] = TokenList + + ## Data parser for the format in which there's path + # + # Only path can have macro used. So we need to replace them before use. + # + def _PathParser(self): + TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT) + self._ValueList[0:len(TokenList)] = TokenList + if len(self._Macros) > 0: + for Index in range(0, len(self._ValueList)): + Value = self._ValueList[Index] + if Value == None or Value == '': + continue + self._ValueList[Index] = NormPath(Value, self._Macros) + + ## Skip unsupported data + def _Skip(self): + EdkLogger.warn("Parser", "Unrecognized content", File=self.MetaFile, + Line=self._LineIndex+1, ExtraData=self._CurrentLine); + self._ValueList[0:1] = [self._CurrentLine] + + ## Section header parser + # + # The section header is always in following format: + # + # [section_name.arch<.platform|module_type>] + # + def _SectionHeaderParser(self): + self._Scope = [] + self._SectionName = '' + ArchList = set() + for Item in GetSplitValueList(self._CurrentLine[1:-1], TAB_COMMA_SPLIT): + if Item == '': + continue + ItemList = GetSplitValueList(Item, TAB_SPLIT) + # different section should not mix in one section + if self._SectionName != '' and self._SectionName != ItemList[0].upper(): + EdkLogger.error('Parser', FORMAT_INVALID, "Different section names in the same section", + File=self.MetaFile, Line=self._LineIndex+1, ExtraData=self._CurrentLine) + self._SectionName = ItemList[0].upper() + if self._SectionName in self.DataType: + self._SectionType = self.DataType[self._SectionName] + else: + self._SectionType = MODEL_UNKNOWN + EdkLogger.warn("Parser", "Unrecognized section", File=self.MetaFile, + Line=self._LineIndex+1, ExtraData=self._CurrentLine) + # S1 is always Arch + if len(ItemList) > 1: + S1 = ItemList[1].upper() + else: + S1 = 'COMMON' + ArchList.add(S1) + # S2 may be Platform or ModuleType + if len(ItemList) > 2: + S2 = ItemList[2].upper() + else: + S2 = 'COMMON' + self._Scope.append([S1, S2]) + + # 'COMMON' must not be used with specific ARCHs at the same section + if 'COMMON' in ArchList and len(ArchList) > 1: + EdkLogger.error('Parser', FORMAT_INVALID, "'common' ARCH must not be used with specific ARCHs", + File=self.MetaFile, Line=self._LineIndex+1, ExtraData=self._CurrentLine) + + ## [defines] section parser + def _DefineParser(self): + TokenList = GetSplitValueList(self._CurrentLine, TAB_EQUAL_SPLIT, 1) + self._ValueList[0:len(TokenList)] = TokenList + if self._ValueList[1] == '': + EdkLogger.error('Parser', FORMAT_INVALID, "No value specified", + ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex+1) + + ## DEFINE name=value parser + def _MacroParser(self): + TokenList = GetSplitValueList(self._CurrentLine, ' ', 1) + MacroType = TokenList[0] + if len(TokenList) < 2 or TokenList[1] == '': + EdkLogger.error('Parser', FORMAT_INVALID, "No macro name/value given", + ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex+1) + TokenList = GetSplitValueList(TokenList[1], TAB_EQUAL_SPLIT, 1) + if TokenList[0] == '': + EdkLogger.error('Parser', FORMAT_INVALID, "No macro name given", + ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex+1) + if len(TokenList) == 1: + self._Macros[TokenList[0]] = '' + else: + # keep the macro definition for later use + self._Macros[TokenList[0]] = ReplaceMacro(TokenList[1], self._Macros, False) + + return TokenList[0], self._Macros[TokenList[0]] + + ## [BuildOptions] section parser + def _BuildOptionParser(self): + TokenList = GetSplitValueList(self._CurrentLine, TAB_EQUAL_SPLIT, 1) + TokenList2 = GetSplitValueList(TokenList[0], ':', 1) + if len(TokenList2) == 2: + self._ValueList[0] = TokenList2[0] # toolchain family + self._ValueList[1] = TokenList2[1] # keys + else: + self._ValueList[1] = TokenList[0] + if len(TokenList) == 2: # value + self._ValueList[2] = ReplaceMacro(TokenList[1], self._Macros) + + if self._ValueList[1].count('_') != 4: + EdkLogger.error( + 'Parser', + FORMAT_INVALID, + "'%s' must be in format of ____FLAGS" % self._ValueList[1], + ExtraData=self._CurrentLine, + File=self.MetaFile, + Line=self._LineIndex+1 + ) + + _SectionParser = {} + Table = property(_GetTable) + Finished = property(_GetFinished, _SetFinished) + + +## INF file parser class +# +# @param FilePath The path of platform description file +# @param FileType The raw data of DSC file +# @param Table Database used to retrieve module/package information +# @param Macros Macros used for replacement in file +# +class InfParser(MetaFileParser): + # INF file supported data types (one type per section) + DataType = { + TAB_UNKNOWN.upper() : MODEL_UNKNOWN, + TAB_INF_DEFINES.upper() : MODEL_META_DATA_HEADER, + TAB_BUILD_OPTIONS.upper() : MODEL_META_DATA_BUILD_OPTION, + TAB_INCLUDES.upper() : MODEL_EFI_INCLUDE, + TAB_LIBRARIES.upper() : MODEL_EFI_LIBRARY_INSTANCE, + TAB_LIBRARY_CLASSES.upper() : MODEL_EFI_LIBRARY_CLASS, + TAB_PACKAGES.upper() : MODEL_META_DATA_PACKAGE, + TAB_NMAKE.upper() : MODEL_META_DATA_NMAKE, + TAB_INF_FIXED_PCD.upper() : MODEL_PCD_FIXED_AT_BUILD, + TAB_INF_PATCH_PCD.upper() : MODEL_PCD_PATCHABLE_IN_MODULE, + TAB_INF_FEATURE_PCD.upper() : MODEL_PCD_FEATURE_FLAG, + TAB_INF_PCD_EX.upper() : MODEL_PCD_DYNAMIC_EX, + TAB_INF_PCD.upper() : MODEL_PCD_DYNAMIC, + TAB_SOURCES.upper() : MODEL_EFI_SOURCE_FILE, + TAB_GUIDS.upper() : MODEL_EFI_GUID, + TAB_PROTOCOLS.upper() : MODEL_EFI_PROTOCOL, + TAB_PPIS.upper() : MODEL_EFI_PPI, + TAB_DEPEX.upper() : MODEL_EFI_DEPEX, + TAB_BINARIES.upper() : MODEL_EFI_BINARY_FILE, + TAB_USER_EXTENSIONS.upper() : MODEL_META_DATA_USER_EXTENSION + } + + ## Constructor of InfParser + # + # Initialize object of InfParser + # + # @param FilePath The path of module description file + # @param FileType The raw data of DSC file + # @param Table Database used to retrieve module/package information + # @param Macros Macros used for replacement in file + # + def __init__(self, FilePath, FileType, Table, Macros=None): + MetaFileParser.__init__(self, FilePath, FileType, Table, Macros) + + ## Parser starter + def Start(self): + NmakeLine = '' + try: + self._Content = open(self.MetaFile, 'r').readlines() + except: + EdkLogger.error("Parser", FILE_READ_FAILURE, ExtraData=self.MetaFile) + + # parse the file line by line + IsFindBlockComment = False + + for Index in range(0, len(self._Content)): + # skip empty, commented, block commented lines + Line = CleanString(self._Content[Index], AllowCppStyleComment=True) + NextLine = '' + if Index + 1 < len(self._Content): + NextLine = CleanString(self._Content[Index + 1]) + if Line == '': + continue + if Line.find(DataType.TAB_COMMENT_R8_START) > -1: + IsFindBlockComment = True + continue + if Line.find(DataType.TAB_COMMENT_R8_END) > -1: + IsFindBlockComment = False + continue + if IsFindBlockComment: + continue + + self._LineIndex = Index + self._CurrentLine = Line + + # section header + if Line[0] == TAB_SECTION_START and Line[-1] == TAB_SECTION_END: + self._SectionHeaderParser() + continue + # merge two lines specified by '\' in section NMAKE + elif self._SectionType == MODEL_META_DATA_NMAKE: + if Line[-1] == '\\': + if NextLine == '': + self._CurrentLine = NmakeLine + Line[0:-1] + NmakeLine = '' + else: + if NextLine[0] == TAB_SECTION_START and NextLine[-1] == TAB_SECTION_END: + self._CurrentLine = NmakeLine + Line[0:-1] + NmakeLine = '' + else: + NmakeLine = NmakeLine + ' ' + Line[0:-1] + continue + else: + self._CurrentLine = NmakeLine + Line + NmakeLine = '' + elif Line.upper().startswith('DEFINE '): + # file private macros + self._MacroParser() + continue + + # section content + self._ValueList = ['','',''] + # parse current line, result will be put in self._ValueList + self._SectionParser[self._SectionType](self) + if self._ValueList == None: + continue + # + # Model, Value1, Value2, Value3, Arch, Platform, BelongsToItem=-1, + # LineBegin=-1, ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, Enabled=-1 + # + for Arch, Platform in self._Scope: + self._Store(self._SectionType, + self._ValueList[0], + self._ValueList[1], + self._ValueList[2], + Arch, + Platform, + self._Owner, + self._LineIndex+1, + -1, + self._LineIndex+1, + -1, + 0 + ) + self._Done() + + ## Data parser for the format in which there's path + # + # Only path can have macro used. So we need to replace them before use. + # + def _IncludeParser(self): + TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT) + self._ValueList[0:len(TokenList)] = TokenList + if len(self._Macros) > 0: + for Index in range(0, len(self._ValueList)): + Value = self._ValueList[Index] + if Value.upper().find('$(EFI_SOURCE)\Edk'.upper()) > -1 or Value.upper().find('$(EFI_SOURCE)/Edk'.upper()) > -1: + Value = '$(EDK_SOURCE)' + Value[17:] + if Value.find('$(EFI_SOURCE)') > -1 or Value.find('$(EDK_SOURCE)') > -1: + pass + elif Value.startswith('.'): + pass + elif Value.startswith('$('): + pass + else: + Value = '$(EFI_SOURCE)/' + Value + + if Value == None or Value == '': + continue + self._ValueList[Index] = NormPath(Value, self._Macros) + + ## Parse [Sources] section + # + # Only path can have macro used. So we need to replace them before use. + # + def _SourceFileParser(self): + TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT) + self._ValueList[0:len(TokenList)] = TokenList + # For Acpi tables, remove macro like ' TABLE_NAME=Sata1' + if 'COMPONENT_TYPE' in self._Macros: + if self._Macros['COMPONENT_TYPE'].upper() == 'ACPITABLE': + self._ValueList[0] = GetSplitValueList(self._ValueList[0], ' ', 1)[0] + if self._Macros['BASE_NAME'] == 'Microcode': + pass + if len(self._Macros) > 0: + for Index in range(0, len(self._ValueList)): + Value = self._ValueList[Index] + if Value == None or Value == '': + continue + self._ValueList[Index] = NormPath(Value, self._Macros) + + ## Parse [Binaries] section + # + # Only path can have macro used. So we need to replace them before use. + # + def _BinaryFileParser(self): + TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT, 2) + if len(TokenList) < 2: + EdkLogger.error('Parser', FORMAT_INVALID, "No file type or path specified", + ExtraData=self._CurrentLine + " ( | [| ])", + File=self.MetaFile, Line=self._LineIndex+1) + if not TokenList[0]: + EdkLogger.error('Parser', FORMAT_INVALID, "No file type specified", + ExtraData=self._CurrentLine + " ( | [| ])", + File=self.MetaFile, Line=self._LineIndex+1) + if not TokenList[1]: + EdkLogger.error('Parser', FORMAT_INVALID, "No file path specified", + ExtraData=self._CurrentLine + " ( | [| ])", + File=self.MetaFile, Line=self._LineIndex+1) + self._ValueList[0:len(TokenList)] = TokenList + self._ValueList[1] = NormPath(self._ValueList[1], self._Macros) + + ## [defines] section parser + def _DefineParser(self): + TokenList = GetSplitValueList(self._CurrentLine, TAB_EQUAL_SPLIT, 1) + self._ValueList[0:len(TokenList)] = TokenList + self._Macros[TokenList[0]] = ReplaceMacro(TokenList[1], self._Macros, False) + if self._ValueList[1] == '': + EdkLogger.error('Parser', FORMAT_INVALID, "No value specified", + ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex+1) + + ## [nmake] section parser (R8.x style only) + def _NmakeParser(self): + TokenList = GetSplitValueList(self._CurrentLine, TAB_EQUAL_SPLIT, 1) + self._ValueList[0:len(TokenList)] = TokenList + # remove macros + self._ValueList[1] = ReplaceMacro(self._ValueList[1], self._Macros, False) + # remove self-reference in macro setting + #self._ValueList[1] = ReplaceMacro(self._ValueList[1], {self._ValueList[0]:''}) + + ## [FixedPcd], [FeaturePcd], [PatchPcd], [Pcd] and [PcdEx] sections parser + def _PcdParser(self): + TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT, 1) + self._ValueList[0:1] = GetSplitValueList(TokenList[0], TAB_SPLIT) + if len(TokenList) > 1: + self._ValueList[2] = TokenList[1] + if self._ValueList[0] == '' or self._ValueList[1] == '': + EdkLogger.error('Parser', FORMAT_INVALID, "No token space GUID or PCD name specified", + ExtraData=self._CurrentLine + " (.)", + File=self.MetaFile, Line=self._LineIndex+1) + + ## [depex] section parser + def _DepexParser(self): + self._ValueList[0:1] = [self._CurrentLine] + + _SectionParser = { + MODEL_UNKNOWN : MetaFileParser._Skip, + MODEL_META_DATA_HEADER : _DefineParser, + MODEL_META_DATA_BUILD_OPTION : MetaFileParser._BuildOptionParser, + MODEL_EFI_INCLUDE : _IncludeParser, # for R8.x modules + MODEL_EFI_LIBRARY_INSTANCE : MetaFileParser._CommonParser, # for R8.x modules + MODEL_EFI_LIBRARY_CLASS : MetaFileParser._PathParser, + MODEL_META_DATA_PACKAGE : MetaFileParser._PathParser, + MODEL_META_DATA_NMAKE : _NmakeParser, # for R8.x modules + MODEL_PCD_FIXED_AT_BUILD : _PcdParser, + MODEL_PCD_PATCHABLE_IN_MODULE : _PcdParser, + MODEL_PCD_FEATURE_FLAG : _PcdParser, + MODEL_PCD_DYNAMIC_EX : _PcdParser, + MODEL_PCD_DYNAMIC : _PcdParser, + MODEL_EFI_SOURCE_FILE : _SourceFileParser, + MODEL_EFI_GUID : MetaFileParser._CommonParser, + MODEL_EFI_PROTOCOL : MetaFileParser._CommonParser, + MODEL_EFI_PPI : MetaFileParser._CommonParser, + MODEL_EFI_DEPEX : _DepexParser, + MODEL_EFI_BINARY_FILE : _BinaryFileParser, + MODEL_META_DATA_USER_EXTENSION : MetaFileParser._Skip, + } + +## DSC file parser class +# +# @param FilePath The path of platform description file +# @param FileType The raw data of DSC file +# @param Table Database used to retrieve module/package information +# @param Macros Macros used for replacement in file +# @param Owner Owner ID (for sub-section parsing) +# @param From ID from which the data comes (for !INCLUDE directive) +# +class DscParser(MetaFileParser): + # DSC file supported data types (one type per section) + DataType = { + TAB_SKUIDS.upper() : MODEL_EFI_SKU_ID, + TAB_LIBRARIES.upper() : MODEL_EFI_LIBRARY_INSTANCE, + TAB_LIBRARY_CLASSES.upper() : MODEL_EFI_LIBRARY_CLASS, + TAB_BUILD_OPTIONS.upper() : MODEL_META_DATA_BUILD_OPTION, + TAB_PCDS_FIXED_AT_BUILD_NULL.upper() : MODEL_PCD_FIXED_AT_BUILD, + TAB_PCDS_PATCHABLE_IN_MODULE_NULL.upper() : MODEL_PCD_PATCHABLE_IN_MODULE, + TAB_PCDS_FEATURE_FLAG_NULL.upper() : MODEL_PCD_FEATURE_FLAG, + TAB_PCDS_DYNAMIC_DEFAULT_NULL.upper() : MODEL_PCD_DYNAMIC_DEFAULT, + TAB_PCDS_DYNAMIC_HII_NULL.upper() : MODEL_PCD_DYNAMIC_HII, + TAB_PCDS_DYNAMIC_VPD_NULL.upper() : MODEL_PCD_DYNAMIC_VPD, + TAB_PCDS_DYNAMIC_EX_DEFAULT_NULL.upper() : MODEL_PCD_DYNAMIC_EX_DEFAULT, + TAB_PCDS_DYNAMIC_EX_HII_NULL.upper() : MODEL_PCD_DYNAMIC_EX_HII, + TAB_PCDS_DYNAMIC_EX_VPD_NULL.upper() : MODEL_PCD_DYNAMIC_EX_VPD, + TAB_COMPONENTS.upper() : MODEL_META_DATA_COMPONENT, + TAB_COMPONENTS_SOURCE_OVERRIDE_PATH.upper() : MODEL_META_DATA_COMPONENT_SOURCE_OVERRIDE_PATH, + TAB_DSC_DEFINES.upper() : MODEL_META_DATA_HEADER, + TAB_INCLUDE.upper() : MODEL_META_DATA_INCLUDE, + TAB_IF.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_IF, + TAB_IF_DEF.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF, + TAB_IF_N_DEF.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF, + TAB_ELSE_IF.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF, + TAB_ELSE.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE, + TAB_END_IF.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF, + } + + # sections which allow "!include" directive + _IncludeAllowedSection = [ + TAB_LIBRARIES.upper(), + TAB_LIBRARY_CLASSES.upper(), + TAB_SKUIDS.upper(), + TAB_COMPONENTS.upper(), + TAB_BUILD_OPTIONS.upper(), + TAB_PCDS_FIXED_AT_BUILD_NULL.upper(), + TAB_PCDS_PATCHABLE_IN_MODULE_NULL.upper(), + TAB_PCDS_FEATURE_FLAG_NULL.upper(), + TAB_PCDS_DYNAMIC_DEFAULT_NULL.upper(), + TAB_PCDS_DYNAMIC_HII_NULL.upper(), + TAB_PCDS_DYNAMIC_VPD_NULL.upper(), + TAB_PCDS_DYNAMIC_EX_DEFAULT_NULL.upper(), + TAB_PCDS_DYNAMIC_EX_HII_NULL.upper(), + TAB_PCDS_DYNAMIC_EX_VPD_NULL.upper(), + ] + + # operators which can be used in "!if/!ifdef/!ifndef" directives + _OP_ = { + "!" : lambda a: not a, + "!=" : lambda a,b: a!=b, + "==" : lambda a,b: a==b, + ">" : lambda a,b: a>b, + "<" : lambda a,b: a" : lambda a,b: a>=b, + ">=" : lambda a,b: a>=b, + "<=" : lambda a,b: a<=b, + "=<" : lambda a,b: a<=b, + } + + ## Constructor of DscParser + # + # Initialize object of DscParser + # + # @param FilePath The path of platform description file + # @param FileType The raw data of DSC file + # @param Table Database used to retrieve module/package information + # @param Macros Macros used for replacement in file + # @param Owner Owner ID (for sub-section parsing) + # @param From ID from which the data comes (for !INCLUDE directive) + # + def __init__(self, FilePath, FileType, Table, Macros=None, Owner=-1, From=-1): + MetaFileParser.__init__(self, FilePath, FileType, Table, Macros, Owner, From) + # to store conditional directive evaluation result + self._Eval = Blist() + + ## Parser starter + def Start(self): + try: + if self._Content == None: + self._Content = open(self.MetaFile, 'r').readlines() + except: + EdkLogger.error("Parser", FILE_READ_FAILURE, ExtraData=self.MetaFile) + + for Index in range(0, len(self._Content)): + Line = CleanString(self._Content[Index]) + # skip empty line + if Line == '': + continue + self._CurrentLine = Line + self._LineIndex = Index + + # section header + if Line[0] == TAB_SECTION_START and Line[-1] == TAB_SECTION_END: + self._SectionHeaderParser() + continue + # subsection ending + elif Line[0] == '}': + self._InSubsection = False + self._SubsectionType = MODEL_UNKNOWN + self._SubsectionName = '' + self._Owner = -1 + continue + # subsection header + elif Line[0] == TAB_OPTION_START and Line[-1] == TAB_OPTION_END: + self._SubsectionHeaderParser() + continue + # directive line + elif Line[0] == '!': + self._DirectiveParser() + continue + # file private macros + elif Line.upper().startswith('DEFINE '): + self._MacroParser() + continue + elif Line.upper().startswith('EDK_GLOBAL '): + (Name, Value) = self._MacroParser() + for Arch, ModuleType in self._Scope: + self._LastItem = self._Store( + MODEL_META_DATA_DEFINE, + Name, + Value, + '', + Arch, + 'COMMON', + self._Owner, + self._From, + self._LineIndex+1, + -1, + self._LineIndex+1, + -1, + self._Enabled + ) + continue + + # section content + if self._InSubsection: + SectionType = self._SubsectionType + SectionName = self._SubsectionName + if self._Owner == -1: + self._Owner = self._LastItem + else: + SectionType = self._SectionType + SectionName = self._SectionName + + self._ValueList = ['', '', ''] + self._SectionParser[SectionType](self) + if self._ValueList == None: + continue + + # + # Model, Value1, Value2, Value3, Arch, ModuleType, BelongsToItem=-1, BelongsToFile=-1, + # LineBegin=-1, ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, Enabled=-1 + # + for Arch, ModuleType in self._Scope: + self._LastItem = self._Store( + SectionType, + self._ValueList[0], + self._ValueList[1], + self._ValueList[2], + Arch, + ModuleType, + self._Owner, + self._From, + self._LineIndex+1, + -1, + self._LineIndex+1, + -1, + self._Enabled + ) + self._Done() + + ## [defines] section parser + def _DefineParser(self): + TokenList = GetSplitValueList(self._CurrentLine, TAB_EQUAL_SPLIT, 1) + if len(TokenList) < 2: + EdkLogger.error('Parser', FORMAT_INVALID, "No value specified", + ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex+1) + # 'FLASH_DEFINITION', 'OUTPUT_DIRECTORY' need special processing + if TokenList[0] in ['FLASH_DEFINITION', 'OUTPUT_DIRECTORY']: + TokenList[1] = NormPath(TokenList[1], self._Macros) + self._ValueList[0:len(TokenList)] = TokenList + + ## parser + def _SubsectionHeaderParser(self): + self._SubsectionName = self._CurrentLine[1:-1].upper() + if self._SubsectionName in self.DataType: + self._SubsectionType = self.DataType[self._SubsectionName] + else: + self._SubsectionType = MODEL_UNKNOWN + EdkLogger.warn("Parser", "Unrecognized sub-section", File=self.MetaFile, + Line=self._LineIndex+1, ExtraData=self._CurrentLine) + + ## Directive statement parser + def _DirectiveParser(self): + self._ValueList = ['','',''] + TokenList = GetSplitValueList(self._CurrentLine, ' ', 1) + self._ValueList[0:len(TokenList)] = TokenList + DirectiveName = self._ValueList[0].upper() + if DirectiveName not in self.DataType: + EdkLogger.error("Parser", FORMAT_INVALID, "Unknown directive [%s]" % DirectiveName, + File=self.MetaFile, Line=self._LineIndex+1) + if DirectiveName in ['!IF', '!IFDEF', '!INCLUDE', '!IFNDEF', '!ELSEIF'] and self._ValueList[1] == '': + EdkLogger.error("Parser", FORMAT_INVALID, "Missing expression", + File=self.MetaFile, Line=self._LineIndex+1, + ExtraData=self._CurrentLine) + # keep the directive in database first + self._LastItem = self._Store( + self.DataType[DirectiveName], + self._ValueList[0], + self._ValueList[1], + self._ValueList[2], + 'COMMON', + 'COMMON', + self._Owner, + self._From, + self._LineIndex + 1, + -1, + self._LineIndex + 1, + -1, + 0 + ) + + # process the directive + if DirectiveName == "!INCLUDE": + if not self._SectionName in self._IncludeAllowedSection: + EdkLogger.error("Parser", FORMAT_INVALID, File=self.MetaFile, Line=self._LineIndex+1, + ExtraData="'!include' is not allowed under section [%s]" % self._SectionName) + # the included file must be relative to the parsing file + IncludedFile = os.path.join(self._FileDir, self._ValueList[1]) + Parser = DscParser(IncludedFile, self._FileType, self._Table, self._Macros, From=self._LastItem) + # set the parser status with current status + Parser._SectionName = self._SectionName + Parser._SectionType = self._SectionType + Parser._Scope = self._Scope + Parser._Enabled = self._Enabled + try: + Parser.Start() + except: + EdkLogger.error("Parser", PARSER_ERROR, File=self.MetaFile, Line=self._LineIndex+1, + ExtraData="Failed to parse content in file %s" % IncludedFile) + # update current status with sub-parser's status + self._SectionName = Parser._SectionName + self._SectionType = Parser._SectionType + self._Scope = Parser._Scope + self._Enabled = Parser._Enabled + else: + if DirectiveName in ["!IF", "!IFDEF", "!IFNDEF"]: + # evaluate the expression + Result = self._Evaluate(self._ValueList[1]) + if DirectiveName == "!IFNDEF": + Result = not Result + self._Eval.append(Result) + elif DirectiveName in ["!ELSEIF"]: + # evaluate the expression + self._Eval[-1] = (not self._Eval[-1]) & self._Evaluate(self._ValueList[1]) + elif DirectiveName in ["!ELSE"]: + self._Eval[-1] = not self._Eval[-1] + elif DirectiveName in ["!ENDIF"]: + if len(self._Eval) > 0: + self._Eval.pop() + else: + EdkLogger.error("Parser", FORMAT_INVALID, "!IF..[!ELSE]..!ENDIF doesn't match", + File=self.MetaFile, Line=self._LineIndex+1) + if self._Eval.Result == False: + self._Enabled = 0 - len(self._Eval) + else: + self._Enabled = len(self._Eval) + + ## Evaludate the value of expression in "if/ifdef/ifndef" directives + def _Evaluate(self, Expression): + TokenList = Expression.split() + TokenNumber = len(TokenList) + # one operand, guess it's just a macro name + if TokenNumber == 1: + return TokenList[0] in self._Macros + # two operands, suppose it's "!xxx" format + elif TokenNumber == 2: + Op = TokenList[0] + if Op not in self._OP_: + EdkLogger.error('Parser', FORMAT_INVALID, "Unsupported operator [%s]" % Op, File=self.MetaFile, + Line=self._LineIndex+1, ExtraData=Expression) + if TokenList[1].upper() == 'TRUE': + Value = True + else: + Value = False + return self._OP_[Op](Value) + # three operands + elif TokenNumber == 3: + Name = TokenList[0] + if Name not in self._Macros: + return False + Value = TokenList[2] + if Value[0] in ["'", '"'] and Value[-1] in ["'", '"']: + Value = Value[1:-1] + Op = TokenList[1] + if Op not in self._OP_: + EdkLogger.error('Parser', FORMAT_INVALID, "Unsupported operator [%s]" % Op, File=self.MetaFile, + Line=self._LineIndex+1, ExtraData=Expression) + return self._OP_[Op](self._Macros[Name], Value) + else: + EdkLogger.error('Parser', FORMAT_INVALID, File=self.MetaFile, Line=self._LineIndex+1, + ExtraData=Expression) + + ## PCD sections parser + # + # [PcdsFixedAtBuild] + # [PcdsPatchableInModule] + # [PcdsFeatureFlag] + # [PcdsDynamicEx + # [PcdsDynamicExDefault] + # [PcdsDynamicExVpd] + # [PcdsDynamicExHii] + # [PcdsDynamic] + # [PcdsDynamicDefault] + # [PcdsDynamicVpd] + # [PcdsDynamicHii] + # + def _PcdParser(self): + TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT, 1) + self._ValueList[0:1] = GetSplitValueList(TokenList[0], TAB_SPLIT) + if len(TokenList) == 2: + self._ValueList[2] = TokenList[1] + if self._ValueList[0] == '' or self._ValueList[1] == '': + EdkLogger.error('Parser', FORMAT_INVALID, "No token space GUID or PCD name specified", + ExtraData=self._CurrentLine + " (.|)", + File=self.MetaFile, Line=self._LineIndex+1) + if self._ValueList[2] == '': + EdkLogger.error('Parser', FORMAT_INVALID, "No PCD value given", + ExtraData=self._CurrentLine + " (.|)", + File=self.MetaFile, Line=self._LineIndex+1) + + ## [components] section parser + def _ComponentParser(self): + if self._CurrentLine[-1] == '{': + self._ValueList[0] = self._CurrentLine[0:-1].strip() + self._InSubsection = True + else: + self._ValueList[0] = self._CurrentLine + if len(self._Macros) > 0: + self._ValueList[0] = NormPath(self._ValueList[0], self._Macros) + + def _LibraryClassParser(self): + TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT) + if len(TokenList) < 2: + EdkLogger.error('Parser', FORMAT_INVALID, "No library class or instance specified", + ExtraData=self._CurrentLine + " (|)", + File=self.MetaFile, Line=self._LineIndex+1) + if TokenList[0] == '': + EdkLogger.error('Parser', FORMAT_INVALID, "No library class specified", + ExtraData=self._CurrentLine + " (|)", + File=self.MetaFile, Line=self._LineIndex+1) + if TokenList[1] == '': + EdkLogger.error('Parser', FORMAT_INVALID, "No library instance specified", + ExtraData=self._CurrentLine + " (|)", + File=self.MetaFile, Line=self._LineIndex+1) + self._ValueList[0:len(TokenList)] = TokenList + if len(self._Macros) > 0: + self._ValueList[1] = NormPath(self._ValueList[1], self._Macros) + + def _CompponentSourceOverridePathParser(self): + if len(self._Macros) > 0: + self._ValueList[0] = NormPath(self._CurrentLine, self._Macros) + + _SectionParser = { + MODEL_META_DATA_HEADER : _DefineParser, + MODEL_EFI_SKU_ID : MetaFileParser._CommonParser, + MODEL_EFI_LIBRARY_INSTANCE : MetaFileParser._PathParser, + MODEL_EFI_LIBRARY_CLASS : _LibraryClassParser, + MODEL_PCD_FIXED_AT_BUILD : _PcdParser, + MODEL_PCD_PATCHABLE_IN_MODULE : _PcdParser, + MODEL_PCD_FEATURE_FLAG : _PcdParser, + MODEL_PCD_DYNAMIC_DEFAULT : _PcdParser, + MODEL_PCD_DYNAMIC_HII : _PcdParser, + MODEL_PCD_DYNAMIC_VPD : _PcdParser, + MODEL_PCD_DYNAMIC_EX_DEFAULT : _PcdParser, + MODEL_PCD_DYNAMIC_EX_HII : _PcdParser, + MODEL_PCD_DYNAMIC_EX_VPD : _PcdParser, + MODEL_META_DATA_COMPONENT : _ComponentParser, + MODEL_META_DATA_COMPONENT_SOURCE_OVERRIDE_PATH : _CompponentSourceOverridePathParser, + MODEL_META_DATA_BUILD_OPTION : MetaFileParser._BuildOptionParser, + MODEL_UNKNOWN : MetaFileParser._Skip, + MODEL_META_DATA_USER_EXTENSION : MetaFileParser._Skip, + } + +## DEC file parser class +# +# @param FilePath The path of platform description file +# @param FileType The raw data of DSC file +# @param Table Database used to retrieve module/package information +# @param Macros Macros used for replacement in file +# +class DecParser(MetaFileParser): + # DEC file supported data types (one type per section) + DataType = { + TAB_DEC_DEFINES.upper() : MODEL_META_DATA_HEADER, + TAB_INCLUDES.upper() : MODEL_EFI_INCLUDE, + TAB_LIBRARY_CLASSES.upper() : MODEL_EFI_LIBRARY_CLASS, + TAB_GUIDS.upper() : MODEL_EFI_GUID, + TAB_PPIS.upper() : MODEL_EFI_PPI, + TAB_PROTOCOLS.upper() : MODEL_EFI_PROTOCOL, + TAB_PCDS_FIXED_AT_BUILD_NULL.upper() : MODEL_PCD_FIXED_AT_BUILD, + TAB_PCDS_PATCHABLE_IN_MODULE_NULL.upper() : MODEL_PCD_PATCHABLE_IN_MODULE, + TAB_PCDS_FEATURE_FLAG_NULL.upper() : MODEL_PCD_FEATURE_FLAG, + TAB_PCDS_DYNAMIC_NULL.upper() : MODEL_PCD_DYNAMIC, + TAB_PCDS_DYNAMIC_EX_NULL.upper() : MODEL_PCD_DYNAMIC_EX, + } + + ## Constructor of DecParser + # + # Initialize object of DecParser + # + # @param FilePath The path of platform description file + # @param FileType The raw data of DSC file + # @param Table Database used to retrieve module/package information + # @param Macros Macros used for replacement in file + # + def __init__(self, FilePath, FileType, Table, Macro=None): + MetaFileParser.__init__(self, FilePath, FileType, Table, Macro, -1) + + ## Parser starter + def Start(self): + try: + if self._Content == None: + self._Content = open(self.MetaFile, 'r').readlines() + except: + EdkLogger.error("Parser", FILE_READ_FAILURE, ExtraData=self.MetaFile) + + for Index in range(0, len(self._Content)): + Line = CleanString(self._Content[Index]) + # skip empty line + if Line == '': + continue + self._CurrentLine = Line + self._LineIndex = Index + + # section header + if Line[0] == TAB_SECTION_START and Line[-1] == TAB_SECTION_END: + self._SectionHeaderParser() + continue + elif Line.startswith('DEFINE '): + self._MacroParser() + continue + elif len(self._SectionType) == 0: + continue + + # section content + self._ValueList = ['','',''] + self._SectionParser[self._SectionType[0]](self) + if self._ValueList == None: + continue + + # + # Model, Value1, Value2, Value3, Arch, BelongsToItem=-1, LineBegin=-1, + # ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, FeatureFlag='', Enabled=-1 + # + for Arch, ModuleType, Type in self._Scope: + self._LastItem = self._Store( + Type, + self._ValueList[0], + self._ValueList[1], + self._ValueList[2], + Arch, + ModuleType, + self._Owner, + self._LineIndex+1, + -1, + self._LineIndex+1, + -1, + 0 + ) + self._Done() + + ## Section header parser + # + # The section header is always in following format: + # + # [section_name.arch<.platform|module_type>] + # + def _SectionHeaderParser(self): + self._Scope = [] + self._SectionName = '' + self._SectionType = [] + ArchList = set() + for Item in GetSplitValueList(self._CurrentLine[1:-1], TAB_COMMA_SPLIT): + if Item == '': + continue + ItemList = GetSplitValueList(Item, TAB_SPLIT) + + # different types of PCD are permissible in one section + self._SectionName = ItemList[0].upper() + if self._SectionName in self.DataType: + if self.DataType[self._SectionName] not in self._SectionType: + self._SectionType.append(self.DataType[self._SectionName]) + else: + EdkLogger.warn("Parser", "Unrecognized section", File=self.MetaFile, + Line=self._LineIndex+1, ExtraData=self._CurrentLine) + continue + + if MODEL_PCD_FEATURE_FLAG in self._SectionType and len(self._SectionType) > 1: + EdkLogger.error( + 'Parser', + FORMAT_INVALID, + "%s must not be in the same section of other types of PCD" % TAB_PCDS_FEATURE_FLAG_NULL, + File=self.MetaFile, + Line=self._LineIndex+1, + ExtraData=self._CurrentLine + ) + # S1 is always Arch + if len(ItemList) > 1: + S1 = ItemList[1].upper() + else: + S1 = 'COMMON' + ArchList.add(S1) + # S2 may be Platform or ModuleType + if len(ItemList) > 2: + S2 = ItemList[2].upper() + else: + S2 = 'COMMON' + if [S1, S2, self.DataType[self._SectionName]] not in self._Scope: + self._Scope.append([S1, S2, self.DataType[self._SectionName]]) + + # 'COMMON' must not be used with specific ARCHs at the same section + if 'COMMON' in ArchList and len(ArchList) > 1: + EdkLogger.error('Parser', FORMAT_INVALID, "'common' ARCH must not be used with specific ARCHs", + File=self.MetaFile, Line=self._LineIndex+1, ExtraData=self._CurrentLine) + + ## [guids], [ppis] and [protocols] section parser + def _GuidParser(self): + TokenList = GetSplitValueList(self._CurrentLine, TAB_EQUAL_SPLIT, 1) + if len(TokenList) < 2: + EdkLogger.error('Parser', FORMAT_INVALID, "No GUID name or value specified", + ExtraData=self._CurrentLine + " ( = )", + File=self.MetaFile, Line=self._LineIndex+1) + if TokenList[0] == '': + EdkLogger.error('Parser', FORMAT_INVALID, "No GUID name specified", + ExtraData=self._CurrentLine + " ( = )", + File=self.MetaFile, Line=self._LineIndex+1) + if TokenList[1] == '': + EdkLogger.error('Parser', FORMAT_INVALID, "No GUID value specified", + ExtraData=self._CurrentLine + " ( = )", + File=self.MetaFile, Line=self._LineIndex+1) + if TokenList[1][0] != '{' or TokenList[1][-1] != '}' or GuidStructureStringToGuidString(TokenList[1]) == '': + EdkLogger.error('Parser', FORMAT_INVALID, "Invalid GUID value format", + ExtraData=self._CurrentLine + \ + " ( = )", + File=self.MetaFile, Line=self._LineIndex+1) + self._ValueList[0] = TokenList[0] + self._ValueList[1] = TokenList[1] + + ## PCD sections parser + # + # [PcdsFixedAtBuild] + # [PcdsPatchableInModule] + # [PcdsFeatureFlag] + # [PcdsDynamicEx + # [PcdsDynamic] + # + def _PcdParser(self): + TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT, 1) + self._ValueList[0:1] = GetSplitValueList(TokenList[0], TAB_SPLIT) + # check PCD information + if self._ValueList[0] == '' or self._ValueList[1] == '': + EdkLogger.error('Parser', FORMAT_INVALID, "No token space GUID or PCD name specified", + ExtraData=self._CurrentLine + \ + " (.|||)", + File=self.MetaFile, Line=self._LineIndex+1) + # check PCD datum information + if len(TokenList) < 2 or TokenList[1] == '': + EdkLogger.error('Parser', FORMAT_INVALID, "No PCD Datum information given", + ExtraData=self._CurrentLine + \ + " (.|||)", + File=self.MetaFile, Line=self._LineIndex+1) + + ValueList = GetSplitValueList(TokenList[1]) + # check if there's enough datum information given + if len(ValueList) != 3: + EdkLogger.error('Parser', FORMAT_INVALID, "Invalid PCD Datum information given", + ExtraData=self._CurrentLine + \ + " (.|||)", + File=self.MetaFile, Line=self._LineIndex+1) + # check default value + if ValueList[0] == '': + EdkLogger.error('Parser', FORMAT_INVALID, "Missing DefaultValue in PCD Datum information", + ExtraData=self._CurrentLine + \ + " (.|||)", + File=self.MetaFile, Line=self._LineIndex+1) + # check datum type + if ValueList[1] == '': + EdkLogger.error('Parser', FORMAT_INVALID, "Missing DatumType in PCD Datum information", + ExtraData=self._CurrentLine + \ + " (.|||)", + File=self.MetaFile, Line=self._LineIndex+1) + # check token of the PCD + if ValueList[2] == '': + EdkLogger.error('Parser', FORMAT_INVALID, "Missing Token in PCD Datum information", + ExtraData=self._CurrentLine + \ + " (.|||)", + File=self.MetaFile, Line=self._LineIndex+1) + # check format of default value against the datum type + IsValid, Cause = CheckPcdDatum(ValueList[1], ValueList[0]) + if not IsValid: + EdkLogger.error('Parser', FORMAT_INVALID, Cause, ExtraData=self._CurrentLine, + File=self.MetaFile, Line=self._LineIndex+1) + self._ValueList[2] = TokenList[1] + + _SectionParser = { + MODEL_META_DATA_HEADER : MetaFileParser._DefineParser, + MODEL_EFI_INCLUDE : MetaFileParser._PathParser, + MODEL_EFI_LIBRARY_CLASS : MetaFileParser._PathParser, + MODEL_EFI_GUID : _GuidParser, + MODEL_EFI_PPI : _GuidParser, + MODEL_EFI_PROTOCOL : _GuidParser, + MODEL_PCD_FIXED_AT_BUILD : _PcdParser, + MODEL_PCD_PATCHABLE_IN_MODULE : _PcdParser, + MODEL_PCD_FEATURE_FLAG : _PcdParser, + MODEL_PCD_DYNAMIC : _PcdParser, + MODEL_PCD_DYNAMIC_EX : _PcdParser, + MODEL_UNKNOWN : MetaFileParser._Skip, + MODEL_META_DATA_USER_EXTENSION : MetaFileParser._Skip, + } + +## +# +# This acts like the main() function for the script, unless it is 'import'ed into another +# script. +# +if __name__ == '__main__': + pass + diff --git a/BaseTools/Source/Python/Workspace/MetaFileTable.py b/BaseTools/Source/Python/Workspace/MetaFileTable.py new file mode 100644 index 0000000000..22e2afa4c9 --- /dev/null +++ b/BaseTools/Source/Python/Workspace/MetaFileTable.py @@ -0,0 +1,275 @@ +## @file +# This file is used to create/update/query/erase a meta file table +# +# Copyright (c) 2008, 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. +# + +## +# Import Modules +# +import Common.EdkLogger as EdkLogger +from MetaDataTable import Table +from MetaDataTable import ConvertToSqlString + +## Python class representation of table storing module data +class ModuleTable(Table): + # TRICK: use file ID as the part before '.' + _ID_STEP_ = 0.00000001 + _ID_MAX_ = 0.99999999 + _COLUMN_ = ''' + ID REAL PRIMARY KEY, + Model INTEGER NOT NULL, + Value1 TEXT NOT NULL, + Value2 TEXT, + Value3 TEXT, + Scope1 TEXT, + Scope2 TEXT, + BelongsToItem REAL NOT NULL, + StartLine INTEGER NOT NULL, + StartColumn INTEGER NOT NULL, + EndLine INTEGER NOT NULL, + EndColumn INTEGER NOT NULL, + Enabled INTEGER DEFAULT 0 + ''' + # used as table end flag, in case the changes to database is not committed to db file + _DUMMY_ = "-1, -1, '====', '====', '====', '====', '====', -1, -1, -1, -1, -1, -1" + + ## Constructor + def __init__(self, Cursor, Name='Inf', IdBase=0, Temporary=False): + Table.__init__(self, Cursor, Name, IdBase, Temporary) + + ## Insert a record into table Inf + # + # @param Model: Model of a Inf item + # @param Value1: Value1 of a Inf item + # @param Value2: Value2 of a Inf item + # @param Value3: Value3 of a Inf item + # @param Scope1: Arch of a Inf item + # @param Scope2 Platform os a Inf item + # @param BelongsToItem: The item belongs to which another item + # @param StartLine: StartLine of a Inf item + # @param StartColumn: StartColumn of a Inf item + # @param EndLine: EndLine of a Inf item + # @param EndColumn: EndColumn of a Inf item + # @param Enabled: If this item enabled + # + def Insert(self, Model, Value1, Value2, Value3, Scope1='COMMON', Scope2='COMMON', + BelongsToItem=-1, StartLine=-1, StartColumn=-1, EndLine=-1, EndColumn=-1, Enabled=0): + (Value1, Value2, Value3, Scope1, Scope2) = ConvertToSqlString((Value1, Value2, Value3, Scope1, Scope2)) + return Table.Insert( + self, + Model, + Value1, + Value2, + Value3, + Scope1, + Scope2, + BelongsToItem, + StartLine, + StartColumn, + EndLine, + EndColumn, + Enabled + ) + + ## Query table + # + # @param Model: The Model of Record + # @param Arch: The Arch attribute of Record + # @param Platform The Platform attribute of Record + # + # @retval: A recordSet of all found records + # + def Query(self, Model, Arch=None, Platform=None): + ConditionString = "Model=%s AND Enabled>=0" % Model + ValueString = "Value1,Value2,Value3,Scope1,Scope2,ID,StartLine" + + if Arch != None and Arch != 'COMMON': + ConditionString += " AND (Scope1='%s' OR Scope1='COMMON')" % Arch + if Platform != None and Platform != 'COMMON': + ConditionString += " AND (Scope2='%s' OR Scope2='COMMON' OR Scope2='DEFAULT')" % Platform + + SqlCommand = "SELECT %s FROM %s WHERE %s" % (ValueString, self.Table, ConditionString) + return self.Exec(SqlCommand) + +## Python class representation of table storing package data +class PackageTable(Table): + _ID_STEP_ = 0.00000001 + _ID_MAX_ = 0.99999999 + _COLUMN_ = ''' + ID REAL PRIMARY KEY, + Model INTEGER NOT NULL, + Value1 TEXT NOT NULL, + Value2 TEXT, + Value3 TEXT, + Scope1 TEXT, + Scope2 TEXT, + BelongsToItem REAL NOT NULL, + StartLine INTEGER NOT NULL, + StartColumn INTEGER NOT NULL, + EndLine INTEGER NOT NULL, + EndColumn INTEGER NOT NULL, + Enabled INTEGER DEFAULT 0 + ''' + # used as table end flag, in case the changes to database is not committed to db file + _DUMMY_ = "-1, -1, '====', '====', '====', '====', '====', -1, -1, -1, -1, -1, -1" + + ## Constructor + def __init__(self, Cursor, Name='Dec', IdBase=0, Temporary=False): + Table.__init__(self, Cursor, Name, IdBase, Temporary) + + ## Insert table + # + # Insert a record into table Dec + # + # @param Model: Model of a Dec item + # @param Value1: Value1 of a Dec item + # @param Value2: Value2 of a Dec item + # @param Value3: Value3 of a Dec item + # @param Scope1: Arch of a Dec item + # @param Scope2: Module type of a Dec item + # @param BelongsToItem: The item belongs to which another item + # @param StartLine: StartLine of a Dec item + # @param StartColumn: StartColumn of a Dec item + # @param EndLine: EndLine of a Dec item + # @param EndColumn: EndColumn of a Dec item + # @param Enabled: If this item enabled + # + def Insert(self, Model, Value1, Value2, Value3, Scope1='COMMON', Scope2='COMMON', + BelongsToItem=-1, StartLine=-1, StartColumn=-1, EndLine=-1, EndColumn=-1, Enabled=0): + (Value1, Value2, Value3, Scope1, Scope2) = ConvertToSqlString((Value1, Value2, Value3, Scope1, Scope2)) + return Table.Insert( + self, + Model, + Value1, + Value2, + Value3, + Scope1, + Scope2, + BelongsToItem, + StartLine, + StartColumn, + EndLine, + EndColumn, + Enabled + ) + + ## Query table + # + # @param Model: The Model of Record + # @param Arch: The Arch attribute of Record + # + # @retval: A recordSet of all found records + # + def Query(self, Model, Arch=None): + ConditionString = "Model=%s AND Enabled>=0" % Model + ValueString = "Value1,Value2,Value3,Scope1,ID,StartLine" + + if Arch != None and Arch != 'COMMON': + ConditionString += " AND (Scope1='%s' OR Scope1='COMMON')" % Arch + + SqlCommand = "SELECT %s FROM %s WHERE %s" % (ValueString, self.Table, ConditionString) + return self.Exec(SqlCommand) + +## Python class representation of table storing platform data +class PlatformTable(Table): + _ID_STEP_ = 0.00000001 + _ID_MAX_ = 0.99999999 + _COLUMN_ = ''' + ID REAL PRIMARY KEY, + Model INTEGER NOT NULL, + Value1 TEXT NOT NULL, + Value2 TEXT, + Value3 TEXT, + Scope1 TEXT, + Scope2 TEXT, + BelongsToItem REAL NOT NULL, + FromItem REAL NOT NULL, + StartLine INTEGER NOT NULL, + StartColumn INTEGER NOT NULL, + EndLine INTEGER NOT NULL, + EndColumn INTEGER NOT NULL, + Enabled INTEGER DEFAULT 0 + ''' + # used as table end flag, in case the changes to database is not committed to db file + _DUMMY_ = "-1, -1, '====', '====', '====', '====', '====', -1, -1, -1, -1, -1, -1, -1" + + ## Constructor + def __init__(self, Cursor, Name='Dsc', IdBase=0, Temporary=False): + Table.__init__(self, Cursor, Name, IdBase, Temporary) + + ## Insert table + # + # Insert a record into table Dsc + # + # @param Model: Model of a Dsc item + # @param Value1: Value1 of a Dsc item + # @param Value2: Value2 of a Dsc item + # @param Value3: Value3 of a Dsc item + # @param Scope1: Arch of a Dsc item + # @param Scope2: Module type of a Dsc item + # @param BelongsToItem: The item belongs to which another item + # @param FromItem: The item belongs to which dsc file + # @param StartLine: StartLine of a Dsc item + # @param StartColumn: StartColumn of a Dsc item + # @param EndLine: EndLine of a Dsc item + # @param EndColumn: EndColumn of a Dsc item + # @param Enabled: If this item enabled + # + def Insert(self, Model, Value1, Value2, Value3, Scope1='COMMON', Scope2='COMMON', BelongsToItem=-1, + FromItem=-1, StartLine=-1, StartColumn=-1, EndLine=-1, EndColumn=-1, Enabled=1): + (Value1, Value2, Value3, Scope1, Scope2) = ConvertToSqlString((Value1, Value2, Value3, Scope1, Scope2)) + return Table.Insert( + self, + Model, + Value1, + Value2, + Value3, + Scope1, + Scope2, + BelongsToItem, + FromItem, + StartLine, + StartColumn, + EndLine, + EndColumn, + Enabled + ) + + ## Query table + # + # @param Model: The Model of Record + # @param Scope1: Arch of a Dsc item + # @param Scope2: Module type of a Dsc item + # @param BelongsToItem: The item belongs to which another item + # @param FromItem: The item belongs to which dsc file + # + # @retval: A recordSet of all found records + # + def Query(self, Model, Scope1=None, Scope2=None, BelongsToItem=None, FromItem=None): + ConditionString = "Model=%s AND Enabled>=0" % Model + ValueString = "Value1,Value2,Value3,Scope1,Scope2,ID,StartLine" + + if Scope1 != None and Scope1 != 'COMMON': + ConditionString += " AND (Scope1='%s' OR Scope1='COMMON')" % Scope1 + if Scope2 != None and Scope2 != 'COMMON': + ConditionString += " AND (Scope2='%s' OR Scope2='COMMON' OR Scope2='DEFAULT')" % Scope2 + + if BelongsToItem != None: + ConditionString += " AND BelongsToItem=%s" % BelongsToItem + else: + ConditionString += " AND BelongsToItem<0" + + if FromItem != None: + ConditionString += " AND FromItem=%s" % FromItem + + SqlCommand = "SELECT %s FROM %s WHERE %s" % (ValueString, self.Table, ConditionString) + return self.Exec(SqlCommand) + diff --git a/BaseTools/Source/Python/Workspace/WorkspaceDatabase.py b/BaseTools/Source/Python/Workspace/WorkspaceDatabase.py new file mode 100644 index 0000000000..8f0056e197 --- /dev/null +++ b/BaseTools/Source/Python/Workspace/WorkspaceDatabase.py @@ -0,0 +1,2274 @@ +## @file +# This file is used to create a database used by build tool +# +# Copyright (c) 2008, 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. +# + +## +# Import Modules +# +import sqlite3 +import os +import os.path + +import Common.EdkLogger as EdkLogger +import Common.GlobalData as GlobalData + +from Common.String import * +from Common.DataType import * +from Common.Misc import * + +from CommonDataClass.CommonClass import SkuInfoClass + +from MetaDataTable import * +from MetaFileTable import * +from MetaFileParser import * +from BuildClassObject import * + +## Platform build information from DSC file +# +# This class is used to retrieve information stored in database and convert them +# into PlatformBuildClassObject form for easier use for AutoGen. +# +class DscBuildData(PlatformBuildClassObject): + # dict used to convert PCD type in database to string used by build tool + _PCD_TYPE_STRING_ = { + MODEL_PCD_FIXED_AT_BUILD : "FixedAtBuild", + MODEL_PCD_PATCHABLE_IN_MODULE : "PatchableInModule", + MODEL_PCD_FEATURE_FLAG : "FeatureFlag", + MODEL_PCD_DYNAMIC : "Dynamic", + MODEL_PCD_DYNAMIC_DEFAULT : "Dynamic", + MODEL_PCD_DYNAMIC_HII : "DynamicHii", + MODEL_PCD_DYNAMIC_VPD : "DynamicVpd", + MODEL_PCD_DYNAMIC_EX : "DynamicEx", + MODEL_PCD_DYNAMIC_EX_DEFAULT : "DynamicEx", + MODEL_PCD_DYNAMIC_EX_HII : "DynamicExHii", + MODEL_PCD_DYNAMIC_EX_VPD : "DynamicExVpd", + } + + # dict used to convert part of [Defines] to members of DscBuildData directly + _PROPERTY_ = { + # + # Required Fields + # + TAB_DSC_DEFINES_PLATFORM_NAME : "_PlatformName", + TAB_DSC_DEFINES_PLATFORM_GUID : "_Guid", + TAB_DSC_DEFINES_PLATFORM_VERSION : "_Version", + TAB_DSC_DEFINES_DSC_SPECIFICATION : "_DscSpecification", + #TAB_DSC_DEFINES_OUTPUT_DIRECTORY : "_OutputDirectory", + #TAB_DSC_DEFINES_SUPPORTED_ARCHITECTURES : "_SupArchList", + #TAB_DSC_DEFINES_BUILD_TARGETS : "_BuildTargets", + #TAB_DSC_DEFINES_SKUID_IDENTIFIER : "_SkuName", + #TAB_DSC_DEFINES_FLASH_DEFINITION : "_FlashDefinition", + TAB_DSC_DEFINES_BUILD_NUMBER : "_BuildNumber", + TAB_DSC_DEFINES_MAKEFILE_NAME : "_MakefileName", + TAB_DSC_DEFINES_BS_BASE_ADDRESS : "_BsBaseAddress", + TAB_DSC_DEFINES_RT_BASE_ADDRESS : "_RtBaseAddress", + } + + # used to compose dummy library class name for those forced library instances + _NullLibraryNumber = 0 + + ## Constructor of DscBuildData + # + # Initialize object of DscBuildData + # + # @param FilePath The path of platform description file + # @param RawData The raw data of DSC file + # @param BuildDataBase Database used to retrieve module/package information + # @param Arch The target architecture + # @param Platform (not used for DscBuildData) + # @param Macros Macros used for replacement in DSC file + # + def __init__(self, FilePath, RawData, BuildDataBase, Arch='COMMON', Platform='DUMMY', Macros={}): + self.MetaFile = FilePath + self._RawData = RawData + self._Bdb = BuildDataBase + self._Arch = Arch + self._Macros = Macros + self._Clear() + RecordList = self._RawData[MODEL_META_DATA_DEFINE, self._Arch] + for Record in RecordList: + GlobalData.gEdkGlobal[Record[0]] = Record[1] + + ## XXX[key] = value + def __setitem__(self, key, value): + self.__dict__[self._PROPERTY_[key]] = value + + ## value = XXX[key] + def __getitem__(self, key): + return self.__dict__[self._PROPERTY_[key]] + + ## "in" test support + def __contains__(self, key): + return key in self._PROPERTY_ + + ## Set all internal used members of DscBuildData to None + def _Clear(self): + self._Header = None + self._PlatformName = None + self._Guid = None + self._Version = None + self._DscSpecification = None + self._OutputDirectory = None + self._SupArchList = None + self._BuildTargets = None + self._SkuName = None + self._FlashDefinition = None + self._BuildNumber = None + self._MakefileName = None + self._BsBaseAddress = None + self._RtBaseAddress = None + self._SkuIds = None + self._Modules = None + self._LibraryInstances = None + self._LibraryClasses = None + self._Pcds = None + self._BuildOptions = None + + ## Get architecture + def _GetArch(self): + return self._Arch + + ## Set architecture + # + # Changing the default ARCH to another may affect all other information + # because all information in a platform may be ARCH-related. That's + # why we need to clear all internal used members, in order to cause all + # information to be re-retrieved. + # + # @param Value The value of ARCH + # + def _SetArch(self, Value): + if self._Arch == Value: + return + self._Arch = Value + self._Clear() + + ## Retrieve all information in [Defines] section + # + # (Retriving all [Defines] information in one-shot is just to save time.) + # + def _GetHeaderInfo(self): + RecordList = self._RawData[MODEL_META_DATA_HEADER, self._Arch] + for Record in RecordList: + Name = Record[0] + # items defined _PROPERTY_ don't need additional processing + if Name in self: + self[Name] = Record[1] + # some special items in [Defines] section need special treatment + elif Name == TAB_DSC_DEFINES_OUTPUT_DIRECTORY: + self._OutputDirectory = NormPath(Record[1], self._Macros) + if ' ' in self._OutputDirectory: + EdkLogger.error("build", FORMAT_NOT_SUPPORTED, "No space is allowed in OUTPUT_DIRECTORY", + File=self.MetaFile, Line=Record[-1], + ExtraData=self._OutputDirectory) + elif Name == TAB_DSC_DEFINES_FLASH_DEFINITION: + self._FlashDefinition = PathClass(NormPath(Record[1], self._Macros), GlobalData.gWorkspace) + ErrorCode, ErrorInfo = self._FlashDefinition.Validate('.fdf') + if ErrorCode != 0: + EdkLogger.error('build', ErrorCode, File=self.MetaFile, Line=Record[-1], + ExtraData=ErrorInfo) + elif Name == TAB_DSC_DEFINES_SUPPORTED_ARCHITECTURES: + self._SupArchList = GetSplitValueList(Record[1], TAB_VALUE_SPLIT) + elif Name == TAB_DSC_DEFINES_BUILD_TARGETS: + self._BuildTargets = GetSplitValueList(Record[1]) + elif Name == TAB_DSC_DEFINES_SKUID_IDENTIFIER: + if self._SkuName == None: + self._SkuName = Record[1] + # set _Header to non-None in order to avoid database re-querying + self._Header = 'DUMMY' + + ## Retrieve platform name + def _GetPlatformName(self): + if self._PlatformName == None: + if self._Header == None: + self._GetHeaderInfo() + if self._PlatformName == None: + EdkLogger.error('build', ATTRIBUTE_NOT_AVAILABLE, "No PLATFORM_NAME", File=self.MetaFile) + return self._PlatformName + + ## Retrieve file guid + def _GetFileGuid(self): + if self._Guid == None: + if self._Header == None: + self._GetHeaderInfo() + if self._Guid == None: + EdkLogger.error('build', ATTRIBUTE_NOT_AVAILABLE, "No FILE_GUID", File=self.MetaFile) + return self._Guid + + ## Retrieve platform version + def _GetVersion(self): + if self._Version == None: + if self._Header == None: + self._GetHeaderInfo() + if self._Version == None: + self._Version = '' + return self._Version + + ## Retrieve platform description file version + def _GetDscSpec(self): + if self._DscSpecification == None: + if self._Header == None: + self._GetHeaderInfo() + if self._DscSpecification == None: + self._DscSpecification = '' + return self._DscSpecification + + ## Retrieve OUTPUT_DIRECTORY + def _GetOutpuDir(self): + if self._OutputDirectory == None: + if self._Header == None: + self._GetHeaderInfo() + if self._OutputDirectory == None: + self._OutputDirectory = os.path.join("Build", self._PlatformName) + return self._OutputDirectory + + ## Retrieve SUPPORTED_ARCHITECTURES + def _GetSupArch(self): + if self._SupArchList == None: + if self._Header == None: + self._GetHeaderInfo() + if self._SupArchList == None: + self._SupArchList = ARCH_LIST + return self._SupArchList + + ## Retrieve BUILD_TARGETS + def _GetBuildTarget(self): + if self._BuildTargets == None: + if self._Header == None: + self._GetHeaderInfo() + if self._BuildTargets == None: + self._BuildTargets = ['DEBUG', 'RELEASE'] + return self._BuildTargets + + ## Retrieve SKUID_IDENTIFIER + def _GetSkuName(self): + if self._SkuName == None: + if self._Header == None: + self._GetHeaderInfo() + if self._SkuName == None or self._SkuName not in self.SkuIds: + self._SkuName = 'DEFAULT' + return self._SkuName + + ## Override SKUID_IDENTIFIER + def _SetSkuName(self, Value): + if Value in self.SkuIds: + self._SkuName = Value + + def _GetFdfFile(self): + if self._FlashDefinition == None: + if self._Header == None: + self._GetHeaderInfo() + if self._FlashDefinition == None: + self._FlashDefinition = '' + return self._FlashDefinition + + ## Retrieve FLASH_DEFINITION + def _GetBuildNumber(self): + if self._BuildNumber == None: + if self._Header == None: + self._GetHeaderInfo() + if self._BuildNumber == None: + self._BuildNumber = '' + return self._BuildNumber + + ## Retrieve MAKEFILE_NAME + def _GetMakefileName(self): + if self._MakefileName == None: + if self._Header == None: + self._GetHeaderInfo() + if self._MakefileName == None: + self._MakefileName = '' + return self._MakefileName + + ## Retrieve BsBaseAddress + def _GetBsBaseAddress(self): + if self._BsBaseAddress == None: + if self._Header == None: + self._GetHeaderInfo() + if self._BsBaseAddress == None: + self._BsBaseAddress = '' + return self._BsBaseAddress + + ## Retrieve RtBaseAddress + def _GetRtBaseAddress(self): + if self._RtBaseAddress == None: + if self._Header == None: + self._GetHeaderInfo() + if self._RtBaseAddress == None: + self._RtBaseAddress = '' + return self._RtBaseAddress + + ## Retrieve [SkuIds] section information + def _GetSkuIds(self): + if self._SkuIds == None: + self._SkuIds = {} + RecordList = self._RawData[MODEL_EFI_SKU_ID] + for Record in RecordList: + if Record[0] in [None, '']: + EdkLogger.error('build', FORMAT_INVALID, 'No Sku ID number', + File=self.MetaFile, Line=Record[-1]) + if Record[1] in [None, '']: + EdkLogger.error('build', FORMAT_INVALID, 'No Sku ID name', + File=self.MetaFile, Line=Record[-1]) + self._SkuIds[Record[1]] = Record[0] + if 'DEFAULT' not in self._SkuIds: + self._SkuIds['DEFAULT'] = 0 + return self._SkuIds + + ## Retrieve [Components] section information + def _GetModules(self): + if self._Modules != None: + return self._Modules + + self._Modules = sdict() + RecordList = self._RawData[MODEL_META_DATA_COMPONENT, self._Arch] + Macros = {"EDK_SOURCE":GlobalData.gEcpSource, "EFI_SOURCE":GlobalData.gEfiSource} + Macros.update(self._Macros) + for Record in RecordList: + ModuleFile = PathClass(NormPath(Record[0], Macros), GlobalData.gWorkspace, Arch=self._Arch) + ModuleId = Record[5] + LineNo = Record[6] + + # check the file validation + ErrorCode, ErrorInfo = ModuleFile.Validate('.inf') + if ErrorCode != 0: + EdkLogger.error('build', ErrorCode, File=self.MetaFile, Line=LineNo, + ExtraData=ErrorInfo) + # Check duplication + if ModuleFile in self._Modules: + EdkLogger.error('build', FILE_DUPLICATED, File=self.MetaFile, ExtraData=str(ModuleFile), Line=LineNo) + + Module = ModuleBuildClassObject() + Module.MetaFile = ModuleFile + + # get module override path + RecordList = self._RawData[MODEL_META_DATA_COMPONENT_SOURCE_OVERRIDE_PATH, self._Arch, None, ModuleId] + if RecordList != []: + Module.SourceOverridePath = os.path.join(GlobalData.gWorkspace, NormPath(RecordList[0][0], Macros)) + + # Check if the source override path exists + if not os.path.isdir(Module.SourceOverridePath): + EdkLogger.error('build', FILE_NOT_FOUND, Message = 'Source override path does not exist:', File=self.MetaFile, ExtraData=Module.SourceOverridePath, Line=LineNo) + + #Add to GlobalData Variables + GlobalData.gOverrideDir[ModuleFile.Key] = Module.SourceOverridePath + + # get module private library instance + RecordList = self._RawData[MODEL_EFI_LIBRARY_CLASS, self._Arch, None, ModuleId] + for Record in RecordList: + LibraryClass = Record[0] + LibraryPath = PathClass(NormPath(Record[1], Macros), GlobalData.gWorkspace, Arch=self._Arch) + LineNo = Record[-1] + + # check the file validation + ErrorCode, ErrorInfo = LibraryPath.Validate('.inf') + if ErrorCode != 0: + EdkLogger.error('build', ErrorCode, File=self.MetaFile, Line=LineNo, + ExtraData=ErrorInfo) + + if LibraryClass == '' or LibraryClass == 'NULL': + self._NullLibraryNumber += 1 + LibraryClass = 'NULL%d' % self._NullLibraryNumber + EdkLogger.verbose("Found forced library for %s\n\t%s [%s]" % (ModuleFile, LibraryPath, LibraryClass)) + Module.LibraryClasses[LibraryClass] = LibraryPath + if LibraryPath not in self.LibraryInstances: + self.LibraryInstances.append(LibraryPath) + + # get module private PCD setting + for Type in [MODEL_PCD_FIXED_AT_BUILD, MODEL_PCD_PATCHABLE_IN_MODULE, \ + MODEL_PCD_FEATURE_FLAG, MODEL_PCD_DYNAMIC, MODEL_PCD_DYNAMIC_EX]: + RecordList = self._RawData[Type, self._Arch, None, ModuleId] + for TokenSpaceGuid, PcdCName, Setting, Dummy1, Dummy2, Dummy3, Dummy4 in RecordList: + TokenList = GetSplitValueList(Setting) + DefaultValue = TokenList[0] + if len(TokenList) > 1: + MaxDatumSize = TokenList[1] + else: + MaxDatumSize = '' + TypeString = self._PCD_TYPE_STRING_[Type] + Pcd = PcdClassObject( + PcdCName, + TokenSpaceGuid, + TypeString, + '', + DefaultValue, + '', + MaxDatumSize, + {}, + None + ) + Module.Pcds[PcdCName, TokenSpaceGuid] = Pcd + + # get module private build options + RecordList = self._RawData[MODEL_META_DATA_BUILD_OPTION, self._Arch, None, ModuleId] + for ToolChainFamily, ToolChain, Option, Dummy1, Dummy2, Dummy3, Dummy4 in RecordList: + if (ToolChainFamily, ToolChain) not in Module.BuildOptions: + Module.BuildOptions[ToolChainFamily, ToolChain] = Option + else: + OptionString = Module.BuildOptions[ToolChainFamily, ToolChain] + Module.BuildOptions[ToolChainFamily, ToolChain] = OptionString + " " + Option + + self._Modules[ModuleFile] = Module + return self._Modules + + ## Retrieve all possible library instances used in this platform + def _GetLibraryInstances(self): + if self._LibraryInstances == None: + self._GetLibraryClasses() + return self._LibraryInstances + + ## Retrieve [LibraryClasses] information + def _GetLibraryClasses(self): + if self._LibraryClasses == None: + self._LibraryInstances = [] + # + # tdict is a special dict kind of type, used for selecting correct + # library instance for given library class and module type + # + LibraryClassDict = tdict(True, 3) + # track all library class names + LibraryClassSet = set() + RecordList = self._RawData[MODEL_EFI_LIBRARY_CLASS, self._Arch] + Macros = {"EDK_SOURCE":GlobalData.gEcpSource, "EFI_SOURCE":GlobalData.gEfiSource} + Macros.update(self._Macros) + for Record in RecordList: + LibraryClass, LibraryInstance, Dummy, Arch, ModuleType, Dummy, LineNo = Record + LibraryClassSet.add(LibraryClass) + LibraryInstance = PathClass(NormPath(LibraryInstance, Macros), GlobalData.gWorkspace, Arch=self._Arch) + # check the file validation + ErrorCode, ErrorInfo = LibraryInstance.Validate('.inf') + if ErrorCode != 0: + EdkLogger.error('build', ErrorCode, File=self.MetaFile, Line=LineNo, + ExtraData=ErrorInfo) + + if ModuleType != 'COMMON' and ModuleType not in SUP_MODULE_LIST: + EdkLogger.error('build', OPTION_UNKNOWN, "Unknown module type [%s]" % ModuleType, + File=self.MetaFile, ExtraData=LibraryInstance, Line=LineNo) + LibraryClassDict[Arch, ModuleType, LibraryClass] = LibraryInstance + if LibraryInstance not in self._LibraryInstances: + self._LibraryInstances.append(LibraryInstance) + + # resolve the specific library instance for each class and each module type + self._LibraryClasses = tdict(True) + for LibraryClass in LibraryClassSet: + # try all possible module types + for ModuleType in SUP_MODULE_LIST: + LibraryInstance = LibraryClassDict[self._Arch, ModuleType, LibraryClass] + if LibraryInstance == None: + continue + self._LibraryClasses[LibraryClass, ModuleType] = LibraryInstance + + # for R8 style library instances, which are listed in different section + RecordList = self._RawData[MODEL_EFI_LIBRARY_INSTANCE, self._Arch] + for Record in RecordList: + File = PathClass(NormPath(Record[0], Macros), GlobalData.gWorkspace, Arch=self._Arch) + LineNo = Record[-1] + # check the file validation + ErrorCode, ErrorInfo = File.Validate('.inf') + if ErrorCode != 0: + EdkLogger.error('build', ErrorCode, File=self.MetaFile, Line=LineNo, + ExtraData=ErrorInfo) + if File not in self._LibraryInstances: + self._LibraryInstances.append(File) + # + # we need the module name as the library class name, so we have + # to parse it here. (self._Bdb[] will trigger a file parse if it + # hasn't been parsed) + # + Library = self._Bdb[File, self._Arch] + self._LibraryClasses[Library.BaseName, ':dummy:'] = Library + return self._LibraryClasses + + ## Retrieve all PCD settings in platform + def _GetPcds(self): + if self._Pcds == None: + self._Pcds = {} + self._Pcds.update(self._GetPcd(MODEL_PCD_FIXED_AT_BUILD)) + self._Pcds.update(self._GetPcd(MODEL_PCD_PATCHABLE_IN_MODULE)) + self._Pcds.update(self._GetPcd(MODEL_PCD_FEATURE_FLAG)) + self._Pcds.update(self._GetDynamicPcd(MODEL_PCD_DYNAMIC_DEFAULT)) + self._Pcds.update(self._GetDynamicHiiPcd(MODEL_PCD_DYNAMIC_HII)) + self._Pcds.update(self._GetDynamicVpdPcd(MODEL_PCD_DYNAMIC_VPD)) + self._Pcds.update(self._GetDynamicPcd(MODEL_PCD_DYNAMIC_EX_DEFAULT)) + self._Pcds.update(self._GetDynamicHiiPcd(MODEL_PCD_DYNAMIC_EX_HII)) + self._Pcds.update(self._GetDynamicVpdPcd(MODEL_PCD_DYNAMIC_EX_VPD)) + return self._Pcds + + ## Retrieve [BuildOptions] + def _GetBuildOptions(self): + if self._BuildOptions == None: + self._BuildOptions = {} + RecordList = self._RawData[MODEL_META_DATA_BUILD_OPTION] + for ToolChainFamily, ToolChain, Option, Dummy1, Dummy2, Dummy3, Dummy4 in RecordList: + self._BuildOptions[ToolChainFamily, ToolChain] = Option + return self._BuildOptions + + ## Retrieve non-dynamic PCD settings + # + # @param Type PCD type + # + # @retval a dict object contains settings of given PCD type + # + def _GetPcd(self, Type): + Pcds = {} + # + # tdict is a special dict kind of type, used for selecting correct + # PCD settings for certain ARCH + # + PcdDict = tdict(True, 3) + PcdSet = set() + # Find out all possible PCD candidates for self._Arch + RecordList = self._RawData[Type, self._Arch] + for TokenSpaceGuid, PcdCName, Setting, Arch, SkuName, Dummy3, Dummy4 in RecordList: + PcdSet.add((PcdCName, TokenSpaceGuid)) + PcdDict[Arch, PcdCName, TokenSpaceGuid] = Setting + # Remove redundant PCD candidates + for PcdCName, TokenSpaceGuid in PcdSet: + ValueList = ['', '', ''] + Setting = PcdDict[self._Arch, PcdCName, TokenSpaceGuid] + if Setting == None: + continue + TokenList = Setting.split(TAB_VALUE_SPLIT) + ValueList[0:len(TokenList)] = TokenList + PcdValue, DatumType, MaxDatumSize = ValueList + Pcds[PcdCName, TokenSpaceGuid] = PcdClassObject( + PcdCName, + TokenSpaceGuid, + self._PCD_TYPE_STRING_[Type], + DatumType, + PcdValue, + '', + MaxDatumSize, + {}, + None + ) + return Pcds + + ## Retrieve dynamic PCD settings + # + # @param Type PCD type + # + # @retval a dict object contains settings of given PCD type + # + def _GetDynamicPcd(self, Type): + Pcds = {} + # + # tdict is a special dict kind of type, used for selecting correct + # PCD settings for certain ARCH and SKU + # + PcdDict = tdict(True, 4) + PcdSet = set() + # Find out all possible PCD candidates for self._Arch + RecordList = self._RawData[Type, self._Arch] + for TokenSpaceGuid, PcdCName, Setting, Arch, SkuName, Dummy3, Dummy4 in RecordList: + PcdSet.add((PcdCName, TokenSpaceGuid)) + PcdDict[Arch, SkuName, PcdCName, TokenSpaceGuid] = Setting + # Remove redundant PCD candidates, per the ARCH and SKU + for PcdCName, TokenSpaceGuid in PcdSet: + ValueList = ['', '', ''] + Setting = PcdDict[self._Arch, self.SkuName, PcdCName, TokenSpaceGuid] + if Setting == None: + continue + TokenList = Setting.split(TAB_VALUE_SPLIT) + ValueList[0:len(TokenList)] = TokenList + PcdValue, DatumType, MaxDatumSize = ValueList + + SkuInfo = SkuInfoClass(self.SkuName, self.SkuIds[self.SkuName], '', '', '', '', '', PcdValue) + Pcds[PcdCName, TokenSpaceGuid] = PcdClassObject( + PcdCName, + TokenSpaceGuid, + self._PCD_TYPE_STRING_[Type], + DatumType, + PcdValue, + '', + MaxDatumSize, + {self.SkuName : SkuInfo}, + None + ) + return Pcds + + ## Retrieve dynamic HII PCD settings + # + # @param Type PCD type + # + # @retval a dict object contains settings of given PCD type + # + def _GetDynamicHiiPcd(self, Type): + Pcds = {} + # + # tdict is a special dict kind of type, used for selecting correct + # PCD settings for certain ARCH and SKU + # + PcdDict = tdict(True, 4) + PcdSet = set() + RecordList = self._RawData[Type, self._Arch] + # Find out all possible PCD candidates for self._Arch + for TokenSpaceGuid, PcdCName, Setting, Arch, SkuName, Dummy3, Dummy4 in RecordList: + PcdSet.add((PcdCName, TokenSpaceGuid)) + PcdDict[Arch, SkuName, PcdCName, TokenSpaceGuid] = Setting + # Remove redundant PCD candidates, per the ARCH and SKU + for PcdCName, TokenSpaceGuid in PcdSet: + ValueList = ['', '', '', ''] + Setting = PcdDict[self._Arch, self.SkuName, PcdCName, TokenSpaceGuid] + if Setting == None: + continue + TokenList = Setting.split(TAB_VALUE_SPLIT) + ValueList[0:len(TokenList)] = TokenList + VariableName, VariableGuid, VariableOffset, DefaultValue = ValueList + SkuInfo = SkuInfoClass(self.SkuName, self.SkuIds[self.SkuName], VariableName, VariableGuid, VariableOffset, DefaultValue) + Pcds[PcdCName, TokenSpaceGuid] = PcdClassObject( + PcdCName, + TokenSpaceGuid, + self._PCD_TYPE_STRING_[Type], + '', + DefaultValue, + '', + '', + {self.SkuName : SkuInfo}, + None + ) + return Pcds + + ## Retrieve dynamic VPD PCD settings + # + # @param Type PCD type + # + # @retval a dict object contains settings of given PCD type + # + def _GetDynamicVpdPcd(self, Type): + Pcds = {} + # + # tdict is a special dict kind of type, used for selecting correct + # PCD settings for certain ARCH and SKU + # + PcdDict = tdict(True, 4) + PcdSet = set() + # Find out all possible PCD candidates for self._Arch + RecordList = self._RawData[Type, self._Arch] + for TokenSpaceGuid, PcdCName, Setting, Arch, SkuName, Dummy3, Dummy4 in RecordList: + PcdSet.add((PcdCName, TokenSpaceGuid)) + PcdDict[Arch, SkuName, PcdCName, TokenSpaceGuid] = Setting + # Remove redundant PCD candidates, per the ARCH and SKU + for PcdCName, TokenSpaceGuid in PcdSet: + ValueList = ['', ''] + Setting = PcdDict[self._Arch, self.SkuName, PcdCName, TokenSpaceGuid] + if Setting == None: + continue + TokenList = Setting.split(TAB_VALUE_SPLIT) + ValueList[0:len(TokenList)] = TokenList + VpdOffset, MaxDatumSize = ValueList + + SkuInfo = SkuInfoClass(self.SkuName, self.SkuIds[self.SkuName], '', '', '', '', VpdOffset) + Pcds[PcdCName, TokenSpaceGuid] = PcdClassObject( + PcdCName, + TokenSpaceGuid, + self._PCD_TYPE_STRING_[Type], + '', + '', + '', + MaxDatumSize, + {self.SkuName : SkuInfo}, + None + ) + return Pcds + + ## Add external modules + # + # The external modules are mostly those listed in FDF file, which don't + # need "build". + # + # @param FilePath The path of module description file + # + def AddModule(self, FilePath): + FilePath = NormPath(FilePath) + if FilePath not in self.Modules: + Module = ModuleBuildClassObject() + Module.MetaFile = FilePath + self.Modules.append(Module) + + ## Add external PCDs + # + # The external PCDs are mostly those listed in FDF file to specify address + # or offset information. + # + # @param Name Name of the PCD + # @param Guid Token space guid of the PCD + # @param Value Value of the PCD + # + def AddPcd(self, Name, Guid, Value): + if (Name, Guid) not in self.Pcds: + self.Pcds[Name, Guid] = PcdClassObject(Name, Guid, '', '', '', '', '', {}, None) + self.Pcds[Name, Guid].DefaultValue = Value + + Arch = property(_GetArch, _SetArch) + Platform = property(_GetPlatformName) + PlatformName = property(_GetPlatformName) + Guid = property(_GetFileGuid) + Version = property(_GetVersion) + DscSpecification = property(_GetDscSpec) + OutputDirectory = property(_GetOutpuDir) + SupArchList = property(_GetSupArch) + BuildTargets = property(_GetBuildTarget) + SkuName = property(_GetSkuName, _SetSkuName) + FlashDefinition = property(_GetFdfFile) + BuildNumber = property(_GetBuildNumber) + MakefileName = property(_GetMakefileName) + BsBaseAddress = property(_GetBsBaseAddress) + RtBaseAddress = property(_GetRtBaseAddress) + + SkuIds = property(_GetSkuIds) + Modules = property(_GetModules) + LibraryInstances = property(_GetLibraryInstances) + LibraryClasses = property(_GetLibraryClasses) + Pcds = property(_GetPcds) + BuildOptions = property(_GetBuildOptions) + +## Platform build information from DSC file +# +# This class is used to retrieve information stored in database and convert them +# into PackageBuildClassObject form for easier use for AutoGen. +# +class DecBuildData(PackageBuildClassObject): + # dict used to convert PCD type in database to string used by build tool + _PCD_TYPE_STRING_ = { + MODEL_PCD_FIXED_AT_BUILD : "FixedAtBuild", + MODEL_PCD_PATCHABLE_IN_MODULE : "PatchableInModule", + MODEL_PCD_FEATURE_FLAG : "FeatureFlag", + MODEL_PCD_DYNAMIC : "Dynamic", + MODEL_PCD_DYNAMIC_DEFAULT : "Dynamic", + MODEL_PCD_DYNAMIC_HII : "DynamicHii", + MODEL_PCD_DYNAMIC_VPD : "DynamicVpd", + MODEL_PCD_DYNAMIC_EX : "DynamicEx", + MODEL_PCD_DYNAMIC_EX_DEFAULT : "DynamicEx", + MODEL_PCD_DYNAMIC_EX_HII : "DynamicExHii", + MODEL_PCD_DYNAMIC_EX_VPD : "DynamicExVpd", + } + + # dict used to convert part of [Defines] to members of DecBuildData directly + _PROPERTY_ = { + # + # Required Fields + # + TAB_DEC_DEFINES_PACKAGE_NAME : "_PackageName", + TAB_DEC_DEFINES_PACKAGE_GUID : "_Guid", + TAB_DEC_DEFINES_PACKAGE_VERSION : "_Version", + } + + + ## Constructor of DecBuildData + # + # Initialize object of DecBuildData + # + # @param FilePath The path of package description file + # @param RawData The raw data of DEC file + # @param BuildDataBase Database used to retrieve module information + # @param Arch The target architecture + # @param Platform (not used for DecBuildData) + # @param Macros Macros used for replacement in DSC file + # + def __init__(self, File, RawData, BuildDataBase, Arch='COMMON', Platform='DUMMY', Macros={}): + self.MetaFile = File + self._PackageDir = File.Dir + self._RawData = RawData + self._Bdb = BuildDataBase + self._Arch = Arch + self._Macros = Macros + self._Clear() + + ## XXX[key] = value + def __setitem__(self, key, value): + self.__dict__[self._PROPERTY_[key]] = value + + ## value = XXX[key] + def __getitem__(self, key): + return self.__dict__[self._PROPERTY_[key]] + + ## "in" test support + def __contains__(self, key): + return key in self._PROPERTY_ + + ## Set all internal used members of DecBuildData to None + def _Clear(self): + self._Header = None + self._PackageName = None + self._Guid = None + self._Version = None + self._Protocols = None + self._Ppis = None + self._Guids = None + self._Includes = None + self._LibraryClasses = None + self._Pcds = None + + ## Get architecture + def _GetArch(self): + return self._Arch + + ## Set architecture + # + # Changing the default ARCH to another may affect all other information + # because all information in a platform may be ARCH-related. That's + # why we need to clear all internal used members, in order to cause all + # information to be re-retrieved. + # + # @param Value The value of ARCH + # + def _SetArch(self, Value): + if self._Arch == Value: + return + self._Arch = Value + self._Clear() + + ## Retrieve all information in [Defines] section + # + # (Retriving all [Defines] information in one-shot is just to save time.) + # + def _GetHeaderInfo(self): + RecordList = self._RawData[MODEL_META_DATA_HEADER] + for Record in RecordList: + Name = Record[0] + if Name in self: + self[Name] = Record[1] + self._Header = 'DUMMY' + + ## Retrieve package name + def _GetPackageName(self): + if self._PackageName == None: + if self._Header == None: + self._GetHeaderInfo() + if self._PackageName == None: + EdkLogger.error("build", ATTRIBUTE_NOT_AVAILABLE, "No PACKAGE_NAME", File=self.MetaFile) + return self._PackageName + + ## Retrieve file guid + def _GetFileGuid(self): + if self._Guid == None: + if self._Header == None: + self._GetHeaderInfo() + if self._Guid == None: + EdkLogger.error("build", ATTRIBUTE_NOT_AVAILABLE, "No PACKAGE_GUID", File=self.MetaFile) + return self._Guid + + ## Retrieve package version + def _GetVersion(self): + if self._Version == None: + if self._Header == None: + self._GetHeaderInfo() + if self._Version == None: + self._Version = '' + return self._Version + + ## Retrieve protocol definitions (name/value pairs) + def _GetProtocol(self): + if self._Protocols == None: + # + # tdict is a special kind of dict, used for selecting correct + # protocol defition for given ARCH + # + ProtocolDict = tdict(True) + NameList = [] + # find out all protocol definitions for specific and 'common' arch + RecordList = self._RawData[MODEL_EFI_PROTOCOL, self._Arch] + for Name, Guid, Dummy, Arch, ID, LineNo in RecordList: + if Name not in NameList: + NameList.append(Name) + ProtocolDict[Arch, Name] = Guid + # use sdict to keep the order + self._Protocols = sdict() + for Name in NameList: + # + # limit the ARCH to self._Arch, if no self._Arch found, tdict + # will automatically turn to 'common' ARCH for trying + # + self._Protocols[Name] = ProtocolDict[self._Arch, Name] + return self._Protocols + + ## Retrieve PPI definitions (name/value pairs) + def _GetPpi(self): + if self._Ppis == None: + # + # tdict is a special kind of dict, used for selecting correct + # PPI defition for given ARCH + # + PpiDict = tdict(True) + NameList = [] + # find out all PPI definitions for specific arch and 'common' arch + RecordList = self._RawData[MODEL_EFI_PPI, self._Arch] + for Name, Guid, Dummy, Arch, ID, LineNo in RecordList: + if Name not in NameList: + NameList.append(Name) + PpiDict[Arch, Name] = Guid + # use sdict to keep the order + self._Ppis = sdict() + for Name in NameList: + # + # limit the ARCH to self._Arch, if no self._Arch found, tdict + # will automatically turn to 'common' ARCH for trying + # + self._Ppis[Name] = PpiDict[self._Arch, Name] + return self._Ppis + + ## Retrieve GUID definitions (name/value pairs) + def _GetGuid(self): + if self._Guids == None: + # + # tdict is a special kind of dict, used for selecting correct + # GUID defition for given ARCH + # + GuidDict = tdict(True) + NameList = [] + # find out all protocol definitions for specific and 'common' arch + RecordList = self._RawData[MODEL_EFI_GUID, self._Arch] + for Name, Guid, Dummy, Arch, ID, LineNo in RecordList: + if Name not in NameList: + NameList.append(Name) + GuidDict[Arch, Name] = Guid + # use sdict to keep the order + self._Guids = sdict() + for Name in NameList: + # + # limit the ARCH to self._Arch, if no self._Arch found, tdict + # will automatically turn to 'common' ARCH for trying + # + self._Guids[Name] = GuidDict[self._Arch, Name] + return self._Guids + + ## Retrieve public include paths declared in this package + def _GetInclude(self): + if self._Includes == None: + self._Includes = [] + RecordList = self._RawData[MODEL_EFI_INCLUDE, self._Arch] + Macros = {"EDK_SOURCE":GlobalData.gEcpSource, "EFI_SOURCE":GlobalData.gEfiSource} + Macros.update(self._Macros) + for Record in RecordList: + File = PathClass(NormPath(Record[0], Macros), self._PackageDir, Arch=self._Arch) + LineNo = Record[-1] + # validate the path + ErrorCode, ErrorInfo = File.Validate() + if ErrorCode != 0: + EdkLogger.error('build', ErrorCode, ExtraData=ErrorInfo, File=self.MetaFile, Line=LineNo) + + # avoid duplicate include path + if File not in self._Includes: + self._Includes.append(File) + return self._Includes + + ## Retrieve library class declarations (not used in build at present) + def _GetLibraryClass(self): + if self._LibraryClasses == None: + # + # tdict is a special kind of dict, used for selecting correct + # library class declaration for given ARCH + # + LibraryClassDict = tdict(True) + LibraryClassSet = set() + RecordList = self._RawData[MODEL_EFI_LIBRARY_CLASS, self._Arch] + Macros = {"EDK_SOURCE":GlobalData.gEcpSource, "EFI_SOURCE":GlobalData.gEfiSource} + Macros.update(self._Macros) + for LibraryClass, File, Dummy, Arch, ID, LineNo in RecordList: + File = PathClass(NormPath(File, Macros), self._PackageDir, Arch=self._Arch) + # check the file validation + ErrorCode, ErrorInfo = File.Validate() + if ErrorCode != 0: + EdkLogger.error('build', ErrorCode, ExtraData=ErrorInfo, File=self.MetaFile, Line=LineNo) + LibraryClassSet.add(LibraryClass) + LibraryClassDict[Arch, LibraryClass] = File + self._LibraryClasses = sdict() + for LibraryClass in LibraryClassSet: + self._LibraryClasses[LibraryClass] = LibraryClassDict[self._Arch, LibraryClass] + return self._LibraryClasses + + ## Retrieve PCD declarations + def _GetPcds(self): + if self._Pcds == None: + self._Pcds = {} + self._Pcds.update(self._GetPcd(MODEL_PCD_FIXED_AT_BUILD)) + self._Pcds.update(self._GetPcd(MODEL_PCD_PATCHABLE_IN_MODULE)) + self._Pcds.update(self._GetPcd(MODEL_PCD_FEATURE_FLAG)) + self._Pcds.update(self._GetPcd(MODEL_PCD_DYNAMIC)) + self._Pcds.update(self._GetPcd(MODEL_PCD_DYNAMIC_EX)) + return self._Pcds + + ## Retrieve PCD declarations for given type + def _GetPcd(self, Type): + Pcds = {} + # + # tdict is a special kind of dict, used for selecting correct + # PCD declaration for given ARCH + # + PcdDict = tdict(True, 3) + # for summarizing PCD + PcdSet = set() + # find out all PCDs of the 'type' + RecordList = self._RawData[Type, self._Arch] + for TokenSpaceGuid, PcdCName, Setting, Arch, Dummy1, Dummy2 in RecordList: + PcdDict[Arch, PcdCName, TokenSpaceGuid] = Setting + PcdSet.add((PcdCName, TokenSpaceGuid)) + + for PcdCName, TokenSpaceGuid in PcdSet: + ValueList = ['', '', ''] + # + # limit the ARCH to self._Arch, if no self._Arch found, tdict + # will automatically turn to 'common' ARCH and try again + # + Setting = PcdDict[self._Arch, PcdCName, TokenSpaceGuid] + if Setting == None: + continue + TokenList = Setting.split(TAB_VALUE_SPLIT) + ValueList[0:len(TokenList)] = TokenList + DefaultValue, DatumType, TokenNumber = ValueList + Pcds[PcdCName, TokenSpaceGuid, self._PCD_TYPE_STRING_[Type]] = PcdClassObject( + PcdCName, + TokenSpaceGuid, + self._PCD_TYPE_STRING_[Type], + DatumType, + DefaultValue, + TokenNumber, + '', + {}, + None + ) + return Pcds + + + Arch = property(_GetArch, _SetArch) + PackageName = property(_GetPackageName) + Guid = property(_GetFileGuid) + Version = property(_GetVersion) + + Protocols = property(_GetProtocol) + Ppis = property(_GetPpi) + Guids = property(_GetGuid) + Includes = property(_GetInclude) + LibraryClasses = property(_GetLibraryClass) + Pcds = property(_GetPcds) + +## Module build information from INF file +# +# This class is used to retrieve information stored in database and convert them +# into ModuleBuildClassObject form for easier use for AutoGen. +# +class InfBuildData(ModuleBuildClassObject): + # dict used to convert PCD type in database to string used by build tool + _PCD_TYPE_STRING_ = { + MODEL_PCD_FIXED_AT_BUILD : "FixedAtBuild", + MODEL_PCD_PATCHABLE_IN_MODULE : "PatchableInModule", + MODEL_PCD_FEATURE_FLAG : "FeatureFlag", + MODEL_PCD_DYNAMIC : "Dynamic", + MODEL_PCD_DYNAMIC_DEFAULT : "Dynamic", + MODEL_PCD_DYNAMIC_HII : "DynamicHii", + MODEL_PCD_DYNAMIC_VPD : "DynamicVpd", + MODEL_PCD_DYNAMIC_EX : "DynamicEx", + MODEL_PCD_DYNAMIC_EX_DEFAULT : "DynamicEx", + MODEL_PCD_DYNAMIC_EX_HII : "DynamicExHii", + MODEL_PCD_DYNAMIC_EX_VPD : "DynamicExVpd", + } + + # dict used to convert part of [Defines] to members of InfBuildData directly + _PROPERTY_ = { + # + # Required Fields + # + TAB_INF_DEFINES_BASE_NAME : "_BaseName", + TAB_INF_DEFINES_FILE_GUID : "_Guid", + TAB_INF_DEFINES_MODULE_TYPE : "_ModuleType", + # + # Optional Fields + # + TAB_INF_DEFINES_INF_VERSION : "_AutoGenVersion", + TAB_INF_DEFINES_COMPONENT_TYPE : "_ComponentType", + TAB_INF_DEFINES_MAKEFILE_NAME : "_MakefileName", + #TAB_INF_DEFINES_CUSTOM_MAKEFILE : "_CustomMakefile", + TAB_INF_DEFINES_VERSION_NUMBER : "_Version", + TAB_INF_DEFINES_VERSION_STRING : "_Version", + TAB_INF_DEFINES_VERSION : "_Version", + TAB_INF_DEFINES_PCD_IS_DRIVER : "_PcdIsDriver", + TAB_INF_DEFINES_SHADOW : "_Shadow", + + TAB_COMPONENTS_SOURCE_OVERRIDE_PATH : "_SourceOverridePath", + } + + # dict used to convert Component type to Module type + _MODULE_TYPE_ = { + "LIBRARY" : "BASE", + "SECURITY_CORE" : "SEC", + "PEI_CORE" : "PEI_CORE", + "COMBINED_PEIM_DRIVER" : "PEIM", + "PIC_PEIM" : "PEIM", + "RELOCATABLE_PEIM" : "PEIM", + "PE32_PEIM" : "PEIM", + "BS_DRIVER" : "DXE_DRIVER", + "RT_DRIVER" : "DXE_RUNTIME_DRIVER", + "SAL_RT_DRIVER" : "DXE_SAL_DRIVER", + # "BS_DRIVER" : "DXE_SMM_DRIVER", + # "BS_DRIVER" : "UEFI_DRIVER", + "APPLICATION" : "UEFI_APPLICATION", + "LOGO" : "BASE", + } + + # regular expression for converting XXX_FLAGS in [nmake] section to new type + _NMAKE_FLAG_PATTERN_ = re.compile("(?:EBC_)?([A-Z]+)_(?:STD_|PROJ_|ARCH_)?FLAGS(?:_DLL|_ASL|_EXE)?", re.UNICODE) + # dict used to convert old tool name used in [nmake] section to new ones + _TOOL_CODE_ = { + "C" : "CC", + "LIB" : "SLINK", + "LINK" : "DLINK", + } + + + ## Constructor of DscBuildData + # + # Initialize object of DscBuildData + # + # @param FilePath The path of platform description file + # @param RawData The raw data of DSC file + # @param BuildDataBase Database used to retrieve module/package information + # @param Arch The target architecture + # @param Platform The name of platform employing this module + # @param Macros Macros used for replacement in DSC file + # + def __init__(self, FilePath, RawData, BuildDatabase, Arch='COMMON', Platform='COMMON', Macros={}): + self.MetaFile = FilePath + self._ModuleDir = FilePath.Dir + self._RawData = RawData + self._Bdb = BuildDatabase + self._Arch = Arch + self._Platform = 'COMMON' + self._Macros = Macros + self._SourceOverridePath = None + if FilePath.Key in GlobalData.gOverrideDir: + self._SourceOverridePath = GlobalData.gOverrideDir[FilePath.Key] + self._Clear() + + ## XXX[key] = value + def __setitem__(self, key, value): + self.__dict__[self._PROPERTY_[key]] = value + + ## value = XXX[key] + def __getitem__(self, key): + return self.__dict__[self._PROPERTY_[key]] + + ## "in" test support + def __contains__(self, key): + return key in self._PROPERTY_ + + ## Set all internal used members of InfBuildData to None + def _Clear(self): + self._Header_ = None + self._AutoGenVersion = None + self._BaseName = None + self._ModuleType = None + self._ComponentType = None + self._BuildType = None + self._Guid = None + self._Version = None + self._PcdIsDriver = None + self._BinaryModule = None + self._Shadow = None + self._MakefileName = None + self._CustomMakefile = None + self._Specification = None + self._LibraryClass = None + self._ModuleEntryPointList = None + self._ModuleUnloadImageList = None + self._ConstructorList = None + self._DestructorList = None + self._Defs = None + self._Binaries = None + self._Sources = None + self._LibraryClasses = None + self._Libraries = None + self._Protocols = None + self._Ppis = None + self._Guids = None + self._Includes = None + self._Packages = None + self._Pcds = None + self._BuildOptions = None + self._Depex = None + #self._SourceOverridePath = None + + ## Get architecture + def _GetArch(self): + return self._Arch + + ## Set architecture + # + # Changing the default ARCH to another may affect all other information + # because all information in a platform may be ARCH-related. That's + # why we need to clear all internal used members, in order to cause all + # information to be re-retrieved. + # + # @param Value The value of ARCH + # + def _SetArch(self, Value): + if self._Arch == Value: + return + self._Arch = Value + self._Clear() + + ## Return the name of platform employing this module + def _GetPlatform(self): + return self._Platform + + ## Change the name of platform employing this module + # + # Changing the default name of platform to another may affect some information + # because they may be PLATFORM-related. That's why we need to clear all internal + # used members, in order to cause all information to be re-retrieved. + # + def _SetPlatform(self, Value): + if self._Platform == Value: + return + self._Platform = Value + self._Clear() + + ## Retrieve all information in [Defines] section + # + # (Retriving all [Defines] information in one-shot is just to save time.) + # + def _GetHeaderInfo(self): + RecordList = self._RawData[MODEL_META_DATA_HEADER, self._Arch, self._Platform] + for Record in RecordList: + Record = ReplaceMacros(Record, GlobalData.gEdkGlobal, False) + Name = Record[0] + # items defined _PROPERTY_ don't need additional processing + if Name in self: + self[Name] = Record[1] + # some special items in [Defines] section need special treatment + elif Name == 'EFI_SPECIFICATION_VERSION': + if self._Specification == None: + self._Specification = sdict() + self._Specification[Name] = Record[1] + elif Name == 'EDK_RELEASE_VERSION': + if self._Specification == None: + self._Specification = sdict() + self._Specification[Name] = Record[1] + elif Name == 'PI_SPECIFICATION_VERSION': + if self._Specification == None: + self._Specification = sdict() + self._Specification[Name] = Record[1] + elif Name == 'LIBRARY_CLASS': + if self._LibraryClass == None: + self._LibraryClass = [] + ValueList = GetSplitValueList(Record[1]) + LibraryClass = ValueList[0] + if len(ValueList) > 1: + SupModuleList = GetSplitValueList(ValueList[1], ' ') + else: + SupModuleList = SUP_MODULE_LIST + self._LibraryClass.append(LibraryClassObject(LibraryClass, SupModuleList)) + elif Name == 'ENTRY_POINT': + if self._ModuleEntryPointList == None: + self._ModuleEntryPointList = [] + self._ModuleEntryPointList.append(Record[1]) + elif Name == 'UNLOAD_IMAGE': + if self._ModuleUnloadImageList == None: + self._ModuleUnloadImageList = [] + if Record[1] == '': + continue + self._ModuleUnloadImageList.append(Record[1]) + elif Name == 'CONSTRUCTOR': + if self._ConstructorList == None: + self._ConstructorList = [] + if Record[1] == '': + continue + self._ConstructorList.append(Record[1]) + elif Name == 'DESTRUCTOR': + if self._DestructorList == None: + self._DestructorList = [] + if Record[1] == '': + continue + self._DestructorList.append(Record[1]) + elif Name == TAB_INF_DEFINES_CUSTOM_MAKEFILE: + TokenList = GetSplitValueList(Record[1]) + if self._CustomMakefile == None: + self._CustomMakefile = {} + if len(TokenList) < 2: + self._CustomMakefile['MSFT'] = TokenList[0] + self._CustomMakefile['GCC'] = TokenList[0] + else: + if TokenList[0] not in ['MSFT', 'GCC']: + EdkLogger.error("build", FORMAT_NOT_SUPPORTED, + "No supported family [%s]" % TokenList[0], + File=self.MetaFile, Line=Record[-1]) + self._CustomMakefile[TokenList[0]] = TokenList[1] + else: + if self._Defs == None: + self._Defs = sdict() + self._Defs[Name] = Record[1] + + # + # Retrieve information in sections specific to R8.x modules + # + if self._AutoGenVersion >= 0x00010005: # _AutoGenVersion may be None, which is less than anything + if not self._ModuleType: + EdkLogger.error("build", ATTRIBUTE_NOT_AVAILABLE, + "MODULE_TYPE is not given", File=self.MetaFile) + if self._Defs and 'PCI_DEVICE_ID' in self._Defs and 'PCI_VENDOR_ID' in self._Defs \ + and 'PCI_CLASS_CODE' in self._Defs: + self._BuildType = 'UEFI_OPTIONROM' + else: + self._BuildType = self._ModuleType.upper() + else: + self._BuildType = self._ComponentType.upper() + if not self._ComponentType: + EdkLogger.error("build", ATTRIBUTE_NOT_AVAILABLE, + "COMPONENT_TYPE is not given", File=self.MetaFile) + if self._ComponentType in self._MODULE_TYPE_: + self._ModuleType = self._MODULE_TYPE_[self._ComponentType] + if self._ComponentType == 'LIBRARY': + self._LibraryClass = [LibraryClassObject(self._BaseName, SUP_MODULE_LIST)] + # make use some [nmake] section macros + RecordList = self._RawData[MODEL_META_DATA_NMAKE, self._Arch, self._Platform] + for Name,Value,Dummy,Arch,Platform,ID,LineNo in RecordList: + Value = Value.replace('$(PROCESSOR)', self._Arch) + Name = Name.replace('$(PROCESSOR)', self._Arch) + Name, Value = ReplaceMacros((Name, Value), GlobalData.gEdkGlobal, True) + if Name == "IMAGE_ENTRY_POINT": + if self._ModuleEntryPointList == None: + self._ModuleEntryPointList = [] + self._ModuleEntryPointList.append(Value) + elif Name == "DPX_SOURCE": + Macros = {"EDK_SOURCE":GlobalData.gEcpSource, "EFI_SOURCE":GlobalData.gEfiSource} + Macros.update(self._Macros) + File = PathClass(NormPath(Value, Macros), self._ModuleDir, Arch=self._Arch) + # check the file validation + ErrorCode, ErrorInfo = File.Validate(".dxs", CaseSensitive=False) + if ErrorCode != 0: + EdkLogger.error('build', ErrorCode, ExtraData=ErrorInfo, + File=self.MetaFile, Line=LineNo) + if self.Sources == None: + self._Sources = [] + self._Sources.append(File) + else: + ToolList = self._NMAKE_FLAG_PATTERN_.findall(Name) + if len(ToolList) == 0 or len(ToolList) != 1: + pass +# EdkLogger.warn("build", "Don't know how to do with macro [%s]" % Name, +# File=self.MetaFile, Line=LineNo) + else: + if self._BuildOptions == None: + self._BuildOptions = sdict() + + if ToolList[0] in self._TOOL_CODE_: + Tool = self._TOOL_CODE_[ToolList[0]] + else: + Tool = ToolList[0] + ToolChain = "*_*_*_%s_FLAGS" % Tool + ToolChainFamily = 'MSFT' # R8.x only support MSFT tool chain + #ignore not replaced macros in value + ValueList = GetSplitValueList(' ' + Value, '/D') + Dummy = ValueList[0] + for Index in range(1, len(ValueList)): + if ValueList[Index][-1] == '=' or ValueList[Index] == '': + continue + Dummy = Dummy + ' /D ' + ValueList[Index] + Value = Dummy.strip() + if (ToolChainFamily, ToolChain) not in self._BuildOptions: + self._BuildOptions[ToolChainFamily, ToolChain] = Value + else: + OptionString = self._BuildOptions[ToolChainFamily, ToolChain] + self._BuildOptions[ToolChainFamily, ToolChain] = OptionString + " " + Value + # set _Header to non-None in order to avoid database re-querying + self._Header_ = 'DUMMY' + + ## Retrieve file version + def _GetInfVersion(self): + if self._AutoGenVersion == None: + if self._Header_ == None: + self._GetHeaderInfo() + if self._AutoGenVersion == None: + self._AutoGenVersion = 0x00010000 + return self._AutoGenVersion + + ## Retrieve BASE_NAME + def _GetBaseName(self): + if self._BaseName == None: + if self._Header_ == None: + self._GetHeaderInfo() + if self._BaseName == None: + EdkLogger.error('build', ATTRIBUTE_NOT_AVAILABLE, "No BASE_NAME name", File=self.MetaFile) + return self._BaseName + + ## Retrieve MODULE_TYPE + def _GetModuleType(self): + if self._ModuleType == None: + if self._Header_ == None: + self._GetHeaderInfo() + if self._ModuleType == None: + self._ModuleType = 'BASE' + if self._ModuleType not in SUP_MODULE_LIST: + self._ModuleType = "USER_DEFINED" + return self._ModuleType + + ## Retrieve COMPONENT_TYPE + def _GetComponentType(self): + if self._ComponentType == None: + if self._Header_ == None: + self._GetHeaderInfo() + if self._ComponentType == None: + self._ComponentType = 'USER_DEFINED' + return self._ComponentType + + ## Retrieve "BUILD_TYPE" + def _GetBuildType(self): + if self._BuildType == None: + if self._Header_ == None: + self._GetHeaderInfo() + if not self._BuildType: + self._BuildType = "BASE" + return self._BuildType + + ## Retrieve file guid + def _GetFileGuid(self): + if self._Guid == None: + if self._Header_ == None: + self._GetHeaderInfo() + if self._Guid == None: + self._Guid = '00000000-0000-0000-000000000000' + return self._Guid + + ## Retrieve module version + def _GetVersion(self): + if self._Version == None: + if self._Header_ == None: + self._GetHeaderInfo() + if self._Version == None: + self._Version = '0.0' + return self._Version + + ## Retrieve PCD_IS_DRIVER + def _GetPcdIsDriver(self): + if self._PcdIsDriver == None: + if self._Header_ == None: + self._GetHeaderInfo() + if self._PcdIsDriver == None: + self._PcdIsDriver = '' + return self._PcdIsDriver + + ## Retrieve SHADOW + def _GetShadow(self): + if self._Shadow == None: + if self._Header_ == None: + self._GetHeaderInfo() + if self._Shadow != None and self._Shadow.upper() == 'TRUE': + self._Shadow = True + else: + self._Shadow = False + return self._Shadow + + ## Retrieve CUSTOM_MAKEFILE + def _GetMakefile(self): + if self._CustomMakefile == None: + if self._Header_ == None: + self._GetHeaderInfo() + if self._CustomMakefile == None: + self._CustomMakefile = {} + return self._CustomMakefile + + ## Retrieve EFI_SPECIFICATION_VERSION + def _GetSpec(self): + if self._Specification == None: + if self._Header_ == None: + self._GetHeaderInfo() + if self._Specification == None: + self._Specification = {} + return self._Specification + + ## Retrieve LIBRARY_CLASS + def _GetLibraryClass(self): + if self._LibraryClass == None: + if self._Header_ == None: + self._GetHeaderInfo() + if self._LibraryClass == None: + self._LibraryClass = [] + return self._LibraryClass + + ## Retrieve ENTRY_POINT + def _GetEntryPoint(self): + if self._ModuleEntryPointList == None: + if self._Header_ == None: + self._GetHeaderInfo() + if self._ModuleEntryPointList == None: + self._ModuleEntryPointList = [] + return self._ModuleEntryPointList + + ## Retrieve UNLOAD_IMAGE + def _GetUnloadImage(self): + if self._ModuleUnloadImageList == None: + if self._Header_ == None: + self._GetHeaderInfo() + if self._ModuleUnloadImageList == None: + self._ModuleUnloadImageList = [] + return self._ModuleUnloadImageList + + ## Retrieve CONSTRUCTOR + def _GetConstructor(self): + if self._ConstructorList == None: + if self._Header_ == None: + self._GetHeaderInfo() + if self._ConstructorList == None: + self._ConstructorList = [] + return self._ConstructorList + + ## Retrieve DESTRUCTOR + def _GetDestructor(self): + if self._DestructorList == None: + if self._Header_ == None: + self._GetHeaderInfo() + if self._DestructorList == None: + self._DestructorList = [] + return self._DestructorList + + ## Retrieve definies other than above ones + def _GetDefines(self): + if self._Defs == None: + if self._Header_ == None: + self._GetHeaderInfo() + if self._Defs == None: + self._Defs = sdict() + return self._Defs + + ## Retrieve binary files + def _GetBinaryFiles(self): + if self._Binaries == None: + self._Binaries = [] + RecordList = self._RawData[MODEL_EFI_BINARY_FILE, self._Arch, self._Platform] + Macros = {"EDK_SOURCE":GlobalData.gEcpSource, "EFI_SOURCE":GlobalData.gEfiSource, 'PROCESSOR':self._Arch} + Macros.update(self._Macros) + for Record in RecordList: + Record = ReplaceMacros(Record, GlobalData.gEdkGlobal, False) + FileType = Record[0] + LineNo = Record[-1] + Target = 'COMMON' + FeatureFlag = [] + if Record[2]: + TokenList = GetSplitValueList(Record[2], TAB_VALUE_SPLIT) + if TokenList: + Target = TokenList[0] + if len(TokenList) > 1: + FeatureFlag = Record[1:] + + File = PathClass(NormPath(Record[1], Macros), self._ModuleDir, '', FileType, True, self._Arch, '', Target) + # check the file validation + ErrorCode, ErrorInfo = File.Validate() + if ErrorCode != 0: + EdkLogger.error('build', ErrorCode, ExtraData=ErrorInfo, File=self.MetaFile, Line=LineNo) + self._Binaries.append(File) + return self._Binaries + + ## Retrieve source files + def _GetSourceFiles(self): + if self._Sources == None: + self._Sources = [] + RecordList = self._RawData[MODEL_EFI_SOURCE_FILE, self._Arch, self._Platform] + Macros = {"EDK_SOURCE":GlobalData.gEcpSource, "EFI_SOURCE":GlobalData.gEfiSource, 'PROCESSOR':self._Arch} + Macros.update(self._Macros) + for Record in RecordList: + Record = ReplaceMacros(Record, GlobalData.gEdkGlobal, False) + LineNo = Record[-1] + ToolChainFamily = Record[1] + TagName = Record[2] + ToolCode = Record[3] + FeatureFlag = Record[4] + if self._AutoGenVersion < 0x00010005: + # old module source files (R8) + File = PathClass(NormPath(Record[0], Macros), self._ModuleDir, self._SourceOverridePath, + '', False, self._Arch, ToolChainFamily, '', TagName, ToolCode) + # check the file validation + ErrorCode, ErrorInfo = File.Validate(CaseSensitive=False) + if ErrorCode != 0: + if File.Ext.lower() == '.h': + EdkLogger.warn('build', 'Include file not found', ExtraData=ErrorInfo, + File=self.MetaFile, Line=LineNo) + continue + else: + EdkLogger.error('build', ErrorCode, ExtraData=File, File=self.MetaFile, Line=LineNo) + else: + File = PathClass(NormPath(Record[0], Macros), self._ModuleDir, '', + '', False, self._Arch, ToolChainFamily, '', TagName, ToolCode) + # check the file validation + ErrorCode, ErrorInfo = File.Validate() + if ErrorCode != 0: + EdkLogger.error('build', ErrorCode, ExtraData=ErrorInfo, File=self.MetaFile, Line=LineNo) + + self._Sources.append(File) + return self._Sources + + ## Retrieve library classes employed by this module + def _GetLibraryClassUses(self): + if self._LibraryClasses == None: + self._LibraryClasses = sdict() + RecordList = self._RawData[MODEL_EFI_LIBRARY_CLASS, self._Arch, self._Platform] + for Record in RecordList: + Record = ReplaceMacros(Record, GlobalData.gEdkGlobal, False) + Lib = Record[0] + Instance = Record[1] + if Instance != None and Instance != '': + Instance = NormPath(Instance, self._Macros) + self._LibraryClasses[Lib] = Instance + return self._LibraryClasses + + ## Retrieve library names (for R8.x style of modules) + def _GetLibraryNames(self): + if self._Libraries == None: + self._Libraries = [] + RecordList = self._RawData[MODEL_EFI_LIBRARY_INSTANCE, self._Arch, self._Platform] + for Record in RecordList: + # in case of name with '.lib' extension, which is unusual in R8.x inf + Record = ReplaceMacros(Record, GlobalData.gEdkGlobal, False) + LibraryName = os.path.splitext(Record[0])[0] + if LibraryName not in self._Libraries: + self._Libraries.append(LibraryName) + return self._Libraries + + ## Retrieve protocols consumed/produced by this module + def _GetProtocols(self): + if self._Protocols == None: + self._Protocols = sdict() + RecordList = self._RawData[MODEL_EFI_PROTOCOL, self._Arch, self._Platform] + for Record in RecordList: + CName = Record[0] + Value = ProtocolValue(CName, self.Packages) + if Value == None: + PackageList = "\n\t".join([str(P) for P in self.Packages]) + EdkLogger.error('build', RESOURCE_NOT_AVAILABLE, + "Value of Protocol [%s] is not found under [Protocols] section in" % CName, + ExtraData=PackageList, File=self.MetaFile, Line=Record[-1]) + self._Protocols[CName] = Value + return self._Protocols + + ## Retrieve PPIs consumed/produced by this module + def _GetPpis(self): + if self._Ppis == None: + self._Ppis = sdict() + RecordList = self._RawData[MODEL_EFI_PPI, self._Arch, self._Platform] + for Record in RecordList: + CName = Record[0] + Value = PpiValue(CName, self.Packages) + if Value == None: + PackageList = "\n\t".join([str(P) for P in self.Packages]) + EdkLogger.error('build', RESOURCE_NOT_AVAILABLE, + "Value of PPI [%s] is not found under [Ppis] section in " % CName, + ExtraData=PackageList, File=self.MetaFile, Line=Record[-1]) + self._Ppis[CName] = Value + return self._Ppis + + ## Retrieve GUIDs consumed/produced by this module + def _GetGuids(self): + if self._Guids == None: + self._Guids = sdict() + RecordList = self._RawData[MODEL_EFI_GUID, self._Arch, self._Platform] + for Record in RecordList: + CName = Record[0] + Value = GuidValue(CName, self.Packages) + if Value == None: + PackageList = "\n\t".join([str(P) for P in self.Packages]) + EdkLogger.error('build', RESOURCE_NOT_AVAILABLE, + "Value of Guid [%s] is not found under [Guids] section in" % CName, + ExtraData=PackageList, File=self.MetaFile, Line=Record[-1]) + self._Guids[CName] = Value + return self._Guids + + ## Retrieve include paths necessary for this module (for R8.x style of modules) + def _GetIncludes(self): + if self._Includes == None: + self._Includes = [] + if self._SourceOverridePath: + self._Includes.append(self._SourceOverridePath) + RecordList = self._RawData[MODEL_EFI_INCLUDE, self._Arch, self._Platform] + # [includes] section must be used only in old (R8.x) inf file + if self.AutoGenVersion >= 0x00010005 and len(RecordList) > 0: + EdkLogger.error('build', FORMAT_NOT_SUPPORTED, "No [include] section allowed", + File=self.MetaFile, Line=RecordList[0][-1]-1) + for Record in RecordList: + Record = ReplaceMacros(Record, GlobalData.gEdkGlobal, False) + Record[0] = Record[0].replace('$(PROCESSOR)', self._Arch) + Record[0] = ReplaceMacro(Record[0], {'EFI_SOURCE' : GlobalData.gEfiSource}, False) + if Record[0].find('EDK_SOURCE') > -1: + File = NormPath(ReplaceMacro(Record[0], {'EDK_SOURCE' : GlobalData.gEcpSource}, False), self._Macros) + if File[0] == '.': + File = os.path.join(self._ModuleDir, File) + else: + File = os.path.join(GlobalData.gWorkspace, File) + File = RealPath(os.path.normpath(File)) + if File: + self._Includes.append(File) + + #TRICK: let compiler to choose correct header file + File = NormPath(ReplaceMacro(Record[0], {'EDK_SOURCE' : GlobalData.gEdkSource}, False), self._Macros) + if File[0] == '.': + File = os.path.join(self._ModuleDir, File) + else: + File = os.path.join(GlobalData.gWorkspace, File) + File = RealPath(os.path.normpath(File)) + if File: + self._Includes.append(File) + else: + File = NormPath(Record[0], self._Macros) + if File[0] == '.': + File = os.path.join(self._ModuleDir, File) + else: + File = os.path.join(GlobalData.gWorkspace, File) + File = RealPath(os.path.normpath(File)) + if File: + self._Includes.append(File) + return self._Includes + + ## Retrieve packages this module depends on + def _GetPackages(self): + if self._Packages == None: + self._Packages = [] + RecordList = self._RawData[MODEL_META_DATA_PACKAGE, self._Arch, self._Platform] + Macros = {"EDK_SOURCE":GlobalData.gEcpSource, "EFI_SOURCE":GlobalData.gEfiSource} + Macros.update(self._Macros) + for Record in RecordList: + File = PathClass(NormPath(Record[0], Macros), GlobalData.gWorkspace, Arch=self._Arch) + LineNo = Record[-1] + # check the file validation + ErrorCode, ErrorInfo = File.Validate('.dec') + if ErrorCode != 0: + EdkLogger.error('build', ErrorCode, ExtraData=ErrorInfo, File=self.MetaFile, Line=LineNo) + # parse this package now. we need it to get protocol/ppi/guid value + Package = self._Bdb[File, self._Arch] + self._Packages.append(Package) + return self._Packages + + ## Retrieve PCDs used in this module + def _GetPcds(self): + if self._Pcds == None: + self._Pcds = {} + self._Pcds.update(self._GetPcd(MODEL_PCD_FIXED_AT_BUILD)) + self._Pcds.update(self._GetPcd(MODEL_PCD_PATCHABLE_IN_MODULE)) + self._Pcds.update(self._GetPcd(MODEL_PCD_FEATURE_FLAG)) + self._Pcds.update(self._GetPcd(MODEL_PCD_DYNAMIC)) + self._Pcds.update(self._GetPcd(MODEL_PCD_DYNAMIC_EX)) + return self._Pcds + + ## Retrieve build options specific to this module + def _GetBuildOptions(self): + if self._BuildOptions == None: + self._BuildOptions = sdict() + RecordList = self._RawData[MODEL_META_DATA_BUILD_OPTION, self._Arch, self._Platform] + for Record in RecordList: + ToolChainFamily = Record[0] + ToolChain = Record[1] + Option = Record[2] + if (ToolChainFamily, ToolChain) not in self._BuildOptions: + self._BuildOptions[ToolChainFamily, ToolChain] = Option + else: + # concatenate the option string if they're for the same tool + OptionString = self._BuildOptions[ToolChainFamily, ToolChain] + self._BuildOptions[ToolChainFamily, ToolChain] = OptionString + " " + Option + return self._BuildOptions + + ## Retrieve depedency expression + def _GetDepex(self): + if self._Depex == None: + self._Depex = tdict(False, 2) + RecordList = self._RawData[MODEL_EFI_DEPEX, self._Arch] + Depex = {} + for Record in RecordList: + Record = ReplaceMacros(Record, GlobalData.gEdkGlobal, False) + Arch = Record[3] + ModuleType = Record[4] + TokenList = Record[0].split() + if (Arch, ModuleType) not in Depex: + Depex[Arch, ModuleType] = [] + DepexList = Depex[Arch, ModuleType] + for Token in TokenList: + if Token in DEPEX_SUPPORTED_OPCODE: + DepexList.append(Token) + elif Token.endswith(".inf"): # module file name + ModuleFile = os.path.normpath(Token) + Module = self.BuildDatabase[ModuleFile] + if Module == None: + EdkLogger.error('build', RESOURCE_NOT_AVAILABLE, "Module is not found in active platform", + ExtraData=Token, File=self.MetaFile, Line=Record[-1]) + DepexList.append(Module.Guid) + else: + # get the GUID value now + Value = ProtocolValue(Token, self.Packages) + if Value == None: + Value = PpiValue(Token, self.Packages) + if Value == None: + Value = GuidValue(Token, self.Packages) + if Value == None: + PackageList = "\n\t".join([str(P) for P in self.Packages]) + EdkLogger.error('build', RESOURCE_NOT_AVAILABLE, + "Value of [%s] is not found in" % Token, + ExtraData=PackageList, File=self.MetaFile, Line=Record[-1]) + DepexList.append(Value) + for Arch, ModuleType in Depex: + self._Depex[Arch, ModuleType] = Depex[Arch, ModuleType] + return self._Depex + + ## Retrieve PCD for given type + def _GetPcd(self, Type): + Pcds = {} + PcdDict = tdict(True, 4) + PcdSet = set() + RecordList = self._RawData[Type, self._Arch, self._Platform] + for TokenSpaceGuid, PcdCName, Setting, Arch, Platform, Dummy1, LineNo in RecordList: + PcdDict[Arch, Platform, PcdCName, TokenSpaceGuid] = (Setting, LineNo) + PcdSet.add((PcdCName, TokenSpaceGuid)) + # get the guid value + if TokenSpaceGuid not in self.Guids: + Value = GuidValue(TokenSpaceGuid, self.Packages) + if Value == None: + PackageList = "\n\t".join([str(P) for P in self.Packages]) + EdkLogger.error('build', RESOURCE_NOT_AVAILABLE, + "Value of Guid [%s] is not found under [Guids] section in" % TokenSpaceGuid, + ExtraData=PackageList, File=self.MetaFile, Line=LineNo) + self.Guids[TokenSpaceGuid] = Value + + # resolve PCD type, value, datum info, etc. by getting its definition from package + for PcdCName, TokenSpaceGuid in PcdSet: + ValueList = ['', ''] + Setting, LineNo = PcdDict[self._Arch, self.Platform, PcdCName, TokenSpaceGuid] + if Setting == None: + continue + TokenList = Setting.split(TAB_VALUE_SPLIT) + ValueList[0:len(TokenList)] = TokenList + DefaultValue = ValueList[0] + Pcd = PcdClassObject( + PcdCName, + TokenSpaceGuid, + '', + '', + DefaultValue, + '', + '', + {}, + self.Guids[TokenSpaceGuid] + ) + + # get necessary info from package declaring this PCD + for Package in self.Packages: + # + # 'dynamic' in INF means its type is determined by platform; + # if platform doesn't give its type, use 'lowest' one in the + # following order, if any + # + # "FixedAtBuild", "PatchableInModule", "FeatureFlag", "Dynamic", "DynamicEx" + # + PcdType = self._PCD_TYPE_STRING_[Type] + if Type in [MODEL_PCD_DYNAMIC, MODEL_PCD_DYNAMIC_EX]: + Pcd.Pending = True + for T in ["FixedAtBuild", "PatchableInModule", "FeatureFlag", "Dynamic", "DynamicEx"]: + if (PcdCName, TokenSpaceGuid, T) in Package.Pcds: + PcdType = T + break + else: + Pcd.Pending = False + + if (PcdCName, TokenSpaceGuid, PcdType) in Package.Pcds: + PcdInPackage = Package.Pcds[PcdCName, TokenSpaceGuid, PcdType] + Pcd.Type = PcdType + Pcd.TokenValue = PcdInPackage.TokenValue + Pcd.DatumType = PcdInPackage.DatumType + Pcd.MaxDatumSize = PcdInPackage.MaxDatumSize + if Pcd.DefaultValue in [None, '']: + Pcd.DefaultValue = PcdInPackage.DefaultValue + break + else: + EdkLogger.error( + 'build', + PARSER_ERROR, + "PCD [%s.%s] in [%s] is not found in dependent packages:" % (TokenSpaceGuid, PcdCName, self.MetaFile), + File =self.MetaFile, Line=LineNo, + ExtraData="\t%s" % '\n\t'.join([str(P) for P in self.Packages]) + ) + Pcds[PcdCName, TokenSpaceGuid] = Pcd + return Pcds + + Arch = property(_GetArch, _SetArch) + Platform = property(_GetPlatform, _SetPlatform) + + AutoGenVersion = property(_GetInfVersion) + BaseName = property(_GetBaseName) + ModuleType = property(_GetModuleType) + ComponentType = property(_GetComponentType) + BuildType = property(_GetBuildType) + Guid = property(_GetFileGuid) + Version = property(_GetVersion) + PcdIsDriver = property(_GetPcdIsDriver) + Shadow = property(_GetShadow) + CustomMakefile = property(_GetMakefile) + Specification = property(_GetSpec) + LibraryClass = property(_GetLibraryClass) + ModuleEntryPointList = property(_GetEntryPoint) + ModuleUnloadImageList = property(_GetUnloadImage) + ConstructorList = property(_GetConstructor) + DestructorList = property(_GetDestructor) + Defines = property(_GetDefines) + + Binaries = property(_GetBinaryFiles) + Sources = property(_GetSourceFiles) + LibraryClasses = property(_GetLibraryClassUses) + Libraries = property(_GetLibraryNames) + Protocols = property(_GetProtocols) + Ppis = property(_GetPpis) + Guids = property(_GetGuids) + Includes = property(_GetIncludes) + Packages = property(_GetPackages) + Pcds = property(_GetPcds) + BuildOptions = property(_GetBuildOptions) + Depex = property(_GetDepex) + +## Database +# +# This class defined the build databse for all modules, packages and platform. +# It will call corresponding parser for the given file if it cannot find it in +# the database. +# +# @param DbPath Path of database file +# @param GlobalMacros Global macros used for replacement during file parsing +# @prarm RenewDb=False Create new database file if it's already there +# +class WorkspaceDatabase(object): + # file parser + _FILE_PARSER_ = { + MODEL_FILE_INF : InfParser, + MODEL_FILE_DEC : DecParser, + MODEL_FILE_DSC : DscParser, + MODEL_FILE_FDF : None, #FdfParser, + MODEL_FILE_CIF : None + } + + # file table + _FILE_TABLE_ = { + MODEL_FILE_INF : ModuleTable, + MODEL_FILE_DEC : PackageTable, + MODEL_FILE_DSC : PlatformTable, + } + + # default database file path + _DB_PATH_ = "Conf/.cache/build.db" + + # + # internal class used for call corresponding file parser and caching the result + # to avoid unnecessary re-parsing + # + class BuildObjectFactory(object): + _FILE_TYPE_ = { + ".inf" : MODEL_FILE_INF, + ".dec" : MODEL_FILE_DEC, + ".dsc" : MODEL_FILE_DSC, + ".fdf" : MODEL_FILE_FDF, + } + + # convert to xxxBuildData object + _GENERATOR_ = { + MODEL_FILE_INF : InfBuildData, + MODEL_FILE_DEC : DecBuildData, + MODEL_FILE_DSC : DscBuildData, + MODEL_FILE_FDF : None #FlashDefTable, + } + + _CACHE_ = {} # (FilePath, Arch) : + + # constructor + def __init__(self, WorkspaceDb): + self.WorkspaceDb = WorkspaceDb + + # key = (FilePath, Arch='COMMON') + def __contains__(self, Key): + FilePath = Key[0] + Arch = 'COMMON' + if len(Key) > 1: + Arch = Key[1] + return (FilePath, Arch) in self._CACHE_ + + # key = (FilePath, Arch='COMMON') + def __getitem__(self, Key): + FilePath = Key[0] + Arch = 'COMMON' + Platform = 'COMMON' + if len(Key) > 1: + Arch = Key[1] + if len(Key) > 2: + Platform = Key[2] + + # if it's generated before, just return the cached one + Key = (FilePath, Arch) + if Key in self._CACHE_: + return self._CACHE_[Key] + + # check file type + Ext = FilePath.Ext.lower() + if Ext not in self._FILE_TYPE_: + return None + FileType = self._FILE_TYPE_[Ext] + if FileType not in self._GENERATOR_: + return None + + # get table for current file + MetaFile = self.WorkspaceDb[FilePath, FileType, self.WorkspaceDb._GlobalMacros] + BuildObject = self._GENERATOR_[FileType]( + FilePath, + MetaFile, + self, + Arch, + Platform, + self.WorkspaceDb._GlobalMacros, + ) + self._CACHE_[Key] = BuildObject + return BuildObject + + # placeholder for file format conversion + class TransformObjectFactory: + def __init__(self, WorkspaceDb): + self.WorkspaceDb = WorkspaceDb + + # key = FilePath, Arch + def __getitem__(self, Key): + pass + + ## Constructor of WorkspaceDatabase + # + # @param DbPath Path of database file + # @param GlobalMacros Global macros used for replacement during file parsing + # @prarm RenewDb=False Create new database file if it's already there + # + def __init__(self, DbPath, GlobalMacros={}, RenewDb=False): + self._GlobalMacros = GlobalMacros + + if DbPath == None or DbPath == '': + DbPath = os.path.normpath(os.path.join(GlobalData.gWorkspace, self._DB_PATH_)) + + # don't create necessary path for db in memory + if DbPath != ':memory:': + DbDir = os.path.split(DbPath)[0] + if not os.path.exists(DbDir): + os.makedirs(DbDir) + + # remove db file in case inconsistency between db and file in file system + if self._CheckWhetherDbNeedRenew(RenewDb, DbPath): + os.remove(DbPath) + + # create db with optimized parameters + self.Conn = sqlite3.connect(DbPath, isolation_level='DEFERRED') + self.Conn.execute("PRAGMA synchronous=OFF") + self.Conn.execute("PRAGMA temp_store=MEMORY") + self.Conn.execute("PRAGMA count_changes=OFF") + self.Conn.execute("PRAGMA cache_size=8192") + #self.Conn.execute("PRAGMA page_size=8192") + + # to avoid non-ascii character conversion issue + self.Conn.text_factory = str + self.Cur = self.Conn.cursor() + + # create table for internal uses + self.TblDataModel = TableDataModel(self.Cur) + self.TblFile = TableFile(self.Cur) + + # conversion object for build or file format conversion purpose + self.BuildObject = WorkspaceDatabase.BuildObjectFactory(self) + self.TransformObject = WorkspaceDatabase.TransformObjectFactory(self) + + ## Check whether workspace database need to be renew. + # The renew reason maybe: + # 1) If user force to renew; + # 2) If user do not force renew, and + # a) If the time of last modified python source is newer than database file; + # b) If the time of last modified frozen executable file is newer than database file; + # + # @param force User force renew database + # @param DbPath The absolute path of workspace database file + # + # @return Bool value for whether need renew workspace databse + # + def _CheckWhetherDbNeedRenew (self, force, DbPath): + # if database does not exist, we need do nothing + if not os.path.exists(DbPath): return False + + # if user force to renew database, then not check whether database is out of date + if force: return True + + # + # Check the time of last modified source file or build.exe + # if is newer than time of database, then database need to be re-created. + # + timeOfToolModified = 0 + if hasattr(sys, "frozen"): + exePath = os.path.abspath(sys.executable) + timeOfToolModified = os.stat(exePath).st_mtime + else: + curPath = os.path.dirname(__file__) # curPath is the path of WorkspaceDatabase.py + rootPath = os.path.split(curPath)[0] # rootPath is root path of python source, such as /BaseTools/Source/Python + if rootPath == "" or rootPath == None: + EdkLogger.verbose("\nFail to find the root path of build.exe or python sources, so can not \ +determine whether database file is out of date!\n") + + # walk the root path of source or build's binary to get the time last modified. + + for root, dirs, files in os.walk (rootPath): + for dir in dirs: + # bypass source control folder + if dir.lower() in [".svn", "_svn", "cvs"]: + dirs.remove(dir) + + for file in files: + ext = os.path.splitext(file)[1] + if ext.lower() == ".py": # only check .py files + fd = os.stat(os.path.join(root, file)) + if timeOfToolModified < fd.st_mtime: + timeOfToolModified = fd.st_mtime + if timeOfToolModified > os.stat(DbPath).st_mtime: + EdkLogger.verbose("\nWorkspace database is out of data!") + return True + + return False + + ## Initialize build database + def InitDatabase(self): + EdkLogger.verbose("\nInitialize build database started ...") + + # + # Create new tables + # + self.TblDataModel.Create(False) + self.TblFile.Create(False) + + # + # Initialize table DataModel + # + self.TblDataModel.InitTable() + EdkLogger.verbose("Initialize build database ... DONE!") + + ## Query a table + # + # @param Table: The instance of the table to be queried + # + def QueryTable(self, Table): + Table.Query() + + ## Close entire database + # + # Commit all first + # Close the connection and cursor + # + def Close(self): + self.Conn.commit() + self.Cur.close() + self.Conn.close() + + ## Get unique file ID for the gvien file + def GetFileId(self, FilePath): + return self.TblFile.GetFileId(FilePath) + + ## Get file type value for the gvien file ID + def GetFileType(self, FileId): + return self.TblFile.GetFileType(FileId) + + ## Get time stamp stored in file table + def GetTimeStamp(self, FileId): + return self.TblFile.GetFileTimeStamp(FileId) + + ## Update time stamp in file table + def SetTimeStamp(self, FileId, TimeStamp): + return self.TblFile.SetFileTimeStamp(FileId, TimeStamp) + + ## Check if a table integrity flag exists or not + def CheckIntegrity(self, TableName): + try: + Result = self.Cur.execute("select min(ID) from %s" % (TableName)).fetchall() + if Result[0][0] != -1: + return False + except: + return False + return True + + ## Compose table name for given file type and file ID + def GetTableName(self, FileType, FileId): + return "_%s_%s" % (FileType, FileId) + + ## Return a temp table containing all content of the given file + # + # @param FileInfo The tuple containing path and type of a file + # + def __getitem__(self, FileInfo): + FilePath, FileType, Macros = FileInfo + if FileType not in self._FILE_TABLE_: + return None + + # flag used to indicate if it's parsed or not + FilePath = str(FilePath) + Parsed = False + FileId = self.GetFileId(FilePath) + if FileId != None: + TimeStamp = os.stat(FilePath)[8] + TableName = self.GetTableName(FileType, FileId) + if TimeStamp != self.GetTimeStamp(FileId): + # update the timestamp in database + self.SetTimeStamp(FileId, TimeStamp) + else: + # if the table exists and is integrity, don't parse it + Parsed = self.CheckIntegrity(TableName) + else: + FileId = self.TblFile.InsertFile(FilePath, FileType) + TableName = self.GetTableName(FileType, FileId) + + FileTable = self._FILE_TABLE_[FileType](self.Cur, TableName, FileId) + FileTable.Create(not Parsed) + Parser = self._FILE_PARSER_[FileType](FilePath, FileType, FileTable, Macros) + # set the "Finished" flag in parser in order to avoid re-parsing (if parsed) + Parser.Finished = Parsed + return Parser + + ## Summarize all packages in the database + def _GetPackageList(self): + PackageList = [] + for Module in self.ModuleList: + for Package in Module.Packages: + if Package not in PackageList: + PackageList.append(Package) + return PackageList + + ## Summarize all platforms in the database + def _GetPlatformList(self): + PlatformList = [] + for PlatformFile in self.TblFile.GetFileList(MODEL_FILE_DSC): + try: + Platform = self.BuildObject[PathClass(PlatformFile), 'COMMON'] + except: + Platform = None + if Platform != None: + PlatformList.append(Platform) + return PlatformList + + ## Summarize all modules in the database + def _GetModuleList(self): + ModuleList = [] + for ModuleFile in self.TblFile.GetFileList(MODEL_FILE_INF): + try: + Module = self.BuildObject[PathClass(ModuleFile), 'COMMON'] + except: + Module = None + if Module != None: + ModuleList.append(Module) + return ModuleList + + PlatformList = property(_GetPlatformList) + PackageList = property(_GetPackageList) + ModuleList = property(_GetModuleList) + +## +# +# This acts like the main() function for the script, unless it is 'import'ed into another +# script. +# +if __name__ == '__main__': + pass + diff --git a/BaseTools/Source/Python/Workspace/__init__.py b/BaseTools/Source/Python/Workspace/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/BaseTools/Source/Python/build/__init__.py b/BaseTools/Source/Python/build/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/BaseTools/Source/Python/build/build.py b/BaseTools/Source/Python/build/build.py new file mode 100644 index 0000000000..c92b442615 --- /dev/null +++ b/BaseTools/Source/Python/build/build.py @@ -0,0 +1,1436 @@ +## @file +# build a platform or a module +# +# Copyright (c) 2007, 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. +# + +## +# Import Modules +# +import os +import re +import sys +import glob +import time +import platform +import traceback + +from threading import * +from optparse import OptionParser +from subprocess import * +from Common import Misc as Utils + +from Common.TargetTxtClassObject import * +from Common.ToolDefClassObject import * +from Common.DataType import * +from AutoGen.AutoGen import * +from Common.BuildToolError import * +from Workspace.WorkspaceDatabase import * + +import Common.EdkLogger +import Common.GlobalData as GlobalData + +# Version and Copyright +VersionNumber = "0.5" +__version__ = "%prog Version " + VersionNumber +__copyright__ = "Copyright (c) 2007, Intel Corporation All rights reserved." + +## standard targets of build command +gSupportedTarget = ['all', 'genc', 'genmake', 'modules', 'libraries', 'fds', 'clean', 'cleanall', 'cleanlib', 'run'] + +## build configuration file +gBuildConfiguration = "Conf/target.txt" +gBuildCacheDir = "Conf/.cache" +gToolsDefinition = "Conf/tools_def.txt" + +## Check environment PATH variable to make sure the specified tool is found +# +# If the tool is found in the PATH, then True is returned +# Otherwise, False is returned +# +def IsToolInPath(tool): + if os.environ.has_key('PATHEXT'): + extns = os.environ['PATHEXT'].split(os.path.pathsep) + else: + extns = ('',) + for pathDir in os.environ['PATH'].split(os.path.pathsep): + for ext in extns: + if os.path.exists(os.path.join(pathDir, tool + ext)): + return True + return False + +## Check environment variables +# +# Check environment variables that must be set for build. Currently they are +# +# WORKSPACE The directory all packages/platforms start from +# EDK_TOOLS_PATH The directory contains all tools needed by the build +# PATH $(EDK_TOOLS_PATH)/Bin/ must be set in PATH +# +# If any of above environment variable is not set or has error, the build +# will be broken. +# +def CheckEnvVariable(): + # check WORKSPACE + if "WORKSPACE" not in os.environ: + EdkLogger.error("build", ATTRIBUTE_NOT_AVAILABLE, "Environment variable not found", + ExtraData="WORKSPACE") + + WorkspaceDir = os.path.normcase(os.path.normpath(os.environ["WORKSPACE"])) + if not os.path.exists(WorkspaceDir): + EdkLogger.error("build", FILE_NOT_FOUND, "WORKSPACE doesn't exist", ExtraData="%s" % WorkspaceDir) + elif ' ' in WorkspaceDir: + EdkLogger.error("build", FORMAT_NOT_SUPPORTED, "No space is allowed in WORKSPACE path", + ExtraData=WorkspaceDir) + os.environ["WORKSPACE"] = WorkspaceDir + + # + # Check EFI_SOURCE (R8 build convention). EDK_SOURCE will always point to ECP + # + os.environ["ECP_SOURCE"] = os.path.join(WorkspaceDir, GlobalData.gEdkCompatibilityPkg) + if "EFI_SOURCE" not in os.environ: + os.environ["EFI_SOURCE"] = os.environ["ECP_SOURCE"] + if "EDK_SOURCE" not in os.environ: + os.environ["EDK_SOURCE"] = os.environ["ECP_SOURCE"] + + # + # Unify case of characters on case-insensitive systems + # + EfiSourceDir = os.path.normcase(os.path.normpath(os.environ["EFI_SOURCE"])) + EdkSourceDir = os.path.normcase(os.path.normpath(os.environ["EDK_SOURCE"])) + EcpSourceDir = os.path.normcase(os.path.normpath(os.environ["ECP_SOURCE"])) + + os.environ["EFI_SOURCE"] = EfiSourceDir + os.environ["EDK_SOURCE"] = EdkSourceDir + os.environ["ECP_SOURCE"] = EcpSourceDir + os.environ["EDK_TOOLS_PATH"] = os.path.normcase(os.environ["EDK_TOOLS_PATH"]) + + if not os.path.exists(EcpSourceDir): + EdkLogger.verbose("ECP_SOURCE = %s doesn't exist. R8 modules could not be built." % EcpSourceDir) + elif ' ' in EcpSourceDir: + EdkLogger.error("build", FORMAT_NOT_SUPPORTED, "No space is allowed in ECP_SOURCE path", + ExtraData=EcpSourceDir) + if not os.path.exists(EdkSourceDir): + if EdkSourceDir == EcpSourceDir: + EdkLogger.verbose("EDK_SOURCE = %s doesn't exist. R8 modules could not be built." % EdkSourceDir) + else: + EdkLogger.error("build", PARAMETER_INVALID, "EDK_SOURCE does not exist", + ExtraData=EdkSourceDir) + elif ' ' in EdkSourceDir: + EdkLogger.error("build", FORMAT_NOT_SUPPORTED, "No space is allowed in EDK_SOURCE path", + ExtraData=EdkSourceDir) + if not os.path.exists(EfiSourceDir): + if EfiSourceDir == EcpSourceDir: + EdkLogger.verbose("EFI_SOURCE = %s doesn't exist. R8 modules could not be built." % EfiSourceDir) + else: + EdkLogger.error("build", PARAMETER_INVALID, "EFI_SOURCE does not exist", + ExtraData=EfiSourceDir) + elif ' ' in EfiSourceDir: + EdkLogger.error("build", FORMAT_NOT_SUPPORTED, "No space is allowed in EFI_SOURCE path", + ExtraData=EfiSourceDir) + + # change absolute path to relative path to WORKSPACE + if EfiSourceDir.upper().find(WorkspaceDir.upper()) != 0: + EdkLogger.error("build", PARAMETER_INVALID, "EFI_SOURCE is not under WORKSPACE", + ExtraData="WORKSPACE = %s\n EFI_SOURCE = %s" % (WorkspaceDir, EfiSourceDir)) + if EdkSourceDir.upper().find(WorkspaceDir.upper()) != 0: + EdkLogger.error("build", PARAMETER_INVALID, "EDK_SOURCE is not under WORKSPACE", + ExtraData="WORKSPACE = %s\n EDK_SOURCE = %s" % (WorkspaceDir, EdkSourceDir)) + if EcpSourceDir.upper().find(WorkspaceDir.upper()) != 0: + EdkLogger.error("build", PARAMETER_INVALID, "ECP_SOURCE is not under WORKSPACE", + ExtraData="WORKSPACE = %s\n ECP_SOURCE = %s" % (WorkspaceDir, EcpSourceDir)) + + # check EDK_TOOLS_PATH + if "EDK_TOOLS_PATH" not in os.environ: + EdkLogger.error("build", ATTRIBUTE_NOT_AVAILABLE, "Environment variable not found", + ExtraData="EDK_TOOLS_PATH") + + # check PATH + if "PATH" not in os.environ: + EdkLogger.error("build", ATTRIBUTE_NOT_AVAILABLE, "Environment variable not found", + ExtraData="PATH") + + # for macro replacement in R9 DSC/DEC/INF file + GlobalData.gGlobalDefines["WORKSPACE"] = "" + + # for macro replacement in R8 INF file + GlobalData.gGlobalDefines["EFI_SOURCE"] = EfiSourceDir + GlobalData.gGlobalDefines["EDK_SOURCE"] = EdkSourceDir + + GlobalData.gWorkspace = WorkspaceDir + GlobalData.gEfiSource = EfiSourceDir + GlobalData.gEdkSource = EdkSourceDir + GlobalData.gEcpSource = EcpSourceDir + +## Get normalized file path +# +# Convert the path to be local format, and remove the WORKSPACE path at the +# beginning if the file path is given in full path. +# +# @param FilePath File path to be normalized +# @param Workspace Workspace path which the FilePath will be checked against +# +# @retval string The normalized file path +# +def NormFile(FilePath, Workspace): + # check if the path is absolute or relative + if os.path.isabs(FilePath): + FileFullPath = os.path.normpath(FilePath) + else: + FileFullPath = os.path.normpath(os.path.join(Workspace, FilePath)) + + # check if the file path exists or not + if not os.path.isfile(FileFullPath): + EdkLogger.error("build", FILE_NOT_FOUND, ExtraData="\t%s (Please give file in absolute path or relative to WORKSPACE)" % FileFullPath) + + # remove workspace directory from the beginning part of the file path + if Workspace[-1] in ["\\", "/"]: + return FileFullPath[len(Workspace):] + else: + return FileFullPath[(len(Workspace) + 1):] + +## Get the output of an external program +# +# This is the entrance method of thread reading output of an external program and +# putting them in STDOUT/STDERR of current program. +# +# @param From The stream message read from +# @param To The stream message put on +# @param ExitFlag The flag used to indicate stopping reading +# +def ReadMessage(From, To, ExitFlag): + while True: + # read one line a time + Line = From.readline() + # empty string means "end" + if Line != None and Line != "": + To(Line.rstrip()) + else: + break + if ExitFlag.isSet(): + break + +## Launch an external program +# +# This method will call subprocess.Popen to execute an external program with +# given options in specified directory. Because of the dead-lock issue during +# redirecting output of the external program, threads are used to to do the +# redirection work. +# +# @param Command A list or string containing the call of the program +# @param WorkingDir The directory in which the program will be running +# +def LaunchCommand(Command, WorkingDir): + # if working directory doesn't exist, Popen() will raise an exception + if not os.path.isdir(WorkingDir): + EdkLogger.error("build", FILE_NOT_FOUND, ExtraData=WorkingDir) + + Proc = None + EndOfProcedure = None + try: + # launch the command + Proc = Popen(Command, stdout=PIPE, stderr=PIPE, env=os.environ, cwd=WorkingDir, bufsize=-1) + + # launch two threads to read the STDOUT and STDERR + EndOfProcedure = Event() + EndOfProcedure.clear() + if Proc.stdout: + StdOutThread = Thread(target=ReadMessage, args=(Proc.stdout, EdkLogger.info, EndOfProcedure)) + StdOutThread.setName("STDOUT-Redirector") + StdOutThread.setDaemon(False) + StdOutThread.start() + + if Proc.stderr: + StdErrThread = Thread(target=ReadMessage, args=(Proc.stderr, EdkLogger.quiet, EndOfProcedure)) + StdErrThread.setName("STDERR-Redirector") + StdErrThread.setDaemon(False) + StdErrThread.start() + + # waiting for program exit + Proc.wait() + except: # in case of aborting + # terminate the threads redirecting the program output + if EndOfProcedure != None: + EndOfProcedure.set() + if Proc == None: + if type(Command) != type(""): + Command = " ".join(Command) + EdkLogger.error("build", COMMAND_FAILURE, "Failed to start command", ExtraData="%s [%s]" % (Command, WorkingDir)) + + if Proc.stdout: + StdOutThread.join() + if Proc.stderr: + StdErrThread.join() + + # check the return code of the program + if Proc.returncode != 0: + if type(Command) != type(""): + Command = " ".join(Command) + EdkLogger.error("build", COMMAND_FAILURE, ExtraData="%s [%s]" % (Command, WorkingDir)) + +## The smallest unit that can be built in multi-thread build mode +# +# This is the base class of build unit. The "Obj" parameter must provide +# __str__(), __eq__() and __hash__() methods. Otherwise there could be build units +# missing build. +# +# Currently the "Obj" should be only ModuleAutoGen or PlatformAutoGen objects. +# +class BuildUnit: + ## The constructor + # + # @param self The object pointer + # @param Obj The object the build is working on + # @param Target The build target name, one of gSupportedTarget + # @param Dependency The BuildUnit(s) which must be completed in advance + # @param WorkingDir The directory build command starts in + # + def __init__(self, Obj, BuildCommand, Target, Dependency, WorkingDir="."): + self.BuildObject = Obj + self.Dependency = Dependency + self.WorkingDir = WorkingDir + self.Target = Target + self.BuildCommand = BuildCommand + if BuildCommand == None or len(BuildCommand) == 0: + EdkLogger.error("build", OPTION_MISSING, "No build command found for", + ExtraData=str(Obj)) + + ## str() method + # + # It just returns the string representaion of self.BuildObject + # + # @param self The object pointer + # + def __str__(self): + return str(self.BuildObject) + + ## "==" operator method + # + # It just compares self.BuildObject with "Other". So self.BuildObject must + # provide its own __eq__() method. + # + # @param self The object pointer + # @param Other The other BuildUnit object compared to + # + def __eq__(self, Other): + return Other != None and self.BuildObject == Other.BuildObject \ + and self.BuildObject.Arch == Other.BuildObject.Arch + + ## hash() method + # + # It just returns the hash value of self.BuildObject which must be hashable. + # + # @param self The object pointer + # + def __hash__(self): + return hash(self.BuildObject) + hash(self.BuildObject.Arch) + + def __repr__(self): + return repr(self.BuildObject) + +## The smallest module unit that can be built by nmake/make command in multi-thread build mode +# +# This class is for module build by nmake/make build system. The "Obj" parameter +# must provide __str__(), __eq__() and __hash__() methods. Otherwise there could +# be make units missing build. +# +# Currently the "Obj" should be only ModuleAutoGen object. +# +class ModuleMakeUnit(BuildUnit): + ## The constructor + # + # @param self The object pointer + # @param Obj The ModuleAutoGen object the build is working on + # @param Target The build target name, one of gSupportedTarget + # + def __init__(self, Obj, Target): + Dependency = [ModuleMakeUnit(La, Target) for La in Obj.LibraryAutoGenList] + BuildUnit.__init__(self, Obj, Obj.BuildCommand, Target, Dependency, Obj.MakeFileDir) + if Target in [None, "", "all"]: + self.Target = "tbuild" + +## The smallest platform unit that can be built by nmake/make command in multi-thread build mode +# +# This class is for platform build by nmake/make build system. The "Obj" parameter +# must provide __str__(), __eq__() and __hash__() methods. Otherwise there could +# be make units missing build. +# +# Currently the "Obj" should be only PlatformAutoGen object. +# +class PlatformMakeUnit(BuildUnit): + ## The constructor + # + # @param self The object pointer + # @param Obj The PlatformAutoGen object the build is working on + # @param Target The build target name, one of gSupportedTarget + # + def __init__(self, Obj, Target): + Dependency = [ModuleMakeUnit(Lib, Target) for Lib in self.BuildObject.LibraryAutoGenList] + Dependency.extend([ModuleMakeUnit(Mod, Target) for Mod in self.BuildObject.ModuleAutoGenList]) + BuildUnit.__init__(self, Obj, Obj.BuildCommand, Target, Dependency, Obj.MakeFileDir) + +## The class representing the task of a module build or platform build +# +# This class manages the build tasks in multi-thread build mode. Its jobs include +# scheduling thread running, catching thread error, monitor the thread status, etc. +# +class BuildTask: + # queue for tasks waiting for schedule + _PendingQueue = sdict() + _PendingQueueLock = threading.Lock() + + # queue for tasks ready for running + _ReadyQueue = sdict() + _ReadyQueueLock = threading.Lock() + + # queue for run tasks + _RunningQueue = sdict() + _RunningQueueLock = threading.Lock() + + # queue containing all build tasks, in case duplicate build + _TaskQueue = sdict() + + # flag indicating error occurs in a running thread + _ErrorFlag = threading.Event() + _ErrorFlag.clear() + _ErrorMessage = "" + + # BoundedSemaphore object used to control the number of running threads + _Thread = None + + # flag indicating if the scheduler is started or not + _SchedulerStopped = threading.Event() + _SchedulerStopped.set() + + ## Start the task scheduler thread + # + # @param MaxThreadNumber The maximum thread number + # @param ExitFlag Flag used to end the scheduler + # + @staticmethod + def StartScheduler(MaxThreadNumber, ExitFlag): + SchedulerThread = Thread(target=BuildTask.Scheduler, args=(MaxThreadNumber, ExitFlag)) + SchedulerThread.setName("Build-Task-Scheduler") + SchedulerThread.setDaemon(False) + SchedulerThread.start() + # wait for the scheduler to be started, especially useful in Linux + while not BuildTask.IsOnGoing(): + time.sleep(0.01) + + ## Scheduler method + # + # @param MaxThreadNumber The maximum thread number + # @param ExitFlag Flag used to end the scheduler + # + @staticmethod + def Scheduler(MaxThreadNumber, ExitFlag): + BuildTask._SchedulerStopped.clear() + try: + # use BoundedSemaphore to control the maximum running threads + BuildTask._Thread = BoundedSemaphore(MaxThreadNumber) + # + # scheduling loop, which will exits when no pending/ready task and + # indicated to do so, or there's error in running thread + # + while (len(BuildTask._PendingQueue) > 0 or len(BuildTask._ReadyQueue) > 0 \ + or not ExitFlag.isSet()) and not BuildTask._ErrorFlag.isSet(): + EdkLogger.debug(EdkLogger.DEBUG_8, "Pending Queue (%d), Ready Queue (%d)" + % (len(BuildTask._PendingQueue), len(BuildTask._ReadyQueue))) + + # get all pending tasks + BuildTask._PendingQueueLock.acquire() + BuildObjectList = BuildTask._PendingQueue.keys() + # + # check if their dependency is resolved, and if true, move them + # into ready queue + # + for BuildObject in BuildObjectList: + Bt = BuildTask._PendingQueue[BuildObject] + if Bt.IsReady(): + BuildTask._ReadyQueue[BuildObject] = BuildTask._PendingQueue.pop(BuildObject) + BuildTask._PendingQueueLock.release() + + # launch build thread until the maximum number of threads is reached + while not BuildTask._ErrorFlag.isSet(): + # empty ready queue, do nothing further + if len(BuildTask._ReadyQueue) == 0: + break + + # wait for active thread(s) exit + BuildTask._Thread.acquire(True) + + # start a new build thread + Bo = BuildTask._ReadyQueue.keys()[0] + Bt = BuildTask._ReadyQueue.pop(Bo) + + # move into running queue + BuildTask._RunningQueueLock.acquire() + BuildTask._RunningQueue[Bo] = Bt + BuildTask._RunningQueueLock.release() + + Bt.Start() + # avoid tense loop + time.sleep(0.01) + + # avoid tense loop + time.sleep(0.01) + + # wait for all running threads exit + if BuildTask._ErrorFlag.isSet(): + EdkLogger.quiet("\nWaiting for all build threads exit...") + # while not BuildTask._ErrorFlag.isSet() and \ + while len(BuildTask._RunningQueue) > 0: + EdkLogger.verbose("Waiting for thread ending...(%d)" % len(BuildTask._RunningQueue)) + EdkLogger.debug(EdkLogger.DEBUG_8, "Threads [%s]" % ", ".join([Th.getName() for Th in threading.enumerate()])) + # avoid tense loop + time.sleep(0.1) + except BaseException, X: + # + # TRICK: hide the output of threads left runing, so that the user can + # catch the error message easily + # + EdkLogger.SetLevel(EdkLogger.ERROR) + BuildTask._ErrorFlag.set() + BuildTask._ErrorMessage = "build thread scheduler error\n\t%s" % str(X) + + BuildTask._PendingQueue.clear() + BuildTask._ReadyQueue.clear() + BuildTask._RunningQueue.clear() + BuildTask._TaskQueue.clear() + BuildTask._SchedulerStopped.set() + + ## Wait for all running method exit + # + @staticmethod + def WaitForComplete(): + BuildTask._SchedulerStopped.wait() + + ## Check if the scheduler is running or not + # + @staticmethod + def IsOnGoing(): + return not BuildTask._SchedulerStopped.isSet() + + ## Abort the build + @staticmethod + def Abort(): + if BuildTask.IsOnGoing(): + BuildTask._ErrorFlag.set() + BuildTask.WaitForComplete() + + ## Check if there's error in running thread + # + # Since the main thread cannot catch exceptions in other thread, we have to + # use threading.Event to communicate this formation to main thread. + # + @staticmethod + def HasError(): + return BuildTask._ErrorFlag.isSet() + + ## Get error message in running thread + # + # Since the main thread cannot catch exceptions in other thread, we have to + # use a static variable to communicate this message to main thread. + # + @staticmethod + def GetErrorMessage(): + return BuildTask._ErrorMessage + + ## Factory method to create a BuildTask object + # + # This method will check if a module is building or has been built. And if + # true, just return the associated BuildTask object in the _TaskQueue. If + # not, create and return a new BuildTask object. The new BuildTask object + # will be appended to the _PendingQueue for scheduling later. + # + # @param BuildItem A BuildUnit object representing a build object + # @param Dependency The dependent build object of BuildItem + # + @staticmethod + def New(BuildItem, Dependency=None): + if BuildItem in BuildTask._TaskQueue: + Bt = BuildTask._TaskQueue[BuildItem] + return Bt + + Bt = BuildTask() + Bt._Init(BuildItem, Dependency) + BuildTask._TaskQueue[BuildItem] = Bt + + BuildTask._PendingQueueLock.acquire() + BuildTask._PendingQueue[BuildItem] = Bt + BuildTask._PendingQueueLock.release() + + return Bt + + ## The real constructor of BuildTask + # + # @param BuildItem A BuildUnit object representing a build object + # @param Dependency The dependent build object of BuildItem + # + def _Init(self, BuildItem, Dependency=None): + self.BuildItem = BuildItem + + self.DependencyList = [] + if Dependency == None: + Dependency = BuildItem.Dependency + else: + Dependency.extend(BuildItem.Dependency) + self.AddDependency(Dependency) + # flag indicating build completes, used to avoid unnecessary re-build + self.CompleteFlag = False + + ## Check if all dependent build tasks are completed or not + # + def IsReady(self): + ReadyFlag = True + for Dep in self.DependencyList: + if Dep.CompleteFlag == True: + continue + ReadyFlag = False + break + + return ReadyFlag + + ## Add dependent build task + # + # @param Dependency The list of dependent build objects + # + def AddDependency(self, Dependency): + for Dep in Dependency: + self.DependencyList.append(BuildTask.New(Dep)) # BuildTask list + + ## The thread wrapper of LaunchCommand function + # + # @param Command A list or string contains the call of the command + # @param WorkingDir The directory in which the program will be running + # + def _CommandThread(self, Command, WorkingDir): + try: + LaunchCommand(Command, WorkingDir) + self.CompleteFlag = True + except: + # + # TRICK: hide the output of threads left runing, so that the user can + # catch the error message easily + # + if not BuildTask._ErrorFlag.isSet(): + GlobalData.gBuildingModule = "%s [%s, %s, %s]" % (str(self.BuildItem.BuildObject), + self.BuildItem.BuildObject.Arch, + self.BuildItem.BuildObject.ToolChain, + self.BuildItem.BuildObject.BuildTarget + ) + EdkLogger.SetLevel(EdkLogger.ERROR) + BuildTask._ErrorFlag.set() + BuildTask._ErrorMessage = "%s broken\n %s [%s]" % \ + (threading.currentThread().getName(), Command, WorkingDir) + # indicate there's a thread is available for another build task + BuildTask._RunningQueueLock.acquire() + BuildTask._RunningQueue.pop(self.BuildItem) + BuildTask._RunningQueueLock.release() + BuildTask._Thread.release() + + ## Start build task thread + # + def Start(self): + EdkLogger.quiet("Building ... %s" % repr(self.BuildItem)) + Command = self.BuildItem.BuildCommand + [self.BuildItem.Target] + self.BuildTread = Thread(target=self._CommandThread, args=(Command, self.BuildItem.WorkingDir)) + self.BuildTread.setName("build thread") + self.BuildTread.setDaemon(False) + self.BuildTread.start() + +## The class implementing the EDK2 build process +# +# The build process includes: +# 1. Load configuration from target.txt and tools_def.txt in $(WORKSPACE)/Conf +# 2. Parse DSC file of active platform +# 3. Parse FDF file if any +# 4. Establish build database, including parse all other files (module, package) +# 5. Create AutoGen files (C code file, depex file, makefile) if necessary +# 6. Call build command +# +class Build(): + ## Constructor + # + # Constructor will load all necessary configurations, parse platform, modules + # and packages and the establish a database for AutoGen. + # + # @param Target The build command target, one of gSupportedTarget + # @param WorkspaceDir The directory of workspace + # @param Platform The DSC file of active platform + # @param Module The INF file of active module, if any + # @param Arch The Arch list of platform or module + # @param ToolChain The name list of toolchain + # @param BuildTarget The "DEBUG" or "RELEASE" build + # @param FlashDefinition The FDF file of active platform + # @param FdList=[] The FD names to be individually built + # @param FvList=[] The FV names to be individually built + # @param MakefileType The type of makefile (for MSFT make or GNU make) + # @param SilentMode Indicate multi-thread build mode + # @param ThreadNumber The maximum number of thread if in multi-thread build mode + # @param SkipAutoGen Skip AutoGen step + # @param Reparse Re-parse all meta files + # @param SkuId SKU id from command line + # + def __init__(self, Target, WorkspaceDir, Platform, Module, Arch, ToolChain, + BuildTarget, FlashDefinition, FdList=[], FvList=[], + MakefileType="nmake", SilentMode=False, ThreadNumber=2, + SkipAutoGen=False, Reparse=False, SkuId=None): + + self.WorkspaceDir = WorkspaceDir + self.Target = Target + self.PlatformFile = Platform + self.ModuleFile = Module + self.ArchList = Arch + self.ToolChainList = ToolChain + self.BuildTargetList= BuildTarget + self.Fdf = FlashDefinition + self.FdList = FdList + self.FvList = FvList + self.MakefileType = MakefileType + self.SilentMode = SilentMode + self.ThreadNumber = ThreadNumber + self.SkipAutoGen = SkipAutoGen + self.Reparse = Reparse + self.SkuId = SkuId + self.SpawnMode = True + + self.TargetTxt = TargetTxtClassObject() + self.ToolDef = ToolDefClassObject() + #self.Db = WorkspaceDatabase(None, GlobalData.gGlobalDefines, self.Reparse) + self.Db = WorkspaceDatabase(None, {}, self.Reparse) + self.BuildDatabase = self.Db.BuildObject + self.Platform = None + + # print dot charater during doing some time-consuming work + self.Progress = Utils.Progressor() + + # parse target.txt, tools_def.txt, and platform file + #self.RestoreBuildData() + self.LoadConfiguration() + self.InitBuild() + + # print current build environment and configuration + EdkLogger.quiet("%-24s = %s" % ("WORKSPACE", os.environ["WORKSPACE"])) + EdkLogger.quiet("%-24s = %s" % ("ECP_SOURCE", os.environ["ECP_SOURCE"])) + EdkLogger.quiet("%-24s = %s" % ("EDK_SOURCE", os.environ["EDK_SOURCE"])) + EdkLogger.quiet("%-24s = %s" % ("EFI_SOURCE", os.environ["EFI_SOURCE"])) + EdkLogger.quiet("%-24s = %s" % ("EDK_TOOLS_PATH", os.environ["EDK_TOOLS_PATH"])) + + EdkLogger.info('\n%-24s = %s' % ("TARGET_ARCH", ' '.join(self.ArchList))) + EdkLogger.info('%-24s = %s' % ("TARGET", ' '.join(self.BuildTargetList))) + EdkLogger.info('%-24s = %s' % ("TOOL_CHAIN_TAG", ' '.join(self.ToolChainList))) + + EdkLogger.info('\n%-24s = %s' % ("Active Platform", self.PlatformFile)) + + if self.Fdf != None and self.Fdf != "": + EdkLogger.info('%-24s = %s' % ("Flash Image Definition", self.Fdf)) + + if self.ModuleFile != None and self.ModuleFile != "": + EdkLogger.info('%-24s = %s' % ("Active Module", self.ModuleFile)) + + os.chdir(self.WorkspaceDir) + self.Progress.Start("\nProcessing meta-data") + + ## Load configuration + # + # This method will parse target.txt and get the build configurations. + # + def LoadConfiguration(self): + # + # Check target.txt and tools_def.txt and Init them + # + BuildConfigurationFile = os.path.normpath(os.path.join(self.WorkspaceDir, gBuildConfiguration)) + if os.path.isfile(BuildConfigurationFile) == True: + StatusCode = self.TargetTxt.LoadTargetTxtFile(BuildConfigurationFile) + + ToolDefinitionFile = self.TargetTxt.TargetTxtDictionary[DataType.TAB_TAT_DEFINES_TOOL_CHAIN_CONF] + if ToolDefinitionFile == '': + ToolDefinitionFile = gToolsDefinition + ToolDefinitionFile = os.path.normpath(os.path.join(self.WorkspaceDir, ToolDefinitionFile)) + if os.path.isfile(ToolDefinitionFile) == True: + StatusCode = self.ToolDef.LoadToolDefFile(ToolDefinitionFile) + else: + EdkLogger.error("build", FILE_NOT_FOUND, ExtraData=ToolDefinitionFile) + else: + EdkLogger.error("build", FILE_NOT_FOUND, ExtraData=BuildConfigurationFile) + + # if no ARCH given in command line, get it from target.txt + if self.ArchList == None or len(self.ArchList) == 0: + self.ArchList = self.TargetTxt.TargetTxtDictionary[DataType.TAB_TAT_DEFINES_TARGET_ARCH] + + # if no build target given in command line, get it from target.txt + if self.BuildTargetList == None or len(self.BuildTargetList) == 0: + self.BuildTargetList = self.TargetTxt.TargetTxtDictionary[DataType.TAB_TAT_DEFINES_TARGET] + + # if no tool chain given in command line, get it from target.txt + if self.ToolChainList == None or len(self.ToolChainList) == 0: + self.ToolChainList = self.TargetTxt.TargetTxtDictionary[DataType.TAB_TAT_DEFINES_TOOL_CHAIN_TAG] + if self.ToolChainList == None or len(self.ToolChainList) == 0: + EdkLogger.error("build", RESOURCE_NOT_AVAILABLE, ExtraData="No toolchain given. Don't know how to build.\n") + + # check if the tool chains are defined or not + NewToolChainList = [] + for ToolChain in self.ToolChainList: + if ToolChain not in self.ToolDef.ToolsDefTxtDatabase[TAB_TOD_DEFINES_TOOL_CHAIN_TAG]: + EdkLogger.warn("build", "Tool chain [%s] is not defined" % ToolChain) + else: + NewToolChainList.append(ToolChain) + # if no tool chain available, break the build + if len(NewToolChainList) == 0: + EdkLogger.error("build", RESOURCE_NOT_AVAILABLE, + ExtraData="[%s] not defined. No toolchain available for build!\n" % ", ".join(self.ToolChainList)) + else: + self.ToolChainList = NewToolChainList + + if self.ThreadNumber == None: + self.ThreadNumber = self.TargetTxt.TargetTxtDictionary[DataType.TAB_TAT_DEFINES_MAX_CONCURRENT_THREAD_NUMBER] + if self.ThreadNumber == '': + self.ThreadNumber = 0 + else: + self.ThreadNumber = int(self.ThreadNumber, 0) + + if self.ThreadNumber == 0: + self.ThreadNumber = 1 + + if not self.PlatformFile: + PlatformFile = self.TargetTxt.TargetTxtDictionary[DataType.TAB_TAT_DEFINES_ACTIVE_PLATFORM] + if not PlatformFile: + # Try to find one in current directory + WorkingDirectory = os.getcwd() + FileList = glob.glob(os.path.normpath(os.path.join(WorkingDirectory, '*.dsc'))) + FileNum = len(FileList) + if FileNum >= 2: + EdkLogger.error("build", OPTION_MISSING, + ExtraData="There are %d DSC files in %s. Use '-p' to specify one.\n" % (FileNum, WorkingDirectory)) + elif FileNum == 1: + PlatformFile = FileList[0] + else: + EdkLogger.error("build", RESOURCE_NOT_AVAILABLE, + ExtraData="No active platform specified in target.txt or command line! Nothing can be built.\n") + + self.PlatformFile = PathClass(NormFile(PlatformFile, self.WorkspaceDir), self.WorkspaceDir) + ErrorCode, ErrorInfo = self.PlatformFile.Validate(".dsc", False) + if ErrorCode != 0: + EdkLogger.error("build", ErrorCode, ExtraData=ErrorInfo) + + ## Initialize build configuration + # + # This method will parse DSC file and merge the configurations from + # command line and target.txt, then get the final build configurations. + # + def InitBuild(self): + ErrorCode, ErrorInfo = self.PlatformFile.Validate(".dsc") + if ErrorCode != 0: + EdkLogger.error("build", ErrorCode, ExtraData=ErrorInfo) + + # create metafile database + self.Db.InitDatabase() + + # we need information in platform description file to determine how to build + self.Platform = self.BuildDatabase[self.PlatformFile, 'COMMON'] + if not self.Fdf: + self.Fdf = self.Platform.FlashDefinition + + if self.SkuId == None or self.SkuId == '': + self.SkuId = self.Platform.SkuName + + # check FD/FV build target + if self.Fdf == None or self.Fdf == "": + if self.FdList != []: + EdkLogger.info("No flash definition file found. FD [%s] will be ignored." % " ".join(self.FdList)) + self.FdList = [] + if self.FvList != []: + EdkLogger.info("No flash definition file found. FV [%s] will be ignored." % " ".join(self.FvList)) + self.FvList = [] + else: + FdfParserObj = FdfParser(str(self.Fdf)) + FdfParserObj.ParseFile() + for fvname in self.FvList: + if fvname.upper() not in FdfParserObj.Profile.FvDict.keys(): + EdkLogger.error("build", OPTION_VALUE_INVALID, + "No such an FV in FDF file: %s" % fvname) + + # + # Merge Arch + # + if self.ArchList == None or len(self.ArchList) == 0: + ArchList = set(self.Platform.SupArchList) + else: + ArchList = set(self.ArchList) & set(self.Platform.SupArchList) + if len(ArchList) == 0: + EdkLogger.error("build", PARAMETER_INVALID, + ExtraData = "Active platform supports [%s] only, but [%s] is given." + % (" ".join(self.Platform.SupArchList), " ".join(self.ArchList))) + elif len(ArchList) != len(self.ArchList): + SkippedArchList = set(self.ArchList).symmetric_difference(set(self.Platform.SupArchList)) + EdkLogger.verbose("\nArch [%s] is ignored because active platform supports [%s] but [%s] is specified !" + % (" ".join(SkippedArchList), " ".join(self.Platform.SupArchList), " ".join(self.ArchList))) + self.ArchList = tuple(ArchList) + + # Merge build target + if self.BuildTargetList == None or len(self.BuildTargetList) == 0: + BuildTargetList = self.Platform.BuildTargets + else: + BuildTargetList = list(set(self.BuildTargetList) & set(self.Platform.BuildTargets)) + if BuildTargetList == []: + EdkLogger.error("build", PARAMETER_INVALID, "Active platform only supports [%s], but [%s] is given" + % (" ".join(self.Platform.BuildTargets), " ".join(self.BuildTargetList))) + self.BuildTargetList = BuildTargetList + + ## Build a module or platform + # + # Create autogen code and makfile for a module or platform, and the launch + # "make" command to build it + # + # @param Target The target of build command + # @param Platform The platform file + # @param Module The module file + # @param BuildTarget The name of build target, one of "DEBUG", "RELEASE" + # @param ToolChain The name of toolchain to build + # @param Arch The arch of the module/platform + # @param CreateDepModuleCodeFile Flag used to indicate creating code + # for dependent modules/Libraries + # @param CreateDepModuleMakeFile Flag used to indicate creating makefile + # for dependent modules/Libraries + # + def _Build(self, Target, AutoGenObject, CreateDepsCodeFile=True, CreateDepsMakeFile=True): + if AutoGenObject == None: + return False + + # skip file generation for cleanxxx targets, run and fds target + if Target not in ['clean', 'cleanlib', 'cleanall', 'run', 'fds']: + # for target which must generate AutoGen code and makefile + if not self.SkipAutoGen or Target == 'genc': + self.Progress.Start("Generating code") + AutoGenObject.CreateCodeFile(CreateDepsCodeFile) + self.Progress.Stop("done!") + if Target == "genc": + return True + + if not self.SkipAutoGen or Target == 'genmake': + self.Progress.Start("Generating makefile") + AutoGenObject.CreateMakeFile(CreateDepsMakeFile) + self.Progress.Stop("done!") + if Target == "genmake": + return True + else: + # always recreate top/platform makefile when clean, just in case of inconsistency + AutoGenObject.CreateCodeFile(False) + AutoGenObject.CreateMakeFile(False) + + if EdkLogger.GetLevel() == EdkLogger.QUIET: + EdkLogger.quiet("Building ... %s" % repr(AutoGenObject)) + + BuildCommand = AutoGenObject.BuildCommand + if BuildCommand == None or len(BuildCommand) == 0: + EdkLogger.error("build", OPTION_MISSING, ExtraData="No MAKE command found for [%s, %s, %s]" % Key) + + BuildCommand = BuildCommand + [Target] + LaunchCommand(BuildCommand, AutoGenObject.MakeFileDir) + if Target == 'cleanall': + try: + #os.rmdir(AutoGenObject.BuildDir) + RemoveDirectory(AutoGenObject.BuildDir, True) + except WindowsError, X: + EdkLogger.error("build", FILE_DELETE_FAILURE, ExtraData=str(X)) + return True + + ## Build active platform for different build targets and different tool chains + # + def _BuildPlatform(self): + for BuildTarget in self.BuildTargetList: + for ToolChain in self.ToolChainList: + Wa = WorkspaceAutoGen( + self.WorkspaceDir, + self.Platform, + BuildTarget, + ToolChain, + self.ArchList, + self.BuildDatabase, + self.TargetTxt, + self.ToolDef, + self.Fdf, + self.FdList, + self.FvList, + self.SkuId + ) + self.Progress.Stop("done!") + self._Build(self.Target, Wa) + + ## Build active module for different build targets, different tool chains and different archs + # + def _BuildModule(self): + for BuildTarget in self.BuildTargetList: + for ToolChain in self.ToolChainList: + # + # module build needs platform build information, so get platform + # AutoGen first + # + Wa = WorkspaceAutoGen( + self.WorkspaceDir, + self.Platform, + BuildTarget, + ToolChain, + self.ArchList, + self.BuildDatabase, + self.TargetTxt, + self.ToolDef, + self.Fdf, + self.FdList, + self.FvList, + self.SkuId + ) + Wa.CreateMakeFile(False) + self.Progress.Stop("done!") + MaList = [] + for Arch in self.ArchList: + Ma = ModuleAutoGen(Wa, self.ModuleFile, BuildTarget, ToolChain, Arch, self.PlatformFile) + if Ma == None: continue + MaList.append(Ma) + self._Build(self.Target, Ma) + if MaList == []: + EdkLogger.error( + 'build', + BUILD_ERROR, + "Module for [%s] is not a component of active platform."\ + " Please make sure that the ARCH and inf file path are"\ + " given in the same as in [%s]" %\ + (', '.join(self.ArchList), self.Platform), + ExtraData=self.ModuleFile + ) + + ## Build a platform in multi-thread mode + # + def _MultiThreadBuildPlatform(self): + for BuildTarget in self.BuildTargetList: + for ToolChain in self.ToolChainList: + Wa = WorkspaceAutoGen( + self.WorkspaceDir, + self.Platform, + BuildTarget, + ToolChain, + self.ArchList, + self.BuildDatabase, + self.TargetTxt, + self.ToolDef, + self.Fdf, + self.FdList, + self.FvList, + self.SkuId + ) + Wa.CreateMakeFile(False) + + # multi-thread exit flag + ExitFlag = threading.Event() + ExitFlag.clear() + for Arch in self.ArchList: + Pa = PlatformAutoGen(Wa, self.PlatformFile, BuildTarget, ToolChain, Arch) + if Pa == None: + continue + for Module in Pa.Platform.Modules: + # Get ModuleAutoGen object to generate C code file and makefile + Ma = ModuleAutoGen(Wa, Module, BuildTarget, ToolChain, Arch, self.PlatformFile) + if Ma == None: + continue + # Not to auto-gen for targets 'clean', 'cleanlib', 'cleanall', 'run', 'fds' + if self.Target not in ['clean', 'cleanlib', 'cleanall', 'run', 'fds']: + # for target which must generate AutoGen code and makefile + if not self.SkipAutoGen or self.Target == 'genc': + Ma.CreateCodeFile(True) + if self.Target == "genc": + continue + + if not self.SkipAutoGen or self.Target == 'genmake': + Ma.CreateMakeFile(True) + if self.Target == "genmake": + continue + self.Progress.Stop("done!") + # Generate build task for the module + Bt = BuildTask.New(ModuleMakeUnit(Ma, self.Target)) + # Break build if any build thread has error + if BuildTask.HasError(): + # we need a full version of makefile for platform + ExitFlag.set() + BuildTask.WaitForComplete() + Pa.CreateMakeFile(False) + EdkLogger.error("build", BUILD_ERROR, "Failed to build module", ExtraData=GlobalData.gBuildingModule) + # Start task scheduler + if not BuildTask.IsOnGoing(): + BuildTask.StartScheduler(self.ThreadNumber, ExitFlag) + + # in case there's an interruption. we need a full version of makefile for platform + Pa.CreateMakeFile(False) + if BuildTask.HasError(): + EdkLogger.error("build", BUILD_ERROR, "Failed to build module", ExtraData=GlobalData.gBuildingModule) + + # + # All modules have been put in build tasks queue. Tell task scheduler + # to exit if all tasks are completed + # + ExitFlag.set() + BuildTask.WaitForComplete() + + # + # Check for build error, and raise exception if one + # has been signaled. + # + if BuildTask.HasError(): + EdkLogger.error("build", BUILD_ERROR, "Failed to build module", ExtraData=GlobalData.gBuildingModule) + + # Generate FD image if there's a FDF file found + if self.Fdf != '' and self.Target in ["", "all", "fds"]: + LaunchCommand(Wa.BuildCommand + ["fds"], Wa.MakeFileDir) + + ## Generate GuidedSectionTools.txt in the FV directories. + # + def CreateGuidedSectionToolsFile(self): + for Arch in self.ArchList: + for BuildTarget in self.BuildTargetList: + for ToolChain in self.ToolChainList: + FvDir = os.path.join( + self.WorkspaceDir, + self.Platform.OutputDirectory, + '_'.join((BuildTarget, ToolChain)), + 'FV' + ) + if not os.path.exists(FvDir): + continue + # Build up the list of supported architectures for this build + prefix = '%s_%s_%s_' % (BuildTarget, ToolChain, Arch) + + # Look through the tool definitions for GUIDed tools + guidAttribs = [] + for (attrib, value) in self.ToolDef.ToolsDefTxtDictionary.iteritems(): + if attrib.upper().endswith('_GUID'): + split = attrib.split('_') + thisPrefix = '_'.join(split[0:3]) + '_' + if thisPrefix == prefix: + guid = self.ToolDef.ToolsDefTxtDictionary[attrib] + guid = guid.lower() + toolName = split[3] + path = '_'.join(split[0:4]) + '_PATH' + path = self.ToolDef.ToolsDefTxtDictionary[path] + path = self.GetFullPathOfTool(path) + guidAttribs.append((guid, toolName, path)) + + # Write out GuidedSecTools.txt + toolsFile = os.path.join(FvDir, 'GuidedSectionTools.txt') + toolsFile = open(toolsFile, 'wt') + for guidedSectionTool in guidAttribs: + print >> toolsFile, ' '.join(guidedSectionTool) + toolsFile.close() + + ## Returns the full path of the tool. + # + def GetFullPathOfTool (self, tool): + if os.path.exists(tool): + return os.path.realpath(tool) + else: + # We need to search for the tool using the + # PATH environment variable. + for dirInPath in os.environ['PATH'].split(os.pathsep): + foundPath = os.path.join(dirInPath, tool) + if os.path.exists(foundPath): + return os.path.realpath(foundPath) + + # If the tool was not found in the path then we just return + # the input tool. + return tool + + ## Launch the module or platform build + # + def Launch(self): + if self.ModuleFile == None or self.ModuleFile == "": + if not self.SpawnMode or self.Target not in ["", "all"]: + self.SpawnMode = False + self._BuildPlatform() + else: + self._MultiThreadBuildPlatform() + self.CreateGuidedSectionToolsFile() + else: + self.SpawnMode = False + self._BuildModule() + + ## Do some clean-up works when error occurred + def Relinquish(self): + OldLogLevel = EdkLogger.GetLevel() + EdkLogger.SetLevel(EdkLogger.ERROR) + #self.DumpBuildData() + Utils.Progressor.Abort() + if self.SpawnMode == True: + BuildTask.Abort() + EdkLogger.SetLevel(OldLogLevel) + + def DumpBuildData(self): + CacheDirectory = os.path.join(self.WorkspaceDir, gBuildCacheDir) + Utils.CreateDirectory(CacheDirectory) + Utils.DataDump(Utils.gFileTimeStampCache, os.path.join(CacheDirectory, "gFileTimeStampCache")) + Utils.DataDump(Utils.gDependencyDatabase, os.path.join(CacheDirectory, "gDependencyDatabase")) + + def RestoreBuildData(self): + FilePath = os.path.join(self.WorkspaceDir, gBuildCacheDir, "gFileTimeStampCache") + if Utils.gFileTimeStampCache == {} and os.path.isfile(FilePath): + Utils.gFileTimeStampCache = Utils.DataRestore(FilePath) + if Utils.gFileTimeStampCache == None: + Utils.gFileTimeStampCache = {} + + FilePath = os.path.join(self.WorkspaceDir, gBuildCacheDir, "gDependencyDatabase") + if Utils.gDependencyDatabase == {} and os.path.isfile(FilePath): + Utils.gDependencyDatabase = Utils.DataRestore(FilePath) + if Utils.gDependencyDatabase == None: + Utils.gDependencyDatabase = {} + +def ParseDefines(DefineList=[]): + DefineDict = {} + if DefineList != None: + for Define in DefineList: + DefineTokenList = Define.split("=", 1) + if len(DefineTokenList) == 1: + DefineDict[DefineTokenList[0]] = "" + else: + DefineDict[DefineTokenList[0]] = DefineTokenList[1].strip() + return DefineDict + +gParamCheck = [] +def SingleCheckCallback(option, opt_str, value, parser): + if option not in gParamCheck: + setattr(parser.values, option.dest, value) + gParamCheck.append(option) + else: + parser.error("Option %s only allows one instance in command line!" % option) + +## Parse command line options +# +# Using standard Python module optparse to parse command line option of this tool. +# +# @retval Opt A optparse.Values object containing the parsed options +# @retval Args Target of build command +# +def MyOptionParser(): + Parser = OptionParser(description=__copyright__,version=__version__,prog="build.exe",usage="%prog [options] [all|fds|genc|genmake|clean|cleanall|cleanlib|modules|libraries|run]") + Parser.add_option("-a", "--arch", action="append", type="choice", choices=['IA32','X64','IPF','EBC','ARM'], dest="TargetArch", + help="ARCHS is one of list: IA32, X64, IPF, ARM or EBC, which overrides target.txt's TARGET_ARCH definition. To specify more archs, please repeat this option.") + Parser.add_option("-p", "--platform", action="callback", type="string", dest="PlatformFile", callback=SingleCheckCallback, + help="Build the platform specified by the DSC file name argument, overriding target.txt's ACTIVE_PLATFORM definition.") + Parser.add_option("-m", "--module", action="callback", type="string", dest="ModuleFile", callback=SingleCheckCallback, + help="Build the module specified by the INF file name argument.") + Parser.add_option("-b", "--buildtarget", action="append", type="choice", choices=['DEBUG','RELEASE'], dest="BuildTarget", + help="BuildTarget is one of list: DEBUG, RELEASE, which overrides target.txt's TARGET definition. To specify more TARGET, please repeat this option.") + Parser.add_option("-t", "--tagname", action="append", type="string", dest="ToolChain", + help="Using the Tool Chain Tagname to build the platform, overriding target.txt's TOOL_CHAIN_TAG definition.") + Parser.add_option("-x", "--sku-id", action="callback", type="string", dest="SkuId", callback=SingleCheckCallback, + help="Using this name of SKU ID to build the platform, overriding SKUID_IDENTIFIER in DSC file.") + + Parser.add_option("-n", action="callback", type="int", dest="ThreadNumber", callback=SingleCheckCallback, + help="Build the platform using multi-threaded compiler. The value overrides target.txt's MAX_CONCURRENT_THREAD_NUMBER. Less than 2 will disable multi-thread builds.") + + Parser.add_option("-f", "--fdf", action="callback", type="string", dest="FdfFile", callback=SingleCheckCallback, + help="The name of the FDF file to use, which overrides the setting in the DSC file.") + Parser.add_option("-r", "--rom-image", action="append", type="string", dest="RomImage", default=[], + help="The name of FD to be generated. The name must be from [FD] section in FDF file.") + Parser.add_option("-i", "--fv-image", action="append", type="string", dest="FvImage", default=[], + help="The name of FV to be generated. The name must be from [FV] section in FDF file.") + + Parser.add_option("-u", "--skip-autogen", action="store_true", dest="SkipAutoGen", help="Skip AutoGen step.") + Parser.add_option("-e", "--re-parse", action="store_true", dest="Reparse", help="Re-parse all meta-data files.") + + Parser.add_option("-c", "--case-insensitive", action="store_true", dest="CaseInsensitive", help="Don't check case of file name.") + + # Parser.add_option("-D", "--define", action="append", dest="Defines", metavar="NAME[=[VALUE]]", + # help="Define global macro which can be used in DSC/DEC/INF files.") + + Parser.add_option("-w", "--warning-as-error", action="store_true", dest="WarningAsError", help="Treat warning in tools as error.") + Parser.add_option("-j", "--log", action="store", dest="LogFile", help="Put log in specified file as well as on console.") + + Parser.add_option("-s", "--silent", action="store_true", type=None, dest="SilentMode", + help="Make use of silent mode of (n)make.") + Parser.add_option("-q", "--quiet", action="store_true", type=None, help="Disable all messages except FATAL ERRORS.") + Parser.add_option("-v", "--verbose", action="store_true", type=None, help="Turn on verbose output with informational messages printed, "\ + "including library instances selected, final dependency expression, "\ + "and warning messages, etc.") + Parser.add_option("-d", "--debug", action="store", type="int", help="Enable debug messages at specified level.") + + (Opt, Args)=Parser.parse_args() + return (Opt, Args) + +## Tool entrance method +# +# This method mainly dispatch specific methods per the command line options. +# If no error found, return zero value so the caller of this tool can know +# if it's executed successfully or not. +# +# @retval 0 Tool was successful +# @retval 1 Tool failed +# +def Main(): + StartTime = time.time() + + # Initialize log system + EdkLogger.Initialize() + + # + # Parse the options and args + # + (Option, Target) = MyOptionParser() + GlobalData.gOptions = Option + GlobalData.gCaseInsensitive = Option.CaseInsensitive + + # Set log level + if Option.verbose != None: + EdkLogger.SetLevel(EdkLogger.VERBOSE) + elif Option.quiet != None: + EdkLogger.SetLevel(EdkLogger.QUIET) + elif Option.debug != None: + EdkLogger.SetLevel(Option.debug + 1) + else: + EdkLogger.SetLevel(EdkLogger.INFO) + + if Option.LogFile != None: + EdkLogger.SetLogFile(Option.LogFile) + + if Option.WarningAsError == True: + EdkLogger.SetWarningAsError() + + if platform.platform().find("Windows") >= 0: + GlobalData.gIsWindows = True + else: + GlobalData.gIsWindows = False + + EdkLogger.quiet(time.strftime("%H:%M:%S, %b.%d %Y ", time.localtime()) + "[%s]\n" % platform.platform()) + ReturnCode = 0 + MyBuild = None + try: + if len(Target) == 0: + Target = "all" + elif len(Target) >= 2: + EdkLogger.error("build", OPTION_NOT_SUPPORTED, "More than one targets are not supported.", + ExtraData="Please select one of: %s" %(' '.join(gSupportedTarget))) + else: + Target = Target[0].lower() + + if Target not in gSupportedTarget: + EdkLogger.error("build", OPTION_NOT_SUPPORTED, "Not supported target [%s]." % Target, + ExtraData="Please select one of: %s" %(' '.join(gSupportedTarget))) + + # GlobalData.gGlobalDefines = ParseDefines(Option.Defines) + # + # Check environment variable: EDK_TOOLS_PATH, WORKSPACE, PATH + # + CheckEnvVariable() + Workspace = os.getenv("WORKSPACE") + # + # Get files real name in workspace dir + # + GlobalData.gAllFiles = Utils.DirCache(Workspace) + + WorkingDirectory = os.getcwd() + if not Option.ModuleFile: + FileList = glob.glob(os.path.normpath(os.path.join(WorkingDirectory, '*.inf'))) + FileNum = len(FileList) + if FileNum >= 2: + EdkLogger.error("build", OPTION_NOT_SUPPORTED, "There are %d INF files in %s." % (FileNum, WorkingDirectory), + ExtraData="Please use '-m ' switch to choose one.") + elif FileNum == 1: + Option.ModuleFile = NormFile(FileList[0], Workspace) + + if Option.ModuleFile: + Option.ModuleFile = PathClass(Option.ModuleFile, Workspace) + ErrorCode, ErrorInfo = Option.ModuleFile.Validate(".inf", False) + if ErrorCode != 0: + EdkLogger.error("build", ErrorCode, ExtraData=ErrorInfo) + + if Option.PlatformFile != None: + Option.PlatformFile = PathClass(Option.PlatformFile, Workspace) + ErrorCode, ErrorInfo = Option.PlatformFile.Validate(".dsc", False) + if ErrorCode != 0: + EdkLogger.error("build", ErrorCode, ExtraData=ErrorInfo) + + if Option.FdfFile != None: + Option.FdfFile = PathClass(Option.FdfFile, Workspace) + ErrorCode, ErrorInfo = Option.FdfFile.Validate(".fdf", False) + if ErrorCode != 0: + EdkLogger.error("build", ErrorCode, ExtraData=ErrorInfo) + + MyBuild = Build(Target, Workspace, Option.PlatformFile, Option.ModuleFile, + Option.TargetArch, Option.ToolChain, Option.BuildTarget, + Option.FdfFile, Option.RomImage, Option.FvImage, + None, Option.SilentMode, Option.ThreadNumber, + Option.SkipAutoGen, Option.Reparse, Option.SkuId) + MyBuild.Launch() + #MyBuild.DumpBuildData() + except FatalError, X: + if MyBuild != None: + # for multi-thread build exits safely + MyBuild.Relinquish() + if Option != None and Option.debug != None: + EdkLogger.quiet("(Python %s on %s) " % (platform.python_version(), sys.platform) + traceback.format_exc()) + ReturnCode = X.args[0] + except Warning, X: + # error from Fdf parser + if MyBuild != None: + # for multi-thread build exits safely + MyBuild.Relinquish() + if Option != None and Option.debug != None: + EdkLogger.quiet("(Python %s on %s) " % (platform.python_version(), sys.platform) + traceback.format_exc()) + else: + EdkLogger.error(X.ToolName, FORMAT_INVALID, File=X.FileName, Line=X.LineNumber, ExtraData=X.Message, RaiseError = False) + ReturnCode = FORMAT_INVALID + except KeyboardInterrupt: + ReturnCode = ABORT_ERROR + if Option != None and Option.debug != None: + EdkLogger.quiet("(Python %s on %s) " % (platform.python_version(), sys.platform) + traceback.format_exc()) + except: + if MyBuild != None: + # for multi-thread build exits safely + MyBuild.Relinquish() + + # try to get the meta-file from the object causing exception + Tb = sys.exc_info()[-1] + MetaFile = GlobalData.gProcessingFile + while Tb != None: + if 'self' in Tb.tb_frame.f_locals and hasattr(Tb.tb_frame.f_locals['self'], 'MetaFile'): + MetaFile = Tb.tb_frame.f_locals['self'].MetaFile + Tb = Tb.tb_next + EdkLogger.error( + "\nbuild", + CODE_ERROR, + "Unknown fatal error when processing [%s]" % MetaFile, + ExtraData="\n(Please send email to dev@buildtools.tianocore.org for help, attaching following call stack trace!)\n", + RaiseError=False + ) + EdkLogger.quiet("(Python %s on %s) " % (platform.python_version(), sys.platform) + traceback.format_exc()) + ReturnCode = CODE_ERROR + finally: + Utils.Progressor.Abort() + + if MyBuild != None: + MyBuild.Db.Close() + + if ReturnCode == 0: + Conclusion = "Done" + elif ReturnCode == ABORT_ERROR: + Conclusion = "Aborted" + else: + Conclusion = "Failed" + FinishTime = time.time() + BuildDuration = time.strftime("%M:%S", time.gmtime(int(round(FinishTime - StartTime)))) + EdkLogger.SetLevel(EdkLogger.QUIET) + EdkLogger.quiet("\n- %s -\n%s [%s]" % (Conclusion, time.strftime("%H:%M:%S, %b.%d %Y", time.localtime()), BuildDuration)) + + return ReturnCode + +if __name__ == '__main__': + r = Main() + ## 0-127 is a safe return range, and 1 is a standard default error + if r < 0 or r > 127: r = 1 + sys.exit(r) + diff --git a/BaseTools/Source/Python/fpd2dsc/EdkIIWorkspaceGuidsInfo.py b/BaseTools/Source/Python/fpd2dsc/EdkIIWorkspaceGuidsInfo.py new file mode 100644 index 0000000000..528dbf3ddb --- /dev/null +++ b/BaseTools/Source/Python/fpd2dsc/EdkIIWorkspaceGuidsInfo.py @@ -0,0 +1,327 @@ +## @file +# Collects the Guid Information in current workspace. +# +# Copyright (c) 2007, 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. +# + +## +# Import Modules +# +import os +import fnmatch +from Common.EdkIIWorkspace import EdkIIWorkspace +from Common.MigrationUtilities import * + +## A class for EdkII work space to resolve Guids +# +# This class inherits from EdkIIWorkspace and collects the Guids information +# in current workspace. The Guids information is important to translate the +# package Guids and recommended library instances Guids to relative file path +# (to workspace directory) in MSA files. +# +class EdkIIWorkspaceGuidsInfo(EdkIIWorkspace): + + ## The classconstructor + # + # The constructor initialize workspace directory. It does not collect + # pakage and module Guids info at initialization; instead, it collects them + # on the fly. + # + # @param self The object pointer + # + def __init__(self): + # Initialize parent class. + EdkIIWorkspace.__init__(self) + # The internal map from Guid to FilePath. + self.__GuidToFilePath = {} + # The internal package directory list. + self.__PackageDirList = [] + # The internal flag to indicate whether package Guids info has been initialized + # to avoid re-collection collected. + self.__PackageGuidInitialized = False + # The internal flag to indicate whether module Guids info has been initialized + # to avoid re-collection collected. + self.__ModuleGuidInitialized = False + + ## Add Guid, Version and FilePath to Guids database + # + # Add Guid, Version and FilePath to Guids database. It constructs a map + # table from Guid, Version to FilePath internally. If also detects possible + # Guid collision. For now, the version information is simply ignored and + # Guid value itself acts as master key. + # + # @param self The object pointer + # @param Guid The Guid Value + # @param Version The version information + # @param FilePath The Guid related file path + # + # @retval True The Guid value is successfully added to map table + # @retval False The Guid is an empty string or the map table + # already contains a same Guid + # + def __AddGuidToFilePath(self, Guid, Version, FilePath): + if Guid == "": + EdkLogger.info("Cannot find Guid in file %s" % FilePath) + return False + #Add the Guid value to map table to ensure case insensitive comparison. + OldFilePath = self.__GuidToFilePath.setdefault(Guid.lower(), FilePath) + if OldFilePath == FilePath: + EdkLogger.verbose("File %s has new Guid '%s'" % (FilePath, Guid)) + return True + else: + EdkLogger.info("File %s has duplicate Guid with & %s" % (FilePath, OldFilePath)) + return False + + + ## Gets file information from a module description file + # + # Extracts Module Name, File Guid and Version number from INF, MSA and NMSA + # file. It supports to exact such information from text based INF file or + # XML based (N)MSA file. + # + # @param self The object pointer + # @param FileName The input module file name + # + # @retval True This module file represents a new module discovered + # in current workspace + # @retval False This module file is not regarded as a valid module + # The File Guid cannot be extracted or the another + # file with the same Guid already exists + # + def __GetModuleFileInfo(self, FileName): + if fnmatch.fnmatch(FileName, "*.inf"): + TagTuple = ("BASE_NAME", "FILE_GUID", "VERSION_STRING") + (Name, Guid, Version) = GetTextFileInfo(FileName, TagTuple) + else : + XmlTag1 = "ModuleSurfaceArea/MsaHeader/ModuleName" + XmlTag2 = "ModuleSurfaceArea/MsaHeader/GuidValue" + XmlTag3 = "ModuleSurfaceArea/MsaHeader/Version" + TagTuple = (XmlTag1, XmlTag2, XmlTag3) + (Name, Guid, Version) = GetXmlFileInfo(FileName, TagTuple) + + return self.__AddGuidToFilePath(Guid, Version, FileName) + + + ## Gets file information from a package description file + # + # Extracts Package Name, File Guid and Version number from INF, SPD and NSPD + # file. It supports to exact such information from text based DEC file or + # XML based (N)SPD file. EDK Compatibility Package is hardcoded to be + # ignored since no EDKII INF file depends on that package. + # + # @param self The object pointer + # @param FileName The input package file name + # + # @retval True This package file represents a new package + # discovered in current workspace + # @retval False This package is not regarded as a valid package + # The File Guid cannot be extracted or the another + # file with the same Guid already exists + # + def __GetPackageFileInfo(self, FileName): + if fnmatch.fnmatch(FileName, "*.dec"): + TagTuple = ("PACKAGE_NAME", "PACKAGE_GUID", "PACKAGE_VERSION") + (Name, Guid, Version) = GetTextFileInfo(FileName, TagTuple) + else: + XmlTag1 = "PackageSurfaceArea/SpdHeader/PackageName" + XmlTag2 = "PackageSurfaceArea/SpdHeader/GuidValue" + XmlTag3 = "PackageSurfaceArea/SpdHeader/Version" + TagTuple = (XmlTag1, XmlTag2, XmlTag3) + (Name, Guid, Version) = GetXmlFileInfo(FileName, TagTuple) + + if Name == "EdkCompatibilityPkg": + # Do not scan EDK compatibitilty package to avoid Guid collision + # with those in EDK Glue Library. + EdkLogger.verbose("Bypass EDK Compatibility Pkg") + return False + + return self.__AddGuidToFilePath(Guid, Version, FileName) + + ## Iterate on all package files listed in framework database file + # + # Yields all package description files listed in framework database files. + # The framework database file describes the packages current workspace + # includes. + # + # @param self The object pointer + # + def __FrameworkDatabasePackageFiles(self): + XmlFrameworkDb = XmlParseFile(self.WorkspaceFile) + XmlTag = "FrameworkDatabase/PackageList/Filename" + for PackageFile in XmlElementList(XmlFrameworkDb, XmlTag): + yield os.path.join(self.WorkspaceDir, PackageFile) + + + ## Iterate on all package files in current workspace directory + # + # Yields all package description files listed in current workspace + # directory. This happens when no framework database file exists. + # + # @param self The object pointer + # + def __TraverseAllPackageFiles(self): + for Path, Dirs, Files in os.walk(self.WorkspaceDir): + # Ignore svn version control directory. + if ".svn" in Dirs: + Dirs.remove(".svn") + if "Build" in Dirs: + Dirs.remove("Build") + # Assume priority from high to low: DEC, NSPD, SPD. + PackageFiles = fnmatch.filter(Files, "*.dec") + if len(PackageFiles) == 0: + PackageFiles = fnmatch.filter(Files, "*.nspd") + if len(PackageFiles) == 0: + PackageFiles = fnmatch.filter(Files, "*.spd") + + for File in PackageFiles: + # Assume no more package decription file in sub-directory. + del Dirs[:] + yield os.path.join(Path, File) + + ## Iterate on all module files in current package directory + # + # Yields all module description files listed in current package + # directory. + # + # @param self The object pointer + # + def __TraverseAllModuleFiles(self): + for PackageDir in self.__PackageDirList: + for Path, Dirs, Files in os.walk(PackageDir): + # Ignore svn version control directory. + if ".svn" in Dirs: + Dirs.remove(".svn") + # Assume priority from high to low: INF, NMSA, MSA. + ModuleFiles = fnmatch.filter(Files, "*.inf") + if len(ModuleFiles) == 0: + ModuleFiles = fnmatch.filter(Files, "*.nmsa") + if len(ModuleFiles) == 0: + ModuleFiles = fnmatch.filter(Files, "*.msa") + + for File in ModuleFiles: + yield os.path.join(Path, File) + + ## Initialize package Guids info mapping table + # + # Collects all package guids map to package decription file path. This + # function is invokes on demand to avoid unnecessary directory scan. + # + # @param self The object pointer + # + def __InitializePackageGuidInfo(self): + if self.__PackageGuidInitialized: + return + + EdkLogger.verbose("Start to collect Package Guids Info.") + + WorkspaceFile = os.path.join("Conf", "FrameworkDatabase.db") + self.WorkspaceFile = os.path.join(self.WorkspaceDir, WorkspaceFile) + + # Try to find the frameworkdatabase file to discover package lists + if os.path.exists(self.WorkspaceFile): + TraversePackage = self.__FrameworkDatabasePackageFiles + EdkLogger.verbose("Package list bases on: %s" % self.WorkspaceFile) + else: + TraversePackage = self.__TraverseAllPackageFiles + EdkLogger.verbose("Package list in: %s" % self.WorkspaceDir) + + for FileName in TraversePackage(): + if self.__GetPackageFileInfo(FileName): + PackageDir = os.path.dirname(FileName) + EdkLogger.verbose("Find new package directory %s" % PackageDir) + self.__PackageDirList.append(PackageDir) + + self.__PackageGuidInitialized = True + + ## Initialize module Guids info mapping table + # + # Collects all module guids map to module decription file path. This + # function is invokes on demand to avoid unnecessary directory scan. + # + # @param self The object pointer + # + def __InitializeModuleGuidInfo(self): + if self.__ModuleGuidInitialized: + return + EdkLogger.verbose("Start to collect Module Guids Info") + + self.__InitializePackageGuidInfo() + for FileName in self.__TraverseAllModuleFiles(): + if self.__GetModuleFileInfo(FileName): + EdkLogger.verbose("Find new module %s" % FileName) + + self.__ModuleGuidInitialized = True + + ## Get Package file path by Package Guid and Version + # + # Translates the Package Guid and Version to a file path relative + # to workspace directory. If no package in current workspace match the + # input Guid, an empty file path is returned. For now, the version + # value is simply ignored. + # + # @param self The object pointer + # @param Guid The Package Guid value to look for + # @param Version The Package Version value to look for + # + def ResolvePackageFilePath(self, Guid, Version = ""): + self.__InitializePackageGuidInfo() + + EdkLogger.verbose("Resolve Package Guid '%s'" % Guid) + FileName = self.__GuidToFilePath.get(Guid.lower(), "") + if FileName == "": + EdkLogger.info("Cannot resolve Package Guid '%s'" % Guid) + else: + FileName = self.WorkspaceRelativePath(FileName) + FileName = os.path.splitext(FileName)[0] + ".dec" + FileName = FileName.replace("\\", "/") + return FileName + + ## Get Module file path by Module Guid and Version + # + # Translates the Module Guid and Version to a file path relative + # to workspace directory. If no module in current workspace match the + # input Guid, an empty file path is returned. For now, the version + # value is simply ignored. + # + # @param self The object pointer + # @param Guid The Module Guid value to look for + # @param Version The Module Version value to look for + # + def ResolveModuleFilePath(self, Guid, Version = ""): + self.__InitializeModuleGuidInfo() + + EdkLogger.verbose("Resolve Module Guid '%s'" % Guid) + FileName = self.__GuidToFilePath.get(Guid.lower(), "") + if FileName == "": + EdkLogger.info("Cannot resolve Module Guid '%s'" % Guid) + else: + FileName = self.WorkspaceRelativePath(FileName) + FileName = os.path.splitext(FileName)[0] + ".inf" + FileName = FileName.replace("\\", "/") + return FileName + +# A global class object of EdkIIWorkspaceGuidsInfo for external reference. +gEdkIIWorkspaceGuidsInfo = EdkIIWorkspaceGuidsInfo() + +# This acts like the main() function for the script, unless it is 'import'ed +# into another script. +if __name__ == '__main__': + # Test the translation of package Guid. +# MdePkgGuid = "1E73767F-8F52-4603-AEB4-F29B510B6766" +# OldMdePkgGuid = "5e0e9358-46b6-4ae2-8218-4ab8b9bbdcec" +# print gEdkIIWorkspaceGuidsInfo.ResolveModuleFilePath(MdePkgGuid) +# print gEdkIIWorkspaceGuidsInfo.ResolveModuleFilePath(OldMdePkgGuid) + + # Test the translation of module Guid. +# UefiLibGuid = "3a004ba5-efe0-4a61-9f1a-267a46ae5ba9" +# UefiDriverModelLibGuid = "52af22ae-9901-4484-8cdc-622dd5838b09" +# print gEdkIIWorkspaceGuidsInfo.ResolvePlatformFilePath(UefiLibGuid) +# print gEdkIIWorkspaceGuidsInfo.ResolvePlatformFilePath(UefiDriverModelLibGuid) + pass \ No newline at end of file diff --git a/BaseTools/Source/Python/fpd2dsc/LoadFpd.py b/BaseTools/Source/Python/fpd2dsc/LoadFpd.py new file mode 100644 index 0000000000..cc97ec5521 --- /dev/null +++ b/BaseTools/Source/Python/fpd2dsc/LoadFpd.py @@ -0,0 +1,1039 @@ +## @file +# Open an FPD file and load all its contents to a PlatformClass object. +# +# Copyright (c) 2007, 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. +# + +## +# Import Modules +# +import os +from CommonDataClass.PlatformClass import * +from CommonDataClass.FdfClass import * +from Common.XmlRoutines import * +from Common.MigrationUtilities import * +from EdkIIWorkspaceGuidsInfo import gEdkIIWorkspaceGuidsInfo + +## Load Platform Header +# +# Read an input Platform XML DOM object and return Platform Header class object +# contained in the DOM object. +# +# @param XmlFpd An XML DOM object read from FPD file +# @param FpdFileName The file path of FPD File +# +# @retvel PlatformHeader A new Platform Header object loaded from XmlFpd +# +def LoadPlatformHeader(XmlFpd, FpdFileName): + PlatformHeader = PlatformHeaderClass() + + XmlTag = "PlatformSurfaceArea/PlatformHeader" + FpdHeader = XmlNode(XmlFpd, XmlTag) + + SetIdentification(PlatformHeader, FpdHeader, "PlatformName", FpdFileName) + SetCommonHeader(PlatformHeader, FpdHeader) + + XmlTag = "PlatformSurfaceArea/PlatformHeader/Specification" + List = XmlElement(XmlFpd, XmlTag).split() + SpecificationName = List[0] + SpecificationValue = List[1] + PlatformHeader.Specification = {SpecificationName:SpecificationValue} + + XmlTag = "PlatformSurfaceArea/PlatformDefinitions/SupportedArchitectures" + PlatformHeader.SupArchList = XmlElement(XmlFpd, XmlTag).split() + + XmlTag = "PlatformSurfaceArea/PlatformDefinitions/BuildTargets" + PlatformHeader.BuildTargets = XmlElement(XmlFpd, XmlTag).split() + + XmlTag = "PlatformSurfaceArea/PlatformDefinitions/IntermediateDirectories" + PlatformHeader.IntermediateDirectories = XmlElement(XmlFpd, XmlTag) + + XmlTag = "PlatformSurfaceArea/PlatformDefinitions/OutputDirectory" + PlatformHeader.OutputDirectory = XmlElement(XmlFpd, XmlTag) + + XmlTag = "PlatformSurfaceArea/PlatformDefinitions/SkuInfo" + List = map(LoadSkuId, XmlList(XmlFpd, XmlTag)) + if List != []: + PlatformHeader.SkuIdName = List[0] + + return PlatformHeader + +## Load a Platform SkuId +# +# Read an input Platform XML DOM object and return a list of Platform SkuId +# contained in the DOM object. +# +# @param XmlPlatformSkuInfo An XML DOM object read from FPD file +# +# @retvel PlatformSkuInfo A SkuInfo loaded from XmlFpd +# +def LoadPlatformSkuInfo(XmlPlatformSkuInfo): + XmlTag = "SkuInfo/SkuId" + SkuInfo = [] + SkuId = XmlElement(XmlPlatformSkuInfo, XmlTag) + SkuInfo.append(SkuId) + + XmlTag = "SkuInfo/Value" + Value = XmlElement(XmlPlatformSkuInfo, XmlTag) + SkuInfo.append(Value) + return SkuInfo + +## Load a Platform SkuId +# +# Read an input Platform XML DOM object and return a list of Platform SkuId +# contained in the DOM object. +# +# @param XmlSkuInfo An XML DOM object read from FPD file +# +# @retvel List A list of SkuId and SkuValue loaded from XmlFpd +# +def LoadSkuId(XmlSkuInfo): + XmlTag = "SkuInfo/UiSkuName" + SkuValue = XmlElement(XmlSkuInfo, XmlTag) + + XmlTag = "SkuInfo/UiSkuName" + List = map(LoadSkuID, XmlList(XmlSkuInfo, XmlTag)) + if List != []: + SkuID = List[0] + #SkuID = XmlAttribute(XmlSkuInfo, XmlTag) + List = [] + List.append(SkuID) + List.append(SkuValue) + return List + +def LoadSkuID(XmlUiSkuName): + XmlTag = "SkuID" + SkuID = XmlAttribute(XmlUiSkuName, XmlTag) + return SkuID + +## Load a list of Platform SkuIds +# +# Read an input Platform XML DOM object and return a list of Platform SkuId +# contained in the DOM object. +# +# @param XmlFpd An XML DOM object read from FPD file +# +# @retvel PlatformSkuIds A platform SkuIds object loaded from XmlFpd +# +def LoadPlatformSkuInfos(XmlFpd): + PlatformSkuIds = SkuInfoListClass() + + SkuInfoList = [] + + XmlTag = "PlatformSurfaceArea/PlatformDefinitions/SkuInfo" + List = map(LoadSkuId, XmlList(XmlFpd, XmlTag)) + SkuInfoList = List + + XmlTag = "PlatformSurfaceArea/PlatformDefinitions/SkuInfo/UiSkuName" + Value = XmlElement(XmlFpd, XmlTag) + + XmlTag = "PlatformSurfaceArea/DynamicPcdBuildDefinitions/PcdBuildData/SkuInfo" + # here return a List + List = map(LoadPlatformSkuInfo, XmlList(XmlFpd, XmlTag)) + + for SkuInfo in List: + SkuId = SkuInfo[0] + Value = SkuInfo[1] + + SkuInfoList.append(SkuInfo) + + PlatformSkuIds.SkuInfoList = SkuInfoList + + return PlatformSkuIds + +## Load Platform Module Build Option +# +# Read an input Platform XML DOM object and return Platform Module Build Option class object +# contained in the DOM object. +# +# @param XmlModuleBuildOption An XML DOM object read from FPD file +# +# @retvel PlatformBuildOption A Platform Build Option object loaded from XmlFpd +# +def LoadModuleBuildOption(XmlModuleBuildOption): + PlatformBuildOption = PlatformBuildOptionClass() + PlatformBuildOption.UserDefinedAntTasks = {} + + XmlTag = "BuildOptions/Options/Option" + PlatformBuildOption.Options = map(LoadBuildOption, XmlList(XmlModuleBuildOption, XmlTag)) + + PlatformBuildOption.UserExtensions = {} + PlatformBuildOption.FfsKeyList = {} + return PlatformBuildOption + +## Load Platform Module Extern +# +# Read an input Platform XML DOM object and return Platform Module Extern class object +# contained in the DOM object. +# +# @param XmlModuleExtern An XML DOM object read from FPD file +# +# @retvel PlatformModuleExtern A Platform Module Extern object loaded from XmlFpd +# +def LoadModuleExtern(XmlModuleExtern): + PlatformModuleExtern = [] + + XmlTag = "Externs/PcdIsDriver" + PcdIsDriver = XmlElement(XmlModuleExtern, XmlTag) + PlatformModuleExtern.append(PcdIsDriver) + + XmlTag = "Externs/Specification" + Specification = XmlElement(XmlModuleExtern, XmlTag) + PlatformModuleExtern.append(Specification) + + XmlTag = "Externs/Extern" + + return PlatformModuleExtern + +## Load Platform ModuleSaBuildOptions +# +# Read an input Platform XML DOM object and return Platform ModuleSaBuildOptions class object +# contained in the DOM object. +# +# @param XmlModuleSaBuildOptions An XML DOM object read from FPD file +# +# @retvel PlatformBuildOptions A list of Platform ModuleSaBuildOption object loaded from XmlFpd +# +def LoadPlatformModuleSaBuildOption(XmlModuleSA): + PlatformModuleSaBuildOption = PlatformBuildOptionClasses() + + XmlTag = "ModuleSA/ModuleSaBuildOptions/FvBinding" + PlatformModuleSaBuildOption.FvBinding = XmlElement(XmlModuleSA, XmlTag) + + XmlTag = "ModuleSA/ModuleSaBuildOptions/FfsFormatKey" + PlatformModuleSaBuildOption.FfsFormatKey = XmlElement(XmlModuleSA, XmlTag) + + XmlTag = "ModuleSA/ModuleSaBuildOptions/FfsFileNameGuid" + PlatformModuleSaBuildOption.FfsFileNameGuid = XmlElement(XmlModuleSA, XmlTag) + + XmlTag = "ModuleSA/ModuleSaBuildOptions/Options/Option" + PlatformModuleSaBuildOption.BuildOptionList = map(LoadBuildOption, XmlList(XmlModuleSA, XmlTag)) + + return PlatformModuleSaBuildOption + +## Load a list of Platform Library Classes +# +# Read an input Platform XML DOM object and return a list of Library Classes +# contained in the DOM object. +# +# @param XmlLibraryInstance An XML DOM object read from FPD file +# +# @retvel LibraryInstance A Library Instance loaded from XmlFpd +# +def LoadPlatformModuleLibraryInstance(XmlLibraryInstance): + LibraryInstance = [] + + XmlTag = "ModuleGuid" + ModuleGuid = XmlAttribute(XmlLibraryInstance, XmlTag) + + ModulePath = gEdkIIWorkspaceGuidsInfo.ResolveModuleFilePath(ModuleGuid) + ModuleMSAFile = ModulePath.replace('.inf', '.msa') + WorkSpace = os.getenv('WORKSPACE') + ModuleMSAFileName = os.path.join(WorkSpace, ModuleMSAFile) + XmlMsa = XmlParseFile(ModuleMSAFileName) + + XmlTag = "ModuleSurfaceArea/LibraryClassDefinitions/LibraryClass/Keyword" + Name = XmlElement(XmlMsa, XmlTag) + LibraryInstance.append(Name) + LibraryInstance.append(ModulePath) + + #XmlTag = "PackageGuid" + #PackageGuid = XmlAttribute(XmlLibraryInstance, XmlTag) + #LibraryInstance.append(PackageGuid) + return LibraryInstance + +## Load a Library Class +# +# Read an input Platform XML DOM object and return a library class object +# contained in the DOM object. +# +# @param XmlLibraryClass An XML DOM object read from FPD file +# +# @retvel SupModuleList A Library Class Supported Module List object loaded from XmlFpd +# +def LoadLibraryClassSupModuleList(XmlLibraryClass): + XmlTag = "Usage" + Usage = XmlAttribute(XmlLibraryClass, XmlTag) + if Usage == "ALWAYS_PRODUCED": + XmlTag = "SupModuleList" + SupModuleList = XmlAttribute(XmlLibraryClass, XmlTag).split() + return SupModuleList + +## Load Platform Library Class +# +# Read an input Platform XML DOM object and return Platform module class object +# contained in the DOM object. +# +# @param XmlLibraries An XML DOM object read from FPD file +# +# @retvel PlatformLibraryClass A Platform Library Class object loaded from XmlFpd +# +def LoadPlatformLibraryClass(XmlPlatformLibraryClass): + PlatformLibraryInstance = PlatformLibraryClass() + + XmlTag = "ModuleGuid" + LibraryInstanceModuleGuid = XmlAttribute(XmlPlatformLibraryClass, XmlTag) + + XmlTag = "PackageGuid" + LibraryInstancePackageGuid = XmlAttribute(XmlPlatformLibraryClass, XmlTag) + + LibraryInstancePath = gEdkIIWorkspaceGuidsInfo.ResolveModuleFilePath(LibraryInstanceModuleGuid) + + if LibraryInstancePath != "": # if LibraryInstancePath == "" that's because the module guid cannot be resolved + PlatformLibraryInstance.FilePath = LibraryInstancePath + # replace *.inf to *.msa + LibraryInstanceMSAName = LibraryInstancePath.replace('.inf', '.msa') + WorkSpace = os.getenv('WORKSPACE') + LibraryInstanceMSAPath = os.path.join(WorkSpace, LibraryInstanceMSAName) + + PlatformLibraryInstance.FilePath = LibraryInstancePath + + XmlMsa = XmlParseFile(LibraryInstanceMSAPath) + + XmlTag = "ModuleSurfaceArea/MsaHeader/ModuleName" + PlatformLibraryInstance.Name = XmlElement(XmlMsa, XmlTag) + + XmlTag = "ModuleSurfaceArea/MsaHeader/ModuleType" + PlatformLibraryInstance.ModuleType = XmlElement(XmlMsa, XmlTag) + + if PlatformLibraryInstance.ModuleType != "BASE": + XmlTag = "ModuleSurfaceArea/LibraryClassDefinitions/LibraryClass" + List = map(LoadLibraryClassSupModuleList, XmlList(XmlMsa, XmlTag)) + if List != []: + PlatformLibraryInstance.SupModuleList = List[0] + XmlTag = "ModuleSurfaceArea/ModuleDefinitions/SupportedArchitectures" + PlatformLibraryInstance.SupArchList = XmlElement(XmlMsa, XmlTag).split() + + PlatformLibraryInstance.ModuleGuid = LibraryInstanceModuleGuid + + XmlTag = "ModuleSurfaceArea/MsaHeader/Version" + PlatformLibraryInstance.ModuleVersion = XmlElement(XmlMsa, XmlTag) + + PlatformLibraryInstance.PackageGuid = LibraryInstancePackageGuid + PlatformLibraryInstance.PackageVersion = '' + + return PlatformLibraryInstance + +## Load Platform Library Classes +# +# Read an input Platform XML DOM object and return Platform module class object +# contained in the DOM object. +# +# @param XmlLibraries An XML DOM object read from FPD file +# +# @retvel PlatformLibraryClasses A list of Platform Library Class object loaded from XmlFpd +# +def LoadPlatformLibraryClasses(XmlFpd): + PlatformLibraryInstances = PlatformLibraryClasses() + PlatformLibraryInstances.LibraryList = [] + + List = [] + XmlTag = "PlatformSurfaceArea/FrameworkModules/ModuleSA/Libraries/Instance" + List = map(LoadPlatformLibraryClass, XmlList(XmlFpd, XmlTag)) + #List.sort() + if List == []: + print "Error" + else: + PlatformLibraryInstances.LibraryList = List + + return PlatformLibraryInstances + +## Load Platform module +# +# Read an input Platform XML DOM object and return Platform module class object +# contained in the DOM object. +# +# @param XmlModuleSA An XML DOM object read from FPD file +# +# @retvel PlatformModule A Platform module object loaded from XmlFpd +# +def LoadModuleSA(XmlModuleSA): + PlatformModule = PlatformModuleClass() + + # three parts: Libraries instances, PcdBuildDefinition, ModuleSaBuildOptions + XmlTag = "ModuleSA/Libraries/Instance" + + PlatformModule.LibraryClasses = map(LoadPlatformModuleLibraryInstance, XmlList(XmlModuleSA, XmlTag)) + + XmlTag = "ModuleSA/PcdBuildDefinition/PcdData" + PlatformModule.PcdBuildDefinitions = map(LoadPlatformPcdData, XmlList(XmlModuleSA, XmlTag)) + + XmlTag = "ModuleSA/ModuleSaBuildOptions" + PlatformModule.ModuleSaBuildOption = LoadPlatformModuleSaBuildOption(XmlModuleSA) + + XmlTag = "ModuleSA/BuildOptions" + PlatformModule.BuildOptions = map(LoadModuleBuildOption, XmlList(XmlModuleSA, XmlTag)) #bugbug fix me + + XmlTag = "ModuleSA/Externs" + PlatformModule.Externs = map(LoadModuleExtern, XmlList(XmlModuleSA, XmlTag)) #bugbug fix me + + XmlTag = "SupArchList" + PlatformModule.SupArchList = XmlAttribute(XmlModuleSA, XmlTag).split() + + # the package guid which the module depends on, do not care for now + XmlTag = "PackageGuid" + PlatformModule.PackageGuid = XmlAttribute(XmlModuleSA, XmlTag) + + # the module guid, use this guid to get the module *.msa file and convert it to *.inf file with path + XmlTag = "ModuleGuid" + PlatformModule.ModuleGuid = XmlAttribute(XmlModuleSA, XmlTag) + # use this guid to find the *.msa file path or FilePath $(WORKSPACE)/EdkModulePkg/Core/Dxe/DxeMain.msa + # then convert $(WORKSPACE)/EdkModulePkg/Core/Dxe/DxeMain.msa to $(WORKSPACE)/EdkModulePkg/Core/Dxe/DxeMain.inf, it's FilePath + PlatformModulePath = gEdkIIWorkspaceGuidsInfo.ResolveModuleFilePath(PlatformModule.ModuleGuid) + + PlatformModule.FilePath = PlatformModulePath # *.inf file path + # *.inf back to *.msa + ModuleMSAFileName = PlatformModulePath.replace('.inf', '.msa') + WorkSpace = os.getenv('WORKSPACE') + ModuleMSAFileName = os.path.join(WorkSpace, ModuleMSAFileName) + # Open this module + #ModuleMSA = open(ModuleMSAFileName, "r") + XmlMsa = XmlParseFile(ModuleMSAFileName) + + XmlTag = "ModuleSurfaceArea/MsaHeader/ModuleName" + PlatformModule.Name = XmlElement(XmlMsa, XmlTag) # ModuleName + + XmlTag = "ModuleSurfaceArea/MsaHeader/ModuleType" + PlatformModule.ModuleType = XmlElement(XmlMsa, XmlTag) + + # IA32, X64, IPF and EBC which the module support arch + #XmlTag = "ModuleSurfaceArea/ModuleDefinitions/SupportedArchitectures" + #PlatformModule.SupArchList = XmlElement(XmlMsa, XmlTag).split() + + #XmlTag = "ModuleSurfaceArea/MsaHeader/" + PlatformModule.Type = '' #LIBRARY | LIBRARY_CLASS | MODULE, used by dsc. New in DSC spec + + PlatformModule.ExecFilePath = '' # New in DSC spec + + XmlTag = "ModuleSurfaceArea/MsaHeader/Specification" + PlatformModule.Specifications = XmlElement(XmlMsa, XmlTag).split() + + return PlatformModule + +## Load Platform modules +# +# Read an input Platform XML DOM object and return a list of Platform modules class object +# contained in the DOM object. +# +# @param XmlFpd An XML DOM object read from FPD file +# +# @retvel PlatformModules A list of Platform modules object loaded from XmlFpd +# +def LoadPlatformModules(XmlFpd): + PlatformModules = PlatformModuleClasses() + + XmlTag = "PlatformSurfaceArea/FrameworkModules/ModuleSA" + PlatformModules.ModuleList = map(LoadModuleSA, XmlList(XmlFpd, XmlTag)) + + return PlatformModules + +## Load Platform Flash Definition File +# +# Read an input Platform XML DOM object and return Platform Flash Definition File class object +# contained in the DOM object. +# +# @param XmlFpd An XML DOM object read from FPD file +# @param FpdFileName The file path of FPD File +# +# @retvel PlatformFlashDefinitionFile A new Platform Flash Definition File object loaded from XmlFpd +# +def LoadPlatformFlashDefinitionFile(XmlFpd, FpdFileName): + PlatformFlashDefinitionFile = PlatformFlashDefinitionFileClass() + + XmlTag = "PlatformSurfaceArea/Flash/FlashDefinitionFile" + PlatformFlashDefinitionFile.FilePath = XmlElement(XmlFpd, XmlTag) + + XmlTag = "PlatformSurfaceArea/Flash/FlashDefinitionFile/Id" + PlatformFlashDefinitionFile.Id = XmlAttribute(XmlFpd, XmlTag) + + XmlTag = "PlatformSurfaceArea/Flash/FlashDefinitionFile/UiName" + PlatformFlashDefinitionFile.UiName = XmlAttribute(XmlFpd, XmlTag) + + XmlTag = "PlatformSurfaceArea/Flash/FlashDefinitionFile/Preferred" + PlatformFlashDefinitionFile.Preferred = XmlAttribute(XmlFpd, XmlTag) + + return PlatformFlashDefinitionFile + +## Load Platform User Defined Ant Tasks +# +# Read an input Platform XML DOM object and return platform +# User Defined Ant Tasks contained in the DOM object. +# +# @param XmlUserDefinedAntTasks An XML DOM object read from FPD file +# +# @retvel AntTask An Ant Task loaded from XmlFpd +# +def LoadUserDefinedAntTasks(XmlFpd): + Dict = {} + AntTask = PlatformAntTaskClass() + + XmlTag = "PlatformSurfaceArea/BuildOptions/UserDefinedAntTasks/AntTask/Id" + AntTask.Id = XmlAttribute(XmlFpd, XmlTag) + + XmlTag = "PlatformSurfaceArea/BuildOptions/UserDefinedAntTasks/AntTask/AntCmdOptions" + AntTask.AntCmdOptions = XmlElement(XmlFpd, XmlTag) + + XmlTag = "PlatformSurfaceArea/BuildOptions/UserDefinedAntTasks/AntTask/Filename" + AntTask.FilePath = XmlElement(XmlFpd, XmlTag) + + Dict[AntTask.Id] = AntTask + return Dict + +## Load Platform Build Options +# +# Read an input Platform XML DOM object and return a list of platform +# Build Option contained in the DOM object. +# +# @param XmlBuildOptions An XML DOM object read from FPD file +# +# @retvel PlatformBuildOptions A list of platform Build Options loaded from XmlFpd +# +def LoadBuildOptions(XmlBuildOptions): + XmlTag = "Option" + return map(LoadBuildOption, XmlList(XmlBuildOptions, XmlTag)) # LoadBuildOption is a method in MigrationUtilities.py + +## Load Platform Build Option +# +# Read an input Platform XML DOM object and return a Build Option +# contained in the DOM object. +# +# @param XmlFpd An XML DOM object read from FPD file +# +# @retvel PlatformBuildOption A Build Options loaded from XmlFpd +# +def LoadPlatformBuildOption(XmlBuildOptions): + PlatformBuildOption = PlatformBuildOptionClass() + + # handle UserDefinedAntTasks + XmlTag = "BuildOptions/UserDefinedAntTasks/AntTask" + PlatformBuildOption.UserDefinedAntTasks = LoadUserDefinedAntTasks(XmlTag) + + # handle Options + XmlTag = "BuildOptions/Options/Option" + PlatformBuildOption.Options = map(LoadBuildOption, XmlList(XmlBuildOptions, XmlTag)) + + # handle UserExtensions + XmlTag = "BuildOptions/UserExtensions" + PlatformBuildOption.UserExtensions = LoadUserExtensions(XmlTag) # from MigrationUtilities.py LoadUserExtensions + + # handle Ffs + XmlTag = "BuildOptions/Ffs/FfsKey" + PlatformBuildOption.FfsKeyList = map(LoadPlatformFfs, XmlList(XmlBuildOptions, XmlTag)) + + return PlatformBuildOption + +## Load Platform Ffs Dictionary +# +# Read an input Platform XML DOM object and return a platform Ffs Dictionary +# contained in the DOM object. +# +# @param XmlFpd An XML DOM object read from FPD file +# +# @retvel Dict A platform Ffs Dict loaded from XmlFpd +# +def LoadPlatformFfsDict(XmlFpd): + Dict = {} + XmlTag = "PlatformSurfaceArea/BuildOptions/Ffs" + List = map(LoadPlatformFfs, XmlList(XmlFpd, XmlTag)) + if List != []: + for Ffs in List: + Dict[Ffs.Key] = Ffs + return Dict + +## Load Platform Ffs Section +# +# Read an input Platform XML DOM object and return a platform Ffs Section +# contained in the DOM object. +# +# @param XmlFfs An XML DOM object read from FPD file +# +# @retvel PlatformFfsSection A platform Ffs Section loaded from XmlFpd +# +def LoadPlatformFfsSection(XmlFfsSection): + PlatformFfsSection = PlatformFfsSectionClass() + + XmlTag = "" + PlatformFfsSection.BindingOrder = '' + + XmlTag = "" + PlatformFfsSection.Compressible = '' + + XmlTag = "SectionType" + PlatformFfsSection.SectionType = XmlAttribute(XmlFfsSection, XmlTag) + + XmlTag = "" + PlatformFfsSection.EncapsulationType = '' + + XmlTag = "" + PlatformFfsSection.ToolName = '' + + XmlTag = "" + PlatformFfsSection.Filenames = [] + + XmlTag = "" + PlatformFfsSection.Args = '' + + XmlTag = "" + PlatformFfsSection.OutFile = '' + + XmlTag = "" + PlatformFfsSection.OutputFileExtension = '' + + XmlTag = "" + PlatformFfsSection.ToolNameElement = '' + + return PlatformFfsSection + +## Load Platform Ffs Sections +# +# Read an input Platform XML DOM object and return a platform Ffs Sections +# contained in the DOM object. +# +# @param XmlFfs An XML DOM object read from FPD file +# +# @retvel PlatformFfsSections A platform Ffs Sections loaded from XmlFpd +# +def LoadFfsSections(): + PlatformFfsSections = PlatformFfsSectionsClass() + PlatformFfsSections.BindingOrder = '' + PlatformFfsSections.Compressible = '' + PlatformFfsSections.SectionType = '' + PlatformFfsSections.EncapsulationType = '' + PlatformFfsSections.ToolName = '' + PlatformFfsSections.Section = [] + PlatformFfsSections.Sections = [] + + return PlatformFfsSections + +## Load Platform Ffs Sections +# +# Read an input Platform XML DOM object and return a platform Ffs Sections +# contained in the DOM object. +# +# @param XmlFfs An XML DOM object read from FPD file +# +# @retvel PlatformFfsSections A platform Ffs Sections loaded from XmlFpd +# +def LoadPlatformFfsSections(XmlFfsSections): + PlatformFfsSections = PlatformFfsSectionsClass() + + XmlTag = "" + PlatformFfsSections.BindingOrder = '' + + XmlTag = "" + Compressible = '' + + XmlTag = "" + SectionType = '' + + XmlTag = "EncapsulationType" + EncapsulationType = XmlAttribute(XmlFfsSections, XmlTag) + + XmlTag = "" + ToolName = '' + + XmlTag = "Sections/Section" + Section = [] #[ PlatformFfsSectionClass, ... ] + Section = map(LoadPlatformFfsSection, XmlList(XmlFfsSections, XmlTag)) + + + XmlTag = "Sections/Sections" + Sections = map(LoadFfsSections, XmlList(XmlFfsSections, XmlTag)) #[ PlatformFfsSectionsClass, ...] + + return PlatformFfsSections + +## Load Platform Ffs Attribute +# +# Read an input Platform XML DOM object and return a platform Ffs Attribute +# contained in the DOM object. +# +# @param XmlFfs An XML DOM object read from FPD file +# +# @retvel List A platform Ffs Attribute loaded from XmlFpd +# +def LoadFfsAttribute(XmlFfs): + List = [] + XmlTag = "Ffs/Attribute" + for XmlAttr in XmlList(XmlFfs, XmlTag): + XmlTag = "Name" + Name = XmlAttribute(XmlAttr, XmlTag) + XmlTag = "Value" + Value = XmlAttribute(XmlAttr, XmlTag) + List.append([Name,Value]) + return List + +## Load a list of Platform Build Options +# +# Read an input Platform XML DOM object and return a list of Build Options +# contained in the DOM object. +# +# @param XmlFfs An XML DOM object read from FPD file +# +# @retvel PlatformFfsKey A platform Ffs key loaded from XmlFpd +# +def LoadPlatformFfs(XmlFfs): + PlatformFfs = PlatformFfsClass() + + PlatformFfs.Attribute = {} + Dict = {} + + List = LoadFfsAttribute(XmlFfs) + + XmlTag = "Ffs/Sections/Sections" + PlatformFfs.Sections = map(LoadPlatformFfsSections, XmlList(XmlFfs, XmlTag)) #[PlatformFfsSectionsClass, ...] + + for Item in List: + Name = Item[0] + Value = Item[1] + for Item in PlatformFfs.Sections: + Dict[(Name, Item)] = Value + PlatformFfs.Attribute = Dict + + XmlTag = "Ffs/FfsKey" + PlatformFfs.Key = XmlAttribute(XmlFfs, XmlTag) + + return PlatformFfs + +## Load a list of Platform Build Options +# +# Read an input Platform XML DOM object and return a list of Build Options +# contained in the DOM object. +# +# @param XmlFpd An XML DOM object read from FPD file +# +# @retvel PlatformBuildOptions A list of Build Options loaded from XmlFpd +# +def LoadPlatformBuildOptions(XmlFpd): + PlatformBuildOptions = PlatformBuildOptionClass() + + PlatformBuildOptions.UserDefinedAntTasks = LoadUserDefinedAntTasks(XmlFpd) + + XmlTag = "PlatformSurfaceArea/BuildOptions/Options/Option" + PlatformBuildOptions.Options = map(LoadBuildOption, XmlList(XmlFpd, XmlTag)) + + PlatformBuildOptions.UserExtensions = LoadPlatformUserExtension(XmlFpd) + + PlatformBuildOptions.FfsKeyList = LoadPlatformFfsDict(XmlFpd) + + return PlatformBuildOptions + +## Load Platform Pcd Data +# +# Read an input Platform XML DOM object and return Platform module class object +# contained in the DOM object. +# +# @param XmlPcd An XML DOM object read from FPD file +# +# @retvel PlatformPcdData A Platform Pcd object loaded from XmlFpd +# +def LoadPlatformPcdData(XmlPcdData): + PcdData = PcdClass() # defined in CommonDataClass.CommonClass.py + + XmlTag = "ItemType" + PcdData.ItemType = XmlAttribute(XmlPcdData, XmlTag) #DYNAMIC + + XmlTag = "PcdData/C_Name" + PcdData.C_NAME = XmlElement(XmlPcdData, XmlTag) + + XmlTag = "PcdData/Token" + PcdData.Token = XmlElement(XmlPcdData, XmlTag) + + XmlTag = "PcdData/TokenSpaceGuidCName" + PcdData.TokenSpaceGuidCName = XmlElement(XmlPcdData, XmlTag) + + XmlTag = "PcdData/DatumType" + PcdData.DatumType = XmlElement(XmlPcdData, XmlTag) + + XmlTag = "PcdData/MaxDatumSize" + PcdData.MaxDatumSize = XmlElement(XmlPcdData, XmlTag) + + XmlTag = "PcdData/Value" + PcdData.Value = XmlElement(XmlPcdData, XmlTag) + + return PcdData + +## Load a Platform Pcd Build Data +# +# Read an input Platform XML DOM object and return a list of Pcd Dynamic +# contained in the DOM object. +# +# @param XmlPcdBuildData An XML DOM object read from FPD file +# +# @retvel PcdBuildData A Platform Pcd Build Data loaded from XmlFpd +# +def LoadPlatformPcdBuildData(XmlPcdBuildData): + PcdBuildData = PcdClass() # defined in CommonDataClass.CommonClass.py + + XmlTag = "ItemType" + PcdBuildData.ItemType = XmlAttribute(XmlPcdBuildData, XmlTag) #DYNAMIC + + XmlTag = "PcdBuildData/C_Name" + PcdBuildData.C_NAME = XmlElement(XmlPcdBuildData, XmlTag) + + XmlTag = "PcdBuildData/Token" + PcdBuildData.Token = XmlElement(XmlPcdBuildData, XmlTag) + + XmlTag = "PcdBuildData/TokenSpaceGuidCName" + PcdBuildData.TokenSpaceGuidCName = XmlElement(XmlPcdBuildData, XmlTag) + + XmlTag = "PcdBuildData/DatumType" + PcdBuildData.DatumType = XmlElement(XmlPcdBuildData, XmlTag) + + XmlTag = "PcdBuildData/MaxDatumSize" + PcdBuildData.MaxDatumSize = XmlElement(XmlPcdBuildData, XmlTag) + + #XmlTag = "PcdBuildData/Value" + #PcdBuildData.Value = XmlElement(XmlPcdBuildData, XmlTag) + + return PcdBuildData + +## Load a list of Platform Pcd Dynamic +# +# Read an input Platform XML DOM object and return a list of Pcd Dynamic +# contained in the DOM object. +# +# @param XmlFpd An XML DOM object read from FPD file +# +# @retvel PcdDynamic A list of Pcd Dynamic loaded from XmlFpd +# +def LoadDynamicPcdBuildDefinitions(XmlFpd): + DynamicPcdBuildDefinitions = [] + XmlTag = "PlatformSurfaceArea/DynamicPcdBuildDefinitions/PcdBuildData" + return map(LoadPlatformPcdBuildData, XmlList(XmlFpd, XmlTag)) + +## Load a Platform NameValue object +# +# Read an input Platform XML DOM object and return a list of User Extensions +# contained in the DOM object. +# +# @param XmlNameValue An XML DOM object read from FPD file +# +# @retvel NameValue A Platform NameValue object +# +def LoadNameValue(XmlNameValue): + NameValue = [] + + XmlTag = "Name" + Name = XmlAttribute(XmlNameValue, XmlTag) + NameValue.append(Name) + + XmlTag = "Value" + Value = XmlAttribute(XmlNameValue, XmlTag) + NameValue.append(Value) + + return NameValue + +## Load a Platform Fv Image Name object +# +# Read an input Platform XML DOM object and return a platform Fv Image +# Name contained in the DOM object. +# +# @param XmlFvImageNames An XML DOM object read from FPD file +# +# @retvel FvImageNames A Platform Fv Image Name object +# +def LoadFvImageNames(XmlFvImageNames): + XmlTag = "FvImageNames" + FvImageNames = XmlElement(XmlFvImageNames, XmlTag) + return FvImageNames + +## Load a Platform Fv Image option object +# +# Read an input Platform XML DOM object and return a platform Fv Image +# Option contained in the DOM object. +# +# @param XmlFvImageOptions An XML DOM object read from FPD file +# +# @retvel PlatformFvImageOption A Platform Fv Image Option object +# +def LoadFvImageOptions(XmlFvImageOptions): + PlatformFvImageOption = PlatformFvImageOptionClass() + + XmlTag = "" + PlatformFvImageOption.FvImageOptionName = '' + + XmlTag = "" + PlatformFvImageOption.FvImageOptionValues = [] + + XmlTag = "FvImageOptions/NameValue" + List = map(LoadNameValue, XmlList(XmlFvImageOptions, XmlTag)) + + return PlatformFvImageOption + +## Load a Platform Fv Image object +# +# Read an input Platform XML DOM object and return a list of User Extensions +# contained in the DOM object. +# +# @param XmlFvImage An XML DOM object read from Fpd file +# +# @retvel PlatformFvImage A Platform Fv Image object +# +def LoadPlatformFvImage(XmlFvImage): + PlatformFvImage = PlatformFvImageClass() + + XmlTag = "Name" + PlatformFvImage.Name = XmlAttribute(XmlFvImage, XmlTag) + + XmlTag = "Value" + PlatformFvImage.Value = XmlAttribute(XmlFvImage, XmlTag) + + XmlTag = "Type" + PlatformFvImage.Type = XmlAttribute(XmlFvImage, XmlTag) + + XmlTag = "FvImage/FvImageNames" + PlatformFvImage.FvImageNames = map(LoadFvImageNames, XmlList(XmlFvImage, XmlTag)) + + XmlTag = "FvImage/FvImageOptions" + PlatformFvImage.FvImageOptions = map(LoadFvImageOptions, XmlList(XmlFvImage, XmlTag)) + + return PlatformFvImage + +## Load a Platform fdf object +# +# Read an input Platform XML DOM object and return a list of User Extensions +# contained in the DOM object. +# +# @param XmlFvImages An XML DOM object read from FPD file +# +# @retvel PlatformFdf A Platform fdf object +# +def LoadPlatformFvImages(XmlFvImages): + List = [] + + XmlTag = "FvImages/NameValue" + NameValues = map(LoadNameValue, XmlList(XmlFvImages, XmlTag)) + List.append(NameValues) + + XmlTag = "FvImages/FvImage" + FvImages = map(LoadPlatformFvImage, XmlList(XmlFvImages, XmlTag)) + List.append(FvImages) + + XmlTag = "FvImages/FvImageName" + FvImageNames = map(LoadPlatformFvImageName, XmlList(XmlFvImages, XmlTag)) + List.append(FvImageNames) + + return List + +## Load a Platform Fv Image Name object +# +# Read an input Platform XML DOM object and return a list of User Extensions +# contained in the DOM object. +# +# @param XmlFvImageName An XML DOM object read from FPD file +# +# @retvel PlatformFvImageName A Platform Fv Image Name object +# +def LoadPlatformFvImageName(XmlFvImageName): + PlatformFvImageName = PlatformFvImageNameClass() + + XmlTag = "Name" + PlatformFvImageName.Name = XmlAttribute(XmlFvImageName, XmlTag) + + XmlTag = "Type" + PlatformFvImageName.Type = XmlAttribute(XmlFvImageName, XmlTag) + + XmlTag = "FvImageOptions" + PlatformFvImageName.FvImageOptions = map(LoadFvImageOptions, XmlList(XmlFvImageName, XmlTag)) + + return PlatformFvImageName + +## Load a list of Platform fdf objects +# +# Read an input Platform XML DOM object and return a list of User Extensions +# contained in the DOM object. +# +# @param XmlFpd An XML DOM object read from FPD file +# +# @retvel PlatformFdfs A list of Platform fdf object +# +def LoadPlatformFdfs(XmlFpd): + PlatformFvImages = PlatformFvImagesClass() + + XmlTag = "PlatformSurfaceArea/Flash/FvImages" + PlatformFvImages.FvImages = map(LoadPlatformFvImages, XmlList(XmlFpd, XmlTag)) + + return PlatformFvImages + +## Load a Platform User Extensions +# +# Read an input Platform XML DOM object and return an User Extension +# contained in the DOM object. +# +# @param XmlUserExtension An XML DOM object read from FPD file +# +# @retvel PlatformUserExtensions A platform User Extension loaded from XmlFpd +# +def LoadPlatformUserExtension(XmlFpd): + Dict = {} + + PlatformUserExtensions = UserExtensionsClass() + + XmlTag = "PlatformSurfaceArea/BuildOptions/UserExtensions" + List = map(LoadUserExtensions, XmlList(XmlFpd, XmlTag)) + if List != []: + for Item in List: + UserID = Item.UserID + Identifier = Item.Identifier + Dict[(UserID, Identifier)] = Item + #XmlTag = "PlatformSurfaceArea/BuildOptions/UserExtensions/UserID" + #PlatformUserExtensions.UserID = XmlAttribute(XmlFpd, XmlTag) + + #XmlTag = "PlatformSurfaceArea/BuildOptions/UserExtensions/Identifier" + #PlatformUserExtensions.Identifier = XmlAttribute(XmlFpd, XmlTag) + + #PlatformUserExtensions.Content = XmlElementData(XmlFpd) + #Dict[(PlatformUserExtensions.UserID,PlatformUserExtensions.Identifier)] = PlatformUserExtensions + #return PlatformUserExtensions + return Dict + +## Load a list of Platform User Extensions +# +# Read an input Platform XML DOM object and return a list of User Extensions +# contained in the DOM object. +# +# @param XmlFpd An XML DOM object read from FPD file +# +# @retvel UserExtensions A list of platform User Extensions loaded from XmlFpd +# +def LoadPlatformUserExtensions(XmlFpd): + XmlTag = "PlatformSurfaceArea/UserExtensions" + return map(LoadUserExtensions, XmlList(XmlFpd, XmlTag)) # from MigrationUtilities.py LoadUserExtensions + +## Load a new Platform class object +# +# Read an input FPD File and return a new Platform class Object. +# +# @param FpdFileName An XML DOM object read from FPD file +# +# @retvel Platform A new Platform class object loaded from FPD File +# +def LoadFpd(FpdFileName): + XmlFpd = XmlParseFile(FpdFileName) + EdkLogger.verbose("Load FPD File: %s" % FpdFileName) + + Platform = PlatformClass() + Platform.Header = LoadPlatformHeader(XmlFpd, FpdFileName) + Platform.SkuInfos = LoadPlatformSkuInfos(XmlFpd) + Platform.Libraries = [] #New in dsc spec, do not handle for now + Platform.LibraryClasses = LoadPlatformLibraryClasses(XmlFpd) + Platform.Modules = LoadPlatformModules(XmlFpd) + Platform.FlashDefinitionFile = LoadPlatformFlashDefinitionFile(XmlFpd, FpdFileName) + Platform.BuildOptions = LoadPlatformBuildOptions(XmlFpd) + Platform.DynamicPcdBuildDefinitions = LoadDynamicPcdBuildDefinitions(XmlFpd) + Platform.Fdf = LoadPlatformFdfs(XmlFpd) + Platform.UserExtensions = LoadPlatformUserExtensions(XmlFpd) + + return Platform + +# This acts like the main() function for the script, unless it is 'import'ed +# into another script. +if __name__ == '__main__': + pass \ No newline at end of file diff --git a/BaseTools/Source/Python/fpd2dsc/MigrationUtilities.py b/BaseTools/Source/Python/fpd2dsc/MigrationUtilities.py new file mode 100644 index 0000000000..d3c724832c --- /dev/null +++ b/BaseTools/Source/Python/fpd2dsc/MigrationUtilities.py @@ -0,0 +1,563 @@ +## @file +# Contains several utilitities shared by migration tools. +# +# Copyright (c) 2007, 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. +# + +## +# Import Modules +# +import os +import re +import EdkLogger +from optparse import OptionParser +from Common.BuildToolError import * +from XmlRoutines import * +from CommonDataClass.CommonClass import * + +## Set all fields of CommonClass object. +# +# Set all attributes of CommonClass object from XML Dom object of XmlCommon. +# +# @param Common The destine CommonClass object. +# @param XmlCommon The source XML Dom object. +# +def SetCommon(Common, XmlCommon): + XmlTag = "Usage" + Common.Usage = XmlAttribute(XmlCommon, XmlTag).split() + + XmlTag = "FeatureFlag" + Common.FeatureFlag = XmlAttribute(XmlCommon, XmlTag) + + XmlTag = "SupArchList" + Common.SupArchList = XmlAttribute(XmlCommon, XmlTag).split() + + XmlTag = XmlNodeName(XmlCommon) + "/" + "HelpText" + Common.HelpText = XmlElement(XmlCommon, XmlTag) + + +## Set some fields of CommonHeaderClass object. +# +# Set Name, Guid, FileName and FullPath fields of CommonHeaderClass object from +# XML Dom object of XmlCommonHeader, NameTag and FileName. +# +# @param CommonHeader The destine CommonClass object. +# @param XmlCommonHeader The source XML Dom object. +# @param NameTag The name tag in XML Dom object. +# @param FileName The file name of the XML file. +# +def SetIdentification(CommonHeader, XmlCommonHeader, NameTag, FileName): + XmlParentTag = XmlNodeName(XmlCommonHeader) + + XmlTag = XmlParentTag + "/" + NameTag + CommonHeader.Name = XmlElement(XmlCommonHeader, XmlTag) + + XmlTag = XmlParentTag + "/" + "GuidValue" + CommonHeader.Guid = XmlElement(XmlCommonHeader, XmlTag) + + XmlTag = XmlParentTag + "/" + "Version" + CommonHeader.Version = XmlElement(XmlCommonHeader, XmlTag) + + CommonHeader.FileName = os.path.basename(FileName) + CommonHeader.FullPath = os.path.abspath(FileName) + + +## Regular expression to match specification and value. +mReSpecification = re.compile(r"(?P\w+)\s+(?P\w*)") + +## Add specification to specification dictionary. +# +# Abstract specification name, value pair from Specification String and add them +# to specification dictionary. +# +# @param SpecificationDict The destine Specification dictionary. +# @param SpecificationString The source Specification String from which the +# specification name and value pair is abstracted. +# +def AddToSpecificationDict(SpecificationDict, SpecificationString): + """Abstract specification name, value pair from Specification String""" + for SpecificationMatch in mReSpecification.finditer(SpecificationString): + Specification = SpecificationMatch.group("Specification") + Value = SpecificationMatch.group("Value") + SpecificationDict[Specification] = Value + +## Set all fields of CommonHeaderClass object. +# +# Set all attributes of CommonHeaderClass object from XML Dom object of +# XmlCommonHeader, NameTag and FileName. +# +# @param CommonHeader The destine CommonClass object. +# @param XmlCommonHeader The source XML Dom object. +# @param NameTag The name tag in XML Dom object. +# @param FileName The file name of the XML file. +# +def SetCommonHeader(CommonHeader, XmlCommonHeader): + """Set all attributes of CommonHeaderClass object from XmlCommonHeader""" + XmlParent = XmlNodeName(XmlCommonHeader) + + XmlTag = XmlParent + "/" + "Abstract" + CommonHeader.Abstract = XmlElement(XmlCommonHeader, XmlTag) + + XmlTag = XmlParent + "/" + "Description" + CommonHeader.Description = XmlElement(XmlCommonHeader, XmlTag) + + XmlTag = XmlParent + "/" + "Copyright" + CommonHeader.Copyright = XmlElement(XmlCommonHeader, XmlTag) + + XmlTag = XmlParent + "/" + "License" + CommonHeader.License = XmlElement(XmlCommonHeader, XmlTag) + + XmlTag = XmlParent + "/" + "Specification" + Specification = XmlElement(XmlCommonHeader, XmlTag) + + AddToSpecificationDict(CommonHeader.Specification, Specification) + + XmlTag = XmlParent + "/" + "ModuleType" + CommonHeader.ModuleType = XmlElement(XmlCommonHeader, XmlTag) + + +## Load a new Cloned Record class object. +# +# Read an input XML ClonedRecord DOM object and return an object of Cloned Record +# contained in the DOM object. +# +# @param XmlCloned A child XML DOM object in a Common XML DOM. +# +# @retvel ClonedRecord A new Cloned Record object created by XmlCloned. +# +def LoadClonedRecord(XmlCloned): + ClonedRecord = ClonedRecordClass() + + XmlTag = "Id" + ClonedRecord.Id = int(XmlAttribute(XmlCloned, XmlTag)) + + XmlTag = "FarGuid" + ClonedRecord.FarGuid = XmlAttribute(XmlCloned, XmlTag) + + XmlTag = "Cloned/PackageGuid" + ClonedRecord.PackageGuid = XmlElement(XmlCloned, XmlTag) + + XmlTag = "Cloned/PackageVersion" + ClonedRecord.PackageVersion = XmlElement(XmlCloned, XmlTag) + + XmlTag = "Cloned/ModuleGuid" + ClonedRecord.ModuleGuid = XmlElement(XmlCloned, XmlTag) + + XmlTag = "Cloned/ModuleVersion" + ClonedRecord.ModuleVersion = XmlElement(XmlCloned, XmlTag) + + return ClonedRecord + + +## Load a new Guid/Protocol/Ppi common class object. +# +# Read an input XML Guid/Protocol/Ppi DOM object and return an object of +# Guid/Protocol/Ppi contained in the DOM object. +# +# @param XmlGuidProtocolPpiCommon A child XML DOM object in a Common XML DOM. +# +# @retvel GuidProtocolPpiCommon A new GuidProtocolPpiCommon class object +# created by XmlGuidProtocolPpiCommon. +# +def LoadGuidProtocolPpiCommon(XmlGuidProtocolPpiCommon): + GuidProtocolPpiCommon = GuidProtocolPpiCommonClass() + + XmlTag = "Name" + GuidProtocolPpiCommon.Name = XmlAttribute(XmlGuidProtocolPpiCommon, XmlTag) + + XmlParent = XmlNodeName(XmlGuidProtocolPpiCommon) + if XmlParent == "Entry": + XmlTag = "%s/C_Name" % XmlParent + elif XmlParent == "GuidCNames": + XmlTag = "%s/GuidCName" % XmlParent + else: + XmlTag = "%s/%sCName" % (XmlParent, XmlParent) + + GuidProtocolPpiCommon.CName = XmlElement(XmlGuidProtocolPpiCommon, XmlTag) + + XmlTag = XmlParent + "/" + "GuidValue" + GuidProtocolPpiCommon.Guid = XmlElement(XmlGuidProtocolPpiCommon, XmlTag) + + if XmlParent.endswith("Notify"): + GuidProtocolPpiCommon.Notify = True + + XmlTag = "GuidTypeList" + GuidTypes = XmlAttribute(XmlGuidProtocolPpiCommon, XmlTag) + GuidProtocolPpiCommon.GuidTypeList = GuidTypes.split() + + XmlTag = "SupModuleList" + SupModules = XmlAttribute(XmlGuidProtocolPpiCommon, XmlTag) + GuidProtocolPpiCommon.SupModuleList = SupModules.split() + + SetCommon(GuidProtocolPpiCommon, XmlGuidProtocolPpiCommon) + + return GuidProtocolPpiCommon + + +## Load a new Pcd class object. +# +# Read an input XML Pcd DOM object and return an object of Pcd +# contained in the DOM object. +# +# @param XmlPcd A child XML DOM object in a Common XML DOM. +# +# @retvel Pcd A new Pcd object created by XmlPcd. +# +def LoadPcd(XmlPcd): + """Return a new PcdClass object equivalent to XmlPcd""" + Pcd = PcdClass() + + XmlTag = "PcdEntry/C_Name" + Pcd.CName = XmlElement(XmlPcd, XmlTag) + + XmlTag = "PcdEntry/Token" + Pcd.Token = XmlElement(XmlPcd, XmlTag) + + XmlTag = "PcdEntry/TokenSpaceGuidCName" + Pcd.TokenSpaceGuidCName = XmlElement(XmlPcd, XmlTag) + + XmlTag = "PcdEntry/DatumType" + Pcd.DatumType = XmlElement(XmlPcd, XmlTag) + + XmlTag = "PcdEntry/MaxDatumSize" + Pcd.MaxDatumSize = XmlElement(XmlPcd, XmlTag) + + XmlTag = "PcdEntry/DefaultValue" + Pcd.DefaultValue = XmlElement(XmlPcd, XmlTag) + + XmlTag = "PcdItemType" + Pcd.ItemType = XmlAttribute(XmlPcd, XmlTag) + + XmlTag = "PcdEntry/ValidUsage" + Pcd.ValidUsage = XmlElement(XmlPcd, XmlTag).split() + + XmlTag = "SupModuleList" + Pcd.SupModuleList = XmlAttribute(XmlPcd, XmlTag).split() + + SetCommon(Pcd, XmlPcd) + + return Pcd + + +## Load a new LibraryClass class object. +# +# Read an input XML LibraryClass DOM object and return an object of LibraryClass +# contained in the DOM object. +# +# @param XmlLibraryClass A child XML DOM object in a Common XML DOM. +# +# @retvel LibraryClass A new LibraryClass object created by XmlLibraryClass. +# +def LoadLibraryClass(XmlLibraryClass): + LibraryClass = LibraryClassClass() + + XmlTag = "LibraryClass/Keyword" + LibraryClass.LibraryClass = XmlElement(XmlLibraryClass, XmlTag) + if LibraryClass.LibraryClass == "": + XmlTag = "Name" + LibraryClass.LibraryClass = XmlAttribute(XmlLibraryClass, XmlTag) + + XmlTag = "LibraryClass/IncludeHeader" + LibraryClass.IncludeHeader = XmlElement(XmlLibraryClass, XmlTag) + + XmlTag = "RecommendedInstanceVersion" + RecommendedInstanceVersion = XmlAttribute(XmlLibraryClass, XmlTag) + LibraryClass.RecommendedInstanceVersion = RecommendedInstanceVersion + + XmlTag = "RecommendedInstanceGuid" + RecommendedInstanceGuid = XmlAttribute(XmlLibraryClass, XmlTag) + LibraryClass.RecommendedInstanceGuid = RecommendedInstanceGuid + + XmlTag = "SupModuleList" + SupModules = XmlAttribute(XmlLibraryClass, XmlTag) + LibraryClass.SupModuleList = SupModules.split() + + SetCommon(LibraryClass, XmlLibraryClass) + + return LibraryClass + + +## Load a new Build Option class object. +# +# Read an input XML BuildOption DOM object and return an object of Build Option +# contained in the DOM object. +# +# @param XmlBuildOption A child XML DOM object in a Common XML DOM. +# +# @retvel BuildOption A new Build Option object created by XmlBuildOption. +# +def LoadBuildOption(XmlBuildOption): + """Return a new BuildOptionClass object equivalent to XmlBuildOption""" + BuildOption = BuildOptionClass() + + BuildOption.Option = XmlElementData(XmlBuildOption) + + XmlTag = "BuildTargets" + BuildOption.BuildTargetList = XmlAttribute(XmlBuildOption, XmlTag).split() + + XmlTag = "ToolChainFamily" + BuildOption.ToolChainFamily = XmlAttribute(XmlBuildOption, XmlTag) + + XmlTag = "TagName" + BuildOption.TagName = XmlAttribute(XmlBuildOption, XmlTag) + + XmlTag = "ToolCode" + BuildOption.ToolCode = XmlAttribute(XmlBuildOption, XmlTag) + + XmlTag = "SupArchList" + BuildOption.SupArchList = XmlAttribute(XmlBuildOption, XmlTag).split() + + return BuildOption + + +## Load a new User Extensions class object. +# +# Read an input XML UserExtensions DOM object and return an object of User +# Extensions contained in the DOM object. +# +# @param XmlUserExtensions A child XML DOM object in a Common XML DOM. +# +# @retvel UserExtensions A new User Extensions object created by +# XmlUserExtensions. +# +def LoadUserExtensions(XmlUserExtensions): + UserExtensions = UserExtensionsClass() + + XmlTag = "UserId" + UserExtensions.UserID = XmlAttribute(XmlUserExtensions, XmlTag) + + XmlTag = "Identifier" + UserExtensions.Identifier = XmlAttribute(XmlUserExtensions, XmlTag) + + UserExtensions.Content = XmlElementData(XmlUserExtensions) + + return UserExtensions + + +## Store content to a text file object. +# +# Write some text file content to a text file object. The contents may echo +# in screen in a verbose way. +# +# @param TextFile The text file object. +# @param Content The string object to be written to a text file. +# +def StoreTextFile(TextFile, Content): + EdkLogger.verbose(Content) + TextFile.write(Content) + + +## Add item to a section. +# +# Add an Item with specific CPU architecture to section dictionary. +# The possible duplication is ensured to be removed. +# +# @param Section Section dictionary indexed by CPU architecture. +# @param Arch CPU architecture: Ia32, X64, Ipf, Ebc or Common. +# @param Item The Item to be added to section dictionary. +# +def AddToSection(Section, Arch, Item): + SectionArch = Section.get(Arch, []) + if Item not in SectionArch: + SectionArch.append(Item) + Section[Arch] = SectionArch + + +## Get section contents. +# +# Return the content of section named SectionName. +# the contents is based on Methods and ObjectLists. +# +# @param SectionName The name of the section. +# @param Method A function returning a string item of an object. +# @param ObjectList The list of object. +# +# @retval Section The string content of a section. +# +def GetSection(SectionName, Method, ObjectList): + SupportedArches = ["common", "Ia32", "X64", "Ipf", "Ebc"] + SectionDict = {} + for Object in ObjectList: + Item = Method(Object) + if Item == "": + continue + Item = " %s" % Item + Arches = Object.SupArchList + if len(Arches) == 0: + AddToSection(SectionDict, "common", Item) + else: + for Arch in SupportedArches: + if Arch.upper() in Arches: + AddToSection(SectionDict, Arch, Item) + + Section = "" + for Arch in SupportedArches: + SectionArch = "\n".join(SectionDict.get(Arch, [])) + if SectionArch != "": + Section += "[%s.%s]\n%s\n" % (SectionName, Arch, SectionArch) + Section += "\n" + if Section != "": + Section += "\n" + return Section + + +## Store file header to a text file. +# +# Write standard file header to a text file. The content includes copyright, +# abstract, description and license extracted from CommonHeader class object. +# +# @param TextFile The text file object. +# @param CommonHeader The source CommonHeader class object. +# +def StoreHeader(TextFile, CommonHeader): + CopyRight = CommonHeader.Copyright + Abstract = CommonHeader.Abstract + Description = CommonHeader.Description + License = CommonHeader.License + + Header = "#/** @file\n#\n" + Header += "# " + Abstract + "\n#\n" + Header += "# " + Description.strip().replace("\n", "\n# ") + "\n" + Header += "# " + CopyRight + "\n#\n" + Header += "# " + License.replace("\n", "\n# ").replace(" ", " ") + Header += "\n#\n#**/\n\n" + + StoreTextFile(TextFile, Header) + +## Store file header to a text file. +# +# Write Defines section to a text file. DefinesTupleList determines the content. +# +# @param TextFile The text file object. +# @param DefinesTupleList The list of (Tag, Value) to be added as one item. +# +def StoreDefinesSection(TextFile, DefinesTupleList): + Section = "[Defines]\n" + for DefineItem in DefinesTupleList: + Section += " %-30s = %s\n" % DefineItem + + Section += "\n\n" + StoreTextFile(TextFile, Section) + + +## Add item to PCD dictionary. +# +# Add an PcdClass object to PCD dictionary. The key is generated from +# PcdItemType. +# +# @param PcdDict PCD dictionary indexed by Pcd Item Type. +# @param Arch CPU architecture: Ia32, X64, Ipf, Ebc or Common. +# @param Item The Item to be added to section dictionary. +# +def AddToPcdsDict(PcdDict, PcdItemType, PcdCode): + PcdSectionName = PcdItemType + PcdSectionName = PcdSectionName.title() + PcdSectionName = PcdSectionName.replace("_", "") + PcdSectionName = "Pcds" + PcdSectionName + PcdDict.setdefault(PcdSectionName, []).append(PcdCode) + +## Regular expression to match an equation. +mReEquation = re.compile(r"\s*(\S+)\s*=\s*(\S*)\s*") + +## Return a value tuple matching information in a text fle. +# +# Parse the text file and return a value tuple corresponding to an input tag +# tuple. In case of any error, an tuple of empty strings is returned. +# +# @param FileName The file name of the text file. +# @param TagTuple A tuple of tags as the key to the value. +# +# @param ValueTupe The returned tuple corresponding to the tag tuple. +# +def GetTextFileInfo(FileName, TagTuple): + ValueTuple = [""] * len(TagTuple) + try: + for Line in open(FileName): + Line = Line.split("#", 1)[0] + MatchEquation = mReEquation.match(Line) + if MatchEquation: + Tag = MatchEquation.group(1).upper() + Value = MatchEquation.group(2) + for Index in range(len(TagTuple)): + if TagTuple[Index] == Tag: + ValueTuple[Index] = Value + except: + EdkLogger.info("IO Error in reading file %s" % FileName) + + return ValueTuple + +## Return a value tuple matching information in an XML fle. +# +# Parse the XML file and return a value tuple corresponding to an input tag +# tuple. In case of any error, an tuple of empty strings is returned. +# +# @param FileName The file name of the XML file. +# @param TagTuple A tuple of tags as the key to the value. +# +# @param ValueTupe The returned tuple corresponding to the tag tuple. +# +def GetXmlFileInfo(FileName, TagTuple): + XmlDom = XmlParseFile(FileName) + return tuple([XmlElement(XmlDom, XmlTag) for XmlTag in TagTuple]) + +# Version and Copyright +__version_number__ = "1.0" +__version__ = "%prog Version " + __version_number__ +__copyright__ = "Copyright (c) 2007, Intel Corporation. All rights reserved." + +## Parse migration command line options +# +# Use standard Python module optparse to parse command line option of this tool. +# +# @param Source The source file type. +# @param Destinate The destinate file type. +# +# @retval Options A optparse object containing the parsed options. +# @retval InputFile Path of an source file to be migrated. +# +def MigrationOptionParser(Source, Destinate): + # use clearer usage to override default usage message + UsageString = "%prog [-a] [-o ] " + + Parser = OptionParser(description=__copyright__, version=__version__, usage=UsageString) + + HelpText = "The name of the %s file to be created." % Destinate + Parser.add_option("-o", "--output", dest="OutputFile", help=HelpText) + + HelpText = "Automatically create the %s file using the name of the %s file and replacing file extension" % (Source, Destinate) + Parser.add_option("-a", "--auto", dest="AutoWrite", action="store_true", default=False, help=HelpText) + + Options, Args = Parser.parse_args() + + # error check + if len(Args) == 0: + raise MigrationError(OPTION_MISSING, name="Input file", usage=Parser.get_usage()) + if len(Args) > 1: + raise MigrationError(OPTION_NOT_SUPPORTED, name="Too many input files", usage=Parser.get_usage()) + + InputFile = Args[0] + if not os.path.exists(InputFile): + raise MigrationError(FILE_NOT_FOUND, name=InputFile) + + if Options.OutputFile: + if Options.AutoWrite: + raise MigrationError(OPTION_CONFLICT, arg1="-o", arg2="-a", usage=Parser.get_usage()) + else: + if Options.AutoWrite: + Options.OutputFile = os.path.splitext(InputFile)[0] + "." + Destinate.lower() + else: + raise MigrationError(OPTION_MISSING, name="-o", usage=Parser.get_usage()) + + return Options, InputFile + +# This acts like the main() function for the script, unless it is 'import'ed +# into another script. +if __name__ == '__main__': + pass diff --git a/BaseTools/Source/Python/fpd2dsc/StoreDsc.py b/BaseTools/Source/Python/fpd2dsc/StoreDsc.py new file mode 100644 index 0000000000..8d07ab9c5b --- /dev/null +++ b/BaseTools/Source/Python/fpd2dsc/StoreDsc.py @@ -0,0 +1,765 @@ +## @file +# Store a Platform class object to an INF file. +# +# Copyright (c) 2007 - 2009, 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. +# + +## +# Import Modules +# +from LoadFpd import LoadFpd +from CommonDataClass.PlatformClass import * +from CommonDataClass.FdfClass import * +from Common.MigrationUtilities import * +from Common.ToolDefClassObject import * +from Common.TargetTxtClassObject import * + +## Store Defines section +# +# Write [Defines] section to the DscFile based on Platform class object. +# Different CPU architectures are specified in the subsection if possible. +# +# @param DscFile The output DSC file to store the Defines section +# @param Platform An input Platform class object +# +def StorePlatformDefinesSection(DscFile, Platform): + PlatformHeader = Platform.Header + + DefinesTupleList = [] + + if PlatformHeader.Name != "": + DefinesTupleList.append(("PLATFORM_NAME", PlatformHeader.Name)) + + if PlatformHeader.Guid != "": + DefinesTupleList.append(("PLATFORM_GUID", PlatformHeader.Guid)) + + if PlatformHeader.Version != "": + DefinesTupleList.append(("PLATFORM_VERSION", PlatformHeader.Version)) + for key in PlatformHeader.Specification.keys(): + SpecificationValue = PlatformHeader.Specification.get(key) + DefinesTupleList.append(("DSC_ SPECIFICATION", SpecificationValue)) + + if PlatformHeader.OutputDirectory != "": + DefinesTupleList.append(("OUTPUT_DIRECTORY", PlatformHeader.OutputDirectory)) + + if PlatformHeader.SupArchList != "": + String = "|".join(PlatformHeader.SupArchList) + DefinesTupleList.append(("SUPPORTED_ARCHITECTURES", String)) + + if PlatformHeader.BuildTargets != "": + String = "|".join(PlatformHeader.BuildTargets) + DefinesTupleList.append(("BUILD_TARGETS", String)) + + if PlatformHeader.SkuIdName != "": + #DefinesTupleList.append(("SKUID_IDENTIFIER", PlatformHeader.SkuIdName)) + String = "|".join(PlatformHeader.SkuIdName) + if String != "": + DefinesTupleList.append(("SKUID_IDENTIFIER", String)) + + String = Platform.FlashDefinitionFile.FilePath + if String != "": + DefinesTupleList.append(("FLASH_DEFINITION", String)) + + List = [] + List.append("################################################################################") + List.append("#") + List.append("# Defines Section - statements that will be processed to create a Makefile.") + List.append("#") + List.append("################################################################################") + Section = "\n".join(List) + Section += "\n" + StoreTextFile(DscFile, Section) + + StoreDefinesSection(DscFile, DefinesTupleList) + +## Store SkuIds section +# +# Write [SkuIds] section to the DscFile based on Platform class object. +# Different CPU architectures are specified in the subsection if possible. +# +# @param DscFile The output DSC file to store the Library Classes section +# @param Platform An input Platform class object +# +def StorePlatformSkuIdsSection(DscFile, Platform): + List = [] + List.append("################################################################################") + List.append("#") + List.append("# SKU Identification section - list of all SKU IDs supported by this Platform.") + List.append("#") + List.append("################################################################################") + Section = "\n".join(List) + Section += "\n" + + Section += "[SkuIds]" + '\n' + + List = Platform.SkuInfos.SkuInfoList + for Item in List: + Section = Section + "%s" % Item[0] + '|' + "%s" % Item[1] + '\n' + Section = Section + '\n' + + StoreTextFile(DscFile, Section) + +## Store Build Options section +# +# Write [BuildOptions] section to the DscFile based on Platform class object. +# Different CPU architectures are specified in the subsection if possible. +# +# @param DscFile The output DSC file to store the Build Options section +# @param Platform An input Platform class object +# +def StorePlatformBuildOptionsSection(DscFile, Platform): + # which is from tools_def.txt + StandardBuildTargets = ["DEBUG", "RELEASE"] + SupportedArches = ["COMMON", "IA32", "X64", "IPF", "EBC", "ARM"] + Target = TargetTxtClassObject() + WorkSpace = os.getenv('WORKSPACE') + Target.LoadTargetTxtFile(WorkSpace + '\\Conf\\target.txt') + ToolDef = ToolDefClassObject() + ToolDef.LoadToolDefFile(WorkSpace + '\\' + Target.TargetTxtDictionary[DataType.TAB_TAT_DEFINES_TOOL_CHAIN_CONF]) + # Now we have got ToolDef object + #ToolDef.ToolsDefTxtDictionary + Dict = ToolDef.ToolsDefTxtDatabase + + Dict1 = ToolDef.ToolsDefTxtDictionary # we care the info in this Dict + # + # We only support *(DEBUG/RELEASE) and *(All Arch: IA32, X64, IPF and EBC) for now + # + SectionWINDDK = '' + SectionVS2003 = '' + SectionVS2005EXP = '' + SectionVS2005STD = '' + SectionVS2005PRO = '' + SectionVS2005TEAMSUITE = '' + SectionUNIXGCC = '' + SectionCYGWINGCC = '' + SectionELFGCC = '' + SectionICC = '' + SectionMYTOOLS = '' + for key in Dict1.keys(): + if key.find("_CC_FLAGS") != -1: + if key.find('WINDDK3790x1830') != -1: + SectionWINDDK = " = " + Dict1.get(key) + "\n" + elif key.find('VS2003') != -1: + SectionVS2003 = " = " + Dict1.get(key)+ "\n" + elif key.find('VS2005EXP') != -1: + SectionVS2005EXP = " = " + Dict1.get(key) + "\n" + elif key.find('VS2005STD') != -1: + SectionVS2005STD = " = " + Dict1.get(key) + "\n" + elif key.find('VS2005PRO') != -1: + SectionVS2005PRO = " = " + Dict1.get(key) + "\n" + elif key.find('VS2005TEAMSUITE') != -1: + SectionVS2005TEAMSUITE = " = " + Dict1.get(key) + "\n" + elif key.find('UNIXGCC') != -1: + SectionUNIXGCC = " = " + Dict1.get(key) + "\n" + elif key.find('CYGWINGCC') != -1: + SectionCYGWINGCC = " = " + Dict1.get(key) + "\n" + elif key.find('ELFGCC') != -1: + SectionELFGCC = " = " + Dict1.get(key) + "\n" + elif key.find('ICC') != -1: + SectionICC = " = " + Dict1.get(key) + "\n" + elif key.find('MYTOOLS') != -1: + SectionMYTOOLS = " = " + Dict1.get(key) + "\n" + else: + print "Error!" + + # + # First need to check which arch + # + Archs = Platform.Header.SupArchList + BuildTargets = Platform.Header.BuildTargets + #if BuildTargets == StandardBuildTargets: + #print "Debug and Release both support" # skip debug/release string search + #else: + #print "need to search debug/release string" + + if len(Archs) == 4: + Arch = "*" + SectionName = "[BuildOptions.Common]\n" + else: + for Arch in Archs: + if Arch == 'IA32': + SectionName = "[BuildOptions.IA32]\n" + elif Arch == 'X64': + SectionName = "[BuildOptions.X64]\n" + elif Arch == 'IPF': + SectionName = "[BuildOptions.IPF]\n" + elif Arch == 'EBC': + SectionName = "[BuildOptions.EBC]\n" + else: + print 'Error!' + Section = "" + if SectionWINDDK != "": + SectionWINDDK = "*_WINDDK3790x1830_" + Arch + "_CC_FLAGS" + SectionWINDDK + Section += SectionWINDDK + if SectionVS2003 != "": + SectionVS2003 = "*_VS2003_" + Arch + "_CC_FLAGS" + SectionVS2003 + Section += SectionVS2003 + if SectionVS2005EXP != "": + SectionVS2005EXP = "*_VS2005EXP_" + Arch + "_CC_FLAGS" + SectionVS2005EXP + Section += SectionVS2005EXP + if SectionVS2005STD != "": + SectionVS2005STD = "*_VS2005STD_" + Arch + "_CC_FLAGS" + SectionVS2005STD + Section += SectionVS2005STD + if SectionVS2005PRO != "": + SectionVS2005PRO = "*_VS2005PRO_" + Arch + "_CC_FLAGS" + SectionVS2005PRO + Section += SectionVS2005PRO + if SectionVS2005TEAMSUITE != "": + SectionVS2005TEAMSUITE = "*_VS2005TEAMSUITE_" + Arch + "_CC_FLAGS" + SectionVS2005TEAMSUITE + Section += SectionVS2005TEAMSUITE + if SectionUNIXGCC != "": + SectionUNIXGCC = "*_UNIXGCC_" + Arch + "_CC_FLAGS" + SectionUNIXGCC + Section += SectionUNIXGCC + if SectionCYGWINGCC != "": + SectionCYGWINGCC = "*_CYGWINGCC_" + Arch + "_CC_FLAGS" + SectionCYGWINGCC + Section += SectionCYGWINGCC + if SectionELFGCC != "": + SectionELFGCC = "*_ELFGCC_" + Arch + "_CC_FLAGS" + SectionELFGCC + Section += SectionELFGCC + if SectionICC != "": + SectionICC = "*_ICC_" + Arch + "_CC_FLAGS" + SectionICC + Section += SectionICC + if SectionMYTOOLS != "": + SectionMYTOOLS = "*_MYTOOLS_" + Arch + "_CC_FLAGS" + SectionMYTOOLS + Section += SectionMYTOOLS + + List = [] + List.append("################################################################################") + List.append("#") + List.append("# Build Options section - list of all Build Options supported by this Platform.") + List.append("#") + List.append("################################################################################") + SectionHeader = "\n".join(List) + SectionHeader += "\n" + + Section = SectionHeader + SectionName + Section + Section += "\n" + StoreTextFile(DscFile, Section) + +## Store Libraries section +# +# Write [Libraries] section to the DscFile based on Platform class object. +# Different CPU architectures are specified in the subsection if possible. +# +# @param DscFile The output DSC file to store the Library Classes section +# @param Platform An input Platform class object +# +def StorePlatformLibrariesSection(DscFile,Platform): + List = [] + List.append("################################################################################") + List.append("#") + List.append("# Libraries section - list of all Libraries needed by this Platform.") + List.append("#") + List.append("################################################################################") + SectionHeader = "\n".join(List) + SectionHeader += "\n" + + Section = SectionHeader + '[Libraries]\n\n' + StoreTextFile(DscFile, Section) + +## Return a Platform Library Class Item +# +# Read the input LibraryClass class object and return one line of Library Class Item. +# +# @param LibraryClass An input LibraryClass class object +# +# @retval LibraryClassItem A Module Library Class Item +# +def GetPlatformLibraryClassItem(LibraryClass): + LibraryClassList = [] + LibraryClassList.append(LibraryClass.Name) + LibraryClassList.append(LibraryClass.FilePath) + + return "|$(WORKSPACE)/".join(LibraryClassList).rstrip("|") + +## Add item to a LibraryClass section +# +# Add an Item with specific Module Type to section dictionary. +# The possible duplication is ensured to be removed. +# +# @param Section Section dictionary indexed by CPU architecture +# @param SupModuleList LibraryClass SupModuleList: BASE, SEC, PEI_CORE, PEIM, etc +# @param Item The Item to be added to section dictionary +# +def AddToLibraryClassSection(Section, SupModuleList, Item): + for ModuleType in SupModuleList: + SectionModule = Section.get(ModuleType, []) + if Item not in SectionModule: + SectionModule.append(Item) + Section[ModuleType] = SectionModule + +## Get Library Classes section contents +# +# Return the content of section named SectionName. +# the contents is based on Methods and ObjectLists. +# +# @param SectionName The name of the section +# @param Method A function returning a string item of an object +# @param ObjectList The list of object +# +# @retval Section The string content of a section +# +def GetLibraryClassesSection(SectionName, Method, ObjectList): + SupportedArches = ["COMMON", "IA32", "X64", "IPF", "EBC"] + ModuleTypes = ["BASE","SEC","PEI_CORE","PEIM","DXE_CORE","DXE_DRIVER","DXE_SMM_DRIVER","DXE_SAL_DRIVER","DXE_RUNTIME_DRIVER","UEFI_DRIVER","UEFI_APPLICATION"] + SectionCommonDict = {} + SectionIA32Dict = {} + SectionX64Dict = {} + SectionIPFDict = {} + SectionEBCDict = {} + #ObjectList = list(set(ObjectList)) # delete the same element in the list + for Object in ObjectList: + if Object == None: + continue + Item = Method(Object) + if Item == "": + continue + Item = " %s" % Item + Arches = Object.SupArchList + if len(Arches) == 4: + ModuleType = Object.ModuleType + # [LibraryClasses.Common.ModuleType] + if ModuleType == "BASE": + SupModuleList = ["BASE"] + AddToLibraryClassSection(SectionCommonDict, SupModuleList, Item) + else: + # + SupModuleList = Object.SupModuleList + #AddToSection(SectionDict, "|".join(SupModuleList), Item) + AddToLibraryClassSection(SectionCommonDict, SupModuleList, Item) + else: + # Arch + for Arch in SupportedArches: + if Arch.upper() in Arches: + if Arch == "IA32": + # [LibraryClasses.IA32.ModuleType] + ModuleType = Object.ModuleType + if ModuleType == "BASE": + SupModuleList = ["BASE"] + AddToLibraryClassSection(SectionIA32Dict, SupModuleList, Item) + else: + SupModuleList = Object.SupModuleList + AddToLibraryClassSection(SectionIA32Dict, SupModuleList, Item) + elif Arch == "X64": + # [LibraryClasses.X64.ModuleType] + ModuleType = Object.ModuleType + if ModuleType == "BASE": + SupModuleList = ["BASE"] + AddToLibraryClassSection(SectionX64Dict, SupModuleList, Item) + else: + SupModuleList = Object.SupModuleList + AddToLibraryClassSection(SectionX64Dict, SupModuleList, Item) + elif Arch == "IPF": + # [LibraryClasses.IPF.ModuleType] + ModuleType = Object.ModuleType + if ModuleType == "BASE": + SupModuleList = ["BASE"] + AddToLibraryClassSection(SectionIPFDict, SupModuleList, Item) + else: + SupModuleList = Object.SupModuleList + AddToLibraryClassSection(SectionIPFDict, SupModuleList, Item) + elif Arch == "EBC": + # [LibraryClasses.EBC.ModuleType] + ModuleType = Object.ModuleType + if ModuleType == "BASE": + SupModuleList = ["BASE"] + AddToLibraryClassSection(SectionEBCDict, SupModuleList, Item) + else: + SupModuleList = Object.SupModuleList + AddToLibraryClassSection(SectionEBCDict, SupModuleList, Item) + + Section = "" + for ModuleType in ModuleTypes: + SectionCommonModule = "\n".join(SectionCommonDict.get(ModuleType, [])) + if SectionCommonModule != "": + Section += "[%s.Common.%s]\n%s\n" % (SectionName, ModuleType, SectionCommonModule) + Section += "\n" + for ModuleType in ModuleTypes: + ListIA32 = SectionIA32Dict.get(ModuleType, []) + if ListIA32 != []: + SectionIA32Module = "\n".join(SectionIA32Dict.get(ModuleType, [])) + if SectionIA32Module != "": + Section += "[%s.IA32.%s]\n%s\n" % (SectionName, ModuleType, SectionIA32Module) + Section += "\n" + ListX64 = SectionX64Dict.get(ModuleType, []) + if ListX64 != []: + SectionX64Module = "\n".join(SectionX64Dict.get(ModuleType, [])) + if SectionX64Module != "": + Section += "[%s.X64.%s]\n%s\n" % (SectionName, ModuleType, SectionX64Module) + Section += "\n" + ListIPF = SectionIPFDict.get(ModuleType, []) + if ListIPF != []: + SectionIPFModule = "\n".join(SectionIPFDict.get(ModuleType, [])) + if SectionIPFModule != "": + Section += "[%s.IPF.%s]\n%s\n" % (SectionName, ModuleType, SectionIPFModule) + Section += "\n" + ListEBC = SectionEBCDict.get(ModuleType, []) + if ListEBC != []: + SectionEBCModule = "\n".join(SectionEBCDict.get(ModuleType, [])) + if SectionEBCModule != "": + Section += "[%s.EBC.%s]\n%s\n" % (SectionName, ModuleType, SectionEBCModule) + Section += "\n" + + if Section != "": + Section += "\n" + return Section + +## Store Library Classes section +# +# Write [LibraryClasses] section to the DscFile based on Platform class object. +# Different CPU architectures are specified in the subsection if possible. +# +# @param DscFile The output DSC file to store the Library Classes section +# @param Platform An input Platform class object +# +def StorePlatformLibraryClassesSection(DscFile, Platform): + Section = GetLibraryClassesSection("LibraryClasses", GetPlatformLibraryClassItem, Platform.LibraryClasses.LibraryList) + List = [] + List.append("################################################################################") + List.append("#") + List.append("# Library Class section - list of all Library Classes needed by this Platform.") + List.append("#") + List.append("################################################################################") + SectionHeader = "\n".join(List) + SectionHeader += "\n" + Section = SectionHeader + Section + StoreTextFile(DscFile, Section) + +## Store Pcd section +# +# Write [Pcd] section to the DscFile based on Platform class object. +# Different CPU architectures are specified in the subsection if possible. +# +# @param DscFile The output DSC file to store the Build Options section +# @param Platform An input Platform class object +# +def StorePlatformPcdSection(DscFile, Platform): + # {PcdsFixedAtBuild:String1, PcdsFixedAtBuild:String2, PcdsPatchableInModule:String3} + SectionDict = {} + # + # [PcdsFixedAtBuild], [PcdsPatchableInModule] and [PcdsFeatureFlag] are from platform.modules + # [PcdsDynamic] is from platform.DynamicPcdBuildDefinitions + # + Modules = Platform.Modules.ModuleList # it's a list of modules + for Module in Modules: + PcdBuildDefinitions = Module.PcdBuildDefinitions # it's a list of PcdData + for PcdData in PcdBuildDefinitions: + if PcdData.ItemType == "FEATURE_FLAG": + List = [] + List.append(PcdData.TokenSpaceGuidCName + "." + PcdData.C_NAME) + List.append(PcdData.Value) + String = "|".join(List) + ItemType = PcdData.ItemType + SectionPcdsFeatureFlag = SectionDict.get(ItemType, []) + if String not in SectionPcdsFeatureFlag: + SectionPcdsFeatureFlag.append(String) + SectionDict[ItemType] = SectionPcdsFeatureFlag + else: + List = [] + List.append(PcdData.TokenSpaceGuidCName + "." + PcdData.C_NAME) + List.append(PcdData.Value) + List.append(PcdData.Token) + List.append(PcdData.DatumType) + List.append(PcdData.MaxDatumSize) + String = "|".join(List) + ItemType = PcdData.ItemType + if PcdData.ItemType == "FIXED_AT_BUILD": + SectionPcdsFixedAtBuild = SectionDict.get(ItemType, []) + if String not in SectionPcdsFixedAtBuild: + SectionPcdsFixedAtBuild.append(String) + SectionDict[ItemType] = SectionPcdsFixedAtBuild + #elif PcdData.ItemType == "FEATURE_FLAG": + #SectionPcdsFeatureFlag = SectionDict.get(ItemType, []) + #if String not in SectionPcdsFeatureFlag: + #SectionPcdsFeatureFlag.append(String) + #SectionDict[ItemType] = SectionPcdsFeatureFlag + elif PcdData.ItemType == "PATCHABLE_IN_MODULE": + SectionPcdsPatchableInModule = SectionDict.get(ItemType, []) + if String not in SectionPcdsPatchableInModule: + SectionPcdsPatchableInModule.append(String) + SectionDict[ItemType] = SectionPcdsPatchableInModule + elif PcdData.ItemType == "DYNAMIC": + SectionPcdsDynamic = SectionDict.get(ItemType, []) + if String not in SectionPcdsDynamic: + SectionPcdsDynamic.append(String) + SectionDict[ItemType] = SectionPcdsDynamic + + DynamicPcdBuildDefinitions = Platform.DynamicPcdBuildDefinitions # It's a list + for PcdBuildData in DynamicPcdBuildDefinitions: + List = [] + List.append(PcdData.TokenSpaceGuidCName + "." + PcdData.C_NAME) + List.append(PcdData.Token) + List.append(PcdData.DatumType) + List.append(PcdData.MaxDatumSize) + String = "|".join(List) + if PcdBuildData.ItemType == "DYNAMIC": + ItemType = PcdBuildData.ItemType + SectionPcdsDynamic = SectionDict.get(ItemType, []) + if String not in SectionPcdsDynamic: + SectionPcdsDynamic.append(String) + SectionDict[ItemType] = SectionPcdsDynamic + ItemType = "FIXED_AT_BUILD" + Section = "[PcdsFixedAtBuild]\n " + "\n ".join(SectionDict.get(ItemType, [])) + ItemType = "FEATURE_FLAG" + Section += "\n\n[PcdsFeatureFlag]\n " + "\n ".join(SectionDict.get(ItemType, [])) + ItemType = "PATCHABLE_IN_MODULE" + Section += "\n\n[PcdsPatchableInModule]\n " + "\n ".join(SectionDict.get(ItemType, [])) + Section += "\n\n" + List = [] + List.append("################################################################################") + List.append("#") + List.append("# Pcd Dynamic Section - list of all EDK II PCD Entries defined by this Platform.") + List.append("#") + List.append("################################################################################") + String = "\n".join(List) + Section += String + ItemType = "DYNAMIC" + Section += "\n\n[PcdsDynamic]\n " + "\n ".join(SectionDict.get(ItemType, [])) + Section += "\n\n" + + List = [] + List.append("################################################################################") + List.append("#") + List.append("# Pcd Section - list of all EDK II PCD Entries defined by this Platform.") + List.append("#") + List.append("################################################################################") + SectionHeader = "\n".join(List) + SectionHeader += "\n" + Section = SectionHeader + Section + StoreTextFile(DscFile, Section) + +## Add item to a section +# +# Add an Item with specific CPU architecture to section dictionary. +# The possible duplication is ensured to be removed. +# +# @param Section Section dictionary indexed by CPU architecture +# @param Arch CPU architecture: Ia32, X64, Ipf, Ebc or Common +# @param Item The Item to be added to section dictionary +# +def AddToSection(Section, Arch, Item): + SectionArch = Section.get(Arch, []) + if Item not in SectionArch: + SectionArch.append(Item) + Section[Arch] = SectionArch + +## Get section contents +# +# Return the content of section named SectionName. +# the contents is based on Methods and ObjectLists. +# +# @param SectionName The name of the section +# @param Method A function returning a string item of an object +# @param ObjectList The list of object +# +# @retval Section The string content of a section +# +def GetSection(SectionName, Method, ObjectList): + SupportedArches = ["COMMON", "IA32", "X64", "IPF", "EBC"] + SectionDict = {} + for Object in ObjectList: + if Object.FilePath == "": + continue + Item = Method(Object) + if Item == "": + continue + Item = " %s" % Item + Arches = Object.SupArchList + if len(Arches) == 4: + AddToSection(SectionDict, "common", Item) + else: + for Arch in SupportedArches: + if Arch.upper() in Arches: + AddToSection(SectionDict, Arch, Item) + + Section = "" + for Arch in SupportedArches: + SectionArch = "\n".join(SectionDict.get(Arch, [])) + if SectionArch != "": + Section += "[%s.%s]\n%s\n" % (SectionName, Arch, SectionArch) + Section += "\n" + if Section != "": + Section += "\n" + return Section + +## Return a Platform Component Item +# +# Read the input Platform Component object and return one line of Platform Component Item. +# +# @param Component An input Platform Component class object +# +# @retval ComponentItem A Platform Component Item +# +def GetPlatformComponentItem(Component): + List = [] + Section = {} + + List.append("$(WORKSPACE)/" + Component.FilePath) + + LibraryClasses = Component.LibraryClasses + if LibraryClasses != []: + List = [] + List.append("$(WORKSPACE)/" + Component.FilePath + " {") + List.append("") + for LibraryClass in LibraryClasses: + if LibraryClass == ["", ""]: + continue + List.append(" " + LibraryClass[0] + "|$(WORKSPACE)/" + LibraryClass[1]) + + PcdBuildDefinitions = Component.PcdBuildDefinitions + for PcdData in PcdBuildDefinitions: + if PcdData.ItemType == "FEATURE_FLAG": + List1 = [] + List1.append(PcdData.TokenSpaceGuidCName + "." + PcdData.C_NAME) + List1.append(PcdData.Value) + String = "|".join(List1) + ItemType = PcdData.ItemType + SectionPcd = Section.get(ItemType, []) + if String not in SectionPcd: + SectionPcd.append(String) + Section[ItemType] = SectionPcd + else: + List1 = [] + List1.append(PcdData.TokenSpaceGuidCName + "." + PcdData.C_NAME) + List1.append(PcdData.Value) + List1.append(PcdData.Token) + List1.append(PcdData.DatumType) + List1.append(PcdData.MaxDatumSize) + String = "|".join(List1) + ItemType = PcdData.ItemType + if ItemType == "FIXED_AT_BUILD": + SectionPcd = Section.get(ItemType, []) + if String not in SectionPcd: + SectionPcd.append(String) + Section[ItemType] = SectionPcd + #elif ItemType == "FEATURE_FLAG": + #SectionPcd = Section.get(ItemType, []) + #if String not in SectionPcd: + #SectionPcd.append(String) + #Section[ItemType] = SectionPcd + elif ItemType == "PATCHABLE_IN_MODULE": + SectionPcd = Section.get(ItemType, []) + if String not in SectionPcd: + SectionPcd.append(String) + Section[ItemType] = SectionPcd + elif ItemType == "DYNAMIC": + SectionPcd = Section.get(ItemType, []) + if String not in SectionPcd: + SectionPcd.append(String) + Section[ItemType] = SectionPcd + + ItemType = "FIXED_AT_BUILD" + if Section.get(ItemType, []) != []: + List.append("") + List.append(" " + "\n ".join(Section.get(ItemType,[]))) + ItemType = "FEATURE_FLAG" + if Section.get(ItemType, []) != []: + List.append("") + List.append(" " + "\n ".join(Section.get(ItemType,[]))) + ItemType = "PATCHABLE_IN_MODULE" + if Section.get(ItemType, []) != []: + List.append("") + List.append(" " + "\n ".join(Section.get(ItemType,[]))) + ItemType = "DYNAMIC" + if Section.get(ItemType, []) != []: + List.append("") + List.append(" " + "\n ".join(Section.get(ItemType,[]))) + + ListOption = [] + SectionOption = "" + ListBuildOptions = Component.BuildOptions # a list + if ListBuildOptions != []: + SectionOption += "\n \n" + for BuildOptions in ListBuildOptions: + Options = BuildOptions.Options + for Option in Options: + for Item in Option.BuildTargetList: + ListOption.append(Item) + List.append(Option.ToolChainFamily) + for Item in Option.SupArchList: + ListOption.append(Item) + ListOption.append(Option.ToolCode) + ListOption.append("FLAGS") + #print ListOption + SectionOption += " " + "_".join(List) + " = " + Option.Option + "\n" + ListOption = [] + if SectionOption != "": + List.append(SectionOption) + if List != ["$(WORKSPACE)/" + Component.FilePath]: + List.append("}\n") + + return "\n ".join(List) + +## Store Components section. +# +# Write [Components] section to the DscFile based on Platform class object. +# Different CPU architectures are specified in the subsection if possible. +# +# @param DscFile The output DSC file to store the Components section +# @param Platform An input Platform class object +# +def StorePlatformComponentsSection(DscFile, Platform): + Section = GetSection("Components", GetPlatformComponentItem, Platform.Modules.ModuleList) + List = [] + List.append("################################################################################") + List.append("#") + List.append("# Components Section - list of all EDK II Modules needed by this Platform.") + List.append("#") + List.append("################################################################################") + SectionHeader = "\n".join(List) + SectionHeader += "\n" + Section = SectionHeader + Section + StoreTextFile(DscFile, Section) + +## Store User Extensions section. +# +# Write [UserExtensions] section to the InfFile based on Module class object. +# Different CPU architectures are specified in the subsection if possible. +# +# @param DscFile The output DSC file to store the User Extensions section +# @param Platform An input Platform class object +# +def StorePlatformUserExtensionsSection(DscFile, Platform): + Section = "".join(map(GetUserExtensions, Platform.UserExtensions)) + List = [] + List.append("################################################################################") + List.append("#") + List.append("# User Extensions Section - list of all User Extensions specified by user.") + List.append("#") + List.append("################################################################################") + SectionHeader = "\n".join(List) + SectionHeader += "\n" + Section = SectionHeader + Section + StoreTextFile(DscFile, Section) + +## Store a Platform class object to a new DSC file. +# +# Read an input Platform class object and save the contents to a new DSC file. +# +# @param DSCFileName The output DSC file +# @param Platform An input Platform class object +# +def StoreDsc(DscFileName, Platform): + DscFile = open(DscFileName, "w+") + EdkLogger.info("Save file to %s" % DscFileName) + + StoreHeader(DscFile, Platform.Header) + StorePlatformDefinesSection(DscFile, Platform) + StorePlatformBuildOptionsSection(DscFile,Platform) + StorePlatformSkuIdsSection(DscFile,Platform) + StorePlatformLibrariesSection(DscFile,Platform) # new in dsc, Edk I components, list of INF files + StorePlatformLibraryClassesSection(DscFile, Platform) # LibraryClasses are from Modules + StorePlatformPcdSection(DscFile, Platform) + #StorePlatformPcdDynamicSection(DscFile, Platform) + StorePlatformComponentsSection(DscFile,Platform) + StorePlatformUserExtensionsSection(DscFile,Platform) + DscFile.close() + +if __name__ == '__main__': + pass diff --git a/BaseTools/Source/Python/fpd2dsc/__init__.py b/BaseTools/Source/Python/fpd2dsc/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/BaseTools/Source/Python/fpd2dsc/fpd2dsc.py b/BaseTools/Source/Python/fpd2dsc/fpd2dsc.py new file mode 100644 index 0000000000..a22ff5a685 --- /dev/null +++ b/BaseTools/Source/Python/fpd2dsc/fpd2dsc.py @@ -0,0 +1,116 @@ +## @file +# Convert an XML-based FPD file to a text-based DSC file. +# +# Copyright (c) 2007, 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. +# + +## +# Import Modules +# +import os, re, sys, xml.dom.minidom #XmlRoutines, EdkIIWorkspace +from LoadFpd import LoadFpd +from StoreDsc import StoreDsc +from optparse import OptionParser + +# Version and Copyright +__version_number__ = "1.0" +__version__ = "%prog Version " + __version_number__ +__copyright__ = "Copyright (c) 2007, Intel Corporation All rights reserved." + +## Parse command line options +# +# Using standard Python module optparse to parse command line option of this tool. +# +# @retval Options A optparse.Values object containing the parsed options +# @retval Args All the arguments got from the command line +# +def MyOptionParser(): + """ Argument Parser """ + usage = "%prog [options] input_filename" + parser = OptionParser(usage=usage,description=__copyright__,version="%prog " + str(__version_number__)) + parser.add_option("-o", "--output", dest="outfile", help="Specific Name of the DSC file to create, otherwise it is the FPD filename with the extension repalced.") + parser.add_option("-a", "--auto", action="store_true", dest="autowrite", default=False, help="Automatically create output files and write the DSC file") + parser.add_option("-q", "--quiet", action="store_const", const=0, dest="verbose", help="Do not print any messages, just return either 0 for succes or 1 for failure") + parser.add_option("-v", "--verbose", action="count", dest="verbose", help="Do not print any messages, just return either 0 for succes or 1 for failure") + parser.add_option("-d", "--debug", action="store_true", dest="debug", default=False, help="Enable printing of debug messages.") + parser.add_option("-w", "--workspace", dest="workspace", default=str(os.environ.get('WORKSPACE')), help="Specify workspace directory.") + (options, args) = parser.parse_args(sys.argv[1:]) + + return options,args + +## Entrance method +# +# This method mainly dispatch specific methods per the command line options. +# If no error found, return zero value so the caller of this tool can know +# if it's executed successfully or not. +# +# @retval 0 Tool was successful +# @retval 1 Tool failed +# +def Main(): + global Options + global Args + global WorkSpace + Options,Args = MyOptionParser() + + WorkSpace = "" + #print Options.workspace + if (Options.workspace == None): + print "ERROR: E0000: WORKSPACE not defined.\n Please set the WORKSPACE environment variable to the location of the EDK II install directory." + sys.exit(1) + else: + WorkSpace = Options.workspace + if (Options.debug): + print "Using Workspace:", WorkSpace + try: + Options.verbose +=1 + except: + Options.verbose = 1 + pass + + InputFile = "" + if Args == []: + print "usage:" "%prog [options] input_filename" + else: + InputFile = Args[0] + #print InputFile + if InputFile != "": + FileName = InputFile + if ((Options.verbose > 1) | (Options.autowrite)): + print "FileName:",InputFile + else: + print "ERROR: E0001 - You must specify an input filename" + sys.exit(1) + + if (Options.outfile): + OutputFile = Options.outfile + else: + OutputFile = FileName.replace('.fpd', '.dsc') + + if ((Options.verbose > 2) or (Options.debug)): + print "Output Filename:", OutputFile + + try: + Platform = LoadFpd(FileName) + StoreDsc(OutputFile, Platform) + return 0 + except Exception, e: + print e + return 1 + +if __name__ == '__main__': + sys.exit(Main()) + #pass + #global Options + #global Args + #Options,Args = MyOptionParser() + + #Main() + #sys.exit(0) \ No newline at end of file diff --git a/BaseTools/Source/Python/msa2inf/ConvertModule.py b/BaseTools/Source/Python/msa2inf/ConvertModule.py new file mode 100644 index 0000000000..e0d7b88695 --- /dev/null +++ b/BaseTools/Source/Python/msa2inf/ConvertModule.py @@ -0,0 +1,112 @@ +## @file +# Convert an MSA Module class object ot an INF Module class object by filling +# several info required by INF file. +# +# Copyright (c) 2007, 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. +# + +## +# Import Modules +# +from LoadMsa import LoadMsa +from StoreInf import StoreInf +from Common.MigrationUtilities import * +from EdkIIWorkspaceGuidsInfo import gEdkIIWorkspaceGuidsInfo + +#The default INF version number tool generates. +gInfVersion = "0x00010005" + +## Add required version information. +# +# Add the default INF version, EFI specificiation version and EDK release +# version to Module class object. +# +# @param Module An input Module class object. +# +def AddModuleMiscVersion(Module): + Version = gInfVersion + Module.Header.InfVersion = Version + + Version = Module.Header.Specification.get("EFI_SPECIFICATION_VERSION", "") + Module.Header.EfiSpecificationVersion = Version + + Version = Module.Header.Specification.get("EDK_RELEASE_VERSION", "") + Module.Header.EdkReleaseVersion = Version + + +## Add Module produced library class. +# +# Add the produced library class from library class list whose usage type is +# always produced. +# +# @param Module An input Module class object. +# +def AddModuleProducedLibraryClass(Module): + for LibraryClass in Module.LibraryClasses: + if "ALWAYS_PRODUCED" in LibraryClass.Usage: + Module.Header.LibraryClass.append(LibraryClass) + + +## Add Module Package Dependency path. +# +# Translate Package Dependency Guid to a file path relative to workspace. +# +# @param Module An input Module class object. +# +def AddModulePackageDependencyPath(Module): + for PackageDependency in Module.PackageDependencies: + PackageGuid = PackageDependency.PackageGuid + PackageVersion = PackageDependency.PackageVersion + + GuidToFilePath = gEdkIIWorkspaceGuidsInfo.ResolvePackageFilePath + PackageFilePath = GuidToFilePath(PackageGuid, PackageVersion) + PackageDependency.FilePath = PackageFilePath + + +## Add Module Recommended Library Instance path. +# +# Translate Module Recommened Library Instance Guid to a file path relative to +# workspace. +# +# @param Module An input Module class object. +# +def AddModuleRecommonedLibraryInstancePath(Module): + for LibraryClass in Module.LibraryClasses: + if "ALWAYS_PRODUCED" in LibraryClass.Usage: + continue + + if LibraryClass.RecommendedInstanceGuid == "": + continue + + LibraryGuid = LibraryClass.RecommendedInstanceGuid + LibraryVersion = LibraryClass.RecommendedIntanceVersion + + GuidToFilePath = gEdkIIWorkspaceGuidsInfo.ResolveModuleFilePath + LibraryInstance = GuidToFilePath(LibraryGuid, LibraryVersion) + LibraryClass.RecommendedIntance = LibraryInstance + + +## Convert MSA Module class object to INF Module class object. +# +# Convert MSA module class ojbect to INF Module class object by filling in +# several information required by INF file. +# +# @param Module An input Module class object. +# +def ConvertMsaModuleToInfModule(Module): + AddModuleMiscVersion(Module) + AddModuleProducedLibraryClass(Module) + AddModulePackageDependencyPath(Module) + AddModuleRecommonedLibraryInstancePath(Module) + + +if __name__ == '__main__': + pass + \ No newline at end of file diff --git a/BaseTools/Source/Python/msa2inf/EdkIIWorkspaceGuidsInfo.py b/BaseTools/Source/Python/msa2inf/EdkIIWorkspaceGuidsInfo.py new file mode 100644 index 0000000000..f1c8d60d75 --- /dev/null +++ b/BaseTools/Source/Python/msa2inf/EdkIIWorkspaceGuidsInfo.py @@ -0,0 +1,325 @@ +## @file +# Collects the Guid Information in current workspace. +# +# Copyright (c) 2007, 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. +# + +## +# Import Modules +# +import os +import fnmatch +from Common.EdkIIWorkspace import EdkIIWorkspace +from Common.MigrationUtilities import * + +## A class for EdkII work space to resolve Guids. +# +# This class inherits from EdkIIWorkspace and collects the Guids information +# in current workspace. The Guids information is important to translate the +# package Guids and recommended library instances Guids to relative file path +# (to workspace directory) in MSA files. +# +class EdkIIWorkspaceGuidsInfo(EdkIIWorkspace): + + ## The classconstructor. + # + # The constructor initialize workspace directory. It does not collect + # pakage and module Guids info at initialization; instead, it collects them + # on the fly. + # + # @param self The object pointer. + # + def __init__(self): + # Initialize parent class. + EdkIIWorkspace.__init__(self) + # The internal map from Guid to FilePath. + self.__GuidToFilePath = {} + # The internal package directory list. + self.__PackageDirList = [] + # The internal flag to indicate whether package Guids info has been + # to avoid re-collection collected. + self.__PackageGuidInitialized = False + # The internal flag to indicate whether module Guids info has been + # to avoid re-collection collected. + self.__ModuleGuidInitialized = False + + ## Add Guid, Version and FilePath to Guids database. + # + # Add Guid, Version and FilePath to Guids database. It constructs a map + # table from Guid, Version to FilePath internally. If also detects possible + # Guid collision. For now, the version information is simply ignored and + # Guid value itself acts as master key. + # + # @param self The object pointer. + # @param Guid The Guid Value. + # @param Version The version information + # + # @retval True The Guid value is successfully added to map table. + # @retval False The Guid is an empty string or the map table + # already contains a same Guid. + # + def __AddGuidToFilePath(self, Guid, Version, FilePath): + if Guid == "": + EdkLogger.info("Cannot find Guid in file %s" % FilePath) + return False + #Add the Guid value to map table to ensure case insensitive comparison. + OldFilePath = self.__GuidToFilePath.setdefault(Guid.lower(), FilePath) + if OldFilePath == FilePath: + EdkLogger.verbose("File %s has new Guid '%s'" % (FilePath, Guid)) + return True + else: + EdkLogger.info("File %s has duplicate Guid with & %s" % (FilePath, OldFilePath)) + return False + + + ## Gets file information from a module description file. + # + # Extracts Module Name, File Guid and Version number from INF, MSA and NMSA + # file. It supports to exact such information from text based INF file or + # XML based (N)MSA file. + # + # @param self The object pointer. + # @param FileName The input module file name. + # + # @retval True This module file represents a new module discovered + # in current workspace. + # @retval False This module file is not regarded as a valid module. + # The File Guid cannot be extracted or the another + # file with the same Guid already exists + # + def __GetModuleFileInfo(self, FileName): + if fnmatch.fnmatch(FileName, "*.inf"): + TagTuple = ("BASE_NAME", "FILE_GUID", "VERSION_STRING") + (Name, Guid, Version) = GetTextFileInfo(FileName, TagTuple) + else : + XmlTag1 = "ModuleSurfaceArea/MsaHeader/ModuleName" + XmlTag2 = "ModuleSurfaceArea/MsaHeader/GuidValue" + XmlTag3 = "ModuleSurfaceArea/MsaHeader/Version" + TagTuple = (XmlTag1, XmlTag2, XmlTag3) + (Name, Guid, Version) = GetXmlFileInfo(FileName, TagTuple) + + return self.__AddGuidToFilePath(Guid, Version, FileName) + + + ## Gets file information from a package description file. + # + # Extracts Package Name, File Guid and Version number from INF, SPD and NSPD + # file. It supports to exact such information from text based DEC file or + # XML based (N)SPD file. EDK Compatibility Package is hardcoded to be + # ignored since no EDKII INF file depends on that package. + # + # @param self The object pointer. + # @param FileName The input package file name. + # + # @retval True This package file represents a new package + # discovered in current workspace. + # @retval False This package is not regarded as a valid package. + # The File Guid cannot be extracted or the another + # file with the same Guid already exists + # + def __GetPackageFileInfo(self, FileName): + if fnmatch.fnmatch(FileName, "*.dec"): + TagTuple = ("PACKAGE_NAME", "PACKAGE_GUID", "PACKAGE_VERSION") + (Name, Guid, Version) = GetTextFileInfo(FileName, TagTuple) + else: + XmlTag1 = "PackageSurfaceArea/SpdHeader/PackageName" + XmlTag2 = "PackageSurfaceArea/SpdHeader/GuidValue" + XmlTag3 = "PackageSurfaceArea/SpdHeader/Version" + TagTuple = (XmlTag1, XmlTag2, XmlTag3) + (Name, Guid, Version) = GetXmlFileInfo(FileName, TagTuple) + + if Name == "EdkCompatibilityPkg": + # Do not scan EDK compatibitilty package to avoid Guid collision + # with those in EDK Glue Library. + EdkLogger.verbose("Bypass EDK Compatibility Pkg") + return False + + return self.__AddGuidToFilePath(Guid, Version, FileName) + + ## Iterate on all package files listed in framework database file. + # + # Yields all package description files listed in framework database files. + # The framework database file describes the packages current workspace + # includes. + # + # @param self The object pointer. + # + def __FrameworkDatabasePackageFiles(self): + XmlFrameworkDb = XmlParseFile(self.WorkspaceFile) + XmlTag = "FrameworkDatabase/PackageList/Filename" + for PackageFile in XmlElementList(XmlFrameworkDb, XmlTag): + yield os.path.join(self.WorkspaceDir, PackageFile) + + + ## Iterate on all package files in current workspace directory. + # + # Yields all package description files listed in current workspace + # directory. This happens when no framework database file exists. + # + # @param self The object pointer. + # + def __TraverseAllPackageFiles(self): + for Path, Dirs, Files in os.walk(self.WorkspaceDir): + # Ignore svn version control directory. + if ".svn" in Dirs: + Dirs.remove(".svn") + if "Build" in Dirs: + Dirs.remove("Build") + # Assume priority from high to low: DEC, NSPD, SPD. + PackageFiles = fnmatch.filter(Files, "*.dec") + if len(PackageFiles) == 0: + PackageFiles = fnmatch.filter(Files, "*.nspd") + if len(PackageFiles) == 0: + PackageFiles = fnmatch.filter(Files, "*.spd") + + for File in PackageFiles: + # Assume no more package decription file in sub-directory. + del Dirs[:] + yield os.path.join(Path, File) + + ## Iterate on all module files in current package directory. + # + # Yields all module description files listed in current package + # directory. + # + # @param self The object pointer. + # + def __TraverseAllModuleFiles(self): + for PackageDir in self.__PackageDirList: + for Path, Dirs, Files in os.walk(PackageDir): + # Ignore svn version control directory. + if ".svn" in Dirs: + Dirs.remove(".svn") + # Assume priority from high to low: INF, NMSA, MSA. + ModuleFiles = fnmatch.filter(Files, "*.inf") + if len(ModuleFiles) == 0: + ModuleFiles = fnmatch.filter(Files, "*.nmsa") + if len(ModuleFiles) == 0: + ModuleFiles = fnmatch.filter(Files, "*.msa") + + for File in ModuleFiles: + yield os.path.join(Path, File) + + ## Initialize package Guids info mapping table. + # + # Collects all package guids map to package decription file path. This + # function is invokes on demand to avoid unnecessary directory scan. + # + # @param self The object pointer. + # + def __InitializePackageGuidInfo(self): + if self.__PackageGuidInitialized: + return + + EdkLogger.verbose("Start to collect Package Guids Info.") + + WorkspaceFile = os.path.join("Conf", "FrameworkDatabase.db") + self.WorkspaceFile = os.path.join(self.WorkspaceDir, WorkspaceFile) + + # Try to find the frameworkdatabase file to discover package lists + if os.path.exists(self.WorkspaceFile): + TraversePackage = self.__FrameworkDatabasePackageFiles + EdkLogger.verbose("Package list bases on: %s" % self.WorkspaceFile) + else: + TraversePackage = self.__TraverseAllPackageFiles + EdkLogger.verbose("Package list in: %s" % self.WorkspaceDir) + + for FileName in TraversePackage(): + if self.__GetPackageFileInfo(FileName): + PackageDir = os.path.dirname(FileName) + EdkLogger.verbose("Find new package directory %s" % PackageDir) + self.__PackageDirList.append(PackageDir) + + self.__PackageGuidInitialized = True + + ## Initialize module Guids info mapping table. + # + # Collects all module guids map to module decription file path. This + # function is invokes on demand to avoid unnecessary directory scan. + # + # @param self The object pointer. + # + def __InitializeModuleGuidInfo(self): + if self.__ModuleGuidInitialized: + return + EdkLogger.verbose("Start to collect Module Guids Info") + + self.__InitializePackageGuidInfo() + for FileName in self.__TraverseAllModuleFiles(): + if self.__GetModuleFileInfo(FileName): + EdkLogger.verbose("Find new module %s" % FileName) + + self.__ModuleGuidInitialized = True + + ## Get Package file path by Package guid and Version. + # + # Translates the Package Guid and Version to a file path relative + # to workspace directory. If no package in current workspace match the + # input Guid, an empty file path is returned. For now, the version + # value is simply ignored. + # + # @param self The object pointer. + # @param Guid The Package Guid value to look for. + # @param Version The Package Version value to look for. + # + def ResolvePackageFilePath(self, Guid, Version = ""): + self.__InitializePackageGuidInfo() + + EdkLogger.verbose("Resolve Package Guid '%s'" % Guid) + FileName = self.__GuidToFilePath.get(Guid.lower(), "") + if FileName == "": + EdkLogger.info("Cannot resolve Package Guid '%s'" % Guid) + else: + FileName = self.WorkspaceRelativePath(FileName) + FileName = os.path.splitext(FileName)[0] + ".dec" + FileName = FileName.replace("\\", "/") + return FileName + + ## Get Module file path by Package guid and Version. + # + # Translates the Module Guid and Version to a file path relative + # to workspace directory. If no module in current workspace match the + # input Guid, an empty file path is returned. For now, the version + # value is simply ignored. + # + # @param self The object pointer. + # @param Guid The Module Guid value to look for. + # @param Version The Module Version value to look for. + # + def ResolveModuleFilePath(self, Guid, Version = ""): + self.__InitializeModuleGuidInfo() + + EdkLogger.verbose("Resolve Module Guid '%s'" % Guid) + FileName = self.__GuidToFilePath.get(Guid.lower(), "") + if FileName == "": + EdkLogger.info("Cannot resolve Module Guid '%s'" % Guid) + else: + FileName = self.WorkspaceRelativePath(FileName) + FileName = os.path.splitext(FileName)[0] + ".inf" + FileName = FileName.replace("\\", "/") + return FileName + +# A global class object of EdkIIWorkspaceGuidsInfo for external reference. +gEdkIIWorkspaceGuidsInfo = EdkIIWorkspaceGuidsInfo() + +# This acts like the main() function for the script, unless it is 'import'ed +# into another script. +if __name__ == '__main__': + # Test the translation of package Guid. + MdePkgGuid = "1E73767F-8F52-4603-AEB4-F29B510B6766" + OldMdePkgGuid = "5e0e9358-46b6-4ae2-8218-4ab8b9bbdcec" + print gEdkIIWorkspaceGuidsInfo.ResolveModuleFilePath(MdePkgGuid) + print gEdkIIWorkspaceGuidsInfo.ResolveModuleFilePath(OldMdePkgGuid) + + # Test the translation of module Guid. + UefiLibGuid = "3a004ba5-efe0-4a61-9f1a-267a46ae5ba9" + UefiDriverModelLibGuid = "52af22ae-9901-4484-8cdc-622dd5838b09" + print gEdkIIWorkspaceGuidsInfo.ResolveModuleFilePath(UefiLibGuid) + print gEdkIIWorkspaceGuidsInfo.ResolveModuleFilePath(UefiDriverModelLibGuid) diff --git a/BaseTools/Source/Python/msa2inf/LoadMsa.py b/BaseTools/Source/Python/msa2inf/LoadMsa.py new file mode 100644 index 0000000000..4995f2cd0c --- /dev/null +++ b/BaseTools/Source/Python/msa2inf/LoadMsa.py @@ -0,0 +1,747 @@ +## @file +# Open an MSA file and load all its contents to a ModuleClass object. +# +# Copyright (c) 2007, 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. +# + +## +# Import Modules +# +import os +from CommonDataClass.ModuleClass import * +from Common.XmlRoutines import * +from Common.MigrationUtilities import * + + +## Load a list of Module Cloned Records. +# +# Read an input Module XML DOM object and return a list of Cloned Records +# contained in the DOM object. +# +# @param XmlMsa An XML DOM object read from MSA file. +# +# @retvel ClonedRecords A list of Cloned Records loaded from XmlMsa. +# +def LoadModuleClonedRecords(XmlMsa): + XmlTag = "ModuleSurfaceArea/ModuleDefinitions/ClonedFrom/Cloned" + return map(LoadClonedRecord, XmlList(XmlMsa, XmlTag)) + +## Load Module Header. +# +# Read an input Module XML DOM object and return Module Header class object +# contained in the DOM object. +# +# @param XmlMsa An XML DOM object read from MSA file. +# @param MsaFileName The file path of MSA File. +# +# @retvel ModuleHeader A new Module Header object loaded from XmlMsa. +# +def LoadModuleHeader(XmlMsa, MsaFileName): + ModuleHeader = ModuleHeaderClass() + + XmlTag = "ModuleSurfaceArea/MsaHeader" + MsaHeader = XmlNode(XmlMsa, XmlTag) + + SetIdentification(ModuleHeader, MsaHeader, "ModuleName", MsaFileName) + SetCommonHeader(ModuleHeader, MsaHeader) + + XmlTag = "ModuleSurfaceArea/ModuleDefinitions/SupportedArchitectures" + ModuleHeader.SupArchList = XmlElement(XmlMsa, XmlTag).split() + + XmlTag = "ModuleSurfaceArea/ModuleDefinitions/BinaryModule" + if XmlElement(XmlMsa, XmlTag).lower() == "true": + ModuleHeader.BinaryModule = True + + XmlTag = "ModuleSurfaceArea/ModuleDefinitions/OutputFileBasename" + ModuleHeader.OutputFileBasename = XmlElement(XmlMsa, XmlTag) + + XmlTag = "ModuleSurfaceArea/ModuleDefinitions/ClonedForm" + ModuleHeader.ClonedFrom = LoadModuleClonedRecords(XmlMsa) + + XmlTag = "ModuleSurfaceArea/Externs/PcdDriverTypes" + ModuleHeader.PcdIsDriver = XmlElement(XmlMsa, XmlTag) + + XmlTag = "ModuleSurfaceArea/Externs/TianoR8FlashMap_h" + if XmlElement(XmlMsa, XmlTag).lower() == "true": + ModuleHeader.TianoR8FlashMap_h = True + + XmlTag = "ModuleSurfaceArea/Externs/Specification" + for Specification in XmlElementList(XmlMsa, XmlTag): + AddToSpecificationDict(ModuleHeader.Specification, Specification) + + return ModuleHeader + + +## Load a list of Module Library Classes. +# +# Read an input Module XML DOM object and return a list of Library Classes +# contained in the DOM object. +# +# @param XmlMsa An XML DOM object read from MSA file. +# +# @retvel LibraryClasses A list of Library Classes loaded from XmlMsa. +# +def LoadModuleLibraryClasses(XmlMsa): + XmlTag = "ModuleSurfaceArea/LibraryClassDefinitions/LibraryClass" + return map(LoadLibraryClass, XmlList(XmlMsa, XmlTag)) + + +## Load a new Module Source class object. +# +# Read an input XML Source DOM object and return an object of Source +# contained in the DOM object. +# +# @param XmlFilename A child XML DOM object in Module XML DOM. +# +# @retvel ModuleSource A new Source object created by XmlFilename. +# +def LoadModuleSource(XmlFilename): + ModuleSource = ModuleSourceFileClass() + + ModuleSource.SourceFile = XmlElementData(XmlFilename) + + XmlTag = "TagName" + ModuleSource.TagName = XmlAttribute(XmlFilename, XmlTag) + + XmlTag = "ToolCode" + ModuleSource.ToolCode = XmlAttribute(XmlFilename, XmlTag) + + XmlTag = "ToolChainFamily" + ModuleSource.ToolChainFamily = XmlAttribute(XmlFilename, XmlTag) + + SetCommon(ModuleSource, XmlFilename) + + return ModuleSource + + +## Load a list of Module Sources. +# +# Read an input Module XML DOM object and return a list of Sources +# contained in the DOM object. +# +# @param XmlMsa An XML DOM object read from MSA file. +# +# @retvel Sources A list of Sources loaded from XmlMsa. +# +def LoadModuleSources(XmlMsa): + XmlTag = "ModuleSurfaceArea/SourceFiles/Filename" + return map(LoadModuleSource, XmlList(XmlMsa, XmlTag)) + + +## Load a new Module Binary class object. +# +# Read an input XML Binary DOM object and return an object of Binary +# contained in the DOM object. +# +# @param XmlFilename A child XML DOM object in Module XML DOM. +# +# @retvel ModuleBinary A new Binary object created by XmlFilename. +# +def LoadModuleBinary(XmlFilename): + ModuleBinary = ModuleBinaryFileClass() + + ModuleBinary.BinaryFile = XmlElementData(XmlFilename) + + XmlTag = "FileType" + ModuleBinary.FileType = XmlElementAttribute(XmlFilename, XmlTag) + + SetCommon(ModuleBinary, XmlFilename) + + +## Load a list of Module Binaries. +# +# Read an input Module XML DOM object and return a list of Binaries +# contained in the DOM object. +# +# @param XmlMsa An XML DOM object read from MSA file. +# +# @retvel Binaries A list of Binaries loaded from XmlMsa. +# +def LoadModuleBinaries(XmlMsa): + XmlTag = "ModuleSurfaceArea/BinaryFiles/Filename" + return map(LoadModuleBinary, XmlList(XmlMsa, XmlTag)) + + +## Load a list of Module Non Processed Files. +# +# Read an input Module XML DOM object and return a list of Non Processed Files +# contained in the DOM object. +# +# @param XmlMsa An XML DOM object read from MSA file. +# +# @retvel NonProcessedFiles A list of Non Processed Files loaded from XmlMsa. +# +def LoadModuleNonProcessedFiles(XmlMsa): + XmlTag = "ModuleSurfaceArea/NonProcessedFiles/Filename" + return XmlElementList(XmlMsa, XmlTag) + + +## Load a new Module Package Dependency class object. +# +# Read an input XML PackageDependency DOM object and return an object of Package Dependency +# contained in the DOM object. +# +# @param XmlPackage A child XML DOM object in Module XML DOM. +# +# @retvel ModulePackageDependency A new Package Dependency object created by XmlPackage. +# +def LoadModulePackageDependency(XmlPackage): + ModulePackageDependency = ModulePackageDependencyClass() + + XmlTag = "PackageGuid" + PackageKey = XmlAttribute(XmlPackage, XmlTag) + + # + #TODO: Add resolution for Package name, package Version + # + ModulePackageDependency.PackageGuid = PackageKey + SetCommon(ModulePackageDependency, XmlPackage) + + return ModulePackageDependency + + +## Load a list of Module Package Dependencies. +# +# Read an input Module XML DOM object and return a list of Package Dependencies +# contained in the DOM object. +# +# @param XmlMsa An XML DOM object read from MSA file. +# +# @retvel PackageDependencies A list of Package Dependencies loaded from XmlMsa. +# +def LoadModulePackageDependencies(XmlMsa): + XmlTag = "ModuleSurfaceArea/PackageDependencies/Package" + return map(LoadModulePackageDependency, XmlList(XmlMsa, XmlTag)) + + +## Load a list of Module Protocols. +# +# Read an input Module XML DOM object and return a list of Protocols +# contained in the DOM object. +# +# @param XmlMsa An XML DOM object read from MSA file. +# +# @retvel Protocols A list of Protocols loaded from XmlMsa. +# +def LoadModuleProtocols(XmlMsa): + XmlTag = "ModuleSurfaceArea/Protocols/Protocol" + XmlProtocolList = XmlList(XmlMsa, XmlTag) + + XmlTag = "ModuleSurfaceArea/Protocols/ProtocolNotify" + XmlProtocolList += XmlList(XmlMsa, XmlTag) + + return map(LoadGuidProtocolPpiCommon, XmlProtocolList) + + +## Load a list of Module Ppis. +# +# Read an input Module XML DOM object and return a list of Ppis +# contained in the DOM object. +# +# @param XmlMsa An XML DOM object read from MSA file. +# +# @retvel Ppis A list of Ppis loaded from XmlMsa. +# +def LoadModulePpis(XmlMsa): + XmlTag = "ModuleSurfaceArea/PPIs/Ppi" + XmlPpiList = XmlList(XmlMsa, XmlTag) + + XmlTag = "ModuleSurfaceArea/PPIs/PpiNotify" + XmlPpiList += XmlList(XmlMsa, XmlTag) + + return map(LoadGuidProtocolPpiCommon, XmlPpiList) + + +## Load a new Module Event class object. +# +# Read an input XML Event DOM object and return an object of Event +# contained in the DOM object. +# +# @param XmlEvent A child XML DOM object in Module XML DOM. +# @param Type Specify the event type: SIGNAL_EVENT or CREATE_EVENT. +# +# @retvel ModuleEvent A new Event object created by XmlEvent. +# +def LoadModuleEvent(XmlEvent, Type): + ModuleEvent = ModuleEventClass() + + XmlTag = "EventTypes/EventType" + ModuleEvent.CName = XmlElement(XmlEvent, XmlTag) + + XmlTag = "EventGuidCName" + ModuleEvent.GuidCName = XmlAttribute(XmlEvent, XmlTag) + + ModuleEvent.Type = Type + + SetCommon(ModuleEvent, XmlEvent) + + return ModuleEvent + + +## Load a list of Module Events. +# +# Read an input Module XML DOM object and return a list of Events +# contained in the DOM object. +# +# @param XmlMsa An XML DOM object read from MSA file. +# +# @retvel Events A list of Events loaded from XmlMsa. +# +def LoadModuleEvents(XmlMsa): + ModuleEvents = [] + + XmlTag = "ModuleSurfaceArea/Events/CreateEvents/EventTypes" + for XmlCreateEvent in XmlList(XmlMsa, XmlTag): + ModuleEvent = LoadModuleEvent(XmlCreateEvent, "CREATE_EVENT") + ModuleEvents.append(ModuleEvent) + + XmlTag = "ModuleSurfaceArea/Events/SignalEvents/EventTypes" + for XmlCreateEvent in XmlList(XmlMsa, XmlTag): + ModuleEvent = LoadModuleEvent(XmlCreateEvent, "SIGNAL_EVENT") + ModuleEvents.append(ModuleEvent) + + return ModuleEvents + + +## Load a new Module Hob class object. +# +# Read an input XML Hob DOM object and return an object of Hob +# contained in the DOM object. +# +# @param XmlHob A child XML DOM object in Module XML DOM. +# +# @retvel ModuleHob A new Hob object created by XmlHob. +# +def LoadModuleHob(XmlHob): + ModuleHob = ModuleHobClass() + + XmlTag = "HobTypes/HobType" + ModuleHob.Type = XmlElement(XmlHob, XmlTag) + + XmlTag = "HobGuidCName" + ModuleHob.GuidCName = XmlAttribute(XmlHob, XmlTag) + + SetCommon(ModuleHob, XmlHob) + + return ModuleHob + + +## Load a list of Module Hobs. +# +# Read an input Module XML DOM object and return a list of Hobs +# contained in the DOM object. +# +# @param XmlMsa An XML DOM object read from MSA file. +# +# @retvel Hobs A list of Hobs loaded from XmlMsa. +# +def LoadModuleHobs(XmlMsa): + XmlTag = "ModuleSurfaceArea/Hobs/HobTypes" + return map(LoadModuleHob, XmlList(XmlMsa, XmlTag)) + + +## Load a new Module Variable class object. +# +# Read an input XML Variable DOM object and return an object of Variable +# contained in the DOM object. +# +# @param XmlVariable A child XML DOM object in Module XML DOM. +# +# @retvel ModuleVariable A new Variable object created by XmlVariable. +# +def LoadModuleVariable(XmlVariable): + ModuleVariable = ModuleVariableClass() + + XmlTag = "Variable/VariableName" + HexWordArray = XmlElement(XmlVariable, XmlTag).split() + try: + ModuleVariable.Name = "".join([unichr(int(a, 16)) for a in HexWordArray]) + except: + ModuleVariable.Name = "" + + XmlTag = "Variable/GuidC_Name" + ModuleVariable.GuidCName = XmlElement(XmlVariable, XmlTag) + + SetCommon(ModuleVariable, XmlVariable) + + return ModuleVariable + + +## Load a list of Module Variables. +# +# Read an input Module XML DOM object and return a list of Variables +# contained in the DOM object. +# +# @param XmlMsa An XML DOM object read from MSA file. +# +# @retvel Variables A list of Variables loaded from XmlMsa. +# +def LoadModuleVariables(XmlMsa): + XmlTag = "ModuleSurfaceArea/Variables/Variable" + return map(LoadModuleVariable, XmlList(XmlMsa, XmlTag)) + + +## Load a new Module Boot Mode class object. +# +# Read an input XML BootMode DOM object and return an object of Boot Mode +# contained in the DOM object. +# +# @param XmlBootMode A child XML DOM object in Module XML DOM. +# +# @retvel ModuleBootMode A new Boot Mode object created by XmlBootMode. +# +def LoadModuleBootMode(XmlBootMode): + ModuleBootMode = ModuleBootModeClass() + + XmlTag = "BootModeName" + ModuleBootMode.Name = XmlAttribute(XmlBootMode, XmlTag) + + SetCommon(ModuleBootMode, XmlBootMode) + + return ModuleBootMode + + +## Load a list of Module Boot Modes. +# +# Read an input Module XML DOM object and return a list of Boot Modes +# contained in the DOM object. +# +# @param XmlMsa An XML DOM object read from MSA file. +# +# @retvel BootModes A list of Boot Modes loaded from XmlMsa. +# +def LoadModuleBootModes(XmlMsa): + XmlTag = "ModuleSurfaceArea/BootModes/BootMode" + return map(LoadModuleBootMode, XmlList(XmlMsa, XmlTag)) + + +## Load a new Module System Table class object. +# +# Read an input XML SystemTable DOM object and return an object of System Table +# contained in the DOM object. +# +# @param XmlSystemTable A child XML DOM object in Module XML DOM. +# +# @retvel ModuleSystemTable A new System Table object created by XmlSystemTable. +# +def LoadModuleSystemTable(XmlSystemTable): + ModuleSystemTable = ModuleSystemTableClass() + + XmlTag = "SystemTable/SystemTableCName" + ModuleSystemTable.CName = XmlElement(XmlSystemTable, XmlTag) + + SetCommon(ModuleSystemTable, XmlSystemTable) + + return ModuleSystemTable + + +## Load a list of Module System Tables. +# +# Read an input Module XML DOM object and return a list of System Tables +# contained in the DOM object. +# +# @param XmlMsa An XML DOM object read from MSA file. +# +# @retvel SystemTables A list of System Tables loaded from XmlMsa. +# +def LoadModuleSystemTables(XmlMsa): + XmlTag = "ModuleSurfaceArea/SystemTables/SystemTableCNames" + return map(LoadModuleSystemTable, XmlList(XmlMsa, XmlTag)) + + +## Load a new Module Data Hub class object. +# +# Read an input XML DataHub DOM object and return an object of Data Hub +# contained in the DOM object. +# +# @param XmlDataHub A child XML DOM object in Module XML DOM. +# +# @retvel ModuleDataHub A new Data Hub object created by XmlDataHub. +# +def LoadModuleDataHub(XmlDataHub): + ModuleDataHub = ModuleDataHubClass() + + XmlTag = "DataHub/DataHubCName" + ModuleDataHub.CName = XmlElement(XmlDataHub, "DataHubCName") + + SetCommon(ModuleDataHub, XmlDataHub) + + return ModuleDataHub + + +## Load a list of Module Data Hubs. +# +# Read an input Module XML DOM object and return a list of Data Hubs +# contained in the DOM object. +# +# @param XmlMsa An XML DOM object read from MSA file. +# +# @retvel DataHubs A list of Data Hubs loaded from XmlMsa. +# +def LoadModuleDataHubs(XmlMsa): + XmlTag = "ModuleSurfaceArea/DataHubs/DataHubRecord" + return map(LoadModuleDataHub, XmlList(XmlMsa, XmlTag)) + + +## Load a new Module Hii Package class object. +# +# Read an input XML HiiPackage DOM object and return an object of Hii Package +# contained in the DOM object. +# +# @param XmlHiiPackage A child XML DOM object in Module XML DOM. +# +# @retvel ModuleHiiPackage A new Hii Package object created by XmlHiiPackage. +# +def LoadModuleHiiPackage(XmlHiiPackage): + ModuleHiiPackage = ModuleHiiPackageClass() + + XmlTag = "HiiPackage/HiiPackageCName" + ModuleHiiPackage.CName = XmlElement(XmlHiiPackage, "HiiCName") + + SetCommon(ModuleHiiPackage, XmlHiiPackage) + + return ModuleHiiPackage + + +## Load a list of Module Hii Packages. +# +# Read an input Module XML DOM object and return a list of Hii Packages +# contained in the DOM object. +# +# @param XmlMsa An XML DOM object read from MSA file. +# +# @retvel HiiPackages A list of Hii Packages loaded from XmlMsa. +# +def LoadModuleHiiPackages(XmlMsa): + XmlTag = "ModuleSurfaceArea/HiiPackages/HiiPackage" + return map(LoadModuleHiiPackage, XmlList(XmlMsa, XmlTag)) + + +## Load a list of Module Guids. +# +# Read an input Module XML DOM object and return a list of Guids +# contained in the DOM object. +# +# @param XmlMsa An XML DOM object read from MSA file. +# +# @retvel Guids A list of Guids loaded from XmlMsa. +# +def LoadModuleGuids(XmlMsa): + XmlTag = "ModuleSurfaceArea/Guids/GuidCNames" + return map(LoadGuidProtocolPpiCommon, XmlList(XmlMsa, XmlTag)) + + +## Load a list of Module Pcd Codes. +# +# Read an input Module XML DOM object and return a list of Pcd Codes +# contained in the DOM object. +# +# @param XmlMsa An XML DOM object read from MSA file. +# +# @retvel PcdCodes A list of Pcd Codes loaded from XmlMsa. +# +def LoadModulePcdCodes(XmlMsa): + XmlTag = "ModuleSurfaceArea/PcdCoded/PcdEntry" + return map(LoadPcd, XmlList(XmlMsa, XmlTag)) + + +## Load a list of Module Extern Images. +# +# Read an input Module XML DOM object and return a list of Extern Images +# contained in the DOM object. +# +# @param XmlMsa An XML DOM object read from MSA file. +# +# @retvel ExternImages A list of Extern Images loaded from XmlMsa. +# +def LoadModuleExternImages(XmlMsa): + ModuleExternImages = [] + + XmlTag = "ModuleSurfaceArea/Externs/Extern" + for XmlExtern in XmlList(XmlMsa, XmlTag): + XmlTag = "Extern/ModuleEntryPoint" + ModuleEntryPoint = XmlElement(XmlExtern, XmlTag) + XmlTag = "Extern/ModuleUnloadImage" + ModuleUnloadImage = XmlElement(XmlExtern, XmlTag) + if ModuleEntryPoint == "" and ModuleUnloadImage == "": + continue + + ModuleExtern = ModuleExternImageClass() + ModuleExtern.ModuleEntryPoint = ModuleEntryPoint + ModuleExtern.ModuleUnloadImage = ModuleUnloadImage + ModuleExternImages.append(ModuleExtern) + + return ModuleExternImages + + +## Load a list of Module Extern Libraries. +# +# Read an input Module XML DOM object and return a list of Extern Libraries +# contained in the DOM object. +# +# @param XmlMsa An XML DOM object read from MSA file. +# +# @retvel ExternLibraries A list of Extern Libraries loaded from XmlMsa. +# +def LoadModuleExternLibraries(XmlMsa): + ModuleExternLibraries = [] + + XmlTag = "ModuleSurfaceArea/Externs/Extern" + for XmlExtern in XmlList(XmlMsa, XmlTag): + XmlTag = "Extern/Constructor" + Constructor = XmlElement(XmlExtern, XmlTag) + XmlTag = "Extern/Destructor" + Destructor = XmlElement(XmlExtern, XmlTag) + if Constructor == "" and Destructor == "": + continue + + ModuleExtern = ModuleExternLibraryClass() + ModuleExtern.Constructor = Constructor + ModuleExtern.Destructor = Destructor + ModuleExternLibraries.append(ModuleExtern) + + return ModuleExternLibraries + + +## Load a list of Module Extern Drivers. +# +# Read an input Module XML DOM object and return a list of Extern Drivers +# contained in the DOM object. +# +# @param XmlMsa An XML DOM object read from MSA file. +# +# @retvel ExternDrivers A list of Extern Drivers loaded from XmlMsa. +# +def LoadModuleExternDrivers(XmlMsa): + ModuleExternDrivers = [] + + XmlTag = "ModuleSurfaceArea/Externs/Extern" + for XmlExtern in XmlList(XmlMsa, XmlTag): + XmlTag = "Extern/DriverBinding" + DriverBinding = XmlElement(XmlExtern, XmlTag) + XmlTag = "Extern/ComponentName" + ComponentName = XmlElement(XmlExtern, XmlTag) + XmlTag = "Extern/DriverConfig" + DriverConfig = XmlElement(XmlExtern, XmlTag) + XmlTag = "Extern/DriverDiag" + DriverDiag = XmlElement(XmlExtern, XmlTag) + if DriverBinding == "": + continue + + ModuleExtern = ModuleExternDriverClass() + ModuleExtern.DriverBinding = DriverBinding + ModuleExtern.ComponentName = ComponentName + ModuleExtern.DriverConfig = DriverConfig + ModuleExtern.DriverDiag = DriverDiag + ModuleExternDrivers.append(ModuleExtern) + + return ModuleExternDrivers + + +## Load a list of Module Extern Call Backs. +# +# Read an input Module XML DOM object and return a list of Extern Call Backs +# contained in the DOM object. +# +# @param XmlMsa An XML DOM object read from MSA file. +# +# @retvel ExternCallBacks A list of Extern Call Backs loaded from XmlMsa. +# +def LoadModuleExternCallBacks(XmlMsa): + ModuleExternCallBacks = [] + + XmlTag = "ModuleSurfaceArea/Externs/Extern" + for XmlExtern in XmlList(XmlMsa, XmlTag): + XmlTag = "Extern/SetVirtualAddressMapCallBack" + SetVirtualAddressMap = XmlElement(XmlExtern, XmlTag) + XmlTag = "Extern/ExitBootServicesCallBack" + ExitBootServices = XmlElement(XmlExtern, XmlTag) + if SetVirtualAddressMap == "" and ExitBootServices == "": + continue + + ModuleExtern = ModuleExternCallBackClass() + ModuleExtern.ExitBootServicesCallBack = ExitBootServices + ModuleExtern.SetVirtualAddressMapCallBack = SetVirtualAddressMap + ModuleExternCallBacks.append(ModuleExtern) + + return ModuleExternCallBacks + + +## Load a list of Module Build Options. +# +# Read an input Module XML DOM object and return a list of Build Options +# contained in the DOM object. +# +# @param XmlMsa An XML DOM object read from MSA file. +# +# @retvel BuildOptions A list of Build Options loaded from XmlMsa. +# +def LoadModuleBuildOptions(XmlMsa): + XmlTag = "ModuleSurfaceArea/ModuleBuildOptions/Options/Option" + return map(LoadBuildOption, XmlList(XmlMsa, XmlTag)) + + +## Load a list of Module User Extensions. +# +# Read an input Module XML DOM object and return a list of User Extensions +# contained in the DOM object. +# +# @param XmlMsa An XML DOM object read from MSA file. +# +# @retvel UserExtensions A list of User Extensions loaded from XmlMsa. +# +def LoadModuleUserExtensions(XmlMsa): + XmlTag = "ModuleSurfaceArea/UserExtensions" + return map(LoadUserExtensions, XmlList(XmlMsa, XmlTag)) + +## Load a new Module class object. +# +# Read an input MSA File and return a new Module class Object. +# +# @param MsaFileName An XML DOM object read from MSA file. +# +# @retvel Module A new Module class object loaded from MSA File. +# +def LoadMsa(MsaFileName): + XmlMsa = XmlParseFile(MsaFileName) + EdkLogger.verbose("Load MSA File: %s" % MsaFileName) + + Module = ModuleClass() + Module.Header = LoadModuleHeader(XmlMsa, MsaFileName) + Module.LibraryClasses = LoadModuleLibraryClasses(XmlMsa) + Module.Sources = LoadModuleSources(XmlMsa) + Module.BinaryFiles = LoadModuleBinaries(XmlMsa) + Module.NonProcessedFiles = LoadModuleNonProcessedFiles(XmlMsa) + Module.PackageDependencies = LoadModulePackageDependencies(XmlMsa) + Module.Protocols = LoadModuleProtocols(XmlMsa) + Module.Ppis = LoadModulePpis(XmlMsa) + Module.Events = LoadModuleEvents(XmlMsa) + Module.Hobs = LoadModuleHobs(XmlMsa) + Module.Variables = LoadModuleVariables(XmlMsa) + Module.BootModes = LoadModuleBootModes(XmlMsa) + Module.SystemTables = LoadModuleSystemTables(XmlMsa) + Module.DataHubs = LoadModuleDataHubs(XmlMsa) + Module.HiiPackages = LoadModuleHiiPackages(XmlMsa) + Module.Guids = LoadModuleGuids(XmlMsa) + Module.PcdCodes = LoadModulePcdCodes(XmlMsa) + Module.ExternImages = LoadModuleExternImages(XmlMsa) + Module.ExternLibraries = LoadModuleExternLibraries(XmlMsa) + Module.ExternDrivers = LoadModuleExternDrivers(XmlMsa) + Module.ExternCallBacks = LoadModuleExternCallBacks(XmlMsa) + Module.BuildOptions = LoadModuleBuildOptions(XmlMsa) + Module.UserExtensions = LoadModuleUserExtensions(XmlMsa) + + return Module + + +# This acts like the main() function for the script, unless it is 'import'ed +# into another script. +if __name__ == '__main__': + pass \ No newline at end of file diff --git a/BaseTools/Source/Python/msa2inf/Msa2Inf.py b/BaseTools/Source/Python/msa2inf/Msa2Inf.py new file mode 100644 index 0000000000..5873b1d198 --- /dev/null +++ b/BaseTools/Source/Python/msa2inf/Msa2Inf.py @@ -0,0 +1,44 @@ +## @file +# Convert an XML-based MSA file to a text-based INF file. +# +# Copyright (c) 2007, 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. +# + +## +# Import Modules +# +import sys +from Common.MigrationUtilities import * +from LoadMsa import LoadMsa +from StoreInf import StoreInf +from ConvertModule import ConvertMsaModuleToInfModule + +## Entrance method +# +# This method mainly dispatch specific methods per the command line options. +# If no error found, return zero value so the caller of this tool can know +# if it's executed successfully or not. +# +# @retval 0 Tool was successful. +# @retval 1 Tool failed. +# +def Main(): + try: + Options, InputFile = MigrationOptionParser("MSA", "INF", "%prog") + Module = LoadMsa(InputFile) + ConvertMsaModuleToInfModule(Module) + StoreInf(Options.OutputFile, Module) + return 0 + except Exception, e: + print e + return 1 + +if __name__ == '__main__': + sys.exit(Main()) diff --git a/BaseTools/Source/Python/msa2inf/StoreInf.py b/BaseTools/Source/Python/msa2inf/StoreInf.py new file mode 100644 index 0000000000..bb58dc2f2f --- /dev/null +++ b/BaseTools/Source/Python/msa2inf/StoreInf.py @@ -0,0 +1,442 @@ +## @file +# Store a Module class object to an INF file. +# +# Copyright (c) 2007, 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. +# + +## +# Import Modules +# +from LoadMsa import LoadMsa +from CommonDataClass.ModuleClass import * +from Common.MigrationUtilities import * + +## Get the produced library class. +# +# Return the item of Library Class based on Library . +# +# @param LibraryClasses A list of library classes the module produces. +# +# @retval LibraryClassItem A text format library class item. +# +def GetModuleLibraryClass(LibraryClasses): + ProducedLibraryClasses = [] + for LibraryClass in LibraryClasses: + ProducedLibraryClass = LibraryClass.LibraryClass + SupportedModueTypes = " ".join(LibraryClass.SupModuleList) + if SupportedModueTypes != "": + ProducedLibraryClass += "|" + SupportedModueTypes + ProducedLibraryClasses.append(ProducedLibraryClass) + + return "|".join(ProducedLibraryClasses) + + +## Store Defines section. +# +# Write [Defines] section to the InfFile based on Module class object. +# Different CPU architectures are specified in the subsection if possible. +# +# @param InfFile The output INF file to store the Defines section. +# @param Module An input Module class object. +# +def StoreModuleDefinesSection(InfFile, Module): + ModuleHeader = Module.Header + + DefinesTupleList = [] + DefinesTupleList.append(("INF_VERSION", ModuleHeader.InfVersion)) + + if ModuleHeader.Name != "": + DefinesTupleList.append(("BASE_NAME", ModuleHeader.Name)) + + if ModuleHeader.Guid != "": + DefinesTupleList.append(("FILE_GUID", ModuleHeader.Guid)) + + if ModuleHeader.Version != "": + DefinesTupleList.append(("VERSION_STRING", ModuleHeader.Version)) + + if ModuleHeader.ModuleType != "": + DefinesTupleList.append(("MODULE_TYPE", ModuleHeader.ModuleType)) + + if ModuleHeader.EfiSpecificationVersion != "": + DefinesTupleList.append(("EFI_SPECIFICATION_VERSION", ModuleHeader.EfiSpecificationVersion)) + + if ModuleHeader.EdkReleaseVersion != "": + DefinesTupleList.append(("EDK_RELEASE_VERSION", ModuleHeader.EdkReleaseVersion)) + + ProducedLibraryClass = GetModuleLibraryClass(ModuleHeader.LibraryClass) + if ProducedLibraryClass != "": + DefinesTupleList.append(("LIBRARY_CLASS", ProducedLibraryClass)) + + if ModuleHeader.MakefileName != "": + DefinesTupleList.append(("MAKEFILE_NAME", ModuleHeader.MakeFileName)) + + if ModuleHeader.PcdIsDriver != "": + DefinesTupleList.append(("PCD_DRIVER", "TRUE")) + + if len(Module.ExternImages) > 0: + ModuleEntryPoint = Module.ExternImages[0].ModuleEntryPoint + ModuleUnloadImage = Module.ExternImages[0].ModuleUnloadImage + if ModuleEntryPoint != "": + DefinesTupleList.append(("ENTRY_POINT", ModuleEntryPoint)) + if ModuleUnloadImage != "": + DefinesTupleList.append(("UNLOAD_IMAGE", ModuleUnloadImage)) + + if len(Module.ExternLibraries) > 0: + Constructor = Module.ExternLibraries[0].Constructor + Destructor = Module.ExternLibraries[0].Destructor + if Constructor != "": + DefinesTupleList.append(("CONSTRUCTOR", Constructor)) + if Destructor != "": + DefinesTupleList.append(("DESTRUCTOR", Destructor)) + + StoreDefinesSection(InfFile, DefinesTupleList) + + +## Return a Module Source Item. +# +# Read the input ModuleSourceFile class object and return one line of Source Item. +# +# @param ModuleSourceFile An input ModuleSourceFile class object. +# +# @retval SourceItem A Module Source Item. +# +def GetModuleSourceItem(ModuleSourceFile): + Source = [] + Source.append(ModuleSourceFile.SourceFile) + Source.append(ModuleSourceFile.ToolChainFamily) + Source.append(ModuleSourceFile.TagName) + Source.append(ModuleSourceFile.ToolCode) + Source.append(ModuleSourceFile.FeatureFlag) + return "|".join(Source).rstrip("|") + + +## Store Sources section. +# +# Write [Sources] section to the InfFile based on Module class object. +# Different CPU architectures are specified in the subsection if possible. +# +# @param InfFile The output INF file to store the Sources section. +# @param Module An input Module class object. +# +def StoreModuleSourcesSection(InfFile, Module): + Section = GetSection("Sources", GetModuleSourceItem, Module.Sources) + StoreTextFile(InfFile, Section) + + +## Return a Module Binary Item. +# +# Read the input ModuleBinaryFile class object and return one line of Binary Item. +# +# @param ModuleBinaryFile An input ModuleBinaryFile class object. +# +# @retval BinaryItem A Module Binary Item. +# +def GetModuleBinaryItem(ModuleBinaryFile): + Binary = [] + Binary.append(ModuleBinaryFile.FileType) + Binary.append(ModuleBinaryFile.BinaryFile) + Binary.append(ModuleBinaryFile.Target) + Binary.append(ModuleBinaryFile.FeatureFlag) + return "|".join(Binary).rstrip("|") + + +## Store Binaries section. +# +# Write [Binaries] section to the InfFile based on Module class object. +# Different CPU architectures are specified in the subsection if possible. +# +# @param InfFile The output INF file to store the Binaries section. +# @param Module An input Module class object. +# +def StoreModuleBinariesSection(InfFile, Module): + Section = GetSection("Binaries", GetModuleBinaryItem, Module.Binaries) + StoreTextFile(InfFile, Section) + + +## Return a Module Library Class Item. +# +# Read the input LibraryClass class object and return one line of Library Class Item. +# +# @param LibraryClass An input LibraryClass class object. +# +# @retval LibraryClassItem A Module Library Class Item. +# +def GetModuleLibraryClassItem(LibraryClass): + if "ALWAYS_PRODUCED" in LibraryClass.Usage: + return "" + + LibraryClassList = [] + LibraryClassList.append(LibraryClass.LibraryClass) + LibraryClassList.append(LibraryClass.RecommendedInstance) + LibraryClassList.append(LibraryClass.FeatureFlag) + + return "|".join(LibraryClassList).rstrip("|") + + +## Store Library Classes section. +# +# Write [LibraryClasses] section to the InfFile based on Module class object. +# Different CPU architectures are specified in the subsection if possible. +# +# @param InfFile The output INF file to store the Library Classes section. +# @param Module An input Module class object. +# +def StoreModuleLibraryClassesSection(InfFile, Module): + Section = GetSection("LibraryClasses", GetModuleLibraryClassItem, Module.LibraryClasses) + StoreTextFile(InfFile, Section) + + +## Return a Module Package Item. +# +# Read the input PackageDependency class object and return one line of Package Item. +# +# @param PackageDependency An input PackageDependency class object. +# +# @retval PackageItem A Module Package Item. +# +def GetModulePackageItem(PackageDependency): + return PackageDependency.FilePath + + +## Store Packages section. +# +# Write [Packages] section to the InfFile based on Module class object. +# Different CPU architectures are specified in the subsection if possible. +# +# @param InfFile The output INF file to store the Packages section. +# @param Module An input Module class object. +# +def StoreModulePackagesSection(InfFile, Module): + Section = GetSection("Packages", GetModulePackageItem, Module.PackageDependencies) + StoreTextFile(InfFile, Section) + + +## Return a Module Guid C Name Item. +# +# Read the input Guid class object and return one line of Guid C Name Item. +# +# @param Guid An input Guid class object. +# +# @retval GuidCNameItem A Module Guid C Name Item. +# +def GetModuleGuidCNameItem(Guid): + try: + return Guid.GuidCName + except: + return Guid.CName + + +## Store Protocols section. +# +# Write [Protocols] section to the InfFile based on Module class object. +# Different CPU architectures are specified in the subsection if possible. +# +# @param InfFile The output INF file to store the Protocols section. +# @param Module An input Module class object. +# +def StoreModuleProtocolsSection(InfFile, Module): + Section = GetSection("Protocols", GetModuleGuidCNameItem, Module.Protocols) + StoreTextFile(InfFile, Section) + + +## Store Ppis section. +# +# Write [Ppis] section to the InfFile based on Module class object. +# Different CPU architectures are specified in the subsection if possible. +# +# @param InfFile The output INF file to store the Ppis section. +# @param Module An input Module class object. +# +def StoreModulePpisSection(InfFile, Module): + Section = GetSection("Ppis", GetModuleGuidCNameItem, Module.Ppis) + StoreTextFile(InfFile, Section) + + +## Store Guids section. +# +# Write [Guids] section to the InfFile based on Module class object. +# Different CPU architectures are specified in the subsection if possible. +# +# @param InfFile The output INF file to store the Guids section. +# @param Module An input Module class object. +# +def StoreModuleGuidsSection(InfFile, Module): + Guids = [] + Guids += Module.Guids + Guids += Module.Events + Guids += Module.Hobs + Guids += Module.Variables + Guids += Module.SystemTables + Guids += Module.DataHubs + Guids += Module.HiiPackages + Section = GetSection("Guids", GetModuleGuidCNameItem, Guids) + StoreTextFile(InfFile, Section) + + +## Return a Module Pcd Item. +# +# Read the input Pcd class object and return one line of Pcd Item. +# +# @param Pcd An input Pcd class object. +# +# @retval PcdItem A Module Pcd Item. +# +def GetModulePcdItem(Pcd): + PcdItem = "%s.%s" % (Pcd.TokenSpaceGuidCName, Pcd.CName) + if Pcd.DefaultValue != "": + PcdItem = "%s|%s" % (PcdItem, Pcd.DefaultValue) + + return PcdItem + + +## DEC Pcd Section Name dictionary indexed by PCD Item Type. +mInfPcdSectionNameDict = { + "FEATURE_FLAG" : "FeaturePcd", + "FIXED_AT_BUILD" : "FixedPcd", + "PATCHABLE_IN_MODULE" : "PatchPcd", + "DYNAMIC" : "Pcd", + "DYNAMIC_EX" : "PcdEx" + } + +## Store Pcds section. +# +# Write [(PcdType)] section to the InfFile based on Module class object. +# Different CPU architectures are specified in the subsection if possible. +# +# @param InfFile The output INF file to store the Pcds section. +# @param Module An input Module class object. +# +def StoreModulePcdsSection(InfFile, Module): + PcdsDict = {} + for Pcd in Module.PcdCodes: + PcdSectionName = mInfPcdSectionNameDict.get(Pcd.ItemType) + if PcdSectionName: + PcdsDict.setdefault(PcdSectionName, []).append(Pcd) + else: + EdkLogger.info("Unknown Pcd Item Type: %s" % Pcd.ItemType) + + Section = "" + for PcdSectionName in PcdsDict: + Pcds = PcdsDict[PcdSectionName] + Section += GetSection(PcdSectionName, GetModulePcdItem, Pcds) + Section += "\n" + + StoreTextFile(InfFile, Section) + + +## Return a Module Depex Item. +# +# Read the input Depex class object and return one line of Depex Item. +# +# @param Depex An input Depex class object. +# +# @retval DepexItem A Module Depex Item. +# +def GetModuleDepexItem(Depex): + return Depex.Depex + + +## Store Depex section. +# +# Write [Depex] section to the InfFile based on Module class object. +# Different CPU architectures are specified in the subsection if possible. +# +# @param InfFile The output INF file to store the Depex section. +# @param Module An input Module class object. +# +def StoreModuleDepexSection(InfFile, Module): + Section = GetSection("Depex", GetModuleDepexItem, Module.Depex) + StoreTextFile(InfFile, Section) + + +## Return a Module Build Option Item. +# +# Read the input BuildOption class object and return one line of Build Option Item. +# +# @param BuildOption An input BuildOption class object. +# +# @retval BuildOptionItem A Module Build Option Item. +# +def GetModuleBuildOptionItem(BuildOption): + BuildTarget = BuildOption.BuildTarget + if BuildTarget == "": + BuildTarget = "*" + + TagName = BuildOption.TagName + if TagName == "": + TagName = "*" + + ToolCode = BuildOption.ToolCode + if ToolCode == "": + ToolCode = "*" + + Item = "_".join((BuildTarget, TagName, "*", ToolCode, "Flag")) + + ToolChainFamily = BuildOption.ToolChainFamily + if ToolChainFamily != "": + Item = "%s:%s" % (ToolChainFamily, Item) + + return "%-30s = %s" % (Item, BuildOption.Option) + + +## Store Build Options section. +# +# Write [BuildOptions] section to the InfFile based on Module class object. +# Different CPU architectures are specified in the subsection if possible. +# +# @param InfFile The output INF file to store the Build Options section. +# @param Module An input Module class object. +# +def StoreModuleBuildOptionsSection(InfFile, Module): + Section = GetSection("BuildOption", GetModuleBuildOptionItem, Module.BuildOptions) + StoreTextFile(InfFile, Section) + + +## Store User Extensions section. +# +# Write [UserExtensions] section to the InfFile based on Module class object. +# +# @param InfFile The output INF file to store the User Extensions section. +# @param Module An input Module class object. +# +def StoreModuleUserExtensionsSection(InfFile, Module): + Section = "".join(map(GetUserExtensions, Module.UserExtensions)) + StoreTextFile(InfFile, Section) + + +## Store a Module class object to a new INF file. +# +# Read an input Module class object and save the contents to a new INF file. +# +# @param INFFileName The output INF file. +# @param Module An input Package class object. +# +def StoreInf(InfFileName, Module): + InfFile = open(InfFileName, "w+") + EdkLogger.info("Save file to %s" % InfFileName) + + StoreHeader(InfFile, Module.Header) + StoreModuleDefinesSection(InfFile, Module) + StoreModuleSourcesSection(InfFile, Module) + StoreModuleBinariesSection(InfFile, Module) + StoreModulePackagesSection(InfFile, Module) + StoreModuleLibraryClassesSection(InfFile, Module) + StoreModuleProtocolsSection(InfFile, Module) + StoreModulePpisSection(InfFile, Module) + StoreModuleGuidsSection(InfFile, Module) + StoreModulePcdsSection(InfFile, Module) + StoreModuleDepexSection(InfFile, Module) + StoreModuleBuildOptionsSection(InfFile, Module) + StoreModuleUserExtensionsSection(InfFile, Module) + + InfFile.close() + +if __name__ == '__main__': + pass diff --git a/BaseTools/Source/Python/msa2inf/__init__.py b/BaseTools/Source/Python/msa2inf/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/BaseTools/Source/Python/spd2dec/ConvertPackage.py b/BaseTools/Source/Python/spd2dec/ConvertPackage.py new file mode 100644 index 0000000000..57bc098bfa --- /dev/null +++ b/BaseTools/Source/Python/spd2dec/ConvertPackage.py @@ -0,0 +1,66 @@ +## @file +# Convert an SPD Package class object ot a DEC Package class object by filling +# some fields required by DEC file. +# +# Copyright (c) 2007, 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. +# + +## +# Import Modules +# +import os +from Common.MigrationUtilities import * +from LoadSpd import LoadSpd +from StoreDec import StoreDec + +#The default DEC version number tool generates. +gDecVersion = "0x00010005" + + +## Add required version information. +# +# Add the default DEC specification version to Package class object. +# +# @param Package An input Package class object. +# +def AddPackageMiscVersion(Package): + PackageHeader = Package.Header + PackageHeader.DecSpecification = gDecVersion + +## Add package include information. +# +# Adds the default "Include" folder to if that directory exists. +# +# @param Package An input Package class object. +# +def AddPackageInclude(Package): + PackageDir = os.path.dirname(Package.Header.FullPath) + DefaultIncludeDir = os.path.join(PackageDir, "Include") + if os.path.exists(DefaultIncludeDir): + Include = IncludeClass() + Include.FilePath = "Include" + Package.Includes.insert(0, Include) + +## Convert SPD Package class object to DEC Package class object. +# +# Convert SPD Package class ojbect to DEC Package class object by filling in +# several information required by DEC file. +# +# @param Package An input Package class object. +# +def ConvertSpdPackageToDecPackage(Package): + AddPackageMiscVersion(Package) + AddPackageInclude(Package) + +# This acts like the main() function for the script, unless it is 'import'ed +# into another script. +if __name__ == '__main__': + pass + \ No newline at end of file diff --git a/BaseTools/Source/Python/spd2dec/LoadSpd.py b/BaseTools/Source/Python/spd2dec/LoadSpd.py new file mode 100644 index 0000000000..e94e7fc317 --- /dev/null +++ b/BaseTools/Source/Python/spd2dec/LoadSpd.py @@ -0,0 +1,273 @@ +## @file +# Open an SPD file and load all its contents to a PackageClass object. +# +# Copyright (c) 2007, 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. +# + +## +# Import Modules +# +import os +from Common.XmlRoutines import * +from Common.MigrationUtilities import * +from CommonDataClass.PackageClass import * + + +## Load a list of Package Cloned Records. +# +# Read an input Package XML DOM object and return a list of Cloned Records +# contained in the DOM object. +# +# @param XmlSpd An XML DOM object read from SPD file. +# +# @retvel ClonedRecords A list of Cloned Records loaded from XmlSpd. +# +def LoadPackageClonedRecords(XmlSpd): + XmlTag = "PackageSurfaceArea/PackageDefinitions/ClonedFrom/Cloned" + return map(LoadClonedRecord, XmlList(XmlSpd, XmlTag)) + + +## Load Package Header. +# +# Read an input Package XML DOM object and return Package Header class object +# contained in the DOM object. +# +# @param XmlSpd An XML DOM object read from SPD file. +# @param SpdFileName The file path of SPD File. +# +# @retvel PackageHeader A new Package Header object loaded from XmlSpd. +# +def LoadPackageHeader(XmlSpd, SpdFileName): + PackageHeader = PackageHeaderClass() + + XmlTag = "PackageSurfaceArea/SpdHeader" + SpdHeader = XmlNode(XmlSpd, XmlTag) + + SetIdentification(PackageHeader, SpdHeader, "PackageName", SpdFileName) + SetCommonHeader(PackageHeader, SpdHeader) + + XmlTag = "PackageSurfaceArea/PackageDefinitions/ReadOnly" + if XmlElement(XmlSpd, XmlTag).lower() == "true": + PackageHeader.ReadOnly = True + + XmlTag = "PackageSurfaceArea/PackageDefinitions/RePackage" + if XmlElement(XmlSpd, XmlTag).lower() == "true": + PackageHeader.RePackage = True + + PackageHeader.ClonedFrom = LoadPackageClonedRecords(XmlSpd) + + return PackageHeader + + +## Load a list of Package Library Classes. +# +# Read an input Package XML DOM object and return a list of Library Classes +# contained in the DOM object. +# +# @param XmlSpd An XML DOM object read from SPD file. +# +# @retvel LibraryClasses A list of Library Classes loaded from XmlSpd. +# +def LoadPackageLibraryClasses(XmlSpd): + XmlTag = "PackageSurfaceArea/LibraryClassDeclarations/LibraryClass" + return map(LoadLibraryClass, XmlList(XmlSpd, XmlTag)) + + +## Load a new Package Industry Std Header class object. +# +# Read an input XML IndustryStdHeader DOM object and return an object of +# Industry Std Header contained in the DOM object. +# +# @param XmlIndustryStdHeader A child XML DOM object in Package XML DOM. +# +# @retvel PackageIndustryStdHeader A new Industry Std Header object created by XmlIndustryStdHeader. +# +def LoadPackageIndustryStdHeader(XmlIndustryStdHeader): + PackageIndustryStdHeader = PackageIndustryStdHeaderClass() + + XmlTag = "Name" + Name = XmlAttribute(XmlIndustryStdHeader, XmlTag) + PackageIndustryStdHeader.Name = Name + + XmlTag = "IndustryStdHeader/IncludeHeader" + IncludeHeader = XmlElement(XmlIndustryStdHeader, XmlTag) + PackageIndustryStdHeader.IncludeHeader = IncludeHeader + + SetCommon(PackageIndustryStdHeader, XmlIndustryStdHeader) + + return PackageIndustryStdHeader + + +## Load a list of Package Industry Std Headers. +# +# Read an input Package XML DOM object and return a list of Industry Std Headers +# contained in the DOM object. +# +# @param XmlSpd An XML DOM object read from SPD file. +# +# @retvel IndustryStdHeaders A list of Industry Std Headers loaded from XmlSpd. +# +def LoadPackageIndustryStdHeaders(XmlSpd): + XmlTag = "PackageSurfaceArea/IndustryStdIncludes/IndustryStdHeader" + return map(LoadPackageIndustryStdHeader, XmlList(XmlSpd, XmlTag)) + + +## Load a list of Package Module Files. +# +# Read an input Package XML DOM object and return a list of Module Files +# contained in the DOM object. +# +# @param XmlSpd An XML DOM object read from SPD file. +# +# @retvel ModuleFiles A list of Module Files loaded from XmlSpd. +# +def LoadPackageModuleFiles(XmlSpd): + XmlTag = "PackageSurfaceArea/MsaFiles/Filename" + return XmlElementList(XmlSpd, XmlTag) + + +## Load a new Package Include Pkg Header class object. +# +# Read an input XML IncludePkgHeader DOM object and return an object of Include +# Package Header contained in the DOM object. +# +# @param XmlPackageIncludeHeader A child XML DOM object in Package XML DOM. +# +# @retvel PackageIncludePkgHeader A new Include Pkg Header object created by +# XmlPackageIncludeHeader. +# +def LoadPackageIncludePkgHeader(XmlPackageIncludeHeader): + PackageIncludeHeader = PackageIncludePkgHeaderClass() + + IncludeHeader = XmlElementData(XmlPackageIncludeHeader) + PackageIncludeHeader.IncludeHeader = IncludeHeader + + XmlTag = "ModuleType" + ModuleTypes = XmlAttribute(XmlPackageIncludeHeader, XmlTag) + PackageIncludeHeader.ModuleType = ModuleTypes.split() + + return PackageIncludeHeader + + +## Load a list of Package Include Pkg Headers. +# +# Read an input Package XML DOM object and return a list of Include Pkg Headers +# contained in the DOM object. +# +# @param XmlSpd An XML DOM object read from SPD file. +# +# @retvel IncludePkgHeaders A list of Include Pkg Headers loaded from XmlSpd. +# +def LoadPackageIncludePkgHeaders(XmlSpd): + XmlTag = "PackageSurfaceArea/PackageHeaders/IncludePkgHeader" + return map(LoadPackageIncludePkgHeader, XmlList(XmlSpd, XmlTag)) + + +## Load a list of Package Guid Declarations. +# +# Read an input Package XML DOM object and return a list of Guid Declarations +# contained in the DOM object. +# +# @param XmlSpd An XML DOM object read from SPD file. +# +# @retvel GuidDeclarations A list of Guid Declarations loaded from XmlSpd. +# +def LoadPackageGuidDeclarations(XmlSpd): + XmlTag = "PackageSurfaceArea/GuidDeclarations/Entry" + return map(LoadGuidProtocolPpiCommon, XmlList(XmlSpd, XmlTag)) + + +## Load a list of Package Protocol Declarations. +# +# Read an input Package XML DOM object and return a list of Protocol Declarations +# contained in the DOM object. +# +# @param XmlSpd An XML DOM object read from SPD file. +# +# @retvel ProtocolDeclarations A list of Protocol Declarations loaded from XmlSpd. +# +def LoadPackageProtocolDeclarations(XmlSpd): + XmlTag = "PackageSurfaceArea/ProtocolDeclarations/Entry" + return map(LoadGuidProtocolPpiCommon, XmlList(XmlSpd, XmlTag)) + + +## Load a list of Package Ppi Declarations. +# +# Read an input Package XML DOM object and return a list of Ppi Declarations +# contained in the DOM object. +# +# @param XmlSpd An XML DOM object read from SPD file. +# +# @retvel PpiDeclarations A list of Ppi Declarations loaded from XmlSpd. +# +def LoadPackagePpiDeclarations(XmlSpd): + XmlTag = "PackageSurfaceArea/PpiDeclarations/Entry" + return map(LoadGuidProtocolPpiCommon, XmlList(XmlSpd, XmlTag)) + + +## Load a list of Package Pcd Declarations. +# +# Read an input Package XML DOM object and return a list of Pcd Declarations +# contained in the DOM object. +# +# @param XmlSpd An XML DOM object read from SPD file. +# +# @retvel PcdDeclarations A list of Pcd Declarations loaded from XmlSpd. +# +def LoadPackagePcdDeclarations(XmlSpd): + XmlTag = "PackageSurfaceArea/PcdDeclarations/PcdEntry" + return map(LoadPcd, XmlList(XmlSpd, XmlTag)) + + +## Load a list of Package User Extensions. +# +# Read an input Package XML DOM object and return a list of User Extensions +# contained in the DOM object. +# +# @param XmlSpd An XML DOM object read from SPD file. +# +# @retvel UserExtensions A list of User Extensions loaded from XmlSpd. +# +def LoadPackageUserExtensions(XmlSpd): + XmlTag = "PackageSurfaceArea/UserExtensions" + return map(LoadUserExtensions, XmlList(XmlSpd, XmlTag)) + + +## Load a new Package class object. +# +# Read an input SPD File and return a new Package class Object. +# +# @param SpdFileName An XML DOM object read from SPD file. +# +# @retvel Package A new Module class object loaded from SPD File. +# +def LoadSpd(SpdFileName): + XmlSpd = XmlParseFile(SpdFileName) + EdkLogger.verbose("Xml Object loaded for file %s" % SpdFileName) + + Package = PackageClass() + Package.Header = LoadPackageHeader(XmlSpd, SpdFileName) + Package.LibraryClassDeclarations = LoadPackageLibraryClasses(XmlSpd) + Package.IndustryStdHeaders = LoadPackageIndustryStdHeaders(XmlSpd) + Package.ModuleFiles = LoadPackageModuleFiles(XmlSpd) + Package.PackageIncludePkgHeaders = LoadPackageIncludePkgHeaders(XmlSpd) + Package.GuidDeclarations = LoadPackageGuidDeclarations(XmlSpd) + Package.ProtocolDeclarations = LoadPackageProtocolDeclarations(XmlSpd) + Package.PpiDeclarations = LoadPackagePpiDeclarations(XmlSpd) + Package.PcdDeclarations = LoadPackagePcdDeclarations(XmlSpd) + Package.UserExtensions = LoadPackageUserExtensions(XmlSpd) + + return Package + + +# This acts like the main() function for the script, unless it is 'import'ed +# into another script. +if __name__ == '__main__': + pass diff --git a/BaseTools/Source/Python/spd2dec/Spd2Dec.py b/BaseTools/Source/Python/spd2dec/Spd2Dec.py new file mode 100644 index 0000000000..46d058344b --- /dev/null +++ b/BaseTools/Source/Python/spd2dec/Spd2Dec.py @@ -0,0 +1,46 @@ +## @file +# Convert an XML-based SPD file to a text-based DEC file. +# +# Copyright (c) 2007, 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. +# + +## +# Import Modules +# +import sys +from Common.MigrationUtilities import * +from LoadSpd import LoadSpd +from StoreDec import StoreDec +from ConvertPackage import ConvertSpdPackageToDecPackage + +## Entrance method +# +# This method mainly dispatch specific methods per the command line options. +# If no error found, return zero value so the caller of this tool can know +# if it's executed successfully or not. +# +# @retval 0 Tool was successful. +# @retval 1 Tool failed. +# +def Main(): + try: + Options, InputFile = MigrationOptionParser("SPD", "DEC", "%prog") + Package = LoadSpd(InputFile) + ConvertSpdPackageToDecPackage(Package) + StoreDec(Options.OutputFile, Package) + return 0 + except Exception, e: + print e + return 1 + +if __name__ == '__main__': + sys.exit(Main()) + + diff --git a/BaseTools/Source/Python/spd2dec/StoreDec.py b/BaseTools/Source/Python/spd2dec/StoreDec.py new file mode 100644 index 0000000000..67cbd11e9b --- /dev/null +++ b/BaseTools/Source/Python/spd2dec/StoreDec.py @@ -0,0 +1,247 @@ +## @file +# Store a Package class object to a DEC file. +# +# Copyright (c) 2007, 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. +# + +## +# Import Modules +# +import os +from Common.MigrationUtilities import * +from LoadSpd import LoadSpd +from CommonDataClass.PackageClass import * + + +## Store Defines section. +# +# Write [Defines] section to the DecFile based on Package class object. +# Different CPU architectures are specified in the subsection if possible. +# +# @param DecFile The output DEC file to store the Defines section. +# @param Package An input Package class object. +# +def StorePackageDefinesSection(DecFile, Package): + DefinesTupleList = [] + DefinesTupleList.append(("DEC_VERSION", Package.Header.DecSpecification)) + DefinesTupleList.append(("PACKAGE_NAME", Package.Header.Name)) + DefinesTupleList.append(("PACKAGE_GUID", Package.Header.Guid)) + + StoreDefinesSection(DecFile, DefinesTupleList) + + +## Return a Package Include Class Item. +# +# Read the input Include class object and return one Include Class Item. +# +# @param Include An input Include class object. +# +# @retval IncludeClassItem A Package Include Class Item. +# +def GetPackageIncludeClassItem(Include): + return Include.FilePath + + +## Store Includes section. +# +# Write [Includes] section to the DecFile based on Package class object. +# Different CPU architectures are specified in the subsection if possible. +# +# @param DecFile The output DEC file to store the Includes section. +# @param Package An input Package class object. +# +def StorePackageIncludesSection(DecFile, Package): + Includes = Package.Includes + Section = GetSection("Includes", GetPackageIncludeClassItem, Includes) + StoreTextFile(DecFile, Section) + + +## Return a Package Library Class Item. +# +# Read the input LibraryClass class object and return one Library Class Item. +# +# @param LibraryClass An input LibraryClass class object. +# +# @retval LibraryClassItem A Package Library Class Item. +# +def GetPackageLibraryClassItem(LibraryClass): + return "|".join((LibraryClass.LibraryClass, LibraryClass.IncludeHeader)) + + +## Store Library Classes section. +# +# Write [LibraryClasses] section to the DecFile based on Package class object. +# Different CPU architectures are specified in the subsection if possible. +# +# @param DecFile The output DEC file to store the Library Classes +# section. +# @param Package An input Package class object. +# +def StorePackageLibraryClassesSection(DecFile, Package): + LibraryClasses = Package.LibraryClassDeclarations + Section = GetSection("LibraryClasses", GetPackageLibraryClassItem, LibraryClasses) + StoreTextFile(DecFile, Section) + + +## Return a Package Guid Declaration Item. +# +# Read the input Guid class object and return one line of Guid Declaration Item. +# +# @param Guid An input Guid class object. +# +# @retval GuidDeclarationItem A Package Guid Declaration Item. +# +def GetPackageGuidDeclarationItem(Guid): + GuidCName = Guid.CName + GuidValue = Guid.Guid.replace("-", "") + GuidValueList = [GuidValue[0:8]] + GuidValueList += [GuidValue[i : i + 4] for i in range(8, 16, 4)] + GuidValueList += [GuidValue[i : i + 2] for i in range(16, 32, 2)] + + GuidCFormat = "{0x%s" + ", 0x%s" * 2 + ", {0x%s" + ", 0x%s" * 7 + "}}" + GuidCValue = GuidCFormat % tuple(GuidValueList) + return "%-30s = %s" % (GuidCName, GuidCValue) + + +## Store Protocols section. +# +# Write [Protocols] section to the DecFile based on Package class object. +# Different CPU architectures are specified in the subsection if possible. +# +# @param DecFile The output DEC file to store the Protocols section. +# @param Package An input Package class object. +# +def StorePackageProtocolsSection(DecFile, Package): + Protocols = Package.ProtocolDeclarations + Section = GetSection("Protocols", GetPackageGuidDeclarationItem, Protocols) + StoreTextFile(DecFile, Section) + + +## Store Ppis section. +# +# Write [Ppis] section to the DecFile based on Package class object. +# Different CPU architectures are specified in the subsection if possible. +# +# @param DecFile The output DEC file to store the Ppis section. +# @param Package An input Package class object. +# +def StorePackagePpisSection(DecFile, Package): + Ppis = Package.PpiDeclarations + Section = GetSection("Ppis", GetPackageGuidDeclarationItem, Ppis) + StoreTextFile(DecFile, Section) + + +## Store Guids section. +# +# Write [Guids] section to the DecFile based on Package class object. +# Different CPU architectures are specified in the subsection if possible. +# +# @param DecFile The output DEC file to store the Guids section. +# @param Package An input Package class object. +# +def StorePackageGuidsSection(DecFile, Package): + Guids = Package.GuidDeclarations + Section = GetSection("Guids", GetPackageGuidDeclarationItem, Guids) + StoreTextFile(DecFile, Section) + + +## Return a Package Pcd Item. +# +# Read the input Pcd class object and return one line of Pcd Item. +# +# @param Pcd An input Pcd class object. +# +# @retval PcdItem A Package Pcd Item. +# +def GetPackagePcdItem(Pcd): + PcdPair = "%s.%s" % (Pcd.TokenSpaceGuidCName, Pcd.CName) + DatumType = Pcd.DatumType + DefaultValue = Pcd.DefaultValue + Token = Pcd.Token + PcdList = [PcdPair, DefaultValue, DatumType, Token] + return "|".join(PcdList) + + +## DEC Pcd Section Name dictionary indexed by PCD Item Type. +mDecPcdSectionNameDict = { + "FEATURE_FLAG" : "PcdsFeatureFlag", + "FIXED_AT_BUILD" : "PcdsFixedAtBuild", + "PATCHABLE_IN_MODULE" : "PcdsPatchableInModule", + "DYNAMIC" : "PcdsDynamic", + "DYNAMIC_EX" : "PcdsDynamicEx" + } + +## Store Pcds section. +# +# Write [Pcds*] section to the DecFile based on Package class object. +# Different CPU architectures are specified in the subsection if possible. +# +# @param DecFile The output DEC file to store the Pcds section. +# @param Package An input Package class object. +# +def StorePackagePcdsSection(DecFile, Package): + PcdsDict = {} + for Pcd in Package.PcdDeclarations: + for PcdItemType in Pcd.ValidUsage: + PcdSectionName = mDecPcdSectionNameDict.get(PcdItemType) + if PcdSectionName: + PcdsDict.setdefault(PcdSectionName, []).append(Pcd) + else: + EdkLogger.info("Unknown Pcd Item Type: %s" % PcdItemType) + + Section = "" + for PcdSectionName in PcdsDict: + Pcds = PcdsDict[PcdSectionName] + Section += GetSection(PcdSectionName, GetPackagePcdItem, Pcds) + + StoreTextFile(DecFile, Section) + + +## Store User Extensions section. +# +# Write [UserExtensions] section to the DecFile based on Package class object. +# +# @param DecFile The output DEC file to store the User Extensions section. +# @param Package An input Package class object. +# +def StorePackageUserExtensionsSection(DecFile, Package): + Section = "".join(map(GetUserExtensions, Package.UserExtensions)) + StoreTextFile(DecFile, Section) + + +## Store a Package class object to a new DEC file. +# +# Read an input Package class object and ave the contents to a new DEC file. +# +# @param DecFileName The output DEC file. +# @param Package An input Package class object. +# +def StoreDec(DecFileName, Package): + DecFile = open(DecFileName, "w+") + EdkLogger.info("Save file to %s" % DecFileName) + + StoreHeader(DecFile, Package.Header) + StorePackageDefinesSection(DecFile, Package) + StorePackageIncludesSection(DecFile, Package) + StorePackageLibraryClassesSection(DecFile, Package) + StorePackageProtocolsSection(DecFile, Package) + StorePackagePpisSection(DecFile, Package) + StorePackageGuidsSection(DecFile, Package) + StorePackagePcdsSection(DecFile, Package) + StorePackageUserExtensionsSection(DecFile, Package) + + DecFile.close() + + +# This acts like the main() function for the script, unless it is 'import'ed +# into another script. +if __name__ == '__main__': + pass + \ No newline at end of file diff --git a/BaseTools/Source/Python/spd2dec/__init__.py b/BaseTools/Source/Python/spd2dec/__init__.py new file mode 100644 index 0000000000..e69de29bb2 -- cgit v1.2.3